Refacto views (#10272)
In this huge (sorry!) PR: - introducing objectMetadataItem in contextStore instead of objectMetadataId which is more convenient - splitting some big hooks into smaller parts to avoid re-renders - removing Effects to avoid re-renders (especially onViewChange) - making the view prefetch separate from favorites to avoid re-renders - making the view prefetch load a state and add selectors on top of it to avoir re-renders As a result, the performance is WAY better (I suspect the favorite implementation to trigger a lot of re-renders unfortunately). However, we are still facing a random app freeze on view creation. I could not investigate the root cause. As this seems to be already there in the precedent release, we can move forward but this seems a urgent follow up to me ==> EDIT: I've found the root cause after a few ours of deep dive... an infinite loop in RecordTableNoRecordGroupBodyEffect... prastoin edit: close https://github.com/twentyhq/twenty/issues/10253 --------- Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com> Co-authored-by: prastoin <paul@twenty.com>
This commit is contained in:
@ -1,10 +1,12 @@
|
||||
import { PrefetchRunQueriesEffect } from '@/prefetch/components/PrefetchRunQueriesEffect';
|
||||
import { PrefetchRunFavoriteQueriesEffect } from '@/prefetch/components/PrefetchRunFavoriteQueriesEffect';
|
||||
import { PrefetchRunViewQueryEffect } from '@/prefetch/components/PrefetchRunViewQueryEffect';
|
||||
import React from 'react';
|
||||
|
||||
export const PrefetchDataProvider = ({ children }: React.PropsWithChildren) => {
|
||||
return (
|
||||
<>
|
||||
<PrefetchRunQueriesEffect />
|
||||
<PrefetchRunFavoriteQueriesEffect />
|
||||
<PrefetchRunViewQueryEffect />
|
||||
{children}
|
||||
</>
|
||||
);
|
||||
|
||||
@ -0,0 +1,110 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useRecoilCallback, useRecoilValue, useSetRecoilState } from 'recoil';
|
||||
|
||||
import { currentUserState } from '@/auth/states/currentUserState';
|
||||
import { Favorite } from '@/favorites/types/Favorite';
|
||||
import { FavoriteFolder } from '@/favorites/types/FavoriteFolder';
|
||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
|
||||
import { findAllFavoritesFolderOperationSignatureFactory } from '@/prefetch/graphql/operation-signatures/factories/findAllFavoritesFolderOperationSignatureFactory';
|
||||
import { findAllFavoritesOperationSignatureFactory } from '@/prefetch/graphql/operation-signatures/factories/findAllFavoritesOperationSignatureFactory';
|
||||
import { prefetchFavoriteFoldersState } from '@/prefetch/states/prefetchFavoriteFoldersState';
|
||||
import { prefetchFavoritesState } from '@/prefetch/states/prefetchFavoritesState';
|
||||
import { prefetchIsLoadedFamilyState } from '@/prefetch/states/prefetchIsLoadedFamilyState';
|
||||
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
|
||||
import { useIsWorkspaceActivationStatusSuspended } from '@/workspace/hooks/useIsWorkspaceActivationStatusSuspended';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||
|
||||
export const PrefetchRunFavoriteQueriesEffect = () => {
|
||||
const currentUser = useRecoilValue(currentUserState);
|
||||
|
||||
const isWorkspaceSuspended = useIsWorkspaceActivationStatusSuspended();
|
||||
|
||||
const { objectMetadataItems } = useObjectMetadataItems();
|
||||
|
||||
const setIsPrefetchFavoritesLoaded = useSetRecoilState(
|
||||
prefetchIsLoadedFamilyState(PrefetchKey.AllFavorites),
|
||||
);
|
||||
|
||||
const setIsPrefetchFavoritesFoldersLoaded = useSetRecoilState(
|
||||
prefetchIsLoadedFamilyState(PrefetchKey.AllFavoritesFolders),
|
||||
);
|
||||
|
||||
const findAllFavoritesOperationSignature =
|
||||
findAllFavoritesOperationSignatureFactory({
|
||||
objectMetadataItem: objectMetadataItems.find(
|
||||
(item) => item.nameSingular === CoreObjectNameSingular.Favorite,
|
||||
),
|
||||
});
|
||||
|
||||
const findAllFavoriteFoldersOperationSignature =
|
||||
findAllFavoritesFolderOperationSignatureFactory({
|
||||
objectMetadataItem: objectMetadataItems.find(
|
||||
(item) => item.nameSingular === CoreObjectNameSingular.FavoriteFolder,
|
||||
),
|
||||
});
|
||||
|
||||
const { records: favorites } = useFindManyRecords({
|
||||
objectNameSingular: CoreObjectNameSingular.Favorite,
|
||||
filter: findAllFavoritesOperationSignature.variables.filter,
|
||||
recordGqlFields: findAllFavoritesOperationSignature.fields,
|
||||
skip: !currentUser || isWorkspaceSuspended,
|
||||
});
|
||||
|
||||
const { records: favoriteFolders } = useFindManyRecords({
|
||||
objectNameSingular: CoreObjectNameSingular.FavoriteFolder,
|
||||
filter: findAllFavoriteFoldersOperationSignature.variables.filter,
|
||||
recordGqlFields: findAllFavoriteFoldersOperationSignature.fields,
|
||||
skip: !currentUser || isWorkspaceSuspended,
|
||||
});
|
||||
|
||||
const setPrefetchFavoritesState = useRecoilCallback(
|
||||
({ set, snapshot }) =>
|
||||
(favorites: Favorite[]) => {
|
||||
const existingFavorites = snapshot
|
||||
.getLoadable(prefetchFavoritesState)
|
||||
.getValue();
|
||||
|
||||
if (!isDeeplyEqual(existingFavorites, favorites)) {
|
||||
set(prefetchFavoritesState, favorites);
|
||||
}
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
const setPrefetchFavoriteFoldersState = useRecoilCallback(
|
||||
({ set, snapshot }) =>
|
||||
(favoriteFolders: FavoriteFolder[]) => {
|
||||
const existingFavoriteFolders = snapshot
|
||||
.getLoadable(prefetchFavoriteFoldersState)
|
||||
.getValue();
|
||||
|
||||
if (!isDeeplyEqual(existingFavoriteFolders, favoriteFolders)) {
|
||||
set(prefetchFavoriteFoldersState, favoriteFolders);
|
||||
}
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (isDefined(favorites)) {
|
||||
setPrefetchFavoritesState(favorites as Favorite[]);
|
||||
setIsPrefetchFavoritesLoaded(true);
|
||||
}
|
||||
}, [favorites, setPrefetchFavoritesState, setIsPrefetchFavoritesLoaded]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isDefined(favoriteFolders)) {
|
||||
setPrefetchFavoriteFoldersState(favoriteFolders as FavoriteFolder[]);
|
||||
setIsPrefetchFavoritesFoldersLoaded(true);
|
||||
}
|
||||
}, [
|
||||
favoriteFolders,
|
||||
setPrefetchFavoriteFoldersState,
|
||||
setIsPrefetchFavoritesFoldersLoaded,
|
||||
]);
|
||||
|
||||
return <></>;
|
||||
};
|
||||
@ -1,70 +0,0 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { currentUserState } from '@/auth/states/currentUserState';
|
||||
import { Favorite } from '@/favorites/types/Favorite';
|
||||
import { FavoriteFolder } from '@/favorites/types/FavoriteFolder';
|
||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||
import { useCombinedFindManyRecords } from '@/object-record/multiple-objects/hooks/useCombinedFindManyRecords';
|
||||
import { PREFETCH_CONFIG } from '@/prefetch/constants/PrefetchConfig';
|
||||
import { useUpsertRecordsInCacheForPrefetchKey } from '@/prefetch/hooks/internal/useUpsertRecordsInCacheForPrefetchKey';
|
||||
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
|
||||
import { View } from '@/views/types/View';
|
||||
import { useIsWorkspaceActivationStatusSuspended } from '@/workspace/hooks/useIsWorkspaceActivationStatusSuspended';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
|
||||
export const PrefetchRunQueriesEffect = () => {
|
||||
const currentUser = useRecoilValue(currentUserState);
|
||||
|
||||
const isWorkspaceSuspended = useIsWorkspaceActivationStatusSuspended();
|
||||
|
||||
const { upsertRecordsInCache: upsertViewsInCache } =
|
||||
useUpsertRecordsInCacheForPrefetchKey<View>({
|
||||
prefetchKey: PrefetchKey.AllViews,
|
||||
});
|
||||
|
||||
const { upsertRecordsInCache: upsertFavoritesInCache } =
|
||||
useUpsertRecordsInCacheForPrefetchKey<Favorite>({
|
||||
prefetchKey: PrefetchKey.AllFavorites,
|
||||
});
|
||||
const { upsertRecordsInCache: upsertFavoritesFoldersInCache } =
|
||||
useUpsertRecordsInCacheForPrefetchKey<FavoriteFolder>({
|
||||
prefetchKey: PrefetchKey.AllFavoritesFolders,
|
||||
});
|
||||
const { objectMetadataItems } = useObjectMetadataItems();
|
||||
|
||||
const operationSignatures = Object.values(PREFETCH_CONFIG)
|
||||
|
||||
.map(({ objectNameSingular, operationSignatureFactory }) => {
|
||||
const objectMetadataItem = objectMetadataItems.find(
|
||||
(item) => item.nameSingular === objectNameSingular,
|
||||
);
|
||||
|
||||
return operationSignatureFactory({ objectMetadataItem });
|
||||
});
|
||||
|
||||
const { result } = useCombinedFindManyRecords({
|
||||
operationSignatures,
|
||||
skip: !currentUser || isWorkspaceSuspended,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (isDefined(result.views)) {
|
||||
upsertViewsInCache(result.views as View[]);
|
||||
}
|
||||
|
||||
if (isDefined(result.favorites)) {
|
||||
upsertFavoritesInCache(result.favorites as Favorite[]);
|
||||
}
|
||||
if (isDefined(result.favoriteFolders)) {
|
||||
upsertFavoritesFoldersInCache(result.favoriteFolders as FavoriteFolder[]);
|
||||
}
|
||||
}, [
|
||||
result,
|
||||
upsertViewsInCache,
|
||||
upsertFavoritesInCache,
|
||||
upsertFavoritesFoldersInCache,
|
||||
]);
|
||||
|
||||
return <></>;
|
||||
};
|
||||
@ -0,0 +1,59 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useRecoilCallback, useRecoilValue } from 'recoil';
|
||||
|
||||
import { currentUserState } from '@/auth/states/currentUserState';
|
||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
|
||||
import { findAllViewsOperationSignatureFactory } from '@/prefetch/graphql/operation-signatures/factories/findAllViewsOperationSignatureFactory';
|
||||
import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState';
|
||||
import { isPersistingViewFieldsState } from '@/views/states/isPersistingViewFieldsState';
|
||||
import { View } from '@/views/types/View';
|
||||
import { useIsWorkspaceActivationStatusSuspended } from '@/workspace/hooks/useIsWorkspaceActivationStatusSuspended';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||
|
||||
export const PrefetchRunViewQueryEffect = () => {
|
||||
const currentUser = useRecoilValue(currentUserState);
|
||||
|
||||
const isWorkspaceSuspended = useIsWorkspaceActivationStatusSuspended();
|
||||
|
||||
const { objectMetadataItems } = useObjectMetadataItems();
|
||||
|
||||
const findAllViewsOperationSignature = findAllViewsOperationSignatureFactory({
|
||||
objectMetadataItem: objectMetadataItems.find(
|
||||
(item) => item.nameSingular === CoreObjectNameSingular.View,
|
||||
),
|
||||
});
|
||||
|
||||
const { records } = useFindManyRecords({
|
||||
objectNameSingular: CoreObjectNameSingular.View,
|
||||
filter: findAllViewsOperationSignature.variables.filter,
|
||||
recordGqlFields: findAllViewsOperationSignature.fields,
|
||||
skip: !currentUser || isWorkspaceSuspended,
|
||||
});
|
||||
|
||||
const setPrefetchViewsState = useRecoilCallback(
|
||||
({ set, snapshot }) =>
|
||||
(views: View[]) => {
|
||||
const existingViews = snapshot
|
||||
.getLoadable(prefetchViewsState)
|
||||
.getValue();
|
||||
|
||||
if (!isDeeplyEqual(existingViews, views)) {
|
||||
set(prefetchViewsState, views);
|
||||
}
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
const isPersistingViewFields = useRecoilValue(isPersistingViewFieldsState);
|
||||
|
||||
useEffect(() => {
|
||||
if (isDefined(records) && !isPersistingViewFields) {
|
||||
setPrefetchViewsState(records as View[]);
|
||||
}
|
||||
}, [isPersistingViewFields, records, setPrefetchViewsState]);
|
||||
|
||||
return <></>;
|
||||
};
|
||||
@ -2,7 +2,6 @@ import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSi
|
||||
import { RecordGqlOperationSignatureFactory } from '@/object-record/graphql/types/RecordGqlOperationSignatureFactory';
|
||||
import { findAllFavoritesFolderOperationSignatureFactory } from '@/prefetch/graphql/operation-signatures/factories/findAllFavoritesFolderOperationSignatureFactory';
|
||||
import { findAllFavoritesOperationSignatureFactory } from '@/prefetch/graphql/operation-signatures/factories/findAllFavoritesOperationSignatureFactory';
|
||||
import { findAllViewsOperationSignatureFactory } from '@/prefetch/graphql/operation-signatures/factories/findAllViewsOperationSignatureFactory';
|
||||
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
|
||||
|
||||
export const PREFETCH_CONFIG: Record<
|
||||
@ -12,10 +11,6 @@ export const PREFETCH_CONFIG: Record<
|
||||
operationSignatureFactory: RecordGqlOperationSignatureFactory;
|
||||
}
|
||||
> = {
|
||||
ALL_VIEWS: {
|
||||
objectNameSingular: CoreObjectNameSingular.View,
|
||||
operationSignatureFactory: findAllViewsOperationSignatureFactory,
|
||||
},
|
||||
ALL_FAVORITES: {
|
||||
objectNameSingular: CoreObjectNameSingular.Favorite,
|
||||
operationSignatureFactory: findAllFavoritesOperationSignatureFactory,
|
||||
|
||||
@ -1,51 +0,0 @@
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { useUpsertFindManyRecordsQueryInCache } from '@/object-record/cache/hooks/useUpsertFindManyRecordsQueryInCache';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { PREFETCH_CONFIG } from '@/prefetch/constants/PrefetchConfig';
|
||||
import { prefetchIsLoadedFamilyState } from '@/prefetch/states/prefetchIsLoadedFamilyState';
|
||||
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
|
||||
|
||||
export type UsePrefetchRunQuery = {
|
||||
prefetchKey: PrefetchKey;
|
||||
};
|
||||
|
||||
export const useUpsertRecordsInCacheForPrefetchKey = <T extends ObjectRecord>({
|
||||
prefetchKey,
|
||||
}: UsePrefetchRunQuery) => {
|
||||
const setPrefetchDataIsLoaded = useSetRecoilState(
|
||||
prefetchIsLoadedFamilyState(prefetchKey),
|
||||
);
|
||||
|
||||
const { operationSignatureFactory, objectNameSingular } =
|
||||
PREFETCH_CONFIG[prefetchKey];
|
||||
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
const operationSignature = operationSignatureFactory({ objectMetadataItem });
|
||||
|
||||
const { upsertFindManyRecordsQueryInCache } =
|
||||
useUpsertFindManyRecordsQueryInCache({
|
||||
objectMetadataItem: objectMetadataItem,
|
||||
});
|
||||
|
||||
const upsertRecordsInCache = (records: T[]) => {
|
||||
setPrefetchDataIsLoaded(false);
|
||||
|
||||
upsertFindManyRecordsQueryInCache({
|
||||
queryVariables: operationSignature.variables,
|
||||
recordGqlFields: operationSignature.fields,
|
||||
objectRecordsToOverwrite: records,
|
||||
computeReferences: false,
|
||||
});
|
||||
setPrefetchDataIsLoaded(true);
|
||||
};
|
||||
|
||||
return {
|
||||
objectMetadataItem,
|
||||
upsertRecordsInCache,
|
||||
};
|
||||
};
|
||||
@ -9,17 +9,12 @@ export const useIsPrefetchLoading = () => {
|
||||
prefetchIsLoadedFamilyState(PrefetchKey.AllFavoritesFolders),
|
||||
);
|
||||
|
||||
const areViewsPrefetched = useRecoilValue(
|
||||
prefetchIsLoadedFamilyState(PrefetchKey.AllViews),
|
||||
);
|
||||
const areFavoritesPrefetched = useRecoilValue(
|
||||
prefetchIsLoadedFamilyState(PrefetchKey.AllFavorites),
|
||||
);
|
||||
|
||||
return (
|
||||
!isWorkspaceSuspended &&
|
||||
(!areViewsPrefetched ||
|
||||
!areFavoritesPrefetched ||
|
||||
!isFavoriteFoldersPrefetched)
|
||||
(!areFavoritesPrefetched || !isFavoriteFoldersPrefetched)
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,30 +0,0 @@
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { RecordGqlOperationFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
|
||||
import { useLazyFindManyRecords } from '@/object-record/hooks/useLazyFindManyRecords';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { PREFETCH_CONFIG } from '@/prefetch/constants/PrefetchConfig';
|
||||
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
|
||||
|
||||
export const useLazyPrefetchedData = <T extends ObjectRecord>(
|
||||
prefetchKey: PrefetchKey,
|
||||
filter?: RecordGqlOperationFilter,
|
||||
) => {
|
||||
const { operationSignatureFactory, objectNameSingular } =
|
||||
PREFETCH_CONFIG[prefetchKey];
|
||||
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
const recordGqlFields =
|
||||
operationSignatureFactory({ objectMetadataItem }).fields ?? filter;
|
||||
const { records, findManyRecords } = useLazyFindManyRecords<T>({
|
||||
objectNameSingular: objectNameSingular,
|
||||
recordGqlFields,
|
||||
});
|
||||
|
||||
return {
|
||||
findManyRecords,
|
||||
records,
|
||||
};
|
||||
};
|
||||
@ -1,38 +0,0 @@
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { RecordGqlOperationFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
|
||||
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { PREFETCH_CONFIG } from '@/prefetch/constants/PrefetchConfig';
|
||||
import { prefetchIsLoadedFamilyState } from '@/prefetch/states/prefetchIsLoadedFamilyState';
|
||||
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
|
||||
|
||||
export const usePrefetchedData = <T extends ObjectRecord>(
|
||||
prefetchKey: PrefetchKey,
|
||||
filter?: RecordGqlOperationFilter,
|
||||
) => {
|
||||
const isDataPrefetched = useRecoilValue(
|
||||
prefetchIsLoadedFamilyState(prefetchKey),
|
||||
);
|
||||
|
||||
const { operationSignatureFactory, objectNameSingular } =
|
||||
PREFETCH_CONFIG[prefetchKey];
|
||||
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
const recordGqlFields =
|
||||
operationSignatureFactory({ objectMetadataItem }).fields ?? filter;
|
||||
const { records } = useFindManyRecords<T>({
|
||||
skip: !isDataPrefetched,
|
||||
objectNameSingular: objectNameSingular,
|
||||
recordGqlFields,
|
||||
});
|
||||
|
||||
return {
|
||||
isDataPrefetched,
|
||||
records,
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,7 @@
|
||||
import { FavoriteFolder } from '@/favorites/types/FavoriteFolder';
|
||||
import { createState } from 'twenty-ui';
|
||||
|
||||
export const prefetchFavoriteFoldersState = createState<FavoriteFolder[]>({
|
||||
key: 'prefetchFavoriteFoldersState',
|
||||
defaultValue: [],
|
||||
});
|
||||
@ -0,0 +1,7 @@
|
||||
import { Favorite } from '@/favorites/types/Favorite';
|
||||
import { createState } from 'twenty-ui';
|
||||
|
||||
export const prefetchFavoritesState = createState<Favorite[]>({
|
||||
key: 'prefetchFavoritesState',
|
||||
defaultValue: [],
|
||||
});
|
||||
@ -0,0 +1,7 @@
|
||||
import { View } from '@/views/types/View';
|
||||
import { createState } from 'twenty-ui';
|
||||
|
||||
export const prefetchViewsState = createState<View[]>({
|
||||
key: 'prefetchViewsState',
|
||||
defaultValue: [],
|
||||
});
|
||||
@ -0,0 +1,18 @@
|
||||
import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState';
|
||||
import { ViewKey } from '@/views/types/ViewKey';
|
||||
import { selectorFamily } from 'recoil';
|
||||
|
||||
export const prefetchIndexViewIdFromObjectMetadataItemFamilySelector =
|
||||
selectorFamily<string | undefined, { objectMetadataItemId: string }>({
|
||||
key: 'prefetchIndexViewIdFromObjectMetadataItemFamilySelector',
|
||||
get:
|
||||
({ objectMetadataItemId }) =>
|
||||
({ get }) => {
|
||||
const views = get(prefetchViewsState);
|
||||
return views?.find(
|
||||
(view) =>
|
||||
view.objectMetadataId === objectMetadataItemId &&
|
||||
view.key === ViewKey.Index,
|
||||
)?.id;
|
||||
},
|
||||
});
|
||||
@ -0,0 +1,16 @@
|
||||
import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState';
|
||||
import { View } from '@/views/types/View';
|
||||
import { selectorFamily } from 'recoil';
|
||||
|
||||
export const prefetchViewFromViewIdFamilySelector = selectorFamily<
|
||||
View | undefined,
|
||||
{ viewId: string }
|
||||
>({
|
||||
key: 'prefetchViewFromViewIdFamilySelector',
|
||||
get:
|
||||
({ viewId }) =>
|
||||
({ get }) => {
|
||||
const views = get(prefetchViewsState);
|
||||
return views?.find((view) => view.id === viewId);
|
||||
},
|
||||
});
|
||||
@ -0,0 +1,15 @@
|
||||
import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState';
|
||||
import { selectorFamily } from 'recoil';
|
||||
|
||||
export const prefetchViewIdsFromObjectMetadataItemFamilySelector =
|
||||
selectorFamily<string[], { objectMetadataItemId: string }>({
|
||||
key: 'prefetchViewIdsFromObjectMetadataItemFamilySelector',
|
||||
get:
|
||||
({ objectMetadataItemId }) =>
|
||||
({ get }) => {
|
||||
const views = get(prefetchViewsState);
|
||||
return views
|
||||
.filter((view) => view.objectMetadataId === objectMetadataItemId)
|
||||
.map((view) => view.id);
|
||||
},
|
||||
});
|
||||
@ -0,0 +1,10 @@
|
||||
import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState';
|
||||
import { selector } from 'recoil';
|
||||
|
||||
export const prefetchViewLengthSelector = selector<number>({
|
||||
key: 'prefetchViewLengthSelector',
|
||||
get: ({ get }) => {
|
||||
const views = get(prefetchViewsState);
|
||||
return views?.length ?? 0;
|
||||
},
|
||||
});
|
||||
@ -0,0 +1,18 @@
|
||||
import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState';
|
||||
import { View } from '@/views/types/View';
|
||||
import { selectorFamily } from 'recoil';
|
||||
|
||||
export const prefetchViewsFromObjectMetadataItemFamilySelector = selectorFamily<
|
||||
View[],
|
||||
{ objectMetadataItemId: string }
|
||||
>({
|
||||
key: 'prefetchViewsFromObjectMetadataItemFamilySelector',
|
||||
get:
|
||||
({ objectMetadataItemId }) =>
|
||||
({ get }) => {
|
||||
const views = get(prefetchViewsState);
|
||||
return views.filter(
|
||||
(view) => view.objectMetadataId === objectMetadataItemId,
|
||||
);
|
||||
},
|
||||
});
|
||||
@ -1,5 +1,4 @@
|
||||
export enum PrefetchKey {
|
||||
AllViews = 'ALL_VIEWS',
|
||||
AllFavorites = 'ALL_FAVORITES',
|
||||
AllFavoritesFolders = 'ALL_FAVORITES_FOLDERS',
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user