Commit d1746f42 by Tim Krones

Address comments from string review.

parent 05d4ed1e
Drag and Drop XBlock v2 Drag and Drop XBlock v2
======================= =======================
This XBlock implements a friendly drag-and-drop style question, where This XBlock implements a friendly drag-and-drop style problem, where
the student has to drag items on zones on a target image. the learner has to drag items to zones on a target image.
The editor is fully guided. Features include: The editor is fully guided. Features include:
...@@ -25,7 +25,7 @@ inside the edX LMS before the user starts solving the problem: ...@@ -25,7 +25,7 @@ inside the edX LMS before the user starts solving the problem:
![Student view start](https://raw.githubusercontent.com/edx-solutions/xblock-drag-and-drop-v2/c955a38dc3a1aaf609c586d293ce19b282e11ffd/doc/img/student-view-start.png) ![Student view start](https://raw.githubusercontent.com/edx-solutions/xblock-drag-and-drop-v2/c955a38dc3a1aaf609c586d293ce19b282e11ffd/doc/img/student-view-start.png)
This screenshot shows the XBlock after the student successfully This screenshot shows the XBlock after the learner successfully
completed the Drag and Drop problem: completed the Drag and Drop problem:
![Student view finish](https://raw.githubusercontent.com/edx-solutions/xblock-drag-and-drop-v2/c955a38dc3a1aaf609c586d293ce19b282e11ffd/doc/img/student-view-finish.png) ![Student view finish](https://raw.githubusercontent.com/edx-solutions/xblock-drag-and-drop-v2/c955a38dc3a1aaf609c586d293ce19b282e11ffd/doc/img/student-view-finish.png)
...@@ -62,7 +62,7 @@ You can use the same approach to apply a custom theme: ...@@ -62,7 +62,7 @@ You can use the same approach to apply a custom theme:
`"package"` can refer to any Python package in your virtualenv, which `"package"` can refer to any Python package in your virtualenv, which
means you can develop and maintain your own theme in a separate means you can develop and maintain your own theme in a separate
package. There is no need to fork or modify this repository in any way package. There is no need to fork or modify this repository in any way
to customize the look and feel of your Drag and Drop exercises. to customize the look and feel of your Drag and Drop problems.
`"locations"` is a list of relative paths pointing to CSS files `"locations"` is a list of relative paths pointing to CSS files
belonging to your theme. While the XBlock loads, files will be added belonging to your theme. While the XBlock loads, files will be added
...@@ -97,9 +97,9 @@ and Drop component to a lesson, then click the `EDIT` button. ...@@ -97,9 +97,9 @@ and Drop component to a lesson, then click the `EDIT` button.
![Edit view](https://raw.githubusercontent.com/edx-solutions/xblock-drag-and-drop-v2/c955a38dc3a1aaf609c586d293ce19b282e11ffd/doc/img/edit-view.png) ![Edit view](https://raw.githubusercontent.com/edx-solutions/xblock-drag-and-drop-v2/c955a38dc3a1aaf609c586d293ce19b282e11ffd/doc/img/edit-view.png)
In the first step, you can set some basic properties of the component, In the first step, you can set some basic properties of the component,
such as the title, the maximum score, the question text to render such as the title, the maximum score, the problem text to render
above the background image, the introductory feedback (shown above the background image, the introductory feedback (shown
initially), and the final feedback (shown after the student initially), and the final feedback (shown after the learner
successfully completes the drag and drop problem). successfully completes the drag and drop problem).
![Drop zone edit](https://raw.githubusercontent.com/edx-solutions/xblock-drag-and-drop-v2/c955a38dc3a1aaf609c586d293ce19b282e11ffd/doc/img/edit-view-zones.png) ![Drop zone edit](https://raw.githubusercontent.com/edx-solutions/xblock-drag-and-drop-v2/c955a38dc3a1aaf609c586d293ce19b282e11ffd/doc/img/edit-view-zones.png)
...@@ -109,7 +109,7 @@ image and define the properties of the drop zones. For each zone you ...@@ -109,7 +109,7 @@ image and define the properties of the drop zones. For each zone you
can specify the text that should be rendered inside it (the "zone can specify the text that should be rendered inside it (the "zone
label"), how wide and tall it should be, and where it should be placed label"), how wide and tall it should be, and where it should be placed
on the background image. In this step you can also specify whether you on the background image. In this step you can also specify whether you
would like zone labels to be shown to students or not, as well as would like zone labels to be shown to learners or not, as well as
whether or not to display borders outlining the zones. It is possible whether or not to display borders outlining the zones. It is possible
to define an arbitrary number of drop zones as long as their labels to define an arbitrary number of drop zones as long as their labels
are unique. are unique.
...@@ -120,16 +120,16 @@ In the final step, you define the background and text color for drag ...@@ -120,16 +120,16 @@ In the final step, you define the background and text color for drag
items, as well as the drag items themselves. A drag item can contain items, as well as the drag items themselves. A drag item can contain
either text or an image. You can define custom success and error either text or an image. You can define custom success and error
feedback for each item. The feedback text is displayed in a popup feedback for each item. The feedback text is displayed in a popup
after the student drops the item on a zone - the success feedback is after the learner drops the item on a zone - the success feedback is
shown if the item is dropped on the correct zone, while the error shown if the item is dropped on the correct zone, while the error
feedback is shown when dropping the item on an incorrect drop zone. feedback is shown when dropping the item on an incorrect drop zone.
Additionally, items can have a numerical value (and an optional error Additionally, items can have a numerical value (and an optional error
margin) associated with them. When a student drops an item that has a margin) associated with them. When a learner drops an item that has a
numerical value on the correct zone, an input field for entering a numerical value on the correct zone, an input field for entering a
value is shown next to the item. The value that the student submits is value is shown next to the item. The value that the learner submits is
checked against the expected value for the item. If you also specify a checked against the expected value for the item. If you also specify a
margin, the value entered by the student will be considered correct if margin, the value entered by the learner will be considered correct if
it does not differ from the expected value by more than that margin it does not differ from the expected value by more than that margin
(and incorrect otherwise). (and incorrect otherwise).
...@@ -192,7 +192,7 @@ Real event example (taken from a devstack): ...@@ -192,7 +192,7 @@ Real event example (taken from a devstack):
## `edx.drag_and_drop_v2.item.picked_up` ## `edx.drag_and_drop_v2.item.picked_up`
Fired when a student picks up a draggable item. Fired when a learner picks up a draggable item.
Example ("common" fields that are not interesting in this context have been left out): Example ("common" fields that are not interesting in this context have been left out):
...@@ -240,9 +240,9 @@ Real event example (taken from a devstack): ...@@ -240,9 +240,9 @@ Real event example (taken from a devstack):
## `edx.drag_and_drop_v2.item.dropped` ## `edx.drag_and_drop_v2.item.dropped`
Fired when a student drops a draggable item. Fired when a learner drops a draggable item.
This event will be emitted when a student drops a draggable item. This event will be emitted when a learner drops a draggable item.
Example ("common" fields that are not interesting in this context have been left out): Example ("common" fields that are not interesting in this context have been left out):
...@@ -251,7 +251,7 @@ Example ("common" fields that are not interesting in this context have been left ...@@ -251,7 +251,7 @@ Example ("common" fields that are not interesting in this context have been left
... ...
"event": { "event": {
"input": null, "input": null,
"is_correct": true, -- False if there is an input in the draggable item, and the student provided the wrong answer. Otherwise true. "is_correct": true, -- False if there is an input in the draggable item, and the learner provided the wrong answer. Otherwise true.
"is_correct_location": true, -- Whether the draggable item has been placed in the correct location. "is_correct_location": true, -- Whether the draggable item has been placed in the correct location.
"item_id": 0, -- ID of the draggable item. "item_id": 0, -- ID of the draggable item.
"location": "The Top Zone", -- Name of the location the item was dragged to. "location": "The Top Zone", -- Name of the location the item was dragged to.
......
...@@ -19,7 +19,7 @@ ITEM_INCORRECT_FEEDBACK = _("No, this item does not belong here. Try again.") ...@@ -19,7 +19,7 @@ ITEM_INCORRECT_FEEDBACK = _("No, this item does not belong here. Try again.")
ITEM_NO_ZONE_FEEDBACK = _("You silly, there are no zones for this one.") ITEM_NO_ZONE_FEEDBACK = _("You silly, there are no zones for this one.")
START_FEEDBACK = _("Drag the items onto the image above.") START_FEEDBACK = _("Drag the items onto the image above.")
FINISH_FEEDBACK = _("Good work! You have completed this drag and drop exercise.") FINISH_FEEDBACK = _("Good work! You have completed this drag and drop problem.")
DEFAULT_DATA = { DEFAULT_DATA = {
"targetImgDescription": TARGET_IMG_DESCRIPTION, "targetImgDescription": TARGET_IMG_DESCRIPTION,
......
...@@ -28,78 +28,76 @@ loader = ResourceLoader(__name__) ...@@ -28,78 +28,76 @@ loader = ResourceLoader(__name__)
@XBlock.wants('settings') @XBlock.wants('settings')
class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin): class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin):
""" """
XBlock providing a Drag and Drop question XBlock that implements a friendly Drag-and-Drop problem
""" """
display_name = String( display_name = String(
display_name=_("Title"), display_name=_("Title"),
help=_("The title of the Drag and Drop that is displayed to the user"), help=_("The title of the drag and drop problem. The title is displayed to learners."),
scope=Scope.settings, scope=Scope.settings,
default=_("Drag and Drop"), default=_("Drag and Drop"),
) )
show_title = Boolean( show_title = Boolean(
display_name=_("Show title"), display_name=_("Show title"),
help=_("Display the title to the user?"), help=_("Display the title to the learner?"),
scope=Scope.settings, scope=Scope.settings,
default=True, default=True,
) )
question_text = String( question_text = String(
display_name=_("Question text"), display_name=_("Problem text"),
help=_("The question text (and/or instructions) shown to the user"), help=_("The description of the problem or instructions shown to the learner"),
scope=Scope.settings, scope=Scope.settings,
default="", default="",
) )
show_question_header = Boolean( show_question_header = Boolean(
display_name=_("Show \"Question\" heading"), display_name=_('Show "Problem" heading'),
help=_("Display the \"Question\" heading above the question/instructions?"), help=_('Display the heading "Problem" above the problem text?'),
scope=Scope.settings, scope=Scope.settings,
default=True, default=True,
) )
weight = Float( weight = Float(
display_name=_("Weight"), display_name=_("Weight"),
help=_("This is the maximum score that the user receives when he/she successfully completes the problem"), help=_("The maximum score the learner can receive for the problem"),
scope=Scope.settings, scope=Scope.settings,
default=1, default=1,
) )
item_background_color = String( item_background_color = String(
display_name=_("Item background color"), display_name=_("Item background color"),
help=_( help=_("The background color of draggable items in the problem."),
"Background color to use for draggable items. "
"Defaults to color specified by current theme, or blue if no theme is set."
),
scope=Scope.settings, scope=Scope.settings,
default="", default="",
) )
item_text_color = String( item_text_color = String(
display_name=_("Item text color"), display_name=_("Item text color"),
help=_( help=_("Text color to use for draggable items."),
"Text color to use for draggable items. "
"Defaults to color specified by current theme, or white if no theme is set."
),
scope=Scope.settings, scope=Scope.settings,
default="", default="",
) )
data = Dict( data = Dict(
display_name=_("Drag and Drop"), display_name=_("Problem data"),
help=_("JSON spec as generated by the builder"), help=_(
"Information about zones, items, feedback, and background image for this problem. "
"This information is derived from the input that a course author provides via the interactive editor "
"when configuring the problem."
),
scope=Scope.content, scope=Scope.content,
default=DEFAULT_DATA, default=DEFAULT_DATA,
) )
item_state = Dict( item_state = Dict(
help=_("How the student has interacted with the problem"), help=_("Information about current positions of items that a learner has dropped on the target image."),
scope=Scope.user_state, scope=Scope.user_state,
default={}, default={},
) )
completed = Boolean( completed = Boolean(
help=_("The student has completed the problem at least once"), help=_("Indicates whether a learner has completed the problem at least once"),
scope=Scope.user_state, scope=Scope.user_state,
default=False, default=False,
) )
...@@ -163,8 +161,8 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin): ...@@ -163,8 +161,8 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin):
"items": items_without_answers(), "items": items_without_answers(),
"title": self.display_name, "title": self.display_name,
"show_title": self.show_title, "show_title": self.show_title,
"question_text": self.question_text, "problem_text": self.question_text,
"show_question_header": self.show_question_header, "show_problem_header": self.show_question_header,
"target_img_expanded_url": self.target_img_expanded_url, "target_img_expanded_url": self.target_img_expanded_url,
"target_img_description": self.target_img_description, "target_img_description": self.target_img_description,
"item_background_color": self.item_background_color or None, "item_background_color": self.item_background_color or None,
...@@ -219,8 +217,8 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin): ...@@ -219,8 +217,8 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin):
def studio_submit(self, submissions, suffix=''): def studio_submit(self, submissions, suffix=''):
self.display_name = submissions['display_name'] self.display_name = submissions['display_name']
self.show_title = submissions['show_title'] self.show_title = submissions['show_title']
self.question_text = submissions['question_text'] self.question_text = submissions['problem_text']
self.show_question_header = submissions['show_question_header'] self.show_question_header = submissions['show_problem_header']
self.weight = float(submissions['weight']) self.weight = float(submissions['weight'])
self.item_background_color = submissions['item_background_color'] self.item_background_color = submissions['item_background_color']
self.item_text_color = submissions['item_text_color'] self.item_text_color = submissions['item_text_color']
...@@ -273,7 +271,7 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin): ...@@ -273,7 +271,7 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin):
if self._is_finished(): if self._is_finished():
overall_feedback = self.data['feedback']['finish'] overall_feedback = self.data['feedback']['finish']
# don't publish the grade if the student has already completed the exercise # don't publish the grade if the student has already completed the problem
if not self.completed: if not self.completed:
if self._is_finished(): if self._is_finished():
self.completed = True self.completed = True
...@@ -363,7 +361,7 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin): ...@@ -363,7 +361,7 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin):
definition = self._get_item_definition(int(item_id)) definition = self._get_item_definition(int(item_id))
item['correct_input'] = self._is_correct_input(definition, item.get('input')) item['correct_input'] = self._is_correct_input(definition, item.get('input'))
# If information about zone is missing # If information about zone is missing
# (because exercise was completed before a11y enhancements were implemented), # (because problem was completed before a11y enhancements were implemented),
# deduce zone in which item is placed from definition: # deduce zone in which item is placed from definition:
if item.get('zone') is None: if item.get('zone') is None:
item['zone'] = definition.get('zone', 'unknown') item['zone'] = definition.get('zone', 'unknown')
......
...@@ -38,7 +38,7 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -38,7 +38,7 @@ function DragAndDropBlock(runtime, element, configuration) {
$.ajax(runtime.handlerUrl(element, 'get_user_state'), {dataType: 'json'}), $.ajax(runtime.handlerUrl(element, 'get_user_state'), {dataType: 'json'}),
loadBackgroundImage() loadBackgroundImage()
).done(function(stateResult, bgImg){ ).done(function(stateResult, bgImg){
// Render exercise // Render problem
configuration.zones.forEach(function (zone) { configuration.zones.forEach(function (zone) {
computeZoneDimension(zone, bgImg.width, bgImg.height); computeZoneDimension(zone, bgImg.width, bgImg.height);
}); });
...@@ -54,9 +54,9 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -54,9 +54,9 @@ function DragAndDropBlock(runtime, element, configuration) {
$element.on('keydown', '.keyboard-help-button', function(evt) { $element.on('keydown', '.keyboard-help-button', function(evt) {
runOnKey(evt, RET, showKeyboardHelp); runOnKey(evt, RET, showKeyboardHelp);
}); });
$element.on('click', '.reset-button', resetExercise); $element.on('click', '.reset-button', resetProblem);
$element.on('keydown', '.reset-button', function(evt) { $element.on('keydown', '.reset-button', function(evt) {
runOnKey(evt, RET, resetExercise); runOnKey(evt, RET, resetProblem);
}); });
$element.on('click', '.submit-input', submitInput); $element.on('click', '.submit-input', submitInput);
...@@ -67,10 +67,10 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -67,10 +67,10 @@ function DragAndDropBlock(runtime, element, configuration) {
applyState(); applyState();
initDroppable(); initDroppable();
// Indicate that exercise is done loading // Indicate that problem is done loading
publishEvent({event_type: 'edx.drag_and_drop_v2.loaded'}); publishEvent({event_type: 'edx.drag_and_drop_v2.loaded'});
}).fail(function() { }).fail(function() {
$root.text(gettext("An error occurred. Unable to load drag and drop exercise.")); $root.text(gettext("An error occurred. Unable to load drag and drop problem."));
}); });
}; };
...@@ -532,7 +532,7 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -532,7 +532,7 @@ function DragAndDropBlock(runtime, element, configuration) {
applyState(); applyState();
}; };
var resetExercise = function(evt) { var resetProblem = function(evt) {
evt.preventDefault(); evt.preventDefault();
$.ajax({ $.ajax({
type: 'POST', type: 'POST',
...@@ -601,10 +601,10 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -601,10 +601,10 @@ function DragAndDropBlock(runtime, element, configuration) {
var context = { var context = {
// configuration - parts that never change: // configuration - parts that never change:
bg_image_width: bgImgNaturalWidth, // Not stored in configuration since it's unknown on the server side bg_image_width: bgImgNaturalWidth, // Not stored in configuration since it's unknown on the server side
header_html: configuration.title, title_html: configuration.title,
show_title: configuration.show_title, show_title: configuration.show_title,
question_html: configuration.question_text, problem_html: configuration.problem_text,
show_question_header: configuration.show_question_header, show_problem_header: configuration.show_problem_header,
target_img_src: configuration.target_img_expanded_url, target_img_src: configuration.target_img_expanded_url,
target_img_description: configuration.target_img_description, target_img_description: configuration.target_img_description,
display_zone_labels: configuration.display_zone_labels, display_zone_labels: configuration.display_zone_labels,
......
...@@ -440,8 +440,8 @@ function DragAndDropEditBlock(runtime, element, params) { ...@@ -440,8 +440,8 @@ function DragAndDropEditBlock(runtime, element, params) {
'display_name': $element.find('.display-name').val(), 'display_name': $element.find('.display-name').val(),
'show_title': $element.find('.show-title').is(':checked'), 'show_title': $element.find('.show-title').is(':checked'),
'weight': $element.find('.weight').val(), 'weight': $element.find('.weight').val(),
'question_text': $element.find('.question-text').val(), 'problem_text': $element.find('.problem-text').val(),
'show_question_header': $element.find('.show-question-header').is(':checked'), 'show_problem_header': $element.find('.show-problem-header').is(':checked'),
'item_background_color': $element.find('.item-background-color').val(), 'item_background_color': $element.find('.item-background-color').val(),
'item_text_color': $element.find('.item-text-color').val(), 'item_text_color': $element.find('.item-text-color').val(),
'data': _fn.data, 'data': _fn.data,
......
...@@ -175,7 +175,7 @@ ...@@ -175,7 +175,7 @@
h( h(
'a.reset-button', 'a.reset-button',
{ style: { display: reset_button_display }, attributes: { tabindex: 0 }}, { style: { display: reset_button_display }, attributes: { tabindex: 0 }},
gettext('Reset exercise') gettext('Reset problem')
), ),
h('h3.title1', { style: { display: feedback_display } }, gettext('Feedback')), h('h3.title1', { style: { display: feedback_display } }, gettext('Feedback')),
h('p.message', { style: { display: feedback_display }, innerHTML: ctx.feedback_html }) h('p.message', { style: { display: feedback_display }, innerHTML: ctx.feedback_html })
...@@ -196,12 +196,12 @@ ...@@ -196,12 +196,12 @@
h('h2.modal-window-title', gettext('Keyboard Help')) h('h2.modal-window-title', gettext('Keyboard Help'))
]), ]),
h('div.modal-content', [ h('div.modal-content', [
h('p', gettext('You can complete this exercise using only your keyboard.')), h('p', gettext('You can complete this problem using only your keyboard.')),
h('ul', [ h('ul', [
h('li', gettext('Use "Tab" and "Shift-Tab" to navigate between items and zones.')), h('li', gettext('Use "Tab" and "Shift-Tab" to navigate between items and zones.')),
h('li', gettext('Press "Enter", "Space", "Ctrl-m", or "⌘-m" on an item to select it for dropping, then navigate to the zone you want to drop it on.')), h('li', gettext('Press "Enter", "Space", "Ctrl-m", or "⌘-m" on an item to select it for dropping, then navigate to the zone you want to drop it on.')),
h('li', gettext('Press "Enter", "Space", "Ctrl-m", or "⌘-m" to drop the item on the current zone.')), h('li', gettext('Press "Enter", "Space", "Ctrl-m", or "⌘-m" to drop the item on the current zone.')),
h('li', gettext('Press "Escape" if you want to cancel the drop operation (e.g. because you would like to select a different item).')), h('li', gettext('Press "Esc" if you want to cancel the drop operation (for example, to select a different item).')),
]) ])
]), ]),
h('div.modal-actions', [ h('div.modal-actions', [
...@@ -214,17 +214,17 @@ ...@@ -214,17 +214,17 @@
}; };
var mainTemplate = function(ctx) { var mainTemplate = function(ctx) {
var problemHeader = ctx.show_title ? h('h2.problem-header', {innerHTML: ctx.header_html}) : null; var problemTitle = ctx.show_title ? h('h2.problem-header', {innerHTML: ctx.title_html}) : null;
var questionHeader = ctx.show_question_header ? h('h3.title1', gettext('Question')) : null; var problemHeader = ctx.show_problem_header ? h('h3.title1', gettext('Problem')) : null;
var is_item_placed = function(i) { return i.is_placed; }; var is_item_placed = function(i) { return i.is_placed; };
var items_placed = $.grep(ctx.items, is_item_placed); var items_placed = $.grep(ctx.items, is_item_placed);
var items_in_bank = $.grep(ctx.items, is_item_placed, true); var items_in_bank = $.grep(ctx.items, is_item_placed, true);
return ( return (
h('section.themed-xblock.xblock--drag-and-drop', [ h('section.themed-xblock.xblock--drag-and-drop', [
problemHeader, problemTitle,
h('section.problem', {role: 'application'}, [ h('section.problem', {role: 'application'}, [
questionHeader, problemHeader,
h('p', {innerHTML: ctx.question_html}), h('p', {innerHTML: ctx.problem_html}),
]), ]),
h('section.drag-container', [ h('section.drag-container', [
h('div.item-bank', renderCollection(itemTemplate, items_in_bank, ctx)), h('div.item-bank', renderCollection(itemTemplate, items_in_bank, ctx)),
......
{% load i18n %} {% load i18n %}
<section class="themed-xblock xblock--drag-and-drop"> <section class="themed-xblock xblock--drag-and-drop">
<i class="fa fa-spin fa-spinner initial-load-spinner"></i>{% trans "Loading drag and drop exercise." %} <i class="fa fa-spin fa-spinner initial-load-spinner"></i>{% trans "Loading drag and drop problem." %}
</section> </section>
...@@ -6,12 +6,12 @@ ...@@ -6,12 +6,12 @@
<section class="drag-builder"> <section class="drag-builder">
<div class="tab feedback-tab"> <div class="tab feedback-tab">
<p class="tab-content"> <p class="tab-content">
{% trans "Note: don't edit the question if students already answered it! Delete it and create a new one." %} {% trans "Note: do not edit the problem if students have already completed it. Delete the problem and create a new one." %}
</p> </p>
<section class="tab-content"> <section class="tab-content">
<form class="feedback-form"> <form class="feedback-form">
<h3>{% trans "Question title" %}</h3> <h3>{% trans "Problem title" %}</h3>
<input class="display-name" value="{{ self.display_name }}" /> <input class="display-name" value="{{ self.display_name }}" />
<label title="{{ help_texts.show_title }}"> <label title="{{ help_texts.show_title }}">
<input class="show-title" type="checkbox" <input class="show-title" type="checkbox"
...@@ -22,12 +22,12 @@ ...@@ -22,12 +22,12 @@
<h3>{% trans "Maximum score" %}</h3> <h3>{% trans "Maximum score" %}</h3>
<input type="number" step="0.1" class="weight" value="1" value="{{ self.weight }}" /> <input type="number" step="0.1" class="weight" value="1" value="{{ self.weight }}" />
<h3>{% trans "Question text" %}</h3> <h3>{% trans "Problem text" %}</h3>
<textarea class="question-text">{{ self.question_text }}</textarea> <textarea class="problem-text">{{ self.question_text }}</textarea>
<label title="{{ help_texts.show_question_header }}"> <label title="{{ help_texts.show_question_header }}">
<input class="show-question-header" type="checkbox" <input class="show-problem-header" type="checkbox"
{% if self.show_question_header %}checked="checked"{% endif %}> {% if self.show_question_header %}checked="checked"{% endif %}>
{% trans "Show \"Question\" heading" %} {% trans 'Show "Problem" heading' %}
</label> </label>
<h3>{% trans "Introductory Feedback" %}</h3> <h3>{% trans "Introductory Feedback" %}</h3>
...@@ -51,7 +51,7 @@ ...@@ -51,7 +51,7 @@
<input type="text" <input type="text"
class="url-input" class="url-input"
aria-labelledby="background-url-label" aria-labelledby="background-url-label"
placeholder="{% trans 'e.g. http://example.com/background.png or /static/background.png' %}"> placeholder="{% trans 'For example, http://example.com/background.png or /static/background.png' %}">
<h3 id="background-description-label"> <h3 id="background-description-label">
{% trans "Background description" %} {% trans "Background description" %}
</h3> </h3>
...@@ -61,7 +61,7 @@ ...@@ -61,7 +61,7 @@
<div id="background-description-description" class="target-image-form-help"> <div id="background-description-description" class="target-image-form-help">
{% blocktrans %} {% blocktrans %}
Please provide a description of the image for non-visual users. Please provide a description of the image for non-visual users.
The description should provide sufficient information that would allow anyone The description should provide sufficient information to allow anyone
to solve the problem even without seeing the image. to solve the problem even without seeing the image.
{% endblocktrans %} {% endblocktrans %}
</div> </div>
......
...@@ -101,7 +101,7 @@ ...@@ -101,7 +101,7 @@
</div> </div>
<div class="row advanced"> <div class="row advanced">
<label for="item-{{id}}-numerical-value"> <label for="item-{{id}}-numerical-value">
{{i18n "Optional numerical value (if you set this, students will be prompted for this value after dropping this item)"}} {{i18n "Optional numerical value (if you set this, learners will be prompted for this value after dropping this item)"}}
</label> </label>
<input type="number" <input type="number"
step="0.1" step="0.1"
...@@ -110,7 +110,7 @@ ...@@ -110,7 +110,7 @@
</div> </div>
<div class="row advanced"> <div class="row advanced">
<label for="item-{{id}}-numerical-margin"> <label for="item-{{id}}-numerical-margin">
{{i18n "Margin ± (when a numerical value is required, values entered by students must not differ from the expected value by more than this margin; default is zero)"}} {{i18n "Margin ± (when a numerical value is required, values entered by learners must not differ from the expected value by more than this margin; default is zero)"}}
</label> </label>
<input type="number" <input type="number"
step="0.1" step="0.1"
......
...@@ -57,7 +57,7 @@ ...@@ -57,7 +57,7 @@
], ],
"feedback": { "feedback": {
"start": "Drag the items onto the image above.", "start": "Drag the items onto the image above.",
"finish": "Good work! You have completed this drag and drop exercise." "finish": "Good work! You have completed this drag and drop problem."
}, },
"targetImgDescription": "This describes the target image", "targetImgDescription": "This describes the target image",
"displayLabels": {display_labels_value}, "displayLabels": {display_labels_value},
......
...@@ -27,14 +27,14 @@ class BaseIntegrationTest(SeleniumBaseTest): ...@@ -27,14 +27,14 @@ class BaseIntegrationTest(SeleniumBaseTest):
} }
@staticmethod @staticmethod
def _make_scenario_xml(display_name, show_title, question_text, completed=False, show_question_header=True): def _make_scenario_xml(display_name, show_title, problem_text, completed=False, show_problem_header=True):
return """ return """
<vertical_demo> <vertical_demo>
<drag-and-drop-v2 <drag-and-drop-v2
display_name='{display_name}' display_name='{display_name}'
show_title='{show_title}' show_title='{show_title}'
question_text='{question_text}' question_text='{problem_text}'
show_question_header='{show_question_header}' show_question_header='{show_problem_header}'
weight='1' weight='1'
completed='{completed}' completed='{completed}'
/> />
...@@ -42,8 +42,8 @@ class BaseIntegrationTest(SeleniumBaseTest): ...@@ -42,8 +42,8 @@ class BaseIntegrationTest(SeleniumBaseTest):
""".format( """.format(
display_name=escape(display_name), display_name=escape(display_name),
show_title=show_title, show_title=show_title,
question_text=escape(question_text), problem_text=escape(problem_text),
show_question_header=show_question_header, show_problem_header=show_problem_header,
completed=completed, completed=completed,
) )
......
...@@ -247,7 +247,7 @@ class InteractionTestBase(object): ...@@ -247,7 +247,7 @@ class InteractionTestBase(object):
# Check decoy items # Check decoy items
self.assert_decoy_items(items_map) self.assert_decoy_items(items_map)
# Scroll "Reset exercise" button into view to make sure Selenium can successfully click it # Scroll "Reset problem" button into view to make sure Selenium can successfully click it
self.scroll_down(pixels=scroll_down+150) self.scroll_down(pixels=scroll_down+150)
reset = self._get_reset_button() reset = self._get_reset_button()
......
...@@ -46,19 +46,19 @@ class TestDragAndDropRender(BaseIntegrationTest): ...@@ -46,19 +46,19 @@ class TestDragAndDropRender(BaseIntegrationTest):
SIDES = ['Top', 'Bottom', 'Left', 'Right'] SIDES = ['Top', 'Bottom', 'Left', 'Right']
def load_scenario(self, item_background_color="", item_text_color="", zone_labels=False, zone_borders=False): def load_scenario(self, item_background_color="", item_text_color="", zone_labels=False, zone_borders=False):
exercise_data = loader.load_unicode("data/test_data_a11y.json") problem_data = loader.load_unicode("data/test_data_a11y.json")
exercise_data = exercise_data.replace('{display_labels_value}', 'true' if zone_labels else 'false') problem_data = problem_data.replace('{display_labels_value}', 'true' if zone_labels else 'false')
exercise_data = exercise_data.replace('{display_borders_value}', 'true' if zone_borders else 'false') problem_data = problem_data.replace('{display_borders_value}', 'true' if zone_borders else 'false')
scenario_xml = """ scenario_xml = """
<vertical_demo> <vertical_demo>
<drag-and-drop-v2 item_background_color='{item_background_color}' <drag-and-drop-v2 item_background_color='{item_background_color}'
item_text_color='{item_text_color}' item_text_color='{item_text_color}'
data='{exercise_data}' /> data='{problem_data}' />
</vertical_demo> </vertical_demo>
""".format( """.format(
item_background_color=item_background_color, item_background_color=item_background_color,
item_text_color=item_text_color, item_text_color=item_text_color,
exercise_data=exercise_data problem_data=problem_data
) )
self._add_scenario(self.PAGE_ID, self.PAGE_TITLE, scenario_xml) self._add_scenario(self.PAGE_ID, self.PAGE_TITLE, scenario_xml)
......
...@@ -5,32 +5,32 @@ from workbench import scenarios ...@@ -5,32 +5,32 @@ from workbench import scenarios
@ddt @ddt
class TestDragAndDropTitleAndQuestion(BaseIntegrationTest): class TestDragAndDropTitleAndProblem(BaseIntegrationTest):
@unpack @unpack
@data( @data(
('Plain text question 1, header visible.', True), ('Plain text problem 1, header visible.', True),
('Plain text question 2, header hidden.', False), ('Plain text problem 2, header hidden.', False),
('Question/instructions with <i>HTML</i> and header.', True), ('Problem/instructions with <i>HTML</i> and header.', True),
('<span style="color: red;">Span question, no header</span>', False), ('<span style="color: red;">Span problem, no header</span>', False),
) )
def test_question_parameters(self, question_text, show_question_header): def test_problem_parameters(self, problem_text, show_problem_header):
const_page_name = 'Test title and question parameters' const_page_name = 'Test title and problem parameters'
const_page_id = 'test_block_title_and_question' const_page_id = 'test_block_title_and_problem'
scenario_xml = self._make_scenario_xml( scenario_xml = self._make_scenario_xml(
display_name="Title", display_name="Title",
show_title=True, show_title=True,
question_text=question_text, problem_text=problem_text,
show_question_header=show_question_header, show_problem_header=show_problem_header,
) )
scenarios.add_xml_scenario(const_page_id, const_page_name, scenario_xml) scenarios.add_xml_scenario(const_page_id, const_page_name, scenario_xml)
self.addCleanup(scenarios.remove_scenario, const_page_id) self.addCleanup(scenarios.remove_scenario, const_page_id)
page = self.go_to_page(const_page_name) page = self.go_to_page(const_page_name)
is_question_header_visible = len(page.find_elements_by_css_selector('section.problem > h3')) > 0 is_problem_header_visible = len(page.find_elements_by_css_selector('section.problem > h3')) > 0
self.assertEqual(is_question_header_visible, show_question_header) self.assertEqual(is_problem_header_visible, show_problem_header)
question = page.find_element_by_css_selector('section.problem > p') problem = page.find_element_by_css_selector('section.problem > p')
self.assertEqual(self.get_element_html(question), question_text) self.assertEqual(self.get_element_html(problem), problem_text)
@unpack @unpack
@data( @data(
...@@ -45,7 +45,7 @@ class TestDragAndDropTitleAndQuestion(BaseIntegrationTest): ...@@ -45,7 +45,7 @@ class TestDragAndDropTitleAndQuestion(BaseIntegrationTest):
scenario_xml = self._make_scenario_xml( scenario_xml = self._make_scenario_xml(
display_name=display_name, display_name=display_name,
show_title=show_title, show_title=show_title,
question_text='Generic question', problem_text='Generic problem',
) )
scenarios.add_xml_scenario(const_page_id, const_page_name, scenario_xml) scenarios.add_xml_scenario(const_page_id, const_page_name, scenario_xml)
self.addCleanup(scenarios.remove_scenario, const_page_id) self.addCleanup(scenarios.remove_scenario, const_page_id)
......
{ {
"title": "DnDv2 XBlock with HTML instructions", "title": "DnDv2 XBlock with HTML instructions",
"show_title": false, "show_title": false,
"question_text": "Solve this <strong>drag-and-drop</strong> problem.", "problem_text": "Solve this <strong>drag-and-drop</strong> problem.",
"show_question_header": false, "show_problem_header": false,
"target_img_expanded_url": "/expanded/url/to/drag_and_drop_v2/public/img/triangle.png", "target_img_expanded_url": "/expanded/url/to/drag_and_drop_v2/public/img/triangle.png",
"target_img_description": "This describes the target image", "target_img_description": "This describes the target image",
"item_background_color": "white", "item_background_color": "white",
......
{ {
"title": "Drag and Drop", "title": "Drag and Drop",
"show_title": true, "show_title": true,
"question_text": "", "problem_text": "",
"show_question_header": true, "show_problem_header": true,
"target_img_expanded_url": "http://i0.kym-cdn.com/photos/images/newsfeed/000/030/404/1260585284155.png", "target_img_expanded_url": "http://i0.kym-cdn.com/photos/images/newsfeed/000/030/404/1260585284155.png",
"target_img_description": "This describes the target image", "target_img_description": "This describes the target image",
"item_background_color": null, "item_background_color": null,
......
{ {
"title": "DnDv2 XBlock with plain text instructions", "title": "DnDv2 XBlock with plain text instructions",
"show_title": true, "show_title": true,
"question_text": "Can you solve this drag-and-drop problem?", "problem_text": "Can you solve this drag-and-drop problem?",
"show_question_header": true, "show_problem_header": true,
"target_img_expanded_url": "http://placehold.it/800x600", "target_img_expanded_url": "http://placehold.it/800x600",
"target_img_description": "This describes the target image", "target_img_description": "This describes the target image",
"item_background_color": null, "item_background_color": null,
......
...@@ -18,7 +18,7 @@ class BasicTests(TestCaseMixin, unittest.TestCase): ...@@ -18,7 +18,7 @@ class BasicTests(TestCaseMixin, unittest.TestCase):
context = {} context = {}
student_fragment = self.block.runtime.render(self.block, 'student_view', context) student_fragment = self.block.runtime.render(self.block, 'student_view', context)
self.assertIn('<section class="themed-xblock xblock--drag-and-drop">', student_fragment.content) self.assertIn('<section class="themed-xblock xblock--drag-and-drop">', student_fragment.content)
self.assertIn('Loading drag and drop exercise.', student_fragment.content) self.assertIn('Loading drag and drop problem.', student_fragment.content)
def test_get_configuration(self): def test_get_configuration(self):
""" """
...@@ -33,8 +33,8 @@ class BasicTests(TestCaseMixin, unittest.TestCase): ...@@ -33,8 +33,8 @@ class BasicTests(TestCaseMixin, unittest.TestCase):
"display_zone_labels": False, "display_zone_labels": False,
"title": "Drag and Drop", "title": "Drag and Drop",
"show_title": True, "show_title": True,
"question_text": "", "problem_text": "",
"show_question_header": True, "show_problem_header": True,
"target_img_expanded_url": '/expanded/url/to/drag_and_drop_v2/public/img/triangle.png', "target_img_expanded_url": '/expanded/url/to/drag_and_drop_v2/public/img/triangle.png',
"target_img_description": TARGET_IMG_DESCRIPTION, "target_img_description": TARGET_IMG_DESCRIPTION,
"item_background_color": None, "item_background_color": None,
...@@ -97,8 +97,8 @@ class BasicTests(TestCaseMixin, unittest.TestCase): ...@@ -97,8 +97,8 @@ class BasicTests(TestCaseMixin, unittest.TestCase):
body = { body = {
'display_name': "Test Drag & Drop", 'display_name': "Test Drag & Drop",
'show_title': False, 'show_title': False,
'question_text': "Question Drag & Drop", 'problem_text': "Problem Drag & Drop",
'show_question_header': False, 'show_problem_header': False,
'item_background_color': 'cornflowerblue', 'item_background_color': 'cornflowerblue',
'item_text_color': 'coral', 'item_text_color': 'coral',
'weight': '5', 'weight': '5',
...@@ -111,7 +111,7 @@ class BasicTests(TestCaseMixin, unittest.TestCase): ...@@ -111,7 +111,7 @@ class BasicTests(TestCaseMixin, unittest.TestCase):
self.assertEqual(self.block.show_title, False) self.assertEqual(self.block.show_title, False)
self.assertEqual(self.block.display_name, "Test Drag & Drop") self.assertEqual(self.block.display_name, "Test Drag & Drop")
self.assertEqual(self.block.question_text, "Question Drag & Drop") self.assertEqual(self.block.question_text, "Problem Drag & Drop")
self.assertEqual(self.block.show_question_header, False) self.assertEqual(self.block.show_question_header, False)
self.assertEqual(self.block.item_background_color, "cornflowerblue") self.assertEqual(self.block.item_background_color, "cornflowerblue")
self.assertEqual(self.block.item_text_color, "coral") self.assertEqual(self.block.item_text_color, "coral")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment