diff --git a/package-lock.json b/package-lock.json
index 0cb11bbc25..619ccdcfb1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -23,7 +23,7 @@
"@fortawesome/free-solid-svg-icons": "5.15.4",
"@fortawesome/react-fontawesome": "^0.1.4",
"@openedx/frontend-build": "^14.5.0",
- "@openedx/frontend-plugin-framework": "^1.6.0",
+ "@openedx/frontend-plugin-framework": "^1.7.0",
"@openedx/frontend-slot-footer": "^1.0.2",
"@openedx/paragon": "^22.16.0",
"@popperjs/core": "2.11.8",
diff --git a/package.json b/package.json
index 2adaba4a41..01320f946c 100644
--- a/package.json
+++ b/package.json
@@ -46,7 +46,7 @@
"@fortawesome/free-solid-svg-icons": "5.15.4",
"@fortawesome/react-fontawesome": "^0.1.4",
"@openedx/frontend-build": "^14.5.0",
- "@openedx/frontend-plugin-framework": "^1.6.0",
+ "@openedx/frontend-plugin-framework": "^1.7.0",
"@openedx/frontend-slot-footer": "^1.0.2",
"@openedx/paragon": "^22.16.0",
"@popperjs/core": "2.11.8",
diff --git a/src/course-home/outline-tab/OutlineTab.jsx b/src/course-home/outline-tab/OutlineTab.jsx
index 35f28e6047..db33f55fc5 100644
--- a/src/course-home/outline-tab/OutlineTab.jsx
+++ b/src/course-home/outline-tab/OutlineTab.jsx
@@ -5,7 +5,7 @@ import { sendTrackEvent } from '@edx/frontend-platform/analytics';
import { getAuthenticatedUser } from '@edx/frontend-platform/auth';
import { useIntl } from '@edx/frontend-platform/i18n';
import { Button } from '@openedx/paragon';
-import { PluginSlot } from '@openedx/frontend-plugin-framework';
+import { CourseOutlineTabNotificationsSlot } from '../../plugin-slots/CourseOutlineTabNotificationsSlot';
import { AlertList } from '../../generic/user-messages';
import CourseDates from './widgets/CourseDates';
@@ -181,13 +181,7 @@ const OutlineTab = () => {
/>
)}
-
+
diff --git a/src/course-home/outline-tab/OutlineTab.test.jsx b/src/course-home/outline-tab/OutlineTab.test.jsx
index 8a95e66ae7..39852568b7 100644
--- a/src/course-home/outline-tab/OutlineTab.test.jsx
+++ b/src/course-home/outline-tab/OutlineTab.test.jsx
@@ -139,7 +139,7 @@ describe('Outline Tab', () => {
});
await fetchAndRender();
- expect(screen.getByTestId('outline_tab_notifications_slot')).toBeInTheDocument();
+ expect(screen.getByTestId('org.openedx.frontend.learning.course_outline_tab_notifications.v1')).toBeInTheDocument();
});
it('handles expand/collapse all button click', async () => {
diff --git a/src/courseware/course/new-sidebar/sidebars/discussions-notifications/notifications/NotificationsWidget.test.tsx b/src/courseware/course/new-sidebar/sidebars/discussions-notifications/notifications/NotificationsWidget.test.tsx
index ce89c30a4b..70205f65f9 100644
--- a/src/courseware/course/new-sidebar/sidebars/discussions-notifications/notifications/NotificationsWidget.test.tsx
+++ b/src/courseware/course/new-sidebar/sidebars/discussions-notifications/notifications/NotificationsWidget.test.tsx
@@ -90,7 +90,7 @@ describe('NotificationsWidget', () => {
,
);
- expect(screen.getByTestId('notification_widget_slot')).toBeInTheDocument();
+ expect(screen.getByTestId('org.openedx.frontend.learning.notification_widget.v1')).toBeInTheDocument();
});
it('renders no notifications bar if no verified mode', async () => {
diff --git a/src/courseware/course/new-sidebar/sidebars/discussions-notifications/notifications/NotificationsWidget.tsx b/src/courseware/course/new-sidebar/sidebars/discussions-notifications/notifications/NotificationsWidget.tsx
index 50644782c6..a9ade46d85 100644
--- a/src/courseware/course/new-sidebar/sidebars/discussions-notifications/notifications/NotificationsWidget.tsx
+++ b/src/courseware/course/new-sidebar/sidebars/discussions-notifications/notifications/NotificationsWidget.tsx
@@ -1,10 +1,10 @@
import React, { useContext, useEffect, useMemo } from 'react';
import { sendTrackEvent } from '@edx/frontend-platform/analytics';
-import { PluginSlot } from '@openedx/frontend-plugin-framework';
import { useModel } from '../../../../../../generic/model-store';
import { WIDGETS } from '../../../../../../constants';
import SidebarContext from '../../../SidebarContext';
+import { NotificationWidgetSlot } from '../../../../../../plugin-slots/NotificationWidgetSlot';
const NotificationsWidget = () => {
const {
@@ -67,15 +67,11 @@ const NotificationsWidget = () => {
return (
diff --git a/src/courseware/course/sequence/Unit/ContentIFrame.test.jsx b/src/courseware/course/sequence/Unit/ContentIFrame.test.jsx
index bc2443a464..610d771e09 100644
--- a/src/courseware/course/sequence/Unit/ContentIFrame.test.jsx
+++ b/src/courseware/course/sequence/Unit/ContentIFrame.test.jsx
@@ -6,6 +6,7 @@ import { shallow } from '@edx/react-unit-test-utils';
import PageLoading from '@src/generic/PageLoading';
+import { ContentIFrameLoaderSlot } from '@src/plugin-slots/ContentIFrameLoaderSlot';
import * as hooks from './hooks';
import ContentIFrame, { IFRAME_FEATURE_POLICY, testIDs } from './ContentIFrame';
@@ -99,8 +100,8 @@ describe('ContentIFrame Component', () => {
});
it('displays PageLoading component if not showError', () => {
el = shallow(
);
- [component] = el.instance.findByType(PageLoading);
- expect(component.props.srMessage).toEqual(props.loadingMessage);
+ [component] = el.instance.findByType(ContentIFrameLoaderSlot);
+ expect(component.props.loadingMessage).toEqual(props.loadingMessage);
});
});
describe('hasLoaded', () => {
diff --git a/src/courseware/course/sequence/Unit/UnitSuspense.jsx b/src/courseware/course/sequence/Unit/UnitSuspense.jsx
index 09843a7164..63203ef7b3 100644
--- a/src/courseware/course/sequence/Unit/UnitSuspense.jsx
+++ b/src/courseware/course/sequence/Unit/UnitSuspense.jsx
@@ -2,14 +2,13 @@ import React, { Suspense } from 'react';
import PropTypes from 'prop-types';
import { useIntl } from '@edx/frontend-platform/i18n';
-import { PluginSlot } from '@openedx/frontend-plugin-framework';
import { useModel } from '@src/generic/model-store';
import PageLoading from '@src/generic/PageLoading';
+import { GatedUnitContentMessageSlot } from '../../../../plugin-slots/GatedUnitContentMessageSlot';
import messages from '../messages';
import HonorCode from '../honor-code';
-import LockPaywall from '../lock-paywall';
import * as hooks from './hooks';
import { modelKeys } from './constants';
@@ -29,14 +28,7 @@ const UnitSuspense = ({
<>
{shouldDisplayContentGating && (
}>
-
-
-
+
)}
{shouldDisplayHonorCode && (
diff --git a/src/courseware/course/sequence/Unit/UnitSuspense.test.jsx b/src/courseware/course/sequence/Unit/UnitSuspense.test.jsx
index f47ee6b241..db829eaa46 100644
--- a/src/courseware/course/sequence/Unit/UnitSuspense.test.jsx
+++ b/src/courseware/course/sequence/Unit/UnitSuspense.test.jsx
@@ -5,6 +5,7 @@ import { formatMessage, shallow } from '@edx/react-unit-test-utils';
import { useModel } from '@src/generic/model-store';
import PageLoading from '@src/generic/PageLoading';
+import { GatedUnitContentMessageSlot } from '@src/plugin-slots/GatedUnitContentMessageSlot';
import messages from '../messages';
import HonorCode from '../honor-code';
import LockPaywall from '../lock-paywall';
@@ -78,10 +79,9 @@ describe('UnitSuspense component', () => {
beforeEach(() => { mockModels(true, true); });
it('displays LockPaywall in Suspense wrapper with PageLoading fallback', () => {
el = shallow(
);
- const [component] = el.instance.findByType(LockPaywall);
- expect(component.parent.type).toEqual('PluginSlot');
- expect(component.parent.parent.type).toEqual('Suspense');
- expect(component.parent.parent.props.fallback)
+ const [component] = el.instance.findByType(GatedUnitContentMessageSlot);
+ expect(component.parent.type).toEqual('Suspense');
+ expect(component.parent.props.fallback)
.toEqual(
);
expect(component.props.courseId).toEqual(props.courseId);
});
diff --git a/src/courseware/course/sequence/Unit/index.test.jsx b/src/courseware/course/sequence/Unit/index.test.jsx
index db21d9c7b0..0e3a0ff6f9 100644
--- a/src/courseware/course/sequence/Unit/index.test.jsx
+++ b/src/courseware/course/sequence/Unit/index.test.jsx
@@ -57,7 +57,7 @@ describe('
', () => {
describe('unit title', () => {
it('has two children', () => {
renderComponent(defaultProps);
- const unitTitleWrapper = screen.getByTestId('unit_title_slot').children[0];
+ const unitTitleWrapper = screen.getByTestId('org.openedx.frontend.learning.unit_title.v1').children[0];
expect(unitTitleWrapper.children).toHaveLength(3);
});
diff --git a/src/courseware/course/sidebar/sidebars/notifications/NotificationTray.jsx b/src/courseware/course/sidebar/sidebars/notifications/NotificationTray.jsx
index 5b4f0ec590..deb7577c07 100644
--- a/src/courseware/course/sidebar/sidebars/notifications/NotificationTray.jsx
+++ b/src/courseware/course/sidebar/sidebars/notifications/NotificationTray.jsx
@@ -2,9 +2,9 @@ import { useIntl } from '@edx/frontend-platform/i18n';
import classNames from 'classnames';
import { useContext, useEffect, useMemo } from 'react';
import { sendTrackEvent } from '@edx/frontend-platform/analytics';
-import { PluginSlot } from '@openedx/frontend-plugin-framework';
import { getAuthenticatedUser } from '@edx/frontend-platform/auth';
import { useModel } from '@src/generic/model-store';
+import { NotificationTraySlot } from '../../../../../plugin-slots/NotificationTraySlot';
import messages from '../../../messages';
import SidebarBase from '../../common/SidebarBase';
@@ -76,14 +76,10 @@ const NotificationTray = () => {
>
{verifiedMode
? (
-
) : (
{intl.formatMessage(messages.noNotificationsMessage)}
diff --git a/src/courseware/course/sidebar/sidebars/notifications/NotificationTray.test.jsx b/src/courseware/course/sidebar/sidebars/notifications/NotificationTray.test.jsx
index 269a35f7a0..309747242f 100644
--- a/src/courseware/course/sidebar/sidebars/notifications/NotificationTray.test.jsx
+++ b/src/courseware/course/sidebar/sidebars/notifications/NotificationTray.test.jsx
@@ -91,7 +91,7 @@ describe('NotificationTray', () => {
,
);
- expect(screen.getByTestId('notification_tray_slot')).toBeInTheDocument();
+ expect(screen.getByTestId('org.openedx.frontend.learning.notification_tray.v1')).toBeInTheDocument();
});
it('renders no notifications message if no verified mode', async () => {
diff --git a/src/plugin-slots/ContentIFrameLoaderSlot/README.md b/src/plugin-slots/ContentIFrameLoaderSlot/README.md
new file mode 100644
index 0000000000..9ee49e5d27
--- /dev/null
+++ b/src/plugin-slots/ContentIFrameLoaderSlot/README.md
@@ -0,0 +1,10 @@
+# Content iframe Loader Slot
+
+### Slot ID: `org.openedx.frontend.learning.content_iframe_loader.v1`
+
+### Slot ID Aliases
+* `content_iframe_loader_slot`
+
+### Props:
+* `courseId`
+* `defaultLoaderComponent`
diff --git a/src/plugin-slots/ContentIFrameLoaderSlot/index.tsx b/src/plugin-slots/ContentIFrameLoaderSlot/index.tsx
new file mode 100644
index 0000000000..d13909fac9
--- /dev/null
+++ b/src/plugin-slots/ContentIFrameLoaderSlot/index.tsx
@@ -0,0 +1,25 @@
+import React, { ReactNode } from 'react';
+
+import { PluginSlot } from '@openedx/frontend-plugin-framework';
+import PageLoading from '../../generic/PageLoading';
+
+export const ContentIFrameLoaderSlot = ({
+ courseId,
+ loadingMessage,
+} : ContentIFrameLoaderSlotProps) => (
+
,
+ courseId,
+ }}
+ >
+
+
+);
+
+interface ContentIFrameLoaderSlotProps {
+ courseId: string;
+ loadingMessage: ReactNode;
+}
diff --git a/src/plugin-slots/CourseBreadcrumbsSlot/README.md b/src/plugin-slots/CourseBreadcrumbsSlot/README.md
index 38de9a0550..12863d4e08 100644
--- a/src/plugin-slots/CourseBreadcrumbsSlot/README.md
+++ b/src/plugin-slots/CourseBreadcrumbsSlot/README.md
@@ -1,6 +1,9 @@
# Course Breadcrumbs Slot
-### Slot ID: `course_breadcrumbs_slot`
+### Slot ID: `org.openedx.frontend.learning.course_breadcrumbs.v1`
+
+### Slot ID Aliases
+* `course_breadcrumbs_slot`
## Description
@@ -21,7 +24,7 @@ import { DIRECT_PLUGIN, PLUGIN_OPERATIONS } from '@openedx/frontend-plugin-frame
const config = {
pluginSlots: {
- course_breadcrumbs_slot: {
+ 'org.openedx.frontend.learning.course_breadcrumbs.v1': {
keepDefault: false,
plugins: [
{
diff --git a/src/plugin-slots/CourseBreadcrumbsSlot/index.tsx b/src/plugin-slots/CourseBreadcrumbsSlot/index.tsx
index 504c4c2549..8a438968a1 100644
--- a/src/plugin-slots/CourseBreadcrumbsSlot/index.tsx
+++ b/src/plugin-slots/CourseBreadcrumbsSlot/index.tsx
@@ -16,7 +16,8 @@ export const CourseBreadcrumbsSlot : React.FC
= ({
courseId, sectionId, sequenceId, unitId, isStaff,
}) => (
= ({
expandAll, sections, sectionIds,
}) => (
diff --git a/src/plugin-slots/CourseOutlineMobileSidebarTriggerSlot/README.md b/src/plugin-slots/CourseOutlineMobileSidebarTriggerSlot/README.md
index 317dee73b6..923e0aea34 100644
--- a/src/plugin-slots/CourseOutlineMobileSidebarTriggerSlot/README.md
+++ b/src/plugin-slots/CourseOutlineMobileSidebarTriggerSlot/README.md
@@ -1,6 +1,9 @@
# Course Outline Mobile Sidebar Trigger Slot
-### Slot ID: `course_outline_mobile_sidebar_trigger_slot`
+### Slot ID: `org.openedx.frontend.learning.course_outline_mobile_sidebar_trigger.v1`
+
+### Slot ID Aliases
+* `course_outline_mobile_sidebar_trigger_slot`
## Description
@@ -21,7 +24,7 @@ import { DIRECT_PLUGIN, PLUGIN_OPERATIONS } from '@openedx/frontend-plugin-frame
const config = {
pluginSlots: {
- course_outline_mobile_sidebar_trigger_slot: {
+ 'org.openedx.frontend.learning.course_outline_mobile_sidebar_trigger.v1': {
keepDefault: false,
plugins: [
{
diff --git a/src/plugin-slots/CourseOutlineMobileSidebarTriggerSlot/index.tsx b/src/plugin-slots/CourseOutlineMobileSidebarTriggerSlot/index.tsx
index f192003b01..199c0322da 100644
--- a/src/plugin-slots/CourseOutlineMobileSidebarTriggerSlot/index.tsx
+++ b/src/plugin-slots/CourseOutlineMobileSidebarTriggerSlot/index.tsx
@@ -6,7 +6,8 @@ import CourseOutlineTrigger from '../../courseware/course/sidebar/sidebars/cours
export const CourseOutlineMobileSidebarTriggerSlot : React.FC = () => (