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
286ae9e7
Commit
286ae9e7
authored
Oct 24, 2013
by
Christina Roberts
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1470 from edx/christina/cleanup-course-index
Get rid of course_index shim.
parents
177d1ea9
12488db0
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
71 additions
and
88 deletions
+71
-88
cms/djangoapps/contentstore/features/grading.py
+7
-3
cms/djangoapps/contentstore/features/signup.feature
+3
-3
cms/djangoapps/contentstore/tests/test_contentstore.py
+41
-42
cms/djangoapps/contentstore/views/course.py
+5
-13
cms/djangoapps/contentstore/views/import_export.py
+7
-17
cms/static/js/index.js
+2
-2
cms/templates/unit.html
+6
-1
cms/urls.py
+0
-7
No files found.
cms/djangoapps/contentstore/features/grading.py
View file @
286ae9e7
...
...
@@ -67,9 +67,13 @@ def change_assignment_name(step, old_name, new_name):
@step
(
u'I go back to the main course page'
)
def
main_course_page
(
step
):
main_page_link
=
'/{}/{}/course/{}'
.
format
(
world
.
scenario_dict
[
'COURSE'
]
.
org
,
world
.
scenario_dict
[
'COURSE'
]
.
number
,
world
.
scenario_dict
[
'COURSE'
]
.
display_name
.
replace
(
' '
,
'_'
),)
course_name
=
world
.
scenario_dict
[
'COURSE'
]
.
display_name
.
replace
(
' '
,
'_'
)
main_page_link
=
'/course/{org}.{number}.{name}/branch/draft/block/{name}'
.
format
(
org
=
world
.
scenario_dict
[
'COURSE'
]
.
org
,
number
=
world
.
scenario_dict
[
'COURSE'
]
.
number
,
name
=
course_name
)
world
.
visit
(
main_page_link
)
assert_in
(
'Course Outline'
,
world
.
css_text
(
'h1.page-header'
))
...
...
cms/djangoapps/contentstore/features/signup.feature
View file @
286ae9e7
...
...
@@ -14,11 +14,11 @@ Feature: CMS.Sign in
Scenario
:
Login with a valid redirect
Given
I have opened a new course in Studio
And
I am not logged in
And
I visit the url
"/
MITx/999/course
/Robot_Super_Course"
And
I should see that the path is
"/signin?next=/
MITx/999/course
/Robot_Super_Course"
And
I visit the url
"/
course/MITx.999.Robot_Super_Course/branch/draft/block
/Robot_Super_Course"
And
I should see that the path is
"/signin?next=/
course/MITx.999.Robot_Super_Course/branch/draft/block
/Robot_Super_Course"
When
I fill in and submit the signin form
And
I wait for
"2"
seconds
Then
I should see that the path is
"/
MITx/999/course
/Robot_Super_Course"
Then
I should see that the path is
"/
course/MITx.999.Robot_Super_Course/branch/draft/block
/Robot_Super_Course"
Scenario
:
Login with an invalid redirect
Given
I have opened a new course in Studio
...
...
cms/djangoapps/contentstore/tests/test_contentstore.py
View file @
286ae9e7
...
...
@@ -56,6 +56,7 @@ from pymongo import MongoClient
from
student.models
import
CourseEnrollment
from
contentstore.utils
import
delete_course_and_groups
from
xmodule.modulestore.django
import
loc_mapper
TEST_DATA_CONTENTSTORE
=
copy
.
deepcopy
(
settings
.
CONTENTSTORE
)
TEST_DATA_CONTENTSTORE
[
'DOC_STORE_CONFIG'
][
'db'
]
=
'test_xcontent_
%
s'
%
uuid4
()
.
hex
...
...
@@ -710,10 +711,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
items
=
module_store
.
get_items
(
Location
([
source_location
.
tag
,
source_location
.
org
,
source_location
.
course
,
None
,
None
,
'draft'
]))
self
.
assertGreater
(
len
(
items
),
0
)
resp
=
self
.
client
.
post
(
reverse
(
'create_new_course'
),
course_data
)
self
.
assertEqual
(
resp
.
status_code
,
200
)
data
=
parse_json
(
resp
)
self
.
assertEqual
(
data
[
'id'
],
'i4x://MITx/999/course/2013_Spring'
)
_create_course
(
self
,
course_data
)
content_store
=
contentstore
()
...
...
@@ -776,7 +774,6 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
}
module_store
=
modulestore
(
'direct'
)
draft_store
=
modulestore
(
'draft'
)
content_store
=
contentstore
()
import_from_xml
(
module_store
,
'common/test/data/'
,
[
'toy'
])
...
...
@@ -801,11 +798,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
self
.
assertEqual
(
new_data
,
html_module
.
data
)
# create the destination course
resp
=
self
.
client
.
post
(
reverse
(
'create_new_course'
),
course_data
)
self
.
assertEqual
(
resp
.
status_code
,
200
)
data
=
parse_json
(
resp
)
self
.
assertEqual
(
data
[
'id'
],
'i4x://MITx/999/course/2013_Spring'
)
_create_course
(
self
,
course_data
)
# do the actual cloning
clone_course
(
module_store
,
content_store
,
source_location
,
dest_location
)
...
...
@@ -1369,25 +1362,21 @@ class ContentStoreTest(ModuleStoreTestCase):
test_course_data
.
update
(
self
.
course_data
)
if
number_suffix
:
test_course_data
[
'number'
]
=
'{0}_{1}'
.
format
(
test_course_data
[
'number'
],
number_suffix
)
resp
=
self
.
client
.
post
(
reverse
(
'create_new_course'
),
test_course_data
)
self
.
assertEqual
(
resp
.
status_code
,
200
)
data
=
parse_json
(
resp
)
self
.
assertNotIn
(
'ErrMsg'
,
data
)
self
.
assertEqual
(
data
[
'id'
],
'i4x://MITx/{0}/course/2013_Spring'
.
format
(
test_course_data
[
'number'
]))
_create_course
(
self
,
test_course_data
)
# Verify that the creator is now registered in the course.
self
.
assertTrue
(
CourseEnrollment
.
is_enrolled
(
self
.
user
,
self
.
_get_course_id
(
test_course_data
)))
self
.
assertTrue
(
CourseEnrollment
.
is_enrolled
(
self
.
user
,
_get_course_id
(
test_course_data
)))
return
test_course_data
def
test_create_course_check_forum_seeding
(
self
):
"""Test new course creation and verify forum seeding """
test_course_data
=
self
.
assert_created_course
(
number_suffix
=
uuid4
()
.
hex
)
self
.
assertTrue
(
are_permissions_roles_seeded
(
self
.
_get_course_id
(
test_course_data
)))
self
.
assertTrue
(
are_permissions_roles_seeded
(
_get_course_id
(
test_course_data
)))
def
test_forum_unseeding_on_delete
(
self
):
"""Test new course creation and verify forum unseeding """
test_course_data
=
self
.
assert_created_course
(
number_suffix
=
uuid4
()
.
hex
)
self
.
assertTrue
(
are_permissions_roles_seeded
(
self
.
_get_course_id
(
test_course_data
))
)
course_id
=
self
.
_get_course_id
(
test_course_data
)
course_id
=
_get_course_id
(
test_course_data
)
self
.
assertTrue
(
are_permissions_roles_seeded
(
course_id
)
)
delete_course_and_groups
(
course_id
,
commit
=
True
)
self
.
assertFalse
(
are_permissions_roles_seeded
(
course_id
))
...
...
@@ -1397,18 +1386,14 @@ class ContentStoreTest(ModuleStoreTestCase):
second_course_data
=
self
.
assert_created_course
(
number_suffix
=
uuid4
()
.
hex
)
# unseed the forums for the first course
course_id
=
self
.
_get_course_id
(
test_course_data
)
course_id
=
_get_course_id
(
test_course_data
)
delete_course_and_groups
(
course_id
,
commit
=
True
)
self
.
assertFalse
(
are_permissions_roles_seeded
(
course_id
))
second_course_id
=
self
.
_get_course_id
(
second_course_data
)
second_course_id
=
_get_course_id
(
second_course_data
)
# permissions should still be there for the other course
self
.
assertTrue
(
are_permissions_roles_seeded
(
second_course_id
))
def
_get_course_id
(
self
,
test_course_data
):
"""Returns the course ID (org/number/run)."""
return
"{org}/{number}/{run}"
.
format
(
**
test_course_data
)
def
test_create_course_duplicate_course
(
self
):
"""Test new course creation - error path"""
self
.
client
.
post
(
reverse
(
'create_new_course'
),
self
.
course_data
)
...
...
@@ -1418,7 +1403,7 @@ class ContentStoreTest(ModuleStoreTestCase):
"""
Checks that the course did not get created
"""
course_id
=
self
.
_get_course_id
(
self
.
course_data
)
course_id
=
_get_course_id
(
self
.
course_data
)
initially_enrolled
=
CourseEnrollment
.
is_enrolled
(
self
.
user
,
course_id
)
resp
=
self
.
client
.
post
(
reverse
(
'create_new_course'
),
self
.
course_data
)
self
.
assertEqual
(
resp
.
status_code
,
200
)
...
...
@@ -1544,13 +1529,8 @@ class ContentStoreTest(ModuleStoreTestCase):
"""Test viewing the course overview page with an existing course"""
CourseFactory
.
create
(
org
=
'MITx'
,
course
=
'999'
,
display_name
=
'Robot Super Course'
)
data
=
{
'org'
:
'MITx'
,
'course'
:
'999'
,
'name'
:
Location
.
clean
(
'Robot Super Course'
),
}
resp
=
self
.
client
.
get
(
reverse
(
'course_index'
,
kwargs
=
data
))
loc
=
Location
([
'i4x'
,
'MITx'
,
'999'
,
'course'
,
Location
.
clean
(
'Robot Super Course'
),
None
])
resp
=
self
.
_show_course_overview
(
loc
)
self
.
assertContains
(
resp
,
'<article class="courseware-overview" data-id="i4x://MITx/999/course/Robot_Super_Course">'
,
...
...
@@ -1605,11 +1585,7 @@ class ContentStoreTest(ModuleStoreTestCase):
"""
import_from_xml
(
modulestore
(
'direct'
),
'common/test/data/'
,
[
'simple'
])
loc
=
Location
([
'i4x'
,
'edX'
,
'simple'
,
'course'
,
'2012_Fall'
,
None
])
resp
=
self
.
client
.
get
(
reverse
(
'course_index'
,
kwargs
=
{
'org'
:
loc
.
org
,
'course'
:
loc
.
course
,
'name'
:
loc
.
name
}))
resp
=
self
.
_show_course_overview
(
loc
)
self
.
assertEqual
(
resp
.
status_code
,
200
)
self
.
assertContains
(
resp
,
'Chapter 2'
)
...
...
@@ -1713,10 +1689,7 @@ class ContentStoreTest(ModuleStoreTestCase):
target_course_id
=
'{0}/{1}/{2}'
.
format
(
target_location
.
org
,
target_location
.
course
,
target_location
.
name
)
resp
=
self
.
client
.
post
(
reverse
(
'create_new_course'
),
course_data
)
self
.
assertEqual
(
resp
.
status_code
,
200
)
data
=
parse_json
(
resp
)
self
.
assertEqual
(
data
[
'id'
],
target_location
.
url
())
_create_course
(
self
,
course_data
)
import_from_xml
(
module_store
,
'common/test/data/'
,
[
'toy'
],
target_location_namespace
=
target_location
)
...
...
@@ -1884,6 +1857,13 @@ class ContentStoreTest(ModuleStoreTestCase):
location
=
course
.
location
.
_replace
(
tag
=
'c4x'
,
category
=
'asset'
,
name
=
course
.
course_image
)
content_store
.
find
(
location
)
def
_show_course_overview
(
self
,
location
):
"""
Show the course overview page.
"""
new_location
=
loc_mapper
()
.
translate_location
(
location
.
course_id
,
location
,
False
,
True
)
return
self
.
client
.
get
(
new_location
.
url_reverse
(
'course/'
,
''
),
HTTP_ACCEPT
=
'text/html'
)
@override_settings
(
MODULESTORE
=
TEST_MODULESTORE
)
class
MetadataSaveTestCase
(
ModuleStoreTestCase
):
...
...
@@ -1947,3 +1927,22 @@ class MetadataSaveTestCase(ModuleStoreTestCase):
# TODO: create the same test as `test_metadata_not_persistence`,
# but check persistence for some other module.
pass
def
_create_course
(
test
,
course_data
):
"""
Creates a course and verifies the URL returned in the response..
"""
course_id
=
_get_course_id
(
course_data
)
new_location
=
loc_mapper
()
.
translate_location
(
course_id
,
CourseDescriptor
.
id_to_location
(
course_id
),
False
,
True
)
response
=
test
.
client
.
post
(
reverse
(
'create_new_course'
),
course_data
)
test
.
assertEqual
(
response
.
status_code
,
200
)
data
=
parse_json
(
response
)
test
.
assertNotIn
(
'ErrMsg'
,
data
)
test
.
assertEqual
(
data
[
'url'
],
new_location
.
url_reverse
(
"course/"
,
""
))
def
_get_course_id
(
test_course_data
):
"""Returns the course ID (org/number/run)."""
return
"{org}/{number}/{run}"
.
format
(
**
test_course_data
)
cms/djangoapps/contentstore/views/course.py
View file @
286ae9e7
...
...
@@ -107,17 +107,6 @@ def course_handler(request, tag=None, course_id=None, branch=None, version_guid=
@login_required
@ensure_csrf_cookie
def
old_course_index_shim
(
request
,
org
,
course
,
name
):
"""
A shim for any unconverted uses of course_index
"""
old_location
=
Location
([
'i4x'
,
org
,
course
,
'course'
,
name
])
locator
=
loc_mapper
()
.
translate_location
(
old_location
.
course_id
,
old_location
,
False
,
True
)
return
course_index
(
request
,
locator
.
course_id
,
locator
.
branch
,
locator
.
version_guid
,
locator
.
usage_id
)
@login_required
@ensure_csrf_cookie
def
course_index
(
request
,
course_id
,
branch
,
version_guid
,
block
):
"""
Display an editable course overview.
...
...
@@ -164,7 +153,9 @@ def course_index(request, course_id, branch, version_guid, block):
@expect_json
def
create_new_course
(
request
):
"""
Create a new course
Create a new course.
Returns the URL for the course overview page.
"""
if
not
is_user_in_creator_group
(
request
.
user
):
raise
PermissionDenied
()
...
...
@@ -255,7 +246,8 @@ def create_new_course(request):
# work.
CourseEnrollment
.
enroll
(
request
.
user
,
new_course
.
location
.
course_id
)
return
JsonResponse
({
'id'
:
new_course
.
location
.
url
()})
new_location
=
loc_mapper
()
.
translate_location
(
new_course
.
location
.
course_id
,
new_course
.
location
,
False
,
True
)
return
JsonResponse
({
'url'
:
new_location
.
url_reverse
(
"course/"
,
""
)})
@login_required
...
...
cms/djangoapps/contentstore/views/import_export.py
View file @
286ae9e7
...
...
@@ -27,7 +27,7 @@ from auth.authz import create_all_course_groups
from
xmodule.modulestore.xml_importer
import
import_from_xml
from
xmodule.contentstore.django
import
contentstore
from
xmodule.modulestore.xml_exporter
import
export_to_xml
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore.django
import
modulestore
,
loc_mapper
from
xmodule.modulestore
import
Location
from
xmodule.exceptions
import
SerializationError
...
...
@@ -240,14 +240,10 @@ def import_course(request, org, course, name):
return
JsonResponse
({
'Status'
:
'OK'
})
else
:
course_module
=
modulestore
()
.
get_item
(
location
)
new_location
=
loc_mapper
()
.
translate_location
(
course_module
.
location
.
course_id
,
course_module
.
location
,
False
,
True
)
return
render_to_response
(
'import.html'
,
{
'context_course'
:
course_module
,
'successful_import_redirect_url'
:
reverse
(
'course_index'
,
kwargs
=
{
'org'
:
location
.
org
,
'course'
:
location
.
course
,
'name'
:
location
.
name
,
})
'successful_import_redirect_url'
:
new_location
.
url_reverse
(
"course/"
,
""
)
})
...
...
@@ -286,6 +282,8 @@ def generate_export_course(request, org, course, name):
loc
=
Location
(
location
)
export_file
=
NamedTemporaryFile
(
prefix
=
name
+
'.'
,
suffix
=
".tar.gz"
)
new_location
=
loc_mapper
()
.
translate_location
(
course_module
.
location
.
course_id
,
course_module
.
location
,
False
,
True
)
root_dir
=
path
(
mkdtemp
())
try
:
...
...
@@ -317,11 +315,7 @@ def generate_export_course(request, org, course, name):
'edit_unit_url'
:
reverse
(
'edit_unit'
,
kwargs
=
{
'location'
:
parent
.
location
})
if
parent
else
''
,
'course_home_url'
:
reverse
(
'course_index'
,
kwargs
=
{
'org'
:
org
,
'course'
:
course
,
'name'
:
name
})
'course_home_url'
:
new_location
.
url_reverse
(
"course/"
,
""
)
})
except
Exception
,
e
:
logging
.
exception
(
'There was an error exporting course {0}. {1}'
.
format
(
course_module
.
location
,
unicode
(
e
)))
...
...
@@ -331,11 +325,7 @@ def generate_export_course(request, org, course, name):
'in_err'
:
True
,
'unit'
:
None
,
'raw_err_msg'
:
str
(
e
),
'course_home_url'
:
reverse
(
'course_index'
,
kwargs
=
{
'org'
:
org
,
'course'
:
course
,
'name'
:
name
})
'course_home_url'
:
new_location
.
url_reverse
(
"course/"
,
""
)
})
logging
.
debug
(
'tar file being generated at {0}'
.
format
(
export_file
.
name
))
...
...
cms/static/js/index.js
View file @
286ae9e7
...
...
@@ -39,8 +39,8 @@ require(["domReady", "jquery", "underscore", "js/utils/cancel_on_escape"],
'run'
:
run
},
function
(
data
)
{
if
(
data
.
id
!==
undefined
)
{
window
.
location
=
'/'
+
data
.
id
.
replace
(
/.*:
\/\/
/
,
''
)
;
if
(
data
.
url
!==
undefined
)
{
window
.
location
=
data
.
url
;
}
else
if
(
data
.
ErrMsg
!==
undefined
)
{
$
(
'.wrap-error'
).
addClass
(
'is-shown'
);
$
(
'#course_creation_error'
).
html
(
'<p>'
+
data
.
ErrMsg
+
'</p>'
);
...
...
cms/templates/unit.html
View file @
286ae9e7
...
...
@@ -2,6 +2,7 @@
<
%!
from
django
.
core
.
urlresolvers
import
reverse
from
django
.
utils
.
translation
import
ugettext
as
_
from
xmodule
.
modulestore
.
django
import
loc_mapper
%
>
<
%
namespace
name=
"units"
file=
"widgets/units.html"
/>
<
%
block
name=
"title"
>
${_("Individual Unit")}
</
%
block>
...
...
@@ -179,7 +180,11 @@ require(["domReady!", "jquery", "coffee/src/models/module", "coffee/src/views/un
</div>
<ol>
<li>
<a
href=
"${reverse('course_index', kwargs=dict(org=context_course.location.org, course=context_course.location.course, name=context_course.location.name))}"
class=
"section-item"
>
${section.display_name_with_default}
</a>
<
%
ctx_loc =
context_course.location
index_url =
loc_mapper().translate_location(ctx_loc.course_id,
ctx_loc
,
False
,
True
).
url_reverse
('
course
/',
'')
%
>
<a
href=
"${index_url}"
class=
"section-item"
>
${section.display_name_with_default}
</a>
<ol>
<li>
<a
href=
"${reverse('edit_subsection', args=[subsection.location])}"
class=
"section-item"
>
...
...
cms/urls.py
View file @
286ae9e7
...
...
@@ -135,13 +135,6 @@ urlpatterns += patterns(
# restful api
urlpatterns
+=
patterns
(
'contentstore.views'
,
# index page, course outline page, and course structure json access
# replaces url(r'^listing', 'contentstore.views.index', name='index'),
# ? url(r'^create_new_course', 'contentstore.views.create_new_course', name='create_new_course')
# TODO remove shim and this pattern once import_export and test_contentstore no longer use
url
(
r'^(?P<org>[^/]+)/(?P<course>[^/]+)/course/(?P<name>[^/]+)$'
,
'course.old_course_index_shim'
,
name
=
'course_index'
),
url
(
r'^course$'
,
'index'
),
# (?ix) == ignore case and verbose (multiline regex)
...
...
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