From c5176fadf8228c550dcd6a3475680f1c9a13e13a Mon Sep 17 00:00:00 2001 From: Arunmozhi Date: Mon, 19 May 2025 17:50:20 +1000 Subject: [PATCH 1/8] refactor: CourseAuthoringUnitSidebarSlot The sidebar slot in the Course Unit page wrapped only a partial set of components that are being rendered when the unit is of 'vertical' type. This leads to 2 issues: * the sidebar slot will not be rendered when the unit is not of `vertical` type * the slot's position in the UI is inconsistent between the Course Outline page and Course Unit page In this commit, all the elements of the sidebar column are wrapped into the slot. --- src/course-unit/CourseUnit.jsx | 30 +++++--------- .../CourseAuthoringUnitSidebarSlot/index.tsx | 39 +++++++++++++------ 2 files changed, 38 insertions(+), 31 deletions(-) diff --git a/src/course-unit/CourseUnit.jsx b/src/course-unit/CourseUnit.jsx index f63dad09e6..72882e8884 100644 --- a/src/course-unit/CourseUnit.jsx +++ b/src/course-unit/CourseUnit.jsx @@ -3,8 +3,7 @@ import PropTypes from 'prop-types'; import { useSelector } from 'react-redux'; import { useParams } from 'react-router-dom'; import { - Container, Layout, Stack, Button, TransitionReplace, - Alert, + Alert, Container, Layout, Button, TransitionReplace, } from '@openedx/paragon'; import { useIntl } from '@edx/frontend-platform/i18n'; import { @@ -27,8 +26,6 @@ import AddComponent from './add-component/AddComponent'; import HeaderTitle from './header-title/HeaderTitle'; import Breadcrumbs from './breadcrumbs/Breadcrumbs'; import Sequence from './course-sequence'; -import Sidebar from './sidebar'; -import SplitTestSidebarInfo from './sidebar/SplitTestSidebarInfo'; import { useCourseUnit, useLayoutGrid, useScrollToLastPosition } from './hooks'; import messages from './messages'; import { PasteNotificationAlert } from './clipboard'; @@ -244,22 +241,15 @@ const CourseUnit = ({ courseId }) => { - - {isUnitVerticalType && ( - - )} - {isSplitTestType && ( - - - - )} - + diff --git a/src/plugin-slots/CourseAuthoringUnitSidebarSlot/index.tsx b/src/plugin-slots/CourseAuthoringUnitSidebarSlot/index.tsx index 0bf6de14ca..c65f87f87e 100644 --- a/src/plugin-slots/CourseAuthoringUnitSidebarSlot/index.tsx +++ b/src/plugin-slots/CourseAuthoringUnitSidebarSlot/index.tsx @@ -1,9 +1,11 @@ import { getConfig } from '@edx/frontend-platform'; import { PluginSlot } from '@openedx/frontend-plugin-framework/dist'; +import {Stack} from '@openedx/paragon'; import TagsSidebarControls from '../../content-tags-drawer/tags-sidebar-controls'; import Sidebar from '../../course-unit/sidebar'; import LocationInfo from '../../course-unit/sidebar/LocationInfo'; import PublishControls from '../../course-unit/sidebar/PublishControls'; +import SplitTestSidebarInfo from '../../course-unit/sidebar/SplitTestSidebarInfo'; export const CourseAuthoringUnitSidebarSlot = ( { @@ -12,6 +14,8 @@ export const CourseAuthoringUnitSidebarSlot = ( unitTitle, xBlocks, readOnly, + isUnitVerticalType, + isSplitTestType, }: CourseAuthoringUnitSidebarSlotProps, ) => ( - - - - {getConfig().ENABLE_TAGGING_TAXONOMY_PAGES === 'true' && ( - - - - )} - - - + + {isUnitVerticalType && ( + <> + + + + {getConfig().ENABLE_TAGGING_TAXONOMY_PAGES === 'true' && ( + + + + )} + + + + + )} + {isSplitTestType && ( + + + + )} + ); @@ -47,4 +62,6 @@ interface CourseAuthoringUnitSidebarSlotProps { unitTitle: string; xBlocks: XBlock[]; readOnly: boolean; + isUnitVerticalType: boolean; + isSplitTestType: boolean; } From 238a11514ea14b76114994df178c045acdf785f4 Mon Sep 17 00:00:00 2001 From: Arunmozhi Date: Mon, 19 May 2025 17:53:06 +1000 Subject: [PATCH 2/8] docs: update the CourseAuthoringUnitSidebarSlot docs --- src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.md b/src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.md index ee00e7ba16..9bb1acf48b 100644 --- a/src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.md +++ b/src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.md @@ -12,6 +12,8 @@ * `unitTitle` - String. The name of the current unit being viewed / edited. * `xBlocks` - Array of Objects. List of XBlocks in the Unit. Object structure defined in `index.tsx`. * `readOnly` - Boolean. True if the user should not be able to edit the contents of the unit. +* `isUnitVerticalType` - Boolean. If the unit category is `vertical`. +* `isSplitTestType` - Boolean. If the unit category is `split_test`. ## Description From c2467e832fb2ed6d21618ec6c657f2931da1f8cf Mon Sep 17 00:00:00 2001 From: Arunmozhi Date: Fri, 23 May 2025 19:21:54 +1000 Subject: [PATCH 3/8] fix: linting issue causing CI failure --- src/plugin-slots/CourseAuthoringUnitSidebarSlot/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugin-slots/CourseAuthoringUnitSidebarSlot/index.tsx b/src/plugin-slots/CourseAuthoringUnitSidebarSlot/index.tsx index c65f87f87e..f5e7e43759 100644 --- a/src/plugin-slots/CourseAuthoringUnitSidebarSlot/index.tsx +++ b/src/plugin-slots/CourseAuthoringUnitSidebarSlot/index.tsx @@ -1,6 +1,6 @@ import { getConfig } from '@edx/frontend-platform'; import { PluginSlot } from '@openedx/frontend-plugin-framework/dist'; -import {Stack} from '@openedx/paragon'; +import { Stack } from '@openedx/paragon'; import TagsSidebarControls from '../../content-tags-drawer/tags-sidebar-controls'; import Sidebar from '../../course-unit/sidebar'; import LocationInfo from '../../course-unit/sidebar/LocationInfo'; From c259d15d2fbbbda7f987e7cce19ff14b8fd3ec09 Mon Sep 17 00:00:00 2001 From: Arunmozhi Date: Wed, 4 Jun 2025 15:25:42 +1000 Subject: [PATCH 4/8] refactor: introduce the changes as slot v2 wrapping v1 The commit wraps the newly added components as the slots's v2 while keeping the original slot component tree as slot v1. --- .../CourseAuthoringUnitSidebarSlot/index.tsx | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/plugin-slots/CourseAuthoringUnitSidebarSlot/index.tsx b/src/plugin-slots/CourseAuthoringUnitSidebarSlot/index.tsx index f5e7e43759..562cbccb0f 100644 --- a/src/plugin-slots/CourseAuthoringUnitSidebarSlot/index.tsx +++ b/src/plugin-slots/CourseAuthoringUnitSidebarSlot/index.tsx @@ -19,15 +19,20 @@ export const CourseAuthoringUnitSidebarSlot = ( }: CourseAuthoringUnitSidebarSlotProps, ) => ( {isUnitVerticalType && ( - <> + @@ -39,7 +44,7 @@ export const CourseAuthoringUnitSidebarSlot = ( - + )} {isSplitTestType && ( From ea99da2f44b22efcfad6e1067d868fdc67005590 Mon Sep 17 00:00:00 2001 From: Arunmozhi Date: Wed, 4 Jun 2025 15:34:11 +1000 Subject: [PATCH 5/8] docs: update the CourseAuthoringUnitSidebarSlot docs --- .../CourseAuthoringUnitSidebarSlot/README.md | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.md b/src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.md index 9bb1acf48b..12744d0850 100644 --- a/src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.md +++ b/src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.md @@ -1,17 +1,27 @@ # CourseAuthoringUnitSidebarSlot -### Slot ID: `org.openedx.frontend.authoring.course_unit_sidebar.v1` +The component currently holds 2 versions of the slot. Version 2 wraps version 1 and hence, is a +superset of version 1. + +### Slot IDs: +* `org.openedx.frontend.authoring.course_unit_sidebar.v2` +* `org.openedx.frontend.authoring.course_unit_sidebar.v1` ### Slot ID Aliases -* `course_authoring_unit_sidebar_slot` +* `org.openedx.frontend.authoring.course_unit_sidebar.v1` - `course_authoring_unit_sidebar_slot` ### Plugin Props: +#### Version 1 + * `courseId` - String. * `blockId` - String. The usage id of the current unit being viewed / edited. * `unitTitle` - String. The name of the current unit being viewed / edited. * `xBlocks` - Array of Objects. List of XBlocks in the Unit. Object structure defined in `index.tsx`. * `readOnly` - Boolean. True if the user should not be able to edit the contents of the unit. + +#### Extra props in Version 2 + * `isUnitVerticalType` - Boolean. If the unit category is `vertical`. * `isSplitTestType` - Boolean. If the unit category is `split_test`. @@ -31,7 +41,7 @@ import { PLUGIN_OPERATIONS } from '@openedx/frontend-plugin-framework'; const config = { pluginSlots: { - 'org.openedx.frontend.authoring.course_unit_sidebar.v1': { + 'org.openedx.frontend.authoring.course_unit_sidebar.v2': { keepDefault: true, plugins: [ { @@ -65,11 +75,11 @@ const ProblemBlocks = ({unitTitle, xBlocks}) => ( } -); +); const config = { pluginSlots: { - 'org.openedx.frontend.authoring.course_unit_sidebar.v1': { + 'org.openedx.frontend.authoring.course_unit_sidebar.v2': { keepDefault: true, plugins: [ { From b1113380e85614eeea010f689da7cffc323c73af Mon Sep 17 00:00:00 2001 From: Arunmozhi Date: Fri, 6 Jun 2025 19:12:33 +1000 Subject: [PATCH 6/8] docs: separate the README files for the 2 versions --- .../CourseAuthoringUnitSidebarSlot/README.md | 15 +--- .../README.v1.md | 86 +++++++++++++++++++ 2 files changed, 89 insertions(+), 12 deletions(-) create mode 100644 src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.v1.md diff --git a/src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.md b/src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.md index 12744d0850..5aa33c7862 100644 --- a/src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.md +++ b/src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.md @@ -1,27 +1,18 @@ # CourseAuthoringUnitSidebarSlot -The component currently holds 2 versions of the slot. Version 2 wraps version 1 and hence, is a -superset of version 1. +### Slot ID: `org.openedx.frontend.authoring.course_unit_sidebar.v2` -### Slot IDs: -* `org.openedx.frontend.authoring.course_unit_sidebar.v2` -* `org.openedx.frontend.authoring.course_unit_sidebar.v1` +### Slot ID Aliases: `course_authoring_unit_sidebar_slot_v2` -### Slot ID Aliases -* `org.openedx.frontend.authoring.course_unit_sidebar.v1` - `course_authoring_unit_sidebar_slot` +### Previous Version: [`org.openedx.frontend.authoring.course_unit_sidebar.v1`](./README.v1.md) ### Plugin Props: -#### Version 1 - * `courseId` - String. * `blockId` - String. The usage id of the current unit being viewed / edited. * `unitTitle` - String. The name of the current unit being viewed / edited. * `xBlocks` - Array of Objects. List of XBlocks in the Unit. Object structure defined in `index.tsx`. * `readOnly` - Boolean. True if the user should not be able to edit the contents of the unit. - -#### Extra props in Version 2 - * `isUnitVerticalType` - Boolean. If the unit category is `vertical`. * `isSplitTestType` - Boolean. If the unit category is `split_test`. diff --git a/src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.v1.md b/src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.v1.md new file mode 100644 index 0000000000..bf505007dd --- /dev/null +++ b/src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.v1.md @@ -0,0 +1,86 @@ +# CourseAuthoringUnitSidebarSlot + +### Slot ID: `org.openedx.frontend.authoring.course_unit_sidebar.v1` + +### Slot ID Aliases: `course_authoring_unit_sidebar_slot` + +### Plugin Props: + +* `courseId` - String. +* `blockId` - String. The usage id of the current unit being viewed / edited. +* `unitTitle` - String. The name of the current unit being viewed / edited. +* `xBlocks` - Array of Objects. List of XBlocks in the Unit. Object structure defined in `index.tsx`. +* `readOnly` - Boolean. True if the user should not be able to edit the contents of the unit. + +### Description + +The slot wraps the sidebar that is displayed on the unit editor page. It can +be used to add additional sidebar components or modify the existing sidebar. + +## Example 1 + +![Screenshot of the unit sidebar surrounded by border](./images/unit_sidebar_with_border.png) + +The following example configuration surrounds the sidebar in a border as shown above. + +```js +import { PLUGIN_OPERATIONS } from '@openedx/frontend-plugin-framework'; + +const config = { + pluginSlots: { + 'org.openedx.frontend.authoring.course_unit_sidebar.v1': { + keepDefault: true, + plugins: [ + { + op: PLUGIN_OPERATIONS.Wrap, + widgetId: 'default_contents', + wrapper: ({ component }) => ( +
{component}
+ ), + }, + ], + }, + } +}; +export default config; +``` + +## Example 2 + +![Screenshot of the unit sidebar with an extra component listing all the problem blocks](./images/unit_sidebar_with_problem_blocks_list.png) + +```js +import { PLUGIN_OPERATIONS, DIRECT_PLUGIN } from '@openedx/frontend-plugin-framework'; + +const ProblemBlocks = ({unitTitle, xBlocks}) => ( + <> +

{unitTitle}: Problem Blocks

+
    + {xBlocks + .filter(block => block.blockType === "problem") + .map(block =>
  • {block.displayName}
  • ) + } +
+ +); + +const config = { + pluginSlots: { + 'org.openedx.frontend.authoring.course_unit_sidebar.v1': { + keepDefault: true, + plugins: [ + { + op: PLUGIN_OPERATIONS.Insert, + widget:{ + id: 'problem-blocks-list', + priority: 1, + type: DIRECT_PLUGIN, + RenderWidget: ProblemBlocks, + } + }, + ], + }, + } +}; +export default config; +``` From b8f026895e2c9a174d6ad3c9ae1f4533b8aa5b25 Mon Sep 17 00:00:00 2001 From: Arunmozhi Date: Fri, 6 Jun 2025 19:14:29 +1000 Subject: [PATCH 7/8] fixup! docs: minor edits around formatting --- src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.md b/src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.md index 5aa33c7862..6c1afc684e 100644 --- a/src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.md +++ b/src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.md @@ -2,7 +2,8 @@ ### Slot ID: `org.openedx.frontend.authoring.course_unit_sidebar.v2` -### Slot ID Aliases: `course_authoring_unit_sidebar_slot_v2` +### Slot ID Aliases +* `course_authoring_unit_sidebar_slot_v2` ### Previous Version: [`org.openedx.frontend.authoring.course_unit_sidebar.v1`](./README.v1.md) From 17755191339666a007a4e19fcfe134350888393a Mon Sep 17 00:00:00 2001 From: Arunmozhi Date: Mon, 9 Jun 2025 12:59:20 +1000 Subject: [PATCH 8/8] docs: improve the docs for v1, remove err alias --- .../CourseAuthoringUnitSidebarSlot/README.md | 3 --- .../CourseAuthoringUnitSidebarSlot/README.v1.md | 9 +++++++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.md b/src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.md index 6c1afc684e..091af0d8df 100644 --- a/src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.md +++ b/src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.md @@ -2,9 +2,6 @@ ### Slot ID: `org.openedx.frontend.authoring.course_unit_sidebar.v2` -### Slot ID Aliases -* `course_authoring_unit_sidebar_slot_v2` - ### Previous Version: [`org.openedx.frontend.authoring.course_unit_sidebar.v1`](./README.v1.md) ### Plugin Props: diff --git a/src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.v1.md b/src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.v1.md index bf505007dd..aafccfb461 100644 --- a/src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.v1.md +++ b/src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.v1.md @@ -17,6 +17,15 @@ The slot wraps the sidebar that is displayed on the unit editor page. It can be used to add additional sidebar components or modify the existing sidebar. +> [!IMPORTANT] +> This document describes an older version `v1` of the `CourseAuthoringUnitSidebarSlot`. +> It is recommended to use the `org.openedx.frontend.authoring.course_unit_sidebar.v2` slot ID for new plugins. + +The `v1` slot has the following limitations compared to the `v2` version: +* It renders conditionally based on the `isUnitVerticalType` prop, which means the plugins won't be rendered in other scenarios like unit with library blocks. +* It does **not** wrap the `SplitTestSidebarInfo` component. So it can't be hidden from the sidebar by overriding the components in the slot. +* As it is not the primary child component of the sidebar, CSS styling for inserted components face limitations, such as an inability to be `sticky` or achieve 100% height. + ## Example 1 ![Screenshot of the unit sidebar surrounded by border](./images/unit_sidebar_with_border.png)