Skip to content

Commit a032955

Browse files
authored
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
1 parent 05d0d09 commit a032955

4 files changed

Lines changed: 73 additions & 14 deletions

File tree

cms/djangoapps/contentstore/rest_api/v2/views/tests/test_downstreams.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ def _get_upstream_link_good_and_syncable(downstream):
5151
error_message=None,
5252
downstream_customized=[],
5353
has_top_level_parent=False,
54+
upstream_name=downstream.upstream_display_name,
5455
)
5556

5657

cms/lib/xblock/upstream_sync.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ class UpstreamLink:
7979
"""
8080
upstream_ref: str | None # Reference to the upstream content, e.g., a serialized library block usage key.
8181
upstream_key: LibraryUsageLocatorV2 | LibraryContainerLocator | None # parsed opaque key version of upstream_ref
82+
upstream_name: str | None # Display name of the upstream content.
8283
downstream_key: str | None # Key of the downstream object.
8384
version_synced: int | None # Version of the upstream to which the downstream was last synced.
8485
version_available: int | None # Latest version of the upstream that's available, or None if it couldn't be loaded.
@@ -223,6 +224,7 @@ def try_get_for_block(cls, downstream: XBlock, log_error: bool = True) -> t.Self
223224
)
224225
return cls(
225226
upstream_ref=getattr(downstream, "upstream", None),
227+
upstream_name=getattr(downstream, "upstream_display_name", None),
226228
upstream_key=None,
227229
downstream_key=str(getattr(downstream, "usage_key", "")),
228230
version_synced=getattr(downstream, "upstream_version", None),
@@ -307,6 +309,7 @@ def get_for_block(cls, downstream: XBlock) -> t.Self:
307309
result = cls(
308310
upstream_ref=downstream.upstream,
309311
upstream_key=upstream_key,
312+
upstream_name=downstream.upstream_display_name,
310313
downstream_key=str(downstream.usage_key),
311314
version_synced=downstream.upstream_version,
312315
version_available=version_available,

cms/static/sass/course-unit-mfe-iframe-bundle.scss

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,32 @@ body,
4444
white-space: nowrap;
4545
overflow: hidden;
4646
text-overflow: ellipsis;
47+
display: flex;
48+
49+
.library-info-icon {
50+
width: 32px;
51+
height: 26px;
52+
margin-top: 2px;
53+
margin-right: 5px;
54+
display: flex;
55+
justify-content: center;
56+
background-color: white;
57+
color: $primary;
58+
border: 1px solid #A9A6A4FF;
59+
border-radius: 4px;
60+
61+
&.two-icons {
62+
width: 60px;
63+
}
64+
65+
&.sync-state {
66+
&:hover {
67+
background-color: $primary;
68+
border-color: $primary;
69+
color: white;
70+
}
71+
}
72+
}
4773
}
4874

4975
.xblock-display-name {

cms/templates/studio_xblock_wrapper.html

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<%page expression_filter="h"/>
22
<%!
33
from django.utils.translation import gettext as _
4+
from openedx.core.djangolib.markup import Text
45
from cms.djangoapps.contentstore.helpers import xblock_studio_url
56
from cms.djangoapps.contentstore.utils import is_visible_to_specific_partition_groups, get_editor_page_base_url, determine_label
67
from lms.lib.utils import is_unit
@@ -112,21 +113,49 @@
112113
% else:
113114
% if upstream_info.upstream_ref:
114115
% if upstream_info.error_message:
115-
<!-- "broken link" icon from https://fonts.google.com/icons?selected=Material+Symbols+Outlined:link_off:FILL@0;wght@400;GRAD@0;opsz@24&icon.size=24&icon.color=%235f6368&icon.query=link -->
116-
<svg role="img" data-tooltip="${_("Sourced from a library - but the upstream link is broken/invalid.")}" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 -960 960 960" style="vertical-align: middle; padding-bottom: 4px;">
117-
<path d="m770-302-60-62q40-11 65-42.5t25-73.5q0-50-35-85t-85-35H520v-80h160q83 0 141.5 58.5T880-480q0 57-29.5 105T770-302ZM634-440l-80-80h86v80h-6ZM792-56 56-792l56-56 736 736-56 56ZM440-280H280q-83 0-141.5-58.5T80-480q0-69 42-123t108-71l74 74h-24q-50 0-85 35t-35 85q0 50 35 85t85 35h160v80ZM320-440v-80h65l79 80H320Z"/>
118-
</svg>
119-
<span class="sr-only">${_("Sourced from a library - but the upstream link is broken/invalid.")}</span>
116+
<div class="library-info-icon two-icons" data-tooltip="${_("The referenced library or library object is not available.")}">
117+
<!-- "library" icon from https://fonts.google.com/icons?selected=Material+Symbols+Outlined:newsstand:FILL@0;wght@400;GRAD@0;opsz@24&icon.size=24 -->
118+
<svg role="img" 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;">
119+
<path d="M80-160v-80h800v80H80Zm80-160v-320h80v320h-80Zm160 0v-480h80v480h-80Zm160 0v-480h80v480h-80Zm280 0L600-600l70-40 160 280-70 40Z"/>
120+
</svg>
121+
<!-- "broken link" icon from https://fonts.google.com/icons?selected=Material+Symbols+Outlined:link_off:FILL@0;wght@400;GRAD@0;opsz@24&icon.size=24&icon.color=%235f6368&icon.query=link -->
122+
<svg role="img" 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;">
123+
<path d="m770-302-60-62q40-11 65-42.5t25-73.5q0-50-35-85t-85-35H520v-80h160q83 0 141.5 58.5T880-480q0 57-29.5 105T770-302ZM634-440l-80-80h86v80h-6ZM792-56 56-792l56-56 736 736-56 56ZM440-280H280q-83 0-141.5-58.5T80-480q0-69 42-123t108-71l74 74h-24q-50 0-85 35t-35 85q0 50 35 85t85 35h160v80ZM320-440v-80h65l79 80H320Z"/>
124+
</svg>
125+
<span class="sr-only">${_("The referenced library or library object is not available.")}</span>
126+
</div>
127+
% elif upstream_info.ready_to_sync:
128+
<button class="library-info-icon two-icons library-sync-button sync-state" data-tooltip="${Text(_("The linked {upstream_name} has updates available.")).format(upstream_name=upstream_info.upstream_name)}">
129+
<!-- "library" icon from https://fonts.google.com/icons?selected=Material+Symbols+Outlined:newsstand:FILL@0;wght@400;GRAD@0;opsz@24&icon.size=24 -->
130+
<svg role="img" 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;">
131+
<path d="M80-160v-80h800v80H80Zm80-160v-320h80v320h-80Zm160 0v-480h80v480h-80Zm160 0v-480h80v480h-80Zm280 0L600-600l70-40 160 280-70 40Z"/>
132+
</svg>
133+
<!-- "sync" icon from https://fonts.google.com/icons?selected=Material+Symbols+Outlined:sync:FILL@0;wght@400;GRAD@0;opsz@24&icon.size=24&icon.color=%235f6368&icon.query=sync&icon.platform=web -->
134+
<svg role="img" 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;">
135+
<path d="M160-160v-80h110l-16-14q-52-46-73-105t-21-119q0-111 66.5-197.5T400-790v84q-72 26-116 88.5T240-478q0 45 17 87.5t53 78.5l10 10v-98h80v240H160Zm400-10v-84q72-26 116-88.5T720-482q0-45-17-87.5T650-648l-10-10v98h-80v-240h240v80H690l16 14q49 49 71.5 106.5T800-482q0 111-66.5 197.5T560-170Z"/>
136+
</svg>
137+
<span class="sr-only">${_("The linked library object has updates available.")}</span>
138+
</button>
139+
% elif len(upstream_info.downstream_customized) > 0:
140+
<div class="library-info-icon two-icons" data-tooltip="${_("This library reference has course overrides applied.")}">
141+
<!-- "library" icon from https://fonts.google.com/icons?selected=Material+Symbols+Outlined:newsstand:FILL@0;wght@400;GRAD@0;opsz@24&icon.size=24 -->
142+
<svg role="img" 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;">
143+
<path d="M80-160v-80h800v80H80Zm80-160v-320h80v320h-80Zm160 0v-480h80v480h-80Zm160 0v-480h80v480h-80Zm280 0L600-600l70-40 160 280-70 40Z"/>
144+
</svg>
145+
<!-- "call split" icon from https://fonts.google.com/icons?selected=Material+Symbols+Outlined:call_split:FILL@0;wght@400;GRAD@0;opsz@24&icon.size=24&icon.color=%235f6368&icon.query=fork -->
146+
<svg role="img" 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;">
147+
<path d="M440-160v-304L240-664v104h-80v-240h240v80H296l224 224v336h-80Zm154-376-58-58 128-126H560v-80h240v240h-80v-104L594-536Z"/>
148+
</svg>
149+
<span class="sr-only">${_("This library reference has course overrides applied.")}</span>
150+
</div>
120151
% else:
121-
<!-- "library" icon from https://fonts.google.com/icons?selected=Material+Symbols+Outlined:newsstand:FILL@0;wght@400;GRAD@0;opsz@24&icon.size=24 -->
122-
<svg role="img" data-tooltip="${_("Sourced from a library - but has been modified locally." if len(upstream_info.downstream_customized) > 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;">
123-
<path d="M80-160v-80h800v80H80Zm80-160v-320h80v320h-80Zm160 0v-480h80v480h-80Zm160 0v-480h80v480h-80Zm280 0L600-600l70-40 160 280-70 40Z"/>
124-
</svg>
125-
% if len(upstream_info.downstream_customized) > 0:
126-
<span class="sr-only">${_("Sourced from a library - but has been modified locally.")}</span>
127-
% else:
128-
<span class="sr-only">${_("Sourced from a library.")}</span>
129-
% endif
152+
<div class="library-info-icon" data-tooltip="${Text(_("This is referenced via {upstream_name}")).format(upstream_name=upstream_info.upstream_name)}">
153+
<!-- "library" icon from https://fonts.google.com/icons?selected=Material+Symbols+Outlined:newsstand:FILL@0;wght@400;GRAD@0;opsz@24&icon.size=24 -->
154+
<svg role="img" 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;">
155+
<path d="M80-160v-80h800v80H80Zm80-160v-320h80v320h-80Zm160 0v-480h80v480h-80Zm160 0v-480h80v480h-80Zm280 0L600-600l70-40 160 280-70 40Z"/>
156+
</svg>
157+
<span class="sr-only">${_("This item is linked to a library item.")}</span>
158+
</div>
130159
% endif
131160
% endif
132161
<span class="xblock-display-name">${label}</span>

0 commit comments

Comments
 (0)