From 1b2178d239c96b4bc2e26fb6dc13a845393d3a52 Mon Sep 17 00:00:00 2001 From: Navin Karkera Date: Thu, 3 Apr 2025 12:35:44 +0530 Subject: [PATCH 1/3] feat: post component height to parent window --- common/templates/xblock_v2/xblock_iframe.html | 60 +++++++++++++++---- 1 file changed, 47 insertions(+), 13 deletions(-) diff --git a/common/templates/xblock_v2/xblock_iframe.html b/common/templates/xblock_v2/xblock_iframe.html index add3c46bce55..69af639da2a8 100644 --- a/common/templates/xblock_v2/xblock_iframe.html +++ b/common/templates/xblock_v2/xblock_iframe.html @@ -180,8 +180,8 @@ - -
+ +
{{ fragment.body_html | safe }} @@ -360,7 +360,7 @@ error_message_div.html('Error: '+response.message); error_message_div.css('display', 'block'); } - }); + }); }); }); } @@ -437,21 +437,55 @@ const rootNode = document.querySelector('.xblock, .xblock-v1'); // will always return the first matching element initializeXBlockAndChildren(rootNode, () => { }); + (function() { + // If this view is rendered in an iframe within the authoring microfrontend app + // it will report the height of its contents to the parent window when the + // document loads, window resizes, or DOM mutates. + if (window !== window.parent) { + var lastHeight = window.parent[0].offsetHeight; + var lastWidth = window.parent[0].offsetWidth; - let lastHeight = -1; - function checkFrameHeight() { - const newHeight = document.documentElement.scrollHeight; - if (newHeight !== lastHeight) { - lastHeight = newHeight; + function dispatchResizeMessage(event) { + // Note: event is actually an Array of MutationRecord objects when fired from the MutationObserver + var newHeight = rootNode.scrollHeight; + var newWidth = rootNode.offsetWidth; + + window.parent.postMessage( + { + type: 'plugin.resize', + payload: { + width: newWidth, + height: newHeight, + } + }, document.referrer + ); + + lastHeight = newHeight; + lastWidth = newWidth; + + // Within the authoring microfrontend the iframe resizes to match the + // height of this document and it should never scroll. It does scroll + // ocassionally when javascript is used to focus elements on the page + // before the parent iframe has been resized to match the content + // height. This window.scrollTo is an attempt to keep the content at the + // top of the page. + window.scrollTo(0, 0); + } + + // Create an observer instance linked to the callback function + const observer = new MutationObserver(dispatchResizeMessage); + + // Start observing the target node for configured mutations + observer.observe(rootNode, { attributes: true, childList: true, subtree: true }); + + const resizeObserver = new ResizeObserver(dispatchResizeMessage); + resizeObserver.observe(rootNode); } - } - // Check the size whenever the DOM changes: - new MutationObserver(checkFrameHeight).observe(document.body, { attributes: true, childList: true, subtree: true }); - // And whenever the IFrame is resized - window.addEventListener('resize', checkFrameHeight); + }()); } window.addEventListener('load', blockFrameJS); + From 00cb1ab3ca0cb6976559a1be31d1dd847185ec2b Mon Sep 17 00:00:00 2001 From: Navin Karkera Date: Fri, 4 Apr 2025 22:20:51 +0530 Subject: [PATCH 2/3] feat: add tags_count to library xblock metadata --- .../djangoapps/content_libraries/api/libraries.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/openedx/core/djangoapps/content_libraries/api/libraries.py b/openedx/core/djangoapps/content_libraries/api/libraries.py index bf9ca6f60d29..610bca8dd257 100644 --- a/openedx/core/djangoapps/content_libraries/api/libraries.py +++ b/openedx/core/djangoapps/content_libraries/api/libraries.py @@ -210,12 +210,16 @@ class LibraryXBlockMetadata(PublishableItem): Class that represents the metadata about an XBlock in a content library. """ usage_key: LibraryUsageLocatorV2 + tags_count: int = 0 @classmethod def from_component(cls, library_key, component, associated_collections=None): """ Construct a LibraryXBlockMetadata from a Component object. """ + # Import content_tagging.api here to avoid circular imports + from openedx.core.djangoapps.content_tagging.api import get_object_tag_counts + last_publish_log = component.versioning.last_publish_log published_by = None @@ -226,12 +230,11 @@ def from_component(cls, library_key, component, associated_collections=None): published = component.versioning.published last_draft_created = draft.created if draft else None last_draft_created_by = draft.publishable_entity_version.created_by if draft else None + usage_key = library_component_usage_key(library_key, component) + tags = get_object_tag_counts(str(usage_key), count_implicit=True) return cls( - usage_key=library_component_usage_key( - library_key, - component, - ), + usage_key=usage_key, display_name=draft.title, created=component.created, modified=draft.created, @@ -244,6 +247,7 @@ def from_component(cls, library_key, component, associated_collections=None): has_unpublished_changes=component.versioning.has_unpublished_changes, collections=associated_collections or [], can_stand_alone=component.publishable_entity.can_stand_alone, + tags_count=tags.get(str(usage_key), 0), ) From 46f1a75e8ff130fb14087182572145c90376ebd5 Mon Sep 17 00:00:00 2001 From: Navin Karkera Date: Wed, 9 Apr 2025 18:44:29 +0530 Subject: [PATCH 3/3] chore: add todo comment about tags_count field --- openedx/core/djangoapps/content_libraries/api/libraries.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openedx/core/djangoapps/content_libraries/api/libraries.py b/openedx/core/djangoapps/content_libraries/api/libraries.py index 610bca8dd257..b204c30ad490 100644 --- a/openedx/core/djangoapps/content_libraries/api/libraries.py +++ b/openedx/core/djangoapps/content_libraries/api/libraries.py @@ -210,6 +210,7 @@ class LibraryXBlockMetadata(PublishableItem): Class that represents the metadata about an XBlock in a content library. """ usage_key: LibraryUsageLocatorV2 + # TODO: move tags_count to LibraryItem as all objects under a library can be tagged. tags_count: int = 0 @classmethod