* fix: refactor MakoService to allow specifying namespace per template (#33061) * fix: instr. dashboard broken by bulk email reusing HtmlBlock studio_view * fix: lint issue from unused import
140 lines
5.1 KiB
Python
140 lines
5.1 KiB
Python
"""
|
|
'library' XBlock (LibraryRoot)
|
|
"""
|
|
|
|
|
|
import logging
|
|
|
|
from web_fragments.fragment import Fragment
|
|
from xblock.core import XBlock
|
|
from xblock.fields import Boolean, List, Scope, String
|
|
from xmodule.studio_editable import StudioEditableBlock
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
# Make '_' a no-op so we can scrape strings. Using lambda instead of
|
|
# `django.utils.translation.ugettext_noop` because Django cannot be imported in this file
|
|
_ = lambda text: text
|
|
|
|
|
|
@XBlock.needs('mako')
|
|
class LibraryRoot(XBlock):
|
|
"""
|
|
The LibraryRoot is the root XBlock of a content library. All other blocks in
|
|
the library are its children. It contains metadata such as the library's
|
|
display_name.
|
|
"""
|
|
resources_dir = None
|
|
|
|
display_name = String(
|
|
help=_("The display name for this component."),
|
|
default="Library",
|
|
display_name=_("Library Display Name"),
|
|
scope=Scope.settings
|
|
)
|
|
advanced_modules = List(
|
|
display_name=_("Advanced Module List"),
|
|
help=_("Enter the names of the advanced components to use in your library."),
|
|
scope=Scope.settings,
|
|
xml_node=True,
|
|
)
|
|
show_children_previews = Boolean(
|
|
display_name="Hide children preview",
|
|
help="Choose if preview of library contents is shown",
|
|
scope=Scope.user_state,
|
|
default=True
|
|
)
|
|
has_children = True
|
|
has_author_view = True
|
|
|
|
def __str__(self):
|
|
return f"Library: {self.display_name}"
|
|
|
|
def author_view(self, context):
|
|
"""
|
|
Renders the Studio preview view.
|
|
"""
|
|
fragment = Fragment()
|
|
self.render_children(context, fragment, can_reorder=False, can_add=True)
|
|
return fragment
|
|
|
|
def render_children(self, context, fragment, can_reorder=False, can_add=False): # pylint: disable=unused-argument
|
|
"""
|
|
Renders the children of the block with HTML appropriate for Studio. Reordering is not supported.
|
|
"""
|
|
contents = []
|
|
|
|
paging = context.get('paging', None)
|
|
|
|
children_count = len(self.children) # pylint: disable=no-member
|
|
item_start, item_end = 0, children_count
|
|
|
|
# TODO sort children
|
|
if paging:
|
|
page_number = paging.get('page_number', 0)
|
|
raw_page_size = paging.get('page_size', None)
|
|
page_size = raw_page_size if raw_page_size is not None else children_count
|
|
item_start, item_end = page_size * page_number, page_size * (page_number + 1)
|
|
|
|
children_to_show = self.children[item_start:item_end] # pylint: disable=no-member
|
|
|
|
force_render = context.get('force_render', None)
|
|
context['can_move'] = False
|
|
|
|
for child_key in children_to_show:
|
|
# Children must have a separate context from the library itself. Make a copy.
|
|
child_context = context.copy()
|
|
child_context['show_preview'] = self.show_children_previews
|
|
child_context['can_edit_visibility'] = False
|
|
child = self.runtime.get_block(child_key)
|
|
child_view_name = StudioEditableBlock.get_preview_view_name(child)
|
|
|
|
if str(child.location) == force_render:
|
|
child_context['show_preview'] = True
|
|
|
|
if child_context['show_preview']:
|
|
rendered_child = self.runtime.render_child(child, child_view_name, child_context)
|
|
else:
|
|
rendered_child = self.runtime.render_child_placeholder(child, child_view_name, child_context)
|
|
fragment.add_fragment_resources(rendered_child)
|
|
|
|
contents.append({
|
|
'id': str(child.location),
|
|
'content': rendered_child.content,
|
|
})
|
|
|
|
fragment.add_content(
|
|
# For historic reasons, this template is in the LMS folder, and some external code may depend on that.
|
|
self.runtime.service(self, 'mako').render_lms_template("studio_render_paged_children_view.html", {
|
|
'items': contents,
|
|
'xblock_context': context,
|
|
'can_add': can_add,
|
|
'first_displayed': item_start,
|
|
'total_children': children_count,
|
|
'displayed_children': len(children_to_show),
|
|
'previews': self.show_children_previews
|
|
})
|
|
)
|
|
|
|
@property
|
|
def display_org_with_default(self):
|
|
"""
|
|
Org display names are not implemented. This just provides API compatibility with CourseBlock.
|
|
Always returns the raw 'org' field from the key.
|
|
"""
|
|
return self.scope_ids.usage_id.course_key.org
|
|
|
|
@property
|
|
def display_number_with_default(self):
|
|
"""
|
|
Display numbers are not implemented. This just provides API compatibility with CourseBlock.
|
|
Always returns the raw 'library' field from the key.
|
|
"""
|
|
return self.scope_ids.usage_id.course_key.library
|
|
|
|
@XBlock.json_handler
|
|
def trigger_previews(self, request_body, suffix): # pylint: disable=unused-argument
|
|
""" Enable or disable previews in studio for library children. """
|
|
self.show_children_previews = request_body.get('showChildrenPreviews', self.show_children_previews)
|
|
return {'showChildrenPreviews': self.show_children_previews}
|