Commit 610ce88a by Tim Krones

Use different color for popups if last action was incorrect.

parent d20f5e6a
...@@ -248,7 +248,7 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin): ...@@ -248,7 +248,7 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin):
feedback = item['feedback']['correct'] feedback = item['feedback']['correct']
else: else:
is_correct = False is_correct = False
elif item['zone'] == attempt['zone']: # Student placed item in zone elif item['zone'] == attempt['zone']: # Student placed item in correct zone
is_correct_location = True is_correct_location = True
if 'inputOptions' in item: if 'inputOptions' in item:
# Input value will have to be provided for the item. # Input value will have to be provided for the item.
......
...@@ -277,6 +277,10 @@ ...@@ -277,6 +277,10 @@
z-index: 100; z-index: 100;
} }
.xblock--drag-and-drop .popup.popup-incorrect {
background-color: rgba(173, 13, 13, 0.8);
}
.xblock--drag-and-drop .popup .popup-content { .xblock--drag-and-drop .popup .popup-content {
color: #ffffff; color: #ffffff;
margin-left: 15px; margin-left: 15px;
......
...@@ -450,6 +450,7 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -450,6 +450,7 @@ 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_location;
if (data.correct_location) { if (data.correct_location) {
state.items[item_id].correct_input = Boolean(data.correct); state.items[item_id].correct_input = Boolean(data.correct);
state.items[item_id].submitting_location = false; state.items[item_id].submitting_location = false;
...@@ -489,6 +490,7 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -489,6 +490,7 @@ function DragAndDropBlock(runtime, element, configuration) {
var data = {val: item_id, input: input_value}; var data = {val: item_id, input: input_value};
$.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_input = false; state.items[item_id].submitting_input = false;
state.items[item_id].correct_input = data.correct; state.items[item_id].correct_input = data.correct;
state.feedback = data.feedback; state.feedback = data.feedback;
...@@ -612,6 +614,7 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -612,6 +614,7 @@ function DragAndDropBlock(runtime, element, configuration) {
zones: configuration.zones, zones: configuration.zones,
items: items, items: items,
// state - parts that can change: // state - parts that can change:
last_action_correct: state.last_action_correct,
popup_html: state.feedback || '', popup_html: state.feedback || '',
feedback_html: $.trim(state.overall_feedback), feedback_html: $.trim(state.overall_feedback),
display_reset_button: Object.keys(state.items).length > 0, display_reset_button: Object.keys(state.items).length > 0,
...@@ -633,7 +636,7 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -633,7 +636,7 @@ function DragAndDropBlock(runtime, element, configuration) {
item.widthPercent = parseInt(item.size.width) / bg_image_width * 100; item.widthPercent = parseInt(item.size.width) / bg_image_width * 100;
} }
} }
} };
/** /**
* migrateState: Apply any changes necessary to support the 'state' format used by older * migrateState: Apply any changes necessary to support the 'state' format used by older
......
...@@ -216,6 +216,10 @@ ...@@ -216,6 +216,10 @@
var mainTemplate = function(ctx) { var mainTemplate = function(ctx) {
var problemTitle = ctx.show_title ? h('h2.problem-header', {innerHTML: ctx.title_html}) : null; var problemTitle = ctx.show_title ? h('h2.problem-header', {innerHTML: ctx.title_html}) : null;
var problemHeader = ctx.show_problem_header ? h('h3.title1', gettext('Problem')) : null; var problemHeader = ctx.show_problem_header ? h('h3.title1', gettext('Problem')) : null;
var popupSelector = 'div.popup';
if (ctx.popup_html && !ctx.last_action_correct) {
popupSelector += '.popup-incorrect';
}
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);
...@@ -230,10 +234,10 @@ ...@@ -230,10 +234,10 @@
h('div.item-bank', renderCollection(itemTemplate, items_in_bank, ctx)), h('div.item-bank', renderCollection(itemTemplate, items_in_bank, ctx)),
h('div.target', [ h('div.target', [
h( h(
'div.popup', popupSelector,
{ {
attributes: {'aria-live': 'polite'},
style: {display: ctx.popup_html ? 'block' : 'none'}, style: {display: ctx.popup_html ? 'block' : 'none'},
attributes: {'aria-live': 'polite'}
}, },
[ [
h('div.close.icon-remove-sign.fa-times-circle'), h('div.close.icon-remove-sign.fa-times-circle'),
......
...@@ -169,29 +169,38 @@ class InteractionTestBase(object): ...@@ -169,29 +169,38 @@ class InteractionTestBase(object):
self.assertEqual(item.get_attribute('data-drag-disabled'), 'true') self.assertEqual(item.get_attribute('data-drag-disabled'), 'true')
def parameterized_item_positive_feedback_on_good_move(self, items_map, scroll_down=100, action_key=None): def parameterized_item_positive_feedback_on_good_move(self, items_map, scroll_down=100, action_key=None):
popup = self._get_popup()
feedback_popup_content = self._get_popup_content()
# Scroll drop zones into view to make sure Selenium can successfully drop items # Scroll drop zones into view to make sure Selenium can successfully drop items
self.scroll_down(pixels=scroll_down) self.scroll_down(pixels=scroll_down)
for definition in self._get_items_with_zone(items_map).values(): for definition in self._get_items_with_zone(items_map).values():
if not definition.input: if not definition.input:
self.place_item(definition.item_id, definition.zone_id, action_key) self.place_item(definition.item_id, definition.zone_id, action_key)
feedback_popup_content = self._get_popup_content()
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.assert_placed_item(definition.item_id, definition.zone_id) self.assert_placed_item(definition.item_id, definition.zone_id)
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):
self.scroll_down(pixels=scroll_down) popup = self._get_popup()
feedback_popup_content = self._get_popup_content() feedback_popup_content = self._get_popup_content()
# Scroll drop zones into view to make sure Selenium can successfully drop items
self.scroll_down(pixels=scroll_down)
for definition in self._get_items_with_zone(items_map).values(): for definition in self._get_items_with_zone(items_map).values():
if definition.input: if definition.input:
self.place_item(definition.item_id, definition.zone_id, action_key) self.place_item(definition.item_id, definition.zone_id, action_key)
self.send_input(definition.item_id, definition.input) self.send_input(definition.item_id, definition.input)
input_div = self._get_input_div_by_value(definition.item_id)
self.wait_until_has_class('correct', input_div)
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.assert_placed_item(definition.item_id, definition.zone_id) self.assert_placed_item(definition.item_id, definition.zone_id)
input_div = self._get_input_div_by_value(definition.item_id)
self.wait_until_has_class('correct', input_div)
def parameterized_item_negative_feedback_on_bad_move(self, items_map, all_zones, scroll_down=100, action_key=None): def parameterized_item_negative_feedback_on_bad_move(self, items_map, all_zones, scroll_down=100, action_key=None):
popup = self._get_popup()
feedback_popup_content = self._get_popup_content() feedback_popup_content = self._get_popup_content()
# Scroll drop zones into view to make sure Selenium can successfully drop items # Scroll drop zones into view to make sure Selenium can successfully drop items
...@@ -203,9 +212,11 @@ class InteractionTestBase(object): ...@@ -203,9 +212,11 @@ class InteractionTestBase(object):
continue continue
self.place_item(definition.item_id, zone, action_key) self.place_item(definition.item_id, zone, action_key)
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.assert_reverted_item(definition.item_id) self.assert_reverted_item(definition.item_id)
def parameterized_item_negative_feedback_on_bad_input(self, items_map, scroll_down=100, action_key=None): def parameterized_item_negative_feedback_on_bad_input(self, items_map, scroll_down=100, action_key=None):
popup = self._get_popup()
feedback_popup_content = self._get_popup_content() feedback_popup_content = self._get_popup_content()
# Scroll drop zones into view to make sure Selenium can successfully drop items # Scroll drop zones into view to make sure Selenium can successfully drop items
...@@ -215,10 +226,11 @@ class InteractionTestBase(object): ...@@ -215,10 +226,11 @@ class InteractionTestBase(object):
if definition.input: if definition.input:
self.place_item(definition.item_id, definition.zone_id, action_key) self.place_item(definition.item_id, definition.zone_id, action_key)
self.send_input(definition.item_id, '1999999') self.send_input(definition.item_id, '1999999')
input_div = self._get_input_div_by_value(definition.item_id)
self.wait_until_has_class('incorrect', input_div)
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.assert_placed_item(definition.item_id, definition.zone_id) self.assert_placed_item(definition.item_id, definition.zone_id)
input_div = self._get_input_div_by_value(definition.item_id)
self.wait_until_has_class('incorrect', input_div)
def parameterized_final_feedback_and_reset(self, items_map, feedback, scroll_down=100, action_key=None): def parameterized_final_feedback_and_reset(self, items_map, feedback, scroll_down=100, action_key=None):
feedback_message = self._get_feedback_message() feedback_message = self._get_feedback_message()
......
...@@ -200,6 +200,7 @@ class TestDragAndDropRender(BaseIntegrationTest): ...@@ -200,6 +200,7 @@ class TestDragAndDropRender(BaseIntegrationTest):
popup = self._get_popup() popup = self._get_popup()
popup_content = self._get_popup_content() popup_content = self._get_popup_content()
self.assertFalse(popup.is_displayed()) self.assertFalse(popup.is_displayed())
self.assertEqual(popup.get_attribute('class'), 'popup')
self.assertEqual(popup.get_attribute('aria-live'), 'polite') self.assertEqual(popup.get_attribute('aria-live'), 'polite')
self.assertEqual(popup_content.text, "") self.assertEqual(popup_content.text, "")
......
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