fix: update sidebar design (#2852)
This commit is contained in:
@@ -11,7 +11,7 @@ import VideoSelectorContainer from './selectors/VideoSelectorContainer';
|
||||
import CustomPages from './custom-pages';
|
||||
import { FilesPage, VideosPage } from './files-and-videos';
|
||||
import { AdvancedSettings } from './advanced-settings';
|
||||
import { CourseOutline } from './course-outline';
|
||||
import { CourseOutline, OutlineSidebarPagesProvider } from './course-outline';
|
||||
import ScheduleAndDetails from './schedule-and-details';
|
||||
import { GradingSettings } from './grading-settings';
|
||||
import CourseTeam from './course-team/CourseTeam';
|
||||
@@ -58,7 +58,13 @@ const CourseAuthoringRoutes = () => {
|
||||
<Routes>
|
||||
<Route
|
||||
path="/"
|
||||
element={<PageWrap><CourseOutline /></PageWrap>}
|
||||
element={(
|
||||
<PageWrap>
|
||||
<OutlineSidebarPagesProvider>
|
||||
<CourseOutline />
|
||||
</OutlineSidebarPagesProvider>
|
||||
</PageWrap>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
path="course_info"
|
||||
|
||||
@@ -46,6 +46,7 @@ import {
|
||||
} from './__mocks__';
|
||||
import { COURSE_BLOCK_NAMES, VIDEO_SHARING_OPTIONS } from './constants';
|
||||
import CourseOutline from './CourseOutline';
|
||||
import { OutlineSidebarPagesProvider } from './outline-sidebar/OutlineSidebarPagesContext';
|
||||
|
||||
import messages from './messages';
|
||||
import headerMessages from './header-navigations/messages';
|
||||
@@ -139,7 +140,9 @@ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||
|
||||
const renderComponent = () => render(
|
||||
<CourseAuthoringProvider courseId={courseId}>
|
||||
<CourseOutline />
|
||||
<OutlineSidebarPagesProvider>
|
||||
<CourseOutline />
|
||||
</OutlineSidebarPagesProvider>
|
||||
</CourseAuthoringProvider>,
|
||||
);
|
||||
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
export { default as CourseOutline } from './CourseOutline';
|
||||
export { OutlineSidebarPagesProvider } from './outline-sidebar/OutlineSidebarPagesContext';
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import { Hyperlink } from '@openedx/paragon';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { SchoolOutline } from '@openedx/paragon/icons';
|
||||
|
||||
import { HelpSidebar } from '@src/generic/help-sidebar';
|
||||
import { SidebarContent, SidebarSection, SidebarTitle } from '@src/generic/sidebar';
|
||||
import { useHelpUrls } from '@src/help-urls/hooks';
|
||||
import { useCourseAuthoringContext } from '@src/CourseAuthoringContext';
|
||||
|
||||
import { useCourseDetails } from '../data/apiHooks';
|
||||
import { getFormattedSidebarMessages } from './utils';
|
||||
|
||||
const OutlineHelpSideBar = () => {
|
||||
@@ -15,6 +17,7 @@ const OutlineHelpSideBar = () => {
|
||||
outline: learnMoreOutlineUrl,
|
||||
} = useHelpUrls(['visibility', 'grading', 'outline']);
|
||||
const { courseId } = useCourseAuthoringContext();
|
||||
const { data: courseDetails } = useCourseDetails(courseId);
|
||||
|
||||
const sidebarMessages = getFormattedSidebarMessages(
|
||||
{
|
||||
@@ -26,24 +29,23 @@ const OutlineHelpSideBar = () => {
|
||||
);
|
||||
|
||||
return (
|
||||
<HelpSidebar
|
||||
courseId={courseId}
|
||||
showOtherSettings={false}
|
||||
className="outline-sidebar mt-4"
|
||||
data-testid="outline-sidebar"
|
||||
>
|
||||
{sidebarMessages.map(({ title, descriptions, link }, index) => {
|
||||
const isLastSection = index === sidebarMessages.length - 1;
|
||||
|
||||
return (
|
||||
<div className="outline-sidebar-section" key={title}>
|
||||
<h4 className="help-sidebar-about-title">{title}</h4>
|
||||
<>
|
||||
<SidebarTitle
|
||||
title={courseDetails?.title || ''}
|
||||
icon={SchoolOutline}
|
||||
/>
|
||||
<SidebarContent>
|
||||
{sidebarMessages.map(({ title, descriptions, link }) => (
|
||||
<SidebarSection
|
||||
key={title}
|
||||
title={title}
|
||||
>
|
||||
{descriptions.map((description) => (
|
||||
<p className="help-sidebar-about-descriptions" key={description}>{description}</p>
|
||||
<p className="x-small" key={description}>{description}</p>
|
||||
))}
|
||||
{!!link?.href && (
|
||||
<Hyperlink
|
||||
className="small"
|
||||
className="x-small"
|
||||
destination={link.href}
|
||||
target="_blank"
|
||||
showLaunchIcon={false}
|
||||
@@ -51,11 +53,10 @@ const OutlineHelpSideBar = () => {
|
||||
{link.text}
|
||||
</Hyperlink>
|
||||
)}
|
||||
{!isLastSection && <hr className="my-3.5" />}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</HelpSidebar>
|
||||
</SidebarSection>
|
||||
))}
|
||||
</SidebarContent>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
import { CourseAuthoringProvider } from '@src/CourseAuthoringContext';
|
||||
|
||||
import { OutlineSidebarProvider } from './OutlineSidebarContext';
|
||||
import { OutlineSidebarPagesProvider } from './OutlineSidebarPagesContext';
|
||||
import OutlineSidebar from './OutlineSidebar';
|
||||
|
||||
// Mock the useCourseDetails hook
|
||||
@@ -19,9 +20,11 @@ const courseId = '123';
|
||||
|
||||
const extraWrapper = ({ children }) => (
|
||||
<CourseAuthoringProvider courseId={courseId}>
|
||||
<OutlineSidebarProvider>
|
||||
{children}
|
||||
</OutlineSidebarProvider>
|
||||
<OutlineSidebarPagesProvider>
|
||||
<OutlineSidebarProvider>
|
||||
{children}
|
||||
</OutlineSidebarProvider>
|
||||
</OutlineSidebarPagesProvider>
|
||||
</CourseAuthoringProvider>
|
||||
);
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { createContext, useContext } from 'react';
|
||||
import { createContext, useContext, useMemo } from 'react';
|
||||
import { getConfig } from '@edx/frontend-platform';
|
||||
import {
|
||||
HelpOutline, Info, Plus, Tag,
|
||||
@@ -19,15 +19,18 @@ export type OutlineSidebarPages = {
|
||||
align?: SidebarPage;
|
||||
};
|
||||
|
||||
const showAlignSidebar = getConfig().ENABLE_TAGGING_TAXONOMY_PAGES === 'true';
|
||||
|
||||
const OUTLINE_SIDEBAR_PAGES: OutlineSidebarPages = {
|
||||
const getOutlineSidebarPages = () => ({
|
||||
info: {
|
||||
component: OutlineInfoSidebar,
|
||||
icon: Info,
|
||||
title: messages.sidebarButtonInfo,
|
||||
},
|
||||
...(showAlignSidebar && {
|
||||
add: {
|
||||
component: AddSidebar,
|
||||
icon: Plus,
|
||||
title: messages.sidebarButtonAdd,
|
||||
},
|
||||
...(getConfig().ENABLE_TAGGING_TAXONOMY_PAGES === 'true' && {
|
||||
align: {
|
||||
component: OutlineAlignSidebar,
|
||||
icon: Tag,
|
||||
@@ -39,12 +42,7 @@ const OUTLINE_SIDEBAR_PAGES: OutlineSidebarPages = {
|
||||
icon: HelpOutline,
|
||||
title: messages.sidebarButtonHelp,
|
||||
},
|
||||
add: {
|
||||
component: AddSidebar,
|
||||
icon: Plus,
|
||||
title: messages.sidebarButtonAdd,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Context for the Outline Sidebar Pages.
|
||||
@@ -77,6 +75,24 @@ const OUTLINE_SIDEBAR_PAGES: OutlineSidebarPages = {
|
||||
* );
|
||||
*}
|
||||
*/
|
||||
export const OutlineSidebarPagesContext = createContext<OutlineSidebarPages>(OUTLINE_SIDEBAR_PAGES);
|
||||
export const OutlineSidebarPagesContext = createContext<OutlineSidebarPages | undefined>(undefined);
|
||||
|
||||
export const useOutlineSidebarPagesContext = (): OutlineSidebarPages => useContext(OutlineSidebarPagesContext);
|
||||
type OutlineSidebarPagesProviderProps = {
|
||||
children: React.ReactNode;
|
||||
};
|
||||
|
||||
export const OutlineSidebarPagesProvider = ({ children }: OutlineSidebarPagesProviderProps) => {
|
||||
const sidebarPages = useMemo(getOutlineSidebarPages, []);
|
||||
|
||||
return (
|
||||
<OutlineSidebarPagesContext.Provider value={sidebarPages}>
|
||||
{children}
|
||||
</OutlineSidebarPagesContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useOutlineSidebarPagesContext = (): OutlineSidebarPages => {
|
||||
const ctx = useContext(OutlineSidebarPagesContext);
|
||||
if (ctx === undefined) { throw new Error('useOutlineSidebarPages must be used within an OutlineSidebarPagesProvider'); }
|
||||
return ctx;
|
||||
};
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
import { getConfig } from '@edx/frontend-platform';
|
||||
import {
|
||||
HelpOutline, Info, Plus, Tag,
|
||||
} from '@openedx/paragon/icons';
|
||||
import type { SidebarPage } from '@src/generic/sidebar';
|
||||
import OutlineHelpSidebar from './OutlineHelpSidebar';
|
||||
import { OutlineInfoSidebar } from './OutlineInfoSidebar';
|
||||
import messages from './messages';
|
||||
import { AddSidebar } from './AddSidebar';
|
||||
import { OutlineAlignSidebar } from './OutlineAlignSidebar';
|
||||
|
||||
export type OutlineSidebarPages = {
|
||||
info: SidebarPage;
|
||||
help: SidebarPage;
|
||||
add: SidebarPage;
|
||||
align?: SidebarPage;
|
||||
};
|
||||
|
||||
export const getOutlineSidebarPages = (): OutlineSidebarPages => {
|
||||
const showAlignSidebar = getConfig().ENABLE_TAGGING_TAXONOMY_PAGES === 'true';
|
||||
return {
|
||||
info: {
|
||||
component: OutlineInfoSidebar,
|
||||
icon: Info,
|
||||
title: messages.sidebarButtonInfo,
|
||||
},
|
||||
...(showAlignSidebar && {
|
||||
align: {
|
||||
component: OutlineAlignSidebar,
|
||||
icon: Tag,
|
||||
title: messages.sidebarButtonAlign,
|
||||
},
|
||||
}),
|
||||
help: {
|
||||
component: OutlineHelpSidebar,
|
||||
icon: HelpOutline,
|
||||
title: messages.sidebarButtonHelp,
|
||||
},
|
||||
add: {
|
||||
component: AddSidebar,
|
||||
icon: Plus,
|
||||
title: messages.sidebarButtonAdd,
|
||||
},
|
||||
} satisfies OutlineSidebarPages;
|
||||
};
|
||||
@@ -581,17 +581,16 @@ describe('<CourseUnit />', () => {
|
||||
published_preview_link: publishedPreviewLink,
|
||||
} = courseSectionVerticalMock;
|
||||
|
||||
await waitFor(async () => {
|
||||
const viewLiveButton = screen.getByRole('button', { name: headerNavigationsMessages.viewLiveButton.defaultMessage });
|
||||
await user.click(viewLiveButton);
|
||||
expect(window.open).toHaveBeenCalled();
|
||||
expect(window.open).toHaveBeenCalledWith(publishedPreviewLink, '_blank');
|
||||
const viewLiveButton = await screen.findByRole('button', { name: headerNavigationsMessages.viewLiveButton.defaultMessage });
|
||||
|
||||
const previewButton = screen.getByRole('button', { name: headerNavigationsMessages.previewButton.defaultMessage });
|
||||
await user.click(previewButton);
|
||||
expect(window.open).toHaveBeenCalled();
|
||||
expect(window.open).toHaveBeenCalledWith(draftPreviewLink, '_blank');
|
||||
});
|
||||
await user.click(viewLiveButton);
|
||||
expect(window.open).toHaveBeenCalled();
|
||||
expect(window.open).toHaveBeenCalledWith(publishedPreviewLink, '_blank');
|
||||
|
||||
const previewButton = screen.getByRole('button', { name: headerNavigationsMessages.previewButton.defaultMessage });
|
||||
await user.click(previewButton);
|
||||
expect(window.open).toHaveBeenCalled();
|
||||
expect(window.open).toHaveBeenCalledWith(draftPreviewLink, '_blank');
|
||||
|
||||
window.open = open;
|
||||
});
|
||||
@@ -870,9 +869,8 @@ describe('<CourseUnit />', () => {
|
||||
.reply(200, courseCreateXblockMock);
|
||||
render(<RootWrapper />);
|
||||
|
||||
await waitFor(async () => {
|
||||
await user.click(screen.getByRole('button', { name: legacySidebarMessages.actionButtonPublishTitle.defaultMessage }));
|
||||
});
|
||||
const publishButton = await screen.findByRole('button', { name: legacySidebarMessages.actionButtonPublishTitle.defaultMessage });
|
||||
await user.click(publishButton);
|
||||
|
||||
axiosMock
|
||||
.onPost(getXBlockBaseApiUrl(blockId), {
|
||||
|
||||
Reference in New Issue
Block a user