From bca3aaccf51bcc5e16ecb1966a833554f6ccd2e6 Mon Sep 17 00:00:00 2001 From: Maria Grimaldi Date: Fri, 8 Mar 2024 09:51:31 -0400 Subject: [PATCH] feat: use navigation sequence metadata to disable navigation components (#1273) Use navigation_disabled sequence metadata based on Hide From TOC block field, so the student cannot navigate to another sequences in the course outline. https://openedx.atlassian.net/wiki/spaces/OEPM/pages/3853975595/Feature+Enhancement+Proposal+Hide+Sections+from+course+outline --- .../data/__snapshots__/redux.test.js.snap | 1 + src/course-home/data/api.js | 1 + src/courseware/course/Course.jsx | 19 +++++--- src/courseware/course/Course.test.jsx | 21 ++++++++ .../SequenceNavigation.jsx | 12 +++-- .../SequenceNavigation.test.jsx | 48 +++++++++++++++++++ .../sequence/sequence-navigation/hooks.js | 17 ++++++- src/courseware/data/api.js | 1 + 8 files changed, 107 insertions(+), 13 deletions(-) diff --git a/src/course-home/data/__snapshots__/redux.test.js.snap b/src/course-home/data/__snapshots__/redux.test.js.snap index 9df06d19e6..a08587b0d1 100644 --- a/src/course-home/data/__snapshots__/redux.test.js.snap +++ b/src/course-home/data/__snapshots__/redux.test.js.snap @@ -518,6 +518,7 @@ Object { "hideFromTOC": undefined, "icon": null, "id": "block-v1:edX+DemoX+Demo_Course+type@sequential+block@bcdabcdabcdabcdabcdabcdabcdabcd1", + "navigationDisabled": undefined, "sectionId": "block-v1:edX+DemoX+Demo_Course+type@chapter+block@bcdabcdabcdabcdabcdabcdabcdabcd2", "showLink": true, "title": "Title of Sequence", diff --git a/src/course-home/data/api.js b/src/course-home/data/api.js index 7ce2525ffe..f963f715c8 100644 --- a/src/course-home/data/api.js +++ b/src/course-home/data/api.js @@ -154,6 +154,7 @@ export function normalizeOutlineBlocks(courseId, blocks) { showLink: !!block.lms_web_url, title: block.display_name, hideFromTOC: block.hide_from_toc, + navigationDisabled: block.navigation_disabled, }; break; diff --git a/src/courseware/course/Course.jsx b/src/courseware/course/Course.jsx index a00a45b333..74fc267b62 100644 --- a/src/courseware/course/Course.jsx +++ b/src/courseware/course/Course.jsx @@ -37,6 +37,7 @@ const Course = ({ const sequence = useModel('sequences', sequenceId); const section = useModel('sections', sequence ? sequence.sectionId : null); const enableNewSidebar = getConfig().ENABLE_NEW_SIDEBAR; + const navigationDisabled = sequence?.navigationDisabled ?? false; const pageTitleBreadCrumbs = [ sequence, @@ -76,13 +77,17 @@ const Course = ({ {`${pageTitleBreadCrumbs.join(' | ')} | ${getConfig().SITE_NAME}`}
- + {navigationDisabled || ( + <> + + + )} {shouldDisplayChat && ( <> { ); }); + it('removes breadcrumbs when navigation is disabled', async () => { + const sequenceBlocks = [Factory.build( + 'block', + { type: 'sequential', children: [] }, + { courseId: mockData.courseId }, + )]; + const sequenceMetadata = [Factory.build( + 'sequenceMetadata', + { navigation_disabled: true }, + { courseId: mockData.courseId, sequenceBlock: sequenceBlocks[0] }, + )]; + const testStore = await initializeTestStore({ sequenceBlocks, sequenceMetadata }, false); + const testData = { + ...mockData, + sequenceId: sequenceBlocks[0].id, + onNavigate: jest.fn(), + }; + render(, { store: testStore, wrapWithRouter: true }); + expect(screen.queryByRole('navigation', { name: 'breadcrumb' })).not.toBeInTheDocument(); + }); + it('displays first section celebration modal', async () => { const courseHomeMetadata = Factory.build('courseHomeMetadata', { celebrations: { firstSection: true } }); const testStore = await initializeTestStore({ courseHomeMetadata }, false); diff --git a/src/courseware/course/sequence/sequence-navigation/SequenceNavigation.jsx b/src/courseware/course/sequence/sequence-navigation/SequenceNavigation.jsx index f52e585892..37b03a4038 100644 --- a/src/courseware/course/sequence/sequence-navigation/SequenceNavigation.jsx +++ b/src/courseware/course/sequence/sequence-navigation/SequenceNavigation.jsx @@ -32,7 +32,12 @@ const SequenceNavigation = ({ }) => { const sequence = useModel('sequences', sequenceId); const { - isFirstUnit, isLastUnit, nextLink, previousLink, + isFirstUnit, + isLastUnit, + nextLink, + previousLink, + navigationDisabledPrevSequence, + navigationDisabledNextSequence, } = useSequenceNavigationMetadata(sequenceId, unitId); const { courseId, @@ -68,8 +73,7 @@ const SequenceNavigation = ({ const renderPreviousButton = () => { const disabled = isFirstUnit; const prevArrow = isRtl(getLocale()) ? ChevronRight : ChevronLeft; - - return ( + return navigationDisabledPrevSequence || (