diff --git a/lms/djangoapps/courseware/block_render.py b/lms/djangoapps/courseware/block_render.py index 5afcaac044af..72200eb44264 100644 --- a/lms/djangoapps/courseware/block_render.py +++ b/lms/djangoapps/courseware/block_render.py @@ -96,6 +96,8 @@ from common.djangoapps.edxmako.services import MakoService from common.djangoapps.xblock_django.user_service import DjangoXBlockUserService from openedx.core.lib.cache_utils import CacheService +from xmodule.modulestore import ModuleStoreEnum # lint-amnesty, pylint: disable=wrong-import-order + if TYPE_CHECKING: from rest_framework.request import Request @@ -813,7 +815,7 @@ def _get_usage_key_for_course(course_key, usage_id) -> UsageKey: raise Http404("Invalid location") from exc -def _get_block_by_usage_key(usage_key): +def _get_block_by_usage_key(usage_key, request=None): """ Gets a block instance based on a mapped-to-course usage_key @@ -828,7 +830,29 @@ def _get_block_by_usage_key(usage_key): usage_key.course_key, usage_key ) - raise Http404 from exc + + if request is None: + # No request provided, cannot proceed + raise Http404 from exc + + referer = request.META.get('HTTP_REFERER') + authoring_mfe_query_key = 'is_authoring_mfe' + authoring_mfe_matches = [settings.COURSE_AUTHORING_MICROFRONTEND_URL, authoring_mfe_query_key] + is_fetched_from_authoring_mfe = referer and any(match in referer for match in authoring_mfe_matches) + + if is_fetched_from_authoring_mfe: + try: + block = modulestore().get_item(usage_key, revision=ModuleStoreEnum.RevisionOption.draft_only) + block_orig_usage_key, block_orig_version = modulestore().get_block_original_usage(usage_key) + except ItemNotFoundError: + log.warning( + "Invalid draft location for course id %s: %s", + usage_key.course_key, + usage_key + ) + raise Http404 from exc + else: + raise Http404 from exc tracking_context = { 'module': { @@ -855,7 +879,7 @@ def get_block_by_usage_id(request, course_id, usage_id, disable_staff_debug_info """ course_key = CourseKey.from_string(course_id) usage_key = _get_usage_key_for_course(course_key, usage_id) - block, tracking_context = _get_block_by_usage_key(usage_key) + block, tracking_context = _get_block_by_usage_key(usage_key, request) _, user = setup_masquerade(request, course_key, has_access(request.user, 'staff', block, course_key)) field_data_cache = FieldDataCache.cache_for_block_descendents( @@ -923,7 +947,7 @@ def _invoke_xblock_handler(request, course_id, usage_id, handler, suffix, course # At the time of writing, this is only used by one handler. If this usage grows, we may want to re-evaluate # how we do this to something more elegant. If you are the author of a third party block that decides it wants # to set this too, please let us know so we can consider making this easier / better-documented. - block, _ = _get_block_by_usage_key(block_usage_key) + block, _ = _get_block_by_usage_key(block_usage_key, request) handler_method = getattr(block, handler, False) will_recheck_access = handler_method and getattr(handler_method, 'will_recheck_access', False) diff --git a/lms/djangoapps/courseware/views/views.py b/lms/djangoapps/courseware/views/views.py index d0e657775bce..d023cc8e5fab 100644 --- a/lms/djangoapps/courseware/views/views.py +++ b/lms/djangoapps/courseware/views/views.py @@ -1536,6 +1536,7 @@ def render_xblock(request, usage_key_string, check_if_enrolled=True, disable_sta set_custom_attribute('block_type', usage_key.block_type) requested_view = request.GET.get('view', 'student_view') + is_authoring_mfe = request.GET.get('is_authoring_mfe') if requested_view != 'student_view' and requested_view != 'public_view': # lint-amnesty, pylint: disable=consider-using-in return HttpResponseBadRequest( f"Rendering of the xblock view '{bleach.clean(requested_view, strip=True)}' is not supported." @@ -1651,7 +1652,7 @@ def render_xblock(request, usage_key_string, check_if_enrolled=True, disable_sta 'web_app_course_url': get_learning_mfe_home_url(course_key=course.id, url_fragment='home'), 'on_courseware_page': True, 'verified_upgrade_link': verified_upgrade_deadline_link(request.user, course=course), - 'is_learning_mfe': is_learning_mfe, + 'is_learning_mfe': is_authoring_mfe or is_learning_mfe, 'is_mobile_app': is_mobile_app, 'render_course_wide_assets': True, diff --git a/lms/envs/common.py b/lms/envs/common.py index 7ed5b76f62e0..69fc4b235360 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -5050,6 +5050,8 @@ def _make_locale_paths(settings): # pylint: disable=missing-function-docstring # .. toggle_tickets: https://openedx.atlassian.net/browse/VAN-838 ENABLE_DYNAMIC_REGISTRATION_FIELDS = False +COURSE_AUTHORING_MICROFRONTEND_URL = None + ############## Settings for EmailChangeMiddleware ############### # .. toggle_name: ENFORCE_SESSION_EMAIL_MATCH diff --git a/lms/envs/devstack.py b/lms/envs/devstack.py index e241852fddf0..a9a6d0562731 100644 --- a/lms/envs/devstack.py +++ b/lms/envs/devstack.py @@ -287,6 +287,9 @@ def should_show_debug_toolbar(request): # lint-amnesty, pylint: disable=missing ########################## LEARNER HOME APP ############################## LEARNER_HOME_MICROFRONTEND_URL = 'http://localhost:1996' +################### FRONTEND APPLICATION COURSE AUTHORING ################### +COURSE_AUTHORING_MICROFRONTEND_URL = 'http://localhost:2001' + ###################### Cross-domain requests ###################### FEATURES['ENABLE_CORS_HEADERS'] = True CORS_ALLOW_CREDENTIALS = True diff --git a/lms/templates/courseware/courseware-chromeless.html b/lms/templates/courseware/courseware-chromeless.html index 1d0d4017267c..afacab58a5dc 100644 --- a/lms/templates/courseware/courseware-chromeless.html +++ b/lms/templates/courseware/courseware-chromeless.html @@ -59,6 +59,12 @@ var $$course_id = "${course.id | n, js_escaped_string}"; +% if block: + +% endif + <%block name="js_extra"> @@ -183,6 +189,7 @@ window.parent.postMessage({ type: 'plugin.resize', + location: $$xBlockLocation || '', payload: { width: newWidth, height: newHeight,