Commit 719812a4 by Braden MacDonald

Merge branch 'braden/bugfixes' into st-gallen-2016-02-10

parents 7e91fe68 698f404d
...@@ -6,6 +6,10 @@ TARGET_IMG_DESCRIPTION = _( ...@@ -6,6 +6,10 @@ TARGET_IMG_DESCRIPTION = _(
"and the narrowest layer is located at the top." "and the narrowest layer is located at the top."
) )
TOP_ZONE_ID = "top"
MIDDLE_ZONE_ID = "middle"
BOTTOM_ZONE_ID = "bottom"
TOP_ZONE_TITLE = _("The Top Zone") TOP_ZONE_TITLE = _("The Top Zone")
MIDDLE_ZONE_TITLE = _("The Middle Zone") MIDDLE_ZONE_TITLE = _("The Middle Zone")
BOTTOM_ZONE_TITLE = _("The Bottom Zone") BOTTOM_ZONE_TITLE = _("The Bottom Zone")
...@@ -25,8 +29,7 @@ DEFAULT_DATA = { ...@@ -25,8 +29,7 @@ DEFAULT_DATA = {
"targetImgDescription": TARGET_IMG_DESCRIPTION, "targetImgDescription": TARGET_IMG_DESCRIPTION,
"zones": [ "zones": [
{ {
"index": 1, "uid": TOP_ZONE_ID,
"id": "zone-1",
"title": TOP_ZONE_TITLE, "title": TOP_ZONE_TITLE,
"description": TOP_ZONE_DESCRIPTION, "description": TOP_ZONE_DESCRIPTION,
"x": 160, "x": 160,
...@@ -35,8 +38,7 @@ DEFAULT_DATA = { ...@@ -35,8 +38,7 @@ DEFAULT_DATA = {
"height": 178, "height": 178,
}, },
{ {
"index": 2, "uid": MIDDLE_ZONE_ID,
"id": "zone-2",
"title": MIDDLE_ZONE_TITLE, "title": MIDDLE_ZONE_TITLE,
"description": MIDDLE_ZONE_DESCRIPTION, "description": MIDDLE_ZONE_DESCRIPTION,
"x": 86, "x": 86,
...@@ -45,8 +47,7 @@ DEFAULT_DATA = { ...@@ -45,8 +47,7 @@ DEFAULT_DATA = {
"height": 138, "height": 138,
}, },
{ {
"index": 3, "uid": BOTTOM_ZONE_ID,
"id": "zone-3",
"title": BOTTOM_ZONE_TITLE, "title": BOTTOM_ZONE_TITLE,
"description": BOTTOM_ZONE_DESCRIPTION, "description": BOTTOM_ZONE_DESCRIPTION,
"x": 15, "x": 15,
...@@ -62,7 +63,7 @@ DEFAULT_DATA = { ...@@ -62,7 +63,7 @@ DEFAULT_DATA = {
"incorrect": ITEM_INCORRECT_FEEDBACK, "incorrect": ITEM_INCORRECT_FEEDBACK,
"correct": ITEM_CORRECT_FEEDBACK.format(zone=TOP_ZONE_TITLE) "correct": ITEM_CORRECT_FEEDBACK.format(zone=TOP_ZONE_TITLE)
}, },
"zone": TOP_ZONE_TITLE, "zone": TOP_ZONE_ID,
"imageURL": "", "imageURL": "",
"id": 0, "id": 0,
}, },
...@@ -72,7 +73,7 @@ DEFAULT_DATA = { ...@@ -72,7 +73,7 @@ DEFAULT_DATA = {
"incorrect": ITEM_INCORRECT_FEEDBACK, "incorrect": ITEM_INCORRECT_FEEDBACK,
"correct": ITEM_CORRECT_FEEDBACK.format(zone=MIDDLE_ZONE_TITLE) "correct": ITEM_CORRECT_FEEDBACK.format(zone=MIDDLE_ZONE_TITLE)
}, },
"zone": MIDDLE_ZONE_TITLE, "zone": MIDDLE_ZONE_ID,
"imageURL": "", "imageURL": "",
"id": 1, "id": 1,
}, },
...@@ -82,7 +83,7 @@ DEFAULT_DATA = { ...@@ -82,7 +83,7 @@ DEFAULT_DATA = {
"incorrect": ITEM_INCORRECT_FEEDBACK, "incorrect": ITEM_INCORRECT_FEEDBACK,
"correct": ITEM_CORRECT_FEEDBACK.format(zone=BOTTOM_ZONE_TITLE) "correct": ITEM_CORRECT_FEEDBACK.format(zone=BOTTOM_ZONE_TITLE)
}, },
"zone": BOTTOM_ZONE_TITLE, "zone": BOTTOM_ZONE_ID,
"imageURL": "", "imageURL": "",
"id": 2, "id": 2,
}, },
......
...@@ -9,6 +9,7 @@ import copy ...@@ -9,6 +9,7 @@ import copy
import urllib import urllib
from xblock.core import XBlock from xblock.core import XBlock
from xblock.exceptions import JsonHandlerError
from xblock.fields import Scope, String, Dict, Float, Boolean from xblock.fields import Scope, String, Dict, Float, Boolean
from xblock.fragment import Fragment from xblock.fragment import Fragment
from xblockutils.resources import ResourceLoader from xblockutils.resources import ResourceLoader
...@@ -154,7 +155,7 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin): ...@@ -154,7 +155,7 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin):
return items return items
return { return {
"zones": self.data.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', ''),
"display_zone_labels": self.data.get('displayLabels', False), "display_zone_labels": self.data.get('displayLabels', False),
...@@ -234,6 +235,7 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin): ...@@ -234,6 +235,7 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin):
item = self._get_item_definition(attempt['val']) item = self._get_item_definition(attempt['val'])
state = None state = None
zone = None
feedback = item['feedback']['incorrect'] feedback = item['feedback']['incorrect']
overall_feedback = None overall_feedback = None
is_correct = False is_correct = False
...@@ -268,6 +270,11 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin): ...@@ -268,6 +270,11 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin):
if state: if state:
self.item_state[str(item['id'])] = state self.item_state[str(item['id'])] = state
zone = self._get_zone_by_uid(state['zone'])
else:
zone = self._get_zone_by_uid(attempt['zone'])
if not zone:
raise JsonHandlerError(400, "Item zone data invalid.")
if self._is_finished(): if self._is_finished():
overall_feedback = self.data['feedback']['finish'] overall_feedback = self.data['feedback']['finish']
...@@ -288,7 +295,8 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin): ...@@ -288,7 +295,8 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin):
self.runtime.publish(self, 'edx.drag_and_drop_v2.item.dropped', { self.runtime.publish(self, 'edx.drag_and_drop_v2.item.dropped', {
'item_id': item['id'], 'item_id': item['id'],
'location': attempt.get('zone'), 'location': zone.get("title"),
'location_id': zone.get("uid"),
'input': attempt.get('input'), 'input': attempt.get('input'),
'is_correct_location': is_correct_location, 'is_correct_location': is_correct_location,
'is_correct': is_correct, 'is_correct': is_correct,
...@@ -395,6 +403,30 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin): ...@@ -395,6 +403,30 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin):
""" """
return next(i for i in self.data['items'] if i['id'] == item_id) return next(i for i in self.data['items'] if i['id'] == item_id)
def _get_zones(self):
"""
Get drop zone data, defined by the author.
"""
# Convert zone data from old to new format if necessary
zones = []
for zone in self.data.get('zones', []):
zone = zone.copy()
if "uid" not in zone:
zone["uid"] = zone.get("title") # Older versions used title as the zone UID
# Remove old, now-unused zone attributes, if present:
zone.pop("id", None)
zone.pop("index", None)
zones.append(zone)
return zones
def _get_zone_by_uid(self, uid):
"""
Given a zone UID, return that zone, or None.
"""
for zone in self._get_zones():
if zone["uid"] == uid:
return zone
def _get_grade(self): def _get_grade(self):
""" """
Returns the student's grade for this block. Returns the student's grade for this block.
......
...@@ -52,6 +52,16 @@ function DragNDropTemplates(url_name) { ...@@ -52,6 +52,16 @@ function DragNDropTemplates(url_name) {
); );
}; };
var getZoneTitle = function(zoneUID, ctx) {
// Given the context and a zone UID, return the zone's title
for (var i = 0; i < ctx.zones.length; i++) {
if (ctx.zones[i].uid === zoneUID) {
return ctx.zones[i].title;
}
}
return "Unknown Zone"; // This title should never be seen, so does not need i18n
}
var itemTemplate = function(item, ctx) { var itemTemplate = function(item, ctx) {
// Define properties // Define properties
var className = (item.class_name) ? item.class_name : ""; var className = (item.class_name) ? item.class_name : "";
...@@ -126,7 +136,7 @@ function DragNDropTemplates(url_name) { ...@@ -126,7 +136,7 @@ function DragNDropTemplates(url_name) {
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: ') + item.zone gettext('Correctly placed in: ') + getZoneTitle(item.zone, ctx)
); );
children.splice(1, 0, item_description); children.splice(1, 0, item_description);
} }
...@@ -164,12 +174,12 @@ function DragNDropTemplates(url_name) { ...@@ -164,12 +174,12 @@ function DragNDropTemplates(url_name) {
h( h(
selector, selector,
{ {
id: zone.id, id: zone.prefixed_uid,
attributes: { attributes: {
'tabindex': 0, 'tabindex': 0,
'dropzone': 'move', 'dropzone': 'move',
'aria-dropeffect': 'move', 'aria-dropeffect': 'move',
'data-zone': zone.title, 'data-uid': zone.uid,
'data-zonealign': zone.align, 'data-zonealign': zone.align,
'role': 'button', 'role': 'button',
}, },
...@@ -473,7 +483,8 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -473,7 +483,8 @@ function DragAndDropBlock(runtime, element, configuration) {
delete zone.width; delete zone.width;
zone.height_percent = (+zone.height) / bg_image_height * 100; zone.height_percent = (+zone.height) / bg_image_height * 100;
delete zone.height; delete zone.height;
zone.id = configuration.url_name + '-' + zone.id; // Generate an HTML ID value that's unique within the DOM and not containing spaces etc:
zone.prefixed_uid = configuration.url_name + '-' + zone.uid.replace(/([^\w\-])/g, "_");
} }
}; };
...@@ -606,7 +617,7 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -606,7 +617,7 @@ function DragAndDropBlock(runtime, element, configuration) {
// so use relevant properties of *zone* when calculating new position below. // so use relevant properties of *zone* when calculating new position below.
$anchor = $zone; $anchor = $zone;
} }
var zone = $zone.data('zone'); var zone = String($zone.data('uid'));
var zone_align = $zone.data('zonealign'); var zone_align = $zone.data('zonealign');
var $target_img = $root.find('.target-img'); var $target_img = $root.find('.target-img');
......
...@@ -211,34 +211,28 @@ function DragAndDropEditBlock(runtime, element, params) { ...@@ -211,34 +211,28 @@ function DragAndDropEditBlock(runtime, element, params) {
}, },
form: { form: {
zone: { zone: {
count: 0, totalZonesCreated: 0, // This counter is used for HTML IDs. Never decremented.
formCount: 0,
zoneObjects: [], zoneObjects: [],
getObjByIndex: function(num) { getZoneObjByUID: function(uid) {
for (var i = 0; i < _fn.build.form.zone.zoneObjects.length; i++) { for (var i = 0; i < _fn.build.form.zone.zoneObjects.length; i++) {
if (_fn.build.form.zone.zoneObjects[i].index == num) if (_fn.build.form.zone.zoneObjects[i].uid == uid) {
return _fn.build.form.zone.zoneObjects[i]; return _fn.build.form.zone.zoneObjects[i];
} }
}
}, },
add: function(oldZone) { add: function(oldZone) {
var inputTemplate = _fn.tpl.zoneInput,
name = 'zone-',
$elements = _fn.build.$el,
num;
if (!oldZone) oldZone = {}; if (!oldZone) oldZone = {};
var num = _fn.build.form.zone.zoneObjects.length + 1;
_fn.build.form.zone.count++;
_fn.build.form.zone.formCount++;
num = _fn.build.form.zone.count;
name += num;
// Update zone obj // Update zone obj
var zoneObj = { var zoneObj = {
title: oldZone.title || 'Zone ' + num, title: oldZone.title || 'Zone ' + num,
description: oldZone.description, description: oldZone.description,
id: name, // uid: unique ID for this zone. For backwards compatibility,
index: num, // this field cannot be called "id" and must inherit the "title"
// property if no 'uid' value is present, since old versions of
// this block used the title as the primary identifier.
uid: oldZone.uid || oldZone.title || _fn.build.form.zone.generateUID(),
width: oldZone.width || 200, width: oldZone.width || 200,
height: oldZone.height || 100, height: oldZone.height || 100,
x: oldZone.x || 0, x: oldZone.x || 0,
...@@ -248,45 +242,55 @@ function DragAndDropEditBlock(runtime, element, params) { ...@@ -248,45 +242,55 @@ function DragAndDropEditBlock(runtime, element, params) {
_fn.build.form.zone.zoneObjects.push(zoneObj); _fn.build.form.zone.zoneObjects.push(zoneObj);
// Add fields to zone position form // Add fields to zone form
$zoneNode = $(inputTemplate(zoneObj)); $zoneNode = $(_fn.tpl.zoneInput({
$zoneNode.data('index', num); zone: zoneObj,
$elements.zones.form.append($zoneNode); index: _fn.build.form.zone.totalZonesCreated++,
}));
_fn.build.$el.zones.form.append($zoneNode);
_fn.build.form.zone.enableDelete(); _fn.build.form.zone.enableDelete();
// Add zone div to target // Add zone div to target
_fn.build.form.zone.renderZonesPreview(); _fn.build.form.zone.renderZonesPreview();
}, },
generateUID: function() {
// Generate a unique ID for a new zone.
for (var i = 1; true; i++) {
var uid = "zone-" + i;
if (!_fn.build.form.zone.getZoneObjByUID(uid)) {
return uid;
}
}
},
remove: function(e) { remove: function(e) {
var $el = $(e.currentTarget).closest('.zone-row'), var $el = $(e.currentTarget).closest('.zone-row'),
classes = $el.attr('class'), classes = $el.attr('class'),
id = classes.slice(classes.indexOf('zone-row') + 9), id = classes.slice(classes.indexOf('zone-row') + 9),
index = $el.data('index'), uid = String($el.data('uid')), // cast to string since UID must be string but .data() converts data-uid="5" to 5
array_index; array_index;
e.preventDefault(); e.preventDefault();
$el.detach(); $el.detach();
// Find the index of the zone in the array and remove it. // Find the uid of the zone in the array and remove it.
for (array_index = 0; array_index < _fn.build.form.zone.zoneObjects.length; for (array_index = 0; array_index < _fn.build.form.zone.zoneObjects.length;
array_index++) { array_index++) {
if (_fn.build.form.zone.zoneObjects[array_index].index == index) break; if (_fn.build.form.zone.zoneObjects[array_index].uid == uid) break;
} }
_fn.build.form.zone.zoneObjects.splice(array_index, 1); _fn.build.form.zone.zoneObjects.splice(array_index, 1);
_fn.build.form.zone.renderZonesPreview(); _fn.build.form.zone.renderZonesPreview();
_fn.build.form.zone.formCount--;
_fn.build.form.zone.disableDelete(); _fn.build.form.zone.disableDelete();
}, },
enableDelete: function() { enableDelete: function() {
if (_fn.build.form.zone.formCount > 1) { if (_fn.build.form.zone.zoneObjects.length > 1) {
_fn.build.$el.zones.form.find('.remove-zone').removeClass('hidden'); _fn.build.$el.zones.form.find('.remove-zone').removeClass('hidden');
} }
}, },
disableDelete: function() { disableDelete: function() {
if (_fn.build.form.zone.formCount === 1) { if (_fn.build.form.zone.zoneObjects.length === 1) {
_fn.build.$el.zones.form.find('.remove-zone').addClass('hidden'); _fn.build.$el.zones.form.find('.remove-zone').addClass('hidden');
} }
}, },
...@@ -303,7 +307,7 @@ function DragAndDropEditBlock(runtime, element, params) { ...@@ -303,7 +307,7 @@ function DragAndDropEditBlock(runtime, element, params) {
this.zoneObjects.forEach(function(zoneObj) { this.zoneObjects.forEach(function(zoneObj) {
_fn.build.$el.zonesPreview.append( _fn.build.$el.zonesPreview.append(
_fn.tpl.zoneElement({ _fn.tpl.zoneElement({
id: zoneObj.id, uid: zoneObj.uid,
title: zoneObj.title, title: zoneObj.title,
description: zoneObj.description, description: zoneObj.description,
x_percent: (+zoneObj.x) / imgWidth * 100, x_percent: (+zoneObj.x) / imgWidth * 100,
...@@ -315,23 +319,11 @@ function DragAndDropEditBlock(runtime, element, params) { ...@@ -315,23 +319,11 @@ function DragAndDropEditBlock(runtime, element, params) {
); );
}); });
}, },
getZoneNames: function() {
var zoneNames = [];
var $form = _fn.build.$el.zones.form.find('.title');
$form.each(function(i, el) {
var val = $(el).val();
if (val.length > 0) {
zoneNames.push(val);
}
});
return zoneNames;
},
changedInputHandler: function(ev) { changedInputHandler: function(ev) {
// Called when any of the inputs have changed. // Called when any of the inputs have changed.
var $changedInput = $(ev.currentTarget); var $changedInput = $(ev.currentTarget);
var $row = $changedInput.closest('.zone-row'); var $row = $changedInput.closest('.zone-row');
var record = _fn.build.form.zone.getObjByIndex($row.data('index')); var record = _fn.build.form.zone.getZoneObjByUID(String($row.data('uid')));
if ($changedInput.hasClass('title')) { if ($changedInput.hasClass('title')) {
record.title = $changedInput.val(); record.title = $changedInput.val();
} else if ($changedInput.hasClass('width')) { } else if ($changedInput.hasClass('width')) {
...@@ -354,18 +346,26 @@ function DragAndDropEditBlock(runtime, element, params) { ...@@ -354,18 +346,26 @@ function DragAndDropEditBlock(runtime, element, params) {
_fn.build.form.zone.renderZonesPreview(); _fn.build.form.zone.renderZonesPreview();
}, },
}, },
createDropdown: function(selected) { createDropdown: function(selectedUID) {
var tpl = _fn.tpl.zoneDropdown, var template = _fn.tpl.zoneDropdown;
dropdown = [], var dropdown = [];
html, var zoneObjects = _fn.build.form.zone.zoneObjects;
dropdown_items = _fn.build.form.zone.getZoneNames().concat('none');
zoneObjects.forEach(function(zoneObj) {
dropdown.push(template({
uid: zoneObj.uid,
title: zoneObj.title,
selected: (zoneObj.uid == selectedUID) ? 'selected' : '',
}));
});
for (var i=0; i<dropdown_items.length; i++) { dropdown.push(template({
var is_sel = (dropdown_items[i] == selected) ? 'selected' : ''; uid: "none",
dropdown.push(tpl({ value: dropdown_items[i], selected: is_sel })); title: window.gettext("None"),
} selected: (selectedUID === "none") ? 'selected' : '',
}));
html = dropdown.join(''); var html = dropdown.join('');
return new Handlebars.SafeString(html); return new Handlebars.SafeString(html);
}, },
feedback: function($form) { feedback: function($form) {
......
{% load i18n %} {% load i18n %}
{% load l10n %}
<div class="xblock--drag-and-drop--editor editor-with-buttons"> <div class="xblock--drag-and-drop--editor editor-with-buttons">
{{ js_templates|safe }} {{ js_templates|safe }}
...@@ -21,7 +22,7 @@ ...@@ -21,7 +22,7 @@
</label> </label>
<label class="h3" for="weight">{% trans "Maximum score" %}</label> <label class="h3" for="weight">{% trans "Maximum score" %}</label>
<input id="weight" type="number" step="0.1" value="{{ self.weight }}" /> <input id="weight" type="number" step="0.1" value="{{ self.weight|unlocalize }}" />
<label class="h3" for="problem-text">{% trans "Problem text" %}</label> <label class="h3" for="problem-text">{% trans "Problem text" %}</label>
<textarea id="problem-text">{{ self.question_text }}</textarea> <textarea id="problem-text">{{ self.question_text }}</textarea>
......
<script id="zone-element-tpl" type="text/html"> <script id="zone-element-tpl" type="text/html">
<div id="{{ id }}" class="zone" data-zone="{{ title }}" style=" <div class="zone" data-zone="{{ uid }}" style="
top:{{ y_percent }}%; top:{{ y_percent }}%;
left:{{ x_percent }}%; left:{{ x_percent }}%;
width:{{ width_percent }}%; width:{{ width_percent }}%;
...@@ -10,12 +10,13 @@ ...@@ -10,12 +10,13 @@
</script> </script>
<script id="zone-input-tpl" type="text/html"> <script id="zone-input-tpl" type="text/html">
<div class="zone-row {{ id }}" data-index="{{index}}"> <div class="zone-row" data-uid="{{zone.uid}}">
<!-- uid values from old versions of the block may contain spaces and other characters, so we use 'index' as an alternate unique ID here. -->
<label for="zone-{{index}}-title">{{i18n "Text"}}</label> <label for="zone-{{index}}-title">{{i18n "Text"}}</label>
<input type="text" <input type="text"
id="zone-{{index}}-title" id="zone-{{index}}-title"
class="title" class="title"
value="{{ title }}" value="{{ zone.title }}"
required /> required />
<a href="#" class="remove-zone hidden"> <a href="#" class="remove-zone hidden">
<div class="icon remove"></div> <div class="icon remove"></div>
...@@ -24,7 +25,7 @@ ...@@ -24,7 +25,7 @@
<input type="text" <input type="text"
id="zone-{{index}}-description" id="zone-{{index}}-description"
class="description" class="description"
value="{{ description }}" value="{{ zone.description }}"
placeholder="{{i18n 'Describe this zone to non-visual users'}}" placeholder="{{i18n 'Describe this zone to non-visual users'}}"
required /> required />
<div class="layout"> <div class="layout">
...@@ -32,23 +33,23 @@ ...@@ -32,23 +33,23 @@
<input type="text" <input type="text"
id="zone-{{index}}-width" id="zone-{{index}}-width"
class="size width" class="size width"
value="{{ width }}" /> value="{{ zone.width }}" />
<label for="zone-{{index}}-height">{{i18n "height"}}</label> <label for="zone-{{index}}-height">{{i18n "height"}}</label>
<input type="text" <input type="text"
id="zone-{{index}}-height" id="zone-{{index}}-height"
class="size height" class="size height"
value="{{ height }}" /> value="{{ zone.height }}" />
<br /> <br />
<label for="zone-{{index}}-x">x</label> <label for="zone-{{index}}-x">x</label>
<input type="text" <input type="text"
id="zone-{{index}}-x" id="zone-{{index}}-x"
class="coord x" class="coord x"
value="{{ x }}" /> value="{{ zone.x }}" />
<label for="zone-{{index}}-y">y</label> <label for="zone-{{index}}-y">y</label>
<input type="text" <input type="text"
id="zone-{{index}}-y" id="zone-{{index}}-y"
class="coord y" class="coord y"
value="{{ y }}" /> value="{{ zone.y }}" />
</div> </div>
<div class="alignment"> <div class="alignment">
<label for="zone-{{index}}-align"> <label for="zone-{{index}}-align">
...@@ -82,7 +83,7 @@ ...@@ -82,7 +83,7 @@
</script> </script>
<script id="zone-dropdown-tpl" type="text/html"> <script id="zone-dropdown-tpl" type="text/html">
<option value="{{ value }}" {{ selected }}>{{ value }}</option> <option value="{{ uid }}" {{ selected }}>{{ title }}</option>
</script> </script>
<script id="item-input-tpl" type="text/html"> <script id="item-input-tpl" type="text/html">
......
...@@ -11,6 +11,7 @@ disable= ...@@ -11,6 +11,7 @@ disable=
missing-docstring, missing-docstring,
too-many-ancestors, too-many-ancestors,
too-many-arguments, too-many-arguments,
too-many-branches,
too-many-instance-attributes, too-many-instance-attributes,
too-few-public-methods, too-few-public-methods,
too-many-public-methods, too-many-public-methods,
......
{ {
"zones": [ "zones": [
{ {
"index": 1,
"width": 200, "width": 200,
"title": "Zone 1", "title": "Zone 1",
"height": 100, "height": 100,
"y": "200", "y": "200",
"x": "100", "x": "100",
"id": "zone-1" "uid": "zone-1"
}, },
{ {
"index": 2,
"width": 200, "width": 200,
"title": "Zone 2", "title": "Zone 2",
"height": 100, "height": 100,
"y": 0, "y": 0,
"x": 0, "x": 0,
"id": "zone-2" "uid": "zone-2"
} }
], ],
"items": [ "items": [
...@@ -26,7 +24,7 @@ ...@@ -26,7 +24,7 @@
"incorrect": "No 1", "incorrect": "No 1",
"correct": "Yes 1" "correct": "Yes 1"
}, },
"zone": "Zone 1", "zone": "zone-1",
"imageURL": "", "imageURL": "",
"id": 0 "id": 0
}, },
...@@ -36,7 +34,7 @@ ...@@ -36,7 +34,7 @@
"incorrect": "No 2", "incorrect": "No 2",
"correct": "Yes 2" "correct": "Yes 2"
}, },
"zone": "Zone 2", "zone": "zone-2",
"imageURL": "", "imageURL": "",
"id": 1, "id": 1,
"inputOptions": { "inputOptions": {
......
{ {
"zones": [ "zones": [
{ {
"index": 1,
"title": "Zone 1", "title": "Zone 1",
"description": "This describes zone 1", "description": "This describes zone 1",
"height": 178, "height": 178,
"width": 196, "width": 196,
"y": "30", "y": "30",
"x": "160", "x": "160",
"id": "zone-1" "id": "the deprecated id attribute is ignored."
}, },
{ {
"index": 2,
"title": "Zone 2", "title": "Zone 2",
"description": "This describes zone 2", "description": "This describes zone 2",
"height": 140, "height": 140,
"width": 340, "width": 340,
"y": "210", "y": "210",
"x": "86", "x": "86",
"id": "zone-2"
} }
], ],
"items": [ "items": [
......
{ {
"zones": [ "zones": [
{ {
"index": 1,
"width": 200, "width": 200,
"title": "Zone 51", "title": "Zone 51",
"height": 100, "height": 100,
"y": "400", "y": "400",
"x": "200", "x": "200",
"id": "zone-51" "uid": "zone-51"
}, },
{ {
"index": 2,
"width": 200, "width": 200,
"title": "Zone 52", "title": "Zone 52",
"height": 100, "height": 100,
"y": "200", "y": "200",
"x": "100", "x": "100",
"id": "zone-52" "uid": "zone-52"
} }
], ],
"items": [ "items": [
...@@ -26,7 +24,7 @@ ...@@ -26,7 +24,7 @@
"incorrect": "Incorrect 1", "incorrect": "Incorrect 1",
"correct": "Correct 1" "correct": "Correct 1"
}, },
"zone": "Zone 51", "zone": "zone-51",
"imageURL": "", "imageURL": "",
"id": 10 "id": 10
}, },
...@@ -36,7 +34,7 @@ ...@@ -36,7 +34,7 @@
"incorrect": "Incorrect 2", "incorrect": "Incorrect 2",
"correct": "Correct 2" "correct": "Correct 2"
}, },
"zone": "Zone 52", "zone": "zone-52",
"imageURL": "", "imageURL": "",
"id": 20, "id": 20,
"inputOptions": { "inputOptions": {
......
{ {
"zones": [ "zones": [
{ {
"index": 1,
"width": 200, "width": 200,
"title": "Zone <i>1</i>", "title": "Zone <i>1</i>",
"height": 100, "height": 100,
"y": 200, "y": 200,
"x": 100, "x": 100,
"id": "zone-1" "uid": "zone-1"
}, },
{ {
"index": 2,
"width": 200, "width": 200,
"title": "Zone <b>2</b>", "title": "Zone <b>2</b>",
"height": 100, "height": 100,
"y": 0, "y": 0,
"x": 0, "x": 0,
"id": "zone-2" "uid": "zone-2"
} }
], ],
"items": [ "items": [
...@@ -26,7 +24,7 @@ ...@@ -26,7 +24,7 @@
"incorrect": "No <b>1</b>", "incorrect": "No <b>1</b>",
"correct": "Yes <b>1</b>" "correct": "Yes <b>1</b>"
}, },
"zone": "Zone <i>1</i>", "zone": "zone-1",
"imageURL": "", "imageURL": "",
"id": 0 "id": 0
}, },
...@@ -36,7 +34,7 @@ ...@@ -36,7 +34,7 @@
"incorrect": "No <i>2</i>", "incorrect": "No <i>2</i>",
"correct": "Yes <i>2</i>" "correct": "Yes <i>2</i>"
}, },
"zone": "Zone <b>2</b>", "zone": "zone-2",
"imageURL": "", "imageURL": "",
"id": 1, "id": 1,
"inputOptions": { "inputOptions": {
......
...@@ -2,16 +2,16 @@ ...@@ -2,16 +2,16 @@
{% if img == "wide" %} {% if img == "wide" %}
"targetImg": "{{img_wide_url}}", "targetImg": "{{img_wide_url}}",
"zones": [ "zones": [
{"index": 1, "title": "Zone 1/3", "width": 533, "height": 200, "x": "0", "y": "0", "id": "zone-1"}, {"title": "Zone 1/3", "width": 533, "height": 200, "x": "0", "y": "0"},
{"index": 2, "title": "Zone 50%", "width": 800, "height": 200, "x": "0", "y": "350", "id": "zone-2"}, {"title": "Zone 50%", "width": 800, "height": 200, "x": "0", "y": "350"},
{"index": 3, "title": "Zone 75%", "width": 1200, "height": 200, "x": "0", "y": "700", "id": "zone-3"} {"title": "Zone 75%", "width": 1200, "height": 200, "x": "0", "y": "700"}
], ],
{% else %} {% else %}
"targetImg": "{{img_square_url}}", "targetImg": "{{img_square_url}}",
"zones": [ "zones": [
{"index": 1, "title": "Zone 1/3", "width": 166, "height": 100, "x": "0", "y": "0", "id": "zone-1"}, {"title": "Zone 1/3", "width": 166, "height": 100, "x": "0", "y": "0"},
{"index": 2, "title": "Zone 50%", "width": 250, "height": 100, "x": "0", "y": "200", "id": "zone-2"}, {"title": "Zone 50%", "width": 250, "height": 100, "x": "0", "y": "200"},
{"index": 3, "title": "Zone 75%", "width": 375, "height": 100, "x": "0", "y": "400", "id": "zone-3"} {"title": "Zone 75%", "width": 375, "height": 100, "x": "0", "y": "400"}
], ],
{% endif %} {% endif %}
"displayBorders": true, "displayBorders": true,
......
...@@ -11,6 +11,7 @@ from workbench.runtime import WorkbenchRuntime ...@@ -11,6 +11,7 @@ from workbench.runtime import WorkbenchRuntime
from xblockutils.resources import ResourceLoader from xblockutils.resources import ResourceLoader
from drag_and_drop_v2.default_data import ( from drag_and_drop_v2.default_data import (
TOP_ZONE_ID, MIDDLE_ZONE_ID, BOTTOM_ZONE_ID,
TOP_ZONE_TITLE, MIDDLE_ZONE_TITLE, BOTTOM_ZONE_TITLE, TOP_ZONE_TITLE, MIDDLE_ZONE_TITLE, BOTTOM_ZONE_TITLE,
ITEM_CORRECT_FEEDBACK, ITEM_INCORRECT_FEEDBACK, ITEM_NO_ZONE_FEEDBACK, ITEM_CORRECT_FEEDBACK, ITEM_INCORRECT_FEEDBACK, ITEM_NO_ZONE_FEEDBACK,
START_FEEDBACK, FINISH_FEEDBACK START_FEEDBACK, FINISH_FEEDBACK
...@@ -26,10 +27,11 @@ loader = ResourceLoader(__name__) ...@@ -26,10 +27,11 @@ loader = ResourceLoader(__name__)
# Classes ########################################################### # Classes ###########################################################
class ItemDefinition(object): class ItemDefinition(object):
def __init__(self, item_id, zone_id, feedback_positive, feedback_negative, input_value=None): def __init__(self, item_id, zone_id, zone_title, feedback_positive, feedback_negative, input_value=None):
self.feedback_negative = feedback_negative self.feedback_negative = feedback_negative
self.feedback_positive = feedback_positive self.feedback_positive = feedback_positive
self.zone_id = zone_id self.zone_id = zone_id
self.zone_title = zone_title
self.item_id = item_id self.item_id = item_id
self.input = input_value self.input = input_value
...@@ -73,7 +75,7 @@ class InteractionTestBase(object): ...@@ -73,7 +75,7 @@ class InteractionTestBase(object):
def _get_zone_by_id(self, zone_id): def _get_zone_by_id(self, zone_id):
zones_container = self._page.find_element_by_css_selector('.target') zones_container = self._page.find_element_by_css_selector('.target')
return zones_container.find_elements_by_xpath(".//div[@data-zone='{zone_id}']".format(zone_id=zone_id))[0] return zones_container.find_elements_by_xpath(".//div[@data-uid='{zone_id}']".format(zone_id=zone_id))[0]
def _get_input_div_by_value(self, item_value): def _get_input_div_by_value(self, item_value):
element = self._get_item_by_value(item_value) element = self._get_item_by_value(item_value)
...@@ -89,7 +91,7 @@ class InteractionTestBase(object): ...@@ -89,7 +91,7 @@ class InteractionTestBase(object):
def _get_zone_position(self, zone_id): def _get_zone_position(self, zone_id):
return self.browser.execute_script( return self.browser.execute_script(
'return $("div[data-zone=\'{zone_id}\']").prevAll(".zone").length'.format(zone_id=zone_id) 'return $("div[data-uid=\'{zone_id}\']").prevAll(".zone").length'.format(zone_id=zone_id)
) )
def place_item(self, item_value, zone_id, action_key=None): def place_item(self, item_value, zone_id, action_key=None):
...@@ -130,7 +132,7 @@ class InteractionTestBase(object): ...@@ -130,7 +132,7 @@ class InteractionTestBase(object):
def assert_grabbed_item(self, item): def assert_grabbed_item(self, item):
self.assertEqual(item.get_attribute('aria-grabbed'), 'true') self.assertEqual(item.get_attribute('aria-grabbed'), 'true')
def assert_placed_item(self, item_value, zone_id): def assert_placed_item(self, item_value, zone_title):
item = self._get_placed_item_by_value(item_value) item = self._get_placed_item_by_value(item_value)
self.wait_until_visible(item) self.wait_until_visible(item)
item_content = item.find_element_by_css_selector('.item-content') item_content = item.find_element_by_css_selector('.item-content')
...@@ -144,7 +146,7 @@ class InteractionTestBase(object): ...@@ -144,7 +146,7 @@ class InteractionTestBase(object):
self.assertEqual(item.get_attribute('data-drag-disabled'), 'true') self.assertEqual(item.get_attribute('data-drag-disabled'), 'true')
self.assertEqual(item_content.get_attribute('aria-describedby'), item_description_id) self.assertEqual(item_content.get_attribute('aria-describedby'), item_description_id)
self.assertEqual(item_description.get_attribute('id'), item_description_id) self.assertEqual(item_description.get_attribute('id'), item_description_id)
self.assertEqual(item_description.text, 'Correctly placed in: {}'.format(zone_id)) self.assertEqual(item_description.text, 'Correctly placed in: {}'.format(zone_title))
def assert_reverted_item(self, item_value): def assert_reverted_item(self, item_value):
item = self._get_item_by_value(item_value) item = self._get_item_by_value(item_value)
...@@ -186,7 +188,7 @@ class InteractionTestBase(object): ...@@ -186,7 +188,7 @@ class InteractionTestBase(object):
self.place_item(definition.item_id, definition.zone_id, action_key) self.place_item(definition.item_id, definition.zone_id, action_key)
self.wait_until_html_in(definition.feedback_positive, feedback_popup_content) self.wait_until_html_in(definition.feedback_positive, feedback_popup_content)
self.assertEqual(popup.get_attribute('class'), 'popup') self.assertEqual(popup.get_attribute('class'), 'popup')
self.assert_placed_item(definition.item_id, definition.zone_id) self.assert_placed_item(definition.item_id, definition.zone_title)
def parameterized_item_positive_feedback_on_good_input(self, items_map, scroll_down=100, action_key=None): def parameterized_item_positive_feedback_on_good_input(self, items_map, scroll_down=100, action_key=None):
popup = self._get_popup() popup = self._get_popup()
...@@ -201,7 +203,7 @@ class InteractionTestBase(object): ...@@ -201,7 +203,7 @@ class InteractionTestBase(object):
self.send_input(definition.item_id, definition.input) self.send_input(definition.item_id, definition.input)
self.wait_until_html_in(definition.feedback_positive, feedback_popup_content) self.wait_until_html_in(definition.feedback_positive, feedback_popup_content)
self.assertEqual(popup.get_attribute('class'), 'popup') self.assertEqual(popup.get_attribute('class'), 'popup')
self.assert_placed_item(definition.item_id, definition.zone_id) self.assert_placed_item(definition.item_id, definition.zone_title)
input_div = self._get_input_div_by_value(definition.item_id) input_div = self._get_input_div_by_value(definition.item_id)
self.wait_until_has_class('correct', input_div) self.wait_until_has_class('correct', input_div)
...@@ -234,7 +236,7 @@ class InteractionTestBase(object): ...@@ -234,7 +236,7 @@ class InteractionTestBase(object):
self.send_input(definition.item_id, '1999999') self.send_input(definition.item_id, '1999999')
self.wait_until_html_in(definition.feedback_negative, feedback_popup_content) self.wait_until_html_in(definition.feedback_negative, feedback_popup_content)
self.assertEqual(popup.get_attribute('class'), 'popup popup-incorrect') self.assertEqual(popup.get_attribute('class'), 'popup popup-incorrect')
self.assert_placed_item(definition.item_id, definition.zone_id) self.assert_placed_item(definition.item_id, definition.zone_title)
input_div = self._get_input_div_by_value(definition.item_id) input_div = self._get_input_div_by_value(definition.item_id)
self.wait_until_has_class('incorrect', input_div) self.wait_until_has_class('incorrect', input_div)
...@@ -258,7 +260,7 @@ class InteractionTestBase(object): ...@@ -258,7 +260,7 @@ class InteractionTestBase(object):
self.send_input(item_key, definition.input) self.send_input(item_key, definition.input)
input_div = self._get_input_div_by_value(item_key) input_div = self._get_input_div_by_value(item_key)
self.wait_until_has_class('correct', input_div) self.wait_until_has_class('correct', input_div)
self.assert_placed_item(definition.item_id, definition.zone_id) self.assert_placed_item(definition.item_id, definition.zone_title)
self.wait_until_html_in(feedback['final'], self._get_feedback_message()) self.wait_until_html_in(feedback['final'], self._get_feedback_message())
...@@ -332,18 +334,21 @@ class DefaultDataTestMixin(object): ...@@ -332,18 +334,21 @@ class DefaultDataTestMixin(object):
items_map = { items_map = {
0: ItemDefinition( 0: ItemDefinition(
0, TOP_ZONE_TITLE, ITEM_CORRECT_FEEDBACK.format(zone=TOP_ZONE_TITLE), ITEM_INCORRECT_FEEDBACK 0, TOP_ZONE_ID, TOP_ZONE_TITLE,
ITEM_CORRECT_FEEDBACK.format(zone=TOP_ZONE_TITLE), ITEM_INCORRECT_FEEDBACK
), ),
1: ItemDefinition( 1: ItemDefinition(
1, MIDDLE_ZONE_TITLE, ITEM_CORRECT_FEEDBACK.format(zone=MIDDLE_ZONE_TITLE), ITEM_INCORRECT_FEEDBACK 1, MIDDLE_ZONE_ID, MIDDLE_ZONE_TITLE,
ITEM_CORRECT_FEEDBACK.format(zone=MIDDLE_ZONE_TITLE), ITEM_INCORRECT_FEEDBACK
), ),
2: ItemDefinition( 2: ItemDefinition(
2, BOTTOM_ZONE_TITLE, ITEM_CORRECT_FEEDBACK.format(zone=BOTTOM_ZONE_TITLE), ITEM_INCORRECT_FEEDBACK 2, BOTTOM_ZONE_ID, BOTTOM_ZONE_TITLE,
ITEM_CORRECT_FEEDBACK.format(zone=BOTTOM_ZONE_TITLE), ITEM_INCORRECT_FEEDBACK
), ),
3: ItemDefinition(3, None, "", ITEM_NO_ZONE_FEEDBACK), 3: ItemDefinition(3, None, None, "", ITEM_NO_ZONE_FEEDBACK),
} }
all_zones = [TOP_ZONE_TITLE, MIDDLE_ZONE_TITLE, BOTTOM_ZONE_TITLE] all_zones = [TOP_ZONE_ID, MIDDLE_ZONE_ID, BOTTOM_ZONE_ID]
feedback = { feedback = {
"intro": START_FEEDBACK, "intro": START_FEEDBACK,
...@@ -404,6 +409,7 @@ class EventsFiredTest(DefaultDataTestMixin, InteractionTestBase, BaseIntegration ...@@ -404,6 +409,7 @@ class EventsFiredTest(DefaultDataTestMixin, InteractionTestBase, BaseIntegration
'is_correct_location': True, 'is_correct_location': True,
'item_id': 0, 'item_id': 0,
'location': TOP_ZONE_TITLE, 'location': TOP_ZONE_TITLE,
'location_id': TOP_ZONE_ID,
}, },
}, },
{ {
...@@ -473,12 +479,12 @@ class KeyboardInteractionTest(BasicInteractionTest, BaseIntegrationTest): ...@@ -473,12 +479,12 @@ class KeyboardInteractionTest(BasicInteractionTest, BaseIntegrationTest):
class CustomDataInteractionTest(BasicInteractionTest, BaseIntegrationTest): class CustomDataInteractionTest(BasicInteractionTest, BaseIntegrationTest):
items_map = { items_map = {
0: ItemDefinition(0, 'Zone 1', "Yes 1", "No 1"), 0: ItemDefinition(0, 'zone-1', "Zone 1", "Yes 1", "No 1"),
1: ItemDefinition(1, 'Zone 2', "Yes 2", "No 2", "102"), 1: ItemDefinition(1, 'zone-2', "Zone 2", "Yes 2", "No 2", "102"),
2: ItemDefinition(2, None, "", "No Zone for this") 2: ItemDefinition(2, None, None, "", "No Zone for this")
} }
all_zones = ['Zone 1', 'Zone 2'] all_zones = ['zone-1', 'zone-2']
feedback = { feedback = {
"intro": "Some Intro Feed", "intro": "Some Intro Feed",
...@@ -491,12 +497,12 @@ class CustomDataInteractionTest(BasicInteractionTest, BaseIntegrationTest): ...@@ -491,12 +497,12 @@ class CustomDataInteractionTest(BasicInteractionTest, BaseIntegrationTest):
class CustomHtmlDataInteractionTest(BasicInteractionTest, BaseIntegrationTest): class CustomHtmlDataInteractionTest(BasicInteractionTest, BaseIntegrationTest):
items_map = { items_map = {
0: ItemDefinition(0, 'Zone <i>1</i>', "Yes <b>1</b>", "No <b>1</b>"), 0: ItemDefinition(0, 'zone-1', 'Zone <i>1</i>', "Yes <b>1</b>", "No <b>1</b>"),
1: ItemDefinition(1, 'Zone <b>2</b>', "Yes <i>2</i>", "No <i>2</i>", "95"), 1: ItemDefinition(1, 'zone-2', 'Zone <b>2</b>', "Yes <i>2</i>", "No <i>2</i>", "95"),
2: ItemDefinition(2, None, "", "No Zone for <i>X</i>") 2: ItemDefinition(2, None, None, "", "No Zone for <i>X</i>")
} }
all_zones = ['Zone <i>1</i>', 'Zone <b>2</b>'] all_zones = ['zone-1', 'zone-2']
feedback = { feedback = {
"intro": "Intro <i>Feed</i>", "intro": "Intro <i>Feed</i>",
...@@ -516,20 +522,20 @@ class MultipleBlocksDataInteraction(InteractionTestBase, BaseIntegrationTest): ...@@ -516,20 +522,20 @@ class MultipleBlocksDataInteraction(InteractionTestBase, BaseIntegrationTest):
item_maps = { item_maps = {
'block1': { 'block1': {
0: ItemDefinition(0, 'Zone 1', "Yes 1", "No 1"), 0: ItemDefinition(0, 'zone-1', 'Zone 1', "Yes 1", "No 1"),
1: ItemDefinition(1, 'Zone 2', "Yes 2", "No 2", "102"), 1: ItemDefinition(1, 'zone-2', 'Zone 2', "Yes 2", "No 2", "102"),
2: ItemDefinition(2, None, "", "No Zone for this") 2: ItemDefinition(2, None, None, "", "No Zone for this")
}, },
'block2': { 'block2': {
10: ItemDefinition(10, 'Zone 51', "Correct 1", "Incorrect 1"), 10: ItemDefinition(10, 'zone-51', 'Zone 51', "Correct 1", "Incorrect 1"),
20: ItemDefinition(20, 'Zone 52', "Correct 2", "Incorrect 2", "102"), 20: ItemDefinition(20, 'zone-52', 'Zone 52', "Correct 2", "Incorrect 2", "102"),
30: ItemDefinition(30, None, "", "No Zone for this") 30: ItemDefinition(30, None, None, "", "No Zone for this")
}, },
} }
all_zones = { all_zones = {
'block1': ['Zone 1', 'Zone 2'], 'block1': ['zone-1', 'zone-2'],
'block2': ['Zone 51', 'Zone 52'] 'block2': ['zone-51', 'zone-52']
} }
feedback = { feedback = {
......
...@@ -180,12 +180,12 @@ class TestDragAndDropRender(BaseIntegrationTest): ...@@ -180,12 +180,12 @@ class TestDragAndDropRender(BaseIntegrationTest):
self.assertEqual(zone.get_attribute('tabindex'), '0') self.assertEqual(zone.get_attribute('tabindex'), '0')
self.assertEqual(zone.get_attribute('dropzone'), 'move') self.assertEqual(zone.get_attribute('dropzone'), 'move')
self.assertEqual(zone.get_attribute('aria-dropeffect'), 'move') self.assertEqual(zone.get_attribute('aria-dropeffect'), 'move')
self.assertEqual(zone.get_attribute('data-zone'), 'Zone {}'.format(zone_number)) self.assertEqual(zone.get_attribute('data-uid'), 'Zone {}'.format(zone_number))
self.assertEqual(zone.get_attribute('data-zonealign'), 'none') self.assertEqual(zone.get_attribute('data-zonealign'), 'none')
self.assertIn('ui-droppable', self.get_element_classes(zone)) self.assertIn('ui-droppable', self.get_element_classes(zone))
zone_box_percentages = box_percentages[index] zone_box_percentages = box_percentages[index]
self._assert_box_percentages( # pylint: disable=star-args self._assert_box_percentages( # pylint: disable=star-args
'#-zone-{}'.format(zone_number), **zone_box_percentages '#-Zone_{}'.format(zone_number), **zone_box_percentages
) )
zone_name = zone.find_element_by_css_selector('p.zone-name') zone_name = zone.find_element_by_css_selector('p.zone-name')
self.assertEqual(zone_name.text, 'Zone {}'.format(zone_number)) self.assertEqual(zone_name.text, 'Zone {}'.format(zone_number))
...@@ -238,7 +238,7 @@ class TestDragAndDropRender(BaseIntegrationTest): ...@@ -238,7 +238,7 @@ class TestDragAndDropRender(BaseIntegrationTest):
self.load_scenario() self.load_scenario()
zones = self._get_zones() zones = self._get_zones()
for index, dummy in enumerate(zones, start=1): for index, dummy in enumerate(zones, start=1):
zone = '#-zone-{}'.format(index) zone = '#-Zone_{}'.format(index)
for side in self.SIDES: for side in self.SIDES:
self.assertEqual(self._get_style(zone, 'border{}Width'.format(side), True), '0px') self.assertEqual(self._get_style(zone, 'border{}Width'.format(side), True), '0px')
self.assertEqual(self._get_style(zone, 'border{}Style'.format(side), True), 'none') self.assertEqual(self._get_style(zone, 'border{}Style'.format(side), True), 'none')
...@@ -247,7 +247,7 @@ class TestDragAndDropRender(BaseIntegrationTest): ...@@ -247,7 +247,7 @@ class TestDragAndDropRender(BaseIntegrationTest):
self.load_scenario(zone_borders=True) self.load_scenario(zone_borders=True)
zones = self._get_zones() zones = self._get_zones()
for index, dummy in enumerate(zones, start=1): for index, dummy in enumerate(zones, start=1):
zone = '#-zone-{}'.format(index) zone = '#-Zone_{}'.format(index)
for side in self.SIDES: for side in self.SIDES:
self.assertEqual(self._get_style(zone, 'border{}Width'.format(side), True), '1px') self.assertEqual(self._get_style(zone, 'border{}Width'.format(side), True), '1px')
self.assertEqual(self._get_style(zone, 'border{}Style'.format(side), True), 'dotted') self.assertEqual(self._get_style(zone, 'border{}Style'.format(side), True), 'dotted')
......
...@@ -14,22 +14,20 @@ ...@@ -14,22 +14,20 @@
"zones": [ "zones": [
{ {
"index": 1,
"title": "Zone <i>1</i>", "title": "Zone <i>1</i>",
"x": 100, "x": 100,
"y": 200, "y": 200,
"width": 200, "width": 200,
"height": 100, "height": 100,
"id": "zone-1" "uid": "Zone <i>1</i>"
}, },
{ {
"index": 2,
"title": "Zone <b>2</b>", "title": "Zone <b>2</b>",
"x": 0, "x": 0,
"y": 0, "y": 0,
"width": 200, "width": 200,
"height": 100, "height": 100,
"id": "zone-2" "uid": "Zone <b>2</b>"
} }
], ],
......
...@@ -14,22 +14,20 @@ ...@@ -14,22 +14,20 @@
"zones": [ "zones": [
{ {
"index": 1,
"title": "Zone 1", "title": "Zone 1",
"x": "100", "x": "100",
"y": "200", "y": "200",
"width": 200, "width": 200,
"height": 100, "height": 100,
"id": "zone-1" "uid": "Zone 1"
}, },
{ {
"index": 2,
"title": "Zone 2", "title": "Zone 2",
"x": 0, "x": 0,
"y": 0, "y": 0,
"width": 200, "width": 200,
"height": 100, "height": 100,
"id": "zone-2" "uid": "Zone 2"
} }
], ],
......
...@@ -14,22 +14,20 @@ ...@@ -14,22 +14,20 @@
"zones": [ "zones": [
{ {
"index": 1,
"title": "Zone 1", "title": "Zone 1",
"y": 123, "y": 123,
"x": 234, "x": 234,
"width": 345, "width": 345,
"height": 456, "height": 456,
"id": "zone-1" "uid": "zone-1"
}, },
{ {
"index": 2,
"title": "Zone 2", "title": "Zone 2",
"y": 20, "y": 20,
"x": 10, "x": 10,
"width": 30, "width": 30,
"height": 40, "height": 40,
"id": "zone-2" "uid": "zone-2"
} }
], ],
......
{ {
"zones": [ "zones": [
{ {
"index": 1,
"title": "Zone 1", "title": "Zone 1",
"y": 123, "y": 123,
"x": 234, "x": 234,
"width": 345, "width": 345,
"height": 456, "height": 456,
"id": "zone-1" "uid": "zone-1"
}, },
{ {
"index": 2,
"title": "Zone 2", "title": "Zone 2",
"y": 20, "y": 20,
"x": 10, "x": 10,
"width": 30, "width": 30,
"height": 40, "height": 40,
"id": "zone-2" "uid": "zone-2"
} }
], ],
...@@ -28,7 +26,7 @@ ...@@ -28,7 +26,7 @@
"incorrect": "No 1", "incorrect": "No 1",
"correct": "Yes 1" "correct": "Yes 1"
}, },
"zone": "Zone 1", "zone": "zone-1",
"imageURL": "", "imageURL": "",
"id": 0 "id": 0
}, },
...@@ -38,7 +36,7 @@ ...@@ -38,7 +36,7 @@
"incorrect": "No 2", "incorrect": "No 2",
"correct": "Yes 2" "correct": "Yes 2"
}, },
"zone": "Zone 2", "zone": "zone-2",
"imageURL": "", "imageURL": "",
"id": 1, "id": 1,
"inputOptions": { "inputOptions": {
......
...@@ -248,8 +248,8 @@ class TestDragAndDropHtmlData(BaseDragAndDropAjaxFixture, unittest.TestCase): ...@@ -248,8 +248,8 @@ class TestDragAndDropHtmlData(BaseDragAndDropAjaxFixture, unittest.TestCase):
class TestDragAndDropPlainData(BaseDragAndDropAjaxFixture, unittest.TestCase): class TestDragAndDropPlainData(BaseDragAndDropAjaxFixture, unittest.TestCase):
FOLDER = "plain" FOLDER = "plain"
ZONE_1 = "Zone 1" ZONE_1 = "zone-1"
ZONE_2 = "Zone 2" ZONE_2 = "zone-2"
FEEDBACK = { FEEDBACK = {
0: {"correct": "Yes 1", "incorrect": "No 1"}, 0: {"correct": "Yes 1", "incorrect": "No 1"},
...@@ -266,3 +266,6 @@ class TestOldDataFormat(TestDragAndDropPlainData): ...@@ -266,3 +266,6 @@ class TestOldDataFormat(TestDragAndDropPlainData):
""" """
FOLDER = "old" FOLDER = "old"
FINAL_FEEDBACK = "Final Feed" FINAL_FEEDBACK = "Final Feed"
ZONE_1 = "Zone 1"
ZONE_2 = "Zone 2"
import unittest import unittest
from drag_and_drop_v2.default_data import ( from drag_and_drop_v2.default_data import (
TARGET_IMG_DESCRIPTION, TOP_ZONE_TITLE, MIDDLE_ZONE_TITLE, BOTTOM_ZONE_TITLE, TARGET_IMG_DESCRIPTION, TOP_ZONE_ID, MIDDLE_ZONE_ID, BOTTOM_ZONE_ID,
START_FEEDBACK, FINISH_FEEDBACK, DEFAULT_DATA START_FEEDBACK, FINISH_FEEDBACK, DEFAULT_DATA
) )
from ..utils import make_block, TestCaseMixin from ..utils import make_block, TestCaseMixin
...@@ -65,25 +65,25 @@ class BasicTests(TestCaseMixin, unittest.TestCase): ...@@ -65,25 +65,25 @@ class BasicTests(TestCaseMixin, unittest.TestCase):
assert_user_state_empty() assert_user_state_empty()
# Drag three items into the correct spot: # Drag three items into the correct spot:
data = {"val": 0, "zone": TOP_ZONE_TITLE, "x_percent": "33%", "y_percent": "11%"} data = {"val": 0, "zone": TOP_ZONE_ID, "x_percent": "33%", "y_percent": "11%"}
self.call_handler('do_attempt', data) self.call_handler('do_attempt', data)
data = {"val": 1, "zone": MIDDLE_ZONE_TITLE, "x_percent": "67%", "y_percent": "80%"} data = {"val": 1, "zone": MIDDLE_ZONE_ID, "x_percent": "67%", "y_percent": "80%"}
self.call_handler('do_attempt', data) self.call_handler('do_attempt', data)
data = {"val": 2, "zone": BOTTOM_ZONE_TITLE, "x_percent": "99%", "y_percent": "95%"} data = {"val": 2, "zone": BOTTOM_ZONE_ID, "x_percent": "99%", "y_percent": "95%"}
self.call_handler('do_attempt', data) self.call_handler('do_attempt', data)
# Check the result: # Check the result:
self.assertTrue(self.block.completed) self.assertTrue(self.block.completed)
self.assertEqual(self.block.item_state, { self.assertEqual(self.block.item_state, {
'0': {'x_percent': '33%', 'y_percent': '11%', 'zone': TOP_ZONE_TITLE}, '0': {'x_percent': '33%', 'y_percent': '11%', 'zone': TOP_ZONE_ID},
'1': {'x_percent': '67%', 'y_percent': '80%', 'zone': MIDDLE_ZONE_TITLE}, '1': {'x_percent': '67%', 'y_percent': '80%', 'zone': MIDDLE_ZONE_ID},
'2': {'x_percent': '99%', 'y_percent': '95%', 'zone': BOTTOM_ZONE_TITLE}, '2': {'x_percent': '99%', 'y_percent': '95%', 'zone': BOTTOM_ZONE_ID},
}) })
self.assertEqual(self.call_handler('get_user_state'), { self.assertEqual(self.call_handler('get_user_state'), {
'items': { 'items': {
'0': {'x_percent': '33%', 'y_percent': '11%', 'correct_input': True, 'zone': TOP_ZONE_TITLE}, '0': {'x_percent': '33%', 'y_percent': '11%', 'correct_input': True, 'zone': TOP_ZONE_ID},
'1': {'x_percent': '67%', 'y_percent': '80%', 'correct_input': True, 'zone': MIDDLE_ZONE_TITLE}, '1': {'x_percent': '67%', 'y_percent': '80%', 'correct_input': True, 'zone': MIDDLE_ZONE_ID},
'2': {'x_percent': '99%', 'y_percent': '95%', 'correct_input': True, 'zone': BOTTOM_ZONE_TITLE}, '2': {'x_percent': '99%', 'y_percent': '95%', 'correct_input': True, 'zone': BOTTOM_ZONE_ID},
}, },
'finished': True, 'finished': True,
'overall_feedback': FINISH_FEEDBACK, 'overall_feedback': FINISH_FEEDBACK,
......
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