Skip to content
Open
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
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import { render, screen, initializeMocks } from '@src/testUtils';

import * as CourseAuthoringContext from '@src/CourseAuthoringContext';
import * as CourseDetailsApi from '@src/data/apiHooks';
Expand All @@ -17,6 +16,7 @@ jest.mock('@src/content-tags-drawer', () => ({

describe('OutlineAlignSidebar', () => {
beforeEach(() => {
initializeMocks();
jest
.spyOn(CourseAuthoringContext, 'useCourseAuthoringContext')
.mockReturnValue({
Expand Down
29 changes: 12 additions & 17 deletions src/course-outline/outline-sidebar/OutlineAlignSidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { SchoolOutline } from '@openedx/paragon/icons';
import { ContentTagsDrawer } from '@src/content-tags-drawer';
import { useContentData } from '@src/content-tags-drawer/data/apiHooks';
import { useCourseAuthoringContext } from '@src/CourseAuthoringContext';
import { useCourseDetails } from '@src/data/apiHooks';
import { SidebarTitle } from '@src/generic/sidebar';
import { AlignSidebar } from '@src/generic/sidebar/AlignSidebar';
import { useOutlineSidebarContext } from './OutlineSidebarContext';

/**
* Align sidebar for course or selected containers.
*/
export const OutlineAlignSidebar = () => {
const { courseId } = useCourseAuthoringContext();
const { currentContainerId } = useOutlineSidebarContext();
Expand All @@ -21,19 +22,13 @@ export const OutlineAlignSidebar = () => {
} = useContentData(currentContainerId);

return (
<div>
<SidebarTitle
title={
contentData && 'displayName' in contentData
? contentData.displayName
: courseData?.name || ''
}
icon={SchoolOutline}
/>
<ContentTagsDrawer
id={sidebarContentId}
variant="component"
/>
</div>
<AlignSidebar
title={
contentData && 'displayName' in contentData
? contentData.displayName
: courseData?.name || ''
}
contentId={sidebarContentId}
/>
);
};
16 changes: 16 additions & 0 deletions src/course-unit/CourseUnit.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2917,4 +2917,20 @@ describe('<CourseUnit />', () => {
render(<RootWrapper />);
expect(await screen.findByText('Access: 3 Groups')).toBeInTheDocument();
});

it('opens the align sidebar on postMessage event', async () => {
setConfig({
...getConfig(),
ENABLE_TAGGING_TAXONOMY_PAGES: 'true',
ENABLE_UNIT_PAGE_NEW_DESIGN: 'true',
});

render(<RootWrapper />);

await screen.findByTitle(xblockContainerIframeMessages.xblockIframeTitle.defaultMessage);

simulatePostMessageEvent(messageTypes.openManageTags, { contentId: blockId });

await screen.findByText('Align');
});
});
33 changes: 33 additions & 0 deletions src/course-unit/unit-sidebar/UnitAlignSidebar.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { render, screen, initializeMocks } from '@src/testUtils';
import { UnitAlignSidebar } from './UnitAlignSidebar';
import { UnitSidebarProvider } from './UnitSidebarContext';

jest.mock('@src/content-tags-drawer', () => ({
ContentTagsDrawer: jest.fn(({ id, variant }) => (
<div data-testid="content-tags-drawer">
drawer-mock-{id}-{variant}
</div>
)),
}));

jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useParams: () => ({ blockId: 'unit-id-1' }),
}));

describe('OutlineAlignSidebar', () => {
beforeEach(() => {
initializeMocks();
});

it('renders ContentTagsDrawer with the correct id and variant', () => {
render(<UnitSidebarProvider><UnitAlignSidebar /></UnitSidebarProvider>);

const drawer = screen.getByTestId('content-tags-drawer');

expect(drawer).toBeInTheDocument();
expect(drawer).toHaveTextContent(
'drawer-mock-unit-id-1-component',
);
});
});
28 changes: 28 additions & 0 deletions src/course-unit/unit-sidebar/UnitAlignSidebar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { useParams } from 'react-router-dom';
import { useContentData } from '@src/content-tags-drawer/data/apiHooks';
import { AlignSidebar } from '@src/generic/sidebar/AlignSidebar';
import { useUnitSidebarContext } from './UnitSidebarContext';

/**
* Align sidebar for unit or selected components.
*/
export const UnitAlignSidebar = () => {
const { blockId } = useParams();
const { currentComponentId } = useUnitSidebarContext();

const sidebarContentId = currentComponentId || blockId;

const {
data: contentData,
} = useContentData(sidebarContentId);

return (
<AlignSidebar
title={
contentData && 'displayName' in contentData
? contentData.displayName : ''
}
contentId={sidebarContentId || ''}
/>
);
};
4 changes: 2 additions & 2 deletions src/course-unit/unit-sidebar/UnitSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Sidebar } from '@src/generic/sidebar';
import LegacySidebar, { LegacySidebarProps } from '../legacy-sidebar';
import { useUnitSidebarContext } from './UnitSidebarContext';
import { isUnitPageNewDesignEnabled } from '../utils';
import { UNIT_SIDEBAR_PAGES } from './constants';
import { getUnitSidebarPages } from './sidebarPages';

export type UnitSidebarProps = {
legacySidebarProps: LegacySidebarProps,
Expand All @@ -26,7 +26,7 @@ export const UnitSidebar = ({

return (
<Sidebar
pages={UNIT_SIDEBAR_PAGES}
pages={getUnitSidebarPages()}
currentPageKey={currentPageKey}
setCurrentPageKey={setCurrentPageKey}
isOpen={isOpen}
Expand Down
25 changes: 21 additions & 4 deletions src/course-unit/unit-sidebar/UnitSidebarContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,20 @@ import {
} from 'react';
import { SidebarPage } from '@src/generic/sidebar';
import { useToggle } from '@openedx/paragon';
import { useStateWithUrlSearchParam } from '@src/hooks';

export type UnitSidebarPageKeys = 'info';
export type UnitSidebarPageKeys = 'info' | 'align';
export type UnitSidebarPages = Record<UnitSidebarPageKeys, SidebarPage>;

interface UnitSidebarContextData {
currentPageKey: UnitSidebarPageKeys;
setCurrentPageKey: (pageKey: UnitSidebarPageKeys) => void;
setCurrentPageKey: (pageKey: UnitSidebarPageKeys, componentId?: string) => void;
currentTabKey?: string;
setCurrentTabKey: (tabKey: string) => void;
// The Id of the component used in the current sidebar page
// The component is not necessarily selected to open a selected sidebar.
// Example: Align sidebar
currentComponentId?: string;
isOpen: boolean;
open: () => void;
toggle: () => void;
Expand All @@ -20,12 +25,22 @@ interface UnitSidebarContextData {
const UnitSidebarContext = createContext<UnitSidebarContextData | undefined>(undefined);

export const UnitSidebarProvider = ({ children }: { children?: React.ReactNode }) => {
const [currentPageKey, setCurrentPageKeyState] = useState<UnitSidebarPageKeys>('info');
const [currentPageKey, setCurrentPageKeyState] = useStateWithUrlSearchParam<UnitSidebarPageKeys>(
'info',
'sidebar',
(value: string) => value as UnitSidebarPageKeys,
(value: UnitSidebarPageKeys) => value,
);
const [currentTabKey, setCurrentTabKey] = useState<string>();
const [currentComponentId, setCurrentComponentId] = useState<string>();
const [isOpen, open,, toggle] = useToggle(true);

const setCurrentPageKey = useCallback(/* istanbul ignore next */ (pageKey: UnitSidebarPageKeys) => {
const setCurrentPageKey = useCallback(/* istanbul ignore next */ (
pageKey: UnitSidebarPageKeys,
componentId?: string,
) => {
setCurrentPageKeyState(pageKey);
setCurrentComponentId(componentId);
open();
}, [open]);

Expand All @@ -35,6 +50,7 @@ export const UnitSidebarProvider = ({ children }: { children?: React.ReactNode }
setCurrentPageKey,
currentTabKey,
setCurrentTabKey,
currentComponentId,
isOpen,
open,
toggle,
Expand All @@ -44,6 +60,7 @@ export const UnitSidebarProvider = ({ children }: { children?: React.ReactNode }
setCurrentPageKey,
currentTabKey,
setCurrentTabKey,
currentComponentId,
isOpen,
open,
toggle,
Expand Down
20 changes: 0 additions & 20 deletions src/course-unit/unit-sidebar/constants.ts

This file was deleted.

5 changes: 5 additions & 0 deletions src/course-unit/unit-sidebar/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ const messages = defineMessages({
defaultMessage: 'Info',
description: 'Label of the button for the Info sidebar',
},
sidebarButtonAlign: {
id: 'course-authoring.unit-page.sidebar.info.sidebar-button-align',
defaultMessage: 'Align',
description: 'Label of the button for the Align sidebar',
},
});

export default messages;
35 changes: 35 additions & 0 deletions src/course-unit/unit-sidebar/sidebarPages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { getConfig } from '@edx/frontend-platform';
import { Info, Tag } from '@openedx/paragon/icons';
import { SidebarPage } from '@src/generic/sidebar';
import messages from './messages';
import { UnitInfoSidebar } from './unit-info/UnitInfoSidebar';
import { UnitAlignSidebar } from './UnitAlignSidebar';

export type UnitSidebarPages = {
info: SidebarPage;
align?: SidebarPage;
};

/**
* Sidebar pages for the unit sidebar
*
* This has been separated from the context to avoid a cyclical import
* if you want to use the context in the sidebar pages.
*/
export const getUnitSidebarPages = (): UnitSidebarPages => {
const showAlignSidebar = getConfig().ENABLE_TAGGING_TAXONOMY_PAGES === 'true';
return {
info: {
component: UnitInfoSidebar,
icon: Info,
title: messages.sidebarButtonInfo,
},
...(showAlignSidebar && {
align: {
component: UnitAlignSidebar,
icon: Tag,
title: messages.sidebarButtonAlign,
},
}),
};
};
12 changes: 10 additions & 2 deletions src/course-unit/xblock-container-iframe/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,15 @@ import {
AccessManagedXBlockDataTypes,
} from './types';
import { formatAccessManagedXBlockData, getIframeUrl, getLegacyEditModalUrl } from './utils';
import { useUnitSidebarContext } from '../unit-sidebar/UnitSidebarContext';
import { isUnitPageNewDesignEnabled } from '../utils';

const XBlockContainerIframe: FC<XBlockContainerIframeProps> = ({
courseId, blockId, unitXBlockActions, courseVerticalChildren, handleConfigureSubmit, isUnitVerticalType,
}) => {
const intl = useIntl();
const dispatch = useDispatch();
const { setCurrentPageKey } = useUnitSidebarContext();

// Useful to reload iframe
const [iframeKey, setIframeKey] = useState(0);
Expand Down Expand Up @@ -169,8 +172,13 @@ const XBlockContainerIframe: FC<XBlockContainerIframeProps> = ({
};

const handleOpenManageTagsModal = (id: string) => {
setConfigureXBlockId(id);
openManageTagsModal();
if (isUnitPageNewDesignEnabled()) {
setCurrentPageKey('align', id);
} else {
// Legacy manage tags modal
setConfigureXBlockId(id);
openManageTagsModal();
}
};

const handleShowProcessingNotification = (variant: string) => {
Expand Down
25 changes: 25 additions & 0 deletions src/generic/sidebar/AlignSidebar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { ContentTagsDrawer } from '@src/content-tags-drawer';
import { SchoolOutline } from '@openedx/paragon/icons';
import { SidebarTitle } from './SidebarTitle';

export interface AlignSidebarProps {
contentId: string;
title: string;
}

/**
* Sidebar that renders Align Sidebar (manage tags sidebar)
* for the given content.
*/
export const AlignSidebar = ({ contentId, title }: AlignSidebarProps) => (
<div>
<SidebarTitle
title={title}
icon={SchoolOutline}
/>
<ContentTagsDrawer
id={contentId}
variant="component"
/>
</div>
);