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
a6faa163
Commit
a6faa163
authored
Oct 18, 2013
by
cahrens
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Convert checklists to new URL scheme.
parent
9cbd2312
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
88 additions
and
102 deletions
+88
-102
cms/djangoapps/contentstore/tests/test_checklists.py
+22
-36
cms/djangoapps/contentstore/views/checklist.py
+59
-59
cms/templates/checklists.html
+2
-2
cms/templates/widgets/header.html
+4
-2
cms/urls.py
+1
-3
No files found.
cms/djangoapps/contentstore/tests/test_checklists.py
View file @
a6faa163
...
...
@@ -3,7 +3,8 @@ from contentstore.utils import get_modulestore
from
contentstore.views.checklist
import
expand_checklist_action_url
from
xmodule.modulestore.inheritance
import
own_metadata
from
xmodule.modulestore.tests.factories
import
CourseFactory
from
django.core.urlresolvers
import
reverse
from
xmodule.modulestore.django
import
loc_mapper
import
json
from
.utils
import
CourseTestCase
...
...
@@ -14,6 +15,8 @@ class ChecklistTestCase(CourseTestCase):
""" Creates the test course. """
super
(
ChecklistTestCase
,
self
)
.
setUp
()
self
.
course
=
CourseFactory
.
create
(
org
=
'mitX'
,
number
=
'333'
,
display_name
=
'Checklists Course'
)
self
.
location
=
loc_mapper
()
.
translate_location
(
self
.
course
.
location
.
course_id
,
self
.
course
.
location
,
False
,
True
)
self
.
checklists_url
=
self
.
location
.
url_reverse
(
'checklists/'
,
''
)
def
get_persisted_checklists
(
self
):
""" Returns the checklists as persisted in the modulestore. """
...
...
@@ -35,13 +38,8 @@ class ChecklistTestCase(CourseTestCase):
self
.
assertEqual
(
pers
[
'action_external'
],
req
[
'action_external'
])
def
test_get_checklists
(
self
):
""" Tests the get checklists method. """
checklists_url
=
reverse
(
"checklists"
,
kwargs
=
{
'org'
:
self
.
course
.
location
.
org
,
'course'
:
self
.
course
.
location
.
course
,
'name'
:
self
.
course
.
location
.
name
,
})
response
=
self
.
client
.
get
(
checklists_url
)
""" Tests the get checklists method and URL expansion. """
response
=
self
.
client
.
get
(
self
.
checklists_url
)
self
.
assertContains
(
response
,
"Getting Started With Studio"
)
# Verify expansion of action URL happened.
self
.
assertContains
(
response
,
'/mitX/333/team/Checklists_Course'
)
...
...
@@ -58,17 +56,19 @@ class ChecklistTestCase(CourseTestCase):
modulestore
=
get_modulestore
(
self
.
course
.
location
)
modulestore
.
update_metadata
(
self
.
course
.
location
,
own_metadata
(
self
.
course
))
self
.
assertEqual
(
self
.
get_persisted_checklists
(),
None
)
response
=
self
.
client
.
get
(
checklists_url
)
response
=
self
.
client
.
get
(
self
.
checklists_url
)
self
.
assertEqual
(
payload
,
response
.
content
)
def
test_get_checklists_html
(
self
):
""" Tests getting the HTML template for the checklists page). """
response
=
self
.
client
.
get
(
self
.
checklists_url
,
HTTP_ACCEPT
=
'text/html'
)
self
.
assertContains
(
response
,
"Getting Started With Studio"
)
# The HTML generated will define the handler URL (for use by the Backbone model).
self
.
assertContains
(
response
,
self
.
checklists_url
)
def
test_update_checklists_no_index
(
self
):
""" No checklist index, should return all of them. """
update_url
=
reverse
(
'checklists_updates'
,
kwargs
=
{
'org'
:
self
.
course
.
location
.
org
,
'course'
:
self
.
course
.
location
.
course
,
'name'
:
self
.
course
.
location
.
name
})
returned_checklists
=
json
.
loads
(
self
.
client
.
get
(
update_url
)
.
content
)
returned_checklists
=
json
.
loads
(
self
.
client
.
get
(
self
.
checklists_url
)
.
content
)
# Verify that persisted checklists do not have expanded action URLs.
# compare_checklists will verify that returned_checklists DO have expanded action URLs.
pers
=
self
.
get_persisted_checklists
()
...
...
@@ -78,10 +78,7 @@ class ChecklistTestCase(CourseTestCase):
def
test_update_checklists_index_ignored_on_get
(
self
):
""" Checklist index ignored on get. """
update_url
=
reverse
(
'checklists_updates'
,
kwargs
=
{
'org'
:
self
.
course
.
location
.
org
,
'course'
:
self
.
course
.
location
.
course
,
'name'
:
self
.
course
.
location
.
name
,
'checklist_index'
:
1
})
update_url
=
self
.
location
.
url_reverse
(
'checklists/'
,
'1'
)
returned_checklists
=
json
.
loads
(
self
.
client
.
get
(
update_url
)
.
content
)
for
pay
,
resp
in
zip
(
self
.
get_persisted_checklists
(),
returned_checklists
):
...
...
@@ -89,27 +86,19 @@ class ChecklistTestCase(CourseTestCase):
def
test_update_checklists_post_no_index
(
self
):
""" No checklist index, will error on post. """
update_url
=
reverse
(
'checklists_updates'
,
kwargs
=
{
'org'
:
self
.
course
.
location
.
org
,
'course'
:
self
.
course
.
location
.
course
,
'name'
:
self
.
course
.
location
.
name
})
response
=
self
.
client
.
post
(
update_url
)
response
=
self
.
client
.
post
(
self
.
checklists_url
)
self
.
assertContains
(
response
,
'Could not save checklist'
,
status_code
=
400
)
def
test_update_checklists_index_out_of_range
(
self
):
""" Checklist index out of range, will error on post. """
update_url
=
reverse
(
'checklists_updates'
,
kwargs
=
{
'org'
:
self
.
course
.
location
.
org
,
'course'
:
self
.
course
.
location
.
course
,
'name'
:
self
.
course
.
location
.
name
,
'checklist_index'
:
100
})
update_url
=
self
.
location
.
url_reverse
(
'checklists/'
,
'100'
)
response
=
self
.
client
.
post
(
update_url
)
self
.
assertContains
(
response
,
'Could not save checklist'
,
status_code
=
400
)
def
test_update_checklists_index
(
self
):
""" Check that an update of a particular checklist works. """
update_url
=
reverse
(
'checklists_updates'
,
kwargs
=
{
'org'
:
self
.
course
.
location
.
org
,
'course'
:
self
.
course
.
location
.
course
,
'name'
:
self
.
course
.
location
.
name
,
'checklist_index'
:
1
})
update_url
=
self
.
location
.
url_reverse
(
'checklists/'
,
'1'
)
payload
=
self
.
course
.
checklists
[
1
]
self
.
assertFalse
(
get_first_item
(
payload
)
.
get
(
'is_checked'
))
...
...
@@ -127,10 +116,7 @@ class ChecklistTestCase(CourseTestCase):
def
test_update_checklists_delete_unsupported
(
self
):
""" Delete operation is not supported. """
update_url
=
reverse
(
'checklists_updates'
,
kwargs
=
{
'org'
:
self
.
course
.
location
.
org
,
'course'
:
self
.
course
.
location
.
course
,
'name'
:
self
.
course
.
location
.
name
,
'checklist_index'
:
100
})
update_url
=
self
.
location
.
url_reverse
(
'checklists/'
,
'100'
)
response
=
self
.
client
.
delete
(
update_url
)
self
.
assertEqual
(
response
.
status_code
,
405
)
...
...
@@ -152,7 +138,7 @@ class ChecklistTestCase(CourseTestCase):
self
.
assertEqual
(
get_action_url
(
checklist
,
index
),
stored
)
test_expansion
(
self
.
course
.
checklists
[
0
],
0
,
'ManageUsers'
,
'/mitX/333/team/Checklists_Course'
)
test_expansion
(
self
.
course
.
checklists
[
1
],
1
,
'CourseOutline'
,
'/
mitX/333/course
/Checklists_Course'
)
test_expansion
(
self
.
course
.
checklists
[
1
],
1
,
'CourseOutline'
,
'/
course/mitX.333.Checklists_Course/branch/draft/block
/Checklists_Course'
)
test_expansion
(
self
.
course
.
checklists
[
2
],
0
,
'http://help.edge.edx.org/'
,
'http://help.edge.edx.org/'
)
...
...
cms/djangoapps/contentstore/views/checklist.py
View file @
a6faa163
...
...
@@ -8,62 +8,63 @@ from django.views.decorators.http import require_http_methods
from
django.core.urlresolvers
import
reverse
from
django_future.csrf
import
ensure_csrf_cookie
from
mitxmako.shortcuts
import
render_to_response
from
django.http
import
HttpResponseNotFound
from
django.core.exceptions
import
PermissionDenied
from
xmodule.modulestore.django
import
loc_mapper
from
xmodule.modulestore.inheritance
import
own_metadata
from
..utils
import
get_modulestore
from
.access
import
get_location_and_verify
_access
from
.access
import
has
_access
from
xmodule.course_module
import
CourseDescriptor
from
xmodule.modulestore.locator
import
BlockUsageLocator
__all__
=
[
'get_checklists'
,
'update_checklist'
]
__all__
=
[
'checklists_handler'
]
@
ensure_csrf_cookie
@
require_http_methods
((
"GET"
,
"POST"
,
"PUT"
))
@login_required
def
get_checklists
(
request
,
org
,
course
,
name
):
@ensure_csrf_cookie
def
checklists_handler
(
request
,
tag
=
None
,
course_id
=
None
,
branch
=
None
,
version_guid
=
None
,
block
=
None
,
checklist_index
=
None
):
"""
Send models, views, and html for displaying the course
checklists.
The restful handler for
checklists.
org, course, name: Attributes of the Location for the item to edit
GET
html: return html page for all checklists
json: return json representing all checklists. checklist_index is not supported for GET at this time.
POST or PUT
json: updates the checked state for items within a particular checklist. checklist_index is required.
"""
location
=
get_location_and_verify_access
(
request
,
org
,
course
,
name
)
location
=
BlockUsageLocator
(
course_id
=
course_id
,
branch
=
branch
,
version_guid
=
version_guid
,
usage_id
=
block
)
if
not
has_access
(
request
.
user
,
location
):
raise
PermissionDenied
()
modulestore
=
get_modulestore
(
location
)
course_module
=
modulestore
.
get_item
(
location
)
old_location
=
loc_mapper
()
.
translate_locator_to_location
(
location
)
# If course was created before checklists were introduced, copy them over
# from the template.
if
not
course_module
.
checklists
:
course_module
.
checklists
=
CourseDescriptor
.
checklists
.
default
course_module
.
save
()
modulestore
.
update_metadata
(
location
,
own_metadata
(
course_module
))
expanded_checklists
=
expand_all_action_urls
(
course_module
)
return
render_to_response
(
'checklists.html'
,
{
'context_course'
:
course_module
,
'checklists'
:
expanded_checklists
})
@require_http_methods
((
"GET"
,
"POST"
,
"PUT"
))
@ensure_csrf_cookie
@login_required
def
update_checklist
(
request
,
org
,
course
,
name
,
checklist_index
=
None
):
"""
restful CRUD operations on course checklists. The payload is a json rep of
the modified checklist. For PUT or POST requests, the index of the
checklist being modified must be included; the returned payload will
be just that one checklist. For GET requests, the returned payload
is a json representation of the list of all checklists.
modulestore
=
get_modulestore
(
old_location
)
course_module
=
modulestore
.
get_item
(
old_location
)
org, course, name: Attributes of the Location for the item to edit
"""
location
=
get_location_and_verify_access
(
request
,
org
,
course
,
name
)
modulestore
=
get_modulestore
(
location
)
course_module
=
modulestore
.
get_item
(
location
)
json_request
=
'application/json'
in
request
.
META
.
get
(
'HTTP_ACCEPT'
,
'application/json'
)
if
request
.
method
==
'GET'
:
# If course was created before checklists were introduced, copy them over
# from the template.
if
not
course_module
.
checklists
:
course_module
.
checklists
=
CourseDescriptor
.
checklists
.
default
course_module
.
save
()
modulestore
.
update_metadata
(
old_location
,
own_metadata
(
course_module
))
if
request
.
method
in
(
"POST"
,
"PUT"
):
expanded_checklists
=
expand_all_action_urls
(
course_module
)
if
json_request
:
return
JsonResponse
(
expanded_checklists
)
else
:
handler_url
=
location
.
url_reverse
(
'checklists/'
,
''
)
return
render_to_response
(
'checklists.html'
,
{
'handler_url'
:
handler_url
,
'checklists'
:
expanded_checklists
})
elif
json_request
:
# Can now assume POST or PUT because GET handled above.
if
checklist_index
is
not
None
and
0
<=
int
(
checklist_index
)
<
len
(
course_module
.
checklists
):
index
=
int
(
checklist_index
)
persisted_checklist
=
course_module
.
checklists
[
index
]
...
...
@@ -77,20 +78,17 @@ def update_checklist(request, org, course, name, checklist_index=None):
# not default
course_module
.
checklists
=
course_module
.
checklists
course_module
.
save
()
modulestore
.
update_metadata
(
location
,
own_metadata
(
course_module
))
modulestore
.
update_metadata
(
old_
location
,
own_metadata
(
course_module
))
expanded_checklist
=
expand_checklist_action_url
(
course_module
,
persisted_checklist
)
return
JsonResponse
(
expanded_checklist
)
else
:
return
HttpResponseBadRequest
(
(
"Could not save checklist state because the checklist index "
"was out of range or unspecified."
),
"was out of range or unspecified."
),
content_type
=
"text/plain"
)
elif
request
.
method
==
'GET'
:
# In the JavaScript view initialize method, we do a fetch to get all
# the checklists.
expanded_checklists
=
expand_all_action_urls
(
course_module
)
return
JsonResponse
(
expanded_checklists
)
else
:
return
HttpResponseNotFound
()
def
expand_all_action_urls
(
course_module
):
...
...
@@ -116,19 +114,21 @@ def expand_checklist_action_url(course_module, checklist):
urlconf_map
=
{
"ManageUsers"
:
"manage_users"
,
"SettingsDetails"
:
"settings_details"
,
"SettingsGrading"
:
"settings_grading"
,
"CourseOutline"
:
"course_index"
,
"Checklists"
:
"checklists"
,
"SettingsGrading"
:
"settings_grading"
}
for
item
in
expanded_checklist
.
get
(
'items'
):
action_url
=
item
.
get
(
'action_url'
)
if
action_url
not
in
urlconf_map
:
continue
urlconf_name
=
urlconf_map
[
action_url
]
item
[
'action_url'
]
=
reverse
(
urlconf_name
,
kwargs
=
{
'org'
:
course_module
.
location
.
org
,
'course'
:
course_module
.
location
.
course
,
'name'
:
course_module
.
location
.
name
,
})
if
action_url
==
"CourseOutline"
:
ctx_loc
=
course_module
.
location
location
=
loc_mapper
()
.
translate_location
(
ctx_loc
.
course_id
,
ctx_loc
,
False
,
True
)
item
[
'action_url'
]
=
location
.
url_reverse
(
'course/'
,
''
)
elif
action_url
in
urlconf_map
:
urlconf_name
=
urlconf_map
[
action_url
]
item
[
'action_url'
]
=
reverse
(
urlconf_name
,
kwargs
=
{
'org'
:
course_module
.
location
.
org
,
'course'
:
course_module
.
location
.
course
,
'name'
:
course_module
.
location
.
name
,
})
return
expanded_checklist
cms/templates/checklists.html
View file @
a6faa163
...
...
@@ -20,8 +20,8 @@
<script
type=
"text/javascript"
>
require
([
"domReady!"
,
"jquery"
,
"js/collections/checklist"
,
"js/views/checklist"
],
function
(
doc
,
$
,
ChecklistCollection
,
ChecklistView
)
{
var
checklistCollection
=
new
ChecklistCollection
()
checklistCollection
.
url
=
"${
reverse('checklists_updates', kwargs=dict(org=context_course.location.org, course=context_course.location.course, name=context_course.location.name))
}"
;
var
checklistCollection
=
new
ChecklistCollection
()
;
checklistCollection
.
url
=
"${
handler_url
}"
;
var
editor
=
new
ChecklistView
({
el
:
$
(
'.course-checklists'
),
...
...
cms/templates/widgets/header.html
View file @
a6faa163
...
...
@@ -15,7 +15,9 @@
% if context_course:
<
%
ctx_loc =
context_course.location
index_url =
loc_mapper().translate_location(ctx_loc.course_id,
ctx_loc
,
False
,
True
).
url_reverse
('
course
/',
'')
location =
loc_mapper().translate_location(ctx_loc.course_id,
ctx_loc
,
False
,
True
)
index_url =
location.url_reverse('course/',
'')
checklists_url =
location.url_reverse('checklists/',
'')
%
>
<h2
class=
"info-course"
>
<span
class=
"sr"
>
${_("Current Course:")}
</span>
...
...
@@ -84,7 +86,7 @@
<div
class=
"nav-sub"
>
<ul>
<li
class=
"nav-item nav-course-tools-checklists"
>
<a
href=
"${
reverse('checklists', kwargs=dict(org=ctx_loc.org, course=ctx_loc.course, name=ctx_loc.name))
}"
>
${_("Checklists")}
</a>
<a
href=
"${
checklists_url
}"
>
${_("Checklists")}
</a>
</li>
<li
class=
"nav-item nav-course-tools-import"
>
<a
href=
"${reverse('import_course', kwargs=dict(org=ctx_loc.org, course=ctx_loc.course, name=ctx_loc.name))}"
>
${_("Import")}
</a>
...
...
cms/urls.py
View file @
a6faa163
...
...
@@ -108,9 +108,6 @@ urlpatterns = patterns('', # nopep8
# User creation and updating views
urlpatterns
+=
patterns
(
''
,
url
(
r'^(?P<org>[^/]+)/(?P<course>[^/]+)/checklists/(?P<name>[^/]+)$'
,
'contentstore.views.get_checklists'
,
name
=
'checklists'
),
url
(
r'^(?P<org>[^/]+)/(?P<course>[^/]+)/checklists/(?P<name>[^/]+)/update(/)?(?P<checklist_index>.+)?.*$'
,
'contentstore.views.update_checklist'
,
name
=
'checklists_updates'
),
url
(
r'^howitworks$'
,
'contentstore.views.howitworks'
,
name
=
'howitworks'
),
url
(
r'^signup$'
,
'contentstore.views.signup'
,
name
=
'signup'
),
...
...
@@ -140,6 +137,7 @@ urlpatterns += patterns(
url
(
r'^course$'
,
'index'
),
# (?ix) == ignore case and verbose (multiline regex)
url
(
r'(?ix)^course/{}$'
.
format
(
parsers
.
URL_RE_SOURCE
),
'course_handler'
),
url
(
r'(?ix)^checklists/{}(/)?(?P<checklist_index>.+)?$'
.
format
(
parsers
.
URL_RE_SOURCE
),
'checklists_handler'
),
)
js_info_dict
=
{
...
...
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