Commit 30173c47 by Matjaz Gregoric Committed by GitHub

Merge pull request #82 from open-craft/mtyaka/assessment-item-placement

Keep items in dropped position in assessment mode.
parents cd689891 97c5c4d8
...@@ -190,6 +190,7 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin): ...@@ -190,6 +190,7 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin):
return items return items
return { return {
"mode": self.mode,
"zones": self._get_zones(), "zones": self._get_zones(),
# SDK doesn't supply url_name. # SDK doesn't supply url_name.
"url_name": getattr(self, 'url_name', ''), "url_name": getattr(self, 'url_name', ''),
...@@ -337,12 +338,18 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin): ...@@ -337,12 +338,18 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin):
'is_correct': is_correct, 'is_correct': is_correct,
}) })
return { if self.mode == self.ASSESSMENT_MODE:
'correct': is_correct, # In assessment mode we don't send any feedback on drop.
'finished': self._is_finished(), result = {}
'overall_feedback': overall_feedback, else:
'feedback': feedback result = {
} 'correct': is_correct,
'finished': self._is_finished(),
'overall_feedback': overall_feedback,
'feedback': feedback
}
return result
@XBlock.json_handler @XBlock.json_handler
def reset(self, data, suffix=''): def reset(self, data, suffix=''):
......
function DragNDropTemplates(url_name) { function DragAndDropTemplates(configuration) {
"use strict"; "use strict";
var h = virtualDom.h; var h = virtualDom.h;
// Set up a mock for gettext if it isn't available in the client runtime: // Set up a mock for gettext if it isn't available in the client runtime:
...@@ -107,13 +107,22 @@ function DragNDropTemplates(url_name) { ...@@ -107,13 +107,22 @@ function DragNDropTemplates(url_name) {
var item_content = h('div', { innerHTML: item_content_html, className: "item-content" }); var item_content = h('div', { innerHTML: item_content_html, className: "item-content" });
if (item.is_placed) { if (item.is_placed) {
// Insert information about zone in which this item has been placed // Insert information about zone in which this item has been placed
var item_description_id = url_name + '-item-' + item.value + '-description'; var item_description_id = configuration.url_name + '-item-' + item.value + '-description';
item_content.properties.attributes = { 'aria-describedby': item_description_id }; item_content.properties.attributes = { 'aria-describedby': item_description_id };
var zone_title = (zone.title || "Unknown Zone"); // This "Unknown" text should never be seen, so does not need i18n var zone_title = (zone.title || "Unknown Zone"); // This "Unknown" text should never be seen, so does not need i18n
var description_content;
if (configuration.mode === DragAndDropBlock.ASSESSMENT_MODE) {
// In assessment mode placed items will "stick" even when not in correct zone.
description_content = gettext('Placed in: {zone_title}').replace('{zone_title}', zone_title);
} else {
// In standard mode item is immediately returned back to the bank if dropped on a wrong zone,
// so all placed items are always in the correct zone.
description_content = gettext('Correctly placed in: {zone_title}').replace('{zone_title}', zone_title);
}
var item_description = h( var item_description = h(
'div', 'div',
{ id: item_description_id, className: 'sr' }, { id: item_description_id, className: 'sr' },
gettext('Correctly placed in: ') + zone_title description_content
); );
children.splice(1, 0, item_description); children.splice(1, 0, item_description);
} }
...@@ -283,14 +292,17 @@ function DragNDropTemplates(url_name) { ...@@ -283,14 +292,17 @@ function DragNDropTemplates(url_name) {
); );
}; };
DragAndDropBlock.renderView = mainTemplate; return mainTemplate;
} }
function DragAndDropBlock(runtime, element, configuration) { function DragAndDropBlock(runtime, element, configuration) {
"use strict"; "use strict";
DragNDropTemplates(configuration.url_name); DragAndDropBlock.STANDARD_MODE = 'standard';
DragAndDropBlock.ASSESSMENT_MODE = 'assessment';
var renderView = DragAndDropTemplates(configuration);
// Set up a mock for gettext if it isn't available in the client runtime: // Set up a mock for gettext if it isn't available in the client runtime:
if (!window.gettext) { window.gettext = function gettext_stub(string) { return string; }; } if (!window.gettext) { window.gettext = function gettext_stub(string) { return string; }; }
...@@ -747,17 +759,21 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -747,17 +759,21 @@ function DragAndDropBlock(runtime, element, configuration) {
$.post(url, JSON.stringify(data), 'json') $.post(url, JSON.stringify(data), 'json')
.done(function(data){ .done(function(data){
state.last_action_correct = data.correct; state.items[item_id].submitting_location = false;
if (data.correct) { // In standard mode we immediately return item to the bank if dropped on wrong zone.
state.items[item_id].correct = true; // In assessment mode we leave it in the chosen zone until explicit answer submission.
state.items[item_id].submitting_location = false; if (configuration.mode === DragAndDropBlock.STANDARD_MODE) {
} else { state.last_action_correct = data.correct;
delete state.items[item_id]; if (data.correct) {
} state.items[item_id].correct = true;
state.feedback = data.feedback; } else {
if (data.finished) { delete state.items[item_id];
state.finished = true; }
state.overall_feedback = data.overall_feedback; state.feedback = data.feedback;
if (data.finished) {
state.finished = true;
state.overall_feedback = data.overall_feedback;
}
} }
applyState(); applyState();
}) })
...@@ -866,7 +882,7 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -866,7 +882,7 @@ function DragAndDropBlock(runtime, element, configuration) {
display_reset_button: Object.keys(state.items).length > 0, display_reset_button: Object.keys(state.items).length > 0,
}; };
return DragAndDropBlock.renderView(context); return renderView(context);
}; };
/** /**
......
...@@ -409,6 +409,10 @@ msgid "ok" ...@@ -409,6 +409,10 @@ msgid "ok"
msgstr "" msgstr ""
#: public/js/drag_and_drop.js #: public/js/drag_and_drop.js
msgid "Placed in: "
msgstr ""
#: public/js/drag_and_drop.js
msgid "Correctly placed in: " msgid "Correctly placed in: "
msgstr "" msgstr ""
......
...@@ -494,6 +494,10 @@ msgid "ok" ...@@ -494,6 +494,10 @@ msgid "ok"
msgstr "ök Ⱡ'σя#" msgstr "ök Ⱡ'σя#"
#: public/js/drag_and_drop.js #: public/js/drag_and_drop.js
msgid "Placed in: "
msgstr "Pläçéd ïn: Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, #"
#: public/js/drag_and_drop.js
msgid "Correctly placed in: " msgid "Correctly placed in: "
msgstr "Çörréçtlý pläçéd ïn: Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, #" msgstr "Çörréçtlý pläçéd ïn: Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, #"
......
{ {
"title": "DnDv2 XBlock with HTML instructions", "title": "DnDv2 XBlock with HTML instructions",
"mode": "standard",
"show_title": false, "show_title": false,
"problem_text": "Solve this <strong>drag-and-drop</strong> problem.", "problem_text": "Solve this <strong>drag-and-drop</strong> problem.",
"show_problem_header": false, "show_problem_header": false,
......
{ {
"title": "Drag and Drop", "title": "Drag and Drop",
"mode": "standard",
"show_title": true, "show_title": true,
"problem_text": "", "problem_text": "",
"show_problem_header": true, "show_problem_header": true,
......
{ {
"title": "DnDv2 XBlock with plain text instructions", "title": "DnDv2 XBlock with plain text instructions",
"mode": "standard",
"show_title": true, "show_title": true,
"problem_text": "Can you solve this drag-and-drop problem?", "problem_text": "Can you solve this drag-and-drop problem?",
"show_problem_header": true, "show_problem_header": true,
......
...@@ -5,6 +5,8 @@ import unittest ...@@ -5,6 +5,8 @@ import unittest
from xblockutils.resources import ResourceLoader from xblockutils.resources import ResourceLoader
from drag_and_drop_v2.drag_and_drop_v2 import DragAndDropBlock
from ..utils import make_block, TestCaseMixin from ..utils import make_block, TestCaseMixin
...@@ -90,6 +92,14 @@ class BaseDragAndDropAjaxFixture(TestCaseMixin): ...@@ -90,6 +92,14 @@ class BaseDragAndDropAjaxFixture(TestCaseMixin):
"feedback": self.FEEDBACK[item_id]["correct"] "feedback": self.FEEDBACK[item_id]["correct"]
}) })
def test_do_attempt_in_assessment_mode(self):
self.block.mode = DragAndDropBlock.ASSESSMENT_MODE
item_id, zone_id = 0, self.ZONE_1
data = {"val": item_id, "zone": zone_id, "x_percent": "33%", "y_percent": "11%"}
res = self.call_handler('do_attempt', data)
# In assessment mode, the do_attempt doesn't return any data.
self.assertEqual(res, {})
def test_grading(self): def test_grading(self):
published_grades = [] published_grades = []
......
...@@ -30,6 +30,7 @@ class BasicTests(TestCaseMixin, unittest.TestCase): ...@@ -30,6 +30,7 @@ class BasicTests(TestCaseMixin, unittest.TestCase):
zones = config.pop("zones") zones = config.pop("zones")
items = config.pop("items") items = config.pop("items")
self.assertEqual(config, { self.assertEqual(config, {
"mode": DragAndDropBlock.STANDARD_MODE,
"display_zone_borders": False, "display_zone_borders": False,
"display_zone_labels": False, "display_zone_labels": False,
"title": "Drag and Drop", "title": "Drag and Drop",
......
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