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:
Charles Bochet
2025-02-18 13:51:07 +01:00
committed by GitHub
parent 103dff4bd0
commit fb42046033
125 changed files with 1607 additions and 1582 deletions

View File

@ -1,18 +1,20 @@
import { useEffect } from 'react';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useSetRecoilComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentFamilyStateV2';
import { useViewFromQueryParams } from '@/views/hooks/internal/useViewFromQueryParams';
import { useApplyViewFiltersToCurrentRecordFilters } from '@/views/hooks/useApplyViewFiltersToCurrentRecordFilters';
import { useResetUnsavedViewStates } from '@/views/hooks/useResetUnsavedViewStates';
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState';
export const QueryParamsFiltersEffect = () => {
const { hasFiltersQueryParams, getFiltersFromQueryParams, viewIdQueryParam } =
useViewFromQueryParams();
const currentViewId = useRecoilComponentValueV2(currentViewIdComponentState);
const currentViewId = useRecoilComponentValueV2(
contextStoreCurrentViewIdComponentState,
);
const setUnsavedViewFilter = useSetRecoilComponentFamilyStateV2(
unsavedToUpsertViewFiltersComponentFamilyState,

View File

@ -1,35 +0,0 @@
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { mainContextStoreComponentInstanceIdState } from '@/context-store/states/mainContextStoreComponentInstanceId';
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
import { useEffect } from 'react';
import { useRecoilValue } from 'recoil';
import { isDefined } from 'twenty-shared';
// TODO: This whole code should be removed. currentViewId should be used directly to set the mainContextStore
// and viewbar / view tooling should be updated to use that state contextStore state directly.
export const QueryParamsViewIdEffect = () => {
const [currentViewId, setCurrentViewId] = useRecoilComponentStateV2(
currentViewIdComponentState,
);
const mainContextStoreComponentInstanceId = useRecoilValue(
mainContextStoreComponentInstanceIdState,
);
const contextStoreCurrentViewId = useRecoilComponentValueV2(
contextStoreCurrentViewIdComponentState,
mainContextStoreComponentInstanceId,
);
useEffect(() => {
if (isDefined(contextStoreCurrentViewId)) {
if (currentViewId !== contextStoreCurrentViewId) {
setCurrentViewId(contextStoreCurrentViewId);
}
}
}, [contextStoreCurrentViewId, currentViewId, setCurrentViewId]);
return <></>;
};

View File

@ -7,6 +7,7 @@ import {
MenuItem,
} from 'twenty-ui';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
@ -19,7 +20,6 @@ import { useAreViewFiltersDifferentFromRecordFilters } from '@/views/hooks/useAr
import { useAreViewSortsDifferentFromRecordSorts } from '@/views/hooks/useAreViewSortsDifferentFromRecordSorts';
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
import { useSaveCurrentViewFiltersAndSorts } from '@/views/hooks/useSaveCurrentViewFiltersAndSorts';
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
import { VIEW_PICKER_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerDropdownId';
import { useViewPickerMode } from '@/views/view-picker/hooks/useViewPickerMode';
import { viewPickerReferenceViewIdComponentState } from '@/views/view-picker/states/viewPickerReferenceViewIdComponentState';
@ -44,7 +44,9 @@ export const UpdateViewButtonGroup = ({
const { setViewPickerMode } = useViewPickerMode();
const currentViewId = useRecoilComponentValueV2(currentViewIdComponentState);
const currentViewId = useRecoilComponentValueV2(
contextStoreCurrentViewIdComponentState,
);
const { closeDropdown: closeUpdateViewButtonDropdown } = useDropdown(
UPDATE_VIEW_BUTTON_DROPDOWN_ID,

View File

@ -7,13 +7,10 @@ import { ObjectSortDropdownButton } from '@/object-record/object-sort-dropdown/c
import { useIsPrefetchLoading } from '@/prefetch/hooks/useIsPrefetchLoading';
import { TopBar } from '@/ui/layout/top-bar/components/TopBar';
import { QueryParamsFiltersEffect } from '@/views/components/QueryParamsFiltersEffect';
import { QueryParamsViewIdEffect } from '@/views/components/QueryParamsViewIdEffect';
import { ViewBarEffect } from '@/views/components/ViewBarEffect';
import { ViewBarFilterEffect } from '@/views/components/ViewBarFilterEffect';
import { ViewBarPageTitle } from '@/views/components/ViewBarPageTitle';
import { ViewBarSkeletonLoader } from '@/views/components/ViewBarSkeletonLoader';
import { ViewBarSortEffect } from '@/views/components/ViewBarSortEffect';
import { GraphQLView } from '@/views/types/GraphQLView';
import { ViewPickerDropdown } from '@/views/view-picker/components/ViewPickerDropdown';
import { ViewsHotkeyScope } from '../types/ViewsHotkeyScope';
@ -22,7 +19,6 @@ import { FiltersHotkeyScope } from '@/object-record/object-filter-dropdown/types
import { VIEW_SORT_DROPDOWN_ID } from '@/object-record/object-sort-dropdown/constants/ViewSortDropdownId';
import { ObjectSortDropdownComponentInstanceContext } from '@/object-record/object-sort-dropdown/states/context/ObjectSortDropdownComponentInstanceContext';
import { ViewBarRecordFilterEffect } from '@/views/components/ViewBarRecordFilterEffect';
import { ViewEventContext } from '@/views/events/contexts/ViewEventContext';
import { UpdateViewButtonGroup } from './UpdateViewButtonGroup';
import { ViewBarDetails } from './ViewBarDetails';
@ -30,14 +26,12 @@ export type ViewBarProps = {
viewBarId: string;
className?: string;
optionsDropdownButton: ReactNode;
onCurrentViewChange: (view: GraphQLView | undefined) => void | Promise<void>;
};
export const ViewBar = ({
viewBarId,
className,
optionsDropdownButton,
onCurrentViewChange,
}: ViewBarProps) => {
const { objectNamePlural } = useParams();
@ -53,53 +47,49 @@ export const ViewBar = ({
<ObjectSortDropdownComponentInstanceContext.Provider
value={{ instanceId: VIEW_SORT_DROPDOWN_ID }}
>
<ViewEventContext.Provider value={{ onCurrentViewChange }}>
<ViewBarRecordFilterEffect />
<ViewBarEffect viewBarId={viewBarId} />
<ViewBarFilterEffect filterDropdownId={filterDropdownId} />
<ViewBarSortEffect />
<QueryParamsFiltersEffect />
<QueryParamsViewIdEffect />
<ViewBarRecordFilterEffect />
<ViewBarFilterEffect filterDropdownId={filterDropdownId} />
<ViewBarSortEffect />
<QueryParamsFiltersEffect />
<ViewBarPageTitle viewBarId={viewBarId} />
<TopBar
className={className}
leftComponent={
loading ? <ViewBarSkeletonLoader /> : <ViewPickerDropdown />
}
rightComponent={
<>
<ObjectFilterDropdownButton
filterDropdownId={filterDropdownId}
hotkeyScope={{
scope: FiltersHotkeyScope.ObjectFilterDropdownButton,
}}
/>
<ObjectSortDropdownButton
hotkeyScope={{
scope: FiltersHotkeyScope.ObjectSortDropdownButton,
}}
/>
{optionsDropdownButton}
</>
}
bottomComponent={
<ViewBarDetails
<ViewBarPageTitle viewBarId={viewBarId} />
<TopBar
className={className}
leftComponent={
loading ? <ViewBarSkeletonLoader /> : <ViewPickerDropdown />
}
rightComponent={
<>
<ObjectFilterDropdownButton
filterDropdownId={filterDropdownId}
hasFilterButton
viewBarId={viewBarId}
objectNamePlural={objectNamePlural}
rightComponent={
<UpdateViewButtonGroup
hotkeyScope={{
scope: ViewsHotkeyScope.UpdateViewButtonDropdown,
}}
/>
}
hotkeyScope={{
scope: FiltersHotkeyScope.ObjectFilterDropdownButton,
}}
/>
}
/>
</ViewEventContext.Provider>
<ObjectSortDropdownButton
hotkeyScope={{
scope: FiltersHotkeyScope.ObjectSortDropdownButton,
}}
/>
{optionsDropdownButton}
</>
}
bottomComponent={
<ViewBarDetails
filterDropdownId={filterDropdownId}
hasFilterButton
viewBarId={viewBarId}
objectNamePlural={objectNamePlural}
rightComponent={
<UpdateViewButtonGroup
hotkeyScope={{
scope: ViewsHotkeyScope.UpdateViewButtonDropdown,
}}
/>
}
/>
}
/>
</ObjectSortDropdownComponentInstanceContext.Provider>
);
};

View File

@ -1,56 +0,0 @@
import { isUndefined } from '@sniptt/guards';
import { useContext, useEffect, useState } from 'react';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { ViewEventContext } from '@/views/events/contexts/ViewEventContext';
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
import { isPersistingViewFieldsComponentState } from '@/views/states/isPersistingViewFieldsComponentState';
import { View } from '@/views/types/View';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
type ViewBarEffectProps = {
viewBarId: string;
};
export const ViewBarEffect = ({ viewBarId }: ViewBarEffectProps) => {
const { currentViewWithCombinedFiltersAndSorts } =
useGetCurrentView(viewBarId);
const { onCurrentViewChange } = useContext(ViewEventContext);
const [currentViewSnapshot, setCurrentViewSnapshot] = useState<
View | undefined
>(undefined);
const isPersistingViewFields = useRecoilComponentValueV2(
isPersistingViewFieldsComponentState,
viewBarId,
);
useEffect(() => {
if (
!isDeeplyEqual(
currentViewWithCombinedFiltersAndSorts,
currentViewSnapshot,
)
) {
if (isUndefined(currentViewWithCombinedFiltersAndSorts)) {
setCurrentViewSnapshot(currentViewWithCombinedFiltersAndSorts);
onCurrentViewChange?.(undefined);
return;
}
if (!isPersistingViewFields) {
setCurrentViewSnapshot(currentViewWithCombinedFiltersAndSorts);
onCurrentViewChange?.(currentViewWithCombinedFiltersAndSorts);
}
}
}, [
currentViewSnapshot,
currentViewWithCombinedFiltersAndSorts,
isPersistingViewFields,
onCurrentViewChange,
]);
return <></>;
};

View File

@ -1,38 +1,24 @@
import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { useFilterableFieldMetadataItems } from '@/object-record/record-filter/hooks/useFilterableFieldMetadataItems';
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector';
import { useRecoilComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyStateV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { hasInitializedCurrentRecordFiltersComponentFamilyState } from '@/views/states/hasInitializedCurrentRecordFiltersComponentFamilyState';
import { View } from '@/views/types/View';
import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters';
import { useEffect } from 'react';
import { useRecoilValue } from 'recoil';
import { isDefined } from 'twenty-shared';
export const ViewBarRecordFilterEffect = () => {
const { records: views, isDataPrefetched } = usePrefetchedData<View>(
PrefetchKey.AllViews,
);
const currentViewId = useRecoilComponentValueV2(
contextStoreCurrentViewIdComponentState,
);
const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2(
contextStoreCurrentObjectMetadataIdComponentState,
);
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
const objectMetadataItem = objectMetadataItems.find(
(objectMetadataItem) =>
objectMetadataItem.id === contextStoreCurrentObjectMetadataId,
const contextStoreCurrentObjectMetadataItem = useRecoilComponentValueV2(
contextStoreCurrentObjectMetadataItemComponentState,
);
const [
@ -54,14 +40,21 @@ export const ViewBarRecordFilterEffect = () => {
);
const { filterableFieldMetadataItems } = useFilterableFieldMetadataItems(
objectMetadataItem?.id,
contextStoreCurrentObjectMetadataItem?.id,
);
const currentView = useRecoilValue(
prefetchViewFromViewIdFamilySelector({
viewId: currentViewId ?? '',
}),
);
useEffect(() => {
if (isDataPrefetched && !hasInitializedCurrentRecordFilters) {
const currentView = views.find((view) => view.id === currentViewId);
if (currentView?.objectMetadataId !== objectMetadataItem?.id) {
if (isDefined(currentView) && !hasInitializedCurrentRecordFilters) {
if (
currentView.objectMetadataId !==
contextStoreCurrentObjectMetadataItem?.id
) {
return;
}
@ -76,15 +69,14 @@ export const ViewBarRecordFilterEffect = () => {
}
}
}, [
isDataPrefetched,
views,
currentViewId,
setCurrentRecordFilters,
filterableFieldMetadataItems,
currentRecordFilters,
hasInitializedCurrentRecordFilters,
setHasInitializedCurrentRecordFilters,
objectMetadataItem?.id,
contextStoreCurrentObjectMetadataItem?.id,
currentView,
]);
return null;

View File

@ -1,8 +0,0 @@
import { View } from '@/views/types/View';
import { createEventContext } from '~/utils/createEventContext';
type ViewEventContextType = {
onCurrentViewChange: (view: View | undefined) => void | Promise<void>;
};
export const ViewEventContext = createEventContext<ViewEventContextType>();

View File

@ -1,20 +1,22 @@
import { act, renderHook } from '@testing-library/react';
import { renderHook } from '@testing-library/react';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
import { AGGREGATE_OPERATIONS } from '@/object-record/record-table/constants/AggregateOperations';
import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
import { View } from '@/views/types/View';
import { ViewFilter } from '@/views/types/ViewFilter';
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
import { ViewType } from '@/views/types/ViewType';
import { act } from 'react';
import { isDefined } from 'twenty-shared';
import { getJestMetadataAndApolloMocksAndActionMenuWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksAndContextStoreWrapper';
import { generatedMockObjectMetadataItems } from '~/testing/mock-data/generatedMockObjectMetadataItems';
import { useApplyCurrentViewFiltersToCurrentRecordFilters } from '../useApplyCurrentViewFiltersToCurrentRecordFilters';
jest.mock('@/prefetch/hooks/usePrefetchedData');
const mockObjectMetadataItemNameSingular = 'company';
describe('useApplyCurrentViewFiltersToCurrentRecordFilters', () => {
@ -41,18 +43,26 @@ describe('useApplyCurrentViewFiltersToCurrentRecordFilters', () => {
positionInViewFilterGroup: 0,
};
const mockView = {
const mockView: View = {
id: 'view-1',
name: 'Test View',
objectMetadataId: mockObjectMetadataItem.id,
viewFilters: [mockViewFilter],
type: ViewType.Table,
key: null,
isCompact: false,
viewFields: [],
viewGroups: [],
viewSorts: [],
kanbanFieldMetadataId: '',
kanbanAggregateOperation: AGGREGATE_OPERATIONS.count,
icon: '',
kanbanAggregateOperationFieldMetadataId: '',
position: 0,
__typename: 'View',
};
it('should apply filters from current view', () => {
(usePrefetchedData as jest.Mock).mockReturnValue({
records: [mockView],
});
const { result } = renderHook(
() => {
const { applyCurrentViewFiltersToCurrentRecordFilters } =
@ -75,11 +85,12 @@ describe('useApplyCurrentViewFiltersToCurrentRecordFilters', () => {
mockObjectMetadataItemNameSingular,
onInitializeRecoilSnapshot: (snapshot) => {
snapshot.set(
currentViewIdComponentState.atomFamily({
contextStoreCurrentViewIdComponentState.atomFamily({
instanceId: 'instanceId',
}),
mockView.id,
);
snapshot.set(prefetchViewsState, [mockView]);
},
}),
},
@ -105,10 +116,6 @@ describe('useApplyCurrentViewFiltersToCurrentRecordFilters', () => {
});
it('should not apply filters when current view is not found', () => {
(usePrefetchedData as jest.Mock).mockReturnValue({
records: [],
});
const { result } = renderHook(
() => {
const { applyCurrentViewFiltersToCurrentRecordFilters } =
@ -131,11 +138,12 @@ describe('useApplyCurrentViewFiltersToCurrentRecordFilters', () => {
mockObjectMetadataItemNameSingular,
onInitializeRecoilSnapshot: (snapshot) => {
snapshot.set(
currentViewIdComponentState.atomFamily({
contextStoreCurrentViewIdComponentState.atomFamily({
instanceId: 'instanceId',
}),
mockView.id,
);
snapshot.set(prefetchViewsState, []);
},
}),
},
@ -149,15 +157,6 @@ describe('useApplyCurrentViewFiltersToCurrentRecordFilters', () => {
});
it('should handle view with empty filters', () => {
const viewWithNoFilters = {
...mockView,
viewFilters: [],
};
(usePrefetchedData as jest.Mock).mockReturnValue({
records: [viewWithNoFilters],
});
const { result } = renderHook(
() => {
const { applyCurrentViewFiltersToCurrentRecordFilters } =
@ -180,11 +179,14 @@ describe('useApplyCurrentViewFiltersToCurrentRecordFilters', () => {
mockObjectMetadataItemNameSingular,
onInitializeRecoilSnapshot: (snapshot) => {
snapshot.set(
currentViewIdComponentState.atomFamily({
contextStoreCurrentViewIdComponentState.atomFamily({
instanceId: 'instanceId',
}),
mockView.id,
);
snapshot.set(prefetchViewsState, [
{ ...mockView, viewFilters: [] },
]);
},
}),
},

View File

@ -1,19 +1,18 @@
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { useFilterableFieldMetadataItemsInRecordIndexContext } from '@/object-record/record-filter/hooks/useFilterableFieldMetadataItemsInRecordIndexContext';
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
import { View } from '@/views/types/View';
import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters';
import { useRecoilCallback } from 'recoil';
import { isDefined } from 'twenty-shared';
export const useApplyCurrentViewFiltersToCurrentRecordFilters = () => {
const { records: views } = usePrefetchedData<View>(PrefetchKey.AllViews);
const currentViewId = useRecoilComponentValueV2(currentViewIdComponentState);
const currentViewId = useRecoilComponentValueV2(
contextStoreCurrentViewIdComponentState,
);
const setCurrentRecordFilters = useSetRecoilComponentStateV2(
currentRecordFiltersComponentState,
@ -22,18 +21,28 @@ export const useApplyCurrentViewFiltersToCurrentRecordFilters = () => {
const { filterableFieldMetadataItems } =
useFilterableFieldMetadataItemsInRecordIndexContext();
const applyCurrentViewFiltersToCurrentRecordFilters = () => {
const currentView = views.find((view) => view.id === currentViewId);
const applyCurrentViewFiltersToCurrentRecordFilters = useRecoilCallback(
({ snapshot }) =>
() => {
const currentView = snapshot
.getLoadable(
prefetchViewFromViewIdFamilySelector({
viewId: currentViewId ?? '',
}),
)
.getValue();
if (isDefined(currentView)) {
setCurrentRecordFilters(
mapViewFiltersToFilters(
currentView.viewFilters,
filterableFieldMetadataItems,
),
);
}
};
if (isDefined(currentView)) {
setCurrentRecordFilters(
mapViewFiltersToFilters(
currentView.viewFilters,
filterableFieldMetadataItems,
),
);
}
},
[currentViewId, filterableFieldMetadataItems, setCurrentRecordFilters],
);
return {
applyCurrentViewFiltersToCurrentRecordFilters,

View File

@ -1,6 +1,9 @@
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord';
import { useLazyFindManyRecords } from '@/object-record/hooks/useLazyFindManyRecords';
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { usePersistViewFieldRecords } from '@/views/hooks/internal/usePersistViewFieldRecords';
@ -11,9 +14,7 @@ import { usePersistViewSortRecords } from '@/views/hooks/internal/usePersistView
import { useGetViewFilterGroupsCombined } from '@/views/hooks/useGetCombinedViewFilterGroups';
import { useGetViewFiltersCombined } from '@/views/hooks/useGetCombinedViewFilters';
import { useGetViewSortsCombined } from '@/views/hooks/useGetCombinedViewSorts';
import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache';
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
import { isPersistingViewFieldsComponentState } from '@/views/states/isPersistingViewFieldsComponentState';
import { isPersistingViewFieldsState } from '@/views/states/isPersistingViewFieldsState';
import { GraphQLView } from '@/views/types/GraphQLView';
import { View } from '@/views/types/View';
import { ViewGroup } from '@/views/types/ViewGroup';
@ -25,17 +26,10 @@ import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => {
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
currentViewIdComponentState,
contextStoreCurrentViewIdComponentState,
viewBarComponentId,
);
const isPersistingViewFieldsCallbackState = useRecoilComponentCallbackStateV2(
isPersistingViewFieldsComponentState,
viewBarComponentId,
);
const { getViewFromCache } = useGetViewFromCache();
const { createOneRecord } = useCreateOneRecord<View>({
objectNameSingular: CoreObjectNameSingular.View,
});
@ -58,6 +52,11 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => {
const { objectMetadataItem } = useRecordIndexContextOrThrow();
const { findManyRecords } = useLazyFindManyRecords({
objectNameSingular: CoreObjectNameSingular.View,
fetchPolicy: 'network-only',
});
const createViewFromCurrentView = useRecoilCallback(
({ snapshot, set }) =>
async (
@ -84,14 +83,19 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => {
return;
}
// Here we might instead want to get view from unsaved filters ?
const sourceView = await getViewFromCache(currentViewId);
const sourceView = snapshot
.getLoadable(
prefetchViewFromViewIdFamilySelector({
viewId: currentViewId,
}),
)
.getValue();
if (!isDefined(sourceView)) {
return;
}
set(isPersistingViewFieldsCallbackState, true);
set(isPersistingViewFieldsState, true);
const newView = await createOneRecord({
id: id ?? v4(),
@ -123,7 +127,7 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => {
}
const viewGroupsToCreate =
objectMetadataItem?.fields
objectMetadataItem.fields
?.find((field) => field.id === kanbanFieldMetadataId)
?.options?.map(
(option, index) =>
@ -169,21 +173,21 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => {
);
}
set(isPersistingViewFieldsCallbackState, false);
await findManyRecords();
set(isPersistingViewFieldsState, false);
},
[
objectMetadataItem,
createViewSortRecords,
createViewFilterRecords,
currentViewIdCallbackState,
createOneRecord,
createViewFieldRecords,
getViewSortsCombined,
getViewFiltersCombined,
getViewFilterGroupsCombined,
currentViewIdCallbackState,
getViewFromCache,
isPersistingViewFieldsCallbackState,
findManyRecords,
objectMetadataItem.fields,
createViewGroupRecords,
getViewFilterGroupsCombined,
getViewFiltersCombined,
getViewSortsCombined,
createViewSortRecords,
createViewFilterRecords,
createViewFilterGroupRecords,
],
);

View File

@ -1,9 +1,9 @@
import { useRecoilCallback } from 'recoil';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache';
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
import { useGetViewFromPrefetchState } from '@/views/hooks/useGetViewFromPrefetchState';
import { unsavedToDeleteViewFilterIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState';
import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState';
import { isDefined } from 'twenty-shared';
@ -22,11 +22,11 @@ export const useDeleteCombinedViewFilters = (viewBarComponentId?: string) => {
);
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
currentViewIdComponentState,
contextStoreCurrentViewIdComponentState,
viewBarComponentId,
);
const { getViewFromCache } = useGetViewFromCache();
const { getViewFromPrefetchState } = useGetViewFromPrefetchState();
const deleteCombinedViewFilter = useRecoilCallback(
({ snapshot, set }) =>
@ -50,7 +50,7 @@ export const useDeleteCombinedViewFilters = (viewBarComponentId?: string) => {
return;
}
const currentView = await getViewFromCache(currentViewId);
const currentView = await getViewFromPrefetchState(currentViewId);
if (!currentView) {
return;
@ -89,7 +89,7 @@ export const useDeleteCombinedViewFilters = (viewBarComponentId?: string) => {
},
[
currentViewIdCallbackState,
getViewFromCache,
getViewFromPrefetchState,
unsavedToDeleteViewFilterIdsCallbackState,
unsavedToUpsertViewFiltersCallbackState,
],

View File

@ -1,17 +1,16 @@
import { useRecoilCallback } from 'recoil';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache';
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
import { useGetViewFromPrefetchState } from '@/views/hooks/useGetViewFromPrefetchState';
import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewSortIdsComponentFamilyState';
import { unsavedToUpsertViewSortsComponentFamilyState } from '@/views/states/unsavedToUpsertViewSortsComponentFamilyState';
import { isDefined } from 'twenty-shared';
export const useDeleteCombinedViewSorts = (viewBarComponentId?: string) => {
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
currentViewIdComponentState,
viewBarComponentId,
contextStoreCurrentViewIdComponentState,
);
const unsavedToUpsertViewSortsCallbackState =
@ -26,7 +25,7 @@ export const useDeleteCombinedViewSorts = (viewBarComponentId?: string) => {
viewBarComponentId,
);
const { getViewFromCache } = useGetViewFromCache();
const { getViewFromPrefetchState } = useGetViewFromPrefetchState();
const deleteCombinedViewSort = useRecoilCallback(
({ snapshot, set }) =>
@ -50,7 +49,7 @@ export const useDeleteCombinedViewSorts = (viewBarComponentId?: string) => {
unsavedToDeleteViewSortIdsCallbackState({ viewId: currentViewId }),
);
const currentView = await getViewFromCache(currentViewId);
const currentView = await getViewFromPrefetchState(currentViewId);
if (!currentView) {
return;
@ -88,7 +87,7 @@ export const useDeleteCombinedViewSorts = (viewBarComponentId?: string) => {
},
[
currentViewIdCallbackState,
getViewFromCache,
getViewFromPrefetchState,
unsavedToDeleteViewSortIdsCallbackState,
unsavedToUpsertViewSortsCallbackState,
],

View File

@ -1,18 +1,14 @@
import { useRecoilCallback } from 'recoil';
import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { unsavedToDeleteViewFilterGroupIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterGroupIdsComponentFamilyState';
import { unsavedToUpsertViewFilterGroupsComponentFamilyState } from '@/views/states/unsavedToUpsertViewFilterGroupsComponentFamilyState';
import { View } from '@/views/types/View';
import { getCombinedViewFilterGroups } from '@/views/utils/getCombinedViewFilterGroups';
import { isDefined } from 'twenty-shared';
export const useGetViewFilterGroupsCombined = (viewBarComponentId?: string) => {
const { records: views } = usePrefetchedData<View>(PrefetchKey.AllViews);
const unsavedToUpsertViewFilterGroupsCallbackState =
useRecoilComponentCallbackStateV2(
unsavedToUpsertViewFilterGroupsComponentFamilyState,
@ -28,7 +24,13 @@ export const useGetViewFilterGroupsCombined = (viewBarComponentId?: string) => {
const getViewFilterGroupsCombined = useRecoilCallback(
({ snapshot }) =>
(viewId: string) => {
const view = views.find((view) => view.id === viewId);
const view = snapshot
.getLoadable(
prefetchViewFromViewIdFamilySelector({
viewId,
}),
)
.getValue();
if (!isDefined(view)) {
throw new Error(
@ -55,7 +57,6 @@ export const useGetViewFilterGroupsCombined = (viewBarComponentId?: string) => {
return combinedViewFilterGroups;
},
[
views,
unsavedToDeleteViewFilterGroupIdsCallbackState,
unsavedToUpsertViewFilterGroupsCallbackState,
],

View File

@ -1,18 +1,14 @@
import { useRecoilCallback } from 'recoil';
import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { unsavedToDeleteViewFilterIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState';
import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState';
import { View } from '@/views/types/View';
import { getCombinedViewFilters } from '@/views/utils/getCombinedViewFilters';
import { isDefined } from 'twenty-shared';
export const useGetViewFiltersCombined = (viewBarComponentId?: string) => {
const { records: views } = usePrefetchedData<View>(PrefetchKey.AllViews);
const unsavedToUpsertViewFiltersCallbackState =
useRecoilComponentCallbackStateV2(
unsavedToUpsertViewFiltersComponentFamilyState,
@ -28,7 +24,13 @@ export const useGetViewFiltersCombined = (viewBarComponentId?: string) => {
const getViewFiltersCombined = useRecoilCallback(
({ snapshot }) =>
(viewId: string) => {
const view = views.find((view) => view.id === viewId);
const view = snapshot
.getLoadable(
prefetchViewFromViewIdFamilySelector({
viewId,
}),
)
.getValue();
if (!isDefined(view)) {
throw new Error(
@ -55,7 +57,6 @@ export const useGetViewFiltersCombined = (viewBarComponentId?: string) => {
return combinedViewFilters;
},
[
views,
unsavedToDeleteViewFilterIdsCallbackState,
unsavedToUpsertViewFiltersCallbackState,
],

View File

@ -1,19 +1,15 @@
import { useRecoilCallback } from 'recoil';
import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewSortIdsComponentFamilyState';
import { unsavedToUpsertViewSortsComponentFamilyState } from '@/views/states/unsavedToUpsertViewSortsComponentFamilyState';
import { View } from '@/views/types/View';
import { getCombinedViewSorts } from '@/views/utils/getCombinedViewSorts';
import { isDefined } from 'twenty-shared';
// TODO: fix naming
export const useGetViewSortsCombined = (viewBarComponentId?: string) => {
const { records: views } = usePrefetchedData<View>(PrefetchKey.AllViews);
const unsavedToUpsertViewSortsCallbackState =
useRecoilComponentCallbackStateV2(
unsavedToUpsertViewSortsComponentFamilyState,
@ -29,7 +25,13 @@ export const useGetViewSortsCombined = (viewBarComponentId?: string) => {
const getViewSortsCombined = useRecoilCallback(
({ snapshot }) =>
(viewId: string) => {
const view = views.find((view) => view.id === viewId);
const view = snapshot
.getLoadable(
prefetchViewFromViewIdFamilySelector({
viewId,
}),
)
.getValue();
if (!isDefined(view)) {
throw new Error(
@ -56,7 +58,6 @@ export const useGetViewSortsCombined = (viewBarComponentId?: string) => {
return combinedViewSorts;
},
[
views,
unsavedToDeleteViewSortIdsCallbackState,
unsavedToUpsertViewSortsCallbackState,
],

View File

@ -1,13 +1,15 @@
import { useEffect } from 'react';
import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { prefetchIndexViewIdFromObjectMetadataItemFamilySelector } from '@/prefetch/states/selector/prefetchIndexViewIdFromObjectMetadataItemFamilySelector';
import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector';
import { prefetchViewsFromObjectMetadataItemFamilySelector } from '@/prefetch/states/selector/prefetchViewsFromObjectMetadataItemFamilySelector';
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
import { isCurrentViewKeyIndexComponentState } from '@/views/states/isCurrentViewIndexComponentState';
import { unsavedToDeleteViewFilterGroupIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterGroupIdsComponentFamilyState';
import { unsavedToDeleteViewFilterIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState';
@ -15,12 +17,10 @@ import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/u
import { unsavedToUpsertViewFilterGroupsComponentFamilyState } from '@/views/states/unsavedToUpsertViewFilterGroupsComponentFamilyState';
import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState';
import { unsavedToUpsertViewSortsComponentFamilyState } from '@/views/states/unsavedToUpsertViewSortsComponentFamilyState';
import { viewObjectMetadataIdComponentState } from '@/views/states/viewObjectMetadataIdComponentState';
import { View } from '@/views/types/View';
import { getCombinedViewFilterGroups } from '@/views/utils/getCombinedViewFilterGroups';
import { getCombinedViewFilters } from '@/views/utils/getCombinedViewFilters';
import { getCombinedViewSorts } from '@/views/utils/getCombinedViewSorts';
import { getObjectMetadataItemViews } from '@/views/utils/getObjectMetadataItemViews';
import { useRecoilValue } from 'recoil';
import { isDefined } from 'twenty-shared';
export const useGetCurrentView = (viewBarInstanceId?: string) => {
@ -29,16 +29,28 @@ export const useGetCurrentView = (viewBarInstanceId?: string) => {
viewBarInstanceId,
);
const { records: views } = usePrefetchedData<View>(PrefetchKey.AllViews);
const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow();
const currentViewId = useRecoilComponentValueV2(
currentViewIdComponentState,
instanceId,
contextStoreCurrentViewIdComponentState,
);
const viewObjectMetadataId = useRecoilComponentValueV2(
viewObjectMetadataIdComponentState,
instanceId,
const indexViewId = useRecoilValue(
prefetchIndexViewIdFromObjectMetadataItemFamilySelector({
objectMetadataItemId: objectMetadataItem.id,
}),
);
const currentViewFromViewId = useRecoilValue(
prefetchViewFromViewIdFamilySelector({
viewId: currentViewId ?? '',
}),
);
const indexView = useRecoilValue(
prefetchViewFromViewIdFamilySelector({
viewId: indexViewId ?? '',
}),
);
const setIsCurrentViewKeyIndex = useSetRecoilComponentStateV2(
@ -46,25 +58,17 @@ export const useGetCurrentView = (viewBarInstanceId?: string) => {
instanceId,
);
const currentViewFromCurrentViewId = views.find(
(view) => view.id === currentViewId,
);
const indexView = views.find(
(view) =>
view.key === 'INDEX' && view.objectMetadataId === viewObjectMetadataId,
);
const currentView = currentViewId ? currentViewFromCurrentViewId : indexView;
const viewId = currentViewId ?? indexView?.id;
const currentView = currentViewFromViewId ?? indexView;
useEffect(() => {
setIsCurrentViewKeyIndex(currentView?.key === 'INDEX');
}, [currentView, setIsCurrentViewKeyIndex]);
const viewsOnCurrentObject = getObjectMetadataItemViews(
viewObjectMetadataId ?? '',
views,
const viewsOnCurrentObject = useRecoilValue(
prefetchViewsFromObjectMetadataItemFamilySelector({
objectMetadataItemId: objectMetadataItem.id,
}),
);
const unsavedToUpsertViewFilters = useRecoilComponentFamilyValueV2(

View File

@ -1,19 +1,18 @@
import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
import { View } from '@/views/types/View';
import { useMemo } from 'react';
import { useRecoilValue } from 'recoil';
export const useGetCurrentViewOnly = () => {
const { records: views } = usePrefetchedData<View>(PrefetchKey.AllViews);
const currentViewId = useRecoilComponentValueV2(
contextStoreCurrentViewIdComponentState,
);
const currentViewId = useRecoilComponentValueV2(currentViewIdComponentState);
const currentView = useMemo(
() => views.find((view) => view.id === currentViewId),
[views, currentViewId],
const currentView = useRecoilValue(
prefetchViewFromViewIdFamilySelector({
viewId: currentViewId ?? '',
}),
);
return {

View File

@ -1,26 +0,0 @@
import { useCallback } from 'react';
import { useApolloClient } from '@apollo/client';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useGetRecordFromCache } from '@/object-record/cache/hooks/useGetRecordFromCache';
import { View } from '@/views/types/View';
export const useGetViewFromCache = () => {
const client = useApolloClient();
const cache = client.cache;
const getRecordFromCache = useGetRecordFromCache({
objectNameSingular: CoreObjectNameSingular.View,
});
const getViewFromCache = useCallback(
async (viewId: string) => {
return getRecordFromCache<View>(viewId, cache);
},
[cache, getRecordFromCache],
);
return {
getViewFromCache,
};
};

View File

@ -0,0 +1,24 @@
import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector';
import { useRecoilCallback } from 'recoil';
export const useGetViewFromPrefetchState = () => {
const getViewFromPrefetchState = useRecoilCallback(
({ snapshot }) =>
(viewId: string) => {
const view = snapshot
.getLoadable(
prefetchViewFromViewIdFamilySelector({
viewId: viewId,
}),
)
.getValue();
return view;
},
[],
);
return {
getViewFromPrefetchState,
};
};

View File

@ -6,14 +6,11 @@ import { getQueryVariablesFromView } from '@/views/utils/getQueryVariablesFromVi
export const useQueryVariablesFromActiveFieldsOfViewOrDefaultView = ({
objectMetadataItem,
viewId,
}: {
objectMetadataItem: ObjectMetadataItem;
viewId: string | null | undefined;
}) => {
const { view } = useViewOrDefaultViewFromPrefetchedViews({
objectMetadataItemId: objectMetadataItem.id,
viewId,
});
const { activeFieldMetadataItems } = useActiveFieldMetadataItems({

View File

@ -1,29 +1,23 @@
import { useRecoilCallback } from 'recoil';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { usePersistViewFieldRecords } from '@/views/hooks/internal/usePersistViewFieldRecords';
import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache';
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
import { isPersistingViewFieldsComponentState } from '@/views/states/isPersistingViewFieldsComponentState';
import { useGetViewFromPrefetchState } from '@/views/hooks/useGetViewFromPrefetchState';
import { isPersistingViewFieldsState } from '@/views/states/isPersistingViewFieldsState';
import { ViewField } from '@/views/types/ViewField';
import { isDefined } from 'twenty-shared';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
export const useSaveCurrentViewFields = (viewBarComponentId?: string) => {
export const useSaveCurrentViewFields = () => {
const { createViewFieldRecords, updateViewFieldRecords } =
usePersistViewFieldRecords();
const { getViewFromCache } = useGetViewFromCache();
const { getViewFromPrefetchState } = useGetViewFromPrefetchState();
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
currentViewIdComponentState,
viewBarComponentId,
);
const isPersistingViewFieldsCallbackState = useRecoilComponentCallbackStateV2(
isPersistingViewFieldsComponentState,
viewBarComponentId,
contextStoreCurrentViewIdComponentState,
);
const saveViewFields = useRecoilCallback(
@ -37,9 +31,9 @@ export const useSaveCurrentViewFields = (viewBarComponentId?: string) => {
return;
}
set(isPersistingViewFieldsCallbackState, true);
set(isPersistingViewFieldsState, true);
const view = await getViewFromCache(currentViewId);
const view = await getViewFromPrefetchState(currentViewId);
if (isUndefinedOrNull(view)) {
return;
@ -94,13 +88,12 @@ export const useSaveCurrentViewFields = (viewBarComponentId?: string) => {
updateViewFieldRecords(viewFieldsToUpdate),
]);
set(isPersistingViewFieldsCallbackState, false);
set(isPersistingViewFieldsState, false);
},
[
createViewFieldRecords,
currentViewIdCallbackState,
getViewFromCache,
isPersistingViewFieldsCallbackState,
getViewFromPrefetchState,
updateViewFieldRecords,
],
);

View File

@ -1,13 +1,13 @@
import { useRecoilCallback } from 'recoil';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { usePersistViewFilterGroupRecords } from '@/views/hooks/internal/usePersistViewFilterGroupRecords';
import { usePersistViewSortRecords } from '@/views/hooks/internal/usePersistViewSortRecords';
import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache';
import { useGetViewFromPrefetchState } from '@/views/hooks/useGetViewFromPrefetchState';
import { useResetUnsavedViewStates } from '@/views/hooks/useResetUnsavedViewStates';
import { useSaveRecordFiltersToViewFilters } from '@/views/hooks/useSaveRecordFiltersToViewFilters';
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
import { unsavedToDeleteViewFilterGroupIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterGroupIdsComponentFamilyState';
import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewSortIdsComponentFamilyState';
import { unsavedToUpsertViewFilterGroupsComponentFamilyState } from '@/views/states/unsavedToUpsertViewFilterGroupsComponentFamilyState';
@ -18,10 +18,10 @@ import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
export const useSaveCurrentViewFiltersAndSorts = (
viewBarComponentId?: string,
) => {
const { getViewFromCache } = useGetViewFromCache();
const { getViewFromPrefetchState } = useGetViewFromPrefetchState();
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
currentViewIdComponentState,
contextStoreCurrentViewIdComponentState,
viewBarComponentId,
);
@ -77,7 +77,7 @@ export const useSaveCurrentViewFiltersAndSorts = (
unsavedToUpsertViewSortsCallbackState({ viewId }),
);
const view = await getViewFromCache(viewId);
const view = await getViewFromPrefetchState(viewId);
if (isUndefinedOrNull(view)) {
return;
@ -103,7 +103,7 @@ export const useSaveCurrentViewFiltersAndSorts = (
[
createViewSortRecords,
deleteViewSortRecords,
getViewFromCache,
getViewFromPrefetchState,
unsavedToDeleteViewSortIdsCallbackState,
unsavedToUpsertViewSortsCallbackState,
updateViewSortRecords,
@ -123,7 +123,7 @@ export const useSaveCurrentViewFiltersAndSorts = (
unsavedToUpsertViewFilterGroupsCallbackState({ viewId }),
);
const view = await getViewFromCache(viewId);
const view = await getViewFromPrefetchState(viewId);
if (isUndefinedOrNull(view)) {
return;
@ -150,7 +150,7 @@ export const useSaveCurrentViewFiltersAndSorts = (
await deleteViewFilterGroupRecords(unsavedToDeleteViewFilterGroupIds);
},
[
getViewFromCache,
getViewFromPrefetchState,
createViewFilterGroupRecords,
deleteViewFilterGroupRecords,
unsavedToDeleteViewFilterGroupIdsCallbackState,

View File

@ -1,9 +1,9 @@
import { useRecoilCallback } from 'recoil';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { usePersistViewGroupRecords } from '@/views/hooks/internal/usePersistViewGroupRecords';
import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache';
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
import { useGetViewFromPrefetchState } from '@/views/hooks/useGetViewFromPrefetchState';
import { ViewGroup } from '@/views/types/ViewGroup';
import { isDefined } from 'twenty-shared';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
@ -13,10 +13,10 @@ export const useSaveCurrentViewGroups = (viewBarComponentId?: string) => {
const { createViewGroupRecords, updateViewGroupRecords } =
usePersistViewGroupRecords();
const { getViewFromCache } = useGetViewFromCache();
const { getViewFromPrefetchState } = useGetViewFromPrefetchState();
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
currentViewIdComponentState,
contextStoreCurrentViewIdComponentState,
viewBarComponentId,
);
@ -31,7 +31,7 @@ export const useSaveCurrentViewGroups = (viewBarComponentId?: string) => {
return;
}
const view = await getViewFromCache(currentViewId);
const view = await getViewFromPrefetchState(currentViewId);
if (isUndefinedOrNull(view)) {
return;
@ -67,7 +67,11 @@ export const useSaveCurrentViewGroups = (viewBarComponentId?: string) => {
{ ...viewGroupToSave, id: existingField.id },
]);
},
[currentViewIdCallbackState, getViewFromCache, updateViewGroupRecords],
[
currentViewIdCallbackState,
getViewFromPrefetchState,
updateViewGroupRecords,
],
);
const saveViewGroups = useRecoilCallback(
@ -81,7 +85,7 @@ export const useSaveCurrentViewGroups = (viewBarComponentId?: string) => {
return;
}
const view = await getViewFromCache(currentViewId);
const view = await getViewFromPrefetchState(currentViewId);
if (isUndefinedOrNull(view)) {
return;
@ -135,7 +139,7 @@ export const useSaveCurrentViewGroups = (viewBarComponentId?: string) => {
[
createViewGroupRecords,
currentViewIdCallbackState,
getViewFromCache,
getViewFromPrefetchState,
updateViewGroupRecords,
],
);

View File

@ -1,16 +1,15 @@
import { useRecoilCallback } from 'recoil';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
import { GraphQLView } from '@/views/types/GraphQLView';
import { isDefined } from 'twenty-shared';
export const useUpdateCurrentView = (viewBarComponentId?: string) => {
export const useUpdateCurrentView = () => {
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
currentViewIdComponentState,
viewBarComponentId,
contextStoreCurrentViewIdComponentState,
);
const { updateOneRecord } = useUpdateOneRecord({

View File

@ -1,12 +1,14 @@
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { ExtendedAggregateOperations } from '@/object-record/record-table/types/ExtendedAggregateOperations';
import { convertExtendedAggregateOperationToAggregateOperation } from '@/object-record/utils/convertExtendedAggregateOperationToAggregateOperation';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useUpdateView } from '@/views/hooks/useUpdateView';
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
import { useCallback } from 'react';
export const useUpdateViewAggregate = () => {
const currentViewId = useRecoilComponentValueV2(currentViewIdComponentState);
const currentViewId = useRecoilComponentValueV2(
contextStoreCurrentViewIdComponentState,
);
const { updateView } = useUpdateView();
const updateViewAggregate = useCallback(
({

View File

@ -1,10 +1,10 @@
import { useRecoilCallback } from 'recoil';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache';
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
import { useGetViewFromPrefetchState } from '@/views/hooks/useGetViewFromPrefetchState';
import { unsavedToDeleteViewFilterIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState';
import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState';
import { ViewFilter } from '@/views/types/ViewFilter';
@ -25,11 +25,11 @@ export const useUpsertCombinedViewFilters = (viewBarComponentId?: string) => {
);
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
currentViewIdComponentState,
contextStoreCurrentViewIdComponentState,
viewBarComponentId,
);
const { getViewFromCache } = useGetViewFromCache();
const { getViewFromPrefetchState } = useGetViewFromPrefetchState();
const upsertCombinedViewFilter = useRecoilCallback(
({ snapshot, set }) =>
@ -53,7 +53,7 @@ export const useUpsertCombinedViewFilters = (viewBarComponentId?: string) => {
return;
}
const currentView = await getViewFromCache(currentViewId);
const currentView = await getViewFromPrefetchState(currentViewId);
if (!currentView) {
return;
@ -120,7 +120,7 @@ export const useUpsertCombinedViewFilters = (viewBarComponentId?: string) => {
},
[
currentViewIdCallbackState,
getViewFromCache,
getViewFromPrefetchState,
unsavedToDeleteViewFilterIdsCallbackState,
unsavedToUpsertViewFiltersCallbackState,
],

View File

@ -1,11 +1,11 @@
import { useRecoilCallback } from 'recoil';
import { v4 } from 'uuid';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { Sort } from '@/object-record/object-sort-dropdown/types/Sort';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache';
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
import { useGetViewFromPrefetchState } from '@/views/hooks/useGetViewFromPrefetchState';
import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewSortIdsComponentFamilyState';
import { unsavedToUpsertViewSortsComponentFamilyState } from '@/views/states/unsavedToUpsertViewSortsComponentFamilyState';
import { ViewSort } from '@/views/types/ViewSort';
@ -13,8 +13,7 @@ import { isDefined } from 'twenty-shared';
export const useUpsertCombinedViewSorts = (viewBarComponentId?: string) => {
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
currentViewIdComponentState,
viewBarComponentId,
contextStoreCurrentViewIdComponentState,
);
const unsavedToUpsertViewSortsCallbackState =
@ -29,7 +28,7 @@ export const useUpsertCombinedViewSorts = (viewBarComponentId?: string) => {
viewBarComponentId,
);
const { getViewFromCache } = useGetViewFromCache();
const { getViewFromPrefetchState } = useGetViewFromPrefetchState();
const upsertCombinedViewSort = useRecoilCallback(
({ snapshot, set }) =>
@ -53,7 +52,7 @@ export const useUpsertCombinedViewSorts = (viewBarComponentId?: string) => {
return;
}
const currentView = await getViewFromCache(currentViewId);
const currentView = await getViewFromPrefetchState(currentViewId);
if (!currentView) {
return;
@ -111,7 +110,7 @@ export const useUpsertCombinedViewSorts = (viewBarComponentId?: string) => {
},
[
currentViewIdCallbackState,
getViewFromCache,
getViewFromPrefetchState,
unsavedToDeleteViewSortIdsCallbackState,
unsavedToUpsertViewSortsCallbackState,
],

View File

@ -1,24 +1,23 @@
import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
import { View } from '@/views/types/View';
import { useMemo } from 'react';
import { prefetchIndexViewIdFromObjectMetadataItemFamilySelector } from '@/prefetch/states/selector/prefetchIndexViewIdFromObjectMetadataItemFamilySelector';
import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector';
import { useRecoilValue } from 'recoil';
export const useViewOrDefaultViewFromPrefetchedViews = ({
objectMetadataItemId,
viewId,
}: {
objectMetadataItemId: string;
viewId: string | null | undefined;
}) => {
const { records: views } = usePrefetchedData<View>(PrefetchKey.AllViews);
const indexViewId = useRecoilValue(
prefetchIndexViewIdFromObjectMetadataItemFamilySelector({
objectMetadataItemId,
}),
);
const view = useMemo(() => {
return views.find(
(view: View) =>
(view.key === 'INDEX' || view?.id === viewId) &&
view?.objectMetadataId === objectMetadataItemId,
);
}, [viewId, views, objectMetadataItemId]);
const indexView = useRecoilValue(
prefetchViewFromViewIdFamilySelector({
viewId: indexViewId ?? '',
}),
);
return { view };
return { view: indexView };
};

View File

@ -1,10 +0,0 @@
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
export const currentViewIdComponentState = createComponentStateV2<
string | undefined
>({
key: 'currentViewIdComponentState',
defaultValue: undefined,
componentInstanceContext: ViewComponentInstanceContext,
});

View File

@ -1,9 +0,0 @@
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
export const isPersistingViewFieldsComponentState =
createComponentStateV2<boolean>({
key: 'isPersistingViewFieldsComponentState',
defaultValue: false,
componentInstanceContext: ViewComponentInstanceContext,
});

View File

@ -0,0 +1,6 @@
import { createState } from 'twenty-ui';
export const isPersistingViewFieldsState = createState<boolean>({
key: 'isPersistingViewFieldsState',
defaultValue: false,
});

View File

@ -18,9 +18,8 @@ export const mapViewFiltersToFilters = (
);
if (!isDefined(availableFieldMetadataItem)) {
throw new Error(
`Field metadata item not found for view filter ${viewFilter.id} and field metadata id ${viewFilter.fieldMetadataId}`,
);
// Todo: we we don't throw an error yet as we have race condition on view change
return undefined;
}
const filterType = getFilterTypeFromFieldType(

View File

@ -1,9 +1,10 @@
import { useEffect } from 'react';
import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow';
import { prefetchViewsFromObjectMetadataItemFamilySelector } from '@/prefetch/states/selector/prefetchViewsFromObjectMetadataItemFamilySelector';
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
import { ViewType } from '@/views/types/ViewType';
import { useGetAvailableFieldsForKanban } from '@/views/view-picker/hooks/useGetAvailableFieldsForKanban';
import { useViewPickerMode } from '@/views/view-picker/hooks/useViewPickerMode';
@ -14,6 +15,7 @@ import { viewPickerKanbanFieldMetadataIdComponentState } from '@/views/view-pick
import { viewPickerReferenceViewIdComponentState } from '@/views/view-picker/states/viewPickerReferenceViewIdComponentState';
import { viewPickerSelectedIconComponentState } from '@/views/view-picker/states/viewPickerSelectedIconComponentState';
import { viewPickerTypeComponentState } from '@/views/view-picker/states/viewPickerTypeComponentState';
import { useRecoilValue } from 'recoil';
import { isDefined } from 'twenty-shared';
export const ViewPickerContentEffect = () => {
@ -44,7 +46,13 @@ export const ViewPickerContentEffect = () => {
viewPickerIsPersistingComponentState,
);
const { viewsOnCurrentObject } = useGetCurrentView();
const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow();
const viewsOnCurrentObject = useRecoilValue(
prefetchViewsFromObjectMetadataItemFamilySelector({
objectMetadataItemId: objectMetadataItem.id,
}),
);
const referenceView = viewsOnCurrentObject.find(
(view) => view.id === viewPickerReferenceViewId,
);

View File

@ -1,21 +1,23 @@
import { FavoriteFolderPicker } from '@/favorites/favorite-folder-picker/components/FavoriteFolderPicker';
import { FavoriteFolderPickerEffect } from '@/favorites/favorite-folder-picker/components/FavoriteFolderPickerEffect';
import { FavoriteFolderPickerComponentInstanceContext } from '@/favorites/favorite-folder-picker/scopes/FavoriteFolderPickerScope';
import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector';
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
import { View } from '@/views/types/View';
import { VIEW_PICKER_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerDropdownId';
import { viewPickerReferenceViewIdComponentState } from '@/views/view-picker/states/viewPickerReferenceViewIdComponentState';
import { useRecoilValue } from 'recoil';
export const ViewPickerFavoriteFoldersDropdown = () => {
const { records: views } = usePrefetchedData<View>(PrefetchKey.AllViews);
const [viewPickerReferenceViewId] = useRecoilComponentStateV2(
viewPickerReferenceViewIdComponentState,
);
const view = views.find((view) => view.id === viewPickerReferenceViewId);
const view = useRecoilValue(
prefetchViewFromViewIdFamilySelector({
viewId: viewPickerReferenceViewId ?? '',
}),
);
return (
<FavoriteFolderPickerComponentInstanceContext

View File

@ -24,6 +24,7 @@ const StyledBoldDropdownMenuItemsContainer = styled(DropdownMenuItemsContainer)`
export const ViewPickerListContent = () => {
const { currentViewWithCombinedFiltersAndSorts, viewsOnCurrentObject } =
useGetCurrentView();
const setViewPickerReferenceViewId = useSetRecoilComponentStateV2(
viewPickerReferenceViewIdComponentState,
);

View File

@ -1,45 +1,31 @@
import { useCallback } from 'react';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { useDropdownV2 } from '@/ui/layout/dropdown/hooks/useDropdownV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { VIEW_PICKER_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerDropdownId';
import { VIEW_PICKER_KANBAN_FIELD_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerKanbanFieldDropdownId';
import { VIEW_PICKER_VIEW_TYPE_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerViewTypeDropdownId';
import { useViewPickerMode } from '@/views/view-picker/hooks/useViewPickerMode';
import { viewPickerIsPersistingComponentState } from '@/views/view-picker/states/viewPickerIsPersistingComponentState';
import { viewPickerModeComponentState } from '@/views/view-picker/states/viewPickerModeComponentState';
export const useCloseAndResetViewPicker = () => {
const { setViewPickerMode } = useViewPickerMode();
const setViewPickerMode = useSetRecoilComponentStateV2(
viewPickerModeComponentState,
);
const setViewPickerIsPersisting = useSetRecoilComponentStateV2(
viewPickerIsPersistingComponentState,
);
const { closeDropdown: closeViewPickerDropdown } = useDropdown(
VIEW_PICKER_DROPDOWN_ID,
);
const { closeDropdown: closeKanbanFieldDropdown } = useDropdown(
VIEW_PICKER_KANBAN_FIELD_DROPDOWN_ID,
);
const { closeDropdown: closeTypeDropdown } = useDropdown(
VIEW_PICKER_VIEW_TYPE_DROPDOWN_ID,
);
const { closeDropdown } = useDropdownV2();
const closeAndResetViewPicker = useCallback(() => {
setViewPickerIsPersisting(false);
setViewPickerMode('list');
closeKanbanFieldDropdown();
closeTypeDropdown();
closeViewPickerDropdown();
}, [
closeKanbanFieldDropdown,
closeTypeDropdown,
closeViewPickerDropdown,
setViewPickerIsPersisting,
setViewPickerMode,
]);
closeDropdown(VIEW_PICKER_KANBAN_FIELD_DROPDOWN_ID);
closeDropdown(VIEW_PICKER_VIEW_TYPE_DROPDOWN_ID);
closeDropdown(VIEW_PICKER_DROPDOWN_ID);
}, [closeDropdown, setViewPickerIsPersisting, setViewPickerMode]);
return { closeAndResetViewPicker };
};