diff --git a/src/assets/ContentUnavailable.jsx b/src/assets/ContentUnavailable.jsx new file mode 100644 index 00000000..4d86837a --- /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 172bcd83..811cdbf3 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 142ec4b2..154b5cdb 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 17e43641..1d27c0c9 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 621a52b3..d9ffad4d 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 00000000..db636dbb --- /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)}
+ +