Commit 286ae9e7 by Christina Roberts

Merge pull request #1470 from edx/christina/cleanup-course-index

Get rid of course_index shim.
parents 177d1ea9 12488db0
......@@ -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'))
......
......@@ -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
......
......@@ -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)
......@@ -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
......
......@@ -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))
......
......@@ -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>');
......
......@@ -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">
......
......@@ -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)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment