feat: add course end dashboard plugin slots (#1658)

* feat: add additional course end plugin slots

* fix: bring plugin slot names in line with new naming scheme

* refactor: change plugin files to tsx,remove propTypes

* fixup! refactor: change plugin files to tsx,remove propTypes

* fixup! fixup! refactor: change plugin files to tsx,remove propTypes

* fixup! fixup! fixup! refactor: change plugin files to tsx,remove propTypes

* fix: accidentally committed test code

* fix: plugin-slot fixes

* chore: add ENTERPRISE_LEARNER_PORTAL_URL env var
This commit is contained in:
Jansen Kantor
2025-05-08 14:23:41 -04:00
committed by GitHub
parent 73406fbb31
commit b1ee8a3713
17 changed files with 206 additions and 66 deletions

View File

@@ -0,0 +1,37 @@
# Course Exit "View Courses" Button Plugin Slot
### Slot ID: `org.openedx.frontend.learning.course_exit_view_courses.v1`
### Props:
* `content: { href }`
## Description
This slot is used for modifying "View Courses" button in the course exit screen
## Example
The following `env.config.jsx` will make the link link to `example.com`
```js
import { DIRECT_PLUGIN, PLUGIN_OPERATIONS } from '@openedx/frontend-plugin-framework';
const config = {
pluginSlots: {
'org.openedx.frontend.learning.course_exit_view_courses.v1: {
keepDefault: true,
plugins: [
{
op: PLUGIN_OPERATIONS.Modify,
widgetId: 'default_contents',
fn: (widget) => {
widget.content.href = 'http://www.example.com';
return widget;
}
},
]
},
},
}
export default config;
```

View File

@@ -0,0 +1,37 @@
import { Button } from '@openedx/paragon';
import { getConfig } from '@edx/frontend-platform';
import { PluginSlot } from '@openedx/frontend-plugin-framework';
import { useIntl } from '@edx/frontend-platform/i18n';
import messages from '../../../courseware/course/course-exit/messages';
interface Props {
href: string
}
const ViewCoursesLink: React.FC<Props> = ({ href }: Props) => {
const intl = useIntl();
return (
<div className="row w-100 mt-2 mb-4 justify-content-end">
<Button
variant="outline-primary"
href={href}
>
{intl.formatMessage(messages.viewCoursesButton)}
</Button>
</div>
);
};
export const CourseExitViewCoursesPluginSlot: React.FC = () => {
const href = `${getConfig().LMS_BASE_URL}/dashboard`;
return (
<PluginSlot
id="org.openedx.frontend.learning.course_exit_view_courses.v1"
slotOptions={{
mergeProps: true,
}}
>
<ViewCoursesLink href={href} />
</PluginSlot>
);
};

View File

@@ -0,0 +1,43 @@
# Course Recommendations Slot
### Slot ID: `org.openedx.frontend.learning.course_recommendations.v1`
### Slot ID Aliases
* `course_recommendations_slot`
### Props:
* `variant`
## Description
This slot is used for modifying the course end recommendation
## Example
The following `env.config.jsx` will replace the course recommendations with a thumbs up
![Screenshot of modified course celebration](./screenshot_custom.png)
```js
import { DIRECT_PLUGIN, PLUGIN_OPERATIONS } from '@openedx/frontend-plugin-framework';
const config = {
pluginSlots: {
'org.openedx.frontend.learning.course_recommendations.v1': {
plugins: [
{
op: PLUGIN_OPERATIONS.Insert,
widget: {
id: 'inserted_direct_plugin',
type: DIRECT_PLUGIN,
priority: 10,
RenderWidget: () => (<div >👍</div>),
},
},
]
},
},
}
export default config;
```

View File

@@ -0,0 +1,15 @@
import { PluginSlot } from '@openedx/frontend-plugin-framework';
import CourseRecommendations from '../../../courseware/course/course-exit/CourseRecommendations';
interface Props {
variant: string;
}
export const CourseRecommendationsSlot: React.FC<Props> = ({ variant }: Props) => (
<PluginSlot
id="org.openedx.frontend.learning.course_recommendations.v1"
idAliases={['course_recommendations_slot']}
>
<CourseRecommendations variant={variant} />
</PluginSlot>
);

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

View File

@@ -0,0 +1,40 @@
# Course Exit Dashboard Footnote Link Plugin Slot
### Slot ID: `org.openedx.frontend.learning.course_exit_dashboard_footnote_link.v1`
### Props:
* `variant`
* `content: { destination }`
## Description
This slot is used for modifying the link to the learner dashboard in the footnote on the course exit page
## Example
The following `env.config.jsx` will change the link to point to `example.com`
![Screenshot of modified course celebration](./screenshot_custom.png)
```js
import { DIRECT_PLUGIN, PLUGIN_OPERATIONS } from '@openedx/frontend-plugin-framework';
const config = {
pluginSlots: {
'org.openedx.frontend.learning.course_exit_dashboard_footnote_link.v1': {
keepDefault: true,
plugins: [
{
op: PLUGIN_OPERATIONS.Modify,
widgetId: 'default_contents',
fn: (widget) => {
widget.content.destination = 'http://www.example.com';
return widget;
}
},
]
},
},
}
export default config;
```

View File

@@ -0,0 +1,49 @@
import { Hyperlink } from '@openedx/paragon';
import { getConfig } from '@edx/frontend-platform';
import { PluginSlot } from '@openedx/frontend-plugin-framework';
import { useIntl } from '@edx/frontend-platform/i18n';
import { getAuthenticatedUser } from '@edx/frontend-platform/auth';
import messages from '../../../courseware/course/course-exit/messages';
import { logClick } from '../../../courseware/course/course-exit/utils';
import { useModel } from '../../../generic/model-store';
import { useContextId } from '../../../data/hooks';
interface LinkProps {
variant: string;
destination: string;
}
const DashboardFootnoteLink: React.FC<LinkProps> = ({ variant, destination }: LinkProps) => {
const intl = useIntl();
const courseId = useContextId();
const { org } = useModel('courseHomeMeta', courseId);
const { administrator } = getAuthenticatedUser();
return (
<Hyperlink
style={{ textDecoration: 'underline' }}
destination={destination}
className="text-reset"
onClick={() => logClick(org, courseId, administrator, 'dashboard_footnote', { variant })}
>
{intl.formatMessage(messages.dashboardLink)}
</Hyperlink>
);
};
interface PluginProps {
variant: string
}
export const DashboardFootnoteLinkPluginSlot: React.FC = ({ variant }: PluginProps) => {
const destination = `${getConfig().LMS_BASE_URL}/dashboard`;
return (
<PluginSlot
id="org.openedx.frontend.learning.course_exit_dashboard_footnote_link.v1"
slotOptions={{
mergeProps: true,
}}
>
<DashboardFootnoteLink variant={variant} destination={destination} />
</PluginSlot>
);
};

View File

@@ -0,0 +1,9 @@
import { DashboardFootnoteLinkPluginSlot } from './DashboardFootnoteLinkPluginSlot';
import { CourseRecommendationsSlot } from './CourseRecommendationsSlot';
import { CourseExitViewCoursesPluginSlot } from './CourseExitViewCoursesPluginSlot';
export {
DashboardFootnoteLinkPluginSlot,
CourseRecommendationsSlot,
CourseExitViewCoursesPluginSlot,
};