feat: [FC-0070] add message events and styles to the library content page (#35785)
This introduces improvements for XBlock interactions within iframes: * Add default styles for Library Content that renders in the iframe in the new Studio unit page * When the `isIframeEmbed` option is enabled, the XBlock sends a `postMessage` to the parent window. When sending such a message, the standard link transition is cancelled and the transition is carried out in the MFE.
This commit is contained in:
@@ -265,9 +265,10 @@ class GetItemTest(ItemTest):
|
||||
html,
|
||||
# The instance of the wrapper class will have an auto-generated ID. Allow any
|
||||
# characters after wrapper.
|
||||
'"/container/{}" class="action-button">\\s*<span class="action-button-text">View</span>'.format(
|
||||
re.escape(str(wrapper_usage_key))
|
||||
),
|
||||
(
|
||||
'"/container/{}" class="action-button xblock-view-action-button">'
|
||||
'\\s*<span class="action-button-text">View</span>'
|
||||
).format(re.escape(str(wrapper_usage_key))),
|
||||
)
|
||||
|
||||
@patch("cms.djangoapps.contentstore.xblock_storage_handlers.xblock_helpers.get_object_tag_counts")
|
||||
|
||||
@@ -39,6 +39,7 @@ function($, _, Backbone, gettext, BasePage,
|
||||
'click .manage-tags-button': 'openManageTags',
|
||||
'change .header-library-checkbox': 'toggleLibraryComponent',
|
||||
'click .collapse-button': 'collapseXBlock',
|
||||
'click .xblock-view-action-button': 'viewXBlockContent',
|
||||
},
|
||||
|
||||
options: {
|
||||
@@ -808,10 +809,6 @@ function($, _, Backbone, gettext, BasePage,
|
||||
this.deleteComponent(this.findXBlockElement(event.target));
|
||||
},
|
||||
|
||||
createPlaceholderElement: function() {
|
||||
return $('<div/>', {class: 'studio-xblock-wrapper'});
|
||||
},
|
||||
|
||||
createComponent: function(template, target) {
|
||||
// A placeholder element is created in the correct location for the new xblock
|
||||
// and then onNewXBlock will replace it with a rendering of the xblock. Note that
|
||||
@@ -905,6 +902,26 @@ function($, _, Backbone, gettext, BasePage,
|
||||
}
|
||||
},
|
||||
|
||||
viewXBlockContent: function(event) {
|
||||
try {
|
||||
if (this.options.isIframeEmbed) {
|
||||
event.preventDefault();
|
||||
var usageId = event.currentTarget.href.split('/').pop() || '';
|
||||
window.parent.postMessage(
|
||||
{
|
||||
type: 'handleViewXBlockContent',
|
||||
payload: {
|
||||
usageId: usageId,
|
||||
},
|
||||
}, document.referrer
|
||||
);
|
||||
return true;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
},
|
||||
|
||||
toggleSaveButton: function() {
|
||||
var $saveButton = $('.nav-actions .save-button');
|
||||
if (JSON.stringify(this.selectedLibraryComponents.sort()) === JSON.stringify(this.storedSelectedLibraryComponents.sort())) {
|
||||
|
||||
@@ -1,14 +1,22 @@
|
||||
@import 'cms/theme/variables-v1';
|
||||
@import 'elements/course-unit-mfe-iframe';
|
||||
|
||||
body {
|
||||
min-width: 800px;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
.inner-wrapper {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.wrapper-xblock {
|
||||
background-color: $transparent;
|
||||
border-radius: 6px;
|
||||
border: none;
|
||||
|
||||
&:hover {
|
||||
border-color: none;
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
.xblock-header-primary {
|
||||
@@ -23,6 +31,54 @@
|
||||
}
|
||||
}
|
||||
|
||||
.xblock-header-secondary {
|
||||
border-radius: 0 0 4px 4px;
|
||||
|
||||
.actions-list .action-item .action-button {
|
||||
border-radius: 4px;
|
||||
|
||||
&:hover {
|
||||
background-color: $primary;
|
||||
color: $white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.level-page .xblock-message {
|
||||
padding: ($baseline * .75) ($baseline * 1.2);
|
||||
border-radius: 0 0 4px 4px;
|
||||
|
||||
&.information {
|
||||
color: $text-color;
|
||||
background-color: $xblock-message-info-bg;
|
||||
border-color: $xblock-message-info-border-color;
|
||||
}
|
||||
|
||||
&.validation.has-warnings {
|
||||
color: $black;
|
||||
background-color: $xblock-message-warning-bg;
|
||||
border-color: $xblock-message-warning-border-color;
|
||||
border-top-width: 1px;
|
||||
|
||||
.icon {
|
||||
color: $xblock-message-warning-border-color;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
color: $primary;
|
||||
}
|
||||
}
|
||||
|
||||
.xblock-author_view-library_content > .wrapper-xblock-message .xblock-message {
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
border-radius: 4px;
|
||||
padding: ($baseline * 1.2);
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, .15), 0 1px 4px rgba(0, 0, 0, .15);
|
||||
margin-bottom: ($baseline * 1.4);
|
||||
}
|
||||
|
||||
&.level-element {
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, .15), 0 2px 8px rgba(0, 0, 0, .15);
|
||||
margin: 0 0 ($baseline * 1.4) 0;
|
||||
@@ -40,28 +96,34 @@
|
||||
border-bottom-right-radius: 6px;
|
||||
}
|
||||
|
||||
.wrapper-xblock .header-actions .actions-list .action-item .action-button {
|
||||
@extend %button-styles;
|
||||
|
||||
color: $primary;
|
||||
|
||||
.fa-ellipsis-v {
|
||||
font-size: $base-font-size;
|
||||
.wrapper-xblock .header-actions .actions-list {
|
||||
.action-actions-menu:last-of-type .nav-sub {
|
||||
right: 120px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: $primary;
|
||||
color: $white;
|
||||
border-color: $transparent;
|
||||
color: $white;
|
||||
}
|
||||
.action-item .action-button {
|
||||
@extend %button-styles;
|
||||
|
||||
&:focus {
|
||||
outline: 2px $transparent;
|
||||
background-color: $transparent;
|
||||
box-shadow: inset 0 0 0 2px $primary;
|
||||
color: $primary;
|
||||
border-color: $transparent;
|
||||
|
||||
.fa-ellipsis-v {
|
||||
font-size: $base-font-size;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: $primary;
|
||||
color: $white;
|
||||
border-color: $transparent;
|
||||
color: $white;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: 2px $transparent;
|
||||
background-color: $transparent;
|
||||
box-shadow: inset 0 0 0 2px $primary;
|
||||
color: $primary;
|
||||
border-color: $transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -631,7 +693,7 @@ select {
|
||||
}
|
||||
}
|
||||
|
||||
.xblock-header-primary {
|
||||
.xblock-header:not(.xblock-header-library_content, .xblock-header-split_test) .xblock-header-primary {
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
|
||||
@@ -315,3 +315,8 @@ $base-font-size: 18px !default;
|
||||
$dark: #212529;
|
||||
|
||||
$zindex-dropdown: 100;
|
||||
|
||||
$xblock-message-info-bg: #eff8fa;
|
||||
$xblock-message-info-border-color: #9cd2e6;
|
||||
$xblock-message-warning-bg: #fffdf0;
|
||||
$xblock-message-warning-border-color: #fff6bf;
|
||||
|
||||
@@ -229,7 +229,7 @@ upstream_info = UpstreamLink.try_get_for_block(xblock)
|
||||
<div class="meta-info">${_('This block contains multiple components.')}</div>
|
||||
<ul class="actions-list">
|
||||
<li class="action-item action-view">
|
||||
<a href="${xblock_url}" class="action-button">
|
||||
<a href="${xblock_url}" class="action-button xblock-view-action-button">
|
||||
## Translators: this is a verb describing the action of viewing more details
|
||||
<span class="action-button-text">${('View')}</span>
|
||||
<span class="icon fa fa-arrow-right" aria-hidden="true"></span>
|
||||
|
||||
Reference in New Issue
Block a user