Commit 7ed5672e by Jonathan Piacenti

Add ability to activate a child block via jump_to_id.

parent 5c6503cd
...@@ -86,6 +86,7 @@ def path_to_location(modulestore, usage_key): ...@@ -86,6 +86,7 @@ def path_to_location(modulestore, usage_key):
# pull out the location names # pull out the location names
chapter = path[1].name if n > 1 else None chapter = path[1].name if n > 1 else None
section = path[2].name if n > 2 else None section = path[2].name if n > 2 else None
vertical = path[3].name if n > 3 else None
# Figure out the position # Figure out the position
position = None position = None
...@@ -109,7 +110,7 @@ def path_to_location(modulestore, usage_key): ...@@ -109,7 +110,7 @@ def path_to_location(modulestore, usage_key):
position_list.append(str(child_locs.index(path[path_index + 1]) + 1)) position_list.append(str(child_locs.index(path[path_index + 1]) + 1))
position = "_".join(position_list) position = "_".join(position_list)
return (course_id, chapter, section, position) return (course_id, chapter, section, vertical, position, path[-1])
def navigation_index(position): def navigation_index(position):
......
...@@ -1222,15 +1222,16 @@ class TestMixedModuleStore(CommonMixedModuleStoreSetup): ...@@ -1222,15 +1222,16 @@ class TestMixedModuleStore(CommonMixedModuleStoreSetup):
should_work = ( should_work = (
(self.problem_x1a_2, (self.problem_x1a_2,
(course_key, u"Chapter_x", u"Sequential_x1", '1')), (course_key, u"Chapter_x", u"Sequential_x1", u'Vertical_x1a', '1', self.problem_x1a_2)),
(self.chapter_x, (self.chapter_x,
(course_key, "Chapter_x", None, None)), (course_key, "Chapter_x", None, None, None, self.chapter_x)),
) )
for location, expected in should_work: for location, expected in should_work:
# each iteration has different find count, pop this iter's find count # each iteration has different find count, pop this iter's find count
with check_mongo_calls(num_finds.pop(0), num_sends): with check_mongo_calls(num_finds.pop(0), num_sends):
self.assertEqual(path_to_location(self.store, location), expected) path = path_to_location(self.store, location)
self.assertEqual(path, expected)
not_found = ( not_found = (
course_key.make_usage_key('video', 'WelcomeX'), course_key.make_usage_key('video', 'WelcomeX'),
...@@ -1260,11 +1261,13 @@ class TestMixedModuleStore(CommonMixedModuleStoreSetup): ...@@ -1260,11 +1261,13 @@ class TestMixedModuleStore(CommonMixedModuleStoreSetup):
# only needs course_locations set # only needs course_locations set
self.initdb('draft') self.initdb('draft')
course_key = self.course_locations[self.XML_COURSEID1].course_key course_key = self.course_locations[self.XML_COURSEID1].course_key
video_key = course_key.make_usage_key('video', 'Welcome')
chapter_key = course_key.make_usage_key('chapter', 'Overview')
should_work = ( should_work = (
(course_key.make_usage_key('video', 'Welcome'), (video_key,
(course_key, "Overview", "Welcome", None)), (course_key, "Overview", "Welcome", None, None, video_key)),
(course_key.make_usage_key('chapter', 'Overview'), (chapter_key,
(course_key, "Overview", None, None)), (course_key, "Overview", None, None, None, chapter_key)),
) )
for location, expected in should_work: for location, expected in should_work:
......
...@@ -84,10 +84,11 @@ class TestJumpTo(ModuleStoreTestCase): ...@@ -84,10 +84,11 @@ class TestJumpTo(ModuleStoreTestCase):
course = CourseFactory.create() course = CourseFactory.create()
chapter = ItemFactory.create(category='chapter', parent_location=course.location) chapter = ItemFactory.create(category='chapter', parent_location=course.location)
section = ItemFactory.create(category='sequential', parent_location=chapter.location) section = ItemFactory.create(category='sequential', parent_location=chapter.location)
expected = 'courses/{course_id}/courseware/{chapter_id}/{section_id}/'.format( expected = 'courses/{course_id}/courseware/{chapter_id}/{section_id}/?activate_block_id={section_key}'.format(
course_id=unicode(course.id), course_id=unicode(course.id),
chapter_id=chapter.url_name, chapter_id=chapter.url_name,
section_id=section.url_name, section_id=section.url_name,
section_key=unicode(section.location)
) )
jumpto_url = '{0}/{1}/jump_to/{2}'.format( jumpto_url = '{0}/{1}/jump_to/{2}'.format(
'/courses', '/courses',
...@@ -106,10 +107,11 @@ class TestJumpTo(ModuleStoreTestCase): ...@@ -106,10 +107,11 @@ class TestJumpTo(ModuleStoreTestCase):
module1 = ItemFactory.create(category='html', parent_location=vertical1.location) module1 = ItemFactory.create(category='html', parent_location=vertical1.location)
module2 = ItemFactory.create(category='html', parent_location=vertical2.location) module2 = ItemFactory.create(category='html', parent_location=vertical2.location)
expected = 'courses/{course_id}/courseware/{chapter_id}/{section_id}/1'.format( expected = 'courses/{course_id}/courseware/{chapter_id}/{section_id}/1?activate_block_id={module_key}'.format(
course_id=unicode(course.id), course_id=unicode(course.id),
chapter_id=chapter.url_name, chapter_id=chapter.url_name,
section_id=section.url_name, section_id=section.url_name,
module_key=unicode(module1.location)
) )
jumpto_url = '{0}/{1}/jump_to/{2}'.format( jumpto_url = '{0}/{1}/jump_to/{2}'.format(
'/courses', '/courses',
...@@ -119,10 +121,11 @@ class TestJumpTo(ModuleStoreTestCase): ...@@ -119,10 +121,11 @@ class TestJumpTo(ModuleStoreTestCase):
response = self.client.get(jumpto_url) response = self.client.get(jumpto_url)
self.assertRedirects(response, expected, status_code=302, target_status_code=302) self.assertRedirects(response, expected, status_code=302, target_status_code=302)
expected = 'courses/{course_id}/courseware/{chapter_id}/{section_id}/2'.format( expected = 'courses/{course_id}/courseware/{chapter_id}/{section_id}/2?activate_block_id={module_key}'.format(
course_id=unicode(course.id), course_id=unicode(course.id),
chapter_id=chapter.url_name, chapter_id=chapter.url_name,
section_id=section.url_name, section_id=section.url_name,
module_key=unicode(module2.location),
) )
jumpto_url = '{0}/{1}/jump_to/{2}'.format( jumpto_url = '{0}/{1}/jump_to/{2}'.format(
'/courses', '/courses',
...@@ -146,10 +149,11 @@ class TestJumpTo(ModuleStoreTestCase): ...@@ -146,10 +149,11 @@ class TestJumpTo(ModuleStoreTestCase):
# internal position of module2 will be 1_2 (2nd item withing 1st item) # internal position of module2 will be 1_2 (2nd item withing 1st item)
expected = 'courses/{course_id}/courseware/{chapter_id}/{section_id}/1'.format( expected = 'courses/{course_id}/courseware/{chapter_id}/{section_id}/1?activate_block_id={module_key}'.format(
course_id=unicode(course.id), course_id=unicode(course.id),
chapter_id=chapter.url_name, chapter_id=chapter.url_name,
section_id=section.url_name, section_id=section.url_name,
module_key=unicode(module2.location)
) )
jumpto_url = '{0}/{1}/jump_to/{2}'.format( jumpto_url = '{0}/{1}/jump_to/{2}'.format(
'/courses', '/courses',
...@@ -1085,6 +1089,23 @@ class GenerateUserCertTests(ModuleStoreTestCase): ...@@ -1085,6 +1089,23 @@ class GenerateUserCertTests(ModuleStoreTestCase):
), resp.content) ), resp.content)
class ActivateIDCheckerBlock(XBlock):
"""
XBlock for checking for an activate_block_id entry in the render context.
"""
# We don't need actual children to test this.
has_children = False
def student_view(self, context):
"""
A student view that displays the activate_block_id context variable.
"""
result = Fragment()
if 'activate_block_id' in context:
result.add_content(u"Activate Block ID: {block_id}</p>".format(block_id=context['activate_block_id']))
return result
class ViewCheckerBlock(XBlock): class ViewCheckerBlock(XBlock):
""" """
XBlock for testing user state in views. XBlock for testing user state in views.
...@@ -1118,7 +1139,7 @@ class TestIndexView(ModuleStoreTestCase): ...@@ -1118,7 +1139,7 @@ class TestIndexView(ModuleStoreTestCase):
@XBlock.register_temp_plugin(ViewCheckerBlock, 'view_checker') @XBlock.register_temp_plugin(ViewCheckerBlock, 'view_checker')
@ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split)
def test_student_state(self, default_store): def test_student_state(self, default_store, ):
""" """
Verify that saved student state is loaded for xblocks rendered in the index view. Verify that saved student state is loaded for xblocks rendered in the index view.
""" """
...@@ -1158,6 +1179,33 @@ class TestIndexView(ModuleStoreTestCase): ...@@ -1158,6 +1179,33 @@ class TestIndexView(ModuleStoreTestCase):
response = views.index(request, unicode(course.id), chapter=chapter.url_name, section=section.url_name) response = views.index(request, unicode(course.id), chapter=chapter.url_name, section=section.url_name)
self.assertEquals(response.content.count("ViewCheckerPassed"), 3) self.assertEquals(response.content.count("ViewCheckerPassed"), 3)
@XBlock.register_temp_plugin(ActivateIDCheckerBlock, 'id_checker')
def test_activate_block_id(self):
user = UserFactory()
course = CourseFactory.create()
chapter = ItemFactory.create(parent=course, category='chapter')
section = ItemFactory.create(parent=chapter, category='sequential', display_name="Sequence")
vertical = ItemFactory.create(parent=section, category='vertical', display_name="Vertical")
ItemFactory.create(parent=vertical, category='id_checker', display_name="ID Checker")
CourseEnrollmentFactory(user=user, course_id=course.id)
request = RequestFactory().get(
reverse(
'courseware_section',
kwargs={
'course_id': unicode(course.id),
'chapter': chapter.url_name,
'section': section.url_name,
}
) + '?activate_block_id=test_block_id'
)
request.user = user
mako_middleware_process_request(request)
response = views.index(request, unicode(course.id), chapter=chapter.url_name, section=section.url_name)
self.assertIn("Activate Block ID: test_block_id", response.content)
class TestRenderXBlock(RenderXBlockTestMixin, ModuleStoreTestCase): class TestRenderXBlock(RenderXBlockTestMixin, ModuleStoreTestCase):
""" """
......
...@@ -20,7 +20,10 @@ def get_redirect_url(course_key, usage_key): ...@@ -20,7 +20,10 @@ def get_redirect_url(course_key, usage_key):
Redirect url string Redirect url string
""" """
(course_key, chapter, section, position) = path_to_location(modulestore(), usage_key) (
course_key, chapter, section, vertical_unused,
position, final_target_id
) = path_to_location(modulestore(), usage_key)
# choose the appropriate view (and provide the necessary args) based on the # choose the appropriate view (and provide the necessary args) based on the
# args provided by the redirect. # args provided by the redirect.
...@@ -43,4 +46,8 @@ def get_redirect_url(course_key, usage_key): ...@@ -43,4 +46,8 @@ def get_redirect_url(course_key, usage_key):
'courseware_position', 'courseware_position',
args=(unicode(course_key), chapter, section, navigation_index(position)) args=(unicode(course_key), chapter, section, navigation_index(position))
) )
if final_target_id:
redirect_url += "?activate_block_id={final_target_id}".format(final_target_id=final_target_id)
return redirect_url return redirect_url
...@@ -554,7 +554,8 @@ def _index_bulk_op(request, course_key, chapter, section, position): ...@@ -554,7 +554,8 @@ def _index_bulk_op(request, course_key, chapter, section, position):
# Save where we are in the chapter # Save where we are in the chapter
save_child_position(chapter_module, section) save_child_position(chapter_module, section)
context['fragment'] = section_module.render(STUDENT_VIEW) section_render_context = {'activate_block_id': request.GET.get('activate_block_id')}
context['fragment'] = section_module.render(STUDENT_VIEW, section_render_context)
context['section_title'] = section_descriptor.display_name_with_default context['section_title'] = section_descriptor.display_name_with_default
else: else:
# section is none, so display a message # section is none, so display a message
......
...@@ -43,7 +43,7 @@ def generate_problem_url(problem_url_parts, base_course_url): ...@@ -43,7 +43,7 @@ def generate_problem_url(problem_url_parts, base_course_url):
# This is placed between the course id and the rest of the url. # This is placed between the course id and the rest of the url.
if i == 1: if i == 1:
problem_url += "courseware/" problem_url += "courseware/"
problem_url += part + "/" problem_url += unicode(part) + "/"
return problem_url return problem_url
......
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