Skip to content

Commit

Permalink
feat: Add plugin slots for progress page components
Browse files Browse the repository at this point in the history
Adds a slot for different components in the progress tab to allow them to be
overridden with custom components.
  • Loading branch information
xitij2000 committed Oct 30, 2024
1 parent d64a4e4 commit 0c462fa
Show file tree
Hide file tree
Showing 9 changed files with 276 additions and 18 deletions.
28 changes: 10 additions & 18 deletions src/course-home/progress-tab/ProgressTab.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,21 @@ import React from 'react';
import { useSelector } from 'react-redux';
import { breakpoints, useWindowSize } from '@openedx/paragon';

import CertificateStatus from './certificate-status/CertificateStatus';
import CourseCompletion from './course-completion/CourseCompletion';
import CourseGrade from './grades/course-grade/CourseGrade';
import DetailedGrades from './grades/detailed-grades/DetailedGrades';
import GradeSummary from './grades/grade-summary/GradeSummary';
import ProgressHeader from './ProgressHeader';
import RelatedLinks from './related-links/RelatedLinks';

import ProgressTabCertificateStatusSlot from '../../plugin-slots/ProgressTabCertificateStatusSlot';
import ProgressTabCourseGradeSlot from '../../plugin-slots/ProgressTabCourseGradeSlot';
import ProgressTabGradeBreakdownSlot from '../../plugin-slots/ProgressTabGradeBreakdownSlot';
import ProgressTabRelatedLinksSlot from '../../plugin-slots/ProgressTabRelatedLinksSlot';
import { useModel } from '../../generic/model-store';

const ProgressTab = () => {
const {
courseId,
} = useSelector(state => state.courseHome);

const {
gradesFeatureIsFullyLocked, disableProgressGraph,
} = useModel('progress', courseId);

const applyLockedOverlay = gradesFeatureIsFullyLocked ? 'locked-overlay' : '';
const { disableProgressGraph } = useModel('progress', courseId);

const windowWidth = useWindowSize().width;
if (windowWidth === undefined) {
Expand All @@ -39,18 +34,15 @@ const ProgressTab = () => {
{/* Main body */}
<div className="col-12 col-md-8 p-0">
{!disableProgressGraph && <CourseCompletion />}
{!wideScreen && <CertificateStatus />}
<CourseGrade />
<div className={`grades my-4 p-4 rounded raised-card ${applyLockedOverlay}`} aria-hidden={gradesFeatureIsFullyLocked}>
<GradeSummary />
<DetailedGrades />
</div>
{!wideScreen && <ProgressTabCertificateStatusSlot courseId={courseId} />}
<ProgressTabCourseGradeSlot courseId={courseId} />
<ProgressTabGradeBreakdownSlot courseId={courseId} />
</div>

{/* Side panel */}
<div className="col-12 col-md-4 p-0 px-md-4">
{wideScreen && <CertificateStatus />}
<RelatedLinks />
{wideScreen && <ProgressTabCertificateStatusSlot courseId={courseId} />}
<ProgressTabRelatedLinksSlot courseId={courseId} />
</div>
</div>
</>
Expand Down
44 changes: 44 additions & 0 deletions src/plugin-slots/ProgressTabCertificateStatusSlot/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Progress Tab Certificate Status Slot

### Slot ID: `progress_tab_certificate_status_slot`
### Props:
* `courseId`

## Description

This slot is used to replace or modify the Certificate Status component in the
Progress Tab.

## Example

The following `env.config.jsx` will render the `course_id` and `unit_id` of the course as `<p>` elements in a `<div>`.

![Screenshot of Content added after the Sequence Container](./images/post_sequence_container.png)

```js
import { DIRECT_PLUGIN, PLUGIN_OPERATIONS } from '@openedx/frontend-plugin-framework';

const config = {
pluginSlots: {
progress_tab_certificate_status_slot: {
plugins: [
{
// Insert custom content after certificate status
op: PLUGIN_OPERATIONS.Insert,
widget: {
id: 'custom_certificate_status_content',
type: DIRECT_PLUGIN,
RenderWidget: ({courseId}) => (
<div>
<p>📚: {courseId}</p>
</div>
),
},
},
]
}
},
}

export default config;
```
20 changes: 20 additions & 0 deletions src/plugin-slots/ProgressTabCertificateStatusSlot/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import PropTypes from 'prop-types';
import { PluginSlot } from '@openedx/frontend-plugin-framework';
import CertificateStatus from '../../course-home/progress-tab/certificate-status/CertificateStatus';

const ProgressTabCertificateStatusSlot = ({ courseId }) => (
<PluginSlot
id="progress_tab_certificate_status_slot"
pluginProps={{
courseId,
}}
>
<CertificateStatus />
</PluginSlot>
);

ProgressTabCertificateStatusSlot.propTypes = {
courseId: PropTypes.string.isRequired,
};

export default ProgressTabCertificateStatusSlot;
43 changes: 43 additions & 0 deletions src/plugin-slots/ProgressTabCourseGradeSlot/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Progress Tab Course Grade Slot

### Slot ID: `progress_tab_course_grade_slot`
### Props:
* `courseId`

## Description

This slot is used to replace or modify the Course Grades view in the Progress Tab.

## Example

The following `env.config.jsx` will render the `course_id` and `unit_id` of the course as `<p>` elements in a `<div>`.

![Screenshot of Content added after the Sequence Container](./images/post_sequence_container.png)

```js
import { DIRECT_PLUGIN, PLUGIN_OPERATIONS } from '@openedx/frontend-plugin-framework';

const config = {
pluginSlots: {
progress_tab_course_grade_slot: {
plugins: [
{
// Insert custom content after course grade widget
op: PLUGIN_OPERATIONS.Insert,
widget: {
id: 'custom_course_grade_content',
type: DIRECT_PLUGIN,
RenderWidget: ({courseId}) => (
<div>
<p>📚: {courseId}</p>
</div>
),
},
},
]
}
},
}

export default config;
```
20 changes: 20 additions & 0 deletions src/plugin-slots/ProgressTabCourseGradeSlot/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import PropTypes from 'prop-types';
import { PluginSlot } from '@openedx/frontend-plugin-framework';
import CourseGrade from '../../course-home/progress-tab/grades/course-grade/CourseGrade';

const ProgressTabCourseGradeSlot = ({ courseId }) => (
<PluginSlot
id="progress_tab_course_grade_slot"
pluginProps={{
courseId,
}}
>
<CourseGrade />
</PluginSlot>
);

ProgressTabCourseGradeSlot.propTypes = {
courseId: PropTypes.string.isRequired,
};

export default ProgressTabCourseGradeSlot;
43 changes: 43 additions & 0 deletions src/plugin-slots/ProgressTabGradeBreakdownSlot/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Progress Tab Grade Summary Slot

### Slot ID: `progress_tab_grade_summary_slot`
### Props:
* `courseId`

## Description

This slot is used to replace or modify the Grade Summary view in the Progress Tab.

## Example

The following `env.config.jsx` will render the `course_id` and `unit_id` of the course as `<p>` elements in a `<div>`.

![Screenshot of Content added after the Sequence Container](./images/post_sequence_container.png)

```js
import { DIRECT_PLUGIN, PLUGIN_OPERATIONS } from '@openedx/frontend-plugin-framework';

const config = {
pluginSlots: {
progress_tab_grade_summary_slot: {
plugins: [
{
// Insert custom content after grade summary widget
op: PLUGIN_OPERATIONS.Insert,
widget: {
id: 'custom_grade_summary_content',
type: DIRECT_PLUGIN,
RenderWidget: ({courseId}) => (
<div>
<p>📚: {courseId}</p>
</div>
),
},
},
]
}
},
}

export default config;
```
33 changes: 33 additions & 0 deletions src/plugin-slots/ProgressTabGradeBreakdownSlot/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { useModel } from '@src/generic/model-store';
import PropTypes from 'prop-types';
import { PluginSlot } from '@openedx/frontend-plugin-framework';
import React from 'react';
import DetailedGrades from '../../course-home/progress-tab/grades/detailed-grades/DetailedGrades';
import GradeSummary from '../../course-home/progress-tab/grades/grade-summary/GradeSummary';

const ProgressTabGradeBreakdownSlot = ({ courseId }) => {
const { gradesFeatureIsFullyLocked } = useModel('progress', courseId);
const applyLockedOverlay = gradesFeatureIsFullyLocked ? 'locked-overlay' : '';
return (
<PluginSlot
id="progress_tab_grade_breakdown_slot"
pluginProps={{
courseId,
}}
>
<div
className={`grades my-4 p-4 rounded raised-card ${applyLockedOverlay}`}
aria-hidden={gradesFeatureIsFullyLocked}
>
<GradeSummary />
<DetailedGrades />
</div>
</PluginSlot>
);
};

ProgressTabGradeBreakdownSlot.propTypes = {
courseId: PropTypes.string.isRequired,
};

export default ProgressTabGradeBreakdownSlot;
43 changes: 43 additions & 0 deletions src/plugin-slots/ProgressTabRelatedLinksSlot/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Progress Tab Related Links Slot

### Slot ID: `progress_tab_related_links_slot`
### Props:
* `courseId`

## Description

This slot is used to replace or modify the related links view in the Progress Tab.

## Example

The following `env.config.jsx` will render the `course_id` and `unit_id` of the course as `<p>` elements in a `<div>`.

![Screenshot of Content added after the Sequence Container](./images/post_sequence_container.png)

```js
import { DIRECT_PLUGIN, PLUGIN_OPERATIONS } from '@openedx/frontend-plugin-framework';

const config = {
pluginSlots: {
progress_tab_related_links_slot: {
plugins: [
{
// Insert custom content after related links widget
op: PLUGIN_OPERATIONS.Insert,
widget: {
id: 'custom_related_links_content',
type: DIRECT_PLUGIN,
RenderWidget: ({courseId}) => (
<div>
<p>📚: {courseId}</p>
</div>
),
},
},
]
}
},
}

export default config;
```
20 changes: 20 additions & 0 deletions src/plugin-slots/ProgressTabRelatedLinksSlot/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import PropTypes from 'prop-types';
import { PluginSlot } from '@openedx/frontend-plugin-framework';
import RelatedLinks from '../../course-home/progress-tab/related-links/RelatedLinks';

const ProgressTabRelatedLinksSlot = ({ courseId }) => (
<PluginSlot
id="progress_tab_related_links_slot"
pluginProps={{
courseId,
}}
>
<RelatedLinks />
</PluginSlot>
);

ProgressTabRelatedLinksSlot.propTypes = {
courseId: PropTypes.string.isRequired,
};

export default ProgressTabRelatedLinksSlot;

0 comments on commit 0c462fa

Please sign in to comment.