From 9ad87d4b52df89ada9327392bc113b29475ef3aa Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Mon, 17 Feb 2025 18:06:02 +0100 Subject: [PATCH 01/14] Refacto views --- .../hooks/useResetContextStoreStates.ts | 2 +- ...contextStoreCurrentViewIdComponentState.ts | 4 +-- .../hooks/useDeleteCombinedViewFilterGroup.ts | 5 ++- ...ptionsDropdownRecordGroupFieldsContent.tsx | 4 +-- .../hooks/useObjectOptionsForBoard.ts | 2 +- .../hooks/useHandleIndexIdentifierClick.ts | 4 +-- .../hooks/useHandleRecordGroupField.ts | 13 ++----- .../components/QueryParamsFiltersEffect.tsx | 6 ++-- .../components/QueryParamsViewIdEffect.tsx | 35 ------------------- .../components/UpdateViewButtonGroup.tsx | 6 ++-- .../src/modules/views/components/ViewBar.tsx | 2 -- ...ViewFiltersToCurrentRecordFilters.test.tsx | 8 ++--- ...urrentViewFiltersToCurrentRecordFilters.ts | 6 ++-- .../hooks/useCreateViewFromCurrentView.ts | 4 +-- .../hooks/useDeleteCombinedViewFilters.ts | 4 +-- .../views/hooks/useDeleteCombinedViewSorts.ts | 5 ++- .../modules/views/hooks/useGetCurrentView.ts | 5 ++- .../views/hooks/useGetCurrentViewOnly.ts | 6 ++-- .../views/hooks/useSaveCurrentViewFields.ts | 5 ++- .../useSaveCurrentViewFiltersAndSorts.ts | 4 +-- .../views/hooks/useSaveCurrentViewGroups.ts | 4 +-- .../views/hooks/useUpdateCurrentView.ts | 7 ++-- .../views/hooks/useUpdateViewAggregate.ts | 6 ++-- .../hooks/useUpsertCombinedViewFilters.ts | 4 +-- .../views/hooks/useUpsertCombinedViewSorts.ts | 5 ++- .../states/currentViewIdComponentState.ts | 10 ------ .../views/utils/mapViewFiltersToFilters.ts | 5 ++- .../pages/object-record/RecordIndexPage.tsx | 3 +- 28 files changed, 60 insertions(+), 114 deletions(-) delete mode 100644 packages/twenty-front/src/modules/views/components/QueryParamsViewIdEffect.tsx delete mode 100644 packages/twenty-front/src/modules/views/states/currentViewIdComponentState.ts diff --git a/packages/twenty-front/src/modules/command-menu/hooks/useResetContextStoreStates.ts b/packages/twenty-front/src/modules/command-menu/hooks/useResetContextStoreStates.ts index 795bb12531c8..4a3ae31b07bd 100644 --- a/packages/twenty-front/src/modules/command-menu/hooks/useResetContextStoreStates.ts +++ b/packages/twenty-front/src/modules/command-menu/hooks/useResetContextStoreStates.ts @@ -45,7 +45,7 @@ export const useResetContextStoreStates = () => { contextStoreCurrentViewIdComponentState.atomFamily({ instanceId, }), - null, + undefined, ); set( diff --git a/packages/twenty-front/src/modules/context-store/states/contextStoreCurrentViewIdComponentState.ts b/packages/twenty-front/src/modules/context-store/states/contextStoreCurrentViewIdComponentState.ts index 10136c28d004..c351a849584f 100644 --- a/packages/twenty-front/src/modules/context-store/states/contextStoreCurrentViewIdComponentState.ts +++ b/packages/twenty-front/src/modules/context-store/states/contextStoreCurrentViewIdComponentState.ts @@ -2,9 +2,9 @@ import { ContextStoreComponentInstanceContext } from '@/context-store/states/con import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; export const contextStoreCurrentViewIdComponentState = createComponentStateV2< - string | null + string | undefined >({ key: 'contextStoreCurrentViewIdComponentState', - defaultValue: null, + defaultValue: undefined, componentInstanceContext: ContextStoreComponentInstanceContext, }); diff --git a/packages/twenty-front/src/modules/object-record/advanced-filter/hooks/useDeleteCombinedViewFilterGroup.ts b/packages/twenty-front/src/modules/object-record/advanced-filter/hooks/useDeleteCombinedViewFilterGroup.ts index c9a7ad93ca81..d6e68280e491 100644 --- a/packages/twenty-front/src/modules/object-record/advanced-filter/hooks/useDeleteCombinedViewFilterGroup.ts +++ b/packages/twenty-front/src/modules/object-record/advanced-filter/hooks/useDeleteCombinedViewFilterGroup.ts @@ -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 { unsavedToDeleteViewFilterGroupIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterGroupIdsComponentFamilyState'; import { unsavedToUpsertViewFilterGroupsComponentFamilyState } from '@/views/states/unsavedToUpsertViewFilterGroupsComponentFamilyState'; import { isDefined } from 'twenty-shared'; @@ -24,8 +24,7 @@ export const useDeleteCombinedViewFilterGroup = ( ); const currentViewIdCallbackState = useRecoilComponentCallbackStateV2( - currentViewIdComponentState, - viewBarComponentId, + contextStoreCurrentViewIdComponentState, ); const { getViewFromCache } = useGetViewFromCache(); diff --git a/packages/twenty-front/src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownRecordGroupFieldsContent.tsx b/packages/twenty-front/src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownRecordGroupFieldsContent.tsx index 314b49c95cef..b8258a88865d 100644 --- a/packages/twenty-front/src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownRecordGroupFieldsContent.tsx +++ b/packages/twenty-front/src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownRecordGroupFieldsContent.tsx @@ -64,9 +64,7 @@ export const ObjectOptionsDropdownRecordGroupFieldsContent = () => { const { handleRecordGroupFieldChange: setRecordGroupField, resetRecordGroupField, - } = useHandleRecordGroupField({ - viewBarComponentId: recordIndexId, - }); + } = useHandleRecordGroupField(); const newSelectFieldSettingsUrl = getSettingsPath( SettingsPath.ObjectNewFieldConfigure, diff --git a/packages/twenty-front/src/modules/object-record/object-options-dropdown/hooks/useObjectOptionsForBoard.ts b/packages/twenty-front/src/modules/object-record/object-options-dropdown/hooks/useObjectOptionsForBoard.ts index 3dba54dc3835..a7542942f036 100644 --- a/packages/twenty-front/src/modules/object-record/object-options-dropdown/hooks/useObjectOptionsForBoard.ts +++ b/packages/twenty-front/src/modules/object-record/object-options-dropdown/hooks/useObjectOptionsForBoard.ts @@ -32,7 +32,7 @@ export const useObjectOptionsForBoard = ({ useRecoilState(recordIndexFieldDefinitionsState); const { saveViewFields } = useSaveCurrentViewFields(viewBarId); - const { updateCurrentView } = useUpdateCurrentView(viewBarId); + const { updateCurrentView } = useUpdateCurrentView(); const [isCompactModeActive, setIsCompactModeActive] = useRecoilComponentStateV2( diff --git a/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleIndexIdentifierClick.ts b/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleIndexIdentifierClick.ts index 0cd17e877e1c..efb30e485852 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleIndexIdentifierClick.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleIndexIdentifierClick.ts @@ -1,7 +1,7 @@ +import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { AppPath } from '@/types/AppPath'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; -import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState'; import { getAppPath } from '~/utils/navigation/getAppPath'; export const useHandleIndexIdentifierClick = ({ @@ -12,7 +12,7 @@ export const useHandleIndexIdentifierClick = ({ objectMetadataItem: ObjectMetadataItem; }) => { const currentViewId = useRecoilComponentValueV2( - currentViewIdComponentState, + contextStoreCurrentViewIdComponentState, recordIndexId, ); diff --git a/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleRecordGroupField.ts b/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleRecordGroupField.ts index 2666578bc178..205b3633178d 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleRecordGroupField.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleRecordGroupField.ts @@ -1,26 +1,19 @@ +import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState'; import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; 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 { ViewGroup } from '@/views/types/ViewGroup'; import { useRecoilCallback } from 'recoil'; import { v4 } from 'uuid'; import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull'; -type UseHandleRecordGroupFieldParams = { - viewBarComponentId: string; -}; - -export const useHandleRecordGroupField = ({ - viewBarComponentId, -}: UseHandleRecordGroupFieldParams) => { +export const useHandleRecordGroupField = () => { const { createViewGroupRecords, deleteViewGroupRecords } = usePersistViewGroupRecords(); const currentViewIdCallbackState = useRecoilComponentCallbackStateV2( - currentViewIdComponentState, - viewBarComponentId, + contextStoreCurrentViewIdComponentState, ); const { getViewFromCache } = useGetViewFromCache(); diff --git a/packages/twenty-front/src/modules/views/components/QueryParamsFiltersEffect.tsx b/packages/twenty-front/src/modules/views/components/QueryParamsFiltersEffect.tsx index 11aca3c3f42c..ca89c5456ae6 100644 --- a/packages/twenty-front/src/modules/views/components/QueryParamsFiltersEffect.tsx +++ b/packages/twenty-front/src/modules/views/components/QueryParamsFiltersEffect.tsx @@ -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, diff --git a/packages/twenty-front/src/modules/views/components/QueryParamsViewIdEffect.tsx b/packages/twenty-front/src/modules/views/components/QueryParamsViewIdEffect.tsx deleted file mode 100644 index d86c2bf1da2c..000000000000 --- a/packages/twenty-front/src/modules/views/components/QueryParamsViewIdEffect.tsx +++ /dev/null @@ -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 <>; -}; diff --git a/packages/twenty-front/src/modules/views/components/UpdateViewButtonGroup.tsx b/packages/twenty-front/src/modules/views/components/UpdateViewButtonGroup.tsx index 4cc33451ef8b..0ed97948dc43 100644 --- a/packages/twenty-front/src/modules/views/components/UpdateViewButtonGroup.tsx +++ b/packages/twenty-front/src/modules/views/components/UpdateViewButtonGroup.tsx @@ -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, diff --git a/packages/twenty-front/src/modules/views/components/ViewBar.tsx b/packages/twenty-front/src/modules/views/components/ViewBar.tsx index 73f84fdb77df..5f4ba10904dc 100644 --- a/packages/twenty-front/src/modules/views/components/ViewBar.tsx +++ b/packages/twenty-front/src/modules/views/components/ViewBar.tsx @@ -7,7 +7,6 @@ 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'; @@ -59,7 +58,6 @@ export const ViewBar = ({ - { mockObjectMetadataItemNameSingular, onInitializeRecoilSnapshot: (snapshot) => { snapshot.set( - currentViewIdComponentState.atomFamily({ + contextStoreCurrentViewIdComponentState.atomFamily({ instanceId: 'instanceId', }), mockView.id, @@ -131,7 +131,7 @@ describe('useApplyCurrentViewFiltersToCurrentRecordFilters', () => { mockObjectMetadataItemNameSingular, onInitializeRecoilSnapshot: (snapshot) => { snapshot.set( - currentViewIdComponentState.atomFamily({ + contextStoreCurrentViewIdComponentState.atomFamily({ instanceId: 'instanceId', }), mockView.id, @@ -180,7 +180,7 @@ describe('useApplyCurrentViewFiltersToCurrentRecordFilters', () => { mockObjectMetadataItemNameSingular, onInitializeRecoilSnapshot: (snapshot) => { snapshot.set( - currentViewIdComponentState.atomFamily({ + contextStoreCurrentViewIdComponentState.atomFamily({ instanceId: 'instanceId', }), mockView.id, diff --git a/packages/twenty-front/src/modules/views/hooks/useApplyCurrentViewFiltersToCurrentRecordFilters.ts b/packages/twenty-front/src/modules/views/hooks/useApplyCurrentViewFiltersToCurrentRecordFilters.ts index f35ee75651f4..5fb1e786a7d5 100644 --- a/packages/twenty-front/src/modules/views/hooks/useApplyCurrentViewFiltersToCurrentRecordFilters.ts +++ b/packages/twenty-front/src/modules/views/hooks/useApplyCurrentViewFiltersToCurrentRecordFilters.ts @@ -1,10 +1,10 @@ +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 { 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'; @@ -13,7 +13,9 @@ import { isDefined } from 'twenty-shared'; export const useApplyCurrentViewFiltersToCurrentRecordFilters = () => { const { records: views } = usePrefetchedData(PrefetchKey.AllViews); - const currentViewId = useRecoilComponentValueV2(currentViewIdComponentState); + const currentViewId = useRecoilComponentValueV2( + contextStoreCurrentViewIdComponentState, + ); const setCurrentRecordFilters = useSetRecoilComponentStateV2( currentRecordFiltersComponentState, diff --git a/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts b/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts index b246becd55e2..874de3fc8dff 100644 --- a/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts +++ b/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts @@ -1,3 +1,4 @@ +import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord'; import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext'; @@ -12,7 +13,6 @@ import { useGetViewFilterGroupsCombined } from '@/views/hooks/useGetCombinedView 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 { GraphQLView } from '@/views/types/GraphQLView'; import { View } from '@/views/types/View'; @@ -25,7 +25,7 @@ import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull'; export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => { const currentViewIdCallbackState = useRecoilComponentCallbackStateV2( - currentViewIdComponentState, + contextStoreCurrentViewIdComponentState, viewBarComponentId, ); diff --git a/packages/twenty-front/src/modules/views/hooks/useDeleteCombinedViewFilters.ts b/packages/twenty-front/src/modules/views/hooks/useDeleteCombinedViewFilters.ts index 1bdf6aec3227..2246a77a3fb2 100644 --- a/packages/twenty-front/src/modules/views/hooks/useDeleteCombinedViewFilters.ts +++ b/packages/twenty-front/src/modules/views/hooks/useDeleteCombinedViewFilters.ts @@ -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 { unsavedToDeleteViewFilterIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState'; import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState'; import { isDefined } from 'twenty-shared'; @@ -22,7 +22,7 @@ export const useDeleteCombinedViewFilters = (viewBarComponentId?: string) => { ); const currentViewIdCallbackState = useRecoilComponentCallbackStateV2( - currentViewIdComponentState, + contextStoreCurrentViewIdComponentState, viewBarComponentId, ); diff --git a/packages/twenty-front/src/modules/views/hooks/useDeleteCombinedViewSorts.ts b/packages/twenty-front/src/modules/views/hooks/useDeleteCombinedViewSorts.ts index 048b06dce0c1..66e10c1fe1b4 100644 --- a/packages/twenty-front/src/modules/views/hooks/useDeleteCombinedViewSorts.ts +++ b/packages/twenty-front/src/modules/views/hooks/useDeleteCombinedViewSorts.ts @@ -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 { 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 = diff --git a/packages/twenty-front/src/modules/views/hooks/useGetCurrentView.ts b/packages/twenty-front/src/modules/views/hooks/useGetCurrentView.ts index 9c25b8722ec7..9c6ec9a4c629 100644 --- a/packages/twenty-front/src/modules/views/hooks/useGetCurrentView.ts +++ b/packages/twenty-front/src/modules/views/hooks/useGetCurrentView.ts @@ -1,5 +1,6 @@ import { useEffect } from 'react'; +import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState'; import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData'; import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow'; @@ -7,7 +8,6 @@ import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/component- 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'; @@ -32,8 +32,7 @@ export const useGetCurrentView = (viewBarInstanceId?: string) => { const { records: views } = usePrefetchedData(PrefetchKey.AllViews); const currentViewId = useRecoilComponentValueV2( - currentViewIdComponentState, - instanceId, + contextStoreCurrentViewIdComponentState, ); const viewObjectMetadataId = useRecoilComponentValueV2( diff --git a/packages/twenty-front/src/modules/views/hooks/useGetCurrentViewOnly.ts b/packages/twenty-front/src/modules/views/hooks/useGetCurrentViewOnly.ts index e6fb9bed9e87..8bb90703e45f 100644 --- a/packages/twenty-front/src/modules/views/hooks/useGetCurrentViewOnly.ts +++ b/packages/twenty-front/src/modules/views/hooks/useGetCurrentViewOnly.ts @@ -1,7 +1,7 @@ +import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState'; import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData'; import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; 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'; @@ -9,7 +9,9 @@ import { useMemo } from 'react'; export const useGetCurrentViewOnly = () => { const { records: views } = usePrefetchedData(PrefetchKey.AllViews); - const currentViewId = useRecoilComponentValueV2(currentViewIdComponentState); + const currentViewId = useRecoilComponentValueV2( + contextStoreCurrentViewIdComponentState, + ); const currentView = useMemo( () => views.find((view) => view.id === currentViewId), diff --git a/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFields.ts b/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFields.ts index 832999fb885e..4bcd1cfefc7c 100644 --- a/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFields.ts +++ b/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFields.ts @@ -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 { 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 { ViewField } from '@/views/types/ViewField'; import { isDefined } from 'twenty-shared'; @@ -17,8 +17,7 @@ export const useSaveCurrentViewFields = (viewBarComponentId?: string) => { const { getViewFromCache } = useGetViewFromCache(); const currentViewIdCallbackState = useRecoilComponentCallbackStateV2( - currentViewIdComponentState, - viewBarComponentId, + contextStoreCurrentViewIdComponentState, ); const isPersistingViewFieldsCallbackState = useRecoilComponentCallbackStateV2( diff --git a/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFiltersAndSorts.ts b/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFiltersAndSorts.ts index d74d8528be9c..27cdeb13f73d 100644 --- a/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFiltersAndSorts.ts +++ b/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFiltersAndSorts.ts @@ -1,5 +1,6 @@ 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'; @@ -7,7 +8,6 @@ import { usePersistViewSortRecords } from '@/views/hooks/internal/usePersistView import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache'; 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'; @@ -21,7 +21,7 @@ export const useSaveCurrentViewFiltersAndSorts = ( const { getViewFromCache } = useGetViewFromCache(); const currentViewIdCallbackState = useRecoilComponentCallbackStateV2( - currentViewIdComponentState, + contextStoreCurrentViewIdComponentState, viewBarComponentId, ); diff --git a/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewGroups.ts b/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewGroups.ts index 83c92ebdfb76..c4345a0b30a3 100644 --- a/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewGroups.ts +++ b/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewGroups.ts @@ -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 { ViewGroup } from '@/views/types/ViewGroup'; import { isDefined } from 'twenty-shared'; import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; @@ -16,7 +16,7 @@ export const useSaveCurrentViewGroups = (viewBarComponentId?: string) => { const { getViewFromCache } = useGetViewFromCache(); const currentViewIdCallbackState = useRecoilComponentCallbackStateV2( - currentViewIdComponentState, + contextStoreCurrentViewIdComponentState, viewBarComponentId, ); diff --git a/packages/twenty-front/src/modules/views/hooks/useUpdateCurrentView.ts b/packages/twenty-front/src/modules/views/hooks/useUpdateCurrentView.ts index 8f3e151302cb..4c626d5d809d 100644 --- a/packages/twenty-front/src/modules/views/hooks/useUpdateCurrentView.ts +++ b/packages/twenty-front/src/modules/views/hooks/useUpdateCurrentView.ts @@ -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({ diff --git a/packages/twenty-front/src/modules/views/hooks/useUpdateViewAggregate.ts b/packages/twenty-front/src/modules/views/hooks/useUpdateViewAggregate.ts index c9924120a260..e65cbbbfc3cb 100644 --- a/packages/twenty-front/src/modules/views/hooks/useUpdateViewAggregate.ts +++ b/packages/twenty-front/src/modules/views/hooks/useUpdateViewAggregate.ts @@ -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( ({ diff --git a/packages/twenty-front/src/modules/views/hooks/useUpsertCombinedViewFilters.ts b/packages/twenty-front/src/modules/views/hooks/useUpsertCombinedViewFilters.ts index 0457919fd415..98c8c9ef6593 100644 --- a/packages/twenty-front/src/modules/views/hooks/useUpsertCombinedViewFilters.ts +++ b/packages/twenty-front/src/modules/views/hooks/useUpsertCombinedViewFilters.ts @@ -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 { unsavedToDeleteViewFilterIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState'; import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState'; import { ViewFilter } from '@/views/types/ViewFilter'; @@ -25,7 +25,7 @@ export const useUpsertCombinedViewFilters = (viewBarComponentId?: string) => { ); const currentViewIdCallbackState = useRecoilComponentCallbackStateV2( - currentViewIdComponentState, + contextStoreCurrentViewIdComponentState, viewBarComponentId, ); diff --git a/packages/twenty-front/src/modules/views/hooks/useUpsertCombinedViewSorts.ts b/packages/twenty-front/src/modules/views/hooks/useUpsertCombinedViewSorts.ts index 1983a1ea6bde..c5d522f3fd8c 100644 --- a/packages/twenty-front/src/modules/views/hooks/useUpsertCombinedViewSorts.ts +++ b/packages/twenty-front/src/modules/views/hooks/useUpsertCombinedViewSorts.ts @@ -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 { 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 = diff --git a/packages/twenty-front/src/modules/views/states/currentViewIdComponentState.ts b/packages/twenty-front/src/modules/views/states/currentViewIdComponentState.ts deleted file mode 100644 index 40b7ecb61836..000000000000 --- a/packages/twenty-front/src/modules/views/states/currentViewIdComponentState.ts +++ /dev/null @@ -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, -}); diff --git a/packages/twenty-front/src/modules/views/utils/mapViewFiltersToFilters.ts b/packages/twenty-front/src/modules/views/utils/mapViewFiltersToFilters.ts index 3aa843660094..d6ee94537285 100644 --- a/packages/twenty-front/src/modules/views/utils/mapViewFiltersToFilters.ts +++ b/packages/twenty-front/src/modules/views/utils/mapViewFiltersToFilters.ts @@ -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( diff --git a/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx b/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx index f151507dc6f1..36b7925ea2a6 100644 --- a/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx +++ b/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx @@ -43,8 +43,7 @@ export const RecordIndexPage = () => { mainContextStoreComponentInstanceId, ); - // Todo: if we want the recordIndexId to contain the viewId, we need to remove the Effects otherwise we will have race condition on view change - const recordIndexId = `${objectNamePlural}`; + const recordIndexId = `${objectNamePlural}-${contextStoreCurrentViewId}`; const { objectNameSingular } = useObjectNameSingularFromPlural({ objectNamePlural, From 2c95605c22fb48c9d642fa69bd4078c25f13625d Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Mon, 17 Feb 2025 19:32:55 +0100 Subject: [PATCH 02/14] Fix --- .../RecordActionMenuEntriesSetter.tsx | 25 +- .../components/RecordIndexActionMenu.tsx | 9 +- .../components/RecordShowActionMenu.tsx | 9 +- .../RecordShowRightDrawerActionMenu.tsx | 9 +- .../command-menu/components/CommandMenu.tsx | 26 +- .../components/CommandMenuTopBar.tsx | 10 +- .../ResetContextToSelectionCommandButton.tsx | 8 +- .../useCopyContextStoreAndActionMenuStates.ts | 10 +- .../hooks/useResetContextStoreStates.ts | 6 +- .../components/MainContextStoreProvider.tsx | 8 +- .../MainContextStoreProviderEffect.tsx | 32 ++- ...textStoreCurrentObjectMetadataIdOrThrow.ts | 17 -- ...seContextStoreObjectMetadataItemOrThrow.ts | 18 ++ ...seFindManyRecordsSelectedInContextStore.ts | 18 +- ...urrentObjectMetadataItemComponentState.ts} | 9 +- .../record-group/hooks/useSetRecordGroup.ts | 4 +- .../components/RecordIndexContainer.tsx | 193 +------------- ...tainerContextStoreObjectMetadataEffect.tsx | 31 --- .../components/RecordIndexContainerGater.tsx | 99 +++++++ ...ecordIndexLoadBaseOnContextStoreEffect.tsx | 12 + .../hooks/useLoadRecordIndexStates.ts | 245 ++++++++++++++++++ ...inerContextStoreObjectMetadataIdEffect.tsx | 17 +- .../SignInBackgroundMockContainer.tsx | 6 +- .../src/modules/views/components/ViewBar.tsx | 86 +++--- .../views/components/ViewBarEffect.tsx | 56 ---- .../components/ViewBarRecordFilterEffect.tsx | 24 +- .../views/events/contexts/ViewEventContext.ts | 8 - .../pages/object-record/RecordIndexPage.tsx | 96 +------ .../testing/jest/JestContextStoreSetter.tsx | 11 +- 29 files changed, 538 insertions(+), 564 deletions(-) delete mode 100644 packages/twenty-front/src/modules/context-store/hooks/useContextStoreCurrentObjectMetadataIdOrThrow.ts create mode 100644 packages/twenty-front/src/modules/context-store/hooks/useContextStoreObjectMetadataItemOrThrow.ts rename packages/twenty-front/src/modules/context-store/states/{contextStoreCurrentObjectMetadataIdComponentState.ts => contextStoreCurrentObjectMetadataItemComponentState.ts} (50%) delete mode 100644 packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainerContextStoreObjectMetadataEffect.tsx create mode 100644 packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainerGater.tsx create mode 100644 packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexLoadBaseOnContextStoreEffect.tsx create mode 100644 packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexStates.ts delete mode 100644 packages/twenty-front/src/modules/views/components/ViewBarEffect.tsx delete mode 100644 packages/twenty-front/src/modules/views/events/contexts/ViewEventContext.ts diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/RecordActionMenuEntriesSetter.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/RecordActionMenuEntriesSetter.tsx index 4bbd1aa15103..06217adc7410 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/RecordActionMenuEntriesSetter.tsx +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/RecordActionMenuEntriesSetter.tsx @@ -2,25 +2,17 @@ import { RegisterRecordActionEffect } from '@/action-menu/actions/record-actions import { WorkflowRunRecordActionMenuEntrySetterEffect } from '@/action-menu/actions/record-actions/workflow-run-record-actions/components/WorkflowRunRecordActionMenuEntrySetter'; import { getActionConfig } from '@/action-menu/actions/utils/getActionConfig'; import { getActionViewType } from '@/action-menu/actions/utils/getActionViewType'; -import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState'; +import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState'; import { contextStoreCurrentViewTypeComponentState } from '@/context-store/states/contextStoreCurrentViewTypeComponentState'; import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; -import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; -import { useRecoilValue } from 'recoil'; import { isDefined } from 'twenty-shared'; import { FeatureFlagKey } from '~/generated/graphql'; export const RecordActionMenuEntriesSetter = () => { - const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2( - contextStoreCurrentObjectMetadataIdComponentState, - ); - - const objectMetadataItems = useRecoilValue(objectMetadataItemsState); - - const objectMetadataItem = objectMetadataItems.find( - (item) => item.id === contextStoreCurrentObjectMetadataId, + const contextStoreCurrentObjectMetadataItem = useRecoilComponentValueV2( + contextStoreCurrentObjectMetadataItemComponentState, ); const contextStoreTargetedRecordsRule = useRecoilComponentValueV2( @@ -39,10 +31,7 @@ export const RecordActionMenuEntriesSetter = () => { FeatureFlagKey.IsCommandMenuV2Enabled, ); - if ( - !isDefined(contextStoreCurrentObjectMetadataId) || - !isDefined(objectMetadataItem) - ) { + if (!isDefined(contextStoreCurrentObjectMetadataItem)) { return null; } @@ -52,7 +41,7 @@ export const RecordActionMenuEntriesSetter = () => { ); const actionConfig = getActionConfig( - objectMetadataItem, + contextStoreCurrentObjectMetadataItem, isCommandMenuV2Enabled, ); @@ -68,7 +57,7 @@ export const RecordActionMenuEntriesSetter = () => { ))} @@ -76,7 +65,7 @@ export const RecordActionMenuEntriesSetter = () => { contextStoreTargetedRecordsRule?.mode === 'selection' && contextStoreTargetedRecordsRule?.selectedRecordIds.length === 1 && ( )} diff --git a/packages/twenty-front/src/modules/action-menu/components/RecordIndexActionMenu.tsx b/packages/twenty-front/src/modules/action-menu/components/RecordIndexActionMenu.tsx index 5fa370179879..6bad7e63a2cc 100644 --- a/packages/twenty-front/src/modules/action-menu/components/RecordIndexActionMenu.tsx +++ b/packages/twenty-front/src/modules/action-menu/components/RecordIndexActionMenu.tsx @@ -8,8 +8,7 @@ import { RecordIndexActionMenuButtons } from '@/action-menu/components/RecordInd import { RecordIndexActionMenuDropdown } from '@/action-menu/components/RecordIndexActionMenuDropdown'; import { RecordIndexActionMenuEffect } from '@/action-menu/components/RecordIndexActionMenuEffect'; import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext'; - -import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState'; +import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState'; import { isRecordIndexLoadMoreLockedComponentState } from '@/object-record/record-index/states/isRecordIndexLoadMoreLockedComponentState'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; @@ -18,8 +17,8 @@ import { useIsMobile } from 'twenty-ui'; import { FeatureFlagKey } from '~/generated/graphql'; export const RecordIndexActionMenu = ({ indexId }: { indexId: string }) => { - const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2( - contextStoreCurrentObjectMetadataIdComponentState, + const contextStoreCurrentObjectMetadataItem = useRecoilComponentValueV2( + contextStoreCurrentObjectMetadataItemComponentState, ); const isCommandMenuV2Enabled = useIsFeatureEnabled( @@ -39,7 +38,7 @@ export const RecordIndexActionMenu = ({ indexId }: { indexId: string }) => { return ( <> - {contextStoreCurrentObjectMetadataId && ( + {contextStoreCurrentObjectMetadataItem && ( void; }) => { - const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2( - contextStoreCurrentObjectMetadataIdComponentState, + const contextStoreCurrentObjectMetadataItem = useRecoilComponentValueV2( + contextStoreCurrentObjectMetadataItemComponentState, ); const isCommandMenuV2Enabled = useIsFeatureEnabled( @@ -42,7 +41,7 @@ export const RecordShowActionMenu = ({ return ( <> - {contextStoreCurrentObjectMetadataId && ( + {contextStoreCurrentObjectMetadataItem && ( { - const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2( - contextStoreCurrentObjectMetadataIdComponentState, + const contextStoreCurrentObjectMetadataItem = useRecoilComponentValueV2( + contextStoreCurrentObjectMetadataItemComponentState, ); const isWorkflowEnabled = useIsFeatureEnabled( @@ -21,7 +20,7 @@ export const RecordShowRightDrawerActionMenu = () => { return ( <> - {contextStoreCurrentObjectMetadataId && ( + {contextStoreCurrentObjectMetadataItem && ( diff --git a/packages/twenty-front/src/modules/command-menu/components/CommandMenu.tsx b/packages/twenty-front/src/modules/command-menu/components/CommandMenu.tsx index 4381df6bc052..a5ac88220c04 100644 --- a/packages/twenty-front/src/modules/command-menu/components/CommandMenu.tsx +++ b/packages/twenty-front/src/modules/command-menu/components/CommandMenu.tsx @@ -5,12 +5,10 @@ import { RESET_CONTEXT_TO_SELECTION } from '@/command-menu/constants/ResetContex import { useMatchingCommandMenuCommands } from '@/command-menu/hooks/useMatchingCommandMenuCommands'; import { commandMenuSearchState } from '@/command-menu/states/commandMenuSearchState'; import { Command } from '@/command-menu/types/Command'; -import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState'; -import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; +import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState'; import { SelectableItem } from '@/ui/layout/selectable-list/components/SelectableItem'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useLingui } from '@lingui/react/macro'; -import { isNonEmptyString } from '@sniptt/guards'; import { useRecoilValue } from 'recoil'; import { isDefined } from 'twenty-shared'; @@ -50,23 +48,19 @@ export const CommandMenu = () => { ) .filter(isDefined); - const previousContextStoreCurrentObjectMetadataId = useRecoilComponentValueV2( - contextStoreCurrentObjectMetadataIdComponentState, - 'command-menu-previous', - ); - - const objectMetadataItems = useRecoilValue(objectMetadataItemsState); - const currentObjectMetadataId = useRecoilComponentValueV2( - contextStoreCurrentObjectMetadataIdComponentState, - ); + const previousContextStoreCurrentObjectMetadataItem = + useRecoilComponentValueV2( + contextStoreCurrentObjectMetadataItemComponentState, + 'command-menu-previous', + ); - const currentObjectMetadataItem = objectMetadataItems.find( - (objectMetadataItem) => objectMetadataItem.id === currentObjectMetadataId, + const currentObjectMetadataItem = useRecoilComponentValueV2( + contextStoreCurrentObjectMetadataItemComponentState, ); const selectableItemIds = selectableItems.map((item) => item.id); - if (isNonEmptyString(previousContextStoreCurrentObjectMetadataId)) { + if (isDefined(previousContextStoreCurrentObjectMetadataItem)) { selectableItemIds.unshift(RESET_CONTEXT_TO_SELECTION); } @@ -103,7 +97,7 @@ export const CommandMenu = () => { selectableItemIds={selectableItemIds} noResults={noResults} > - {isNonEmptyString(previousContextStoreCurrentObjectMetadataId) && ( + {isDefined(previousContextStoreCurrentObjectMetadataItem) && ( diff --git a/packages/twenty-front/src/modules/command-menu/components/CommandMenuTopBar.tsx b/packages/twenty-front/src/modules/command-menu/components/CommandMenuTopBar.tsx index c3fd69d38f60..68033af5b55a 100644 --- a/packages/twenty-front/src/modules/command-menu/components/CommandMenuTopBar.tsx +++ b/packages/twenty-front/src/modules/command-menu/components/CommandMenuTopBar.tsx @@ -9,7 +9,7 @@ import { commandMenuNavigationStackState } from '@/command-menu/states/commandMe import { commandMenuPageState } from '@/command-menu/states/commandMenuPageState'; import { commandMenuSearchState } from '@/command-menu/states/commandMenuSearchState'; import { CommandMenuPages } from '@/command-menu/types/CommandMenuPages'; -import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState'; +import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; import { useTheme } from '@emotion/react'; @@ -96,8 +96,8 @@ export const CommandMenuTopBar = () => { const { closeCommandMenu, goBackFromCommandMenu } = useCommandMenu(); - const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2( - contextStoreCurrentObjectMetadataIdComponentState, + const contextStoreCurrentObjectMetadataItem = useRecoilComponentValueV2( + contextStoreCurrentObjectMetadataItemComponentState, ); const commandMenuPage = useRecoilValue(commandMenuPageState); @@ -137,11 +137,11 @@ export const CommandMenuTopBar = () => { testId="command-menu-go-back-button" /> )} - {isDefined(contextStoreCurrentObjectMetadataId) && + {isDefined(contextStoreCurrentObjectMetadataItem) && commandMenuPage !== CommandMenuPages.SearchRecords ? ( ) : ( diff --git a/packages/twenty-front/src/modules/command-menu/components/ResetContextToSelectionCommandButton.tsx b/packages/twenty-front/src/modules/command-menu/components/ResetContextToSelectionCommandButton.tsx index a8c85c3b6bcf..5992786b32c5 100644 --- a/packages/twenty-front/src/modules/command-menu/components/ResetContextToSelectionCommandButton.tsx +++ b/packages/twenty-front/src/modules/command-menu/components/ResetContextToSelectionCommandButton.tsx @@ -2,7 +2,7 @@ import { CommandMenuContextRecordChip } from '@/command-menu/components/CommandM import { CommandMenuItem } from '@/command-menu/components/CommandMenuItem'; import { RESET_CONTEXT_TO_SELECTION } from '@/command-menu/constants/ResetContextToSelection'; import { useResetPreviousCommandMenuContext } from '@/command-menu/hooks/useResetPreviousCommandMenuContext'; -import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState'; +import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState'; import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; @@ -17,8 +17,8 @@ export const ResetContextToSelectionCommandButton = () => { 'command-menu-previous', ); - const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2( - contextStoreCurrentObjectMetadataIdComponentState, + const contextStoreCurrentObjectMetadataItem = useRecoilComponentValueV2( + contextStoreCurrentObjectMetadataItemComponentState, 'command-menu-previous', ); @@ -26,7 +26,7 @@ export const ResetContextToSelectionCommandButton = () => { const objectMetadataItem = objectMetadataItems.find( (objectMetadataItem) => - objectMetadataItem.id === contextStoreCurrentObjectMetadataId, + objectMetadataItem.id === contextStoreCurrentObjectMetadataItem?.id, ); const { resetPreviousCommandMenuContext } = diff --git a/packages/twenty-front/src/modules/command-menu/hooks/useCopyContextStoreAndActionMenuStates.ts b/packages/twenty-front/src/modules/command-menu/hooks/useCopyContextStoreAndActionMenuStates.ts index 61e76709272b..607ed17f9e04 100644 --- a/packages/twenty-front/src/modules/command-menu/hooks/useCopyContextStoreAndActionMenuStates.ts +++ b/packages/twenty-front/src/modules/command-menu/hooks/useCopyContextStoreAndActionMenuStates.ts @@ -1,5 +1,5 @@ import { actionMenuEntriesComponentState } from '@/action-menu/states/actionMenuEntriesComponentState'; -import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState'; +import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState'; import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState'; import { contextStoreCurrentViewTypeComponentState } from '@/context-store/states/contextStoreCurrentViewTypeComponentState'; import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState'; @@ -17,19 +17,19 @@ export const useCopyContextStoreStates = () => { instanceIdToCopyFrom: string; instanceIdToCopyTo: string; }) => { - const contextStoreCurrentObjectMetadataId = snapshot + const contextStoreCurrentObjectMetadataItem = snapshot .getLoadable( - contextStoreCurrentObjectMetadataIdComponentState.atomFamily({ + contextStoreCurrentObjectMetadataItemComponentState.atomFamily({ instanceId: instanceIdToCopyFrom, }), ) .getValue(); set( - contextStoreCurrentObjectMetadataIdComponentState.atomFamily({ + contextStoreCurrentObjectMetadataItemComponentState.atomFamily({ instanceId: instanceIdToCopyTo, }), - contextStoreCurrentObjectMetadataId, + contextStoreCurrentObjectMetadataItem, ); const contextStoreTargetedRecordsRule = snapshot diff --git a/packages/twenty-front/src/modules/command-menu/hooks/useResetContextStoreStates.ts b/packages/twenty-front/src/modules/command-menu/hooks/useResetContextStoreStates.ts index 4a3ae31b07bd..f90a0f3e914e 100644 --- a/packages/twenty-front/src/modules/command-menu/hooks/useResetContextStoreStates.ts +++ b/packages/twenty-front/src/modules/command-menu/hooks/useResetContextStoreStates.ts @@ -1,5 +1,5 @@ import { actionMenuEntriesComponentState } from '@/action-menu/states/actionMenuEntriesComponentState'; -import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState'; +import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState'; import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState'; import { contextStoreCurrentViewTypeComponentState } from '@/context-store/states/contextStoreCurrentViewTypeComponentState'; import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState'; @@ -11,10 +11,10 @@ export const useResetContextStoreStates = () => { const resetContextStoreStates = useRecoilCallback(({ set }) => { return (instanceId: string) => { set( - contextStoreCurrentObjectMetadataIdComponentState.atomFamily({ + contextStoreCurrentObjectMetadataItemComponentState.atomFamily({ instanceId, }), - null, + undefined, ); set( diff --git a/packages/twenty-front/src/modules/context-store/components/MainContextStoreProvider.tsx b/packages/twenty-front/src/modules/context-store/components/MainContextStoreProvider.tsx index 5ca07b30b022..0a1645e2d227 100644 --- a/packages/twenty-front/src/modules/context-store/components/MainContextStoreProvider.tsx +++ b/packages/twenty-front/src/modules/context-store/components/MainContextStoreProvider.tsx @@ -72,10 +72,14 @@ export const MainContextStoreProvider = () => { const mainContextStoreComponentInstanceId = `${pageName}-${objectMetadataItem?.namePlural}-${viewId}`; + const view = viewsOnCurrentObject.find((view) => view.id === viewId); + + console.log('Provider'); if ( !isDefined(pageName) || !isDefined(objectMetadataItem) || - !isNonEmptyString(viewId) + !isNonEmptyString(viewId) || + !isDefined(view) ) { return null; } @@ -85,7 +89,7 @@ export const MainContextStoreProvider = () => { mainContextStoreComponentInstanceIdToSet={ mainContextStoreComponentInstanceId } - viewId={viewId} + view={view} objectMetadataItem={objectMetadataItem} /> ); diff --git a/packages/twenty-front/src/modules/context-store/components/MainContextStoreProviderEffect.tsx b/packages/twenty-front/src/modules/context-store/components/MainContextStoreProviderEffect.tsx index 28a634a72137..9e077765097a 100644 --- a/packages/twenty-front/src/modules/context-store/components/MainContextStoreProviderEffect.tsx +++ b/packages/twenty-front/src/modules/context-store/components/MainContextStoreProviderEffect.tsx @@ -1,20 +1,21 @@ -import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState'; +import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState'; import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState'; import { mainContextStoreComponentInstanceIdState } from '@/context-store/states/mainContextStoreComponentInstanceId'; import { useSetLastVisitedObjectMetadataId } from '@/navigation/hooks/useSetLastVisitedObjectMetadataId'; import { useSetLastVisitedViewForObjectMetadataNamePlural } from '@/navigation/hooks/useSetLastVisitedViewForObjectMetadataNamePlural'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2'; +import { View } from '@/views/types/View'; import { useEffect } from 'react'; import { useRecoilState } from 'recoil'; export const MainContextStoreProviderEffect = ({ mainContextStoreComponentInstanceIdToSet, - viewId, + view, objectMetadataItem, }: { mainContextStoreComponentInstanceIdToSet: string; - viewId: string; + view: View; objectMetadataItem: ObjectMetadataItem; }) => { const [ @@ -35,16 +36,19 @@ export const MainContextStoreProviderEffect = ({ ); const [ - contextStoreCurrentObjectMetadataId, - setContextStoreCurrentObjectMetadataId, + contextStoreCurrentObjectMetadataItem, + setContextStoreCurrentObjectMetadataItem, ] = useRecoilComponentStateV2( - contextStoreCurrentObjectMetadataIdComponentState, + contextStoreCurrentObjectMetadataItemComponentState, mainContextStoreComponentInstanceId, ); + console.log('Provider effect'); useEffect(() => { - if (contextStoreCurrentObjectMetadataId !== objectMetadataItem.id) { - setContextStoreCurrentObjectMetadataId(objectMetadataItem.id); + if (contextStoreCurrentObjectMetadataItem?.id !== objectMetadataItem.id) { + console.log('Setting object metadata item'); + console.log('objectMetadataItem', objectMetadataItem); + setContextStoreCurrentObjectMetadataItem(objectMetadataItem); } if ( @@ -58,29 +62,29 @@ export const MainContextStoreProviderEffect = ({ setLastVisitedViewForObjectMetadataNamePlural({ objectNamePlural: objectMetadataItem.namePlural, - viewId: viewId, + viewId: view.id, }); setLastVisitedObjectMetadataId({ objectMetadataItemId: objectMetadataItem.id, }); - if (contextStoreCurrentViewId !== viewId) { - setContextStoreCurrentViewId(viewId); + if (contextStoreCurrentViewId !== view.id) { + setContextStoreCurrentViewId(view.id); } }, [ - contextStoreCurrentObjectMetadataId, + contextStoreCurrentObjectMetadataItem, contextStoreCurrentViewId, mainContextStoreComponentInstanceId, mainContextStoreComponentInstanceIdToSet, objectMetadataItem, objectMetadataItem.namePlural, - setContextStoreCurrentObjectMetadataId, + setContextStoreCurrentObjectMetadataItem, setContextStoreCurrentViewId, setLastVisitedObjectMetadataId, setLastVisitedViewForObjectMetadataNamePlural, setMainContextStoreComponentInstanceId, - viewId, + view, ]); return null; diff --git a/packages/twenty-front/src/modules/context-store/hooks/useContextStoreCurrentObjectMetadataIdOrThrow.ts b/packages/twenty-front/src/modules/context-store/hooks/useContextStoreCurrentObjectMetadataIdOrThrow.ts deleted file mode 100644 index 2b265fe47346..000000000000 --- a/packages/twenty-front/src/modules/context-store/hooks/useContextStoreCurrentObjectMetadataIdOrThrow.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState'; -import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; - -export const useContextStoreCurrentObjectMetadataIdOrThrow = ( - instanceId?: string, -) => { - const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2( - contextStoreCurrentObjectMetadataIdComponentState, - instanceId, - ); - - if (!contextStoreCurrentObjectMetadataId) { - throw new Error('contextStoreCurrentObjectMetadataIdComponent is not set'); - } - - return contextStoreCurrentObjectMetadataId; -}; diff --git a/packages/twenty-front/src/modules/context-store/hooks/useContextStoreObjectMetadataItemOrThrow.ts b/packages/twenty-front/src/modules/context-store/hooks/useContextStoreObjectMetadataItemOrThrow.ts new file mode 100644 index 000000000000..0dc5cb72ba17 --- /dev/null +++ b/packages/twenty-front/src/modules/context-store/hooks/useContextStoreObjectMetadataItemOrThrow.ts @@ -0,0 +1,18 @@ +import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; + +export const useContextStoreObjectMetadataItemOrThrow = ( + contextStoreInstanceId?: string, +) => { + const objectMetadataItem = useRecoilComponentValueV2( + contextStoreCurrentObjectMetadataItemComponentState, + contextStoreInstanceId, + ); + console.log('objectMetadataItem', objectMetadataItem); + + if (!objectMetadataItem) { + throw new Error('Object metadata item is not se in context store'); + } + + return { objectMetadataItem }; +}; diff --git a/packages/twenty-front/src/modules/context-store/hooks/useFindManyRecordsSelectedInContextStore.ts b/packages/twenty-front/src/modules/context-store/hooks/useFindManyRecordsSelectedInContextStore.ts index 5743292a5633..eb89af04db7a 100644 --- a/packages/twenty-front/src/modules/context-store/hooks/useFindManyRecordsSelectedInContextStore.ts +++ b/packages/twenty-front/src/modules/context-store/hooks/useFindManyRecordsSelectedInContextStore.ts @@ -1,8 +1,7 @@ -import { useContextStoreCurrentObjectMetadataIdOrThrow } from '@/context-store/hooks/useContextStoreCurrentObjectMetadataIdOrThrow'; +import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState'; import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState'; import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; import { computeContextStoreFilters } from '@/context-store/utils/computeContextStoreFilters'; -import { useObjectMetadataItemById } from '@/object-metadata/hooks/useObjectMetadataItemById'; import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords'; import { useFilterValueDependencies } from '@/object-record/record-filter/hooks/useFilterValueDependencies'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; @@ -14,12 +13,10 @@ export const useFindManyRecordsSelectedInContextStore = ({ instanceId?: string; limit?: number; }) => { - const objectMetadataId = - useContextStoreCurrentObjectMetadataIdOrThrow(instanceId); - - const { objectMetadataItem } = useObjectMetadataItemById({ - objectId: objectMetadataId, - }); + const objectMetadataItem = useRecoilComponentValueV2( + contextStoreCurrentObjectMetadataItemComponentState, + instanceId, + ); const contextStoreTargetedRecordsRule = useRecoilComponentValueV2( contextStoreTargetedRecordsRuleComponentState, @@ -36,12 +33,13 @@ export const useFindManyRecordsSelectedInContextStore = ({ const queryFilter = computeContextStoreFilters( contextStoreTargetedRecordsRule, contextStoreFilters, - objectMetadataItem, + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + objectMetadataItem!, filterValueDependencies, ); const { records, loading, totalCount } = useFindManyRecords({ - objectNameSingular: objectMetadataItem.nameSingular, + objectNameSingular: objectMetadataItem?.nameSingular ?? '', filter: queryFilter, withSoftDeleted: true, orderBy: [ diff --git a/packages/twenty-front/src/modules/context-store/states/contextStoreCurrentObjectMetadataIdComponentState.ts b/packages/twenty-front/src/modules/context-store/states/contextStoreCurrentObjectMetadataItemComponentState.ts similarity index 50% rename from packages/twenty-front/src/modules/context-store/states/contextStoreCurrentObjectMetadataIdComponentState.ts rename to packages/twenty-front/src/modules/context-store/states/contextStoreCurrentObjectMetadataItemComponentState.ts index 9898e6c6f540..4d9d8eb983f1 100644 --- a/packages/twenty-front/src/modules/context-store/states/contextStoreCurrentObjectMetadataIdComponentState.ts +++ b/packages/twenty-front/src/modules/context-store/states/contextStoreCurrentObjectMetadataItemComponentState.ts @@ -1,9 +1,10 @@ import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext'; +import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; -export const contextStoreCurrentObjectMetadataIdComponentState = - createComponentStateV2({ - key: 'contextStoreCurrentObjectMetadataIdComponentState', - defaultValue: null, +export const contextStoreCurrentObjectMetadataItemComponentState = + createComponentStateV2({ + key: 'contextStoreCurrentObjectMetadataItemComponentState', + defaultValue: undefined, componentInstanceContext: ContextStoreComponentInstanceContext, }); diff --git a/packages/twenty-front/src/modules/object-record/record-group/hooks/useSetRecordGroup.ts b/packages/twenty-front/src/modules/object-record/record-group/hooks/useSetRecordGroup.ts index 96b5d0184f11..490b65b4abd8 100644 --- a/packages/twenty-front/src/modules/object-record/record-group/hooks/useSetRecordGroup.ts +++ b/packages/twenty-front/src/modules/object-record/record-group/hooks/useSetRecordGroup.ts @@ -1,15 +1,15 @@ +import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow'; import { recordGroupDefinitionFamilyState } from '@/object-record/record-group/states/recordGroupDefinitionFamilyState'; import { recordGroupFieldMetadataComponentState } from '@/object-record/record-group/states/recordGroupFieldMetadataComponentState'; import { recordGroupIdsComponentState } from '@/object-record/record-group/states/recordGroupIdsComponentState'; import { RecordGroupDefinition } from '@/object-record/record-group/types/RecordGroupDefinition'; -import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext'; import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue'; import { useRecoilCallback } from 'recoil'; import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; export const useSetRecordGroup = (viewId?: string) => { - const { objectMetadataItem } = useRecordIndexContextOrThrow(); + const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow(); const recordIndexRecordGroupIdsState = useRecoilComponentCallbackStateV2( recordGroupIdsComponentState, diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainer.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainer.tsx index b2c24e4d7e0f..b8d784016d11 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainer.tsx +++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainer.tsx @@ -1,52 +1,28 @@ import styled from '@emotion/styled'; -import { useRecoilCallback, useRecoilState, useSetRecoilState } from 'recoil'; -import { isDefined } from 'twenty-shared'; +import { useRecoilState } from 'recoil'; -import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata'; import { ObjectOptionsDropdown } from '@/object-record/object-options-dropdown/components/ObjectOptionsDropdown'; import { RecordIndexBoardContainer } from '@/object-record/record-index/components/RecordIndexBoardContainer'; import { RecordIndexBoardDataLoader } from '@/object-record/record-index/components/RecordIndexBoardDataLoader'; import { RecordIndexBoardDataLoaderEffect } from '@/object-record/record-index/components/RecordIndexBoardDataLoaderEffect'; import { RecordIndexTableContainer } from '@/object-record/record-index/components/RecordIndexTableContainer'; import { RecordIndexViewBarEffect } from '@/object-record/record-index/components/RecordIndexViewBarEffect'; -import { recordIndexFieldDefinitionsState } from '@/object-record/record-index/states/recordIndexFieldDefinitionsState'; -import { recordIndexFiltersState } from '@/object-record/record-index/states/recordIndexFiltersState'; -import { recordIndexIsCompactModeActiveState } from '@/object-record/record-index/states/recordIndexIsCompactModeActiveState'; -import { recordIndexKanbanFieldMetadataIdState } from '@/object-record/record-index/states/recordIndexKanbanFieldMetadataIdState'; -import { recordIndexSortsState } from '@/object-record/record-index/states/recordIndexSortsState'; import { recordIndexViewTypeState } from '@/object-record/record-index/states/recordIndexViewTypeState'; import { InformationBannerWrapper } from '@/information-banner/components/InformationBannerWrapper'; import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext'; import { RecordFieldValueSelectorContextProvider } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext'; -import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable'; import { SpreadsheetImportProvider } from '@/spreadsheet-import/provider/components/SpreadsheetImportProvider'; import { RecordIndexActionMenu } from '@/action-menu/components/RecordIndexActionMenu'; import { ContextStoreCurrentViewTypeEffect } from '@/context-store/components/ContextStoreCurrentViewTypeEffect'; -import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; import { ContextStoreViewType } from '@/context-store/types/ContextStoreViewType'; -import { useFilterableFieldMetadataItems } from '@/object-record/record-filter/hooks/useFilterableFieldMetadataItems'; -import { useSetRecordGroup } from '@/object-record/record-group/hooks/useSetRecordGroup'; import { RecordIndexFiltersToContextStoreEffect } from '@/object-record/record-index/components/RecordIndexFiltersToContextStoreEffect'; import { RecordIndexTableContainerEffect } from '@/object-record/record-index/components/RecordIndexTableContainerEffect'; -import { recordIndexKanbanAggregateOperationState } from '@/object-record/record-index/states/recordIndexKanbanAggregateOperationState'; -import { recordIndexViewFilterGroupsState } from '@/object-record/record-index/states/recordIndexViewFilterGroupsState'; -import { viewFieldAggregateOperationState } from '@/object-record/record-table/record-table-footer/states/viewFieldAggregateOperationState'; -import { convertAggregateOperationToExtendedAggregateOperation } from '@/object-record/utils/convertAggregateOperationToExtendedAggregateOperation'; -import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; import { ViewBar } from '@/views/components/ViewBar'; -import { ViewField } from '@/views/types/ViewField'; -import { ViewGroup } from '@/views/types/ViewGroup'; import { ViewType } from '@/views/types/ViewType'; -import { mapViewFieldsToColumnDefinitions } from '@/views/utils/mapViewFieldsToColumnDefinitions'; -import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters'; -import { mapViewGroupsToRecordGroupDefinitions } from '@/views/utils/mapViewGroupsToRecordGroupDefinitions'; -import { mapViewSortsToSorts } from '@/views/utils/mapViewSortsToSorts'; import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; -import { useCallback } from 'react'; import { FeatureFlagKey } from '~/generated/graphql'; -import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; const StyledContainer = styled.div` display: flex; @@ -64,9 +40,7 @@ const StyledContainerWithPadding = styled.div` `; export const RecordIndexContainer = () => { - const [recordIndexViewType, setRecordIndexViewType] = useRecoilState( - recordIndexViewTypeState, - ); + const [recordIndexViewType] = useRecoilState(recordIndexViewTypeState); const { objectNamePlural, @@ -75,115 +49,6 @@ export const RecordIndexContainer = () => { objectNameSingular, } = useRecordIndexContextOrThrow(); - const setRecordGroup = useSetRecordGroup(recordIndexId); - - const { columnDefinitions, sortDefinitions } = - useColumnDefinitionsFromFieldMetadata(objectMetadataItem); - - const setRecordIndexViewFilterGroups = useSetRecoilState( - recordIndexViewFilterGroupsState, - ); - const setRecordIndexFilters = useSetRecoilState(recordIndexFiltersState); - const setRecordIndexSorts = useSetRecoilState(recordIndexSortsState); - const setRecordIndexIsCompactModeActive = useSetRecoilState( - recordIndexIsCompactModeActiveState, - ); - const setRecordIndexViewKanbanFieldMetadataIdState = useSetRecoilState( - recordIndexKanbanFieldMetadataIdState, - ); - const setRecordIndexViewKanbanAggregateOperationState = useSetRecoilState( - recordIndexKanbanAggregateOperationState, - ); - - const { - setTableViewFilterGroups, - setTableFilters, - setTableSorts, - setTableColumns, - } = useRecordTable({ - recordTableId: recordIndexId, - }); - - const onViewFieldsChange = useRecoilCallback( - ({ set, snapshot }) => - (viewFields: ViewField[]) => { - const newFieldDefinitions = mapViewFieldsToColumnDefinitions({ - viewFields, - columnDefinitions, - }); - - setTableColumns(newFieldDefinitions); - - const existingRecordIndexFieldDefinitions = snapshot - .getLoadable(recordIndexFieldDefinitionsState) - .getValue(); - - if ( - !isDeeplyEqual( - existingRecordIndexFieldDefinitions, - newFieldDefinitions, - ) - ) { - set(recordIndexFieldDefinitionsState, newFieldDefinitions); - } - - for (const viewField of viewFields) { - const viewFieldMetadataType = objectMetadataItem.fields?.find( - (field) => field.id === viewField.fieldMetadataId, - )?.type; - const aggregateOperationForViewField = snapshot - .getLoadable( - viewFieldAggregateOperationState({ - viewFieldId: viewField.id, - }), - ) - .getValue(); - - const convertedViewFieldAggregateOperation = isDefined( - viewField.aggregateOperation, - ) - ? convertAggregateOperationToExtendedAggregateOperation( - viewField.aggregateOperation, - viewFieldMetadataType, - ) - : viewField.aggregateOperation; - - if ( - aggregateOperationForViewField !== - convertedViewFieldAggregateOperation - ) { - set( - viewFieldAggregateOperationState({ - viewFieldId: viewField.id, - }), - convertedViewFieldAggregateOperation, - ); - } - } - }, - [columnDefinitions, objectMetadataItem.fields, setTableColumns], - ); - - const onViewGroupsChange = useCallback( - (viewGroups: ViewGroup[]) => { - const newGroupDefinitions = mapViewGroupsToRecordGroupDefinitions({ - objectMetadataItem, - viewGroups, - }); - - setRecordGroup(newGroupDefinitions); - }, - [objectMetadataItem, setRecordGroup], - ); - - const setContextStoreTargetedRecordsRule = useSetRecoilComponentStateV2( - contextStoreTargetedRecordsRuleComponentState, - ); - - const { filterableFieldMetadataItems } = useFilterableFieldMetadataItems( - objectMetadataItem.id, - ); - const isCommandMenuV2Enabled = useIsFeatureEnabled( FeatureFlagKey.IsCommandMenuV2Enabled, ); @@ -210,60 +75,6 @@ export const RecordIndexContainer = () => { viewType={recordIndexViewType ?? ViewType.Table} /> } - onCurrentViewChange={(view) => { - if (!view) { - return; - } - - onViewFieldsChange(view.viewFields); - onViewGroupsChange(view.viewGroups); - setTableViewFilterGroups(view.viewFilterGroups ?? []); - setTableFilters( - mapViewFiltersToFilters( - view.viewFilters, - filterableFieldMetadataItems, - ), - ); - setRecordIndexFilters( - mapViewFiltersToFilters( - view.viewFilters, - filterableFieldMetadataItems, - ), - ); - setRecordIndexViewFilterGroups(view.viewFilterGroups ?? []); - setContextStoreTargetedRecordsRule((prev) => ({ - ...prev, - filters: mapViewFiltersToFilters( - view.viewFilters, - filterableFieldMetadataItems, - ), - })); - setTableSorts( - mapViewSortsToSorts(view.viewSorts, sortDefinitions), - ); - setRecordIndexSorts( - mapViewSortsToSorts(view.viewSorts, sortDefinitions), - ); - setRecordIndexViewType(view.type); - setRecordIndexViewKanbanFieldMetadataIdState( - view.kanbanFieldMetadataId, - ); - const kanbanAggregateOperationFieldMetadataType = - objectMetadataItem.fields?.find( - (field) => - field.id === view.kanbanAggregateOperationFieldMetadataId, - )?.type; - setRecordIndexViewKanbanAggregateOperationState({ - operation: isDefined(view.kanbanAggregateOperation) - ? convertAggregateOperationToExtendedAggregateOperation( - view.kanbanAggregateOperation, - kanbanAggregateOperationFieldMetadataType, - ) - : view.kanbanAggregateOperation, - fieldMetadataId: view.kanbanAggregateOperationFieldMetadataId, - }); - setRecordIndexIsCompactModeActive(view.isCompact); - }} /> { - const setContextStoreCurrentObjectMetadataItem = useSetRecoilComponentStateV2( - contextStoreCurrentObjectMetadataIdComponentState, - ); - const { objectNamePlural } = useRecordIndexContextOrThrow(); - - const { objectNameSingular } = useObjectNameSingularFromPlural({ - objectNamePlural, - }); - - const { objectMetadataItem } = useObjectMetadataItem({ - objectNameSingular, - }); - - useEffect(() => { - setContextStoreCurrentObjectMetadataItem(objectMetadataItem.id); - - return () => { - setContextStoreCurrentObjectMetadataItem(null); - }; - }, [objectMetadataItem.id, setContextStoreCurrentObjectMetadataItem]); - - return null; -}; diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainerGater.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainerGater.tsx new file mode 100644 index 000000000000..153f4c1d366b --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainerGater.tsx @@ -0,0 +1,99 @@ +import { RecordIndexContextProvider } from '@/object-record/record-index/contexts/RecordIndexContext'; + +import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext'; +import { getActionMenuIdFromRecordIndexId } from '@/action-menu/utils/getActionMenuIdFromRecordIndexId'; +import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow'; +import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState'; +import { mainContextStoreComponentInstanceIdState } from '@/context-store/states/mainContextStoreComponentInstanceId'; +import { lastShowPageRecordIdState } from '@/object-record/record-field/states/lastShowPageRecordId'; +import { RecordFiltersComponentInstanceContext } from '@/object-record/record-filter/states/context/RecordFiltersComponentInstanceContext'; +import { RecordIndexContainer } from '@/object-record/record-index/components/RecordIndexContainer'; +import { RecordIndexContainerContextStoreNumberOfSelectedRecordsEffect } from '@/object-record/record-index/components/RecordIndexContainerContextStoreNumberOfSelectedRecordsEffect'; +import { RecordIndexLoadBaseOnContextStoreEffect } from '@/object-record/record-index/components/RecordIndexLoadBaseOnContextStoreEffect'; +import { RecordIndexPageHeader } from '@/object-record/record-index/components/RecordIndexPageHeader'; +import { useHandleIndexIdentifierClick } from '@/object-record/record-index/hooks/useHandleIndexIdentifierClick'; +import { PageBody } from '@/ui/layout/page/components/PageBody'; +import { PageTitle } from '@/ui/utilities/page-title/components/PageTitle'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext'; +import styled from '@emotion/styled'; +import { useRecoilCallback, useRecoilValue } from 'recoil'; +import { capitalize } from 'twenty-shared'; + +const StyledIndexContainer = styled.div` + display: flex; + height: 100%; + width: 100%; +`; + +export const RecordIndexContainerGater = () => { + const mainContextStoreComponentInstanceId = useRecoilValue( + mainContextStoreComponentInstanceIdState, + ); + + const contextStoreCurrentViewId = useRecoilComponentValueV2( + contextStoreCurrentViewIdComponentState, + mainContextStoreComponentInstanceId, + ); + + const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow(); + + const recordIndexId = `${objectMetadataItem.namePlural}-${contextStoreCurrentViewId}`; + + const handleIndexRecordsLoaded = useRecoilCallback( + ({ set }) => + () => { + // TODO: find a better way to reset this state ? + set(lastShowPageRecordIdState, null); + }, + [], + ); + + const { indexIdentifierUrl } = useHandleIndexIdentifierClick({ + objectMetadataItem, + recordIndexId, + }); + + console.log('recordIndexId', recordIndexId); + + return ( + <> + + + + + + + + + + + + + + + + + + + ); +}; diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexLoadBaseOnContextStoreEffect.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexLoadBaseOnContextStoreEffect.tsx new file mode 100644 index 000000000000..e4cf82dc20b3 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexLoadBaseOnContextStoreEffect.tsx @@ -0,0 +1,12 @@ +import { useLoadRecordIndexStates } from '@/object-record/record-index/hooks/useLoadRecordIndexStates'; +import { useEffect } from 'react'; + +export const RecordIndexLoadBaseOnContextStoreEffect = () => { + const { loadRecordIndexStates } = useLoadRecordIndexStates(); + + useEffect(() => { + loadRecordIndexStates(); + }, [loadRecordIndexStates]); + + return <>; +}; diff --git a/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexStates.ts b/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexStates.ts new file mode 100644 index 000000000000..298176597950 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexStates.ts @@ -0,0 +1,245 @@ +import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow'; +import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState'; +import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; +import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata'; +import { useFilterableFieldMetadataItems } from '@/object-record/record-filter/hooks/useFilterableFieldMetadataItems'; +import { useSetRecordGroup } from '@/object-record/record-group/hooks/useSetRecordGroup'; +import { recordIndexFieldDefinitionsState } from '@/object-record/record-index/states/recordIndexFieldDefinitionsState'; +import { recordIndexFiltersState } from '@/object-record/record-index/states/recordIndexFiltersState'; +import { recordIndexIsCompactModeActiveState } from '@/object-record/record-index/states/recordIndexIsCompactModeActiveState'; +import { recordIndexKanbanAggregateOperationState } from '@/object-record/record-index/states/recordIndexKanbanAggregateOperationState'; +import { recordIndexKanbanFieldMetadataIdState } from '@/object-record/record-index/states/recordIndexKanbanFieldMetadataIdState'; +import { recordIndexSortsState } from '@/object-record/record-index/states/recordIndexSortsState'; +import { recordIndexViewFilterGroupsState } from '@/object-record/record-index/states/recordIndexViewFilterGroupsState'; +import { recordIndexViewTypeState } from '@/object-record/record-index/states/recordIndexViewTypeState'; +import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable'; +import { viewFieldAggregateOperationState } from '@/object-record/record-table/record-table-footer/states/viewFieldAggregateOperationState'; +import { convertAggregateOperationToExtendedAggregateOperation } from '@/object-record/utils/convertAggregateOperationToExtendedAggregateOperation'; +import { useLazyPrefetchedData } from '@/prefetch/hooks/useLazyPrefetchData'; +import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; +import { ViewField } from '@/views/types/ViewField'; +import { ViewGroup } from '@/views/types/ViewGroup'; +import { mapViewFieldsToColumnDefinitions } from '@/views/utils/mapViewFieldsToColumnDefinitions'; +import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters'; +import { mapViewGroupsToRecordGroupDefinitions } from '@/views/utils/mapViewGroupsToRecordGroupDefinitions'; +import { mapViewSortsToSorts } from '@/views/utils/mapViewSortsToSorts'; +import { useCallback } from 'react'; +import { useRecoilCallback, useSetRecoilState } from 'recoil'; +import { isDefined } from 'twenty-shared'; +import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; + +export const useLoadRecordIndexStates = () => { + const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow(); + const contextStoreCurrentViewId = useRecoilComponentValueV2( + contextStoreCurrentViewIdComponentState, + ); + + const setContextStoreTargetedRecordsRuleComponentState = + useSetRecoilComponentStateV2(contextStoreTargetedRecordsRuleComponentState); + + const { records: views, findManyRecords } = useLazyPrefetchedData( + PrefetchKey.AllViews, + ); + + const recordIndexId = `${objectMetadataItem.namePlural}-${contextStoreCurrentViewId}`; + console.log('recordIndexId', recordIndexId); + + const setRecordIndexViewFilterGroups = useSetRecoilState( + recordIndexViewFilterGroupsState, + ); + + const { filterableFieldMetadataItems } = useFilterableFieldMetadataItems( + objectMetadataItem?.id ?? '', + ); + + const setRecordIndexFilters = useSetRecoilState(recordIndexFiltersState); + const setRecordIndexSorts = useSetRecoilState(recordIndexSortsState); + const setRecordIndexIsCompactModeActive = useSetRecoilState( + recordIndexIsCompactModeActiveState, + ); + const setRecordIndexViewType = useSetRecoilState(recordIndexViewTypeState); + const setRecordIndexViewKanbanFieldMetadataIdState = useSetRecoilState( + recordIndexKanbanFieldMetadataIdState, + ); + const setRecordIndexViewKanbanAggregateOperationState = useSetRecoilState( + recordIndexKanbanAggregateOperationState, + ); + const setRecordGroup = useSetRecordGroup(recordIndexId); + const { + setTableViewFilterGroups, + setTableFilters, + setTableSorts, + setTableColumns, + } = useRecordTable({ + recordTableId: recordIndexId, + }); + + const { columnDefinitions, sortDefinitions } = + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + useColumnDefinitionsFromFieldMetadata(objectMetadataItem!); + + const onViewFieldsChange = useRecoilCallback( + ({ set, snapshot }) => + (viewFields: ViewField[]) => { + if (!objectMetadataItem) { + return; + } + + const newFieldDefinitions = mapViewFieldsToColumnDefinitions({ + viewFields, + columnDefinitions, + }); + + setTableColumns(newFieldDefinitions); + + const existingRecordIndexFieldDefinitions = snapshot + .getLoadable(recordIndexFieldDefinitionsState) + .getValue(); + + if ( + !isDeeplyEqual( + existingRecordIndexFieldDefinitions, + newFieldDefinitions, + ) + ) { + set(recordIndexFieldDefinitionsState, newFieldDefinitions); + } + + for (const viewField of viewFields) { + const viewFieldMetadataType = objectMetadataItem.fields?.find( + (field) => field.id === viewField.fieldMetadataId, + )?.type; + const aggregateOperationForViewField = snapshot + .getLoadable( + viewFieldAggregateOperationState({ + viewFieldId: viewField.id, + }), + ) + .getValue(); + + const convertedViewFieldAggregateOperation = isDefined( + viewField.aggregateOperation, + ) + ? convertAggregateOperationToExtendedAggregateOperation( + viewField.aggregateOperation, + viewFieldMetadataType, + ) + : viewField.aggregateOperation; + + if ( + aggregateOperationForViewField !== + convertedViewFieldAggregateOperation + ) { + set( + viewFieldAggregateOperationState({ + viewFieldId: viewField.id, + }), + convertedViewFieldAggregateOperation, + ); + } + } + }, + [columnDefinitions, objectMetadataItem, setTableColumns], + ); + + const onViewGroupsChange = useCallback( + (viewGroups: ViewGroup[]) => { + if (!objectMetadataItem) { + return; + } + + const newGroupDefinitions = mapViewGroupsToRecordGroupDefinitions({ + objectMetadataItem, + viewGroups, + }); + + setRecordGroup(newGroupDefinitions); + }, + [objectMetadataItem, setRecordGroup], + ); + + const loadRecordIndexStates = useRecoilCallback( + ({ set }) => + async () => { + await findManyRecords(); + + const view = views.find( + (view) => view.id === contextStoreCurrentViewId, + ); + + if (!view || !objectMetadataItem) { + return; + } + + onViewFieldsChange(view.viewFields); + onViewGroupsChange(view.viewGroups); + setTableViewFilterGroups(view.viewFilterGroups ?? []); + setTableFilters( + mapViewFiltersToFilters( + view.viewFilters, + filterableFieldMetadataItems, + ), + ); + setRecordIndexFilters( + mapViewFiltersToFilters( + view.viewFilters, + filterableFieldMetadataItems, + ), + ); + setRecordIndexViewFilterGroups(view.viewFilterGroups ?? []); + setContextStoreTargetedRecordsRuleComponentState((prev) => ({ + ...prev, + filters: mapViewFiltersToFilters( + view.viewFilters, + filterableFieldMetadataItems, + ), + })); + setTableSorts(mapViewSortsToSorts(view.viewSorts, sortDefinitions)); + setRecordIndexSorts( + mapViewSortsToSorts(view.viewSorts, sortDefinitions), + ); + setRecordIndexViewType(view.type); + setRecordIndexViewKanbanFieldMetadataIdState( + view.kanbanFieldMetadataId, + ); + const kanbanAggregateOperationFieldMetadataType = + objectMetadataItem.fields?.find( + (field) => + field.id === view.kanbanAggregateOperationFieldMetadataId, + )?.type; + setRecordIndexViewKanbanAggregateOperationState({ + operation: isDefined(view.kanbanAggregateOperation) + ? convertAggregateOperationToExtendedAggregateOperation( + view.kanbanAggregateOperation, + kanbanAggregateOperationFieldMetadataType, + ) + : view.kanbanAggregateOperation, + fieldMetadataId: view.kanbanAggregateOperationFieldMetadataId, + }); + setRecordIndexIsCompactModeActive(view.isCompact); + }, + [ + filterableFieldMetadataItems, + objectMetadataItem, + onViewFieldsChange, + onViewGroupsChange, + setRecordIndexFilters, + setRecordIndexIsCompactModeActive, + setRecordIndexSorts, + setRecordIndexViewFilterGroups, + setRecordIndexViewKanbanAggregateOperationState, + setRecordIndexViewKanbanFieldMetadataIdState, + setRecordIndexViewType, + setTableFilters, + setTableSorts, + setTableViewFilterGroups, + sortDefinitions, + ], + ); + + return { + loadRecordIndexStates, + }; +}; diff --git a/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainerContextStoreObjectMetadataIdEffect.tsx b/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainerContextStoreObjectMetadataIdEffect.tsx index 79d0dce9d624..2715c8d21e97 100644 --- a/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainerContextStoreObjectMetadataIdEffect.tsx +++ b/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainerContextStoreObjectMetadataIdEffect.tsx @@ -1,4 +1,4 @@ -import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState'; +import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; import { useEffect } from 'react'; @@ -10,8 +10,8 @@ export const RecordShowContainerContextStoreObjectMetadataIdEffect = ({ recordId: string; objectNameSingular: string; }) => { - const setContextStoreCurrentObjectMetadataId = useSetRecoilComponentStateV2( - contextStoreCurrentObjectMetadataIdComponentState, + const setContextStoreCurrentObjectMetadataItem = useSetRecoilComponentStateV2( + contextStoreCurrentObjectMetadataItemComponentState, ); const { objectMetadataItem } = useObjectMetadataItem({ @@ -19,12 +19,17 @@ export const RecordShowContainerContextStoreObjectMetadataIdEffect = ({ }); useEffect(() => { - setContextStoreCurrentObjectMetadataId(objectMetadataItem?.id); + setContextStoreCurrentObjectMetadataItem(objectMetadataItem); return () => { - setContextStoreCurrentObjectMetadataId(null); + setContextStoreCurrentObjectMetadataItem(undefined); }; - }, [recordId, setContextStoreCurrentObjectMetadataId, objectMetadataItem.id]); + }, [ + recordId, + objectMetadataItem.id, + setContextStoreCurrentObjectMetadataItem, + objectMetadataItem, + ]); return null; }; diff --git a/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainer.tsx b/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainer.tsx index 4c2a25958bab..e6319b61c86f 100644 --- a/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainer.tsx +++ b/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainer.tsx @@ -53,11 +53,7 @@ export const SignInBackgroundMockContainer = () => { - {}} - optionsDropdownButton={<>} - /> + } /> void | Promise; }; export const ViewBar = ({ viewBarId, className, optionsDropdownButton, - onCurrentViewChange, }: ViewBarProps) => { const { objectNamePlural } = useParams(); @@ -52,52 +47,49 @@ export const ViewBar = ({ - - - - - - + + + + - - : - } - rightComponent={ - <> - - + : + } + rightComponent={ + <> + + + {optionsDropdownButton} + + } + bottomComponent={ + - {optionsDropdownButton} - - } - bottomComponent={ - - } - /> - } - /> - + } + /> + } + /> ); }; diff --git a/packages/twenty-front/src/modules/views/components/ViewBarEffect.tsx b/packages/twenty-front/src/modules/views/components/ViewBarEffect.tsx deleted file mode 100644 index 662b4ed49fcb..000000000000 --- a/packages/twenty-front/src/modules/views/components/ViewBarEffect.tsx +++ /dev/null @@ -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 <>; -}; diff --git a/packages/twenty-front/src/modules/views/components/ViewBarRecordFilterEffect.tsx b/packages/twenty-front/src/modules/views/components/ViewBarRecordFilterEffect.tsx index 09c8ecd84491..b1e83861e75e 100644 --- a/packages/twenty-front/src/modules/views/components/ViewBarRecordFilterEffect.tsx +++ b/packages/twenty-front/src/modules/views/components/ViewBarRecordFilterEffect.tsx @@ -1,6 +1,5 @@ -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'; @@ -12,7 +11,6 @@ import { hasInitializedCurrentRecordFiltersComponentFamilyState } from '@/views/ 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 = () => { @@ -24,15 +22,8 @@ export const ViewBarRecordFilterEffect = () => { contextStoreCurrentViewIdComponentState, ); - const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2( - contextStoreCurrentObjectMetadataIdComponentState, - ); - - const objectMetadataItems = useRecoilValue(objectMetadataItemsState); - - const objectMetadataItem = objectMetadataItems.find( - (objectMetadataItem) => - objectMetadataItem.id === contextStoreCurrentObjectMetadataId, + const contextStoreCurrentObjectMetadataItem = useRecoilComponentValueV2( + contextStoreCurrentObjectMetadataItemComponentState, ); const [ @@ -54,14 +45,17 @@ export const ViewBarRecordFilterEffect = () => { ); const { filterableFieldMetadataItems } = useFilterableFieldMetadataItems( - objectMetadataItem?.id, + contextStoreCurrentObjectMetadataItem?.id, ); useEffect(() => { if (isDataPrefetched && !hasInitializedCurrentRecordFilters) { const currentView = views.find((view) => view.id === currentViewId); - if (currentView?.objectMetadataId !== objectMetadataItem?.id) { + if ( + currentView?.objectMetadataId !== + contextStoreCurrentObjectMetadataItem?.id + ) { return; } @@ -84,7 +78,7 @@ export const ViewBarRecordFilterEffect = () => { currentRecordFilters, hasInitializedCurrentRecordFilters, setHasInitializedCurrentRecordFilters, - objectMetadataItem?.id, + contextStoreCurrentObjectMetadataItem?.id, ]); return null; diff --git a/packages/twenty-front/src/modules/views/events/contexts/ViewEventContext.ts b/packages/twenty-front/src/modules/views/events/contexts/ViewEventContext.ts deleted file mode 100644 index ba02a09aa2e4..000000000000 --- a/packages/twenty-front/src/modules/views/events/contexts/ViewEventContext.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { View } from '@/views/types/View'; -import { createEventContext } from '~/utils/createEventContext'; - -type ViewEventContextType = { - onCurrentViewChange: (view: View | undefined) => void | Promise; -}; - -export const ViewEventContext = createEventContext(); diff --git a/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx b/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx index 36b7925ea2a6..d37448de9937 100644 --- a/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx +++ b/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx @@ -1,39 +1,14 @@ -import styled from '@emotion/styled'; -import { useParams } from 'react-router-dom'; - -import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext'; -import { getActionMenuIdFromRecordIndexId } from '@/action-menu/utils/getActionMenuIdFromRecordIndexId'; +import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState'; import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState'; import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext'; import { mainContextStoreComponentInstanceIdState } from '@/context-store/states/mainContextStoreComponentInstanceId'; -import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; -import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural'; -import { lastShowPageRecordIdState } from '@/object-record/record-field/states/lastShowPageRecordId'; -import { RecordFiltersComponentInstanceContext } from '@/object-record/record-filter/states/context/RecordFiltersComponentInstanceContext'; -import { RecordIndexContainer } from '@/object-record/record-index/components/RecordIndexContainer'; -import { RecordIndexContainerContextStoreNumberOfSelectedRecordsEffect } from '@/object-record/record-index/components/RecordIndexContainerContextStoreNumberOfSelectedRecordsEffect'; -import { RecordIndexContainerContextStoreObjectMetadataEffect } from '@/object-record/record-index/components/RecordIndexContainerContextStoreObjectMetadataEffect'; -import { RecordIndexPageHeader } from '@/object-record/record-index/components/RecordIndexPageHeader'; -import { RecordIndexContextProvider } from '@/object-record/record-index/contexts/RecordIndexContext'; -import { useHandleIndexIdentifierClick } from '@/object-record/record-index/hooks/useHandleIndexIdentifierClick'; -import { PageBody } from '@/ui/layout/page/components/PageBody'; +import { RecordIndexContainerGater } from '@/object-record/record-index/components/RecordIndexContainerGater'; import { PageContainer } from '@/ui/layout/page/components/PageContainer'; -import { PageTitle } from '@/ui/utilities/page-title/components/PageTitle'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; -import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext'; import { isUndefined } from '@sniptt/guards'; -import { useRecoilCallback, useRecoilValue } from 'recoil'; -import { capitalize } from 'twenty-shared'; - -const StyledIndexContainer = styled.div` - display: flex; - height: 100%; - width: 100%; -`; +import { useRecoilValue } from 'recoil'; export const RecordIndexPage = () => { - const objectNamePlural = useParams().objectNamePlural ?? ''; - const mainContextStoreComponentInstanceId = useRecoilValue( mainContextStoreComponentInstanceIdState, ); @@ -43,31 +18,15 @@ export const RecordIndexPage = () => { mainContextStoreComponentInstanceId, ); - const recordIndexId = `${objectNamePlural}-${contextStoreCurrentViewId}`; - - const { objectNameSingular } = useObjectNameSingularFromPlural({ - objectNamePlural, - }); - - const { objectMetadataItem } = useObjectMetadataItem({ - objectNameSingular, - }); - - const { indexIdentifierUrl } = useHandleIndexIdentifierClick({ - objectMetadataItem, - recordIndexId, - }); - - const handleIndexRecordsLoaded = useRecoilCallback( - ({ set }) => - () => { - // TODO: find a better way to reset this state ? - set(lastShowPageRecordIdState, null); - }, - [], + const objectMetadataItem = useRecoilComponentValueV2( + contextStoreCurrentObjectMetadataItemComponentState, + mainContextStoreComponentInstanceId, ); - if (isUndefined(contextStoreCurrentViewId)) { + if ( + isUndefined(objectMetadataItem) || + isUndefined(contextStoreCurrentViewId) + ) { return null; } @@ -78,40 +37,7 @@ export const RecordIndexPage = () => { instanceId: mainContextStoreComponentInstanceId, }} > - - - - - - - - - - - - - - - - - + ); diff --git a/packages/twenty-front/src/testing/jest/JestContextStoreSetter.tsx b/packages/twenty-front/src/testing/jest/JestContextStoreSetter.tsx index b54dedf390be..f51a3557f539 100644 --- a/packages/twenty-front/src/testing/jest/JestContextStoreSetter.tsx +++ b/packages/twenty-front/src/testing/jest/JestContextStoreSetter.tsx @@ -1,6 +1,6 @@ import { PropsWithChildren, useEffect, useState } from 'react'; -import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState'; +import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState'; import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState'; import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState'; import { @@ -34,8 +34,8 @@ export const JestContextStoreSetter = ({ contextStoreTargetedRecordsRuleComponentState, ); - const setContextStoreCurrentObjectMetadataId = useSetRecoilComponentStateV2( - contextStoreCurrentObjectMetadataIdComponentState, + const setContextStoreCurrentObjectMetadataItem = useSetRecoilComponentStateV2( + contextStoreCurrentObjectMetadataItemComponentState, ); const setContextStoreNumberOfSelectedRecords = useSetRecoilComponentStateV2( @@ -55,20 +55,21 @@ export const JestContextStoreSetter = ({ const [isLoaded, setIsLoaded] = useState(false); useEffect(() => { setContextStoreTargetedRecordsRule(contextStoreTargetedRecordsRule); - setContextStoreCurrentObjectMetadataId(contextStoreCurrentObjectMetadataId); + setContextStoreCurrentObjectMetadataItem(objectMetadataItem); setContextStoreNumberOfSelectedRecords(contextStoreNumberOfSelectedRecords); setcontextStoreFiltersComponentState(contextStoreFilters); setIsLoaded(true); }, [ setContextStoreTargetedRecordsRule, - setContextStoreCurrentObjectMetadataId, + setContextStoreCurrentObjectMetadataItem, contextStoreTargetedRecordsRule, contextStoreCurrentObjectMetadataId, setContextStoreNumberOfSelectedRecords, contextStoreNumberOfSelectedRecords, setcontextStoreFiltersComponentState, contextStoreFilters, + objectMetadataItem, ]); return isLoaded ? <>{children} : null; From ec415ef4847170061e967ca028d016ade395351a Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Mon, 17 Feb 2025 20:59:44 +0100 Subject: [PATCH 03/14] Fix --- .../components/MainContextStoreProvider.tsx | 30 +++----- .../MainContextStoreProviderEffect.tsx | 15 ++-- ...seContextStoreObjectMetadataItemOrThrow.ts | 1 - .../useColumnDefinitionsFromFieldMetadata.ts | 73 +++++++------------ .../components/RecordIndexContainerGater.tsx | 2 - .../hooks/useLoadRecordIndexStates.ts | 45 ++++-------- .../components/RecordShowContainer.tsx | 5 -- ...inerContextStoreObjectMetadataIdEffect.tsx | 35 --------- .../record-table/hooks/useRecordTable.ts | 20 ----- .../record-table/hooks/useSetTableColumns.ts | 29 ++++++++ .../record-table/hooks/useTableColumns.ts | 5 +- .../components/PrefetchRunQueriesEffect.tsx | 20 ++++- .../prefetch/states/prefetchViewsState.ts | 7 ++ ...wIdFromObjectMetadataItemFamilySelector.ts | 18 +++++ .../prefetchViewFromViewIdFamilySelector.ts | 20 +++++ ...IdsFromObjectMetadataItemFamilySelector.ts | 15 ++++ ...ewsFromObjectMetadataItemFamilySelector.ts | 18 +++++ .../SignInBackgroundMockContainerEffect.tsx | 10 ++- .../pages/object-record/RecordIndexPage.tsx | 13 +++- 19 files changed, 206 insertions(+), 175 deletions(-) delete mode 100644 packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainerContextStoreObjectMetadataIdEffect.tsx create mode 100644 packages/twenty-front/src/modules/object-record/record-table/hooks/useSetTableColumns.ts create mode 100644 packages/twenty-front/src/modules/prefetch/states/prefetchViewsState.ts create mode 100644 packages/twenty-front/src/modules/prefetch/states/selector/prefetchIndexViewIdFromObjectMetadataItemFamilySelector.ts create mode 100644 packages/twenty-front/src/modules/prefetch/states/selector/prefetchViewFromViewIdFamilySelector.ts create mode 100644 packages/twenty-front/src/modules/prefetch/states/selector/prefetchViewIdsFromObjectMetadataItemFamilySelector.ts create mode 100644 packages/twenty-front/src/modules/prefetch/states/selector/prefetchViewsFromObjectMetadataItemFamilySelector.ts diff --git a/packages/twenty-front/src/modules/context-store/components/MainContextStoreProvider.tsx b/packages/twenty-front/src/modules/context-store/components/MainContextStoreProvider.tsx index 0a1645e2d227..fc2051a65e53 100644 --- a/packages/twenty-front/src/modules/context-store/components/MainContextStoreProvider.tsx +++ b/packages/twenty-front/src/modules/context-store/components/MainContextStoreProvider.tsx @@ -1,10 +1,8 @@ import { MainContextStoreProviderEffect } from '@/context-store/components/MainContextStoreProviderEffect'; import { useLastVisitedView } from '@/navigation/hooks/useLastVisitedView'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; -import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData'; -import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; +import { prefetchIndexViewIdFromObjectMetadataItemFamilySelector } from '@/prefetch/states/selector/prefetchIndexViewIdFromObjectMetadataItemFamilySelector'; import { AppPath } from '@/types/AppPath'; -import { View } from '@/views/types/View'; import { isNonEmptyString } from '@sniptt/guards'; import { useParams, useSearchParams } from 'react-router-dom'; import { useRecoilValue } from 'recoil'; @@ -14,7 +12,7 @@ import { useIsMatchingLocation } from '~/hooks/useIsMatchingLocation'; const getViewId = ( viewIdFromQueryParams: string | null, - indexView?: View, + indexViewId?: string, lastVisitedViewId?: string, ) => { if (isDefined(viewIdFromQueryParams)) { @@ -25,8 +23,8 @@ const getViewId = ( return lastVisitedViewId; } - if (isDefined(indexView)) { - return indexView.id; + if (isDefined(indexViewId)) { + return indexViewId; } return undefined; @@ -48,9 +46,6 @@ export const MainContextStoreProvider = () => { const [searchParams] = useSearchParams(); const viewIdQueryParam = searchParams.get('viewId'); - // Todo: this is triggering a lot of re-renders as we update the viewFields, we should introduce a state here - const { records: views } = usePrefetchedData(PrefetchKey.AllViews); - const objectMetadataItems = useRecoilValue(objectMetadataItemsState); const objectMetadataItem = objectMetadataItems.find( @@ -63,23 +58,20 @@ export const MainContextStoreProvider = () => { objectMetadataItem?.namePlural ?? '', ); - const viewsOnCurrentObject = views.filter( - (view) => view.objectMetadataId === objectMetadataItem?.id, + const indexViewId = useRecoilValue( + prefetchIndexViewIdFromObjectMetadataItemFamilySelector({ + objectMetadataItemId: objectMetadataItem?.id, + }), ); - const indexView = viewsOnCurrentObject.find((view) => view.key === 'INDEX'); - const viewId = getViewId(viewIdQueryParam, indexView, lastVisitedViewId); + const viewId = getViewId(viewIdQueryParam, indexViewId, lastVisitedViewId); const mainContextStoreComponentInstanceId = `${pageName}-${objectMetadataItem?.namePlural}-${viewId}`; - const view = viewsOnCurrentObject.find((view) => view.id === viewId); - - console.log('Provider'); if ( !isDefined(pageName) || !isDefined(objectMetadataItem) || - !isNonEmptyString(viewId) || - !isDefined(view) + !isNonEmptyString(viewId) ) { return null; } @@ -89,7 +81,7 @@ export const MainContextStoreProvider = () => { mainContextStoreComponentInstanceIdToSet={ mainContextStoreComponentInstanceId } - view={view} + viewId={viewId} objectMetadataItem={objectMetadataItem} /> ); diff --git a/packages/twenty-front/src/modules/context-store/components/MainContextStoreProviderEffect.tsx b/packages/twenty-front/src/modules/context-store/components/MainContextStoreProviderEffect.tsx index 9e077765097a..01d63ff5c31f 100644 --- a/packages/twenty-front/src/modules/context-store/components/MainContextStoreProviderEffect.tsx +++ b/packages/twenty-front/src/modules/context-store/components/MainContextStoreProviderEffect.tsx @@ -5,17 +5,16 @@ import { useSetLastVisitedObjectMetadataId } from '@/navigation/hooks/useSetLast import { useSetLastVisitedViewForObjectMetadataNamePlural } from '@/navigation/hooks/useSetLastVisitedViewForObjectMetadataNamePlural'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2'; -import { View } from '@/views/types/View'; import { useEffect } from 'react'; import { useRecoilState } from 'recoil'; export const MainContextStoreProviderEffect = ({ mainContextStoreComponentInstanceIdToSet, - view, + viewId, objectMetadataItem, }: { mainContextStoreComponentInstanceIdToSet: string; - view: View; + viewId: string; objectMetadataItem: ObjectMetadataItem; }) => { const [ @@ -46,8 +45,6 @@ export const MainContextStoreProviderEffect = ({ useEffect(() => { if (contextStoreCurrentObjectMetadataItem?.id !== objectMetadataItem.id) { - console.log('Setting object metadata item'); - console.log('objectMetadataItem', objectMetadataItem); setContextStoreCurrentObjectMetadataItem(objectMetadataItem); } @@ -62,15 +59,15 @@ export const MainContextStoreProviderEffect = ({ setLastVisitedViewForObjectMetadataNamePlural({ objectNamePlural: objectMetadataItem.namePlural, - viewId: view.id, + viewId: viewId, }); setLastVisitedObjectMetadataId({ objectMetadataItemId: objectMetadataItem.id, }); - if (contextStoreCurrentViewId !== view.id) { - setContextStoreCurrentViewId(view.id); + if (contextStoreCurrentViewId !== viewId) { + setContextStoreCurrentViewId(viewId); } }, [ contextStoreCurrentObjectMetadataItem, @@ -84,7 +81,7 @@ export const MainContextStoreProviderEffect = ({ setLastVisitedObjectMetadataId, setLastVisitedViewForObjectMetadataNamePlural, setMainContextStoreComponentInstanceId, - view, + viewId, ]); return null; diff --git a/packages/twenty-front/src/modules/context-store/hooks/useContextStoreObjectMetadataItemOrThrow.ts b/packages/twenty-front/src/modules/context-store/hooks/useContextStoreObjectMetadataItemOrThrow.ts index 0dc5cb72ba17..ffab8b348300 100644 --- a/packages/twenty-front/src/modules/context-store/hooks/useContextStoreObjectMetadataItemOrThrow.ts +++ b/packages/twenty-front/src/modules/context-store/hooks/useContextStoreObjectMetadataItemOrThrow.ts @@ -8,7 +8,6 @@ export const useContextStoreObjectMetadataItemOrThrow = ( contextStoreCurrentObjectMetadataItemComponentState, contextStoreInstanceId, ); - console.log('objectMetadataItem', objectMetadataItem); if (!objectMetadataItem) { throw new Error('Object metadata item is not se in context store'); diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata.ts index e1b50dc6d7d0..7a3dd4ec873d 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata.ts @@ -1,5 +1,3 @@ -import { useMemo } from 'react'; - import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata'; import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition'; @@ -13,14 +11,8 @@ import { formatFieldMetadataItemsAsSortDefinitions } from '../utils/formatFieldM export const useColumnDefinitionsFromFieldMetadata = ( objectMetadataItem: ObjectMetadataItem, ) => { - const activeFieldMetadataItems = useMemo( - () => - objectMetadataItem - ? objectMetadataItem.fields.filter( - ({ isActive, isSystem }) => isActive && !isSystem, - ) - : [], - [objectMetadataItem], + const activeFieldMetadataItems = objectMetadataItem.fields.filter( + ({ isActive, isSystem }) => isActive && !isSystem, ); const filterableFieldMetadataItems = useRecoilValue( @@ -33,43 +25,30 @@ export const useColumnDefinitionsFromFieldMetadata = ( fields: activeFieldMetadataItems, }); - const columnDefinitions: ColumnDefinition[] = useMemo( - () => - objectMetadataItem - ? activeFieldMetadataItems - .map((field, index) => - formatFieldMetadataItemAsColumnDefinition({ - position: index, - field, - objectMetadataItem, - }), - ) - .filter(filterAvailableTableColumns) - .map((column) => { - const existsInFilterDefinitions = - filterableFieldMetadataItems.some( - (fieldMetadataItem) => - fieldMetadataItem.id === column.fieldMetadataId, - ); - - const existsInSortDefinitions = sortDefinitions.some( - (sort) => sort.fieldMetadataId === column.fieldMetadataId, - ); - - return { - ...column, - isFilterable: existsInFilterDefinitions, - isSortable: existsInSortDefinitions, - }; - }) - : [], - [ - filterableFieldMetadataItems, - activeFieldMetadataItems, - objectMetadataItem, - sortDefinitions, - ], - ); + const columnDefinitions: ColumnDefinition[] = + activeFieldMetadataItems + .map((field, index) => + formatFieldMetadataItemAsColumnDefinition({ + position: index, + field, + objectMetadataItem, + }), + ) + .filter(filterAvailableTableColumns) + .map((column) => { + const existsInFilterDefinitions = filterableFieldMetadataItems.some( + (fieldMetadataItem) => + fieldMetadataItem.id === column.fieldMetadataId, + ); + const existsInSortDefinitions = sortDefinitions.some( + (sort) => sort.fieldMetadataId === column.fieldMetadataId, + ); + return { + ...column, + isFilterable: existsInFilterDefinitions, + isSortable: existsInSortDefinitions, + }; + }); return { columnDefinitions, diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainerGater.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainerGater.tsx index 153f4c1d366b..5c66bfe5224b 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainerGater.tsx +++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainerGater.tsx @@ -54,8 +54,6 @@ export const RecordIndexContainerGater = () => { recordIndexId, }); - console.log('recordIndexId', recordIndexId); - return ( <> { const setContextStoreTargetedRecordsRuleComponentState = useSetRecoilComponentStateV2(contextStoreTargetedRecordsRuleComponentState); - const { records: views, findManyRecords } = useLazyPrefetchedData( - PrefetchKey.AllViews, - ); - const recordIndexId = `${objectMetadataItem.namePlural}-${contextStoreCurrentViewId}`; - console.log('recordIndexId', recordIndexId); const setRecordIndexViewFilterGroups = useSetRecoilState( recordIndexViewFilterGroupsState, @@ -67,18 +62,15 @@ export const useLoadRecordIndexStates = () => { recordIndexKanbanAggregateOperationState, ); const setRecordGroup = useSetRecordGroup(recordIndexId); - const { - setTableViewFilterGroups, - setTableFilters, - setTableSorts, - setTableColumns, - } = useRecordTable({ - recordTableId: recordIndexId, - }); + const { setTableViewFilterGroups, setTableFilters, setTableSorts } = + useRecordTable({ + recordTableId: recordIndexId, + }); + + const { setTableColumns } = useSetTableColumns(recordIndexId); const { columnDefinitions, sortDefinitions } = - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - useColumnDefinitionsFromFieldMetadata(objectMetadataItem!); + useColumnDefinitionsFromFieldMetadata(objectMetadataItem); const onViewFieldsChange = useRecoilCallback( ({ set, snapshot }) => @@ -86,18 +78,14 @@ export const useLoadRecordIndexStates = () => { if (!objectMetadataItem) { return; } - const newFieldDefinitions = mapViewFieldsToColumnDefinitions({ viewFields, columnDefinitions, }); - setTableColumns(newFieldDefinitions); - const existingRecordIndexFieldDefinitions = snapshot .getLoadable(recordIndexFieldDefinitionsState) .getValue(); - if ( !isDeeplyEqual( existingRecordIndexFieldDefinitions, @@ -106,7 +94,6 @@ export const useLoadRecordIndexStates = () => { ) { set(recordIndexFieldDefinitionsState, newFieldDefinitions); } - for (const viewField of viewFields) { const viewFieldMetadataType = objectMetadataItem.fields?.find( (field) => field.id === viewField.fieldMetadataId, @@ -118,7 +105,6 @@ export const useLoadRecordIndexStates = () => { }), ) .getValue(); - const convertedViewFieldAggregateOperation = isDefined( viewField.aggregateOperation, ) @@ -127,7 +113,6 @@ export const useLoadRecordIndexStates = () => { viewFieldMetadataType, ) : viewField.aggregateOperation; - if ( aggregateOperationForViewField !== convertedViewFieldAggregateOperation @@ -141,7 +126,7 @@ export const useLoadRecordIndexStates = () => { } } }, - [columnDefinitions, objectMetadataItem, setTableColumns], + [], ); const onViewGroupsChange = useCallback( @@ -161,15 +146,15 @@ export const useLoadRecordIndexStates = () => { ); const loadRecordIndexStates = useRecoilCallback( - ({ set }) => + ({ snapshot }) => async () => { - await findManyRecords(); + const views = snapshot.getLoadable(prefetchViewsState).getValue(); const view = views.find( (view) => view.id === contextStoreCurrentViewId, ); - if (!view || !objectMetadataItem) { + if (!view) { return; } @@ -221,10 +206,12 @@ export const useLoadRecordIndexStates = () => { setRecordIndexIsCompactModeActive(view.isCompact); }, [ + contextStoreCurrentViewId, filterableFieldMetadataItems, - objectMetadataItem, + objectMetadataItem.fields, onViewFieldsChange, onViewGroupsChange, + setContextStoreTargetedRecordsRuleComponentState, setRecordIndexFilters, setRecordIndexIsCompactModeActive, setRecordIndexSorts, diff --git a/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx b/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx index 2b837c33fa19..4b9408308141 100644 --- a/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx +++ b/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx @@ -5,7 +5,6 @@ import { InformationBannerDeletedRecord } from '@/information-banner/components/ import { ContextStoreCurrentViewTypeEffect } from '@/context-store/components/ContextStoreCurrentViewTypeEffect'; import { ContextStoreViewType } from '@/context-store/types/ContextStoreViewType'; -import { RecordShowContainerContextStoreObjectMetadataIdEffect } from '@/object-record/record-show/components/RecordShowContainerContextStoreObjectMetadataIdEffect'; import { RecordShowContainerContextStoreTargetedRecordsEffect } from '@/object-record/record-show/components/RecordShowContainerContextStoreTargetedRecordsEffect'; import { useRecordShowContainerData } from '@/object-record/record-show/hooks/useRecordShowContainerData'; import { useRecordShowContainerTabs } from '@/object-record/record-show/hooks/useRecordShowContainerTabs'; @@ -45,10 +44,6 @@ export const RecordShowContainer = ({ return ( <> - diff --git a/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainerContextStoreObjectMetadataIdEffect.tsx b/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainerContextStoreObjectMetadataIdEffect.tsx deleted file mode 100644 index 2715c8d21e97..000000000000 --- a/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainerContextStoreObjectMetadataIdEffect.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState'; -import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; -import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; -import { useEffect } from 'react'; - -export const RecordShowContainerContextStoreObjectMetadataIdEffect = ({ - recordId, - objectNameSingular, -}: { - recordId: string; - objectNameSingular: string; -}) => { - const setContextStoreCurrentObjectMetadataItem = useSetRecoilComponentStateV2( - contextStoreCurrentObjectMetadataItemComponentState, - ); - - const { objectMetadataItem } = useObjectMetadataItem({ - objectNameSingular: objectNameSingular, - }); - - useEffect(() => { - setContextStoreCurrentObjectMetadataItem(objectMetadataItem); - - return () => { - setContextStoreCurrentObjectMetadataItem(undefined); - }; - }, [ - recordId, - objectMetadataItem.id, - setContextStoreCurrentObjectMetadataItem, - objectMetadataItem, - ]); - - return null; -}; diff --git a/packages/twenty-front/src/modules/object-record/record-table/hooks/useRecordTable.ts b/packages/twenty-front/src/modules/object-record/record-table/hooks/useRecordTable.ts index cd54668fd1d9..2bc033f33077 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/hooks/useRecordTable.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/hooks/useRecordTable.ts @@ -22,7 +22,6 @@ import { onColumnsChangeComponentState } from '@/object-record/record-table/stat import { onEntityCountChangeComponentState } from '@/object-record/record-table/states/onEntityCountChangeComponentState'; import { onToggleColumnFilterComponentState } from '@/object-record/record-table/states/onToggleColumnFilterComponentState'; import { onToggleColumnSortComponentState } from '@/object-record/record-table/states/onToggleColumnSortComponentState'; -import { tableColumnsComponentState } from '@/object-record/record-table/states/tableColumnsComponentState'; import { tableFiltersComponentState } from '@/object-record/record-table/states/tableFiltersComponentState'; import { tableLastRowVisibleComponentState } from '@/object-record/record-table/states/tableLastRowVisibleComponentState'; import { tableSortsComponentState } from '@/object-record/record-table/states/tableSortsComponentState'; @@ -53,11 +52,6 @@ export const useRecordTable = (props?: useRecordTableProps) => { recordTableId, ); - const tableColumnsState = useRecoilComponentCallbackStateV2( - tableColumnsComponentState, - recordTableId, - ); - const setAvailableTableColumns = useRecoilCallback( ({ snapshot, set }) => (columns: ColumnDefinition[]) => { @@ -74,19 +68,6 @@ export const useRecordTable = (props?: useRecordTableProps) => { [availableTableColumnsState], ); - const setTableColumns = useRecoilCallback( - ({ snapshot, set }) => - (columns: ColumnDefinition[]) => { - const tableColumns = getSnapshotValue(snapshot, tableColumnsState); - - if (isDeeplyEqual(tableColumns, columns)) { - return; - } - set(tableColumnsState, columns); - }, - [tableColumnsState], - ); - const setOnEntityCountChange = useSetRecoilComponentStateV2( onEntityCountChangeComponentState, recordTableId, @@ -260,7 +241,6 @@ export const useRecordTable = (props?: useRecordTableProps) => { setTableSorts, setOnEntityCountChange, setRecordTableData, - setTableColumns, leaveTableFocus, setRowSelected, resetTableRowSelection, diff --git a/packages/twenty-front/src/modules/object-record/record-table/hooks/useSetTableColumns.ts b/packages/twenty-front/src/modules/object-record/record-table/hooks/useSetTableColumns.ts new file mode 100644 index 000000000000..6cd9c91114c1 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-table/hooks/useSetTableColumns.ts @@ -0,0 +1,29 @@ +import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata'; +import { tableColumnsComponentState } from '@/object-record/record-table/states/tableColumnsComponentState'; +import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition'; +import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; +import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue'; +import { useRecoilCallback } from 'recoil'; +import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; + +export const useSetTableColumns = (recordTableId?: string) => { + const tableColumnsState = useRecoilComponentCallbackStateV2( + tableColumnsComponentState, + recordTableId, + ); + + const setTableColumns = useRecoilCallback( + ({ snapshot, set }) => + (columns: ColumnDefinition[]) => { + const tableColumns = getSnapshotValue(snapshot, tableColumnsState); + + if (isDeeplyEqual(tableColumns, columns)) { + return; + } + set(tableColumnsState, columns); + }, + [tableColumnsState], + ); + + return { setTableColumns }; +}; diff --git a/packages/twenty-front/src/modules/object-record/record-table/hooks/useTableColumns.ts b/packages/twenty-front/src/modules/object-record/record-table/hooks/useTableColumns.ts index f972e41e97a6..af756b49f53f 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/hooks/useTableColumns.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/hooks/useTableColumns.ts @@ -4,6 +4,7 @@ import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata' import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable'; import { useMoveViewColumns } from '@/views/hooks/useMoveViewColumns'; +import { useSetTableColumns } from '@/object-record/record-table/hooks/useSetTableColumns'; import { availableTableColumnsComponentState } from '@/object-record/record-table/states/availableTableColumnsComponentState'; import { visibleTableColumnsComponentSelector } from '@/object-record/record-table/states/selectors/visibleTableColumnsComponentSelector'; import { tableColumnsComponentState } from '@/object-record/record-table/states/tableColumnsComponentState'; @@ -15,10 +16,12 @@ type useRecordTableProps = { }; export const useTableColumns = (props?: useRecordTableProps) => { - const { onColumnsChange, setTableColumns } = useRecordTable({ + const { onColumnsChange } = useRecordTable({ recordTableId: props?.recordTableId, }); + const { setTableColumns } = useSetTableColumns(props?.recordTableId); + const availableTableColumns = useRecoilComponentValueV2( availableTableColumnsComponentState, props?.recordTableId, diff --git a/packages/twenty-front/src/modules/prefetch/components/PrefetchRunQueriesEffect.tsx b/packages/twenty-front/src/modules/prefetch/components/PrefetchRunQueriesEffect.tsx index 2c4d1f916992..548fb1e20398 100644 --- a/packages/twenty-front/src/modules/prefetch/components/PrefetchRunQueriesEffect.tsx +++ b/packages/twenty-front/src/modules/prefetch/components/PrefetchRunQueriesEffect.tsx @@ -1,5 +1,5 @@ import { useEffect } from 'react'; -import { useRecoilValue } from 'recoil'; +import { useRecoilCallback, useRecoilValue } from 'recoil'; import { currentUserState } from '@/auth/states/currentUserState'; import { Favorite } from '@/favorites/types/Favorite'; @@ -8,10 +8,12 @@ import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadat import { useCombinedFindManyRecords } from '@/object-record/multiple-objects/hooks/useCombinedFindManyRecords'; import { PREFETCH_CONFIG } from '@/prefetch/constants/PrefetchConfig'; import { useUpsertRecordsInCacheForPrefetchKey } from '@/prefetch/hooks/internal/useUpsertRecordsInCacheForPrefetchKey'; +import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState'; import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; import { View } from '@/views/types/View'; import { useIsWorkspaceActivationStatusSuspended } from '@/workspace/hooks/useIsWorkspaceActivationStatusSuspended'; import { isDefined } from 'twenty-shared'; +import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; export const PrefetchRunQueriesEffect = () => { const currentUser = useRecoilValue(currentUserState); @@ -48,9 +50,24 @@ export const PrefetchRunQueriesEffect = () => { skip: !currentUser || isWorkspaceSuspended, }); + const setPrefetchViewsState = useRecoilCallback( + ({ set, snapshot }) => + (views: View[]) => { + const existingViews = snapshot + .getLoadable(prefetchViewsState) + .getValue(); + + if (!isDeeplyEqual(existingViews, views)) { + set(prefetchViewsState, views); + } + }, + [], + ); + useEffect(() => { if (isDefined(result.views)) { upsertViewsInCache(result.views as View[]); + setPrefetchViewsState(result.views as View[]); } if (isDefined(result.favorites)) { @@ -64,6 +81,7 @@ export const PrefetchRunQueriesEffect = () => { upsertViewsInCache, upsertFavoritesInCache, upsertFavoritesFoldersInCache, + setPrefetchViewsState, ]); return <>; diff --git a/packages/twenty-front/src/modules/prefetch/states/prefetchViewsState.ts b/packages/twenty-front/src/modules/prefetch/states/prefetchViewsState.ts new file mode 100644 index 000000000000..240d8d7a1a13 --- /dev/null +++ b/packages/twenty-front/src/modules/prefetch/states/prefetchViewsState.ts @@ -0,0 +1,7 @@ +import { View } from '@/views/types/View'; +import { createState } from 'twenty-ui'; + +export const prefetchViewsState = createState({ + key: 'prefetchViewsState', + defaultValue: [], +}); diff --git a/packages/twenty-front/src/modules/prefetch/states/selector/prefetchIndexViewIdFromObjectMetadataItemFamilySelector.ts b/packages/twenty-front/src/modules/prefetch/states/selector/prefetchIndexViewIdFromObjectMetadataItemFamilySelector.ts new file mode 100644 index 000000000000..9399d602a11a --- /dev/null +++ b/packages/twenty-front/src/modules/prefetch/states/selector/prefetchIndexViewIdFromObjectMetadataItemFamilySelector.ts @@ -0,0 +1,18 @@ +import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState'; +import { ViewKey } from '@/views/types/ViewKey'; +import { selectorFamily } from 'recoil'; + +export const prefetchIndexViewIdFromObjectMetadataItemFamilySelector = + selectorFamily({ + key: 'prefetchIndexViewIdFromObjectMetadataItemFamilySelector', + get: + ({ objectMetadataItemId }) => + ({ get }) => { + const views = get(prefetchViewsState); + return views?.find( + (view) => + view.objectMetadataId === objectMetadataItemId && + view.key === ViewKey.Index, + )?.id; + }, + }); diff --git a/packages/twenty-front/src/modules/prefetch/states/selector/prefetchViewFromViewIdFamilySelector.ts b/packages/twenty-front/src/modules/prefetch/states/selector/prefetchViewFromViewIdFamilySelector.ts new file mode 100644 index 000000000000..174cedef735e --- /dev/null +++ b/packages/twenty-front/src/modules/prefetch/states/selector/prefetchViewFromViewIdFamilySelector.ts @@ -0,0 +1,20 @@ +import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState'; +import { ViewKey } from '@/views/types/ViewKey'; +import { selectorFamily } from 'recoil'; + +export const prefetchViewFromViewIdFamilySelector = selectorFamily< + string | undefined, + { objectMetadataItemId: string } +>({ + key: 'prefetchViewFromViewIdFamilySelector', + get: + ({ objectMetadataItemId }) => + ({ get }) => { + const views = get(prefetchViewsState); + return views?.find( + (view) => + view.objectMetadataId === objectMetadataItemId && + view.key === ViewKey.Index, + )?.id; + }, +}); diff --git a/packages/twenty-front/src/modules/prefetch/states/selector/prefetchViewIdsFromObjectMetadataItemFamilySelector.ts b/packages/twenty-front/src/modules/prefetch/states/selector/prefetchViewIdsFromObjectMetadataItemFamilySelector.ts new file mode 100644 index 000000000000..30277752c4f7 --- /dev/null +++ b/packages/twenty-front/src/modules/prefetch/states/selector/prefetchViewIdsFromObjectMetadataItemFamilySelector.ts @@ -0,0 +1,15 @@ +import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState'; +import { selectorFamily } from 'recoil'; + +export const prefetchViewIdsFromObjectMetadataItemFamilySelector = + selectorFamily({ + key: 'prefetchViewIdsFromObjectMetadataItemFamilySelector', + get: + ({ objectMetadataItemId }) => + ({ get }) => { + const views = get(prefetchViewsState); + return views + .filter((view) => view.objectMetadataId === objectMetadataItemId) + .map((view) => view.id); + }, + }); diff --git a/packages/twenty-front/src/modules/prefetch/states/selector/prefetchViewsFromObjectMetadataItemFamilySelector.ts b/packages/twenty-front/src/modules/prefetch/states/selector/prefetchViewsFromObjectMetadataItemFamilySelector.ts new file mode 100644 index 000000000000..902d4c66cb56 --- /dev/null +++ b/packages/twenty-front/src/modules/prefetch/states/selector/prefetchViewsFromObjectMetadataItemFamilySelector.ts @@ -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, + ); + }, +}); diff --git a/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainerEffect.tsx b/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainerEffect.tsx index 75929819a69b..8c5c81b46235 100644 --- a/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainerEffect.tsx +++ b/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainerEffect.tsx @@ -4,6 +4,7 @@ import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadata import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural'; import { useSetRecordIndexEntityCount } from '@/object-record/record-index/hooks/useSetRecordIndexEntityCount'; import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable'; +import { useSetTableColumns } from '@/object-record/record-table/hooks/useSetTableColumns'; import { SIGN_IN_BACKGROUND_MOCK_COLUMN_DEFINITIONS } from '@/sign-in-background-mock/constants/SignInBackgroundMockColumnDefinitions'; import { SIGN_IN_BACKGROUND_MOCK_SORT_DEFINITIONS } from '@/sign-in-background-mock/constants/SignInBackgroundMockSortDefinitions'; import { SIGN_IN_BACKGROUND_MOCK_VIEW_FIELDS } from '@/sign-in-background-mock/constants/SignInBackgroundMockViewFields'; @@ -21,10 +22,11 @@ export const SignInBackgroundMockContainerEffect = ({ recordTableId, viewId, }: SignInBackgroundMockContainerEffectProps) => { - const { setAvailableTableColumns, setOnEntityCountChange, setTableColumns } = - useRecordTable({ - recordTableId, - }); + const { setAvailableTableColumns, setOnEntityCountChange } = useRecordTable({ + recordTableId, + }); + + const { setTableColumns } = useSetTableColumns(recordTableId); const { objectNameSingular } = useObjectNameSingularFromPlural({ objectNamePlural, diff --git a/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx b/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx index d37448de9937..733f026c091a 100644 --- a/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx +++ b/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx @@ -3,12 +3,20 @@ import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/ import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext'; import { mainContextStoreComponentInstanceIdState } from '@/context-store/states/mainContextStoreComponentInstanceId'; import { RecordIndexContainerGater } from '@/object-record/record-index/components/RecordIndexContainerGater'; +import { prefetchIsLoadedFamilyState } from '@/prefetch/states/prefetchIsLoadedFamilyState'; +import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; import { PageContainer } from '@/ui/layout/page/components/PageContainer'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; -import { isUndefined } from '@sniptt/guards'; +import { isNonEmptyString, isUndefined } from '@sniptt/guards'; import { useRecoilValue } from 'recoil'; export const RecordIndexPage = () => { + const prefetchIsLoaded = useRecoilValue( + prefetchIsLoadedFamilyState(PrefetchKey.AllViews), + ); + + console.log('prefetchIsLoaded', prefetchIsLoaded); + const mainContextStoreComponentInstanceId = useRecoilValue( mainContextStoreComponentInstanceIdState, ); @@ -25,7 +33,8 @@ export const RecordIndexPage = () => { if ( isUndefined(objectMetadataItem) || - isUndefined(contextStoreCurrentViewId) + !isNonEmptyString(contextStoreCurrentViewId) || + !prefetchIsLoaded ) { return null; } From 3f29d167d4d33272a3baa7948821d07b0f8a4cf9 Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Mon, 17 Feb 2025 22:15:20 +0100 Subject: [PATCH 04/14] Continue refactoring --- .../app/components/AppRouterProviders.tsx | 2 +- .../components/MainContextStoreProvider.tsx | 7 +- .../MainContextStoreProviderEffect.tsx | 3 + ...tVisitedViewForObjectMetadataNamePlural.ts | 11 +- .../ObjectMetadataItemsProvider.tsx | 1 + .../hooks/useRecordGroupReorder.ts | 5 +- .../record-group/hooks/useSetRecordGroup.ts | 59 +++--- ...ecordIndexLoadBaseOnContextStoreEffect.tsx | 12 +- .../hooks/useLoadRecordIndexStates.ts | 181 +++++++++++++----- .../record-table/hooks/useRecordTable.ts | 7 - .../record-table/hooks/useSetTableColumns.ts | 26 +-- .../record-table/hooks/useTableColumns.ts | 13 +- .../components/PrefetchRunQueriesEffect.tsx | 1 + .../prefetch/hooks/useLazyPrefetchData.ts | 30 --- .../SignInBackgroundMockContainerEffect.tsx | 4 +- .../hooks/useCreateViewFromCurrentView.ts | 23 ++- .../pages/object-record/RecordIndexPage.tsx | 2 - 17 files changed, 230 insertions(+), 157 deletions(-) delete mode 100644 packages/twenty-front/src/modules/prefetch/hooks/useLazyPrefetchData.ts diff --git a/packages/twenty-front/src/modules/app/components/AppRouterProviders.tsx b/packages/twenty-front/src/modules/app/components/AppRouterProviders.tsx index 37abf41e6347..f5c45a946c6e 100644 --- a/packages/twenty-front/src/modules/app/components/AppRouterProviders.tsx +++ b/packages/twenty-front/src/modules/app/components/AppRouterProviders.tsx @@ -59,10 +59,10 @@ export const AppRouterProviders = () => { + - diff --git a/packages/twenty-front/src/modules/context-store/components/MainContextStoreProvider.tsx b/packages/twenty-front/src/modules/context-store/components/MainContextStoreProvider.tsx index fc2051a65e53..ff72d401ec80 100644 --- a/packages/twenty-front/src/modules/context-store/components/MainContextStoreProvider.tsx +++ b/packages/twenty-front/src/modules/context-store/components/MainContextStoreProvider.tsx @@ -31,6 +31,7 @@ const getViewId = ( }; export const MainContextStoreProvider = () => { + console.log('Provider'); const { isMatchingLocation } = useIsMatchingLocation(); const isRecordIndexPage = isMatchingLocation(AppPath.RecordIndexPage); const isRecordShowPage = isMatchingLocation(AppPath.RecordShowPage); @@ -66,8 +67,6 @@ export const MainContextStoreProvider = () => { const viewId = getViewId(viewIdQueryParam, indexViewId, lastVisitedViewId); - const mainContextStoreComponentInstanceId = `${pageName}-${objectMetadataItem?.namePlural}-${viewId}`; - if ( !isDefined(pageName) || !isDefined(objectMetadataItem) || @@ -78,9 +77,7 @@ export const MainContextStoreProvider = () => { return ( diff --git a/packages/twenty-front/src/modules/context-store/components/MainContextStoreProviderEffect.tsx b/packages/twenty-front/src/modules/context-store/components/MainContextStoreProviderEffect.tsx index 01d63ff5c31f..90d29936d99a 100644 --- a/packages/twenty-front/src/modules/context-store/components/MainContextStoreProviderEffect.tsx +++ b/packages/twenty-front/src/modules/context-store/components/MainContextStoreProviderEffect.tsx @@ -45,6 +45,7 @@ export const MainContextStoreProviderEffect = ({ useEffect(() => { if (contextStoreCurrentObjectMetadataItem?.id !== objectMetadataItem.id) { + console.log('Setting object metadata item'); setContextStoreCurrentObjectMetadataItem(objectMetadataItem); } @@ -52,6 +53,7 @@ export const MainContextStoreProviderEffect = ({ mainContextStoreComponentInstanceIdToSet !== mainContextStoreComponentInstanceId ) { + console.log('Setting main context store component instance id'); setMainContextStoreComponentInstanceId( mainContextStoreComponentInstanceIdToSet, ); @@ -67,6 +69,7 @@ export const MainContextStoreProviderEffect = ({ }); if (contextStoreCurrentViewId !== viewId) { + console.log('Setting context store current view id'); setContextStoreCurrentViewId(viewId); } }, [ diff --git a/packages/twenty-front/src/modules/navigation/hooks/useSetLastVisitedViewForObjectMetadataNamePlural.ts b/packages/twenty-front/src/modules/navigation/hooks/useSetLastVisitedViewForObjectMetadataNamePlural.ts index 762c75b27052..ede4ec62b8d6 100644 --- a/packages/twenty-front/src/modules/navigation/hooks/useSetLastVisitedViewForObjectMetadataNamePlural.ts +++ b/packages/twenty-front/src/modules/navigation/hooks/useSetLastVisitedViewForObjectMetadataNamePlural.ts @@ -1,16 +1,11 @@ import { lastVisitedViewPerObjectMetadataItemState } from '@/navigation/states/lastVisitedViewPerObjectMetadataItemState'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; -import { useLazyPrefetchedData } from '@/prefetch/hooks/useLazyPrefetchData'; -import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; +import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState'; import { View } from '@/views/types/View'; import { useRecoilCallback } from 'recoil'; import { isDefined } from 'twenty-shared'; export const useSetLastVisitedViewForObjectMetadataNamePlural = () => { - const { records: views, findManyRecords } = useLazyPrefetchedData( - PrefetchKey.AllViews, - ); - const setLastVisitedViewForObjectMetadataNamePlural = useRecoilCallback( ({ set, snapshot }) => async ({ @@ -20,7 +15,7 @@ export const useSetLastVisitedViewForObjectMetadataNamePlural = () => { objectNamePlural: string; viewId: string; }) => { - await findManyRecords(); + const views = snapshot.getLoadable(prefetchViewsState).getValue(); const view = views.find((view: View) => view.id === viewId); @@ -54,7 +49,7 @@ export const useSetLastVisitedViewForObjectMetadataNamePlural = () => { }); } }, - [findManyRecords, views], + [], ); return { diff --git a/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsProvider.tsx b/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsProvider.tsx index d516f3ecf3dc..2d83ec61868e 100644 --- a/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsProvider.tsx +++ b/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsProvider.tsx @@ -11,6 +11,7 @@ import { UserOrMetadataLoader } from '~/loading/components/UserOrMetadataLoader' export const ObjectMetadataItemsProvider = ({ children, }: React.PropsWithChildren) => { + console.log('ObjectMetadataItemsProvider'); const objectMetadataItems = useRecoilValue(objectMetadataItemsState); const shouldDisplayChildren = objectMetadataItems.length > 0; diff --git a/packages/twenty-front/src/modules/object-record/record-group/hooks/useRecordGroupReorder.ts b/packages/twenty-front/src/modules/object-record/record-group/hooks/useRecordGroupReorder.ts index e7d124118113..3aeb93d34ed8 100644 --- a/packages/twenty-front/src/modules/object-record/record-group/hooks/useRecordGroupReorder.ts +++ b/packages/twenty-front/src/modules/object-record/record-group/hooks/useRecordGroupReorder.ts @@ -23,7 +23,7 @@ export const useRecordGroupReorder = ({ viewBarId, viewType, }: UseRecordGroupHandlersParams) => { - const setRecordGroup = useSetRecordGroup(viewBarId); + const setRecordGroup = useSetRecordGroup(); const visibleRecordGroupIdsFamilySelector = useRecoilComponentCallbackStateV2( visibleRecordGroupIdsComponentFamilySelector, @@ -78,7 +78,7 @@ export const useRecordGroupReorder = ({ ]; }, []); - setRecordGroup(updatedRecordGroups); + setRecordGroup(updatedRecordGroups, viewBarId); saveViewGroups( mapRecordGroupDefinitionsToViewGroups(updatedRecordGroups), ); @@ -86,6 +86,7 @@ export const useRecordGroupReorder = ({ [ saveViewGroups, setRecordGroup, + viewBarId, viewType, visibleRecordGroupIdsFamilySelector, ], diff --git a/packages/twenty-front/src/modules/object-record/record-group/hooks/useSetRecordGroup.ts b/packages/twenty-front/src/modules/object-record/record-group/hooks/useSetRecordGroup.ts index 490b65b4abd8..fe4c12d0924b 100644 --- a/packages/twenty-front/src/modules/object-record/record-group/hooks/useSetRecordGroup.ts +++ b/packages/twenty-front/src/modules/object-record/record-group/hooks/useSetRecordGroup.ts @@ -1,32 +1,33 @@ -import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow'; +import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState'; import { recordGroupDefinitionFamilyState } from '@/object-record/record-group/states/recordGroupDefinitionFamilyState'; import { recordGroupFieldMetadataComponentState } from '@/object-record/record-group/states/recordGroupFieldMetadataComponentState'; import { recordGroupIdsComponentState } from '@/object-record/record-group/states/recordGroupIdsComponentState'; import { RecordGroupDefinition } from '@/object-record/record-group/types/RecordGroupDefinition'; -import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue'; import { useRecoilCallback } from 'recoil'; import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; -export const useSetRecordGroup = (viewId?: string) => { - const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow(); - - const recordIndexRecordGroupIdsState = useRecoilComponentCallbackStateV2( - recordGroupIdsComponentState, - viewId, - ); - - const recordGroupFieldMetadataState = useRecoilComponentCallbackStateV2( - recordGroupFieldMetadataComponentState, - viewId, - ); - +export const useSetRecordGroup = () => { return useRecoilCallback( ({ snapshot, set }) => - (recordGroups: RecordGroupDefinition[]) => { + (recordGroups: RecordGroupDefinition[], recordIndexId: string) => { + const objectMetadataItem = snapshot + .getLoadable( + contextStoreCurrentObjectMetadataItemComponentState.atomFamily({ + instanceId: 'main-context-store', + }), + ) + .getValue(); + + if (!objectMetadataItem) { + return; + } + const currentRecordGroupIds = getSnapshotValue( snapshot, - recordIndexRecordGroupIdsState, + recordGroupIdsComponentState.atomFamily({ + instanceId: recordIndexId, + }), ); const fieldMetadataId = recordGroups?.[0]?.fieldMetadataId; const fieldMetadata = fieldMetadataId @@ -36,12 +37,19 @@ export const useSetRecordGroup = (viewId?: string) => { : undefined; const currentFieldMetadata = getSnapshotValue( snapshot, - recordGroupFieldMetadataState, + recordGroupFieldMetadataComponentState.atomFamily({ + instanceId: recordIndexId, + }), ); // Set the field metadata linked to the record groups if (!isDeeplyEqual(fieldMetadata, currentFieldMetadata)) { - set(recordGroupFieldMetadataState, fieldMetadata); + set( + recordGroupFieldMetadataComponentState.atomFamily({ + instanceId: recordIndexId, + }), + fieldMetadata, + ); } // Set the record groups by id @@ -75,12 +83,13 @@ export const useSetRecordGroup = (viewId?: string) => { } // Set the record group ids - set(recordIndexRecordGroupIdsState, recordGroupIds); + set( + recordGroupIdsComponentState.atomFamily({ + instanceId: recordIndexId, + }), + recordGroupIds, + ); }, - [ - objectMetadataItem.fields, - recordGroupFieldMetadataState, - recordIndexRecordGroupIdsState, - ], + [], ); }; diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexLoadBaseOnContextStoreEffect.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexLoadBaseOnContextStoreEffect.tsx index e4cf82dc20b3..cb1d65ea7f5e 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexLoadBaseOnContextStoreEffect.tsx +++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexLoadBaseOnContextStoreEffect.tsx @@ -1,12 +1,20 @@ +import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState'; import { useLoadRecordIndexStates } from '@/object-record/record-index/hooks/useLoadRecordIndexStates'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useEffect } from 'react'; +import { isDefined } from 'twenty-shared'; export const RecordIndexLoadBaseOnContextStoreEffect = () => { const { loadRecordIndexStates } = useLoadRecordIndexStates(); + const contextStoreCurrentViewId = useRecoilComponentValueV2( + contextStoreCurrentViewIdComponentState, + ); useEffect(() => { - loadRecordIndexStates(); - }, [loadRecordIndexStates]); + if (isDefined(contextStoreCurrentViewId)) { + loadRecordIndexStates(); + } + }, [contextStoreCurrentViewId, loadRecordIndexStates]); return <>; }; diff --git a/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexStates.ts b/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexStates.ts index 7bcb8fd992b6..918cd8f0ce6e 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexStates.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexStates.ts @@ -1,8 +1,11 @@ -import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow'; +import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState'; import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState'; import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; -import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata'; -import { useFilterableFieldMetadataItems } from '@/object-record/record-filter/hooks/useFilterableFieldMetadataItems'; +import { availableFieldMetadataItemsForFilterFamilySelector } from '@/object-metadata/states/availableFieldMetadataItemsForFilterFamilySelector'; +import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; +import { formatFieldMetadataItemAsColumnDefinition } from '@/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition'; +import { formatFieldMetadataItemsAsSortDefinitions } from '@/object-metadata/utils/formatFieldMetadataItemsAsSortDefinitions'; +import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata'; import { useSetRecordGroup } from '@/object-record/record-group/hooks/useSetRecordGroup'; import { recordIndexFieldDefinitionsState } from '@/object-record/record-index/states/recordIndexFieldDefinitionsState'; import { recordIndexFiltersState } from '@/object-record/record-index/states/recordIndexFiltersState'; @@ -12,12 +15,15 @@ import { recordIndexKanbanFieldMetadataIdState } from '@/object-record/record-in import { recordIndexSortsState } from '@/object-record/record-index/states/recordIndexSortsState'; import { recordIndexViewFilterGroupsState } from '@/object-record/record-index/states/recordIndexViewFilterGroupsState'; import { recordIndexViewTypeState } from '@/object-record/record-index/states/recordIndexViewTypeState'; -import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable'; import { useSetTableColumns } from '@/object-record/record-table/hooks/useSetTableColumns'; import { viewFieldAggregateOperationState } from '@/object-record/record-table/record-table-footer/states/viewFieldAggregateOperationState'; +import { tableFiltersComponentState } from '@/object-record/record-table/states/tableFiltersComponentState'; +import { tableSortsComponentState } from '@/object-record/record-table/states/tableSortsComponentState'; +import { tableViewFilterGroupsComponentState } from '@/object-record/record-table/states/tableViewFilterGroupsComponentState'; +import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition'; import { convertAggregateOperationToExtendedAggregateOperation } from '@/object-record/utils/convertAggregateOperationToExtendedAggregateOperation'; +import { filterAvailableTableColumns } from '@/object-record/utils/filterAvailableTableColumns'; import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState'; -import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; import { ViewField } from '@/views/types/ViewField'; import { ViewGroup } from '@/views/types/ViewGroup'; @@ -31,24 +37,13 @@ import { isDefined } from 'twenty-shared'; import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; export const useLoadRecordIndexStates = () => { - const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow(); - const contextStoreCurrentViewId = useRecoilComponentValueV2( - contextStoreCurrentViewIdComponentState, - ); - const setContextStoreTargetedRecordsRuleComponentState = useSetRecoilComponentStateV2(contextStoreTargetedRecordsRuleComponentState); - const recordIndexId = `${objectMetadataItem.namePlural}-${contextStoreCurrentViewId}`; - const setRecordIndexViewFilterGroups = useSetRecoilState( recordIndexViewFilterGroupsState, ); - const { filterableFieldMetadataItems } = useFilterableFieldMetadataItems( - objectMetadataItem?.id ?? '', - ); - const setRecordIndexFilters = useSetRecoilState(recordIndexFiltersState); const setRecordIndexSorts = useSetRecoilState(recordIndexSortsState); const setRecordIndexIsCompactModeActive = useSetRecoilState( @@ -61,28 +56,66 @@ export const useLoadRecordIndexStates = () => { const setRecordIndexViewKanbanAggregateOperationState = useSetRecoilState( recordIndexKanbanAggregateOperationState, ); - const setRecordGroup = useSetRecordGroup(recordIndexId); - const { setTableViewFilterGroups, setTableFilters, setTableSorts } = - useRecordTable({ - recordTableId: recordIndexId, - }); - - const { setTableColumns } = useSetTableColumns(recordIndexId); + const setRecordGroup = useSetRecordGroup(); - const { columnDefinitions, sortDefinitions } = - useColumnDefinitionsFromFieldMetadata(objectMetadataItem); + const { setTableColumns } = useSetTableColumns(); const onViewFieldsChange = useRecoilCallback( ({ set, snapshot }) => - (viewFields: ViewField[]) => { - if (!objectMetadataItem) { - return; - } + ( + viewFields: ViewField[], + objectMetadataItem: ObjectMetadataItem, + recordIndexId: string, + ) => { + const activeFieldMetadataItems = objectMetadataItem.fields.filter( + ({ isActive, isSystem }) => isActive && !isSystem, + ); + + const filterableFieldMetadataItems = snapshot + .getLoadable( + availableFieldMetadataItemsForFilterFamilySelector({ + objectMetadataItemId: objectMetadataItem.id, + }), + ) + .getValue(); + + const sortDefinitions = formatFieldMetadataItemsAsSortDefinitions({ + fields: activeFieldMetadataItems, + }); + + const columnDefinitions: ColumnDefinition[] = + activeFieldMetadataItems + .map((field, index) => + formatFieldMetadataItemAsColumnDefinition({ + position: index, + field, + objectMetadataItem, + }), + ) + .filter(filterAvailableTableColumns) + .map((column) => { + const existsInFilterDefinitions = + filterableFieldMetadataItems.some( + (fieldMetadataItem) => + fieldMetadataItem.id === column.fieldMetadataId, + ); + const existsInSortDefinitions = sortDefinitions.some( + (sort) => sort.fieldMetadataId === column.fieldMetadataId, + ); + return { + ...column, + isFilterable: existsInFilterDefinitions, + isSortable: existsInSortDefinitions, + }; + }); + const newFieldDefinitions = mapViewFieldsToColumnDefinitions({ viewFields, columnDefinitions, }); - setTableColumns(newFieldDefinitions); + + setTableColumns(newFieldDefinitions, recordIndexId); + const existingRecordIndexFieldDefinitions = snapshot .getLoadable(recordIndexFieldDefinitionsState) .getValue(); @@ -94,10 +127,12 @@ export const useLoadRecordIndexStates = () => { ) { set(recordIndexFieldDefinitionsState, newFieldDefinitions); } + for (const viewField of viewFields) { const viewFieldMetadataType = objectMetadataItem.fields?.find( (field) => field.id === viewField.fieldMetadataId, )?.type; + const aggregateOperationForViewField = snapshot .getLoadable( viewFieldAggregateOperationState({ @@ -113,6 +148,7 @@ export const useLoadRecordIndexStates = () => { viewFieldMetadataType, ) : viewField.aggregateOperation; + if ( aggregateOperationForViewField !== convertedViewFieldAggregateOperation @@ -126,42 +162,76 @@ export const useLoadRecordIndexStates = () => { } } }, - [], + [setTableColumns], ); const onViewGroupsChange = useCallback( - (viewGroups: ViewGroup[]) => { - if (!objectMetadataItem) { - return; - } - + ( + viewGroups: ViewGroup[], + objectMetadataItem: ObjectMetadataItem, + recordIndexId: string, + ) => { const newGroupDefinitions = mapViewGroupsToRecordGroupDefinitions({ objectMetadataItem, viewGroups, }); - setRecordGroup(newGroupDefinitions); + setRecordGroup(newGroupDefinitions, recordIndexId); }, - [objectMetadataItem, setRecordGroup], + [setRecordGroup], ); const loadRecordIndexStates = useRecoilCallback( - ({ snapshot }) => + ({ snapshot, set }) => async () => { + const objectMetadataItem = snapshot + .getLoadable( + contextStoreCurrentObjectMetadataItemComponentState.atomFamily({ + instanceId: 'main-context-store', + }), + ) + .getValue(); + + const contextStoreCurrentViewId = snapshot + .getLoadable( + contextStoreCurrentViewIdComponentState.atomFamily({ + instanceId: 'main-context-store', + }), + ) + .getValue(); + const views = snapshot.getLoadable(prefetchViewsState).getValue(); const view = views.find( (view) => view.id === contextStoreCurrentViewId, ); - if (!view) { + if (!view || !objectMetadataItem) { return; } - onViewFieldsChange(view.viewFields); - onViewGroupsChange(view.viewGroups); - setTableViewFilterGroups(view.viewFilterGroups ?? []); - setTableFilters( + const recordIndexId = `${objectMetadataItem.namePlural}-${view.id}`; + + const filterableFieldMetadataItems = snapshot + .getLoadable( + availableFieldMetadataItemsForFilterFamilySelector({ + objectMetadataItemId: objectMetadataItem.id, + }), + ) + .getValue(); + + onViewFieldsChange(view.viewFields, objectMetadataItem, recordIndexId); + onViewGroupsChange(view.viewGroups, objectMetadataItem, recordIndexId); + set( + tableViewFilterGroupsComponentState.atomFamily({ + instanceId: recordIndexId, + }), + view.viewFilterGroups ?? [], + ); + set( + tableFiltersComponentState.atomFamily({ + instanceId: recordIndexId, + }), mapViewFiltersToFilters( view.viewFilters, filterableFieldMetadataItems, @@ -181,7 +251,21 @@ export const useLoadRecordIndexStates = () => { filterableFieldMetadataItems, ), })); - setTableSorts(mapViewSortsToSorts(view.viewSorts, sortDefinitions)); + + const activeFieldMetadataItems = objectMetadataItem.fields.filter( + ({ isActive, isSystem }) => isActive && !isSystem, + ); + + const sortDefinitions = formatFieldMetadataItemsAsSortDefinitions({ + fields: activeFieldMetadataItems, + }); + + set( + tableSortsComponentState.atomFamily({ + instanceId: recordIndexId, + }), + mapViewSortsToSorts(view.viewSorts, sortDefinitions), + ); setRecordIndexSorts( mapViewSortsToSorts(view.viewSorts, sortDefinitions), ); @@ -206,9 +290,6 @@ export const useLoadRecordIndexStates = () => { setRecordIndexIsCompactModeActive(view.isCompact); }, [ - contextStoreCurrentViewId, - filterableFieldMetadataItems, - objectMetadataItem.fields, onViewFieldsChange, onViewGroupsChange, setContextStoreTargetedRecordsRuleComponentState, @@ -219,10 +300,6 @@ export const useLoadRecordIndexStates = () => { setRecordIndexViewKanbanAggregateOperationState, setRecordIndexViewKanbanFieldMetadataIdState, setRecordIndexViewType, - setTableFilters, - setTableSorts, - setTableViewFilterGroups, - sortDefinitions, ], ); diff --git a/packages/twenty-front/src/modules/object-record/record-table/hooks/useRecordTable.ts b/packages/twenty-front/src/modules/object-record/record-table/hooks/useRecordTable.ts index 2bc033f33077..d0d6784ea033 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/hooks/useRecordTable.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/hooks/useRecordTable.ts @@ -25,7 +25,6 @@ import { onToggleColumnSortComponentState } from '@/object-record/record-table/s import { tableFiltersComponentState } from '@/object-record/record-table/states/tableFiltersComponentState'; import { tableLastRowVisibleComponentState } from '@/object-record/record-table/states/tableLastRowVisibleComponentState'; import { tableSortsComponentState } from '@/object-record/record-table/states/tableSortsComponentState'; -import { tableViewFilterGroupsComponentState } from '@/object-record/record-table/states/tableViewFilterGroupsComponentState'; import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow'; import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; @@ -73,11 +72,6 @@ export const useRecordTable = (props?: useRecordTableProps) => { recordTableId, ); - const setTableViewFilterGroups = useSetRecoilComponentStateV2( - tableViewFilterGroupsComponentState, - recordTableId, - ); - const setTableFilters = useSetRecoilComponentStateV2( tableFiltersComponentState, recordTableId, @@ -236,7 +230,6 @@ export const useRecordTable = (props?: useRecordTableProps) => { return { onColumnsChange, setAvailableTableColumns, - setTableViewFilterGroups, setTableFilters, setTableSorts, setOnEntityCountChange, diff --git a/packages/twenty-front/src/modules/object-record/record-table/hooks/useSetTableColumns.ts b/packages/twenty-front/src/modules/object-record/record-table/hooks/useSetTableColumns.ts index 6cd9c91114c1..5739235d85d7 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/hooks/useSetTableColumns.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/hooks/useSetTableColumns.ts @@ -1,28 +1,32 @@ import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata'; import { tableColumnsComponentState } from '@/object-record/record-table/states/tableColumnsComponentState'; import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition'; -import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue'; import { useRecoilCallback } from 'recoil'; import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; -export const useSetTableColumns = (recordTableId?: string) => { - const tableColumnsState = useRecoilComponentCallbackStateV2( - tableColumnsComponentState, - recordTableId, - ); - +export const useSetTableColumns = () => { const setTableColumns = useRecoilCallback( ({ snapshot, set }) => - (columns: ColumnDefinition[]) => { - const tableColumns = getSnapshotValue(snapshot, tableColumnsState); + (columns: ColumnDefinition[], recordTableId: string) => { + const tableColumns = getSnapshotValue( + snapshot, + tableColumnsComponentState.atomFamily({ + instanceId: recordTableId, + }), + ); if (isDeeplyEqual(tableColumns, columns)) { return; } - set(tableColumnsState, columns); + set( + tableColumnsComponentState.atomFamily({ + instanceId: recordTableId, + }), + columns, + ); }, - [tableColumnsState], + [], ); return { setTableColumns }; diff --git a/packages/twenty-front/src/modules/object-record/record-table/hooks/useTableColumns.ts b/packages/twenty-front/src/modules/object-record/record-table/hooks/useTableColumns.ts index af756b49f53f..707429be0389 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/hooks/useTableColumns.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/hooks/useTableColumns.ts @@ -6,8 +6,10 @@ import { useMoveViewColumns } from '@/views/hooks/useMoveViewColumns'; import { useSetTableColumns } from '@/object-record/record-table/hooks/useSetTableColumns'; import { availableTableColumnsComponentState } from '@/object-record/record-table/states/availableTableColumnsComponentState'; +import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext'; import { visibleTableColumnsComponentSelector } from '@/object-record/record-table/states/selectors/visibleTableColumnsComponentSelector'; import { tableColumnsComponentState } from '@/object-record/record-table/states/tableColumnsComponentState'; +import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { ColumnDefinition } from '../types/ColumnDefinition'; @@ -20,7 +22,7 @@ export const useTableColumns = (props?: useRecordTableProps) => { recordTableId: props?.recordTableId, }); - const { setTableColumns } = useSetTableColumns(props?.recordTableId); + const { setTableColumns } = useSetTableColumns(); const availableTableColumns = useRecoilComponentValueV2( availableTableColumnsComponentState, @@ -38,13 +40,18 @@ export const useTableColumns = (props?: useRecordTableProps) => { const { handleColumnMove } = useMoveViewColumns(); + const instanceId = useAvailableComponentInstanceIdOrThrow( + RecordTableComponentInstanceContext, + props?.recordTableId, + ); + const handleColumnsChange = useCallback( async (columns: ColumnDefinition[]) => { - setTableColumns(columns); + setTableColumns(columns, instanceId); await onColumnsChange?.(columns); }, - [onColumnsChange, setTableColumns], + [setTableColumns, instanceId, onColumnsChange], ); const handleColumnVisibilityChange = useCallback( diff --git a/packages/twenty-front/src/modules/prefetch/components/PrefetchRunQueriesEffect.tsx b/packages/twenty-front/src/modules/prefetch/components/PrefetchRunQueriesEffect.tsx index 548fb1e20398..175c327083a4 100644 --- a/packages/twenty-front/src/modules/prefetch/components/PrefetchRunQueriesEffect.tsx +++ b/packages/twenty-front/src/modules/prefetch/components/PrefetchRunQueriesEffect.tsx @@ -16,6 +16,7 @@ import { isDefined } from 'twenty-shared'; import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; export const PrefetchRunQueriesEffect = () => { + console.log('PrefetchRunQueriesEffect'); const currentUser = useRecoilValue(currentUserState); const isWorkspaceSuspended = useIsWorkspaceActivationStatusSuspended(); diff --git a/packages/twenty-front/src/modules/prefetch/hooks/useLazyPrefetchData.ts b/packages/twenty-front/src/modules/prefetch/hooks/useLazyPrefetchData.ts deleted file mode 100644 index 3576b4fe4e8b..000000000000 --- a/packages/twenty-front/src/modules/prefetch/hooks/useLazyPrefetchData.ts +++ /dev/null @@ -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 = ( - prefetchKey: PrefetchKey, - filter?: RecordGqlOperationFilter, -) => { - const { operationSignatureFactory, objectNameSingular } = - PREFETCH_CONFIG[prefetchKey]; - - const { objectMetadataItem } = useObjectMetadataItem({ - objectNameSingular, - }); - - const recordGqlFields = - operationSignatureFactory({ objectMetadataItem }).fields ?? filter; - const { records, findManyRecords } = useLazyFindManyRecords({ - objectNameSingular: objectNameSingular, - recordGqlFields, - }); - - return { - findManyRecords, - records, - }; -}; diff --git a/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainerEffect.tsx b/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainerEffect.tsx index 8c5c81b46235..63ce37579dc7 100644 --- a/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainerEffect.tsx +++ b/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainerEffect.tsx @@ -26,7 +26,7 @@ export const SignInBackgroundMockContainerEffect = ({ recordTableId, }); - const { setTableColumns } = useSetTableColumns(recordTableId); + const { setTableColumns } = useSetTableColumns(); const { objectNameSingular } = useObjectNameSingularFromPlural({ objectNamePlural, @@ -57,6 +57,7 @@ export const SignInBackgroundMockContainerEffect = ({ viewFields: SIGN_IN_BACKGROUND_MOCK_VIEW_FIELDS, columnDefinitions: SIGN_IN_BACKGROUND_MOCK_COLUMN_DEFINITIONS, }), + recordTableId, ); }, [ setViewObjectMetadataId, @@ -65,6 +66,7 @@ export const SignInBackgroundMockContainerEffect = ({ objectMetadataItem, setAvailableTableColumns, setTableColumns, + recordTableId, ]); useEffect(() => { diff --git a/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts b/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts index 874de3fc8dff..38488bd92106 100644 --- a/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts +++ b/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts @@ -1,6 +1,7 @@ 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 { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; @@ -34,6 +35,10 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => { viewBarComponentId, ); + const { findManyRecords: findManyViews } = useLazyFindManyRecords({ + objectNameSingular: CoreObjectNameSingular.View, + }); + const { getViewFromCache } = useGetViewFromCache(); const { createOneRecord } = useCreateOneRecord({ @@ -169,21 +174,23 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => { ); } + await findManyViews(); set(isPersistingViewFieldsCallbackState, false); }, [ - objectMetadataItem, - createViewSortRecords, - createViewFilterRecords, - createOneRecord, - createViewFieldRecords, - getViewSortsCombined, - getViewFiltersCombined, - getViewFilterGroupsCombined, currentViewIdCallbackState, getViewFromCache, isPersistingViewFieldsCallbackState, + createOneRecord, + createViewFieldRecords, + findManyViews, + objectMetadataItem?.fields, createViewGroupRecords, + getViewFilterGroupsCombined, + getViewFiltersCombined, + getViewSortsCombined, + createViewSortRecords, + createViewFilterRecords, createViewFilterGroupRecords, ], ); diff --git a/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx b/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx index 733f026c091a..437dde54bb91 100644 --- a/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx +++ b/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx @@ -15,8 +15,6 @@ export const RecordIndexPage = () => { prefetchIsLoadedFamilyState(PrefetchKey.AllViews), ); - console.log('prefetchIsLoaded', prefetchIsLoaded); - const mainContextStoreComponentInstanceId = useRecoilValue( mainContextStoreComponentInstanceIdState, ); From 355035a30cbf49a226f1f2abb663d7cbaf574231 Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Tue, 18 Feb 2025 00:11:29 +0100 Subject: [PATCH 05/14] Fix --- .../components/MainContextStoreProvider.tsx | 9 +-- ...seContextStoreObjectMetadataItemOrThrow.ts | 2 +- .../modules/favorites/hooks/useFavorites.ts | 12 ++-- .../favorites/hooks/useFavoritesByFolder.ts | 7 +- .../favorites/hooks/useFavoritesMetadata.ts | 5 -- .../favorites/hooks/useSortedFavorites.ts | 15 ++-- .../favorites/hooks/useWorkspaceFavorites.ts | 13 ++-- .../favoriteViewsWithMinimalDataSelector.ts | 18 +++++ .../getObjectMetadataLabelPluralFromViewId.ts | 14 +--- .../modules/favorites/utils/sortFavorites.ts | 15 ++-- .../hooks/useDefaultHomePagePath.ts | 12 ++-- ...igationDrawerItemForObjectMetadataItem.tsx | 18 ++--- ...ecordIndexLoadBaseOnContextStoreEffect.tsx | 23 ++++++- .../hooks/useLoadRecordIndexStates.ts | 7 ++ .../RecordDetailRelationSection.tsx | 16 ++--- .../components/PrefetchDataProvider.tsx | 6 +- ...x => PrefetchRunFavoriteQueriesEffect.tsx} | 40 +---------- .../components/PrefetchRunViewQueryEffect.tsx | 68 +++++++++++++++++++ .../prefetch/constants/PrefetchConfig.ts | 5 -- .../prefetch/hooks/useIsPrefetchLoading.ts | 7 +- .../prefetch/hooks/usePrefetchedData.ts | 1 + .../prefetchViewFromViewIdFamilySelector.ts | 14 ++-- .../prefetchViewLengthFamilySelector.ts | 10 +++ .../src/modules/prefetch/types/PrefetchKey.ts | 1 - .../SettingsObjectFieldItemTableRow.tsx | 11 ++- .../SignInBackgroundMockContainer.tsx | 17 +++-- .../components/ViewBarRecordFilterEffect.tsx | 24 +++---- ...urrentViewFiltersToCurrentRecordFilters.ts | 41 ++++++----- .../src/modules/views/hooks/useChangeView.ts | 1 + .../hooks/useCreateViewFromCurrentView.ts | 2 + .../hooks/useGetCombinedViewFilterGroups.ts | 15 ++-- .../views/hooks/useGetCombinedViewFilters.ts | 15 ++-- .../views/hooks/useGetCombinedViewSorts.ts | 15 ++-- .../modules/views/hooks/useGetCurrentView.ts | 49 +++++++------ .../views/hooks/useGetCurrentViewOnly.ts | 15 ++-- ...useViewOrDefaultViewFromPrefetchedViews.ts | 27 ++++---- .../components/ViewPickerContentEffect.tsx | 12 +++- .../ViewPickerFavoriteFoldersDropdown.tsx | 12 ++-- .../components/ViewPickerListContent.tsx | 1 + .../pages/object-record/RecordIndexPage.tsx | 21 ++---- .../decorators/PrefetchLoadedDecorator.tsx | 4 -- .../decorators/PrefetchLoadingDecorator.tsx | 6 +- 42 files changed, 349 insertions(+), 277 deletions(-) create mode 100644 packages/twenty-front/src/modules/favorites/states/selectors/favoriteViewsWithMinimalDataSelector.ts rename packages/twenty-front/src/modules/prefetch/components/{PrefetchRunQueriesEffect.tsx => PrefetchRunFavoriteQueriesEffect.tsx} (65%) create mode 100644 packages/twenty-front/src/modules/prefetch/components/PrefetchRunViewQueryEffect.tsx create mode 100644 packages/twenty-front/src/modules/prefetch/states/selector/prefetchViewLengthFamilySelector.ts diff --git a/packages/twenty-front/src/modules/context-store/components/MainContextStoreProvider.tsx b/packages/twenty-front/src/modules/context-store/components/MainContextStoreProvider.tsx index ff72d401ec80..bbd3c8b0ddb6 100644 --- a/packages/twenty-front/src/modules/context-store/components/MainContextStoreProvider.tsx +++ b/packages/twenty-front/src/modules/context-store/components/MainContextStoreProvider.tsx @@ -31,7 +31,6 @@ const getViewId = ( }; export const MainContextStoreProvider = () => { - console.log('Provider'); const { isMatchingLocation } = useIsMatchingLocation(); const isRecordIndexPage = isMatchingLocation(AppPath.RecordIndexPage); const isRecordShowPage = isMatchingLocation(AppPath.RecordShowPage); @@ -49,9 +48,11 @@ export const MainContextStoreProvider = () => { const objectMetadataItems = useRecoilValue(objectMetadataItemsState); - const objectMetadataItem = objectMetadataItems.find( - (objectMetadataItem) => objectMetadataItem.namePlural === objectNamePlural, - ); + const objectMetadataItem = + objectMetadataItems.find( + (objectMetadataItem) => + objectMetadataItem.namePlural === objectNamePlural, + ) ?? objectMetadataItems[0]; const { getLastVisitedViewIdFromObjectNamePlural } = useLastVisitedView(); diff --git a/packages/twenty-front/src/modules/context-store/hooks/useContextStoreObjectMetadataItemOrThrow.ts b/packages/twenty-front/src/modules/context-store/hooks/useContextStoreObjectMetadataItemOrThrow.ts index ffab8b348300..5e09defb6937 100644 --- a/packages/twenty-front/src/modules/context-store/hooks/useContextStoreObjectMetadataItemOrThrow.ts +++ b/packages/twenty-front/src/modules/context-store/hooks/useContextStoreObjectMetadataItemOrThrow.ts @@ -10,7 +10,7 @@ export const useContextStoreObjectMetadataItemOrThrow = ( ); if (!objectMetadataItem) { - throw new Error('Object metadata item is not se in context store'); + throw new Error('Object metadata item is not set in context store'); } return { objectMetadataItem }; diff --git a/packages/twenty-front/src/modules/favorites/hooks/useFavorites.ts b/packages/twenty-front/src/modules/favorites/hooks/useFavorites.ts index e528ee5e8dc0..6662fd71e671 100644 --- a/packages/twenty-front/src/modules/favorites/hooks/useFavorites.ts +++ b/packages/twenty-front/src/modules/favorites/hooks/useFavorites.ts @@ -1,11 +1,9 @@ +import { favoriteViewsWithMinimalDataSelector } from '@/favorites/states/selectors/favoriteViewsWithMinimalDataSelector'; import { sortFavorites } from '@/favorites/utils/sortFavorites'; import { useGetObjectRecordIdentifierByNameSingular } from '@/object-metadata/hooks/useGetObjectRecordIdentifierByNameSingular'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; -import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData'; -import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; -import { View } from '@/views/types/View'; import { useMemo } from 'react'; import { useRecoilValue } from 'recoil'; import { FieldMetadataType } from '~/generated-metadata/graphql'; @@ -13,7 +11,9 @@ import { usePrefetchedFavoritesData } from './usePrefetchedFavoritesData'; export const useFavorites = () => { const { favorites } = usePrefetchedFavoritesData(); - const { records: views } = usePrefetchedData(PrefetchKey.AllViews); + const favoriteViewsWithMinimalData = useRecoilValue( + favoriteViewsWithMinimalDataSelector, + ); const objectMetadataItems = useRecoilValue(objectMetadataItemsState); const { objectMetadataItem: favoriteObjectMetadataItem } = useObjectMetadataItem({ @@ -40,14 +40,14 @@ export const useFavorites = () => { favoriteRelationFieldMetadataItems, getObjectRecordIdentifierByNameSingular, true, - views, + favoriteViewsWithMinimalData, objectMetadataItems, ), [ favorites, favoriteRelationFieldMetadataItems, getObjectRecordIdentifierByNameSingular, - views, + favoriteViewsWithMinimalData, objectMetadataItems, ], ); diff --git a/packages/twenty-front/src/modules/favorites/hooks/useFavoritesByFolder.ts b/packages/twenty-front/src/modules/favorites/hooks/useFavoritesByFolder.ts index 2747c1e1f14c..4f9977f1f31d 100644 --- a/packages/twenty-front/src/modules/favorites/hooks/useFavoritesByFolder.ts +++ b/packages/twenty-front/src/modules/favorites/hooks/useFavoritesByFolder.ts @@ -1,4 +1,6 @@ import { sortFavorites } from '@/favorites/utils/sortFavorites'; +import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState'; +import { useRecoilValue } from 'recoil'; import { useFavoritesMetadata } from './useFavoritesMetadata'; import { usePrefetchedFavoritesData } from './usePrefetchedFavoritesData'; import { usePrefetchedFavoritesFoldersData } from './usePrefetchedFavoritesFoldersData'; @@ -7,12 +9,13 @@ export const useFavoritesByFolder = () => { const { favorites } = usePrefetchedFavoritesData(); const { favoriteFolders } = usePrefetchedFavoritesFoldersData(); const { - views, objectMetadataItems, getObjectRecordIdentifierByNameSingular, favoriteRelationFields, } = useFavoritesMetadata(); + const prefetchViews = useRecoilValue(prefetchViewsState); + const favoritesByFolder = favoriteFolders.map((folder) => ({ folderId: folder.id, folderName: folder.name, @@ -21,7 +24,7 @@ export const useFavoritesByFolder = () => { favoriteRelationFields, getObjectRecordIdentifierByNameSingular, true, - views, + prefetchViews, objectMetadataItems, ), })); diff --git a/packages/twenty-front/src/modules/favorites/hooks/useFavoritesMetadata.ts b/packages/twenty-front/src/modules/favorites/hooks/useFavoritesMetadata.ts index 04780f975295..e6c4e9b29b7b 100644 --- a/packages/twenty-front/src/modules/favorites/hooks/useFavoritesMetadata.ts +++ b/packages/twenty-front/src/modules/favorites/hooks/useFavoritesMetadata.ts @@ -2,14 +2,10 @@ import { useGetObjectRecordIdentifierByNameSingular } from '@/object-metadata/ho import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; -import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData'; -import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; -import { View } from '@/views/types/View'; import { useRecoilValue } from 'recoil'; import { FieldMetadataType } from '~/generated-metadata/graphql'; export const useFavoritesMetadata = () => { - const { records: views } = usePrefetchedData(PrefetchKey.AllViews); const objectMetadataItems = useRecoilValue(objectMetadataItemsState); const getObjectRecordIdentifierByNameSingular = useGetObjectRecordIdentifierByNameSingular(); @@ -27,7 +23,6 @@ export const useFavoritesMetadata = () => { ); return { - views, objectMetadataItems, getObjectRecordIdentifierByNameSingular, favoriteRelationFields, diff --git a/packages/twenty-front/src/modules/favorites/hooks/useSortedFavorites.ts b/packages/twenty-front/src/modules/favorites/hooks/useSortedFavorites.ts index 3ec57bf5d5df..582a2abfc1b2 100644 --- a/packages/twenty-front/src/modules/favorites/hooks/useSortedFavorites.ts +++ b/packages/twenty-front/src/modules/favorites/hooks/useSortedFavorites.ts @@ -1,32 +1,35 @@ import { sortFavorites } from '@/favorites/utils/sortFavorites'; +import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState'; import { useMemo } from 'react'; +import { useRecoilValue } from 'recoil'; import { useFavoritesMetadata } from './useFavoritesMetadata'; import { usePrefetchedFavoritesData } from './usePrefetchedFavoritesData'; export const useSortedFavorites = () => { const { favorites, workspaceFavorites } = usePrefetchedFavoritesData(); const { - views, objectMetadataItems, getObjectRecordIdentifierByNameSingular, favoriteRelationFields, } = useFavoritesMetadata(); + const prefetchViews = useRecoilValue(prefetchViewsState); + const favoritesSorted = useMemo(() => { return sortFavorites( favorites, favoriteRelationFields, getObjectRecordIdentifierByNameSingular, true, - views, + prefetchViews, objectMetadataItems, ); }, [ favoriteRelationFields, favorites, getObjectRecordIdentifierByNameSingular, - views, objectMetadataItems, + prefetchViews, ]); const workspaceFavoritesSorted = useMemo(() => { @@ -35,14 +38,14 @@ export const useSortedFavorites = () => { favoriteRelationFields, getObjectRecordIdentifierByNameSingular, false, - views, + prefetchViews, objectMetadataItems, ); }, [ + workspaceFavorites, favoriteRelationFields, getObjectRecordIdentifierByNameSingular, - workspaceFavorites, - views, + prefetchViews, objectMetadataItems, ]); diff --git a/packages/twenty-front/src/modules/favorites/hooks/useWorkspaceFavorites.ts b/packages/twenty-front/src/modules/favorites/hooks/useWorkspaceFavorites.ts index 04d52cb229e9..d41a6ca3215f 100644 --- a/packages/twenty-front/src/modules/favorites/hooks/useWorkspaceFavorites.ts +++ b/packages/twenty-front/src/modules/favorites/hooks/useWorkspaceFavorites.ts @@ -4,9 +4,7 @@ import { useGetObjectRecordIdentifierByNameSingular } from '@/object-metadata/ho import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; -import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData'; -import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; -import { View } from '@/views/types/View'; +import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState'; import { useMemo } from 'react'; import { useRecoilValue } from 'recoil'; import { FieldMetadataType } from '~/generated-metadata/graphql'; @@ -14,8 +12,7 @@ import { usePrefetchedFavoritesData } from './usePrefetchedFavoritesData'; export const useWorkspaceFavorites = () => { const { workspaceFavorites } = usePrefetchedFavoritesData(); - - const { records: views } = usePrefetchedData(PrefetchKey.AllViews); + const prefetchViews = useRecoilValue(prefetchViewsState); const objectMetadataItems = useRecoilValue(objectMetadataItemsState); const { objectMetadataItem: favoriteObjectMetadataItem } = useObjectMetadataItem({ @@ -42,14 +39,14 @@ export const useWorkspaceFavorites = () => { favoriteRelationFieldMetadataItems, getObjectRecordIdentifierByNameSingular, false, - views, + prefetchViews, objectMetadataItems, ), [ workspaceFavorites, favoriteRelationFieldMetadataItems, getObjectRecordIdentifierByNameSingular, - views, + prefetchViews, objectMetadataItems, ], ); @@ -59,7 +56,7 @@ export const useWorkspaceFavorites = () => { ); const favoriteViewObjectMetadataIds = new Set( - views.reduce((acc, view) => { + prefetchViews.reduce((acc, view) => { if (workspaceFavoriteIds.has(view.id)) { acc.push(view.objectMetadataId); } diff --git a/packages/twenty-front/src/modules/favorites/states/selectors/favoriteViewsWithMinimalDataSelector.ts b/packages/twenty-front/src/modules/favorites/states/selectors/favoriteViewsWithMinimalDataSelector.ts new file mode 100644 index 000000000000..f963a69fffda --- /dev/null +++ b/packages/twenty-front/src/modules/favorites/states/selectors/favoriteViewsWithMinimalDataSelector.ts @@ -0,0 +1,18 @@ +import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState'; +import { View } from '@/views/types/View'; +import { selector } from 'recoil'; + +export const favoriteViewsWithMinimalDataSelector = selector< + Pick[] +>({ + key: 'favoriteViewsWithMinimalDataSelector', + get: ({ get }) => { + const views = get(prefetchViewsState); + return views.map((view) => ({ + id: view.id, + name: view.name, + objectMetadataId: view.objectMetadataId, + icon: view.icon, + })); + }, +}); diff --git a/packages/twenty-front/src/modules/favorites/utils/getObjectMetadataLabelPluralFromViewId.ts b/packages/twenty-front/src/modules/favorites/utils/getObjectMetadataLabelPluralFromViewId.ts index 91e3a0ec0ff2..53e8771721a4 100644 --- a/packages/twenty-front/src/modules/favorites/utils/getObjectMetadataLabelPluralFromViewId.ts +++ b/packages/twenty-front/src/modules/favorites/utils/getObjectMetadataLabelPluralFromViewId.ts @@ -4,23 +4,13 @@ import { isDefined } from 'twenty-shared'; type ReturnType = { labelPlural: string; - view: View | null; + view: Pick; }; export const getObjectMetadataLabelPluralFromViewId = ( - views: View[], + view: Pick, objectMetadataItems: ObjectMetadataItem[], - viewId: string, ): ReturnType => { - const view = views.find((view) => view.id === viewId); - - if (!view) { - return { - labelPlural: '', - view: null, - }; - } - const objectMetadataItem = objectMetadataItems.find( (objectMetadataItem) => objectMetadataItem.id === view.objectMetadataId, ); diff --git a/packages/twenty-front/src/modules/favorites/utils/sortFavorites.ts b/packages/twenty-front/src/modules/favorites/utils/sortFavorites.ts index 46d6d32fb21d..1f848e6c8c4d 100644 --- a/packages/twenty-front/src/modules/favorites/utils/sortFavorites.ts +++ b/packages/twenty-front/src/modules/favorites/utils/sortFavorites.ts @@ -22,16 +22,23 @@ export const sortFavorites = ( objectNameSingular: string, ) => ObjectRecordIdentifier, hasLinkToShowPage: boolean, - views: View[], + views: Pick[], objectMetadataItems: ObjectMetadataItem[], ) => { return favorites .map((favorite) => { if (isDefined(favorite.viewId) && isDefined(favorite.workspaceMemberId)) { - const { labelPlural, view } = getObjectMetadataLabelPluralFromViewId( - views, + const view = views.find((view) => view.id === favorite.viewId); + + if (!isDefined(view)) { + return { + ...favorite, + } as ProcessedFavorite; + } + + const { labelPlural } = getObjectMetadataLabelPluralFromViewId( + view, objectMetadataItems, - favorite.viewId, ); return { diff --git a/packages/twenty-front/src/modules/navigation/hooks/useDefaultHomePagePath.ts b/packages/twenty-front/src/modules/navigation/hooks/useDefaultHomePagePath.ts index fe8d45a6c60c..dea010525071 100644 --- a/packages/twenty-front/src/modules/navigation/hooks/useDefaultHomePagePath.ts +++ b/packages/twenty-front/src/modules/navigation/hooks/useDefaultHomePagePath.ts @@ -2,10 +2,8 @@ import { currentUserState } from '@/auth/states/currentUserState'; import { lastVisitedObjectMetadataItemIdState } from '@/navigation/states/lastVisitedObjectMetadataItemIdState'; import { ObjectPathInfo } from '@/navigation/types/ObjectPathInfo'; import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems'; -import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData'; -import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; +import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState'; import { AppPath } from '@/types/AppPath'; -import { View } from '@/views/types/View'; import { useCallback, useMemo } from 'react'; import { useRecoilValue } from 'recoil'; import { isDefined } from 'twenty-shared'; @@ -15,7 +13,7 @@ export const useDefaultHomePagePath = () => { const currentUser = useRecoilValue(currentUserState); const { activeObjectMetadataItems, alphaSortedActiveObjectMetadataItems } = useFilteredObjectMetadataItems(); - const { records: views } = usePrefetchedData(PrefetchKey.AllViews); + const prefetchViews = useRecoilValue(prefetchViewsState); const lastVisitedObjectMetadataItemId = useRecoilValue( lastVisitedObjectMetadataItemIdState, ); @@ -31,8 +29,10 @@ export const useDefaultHomePagePath = () => { const getFirstView = useCallback( (objectMetadataItemId: string | undefined | null) => - views.find((view) => view.objectMetadataId === objectMetadataItemId), - [views], + prefetchViews.find( + (view) => view.objectMetadataId === objectMetadataItemId, + ), + [prefetchViews], ); const firstObjectPathInfo = useMemo(() => { diff --git a/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerItemForObjectMetadataItem.tsx b/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerItemForObjectMetadataItem.tsx index b93a9df2c734..12ac9a208879 100644 --- a/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerItemForObjectMetadataItem.tsx +++ b/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerItemForObjectMetadataItem.tsx @@ -2,16 +2,13 @@ import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/ import { mainContextStoreComponentInstanceIdState } from '@/context-store/states/mainContextStoreComponentInstanceId'; import { lastVisitedViewPerObjectMetadataItemState } from '@/navigation/states/lastVisitedViewPerObjectMetadataItemState'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; -import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData'; -import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; +import { prefetchViewsFromObjectMetadataItemFamilySelector } from '@/prefetch/states/selector/prefetchViewsFromObjectMetadataItemFamilySelector'; import { AppPath } from '@/types/AppPath'; import { NavigationDrawerItem } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItem'; import { NavigationDrawerItemsCollapsableContainer } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItemsCollapsableContainer'; import { NavigationDrawerSubItem } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSubItem'; import { getNavigationSubItemLeftAdornment } from '@/ui/navigation/navigation-drawer/utils/getNavigationSubItemLeftAdornment'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; -import { View } from '@/views/types/View'; -import { getObjectMetadataItemViews } from '@/views/utils/getObjectMetadataItemViews'; import { useLocation } from 'react-router-dom'; import { useRecoilValue } from 'recoil'; import { AnimatedExpandableContainer, useIcons } from 'twenty-ui'; @@ -24,11 +21,10 @@ export type NavigationDrawerItemForObjectMetadataItemProps = { export const NavigationDrawerItemForObjectMetadataItem = ({ objectMetadataItem, }: NavigationDrawerItemForObjectMetadataItemProps) => { - const { records: views } = usePrefetchedData(PrefetchKey.AllViews); - - const objectMetadataViews = getObjectMetadataItemViews( - objectMetadataItem.id, - views, + const views = useRecoilValue( + prefetchViewsFromObjectMetadataItemFamilySelector({ + objectMetadataItemId: objectMetadataItem.id, + }), ); const mainContextStoreComponentInstanceId = useRecoilValue( @@ -68,9 +64,9 @@ export const NavigationDrawerItemForObjectMetadataItem = ({ }) + '/', ); - const shouldSubItemsBeDisplayed = isActive && objectMetadataViews.length > 1; + const shouldSubItemsBeDisplayed = isActive && views.length > 1; - const sortedObjectMetadataViews = [...objectMetadataViews].sort( + const sortedObjectMetadataViews = [...views].sort( (viewA, viewB) => viewA.position - viewB.position, ); diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexLoadBaseOnContextStoreEffect.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexLoadBaseOnContextStoreEffect.tsx index cb1d65ea7f5e..db79fc1a082b 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexLoadBaseOnContextStoreEffect.tsx +++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexLoadBaseOnContextStoreEffect.tsx @@ -1,7 +1,9 @@ import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState'; import { useLoadRecordIndexStates } from '@/object-record/record-index/hooks/useLoadRecordIndexStates'; +import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; -import { useEffect } from 'react'; +import { useEffect, useState } from 'react'; +import { useRecoilValue } from 'recoil'; import { isDefined } from 'twenty-shared'; export const RecordIndexLoadBaseOnContextStoreEffect = () => { @@ -10,11 +12,26 @@ export const RecordIndexLoadBaseOnContextStoreEffect = () => { contextStoreCurrentViewIdComponentState, ); + const [loadedViewId, setLoadedViewId] = useState( + undefined, + ); + + const view = useRecoilValue( + prefetchViewFromViewIdFamilySelector({ + viewId: contextStoreCurrentViewId ?? '', + }), + ); + useEffect(() => { - if (isDefined(contextStoreCurrentViewId)) { + if (loadedViewId === contextStoreCurrentViewId) { + return; + } + + if (isDefined(view)) { loadRecordIndexStates(); + setLoadedViewId(contextStoreCurrentViewId); } - }, [contextStoreCurrentViewId, loadRecordIndexStates]); + }, [contextStoreCurrentViewId, loadRecordIndexStates, loadedViewId, view]); return <>; }; diff --git a/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexStates.ts b/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexStates.ts index 918cd8f0ce6e..0eaab3f2642d 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexStates.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexStates.ts @@ -206,11 +206,18 @@ export const useLoadRecordIndexStates = () => { (view) => view.id === contextStoreCurrentViewId, ); + console.log(contextStoreCurrentViewId); + + console.log('view', view); + console.log('views', views); + console.log('objectMetadataItem', objectMetadataItem); + if (!view || !objectMetadataItem) { return; } const recordIndexId = `${objectMetadataItem.namePlural}-${view.id}`; + console.log('recordIndexId', recordIndexId); const filterableFieldMetadataItems = snapshot .getLoadable( diff --git a/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx b/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx index dfee520a74b1..6d70fa91698a 100644 --- a/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx +++ b/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx @@ -23,14 +23,12 @@ import { useRecordPicker } from '@/object-record/relation-picker/hooks/useRecord import { RecordPickerComponentInstanceContext } from '@/object-record/relation-picker/states/contexts/RecordPickerComponentInstanceContext'; import { RecordForSelect } from '@/object-record/relation-picker/types/RecordForSelect'; import { ObjectRecord } from '@/object-record/types/ObjectRecord'; -import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData'; -import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; +import { prefetchIndexViewIdFromObjectMetadataItemFamilySelector } from '@/prefetch/states/selector/prefetchIndexViewIdFromObjectMetadataItemFamilySelector'; import { AppPath } from '@/types/AppPath'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope'; import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; -import { View } from '@/views/types/View'; import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; import { useLingui } from '@lingui/react/macro'; import { RelationDefinitionType } from '~/generated-metadata/graphql'; @@ -123,12 +121,10 @@ export const RecordDetailRelationSection = ({ scopeId: dropdownId, }); - const { records: views } = usePrefetchedData(PrefetchKey.AllViews); - - const indexView = views.find( - (view) => - view.key === 'INDEX' && - view.objectMetadataId === relationObjectMetadataItem.id, + const indexViewId = useRecoilValue( + prefetchIndexViewIdFromObjectMetadataItemFamilySelector({ + objectMetadataItemId: relationObjectMetadataItem.id, + }), ); const filterQueryParams = { @@ -139,7 +135,7 @@ export const RecordDetailRelationSection = ({ }, }, }, - view: indexView?.id, + view: indexViewId, }; const filterLinkHref = getAppPath( diff --git a/packages/twenty-front/src/modules/prefetch/components/PrefetchDataProvider.tsx b/packages/twenty-front/src/modules/prefetch/components/PrefetchDataProvider.tsx index 04fdb0a21c7b..1b358a3ede63 100644 --- a/packages/twenty-front/src/modules/prefetch/components/PrefetchDataProvider.tsx +++ b/packages/twenty-front/src/modules/prefetch/components/PrefetchDataProvider.tsx @@ -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 ( <> - + + {children} ); diff --git a/packages/twenty-front/src/modules/prefetch/components/PrefetchRunQueriesEffect.tsx b/packages/twenty-front/src/modules/prefetch/components/PrefetchRunFavoriteQueriesEffect.tsx similarity index 65% rename from packages/twenty-front/src/modules/prefetch/components/PrefetchRunQueriesEffect.tsx rename to packages/twenty-front/src/modules/prefetch/components/PrefetchRunFavoriteQueriesEffect.tsx index 175c327083a4..e3a607ee3e89 100644 --- a/packages/twenty-front/src/modules/prefetch/components/PrefetchRunQueriesEffect.tsx +++ b/packages/twenty-front/src/modules/prefetch/components/PrefetchRunFavoriteQueriesEffect.tsx @@ -1,5 +1,5 @@ import { useEffect } from 'react'; -import { useRecoilCallback, useRecoilValue } from 'recoil'; +import { useRecoilValue } from 'recoil'; import { currentUserState } from '@/auth/states/currentUserState'; import { Favorite } from '@/favorites/types/Favorite'; @@ -8,24 +8,15 @@ import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadat import { useCombinedFindManyRecords } from '@/object-record/multiple-objects/hooks/useCombinedFindManyRecords'; import { PREFETCH_CONFIG } from '@/prefetch/constants/PrefetchConfig'; import { useUpsertRecordsInCacheForPrefetchKey } from '@/prefetch/hooks/internal/useUpsertRecordsInCacheForPrefetchKey'; -import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState'; import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; -import { View } from '@/views/types/View'; import { useIsWorkspaceActivationStatusSuspended } from '@/workspace/hooks/useIsWorkspaceActivationStatusSuspended'; import { isDefined } from 'twenty-shared'; -import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; -export const PrefetchRunQueriesEffect = () => { - console.log('PrefetchRunQueriesEffect'); +export const PrefetchRunFavoriteQueriesEffect = () => { const currentUser = useRecoilValue(currentUserState); const isWorkspaceSuspended = useIsWorkspaceActivationStatusSuspended(); - const { upsertRecordsInCache: upsertViewsInCache } = - useUpsertRecordsInCacheForPrefetchKey({ - prefetchKey: PrefetchKey.AllViews, - }); - const { upsertRecordsInCache: upsertFavoritesInCache } = useUpsertRecordsInCacheForPrefetchKey({ prefetchKey: PrefetchKey.AllFavorites, @@ -51,39 +42,14 @@ export const PrefetchRunQueriesEffect = () => { skip: !currentUser || isWorkspaceSuspended, }); - const setPrefetchViewsState = useRecoilCallback( - ({ set, snapshot }) => - (views: View[]) => { - const existingViews = snapshot - .getLoadable(prefetchViewsState) - .getValue(); - - if (!isDeeplyEqual(existingViews, views)) { - set(prefetchViewsState, views); - } - }, - [], - ); - useEffect(() => { - if (isDefined(result.views)) { - upsertViewsInCache(result.views as View[]); - setPrefetchViewsState(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, - setPrefetchViewsState, - ]); + }, [result, upsertFavoritesInCache, upsertFavoritesFoldersInCache]); return <>; }; diff --git a/packages/twenty-front/src/modules/prefetch/components/PrefetchRunViewQueryEffect.tsx b/packages/twenty-front/src/modules/prefetch/components/PrefetchRunViewQueryEffect.tsx new file mode 100644 index 000000000000..55553eda99cf --- /dev/null +++ b/packages/twenty-front/src/modules/prefetch/components/PrefetchRunViewQueryEffect.tsx @@ -0,0 +1,68 @@ +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 { PREFETCH_CONFIG } from '@/prefetch/constants/PrefetchConfig'; +import { findAllViewsOperationSignatureFactory } from '@/prefetch/graphql/operation-signatures/factories/findAllViewsOperationSignatureFactory'; +import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState'; +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 = () => { + console.log('PrefetchRunQueriesEffect'); + const currentUser = useRecoilValue(currentUserState); + + const isWorkspaceSuspended = useIsWorkspaceActivationStatusSuspended(); + + const { objectMetadataItems } = useObjectMetadataItems(); + + const operationSignatures = Object.values(PREFETCH_CONFIG) + + .map(({ objectNameSingular, operationSignatureFactory }) => { + const objectMetadataItem = objectMetadataItems.find( + (item) => item.nameSingular === objectNameSingular, + ); + + return operationSignatureFactory({ objectMetadataItem }); + }); + + 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); + } + }, + [], + ); + + useEffect(() => { + if (isDefined(records)) { + setPrefetchViewsState(records as View[]); + } + }, [records, setPrefetchViewsState]); + + return <>; +}; diff --git a/packages/twenty-front/src/modules/prefetch/constants/PrefetchConfig.ts b/packages/twenty-front/src/modules/prefetch/constants/PrefetchConfig.ts index ee3e1dab0f55..a3fbb9d45508 100644 --- a/packages/twenty-front/src/modules/prefetch/constants/PrefetchConfig.ts +++ b/packages/twenty-front/src/modules/prefetch/constants/PrefetchConfig.ts @@ -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, diff --git a/packages/twenty-front/src/modules/prefetch/hooks/useIsPrefetchLoading.ts b/packages/twenty-front/src/modules/prefetch/hooks/useIsPrefetchLoading.ts index ceaab4bd61d0..6135236df05e 100644 --- a/packages/twenty-front/src/modules/prefetch/hooks/useIsPrefetchLoading.ts +++ b/packages/twenty-front/src/modules/prefetch/hooks/useIsPrefetchLoading.ts @@ -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) ); }; diff --git a/packages/twenty-front/src/modules/prefetch/hooks/usePrefetchedData.ts b/packages/twenty-front/src/modules/prefetch/hooks/usePrefetchedData.ts index 8ffd11478570..51f374546b8e 100644 --- a/packages/twenty-front/src/modules/prefetch/hooks/usePrefetchedData.ts +++ b/packages/twenty-front/src/modules/prefetch/hooks/usePrefetchedData.ts @@ -12,6 +12,7 @@ export const usePrefetchedData = ( prefetchKey: PrefetchKey, filter?: RecordGqlOperationFilter, ) => { + console.log('prefetchKey', prefetchKey); const isDataPrefetched = useRecoilValue( prefetchIsLoadedFamilyState(prefetchKey), ); diff --git a/packages/twenty-front/src/modules/prefetch/states/selector/prefetchViewFromViewIdFamilySelector.ts b/packages/twenty-front/src/modules/prefetch/states/selector/prefetchViewFromViewIdFamilySelector.ts index 174cedef735e..7efb55082ffb 100644 --- a/packages/twenty-front/src/modules/prefetch/states/selector/prefetchViewFromViewIdFamilySelector.ts +++ b/packages/twenty-front/src/modules/prefetch/states/selector/prefetchViewFromViewIdFamilySelector.ts @@ -1,20 +1,16 @@ import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState'; -import { ViewKey } from '@/views/types/ViewKey'; +import { View } from '@/views/types/View'; import { selectorFamily } from 'recoil'; export const prefetchViewFromViewIdFamilySelector = selectorFamily< - string | undefined, - { objectMetadataItemId: string } + View | undefined, + { viewId: string } >({ key: 'prefetchViewFromViewIdFamilySelector', get: - ({ objectMetadataItemId }) => + ({ viewId }) => ({ get }) => { const views = get(prefetchViewsState); - return views?.find( - (view) => - view.objectMetadataId === objectMetadataItemId && - view.key === ViewKey.Index, - )?.id; + return views?.find((view) => view.id === viewId); }, }); diff --git a/packages/twenty-front/src/modules/prefetch/states/selector/prefetchViewLengthFamilySelector.ts b/packages/twenty-front/src/modules/prefetch/states/selector/prefetchViewLengthFamilySelector.ts new file mode 100644 index 000000000000..89e525ad6ab1 --- /dev/null +++ b/packages/twenty-front/src/modules/prefetch/states/selector/prefetchViewLengthFamilySelector.ts @@ -0,0 +1,10 @@ +import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState'; +import { selector } from 'recoil'; + +export const prefetchViewLengthSelector = selector({ + key: 'prefetchViewLengthSelector', + get: ({ get }) => { + const views = get(prefetchViewsState); + return views?.length ?? 0; + }, +}); diff --git a/packages/twenty-front/src/modules/prefetch/types/PrefetchKey.ts b/packages/twenty-front/src/modules/prefetch/types/PrefetchKey.ts index c71fe02e3810..0d076ad0e6bb 100644 --- a/packages/twenty-front/src/modules/prefetch/types/PrefetchKey.ts +++ b/packages/twenty-front/src/modules/prefetch/types/PrefetchKey.ts @@ -1,5 +1,4 @@ export enum PrefetchKey { - AllViews = 'ALL_VIEWS', AllFavorites = 'ALL_FAVORITES', AllFavoritesFolders = 'ALL_FAVORITES_FOLDERS', } diff --git a/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow.tsx b/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow.tsx index 38a1830766ad..c196768d2eaa 100644 --- a/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow.tsx +++ b/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow.tsx @@ -6,8 +6,7 @@ import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSi import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; import { isLabelIdentifierField } from '@/object-metadata/utils/isLabelIdentifierField'; import { useDeleteRecordFromCache } from '@/object-record/cache/hooks/useDeleteRecordFromCache'; -import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData'; -import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; +import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState'; import { SettingsObjectFieldActiveActionDropdown } from '@/settings/data-model/object-details/components/SettingsObjectFieldActiveActionDropdown'; import { SettingsObjectFieldInactiveActionDropdown } from '@/settings/data-model/object-details/components/SettingsObjectFieldDisabledActionDropdown'; import { settingsObjectFieldsFamilyState } from '@/settings/data-model/object-details/states/settingsObjectFieldsFamilyState'; @@ -16,11 +15,10 @@ import { SettingsPath } from '@/types/SettingsPath'; import { TableCell } from '@/ui/layout/table/components/TableCell'; import { TableRow } from '@/ui/layout/table/components/TableRow'; import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMemorizedUrlState'; -import { View } from '@/views/types/View'; import { useTheme } from '@emotion/react'; import styled from '@emotion/styled'; import { useMemo } from 'react'; -import { useRecoilState } from 'recoil'; +import { useRecoilState, useRecoilValue } from 'recoil'; import { isDefined } from 'twenty-shared'; import { IconMinus, @@ -121,8 +119,7 @@ export const SettingsObjectFieldItemTableRow = ({ deleteMetadataField, } = useFieldMetadataItem(); - const { records: allViews } = usePrefetchedData(PrefetchKey.AllViews); - + const prefetchViews = useRecoilValue(prefetchViewsState); const deleteViewFromCache = useDeleteRecordFromCache({ objectNameSingular: CoreObjectNameSingular.View, }); @@ -135,7 +132,7 @@ export const SettingsObjectFieldItemTableRow = ({ objectMetadataItem.id, ); - const deletedViewIds = allViews + const deletedViewIds = prefetchViews .map((view) => { if (view.kanbanFieldMetadataId === activeFieldMetadatItem.id) { deleteViewFromCache(view); diff --git a/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainer.tsx b/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainer.tsx index e6319b61c86f..813097e90e00 100644 --- a/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainer.tsx +++ b/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainer.tsx @@ -1,14 +1,16 @@ import styled from '@emotion/styled'; import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext'; +import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState'; import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext'; -import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { RecordFiltersComponentInstanceContext } from '@/object-record/record-filter/states/context/RecordFiltersComponentInstanceContext'; import { RecordIndexContextProvider } from '@/object-record/record-index/contexts/RecordIndexContext'; import { RecordTableWithWrappers } from '@/object-record/record-table/components/RecordTableWithWrappers'; import { SignInBackgroundMockContainerEffect } from '@/sign-in-background-mock/components/SignInBackgroundMockContainerEffect'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { ViewBar } from '@/views/components/ViewBar'; import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext'; +import { isDefined } from 'twenty-shared'; const StyledContainer = styled.div` display: flex; @@ -23,9 +25,14 @@ export const SignInBackgroundMockContainer = () => { const recordIndexId = 'sign-up-mock-record-table-id'; const viewBarId = 'companies-mock'; - const { objectMetadataItem } = useObjectMetadataItem({ - objectNameSingular, - }); + const objectMetadataItem = useRecoilComponentValueV2( + contextStoreCurrentObjectMetadataItemComponentState, + 'main-context-store', + ); + + if (!isDefined(objectMetadataItem)) { + return null; + } return ( @@ -47,7 +54,7 @@ export const SignInBackgroundMockContainer = () => { > { - const { records: views, isDataPrefetched } = usePrefetchedData( - PrefetchKey.AllViews, - ); - const currentViewId = useRecoilComponentValueV2( contextStoreCurrentViewIdComponentState, ); @@ -48,12 +43,16 @@ export const ViewBarRecordFilterEffect = () => { contextStoreCurrentObjectMetadataItem?.id, ); - useEffect(() => { - if (isDataPrefetched && !hasInitializedCurrentRecordFilters) { - const currentView = views.find((view) => view.id === currentViewId); + const currentView = useRecoilValue( + prefetchViewFromViewIdFamilySelector({ + viewId: currentViewId ?? '', + }), + ); + useEffect(() => { + if (isDefined(currentView) && !hasInitializedCurrentRecordFilters) { if ( - currentView?.objectMetadataId !== + currentView.objectMetadataId !== contextStoreCurrentObjectMetadataItem?.id ) { return; @@ -70,8 +69,6 @@ export const ViewBarRecordFilterEffect = () => { } } }, [ - isDataPrefetched, - views, currentViewId, setCurrentRecordFilters, filterableFieldMetadataItems, @@ -79,6 +76,7 @@ export const ViewBarRecordFilterEffect = () => { hasInitializedCurrentRecordFilters, setHasInitializedCurrentRecordFilters, contextStoreCurrentObjectMetadataItem?.id, + currentView, ]); return null; diff --git a/packages/twenty-front/src/modules/views/hooks/useApplyCurrentViewFiltersToCurrentRecordFilters.ts b/packages/twenty-front/src/modules/views/hooks/useApplyCurrentViewFiltersToCurrentRecordFilters.ts index 5fb1e786a7d5..3d90fabdf47c 100644 --- a/packages/twenty-front/src/modules/views/hooks/useApplyCurrentViewFiltersToCurrentRecordFilters.ts +++ b/packages/twenty-front/src/modules/views/hooks/useApplyCurrentViewFiltersToCurrentRecordFilters.ts @@ -1,18 +1,15 @@ 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 { 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(PrefetchKey.AllViews); - const currentViewId = useRecoilComponentValueV2( contextStoreCurrentViewIdComponentState, ); @@ -24,18 +21,28 @@ export const useApplyCurrentViewFiltersToCurrentRecordFilters = () => { const { filterableFieldMetadataItems } = useFilterableFieldMetadataItemsInRecordIndexContext(); - const applyCurrentViewFiltersToCurrentRecordFilters = () => { - const currentView = views.find((view) => view.id === currentViewId); - - if (isDefined(currentView)) { - setCurrentRecordFilters( - mapViewFiltersToFilters( - currentView.viewFilters, - filterableFieldMetadataItems, - ), - ); - } - }; + const applyCurrentViewFiltersToCurrentRecordFilters = useRecoilCallback( + ({ snapshot }) => + () => { + const currentView = snapshot + .getLoadable( + prefetchViewFromViewIdFamilySelector({ + viewId: currentViewId ?? '', + }), + ) + .getValue(); + + if (isDefined(currentView)) { + setCurrentRecordFilters( + mapViewFiltersToFilters( + currentView.viewFilters, + filterableFieldMetadataItems, + ), + ); + } + }, + [currentViewId, filterableFieldMetadataItems, setCurrentRecordFilters], + ); return { applyCurrentViewFiltersToCurrentRecordFilters, diff --git a/packages/twenty-front/src/modules/views/hooks/useChangeView.ts b/packages/twenty-front/src/modules/views/hooks/useChangeView.ts index 9ed9aeeff420..a8bbdffc06ff 100644 --- a/packages/twenty-front/src/modules/views/hooks/useChangeView.ts +++ b/packages/twenty-front/src/modules/views/hooks/useChangeView.ts @@ -8,6 +8,7 @@ export const useChangeView = (viewBarComponentId?: string) => { const { setViewInUrl } = useSetViewInUrl(); const changeView = async (viewId: string) => { + console.log('changeView', viewId); setViewInUrl(viewId); resetUnsavedViewStates(viewId); }; diff --git a/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts b/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts index 38488bd92106..542ea0b3791a 100644 --- a/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts +++ b/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts @@ -174,7 +174,9 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => { ); } + console.log('findManyViews before'); await findManyViews(); + console.log('findManyViews after'); set(isPersistingViewFieldsCallbackState, false); }, [ diff --git a/packages/twenty-front/src/modules/views/hooks/useGetCombinedViewFilterGroups.ts b/packages/twenty-front/src/modules/views/hooks/useGetCombinedViewFilterGroups.ts index c1300f2b8295..6de34305898a 100644 --- a/packages/twenty-front/src/modules/views/hooks/useGetCombinedViewFilterGroups.ts +++ b/packages/twenty-front/src/modules/views/hooks/useGetCombinedViewFilterGroups.ts @@ -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(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, ], diff --git a/packages/twenty-front/src/modules/views/hooks/useGetCombinedViewFilters.ts b/packages/twenty-front/src/modules/views/hooks/useGetCombinedViewFilters.ts index 1a72e3353900..8adf8304377b 100644 --- a/packages/twenty-front/src/modules/views/hooks/useGetCombinedViewFilters.ts +++ b/packages/twenty-front/src/modules/views/hooks/useGetCombinedViewFilters.ts @@ -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(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, ], diff --git a/packages/twenty-front/src/modules/views/hooks/useGetCombinedViewSorts.ts b/packages/twenty-front/src/modules/views/hooks/useGetCombinedViewSorts.ts index 7b3131da6685..10fbc26d793a 100644 --- a/packages/twenty-front/src/modules/views/hooks/useGetCombinedViewSorts.ts +++ b/packages/twenty-front/src/modules/views/hooks/useGetCombinedViewSorts.ts @@ -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(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, ], diff --git a/packages/twenty-front/src/modules/views/hooks/useGetCurrentView.ts b/packages/twenty-front/src/modules/views/hooks/useGetCurrentView.ts index 9c6ec9a4c629..4d8a9d204594 100644 --- a/packages/twenty-front/src/modules/views/hooks/useGetCurrentView.ts +++ b/packages/twenty-front/src/modules/views/hooks/useGetCurrentView.ts @@ -1,8 +1,10 @@ import { useEffect } from 'react'; +import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow'; import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState'; -import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData'; -import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; +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'; @@ -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,41 +29,46 @@ export const useGetCurrentView = (viewBarInstanceId?: string) => { viewBarInstanceId, ); - const { records: views } = usePrefetchedData(PrefetchKey.AllViews); + const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow(); const currentViewId = useRecoilComponentValueV2( contextStoreCurrentViewIdComponentState, ); - const viewObjectMetadataId = useRecoilComponentValueV2( - viewObjectMetadataIdComponentState, - instanceId, + const indexViewId = useRecoilValue( + prefetchIndexViewIdFromObjectMetadataItemFamilySelector({ + objectMetadataItemId: objectMetadataItem.id, + }), ); - const setIsCurrentViewKeyIndex = useSetRecoilComponentStateV2( - isCurrentViewKeyIndexComponentState, - instanceId, + const currentViewFromViewId = useRecoilValue( + prefetchViewFromViewIdFamilySelector({ + viewId: currentViewId ?? '', + }), ); - const currentViewFromCurrentViewId = views.find( - (view) => view.id === currentViewId, - ); - const indexView = views.find( - (view) => - view.key === 'INDEX' && view.objectMetadataId === viewObjectMetadataId, + const indexView = useRecoilValue( + prefetchViewFromViewIdFamilySelector({ + viewId: indexViewId ?? '', + }), ); - const currentView = currentViewId ? currentViewFromCurrentViewId : indexView; + const setIsCurrentViewKeyIndex = useSetRecoilComponentStateV2( + isCurrentViewKeyIndexComponentState, + instanceId, + ); 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( diff --git a/packages/twenty-front/src/modules/views/hooks/useGetCurrentViewOnly.ts b/packages/twenty-front/src/modules/views/hooks/useGetCurrentViewOnly.ts index 8bb90703e45f..9614c25d943b 100644 --- a/packages/twenty-front/src/modules/views/hooks/useGetCurrentViewOnly.ts +++ b/packages/twenty-front/src/modules/views/hooks/useGetCurrentViewOnly.ts @@ -1,21 +1,18 @@ import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState'; -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 { View } from '@/views/types/View'; -import { useMemo } from 'react'; +import { useRecoilValue } from 'recoil'; export const useGetCurrentViewOnly = () => { - const { records: views } = usePrefetchedData(PrefetchKey.AllViews); - const currentViewId = useRecoilComponentValueV2( contextStoreCurrentViewIdComponentState, ); - const currentView = useMemo( - () => views.find((view) => view.id === currentViewId), - [views, currentViewId], + const currentView = useRecoilValue( + prefetchViewFromViewIdFamilySelector({ + viewId: currentViewId ?? '', + }), ); return { diff --git a/packages/twenty-front/src/modules/views/hooks/useViewOrDefaultViewFromPrefetchedViews.ts b/packages/twenty-front/src/modules/views/hooks/useViewOrDefaultViewFromPrefetchedViews.ts index 40bd3d7a7393..f68ed5952687 100644 --- a/packages/twenty-front/src/modules/views/hooks/useViewOrDefaultViewFromPrefetchedViews.ts +++ b/packages/twenty-front/src/modules/views/hooks/useViewOrDefaultViewFromPrefetchedViews.ts @@ -1,7 +1,6 @@ -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, @@ -10,15 +9,17 @@ export const useViewOrDefaultViewFromPrefetchedViews = ({ objectMetadataItemId: string; viewId: string | null | undefined; }) => { - const { records: views } = usePrefetchedData(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 }; }; diff --git a/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerContentEffect.tsx b/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerContentEffect.tsx index eaacac4173c2..34d4076e23eb 100644 --- a/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerContentEffect.tsx +++ b/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerContentEffect.tsx @@ -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, ); diff --git a/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerFavoriteFoldersDropdown.tsx b/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerFavoriteFoldersDropdown.tsx index 470337e77687..587b3008b0b3 100644 --- a/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerFavoriteFoldersDropdown.tsx +++ b/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerFavoriteFoldersDropdown.tsx @@ -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(PrefetchKey.AllViews); const [viewPickerReferenceViewId] = useRecoilComponentStateV2( viewPickerReferenceViewIdComponentState, ); - const view = views.find((view) => view.id === viewPickerReferenceViewId); + const view = useRecoilValue( + prefetchViewFromViewIdFamilySelector({ + viewId: viewPickerReferenceViewId ?? '', + }), + ); return ( { const { currentViewWithCombinedFiltersAndSorts, viewsOnCurrentObject } = useGetCurrentView(); + const setViewPickerReferenceViewId = useSetRecoilComponentStateV2( viewPickerReferenceViewIdComponentState, ); diff --git a/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx b/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx index 437dde54bb91..de995150926e 100644 --- a/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx +++ b/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx @@ -1,38 +1,27 @@ import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState'; import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState'; import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext'; -import { mainContextStoreComponentInstanceIdState } from '@/context-store/states/mainContextStoreComponentInstanceId'; import { RecordIndexContainerGater } from '@/object-record/record-index/components/RecordIndexContainerGater'; -import { prefetchIsLoadedFamilyState } from '@/prefetch/states/prefetchIsLoadedFamilyState'; -import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; import { PageContainer } from '@/ui/layout/page/components/PageContainer'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { isNonEmptyString, isUndefined } from '@sniptt/guards'; -import { useRecoilValue } from 'recoil'; export const RecordIndexPage = () => { - const prefetchIsLoaded = useRecoilValue( - prefetchIsLoadedFamilyState(PrefetchKey.AllViews), - ); - - const mainContextStoreComponentInstanceId = useRecoilValue( - mainContextStoreComponentInstanceIdState, - ); + console.log('RecordIndexPage'); const contextStoreCurrentViewId = useRecoilComponentValueV2( contextStoreCurrentViewIdComponentState, - mainContextStoreComponentInstanceId, + 'main-context-store', ); const objectMetadataItem = useRecoilComponentValueV2( contextStoreCurrentObjectMetadataItemComponentState, - mainContextStoreComponentInstanceId, + 'main-context-store', ); if ( isUndefined(objectMetadataItem) || - !isNonEmptyString(contextStoreCurrentViewId) || - !prefetchIsLoaded + !isNonEmptyString(contextStoreCurrentViewId) ) { return null; } @@ -41,7 +30,7 @@ export const RecordIndexPage = () => { diff --git a/packages/twenty-front/src/testing/decorators/PrefetchLoadedDecorator.tsx b/packages/twenty-front/src/testing/decorators/PrefetchLoadedDecorator.tsx index f9e35c56b258..9e856f7ea3a1 100644 --- a/packages/twenty-front/src/testing/decorators/PrefetchLoadedDecorator.tsx +++ b/packages/twenty-front/src/testing/decorators/PrefetchLoadedDecorator.tsx @@ -5,9 +5,6 @@ import { prefetchIsLoadedFamilyState } from '@/prefetch/states/prefetchIsLoadedF import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; export const PrefetchLoadedDecorator: Decorator = (Story) => { - const setAreViewsPrefetched = useSetRecoilState( - prefetchIsLoadedFamilyState(PrefetchKey.AllViews), - ); const setAreFavoritesPrefetched = useSetRecoilState( prefetchIsLoadedFamilyState(PrefetchKey.AllFavorites), ); @@ -15,7 +12,6 @@ export const PrefetchLoadedDecorator: Decorator = (Story) => { prefetchIsLoadedFamilyState(PrefetchKey.AllFavoritesFolders), ); - setAreViewsPrefetched(true); setAreFavoritesPrefetched(true); setAreFavoritesFoldersPrefetched(true); diff --git a/packages/twenty-front/src/testing/decorators/PrefetchLoadingDecorator.tsx b/packages/twenty-front/src/testing/decorators/PrefetchLoadingDecorator.tsx index 12290c724b0e..76f87a69102b 100644 --- a/packages/twenty-front/src/testing/decorators/PrefetchLoadingDecorator.tsx +++ b/packages/twenty-front/src/testing/decorators/PrefetchLoadingDecorator.tsx @@ -5,14 +5,10 @@ import { prefetchIsLoadedFamilyState } from '@/prefetch/states/prefetchIsLoadedF import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; export const PrefetchLoadingDecorator: Decorator = (Story) => { - const setAreViewsPrefetched = useSetRecoilState( - prefetchIsLoadedFamilyState(PrefetchKey.AllViews), - ); const setAreFavoritesPrefetched = useSetRecoilState( - prefetchIsLoadedFamilyState(PrefetchKey.AllFavorites), + prefetchIsLoadedFamilyState(PrefetchKey.AllFavoritesFolders), ); - setAreViewsPrefetched(false); setAreFavoritesPrefetched(false); return ; From b32c205a120aedf410a742f7d5be55f172d2e96e Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Tue, 18 Feb 2025 00:20:49 +0100 Subject: [PATCH 06/14] Fix lint --- .../components/MainContextStoreProviderEffect.tsx | 4 ---- .../components/ObjectMetadataItemsProvider.tsx | 1 - ...ObjectOptionsDropdownRecordGroupFieldsContent.tsx | 1 - .../record-index/hooks/useLoadRecordIndexStates.ts | 7 ------- .../components/PrefetchRunViewQueryEffect.tsx | 12 ------------ .../src/modules/prefetch/hooks/usePrefetchedData.ts | 1 - .../src/modules/views/hooks/useChangeView.ts | 1 - .../views/hooks/useCreateViewFromCurrentView.ts | 2 -- .../hooks/useViewOrDefaultViewFromPrefetchedViews.ts | 2 -- .../src/pages/object-record/RecordIndexPage.tsx | 2 -- 10 files changed, 33 deletions(-) diff --git a/packages/twenty-front/src/modules/context-store/components/MainContextStoreProviderEffect.tsx b/packages/twenty-front/src/modules/context-store/components/MainContextStoreProviderEffect.tsx index 90d29936d99a..0dd368ba03ac 100644 --- a/packages/twenty-front/src/modules/context-store/components/MainContextStoreProviderEffect.tsx +++ b/packages/twenty-front/src/modules/context-store/components/MainContextStoreProviderEffect.tsx @@ -41,11 +41,9 @@ export const MainContextStoreProviderEffect = ({ contextStoreCurrentObjectMetadataItemComponentState, mainContextStoreComponentInstanceId, ); - console.log('Provider effect'); useEffect(() => { if (contextStoreCurrentObjectMetadataItem?.id !== objectMetadataItem.id) { - console.log('Setting object metadata item'); setContextStoreCurrentObjectMetadataItem(objectMetadataItem); } @@ -53,7 +51,6 @@ export const MainContextStoreProviderEffect = ({ mainContextStoreComponentInstanceIdToSet !== mainContextStoreComponentInstanceId ) { - console.log('Setting main context store component instance id'); setMainContextStoreComponentInstanceId( mainContextStoreComponentInstanceIdToSet, ); @@ -69,7 +66,6 @@ export const MainContextStoreProviderEffect = ({ }); if (contextStoreCurrentViewId !== viewId) { - console.log('Setting context store current view id'); setContextStoreCurrentViewId(viewId); } }, [ diff --git a/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsProvider.tsx b/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsProvider.tsx index 2d83ec61868e..d516f3ecf3dc 100644 --- a/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsProvider.tsx +++ b/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsProvider.tsx @@ -11,7 +11,6 @@ import { UserOrMetadataLoader } from '~/loading/components/UserOrMetadataLoader' export const ObjectMetadataItemsProvider = ({ children, }: React.PropsWithChildren) => { - console.log('ObjectMetadataItemsProvider'); const objectMetadataItems = useRecoilValue(objectMetadataItemsState); const shouldDisplayChildren = objectMetadataItems.length > 0; diff --git a/packages/twenty-front/src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownRecordGroupFieldsContent.tsx b/packages/twenty-front/src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownRecordGroupFieldsContent.tsx index b8258a88865d..aaf0287b172a 100644 --- a/packages/twenty-front/src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownRecordGroupFieldsContent.tsx +++ b/packages/twenty-front/src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownRecordGroupFieldsContent.tsx @@ -36,7 +36,6 @@ export const ObjectOptionsDropdownRecordGroupFieldsContent = () => { const { viewType, currentContentId, - recordIndexId, objectMetadataItem, onContentChange, resetContent, diff --git a/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexStates.ts b/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexStates.ts index 0eaab3f2642d..918cd8f0ce6e 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexStates.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexStates.ts @@ -206,18 +206,11 @@ export const useLoadRecordIndexStates = () => { (view) => view.id === contextStoreCurrentViewId, ); - console.log(contextStoreCurrentViewId); - - console.log('view', view); - console.log('views', views); - console.log('objectMetadataItem', objectMetadataItem); - if (!view || !objectMetadataItem) { return; } const recordIndexId = `${objectMetadataItem.namePlural}-${view.id}`; - console.log('recordIndexId', recordIndexId); const filterableFieldMetadataItems = snapshot .getLoadable( diff --git a/packages/twenty-front/src/modules/prefetch/components/PrefetchRunViewQueryEffect.tsx b/packages/twenty-front/src/modules/prefetch/components/PrefetchRunViewQueryEffect.tsx index 55553eda99cf..0018839377c5 100644 --- a/packages/twenty-front/src/modules/prefetch/components/PrefetchRunViewQueryEffect.tsx +++ b/packages/twenty-front/src/modules/prefetch/components/PrefetchRunViewQueryEffect.tsx @@ -5,7 +5,6 @@ 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 { PREFETCH_CONFIG } from '@/prefetch/constants/PrefetchConfig'; import { findAllViewsOperationSignatureFactory } from '@/prefetch/graphql/operation-signatures/factories/findAllViewsOperationSignatureFactory'; import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState'; import { View } from '@/views/types/View'; @@ -14,23 +13,12 @@ import { isDefined } from 'twenty-shared'; import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; export const PrefetchRunViewQueryEffect = () => { - console.log('PrefetchRunQueriesEffect'); const currentUser = useRecoilValue(currentUserState); const isWorkspaceSuspended = useIsWorkspaceActivationStatusSuspended(); const { objectMetadataItems } = useObjectMetadataItems(); - const operationSignatures = Object.values(PREFETCH_CONFIG) - - .map(({ objectNameSingular, operationSignatureFactory }) => { - const objectMetadataItem = objectMetadataItems.find( - (item) => item.nameSingular === objectNameSingular, - ); - - return operationSignatureFactory({ objectMetadataItem }); - }); - const findAllViewsOperationSignature = findAllViewsOperationSignatureFactory({ objectMetadataItem: objectMetadataItems.find( (item) => item.nameSingular === CoreObjectNameSingular.View, diff --git a/packages/twenty-front/src/modules/prefetch/hooks/usePrefetchedData.ts b/packages/twenty-front/src/modules/prefetch/hooks/usePrefetchedData.ts index 51f374546b8e..8ffd11478570 100644 --- a/packages/twenty-front/src/modules/prefetch/hooks/usePrefetchedData.ts +++ b/packages/twenty-front/src/modules/prefetch/hooks/usePrefetchedData.ts @@ -12,7 +12,6 @@ export const usePrefetchedData = ( prefetchKey: PrefetchKey, filter?: RecordGqlOperationFilter, ) => { - console.log('prefetchKey', prefetchKey); const isDataPrefetched = useRecoilValue( prefetchIsLoadedFamilyState(prefetchKey), ); diff --git a/packages/twenty-front/src/modules/views/hooks/useChangeView.ts b/packages/twenty-front/src/modules/views/hooks/useChangeView.ts index a8bbdffc06ff..9ed9aeeff420 100644 --- a/packages/twenty-front/src/modules/views/hooks/useChangeView.ts +++ b/packages/twenty-front/src/modules/views/hooks/useChangeView.ts @@ -8,7 +8,6 @@ export const useChangeView = (viewBarComponentId?: string) => { const { setViewInUrl } = useSetViewInUrl(); const changeView = async (viewId: string) => { - console.log('changeView', viewId); setViewInUrl(viewId); resetUnsavedViewStates(viewId); }; diff --git a/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts b/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts index 542ea0b3791a..38488bd92106 100644 --- a/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts +++ b/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts @@ -174,9 +174,7 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => { ); } - console.log('findManyViews before'); await findManyViews(); - console.log('findManyViews after'); set(isPersistingViewFieldsCallbackState, false); }, [ diff --git a/packages/twenty-front/src/modules/views/hooks/useViewOrDefaultViewFromPrefetchedViews.ts b/packages/twenty-front/src/modules/views/hooks/useViewOrDefaultViewFromPrefetchedViews.ts index f68ed5952687..26ee0b327941 100644 --- a/packages/twenty-front/src/modules/views/hooks/useViewOrDefaultViewFromPrefetchedViews.ts +++ b/packages/twenty-front/src/modules/views/hooks/useViewOrDefaultViewFromPrefetchedViews.ts @@ -4,10 +4,8 @@ import { useRecoilValue } from 'recoil'; export const useViewOrDefaultViewFromPrefetchedViews = ({ objectMetadataItemId, - viewId, }: { objectMetadataItemId: string; - viewId: string | null | undefined; }) => { const indexViewId = useRecoilValue( prefetchIndexViewIdFromObjectMetadataItemFamilySelector({ diff --git a/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx b/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx index de995150926e..46719d9ea49b 100644 --- a/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx +++ b/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx @@ -7,8 +7,6 @@ import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/ import { isNonEmptyString, isUndefined } from '@sniptt/guards'; export const RecordIndexPage = () => { - console.log('RecordIndexPage'); - const contextStoreCurrentViewId = useRecoilComponentValueV2( contextStoreCurrentViewIdComponentState, 'main-context-store', From e081da60582c1468c4a9a3756cd3708f135f4e07 Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Tue, 18 Feb 2025 02:27:25 +0100 Subject: [PATCH 07/14] Refactor useGetViewFromPrefetchState --- ...igationDrawerItemForObjectMetadataItem.tsx | 5 +++ .../hooks/useDeleteCombinedViewFilterGroup.ts | 8 ++-- .../hooks/useObjectOptionsForBoard.ts | 3 +- ...ecordIndexLoadBaseOnContextStoreEffect.tsx | 23 ++++++++++- .../hooks/useHandleRecordGroupField.ts | 12 +++--- .../hooks/useLoadRecordIndexStates.ts | 34 ++-------------- .../hooks/useRecordShowPagePagination.ts | 1 - .../components/RecordTableWithWrappers.tsx | 2 +- .../components/PrefetchRunViewQueryEffect.tsx | 7 +++- .../hooks/useCreateViewFromCurrentView.ts | 40 +++++++++---------- .../hooks/useDeleteCombinedViewFilters.ts | 8 ++-- .../views/hooks/useDeleteCombinedViewSorts.ts | 8 ++-- .../views/hooks/useGetViewFromCache.ts | 26 ------------ .../hooks/useGetViewFromPrefetchState.ts | 24 +++++++++++ ...blesFromActiveFieldsOfViewOrDefaultView.ts | 3 -- .../views/hooks/useSaveCurrentViewFields.ts | 22 ++++------ .../useSaveCurrentViewFiltersAndSorts.ts | 12 +++--- .../views/hooks/useSaveCurrentViewGroups.ts | 12 +++--- .../hooks/useUpsertCombinedViewFilters.ts | 8 ++-- .../views/hooks/useUpsertCombinedViewSorts.ts | 8 ++-- .../isPersistingViewFieldsComponentState.ts | 9 ----- .../states/isPersistingViewFieldsState.ts | 6 +++ .../hooks/useCloseAndResetViewPicker.ts | 34 +++++----------- .../hooks/useCreateViewFromCurrentState.ts | 1 + .../WorkflowEditActionFormCreateRecord.tsx | 1 - 25 files changed, 143 insertions(+), 174 deletions(-) delete mode 100644 packages/twenty-front/src/modules/views/hooks/useGetViewFromCache.ts create mode 100644 packages/twenty-front/src/modules/views/hooks/useGetViewFromPrefetchState.ts delete mode 100644 packages/twenty-front/src/modules/views/states/isPersistingViewFieldsComponentState.ts create mode 100644 packages/twenty-front/src/modules/views/states/isPersistingViewFieldsState.ts diff --git a/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerItemForObjectMetadataItem.tsx b/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerItemForObjectMetadataItem.tsx index 12ac9a208879..94b58c872069 100644 --- a/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerItemForObjectMetadataItem.tsx +++ b/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerItemForObjectMetadataItem.tsx @@ -26,6 +26,11 @@ export const NavigationDrawerItemForObjectMetadataItem = ({ objectMetadataItemId: objectMetadataItem.id, }), ); + console.log( + 'views from navigation drawer item', + objectMetadataItem.namePlural, + views, + ); const mainContextStoreComponentInstanceId = useRecoilValue( mainContextStoreComponentInstanceIdState, diff --git a/packages/twenty-front/src/modules/object-record/advanced-filter/hooks/useDeleteCombinedViewFilterGroup.ts b/packages/twenty-front/src/modules/object-record/advanced-filter/hooks/useDeleteCombinedViewFilterGroup.ts index d6e68280e491..0e0150e8ab4d 100644 --- a/packages/twenty-front/src/modules/object-record/advanced-filter/hooks/useDeleteCombinedViewFilterGroup.ts +++ b/packages/twenty-front/src/modules/object-record/advanced-filter/hooks/useDeleteCombinedViewFilterGroup.ts @@ -3,7 +3,7 @@ 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 { useGetViewFromPrefetchState } from '@/views/hooks/useGetViewFromPrefetchState'; import { unsavedToDeleteViewFilterGroupIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterGroupIdsComponentFamilyState'; import { unsavedToUpsertViewFilterGroupsComponentFamilyState } from '@/views/states/unsavedToUpsertViewFilterGroupsComponentFamilyState'; import { isDefined } from 'twenty-shared'; @@ -27,7 +27,7 @@ export const useDeleteCombinedViewFilterGroup = ( contextStoreCurrentViewIdComponentState, ); - const { getViewFromCache } = useGetViewFromCache(); + const { getViewFromPrefetchState } = useGetViewFromPrefetchState(); const deleteCombinedViewFilterGroup = useRecoilCallback( ({ snapshot, set }) => @@ -55,7 +55,7 @@ export const useDeleteCombinedViewFilterGroup = ( return; } - const currentView = await getViewFromCache(currentViewId); + const currentView = await getViewFromPrefetchState(currentViewId); if (!currentView) { return; @@ -98,7 +98,7 @@ export const useDeleteCombinedViewFilterGroup = ( }, [ currentViewIdCallbackState, - getViewFromCache, + getViewFromPrefetchState, unsavedToDeleteViewFilterGroupIdsCallbackState, unsavedToUpsertViewFilterGroupsCallbackState, ], diff --git a/packages/twenty-front/src/modules/object-record/object-options-dropdown/hooks/useObjectOptionsForBoard.ts b/packages/twenty-front/src/modules/object-record/object-options-dropdown/hooks/useObjectOptionsForBoard.ts index a7542942f036..607eab23fafc 100644 --- a/packages/twenty-front/src/modules/object-record/object-options-dropdown/hooks/useObjectOptionsForBoard.ts +++ b/packages/twenty-front/src/modules/object-record/object-options-dropdown/hooks/useObjectOptionsForBoard.ts @@ -26,12 +26,11 @@ type useObjectOptionsForBoardParams = { export const useObjectOptionsForBoard = ({ objectNameSingular, recordBoardId, - viewBarId, }: useObjectOptionsForBoardParams) => { const [recordIndexFieldDefinitions, setRecordIndexFieldDefinitions] = useRecoilState(recordIndexFieldDefinitionsState); - const { saveViewFields } = useSaveCurrentViewFields(viewBarId); + const { saveViewFields } = useSaveCurrentViewFields(); const { updateCurrentView } = useUpdateCurrentView(); const [isCompactModeActive, setIsCompactModeActive] = diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexLoadBaseOnContextStoreEffect.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexLoadBaseOnContextStoreEffect.tsx index db79fc1a082b..e2ee904e57cb 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexLoadBaseOnContextStoreEffect.tsx +++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexLoadBaseOnContextStoreEffect.tsx @@ -1,3 +1,4 @@ +import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState'; import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState'; import { useLoadRecordIndexStates } from '@/object-record/record-index/hooks/useLoadRecordIndexStates'; import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector'; @@ -22,16 +23,34 @@ export const RecordIndexLoadBaseOnContextStoreEffect = () => { }), ); + const objectMetadataItem = useRecoilComponentValueV2( + contextStoreCurrentObjectMetadataItemComponentState, + ); + + console.log('objectMetadataItem', objectMetadataItem); + console.log(view); + useEffect(() => { if (loadedViewId === contextStoreCurrentViewId) { return; } + if (!isDefined(objectMetadataItem)) { + return; + } + if (isDefined(view)) { - loadRecordIndexStates(); + console.log('view', view); + loadRecordIndexStates(view, objectMetadataItem); setLoadedViewId(contextStoreCurrentViewId); } - }, [contextStoreCurrentViewId, loadRecordIndexStates, loadedViewId, view]); + }, [ + contextStoreCurrentViewId, + loadRecordIndexStates, + loadedViewId, + objectMetadataItem, + view, + ]); return <>; }; diff --git a/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleRecordGroupField.ts b/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleRecordGroupField.ts index 205b3633178d..bcfe2a037f1d 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleRecordGroupField.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleRecordGroupField.ts @@ -2,7 +2,7 @@ import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/ import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; import { usePersistViewGroupRecords } from '@/views/hooks/internal/usePersistViewGroupRecords'; -import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache'; +import { useGetViewFromPrefetchState } from '@/views/hooks/useGetViewFromPrefetchState'; import { ViewGroup } from '@/views/types/ViewGroup'; import { useRecoilCallback } from 'recoil'; import { v4 } from 'uuid'; @@ -16,7 +16,7 @@ export const useHandleRecordGroupField = () => { contextStoreCurrentViewIdComponentState, ); - const { getViewFromCache } = useGetViewFromCache(); + const { getViewFromPrefetchState } = useGetViewFromPrefetchState(); const handleRecordGroupFieldChange = useRecoilCallback( ({ snapshot }) => @@ -29,7 +29,7 @@ export const useHandleRecordGroupField = () => { return; } - const view = await getViewFromCache(currentViewId); + const view = await getViewFromPrefetchState(currentViewId); if (isUndefinedOrNull(view)) { return; @@ -98,7 +98,7 @@ export const useHandleRecordGroupField = () => { createViewGroupRecords, deleteViewGroupRecords, currentViewIdCallbackState, - getViewFromCache, + getViewFromPrefetchState, ], ); @@ -113,7 +113,7 @@ export const useHandleRecordGroupField = () => { return; } - const view = await getViewFromCache(currentViewId); + const view = await getViewFromPrefetchState(currentViewId); if (isUndefinedOrNull(view)) { return; @@ -125,7 +125,7 @@ export const useHandleRecordGroupField = () => { await deleteViewGroupRecords(view.viewGroups); }, - [deleteViewGroupRecords, currentViewIdCallbackState, getViewFromCache], + [deleteViewGroupRecords, currentViewIdCallbackState, getViewFromPrefetchState], ); return { handleRecordGroupFieldChange, resetRecordGroupField }; diff --git a/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexStates.ts b/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexStates.ts index 918cd8f0ce6e..a744939c3978 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexStates.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexStates.ts @@ -1,5 +1,3 @@ -import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState'; -import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState'; import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; import { availableFieldMetadataItemsForFilterFamilySelector } from '@/object-metadata/states/availableFieldMetadataItemsForFilterFamilySelector'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; @@ -23,8 +21,8 @@ import { tableViewFilterGroupsComponentState } from '@/object-record/record-tabl import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition'; import { convertAggregateOperationToExtendedAggregateOperation } from '@/object-record/utils/convertAggregateOperationToExtendedAggregateOperation'; import { filterAvailableTableColumns } from '@/object-record/utils/filterAvailableTableColumns'; -import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState'; import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; +import { View } from '@/views/types/View'; import { ViewField } from '@/views/types/ViewField'; import { ViewGroup } from '@/views/types/ViewGroup'; import { mapViewFieldsToColumnDefinitions } from '@/views/utils/mapViewFieldsToColumnDefinitions'; @@ -114,6 +112,8 @@ export const useLoadRecordIndexStates = () => { columnDefinitions, }); + console.log('newFieldDefinitions', newFieldDefinitions); + setTableColumns(newFieldDefinitions, recordIndexId); const existingRecordIndexFieldDefinitions = snapshot @@ -183,33 +183,7 @@ export const useLoadRecordIndexStates = () => { const loadRecordIndexStates = useRecoilCallback( ({ snapshot, set }) => - async () => { - const objectMetadataItem = snapshot - .getLoadable( - contextStoreCurrentObjectMetadataItemComponentState.atomFamily({ - instanceId: 'main-context-store', - }), - ) - .getValue(); - - const contextStoreCurrentViewId = snapshot - .getLoadable( - contextStoreCurrentViewIdComponentState.atomFamily({ - instanceId: 'main-context-store', - }), - ) - .getValue(); - - const views = snapshot.getLoadable(prefetchViewsState).getValue(); - - const view = views.find( - (view) => view.id === contextStoreCurrentViewId, - ); - - if (!view || !objectMetadataItem) { - return; - } - + async (view: View, objectMetadataItem: ObjectMetadataItem) => { const recordIndexId = `${objectMetadataItem.namePlural}-${view.id}`; const filterableFieldMetadataItems = snapshot diff --git a/packages/twenty-front/src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts b/packages/twenty-front/src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts index 460f60a1ab20..f089ee8c7a4b 100644 --- a/packages/twenty-front/src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts +++ b/packages/twenty-front/src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts @@ -39,7 +39,6 @@ export const useRecordShowPagePagination = ( const { filter, orderBy } = useQueryVariablesFromActiveFieldsOfViewOrDefaultView({ objectMetadataItem, - viewId: viewIdQueryParam, }); const { loading: loadingCursor, pageInfo: currentRecordsPageInfo } = diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableWithWrappers.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableWithWrappers.tsx index 30827c224998..575dd0673012 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableWithWrappers.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableWithWrappers.tsx @@ -75,7 +75,7 @@ export const RecordTableWithWrappers = ({ ActionBarHotkeyScope.ActionBar, ); - const { saveViewFields } = useSaveCurrentViewFields(viewBarId); + const { saveViewFields } = useSaveCurrentViewFields(); const { deleteOneRecord } = useDeleteOneRecord({ objectNameSingular }); diff --git a/packages/twenty-front/src/modules/prefetch/components/PrefetchRunViewQueryEffect.tsx b/packages/twenty-front/src/modules/prefetch/components/PrefetchRunViewQueryEffect.tsx index 0018839377c5..fbb5bb8cd3dc 100644 --- a/packages/twenty-front/src/modules/prefetch/components/PrefetchRunViewQueryEffect.tsx +++ b/packages/twenty-front/src/modules/prefetch/components/PrefetchRunViewQueryEffect.tsx @@ -7,6 +7,7 @@ import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSi 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'; @@ -46,11 +47,13 @@ export const PrefetchRunViewQueryEffect = () => { [], ); + const isPersistingViewFields = useRecoilValue(isPersistingViewFieldsState); + useEffect(() => { - if (isDefined(records)) { + if (isDefined(records) && !isPersistingViewFields) { setPrefetchViewsState(records as View[]); } - }, [records, setPrefetchViewsState]); + }, [isPersistingViewFields, records, setPrefetchViewsState]); return <>; }; diff --git a/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts b/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts index 38488bd92106..c9e41d488b11 100644 --- a/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts +++ b/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts @@ -3,6 +3,7 @@ import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSi 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'; @@ -13,8 +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 { 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'; @@ -30,17 +30,6 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => { viewBarComponentId, ); - const isPersistingViewFieldsCallbackState = useRecoilComponentCallbackStateV2( - isPersistingViewFieldsComponentState, - viewBarComponentId, - ); - - const { findManyRecords: findManyViews } = useLazyFindManyRecords({ - objectNameSingular: CoreObjectNameSingular.View, - }); - - const { getViewFromCache } = useGetViewFromCache(); - const { createOneRecord } = useCreateOneRecord({ objectNameSingular: CoreObjectNameSingular.View, }); @@ -62,6 +51,12 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => { const { createViewFilterGroupRecords } = usePersistViewFilterGroupRecords(); const { objectMetadataItem } = useRecordIndexContextOrThrow(); + console.log('re-render'); + + const { findManyRecords } = useLazyFindManyRecords({ + objectNameSingular: CoreObjectNameSingular.View, + fetchPolicy: 'network-only', + }); const createViewFromCurrentView = useRecoilCallback( ({ snapshot, set }) => @@ -89,14 +84,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(), @@ -174,16 +174,14 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => { ); } - await findManyViews(); - set(isPersistingViewFieldsCallbackState, false); + await findManyRecords(); + set(isPersistingViewFieldsState, false); }, [ currentViewIdCallbackState, - getViewFromCache, - isPersistingViewFieldsCallbackState, createOneRecord, createViewFieldRecords, - findManyViews, + findManyRecords, objectMetadataItem?.fields, createViewGroupRecords, getViewFilterGroupsCombined, diff --git a/packages/twenty-front/src/modules/views/hooks/useDeleteCombinedViewFilters.ts b/packages/twenty-front/src/modules/views/hooks/useDeleteCombinedViewFilters.ts index 2246a77a3fb2..67dc018739c3 100644 --- a/packages/twenty-front/src/modules/views/hooks/useDeleteCombinedViewFilters.ts +++ b/packages/twenty-front/src/modules/views/hooks/useDeleteCombinedViewFilters.ts @@ -3,7 +3,7 @@ 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 { useGetViewFromPrefetchState } from '@/views/hooks/useGetViewFromPrefetchState'; import { unsavedToDeleteViewFilterIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState'; import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState'; import { isDefined } from 'twenty-shared'; @@ -26,7 +26,7 @@ export const useDeleteCombinedViewFilters = (viewBarComponentId?: string) => { 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, ], diff --git a/packages/twenty-front/src/modules/views/hooks/useDeleteCombinedViewSorts.ts b/packages/twenty-front/src/modules/views/hooks/useDeleteCombinedViewSorts.ts index 66e10c1fe1b4..ce7f2827ffb9 100644 --- a/packages/twenty-front/src/modules/views/hooks/useDeleteCombinedViewSorts.ts +++ b/packages/twenty-front/src/modules/views/hooks/useDeleteCombinedViewSorts.ts @@ -3,7 +3,7 @@ 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 { useGetViewFromPrefetchState } from '@/views/hooks/useGetViewFromPrefetchState'; import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewSortIdsComponentFamilyState'; import { unsavedToUpsertViewSortsComponentFamilyState } from '@/views/states/unsavedToUpsertViewSortsComponentFamilyState'; import { isDefined } from 'twenty-shared'; @@ -25,7 +25,7 @@ export const useDeleteCombinedViewSorts = (viewBarComponentId?: string) => { viewBarComponentId, ); - const { getViewFromCache } = useGetViewFromCache(); + const { getViewFromPrefetchState } = useGetViewFromPrefetchState(); const deleteCombinedViewSort = useRecoilCallback( ({ snapshot, set }) => @@ -49,7 +49,7 @@ export const useDeleteCombinedViewSorts = (viewBarComponentId?: string) => { unsavedToDeleteViewSortIdsCallbackState({ viewId: currentViewId }), ); - const currentView = await getViewFromCache(currentViewId); + const currentView = await getViewFromPrefetchState(currentViewId); if (!currentView) { return; @@ -87,7 +87,7 @@ export const useDeleteCombinedViewSorts = (viewBarComponentId?: string) => { }, [ currentViewIdCallbackState, - getViewFromCache, + getViewFromPrefetchState, unsavedToDeleteViewSortIdsCallbackState, unsavedToUpsertViewSortsCallbackState, ], diff --git a/packages/twenty-front/src/modules/views/hooks/useGetViewFromCache.ts b/packages/twenty-front/src/modules/views/hooks/useGetViewFromCache.ts deleted file mode 100644 index cdc95e1e8fbd..000000000000 --- a/packages/twenty-front/src/modules/views/hooks/useGetViewFromCache.ts +++ /dev/null @@ -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(viewId, cache); - }, - [cache, getRecordFromCache], - ); - - return { - getViewFromCache, - }; -}; diff --git a/packages/twenty-front/src/modules/views/hooks/useGetViewFromPrefetchState.ts b/packages/twenty-front/src/modules/views/hooks/useGetViewFromPrefetchState.ts new file mode 100644 index 000000000000..1dc1d35f3e06 --- /dev/null +++ b/packages/twenty-front/src/modules/views/hooks/useGetViewFromPrefetchState.ts @@ -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, + }; +}; diff --git a/packages/twenty-front/src/modules/views/hooks/useQueryVariablesFromActiveFieldsOfViewOrDefaultView.ts b/packages/twenty-front/src/modules/views/hooks/useQueryVariablesFromActiveFieldsOfViewOrDefaultView.ts index 048334c6f416..527f6b6b7acd 100644 --- a/packages/twenty-front/src/modules/views/hooks/useQueryVariablesFromActiveFieldsOfViewOrDefaultView.ts +++ b/packages/twenty-front/src/modules/views/hooks/useQueryVariablesFromActiveFieldsOfViewOrDefaultView.ts @@ -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({ diff --git a/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFields.ts b/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFields.ts index 4bcd1cfefc7c..5c14c5e90ed4 100644 --- a/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFields.ts +++ b/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFields.ts @@ -3,28 +3,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 { 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( contextStoreCurrentViewIdComponentState, ); - const isPersistingViewFieldsCallbackState = useRecoilComponentCallbackStateV2( - isPersistingViewFieldsComponentState, - viewBarComponentId, - ); - const saveViewFields = useRecoilCallback( ({ set, snapshot }) => async (viewFieldsToSave: ViewField[]) => { @@ -36,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; @@ -93,13 +88,12 @@ export const useSaveCurrentViewFields = (viewBarComponentId?: string) => { updateViewFieldRecords(viewFieldsToUpdate), ]); - set(isPersistingViewFieldsCallbackState, false); + set(isPersistingViewFieldsState, false); }, [ createViewFieldRecords, currentViewIdCallbackState, - getViewFromCache, - isPersistingViewFieldsCallbackState, + getViewFromPrefetchState, updateViewFieldRecords, ], ); diff --git a/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFiltersAndSorts.ts b/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFiltersAndSorts.ts index 27cdeb13f73d..ef8d7b0e7ae2 100644 --- a/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFiltersAndSorts.ts +++ b/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFiltersAndSorts.ts @@ -5,7 +5,7 @@ import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotV 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 { unsavedToDeleteViewFilterGroupIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterGroupIdsComponentFamilyState'; @@ -18,7 +18,7 @@ import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull'; export const useSaveCurrentViewFiltersAndSorts = ( viewBarComponentId?: string, ) => { - const { getViewFromCache } = useGetViewFromCache(); + const { getViewFromPrefetchState } = useGetViewFromPrefetchState(); const currentViewIdCallbackState = useRecoilComponentCallbackStateV2( contextStoreCurrentViewIdComponentState, @@ -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, diff --git a/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewGroups.ts b/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewGroups.ts index c4345a0b30a3..dbd80f0c07ba 100644 --- a/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewGroups.ts +++ b/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewGroups.ts @@ -3,7 +3,7 @@ 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 { useGetViewFromPrefetchState } from '@/views/hooks/useGetViewFromPrefetchState'; import { ViewGroup } from '@/views/types/ViewGroup'; import { isDefined } from 'twenty-shared'; import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; @@ -13,7 +13,7 @@ export const useSaveCurrentViewGroups = (viewBarComponentId?: string) => { const { createViewGroupRecords, updateViewGroupRecords } = usePersistViewGroupRecords(); - const { getViewFromCache } = useGetViewFromCache(); + const { getViewFromPrefetchState } = useGetViewFromPrefetchState(); const currentViewIdCallbackState = useRecoilComponentCallbackStateV2( contextStoreCurrentViewIdComponentState, @@ -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,7 @@ export const useSaveCurrentViewGroups = (viewBarComponentId?: string) => { { ...viewGroupToSave, id: existingField.id }, ]); }, - [currentViewIdCallbackState, getViewFromCache, updateViewGroupRecords], + [currentViewIdCallbackState, getViewFromPrefetchState, updateViewGroupRecords], ); const saveViewGroups = useRecoilCallback( @@ -81,7 +81,7 @@ export const useSaveCurrentViewGroups = (viewBarComponentId?: string) => { return; } - const view = await getViewFromCache(currentViewId); + const view = await getViewFromPrefetchState(currentViewId); if (isUndefinedOrNull(view)) { return; @@ -135,7 +135,7 @@ export const useSaveCurrentViewGroups = (viewBarComponentId?: string) => { [ createViewGroupRecords, currentViewIdCallbackState, - getViewFromCache, + getViewFromPrefetchState, updateViewGroupRecords, ], ); diff --git a/packages/twenty-front/src/modules/views/hooks/useUpsertCombinedViewFilters.ts b/packages/twenty-front/src/modules/views/hooks/useUpsertCombinedViewFilters.ts index 98c8c9ef6593..9df11a992ab0 100644 --- a/packages/twenty-front/src/modules/views/hooks/useUpsertCombinedViewFilters.ts +++ b/packages/twenty-front/src/modules/views/hooks/useUpsertCombinedViewFilters.ts @@ -4,7 +4,7 @@ import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/ 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 { useGetViewFromPrefetchState } from '@/views/hooks/useGetViewFromPrefetchState'; import { unsavedToDeleteViewFilterIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState'; import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState'; import { ViewFilter } from '@/views/types/ViewFilter'; @@ -29,7 +29,7 @@ export const useUpsertCombinedViewFilters = (viewBarComponentId?: string) => { 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, ], diff --git a/packages/twenty-front/src/modules/views/hooks/useUpsertCombinedViewSorts.ts b/packages/twenty-front/src/modules/views/hooks/useUpsertCombinedViewSorts.ts index c5d522f3fd8c..0d9f1f283da8 100644 --- a/packages/twenty-front/src/modules/views/hooks/useUpsertCombinedViewSorts.ts +++ b/packages/twenty-front/src/modules/views/hooks/useUpsertCombinedViewSorts.ts @@ -5,7 +5,7 @@ import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/ 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 { useGetViewFromPrefetchState } from '@/views/hooks/useGetViewFromPrefetchState'; import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewSortIdsComponentFamilyState'; import { unsavedToUpsertViewSortsComponentFamilyState } from '@/views/states/unsavedToUpsertViewSortsComponentFamilyState'; import { ViewSort } from '@/views/types/ViewSort'; @@ -28,7 +28,7 @@ export const useUpsertCombinedViewSorts = (viewBarComponentId?: string) => { viewBarComponentId, ); - const { getViewFromCache } = useGetViewFromCache(); + const { getViewFromPrefetchState } = useGetViewFromPrefetchState(); const upsertCombinedViewSort = useRecoilCallback( ({ snapshot, set }) => @@ -52,7 +52,7 @@ export const useUpsertCombinedViewSorts = (viewBarComponentId?: string) => { return; } - const currentView = await getViewFromCache(currentViewId); + const currentView = await getViewFromPrefetchState(currentViewId); if (!currentView) { return; @@ -110,7 +110,7 @@ export const useUpsertCombinedViewSorts = (viewBarComponentId?: string) => { }, [ currentViewIdCallbackState, - getViewFromCache, + getViewFromPrefetchState, unsavedToDeleteViewSortIdsCallbackState, unsavedToUpsertViewSortsCallbackState, ], diff --git a/packages/twenty-front/src/modules/views/states/isPersistingViewFieldsComponentState.ts b/packages/twenty-front/src/modules/views/states/isPersistingViewFieldsComponentState.ts deleted file mode 100644 index 7ddaa5e43d0c..000000000000 --- a/packages/twenty-front/src/modules/views/states/isPersistingViewFieldsComponentState.ts +++ /dev/null @@ -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({ - key: 'isPersistingViewFieldsComponentState', - defaultValue: false, - componentInstanceContext: ViewComponentInstanceContext, - }); diff --git a/packages/twenty-front/src/modules/views/states/isPersistingViewFieldsState.ts b/packages/twenty-front/src/modules/views/states/isPersistingViewFieldsState.ts new file mode 100644 index 000000000000..40dc43ab1942 --- /dev/null +++ b/packages/twenty-front/src/modules/views/states/isPersistingViewFieldsState.ts @@ -0,0 +1,6 @@ +import { createState } from 'twenty-ui'; + +export const isPersistingViewFieldsState = createState({ + key: 'isPersistingViewFieldsState', + defaultValue: false, +}); diff --git a/packages/twenty-front/src/modules/views/view-picker/hooks/useCloseAndResetViewPicker.ts b/packages/twenty-front/src/modules/views/view-picker/hooks/useCloseAndResetViewPicker.ts index 46fde3f74a19..d6dbe903ae82 100644 --- a/packages/twenty-front/src/modules/views/view-picker/hooks/useCloseAndResetViewPicker.ts +++ b/packages/twenty-front/src/modules/views/view-picker/hooks/useCloseAndResetViewPicker.ts @@ -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 }; }; diff --git a/packages/twenty-front/src/modules/views/view-picker/hooks/useCreateViewFromCurrentState.ts b/packages/twenty-front/src/modules/views/view-picker/hooks/useCreateViewFromCurrentState.ts index edd8421e54bf..c8a5f834c8f8 100644 --- a/packages/twenty-front/src/modules/views/view-picker/hooks/useCreateViewFromCurrentState.ts +++ b/packages/twenty-front/src/modules/views/view-picker/hooks/useCreateViewFromCurrentState.ts @@ -14,6 +14,7 @@ import { useRecoilCallback } from 'recoil'; import { v4 } from 'uuid'; export const useCreateViewFromCurrentState = () => { + console.log('useCreateViewFromCurrentState'); const { closeAndResetViewPicker } = useCloseAndResetViewPicker(); const viewPickerInputNameCallbackState = useRecoilComponentCallbackStateV2( diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionFormCreateRecord.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionFormCreateRecord.tsx index 768f6f8b9e94..b91ffebd8884 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionFormCreateRecord.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionFormCreateRecord.tsx @@ -83,7 +83,6 @@ export const WorkflowEditActionFormCreateRecord = ({ const { view: indexView } = useViewOrDefaultViewFromPrefetchedViews({ objectMetadataItemId: objectMetadataItem.id ?? '', - viewId: undefined, }); const viewFields = indexView?.viewFields ?? []; From 16309f1f71946374f060afeca7b8f68f6bc1a6b9 Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Tue, 18 Feb 2025 02:29:30 +0100 Subject: [PATCH 08/14] Fix lint --- .../NavigationDrawerItemForObjectMetadataItem.tsx | 5 ----- .../components/RecordIndexLoadBaseOnContextStoreEffect.tsx | 4 ---- .../record-index/hooks/useHandleRecordGroupField.ts | 6 +++++- .../src/modules/views/hooks/useCreateViewFromCurrentView.ts | 1 - .../src/modules/views/hooks/useSaveCurrentViewGroups.ts | 6 +++++- .../view-picker/hooks/useCreateViewFromCurrentState.ts | 1 - 6 files changed, 10 insertions(+), 13 deletions(-) diff --git a/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerItemForObjectMetadataItem.tsx b/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerItemForObjectMetadataItem.tsx index 94b58c872069..12ac9a208879 100644 --- a/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerItemForObjectMetadataItem.tsx +++ b/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerItemForObjectMetadataItem.tsx @@ -26,11 +26,6 @@ export const NavigationDrawerItemForObjectMetadataItem = ({ objectMetadataItemId: objectMetadataItem.id, }), ); - console.log( - 'views from navigation drawer item', - objectMetadataItem.namePlural, - views, - ); const mainContextStoreComponentInstanceId = useRecoilValue( mainContextStoreComponentInstanceIdState, diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexLoadBaseOnContextStoreEffect.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexLoadBaseOnContextStoreEffect.tsx index e2ee904e57cb..1521b2a5fa23 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexLoadBaseOnContextStoreEffect.tsx +++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexLoadBaseOnContextStoreEffect.tsx @@ -27,9 +27,6 @@ export const RecordIndexLoadBaseOnContextStoreEffect = () => { contextStoreCurrentObjectMetadataItemComponentState, ); - console.log('objectMetadataItem', objectMetadataItem); - console.log(view); - useEffect(() => { if (loadedViewId === contextStoreCurrentViewId) { return; @@ -40,7 +37,6 @@ export const RecordIndexLoadBaseOnContextStoreEffect = () => { } if (isDefined(view)) { - console.log('view', view); loadRecordIndexStates(view, objectMetadataItem); setLoadedViewId(contextStoreCurrentViewId); } diff --git a/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleRecordGroupField.ts b/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleRecordGroupField.ts index bcfe2a037f1d..6a0c5d03bd1c 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleRecordGroupField.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleRecordGroupField.ts @@ -125,7 +125,11 @@ export const useHandleRecordGroupField = () => { await deleteViewGroupRecords(view.viewGroups); }, - [deleteViewGroupRecords, currentViewIdCallbackState, getViewFromPrefetchState], + [ + deleteViewGroupRecords, + currentViewIdCallbackState, + getViewFromPrefetchState, + ], ); return { handleRecordGroupFieldChange, resetRecordGroupField }; diff --git a/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts b/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts index c9e41d488b11..68d2c19f95eb 100644 --- a/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts +++ b/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts @@ -51,7 +51,6 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => { const { createViewFilterGroupRecords } = usePersistViewFilterGroupRecords(); const { objectMetadataItem } = useRecordIndexContextOrThrow(); - console.log('re-render'); const { findManyRecords } = useLazyFindManyRecords({ objectNameSingular: CoreObjectNameSingular.View, diff --git a/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewGroups.ts b/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewGroups.ts index dbd80f0c07ba..2c98521cb071 100644 --- a/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewGroups.ts +++ b/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewGroups.ts @@ -67,7 +67,11 @@ export const useSaveCurrentViewGroups = (viewBarComponentId?: string) => { { ...viewGroupToSave, id: existingField.id }, ]); }, - [currentViewIdCallbackState, getViewFromPrefetchState, updateViewGroupRecords], + [ + currentViewIdCallbackState, + getViewFromPrefetchState, + updateViewGroupRecords, + ], ); const saveViewGroups = useRecoilCallback( diff --git a/packages/twenty-front/src/modules/views/view-picker/hooks/useCreateViewFromCurrentState.ts b/packages/twenty-front/src/modules/views/view-picker/hooks/useCreateViewFromCurrentState.ts index c8a5f834c8f8..edd8421e54bf 100644 --- a/packages/twenty-front/src/modules/views/view-picker/hooks/useCreateViewFromCurrentState.ts +++ b/packages/twenty-front/src/modules/views/view-picker/hooks/useCreateViewFromCurrentState.ts @@ -14,7 +14,6 @@ import { useRecoilCallback } from 'recoil'; import { v4 } from 'uuid'; export const useCreateViewFromCurrentState = () => { - console.log('useCreateViewFromCurrentState'); const { closeAndResetViewPicker } = useCloseAndResetViewPicker(); const viewPickerInputNameCallbackState = useRecoilComponentCallbackStateV2( From 6b4928eae4d5e739f66eb5e74b1d3c933d7ba287 Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Tue, 18 Feb 2025 09:05:51 +0100 Subject: [PATCH 09/14] Fix --- .../RecordTableNoRecordGroupBodyEffect.tsx | 9 +++- .../SignInBackgroundMockContainer.tsx | 42 +++++++++++-------- .../SignInBackgroundMockContainerEffect.tsx | 10 +++++ 3 files changed, 42 insertions(+), 19 deletions(-) diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableNoRecordGroupBodyEffect.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableNoRecordGroupBodyEffect.tsx index 8e3466afd336..64b994226b0c 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableNoRecordGroupBodyEffect.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableNoRecordGroupBodyEffect.tsx @@ -55,6 +55,8 @@ export const RecordTableNoRecordGroupBodyEffect = () => { lastShowPageRecordIdState, ); + const [hasInitialized, setHasInitialized] = useState(false); + const { scrollToPosition } = useScrollToPosition(); useEffect(() => { @@ -141,8 +143,11 @@ export const RecordTableNoRecordGroupBodyEffect = () => { return; } - findManyRecords(); - }, [currentWorkspaceMember, findManyRecords]); + if (!hasInitialized) { + findManyRecords(); + setHasInitialized(true); + } + }, [currentWorkspaceMember, findManyRecords, hasInitialized]); return <>; }; diff --git a/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainer.tsx b/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainer.tsx index 813097e90e00..e950bb7912ff 100644 --- a/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainer.tsx +++ b/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainer.tsx @@ -3,6 +3,7 @@ import styled from '@emotion/styled'; import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext'; import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState'; import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext'; +import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; import { RecordFiltersComponentInstanceContext } from '@/object-record/record-filter/states/context/RecordFiltersComponentInstanceContext'; import { RecordIndexContextProvider } from '@/object-record/record-index/contexts/RecordIndexContext'; import { RecordTableWithWrappers } from '@/object-record/record-table/components/RecordTableWithWrappers'; @@ -10,6 +11,7 @@ import { SignInBackgroundMockContainerEffect } from '@/sign-in-background-mock/c import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { ViewBar } from '@/views/components/ViewBar'; import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext'; +import { useRecoilValue } from 'recoil'; import { isDefined } from 'twenty-shared'; const StyledContainer = styled.div` @@ -25,15 +27,13 @@ export const SignInBackgroundMockContainer = () => { const recordIndexId = 'sign-up-mock-record-table-id'; const viewBarId = 'companies-mock'; + const objectMetadataItems = useRecoilValue(objectMetadataItemsState); + const objectMetadataItem = useRecoilComponentValueV2( contextStoreCurrentObjectMetadataItemComponentState, 'main-context-store', ); - if (!isDefined(objectMetadataItem)) { - return null; - } - return ( { recordIndexId, objectNamePlural, objectNameSingular, - objectMetadataItem, + objectMetadataItem: objectMetadataItem ?? objectMetadataItems[0], onIndexRecordsLoaded: () => {}, indexIdentifierUrl: () => '', }} @@ -57,21 +57,29 @@ export const SignInBackgroundMockContainer = () => { instanceId: 'main-context-store', }} > + - } /> - - {}} - /> + {isDefined(objectMetadataItem) && ( + <> + } + /> + + {}} + /> + + )} diff --git a/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainerEffect.tsx b/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainerEffect.tsx index 63ce37579dc7..0c501fc92636 100644 --- a/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainerEffect.tsx +++ b/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainerEffect.tsx @@ -1,5 +1,6 @@ import { useEffect } from 'react'; +import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural'; import { useSetRecordIndexEntityCount } from '@/object-record/record-index/hooks/useSetRecordIndexEntityCount'; @@ -8,6 +9,7 @@ import { useSetTableColumns } from '@/object-record/record-table/hooks/useSetTab import { SIGN_IN_BACKGROUND_MOCK_COLUMN_DEFINITIONS } from '@/sign-in-background-mock/constants/SignInBackgroundMockColumnDefinitions'; import { SIGN_IN_BACKGROUND_MOCK_SORT_DEFINITIONS } from '@/sign-in-background-mock/constants/SignInBackgroundMockSortDefinitions'; import { SIGN_IN_BACKGROUND_MOCK_VIEW_FIELDS } from '@/sign-in-background-mock/constants/SignInBackgroundMockViewFields'; +import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; import { useInitViewBar } from '@/views/hooks/useInitViewBar'; import { mapViewFieldsToColumnDefinitions } from '@/views/utils/mapViewFieldsToColumnDefinitions'; @@ -22,6 +24,11 @@ export const SignInBackgroundMockContainerEffect = ({ recordTableId, viewId, }: SignInBackgroundMockContainerEffectProps) => { + const setContextStoreCurrentObjectMetadataItem = useSetRecoilComponentStateV2( + contextStoreCurrentObjectMetadataItemComponentState, + 'main-context-store', + ); + const { setAvailableTableColumns, setOnEntityCountChange } = useRecordTable({ recordTableId, }); @@ -59,6 +66,8 @@ export const SignInBackgroundMockContainerEffect = ({ }), recordTableId, ); + + setContextStoreCurrentObjectMetadataItem(objectMetadataItem); }, [ setViewObjectMetadataId, setAvailableSortDefinitions, @@ -67,6 +76,7 @@ export const SignInBackgroundMockContainerEffect = ({ setAvailableTableColumns, setTableColumns, recordTableId, + setContextStoreCurrentObjectMetadataItem, ]); useEffect(() => { From 13b5a5ee6fa2b94aa8d66c63126bf9f806e16143 Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Tue, 18 Feb 2025 09:40:57 +0100 Subject: [PATCH 10/14] Fix tests --- .../__tests__/useDefaultHomePagePath.test.ts | 81 ++++++++++++------- .../hooks/useDefaultHomePagePath.ts | 1 + .../hooks/useLoadRecordIndexStates.ts | 2 - ...ViewFiltersToCurrentRecordFilters.test.tsx | 48 +++++------ 4 files changed, 77 insertions(+), 55 deletions(-) diff --git a/packages/twenty-front/src/modules/navigation/hooks/__tests__/useDefaultHomePagePath.test.ts b/packages/twenty-front/src/modules/navigation/hooks/__tests__/useDefaultHomePagePath.test.ts index 31a7172dfa9e..2b55546786e4 100644 --- a/packages/twenty-front/src/modules/navigation/hooks/__tests__/useDefaultHomePagePath.test.ts +++ b/packages/twenty-front/src/modules/navigation/hooks/__tests__/useDefaultHomePagePath.test.ts @@ -4,41 +4,54 @@ import { RecoilRoot, useSetRecoilState } from 'recoil'; import { currentUserState } from '@/auth/states/currentUserState'; import { useDefaultHomePagePath } from '@/navigation/hooks/useDefaultHomePagePath'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; -import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData'; +import { AGGREGATE_OPERATIONS } from '@/object-record/record-table/constants/AggregateOperations'; +import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState'; import { AppPath } from '@/types/AppPath'; +import { ViewType } from '@/views/types/ViewType'; +import { getCompanyObjectMetadataItem } from '~/testing/mock-data/companies'; import { generatedMockObjectMetadataItems } from '~/testing/mock-data/generatedMockObjectMetadataItems'; import { mockedUserData } from '~/testing/mock-data/users'; -jest.mock('@/prefetch/hooks/usePrefetchedData'); -const setupMockPrefetchedData = (viewId?: string) => { - const companyObjectMetadata = generatedMockObjectMetadataItems.find( - (item) => item.nameSingular === 'company', - ); - - jest.mocked(usePrefetchedData).mockReturnValue({ - isDataPrefetched: true, - records: viewId - ? [ - { - id: viewId, - __typename: 'object', - objectMetadataId: companyObjectMetadata?.id, - }, - ] - : [], - }); -}; - -const renderHooks = (withCurrentUser: boolean) => { +const renderHooks = ({ + withCurrentUser, + withExistingView, +}: { + withCurrentUser: boolean; + withExistingView: boolean; +}) => { const { result } = renderHook( () => { const setCurrentUser = useSetRecoilState(currentUserState); const setObjectMetadataItems = useSetRecoilState( objectMetadataItemsState, ); + const setPrefetchViews = useSetRecoilState(prefetchViewsState); setObjectMetadataItems(generatedMockObjectMetadataItems); + if (withExistingView) { + setPrefetchViews([ + { + id: 'viewId', + name: 'Test View', + objectMetadataId: getCompanyObjectMetadataItem().id, + type: ViewType.Table, + key: null, + isCompact: false, + viewFields: [], + viewGroups: [], + viewSorts: [], + kanbanFieldMetadataId: '', + kanbanAggregateOperation: AGGREGATE_OPERATIONS.count, + icon: '', + kanbanAggregateOperationFieldMetadataId: '', + position: 0, + viewFilters: [], + __typename: 'View', + }, + ]); + } + if (withCurrentUser) { setCurrentUser(mockedUserData); } @@ -52,23 +65,31 @@ const renderHooks = (withCurrentUser: boolean) => { }; describe('useDefaultHomePagePath', () => { it('should return proper path when no currentUser', () => { - setupMockPrefetchedData(); - const { result } = renderHooks(false); + const { result } = renderHooks({ + withCurrentUser: false, + withExistingView: false, + }); expect(result.current.defaultHomePagePath).toEqual(AppPath.SignInUp); }); it('should return proper path when no currentUser and existing view', () => { - setupMockPrefetchedData('viewId'); - const { result } = renderHooks(false); + const { result } = renderHooks({ + withCurrentUser: false, + withExistingView: true, + }); expect(result.current.defaultHomePagePath).toEqual(AppPath.SignInUp); }); it('should return proper path when currentUser is defined', () => { - setupMockPrefetchedData(); - const { result } = renderHooks(true); + const { result } = renderHooks({ + withCurrentUser: true, + withExistingView: false, + }); expect(result.current.defaultHomePagePath).toEqual('/objects/companies'); }); it('should return proper path when currentUser is defined and view exists', () => { - setupMockPrefetchedData('viewId'); - const { result } = renderHooks(true); + const { result } = renderHooks({ + withCurrentUser: true, + withExistingView: true, + }); expect(result.current.defaultHomePagePath).toEqual( '/objects/companies?viewId=viewId', ); diff --git a/packages/twenty-front/src/modules/navigation/hooks/useDefaultHomePagePath.ts b/packages/twenty-front/src/modules/navigation/hooks/useDefaultHomePagePath.ts index dea010525071..0d8e98a5d8c5 100644 --- a/packages/twenty-front/src/modules/navigation/hooks/useDefaultHomePagePath.ts +++ b/packages/twenty-front/src/modules/navigation/hooks/useDefaultHomePagePath.ts @@ -42,6 +42,7 @@ export const useDefaultHomePagePath = () => { return null; } + console.log('firstObjectMetadataItem', firstObjectMetadataItem.id); const view = getFirstView(firstObjectMetadataItem?.id); return { objectMetadataItem: firstObjectMetadataItem, view }; diff --git a/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexStates.ts b/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexStates.ts index a744939c3978..ac0a4b8bb472 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexStates.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexStates.ts @@ -112,8 +112,6 @@ export const useLoadRecordIndexStates = () => { columnDefinitions, }); - console.log('newFieldDefinitions', newFieldDefinitions); - setTableColumns(newFieldDefinitions, recordIndexId); const existingRecordIndexFieldDefinitions = snapshot diff --git a/packages/twenty-front/src/modules/views/hooks/__tests__/useApplyCurrentViewFiltersToCurrentRecordFilters.test.tsx b/packages/twenty-front/src/modules/views/hooks/__tests__/useApplyCurrentViewFiltersToCurrentRecordFilters.test.tsx index a904160e6b1d..108b49a4b0eb 100644 --- a/packages/twenty-front/src/modules/views/hooks/__tests__/useApplyCurrentViewFiltersToCurrentRecordFilters.test.tsx +++ b/packages/twenty-front/src/modules/views/hooks/__tests__/useApplyCurrentViewFiltersToCurrentRecordFilters.test.tsx @@ -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 { 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 wrapper = it('should apply filters from current view', () => { const { result } = renderHook( () => { const { applyCurrentViewFiltersToCurrentRecordFilters } = @@ -80,6 +90,7 @@ describe('useApplyCurrentViewFiltersToCurrentRecordFilters', () => { }), 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 } = @@ -136,6 +143,7 @@ describe('useApplyCurrentViewFiltersToCurrentRecordFilters', () => { }), 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 } = @@ -185,6 +184,9 @@ describe('useApplyCurrentViewFiltersToCurrentRecordFilters', () => { }), mockView.id, ); + snapshot.set(prefetchViewsState, [ + { ...mockView, viewFilters: [] }, + ]); }, }), }, From 42daab92ad2c0a535897b560b4496ade5bd2ea8e Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Tue, 18 Feb 2025 09:44:14 +0100 Subject: [PATCH 11/14] Fix lint --- .../src/modules/navigation/hooks/useDefaultHomePagePath.ts | 1 - .../useApplyCurrentViewFiltersToCurrentRecordFilters.test.tsx | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/twenty-front/src/modules/navigation/hooks/useDefaultHomePagePath.ts b/packages/twenty-front/src/modules/navigation/hooks/useDefaultHomePagePath.ts index 0d8e98a5d8c5..dea010525071 100644 --- a/packages/twenty-front/src/modules/navigation/hooks/useDefaultHomePagePath.ts +++ b/packages/twenty-front/src/modules/navigation/hooks/useDefaultHomePagePath.ts @@ -42,7 +42,6 @@ export const useDefaultHomePagePath = () => { return null; } - console.log('firstObjectMetadataItem', firstObjectMetadataItem.id); const view = getFirstView(firstObjectMetadataItem?.id); return { objectMetadataItem: firstObjectMetadataItem, view }; diff --git a/packages/twenty-front/src/modules/views/hooks/__tests__/useApplyCurrentViewFiltersToCurrentRecordFilters.test.tsx b/packages/twenty-front/src/modules/views/hooks/__tests__/useApplyCurrentViewFiltersToCurrentRecordFilters.test.tsx index 108b49a4b0eb..63aaac01b16e 100644 --- a/packages/twenty-front/src/modules/views/hooks/__tests__/useApplyCurrentViewFiltersToCurrentRecordFilters.test.tsx +++ b/packages/twenty-front/src/modules/views/hooks/__tests__/useApplyCurrentViewFiltersToCurrentRecordFilters.test.tsx @@ -62,7 +62,7 @@ describe('useApplyCurrentViewFiltersToCurrentRecordFilters', () => { __typename: 'View', }; - const wrapper = it('should apply filters from current view', () => { + it('should apply filters from current view', () => { const { result } = renderHook( () => { const { applyCurrentViewFiltersToCurrentRecordFilters } = From 07d8335b2ebfd5c992e5c6865873c2d8648e0cb3 Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Tue, 18 Feb 2025 10:58:21 +0100 Subject: [PATCH 12/14] Fix tests --- .../MultipleFiltersDropdownButton.stories.tsx | 2 + .../ObjectOptionsDropdownContent.stories.tsx | 17 ++++---- .../display/components/BooleanDisplay.tsx | 4 +- .../decorators/ContextStoreDecorator.tsx | 40 +++++++++++++++++++ 4 files changed, 50 insertions(+), 13 deletions(-) create mode 100644 packages/twenty-front/src/testing/decorators/ContextStoreDecorator.tsx diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/__stories__/MultipleFiltersDropdownButton.stories.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/__stories__/MultipleFiltersDropdownButton.stories.tsx index 5f67343a98e7..a73505d69bd6 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/__stories__/MultipleFiltersDropdownButton.stories.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/__stories__/MultipleFiltersDropdownButton.stories.tsx @@ -17,6 +17,7 @@ import { ComponentDecorator, getCanvasElementForDropdownTesting, } from 'twenty-ui'; +import { ContextStoreDecorator } from '~/testing/decorators/ContextStoreDecorator'; import { I18nFrontDecorator } from '~/testing/decorators/I18nFrontDecorator'; import { IconsProviderDecorator } from '~/testing/decorators/IconsProviderDecorator'; import { ObjectMetadataItemsDecorator } from '~/testing/decorators/ObjectMetadataItemsDecorator'; @@ -79,6 +80,7 @@ const meta: Meta = { ); }, + ContextStoreDecorator, ObjectMetadataItemsDecorator, SnackBarDecorator, ComponentDecorator, diff --git a/packages/twenty-front/src/modules/object-record/object-options-dropdown/components/__stories__/ObjectOptionsDropdownContent.stories.tsx b/packages/twenty-front/src/modules/object-record/object-options-dropdown/components/__stories__/ObjectOptionsDropdownContent.stories.tsx index bb06fb6617fc..94251ab53370 100644 --- a/packages/twenty-front/src/modules/object-record/object-options-dropdown/components/__stories__/ObjectOptionsDropdownContent.stories.tsx +++ b/packages/twenty-front/src/modules/object-record/object-options-dropdown/components/__stories__/ObjectOptionsDropdownContent.stories.tsx @@ -1,7 +1,6 @@ import { Meta, StoryObj } from '@storybook/react'; import { ComponentDecorator } from 'twenty-ui'; -import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; import { ObjectOptionsDropdownContent } from '@/object-record/object-options-dropdown/components/ObjectOptionsDropdownContent'; import { OBJECT_OPTIONS_DROPDOWN_ID } from '@/object-record/object-options-dropdown/constants/ObjectOptionsDropdownId'; @@ -16,6 +15,7 @@ import { ViewType } from '@/views/types/ViewType'; import { useEffect } from 'react'; import { MemoryRouter } from 'react-router-dom'; import { useSetRecoilState } from 'recoil'; +import { ContextStoreDecorator } from '~/testing/decorators/ContextStoreDecorator'; import { IconsProviderDecorator } from '~/testing/decorators/IconsProviderDecorator'; import { ObjectMetadataItemsDecorator } from '~/testing/decorators/ObjectMetadataItemsDecorator'; import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator'; @@ -45,21 +45,18 @@ const meta: Meta = { value={{ instanceId, onColumnsChange: () => {} }} > - - - - - + + ); }, + ContextStoreDecorator, ObjectMetadataItemsDecorator, SnackBarDecorator, ComponentDecorator, diff --git a/packages/twenty-front/src/modules/ui/field/display/components/BooleanDisplay.tsx b/packages/twenty-front/src/modules/ui/field/display/components/BooleanDisplay.tsx index b9568ffbe91f..044a00662f5d 100644 --- a/packages/twenty-front/src/modules/ui/field/display/components/BooleanDisplay.tsx +++ b/packages/twenty-front/src/modules/ui/field/display/components/BooleanDisplay.tsx @@ -1,8 +1,6 @@ import { styled } from '@linaria/react'; import { IconCheck, IconX, THEME_COMMON } from 'twenty-ui'; -import { isDefined } from 'twenty-shared'; - const spacing = THEME_COMMON.spacingMultiplicator * 1; const iconSizeSm = THEME_COMMON.icon.size.sm; @@ -15,7 +13,7 @@ type BooleanDisplayProps = { }; export const BooleanDisplay = ({ value }: BooleanDisplayProps) => { - if (!isDefined(value)) { + if (value === null || value === undefined) { return <>; } diff --git a/packages/twenty-front/src/testing/decorators/ContextStoreDecorator.tsx b/packages/twenty-front/src/testing/decorators/ContextStoreDecorator.tsx new file mode 100644 index 000000000000..09a589a14cb1 --- /dev/null +++ b/packages/twenty-front/src/testing/decorators/ContextStoreDecorator.tsx @@ -0,0 +1,40 @@ +import { Decorator } from '@storybook/react'; +import { useEffect, useState } from 'react'; + +import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState'; +import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext'; +import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; +import { isUndefined } from '@sniptt/guards'; +import { getCompanyObjectMetadataItem } from '~/testing/mock-data/companies'; + +export const ContextStoreDecorator: Decorator = (Story, context) => { + const { contextStore } = context.parameters; + + let componentInstanceId = contextStore?.componentInstanceId; + + if (isUndefined(componentInstanceId)) { + componentInstanceId = 'main-context-store'; + } + + const setCurrentObjectMetadataItem = useSetRecoilComponentStateV2( + contextStoreCurrentObjectMetadataItemComponentState, + componentInstanceId, + ); + + const [isLoaded, setIsLoaded] = useState(false); + + const objectMetadataItem = getCompanyObjectMetadataItem(); + + useEffect(() => { + setCurrentObjectMetadataItem(objectMetadataItem); + setIsLoaded(true); + }, [setCurrentObjectMetadataItem, objectMetadataItem]); + + return ( + + {isLoaded && } + + ); +}; From f45b37765b8e5af2d71708564bd9d5d1da039e24 Mon Sep 17 00:00:00 2001 From: prastoin Date: Tue, 18 Feb 2025 12:34:57 +0100 Subject: [PATCH 13/14] nitpick(front): objectMetadaItem fields always defined --- .../src/modules/views/hooks/useCreateViewFromCurrentView.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts b/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts index 68d2c19f95eb..87f6a3f7b668 100644 --- a/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts +++ b/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts @@ -127,7 +127,7 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => { } const viewGroupsToCreate = - objectMetadataItem?.fields + objectMetadataItem.fields ?.find((field) => field.id === kanbanFieldMetadataId) ?.options?.map( (option, index) => @@ -181,7 +181,7 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => { createOneRecord, createViewFieldRecords, findManyRecords, - objectMetadataItem?.fields, + objectMetadataItem.fields, createViewGroupRecords, getViewFilterGroupsCombined, getViewFiltersCombined, From 2ea1e186e86ae79ecd11f5ae2ee3aa708f7801ca Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Tue, 18 Feb 2025 13:47:19 +0100 Subject: [PATCH 14/14] Fix favorites too --- .../triggerCreateRecordsOptimisticEffect.ts | 1 + .../ContextStoreCurrentViewTypeEffect.tsx | 24 ---- .../components/MainContextStoreProvider.tsx | 20 ++-- .../MainContextStoreProviderEffect.tsx | 42 ++++++- .../hooks/useDeleteFavoriteFolder.ts | 34 ------ .../hooks/usePrefetchedFavoritesData.ts | 24 +--- .../usePrefetchedFavoritesFoldersData.ts | 22 +--- .../object-record/hooks/useCreateOneRecord.ts | 1 + .../components/RecordIndexContainer.tsx | 9 -- .../hooks/useLoadRecordIndexBoardColumn.ts | 9 +- .../components/RecordShowContainer.tsx | 5 - .../PrefetchRunFavoriteQueriesEffect.tsx | 105 +++++++++++++----- .../useUpsertRecordsInCacheForPrefetchKey.ts | 51 --------- .../prefetch/hooks/usePrefetchedData.ts | 38 ------- .../states/prefetchFavoriteFoldersState.ts | 7 ++ .../prefetch/states/prefetchFavoritesState.ts | 7 ++ .../pages/object-record/RecordShowPage.tsx | 2 +- 17 files changed, 158 insertions(+), 243 deletions(-) delete mode 100644 packages/twenty-front/src/modules/context-store/components/ContextStoreCurrentViewTypeEffect.tsx delete mode 100644 packages/twenty-front/src/modules/prefetch/hooks/internal/useUpsertRecordsInCacheForPrefetchKey.ts delete mode 100644 packages/twenty-front/src/modules/prefetch/hooks/usePrefetchedData.ts create mode 100644 packages/twenty-front/src/modules/prefetch/states/prefetchFavoriteFoldersState.ts create mode 100644 packages/twenty-front/src/modules/prefetch/states/prefetchFavoritesState.ts diff --git a/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/triggerCreateRecordsOptimisticEffect.ts b/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/triggerCreateRecordsOptimisticEffect.ts index 9acca6114a5f..88f1220f31d5 100644 --- a/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/triggerCreateRecordsOptimisticEffect.ts +++ b/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/triggerCreateRecordsOptimisticEffect.ts @@ -66,6 +66,7 @@ export const triggerCreateRecordsOptimisticEffect = ({ }); cache.modify({ + broadcast: false, fields: { [objectMetadataItem.namePlural]: ( rootQueryCachedResponse, diff --git a/packages/twenty-front/src/modules/context-store/components/ContextStoreCurrentViewTypeEffect.tsx b/packages/twenty-front/src/modules/context-store/components/ContextStoreCurrentViewTypeEffect.tsx deleted file mode 100644 index fc8b9b9c7443..000000000000 --- a/packages/twenty-front/src/modules/context-store/components/ContextStoreCurrentViewTypeEffect.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { contextStoreCurrentViewTypeComponentState } from '@/context-store/states/contextStoreCurrentViewTypeComponentState'; -import { ContextStoreViewType } from '@/context-store/types/ContextStoreViewType'; -import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; -import { useEffect } from 'react'; - -export const ContextStoreCurrentViewTypeEffect = ({ - viewType, -}: { - viewType: ContextStoreViewType | null; -}) => { - const setContextStoreCurrentViewType = useSetRecoilComponentStateV2( - contextStoreCurrentViewTypeComponentState, - ); - - useEffect(() => { - setContextStoreCurrentViewType(viewType); - - return () => { - setContextStoreCurrentViewType(null); - }; - }, [setContextStoreCurrentViewType, viewType]); - - return null; -}; diff --git a/packages/twenty-front/src/modules/context-store/components/MainContextStoreProvider.tsx b/packages/twenty-front/src/modules/context-store/components/MainContextStoreProvider.tsx index bbd3c8b0ddb6..73bc03463756 100644 --- a/packages/twenty-front/src/modules/context-store/components/MainContextStoreProvider.tsx +++ b/packages/twenty-front/src/modules/context-store/components/MainContextStoreProvider.tsx @@ -3,11 +3,9 @@ import { useLastVisitedView } from '@/navigation/hooks/useLastVisitedView'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; import { prefetchIndexViewIdFromObjectMetadataItemFamilySelector } from '@/prefetch/states/selector/prefetchIndexViewIdFromObjectMetadataItemFamilySelector'; import { AppPath } from '@/types/AppPath'; -import { isNonEmptyString } from '@sniptt/guards'; import { useParams, useSearchParams } from 'react-router-dom'; import { useRecoilValue } from 'recoil'; import { isDefined } from 'twenty-shared'; -import { undefined } from 'zod'; import { useIsMatchingLocation } from '~/hooks/useIsMatchingLocation'; const getViewId = ( @@ -42,17 +40,18 @@ export const MainContextStoreProvider = () => { : undefined; const objectNamePlural = useParams().objectNamePlural ?? ''; + const objectNameSingular = useParams().objectNameSingular ?? ''; const [searchParams] = useSearchParams(); const viewIdQueryParam = searchParams.get('viewId'); const objectMetadataItems = useRecoilValue(objectMetadataItemsState); - const objectMetadataItem = - objectMetadataItems.find( - (objectMetadataItem) => - objectMetadataItem.namePlural === objectNamePlural, - ) ?? objectMetadataItems[0]; + const objectMetadataItem = objectMetadataItems.find( + (objectMetadataItem) => + objectMetadataItem.namePlural === objectNamePlural || + objectMetadataItem.nameSingular === objectNameSingular, + ); const { getLastVisitedViewIdFromObjectNamePlural } = useLastVisitedView(); @@ -68,11 +67,7 @@ export const MainContextStoreProvider = () => { const viewId = getViewId(viewIdQueryParam, indexViewId, lastVisitedViewId); - if ( - !isDefined(pageName) || - !isDefined(objectMetadataItem) || - !isNonEmptyString(viewId) - ) { + if (!isDefined(pageName) || !isDefined(objectMetadataItem)) { return null; } @@ -81,6 +76,7 @@ export const MainContextStoreProvider = () => { mainContextStoreComponentInstanceIdToSet={'main-context-store'} viewId={viewId} objectMetadataItem={objectMetadataItem} + pageName={pageName} /> ); }; diff --git a/packages/twenty-front/src/modules/context-store/components/MainContextStoreProviderEffect.tsx b/packages/twenty-front/src/modules/context-store/components/MainContextStoreProviderEffect.tsx index 0dd368ba03ac..d0db2ea4e97f 100644 --- a/packages/twenty-front/src/modules/context-store/components/MainContextStoreProviderEffect.tsx +++ b/packages/twenty-front/src/modules/context-store/components/MainContextStoreProviderEffect.tsx @@ -1,21 +1,27 @@ import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState'; import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState'; +import { contextStoreCurrentViewTypeComponentState } from '@/context-store/states/contextStoreCurrentViewTypeComponentState'; import { mainContextStoreComponentInstanceIdState } from '@/context-store/states/mainContextStoreComponentInstanceId'; +import { ContextStoreViewType } from '@/context-store/types/ContextStoreViewType'; import { useSetLastVisitedObjectMetadataId } from '@/navigation/hooks/useSetLastVisitedObjectMetadataId'; import { useSetLastVisitedViewForObjectMetadataNamePlural } from '@/navigation/hooks/useSetLastVisitedViewForObjectMetadataNamePlural'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; +import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector'; import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2'; +import { ViewType } from '@/views/types/ViewType'; import { useEffect } from 'react'; -import { useRecoilState } from 'recoil'; +import { useRecoilState, useRecoilValue } from 'recoil'; export const MainContextStoreProviderEffect = ({ mainContextStoreComponentInstanceIdToSet, viewId, objectMetadataItem, + pageName, }: { mainContextStoreComponentInstanceIdToSet: string; - viewId: string; + viewId?: string; objectMetadataItem: ObjectMetadataItem; + pageName: string; }) => { const [ mainContextStoreComponentInstanceId, @@ -34,6 +40,12 @@ export const MainContextStoreProviderEffect = ({ mainContextStoreComponentInstanceId, ); + const [contextStoreCurrentViewType, setContextStoreCurrentViewType] = + useRecoilComponentStateV2( + contextStoreCurrentViewTypeComponentState, + mainContextStoreComponentInstanceId, + ); + const [ contextStoreCurrentObjectMetadataItem, setContextStoreCurrentObjectMetadataItem, @@ -42,6 +54,12 @@ export const MainContextStoreProviderEffect = ({ mainContextStoreComponentInstanceId, ); + const view = useRecoilValue( + prefetchViewFromViewIdFamilySelector({ + viewId: viewId ?? '', + }), + ); + useEffect(() => { if (contextStoreCurrentObjectMetadataItem?.id !== objectMetadataItem.id) { setContextStoreCurrentObjectMetadataItem(objectMetadataItem); @@ -58,7 +76,7 @@ export const MainContextStoreProviderEffect = ({ setLastVisitedViewForObjectMetadataNamePlural({ objectNamePlural: objectMetadataItem.namePlural, - viewId: viewId, + viewId: viewId ?? '', }); setLastVisitedObjectMetadataId({ @@ -83,5 +101,23 @@ export const MainContextStoreProviderEffect = ({ viewId, ]); + useEffect(() => { + const viewType = + pageName === 'record-show' + ? ContextStoreViewType.ShowPage + : view && view.type === ViewType.Kanban + ? ContextStoreViewType.Kanban + : ContextStoreViewType.Table; + + if (contextStoreCurrentViewType !== viewType) { + setContextStoreCurrentViewType(viewType); + } + }, [ + contextStoreCurrentViewType, + pageName, + setContextStoreCurrentViewType, + view, + ]); + return null; }; diff --git a/packages/twenty-front/src/modules/favorites/hooks/useDeleteFavoriteFolder.ts b/packages/twenty-front/src/modules/favorites/hooks/useDeleteFavoriteFolder.ts index c10adccb88f3..7b1ed284c87e 100644 --- a/packages/twenty-front/src/modules/favorites/hooks/useDeleteFavoriteFolder.ts +++ b/packages/twenty-front/src/modules/favorites/hooks/useDeleteFavoriteFolder.ts @@ -1,47 +1,13 @@ -import { Favorite } from '@/favorites/types/Favorite'; -import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; -import { useReadFindManyRecordsQueryInCache } from '@/object-record/cache/hooks/useReadFindManyRecordsQueryInCache'; import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord'; -import { PREFETCH_CONFIG } from '@/prefetch/constants/PrefetchConfig'; -import { useUpsertRecordsInCacheForPrefetchKey } from '@/prefetch/hooks/internal/useUpsertRecordsInCacheForPrefetchKey'; -import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; export const useDeleteFavoriteFolder = () => { const { deleteOneRecord } = useDeleteOneRecord({ objectNameSingular: CoreObjectNameSingular.FavoriteFolder, }); - const { upsertRecordsInCache } = - useUpsertRecordsInCacheForPrefetchKey({ - prefetchKey: PrefetchKey.AllFavorites, - }); - - const { objectMetadataItem } = useObjectMetadataItem({ - objectNameSingular: - PREFETCH_CONFIG[PrefetchKey.AllFavorites].objectNameSingular, - }); - - const { readFindManyRecordsQueryInCache } = - useReadFindManyRecordsQueryInCache({ - objectMetadataItem, - }); - const deleteFavoriteFolder = async (folderId: string): Promise => { await deleteOneRecord(folderId); - - const allFavorites = readFindManyRecordsQueryInCache({ - queryVariables: {}, - recordGqlFields: PREFETCH_CONFIG[ - PrefetchKey.AllFavorites - ].operationSignatureFactory({ objectMetadataItem }).fields, - }); - - const updatedFavorites = allFavorites.filter( - (favorite) => favorite.favoriteFolderId !== folderId, - ); - - upsertRecordsInCache(updatedFavorites); }; return { diff --git a/packages/twenty-front/src/modules/favorites/hooks/usePrefetchedFavoritesData.ts b/packages/twenty-front/src/modules/favorites/hooks/usePrefetchedFavoritesData.ts index ece3d2bdf3f3..c6a8cee7259c 100644 --- a/packages/twenty-front/src/modules/favorites/hooks/usePrefetchedFavoritesData.ts +++ b/packages/twenty-front/src/modules/favorites/hooks/usePrefetchedFavoritesData.ts @@ -1,46 +1,30 @@ import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState'; import { Favorite } from '@/favorites/types/Favorite'; -import { useUpsertRecordsInCacheForPrefetchKey } from '@/prefetch/hooks/internal/useUpsertRecordsInCacheForPrefetchKey'; -import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData'; -import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; +import { prefetchFavoritesState } from '@/prefetch/states/prefetchFavoritesState'; import { useRecoilValue } from 'recoil'; type PrefetchedFavoritesData = { favorites: Favorite[]; workspaceFavorites: Favorite[]; - upsertFavorites: (records: Favorite[]) => void; currentWorkspaceMemberId: string | undefined; }; export const usePrefetchedFavoritesData = (): PrefetchedFavoritesData => { const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); const currentWorkspaceMemberId = currentWorkspaceMember?.id; - const { records: _favorites } = usePrefetchedData( - PrefetchKey.AllFavorites, - { - workspaceMemberId: { - eq: currentWorkspaceMemberId, - }, - }, - ); + const prefetchFavorites = useRecoilValue(prefetchFavoritesState); - const favorites = _favorites.filter( + const favorites = prefetchFavorites.filter( (favorite) => favorite.workspaceMemberId === currentWorkspaceMemberId, ); - const workspaceFavorites = _favorites.filter( + const workspaceFavorites = prefetchFavorites.filter( (favorite) => favorite.workspaceMemberId === null, ); - const { upsertRecordsInCache: upsertFavorites } = - useUpsertRecordsInCacheForPrefetchKey({ - prefetchKey: PrefetchKey.AllFavorites, - }); - return { favorites, workspaceFavorites, - upsertFavorites, currentWorkspaceMemberId, }; }; diff --git a/packages/twenty-front/src/modules/favorites/hooks/usePrefetchedFavoritesFoldersData.ts b/packages/twenty-front/src/modules/favorites/hooks/usePrefetchedFavoritesFoldersData.ts index 32972ed05697..4c53d5dd8d64 100644 --- a/packages/twenty-front/src/modules/favorites/hooks/usePrefetchedFavoritesFoldersData.ts +++ b/packages/twenty-front/src/modules/favorites/hooks/usePrefetchedFavoritesFoldersData.ts @@ -1,13 +1,10 @@ import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState'; import { FavoriteFolder } from '@/favorites/types/FavoriteFolder'; -import { useUpsertRecordsInCacheForPrefetchKey } from '@/prefetch/hooks/internal/useUpsertRecordsInCacheForPrefetchKey'; -import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData'; -import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; +import { prefetchFavoriteFoldersState } from '@/prefetch/states/prefetchFavoriteFoldersState'; import { useRecoilValue } from 'recoil'; type PrefetchedFavoritesFoldersData = { favoriteFolders: FavoriteFolder[]; - upsertFavoriteFolders: (records: FavoriteFolder[]) => void; currentWorkspaceMemberId: string | undefined; }; @@ -16,23 +13,12 @@ export const usePrefetchedFavoritesFoldersData = const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); const currentWorkspaceMemberId = currentWorkspaceMember?.id; - const { records: favoriteFolders } = usePrefetchedData( - PrefetchKey.AllFavoritesFolders, - { - workspaceMemberId: { - eq: currentWorkspaceMemberId, - }, - }, + const prefetchFavoriteFolders = useRecoilValue( + prefetchFavoriteFoldersState, ); - const { upsertRecordsInCache: upsertFavoriteFolders } = - useUpsertRecordsInCacheForPrefetchKey({ - prefetchKey: PrefetchKey.AllFavoritesFolders, - }); - return { - favoriteFolders, - upsertFavoriteFolders, + favoriteFolders: prefetchFavoriteFolders, currentWorkspaceMemberId, }; }; diff --git a/packages/twenty-front/src/modules/object-record/hooks/useCreateOneRecord.ts b/packages/twenty-front/src/modules/object-record/hooks/useCreateOneRecord.ts index f4555f7e6b24..8f33b31d67f1 100644 --- a/packages/twenty-front/src/modules/object-record/hooks/useCreateOneRecord.ts +++ b/packages/twenty-front/src/modules/object-record/hooks/useCreateOneRecord.ts @@ -116,6 +116,7 @@ export const useCreateOneRecord = < objectMetadataItem, objectMetadataItems, record: recordCreatedInCache, + recordGqlFields: computedRecordGqlFields, computeReferences: false, }); diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainer.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainer.tsx index b8d784016d11..ad131b51cd08 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainer.tsx +++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainer.tsx @@ -15,8 +15,6 @@ import { RecordFieldValueSelectorContextProvider } from '@/object-record/record- import { SpreadsheetImportProvider } from '@/spreadsheet-import/provider/components/SpreadsheetImportProvider'; import { RecordIndexActionMenu } from '@/action-menu/components/RecordIndexActionMenu'; -import { ContextStoreCurrentViewTypeEffect } from '@/context-store/components/ContextStoreCurrentViewTypeEffect'; -import { ContextStoreViewType } from '@/context-store/types/ContextStoreViewType'; import { RecordIndexFiltersToContextStoreEffect } from '@/object-record/record-index/components/RecordIndexFiltersToContextStoreEffect'; import { RecordIndexTableContainerEffect } from '@/object-record/record-index/components/RecordIndexTableContainerEffect'; import { ViewBar } from '@/views/components/ViewBar'; @@ -55,13 +53,6 @@ export const RecordIndexContainer = () => { return ( <> - diff --git a/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexBoardColumn.ts b/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexBoardColumn.ts index e105cca850a4..d83eecfb79cd 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexBoardColumn.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexBoardColumn.ts @@ -6,13 +6,14 @@ import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords'; import { turnSortsIntoOrderBy } from '@/object-record/object-sort-dropdown/utils/turnSortsIntoOrderBy'; import { useSetRecordIdsForColumn } from '@/object-record/record-board/hooks/useSetRecordIdsForColumn'; import { useFilterValueDependencies } from '@/object-record/record-filter/hooks/useFilterValueDependencies'; +import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState'; import { computeViewRecordGqlOperationFilter } from '@/object-record/record-filter/utils/computeViewRecordGqlOperationFilter'; import { recordGroupDefinitionFamilyState } from '@/object-record/record-group/states/recordGroupDefinitionFamilyState'; import { useRecordBoardRecordGqlFields } from '@/object-record/record-index/hooks/useRecordBoardRecordGqlFields'; -import { recordIndexFiltersState } from '@/object-record/record-index/states/recordIndexFiltersState'; import { recordIndexSortsState } from '@/object-record/record-index/states/recordIndexSortsState'; import { recordIndexViewFilterGroupsState } from '@/object-record/record-index/states/recordIndexViewFilterGroupsState'; import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { isDefined } from 'twenty-shared'; type UseLoadRecordIndexBoardProps = { @@ -41,14 +42,16 @@ export const useLoadRecordIndexBoardColumn = ({ const recordIndexViewFilterGroups = useRecoilValue( recordIndexViewFilterGroupsState, ); - const recordIndexFilters = useRecoilValue(recordIndexFiltersState); + const currentRecordFilters = useRecoilComponentValueV2( + currentRecordFiltersComponentState, + ); const recordIndexSorts = useRecoilValue(recordIndexSortsState); const { filterValueDependencies } = useFilterValueDependencies(); const requestFilters = computeViewRecordGqlOperationFilter( filterValueDependencies, - recordIndexFilters, + currentRecordFilters, objectMetadataItem?.fields ?? [], recordIndexViewFilterGroups, ); diff --git a/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx b/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx index 4b9408308141..0e572e3ccf7f 100644 --- a/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx +++ b/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx @@ -3,8 +3,6 @@ import { ShowPageContainer } from '@/ui/layout/page/components/ShowPageContainer import { InformationBannerDeletedRecord } from '@/information-banner/components/deleted-record/InformationBannerDeletedRecord'; -import { ContextStoreCurrentViewTypeEffect } from '@/context-store/components/ContextStoreCurrentViewTypeEffect'; -import { ContextStoreViewType } from '@/context-store/types/ContextStoreViewType'; import { RecordShowContainerContextStoreTargetedRecordsEffect } from '@/object-record/record-show/components/RecordShowContainerContextStoreTargetedRecordsEffect'; import { useRecordShowContainerData } from '@/object-record/record-show/hooks/useRecordShowContainerData'; import { useRecordShowContainerTabs } from '@/object-record/record-show/hooks/useRecordShowContainerTabs'; @@ -47,9 +45,6 @@ export const RecordShowContainer = ({ - {recordFromStore && recordFromStore.deletedAt && ( { const currentUser = useRecoilValue(currentUserState); const isWorkspaceSuspended = useIsWorkspaceActivationStatusSuspended(); - const { upsertRecordsInCache: upsertFavoritesInCache } = - useUpsertRecordsInCacheForPrefetchKey({ - prefetchKey: PrefetchKey.AllFavorites, - }); - const { upsertRecordsInCache: upsertFavoritesFoldersInCache } = - useUpsertRecordsInCacheForPrefetchKey({ - prefetchKey: PrefetchKey.AllFavoritesFolders, - }); const { objectMetadataItems } = useObjectMetadataItems(); - const operationSignatures = Object.values(PREFETCH_CONFIG) + const setIsPrefetchFavoritesLoaded = useSetRecoilState( + prefetchIsLoadedFamilyState(PrefetchKey.AllFavorites), + ); - .map(({ objectNameSingular, operationSignatureFactory }) => { - const objectMetadataItem = objectMetadataItems.find( - (item) => item.nameSingular === objectNameSingular, - ); + const setIsPrefetchFavoritesFoldersLoaded = useSetRecoilState( + prefetchIsLoadedFamilyState(PrefetchKey.AllFavoritesFolders), + ); + + const findAllFavoritesOperationSignature = + findAllFavoritesOperationSignatureFactory({ + objectMetadataItem: objectMetadataItems.find( + (item) => item.nameSingular === CoreObjectNameSingular.Favorite, + ), + }); - return operationSignatureFactory({ objectMetadataItem }); + const findAllFavoriteFoldersOperationSignature = + findAllFavoritesFolderOperationSignatureFactory({ + objectMetadataItem: objectMetadataItems.find( + (item) => item.nameSingular === CoreObjectNameSingular.FavoriteFolder, + ), }); - const { result } = useCombinedFindManyRecords({ - operationSignatures, + 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(result.favorites)) { - upsertFavoritesInCache(result.favorites as Favorite[]); + if (isDefined(favorites)) { + setPrefetchFavoritesState(favorites as Favorite[]); + setIsPrefetchFavoritesLoaded(true); } - if (isDefined(result.favoriteFolders)) { - upsertFavoritesFoldersInCache(result.favoriteFolders as FavoriteFolder[]); + }, [favorites, setPrefetchFavoritesState, setIsPrefetchFavoritesLoaded]); + + useEffect(() => { + if (isDefined(favoriteFolders)) { + setPrefetchFavoriteFoldersState(favoriteFolders as FavoriteFolder[]); + setIsPrefetchFavoritesFoldersLoaded(true); } - }, [result, upsertFavoritesInCache, upsertFavoritesFoldersInCache]); + }, [ + favoriteFolders, + setPrefetchFavoriteFoldersState, + setIsPrefetchFavoritesFoldersLoaded, + ]); return <>; }; diff --git a/packages/twenty-front/src/modules/prefetch/hooks/internal/useUpsertRecordsInCacheForPrefetchKey.ts b/packages/twenty-front/src/modules/prefetch/hooks/internal/useUpsertRecordsInCacheForPrefetchKey.ts deleted file mode 100644 index 381166c1bbdb..000000000000 --- a/packages/twenty-front/src/modules/prefetch/hooks/internal/useUpsertRecordsInCacheForPrefetchKey.ts +++ /dev/null @@ -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 = ({ - 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, - }; -}; diff --git a/packages/twenty-front/src/modules/prefetch/hooks/usePrefetchedData.ts b/packages/twenty-front/src/modules/prefetch/hooks/usePrefetchedData.ts deleted file mode 100644 index 8ffd11478570..000000000000 --- a/packages/twenty-front/src/modules/prefetch/hooks/usePrefetchedData.ts +++ /dev/null @@ -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 = ( - 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({ - skip: !isDataPrefetched, - objectNameSingular: objectNameSingular, - recordGqlFields, - }); - - return { - isDataPrefetched, - records, - }; -}; diff --git a/packages/twenty-front/src/modules/prefetch/states/prefetchFavoriteFoldersState.ts b/packages/twenty-front/src/modules/prefetch/states/prefetchFavoriteFoldersState.ts new file mode 100644 index 000000000000..18ba7398f7c8 --- /dev/null +++ b/packages/twenty-front/src/modules/prefetch/states/prefetchFavoriteFoldersState.ts @@ -0,0 +1,7 @@ +import { FavoriteFolder } from '@/favorites/types/FavoriteFolder'; +import { createState } from 'twenty-ui'; + +export const prefetchFavoriteFoldersState = createState({ + key: 'prefetchFavoriteFoldersState', + defaultValue: [], +}); diff --git a/packages/twenty-front/src/modules/prefetch/states/prefetchFavoritesState.ts b/packages/twenty-front/src/modules/prefetch/states/prefetchFavoritesState.ts new file mode 100644 index 000000000000..e3143ab330c8 --- /dev/null +++ b/packages/twenty-front/src/modules/prefetch/states/prefetchFavoritesState.ts @@ -0,0 +1,7 @@ +import { Favorite } from '@/favorites/types/Favorite'; +import { createState } from 'twenty-ui'; + +export const prefetchFavoritesState = createState({ + key: 'prefetchFavoritesState', + defaultValue: [], +}); diff --git a/packages/twenty-front/src/pages/object-record/RecordShowPage.tsx b/packages/twenty-front/src/pages/object-record/RecordShowPage.tsx index e0f62e4bb8c4..c4626d4e3b93 100644 --- a/packages/twenty-front/src/pages/object-record/RecordShowPage.tsx +++ b/packages/twenty-front/src/pages/object-record/RecordShowPage.tsx @@ -51,7 +51,7 @@ export const RecordShowPage = () => { value={{ instanceId: `record-show-${objectRecordId}` }} >