def student_view(self, context=None): """ The primary view of the CodeSnippetXBlock, shown to students when viewing courses. """ frag = Fragment() frag.content = loader.render_django_template( 'templates/code_snippet.html', self._get_context()) frag.add_css(self.resource_string("static/css/code_snippet.css")) frag.add_css_url( "//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.3.2/styles/agate.min.css" ) logger.info("{}".format(self._get_context())) # Add i18n js statici18n_js_url = self._get_statici18n_js_url() if statici18n_js_url: frag.add_javascript_url( self.runtime.local_resource_url(self, statici18n_js_url)) frag.add_javascript( self.resource_string("static/js/src/code_snippet.js")) frag.add_javascript_url( "//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.3.2/highlight.min.js" ) frag.initialize_js('CodeSnippetXBlock', self._get_context()) return frag
def author_view(self, context=None): """ The primary view of the CLFClientXBlock, shown to students when viewing courses. """ frag = Fragment() clf_info = {} if (self.clfId != ''): status, clf_info = self.consume_service('getClf', {'clfId': self.clfId}) html_context = dict( self=self, clf_info=clf_info, back_icon=self.runtime.local_resource_url( self, 'static/icons/back-016.png'), ) frag.add_content( loader.render_template('templates/clfclient-author.html', html_context)) frag.add_css_url( "https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" ) frag.add_javascript( self.resource_string("static/js/src/clfclient-author.js")) frag.initialize_js('CLFClientXBlock') return frag
def student_view(self, context=None): """ Render student view for LMS. """ context = context or {} fragment = Fragment() render_context = self.student_view_data() if self.has_children: child_blocks_data = [] for child_usage_id in self.children: child_block = self.runtime.get_block(child_usage_id) if child_block: child_block_fragment = child_block.render( 'student_view', context) child_block_content = child_block_fragment.content fragment.add_fragment_resources(child_block_fragment) child_blocks_data.append({ 'content': child_block_content, 'display_name': child_block.display_name, }) render_context['child_blocks'] = child_blocks_data fragment.add_content( loader.render_template(self.student_view_template, render_context)) if self.css_resource_url: fragment.add_css_url( self.runtime.local_resource_url(self, self.css_resource_url)) return fragment
def student_view(self, context=None): name = getattr(self, "unmixed_class", self.__class__).__name__ template_path = f'templates/html/{name.lower()}.html' context = context.copy() if context else {} context['self'] = self context['custom_choices'] = self.custom_choices context['hide_header'] = context.get('hide_header', False) or not self.show_title fragment = Fragment( loader.render_django_template(template_path, context, i18n_service=self.i18n_service)) # If we use local_resource_url(self, ...) the runtime may insert many identical copies # of questionnaire.[css/js] into the DOM. So we use the mentoring block here if possible. block_with_resources = self.get_parent() from .mentoring import MentoringBlock # We use an inline import here to avoid a circular dependency with the .mentoring module. if not isinstance(block_with_resources, MentoringBlock): block_with_resources = self fragment.add_css_url( self.runtime.local_resource_url(block_with_resources, 'public/css/questionnaire.css')) fragment.add_javascript_url( self.runtime.local_resource_url(block_with_resources, 'public/js/questionnaire.js')) fragment.add_javascript(self.get_translation_content()) fragment.initialize_js(name) return fragment
def mentoring_view(self, context=None): """ Render this XBlock within a mentoring block. """ context = context.copy() if context else {} student_submissions_key = context.get('student_submissions_key') context['title'] = self.display_name context['description'] = self.description if student_submissions_key: location = self.location.replace( branch=None, version=None) # Standardize the key in case it isn't already target_key = { 'student_id': student_submissions_key, 'course_id': str(location.course_key), 'item_id': self.name, 'item_type': 'pb-answer', } submissions = sub_api.get_submissions(target_key, limit=1) try: context['student_input'] = submissions[0]['answer'] except IndexError: context['student_input'] = None else: context['student_input'] = self.student_input html = loader.render_django_template( 'templates/html/answer_read_only.html', context, i18n_service=self.i18n_service) fragment = Fragment(html) fragment.add_css_url( self.runtime.local_resource_url(self, self.css_path)) fragment.add_javascript_url( self.runtime.local_resource_url(self, 'public/js/answer_recap.js')) fragment.initialize_js('AnswerRecapBlock') return fragment
def student_view(self, context): """ Player view, displayed to the student """ fragment = Fragment() fragment.add_content( loader.render_django_template('/templates/html/drag_and_drop.html', i18n_service=self.i18n_service)) css_urls = ('public/css/drag_and_drop.css', ) js_urls = [ 'public/js/vendor/virtual-dom-1.3.0.min.js', 'public/js/drag_and_drop.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)) self.include_theme_files(fragment) fragment.initialize_js('DragAndDropBlock', self.student_view_data()) return fragment
def render_to_fragment(self, request, course_id=None, **kwargs): """ Render the calendar tab to a fragment. Args: request: The Django request. course_id: The id of the course. Returns: Fragment: The fragment representing the calendar tab. """ try: context = _create_base_calendar_view_context(request, course_id) log.debug(context) html = render_to_string('calendar_tab/calendar_tab_fragment.html', context) fragment = Fragment(html) fragment.add_css_url(VENDOR_CSS_URL) fragment.add_javascript_url(VENDOR_JS_URL) fragment.add_javascript_url(VENDOR_PLUGIN_JS_URL) fragment.add_javascript_url(JS_URL) inline_js = render_to_string( 'calendar_tab/calendar_tab_js.template', context) fragment.add_javascript(inline_js) return fragment except Exception as e: log.exception(e) html = render_to_string('calendar_tab/500_fragment.html') return Fragment(html)
def student_view(self, context): context['self'] = self fragment = Fragment() fragment.add_content( loader.render_django_template('templates/html/overlay.html', context)) fragment.add_css_url( self.runtime.local_resource_url(self, 'public/css/overlay.css')) return fragment
def student_view(self, context): context = context.copy() if context else {} fragment = Fragment() for child_id in self.children: child = self.runtime.get_block(child_id) # Child should be an instance of MentoringTableColumn child_frag = child.render('mentoring_view', context) fragment.add_fragment_resources(child_frag) context['allow_sharing'] = self.allow_sharing context['allow_download'] = self.allow_download user_service = self.runtime.service(self, 'user') if user_service: context['view_options'] = Share.objects.filter( shared_with__username=self.current_user_key, block_id=self.block_id, ).values_list('shared_by__username', flat=True) context['username'] = self.current_user_key share_notifications = Share.objects.filter( shared_with__username=self.current_user_key, notified=False, block_id=self.block_id, ).values_list('shared_by__username', flat=True) context['share_notifications'] = share_notifications and json.dumps(list(share_notifications)) if self.type: # Load an optional background image: context['bg_image_url'] = self.runtime.local_resource_url(self, f'public/img/{self.type}-bg.png') # Load an optional description for the background image, for accessibility try: context['bg_image_description'] = loader.load_unicode(f'static/text/table-{self.type}.txt') except OSError as e: if e.errno == errno.ENOENT: pass else: raise report_template = loader.render_django_template('templates/html/mentoring-table-report.html', { 'title': self.display_name, 'css': loader.load_unicode(AnswerRecapBlock.css_path) + loader.load_unicode(self.css_path), 'student_name': self._get_user_full_name(), 'course_name': self._get_course_name(), }) fragment.add_content(loader.render_django_template('templates/html/mentoring-table-container.html', context)) fragment.add_css_url(self.runtime.local_resource_url(self, 'public/css/mentoring-table.css')) fragment.add_javascript_url(self.runtime.local_resource_url(self, 'public/js/vendor/jquery-shorten.js')) fragment.add_javascript_url(self.runtime.local_resource_url(self, self.js_path)) fragment.initialize_js( 'MentoringTableBlock', { 'reportContentSelector': '.mentoring-table-container', 'reportTemplate': report_template, } ) return fragment
def _create_fragment(self, template, context_dict, initialize_js_func, additional_css=None, additional_js=None): """ Creates a fragment for display. """ fragment = Fragment(template.render(context_dict)) if additional_css is None: additional_css = [] if additional_js is None: additional_js = [] i18n_service = self.runtime.service(self, 'i18n') if hasattr(i18n_service, 'get_language_bidi') and i18n_service.get_language_bidi(): css_url = "static/css/openassessment-rtl.css" else: css_url = "static/css/openassessment-ltr.css" if settings.DEBUG: for css in additional_css: fragment.add_css_url(self.runtime.local_resource_url( self, css)) fragment.add_css_url(self.runtime.local_resource_url( self, css_url)) for js in additional_js: # pylint: disable=invalid-name self.add_javascript_files(fragment, js) self.add_javascript_files(fragment, "static/js/src/oa_shared.js") self.add_javascript_files(fragment, "static/js/src/oa_server.js") self.add_javascript_files(fragment, "static/js/src/lms") else: # TODO: load CSS and JavaScript as URLs once they can be served by the CDN for css in additional_css: fragment.add_css(load(css)) fragment.add_css(load(css_url)) # minified additional_js should be already included in 'make javascript' fragment.add_javascript( load("static/js/openassessment-lms.min.js")) js_context_dict = { "ALLOWED_IMAGE_MIME_TYPES": self.ALLOWED_IMAGE_MIME_TYPES, "ALLOWED_FILE_MIME_TYPES": self.ALLOWED_FILE_MIME_TYPES, "FILE_EXT_BLACK_LIST": self.FILE_EXT_BLACK_LIST, "FILE_TYPE_WHITE_LIST": self.white_listed_file_types, "MAXIMUM_FILE_UPLOAD_COUNT": self.MAX_FILES_COUNT, "TEAM_ASSIGNMENT": self.is_team_assignment() } fragment.initialize_js(initialize_js_func, js_context_dict) return fragment
def create_test_fragment(self): """ Creates a fragment for use in unit tests. """ fragment = Fragment() fragment.add_content(TEST_HTML) fragment.add_css(TEST_CSS) fragment.add_css_url(TEST_CSS_URL) fragment.add_javascript(TEST_JS) fragment.add_javascript_url(TEST_JS_URL) fragment.initialize_js(TEST_JS_INIT_FN, json_args=TEST_JSON_INIT_ARGS) return fragment
def student_view(self, context=None): """ The primary view of the GradedDiscussionXBlock, shown to students when viewing courses. """ frag = Fragment(LOADER.render_django_template("static/html/graded_discussion.html", self._get_context())) frag.add_css_url("https://cdnjs.cloudflare.com/ajax/libs/jquery-modal/0.9.1/jquery.modal.min.css") frag.add_css(self.resource_string("static/css/graded_discussion.css")) frag.add_javascript_url("https://cdnjs.cloudflare.com/ajax/libs/jquery-modal/0.9.1/jquery.modal.min.js") frag.add_javascript(self.resource_string("static/js/src/graded_discussion.js")) frag.initialize_js('GradedDiscussionXBlock') return frag
def _create_fragment( self, template, context_dict, initialize_js_func, additional_css=None, additional_js=None, additional_js_context=None ): """ Creates a fragment for display. """ fragment = Fragment(template.render(context_dict)) if additional_css is None: additional_css = [] if additional_js is None: additional_js = [] i18n_service = self.runtime.service(self, 'i18n') if hasattr(i18n_service, 'get_language_bidi') and i18n_service.get_language_bidi(): css_url = LoadStatic.get_url("openassessment-rtl.css") else: css_url = LoadStatic.get_url("openassessment-ltr.css") # TODO: load CSS and JavaScript as URLs once they can be served by the CDN for css in additional_css: fragment.add_css_url(css) fragment.add_css_url(css_url) # minified additional_js should be already included in 'make javascript' fragment.add_javascript_url(LoadStatic.get_url("openassessment-lms.js")) js_context_dict = { "ALLOWED_IMAGE_MIME_TYPES": self.ALLOWED_IMAGE_MIME_TYPES, "ALLOWED_FILE_MIME_TYPES": self.ALLOWED_FILE_MIME_TYPES, "FILE_EXT_BLACK_LIST": self.FILE_EXT_BLACK_LIST, "FILE_TYPE_WHITE_LIST": self.white_listed_file_types, "MAXIMUM_FILE_UPLOAD_COUNT": self.MAX_FILES_COUNT, "TEAM_ASSIGNMENT": self.is_team_assignment(), "AVAILABLE_EDITORS": AVAILABLE_EDITORS, "TEXT_RESPONSE_EDITOR": self.text_response_editor, } # If there's any additional data to be passed down to JS # include it in the context dict if additional_js_context: js_context_dict.update({"CONTEXT": additional_js_context}) fragment.initialize_js(initialize_js_func, js_context_dict) return fragment
def student_view(self, context=None): """ Student View """ context = context.copy() if context else {} context['hide_header'] = True context['self'] = self fragment = Fragment() fragment.add_content( loader.render_django_template('templates/html/plot.html', context)) fragment.add_css_url( self.runtime.local_resource_url(self, 'public/css/plot.css')) fragment.add_javascript_url( self.runtime.local_resource_url(self, 'public/js/vendor/d3.min.js')) fragment.add_javascript_url( self.runtime.local_resource_url(self, 'public/js/plot.js')) fragment.initialize_js('PlotBlock') return fragment
def student_view(self, context): fragment = Fragment() children_contents = [] context = context or {} context[ 'hide_prev_answer'] = True # For Step Builder, we don't show the users' old answers when they try again context['score_summary'] = self.get_score_summary() for child_id in self.children: child = self.runtime.get_block(child_id) if child is None: # child should not be None but it can happen due to bugs or permission issues child_content = f'<p>[{self._("Error: Unable to load child component.")}]</p>' else: child_fragment = self._render_child_fragment( child, context, view='mentoring_view') fragment.add_fragment_resources(child_fragment) child_content = child_fragment.content children_contents.append(child_content) fragment.add_content( loader.render_django_template( 'templates/html/mentoring_with_steps.html', { 'self': self, 'title': self.display_name, 'show_title': self.show_title, 'children_contents': children_contents, }, i18n_service=self.i18n_service)) fragment.add_css_url( self.runtime.local_resource_url(self, 'public/css/problem-builder.css')) fragment.add_javascript_url( self.runtime.local_resource_url( self, 'public/js/vendor/underscore-min.js')) fragment.add_javascript_url( self.runtime.local_resource_url(self, 'public/js/step_util.js')) fragment.add_javascript_url( self.runtime.local_resource_url( self, 'public/js/mentoring_with_steps.js')) fragment.initialize_js( 'MentoringWithStepsBlock', { 'show_extended_feedback': self.show_extended_feedback(), }) return fragment
def student_view(self, context=None): """View shown to students""" context = context.copy() if context else {} context["steps"] = self.steps fragment = Fragment() fragment.add_content( loader.render_template("templates/chat.html", context)) fragment.add_css_url( self.runtime.local_resource_url(self, "public/css/chat.css")) fragment.add_javascript_url( self.runtime.local_resource_url( self, "public/js/vendor/virtual-dom-1.3.0.min.js")) fragment.add_javascript(self.get_translation_content()) fragment.add_javascript_url( self.runtime.local_resource_url(self, "public/js/src/chat.js")) fragment.initialize_js("ChatXBlock", self._js_init_data()) return fragment
def view(self, context=None): """Provide default student view.""" frag = Fragment() child_frags = self.runtime.render_children(self, context=context) frag.add_resources(child_frags) frag.add_content(self.runtime.render_template("sequence.html", children=child_frags)) frag.add_css_url('http://code.jquery.com/ui/1.9.2/themes/base/jquery-ui.css') frag.add_javascript_url('http://ajax.googleapis.com/ajax/libs/jqueryui/1.9.2/jquery-ui.min.js') # mess things up frag.add_javascript(""" function Sequence(runtime, element) { $(element).children('.tabs').tabs(); }; """) frag.initialize_js('Sequence') return frag
def author_preview_view(self, context): context['self'] = self fragment = Fragment() fragment.add_content( loader.render_django_template('templates/html/plot_preview.html', context)) fragment.add_css_url( self.runtime.local_resource_url(self, 'public/css/plot-preview.css')) if self.overlay_ids: message = _( "In addition to the default and average overlays the plot includes the following overlays:" ) fragment.add_content(f'<p>{message}</p>') for overlay in self.overlays: overlay_fragment = self._render_child_fragment( overlay, context, view='mentoring_view') fragment.add_fragment_resources(overlay_fragment) fragment.add_content(overlay_fragment.content) return fragment
def mentoring_view(self, context=None): """ Render this XBlock within a mentoring block. """ context = context.copy() if context else {} context['answer_editable_id'] = uuid.uuid4().hex[:15] context['self'] = self context['hide_header'] = context.get('hide_header', False) or not self.show_title html = loader.render_django_template( 'templates/html/answer_editable.html', context, i18n_service=self.i18n_service) fragment = Fragment(html) fragment.add_css_url( self.runtime.local_resource_url(self, 'public/css/answer.css')) fragment.add_javascript_url( self.runtime.local_resource_url(self, 'public/js/answer.js')) fragment.add_javascript(self.get_translation_content()) fragment.initialize_js('AnswerBlock') return fragment
def student_view(self, context=None): """ Normal View """ if not self.user_is_staff(): return Fragment( '<p>This interface can only be used by course staff.</p>') block_choices = { self._('Multiple Choice Question'): 'MCQBlock', self._('Multiple Response Question'): 'MRQBlock', self._('Rating Question'): 'RatingBlock', self._('Long Answer'): 'AnswerBlock', } html = loader.render_django_template( 'templates/html/instructor_tool.html', { 'block_choices': block_choices, 'course_blocks_api': COURSE_BLOCKS_API, 'root_block_id': str(getattr(self.runtime, 'course_id', 'course_id')), }, i18n_service=self.i18n_service) fragment = Fragment(html) fragment.add_javascript(self.get_translation_content()) fragment.add_css_url( self.runtime.local_resource_url(self, 'public/css/instructor_tool.css')) fragment.add_javascript_url( self.runtime.local_resource_url(self, 'public/js/instructor_tool.js')) fragment.add_javascript_url( self.runtime.local_resource_url( self, 'public/js/vendor/underscore-min.js')) fragment.add_javascript_url( self.runtime.local_resource_url( self, 'public/js/vendor/backbone-min.js')) fragment.add_javascript_url( self.runtime.local_resource_url( self, 'public/js/vendor/backbone.paginator.min.js')) fragment.initialize_js('InstructorToolBlock') return fragment
def build_fragment( self, template='', context=None, css=None, js=None, js_init=None, ): """ Creates a fragment for display. """ context = context or {} css = css or [] js = js or [] rendered_template = '' if template: # pragma: no cover template = 'templates/' + template rendered_template = self.loader.render_django_template( template, context=context, i18n_service=self._i18n_service(), ) fragment = Fragment(rendered_template) for item in css: if item.startswith('/'): url = item fragment.add_css_url(url) else: item = '../public/' + item data = pkg_resources.resource_string(__name__, item) data = data.decode('utf8') fragment.add_css(data) for item in js: item = 'public/' + item url = self.runtime.local_resource_url(self, item) fragment.add_javascript_url(url) if js_init: # pragma: no cover fragment.initialize_js(js_init) return fragment
def build_fragment( self, path_html='', paths_css=None, paths_js=None, urls_css=None, urls_js=None, fragment_js=None, context=None, ): # pylint: disable=too-many-arguments """ Assemble the HTML, JS, and CSS for an XBlock fragment """ paths_css = paths_css or [] paths_js = paths_js or [] urls_css = urls_css or [] urls_js = urls_js or [] # If no context is provided, convert self.fields into a dict context = context or { key: getattr(self, key) for key in self.editable_fields } html_source = get_resource_string(path_html) html_source = html_source.format(**context) fragment = Fragment(html_source) for path in paths_css: url = self.get_resource_url(path) fragment.add_css_url(url) for path in paths_js: url = self.get_resource_url(path) fragment.add_javascript_url(url) for url in urls_css: fragment.add_css_url(url) for url in urls_js: fragment.add_javascript_url(url) if fragment_js: fragment.initialize_js(fragment_js) return fragment
def process(self, request, **kwargs): """ Render tab fragment. """ course = kwargs['course'] available_courses = [{ 'course_id': str(c.id), 'course_name': str(c.display_name), 'is_current': course == c, } for c in self.get_avalibel_courses(request.user)] enroll_info = { str(c.id): self.get_enroll_info(c) for c in self.get_avalibel_courses(request.user) } context = { 'course': course, 'enroll_info': json.dumps(enroll_info), 'available_courses': available_courses } html = render_to_string( 'rg_instructor_analytics/instructor_analytics_fragment.html', context) fragment = Fragment(html) fragment.add_javascript_url(JS_URL + 'Tab.js') fragment.add_javascript_url(JS_URL + 'TabHolder.js') fragment.add_javascript_url(JS_URL + 'CohortTab.js') fragment.add_javascript_url(JS_URL + 'EnrollmentTab.js') fragment.add_javascript_url(JS_URL + 'GradebookTab.js') fragment.add_javascript_url(JS_URL + 'ProblemTab.js') fragment.add_javascript_url(JS_URL + 'FunnelTab.js') fragment.add_javascript_url(JS_URL + 'Suggestion.js') fragment.add_javascript_url(JS_URL + 'Base.js') fragment.add_css_url(CSS_URL + 'instructor_analytics.css') return fragment
def build_fragment( self, template='', context=None, css=None, js=None, js_init=None, ): """ Creates a fragment for display. """ context = context or {} css = css or [] js = js or [] rendered_template = '' if template: # pragma: no cover template = 'templates/' + template rendered_template = self.loader.render_django_template( template, context=Context(context), i18n_service=self.runtime.service(self, 'i18n'), ) fragment = Fragment(rendered_template) for item in css: if item.startswith('/'): url = item else: item = 'public/' + item url = self.runtime.local_resource_url(self, item) fragment.add_css_url(url) for item in js: item = 'public/' + item url = self.runtime.local_resource_url(self, item) fragment.add_javascript_url(url) if js_init: # pragma: no cover fragment.initialize_js(js_init) return fragment
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': six.moves.urllib.parse.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 student_view(self, context): from .questionnaire import \ QuestionnaireAbstractBlock # Import here to avoid circular dependency # Migrate stored data if necessary self.migrate_fields() # Validate self.step: num_steps = len(self.steps) self.step = min(num_steps, self.step) fragment = Fragment() child_content = "" mcq_hide_previous_answer = self.get_option( 'pb_mcq_hide_previous_answer') for child_id in self.children: child = self.runtime.get_block(child_id) if child is None: # child should not be None but it can happen due to bugs or permission issues child_content += f'<p>[{self._("Error: Unable to load child component.")}]</p>' elif not isinstance(child, MentoringMessageBlock): try: if mcq_hide_previous_answer and isinstance( child, QuestionnaireAbstractBlock): context['hide_prev_answer'] = True else: context['hide_prev_answer'] = False child_fragment = child.render('mentoring_view', context) except NoSuchViewError: if child.scope_ids.block_type == 'html' and getattr( self.runtime, 'is_author_mode', False): # html block doesn't support mentoring_view, and if we use student_view Studio will wrap # it in HTML that we don't want in the preview. So just render its HTML directly: child_fragment = Fragment(child.data) else: child_fragment = child.render('student_view', context) fragment.add_fragment_resources(child_fragment) child_content += child_fragment.content fragment.add_content( loader.render_django_template('templates/html/mentoring.html', { 'self': self, 'title': self.display_name, 'show_title': self.show_title, 'child_content': child_content, 'missing_dependency_url': self.has_missing_dependency and self.next_step_url, }, i18n_service=self.i18n_service)) fragment.add_javascript(self.get_translation_content()) fragment.add_css_url( self.runtime.local_resource_url(self, 'public/css/problem-builder.css')) fragment.add_javascript_url( self.runtime.local_resource_url( self, 'public/js/vendor/underscore-min.js')) fragment.add_javascript_url( self.runtime.local_resource_url(self, 'public/js/util.js')) fragment.add_javascript_url( self.runtime.local_resource_url( self, 'public/js/mentoring_standard_view.js')) fragment.add_javascript_url( self.runtime.local_resource_url(self, 'public/js/mentoring.js')) # Workbench doesn't have font awesome, so add it: if WorkbenchRuntime and isinstance(self.runtime, WorkbenchRuntime): fragment.add_css_url( '//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css' ) fragment.initialize_js('MentoringBlock') if not self.display_submit: self.runtime.publish(self, 'progress', {}) return fragment
def student_view(self, context=None): # pylint: disable=unused-argument """ Standard view of this XBlock. """ if not self.mentoring_ids: return Fragment(f'<h1>{self.display_name}</h1><p>{_("Not configured.")}</p>') blocks = [] for mentoring_block in self.get_mentoring_blocks(self.mentoring_ids): if mentoring_block is None: continue block = { 'display_name': mentoring_block.display_name, 'mcqs': [] } try: hide_questions = self.exclude_questions.get(mentoring_block.url_name, []) except Exception: # pylint: disable=broad-except-clause log.exception("Cannot parse exclude_questions setting - probably malformed: %s", self.exclude_questions) hide_questions = [] for question_number, child_id in enumerate(self._get_problem_questions(mentoring_block), 1): try: if question_number in hide_questions: continue except TypeError: log.exception( "Cannot check question number - expected list of ints got: %s", hide_questions ) # Get the student's submitted answer to this MCQ from the submissions API: mcq_block = self.runtime.get_block(child_id) mcq_submission_key = self._get_submission_key(child_id) try: value = sub_api.get_submissions(mcq_submission_key, limit=1)[0]["answer"] except IndexError: value = None block['mcqs'].append({ "display_name": mcq_block.display_name_with_default, "value": value, "accessible_value": _("Score: {score}").format(score=value) if value else _("No value yet"), "color": self.color_for_value(value) if value is not None else None, }) # If the values are numeric, display an average: numeric_values = [ float(mcq['value']) for mcq in block['mcqs'] if mcq['value'] is not None and mcq['value'].isnumeric() ] if numeric_values: average_value = sum(numeric_values) / len(numeric_values) block['average'] = average_value # average block is shown only if average value exists, so accessible text for no data is not required block['accessible_average'] = _("Score: {score}").format( score=floatformat(average_value) ) block['average_label'] = self.average_labels.get(mentoring_block.url_name, _("Average")) block['has_average'] = True block['average_color'] = self.color_for_value(average_value) blocks.append(block) visual_repr = None if self.visual_rules: try: rules_parsed = json.loads(self.visual_rules) except ValueError: pass # JSON errors should be shown as part of validation else: visual_repr = DashboardVisualData( blocks, rules_parsed, self.color_for_value, self.visual_title, self.visual_desc ) report_template = loader.render_django_template('templates/html/dashboard_report.html', { 'title': self.display_name, 'css': loader.load_unicode(self.css_path), 'student_name': self._get_user_full_name(), 'course_name': self._get_course_name(), }) html = loader.render_django_template('templates/html/dashboard.html', { 'blocks': blocks, 'display_name': self.display_name, 'visual_repr': visual_repr, 'show_numbers': self.show_numbers, 'header_html': self.header_html, 'footer_html': self.footer_html, }) fragment = Fragment(html) fragment.add_css_url(self.runtime.local_resource_url(self, self.css_path)) fragment.add_javascript_url(self.runtime.local_resource_url(self, self.js_path)) fragment.initialize_js( 'PBDashboardBlock', { 'reportTemplate': report_template, 'reportContentSelector': '.dashboard-report' }) return fragment