From d67f46865b1865512faf7c62ae2d598dfef428bf Mon Sep 17 00:00:00 2001 From: Michael Terry Date: Tue, 4 Aug 2020 14:09:01 -0400 Subject: [PATCH] AA-279: Add course expired alert to outline It was previously only used in the courseware. But to match the LMS, we also want to show it on the outline tab. --- .../AccessExpirationAlert.jsx | 5 +++-- src/alerts/access-expiration-alert/hooks.js | 17 ++++++++++------- src/alerts/access-expiration-alert/index.js | 3 +-- src/course-home/data/api.js | 4 +++- src/course-home/outline-tab/OutlineTab.jsx | 4 ++++ src/courseware/course/Course.jsx | 13 ++++--------- 6 files changed, 25 insertions(+), 21 deletions(-) diff --git a/src/alerts/access-expiration-alert/AccessExpirationAlert.jsx b/src/alerts/access-expiration-alert/AccessExpirationAlert.jsx index bab938de..35aecec4 100644 --- a/src/alerts/access-expiration-alert/AccessExpirationAlert.jsx +++ b/src/alerts/access-expiration-alert/AccessExpirationAlert.jsx @@ -1,14 +1,15 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { Alert } from '../../generic/user-messages'; +import { Alert, ALERT_TYPES } from '../../generic/user-messages'; function AccessExpirationAlert({ payload }) { const { rawHtml, } = payload; return rawHtml && ( - + + {/* eslint-disable-next-line react/no-danger */}
); diff --git a/src/alerts/access-expiration-alert/hooks.js b/src/alerts/access-expiration-alert/hooks.js index 58d05414..c60c159d 100644 --- a/src/alerts/access-expiration-alert/hooks.js +++ b/src/alerts/access-expiration-alert/hooks.js @@ -1,18 +1,21 @@ -/* eslint-disable import/prefer-default-export */ -import { useMemo } from 'react'; -import { useModel } from '../../generic/model-store'; +import React, { useMemo } from 'react'; import { useAlert } from '../../generic/user-messages'; -export function useAccessExpirationAlert(courseId) { - const course = useModel('courses', courseId); - const rawHtml = (course && course.courseExpiredMessage) || null; +const AccessExpirationAlert = React.lazy(() => import('./AccessExpirationAlert')); + +function useAccessExpirationAlert(courseExpiredMessage, topic) { + const rawHtml = courseExpiredMessage || null; const isVisible = !!rawHtml; // If it exists, show it. const payload = useMemo(() => ({ rawHtml }), [rawHtml]); useAlert(isVisible, { code: 'clientAccessExpirationAlert', - topic: 'course', payload, + topic, }); + + return { clientAccessExpirationAlert: AccessExpirationAlert }; } + +export default useAccessExpirationAlert; diff --git a/src/alerts/access-expiration-alert/index.js b/src/alerts/access-expiration-alert/index.js index d8b07c2f..ed12eb0b 100644 --- a/src/alerts/access-expiration-alert/index.js +++ b/src/alerts/access-expiration-alert/index.js @@ -1,2 +1 @@ -export { default as AccessExpirationAlert } from './AccessExpirationAlert'; -export { useAccessExpirationAlert } from './hooks'; +export { default } from './hooks'; diff --git a/src/course-home/data/api.js b/src/course-home/data/api.js index 6ab7dcd4..9cd69ae5 100644 --- a/src/course-home/data/api.js +++ b/src/course-home/data/api.js @@ -69,6 +69,7 @@ export async function getOutlineTabData(courseId) { data, } = tabData; const courseBlocks = normalizeBlocks(courseId, data.course_blocks.blocks); + const courseExpiredHtml = data.course_expired_html; const courseTools = camelCaseObject(data.course_tools); const datesWidget = camelCaseObject(data.dates_widget); const enrollAlert = camelCaseObject(data.enroll_alert); @@ -77,8 +78,9 @@ export async function getOutlineTabData(courseId) { const welcomeMessageHtml = data.welcome_message_html; return { - courseTools, courseBlocks, + courseExpiredHtml, + courseTools, datesWidget, enrollAlert, handoutsHtml, diff --git a/src/course-home/outline-tab/OutlineTab.jsx b/src/course-home/outline-tab/OutlineTab.jsx index 261aa5cb..25a81364 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 useAccessExpirationAlert from '../../alerts/access-expiration-alert'; import useCertificateAvailableAlert from './alerts/certificate-available-alert'; import useCourseEndAlert from './alerts/course-end-alert'; import useCourseStartAlert from './alerts/course-start-alert'; @@ -39,6 +40,7 @@ function OutlineTab({ intl }) { courses, sections, }, + courseExpiredHtml, offerHtml, } = useModel('outline', courseId); @@ -48,6 +50,7 @@ function OutlineTab({ intl }) { // Below the course title alerts (appearing in the order listed here) const offerAlert = useOfferAlert(offerHtml, 'outline-course-alerts'); + const accessExpirationAlert = useAccessExpirationAlert(courseExpiredHtml, 'outline-course-alerts'); const courseStartAlert = useCourseStartAlert(courseId); const courseEndAlert = useCourseEndAlert(courseId); const certificateAvailableAlert = useCertificateAvailableAlert(courseId); @@ -76,6 +79,7 @@ function OutlineTab({ intl }) { topic="outline-course-alerts" className="mb-3" customAlerts={{ + ...accessExpirationAlert, ...certificateAvailableAlert, ...courseEndAlert, ...courseStartAlert, diff --git a/src/courseware/course/Course.jsx b/src/courseware/course/Course.jsx index fac3ed4f..5c180928 100644 --- a/src/courseware/course/Course.jsx +++ b/src/courseware/course/Course.jsx @@ -5,7 +5,7 @@ import { useDispatch } from 'react-redux'; import { getConfig } from '@edx/frontend-platform'; import { AlertList } from '../../generic/user-messages'; -import { useAccessExpirationAlert } from '../../alerts/access-expiration-alert'; +import useAccessExpirationAlert from '../../alerts/access-expiration-alert'; import useOfferAlert from '../../alerts/offer-alert'; import Sequence from './sequence'; @@ -16,12 +16,6 @@ import CourseSock from './course-sock'; import ContentTools from './content-tools'; import { useModel } from '../../generic/model-store'; -// Note that we import from the component files themselves in the enrollment-alert package. -// This is because Reacy.lazy() requires that we import() from a file with a Component as it's -// default export. -// See React.lazy docs here: https://reactjs.org/docs/code-splitting.html#reactlazy -const AccessExpirationAlert = React.lazy(() => import('../../alerts/access-expiration-alert/AccessExpirationAlert')); - function Course({ courseId, sequenceId, @@ -43,13 +37,14 @@ function Course({ const { canShowUpgradeSock, celebrations, + courseExpiredMessage, offerHtml, verifiedMode, } = course; // Below the tabs, above the breadcrumbs alerts (appearing in the order listed here) const offerAlert = useOfferAlert(offerHtml, 'course'); - useAccessExpirationAlert(courseId); + const accessExpirationAlert = useAccessExpirationAlert(courseExpiredMessage, 'course'); const dispatch = useDispatch(); const celebrateFirstSection = celebrations && celebrations.firstSection; @@ -64,7 +59,7 @@ function Course({ className="my-3" topic="course" customAlerts={{ - clientAccessExpirationAlert: AccessExpirationAlert, + ...accessExpirationAlert, ...offerAlert, }} />