Improve Jotai work (#18205)

This commit is contained in:
Charles Bochet
2026-02-24 20:38:30 +01:00
committed by GitHub
parent b339c93699
commit eaf9fe27b2
210 changed files with 1714 additions and 1662 deletions
@@ -6,7 +6,10 @@ import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useR
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
import {
jotaiStore,
resetJotaiStore,
} from '@/ui/utilities/state/jotai/jotaiStore';
import { coreViewsState } from '@/views/states/coreViewState';
import { type CoreViewSortEssential } from '@/views/types/CoreViewSortEssential';
import { type CoreViewWithRelations } from '@/views/types/CoreViewWithRelations';
@@ -35,7 +38,7 @@ describe('useApplyCurrentViewSortsToCurrentRecordSorts', () => {
}
afterEach(() => {
jotaiStore.set(coreViewsState.atom, []);
resetJotaiStore();
});
const mockFieldMetadataItem = mockObjectMetadataItem.fields.find(
@@ -20,10 +20,9 @@ export const useApplyCurrentViewFilterGroupsToCurrentRecordFilterGroups =
currentRecordFilterGroupsComponentState,
);
const currentRecordFilterGroupsAtom =
useRecoilComponentStateCallbackStateV2(
currentRecordFilterGroupsComponentState,
);
const currentRecordFilterGroups = useRecoilComponentStateCallbackStateV2(
currentRecordFilterGroupsComponentState,
);
const store = useStore();
@@ -36,8 +35,8 @@ export const useApplyCurrentViewFilterGroupsToCurrentRecordFilterGroups =
);
if (isDefined(currentView)) {
const currentRecordFilterGroups = store.get(
currentRecordFilterGroupsAtom,
const existingRecordFilterGroups = store.get(
currentRecordFilterGroups,
);
const newRecordFilterGroups = mapViewFilterGroupsToRecordFilterGroups(
@@ -45,7 +44,7 @@ export const useApplyCurrentViewFilterGroupsToCurrentRecordFilterGroups =
);
if (
!isDeeplyEqual(currentRecordFilterGroups, newRecordFilterGroups)
!isDeeplyEqual(existingRecordFilterGroups, newRecordFilterGroups)
) {
setCurrentRecordFilterGroups(newRecordFilterGroups);
}
@@ -53,7 +52,7 @@ export const useApplyCurrentViewFilterGroupsToCurrentRecordFilterGroups =
}, [
currentViewId,
setCurrentRecordFilterGroups,
currentRecordFilterGroupsAtom,
currentRecordFilterGroups,
store,
]);
@@ -33,7 +33,7 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => {
const { objectMetadataItem, recordIndexId } = useRecordIndexContextOrThrow();
const currentViewIdAtom = useRecoilComponentStateCallbackStateV2(
const currentViewId = useRecoilComponentStateCallbackStateV2(
contextStoreCurrentViewIdComponentState,
viewBarComponentId,
);
@@ -96,15 +96,15 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => {
>,
shouldCopyFiltersAndSortsAndAggregate?: boolean,
): Promise<string | undefined> => {
const currentViewId = store.get(currentViewIdAtom);
const existingCurrentViewId = store.get(currentViewId);
if (!isDefined(currentViewId)) {
if (!isDefined(existingCurrentViewId)) {
return undefined;
}
const sourceView = store.get(
coreViewFromViewIdFamilySelector.selectorFamily({
viewId: currentViewId,
viewId: existingCurrentViewId,
}),
);
@@ -238,7 +238,7 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => {
return newViewId;
},
[
currentViewIdAtom,
currentViewId,
performViewAPICreate,
anyFieldFilterValue,
objectMetadataItem,
@@ -1,15 +1,16 @@
import { FIND_ALL_CORE_VIEWS } from '@/views/graphql/queries/findAllCoreViews';
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
import { coreViewsState } from '@/views/states/coreViewState';
import { type FetchPolicy, useApolloClient } from '@apollo/client';
import { useCallback } from 'react';
import { isDefined } from 'twenty-shared/utils';
import { type FindAllCoreViewsQuery } from '~/generated-metadata/graphql';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
import { useStore } from 'jotai';
export const useRefreshAllCoreViews = (
fetchPolicy: FetchPolicy = 'network-only',
) => {
const store = useStore();
const client = useApolloClient();
const refreshAllCoreViews = useCallback(async () => {
@@ -19,7 +20,7 @@ export const useRefreshAllCoreViews = (
fetchPolicy,
});
const currentCoreViews = jotaiStore.get(coreViewsState.atom);
const currentCoreViews = store.get(coreViewsState.atom);
const coreViewsFromResult = result.data.getCoreViews;
@@ -27,11 +28,11 @@ export const useRefreshAllCoreViews = (
isDefined(result.data?.getCoreViews) &&
!isDeeplyEqual(currentCoreViews, coreViewsFromResult)
) {
jotaiStore.set(coreViewsState.atom, coreViewsFromResult);
store.set(coreViewsState.atom, coreViewsFromResult);
}
return result.data?.getCoreViews;
}, [client, fetchPolicy]);
}, [client, fetchPolicy, store]);
return {
refreshAllCoreViews,
@@ -4,7 +4,6 @@ import { currentRecordFiltersComponentState } from '@/object-record/record-filte
import { recordIndexShouldHideEmptyRecordGroupsComponentState } from '@/object-record/record-index/states/recordIndexShouldHideEmptyRecordGroupsComponentState';
import { currentRecordSortsComponentState } from '@/object-record/record-sort/states/currentRecordSortsComponentState';
import { getRecordIndexIdFromObjectNamePluralAndViewId } from '@/object-record/utils/getRecordIndexIdFromObjectNamePluralAndViewId';
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
import { coreViewsByObjectMetadataIdFamilySelector } from '@/views/states/selectors/coreViewsByObjectMetadataIdFamilySelector';
import { convertCoreViewToView } from '@/views/utils/convertCoreViewToView';
import { getFilterableFields } from '@/views/utils/getFilterableFields';
@@ -15,8 +14,10 @@ import { useCallback } from 'react';
import { isDefined, removePropertiesFromRecord } from 'twenty-shared/utils';
import { useFindManyCoreViewsLazyQuery } from '~/generated-metadata/graphql';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
import { useStore } from 'jotai';
export const useRefreshCoreViewsByObjectMetadataId = () => {
const store = useStore();
const [findManyCoreViewsLazy] = useFindManyCoreViewsLazyQuery();
const refreshCoreViewsByObjectMetadataId = useCallback(
@@ -32,7 +33,7 @@ export const useRefreshCoreViewsByObjectMetadataId = () => {
return;
}
const objectMetadataItems = jotaiStore.get(objectMetadataItemsState.atom);
const objectMetadataItems = store.get(objectMetadataItemsState.atom);
const objectMetadataItem = objectMetadataItems.find(
(objectMetadataItem) => objectMetadataItem.id === objectMetadataId,
@@ -42,7 +43,7 @@ export const useRefreshCoreViewsByObjectMetadataId = () => {
return;
}
const coreViewsForObjectMetadataId = jotaiStore.get(
const coreViewsForObjectMetadataId = store.get(
coreViewsByObjectMetadataIdFamilySelector.selectorFamily(
objectMetadataId,
),
@@ -54,7 +55,7 @@ export const useRefreshCoreViewsByObjectMetadataId = () => {
return;
}
jotaiStore.set(
store.set(
coreViewsByObjectMetadataIdFamilySelector.selectorFamily(
objectMetadataId,
),
@@ -80,7 +81,7 @@ export const useRefreshCoreViewsByObjectMetadataId = () => {
)
) {
const view = convertCoreViewToView(coreView);
jotaiStore.set(
store.set(
currentRecordFieldsComponentState.atomFamily({
instanceId: getRecordIndexIdFromObjectNamePluralAndViewId(
objectMetadataItem.namePlural,
@@ -105,7 +106,7 @@ export const useRefreshCoreViewsByObjectMetadataId = () => {
)
) {
const view = convertCoreViewToView(coreView);
jotaiStore.set(
store.set(
currentRecordFiltersComponentState.atomFamily({
instanceId: getRecordIndexIdFromObjectNamePluralAndViewId(
objectMetadataItem.namePlural,
@@ -121,7 +122,7 @@ export const useRefreshCoreViewsByObjectMetadataId = () => {
if (!isDeeplyEqual(coreView.viewSorts, existingView.viewSorts)) {
const view = convertCoreViewToView(coreView);
jotaiStore.set(
store.set(
currentRecordSortsComponentState.atomFamily({
instanceId: getRecordIndexIdFromObjectNamePluralAndViewId(
objectMetadataItem.namePlural,
@@ -136,7 +137,7 @@ export const useRefreshCoreViewsByObjectMetadataId = () => {
coreView.shouldHideEmptyGroups !== existingView.shouldHideEmptyGroups
) {
const view = convertCoreViewToView(coreView);
jotaiStore.set(
store.set(
recordIndexShouldHideEmptyRecordGroupsComponentState.atomFamily({
instanceId: getRecordIndexIdFromObjectNamePluralAndViewId(
objectMetadataItem.namePlural,
@@ -148,7 +149,7 @@ export const useRefreshCoreViewsByObjectMetadataId = () => {
}
}
},
[findManyCoreViewsLazy],
[findManyCoreViewsLazy, store],
);
return {
@@ -4,7 +4,6 @@ import { useLoadRecordIndexStates } from '@/object-record/record-index/hooks/use
import { type ExtendedAggregateOperations } from '@/object-record/record-table/types/ExtendedAggregateOperations';
import { convertExtendedAggregateOperationToAggregateOperation } from '@/object-record/utils/convertExtendedAggregateOperationToAggregateOperation';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
import { usePerformViewAPIUpdate } from '@/views/hooks/internal/usePerformViewAPIUpdate';
import { useCanPersistViewChanges } from '@/views/hooks/useCanPersistViewChanges';
import { coreViewsState } from '@/views/states/coreViewState';
@@ -15,8 +14,10 @@ import {
upsertIntoArrayOfObjectsComparingId,
} from 'twenty-shared/utils';
import { type CoreView } from '~/generated-metadata/graphql';
import { useStore } from 'jotai';
export const useUpdateViewAggregate = () => {
const store = useStore();
const { canPersistChanges } = useCanPersistViewChanges();
const currentViewId = useRecoilComponentValueV2(
contextStoreCurrentViewIdComponentState,
@@ -66,7 +67,7 @@ export const useUpdateViewAggregate = () => {
return;
}
jotaiStore.set(coreViewsState.atom, (currentCoreViews) =>
store.set(coreViewsState.atom, (currentCoreViews) =>
upsertIntoArrayOfObjectsComparingId(
currentCoreViews,
updatedCoreView,
@@ -83,6 +84,7 @@ export const useUpdateViewAggregate = () => {
currentViewId,
performViewAPIUpdate,
loadRecordIndexStates,
store,
],
);
@@ -1,4 +1,3 @@
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
import { coreViewsState } from '@/views/states/coreViewState';
import { type CoreViewWithRelations } from '@/views/types/CoreViewWithRelations';
import { useApolloClient } from '@apollo/client';
@@ -6,6 +5,7 @@ import { useCallback } from 'react';
import { isDefined } from 'twenty-shared/utils';
import { type CoreViewFieldGroup } from '~/generated-metadata/graphql';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
import { useStore } from 'jotai';
type ViewFieldGroupForOptimisticEffect = Omit<
CoreViewFieldGroup,
@@ -13,6 +13,7 @@ type ViewFieldGroupForOptimisticEffect = Omit<
>;
export const useTriggerViewFieldGroupOptimisticEffect = () => {
const store = useStore();
const apolloClient = useApolloClient();
const cache = apolloClient.cache;
@@ -27,7 +28,7 @@ export const useTriggerViewFieldGroupOptimisticEffect = () => {
updatedViewFieldGroups?: ViewFieldGroupForOptimisticEffect[];
deletedViewFieldGroups?: Pick<CoreViewFieldGroup, 'id' | 'viewId'>[];
}) => {
const coreViews = jotaiStore.get(coreViewsState.atom);
const coreViews = store.get(coreViewsState.atom);
let newCoreViews = [...coreViews];
createdViewFieldGroups.forEach((createdViewFieldGroup) => {
@@ -147,10 +148,10 @@ export const useTriggerViewFieldGroupOptimisticEffect = () => {
);
if (!isDeeplyEqual(coreViews, newCoreViews)) {
jotaiStore.set(coreViewsState.atom, newCoreViews);
store.set(coreViewsState.atom, newCoreViews);
}
},
[cache],
[cache, store],
);
return {
@@ -1,4 +1,3 @@
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
import { coreViewsState } from '@/views/states/coreViewState';
import { type CoreViewWithRelations } from '@/views/types/CoreViewWithRelations';
import { useApolloClient } from '@apollo/client';
@@ -6,8 +5,10 @@ import { useCallback } from 'react';
import { isDefined } from 'twenty-shared/utils';
import { type CoreViewField } from '~/generated-metadata/graphql';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
import { useStore } from 'jotai';
export const useTriggerViewFieldOptimisticEffect = () => {
const store = useStore();
const apolloClient = useApolloClient();
const cache = apolloClient.cache;
@@ -22,7 +23,7 @@ export const useTriggerViewFieldOptimisticEffect = () => {
updatedViewFields?: Omit<CoreViewField, 'workspaceId'>[];
deletedViewFields?: Pick<CoreViewField, 'id' | 'viewId'>[];
}) => {
const coreViews = jotaiStore.get(coreViewsState.atom);
const coreViews = store.get(coreViewsState.atom);
let newCoreViews = [...coreViews];
createdViewFields.forEach((createdViewField) => {
@@ -131,10 +132,10 @@ export const useTriggerViewFieldOptimisticEffect = () => {
);
if (!isDeeplyEqual(coreViews, newCoreViews)) {
jotaiStore.set(coreViewsState.atom, newCoreViews);
store.set(coreViewsState.atom, newCoreViews);
}
},
[cache],
[cache, store],
);
return {
@@ -1,4 +1,3 @@
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
import { coreViewsState } from '@/views/states/coreViewState';
import { type CoreViewWithRelations } from '@/views/types/CoreViewWithRelations';
import { useApolloClient } from '@apollo/client';
@@ -6,12 +5,14 @@ import { useCallback } from 'react';
import { isDefined } from 'twenty-shared/utils';
import { type CoreViewFilter } from '~/generated-metadata/graphql';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
import { useStore } from 'jotai';
type UpdatedDeletedCoreViewFilter = {
createdViewFilters?: Omit<CoreViewFilter, 'workspaceId'>[];
updatedViewFilters?: Omit<CoreViewFilter, 'workspaceId'>[];
deletedViewFilters?: Pick<CoreViewFilter, 'id' | 'viewId'>[];
};
export const useTriggerViewFilterOptimisticEffect = () => {
const store = useStore();
const apolloClient = useApolloClient();
const cache = apolloClient.cache;
@@ -22,7 +23,7 @@ export const useTriggerViewFilterOptimisticEffect = () => {
updatedViewFilters = [],
deletedViewFilters = [],
}: UpdatedDeletedCoreViewFilter) => {
const coreViews = jotaiStore.get(coreViewsState.atom);
const coreViews = store.get(coreViewsState.atom);
let newCoreViews = [...coreViews];
createdViewFilters.forEach((createdViewFilter) => {
@@ -131,10 +132,10 @@ export const useTriggerViewFilterOptimisticEffect = () => {
);
if (!isDeeplyEqual(coreViews, newCoreViews)) {
jotaiStore.set(coreViewsState.atom, newCoreViews);
store.set(coreViewsState.atom, newCoreViews);
}
},
[cache],
[cache, store],
);
return {
@@ -1,4 +1,3 @@
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
import { coreViewsState } from '@/views/states/coreViewState';
import { type CoreViewWithRelations } from '@/views/types/CoreViewWithRelations';
import { useApolloClient } from '@apollo/client';
@@ -6,6 +5,7 @@ import { useCallback } from 'react';
import { isDefined } from 'twenty-shared/utils';
import { type CoreViewGroup } from '~/generated-metadata/graphql';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
import { useStore } from 'jotai';
type UpdatedDeletedCoreViewGroup = {
createdViewGroups?: Omit<CoreViewGroup, 'workspaceId'>[];
@@ -13,6 +13,7 @@ type UpdatedDeletedCoreViewGroup = {
deletedViewGroups?: Pick<CoreViewGroup, 'id' | 'viewId'>[];
};
export const useTriggerViewGroupOptimisticEffect = () => {
const store = useStore();
const apolloClient = useApolloClient();
const cache = apolloClient.cache;
@@ -23,7 +24,7 @@ export const useTriggerViewGroupOptimisticEffect = () => {
updatedViewGroups = [],
deletedViewGroups = [],
}: UpdatedDeletedCoreViewGroup) => {
const coreViews = jotaiStore.get(coreViewsState.atom);
const coreViews = store.get(coreViewsState.atom);
let newCoreViews = [...coreViews];
createdViewGroups.forEach((createdViewGroup) => {
@@ -130,10 +131,10 @@ export const useTriggerViewGroupOptimisticEffect = () => {
});
if (!isDeeplyEqual(coreViews, newCoreViews)) {
jotaiStore.set(coreViewsState.atom, newCoreViews);
store.set(coreViewsState.atom, newCoreViews);
}
},
[cache],
[cache, store],
);
return {
@@ -1,4 +1,3 @@
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
import { coreViewsState } from '@/views/states/coreViewState';
import { type CoreViewWithRelations } from '@/views/types/CoreViewWithRelations';
import { useApolloClient } from '@apollo/client';
@@ -6,8 +5,10 @@ import { useCallback } from 'react';
import { isDefined } from 'twenty-shared/utils';
import { type CoreViewSort } from '~/generated-metadata/graphql';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
import { useStore } from 'jotai';
export const useTriggerViewSortOptimisticEffect = () => {
const store = useStore();
const apolloClient = useApolloClient();
const cache = apolloClient.cache;
@@ -22,7 +23,7 @@ export const useTriggerViewSortOptimisticEffect = () => {
updatedViewSorts?: Omit<CoreViewSort, 'workspaceId'>[];
deletedViewSorts?: Pick<CoreViewSort, 'id' | 'viewId'>[];
}) => {
const coreViews = jotaiStore.get(coreViewsState.atom);
const coreViews = store.get(coreViewsState.atom);
let newCoreViews = [...coreViews];
createdViewSorts.forEach((createdViewSort) => {
@@ -128,10 +129,10 @@ export const useTriggerViewSortOptimisticEffect = () => {
);
if (!isDeeplyEqual(coreViews, newCoreViews)) {
jotaiStore.set(coreViewsState.atom, newCoreViews);
store.set(coreViewsState.atom, newCoreViews);
}
},
[cache],
[cache, store],
);
return {