Files
edx-platform/xmodule/studio_editable.py
Kyle McCormick e800ae7622 feat: provisionally support V2 libraries in LibraryContentBlock (randomized only) (#33263)
Refactors and reworks the LibraryContentBlock so that its
sync-from-library operations are asynchronous and work with
V2 content libraries. This also required us to make
library_content block duplication asynchronous, as that
involves syncing from the source library.

For the sake of clarity, this PR includes two major method renames:

* update_children(...) -> sync_from_library(...)
* refresh_library(...) -> sync_from_library(upgrade_to_latest=True, ...)

an an XBlock HTTP handler rename:

  /refresh_children -> /upgrade_and_sync

There are still a couple issues with import or duplication
of library_content blocks referencing V2 libraries other than
latest. These will be resolved in an upcoming PR.

Part of: https://openedx.atlassian.net/wiki/spaces/COMM/pages/3820617729/Spec+Memo+Content+Library+Authoring+Experience+V2
Follow-up work: https://github.com/openedx/edx-platform/issues/33640

Co-authored-by: Connor Haugh <chaugh@2u.com>
Co-authored-by: Eugene Dyudyunov <evgen.dyudyunov@raccoongang.com>
2023-11-20 15:58:10 +00:00

88 lines
3.4 KiB
Python

"""
Mixin to support editing in Studio.
"""
from xblock.core import XBlock, XBlockMixin
from xmodule.x_module import AUTHOR_VIEW, STUDENT_VIEW
@XBlock.needs('mako')
class StudioEditableBlock(XBlockMixin):
"""
Helper methods for supporting Studio editing of XBlocks.
This class is only intended to be used with an XBlock!
"""
has_author_view = True
def render_children(self, context, fragment, can_reorder=False, can_add=False):
"""
Renders the children of the block with HTML appropriate for Studio. If can_reorder is True,
then the children will be rendered to support drag and drop.
"""
contents = []
for child in self.get_children(): # pylint: disable=no-member
if can_reorder:
context['reorderable_items'].add(child.location)
context['can_add'] = can_add
rendered_child = child.render(StudioEditableBlock.get_preview_view_name(child), context)
fragment.add_fragment_resources(rendered_child)
contents.append({
'id': str(child.location),
'content': rendered_child.content
})
mako_service = self.runtime.service(self, 'mako')
# For historic reasons, this template is in the LMS folder, and some code like xblock-utils expects that.
fragment.add_content(mako_service.render_lms_template("studio_render_children_view.html", { # pylint: disable=no-member
'items': contents,
'xblock_context': context,
'can_add': can_add,
'can_reorder': can_reorder,
}))
@staticmethod
def get_preview_view_name(block):
"""
Helper method for getting preview view name (student_view or author_view) for a given block.
"""
return AUTHOR_VIEW if has_author_view(block) else STUDENT_VIEW
# Some parts of the code use getattr to dynamically check for the following three methods on subclasses.
# We'd like to refactor so that we can actually declare them here as overridable methods.
# For now, we leave them here as documentation.
# See https://github.com/openedx/edx-platform/issues/33715.
#
# def editor_saved(self, old_metadata, old_content) -> None: # pylint: disable=unused-argument
# """
# Called right *before* the block is written to the DB. Can be used, e.g., to modify fields before saving.
#
# By default, is a no-op. Can be overriden in subclasses.
# """
#
# def post_editor_saved(self, old_metadata, old_content) -> None: # pylint: disable=unused-argument
# """
# Called right *after* the block is written to the DB. Can be used, e.g., to spin up followup tasks.
#
# By default, is a no-op. Can be overriden in subclasses.
# """
#
# def studio_post_duplicate(self, dest_block) -> bool: # pylint: disable=unused-argument
# """
# Called when a the block is duplicated. Can be used, e.g., for special handling of child duplication.
#
# Returns 'True' if children have been handled and thus shouldn't be handled by the standard
# duplication logic.
#
# By default, is a no-op. Can be overriden in subclasses.
# """
# return False
def has_author_view(block):
"""
Returns True if the xmodule linked to the block supports "author_view".
"""
return getattr(block, 'has_author_view', False)