diff --git a/package-lock.json b/package-lock.json index 18e9afbb0..847894bbe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -37,6 +37,7 @@ "@openedx-plugins/course-app-xpert_unit_summary": "file:plugins/course-apps/xpert_unit_summary", "@openedx/frontend-build": "^14.3.3", "@openedx/frontend-plugin-framework": "^1.6.0", + "@openedx/frontend-slot-footer": "^1.2.0", "@openedx/paragon": "^22.16.0", "@redux-devtools/extension": "^3.3.0", "@reduxjs/toolkit": "1.9.7", @@ -4241,6 +4242,20 @@ "@babel/runtime": "^7.9.2" } }, + "node_modules/@openedx/frontend-slot-footer": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@openedx/frontend-slot-footer/-/frontend-slot-footer-1.2.0.tgz", + "integrity": "sha512-bJuqgdiAlPRj1QuUOJWtNqGTCTcdsk4vHeOM3jRkxtWycq+j1JpGnnZEWAmjoRv9dDKr39vt2buNrmvj0sCTbA==", + "license": "AGPL-3.0", + "dependencies": { + "@openedx/frontend-plugin-framework": "^1.5.0" + }, + "peerDependencies": { + "@edx/frontend-component-footer": "*", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + } + }, "node_modules/@openedx/paragon": { "version": "22.17.0", "resolved": "https://registry.npmjs.org/@openedx/paragon/-/paragon-22.17.0.tgz", diff --git a/package.json b/package.json index 1043e4711..785df3bc4 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,7 @@ "@openedx-plugins/course-app-wiki": "file:plugins/course-apps/wiki", "@openedx-plugins/course-app-xpert_unit_summary": "file:plugins/course-apps/xpert_unit_summary", "@openedx/frontend-build": "^14.3.3", + "@openedx/frontend-slot-footer": "^1.2.0", "@openedx/frontend-plugin-framework": "^1.6.0", "@openedx/paragon": "^22.16.0", "@redux-devtools/extension": "^3.3.0", diff --git a/src/CourseAuthoringPage.jsx b/src/CourseAuthoringPage.jsx index e187522c0..9a594ff6c 100644 --- a/src/CourseAuthoringPage.jsx +++ b/src/CourseAuthoringPage.jsx @@ -5,7 +5,7 @@ import { useDispatch, useSelector } from 'react-redux'; import { useLocation, } from 'react-router-dom'; -import { StudioFooter } from '@edx/frontend-component-footer'; +import { StudioFooterSlot } from '@openedx/frontend-slot-footer'; import Header from './header'; import { fetchCourseDetail, fetchWaffleFlags } from './data/thunks'; import { useModel } from './generic/model-store'; @@ -66,7 +66,7 @@ const CourseAuthoringPage = ({ courseId, children }) => { ) )} {children} - {!inProgress && !isEditor && } + {!inProgress && !isEditor && } ); }; diff --git a/src/accessibility-page/AccessibilityPage.jsx b/src/accessibility-page/AccessibilityPage.jsx index d3dd1c99a..d7cc8959f 100644 --- a/src/accessibility-page/AccessibilityPage.jsx +++ b/src/accessibility-page/AccessibilityPage.jsx @@ -2,7 +2,7 @@ import React from 'react'; import { injectIntl, intlShape } from '@edx/frontend-platform/i18n'; import { Helmet } from 'react-helmet'; import { Container } from '@openedx/paragon'; -import { StudioFooter } from '@edx/frontend-component-footer'; +import { StudioFooterSlot } from '@openedx/frontend-slot-footer'; import Header from '../header'; import messages from './messages'; @@ -29,7 +29,7 @@ const AccessibilityPage = ({ - + ); }; diff --git a/src/course-rerun/index.jsx b/src/course-rerun/index.jsx index 1bfeed4f9..425d8163c 100644 --- a/src/course-rerun/index.jsx +++ b/src/course-rerun/index.jsx @@ -7,7 +7,8 @@ import { ActionRow, Button, } from '@openedx/paragon'; -import { StudioFooter } from '@edx/frontend-component-footer'; +import { StudioFooterSlot } from '@openedx/frontend-slot-footer'; + import { useNavigate, useParams } from 'react-router-dom'; import Header from '../header'; @@ -88,7 +89,7 @@ const CourseRerun = () => { isQueryPending={savingStatus === RequestStatus.PENDING} /> - + ); }; diff --git a/src/library-authoring/LibraryAuthoringPage.tsx b/src/library-authoring/LibraryAuthoringPage.tsx index 7871fd99b..10741d118 100644 --- a/src/library-authoring/LibraryAuthoringPage.tsx +++ b/src/library-authoring/LibraryAuthoringPage.tsx @@ -1,7 +1,7 @@ import { useCallback, useEffect, useState } from 'react'; import { Helmet } from 'react-helmet'; import classNames from 'classnames'; -import { StudioFooter } from '@edx/frontend-component-footer'; +import { StudioFooterSlot } from '@openedx/frontend-slot-footer'; import { useIntl } from '@edx/frontend-platform/i18n'; import { ActionRow, @@ -286,7 +286,7 @@ const LibraryAuthoringPage = ({ returnToLibrarySelection }: LibraryAuthoringPage - {!componentPickerMode && } + {!componentPickerMode && } {!!sidebarComponentInfo?.type && (
diff --git a/src/library-authoring/collections/LibraryCollectionPage.tsx b/src/library-authoring/collections/LibraryCollectionPage.tsx index 306a64ab5..4bff6751a 100644 --- a/src/library-authoring/collections/LibraryCollectionPage.tsx +++ b/src/library-authoring/collections/LibraryCollectionPage.tsx @@ -1,5 +1,5 @@ import { useEffect } from 'react'; -import { StudioFooter } from '@edx/frontend-component-footer'; +import { StudioFooterSlot } from '@openedx/frontend-slot-footer'; import { useIntl } from '@edx/frontend-platform/i18n'; import { ActionRow, @@ -220,7 +220,7 @@ const LibraryCollectionPage = () => { - {!componentPickerMode && } + {!componentPickerMode && }
{!!sidebarComponentInfo?.type && (
diff --git a/src/library-authoring/create-library/CreateLibrary.tsx b/src/library-authoring/create-library/CreateLibrary.tsx index 7939a2b4f..009069430 100644 --- a/src/library-authoring/create-library/CreateLibrary.tsx +++ b/src/library-authoring/create-library/CreateLibrary.tsx @@ -1,4 +1,4 @@ -import { StudioFooter } from '@edx/frontend-component-footer'; +import { StudioFooterSlot } from '@openedx/frontend-slot-footer'; import { useIntl } from '@edx/frontend-platform/i18n'; import { Container, @@ -162,7 +162,7 @@ const CreateLibrary = () => { {isError && ()} - + ); }; diff --git a/src/plugin-slots/README.md b/src/plugin-slots/README.md index a7a3c3c21..c017435bd 100644 --- a/src/plugin-slots/README.md +++ b/src/plugin-slots/README.md @@ -9,3 +9,6 @@ ## Course Unit page * [`course_unit_header_actions_slot`](./CourseUnitHeaderActionsSlot/) + +## Footer Slot +* [`studio_footer_slot`](./StudioFooterSlot/) diff --git a/src/plugin-slots/StudioFooterSlot/README.md b/src/plugin-slots/StudioFooterSlot/README.md new file mode 100644 index 000000000..f45d46947 --- /dev/null +++ b/src/plugin-slots/StudioFooterSlot/README.md @@ -0,0 +1,50 @@ +# Studio Footer Slot + +### Slot ID: `studio_footer_slot` + +## Description + +This slot is used to replace/modify/hide the footer. + +The implementation of the `StudioFooterSlot` component lives in [the `frontend-slot-footer` repository](https://github.com/openedx/frontend-slot-footer/). + +## Example + +The following `env.config.jsx` will replace the default footer. + +![Screenshot of Default Studio Footer](./images/default_studio_footer.png) + +with a simple custom footer + +![Screenshot of Custom Footer](./images/custom_footer.png) + +```jsx +import { DIRECT_PLUGIN, PLUGIN_OPERATIONS } from '@openedx/frontend-plugin-framework'; + +const config = { + pluginSlots: { + studio_footer_slot: { + plugins: [ + { + // Hide the default footer + op: PLUGIN_OPERATIONS.Hide, + widgetId: 'default_contents', + }, + { + // Insert a custom footer + op: PLUGIN_OPERATIONS.Insert, + widget: { + id: 'custom_footer', + type: DIRECT_PLUGIN, + RenderWidget: () => ( +

🦶

+ ), + }, + }, + ] + } + }, +} + +export default config; +``` \ No newline at end of file diff --git a/src/plugin-slots/StudioFooterSlot/images/custom_footer.png b/src/plugin-slots/StudioFooterSlot/images/custom_footer.png new file mode 100644 index 000000000..ccae66ecd Binary files /dev/null and b/src/plugin-slots/StudioFooterSlot/images/custom_footer.png differ diff --git a/src/plugin-slots/StudioFooterSlot/images/default_studio_footer.png b/src/plugin-slots/StudioFooterSlot/images/default_studio_footer.png new file mode 100644 index 000000000..d7b71698a Binary files /dev/null and b/src/plugin-slots/StudioFooterSlot/images/default_studio_footer.png differ diff --git a/src/studio-home/StudioHome.tsx b/src/studio-home/StudioHome.tsx index 9b8bc20a3..0e3380bef 100644 --- a/src/studio-home/StudioHome.tsx +++ b/src/studio-home/StudioHome.tsx @@ -9,7 +9,7 @@ import { } from '@openedx/paragon'; import { Add as AddIcon, Error } from '@openedx/paragon/icons'; import { useIntl } from '@edx/frontend-platform/i18n'; -import { StudioFooter } from '@edx/frontend-component-footer'; +import { StudioFooterSlot } from '@openedx/frontend-slot-footer'; import { getConfig } from '@edx/frontend-platform'; import { useLocation, useNavigate } from 'react-router-dom'; @@ -188,7 +188,7 @@ const StudioHome = () => { isQueryPending={anyQueryIsPending} />
- + ); }; diff --git a/src/taxonomy/TaxonomyLayout.tsx b/src/taxonomy/TaxonomyLayout.tsx index 63c41b9ed..68827aad9 100644 --- a/src/taxonomy/TaxonomyLayout.tsx +++ b/src/taxonomy/TaxonomyLayout.tsx @@ -1,5 +1,5 @@ import { useMemo, useState } from 'react'; -import { StudioFooter } from '@edx/frontend-component-footer'; +import { StudioFooterSlot } from '@openedx/frontend-slot-footer'; import { Outlet, ScrollRestoration } from 'react-router-dom'; import { Toast } from '@openedx/paragon'; @@ -28,7 +28,7 @@ export const TaxonomyLayout = () => { /> )} - + {toastMessage && (