diff --git a/src/courseware/course/Course.jsx b/src/courseware/course/Course.jsx index 748d8a40..7458fe7a 100644 --- a/src/courseware/course/Course.jsx +++ b/src/courseware/course/Course.jsx @@ -90,6 +90,7 @@ function Course({ courseId={courseId} sectionId={section ? section.id : null} sequenceId={sequenceId} + unitId={unitId} //* * [MM-P2P] Experiment */ mmp2p={MMP2P} /> diff --git a/src/courseware/course/CourseBreadcrumbs.jsx b/src/courseware/course/CourseBreadcrumbs.jsx index 14d76d31..013941fb 100644 --- a/src/courseware/course/CourseBreadcrumbs.jsx +++ b/src/courseware/course/CourseBreadcrumbs.jsx @@ -5,32 +5,18 @@ import { FormattedMessage } from '@edx/frontend-platform/i18n'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faHome } from '@fortawesome/free-solid-svg-icons'; import { useSelector } from 'react-redux'; -import { Hyperlink, MenuItem, SelectMenu } from '@edx/paragon'; +import { SelectMenu } from '@edx/paragon'; import { getAuthenticatedUser } from '@edx/frontend-platform/auth'; -import { - sendTrackingLogEvent, - sendTrackEvent, -} from '@edx/frontend-platform/analytics'; import { useModel, useModels } from '../../generic/model-store'; /** [MM-P2P] Experiment */ import { MMP2PFlyoverTrigger } from '../../experiments/mm-p2p'; +import ConnectedJumpNavMenuItem from './JumpNavMenuItem'; function CourseBreadcrumb({ - content, withSeparator, + content, withSeparator, courseId, unitId, }) { - const defaultContent = content.filter(destination => destination.default)[0]; - const administrator = getAuthenticatedUser() ? getAuthenticatedUser().administrator : false; - function logEvent(target) { - const eventName = 'edx.ui.lms.jump_nav.selected'; - const payload = { - target_name: target.label, - id: target.id, - current_id: defaultContent.id, - widget_placement: 'breadcrumb', - }; - sendTrackEvent(eventName, payload); - sendTrackingLogEvent(eventName, payload); - } + const defaultContent = content.filter(destination => destination.default)[0] || { id: courseId, label: '' }; + const { administrator } = getAuthenticatedUser(); return ( <> @@ -46,20 +32,20 @@ function CourseBreadcrumb({ > { getConfig().ENABLE_JUMPNAV !== 'true' || content.length < 2 || !administrator ? ( - {defaultContent.label} + + {defaultContent.label} ) : ( {content.map(item => ( - - {item.label} - + ))} )} @@ -72,58 +58,71 @@ CourseBreadcrumb.propTypes = { content: PropTypes.arrayOf( PropTypes.shape({ default: PropTypes.bool, - url: PropTypes.string, id: PropTypes.string, label: PropTypes.string, }), ).isRequired, + unitId: PropTypes.string, withSeparator: PropTypes.bool, + courseId: PropTypes.string, }; CourseBreadcrumb.defaultProps = { withSeparator: false, + unitId: null, + courseId: null, }; export default function CourseBreadcrumbs({ courseId, sectionId, sequenceId, + unitId, /** [MM-P2P] Experiment */ mmp2p, }) { const course = useModel('coursewareMeta', courseId); const courseStatus = useSelector(state => state.courseware.courseStatus); - const sections = course ? Object.fromEntries(useModels('sections', course.sectionIds).map(section => [section.id, section])) : null; - const possibleSequences = sections && sectionId ? sections[sectionId].sequenceIds : []; - const sequences = Object.fromEntries(useModels('sequences', possibleSequences).map(sequence => [sequence.id, sequence])); const sequenceStatus = useSelector(state => state.courseware.sequenceStatus); + const allSequencesInSections = Object.fromEntries(useModels('sections', course.sectionIds).map(section => [section.id, { + default: section.id === sectionId, + title: section.title, + sequences: useModels('sequences', section.sequenceIds), + }])); + const links = useMemo(() => { - const temp = []; + const chapters = []; + const sequentials = []; if (courseStatus === 'loaded' && sequenceStatus === 'loaded') { - temp.push(course.sectionIds.map(id => ({ - id, - label: sections[id].title, - default: (id === sectionId), - // navigate to first sequence in section, (TODO: navigate to first incomplete sequence in section) - url: `${getConfig().BASE_URL}/course/${courseId}/${sections[id].sequenceIds[0]}`, - }))); - temp.push(sections[sectionId].sequenceIds.map(id => ({ - id, - label: sequences[id].title, - default: id === sequenceId, - // first unit it section (TODO: navigate to first incomplete in sequence) - url: `${getConfig().BASE_URL}/course/${courseId}/${sequences[id].id}/${sequences[id].unitIds[0]}`, - }))); + Object.entries(allSequencesInSections).forEach(([id, section]) => { + chapters.push({ + id, + label: section.title, + default: section.default, + sequences: section.sequences, + }); + if (section.default) { + section.sequences.forEach(sequence => { + sequentials.push({ + id: sequence.id, + label: sequence.title, + default: sequence.id === sequenceId, + sequences: [sequence], + }); + }); + } + }); } - return temp; - }, [courseStatus, sections, sequences]); + return [chapters, sequentials]; + }, [courseStatus, sequenceStatus, allSequencesInSections]); + return (