From 2d8f5fd6e328dc727325cd12984eeeabe8d8d253 Mon Sep 17 00:00:00 2001 From: Braden MacDonald Date: Mon, 27 Jan 2025 14:26:26 -0800 Subject: [PATCH] chore: fix lint warnings in course_outline.js --- cms/static/js/views/course_outline.js | 167 ++++++++++++-------------- 1 file changed, 79 insertions(+), 88 deletions(-) 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 = `

@@ -369,17 +364,15 @@ function( $listPanel.append($placeholderEl); // Start showing a "Pasting" notification: - ViewUtils.runOperationShowingMessage(gettext('Pasting'), () => { - return $.postJSON(this.model.urlRoot + '/', { - parent_locator: parentLocator, - staged_content: "clipboard", - }).then((data) => { - this.refresh(); // Update this and replace the placeholder with the actual pasted unit. - return data; - }).fail(() => { - $placeholderEl.remove(); - }); - }).done((data) => { + ViewUtils.runOperationShowingMessage(gettext('Pasting'), () => $.postJSON(this.model.urlRoot + '/', { + parent_locator: parentLocator, + staged_content: 'clipboard', + }).then((data) => { + this.refresh(); // Update this and replace the placeholder with the actual pasted unit. + return data; + }).fail(() => { + $placeholderEl.remove(); + })).done((data) => { const { conflicting_files: conflictingFiles, error_files: errorFiles, @@ -389,32 +382,32 @@ function( const notices = []; if (errorFiles.length) { notices.push((next) => new PromptView.Error({ - title: gettext("Some errors occurred"), + title: gettext('Some errors occurred'), message: ( - gettext("The following required files could not be added to the course:") + - " " + errorFiles.join(", ") + gettext('The following required files could not be added to the course:') + + ' ' + errorFiles.join(', ') ), - actions: {primary: {text: gettext("OK"), click: (x) => { x.hide(); next(); }}}, + actions: {primary: {text: gettext('OK'), click: (x) => { x.hide(); next(); }}}, })); } if (conflictingFiles.length) { notices.push((next) => new PromptView.Warning({ - title: gettext("You may need to update a file(s) manually"), + title: gettext('You may need to update a file(s) manually'), message: ( gettext( - "The following files already exist in this course but don't match the " + - "version used by the component you pasted:" - ) + " " + conflictingFiles.join(", ") + 'The following files already exist in this course but don\'t match the ' + + 'version used by the component you pasted:' + ) + ' ' + conflictingFiles.join(', ') ), - actions: {primary: {text: gettext("OK"), click: (x) => { x.hide(); next(); }}}, + actions: {primary: {text: gettext('OK'), click: (x) => { x.hide(); next(); }}}, })); } if (newFiles.length) { notices.push(() => new NotificationView.Info({ - title: gettext("New file(s) added to Files & Uploads."), + title: gettext('New file(s) added to Files & Uploads.'), message: ( - gettext("The following required files were imported to this course:") + - " " + newFiles.join(", ") + gettext('The following required files were imported to this course:') + + ' ' + newFiles.join(', ') ), actions: { primary: { @@ -423,7 +416,6 @@ function( const article = document.querySelector('[data-course-assets]'); const assetsUrl = $(article).attr('data-course-assets'); window.location.href = assetsUrl; - return; } }, secondary: { @@ -440,7 +432,7 @@ function( const showNext = () => { const view = notices.shift()(showNext); view.show(); - } + }; // Delay to avoid conflict with the "Pasting..." notification. setTimeout(showNext, 1250); } @@ -478,14 +470,13 @@ function( * If the new "Actions" menu is enabled, most actions like Configure, * Duplicate, Move, Delete, etc. are moved into this menu. For this * event, we just toggle displaying the menu. - * @param {*} event */ showActionsMenu(event) { const showActionsButton = event.currentTarget; - const subMenu = showActionsButton.parentElement.querySelector(".wrapper-nav-sub"); + const subMenu = showActionsButton.parentElement.querySelector('.wrapper-nav-sub'); // Close all open dropdowns - const elements = document.querySelectorAll("li.action-item.action-actions-menu.nav-item"); + const elements = document.querySelectorAll('li.action-item.action-actions-menu.nav-item'); elements.forEach(element => { if (element !== showActionsButton.parentElement) { element.querySelector('.wrapper-nav-sub').classList.remove('is-shown'); @@ -494,7 +485,7 @@ function( // Code in 'base.js' normally handles toggling these dropdowns but since this one is // not present yet during the domReady event, we have to handle displaying it ourselves. - subMenu.classList.toggle("is-shown"); + subMenu.classList.toggle('is-shown'); // if propagation is not stopped, the event will bubble up to the // body element, which will close the dropdown. event.stopPropagation();