Skip to content

Commit a9654dc

Browse files
xitij2000Agrendalath
authored andcommitted
feat: Add plugin slots for progress page components
Adds a slot for different components in the progress tab to allow them to be overridden with custom components. (cherry picked from commit 0c462fa)
1 parent ce6b13b commit a9654dc

File tree

9 files changed

+276
-18
lines changed

9 files changed

+276
-18
lines changed

src/course-home/progress-tab/ProgressTab.jsx

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,21 @@ import React from 'react';
22
import { useSelector } from 'react-redux';
33
import { breakpoints, useWindowSize } from '@openedx/paragon';
44

5-
import CertificateStatus from './certificate-status/CertificateStatus';
65
import CourseCompletion from './course-completion/CourseCompletion';
7-
import CourseGrade from './grades/course-grade/CourseGrade';
8-
import DetailedGrades from './grades/detailed-grades/DetailedGrades';
9-
import GradeSummary from './grades/grade-summary/GradeSummary';
106
import ProgressHeader from './ProgressHeader';
11-
import RelatedLinks from './related-links/RelatedLinks';
127

8+
import ProgressTabCertificateStatusSlot from '../../plugin-slots/ProgressTabCertificateStatusSlot';
9+
import ProgressTabCourseGradeSlot from '../../plugin-slots/ProgressTabCourseGradeSlot';
10+
import ProgressTabGradeBreakdownSlot from '../../plugin-slots/ProgressTabGradeBreakdownSlot';
11+
import ProgressTabRelatedLinksSlot from '../../plugin-slots/ProgressTabRelatedLinksSlot';
1312
import { useModel } from '../../generic/model-store';
1413

1514
const ProgressTab = () => {
1615
const {
1716
courseId,
1817
} = useSelector(state => state.courseHome);
1918

20-
const {
21-
gradesFeatureIsFullyLocked, disableProgressGraph,
22-
} = useModel('progress', courseId);
23-
24-
const applyLockedOverlay = gradesFeatureIsFullyLocked ? 'locked-overlay' : '';
19+
const { disableProgressGraph } = useModel('progress', courseId);
2520

2621
const windowWidth = useWindowSize().width;
2722
if (windowWidth === undefined) {
@@ -39,18 +34,15 @@ const ProgressTab = () => {
3934
{/* Main body */}
4035
<div className="col-12 col-md-8 p-0">
4136
{!disableProgressGraph && <CourseCompletion />}
42-
{!wideScreen && <CertificateStatus />}
43-
<CourseGrade />
44-
<div className={`grades my-4 p-4 rounded raised-card ${applyLockedOverlay}`} aria-hidden={gradesFeatureIsFullyLocked}>
45-
<GradeSummary />
46-
<DetailedGrades />
47-
</div>
37+
{!wideScreen && <ProgressTabCertificateStatusSlot courseId={courseId} />}
38+
<ProgressTabCourseGradeSlot courseId={courseId} />
39+
<ProgressTabGradeBreakdownSlot courseId={courseId} />
4840
</div>
4941

5042
{/* Side panel */}
5143
<div className="col-12 col-md-4 p-0 px-md-4">
52-
{wideScreen && <CertificateStatus />}
53-
<RelatedLinks />
44+
{wideScreen && <ProgressTabCertificateStatusSlot courseId={courseId} />}
45+
<ProgressTabRelatedLinksSlot courseId={courseId} />
5446
</div>
5547
</div>
5648
</>
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Progress Tab Certificate Status Slot
2+
3+
### Slot ID: `progress_tab_certificate_status_slot`
4+
### Props:
5+
* `courseId`
6+
7+
## Description
8+
9+
This slot is used to replace or modify the Certificate Status component in the
10+
Progress Tab.
11+
12+
## Example
13+
14+
The following `env.config.jsx` will render the `course_id` and `unit_id` of the course as `<p>` elements in a `<div>`.
15+
16+
![Screenshot of Content added after the Sequence Container](./images/post_sequence_container.png)
17+
18+
```js
19+
import { DIRECT_PLUGIN, PLUGIN_OPERATIONS } from '@openedx/frontend-plugin-framework';
20+
21+
const config = {
22+
pluginSlots: {
23+
progress_tab_certificate_status_slot: {
24+
plugins: [
25+
{
26+
// Insert custom content after certificate status
27+
op: PLUGIN_OPERATIONS.Insert,
28+
widget: {
29+
id: 'custom_certificate_status_content',
30+
type: DIRECT_PLUGIN,
31+
RenderWidget: ({courseId}) => (
32+
<div>
33+
<p>📚: {courseId}</p>
34+
</div>
35+
),
36+
},
37+
},
38+
]
39+
}
40+
},
41+
}
42+
43+
export default config;
44+
```
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import PropTypes from 'prop-types';
2+
import { PluginSlot } from '@openedx/frontend-plugin-framework';
3+
import CertificateStatus from '../../course-home/progress-tab/certificate-status/CertificateStatus';
4+
5+
const ProgressTabCertificateStatusSlot = ({ courseId }) => (
6+
<PluginSlot
7+
id="progress_tab_certificate_status_slot"
8+
pluginProps={{
9+
courseId,
10+
}}
11+
>
12+
<CertificateStatus />
13+
</PluginSlot>
14+
);
15+
16+
ProgressTabCertificateStatusSlot.propTypes = {
17+
courseId: PropTypes.string.isRequired,
18+
};
19+
20+
export default ProgressTabCertificateStatusSlot;
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Progress Tab Course Grade Slot
2+
3+
### Slot ID: `progress_tab_course_grade_slot`
4+
### Props:
5+
* `courseId`
6+
7+
## Description
8+
9+
This slot is used to replace or modify the Course Grades view in the Progress Tab.
10+
11+
## Example
12+
13+
The following `env.config.jsx` will render the `course_id` and `unit_id` of the course as `<p>` elements in a `<div>`.
14+
15+
![Screenshot of Content added after the Sequence Container](./images/post_sequence_container.png)
16+
17+
```js
18+
import { DIRECT_PLUGIN, PLUGIN_OPERATIONS } from '@openedx/frontend-plugin-framework';
19+
20+
const config = {
21+
pluginSlots: {
22+
progress_tab_course_grade_slot: {
23+
plugins: [
24+
{
25+
// Insert custom content after course grade widget
26+
op: PLUGIN_OPERATIONS.Insert,
27+
widget: {
28+
id: 'custom_course_grade_content',
29+
type: DIRECT_PLUGIN,
30+
RenderWidget: ({courseId}) => (
31+
<div>
32+
<p>📚: {courseId}</p>
33+
</div>
34+
),
35+
},
36+
},
37+
]
38+
}
39+
},
40+
}
41+
42+
export default config;
43+
```
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import PropTypes from 'prop-types';
2+
import { PluginSlot } from '@openedx/frontend-plugin-framework';
3+
import CourseGrade from '../../course-home/progress-tab/grades/course-grade/CourseGrade';
4+
5+
const ProgressTabCourseGradeSlot = ({ courseId }) => (
6+
<PluginSlot
7+
id="progress_tab_course_grade_slot"
8+
pluginProps={{
9+
courseId,
10+
}}
11+
>
12+
<CourseGrade />
13+
</PluginSlot>
14+
);
15+
16+
ProgressTabCourseGradeSlot.propTypes = {
17+
courseId: PropTypes.string.isRequired,
18+
};
19+
20+
export default ProgressTabCourseGradeSlot;
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Progress Tab Grade Summary Slot
2+
3+
### Slot ID: `progress_tab_grade_summary_slot`
4+
### Props:
5+
* `courseId`
6+
7+
## Description
8+
9+
This slot is used to replace or modify the Grade Summary view in the Progress Tab.
10+
11+
## Example
12+
13+
The following `env.config.jsx` will render the `course_id` and `unit_id` of the course as `<p>` elements in a `<div>`.
14+
15+
![Screenshot of Content added after the Sequence Container](./images/post_sequence_container.png)
16+
17+
```js
18+
import { DIRECT_PLUGIN, PLUGIN_OPERATIONS } from '@openedx/frontend-plugin-framework';
19+
20+
const config = {
21+
pluginSlots: {
22+
progress_tab_grade_summary_slot: {
23+
plugins: [
24+
{
25+
// Insert custom content after grade summary widget
26+
op: PLUGIN_OPERATIONS.Insert,
27+
widget: {
28+
id: 'custom_grade_summary_content',
29+
type: DIRECT_PLUGIN,
30+
RenderWidget: ({courseId}) => (
31+
<div>
32+
<p>📚: {courseId}</p>
33+
</div>
34+
),
35+
},
36+
},
37+
]
38+
}
39+
},
40+
}
41+
42+
export default config;
43+
```
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { useModel } from '@src/generic/model-store';
2+
import PropTypes from 'prop-types';
3+
import { PluginSlot } from '@openedx/frontend-plugin-framework';
4+
import React from 'react';
5+
import DetailedGrades from '../../course-home/progress-tab/grades/detailed-grades/DetailedGrades';
6+
import GradeSummary from '../../course-home/progress-tab/grades/grade-summary/GradeSummary';
7+
8+
const ProgressTabGradeBreakdownSlot = ({ courseId }) => {
9+
const { gradesFeatureIsFullyLocked } = useModel('progress', courseId);
10+
const applyLockedOverlay = gradesFeatureIsFullyLocked ? 'locked-overlay' : '';
11+
return (
12+
<PluginSlot
13+
id="progress_tab_grade_breakdown_slot"
14+
pluginProps={{
15+
courseId,
16+
}}
17+
>
18+
<div
19+
className={`grades my-4 p-4 rounded raised-card ${applyLockedOverlay}`}
20+
aria-hidden={gradesFeatureIsFullyLocked}
21+
>
22+
<GradeSummary />
23+
<DetailedGrades />
24+
</div>
25+
</PluginSlot>
26+
);
27+
};
28+
29+
ProgressTabGradeBreakdownSlot.propTypes = {
30+
courseId: PropTypes.string.isRequired,
31+
};
32+
33+
export default ProgressTabGradeBreakdownSlot;
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Progress Tab Related Links Slot
2+
3+
### Slot ID: `progress_tab_related_links_slot`
4+
### Props:
5+
* `courseId`
6+
7+
## Description
8+
9+
This slot is used to replace or modify the related links view in the Progress Tab.
10+
11+
## Example
12+
13+
The following `env.config.jsx` will render the `course_id` and `unit_id` of the course as `<p>` elements in a `<div>`.
14+
15+
![Screenshot of Content added after the Sequence Container](./images/post_sequence_container.png)
16+
17+
```js
18+
import { DIRECT_PLUGIN, PLUGIN_OPERATIONS } from '@openedx/frontend-plugin-framework';
19+
20+
const config = {
21+
pluginSlots: {
22+
progress_tab_related_links_slot: {
23+
plugins: [
24+
{
25+
// Insert custom content after related links widget
26+
op: PLUGIN_OPERATIONS.Insert,
27+
widget: {
28+
id: 'custom_related_links_content',
29+
type: DIRECT_PLUGIN,
30+
RenderWidget: ({courseId}) => (
31+
<div>
32+
<p>📚: {courseId}</p>
33+
</div>
34+
),
35+
},
36+
},
37+
]
38+
}
39+
},
40+
}
41+
42+
export default config;
43+
```
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import PropTypes from 'prop-types';
2+
import { PluginSlot } from '@openedx/frontend-plugin-framework';
3+
import RelatedLinks from '../../course-home/progress-tab/related-links/RelatedLinks';
4+
5+
const ProgressTabRelatedLinksSlot = ({ courseId }) => (
6+
<PluginSlot
7+
id="progress_tab_related_links_slot"
8+
pluginProps={{
9+
courseId,
10+
}}
11+
>
12+
<RelatedLinks />
13+
</PluginSlot>
14+
);
15+
16+
ProgressTabRelatedLinksSlot.propTypes = {
17+
courseId: PropTypes.string.isRequired,
18+
};
19+
20+
export default ProgressTabRelatedLinksSlot;

0 commit comments

Comments
 (0)