def library_blocks_view(library, user, response_format): """ The main view of a course's content library. Shows all the XBlocks in the library, and allows adding/editing/deleting them. Can be called with response_format="json" to get a JSON-formatted list of the XBlocks in the library along with library metadata. Assumes that read permissions have been checked before calling this. """ assert isinstance(library.location.library_key, LibraryLocator) assert isinstance(library.location, LibraryUsageLocator) children = library.children if response_format == "json": # The JSON response for this request is short and sweet: prev_version = library.runtime.course_entry.structure[ 'previous_version'] return JsonResponse({ "display_name": library.display_name, "library_id": unicode(library.location.library_key), "version": unicode(library.runtime.course_entry.course_key.version), "previous_version": unicode(prev_version) if prev_version else None, "blocks": [unicode(x) for x in children], }) can_edit = has_studio_write_access(user, library.location.library_key) xblock_info = create_xblock_info(library, include_ancestor_info=False, graders=[]) component_templates = get_component_templates( library, library=True) if can_edit else [] return render_to_response( 'library.html', { 'can_edit': can_edit, 'context_library': library, 'component_templates': json.dumps(component_templates), 'xblock_info': xblock_info, 'templates': CONTAINER_TEMPATES, 'lib_users_url': reverse_library_url('manage_library_users', unicode(library.location.library_key)), })
def test_course_outline_initial_state(self): course_module = modulestore().get_item(self.course.location) course_structure = create_xblock_info( course_module, include_child_info=True, include_children_predicate=lambda xblock: not xblock.category == 'vertical' ) # Verify that None is returned for a non-existent locator self.assertIsNone(course_outline_initial_state('no-such-locator', course_structure)) # Verify that the correct initial state is returned for the test chapter chapter_locator = six.text_type(self.chapter.location) initial_state = course_outline_initial_state(chapter_locator, course_structure) self.assertEqual(initial_state['locator_to_show'], chapter_locator) expanded_locators = initial_state['expanded_locators'] self.assertIn(six.text_type(self.sequential.location), expanded_locators) self.assertIn(six.text_type(self.vertical.location), expanded_locators)
def test_course_outline_initial_state(self): course_module = modulestore().get_item(self.course.location) course_structure = create_xblock_info( course_module, include_child_info=True, include_children_predicate=lambda xblock: not xblock.category == 'vertical' ) # Verify that None is returned for a non-existent locator self.assertIsNone(course_outline_initial_state('no-such-locator', course_structure)) # Verify that the correct initial state is returned for the test chapter chapter_locator = unicode(self.chapter.location) initial_state = course_outline_initial_state(chapter_locator, course_structure) self.assertEqual(initial_state['locator_to_show'], chapter_locator) expanded_locators = initial_state['expanded_locators'] self.assertIn(unicode(self.sequential.location), expanded_locators) self.assertIn(unicode(self.vertical.location), expanded_locators)
def library_blocks_view(library, user, response_format): """ The main view of a course's content library. Shows all the XBlocks in the library, and allows adding/editing/deleting them. Can be called with response_format="json" to get a JSON-formatted list of the XBlocks in the library along with library metadata. Assumes that read permissions have been checked before calling this. """ assert isinstance(library.location.library_key, LibraryLocator) assert isinstance(library.location, LibraryUsageLocator) children = library.children if response_format == "json": # The JSON response for this request is short and sweet: prev_version = library.runtime.course_entry.structure['previous_version'] return JsonResponse({ "display_name": library.display_name, "library_id": unicode(library.location.library_key), "version": unicode(library.runtime.course_entry.course_key.version), "previous_version": unicode(prev_version) if prev_version else None, "blocks": [unicode(x) for x in children], }) can_edit = has_studio_write_access(user, library.location.library_key) xblock_info = create_xblock_info(library, include_ancestor_info=False, graders=[]) component_templates = get_component_templates(library, library=True) if can_edit else [] return render_to_response('library.html', { 'can_edit': can_edit, 'context_library': library, 'component_templates': json.dumps(component_templates), 'xblock_info': xblock_info, 'templates': CONTAINER_TEMPATES, 'lib_users_url': reverse_library_url('manage_library_users', unicode(library.location.library_key)), })
def container_handler(request, usage_key_string): """ The restful handler for container xblock requests. GET html: returns the HTML page for editing a container json: not currently supported """ if 'text/html' in request.META.get('HTTP_ACCEPT', 'text/html'): try: usage_key = UsageKey.from_string(usage_key_string) except InvalidKeyError: # Raise Http404 on invalid 'usage_key_string' raise Http404 with modulestore().bulk_operations(usage_key.course_key): try: course, xblock, lms_link, preview_lms_link = _get_item_in_course( request, usage_key) except ItemNotFoundError: return HttpResponseBadRequest() component_templates = get_component_templates(course) ancestor_xblocks = [] parent = get_parent_xblock(xblock) action = request.GET.get('action', 'view') is_unit_page = is_unit(xblock) unit = xblock if is_unit_page else None while parent and parent.category != 'course': if unit is None and is_unit(parent): unit = parent ancestor_xblocks.append(parent) parent = get_parent_xblock(parent) ancestor_xblocks.reverse() assert unit is not None, "Could not determine unit page" subsection = get_parent_xblock(unit) assert subsection is not None, "Could not determine parent subsection from unit " + unicode( unit.location) section = get_parent_xblock(subsection) assert section is not None, "Could not determine ancestor section from unit " + unicode( unit.location) # Fetch the XBlock info for use by the container page. Note that it includes information # about the block's ancestors and siblings for use by the Unit Outline. xblock_info = create_xblock_info( xblock, include_ancestor_info=is_unit_page) if is_unit_page: add_container_page_publishing_info(xblock, xblock_info) # need to figure out where this item is in the list of children as the # preview will need this index = 1 for child in subsection.get_children(): if child.location == unit.location: break index += 1 return render_to_response( 'container.html', { 'context_course': course, # Needed only for display of menus at top of page. 'action': action, 'xblock': xblock, 'xblock_locator': xblock.location, 'unit': unit, 'is_unit_page': is_unit_page, 'subsection': subsection, 'section': section, 'new_unit_category': 'vertical', 'ancestor_xblocks': ancestor_xblocks, 'component_templates': component_templates, 'xblock_info': xblock_info, 'draft_preview_link': preview_lms_link, 'published_preview_link': lms_link, 'templates': CONTAINER_TEMPLATES }) else: return HttpResponseBadRequest("Only supports HTML requests")
def container_handler(request, usage_key_string): """ The restful handler for container xblock requests. GET html: returns the HTML page for editing a container json: not currently supported """ if 'text/html' in request.META.get('HTTP_ACCEPT', 'text/html'): try: usage_key = UsageKey.from_string(usage_key_string) except InvalidKeyError: # Raise Http404 on invalid 'usage_key_string' raise Http404 with modulestore().bulk_operations(usage_key.course_key): try: course, xblock, lms_link, preview_lms_link = _get_item_in_course( request, usage_key) except ItemNotFoundError: return HttpResponseBadRequest() component_templates = get_component_templates(course) ancestor_xblocks = [] parent = get_parent_xblock(xblock) action = request.GET.get('action', 'view') is_unit_page = is_unit(xblock) unit = xblock if is_unit_page else None is_first = True while parent: if unit is None and is_unit(parent): unit = parent elif parent.category != 'sequential': current_block = { 'block': parent, 'children': parent.get_children(), 'is_last': is_first } is_first = False ancestor_xblocks.append(current_block) parent = get_parent_xblock(parent) ancestor_xblocks.reverse() assert unit is not None, "Could not determine unit page" subsection = get_parent_xblock(unit) assert subsection is not None, "Could not determine parent subsection from unit " + six.text_type( unit.location) section = get_parent_xblock(subsection) assert section is not None, "Could not determine ancestor section from unit " + six.text_type( unit.location) # for the sequence navigator prev_url, next_url = get_sibling_urls(subsection) # these are quoted here because they'll end up in a query string on the page, # and quoting with mako will trigger the xss linter... prev_url = quote_plus(prev_url) if prev_url else None next_url = quote_plus(next_url) if next_url else None # Fetch the XBlock info for use by the container page. Note that it includes information # about the block's ancestors and siblings for use by the Unit Outline. xblock_info = create_xblock_info( xblock, include_ancestor_info=is_unit_page) if is_unit_page: add_container_page_publishing_info(xblock, xblock_info) # need to figure out where this item is in the list of children as the # preview will need this index = 1 for child in subsection.get_children(): if child.location == unit.location: break index += 1 return render_to_response( 'container.html', { 'language_code': request.LANGUAGE_CODE, 'context_course': course, # Needed only for display of menus at top of page. 'action': action, 'xblock': xblock, 'xblock_locator': xblock.location, 'unit': unit, 'is_unit_page': is_unit_page, 'subsection': subsection, 'section': section, 'position': index, 'prev_url': prev_url, 'next_url': next_url, 'new_unit_category': 'vertical', 'outline_url': '{url}?format=concise'.format( url=reverse_course_url('course_handler', course.id)), 'ancestor_xblocks': ancestor_xblocks, 'component_templates': component_templates, 'xblock_info': xblock_info, 'draft_preview_link': preview_lms_link, 'published_preview_link': lms_link, 'templates': CONTAINER_TEMPLATES }) else: return HttpResponseBadRequest("Only supports HTML requests")
def container_handler(request, usage_key_string): """ The restful handler for container xblock requests. GET html: returns the HTML page for editing a container json: not currently supported """ if 'text/html' in request.META.get('HTTP_ACCEPT', 'text/html'): usage_key = UsageKey.from_string(usage_key_string) try: course, xblock, lms_link = _get_item_in_course(request, usage_key) except ItemNotFoundError: return HttpResponseBadRequest() component_templates = get_component_templates(course) ancestor_xblocks = [] parent = get_parent_xblock(xblock) action = request.REQUEST.get('action', 'view') is_unit_page = is_unit(xblock) unit = xblock if is_unit_page else None while parent and parent.category != 'course': if unit is None and is_unit(parent): unit = parent ancestor_xblocks.append(parent) parent = get_parent_xblock(parent) ancestor_xblocks.reverse() assert unit is not None, "Could not determine unit page" subsection = get_parent_xblock(unit) assert subsection is not None, "Could not determine parent subsection from unit " + unicode(unit.location) section = get_parent_xblock(subsection) assert section is not None, "Could not determine ancestor section from unit " + unicode(unit.location) # Fetch the XBlock info for use by the container page. Note that it includes information # about the block's ancestors and siblings for use by the Unit Outline. xblock_info = create_xblock_info(xblock, include_ancestor_info=is_unit_page) # Create the link for preview. preview_lms_base = settings.FEATURES.get('PREVIEW_LMS_BASE') # need to figure out where this item is in the list of children as the # preview will need this index = 1 for child in subsection.get_children(): if child.location == unit.location: break index += 1 preview_lms_link = ( u'//{preview_lms_base}/courses/{org}/{course}/{course_name}/courseware/{section}/{subsection}/{index}' ).format( preview_lms_base=preview_lms_base, lms_base=settings.LMS_BASE, org=course.location.org, course=course.location.course, course_name=course.location.name, section=section.location.name, subsection=subsection.location.name, index=index ) return render_to_response('container.html', { 'context_course': course, # Needed only for display of menus at top of page. 'action': action, 'xblock': xblock, 'xblock_locator': xblock.location, 'unit': unit, 'is_unit_page': is_unit_page, 'subsection': subsection, 'section': section, 'new_unit_category': 'vertical', 'ancestor_xblocks': ancestor_xblocks, 'component_templates': json.dumps(component_templates), 'xblock_info': xblock_info, 'draft_preview_link': preview_lms_link, 'published_preview_link': lms_link, }) else: return HttpResponseBadRequest("Only supports HTML requests")
def container_handler(request, usage_key_string): """ The restful handler for container xblock requests. GET html: returns the HTML page for editing a container json: not currently supported """ if 'text/html' in request.META.get('HTTP_ACCEPT', 'text/html'): try: usage_key = UsageKey.from_string(usage_key_string) except InvalidKeyError: # Raise Http404 on invalid 'usage_key_string' raise Http404 with modulestore().bulk_operations(usage_key.course_key): try: course, xblock, lms_link, preview_lms_link = _get_item_in_course(request, usage_key) except ItemNotFoundError: return HttpResponseBadRequest() component_templates = get_component_templates(course) ancestor_xblocks = [] parent = get_parent_xblock(xblock) action = request.REQUEST.get('action', 'view') is_unit_page = is_unit(xblock) unit = xblock if is_unit_page else None while parent and parent.category != 'course': if unit is None and is_unit(parent): unit = parent ancestor_xblocks.append(parent) parent = get_parent_xblock(parent) ancestor_xblocks.reverse() assert unit is not None, "Could not determine unit page" subsection = get_parent_xblock(unit) assert subsection is not None, "Could not determine parent subsection from unit " + unicode(unit.location) section = get_parent_xblock(subsection) assert section is not None, "Could not determine ancestor section from unit " + unicode(unit.location) # Fetch the XBlock info for use by the container page. Note that it includes information # about the block's ancestors and siblings for use by the Unit Outline. xblock_info = create_xblock_info(xblock, include_ancestor_info=is_unit_page) if is_unit_page: add_container_page_publishing_info(xblock, xblock_info) # need to figure out where this item is in the list of children as the # preview will need this index = 1 for child in subsection.get_children(): if child.location == unit.location: break index += 1 return render_to_response('container.html', { 'context_course': course, # Needed only for display of menus at top of page. 'action': action, 'xblock': xblock, 'xblock_locator': xblock.location, 'unit': unit, 'is_unit_page': is_unit_page, 'subsection': subsection, 'section': section, 'new_unit_category': 'vertical', 'ancestor_xblocks': ancestor_xblocks, 'component_templates': json.dumps(component_templates), 'xblock_info': xblock_info, 'draft_preview_link': preview_lms_link, 'published_preview_link': lms_link, 'keywords_supported': get_keywords_supported(), 'templates': CONTAINER_TEMPATES }) else: return HttpResponseBadRequest("Only supports HTML requests")
def container_handler(request, usage_key_string): """ The restful handler for container xblock requests. GET html: returns the HTML page for editing a container json: not currently supported """ if 'text/html' in request.META.get('HTTP_ACCEPT', 'text/html'): usage_key = UsageKey.from_string(usage_key_string) try: course, xblock, lms_link = _get_item_in_course(request, usage_key) except ItemNotFoundError: return HttpResponseBadRequest() component_templates = get_component_templates(course) ancestor_xblocks = [] parent = get_parent_xblock(xblock) action = request.REQUEST.get('action', 'view') is_unit_page = is_unit(xblock) unit = xblock if is_unit_page else None while parent and parent.category != 'course': if unit is None and is_unit(parent): unit = parent ancestor_xblocks.append(parent) parent = get_parent_xblock(parent) ancestor_xblocks.reverse() assert unit is not None, "Could not determine unit page" subsection = get_parent_xblock(unit) assert subsection is not None, "Could not determine parent subsection from unit " + unicode(unit.location) section = get_parent_xblock(subsection) assert section is not None, "Could not determine ancestor section from unit " + unicode(unit.location) # Fetch the XBlock info for use by the container page. Note that it includes information # about the block's ancestors and siblings for use by the Unit Outline. xblock_info = create_xblock_info(xblock, include_ancestor_info=is_unit_page) # Create the link for preview. preview_lms_base = settings.FEATURES.get('PREVIEW_LMS_BASE') # need to figure out where this item is in the list of children as the # preview will need this index = 1 for child in subsection.get_children(): if child.location == unit.location: break index += 1 preview_lms_link = ( u'//{preview_lms_base}/courses/{org}/{course}/{course_name}/courseware/{section}/{subsection}/{index}' ).format( preview_lms_base=preview_lms_base, lms_base=settings.LMS_BASE, org=course.location.org, course=course.location.course, course_name=course.location.name, section=section.location.name, subsection=subsection.location.name, index=index ) return render_to_response('container.html', { 'context_course': course, # Needed only for display of menus at top of page. 'action': action, 'xblock': xblock, 'xblock_locator': xblock.location, 'unit': unit, 'is_unit_page': is_unit_page, 'subsection': subsection, 'section': section, 'new_unit_category': 'vertical', 'ancestor_xblocks': ancestor_xblocks, 'component_templates': json.dumps(component_templates), 'xblock_info': xblock_info, 'draft_preview_link': preview_lms_link, 'published_preview_link': lms_link, }) else: return HttpResponseBadRequest("Only supports HTML requests")