Skip to content

Commit 48754a9

Browse files
authored
Merge pull request #219 from edx-solutions/dsheraz/educator-4521
use submission deadline methods to add subsection due check in DnD
2 parents 24e094e + 5624882 commit 48754a9

File tree

10 files changed

+56
-3
lines changed

10 files changed

+56
-3
lines changed

Changelog.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
Drag and Drop XBlock changelog
22
==============================
33

4+
Version 2.2.4 (2019-07-30)
5+
---------------------------
6+
7+
* Use InheritanceMixin for submission deadline checks (PR #219)
8+
* Submit button behavior will change in Assessment Mode and will now be impacted by subsection due date, grace period and course pacing
9+
410
Version 2.2.3 (2019-04-05)
511
---------------------------
612

drag_and_drop_v2/drag_and_drop_v2.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,7 @@ def items_without_answers():
355355
"target_img_description": self.target_img_description,
356356
"item_background_color": self.item_background_color or None,
357357
"item_text_color": self.item_text_color or None,
358+
"has_deadline_passed": self.has_submission_deadline_passed,
358359
# final feedback (data.feedback.finish) is not included - it may give away answers.
359360
}
360361

@@ -624,6 +625,22 @@ def attempts_remain(self):
624625
"""
625626
return self.max_attempts is None or self.max_attempts == 0 or self.attempts < self.max_attempts
626627

628+
@property
629+
def has_submission_deadline_passed(self):
630+
"""
631+
Returns a boolean indicating if the submission is past its deadline.
632+
633+
Using the `has_deadline_passed` method from InheritanceMixin which gets
634+
added on the LMS/Studio, return if the submission is past its due date.
635+
If the method not found, which happens for pure DragAndDropXblock,
636+
return False which makes sure submission checks don't affect other
637+
functionality.
638+
"""
639+
if hasattr(self, "has_deadline_passed"):
640+
return self.has_deadline_passed() # pylint: disable=no-member
641+
else:
642+
return False
643+
627644
@XBlock.handler
628645
def student_view_user_state(self, request, suffix=''):
629646
""" GET all user-specific data, and any applicable feedback """
@@ -645,6 +662,11 @@ def _validate_do_attempt(self):
645662
409,
646663
self.i18n_service.gettext("Max number of attempts reached")
647664
)
665+
if self.has_submission_deadline_passed:
666+
raise JsonHandlerError(
667+
409,
668+
self.i18n_service.gettext("Submission deadline has passed.")
669+
)
648670

649671
def _get_feedback(self, include_item_feedback=False):
650672
"""

drag_and_drop_v2/public/js/drag_and_drop.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1827,7 +1827,7 @@ function DragAndDropBlock(runtime, element, configuration) {
18271827
};
18281828

18291829
var canSubmitAttempt = function() {
1830-
return Object.keys(state.items).length > 0 && attemptsRemain() && !submittingLocation();
1830+
return Object.keys(state.items).length > 0 && isPastDue() && attemptsRemain() && !submittingLocation();
18311831
};
18321832

18331833
var canReset = function() {
@@ -1846,6 +1846,10 @@ function DragAndDropBlock(runtime, element, configuration) {
18461846
return any_items_placed && (configuration.mode !== DragAndDropBlock.ASSESSMENT_MODE || attemptsRemain());
18471847
};
18481848

1849+
var isPastDue = function () {
1850+
return !configuration.has_deadline_passed;
1851+
};
1852+
18491853
var canShowAnswer = function() {
18501854
return configuration.mode === DragAndDropBlock.ASSESSMENT_MODE && !attemptsRemain();
18511855
};

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def package_data(pkg, root_list):
2323

2424
setup(
2525
name='xblock-drag-and-drop-v2',
26-
version='2.2.3',
26+
version='2.2.4',
2727
description='XBlock - Drag-and-Drop v2',
2828
packages=['drag_and_drop_v2'],
2929
install_requires=[

tests/unit/data/assessment/config_out.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"display_zone_labels": false,
2020
"url_name": "test",
2121
"max_items_per_zone": null,
22+
"has_deadline_passed": false,
2223

2324
"zones": [
2425
{

tests/unit/data/html/config_out.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"display_zone_labels": false,
2020
"url_name": "unique_name",
2121
"max_items_per_zone": null,
22-
22+
"has_deadline_passed": false,
2323
"zones": [
2424
{
2525
"title": "Zone <i>1</i>",

tests/unit/data/old/config_out.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"display_zone_labels": false,
2020
"url_name": "",
2121
"max_items_per_zone": null,
22+
"has_deadline_passed": false,
2223

2324
"zones": [
2425
{

tests/unit/data/plain/config_out.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"display_zone_labels": false,
2020
"url_name": "test",
2121
"max_items_per_zone": 4,
22+
"has_deadline_passed": false,
2223

2324
"zones": [
2425
{

tests/unit/test_advanced.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,23 @@ def test_do_attempt_raises_number_of_attempts(self, attempts):
398398
self.assertEqual(self.block.attempts, attempts + 1)
399399
self.assertEqual(res['attempts'], self.block.attempts)
400400

401+
@ddt.data(
402+
(True, 409, True),
403+
(False, 200, False),
404+
)
405+
@ddt.unpack
406+
@mock.patch('drag_and_drop_v2.DragAndDropBlock.has_submission_deadline_passed', new_callable=mock.PropertyMock)
407+
def test_do_attempt_has_deadline_passed(self, is_past_deadline, status_code, expect_error, mock_deadline_passed):
408+
"""
409+
Scenario: If the submission is past its deadline date, the attempt is not possible and
410+
409 Conflict error is thrown.
411+
"""
412+
mock_deadline_passed.return_value = is_past_deadline
413+
response = self.call_handler(self.DO_ATTEMPT_HANDLER, data={}, expect_json=False)
414+
self.assertEqual(response.status_code, status_code)
415+
if expect_error:
416+
self.assertIn("Submission deadline has passed.", response.body)
417+
401418
@ddt.data(*[random.randint(1, 50) for _ in xrange(5)]) # pylint: disable=star-args
402419
def test_do_attempt_correct_mark_complete_and_publish_grade(self, weight):
403420
self.block.weight = weight

tests/unit/test_basics.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ def test_student_view_data(self):
7777
"item_background_color": None,
7878
"item_text_color": None,
7979
"url_name": "",
80+
"has_deadline_passed": False,
8081
})
8182
self.assertEqual(zones, DEFAULT_DATA["zones"])
8283
# Items should contain no answer data:

0 commit comments

Comments
 (0)