From 2ab5d3858a6c882106dd73acb72074ca31d51af6 Mon Sep 17 00:00:00 2001 From: Pramod S Date: Thu, 22 Aug 2024 14:17:56 +0200 Subject: [PATCH 1/4] removed initialMapping query call from asset search hook, now it should be handle outside by using all asset mapping hook --- react-components/src/index.ts | 3 +- .../useSearchMappedEquipmentAssetMappings.tsx | 91 +++++++------------ react-components/src/utilities/buildFilter.ts | 23 ++--- .../stories/SearchHooks.stories.tsx | 18 ++-- 4 files changed, 51 insertions(+), 84 deletions(-) diff --git a/react-components/src/index.ts b/react-components/src/index.ts index 986ad954ca5..5165d53b1b9 100644 --- a/react-components/src/index.ts +++ b/react-components/src/index.ts @@ -114,7 +114,8 @@ export { type AddImage360CollectionOptions, type AddResourceOptions, type AddCadResourceOptions, - type AddPointCloudResourceOptions + type AddPointCloudResourceOptions, + type CadModelOptions } from './components/Reveal3DResources/types'; export { type PointCloudAnnotationMappedAssetData, diff --git a/react-components/src/query/useSearchMappedEquipmentAssetMappings.tsx b/react-components/src/query/useSearchMappedEquipmentAssetMappings.tsx index 374b50a67ff..b62744b5281 100644 --- a/react-components/src/query/useSearchMappedEquipmentAssetMappings.tsx +++ b/react-components/src/query/useSearchMappedEquipmentAssetMappings.tsx @@ -48,8 +48,6 @@ export const useSearchMappedEquipmentAssetMappings = ( const sdk = useSDK(userSdk); const { data: assetMappingList, isFetched: isAssetMappingNodesFetched } = useAssetMappedNodesForRevisions(models.map((model) => ({ ...model, type: 'cad' }))); - const { data: initialAssetMappings, isLoading: isInitialAssetMappingsLoading } = - useAllMappedEquipmentAssetMappings(models, sdk); return useInfiniteQuery({ queryKey: [ @@ -60,38 +58,42 @@ export const useSearchMappedEquipmentAssetMappings = ( ...models.map((model) => [model.modelId, model.revisionId]) ], queryFn: async ({ pageParam }: { pageParam: string | undefined }) => { - if (initialAssetMappings === undefined) { - return { assets: [], nextCursor: undefined }; - } if (query === '') { - const assets = initialAssetMappings.pages.flatMap((modelWithAssets) => - modelWithAssets.modelsAssets.flatMap((modelsAsset) => modelsAsset.assets).flat() - ); - return { assets, nextCursor: undefined }; + return { assets: [], nextCursor: undefined }; } if (assetMappingList === undefined) { return { assets: [], nextCursor: undefined }; } - const assetsResponse = await getAssetsList(sdk, { - query, - limit, - cursor: pageParam - }); + const assets: Asset[] = []; + let nextCursor = pageParam; + let hasMore = true; + + while (assets.length < limit && hasMore) { + const assetsResponse = await getAssetsList(sdk, { + query, + limit, + cursor: nextCursor + }); - const assets = assetsResponse.items.filter(isDefined); - const filteredSearchedAssets = assetMappingList.flatMap((mapping) => { - return mapping.assetMappings - .filter((assetMapping) => assets.some((asset) => asset.id === assetMapping.assetId)) - .map((assetMapping) => assets.find((asset) => asset.id === assetMapping.assetId)) - .filter(isDefined); - }); + const fetchedAssets = assetsResponse.items.filter(isDefined); + const filteredSearchedAssets = assetMappingList.flatMap((mapping) => { + return mapping.assetMappings + .filter((assetMapping) => + fetchedAssets.some((asset) => asset.id === assetMapping.assetId) + ) + .map((assetMapping) => fetchedAssets.find((asset) => asset.id === assetMapping.assetId)) + .filter(isDefined); + }); + const uniqueAssets = uniq([...assets, ...filteredSearchedAssets]); - // Remove duplicates - const uniqueFilteredSearchedAssets = uniq(filteredSearchedAssets); + assets.push(...uniqueAssets); + nextCursor = assetsResponse.nextCursor; + hasMore = !(nextCursor === undefined || assets.length >= limit); + } return { - assets: uniqueFilteredSearchedAssets, - nextCursor: assetsResponse.nextCursor + assets, + nextCursor }; }, initialPageParam: undefined, @@ -101,10 +103,7 @@ export const useSearchMappedEquipmentAssetMappings = ( return lastPageData.nextCursor; }, enabled: - !isInitialAssetMappingsLoading && - isAssetMappingNodesFetched && - assetMappingList !== undefined && - assetMappingList.length > 0 + isAssetMappingNodesFetched && assetMappingList !== undefined && assetMappingList.length > 0 }); }; @@ -112,9 +111,8 @@ export const useAllMappedEquipmentAssetMappings = ( models: AddModelOptions[], userSdk?: CogniteClient, limit: number = 1000 -): UseInfiniteQueryResult, Error> => { +): UseInfiniteQueryResult, Error> => { const sdk = useSDK(userSdk); - const usedCursors = useRef(new Set()); return useInfiniteQuery({ queryKey: [ @@ -129,13 +127,11 @@ export const useAllMappedEquipmentAssetMappings = ( cursor: string | 'start' | undefined; model: AddModelOptions; }>; - const nextCursor = nextCursors.find( (nextCursor) => nextCursor.model.modelId === model.modelId && nextCursor.model.revisionId === model.revisionId )?.cursor; - if (nextCursor === undefined) { return { mappings: { items: [] }, model }; } @@ -145,43 +141,18 @@ export const useAllMappedEquipmentAssetMappings = ( limit }); - usedCursors.current.add(nextCursor); - return { mappings, model }; }); const currentPagesOfAssetMappings = await Promise.all(currentPagesOfAssetMappingsPromises); const modelsAssets = await getAssetsFromAssetMappings(sdk, currentPagesOfAssetMappings); - const nextCursors = currentPagesOfAssetMappings - .map(({ mappings }) => mappings.nextCursor) - .filter(isDefined); - return await Promise.resolve({ - modelsAssets, - nextCursors - }); + return modelsAssets; }, initialPageParam: models.map((model) => ({ cursor: 'start', model })), staleTime: Infinity, - getNextPageParam: (lastPage: { - modelsAssets: ModelMappingsWithAssets[]; - nextCursors: string[]; - }): Array<{ cursor: string | undefined; model: AddModelOptions }> | undefined => { - const nextCursors = lastPage.nextCursors - .map((cursor, index) => ({ cursor, model: lastPage.modelsAssets[index].model })) - .filter((mappingModel) => { - if (mappingModel.cursor === undefined || usedCursors.current.has(mappingModel.cursor)) { - return false; - } - usedCursors.current.add(mappingModel.cursor); - return true; - }); - if (nextCursors.length === 0) { - return undefined; - } - return nextCursors; - } + getNextPageParam }); }; diff --git a/react-components/src/utilities/buildFilter.ts b/react-components/src/utilities/buildFilter.ts index 7bd56fb27a3..540af4edc06 100644 --- a/react-components/src/utilities/buildFilter.ts +++ b/react-components/src/utilities/buildFilter.ts @@ -6,27 +6,16 @@ export const buildFilter = (query: string): any => { if (query === '') { return undefined; } - const conditions = ['search'] - .map((condition) => [ - { - [condition]: { - property: ['name'], - value: query - } - }, - { - [condition]: { - property: ['description'], - value: query - } - } - ]) - .flat(); + + const searchConditions = [ + { search: { property: ['name'], value: query } }, + { search: { property: ['description'], value: query } } + ]; return { and: [ { - or: conditions + or: searchConditions } ] }; diff --git a/react-components/stories/SearchHooks.stories.tsx b/react-components/stories/SearchHooks.stories.tsx index 85eb468b938..05f33c32332 100644 --- a/react-components/stories/SearchHooks.stories.tsx +++ b/react-components/stories/SearchHooks.stories.tsx @@ -126,7 +126,15 @@ const StoryContent = ({ resources }: { resources: AddResourceOptions[] }): React } else if (searchMethod === 'assetSearch' && !isAssetSearchFetching && assetSearchHasNextPage) { void fetchAssetSearchNextPage(); } - }, []); + }, [ + searchMethod, + isFetching, + hasNextPage, + fetchNextPage, + isAssetSearchFetching, + assetSearchHasNextPage, + fetchAssetSearchNextPage + ]); const filteredEquipment = useMemo(() => { if (searchMethod === 'allFdm') { @@ -152,9 +160,7 @@ const StoryContent = ({ resources }: { resources: AddResourceOptions[] }): React const transformedAssets = allAssets?.pages .flat() - .map((modelsAssetPage) => - modelsAssetPage.modelsAssets.flatMap((modelsAsset) => modelsAsset.assets) - ) + .map((mapping) => mapping.assets) .flat() ?? []; const all360ImageAssets = @@ -372,8 +378,8 @@ export const Main: Story = { siteId: 'celanese1' }, { - modelId: 5653798104332258, - revisionId: 5045518244111296 + modelId: 7646043527629245, + revisionId: 6059566106376463 } ] }, From 85a40236723ae7cdcec72d996e5f21ea3300bdf8 Mon Sep 17 00:00:00 2001 From: Pramod S Date: Thu, 22 Aug 2024 14:28:03 +0200 Subject: [PATCH 2/4] update variable using let to constant --- .../useSearchMappedEquipmentAssetMappings.tsx | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/react-components/src/query/useSearchMappedEquipmentAssetMappings.tsx b/react-components/src/query/useSearchMappedEquipmentAssetMappings.tsx index b62744b5281..77d786f7a42 100644 --- a/react-components/src/query/useSearchMappedEquipmentAssetMappings.tsx +++ b/react-components/src/query/useSearchMappedEquipmentAssetMappings.tsx @@ -1,7 +1,6 @@ /*! * Copyright 2023 Cognite AS */ -import { useRef } from 'react'; import { type AddModelOptions } from '@cognite/reveal'; import { type Asset, @@ -64,15 +63,14 @@ export const useSearchMappedEquipmentAssetMappings = ( if (assetMappingList === undefined) { return { assets: [], nextCursor: undefined }; } - const assets: Asset[] = []; - let nextCursor = pageParam; - let hasMore = true; - - while (assets.length < limit && hasMore) { + const fetchAssets = async ( + cursor: string | undefined, + accumulatedAssets: Asset[] + ): Promise<{ assets: Asset[]; nextCursor: string | undefined }> => { const assetsResponse = await getAssetsList(sdk, { query, limit, - cursor: nextCursor + cursor }); const fetchedAssets = assetsResponse.items.filter(isDefined); @@ -84,12 +82,17 @@ export const useSearchMappedEquipmentAssetMappings = ( .map((assetMapping) => fetchedAssets.find((asset) => asset.id === assetMapping.assetId)) .filter(isDefined); }); - const uniqueAssets = uniq([...assets, ...filteredSearchedAssets]); - assets.push(...uniqueAssets); - nextCursor = assetsResponse.nextCursor; - hasMore = !(nextCursor === undefined || assets.length >= limit); - } + const uniqueAssets = uniq([...accumulatedAssets, ...filteredSearchedAssets]); + + if (uniqueAssets.length >= limit || assetsResponse.nextCursor === undefined) { + return { assets: uniqueAssets, nextCursor: assetsResponse.nextCursor }; + } + + return await fetchAssets(assetsResponse.nextCursor, uniqueAssets); + }; + + const { assets, nextCursor } = await fetchAssets(pageParam, []); return { assets, From d13ebdb3e1642fba77cbfbf4d3d470b6d4a6cdea Mon Sep 17 00:00:00 2001 From: Pramod S Date: Thu, 22 Aug 2024 15:08:23 +0200 Subject: [PATCH 3/4] combined the check for no query string and undefined assetmappinglist in single if statement --- .../src/query/useSearchMappedEquipmentAssetMappings.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/react-components/src/query/useSearchMappedEquipmentAssetMappings.tsx b/react-components/src/query/useSearchMappedEquipmentAssetMappings.tsx index 77d786f7a42..ca021bdf0dd 100644 --- a/react-components/src/query/useSearchMappedEquipmentAssetMappings.tsx +++ b/react-components/src/query/useSearchMappedEquipmentAssetMappings.tsx @@ -57,12 +57,10 @@ export const useSearchMappedEquipmentAssetMappings = ( ...models.map((model) => [model.modelId, model.revisionId]) ], queryFn: async ({ pageParam }: { pageParam: string | undefined }) => { - if (query === '') { - return { assets: [], nextCursor: undefined }; - } - if (assetMappingList === undefined) { + if (query === '' || assetMappingList === undefined) { return { assets: [], nextCursor: undefined }; } + const fetchAssets = async ( cursor: string | undefined, accumulatedAssets: Asset[] From 7bbba83835a9a873c9ca588661d0bc5f123b1270 Mon Sep 17 00:00:00 2001 From: Pramod S Date: Thu, 22 Aug 2024 16:01:28 +0200 Subject: [PATCH 4/4] updated lodash unique to filter with safe type guard --- .../src/components/CacheProvider/AnnotationModelUtils.ts | 5 ++++- .../hooks/useExtractUniqueAssetIdsFromMapped.tsx | 2 +- .../src/query/useSearchAssetsMapped360Annotations.tsx | 5 ++++- .../src/query/useSearchMappedEquipmentAssetMappings.tsx | 7 +++++-- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/react-components/src/components/CacheProvider/AnnotationModelUtils.ts b/react-components/src/components/CacheProvider/AnnotationModelUtils.ts index e6c164b3461..cb92a0e63dc 100644 --- a/react-components/src/components/CacheProvider/AnnotationModelUtils.ts +++ b/react-components/src/components/CacheProvider/AnnotationModelUtils.ts @@ -23,7 +23,10 @@ export async function fetchPointCloudAnnotationAssets( }); const filteredAnnotationMapping = annotationMapping.filter(isDefined); - const uniqueAnnotationMapping = uniqBy(filteredAnnotationMapping, 'assetId'); + const uniqueAnnotationMapping = uniqBy( + filteredAnnotationMapping, + (annotationMapping) => annotationMapping.assetId + ); const assetIds = uniqueAnnotationMapping.map((mapping) => mapping.assetId); const assets = await fetchAssetForAssetIds(assetIds, sdk); diff --git a/react-components/src/components/RuleBasedOutputs/hooks/useExtractUniqueAssetIdsFromMapped.tsx b/react-components/src/components/RuleBasedOutputs/hooks/useExtractUniqueAssetIdsFromMapped.tsx index 60c65908077..e9f9f6ed1f3 100644 --- a/react-components/src/components/RuleBasedOutputs/hooks/useExtractUniqueAssetIdsFromMapped.tsx +++ b/react-components/src/components/RuleBasedOutputs/hooks/useExtractUniqueAssetIdsFromMapped.tsx @@ -17,7 +17,7 @@ export const useExtractUniqueAssetIdsFromMapped = ( id: item.assetId }; }); - const uniqueAssetIds = uniqBy(assetIds, 'id'); + const uniqueAssetIds = uniqBy(assetIds, (assetId) => assetId.id); return uniqueAssetIds; }, [assetMappings]); }; diff --git a/react-components/src/query/useSearchAssetsMapped360Annotations.tsx b/react-components/src/query/useSearchAssetsMapped360Annotations.tsx index ffb308434f5..827ce111b4e 100644 --- a/react-components/src/query/useSearchAssetsMapped360Annotations.tsx +++ b/react-components/src/query/useSearchAssetsMapped360Annotations.tsx @@ -116,7 +116,10 @@ async function get360AnnotationAssets( }) .filter(isDefined); - const uniqueAnnotationMapping = uniqBy(filteredAnnotationMappings, 'assetId'); + const uniqueAnnotationMapping = uniqBy( + filteredAnnotationMappings, + (annotationMapping) => annotationMapping.assetId + ); const assets = await retrieveAssets(sdk, uniqueAnnotationMapping); const flatAssets = assets.flat(); diff --git a/react-components/src/query/useSearchMappedEquipmentAssetMappings.tsx b/react-components/src/query/useSearchMappedEquipmentAssetMappings.tsx index ca021bdf0dd..34244a5159a 100644 --- a/react-components/src/query/useSearchMappedEquipmentAssetMappings.tsx +++ b/react-components/src/query/useSearchMappedEquipmentAssetMappings.tsx @@ -17,7 +17,7 @@ import { useSDK } from '../components/RevealCanvas/SDKProvider'; import { getAssetsList } from '../hooks/network/getAssetsList'; import { useAssetMappedNodesForRevisions } from '../components/CacheProvider/AssetMappingAndNode3DCacheProvider'; import { isDefined } from '../utilities/isDefined'; -import { uniq } from 'lodash'; +import { uniqBy } from 'lodash'; export type ModelMappings = { model: AddModelOptions; @@ -81,7 +81,10 @@ export const useSearchMappedEquipmentAssetMappings = ( .filter(isDefined); }); - const uniqueAssets = uniq([...accumulatedAssets, ...filteredSearchedAssets]); + const uniqueAssets = uniqBy( + [...accumulatedAssets, ...filteredSearchedAssets], + (asset) => asset.id + ); if (uniqueAssets.length >= limit || assetsResponse.nextCursor === undefined) { return { assets: uniqueAssets, nextCursor: assetsResponse.nextCursor };