def studio_view(self, context): """ Render a form for editing this XBlock (override the StudioEditableXBlockMixin's method) """ # if the XBlock has been submitted already then disable the studio_edit screen location = self.location.replace( branch=None, version=None) # Standardize the key in case it isn't already item_id = unicode(location) if db_service.is_xblock_submitted(item_id): disabled_edit_fragment = Fragment() disabled_edit_fragment.content = loader.render_template( 'static/html/formula_exercise_disabled_studio_edit.html', {}) disabled_edit_fragment.add_javascript( loader.load_unicode( 'static/js/src/formula_exercise_disabled_studio_edit.js')) disabled_edit_fragment.initialize_js('StudioDisabledEditXBlock') return disabled_edit_fragment # Student not yet submit then we can edit the XBlock fragment = Fragment() context = {'fields': []} # Build a list of all the fields that can be edited: for field_name in self.editable_fields: field = self.fields[field_name] assert field.scope in (Scope.content, Scope.settings), ( "Only Scope.content or Scope.settings fields can be used with " "StudioEditableXBlockMixin. Other scopes are for user-specific data and are " "not generally created/configured by content authors in Studio." ) field_info = self._make_field_info(field_name, field) if field_info is not None: context["fields"].append(field_info) # (re-)fetch data from the database self.load_data_from_dbms() # self.serialize_data_to_context(context) ??? REMOVE not necessary, remove context['question_template'] = self.question_template context["variables"] = self.variables context["expressions"] = self.expressions fragment.content = loader.render_template( 'static/html/formula_exercise_studio_edit.html', context) fragment.add_css( self.resource_string( "static/css/formula_exercise_block_studio_edit.css")) fragment.add_javascript( loader.load_unicode( 'static/js/src/formula_exercise_studio_edit.js')) fragment.initialize_js('StudioEditableXBlockMixin') return fragment
def fallback_view(self, view_name, context=None): result = Fragment() child_frags = self.runtime.render_children(self, context=context) result.add_frags_resources(child_frags) result.content = self.content result.add_content(self.runtime.render_template("vertical.html", children=child_frags)) return result
def studio_view(self, context): """ Render a form for editing this XBlock """ from .models import CorfoCodeMappingContent, CorfoCodeInstitution fragment = Fragment() context = { 'xblock': self, 'location': str(self.location).split('@')[-1], 'list_content': CorfoCodeMappingContent.objects.all().values( 'id_content', 'content'), 'list_institution': CorfoCodeInstitution.objects.all().values('id_institution', 'institution') } context['len_list_institution'] = len(context['list_institution']) fragment.content = loader.render_django_template( 'static/html/studio_view.html', context) fragment.add_css( self.resource_string("static/css/corfogeneratecode.css")) fragment.add_javascript( self.resource_string("static/js/src/corfogeneratecode_studio.js")) fragment.initialize_js('CorfoGenerateXBlock') return fragment
def studio_view(self, context=None): # pylint: disable=unused-argument """ Return a fragment that contains the html for the Studio view. """ frag = Fragment() settings_fields = self.get_editable_fields() settings_page = loader.render_django_template( 'templates/studio_edit.html', {'fields': settings_fields}) context = { 'self': self, 'settings_page': settings_page, } frag.content = xblock_loader.render_django_template( 'static/html/studio.html', context) self.add_stylesheets(frag) self.add_scripts(frag) js_data = { 'editor': self.editor, 'skin_url': self.runtime.local_resource_url(self, 'public/skin'), 'external_plugins': self.get_editor_plugins() } frag.initialize_js('HTML5XBlock', js_data) return frag
def studio_view(self, context=None): """This is the view displaying xblock form in studio.""" fragment = Fragment() fragment.content = self._render_template('static/html/studio_edit.html', **context) fragment.add_javascript(self.resource_string("static/js/src/studio_edit.js")) fragment.initialize_js('BotContainerStudio') return fragment
def studio_view(self, context): """ Render a form for editing this XBlock """ frag = Fragment() context = { 'fields': [], 'test_id_list': self.test_id_list, } # Build a list of all the fields that can be edited: for field_name in self.editable_fields: field = self.fields[field_name] if field.scope not in (Scope.content, Scope.settings): logger.error( "Only Scope.content or Scope.settings fields can be used with " "StudioEditableXBlockMixin. Other scopes are for user-specific data and are " "not generally created/configured by content authors in Studio." ) field_info = self._make_field_info(field_name, field) if field_info is not None: context["fields"].append(field_info) frag.content = loader.render_django_template( "static/html/genesys_edit.html", context) frag.add_javascript( loader.load_unicode("static/js/src/genesys_edit.js")) frag.initialize_js('StudioEditableXBlockMixin') return frag
def studio_view(self, context, override=None): """ Render a form for editing this XBlock. Xblock using this utility method can add more functionality to the simple form generated by this studio_view method. In this case the overriding method is responsible of initializing the fragment javascript function (that's fragment.initialize_js part). It is also the overrriding method resposability to call 'StudioEditableXBlockMixin' from insdie the initialization function. Overriding methods should set override paramter to 'True' """ fragment = Fragment() context = {'fields': []} # Build a list of all the fields that can be edited: for field_name in self.editable_fields: field = self.fields[field_name] assert field.scope in (Scope.content, Scope.settings), ( "Only Scope.content or Scope.settings fields can be used with " "StudioEditableXBlockMixin. Other scopes are for " "user-specific data and are ot generally created/configured" " by content authors in Studio." ) field_info = self._make_field_info(field_name, field) if field_info is not None: context["fields"].append(field_info) fragment.content = loader.render_template( 'templates/studio_edit.html', context) fragment.add_javascript(loader.load_unicode('public/studio_edit.js')) # When ovveride is True that means the child class will call # function StudioEditableXBlockMixin his client side JavaScript if override is None: fragment.initialize_js('StudioEditableXBlockMixin') return fragment
def studio_view(self, context, request=None): """ Render a form for editing this XBlock """ fragment = Fragment() context = {'fields': [], 'courseKey': self.location.course_key} # Build a list of all the fields that can be edited: for field_name in self.editable_fields: field = self.fields[field_name] assert field.scope in (Scope.content, Scope.settings), ( "Only Scope.content or Scope.settings fields can be used with " "StudioEditableXBlockMixin. Other scopes are for user-specific data and are " "not generally created/configured by content authors in Studio." ) field_info = self._make_field_info(field_name, field) if field_info is not None: context["fields"].append(field_info) fragment.content = self.render_template('static/html/studio_edit.html', context) fragment.add_css( self.resource_string("static/css/jupyternotebook_xblock.css")) fragment.add_javascript( self.resource_string("static/js/src/studio_edit.js")) fragment.initialize_js('JupyterNotebookStudioEditableXBlock') return fragment
def studio_view(self, context): """ Render a form for editing this XBlock """ fragment = Fragment() context = {'fields': []} # Build a list of all the fields that can be edited: for field_name in self.editable_fields: field = self.fields[field_name] assert field.scope in (Scope.content, Scope.settings), ( "Only Scope.content or Scope.settings fields can be used with " "StudioEditableXBlockMixin. Other scopes are for user-specific data and are " "not generally created/configured by content authors in Studio." ) field_info = self._make_field_info(field_name, field) if field_info is not None: context["fields"].append(field_info) fragment.content = loader.render_template('static/html/infosecurexblock_studio.html', context) fragment.add_javascript(loader.load_unicode('static/js/src/infosecurexblock_studio.js')) css_urls = ( "static/css/infosecurexblock_studio.css", ) load_resources([], css_urls, fragment) fragment.initialize_js('StudioEditableXBlockMixin') return fragment
def studio_view(self, context): """ Render a form for editing this XBlock """ xblockId = self._get_xblock_id() frag = Fragment() context = {'fields': []} # Build a list of all the fields that can be edited: for field_name in self.editable_fields: field = self.fields[field_name] assert field.scope in (Scope.content, Scope.settings), ( "Only Scope.content or Scope.settings fields can be used with " "StudioEditableXBlockMixin. Other scopes are for user-specific data and are " "not generally created/configured by content authors in Studio." ) field_info = self._make_field_info(field_name, field) if field_info is not None: if field_name == 'block_id': field_info['value'] = xblockId context["fields"].append(field_info) frag.content = loader.render_django_template("static/studio_edit.html", context) frag.add_javascript(loader.load_unicode("static/studio_edit.js")) frag.initialize_js('StudioEditableXBlockMixin') return frag
def fallback_view(self, view_name, context=None): result = Fragment() child_frags = self.runtime.render_children(self, context=context) result.add_frags_resources(child_frags) result.content = self.content result.add_content( self.runtime.render_template("vertical.html", children=child_frags)) return result
def xblock_view_handler(request, package_id, view_name, tag=None, branch=None, version_guid=None, block=None): """ The restful handler for requests for rendered xblock views. Returns a json object containing two keys: html: The rendered html of the view resources: A list of tuples where the first element is the resource hash, and the second is the resource description """ locator = BlockUsageLocator(package_id=package_id, branch=branch, version_guid=version_guid, block_id=block) if not has_course_access(request.user, locator): raise PermissionDenied() old_location = loc_mapper().translate_locator_to_location(locator) accept_header = request.META.get('HTTP_ACCEPT', 'application/json') if 'application/x-fragment+json' in accept_header: store = get_modulestore(old_location) component = store.get_item(old_location) # wrap the generated fragment in the xmodule_editor div so that the javascript # can bind to it correctly component.runtime.wrappers.append(partial(wrap_xblock, 'StudioRuntime')) if view_name == 'studio_view': try: fragment = component.render('studio_view') # catch exceptions indiscriminately, since after this point they escape the # dungeon and surface as uneditable, unsaveable, and undeletable # component-goblins. except Exception as exc: # pylint: disable=w0703 log.debug("unable to render studio_view for %r", component, exc_info=True) fragment = Fragment(render_to_string('html_error.html', {'message': str(exc)})) store.save_xmodule(component) elif view_name == 'student_view': fragment = get_preview_fragment(request, component) fragment.content = render_to_string('component.html', { 'preview': fragment.content, 'label': component.display_name or component.scope_ids.block_type, }) else: raise Http404 hashed_resources = OrderedDict() for resource in fragment.resources: hashed_resources[hash_resource(resource)] = resource return JsonResponse({ 'html': fragment.content, 'resources': hashed_resources.items() }) else: return HttpResponse(status=406)
def student_view(self, context=None): # pylint: disable=unused-argument """ Return a fragment that contains the html for the student view. """ frag = Fragment() frag.content = xblock_loader.render_django_template('static/html/lms.html', {'self': self}) frag.add_css(self.resource_string('public/plugins/codesample/css/prism.css')) frag.add_javascript(self.resource_string('public/plugins/codesample/js/prism.js')) frag.add_css(self.resource_string('static/css/pygments.css')) return frag
def studio_view(self, context=None): """This is the view displaying xblock form in studio.""" fragment = Fragment() initial = { 'passing_grade': self.passing_grade, } form = BotXBlockForm(initial=initial) context = {} context['form'] = form fragment.content = self._render_template('static/html/studio_edit.html', **context) fragment.add_javascript(self.resource_string("static/js/src/studio_edit.js")) fragment.initialize_js('BotContainerStudio') return fragment
def studio_view(self, context=None): """This is the view displaying xblock form in studio.""" fragment = Fragment() initial = { 'passing_grade': self.passing_grade, } form = BotXBlockForm(initial=initial) context = {} context['form'] = form fragment.content = self._render_template( 'static/html/studio_edit.html', **context) fragment.add_javascript( self.resource_string("static/js/src/studio_edit.js")) fragment.initialize_js('BotContainerStudio') return fragment
def studio_view(self, context=None): """This is the view displaying xblock form in studio.""" fragment = Fragment() initial = { 'group_id': self.group_id, 'start_date': self.configuration.start_date, 'end_date': self.configuration.end_date, 'password': self.configuration.password, 'duration': self.configuration.duration, } form = PasswordContainerXBlockForm(initial=initial) context = {} context['form'] = form fragment.content = self._render_template('static/html/studio_edit.html', **context) fragment.add_javascript(self.resource_string("static/js/src/studio_edit.js")) fragment.initialize_js('PasswordContainerStudio') return fragment
def studio_view(self, context): """ Render a form for editing this XBlock """ fragment = Fragment() context = {'fields': []} # Build a list of all the fields that can be edited: for field_name in self.editable_fields: field = self.fields[field_name] assert field.scope in (Scope.content, Scope.settings) field_info = self._make_field_info(field_name, field) if field_info is not None: context["fields"].append(field_info) fragment.content = loader.render_template('templates/studio_edit.html', context) fragment.add_javascript(loader.load_unicode('public/js/src/studio_edit.js')) # Function StudioEditableXBlockMixin will be called from subclass client side JavaScript # fragment.initialize_js('StudioEditableXBlockMixin') return fragment
def studio_view(self, context): """ Render a form for editing this XBlock """ fragment = Fragment() context = { 'xblock': self, 'field_autoclose': self.fields['autoclose'], 'location': str(self.location).split('@')[-1] } context['idform'] = self._make_field_info2('idform', self.fields['idform']) fragment.content = loader.render_django_template( 'static/html/studio_view.html', context) fragment.add_css(self.resource_string("static/css/eoltimify.css")) fragment.add_javascript( self.resource_string("static/js/src/eoltimify_studio.js")) fragment.initialize_js('EolTimifyXBlock') return fragment
def studio_view(self, context): """ Render a form for editing this XBlock """ fragment = Fragment() context = {'fields': []} # Build a list of all the fields that can be edited: for field_name in self.editable_fields: field = self.fields[field_name] assert field.scope in (Scope.content, Scope.settings), ( "Only Scope.content or Scope.settings fields can be used with " "StudioEditableXBlockMixin. Other scopes are for user-specific data and are " "not generally created/configured by content authors in Studio." ) field_info = self._make_field_info(field_name, field) if field_info is not None: context["fields"].append(field_info) fragment.content = loader.render_template('templates/studio_edit.html', context) fragment.add_javascript(loader.load_unicode('public/studio_edit.js')) fragment.initialize_js('StudioEditableXBlockMixin') return fragment
def studio_view(self, context): """ Render a form for editing this XBlock """ fragment = Fragment() context = {'fields': [], 'courseKey': self.location.course_key} # Build a list of all the fields that can be edited: for field_name in self.editable_fields: field = self.fields[field_name] assert field.scope in (Scope.content, Scope.settings), ( "Only Scope.content or Scope.settings fields can be used with " "StudioEditableXBlockMixin. Other scopes are for user-specific data and are " "not generally created/configured by content authors in Studio." ) field_info = self._make_field_info(field_name, field) if field_info is not None: context["fields"].append(field_info) fragment.content = self.render_template('static/html/studio_edit.html', context) fragment.add_css(self.resource_string("static/css/jupyterhub_xblock.css")) fragment.add_javascript(self.resource_string("static/js/src/studio_edit.js")) fragment.initialize_js('JupyterhubStudioEditableXBlock') return fragment
def student_view(self, context=None): """ The primary view of the CodePlayground XBlock, shown to students when viewing courses. """ if not (self.showanswer): self.answer_button_text = self.SHOW_ANSWER_BUTTON_TEXT context = { 'point_string': self.point_string, 'question_content': self.question_content, 'showanswer': self.showanswer, 'code_skeleton': self.code_skeleton, 'expected_output': self.expected_output, 'answer': '' if (self.answer_button_text == self.SHOW_ANSWER_BUTTON_TEXT) else self.answer, 'answer_button_text': self.answer_button_text } frag = Fragment() frag.content = loader.render_template( 'static/html/codeplayground.html', context) frag.add_css(self.resource_string("static/css/codeplayground.css")) frag.add_javascript( self.resource_string("static/js/codeplayground.js")) frag.initialize_js('CodePlayground') return frag
def xblock_view_handler(request, usage_key_string, view_name): """ The restful handler for requests for rendered xblock views. Returns a json object containing two keys: html: The rendered html of the view resources: A list of tuples where the first element is the resource hash, and the second is the resource description """ usage_key = usage_key_with_run(usage_key_string) if not has_course_access(request.user, usage_key.course_key): raise PermissionDenied() accept_header = request.META.get('HTTP_ACCEPT', 'application/json') if 'application/json' in accept_header: store = modulestore() xblock = store.get_item(usage_key) container_views = ['container_preview', 'reorderable_container_child_preview'] # wrap the generated fragment in the xmodule_editor div so that the javascript # can bind to it correctly xblock.runtime.wrappers.append(partial( wrap_xblock, 'StudioRuntime', usage_id_serializer=unicode, request_token=request_token(request), )) if view_name == STUDIO_VIEW: try: fragment = xblock.render(STUDIO_VIEW) # catch exceptions indiscriminately, since after this point they escape the # dungeon and surface as uneditable, unsaveable, and undeletable # component-goblins. except Exception as exc: # pylint: disable=w0703 log.debug("unable to render studio_view for %r", xblock, exc_info=True) fragment = Fragment(render_to_string('html_error.html', {'message': str(exc)})) store.update_item(xblock, request.user.id) elif view_name in (PREVIEW_VIEWS + container_views): is_pages_view = view_name == STUDENT_VIEW # Only the "Pages" view uses student view in Studio # Determine the items to be shown as reorderable. Note that the view # 'reorderable_container_child_preview' is only rendered for xblocks that # are being shown in a reorderable container, so the xblock is automatically # added to the list. reorderable_items = set() if view_name == 'reorderable_container_child_preview': reorderable_items.add(xblock.location) # Set up the context to be passed to each XBlock's render method. context = { 'is_pages_view': is_pages_view, # This setting disables the recursive wrapping of xblocks 'is_unit_page': is_unit(xblock), 'root_xblock': xblock if (view_name == 'container_preview') else None, 'reorderable_items': reorderable_items } fragment = get_preview_fragment(request, xblock, context) # Note that the container view recursively adds headers into the preview fragment, # so only the "Pages" view requires that this extra wrapper be included. if is_pages_view: fragment.content = render_to_string('component.html', { 'xblock_context': context, 'xblock': xblock, 'locator': usage_key, 'preview': fragment.content, 'label': xblock.display_name or xblock.scope_ids.block_type, }) else: raise Http404 hashed_resources = OrderedDict() for resource in fragment.resources: hashed_resources[hash_resource(resource)] = resource return JsonResponse({ 'html': fragment.content, 'resources': hashed_resources.items() }) else: return HttpResponse(status=406)
def xblock_view_handler(request, usage_key_string, view_name): """ The restful handler for requests for rendered xblock views. Returns a json object containing two keys: html: The rendered html of the view resources: A list of tuples where the first element is the resource hash, and the second is the resource description """ usage_key = usage_key_with_run(usage_key_string) if not has_course_author_access(request.user, usage_key.course_key): raise PermissionDenied() accept_header = request.META.get('HTTP_ACCEPT', 'application/json') if 'application/json' in accept_header: store = modulestore() xblock = store.get_item(usage_key) container_views = [ 'container_preview', 'reorderable_container_child_preview' ] # wrap the generated fragment in the xmodule_editor div so that the javascript # can bind to it correctly xblock.runtime.wrappers.append( partial( wrap_xblock, 'StudioRuntime', usage_id_serializer=unicode, request_token=request_token(request), )) if view_name == STUDIO_VIEW: try: fragment = xblock.render(STUDIO_VIEW) # catch exceptions indiscriminately, since after this point they escape the # dungeon and surface as uneditable, unsaveable, and undeletable # component-goblins. except Exception as exc: # pylint: disable=broad-except log.debug("unable to render studio_view for %r", xblock, exc_info=True) fragment = Fragment( render_to_string('html_error.html', {'message': str(exc)})) elif view_name in (PREVIEW_VIEWS + container_views): is_pages_view = view_name == STUDENT_VIEW # Only the "Pages" view uses student view in Studio # Determine the items to be shown as reorderable. Note that the view # 'reorderable_container_child_preview' is only rendered for xblocks that # are being shown in a reorderable container, so the xblock is automatically # added to the list. reorderable_items = set() if view_name == 'reorderable_container_child_preview': reorderable_items.add(xblock.location) # Set up the context to be passed to each XBlock's render method. context = { 'is_pages_view': is_pages_view, # This setting disables the recursive wrapping of xblocks 'is_unit_page': is_unit(xblock), 'root_xblock': xblock if (view_name == 'container_preview') else None, 'reorderable_items': reorderable_items } fragment = get_preview_fragment(request, xblock, context) # Note that the container view recursively adds headers into the preview fragment, # so only the "Pages" view requires that this extra wrapper be included. if is_pages_view: fragment.content = render_to_string( 'component.html', { 'xblock_context': context, 'xblock': xblock, 'locator': usage_key, 'preview': fragment.content, 'label': xblock.display_name or xblock.scope_ids.block_type, }) else: raise Http404 hashed_resources = OrderedDict() for resource in fragment.resources: hashed_resources[hash_resource(resource)] = resource return JsonResponse({ 'html': fragment.content, 'resources': hashed_resources.items() }) else: return HttpResponse(status=406)
def xblock_view_handler(request, package_id, view_name, tag=None, branch=None, version_guid=None, block=None): """ The restful handler for requests for rendered xblock views. Returns a json object containing two keys: html: The rendered html of the view resources: A list of tuples where the first element is the resource hash, and the second is the resource description """ locator = BlockUsageLocator(package_id=package_id, branch=branch, version_guid=version_guid, block_id=block) if not has_course_access(request.user, locator): raise PermissionDenied() old_location = loc_mapper().translate_locator_to_location(locator) accept_header = request.META.get('HTTP_ACCEPT', 'application/json') if 'application/json' in accept_header: store = get_modulestore(old_location) component = store.get_item(old_location) # wrap the generated fragment in the xmodule_editor div so that the javascript # can bind to it correctly component.runtime.wrappers.append(partial(wrap_xblock, 'StudioRuntime')) if view_name == 'studio_view': try: fragment = component.render('studio_view') # catch exceptions indiscriminately, since after this point they escape the # dungeon and surface as uneditable, unsaveable, and undeletable # component-goblins. except Exception as exc: # pylint: disable=w0703 log.debug("unable to render studio_view for %r", component, exc_info=True) fragment = Fragment( render_to_string('html_error.html', {'message': str(exc)})) # change not authored by requestor but by xblocks. store.update_item(component, None) elif view_name == 'student_view' and component.has_children: # For non-leaf xblocks on the unit page, show the special rendering # which links to the new container page. html = render_to_string( 'container_xblock_component.html', { 'xblock': component, 'locator': locator, 'reordering_enabled': True, }) return JsonResponse({ 'html': html, 'resources': [], }) elif view_name in ('student_view', 'container_preview'): is_container_view = (view_name == 'container_preview') component_publish_state = compute_publish_state(component) is_read_only_view = component_publish_state == PublishState.public # Only show the new style HTML for the container view, i.e. for non-verticals # Note: this special case logic can be removed once the unit page is replaced # with the new container view. context = { 'runtime_type': 'studio', 'container_view': is_container_view, 'read_only': is_read_only_view, 'root_xblock': component, } fragment = get_preview_fragment(request, component, context) # For old-style pages (such as unit and static pages), wrap the preview with # the component div. Note that the container view recursively adds headers # into the preview fragment, so we don't want to add another header here. if not is_container_view: fragment.content = render_to_string( 'component.html', { 'preview': fragment.content, 'label': component.display_name or component.scope_ids.block_type, }) else: raise Http404 hashed_resources = OrderedDict() for resource in fragment.resources: hashed_resources[hash_resource(resource)] = resource return JsonResponse({ 'html': fragment.content, 'resources': hashed_resources.items() }) else: return HttpResponse(status=406)
def xblock_view_handler(request, package_id, view_name, tag=None, branch=None, version_guid=None, block=None): """ The restful handler for requests for rendered xblock views. Returns a json object containing two keys: html: The rendered html of the view resources: A list of tuples where the first element is the resource hash, and the second is the resource description """ locator = BlockUsageLocator(package_id=package_id, branch=branch, version_guid=version_guid, block_id=block) if not has_course_access(request.user, locator): raise PermissionDenied() old_location = loc_mapper().translate_locator_to_location(locator) accept_header = request.META.get('HTTP_ACCEPT', 'application/json') if 'application/json' in accept_header: store = get_modulestore(old_location) component = store.get_item(old_location) # wrap the generated fragment in the xmodule_editor div so that the javascript # can bind to it correctly component.runtime.wrappers.append(partial(wrap_xblock, 'StudioRuntime')) if view_name == 'studio_view': try: fragment = component.render('studio_view') # catch exceptions indiscriminately, since after this point they escape the # dungeon and surface as uneditable, unsaveable, and undeletable # component-goblins. except Exception as exc: # pylint: disable=w0703 log.debug("unable to render studio_view for %r", component, exc_info=True) fragment = Fragment(render_to_string('html_error.html', {'message': str(exc)})) # change not authored by requestor but by xblocks. store.update_item(component, None) elif view_name == 'student_view' and component.has_children: # For non-leaf xblocks on the unit page, show the special rendering # which links to the new container page. html = render_to_string('container_xblock_component.html', { 'xblock': component, 'locator': locator, 'reordering_enabled': True, }) return JsonResponse({ 'html': html, 'resources': [], }) elif view_name in ('student_view', 'container_preview'): is_container_view = (view_name == 'container_preview') # Only show the new style HTML for the container view, i.e. for non-verticals # Note: this special case logic can be removed once the unit page is replaced # with the new container view. is_read_only_view = is_container_view context = { 'container_view': is_container_view, 'read_only': is_read_only_view, 'root_xblock': component } fragment = get_preview_fragment(request, component, context) # For old-style pages (such as unit and static pages), wrap the preview with # the component div. Note that the container view recursively adds headers # into the preview fragment, so we don't want to add another header here. if not is_container_view: fragment.content = render_to_string('component.html', { 'preview': fragment.content, 'label': component.display_name or component.scope_ids.block_type, # Native XBlocks are responsible for persisting their own data, # so they are also responsible for providing save/cancel buttons. 'show_save_cancel': isinstance(component, xmodule.x_module.XModuleDescriptor), }) else: raise Http404 hashed_resources = OrderedDict() for resource in fragment.resources: hashed_resources[hash_resource(resource)] = resource return JsonResponse({ 'html': fragment.content, 'resources': hashed_resources.items() }) else: return HttpResponse(status=406)
def studio_view(self, _context): """ Render a form for XBlock editing. """ fragment = Fragment() player = self.get_player() languages = [{'label': label, 'code': lang} for lang, label in ALL_LANGUAGES] languages.sort(key=lambda l: l['label']) transcripts = self.get_enabled_transcripts() download_transcript_handler_url = self.runtime.handler_url(self, 'download_transcript') auth_error_message = '' # Authenticate to API of the player video platform and update metadata with auth information. # Note that there is no need to authenticate to Youtube API, # whilst for Wistia, a sample authorised request is to be made to ensure authentication succeeded, # since it is needed for the auth status message generation and the player's state update with auth status. if self.token: _auth_data, auth_error_message = self.authenticate_video_api(self.token.encode(encoding='utf-8')) initial_default_transcripts, transcripts_autoupload_message = self._update_default_transcripts( player, transcripts ) log.debug("Fetched default transcripts: {}".format(initial_default_transcripts)) # Prepare basic_fields and advanced_fields for them to be rendered basic_fields = self.prepare_studio_editor_fields(player.basic_fields) advanced_fields = self.prepare_studio_editor_fields(player.advanced_fields) context = { 'advanced_fields': advanced_fields, 'auth_error_message': auth_error_message, 'basic_fields': basic_fields, 'courseKey': self.course_key, 'languages': languages, 'player_name': self.player_name, # for players identification 'players': PlayerName, 'sources': list(TranscriptSource.to_dict().items()), # transcripts context: 'transcripts': filter_transcripts_by_source( transcripts, sources=[TranscriptSource.THREE_PLAY_MEDIA], exclude=True ), 'transcripts_fields': self.prepare_studio_editor_fields(player.trans_fields), 'three_pm_fields': self.prepare_studio_editor_fields(player.three_pm_fields), 'transcripts_type': '3PM' if self.threeplaymedia_streaming else 'manual', 'default_transcripts': self.default_transcripts, 'enabled_default_transcripts': filter_transcripts_by_source(transcripts), 'enabled_managed_transcripts': self.get_enabled_managed_transcripts(), 'initial_default_transcripts': initial_default_transcripts, 'transcripts_autoupload_message': transcripts_autoupload_message, 'download_transcript_handler_url': download_transcript_handler_url, } fragment.content = render_template('studio-edit.html', **context) fragment.add_css(resource_string("static/css/student-view.css")) fragment.add_css(resource_string("static/css/transcripts-upload.css")) fragment.add_css(resource_string("static/css/studio-edit.css")) fragment.add_css(resource_string("static/css/studio-edit-accordion.css")) fragment.add_javascript(resource_string("static/js/runtime-handlers.js")) fragment.add_javascript(resource_string("static/js/studio-edit/utils.js")) fragment.add_javascript(resource_string("static/js/studio-edit/studio-edit.js")) fragment.add_javascript(resource_string("static/js/studio-edit/transcripts-autoload.js")) fragment.add_javascript(resource_string("static/js/studio-edit/transcripts-manual-upload.js")) fragment.initialize_js('StudioEditableXBlock') return fragment
def student_view(self, context=None): """ The primary view of the FormulaExerciseXBlock, shown to students when viewing courses. """ context = {} self.submitted_expressions = {} if self.xblock_id is None: self.xblock_id = unicode( self.location.replace(branch=None, version=None)) if self.newly_created_block: self.newly_created_block = (db_service.is_block_in_db( self.xblock_id) is False) if (self.newly_created_block is True): # generate question template for newly created XBlock self.question_template, self.variables, self.expressions = question_service.generate_question_template( ) db_service.create_question_template(self.xblock_id, self.question_template, self.variables, self.expressions) self.newly_created_block = False else: # existing question template in dbms self.load_data_from_dbms() # generate question from template if necessary if (self.generated_question == ""): self.generated_question, self.generated_variables = question_service.generate_question( self.question_template, self.variables) for expression_name, expression_value in self.expressions.iteritems(): self.submitted_expressions[expression_name] = '' # load submission data to display the previously submitted result submissions = sub_api.get_submissions(self.student_item_key, 1) if submissions: latest_submission = submissions[0] # parse the answer answer = latest_submission['answer'] self.generated_question = answer['generated_question'] if ('variable_values' in answer): # backward compatibility saved_generated_variables = json.loads( answer['variable_values']) for var_name, var_value in saved_generated_variables.iteritems( ): self.generated_variables[var_name] = var_value saved_submitted_expressions = json.loads( answer['expression_values']) for submitted_expr_name, submitted_expr_val in saved_submitted_expressions.iteritems( ): self.submitted_expressions[ submitted_expr_name] = submitted_expr_val self.attempt_number = latest_submission['attempt_number'] if (self.attempt_number >= self.max_attempts): context['disabled'] = 'disabled' else: context['disabled'] = '' self.serialize_data_to_context(context) context['attempt_number'] = self.attempt_number_string context['point_string'] = self.point_string context['question'] = self.generated_question context['xblock_id'] = self.xblock_id context['submitted_expressions'] = self.submitted_expressions context['show_answer'] = self.show_answer frag = Fragment() frag.content = loader.render_template( 'static/html/formula_exercise_block.html', context) frag.add_css( self.resource_string("static/css/formula_exercise_block.css")) frag.add_javascript( self.resource_string("static/js/src/formula_exercise_block.js")) frag.initialize_js('FormulaExerciseXBlock') return frag
def xblock_view_handler(request, usage_key_string, view_name): """ The restful handler for requests for rendered xblock views. Returns a json object containing two keys: html: The rendered html of the view resources: A list of tuples where the first element is the resource hash, and the second is the resource description """ usage_key = UsageKey.from_string(usage_key_string) if not has_course_access(request.user, usage_key.course_key): raise PermissionDenied() accept_header = request.META.get('HTTP_ACCEPT', 'application/json') if 'application/json' in accept_header: store = modulestore() xblock = store.get_item(usage_key) is_read_only = _is_xblock_read_only(xblock) container_views = ['container_preview', 'reorderable_container_child_preview'] unit_views = PREVIEW_VIEWS # wrap the generated fragment in the xmodule_editor div so that the javascript # can bind to it correctly xblock.runtime.wrappers.append(partial(wrap_xblock, 'StudioRuntime', usage_id_serializer=unicode)) if view_name == STUDIO_VIEW: try: fragment = xblock.render(STUDIO_VIEW) # catch exceptions indiscriminately, since after this point they escape the # dungeon and surface as uneditable, unsaveable, and undeletable # component-goblins. except Exception as exc: # pylint: disable=w0703 log.debug("unable to render studio_view for %r", xblock, exc_info=True) fragment = Fragment(render_to_string('html_error.html', {'message': str(exc)})) store.update_item(xblock, request.user.id) elif view_name in (unit_views + container_views): is_container_view = (view_name in container_views) # Determine the items to be shown as reorderable. Note that the view # 'reorderable_container_child_preview' is only rendered for xblocks that # are being shown in a reorderable container, so the xblock is automatically # added to the list. reorderable_items = set() if view_name == 'reorderable_container_child_preview': reorderable_items.add(xblock.location) # Only show the new style HTML for the container view, i.e. for non-verticals # Note: this special case logic can be removed once the unit page is replaced # with the new container view. context = { 'container_view': is_container_view, 'read_only': is_read_only, 'root_xblock': xblock if (view_name == 'container_preview') else None, 'reorderable_items': reorderable_items } fragment = get_preview_fragment(request, xblock, context) # For old-style pages (such as unit and static pages), wrap the preview with # the component div. Note that the container view recursively adds headers # into the preview fragment, so we don't want to add another header here. if not is_container_view: # For non-leaf xblocks, show the special rendering which links to the new container page. if xblock_has_own_studio_page(xblock): template = 'container_xblock_component.html' else: template = 'component.html' fragment.content = render_to_string(template, { 'xblock_context': context, 'xblock': xblock, 'locator': usage_key, 'preview': fragment.content, 'label': xblock.display_name or xblock.scope_ids.block_type, }) else: raise Http404 hashed_resources = OrderedDict() for resource in fragment.resources: hashed_resources[hash_resource(resource)] = resource return JsonResponse({ 'html': fragment.content, 'resources': hashed_resources.items() }) else: return HttpResponse(status=406)
def recap_blocks_listing_view(self, context=None): """This view is used in the Racap tab in the LMS Instructor Dashboard to display all available course Recap xblocks. Args: context: contains two items: "recap_items" - all course items with names and parents, example: [{"parent_name": "Vertical name", "name": "Recap Display Name", }, ...] Returns: (Fragment): The HTML Fragment for this XBlock. """ course_id = self.location.course_key recap_blocks = self.get_recap_course_blocks(course_id) recap_name_list = [] for block in recap_blocks: recap_name_list.append((block.display_name, block.xblock_list)) make_pdf_json = reverse('xblock_handler', args=[course_id, block.location, 'make_pdf_json']) refresh_table = reverse('xblock_handler', args=[course_id, block.location, 'refresh_table']) user = self.runtime.get_real_user(self.runtime.anonymous_student_id) lang_prefs = get_user_preference(user, LANGUAGE_KEY) context_dict = { "make_pdf_json": make_pdf_json, "refresh_table": refresh_table, "recap_name_list": recap_name_list, "lang_prefs": lang_prefs } instructor_dashboard_fragment = Fragment() instructor_dashboard_fragment.content = loader.render_django_template( 'static/html/recap_dashboard.html', context_dict ) instructor_dashboard_fragment.add_css( self.resource_string("static/css/recap.css") ) instructor_dashboard_fragment.add_css( self.resource_string("public/DataTables/css/jquery.dataTables.css") ) instructor_dashboard_fragment.add_javascript_url( self.runtime.local_resource_url( self, 'public/FileSaver.js/FileSaver.min.js' ) ) instructor_dashboard_fragment.add_javascript_url( self.runtime.local_resource_url( self, 'public/jsPDF-1.3.2/jspdf.min.js' ) ) instructor_dashboard_fragment.add_javascript_url( self.runtime.local_resource_url( self, 'public/jsPDF-1.3.2/html2canvas.min.js' ) ) instructor_dashboard_fragment.add_javascript_url( self.runtime.local_resource_url( self, 'public/jsPDF-1.3.2/html2pdf.js' ) ) instructor_dashboard_fragment.add_javascript_url( self.runtime.local_resource_url( self, 'public/DataTables/js/jquery.dataTables.js' ) ) instructor_dashboard_fragment.add_javascript_url( self.runtime.local_resource_url( self, "public/recap_dashboard.js" ) ) instructor_dashboard_fragment.initialize_js('RecapDashboard') return instructor_dashboard_fragment
def xblock_view_handler(request, usage_key_string, view_name): """ The restful handler for requests for rendered xblock views. Returns a json object containing two keys: html: The rendered html of the view resources: A list of tuples where the first element is the resource hash, and the second is the resource description """ usage_key = usage_key_with_run(usage_key_string) if not has_studio_read_access(request.user, usage_key.course_key): raise PermissionDenied() accept_header = request.META.get("HTTP_ACCEPT", "application/json") if "application/json" in accept_header: store = modulestore() xblock = store.get_item(usage_key) container_views = ["container_preview", "reorderable_container_child_preview", "container_child_preview"] # wrap the generated fragment in the xmodule_editor div so that the javascript # can bind to it correctly xblock.runtime.wrappers.append( partial(wrap_xblock, "StudioRuntime", usage_id_serializer=unicode, request_token=request_token(request)) ) if view_name in (STUDIO_VIEW, VISIBILITY_VIEW): try: fragment = xblock.render(view_name) # catch exceptions indiscriminately, since after this point they escape the # dungeon and surface as uneditable, unsaveable, and undeletable # component-goblins. except Exception as exc: # pylint: disable=broad-except log.debug("Unable to render %s for %r", view_name, xblock, exc_info=True) fragment = Fragment(render_to_string("html_error.html", {"message": str(exc)})) elif view_name in PREVIEW_VIEWS + container_views: is_pages_view = view_name == STUDENT_VIEW # Only the "Pages" view uses student view in Studio can_edit = has_studio_write_access(request.user, usage_key.course_key) # Determine the items to be shown as reorderable. Note that the view # 'reorderable_container_child_preview' is only rendered for xblocks that # are being shown in a reorderable container, so the xblock is automatically # added to the list. reorderable_items = set() if view_name == "reorderable_container_child_preview": reorderable_items.add(xblock.location) paging = None try: if request.REQUEST.get("enable_paging", "false") == "true": paging = { "page_number": int(request.REQUEST.get("page_number", 0)), "page_size": int(request.REQUEST.get("page_size", 0)), } except ValueError: # pylint: disable=too-many-format-args return HttpResponse( content="Couldn't parse paging parameters: enable_paging: " "{0}, page_number: {1}, page_size: {2}".format( request.REQUEST.get("enable_paging", "false"), request.REQUEST.get("page_number", 0), request.REQUEST.get("page_size", 0), ), status=400, content_type="text/plain", ) force_render = request.REQUEST.get("force_render", None) # Set up the context to be passed to each XBlock's render method. context = { "is_pages_view": is_pages_view, # This setting disables the recursive wrapping of xblocks "is_unit_page": is_unit(xblock), "can_edit": can_edit, "root_xblock": xblock if (view_name == "container_preview") else None, "reorderable_items": reorderable_items, "paging": paging, "force_render": force_render, } fragment = get_preview_fragment(request, xblock, context) # Note that the container view recursively adds headers into the preview fragment, # so only the "Pages" view requires that this extra wrapper be included. if is_pages_view: fragment.content = render_to_string( "component.html", { "xblock_context": context, "xblock": xblock, "locator": usage_key, "preview": fragment.content, "label": xblock.display_name or xblock.scope_ids.block_type, }, ) else: raise Http404 hashed_resources = OrderedDict() for resource in fragment.resources: hashed_resources[hash_resource(resource)] = resource return JsonResponse({"html": fragment.content, "resources": hashed_resources.items()}) else: return HttpResponse(status=406)
def xblock_view_handler(request, usage_key_string, view_name): """ The restful handler for requests for rendered xblock views. Returns a json object containing two keys: html: The rendered html of the view resources: A list of tuples where the first element is the resource hash, and the second is the resource description """ usage_key = UsageKey.from_string(usage_key_string) if not has_course_access(request.user, usage_key.course_key): raise PermissionDenied() accept_header = request.META.get('HTTP_ACCEPT', 'application/json') if 'application/json' in accept_header: store = get_modulestore(usage_key) xblock = store.get_item(usage_key) is_read_only = _is_xblock_read_only(xblock) container_views = [ 'container_preview', 'reorderable_container_child_preview' ] unit_views = ['student_view'] # wrap the generated fragment in the xmodule_editor div so that the javascript # can bind to it correctly xblock.runtime.wrappers.append( partial(wrap_xblock, 'StudioRuntime', usage_id_serializer=unicode)) if view_name == 'studio_view': try: fragment = xblock.render('studio_view') # catch exceptions indiscriminately, since after this point they escape the # dungeon and surface as uneditable, unsaveable, and undeletable # component-goblins. except Exception as exc: # pylint: disable=w0703 log.debug("unable to render studio_view for %r", xblock, exc_info=True) fragment = Fragment( render_to_string('html_error.html', {'message': str(exc)})) # change not authored by requestor but by xblocks. store.update_item(xblock, None) elif view_name in (unit_views + container_views): is_container_view = (view_name in container_views) # Determine the items to be shown as reorderable. Note that the view # 'reorderable_container_child_preview' is only rendered for xblocks that # are being shown in a reorderable container, so the xblock is automatically # added to the list. reorderable_items = set() if view_name == 'reorderable_container_child_preview': reorderable_items.add(xblock.location) # Only show the new style HTML for the container view, i.e. for non-verticals # Note: this special case logic can be removed once the unit page is replaced # with the new container view. context = { 'runtime_type': 'studio', 'container_view': is_container_view, 'read_only': is_read_only, 'root_xblock': xblock if (view_name == 'container_preview') else None, 'reorderable_items': reorderable_items } fragment = get_preview_fragment(request, xblock, context) # For old-style pages (such as unit and static pages), wrap the preview with # the component div. Note that the container view recursively adds headers # into the preview fragment, so we don't want to add another header here. if not is_container_view: # For non-leaf xblocks, show the special rendering which links to the new container page. if xblock_has_own_studio_page(xblock): template = 'container_xblock_component.html' else: template = 'component.html' fragment.content = render_to_string( template, { 'xblock_context': context, 'xblock': xblock, 'locator': usage_key, 'preview': fragment.content, 'label': xblock.display_name or xblock.scope_ids.block_type, }) else: raise Http404 hashed_resources = OrderedDict() for resource in fragment.resources: hashed_resources[hash_resource(resource)] = resource return JsonResponse({ 'html': fragment.content, 'resources': hashed_resources.items() }) else: return HttpResponse(status=406)