Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
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
edx
edx-platform
Commits
2930e29a
Commit
2930e29a
authored
Sep 08, 2014
by
Nimisha Asthagiri
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
LMS-11373 Fix Studio drag and drop race condition.
parent
7637f063
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
94 additions
and
59 deletions
+94
-59
cms/djangoapps/contentstore/views/item.py
+0
-0
cms/djangoapps/contentstore/views/tests/test_item.py
+81
-43
cms/static/js/spec/utils/drag_and_drop_spec.js
+2
-5
cms/static/js/utils/drag_and_drop.js
+11
-11
No files found.
cms/djangoapps/contentstore/views/item.py
View file @
2930e29a
This diff is collapsed.
Click to expand it.
cms/djangoapps/contentstore/views/tests/test_item.py
View file @
2930e29a
...
@@ -480,10 +480,16 @@ class TestEditItem(ItemTest):
...
@@ -480,10 +480,16 @@ class TestEditItem(ItemTest):
display_name
=
'chapter created'
display_name
=
'chapter created'
resp
=
self
.
create_xblock
(
display_name
=
display_name
,
category
=
'chapter'
)
resp
=
self
.
create_xblock
(
display_name
=
display_name
,
category
=
'chapter'
)
chap_usage_key
=
self
.
response_usage_key
(
resp
)
chap_usage_key
=
self
.
response_usage_key
(
resp
)
# create 2 sequentials
resp
=
self
.
create_xblock
(
parent_usage_key
=
chap_usage_key
,
category
=
'sequential'
)
resp
=
self
.
create_xblock
(
parent_usage_key
=
chap_usage_key
,
category
=
'sequential'
)
self
.
seq_usage_key
=
self
.
response_usage_key
(
resp
)
self
.
seq_usage_key
=
self
.
response_usage_key
(
resp
)
self
.
seq_update_url
=
reverse_usage_url
(
"xblock_handler"
,
self
.
seq_usage_key
)
self
.
seq_update_url
=
reverse_usage_url
(
"xblock_handler"
,
self
.
seq_usage_key
)
resp
=
self
.
create_xblock
(
parent_usage_key
=
chap_usage_key
,
category
=
'sequential'
)
self
.
seq2_usage_key
=
self
.
response_usage_key
(
resp
)
self
.
seq2_update_url
=
reverse_usage_url
(
"xblock_handler"
,
self
.
seq2_usage_key
)
# create problem w/ boilerplate
# create problem w/ boilerplate
template_id
=
'multiplechoice.yaml'
template_id
=
'multiplechoice.yaml'
resp
=
self
.
create_xblock
(
parent_usage_key
=
self
.
seq_usage_key
,
category
=
'problem'
,
boilerplate
=
template_id
)
resp
=
self
.
create_xblock
(
parent_usage_key
=
self
.
seq_usage_key
,
category
=
'problem'
,
boilerplate
=
template_id
)
...
@@ -557,11 +563,8 @@ class TestEditItem(ItemTest):
...
@@ -557,11 +563,8 @@ class TestEditItem(ItemTest):
self
.
assertIn
(
chapter2_usage_key
,
course
.
children
)
self
.
assertIn
(
chapter2_usage_key
,
course
.
children
)
# Remove one child from the course.
# Remove one child from the course.
resp
=
self
.
client
.
ajax_post
(
resp
=
self
.
client
.
delete
(
reverse_usage_url
(
"xblock_handler"
,
chapter1_usage_key
))
self
.
course_update_url
,
self
.
assertEqual
(
resp
.
status_code
,
204
)
data
=
{
'children'
:
[
unicode
(
chapter2_usage_key
)]}
)
self
.
assertEqual
(
resp
.
status_code
,
200
)
# Verify that the child is removed.
# Verify that the child is removed.
course
=
self
.
get_item_from_modulestore
(
self
.
usage_key
)
course
=
self
.
get_item_from_modulestore
(
self
.
usage_key
)
...
@@ -597,6 +600,79 @@ class TestEditItem(ItemTest):
...
@@ -597,6 +600,79 @@ class TestEditItem(ItemTest):
self
.
assertEqual
(
unit1_usage_key
,
children
[
2
])
self
.
assertEqual
(
unit1_usage_key
,
children
[
2
])
self
.
assertEqual
(
unit2_usage_key
,
children
[
1
])
self
.
assertEqual
(
unit2_usage_key
,
children
[
1
])
def
test_move_parented_child
(
self
):
"""
Test moving a child from one Section to another
"""
unit_1_key
=
self
.
response_usage_key
(
self
.
create_xblock
(
parent_usage_key
=
self
.
seq_usage_key
,
category
=
'vertical'
,
display_name
=
'unit 1'
)
)
unit_2_key
=
self
.
response_usage_key
(
self
.
create_xblock
(
parent_usage_key
=
self
.
seq2_usage_key
,
category
=
'vertical'
,
display_name
=
'unit 2'
)
)
# move unit 1 from sequential1 to sequential2
resp
=
self
.
client
.
ajax_post
(
self
.
seq2_update_url
,
data
=
{
'children'
:
[
unicode
(
unit_1_key
),
unicode
(
unit_2_key
)]}
)
self
.
assertEqual
(
resp
.
status_code
,
200
)
# verify children
self
.
assertListEqual
(
self
.
get_item_from_modulestore
(
self
.
seq2_usage_key
)
.
children
,
[
unit_1_key
,
unit_2_key
],
)
self
.
assertListEqual
(
self
.
get_item_from_modulestore
(
self
.
seq_usage_key
)
.
children
,
[
self
.
problem_usage_key
],
# problem child created in setUp
)
def
test_move_orphaned_child_error
(
self
):
"""
Test moving an orphan returns an error
"""
unit_1_key
=
self
.
store
.
create_item
(
self
.
user
.
id
,
self
.
course_key
,
'vertical'
,
'unit1'
)
.
location
# adding orphaned unit 1 should return an error
resp
=
self
.
client
.
ajax_post
(
self
.
seq2_update_url
,
data
=
{
'children'
:
[
unicode
(
unit_1_key
)]}
)
self
.
assertEqual
(
resp
.
status_code
,
400
)
self
.
assertIn
(
"Invalid data, possibly caused by concurrent authors"
,
resp
.
content
)
# verify children
self
.
assertListEqual
(
self
.
get_item_from_modulestore
(
self
.
seq2_usage_key
)
.
children
,
[]
)
def
test_move_child_creates_orphan_error
(
self
):
"""
Test creating an orphan returns an error
"""
unit_1_key
=
self
.
response_usage_key
(
self
.
create_xblock
(
parent_usage_key
=
self
.
seq2_usage_key
,
category
=
'vertical'
,
display_name
=
'unit 1'
)
)
unit_2_key
=
self
.
response_usage_key
(
self
.
create_xblock
(
parent_usage_key
=
self
.
seq2_usage_key
,
category
=
'vertical'
,
display_name
=
'unit 2'
)
)
# remove unit 2 should return an error
resp
=
self
.
client
.
ajax_post
(
self
.
seq2_update_url
,
data
=
{
'children'
:
[
unicode
(
unit_1_key
)]}
)
self
.
assertEqual
(
resp
.
status_code
,
400
)
self
.
assertIn
(
"Invalid data, possibly caused by concurrent authors"
,
resp
.
content
)
# verify children
self
.
assertListEqual
(
self
.
get_item_from_modulestore
(
self
.
seq2_usage_key
)
.
children
,
[
unit_1_key
,
unit_2_key
]
)
def
_is_location_published
(
self
,
location
):
def
_is_location_published
(
self
,
location
):
"""
"""
Returns whether or not the item with given location has a published version.
Returns whether or not the item with given location has a published version.
...
@@ -954,44 +1030,6 @@ class TestEditSplitModule(ItemTest):
...
@@ -954,44 +1030,6 @@ class TestEditSplitModule(ItemTest):
self
.
assertEqual
(
2
,
len
(
split_test
.
children
))
self
.
assertEqual
(
2
,
len
(
split_test
.
children
))
self
.
assertEqual
(
initial_group_id_to_child
,
split_test
.
group_id_to_child
)
self
.
assertEqual
(
initial_group_id_to_child
,
split_test
.
group_id_to_child
)
def
test_delete_children
(
self
):
"""
Test that deleting a child in the group_id_to_child map updates the map.
Also test that deleting a child not in the group_id_to_child_map behaves properly.
"""
# Set to first group configuration.
self
.
_update_partition_id
(
0
)
split_test
=
self
.
_assert_children
(
2
)
vertical_1_usage_key
=
split_test
.
children
[
1
]
# Add an extra child to the split_test
resp
=
self
.
create_xblock
(
category
=
'html'
,
parent_usage_key
=
self
.
split_test_usage_key
)
extra_child_usage_key
=
self
.
response_usage_key
(
resp
)
self
.
_assert_children
(
3
)
# Remove the first child (which is part of the group configuration).
resp
=
self
.
client
.
ajax_post
(
self
.
split_test_update_url
,
data
=
{
'children'
:
[
unicode
(
vertical_1_usage_key
),
unicode
(
extra_child_usage_key
)]}
)
self
.
assertEqual
(
resp
.
status_code
,
200
)
split_test
=
self
.
_assert_children
(
2
)
# Check that group_id_to_child was updated appropriately
group_id_to_child
=
split_test
.
group_id_to_child
self
.
assertEqual
(
1
,
len
(
group_id_to_child
))
self
.
assertEqual
(
vertical_1_usage_key
,
group_id_to_child
[
'1'
])
# Remove the "extra" child and make sure that group_id_to_child did not change.
resp
=
self
.
client
.
ajax_post
(
self
.
split_test_update_url
,
data
=
{
'children'
:
[
unicode
(
vertical_1_usage_key
)]}
)
self
.
assertEqual
(
resp
.
status_code
,
200
)
split_test
=
self
.
_assert_children
(
1
)
self
.
assertEqual
(
group_id_to_child
,
split_test
.
group_id_to_child
)
def
test_add_groups
(
self
):
def
test_add_groups
(
self
):
"""
"""
Test the "fix up behavior" when groups are missing (after a group is added to a group configuration).
Test the "fix up behavior" when groups are missing (after a group is added to a group configuration).
...
...
cms/static/js/spec/utils/drag_and_drop_spec.js
View file @
2930e29a
...
@@ -323,18 +323,15 @@ define(["js/utils/drag_and_drop", "js/views/feedback_notification", "js/spec_hel
...
@@ -323,18 +323,15 @@ define(["js/utils/drag_and_drop", "js/views/feedback_notification", "js/spec_hel
},
null
,
{
},
null
,
{
clientX
:
$
(
'#unit-1'
).
offset
().
left
clientX
:
$
(
'#unit-1'
).
offset
().
left
});
});
expect
(
requests
.
length
).
toEqual
(
2
);
expect
(
requests
.
length
).
toEqual
(
1
);
expect
(
this
.
savingSpies
.
constructor
).
toHaveBeenCalled
();
expect
(
this
.
savingSpies
.
constructor
).
toHaveBeenCalled
();
expect
(
this
.
savingSpies
.
show
).
toHaveBeenCalled
();
expect
(
this
.
savingSpies
.
show
).
toHaveBeenCalled
();
expect
(
this
.
savingSpies
.
hide
).
not
.
toHaveBeenCalled
();
expect
(
this
.
savingSpies
.
hide
).
not
.
toHaveBeenCalled
();
savingOptions
=
this
.
savingSpies
.
constructor
.
mostRecentCall
.
args
[
0
];
savingOptions
=
this
.
savingSpies
.
constructor
.
mostRecentCall
.
args
[
0
];
expect
(
savingOptions
.
title
).
toMatch
(
/Saving/
);
expect
(
savingOptions
.
title
).
toMatch
(
/Saving/
);
expect
(
$
(
'#unit-1'
)).
toHaveClass
(
'was-dropped'
);
expect
(
$
(
'#unit-1'
)).
toHaveClass
(
'was-dropped'
);
expect
(
requests
[
0
].
requestBody
).
toEqual
(
'{"children":["
second-unit-id","third
-unit-id"]}'
);
expect
(
requests
[
0
].
requestBody
).
toEqual
(
'{"children":["
fourth-unit-id","first
-unit-id"]}'
);
requests
[
0
].
respond
(
200
);
requests
[
0
].
respond
(
200
);
expect
(
this
.
savingSpies
.
hide
).
not
.
toHaveBeenCalled
();
expect
(
requests
[
1
].
requestBody
).
toEqual
(
'{"children":["fourth-unit-id","first-unit-id"]}'
);
requests
[
1
].
respond
(
200
);
expect
(
this
.
savingSpies
.
hide
).
toHaveBeenCalled
();
expect
(
this
.
savingSpies
.
hide
).
toHaveBeenCalled
();
this
.
clock
.
tick
(
1001
);
this
.
clock
.
tick
(
1001
);
expect
(
$
(
'#unit-1'
)).
not
.
toHaveClass
(
'was-dropped'
);
expect
(
$
(
'#unit-1'
)).
not
.
toHaveClass
(
'was-dropped'
);
...
...
cms/static/js/utils/drag_and_drop.js
View file @
2930e29a
...
@@ -288,17 +288,6 @@ define(["jquery", "jquery.ui", "underscore", "gettext", "js/views/feedback_notif
...
@@ -288,17 +288,6 @@ define(["jquery", "jquery.ui", "underscore", "gettext", "js/views/feedback_notif
if
(
_
.
isFunction
(
refresh
))
{
refresh
(
collapsed
);
}
if
(
_
.
isFunction
(
refresh
))
{
refresh
(
collapsed
);
}
};
};
// If the parent has changed, update the children of the old parent.
if
(
newParentLocator
!==
oldParentLocator
)
{
// Find the old parent element.
oldParentEle
=
$
(
parentSelector
).
filter
(
function
()
{
return
$
(
this
).
data
(
'locator'
)
===
oldParentLocator
;
});
this
.
saveItem
(
oldParentEle
,
childrenSelector
,
function
()
{
element
.
data
(
'parent'
,
newParentLocator
);
refreshParent
(
oldParentEle
);
});
}
saving
=
new
NotificationView
.
Mini
({
saving
=
new
NotificationView
.
Mini
({
title
:
gettext
(
'Saving…'
)
title
:
gettext
(
'Saving…'
)
});
});
...
@@ -310,7 +299,18 @@ define(["jquery", "jquery.ui", "underscore", "gettext", "js/views/feedback_notif
...
@@ -310,7 +299,18 @@ define(["jquery", "jquery.ui", "underscore", "gettext", "js/views/feedback_notif
},
1000
);
},
1000
);
this
.
saveItem
(
newParentEle
,
childrenSelector
,
function
()
{
this
.
saveItem
(
newParentEle
,
childrenSelector
,
function
()
{
saving
.
hide
();
saving
.
hide
();
// Refresh new parent.
refreshParent
(
newParentEle
);
refreshParent
(
newParentEle
);
// Refresh old parent.
if
(
newParentLocator
!==
oldParentLocator
)
{
oldParentEle
=
$
(
parentSelector
).
filter
(
function
()
{
return
$
(
this
).
data
(
'locator'
)
===
oldParentLocator
;
});
refreshParent
(
oldParentEle
);
element
.
data
(
'parent'
,
newParentLocator
);
}
});
});
},
},
...
...
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