Skip to content

Commit 341a03c

Browse files
authored
feat: Add plugin slots for sidebars (#1752)
1 parent 5df7adf commit 341a03c

File tree

12 files changed

+168
-50
lines changed

12 files changed

+168
-50
lines changed

src/course-outline/CourseOutline.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
verticalListSortingStrategy,
2323
} from '@dnd-kit/sortable';
2424
import { useLocation } from 'react-router-dom';
25+
import { CourseAuthoringOutlineSidebarSlot } from '../plugin-slots/CourseAuthoringOutlineSidebarSlot';
2526

2627
import { LoadingSpinner } from '../generic/Loading';
2728
import { getProcessingNotification } from '../generic/processing-notification/data/selectors';
@@ -35,7 +36,6 @@ import AlertMessage from '../generic/alert-message';
3536
import getPageHeadTitle from '../generic/utils';
3637
import { getCurrentItem, getProctoredExamsFlag } from './data/selectors';
3738
import { COURSE_BLOCK_NAMES } from './constants';
38-
import OutlineSideBar from './outline-sidebar/OutlineSidebar';
3939
import StatusBar from './status-bar/StatusBar';
4040
import EnableHighlightsModal from './enable-highlights-modal/EnableHighlightsModal';
4141
import SectionCard from './section-card/SectionCard';
@@ -453,7 +453,7 @@ const CourseOutline = ({ courseId }) => {
453453
</article>
454454
</Layout.Element>
455455
<Layout.Element>
456-
<OutlineSideBar courseId={courseId} />
456+
<CourseAuthoringOutlineSidebarSlot courseId={courseId} />
457457
</Layout.Element>
458458
</Layout>
459459
<EnableHighlightsModal

src/course-outline/outline-sidebar/OutlineSidebar.jsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ const OutlineSideBar = ({ courseId }) => {
2626

2727
return (
2828
<HelpSidebar
29-
intl={intl}
3029
courseId={courseId}
3130
showOtherSettings={false}
3231
className="outline-sidebar mt-4"

src/course-unit/CourseUnit.jsx

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ import { useParams } from 'react-router-dom';
55
import {
66
Container, Layout, Stack, Button, TransitionReplace,
77
} from '@openedx/paragon';
8-
import { getConfig } from '@edx/frontend-platform';
9-
import { useIntl, injectIntl } from '@edx/frontend-platform/i18n';
8+
import { useIntl } from '@edx/frontend-platform/i18n';
109
import {
1110
Warning as WarningIcon,
1211
CheckCircle as CheckCircleIcon,
1312
} from '@openedx/paragon/icons';
13+
import { CourseAuthoringUnitSidebarSlot } from '../plugin-slots/CourseAuthoringUnitSidebarSlot';
1414

1515
import { getProcessingNotification } from '../generic/processing-notification/data/selectors';
1616
import SubHeader from '../generic/sub-header/SubHeader';
@@ -30,9 +30,6 @@ import Sidebar from './sidebar';
3030
import SplitTestSidebarInfo from './sidebar/SplitTestSidebarInfo';
3131
import { useCourseUnit, useLayoutGrid, useScrollToLastPosition } from './hooks';
3232
import messages from './messages';
33-
import PublishControls from './sidebar/PublishControls';
34-
import LocationInfo from './sidebar/LocationInfo';
35-
import TagsSidebarControls from '../content-tags-drawer/tags-sidebar-controls';
3633
import { PasteNotificationAlert } from './clipboard';
3734
import XBlockContainerIframe from './xblock-container-iframe';
3835
import MoveModal from './move-modal';
@@ -225,19 +222,11 @@ const CourseUnit = ({ courseId }) => {
225222
<Layout.Element>
226223
<Stack gap={3}>
227224
{isUnitVerticalType && (
228-
<>
229-
<Sidebar data-testid="course-unit-sidebar">
230-
<PublishControls blockId={blockId} />
231-
</Sidebar>
232-
{getConfig().ENABLE_TAGGING_TAXONOMY_PAGES === 'true' && (
233-
<Sidebar className="tags-sidebar">
234-
<TagsSidebarControls />
235-
</Sidebar>
236-
)}
237-
<Sidebar data-testid="course-unit-location-sidebar">
238-
<LocationInfo />
239-
</Sidebar>
240-
</>
225+
<CourseAuthoringUnitSidebarSlot
226+
courseId={courseId}
227+
blockId={blockId}
228+
unitTitle={unitTitle}
229+
/>
241230
)}
242231
{isSplitTestType && (
243232
<Sidebar data-testid="course-split-test-sidebar">
@@ -267,4 +256,4 @@ CourseUnit.propTypes = {
267256
courseId: PropTypes.string.isRequired,
268257
};
269258

270-
export default injectIntl(CourseUnit);
259+
export default CourseUnit;

src/course-unit/sidebar/index.jsx

Lines changed: 0 additions & 24 deletions
This file was deleted.

src/course-unit/sidebar/index.tsx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import classNames from 'classnames';
2+
import { Card } from '@openedx/paragon';
3+
4+
const Sidebar = ({ className = null, children = null, ...props }:SidebarProps) => (
5+
<Card
6+
className={classNames('course-unit-sidebar', className)}
7+
{...props}
8+
>
9+
{children}
10+
</Card>
11+
);
12+
13+
interface SidebarProps {
14+
className?: string | null;
15+
children?: React.ReactNode | null;
16+
}
17+
18+
export default Sidebar;

src/generic/help-sidebar/HelpSidebar.jsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import PropTypes from 'prop-types';
22
import { useSelector } from 'react-redux';
33
import { useLocation } from 'react-router-dom';
44
import classNames from 'classnames';
5-
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
5+
import { useIntl } from '@edx/frontend-platform/i18n';
66
import { getConfig } from '@edx/frontend-platform';
77

88
import { getWaffleFlags } from '../../data/selectors';
@@ -11,13 +11,13 @@ import messages from './messages';
1111
import HelpSidebarLink from './HelpSidebarLink';
1212

1313
const HelpSidebar = ({
14-
intl,
1514
courseId,
1615
showOtherSettings,
1716
proctoredExamSettingsUrl,
1817
children,
1918
className,
2019
}) => {
20+
const intl = useIntl();
2121
const { pathname } = useLocation();
2222
const {
2323
grading,
@@ -124,12 +124,11 @@ HelpSidebar.defaultProps = {
124124
};
125125

126126
HelpSidebar.propTypes = {
127-
intl: intlShape.isRequired,
128127
courseId: PropTypes.string,
129128
showOtherSettings: PropTypes.bool,
130129
proctoredExamSettingsUrl: PropTypes.string,
131130
children: PropTypes.node.isRequired,
132131
className: PropTypes.string,
133132
};
134133

135-
export default injectIntl(HelpSidebar);
134+
export default HelpSidebar;
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# CourseAuthoringOutlineSidebarSlot
2+
3+
### Slot ID: `course_authoring_outline_sidebar_slot`
4+
5+
### Plugin Props:
6+
7+
* `courseId` - String.
8+
9+
## Description
10+
11+
The slot wraps the sidebar that is displayed on the course outline page. It can
12+
be used to add additional sidebar components or modify the existing sidebar.
13+
14+
## Example
15+
16+
![Screenshot of the outline sidebar surrounded by border](./images/outline_sidebar_with_border.png)
17+
18+
The following example configuration surrounds the sidebar in a border as shown above.
19+
20+
```js
21+
import { PLUGIN_OPERATIONS } from '@openedx/frontend-plugin-framework';
22+
23+
const config = {
24+
pluginSlots: {
25+
course_authoring_outline_sidebar_slot: {
26+
keepDefault: true,
27+
plugins: [
28+
{
29+
op: PLUGIN_OPERATIONS.Wrap,
30+
widgetId: 'default_contents',
31+
wrapper: ({ component }) => (
32+
<div style={{ border: 'thick dashed red' }}>{component}</div>
33+
),
34+
},
35+
],
36+
},
37+
}
38+
};
39+
export default config;
40+
```
Loading
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { PluginSlot } from '@openedx/frontend-plugin-framework/dist';
2+
import React from 'react';
3+
import OutlineSideBar from '../../course-outline/outline-sidebar/OutlineSidebar';
4+
5+
export const CourseAuthoringOutlineSidebarSlot = ({ courseId }: CourseAuthoringOutlineSidebarSlotProps) => (
6+
<PluginSlot
7+
id="course_authoring_outline_sidebar_slot"
8+
pluginProps={{
9+
courseId,
10+
}}
11+
>
12+
<OutlineSideBar courseId={courseId} />
13+
</PluginSlot>
14+
);
15+
16+
interface CourseAuthoringOutlineSidebarSlotProps {
17+
courseId: string;
18+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# CourseAuthoringUnitSidebarSlot
2+
3+
### Slot ID: `course_authoring_unit_sidebar_slot`
4+
5+
### Plugin Props:
6+
7+
* `courseId` - String.
8+
* `blockId` - String. The usage id of the current unit being viewed / edited.
9+
* `unitTitle` - String. The name of the current unit being viewed / edited.
10+
11+
## Description
12+
13+
The slot wraps the sidebar that is displayed on the unit editor page. It can
14+
be used to add additional sidebar components or modify the existing sidebar.
15+
16+
## Example
17+
18+
![Screenshot of the unit sidebar surrounded by border](./images/unit_sidebar_with_border.png)
19+
20+
The following example configuration surrounds the sidebar in a border as shown above.
21+
22+
```js
23+
import { PLUGIN_OPERATIONS } from '@openedx/frontend-plugin-framework';
24+
25+
const config = {
26+
pluginSlots: {
27+
course_authoring_unit_sidebar_slot: {
28+
keepDefault: true,
29+
plugins: [
30+
{
31+
op: PLUGIN_OPERATIONS.Wrap,
32+
widgetId: 'default_contents',
33+
wrapper: ({ component }) => (
34+
<div style={{ border: 'thick dashed red' }}>{component}</div>
35+
),
36+
},
37+
],
38+
},
39+
}
40+
};
41+
export default config;
42+
```
Loading
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { getConfig } from '@edx/frontend-platform';
2+
import { PluginSlot } from '@openedx/frontend-plugin-framework/dist';
3+
import TagsSidebarControls from '../../content-tags-drawer/tags-sidebar-controls';
4+
import Sidebar from '../../course-unit/sidebar';
5+
import LocationInfo from '../../course-unit/sidebar/LocationInfo';
6+
import PublishControls from '../../course-unit/sidebar/PublishControls';
7+
8+
export const CourseAuthoringUnitSidebarSlot = (
9+
{
10+
blockId,
11+
courseId,
12+
unitTitle,
13+
}: CourseAuthoringUnitSidebarSlotProps,
14+
) => (
15+
<PluginSlot
16+
id="course_authoring_unit_sidebar_slot"
17+
pluginProps={{ blockId, courseId, unitTitle }}
18+
>
19+
<Sidebar data-testid="course-unit-sidebar">
20+
<PublishControls blockId={blockId} />
21+
</Sidebar>
22+
{getConfig().ENABLE_TAGGING_TAXONOMY_PAGES === 'true' && (
23+
<Sidebar className="tags-sidebar">
24+
<TagsSidebarControls />
25+
</Sidebar>
26+
)}
27+
<Sidebar data-testid="course-unit-location-sidebar">
28+
<LocationInfo />
29+
</Sidebar>
30+
</PluginSlot>
31+
);
32+
33+
interface CourseAuthoringUnitSidebarSlotProps {
34+
blockId: string;
35+
courseId: string;
36+
unitTitle: string;
37+
}

0 commit comments

Comments
 (0)