From a0329552437ff66d06483ae11cb212d4ecafe275 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Ch=C3=A1vez?= Date: Tue, 16 Dec 2025 14:18:24 -0500 Subject: [PATCH] feat: New states for library info icon in components in Unit page (#37735) - Adds `upstream_name` to the `UpstreamLink` dataclass. - Add new states to library info icon in components in Unit page --- .../v2/views/tests/test_downstreams.py | 1 + cms/lib/xblock/upstream_sync.py | 3 + .../sass/course-unit-mfe-iframe-bundle.scss | 26 +++++++++ cms/templates/studio_xblock_wrapper.html | 57 ++++++++++++++----- 4 files changed, 73 insertions(+), 14 deletions(-) diff --git a/cms/djangoapps/contentstore/rest_api/v2/views/tests/test_downstreams.py b/cms/djangoapps/contentstore/rest_api/v2/views/tests/test_downstreams.py index b33d980732..f32d25a6a5 100644 --- a/cms/djangoapps/contentstore/rest_api/v2/views/tests/test_downstreams.py +++ b/cms/djangoapps/contentstore/rest_api/v2/views/tests/test_downstreams.py @@ -51,6 +51,7 @@ def _get_upstream_link_good_and_syncable(downstream): error_message=None, downstream_customized=[], has_top_level_parent=False, + upstream_name=downstream.upstream_display_name, ) diff --git a/cms/lib/xblock/upstream_sync.py b/cms/lib/xblock/upstream_sync.py index b56e0d9568..2b96e54c5e 100644 --- a/cms/lib/xblock/upstream_sync.py +++ b/cms/lib/xblock/upstream_sync.py @@ -79,6 +79,7 @@ class UpstreamLink: """ upstream_ref: str | None # Reference to the upstream content, e.g., a serialized library block usage key. upstream_key: LibraryUsageLocatorV2 | LibraryContainerLocator | None # parsed opaque key version of upstream_ref + upstream_name: str | None # Display name of the upstream content. downstream_key: str | None # Key of the downstream object. version_synced: int | None # Version of the upstream to which the downstream was last synced. version_available: int | None # Latest version of the upstream that's available, or None if it couldn't be loaded. @@ -223,6 +224,7 @@ class UpstreamLink: ) return cls( upstream_ref=getattr(downstream, "upstream", None), + upstream_name=getattr(downstream, "upstream_display_name", None), upstream_key=None, downstream_key=str(getattr(downstream, "usage_key", "")), version_synced=getattr(downstream, "upstream_version", None), @@ -307,6 +309,7 @@ class UpstreamLink: result = cls( upstream_ref=downstream.upstream, upstream_key=upstream_key, + upstream_name=downstream.upstream_display_name, downstream_key=str(downstream.usage_key), version_synced=downstream.upstream_version, version_available=version_available, diff --git a/cms/static/sass/course-unit-mfe-iframe-bundle.scss b/cms/static/sass/course-unit-mfe-iframe-bundle.scss index 6c9b43cf0b..3e2c9f3b6a 100644 --- a/cms/static/sass/course-unit-mfe-iframe-bundle.scss +++ b/cms/static/sass/course-unit-mfe-iframe-bundle.scss @@ -44,6 +44,32 @@ body, white-space: nowrap; overflow: hidden; text-overflow: ellipsis; + display: flex; + + .library-info-icon { + width: 32px; + height: 26px; + margin-top: 2px; + margin-right: 5px; + display: flex; + justify-content: center; + background-color: white; + color: $primary; + border: 1px solid #A9A6A4FF; + border-radius: 4px; + + &.two-icons { + width: 60px; + } + + &.sync-state { + &:hover { + background-color: $primary; + border-color: $primary; + color: white; + } + } + } } .xblock-display-name { diff --git a/cms/templates/studio_xblock_wrapper.html b/cms/templates/studio_xblock_wrapper.html index 8929b225cc..9ffd94fd0c 100644 --- a/cms/templates/studio_xblock_wrapper.html +++ b/cms/templates/studio_xblock_wrapper.html @@ -1,6 +1,7 @@ <%page expression_filter="h"/> <%! from django.utils.translation import gettext as _ +from openedx.core.djangolib.markup import Text from cms.djangoapps.contentstore.helpers import xblock_studio_url from cms.djangoapps.contentstore.utils import is_visible_to_specific_partition_groups, get_editor_page_base_url, determine_label from lms.lib.utils import is_unit @@ -112,21 +113,49 @@ can_unlink = upstream_info.upstream_ref and not upstream_info.has_top_level_pare % else: % if upstream_info.upstream_ref: % if upstream_info.error_message: - - - ${_("Sourced from a library - but the upstream link is broken/invalid.")} +
+ + + + + ${_("The referenced library or library object is not available.")} +
+ % elif upstream_info.ready_to_sync: + + % elif len(upstream_info.downstream_customized) > 0: +
+ + + + + ${_("This library reference has course overrides applied.")} +
% else: - - 0 else "Sourced from a library.")}" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 -960 960 960" fill="currentColor" style="vertical-align: middle; padding-bottom: 4px;"> - - - % if len(upstream_info.downstream_customized) > 0: - ${_("Sourced from a library - but has been modified locally.")} - % else: - ${_("Sourced from a library.")} - % endif +
+ + + ${_("This item is linked to a library item.")} +
% endif % endif ${label}