Skip to content

Commit 1648ff3

Browse files
committed
feat: add dashboard footnote plugin slot
1 parent 65beaae commit 1648ff3

File tree

7 files changed

+85
-28
lines changed

7 files changed

+85
-28
lines changed

src/courseware/course/course-exit/CourseCelebration.jsx

+6-6
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,12 @@ import messages from './messages';
2727
import { useModel } from '../../../generic/model-store';
2828
import { requestCert } from '../../../course-home/data/thunks';
2929
import ProgramCompletion from './ProgramCompletion';
30-
import DashboardFootnote from './DashboardFootnote';
3130
import UpgradeFootnote from './UpgradeFootnote';
3231
import SocialIcons from '../../social-share/SocialIcons';
3332
import { logClick, logVisit } from './utils';
3433
import { DashboardLink, IdVerificationSupportLink, ProfileLink } from '../../../shared/links';
3534
import CourseRecommendationsSlot from '../../../plugin-slots/CourseExitPluginSlots/CourseRecommendationsSlot';
35+
import DashboardFootnotePluginSlot from '../../../plugin-slots/CourseExitPluginSlots/DashboardFootnotePluginSlot';
3636

3737
const LINKEDIN_BLUE = '#2867B2';
3838

@@ -119,7 +119,7 @@ const CourseCelebration = ({ intl }) => {
119119
}
120120
buttonEvent = 'view_cert';
121121
visitEvent = 'celebration_with_cert';
122-
footnote = <DashboardFootnote variant={visitEvent} />;
122+
footnote = <DashboardFootnotePluginSlot variant={visitEvent} />;
123123
break;
124124
case 'earned_but_not_available': {
125125
const endDate = <FormattedDate value={end} day="numeric" month="long" year="numeric" />;
@@ -142,7 +142,7 @@ const CourseCelebration = ({ intl }) => {
142142
</>
143143
);
144144
visitEvent = 'celebration_with_unavailable_cert';
145-
footnote = <DashboardFootnote variant={visitEvent} />;
145+
footnote = <DashboardFootnotePluginSlot variant={visitEvent} />;
146146
break;
147147
}
148148
case 'requesting':
@@ -163,12 +163,12 @@ const CourseCelebration = ({ intl }) => {
163163
certHeader = intl.formatMessage(messages.certificateHeaderRequestable);
164164
message = (<p>{intl.formatMessage(messages.requestCertificateBodyText)}</p>);
165165
visitEvent = 'celebration_with_requestable_cert';
166-
footnote = <DashboardFootnote variant={visitEvent} />;
166+
footnote = <DashboardFootnotePluginSlot variant={visitEvent} />;
167167
break;
168168
case 'unverified':
169169
certHeader = intl.formatMessage(messages.certificateHeaderUnverified);
170170
visitEvent = 'celebration_unverified';
171-
footnote = <DashboardFootnote variant={visitEvent} />;
171+
footnote = <DashboardFootnotePluginSlot variant={visitEvent} />;
172172
if (verificationStatus === 'pending') {
173173
message = (<p>{intl.formatMessage(messages.verificationPending)}</p>);
174174
} else {
@@ -240,7 +240,7 @@ const CourseCelebration = ({ intl }) => {
240240
if (verifiedMode.accessExpirationDate) {
241241
footnote = <UpgradeFootnote deadline={verifiedMode.accessExpirationDate} href={verifiedMode.upgradeUrl} />;
242242
} else {
243-
footnote = <DashboardFootnote variant={visitEvent} />;
243+
footnote = <DashboardFootnotePluginSlot variant={visitEvent} />;
244244
}
245245
} else {
246246
visitEvent = 'celebration_audit_no_upgrade';

src/courseware/course/course-exit/CourseInProgress.jsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { getConfig } from '@edx/frontend-platform';
1010
import { useModel } from '../../../generic/model-store';
1111

1212
import CatalogSuggestion from './CatalogSuggestion';
13-
import DashboardFootnote from './DashboardFootnote';
13+
import DashboardFootnotePluginSlot from '../../../plugin-slots/CourseExitPluginSlots/DashboardFootnotePluginSlot';
1414
import messages from './messages';
1515
import { logClick, logVisit } from './utils';
1616

@@ -53,7 +53,7 @@ const CourseInProgress = ({ intl }) => {
5353
)}
5454
</div>
5555
</Alert>
56-
<DashboardFootnote variant="in_progress" />
56+
<DashboardFootnotePluginSlot variant="in_progress" />
5757
<CatalogSuggestion variant="in_progress" />
5858
</div>
5959
</>

src/courseware/course/course-exit/CourseNonPassing.jsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { getConfig } from '@edx/frontend-platform';
1010
import { useModel } from '../../../generic/model-store';
1111

1212
import CatalogSuggestion from './CatalogSuggestion';
13-
import DashboardFootnote from './DashboardFootnote';
13+
import DashboardFootnotePluginSlot from '../../../plugin-slots/CourseExitPluginSlots/DashboardFootnotePluginSlot';
1414
import messages from './messages';
1515
import { logClick, logVisit } from './utils';
1616

@@ -53,7 +53,7 @@ const CourseNonPassing = ({ intl }) => {
5353
)}
5454
</div>
5555
</Alert>
56-
<DashboardFootnote variant="nonpassing" />
56+
<DashboardFootnotePluginSlot variant="nonpassing" />
5757
<CatalogSuggestion variant="nonpassing" />
5858
</div>
5959
</>
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,27 @@
1-
import React from 'react';
21
import PropTypes from 'prop-types';
32
import { useSelector } from 'react-redux';
4-
3+
import { getConfig } from '@edx/frontend-platform';
54
import { getAuthenticatedUser } from '@edx/frontend-platform/auth';
6-
import {
7-
FormattedMessage, injectIntl, intlShape,
8-
} from '@edx/frontend-platform/i18n';
5+
import { useIntl } from '@edx/frontend-platform/i18n';
96
import { Hyperlink } from '@openedx/paragon';
107
import { faCalendarAlt } from '@fortawesome/free-regular-svg-icons';
11-
import { getConfig } from '@edx/frontend-platform';
128

139
import { useModel } from '../../../generic/model-store';
1410

1511
import Footnote from './Footnote';
1612
import messages from './messages';
1713
import { logClick } from './utils';
1814

19-
const DashboardFootnote = ({ intl, variant }) => {
15+
const DashboardFootnote = ({ variant, content }) => {
16+
const intl = useIntl();
2017
const { courseId } = useSelector(state => state.courseware);
2118
const { org } = useModel('courseHomeMeta', courseId);
2219
const { administrator } = getAuthenticatedUser();
2320

2421
const dashboardLink = (
2522
<Hyperlink
2623
style={{ textDecoration: 'underline' }}
27-
destination={`${getConfig().LMS_BASE_URL}/dashboard`}
24+
destination={content?.dashboardFootnoteUrl || `${getConfig().LMS_BASE_URL}/dashboard`}
2825
className="text-reset"
2926
onClick={() => logClick(org, courseId, administrator, 'dashboard_footnote', { variant })}
3027
>
@@ -35,21 +32,16 @@ const DashboardFootnote = ({ intl, variant }) => {
3532
return (
3633
<Footnote
3734
icon={faCalendarAlt}
38-
text={(
39-
<FormattedMessage
40-
id="courseCelebration.dashboardInfo" // for historical reasons
41-
defaultMessage="You can access this course and its materials on your {dashboardLink}."
42-
description="Text that precedes link to learner's dashboard"
43-
values={{ dashboardLink }}
44-
/>
45-
)}
35+
text={intl.formatMessage(messages.dashboardInfo, { dashboardLink })}
4636
/>
4737
);
4838
};
4939

5040
DashboardFootnote.propTypes = {
51-
intl: intlShape.isRequired,
41+
content: PropTypes.shape({
42+
dashboardFootnoteUrl: PropTypes.string,
43+
}),
5244
variant: PropTypes.string.isRequired,
5345
};
5446

55-
export default injectIntl(DashboardFootnote);
47+
export default DashboardFootnote;

src/courseware/course/course-exit/messages.ts

+5
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ const messages = defineMessages({
7676
defaultMessage: 'Dashboard',
7777
description: 'Link to user’s dashboard',
7878
},
79+
dashboardInfo: {
80+
id: 'courseCelebration.dashboardInfo', // for historical reasons
81+
defaultMessage: 'You can access this course and its materials on your {dashboardLink}.',
82+
description: "Text that precedes link to learner's dashboard",
83+
},
7984
endOfCourseDescription: {
8085
id: 'courseExit.endOfCourseDescription',
8186
defaultMessage: 'Unfortunately, you are not currently eligible for a certificate. You need to receive a passing grade to be eligible for a certificate.',
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Course Exit Dashboard Footnote Plugin Slot
2+
3+
### Slot ID: `course_exit_dashboard_footnote_slot`
4+
### Props:
5+
* `variant`
6+
7+
## Description
8+
9+
This slot is used for modifying the footnote on the course exit page that links to the learner dashboard
10+
11+
## Example
12+
13+
The following `env.config.jsx` will change the link to point to `example.com`
14+
15+
![Screenshot of modified course celebration](./screenshot_custom.png)
16+
17+
```js
18+
import { DIRECT_PLUGIN, PLUGIN_OPERATIONS } from '@openedx/frontend-plugin-framework';
19+
20+
const config = {
21+
pluginSlots: {
22+
course_exit_dashboard_footnote_slot: {
23+
keepDefault: true,
24+
plugins: [
25+
{
26+
op: PLUGIN_OPERATIONS.Modify,
27+
widgetId: 'default_contents',
28+
fn: (widget) => {
29+
widget.content.dashboardFootnoteUrl = 'http://www.example.com';
30+
return widget;
31+
}
32+
},
33+
]
34+
},
35+
},
36+
}
37+
38+
export default config;
39+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import PropTypes from 'prop-types';
2+
import { getConfig } from '@edx/frontend-platform';
3+
import { PluginSlot } from '@openedx/frontend-plugin-framework';
4+
import DashboardFootnote from '../../../courseware/course/course-exit/DashboardFootnote';
5+
6+
const DashboardFootnotePluginSlot = ({ variant }) => {
7+
const dashboardFootnoteUrl = `${getConfig().LMS_BASE_URL}/dashboard`;
8+
return (
9+
<PluginSlot id="course_exit_dashboard_footnote_slot">
10+
<DashboardFootnote
11+
variant={variant}
12+
content={{ dashboardFootnoteUrl }}
13+
/>
14+
</PluginSlot>
15+
);
16+
};
17+
18+
DashboardFootnotePluginSlot.propTypes = {
19+
variant: PropTypes.string.isRequired,
20+
};
21+
export default DashboardFootnotePluginSlot;

0 commit comments

Comments
 (0)