diff --git a/src/courseware/course/CourseBreadcrumbs.test.jsx b/src/courseware/course/CourseBreadcrumbs.test.jsx
deleted file mode 100644
index f51ead34..00000000
--- a/src/courseware/course/CourseBreadcrumbs.test.jsx
+++ /dev/null
@@ -1,134 +0,0 @@
-import React from 'react';
-import { screen, render } from '@testing-library/react';
-import { getAuthenticatedUser } from '@edx/frontend-platform/auth';
-import { getConfig } from '@edx/frontend-platform';
-import { BrowserRouter } from 'react-router-dom';
-import { IntlProvider } from '@edx/frontend-platform/i18n';
-import { useModel, useModels } from '../../generic/model-store';
-import CourseBreadcrumbs from './CourseBreadcrumbs';
-
-jest.mock('@edx/frontend-platform');
-jest.mock('@edx/frontend-platform/analytics');
-
-// Remove When Fully rolled out>>>
-jest.mock('../../generic/model-store');
-jest.mock('@edx/frontend-platform/auth');
-getConfig.mockImplementation(() => ({ ENABLE_JUMPNAV: 'true' }));
-getAuthenticatedUser.mockImplementation(() => ({ administrator: true }));
-// ^^^^Remove When Fully rolled out
-
-jest.mock('react-redux', () => ({
- connect: (mapStateToProps, mapDispatchToProps) => (ReactComponent) => ({
- mapStateToProps,
- mapDispatchToProps,
- ReactComponent,
- }),
- Provider: ({ children }) => children,
- useSelector: () => 'loaded',
-}));
-jest.mock('react-router-dom', () => ({
- ...jest.requireActual('react-router-dom'),
- Link: jest.fn().mockImplementation(({ to, children }) => (
- {children}
- )),
-}));
-
-useModels.mockImplementation((name) => {
- if (name === 'sections') {
- return [
- {
- courseId: 'course-v1:edX+DemoX+Demo_Course',
- id: 'block-v1:edX+DemoX+Demo_Course+type@chapter+block@d8a6192ade314473a78242dfeedfbf5b',
- sequenceIds: ['block-v1:edX+DemoX+Demo_Course+type@sequential+block@edx_introduction'],
- title: 'Introduction',
- },
- {
- courseId: 'course-v1:edX+DemoX+Demo_Course',
- id: 'block-v1:edX+DemoX+Demo_Course+type@chapter+block@interactive_demonstrations',
- sequenceIds: ['block-v1:edX+DemoX+Demo_Course+type@sequential+block@19a30717eff543078a5d94ae9d6c18a5',
- 'block-v1:edX+DemoX+Demo_Course+type@sequential+block@basic_questions'],
- title: 'Example Week 1: Getting Started',
- },
- ];
- }
- return [
- {
- id: 'block-v1:edX+DemoX+Demo_Course+type@sequential+block@19a30717eff543078a5d94ae9d6c18a5',
- sectionId: 'block-v1:edX+DemoX+Demo_Course+type@chapter+block@interactive_demonstrations',
- title: 'Lesson 1 - Getting Started',
- unitIds: [
- 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@867dddb6f55d410caaa9c1eb9c6743ec',
- 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@4f6c1b4e316a419ab5b6bf30e6c708e9',
- 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@3dc16db8d14842e38324e95d4030b8a0',
- 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@4a1bba2a403f40bca5ec245e945b0d76',
- 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@256f17a44983429fb1a60802203ee4e0',
- 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@e3601c0abee6427d8c17e6d6f8fdddd1',
- 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@134df56c516a4a0dbb24dd5facef746e',
- ],
- },
- {
- id: 'block-v1:edX+DemoX+Demo_Course+type@sequential+block@basic_questions',
- sectionId: 'block-v1:edX+DemoX+Demo_Course+type@chapter+block@interactive_demonstrations',
- title: 'Homework - Question Styles',
- unitIds: [
- 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@2152d4a4aadc4cb0af5256394a3d1fc7',
- 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@47dbd5f836544e61877a483c0b75606c',
- 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@54bb9b142c6c4c22afc62bcb628f0e68',
- 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@vertical_0c92347a5c00',
- 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@vertical_1fef54c2b23b',
- 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@2889db1677a549abb15eb4d886f95d1c',
- 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@e8a5cc2aed424838853defab7be45e42',
- ],
- },
- ];
-});
-useModel.mockImplementation(() => ({
- sectionIds: ['block-v1:edX+DemoX+Demo_Course+type@chapter+block@d8a6192ade314473a78242dfeedfbf5b',
- 'block-v1:edX+DemoX+Demo_Course+type@chapter+block@interactive_demonstrations'],
-}));
-
-describe('CourseBreadcrumbs', () => {
- jest.spyOn(React, 'useMemo').mockImplementation(() => [
- [
- {
- default: false,
- id: 'block-v1:edX+DemoX+Demo_Course+type@chapter+block@d8a6192ade314473a78242dfeedfbf5b',
- label: 'Introduction',
- url: 'http://localhost:2000/course/course-v1:edX+DemoX+Demo_Course/block-v1:edX+DemoX+Demo_Course+type@sequential+block@edx_introduction',
- },
- {
- default: true,
- id: 'block-v1:edX+DemoX+Demo_Course+type@chapter+block@interactive_demonstrations',
- label: 'Example Week 1: Getting Started',
- url: 'http://localhost:2000/course/course-v1:edX+DemoX+Demo_Course/block-v1:edX+DemoX+Demo_Course+type@sequential+block@19a30717eff543078a5d94ae9d6c18a5',
- },
- ],
- [
- {
- id: 'block-v1:edX+DemoX+Demo_Course+type@sequential+block@simulations', label: "Lesson 2 - Let's Get Interactive!", default: true, url: 'http://localhost:2000/course/course-v1:edX+DemoX+D…e@vertical+block@d0d804e8863c4a95a659c04d8a2b2bc0',
- },
- {
- id: 'block-v1:edX+DemoX+Demo_Course+type@sequential+block@175e76c4951144a29d46211361266e0e', label: 'Homework - Essays', default: false, url: 'http://localhost:2000/course/course-v1:edX+DemoX+D…e@vertical+block@fb79dcbad35b466a8c6364f8ffee9050',
- },
- ],
- ]);
- render(
-
-
-
- ,
- ,
- );
- it('renders course breadcrumbs as expected', async () => {
- expect(screen.queryAllByRole('link')).toHaveLength(1);
- const courseHomeButtonDestination = screen.getAllByRole('link')[0].href;
- expect(courseHomeButtonDestination).toBe('http://localhost/course/course-v1:edX+DemoX+Demo_Course/home');
- expect(screen.getByRole('navigation', { name: 'breadcrumb' })).toBeInTheDocument();
- expect(screen.queryAllByTestId('breadcrumb-item')).toHaveLength(2);
- });
-});
diff --git a/src/courseware/course/breadcrumbs/BreadcrumbItem.tsx b/src/courseware/course/breadcrumbs/BreadcrumbItem.tsx
new file mode 100644
index 00000000..9533797e
--- /dev/null
+++ b/src/courseware/course/breadcrumbs/BreadcrumbItem.tsx
@@ -0,0 +1,103 @@
+import React, { useState } from 'react';
+import { getConfig } from '@edx/frontend-platform';
+import {
+ useToggle,
+ ModalPopup,
+ Menu,
+} from '@openedx/paragon';
+import { Link, useLocation } from 'react-router-dom';
+import JumpNavMenuItem from '../JumpNavMenuItem';
+
+interface Props {
+ content: {
+ default: boolean,
+ id: string,
+ label: string,
+ sequences: {
+ id: string,
+ }[],
+ } [];
+ withSeparator: boolean | false,
+ separator: string | '';
+ courseId: string;
+ sequenceId: string | '';
+ unitId: string | '';
+ isStaff: boolean | false;
+}
+
+const BreadcrumbItem: React.FC = ({
+ content,
+ withSeparator,
+ separator,
+ courseId,
+ sequenceId,
+ unitId,
+ isStaff,
+}) => {
+ const defaultContent = content.filter(
+ (destination: { default: boolean }) => 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);
+
+ const { pathname } = useLocation();
+ const isPreview = pathname.startsWith('/preview');
+ const baseUrl = defaultContent.sequences.length
+ ? `/course/${courseId}/${defaultContent.sequences[0].id}`
+ : `/course/${courseId}/${defaultContent.id}`;
+ const link = isPreview ? `/preview${baseUrl}` : baseUrl;
+ return (
+ <>
+ {withSeparator && separator && (
+ {separator}
+ )}
+
+
+ {showRegularLink ? (
+
+ {defaultContent.label}
+
+ ) : (
+ <>
+ {
+ // @ts-ignore
+
+ {defaultContent.label}
+
+ }
+
+
+
+ >
+ )}
+
+ >
+ );
+};
+
+export default BreadcrumbItem;
\ No newline at end of file
diff --git a/src/courseware/course/CourseBreadcrumbs.jsx b/src/courseware/course/breadcrumbs/CourseBreadcrumbs.jsx
similarity index 50%
rename from src/courseware/course/CourseBreadcrumbs.jsx
rename to src/courseware/course/breadcrumbs/CourseBreadcrumbs.jsx
index ab9d031d..d94ada18 100644
--- a/src/courseware/course/CourseBreadcrumbs.jsx
+++ b/src/courseware/course/breadcrumbs/CourseBreadcrumbs.jsx
@@ -1,107 +1,12 @@
-import React, { useMemo, useState } from 'react';
+import React, { useMemo } 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 '@openedx/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 && (
- /
- )}
-
-
- {showRegularLink ? (
-
- {defaultContent.label}
-
- ) : (
- <>
- {
- // eslint-disable-next-line
-
- {defaultContent.label}
-
- }
-
-
-
- >
- )}
-
- >
- );
-};
-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,
-};
+import { useModel, useModels } from '../../../generic/model-store';
+import BreadcrumbItem from './BreadcrumbItem';
const CourseBreadcrumbs = ({
courseId,
@@ -110,14 +15,16 @@ const CourseBreadcrumbs = ({
unitId,
isStaff,
}) => {
- const course = useModel('coursewareMeta', courseId);
+ const course = useModel('coursewareMeta', courseId);
const courseStatus = useSelector((state) => state.courseware.courseStatus);
const sequenceStatus = useSelector(
(state) => state.courseware.sequenceStatus,
);
+ console.log( useModels('sections', course.sectionIds));
+
const allSequencesInSections = Object.fromEntries(
- useModels('sections', course.sectionIds).map((section) => [
+ useModels('sections', course.sectionIds)?.map((section) => [
section.id,
{
default: section.id === sectionId,
@@ -152,6 +59,8 @@ const CourseBreadcrumbs = ({
}
return [chapters, sequentials];
}, [courseStatus, sequenceStatus, allSequencesInSections]);
+ console.log(links);
+
return (