Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
X
xblock-drag-and-drop-v2
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
OpenEdx
xblock-drag-and-drop-v2
Commits
6b211933
Commit
6b211933
authored
Aug 30, 2016
by
Matjaz Gregoric
Committed by
GitHub
Aug 30, 2016
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #98 from open-craft/mtyaka/legacy-item-state
Ensure old problems work on new version.
parents
e2600bc5
c67d91cd
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
58 additions
and
24 deletions
+58
-24
drag_and_drop_v2/drag_and_drop_v2.py
+30
-24
tests/unit/test_basics.py
+28
-0
No files found.
drag_and_drop_v2/drag_and_drop_v2.py
View file @
6b211933
...
@@ -638,25 +638,10 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin):
...
@@ -638,25 +638,10 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin):
def
_get_user_state
(
self
):
def
_get_user_state
(
self
):
""" Get all user-specific data, and any applicable feedback """
""" Get all user-specific data, and any applicable feedback """
item_state
=
self
.
_get_item_state
()
item_state
=
self
.
_get_item_state
()
for
item_id
,
item
in
item_state
.
iteritems
():
# In assessment mode, we do not want to leak the correctness info for individual items to the frontend,
# If information about zone is missing
# so we remove "correct" from all items when in assessment mode.
# (because problem was completed before a11y enhancements were implemented),
if
self
.
mode
==
self
.
ASSESSMENT_MODE
:
# deduce zone in which item is placed from definition:
for
item
in
item_state
.
values
():
if
item
.
get
(
'zone'
)
is
None
:
valid_zones
=
self
.
_get_item_zones
(
int
(
item_id
))
if
valid_zones
:
# If we get to this point, then the item was placed prior to support for
# multiple correct zones being added. As a result, it can only be correct
# on a single zone, and so we can trust that the item was placed on the
# zone with index 0.
item
[
'zone'
]
=
valid_zones
[
0
]
else
:
item
[
'zone'
]
=
'unknown'
# In assessment mode, if item is placed correctly and than the page is refreshed, "correct"
# will spill to the frontend, making item "disabled", thus allowing students to obtain answer by trial
# and error + refreshing the page. In order to avoid that, we remove "correct" from an item here
if
self
.
mode
==
self
.
ASSESSMENT_MODE
:
del
item
[
"correct"
]
del
item
[
"correct"
]
overall_feedback_msgs
,
__
=
self
.
_get_feedback
()
overall_feedback_msgs
,
__
=
self
.
_get_feedback
()
...
@@ -679,14 +664,35 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin):
...
@@ -679,14 +664,35 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin):
"""
"""
# IMPORTANT: this method should always return a COPY of self.item_state - it is called from get_user_state
# IMPORTANT: this method should always return a COPY of self.item_state - it is called from get_user_state
# handler and
manipulated there to hide correctness of items placed
# handler and
the data it returns is manipulated there to hide correctness of items placed.
state
=
{}
state
=
{}
for
item_id
,
item
in
self
.
item_state
.
iteritems
():
for
item_id
,
raw_item
in
self
.
item_state
.
iteritems
():
if
isinstance
(
item
,
dict
):
if
isinstance
(
raw_item
,
dict
):
state
[
item_id
]
=
item
.
copy
()
# items are manipulated in _get_user_state, so we protect actual data
# Items are manipulated in _get_user_state, so we protect actual data.
item
=
copy
.
deepcopy
(
raw_item
)
else
:
else
:
state
[
item_id
]
=
{
'top'
:
item
[
0
],
'left'
:
item
[
1
]}
item
=
{
'top'
:
raw_item
[
0
],
'left'
:
raw_item
[
1
]}
# If information about zone is missing
# (because problem was completed before a11y enhancements were implemented),
# deduce zone in which item is placed from definition:
if
item
.
get
(
'zone'
)
is
None
:
valid_zones
=
self
.
_get_item_zones
(
int
(
item_id
))
if
valid_zones
:
# If we get to this point, then the item was placed prior to support for
# multiple correct zones being added. As a result, it can only be correct
# on a single zone, and so we can trust that the item was placed on the
# zone with index 0.
item
[
'zone'
]
=
valid_zones
[
0
]
else
:
item
[
'zone'
]
=
'unknown'
# If correctness information is missing
# (because problem was completed before assessment mode was implemented),
# assume the item is in correct zone (in standard mode, only items placed
# into correct zone are stored in item state).
if
item
.
get
(
'correct'
)
is
None
:
item
[
'correct'
]
=
True
state
[
item_id
]
=
item
return
state
return
state
...
...
tests/unit/test_basics.py
View file @
6b211933
...
@@ -109,6 +109,34 @@ class BasicTests(TestCaseMixin, unittest.TestCase):
...
@@ -109,6 +109,34 @@ class BasicTests(TestCaseMixin, unittest.TestCase):
self
.
assertTrue
(
self
.
block
.
completed
)
self
.
assertTrue
(
self
.
block
.
completed
)
assert_user_state_empty
()
assert_user_state_empty
()
def
test_legacy_state_support
(
self
):
"""
The form of items stored in user item_state has changed several times.
This test makes sure that legacy forms are properly converted to compatible format.
"""
self
.
assertEqual
(
self
.
block
.
item_state
,
{})
self
.
assertEqual
(
self
.
call_handler
(
'get_user_state'
)[
'items'
],
{})
self
.
block
.
item_state
=
{
# Legacy tuple (top, left) representation.
'0'
:
[
60
,
20
],
# Legacy dict with absolute values and no correctness or zone info.
'1'
:
{
'top'
:
45
,
'left'
:
99
},
# Legacy dict with no correctness info.
'2'
:
{
'x_percent'
:
'99
%
'
,
'y_percent'
:
'95
%
'
,
'zone'
:
BOTTOM_ZONE_ID
},
# Current dict form.
'3'
:
{
'x_percent'
:
'67
%
'
,
'y_percent'
:
'80
%
'
,
'zone'
:
BOTTOM_ZONE_ID
,
'correct'
:
False
},
}
self
.
block
.
save
()
self
.
assertEqual
(
self
.
call_handler
(
'get_user_state'
)[
'items'
],
{
# Legacy top/left values are converted to x/y percentage on the client.
'0'
:
{
'top'
:
60
,
'left'
:
20
,
'correct'
:
True
,
'zone'
:
TOP_ZONE_ID
},
'1'
:
{
'top'
:
45
,
'left'
:
99
,
'correct'
:
True
,
'zone'
:
MIDDLE_ZONE_ID
},
'2'
:
{
'x_percent'
:
'99
%
'
,
'y_percent'
:
'95
%
'
,
'correct'
:
True
,
'zone'
:
BOTTOM_ZONE_ID
},
'3'
:
{
'x_percent'
:
'67
%
'
,
'y_percent'
:
'80
%
'
,
'correct'
:
False
,
"zone"
:
BOTTOM_ZONE_ID
},
})
def
test_studio_submit
(
self
):
def
test_studio_submit
(
self
):
body
=
{
body
=
{
'display_name'
:
"Test Drag & Drop"
,
'display_name'
:
"Test Drag & Drop"
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment