diff --git a/src/library-authoring/LibraryAuthoringPage.test.tsx b/src/library-authoring/LibraryAuthoringPage.test.tsx
index 9eaf0167d..d6e7f1c30 100644
--- a/src/library-authoring/LibraryAuthoringPage.test.tsx
+++ b/src/library-authoring/LibraryAuthoringPage.test.tsx
@@ -702,6 +702,34 @@ describe('', () => {
});
});
+ it('Disables Type filter on Collections tab', async () => {
+ await renderLibraryPage();
+
+ expect(await screen.findByText('Content library')).toBeInTheDocument();
+ expect((await screen.findAllByText(libraryTitle))[0]).toBeInTheDocument();
+ expect((await screen.findAllByText('Introduction to Testing'))[0]).toBeInTheDocument();
+ expect((await screen.findAllByText('Collection 1'))[0]).toBeInTheDocument();
+
+ // Filter by Text block type
+ fireEvent.click(screen.getByRole('button', { name: /type/i }));
+ fireEvent.click(screen.getByRole('checkbox', { name: /text/i }));
+ // Escape to close the Types filter drop-down and re-enable the tabs
+ fireEvent.keyDown(screen.getByRole('button', { name: /type/i }), { key: 'Escape' });
+
+ // Navigate to the collections tab
+ fireEvent.click(await screen.findByRole('tab', { name: 'Collections' }));
+ expect((await screen.findAllByText('Collection 1'))[0]).toBeInTheDocument();
+ // No Types filter shown
+ expect(screen.queryByRole('button', { name: /type/i })).not.toBeInTheDocument();
+
+ // Navigate to the components tab
+ fireEvent.click(screen.getByRole('tab', { name: 'Components' }));
+ // Text components should be shown
+ expect((await screen.findAllByText('Introduction to Testing'))[0]).toBeInTheDocument();
+ // Types filter is shown
+ expect(screen.getByRole('button', { name: /type/i })).toBeInTheDocument();
+ });
+
it('Shows an error if libraries V2 is disabled', async () => {
const { axiosMock } = initializeMocks();
axiosMock.onGet(getStudioHomeApiUrl()).reply(200, {
diff --git a/src/library-authoring/LibraryAuthoringPage.tsx b/src/library-authoring/LibraryAuthoringPage.tsx
index 13687987e..b952310f5 100644
--- a/src/library-authoring/LibraryAuthoringPage.tsx
+++ b/src/library-authoring/LibraryAuthoringPage.tsx
@@ -30,6 +30,7 @@ import {
SearchContextProvider,
SearchKeywordsField,
SearchSortWidget,
+ TypesFilterData,
} from '../search-manager';
import LibraryContent from './LibraryContent';
import { LibrarySidebar } from './library-sidebar';
@@ -220,6 +221,9 @@ const LibraryAuthoringPage = ({ returnToLibrarySelection }: LibraryAuthoringPage
extraFilter.push(activeTypeFilters[activeKey]);
}
+ // Disable filtering by block/problem type when viewing the Collections tab.
+ const overrideTypesFilter = insideCollections ? new TypesFilterData() : undefined;
+
return (
@@ -239,6 +243,7 @@ const LibraryAuthoringPage = ({ returnToLibrarySelection }: LibraryAuthoringPage
}
@@ -260,7 +265,7 @@ const LibraryAuthoringPage = ({ returnToLibrarySelection }: LibraryAuthoringPage
-
+ {!insideCollections && }
diff --git a/src/search-manager/FilterByBlockType.tsx b/src/search-manager/FilterByBlockType.tsx
index 16c0b1de1..0b5160d37 100644
--- a/src/search-manager/FilterByBlockType.tsx
+++ b/src/search-manager/FilterByBlockType.tsx
@@ -191,16 +191,12 @@ const FilterItem = ({ blockType, count } : FilterItemProps) => {
);
};
-interface FilterByBlockTypeProps {
- disabled?: boolean,
-}
/**
* A button with a dropdown that allows filtering the current search by component type (XBlock type)
* e.g. Limit results to "Text" (html) and "Problem" (problem) components.
* The button displays the first type selected, and a count of how many other types are selected, if more than one.
- * @param disabled - If true, the filter is disabled and hidden.
*/
-const FilterByBlockType: React.FC = ({ disabled = false }) => {
+const FilterByBlockType: React.FC> = () => {
const {
blockTypes,
typesFilter,
@@ -248,10 +244,6 @@ const FilterByBlockType: React.FC = ({ disabled = false
blockType => ({ label: }),
);
- if (disabled) {
- return null;
- }
-
return (
(undefined);
export const SearchContextProvider: React.FC<{
- extraFilter?: Filter;
+ extraFilter?: Filter,
+ overrideTypesFilter?: TypesFilterData,
overrideSearchSortOrder?: SearchSortOption
children: React.ReactNode,
closeSearchModal?: () => void,
skipBlockTypeFetch?: boolean,
skipUrlUpdate?: boolean,
}> = ({
- overrideSearchSortOrder, skipBlockTypeFetch, skipUrlUpdate, ...props
+ overrideTypesFilter,
+ overrideSearchSortOrder,
+ skipBlockTypeFetch,
+ skipUrlUpdate,
+ ...props
}) => {
// Search parameters can be set via the query string
// E.g. ?q=draft+text
@@ -69,13 +74,15 @@ export const SearchContextProvider: React.FC<{
// Block + problem types use alphanumeric plus a few other characters.
// E.g ?type=html&type=video&type=p.multiplechoiceresponse
- const [typesFilter, setTypesFilter] = useStateOrUrlSearchParam(
+ const [internalTypesFilter, setTypesFilter] = useStateOrUrlSearchParam(
new TypesFilterData(),
'type',
(value: string | null) => new TypesFilterData(value),
(value: TypesFilterData | undefined) => (value ? value.toString() : undefined),
skipUrlUpdate,
);
+ // Callers can override the types filter when searching, but we still preserve the user's selected state.
+ const typesFilter = overrideTypesFilter ?? internalTypesFilter;
// Tags can be almost any string value (see openedx-learning's RESERVED_TAG_CHARS)
// and multiple tags may be selected together.
diff --git a/src/search-manager/index.ts b/src/search-manager/index.ts
index e2d4188be..278a53715 100644
--- a/src/search-manager/index.ts
+++ b/src/search-manager/index.ts
@@ -9,5 +9,6 @@ export { default as SearchSortWidget } from './SearchSortWidget';
export { default as Stats } from './Stats';
export { HIGHLIGHT_PRE_TAG, HIGHLIGHT_POST_TAG } from './data/api';
export { useGetBlockTypes } from './data/apiHooks';
+export { TypesFilterData } from './hooks';
export type { CollectionHit, ContentHit, ContentHitTags } from './data/api';