feat: support for syncing units from libraries to courses (#36553)
* feat: library unit sync * feat: create component link only for component xblocks * feat: container link model * feat: update downstream api views * feat: delete extra components in container on sync (not working) * fix: duplicate definitions of LibraryXBlockMetadata * test: add a new integration test suite for syncing * feat: partially implement container+child syncing * fix: blockserializer wasn't always serializing all HTML block fields * feat: handle reorder, addition and deletion of components in sync Updates children components of unit in course based on upstream unit, deletes removed component, adds new ones and updates order as per upstream. * feat: return unit upstreamInfo and disallow edits to units in courses that are sourced from a library (#773) * feat: Add upstream_info to unit * feat: disallow edits to units in courses that are sourced from a library (#774) --------- Co-authored-by: Jillian Vogel <jill@opencraft.com> Co-authored-by: Rômulo Penido <romulo.penido@gmail.com> * docs: capitalization of XBlock Co-authored-by: David Ormsbee <dave@axim.org> * refactor: (minor) change python property name to reflect type better * fix: lots of "Tried to inspect a missing...upstream link" warnings when viewing a unit in Studio * docs: mention potential REST API for future refactor * fix: check if upstream actually exists before making unit read-only * chore: fix camel-case var * fix: test failure when mocked XBlock doesn't have UpstreamSyncMixin --------- Co-authored-by: Braden MacDonald <braden@opencraft.com> Co-authored-by: Chris Chávez <xnpiochv@gmail.com> Co-authored-by: Jillian Vogel <jill@opencraft.com> Co-authored-by: Rômulo Penido <romulo.penido@gmail.com> Co-authored-by: Braden MacDonald <mail@bradenm.com> Co-authored-by: David Ormsbee <dave@axim.org>
This commit is contained in:
@@ -11,6 +11,7 @@ from django.urls import reverse
|
||||
from django.utils.translation import gettext as _
|
||||
from django.views.decorators.clickjacking import xframe_options_exempt
|
||||
from opaque_keys.edx.keys import UsageKey
|
||||
from opaque_keys.edx.locator import LibraryContainerLocator
|
||||
from rest_framework.request import Request
|
||||
from web_fragments.fragment import Fragment
|
||||
from xblock.django.request import django_to_webob_request, webob_to_django_response
|
||||
@@ -29,6 +30,7 @@ from xmodule.x_module import AUTHOR_VIEW, PREVIEW_VIEWS, STUDENT_VIEW, XModuleMi
|
||||
from cms.djangoapps.xblock_config.models import StudioConfig
|
||||
from cms.djangoapps.contentstore.toggles import individualize_anonymous_user_id
|
||||
from cms.lib.xblock.field_data import CmsFieldData
|
||||
from cms.lib.xblock.upstream_sync import UpstreamLink
|
||||
from common.djangoapps.static_replace.services import ReplaceURLService
|
||||
from common.djangoapps.static_replace.wrapper import replace_urls_wrapper
|
||||
from common.djangoapps.student.models import anonymous_id_for_user
|
||||
@@ -299,8 +301,17 @@ def _studio_wrap_xblock(xblock, view, frag, context, display_name_only=False):
|
||||
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)
|
||||
|
||||
can_edit = context.get('can_edit', True)
|
||||
can_add = context.get('can_add', True)
|
||||
upstream_link = UpstreamLink.try_get_for_block(root_xblock, log_error=False)
|
||||
if upstream_link.error_message is None and isinstance(upstream_link.upstream_key, LibraryContainerLocator):
|
||||
# If this unit is linked to a library unit, for now we make it completely read-only
|
||||
# because when it is synced, all local changes like added components will be lost.
|
||||
# (This is only on the frontend; the backend doesn't enforce it)
|
||||
can_edit = False
|
||||
can_add = False
|
||||
|
||||
# Is this a course or a library?
|
||||
is_course = xblock.context_key.is_course
|
||||
tags_count_map = context.get('tags_count_map')
|
||||
@@ -315,7 +326,7 @@ def _studio_wrap_xblock(xblock, view, frag, context, display_name_only=False):
|
||||
'is_root': is_root,
|
||||
'is_reorderable': is_reorderable,
|
||||
'can_edit': can_edit,
|
||||
'can_edit_visibility': context.get('can_edit_visibility', is_course),
|
||||
'can_edit_visibility': can_edit and context.get('can_edit_visibility', is_course),
|
||||
'course_authoring_url': settings.COURSE_AUTHORING_MICROFRONTEND_URL,
|
||||
'is_loading': context.get('is_loading', False),
|
||||
'is_selected': context.get('is_selected', False),
|
||||
|
||||
Reference in New Issue
Block a user