Skip to content

Commit c0aab46

Browse files
committed
feat: collection sidebar
1 parent 29a01c4 commit c0aab46

File tree

10 files changed

+126
-49
lines changed

10 files changed

+126
-49
lines changed

src/library-authoring/LibraryAuthoringPage.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import {
2828
SearchSortWidget,
2929
} from '../search-manager';
3030
import LibraryComponents from './components/LibraryComponents';
31-
import LibraryCollections from './LibraryCollections';
31+
import LibraryCollections from './collections/LibraryCollections';
3232
import LibraryHome from './LibraryHome';
3333
import { useContentLibrary } from './data/apiHooks';
3434
import { LibrarySidebar } from './library-sidebar';

src/library-authoring/LibraryHome.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { useIntl } from '@edx/frontend-platform/i18n';
44

55
import { useSearchContext } from '../search-manager';
66
import { NoComponents, NoSearchResults } from './EmptyStates';
7-
import LibraryCollections from './LibraryCollections';
7+
import LibraryCollections from './collections/LibraryCollections';
88
import { LibraryComponents } from './components';
99
import LibrarySection from './components/LibrarySection';
1010
import LibraryRecentlyModified from './LibraryRecentlyModified';

src/library-authoring/LibraryLayout.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { LibraryProvider } from './common/context';
1414
import { CreateCollectionModal } from './create-collection';
1515
import { invalidateComponentData } from './data/apiHooks';
1616
import LibraryCollectionPageWrapper from './LibraryCollectionPage';
17+
import LibraryCollectionPageWrapper from './collections/LibraryCollectionPage';
1718

1819
const LibraryLayout = () => {
1920
const { libraryId } = useParams();
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import React from 'react';
2+
import { useIntl } from '@edx/frontend-platform/i18n';
3+
import {
4+
Tab,
5+
Tabs,
6+
Stack,
7+
} from '@openedx/paragon';
8+
9+
import messages from './messages';
10+
import { useCollection } from '../data/apiHooks';
11+
import Loading from '../../generic/Loading';
12+
13+
interface CollectionInfoProps {
14+
collectionId: string;
15+
libraryId: string;
16+
}
17+
18+
const CollectionInfo = ({ libraryId, collectionId } : CollectionInfoProps) => {
19+
const intl = useIntl();
20+
const { data: collectionData, isLoading: isCollectionLoading } = useCollection(libraryId, collectionId);
21+
22+
if (isCollectionLoading) {
23+
return <Loading />;
24+
}
25+
26+
return (
27+
<Stack>
28+
<div className="d-flex flex-wrap">
29+
{collectionData?.title}
30+
</div>
31+
<Tabs
32+
variant="tabs"
33+
className="my-3 d-flex justify-content-around"
34+
defaultActiveKey="manage"
35+
>
36+
<Tab eventKey="manage" title={intl.formatMessage(messages.manageTabTitle)}>
37+
Manage tab placeholder
38+
</Tab>
39+
<Tab eventKey="details" title={intl.formatMessage(messages.detailsTabTitle)}>
40+
Details tab placeholder
41+
</Tab>
42+
</Tabs>
43+
</Stack>
44+
);
45+
};
46+
47+
export default CollectionInfo;

src/library-authoring/LibraryCollectionPage.tsx renamed to src/library-authoring/collections/LibraryCollectionPage.tsx

Lines changed: 31 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import React, { useContext } from 'react';
2-
import classNames from 'classnames';
1+
import React, { useContext, useEffect } from 'react';
32
import { StudioFooter } from '@edx/frontend-component-footer';
43
import { useIntl } from '@edx/frontend-platform/i18n';
54
import {
@@ -14,21 +13,22 @@ import {
1413
import { Add, InfoOutline } from '@openedx/paragon/icons';
1514
import { Link, useParams } from 'react-router-dom';
1615

17-
import Loading from '../generic/Loading';
18-
import SubHeader from '../generic/sub-header/SubHeader';
19-
import Header from '../header';
20-
import NotFoundAlert from '../generic/NotFoundAlert';
16+
import Loading from '../../generic/Loading';
17+
import SubHeader from '../../generic/sub-header/SubHeader';
18+
import Header from '../../header';
19+
import NotFoundAlert from '../../generic/NotFoundAlert';
2120
import {
2221
ClearFiltersButton,
2322
FilterByBlockType,
2423
FilterByTags,
2524
SearchContextProvider,
2625
SearchKeywordsField,
2726
SearchSortWidget,
28-
} from '../search-manager';
29-
import { useCollection, useContentLibrary } from './data/apiHooks';
30-
import { LibraryContext, SidebarBodyComponentId } from './common/context';
31-
import messages from './messages';
27+
} from '../../search-manager';
28+
import { useCollection, useContentLibrary } from '../data/apiHooks';
29+
import { LibraryContext } from '../common/context';
30+
import messages from '../messages';
31+
import { LibrarySidebar } from '../library-sidebar';
3232

3333
interface HeaderActionsProps {
3434
canEditLibrary: boolean;
@@ -38,40 +38,14 @@ const HeaderActions = ({ canEditLibrary }: HeaderActionsProps) => {
3838
const intl = useIntl();
3939
const {
4040
openAddContentSidebar,
41-
openInfoSidebar,
42-
closeLibrarySidebar,
43-
sidebarBodyComponent,
4441
} = useContext(LibraryContext);
4542

4643
if (!canEditLibrary) {
4744
return null;
4845
}
4946

50-
const infoSidebarIsOpen = () => (
51-
sidebarBodyComponent === SidebarBodyComponentId.Info
52-
);
53-
54-
const handleOnClickInfoSidebar = () => {
55-
if (infoSidebarIsOpen()) {
56-
closeLibrarySidebar();
57-
} else {
58-
openInfoSidebar();
59-
}
60-
};
61-
6247
return (
6348
<div className="header-actions">
64-
<Button
65-
className={classNames('mr-1', {
66-
'normal-border': !infoSidebarIsOpen(),
67-
'open-border': infoSidebarIsOpen(),
68-
})}
69-
iconBefore={InfoOutline}
70-
variant="outline-primary rounded-0"
71-
onClick={handleOnClickInfoSidebar}
72-
>
73-
{intl.formatMessage(messages.libraryInfoButton)}
74-
</Button>
7549
<Button
7650
className="ml-1"
7751
iconBefore={Add}
@@ -85,7 +59,7 @@ const HeaderActions = ({ canEditLibrary }: HeaderActionsProps) => {
8559
);
8660
};
8761

88-
const SubHeaderTitle = ({ title, canEditLibrary }: { title: string, canEditLibrary: boolean }) => {
62+
const SubHeaderTitle = ({ title, canEditLibrary, infoClickHandler }: { title: string, canEditLibrary: boolean, infoClickHandler: () => void }) => {
8963
const intl = useIntl();
9064

9165
return (
@@ -96,7 +70,7 @@ const SubHeaderTitle = ({ title, canEditLibrary }: { title: string, canEditLibra
9670
src={InfoOutline}
9771
iconAs={Icon}
9872
alt={intl.formatMessage(messages.collectionInfoButton)}
99-
onClick={() => {}}
73+
onClick={infoClickHandler}
10074
variant="primary"
10175
/>
10276
</Stack>
@@ -114,6 +88,15 @@ const SubHeaderTitle = ({ title, canEditLibrary }: { title: string, canEditLibra
11488
const LibraryCollectionPage = ({ libraryId, collectionId }: { libraryId: string, collectionId: string }) => {
11589
const intl = useIntl();
11690

91+
const {
92+
sidebarBodyComponent,
93+
openCollectionInfoSidebar,
94+
} = useContext(LibraryContext);
95+
96+
useEffect(() => {
97+
openCollectionInfoSidebar(collectionId);
98+
}, []);
99+
117100
const { data: libraryData, isLoading: isLibLoading } = useContentLibrary(libraryId);
118101
const { data: collectionData, isLoading: isCollectionLoading } = useCollection(libraryId, collectionId);
119102

@@ -153,7 +136,11 @@ const LibraryCollectionPage = ({ libraryId, collectionId }: { libraryId: string,
153136
/>
154137
<Container size="xl" className="px-4 mt-4 mb-5 library-authoring-page">
155138
<SubHeader
156-
title={<SubHeaderTitle title={collectionData.title} canEditLibrary={libraryData.canEditLibrary} />}
139+
title={<SubHeaderTitle
140+
title={collectionData.title}
141+
canEditLibrary={libraryData.canEditLibrary}
142+
infoClickHandler={() => openCollectionInfoSidebar(collectionId)}
143+
/>}
157144
breadcrumbs={(
158145
<Breadcrumb
159146
ariaLabel={intl.formatMessage(messages.allCollections)}
@@ -174,6 +161,11 @@ const LibraryCollectionPage = ({ libraryId, collectionId }: { libraryId: string,
174161
</Container>
175162
<StudioFooter />
176163
</div>
164+
{ !!sidebarBodyComponent && (
165+
<div className="library-authoring-sidebar box-shadow-left-1 bg-white" data-testid="library-sidebar">
166+
<LibrarySidebar library={libraryData} />
167+
</div>
168+
)}
177169
</div>
178170
);
179171
};

src/library-authoring/LibraryCollections.tsx renamed to src/library-authoring/collections/LibraryCollections.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { CardGrid } from '@openedx/paragon';
22

3-
import { useLoadOnScroll } from '../hooks';
4-
import { useSearchContext } from '../search-manager';
5-
import { NoComponents, NoSearchResults } from './EmptyStates';
6-
import CollectionCard from './components/CollectionCard';
7-
import { LIBRARY_SECTION_PREVIEW_LIMIT } from './components/LibrarySection';
3+
import { useLoadOnScroll } from '../../hooks';
4+
import { useSearchContext } from '../../search-manager';
5+
import { NoComponents, NoSearchResults } from '../EmptyStates';
6+
import CollectionCard from '../components/CollectionCard';
7+
import { LIBRARY_SECTION_PREVIEW_LIMIT } from '../components/LibrarySection';
88

99
type LibraryCollectionsProps = {
1010
variant: 'full' | 'preview',
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default as CollectionInfo } from './CollectionInfo';
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { defineMessages } from '@edx/frontend-platform/i18n';
2+
3+
const messages = defineMessages({
4+
manageTabTitle: {
5+
id: 'course-authoring.library-authoring.collections-sidebar.manage-tab.title',
6+
defaultMessage: 'Manage',
7+
description: 'Title for manage tab',
8+
},
9+
detailsTabTitle: {
10+
id: 'course-authoring.library-authoring.collections-sidebar.details-tab.title',
11+
defaultMessage: 'Details',
12+
description: 'Title for details tab',
13+
},
14+
});
15+
16+
export default messages;

src/library-authoring/common/context.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export enum SidebarBodyComponentId {
55
AddContent = 'add-content',
66
Info = 'info',
77
ComponentInfo = 'component-info',
8+
CollectionInfo = 'collection-info',
89
}
910

1011
export interface LibraryContextData {
@@ -17,6 +18,7 @@ export interface LibraryContextData {
1718
isCreateCollectionModalOpen: boolean;
1819
openCreateCollectionModal: () => void;
1920
closeCreateCollectionModal: () => void;
21+
openCollectionInfoSidebar: (collectionId: string) => void;
2022
}
2123

2224
export const LibraryContext = React.createContext({
@@ -28,6 +30,7 @@ export const LibraryContext = React.createContext({
2830
isCreateCollectionModalOpen: false,
2931
openCreateCollectionModal: () => {},
3032
closeCreateCollectionModal: () => {},
33+
openCollectionInfoSidebar: (_collectionId: string) => {}, // eslint-disable-line @typescript-eslint/no-unused-vars
3134
} as LibraryContextData);
3235

3336
/**
@@ -37,6 +40,7 @@ export const LibraryProvider = (props: { children?: React.ReactNode }) => {
3740
const [sidebarBodyComponent, setSidebarBodyComponent] = React.useState<SidebarBodyComponentId | null>(null);
3841
const [currentComponentUsageKey, setCurrentComponentUsageKey] = React.useState<string>();
3942
const [isCreateCollectionModalOpen, openCreateCollectionModal, closeCreateCollectionModal] = useToggle(false);
43+
const [currentComponentKey, setCurrentComponentKey] = React.useState<string>();
4044

4145
const closeLibrarySidebar = React.useCallback(() => {
4246
setSidebarBodyComponent(null);
@@ -57,6 +61,13 @@ export const LibraryProvider = (props: { children?: React.ReactNode }) => {
5761
},
5862
[],
5963
);
64+
const openCollectionInfoSidebar = React.useCallback(
65+
(collectionId: string) => {
66+
setCurrentComponentKey(collectionId);
67+
setSidebarBodyComponent(SidebarBodyComponentId.CollectionInfo);
68+
},
69+
[],
70+
);
6071

6172
const context = React.useMemo(() => ({
6273
sidebarBodyComponent,
@@ -68,6 +79,7 @@ export const LibraryProvider = (props: { children?: React.ReactNode }) => {
6879
isCreateCollectionModalOpen,
6980
openCreateCollectionModal,
7081
closeCreateCollectionModal,
82+
openCollectionInfoSidebar,
7183
}), [
7284
sidebarBodyComponent,
7385
closeLibrarySidebar,
@@ -78,6 +90,7 @@ export const LibraryProvider = (props: { children?: React.ReactNode }) => {
7890
isCreateCollectionModalOpen,
7991
openCreateCollectionModal,
8092
closeCreateCollectionModal,
93+
openCollectionInfoSidebar,
8194
]);
8295

8396
return (

src/library-authoring/library-sidebar/LibrarySidebar.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { LibraryContext, SidebarBodyComponentId } from '../common/context';
1212
import { LibraryInfo, LibraryInfoHeader } from '../library-info';
1313
import { ComponentInfo, ComponentInfoHeader } from '../component-info';
1414
import { ContentLibrary } from '../data/api';
15+
import { CollectionInfo } from '../collections';
1516

1617
type LibrarySidebarProps = {
1718
library: ContentLibrary,
@@ -31,14 +32,17 @@ const LibrarySidebar = ({ library }: LibrarySidebarProps) => {
3132
const {
3233
sidebarBodyComponent,
3334
closeLibrarySidebar,
34-
currentComponentUsageKey,
35+
currentComponentKey,
3536
} = useContext(LibraryContext);
3637

3738
const bodyComponentMap = {
3839
[SidebarBodyComponentId.AddContent]: <AddContentContainer />,
3940
[SidebarBodyComponentId.Info]: <LibraryInfo library={library} />,
4041
[SidebarBodyComponentId.ComponentInfo]: (
41-
currentComponentUsageKey && <ComponentInfo usageKey={currentComponentUsageKey} />
42+
currentComponentKey && <ComponentInfo usageKey={currentComponentKey} />
43+
),
44+
[SidebarBodyComponentId.CollectionInfo]: (
45+
currentComponentKey && <CollectionInfo libraryId={library.id} collectionId={currentComponentKey} />
4246
),
4347
unknown: null,
4448
};
@@ -47,8 +51,11 @@ const LibrarySidebar = ({ library }: LibrarySidebarProps) => {
4751
[SidebarBodyComponentId.AddContent]: <AddContentHeader />,
4852
[SidebarBodyComponentId.Info]: <LibraryInfoHeader library={library} />,
4953
[SidebarBodyComponentId.ComponentInfo]: (
50-
currentComponentUsageKey && <ComponentInfoHeader library={library} usageKey={currentComponentUsageKey} />
54+
currentComponentKey && <ComponentInfoHeader library={library} usageKey={currentComponentKey} />
5155
),
56+
//[SidebarBodyComponentId.CollectionInfo]: (
57+
// currentComponentKey && <CollectionInfoHeader library={library} collectionId={currentComponentKey} />
58+
//),
5259
unknown: null,
5360
};
5461

0 commit comments

Comments
 (0)