diff --git a/package-lock.json b/package-lock.json index 1268feda46..a9abbc4127 100644 --- a/package-lock.json +++ b/package-lock.json @@ -47,7 +47,6 @@ "lodash": "4.17.21", "moment": "2.29.4", "prop-types": "15.7.2", - "querystring": "0.2.1", "react": "17.0.2", "react-datepicker": "^4.13.0", "react-dom": "17.0.2", @@ -22072,15 +22071,6 @@ "node": ">=4" } }, - "node_modules/querystring": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.1.tgz", - "integrity": "sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==", - "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", - "engines": { - "node": ">=0.4.x" - } - }, "node_modules/querystringify": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", diff --git a/package.json b/package.json index c0c2ee214d..1d9782c140 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,6 @@ "@edx/frontend-lib-content-components": "^2.0.0", "@edx/frontend-platform": "7.0.1", "@edx/openedx-atlas": "^0.6.0", - "@openedx/paragon": "^21.5.7", "@edx/react-unit-test-utils": "^1.7.0", "@fortawesome/fontawesome-svg-core": "1.2.36", "@fortawesome/free-brands-svg-icons": "5.15.4", @@ -54,14 +53,15 @@ "@fortawesome/react-fontawesome": "0.2.0", "@openedx-plugins/course-app-calculator": "file:plugins/course-apps/calculator", "@openedx-plugins/course-app-edxnotes": "file:plugins/course-apps/edxnotes", + "@openedx-plugins/course-app-learning_assistant": "file:plugins/course-apps/learning_assistant", "@openedx-plugins/course-app-live": "file:plugins/course-apps/live", "@openedx-plugins/course-app-ora_settings": "file:plugins/course-apps/ora_settings", "@openedx-plugins/course-app-proctoring": "file:plugins/course-apps/proctoring", "@openedx-plugins/course-app-progress": "file:plugins/course-apps/progress", "@openedx-plugins/course-app-teams": "file:plugins/course-apps/teams", "@openedx-plugins/course-app-wiki": "file:plugins/course-apps/wiki", - "@openedx-plugins/course-app-learning_assistant": "file:plugins/course-apps/learning_assistant", "@openedx-plugins/course-app-xpert_unit_summary": "file:plugins/course-apps/xpert_unit_summary", + "@openedx/paragon": "^21.5.7", "@reduxjs/toolkit": "1.9.7", "@tanstack/react-query": "4.36.1", "broadcast-channel": "^7.0.0", @@ -88,22 +88,22 @@ "regenerator-runtime": "0.13.7", "universal-cookie": "^4.0.4", "uuid": "^3.4.0", - "yup": "0.31.1", - "querystring": "0.2.1" + "yup": "0.31.1" }, "devDependencies": { "@edx/browserslist-config": "1.2.0", - "@openedx/frontend-build": "13.0.27", "@edx/react-unit-test-utils": "^2.0.0", "@edx/reactifex": "^1.0.3", "@edx/stylelint-config-edx": "2.3.0", "@edx/typescript-config": "^1.0.1", + "@openedx/frontend-build": "13.0.27", "@testing-library/jest-dom": "5.17.0", "@testing-library/react": "12.1.5", "@testing-library/react-hooks": "^8.0.1", "@testing-library/user-event": "^13.2.1", "axios": "^0.27.2", "axios-mock-adapter": "1.22.0", + "copy-webpack-plugin": "^11.0.0", "eslint-import-resolver-webpack": "^0.13.8", "glob": "7.2.3", "husky": "7.0.4", @@ -111,8 +111,7 @@ "jest-expect-message": "^1.1.3", "react-test-renderer": "17.0.2", "reactifex": "1.1.1", - "ts-loader": "^9.5.0", - "copy-webpack-plugin": "^11.0.0" + "ts-loader": "^9.5.0" }, "peerDependencies": { "decode-uri-component": ">=0.2.2" diff --git a/src/course-unit/course-xblock/CourseXBlock.jsx b/src/course-unit/course-xblock/CourseXBlock.jsx index f7734522bc..ac46d42379 100644 --- a/src/course-unit/course-xblock/CourseXBlock.jsx +++ b/src/course-unit/course-xblock/CourseXBlock.jsx @@ -17,18 +17,18 @@ import { COURSE_BLOCK_NAMES } from '../../constants'; import { getCanEdit, getCourseId, - getXBlockIframeHtmlAndResources, + getXBlockIFrameHtmlAndResources, } from '../data/selectors'; import { copyToClipboard, - fetchXBlockIframeHtmlAndResourcesQuery, + fetchXBlockIFrameHtmlAndResourcesQuery, } from '../data/thunk'; +import { getHandlerUrl } from '../data/api'; import { COMPONENT_TYPES } from '../constants'; import XBlockMessages from './xblock-messages/XBlockMessages'; import RenderErrorAlert from './render-error-alert'; import { XBlockContent } from './xblock-content'; import messages from './messages'; -import { getHandlerUrl } from './utils'; const CourseXBlock = ({ id, title, type, unitXBlockActions, shouldScroll, userPartitionInfo, @@ -42,15 +42,15 @@ const CourseXBlock = ({ const courseId = useSelector(getCourseId); const canEdit = useSelector(getCanEdit); const intl = useIntl(); - const xblockIframeHtmlAndResources = useSelector(getXBlockIframeHtmlAndResources); - const xblockInstanceHtmlAndResources = find(xblockIframeHtmlAndResources, { xblockId: id }); + const xblockIFrameHtmlAndResources = useSelector(getXBlockIFrameHtmlAndResources); + const xblockInstanceHtmlAndResources = find(xblockIFrameHtmlAndResources, { xblockId: id }); const visibilityMessage = userPartitionInfo.selectedGroupsLabel ? intl.formatMessage(messages.visibilityMessage, { selectedGroupsLabel: userPartitionInfo.selectedGroupsLabel }) : null; useEffect(() => { - dispatch(fetchXBlockIframeHtmlAndResourcesQuery(id)); + dispatch(fetchXBlockIFrameHtmlAndResourcesQuery(id)); }, []); const currentItemData = { diff --git a/src/course-unit/course-xblock/CourseXBlock.test.jsx b/src/course-unit/course-xblock/CourseXBlock.test.jsx index e588fc8701..8424f71620 100644 --- a/src/course-unit/course-xblock/CourseXBlock.test.jsx +++ b/src/course-unit/course-xblock/CourseXBlock.test.jsx @@ -323,7 +323,7 @@ describe('', () => { const errorAlertDescription = renderErrorAlertMessages.alertRenderErrorDescription.defaultMessage; const errorAlertMessage = renderErrorAlertMessages.alertRenderErrorMessage.defaultMessage .replace('{message}', renderErrorMessage); - const contentIframe = queryByTestId('content-iframe-test-id'); + const contentIFrame = queryByTestId('content-iframe-test-id'); expect(getByText(errorAlertTitle)).toBeInTheDocument(); expect(getByText(errorAlertDescription)).toBeInTheDocument(); @@ -331,6 +331,6 @@ describe('', () => { expect(getByText(name)).toBeInTheDocument(); expect(getByLabelText(messages.blockAltButtonEdit.defaultMessage)).toBeInTheDocument(); expect(getByLabelText(messages.blockActionsDropdownAlt.defaultMessage)).toBeInTheDocument(); - expect(contentIframe).not.toBeInTheDocument(); + expect(contentIFrame).not.toBeInTheDocument(); }); }); diff --git a/src/course-unit/course-xblock/utils.js b/src/course-unit/course-xblock/utils.js deleted file mode 100644 index 5aaae68488..0000000000 --- a/src/course-unit/course-xblock/utils.js +++ /dev/null @@ -1,10 +0,0 @@ -import { getConfig } from '@edx/frontend-platform'; - -const getXBlockHandlerUrl = async (blockId, handlerName) => { - const baseUrl = getConfig().STUDIO_BASE_URL; - - return `${baseUrl}/xblock/${blockId}/handler/${handlerName}`; -}; - -// eslint-disable-next-line import/prefer-default-export -export const getHandlerUrl = async (blockId) => getXBlockHandlerUrl(blockId, 'handler_name'); diff --git a/src/course-unit/course-xblock/xblock-content/XBlockContent.jsx b/src/course-unit/course-xblock/xblock-content/XBlockContent.jsx index 1e6a620878..39ec9e569c 100644 --- a/src/course-unit/course-xblock/xblock-content/XBlockContent.jsx +++ b/src/course-unit/course-xblock/xblock-content/XBlockContent.jsx @@ -9,22 +9,13 @@ import { wrapBlockHtmlForIFrame } from './iframe-wrapper'; ensureConfig(['STUDIO_BASE_URL', 'SECURE_ORIGIN_XBLOCK_BOOTSTRAP_HTML_URL'], 'studio xblock component'); -/** - * React component that displays an XBlock in a sandboxed IFrame. - * - * The IFrame is resized responsively so that it fits the content height. - * - * We use an IFrame so that the XBlock code, including user-authored HTML, - * cannot access things like the user's cookies, nor can it make GET/POST - * requests as the user. However, it is allowed to call any XBlock handlers. - */ const XBlockContent = ({ view, type, getHandlerUrl, onBlockNotification, }) => { const iframeRef = useRef(null); const [html, setHtml] = useState(null); - const [iFrameHeight, setIFrameHeight] = useState(0); - const [iframeKey, setIframeKey] = useState(0); + const [iframeHeight, setIFrameHeight] = useState(0); + const [iframeKey, setIFrameKey] = useState(0); const [isLoading, setIsLoading] = useState(true); useEffect(() => { @@ -40,7 +31,7 @@ const XBlockContent = ({ // Load the XBlock HTML into the IFrame: // iframe will only re-render in React when its property changes (key here) setHtml(newHtml); - setIframeKey(prevKey => prevKey + 1); + setIFrameKey(prevKey => prevKey + 1); } }; @@ -75,7 +66,7 @@ const XBlockContent = ({ if (onBlockNotification) { // This is a notification from the XBlock's frontend via 'runtime.notify(event, args)' onBlockNotification({ - eventType: method.substr(7), // Remove the 'xblock:' prefix that we added in iframe-wrapper.ts + eventType: method.substr('xblock'.length), // Remove the 'xblock:' prefix that we added in iframe-wrapper.ts ...args, }); } @@ -106,7 +97,7 @@ const XBlockContent = ({ )}