From e17b66851eaa262ee50e0613aaffcc201f735845 Mon Sep 17 00:00:00 2001 From: Michael Terry Date: Mon, 3 Aug 2020 13:04:47 -0400 Subject: [PATCH] AA-277: Add certificate available alert on outline (#144) --- .../CertificateAvailableAlert.jsx | 62 +++++++++++++++++++ .../certificate-available-alert/hooks.js | 42 +++++++++++++ .../certificate-available-alert/index.js | 1 + src/course-home/outline-tab/OutlineTab.jsx | 3 + 4 files changed, 108 insertions(+) create mode 100644 src/alerts/certificate-available-alert/CertificateAvailableAlert.jsx create mode 100644 src/alerts/certificate-available-alert/hooks.js create mode 100644 src/alerts/certificate-available-alert/index.js diff --git a/src/alerts/certificate-available-alert/CertificateAvailableAlert.jsx b/src/alerts/certificate-available-alert/CertificateAvailableAlert.jsx new file mode 100644 index 00000000..eac8d04a --- /dev/null +++ b/src/alerts/certificate-available-alert/CertificateAvailableAlert.jsx @@ -0,0 +1,62 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { getConfig } from '@edx/frontend-platform'; +import { FormattedMessage, FormattedRelative } from '@edx/frontend-platform/i18n'; +import { Hyperlink } from '@edx/paragon'; + +import { Alert, ALERT_TYPES } from '../../generic/user-messages'; + +function CertificateAvailableAlert({ payload }) { + const { + certDate, + username, + userTimezone, + } = payload; + + const timezoneFormatArgs = userTimezone ? { timeZone: userTimezone } : {}; + + return ( + + + + +
+ + + + ), + timeRemaining: ( + + ), + }} + /> +
+ ); +} + +CertificateAvailableAlert.propTypes = { + payload: PropTypes.shape({ + certDate: PropTypes.string, + username: PropTypes.string, + userTimezone: PropTypes.string, + }).isRequired, +}; + +export default CertificateAvailableAlert; diff --git a/src/alerts/certificate-available-alert/hooks.js b/src/alerts/certificate-available-alert/hooks.js new file mode 100644 index 00000000..f8bf2e18 --- /dev/null +++ b/src/alerts/certificate-available-alert/hooks.js @@ -0,0 +1,42 @@ +import React from 'react'; +import { getAuthenticatedUser } from '@edx/frontend-platform/auth'; + +import { useAlert } from '../../generic/user-messages'; +import { useModel } from '../../generic/model-store'; + +const CertificateAvailableAlert = React.lazy(() => import('./CertificateAvailableAlert')); + +function useCertificateAvailableAlert(courseId) { + const { + isEnrolled, + } = useModel('courses', courseId); + const { + datesWidget: { + courseDateBlocks, + userTimezone, + }, + } = useModel('outline', courseId); + const { username } = getAuthenticatedUser(); + + const certBlock = courseDateBlocks.find(b => b.dateType === 'certificate-available-date'); + const endBlock = courseDateBlocks.find(b => b.dateType === 'course-end-date'); + const endDate = endBlock ? new Date(endBlock.date) : null; + const hasEnded = endBlock ? endDate < new Date() : false; + const isVisible = isEnrolled && certBlock && hasEnded; // only show if we're between end and cert dates + + useAlert(isVisible, { + code: 'clientCertificateAvailableAlert', + payload: { + certDate: certBlock && certBlock.date, + username, + userTimezone, + }, + topic: 'outline-course-alerts', + }); + + return { + clientCertificateAvailableAlert: CertificateAvailableAlert, + }; +} + +export default useCertificateAvailableAlert; diff --git a/src/alerts/certificate-available-alert/index.js b/src/alerts/certificate-available-alert/index.js new file mode 100644 index 00000000..ed12eb0b --- /dev/null +++ b/src/alerts/certificate-available-alert/index.js @@ -0,0 +1 @@ +export { default } from './hooks'; diff --git a/src/course-home/outline-tab/OutlineTab.jsx b/src/course-home/outline-tab/OutlineTab.jsx index af250a52..02a2e2ca 100644 --- a/src/course-home/outline-tab/OutlineTab.jsx +++ b/src/course-home/outline-tab/OutlineTab.jsx @@ -10,6 +10,7 @@ import CourseHandouts from './widgets/CourseHandouts'; import CourseTools from './widgets/CourseTools'; import messages from './messages'; import Section from './Section'; +import useCertificateAvailableAlert from '../../alerts/certificate-available-alert'; import useCourseEndAlert from '../../alerts/course-end-alert'; import useEnrollmentAlert from '../../alerts/enrollment-alert'; import useLogistrationAlert from '../../alerts/logistration-alert'; @@ -38,6 +39,7 @@ function OutlineTab({ intl }) { }, } = useModel('outline', courseId); + const certificateAvailableAlert = useCertificateAvailableAlert(courseId); const courseEndAlert = useCourseEndAlert(courseId); const enrollmentAlert = useEnrollmentAlert(courseId); const logistrationAlert = useLogistrationAlert(); @@ -66,6 +68,7 @@ function OutlineTab({ intl }) { topic="outline-course-alerts" className="mb-3" customAlerts={{ + ...certificateAvailableAlert, ...courseEndAlert, }} />