Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 10 additions & 20 deletions src/course-unit/CourseUnit.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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';
Expand Down Expand Up @@ -244,22 +241,15 @@ const CourseUnit = ({ courseId }) => {
<IframePreviewLibraryXBlockChanges />
</Layout.Element>
<Layout.Element>
<Stack gap={3}>
{isUnitVerticalType && (
<CourseAuthoringUnitSidebarSlot
courseId={courseId}
blockId={blockId}
unitTitle={unitTitle}
xBlocks={courseVerticalChildren.children}
readOnly={readOnly}
/>
)}
{isSplitTestType && (
<Sidebar data-testid="course-split-test-sidebar">
<SplitTestSidebarInfo />
</Sidebar>
)}
</Stack>
<CourseAuthoringUnitSidebarSlot
courseId={courseId}
blockId={blockId}
unitTitle={unitTitle}
xBlocks={courseVerticalChildren.children}
readOnly={readOnly}
isUnitVerticalType={isUnitVerticalType}
isSplitTestType={isSplitTestType}
/>
</Layout.Element>
</Layout>
</section>
Expand Down
13 changes: 7 additions & 6 deletions src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
# CourseAuthoringUnitSidebarSlot

### Slot ID: `org.openedx.frontend.authoring.course_unit_sidebar.v1`
### Slot ID: `org.openedx.frontend.authoring.course_unit_sidebar.v2`

### Slot ID Aliases
* `course_authoring_unit_sidebar_slot`
### Previous Version: [`org.openedx.frontend.authoring.course_unit_sidebar.v1`](./README.v1.md)

### Plugin Props:

Expand All @@ -12,6 +11,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

Expand All @@ -29,7 +30,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: [
{
Expand Down Expand Up @@ -63,11 +64,11 @@ const ProblemBlocks = ({unitTitle, xBlocks}) => (
}
</ul>
</>
);
);

const config = {
pluginSlots: {
'org.openedx.frontend.authoring.course_unit_sidebar.v1': {
'org.openedx.frontend.authoring.course_unit_sidebar.v2': {
keepDefault: true,
plugins: [
{
Expand Down
95 changes: 95 additions & 0 deletions src/plugin-slots/CourseAuthoringUnitSidebarSlot/README.v1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# 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.

> [!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)

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 }) => (
<div style={{ border: 'thick dashed red' }}>{component}</div>
),
},
],
},
}
};
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}) => (
<>
<h4 className="h4">{unitTitle}: Problem Blocks</h4>
<ul>
{xBlocks
.filter(block => block.blockType === "problem")
.map(block => <li key={block.id}>{block.displayName}</li>)
}
</ul>
</>
);

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;
```
50 changes: 36 additions & 14 deletions src/plugin-slots/CourseAuthoringUnitSidebarSlot/index.tsx
Original file line number Diff line number Diff line change
@@ -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 = (
{
Expand All @@ -12,26 +14,44 @@ export const CourseAuthoringUnitSidebarSlot = (
unitTitle,
xBlocks,
readOnly,
isUnitVerticalType,
isSplitTestType,
}: CourseAuthoringUnitSidebarSlotProps,
) => (
<PluginSlot
id="org.openedx.frontend.authoring.course_unit_sidebar.v1"
idAliases={['course_authoring_unit_sidebar_slot']}
id="org.openedx.frontend.authoring.course_unit_sidebar.v2"
pluginProps={{
blockId, courseId, unitTitle, xBlocks, readOnly,
blockId, courseId, unitTitle, xBlocks, readOnly, isUnitVerticalType, isSplitTestType,
}}
>
<Sidebar data-testid="course-unit-sidebar">
<PublishControls blockId={blockId} />
</Sidebar>
{getConfig().ENABLE_TAGGING_TAXONOMY_PAGES === 'true' && (
<Sidebar className="tags-sidebar">
<TagsSidebarControls readOnly={readOnly} />
</Sidebar>
)}
<Sidebar data-testid="course-unit-location-sidebar">
<LocationInfo />
</Sidebar>
<Stack gap={3}>
{isUnitVerticalType && (
<PluginSlot
id="org.openedx.frontend.authoring.course_unit_sidebar.v1"
idAliases={['course_authoring_unit_sidebar_slot']}
pluginProps={{
blockId, courseId, unitTitle, xBlocks, readOnly,
}}
>
<Sidebar data-testid="course-unit-sidebar">
<PublishControls blockId={blockId} />
</Sidebar>
{getConfig().ENABLE_TAGGING_TAXONOMY_PAGES === 'true' && (
<Sidebar className="tags-sidebar">
<TagsSidebarControls readOnly={readOnly} />
</Sidebar>
)}
<Sidebar data-testid="course-unit-location-sidebar">
<LocationInfo />
</Sidebar>
</PluginSlot>
)}
{isSplitTestType && (
<Sidebar data-testid="course-split-test-sidebar">
<SplitTestSidebarInfo />
</Sidebar>
)}
</Stack>
</PluginSlot>
);

Expand All @@ -47,4 +67,6 @@ interface CourseAuthoringUnitSidebarSlotProps {
unitTitle: string;
xBlocks: XBlock[];
readOnly: boolean;
isUnitVerticalType: boolean;
isSplitTestType: boolean;
}