Skip to content
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
69 changes: 35 additions & 34 deletions src/library-authoring/LibraryAuthoringPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import {
} from '../search-manager';
import LibraryContent from './LibraryContent';
import { LibrarySidebar } from './library-sidebar';
import { useComponentPickerContext } from './common/context/ComponentPickerContext';
import { useComponentPickerContext, CollectionIndexProvider } from './common/context/ComponentPickerContext';
import { useLibraryContext } from './common/context/LibraryContext';
import { SidebarBodyComponentId, useSidebarContext } from './common/context/SidebarContext';
import { allLibraryPageTabs, ContentType, useLibraryRoutes } from './routes';
Expand Down Expand Up @@ -233,10 +233,9 @@ const LibraryAuthoringPage = ({

const activeTypeFilters = {
components: 'type = "library_block"',
collections: 'type = "collection"',
units: 'block_type = "unit"',
};
if (activeKey !== ContentType.home) {
if (activeKey !== ContentType.home && activeKey !== ContentType.collections) {
extraFilter.push(activeTypeFilters[activeKey]);
}

Expand Down Expand Up @@ -285,38 +284,40 @@ const LibraryAuthoringPage = ({
extraFilter={extraFilter}
overrideTypesFilter={overrideTypesFilter}
>
<SubHeader
title={<SubHeaderTitle title={libraryData.title} />}
subtitle={!componentPickerMode ? intl.formatMessage(messages.headingSubtitle) : undefined}
breadcrumbs={breadcumbs}
headerActions={<HeaderActions />}
hideBorder
/>
<Tabs
variant="tabs"
activeKey={activeKey}
onSelect={handleTabChange}
className="my-3"
>
{visibleTabsToRender}
</Tabs>
<ActionRow className="my-3">
<SearchKeywordsField className="mr-3" />
<FilterByTags />
{!(insideCollections || insideUnits) && <FilterByBlockType />}
<LibraryFilterByPublished key={
// It is necessary to re-render `LibraryFilterByPublished` every time `FilterByBlockType`
// appears or disappears, this is because when the menu is opened it is rendered
// in a previous state, causing an inconsistency in its position.
// By changing the key we can re-render the component.
!(insideCollections || insideUnits) ? 'filter-published-1' : 'filter-published-2'
}
<CollectionIndexProvider>
<SubHeader
title={<SubHeaderTitle title={libraryData.title} />}
subtitle={!componentPickerMode ? intl.formatMessage(messages.headingSubtitle) : undefined}
breadcrumbs={breadcumbs}
headerActions={<HeaderActions />}
hideBorder
/>
<ClearFiltersButton />
<ActionRow.Spacer />
<SearchSortWidget />
</ActionRow>
<LibraryContent contentType={activeKey} />
<Tabs
variant="tabs"
activeKey={activeKey}
onSelect={handleTabChange}
className="my-3"
>
{visibleTabsToRender}
</Tabs>
<ActionRow className="my-3">
<SearchKeywordsField className="mr-3" />
<FilterByTags />
{!(insideCollections || insideUnits) && <FilterByBlockType />}
<LibraryFilterByPublished key={
// It is necessary to re-render `LibraryFilterByPublished` every time `FilterByBlockType`
// appears or disappears, this is because when the menu is opened it is rendered
// in a previous state, causing an inconsistency in its position.
// By changing the key we can re-render the component.
!(insideCollections || insideUnits) ? 'filter-published-1' : 'filter-published-2'
}
/>
<ClearFiltersButton />
<ActionRow.Spacer />
<SearchSortWidget />
</ActionRow>
<LibraryContent contentType={activeKey} />
</CollectionIndexProvider>
</SearchContextProvider>
</Container>
{!componentPickerMode && <StudioFooterSlot containerProps={{ size: undefined }} />}
Expand Down
18 changes: 16 additions & 2 deletions src/library-authoring/LibraryContent.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect } from 'react';
import { useEffect, useMemo } from 'react';
import { LoadingSpinner } from '../generic/Loading';
import { useSearchContext } from '../search-manager';
import { NoComponents, NoSearchResults } from './EmptyStates';
Expand Down Expand Up @@ -43,6 +43,20 @@ const LibraryContent = ({ contentType = ContentType.home }: LibraryContentProps)
const { openCreateCollectionModal } = useLibraryContext();
const { openAddContentSidebar, openComponentInfoSidebar } = useSidebarContext();

/**
* Filter collections on the frontend to display only collection cards in the Collections tab.
* This approach is used instead of backend filtering to ensure that all components (including those
* within collections) remain available in the 'hits' array. This is necessary for the component
* selection workflow when adding components to xblocks by choosing the whole collection in Collections tab.
* Note: LibraryAuthoringPage.tsx has been modified to skip backend filtering for this purpose.
*/
const filteredHits = useMemo(
() => (contentType === ContentType.collections
? hits.filter((hit) => hit.type === 'collection')
: hits),
[hits, contentType],
);

useEffect(() => {
if (usageKey) {
openComponentInfoSidebar(usageKey);
Expand Down Expand Up @@ -76,7 +90,7 @@ const LibraryContent = ({ contentType = ContentType.home }: LibraryContentProps)

return (
<div className="library-cards-grid">
{hits.map((contentHit) => {
{filteredHits.map((contentHit) => {
const CardComponent = LibraryItemCard[contentHit.type] || ComponentCard;

return <CardComponent key={contentHit.id} hit={contentHit} />;
Expand Down
5 changes: 5 additions & 0 deletions src/library-authoring/__mocks__/library-search.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
},
{
"display_name": "Collection 2",
"block_id": "col2",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque et mi ac nisi accumsan imperdiet vitae at odio. Vivamus tempor nec lorem eget lacinia. Vivamus efficitur lacus non dapibus porta. Nulla venenatis luctus nisi id posuere. Sed sollicitudin magna a sem ultrices accumsan. Praesent volutpat tortor vitae luctus rutrum. Integer. Descrition 58",
"id": 2,
"type": "collection",
Expand Down Expand Up @@ -99,6 +100,7 @@
},
{
"display_name": "Collection 3",
"block_id": "col3",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque et mi ac nisi accumsan imperdiet vitae at odio. Vivamus tempor nec lorem eget lacinia. Vivamus efficitur lacus non dapibus porta. Nulla venenatis luctus nisi id posuere. Sed sollicitudin magna a sem ultrices accumsan. Praesent volutpat tortor vitae luctus rutrum. Integer. Descrition 57",
"id": 3,
"type": "collection",
Expand Down Expand Up @@ -131,6 +133,7 @@
},
{
"display_name": "Collection 4",
"block_id": "col4",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque et mi ac nisi accumsan imperdiet vitae at odio. Vivamus tempor nec lorem eget lacinia. Vivamus efficitur lacus non dapibus porta. Nulla venenatis luctus nisi id posuere. Sed sollicitudin magna a sem ultrices accumsan. Praesent volutpat tortor vitae luctus rutrum. Integer. Descrition 56",
"id": 4,
"type": "collection",
Expand Down Expand Up @@ -163,6 +166,7 @@
},
{
"display_name": "Collection 5",
"block_id": "col5",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque et mi ac nisi accumsan imperdiet vitae at odio. Vivamus tempor nec lorem eget lacinia. Vivamus efficitur lacus non dapibus porta. Nulla venenatis luctus nisi id posuere. Sed sollicitudin magna a sem ultrices accumsan. Praesent volutpat tortor vitae luctus rutrum. Integer. Descrition 55",
"id": 5,
"type": "collection",
Expand Down Expand Up @@ -195,6 +199,7 @@
},
{
"display_name": "Collection 6",
"block_id": "col6",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque et mi ac nisi accumsan imperdiet vitae at odio. Vivamus tempor nec lorem eget lacinia. Vivamus efficitur lacus non dapibus porta. Nulla venenatis luctus nisi id posuere. Sed sollicitudin magna a sem ultrices accumsan. Praesent volutpat tortor vitae luctus rutrum. Integer. Descrition 54",
"id": 6,
"type": "collection",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { useSearchContext } from '../../search-manager';
import messages from './messages';
import { useSidebarContext } from '../common/context/SidebarContext';
import LibraryContent from '../LibraryContent';
import { ContentType } from '../routes';

const LibraryCollectionComponents = () => {
const { totalHits: componentCount, isFiltered } = useSearchContext();
Expand All @@ -25,7 +24,7 @@ const LibraryCollectionComponents = () => {
return (
<Stack direction="vertical" gap={3}>
<h3 className="text-gray">Content ({componentCount})</h3>
<LibraryContent contentType={ContentType.collections} />
<LibraryContent />
</Stack>
);
};
Expand Down
36 changes: 19 additions & 17 deletions src/library-authoring/collections/LibraryCollectionPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import {
} from '../../search-manager';
import { SubHeaderTitle } from '../LibraryAuthoringPage';
import { useCollection, useContentLibrary } from '../data/apiHooks';
import { useComponentPickerContext } from '../common/context/ComponentPickerContext';
import { useComponentPickerContext, CollectionIndexProvider } from '../common/context/ComponentPickerContext';
import { useLibraryContext } from '../common/context/LibraryContext';
import { SidebarBodyComponentId, useSidebarContext } from '../common/context/SidebarContext';
import messages from './messages';
Expand Down Expand Up @@ -208,22 +208,24 @@ const LibraryCollectionPage = () => {
<SearchContextProvider
extraFilter={extraFilter}
>
<SubHeader
title={<SubHeaderTitle title={collectionData.title} />}
breadcrumbs={breadcrumbs}
headerActions={<HeaderActions />}
hideBorder
/>
<ActionRow className="my-3">
<SearchKeywordsField className="mr-3" />
<FilterByTags />
<FilterByBlockType />
<LibraryFilterByPublished />
<ClearFiltersButton />
<ActionRow.Spacer />
<SearchSortWidget />
</ActionRow>
<LibraryCollectionComponents />
<CollectionIndexProvider>
<SubHeader
title={<SubHeaderTitle title={collectionData.title} />}
breadcrumbs={breadcrumbs}
headerActions={<HeaderActions />}
hideBorder
/>
<ActionRow className="my-3">
<SearchKeywordsField className="mr-3" />
<FilterByTags />
<FilterByBlockType />
<LibraryFilterByPublished />
<ClearFiltersButton />
<ActionRow.Spacer />
<SearchSortWidget />
</ActionRow>
<LibraryCollectionComponents />
</CollectionIndexProvider>
</SearchContextProvider>
</Container>
{!componentPickerMode && <StudioFooterSlot containerProps={{ size: undefined }} />}
Expand Down
Loading
Loading