diff --git a/cms/static/cms/js/require-config.js b/cms/static/cms/js/require-config.js index 28898e5cf7be..d2bc6341ebba 100644 --- a/cms/static/cms/js/require-config.js +++ b/cms/static/cms/js/require-config.js @@ -355,9 +355,9 @@ } }, config: { - text: { - useXhr: () => true - } + text: { + useXhr: () => true + } } }); }).call(this, require, define); diff --git a/cms/static/js/models/xblock_info.js b/cms/static/js/models/xblock_info.js index 2b82cf72b15b..60f4ca3e77a2 100644 --- a/cms/static/js/models/xblock_info.js +++ b/cms/static/js/models/xblock_info.js @@ -15,180 +15,138 @@ define( category: null, data: null, metadata: null, - /** - * The Studio URL for this xblock, or null if it doesn't have one. - */ + /** The Studio URL for this xblock, or null if it doesn't have one. */ studio_url: null, /** - * An optional object with information about the children as well as about - * the primary xblock type that is supported as a child. - */ + * An optional object with information about the children as well as about + * the primary xblock type that is supported as a child. + */ child_info: null, - /** - * An optional object with information about each of the ancestors. - */ + /** An optional object with information about each of the ancestors. */ ancestor_info: null, - /** - * Date of the last edit to this xblock or any of its descendants. - */ + /** Date of the last edit to this xblock or any of its descendants. */ edited_on: null, /** - * User who last edited the xblock or any of its descendants. Will only be present if - * publishing info was explicitly requested. - */ + * User who last edited the xblock or any of its descendants. Will only be present if + * publishing info was explicitly requested. + */ edited_by: null, - /** - * True iff a published version of the xblock exists. - */ + /** True iff a published version of the xblock exists. */ published: null, - /** - * Date of the last publish of this xblock, or null if never published. - */ + /** Date of the last publish of this xblock, or null if never published. */ published_on: null, /** - * User who last published the xblock, or null if never published. Will only be present if - * publishing info was explicitly requested. - */ + * User who last published the xblock, or null if never published. Will only be present if + * publishing info was explicitly requested. + */ published_by: null, - /** - * True if the xblock is a parentable xblock. - */ + /** True if the xblock is a parentable xblock. */ has_children: null, /** - * True if the xblock has changes. - * Note: this is not always provided as a performance optimization. It is only provided for - * verticals functioning as units. - */ + * True if the xblock has changes. + * Note: this is not always provided as a performance optimization. It is only provided for + * verticals functioning as units. + */ has_changes: null, /** - * Represents the possible publish states for an xblock. See the documentation - * for XBlockVisibility to see a comprehensive enumeration of the states. - */ + * Represents the possible publish states for an xblock. See the documentation + * for XBlockVisibility to see a comprehensive enumeration of the states. + */ visibility_state: null, /** - * True if the release date of the xblock is in the past. - */ + * True if the release date of the xblock is in the past. + */ released_to_students: null, /** - * If the xblock is published, the date on which it will be released to students. - * This can be null if the release date is unscheduled. - */ + * If the xblock is published, the date on which it will be released to students. + * This can be null if the release date is unscheduled. + */ release_date: null, /** - * The xblock which is determining the release date. For instance, for a unit, - * this will either be the parent subsection or the grandparent section. - * This can be null if the release date is unscheduled. Will only be present if - * publishing info was explicitly requested. - */ + * The xblock which is determining the release date. For instance, for a unit, + * this will either be the parent subsection or the grandparent section. + * This can be null if the release date is unscheduled. Will only be present if + * publishing info was explicitly requested. + */ release_date_from: null, /** - * True if this xblock is currently visible to students. This is computed server-side - * so that the logic isn't duplicated on the client. Will only be present if - * publishing info was explicitly requested. - */ + * True if this xblock is currently visible to students. This is computed server-side + * so that the logic isn't duplicated on the client. Will only be present if + * publishing info was explicitly requested. + */ currently_visible_to_students: null, /** - * If xblock is graded, the date after which student assessment will be evaluated. - * It has same format as release date, for example: 'Jan 02, 2015 at 00:00 UTC'. - */ + * If xblock is graded, the date after which student assessment will be evaluated. + * It has same format as release date, for example: 'Jan 02, 2015 at 00:00 UTC'. + */ due_date: null, - /** - * Grading policy for xblock. - */ + /** Grading policy for xblock. */ format: null, - /** - * List of course graders names. - */ + /** List of course graders names. */ course_graders: null, - /** - * True if this xblock contributes to the final course grade. - */ + /** True if this xblock contributes to the final course grade. */ graded: null, - /** - * The same as `release_date` but as an ISO-formatted date string. - */ + /** The same as `release_date` but as an ISO-formatted date string. */ start: null, - /** - * The same as `due_date` but as an ISO-formatted date string. - */ + /** The same as `due_date` but as an ISO-formatted date string. */ due: null, - /** - * True iff this xblock is explicitly staff locked. - */ + /** True iff this xblock is explicitly staff locked. */ has_explicit_staff_lock: null, - /** - * True iff this any of this xblock's ancestors are staff locked. - */ + /** True iff this any of this xblock's ancestors are staff locked. */ ancestor_has_staff_lock: null, /** - * The xblock which is determining the staff lock value. For instance, for a unit, - * this will either be the parent subsection or the grandparent section. - * This can be null if the xblock has no inherited staff lock. Will only be present if - * publishing info was explicitly requested. - */ + * The xblock which is determining the staff lock value. For instance, for a unit, + * this will either be the parent subsection or the grandparent section. + * This can be null if the xblock has no inherited staff lock. Will only be present if + * publishing info was explicitly requested. + */ staff_lock_from: null, - /** - * True iff this xblock should display a "Contains staff only content" message. - */ + /** True iff this xblock should display a "Contains staff only content" message. */ staff_only_message: null, /** - * True iff this xblock is a unit, and it has children that are only visible to certain - * user partition groups. Note that this is not a recursive property. Will only be present if - * publishing info was explicitly requested. - */ + * True iff this xblock is a unit, and it has children that are only visible to certain + * user partition groups. Note that this is not a recursive property. Will only be present if + * publishing info was explicitly requested. + */ has_partition_group_components: null, /** - * actions defines the state of delete, drag and child add functionality for a xblock. - * currently, each xblock has default value of 'True' for keys: deletable, draggable and childAddable. - */ + * actions defines the state of delete, drag and child add functionality for a xblock. + * currently, each xblock has default value of 'True' for keys: deletable, draggable and childAddable. + */ actions: null, - /** - * Header visible to UI. - */ + /** Header visible to UI. */ is_header_visible: null, - /** - * Optional explanatory message about the xblock. - */ + /** Optional explanatory message about the xblock. */ explanatory_message: null, /** - * The XBlock's group access rules. This is a dictionary keyed to user partition IDs, - * where the values are lists of group IDs. - */ + * The XBlock's group access rules. This is a dictionary keyed to user partition IDs, + * where the values are lists of group IDs. + */ group_access: null, /** - * User partition dictionary. This is pre-processed by Studio, so it contains - * some additional fields that are not stored in the course descriptor - * (for example, which groups are selected for this particular XBlock). - */ + * User partition dictionary. This is pre-processed by Studio, so it contains + * some additional fields that are not stored in the course descriptor + * (for example, which groups are selected for this particular XBlock). + */ user_partitions: null, - /** - * This xBlock's Highlights to message to learners. - */ + /** This xBlock's Highlights to message to learners. */ highlights: [], highlights_enabled: false, highlights_enabled_for_messaging: false, highlights_preview_only: true, highlights_doc_url: '', - /** - * True if summary configuration is enabled. - */ + /** True if summary configuration is enabled. */ summary_configuration_enabled: null, - /** - * List of tags of the unit. This list is managed by the content_tagging module. - */ - tags: null, - /** - * True if the xblock is not visible to students only via links. - */ - hide_from_toc: null, - /** - * True iff this xblock should display a "Contains staff only content" message. - */ - hide_from_toc_message: null, + /** List of tags of the unit. This list is managed by the content_tagging module. */ + tags: null, + /** True if the xblock is not visible to students only via links. */ + hide_from_toc: null, + /** True iff this xblock should display a "Contains staff only content" message. */ + hide_from_toc_message: null, }, initialize: function() { - // Extend our Model by helper methods. + // Extend our Model by helper methods. _.extend(this, this.getCategoryHelpers()); }, @@ -245,9 +203,9 @@ define( }, /** - * Return true if action is required e.g. delete, drag, add new child etc or if given key is not present. - * @return {boolean} - */ + * Return true if action is required e.g. delete, drag, add new child etc or if given key is not present. + * @return {boolean} + */ isActionRequired: function(actionName) { var actions = this.get('actions'); if (actions !== null) { @@ -259,9 +217,9 @@ define( }, /** - * Return a list of convenience methods to check affiliation to the category. - * @return {Array} - */ + * Return a list of convenience methods to check affiliation to the category. + * @return {Array} + */ getCategoryHelpers: function() { var categories = ['course', 'chapter', 'sequential', 'vertical'], helpers = {}; @@ -276,9 +234,9 @@ define( }, /** - * Check if we can edit current XBlock or not on Course Outline page. - * @return {Boolean} - */ + * Check if we can edit current XBlock or not on Course Outline page. + * @return {Boolean} + */ isEditableOnCourseOutline: function() { return this.isSequential() || this.isChapter() || this.isVertical(); } diff --git a/cms/static/js/spec/views/pages/container_subviews_spec.js b/cms/static/js/spec/views/pages/container_subviews_spec.js index 28ea2a4b9196..e74bf82869d5 100644 --- a/cms/static/js/spec/views/pages/container_subviews_spec.js +++ b/cms/static/js/spec/views/pages/container_subviews_spec.js @@ -581,7 +581,6 @@ describe('Container Subviews', function() { }); }); - describe('Message Area', function() { var messageSelector = '.container-message .warning', warningMessage = 'Caution: The last published version of this unit is live. ' diff --git a/cms/static/js/spec/views/pages/course_outline_spec.js b/cms/static/js/spec/views/pages/course_outline_spec.js index c083eb8ec10c..ba975bf7b054 100644 --- a/cms/static/js/spec/views/pages/course_outline_spec.js +++ b/cms/static/js/spec/views/pages/course_outline_spec.js @@ -2540,7 +2540,7 @@ describe('CourseOutlinePage', function() { hide_from_toc: null } }); - }) + }); }); verifyTypePublishable('unit', function(options) { diff --git a/cms/static/js/utils/copy_to_clipboard.js b/cms/static/js/utils/copy_to_clipboard.js index 8c4c22c47128..71d7c6c4be53 100644 --- a/cms/static/js/utils/copy_to_clipboard.js +++ b/cms/static/js/utils/copy_to_clipboard.js @@ -1,31 +1,32 @@ -define(["jquery"], function ($) { - "use strict"; - function copyToClipboard(id, textToCopy) { - if (navigator.clipboard) { - navigator.clipboard.writeText(textToCopy); - changeButtonText(id); - return; +define(['jquery'], function($) { + 'use strict'; + + function copyToClipboard(id, textToCopy) { + if (navigator.clipboard) { + navigator.clipboard.writeText(textToCopy); + changeButtonText(id); + return; + } + const textArea = document.createElement('textarea'); + textArea.value = textToCopy; + document.body.appendChild(textArea); + textArea.select(); + document.execCommand('copy'); + document.body.removeChild(textArea); + changeButtonText(id); } - const textArea = document.createElement("textarea"); - textArea.value = textToCopy; - document.body.appendChild(textArea); - textArea.select(); - document.execCommand("copy"); - document.body.removeChild(textArea); - changeButtonText(id); - } - function changeButtonText(id, delay = 2000) { - const buttonId = `#${id}`; - const textClass = ".copy-link-button-text"; + function changeButtonText(id, delay = 2000) { + const buttonId = `#${id}`; + const textClass = '.copy-link-button-text'; - const previewShareLinkText = $(buttonId).find(textClass).html(); - const shareLinkCopiedText = gettext("Copied"); - $(buttonId).find(textClass).text(shareLinkCopiedText); + const previewShareLinkText = $(buttonId).find(textClass).html(); + const shareLinkCopiedText = gettext('Copied'); + $(buttonId).find(textClass).text(shareLinkCopiedText); - setTimeout(() => { - $(buttonId).find(textClass).text(previewShareLinkText); - }, delay); - } - return { copyToClipboard }; + setTimeout(() => { + $(buttonId).find(textClass).text(previewShareLinkText); + }, delay); + } + return {copyToClipboard}; }); diff --git a/cms/static/js/views/course_outline.js b/cms/static/js/views/course_outline.js index ff1d07696342..0817db168c0e 100644 --- a/cms/static/js/views/course_outline.js +++ b/cms/static/js/views/course_outline.js @@ -237,46 +237,44 @@ function( /** Copy a Unit to the clipboard */ copyXBlock() { - const clipboardEndpoint = "/api/content-staging/v1/clipboard/"; + const clipboardEndpoint = '/api/content-staging/v1/clipboard/'; // Start showing a "Copying" notification: - ViewUtils.runOperationShowingMessage(gettext('Copying'), () => { - return $.postJSON( - clipboardEndpoint, - { usage_key: this.model.get('id') } - ).then((data) => { - // const status = data.content?.status; - const status = data.content && data.content.status; - // ^ platform's old require.js/esprima breaks on newer syntax in some JS files but not all. - if (status === "ready") { - // The Unit has been copied and is ready to use. - this.clipboardManager.updateUserClipboard(data); // This will update the UI and notify other tabs - return data; - } else if (status === "loading") { - // The clipboard is being loaded asynchronously. - // Poll the endpoint until the copying process is complete: - const deferred = $.Deferred(); - const checkStatus = () => { - $.getJSON(clipboardEndpoint, (pollData) => { - // const newStatus = pollData.content?.status; - const newStatus = pollData.content && pollData.content.status; - if (newStatus === "ready") { - this.clipboardManager.updateUserClipboard(pollData); - deferred.resolve(pollData); - } else if (newStatus === "loading") { - setTimeout(checkStatus, 1000); - } else { - deferred.reject(); - throw new Error(`Unexpected clipboard status "${newStatus}" in successful API response.`); - } - }) - } - setTimeout(checkStatus, 1000); - return deferred; - } else { - throw new Error(`Unexpected clipboard status "${status}" in successful API response.`); - } - }); - }); + ViewUtils.runOperationShowingMessage(gettext('Copying'), () => $.postJSON( + clipboardEndpoint, + {usage_key: this.model.get('id')} + ).then((data) => { + // const status = data.content?.status; + const status = data.content && data.content.status; + // ^ platform's old require.js/esprima breaks on newer syntax in some JS files but not all. + if (status === 'ready') { + // The Unit has been copied and is ready to use. + this.clipboardManager.updateUserClipboard(data); // This will update the UI and notify other tabs + return data; + } else if (status === 'loading') { + // The clipboard is being loaded asynchronously. + // Poll the endpoint until the copying process is complete: + const deferred = $.Deferred(); + const checkStatus = () => { + $.getJSON(clipboardEndpoint, (pollData) => { + // const newStatus = pollData.content?.status; + const newStatus = pollData.content && pollData.content.status; + if (newStatus === 'ready') { + this.clipboardManager.updateUserClipboard(pollData); + deferred.resolve(pollData); + } else if (newStatus === 'loading') { + setTimeout(checkStatus, 1000); + } else { + deferred.reject(); + throw new Error(`Unexpected clipboard status "${newStatus}" in successful API response.`); + } + }); + }; + setTimeout(checkStatus, 1000); + return deferred; + } else { + throw new Error(`Unexpected clipboard status "${status}" in successful API response.`); + } + })); }, initializePasteButton(element) { @@ -285,11 +283,11 @@ function( // We should have the user's clipboard status from CourseOutlinePage, whose clipboardManager manages // the clipboard data on behalf of all the XBlocks in the outline. this.refreshPasteButton(this.clipboardManager.userClipboard); - this.clipboardManager.addEventListener("update", (event) => { + this.clipboardManager.addEventListener('update', (event) => { this.refreshPasteButton(event.detail); }); } else { - this.$(".paste-component").hide(); + this.$('.paste-component').hide(); } } }, @@ -301,41 +299,38 @@ function( // 'data' is the same data returned by the "get clipboard status" API endpoint // i.e. /api/content-staging/v1/clipboard/ if (this.options.canEdit && data.content) { - if (data.content.status === "expired") { + if (data.content.status === 'expired') { // This has expired and can no longer be pasted. - this.$(".paste-component").hide(); + this.$('.paste-component').hide(); } else if (data.content.block_type === 'vertical') { // This is suitable for pasting as a unit. - const detailsPopupEl = this.$(".clipboard-details-popup")[0]; + const detailsPopupEl = this.$('.clipboard-details-popup')[0]; // Only Units should have the paste button initialized if (detailsPopupEl !== undefined) { - const detailsPopupEl = this.$(".clipboard-details-popup")[0]; - detailsPopupEl.querySelector(".detail-block-name").innerText = data.content.display_name; - detailsPopupEl.querySelector(".detail-block-type").innerText = data.content.block_type_display; - detailsPopupEl.querySelector(".detail-course-name").innerText = data.source_context_title; + detailsPopupEl.querySelector('.detail-block-name').innerText = data.content.display_name; + detailsPopupEl.querySelector('.detail-block-type').innerText = data.content.block_type_display; + detailsPopupEl.querySelector('.detail-course-name').innerText = data.source_context_title; if (data.source_edit_url) { - detailsPopupEl.setAttribute("href", data.source_edit_url); - detailsPopupEl.classList.remove("no-edit-link"); + detailsPopupEl.setAttribute('href', data.source_edit_url); + detailsPopupEl.classList.remove('no-edit-link'); } else { - detailsPopupEl.setAttribute("href", "#"); - detailsPopupEl.classList.add("no-edit-link"); + detailsPopupEl.setAttribute('href', '#'); + detailsPopupEl.classList.add('no-edit-link'); } - this.$('.paste-component').show() + this.$('.paste-component').show(); } - } else { - this.$('.paste-component').hide() + this.$('.paste-component').hide(); } - } else { this.$('.paste-component').hide(); } }, createPlaceholderElementForPaste(category, componentDisplayName) { - const nameStr = StringUtils.interpolate(gettext("Copy of '{componentDisplayName}'"), { componentDisplayName }, true); - const el = document.createElement("li"); - el.classList.add("outline-item", "outline-" + category, "has-warnings", "is-draggable"); + const nameStr = StringUtils.interpolate(gettext('Copy of "{componentDisplayName}"'), {componentDisplayName}, true); + const el = document.createElement('li'); + el.classList.add('outline-item', 'outline-' + category, 'has-warnings', 'is-draggable'); el.innerHTML = `