From f715fd5ed6cdb051a39f540ceff072f2cc88230c Mon Sep 17 00:00:00 2001 From: Nick Date: Thu, 23 Jul 2020 12:28:56 -0400 Subject: [PATCH] AA-123 welcome message (#121) --- .../data/__snapshots__/redux.test.js.snap | 1 + src/course-home/data/api.js | 7 ++ src/course-home/data/redux.test.js | 12 ++++ src/course-home/data/thunks.js | 5 ++ src/course-home/outline-tab/OutlineTab.jsx | 2 + src/course-home/outline-tab/messages.js | 12 ++++ .../outline-tab/widgets/WelcomeMessage.jsx | 68 +++++++++++++++++++ src/generic/user-messages/Alert.jsx | 20 ++++-- src/generic/user-messages/Alert.scss | 4 ++ .../user-messages/UserMessagesProvider.jsx | 1 + 10 files changed, 128 insertions(+), 4 deletions(-) create mode 100644 src/course-home/outline-tab/widgets/WelcomeMessage.jsx create mode 100644 src/generic/user-messages/Alert.scss diff --git a/src/course-home/data/__snapshots__/redux.test.js.snap b/src/course-home/data/__snapshots__/redux.test.js.snap index 9dad7db4..b0baead2 100644 --- a/src/course-home/data/__snapshots__/redux.test.js.snap +++ b/src/course-home/data/__snapshots__/redux.test.js.snap @@ -199,6 +199,7 @@ Object { "datesWidget": undefined, "handoutsHtml": "", "id": "course-v1:edX+DemoX+Demo_Course_1", + "welcomeMessageHtml": undefined, }, }, }, diff --git a/src/course-home/data/api.js b/src/course-home/data/api.js index c1310535..8c15eb1c 100644 --- a/src/course-home/data/api.js +++ b/src/course-home/data/api.js @@ -72,12 +72,14 @@ export async function getOutlineTabData(courseId) { const courseTools = camelCaseObject(data.course_tools); const datesWidget = camelCaseObject(data.dates_widget); const handoutsHtml = data.handouts_html; + const welcomeMessageHtml = data.welcome_message_html; return { courseTools, courseBlocks, datesWidget, handoutsHtml, + welcomeMessageHtml, }; } @@ -85,3 +87,8 @@ export async function postCourseDeadlines(courseId) { const url = new URL(`${getConfig().LMS_BASE_URL}/api/course_experience/v1/reset_course_deadlines`); await getAuthenticatedHttpClient().post(url.href, { course_key: courseId }); } + +export async function postDismissWelcomeMessage(courseId) { + const url = new URL(`${getConfig().LMS_BASE_URL}/api/course_home/v1/dismiss_welcome_message`); + await getAuthenticatedHttpClient().post(url.href, { course_id: courseId }); +} diff --git a/src/course-home/data/redux.test.js b/src/course-home/data/redux.test.js index db87abf6..ad226a6e 100644 --- a/src/course-home/data/redux.test.js +++ b/src/course-home/data/redux.test.js @@ -125,4 +125,16 @@ describe('Data layer integration tests', () => { expect(getTabDataMock).toHaveBeenCalledWith(courseId); }); }); + + describe('Test dismissWelcomeMessage', () => { + it('Should dismiss welcome message', async () => { + const dismissUrl = `${getConfig().LMS_BASE_URL}/api/course_home/v1/dismiss_welcome_message`; + axiosMock.onPost(dismissUrl).reply(201); + + await executeThunk(thunks.dismissWelcomeMessage(courseId), store.dispatch); + + expect(axiosMock.history.post[0].url).toEqual(dismissUrl); + expect(axiosMock.history.post[0].data).toEqual(`{"course_id":"${courseId}"}`); + }); + }); }); diff --git a/src/course-home/data/thunks.js b/src/course-home/data/thunks.js index 335289df..0caf530a 100644 --- a/src/course-home/data/thunks.js +++ b/src/course-home/data/thunks.js @@ -5,6 +5,7 @@ import { getOutlineTabData, getProgressTabData, postCourseDeadlines, + postDismissWelcomeMessage, } from './api'; import { @@ -79,3 +80,7 @@ export function resetDeadlines(courseId, getTabData) { }); }; } + +export function dismissWelcomeMessage(courseId) { + return async () => postDismissWelcomeMessage(courseId); +} diff --git a/src/course-home/outline-tab/OutlineTab.jsx b/src/course-home/outline-tab/OutlineTab.jsx index 20d03e54..1bb23767 100644 --- a/src/course-home/outline-tab/OutlineTab.jsx +++ b/src/course-home/outline-tab/OutlineTab.jsx @@ -11,6 +11,7 @@ import CourseTools from './widgets/CourseTools'; import messages from './messages'; import Section from './Section'; import { useModel } from '../../generic/model-store'; +import WelcomeMessage from './widgets/WelcomeMessage'; // Note that we import from the component files themselves in the enrollment-alert package. // This is because React.lazy() requires that we import() from a file with a Component as its @@ -61,6 +62,7 @@ function OutlineTab({ intl }) {
+ {sectionIds.map((sectionId) => (
200 && `${welcomeMessageHtml.substring(0, 199)}...`; + const [showShortMessage, setShowShortMessage] = useState(!!shortWelcomeMessageHtml); + const dispatch = useDispatch(); + + return ( + display && ( + { + setDisplay(false); + dispatch(dismissWelcomeMessage(courseId)); + }} + > +
+ +
+ { + shortWelcomeMessageHtml && ( +
+ +
+ ) + } +
+ ) + ); +} + +WelcomeMessage.propTypes = { + courseId: PropTypes.string.isRequired, + intl: intlShape.isRequired, +}; + +export default injectIntl(WelcomeMessage); diff --git a/src/generic/user-messages/Alert.jsx b/src/generic/user-messages/Alert.jsx index 2dea7c7e..fa5fe336 100644 --- a/src/generic/user-messages/Alert.jsx +++ b/src/generic/user-messages/Alert.jsx @@ -8,6 +8,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Button } from '@edx/paragon'; import { ALERT_TYPES } from './UserMessagesProvider'; +import './Alert.scss'; function getAlertClass(type) { if (type === ALERT_TYPES.ERROR) { @@ -19,6 +20,9 @@ function getAlertClass(type) { if (type === ALERT_TYPES.SUCCESS) { return 'alert-success'; } + if (type === ALERT_TYPES.WELCOME) { + return 'alert-welcome alert-light'; + } return 'alert-info'; } @@ -41,9 +45,11 @@ function Alert({ return (
-
- -
+ {type !== ALERT_TYPES.WELCOME && ( +
+ +
+ )}
{children}
@@ -54,7 +60,13 @@ function Alert({ } Alert.propTypes = { - type: PropTypes.oneOf([ALERT_TYPES.ERROR, ALERT_TYPES.DANGER, ALERT_TYPES.INFO, ALERT_TYPES.SUCCESS]).isRequired, + type: PropTypes.oneOf([ + ALERT_TYPES.ERROR, + ALERT_TYPES.DANGER, + ALERT_TYPES.INFO, + ALERT_TYPES.SUCCESS, + ALERT_TYPES.WELCOME, + ]).isRequired, dismissible: PropTypes.bool, children: PropTypes.node, onDismiss: PropTypes.func, diff --git a/src/generic/user-messages/Alert.scss b/src/generic/user-messages/Alert.scss new file mode 100644 index 00000000..8808693e --- /dev/null +++ b/src/generic/user-messages/Alert.scss @@ -0,0 +1,4 @@ +.alert-welcome { + border: #b9babe solid 1px !important; + border-left: #000000 solid 3px !important; +} diff --git a/src/generic/user-messages/UserMessagesProvider.jsx b/src/generic/user-messages/UserMessagesProvider.jsx index f51b8663..c504d31f 100644 --- a/src/generic/user-messages/UserMessagesProvider.jsx +++ b/src/generic/user-messages/UserMessagesProvider.jsx @@ -9,6 +9,7 @@ export const ALERT_TYPES = { DANGER: 'danger', SUCCESS: 'success', INFO: 'info', + WELCOME: 'welcome', }; const FLASH_MESSAGES_LOCAL_STORAGE_KEY = 'UserMessagesProvider.flashMessages';