Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
problem-builder
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
OpenEdx
problem-builder
Commits
144bf820
Commit
144bf820
authored
Oct 23, 2015
by
Tim Krones
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement proper interoperability for scale and plot blocks.
parent
0ff61a29
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
189 additions
and
18 deletions
+189
-18
problem_builder/mcq.py
+23
-1
problem_builder/plot.py
+6
-13
problem_builder/slider.py
+11
-0
problem_builder/step.py
+1
-0
problem_builder/templates/html/rating_edit_footer.html
+5
-0
problem_builder/tests/integration/test_step_builder.py
+100
-4
problem_builder/tests/integration/xml_templates/step_builder_plot_scale_questions.xml
+43
-0
No files found.
problem_builder/mcq.py
View file @
144bf820
...
...
@@ -185,7 +185,7 @@ class RatingBlock(MCQBlock):
list_values_provider
=
QuestionnaireAbstractBlock
.
choice_values_provider
,
list_style
=
'set'
,
# Underered, unique items. Affects the UI editor.
)
editable_fields
=
MCQBlock
.
editable_fields
+
(
'low'
,
'high'
,
'name'
)
editable_fields
=
MCQBlock
.
editable_fields
+
(
'low'
,
'high'
)
@property
def
all_choice_values
(
self
):
...
...
@@ -212,3 +212,25 @@ class RatingBlock(MCQBlock):
}))
self
.
render_children
(
context
,
fragment
,
can_reorder
=
True
,
can_add
=
False
)
return
fragment
@property
def
url_name
(
self
):
"""
Get the url_name for this block. In Studio/LMS it is provided by a mixin, so we just
defer to super(). In the workbench or any other platform, we use the name.
"""
try
:
return
super
(
RatingBlock
,
self
)
.
url_name
except
AttributeError
:
return
self
.
name
def
student_view
(
self
,
context
):
fragment
=
super
(
RatingBlock
,
self
)
.
student_view
(
context
)
rendering_for_studio
=
None
if
context
:
# Workbench does not provide context
rendering_for_studio
=
context
.
get
(
'author_edit_view'
)
if
rendering_for_studio
:
fragment
.
add_content
(
loader
.
render_template
(
'templates/html/rating_edit_footer.html'
,
{
"url_name"
:
self
.
url_name
}))
return
fragment
problem_builder/plot.py
View file @
144bf820
...
...
@@ -59,7 +59,7 @@ def _normalize_id(key):
@XBlock.wants
(
'user'
)
class
PlotBlock
(
StudioEditableXBlockMixin
,
StudioContainerWithNestedXBlocksMixin
,
XBlockWithPreviewMixin
,
XBlock
):
"""
XBlock that displays plot that summarizes answers to scale questions.
XBlock that displays plot that summarizes answers to scale
and/or rating
questions.
"""
CATEGORY
=
'sb-plot'
...
...
@@ -139,7 +139,7 @@ class PlotBlock(StudioEditableXBlockMixin, StudioContainerWithNestedXBlocksMixin
'Claims and questions that should be included in the plot. '
'Each line defines a triple of the form "claim, q1, q2", '
'where "claim" is arbitrary text that represents a claim, '
'and "q1" and "q2" are IDs of scale questions. '
'and "q1" and "q2" are IDs of scale
or rating
questions. '
),
default
=
""
,
multiline_editor
=
True
,
...
...
@@ -175,17 +175,10 @@ class PlotBlock(StudioEditableXBlockMixin, StudioContainerWithNestedXBlocksMixin
claim
,
q1
,
q2
=
line
.
split
(
', '
)
r1
,
r2
=
None
,
None
for
question_id
,
question
in
zip
(
question_ids
,
questions
):
question_type
=
question
.
scope_ids
.
block_type
if
question_type
==
'pb-slider'
:
if
question
.
url_name
==
q1
:
r1
=
response_function
(
question
,
question_id
)
if
question
.
url_name
==
q2
:
r2
=
response_function
(
question
,
question_id
)
else
:
if
question
.
name
==
q1
:
r1
=
response_function
(
question
,
question_id
)
if
question
.
name
==
q2
:
r2
=
response_function
(
question
,
question_id
)
if
question
.
url_name
==
q1
:
r1
=
response_function
(
question
,
question_id
)
if
question
.
url_name
==
q2
:
r2
=
response_function
(
question
,
question_id
)
if
r1
is
not
None
and
r2
is
not
None
:
break
claims
.
append
([
claim
,
r1
,
r2
])
...
...
problem_builder/slider.py
View file @
144bf820
...
...
@@ -87,6 +87,17 @@ class SliderBlock(
editable_fields
=
(
'min_label'
,
'max_label'
,
'display_name'
,
'question'
,
'show_title'
)
@property
def
url_name
(
self
):
"""
Get the url_name for this block. In Studio/LMS it is provided by a mixin, so we just
defer to super(). In the workbench or any other platform, we use the name.
"""
try
:
return
super
(
SliderBlock
,
self
)
.
url_name
except
AttributeError
:
return
self
.
name
def
mentoring_view
(
self
,
context
):
""" Main view of this block """
context
=
context
.
copy
()
if
context
else
{}
...
...
problem_builder/step.py
View file @
144bf820
...
...
@@ -217,6 +217,7 @@ class MentoringStepBlock(
'head'
:
u'<div class="mentoring">'
,
'tail'
:
u'</div>'
}
local_context
[
'author_edit_view'
]
=
True
fragment
=
super
(
MentoringStepBlock
,
self
)
.
author_edit_view
(
local_context
)
fragment
.
add_css_url
(
self
.
runtime
.
local_resource_url
(
self
,
'public/css/problem-builder.css'
))
fragment
.
add_css_url
(
self
.
runtime
.
local_resource_url
(
self
,
'public/css/problem-builder-edit.css'
))
...
...
problem_builder/templates/html/rating_edit_footer.html
0 → 100644
View file @
144bf820
{% load i18n %}
<div
class=
"xblock-header-secondary url-name-footer"
>
<span
class=
"url-name-label"
>
{% trans "ID for referencing this rating block:" %}
</span>
<span
class=
"url-name"
>
{{ url_name }}
</span>
</div>
problem_builder/tests/integration/test_step_builder.py
View file @
144bf820
...
...
@@ -14,8 +14,23 @@ class ExtendedMockSubmissionsAPI(MockSubmissionsAPI):
)
class
MultipleSliderBlocksTestMixins
():
""" Mixins for testing slider blocks. Allows multiple slider blocks on the page. """
def
get_slider_value
(
self
,
slider_number
):
print
(
'SLIDER NUMBER: {}'
.
format
(
slider_number
))
return
int
(
self
.
browser
.
execute_script
(
"return $('.pb-slider-range').eq(arguments[0]).val()"
,
slider_number
-
1
)
)
def
set_slider_value
(
self
,
slider_number
,
val
):
self
.
browser
.
execute_script
(
"$('.pb-slider-range').eq(arguments[0]).val(arguments[1]).change()"
,
slider_number
-
1
,
val
)
@ddt
class
StepBuilderTest
(
MentoringAssessmentBaseTest
):
class
StepBuilderTest
(
MentoringAssessmentBaseTest
,
MultipleSliderBlocksTestMixins
):
def
setUp
(
self
):
super
(
StepBuilderTest
,
self
)
.
setUp
()
...
...
@@ -35,13 +50,17 @@ class StepBuilderTest(MentoringAssessmentBaseTest):
mock_submissions_api
),
(
"problem_builder.slider.sub_api"
,
mock_submissions_api
),
(
"problem_builder.sub_api.SubmittingXBlockMixin.student_item_key"
,
property
(
lambda
block
:
dict
(
student_id
=
"student_id"
,
course_id
=
"course_id"
,
item_id
=
block
.
scope_ids
.
usage_id
,
item_type
=
"pb-rating"
item_type
=
block
.
scope_ids
.
block_type
)
)
),
...
...
@@ -725,8 +744,8 @@ class StepBuilderTest(MentoringAssessmentBaseTest):
'point_color'
:
'rgb(255, 165, 0)'
,
# orange
'titles'
:
[
'2 + 2 = 5: 1, 5'
,
'The answer to everything is 42: 5, 1'
],
'positions'
:
[
(
'20'
,
'396'
),
# Values computed according to xScale and yScale (cf. plot.js)
(
'4'
,
'380'
),
# Values computed according to xScale and yScale (cf. plot.js)
(
'20'
,
'396'
),
# Values computed according to xScale and yScale (cf. plot.js)
],
}
average_overlay
=
{
...
...
@@ -735,8 +754,85 @@ class StepBuilderTest(MentoringAssessmentBaseTest):
'point_color'
:
'rgb(128, 0, 128)'
,
# purple
'titles'
:
[
'2 + 2 = 5: 1, 5'
,
'The answer to everything is 42: 5, 1'
],
'positions'
:
[
(
'20'
,
'396'
),
# Values computed according to xScale and yScale (cf. plot.js)
(
'4'
,
'380'
),
# Values computed according to xScale and yScale (cf. plot.js)
(
'20'
,
'396'
),
# Values computed according to xScale and yScale (cf. plot.js)
],
}
# Check if plot shows correct overlay(s) initially (default overlay on, average overlay off)
self
.
check_overlays
(
step_builder
,
total_num_points
=
2
,
overlays
=
[
default_overlay
])
# Check if plot shows correct overlay(s) (default overlay on, average overlay on)
self
.
click_average_button
(
plot_controls
,
overlay_on
=
True
,
color_on
=
'rgba(128, 0, 128, 1)'
)
# purple
self
.
check_overlays
(
step_builder
,
4
,
overlays
=
[
default_overlay
,
average_overlay
])
# Check if plot shows correct overlay(s) (default overlay off, average overlay on)
self
.
click_default_button
(
plot_controls
,
overlay_on
=
False
)
self
.
check_overlays
(
step_builder
,
2
,
overlays
=
[
average_overlay
])
# Check if plot shows correct overlay(s) (default overlay off, average overlay off)
self
.
click_average_button
(
plot_controls
,
overlay_on
=
False
)
self
.
plot_empty
(
step_builder
)
# Check if plot shows correct overlay(s) (default overlay on, average overlay off)
self
.
click_default_button
(
plot_controls
,
overlay_on
=
True
,
color_on
=
'rgba(255, 165, 0, 1)'
)
# orange
self
.
check_overlays
(
step_builder
,
2
,
overlays
=
[
default_overlay
])
# Check quadrant labels
self
.
check_quadrant_labels
(
step_builder
,
plot_controls
,
hidden
=
True
)
plot_controls
.
quadrants_button
.
click
()
self
.
check_quadrant_labels
(
step_builder
,
plot_controls
,
hidden
=
False
,
labels
=
[
'Custom Q1 label'
,
'Custom Q2 label'
,
'Custom Q3 label'
,
'Custom Q4 label'
]
)
def
answer_scale_question
(
self
,
question_number
,
step_builder
,
question
,
value
):
self
.
assertEqual
(
self
.
get_slider_value
(
question_number
),
50
)
question_text
=
self
.
question_text
(
question_number
)
self
.
wait_until_text_in
(
question_text
,
step_builder
)
self
.
assertIn
(
question
,
step_builder
.
text
)
self
.
set_slider_value
(
question_number
,
value
)
def
test_plot_with_scale_questions
(
self
):
step_builder
,
controls
=
self
.
load_assessment_scenario
(
"step_builder_plot_scale_questions.xml"
,
{})
# Step 1: Questions
# Provide first rating
self
.
answer_scale_question
(
1
,
step_builder
,
"How much do you agree?"
,
17
)
# Provide second rating
self
.
answer_scale_question
(
2
,
step_builder
,
"How important do you think this is?"
,
83
)
# Advance
self
.
submit_and_go_to_next_step
(
controls
)
# Step 2: Questions
# Provide first rating
self
.
answer_rating_question
(
2
,
1
,
step_builder
,
"How much do you agree?"
,
"5 - Agree"
)
# Provide second rating
self
.
answer_rating_question
(
2
,
2
,
step_builder
,
"How important do you think this is?"
,
"1 - Not important"
)
# Advance
self
.
submit_and_go_to_next_step
(
controls
,
last
=
True
)
# Step 2: Plot
# Obtain references to plot controls
plot_controls
=
self
.
plot_controls
(
step_builder
)
# Overlay data
default_overlay
=
{
'selector'
:
'.claim-default'
,
'num_points'
:
2
,
'point_color'
:
'rgb(255, 165, 0)'
,
# orange
'titles'
:
[
'2 + 2 = 5: 17, 83'
,
'The answer to everything is 42: 5, 1'
],
'positions'
:
[
(
'68'
,
'68'
),
# Values computed according to xScale and yScale (cf. plot.js)
(
'20'
,
'396'
),
# Values computed according to xScale and yScale (cf. plot.js)
],
}
average_overlay
=
{
'selector'
:
'.claim-average'
,
'num_points'
:
2
,
'point_color'
:
'rgb(128, 0, 128)'
,
# purple
'titles'
:
[
'2 + 2 = 5: 17, 83'
,
'The answer to everything is 42: 5, 1'
],
'positions'
:
[
(
'68'
,
'68'
),
# Values computed according to xScale and yScale (cf. plot.js)
(
'20'
,
'396'
),
# Values computed according to xScale and yScale (cf. plot.js)
],
}
# Check if plot shows correct overlay(s) initially (default overlay on, average overlay off)
...
...
problem_builder/tests/integration/xml_templates/step_builder_plot_scale_questions.xml
0 → 100644
View file @
144bf820
<step-builder
url_name=
"step-builder"
display_name=
"Step Builder"
>
<sb-step
display_name=
"First step"
>
<pb-slider
name=
"slider_1_1"
question=
"How much do you agree?"
>
</pb-slider>
<pb-slider
name=
"slider_1_2"
question=
"How important do you think this is?"
min_label=
"Not important"
max_label=
"Very important"
>
</pb-slider>
</sb-step>
<sb-step
display_name=
"Second step"
>
<pb-rating
name=
"rating_2_1"
low=
"Disagree"
high=
"Agree"
question=
"How much do you agree?"
correct_choices=
'["1", "2", "3", "4","5"]'
>
</pb-rating>
<pb-rating
name=
"rating_2_2"
low=
"Not important"
high=
"Very important"
question=
"How important do you think this is?"
correct_choices=
'["1", "2", "3", "4","5"]'
>
</pb-rating>
</sb-step>
<sb-step
display_name=
"Last step"
>
<sb-plot
plot_label=
"Custom plot label"
point_color_default=
"orange"
point_color_average=
"purple"
q1_label=
"Custom Q1 label"
q2_label=
"Custom Q2 label"
q3_label=
"Custom Q3 label"
q4_label=
"Custom Q4 label"
claims=
"2 + 2 = 5, slider_1_1, slider_1_2 The answer to everything is 42, rating_2_1, rating_2_2"
>
</sb-plot>
</sb-step>
<sb-review-step></sb-review-step>
</step-builder>
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment