def student_view(self, context): return Fragment()
def student_view(self, context=None): """ The primary view of the RecapXBlock seen in LMS """ blocks = [] for usage_key, xblock_type in self.get_blocks(self.xblock_list): block = self.runtime.get_block(usage_key) if hasattr(block, 'custom_report_format'): question = str(block.display_name) try: user = self.runtime.get_real_user(self.runtime.anonymous_student_id) except TypeError: user = None answer = block.custom_report_format( user=user, block=block, ) blocks.append((question, answer)) elif xblock_type == 'problem': answer = u"" question = u"" try: question = str(block.display_name) answer = self.get_submission(usage_key) if answer is None: answer = block.lcp.get_question_answer_text() blocks.append((question, answer)) except Exception as e: logger.warn(str(e)) answer = block.lcp.get_question_answer_text() blocks.append((question, answer)) layout = self.get_user_layout(blocks) idArray = self.scope_ids.usage_id._to_string().split('@') xblockId = idArray[len(idArray) - 1] context = { 'recap_answers_id': 'recap_answers_' + xblockId, 'recap_editor_id': 'recap_editor_' + xblockId, 'recap_cmd_id': 'recap_cmd_' + xblockId, 'blocks': blocks, 'layout': layout, 'allow_download': self.allow_download, 'download_text': self.download_text, } frag = Fragment( loader.render_django_template( "static/html/recap.html", context).format(self=self) ) if (self.css_file): frag.add_css(self.css_file) frag.add_css(self.resource_string("static/css/recap.css")) frag.add_javascript_url( self.runtime.local_resource_url( self, 'public/FileSaver.js/FileSaver.min.js' ) ) frag.add_javascript_url( self.runtime.local_resource_url( self, 'public/jsPDF-1.3.2/jspdf.min.js' ) ) frag.add_javascript_url( self.runtime.local_resource_url( self, 'public/jsPDF-1.3.2/html2canvas.min.js' ) ) frag.add_javascript_url( self.runtime.local_resource_url( self, 'public/jsPDF-1.3.2/html2pdf.js' ) ) frag.add_javascript(self.resource_string("static/js/src/recap.js")) frag.initialize_js('RecapXBlock', { 'recap_answers_id': 'recap_answers_' + xblockId, 'recap_editor_id': 'recap_editor_' + xblockId, 'recap_cmd_id': 'recap_cmd_' + xblockId, }) return frag
def student_view_aside(self, block, context): # pylint: disable=unused-argument """Add to the student view""" return Fragment(self.FRAG_CONTENT)
def fallback_view(self, view_name, context=None): # pylint: disable=W0613 """Provide a fallback view handler""" return Fragment(u"Hello, World!")
def student_view(self, context): if self.child is None: # raise error instead? In fact, could complain on descriptor load... return Fragment(content=u"<div>Nothing to randomize between</div>") return self.child.render(STUDENT_VIEW, context)
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: " "%s, page_number: %s, page_size: %s".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", ) # 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, } 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 student_view(self, _context=None): # pylint: disable=unused-argument """ The primary view of the RecommenderXBlock, shown to students when viewing courses. """ self.recommendations = (data_structure_upgrade(self.recommendations) or data_structure_upgrade( self.default_recommendations) or {}) # Transition between two versions. In the previous version, there is # no endorsed_recommendation_reasons. Thus, we add empty reasons to # make the length of the two lists equal # # TODO: Go through old lists of resources in course, and remove this # code. The migration should be done. while len(self.endorsed_recommendation_ids) > len( self.endorsed_recommendation_reasons): self.endorsed_recommendation_reasons.append('') global template_lookup if not template_lookup: self._init_template_lookup() # Ideally, we'd estimate score based on votes, such that items with # 1 vote have a sensible ranking (rather than a perfect rating) # We pre-generate URLs for all resources. We benchmarked doing this # for 44 URLs, and the time per URL was about 8ms. The 44 URLs were # all of the images added by students over several problem sets. If # load continues to be as-is, pre-generation is not a performance # issue. If students make substantially more resources, we may want # to paginate, and generate in sets of 5-20 URLs per load. resources = [{ 'id': r['id'], 'title': r['title'], "votes": r['upvotes'] - r['downvotes'], 'url': r['url'], 'description': self._get_onetime_url(r['description']), 'descriptionText': r['descriptionText'] } for r in self.recommendations.values()] resources = sorted(resources, key=lambda r: r['votes'], reverse=True) frag = Fragment( template_lookup.get_template("recommender.html").render( resources=resources, upvoted_ids=self.upvoted_ids, downvoted_ids=self.downvoted_ids, endorsed_recommendation_ids=self.endorsed_recommendation_ids, endorsed_recommendation_reasons=self. endorsed_recommendation_reasons, flagged_ids=self.flagged_ids, flagged_reasons=self.flagged_reasons)) frag.add_css_url( "//ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/themes/smoothness/jquery-ui.css" ) frag.add_javascript_url( "//ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/jquery-ui.min.js") frag.add_javascript_url( '//cdnjs.cloudflare.com/ajax/libs/mustache.js/0.8.1/mustache.min.js' ) frag.add_javascript_url( '//cdnjs.cloudflare.com/ajax/libs/intro.js/0.5.0/intro.min.js') frag.add_css(self.resource_string("static/css/tooltipster.css")) frag.add_css(self.resource_string("static/css/recommender.css")) frag.add_css(self.resource_string("static/css/introjs.css")) frag.add_javascript( self.resource_string("static/js/src/jquery.tooltipster.min.js")) frag.add_javascript(self.resource_string("static/js/src/cats.js")) frag.add_javascript( self.resource_string("static/js/src/recommender.js")) frag.initialize_js('RecommenderXBlock', self.get_client_configuration()) return frag
def student_view(self, context=None): """ The primary view of the FeedbackXBlock, shown to students when viewing courses. """ # Figure out which prompt we show. We set self.prompt_choice to # the index of the prompt. We set it if it is out of range (either # uninitiailized, or incorrect due to changing list length). Then, # we grab the prompt, prepopulated with defaults. if self.prompt_choice < 0 or self.prompt_choice >= len(self.prompts): self.prompt_choice = random.randint(0, len(self.prompts) - 1) prompt = self.get_prompt() # Now, we render the FeedbackXBlock. html = self.resource_string("static/html/feedback.html") # Staff see vote totals, so we have slightly different HTML here. if self.vote_aggregate and self.is_staff(): scale_item = self.resource_string("static/html/staff_item.html") else: scale_item = self.resource_string("static/html/scale_item.html") # The replace allows us to format the HTML nicely without getting # extra whitespace scale_item = scale_item.replace('\n', '') # We have five Likert fields right now, but we'd like this to # be dynamic indexes = range(5) # If the user voted before, we'd like to show that active_vote = ["checked" if i == self.user_vote else "" for i in indexes] # Confirm that we do have vote totals (this may be uninitialized # otherwise). This should probably go into __init__ or similar. self.init_vote_aggregate() votes = self.vote_aggregate # We grab the icons. This should move to a Filesystem field so # instructors can upload new ones def get_url(icon_type, i): ''' Helper function to generate the URL for the icons shown in the tool. Takes the type of icon (active, inactive, etc.) and the number of the icon. Note that some icon types may not be actively used in the styling. For example, at the time of this writing, we do selected through CSS, rather than by using those icons. ''' templates = {'inactive': 'public/default_icons/i{set}{i}.png', 'active': 'public/default_icons/a{set}{i}.png', 'selected': 'public/default_icons/s{set}{i}.png'} template = templates[icon_type] icon_file = template.format(i=i, set=prompt['icon_set']) return self.runtime.local_resource_url(self, icon_file) ina_urls = [get_url('inactive', i) for i in range(1, 6)] act_urls = [get_url('active', i) for i in range(1, 6)] sel_urls = [get_url('selected', i) for i in range(1, 6)] # Render the Likert scale (not the whole page) scale = u"".join( scale_item.format(scale_text=scale_text, unicode_icon=unicode_icon, idx=idx, active=active, vote_cnt=vote_cnt, ina_icon=ina_icon, act_icon=act_icon, sel_icon=sel_icon) for (scale_text, unicode_icon, idx, active, vote_cnt, act_icon, ina_icon, sel_icon) in zip(prompt['scale_text'], ICON_SETS[(prompt['icon_set'])], indexes, active_vote, votes, act_urls, ina_urls, sel_urls) ) if self.user_vote != -1: _ = self.runtime.service(self, 'i18n').ugettext response = _("Thank you for voting!") else: response = "" # Now, render the whole page rendered = html.format(self=self, scale=scale, freeform_prompt=prompt['freeform'], likert_prompt=prompt['likert'], response=response, placeholder=prompt['placeholder']) # We initialize self.p_user if not initialized -- this sets whether # or not we show it. From there, if it is less than odds of showing, # we set the fragment to the rendered XBlock. Otherwise, we return # empty HTML. There ought to be a way to return None, but XBlocks # doesn't support that. if self.p_user == -1: self.p_user = random.uniform(0, 100) if self.p_user < self.p: frag = Fragment(rendered) else: frag = Fragment(u"") # Finally, we do the standard JS+CSS boilerplate. Honestly, XBlocks # ought to have a sane default here. frag.add_css(self.resource_string("static/css/feedback.css")) frag.add_javascript(self.resource_string("static/js/src/feedback.js")) frag.initialize_js('FeedbackXBlock') return frag
def student_view(self, context=None): # runtime error if not hasattr(self.runtime, "anonymous_student_id"): return self.message_view( "Error in uc_docker (get anonymous student id)", "Cannot get anonymous_student_id in runtime", context) # preview in studio if self.runtime.anonymous_student_id == "student": result, message = GitLabUtil.get_user_projects( self.git_host, self.git_port, self.git_teacher_token) if not result: return self.message_view( "Error in uc_docker (get git projects)", "Cannot get user's projects in git", context) context_dict = {"labs": self.labs, "message": ""} fragment = Fragment() fragment.add_content( Util.render_template('static/html/uc_lab.html', context_dict)) fragment.add_css(Util.load_resource("static/css/uc_docker.css")) fragment.add_javascript( Util.load_resource("static/js/src/uc_lab.js")) fragment.initialize_js("UcDockerXBlock") return fragment return # student view in open-edx if self.is_new: # create git account when first visiting student = self.runtime.get_real_user( self.runtime.anonymous_student_id) email = student.email name = student.first_name + " " + student.last_name username = student.username self.git_password = Util.create_random_password() self.save() # first_name, last_name are empty if name == " ": name = username self.logger.info("password is " + self.git_password) # create ldap account l = ldap.initialize(self.ldap_url) l.bind(self.principal_name, self.ldap_password) dn = "uid=" + username + "," + self.base_dn attrs = {} attrs['objectclass'] = ['top', 'inetOrgPerson', 'eduPerson'] attrs['cn'] = str(username) attrs['sn'] = str(username) attrs['givenName'] = str(username) attrs['uid'] = str(username) attrs['userPassword'] = str(self.git_password) attrs['description'] = 'ldap user for shibboleth' attrs['eduPersonPrincipalName'] = str(email) attrs['mail'] = str(email) # Convert our dict to nice syntax for the add-function using modlist-module ldif = modlist.addModlist(attrs) l.add_s(dn, ldif) l.unbind_s() self.logger.info("create ldap account " + username + "," + dn) self.logger.info(self.git_host + "," + str(self.git_port) + "," + self.git_admin_token + "," + name + "," + username + "," + email + "," + self.git_password) result, message = GitLabUtil.create_account( self.git_host, self.git_port, self.git_admin_token, name, username, email, self.git_password) self.logger.info("create_account result:") self.logger.info(result) self.logger.info(message) if not result: return self.message_view( "Error in uc_docker (create git account)", message, context) result, message = GitLabUtil.login(self.git_host, self.git_port, username, self.git_password) self.logger.info("login result:") self.logger.info(result) self.logger.info(message) if not result: return self.message_view( "Error in uc_docker (login git account)", message, context) try: message = json.loads(message) self.git_id = message["id"] self.git_user_token = message["private_token"] self.save() except Exception, ex: return self.message_view( "Error in uc_docker (load json string)", message, context) try: self.private_key, self.public_key = Util.gen_ssh_keys(email) self.logger.info("private_key:" + self.private_key) self.save() conn = pymongo.Connection('localhost', 27017) db = conn.test db.authenticate(self.mongo_pwd, self.mongo_pwd) token = db.token token.insert({ "username": username, "token": message["private_token"], "password": self.git_password, "private_key": self.private_key, "public_key": self.public_key }) conn.disconnect() except Exception, ex: return self.message_view("Error in uc_docker (gen ssh key)", ex, context)
def get_frag(self, **context): # pylint: disable=unused-argument """ Return a Fragment required to render video player on the client side. """ return Fragment(u'[Here be Video]')
def student_view(self, context): """ The primary view for the students """ # Setup data to claim a badge self.n_user_id = self.get_student_id() self.claim_db_user_data = self.DB_get_user_data() self.claim_db_user_id = self.claim_db_user_data[0] self.claim_db_user_course = self.claim_db_user_data[1] self.claim_db_user_name = self.claim_db_user_data[2] self.claim_db_user_email = self.claim_db_user_data[3] self.claim_db_user_score = self.claim_db_user_data[4] self.claim_db_problems_lists = self.claim_db_user_data[5] self.claim_db_problems_total_score = self.claim_db_user_data[6] self.claim_db_problems_partial_score = self.claim_db_user_data[7] self.claim_db_problems_percent_score = self.claim_db_user_data[8] self.claim_db_badge_problems_score = self.claim_db_user_data[9] self.user_score = self.claim_db_user_data[4] claim_name = self.claim_db_user_name claim_mail = self.claim_db_user_email self.claim_badge_errors = self.claim_badge_errors self.claim_badge_form = '' self.check_earned = '' self.preview_badge = '' # Check out provider badge data if self.claim_badge_errors == "": self.claim_prov_access_token = self.iblclient.get_auth_token(self.claim_prov_usr, self.claim_prov_pwd) if self.claim_prov_access_token !="": badge_info = self.iblclient.get_badge_data(self.claim_prov_access_token,self.bg_id,'info') badge_params = self.iblclient.get_badge_data(self.claim_prov_access_token,self.bg_id,'params') obj_badge = self.iblclient.create_obj_badge(badge_info,badge_params) self.check_earned = self.iblclient.check_earn_badge(self.claim_prov_access_token,self.claim_db_user_email,self.bg_id) self.preview_badge = self.iblclient.build_badge_preview(obj_badge) if obj_badge : # check if user has been awarded yet if self.check_earned!='': self.award_earn_prov = self.iblclient.get_award_result ( self.check_earned ) self.award_earned = self.iblclient.get_award_result_formatted(self.award_earn_prov,self.congratulations_text) else: self.claim_badge_form = self.iblclient.build_badge_form(self.claim_db_user_name,self.claim_db_user_email,self.form_text,obj_badge) else: self.claim_badge_errors = 'Could not retrieve the information associated with the Badge ID selected. Please, verify your data.' else: self.claim_badge_errors = 'Could not connect to provider. Please, verify your credentials.' # Initialize html view self.claim_data = "" if self.claim_badge_errors == "": if self.debug_mode == "1": html = self.resource_string("static/html/debug.html") else: if int(self.user_score) < int(self.required_score): html = self.resource_string("static/html/student_view_noscore.html") else: if self.check_earned!='': html = self.resource_string("static/html/student_view_earn_badge.html") else: html = self.resource_string("static/html/student_view_claim_badge.html") frag = Fragment(html.format(self=self)) frag.add_css(self.resource_string("static/css/style.css")) if self.check_earned =='': frag.add_javascript(self.resource_string("static/js/src/student_view_scripts.js")) frag.initialize_js('StudentViewBadge') else: if self.debug_mode == "1": html = self.resource_string("static/html/result_errors_debug.html") else: html = self.resource_string("static/html/result_errors.html") frag = Fragment(html.format(self=self)) frag.add_css(self.resource_string("static/css/style.css")) return frag
def student_view(self, context): # If we're rendering this sequence, but no position is set yet, # default the position to the first element if self.position is None: self.position = 1 ## Returns a set of all types of all sub-children contents = [] fragment = Fragment() context = context or {} bookmarks_service = self.runtime.service(self, "bookmarks") context["username"] = self.runtime.service( self, "user").get_current_user().opt_attrs['edx-platform.username'] display_names = [ self.get_parent().display_name or '', self.display_name or '' ] # Is this sequential part of a timed or proctored exam? if self.is_time_limited: view_html = self._time_limited_student_view(context) # Do we have an alternate rendering # from the edx_proctoring subsystem? if view_html: fragment.add_content(view_html) return fragment for child in self.get_display_items(): is_bookmarked = bookmarks_service.is_bookmarked( usage_key=child.scope_ids.usage_id) context["bookmarked"] = is_bookmarked progress = child.get_progress() rendered_child = child.render(STUDENT_VIEW, context) fragment.add_frag_resources(rendered_child) # `titles` is a list of titles to inject into the sequential tooltip display. # We omit any blank titles to avoid blank lines in the tooltip display. titles = [ title.strip() for title in child.get_content_titles() if title.strip() ] childinfo = { 'content': rendered_child.content, 'title': "\n".join(titles), 'page_title': titles[0] if titles else '', 'progress_status': Progress.to_js_status_str(progress), 'progress_detail': Progress.to_js_detail_str(progress), 'type': child.get_icon_class(), 'id': child.scope_ids.usage_id.to_deprecated_string(), 'bookmarked': is_bookmarked, 'path': " > ".join(display_names + [child.display_name or '']), } if childinfo['title'] == '': childinfo['title'] = child.display_name_with_default_escaped contents.append(childinfo) params = { 'items': contents, 'element_id': self.location.html_id(), 'item_id': self.location.to_deprecated_string(), 'position': self.position, 'tag': self.location.category, 'ajax_url': self.system.ajax_url, } fragment.add_content( self.system.render_template("seq_module.html", params)) return fragment
def student_view(self, context=None, authoring=False): scheme = 'https' if settings.HTTPS == 'on' else 'http' lms_base = settings.ENV_TOKENS.get('LMS_BASE') if isinstance(context, QueryDict): context = context.dict() if microsite.is_request_in_microsite(): subdomain = microsite.get_value( "domain_prefix", None) or microsite.get_value('microsite_config_key') lms_base = "{}.{}".format(subdomain, lms_base) scorm_player_url = "" course_directory = self.scorm_file if self.scorm_player == 'SCORM_PKG_INTERNAL': # TODO: support initial filename other than index.html for internal players scorm_player_url = '{}://{}{}'.format(scheme, lms_base, self.scorm_file) elif self.scorm_player: player_config = DEFINED_PLAYERS[self.scorm_player] player = player_config['location'] if '://' in player: scorm_player_url = player else: scorm_player_url = '{}://{}{}'.format(scheme, lms_base, player) course_directory = '{}://{}{}'.format( scheme, lms_base, self.runtime.handler_url(self, "proxy_content")) html = self.resource_string("static/html/scormxblock.html") # don't call handlers if student_view is not called from within LMS # (not really a student) if not authoring: get_url = '{}://{}{}'.format( scheme, lms_base, self.runtime.handler_url(self, "get_raw_scorm_status")) set_url = '{}://{}{}'.format( scheme, lms_base, self.runtime.handler_url(self, "set_raw_scorm_status")) get_completion_url = '{}://{}{}'.format( scheme, lms_base, self.runtime.handler_url(self, "get_scorm_completion")) # PreviewModuleSystem (runtime Mixin from Studio) won't have a hostname else: # we don't want to get/set SCORM status from preview get_url = set_url = get_completion_url = '#' # if display type is popup, don't use the full window width for the host iframe iframe_width = self.display_type == 'popup' and DEFAULT_IFRAME_WIDTH or self.display_width iframe_height = self.display_type == 'popup' and DEFAULT_IFRAME_HEIGHT or self.display_height show_popup_manually = True if self.display_type == 'popup' and self.popup_launch_type == 'manual' else False lock_next_module = self.is_next_module_locked and self.scorm_progress < constants.MAX_PROGRESS_VALUE try: player_config = json.loads(self.player_configuration) except ValueError: player_config = {} frag = Fragment() frag.add_content( MakoTemplate(text=html.format( self=self, scorm_player_url=scorm_player_url, get_url=get_url, set_url=set_url, get_completion_url=get_completion_url, iframe_width=iframe_width, iframe_height=iframe_height, player_config=player_config, show_popup_manually=show_popup_manually, scorm_file=course_directory, is_next_module_locked=lock_next_module)).render_unicode()) frag.add_css(self.resource_string("static/css/scormxblock.css")) context['block_id'] = self.url_name js = self.resource_string("static/js/src/scormxblock.js") jsfrag = MakoTemplate(js).render_unicode(**context) frag.add_javascript(jsfrag) # TODO: this will only work to display staff debug info if 'scormxblock' is one of the # categories of blocks that are specified in lms/templates/staff_problem_info.html so this will # for now have to be overridden in theme or directly in edx-platform # TODO: is there another way to approach this? key's location.category isn't mutable to spoof 'problem', # like setting the name in the entry point to 'problem'. Doesn't seem like a good idea. Better to # have 'staff debuggable' categories configurable in settings or have an XBlock declare itself staff debuggable if SCORM_DISPLAY_STAFF_DEBUG_INFO and not authoring: # don't show for author preview from courseware.access import has_access from courseware.courses import get_course_by_id course = get_course_by_id(self.xmodule_runtime.course_id) dj_user = self.xmodule_runtime._services['user']._django_user has_instructor_access = bool( has_access(dj_user, 'instructor', course)) if has_instructor_access: disable_staff_debug_info = settings.FEATURES.get( 'DISPLAY_DEBUG_INFO_TO_STAFF', True) and False or True block = self view = 'student_view' frag = add_staff_markup(dj_user, has_instructor_access, disable_staff_debug_info, block, view, frag, context) frag.initialize_js('ScormXBlock_{0}'.format(context['block_id'])) return frag
def author_view(self, context=None): html = self.render_template("static/html/author_view.html", context) frag = Fragment(html) return frag
def student_view(self, context=None): # runtime error if not hasattr(self.runtime, "anonymous_student_id"): return self.message_view( "Error in uc_docker (get anonymous student id)", "Cannot get anonymous_student_id in runtime", context) # preview in studio if self.runtime.anonymous_student_id == "student": result, message = GitLabUtil.get_user_projects( self.git_host, self.git_port, self.git_teacher_token) if not result: return self.message_view( "Error in uc_docker (get git projects)", "Cannot get user's projects in git", context) context_dict = {"labs": self.labs, "message": ""} fragment = Fragment() fragment.add_content( Util.render_template('static/html/uc_lab.html', context_dict)) fragment.add_css(Util.load_resource("static/css/uc_docker.css")) fragment.add_javascript( Util.load_resource("static/js/src/uc_lab.js")) fragment.initialize_js("UcDockerXBlock") return fragment # student view in open-edx if self.is_new: # create git account when first visiting student = self.runtime.get_real_user( self.runtime.anonymous_student_id) email = student.email name = student.first_name + " " + student.last_name username = student.username self.git_password = Util.create_random_password() self.save() # first_name, last_name are empty if name == " ": name = username self.logger.info("password is " + self.git_password) self.logger.info(self.git_host + "," + str(self.git_port) + "," + self.git_admin_token + "," + name + "," + username + "," + email + "," + self.git_password) result, message = GitLabUtil.create_account( self.git_host, self.git_port, self.git_admin_token, name, username, email, self.git_password) self.logger.info("create_account result:") self.logger.info(result) self.logger.info(message) if not result: return self.message_view( "Error in uc_docker (create git account)", message, context) result, message = GitLabUtil.login(self.git_host, self.git_port, username, self.git_password) self.logger.info("login result:") self.logger.info(result) self.logger.info(message) if not result: return self.message_view( "Error in uc_docker (login git account)", message, context) try: message = json.loads(message) self.git_id = message["id"] self.git_user_token = message["private_token"] self.save() except Exception, ex: return self.message_view( "Error in uc_docker (load json string)", message, context) try: self.private_key, self.public_key = Util.gen_ssh_keys(email) self.logger.info("private_key:" + self.private_key) self.save() conn = pymongo.Connection('192.168.122.183', 27017) db = conn.test token = db.token token.insert({ "username": username, "token": message["private_token"], "password": self.git_password, "private_key": self.private_key, "public_key": self.public_key }) conn.disconnect() except Exception, ex: return self.message_view("Error in uc_docker (gen ssh key)", ex, context)
def student_view(self, context): """ Render a student view with context """ self.register_context(context) return Fragment()
def student_view(self, context): display_items = self.get_display_items() # If we're rendering this sequence, but no position is set yet, # or exceeds the length of the displayable items, # default the position to the first element if context.get('requested_child') == 'first': self.position = 1 elif context.get('requested_child') == 'last': self.position = len(display_items) or None elif self.position is None or self.position > len(display_items): self.position = 1 ## Returns a set of all types of all sub-children contents = [] fragment = Fragment() context = context or {} bookmarks_service = self.runtime.service(self, "bookmarks") context["username"] = self.runtime.service( self, "user").get_current_user().opt_attrs['edx-platform.username'] parent_module = self.get_parent() display_names = [ parent_module.display_name_with_default, self.display_name_with_default ] # We do this up here because proctored exam functionality could bypass # rendering after this section. self._capture_basic_metrics() # Is this sequential part of a timed or proctored exam? if self.is_time_limited: view_html = self._time_limited_student_view(context) # Do we have an alternate rendering # from the edx_proctoring subsystem? if view_html: fragment.add_content(view_html) return fragment for child in display_items: is_bookmarked = bookmarks_service.is_bookmarked( usage_key=child.scope_ids.usage_id) context["bookmarked"] = is_bookmarked progress = child.get_progress() rendered_child = child.render(STUDENT_VIEW, context) fragment.add_frag_resources(rendered_child) # `titles` is a list of titles to inject into the sequential tooltip display. # We omit any blank titles to avoid blank lines in the tooltip display. titles = [ title.strip() for title in child.get_content_titles() if title.strip() ] childinfo = { 'content': rendered_child.content, 'title': "\n".join(titles), 'page_title': titles[0] if titles else '', 'progress_status': Progress.to_js_status_str(progress), 'progress_detail': Progress.to_js_detail_str(progress), 'type': child.get_icon_class(), 'id': child.scope_ids.usage_id.to_deprecated_string(), 'bookmarked': is_bookmarked, 'path': " > ".join(display_names + [child.display_name_with_default]), } if childinfo['title'] == '': childinfo['title'] = child.display_name_with_default_escaped contents.append(childinfo) params = { 'items': contents, 'element_id': self.location.html_id(), 'item_id': self.location.to_deprecated_string(), 'position': self.position, 'tag': self.location.category, 'ajax_url': self.system.ajax_url, 'next_url': _compute_next_url( self.location, parent_module, context.get('redirect_url_func'), ), 'prev_url': _compute_previous_url( self.location, parent_module, context.get('redirect_url_func'), ), } fragment.add_content( self.system.render_template("seq_module.html", params)) self._capture_full_seq_item_metrics(display_items) self._capture_current_unit_metrics(display_items) # Get all descendant XBlock types and counts return fragment
def student_view(self, context=None): # pylint: disable=W0613 """A view, with the default name.""" return Fragment(u"This is student view!")
def studio_view(self, context): """ Editing view in Studio """ js_templates = loader.load_unicode('/templates/html/js_templates.html') # Get an 'id_suffix' string that is unique for this block. # We append it to HTML element ID attributes to ensure multiple instances of the DnDv2 block # on the same page don't share the same ID value. # We avoid using ID attributes in preference to classes, but sometimes we still need IDs to # connect 'for' and 'aria-describedby' attributes to the associated elements. id_suffix = self._get_block_id() js_templates = js_templates.replace('{{id_suffix}}', id_suffix) context = { 'js_templates': js_templates, 'id_suffix': id_suffix, 'fields': self.fields, 'self': self, 'data': urllib.quote(json.dumps(self.data)), } fragment = Fragment() fragment.add_content( loader.render_django_template( '/templates/html/drag_and_drop_edit.html', context=context, i18n_service=self.i18n_service)) css_urls = ('public/css/drag_and_drop_edit.css', ) js_urls = [ 'public/js/vendor/handlebars-v1.1.2.js', 'public/js/drag_and_drop_edit.js', ] statici18n_js_url = self._get_statici18n_js_url() if statici18n_js_url: js_urls.append(statici18n_js_url) for css_url in css_urls: fragment.add_css_url(self.runtime.local_resource_url( self, css_url)) for js_url in js_urls: fragment.add_javascript_url( self.runtime.local_resource_url(self, js_url)) # Do a bit of manipulation so we get the appearance of a list of zone options on # items that still have just a single zone stored items = self.data.get('items', []) for item in items: zones = self.get_item_zones(item['id']) # Note that we appear to be mutating the state of the XBlock here, but because # the change won't be committed, we're actually just affecting the data that # we're going to send to the client, not what's saved in the backing store. item['zones'] = zones item.pop('zone', None) fragment.initialize_js( 'DragAndDropEditBlock', { 'data': self.data, 'target_img_expanded_url': self.target_img_expanded_url, 'default_background_image_url': self.default_background_image_url, }) return fragment
def another_view(self, context=None): # pylint: disable=W0613 """A secondary view for this block.""" return Fragment(u"This is another view!")
def fallback_view(self, _view_name, context=None): """Provide a fallback view handler""" context = context or {} return Fragment(Template(self.content).substitute(**context))
def student_view(self, context=None): # pylint: disable=W0613 """Provide the default view.""" body = u"The data: %r." % self.the_data body += u":::%s:::" % self.runtime.handler_url(self, "update_the_data") return Fragment(body)
def student_view(self, context): """ Player view, displayed to the student """ # Skin file path according to block type if hasattr(self, 'lightchild_block_type'): json_config_url = self.resource_url( OoyalaPlayerLightChildBlock.lightchild_block_type, SKIN_FILE_PATH) bit_movin_player_url = self.resource_url( OoyalaPlayerLightChildBlock.lightchild_block_type, BIT_MOVIN_PLAYER_PATH) else: json_config_url = self.resource_url(self.scope_ids.block_type, SKIN_FILE_PATH) bit_movin_player_url = self.resource_url(self.scope_ids.block_type, BIT_MOVIN_PLAYER_PATH) dom_id = 'ooyala-' + self._get_unique_id() overlay_fragments = "" for overlay in self.overlays: overlay_fragments += overlay.render() transcript = self.transcript.render(i18n_service=self.i18n_service) context = self.player_token() context.update({ 'title': self.display_name, 'cc_lang': self.cc_language_preference, 'cc_disabled': self.disable_cc_and_translations, 'pcode': self.pcode, 'content_id': self.content_id, 'player_id': self.player_id, 'dom_id': dom_id, 'overlay_fragments': overlay_fragments, 'transcript': transcript, 'width': self.width, 'height': self.height, 'autoplay': self.autoplay, 'config_url': json_config_url, 'complete_percentage': COMPLETION_VIDEO_COMPLETE_PERCENTAGE, 'bit_movin_player': bit_movin_player_url, }) JS_URLS = [ self.local_resource_url(self, 'public/build/player_all.min.js'), '//p3.3playmedia.com/p3sdk.current.js', ] CSS_URLS = [ self.local_resource_url(self, 'public/build/player_all.min.css'), ] fragment = Fragment() fragment.add_content( render_template('/templates/html/ooyala_player.html', context)) for url in JS_URLS: fragment.add_javascript_url(url) for url in CSS_URLS: fragment.add_css_url(url) fragment.initialize_js('OoyalaPlayerBlock') if self.fire_progress_event_on_student_view: # In certain cases we want to know when a student has visited a video player # as an indication that they are progressing through a course # Progress *does not* mean progress over viewing a video (i.e. elapsed time) self.runtime.publish(self, 'completion', {"completion": 1.0}) return fragment
def render_child_placeholder(self, block, view_name, context): """ Renders a placeholder XBlock. """ return self.wrap_xblock(block, view_name, Fragment(), context)
def student_view(self, context): """ Player view, displayed to the student """ xmltree = etree.fromstring(self.data) description = self._get_description(xmltree) hotspots = self._get_hotspots(xmltree) background = self._get_background(xmltree) has_youtube = False has_ooyala = False for hotspot in hotspots: width = 'width:{0}px'.format( hotspot.feedback.width ) if hotspot.feedback.width else 'width:300px' height = 'height:{0}px'.format( hotspot.feedback.height) if hotspot.feedback.height else '' max_height = '' if not hotspot.feedback.height: max_height = 'max-height:{0}px'.format(hotspot.feedback.max_height) if \ hotspot.feedback.max_height else 'max-height:300px' hotspot.reveal_style = 'style="{0};{1};{2}"'.format( width, height, max_height) if hotspot.feedback.youtube: has_youtube = True if hotspot.feedback.ooyala: has_ooyala = True context = { 'title': self.display_name, 'hotspot_coordinates_centered': self.hotspot_coordinates_centered, 'description_html': description, 'hotspots': hotspots, 'background': background, } fragment = Fragment() fragment.add_content( loader.render_django_template( '/templates/html/image_explorer.html', context=context, i18n_service=self.runtime.service(self, 'i18n'))) fragment.add_css_url( self.runtime.local_resource_url(self, 'public/css/image_explorer.css')) fragment.add_javascript_url( self.runtime.local_resource_url(self, 'public/js/image_explorer.js')) if has_youtube: fragment.add_javascript_url('https://www.youtube.com/iframe_api') if has_ooyala: fragment.add_javascript_url( 'https://player.ooyala.com/v3/635104fd644c4170ae227af2de27deab?platform=html5-priority' ) fragment.add_javascript_url( self.runtime.local_resource_url(self, 'public/js/ooyala_player.js')) fragment.initialize_js('ImageExplorerBlock') return fragment
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': 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 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
else: # TODO update git account student = self.runtime.get_real_user( self.runtime.anonymous_student_id) username = student.username print 'OK' context_dict = { "labs": self._get_available_labs(), "dockers": self.dockers, "password": self.git_password, "username": username, "message": "", "report": "" } fragment = Fragment() fragment.add_content( Util.render_template('static/html/uc_docker.html', context_dict)) fragment.add_css(Util.load_resource("static/css/uc_docker.css")) fragment.add_javascript( Util.load_resource("static/js/src/uc_docker.js")) fragment.initialize_js("UcDockerXBlock") return fragment def studio_view(self, context=None): # to add new lab context_dict = { "labs": self.labs, "docker_file": """FROM uclassroom/ucore-vnc-base MAINTAINER ggxx<*****@*****.**>
def index(request, course_id, chapter=None, section=None, position=None): """ Displays courseware accordion and associated content. If course, chapter, and section are all specified, renders the page, or returns an error if they are invalid. If section is not specified, displays the accordion opened to the right chapter. If neither chapter or section are specified, redirects to user's most recent chapter, or the first chapter if this is the user's first visit. Arguments: - request : HTTP request - course_id : course id (str: ORG/course/URL_NAME) - chapter : chapter url_name (str) - section : section url_name (str) - position : position in module, eg of <sequential> module (str) Returns: - HTTPresponse """ user = User.objects.prefetch_related("groups").get(id=request.user.id) request.user = user # keep just one instance of User course = get_course_with_access(user, course_id, 'load', depth=2) staff_access = has_access(user, course, 'staff') registered = registered_for_course(course, user) if not registered: # TODO (vshnayder): do course instructors need to be registered to see course? log.debug(u'User %s tried to view course %s but is not enrolled', user, course.location.url()) return redirect(reverse('about_course', args=[course.id])) masq = setup_masquerade(request, staff_access) try: field_data_cache = FieldDataCache.cache_for_descriptor_descendents( course.id, user, course, depth=2) course_module = get_module_for_descriptor(user, request, course, field_data_cache, course.id) if course_module is None: log.warning(u'If you see this, something went wrong: if we got this' u' far, should have gotten a course module for this user') return redirect(reverse('about_course', args=[course.id])) studio_url = get_studio_url(course_id, 'course') if chapter is None: return redirect_to_course_position(course_module) context = { 'csrf': csrf(request)['csrf_token'], 'accordion': render_accordion(request, course, chapter, section, field_data_cache), 'COURSE_TITLE': course.display_name_with_default, 'course': course, 'init': '', 'fragment': Fragment(), 'staff_access': staff_access, 'studio_url': studio_url, 'masquerade': masq, 'xqa_server': settings.FEATURES.get('USE_XQA_SERVER', 'http://*****:*****@content-qa.mitx.mit.edu/xqa'), 'reverifications': fetch_reverify_banner_info(request, course_id), } # Only show the chat if it's enabled by the course and in the # settings. show_chat = course.show_chat and settings.FEATURES['ENABLE_CHAT'] if show_chat: context['chat'] = chat_settings(course, user) # If we couldn't load the chat settings, then don't show # the widget in the courseware. if context['chat'] is None: show_chat = False context['show_chat'] = show_chat chapter_descriptor = course.get_child_by(lambda m: m.url_name == chapter) if chapter_descriptor is not None: save_child_position(course_module, chapter) else: raise Http404('No chapter descriptor found with name {}'.format(chapter)) chapter_module = course_module.get_child_by(lambda m: m.url_name == chapter) if chapter_module is None: # User may be trying to access a chapter that isn't live yet if masq == 'student': # if staff is masquerading as student be kinder, don't 404 log.debug('staff masq as student: no chapter %s' % chapter) return redirect(reverse('courseware', args=[course.id])) raise Http404 if section is not None: section_descriptor = chapter_descriptor.get_child_by(lambda m: m.url_name == section) if section_descriptor is None: # Specifically asked-for section doesn't exist if masq == 'student': # if staff is masquerading as student be kinder, don't 404 log.debug('staff masq as student: no section %s' % section) return redirect(reverse('courseware', args=[course.id])) raise Http404 # cdodge: this looks silly, but let's refetch the section_descriptor with depth=None # which will prefetch the children more efficiently than doing a recursive load section_descriptor = modulestore().get_instance(course.id, section_descriptor.location, depth=None) # Load all descendants of the section, because we're going to display its # html, which in general will need all of its children section_field_data_cache = FieldDataCache.cache_for_descriptor_descendents( course_id, user, section_descriptor, depth=None) section_module = get_module_for_descriptor( request.user, request, section_descriptor, section_field_data_cache, course_id, position ) if section_module is None: # User may be trying to be clever and access something # they don't have access to. raise Http404 # Save where we are in the chapter save_child_position(chapter_module, section) context['fragment'] = section_module.render('student_view') context['section_title'] = section_descriptor.display_name_with_default else: # section is none, so display a message studio_url = get_studio_url(course_id, 'course') prev_section = get_current_child(chapter_module) if prev_section is None: # Something went wrong -- perhaps this chapter has no sections visible to the user raise Http404 prev_section_url = reverse('courseware_section', kwargs={'course_id': course_id, 'chapter': chapter_descriptor.url_name, 'section': prev_section.url_name}) context['fragment'] = Fragment(content=render_to_string( 'courseware/welcome-back.html', { 'course': course, 'studio_url': studio_url, 'chapter_module': chapter_module, 'prev_section': prev_section, 'prev_section_url': prev_section_url } )) result = render_to_response('courseware/courseware.html', context) except Exception as e: if isinstance(e, Http404): # let it propagate raise # In production, don't want to let a 500 out for any reason if settings.DEBUG: raise else: log.exception( u"Error in index view: user={user}, course={course}, chapter={chapter}" u" section={section} position={position}".format( user=user, course=course, chapter=chapter, section=section, position=position )) try: result = render_to_response('courseware/courseware-error.html', { 'staff_access': staff_access, 'course': course }) except: # Let the exception propagate, relying on global config to at # at least return a nice error message log.exception("Error while rendering courseware-error page") raise 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/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, # 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)