refactor: inheritable authoring mixin callbacks for editing & duplication (#33756)

This commit is contained in:
Daniel Valenzuela
2024-07-25 13:30:37 -04:00
committed by GitHub
parent 238dca732e
commit 78b691b56a
5 changed files with 23 additions and 49 deletions

View File

@@ -13,6 +13,7 @@ from django.views.decorators.http import require_http_methods
from opaque_keys.edx.keys import CourseKey from opaque_keys.edx.keys import CourseKey
from web_fragments.fragment import Fragment from web_fragments.fragment import Fragment
from cms.djangoapps.contentstore.utils import load_services_for_studio
from cms.lib.xblock.authoring_mixin import VISIBILITY_VIEW from cms.lib.xblock.authoring_mixin import VISIBILITY_VIEW
from common.djangoapps.edxmako.shortcuts import render_to_string from common.djangoapps.edxmako.shortcuts import render_to_string
from common.djangoapps.student.auth import ( from common.djangoapps.student.auth import (
@@ -47,7 +48,6 @@ from .preview import get_preview_fragment
from cms.djangoapps.contentstore.xblock_storage_handlers.view_handlers import ( from cms.djangoapps.contentstore.xblock_storage_handlers.view_handlers import (
handle_xblock, handle_xblock,
create_xblock_info, create_xblock_info,
load_services_for_studio,
get_block_info, get_block_info,
get_xblock, get_xblock,
delete_orphans, delete_orphans,

View File

@@ -45,7 +45,7 @@ from openedx.core.lib.xblock_utils import (
wrap_xblock_aside wrap_xblock_aside
) )
from ..utils import get_visibility_partition_info, StudioPermissionsService from ..utils import StudioPermissionsService, get_visibility_partition_info
from .access import get_user_role from .access import get_user_role
from .session_kv_store import SessionKeyValueStore from .session_kv_store import SessionKeyValueStore

View File

@@ -305,13 +305,10 @@ def _update_with_callback(xblock, user, old_metadata=None, old_content=None):
old_metadata = own_metadata(xblock) old_metadata = own_metadata(xblock)
if old_content is None: if old_content is None:
old_content = xblock.get_explicitly_set_fields_by_scope(Scope.content) old_content = xblock.get_explicitly_set_fields_by_scope(Scope.content)
if hasattr(xblock, "editor_saved"): load_services_for_studio(xblock.runtime, user)
load_services_for_studio(xblock.runtime, user) xblock.editor_saved(user, old_metadata, old_content)
xblock.editor_saved(user, old_metadata, old_content)
xblock_updated = modulestore().update_item(xblock, user.id) xblock_updated = modulestore().update_item(xblock, user.id)
if hasattr(xblock_updated, "post_editor_saved"): xblock_updated.post_editor_saved(user, old_metadata, old_content)
load_services_for_studio(xblock_updated.runtime, user)
xblock_updated.post_editor_saved(user, old_metadata, old_content)
return xblock_updated return xblock_updated

View File

@@ -10,6 +10,7 @@ from web_fragments.fragment import Fragment
from xblock.core import XBlock, XBlockMixin from xblock.core import XBlock, XBlockMixin
from xblock.fields import String, Scope from xblock.fields import String, Scope
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
VISIBILITY_VIEW = 'visibility_view' VISIBILITY_VIEW = 'visibility_view'
@@ -21,6 +22,7 @@ class AuthoringMixin(XBlockMixin):
""" """
Mixin class that provides authoring capabilities for XBlocks. Mixin class that provides authoring capabilities for XBlocks.
""" """
def _get_studio_resource_url(self, relative_url): def _get_studio_resource_url(self, relative_url):
""" """
Returns the Studio URL to a static resource. Returns the Studio URL to a static resource.
@@ -51,3 +53,17 @@ class AuthoringMixin(XBlockMixin):
scope=Scope.settings, scope=Scope.settings,
enforce_type=True, enforce_type=True,
) )
def editor_saved(self, user, 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, user, 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.
"""

View File

@@ -2,6 +2,7 @@
Mixin to support editing in Studio. Mixin to support editing in Studio.
""" """
from xblock.core import XBlock, XBlockMixin from xblock.core import XBlock, XBlockMixin
from xmodule.x_module import AUTHOR_VIEW, STUDENT_VIEW from xmodule.x_module import AUTHOR_VIEW, STUDENT_VIEW
@@ -12,6 +13,7 @@ class StudioEditableBlock(XBlockMixin):
This class is only intended to be used with an XBlock! This class is only intended to be used with an XBlock!
""" """
has_author_view = True has_author_view = True
def render_children(self, context, fragment, can_reorder=False, can_add=False): def render_children(self, context, fragment, can_reorder=False, can_add=False):
@@ -49,47 +51,6 @@ class StudioEditableBlock(XBlockMixin):
""" """
return AUTHOR_VIEW if has_author_view(block) else STUDENT_VIEW return AUTHOR_VIEW if has_author_view(block) else STUDENT_VIEW
# Some parts of the code use getattr to dynamically check for the following 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, store, source_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 studio_post_paste(self, store, source_node) -> bool: # pylint: disable=unused-argument
# """
# Called after a block is copy-pasted. 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): def has_author_view(block):
""" """