From ac17fd72943972590b3126b004c51c4bae8480f2 Mon Sep 17 00:00:00 2001 From: sundasnoreen12 <72802712+sundasnoreen12@users.noreply.github.com> Date: Wed, 21 Feb 2024 14:37:37 +0500 Subject: [PATCH] feat: implemented error handling mockup (#663) * feat: implemented error handling mockup * fix: fixed incontextsidebar issues * fix: fixed discussion home test cases * fix: fixed dicussion home test cases * refactor: added code review fixes --------- Co-authored-by: Awais Ansari <79941147+awais-ansari@users.noreply.github.com> --- src/assets/ContentUnavailable.jsx | 14 ++ .../__factories__/navigationBar.factory.js | 2 +- src/components/NavigationBar/data/api.test.js | 4 +- src/components/NavigationBar/data/slice.js | 1 + src/components/NavigationBar/data/thunks.js | 1 + .../CourseContentUnavailable.jsx | 52 ++++++++ .../discussions-home/DiscussionsHome.jsx | 123 +++++++++++------- .../discussions-home/DiscussionsHome.test.jsx | 65 +++++++-- src/discussions/messages.js | 15 +++ src/index.scss | 4 + 10 files changed, 218 insertions(+), 63 deletions(-) create mode 100644 src/assets/ContentUnavailable.jsx create mode 100644 src/discussions/course-content-unavailable/CourseContentUnavailable.jsx diff --git a/src/assets/ContentUnavailable.jsx b/src/assets/ContentUnavailable.jsx new file mode 100644 index 000000000..4d86837a6 --- /dev/null +++ b/src/assets/ContentUnavailable.jsx @@ -0,0 +1,14 @@ +const ContentUnavailable = () => ( + +); + +export default ContentUnavailable; diff --git a/src/components/NavigationBar/data/__factories__/navigationBar.factory.js b/src/components/NavigationBar/data/__factories__/navigationBar.factory.js index 172bcd832..811cdbf38 100644 --- a/src/components/NavigationBar/data/__factories__/navigationBar.factory.js +++ b/src/components/NavigationBar/data/__factories__/navigationBar.factory.js @@ -19,7 +19,7 @@ Factory.define('navigationBar') user_message: null, })) .option('course_id', null, 'course-v1:edX+DemoX+Demo_Course') - .attr('is_enrolled', null, false) + .sequence('is_enrolled', ['isEnrolled'], (idx, isEnrolled) => isEnrolled) .attr('is_self_paced', null, false) .attr('is_staff', null, true) .attr('number', null, 'DemoX') diff --git a/src/components/NavigationBar/data/api.test.js b/src/components/NavigationBar/data/api.test.js index 142ec4b2d..154b5cdb2 100644 --- a/src/components/NavigationBar/data/api.test.js +++ b/src/components/NavigationBar/data/api.test.js @@ -34,7 +34,7 @@ describe('Navigation bar api tests', () => { }); it('Successfully get navigation tabs', async () => { - axiosMock.onGet(`${getCourseMetadataApiUrl(courseId)}`).reply(200, (Factory.build('navigationBar', 1))); + axiosMock.onGet(`${getCourseMetadataApiUrl(courseId)}`).reply(200, (Factory.build('navigationBar', 1, { isEnrolled: true }))); await executeThunk(fetchTab(courseId, 'outline'), store.dispatch, store.getState); expect(store.getState().courseTabs.tabs).toHaveLength(4); @@ -58,7 +58,7 @@ describe('Navigation bar api tests', () => { it('Denied to get navigation bar when user has no access on course', async () => { axiosMock.onGet(`${getCourseMetadataApiUrl(courseId)}`).reply( 200, - (Factory.build('navigationBar', 1, { hasCourseAccess: false })), + (Factory.build('navigationBar', 1, { hasCourseAccess: false, isEnrolled: true })), ); await executeThunk(fetchTab(courseId, 'outline'), store.dispatch, store.getState); diff --git a/src/components/NavigationBar/data/slice.js b/src/components/NavigationBar/data/slice.js index 17e43641f..1d27c0c9b 100644 --- a/src/components/NavigationBar/data/slice.js +++ b/src/components/NavigationBar/data/slice.js @@ -47,6 +47,7 @@ const slice = createSlice({ courseTitle: payload.courseTitle, courseNumber: payload.courseNumber, org: payload.org, + isEnrolled: payload.isEnrolled, } ), }, diff --git a/src/components/NavigationBar/data/thunks.js b/src/components/NavigationBar/data/thunks.js index 621a52b34..d9ffad4d2 100644 --- a/src/components/NavigationBar/data/thunks.js +++ b/src/components/NavigationBar/data/thunks.js @@ -23,6 +23,7 @@ export default function fetchTab(courseId, rootSlug) { org: courseHomeCourseMetadata.org, courseNumber: courseHomeCourseMetadata.number, courseTitle: courseHomeCourseMetadata.title, + isEnrolled: courseHomeCourseMetadata.isEnrolled, })); } } catch (e) { diff --git a/src/discussions/course-content-unavailable/CourseContentUnavailable.jsx b/src/discussions/course-content-unavailable/CourseContentUnavailable.jsx new file mode 100644 index 000000000..db636dbbd --- /dev/null +++ b/src/discussions/course-content-unavailable/CourseContentUnavailable.jsx @@ -0,0 +1,52 @@ +import React, { useCallback } from 'react'; +import propTypes from 'prop-types'; + +import classNames from 'classnames'; +import { useSelector } from 'react-redux'; + +import { getConfig } from '@edx/frontend-platform'; +import { useIntl } from '@edx/frontend-platform/i18n'; +import { Button } from '@edx/paragon'; + +import ContentUnavailableIcon from '../../assets/ContentUnavailable'; +import selectCourseTabs from '../../components/NavigationBar/data/selectors'; +import { useIsOnDesktop, useIsOnXLDesktop } from '../data/hooks'; +import messages from '../messages'; + +const CourseContentUnavailable = ({ subTitleMessage }) => { + const intl = useIntl(); + const isOnDesktop = useIsOnDesktop(); + const isOnXLDesktop = useIsOnXLDesktop(); + const { courseId } = useSelector(selectCourseTabs); + + const redirectToDashboard = useCallback(() => { + window.location.replace(`${getConfig().LMS_BASE_URL}/courses/${courseId}/about`); + }, [courseId]); + + return ( +
{intl.formatMessage(subTitleMessage)}
+ +