Files
frontend-app-learning/src/courseware/course/CourseBreadcrumbs.jsx
sundasnoreen12 023f5ac254 feat: added implementation for new sidebar (#1260)
* feat: added implementation for new sidebar

* test: fixed test cases

* refactor: fixed naming convention and combine useeffects

* refactor: improved sidebar UI and renamed sidebar flag

* refactor: remove additional states

* refactor: fixed UI and logic related issue

* refactor: simplified condition

* refactor: toggle sidebar action

* refactor: fixed toggle issues

* refactor: back arrow component

* refactor: changed useeffect position

---------

Co-authored-by: Awais Ansari <awais.ansari63@gmail.com>
2024-01-08 13:40:21 +05:00

203 lines
5.7 KiB
JavaScript

import React, { useMemo, useState } from 'react';
import PropTypes from 'prop-types';
import { getConfig } from '@edx/frontend-platform';
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 { useToggle, ModalPopup, Menu } from '@edx/paragon';
import { Link } from 'react-router-dom';
import { useModel, useModels } from '../../generic/model-store';
import JumpNavMenuItem from './JumpNavMenuItem';
const CourseBreadcrumb = ({
content,
withSeparator,
courseId,
sequenceId,
unitId,
isStaff,
}) => {
const defaultContent = content.filter(
(destination) => destination.default,
)[0] || { id: courseId, label: '', sequences: [] };
const showRegularLink = getConfig().ENABLE_JUMPNAV !== 'true' || content.length < 2 || !isStaff;
const [isOpen, open, close] = useToggle(false);
const [target, setTarget] = useState(null);
return (
<>
{withSeparator && (
<li className="col-auto p-0 mx-2 text-primary-500 text-truncate text-nowrap" role="presentation" aria-hidden>/</li>
)}
<li
style={{
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
}}
data-testid="breadcrumb-item"
>
{showRegularLink ? (
<Link
className="text-primary-500"
to={
defaultContent.sequences.length
? `/course/${courseId}/${defaultContent.sequences[0].id}`
: `/course/${courseId}/${defaultContent.id}`
}
>
{defaultContent.label}
</Link>
) : (
<>
{
// eslint-disable-next-line
<a className="text-primary-500" onClick={open} ref={setTarget}>
{defaultContent.label}
</a>
}
<ModalPopup positionRef={target} isOpen={isOpen} onClose={close}>
<Menu>
{content.map((item) => (
<JumpNavMenuItem
isDefault={item.default}
sequences={item.sequences}
courseId={courseId}
title={item.label}
currentSequence={sequenceId}
currentUnit={unitId}
onClick={close}
/>
))}
</Menu>
</ModalPopup>
</>
)}
</li>
</>
);
};
CourseBreadcrumb.propTypes = {
content: PropTypes.arrayOf(
PropTypes.shape({
default: PropTypes.bool,
id: PropTypes.string,
label: PropTypes.string,
}),
).isRequired,
sequenceId: PropTypes.string,
unitId: PropTypes.string,
withSeparator: PropTypes.bool,
courseId: PropTypes.string,
isStaff: PropTypes.bool,
};
CourseBreadcrumb.defaultProps = {
withSeparator: false,
sequenceId: null,
unitId: null,
courseId: null,
isStaff: null,
};
const CourseBreadcrumbs = ({
courseId,
sectionId,
sequenceId,
unitId,
isStaff,
}) => {
const course = useModel('coursewareMeta', courseId);
const courseStatus = useSelector((state) => state.courseware.courseStatus);
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 chapters = [];
const sequentials = [];
if (courseStatus === 'loaded' && sequenceStatus === 'loaded') {
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 [chapters, sequentials];
}, [courseStatus, sequenceStatus, allSequencesInSections]);
return (
<nav aria-label="breadcrumb" className="d-inline-block col-sm-10">
<ol className="list-unstyled d-flex flex-nowrap align-items-center m-0">
<li className="list-unstyled col-auto m-0 p-0">
<Link
className="flex-shrink-0 text-primary"
to={`/course/${courseId}/home`}
replace
>
<FontAwesomeIcon icon={faHome} className="mr-2" />
<FormattedMessage
id="learn.breadcrumb.navigation.course.home"
description="The course home link in breadcrumbs nav"
defaultMessage="Course"
/>
</Link>
</li>
{links.map((content) => (
<CourseBreadcrumb
courseId={courseId}
sequenceId={sequenceId}
content={content}
unitId={unitId}
withSeparator
isStaff={isStaff}
/>
))}
</ol>
</nav>
);
};
CourseBreadcrumbs.propTypes = {
courseId: PropTypes.string.isRequired,
sectionId: PropTypes.string,
sequenceId: PropTypes.string,
unitId: PropTypes.string,
isStaff: PropTypes.bool,
};
CourseBreadcrumbs.defaultProps = {
sectionId: null,
sequenceId: null,
unitId: null,
isStaff: null,
};
export default CourseBreadcrumbs;