diff --git a/catalog-info.yaml b/catalog-info.yaml
index 9eec06ff6c..9fa7a240ea 100644
--- a/catalog-info.yaml
+++ b/catalog-info.yaml
@@ -12,6 +12,7 @@ metadata:
icon: "Web"
annotations:
openedx.org/arch-interest-groups: ""
+ openedx.org/release: "master"
spec:
owner: group:2u-tnl
type: 'website'
diff --git a/openedx.yaml b/openedx.yaml
deleted file mode 100644
index 4e57270214..0000000000
--- a/openedx.yaml
+++ /dev/null
@@ -1,11 +0,0 @@
-# This file describes this Open edX repo, as described in OEP-2:
-# http://open-edx-proposals.readthedocs.io/en/latest/oeps/oep-0002.html#specification
-
-nick: cath
-oeps: {}
-owner: edx/platform-core-tnl
-openedx-release:
- # The openedx-release key is described in OEP-10:
- # https://open-edx-proposals.readthedocs.io/en/latest/oep-0010-proc-openedx-releases.html
- # The FAQ might also be helpful: https://openedx.atlassian.net/wiki/spaces/COMM/pages/1331268879/Open+edX+Release+FAQ
- ref: master
diff --git a/package-lock.json b/package-lock.json
index 6689a22cee..24bd8a4ac7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -6644,9 +6644,9 @@
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001677",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001677.tgz",
- "integrity": "sha512-fmfjsOlJUpMWu+mAAtZZZHz7UEwsUxIIvu1TJfO1HqFQvB/B+ii0xr9B5HpbZY/mC4XZ8SvjHJqtAY6pDPQEog==",
+ "version": "1.0.30001690",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001690.tgz",
+ "integrity": "sha512-5ExiE3qQN6oF8Clf8ifIDcMRCRE/dMGcETG/XGMD8/XiXm6HXQgQTh1yZYLXXpSOsEUlJm1Xr7kGULZTuGtP/w==",
"funding": [
{
"type": "opencollective",
diff --git a/src/CourseAuthoringRoutes.jsx b/src/CourseAuthoringRoutes.jsx
index ded2f07eae..4bef342689 100644
--- a/src/CourseAuthoringRoutes.jsx
+++ b/src/CourseAuthoringRoutes.jsx
@@ -20,6 +20,7 @@ import { CourseUpdates } from './course-updates';
import { CourseUnit, IframeProvider } from './course-unit';
import { Certificates } from './certificates';
import CourseExportPage from './export-page/CourseExportPage';
+import CourseOptimizerPage from './optimizer-page/CourseOptimizerPage';
import CourseImportPage from './import-page/CourseImportPage';
import { DECODED_ROUTES } from './constants';
import CourseChecklist from './course-checklist';
@@ -118,6 +119,10 @@ const CourseAuthoringRoutes = () => {
path="export"
element={}
/>
+ }
+ />
}
diff --git a/src/constants.js b/src/constants.js
index 163a16ef84..80e7cdd778 100644
--- a/src/constants.js
+++ b/src/constants.js
@@ -58,6 +58,7 @@ export const COURSE_BLOCK_NAMES = ({
chapter: { id: 'chapter', name: 'Section' },
sequential: { id: 'sequential', name: 'Subsection' },
vertical: { id: 'vertical', name: 'Unit' },
+ libraryContent: { id: 'library_content', name: 'Library content' },
component: { id: 'component', name: 'Component' },
});
@@ -76,3 +77,7 @@ export const REGEX_RULES = {
specialCharsRule: /^[a-zA-Z0-9_\-.'*~\s]+$/,
noSpaceRule: /^\S*$/,
};
+
+export const IFRAME_FEATURE_POLICY = (
+ 'microphone *; camera *; midi *; geolocation *; encrypted-media *; clipboard-write *'
+);
diff --git a/src/content-tags-drawer/ContentTagsDrawer.test.jsx b/src/content-tags-drawer/ContentTagsDrawer.test.jsx
index 426f0d5323..0ff99eaf27 100644
--- a/src/content-tags-drawer/ContentTagsDrawer.test.jsx
+++ b/src/content-tags-drawer/ContentTagsDrawer.test.jsx
@@ -18,7 +18,7 @@ import {
} from './data/api.mocks';
import { getContentTaxonomyTagsApiUrl } from './data/api';
-const path = '/content/:contentId/*';
+const path = '/content/:contentId?/*';
const mockOnClose = jest.fn();
const mockSetBlockingSheet = jest.fn();
const mockNavigate = jest.fn();
diff --git a/src/course-outline/constants.js b/src/course-outline/constants.js
index 4430694a78..eda0522a03 100644
--- a/src/course-outline/constants.js
+++ b/src/course-outline/constants.js
@@ -87,4 +87,5 @@ export const API_ERROR_TYPES = /** @type {const} */ ({
networkError: 'networkError',
serverError: 'serverError',
unknown: 'unknown',
+ forbidden: 'forbidden',
});
diff --git a/src/course-outline/data/slice.js b/src/course-outline/data/slice.js
index 0bd146f95d..0275555262 100644
--- a/src/course-outline/data/slice.js
+++ b/src/course-outline/data/slice.js
@@ -104,7 +104,7 @@ const slice = createSlice({
...payload,
};
},
- fetchStatusBarSelPacedSuccess: (state, { payload }) => {
+ fetchStatusBarSelfPacedSuccess: (state, { payload }) => {
state.statusBarData.isSelfPaced = payload.isSelfPaced;
},
updateSavingStatus: (state, { payload }) => {
@@ -206,7 +206,7 @@ export const {
updateStatusBar,
updateCourseActions,
fetchStatusBarChecklistSuccess,
- fetchStatusBarSelPacedSuccess,
+ fetchStatusBarSelfPacedSuccess,
updateFetchSectionLoadingStatus,
updateCourseLaunchQueryStatus,
updateSavingStatus,
diff --git a/src/course-outline/data/thunk.js b/src/course-outline/data/thunk.js
index c555fcb978..457d039114 100644
--- a/src/course-outline/data/thunk.js
+++ b/src/course-outline/data/thunk.js
@@ -1,7 +1,7 @@
import { RequestStatus } from '../../data/constants';
import { updateClipboardData } from '../../generic/data/slice';
import { NOTIFICATION_MESSAGES } from '../../constants';
-import { API_ERROR_TYPES, COURSE_BLOCK_NAMES } from '../constants';
+import { COURSE_BLOCK_NAMES } from '../constants';
import {
hideProcessingNotification,
showProcessingNotification,
@@ -10,6 +10,7 @@ import {
getCourseBestPracticesChecklist,
getCourseLaunchChecklist,
} from '../utils/getChecklistForStatusBar';
+import { getErrorDetails } from '../utils/getErrorDetails';
import {
addNewCourseItem,
deleteCourseItem,
@@ -41,7 +42,7 @@ import {
updateStatusBar,
updateCourseActions,
fetchStatusBarChecklistSuccess,
- fetchStatusBarSelPacedSuccess,
+ fetchStatusBarSelfPacedSuccess,
updateSavingStatus,
updateSectionList,
updateFetchSectionLoadingStatus,
@@ -54,24 +55,6 @@ import {
updateCourseLaunchQueryStatus,
} from './slice';
-const getErrorDetails = (error, dismissible = true) => {
- const errorInfo = { dismissible };
- if (error.response?.data) {
- const { data } = error.response;
- if ((typeof data === 'string' && !data.includes('