示例#1
0
    def student_view(self, context):
        """
        Renders the normal student view of the block in the LMS.
        """
        _ = self.runtime.service(self, "i18n").ugettext
        context = context or {}
        self._capture_basic_metrics()
        banner_text = None
        prereq_met = True
        prereq_meta_info = {}
        if self._required_prereq():
            if self.runtime.user_is_staff:
                banner_text = _(
                    'This subsection is unlocked for learners when they meet the prerequisite requirements.'
                )
            else:
                # check if prerequisite has been met
                prereq_met, prereq_meta_info = self._compute_is_prereq_met(
                    True)
        if prereq_met:
            special_html_view = self._hidden_content_student_view(
                context) or self._special_exam_student_view()
            if special_html_view:
                masquerading_as_specific_student = context.get(
                    'specific_masquerade', False)
                banner_text, special_html = special_html_view
                if special_html and not masquerading_as_specific_student:
                    fragment = Fragment(special_html)
                    add_webpack_to_fragment(fragment, 'SequenceBlockPreview')
                    shim_xmodule_js(fragment, 'Sequence')
                    return fragment

        return self._student_or_public_view(context, prereq_met,
                                            prereq_meta_info, banner_text)
示例#2
0
    def _student_or_public_view(self,
                                context,
                                prereq_met,
                                prereq_meta_info,
                                banner_text=None,
                                view=STUDENT_VIEW):
        """
        Returns the rendered student view of the content of this
        sequential.  If banner_text is given, it is added to the
        content.
        """
        _ = self.runtime.service(self, "i18n").ugettext
        display_items = self.get_display_items()
        self._update_position(context, len(display_items))

        fragment = Fragment()
        params = self._get_render_metadata(context, display_items, prereq_met, prereq_meta_info, banner_text, view, fragment)  # lint-amnesty, pylint: disable=line-too-long
        if SHOW_PROGRESS_BAR.is_enabled() and getattr(
                settings, 'COMPLETION_AGGREGATOR_URL', ''):
            parent_block_id = self.get_parent().scope_ids.usage_id.block_id
            params['chapter_completion_aggregator_url'] = '/'.join([
                settings.COMPLETION_AGGREGATOR_URL,
                str(self.course_id), parent_block_id
            ]) + '/'
        fragment.add_content(
            self.runtime.service(self, 'mako').render_template(
                "seq_module.html", params))

        self._capture_full_seq_item_metrics(display_items)
        self._capture_current_unit_metrics(display_items)

        add_webpack_to_fragment(fragment, 'SequenceBlockPreview')
        shim_xmodule_js(fragment, 'Sequence')
        return fragment
示例#3
0
    def _student_or_public_view(self,
                                context,
                                prereq_met,
                                prereq_meta_info,
                                banner_text=None,
                                view=STUDENT_VIEW):
        """
        Returns the rendered student view of the content of this
        sequential.  If banner_text is given, it is added to the
        content.
        """
        _ = self.runtime.service(self, "i18n").ugettext
        display_items = self.get_display_items()
        self._update_position(context, len(display_items))

        fragment = Fragment()
        params = self._get_render_metadata(context, display_items, prereq_met, prereq_meta_info, banner_text, view, fragment)  # lint-amnesty, pylint: disable=line-too-long
        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)

        add_webpack_to_fragment(fragment, 'SequenceBlockPreview')
        shim_xmodule_js(fragment, 'Sequence')
        return fragment
示例#4
0
 def student_view(self, _context):
     """
     Return a fragment that contains the html for the student view
     """
     fragment = Fragment(self.get_html())
     add_webpack_to_fragment(fragment, 'HtmlBlockPreview')
     shim_xmodule_js(fragment, 'HTMLModule')
     return fragment
示例#5
0
 def student_view(self, _context):
     """
     Return the student view.
     """
     fragment = Fragment(self.get_html())
     add_webpack_to_fragment(fragment, 'VideoBlockPreview')
     shim_xmodule_js(fragment, 'Video')
     return fragment
示例#6
0
    def student_view(self, context):
        """
        Renders the student view of the block in the LMS.
        """
        fragment = Fragment()
        contents = []

        if context:
            child_context = copy(context)
        else:
            child_context = {}

        if 'bookmarked' not in child_context:
            bookmarks_service = self.runtime.service(self, 'bookmarks')
            child_context['bookmarked'] = bookmarks_service.is_bookmarked(usage_key=self.location),  # pylint: disable=no-member
        if 'username' not in child_context:
            user_service = self.runtime.service(self, 'user')
            child_context['username'] = user_service.get_current_user().opt_attrs['edx-platform.username']

        child_blocks = self.get_display_items()

        child_blocks_to_complete_on_view = set()
        completion_service = self.runtime.service(self, 'completion')
        if completion_service and completion_service.completion_tracking_enabled():
            child_blocks_to_complete_on_view = completion_service.blocks_to_mark_complete_on_view(child_blocks)
            complete_on_view_delay = completion_service.get_complete_on_view_delay_ms()

        child_context['child_of_vertical'] = True
        is_child_of_vertical = context.get('child_of_vertical', False)

        # pylint: disable=no-member
        for child in child_blocks:
            child_block_context = copy(child_context)
            if child in child_blocks_to_complete_on_view:
                child_block_context['wrap_xblock_data'] = {
                    'mark-completed-on-view-after-delay': complete_on_view_delay
                }
            rendered_child = child.render(STUDENT_VIEW, child_block_context)
            fragment.add_fragment_resources(rendered_child)

            contents.append({
                'id': six.text_type(child.location),
                'content': rendered_child.content
            })

        fragment.add_content(self.system.render_template('vert_module.html', {
            'items': contents,
            'xblock_context': context,
            'unit_title': self.display_name_with_default if not is_child_of_vertical else None,
            'show_bookmark_button': child_context.get('show_bookmark_button', not is_child_of_vertical),
            'bookmarked': child_context['bookmarked'],
            'bookmark_id': u"{},{}".format(child_context['username'], unicode(self.location)),  # pylint: disable=no-member
        }))

        add_webpack_to_fragment(fragment, 'VerticalStudentView')
        fragment.initialize_js('VerticalStudentView')

        return fragment
示例#7
0
 def student_view(self, _context):
     """
     Return the student view.
     """
     fragment = Fragment()
     fragment.add_content(self.runtime.service(self, 'mako').render_template('lti.html', self.get_context()))
     add_webpack_to_fragment(fragment, 'LTIBlockPreview')
     shim_xmodule_js(fragment, 'LTI')
     return fragment
 def student_view(self, _context):
     """
     Renders the student view.
     """
     fragment = Fragment()
     fragment.add_content(self.get_html())
     add_webpack_to_fragment(fragment, 'ConditionalBlockPreview')
     shim_xmodule_js(fragment, 'Conditional')
     return fragment
示例#9
0
    def student_view(self, context):
        """
        Renders the output that a student will see.
        """
        fragment = Fragment()
        fragment.add_content(self.get_html())
        add_webpack_to_fragment(fragment, 'AnnotatableBlockPreview')
        shim_xmodule_js(fragment, 'Annotatable')

        return fragment
示例#10
0
    def student_view(self, context):  # lint-amnesty, pylint: disable=unused-argument
        """
        Renders the output that a student will see.
        """
        fragment = Fragment()
        fragment.add_content(self.get_html())
        add_webpack_to_fragment(fragment, 'AnnotatableBlockPreview')
        shim_xmodule_js(fragment, 'Annotatable')

        return fragment
示例#11
0
 def studio_view(self, _context):
     """
     Return the studio view.
     """
     fragment = Fragment(
         self.runtime.service(self, 'mako').render_template(
             self.mako_template, self.get_context()))
     add_webpack_to_fragment(fragment, 'HtmlBlockStudio')
     shim_xmodule_js(fragment, 'HTMLEditingDescriptor')
     return fragment
示例#12
0
 def student_view(self, _context):
     """
     Return the student view.
     """
     # self.score is initialized in self.lcp but in this method is accessed before self.lcp so just call it first.
     self.lcp
     fragment = Fragment(self.get_html())
     add_webpack_to_fragment(fragment, 'ProblemBlockPreview')
     shim_xmodule_js(fragment, 'Problem')
     return fragment
示例#13
0
 def student_view(self, _context):
     """
     Return the student view.
     """
     # self.score is initialized in self.lcp but in this method is accessed before self.lcp so just call it first.
     self.lcp
     fragment = Fragment(self.get_html())
     add_webpack_to_fragment(fragment, 'ProblemBlockPreview')
     shim_xmodule_js(fragment, 'Problem')
     return fragment
示例#14
0
 def studio_view(self, _context):
     """
     Return the studio view.
     """
     fragment = Fragment(
         self.system.render_template(self.mako_template, self.get_context())
     )
     add_webpack_to_fragment(fragment, 'ProblemBlockStudio')
     shim_xmodule_js(fragment, 'MarkdownEditingDescriptor')
     return fragment
示例#15
0
 def student_view(self, _context):
     """
     Return a fragment that contains the html for the student view
     """
     fragment = Fragment(self.get_html())
     ## this line is a cutom change made during ironwood rebase
     fragment.add_javascript_url(settings.STATIC_URL + 'bundles/commons.js')
     add_webpack_to_fragment(fragment, 'HtmlBlockPreview')
     shim_xmodule_js(fragment, 'HTMLModule')
     return fragment
 def studio_view(self, _context):
     """
     Return the studio view.
     """
     fragment = Fragment(
         self.system.render_template(self.mako_template,
                                     self.get_context()))
     add_webpack_to_fragment(fragment, 'LibraryContentBlockStudio')
     shim_xmodule_js(fragment, self.studio_js_module_name)
     return fragment
示例#17
0
 def studio_view(self, _context):
     """
     Return the studio view.
     """
     fragment = Fragment(
         self.system.render_template(self.mako_template,
                                     self.get_context()))
     add_webpack_to_fragment(fragment, 'CustomTagBlockStudio')
     shim_xmodule_js(fragment, 'XMLEditingDescriptor')
     return fragment
示例#18
0
 def studio_view(self, _context):
     """
     Return the studio view.
     """
     fragment = Fragment(
         self.runtime.service(self, 'mako').render_template(self.mako_template, self.get_context())
     )
     add_webpack_to_fragment(fragment, 'WordCloudBlockStudio')
     shim_xmodule_js(fragment, self.studio_js_module_name)
     return fragment
示例#19
0
def _studio_wrap_xblock(xblock, view, frag, context, display_name_only=False):
    """
    Wraps the results of rendering an XBlock view in a div which adds a header and Studio action buttons.
    """
    # Only add the Studio wrapper when on the container page. The "Pages" page will remain as is for now.
    if not context.get('is_pages_view', None) and view in PREVIEW_VIEWS:
        root_xblock = context.get('root_xblock')
        is_root = root_xblock and xblock.location == root_xblock.location
        is_reorderable = _is_xblock_reorderable(xblock, context)
        selected_groups_label = get_visibility_partition_info(
            xblock)['selected_groups_label']
        if selected_groups_label:
            selected_groups_label = _('Access restricted to: {list_of_groups}').format(list_of_groups=selected_groups_label)  # lint-amnesty, pylint: disable=line-too-long
        course = modulestore().get_course(xblock.location.course_key)
        template_context = {
            'xblock_context':
            context,
            'xblock':
            xblock,
            'show_preview':
            context.get('show_preview', True),
            'content':
            frag.content,
            'is_root':
            is_root,
            'is_reorderable':
            is_reorderable,
            'can_edit':
            context.get('can_edit', True),
            'can_edit_visibility':
            context.get('can_edit_visibility',
                        xblock.scope_ids.usage_id.context_key.is_course),
            'selected_groups_label':
            selected_groups_label,
            'can_add':
            context.get('can_add', True),
            'can_move':
            context.get('can_move',
                        xblock.scope_ids.usage_id.context_key.is_course),
            'language':
            getattr(course, 'language', None)
        }

        if isinstance(xblock, (XModule, XModuleDescriptor)):
            # Add the webpackified asset tags
            class_name = getattr(xblock.__class__, 'unmixed_class',
                                 xblock.__class__).__name__
            add_webpack_to_fragment(frag, class_name)

        add_webpack_to_fragment(frag, "js/factories/xblock_validation")

        html = render_to_string('studio_xblock_wrapper.html', template_context)
        frag = wrap_fragment(frag, html)
    return frag
示例#20
0
 def studio_view(self, _context):
     """
     Return the studio view.
     """
     context = MakoTemplateBlockBase.get_context(self)
     # Add our specific template information (the raw data body)
     context.update({'data': self.data})
     fragment = Fragment(
         self.system.render_template(self.mako_template, context))
     add_webpack_to_fragment(fragment, 'LTIBlockStudio')
     shim_xmodule_js(fragment, self.studio_js_module_name)
     return fragment
示例#21
0
 def studio_view(self, context):
     """
     Return the studio view.
     """
     fragment = Fragment(
         self.system.render_template(self.mako_template,
                                     self.get_context()))
     # Use the SequenceDescriptor js for the metadata edit view.
     # Both the webpack bundle to include and the js class are named "SequenceDescriptor".
     add_webpack_to_fragment(fragment, SequenceDescriptor.js_module_name)
     shim_xmodule_js(fragment, SequenceDescriptor.js_module_name)
     return fragment
示例#22
0
 def student_view(self, _context, show_detailed_errors=False):
     """
     Return the student view.
     """
     # self.score is initialized in self.lcp but in this method is accessed before self.lcp so just call it first.
     try:
         self.lcp
     except Exception as err:
         html = self.handle_fatal_lcp_error(err if show_detailed_errors else None)
     else:
         html = self.get_html()
     fragment = Fragment(html)
     add_webpack_to_fragment(fragment, 'ProblemBlockPreview')
     shim_xmodule_js(fragment, 'Problem')
     return fragment
 def student_view(self, _context):
     """
     Renders the student view.
     """
     fragment = Fragment()
     params = {
         'element_id': self.location.html_id(),
         'element_class': self.location.block_type,
         'ajax_url': self.ajax_url,
         'configuration_json': self.dump_poll(),
     }
     fragment.add_content(self.system.render_template('poll.html', params))
     add_webpack_to_fragment(fragment, 'PollBlockPreview')
     shim_xmodule_js(fragment, 'Poll')
     return fragment
示例#24
0
    def student_view(self, context):  # lint-amnesty, pylint: disable=unused-argument
        """
        Renders the output that a student will see.
        """
        fragment = Fragment()
        fragment.add_content(self.runtime.service(self, 'mako').render_template('word_cloud.html', {
            'ajax_url': self.ajax_url,
            'display_name': self.display_name,
            'instructions': self.instructions,
            'element_class': self.location.block_type,
            'element_id': self.location.html_id(),
            'num_inputs': self.num_inputs,
            'submitted': self.submitted,
        }))
        add_webpack_to_fragment(fragment, 'WordCloudBlockPreview')
        shim_xmodule_js(fragment, 'WordCloud')

        return fragment
示例#25
0
    def student_view(self, context):
        """
        Renders the output that a student will see.
        """
        fragment = Fragment()
        fragment.add_content(self.system.render_template('word_cloud.html', {
            'ajax_url': self.ajax_url,
            'display_name': self.display_name,
            'instructions': self.instructions,
            'element_class': self.location.block_type,
            'element_id': self.location.html_id(),
            'num_inputs': self.num_inputs,
            'submitted': self.submitted,
        }))
        add_webpack_to_fragment(fragment, 'WordCloudBlockPreview')
        shim_xmodule_js(fragment, 'WordCloud')

        return fragment
示例#26
0
def _studio_wrap_xblock(xblock, view, frag, context, display_name_only=False):
    """
    Wraps the results of rendering an XBlock view in a div which adds a header and Studio action buttons.
    """
    # Only add the Studio wrapper when on the container page. The "Pages" page will remain as is for now.
    if not context.get('is_pages_view', None) and view in PREVIEW_VIEWS:
        root_xblock = context.get('root_xblock')
        is_root = root_xblock and xblock.location == root_xblock.location
        is_reorderable = _is_xblock_reorderable(xblock, context)
        selected_groups_label = get_visibility_partition_info(xblock)['selected_groups_label']
        if selected_groups_label:
            selected_groups_label = _(u'Access restricted to: {list_of_groups}').format(list_of_groups=selected_groups_label)
        course = modulestore().get_course(xblock.location.course_key)
        template_context = {
            'xblock_context': context,
            'xblock': xblock,
            'show_preview': context.get('show_preview', True),
            'content': frag.content,
            'is_root': is_root,
            'is_reorderable': is_reorderable,
            'can_edit': context.get('can_edit', True),
            'can_edit_visibility': context.get('can_edit_visibility', True),
            'selected_groups_label': selected_groups_label,
            'can_add': context.get('can_add', True),
            'can_move': context.get('can_move', True),
            'language': getattr(course, 'language', None)
        }

        if isinstance(xblock, (XModule, XModuleDescriptor)):
            # Add the webpackified asset tags
            class_name = getattr(xblock.__class__, 'unmixed_class', xblock.__class__).__name__
            add_webpack_to_fragment(frag, class_name)

        add_webpack_to_fragment(frag, "js/factories/xblock_validation")

        html = render_to_string('studio_xblock_wrapper.html', template_context)
        frag = wrap_fragment(frag, html)
    return frag
示例#27
0
    def _student_or_public_view(self, context, view):
        """
        Renders the requested view type of the block in the LMS.
        """
        fragment = Fragment()
        contents = []

        if context:
            child_context = copy(context)
        else:
            child_context = {}

        if view == STUDENT_VIEW:
            if 'bookmarked' not in child_context:
                bookmarks_service = self.runtime.service(self, 'bookmarks')
                child_context['bookmarked'] = bookmarks_service.is_bookmarked(
                    usage_key=self.location),  # lint-amnesty, pylint: disable=no-member, trailing-comma-tuple
            if 'username' not in child_context:
                user_service = self.runtime.service(self, 'user')
                child_context['username'] = user_service.get_current_user(
                ).opt_attrs.get('edx-platform.username')

        child_blocks = self.get_display_items()  # lint-amnesty, pylint: disable=no-member

        child_blocks_to_complete_on_view = set()
        completion_service = self.runtime.service(self, 'completion')
        if completion_service and completion_service.completion_tracking_enabled(
        ):
            child_blocks_to_complete_on_view = completion_service.blocks_to_mark_complete_on_view(
                child_blocks)
            complete_on_view_delay = completion_service.get_complete_on_view_delay_ms(
            )

        child_context['child_of_vertical'] = True
        is_child_of_vertical = context.get('child_of_vertical', False)

        # pylint: disable=no-member
        for child in child_blocks:
            child_has_access_error = self.block_has_access_error(child)
            if context.get(
                    'hide_access_error_blocks') and child_has_access_error:
                continue
            child_block_context = copy(child_context)
            if child in list(child_blocks_to_complete_on_view):
                child_block_context['wrap_xblock_data'] = {
                    'mark-completed-on-view-after-delay':
                    complete_on_view_delay
                }
            rendered_child = child.render(view, child_block_context)
            fragment.add_fragment_resources(rendered_child)

            contents.append({
                'id': str(child.location),
                'content': rendered_child.content
            })

        completed = self.is_block_complete_for_assignments(completion_service)
        past_due = completed is False and self.due and self.due < datetime.now(
            pytz.UTC)
        cta_service = self.runtime.service(self, 'call_to_action')
        vertical_banner_ctas = cta_service.get_ctas(
            self, 'vertical_banner', completed) if cta_service else []

        fragment_context = {
            'items':
            contents,
            'xblock_context':
            context,
            'unit_title':
            self.display_name_with_default
            if not is_child_of_vertical else None,
            'due':
            self.due,
            'completed':
            completed,
            'past_due':
            past_due,
            'has_assignments':
            completed is not None,
            'subsection_format':
            context.get('format', ''),
            'vertical_banner_ctas':
            vertical_banner_ctas,
        }

        if view == STUDENT_VIEW:
            fragment_context.update({
                'show_bookmark_button':
                child_context.get('show_bookmark_button',
                                  not is_child_of_vertical),
                'show_title':
                child_context.get('show_title', True),
                'bookmarked':
                child_context['bookmarked'],
                'bookmark_id':
                "{},{}".format(child_context['username'], str(self.location)),  # pylint: disable=no-member
            })

        fragment.add_content(
            self.runtime.service(self, 'mako').render_template(
                'vert_module.html', fragment_context))

        add_webpack_to_fragment(fragment, 'VerticalStudentView')
        fragment.initialize_js('VerticalStudentView')

        return fragment
def wrap_xblock(
        runtime_class,
        block,
        view,
        frag,
        context,
        usage_id_serializer,
        request_token,                  # pylint: disable=redefined-outer-name
        display_name_only=False,
        extra_data=None
):
    """
    Wraps the results of rendering an XBlock view in a standard <section> with identifying
    data so that the appropriate javascript module can be loaded onto it.

    :param runtime_class: The name of the javascript runtime class to use to load this block
    :param block: An XBlock (that may be an XModule or XModuleDescriptor)
    :param view: The name of the view that rendered the fragment being wrapped
    :param frag: The :class:`Fragment` to be wrapped
    :param context: The context passed to the view being rendered
    :param usage_id_serializer: A function to serialize the block's usage_id for use by the
        front-end Javascript Runtime.
    :param request_token: An identifier that is unique per-request, so that only xblocks
        rendered as part of this request will have their javascript initialized.
    :param display_name_only: If true, don't render the fragment content at all.
        Instead, just render the `display_name` of `block`
    :param extra_data: A dictionary with extra data values to be set on the wrapper
    """
    if extra_data is None:
        extra_data = {}

    # If any mixins have been applied, then use the unmixed class
    class_name = getattr(block, 'unmixed_class', block.__class__).__name__

    data = {}
    data.update(extra_data)

    if context:
        data.update(context.get('wrap_xblock_data', {}))

    css_classes = [
        'xblock',
        'xblock-{}'.format(markupsafe.escape(view)),
        'xblock-{}-{}'.format(
            markupsafe.escape(view),
            markupsafe.escape(block.scope_ids.block_type),
        )
    ]

    if view == STUDENT_VIEW and getattr(block, 'HIDDEN', False):
        css_classes.append('is-hidden')

    if isinstance(block, (XModule, XModuleDescriptor)) or getattr(block, 'uses_xmodule_styles_setup', False):
        if view in PREVIEW_VIEWS:
            # The block is acting as an XModule
            css_classes.append('xmodule_display')
        elif view == STUDIO_VIEW:
            # The block is acting as an XModuleDescriptor
            css_classes.append('xmodule_edit')

        css_classes.append('xmodule_' + markupsafe.escape(class_name))

    if isinstance(block, (XModule, XModuleDescriptor)):
        data['type'] = block.js_module_name
        shim_xmodule_js(frag, block.js_module_name)

    if frag.js_init_fn:
        data['init'] = frag.js_init_fn
        data['runtime-class'] = runtime_class
        data['runtime-version'] = frag.js_init_version

    data['block-type'] = block.scope_ids.block_type
    data['usage-id'] = usage_id_serializer(block.scope_ids.usage_id)
    data['request-token'] = request_token
    data['graded'] = getattr(block, 'graded', False)
    data['has-score'] = getattr(block, 'has_score', False)

    if block.name:
        data['name'] = block.name

    template_context = {
        'content': block.display_name if display_name_only else frag.content,
        'classes': css_classes,
        'display_name': block.display_name_with_default_escaped,  # xss-lint: disable=python-deprecated-display-name
        'data_attributes': ' '.join('data-{}="{}"'.format(markupsafe.escape(key), markupsafe.escape(value))
                                    for key, value in data.items()),
    }

    if hasattr(frag, 'json_init_args') and frag.json_init_args is not None:
        template_context['js_init_parameters'] = frag.json_init_args
    else:
        template_context['js_init_parameters'] = ""

    if isinstance(block, (XModule, XModuleDescriptor)):
        # Add the webpackified asset tags
        add_webpack_to_fragment(frag, class_name)

    return wrap_fragment(frag, render_to_string('xblock_wrapper.html', template_context))
示例#29
0
def wrap_xblock(
        runtime_class,
        block,
        view,
        frag,
        context,
        usage_id_serializer,
        request_token,                  # pylint: disable=redefined-outer-name
        display_name_only=False,
        extra_data=None
):
    """
    Wraps the results of rendering an XBlock view in a standard <section> with identifying
    data so that the appropriate javascript module can be loaded onto it.

    :param runtime_class: The name of the javascript runtime class to use to load this block
    :param block: An XBlock (that may be an XModule or XModuleDescriptor)
    :param view: The name of the view that rendered the fragment being wrapped
    :param frag: The :class:`Fragment` to be wrapped
    :param context: The context passed to the view being rendered
    :param usage_id_serializer: A function to serialize the block's usage_id for use by the
        front-end Javascript Runtime.
    :param request_token: An identifier that is unique per-request, so that only xblocks
        rendered as part of this request will have their javascript initialized.
    :param display_name_only: If true, don't render the fragment content at all.
        Instead, just render the `display_name` of `block`
    :param extra_data: A dictionary with extra data values to be set on the wrapper
    """
    if extra_data is None:
        extra_data = {}

    # If any mixins have been applied, then use the unmixed class
    class_name = getattr(block, 'unmixed_class', block.__class__).__name__

    data = {}
    data.update(extra_data)

    if context:
        data.update(context.get('wrap_xblock_data', {}))

    css_classes = [
        'xblock',
        'xblock-{}'.format(markupsafe.escape(view)),
        'xblock-{}-{}'.format(
            markupsafe.escape(view),
            markupsafe.escape(block.scope_ids.block_type),
        )
    ]

    if isinstance(block, (XModule, XModuleDescriptor)):
        if view in PREVIEW_VIEWS:
            # The block is acting as an XModule
            css_classes.append('xmodule_display')
        elif view == STUDIO_VIEW:
            # The block is acting as an XModuleDescriptor
            css_classes.append('xmodule_edit')

        if getattr(block, 'HIDDEN', False):
            css_classes.append('is-hidden')

        css_classes.append('xmodule_' + markupsafe.escape(class_name))
        data['type'] = block.js_module_name
        shim_xmodule_js(block, frag)

    if frag.js_init_fn:
        data['init'] = frag.js_init_fn
        data['runtime-class'] = runtime_class
        data['runtime-version'] = frag.js_init_version

    data['block-type'] = block.scope_ids.block_type
    data['usage-id'] = usage_id_serializer(block.scope_ids.usage_id)
    data['request-token'] = request_token
    data['graded'] = getattr(block, 'graded', False)
    data['has-score'] = getattr(block, 'has_score', False)

    if block.name:
        data['name'] = block.name

    template_context = {
        'content': block.display_name if display_name_only else frag.content,
        'classes': css_classes,
        'display_name': block.display_name_with_default_escaped,  # xss-lint: disable=python-deprecated-display-name
        'data_attributes': u' '.join(u'data-{}="{}"'.format(markupsafe.escape(key), markupsafe.escape(value))
                                     for key, value in data.iteritems()),
    }

    if hasattr(frag, 'json_init_args') and frag.json_init_args is not None:
        template_context['js_init_parameters'] = frag.json_init_args
    else:
        template_context['js_init_parameters'] = ""

    if isinstance(block, (XModule, XModuleDescriptor)):
        # Add the webpackified asset tags
        add_webpack_to_fragment(frag, class_name)

    return wrap_fragment(frag, render_to_string('xblock_wrapper.html', template_context))