diff --git a/src/courseware/course/sequence/Sequence.jsx b/src/courseware/course/sequence/Sequence.jsx index 6c56b219..e0b3c0a8 100644 --- a/src/courseware/course/sequence/Sequence.jsx +++ b/src/courseware/course/sequence/Sequence.jsx @@ -13,17 +13,18 @@ import SequenceExamWrapper from '@edx/frontend-lib-special-exams'; import PageLoading from '@src/generic/PageLoading'; import { useModel } from '@src/generic/model-store'; import { useSequenceBannerTextAlert, useSequenceEntranceExamAlert } from '@src/alerts/sequence-alerts/hooks'; -import SequenceContainerSlot from '../../../plugin-slots/SequenceContainerSlot'; +import SequenceContainerSlot from '@src/plugin-slots/SequenceContainerSlot'; +import { CourseOutlineSidebarSlot } from '@src/plugin-slots/CourseOutlineSidebarSlot'; +import { CourseOutlineSidebarTriggerSlot } from '@src/plugin-slots/CourseOutlineSidebarTriggerSlot'; +import { NotificationsDiscussionsSidebarSlot } from '@src/plugin-slots/NotificationsDiscussionsSidebarSlot'; +import SequenceNavigationSlot from '@src/plugin-slots/SequenceNavigationSlot'; import { getCoursewareOutlineSidebarSettings } from '../../data/selectors'; import CourseLicense from '../course-license'; -import { NotificationsDiscussionsSidebarSlot } from '../../../plugin-slots/NotificationsDiscussionsSidebarSlot'; import messages from './messages'; import HiddenAfterDue from './hidden-after-due'; -import { SequenceNavigation, UnitNavigation } from './sequence-navigation'; +import { UnitNavigation } from './sequence-navigation'; import SequenceContent from './SequenceContent'; -import { CourseOutlineSidebarSlot } from '../../../plugin-slots/CourseOutlineSidebarSlot'; -import { CourseOutlineSidebarTriggerSlot } from '../../../plugin-slots/CourseOutlineSidebarTriggerSlot'; const Sequence = ({ unitId, @@ -172,7 +173,7 @@ const Sequence = ({
{!isEnabledOutlineSidebar && (
- { diff --git a/src/plugin-slots/README.md b/src/plugin-slots/README.md index 6444bbaf..be410164 100644 --- a/src/plugin-slots/README.md +++ b/src/plugin-slots/README.md @@ -23,4 +23,5 @@ * [`org.openedx.frontend.learning.progress_tab_grade_breakdown.v1`](./ProgressTabGradeBreakdownSlot/) * [`org.openedx.frontend.learning.progress_tab_related_links.v1`](./ProgressTabRelatedLinksSlot/) * [`org.openedx.frontend.learning.sequence_container.v1`](./SequenceContainerSlot/) +* [`org.openedx.frontend.learning.sequence_navigation.v1`](./SequenceNavigationSlot/) * [`org.openedx.frontend.learning.unit_title.v1`](./UnitTitleSlot/) diff --git a/src/plugin-slots/SequenceNavigationSlot/README.md b/src/plugin-slots/SequenceNavigationSlot/README.md new file mode 100644 index 00000000..b8681625 --- /dev/null +++ b/src/plugin-slots/SequenceNavigationSlot/README.md @@ -0,0 +1,80 @@ +# Sequence Navigation Slot + +### Slot ID: `org.openedx.frontend.learning.sequence_navigation.v1` + +### Props: +* `sequenceId` (string) — Current sequence identifier +* `unitId` (string) — Current unit identifier +* `nextHandler` (function) — Handler for next navigation action +* `onNavigate` (function) — Handler for direct unit navigation +* `previousHandler` (function) — Handler for previous navigation action + +## Description + +This slot is used to replace/modify/hide the sequence navigation component that controls navigation between units within a course sequence. + +## Example + +### Default content +![Sequence navigation slot with default content](./screenshot_default.png) + +### Replaced with custom component +![📖 in sequence navigation slot](./screenshot_custom.png) + +The following `env.config.jsx` will replace the sequence navigation with a custom implementation that uses all available props. + +```js +import { DIRECT_PLUGIN, PLUGIN_OPERATIONS } from '@openedx/frontend-plugin-framework'; + +const config = { + pluginSlots: { + 'org.openedx.frontend.learning.sequence_navigation.v1': { + keepDefault: false, + plugins: [ + { + op: PLUGIN_OPERATIONS.Insert, + widget: { + id: 'custom_sequence_navigation', + type: DIRECT_PLUGIN, + RenderWidget: ({ sequenceId, unitId, nextHandler, onNavigate, previousHandler }) => { + // Mock unit data for demonstration + const units = ['unit-1', 'unit-2', 'unit-3']; + + return ( + + + + {units.map((unit, index) => ( + + ))} + + + + ) + }, + }, + }, + ] + } + }, +} + +export default config; +``` diff --git a/src/plugin-slots/SequenceNavigationSlot/index.jsx b/src/plugin-slots/SequenceNavigationSlot/index.jsx new file mode 100644 index 00000000..c48652a4 --- /dev/null +++ b/src/plugin-slots/SequenceNavigationSlot/index.jsx @@ -0,0 +1,45 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { PluginSlot } from '@openedx/frontend-plugin-framework'; + +import { SequenceNavigation } from '../../courseware/course/sequence/sequence-navigation'; + +const SequenceNavigationSlot = ({ + sequenceId, + unitId, + nextHandler, + onNavigate, + previousHandler, +}) => ( + + + +); + +SequenceNavigationSlot.propTypes = { + sequenceId: PropTypes.string.isRequired, + unitId: PropTypes.string.isRequired, + nextHandler: PropTypes.func.isRequired, + onNavigate: PropTypes.func.isRequired, + previousHandler: PropTypes.func.isRequired, +}; + +export default SequenceNavigationSlot; diff --git a/src/plugin-slots/SequenceNavigationSlot/screenshot_custom.png b/src/plugin-slots/SequenceNavigationSlot/screenshot_custom.png new file mode 100644 index 00000000..b2bb10a9 Binary files /dev/null and b/src/plugin-slots/SequenceNavigationSlot/screenshot_custom.png differ diff --git a/src/plugin-slots/SequenceNavigationSlot/screenshot_default.png b/src/plugin-slots/SequenceNavigationSlot/screenshot_default.png new file mode 100644 index 00000000..036cca1c Binary files /dev/null and b/src/plugin-slots/SequenceNavigationSlot/screenshot_default.png differ