fix: Refresh section list on subsection page (#2103)
Invalidates the query in the subsection page used to get the list of sections that contains the subsection
This commit is contained in:
@@ -311,6 +311,26 @@ describe('library api hooks', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should invalidate subsection when added to section', async () => {
|
||||
const spy = jest.spyOn(queryClient, 'invalidateQueries');
|
||||
const subsectionId1 = 'lct:org:lib:subsection:1';
|
||||
const subsectionId2 = 'lct:org:lib:subsection:2';
|
||||
const sectionId = 'lct:org:lib:section:1';
|
||||
const url = getLibraryContainerChildrenApiUrl(sectionId);
|
||||
|
||||
axiosMock.onPost(url).reply(200);
|
||||
|
||||
const { result } = renderHook(() => useAddItemsToContainer(sectionId), { wrapper });
|
||||
|
||||
await result.current.mutateAsync([subsectionId1, subsectionId2]);
|
||||
|
||||
expect(axiosMock.history.post[0].url).toEqual(url);
|
||||
|
||||
// Two call for `containerChildren` and library predicate
|
||||
// and two more calls to invalidate the subsections.
|
||||
expect(spy).toHaveBeenCalledTimes(4);
|
||||
});
|
||||
|
||||
describe('publishContainer', () => {
|
||||
it('should publish a container', async () => {
|
||||
const containerId = 'lct:org:lib:unit:1';
|
||||
|
||||
@@ -8,11 +8,12 @@ import {
|
||||
replaceEqualDeep,
|
||||
} from '@tanstack/react-query';
|
||||
import { useCallback } from 'react';
|
||||
import { type MeiliSearch } from 'meilisearch';
|
||||
|
||||
import { getLibraryId } from '../../generic/key-utils';
|
||||
import { getBlockType, getLibraryId } from '../../generic/key-utils';
|
||||
import * as api from './api';
|
||||
import { VersionSpec } from '../LibraryBlock';
|
||||
import { useContentSearchConnection, useContentSearchResults } from '../../search-manager';
|
||||
import { useContentSearchConnection, useContentSearchResults, buildSearchQueryKey } from '../../search-manager';
|
||||
|
||||
export const libraryQueryPredicate = (query: Query, libraryId: string): boolean => {
|
||||
// Invalidate all content queries related to this library.
|
||||
@@ -697,11 +698,34 @@ export const useContainerChildren = (containerId?: string, published: boolean =
|
||||
})
|
||||
);
|
||||
|
||||
/**
|
||||
* If you work with `useContentFromSearchIndex`, you can use this
|
||||
* function to get the query key, usually to invalidate the query.
|
||||
*/
|
||||
const getSearchQueryKeyFromContent = (
|
||||
contentIds: string[],
|
||||
client?: MeiliSearch,
|
||||
indexName?: string,
|
||||
) => (
|
||||
buildSearchQueryKey({
|
||||
client,
|
||||
indexName,
|
||||
extraFilter: [`usage_key IN ["${contentIds.join('","')}"]`],
|
||||
searchKeywords: '',
|
||||
blockTypesFilter: [],
|
||||
problemTypesFilter: [],
|
||||
publishStatusFilter: [],
|
||||
tagsFilter: [],
|
||||
sort: [],
|
||||
})
|
||||
);
|
||||
|
||||
/**
|
||||
* Use this mutation to add items to a container
|
||||
*/
|
||||
export const useAddItemsToContainer = (containerId?: string) => {
|
||||
const queryClient = useQueryClient();
|
||||
const { client, indexName } = useContentSearchConnection();
|
||||
return useMutation({
|
||||
mutationFn: async (itemIds: string[]) => {
|
||||
// istanbul ignore if: this should never happen
|
||||
@@ -710,7 +734,7 @@ export const useAddItemsToContainer = (containerId?: string) => {
|
||||
}
|
||||
return api.addComponentsToContainer(containerId, itemIds);
|
||||
},
|
||||
onSettled: () => {
|
||||
onSettled: (_data, _error, variables) => {
|
||||
// istanbul ignore if: this should never happen
|
||||
if (!containerId) {
|
||||
return;
|
||||
@@ -720,6 +744,17 @@ export const useAddItemsToContainer = (containerId?: string) => {
|
||||
const libraryId = getLibraryId(containerId);
|
||||
queryClient.invalidateQueries({ queryKey: libraryAuthoringQueryKeys.containerChildren(containerId) });
|
||||
queryClient.invalidateQueries({ predicate: (query) => libraryQueryPredicate(query, libraryId) });
|
||||
|
||||
const containerType = getBlockType(containerId);
|
||||
if (containerType === 'section') {
|
||||
// We invalidate the search query of the each itemId if the container is a section.
|
||||
// This because the subsection page calls this query individually.
|
||||
variables.forEach((itemId) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: getSearchQueryKeyFromContent([itemId], client, indexName),
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@@ -44,6 +44,43 @@ export const useContentSearchConnection = (): {
|
||||
return { client, indexName, hasConnectionError };
|
||||
};
|
||||
|
||||
export const buildSearchQueryKey = ({
|
||||
client,
|
||||
indexName,
|
||||
extraFilter,
|
||||
searchKeywords,
|
||||
blockTypesFilter,
|
||||
problemTypesFilter,
|
||||
publishStatusFilter,
|
||||
tagsFilter,
|
||||
sort,
|
||||
}: {
|
||||
client?: MeiliSearch;
|
||||
indexName?: string;
|
||||
extraFilter?: Filter;
|
||||
searchKeywords: string;
|
||||
blockTypesFilter: string[];
|
||||
problemTypesFilter: string[];
|
||||
publishStatusFilter: PublishStatus[];
|
||||
tagsFilter: string[];
|
||||
sort: SearchSortOption[];
|
||||
}) => (
|
||||
[
|
||||
'content_search',
|
||||
'results',
|
||||
client?.config.apiKey,
|
||||
client?.config.host,
|
||||
indexName,
|
||||
extraFilter,
|
||||
searchKeywords,
|
||||
blockTypesFilter,
|
||||
problemTypesFilter,
|
||||
publishStatusFilter,
|
||||
tagsFilter,
|
||||
sort,
|
||||
]
|
||||
);
|
||||
|
||||
/**
|
||||
* Get the results of a search
|
||||
*/
|
||||
@@ -87,11 +124,8 @@ export const useContentSearchResults = ({
|
||||
}) => {
|
||||
const query = useInfiniteQuery({
|
||||
enabled: enabled && client !== undefined && indexName !== undefined,
|
||||
queryKey: [
|
||||
'content_search',
|
||||
'results',
|
||||
client?.config.apiKey,
|
||||
client?.config.host,
|
||||
queryKey: buildSearchQueryKey({
|
||||
client,
|
||||
indexName,
|
||||
extraFilter,
|
||||
searchKeywords,
|
||||
@@ -100,7 +134,7 @@ export const useContentSearchResults = ({
|
||||
publishStatusFilter,
|
||||
tagsFilter,
|
||||
sort,
|
||||
],
|
||||
}),
|
||||
queryFn: ({ pageParam = 0 }) => {
|
||||
// istanbul ignore if: this should never happen
|
||||
if (client === undefined || indexName === undefined) {
|
||||
|
||||
@@ -9,7 +9,12 @@ export { default as SearchKeywordsField } from './SearchKeywordsField';
|
||||
export { default as SearchSortWidget } from './SearchSortWidget';
|
||||
export { default as Stats } from './Stats';
|
||||
export { HIGHLIGHT_PRE_TAG, HIGHLIGHT_POST_TAG, PublishStatus } from './data/api';
|
||||
export { useContentSearchConnection, useContentSearchResults, useGetBlockTypes } from './data/apiHooks';
|
||||
export {
|
||||
useContentSearchConnection,
|
||||
useContentSearchResults,
|
||||
useGetBlockTypes,
|
||||
buildSearchQueryKey,
|
||||
} from './data/apiHooks';
|
||||
export { TypesFilterData } from './hooks';
|
||||
|
||||
export type {
|
||||
|
||||
Reference in New Issue
Block a user