Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FC-0056] Course outline sidebar #1375

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 4 additions & 11 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"@fortawesome/free-solid-svg-icons": "5.15.4",
"@fortawesome/react-fontawesome": "^0.1.4",
"@openedx/frontend-plugin-framework": "^1.0.2",
"@openedx/paragon": "^22.1.1",
"@openedx/paragon": "^22.3.0",
"@popperjs/core": "2.11.8",
"@reduxjs/toolkit": "1.8.1",
"classnames": "2.3.2",
Expand Down
12 changes: 12 additions & 0 deletions src/course-home/data/__snapshots__/redux.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ Object {
},
"courseware": Object {
"courseId": null,
"courseOutline": Object {},
"courseOutlineShouldUpdate": false,
"courseOutlineStatus": "loading",
"courseStatus": "loading",
"coursewareOutlineSidebarSettings": Object {},
"sequenceId": null,
"sequenceMightBeUnit": false,
"sequenceStatus": "loading",
Expand Down Expand Up @@ -402,7 +406,11 @@ Object {
},
"courseware": Object {
"courseId": null,
"courseOutline": Object {},
"courseOutlineShouldUpdate": false,
"courseOutlineStatus": "loading",
"courseStatus": "loading",
"coursewareOutlineSidebarSettings": Object {},
"sequenceId": null,
"sequenceMightBeUnit": false,
"sequenceStatus": "loading",
Expand Down Expand Up @@ -671,7 +679,11 @@ Object {
},
"courseware": Object {
"courseId": null,
"courseOutline": Object {},
"courseOutlineShouldUpdate": false,
"courseOutlineStatus": "loading",
"courseStatus": "loading",
"coursewareOutlineSidebarSettings": Object {},
"sequenceId": null,
"sequenceMightBeUnit": false,
"sequenceStatus": "loading",
Expand Down
19 changes: 9 additions & 10 deletions src/course-home/outline-tab/SequenceLink.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { Link } from 'react-router-dom';
Expand Down Expand Up @@ -96,15 +95,15 @@ const SequenceLink = ({
icon={fasCheckCircle}
fixedWidth
className="float-left text-success mt-1"
aria-hidden="true"
aria-hidden={complete}
title={intl.formatMessage(messages.completedAssignment)}
/>
) : (
<FontAwesomeIcon
icon={farCheckCircle}
fixedWidth
className="float-left text-gray-400 mt-1"
aria-hidden="true"
aria-hidden={complete}
title={intl.formatMessage(messages.incompleteAssignment)}
/>
)}
Expand All @@ -118,14 +117,14 @@ const SequenceLink = ({
</div>
</div>
{hideFromTOC && (
<div className="row w-100 my-2 mx-4 pl-3">
<span className="small d-flex">
<Icon className="mr-2" src={Block} data-testid="hide-from-toc-sequence-link-icon" />
<span data-testid="hide-from-toc-sequence-link-text">
{intl.formatMessage(messages.hiddenSequenceLink)}
<div className="row w-100 my-2 mx-4 pl-3">
<span className="small d-flex">
<Icon className="mr-2" src={Block} data-testid="hide-from-toc-sequence-link-icon" />
<span data-testid="hide-from-toc-sequence-link-text">
{intl.formatMessage(messages.hiddenSequenceLink)}
</span>
</span>
</span>
</div>
</div>
)}
<div className="row w-100 m-0 ml-3 pl-3">
<small className="text-body pl-2">
Expand Down
36 changes: 17 additions & 19 deletions src/courseware/course/Course.jsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,23 @@
import React, { useEffect, useState } from 'react';
import { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import { Helmet } from 'react-helmet';
import { useDispatch } from 'react-redux';
import { useDispatch, useSelector } from 'react-redux';
import { getConfig } from '@edx/frontend-platform';
import { breakpoints, useWindowSize } from '@openedx/paragon';

import { AlertList } from '../../generic/user-messages';

import Sequence from './sequence';

import { CelebrationModal, shouldCelebrateOnSectionLoad, WeeklyGoalCelebrationModal } from './celebration';
import { AlertList } from '@src/generic/user-messages';
import { useModel } from '@src/generic/model-store';
import { getCoursewareOutlineSidebarSettings } from '../data/selectors';
import { Trigger as CourseOutlineTrigger } from './sidebar/sidebars/course-outline';
import Chat from './chat/Chat';
import ContentTools from './content-tools';
import CourseBreadcrumbs from './CourseBreadcrumbs';
import SidebarProvider from './sidebar/SidebarContextProvider';
import SidebarTriggers from './sidebar/SidebarTriggers';
import NewSidebarProvider from './new-sidebar/SidebarContextProvider';
import NewSidebarTriggers from './new-sidebar/SidebarTriggers';

import { useModel } from '../../generic/model-store';
import { CelebrationModal, shouldCelebrateOnSectionLoad, WeeklyGoalCelebrationModal } from './celebration';
import CourseBreadcrumbs from './CourseBreadcrumbs';
import ContentTools from './content-tools';
import Sequence from './sequence';

const Course = ({
courseId,
Expand All @@ -37,7 +36,8 @@ const Course = ({
} = useModel('courseHomeMeta', courseId);
const sequence = useModel('sequences', sequenceId);
const section = useModel('sections', sequence ? sequence.sectionId : null);
const navigationDisabled = sequence?.navigationDisabled ?? false;
const { enableNavigationSidebar } = useSelector(getCoursewareOutlineSidebarSettings);
const navigationDisabled = enableNavigationSidebar || (sequence?.navigationDisabled ?? false);

const pageTitleBreadCrumbs = [
sequence,
Expand All @@ -54,7 +54,6 @@ const Course = ({
const [weeklyGoalCelebrationOpen, setWeeklyGoalCelebrationOpen] = useState(
celebrations && !celebrations.streakLengthToCelebrate && celebrations.weeklyGoal,
);
const shouldDisplayTriggers = windowWidth >= breakpoints.small.minWidth;
const shouldDisplayChat = windowWidth >= breakpoints.medium.minWidth;
const daysPerWeek = course?.courseGoals?.selectedGoal?.daysPerWeek;

Expand All @@ -76,7 +75,7 @@ const Course = ({
<Helmet>
<title>{`${pageTitleBreadCrumbs.join(' | ')} | ${getConfig().SITE_NAME}`}</title>
</Helmet>
<div className="position-relative d-flex align-items-center mb-4 mt-1">
<div className="position-relative d-flex align-items-xl-center mb-4 mt-1 flex-column flex-xl-row">
{navigationDisabled || (
<>
<CourseBreadcrumbs
Expand All @@ -100,11 +99,10 @@ const Course = ({
/>
</>
)}
{shouldDisplayTriggers && (
<>
{isNewDiscussionSidebarViewEnabled ? <NewSidebarTriggers /> : <SidebarTriggers /> }
</>
)}
<div className="w-100 d-flex align-items-center">
<CourseOutlineTrigger isMobileView />
{isNewDiscussionSidebarViewEnabled ? <NewSidebarTriggers /> : <SidebarTriggers /> }
</div>
</div>

<AlertList topic="sequence" />
Expand Down
38 changes: 23 additions & 15 deletions src/courseware/course/Course.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Factory } from 'rosie';
import { breakpoints } from '@openedx/paragon';

import {
act, fireEvent, getByRole, initializeTestStore, loadUnit, render, screen, waitFor,
fireEvent, getByRole, initializeTestStore, loadUnit, render, screen, waitFor,
} from '../../setupTest';
import * as celebrationUtils from './celebration/utils';
import { handleNextSectionCelebration } from './celebration';
Expand Down Expand Up @@ -59,7 +59,7 @@ describe('Course', () => {

it('loads learning sequence', async () => {
render(<Course {...mockData} />, { wrapWithRouter: true });
expect(screen.getByRole('navigation', { name: 'breadcrumb' })).toBeInTheDocument();
expect(screen.queryByRole('navigation', { name: 'breadcrumb' })).not.toBeInTheDocument();
expect(await screen.findByText('Loading learning sequence...')).toBeInTheDocument();

expect(screen.queryByRole('alert')).not.toBeInTheDocument();
Expand Down Expand Up @@ -142,27 +142,32 @@ describe('Course', () => {

const notificationTrigger = screen.getByRole('button', { name: /Show notification tray/i });
expect(notificationTrigger).toBeInTheDocument();
expect(notificationTrigger.parentNode).not.toHaveClass('mt-3', { exact: true });
expect(notificationTrigger.parentNode).not.toHaveClass('sidebar-active', { exact: true });
fireEvent.click(notificationTrigger);
expect(notificationTrigger.parentNode).toHaveClass('mt-3');
expect(notificationTrigger.parentNode).toHaveClass('sidebar-active');
});

it('handles click to open/close discussions sidebar', async () => {
await setupDiscussionSidebar();
const discussionsTrigger = await screen.getByRole('button', { name: /Show discussions tray/i });
const discussionsSideBar = await waitFor(() => screen.findByTestId('sidebar-DISCUSSIONS'));

expect(discussionsSideBar).not.toHaveClass('d-none');
await waitFor(() => {
expect(screen.getByTestId('sidebar-DISCUSSIONS')).toBeInTheDocument();
expect(screen.getByTestId('sidebar-DISCUSSIONS')).not.toHaveClass('d-none');
});

const discussionsTrigger = await screen.getByRole('button', { name: /Show discussions tray/i });
expect(discussionsTrigger).toBeInTheDocument();
fireEvent.click(discussionsTrigger);

await act(async () => {
fireEvent.click(discussionsTrigger);
await waitFor(() => {
expect(screen.queryByTestId('sidebar-DISCUSSIONS')).not.toBeInTheDocument();
});
await expect(discussionsSideBar).toHaveClass('d-none');

await act(async () => {
fireEvent.click(discussionsTrigger);
fireEvent.click(discussionsTrigger);

await waitFor(() => {
expect(screen.queryByTestId('sidebar-DISCUSSIONS')).toBeInTheDocument();
});
await expect(discussionsSideBar).not.toHaveClass('d-none');
});

it('displays discussions sidebar when unit changes', async () => {
Expand Down Expand Up @@ -192,8 +197,9 @@ describe('Course', () => {
it('handles click to open/close notification tray', async () => {
await setupDiscussionSidebar();
const notificationShowButton = await screen.findByRole('button', { name: /Show notification tray/i });
expect(screen.queryByRole('region', { name: /notification tray/i })).toHaveClass('d-none');
expect(screen.queryByRole('region', { name: /notification tray/i })).not.toBeInTheDocument();
fireEvent.click(notificationShowButton);
expect(screen.queryByRole('region', { name: /notification tray/i })).toBeInTheDocument();
expect(screen.queryByRole('region', { name: /notification tray/i })).not.toHaveClass('d-none');
});

Expand All @@ -204,7 +210,9 @@ describe('Course', () => {
{ type: 'vertical' },
{ courseId: courseMetadata.id },
));
const testStore = await initializeTestStore({ courseMetadata, unitBlocks }, false);
const testStore = await initializeTestStore({
courseMetadata, unitBlocks, enableNavigationSidebar: { enable_navigation_sidebar: false },
}, false);
const { courseware, models } = testStore.getState();
const { courseId, sequenceId } = courseware;
const testData = {
Expand Down
2 changes: 1 addition & 1 deletion src/courseware/course/CourseBreadcrumbs.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ const CourseBreadcrumbs = ({
}, [courseStatus, sequenceStatus, allSequencesInSections]);

return (
<nav aria-label="breadcrumb" className="d-inline-block col-sm-10">
<nav aria-label="breadcrumb" className="d-inline-block col-sm-10 mb-3">
<ol className="list-unstyled d-flex flex-nowrap align-items-center m-0">
<li className="list-unstyled col-auto m-0 p-0">
<Link
Expand Down
Loading
Loading