From cfb0cce9b86f9d6f0a5e3fc0681f079cd4535a22 Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Wed, 20 Mar 2024 14:21:58 +0100 Subject: [PATCH] Refactor Views by cleaning the code, relying on apolloCache and improving performances (#4516) * Wip refactoring view * Post merge conflicts * Fix review * Add create view capability * Fix create object missing view * Fix tests --- package.json | 1 + packages/twenty-front/src/App.tsx | 2 +- .../effect-components/CommandMenuEffect.tsx | 2 +- .../effect-components/PageChangeEffect.tsx | 2 +- .../src/hooks/useDefaultHomePagePath.tsx | 2 +- packages/twenty-front/src/index.tsx | 5 + .../calendar/components/CalendarEventRow.tsx | 2 +- .../components/RightDrawerCalendarEvent.tsx | 4 +- .../useOpenCalendarEventRightDrawer.test.tsx | 4 +- .../hooks/useOpenCalendarEventRightDrawer.ts | 2 +- .../comment/__stories__/Comment.stories.tsx | 2 +- .../__stories__/CommentHeader.stories.tsx | 2 +- .../components/ActivityBodyEditor.tsx | 4 +- .../components/ActivityComments.tsx | 2 +- .../components/ActivityEditorEffect.tsx | 8 +- .../activities/components/ActivityTitle.tsx | 2 +- .../emails/components/EmailThreadPreview.tsx | 2 +- .../emails/components/EmailThreads.tsx | 4 +- .../hooks/__tests__/useEmailThread.test.tsx | 8 +- .../__tests__/useEmailThreadStates.test.ts | 2 +- .../hooks/internal/useEmailThreadStates.ts | 2 +- .../activities/emails/hooks/useEmailThread.ts | 8 +- .../components/RightDrawerEmailThread.tsx | 2 +- .../hooks/useRightDrawerEmailThread.ts | 2 +- .../files/hooks/useUploadAttachmentFile.tsx | 2 +- .../hooks/__tests__/useActivities.test.tsx | 2 +- .../useActivityConnectionUtils.test.tsx | 4 +- .../useActivityTargetObjectRecords.test.tsx | 4 +- ...ctivityTargetsForTargetableObject.test.tsx | 2 +- ...useAttachRelationInBothDirections.test.tsx | 4 +- .../useCreateActivityInCache.test.tsx | 4 +- .../useOpenActivityRightDrawer.test.tsx | 4 +- .../useOpenCreateActivityDrawer.test.tsx | 6 +- ...teActivityDrawerForSelectedRowIds.test.tsx | 6 +- .../__tests__/useUpsertActivity.test.tsx | 4 +- .../hooks/useActivityTargetObjectRecords.ts | 2 +- .../hooks/useCreateActivityInCache.ts | 2 +- .../hooks/useOpenActivityRightDrawer.ts | 4 +- .../hooks/useOpenCreateActivityDrawer.ts | 14 +- ...enCreateActivityDrawerForSelectedRowIds.ts | 6 +- .../activities/hooks/useUpsertActivity.ts | 6 +- .../ActivityTargetInlineCellEditMode.tsx | 4 +- .../components/ActivityActionBar.tsx | 16 +- .../create/RightDrawerCreateActivity.tsx | 2 +- .../edit/RightDrawerEditActivity.tsx | 2 +- .../CurrentUserDueTaskCountEffect.tsx | 4 +- .../tasks/components/TaskGroups.tsx | 4 +- .../tasks/hooks/useCurrentUserDueTaskCount.ts | 2 +- .../activities/tasks/hooks/useTasks.ts | 6 +- .../timeline/components/Timeline.tsx | 2 +- .../components/TimelineCreateButtonGroup.tsx | 4 +- .../components/TimelineItemsContainer.tsx | 2 +- .../components/TimelineQueryEffect.tsx | 4 +- .../analytics/hooks/useEventTracker.ts | 2 +- .../modules/apollo/hooks/useApolloFactory.ts | 4 +- .../triggerUpdateRelationsOptimisticEffect.ts | 218 ++++----- .../auth/hooks/__test__/useAuth.test.tsx | 14 +- .../auth/hooks/__test__/useIsLogged.test.ts | 2 +- .../__test__/useOnboardingStatus.test.ts | 10 +- .../src/modules/auth/hooks/useAuth.ts | 38 +- .../src/modules/auth/hooks/useIsLogged.ts | 4 +- .../modules/auth/hooks/useOnboardingStatus.ts | 6 +- .../sign-in-up/components/SignInUpForm.tsx | 2 +- .../hooks/useNavigateAfterSignInUp.ts | 2 +- .../auth/sign-in-up/hooks/useSignInUpForm.ts | 2 +- .../components/ClientConfigProvider.tsx | 16 +- .../command-menu/components/CommandMenu.tsx | 4 +- .../__stories__/CommandMenu.stories.tsx | 4 +- .../hooks/__test__/useCommandMenu.test.tsx | 2 +- .../command-menu/hooks/useCommandMenu.ts | 4 +- .../debug/components/ApolloDevLogEffect.tsx | 2 +- .../debug/components/RecoilDebugObserver.tsx | 2 +- .../components/SentryInitiEffect.tsx | 8 +- .../hooks/__tests__/useFavorites.test.tsx | 16 +- .../modules/favorites/hooks/useFavorites.ts | 2 +- .../components/AppNavigationDrawer.tsx | 4 +- .../components/MainNavigationDrawerItems.tsx | 6 +- .../components/MobileNavigationBar.tsx | 2 +- .../AppNavigationDrawer.stories.tsx | 2 +- .../ApolloMetadataClientProvider.tsx | 2 +- .../ObjectMetadataItemsLoadEffect.tsx | 2 +- .../ObjectMetadataItemsProvider.tsx | 4 +- ...rOutUnexistingObjectMetadataItems.test.tsx | 2 +- ...ectRecordIdentifierByNameSingular.test.tsx | 2 +- .../__tests__/useGetRelationMetadata.test.tsx | 2 +- .../useObjectMetadataItemForSettings.test.tsx | 6 +- .../hooks/useCreateOneObjectMetadataItem.ts | 5 +- ...GetObjectRecordIdentifierByNameSingular.ts | 2 +- .../hooks/useObjectMetadataItem.ts | 4 +- .../hooks/useObjectMetadataItemForSettings.ts | 2 +- .../hooks/useObjectMetadataItemOnly.ts | 4 +- .../hooks/useObjectMetadataItems.ts | 2 +- .../hooks/useObjectNamePluralFromSingular.ts | 2 +- .../hooks/useObjectNameSingularFromPlural.ts | 2 +- .../objectMetadataItemFamilySelector.ts | 2 +- ...ectMetadataItemsByNamePluralMapSelector.ts | 2 +- ...tMetadataItemsByNameSingularMapSelector.ts | 2 +- .../cache/hooks/useAddRecordInCache.ts | 2 +- .../cache/hooks/useGetRecordFromCache.ts | 42 +- .../cache/utils/getRecordEdgeFromRecord.ts | 3 +- .../__tests__/useFindManyRecords.test.tsx | 4 +- ...ordsForMultipleMetadataItemsQuery.test.tsx | 2 +- .../useMapConnectionToRecords.test.tsx | 2 +- .../object-record/hooks/useFindManyRecords.ts | 2 +- .../useGenerateCreateManyRecordMutation.ts | 2 +- .../useGenerateCreateOneRecordMutation.ts | 2 +- ...teExecuteQuickActionOnOneRecordMutation.ts | 2 +- .../useGenerateFindDuplicateRecordsQuery.ts | 2 +- ...anyRecordsForMultipleMetadataItemsQuery.ts | 12 +- .../hooks/useGenerateFindManyRecordsQuery.ts | 2 +- .../hooks/useGenerateFindOneRecordQuery.ts | 2 +- .../useGenerateUpdateOneRecordMutation.ts | 2 +- .../hooks/useMapConnectionToRecords.ts | 2 +- .../MultipleFiltersDropdownContent.tsx | 18 +- .../components/ObjectFilterDropdownButton.tsx | 9 +- .../ObjectFilterDropdownDateInput.tsx | 13 +- ...ObjectFilterDropdownEntitySearchSelect.tsx | 20 +- .../ObjectFilterDropdownFilterSelect.tsx | 8 +- .../ObjectFilterDropdownNumberInput.tsx | 12 +- .../ObjectFilterDropdownOperandButton.tsx | 13 +- .../ObjectFilterDropdownOperandSelect.tsx | 18 +- .../ObjectFilterDropdownOptionSelect.tsx | 22 +- .../ObjectFilterDropdownRecordSelect.tsx | 23 +- .../ObjectFilterDropdownSearchInput.tsx | 17 +- .../ObjectFilterDropdownTextSearchInput.tsx | 20 +- ...SingleEntityObjectFilterDropdownButton.tsx | 10 +- .../__tests__/useFilterDropdown.test.tsx | 188 ++++++-- .../hooks/useFilterDropdown.ts | 183 +++++--- .../hooks/useFilterDropdownStates.ts | 133 +++--- ...ailableFilterDefinitionsComponentState.ts} | 4 +- ...DefinitionUsedInDropdownComponentState.ts} | 4 +- ...downOperandSelectUnfoldedComponentState.ts | 7 + ...ctFilterDropdownUnfoldedComponentState.ts} | 2 +- ...ilterDropdownSearchInputComponentState.ts} | 4 +- ...DropdownSelectedEntityIdComponentState.ts} | 4 +- ...downSelectedOptionValuesComponentState.ts} | 4 +- ...ropdownSelectedRecordIdsComponentState.ts} | 4 +- ...ate.ts => onFilterSelectComponentState.ts} | 4 +- ...ate.ts => selectedFilterComponentState.ts} | 4 +- ...electedOperandInDropdownComponentState.ts} | 4 +- .../components/ObjectSortDropdownButton.tsx | 11 +- .../hooks/__tests__/useSortDropdown.test.tsx | 67 ++- .../hooks/useSortDropdown.ts | 18 +- .../hooks/useSortDropdownStates.ts | 34 +- ...availableSortDefinitionsComponentState.ts} | 4 +- .../states/isSortSelectedScopedState.ts | 4 +- .../states/onSortSelectScopedState.ts | 4 +- .../__tests__/turnSortsIntoOrderBy.test.tsx | 8 +- .../utils/turnSortsIntoOrderBy.ts | 23 +- .../hooks/useRecordActionBar.tsx | 4 +- .../components/RecordBoardActionBar.tsx | 4 +- .../record-board/components/RecordBoard.tsx | 4 +- .../components/RecordBoardContextMenu.tsx | 4 +- .../hooks/internal/useRecordBoardStates.ts | 23 +- .../internal/useSetRecordBoardColumns.ts | 8 +- .../internal/useSetRecordBoardRecordIds.ts | 6 +- .../record-board/hooks/useRecordBoard.ts | 20 +- .../hooks/useRecordBoardSelection.ts | 6 +- .../components/RecordBoardCard.tsx | 16 +- .../RecordBoardColumnFetchMoreLoader.tsx | 8 +- .../record-field/hooks/useClearField.ts | 2 +- .../RelationFieldInput.stories.tsx | 4 +- ...turnObjectDropdownFilterIntoQueryFilter.ts | 6 +- .../RecordIndexBoardContainerEffect.tsx | 10 +- .../components/RecordIndexContainer.tsx | 51 +- .../RecordIndexTableContainerEffect.tsx | 15 +- .../components/RecordIndexViewBarEffect.tsx | 4 +- .../hooks/useLoadRecordIndexBoard.ts | 25 +- .../hooks/useLoadRecordIndexTable.ts | 12 +- .../components/RecordIndexOptionsDropdown.tsx | 40 +- .../RecordIndexOptionsDropdownContent.tsx | 36 +- .../options/hooks/useExportTableData.ts | 6 +- .../hooks/useRecordIndexOptionsForBoard.ts | 39 +- .../hooks/useRecordIndexOptionsForTable.ts | 6 +- .../RecordDetailRelationSection.tsx | 2 +- .../recordStoreIdentifierSelector.ts | 2 +- .../components/RecordTableActionBar.tsx | 4 +- .../record-table/components/CheckboxCell.tsx | 2 +- .../record-table/components/ColumnHead.tsx | 2 +- .../record-table/components/RecordTable.tsx | 2 +- .../components/RecordTableBody.tsx | 4 +- .../components/RecordTableBodyEffect.tsx | 4 +- .../components/RecordTableCellContainer.tsx | 4 +- .../RecordTableColumnDropdownMenu.tsx | 4 +- .../components/RecordTableHeader.tsx | 7 +- .../components/RecordTableHeaderCell.tsx | 15 +- .../RecordTableHeaderPlusButtonContent.tsx | 4 +- .../components/RecordTableRow.tsx | 4 +- .../components/RecordTableWithWrappers.tsx | 14 +- .../components/SelectAllCheckbox.tsx | 6 +- .../components/RecordTableContextMenu.tsx | 4 +- .../useCloseCurrentTableCellInEditMode.ts | 9 +- .../hooks/internal/useDisableSoftFocus.ts | 12 +- .../internal/useGetIsSomeCellInEditMode.ts | 9 +- .../hooks/internal/useLeaveTableFocus.ts | 8 +- .../internal/useMoveEditModeToCellPosition.ts | 11 +- .../hooks/internal/useRecordTableStates.ts | 44 +- .../internal/useResetTableRowSelection.ts | 6 +- .../hooks/internal/useSelectAllRows.ts | 14 +- .../hooks/internal/useSetRecordTableData.ts | 10 +- .../hooks/internal/useSetSoftFocusPosition.ts | 14 +- .../record-table/hooks/useRecordTable.ts | 58 ++- .../hooks/useRecordTableMoveFocus.ts | 44 +- .../record-table/hooks/useTableColumns.ts | 19 +- .../components/RecordTableCellContainer.tsx | 2 +- .../RecordTableCellSoftFocusMode.tsx | 2 +- .../useCloseRecordTableCell.test.tsx | 4 +- ...MoveSoftFocusToCurrentCellOnHover.test.tsx | 6 +- .../useMoveSoftFocusToCurrentCellOnHover.ts | 8 +- .../hooks/useSetSoftFocus.ts | 6 +- ...attedAsObjectRecordForSelectArray.test.tsx | 2 +- .../__tests__/useMultiObjectSearch.test.tsx | 2 +- ...atchesSearchFilterAndSelectedItemsQuery.ts | 4 +- ...archMatchesSearchFilterAndToSelectQuery.ts | 4 +- .../useMultiObjectSearchSelectedItemsQuery.ts | 4 +- .../useSpreadsheetRecordImport.test.tsx | 2 +- .../components/PrefetchRunQueriesEffect.tsx | 19 +- .../useFilteredSearchEntityQuery.test.tsx | 4 +- ...ttingsAccountsCalendarAccountsListCard.tsx | 2 +- ...SettingsAccountsEmailsAccountsListCard.tsx | 2 +- ...SettingsAccountsEmailsBlocklistSection.tsx | 2 +- .../SettingsNavigationDrawerItems.tsx | 2 +- .../profile/components/ChangePassword.tsx | 2 +- .../profile/components/DeleteAccount.tsx | 2 +- .../profile/components/DeleteWorkspace.tsx | 2 +- .../profile/components/EmailField.tsx | 2 +- .../profile/components/NameFields.tsx | 4 +- .../components/ProfilePictureUploader.tsx | 2 +- .../workspace/components/NameField.tsx | 2 +- .../components/ToggleImpersonate.tsx | 2 +- .../components/WorkspaceLogoUploader.tsx | 2 +- .../SignInBackgroundMockContainer.tsx | 1 + .../SignInBackgroundMockContainerEffect.tsx | 13 +- .../__tests__/useSpreadsheetImport.test.tsx | 2 +- .../hooks/useSpreadsheetImport.ts | 2 +- .../components/SpreadsheetImportProvider.tsx | 2 +- .../support/components/SupportChat.tsx | 6 +- .../display/icon/components/IconsProvider.tsx | 2 +- .../modules/ui/display/icon/hooks/useIcons.ts | 2 +- .../modules/ui/input/hooks/useIconPicker.ts | 2 +- .../dropdown/components/DropdownMenuInput.tsx | 3 +- .../useInternalHotkeyScopeManagement.test.tsx | 2 +- .../ui/layout/dropdown/hooks/useDropdown.ts | 10 +- .../hooks/useInternalHotkeyScopeManagement.ts | 2 +- .../right-drawer/components/RightDrawer.tsx | 10 +- .../components/RightDrawerRouter.tsx | 2 +- .../RightDrawerTopBarExpandButton.tsx | 2 +- .../hooks/__tests__/useRightDrawer.test.tsx | 8 +- .../right-drawer/hooks/useRightDrawer.ts | 16 +- .../hooks/__tests__/useSelectableList.test.ts | 7 +- .../internal/useSelectableListHotKeys.tsx | 13 +- .../hooks/useSelectableList.ts | 6 +- .../components/ShowPageMoreButton.tsx | 2 +- .../components/ShowPageRightContainer.tsx | 4 +- .../ui/layout/tab/components/TabList.tsx | 4 +- .../tab/hooks/__tests__/useTabList.test.tsx | 6 +- .../tab/hooks/internal/useTabListStates.ts | 5 +- .../modules/ui/layout/tab/hooks/useTabList.ts | 6 +- .../action-bar/components/ActionBar.tsx | 4 +- .../__stories__/ActionBar.stories.tsx | 2 +- .../context-menu/components/ContextMenu.tsx | 8 +- .../__stories__/ContextMenu.stories.tsx | 4 +- .../menu-item/components/MenuItemToggle.tsx | 6 +- .../components/StyledMenuItemBase.tsx | 2 + .../components/NavigationDrawerBackButton.tsx | 2 +- .../hooks/__tests__/useStepBar.test.tsx | 2 +- .../navigation/step-bar/hooks/useStepBar.ts | 5 +- .../hooks/__tests__/useColorScheme.test.tsx | 2 +- .../modules/ui/theme/hooks/useColorScheme.ts | 2 +- .../hotkey/hooks/usePreviousHotkeyScope.ts | 8 +- .../hotkey/hooks/useScopedHotkeyCallback.ts | 2 +- .../hotkey/hooks/useScopedHotkeys.ts | 3 +- .../hotkey/hooks/useSequenceScopedHotkeys.ts | 3 +- .../hotkey/hooks/useSetHotkeyScope.ts | 6 +- .../useClickOutsideListener.test.tsx | 4 +- .../hooks/useClickOutsideListener.ts | 14 +- .../hooks/useListenClickOutsideV2.ts | 8 +- .../utils/getScopedFamilyStateDeprecated.ts | 19 - .../utils/getScopedSelectorDeprecated.ts | 10 - .../hooks/__tests__/useListenScroll.test.tsx | 2 +- .../utilities/scroll/hooks/useListenScroll.ts | 10 +- .../utils/extractComponentState.ts | 2 +- .../ui/utilities/state/utils/createState.ts | 2 +- .../modules/users/components/UserProvider.tsx | 6 +- .../views/components/EditableFilterChip.tsx | 4 +- .../EditableFilterDropdownButton.tsx | 21 +- .../views/components/EditableSortChip.tsx | 13 +- .../components/FilterQueryParamsEffect.tsx | 43 +- .../components/UpdateViewButtonGroup.tsx | 20 +- .../src/modules/views/components/ViewBar.tsx | 42 +- .../views/components/ViewBarDetails.tsx | 79 ++-- .../views/components/ViewBarEffect.tsx | 117 ++--- .../views/components/ViewBarFilterEffect.tsx | 40 +- .../views/components/ViewBarSortEffect.tsx | 34 +- .../views/components/ViewsDropdownButton.tsx | 59 +-- .../src/modules/views/constants/index.ts | 2 - .../views/hooks/__tests__/useViewBar.test.tsx | 238 +--------- .../__tests__/useViewBar_ViewFields.test.tsx | 170 ------- .../__tests__/useViewBar_ViewFilters.test.tsx | 178 ------- .../__tests__/useViewBar_ViewSorts.test.tsx | 165 ------- .../internal/usePersistViewFieldRecords.ts | 115 +++++ .../internal/usePersistViewFilterRecords.ts | 156 +++++++ .../internal/usePersistViewSortRecords.ts | 151 ++++++ .../views/hooks/internal/useViewFields.ts | 160 ------- .../views/hooks/internal/useViewFilters.ts | 246 ---------- ...eryParams.ts => useViewFromQueryParams.ts} | 34 +- .../hooks/internal/useViewScopedStates.ts | 90 ---- .../views/hooks/internal/useViewSorts.ts | 236 ---------- .../views/hooks/internal/useViewStates.ts | 96 ++++ .../modules/views/hooks/internal/useViews.ts | 80 ---- .../views/hooks/useCombinedViewFilters.ts | 158 +++++++ .../views/hooks/useCombinedViewSorts.ts | 159 +++++++ .../modules/views/hooks/useGetCurrentView.ts | 107 +++++ .../views/hooks/useGetViewFromCache.ts | 48 ++ .../src/modules/views/hooks/useHandleViews.ts | 130 ++++++ .../src/modules/views/hooks/useInitViewBar.ts | 31 ++ .../views/hooks/useResetCurrentView.ts | 32 ++ .../views/hooks/useSaveCurrentViewFields.ts | 87 ++++ .../useSaveCurrentViewFiltersAndSorts.ts | 147 ++++++ .../hooks/useSetRecordCountInCurrentView.ts | 15 + .../src/modules/views/hooks/useViewBar.ts | 441 ------------------ .../modules/views/hooks/useViewBarEditMode.ts | 14 + .../src/modules/views/scopes/ViewScope.tsx | 26 +- .../init-effect/ViewScopeInitEffect.tsx | 56 +-- ...vailableFieldDefinitionsComponentState.ts} | 4 +- ...ailableFilterDefinitionsComponentState.ts} | 4 +- ...availableSortDefinitionsComponentState.ts} | 4 +- .../currentViewFieldsScopedFamilyState.ts | 11 - .../currentViewFiltersScopedFamilyState.ts | 11 - ...tate.ts => currentViewIdComponentState.ts} | 4 +- .../currentViewSortsScopedFamilyState.ts | 11 - .../entityCountInCurrentViewComponentState.ts | 7 + .../entityCountInCurrentViewScopedState.ts | 8 - .../isCurrentViewIndexComponentState.ts | 7 + .../isPersistingViewFieldsComponentState.ts} | 4 +- .../states/isPersistingViewScopedState.ts | 6 - ....ts => isViewBarExpandedComponentState.ts} | 4 +- .../views/states/noneScopedFamilyState.ts | 6 - .../onCurrentViewChangeComponentState.ts | 9 + .../onViewCompactModeChangeScopeState.ts | 8 - .../states/onViewFieldsChangeScopedState.ts | 10 - .../states/onViewFiltersChangeScopedState.ts | 9 - .../states/onViewSortsChangeScopedState.ts | 9 - .../states/onViewTypeChangeScopedState.ts | 9 - .../savedViewFieldsScopedFamilyState.ts | 11 - .../savedViewFiltersScopedFamilyState.ts | 11 - .../states/savedViewSortsScopedFamilyState.ts | 11 - .../canPersistViewComponentSelector.ts | 21 + ...nPersistViewFiltersScopedFamilySelector.ts | 32 -- ...canPersistViewSortsScopedFamilySelector.ts | 31 -- .../canResetViewComponentSelector.ts | 22 + .../selectors/currentViewComponentSelector.ts | 21 - ...savedViewFieldByKeyScopedFamilySelector.ts | 32 -- ...vedViewFiltersByKeyScopedFamilySelector.ts | 25 - ...savedViewSortsByKeyScopedFamilySelector.ts | 25 - .../selectors/savedViewSortsFamilySelector.ts | 16 - .../selectors/viewsByIdScopedSelector.ts | 18 - ...avedToDeleteViewFilterIdsComponentState.ts | 8 + ...nsavedToDeleteViewSortIdsComponentState.ts | 8 + ...nsavedToUpsertViewFiltersComponentState.ts | 10 + .../unsavedToUpsertViewSortsComponentState.ts | 10 + ...State.ts => viewEditModeComponentState.ts} | 4 +- ... => viewObjectMetadataIdComponentState.ts} | 4 +- .../views/states/viewTypeScopedState.ts | 8 - .../modules/views/states/viewsScopedState.ts | 7 - .../src/modules/views/types/ViewField.ts | 1 + .../src/modules/views/types/ViewFilter.ts | 7 +- .../src/modules/views/types/ViewSort.ts | 3 +- .../utils/__tests__/viewMapFunctions.test.ts | 36 +- .../views/utils/combinedViewFilters.ts | 34 ++ .../modules/views/utils/combinedViewSorts.ts | 34 ++ .../getViewScopedStateValuesFromSnapshot.ts | 115 ----- .../utils/getViewScopedStatesFromSnapshot.ts | 87 ---- .../utils/internal/getViewScopedStates.ts | 225 --------- .../mapBoardFieldDefinitionsToViewFields.ts | 5 +- .../utils/mapColumnDefinitionToViewField.ts | 1 + .../views/utils/mapViewFiltersToFilters.ts | 30 +- .../views/utils/mapViewSortsToSorts.ts | 29 +- .../workspace/hooks/useIsFeatureEnabled.ts | 2 +- .../src/pages/auth/ChooseYourPlan.tsx | 2 +- .../src/pages/auth/CreateProfile.tsx | 2 +- .../src/pages/auth/VerifyEffect.tsx | 2 +- .../__stories__/CreateWorkspace.stories.tsx | 2 +- .../pages/impersonate/ImpersonateEffect.tsx | 4 +- .../object-record/RecordIndexPageHeader.tsx | 2 +- .../settings/SettingsWorkspaceMembers.tsx | 4 +- .../settings/accounts/SettingsAccounts.tsx | 2 +- .../accounts/SettingsAccountsCalendars.tsx | 2 +- .../src/pages/tasks/TasksEffect.tsx | 2 +- .../ObjectMetadataItemsDecorator.tsx | 4 +- .../timeline-calendar-event.service.ts | 2 +- yarn.lock | 8 + 392 files changed, 3474 insertions(+), 4410 deletions(-) rename packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/{availableFilterDefinitionsScopedState.ts => availableFilterDefinitionsComponentState.ts} (66%) rename packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/{filterDefinitionUsedInDropdownScopedState.ts => filterDefinitionUsedInDropdownComponentState.ts} (67%) create mode 100644 packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/isObjectFilterDropdownOperandSelectUnfoldedComponentState.ts rename packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/{isObjectFilterDropdownUnfoldedScopedState.ts => isObjectFilterDropdownUnfoldedComponentState.ts} (78%) rename packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/{objectFilterDropdownSearchInputScopedState.ts => objectFilterDropdownSearchInputComponentState.ts} (58%) rename packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/{objectFilterDropdownSelectedEntityIdScopedState.ts => objectFilterDropdownSelectedEntityIdComponentState.ts} (57%) rename packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/{objectFilterDropdownSelectedRecordIdsScopedState.ts => objectFilterDropdownSelectedOptionValuesComponentState.ts} (55%) rename packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/{objectFilterDropdownSelectedOptionValuesScopedState.ts => objectFilterDropdownSelectedRecordIdsComponentState.ts} (57%) rename packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/{onFilterSelectScopedState.ts => onFilterSelectComponentState.ts} (68%) rename packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/{selectedFilterScopedState.ts => selectedFilterComponentState.ts} (66%) rename packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/{selectedOperandInDropdownScopedState.ts => selectedOperandInDropdownComponentState.ts} (70%) rename packages/twenty-front/src/modules/object-record/object-sort-dropdown/states/{availableSortDefinitionsScopedState.ts => availableSortDefinitionsComponentState.ts} (62%) delete mode 100644 packages/twenty-front/src/modules/ui/utilities/recoil-scope/utils/getScopedFamilyStateDeprecated.ts delete mode 100644 packages/twenty-front/src/modules/ui/utilities/recoil-scope/utils/getScopedSelectorDeprecated.ts delete mode 100644 packages/twenty-front/src/modules/views/constants/index.ts delete mode 100644 packages/twenty-front/src/modules/views/hooks/__tests__/useViewBar_ViewFields.test.tsx delete mode 100644 packages/twenty-front/src/modules/views/hooks/__tests__/useViewBar_ViewFilters.test.tsx delete mode 100644 packages/twenty-front/src/modules/views/hooks/__tests__/useViewBar_ViewSorts.test.tsx create mode 100644 packages/twenty-front/src/modules/views/hooks/internal/usePersistViewFieldRecords.ts create mode 100644 packages/twenty-front/src/modules/views/hooks/internal/usePersistViewFilterRecords.ts create mode 100644 packages/twenty-front/src/modules/views/hooks/internal/usePersistViewSortRecords.ts delete mode 100644 packages/twenty-front/src/modules/views/hooks/internal/useViewFields.ts delete mode 100644 packages/twenty-front/src/modules/views/hooks/internal/useViewFilters.ts rename packages/twenty-front/src/modules/views/hooks/internal/{useFiltersFromQueryParams.ts => useViewFromQueryParams.ts} (89%) delete mode 100644 packages/twenty-front/src/modules/views/hooks/internal/useViewScopedStates.ts delete mode 100644 packages/twenty-front/src/modules/views/hooks/internal/useViewSorts.ts create mode 100644 packages/twenty-front/src/modules/views/hooks/internal/useViewStates.ts delete mode 100644 packages/twenty-front/src/modules/views/hooks/internal/useViews.ts create mode 100644 packages/twenty-front/src/modules/views/hooks/useCombinedViewFilters.ts create mode 100644 packages/twenty-front/src/modules/views/hooks/useCombinedViewSorts.ts create mode 100644 packages/twenty-front/src/modules/views/hooks/useGetCurrentView.ts create mode 100644 packages/twenty-front/src/modules/views/hooks/useGetViewFromCache.ts create mode 100644 packages/twenty-front/src/modules/views/hooks/useHandleViews.ts create mode 100644 packages/twenty-front/src/modules/views/hooks/useInitViewBar.ts create mode 100644 packages/twenty-front/src/modules/views/hooks/useResetCurrentView.ts create mode 100644 packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFields.ts create mode 100644 packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFiltersAndSorts.ts create mode 100644 packages/twenty-front/src/modules/views/hooks/useSetRecordCountInCurrentView.ts delete mode 100644 packages/twenty-front/src/modules/views/hooks/useViewBar.ts create mode 100644 packages/twenty-front/src/modules/views/hooks/useViewBarEditMode.ts rename packages/twenty-front/src/modules/views/states/{availableFieldDefinitionsScopedState.ts => availableFieldDefinitionsComponentState.ts} (72%) rename packages/twenty-front/src/modules/views/states/{availableFilterDefinitionsScopedState.ts => availableFilterDefinitionsComponentState.ts} (66%) rename packages/twenty-front/src/modules/views/states/{availableSortDefinitionsScopedState.ts => availableSortDefinitionsComponentState.ts} (66%) delete mode 100644 packages/twenty-front/src/modules/views/states/currentViewFieldsScopedFamilyState.ts delete mode 100644 packages/twenty-front/src/modules/views/states/currentViewFiltersScopedFamilyState.ts rename packages/twenty-front/src/modules/views/states/{currentViewIdScopedState.ts => currentViewIdComponentState.ts} (60%) delete mode 100644 packages/twenty-front/src/modules/views/states/currentViewSortsScopedFamilyState.ts create mode 100644 packages/twenty-front/src/modules/views/states/entityCountInCurrentViewComponentState.ts delete mode 100644 packages/twenty-front/src/modules/views/states/entityCountInCurrentViewScopedState.ts create mode 100644 packages/twenty-front/src/modules/views/states/isCurrentViewIndexComponentState.ts rename packages/twenty-front/src/modules/{object-record/object-filter-dropdown/states/isObjectFilterDropdownOperandSelectUnfoldedScopedState.ts => views/states/isPersistingViewFieldsComponentState.ts} (55%) delete mode 100644 packages/twenty-front/src/modules/views/states/isPersistingViewScopedState.ts rename packages/twenty-front/src/modules/views/states/{isViewBarExpandedScopedState.ts => isViewBarExpandedComponentState.ts} (51%) delete mode 100644 packages/twenty-front/src/modules/views/states/noneScopedFamilyState.ts create mode 100644 packages/twenty-front/src/modules/views/states/onCurrentViewChangeComponentState.ts delete mode 100644 packages/twenty-front/src/modules/views/states/onViewCompactModeChangeScopeState.ts delete mode 100644 packages/twenty-front/src/modules/views/states/onViewFieldsChangeScopedState.ts delete mode 100644 packages/twenty-front/src/modules/views/states/onViewFiltersChangeScopedState.ts delete mode 100644 packages/twenty-front/src/modules/views/states/onViewSortsChangeScopedState.ts delete mode 100644 packages/twenty-front/src/modules/views/states/onViewTypeChangeScopedState.ts delete mode 100644 packages/twenty-front/src/modules/views/states/savedViewFieldsScopedFamilyState.ts delete mode 100644 packages/twenty-front/src/modules/views/states/savedViewFiltersScopedFamilyState.ts delete mode 100644 packages/twenty-front/src/modules/views/states/savedViewSortsScopedFamilyState.ts create mode 100644 packages/twenty-front/src/modules/views/states/selectors/canPersistViewComponentSelector.ts delete mode 100644 packages/twenty-front/src/modules/views/states/selectors/canPersistViewFiltersScopedFamilySelector.ts delete mode 100644 packages/twenty-front/src/modules/views/states/selectors/canPersistViewSortsScopedFamilySelector.ts create mode 100644 packages/twenty-front/src/modules/views/states/selectors/canResetViewComponentSelector.ts delete mode 100644 packages/twenty-front/src/modules/views/states/selectors/currentViewComponentSelector.ts delete mode 100644 packages/twenty-front/src/modules/views/states/selectors/savedViewFieldByKeyScopedFamilySelector.ts delete mode 100644 packages/twenty-front/src/modules/views/states/selectors/savedViewFiltersByKeyScopedFamilySelector.ts delete mode 100644 packages/twenty-front/src/modules/views/states/selectors/savedViewSortsByKeyScopedFamilySelector.ts delete mode 100644 packages/twenty-front/src/modules/views/states/selectors/savedViewSortsFamilySelector.ts delete mode 100644 packages/twenty-front/src/modules/views/states/selectors/viewsByIdScopedSelector.ts create mode 100644 packages/twenty-front/src/modules/views/states/unsavedToDeleteViewFilterIdsComponentState.ts create mode 100644 packages/twenty-front/src/modules/views/states/unsavedToDeleteViewSortIdsComponentState.ts create mode 100644 packages/twenty-front/src/modules/views/states/unsavedToUpsertViewFiltersComponentState.ts create mode 100644 packages/twenty-front/src/modules/views/states/unsavedToUpsertViewSortsComponentState.ts rename packages/twenty-front/src/modules/views/states/{viewEditModeScopedState.ts => viewEditModeComponentState.ts} (62%) rename packages/twenty-front/src/modules/views/states/{viewObjectMetadataIdScopeState.ts => viewObjectMetadataIdComponentState.ts} (57%) delete mode 100644 packages/twenty-front/src/modules/views/states/viewTypeScopedState.ts delete mode 100644 packages/twenty-front/src/modules/views/states/viewsScopedState.ts create mode 100644 packages/twenty-front/src/modules/views/utils/combinedViewFilters.ts create mode 100644 packages/twenty-front/src/modules/views/utils/combinedViewSorts.ts delete mode 100644 packages/twenty-front/src/modules/views/utils/getViewScopedStateValuesFromSnapshot.ts delete mode 100644 packages/twenty-front/src/modules/views/utils/getViewScopedStatesFromSnapshot.ts delete mode 100644 packages/twenty-front/src/modules/views/utils/internal/getViewScopedStates.ts diff --git a/package.json b/package.json index b99715b829..da21618c97 100644 --- a/package.json +++ b/package.json @@ -108,6 +108,7 @@ "libphonenumber-js": "^1.10.26", "lodash.camelcase": "^4.3.0", "lodash.debounce": "^4.0.8", + "lodash.groupby": "^4.6.0", "lodash.isempty": "^4.4.0", "lodash.isequal": "^4.5.0", "lodash.isobject": "^3.0.2", diff --git a/packages/twenty-front/src/App.tsx b/packages/twenty-front/src/App.tsx index 81b665165c..71f0e211c8 100644 --- a/packages/twenty-front/src/App.tsx +++ b/packages/twenty-front/src/App.tsx @@ -47,7 +47,7 @@ import { SettingsWorkspaceMembers } from '~/pages/settings/SettingsWorkspaceMemb import { Tasks } from '~/pages/tasks/Tasks'; export const App = () => { - const billing = useRecoilValue(billingState()); + const billing = useRecoilValue(billingState); return ( <> diff --git a/packages/twenty-front/src/effect-components/CommandMenuEffect.tsx b/packages/twenty-front/src/effect-components/CommandMenuEffect.tsx index 7803c81032..ece319312e 100644 --- a/packages/twenty-front/src/effect-components/CommandMenuEffect.tsx +++ b/packages/twenty-front/src/effect-components/CommandMenuEffect.tsx @@ -5,7 +5,7 @@ import { COMMAND_MENU_COMMANDS } from '@/command-menu/constants/CommandMenuComma import { commandMenuCommandsState } from '@/command-menu/states/commandMenuCommandsState'; export const CommandMenuEffect = () => { - const setCommands = useSetRecoilState(commandMenuCommandsState()); + const setCommands = useSetRecoilState(commandMenuCommandsState); const commands = COMMAND_MENU_COMMANDS; useEffect(() => { diff --git a/packages/twenty-front/src/effect-components/PageChangeEffect.tsx b/packages/twenty-front/src/effect-components/PageChangeEffect.tsx index 65c57eefac..2cf692c3e3 100644 --- a/packages/twenty-front/src/effect-components/PageChangeEffect.tsx +++ b/packages/twenty-front/src/effect-components/PageChangeEffect.tsx @@ -45,7 +45,7 @@ export const PageChangeEffect = () => { const openCreateActivity = useOpenCreateActivityDrawer(); - const isSignUpDisabled = useRecoilValue(isSignUpDisabledState()); + const isSignUpDisabled = useRecoilValue(isSignUpDisabledState); useEffect(() => { if (!previousLocation || previousLocation !== location.pathname) { diff --git a/packages/twenty-front/src/hooks/useDefaultHomePagePath.tsx b/packages/twenty-front/src/hooks/useDefaultHomePagePath.tsx index c0f3327917..8ed52fe8cf 100644 --- a/packages/twenty-front/src/hooks/useDefaultHomePagePath.tsx +++ b/packages/twenty-front/src/hooks/useDefaultHomePagePath.tsx @@ -13,7 +13,7 @@ export const useDefaultHomePagePath = () => { const companyViewId = records.find( (view: any) => view?.objectMetadataId === companyObjectMetadataItem.id, - )?.node.id; + )?.id; const defaultHomePagePath = '/objects/companies' + (companyViewId ? `?view=${companyViewId}` : ''); diff --git a/packages/twenty-front/src/index.tsx b/packages/twenty-front/src/index.tsx index c23babc438..ac59cf8827 100644 --- a/packages/twenty-front/src/index.tsx +++ b/packages/twenty-front/src/index.tsx @@ -2,6 +2,7 @@ import { StrictMode } from 'react'; import ReactDOM from 'react-dom/client'; import { HelmetProvider } from 'react-helmet-async'; import { BrowserRouter } from 'react-router-dom'; +import { loadDevMessages, loadErrorMessages } from '@apollo/client/dev'; import { RecoilRoot } from 'recoil'; import { ApolloProvider } from '@/apollo/components/ApolloProvider'; @@ -33,6 +34,10 @@ import 'react-loading-skeleton/dist/skeleton.css'; const root = ReactDOM.createRoot(document.getElementById('root')!); +// Adds messages only in a dev environment +loadDevMessages(); +loadErrorMessages(); + root.render( diff --git a/packages/twenty-front/src/modules/activities/calendar/components/CalendarEventRow.tsx b/packages/twenty-front/src/modules/activities/calendar/components/CalendarEventRow.tsx index da0c22a72d..8ea22bc6db 100644 --- a/packages/twenty-front/src/modules/activities/calendar/components/CalendarEventRow.tsx +++ b/packages/twenty-front/src/modules/activities/calendar/components/CalendarEventRow.tsx @@ -102,7 +102,7 @@ export const CalendarEventRow = ({ className, }: CalendarEventRowProps) => { const theme = useTheme(); - const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState()); + const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); const { displayCurrentEventCursor = false } = useContext(CalendarContext); const { openCalendarEventRightDrawer } = useOpenCalendarEventRightDrawer(); diff --git a/packages/twenty-front/src/modules/activities/calendar/right-drawer/components/RightDrawerCalendarEvent.tsx b/packages/twenty-front/src/modules/activities/calendar/right-drawer/components/RightDrawerCalendarEvent.tsx index 2a60859646..845885e7cd 100644 --- a/packages/twenty-front/src/modules/activities/calendar/right-drawer/components/RightDrawerCalendarEvent.tsx +++ b/packages/twenty-front/src/modules/activities/calendar/right-drawer/components/RightDrawerCalendarEvent.tsx @@ -9,10 +9,10 @@ import { useSetRecordInStore } from '@/object-record/record-store/hooks/useSetRe export const RightDrawerCalendarEvent = () => { const { setRecords } = useSetRecordInStore(); - const calendarEventId = useRecoilValue(viewableCalendarEventIdState()); + const viewableCalendarEventId = useRecoilValue(viewableCalendarEventIdState); const { record: calendarEvent } = useFindOneRecord({ objectNameSingular: CoreObjectNameSingular.CalendarEvent, - objectRecordId: calendarEventId ?? '', + objectRecordId: viewableCalendarEventId ?? '', onCompleted: (record) => setRecords([record]), }); diff --git a/packages/twenty-front/src/modules/activities/calendar/right-drawer/hooks/__tests__/useOpenCalendarEventRightDrawer.test.tsx b/packages/twenty-front/src/modules/activities/calendar/right-drawer/hooks/__tests__/useOpenCalendarEventRightDrawer.test.tsx index 04544ed53b..027f7f8755 100644 --- a/packages/twenty-front/src/modules/activities/calendar/right-drawer/hooks/__tests__/useOpenCalendarEventRightDrawer.test.tsx +++ b/packages/twenty-front/src/modules/activities/calendar/right-drawer/hooks/__tests__/useOpenCalendarEventRightDrawer.test.tsx @@ -9,9 +9,9 @@ describe('useOpenCalendarEventRightDrawer', () => { it('opens the right drawer with the calendar event', () => { const { result } = renderHook( () => { - const isRightDrawerOpen = useRecoilValue(isRightDrawerOpenState()); + const isRightDrawerOpen = useRecoilValue(isRightDrawerOpenState); const viewableCalendarEventId = useRecoilValue( - viewableCalendarEventIdState(), + viewableCalendarEventIdState, ); return { ...useOpenCalendarEventRightDrawer(), diff --git a/packages/twenty-front/src/modules/activities/calendar/right-drawer/hooks/useOpenCalendarEventRightDrawer.ts b/packages/twenty-front/src/modules/activities/calendar/right-drawer/hooks/useOpenCalendarEventRightDrawer.ts index ccf3e4fce5..9cd27d017e 100644 --- a/packages/twenty-front/src/modules/activities/calendar/right-drawer/hooks/useOpenCalendarEventRightDrawer.ts +++ b/packages/twenty-front/src/modules/activities/calendar/right-drawer/hooks/useOpenCalendarEventRightDrawer.ts @@ -10,7 +10,7 @@ export const useOpenCalendarEventRightDrawer = () => { const { openRightDrawer } = useRightDrawer(); const setHotkeyScope = useSetHotkeyScope(); const setViewableCalendarEventId = useSetRecoilState( - viewableCalendarEventIdState(), + viewableCalendarEventIdState, ); const openCalendarEventRightDrawer = (calendarEventId: string) => { diff --git a/packages/twenty-front/src/modules/activities/comment/__stories__/Comment.stories.tsx b/packages/twenty-front/src/modules/activities/comment/__stories__/Comment.stories.tsx index 3c1b39bcbc..876d5a2517 100644 --- a/packages/twenty-front/src/modules/activities/comment/__stories__/Comment.stories.tsx +++ b/packages/twenty-front/src/modules/activities/comment/__stories__/Comment.stories.tsx @@ -11,7 +11,7 @@ import { Comment } from '../Comment'; import { mockComment, mockCommentWithLongValues } from './mock-comment'; const CommentSetterEffect = () => { - const setViewableActivity = useSetRecoilState(viewableActivityIdState()); + const setViewableActivity = useSetRecoilState(viewableActivityIdState); useEffect(() => { setViewableActivity('test-id'); diff --git a/packages/twenty-front/src/modules/activities/comment/__stories__/CommentHeader.stories.tsx b/packages/twenty-front/src/modules/activities/comment/__stories__/CommentHeader.stories.tsx index 5206587ac0..d61ebc25b2 100644 --- a/packages/twenty-front/src/modules/activities/comment/__stories__/CommentHeader.stories.tsx +++ b/packages/twenty-front/src/modules/activities/comment/__stories__/CommentHeader.stories.tsx @@ -13,7 +13,7 @@ import { CommentHeader } from '../CommentHeader'; import { mockComment, mockCommentWithLongValues } from './mock-comment'; const CommentHeaderSetterEffect = () => { - const setViewableActivity = useSetRecoilState(viewableActivityIdState()); + const setViewableActivity = useSetRecoilState(viewableActivityIdState); useEffect(() => { setViewableActivity('test-id'); diff --git a/packages/twenty-front/src/modules/activities/components/ActivityBodyEditor.tsx b/packages/twenty-front/src/modules/activities/components/ActivityBodyEditor.tsx index fbc61bb3cc..b9c4c84c24 100644 --- a/packages/twenty-front/src/modules/activities/components/ActivityBodyEditor.tsx +++ b/packages/twenty-front/src/modules/activities/components/ActivityBodyEditor.tsx @@ -116,7 +116,7 @@ export const ActivityBodyEditor = ({ ); const [canCreateActivity, setCanCreateActivity] = useRecoilState( - canCreateActivityState(), + canCreateActivityState, ); const [uploadFile] = useUploadFileMutation(); @@ -339,7 +339,7 @@ export const ActivityBodyEditor = ({ if ( isDefined(currentBlockContent) && isArray(currentBlockContent) && - currentBlockContent[0] && + isDefined(currentBlockContent[0]) && currentBlockContent[0].type === 'text' ) { // Text block case diff --git a/packages/twenty-front/src/modules/activities/components/ActivityComments.tsx b/packages/twenty-front/src/modules/activities/components/ActivityComments.tsx index 8647c485e8..16bdbed696 100644 --- a/packages/twenty-front/src/modules/activities/components/ActivityComments.tsx +++ b/packages/twenty-front/src/modules/activities/components/ActivityComments.tsx @@ -61,7 +61,7 @@ export const ActivityComments = ({ objectNameSingular: CoreObjectNameSingular.Comment, }); - const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState()); + const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); const { records: comments } = useFindManyRecords({ objectNameSingular: CoreObjectNameSingular.Comment, diff --git a/packages/twenty-front/src/modules/activities/components/ActivityEditorEffect.tsx b/packages/twenty-front/src/modules/activities/components/ActivityEditorEffect.tsx index 1f839640e9..93b6f54056 100644 --- a/packages/twenty-front/src/modules/activities/components/ActivityEditorEffect.tsx +++ b/packages/twenty-front/src/modules/activities/components/ActivityEditorEffect.tsx @@ -29,15 +29,15 @@ export const ActivityEditorEffect = ({ ({ snapshot, set }) => () => { const isUpsertingActivityInDB = snapshot - .getLoadable(isUpsertingActivityInDBState()) + .getLoadable(isUpsertingActivityInDBState) .getValue(); const canCreateActivity = snapshot - .getLoadable(canCreateActivityState()) + .getLoadable(canCreateActivityState) .getValue(); const isActivityInCreateMode = snapshot - .getLoadable(isActivityInCreateModeState()) + .getLoadable(isActivityInCreateModeState) .getValue(); const activityFromStore = snapshot @@ -71,7 +71,7 @@ export const ActivityEditorEffect = ({ deleteActivityFromCache(activity); } - set(isActivityInCreateModeState(), false); + set(isActivityInCreateModeState, false); } else if (isDefined(activity)) { if ( activity.title !== activityTitle || diff --git a/packages/twenty-front/src/modules/activities/components/ActivityTitle.tsx b/packages/twenty-front/src/modules/activities/components/ActivityTitle.tsx index 7a4a11f273..05cc0bdd3e 100644 --- a/packages/twenty-front/src/modules/activities/components/ActivityTitle.tsx +++ b/packages/twenty-front/src/modules/activities/components/ActivityTitle.tsx @@ -71,7 +71,7 @@ export const ActivityTitle = ({ activityId }: ActivityTitleProps) => { const activity = activityInStore as Activity; const [canCreateActivity, setCanCreateActivity] = useRecoilState( - canCreateActivityState(), + canCreateActivityState, ); const { upsertActivity } = useUpsertActivity(); diff --git a/packages/twenty-front/src/modules/activities/emails/components/EmailThreadPreview.tsx b/packages/twenty-front/src/modules/activities/emails/components/EmailThreadPreview.tsx index 8c7b10aae2..ce085a8e7b 100644 --- a/packages/twenty-front/src/modules/activities/emails/components/EmailThreadPreview.tsx +++ b/packages/twenty-front/src/modules/activities/emails/components/EmailThreadPreview.tsx @@ -122,7 +122,7 @@ export const EmailThreadPreview = ({ isSameEventThanRightDrawerClose(event.nativeEvent); const emailThreadIdWhenEmailThreadWasClosed = snapshot - .getLoadable(emailThreadIdWhenEmailThreadWasClosedState()) + .getLoadable(emailThreadIdWhenEmailThreadWasClosedState) .getValue(); const canOpen = diff --git a/packages/twenty-front/src/modules/activities/emails/components/EmailThreads.tsx b/packages/twenty-front/src/modules/activities/emails/components/EmailThreads.tsx index 65251d76be..91cc33ece6 100644 --- a/packages/twenty-front/src/modules/activities/emails/components/EmailThreads.tsx +++ b/packages/twenty-front/src/modules/activities/emails/components/EmailThreads.tsx @@ -58,12 +58,12 @@ export const EmailThreads = ({ }) => { const { enqueueSnackBar } = useSnackBar(); - const { getEmailThreadsPageState } = useEmailThreadStates({ + const { emailThreadsPageState } = useEmailThreadStates({ emailThreadScopeId: getScopeIdFromComponentId(entity.id), }); const [emailThreadsPage, setEmailThreadsPage] = useRecoilState( - getEmailThreadsPageState(), + emailThreadsPageState, ); const [isFetchingMoreEmails, setIsFetchingMoreEmails] = useState(false); diff --git a/packages/twenty-front/src/modules/activities/emails/hooks/__tests__/useEmailThread.test.tsx b/packages/twenty-front/src/modules/activities/emails/hooks/__tests__/useEmailThread.test.tsx index f68a887208..4dae422ca2 100644 --- a/packages/twenty-front/src/modules/activities/emails/hooks/__tests__/useEmailThread.test.tsx +++ b/packages/twenty-front/src/modules/activities/emails/hooks/__tests__/useEmailThread.test.tsx @@ -12,9 +12,9 @@ describe('useEmailThread', () => { const { result } = renderHook( () => { const emailThread = useEmailThread(); - const isRightDrawerOpen = useRecoilValue(isRightDrawerOpenState()); + const isRightDrawerOpen = useRecoilValue(isRightDrawerOpenState); const viewableEmailThreadId = useRecoilValue( - viewableEmailThreadIdState(), + viewableEmailThreadIdState, ); return { ...emailThread, isRightDrawerOpen, viewableEmailThreadId }; @@ -38,10 +38,10 @@ describe('useEmailThread', () => { () => { const emailThread = useEmailThread(); const [isRightDrawerOpen, setIsRightDrawerOpen] = useRecoilState( - isRightDrawerOpenState(), + isRightDrawerOpenState, ); const [viewableEmailThreadId, setViewableEmailThreadId] = - useRecoilState(viewableEmailThreadIdState()); + useRecoilState(viewableEmailThreadIdState); return { ...emailThread, diff --git a/packages/twenty-front/src/modules/activities/emails/hooks/internal/__tests__/useEmailThreadStates.test.ts b/packages/twenty-front/src/modules/activities/emails/hooks/internal/__tests__/useEmailThreadStates.test.ts index a1a65c99c2..0f77de3a96 100644 --- a/packages/twenty-front/src/modules/activities/emails/hooks/internal/__tests__/useEmailThreadStates.test.ts +++ b/packages/twenty-front/src/modules/activities/emails/hooks/internal/__tests__/useEmailThreadStates.test.ts @@ -30,7 +30,7 @@ describe('useEmailThreadStates hook', () => { ); expect(result.current.scopeId).toBe(mockScopeId); - expect(result.current.getEmailThreadsPageState).toBe( + expect(result.current.emailThreadsPageState).toBe( mockGetEmailThreadsPageState, ); }); diff --git a/packages/twenty-front/src/modules/activities/emails/hooks/internal/useEmailThreadStates.ts b/packages/twenty-front/src/modules/activities/emails/hooks/internal/useEmailThreadStates.ts index 0162ee6d4f..472377dfec 100644 --- a/packages/twenty-front/src/modules/activities/emails/hooks/internal/useEmailThreadStates.ts +++ b/packages/twenty-front/src/modules/activities/emails/hooks/internal/useEmailThreadStates.ts @@ -17,7 +17,7 @@ export const useEmailThreadStates = ({ return { scopeId, - getEmailThreadsPageState: extractComponentState( + emailThreadsPageState: extractComponentState( emailThreadsPageComponentState, scopeId, ), diff --git a/packages/twenty-front/src/modules/activities/emails/hooks/useEmailThread.ts b/packages/twenty-front/src/modules/activities/emails/hooks/useEmailThread.ts index 5ca934b738..a0757a18af 100644 --- a/packages/twenty-front/src/modules/activities/emails/hooks/useEmailThread.ts +++ b/packages/twenty-front/src/modules/activities/emails/hooks/useEmailThread.ts @@ -13,21 +13,21 @@ export const useEmailThread = () => { ({ snapshot, set }) => (threadId: string) => { const isRightDrawerOpen = snapshot - .getLoadable(isRightDrawerOpenState()) + .getLoadable(isRightDrawerOpenState) .getValue(); const viewableEmailThreadId = snapshot - .getLoadable(viewableEmailThreadIdState()) + .getLoadable(viewableEmailThreadIdState) .getValue(); if (isRightDrawerOpen && viewableEmailThreadId === threadId) { - set(viewableEmailThreadIdState(), null); + set(viewableEmailThreadIdState, null); closeRightDrawer(); return; } openEmailThredRightDrawer(); - set(viewableEmailThreadIdState(), threadId); + set(viewableEmailThreadIdState, threadId); }, [closeRightDrawer, openEmailThredRightDrawer], ); diff --git a/packages/twenty-front/src/modules/activities/emails/right-drawer/components/RightDrawerEmailThread.tsx b/packages/twenty-front/src/modules/activities/emails/right-drawer/components/RightDrawerEmailThread.tsx index fc71fdfe3a..e353f1dd4a 100644 --- a/packages/twenty-front/src/modules/activities/emails/right-drawer/components/RightDrawerEmailThread.tsx +++ b/packages/twenty-front/src/modules/activities/emails/right-drawer/components/RightDrawerEmailThread.tsx @@ -34,7 +34,7 @@ export const RightDrawerEmailThread = () => { callbackFunction: useRecoilCallback( ({ set }) => () => { - set(emailThreadIdWhenEmailThreadWasClosedState(), thread.id); + set(emailThreadIdWhenEmailThreadWasClosedState, thread.id); }, [thread], ), diff --git a/packages/twenty-front/src/modules/activities/emails/right-drawer/hooks/useRightDrawerEmailThread.ts b/packages/twenty-front/src/modules/activities/emails/right-drawer/hooks/useRightDrawerEmailThread.ts index dac62986ff..a6abbd80e2 100644 --- a/packages/twenty-front/src/modules/activities/emails/right-drawer/hooks/useRightDrawerEmailThread.ts +++ b/packages/twenty-front/src/modules/activities/emails/right-drawer/hooks/useRightDrawerEmailThread.ts @@ -9,7 +9,7 @@ import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSi import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords'; export const useRightDrawerEmailThread = () => { - const viewableEmailThreadId = useRecoilValue(viewableEmailThreadIdState()); + const viewableEmailThreadId = useRecoilValue(viewableEmailThreadIdState); const apolloClient = useApolloClient(); const thread = apolloClient.readFragment({ diff --git a/packages/twenty-front/src/modules/activities/files/hooks/useUploadAttachmentFile.tsx b/packages/twenty-front/src/modules/activities/files/hooks/useUploadAttachmentFile.tsx index bfc66abd48..1a0cceee7a 100644 --- a/packages/twenty-front/src/modules/activities/files/hooks/useUploadAttachmentFile.tsx +++ b/packages/twenty-front/src/modules/activities/files/hooks/useUploadAttachmentFile.tsx @@ -10,7 +10,7 @@ import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord'; import { FileFolder, useUploadFileMutation } from '~/generated/graphql'; export const useUploadAttachmentFile = () => { - const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState()); + const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); const [uploadFile] = useUploadFileMutation(); const { createOneRecord: createOneAttachment } = diff --git a/packages/twenty-front/src/modules/activities/hooks/__tests__/useActivities.test.tsx b/packages/twenty-front/src/modules/activities/hooks/__tests__/useActivities.test.tsx index 56730f9c8f..53d32b2694 100644 --- a/packages/twenty-front/src/modules/activities/hooks/__tests__/useActivities.test.tsx +++ b/packages/twenty-front/src/modules/activities/hooks/__tests__/useActivities.test.tsx @@ -201,7 +201,7 @@ describe('useActivities', () => { const { result } = renderHook( () => { const setCurrentWorkspaceMember = useSetRecoilState( - currentWorkspaceMemberState(), + currentWorkspaceMemberState, ); const activities = useActivities({ diff --git a/packages/twenty-front/src/modules/activities/hooks/__tests__/useActivityConnectionUtils.test.tsx b/packages/twenty-front/src/modules/activities/hooks/__tests__/useActivityConnectionUtils.test.tsx index ddda904ee4..c596ecfbd6 100644 --- a/packages/twenty-front/src/modules/activities/hooks/__tests__/useActivityConnectionUtils.test.tsx +++ b/packages/twenty-front/src/modules/activities/hooks/__tests__/useActivityConnectionUtils.test.tsx @@ -58,7 +58,7 @@ describe('useActivityConnectionUtils', () => { { snapshot.set( - objectMetadataItemsState(), + objectMetadataItemsState, getObjectMetadataItemsMock(), ); }} @@ -86,7 +86,7 @@ describe('useActivityConnectionUtils', () => { { snapshot.set( - objectMetadataItemsState(), + objectMetadataItemsState, getObjectMetadataItemsMock(), ); }} diff --git a/packages/twenty-front/src/modules/activities/hooks/__tests__/useActivityTargetObjectRecords.test.tsx b/packages/twenty-front/src/modules/activities/hooks/__tests__/useActivityTargetObjectRecords.test.tsx index 0a1b8f7b40..e1041843dc 100644 --- a/packages/twenty-front/src/modules/activities/hooks/__tests__/useActivityTargetObjectRecords.test.tsx +++ b/packages/twenty-front/src/modules/activities/hooks/__tests__/useActivityTargetObjectRecords.test.tsx @@ -186,10 +186,10 @@ describe('useActivityTargetObjectRecords', () => { const { result } = renderHook( () => { const setCurrentWorkspaceMember = useSetRecoilState( - currentWorkspaceMemberState(), + currentWorkspaceMemberState, ); const setObjectMetadataItems = useSetRecoilState( - objectMetadataItemsState(), + objectMetadataItemsState, ); const { activityTargetObjectRecords, loadingActivityTargets } = diff --git a/packages/twenty-front/src/modules/activities/hooks/__tests__/useActivityTargetsForTargetableObject.test.tsx b/packages/twenty-front/src/modules/activities/hooks/__tests__/useActivityTargetsForTargetableObject.test.tsx index e1e55e9c31..dedd2e3a0c 100644 --- a/packages/twenty-front/src/modules/activities/hooks/__tests__/useActivityTargetsForTargetableObject.test.tsx +++ b/packages/twenty-front/src/modules/activities/hooks/__tests__/useActivityTargetsForTargetableObject.test.tsx @@ -102,7 +102,7 @@ describe('useActivityTargetsForTargetableObject', () => { const { result } = renderHook( () => { const setCurrentWorkspaceMember = useSetRecoilState( - currentWorkspaceMemberState(), + currentWorkspaceMemberState, ); const res = useActivityTargetsForTargetableObject({ diff --git a/packages/twenty-front/src/modules/activities/hooks/__tests__/useAttachRelationInBothDirections.test.tsx b/packages/twenty-front/src/modules/activities/hooks/__tests__/useAttachRelationInBothDirections.test.tsx index e55118b7a0..a3e8fd73f0 100644 --- a/packages/twenty-front/src/modules/activities/hooks/__tests__/useAttachRelationInBothDirections.test.tsx +++ b/packages/twenty-front/src/modules/activities/hooks/__tests__/useAttachRelationInBothDirections.test.tsx @@ -29,10 +29,10 @@ describe('useAttachRelationInBothDirections', () => { const { result } = renderHook( () => { const setCurrentWorkspaceMember = useSetRecoilState( - currentWorkspaceMemberState(), + currentWorkspaceMemberState, ); const setObjectMetadataItems = useSetRecoilState( - objectMetadataItemsState(), + objectMetadataItemsState, ); const res = useAttachRelationInBothDirections(); diff --git a/packages/twenty-front/src/modules/activities/hooks/__tests__/useCreateActivityInCache.test.tsx b/packages/twenty-front/src/modules/activities/hooks/__tests__/useCreateActivityInCache.test.tsx index 08a571a2e7..a23ee3b4eb 100644 --- a/packages/twenty-front/src/modules/activities/hooks/__tests__/useCreateActivityInCache.test.tsx +++ b/packages/twenty-front/src/modules/activities/hooks/__tests__/useCreateActivityInCache.test.tsx @@ -59,10 +59,10 @@ describe('useCreateActivityInCache', () => { const { result } = renderHook( () => { const setCurrentWorkspaceMember = useSetRecoilState( - currentWorkspaceMemberState(), + currentWorkspaceMemberState, ); const setObjectMetadataItems = useSetRecoilState( - objectMetadataItemsState(), + objectMetadataItemsState, ); const res = useCreateActivityInCache(); diff --git a/packages/twenty-front/src/modules/activities/hooks/__tests__/useOpenActivityRightDrawer.test.tsx b/packages/twenty-front/src/modules/activities/hooks/__tests__/useOpenActivityRightDrawer.test.tsx index 2a323f3bde..19a027551a 100644 --- a/packages/twenty-front/src/modules/activities/hooks/__tests__/useOpenActivityRightDrawer.test.tsx +++ b/packages/twenty-front/src/modules/activities/hooks/__tests__/useOpenActivityRightDrawer.test.tsx @@ -18,8 +18,8 @@ describe('useOpenActivityRightDrawer', () => { const { result } = renderHook( () => { const openActivityRightDrawer = useOpenActivityRightDrawer(); - const viewableActivityId = useRecoilValue(viewableActivityIdState()); - const activityIdInDrawer = useRecoilValue(activityIdInDrawerState()); + const viewableActivityId = useRecoilValue(viewableActivityIdState); + const activityIdInDrawer = useRecoilValue(activityIdInDrawerState); return { openActivityRightDrawer, activityIdInDrawer, diff --git a/packages/twenty-front/src/modules/activities/hooks/__tests__/useOpenCreateActivityDrawer.test.tsx b/packages/twenty-front/src/modules/activities/hooks/__tests__/useOpenCreateActivityDrawer.test.tsx index ee294657c8..eb60717a41 100644 --- a/packages/twenty-front/src/modules/activities/hooks/__tests__/useOpenCreateActivityDrawer.test.tsx +++ b/packages/twenty-front/src/modules/activities/hooks/__tests__/useOpenCreateActivityDrawer.test.tsx @@ -28,10 +28,10 @@ describe('useOpenCreateActivityDrawer', () => { const { result } = renderHook( () => { const openActivityRightDrawer = useOpenCreateActivityDrawer(); - const viewableActivityId = useRecoilValue(viewableActivityIdState()); - const activityIdInDrawer = useRecoilValue(activityIdInDrawerState()); + const viewableActivityId = useRecoilValue(viewableActivityIdState); + const activityIdInDrawer = useRecoilValue(activityIdInDrawerState); const setObjectMetadataItems = useSetRecoilState( - objectMetadataItemsState(), + objectMetadataItemsState, ); return { openActivityRightDrawer, diff --git a/packages/twenty-front/src/modules/activities/hooks/__tests__/useOpenCreateActivityDrawerForSelectedRowIds.test.tsx b/packages/twenty-front/src/modules/activities/hooks/__tests__/useOpenCreateActivityDrawerForSelectedRowIds.test.tsx index 6a4ecc83de..7df977a2ad 100644 --- a/packages/twenty-front/src/modules/activities/hooks/__tests__/useOpenCreateActivityDrawerForSelectedRowIds.test.tsx +++ b/packages/twenty-front/src/modules/activities/hooks/__tests__/useOpenCreateActivityDrawerForSelectedRowIds.test.tsx @@ -41,10 +41,10 @@ describe('useOpenCreateActivityDrawerForSelectedRowIds', () => { () => { const openCreateActivityDrawerForSelectedRowIds = useOpenCreateActivityDrawerForSelectedRowIds(recordTableId); - const viewableActivityId = useRecoilValue(viewableActivityIdState()); - const activityIdInDrawer = useRecoilValue(activityIdInDrawerState()); + const viewableActivityId = useRecoilValue(viewableActivityIdState); + const activityIdInDrawer = useRecoilValue(activityIdInDrawerState); const setObjectMetadataItems = useSetRecoilState( - objectMetadataItemsState(), + objectMetadataItemsState, ); const scopeId = `${recordTableId}-scope`; const setTableRowIds = useSetRecoilState( diff --git a/packages/twenty-front/src/modules/activities/hooks/__tests__/useUpsertActivity.test.tsx b/packages/twenty-front/src/modules/activities/hooks/__tests__/useUpsertActivity.test.tsx index fcfb2c94c2..ddf4d40e5e 100644 --- a/packages/twenty-front/src/modules/activities/hooks/__tests__/useUpsertActivity.test.tsx +++ b/packages/twenty-front/src/modules/activities/hooks/__tests__/useUpsertActivity.test.tsx @@ -105,7 +105,7 @@ describe('useUpsertActivity', () => { () => { const res = useUpsertActivity(); const setIsActivityInCreateMode = useSetRecoilState( - isActivityInCreateModeState(), + isActivityInCreateModeState, ); return { ...res, setIsActivityInCreateMode }; @@ -134,7 +134,7 @@ describe('useUpsertActivity', () => { () => { const res = useUpsertActivity(); const setIsActivityInCreateMode = useSetRecoilState( - isActivityInCreateModeState(), + isActivityInCreateModeState, ); const setObjectShowPageTargetableObject = useSetRecoilState( objectShowPageTargetableObjectState, diff --git a/packages/twenty-front/src/modules/activities/hooks/useActivityTargetObjectRecords.ts b/packages/twenty-front/src/modules/activities/hooks/useActivityTargetObjectRecords.ts index 63e87ba07d..359b1c7550 100644 --- a/packages/twenty-front/src/modules/activities/hooks/useActivityTargetObjectRecords.ts +++ b/packages/twenty-front/src/modules/activities/hooks/useActivityTargetObjectRecords.ts @@ -14,7 +14,7 @@ export const useActivityTargetObjectRecords = ({ }: { activityId: string; }) => { - const objectMetadataItems = useRecoilValue(objectMetadataItemsState()); + const objectMetadataItems = useRecoilValue(objectMetadataItemsState); const { records: activityTargets, loading: loadingActivityTargets } = useFindManyRecords({ diff --git a/packages/twenty-front/src/modules/activities/hooks/useCreateActivityInCache.ts b/packages/twenty-front/src/modules/activities/hooks/useCreateActivityInCache.ts index 1479b0580a..4c1a927f7a 100644 --- a/packages/twenty-front/src/modules/activities/hooks/useCreateActivityInCache.ts +++ b/packages/twenty-front/src/modules/activities/hooks/useCreateActivityInCache.ts @@ -27,7 +27,7 @@ export const useCreateActivityInCache = () => { objectNameSingular: CoreObjectNameSingular.Activity, }); - const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState()); + const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); const { record: currentWorkspaceMemberRecord } = useFindOneRecord({ objectNameSingular: CoreObjectNameSingular.WorkspaceMember, diff --git a/packages/twenty-front/src/modules/activities/hooks/useOpenActivityRightDrawer.ts b/packages/twenty-front/src/modules/activities/hooks/useOpenActivityRightDrawer.ts index ae4d579a7c..b0279e17ee 100644 --- a/packages/twenty-front/src/modules/activities/hooks/useOpenActivityRightDrawer.ts +++ b/packages/twenty-front/src/modules/activities/hooks/useOpenActivityRightDrawer.ts @@ -12,9 +12,9 @@ export const useOpenActivityRightDrawer = () => { const { openRightDrawer, isRightDrawerOpen, rightDrawerPage } = useRightDrawer(); const [viewableActivityId, setViewableActivityId] = useRecoilState( - viewableActivityIdState(), + viewableActivityIdState, ); - const setActivityIdInDrawer = useSetRecoilState(activityIdInDrawerState()); + const setActivityIdInDrawer = useSetRecoilState(activityIdInDrawerState); const setHotkeyScope = useSetHotkeyScope(); return (activityId: string) => { diff --git a/packages/twenty-front/src/modules/activities/hooks/useOpenCreateActivityDrawer.ts b/packages/twenty-front/src/modules/activities/hooks/useOpenCreateActivityDrawer.ts index 5b4c313fbb..bcd10fcd77 100644 --- a/packages/twenty-front/src/modules/activities/hooks/useOpenCreateActivityDrawer.ts +++ b/packages/twenty-front/src/modules/activities/hooks/useOpenCreateActivityDrawer.ts @@ -24,22 +24,20 @@ export const useOpenCreateActivityDrawer = () => { const { createActivityInCache } = useCreateActivityInCache(); const setActivityTargetableEntityArray = useSetRecoilState( - activityTargetableEntityArrayState(), + activityTargetableEntityArrayState, ); - const setViewableActivityId = useSetRecoilState(viewableActivityIdState()); + const setViewableActivityId = useSetRecoilState(viewableActivityIdState); - const setIsCreatingActivity = useSetRecoilState( - isActivityInCreateModeState(), - ); + const setIsCreatingActivity = useSetRecoilState(isActivityInCreateModeState); const setTemporaryActivityForEditor = useSetRecoilState( - temporaryActivityForEditorState(), + temporaryActivityForEditorState, ); - const setActivityIdInDrawer = useSetRecoilState(activityIdInDrawerState()); + const setActivityIdInDrawer = useSetRecoilState(activityIdInDrawerState); const [, setIsUpsertingActivityInDB] = useRecoilState( - isUpsertingActivityInDBState(), + isUpsertingActivityInDBState, ); const openCreateActivityDrawer = async ({ diff --git a/packages/twenty-front/src/modules/activities/hooks/useOpenCreateActivityDrawerForSelectedRowIds.ts b/packages/twenty-front/src/modules/activities/hooks/useOpenCreateActivityDrawerForSelectedRowIds.ts index 11cd38d541..90713931b6 100644 --- a/packages/twenty-front/src/modules/activities/hooks/useOpenCreateActivityDrawerForSelectedRowIds.ts +++ b/packages/twenty-front/src/modules/activities/hooks/useOpenCreateActivityDrawerForSelectedRowIds.ts @@ -14,7 +14,7 @@ export const useOpenCreateActivityDrawerForSelectedRowIds = ( ) => { const openCreateActivityDrawer = useOpenCreateActivityDrawer(); - const { getSelectedRowIdsSelector } = useRecordTableStates(recordTableId); + const { selectedRowIdsSelector } = useRecordTableStates(recordTableId); return useRecoilCallback( ({ snapshot }) => @@ -25,7 +25,7 @@ export const useOpenCreateActivityDrawerForSelectedRowIds = ( ) => { const selectedRowIds = getSnapshotValue( snapshot, - getSelectedRowIdsSelector(), + selectedRowIdsSelector(), ); let activityTargetableObjectArray: ActivityTargetableObject[] = @@ -59,6 +59,6 @@ export const useOpenCreateActivityDrawerForSelectedRowIds = ( targetableObjects: activityTargetableObjectArray, }); }, - [openCreateActivityDrawer, getSelectedRowIdsSelector], + [selectedRowIdsSelector, openCreateActivityDrawer], ); }; diff --git a/packages/twenty-front/src/modules/activities/hooks/useUpsertActivity.ts b/packages/twenty-front/src/modules/activities/hooks/useUpsertActivity.ts index 2634eddc10..c383d22dfe 100644 --- a/packages/twenty-front/src/modules/activities/hooks/useUpsertActivity.ts +++ b/packages/twenty-front/src/modules/activities/hooks/useUpsertActivity.ts @@ -21,7 +21,7 @@ import { isDefined } from '~/utils/isDefined'; // TODO: create a generic way to have records only in cache for create mode and delete them afterwards ? export const useUpsertActivity = () => { const [isActivityInCreateMode, setIsActivityInCreateMode] = useRecoilState( - isActivityInCreateModeState(), + isActivityInCreateModeState, ); const { updateOneRecord: updateOneActivity } = useUpdateOneRecord({ @@ -31,10 +31,10 @@ export const useUpsertActivity = () => { const { createActivityInDB } = useCreateActivityInDB(); const [, setIsUpsertingActivityInDB] = useRecoilState( - isUpsertingActivityInDBState(), + isUpsertingActivityInDBState, ); - const setActivityIdInDrawer = useSetRecoilState(activityIdInDrawerState()); + const setActivityIdInDrawer = useSetRecoilState(activityIdInDrawerState); const objectShowPageTargetableObject = useRecoilValue( objectShowPageTargetableObjectState, diff --git a/packages/twenty-front/src/modules/activities/inline-cell/components/ActivityTargetInlineCellEditMode.tsx b/packages/twenty-front/src/modules/activities/inline-cell/components/ActivityTargetInlineCellEditMode.tsx index 2c2c3a68ed..3275f09233 100644 --- a/packages/twenty-front/src/modules/activities/inline-cell/components/ActivityTargetInlineCellEditMode.tsx +++ b/packages/twenty-front/src/modules/activities/inline-cell/components/ActivityTargetInlineCellEditMode.tsx @@ -34,9 +34,7 @@ export const ActivityTargetInlineCellEditMode = ({ activity, activityTargetWithTargetRecords, }: ActivityTargetInlineCellEditModeProps) => { - const [isActivityInCreateMode] = useRecoilState( - isActivityInCreateModeState(), - ); + const [isActivityInCreateMode] = useRecoilState(isActivityInCreateModeState); const selectedTargetObjectIds = activityTargetWithTargetRecords.map( (activityTarget) => ({ diff --git a/packages/twenty-front/src/modules/activities/right-drawer/components/ActivityActionBar.tsx b/packages/twenty-front/src/modules/activities/right-drawer/components/ActivityActionBar.tsx index 1069e8f794..40ed872f97 100644 --- a/packages/twenty-front/src/modules/activities/right-drawer/components/ActivityActionBar.tsx +++ b/packages/twenty-front/src/modules/activities/right-drawer/components/ActivityActionBar.tsx @@ -36,13 +36,13 @@ const StyledButtonContainer = styled.div` `; export const ActivityActionBar = () => { - const viewableActivityId = useRecoilValue(viewableActivityIdState()); - const activityIdInDrawer = useRecoilValue(activityIdInDrawerState()); + const viewableActivityId = useRecoilValue(viewableActivityIdState); + const activityIdInDrawer = useRecoilValue(activityIdInDrawerState); const activityTargetableEntityArray = useRecoilValue( - activityTargetableEntityArrayState(), + activityTargetableEntityArrayState, ); - const [, setIsRightDrawerOpen] = useRecoilState(isRightDrawerOpenState()); + const [, setIsRightDrawerOpen] = useRecoilState(isRightDrawerOpenState); const { deleteOneRecord: deleteOneActivity } = useDeleteOneRecord({ objectNameSingular: CoreObjectNameSingular.Activity, }); @@ -54,15 +54,13 @@ export const ActivityActionBar = () => { ); const [temporaryActivityForEditor, setTemporaryActivityForEditor] = - useRecoilState(temporaryActivityForEditorState()); + useRecoilState(temporaryActivityForEditorState); const { deleteActivityFromCache } = useDeleteActivityFromCache(); - const [isActivityInCreateMode] = useRecoilState( - isActivityInCreateModeState(), - ); + const [isActivityInCreateMode] = useRecoilState(isActivityInCreateModeState); const [isUpsertingActivityInDB] = useRecoilState( - isUpsertingActivityInDBState(), + isUpsertingActivityInDBState, ); const objectShowPageTargetableObject = useRecoilValue( diff --git a/packages/twenty-front/src/modules/activities/right-drawer/components/create/RightDrawerCreateActivity.tsx b/packages/twenty-front/src/modules/activities/right-drawer/components/create/RightDrawerCreateActivity.tsx index 4ec49de22a..fe6ac8ecaf 100644 --- a/packages/twenty-front/src/modules/activities/right-drawer/components/create/RightDrawerCreateActivity.tsx +++ b/packages/twenty-front/src/modules/activities/right-drawer/components/create/RightDrawerCreateActivity.tsx @@ -5,7 +5,7 @@ import { viewableActivityIdState } from '@/activities/states/viewableActivityIdS import { RightDrawerActivity } from '../RightDrawerActivity'; export const RightDrawerCreateActivity = () => { - const viewableActivityId = useRecoilValue(viewableActivityIdState()); + const viewableActivityId = useRecoilValue(viewableActivityIdState); return ( <> diff --git a/packages/twenty-front/src/modules/activities/right-drawer/components/edit/RightDrawerEditActivity.tsx b/packages/twenty-front/src/modules/activities/right-drawer/components/edit/RightDrawerEditActivity.tsx index 971d34b81b..288d7aca88 100644 --- a/packages/twenty-front/src/modules/activities/right-drawer/components/edit/RightDrawerEditActivity.tsx +++ b/packages/twenty-front/src/modules/activities/right-drawer/components/edit/RightDrawerEditActivity.tsx @@ -5,7 +5,7 @@ import { viewableActivityIdState } from '@/activities/states/viewableActivityIdS import { RightDrawerActivity } from '../RightDrawerActivity'; export const RightDrawerEditActivity = () => { - const viewableActivityId = useRecoilValue(viewableActivityIdState()); + const viewableActivityId = useRecoilValue(viewableActivityIdState); return ( <> diff --git a/packages/twenty-front/src/modules/activities/tasks/components/CurrentUserDueTaskCountEffect.tsx b/packages/twenty-front/src/modules/activities/tasks/components/CurrentUserDueTaskCountEffect.tsx index a6819f2342..3f82be635b 100644 --- a/packages/twenty-front/src/modules/activities/tasks/components/CurrentUserDueTaskCountEffect.tsx +++ b/packages/twenty-front/src/modules/activities/tasks/components/CurrentUserDueTaskCountEffect.tsx @@ -9,10 +9,10 @@ import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords'; import { parseDate } from '~/utils/date-utils'; export const CurrentUserDueTaskCountEffect = () => { - const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState()); + const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); const [currentUserDueTaskCount, setCurrentUserDueTaskCount] = useRecoilState( - currentUserDueTaskCountState(), + currentUserDueTaskCountState, ); const { records: tasks } = useFindManyRecords({ diff --git a/packages/twenty-front/src/modules/activities/tasks/components/TaskGroups.tsx b/packages/twenty-front/src/modules/activities/tasks/components/TaskGroups.tsx index bdc9b1c170..3d1ad6a43b 100644 --- a/packages/twenty-front/src/modules/activities/tasks/components/TaskGroups.tsx +++ b/packages/twenty-front/src/modules/activities/tasks/components/TaskGroups.tsx @@ -48,8 +48,8 @@ export const TaskGroups = ({ const openCreateActivity = useOpenCreateActivityDrawer(); - const { getActiveTabIdState } = useTabList(TASKS_TAB_LIST_COMPONENT_ID); - const activeTabId = useRecoilValue(getActiveTabIdState()); + const { activeTabIdState } = useTabList(TASKS_TAB_LIST_COMPONENT_ID); + const activeTabId = useRecoilValue(activeTabIdState); if (!initialized) { return <>; diff --git a/packages/twenty-front/src/modules/activities/tasks/hooks/useCurrentUserDueTaskCount.ts b/packages/twenty-front/src/modules/activities/tasks/hooks/useCurrentUserDueTaskCount.ts index 8ef7e168f9..836ed21bad 100644 --- a/packages/twenty-front/src/modules/activities/tasks/hooks/useCurrentUserDueTaskCount.ts +++ b/packages/twenty-front/src/modules/activities/tasks/hooks/useCurrentUserDueTaskCount.ts @@ -7,7 +7,7 @@ import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords'; import { parseDate } from '~/utils/date-utils'; export const useCurrentUserTaskCount = () => { - const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState()); + const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); const { records: tasks } = useFindManyRecords({ objectNameSingular: CoreObjectNameSingular.Activity, diff --git a/packages/twenty-front/src/modules/activities/tasks/hooks/useTasks.ts b/packages/twenty-front/src/modules/activities/tasks/hooks/useTasks.ts index b4d7b0179f..0adbe01f18 100644 --- a/packages/twenty-front/src/modules/activities/tasks/hooks/useTasks.ts +++ b/packages/twenty-front/src/modules/activities/tasks/hooks/useTasks.ts @@ -1,7 +1,7 @@ import { useEffect, useMemo } from 'react'; import { isNonEmptyArray } from '@sniptt/guards'; import { DateTime } from 'luxon'; -import { useRecoilState } from 'recoil'; +import { useRecoilState, useRecoilValue } from 'recoil'; import { useActivities } from '@/activities/hooks/useActivities'; import { currentCompletedTaskQueryVariablesState } from '@/activities/tasks/states/currentCompletedTaskQueryVariablesState'; @@ -23,10 +23,12 @@ export const useTasks = ({ targetableObjects, filterDropdownId, }: UseTasksProps) => { - const { selectedFilter } = useFilterDropdown({ + const { selectedFilterState } = useFilterDropdown({ filterDropdownId, }); + const selectedFilter = useRecoilValue(selectedFilterState); + const assigneeIdFilter = useMemo( () => selectedFilter diff --git a/packages/twenty-front/src/modules/activities/timeline/components/Timeline.tsx b/packages/twenty-front/src/modules/activities/timeline/components/Timeline.tsx index 96621b34a4..37cc77560e 100644 --- a/packages/twenty-front/src/modules/activities/timeline/components/Timeline.tsx +++ b/packages/twenty-front/src/modules/activities/timeline/components/Timeline.tsx @@ -33,7 +33,7 @@ export const Timeline = ({ targetableObject: ActivityTargetableObject; }) => { const { initialized, noActivities } = useRecoilValue( - timelineActivitiesNetworkingState(), + timelineActivitiesNetworkingState, ); const showEmptyState = noActivities; diff --git a/packages/twenty-front/src/modules/activities/timeline/components/TimelineCreateButtonGroup.tsx b/packages/twenty-front/src/modules/activities/timeline/components/TimelineCreateButtonGroup.tsx index b8542cd19f..e53b9ddd84 100644 --- a/packages/twenty-front/src/modules/activities/timeline/components/TimelineCreateButtonGroup.tsx +++ b/packages/twenty-front/src/modules/activities/timeline/components/TimelineCreateButtonGroup.tsx @@ -16,8 +16,8 @@ export const TimelineCreateButtonGroup = ({ }: { targetableObject: ActivityTargetableObject; }) => { - const { getActiveTabIdState } = useTabList(TAB_LIST_COMPONENT_ID); - const setActiveTabId = useSetRecoilState(getActiveTabIdState()); + const { activeTabIdState } = useTabList(TAB_LIST_COMPONENT_ID); + const setActiveTabId = useSetRecoilState(activeTabIdState); const openCreateActivity = useOpenCreateActivityDrawer(); diff --git a/packages/twenty-front/src/modules/activities/timeline/components/TimelineItemsContainer.tsx b/packages/twenty-front/src/modules/activities/timeline/components/TimelineItemsContainer.tsx index 59a5a925e5..f509a4781a 100644 --- a/packages/twenty-front/src/modules/activities/timeline/components/TimelineItemsContainer.tsx +++ b/packages/twenty-front/src/modules/activities/timeline/components/TimelineItemsContainer.tsx @@ -26,7 +26,7 @@ const StyledScrollWrapper = styled(ScrollWrapper)``; export const TimelineItemsContainer = () => { const timelineActivitiesForGroup = useRecoilValue( - timelineActivitiesForGroupState(), + timelineActivitiesForGroupState, ); const groupedActivities = groupActivitiesByMonth(timelineActivitiesForGroup); diff --git a/packages/twenty-front/src/modules/activities/timeline/components/TimelineQueryEffect.tsx b/packages/twenty-front/src/modules/activities/timeline/components/TimelineQueryEffect.tsx index cc0f24fdc1..26a2b781b7 100644 --- a/packages/twenty-front/src/modules/activities/timeline/components/TimelineQueryEffect.tsx +++ b/packages/twenty-front/src/modules/activities/timeline/components/TimelineQueryEffect.tsx @@ -35,10 +35,10 @@ export const TimelineQueryEffect = ({ }); const [timelineActivitiesNetworking, setTimelineActivitiesNetworking] = - useRecoilState(timelineActivitiesNetworkingState()); + useRecoilState(timelineActivitiesNetworkingState); const [timelineActivitiesForGroup, setTimelineActivitiesForGroup] = - useRecoilState(timelineActivitiesForGroupState()); + useRecoilState(timelineActivitiesForGroupState); useEffect(() => { if (!isDefined(targetableObject)) { diff --git a/packages/twenty-front/src/modules/analytics/hooks/useEventTracker.ts b/packages/twenty-front/src/modules/analytics/hooks/useEventTracker.ts index d2c34d0230..88d1d65674 100644 --- a/packages/twenty-front/src/modules/analytics/hooks/useEventTracker.ts +++ b/packages/twenty-front/src/modules/analytics/hooks/useEventTracker.ts @@ -13,7 +13,7 @@ export interface EventData { } export const useEventTracker = () => { - const telemetry = useRecoilValue(telemetryState()); + const telemetry = useRecoilValue(telemetryState); const [createEventMutation] = useTrackMutation(); return useCallback( diff --git a/packages/twenty-front/src/modules/apollo/hooks/useApolloFactory.ts b/packages/twenty-front/src/modules/apollo/hooks/useApolloFactory.ts index 4a20147793..4da2bc7863 100644 --- a/packages/twenty-front/src/modules/apollo/hooks/useApolloFactory.ts +++ b/packages/twenty-front/src/modules/apollo/hooks/useApolloFactory.ts @@ -16,11 +16,11 @@ import { ApolloFactory } from '../services/apollo.factory'; export const useApolloFactory = () => { // eslint-disable-next-line @nx/workspace-no-state-useref const apolloRef = useRef | null>(null); - const [isDebugMode] = useRecoilState(isDebugModeState()); + const [isDebugMode] = useRecoilState(isDebugModeState); const navigate = useNavigate(); const isMatchingLocation = useIsMatchingLocation(); - const [tokenPair, setTokenPair] = useRecoilState(tokenPairState()); + const [tokenPair, setTokenPair] = useRecoilState(tokenPairState); const apolloClient = useMemo(() => { apolloRef.current = new ApolloFactory({ diff --git a/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/triggerUpdateRelationsOptimisticEffect.ts b/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/triggerUpdateRelationsOptimisticEffect.ts index 0597a89ed7..f76074e284 100644 --- a/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/triggerUpdateRelationsOptimisticEffect.ts +++ b/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/triggerUpdateRelationsOptimisticEffect.ts @@ -26,127 +26,129 @@ export const triggerUpdateRelationsOptimisticEffect = ({ currentSourceRecord: CachedObjectRecord | null; updatedSourceRecord: CachedObjectRecord | null; objectMetadataItems: ObjectMetadataItem[]; -}) => - sourceObjectMetadataItem.fields.forEach((fieldMetadataItemOnSourceRecord) => { - const notARelationField = - fieldMetadataItemOnSourceRecord.type !== FieldMetadataType.Relation; +}) => { + return sourceObjectMetadataItem.fields.forEach( + (fieldMetadataItemOnSourceRecord) => { + const notARelationField = + fieldMetadataItemOnSourceRecord.type !== FieldMetadataType.Relation; - if (notARelationField) { - return; - } + if (notARelationField) { + return; + } - const fieldDoesNotExist = - isDefined(updatedSourceRecord) && - !(fieldMetadataItemOnSourceRecord.name in updatedSourceRecord); + const fieldDoesNotExist = + isDefined(updatedSourceRecord) && + !(fieldMetadataItemOnSourceRecord.name in updatedSourceRecord); - if (fieldDoesNotExist) { - return; - } + if (fieldDoesNotExist) { + return; + } - const relationDefinition = getRelationDefinition({ - fieldMetadataItemOnSourceRecord, - objectMetadataItems, - }); + const relationDefinition = getRelationDefinition({ + fieldMetadataItemOnSourceRecord, + objectMetadataItems, + }); + if (!relationDefinition) { + return; + } - if (!relationDefinition) { - return; - } + const { targetObjectMetadataItem, fieldMetadataItemOnTargetRecord } = + relationDefinition; - const { targetObjectMetadataItem, fieldMetadataItemOnTargetRecord } = - relationDefinition; + const currentFieldValueOnSourceRecord: + | ObjectRecordConnection + | CachedObjectRecord + | null = currentSourceRecord?.[fieldMetadataItemOnSourceRecord.name]; - const currentFieldValueOnSourceRecord: - | ObjectRecordConnection - | CachedObjectRecord - | null = currentSourceRecord?.[fieldMetadataItemOnSourceRecord.name]; + const updatedFieldValueOnSourceRecord: + | ObjectRecordConnection + | CachedObjectRecord + | null = updatedSourceRecord?.[fieldMetadataItemOnSourceRecord.name]; - const updatedFieldValueOnSourceRecord: - | ObjectRecordConnection - | CachedObjectRecord - | null = updatedSourceRecord?.[fieldMetadataItemOnSourceRecord.name]; + if ( + isDeeplyEqual( + currentFieldValueOnSourceRecord, + updatedFieldValueOnSourceRecord, + ) + ) { + return; + } - if ( - isDeeplyEqual( - currentFieldValueOnSourceRecord, - updatedFieldValueOnSourceRecord, - ) - ) { - return; - } - - // TODO: replace this by a relation type check, if it's one to many, - // it's an object record connection (we can still check it though as a safeguard) - const currentFieldValueOnSourceRecordIsARecordConnection = - isObjectRecordConnection( - targetObjectMetadataItem.nameSingular, - currentFieldValueOnSourceRecord, - ); - - const targetRecordsToDetachFrom = - currentFieldValueOnSourceRecordIsARecordConnection - ? currentFieldValueOnSourceRecord.edges.map( - ({ node }) => node as CachedObjectRecord, - ) - : [currentFieldValueOnSourceRecord].filter(isDefined); - - const updatedFieldValueOnSourceRecordIsARecordConnection = - isObjectRecordConnection( - targetObjectMetadataItem.nameSingular, - updatedFieldValueOnSourceRecord, - ); - - const targetRecordsToAttachTo = - updatedFieldValueOnSourceRecordIsARecordConnection - ? updatedFieldValueOnSourceRecord.edges.map( - ({ node }) => node as CachedObjectRecord, - ) - : [updatedFieldValueOnSourceRecord].filter(isDefined); - - const shouldDetachSourceFromAllTargets = - isDefined(currentSourceRecord) && targetRecordsToDetachFrom.length > 0; - - if (shouldDetachSourceFromAllTargets) { - // TODO: see if we can de-hardcode this, put cascade delete in relation metadata item - // Instead of hardcoding it here - const shouldCascadeDeleteTargetRecords = - CORE_OBJECT_NAMES_TO_DELETE_ON_TRIGGER_RELATION_DETACH.includes( - targetObjectMetadataItem.nameSingular as CoreObjectNameSingular, + // TODO: replace this by a relation type check, if it's one to many, + // it's an object record connection (we can still check it though as a safeguard) + const currentFieldValueOnSourceRecordIsARecordConnection = + isObjectRecordConnection( + targetObjectMetadataItem.nameSingular, + currentFieldValueOnSourceRecord, ); - if (shouldCascadeDeleteTargetRecords) { - triggerDeleteRecordsOptimisticEffect({ - cache, - objectMetadataItem: targetObjectMetadataItem, - recordsToDelete: targetRecordsToDetachFrom, - objectMetadataItems, - }); - } else { - targetRecordsToDetachFrom.forEach((targetRecordToDetachFrom) => { - triggerDetachRelationOptimisticEffect({ + const targetRecordsToDetachFrom = + currentFieldValueOnSourceRecordIsARecordConnection + ? currentFieldValueOnSourceRecord.edges.map( + ({ node }) => node as CachedObjectRecord, + ) + : [currentFieldValueOnSourceRecord].filter(isDefined); + + const updatedFieldValueOnSourceRecordIsARecordConnection = + isObjectRecordConnection( + targetObjectMetadataItem.nameSingular, + updatedFieldValueOnSourceRecord, + ); + + const targetRecordsToAttachTo = + updatedFieldValueOnSourceRecordIsARecordConnection + ? updatedFieldValueOnSourceRecord.edges.map( + ({ node }) => node as CachedObjectRecord, + ) + : [updatedFieldValueOnSourceRecord].filter(isDefined); + + const shouldDetachSourceFromAllTargets = + isDefined(currentSourceRecord) && targetRecordsToDetachFrom.length > 0; + + if (shouldDetachSourceFromAllTargets) { + // TODO: see if we can de-hardcode this, put cascade delete in relation metadata item + // Instead of hardcoding it here + const shouldCascadeDeleteTargetRecords = + CORE_OBJECT_NAMES_TO_DELETE_ON_TRIGGER_RELATION_DETACH.includes( + targetObjectMetadataItem.nameSingular as CoreObjectNameSingular, + ); + + if (shouldCascadeDeleteTargetRecords) { + triggerDeleteRecordsOptimisticEffect({ + cache, + objectMetadataItem: targetObjectMetadataItem, + recordsToDelete: targetRecordsToDetachFrom, + objectMetadataItems, + }); + } else { + targetRecordsToDetachFrom.forEach((targetRecordToDetachFrom) => { + triggerDetachRelationOptimisticEffect({ + cache, + sourceObjectNameSingular: sourceObjectMetadataItem.nameSingular, + sourceRecordId: currentSourceRecord.id, + fieldNameOnTargetRecord: fieldMetadataItemOnTargetRecord.name, + targetObjectNameSingular: targetObjectMetadataItem.nameSingular, + targetRecordId: targetRecordToDetachFrom.id, + }); + }); + } + } + + const shouldAttachSourceToAllTargets = + isDefined(updatedSourceRecord) && targetRecordsToAttachTo.length > 0; + + if (shouldAttachSourceToAllTargets) { + targetRecordsToAttachTo.forEach((targetRecordToAttachTo) => + triggerAttachRelationOptimisticEffect({ cache, sourceObjectNameSingular: sourceObjectMetadataItem.nameSingular, - sourceRecordId: currentSourceRecord.id, + sourceRecordId: updatedSourceRecord.id, fieldNameOnTargetRecord: fieldMetadataItemOnTargetRecord.name, targetObjectNameSingular: targetObjectMetadataItem.nameSingular, - targetRecordId: targetRecordToDetachFrom.id, - }); - }); + targetRecordId: targetRecordToAttachTo.id, + }), + ); } - } - - const shouldAttachSourceToAllTargets = - isDefined(updatedSourceRecord) && targetRecordsToAttachTo.length > 0; - - if (shouldAttachSourceToAllTargets) { - targetRecordsToAttachTo.forEach((targetRecordToAttachTo) => - triggerAttachRelationOptimisticEffect({ - cache, - sourceObjectNameSingular: sourceObjectMetadataItem.nameSingular, - sourceRecordId: updatedSourceRecord.id, - fieldNameOnTargetRecord: fieldMetadataItemOnTargetRecord.name, - targetObjectNameSingular: targetObjectMetadataItem.nameSingular, - targetRecordId: targetRecordToAttachTo.id, - }), - ); - } - }); + }, + ); +}; diff --git a/packages/twenty-front/src/modules/auth/hooks/__test__/useAuth.test.tsx b/packages/twenty-front/src/modules/auth/hooks/__test__/useAuth.test.tsx index 230075cdb5..25bfda7511 100644 --- a/packages/twenty-front/src/modules/auth/hooks/__test__/useAuth.test.tsx +++ b/packages/twenty-front/src/modules/auth/hooks/__test__/useAuth.test.tsx @@ -76,13 +76,13 @@ describe('useAuth', () => { const { result } = renderHook( () => { const client = useApolloClient(); - const icons = useRecoilValue(iconsState()); - const authProviders = useRecoilValue(authProvidersState()); - const billing = useRecoilValue(billingState()); - const isSignInPrefilled = useRecoilValue(isSignInPrefilledState()); - const supportChat = useRecoilValue(supportChatState()); - const telemetry = useRecoilValue(telemetryState()); - const isDebugMode = useRecoilValue(isDebugModeState()); + const icons = useRecoilValue(iconsState); + const authProviders = useRecoilValue(authProvidersState); + const billing = useRecoilValue(billingState); + const isSignInPrefilled = useRecoilValue(isSignInPrefilledState); + const supportChat = useRecoilValue(supportChatState); + const telemetry = useRecoilValue(telemetryState); + const isDebugMode = useRecoilValue(isDebugModeState); return { ...useAuth(), client, diff --git a/packages/twenty-front/src/modules/auth/hooks/__test__/useIsLogged.test.ts b/packages/twenty-front/src/modules/auth/hooks/__test__/useIsLogged.test.ts index a441c47970..2674f26d9c 100644 --- a/packages/twenty-front/src/modules/auth/hooks/__test__/useIsLogged.test.ts +++ b/packages/twenty-front/src/modules/auth/hooks/__test__/useIsLogged.test.ts @@ -9,7 +9,7 @@ const renderHooks = () => { const { result } = renderHook( () => { const isLogged = useIsLogged(); - const setTokenPair = useSetRecoilState(tokenPairState()); + const setTokenPair = useSetRecoilState(tokenPairState); return { isLogged, diff --git a/packages/twenty-front/src/modules/auth/hooks/__test__/useOnboardingStatus.test.ts b/packages/twenty-front/src/modules/auth/hooks/__test__/useOnboardingStatus.test.ts index ec035d3c80..c57337c914 100644 --- a/packages/twenty-front/src/modules/auth/hooks/__test__/useOnboardingStatus.test.ts +++ b/packages/twenty-front/src/modules/auth/hooks/__test__/useOnboardingStatus.test.ts @@ -38,13 +38,13 @@ const renderHooks = () => { const { result } = renderHook( () => { const onboardingStatus = useOnboardingStatus(); - const setBilling = useSetRecoilState(billingState()); - const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState()); + const setBilling = useSetRecoilState(billingState); + const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState); const setCurrentWorkspaceMember = useSetRecoilState( - currentWorkspaceMemberState(), + currentWorkspaceMemberState, ); - const setTokenPair = useSetRecoilState(tokenPairState()); - const setVerifyPending = useSetRecoilState(isVerifyPendingState()); + const setTokenPair = useSetRecoilState(tokenPairState); + const setVerifyPending = useSetRecoilState(isVerifyPendingState); return { onboardingStatus, diff --git a/packages/twenty-front/src/modules/auth/hooks/useAuth.ts b/packages/twenty-front/src/modules/auth/hooks/useAuth.ts index 3ecd5271e5..a39d49bcd1 100644 --- a/packages/twenty-front/src/modules/auth/hooks/useAuth.ts +++ b/packages/twenty-front/src/modules/auth/hooks/useAuth.ts @@ -32,14 +32,14 @@ import { currentUserState } from '../states/currentUserState'; import { tokenPairState } from '../states/tokenPairState'; export const useAuth = () => { - const [, setTokenPair] = useRecoilState(tokenPairState()); - const setCurrentUser = useSetRecoilState(currentUserState()); + const [, setTokenPair] = useRecoilState(tokenPairState); + const setCurrentUser = useSetRecoilState(currentUserState); const setCurrentWorkspaceMember = useSetRecoilState( - currentWorkspaceMemberState(), + currentWorkspaceMemberState, ); - const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState()); - const setIsVerifyPendingState = useSetRecoilState(isVerifyPendingState()); + const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState); + const setIsVerifyPendingState = useSetRecoilState(isVerifyPendingState); const [challenge] = useChallengeMutation(); const [signUp] = useSignUpMutation(); @@ -141,26 +141,26 @@ export const useAuth = () => { ({ snapshot }) => async () => { const emptySnapshot = snapshot_UNSTABLE(); - const iconsValue = snapshot.getLoadable(iconsState()).getValue(); + const iconsValue = snapshot.getLoadable(iconsState).getValue(); const authProvidersValue = snapshot - .getLoadable(authProvidersState()) + .getLoadable(authProvidersState) .getValue(); - const billing = snapshot.getLoadable(billingState()).getValue(); + const billing = snapshot.getLoadable(billingState).getValue(); const isSignInPrefilled = snapshot - .getLoadable(isSignInPrefilledState()) + .getLoadable(isSignInPrefilledState) .getValue(); - const supportChat = snapshot.getLoadable(supportChatState()).getValue(); - const telemetry = snapshot.getLoadable(telemetryState()).getValue(); - const isDebugMode = snapshot.getLoadable(isDebugModeState()).getValue(); + const supportChat = snapshot.getLoadable(supportChatState).getValue(); + const telemetry = snapshot.getLoadable(telemetryState).getValue(); + const isDebugMode = snapshot.getLoadable(isDebugModeState).getValue(); const initialSnapshot = emptySnapshot.map(({ set }) => { - set(iconsState(), iconsValue); - set(authProvidersState(), authProvidersValue); - set(billingState(), billing); - set(isSignInPrefilledState(), isSignInPrefilled); - set(supportChatState(), supportChat); - set(telemetryState(), telemetry); - set(isDebugModeState(), isDebugMode); + set(iconsState, iconsValue); + set(authProvidersState, authProvidersValue); + set(billingState, billing); + set(isSignInPrefilledState, isSignInPrefilled); + set(supportChatState, supportChat); + set(telemetryState, telemetry); + set(isDebugModeState, isDebugMode); return undefined; }); diff --git a/packages/twenty-front/src/modules/auth/hooks/useIsLogged.ts b/packages/twenty-front/src/modules/auth/hooks/useIsLogged.ts index 1c235a747e..4399b564c0 100644 --- a/packages/twenty-front/src/modules/auth/hooks/useIsLogged.ts +++ b/packages/twenty-front/src/modules/auth/hooks/useIsLogged.ts @@ -5,8 +5,8 @@ import { isVerifyPendingState } from '@/auth/states/isVerifyPendingState'; import { tokenPairState } from '../states/tokenPairState'; export const useIsLogged = (): boolean => { - const [tokenPair] = useRecoilState(tokenPairState()); - const isVerifyPending = useRecoilValue(isVerifyPendingState()); + const [tokenPair] = useRecoilState(tokenPairState); + const isVerifyPending = useRecoilValue(isVerifyPendingState); return !!tokenPair && !isVerifyPending; }; diff --git a/packages/twenty-front/src/modules/auth/hooks/useOnboardingStatus.ts b/packages/twenty-front/src/modules/auth/hooks/useOnboardingStatus.ts index bd8ed6b0df..91a8a60e84 100644 --- a/packages/twenty-front/src/modules/auth/hooks/useOnboardingStatus.ts +++ b/packages/twenty-front/src/modules/auth/hooks/useOnboardingStatus.ts @@ -11,9 +11,9 @@ import { } from '../utils/getOnboardingStatus'; export const useOnboardingStatus = (): OnboardingStatus | undefined => { - const billing = useRecoilValue(billingState()); - const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState()); - const currentWorkspace = useRecoilValue(currentWorkspaceState()); + const billing = useRecoilValue(billingState); + const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); + const currentWorkspace = useRecoilValue(currentWorkspaceState); const isLoggedIn = useIsLogged(); return getOnboardingStatus({ diff --git a/packages/twenty-front/src/modules/auth/sign-in-up/components/SignInUpForm.tsx b/packages/twenty-front/src/modules/auth/sign-in-up/components/SignInUpForm.tsx index b028ba01ad..bc1997f2d4 100644 --- a/packages/twenty-front/src/modules/auth/sign-in-up/components/SignInUpForm.tsx +++ b/packages/twenty-front/src/modules/auth/sign-in-up/components/SignInUpForm.tsx @@ -46,7 +46,7 @@ const StyledInputContainer = styled.div` `; export const SignInUpForm = () => { - const [authProviders] = useRecoilState(authProvidersState()); + const [authProviders] = useRecoilState(authProvidersState); const [showErrors, setShowErrors] = useState(false); const { handleResetPassword } = useHandleResetPassword(); const workspace = useWorkspaceFromInviteHash(); diff --git a/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useNavigateAfterSignInUp.ts b/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useNavigateAfterSignInUp.ts index e659696c4c..ee090c1270 100644 --- a/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useNavigateAfterSignInUp.ts +++ b/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useNavigateAfterSignInUp.ts @@ -9,7 +9,7 @@ import { WorkspaceMember } from '~/generated/graphql.tsx'; export const useNavigateAfterSignInUp = () => { const navigate = useNavigate(); - const billing = useRecoilValue(billingState()); + const billing = useRecoilValue(billingState); const navigateAfterSignInUp = useCallback( ( currentWorkspace: CurrentWorkspace, diff --git a/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInUpForm.ts b/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInUpForm.ts index 6677754d26..591abf368f 100644 --- a/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInUpForm.ts +++ b/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInUpForm.ts @@ -19,7 +19,7 @@ const validationSchema = z export type Form = z.infer; export const useSignInUpForm = () => { - const isSignInPrefilled = useRecoilValue(isSignInPrefilledState()); + const isSignInPrefilled = useRecoilValue(isSignInPrefilledState); const form = useForm
({ mode: 'onChange', defaultValues: { diff --git a/packages/twenty-front/src/modules/client-config/components/ClientConfigProvider.tsx b/packages/twenty-front/src/modules/client-config/components/ClientConfigProvider.tsx index f7caad94b2..db62ad64fa 100644 --- a/packages/twenty-front/src/modules/client-config/components/ClientConfigProvider.tsx +++ b/packages/twenty-front/src/modules/client-config/components/ClientConfigProvider.tsx @@ -15,17 +15,17 @@ import { isDefined } from '~/utils/isDefined'; export const ClientConfigProvider: React.FC = ({ children, }) => { - const setAuthProviders = useSetRecoilState(authProvidersState()); - const setIsDebugMode = useSetRecoilState(isDebugModeState()); + const setAuthProviders = useSetRecoilState(authProvidersState); + const setIsDebugMode = useSetRecoilState(isDebugModeState); - const setIsSignInPrefilled = useSetRecoilState(isSignInPrefilledState()); - const setIsSignUpDisabled = useSetRecoilState(isSignUpDisabledState()); + const setIsSignInPrefilled = useSetRecoilState(isSignInPrefilledState); + const setIsSignUpDisabled = useSetRecoilState(isSignUpDisabledState); - const setBilling = useSetRecoilState(billingState()); - const setTelemetry = useSetRecoilState(telemetryState()); - const setSupportChat = useSetRecoilState(supportChatState()); + const setBilling = useSetRecoilState(billingState); + const setTelemetry = useSetRecoilState(telemetryState); + const setSupportChat = useSetRecoilState(supportChatState); - const setSentryConfig = useSetRecoilState(sentryConfigState()); + const setSentryConfig = useSetRecoilState(sentryConfigState); const { data, loading } = useGetClientConfigQuery(); 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 0a7a6c5541..b7f281eb15 100644 --- a/packages/twenty-front/src/modules/command-menu/components/CommandMenu.tsx +++ b/packages/twenty-front/src/modules/command-menu/components/CommandMenu.tsx @@ -109,9 +109,9 @@ export const CommandMenu = () => { const openActivityRightDrawer = useOpenActivityRightDrawer(); const isCommandMenuOpened = useRecoilValue(isCommandMenuOpenedState); const [commandMenuSearch, setCommandMenuSearch] = useRecoilState( - commandMenuSearchState(), + commandMenuSearchState, ); - const commandMenuCommands = useRecoilValue(commandMenuCommandsState()); + const commandMenuCommands = useRecoilValue(commandMenuCommandsState); const { closeKeyboardShortcutMenu } = useKeyboardShortcutMenu(); const handleSearchChange = (event: React.ChangeEvent) => { diff --git a/packages/twenty-front/src/modules/command-menu/components/__stories__/CommandMenu.stories.tsx b/packages/twenty-front/src/modules/command-menu/components/__stories__/CommandMenu.stories.tsx index 95e4da7d18..6cf5c7fbf3 100644 --- a/packages/twenty-front/src/modules/command-menu/components/__stories__/CommandMenu.stories.tsx +++ b/packages/twenty-front/src/modules/command-menu/components/__stories__/CommandMenu.stories.tsx @@ -27,9 +27,9 @@ const meta: Meta = { component: CommandMenu, decorators: [ (Story) => { - const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState()); + const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState); const setCurrentWorkspaceMember = useSetRecoilState( - currentWorkspaceMemberState(), + currentWorkspaceMemberState, ); const { addToCommandMenu, setToInitialCommandMenu, openCommandMenu } = useCommandMenu(); diff --git a/packages/twenty-front/src/modules/command-menu/hooks/__test__/useCommandMenu.test.tsx b/packages/twenty-front/src/modules/command-menu/hooks/__test__/useCommandMenu.test.tsx index 2cdec0fdc4..e1ee550138 100644 --- a/packages/twenty-front/src/modules/command-menu/hooks/__test__/useCommandMenu.test.tsx +++ b/packages/twenty-front/src/modules/command-menu/hooks/__test__/useCommandMenu.test.tsx @@ -25,7 +25,7 @@ const renderHooks = () => { const commandMenu = useCommandMenu(); const isCommandMenuOpened = useRecoilValue(isCommandMenuOpenedState); const [commandMenuCommands, setCommandMenuCommands] = useRecoilState( - commandMenuCommandsState(), + commandMenuCommandsState, ); return { diff --git a/packages/twenty-front/src/modules/command-menu/hooks/useCommandMenu.ts b/packages/twenty-front/src/modules/command-menu/hooks/useCommandMenu.ts index 438e3b11d8..1a8e085064 100644 --- a/packages/twenty-front/src/modules/command-menu/hooks/useCommandMenu.ts +++ b/packages/twenty-front/src/modules/command-menu/hooks/useCommandMenu.ts @@ -17,7 +17,7 @@ import { Command } from '../types/Command'; export const useCommandMenu = () => { const navigate = useNavigate(); const setIsCommandMenuOpened = useSetRecoilState(isCommandMenuOpenedState); - const setCommands = useSetRecoilState(commandMenuCommandsState()); + const setCommands = useSetRecoilState(commandMenuCommandsState); const { resetSelectedItem } = useSelectableList('command-menu-list'); const { setHotkeyScopeAndMemorizePreviousScope, @@ -52,7 +52,7 @@ export const useCommandMenu = () => { .getLoadable(isCommandMenuOpenedState) .getValue(); - set(commandMenuSearchState(), ''); + set(commandMenuSearchState, ''); if (isCommandMenuOpened) { closeCommandMenu(); diff --git a/packages/twenty-front/src/modules/debug/components/ApolloDevLogEffect.tsx b/packages/twenty-front/src/modules/debug/components/ApolloDevLogEffect.tsx index 7ce1508463..93a6af6f0c 100644 --- a/packages/twenty-front/src/modules/debug/components/ApolloDevLogEffect.tsx +++ b/packages/twenty-front/src/modules/debug/components/ApolloDevLogEffect.tsx @@ -5,7 +5,7 @@ import { useRecoilValue } from 'recoil'; import { isDebugModeState } from '@/client-config/states/isDebugModeState'; export const ApolloDevLogEffect = () => { - const isDebugMode = useRecoilValue(isDebugModeState()); + const isDebugMode = useRecoilValue(isDebugModeState); useEffect(() => { if (isDebugMode) { diff --git a/packages/twenty-front/src/modules/debug/components/RecoilDebugObserver.tsx b/packages/twenty-front/src/modules/debug/components/RecoilDebugObserver.tsx index e603623f78..5031c1963f 100644 --- a/packages/twenty-front/src/modules/debug/components/RecoilDebugObserver.tsx +++ b/packages/twenty-front/src/modules/debug/components/RecoilDebugObserver.tsx @@ -15,7 +15,7 @@ const formatTitle = (stateName: string) => { }; export const RecoilDebugObserverEffect = () => { - const isDebugMode = useRecoilValue(isDebugModeState()); + const isDebugMode = useRecoilValue(isDebugModeState); useRecoilTransactionObserver_UNSTABLE(({ snapshot }) => { if (!isDebugMode) { diff --git a/packages/twenty-front/src/modules/error-handler/components/SentryInitiEffect.tsx b/packages/twenty-front/src/modules/error-handler/components/SentryInitiEffect.tsx index 874b5ac4b7..4638106744 100644 --- a/packages/twenty-front/src/modules/error-handler/components/SentryInitiEffect.tsx +++ b/packages/twenty-front/src/modules/error-handler/components/SentryInitiEffect.tsx @@ -11,11 +11,11 @@ import { REACT_APP_SERVER_BASE_URL } from '~/config'; import { isDefined } from '~/utils/isDefined'; export const SentryInitEffect = () => { - const sentryConfig = useRecoilValue(sentryConfigState()); + const sentryConfig = useRecoilValue(sentryConfigState); - const currentUser = useRecoilValue(currentUserState()); - const currentWorkspace = useRecoilValue(currentWorkspaceState()); - const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState()); + const currentUser = useRecoilValue(currentUserState); + const currentWorkspace = useRecoilValue(currentWorkspaceState); + const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); const [isSentryInitialized, setIsSentryInitialized] = useState(false); diff --git a/packages/twenty-front/src/modules/favorites/hooks/__tests__/useFavorites.test.tsx b/packages/twenty-front/src/modules/favorites/hooks/__tests__/useFavorites.test.tsx index a060750e48..3d9347f0bc 100644 --- a/packages/twenty-front/src/modules/favorites/hooks/__tests__/useFavorites.test.tsx +++ b/packages/twenty-front/src/modules/favorites/hooks/__tests__/useFavorites.test.tsx @@ -46,11 +46,11 @@ describe('useFavorites', () => { const { result } = renderHook( () => { const setCurrentWorkspaceMember = useSetRecoilState( - currentWorkspaceMemberState(), + currentWorkspaceMemberState, ); setCurrentWorkspaceMember(mockWorkspaceMember); - const setMetadataItems = useSetRecoilState(objectMetadataItemsState()); + const setMetadataItems = useSetRecoilState(objectMetadataItemsState); setMetadataItems(mockObjectMetadataItems); return useFavorites(); @@ -67,11 +67,11 @@ describe('useFavorites', () => { const { result } = renderHook( () => { const setCurrentWorkspaceMember = useSetRecoilState( - currentWorkspaceMemberState(), + currentWorkspaceMemberState, ); setCurrentWorkspaceMember(mockWorkspaceMember); - const setMetadataItems = useSetRecoilState(objectMetadataItemsState()); + const setMetadataItems = useSetRecoilState(objectMetadataItemsState); setMetadataItems(mockObjectMetadataItems); return useFavorites(); @@ -95,11 +95,11 @@ describe('useFavorites', () => { const { result } = renderHook( () => { const setCurrentWorkspaceMember = useSetRecoilState( - currentWorkspaceMemberState(), + currentWorkspaceMemberState, ); setCurrentWorkspaceMember(mockWorkspaceMember); - const setMetadataItems = useSetRecoilState(objectMetadataItemsState()); + const setMetadataItems = useSetRecoilState(objectMetadataItemsState); setMetadataItems(mockObjectMetadataItems); return useFavorites(); @@ -120,11 +120,11 @@ describe('useFavorites', () => { const { result } = renderHook( () => { const setCurrentWorkspaceMember = useSetRecoilState( - currentWorkspaceMemberState(), + currentWorkspaceMemberState, ); setCurrentWorkspaceMember(mockWorkspaceMember); - const setMetadataItems = useSetRecoilState(objectMetadataItemsState()); + const setMetadataItems = useSetRecoilState(objectMetadataItemsState); setMetadataItems(mockObjectMetadataItems); return useFavorites(); diff --git a/packages/twenty-front/src/modules/favorites/hooks/useFavorites.ts b/packages/twenty-front/src/modules/favorites/hooks/useFavorites.ts index 25595a4098..f01cdd1d4f 100644 --- a/packages/twenty-front/src/modules/favorites/hooks/useFavorites.ts +++ b/packages/twenty-front/src/modules/favorites/hooks/useFavorites.ts @@ -16,7 +16,7 @@ import { FieldMetadataType } from '~/generated-metadata/graphql'; import { isDefined } from '~/utils/isDefined'; export const useFavorites = () => { - const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState()); + const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); const { objectMetadataItem: favoriteObjectMetadataItem } = useObjectMetadataItem({ diff --git a/packages/twenty-front/src/modules/navigation/components/AppNavigationDrawer.tsx b/packages/twenty-front/src/modules/navigation/components/AppNavigationDrawer.tsx index 216a12462f..0a8a50cdd2 100644 --- a/packages/twenty-front/src/modules/navigation/components/AppNavigationDrawer.tsx +++ b/packages/twenty-front/src/modules/navigation/components/AppNavigationDrawer.tsx @@ -28,12 +28,12 @@ export const AppNavigationDrawer = ({ const isMobile = useIsMobile(); const isSettingsPage = useIsSettingsPage(); const currentMobileNavigationDrawer = useRecoilValue( - currentMobileNavigationDrawerState(), + currentMobileNavigationDrawerState, ); const setIsNavigationDrawerOpen = useSetRecoilState( isNavigationDrawerOpenState, ); - const currentWorkspace = useRecoilValue(currentWorkspaceState()); + const currentWorkspace = useRecoilValue(currentWorkspaceState); const isSettingsDrawer = isMobile ? currentMobileNavigationDrawer === 'settings' diff --git a/packages/twenty-front/src/modules/navigation/components/MainNavigationDrawerItems.tsx b/packages/twenty-front/src/modules/navigation/components/MainNavigationDrawerItems.tsx index 102f5d7cf3..f8a437ed7c 100644 --- a/packages/twenty-front/src/modules/navigation/components/MainNavigationDrawerItems.tsx +++ b/packages/twenty-front/src/modules/navigation/components/MainNavigationDrawerItems.tsx @@ -24,13 +24,11 @@ export const MainNavigationDrawerItems = () => { const isMobile = useIsMobile(); const { toggleCommandMenu } = useCommandMenu(); const isTasksPage = useIsTasksPage(); - const currentUserDueTaskCount = useRecoilValue( - currentUserDueTaskCountState(), - ); + const currentUserDueTaskCount = useRecoilValue(currentUserDueTaskCountState); const navigate = useNavigate(); const location = useLocation(); const setNavigationMemorizedUrl = useSetRecoilState( - navigationMemorizedUrlState(), + navigationMemorizedUrlState, ); return ( diff --git a/packages/twenty-front/src/modules/navigation/components/MobileNavigationBar.tsx b/packages/twenty-front/src/modules/navigation/components/MobileNavigationBar.tsx index d671a284e8..3680415ba4 100644 --- a/packages/twenty-front/src/modules/navigation/components/MobileNavigationBar.tsx +++ b/packages/twenty-front/src/modules/navigation/components/MobileNavigationBar.tsx @@ -30,7 +30,7 @@ export const MobileNavigationBar = () => { isNavigationDrawerOpenState, ); const [currentMobileNavigationDrawer, setCurrentMobileNavigationDrawer] = - useRecoilState(currentMobileNavigationDrawerState()); + useRecoilState(currentMobileNavigationDrawerState); const activeItemName = isNavigationDrawerOpen ? currentMobileNavigationDrawer diff --git a/packages/twenty-front/src/modules/navigation/components/__stories__/AppNavigationDrawer.stories.tsx b/packages/twenty-front/src/modules/navigation/components/__stories__/AppNavigationDrawer.stories.tsx index 3c538ccd63..e267c7e24a 100644 --- a/packages/twenty-front/src/modules/navigation/components/__stories__/AppNavigationDrawer.stories.tsx +++ b/packages/twenty-front/src/modules/navigation/components/__stories__/AppNavigationDrawer.stories.tsx @@ -24,7 +24,7 @@ const MobileNavigationDrawerStateSetterEffect = ({ isNavigationDrawerOpenState, ); const setCurrentMobileNavigationDrawer = useSetRecoilState( - currentMobileNavigationDrawerState(), + currentMobileNavigationDrawerState, ); useEffect(() => { diff --git a/packages/twenty-front/src/modules/object-metadata/components/ApolloMetadataClientProvider.tsx b/packages/twenty-front/src/modules/object-metadata/components/ApolloMetadataClientProvider.tsx index 38bd8fc66d..2af8362986 100644 --- a/packages/twenty-front/src/modules/object-metadata/components/ApolloMetadataClientProvider.tsx +++ b/packages/twenty-front/src/modules/object-metadata/components/ApolloMetadataClientProvider.tsx @@ -13,7 +13,7 @@ export const ApolloMetadataClientProvider = ({ }: { children: React.ReactNode; }) => { - const [tokenPair] = useRecoilState(tokenPairState()); + const [tokenPair] = useRecoilState(tokenPairState); const apolloMetadataClient = useMemo(() => { if (isNonEmptyString(tokenPair?.accessToken.token)) { return new ApolloClient({ diff --git a/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsLoadEffect.tsx b/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsLoadEffect.tsx index 0313a164fb..9288ec017b 100644 --- a/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsLoadEffect.tsx +++ b/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsLoadEffect.tsx @@ -10,7 +10,7 @@ export const ObjectMetadataItemsLoadEffect = () => { useFindManyObjectMetadataItems(); const [objectMetadataItems, setObjectMetadataItems] = useRecoilState( - objectMetadataItemsState(), + objectMetadataItemsState, ); useEffect(() => { 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 a4a50ac352..0c3ebdadc5 100644 --- a/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsProvider.tsx +++ b/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsProvider.tsx @@ -9,8 +9,8 @@ import { RelationPickerScope } from '@/object-record/relation-picker/scopes/Rela export const ObjectMetadataItemsProvider = ({ children, }: React.PropsWithChildren) => { - const objectMetadataItems = useRecoilValue(objectMetadataItemsState()); - const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState()); + const objectMetadataItems = useRecoilValue(objectMetadataItemsState); + const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); const shouldDisplayChildren = objectMetadataItems.length > 0 || !currentWorkspaceMember; diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useFilterOutUnexistingObjectMetadataItems.test.tsx b/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useFilterOutUnexistingObjectMetadataItems.test.tsx index d23f347d67..e544f642c0 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useFilterOutUnexistingObjectMetadataItems.test.tsx +++ b/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useFilterOutUnexistingObjectMetadataItems.test.tsx @@ -12,7 +12,7 @@ describe('useFilterOutUnexistingObjectMetadataItems', () => { it('should work as expected', async () => { const { result } = renderHook( () => { - const setMetadataItems = useSetRecoilState(objectMetadataItemsState()); + const setMetadataItems = useSetRecoilState(objectMetadataItemsState); setMetadataItems(mockObjectMetadataItems.slice(1)); return useFilterOutUnexistingObjectMetadataItems(); diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useGetObjectRecordIdentifierByNameSingular.test.tsx b/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useGetObjectRecordIdentifierByNameSingular.test.tsx index 6f25e039ca..1a4c0e2cbf 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useGetObjectRecordIdentifierByNameSingular.test.tsx +++ b/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useGetObjectRecordIdentifierByNameSingular.test.tsx @@ -17,7 +17,7 @@ describe('useGetObjectRecordIdentifierByNameSingular', () => { record: any; objectNameSingular: string; }) => { - const setMetadataItems = useSetRecoilState(objectMetadataItemsState()); + const setMetadataItems = useSetRecoilState(objectMetadataItemsState); setMetadataItems(mockObjectMetadataItems); diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useGetRelationMetadata.test.tsx b/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useGetRelationMetadata.test.tsx index 4548662908..b13554ed6e 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useGetRelationMetadata.test.tsx +++ b/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useGetRelationMetadata.test.tsx @@ -31,7 +31,7 @@ describe('useGetRelationMetadata', () => { const { result } = renderHook( () => { - const setMetadataItems = useSetRecoilState(objectMetadataItemsState()); + const setMetadataItems = useSetRecoilState(objectMetadataItemsState); useEffect(() => { setMetadataItems(objectMetadataItems); diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useObjectMetadataItemForSettings.test.tsx b/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useObjectMetadataItemForSettings.test.tsx index e13c468e4e..c93057e2e8 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useObjectMetadataItemForSettings.test.tsx +++ b/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useObjectMetadataItemForSettings.test.tsx @@ -44,7 +44,7 @@ describe('useObjectMetadataItemForSettings', () => { it('should findActiveObjectMetadataItemBySlug', async () => { const { result } = renderHook( () => { - const setMetadataItems = useSetRecoilState(objectMetadataItemsState()); + const setMetadataItems = useSetRecoilState(objectMetadataItemsState); setMetadataItems(mockObjectMetadataItems); return useObjectMetadataItemForSettings(); @@ -64,7 +64,7 @@ describe('useObjectMetadataItemForSettings', () => { it('should findObjectMetadataItemById', async () => { const { result } = renderHook( () => { - const setMetadataItems = useSetRecoilState(objectMetadataItemsState()); + const setMetadataItems = useSetRecoilState(objectMetadataItemsState); setMetadataItems(mockObjectMetadataItems); return useObjectMetadataItemForSettings(); @@ -86,7 +86,7 @@ describe('useObjectMetadataItemForSettings', () => { it('should findObjectMetadataItemByNamePlural', async () => { const { result } = renderHook( () => { - const setMetadataItems = useSetRecoilState(objectMetadataItemsState()); + const setMetadataItems = useSetRecoilState(objectMetadataItemsState); setMetadataItems(mockObjectMetadataItems); return useObjectMetadataItemForSettings(); diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/useCreateOneObjectMetadataItem.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useCreateOneObjectMetadataItem.ts index e187ba8321..624cc4066f 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/useCreateOneObjectMetadataItem.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/useCreateOneObjectMetadataItem.ts @@ -28,7 +28,10 @@ export const useCreateOneObjectMetadataItem = () => { input: { object: input }, }, awaitRefetchQueries: true, - refetchQueries: [getOperationName(FIND_MANY_OBJECT_METADATA_ITEMS) ?? ''], + refetchQueries: [ + getOperationName(FIND_MANY_OBJECT_METADATA_ITEMS) ?? '', + 'FindManyRecordsMultipleMetadataItems', + ], }); }; diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/useGetObjectRecordIdentifierByNameSingular.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useGetObjectRecordIdentifierByNameSingular.ts index 53c878f873..be32e21629 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/useGetObjectRecordIdentifierByNameSingular.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/useGetObjectRecordIdentifierByNameSingular.ts @@ -5,7 +5,7 @@ import { getObjectRecordIdentifier } from '@/object-metadata/utils/getObjectReco import { ObjectRecordIdentifier } from '@/object-record/types/ObjectRecordIdentifier'; export const useGetObjectRecordIdentifierByNameSingular = () => { - const objectMetadataItems = useRecoilValue(objectMetadataItemsState()); + const objectMetadataItems = useRecoilValue(objectMetadataItemsState); return (record: any, objectNameSingular: string): ObjectRecordIdentifier => { const objectMetadataItem = objectMetadataItems.find( diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/useObjectMetadataItem.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useObjectMetadataItem.ts index 5bd2c94a36..a4edf8c39c 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/useObjectMetadataItem.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/useObjectMetadataItem.ts @@ -42,7 +42,7 @@ export const useObjectMetadataItem = ( depth?: number, eagerLoadedRelations?: Record, ) => { - const currentWorkspace = useRecoilValue(currentWorkspaceState()); + const currentWorkspace = useRecoilValue(currentWorkspaceState); const mockObjectMetadataItems = getObjectMetadataItemsMock(); @@ -53,7 +53,7 @@ export const useObjectMetadataItem = ( }), ); - let objectMetadataItems = useRecoilValue(objectMetadataItemsState()); + let objectMetadataItems = useRecoilValue(objectMetadataItemsState); if (currentWorkspace?.activationStatus !== 'active') { objectMetadataItem = diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/useObjectMetadataItemForSettings.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useObjectMetadataItemForSettings.ts index fce0388690..eb8bfe651f 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/useObjectMetadataItemForSettings.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/useObjectMetadataItemForSettings.ts @@ -5,7 +5,7 @@ import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadat import { getObjectSlug } from '../utils/getObjectSlug'; export const useObjectMetadataItemForSettings = () => { - const objectMetadataItems = useRecoilValue(objectMetadataItemsState()); + const objectMetadataItems = useRecoilValue(objectMetadataItemsState); const activeObjectMetadataItems = objectMetadataItems.filter( ({ isActive, isSystem }) => isActive && !isSystem, diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/useObjectMetadataItemOnly.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useObjectMetadataItemOnly.ts index aa74d57cc4..d5e5b3f552 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/useObjectMetadataItemOnly.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/useObjectMetadataItemOnly.ts @@ -12,7 +12,7 @@ import { ObjectMetadataItemIdentifier } from '../types/ObjectMetadataItemIdentif export const useObjectMetadataItemOnly = ({ objectNameSingular, }: ObjectMetadataItemIdentifier) => { - const currentWorkspace = useRecoilValue(currentWorkspaceState()); + const currentWorkspace = useRecoilValue(currentWorkspaceState); const mockObjectMetadataItems = getObjectMetadataItemsMock(); @@ -23,7 +23,7 @@ export const useObjectMetadataItemOnly = ({ }), ); - let objectMetadataItems = useRecoilValue(objectMetadataItemsState()); + let objectMetadataItems = useRecoilValue(objectMetadataItemsState); if (currentWorkspace?.activationStatus !== 'active') { objectMetadataItem = diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/useObjectMetadataItems.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useObjectMetadataItems.ts index 0085cccabc..215d61200c 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/useObjectMetadataItems.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/useObjectMetadataItems.ts @@ -3,7 +3,7 @@ import { useRecoilValue } from 'recoil'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; export const useObjectMetadataItems = () => { - const objectMetadataItems = useRecoilValue(objectMetadataItemsState()); + const objectMetadataItems = useRecoilValue(objectMetadataItemsState); return { objectMetadataItems, diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/useObjectNamePluralFromSingular.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useObjectNamePluralFromSingular.ts index 5af4b781f9..3cf1c60bbb 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/useObjectNamePluralFromSingular.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/useObjectNamePluralFromSingular.ts @@ -10,7 +10,7 @@ export const useObjectNamePluralFromSingular = ({ }: { objectNameSingular: string; }) => { - const currentWorkspace = useRecoilValue(currentWorkspaceState()); + const currentWorkspace = useRecoilValue(currentWorkspaceState); const mockObjectMetadataItems = getObjectMetadataItemsMock(); let objectMetadataItem = useRecoilValue( diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/useObjectNameSingularFromPlural.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useObjectNameSingularFromPlural.ts index 3e189e2247..432a3b7187 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/useObjectNameSingularFromPlural.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/useObjectNameSingularFromPlural.ts @@ -10,7 +10,7 @@ export const useObjectNameSingularFromPlural = ({ }: { objectNamePlural: string; }) => { - const currentWorkspace = useRecoilValue(currentWorkspaceState()); + const currentWorkspace = useRecoilValue(currentWorkspaceState); const mockObjectMetadataItems = getObjectMetadataItemsMock(); diff --git a/packages/twenty-front/src/modules/object-metadata/states/objectMetadataItemFamilySelector.ts b/packages/twenty-front/src/modules/object-metadata/states/objectMetadataItemFamilySelector.ts index 7e0d695b3e..b264758fba 100644 --- a/packages/twenty-front/src/modules/object-metadata/states/objectMetadataItemFamilySelector.ts +++ b/packages/twenty-front/src/modules/object-metadata/states/objectMetadataItemFamilySelector.ts @@ -16,7 +16,7 @@ export const objectMetadataItemFamilySelector = selectorFamily< get: ({ objectNameType, objectName }: ObjectMetadataItemSelector) => ({ get }) => { - const objectMetadataItems = get(objectMetadataItemsState()); + const objectMetadataItems = get(objectMetadataItemsState); if (objectNameType === 'singular') { return ( diff --git a/packages/twenty-front/src/modules/object-metadata/states/objectMetadataItemsByNamePluralMapSelector.ts b/packages/twenty-front/src/modules/object-metadata/states/objectMetadataItemsByNamePluralMapSelector.ts index 7168e5054e..30dfb115ef 100644 --- a/packages/twenty-front/src/modules/object-metadata/states/objectMetadataItemsByNamePluralMapSelector.ts +++ b/packages/twenty-front/src/modules/object-metadata/states/objectMetadataItemsByNamePluralMapSelector.ts @@ -8,7 +8,7 @@ export const objectMetadataItemsByNamePluralMapSelector = selector< >({ key: 'objectMetadataItemsByNamePluralMapSelector', get: ({ get }) => { - const objectMetadataItems = get(objectMetadataItemsState()); + const objectMetadataItems = get(objectMetadataItemsState); return new Map( objectMetadataItems.map((objectMetadataItem) => [ diff --git a/packages/twenty-front/src/modules/object-metadata/states/objectMetadataItemsByNameSingularMapSelector.ts b/packages/twenty-front/src/modules/object-metadata/states/objectMetadataItemsByNameSingularMapSelector.ts index 9111cc6c2d..2eddad42b1 100644 --- a/packages/twenty-front/src/modules/object-metadata/states/objectMetadataItemsByNameSingularMapSelector.ts +++ b/packages/twenty-front/src/modules/object-metadata/states/objectMetadataItemsByNameSingularMapSelector.ts @@ -8,7 +8,7 @@ export const objectMetadataItemsByNameSingularMapSelector = selector< >({ key: 'objectMetadataItemsByNameSingularMapSelector', get: ({ get }) => { - const objectMetadataItems = get(objectMetadataItemsState()); + const objectMetadataItems = get(objectMetadataItemsState); return new Map( objectMetadataItems.map((objectMetadataItem) => [ diff --git a/packages/twenty-front/src/modules/object-record/cache/hooks/useAddRecordInCache.ts b/packages/twenty-front/src/modules/object-record/cache/hooks/useAddRecordInCache.ts index c8d821927e..3ef788f6cc 100644 --- a/packages/twenty-front/src/modules/object-record/cache/hooks/useAddRecordInCache.ts +++ b/packages/twenty-front/src/modules/object-record/cache/hooks/useAddRecordInCache.ts @@ -15,7 +15,7 @@ export const useAddRecordInCache = ({ }: { objectMetadataItem: ObjectMetadataItem; }) => { - const objectMetadataItems = useRecoilValue(objectMetadataItemsState()); + const objectMetadataItems = useRecoilValue(objectMetadataItemsState); const apolloClient = useApolloClient(); const { injectIntoFindOneRecordQueryCache } = diff --git a/packages/twenty-front/src/modules/object-record/cache/hooks/useGetRecordFromCache.ts b/packages/twenty-front/src/modules/object-record/cache/hooks/useGetRecordFromCache.ts index ae30c58976..3f9e35a95c 100644 --- a/packages/twenty-front/src/modules/object-record/cache/hooks/useGetRecordFromCache.ts +++ b/packages/twenty-front/src/modules/object-record/cache/hooks/useGetRecordFromCache.ts @@ -1,3 +1,4 @@ +import { useCallback } from 'react'; import { gql, useApolloClient } from '@apollo/client'; import { useRecoilValue } from 'recoil'; @@ -13,21 +14,22 @@ export const useGetRecordFromCache = ({ }: { objectMetadataItem: ObjectMetadataItem; }) => { - const objectMetadataItems = useRecoilValue(objectMetadataItemsState()); + const objectMetadataItems = useRecoilValue(objectMetadataItemsState); const apolloClient = useApolloClient(); - return ( - recordId: string, - cache = apolloClient.cache, - ) => { - if (isUndefinedOrNull(objectMetadataItem)) { - return null; - } + return useCallback( + ( + recordId: string, + cache = apolloClient.cache, + ) => { + if (isUndefinedOrNull(objectMetadataItem)) { + return null; + } - const capitalizedObjectName = capitalize(objectMetadataItem.nameSingular); + const capitalizedObjectName = capitalize(objectMetadataItem.nameSingular); - const cacheReadFragment = gql` + const cacheReadFragment = gql` fragment ${capitalizedObjectName}Fragment on ${capitalizedObjectName} ${mapObjectMetadataToGraphQLQuery( { objectMetadataItems, @@ -36,14 +38,16 @@ export const useGetRecordFromCache = ({ )} `; - const cachedRecordId = cache.identify({ - __typename: capitalize(objectMetadataItem.nameSingular), - id: recordId, - }); + const cachedRecordId = cache.identify({ + __typename: capitalize(objectMetadataItem.nameSingular), + id: recordId, + }); - return cache.readFragment({ - id: cachedRecordId, - fragment: cacheReadFragment, - }); - }; + return cache.readFragment({ + id: cachedRecordId, + fragment: cacheReadFragment, + }); + }, + [objectMetadataItem, objectMetadataItems, apolloClient], + ); }; diff --git a/packages/twenty-front/src/modules/object-record/cache/utils/getRecordEdgeFromRecord.ts b/packages/twenty-front/src/modules/object-record/cache/utils/getRecordEdgeFromRecord.ts index b82b77ff84..86a09e9f8c 100644 --- a/packages/twenty-front/src/modules/object-record/cache/utils/getRecordEdgeFromRecord.ts +++ b/packages/twenty-front/src/modules/object-record/cache/utils/getRecordEdgeFromRecord.ts @@ -17,7 +17,8 @@ export const getRecordEdgeFromRecord = ({ return [ key, getRecordConnectionFromRecords({ - objectNameSingular: key, + // Todo: this is a ugly and broken hack to get the singular, we need to infer this from metadata + objectNameSingular: key.slice(0, -1), records: value as ObjectRecord[], }), ]; diff --git a/packages/twenty-front/src/modules/object-record/hooks/__tests__/useFindManyRecords.test.tsx b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useFindManyRecords.test.tsx index 9da0f77fc2..480e74bab6 100644 --- a/packages/twenty-front/src/modules/object-record/hooks/__tests__/useFindManyRecords.test.tsx +++ b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useFindManyRecords.test.tsx @@ -57,7 +57,7 @@ describe('useFindManyRecords', () => { const { result } = renderHook( () => { const setCurrentWorkspaceMember = useSetRecoilState( - currentWorkspaceMemberState(), + currentWorkspaceMemberState, ); setCurrentWorkspaceMember({ id: '32219445-f587-4c40-b2b1-6d3205ed96da', @@ -67,7 +67,7 @@ describe('useFindManyRecords', () => { const mockObjectMetadataItems = getObjectMetadataItemsMock(); - const setMetadataItems = useSetRecoilState(objectMetadataItemsState()); + const setMetadataItems = useSetRecoilState(objectMetadataItemsState); setMetadataItems(mockObjectMetadataItems); diff --git a/packages/twenty-front/src/modules/object-record/hooks/__tests__/useGenerateFindManyRecordsForMultipleMetadataItemsQuery.test.tsx b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useGenerateFindManyRecordsForMultipleMetadataItemsQuery.test.tsx index 2b1ef39614..9120bb026e 100644 --- a/packages/twenty-front/src/modules/object-record/hooks/__tests__/useGenerateFindManyRecordsForMultipleMetadataItemsQuery.test.tsx +++ b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useGenerateFindManyRecordsForMultipleMetadataItemsQuery.test.tsx @@ -16,7 +16,7 @@ describe('useGenerateFindManyRecordsForMultipleMetadataItemsQuery', () => { const mockObjectMetadataItems = getObjectMetadataItemsMock(); return useGenerateFindManyRecordsForMultipleMetadataItemsQuery({ - objectMetadataItems: mockObjectMetadataItems.slice(0, 2), + targetObjectMetadataItems: mockObjectMetadataItems.slice(0, 2), }); }, { diff --git a/packages/twenty-front/src/modules/object-record/hooks/__tests__/useMapConnectionToRecords.test.tsx b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useMapConnectionToRecords.test.tsx index a975e7cb07..6d58d3b7db 100644 --- a/packages/twenty-front/src/modules/object-record/hooks/__tests__/useMapConnectionToRecords.test.tsx +++ b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useMapConnectionToRecords.test.tsx @@ -18,7 +18,7 @@ import { isDefined } from '~/utils/isDefined'; const Wrapper = getJestHookWrapper({ apolloMocks: [], onInitializeRecoilSnapshot: (snapshot) => { - snapshot.set(objectMetadataItemsState(), getObjectMetadataItemsMock()); + snapshot.set(objectMetadataItemsState, getObjectMetadataItemsMock()); }, }); diff --git a/packages/twenty-front/src/modules/object-record/hooks/useFindManyRecords.ts b/packages/twenty-front/src/modules/object-record/hooks/useFindManyRecords.ts index f3d201bac4..4531e47e6e 100644 --- a/packages/twenty-front/src/modules/object-record/hooks/useFindManyRecords.ts +++ b/packages/twenty-front/src/modules/object-record/hooks/useFindManyRecords.ts @@ -69,7 +69,7 @@ export const useFindManyRecords = ({ ); const { enqueueSnackBar } = useSnackBar(); - const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState()); + const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); const { data, loading, error, fetchMore } = useQuery< ObjectRecordQueryResult diff --git a/packages/twenty-front/src/modules/object-record/hooks/useGenerateCreateManyRecordMutation.ts b/packages/twenty-front/src/modules/object-record/hooks/useGenerateCreateManyRecordMutation.ts index c36c99f5ce..686a5cc5ca 100644 --- a/packages/twenty-front/src/modules/object-record/hooks/useGenerateCreateManyRecordMutation.ts +++ b/packages/twenty-front/src/modules/object-record/hooks/useGenerateCreateManyRecordMutation.ts @@ -17,7 +17,7 @@ export const useGenerateCreateManyRecordMutation = ({ }: { objectMetadataItem: ObjectMetadataItem; }) => { - const objectMetadataItems = useRecoilValue(objectMetadataItemsState()); + const objectMetadataItems = useRecoilValue(objectMetadataItemsState); if (isUndefinedOrNull(objectMetadataItem)) { return EMPTY_MUTATION; diff --git a/packages/twenty-front/src/modules/object-record/hooks/useGenerateCreateOneRecordMutation.ts b/packages/twenty-front/src/modules/object-record/hooks/useGenerateCreateOneRecordMutation.ts index 61cef84604..b6837892af 100644 --- a/packages/twenty-front/src/modules/object-record/hooks/useGenerateCreateOneRecordMutation.ts +++ b/packages/twenty-front/src/modules/object-record/hooks/useGenerateCreateOneRecordMutation.ts @@ -17,7 +17,7 @@ export const useGenerateCreateOneRecordMutation = ({ }: { objectMetadataItem: ObjectMetadataItem; }) => { - const objectMetadataItems = useRecoilValue(objectMetadataItemsState()); + const objectMetadataItems = useRecoilValue(objectMetadataItemsState); if (isUndefinedOrNull(objectMetadataItem)) { return EMPTY_MUTATION; diff --git a/packages/twenty-front/src/modules/object-record/hooks/useGenerateExecuteQuickActionOnOneRecordMutation.ts b/packages/twenty-front/src/modules/object-record/hooks/useGenerateExecuteQuickActionOnOneRecordMutation.ts index 80719fe39f..0eb9d6b6c7 100644 --- a/packages/twenty-front/src/modules/object-record/hooks/useGenerateExecuteQuickActionOnOneRecordMutation.ts +++ b/packages/twenty-front/src/modules/object-record/hooks/useGenerateExecuteQuickActionOnOneRecordMutation.ts @@ -21,7 +21,7 @@ export const useGenerateExecuteQuickActionOnOneRecordMutation = ({ }: { objectMetadataItem: ObjectMetadataItem; }) => { - const objectMetadataItems = useRecoilValue(objectMetadataItemsState()); + const objectMetadataItems = useRecoilValue(objectMetadataItemsState); if (isUndefinedOrNull(objectMetadataItem)) { return EMPTY_MUTATION; diff --git a/packages/twenty-front/src/modules/object-record/hooks/useGenerateFindDuplicateRecordsQuery.ts b/packages/twenty-front/src/modules/object-record/hooks/useGenerateFindDuplicateRecordsQuery.ts index 51bba8e5fe..747018d0da 100644 --- a/packages/twenty-front/src/modules/object-record/hooks/useGenerateFindDuplicateRecordsQuery.ts +++ b/packages/twenty-front/src/modules/object-record/hooks/useGenerateFindDuplicateRecordsQuery.ts @@ -11,7 +11,7 @@ export const getFindDuplicateRecordsQueryResponseField = ( ) => `${objectNameSingular}Duplicates`; export const useGenerateFindDuplicateRecordsQuery = () => { - const objectMetadataItems = useRecoilValue(objectMetadataItemsState()); + const objectMetadataItems = useRecoilValue(objectMetadataItemsState); return ({ objectMetadataItem, diff --git a/packages/twenty-front/src/modules/object-record/hooks/useGenerateFindManyRecordsForMultipleMetadataItemsQuery.ts b/packages/twenty-front/src/modules/object-record/hooks/useGenerateFindManyRecordsForMultipleMetadataItemsQuery.ts index a85b4068d6..60b1ca38f0 100644 --- a/packages/twenty-front/src/modules/object-record/hooks/useGenerateFindManyRecordsForMultipleMetadataItemsQuery.ts +++ b/packages/twenty-front/src/modules/object-record/hooks/useGenerateFindManyRecordsForMultipleMetadataItemsQuery.ts @@ -8,14 +8,14 @@ import { isNonEmptyArray } from '~/utils/isNonEmptyArray'; import { capitalize } from '~/utils/string/capitalize'; export const useGenerateFindManyRecordsForMultipleMetadataItemsQuery = ({ - objectMetadataItems, + targetObjectMetadataItems, depth, }: { - objectMetadataItems: ObjectMetadataItem[]; + targetObjectMetadataItems: ObjectMetadataItem[]; depth?: number; }) => { - const allObjectMetadataItems = useRecoilValue(objectMetadataItemsState()); - const capitalizedObjectNameSingulars = objectMetadataItems.map( + const objectMetadataItems = useRecoilValue(objectMetadataItemsState); + const capitalizedObjectNameSingulars = targetObjectMetadataItems.map( ({ nameSingular }) => capitalize(nameSingular), ); @@ -58,7 +58,7 @@ export const useGenerateFindManyRecordsForMultipleMetadataItemsQuery = ({ ${lastCursorPerMetadataItemArray}, ${limitPerMetadataItemArray} ) { - ${objectMetadataItems + ${targetObjectMetadataItems .map( (objectMetadataItem) => `${objectMetadataItem.namePlural}(filter: $filter${capitalize( @@ -72,7 +72,7 @@ export const useGenerateFindManyRecordsForMultipleMetadataItemsQuery = ({ )}){ edges { node ${mapObjectMetadataToGraphQLQuery({ - objectMetadataItems: allObjectMetadataItems, + objectMetadataItems: objectMetadataItems, objectMetadataItem, depth, })} diff --git a/packages/twenty-front/src/modules/object-record/hooks/useGenerateFindManyRecordsQuery.ts b/packages/twenty-front/src/modules/object-record/hooks/useGenerateFindManyRecordsQuery.ts index db6d077817..5a21fe3de6 100644 --- a/packages/twenty-front/src/modules/object-record/hooks/useGenerateFindManyRecordsQuery.ts +++ b/packages/twenty-front/src/modules/object-record/hooks/useGenerateFindManyRecordsQuery.ts @@ -7,7 +7,7 @@ import { mapObjectMetadataToGraphQLQuery } from '@/object-metadata/utils/mapObje import { capitalize } from '~/utils/string/capitalize'; export const useGenerateFindManyRecordsQuery = () => { - const objectMetadataItems = useRecoilValue(objectMetadataItemsState()); + const objectMetadataItems = useRecoilValue(objectMetadataItemsState); return ({ objectMetadataItem, diff --git a/packages/twenty-front/src/modules/object-record/hooks/useGenerateFindOneRecordQuery.ts b/packages/twenty-front/src/modules/object-record/hooks/useGenerateFindOneRecordQuery.ts index 77a14395a8..e9260cd710 100644 --- a/packages/twenty-front/src/modules/object-record/hooks/useGenerateFindOneRecordQuery.ts +++ b/packages/twenty-front/src/modules/object-record/hooks/useGenerateFindOneRecordQuery.ts @@ -7,7 +7,7 @@ import { mapObjectMetadataToGraphQLQuery } from '@/object-metadata/utils/mapObje import { capitalize } from '~/utils/string/capitalize'; export const useGenerateFindOneRecordQuery = () => { - const objectMetadataItems = useRecoilValue(objectMetadataItemsState()); + const objectMetadataItems = useRecoilValue(objectMetadataItemsState); return ({ objectMetadataItem, diff --git a/packages/twenty-front/src/modules/object-record/hooks/useGenerateUpdateOneRecordMutation.ts b/packages/twenty-front/src/modules/object-record/hooks/useGenerateUpdateOneRecordMutation.ts index 1ba33a915d..8880f3a0b8 100644 --- a/packages/twenty-front/src/modules/object-record/hooks/useGenerateUpdateOneRecordMutation.ts +++ b/packages/twenty-front/src/modules/object-record/hooks/useGenerateUpdateOneRecordMutation.ts @@ -17,7 +17,7 @@ export const useGenerateUpdateOneRecordMutation = ({ }: { objectMetadataItem: ObjectMetadataItem; }) => { - const objectMetadataItems = useRecoilValue(objectMetadataItemsState()); + const objectMetadataItems = useRecoilValue(objectMetadataItemsState); if (isUndefinedOrNull(objectMetadataItem)) { return EMPTY_MUTATION; diff --git a/packages/twenty-front/src/modules/object-record/hooks/useMapConnectionToRecords.ts b/packages/twenty-front/src/modules/object-record/hooks/useMapConnectionToRecords.ts index bde4e4e92c..a682f1e2b6 100644 --- a/packages/twenty-front/src/modules/object-record/hooks/useMapConnectionToRecords.ts +++ b/packages/twenty-front/src/modules/object-record/hooks/useMapConnectionToRecords.ts @@ -11,7 +11,7 @@ import { FieldMetadataType } from '~/generated/graphql'; import { isDefined } from '~/utils/isDefined'; export const useMapConnectionToRecords = () => { - const objectMetadataItems = useRecoilValue(objectMetadataItemsState()); + const objectMetadataItems = useRecoilValue(objectMetadataItemsState); const mapConnectionToRecords = useCallback( ({ diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/MultipleFiltersDropdownContent.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/MultipleFiltersDropdownContent.tsx index 070d8bf8e4..152fb1f82a 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/MultipleFiltersDropdownContent.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/MultipleFiltersDropdownContent.tsx @@ -1,3 +1,5 @@ +import { useRecoilValue } from 'recoil'; + import { ObjectFilterDropdownSearchInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownSearchInput'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator'; @@ -20,11 +22,21 @@ export const MultipleFiltersDropdownContent = ({ filterDropdownId, }: MultipleFiltersDropdownContentProps) => { const { - isObjectFilterDropdownOperandSelectUnfolded, - filterDefinitionUsedInDropdown, - selectedOperandInDropdown, + isObjectFilterDropdownOperandSelectUnfoldedState, + filterDefinitionUsedInDropdownState, + selectedOperandInDropdownState, } = useFilterDropdown({ filterDropdownId }); + const isObjectFilterDropdownOperandSelectUnfolded = useRecoilValue( + isObjectFilterDropdownOperandSelectUnfoldedState, + ); + const filterDefinitionUsedInDropdown = useRecoilValue( + filterDefinitionUsedInDropdownState, + ); + const selectedOperandInDropdown = useRecoilValue( + selectedOperandInDropdownState, + ); + return ( <> {!filterDefinitionUsedInDropdown ? ( diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownButton.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownButton.tsx index 0a4a16e62b..3b56727837 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownButton.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownButton.tsx @@ -1,3 +1,5 @@ +import { useRecoilValue } from 'recoil'; + import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { ObjectFilterDropdownScope } from '@/object-record/object-filter-dropdown/scopes/ObjectFilterDropdownScope'; import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope'; @@ -14,9 +16,14 @@ export const ObjectFilterDropdownButton = ({ filterDropdownId, hotkeyScope, }: ObjectFilterDropdownButtonProps) => { - const { availableFilterDefinitions } = useFilterDropdown({ + const { availableFilterDefinitionsState } = useFilterDropdown({ filterDropdownId: filterDropdownId, }); + + const availableFilterDefinitions = useRecoilValue( + availableFilterDefinitionsState, + ); + const hasOnlyOneEntityFilter = availableFilterDefinitions.length === 1 && availableFilterDefinitions[0].type === 'RELATION'; diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownDateInput.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownDateInput.tsx index d3098859ef..11c9f1ab28 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownDateInput.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownDateInput.tsx @@ -1,15 +1,24 @@ +import { useRecoilValue } from 'recoil'; + import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { InternalDatePicker } from '@/ui/input/components/internal/date/components/InternalDatePicker'; import { isDefined } from '~/utils/isDefined'; export const ObjectFilterDropdownDateInput = () => { const { - filterDefinitionUsedInDropdown, - selectedOperandInDropdown, + filterDefinitionUsedInDropdownState, + selectedOperandInDropdownState, setIsObjectFilterDropdownUnfolded, selectFilter, } = useFilterDropdown(); + const filterDefinitionUsedInDropdown = useRecoilValue( + filterDefinitionUsedInDropdownState, + ); + const selectedOperandInDropdown = useRecoilValue( + selectedOperandInDropdownState, + ); + const handleChange = (date: Date | null) => { if (!filterDefinitionUsedInDropdown || !selectedOperandInDropdown) return; diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownEntitySearchSelect.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownEntitySearchSelect.tsx index 0d19879da2..27b1559750 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownEntitySearchSelect.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownEntitySearchSelect.tsx @@ -1,4 +1,5 @@ import { useEffect, useState } from 'react'; +import { useRecoilValue } from 'recoil'; import { OBJECT_FILTER_DROPDOWN_ID } from '@/object-record/object-filter-dropdown/constants/ObjectFilterDropdownId'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; @@ -15,13 +16,24 @@ export const ObjectFilterDropdownEntitySearchSelect = ({ }) => { const { setObjectFilterDropdownSelectedEntityId, - filterDefinitionUsedInDropdown, - selectedOperandInDropdown, - objectFilterDropdownSearchInput, - selectedFilter, + filterDefinitionUsedInDropdownState, + selectedOperandInDropdownState, + objectFilterDropdownSearchInputState, + selectedFilterState, selectFilter, } = useFilterDropdown(); + const filterDefinitionUsedInDropdown = useRecoilValue( + filterDefinitionUsedInDropdownState, + ); + const selectedOperandInDropdown = useRecoilValue( + selectedOperandInDropdownState, + ); + const objectFilterDropdownSearchInput = useRecoilValue( + objectFilterDropdownSearchInputState, + ); + const selectedFilter = useRecoilValue(selectedFilterState); + const { closeDropdown } = useDropdown(OBJECT_FILTER_DROPDOWN_ID); const [isAllEntitySelected, setIsAllEntitySelected] = useState(false); diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect.tsx index 93bc71a1be..676fcb9a32 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect.tsx @@ -1,3 +1,5 @@ +import { useRecoilValue } from 'recoil'; + import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope'; import { useIcons } from '@/ui/display/icon/hooks/useIcons'; @@ -12,9 +14,13 @@ export const ObjectFilterDropdownFilterSelect = () => { setFilterDefinitionUsedInDropdown, setSelectedOperandInDropdown, setObjectFilterDropdownSearchInput, - availableFilterDefinitions, + availableFilterDefinitionsState, } = useFilterDropdown(); + const availableFilterDefinitions = useRecoilValue( + availableFilterDefinitionsState, + ); + const { getIcon } = useIcons(); const setHotkeyScope = useSetHotkeyScope(); diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownNumberInput.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownNumberInput.tsx index aec6377140..d6cc92eaaf 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownNumberInput.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownNumberInput.tsx @@ -1,15 +1,23 @@ import { ChangeEvent } from 'react'; +import { useRecoilValue } from 'recoil'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { DropdownMenuInput } from '@/ui/layout/dropdown/components/DropdownMenuInput'; export const ObjectFilterDropdownNumberInput = () => { const { - selectedOperandInDropdown, - filterDefinitionUsedInDropdown, + selectedOperandInDropdownState, + filterDefinitionUsedInDropdownState, selectFilter, } = useFilterDropdown(); + const filterDefinitionUsedInDropdown = useRecoilValue( + filterDefinitionUsedInDropdownState, + ); + const selectedOperandInDropdown = useRecoilValue( + selectedOperandInDropdownState, + ); + return ( filterDefinitionUsedInDropdown && selectedOperandInDropdown && ( diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOperandButton.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOperandButton.tsx index 7c5e0b2513..6641de0dd4 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOperandButton.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOperandButton.tsx @@ -1,3 +1,5 @@ +import { useRecoilValue } from 'recoil'; + import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { IconChevronDown } from '@/ui/display/icon'; import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader'; @@ -6,11 +8,18 @@ import { getOperandLabel } from '../utils/getOperandLabel'; export const ObjectFilterDropdownOperandButton = () => { const { - selectedOperandInDropdown, + selectedOperandInDropdownState, setIsObjectFilterDropdownOperandSelectUnfolded, - isObjectFilterDropdownOperandSelectUnfolded, + isObjectFilterDropdownOperandSelectUnfoldedState, } = useFilterDropdown(); + const selectedOperandInDropdown = useRecoilValue( + selectedOperandInDropdownState, + ); + const isObjectFilterDropdownOperandSelectUnfolded = useRecoilValue( + isObjectFilterDropdownOperandSelectUnfoldedState, + ); + if (isObjectFilterDropdownOperandSelectUnfolded) { return null; } diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOperandSelect.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOperandSelect.tsx index 43886b3921..d3f0ccccfd 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOperandSelect.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOperandSelect.tsx @@ -1,3 +1,5 @@ +import { useRecoilValue } from 'recoil'; + import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem'; @@ -9,14 +11,24 @@ import { getOperandsForFilterType } from '../utils/getOperandsForFilterType'; export const ObjectFilterDropdownOperandSelect = () => { const { - filterDefinitionUsedInDropdown, + filterDefinitionUsedInDropdownState, setSelectedOperandInDropdown, - isObjectFilterDropdownOperandSelectUnfolded, + isObjectFilterDropdownOperandSelectUnfoldedState, setIsObjectFilterDropdownOperandSelectUnfolded, - selectedFilter, + selectedFilterState, selectFilter, } = useFilterDropdown(); + const filterDefinitionUsedInDropdown = useRecoilValue( + filterDefinitionUsedInDropdownState, + ); + + const isObjectFilterDropdownOperandSelectUnfolded = useRecoilValue( + isObjectFilterDropdownOperandSelectUnfoldedState, + ); + + const selectedFilter = useRecoilValue(selectedFilterState); + const operandsForFilterType = getOperandsForFilterType( filterDefinitionUsedInDropdown?.type, ); diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOptionSelect.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOptionSelect.tsx index db46aa88d1..9e09777fa5 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOptionSelect.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOptionSelect.tsx @@ -1,4 +1,5 @@ import { useEffect, useState } from 'react'; +import { useRecoilValue } from 'recoil'; import { MenuItem, MenuItemMultiSelect } from 'tsup.ui.index'; import { FieldMetadataItemOption } from '@/object-metadata/types/FieldMetadataItem'; @@ -16,13 +17,26 @@ type SelectOptionForFilter = FieldMetadataItemOption & { export const ObjectFilterDropdownOptionSelect = () => { const { - filterDefinitionUsedInDropdown, - objectFilterDropdownSearchInput, - selectedOperandInDropdown, - objectFilterDropdownSelectedOptionValues, + filterDefinitionUsedInDropdownState, + objectFilterDropdownSearchInputState, + selectedOperandInDropdownState, + objectFilterDropdownSelectedOptionValuesState, selectFilter, } = useFilterDropdown(); + const filterDefinitionUsedInDropdown = useRecoilValue( + filterDefinitionUsedInDropdownState, + ); + const selectedOperandInDropdown = useRecoilValue( + selectedOperandInDropdownState, + ); + const objectFilterDropdownSearchInput = useRecoilValue( + objectFilterDropdownSearchInputState, + ); + const objectFilterDropdownSelectedOptionValues = useRecoilValue( + objectFilterDropdownSelectedOptionValuesState, + ); + const fieldMetaDataId = filterDefinitionUsedInDropdown?.fieldMetadataId ?? ''; const { selectOptions } = useOptionsForSelect(fieldMetaDataId); diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownRecordSelect.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownRecordSelect.tsx index 0b41a5c5df..65a2c3263d 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownRecordSelect.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownRecordSelect.tsx @@ -1,3 +1,5 @@ +import { useRecoilValue } from 'recoil'; + import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { MultipleRecordSelectDropdown } from '@/object-record/select/components/MultipleRecordSelectDropdown'; import { useRecordsForSelect } from '@/object-record/select/hooks/useRecordsForSelect'; @@ -9,15 +11,28 @@ export const MAX_RECORDS_TO_DISPLAY = 3; export const ObjectFilterDropdownRecordSelect = () => { const { - filterDefinitionUsedInDropdown, - objectFilterDropdownSearchInput, - selectedOperandInDropdown, + filterDefinitionUsedInDropdownState, + objectFilterDropdownSearchInputState, + selectedOperandInDropdownState, setObjectFilterDropdownSelectedRecordIds, - objectFilterDropdownSelectedRecordIds, + objectFilterDropdownSelectedRecordIdsState, selectFilter, emptyFilterButKeepDefinition, } = useFilterDropdown(); + const filterDefinitionUsedInDropdown = useRecoilValue( + filterDefinitionUsedInDropdownState, + ); + const objectFilterDropdownSearchInput = useRecoilValue( + objectFilterDropdownSearchInputState, + ); + const selectedOperandInDropdown = useRecoilValue( + selectedOperandInDropdownState, + ); + const objectFilterDropdownSelectedRecordIds = useRecoilValue( + objectFilterDropdownSelectedRecordIdsState, + ); + const objectNameSingular = filterDefinitionUsedInDropdown?.relationObjectMetadataNameSingular ?? ''; diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownSearchInput.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownSearchInput.tsx index 1a45f6aa37..d84d2e4dde 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownSearchInput.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownSearchInput.tsx @@ -1,16 +1,27 @@ import { ChangeEvent } from 'react'; +import { useRecoilValue } from 'recoil'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput'; export const ObjectFilterDropdownSearchInput = () => { const { - filterDefinitionUsedInDropdown, - selectedOperandInDropdown, - objectFilterDropdownSearchInput, + filterDefinitionUsedInDropdownState, + selectedOperandInDropdownState, + objectFilterDropdownSearchInputState, setObjectFilterDropdownSearchInput, } = useFilterDropdown(); + const filterDefinitionUsedInDropdown = useRecoilValue( + filterDefinitionUsedInDropdownState, + ); + const selectedOperandInDropdown = useRecoilValue( + selectedOperandInDropdownState, + ); + const objectFilterDropdownSearchInput = useRecoilValue( + objectFilterDropdownSearchInputState, + ); + return ( filterDefinitionUsedInDropdown && selectedOperandInDropdown && ( diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownTextSearchInput.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownTextSearchInput.tsx index 999fd64030..445d080ad6 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownTextSearchInput.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownTextSearchInput.tsx @@ -1,18 +1,30 @@ import { ChangeEvent } from 'react'; +import { useRecoilValue } from 'recoil'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput'; export const ObjectFilterDropdownTextSearchInput = () => { const { - filterDefinitionUsedInDropdown, - selectedOperandInDropdown, - objectFilterDropdownSearchInput, + filterDefinitionUsedInDropdownState, + selectedOperandInDropdownState, + objectFilterDropdownSearchInputState, setObjectFilterDropdownSearchInput, - selectedFilter, + selectedFilterState, selectFilter, } = useFilterDropdown(); + const filterDefinitionUsedInDropdown = useRecoilValue( + filterDefinitionUsedInDropdownState, + ); + const selectedOperandInDropdown = useRecoilValue( + selectedOperandInDropdownState, + ); + const objectFilterDropdownSearchInput = useRecoilValue( + objectFilterDropdownSearchInputState, + ); + const selectedFilter = useRecoilValue(selectedFilterState); + return ( filterDefinitionUsedInDropdown && selectedOperandInDropdown && ( diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/SingleEntityObjectFilterDropdownButton.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/SingleEntityObjectFilterDropdownButton.tsx index 8e8d52fe5b..e6de651105 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/SingleEntityObjectFilterDropdownButton.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/SingleEntityObjectFilterDropdownButton.tsx @@ -1,5 +1,6 @@ import React from 'react'; import { useTheme } from '@emotion/react'; +import { useRecoilValue } from 'recoil'; import { ObjectFilterDropdownRecordRemoveFilterMenuItem } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownRecordRemoveFilterMenuItem'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; @@ -22,12 +23,17 @@ export const SingleEntityObjectFilterDropdownButton = ({ hotkeyScope: HotkeyScope; }) => { const { - availableFilterDefinitions, - selectedFilter, + availableFilterDefinitionsState, + selectedFilterState, setFilterDefinitionUsedInDropdown, setSelectedOperandInDropdown, } = useFilterDropdown(); + const availableFilterDefinitions = useRecoilValue( + availableFilterDefinitionsState, + ); + const selectedFilter = useRecoilValue(selectedFilterState); + const availableFilter = availableFilterDefinitions[0]; React.useEffect(() => { diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/__tests__/useFilterDropdown.test.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/__tests__/useFilterDropdown.test.tsx index 76316b9dcd..3b3cd45a44 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/__tests__/useFilterDropdown.test.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/__tests__/useFilterDropdown.test.tsx @@ -1,8 +1,9 @@ import { expect } from '@storybook/test'; import { act, renderHook, waitFor } from '@testing-library/react'; -import { RecoilRoot } from 'recoil'; +import { RecoilRoot, useRecoilState } from 'recoil'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; +import { useFilterDropdownStates } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdownStates'; import { Filter } from '@/object-record/object-filter-dropdown/types/Filter'; import { FilterDefinition } from '@/object-record/object-filter-dropdown/types/FilterDefinition'; import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; @@ -31,10 +32,15 @@ const mockFilter: Filter = { describe('useFilterDropdown', () => { it('should set availableFilterDefinitions', async () => { - const { result } = renderHook( - () => useFilterDropdown({ filterDropdownId }), - renderHookConfig, - ); + const { result } = renderHook(() => { + useFilterDropdown({ filterDropdownId }); + const { availableFilterDefinitionsState } = + useFilterDropdownStates(filterDropdownId); + + const [availableFilterDefinitions, setAvailableFilterDefinitions] = + useRecoilState(availableFilterDefinitionsState); + return { availableFilterDefinitions, setAvailableFilterDefinitions }; + }, renderHookConfig); expect(result.current.availableFilterDefinitions).toEqual([]); @@ -50,10 +56,14 @@ describe('useFilterDropdown', () => { }); it('should set onFilterSelect', async () => { - const { result } = renderHook( - () => useFilterDropdown({ filterDropdownId }), - renderHookConfig, - ); + const { result } = renderHook(() => { + useFilterDropdown({ filterDropdownId }); + const { onFilterSelectState } = useFilterDropdownStates(filterDropdownId); + + const [onFilterSelect, setOnFilterSelect] = + useRecoilState(onFilterSelectState); + return { onFilterSelect, setOnFilterSelect }; + }, renderHookConfig); expect(result.current.onFilterSelect).toBeUndefined(); @@ -68,10 +78,16 @@ describe('useFilterDropdown', () => { }); it('should set selectedOperandInDropdown', async () => { - const { result } = renderHook( - () => useFilterDropdown({ filterDropdownId }), - renderHookConfig, - ); + const { result } = renderHook(() => { + useFilterDropdown({ filterDropdownId }); + const { selectedOperandInDropdownState } = + useFilterDropdownStates(filterDropdownId); + + const [selectedOperandInDropdown, setSelectedOperandInDropdown] = + useRecoilState(selectedOperandInDropdownState); + return { selectedOperandInDropdown, setSelectedOperandInDropdown }; + }, renderHookConfig); + const mockOperand = ViewFilterOperand.Contains; expect(result.current.selectedOperandInDropdown).toBeNull(); @@ -84,10 +100,14 @@ describe('useFilterDropdown', () => { }); it('should set selectedFilter', async () => { - const { result } = renderHook( - () => useFilterDropdown({ filterDropdownId }), - renderHookConfig, - ); + const { result } = renderHook(() => { + useFilterDropdown({ filterDropdownId }); + const { selectedFilterState } = useFilterDropdownStates(filterDropdownId); + + const [selectedFilter, setSelectedFilter] = + useRecoilState(selectedFilterState); + return { selectedFilter, setSelectedFilter }; + }, renderHookConfig); expect(result.current.selectedFilter).toBeUndefined(); @@ -101,10 +121,20 @@ describe('useFilterDropdown', () => { }); it('should set filterDefinitionUsedInDropdown', async () => { - const { result } = renderHook( - () => useFilterDropdown({ filterDropdownId }), - renderHookConfig, - ); + const { result } = renderHook(() => { + useFilterDropdown({ filterDropdownId }); + const { filterDefinitionUsedInDropdownState } = + useFilterDropdownStates(filterDropdownId); + + const [ + filterDefinitionUsedInDropdown, + setFilterDefinitionUsedInDropdown, + ] = useRecoilState(filterDefinitionUsedInDropdownState); + return { + filterDefinitionUsedInDropdown, + setFilterDefinitionUsedInDropdown, + }; + }, renderHookConfig); expect(result.current.filterDefinitionUsedInDropdown).toBeNull(); @@ -121,10 +151,20 @@ describe('useFilterDropdown', () => { it('should set objectFilterDropdownSearchInput', async () => { const mockResult = 'value'; - const { result } = renderHook( - () => useFilterDropdown({ filterDropdownId }), - renderHookConfig, - ); + const { result } = renderHook(() => { + useFilterDropdown({ filterDropdownId }); + const { objectFilterDropdownSearchInputState } = + useFilterDropdownStates(filterDropdownId); + + const [ + objectFilterDropdownSearchInput, + setObjectFilterDropdownSearchInput, + ] = useRecoilState(objectFilterDropdownSearchInputState); + return { + objectFilterDropdownSearchInput, + setObjectFilterDropdownSearchInput, + }; + }, renderHookConfig); expect(result.current.objectFilterDropdownSearchInput).toBe(''); @@ -139,10 +179,20 @@ describe('useFilterDropdown', () => { it('should set objectFilterDropdownSelectedEntityId', async () => { const mockResult = 'value'; - const { result } = renderHook( - () => useFilterDropdown({ filterDropdownId }), - renderHookConfig, - ); + const { result } = renderHook(() => { + useFilterDropdown({ filterDropdownId }); + const { objectFilterDropdownSelectedEntityIdState } = + useFilterDropdownStates(filterDropdownId); + + const [ + objectFilterDropdownSelectedEntityId, + setObjectFilterDropdownSelectedEntityId, + ] = useRecoilState(objectFilterDropdownSelectedEntityIdState); + return { + objectFilterDropdownSelectedEntityId, + setObjectFilterDropdownSelectedEntityId, + }; + }, renderHookConfig); expect(result.current.objectFilterDropdownSelectedEntityId).toBeNull(); @@ -159,10 +209,20 @@ describe('useFilterDropdown', () => { it('should set objectFilterDropdownSelectedRecordIds', async () => { const mockResult = ['id-0', 'id-1', 'id-2']; - const { result } = renderHook( - () => useFilterDropdown({ filterDropdownId }), - renderHookConfig, - ); + const { result } = renderHook(() => { + useFilterDropdown({ filterDropdownId }); + const { objectFilterDropdownSelectedRecordIdsState } = + useFilterDropdownStates(filterDropdownId); + + const [ + objectFilterDropdownSelectedRecordIds, + setObjectFilterDropdownSelectedRecordIds, + ] = useRecoilState(objectFilterDropdownSelectedRecordIdsState); + return { + objectFilterDropdownSelectedRecordIds, + setObjectFilterDropdownSelectedRecordIds, + }; + }, renderHookConfig); expect(result.current.objectFilterDropdownSelectedRecordIds).toHaveLength( 0, @@ -180,10 +240,20 @@ describe('useFilterDropdown', () => { }); it('should set isObjectFilterDropdownOperandSelectUnfolded', async () => { - const { result } = renderHook( - () => useFilterDropdown({ filterDropdownId }), - renderHookConfig, - ); + const { result } = renderHook(() => { + useFilterDropdown({ filterDropdownId }); + const { isObjectFilterDropdownOperandSelectUnfoldedState } = + useFilterDropdownStates(filterDropdownId); + + const [ + isObjectFilterDropdownOperandSelectUnfolded, + setIsObjectFilterDropdownOperandSelectUnfolded, + ] = useRecoilState(isObjectFilterDropdownOperandSelectUnfoldedState); + return { + isObjectFilterDropdownOperandSelectUnfolded, + setIsObjectFilterDropdownOperandSelectUnfolded, + }; + }, renderHookConfig); expect(result.current.isObjectFilterDropdownOperandSelectUnfolded).toBe( false, @@ -201,10 +271,20 @@ describe('useFilterDropdown', () => { }); it('should set isObjectFilterDropdownUnfolded', async () => { - const { result } = renderHook( - () => useFilterDropdown({ filterDropdownId }), - renderHookConfig, - ); + const { result } = renderHook(() => { + useFilterDropdown({ filterDropdownId }); + const { isObjectFilterDropdownUnfoldedState } = + useFilterDropdownStates(filterDropdownId); + + const [ + isObjectFilterDropdownUnfolded, + setIsObjectFilterDropdownUnfolded, + ] = useRecoilState(isObjectFilterDropdownUnfoldedState); + return { + isObjectFilterDropdownUnfolded, + setIsObjectFilterDropdownUnfolded, + }; + }, renderHookConfig); expect(result.current.isObjectFilterDropdownUnfolded).toBe(false); @@ -218,10 +298,16 @@ describe('useFilterDropdown', () => { }); it('should reset filter', async () => { - const { result } = renderHook( - () => useFilterDropdown({ filterDropdownId }), - renderHookConfig, - ); + const { result } = renderHook(() => { + const { selectFilter, resetFilter } = useFilterDropdown({ + filterDropdownId, + }); + const { selectedFilterState } = useFilterDropdownStates(filterDropdownId); + + const [selectedFilter, setSelectedFilter] = + useRecoilState(selectedFilterState); + return { selectedFilter, setSelectedFilter, selectFilter, resetFilter }; + }, renderHookConfig); act(() => { result.current.selectFilter(mockFilter); @@ -241,10 +327,14 @@ describe('useFilterDropdown', () => { }); it('should call onFilterSelect when a filter option is set', async () => { - const { result } = renderHook( - () => useFilterDropdown({ filterDropdownId }), - renderHookConfig, - ); + const { result } = renderHook(() => { + const { selectFilter } = useFilterDropdown({ filterDropdownId }); + const { onFilterSelectState } = useFilterDropdownStates(filterDropdownId); + + const [onFilterSelect, setOnFilterSelect] = + useRecoilState(onFilterSelectState); + return { onFilterSelect, setOnFilterSelect, selectFilter }; + }, renderHookConfig); const onFilterSelectMock = jest.fn(); expect(result.current.onFilterSelect).toBeUndefined(); diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useFilterDropdown.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useFilterDropdown.ts index 90d6f77f1e..945d19c689 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useFilterDropdown.ts +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useFilterDropdown.ts @@ -1,7 +1,8 @@ -import { useCallback } from 'react'; +import { useRecoilCallback, useSetRecoilState } from 'recoil'; import { useFilterDropdownStates } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdownStates'; import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId'; +import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; import { ObjectFilterDropdownScopeInternalContext } from '../scopes/scope-internal-context/ObjectFilterDropdownScopeInternalContext'; import { Filter } from '../types/Filter'; @@ -17,92 +18,122 @@ export const useFilterDropdown = (props?: UseFilterDropdownProps) => { ); const { - availableFilterDefinitions, - setAvailableFilterDefinitions, - filterDefinitionUsedInDropdown, - setFilterDefinitionUsedInDropdown, - objectFilterDropdownSearchInput, - setObjectFilterDropdownSearchInput, - objectFilterDropdownSelectedEntityId, - setObjectFilterDropdownSelectedEntityId, - objectFilterDropdownSelectedRecordIds, - setObjectFilterDropdownSelectedRecordIds, - objectFilterDropdownSelectedOptionValues, - setObjectFilterDropdownSelectedOptionValues, - isObjectFilterDropdownOperandSelectUnfolded, - setIsObjectFilterDropdownOperandSelectUnfolded, - isObjectFilterDropdownUnfolded, - setIsObjectFilterDropdownUnfolded, - selectedFilter, - setSelectedFilter, - selectedOperandInDropdown, - setSelectedOperandInDropdown, - onFilterSelect, - setOnFilterSelect, + availableFilterDefinitionsState, + filterDefinitionUsedInDropdownState, + objectFilterDropdownSearchInputState, + objectFilterDropdownSelectedEntityIdState, + objectFilterDropdownSelectedRecordIdsState, + objectFilterDropdownSelectedOptionValuesState, + isObjectFilterDropdownOperandSelectUnfoldedState, + isObjectFilterDropdownUnfoldedState, + selectedFilterState, + selectedOperandInDropdownState, + onFilterSelectState, } = useFilterDropdownStates(scopeId); - const selectFilter = useCallback( - (filter: Filter | null) => { - setSelectedFilter(filter); - onFilterSelect?.(filter); - }, - [setSelectedFilter, onFilterSelect], + const selectFilter = useRecoilCallback( + ({ set, snapshot }) => + (filter: Filter | null) => { + set(selectedFilterState, filter); + const onFilterSelect = getSnapshotValue(snapshot, onFilterSelectState); + + onFilterSelect?.(filter); + }, + [selectedFilterState, onFilterSelectState], ); - const emptyFilterButKeepDefinition = useCallback(() => { - setObjectFilterDropdownSearchInput(''); - setObjectFilterDropdownSelectedEntityId(null); - setObjectFilterDropdownSelectedRecordIds([]); - setSelectedFilter(undefined); - }, [ - setSelectedFilter, - setObjectFilterDropdownSelectedRecordIds, - setObjectFilterDropdownSelectedEntityId, - setObjectFilterDropdownSearchInput, - ]); + const emptyFilterButKeepDefinition = useRecoilCallback( + ({ set }) => + () => { + set(objectFilterDropdownSearchInputState, ''); + set(objectFilterDropdownSelectedEntityIdState, null); + set(objectFilterDropdownSelectedRecordIdsState, []); + set(selectedFilterState, undefined); + }, + [ + objectFilterDropdownSearchInputState, + objectFilterDropdownSelectedEntityIdState, + objectFilterDropdownSelectedRecordIdsState, + selectedFilterState, + ], + ); - const resetFilter = useCallback(() => { - setObjectFilterDropdownSearchInput(''); - setObjectFilterDropdownSelectedEntityId(null); - setObjectFilterDropdownSelectedRecordIds([]); - setSelectedFilter(undefined); - setFilterDefinitionUsedInDropdown(null); - setSelectedOperandInDropdown(null); - }, [ - setFilterDefinitionUsedInDropdown, - setObjectFilterDropdownSearchInput, - setObjectFilterDropdownSelectedEntityId, - setObjectFilterDropdownSelectedRecordIds, - setSelectedFilter, - setSelectedOperandInDropdown, - ]); + const resetFilter = useRecoilCallback( + ({ set }) => + () => { + set(objectFilterDropdownSearchInputState, ''); + set(objectFilterDropdownSelectedEntityIdState, null); + set(objectFilterDropdownSelectedRecordIdsState, []); + set(selectedFilterState, undefined); + set(filterDefinitionUsedInDropdownState, null); + set(selectedOperandInDropdownState, null); + }, + [ + filterDefinitionUsedInDropdownState, + objectFilterDropdownSearchInputState, + objectFilterDropdownSelectedEntityIdState, + objectFilterDropdownSelectedRecordIdsState, + selectedFilterState, + selectedOperandInDropdownState, + ], + ); + + const setAvailableFilterDefinitions = useSetRecoilState( + availableFilterDefinitionsState, + ); + const setSelectedFilter = useSetRecoilState(selectedFilterState); + const setSelectedOperandInDropdown = useSetRecoilState( + selectedOperandInDropdownState, + ); + const setFilterDefinitionUsedInDropdown = useSetRecoilState( + filterDefinitionUsedInDropdownState, + ); + const setObjectFilterDropdownSearchInput = useSetRecoilState( + objectFilterDropdownSearchInputState, + ); + const setObjectFilterDropdownSelectedEntityId = useSetRecoilState( + objectFilterDropdownSelectedEntityIdState, + ); + const setObjectFilterDropdownSelectedRecordIds = useSetRecoilState( + objectFilterDropdownSelectedRecordIdsState, + ); + const setObjectFilterDropdownSelectedOptionValues = useSetRecoilState( + objectFilterDropdownSelectedOptionValuesState, + ); + const setIsObjectFilterDropdownOperandSelectUnfolded = useSetRecoilState( + isObjectFilterDropdownOperandSelectUnfoldedState, + ); + const setIsObjectFilterDropdownUnfolded = useSetRecoilState( + isObjectFilterDropdownUnfoldedState, + ); + const setOnFilterSelect = useSetRecoilState(onFilterSelectState); return { scopeId, - availableFilterDefinitions, - setAvailableFilterDefinitions, - filterDefinitionUsedInDropdown, - setFilterDefinitionUsedInDropdown, - objectFilterDropdownSearchInput, - setObjectFilterDropdownSearchInput, - objectFilterDropdownSelectedEntityId, - setObjectFilterDropdownSelectedEntityId, - objectFilterDropdownSelectedRecordIds, - setObjectFilterDropdownSelectedRecordIds, - objectFilterDropdownSelectedOptionValues, - setObjectFilterDropdownSelectedOptionValues, - isObjectFilterDropdownOperandSelectUnfolded, - setIsObjectFilterDropdownOperandSelectUnfolded, - isObjectFilterDropdownUnfolded, - setIsObjectFilterDropdownUnfolded, - selectedFilter, - setSelectedFilter, - selectedOperandInDropdown, - setSelectedOperandInDropdown, selectFilter, resetFilter, - onFilterSelect, + setSelectedFilter, + setSelectedOperandInDropdown, + setAvailableFilterDefinitions, + setFilterDefinitionUsedInDropdown, + setObjectFilterDropdownSearchInput, + setObjectFilterDropdownSelectedEntityId, + setObjectFilterDropdownSelectedRecordIds, + setObjectFilterDropdownSelectedOptionValues, + setIsObjectFilterDropdownOperandSelectUnfolded, + setIsObjectFilterDropdownUnfolded, setOnFilterSelect, emptyFilterButKeepDefinition, + availableFilterDefinitionsState, + filterDefinitionUsedInDropdownState, + objectFilterDropdownSearchInputState, + objectFilterDropdownSelectedEntityIdState, + objectFilterDropdownSelectedRecordIdsState, + objectFilterDropdownSelectedOptionValuesState, + isObjectFilterDropdownOperandSelectUnfoldedState, + isObjectFilterDropdownUnfoldedState, + selectedFilterState, + selectedOperandInDropdownState, + onFilterSelectState, }; }; diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useFilterDropdownStates.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useFilterDropdownStates.ts index 94b969b84a..47a4835c1d 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useFilterDropdownStates.ts +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useFilterDropdownStates.ts @@ -1,97 +1,84 @@ -import { objectFilterDropdownSelectedRecordIdsScopedState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedRecordIdsScopedState'; -import { onFilterSelectScopedState } from '@/object-record/object-filter-dropdown/states/onFilterSelectScopedState'; -import { useRecoilScopedStateV2 } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedStateV2'; - -import { availableFilterDefinitionsScopedState } from '../states/availableFilterDefinitionsScopedState'; -import { filterDefinitionUsedInDropdownScopedState } from '../states/filterDefinitionUsedInDropdownScopedState'; -import { isObjectFilterDropdownOperandSelectUnfoldedScopedState } from '../states/isObjectFilterDropdownOperandSelectUnfoldedScopedState'; -import { isObjectFilterDropdownUnfoldedScopedState } from '../states/isObjectFilterDropdownUnfoldedScopedState'; -import { objectFilterDropdownSearchInputScopedState } from '../states/objectFilterDropdownSearchInputScopedState'; -import { objectFilterDropdownSelectedEntityIdScopedState } from '../states/objectFilterDropdownSelectedEntityIdScopedState'; -import { objectFilterDropdownSelectedOptionValuesScopedState } from '../states/objectFilterDropdownSelectedOptionValuesScopedState'; -import { selectedFilterScopedState } from '../states/selectedFilterScopedState'; -import { selectedOperandInDropdownScopedState } from '../states/selectedOperandInDropdownScopedState'; +import { filterDefinitionUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/filterDefinitionUsedInDropdownComponentState'; +import { isObjectFilterDropdownOperandSelectUnfoldedComponentState } from '@/object-record/object-filter-dropdown/states/isObjectFilterDropdownOperandSelectUnfoldedComponentState'; +import { isObjectFilterDropdownUnfoldedComponentState } from '@/object-record/object-filter-dropdown/states/isObjectFilterDropdownUnfoldedComponentState'; +import { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState'; +import { objectFilterDropdownSelectedEntityIdComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedEntityIdComponentState'; +import { objectFilterDropdownSelectedOptionValuesComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedOptionValuesComponentState'; +import { objectFilterDropdownSelectedRecordIdsComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedRecordIdsComponentState'; +import { onFilterSelectComponentState } from '@/object-record/object-filter-dropdown/states/onFilterSelectComponentState'; +import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState'; +import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState'; +import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState'; +import { availableFilterDefinitionsComponentState } from '@/views/states/availableFilterDefinitionsComponentState'; export const useFilterDropdownStates = (scopeId: string) => { - const [availableFilterDefinitions, setAvailableFilterDefinitions] = - useRecoilScopedStateV2(availableFilterDefinitionsScopedState, scopeId); - - const [filterDefinitionUsedInDropdown, setFilterDefinitionUsedInDropdown] = - useRecoilScopedStateV2(filterDefinitionUsedInDropdownScopedState, scopeId); - - const [objectFilterDropdownSearchInput, setObjectFilterDropdownSearchInput] = - useRecoilScopedStateV2(objectFilterDropdownSearchInputScopedState, scopeId); - - const [ - objectFilterDropdownSelectedEntityId, - setObjectFilterDropdownSelectedEntityId, - ] = useRecoilScopedStateV2( - objectFilterDropdownSelectedEntityIdScopedState, + const availableFilterDefinitionsState = extractComponentState( + availableFilterDefinitionsComponentState, scopeId, ); - const [ - objectFilterDropdownSelectedRecordIds, - setObjectFilterDropdownSelectedRecordIds, - ] = useRecoilScopedStateV2( - objectFilterDropdownSelectedRecordIdsScopedState, + const filterDefinitionUsedInDropdownState = extractComponentState( + filterDefinitionUsedInDropdownComponentState, scopeId, ); - const [ - objectFilterDropdownSelectedOptionValues, - setObjectFilterDropdownSelectedOptionValues, - ] = useRecoilScopedStateV2( - objectFilterDropdownSelectedOptionValuesScopedState, + const objectFilterDropdownSearchInputState = extractComponentState( + objectFilterDropdownSearchInputComponentState, scopeId, ); - const [ - isObjectFilterDropdownOperandSelectUnfolded, - setIsObjectFilterDropdownOperandSelectUnfolded, - ] = useRecoilScopedStateV2( - isObjectFilterDropdownOperandSelectUnfoldedScopedState, + const objectFilterDropdownSelectedEntityIdState = extractComponentState( + objectFilterDropdownSelectedEntityIdComponentState, scopeId, ); - const [isObjectFilterDropdownUnfolded, setIsObjectFilterDropdownUnfolded] = - useRecoilScopedStateV2(isObjectFilterDropdownUnfoldedScopedState, scopeId); - - const [selectedFilter, setSelectedFilter] = useRecoilScopedStateV2( - selectedFilterScopedState, + const objectFilterDropdownSelectedRecordIdsState = extractComponentState( + objectFilterDropdownSelectedRecordIdsComponentState, scopeId, ); - const [selectedOperandInDropdown, setSelectedOperandInDropdown] = - useRecoilScopedStateV2(selectedOperandInDropdownScopedState, scopeId); + const objectFilterDropdownSelectedOptionValuesState = extractComponentState( + objectFilterDropdownSelectedOptionValuesComponentState, + scopeId, + ); - const [onFilterSelect, setOnFilterSelect] = useRecoilScopedStateV2( - onFilterSelectScopedState, + const isObjectFilterDropdownOperandSelectUnfoldedState = + extractComponentState( + isObjectFilterDropdownOperandSelectUnfoldedComponentState, + scopeId, + ); + + const isObjectFilterDropdownUnfoldedState = extractComponentState( + isObjectFilterDropdownUnfoldedComponentState, + scopeId, + ); + + const selectedFilterState = extractComponentState( + selectedFilterComponentState, + scopeId, + ); + + const selectedOperandInDropdownState = extractComponentState( + selectedOperandInDropdownComponentState, + scopeId, + ); + + const onFilterSelectState = extractComponentState( + onFilterSelectComponentState, scopeId, ); return { - availableFilterDefinitions, - setAvailableFilterDefinitions, - filterDefinitionUsedInDropdown, - setFilterDefinitionUsedInDropdown, - objectFilterDropdownSearchInput, - setObjectFilterDropdownSearchInput, - objectFilterDropdownSelectedEntityId, - setObjectFilterDropdownSelectedEntityId, - objectFilterDropdownSelectedRecordIds, - objectFilterDropdownSelectedOptionValues, - setObjectFilterDropdownSelectedOptionValues, - setObjectFilterDropdownSelectedRecordIds, - isObjectFilterDropdownOperandSelectUnfolded, - setIsObjectFilterDropdownOperandSelectUnfolded, - isObjectFilterDropdownUnfolded, - setIsObjectFilterDropdownUnfolded, - selectedFilter, - setSelectedFilter, - selectedOperandInDropdown, - setSelectedOperandInDropdown, - onFilterSelect, - setOnFilterSelect, + availableFilterDefinitionsState, + filterDefinitionUsedInDropdownState, + objectFilterDropdownSearchInputState, + objectFilterDropdownSelectedEntityIdState, + objectFilterDropdownSelectedRecordIdsState, + objectFilterDropdownSelectedOptionValuesState, + isObjectFilterDropdownOperandSelectUnfoldedState, + isObjectFilterDropdownUnfoldedState, + selectedFilterState, + selectedOperandInDropdownState, + onFilterSelectState, }; }; diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/availableFilterDefinitionsScopedState.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/availableFilterDefinitionsComponentState.ts similarity index 66% rename from packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/availableFilterDefinitionsScopedState.ts rename to packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/availableFilterDefinitionsComponentState.ts index 8433868e1b..9a3f649ea4 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/availableFilterDefinitionsScopedState.ts +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/availableFilterDefinitionsComponentState.ts @@ -1,9 +1,9 @@ import { FilterDefinition } from '@/object-record/object-filter-dropdown/types/FilterDefinition'; import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; -export const availableFilterDefinitionsScopedState = createComponentState< +export const availableFilterDefinitionsComponentState = createComponentState< FilterDefinition[] >({ - key: 'availableFilterDefinitionsScopedState', + key: 'availableFilterDefinitionsComponentState', defaultValue: [], }); diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/filterDefinitionUsedInDropdownScopedState.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/filterDefinitionUsedInDropdownComponentState.ts similarity index 67% rename from packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/filterDefinitionUsedInDropdownScopedState.ts rename to packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/filterDefinitionUsedInDropdownComponentState.ts index 874d06a630..c7fd89f929 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/filterDefinitionUsedInDropdownScopedState.ts +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/filterDefinitionUsedInDropdownComponentState.ts @@ -2,8 +2,8 @@ import { createComponentState } from '@/ui/utilities/state/component-state/utils import { FilterDefinition } from '../types/FilterDefinition'; -export const filterDefinitionUsedInDropdownScopedState = +export const filterDefinitionUsedInDropdownComponentState = createComponentState({ - key: 'filterDefinitionUsedInDropdownScopedState', + key: 'filterDefinitionUsedInDropdownComponentState', defaultValue: null, }); diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/isObjectFilterDropdownOperandSelectUnfoldedComponentState.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/isObjectFilterDropdownOperandSelectUnfoldedComponentState.ts new file mode 100644 index 0000000000..389c6d30f9 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/isObjectFilterDropdownOperandSelectUnfoldedComponentState.ts @@ -0,0 +1,7 @@ +import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; + +export const isObjectFilterDropdownOperandSelectUnfoldedComponentState = + createComponentState({ + key: 'isObjectFilterDropdownOperandSelectUnfoldedComponentState', + defaultValue: false, + }); diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/isObjectFilterDropdownUnfoldedScopedState.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/isObjectFilterDropdownUnfoldedComponentState.ts similarity index 78% rename from packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/isObjectFilterDropdownUnfoldedScopedState.ts rename to packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/isObjectFilterDropdownUnfoldedComponentState.ts index e07f31ca1b..cfd6dea10c 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/isObjectFilterDropdownUnfoldedScopedState.ts +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/isObjectFilterDropdownUnfoldedComponentState.ts @@ -1,6 +1,6 @@ import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; -export const isObjectFilterDropdownUnfoldedScopedState = +export const isObjectFilterDropdownUnfoldedComponentState = createComponentState({ key: 'isObjectFilterDropdownUnfoldedScopedState', defaultValue: false, diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputScopedState.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState.ts similarity index 58% rename from packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputScopedState.ts rename to packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState.ts index 83c73842da..8addf2fb6c 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputScopedState.ts +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState.ts @@ -1,7 +1,7 @@ import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; -export const objectFilterDropdownSearchInputScopedState = +export const objectFilterDropdownSearchInputComponentState = createComponentState({ - key: 'objectFilterDropdownSearchInputScopedState', + key: 'objectFilterDropdownSearchInputComponentState', defaultValue: '', }); diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedEntityIdScopedState.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedEntityIdComponentState.ts similarity index 57% rename from packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedEntityIdScopedState.ts rename to packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedEntityIdComponentState.ts index 9eba05a6b7..3f62c3d65b 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedEntityIdScopedState.ts +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedEntityIdComponentState.ts @@ -1,7 +1,7 @@ import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; -export const objectFilterDropdownSelectedEntityIdScopedState = +export const objectFilterDropdownSelectedEntityIdComponentState = createComponentState({ - key: 'objectFilterDropdownSelectedEntityIdScopedState', + key: 'objectFilterDropdownSelectedEntityIdComponentState', defaultValue: null, }); diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedRecordIdsScopedState.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedOptionValuesComponentState.ts similarity index 55% rename from packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedRecordIdsScopedState.ts rename to packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedOptionValuesComponentState.ts index e5e1b396c0..feef87220c 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedRecordIdsScopedState.ts +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedOptionValuesComponentState.ts @@ -1,7 +1,7 @@ import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; -export const objectFilterDropdownSelectedRecordIdsScopedState = +export const objectFilterDropdownSelectedOptionValuesComponentState = createComponentState({ - key: 'objectFilterDropdownSelectedRecordIdsScopedState', + key: 'objectFilterDropdownSelectedOptionValuesComponentState', defaultValue: [], }); diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedOptionValuesScopedState.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedRecordIdsComponentState.ts similarity index 57% rename from packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedOptionValuesScopedState.ts rename to packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedRecordIdsComponentState.ts index db1124959f..de23b3b0da 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedOptionValuesScopedState.ts +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedRecordIdsComponentState.ts @@ -1,7 +1,7 @@ import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; -export const objectFilterDropdownSelectedOptionValuesScopedState = +export const objectFilterDropdownSelectedRecordIdsComponentState = createComponentState({ - key: 'objectFilterDropdownSelectedOptionValuesScopedState', + key: 'objectFilterDropdownSelectedRecordIdsComponentState', defaultValue: [], }); diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/onFilterSelectScopedState.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/onFilterSelectComponentState.ts similarity index 68% rename from packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/onFilterSelectScopedState.ts rename to packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/onFilterSelectComponentState.ts index 43a90fa7aa..b73c2cbe96 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/onFilterSelectScopedState.ts +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/onFilterSelectComponentState.ts @@ -2,9 +2,9 @@ import { createComponentState } from '@/ui/utilities/state/component-state/utils import { Filter } from '../types/Filter'; -export const onFilterSelectScopedState = createComponentState< +export const onFilterSelectComponentState = createComponentState< ((filter: Filter | null) => void) | undefined >({ - key: 'onFilterSelectScopedState', + key: 'onFilterSelectComponentState', defaultValue: undefined, }); diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/selectedFilterScopedState.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/selectedFilterComponentState.ts similarity index 66% rename from packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/selectedFilterScopedState.ts rename to packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/selectedFilterComponentState.ts index c9df2abcea..7b4183c748 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/selectedFilterScopedState.ts +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/selectedFilterComponentState.ts @@ -2,9 +2,9 @@ import { createComponentState } from '@/ui/utilities/state/component-state/utils import { Filter } from '../types/Filter'; -export const selectedFilterScopedState = createComponentState< +export const selectedFilterComponentState = createComponentState< Filter | undefined | null >({ - key: 'selectedFilterScopedState', + key: 'selectedFilterComponentState', defaultValue: undefined, }); diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/selectedOperandInDropdownScopedState.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState.ts similarity index 70% rename from packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/selectedOperandInDropdownScopedState.ts rename to packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState.ts index 087ac6d07f..eef8fe552a 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/selectedOperandInDropdownScopedState.ts +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState.ts @@ -1,8 +1,8 @@ import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; -export const selectedOperandInDropdownScopedState = +export const selectedOperandInDropdownComponentState = createComponentState({ - key: 'selectedOperandInDropdownScopedState', + key: 'selectedOperandInDropdownComponentState', defaultValue: null, }); diff --git a/packages/twenty-front/src/modules/object-record/object-sort-dropdown/components/ObjectSortDropdownButton.tsx b/packages/twenty-front/src/modules/object-record/object-sort-dropdown/components/ObjectSortDropdownButton.tsx index 4487463fa5..2b3fb2541c 100644 --- a/packages/twenty-front/src/modules/object-record/object-sort-dropdown/components/ObjectSortDropdownButton.tsx +++ b/packages/twenty-front/src/modules/object-record/object-sort-dropdown/components/ObjectSortDropdownButton.tsx @@ -1,4 +1,5 @@ import { useCallback, useState } from 'react'; +import { useRecoilValue } from 'recoil'; import { OBJECT_SORT_DROPDOWN_ID } from '@/object-record/object-sort-dropdown/constants/ObjectSortDropdownId'; import { useSortDropdown } from '@/object-record/object-sort-dropdown/hooks/useSortDropdown'; @@ -37,7 +38,7 @@ export const ObjectSortDropdownButton = ({ setSelectedSortDirection('asc'); }, []); - const { isSortSelected } = useSortDropdown({ + const { isSortSelectedState } = useSortDropdown({ sortDropdownId: sortDropdownId, }); @@ -48,10 +49,16 @@ export const ObjectSortDropdownButton = ({ resetState(); }; - const { availableSortDefinitions, onSortSelect } = useSortDropdown({ + const { availableSortDefinitionsState, onSortSelectState } = useSortDropdown({ sortDropdownId: sortDropdownId, }); + const isSortSelected = useRecoilValue(isSortSelectedState); + const availableSortDefinitions = useRecoilValue( + availableSortDefinitionsState, + ); + const onSortSelect = useRecoilValue(onSortSelectState); + const handleAddSort = (selectedSortDefinition: SortDefinition) => { toggleDropdown(); onSortSelect?.({ diff --git a/packages/twenty-front/src/modules/object-record/object-sort-dropdown/hooks/__tests__/useSortDropdown.test.tsx b/packages/twenty-front/src/modules/object-record/object-sort-dropdown/hooks/__tests__/useSortDropdown.test.tsx index 1080552025..6bf6ddf0d5 100644 --- a/packages/twenty-front/src/modules/object-record/object-sort-dropdown/hooks/__tests__/useSortDropdown.test.tsx +++ b/packages/twenty-front/src/modules/object-record/object-sort-dropdown/hooks/__tests__/useSortDropdown.test.tsx @@ -1,7 +1,9 @@ +import { expect } from '@storybook/test'; import { act, renderHook, waitFor } from '@testing-library/react'; -import { RecoilRoot } from 'recoil'; +import { RecoilRoot, useRecoilState } from 'recoil'; import { useSortDropdown } from '@/object-record/object-sort-dropdown/hooks/useSortDropdown'; +import { useSortDropdownStates } from '@/object-record/object-sort-dropdown/hooks/useSortDropdownStates'; import { Sort } from '@/object-record/object-sort-dropdown/types/Sort'; import { SortDefinition } from '@/object-record/object-sort-dropdown/types/SortDefinition'; @@ -20,10 +22,19 @@ const sortDefinitions: SortDefinition[] = [ describe('useSortDropdown', () => { it('should set availableSortDefinitions', async () => { - const { result } = renderHook( - () => useSortDropdown({ sortDropdownId }), - renderHookConfig, - ); + const { result } = renderHook(() => { + useSortDropdown({ sortDropdownId }); + const { availableSortDefinitionsState } = + useSortDropdownStates(sortDropdownId); + + const [availableSortDefinitions, setAvailableSortDefinitions] = + useRecoilState(availableSortDefinitionsState); + + return { + availableSortDefinitions, + setAvailableSortDefinitions, + }; + }, renderHookConfig); expect(result.current.availableSortDefinitions).toEqual([]); act(() => { result.current.setAvailableSortDefinitions(sortDefinitions); @@ -35,10 +46,18 @@ describe('useSortDropdown', () => { }); it('should set isSortSelected', async () => { - const { result } = renderHook( - () => useSortDropdown({ sortDropdownId }), - renderHookConfig, - ); + const { result } = renderHook(() => { + useSortDropdown({ sortDropdownId }); + const { isSortSelectedState } = useSortDropdownStates(sortDropdownId); + + const [isSortSelected, setIsSortSelected] = + useRecoilState(isSortSelectedState); + + return { + isSortSelected, + setIsSortSelected, + }; + }, renderHookConfig); expect(result.current.isSortSelected).toBe(false); @@ -54,10 +73,17 @@ describe('useSortDropdown', () => { it('should set onSortSelect', async () => { const OnSortSelectFunction = () => {}; const mockOnSortSelect = jest.fn(() => OnSortSelectFunction); - const { result } = renderHook( - () => useSortDropdown({ sortDropdownId }), - renderHookConfig, - ); + const { result } = renderHook(() => { + useSortDropdown({ sortDropdownId }); + const { onSortSelectState } = useSortDropdownStates(sortDropdownId); + + const [onSortSelect, setOnSortSelect] = useRecoilState(onSortSelectState); + + return { + onSortSelect, + setOnSortSelect, + }; + }, renderHookConfig); expect(result.current.onSortSelect).toBeUndefined(); @@ -78,10 +104,17 @@ describe('useSortDropdown', () => { definition: sortDefinitions[0], }; - const { result } = renderHook( - () => useSortDropdown({ sortDropdownId }), - renderHookConfig, - ); + const { result } = renderHook(() => { + useSortDropdown({ sortDropdownId }); + const { onSortSelectState } = useSortDropdownStates(sortDropdownId); + + const [onSortSelect, setOnSortSelect] = useRecoilState(onSortSelectState); + + return { + onSortSelect, + setOnSortSelect, + }; + }, renderHookConfig); act(() => { result.current.setOnSortSelect(mockOnSortSelect); diff --git a/packages/twenty-front/src/modules/object-record/object-sort-dropdown/hooks/useSortDropdown.ts b/packages/twenty-front/src/modules/object-record/object-sort-dropdown/hooks/useSortDropdown.ts index 696dae8cd6..aee777aa12 100644 --- a/packages/twenty-front/src/modules/object-record/object-sort-dropdown/hooks/useSortDropdown.ts +++ b/packages/twenty-front/src/modules/object-record/object-sort-dropdown/hooks/useSortDropdown.ts @@ -13,21 +13,15 @@ export const useSortDropdown = (props?: UseSortProps) => { props?.sortDropdownId, ); const { - availableSortDefinitions, - setAvailableSortDefinitions, - isSortSelected, - setIsSortSelected, - onSortSelect, - setOnSortSelect, + availableSortDefinitionsState, + isSortSelectedState, + onSortSelectState, } = useSortDropdownStates(scopeId); return { scopeId, - availableSortDefinitions, - isSortSelected, - setIsSortSelected, - setAvailableSortDefinitions, - onSortSelect, - setOnSortSelect, + availableSortDefinitionsState, + isSortSelectedState, + onSortSelectState, }; }; diff --git a/packages/twenty-front/src/modules/object-record/object-sort-dropdown/hooks/useSortDropdownStates.ts b/packages/twenty-front/src/modules/object-record/object-sort-dropdown/hooks/useSortDropdownStates.ts index 9453508fee..74c6bdb548 100644 --- a/packages/twenty-front/src/modules/object-record/object-sort-dropdown/hooks/useSortDropdownStates.ts +++ b/packages/twenty-front/src/modules/object-record/object-sort-dropdown/hooks/useSortDropdownStates.ts @@ -1,29 +1,27 @@ -import { onSortSelectScopedState } from '@/object-record/object-sort-dropdown/states/onSortSelectScopedState'; -import { useRecoilScopedStateV2 } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedStateV2'; - -import { availableSortDefinitionsScopedState } from '../states/availableSortDefinitionsScopedState'; -import { isSortSelectedScopedState } from '../states/isSortSelectedScopedState'; +import { isSortSelectedComponentState } from '@/object-record/object-sort-dropdown/states/isSortSelectedScopedState'; +import { onSortSelectComponentState } from '@/object-record/object-sort-dropdown/states/onSortSelectScopedState'; +import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState'; +import { availableSortDefinitionsComponentState } from '@/views/states/availableSortDefinitionsComponentState'; export const useSortDropdownStates = (scopeId: string) => { - const [availableSortDefinitions, setAvailableSortDefinitions] = - useRecoilScopedStateV2(availableSortDefinitionsScopedState, scopeId); - - const [isSortSelected, setIsSortSelected] = useRecoilScopedStateV2( - isSortSelectedScopedState, + const availableSortDefinitionsState = extractComponentState( + availableSortDefinitionsComponentState, scopeId, ); - const [onSortSelect, setOnSortSelect] = useRecoilScopedStateV2( - onSortSelectScopedState, + const isSortSelectedState = extractComponentState( + isSortSelectedComponentState, + scopeId, + ); + + const onSortSelectState = extractComponentState( + onSortSelectComponentState, scopeId, ); return { - availableSortDefinitions, - setAvailableSortDefinitions, - isSortSelected, - setIsSortSelected, - onSortSelect, - setOnSortSelect, + availableSortDefinitionsState, + isSortSelectedState, + onSortSelectState, }; }; diff --git a/packages/twenty-front/src/modules/object-record/object-sort-dropdown/states/availableSortDefinitionsScopedState.ts b/packages/twenty-front/src/modules/object-record/object-sort-dropdown/states/availableSortDefinitionsComponentState.ts similarity index 62% rename from packages/twenty-front/src/modules/object-record/object-sort-dropdown/states/availableSortDefinitionsScopedState.ts rename to packages/twenty-front/src/modules/object-record/object-sort-dropdown/states/availableSortDefinitionsComponentState.ts index 3f8165b63d..db559fa52f 100644 --- a/packages/twenty-front/src/modules/object-record/object-sort-dropdown/states/availableSortDefinitionsScopedState.ts +++ b/packages/twenty-front/src/modules/object-record/object-sort-dropdown/states/availableSortDefinitionsComponentState.ts @@ -2,9 +2,9 @@ import { createComponentState } from '@/ui/utilities/state/component-state/utils import { SortDefinition } from '../types/SortDefinition'; -export const availableSortDefinitionsScopedState = createComponentState< +export const availableSortDefinitionsComponentState = createComponentState< SortDefinition[] >({ - key: 'availableSortDefinitionsScopedState', + key: 'availableSortDefinitionsComponentState', defaultValue: [], }); diff --git a/packages/twenty-front/src/modules/object-record/object-sort-dropdown/states/isSortSelectedScopedState.ts b/packages/twenty-front/src/modules/object-record/object-sort-dropdown/states/isSortSelectedScopedState.ts index 071d662741..180a2f0172 100644 --- a/packages/twenty-front/src/modules/object-record/object-sort-dropdown/states/isSortSelectedScopedState.ts +++ b/packages/twenty-front/src/modules/object-record/object-sort-dropdown/states/isSortSelectedScopedState.ts @@ -1,6 +1,6 @@ import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; -export const isSortSelectedScopedState = createComponentState({ - key: 'isSortSelectedScopedState', +export const isSortSelectedComponentState = createComponentState({ + key: 'isSortSelectedComponentState', defaultValue: false, }); diff --git a/packages/twenty-front/src/modules/object-record/object-sort-dropdown/states/onSortSelectScopedState.ts b/packages/twenty-front/src/modules/object-record/object-sort-dropdown/states/onSortSelectScopedState.ts index 9e06617229..8b6ca0a8cb 100644 --- a/packages/twenty-front/src/modules/object-record/object-sort-dropdown/states/onSortSelectScopedState.ts +++ b/packages/twenty-front/src/modules/object-record/object-sort-dropdown/states/onSortSelectScopedState.ts @@ -2,9 +2,9 @@ import { createComponentState } from '@/ui/utilities/state/component-state/utils import { Sort } from '../types/Sort'; -export const onSortSelectScopedState = createComponentState< +export const onSortSelectComponentState = createComponentState< ((sort: Sort) => void) | undefined >({ - key: 'onSortSelectScopedState', + key: 'onSortSelectComponentState', defaultValue: undefined, }); diff --git a/packages/twenty-front/src/modules/object-record/object-sort-dropdown/utils/__tests__/turnSortsIntoOrderBy.test.tsx b/packages/twenty-front/src/modules/object-record/object-sort-dropdown/utils/__tests__/turnSortsIntoOrderBy.test.tsx index b46ee87ac7..5a9dc2de62 100644 --- a/packages/twenty-front/src/modules/object-record/object-sort-dropdown/utils/__tests__/turnSortsIntoOrderBy.test.tsx +++ b/packages/twenty-front/src/modules/object-record/object-sort-dropdown/utils/__tests__/turnSortsIntoOrderBy.test.tsx @@ -55,7 +55,7 @@ describe('turnSortsIntoOrderBy', () => { }); }); - it('should throw error if field not found', () => { + it('should ignore if field not found', () => { const sorts: Sort[] = [ { fieldMetadataId: 'invalidField', @@ -63,8 +63,8 @@ describe('turnSortsIntoOrderBy', () => { definition: sortDefinition, }, ]; - expect(() => turnSortsIntoOrderBy(sorts, [])).toThrow( - 'Could not find field invalidField in metadata object', - ); + expect(turnSortsIntoOrderBy(sorts, [])).toEqual({ + position: 'AscNullsFirst', + }); }); }); diff --git a/packages/twenty-front/src/modules/object-record/object-sort-dropdown/utils/turnSortsIntoOrderBy.ts b/packages/twenty-front/src/modules/object-record/object-sort-dropdown/utils/turnSortsIntoOrderBy.ts index b2c487f6ec..85452ddfcf 100644 --- a/packages/twenty-front/src/modules/object-record/object-sort-dropdown/utils/turnSortsIntoOrderBy.ts +++ b/packages/twenty-front/src/modules/object-record/object-sort-dropdown/utils/turnSortsIntoOrderBy.ts @@ -2,6 +2,7 @@ import { OrderBy } from '@/object-metadata/types/OrderBy'; import { OrderByField } from '@/object-metadata/types/OrderByField'; import { Field } from '~/generated/graphql'; import { mapArrayToObject } from '~/utils/array/mapArrayToObject'; +import { isDefined } from '~/utils/isDefined'; import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull'; import { Sort } from '../types/Sort'; @@ -12,20 +13,20 @@ export const turnSortsIntoOrderBy = ( ): OrderByField => { const fieldsById = mapArrayToObject(fields, ({ id }) => id); const sortsOrderBy = Object.fromEntries( - sorts.map((sort) => { - const correspondingField = fieldsById[sort.fieldMetadataId]; + sorts + .map((sort) => { + const correspondingField = fieldsById[sort.fieldMetadataId]; - if (isUndefinedOrNull(correspondingField)) { - throw new Error( - `Could not find field ${sort.fieldMetadataId} in metadata object`, - ); - } + if (isUndefinedOrNull(correspondingField)) { + return undefined; + } - const direction: OrderBy = - sort.direction === 'asc' ? 'AscNullsFirst' : 'DescNullsLast'; + const direction: OrderBy = + sort.direction === 'asc' ? 'AscNullsFirst' : 'DescNullsLast'; - return [correspondingField.name, direction]; - }), + return [correspondingField.name, direction]; + }) + .filter(isDefined), ); return { diff --git a/packages/twenty-front/src/modules/object-record/record-action-bar/hooks/useRecordActionBar.tsx b/packages/twenty-front/src/modules/object-record/record-action-bar/hooks/useRecordActionBar.tsx index 7ee44441af..090647575d 100644 --- a/packages/twenty-front/src/modules/object-record/record-action-bar/hooks/useRecordActionBar.tsx +++ b/packages/twenty-front/src/modules/object-record/record-action-bar/hooks/useRecordActionBar.tsx @@ -34,8 +34,8 @@ export const useRecordActionBar = ({ selectedRecordIds, callback, }: useRecordActionBarProps) => { - const setContextMenuEntries = useSetRecoilState(contextMenuEntriesState()); - const setActionBarEntriesState = useSetRecoilState(actionBarEntriesState()); + const setContextMenuEntries = useSetRecoilState(contextMenuEntriesState); + const setActionBarEntriesState = useSetRecoilState(actionBarEntriesState); const { createFavorite, favorites, deleteFavorite } = useFavorites(); diff --git a/packages/twenty-front/src/modules/object-record/record-board/action-bar/components/RecordBoardActionBar.tsx b/packages/twenty-front/src/modules/object-record/record-board/action-bar/components/RecordBoardActionBar.tsx index d0d8102220..2bb43e96ce 100644 --- a/packages/twenty-front/src/modules/object-record/record-board/action-bar/components/RecordBoardActionBar.tsx +++ b/packages/twenty-front/src/modules/object-record/record-board/action-bar/components/RecordBoardActionBar.tsx @@ -10,9 +10,9 @@ type RecordBoardActionBarProps = { export const RecordBoardActionBar = ({ recordBoardId, }: RecordBoardActionBarProps) => { - const { getSelectedRecordIdsSelector } = useRecordBoardStates(recordBoardId); + const { selectedRecordIdsSelector } = useRecordBoardStates(recordBoardId); - const selectedRecordIds = useRecoilValue(getSelectedRecordIdsSelector()); + const selectedRecordIds = useRecoilValue(selectedRecordIdsSelector()); if (!selectedRecordIds.length) { return null; diff --git a/packages/twenty-front/src/modules/object-record/record-board/components/RecordBoard.tsx b/packages/twenty-front/src/modules/object-record/record-board/components/RecordBoard.tsx index f8aa66909a..c877865d98 100644 --- a/packages/twenty-front/src/modules/object-record/record-board/components/RecordBoard.tsx +++ b/packages/twenty-front/src/modules/object-record/record-board/components/RecordBoard.tsx @@ -50,12 +50,12 @@ export const RecordBoard = ({ recordBoardId }: RecordBoardProps) => { const boardRef = useRef(null); const { - getColumnIdsState, + columnIdsState, columnsFamilySelector, recordIdsByColumnIdFamilyState, } = useRecordBoardStates(recordBoardId); - const columnIds = useRecoilValue(getColumnIdsState()); + const columnIds = useRecoilValue(columnIdsState); const { resetRecordSelection, setRecordAsSelected } = useRecordBoardSelection(recordBoardId); diff --git a/packages/twenty-front/src/modules/object-record/record-board/context-menu/components/RecordBoardContextMenu.tsx b/packages/twenty-front/src/modules/object-record/record-board/context-menu/components/RecordBoardContextMenu.tsx index b98245d901..fed35a6506 100644 --- a/packages/twenty-front/src/modules/object-record/record-board/context-menu/components/RecordBoardContextMenu.tsx +++ b/packages/twenty-front/src/modules/object-record/record-board/context-menu/components/RecordBoardContextMenu.tsx @@ -10,9 +10,9 @@ type RecordBoardContextMenuProps = { export const RecordBoardContextMenu = ({ recordBoardId, }: RecordBoardContextMenuProps) => { - const { getSelectedRecordIdsSelector } = useRecordBoardStates(recordBoardId); + const { selectedRecordIdsSelector } = useRecordBoardStates(recordBoardId); - const selectedRecordIds = useRecoilValue(getSelectedRecordIdsSelector()); + const selectedRecordIds = useRecoilValue(selectedRecordIdsSelector()); if (!selectedRecordIds.length) { return null; diff --git a/packages/twenty-front/src/modules/object-record/record-board/hooks/internal/useRecordBoardStates.ts b/packages/twenty-front/src/modules/object-record/record-board/hooks/internal/useRecordBoardStates.ts index cd5b2cf314..1c8f8a1849 100644 --- a/packages/twenty-front/src/modules/object-record/record-board/hooks/internal/useRecordBoardStates.ts +++ b/packages/twenty-front/src/modules/object-record/record-board/hooks/internal/useRecordBoardStates.ts @@ -28,15 +28,15 @@ export const useRecordBoardStates = (recordBoardId?: string) => { return { scopeId, - getObjectSingularNameState: extractComponentState( + objectSingularNameState: extractComponentState( recordBoardObjectSingularNameComponentState, scopeId, ), - getIsFetchingRecordState: extractComponentState( + isFetchingRecordState: extractComponentState( isRecordBoardFetchingRecordsComponentState, scopeId, ), - getColumnIdsState: extractComponentState( + columnIdsState: extractComponentState( recordBoardColumnIdsComponentState, scopeId, ), @@ -53,19 +53,16 @@ export const useRecordBoardStates = (recordBoardId?: string) => { scopeId, ), - getFiltersState: extractComponentState( + filtersState: extractComponentState( recordBoardFiltersComponentState, scopeId, ), - getSortsState: extractComponentState( - recordBoardSortsComponentState, - scopeId, - ), - getFieldDefinitionsState: extractComponentState( + sortsState: extractComponentState(recordBoardSortsComponentState, scopeId), + fieldDefinitionsState: extractComponentState( recordBoardFieldDefinitionsComponentState, scopeId, ), - getVisibleFieldDefinitionsState: extractComponentReadOnlySelector( + visibleFieldDefinitionsState: extractComponentReadOnlySelector( recordBoardVisibleFieldDefinitionsComponentSelector, scopeId, ), @@ -78,17 +75,17 @@ export const useRecordBoardStates = (recordBoardId?: string) => { isRecordBoardCardSelectedComponentFamilyState, scopeId, ), - getSelectedRecordIdsSelector: extractComponentReadOnlySelector( + selectedRecordIdsSelector: extractComponentReadOnlySelector( recordBoardSelectedRecordIdsComponentSelector, scopeId, ), - getIsCompactModeActiveState: extractComponentState( + isCompactModeActiveState: extractComponentState( isRecordBoardCompactModeActiveComponentState, scopeId, ), - getOnFetchMoreVisibilityChangeState: extractComponentState( + onFetchMoreVisibilityChangeState: extractComponentState( onRecordBoardFetchMoreVisibilityChangeComponentState, scopeId, ), diff --git a/packages/twenty-front/src/modules/object-record/record-board/hooks/internal/useSetRecordBoardColumns.ts b/packages/twenty-front/src/modules/object-record/record-board/hooks/internal/useSetRecordBoardColumns.ts index 34ca406203..d330a476d6 100644 --- a/packages/twenty-front/src/modules/object-record/record-board/hooks/internal/useSetRecordBoardColumns.ts +++ b/packages/twenty-front/src/modules/object-record/record-board/hooks/internal/useSetRecordBoardColumns.ts @@ -5,14 +5,14 @@ import { RecordBoardColumnDefinition } from '@/object-record/record-board/types/ import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; export const useSetRecordBoardColumns = (recordBoardId?: string) => { - const { scopeId, getColumnIdsState, columnsFamilySelector } = + const { scopeId, columnIdsState, columnsFamilySelector } = useRecordBoardStates(recordBoardId); const setColumns = useRecoilCallback( ({ set, snapshot }) => (columns: RecordBoardColumnDefinition[]) => { const currentColumnsIds = snapshot - .getLoadable(getColumnIdsState()) + .getLoadable(columnIdsState) .getValue(); const columnIds = columns.map(({ id }) => id); @@ -22,7 +22,7 @@ export const useSetRecordBoardColumns = (recordBoardId?: string) => { } set( - getColumnIdsState(), + columnIdsState, columns.map((column) => column.id), ); @@ -38,7 +38,7 @@ export const useSetRecordBoardColumns = (recordBoardId?: string) => { set(columnsFamilySelector(column.id), column); }); }, - [columnsFamilySelector, getColumnIdsState], + [columnsFamilySelector, columnIdsState], ); return { diff --git a/packages/twenty-front/src/modules/object-record/record-board/hooks/internal/useSetRecordBoardRecordIds.ts b/packages/twenty-front/src/modules/object-record/record-board/hooks/internal/useSetRecordBoardRecordIds.ts index 03db29158c..90f5a1ad93 100644 --- a/packages/twenty-front/src/modules/object-record/record-board/hooks/internal/useSetRecordBoardRecordIds.ts +++ b/packages/twenty-front/src/modules/object-record/record-board/hooks/internal/useSetRecordBoardRecordIds.ts @@ -9,13 +9,13 @@ export const useSetRecordBoardRecordIds = (recordBoardId?: string) => { scopeId, recordIdsByColumnIdFamilyState, columnsFamilySelector, - getColumnIdsState, + columnIdsState, } = useRecordBoardStates(recordBoardId); const setRecordIds = useRecoilCallback( ({ set, snapshot }) => (records: ObjectRecord[]) => { - const columnIds = snapshot.getLoadable(getColumnIdsState()).getValue(); + const columnIds = snapshot.getLoadable(columnIdsState).getValue(); columnIds.forEach((columnId) => { const column = snapshot @@ -36,7 +36,7 @@ export const useSetRecordBoardRecordIds = (recordBoardId?: string) => { } }); }, - [columnsFamilySelector, getColumnIdsState, recordIdsByColumnIdFamilyState], + [columnsFamilySelector, columnIdsState, recordIdsByColumnIdFamilyState], ); return { diff --git a/packages/twenty-front/src/modules/object-record/record-board/hooks/useRecordBoard.ts b/packages/twenty-front/src/modules/object-record/record-board/hooks/useRecordBoard.ts index 59429b2546..f6a266d474 100644 --- a/packages/twenty-front/src/modules/object-record/record-board/hooks/useRecordBoard.ts +++ b/packages/twenty-front/src/modules/object-record/record-board/hooks/useRecordBoard.ts @@ -7,17 +7,17 @@ import { useSetRecordBoardRecordIds } from '@/object-record/record-board/hooks/i export const useRecordBoard = (recordBoardId?: string) => { const { scopeId, - getFieldDefinitionsState, - getObjectSingularNameState, - getSelectedRecordIdsSelector, - getIsCompactModeActiveState, - getOnFetchMoreVisibilityChangeState, + fieldDefinitionsState, + objectSingularNameState, + selectedRecordIdsSelector, + isCompactModeActiveState, + onFetchMoreVisibilityChangeState, } = useRecordBoardStates(recordBoardId); const { setColumns } = useSetRecordBoardColumns(recordBoardId); const { setRecordIds } = useSetRecordBoardRecordIds(recordBoardId); - const setFieldDefinitions = useSetRecoilState(getFieldDefinitionsState()); - const setObjectSingularName = useSetRecoilState(getObjectSingularNameState()); + const setFieldDefinitions = useSetRecoilState(fieldDefinitionsState); + const setObjectSingularName = useSetRecoilState(objectSingularNameState); return { scopeId, @@ -25,8 +25,8 @@ export const useRecordBoard = (recordBoardId?: string) => { setRecordIds, setFieldDefinitions, setObjectSingularName, - getSelectedRecordIdsSelector, - getIsCompactModeActiveState, - getOnFetchMoreVisibilityChangeState, + selectedRecordIdsSelector, + isCompactModeActiveState, + onFetchMoreVisibilityChangeState, }; }; diff --git a/packages/twenty-front/src/modules/object-record/record-board/hooks/useRecordBoardSelection.ts b/packages/twenty-front/src/modules/object-record/record-board/hooks/useRecordBoardSelection.ts index ae89223c79..a2024d4ba6 100644 --- a/packages/twenty-front/src/modules/object-record/record-board/hooks/useRecordBoardSelection.ts +++ b/packages/twenty-front/src/modules/object-record/record-board/hooks/useRecordBoardSelection.ts @@ -3,21 +3,21 @@ import { useRecoilCallback } from 'recoil'; import { useRecordBoardStates } from '@/object-record/record-board/hooks/internal/useRecordBoardStates'; export const useRecordBoardSelection = (recordBoardId?: string) => { - const { getSelectedRecordIdsSelector, isRecordBoardCardSelectedFamilyState } = + const { selectedRecordIdsSelector, isRecordBoardCardSelectedFamilyState } = useRecordBoardStates(recordBoardId); const resetRecordSelection = useRecoilCallback( ({ snapshot, set }) => () => { const recordIds = snapshot - .getLoadable(getSelectedRecordIdsSelector()) + .getLoadable(selectedRecordIdsSelector()) .getValue(); for (const recordId of recordIds) { set(isRecordBoardCardSelectedFamilyState(recordId), false); } }, - [getSelectedRecordIdsSelector, isRecordBoardCardSelectedFamilyState], + [selectedRecordIdsSelector, isRecordBoardCardSelectedFamilyState], ); const setRecordAsSelected = useRecoilCallback( diff --git a/packages/twenty-front/src/modules/object-record/record-board/record-board-card/components/RecordBoardCard.tsx b/packages/twenty-front/src/modules/object-record/record-board/record-board-card/components/RecordBoardCard.tsx index 0344668737..dda3bc34e8 100644 --- a/packages/twenty-front/src/modules/object-record/record-board/record-board-card/components/RecordBoardCard.tsx +++ b/packages/twenty-front/src/modules/object-record/record-board/record-board-card/components/RecordBoardCard.tsx @@ -133,12 +133,12 @@ export const RecordBoardCard = () => { const { updateOneRecord, objectMetadataItem } = useContext(RecordBoardContext); const { - getIsCompactModeActiveState, + isCompactModeActiveState, isRecordBoardCardSelectedFamilyState, - getVisibleFieldDefinitionsState, + visibleFieldDefinitionsState, } = useRecordBoardStates(); - const isCompactModeActive = useRecoilValue(getIsCompactModeActiveState()); + const isCompactModeActive = useRecoilValue(isCompactModeActiveState); const [isCardInCompactMode, setIsCardInCompactMode] = useState(true); @@ -146,14 +146,14 @@ export const RecordBoardCard = () => { isRecordBoardCardSelectedFamilyState(recordId), ); - const visibleBoardCardFieldDefinitions = useRecoilValue( - getVisibleFieldDefinitionsState(), + const visibleFieldDefinitions = useRecoilValue( + visibleFieldDefinitionsState(), ); const record = useRecoilValue(recordStoreFamilyState(recordId)); - const setContextMenuPosition = useSetRecoilState(contextMenuPositionState()); - const setContextMenuOpenState = useSetRecoilState(contextMenuIsOpenState()); + const setContextMenuPosition = useSetRecoilState(contextMenuPositionState); + const setContextMenuOpenState = useSetRecoilState(contextMenuIsOpenState); const handleContextMenu = (event: React.MouseEvent) => { event.preventDefault(); @@ -247,7 +247,7 @@ export const RecordBoardCard = () => { isOpen={!isCardInCompactMode || !isCompactModeActive} initial={false} > - {visibleBoardCardFieldDefinitions.map((fieldDefinition) => ( + {visibleFieldDefinitions.map((fieldDefinition) => ( diff --git a/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnFetchMoreLoader.tsx b/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnFetchMoreLoader.tsx index 072120d680..56127562c0 100644 --- a/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnFetchMoreLoader.tsx +++ b/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnFetchMoreLoader.tsx @@ -16,12 +16,12 @@ const StyledText = styled.div` `; export const RecordBoardColumnFetchMoreLoader = () => { - const { getIsFetchingRecordState, getOnFetchMoreVisibilityChangeState } = + const { isFetchingRecordState, onFetchMoreVisibilityChangeState } = useRecordBoardStates(); - const isFetchingRecords = useRecoilValue(getIsFetchingRecordState()); + const isFetchingRecord = useRecoilValue(isFetchingRecordState); const onFetchMoreVisibilityChange = useRecoilValue( - getOnFetchMoreVisibilityChangeState(), + onFetchMoreVisibilityChangeState, ); const { ref } = useInView({ @@ -30,7 +30,7 @@ export const RecordBoardColumnFetchMoreLoader = () => { return (
- {isFetchingRecords && Loading more...} + {isFetchingRecord && Loading more...}
); }; diff --git a/packages/twenty-front/src/modules/object-record/record-field/hooks/useClearField.ts b/packages/twenty-front/src/modules/object-record/record-field/hooks/useClearField.ts index f65fbe900a..548e212f98 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/hooks/useClearField.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/hooks/useClearField.ts @@ -20,7 +20,7 @@ export const useClearField = () => { ({ snapshot, set }) => () => { const objectMetadataItems = snapshot - .getLoadable(objectMetadataItemsState()) + .getLoadable(objectMetadataItemsState) .getValue(); const foundObjectMetadataItem = objectMetadataItems.find( diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/__stories__/RelationFieldInput.stories.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/__stories__/RelationFieldInput.stories.tsx index 9d8dd60340..3cbe87a498 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/__stories__/RelationFieldInput.stories.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/__stories__/RelationFieldInput.stories.tsx @@ -30,9 +30,9 @@ import { } from '../RelationFieldInput'; const RelationWorkspaceSetterEffect = () => { - const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState()); + const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState); const setCurrentWorkspaceMember = useSetRecoilState( - currentWorkspaceMemberState(), + currentWorkspaceMemberState, ); useEffect(() => { diff --git a/packages/twenty-front/src/modules/object-record/record-filter/utils/turnObjectDropdownFilterIntoQueryFilter.ts b/packages/twenty-front/src/modules/object-record/record-filter/utils/turnObjectDropdownFilterIntoQueryFilter.ts index 49918c7371..728c681d5c 100644 --- a/packages/twenty-front/src/modules/object-record/record-filter/utils/turnObjectDropdownFilterIntoQueryFilter.ts +++ b/packages/twenty-front/src/modules/object-record/record-filter/utils/turnObjectDropdownFilterIntoQueryFilter.ts @@ -35,13 +35,11 @@ export const turnObjectDropdownFilterIntoQueryFilter = ( ); if (!correspondingField) { - throw new Error( - `Could not find field ${rawUIFilter.fieldMetadataId} in metadata object`, - ); + continue; } if (!isDefined(rawUIFilter.value) || rawUIFilter.value === '') { - return undefined; + continue; } switch (rawUIFilter.definition.type) { diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexBoardContainerEffect.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexBoardContainerEffect.tsx index 08e3bd35d9..3e7fff5bd0 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexBoardContainerEffect.tsx +++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexBoardContainerEffect.tsx @@ -28,9 +28,9 @@ export const RecordIndexBoardContainerEffect = ({ const { setColumns, setObjectSingularName, - getSelectedRecordIdsSelector, + selectedRecordIdsSelector, setFieldDefinitions, - getOnFetchMoreVisibilityChangeState, + onFetchMoreVisibilityChangeState, } = useRecordBoard(recordBoardId); const { fetchMoreRecords, loading } = useLoadRecordIndexBoard({ @@ -40,7 +40,7 @@ export const RecordIndexBoardContainerEffect = ({ }); const setOnFetchMoreVisibilityChange = useSetRecoilState( - getOnFetchMoreVisibilityChangeState(), + onFetchMoreVisibilityChangeState, ); useEffect(() => { @@ -78,14 +78,14 @@ export const RecordIndexBoardContainerEffect = ({ ]); const recordIndexFieldDefinitions = useRecoilValue( - recordIndexFieldDefinitionsState(), + recordIndexFieldDefinitionsState, ); useEffect(() => { setFieldDefinitions(recordIndexFieldDefinitions); }, [objectMetadataItem, setFieldDefinitions, recordIndexFieldDefinitions]); - const selectedRecordIds = useRecoilValue(getSelectedRecordIdsSelector()); + const selectedRecordIds = useRecoilValue(selectedRecordIdsSelector()); const { setActionBarEntries, setContextMenuEntries } = useRecordActionBar({ objectMetadataItem, 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 d9873a1b14..1d9e89b250 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 @@ -47,7 +47,7 @@ export const RecordIndexContainer = ({ objectNamePlural, }: RecordIndexContainerProps) => { const [recordIndexViewType, setRecordIndexViewType] = useRecoilState( - recordIndexViewTypeState(), + recordIndexViewTypeState, ); const { objectNameSingular } = useObjectNameSingularFromPlural({ objectNamePlural, @@ -57,13 +57,13 @@ export const RecordIndexContainer = ({ objectNameSingular, }); - const { columnDefinitions } = + const { columnDefinitions, filterDefinitions, sortDefinitions } = useColumnDefinitionsFromFieldMetadata(objectMetadataItem); - const setRecordIndexFilters = useSetRecoilState(recordIndexFiltersState()); - const setRecordIndexSorts = useSetRecoilState(recordIndexSortsState()); + const setRecordIndexFilters = useSetRecoilState(recordIndexFiltersState); + const setRecordIndexSorts = useSetRecoilState(recordIndexSortsState); const setRecordIndexIsCompactModeActive = useSetRecoilState( - recordIndexIsCompactModeActiveState(), + recordIndexIsCompactModeActiveState, ); const { setTableFilters, setTableSorts, setTableColumns } = useRecordTable({ @@ -85,7 +85,7 @@ export const RecordIndexContainer = ({ ); const existingRecordIndexFieldDefinitions = snapshot - .getLoadable(recordIndexFieldDefinitionsState()) + .getLoadable(recordIndexFieldDefinitionsState) .getValue(); if ( @@ -94,10 +94,7 @@ export const RecordIndexContainer = ({ newRecordIndexFieldDefinitions, ) ) { - set( - recordIndexFieldDefinitionsState(), - newRecordIndexFieldDefinitions, - ); + set(recordIndexFieldDefinitionsState, newRecordIndexFieldDefinitions); } }, [columnDefinitions, setTableColumns], @@ -115,22 +112,26 @@ export const RecordIndexContainer = ({ viewType={recordIndexViewType ?? ViewType.Table} /> } + onCurrentViewChange={(view) => { + if (!view) { + return; + } + + onViewFieldsChange(view.viewFields); + setTableFilters( + mapViewFiltersToFilters(view.viewFilters, filterDefinitions), + ); + setRecordIndexFilters( + mapViewFiltersToFilters(view.viewFilters, filterDefinitions), + ); + setTableSorts(mapViewSortsToSorts(view.viewSorts, sortDefinitions)); + setRecordIndexSorts( + mapViewSortsToSorts(view.viewSorts, sortDefinitions), + ); + setRecordIndexViewType(view.type); + setRecordIndexIsCompactModeActive(view.isCompact); + }} optionsDropdownScopeId={RECORD_INDEX_OPTIONS_DROPDOWN_ID} - onViewFieldsChange={onViewFieldsChange} - onViewFiltersChange={(viewFilters) => { - setTableFilters(mapViewFiltersToFilters(viewFilters)); - setRecordIndexFilters(mapViewFiltersToFilters(viewFilters)); - }} - onViewSortsChange={(viewSorts) => { - setTableSorts(mapViewSortsToSorts(viewSorts)); - setRecordIndexSorts(mapViewSortsToSorts(viewSorts)); - }} - onViewTypeChange={(viewType: ViewType) => { - setRecordIndexViewType(viewType); - }} - onViewCompactModeChange={(isCompactModeActive: boolean) => { - setRecordIndexIsCompactModeActive(isCompactModeActive); - }} /> { setAvailableTableColumns(columnDefinitions); }, [columnDefinitions, setAvailableTableColumns]); - const selectedRowIds = useRecoilValue(getSelectedRowIdsSelector()); + const selectedRowIds = useRecoilValue(selectedRowIdsSelector()); const { setActionBarEntries, setContextMenuEntries } = useRecordActionBar({ objectMetadataItem, @@ -57,9 +56,9 @@ export const RecordIndexTableContainerEffect = ({ useEffect(() => { setOnEntityCountChange( - () => (entityCount: number) => setEntityCountInCurrentView(entityCount), + () => (entityCount: number) => setRecordCountInCurrentView(entityCount), ); - }, [setEntityCountInCurrentView, setOnEntityCountChange]); + }, [setRecordCountInCurrentView, setOnEntityCountChange]); return <>; }; diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexViewBarEffect.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexViewBarEffect.tsx index 51d27b0c38..44ae887962 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexViewBarEffect.tsx +++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexViewBarEffect.tsx @@ -3,7 +3,7 @@ import { useEffect } from 'react'; import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural'; -import { useViewBar } from '@/views/hooks/useViewBar'; +import { useInitViewBar } from '@/views/hooks/useInitViewBar'; import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull'; type RecordIndexViewBarEffectProps = { @@ -31,7 +31,7 @@ export const RecordIndexViewBarEffect = ({ setAvailableSortDefinitions, setAvailableFilterDefinitions, setAvailableFieldDefinitions, - } = useViewBar({ viewBarId }); + } = useInitViewBar(viewBarId); useEffect(() => { if (isUndefinedOrNull(objectMetadataItem)) { diff --git a/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexBoard.ts b/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexBoard.ts index fa894ebb19..0efe9e2f5e 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexBoard.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexBoard.ts @@ -11,7 +11,7 @@ import { recordIndexFiltersState } from '@/object-record/record-index/states/rec import { recordIndexIsCompactModeActiveState } from '@/object-record/record-index/states/recordIndexIsCompactModeActiveState'; import { recordIndexSortsState } from '@/object-record/record-index/states/recordIndexSortsState'; import { useSetRecordInStore } from '@/object-record/record-store/hooks/useSetRecordInStore'; -import { useViewBar } from '@/views/hooks/useViewBar'; +import { useSetRecordCountInCurrentView } from '@/views/hooks/useSetRecordCountInCurrentView'; type UseLoadRecordIndexBoardProps = { objectNameSingular: string; @@ -30,19 +30,19 @@ export const useLoadRecordIndexBoard = ({ const { setRecordIds: setRecordIdsInBoard, setFieldDefinitions, - getIsCompactModeActiveState, + isCompactModeActiveState, } = useRecordBoard(recordBoardId); const { setRecords: setRecordsInStore } = useSetRecordInStore(); const recordIndexFieldDefinitions = useRecoilValue( - recordIndexFieldDefinitionsState(), + recordIndexFieldDefinitionsState, ); useEffect(() => { setFieldDefinitions(recordIndexFieldDefinitions); }, [recordIndexFieldDefinitions, setFieldDefinitions]); - const recordIndexFilters = useRecoilValue(recordIndexFiltersState()); - const recordIndexSorts = useRecoilValue(recordIndexSortsState()); + const recordIndexFilters = useRecoilValue(recordIndexFiltersState); + const recordIndexSorts = useRecoilValue(recordIndexSortsState); const requestFilters = turnObjectDropdownFilterIntoQueryFilter( recordIndexFilters, objectMetadataItem?.fields ?? [], @@ -53,7 +53,7 @@ export const useLoadRecordIndexBoard = ({ ); const recordIndexIsCompactModeActive = useRecoilValue( - recordIndexIsCompactModeActiveState(), + recordIndexIsCompactModeActiveState, ); const { @@ -68,13 +68,10 @@ export const useLoadRecordIndexBoard = ({ orderBy, }); - const { setEntityCountInCurrentView } = useViewBar({ - viewBarId, - }); + const { setRecordCountInCurrentView } = + useSetRecordCountInCurrentView(viewBarId); - const setIsCompactModeActive = useSetRecoilState( - getIsCompactModeActiveState(), - ); + const setIsCompactModeActive = useSetRecoilState(isCompactModeActiveState); useEffect(() => { setRecordIdsInBoard(records); @@ -85,8 +82,8 @@ export const useLoadRecordIndexBoard = ({ }, [records, setRecordsInStore]); useEffect(() => { - setEntityCountInCurrentView(totalCount); - }, [totalCount, setEntityCountInCurrentView]); + setRecordCountInCurrentView(totalCount); + }, [totalCount, setRecordCountInCurrentView]); useEffect(() => { setIsCompactModeActive(recordIndexIsCompactModeActive); diff --git a/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexTable.ts b/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexTable.ts index 90c4d46e20..4594d516d4 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexTable.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexTable.ts @@ -18,11 +18,11 @@ export const useFindManyParams = ( objectNameSingular, }); - const { getTableFiltersState, getTableSortsState } = + const { tableFiltersState, tableSortsState } = useRecordTableStates(recordTableId); - const tableFilters = useRecoilValue(getTableFiltersState()); - const tableSorts = useRecoilValue(getTableSortsState()); + const tableFilters = useRecoilValue(tableFiltersState); + const tableSorts = useRecoilValue(tableSortsState); const filter = turnObjectDropdownFilterIntoQueryFilter( tableFilters, @@ -40,9 +40,9 @@ export const useFindManyParams = ( export const useLoadRecordIndexTable = (objectNameSingular: string) => { const { setRecordTableData, setIsRecordTableInitialLoading } = useRecordTable(); - const { getTableLastRowVisibleState } = useRecordTableStates(); - const setLastRowVisible = useSetRecoilState(getTableLastRowVisibleState()); - const currentWorkspace = useRecoilValue(currentWorkspaceState()); + const { tableLastRowVisibleState } = useRecordTableStates(); + const setLastRowVisible = useSetRecoilState(tableLastRowVisibleState); + const currentWorkspace = useRecoilValue(currentWorkspaceState); const params = useFindManyParams(objectNameSingular); const { diff --git a/packages/twenty-front/src/modules/object-record/record-index/options/components/RecordIndexOptionsDropdown.tsx b/packages/twenty-front/src/modules/object-record/record-index/options/components/RecordIndexOptionsDropdown.tsx index d79427c0fe..69b7b567dc 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/options/components/RecordIndexOptionsDropdown.tsx +++ b/packages/twenty-front/src/modules/object-record/record-index/options/components/RecordIndexOptionsDropdown.tsx @@ -1,11 +1,9 @@ import { RecordIndexOptionsDropdownButton } from '@/object-record/record-index/options/components/RecordIndexOptionsDropdownButton'; import { RecordIndexOptionsDropdownContent } from '@/object-record/record-index/options/components/RecordIndexOptionsDropdownContent'; import { RECORD_INDEX_OPTIONS_DROPDOWN_ID } from '@/object-record/record-index/options/constants/RecordIndexOptionsDropdownId'; -import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates'; -import { RecordTableScope } from '@/object-record/record-table/scopes/RecordTableScope'; import { TableOptionsHotkeyScope } from '@/object-record/record-table/types/TableOptionsHotkeyScope'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; -import { useViewBar } from '@/views/hooks/useViewBar'; +import { useViewBarEditMode } from '@/views/hooks/useViewBarEditMode'; import { ViewType } from '@/views/types/ViewType'; type RecordIndexOptionsDropdownProps = { @@ -19,28 +17,22 @@ export const RecordIndexOptionsDropdown = ({ objectNameSingular, viewType, }: RecordIndexOptionsDropdownProps) => { - const { setViewEditMode } = useViewBar(); - const { scopeId } = useRecordTableStates(recordIndexId); + const { setViewEditMode } = useViewBarEditMode(recordIndexId); return ( - false} - > - } - dropdownHotkeyScope={{ scope: TableOptionsHotkeyScope.Dropdown }} - dropdownOffset={{ y: 8 }} - dropdownComponents={ - - } - onClickOutside={() => setViewEditMode('none')} - /> - + } + dropdownHotkeyScope={{ scope: TableOptionsHotkeyScope.Dropdown }} + dropdownOffset={{ y: 8 }} + dropdownComponents={ + + } + onClickOutside={() => setViewEditMode('none')} + /> ); }; diff --git a/packages/twenty-front/src/modules/object-record/record-index/options/components/RecordIndexOptionsDropdownContent.tsx b/packages/twenty-front/src/modules/object-record/record-index/options/components/RecordIndexOptionsDropdownContent.tsx index 59831da293..19f1e25947 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/options/components/RecordIndexOptionsDropdownContent.tsx +++ b/packages/twenty-front/src/modules/object-record/record-index/options/components/RecordIndexOptionsDropdownContent.tsx @@ -1,6 +1,6 @@ import { useRef, useState } from 'react'; -import { useRecoilValue } from 'recoil'; import { Key } from 'ts-key-enum'; +import { v4 } from 'uuid'; import { RECORD_INDEX_OPTIONS_DROPDOWN_ID } from '@/object-record/record-index/options/constants/RecordIndexOptionsDropdownId'; import { useRecordIndexOptionsForBoard } from '@/object-record/record-index/options/hooks/useRecordIndexOptionsForBoard'; @@ -22,8 +22,9 @@ import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem'; import { MenuItemToggle } from '@/ui/navigation/menu-item/components/MenuItemToggle'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { ViewFieldsVisibilityDropdownSection } from '@/views/components/ViewFieldsVisibilityDropdownSection'; -import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates'; -import { useViewBar } from '@/views/hooks/useViewBar'; +import { useGetCurrentView } from '@/views/hooks/useGetCurrentView'; +import { useHandleViews } from '@/views/hooks/useHandleViews'; +import { useViewBarEditMode } from '@/views/hooks/useViewBarEditMode'; import { ViewType } from '@/views/types/ViewType'; type RecordIndexOptionsMenu = 'fields'; @@ -39,13 +40,11 @@ export const RecordIndexOptionsDropdownContent = ({ recordIndexId, objectNameSingular, }: RecordIndexOptionsDropdownContentProps) => { - const { setViewEditMode, handleViewNameSubmit } = useViewBar({ - viewBarId: recordIndexId, - }); - const { viewEditModeState, currentViewSelector } = useViewScopedStates(); + const { updateCurrentView, createEmptyView, selectView } = + useHandleViews(recordIndexId); + const { viewEditMode, setViewEditMode } = useViewBarEditMode(recordIndexId); + const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView(); - const viewEditMode = useRecoilValue(viewEditModeState); - const currentView = useRecoilValue(currentViewSelector); const { closeDropdown } = useDropdown(RECORD_INDEX_OPTIONS_DROPDOWN_ID); const [currentMenu, setCurrentMenu] = useState< @@ -70,9 +69,16 @@ export const RecordIndexOptionsDropdownContent = ({ useScopedHotkeys( Key.Enter, - () => { + async () => { const name = viewEditInputRef.current?.value; - handleViewNameSubmit(name); + if (viewEditMode === 'create') { + const id = v4(); + await createEmptyView(id, name ?? ''); + selectView(id); + } else { + updateCurrentView({ name }); + } + resetMenu(); setViewEditMode('none'); closeDropdown(); @@ -133,7 +139,11 @@ export const RecordIndexOptionsDropdownContent = ({ ? 'View name' : '' } - defaultValue={viewEditMode === 'create' ? '' : currentView?.name} + defaultValue={ + viewEditMode === 'create' + ? '' + : currentViewWithCombinedFiltersAndSorts?.name + } /> @@ -185,7 +195,7 @@ export const RecordIndexOptionsDropdownContent = ({ onToggleChange={() => setAndPersistIsCompactModeActive( !isCompactModeActive, - currentView, + currentViewWithCombinedFiltersAndSorts, ) } toggled={isCompactModeActive} diff --git a/packages/twenty-front/src/modules/object-record/record-index/options/hooks/useExportTableData.ts b/packages/twenty-front/src/modules/object-record/record-index/options/hooks/useExportTableData.ts index ab72add280..8ee5ecb172 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/options/hooks/useExportTableData.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/options/hooks/useExportTableData.ts @@ -109,11 +109,11 @@ export const useExportTableData = ({ const [progress, setProgress] = useState(undefined); const [hasNextPage, setHasNextPage] = useState(true); - const { getVisibleTableColumnsSelector, getSelectedRowIdsSelector } = + const { visibleTableColumnsSelector, selectedRowIdsSelector } = useRecordTableStates(recordIndexId); - const columns = useRecoilValue(getVisibleTableColumnsSelector()); - const selectedRowIds = useRecoilValue(getSelectedRowIdsSelector()); + const columns = useRecoilValue(visibleTableColumnsSelector()); + const selectedRowIds = useRecoilValue(selectedRowIdsSelector()); const hasSelectedRows = selectedRowIds.length > 0; diff --git a/packages/twenty-front/src/modules/object-record/record-index/options/hooks/useRecordIndexOptionsForBoard.ts b/packages/twenty-front/src/modules/object-record/record-index/options/hooks/useRecordIndexOptionsForBoard.ts index 33da264c96..da059ea504 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/options/hooks/useRecordIndexOptionsForBoard.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/options/hooks/useRecordIndexOptionsForBoard.ts @@ -8,8 +8,8 @@ import { useRecordBoard } from '@/object-record/record-board/hooks/useRecordBoar import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata'; import { recordIndexFieldDefinitionsState } from '@/object-record/record-index/states/recordIndexFieldDefinitionsState'; import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition'; -import { useViewFields } from '@/views/hooks/internal/useViewFields'; -import { useViews } from '@/views/hooks/internal/useViews'; +import { useHandleViews } from '@/views/hooks/useHandleViews'; +import { useSaveCurrentViewFields } from '@/views/hooks/useSaveCurrentViewFields'; import { GraphQLView } from '@/views/types/GraphQLView'; import { mapBoardFieldDefinitionsToViewFields } from '@/views/utils/mapBoardFieldDefinitionsToViewFields'; import { mapArrayToObject } from '~/utils/array/mapArrayToObject'; @@ -28,14 +28,14 @@ export const useRecordIndexOptionsForBoard = ({ viewBarId, }: useRecordIndexOptionsForBoardParams) => { const [recordIndexFieldDefinitions, setRecordIndexFieldDefinitions] = - useRecoilState(recordIndexFieldDefinitionsState()); + useRecoilState(recordIndexFieldDefinitionsState); - const { persistViewFields } = useViewFields(viewBarId); - const { updateView } = useViews(viewBarId); - const { getIsCompactModeActiveState } = useRecordBoard(recordBoardId); + const { saveViewFields } = useSaveCurrentViewFields(viewBarId); + const { updateCurrentView } = useHandleViews(viewBarId); + const { isCompactModeActiveState } = useRecordBoard(recordBoardId); const [isCompactModeActive, setIsCompactModeActive] = useRecoilState( - getIsCompactModeActiveState(), + isCompactModeActiveState, ); const { objectMetadataItem } = useObjectMetadataItemOnly({ @@ -105,20 +105,14 @@ export const useRecordIndexOptionsForBoard = ({ if (isDeeplyEqual(visibleBoardFields, reorderedVisibleBoardFields)) return; - const updatedFields = [ - ...reorderedVisibleBoardFields, - ...hiddenBoardFields, - ].map((field, index) => ({ ...field, position: index })); + const updatedFields = [...reorderedVisibleBoardFields].map( + (field, index) => ({ ...field, position: index }), + ); setRecordIndexFieldDefinitions(updatedFields); - persistViewFields(mapBoardFieldDefinitionsToViewFields(updatedFields)); + saveViewFields(mapBoardFieldDefinitionsToViewFields(updatedFields)); }, - [ - hiddenBoardFields, - persistViewFields, - setRecordIndexFieldDefinitions, - visibleBoardFields, - ], + [saveViewFields, setRecordIndexFieldDefinitions, visibleBoardFields], ); // Todo : this seems over complex and should at least be extracted to an util with unit test. @@ -172,14 +166,14 @@ export const useRecordIndexOptionsForBoard = ({ setRecordIndexFieldDefinitions(updatedFieldsDefinitions); - persistViewFields( + saveViewFields( mapBoardFieldDefinitionsToViewFields(updatedFieldsDefinitions), ); }, [ recordIndexFieldDefinitionsByKey, setRecordIndexFieldDefinitions, - persistViewFields, + saveViewFields, availableColumnDefinitions, visibleBoardFields, recordIndexFieldDefinitions, @@ -190,12 +184,11 @@ export const useRecordIndexOptionsForBoard = ({ (isCompactModeActive: boolean, view: GraphQLView | undefined) => { if (!view) return; setIsCompactModeActive(isCompactModeActive); - updateView({ - ...view, + updateCurrentView({ isCompact: isCompactModeActive, }); }, - [setIsCompactModeActive, updateView], + [setIsCompactModeActive, updateCurrentView], ); return { diff --git a/packages/twenty-front/src/modules/object-record/record-index/options/hooks/useRecordIndexOptionsForTable.ts b/packages/twenty-front/src/modules/object-record/record-index/options/hooks/useRecordIndexOptionsForTable.ts index 011c6f87d4..e72bc75343 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/options/hooks/useRecordIndexOptionsForTable.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/options/hooks/useRecordIndexOptionsForTable.ts @@ -7,11 +7,11 @@ import { useTableColumns } from '@/object-record/record-table/hooks/useTableColu import { moveArrayItem } from '~/utils/array/moveArrayItem'; export const useRecordIndexOptionsForTable = (recordTableId: string) => { - const { getHiddenTableColumnsSelector, getVisibleTableColumnsSelector } = + const { hiddenTableColumnsSelector, visibleTableColumnsSelector } = useRecordTableStates(recordTableId); - const hiddenTableColumns = useRecoilValue(getHiddenTableColumnsSelector()); - const visibleTableColumns = useRecoilValue(getVisibleTableColumnsSelector()); + const hiddenTableColumns = useRecoilValue(hiddenTableColumnsSelector()); + const visibleTableColumns = useRecoilValue(visibleTableColumnsSelector()); const { handleColumnVisibilityChange, handleColumnReorder } = useTableColumns( { recordTableId: recordTableId }, 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 c3c2133377..76035fb781 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 @@ -24,7 +24,7 @@ import { LightIconButton } from '@/ui/input/button/components/LightIconButton'; 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 { FilterQueryParams } from '@/views/hooks/internal/useFiltersFromQueryParams'; +import { FilterQueryParams } from '@/views/hooks/internal/useViewFromQueryParams'; import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; const StyledAddDropdown = styled(Dropdown)` diff --git a/packages/twenty-front/src/modules/object-record/record-store/states/selectors/recordStoreIdentifierSelector.ts b/packages/twenty-front/src/modules/object-record/record-store/states/selectors/recordStoreIdentifierSelector.ts index 10167cc4c8..24502a2881 100644 --- a/packages/twenty-front/src/modules/object-record/record-store/states/selectors/recordStoreIdentifierSelector.ts +++ b/packages/twenty-front/src/modules/object-record/record-store/states/selectors/recordStoreIdentifierSelector.ts @@ -17,7 +17,7 @@ export const recordStoreIdentifierFamilySelector = selectorFamily({ ({ get }) => { const recordFromStore = get(recordStoreFamilyState(recordId)); - const objectMetadataItems = get(objectMetadataItemsState()); + const objectMetadataItems = get(objectMetadataItemsState); const objectMetadataItem = objectMetadataItems.find( (item) => item.nameSingular === objectNameSingular, diff --git a/packages/twenty-front/src/modules/object-record/record-table/action-bar/components/RecordTableActionBar.tsx b/packages/twenty-front/src/modules/object-record/record-table/action-bar/components/RecordTableActionBar.tsx index 86b5e3534b..14b3768d08 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/action-bar/components/RecordTableActionBar.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/action-bar/components/RecordTableActionBar.tsx @@ -8,9 +8,9 @@ export const RecordTableActionBar = ({ }: { recordTableId: string; }) => { - const { getSelectedRowIdsSelector } = useRecordTableStates(recordTableId); + const { selectedRowIdsSelector } = useRecordTableStates(recordTableId); - const selectedRowIds = useRecoilValue(getSelectedRowIdsSelector()); + const selectedRowIds = useRecoilValue(selectedRowIdsSelector()); if (!selectedRowIds.length) { return null; diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/CheckboxCell.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/CheckboxCell.tsx index d6c432c815..2aff77e1b1 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/components/CheckboxCell.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/components/CheckboxCell.tsx @@ -22,7 +22,7 @@ const StyledContainer = styled.div` export const CheckboxCell = () => { const { recordId } = useContext(RecordTableRowContext); const { isRowSelectedFamilyState } = useRecordTableStates(); - const setActionBarOpenState = useSetRecoilState(actionBarOpenState()); + const setActionBarOpenState = useSetRecoilState(actionBarOpenState); const { setCurrentRowSelected } = useSetCurrentRowSelected(); const currentRowSelected = useRecoilValue(isRowSelectedFamilyState(recordId)); diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/ColumnHead.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/ColumnHead.tsx index 2cd9432bd2..5f3207bfa2 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/components/ColumnHead.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/components/ColumnHead.tsx @@ -53,7 +53,7 @@ export const ColumnHead = ({ column }: ColumnHeadProps) => { const { getIcon } = useIcons(); const Icon = getIcon(column.iconName); - const scrollLeft = useRecoilValue(scrollLeftState()); + const scrollLeft = useRecoilValue(scrollLeftState); return ( 0}> diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTable.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTable.tsx index 6d9a60ca70..80dbedafd4 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTable.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTable.tsx @@ -122,7 +122,7 @@ export const RecordTable = ({ createRecord, }: RecordTableProps) => { const { scopeId } = useRecordTableStates(recordTableId); - const scrollLeft = useRecoilValue(scrollLeftState()); + const scrollLeft = useRecoilValue(scrollLeftState); const { objectMetadataItem } = useObjectMetadataItemOnly({ objectNameSingular, diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableBody.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableBody.tsx index 4ba288f228..3f9ad3da58 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableBody.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableBody.tsx @@ -11,9 +11,9 @@ type RecordTableBodyProps = { export const RecordTableBody = ({ objectNameSingular, }: RecordTableBodyProps) => { - const { getTableRowIdsState } = useRecordTableStates(); + const { tableRowIdsState } = useRecordTableStates(); - const tableRowIds = useRecoilValue(getTableRowIdsState()); + const tableRowIds = useRecoilValue(tableRowIdsState); return ( <> diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableBodyEffect.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableBodyEffect.tsx index 6b215db7ed..bb70caea38 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableBodyEffect.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableBodyEffect.tsx @@ -21,10 +21,10 @@ export const RecordTableBodyEffect = ({ loading, } = useLoadRecordIndexTable(objectNameSingular); - const { getTableLastRowVisibleState } = useRecordTableStates(); + const { tableLastRowVisibleState } = useRecordTableStates(); const [tableLastRowVisible, setTableLastRowVisible] = useRecoilState( - getTableLastRowVisibleState(), + tableLastRowVisibleState, ); const isFetchingMoreObjects = useRecoilValue( diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableCellContainer.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableCellContainer.tsx index da9c038b56..a879ed19af 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableCellContainer.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableCellContainer.tsx @@ -23,8 +23,8 @@ const StyledContainer = styled.td<{ isSelected: boolean }>` `; export const RecordTableCellContainer = () => { - const setContextMenuPosition = useSetRecoilState(contextMenuPositionState()); - const setContextMenuOpenState = useSetRecoilState(contextMenuIsOpenState()); + const setContextMenuPosition = useSetRecoilState(contextMenuPositionState); + const setContextMenuOpenState = useSetRecoilState(contextMenuIsOpenState); const { setCurrentRowSelected } = useSetCurrentRowSelected(); diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableColumnDropdownMenu.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableColumnDropdownMenu.tsx index 911bb3d87f..17417a8329 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableColumnDropdownMenu.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableColumnDropdownMenu.tsx @@ -17,9 +17,9 @@ export type RecordTableColumnDropdownMenuProps = { export const RecordTableColumnDropdownMenu = ({ column, }: RecordTableColumnDropdownMenuProps) => { - const { getVisibleTableColumnsSelector } = useRecordTableStates(); + const { visibleTableColumnsSelector } = useRecordTableStates(); - const visibleTableColumns = useRecoilValue(getVisibleTableColumnsSelector()); + const visibleTableColumns = useRecoilValue(visibleTableColumnsSelector()); const secondVisibleColumn = visibleTableColumns[1]; const canMoveLeft = diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableHeader.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableHeader.tsx index 6cde82074c..90611c0eb2 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableHeader.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableHeader.tsx @@ -56,16 +56,15 @@ export const RecordTableHeader = ({ }: { createRecord: () => void; }) => { - const { getHiddenTableColumnsSelector, getVisibleTableColumnsSelector } = - useRecordTableStates(); + const { visibleTableColumnsSelector } = useRecordTableStates(); const scrollWrapper = useScrollWrapperScopedRef(); const isTableWiderThanScreen = (scrollWrapper.current?.clientWidth ?? 0) < (scrollWrapper.current?.scrollWidth ?? 0); - const visibleTableColumns = useRecoilValue(getVisibleTableColumnsSelector()); - const hiddenTableColumns = useRecoilValue(getHiddenTableColumnsSelector()); + const visibleTableColumns = useRecoilValue(visibleTableColumnsSelector()); + const hiddenTableColumns = useRecoilValue(visibleTableColumnsSelector()); const theme = useTheme(); diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableHeaderCell.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableHeaderCell.tsx index 9d1f7f89a9..ec96d4990f 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableHeaderCell.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableHeaderCell.tsx @@ -82,14 +82,13 @@ export const RecordTableHeaderCell = ({ column: ColumnDefinition; createRecord: () => void; }) => { - const { getResizeFieldOffsetState, getTableColumnsState } = - useRecordTableStates(); + const { resizeFieldOffsetState, tableColumnsState } = useRecordTableStates(); const [resizeFieldOffset, setResizeFieldOffset] = useRecoilState( - getResizeFieldOffsetState(), + resizeFieldOffsetState, ); - const tableColumns = useRecoilValue(getTableColumnsState()); + const tableColumns = useRecoilValue(tableColumnsState); const tableColumnsByKey = useMemo( () => mapArrayToObject(tableColumns, ({ fieldMetadataId }) => fieldMetadataId), @@ -124,7 +123,7 @@ export const RecordTableHeaderCell = ({ const resizeFieldOffset = getSnapshotValue( snapshot, - getResizeFieldOffsetState(), + resizeFieldOffsetState, ); const nextWidth = Math.round( @@ -134,7 +133,7 @@ export const RecordTableHeaderCell = ({ ), ); - set(getResizeFieldOffsetState(), 0); + set(resizeFieldOffsetState, 0); setInitialPointerPositionX(null); setResizedFieldKey(null); @@ -150,7 +149,7 @@ export const RecordTableHeaderCell = ({ }, [ resizedFieldKey, - getResizeFieldOffsetState, + resizeFieldOffsetState, tableColumnsByKey, tableColumns, handleColumnsChange, @@ -165,7 +164,7 @@ export const RecordTableHeaderCell = ({ }); const isMobile = useIsMobile(); - const scrollLeft = useRecoilValue(scrollLeftState()); + const scrollLeft = useRecoilValue(scrollLeftState); const disableColumnResize = column.isLabelIdentifier && isMobile && scrollLeft > 0; diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableHeaderPlusButtonContent.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableHeaderPlusButtonContent.tsx index b08140cea4..91b3f8527c 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableHeaderPlusButtonContent.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableHeaderPlusButtonContent.tsx @@ -17,9 +17,9 @@ import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem'; export const RecordTableHeaderPlusButtonContent = () => { const { closeDropdown } = useDropdown(); - const { getHiddenTableColumnsSelector } = useRecordTableStates(); + const { hiddenTableColumnsSelector } = useRecordTableStates(); - const hiddenTableColumns = useRecoilValue(getHiddenTableColumnsSelector()); + const hiddenTableColumns = useRecoilValue(hiddenTableColumnsSelector()); const { getIcon } = useIcons(); const { handleColumnVisibilityChange } = useTableColumns(); diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableRow.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableRow.tsx index b6af608f61..9f018f8f5c 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableRow.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableRow.tsx @@ -23,12 +23,12 @@ const StyledTd = styled.td` `; export const RecordTableRow = ({ recordId, rowIndex }: RecordTableRowProps) => { - const { getVisibleTableColumnsSelector, isRowSelectedFamilyState } = + const { visibleTableColumnsSelector, isRowSelectedFamilyState } = useRecordTableStates(); const currentRowSelected = useRecoilValue(isRowSelectedFamilyState(recordId)); const { objectMetadataItem } = useContext(RecordTableContext); - const visibleTableColumns = useRecoilValue(getVisibleTableColumnsSelector()); + const visibleTableColumns = useRecoilValue(visibleTableColumnsSelector()); const scrollWrapperRef = useContext(ScrollWrapperContext); 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 8eca731871..cb071bfffd 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 @@ -20,7 +20,7 @@ import { } from '@/ui/layout/animated-placeholder/components/EmptyPlaceholderStyled'; import { DragSelect } from '@/ui/utilities/drag-select/components/DragSelect'; import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper'; -import { useViewFields } from '@/views/hooks/internal/useViewFields'; +import { useSaveCurrentViewFields } from '@/views/hooks/useSaveCurrentViewFields'; import { mapColumnDefinitionsToViewFields } from '@/views/utils/mapColumnDefinitionToViewField'; import { RecordUpdateContext } from '../contexts/EntityUpdateMutationHookContext'; @@ -59,13 +59,13 @@ export const RecordTableWithWrappers = ({ }: RecordTableWithWrappersProps) => { const tableBodyRef = useRef(null); - const { getNumberOfTableRowsState, getIsRecordTableInitialLoadingState } = + const { numberOfTableRowsState, isRecordTableInitialLoadingState } = useRecordTableStates(recordTableId); - const numberOfTableRows = useRecoilValue(getNumberOfTableRowsState()); + const numberOfTableRows = useRecoilValue(numberOfTableRowsState); const isRecordTableInitialLoading = useRecoilValue( - getIsRecordTableInitialLoadingState(), + isRecordTableInitialLoadingState, ); const { resetTableRowSelection, setRowSelectedState } = useRecordTable({ @@ -78,7 +78,7 @@ export const RecordTableWithWrappers = ({ }, ); - const { persistViewFields } = useViewFields(viewBarId); + const { saveViewFields } = useSaveCurrentViewFields(viewBarId); const { deleteOneRecord } = useDeleteOneRecord({ objectNameSingular }); @@ -96,13 +96,13 @@ export const RecordTableWithWrappers = ({ objectNameSingular={objectNameSingular} onColumnsChange={useRecoilCallback( () => (columns) => { - persistViewFields( + saveViewFields( mapColumnDefinitionsToViewFields( columns as ColumnDefinition[], ), ); }, - [persistViewFields], + [saveViewFields], )} createRecord={createRecord} /> diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/SelectAllCheckbox.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/SelectAllCheckbox.tsx index 9f9a46a70f..c5036f2888 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/components/SelectAllCheckbox.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/components/SelectAllCheckbox.tsx @@ -17,11 +17,9 @@ const StyledContainer = styled.div` `; export const SelectAllCheckbox = () => { - const { getAllRowsSelectedStatusSelector } = useRecordTableStates(); + const { allRowsSelectedStatusSelector } = useRecordTableStates(); - const allRowsSelectedStatus = useRecoilValue( - getAllRowsSelectedStatusSelector(), - ); + const allRowsSelectedStatus = useRecoilValue(allRowsSelectedStatusSelector()); const { selectAllRows } = useRecordTable(); const checked = allRowsSelectedStatus === 'all'; diff --git a/packages/twenty-front/src/modules/object-record/record-table/context-menu/components/RecordTableContextMenu.tsx b/packages/twenty-front/src/modules/object-record/record-table/context-menu/components/RecordTableContextMenu.tsx index 2ccbae7698..d9f712ef82 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/context-menu/components/RecordTableContextMenu.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/context-menu/components/RecordTableContextMenu.tsx @@ -8,9 +8,9 @@ export const RecordTableContextMenu = ({ }: { recordTableId: string; }) => { - const { getSelectedRowIdsSelector } = useRecordTableStates(recordTableId); + const { selectedRowIdsSelector } = useRecordTableStates(recordTableId); - const selectedRowIds = useRecoilValue(getSelectedRowIdsSelector()); + const selectedRowIds = useRecoilValue(selectedRowIdsSelector()); if (!selectedRowIds.length) { return null; diff --git a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useCloseCurrentTableCellInEditMode.ts b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useCloseCurrentTableCellInEditMode.ts index d8c21c8440..a9976aa05f 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useCloseCurrentTableCellInEditMode.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useCloseCurrentTableCellInEditMode.ts @@ -5,7 +5,7 @@ import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotV export const useCloseCurrentTableCellInEditMode = (recordTableId?: string) => { const { - getCurrentTableCellInEditModePositionState, + currentTableCellInEditModePositionState, isTableCellInEditModeFamilyState, } = useRecordTableStates(recordTableId); @@ -14,7 +14,7 @@ export const useCloseCurrentTableCellInEditMode = (recordTableId?: string) => { return async () => { const currentTableCellInEditModePosition = getSnapshotValue( snapshot, - getCurrentTableCellInEditModePositionState(), + currentTableCellInEditModePositionState, ); set( @@ -23,9 +23,6 @@ export const useCloseCurrentTableCellInEditMode = (recordTableId?: string) => { ); }; }, - [ - getCurrentTableCellInEditModePositionState, - isTableCellInEditModeFamilyState, - ], + [currentTableCellInEditModePositionState, isTableCellInEditModeFamilyState], ); }; diff --git a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useDisableSoftFocus.ts b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useDisableSoftFocus.ts index fed4211c97..2e1704dfa5 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useDisableSoftFocus.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useDisableSoftFocus.ts @@ -5,8 +5,8 @@ import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotV export const useDisableSoftFocus = (recordTableId?: string) => { const { - getSoftFocusPositionState, - getIsSoftFocusActiveState, + softFocusPositionState, + isSoftFocusActiveState, isSoftFocusOnTableCellFamilyState, } = useRecordTableStates(recordTableId); @@ -15,17 +15,17 @@ export const useDisableSoftFocus = (recordTableId?: string) => { return () => { const currentPosition = getSnapshotValue( snapshot, - getSoftFocusPositionState(), + softFocusPositionState, ); - set(getIsSoftFocusActiveState(), false); + set(isSoftFocusActiveState, false); set(isSoftFocusOnTableCellFamilyState(currentPosition), false); }; }, [ - getIsSoftFocusActiveState, - getSoftFocusPositionState, + isSoftFocusActiveState, + softFocusPositionState, isSoftFocusOnTableCellFamilyState, ], ); diff --git a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useGetIsSomeCellInEditMode.ts b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useGetIsSomeCellInEditMode.ts index 8a4b486258..ecc422eecd 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useGetIsSomeCellInEditMode.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useGetIsSomeCellInEditMode.ts @@ -5,7 +5,7 @@ import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotV export const useGetIsSomeCellInEditModeState = (recordTableId?: string) => { const { - getCurrentTableCellInEditModePositionState, + currentTableCellInEditModePositionState, isTableCellInEditModeFamilyState, } = useRecordTableStates(recordTableId); @@ -14,7 +14,7 @@ export const useGetIsSomeCellInEditModeState = (recordTableId?: string) => { () => { const currentTableCellInEditModePosition = getSnapshotValue( snapshot, - getCurrentTableCellInEditModePositionState(), + currentTableCellInEditModePositionState, ); const isSomeCellInEditModeState = isTableCellInEditModeFamilyState( @@ -23,9 +23,6 @@ export const useGetIsSomeCellInEditModeState = (recordTableId?: string) => { return isSomeCellInEditModeState; }, - [ - getCurrentTableCellInEditModePositionState, - isTableCellInEditModeFamilyState, - ], + [currentTableCellInEditModePositionState, isTableCellInEditModeFamilyState], ); }; diff --git a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useLeaveTableFocus.ts b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useLeaveTableFocus.ts index ff2e2b877c..0ee3aa62d6 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useLeaveTableFocus.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useLeaveTableFocus.ts @@ -14,18 +14,18 @@ export const useLeaveTableFocus = (recordTableId?: string) => { const closeCurrentCellInEditMode = useCloseCurrentTableCellInEditMode(recordTableId); - const { getIsSoftFocusActiveState } = useRecordTableStates(recordTableId); + const { isSoftFocusActiveState } = useRecordTableStates(recordTableId); return useRecoilCallback( ({ snapshot }) => () => { const isSoftFocusActive = getSnapshotValue( snapshot, - getIsSoftFocusActiveState(), + isSoftFocusActiveState, ); const currentHotkeyScope = snapshot - .getLoadable(currentHotkeyScopeState()) + .getLoadable(currentHotkeyScopeState) .getValue(); if (!isSoftFocusActive) { @@ -39,6 +39,6 @@ export const useLeaveTableFocus = (recordTableId?: string) => { closeCurrentCellInEditMode(); disableSoftFocus(); }, - [closeCurrentCellInEditMode, disableSoftFocus, getIsSoftFocusActiveState], + [closeCurrentCellInEditMode, disableSoftFocus, isSoftFocusActiveState], ); }; diff --git a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useMoveEditModeToCellPosition.ts b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useMoveEditModeToCellPosition.ts index 5bb32c4abe..02e04a259d 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useMoveEditModeToCellPosition.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useMoveEditModeToCellPosition.ts @@ -8,7 +8,7 @@ import { TableCellPosition } from '../../types/TableCellPosition'; export const useMoveEditModeToTableCellPosition = (recordTableId?: string) => { const { isTableCellInEditModeFamilyState, - getCurrentTableCellInEditModePositionState, + currentTableCellInEditModePositionState, } = useRecordTableStates(recordTableId); return useRecoilCallback( @@ -16,7 +16,7 @@ export const useMoveEditModeToTableCellPosition = (recordTableId?: string) => { return (newPosition: TableCellPosition) => { const currentTableCellInEditModePosition = getSnapshotValue( snapshot, - getCurrentTableCellInEditModePositionState(), + currentTableCellInEditModePositionState, ); set( @@ -24,14 +24,11 @@ export const useMoveEditModeToTableCellPosition = (recordTableId?: string) => { false, ); - set(getCurrentTableCellInEditModePositionState(), newPosition); + set(currentTableCellInEditModePositionState, newPosition); set(isTableCellInEditModeFamilyState(newPosition), true); }; }, - [ - getCurrentTableCellInEditModePositionState, - isTableCellInEditModeFamilyState, - ], + [currentTableCellInEditModePositionState, isTableCellInEditModeFamilyState], ); }; diff --git a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useRecordTableStates.ts b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useRecordTableStates.ts index 21414ec2d7..1d7fff60f1 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useRecordTableStates.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useRecordTableStates.ts @@ -35,44 +35,41 @@ export const useRecordTableStates = (recordTableId?: string) => { return { scopeId, - getAvailableTableColumnsState: extractComponentState( + availableTableColumnsState: extractComponentState( availableTableColumnsComponentState, scopeId, ), - getTableFiltersState: extractComponentState( + tableFiltersState: extractComponentState( tableFiltersComponentState, scopeId, ), - getTableSortsState: extractComponentState( - tableSortsComponentState, - scopeId, - ), - getTableColumnsState: extractComponentState( + tableSortsState: extractComponentState(tableSortsComponentState, scopeId), + tableColumnsState: extractComponentState( tableColumnsComponentState, scopeId, ), - getOnColumnsChangeState: extractComponentState( + onColumnsChangeState: extractComponentState( onColumnsChangeComponentState, scopeId, ), - getOnEntityCountChangeState: extractComponentState( + onEntityCountChangeState: extractComponentState( onEntityCountChangeComponentState, scopeId, ), - getTableLastRowVisibleState: extractComponentState( + tableLastRowVisibleState: extractComponentState( tableLastRowVisibleComponentState, scopeId, ), - getSoftFocusPositionState: extractComponentState( + softFocusPositionState: extractComponentState( softFocusPositionComponentState, scopeId, ), - getNumberOfTableRowsState: extractComponentState( + numberOfTableRowsState: extractComponentState( numberOfTableRowsComponentState, scopeId, ), - getCurrentTableCellInEditModePositionState: extractComponentState( + currentTableCellInEditModePositionState: extractComponentState( currentTableCellInEditModePositionComponentState, scopeId, ), @@ -80,19 +77,16 @@ export const useRecordTableStates = (recordTableId?: string) => { isTableCellInEditModeComponentFamilyState, scopeId, ), - getIsSoftFocusActiveState: extractComponentState( + isSoftFocusActiveState: extractComponentState( isSoftFocusActiveComponentState, scopeId, ), - getTableRowIdsState: extractComponentState( - tableRowIdsComponentState, - scopeId, - ), - getIsRecordTableInitialLoadingState: extractComponentState( + tableRowIdsState: extractComponentState(tableRowIdsComponentState, scopeId), + isRecordTableInitialLoadingState: extractComponentState( isRecordTableInitialLoadingComponentState, scopeId, ), - getResizeFieldOffsetState: extractComponentState( + resizeFieldOffsetState: extractComponentState( resizeFieldOffsetComponentState, scopeId, ), @@ -104,23 +98,23 @@ export const useRecordTableStates = (recordTableId?: string) => { isRowSelectedComponentFamilyState, scopeId, ), - getAllRowsSelectedStatusSelector: extractComponentReadOnlySelector( + allRowsSelectedStatusSelector: extractComponentReadOnlySelector( allRowsSelectedStatusComponentSelector, scopeId, ), - getHiddenTableColumnsSelector: extractComponentReadOnlySelector( + hiddenTableColumnsSelector: extractComponentReadOnlySelector( hiddenTableColumnsComponentSelector, scopeId, ), - getNumberOfTableColumnsSelector: extractComponentReadOnlySelector( + numberOfTableColumnsSelector: extractComponentReadOnlySelector( numberOfTableColumnsComponentSelector, scopeId, ), - getSelectedRowIdsSelector: extractComponentReadOnlySelector( + selectedRowIdsSelector: extractComponentReadOnlySelector( selectedRowIdsComponentSelector, scopeId, ), - getVisibleTableColumnsSelector: extractComponentReadOnlySelector( + visibleTableColumnsSelector: extractComponentReadOnlySelector( visibleTableColumnsComponentSelector, scopeId, ), diff --git a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useResetTableRowSelection.ts b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useResetTableRowSelection.ts index c722d40bb5..7e86f58190 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useResetTableRowSelection.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useResetTableRowSelection.ts @@ -4,18 +4,18 @@ import { useRecordTableStates } from '@/object-record/record-table/hooks/interna import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; export const useResetTableRowSelection = (recordTableId?: string) => { - const { getTableRowIdsState, isRowSelectedFamilyState } = + const { tableRowIdsState, isRowSelectedFamilyState } = useRecordTableStates(recordTableId); return useRecoilCallback( ({ snapshot, set }) => () => { - const tableRowIds = getSnapshotValue(snapshot, getTableRowIdsState()); + const tableRowIds = getSnapshotValue(snapshot, tableRowIdsState); for (const rowId of tableRowIds) { set(isRowSelectedFamilyState(rowId), false); } }, - [getTableRowIdsState, isRowSelectedFamilyState], + [tableRowIdsState, isRowSelectedFamilyState], ); }; diff --git a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useSelectAllRows.ts b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useSelectAllRows.ts index 1a7e563c15..c76683e6ae 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useSelectAllRows.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useSelectAllRows.ts @@ -5,8 +5,8 @@ import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotV export const useSelectAllRows = (recordTableId?: string) => { const { - getAllRowsSelectedStatusSelector, - getTableRowIdsState, + allRowsSelectedStatusSelector, + tableRowIdsState, isRowSelectedFamilyState, } = useRecordTableStates(recordTableId); @@ -15,10 +15,10 @@ export const useSelectAllRows = (recordTableId?: string) => { () => { const allRowsSelectedStatus = getSnapshotValue( snapshot, - getAllRowsSelectedStatusSelector(), + allRowsSelectedStatusSelector(), ); - const tableRowIds = getSnapshotValue(snapshot, getTableRowIdsState()); + const tableRowIds = getSnapshotValue(snapshot, tableRowIdsState); if ( allRowsSelectedStatus === 'none' || @@ -33,11 +33,7 @@ export const useSelectAllRows = (recordTableId?: string) => { } } }, - [ - getAllRowsSelectedStatusSelector, - getTableRowIdsState, - isRowSelectedFamilyState, - ], + [allRowsSelectedStatusSelector, tableRowIdsState, isRowSelectedFamilyState], ); return { diff --git a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useSetRecordTableData.ts b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useSetRecordTableData.ts index 01fa47fe3b..32c1986ec4 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useSetRecordTableData.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useSetRecordTableData.ts @@ -14,7 +14,7 @@ export const useSetRecordTableData = ({ recordTableId, onEntityCountChange, }: useSetRecordTableDataProps) => { - const { getTableRowIdsState, getNumberOfTableRowsState } = + const { tableRowIdsState, numberOfTableRowsState } = useRecordTableStates(recordTableId); return useRecoilCallback( @@ -30,17 +30,17 @@ export const useSetRecordTableData = ({ set(recordStoreFamilyState(entity.id), entity); } } - const currentRowIds = getSnapshotValue(snapshot, getTableRowIdsState()); + const currentRowIds = getSnapshotValue(snapshot, tableRowIdsState); const entityIds = newEntityArray.map((entity) => entity.id); if (!isDeeplyEqual(currentRowIds, entityIds)) { - set(getTableRowIdsState(), entityIds); + set(tableRowIdsState, entityIds); } - set(getNumberOfTableRowsState(), totalCount); + set(numberOfTableRowsState, totalCount); onEntityCountChange(totalCount); }, - [getNumberOfTableRowsState, getTableRowIdsState, onEntityCountChange], + [numberOfTableRowsState, tableRowIdsState, onEntityCountChange], ); }; diff --git a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useSetSoftFocusPosition.ts b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useSetSoftFocusPosition.ts index 5c0408c625..edf8f7a904 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useSetSoftFocusPosition.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useSetSoftFocusPosition.ts @@ -7,8 +7,8 @@ import { TableCellPosition } from '../../types/TableCellPosition'; export const useSetSoftFocusPosition = (recordTableId?: string) => { const { - getSoftFocusPositionState, - getIsSoftFocusActiveState, + softFocusPositionState, + isSoftFocusActiveState, isSoftFocusOnTableCellFamilyState, } = useRecordTableStates(recordTableId); @@ -17,21 +17,21 @@ export const useSetSoftFocusPosition = (recordTableId?: string) => { return (newPosition: TableCellPosition) => { const currentPosition = getSnapshotValue( snapshot, - getSoftFocusPositionState(), + softFocusPositionState, ); - set(getIsSoftFocusActiveState(), true); + set(isSoftFocusActiveState, true); set(isSoftFocusOnTableCellFamilyState(currentPosition), false); - set(getSoftFocusPositionState(), newPosition); + set(softFocusPositionState, newPosition); set(isSoftFocusOnTableCellFamilyState(newPosition), true); }; }, [ - getSoftFocusPositionState, - getIsSoftFocusActiveState, + softFocusPositionState, + isSoftFocusActiveState, isSoftFocusOnTableCellFamilyState, ], ); 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 a530bb6353..e876c51844 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 @@ -32,51 +32,49 @@ export const useRecordTable = (props?: useRecordTableProps) => { const { scopeId, - getAvailableTableColumnsState, - getTableFiltersState, - getTableSortsState, - getTableColumnsState, - getOnEntityCountChangeState, - getOnColumnsChangeState, - getIsRecordTableInitialLoadingState, - getTableLastRowVisibleState, - getSelectedRowIdsSelector, + availableTableColumnsState, + tableFiltersState, + tableSortsState, + tableColumnsState, + onEntityCountChangeState, + onColumnsChangeState, + isRecordTableInitialLoadingState, + tableLastRowVisibleState, + selectedRowIdsSelector, } = useRecordTableStates(recordTableId); const setAvailableTableColumns = useRecoilCallback( ({ snapshot, set }) => (columns: ColumnDefinition[]) => { - const availableTableColumnsState = getSnapshotValue( + const availableTableColumns = getSnapshotValue( snapshot, - getAvailableTableColumnsState(), + availableTableColumnsState, ); - if (isDeeplyEqual(availableTableColumnsState, columns)) { + if (isDeeplyEqual(availableTableColumns, columns)) { return; } - set(getAvailableTableColumnsState(), columns); + set(availableTableColumnsState, columns); }, - [getAvailableTableColumnsState], + [availableTableColumnsState], ); - const setOnEntityCountChange = useSetRecoilState( - getOnEntityCountChangeState(), - ); + const setOnEntityCountChange = useSetRecoilState(onEntityCountChangeState); - const setTableFilters = useSetRecoilState(getTableFiltersState()); + const setTableFilters = useSetRecoilState(tableFiltersState); - const setTableSorts = useSetRecoilState(getTableSortsState()); + const setTableSorts = useSetRecoilState(tableSortsState); - const setTableColumns = useSetRecoilState(getTableColumnsState()); + const setTableColumns = useSetRecoilState(tableColumnsState); - const setOnColumnsChange = useSetRecoilState(getOnColumnsChangeState()); + const setOnColumnsChange = useSetRecoilState(onColumnsChangeState); const setIsRecordTableInitialLoading = useSetRecoilState( - getIsRecordTableInitialLoadingState(), + isRecordTableInitialLoadingState, ); const setRecordTableLastRowVisible = useSetRecoilState( - getTableLastRowVisibleState(), + tableLastRowVisibleState, ); const onColumnsChange = useRecoilCallback( @@ -84,12 +82,12 @@ export const useRecordTable = (props?: useRecordTableProps) => { (columns: ColumnDefinition[]) => { const onColumnsChange = getSnapshotValue( snapshot, - getOnColumnsChangeState(), + onColumnsChangeState, ); onColumnsChange?.(columns); }, - [getOnColumnsChangeState], + [onColumnsChangeState], ); const onEntityCountChange = useRecoilCallback( @@ -97,12 +95,12 @@ export const useRecordTable = (props?: useRecordTableProps) => { (count: number) => { const onEntityCountChange = getSnapshotValue( snapshot, - getOnEntityCountChangeState(), + onEntityCountChangeState, ); onEntityCountChange?.(count); }, - [getOnEntityCountChangeState], + [onEntityCountChangeState], ); const setRecordTableData = useSetRecordTableData({ @@ -116,7 +114,7 @@ export const useRecordTable = (props?: useRecordTableProps) => { const resetTableRowSelection = useResetTableRowSelection(recordTableId); - const upsertRecordTableItem = useUpsertRecordFromState(); + const upsertRecordTableItem = useUpsertRecordFromState; const setSoftFocusPosition = useSetSoftFocusPosition(recordTableId); @@ -128,7 +126,7 @@ export const useRecordTable = (props?: useRecordTableProps) => { const setHotkeyScope = useSetHotkeyScope(); const setIsSoftFocusUsingMouseState = useSetRecoilState( - isSoftFocusUsingMouseState(), + isSoftFocusUsingMouseState, ); useScopedHotkeys( @@ -212,6 +210,6 @@ export const useRecordTable = (props?: useRecordTableProps) => { setRecordTableLastRowVisible, setSoftFocusPosition, isSomeCellInEditModeState, - getSelectedRowIdsSelector, + selectedRowIdsSelector, }; }; diff --git a/packages/twenty-front/src/modules/object-record/record-table/hooks/useRecordTableMoveFocus.ts b/packages/twenty-front/src/modules/object-record/record-table/hooks/useRecordTableMoveFocus.ts index 7c5de53e70..2291659af8 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/hooks/useRecordTableMoveFocus.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/hooks/useRecordTableMoveFocus.ts @@ -8,10 +8,10 @@ import { useSetSoftFocusPosition } from './internal/useSetSoftFocusPosition'; export const useRecordTableMoveFocus = (recordTableId?: string) => { const { scopeId, - getSoftFocusPositionState, - getNumberOfTableRowsState, - getNumberOfTableColumnsSelector, - getSelectedRowIdsSelector, + softFocusPositionState, + numberOfTableRowsState, + numberOfTableColumnsSelector, + selectedRowIdsSelector, } = useRecordTableStates(recordTableId); const setSoftFocusPosition = useSetSoftFocusPosition(recordTableId); @@ -21,7 +21,7 @@ export const useRecordTableMoveFocus = (recordTableId?: string) => { () => { const softFocusPosition = getSnapshotValue( snapshot, - getSoftFocusPositionState(), + softFocusPositionState, ); let newRowNumber = softFocusPosition.row - 1; @@ -35,7 +35,7 @@ export const useRecordTableMoveFocus = (recordTableId?: string) => { row: newRowNumber, }); }, - [getSoftFocusPositionState, setSoftFocusPosition], + [softFocusPositionState, setSoftFocusPosition], ); const moveDown = useRecoilCallback( @@ -43,12 +43,12 @@ export const useRecordTableMoveFocus = (recordTableId?: string) => { () => { const softFocusPosition = getSnapshotValue( snapshot, - getSoftFocusPositionState(), + softFocusPositionState, ); const numberOfTableRows = getSnapshotValue( snapshot, - getNumberOfTableRowsState(), + numberOfTableRowsState, ); let newRowNumber = softFocusPosition.row + 1; @@ -62,11 +62,7 @@ export const useRecordTableMoveFocus = (recordTableId?: string) => { row: newRowNumber, }); }, - [ - getNumberOfTableRowsState, - setSoftFocusPosition, - getSoftFocusPositionState, - ], + [numberOfTableRowsState, setSoftFocusPosition, softFocusPositionState], ); const moveRight = useRecoilCallback( @@ -74,17 +70,17 @@ export const useRecordTableMoveFocus = (recordTableId?: string) => { () => { const softFocusPosition = getSnapshotValue( snapshot, - getSoftFocusPositionState(), + softFocusPositionState, ); const numberOfTableColumns = getSnapshotValue( snapshot, - getNumberOfTableColumnsSelector(), + numberOfTableColumnsSelector(), ); const numberOfTableRows = getSnapshotValue( snapshot, - getNumberOfTableRowsState(), + numberOfTableRowsState, ); const currentColumnNumber = softFocusPosition.column; const currentRowNumber = softFocusPosition.row; @@ -117,9 +113,9 @@ export const useRecordTableMoveFocus = (recordTableId?: string) => { } }, [ - getSoftFocusPositionState, - getNumberOfTableColumnsSelector, - getNumberOfTableRowsState, + softFocusPositionState, + numberOfTableColumnsSelector, + numberOfTableRowsState, setSoftFocusPosition, ], ); @@ -129,12 +125,12 @@ export const useRecordTableMoveFocus = (recordTableId?: string) => { () => { const softFocusPosition = getSnapshotValue( snapshot, - getSoftFocusPositionState(), + softFocusPositionState, ); const numberOfTableColumns = getSnapshotValue( snapshot, - getNumberOfTableColumnsSelector(), + numberOfTableColumnsSelector(), ); const currentColumnNumber = softFocusPosition.column; @@ -165,8 +161,8 @@ export const useRecordTableMoveFocus = (recordTableId?: string) => { } }, [ - getNumberOfTableColumnsSelector, - getSoftFocusPositionState, + numberOfTableColumnsSelector, + softFocusPositionState, setSoftFocusPosition, ], ); @@ -178,6 +174,6 @@ export const useRecordTableMoveFocus = (recordTableId?: string) => { moveRight, moveUp, setSoftFocusPosition, - getSelectedRowIdsSelector, + selectedRowIdsSelector, }; }; 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 1cc9fa3444..534db94625 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 @@ -18,15 +18,15 @@ export const useTableColumns = (props?: useRecordTableProps) => { }); const { - getAvailableTableColumnsState, - getTableColumnsState, - getVisibleTableColumnsSelector, + availableTableColumnsState, + tableColumnsState, + visibleTableColumnsSelector, } = useRecordTableStates(props?.recordTableId); - const availableTableColumns = useRecoilValue(getAvailableTableColumnsState()); + const availableTableColumns = useRecoilValue(availableTableColumnsState); - const tableColumns = useRecoilValue(getTableColumnsState()); - const visibleTableColumns = useRecoilValue(getVisibleTableColumnsSelector()); + const tableColumns = useRecoilValue(tableColumnsState); + const visibleTableColumns = useRecoilValue(visibleTableColumnsSelector()); const { handleColumnMove } = useMoveViewColumns(); @@ -47,6 +47,11 @@ export const useTableColumns = (props?: useRecordTableProps) => { (tableColumns) => tableColumns.fieldMetadataId === viewField.fieldMetadataId, ); + const lastTableColumnPosition = [...tableColumns] + .sort((a, b) => b.position - a.position) + .map((column) => column.position); + + const lastPosition = lastTableColumnPosition[0] ?? 0; if (isNewColumn) { const newColumn = availableTableColumns.find( @@ -57,7 +62,7 @@ export const useTableColumns = (props?: useRecordTableProps) => { const nextColumns = [ ...tableColumns, - { ...newColumn, isVisible: true }, + { ...newColumn, isVisible: true, position: lastPosition + 1 }, ]; await handleColumnsChange(nextColumns); diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellContainer.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellContainer.tsx index b5ac47aafc..344988c941 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellContainer.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellContainer.tsx @@ -64,7 +64,7 @@ export const RecordTableCellContainer = ({ const isSomeCellInEditMode = useRecoilValue(isSomeCellInEditModeState()); const setIsSoftFocusUsingMouseState = useSetRecoilState( - isSoftFocusUsingMouseState(), + isSoftFocusUsingMouseState, ); const moveSoftFocusToCurrentCellOnHover = diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellSoftFocusMode.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellSoftFocusMode.tsx index b75d36e29a..7f10d98ba7 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellSoftFocusMode.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellSoftFocusMode.tsx @@ -29,7 +29,7 @@ export const RecordTableCellSoftFocusMode = ({ const toggleEditOnlyInput = useToggleEditOnlyInput(); const scrollRef = useRef(null); - const isSoftFocusUsingMouse = useRecoilValue(isSoftFocusUsingMouseState()); + const isSoftFocusUsingMouse = useRecoilValue(isSoftFocusUsingMouseState); const clearField = useClearField(); useEffect(() => { diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useCloseRecordTableCell.test.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useCloseRecordTableCell.test.tsx index c608e921e6..7e6dfb6f50 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useCloseRecordTableCell.test.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useCloseRecordTableCell.test.tsx @@ -55,11 +55,11 @@ describe('useCloseRecordTableCell', () => { const { result } = renderHook( () => { const { - getCurrentTableCellInEditModePositionState, + currentTableCellInEditModePositionState, isTableCellInEditModeFamilyState, } = useRecordTableStates(); const currentTableCellInEditModePosition = useRecoilValue( - getCurrentTableCellInEditModePositionState(), + currentTableCellInEditModePositionState, ); const isTableCellInEditMode = useRecoilValue( isTableCellInEditModeFamilyState(currentTableCellInEditModePosition), diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useMoveSoftFocusToCurrentCellOnHover.test.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useMoveSoftFocusToCurrentCellOnHover.test.tsx index 1ebad63a8f..b794641650 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useMoveSoftFocusToCurrentCellOnHover.test.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useMoveSoftFocusToCurrentCellOnHover.test.tsx @@ -65,11 +65,11 @@ jest.mock( '@/object-record/record-table/hooks/internal/useRecordTableStates', () => ({ useRecordTableStates: () => ({ - getSoftFocusPositionState: () => mockSoftFocusPositionState, - getIsSoftFocusActiveState: () => mockSoftFocusActiveState, + softFocusPositionState: mockSoftFocusPositionState, + isSoftFocusActiveState: mockSoftFocusActiveState, isSoftFocusOnTableCellFamilyState: () => mockIsSoftFocusOnTableCellFamilyState, - getCurrentTableCellInEditModePositionState: () => + currentTableCellInEditModePositionState: mockCurrentTableCellInEditModePositionState, isTableCellInEditModeFamilyState: () => mockIsTableCellInEditModeFamilyState, diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useMoveSoftFocusToCurrentCellOnHover.ts b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useMoveSoftFocusToCurrentCellOnHover.ts index 0ddc6fe6a1..3d53b8d9b0 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useMoveSoftFocusToCurrentCellOnHover.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useMoveSoftFocusToCurrentCellOnHover.ts @@ -12,7 +12,7 @@ export const useMoveSoftFocusToCurrentCellOnHover = () => { const setSoftFocusOnCurrentTableCell = useSetSoftFocusOnCurrentTableCell(); const { - getCurrentTableCellInEditModePositionState, + currentTableCellInEditModePositionState, isTableCellInEditModeFamilyState, } = useRecordTableStates(); @@ -21,7 +21,7 @@ export const useMoveSoftFocusToCurrentCellOnHover = () => { () => { const currentTableCellInEditModePosition = getSnapshotValue( snapshot, - getCurrentTableCellInEditModePositionState(), + currentTableCellInEditModePositionState, ); const isSomeCellInEditMode = snapshot @@ -33,7 +33,7 @@ export const useMoveSoftFocusToCurrentCellOnHover = () => { .getValue(); const currentHotkeyScope = snapshot - .getLoadable(currentHotkeyScopeState()) + .getLoadable(currentHotkeyScopeState) .getValue(); if ( @@ -49,7 +49,7 @@ export const useMoveSoftFocusToCurrentCellOnHover = () => { } }, [ - getCurrentTableCellInEditModePositionState, + currentTableCellInEditModePositionState, isTableCellInEditModeFamilyState, setSoftFocusOnCurrentTableCell, ], diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useSetSoftFocus.ts b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useSetSoftFocus.ts index 9c2ef5f73a..9b630f4e2f 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useSetSoftFocus.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useSetSoftFocus.ts @@ -10,7 +10,7 @@ import { TableHotkeyScope } from '../../types/TableHotkeyScope'; export const useSetSoftFocus = () => { const setSoftFocusPosition = useSetSoftFocusPosition(); - const { getIsSoftFocusActiveState } = useRecordTableStates(); + const { isSoftFocusActiveState } = useRecordTableStates(); const setHotkeyScope = useSetHotkeyScope(); @@ -19,10 +19,10 @@ export const useSetSoftFocus = () => { (newPosition: TableCellPosition) => { setSoftFocusPosition(newPosition); - set(getIsSoftFocusActiveState(), true); + set(isSoftFocusActiveState, true); setHotkeyScope(TableHotkeyScope.TableSoftFocus); }, - [setSoftFocusPosition, getIsSoftFocusActiveState, setHotkeyScope], + [setSoftFocusPosition, isSoftFocusActiveState, setHotkeyScope], ); }; diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray.test.tsx b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray.test.tsx index 92661b8e61..decadcd2e5 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray.test.tsx +++ b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray.test.tsx @@ -58,7 +58,7 @@ describe('useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray' }, }, ), - setObjectMetadata: useSetRecoilState(objectMetadataItemsState()), + setObjectMetadata: useSetRecoilState(objectMetadataItemsState), }; }, { diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useMultiObjectSearch.test.tsx b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useMultiObjectSearch.test.tsx index d48688e51d..fa85d86290 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useMultiObjectSearch.test.tsx +++ b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useMultiObjectSearch.test.tsx @@ -105,7 +105,7 @@ describe('useMultiObjectSearch', () => { }, ], }), - setObjectMetadata: useSetRecoilState(objectMetadataItemsState()), + setObjectMetadata: useSetRecoilState(objectMetadataItemsState), }), { wrapper: Wrapper, diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectSearchMatchesSearchFilterAndSelectedItemsQuery.ts b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectSearchMatchesSearchFilterAndSelectedItemsQuery.ts index 2da8287790..3f91947262 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectSearchMatchesSearchFilterAndSelectedItemsQuery.ts +++ b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectSearchMatchesSearchFilterAndSelectedItemsQuery.ts @@ -25,7 +25,7 @@ export const useMultiObjectSearchMatchesSearchFilterAndSelectedItemsQuery = ({ searchFilterValue: string; limit?: number; }) => { - const objectMetadataItems = useRecoilValue(objectMetadataItemsState()); + const objectMetadataItems = useRecoilValue(objectMetadataItemsState); const { searchFilterPerMetadataItemNameSingular } = useSearchFilterPerMetadataItem({ @@ -85,7 +85,7 @@ export const useMultiObjectSearchMatchesSearchFilterAndSelectedItemsQuery = ({ const multiSelectQueryForSelectedIds = useGenerateFindManyRecordsForMultipleMetadataItemsQuery({ - objectMetadataItems: objectMetadataItemsUsedInSelectedIdsQuery, + targetObjectMetadataItems: objectMetadataItemsUsedInSelectedIdsQuery, depth: 0, }); diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectSearchMatchesSearchFilterAndToSelectQuery.ts b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectSearchMatchesSearchFilterAndToSelectQuery.ts index 16ce8e1cf3..675dd938df 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectSearchMatchesSearchFilterAndToSelectQuery.ts +++ b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectSearchMatchesSearchFilterAndToSelectQuery.ts @@ -28,7 +28,7 @@ export const useMultiObjectSearchMatchesSearchFilterAndToSelectQuery = ({ searchFilterValue: string; limit?: number; }) => { - const objectMetadataItems = useRecoilValue(objectMetadataItemsState()); + const objectMetadataItems = useRecoilValue(objectMetadataItemsState); const nonSystemObjectMetadataItems = objectMetadataItems.filter( ({ nameSingular, isSystem }) => @@ -86,7 +86,7 @@ export const useMultiObjectSearchMatchesSearchFilterAndToSelectQuery = ({ const multiSelectQuery = useGenerateFindManyRecordsForMultipleMetadataItemsQuery({ - objectMetadataItems: nonSystemObjectMetadataItems, + targetObjectMetadataItems: nonSystemObjectMetadataItems, depth: 0, }); diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectSearchSelectedItemsQuery.ts b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectSearchSelectedItemsQuery.ts index a390c13f7c..0cfdaebf79 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectSearchSelectedItemsQuery.ts +++ b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectSearchSelectedItemsQuery.ts @@ -26,7 +26,7 @@ export const useMultiObjectSearchSelectedItemsQuery = ({ }: { selectedObjectRecordIds: SelectedObjectRecordId[]; }) => { - const objectMetadataItems = useRecoilValue(objectMetadataItemsState()); + const objectMetadataItems = useRecoilValue(objectMetadataItemsState); const objectMetadataItemsUsedInSelectedIdsQuery = objectMetadataItems.filter( ({ nameSingular }) => { @@ -69,7 +69,7 @@ export const useMultiObjectSearchSelectedItemsQuery = ({ const multiSelectQueryForSelectedIds = useGenerateFindManyRecordsForMultipleMetadataItemsQuery({ - objectMetadataItems: objectMetadataItemsUsedInSelectedIdsQuery, + targetObjectMetadataItems: objectMetadataItemsUsedInSelectedIdsQuery, }); const { diff --git a/packages/twenty-front/src/modules/object-record/spreadsheet-import/__tests__/useSpreadsheetRecordImport.test.tsx b/packages/twenty-front/src/modules/object-record/spreadsheet-import/__tests__/useSpreadsheetRecordImport.test.tsx index 6e400e579d..a925b36c8c 100644 --- a/packages/twenty-front/src/modules/object-record/spreadsheet-import/__tests__/useSpreadsheetRecordImport.test.tsx +++ b/packages/twenty-front/src/modules/object-record/spreadsheet-import/__tests__/useSpreadsheetRecordImport.test.tsx @@ -92,7 +92,7 @@ describe('useSpreadsheetCompanyImport', () => { it('should work as expected', async () => { const { result } = renderHook( () => { - const spreadsheetImport = useRecoilValue(spreadsheetImportState()); + const spreadsheetImport = useRecoilValue(spreadsheetImportState); const { openRecordSpreadsheetImport } = useSpreadsheetRecordImport( CoreObjectNameSingular.Company, ); diff --git a/packages/twenty-front/src/modules/prefetch/components/PrefetchRunQueriesEffect.tsx b/packages/twenty-front/src/modules/prefetch/components/PrefetchRunQueriesEffect.tsx index 18a73506f9..0554b03880 100644 --- a/packages/twenty-front/src/modules/prefetch/components/PrefetchRunQueriesEffect.tsx +++ b/packages/twenty-front/src/modules/prefetch/components/PrefetchRunQueriesEffect.tsx @@ -1,6 +1,9 @@ import { useEffect } from 'react'; import { useQuery } from '@apollo/client'; +import { useRecoilValue } from 'recoil'; +import { currentUserState } from '@/auth/states/currentUserState'; +import { EMPTY_QUERY } from '@/object-metadata/hooks/useObjectMetadataItem'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { useGenerateFindManyRecordsForMultipleMetadataItemsQuery } from '@/object-record/hooks/useGenerateFindManyRecordsForMultipleMetadataItemsQuery'; import { MultiObjectRecordQueryResult } from '@/object-record/relation-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray'; @@ -9,6 +12,8 @@ import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; import { isDefined } from '~/utils/isDefined'; export const PrefetchRunQueriesEffect = () => { + const currentUser = useRecoilValue(currentUserState); + const { objectMetadataItem: objectMetadataItemView, upsertRecordsInCache: upsertViewsInCache, @@ -27,16 +32,18 @@ export const PrefetchRunQueriesEffect = () => { const prefetchFindManyQuery = useGenerateFindManyRecordsForMultipleMetadataItemsQuery({ - objectMetadataItems: [objectMetadataItemView, objectMetadataItemFavorite], + targetObjectMetadataItems: [ + objectMetadataItemView, + objectMetadataItemFavorite, + ], depth: 2, }); - if (!isDefined(prefetchFindManyQuery)) { - throw new Error('Could not prefetch recrds'); - } - const { data } = useQuery( - prefetchFindManyQuery, + prefetchFindManyQuery ?? EMPTY_QUERY, + { + skip: !currentUser, + }, ); useEffect(() => { diff --git a/packages/twenty-front/src/modules/search/hooks/__tests__/useFilteredSearchEntityQuery.test.tsx b/packages/twenty-front/src/modules/search/hooks/__tests__/useFilteredSearchEntityQuery.test.tsx index ea46bac44b..57a93cdec6 100644 --- a/packages/twenty-front/src/modules/search/hooks/__tests__/useFilteredSearchEntityQuery.test.tsx +++ b/packages/twenty-front/src/modules/search/hooks/__tests__/useFilteredSearchEntityQuery.test.tsx @@ -67,7 +67,7 @@ describe('useFilteredSearchEntityQuery', () => { const { result } = renderHook( () => { const setCurrentWorkspaceMember = useSetRecoilState( - currentWorkspaceMemberState(), + currentWorkspaceMemberState, ); setCurrentWorkspaceMember({ id: '32219445-f587-4c40-b2b1-6d3205ed96da', @@ -76,7 +76,7 @@ describe('useFilteredSearchEntityQuery', () => { const mockObjectMetadataItems = getObjectMetadataItemsMock(); - const setMetadataItems = useSetRecoilState(objectMetadataItemsState()); + const setMetadataItems = useSetRecoilState(objectMetadataItemsState); setMetadataItems(mockObjectMetadataItems); diff --git a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsCalendarAccountsListCard.tsx b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsCalendarAccountsListCard.tsx index b157fb588f..5425976316 100644 --- a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsCalendarAccountsListCard.tsx +++ b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsCalendarAccountsListCard.tsx @@ -20,7 +20,7 @@ const StyledRowRightContainer = styled.div` `; export const SettingsAccountsCalendarAccountsListCard = () => { - const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState()); + const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); const navigate = useNavigate(); const { records: _accounts, loading } = useFindManyRecords({ diff --git a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsEmailsAccountsListCard.tsx b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsEmailsAccountsListCard.tsx index 7999f062b9..2fc6154f1e 100644 --- a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsEmailsAccountsListCard.tsx +++ b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsEmailsAccountsListCard.tsx @@ -20,7 +20,7 @@ const StyledRowRightContainer = styled.div` `; export const SettingsAccountsEmailsAccountsListCard = () => { - const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState()); + const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); const navigate = useNavigate(); const { records: accounts, loading: accountsLoading } = diff --git a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsEmailsBlocklistSection.tsx b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsEmailsBlocklistSection.tsx index 03e6a9e25b..28646b9d8c 100644 --- a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsEmailsBlocklistSection.tsx +++ b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsEmailsBlocklistSection.tsx @@ -12,7 +12,7 @@ import { H2Title } from '@/ui/display/typography/components/H2Title'; import { Section } from '@/ui/layout/section/components/Section'; export const SettingsAccountsEmailsBlocklistSection = () => { - const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState()); + const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); const { records: blocklist } = useFindManyRecords({ objectNameSingular: CoreObjectNameSingular.Blocklist, diff --git a/packages/twenty-front/src/modules/settings/components/SettingsNavigationDrawerItems.tsx b/packages/twenty-front/src/modules/settings/components/SettingsNavigationDrawerItems.tsx index 0c9aa2f19d..fb3ab5f1cc 100644 --- a/packages/twenty-front/src/modules/settings/components/SettingsNavigationDrawerItems.tsx +++ b/packages/twenty-front/src/modules/settings/components/SettingsNavigationDrawerItems.tsx @@ -37,7 +37,7 @@ export const SettingsNavigationDrawerItems = () => { }, [signOut, navigate]); const isCalendarEnabled = useIsFeatureEnabled('IS_CALENDAR_ENABLED'); - const billing = useRecoilValue(billingState()); + const billing = useRecoilValue(billingState); return ( <> diff --git a/packages/twenty-front/src/modules/settings/profile/components/ChangePassword.tsx b/packages/twenty-front/src/modules/settings/profile/components/ChangePassword.tsx index eb08cd0452..ee60971528 100644 --- a/packages/twenty-front/src/modules/settings/profile/components/ChangePassword.tsx +++ b/packages/twenty-front/src/modules/settings/profile/components/ChangePassword.tsx @@ -9,7 +9,7 @@ import { useEmailPasswordResetLinkMutation } from '~/generated/graphql'; export const ChangePassword = () => { const { enqueueSnackBar } = useSnackBar(); - const currentUser = useRecoilValue(currentUserState()); + const currentUser = useRecoilValue(currentUserState); const [emailPasswordResetLink] = useEmailPasswordResetLinkMutation(); diff --git a/packages/twenty-front/src/modules/settings/profile/components/DeleteAccount.tsx b/packages/twenty-front/src/modules/settings/profile/components/DeleteAccount.tsx index bd0de3f17a..d3e52ad09e 100644 --- a/packages/twenty-front/src/modules/settings/profile/components/DeleteAccount.tsx +++ b/packages/twenty-front/src/modules/settings/profile/components/DeleteAccount.tsx @@ -15,7 +15,7 @@ export const DeleteAccount = () => { useState(false); const [deleteUserAccount] = useDeleteUserAccountMutation(); - const currentUser = useRecoilValue(currentUserState()); + const currentUser = useRecoilValue(currentUserState); const userEmail = currentUser?.email; const { signOut } = useAuth(); const navigate = useNavigate(); diff --git a/packages/twenty-front/src/modules/settings/profile/components/DeleteWorkspace.tsx b/packages/twenty-front/src/modules/settings/profile/components/DeleteWorkspace.tsx index b0fcdf1215..4264bd9282 100644 --- a/packages/twenty-front/src/modules/settings/profile/components/DeleteWorkspace.tsx +++ b/packages/twenty-front/src/modules/settings/profile/components/DeleteWorkspace.tsx @@ -17,7 +17,7 @@ export const DeleteWorkspace = () => { useState(false); const [deleteCurrentWorkspace] = useDeleteCurrentWorkspaceMutation(); - const currentUser = useRecoilValue(currentUserState()); + const currentUser = useRecoilValue(currentUserState); const userEmail = currentUser?.email; const { signOut } = useAuth(); const navigate = useNavigate(); diff --git a/packages/twenty-front/src/modules/settings/profile/components/EmailField.tsx b/packages/twenty-front/src/modules/settings/profile/components/EmailField.tsx index 80494ebbbe..02c1e87341 100644 --- a/packages/twenty-front/src/modules/settings/profile/components/EmailField.tsx +++ b/packages/twenty-front/src/modules/settings/profile/components/EmailField.tsx @@ -4,7 +4,7 @@ import { currentUserState } from '@/auth/states/currentUserState'; import { TextInput } from '@/ui/input/components/TextInput'; export const EmailField = () => { - const currentUser = useRecoilValue(currentUserState()); + const currentUser = useRecoilValue(currentUserState); return ( { - const currentUser = useRecoilValue(currentUserState()); + const currentUser = useRecoilValue(currentUserState); const [currentWorkspaceMember, setCurrentWorkspaceMember] = useRecoilState( - currentWorkspaceMemberState(), + currentWorkspaceMemberState, ); const [firstName, setFirstName] = useState( diff --git a/packages/twenty-front/src/modules/settings/profile/components/ProfilePictureUploader.tsx b/packages/twenty-front/src/modules/settings/profile/components/ProfilePictureUploader.tsx index 8da64b0f1a..4a65b1ff3a 100644 --- a/packages/twenty-front/src/modules/settings/profile/components/ProfilePictureUploader.tsx +++ b/packages/twenty-front/src/modules/settings/profile/components/ProfilePictureUploader.tsx @@ -15,7 +15,7 @@ export const ProfilePictureUploader = () => { useUploadProfilePictureMutation(); const [currentWorkspaceMember, setCurrentWorkspaceMember] = useRecoilState( - currentWorkspaceMemberState(), + currentWorkspaceMemberState, ); const [uploadController, setUploadController] = diff --git a/packages/twenty-front/src/modules/settings/workspace/components/NameField.tsx b/packages/twenty-front/src/modules/settings/workspace/components/NameField.tsx index 62dc739305..b72e76b4e8 100644 --- a/packages/twenty-front/src/modules/settings/workspace/components/NameField.tsx +++ b/packages/twenty-front/src/modules/settings/workspace/components/NameField.tsx @@ -27,7 +27,7 @@ export const NameField = ({ autoSave = true, onNameUpdate, }: NameFieldProps) => { - const currentWorkspace = useRecoilValue(currentWorkspaceState()); + const currentWorkspace = useRecoilValue(currentWorkspaceState); const [displayName, setDisplayName] = useState( currentWorkspace?.displayName ?? '', diff --git a/packages/twenty-front/src/modules/settings/workspace/components/ToggleImpersonate.tsx b/packages/twenty-front/src/modules/settings/workspace/components/ToggleImpersonate.tsx index ebb909ede8..453cfc21dd 100644 --- a/packages/twenty-front/src/modules/settings/workspace/components/ToggleImpersonate.tsx +++ b/packages/twenty-front/src/modules/settings/workspace/components/ToggleImpersonate.tsx @@ -9,7 +9,7 @@ export const ToggleImpersonate = () => { const { enqueueSnackBar } = useSnackBar(); const [currentWorkspace, setCurrentWorkspace] = useRecoilState( - currentWorkspaceState(), + currentWorkspaceState, ); const [updateWorkspace] = useUpdateWorkspaceMutation(); diff --git a/packages/twenty-front/src/modules/settings/workspace/components/WorkspaceLogoUploader.tsx b/packages/twenty-front/src/modules/settings/workspace/components/WorkspaceLogoUploader.tsx index ba410823af..009c32d54f 100644 --- a/packages/twenty-front/src/modules/settings/workspace/components/WorkspaceLogoUploader.tsx +++ b/packages/twenty-front/src/modules/settings/workspace/components/WorkspaceLogoUploader.tsx @@ -13,7 +13,7 @@ export const WorkspaceLogoUploader = () => { const [uploadLogo] = useUploadWorkspaceLogoMutation(); const [updateWorkspce] = useUpdateWorkspaceMutation(); const [currentWorkspace, setCurrentWorkspace] = useRecoilState( - currentWorkspaceState(), + currentWorkspaceState, ); const onUpload = async (file: File) => { 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 941647853c..447ca98aa4 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 @@ -24,6 +24,7 @@ export const SignInBackgroundMockContainer = () => { {}} optionsDropdownButton={ { setViewObjectMetadataId?.(objectMetadataItem.id); @@ -85,9 +88,9 @@ export const SignInBackgroundMockContainerEffect = ({ useEffect(() => { setOnEntityCountChange( - () => (entityCount: number) => setEntityCountInCurrentView(entityCount), + () => (entityCount: number) => setRecordCountInCurrentView(entityCount), ); - }, [setEntityCountInCurrentView, setOnEntityCountChange]); + }, [setRecordCountInCurrentView, setOnEntityCountChange]); return <>; }; diff --git a/packages/twenty-front/src/modules/spreadsheet-import/hooks/__tests__/useSpreadsheetImport.test.tsx b/packages/twenty-front/src/modules/spreadsheet-import/hooks/__tests__/useSpreadsheetImport.test.tsx index a294806634..c54a5498a5 100644 --- a/packages/twenty-front/src/modules/spreadsheet-import/hooks/__tests__/useSpreadsheetImport.test.tsx +++ b/packages/twenty-front/src/modules/spreadsheet-import/hooks/__tests__/useSpreadsheetImport.test.tsx @@ -44,7 +44,7 @@ describe('useSpreadsheetImport', () => { const { result } = renderHook( () => ({ useSpreadsheetImport: useSpreadsheetImport(), - spreadsheetImportState: useRecoilState(spreadsheetImportState())[0], + spreadsheetImportState: useRecoilState(spreadsheetImportState)[0], }), { wrapper: Wrapper, diff --git a/packages/twenty-front/src/modules/spreadsheet-import/hooks/useSpreadsheetImport.ts b/packages/twenty-front/src/modules/spreadsheet-import/hooks/useSpreadsheetImport.ts index 160ba49caa..0259faad60 100644 --- a/packages/twenty-front/src/modules/spreadsheet-import/hooks/useSpreadsheetImport.ts +++ b/packages/twenty-front/src/modules/spreadsheet-import/hooks/useSpreadsheetImport.ts @@ -4,7 +4,7 @@ import { spreadsheetImportState } from '@/spreadsheet-import/states/spreadsheetI import { SpreadsheetOptions } from '@/spreadsheet-import/types'; export const useSpreadsheetImport = () => { - const setSpreadSheetImport = useSetRecoilState(spreadsheetImportState()); + const setSpreadSheetImport = useSetRecoilState(spreadsheetImportState); const openSpreadsheetImport = ( options: Omit, 'isOpen' | 'onClose'>, diff --git a/packages/twenty-front/src/modules/spreadsheet-import/provider/components/SpreadsheetImportProvider.tsx b/packages/twenty-front/src/modules/spreadsheet-import/provider/components/SpreadsheetImportProvider.tsx index 3bec782699..5c5b7a1377 100644 --- a/packages/twenty-front/src/modules/spreadsheet-import/provider/components/SpreadsheetImportProvider.tsx +++ b/packages/twenty-front/src/modules/spreadsheet-import/provider/components/SpreadsheetImportProvider.tsx @@ -11,7 +11,7 @@ export const SpreadsheetImportProvider = ( props: SpreadsheetImportProviderProps, ) => { const [spreadsheetImport, setSpreadsheetImport] = useRecoilState( - spreadsheetImportState(), + spreadsheetImportState, ); const handleClose = () => { diff --git a/packages/twenty-front/src/modules/support/components/SupportChat.tsx b/packages/twenty-front/src/modules/support/components/SupportChat.tsx index ab15532b4a..4a41c61688 100644 --- a/packages/twenty-front/src/modules/support/components/SupportChat.tsx +++ b/packages/twenty-front/src/modules/support/components/SupportChat.tsx @@ -33,9 +33,9 @@ const insertScript = ({ }; export const SupportChat = () => { - const currentUser = useRecoilValue(currentUserState()); - const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState()); - const supportChat = useRecoilValue(supportChatState()); + const currentUser = useRecoilValue(currentUserState); + const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); + const supportChat = useRecoilValue(supportChatState); const [isFrontChatLoaded, setIsFrontChatLoaded] = useState(false); const configureFront = useCallback( diff --git a/packages/twenty-front/src/modules/ui/display/icon/components/IconsProvider.tsx b/packages/twenty-front/src/modules/ui/display/icon/components/IconsProvider.tsx index 16112d90fc..918d7d32d6 100644 --- a/packages/twenty-front/src/modules/ui/display/icon/components/IconsProvider.tsx +++ b/packages/twenty-front/src/modules/ui/display/icon/components/IconsProvider.tsx @@ -8,7 +8,7 @@ type IconsProviderProps = { }; export const IconsProvider = ({ children }: IconsProviderProps) => { - const setIcons = useSetRecoilState(iconsState()); + const setIcons = useSetRecoilState(iconsState); useEffect(() => { import('../constants/index').then((lazyLoadedIcons) => { diff --git a/packages/twenty-front/src/modules/ui/display/icon/hooks/useIcons.ts b/packages/twenty-front/src/modules/ui/display/icon/hooks/useIcons.ts index e3619b770d..4efd71e7f6 100644 --- a/packages/twenty-front/src/modules/ui/display/icon/hooks/useIcons.ts +++ b/packages/twenty-front/src/modules/ui/display/icon/hooks/useIcons.ts @@ -4,7 +4,7 @@ import { Icon123 } from '@/ui/display/icon'; import { iconsState } from '@/ui/display/icon/states/iconsState'; export const useIcons = () => { - const icons = useRecoilValue(iconsState()); + const icons = useRecoilValue(iconsState); const defaultIcon = Icon123; const getIcons = () => { diff --git a/packages/twenty-front/src/modules/ui/input/hooks/useIconPicker.ts b/packages/twenty-front/src/modules/ui/input/hooks/useIconPicker.ts index 998dd0dee4..141431c715 100644 --- a/packages/twenty-front/src/modules/ui/input/hooks/useIconPicker.ts +++ b/packages/twenty-front/src/modules/ui/input/hooks/useIconPicker.ts @@ -3,7 +3,7 @@ import { useRecoilState } from 'recoil'; import { iconPickerState } from '../states/iconPickerState'; export const useIconPicker = () => { - const [iconPicker, setIconPicker] = useRecoilState(iconPickerState()); + const [iconPicker, setIconPicker] = useRecoilState(iconPickerState); return { Icon: iconPicker.Icon, diff --git a/packages/twenty-front/src/modules/ui/layout/dropdown/components/DropdownMenuInput.tsx b/packages/twenty-front/src/modules/ui/layout/dropdown/components/DropdownMenuInput.tsx index 913534a8d7..be3f42d2e0 100644 --- a/packages/twenty-front/src/modules/ui/layout/dropdown/components/DropdownMenuInput.tsx +++ b/packages/twenty-front/src/modules/ui/layout/dropdown/components/DropdownMenuInput.tsx @@ -30,13 +30,14 @@ const StyledInputContainer = styled.div` export const DropdownMenuInput = forwardRef< HTMLInputElement, InputHTMLAttributes ->(({ autoFocus, defaultValue, placeholder }, ref) => { +>(({ autoFocus, defaultValue, placeholder, onChange }, ref) => { return ( diff --git a/packages/twenty-front/src/modules/ui/layout/dropdown/hooks/__tests__/useInternalHotkeyScopeManagement.test.tsx b/packages/twenty-front/src/modules/ui/layout/dropdown/hooks/__tests__/useInternalHotkeyScopeManagement.test.tsx index 9bdb17bae4..3bfd0f3a35 100644 --- a/packages/twenty-front/src/modules/ui/layout/dropdown/hooks/__tests__/useInternalHotkeyScopeManagement.test.tsx +++ b/packages/twenty-front/src/modules/ui/layout/dropdown/hooks/__tests__/useInternalHotkeyScopeManagement.test.tsx @@ -27,7 +27,7 @@ describe('useInternalHotkeyScopeManagement', () => { const { dropdownHotkeyScopeState } = useDropdownStates({ dropdownScopeId, }); - const dropdownHotkeyScope = useRecoilValue(dropdownHotkeyScopeState()); + const dropdownHotkeyScope = useRecoilValue(dropdownHotkeyScopeState); return { dropdownHotkeyScope }; }, { diff --git a/packages/twenty-front/src/modules/ui/layout/dropdown/hooks/useDropdown.ts b/packages/twenty-front/src/modules/ui/layout/dropdown/hooks/useDropdown.ts index 0a671a40e9..f3b196f418 100644 --- a/packages/twenty-front/src/modules/ui/layout/dropdown/hooks/useDropdown.ts +++ b/packages/twenty-front/src/modules/ui/layout/dropdown/hooks/useDropdown.ts @@ -20,14 +20,12 @@ export const useDropdown = (dropdownId?: string) => { goBackToPreviousHotkeyScope, } = usePreviousHotkeyScope(); - const [dropdownHotkeyScope] = useRecoilState(dropdownHotkeyScopeState()); + const [dropdownHotkeyScope] = useRecoilState(dropdownHotkeyScopeState); - const [dropdownWidth, setDropdownWidth] = - useRecoilState(dropdownWidthState()); + const [dropdownWidth, setDropdownWidth] = useRecoilState(dropdownWidthState); - const [isDropdownOpen, setIsDropdownOpen] = useRecoilState( - isDropdownOpenState(), - ); + const [isDropdownOpen, setIsDropdownOpen] = + useRecoilState(isDropdownOpenState); const closeDropdown = () => { goBackToPreviousHotkeyScope(); diff --git a/packages/twenty-front/src/modules/ui/layout/dropdown/hooks/useInternalHotkeyScopeManagement.ts b/packages/twenty-front/src/modules/ui/layout/dropdown/hooks/useInternalHotkeyScopeManagement.ts index 74f29b508d..9ea9db7973 100644 --- a/packages/twenty-front/src/modules/ui/layout/dropdown/hooks/useInternalHotkeyScopeManagement.ts +++ b/packages/twenty-front/src/modules/ui/layout/dropdown/hooks/useInternalHotkeyScopeManagement.ts @@ -15,7 +15,7 @@ export const useInternalHotkeyScopeManagement = ({ const { dropdownHotkeyScopeState } = useDropdownStates({ dropdownScopeId }); const [dropdownHotkeyScope, setDropdownHotkeyScope] = useRecoilState( - dropdownHotkeyScopeState(), + dropdownHotkeyScopeState, ); useEffect(() => { diff --git a/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawer.tsx b/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawer.tsx index 1ab9143e98..a73e674dfd 100644 --- a/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawer.tsx +++ b/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawer.tsx @@ -42,12 +42,12 @@ const StyledRightDrawer = styled.div` export const RightDrawer = () => { const [isRightDrawerOpen, setIsRightDrawerOpen] = useRecoilState( - isRightDrawerOpenState(), + isRightDrawerOpenState, ); - const isRightDrawerExpanded = useRecoilValue(isRightDrawerExpandedState()); + const isRightDrawerExpanded = useRecoilValue(isRightDrawerExpandedState); - const rightDrawerPage = useRecoilValue(rightDrawerPageState()); + const rightDrawerPage = useRecoilValue(rightDrawerPageState); const { closeRightDrawer } = useRightDrawer(); @@ -63,11 +63,11 @@ export const RightDrawer = () => { ({ snapshot, set }) => (event) => { const isRightDrawerOpen = snapshot - .getLoadable(isRightDrawerOpenState()) + .getLoadable(isRightDrawerOpenState) .getValue(); if (isRightDrawerOpen) { - set(rightDrawerCloseEventState(), event); + set(rightDrawerCloseEventState, event); closeRightDrawer(); } }, diff --git a/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerRouter.tsx b/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerRouter.tsx index 7eced58ff4..a0eb83b409 100644 --- a/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerRouter.tsx +++ b/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerRouter.tsx @@ -47,7 +47,7 @@ const RIGHT_DRAWER_PAGES_CONFIG = { }; export const RightDrawerRouter = () => { - const [rightDrawerPage] = useRecoilState(rightDrawerPageState()); + const [rightDrawerPage] = useRecoilState(rightDrawerPageState); const { topBar = null, page = null } = rightDrawerPage ? RIGHT_DRAWER_PAGES_CONFIG[rightDrawerPage] diff --git a/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerTopBarExpandButton.tsx b/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerTopBarExpandButton.tsx index d22700e732..701c69edfa 100644 --- a/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerTopBarExpandButton.tsx +++ b/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerTopBarExpandButton.tsx @@ -10,7 +10,7 @@ import { isRightDrawerExpandedState } from '../states/isRightDrawerExpandedState export const RightDrawerTopBarExpandButton = () => { const [isRightDrawerExpanded, setIsRightDrawerExpanded] = useRecoilState( - isRightDrawerExpandedState(), + isRightDrawerExpandedState, ); const handleButtonClick = () => { diff --git a/packages/twenty-front/src/modules/ui/layout/right-drawer/hooks/__tests__/useRightDrawer.test.tsx b/packages/twenty-front/src/modules/ui/layout/right-drawer/hooks/__tests__/useRightDrawer.test.tsx index 727f6a7ca9..843de0118c 100644 --- a/packages/twenty-front/src/modules/ui/layout/right-drawer/hooks/__tests__/useRightDrawer.test.tsx +++ b/packages/twenty-front/src/modules/ui/layout/right-drawer/hooks/__tests__/useRightDrawer.test.tsx @@ -12,12 +12,10 @@ describe('useRightDrawer', () => { it('Should test the default behavior of useRightDrawer and change the states as the function calls', async () => { const useCombinedHooks = () => { const { openRightDrawer, closeRightDrawer } = useRightDrawer(); - const isRightDrawerOpen = useRecoilValue(isRightDrawerOpenState()); - const isRightDrawerExpanded = useRecoilValue( - isRightDrawerExpandedState(), - ); + const isRightDrawerOpen = useRecoilValue(isRightDrawerOpenState); + const isRightDrawerExpanded = useRecoilValue(isRightDrawerExpandedState); - const rightDrawerPage = useRecoilValue(rightDrawerPageState()); + const rightDrawerPage = useRecoilValue(rightDrawerPageState); return { openRightDrawer, diff --git a/packages/twenty-front/src/modules/ui/layout/right-drawer/hooks/useRightDrawer.ts b/packages/twenty-front/src/modules/ui/layout/right-drawer/hooks/useRightDrawer.ts index fe04ac5a1b..5cf5cc6214 100644 --- a/packages/twenty-front/src/modules/ui/layout/right-drawer/hooks/useRightDrawer.ts +++ b/packages/twenty-front/src/modules/ui/layout/right-drawer/hooks/useRightDrawer.ts @@ -8,16 +8,16 @@ import { rightDrawerPageState } from '../states/rightDrawerPageState'; import { RightDrawerPages } from '../types/RightDrawerPages'; export const useRightDrawer = () => { - const [isRightDrawerOpen] = useRecoilState(isRightDrawerOpenState()); + const [isRightDrawerOpen] = useRecoilState(isRightDrawerOpenState); - const [rightDrawerPage] = useRecoilState(rightDrawerPageState()); + const [rightDrawerPage] = useRecoilState(rightDrawerPageState); const openRightDrawer = useRecoilCallback( ({ set }) => (rightDrawerPage: RightDrawerPages) => { - set(rightDrawerPageState(), rightDrawerPage); - set(isRightDrawerExpandedState(), false); - set(isRightDrawerOpenState(), true); + set(rightDrawerPageState, rightDrawerPage); + set(isRightDrawerExpandedState, false); + set(isRightDrawerOpenState, true); }, [], ); @@ -25,8 +25,8 @@ export const useRightDrawer = () => { const closeRightDrawer = useRecoilCallback( ({ set }) => () => { - set(isRightDrawerExpandedState(), false); - set(isRightDrawerOpenState(), false); + set(isRightDrawerExpandedState, false); + set(isRightDrawerOpenState, false); }, [], ); @@ -35,7 +35,7 @@ export const useRightDrawer = () => { ({ snapshot }) => (event: MouseEvent | TouchEvent) => { const rightDrawerCloseEvent = snapshot - .getLoadable(rightDrawerCloseEventState()) + .getLoadable(rightDrawerCloseEventState) .getValue(); const isSameEvent = diff --git a/packages/twenty-front/src/modules/ui/layout/selectable-list/hooks/__tests__/useSelectableList.test.ts b/packages/twenty-front/src/modules/ui/layout/selectable-list/hooks/__tests__/useSelectableList.test.ts index a7bbe398dd..930ea10ad5 100644 --- a/packages/twenty-front/src/modules/ui/layout/selectable-list/hooks/__tests__/useSelectableList.test.ts +++ b/packages/twenty-front/src/modules/ui/layout/selectable-list/hooks/__tests__/useSelectableList.test.ts @@ -21,7 +21,7 @@ describe('useSelectableList', () => { selectableListScopeId, }); - const selectableItemIds = useRecoilValue(selectableItemIdsState()); + const selectableItemIds = useRecoilValue(selectableItemIdsState); return { setSelectableItemIds, @@ -51,9 +51,8 @@ describe('useSelectableList', () => { selectableListScopeId, }); - const [selectedItemId, setSelectedItemId] = useRecoilState( - selectedItemIdState(), - ); + const [selectedItemId, setSelectedItemId] = + useRecoilState(selectedItemIdState); return { resetSelectedItem, diff --git a/packages/twenty-front/src/modules/ui/layout/selectable-list/hooks/internal/useSelectableListHotKeys.tsx b/packages/twenty-front/src/modules/ui/layout/selectable-list/hooks/internal/useSelectableListHotKeys.tsx index 91340db8d0..9d668f3e0a 100644 --- a/packages/twenty-front/src/modules/ui/layout/selectable-list/hooks/internal/useSelectableListHotKeys.tsx +++ b/packages/twenty-front/src/modules/ui/layout/selectable-list/hooks/internal/useSelectableListHotKeys.tsx @@ -40,13 +40,10 @@ export const useSelectableListHotKeys = ( const handleSelect = useRecoilCallback( ({ snapshot, set }) => (direction: Direction) => { - const selectedItemId = getSnapshotValue( - snapshot, - selectedItemIdState(), - ); + const selectedItemId = getSnapshotValue(snapshot, selectedItemIdState); const selectableItemIds = getSnapshotValue( snapshot, - selectableItemIdsState(), + selectableItemIdsState, ); const currentPosition = findPosition(selectableItemIds, selectedItemId); @@ -107,7 +104,7 @@ export const useSelectableListHotKeys = ( if (selectedItemId !== nextId) { if (isNonEmptyString(nextId)) { set(isSelectedItemIdSelector(nextId), true); - set(selectedItemIdState(), nextId); + set(selectedItemIdState, nextId); } if (isNonEmptyString(selectedItemId)) { @@ -138,11 +135,11 @@ export const useSelectableListHotKeys = ( () => { const selectedItemId = getSnapshotValue( snapshot, - selectedItemIdState(), + selectedItemIdState, ); const onEnter = getSnapshotValue( snapshot, - selectableListOnEnterState(), + selectableListOnEnterState, ); if (isNonEmptyString(selectedItemId)) { diff --git a/packages/twenty-front/src/modules/ui/layout/selectable-list/hooks/useSelectableList.ts b/packages/twenty-front/src/modules/ui/layout/selectable-list/hooks/useSelectableList.ts index 7d33e15ac1..37098d3c90 100644 --- a/packages/twenty-front/src/modules/ui/layout/selectable-list/hooks/useSelectableList.ts +++ b/packages/twenty-front/src/modules/ui/layout/selectable-list/hooks/useSelectableList.ts @@ -13,12 +13,12 @@ export const useSelectableList = (selectableListId?: string) => { selectableListScopeId: selectableListId, }); - const setSelectableItemIds = useSetRecoilState(selectableItemIdsState()); + const setSelectableItemIds = useSetRecoilState(selectableItemIdsState); const setSelectableListOnEnter = useSetRecoilState( - selectableListOnEnterState(), + selectableListOnEnterState, ); - const resetSelectedItemIdState = useResetRecoilState(selectedItemIdState()); + const resetSelectedItemIdState = useResetRecoilState(selectedItemIdState); const resetSelectedItem = () => { resetSelectedItemIdState(); diff --git a/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageMoreButton.tsx b/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageMoreButton.tsx index 3b75efe626..fee1454b6f 100644 --- a/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageMoreButton.tsx +++ b/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageMoreButton.tsx @@ -26,7 +26,7 @@ export const ShowPageMoreButton = ({ objectNameSingular: string; }) => { const { closeDropdown, toggleDropdown } = useDropdown('more-show-page'); - const navigationMemorizedUrl = useRecoilValue(navigationMemorizedUrlState()); + const navigationMemorizedUrl = useRecoilValue(navigationMemorizedUrlState); const navigate = useNavigate(); const { deleteOneRecord } = useDeleteOneRecord({ diff --git a/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageRightContainer.tsx b/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageRightContainer.tsx index f8d4b9deef..390e5e9e10 100644 --- a/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageRightContainer.tsx +++ b/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageRightContainer.tsx @@ -61,8 +61,8 @@ export const ShowPageRightContainer = ({ notes, emails, }: ShowPageRightContainerProps) => { - const { getActiveTabIdState } = useTabList(TAB_LIST_COMPONENT_ID); - const activeTabId = useRecoilValue(getActiveTabIdState()); + const { activeTabIdState } = useTabList(TAB_LIST_COMPONENT_ID); + const activeTabId = useRecoilValue(activeTabIdState); const shouldDisplayCalendarTab = useIsFeatureEnabled('IS_CALENDAR_ENABLED'); const shouldDisplayEmailsTab = diff --git a/packages/twenty-front/src/modules/ui/layout/tab/components/TabList.tsx b/packages/twenty-front/src/modules/ui/layout/tab/components/TabList.tsx index 8554be46b8..ce1f2a9420 100644 --- a/packages/twenty-front/src/modules/ui/layout/tab/components/TabList.tsx +++ b/packages/twenty-front/src/modules/ui/layout/tab/components/TabList.tsx @@ -36,9 +36,9 @@ const StyledContainer = styled.div` export const TabList = ({ tabs, tabListId }: TabListProps) => { const initialActiveTabId = tabs[0].id; - const { getActiveTabIdState, setActiveTabId } = useTabList(tabListId); + const { activeTabIdState, setActiveTabId } = useTabList(tabListId); - const activeTabId = useRecoilValue(getActiveTabIdState()); + const activeTabId = useRecoilValue(activeTabIdState); React.useEffect(() => { setActiveTabId(initialActiveTabId); diff --git a/packages/twenty-front/src/modules/ui/layout/tab/hooks/__tests__/useTabList.test.tsx b/packages/twenty-front/src/modules/ui/layout/tab/hooks/__tests__/useTabList.test.tsx index 986e243bfa..83e30532fc 100644 --- a/packages/twenty-front/src/modules/ui/layout/tab/hooks/__tests__/useTabList.test.tsx +++ b/packages/twenty-front/src/modules/ui/layout/tab/hooks/__tests__/useTabList.test.tsx @@ -8,12 +8,11 @@ describe('useTabList', () => { it('Should update the activeTabId state', async () => { const { result } = renderHook( () => { - const { getActiveTabIdState, setActiveTabId } = + const { activeTabIdState, setActiveTabId } = useTabList('TEST_TAB_LIST_ID'); - const activeTabId = useRecoilValue(getActiveTabIdState()); + const activeTabId = useRecoilValue(activeTabIdState); return { - getActiveTabIdState: getActiveTabIdState, activeTabId, setActiveTabId: setActiveTabId, }; @@ -22,7 +21,6 @@ describe('useTabList', () => { wrapper: RecoilRoot, }, ); - expect(result.current.getActiveTabIdState).toBeInstanceOf(Function); expect(result.current.setActiveTabId).toBeInstanceOf(Function); expect(result.current.activeTabId).toBeNull(); diff --git a/packages/twenty-front/src/modules/ui/layout/tab/hooks/internal/useTabListStates.ts b/packages/twenty-front/src/modules/ui/layout/tab/hooks/internal/useTabListStates.ts index 6915852548..2d33932be5 100644 --- a/packages/twenty-front/src/modules/ui/layout/tab/hooks/internal/useTabListStates.ts +++ b/packages/twenty-front/src/modules/ui/layout/tab/hooks/internal/useTabListStates.ts @@ -15,9 +15,6 @@ export const useTabListStates = ({ tabListScopeId }: useTabListStatesProps) => { return { scopeId, - getActiveTabIdState: extractComponentState( - activeTabIdComponentState, - scopeId, - ), + activeTabIdState: extractComponentState(activeTabIdComponentState, scopeId), }; }; diff --git a/packages/twenty-front/src/modules/ui/layout/tab/hooks/useTabList.ts b/packages/twenty-front/src/modules/ui/layout/tab/hooks/useTabList.ts index c02624ada4..9925dec4c6 100644 --- a/packages/twenty-front/src/modules/ui/layout/tab/hooks/useTabList.ts +++ b/packages/twenty-front/src/modules/ui/layout/tab/hooks/useTabList.ts @@ -3,14 +3,14 @@ import { useSetRecoilState } from 'recoil'; import { useTabListStates } from '@/ui/layout/tab/hooks/internal/useTabListStates'; export const useTabList = (tabListId?: string) => { - const { getActiveTabIdState } = useTabListStates({ + const { activeTabIdState } = useTabListStates({ tabListScopeId: `${tabListId}-scope`, }); - const setActiveTabId = useSetRecoilState(getActiveTabIdState()); + const setActiveTabId = useSetRecoilState(activeTabIdState); return { - getActiveTabIdState, + activeTabIdState, setActiveTabId, }; }; diff --git a/packages/twenty-front/src/modules/ui/navigation/action-bar/components/ActionBar.tsx b/packages/twenty-front/src/modules/ui/navigation/action-bar/components/ActionBar.tsx index 2c7b9db3b5..bf5c2586a0 100644 --- a/packages/twenty-front/src/modules/ui/navigation/action-bar/components/ActionBar.tsx +++ b/packages/twenty-front/src/modules/ui/navigation/action-bar/components/ActionBar.tsx @@ -28,8 +28,8 @@ const StyledContainerActionBar = styled.div` `; export const ActionBar = () => { - const contextMenuIsOpen = useRecoilValue(contextMenuIsOpenState()); - const actionBarEntries = useRecoilValue(actionBarEntriesState()); + const contextMenuIsOpen = useRecoilValue(contextMenuIsOpenState); + const actionBarEntries = useRecoilValue(actionBarEntriesState); const wrapperRef = useRef(null); if (contextMenuIsOpen) { diff --git a/packages/twenty-front/src/modules/ui/navigation/action-bar/components/__stories__/ActionBar.stories.tsx b/packages/twenty-front/src/modules/ui/navigation/action-bar/components/__stories__/ActionBar.stories.tsx index 460ee20487..24daaea855 100644 --- a/packages/twenty-front/src/modules/ui/navigation/action-bar/components/__stories__/ActionBar.stories.tsx +++ b/packages/twenty-front/src/modules/ui/navigation/action-bar/components/__stories__/ActionBar.stories.tsx @@ -9,7 +9,7 @@ import { actionBarOpenState } from '../../states/actionBarIsOpenState'; import { ActionBar } from '../ActionBar'; const FilledActionBar = () => { - const setActionBarOpenState = useSetRecoilState(actionBarOpenState()); + const setActionBarOpenState = useSetRecoilState(actionBarOpenState); setActionBarOpenState(true); return ; }; diff --git a/packages/twenty-front/src/modules/ui/navigation/context-menu/components/ContextMenu.tsx b/packages/twenty-front/src/modules/ui/navigation/context-menu/components/ContextMenu.tsx index 519c6bf87a..8a3a1cfd0e 100644 --- a/packages/twenty-front/src/modules/ui/navigation/context-menu/components/ContextMenu.tsx +++ b/packages/twenty-front/src/modules/ui/navigation/context-menu/components/ContextMenu.tsx @@ -37,10 +37,10 @@ const StyledContainerContextMenu = styled.div` `; export const ContextMenu = () => { - const contextMenuPosition = useRecoilValue(contextMenuPositionState()); - const contextMenuIsOpen = useRecoilValue(contextMenuIsOpenState()); - const contextMenuEntries = useRecoilValue(contextMenuEntriesState()); - const setContextMenuOpenState = useSetRecoilState(contextMenuIsOpenState()); + const contextMenuPosition = useRecoilValue(contextMenuPositionState); + const contextMenuIsOpen = useRecoilValue(contextMenuIsOpenState); + const contextMenuEntries = useRecoilValue(contextMenuEntriesState); + const setContextMenuOpenState = useSetRecoilState(contextMenuIsOpenState); const wrapperRef = useRef(null); useListenClickOutside({ diff --git a/packages/twenty-front/src/modules/ui/navigation/context-menu/components/__stories__/ContextMenu.stories.tsx b/packages/twenty-front/src/modules/ui/navigation/context-menu/components/__stories__/ContextMenu.stories.tsx index d0a5f4a798..ee9eddd2f8 100644 --- a/packages/twenty-front/src/modules/ui/navigation/context-menu/components/__stories__/ContextMenu.stories.tsx +++ b/packages/twenty-front/src/modules/ui/navigation/context-menu/components/__stories__/ContextMenu.stories.tsx @@ -10,12 +10,12 @@ import { contextMenuPositionState } from '../../states/contextMenuPositionState' import { ContextMenu } from '../ContextMenu'; const FilledContextMenu = () => { - const setContextMenuPosition = useSetRecoilState(contextMenuPositionState()); + const setContextMenuPosition = useSetRecoilState(contextMenuPositionState); setContextMenuPosition({ x: 100, y: 10, }); - const setContextMenuOpenState = useSetRecoilState(contextMenuIsOpenState()); + const setContextMenuOpenState = useSetRecoilState(contextMenuIsOpenState); setContextMenuOpenState(true); return ; }; diff --git a/packages/twenty-front/src/modules/ui/navigation/menu-item/components/MenuItemToggle.tsx b/packages/twenty-front/src/modules/ui/navigation/menu-item/components/MenuItemToggle.tsx index 70ed9dfb6a..99465e0ca8 100644 --- a/packages/twenty-front/src/modules/ui/navigation/menu-item/components/MenuItemToggle.tsx +++ b/packages/twenty-front/src/modules/ui/navigation/menu-item/components/MenuItemToggle.tsx @@ -24,12 +24,8 @@ export const MenuItemToggle = ({ onToggleChange, toggleSize, }: MenuItemToggleProps) => { - const handleOnClick = () => { - onToggleChange?.(!toggled); - }; - return ( - + theme.spacing(2)}; + opacity: 0; transition: opacity ${({ theme }) => theme.animation.duration.instant}s ease; } &:hover { & .hoverable-buttons { + opacity: 1; pointer-events: auto; position: static; } diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerBackButton.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerBackButton.tsx index 14f4cc3b6c..30f478a933 100644 --- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerBackButton.tsx +++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerBackButton.tsx @@ -37,7 +37,7 @@ export const NavigationDrawerBackButton = ({ }: NavigationDrawerBackButtonProps) => { const theme = useTheme(); const navigate = useNavigate(); - const navigationMemorizedUrl = useRecoilValue(navigationMemorizedUrlState()); + const navigationMemorizedUrl = useRecoilValue(navigationMemorizedUrlState); return ( diff --git a/packages/twenty-front/src/modules/ui/navigation/step-bar/hooks/__tests__/useStepBar.test.tsx b/packages/twenty-front/src/modules/ui/navigation/step-bar/hooks/__tests__/useStepBar.test.tsx index 5dfbd9c79a..9acd228fb9 100644 --- a/packages/twenty-front/src/modules/ui/navigation/step-bar/hooks/__tests__/useStepBar.test.tsx +++ b/packages/twenty-front/src/modules/ui/navigation/step-bar/hooks/__tests__/useStepBar.test.tsx @@ -11,7 +11,7 @@ const renderHooks = (initialStep: number) => { const { nextStep, prevStep, reset, setStep } = useStepBar({ initialStep, }); - const stepBarInternal = useRecoilValue(stepBarInternalState()); + const stepBarInternal = useRecoilValue(stepBarInternalState); return { nextStep, diff --git a/packages/twenty-front/src/modules/ui/navigation/step-bar/hooks/useStepBar.ts b/packages/twenty-front/src/modules/ui/navigation/step-bar/hooks/useStepBar.ts index f567d9c4da..0bc1449420 100644 --- a/packages/twenty-front/src/modules/ui/navigation/step-bar/hooks/useStepBar.ts +++ b/packages/twenty-front/src/modules/ui/navigation/step-bar/hooks/useStepBar.ts @@ -8,9 +8,8 @@ export type StepsOptions = { }; export const useStepBar = ({ initialStep }: StepsOptions) => { - const [stepBarInternal, setStepBarInternal] = useRecoilState( - stepBarInternalState(), - ); + const [stepBarInternal, setStepBarInternal] = + useRecoilState(stepBarInternalState); const nextStep = () => { setStepBarInternal((prevState) => ({ diff --git a/packages/twenty-front/src/modules/ui/theme/hooks/__tests__/useColorScheme.test.tsx b/packages/twenty-front/src/modules/ui/theme/hooks/__tests__/useColorScheme.test.tsx index 8412530612..f84692bfad 100644 --- a/packages/twenty-front/src/modules/ui/theme/hooks/__tests__/useColorScheme.test.tsx +++ b/packages/twenty-front/src/modules/ui/theme/hooks/__tests__/useColorScheme.test.tsx @@ -32,7 +32,7 @@ describe('useColorScheme', () => { const colorScheme = useColorScheme(); const setCurrentWorkspaceMember = useSetRecoilState( - currentWorkspaceMemberState(), + currentWorkspaceMemberState, ); setCurrentWorkspaceMember(workspaceMember); diff --git a/packages/twenty-front/src/modules/ui/theme/hooks/useColorScheme.ts b/packages/twenty-front/src/modules/ui/theme/hooks/useColorScheme.ts index 46cfa93571..e3b46c7adb 100644 --- a/packages/twenty-front/src/modules/ui/theme/hooks/useColorScheme.ts +++ b/packages/twenty-front/src/modules/ui/theme/hooks/useColorScheme.ts @@ -8,7 +8,7 @@ import { ColorScheme } from '@/workspace-member/types/WorkspaceMember'; export const useColorScheme = () => { const [currentWorkspaceMember, setCurrentWorkspaceMember] = useRecoilState( - currentWorkspaceMemberState(), + currentWorkspaceMemberState, ); const { updateOneRecord: updateOneWorkspaceMember } = useUpdateOneRecord({ diff --git a/packages/twenty-front/src/modules/ui/utilities/hotkey/hooks/usePreviousHotkeyScope.ts b/packages/twenty-front/src/modules/ui/utilities/hotkey/hooks/usePreviousHotkeyScope.ts index d3eb6d043e..d332b9df0e 100644 --- a/packages/twenty-front/src/modules/ui/utilities/hotkey/hooks/usePreviousHotkeyScope.ts +++ b/packages/twenty-front/src/modules/ui/utilities/hotkey/hooks/usePreviousHotkeyScope.ts @@ -13,7 +13,7 @@ export const usePreviousHotkeyScope = () => { ({ snapshot, set }) => () => { const previousHotkeyScope = snapshot - .getLoadable(previousHotkeyScopeState()) + .getLoadable(previousHotkeyScopeState) .getValue(); if (!previousHotkeyScope) { @@ -25,7 +25,7 @@ export const usePreviousHotkeyScope = () => { previousHotkeyScope.customScopes, ); - set(previousHotkeyScopeState(), null); + set(previousHotkeyScopeState, null); }, [setHotkeyScope], ); @@ -34,11 +34,11 @@ export const usePreviousHotkeyScope = () => { ({ snapshot, set }) => (scope: string, customScopes?: CustomHotkeyScopes) => { const currentHotkeyScope = snapshot - .getLoadable(currentHotkeyScopeState()) + .getLoadable(currentHotkeyScopeState) .getValue(); setHotkeyScope(scope, customScopes); - set(previousHotkeyScopeState(), currentHotkeyScope); + set(previousHotkeyScopeState, currentHotkeyScope); }, [setHotkeyScope], ); diff --git a/packages/twenty-front/src/modules/ui/utilities/hotkey/hooks/useScopedHotkeyCallback.ts b/packages/twenty-front/src/modules/ui/utilities/hotkey/hooks/useScopedHotkeyCallback.ts index 92ebc8b898..6e3d2d1020 100644 --- a/packages/twenty-front/src/modules/ui/utilities/hotkey/hooks/useScopedHotkeyCallback.ts +++ b/packages/twenty-front/src/modules/ui/utilities/hotkey/hooks/useScopedHotkeyCallback.ts @@ -24,7 +24,7 @@ export const useScopedHotkeyCallback = () => preventDefault?: boolean; }) => { const currentHotkeyScopes = snapshot - .getLoadable(internalHotkeysEnabledScopesState()) + .getLoadable(internalHotkeysEnabledScopesState) .getValue(); if (!currentHotkeyScopes.includes(scope)) { diff --git a/packages/twenty-front/src/modules/ui/utilities/hotkey/hooks/useScopedHotkeys.ts b/packages/twenty-front/src/modules/ui/utilities/hotkey/hooks/useScopedHotkeys.ts index b8059643c4..b8c7ff31da 100644 --- a/packages/twenty-front/src/modules/ui/utilities/hotkey/hooks/useScopedHotkeys.ts +++ b/packages/twenty-front/src/modules/ui/utilities/hotkey/hooks/useScopedHotkeys.ts @@ -22,8 +22,7 @@ export const useScopedHotkeys = ( preventDefault: true, }, ) => { - const [pendingHotkey, setPendingHotkey] = - useRecoilState(pendingHotkeyState()); + const [pendingHotkey, setPendingHotkey] = useRecoilState(pendingHotkeyState); const callScopedHotkeyCallback = useScopedHotkeyCallback(); diff --git a/packages/twenty-front/src/modules/ui/utilities/hotkey/hooks/useSequenceScopedHotkeys.ts b/packages/twenty-front/src/modules/ui/utilities/hotkey/hooks/useSequenceScopedHotkeys.ts index e2a4ead6b0..1ab3fe8e04 100644 --- a/packages/twenty-front/src/modules/ui/utilities/hotkey/hooks/useSequenceScopedHotkeys.ts +++ b/packages/twenty-front/src/modules/ui/utilities/hotkey/hooks/useSequenceScopedHotkeys.ts @@ -20,8 +20,7 @@ export const useSequenceHotkeys = ( }, deps: any[] = [], ) => { - const [pendingHotkey, setPendingHotkey] = - useRecoilState(pendingHotkeyState()); + const [pendingHotkey, setPendingHotkey] = useRecoilState(pendingHotkeyState); const callScopedHotkeyCallback = useScopedHotkeyCallback(); diff --git a/packages/twenty-front/src/modules/ui/utilities/hotkey/hooks/useSetHotkeyScope.ts b/packages/twenty-front/src/modules/ui/utilities/hotkey/hooks/useSetHotkeyScope.ts index aee1f213f2..ad890e08b4 100644 --- a/packages/twenty-front/src/modules/ui/utilities/hotkey/hooks/useSetHotkeyScope.ts +++ b/packages/twenty-front/src/modules/ui/utilities/hotkey/hooks/useSetHotkeyScope.ts @@ -26,7 +26,7 @@ export const useSetHotkeyScope = () => ({ snapshot, set }) => async (hotkeyScopeToSet: string, customScopes?: CustomHotkeyScopes) => { const currentHotkeyScope = snapshot - .getLoadable(currentHotkeyScopeState()) + .getLoadable(currentHotkeyScopeState) .getValue(); if (currentHotkeyScope.scope === hotkeyScopeToSet) { @@ -76,8 +76,8 @@ export const useSetHotkeyScope = () => } scopesToSet.push(newHotkeyScope.scope); - set(internalHotkeysEnabledScopesState(), scopesToSet); - set(currentHotkeyScopeState(), newHotkeyScope); + set(internalHotkeysEnabledScopesState, scopesToSet); + set(currentHotkeyScopeState, newHotkeyScope); }, [], ); diff --git a/packages/twenty-front/src/modules/ui/utilities/pointer-event/hooks/__tests__/useClickOutsideListener.test.tsx b/packages/twenty-front/src/modules/ui/utilities/pointer-event/hooks/__tests__/useClickOutsideListener.test.tsx index 5916fa12ad..04d2b88254 100644 --- a/packages/twenty-front/src/modules/ui/utilities/pointer-event/hooks/__tests__/useClickOutsideListener.test.tsx +++ b/packages/twenty-front/src/modules/ui/utilities/pointer-event/hooks/__tests__/useClickOutsideListener.test.tsx @@ -15,9 +15,7 @@ describe('useClickOutsideListener', () => { return { useClickOutside: useClickOutsideListener(componentId), - isActivated: useRecoilValue( - getClickOutsideListenerIsActivatedState(), - ), + isActivated: useRecoilValue(getClickOutsideListenerIsActivatedState), }; }, { diff --git a/packages/twenty-front/src/modules/ui/utilities/pointer-event/hooks/useClickOutsideListener.ts b/packages/twenty-front/src/modules/ui/utilities/pointer-event/hooks/useClickOutsideListener.ts index e1db02e483..a03da62510 100644 --- a/packages/twenty-front/src/modules/ui/utilities/pointer-event/hooks/useClickOutsideListener.ts +++ b/packages/twenty-front/src/modules/ui/utilities/pointer-event/hooks/useClickOutsideListener.ts @@ -34,7 +34,7 @@ export const useClickOutsideListener = (componentId: string) => { callback(event); const additionalCallbacks = snapshot - .getLoadable(getClickOutsideListenerCallbacksState()) + .getLoadable(getClickOutsideListenerCallbacksState) .getValue(); additionalCallbacks.forEach((additionalCallback) => { @@ -51,7 +51,7 @@ export const useClickOutsideListener = (componentId: string) => { const toggleClickOutsideListener = useRecoilCallback( ({ set }) => (activated: boolean) => { - set(getClickOutsideListenerIsActivatedState(), activated); + set(getClickOutsideListenerIsActivatedState, activated); }, [getClickOutsideListenerIsActivatedState], ); @@ -60,7 +60,7 @@ export const useClickOutsideListener = (componentId: string) => { ({ set, snapshot }) => ({ callbackFunction, callbackId }: ClickOutsideListenerCallback) => { const existingCallbacks = snapshot - .getLoadable(getClickOutsideListenerCallbacksState()) + .getLoadable(getClickOutsideListenerCallbacksState) .getValue(); const existingCallbackWithSameId = existingCallbacks.find( @@ -74,7 +74,7 @@ export const useClickOutsideListener = (componentId: string) => { }); set( - getClickOutsideListenerCallbacksState(), + getClickOutsideListenerCallbacksState, existingCallbacksWithNewCallback, ); } else { @@ -95,7 +95,7 @@ export const useClickOutsideListener = (componentId: string) => { }; set( - getClickOutsideListenerCallbacksState(), + getClickOutsideListenerCallbacksState, existingCallbacksWithOverwrittenCallback, ); } @@ -107,7 +107,7 @@ export const useClickOutsideListener = (componentId: string) => { ({ set, snapshot }) => ({ callbackId }: { callbackId: string }) => { const existingCallbacks = snapshot - .getLoadable(getClickOutsideListenerCallbacksState()) + .getLoadable(getClickOutsideListenerCallbacksState) .getValue(); const indexOfCallbackToUnsubscribe = existingCallbacks.findIndex( @@ -121,7 +121,7 @@ export const useClickOutsideListener = (componentId: string) => { existingCallbacks.toSpliced(indexOfCallbackToUnsubscribe, 1); set( - getClickOutsideListenerCallbacksState(), + getClickOutsideListenerCallbacksState, newCallbacksWithoutCallbackToUnsubscribe, ); } diff --git a/packages/twenty-front/src/modules/ui/utilities/pointer-event/hooks/useListenClickOutsideV2.ts b/packages/twenty-front/src/modules/ui/utilities/pointer-event/hooks/useListenClickOutsideV2.ts index e7f178e7d7..287d6b0f8e 100644 --- a/packages/twenty-front/src/modules/ui/utilities/pointer-event/hooks/useListenClickOutsideV2.ts +++ b/packages/twenty-front/src/modules/ui/utilities/pointer-event/hooks/useListenClickOutsideV2.ts @@ -32,7 +32,7 @@ export const useListenClickOutsideV2 = ({ ({ snapshot, set }) => (event: MouseEvent | TouchEvent) => { const clickOutsideListenerIsActivated = snapshot - .getLoadable(getClickOutsideListenerIsActivatedState()) + .getLoadable(getClickOutsideListenerIsActivatedState) .getValue(); const isListening = clickOutsideListenerIsActivated && enabled; @@ -47,7 +47,7 @@ export const useListenClickOutsideV2 = ({ .some((ref) => ref.current?.contains(event.target as Node)); set( - getClickOutsideListenerIsMouseDownInsideState(), + getClickOutsideListenerIsMouseDownInsideState, clickedOnAtLeastOneRef, ); } @@ -84,7 +84,7 @@ export const useListenClickOutsideV2 = ({ }); set( - getClickOutsideListenerIsMouseDownInsideState(), + getClickOutsideListenerIsMouseDownInsideState, clickedOnAtLeastOneRef, ); } @@ -102,7 +102,7 @@ export const useListenClickOutsideV2 = ({ ({ snapshot }) => (event: MouseEvent | TouchEvent) => { const isMouseDownInside = snapshot - .getLoadable(getClickOutsideListenerIsMouseDownInsideState()) + .getLoadable(getClickOutsideListenerIsMouseDownInsideState) .getValue(); if (mode === ClickOutsideMode.compareHTMLRef) { diff --git a/packages/twenty-front/src/modules/ui/utilities/recoil-scope/utils/getScopedFamilyStateDeprecated.ts b/packages/twenty-front/src/modules/ui/utilities/recoil-scope/utils/getScopedFamilyStateDeprecated.ts deleted file mode 100644 index 89dad50b94..0000000000 --- a/packages/twenty-front/src/modules/ui/utilities/recoil-scope/utils/getScopedFamilyStateDeprecated.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { RecoilState, SerializableParam } from 'recoil'; - -import { ComponentFamilyStateKey } from '@/ui/utilities/state/component-state/types/ComponentFamilyStateKey'; - -export const getScopedFamilyStateDeprecated = < - StateType, - FamilyKey extends SerializableParam, ->( - recoilState: ( - scopedFamilyKey: ComponentFamilyStateKey, - ) => RecoilState, - scopeId: string, - familyKey: FamilyKey, -) => { - return recoilState({ - scopeId, - familyKey: familyKey || ('' as FamilyKey), - }); -}; diff --git a/packages/twenty-front/src/modules/ui/utilities/recoil-scope/utils/getScopedSelectorDeprecated.ts b/packages/twenty-front/src/modules/ui/utilities/recoil-scope/utils/getScopedSelectorDeprecated.ts deleted file mode 100644 index 7ff7d3d914..0000000000 --- a/packages/twenty-front/src/modules/ui/utilities/recoil-scope/utils/getScopedSelectorDeprecated.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { RecoilScopedSelector } from '../types/RecoilScopedSelector'; - -export const getScopedSelectorDeprecated = ( - recoilScopedState: RecoilScopedSelector, - scopeId: string, -) => { - return recoilScopedState({ - scopeId, - }); -}; diff --git a/packages/twenty-front/src/modules/ui/utilities/scroll/hooks/__tests__/useListenScroll.test.tsx b/packages/twenty-front/src/modules/ui/utilities/scroll/hooks/__tests__/useListenScroll.test.tsx index ccde6fbca8..4d254e0f99 100644 --- a/packages/twenty-front/src/modules/ui/utilities/scroll/hooks/__tests__/useListenScroll.test.tsx +++ b/packages/twenty-front/src/modules/ui/utilities/scroll/hooks/__tests__/useListenScroll.test.tsx @@ -24,7 +24,7 @@ describe('useListenScroll', () => { const { result } = renderHook( () => { useListenScroll({ scrollableRef: containerRef }); - const isScrolling = useRecoilValue(isScrollingState()); + const isScrolling = useRecoilValue(isScrollingState); return { isScrolling }; }, diff --git a/packages/twenty-front/src/modules/ui/utilities/scroll/hooks/useListenScroll.ts b/packages/twenty-front/src/modules/ui/utilities/scroll/hooks/useListenScroll.ts index 969f24e0e3..7607c51fef 100644 --- a/packages/twenty-front/src/modules/ui/utilities/scroll/hooks/useListenScroll.ts +++ b/packages/twenty-front/src/modules/ui/utilities/scroll/hooks/useListenScroll.ts @@ -15,7 +15,7 @@ export const useListenScroll = ({ const hideScrollBarsCallback = useRecoilCallback( ({ snapshot }) => () => { - const isScrolling = snapshot.getLoadable(isScrollingState()).getValue(); + const isScrolling = snapshot.getLoadable(isScrollingState).getValue(); if (!isScrolling) { scrollableRef.current?.classList.remove('scrolling'); @@ -27,13 +27,13 @@ export const useListenScroll = ({ const handleScrollStart = useRecoilCallback( ({ set }) => (event: Event) => { - set(isScrollingState(), true); + set(isScrollingState, true); scrollableRef.current?.classList.add('scrolling'); const target = event.target as HTMLElement; - set(scrollTopState(), target.scrollTop); - set(scrollLeftState(), target.scrollLeft); + set(scrollTopState, target.scrollTop); + set(scrollLeftState, target.scrollLeft); }, [scrollableRef], ); @@ -41,7 +41,7 @@ export const useListenScroll = ({ const handleScrollEnd = useRecoilCallback( ({ set }) => () => { - set(isScrollingState(), false); + set(isScrollingState, false); debounce(hideScrollBarsCallback, 1000)(); }, [hideScrollBarsCallback], diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/extractComponentState.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/extractComponentState.ts index c9b6478c2e..ea797fe77e 100644 --- a/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/extractComponentState.ts +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/extractComponentState.ts @@ -8,5 +8,5 @@ export const extractComponentState = ( ) => RecoilState, scopeId: string, ) => { - return () => componentState({ scopeId }); + return componentState({ scopeId }); }; diff --git a/packages/twenty-front/src/modules/ui/utilities/state/utils/createState.ts b/packages/twenty-front/src/modules/ui/utilities/state/utils/createState.ts index b2fdfcdd0c..c81d9a86db 100644 --- a/packages/twenty-front/src/modules/ui/utilities/state/utils/createState.ts +++ b/packages/twenty-front/src/modules/ui/utilities/state/utils/createState.ts @@ -14,5 +14,5 @@ export const createState = ({ default: defaultValue, effects, }); - return () => recoilState; + return recoilState; }; diff --git a/packages/twenty-front/src/modules/users/components/UserProvider.tsx b/packages/twenty-front/src/modules/users/components/UserProvider.tsx index e871755179..aa0af98a25 100644 --- a/packages/twenty-front/src/modules/users/components/UserProvider.tsx +++ b/packages/twenty-front/src/modules/users/components/UserProvider.tsx @@ -12,11 +12,11 @@ import { isDefined } from '~/utils/isDefined'; export const UserProvider = ({ children }: React.PropsWithChildren) => { const [isLoading, setIsLoading] = useState(true); - const setCurrentUser = useSetRecoilState(currentUserState()); - const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState()); + const setCurrentUser = useSetRecoilState(currentUserState); + const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState); const setCurrentWorkspaceMember = useSetRecoilState( - currentWorkspaceMemberState(), + currentWorkspaceMemberState, ); const { loading: queryLoading, data: queryData } = useQuery(GET_CURRENT_USER); diff --git a/packages/twenty-front/src/modules/views/components/EditableFilterChip.tsx b/packages/twenty-front/src/modules/views/components/EditableFilterChip.tsx index b054c58fb8..af75297298 100644 --- a/packages/twenty-front/src/modules/views/components/EditableFilterChip.tsx +++ b/packages/twenty-front/src/modules/views/components/EditableFilterChip.tsx @@ -1,10 +1,10 @@ +import { Filter } from '@/object-record/object-filter-dropdown/types/Filter'; import { getOperandLabelShort } from '@/object-record/object-filter-dropdown/utils/getOperandLabel'; import { useIcons } from '@/ui/display/icon/hooks/useIcons'; import { SortOrFilterChip } from '@/views/components/SortOrFilterChip'; -import { ViewFilter } from '@/views/types/ViewFilter'; type EditableFilterChipProps = { - viewFilter: ViewFilter; + viewFilter: Filter; onRemove: () => void; }; diff --git a/packages/twenty-front/src/modules/views/components/EditableFilterDropdownButton.tsx b/packages/twenty-front/src/modules/views/components/EditableFilterDropdownButton.tsx index 0f9ef89b1b..aa10156cdc 100644 --- a/packages/twenty-front/src/modules/views/components/EditableFilterDropdownButton.tsx +++ b/packages/twenty-front/src/modules/views/components/EditableFilterDropdownButton.tsx @@ -1,18 +1,19 @@ import { useCallback, useEffect } from 'react'; +import { useRecoilValue } from 'recoil'; import { MultipleFiltersDropdownContent } from '@/object-record/object-filter-dropdown/components/MultipleFiltersDropdownContent'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; +import { Filter } from '@/object-record/object-filter-dropdown/types/Filter'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope'; import { EditableFilterChip } from '@/views/components/EditableFilterChip'; -import { useViewBar } from '@/views/hooks/useViewBar'; -import { ViewFilter } from '@/views/types/ViewFilter'; +import { useCombinedViewFilters } from '@/views/hooks/useCombinedViewFilters'; import { isDefined } from '~/utils/isDefined'; type EditableFilterDropdownButtonProps = { viewFilterDropdownId: string; - viewFilter: ViewFilter; + viewFilter: Filter; hotkeyScope: HotkeyScope; }; @@ -22,7 +23,7 @@ export const EditableFilterDropdownButton = ({ hotkeyScope, }: EditableFilterDropdownButtonProps) => { const { - availableFilterDefinitions, + availableFilterDefinitionsState, setFilterDefinitionUsedInDropdown, setSelectedOperandInDropdown, setSelectedFilter, @@ -30,9 +31,13 @@ export const EditableFilterDropdownButton = ({ filterDropdownId: viewFilterDropdownId, }); + const availableFilterDefinitions = useRecoilValue( + availableFilterDefinitionsState, + ); + const { closeDropdown } = useDropdown(viewFilterDropdownId); - const { removeViewFilter } = useViewBar(); + const { removeCombinedViewFilter } = useCombinedViewFilters(); useEffect(() => { const filterDefinition = availableFilterDefinitions.find( @@ -57,15 +62,15 @@ export const EditableFilterDropdownButton = ({ const handleRemove = () => { closeDropdown(); - removeViewFilter(viewFilter.fieldMetadataId); + removeCombinedViewFilter(viewFilter.fieldMetadataId); }; const handleDropdownClickOutside = useCallback(() => { const { value, fieldMetadataId } = viewFilter; if (!value) { - removeViewFilter(fieldMetadataId); + removeCombinedViewFilter(fieldMetadataId); } - }, [viewFilter, removeViewFilter]); + }, [viewFilter, removeCombinedViewFilter]); return ( { - const { removeViewSort, upsertViewSort } = useViewBar(); + const { removeCombinedViewSort, upsertCombinedViewSort } = + useCombinedViewSorts(); const handleRemoveClick = () => { - removeViewSort(viewSort.fieldMetadataId); + removeCombinedViewSort(viewSort.fieldMetadataId); }; const handleClick = () => { - upsertViewSort({ + upsertCombinedViewSort({ ...viewSort, direction: viewSort.direction === 'asc' ? 'desc' : 'asc', }); diff --git a/packages/twenty-front/src/modules/views/components/FilterQueryParamsEffect.tsx b/packages/twenty-front/src/modules/views/components/FilterQueryParamsEffect.tsx index fe72b24bc0..ad9d608005 100644 --- a/packages/twenty-front/src/modules/views/components/FilterQueryParamsEffect.tsx +++ b/packages/twenty-front/src/modules/views/components/FilterQueryParamsEffect.tsx @@ -1,38 +1,47 @@ import { useEffect } from 'react'; -import { useRecoilValue, useSetRecoilState } from 'recoil'; +import { isUndefined } from '@sniptt/guards'; +import { useSetRecoilState } from 'recoil'; -import { useFiltersFromQueryParams } from '@/views/hooks/internal/useFiltersFromQueryParams'; -import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates'; -import { useViewBar } from '@/views/hooks/useViewBar'; +import { useViewFromQueryParams } from '@/views/hooks/internal/useViewFromQueryParams'; +import { useViewStates } from '@/views/hooks/internal/useViewStates'; +import { useResetCurrentView } from '@/views/hooks/useResetCurrentView'; export const FilterQueryParamsEffect = () => { - const { hasFiltersQueryParams, getFiltersFromQueryParams } = - useFiltersFromQueryParams(); - const { currentViewFiltersState, onViewFiltersChangeState } = - useViewScopedStates(); - const setCurrentViewFilters = useSetRecoilState(currentViewFiltersState); - const onViewFiltersChange = useRecoilValue(onViewFiltersChangeState); - const { resetViewBar } = useViewBar(); + const { hasFiltersQueryParams, getFiltersFromQueryParams, viewIdQueryParam } = + useViewFromQueryParams(); + const { unsavedToUpsertViewFiltersState, currentViewIdState } = + useViewStates(); + const setUnsavedViewFilter = useSetRecoilState( + unsavedToUpsertViewFiltersState, + ); + const setCurrentViewId = useSetRecoilState(currentViewIdState); + const { resetCurrentView } = useResetCurrentView(); + + useEffect(() => { + if (isUndefined(viewIdQueryParam) || !viewIdQueryParam) { + return; + } + + setCurrentViewId(viewIdQueryParam); + }, [getFiltersFromQueryParams, setCurrentViewId, viewIdQueryParam]); useEffect(() => { if (!hasFiltersQueryParams) return; getFiltersFromQueryParams().then((filtersFromParams) => { if (Array.isArray(filtersFromParams)) { - setCurrentViewFilters(filtersFromParams); - onViewFiltersChange?.(filtersFromParams); + setUnsavedViewFilter(filtersFromParams); } }); return () => { - resetViewBar(); + resetCurrentView(); }; }, [ getFiltersFromQueryParams, hasFiltersQueryParams, - onViewFiltersChange, - resetViewBar, - setCurrentViewFilters, + resetCurrentView, + setUnsavedViewFilter, ]); return null; diff --git a/packages/twenty-front/src/modules/views/components/UpdateViewButtonGroup.tsx b/packages/twenty-front/src/modules/views/components/UpdateViewButtonGroup.tsx index ac8c6da739..d4dac54f45 100644 --- a/packages/twenty-front/src/modules/views/components/UpdateViewButtonGroup.tsx +++ b/packages/twenty-front/src/modules/views/components/UpdateViewButtonGroup.tsx @@ -1,6 +1,6 @@ import { useCallback } from 'react'; import styled from '@emotion/styled'; -import { useRecoilValue } from 'recoil'; +import { useRecoilValue, useSetRecoilState } from 'recoil'; import { IconChevronDown, IconPlus } from '@/ui/display/icon'; import { Button } from '@/ui/input/button/components/Button'; @@ -10,9 +10,8 @@ import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/Drop import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem'; import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope'; import { UPDATE_VIEW_DROPDOWN_ID } from '@/views/constants/UpdateViewDropdownId'; -import { useViewBar } from '@/views/hooks/useViewBar'; - -import { useViewScopedStates } from '../hooks/internal/useViewScopedStates'; +import { useViewStates } from '@/views/hooks/internal/useViewStates'; +import { useSaveCurrentViewFiltersAndSorts } from '@/views/hooks/useSaveCurrentViewFiltersAndSorts'; const StyledContainer = styled.div` background: ${({ theme }) => theme.color.blue}; @@ -31,14 +30,11 @@ export const UpdateViewButtonGroup = ({ hotkeyScope, onViewEditModeChange, }: UpdateViewButtonGroupProps) => { - const { updateCurrentView, setViewEditMode } = useViewBar(); - const { canPersistFiltersSelector, canPersistSortsSelector } = - useViewScopedStates(); + const { canPersistViewSelector, viewEditModeState } = useViewStates(); + const { saveCurrentViewFilterAndSorts } = useSaveCurrentViewFiltersAndSorts(); - const canPersistFilters = useRecoilValue(canPersistFiltersSelector); - const canPersistSorts = useRecoilValue(canPersistSortsSelector); - - const canPersistView = canPersistFilters || canPersistSorts; + const setViewEditMode = useSetRecoilState(viewEditModeState); + const canPersistView = useRecoilValue(canPersistViewSelector()); const handleCreateViewButtonClick = useCallback(() => { setViewEditMode('create'); @@ -46,7 +42,7 @@ export const UpdateViewButtonGroup = ({ }, [setViewEditMode, onViewEditModeChange]); const handleViewSubmit = async () => { - await updateCurrentView?.(); + await saveCurrentViewFilterAndSorts(); }; if (!canPersistView) { diff --git a/packages/twenty-front/src/modules/views/components/ViewBar.tsx b/packages/twenty-front/src/modules/views/components/ViewBar.tsx index 2ee4be3f2e..2d13fe1ac2 100644 --- a/packages/twenty-front/src/modules/views/components/ViewBar.tsx +++ b/packages/twenty-front/src/modules/views/components/ViewBar.tsx @@ -10,12 +10,8 @@ import { FilterQueryParamsEffect } from '@/views/components/FilterQueryParamsEff import { ViewBarEffect } from '@/views/components/ViewBarEffect'; import { ViewBarFilterEffect } from '@/views/components/ViewBarFilterEffect'; import { ViewBarSortEffect } from '@/views/components/ViewBarSortEffect'; -import { useViewBar } from '@/views/hooks/useViewBar'; import { ViewScope } from '@/views/scopes/ViewScope'; -import { ViewField } from '@/views/types/ViewField'; -import { ViewFilter } from '@/views/types/ViewFilter'; -import { ViewSort } from '@/views/types/ViewSort'; -import { ViewType } from '@/views/types/ViewType'; +import { GraphQLView } from '@/views/types/GraphQLView'; import { ViewsHotkeyScope } from '../types/ViewsHotkeyScope'; @@ -28,13 +24,7 @@ export type ViewBarProps = { className?: string; optionsDropdownButton: ReactNode; optionsDropdownScopeId: string; - onViewSortsChange?: (sorts: ViewSort[]) => void | Promise; - onViewFiltersChange?: (filters: ViewFilter[]) => void | Promise; - onViewFieldsChange?: (fields: ViewField[]) => void | Promise; - onViewTypeChange?: (viewType: ViewType) => void | Promise; - onViewCompactModeChange?: ( - isCompactModeActive: boolean, - ) => void | Promise; + onCurrentViewChange: (view: GraphQLView | undefined) => void | Promise; }; export const ViewBar = ({ @@ -42,18 +32,12 @@ export const ViewBar = ({ className, optionsDropdownButton, optionsDropdownScopeId, - onViewFieldsChange, - onViewFiltersChange, - onViewSortsChange, - onViewTypeChange, - onViewCompactModeChange, + onCurrentViewChange, }: ViewBarProps) => { const { openDropdown: openOptionsDropdownButton } = useDropdown( optionsDropdownScopeId, ); - const { upsertViewSort, upsertViewFilter } = useViewBar({ - viewBarId, - }); + const { objectNamePlural } = useParams(); const filterDropdownId = 'view-filter'; @@ -62,21 +46,11 @@ export const ViewBar = ({ return ( - - - + + + {!!objectNamePlural && } theme.border.color.light}; display: flex; flex-direction: row; - height: 40px; + min-height: 32px; justify-content: space-between; z-index: 4; + padding-top: ${({ theme }) => theme.spacing(1)}; + padding-bottom: ${({ theme }) => theme.spacing(1)}; `; const StyledChipcontainer = styled.div` @@ -35,10 +39,9 @@ const StyledChipcontainer = styled.div` display: flex; flex-direction: row; gap: ${({ theme }) => theme.spacing(1)}; - height: 40px; - justify-content: space-between; + min-height: 32px; margin-left: ${({ theme }) => theme.spacing(2)}; - overflow-x: auto; + flex-wrap: wrap; `; const StyledCancelButton = styled.button` @@ -92,37 +95,35 @@ export const ViewBarDetails = ({ hasFilterButton = false, rightComponent, filterDropdownId, - viewBarId, }: ViewBarDetailsProps) => { const { - currentViewSortsState, - currentViewFiltersState, - canPersistFiltersSelector, - canPersistSortsSelector, + canPersistViewSelector, isViewBarExpandedState, - } = useViewScopedStates(); + availableFilterDefinitionsState, + availableSortDefinitionsState, + } = useViewStates(); + + const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView(); - const currentViewSorts = useRecoilValue(currentViewSortsState); - const currentViewFilters = useRecoilValue(currentViewFiltersState); - const canPersistFilters = useRecoilValue(canPersistFiltersSelector); - const canPersistSorts = useRecoilValue(canPersistSortsSelector); const isViewBarExpanded = useRecoilValue(isViewBarExpandedState); + const canPersistView = useRecoilValue(canPersistViewSelector()); + const availableFilterDefinitions = useRecoilValue( + availableFilterDefinitionsState, + ); + const availableSortDefinitions = useRecoilValue( + availableSortDefinitionsState, + ); - const { resetViewBar } = useViewBar(); - - const canPersistView = canPersistFilters || canPersistSorts; + const { resetCurrentView } = useResetCurrentView(); const handleCancelClick = () => { - resetViewBar(); + resetCurrentView(); }; - const { upsertViewFilter } = useViewBar({ - viewBarId: viewBarId, - }); - const shouldExpandViewBar = canPersistView || - ((currentViewSorts?.length || currentViewFilters?.length) && + ((currentViewWithCombinedFiltersAndSorts?.viewSorts?.length || + currentViewWithCombinedFiltersAndSorts?.viewFilters?.length) && isViewBarExpanded); if (!shouldExpandViewBar) { @@ -133,23 +134,29 @@ export const ViewBarDetails = ({ - {currentViewSorts?.map((sort) => ( - + {mapViewSortsToSorts( + currentViewWithCombinedFiltersAndSorts?.viewSorts ?? [], + availableSortDefinitions, + ).map((sort) => ( + ))} - {!!currentViewSorts?.length && !!currentViewFilters?.length && ( - - - - )} - {currentViewFilters?.map((viewFilter) => ( + {!!currentViewWithCombinedFiltersAndSorts?.viewSorts?.length && + !!currentViewWithCombinedFiltersAndSorts?.viewFilters?.length && ( + + + + )} + {mapViewFiltersToFilters( + currentViewWithCombinedFiltersAndSorts?.viewFilters ?? [], + availableFilterDefinitions, + ).map((viewFilter) => ( { +export const ViewBarEffect = ({ viewBarId }: ViewBarEffectProps) => { + const { currentViewWithCombinedFiltersAndSorts } = + useGetCurrentView(viewBarId); const { - loadView, - changeViewInUrl, - loadViewFields, - loadViewFilters, - loadViewSorts, - } = useViewBar(); + onCurrentViewChangeState, + currentViewIdState, + availableFilterDefinitionsState, + isPersistingViewFieldsState, + } = useViewStates(viewBarId); - const [searchParams] = useSearchParams(); - const currentViewIdFromUrl = searchParams.get('view'); - - const { viewObjectMetadataIdState, viewsState, currentViewIdState } = - useViewScopedStates(); - - const [views, setViews] = useRecoilState(viewsState); - const viewObjectMetadataId = useRecoilValue(viewObjectMetadataIdState); - const setCurrentViewId = useSetRecoilState(currentViewIdState); - - const { records: newViews } = usePrefetchedData( - PrefetchKey.AllViews, - ); - - const newViewsOnCurrentObject = newViews.filter( - (view) => view.objectMetadataId === viewObjectMetadataId, + const [currentViewSnapshot, setCurrentViewSnapshot] = useState< + GraphQLView | undefined + >(undefined); + const onCurrentViewChange = useRecoilValue(onCurrentViewChangeState); + const availableFilterDefinitions = useRecoilValue( + availableFilterDefinitionsState, ); + const isPersistingViewFields = useRecoilValue(isPersistingViewFieldsState); + const [currentViewId, setCurrentViewId] = useRecoilState(currentViewIdState); useEffect(() => { - if (!newViewsOnCurrentObject.length) return; + if ( + !isDeeplyEqual( + currentViewWithCombinedFiltersAndSorts, + currentViewSnapshot, + ) + ) { + setCurrentViewSnapshot(currentViewWithCombinedFiltersAndSorts); - if (!isDeeplyEqual(views, newViewsOnCurrentObject)) { - setViews(newViewsOnCurrentObject); + if (isUndefined(currentViewWithCombinedFiltersAndSorts)) { + onCurrentViewChange?.(undefined); + return; + } + + if (!isPersistingViewFields) { + onCurrentViewChange?.(currentViewWithCombinedFiltersAndSorts); + } } - - const currentView = - newViewsOnCurrentObject.find( - (view) => view.id === currentViewIdFromUrl, - ) ?? - newViewsOnCurrentObject[0] ?? - null; - - if (isUndefinedOrNull(currentView)) return; - - setCurrentViewId(currentView.id); - - if (isDefined(currentView?.viewFields)) { - loadViewFields(currentView.viewFields, currentView.id); - loadViewFilters(currentView.viewFilters, currentView.id); - loadViewSorts(currentView.viewSorts, currentView.id); - } - - if (!currentViewIdFromUrl) return changeViewInUrl(currentView.id); }, [ - changeViewInUrl, - currentViewIdFromUrl, - loadViewFields, - loadViewFilters, - loadViewSorts, - newViewsOnCurrentObject, - setCurrentViewId, - setViews, - views, + availableFilterDefinitions, + currentViewSnapshot, + currentViewWithCombinedFiltersAndSorts, + isPersistingViewFields, + onCurrentViewChange, ]); useEffect(() => { - if (!currentViewIdFromUrl || !newViewsOnCurrentObject.length) return; - - loadView(currentViewIdFromUrl); - }, [currentViewIdFromUrl, loadView, newViewsOnCurrentObject]); + if ( + isDefined(currentViewWithCombinedFiltersAndSorts) && + !isDefined(currentViewId) + ) { + setCurrentViewId(currentViewWithCombinedFiltersAndSorts.id); + } + }, [currentViewWithCombinedFiltersAndSorts, currentViewId, setCurrentViewId]); return <>; }; diff --git a/packages/twenty-front/src/modules/views/components/ViewBarFilterEffect.tsx b/packages/twenty-front/src/modules/views/components/ViewBarFilterEffect.tsx index d496280994..1f19e48103 100644 --- a/packages/twenty-front/src/modules/views/components/ViewBarFilterEffect.tsx +++ b/packages/twenty-front/src/modules/views/components/ViewBarFilterEffect.tsx @@ -4,20 +4,21 @@ import { useRecoilValue } from 'recoil'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { Filter } from '@/object-record/object-filter-dropdown/types/Filter'; -import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates'; +import { useViewStates } from '@/views/hooks/internal/useViewStates'; +import { useCombinedViewFilters } from '@/views/hooks/useCombinedViewFilters'; import { isDefined } from '~/utils/isDefined'; type ViewBarFilterEffectProps = { filterDropdownId: string; - onFilterSelect?: ((filter: Filter) => void) | undefined; }; export const ViewBarFilterEffect = ({ filterDropdownId, - onFilterSelect, }: ViewBarFilterEffectProps) => { - const { availableFilterDefinitionsState, currentViewFiltersState } = - useViewScopedStates(); + const { availableFilterDefinitionsState, unsavedToUpsertViewFiltersState } = + useViewStates(); + + const { upsertCombinedViewFilter } = useCombinedViewFilters(); const availableFilterDefinitions = useRecoilValue( availableFilterDefinitionsState, @@ -25,32 +26,38 @@ export const ViewBarFilterEffect = ({ const { setAvailableFilterDefinitions, setOnFilterSelect, - filterDefinitionUsedInDropdown, + filterDefinitionUsedInDropdownState, setObjectFilterDropdownSelectedRecordIds, setObjectFilterDropdownSelectedOptionValues, - isObjectFilterDropdownUnfolded, } = useFilterDropdown({ filterDropdownId }); + const filterDefinitionUsedInDropdown = useRecoilValue( + filterDefinitionUsedInDropdownState, + ); + useEffect(() => { if (isDefined(availableFilterDefinitions)) { setAvailableFilterDefinitions(availableFilterDefinitions); } - - if (isDefined(onFilterSelect)) { - setOnFilterSelect(() => onFilterSelect); - } + setOnFilterSelect(() => (filter: Filter | null) => { + if (isDefined(filter)) { + upsertCombinedViewFilter(filter); + } + }); }, [ availableFilterDefinitions, - onFilterSelect, setAvailableFilterDefinitions, setOnFilterSelect, + upsertCombinedViewFilter, ]); - const currentViewFilters = useRecoilValue(currentViewFiltersState); + const unsavedToUpsertViewFilters = useRecoilValue( + unsavedToUpsertViewFiltersState, + ); useEffect(() => { if (filterDefinitionUsedInDropdown?.type === 'RELATION') { - const viewFilterUsedInDropdown = currentViewFilters.find( + const viewFilterUsedInDropdown = unsavedToUpsertViewFilters.find( (filter) => filter.fieldMetadataId === filterDefinitionUsedInDropdown.fieldMetadataId, @@ -64,7 +71,7 @@ export const ViewBarFilterEffect = ({ setObjectFilterDropdownSelectedRecordIds(viewFilterSelectedRecordIds); } else if (filterDefinitionUsedInDropdown?.type === 'SELECT') { - const viewFilterUsedInDropdown = currentViewFilters.find( + const viewFilterUsedInDropdown = unsavedToUpsertViewFilters.find( (filter) => filter.fieldMetadataId === filterDefinitionUsedInDropdown.fieldMetadataId, @@ -82,10 +89,9 @@ export const ViewBarFilterEffect = ({ } }, [ filterDefinitionUsedInDropdown, - currentViewFilters, setObjectFilterDropdownSelectedRecordIds, - isObjectFilterDropdownUnfolded, setObjectFilterDropdownSelectedOptionValues, + unsavedToUpsertViewFilters, ]); return <>; diff --git a/packages/twenty-front/src/modules/views/components/ViewBarSortEffect.tsx b/packages/twenty-front/src/modules/views/components/ViewBarSortEffect.tsx index eed9b42982..0baba6d0b4 100644 --- a/packages/twenty-front/src/modules/views/components/ViewBarSortEffect.tsx +++ b/packages/twenty-front/src/modules/views/components/ViewBarSortEffect.tsx @@ -1,42 +1,52 @@ import { useEffect } from 'react'; -import { useRecoilValue } from 'recoil'; +import { useRecoilValue, useSetRecoilState } from 'recoil'; import { useSortDropdown } from '@/object-record/object-sort-dropdown/hooks/useSortDropdown'; import { Sort } from '@/object-record/object-sort-dropdown/types/Sort'; -import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates'; +import { useViewStates } from '@/views/hooks/internal/useViewStates'; +import { useCombinedViewSorts } from '@/views/hooks/useCombinedViewSorts'; import { isDefined } from '~/utils/isDefined'; type ViewBarSortEffectProps = { sortDropdownId: string; - onSortSelect?: ((sort: Sort) => void) | undefined; }; export const ViewBarSortEffect = ({ sortDropdownId, - onSortSelect, }: ViewBarSortEffectProps) => { - const { availableSortDefinitionsState } = useViewScopedStates(); + const { availableSortDefinitionsState } = useViewStates(); + const { upsertCombinedViewSort } = useCombinedViewSorts(); const availableSortDefinitions = useRecoilValue( availableSortDefinitionsState, ); - const { setAvailableSortDefinitions, setOnSortSelect } = useSortDropdown({ + const { + availableSortDefinitionsState: availableSortDefinitionsInSortDropdownState, + onSortSelectState, + } = useSortDropdown({ sortDropdownId, }); + const setAvailableSortDefinitionsInSortDropdown = useSetRecoilState( + availableSortDefinitionsInSortDropdownState, + ); + const setOnSortSelect = useSetRecoilState(onSortSelectState); + useEffect(() => { if (isDefined(availableSortDefinitions)) { - setAvailableSortDefinitions(availableSortDefinitions); - } - if (isDefined(onSortSelect)) { - setOnSortSelect(() => onSortSelect); + setAvailableSortDefinitionsInSortDropdown(availableSortDefinitions); } + setOnSortSelect(() => (sort: Sort | null) => { + if (isDefined(sort)) { + upsertCombinedViewSort(sort); + } + }); }, [ availableSortDefinitions, - onSortSelect, - setAvailableSortDefinitions, + setAvailableSortDefinitionsInSortDropdown, setOnSortSelect, + upsertCombinedViewSort, ]); return <>; diff --git a/packages/twenty-front/src/modules/views/components/ViewsDropdownButton.tsx b/packages/twenty-front/src/modules/views/components/ViewsDropdownButton.tsx index d85a344c89..1ff11b28b4 100644 --- a/packages/twenty-front/src/modules/views/components/ViewsDropdownButton.tsx +++ b/packages/twenty-front/src/modules/views/components/ViewsDropdownButton.tsx @@ -1,7 +1,7 @@ import { MouseEvent } from 'react'; import { useTheme } from '@emotion/react'; import styled from '@emotion/styled'; -import { useRecoilCallback, useRecoilValue } from 'recoil'; +import { useRecoilValue, useSetRecoilState } from 'recoil'; import { IconChevronDown, @@ -20,10 +20,11 @@ import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem'; import { MOBILE_VIEWPORT } from '@/ui/theme/constants/MobileViewport'; import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope'; import { VIEWS_DROPDOWN_ID } from '@/views/constants/ViewsDropdownId'; -import { useViewBar } from '@/views/hooks/useViewBar'; +import { useGetCurrentView } from '@/views/hooks/useGetCurrentView'; +import { useHandleViews } from '@/views/hooks/useHandleViews'; import { isDefined } from '~/utils/isDefined'; -import { useViewScopedStates } from '../hooks/internal/useViewScopedStates'; +import { useViewStates } from '../hooks/internal/useViewStates'; const StyledBoldDropdownMenuItemsContainer = styled(DropdownMenuItemsContainer)` font-weight: ${({ theme }) => theme.font.weight.regular}; @@ -65,18 +66,18 @@ export const ViewsDropdownButton = ({ optionsDropdownScopeId, }: ViewsDropdownButtonProps) => { const theme = useTheme(); - const { removeView, changeViewInUrl } = useViewBar(); - const { viewsState, currentViewSelector, entityCountInCurrentViewState } = - useViewScopedStates(); + const { removeView, selectView } = useHandleViews(); + const { entityCountInCurrentViewState, viewEditModeState } = useViewStates(); + + const { currentViewWithCombinedFiltersAndSorts, viewsOnCurrentObject } = + useGetCurrentView(); - const views = useRecoilValue(viewsState); - const currentView = useRecoilValue(currentViewSelector); const entityCountInCurrentView = useRecoilValue( entityCountInCurrentViewState, ); - const { setViewEditMode, setCurrentViewId, loadView } = useViewBar(); + const setViewEditMode = useSetRecoilState(viewEditModeState); const { isDropdownOpen: isViewsDropdownOpen, @@ -87,14 +88,10 @@ export const ViewsDropdownButton = ({ optionsDropdownScopeId, ); - const handleViewSelect = useRecoilCallback( - () => async (viewId: string) => { - changeViewInUrl(viewId); - loadView(viewId); - closeViewsDropdown(); - }, - [changeViewInUrl, closeViewsDropdown, loadView], - ); + const handleViewSelect = (viewId: string) => { + selectView(viewId); + closeViewsDropdown(); + }; const handleAddViewButtonClick = () => { setViewEditMode('create'); @@ -108,8 +105,7 @@ export const ViewsDropdownButton = ({ viewId: string, ) => { event.stopPropagation(); - changeViewInUrl(viewId); - setCurrentViewId(viewId); + selectView(viewId); setViewEditMode('edit'); onViewEditModeChange?.(); closeViewsDropdown(); @@ -123,11 +119,12 @@ export const ViewsDropdownButton = ({ event.stopPropagation(); await removeView(viewId); + selectView(viewsOnCurrentObject.filter((view) => view.id !== viewId)[0].id); closeViewsDropdown(); }; const { getIcon } = useIcons(); - const CurrentViewIcon = getIcon(currentView?.icon); + const CurrentViewIcon = getIcon(currentViewWithCombinedFiltersAndSorts?.icon); return ( - {currentView && CurrentViewIcon ? ( + {currentViewWithCombinedFiltersAndSorts && CurrentViewIcon ? ( ) : ( )} - {currentView?.name ?? 'All'} + + {currentViewWithCombinedFiltersAndSorts?.name ?? 'All'} + · {entityCountInCurrentView}{' '} @@ -150,16 +149,18 @@ export const ViewsDropdownButton = ({ dropdownComponents={ <> - {views.map((view) => ( + {viewsOnCurrentObject.map((view) => ( ) => - handleEditViewButtonClick(event, view.id), - }, - views.length > 1 + currentViewWithCombinedFiltersAndSorts?.id === view.id + ? { + Icon: IconPencil, + onClick: (event: MouseEvent) => + handleEditViewButtonClick(event, view.id), + } + : null, + viewsOnCurrentObject.length > 1 ? { Icon: IconTrash, onClick: (event: MouseEvent) => diff --git a/packages/twenty-front/src/modules/views/constants/index.ts b/packages/twenty-front/src/modules/views/constants/index.ts deleted file mode 100644 index 932654ac31..0000000000 --- a/packages/twenty-front/src/modules/views/constants/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -// TODO: find a better pattern than using '' as a fallback -export const UNDEFINED_FAMILY_ITEM_ID = ''; diff --git a/packages/twenty-front/src/modules/views/hooks/__tests__/useViewBar.test.tsx b/packages/twenty-front/src/modules/views/hooks/__tests__/useViewBar.test.tsx index d0a0de37cd..3dabf65e0f 100644 --- a/packages/twenty-front/src/modules/views/hooks/__tests__/useViewBar.test.tsx +++ b/packages/twenty-front/src/modules/views/hooks/__tests__/useViewBar.test.tsx @@ -1,27 +1,11 @@ -import { act } from 'react-dom/test-utils'; -import { MemoryRouter, useSearchParams } from 'react-router-dom'; +import { MemoryRouter } from 'react-router-dom'; import { MockedProvider } from '@apollo/client/testing'; -import { renderHook, waitFor } from '@testing-library/react'; -import { RecoilRoot, useRecoilState, useRecoilValue } from 'recoil'; +import { RecoilRoot } from 'recoil'; import { v4 as uuidv4 } from 'uuid'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { generateDeleteOneRecordMutation } from '@/object-record/utils/generateDeleteOneRecordMutation'; -import { getScopedStateDeprecated } from '@/ui/utilities/recoil-scope/utils/getScopedStateDeprecated'; -import { - filterDefinition, - viewFilter, -} from '@/views/hooks/__tests__/useViewBar_ViewFilters.test'; -import { - sortDefinition, - viewSort, -} from '@/views/hooks/__tests__/useViewBar_ViewSorts.test'; -import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates'; -import { useViewBar } from '@/views/hooks/useViewBar'; import { ViewScope } from '@/views/scopes/ViewScope'; -import { entityCountInCurrentViewScopedState } from '@/views/states/entityCountInCurrentViewScopedState'; -import { viewEditModeScopedState } from '@/views/states/viewEditModeScopedState'; -import { viewObjectMetadataIdScopeState } from '@/views/states/viewObjectMetadataIdScopeState'; const mockedUuid = 'mocked-uuid'; jest.mock('uuid'); @@ -49,225 +33,19 @@ const Wrapper = ({ children }: { children: React.ReactNode }) => ( > - {children} + {}}> + {children} + ); -const renderHookConfig = { +const _renderHookConfig = { wrapper: Wrapper, }; -const viewBarId = 'viewBarTestId'; +const _viewBarId = 'viewBarTestId'; describe('useViewBar', () => { - it('should set and get current view Id', () => { - const { result } = renderHook( - () => useViewBar({ viewBarId }), - renderHookConfig, - ); - - expect(result.current.scopeId).toBe(viewBarId); - expect(result.current.currentViewId).toBeUndefined(); - - act(() => { - result.current.setCurrentViewId('testId'); - }); - - expect(result.current.currentViewId).toBe('testId'); - }); - - it('should create view and update url params', async () => { - const { result } = renderHook(() => { - const viewBar = useViewBar({ viewBarId }); - const searchParams = useSearchParams(); - - return { - viewBar, - searchParams, - }; - }, renderHookConfig); - await act(async () => { - await result.current.viewBar.createView('Test View'); - }); - expect(result.current.searchParams[0].get('view')).toBe(mockedUuid); - }); - - it('should delete current view and remove id from params', async () => { - const { result } = renderHook( - () => ({ - viewBar: useViewBar({ viewBarId }), - searchParams: useSearchParams(), - }), - renderHookConfig, - ); - - await act(async () => { - await result.current.viewBar.createView('Test View'); - result.current.viewBar.setCurrentViewId(mockedUuid); - }); - expect(result.current.searchParams[0].get('view')).toBe(mockedUuid); - - await act(async () => { - await result.current.viewBar.removeView(mockedUuid); - }); - expect(result.current.searchParams[0].get('view')).toBeNull(); - - const addBookMutationMock = mocks[0].result; - await waitFor(() => expect(addBookMutationMock).toHaveBeenCalled()); - }); - - it('should resetViewBar', async () => { - const { result } = renderHook(() => { - const viewBar = useViewBar({ viewBarId }); - const { - currentViewFiltersState, - currentViewSortsState, - viewEditModeState, - } = useViewScopedStates({ - viewScopeId: viewBarId, - }); - const currentViewFilters = useRecoilValue(currentViewFiltersState); - const currentViewSorts = useRecoilValue(currentViewSortsState); - const viewEditMode = useRecoilValue(viewEditModeState); - - return { - viewBar, - currentViewFilters, - currentViewSorts, - viewEditMode, - }; - }, renderHookConfig); - - act(() => { - result.current.viewBar.resetViewBar(); - }); - - expect(result.current.currentViewFilters).toStrictEqual([]); - expect(result.current.currentViewSorts).toStrictEqual([]); - expect(result.current.viewEditMode).toBe('none'); - }); - - it('should handleViewNameSubmit', async () => { - const { result } = renderHook( - () => useViewBar({ viewBarId }), - renderHookConfig, - ); - - await act(async () => { - await result.current.handleViewNameSubmit('New View Name'); - }); - }); - - it('should update edit mode', async () => { - const { result } = renderHook( - () => ({ - viewBar: useViewBar({ viewBarId }), - editMode: useRecoilState( - getScopedStateDeprecated(viewEditModeScopedState, viewBarId), - )[0], - }), - renderHookConfig, - ); - - expect(result.current.editMode).toBe('none'); - await act(async () => { - result.current.viewBar.setViewEditMode('create'); - }); - - expect(result.current.editMode).toBe('create'); - await act(async () => { - result.current.viewBar.setViewEditMode('edit'); - }); - - expect(result.current.editMode).toBe('edit'); - }); - - it('should update url param', async () => { - const { result } = renderHook( - () => ({ - viewBar: useViewBar({ viewBarId }), - searchParams: useSearchParams(), - }), - renderHookConfig, - ); - expect(result.current.searchParams[0].get('view')).toBeNull(); - await act(async () => { - result.current.viewBar.changeViewInUrl('view1'); - }); - expect(result.current.searchParams[0].get('view')).toBe('view1'); - }); - - it('should update object metadata id', async () => { - const { result } = renderHook( - () => ({ - viewBar: useViewBar({ viewBarId }), - metadataId: useRecoilState( - getScopedStateDeprecated(viewObjectMetadataIdScopeState, viewBarId), - )[0], - }), - renderHookConfig, - ); - - expect(result.current.metadataId).toBeUndefined(); - await act(async () => { - result.current.viewBar.setViewObjectMetadataId('newId'); - }); - - expect(result.current.metadataId).toBe('newId'); - }); - - it('should update count in current view', async () => { - const { result } = renderHook( - () => ({ - viewBar: useViewBar({ viewBarId }), - count: useRecoilState( - getScopedStateDeprecated( - entityCountInCurrentViewScopedState, - viewBarId, - ), - )[0], - }), - renderHookConfig, - ); - - expect(result.current.count).toBe(0); - await act(async () => { - result.current.viewBar.setEntityCountInCurrentView(1); - }); - - expect(result.current.count).toBe(1); - }); - - it('should loadView', async () => { - const { result } = renderHook( - () => useViewBar({ viewBarId }), - renderHookConfig, - ); - - act(() => { - result.current.loadView(mockedUuid); - }); - }); - - it('should updateCurrentView', async () => { - const { result } = renderHook(() => { - const viewBar = useViewBar({ viewBarId }); - viewBar.setCurrentViewId(mockedUuid); - - viewBar.setAvailableSortDefinitions([sortDefinition]); - - viewBar.loadViewSorts([viewSort], mockedUuid); - - viewBar.setAvailableFilterDefinitions([filterDefinition]); - - viewBar.loadViewFilters([viewFilter], mockedUuid); - - return { viewBar }; - }, renderHookConfig); - - await act(async () => { - await result.current.viewBar.updateCurrentView(); - }); - }); + it('should set and get current view Id', () => {}); }); diff --git a/packages/twenty-front/src/modules/views/hooks/__tests__/useViewBar_ViewFields.test.tsx b/packages/twenty-front/src/modules/views/hooks/__tests__/useViewBar_ViewFields.test.tsx deleted file mode 100644 index 7097205dc4..0000000000 --- a/packages/twenty-front/src/modules/views/hooks/__tests__/useViewBar_ViewFields.test.tsx +++ /dev/null @@ -1,170 +0,0 @@ -import { act } from 'react-dom/test-utils'; -import { MemoryRouter } from 'react-router-dom'; -import { gql } from '@apollo/client'; -import { MockedProvider } from '@apollo/client/testing'; -import { renderHook, waitFor } from '@testing-library/react'; -import { RecoilRoot, useRecoilState, useRecoilValue } from 'recoil'; - -import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata'; -import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition'; -import { getScopedFamilyStateDeprecated } from '@/ui/utilities/recoil-scope/utils/getScopedFamilyStateDeprecated'; -import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates'; -import { useViewBar } from '@/views/hooks/useViewBar'; -import { ViewScope } from '@/views/scopes/ViewScope'; -import { currentViewFieldsScopedFamilyState } from '@/views/states/currentViewFieldsScopedFamilyState'; -import { ViewField } from '@/views/types/ViewField'; - -const fieldMetadataId = '12ecdf87-506f-44a7-98c6-393e5f05b225'; - -const fieldDefinition: ColumnDefinition = { - size: 1, - position: 1, - fieldMetadataId, - label: 'label', - iconName: 'icon', - type: 'TEXT', - metadata: { - placeHolder: 'placeHolder', - fieldName: 'fieldName', - }, -}; -const viewField: ViewField = { - id: '88930a16-685f-493b-a96b-91ca55666bba', - fieldMetadataId, - position: 1, - isVisible: true, - size: 1, - definition: fieldDefinition, -}; - -const viewBarId = 'viewBarTestId'; - -const currentViewId = '23f5dceb-3482-4e3a-9bb4-2f52f2556be9'; - -const mocks = [ - { - request: { - query: gql` - mutation CreateOneViewField($input: ViewFieldCreateInput!) { - createViewField(data: $input) { - __typename - position - isVisible - fieldMetadataId - viewId - id - size - createdAt - updatedAt - } - } - `, - variables: { - input: { - fieldMetadataId, - viewId: currentViewId, - isVisible: true, - size: 1, - position: 1, - }, - }, - }, - result: jest.fn(() => ({ - data: { createViewField: { id: '' } }, - })), - }, -]; - -const Wrapper = ({ children }: { children: React.ReactNode }) => ( - - - - {children} - - - -); - -const renderHookConfig = { - wrapper: Wrapper, -}; - -describe('useViewBar > viewFields', () => { - it('should update current fields', async () => { - const { result } = renderHook( - () => ({ - viewBar: useViewBar({ viewBarId }), - currentFields: useRecoilState( - getScopedFamilyStateDeprecated( - currentViewFieldsScopedFamilyState, - viewBarId, - currentViewId, - ), - )[0], - }), - renderHookConfig, - ); - - expect(result.current.currentFields).toStrictEqual([]); - await act(async () => { - result.current.viewBar.setCurrentViewId(currentViewId); - result.current.viewBar.setViewObjectMetadataId('newId'); - result.current.viewBar.persistViewFields([viewField]); - }); - - await waitFor(() => - expect(result.current.currentFields).toEqual([viewField]), - ); - }); - - it('should persist view fields', async () => { - const { result } = renderHook( - () => useViewBar({ viewBarId }), - renderHookConfig, - ); - - await act(async () => { - result.current.setCurrentViewId(currentViewId); - result.current.setViewObjectMetadataId('newId'); - await result.current.persistViewFields([viewField]); - }); - - const persistViewFieldsMutation = mocks[0]; - - await waitFor(() => - expect(persistViewFieldsMutation.result).toHaveBeenCalled(), - ); - }); - - it('should load view fields', async () => { - const currentViewId = 'ac8807fd-0065-436d-bdf6-94333d75af6e'; - - const { result } = renderHook(() => { - const viewBar = useViewBar({ viewBarId }); - - const { currentViewFieldsState } = useViewScopedStates({ - viewScopeId: viewBarId, - }); - const currentViewFields = useRecoilValue(currentViewFieldsState); - - return { - viewBar, - currentViewFields, - }; - }, renderHookConfig); - - expect(result.current.currentViewFields).toStrictEqual([]); - - await act(async () => { - result.current.viewBar.setAvailableFieldDefinitions([fieldDefinition]); - - await result.current.viewBar.loadViewFields([viewField], currentViewId); - result.current.viewBar.setCurrentViewId(currentViewId); - }); - - expect(result.current.currentViewFields).toStrictEqual([viewField]); - }); -}); diff --git a/packages/twenty-front/src/modules/views/hooks/__tests__/useViewBar_ViewFilters.test.tsx b/packages/twenty-front/src/modules/views/hooks/__tests__/useViewBar_ViewFilters.test.tsx deleted file mode 100644 index 442e9a8722..0000000000 --- a/packages/twenty-front/src/modules/views/hooks/__tests__/useViewBar_ViewFilters.test.tsx +++ /dev/null @@ -1,178 +0,0 @@ -import { act } from 'react-dom/test-utils'; -import { MemoryRouter } from 'react-router-dom'; -import { MockedProvider } from '@apollo/client/testing'; -import { renderHook } from '@testing-library/react'; -import { RecoilRoot, useRecoilValue } from 'recoil'; - -import { Filter } from '@/object-record/object-filter-dropdown/types/Filter'; -import { FilterDefinition } from '@/object-record/object-filter-dropdown/types/FilterDefinition'; -import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates'; -import { useViewBar } from '@/views/hooks/useViewBar'; -import { ViewScope } from '@/views/scopes/ViewScope'; -import { ViewFilter } from '@/views/types/ViewFilter'; -import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; - -const Wrapper = ({ children }: { children: React.ReactNode }) => ( - - - - {children} - - - -); -const renderHookConfig = { - wrapper: Wrapper, -}; - -const viewBarId = 'viewBarTestId'; - -export const filterDefinition: FilterDefinition = { - fieldMetadataId: '113ea8f8-1908-4c9c-9984-3f23c96b92f5', - label: 'label', - iconName: 'iconName', - type: 'TEXT', -}; - -export const viewFilter: ViewFilter = { - id: 'id', - fieldMetadataId: '113ea8f8-1908-4c9c-9984-3f23c96b92f5', - operand: ViewFilterOperand.Is, - value: 'value', - displayValue: 'displayValue', - definition: filterDefinition, -}; - -const currentViewId = '23f5dceb-3482-4e3a-9bb4-2f52f2556be9'; - -describe('useViewBar > viewFilters', () => { - it('should load view filters', async () => { - const { result } = renderHook(() => { - const viewBar = useViewBar({ viewBarId }); - - const { currentViewFiltersState } = useViewScopedStates({ - viewScopeId: viewBarId, - }); - const currentViewFilters = useRecoilValue(currentViewFiltersState); - - return { - viewBar, - currentViewFilters, - }; - }, renderHookConfig); - - expect(result.current.currentViewFilters).toStrictEqual([]); - - await act(async () => { - result.current.viewBar.setAvailableFilterDefinitions([filterDefinition]); - - await result.current.viewBar.loadViewFilters([viewFilter], currentViewId); - result.current.viewBar.setCurrentViewId(currentViewId); - }); - - expect(result.current.currentViewFilters).toStrictEqual([viewFilter]); - }); - - it('should upsertViewFilter', async () => { - const { result } = renderHook(() => { - const viewBar = useViewBar({ viewBarId }); - - viewBar.setAvailableFilterDefinitions([filterDefinition]); - - viewBar.loadViewFilters([viewFilter], currentViewId); - viewBar.setCurrentViewId(currentViewId); - - const { currentViewFiltersState } = useViewScopedStates({ - viewScopeId: viewBarId, - }); - const currentViewFilters = useRecoilValue(currentViewFiltersState); - - return { - viewBar, - currentViewFilters, - }; - }, renderHookConfig); - - expect(result.current.currentViewFilters).toStrictEqual([viewFilter]); - - const newFilters: Filter[] = [ - { - fieldMetadataId: '113ea8f8-1908-4c9c-9984-3f23c96b92f5', - value: 'value', - displayValue: 'displayValue', - operand: ViewFilterOperand.IsNot, - definition: { - fieldMetadataId: 'id', - label: 'label', - iconName: 'icon', - type: 'TEXT', - }, - }, - { - fieldMetadataId: 'd9487757-183e-4fa0-a554-a980850cb23d', - value: 'value', - displayValue: 'displayValue', - operand: ViewFilterOperand.Contains, - definition: { - fieldMetadataId: 'id', - label: 'label', - iconName: 'icon', - type: 'TEXT', - }, - }, - ]; - - // upsert an existing filter - act(() => { - result.current.viewBar.upsertViewFilter(newFilters[0]); - }); - - expect(result.current.currentViewFilters).toStrictEqual([ - { ...newFilters[0], id: viewFilter.id }, - ]); - - // upsert a new filter - act(() => { - result.current.viewBar.upsertViewFilter(newFilters[1]); - }); - - // expect currentViewFilters to contain both filters - expect(result.current.currentViewFilters).toStrictEqual([ - { ...newFilters[0], id: viewFilter.id }, - { ...newFilters[1], id: undefined }, - ]); - }); - - it('should remove view filter', () => { - const { result } = renderHook(() => { - const viewBar = useViewBar({ viewBarId }); - - viewBar.setAvailableFilterDefinitions([filterDefinition]); - - viewBar.loadViewFilters([viewFilter], currentViewId); - viewBar.setCurrentViewId(currentViewId); - - const { currentViewFiltersState } = useViewScopedStates({ - viewScopeId: viewBarId, - }); - const currentViewFilters = useRecoilValue(currentViewFiltersState); - - return { - viewBar, - currentViewFilters, - }; - }, renderHookConfig); - - expect(result.current.currentViewFilters).toStrictEqual([viewFilter]); - - // remove an existing filter - act(() => { - result.current.viewBar.removeViewFilter(filterDefinition.fieldMetadataId); - }); - - expect(result.current.currentViewFilters).toStrictEqual([]); - }); -}); diff --git a/packages/twenty-front/src/modules/views/hooks/__tests__/useViewBar_ViewSorts.test.tsx b/packages/twenty-front/src/modules/views/hooks/__tests__/useViewBar_ViewSorts.test.tsx deleted file mode 100644 index b1a9c4d7a3..0000000000 --- a/packages/twenty-front/src/modules/views/hooks/__tests__/useViewBar_ViewSorts.test.tsx +++ /dev/null @@ -1,165 +0,0 @@ -import { act } from 'react-dom/test-utils'; -import { MemoryRouter } from 'react-router-dom'; -import { MockedProvider } from '@apollo/client/testing'; -import { renderHook } from '@testing-library/react'; -import { RecoilRoot, useRecoilValue } from 'recoil'; - -import { Sort } from '@/object-record/object-sort-dropdown/types/Sort'; -import { SortDefinition } from '@/object-record/object-sort-dropdown/types/SortDefinition'; -import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates'; -import { useViewBar } from '@/views/hooks/useViewBar'; -import { ViewScope } from '@/views/scopes/ViewScope'; -import { ViewSort } from '@/views/types/ViewSort'; - -const Wrapper = ({ children }: { children: React.ReactNode }) => ( - - - - {children} - - - -); -const renderHookConfig = { - wrapper: Wrapper, -}; - -const viewBarId = 'viewBarTestId'; - -export const sortDefinition: SortDefinition = { - fieldMetadataId: '12ecdf87-506f-44a7-98c6-393e5f05b225', - label: 'label', - iconName: 'icon', -}; - -export const viewSort: ViewSort = { - id: '88930a16-685f-493b-a96b-91ca55666bba', - fieldMetadataId: '12ecdf87-506f-44a7-98c6-393e5f05b225', - direction: 'asc', - definition: sortDefinition, -}; - -describe('View Sorts', () => { - const currentViewId = 'ac8807fd-0065-436d-bdf6-94333d75af6e'; - - it('should load view sorts', async () => { - const { result } = renderHook(() => { - const viewBar = useViewBar({ viewBarId }); - - const { currentViewSortsState } = useViewScopedStates({ - viewScopeId: viewBarId, - }); - const currentViewSorts = useRecoilValue(currentViewSortsState); - - return { - viewBar, - currentViewSorts, - }; - }, renderHookConfig); - - expect(result.current.currentViewSorts).toStrictEqual([]); - - await act(async () => { - result.current.viewBar.setAvailableSortDefinitions([sortDefinition]); - - await result.current.viewBar.loadViewSorts([viewSort], currentViewId); - result.current.viewBar.setCurrentViewId(currentViewId); - }); - - expect(result.current.currentViewSorts).toStrictEqual([viewSort]); - }); - - it('should upsertViewSort', async () => { - const { result } = renderHook(() => { - const viewBar = useViewBar({ viewBarId }); - - viewBar.setAvailableSortDefinitions([sortDefinition]); - - viewBar.loadViewSorts([viewSort], currentViewId); - viewBar.setCurrentViewId(currentViewId); - - const { currentViewSortsState } = useViewScopedStates({ - viewScopeId: viewBarId, - }); - const currentViewSorts = useRecoilValue(currentViewSortsState); - - return { - viewBar, - currentViewSorts, - }; - }, renderHookConfig); - - expect(result.current.currentViewSorts).toStrictEqual([viewSort]); - - const newSortFieldMetadataId = 'd9487757-183e-4fa0-a554-a980850cb23d'; - - const newSorts: Sort[] = [ - { - fieldMetadataId: viewSort.fieldMetadataId, - direction: 'desc', - definition: sortDefinition, - }, - { - fieldMetadataId: newSortFieldMetadataId, - direction: 'asc', - definition: { - ...sortDefinition, - fieldMetadataId: newSortFieldMetadataId, - }, - }, - ]; - - // upsert an existing sort - act(() => { - result.current.viewBar.upsertViewSort(newSorts[0]); - }); - - expect(result.current.currentViewSorts).toStrictEqual([ - { ...newSorts[0], id: viewSort.id }, - ]); - - // upsert a new sort - act(() => { - result.current.viewBar.upsertViewSort(newSorts[1]); - }); - - // expect currentViewSorts to contain both sorts - expect(result.current.currentViewSorts).toStrictEqual([ - { ...newSorts[0], id: viewSort.id }, - { ...newSorts[1], id: undefined }, - ]); - }); - - it('should remove view sort', () => { - const { result } = renderHook(() => { - const viewBar = useViewBar({ viewBarId }); - - viewBar.setAvailableSortDefinitions([sortDefinition]); - - viewBar.loadViewSorts([viewSort], currentViewId); - viewBar.setCurrentViewId(currentViewId); - - const { currentViewSortsState } = useViewScopedStates({ - viewScopeId: viewBarId, - }); - const currentViewSorts = useRecoilValue(currentViewSortsState); - - return { - viewBar, - currentViewSorts, - }; - }, renderHookConfig); - - expect(result.current.currentViewSorts).toStrictEqual([viewSort]); - - // remove an existing sort - act(() => { - result.current.viewBar.removeViewSort(sortDefinition.fieldMetadataId); - }); - - expect(result.current.currentViewSorts).toStrictEqual([]); - }); -}); diff --git a/packages/twenty-front/src/modules/views/hooks/internal/usePersistViewFieldRecords.ts b/packages/twenty-front/src/modules/views/hooks/internal/usePersistViewFieldRecords.ts new file mode 100644 index 0000000000..0b7db03d03 --- /dev/null +++ b/packages/twenty-front/src/modules/views/hooks/internal/usePersistViewFieldRecords.ts @@ -0,0 +1,115 @@ +import { useCallback } from 'react'; +import { useApolloClient } from '@apollo/client'; +import { v4 } from 'uuid'; + +import { triggerCreateRecordsOptimisticEffect } from '@/apollo/optimistic-effect/utils/triggerCreateRecordsOptimisticEffect'; +import { triggerUpdateRecordOptimisticEffect } from '@/apollo/optimistic-effect/utils/triggerUpdateRecordOptimisticEffect'; +import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; +import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems'; +import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; +import { ObjectRecord } from '@/object-record/types/ObjectRecord'; +import { GraphQLView } from '@/views/types/GraphQLView'; +import { ViewField } from '@/views/types/ViewField'; + +export const usePersistViewFieldRecords = () => { + const { + updateOneRecordMutation, + createOneRecordMutation, + getRecordFromCache, + objectMetadataItem, + } = useObjectMetadataItem({ + objectNameSingular: CoreObjectNameSingular.ViewField, + }); + + const { objectMetadataItems } = useObjectMetadataItems(); + + const apolloClient = useApolloClient(); + + const createViewFieldRecords = useCallback( + (viewFieldsToCreate: ViewField[], view: GraphQLView) => { + if (!viewFieldsToCreate.length) return; + return Promise.all( + viewFieldsToCreate.map((viewField) => + apolloClient.mutate({ + mutation: createOneRecordMutation, + variables: { + input: { + fieldMetadataId: viewField.fieldMetadataId, + viewId: view.id, + isVisible: viewField.isVisible, + position: viewField.position, + size: viewField.size, + id: v4(), + }, + }, + update: (cache, { data }) => { + const record = data?.['createViewField']; + if (!record) return; + + triggerCreateRecordsOptimisticEffect({ + cache, + objectMetadataItem, + recordsToCreate: [record], + objectMetadataItems, + }); + }, + }), + ), + ); + }, + [ + apolloClient, + createOneRecordMutation, + objectMetadataItem, + objectMetadataItems, + ], + ); + + const updateViewFieldRecords = useCallback( + (viewFieldsToUpdate: ViewField[]) => { + if (!viewFieldsToUpdate.length) return; + return Promise.all( + viewFieldsToUpdate.map((viewField) => + apolloClient.mutate({ + mutation: updateOneRecordMutation, + variables: { + idToUpdate: viewField.id, + input: { + isVisible: viewField.isVisible, + position: viewField.position, + size: viewField.size, + }, + }, + update: (cache, { data }) => { + const record = data?.['updateViewField']; + if (!record) return; + const cachedRecord = getRecordFromCache(record.id); + + if (!cachedRecord) return; + + triggerUpdateRecordOptimisticEffect({ + cache, + objectMetadataItem, + currentRecord: cachedRecord, + updatedRecord: record, + objectMetadataItems, + }); + }, + }), + ), + ); + }, + [ + apolloClient, + getRecordFromCache, + objectMetadataItem, + objectMetadataItems, + updateOneRecordMutation, + ], + ); + + return { + createViewFieldRecords, + updateViewFieldRecords, + }; +}; diff --git a/packages/twenty-front/src/modules/views/hooks/internal/usePersistViewFilterRecords.ts b/packages/twenty-front/src/modules/views/hooks/internal/usePersistViewFilterRecords.ts new file mode 100644 index 0000000000..2a6527c0cf --- /dev/null +++ b/packages/twenty-front/src/modules/views/hooks/internal/usePersistViewFilterRecords.ts @@ -0,0 +1,156 @@ +import { useCallback } from 'react'; +import { useApolloClient } from '@apollo/client'; + +import { triggerCreateRecordsOptimisticEffect } from '@/apollo/optimistic-effect/utils/triggerCreateRecordsOptimisticEffect'; +import { triggerDeleteRecordsOptimisticEffect } from '@/apollo/optimistic-effect/utils/triggerDeleteRecordsOptimisticEffect'; +import { triggerUpdateRecordOptimisticEffect } from '@/apollo/optimistic-effect/utils/triggerUpdateRecordOptimisticEffect'; +import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; +import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems'; +import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; +import { ObjectRecord } from '@/object-record/types/ObjectRecord'; +import { GraphQLView } from '@/views/types/GraphQLView'; +import { ViewFilter } from '@/views/types/ViewFilter'; + +export const usePersistViewFilterRecords = () => { + const { + updateOneRecordMutation, + createOneRecordMutation, + deleteOneRecordMutation, + objectMetadataItem, + getRecordFromCache, + } = useObjectMetadataItem({ + objectNameSingular: CoreObjectNameSingular.ViewFilter, + }); + + const { objectMetadataItems } = useObjectMetadataItems(); + + const apolloClient = useApolloClient(); + + const createViewFilterRecords = useCallback( + (viewFiltersToCreate: ViewFilter[], view: GraphQLView) => { + if (!viewFiltersToCreate.length) return; + + return Promise.all( + viewFiltersToCreate.map((viewFilter) => + apolloClient.mutate({ + mutation: createOneRecordMutation, + variables: { + input: { + fieldMetadataId: viewFilter.fieldMetadataId, + viewId: view.id, + value: viewFilter.value, + displayValue: viewFilter.displayValue, + operand: viewFilter.operand, + }, + }, + update: (cache, { data }) => { + const record = data?.['createViewFilter']; + if (!record) return; + + triggerCreateRecordsOptimisticEffect({ + cache, + objectMetadataItem, + recordsToCreate: [record], + objectMetadataItems, + }); + }, + }), + ), + ); + }, + [ + apolloClient, + createOneRecordMutation, + objectMetadataItem, + objectMetadataItems, + ], + ); + + const updateViewFilterRecords = useCallback( + (viewFiltersToUpdate: ViewFilter[]) => { + if (!viewFiltersToUpdate.length) return; + return Promise.all( + viewFiltersToUpdate.map((viewFilter) => + apolloClient.mutate({ + mutation: updateOneRecordMutation, + variables: { + idToUpdate: viewFilter.id, + input: { + value: viewFilter.value, + displayValue: viewFilter.displayValue, + operand: viewFilter.operand, + }, + }, + update: (cache, { data }) => { + const record = data?.['updateViewFilter']; + if (!record) return; + const cachedRecord = getRecordFromCache(record.id); + + if (!cachedRecord) return; + + triggerUpdateRecordOptimisticEffect({ + cache, + objectMetadataItem, + currentRecord: cachedRecord, + updatedRecord: record, + objectMetadataItems, + }); + }, + }), + ), + ); + }, + [ + apolloClient, + getRecordFromCache, + objectMetadataItem, + objectMetadataItems, + updateOneRecordMutation, + ], + ); + + const deleteViewFilterRecords = useCallback( + (viewFilterIdsToDelete: string[]) => { + if (!viewFilterIdsToDelete.length) return; + return Promise.all( + viewFilterIdsToDelete.map((viewFilterId) => + apolloClient.mutate({ + mutation: deleteOneRecordMutation, + variables: { + idToDelete: viewFilterId, + }, + update: (cache, { data }) => { + const record = data?.['deleteViewFilter']; + + if (!record) return; + + const cachedRecord = getRecordFromCache(record.id, cache); + + if (!cachedRecord) return; + + triggerDeleteRecordsOptimisticEffect({ + cache, + objectMetadataItem, + recordsToDelete: [cachedRecord], + objectMetadataItems, + }); + }, + }), + ), + ); + }, + [ + apolloClient, + deleteOneRecordMutation, + getRecordFromCache, + objectMetadataItem, + objectMetadataItems, + ], + ); + + return { + createViewFilterRecords, + updateViewFilterRecords, + deleteViewFilterRecords, + }; +}; diff --git a/packages/twenty-front/src/modules/views/hooks/internal/usePersistViewSortRecords.ts b/packages/twenty-front/src/modules/views/hooks/internal/usePersistViewSortRecords.ts new file mode 100644 index 0000000000..4c927df23c --- /dev/null +++ b/packages/twenty-front/src/modules/views/hooks/internal/usePersistViewSortRecords.ts @@ -0,0 +1,151 @@ +import { useCallback } from 'react'; +import { useApolloClient } from '@apollo/client'; + +import { triggerCreateRecordsOptimisticEffect } from '@/apollo/optimistic-effect/utils/triggerCreateRecordsOptimisticEffect'; +import { triggerDeleteRecordsOptimisticEffect } from '@/apollo/optimistic-effect/utils/triggerDeleteRecordsOptimisticEffect'; +import { triggerUpdateRecordOptimisticEffect } from '@/apollo/optimistic-effect/utils/triggerUpdateRecordOptimisticEffect'; +import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; +import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems'; +import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; +import { ObjectRecord } from '@/object-record/types/ObjectRecord'; +import { GraphQLView } from '@/views/types/GraphQLView'; +import { ViewSort } from '@/views/types/ViewSort'; + +export const usePersistViewSortRecords = () => { + const { + updateOneRecordMutation, + createOneRecordMutation, + deleteOneRecordMutation, + objectMetadataItem, + getRecordFromCache, + } = useObjectMetadataItem({ + objectNameSingular: CoreObjectNameSingular.ViewSort, + }); + + const { objectMetadataItems } = useObjectMetadataItems(); + + const apolloClient = useApolloClient(); + + const createViewSortRecords = useCallback( + (viewSortsToCreate: ViewSort[], view: GraphQLView) => { + if (!viewSortsToCreate.length) return; + return Promise.all( + viewSortsToCreate.map((viewSort) => + apolloClient.mutate({ + mutation: createOneRecordMutation, + variables: { + input: { + fieldMetadataId: viewSort.fieldMetadataId, + viewId: view.id, + direction: viewSort.direction, + }, + }, + update: (cache, { data }) => { + const record = data?.['createViewSort']; + if (!record) return; + + triggerCreateRecordsOptimisticEffect({ + cache, + objectMetadataItem, + recordsToCreate: [record], + objectMetadataItems, + }); + }, + }), + ), + ); + }, + [ + apolloClient, + createOneRecordMutation, + objectMetadataItem, + objectMetadataItems, + ], + ); + + const updateViewSortRecords = useCallback( + (viewSortsToUpdate: ViewSort[]) => { + if (!viewSortsToUpdate.length) return; + return Promise.all( + viewSortsToUpdate.map((viewSort) => + apolloClient.mutate({ + mutation: updateOneRecordMutation, + variables: { + idToUpdate: viewSort.id, + input: { + direction: viewSort.direction, + }, + }, + update: (cache, { data }) => { + const record = data?.['updateViewSort']; + if (!record) return; + const cachedRecord = getRecordFromCache(record.id); + + if (!cachedRecord) return; + + triggerUpdateRecordOptimisticEffect({ + cache, + objectMetadataItem, + currentRecord: cachedRecord, + updatedRecord: record, + objectMetadataItems, + }); + }, + }), + ), + ); + }, + [ + apolloClient, + getRecordFromCache, + objectMetadataItem, + objectMetadataItems, + updateOneRecordMutation, + ], + ); + + const deleteViewSortRecords = useCallback( + (viewSortIdsToDelete: string[]) => { + if (!viewSortIdsToDelete.length) return; + return Promise.all( + viewSortIdsToDelete.map((viewSortId) => + apolloClient.mutate({ + mutation: deleteOneRecordMutation, + variables: { + idToDelete: viewSortId, + }, + update: (cache, { data }) => { + const record = data?.['deleteViewSort']; + + if (!record) return; + + const cachedRecord = getRecordFromCache(record.id, cache); + + if (!cachedRecord) return; + + triggerDeleteRecordsOptimisticEffect({ + cache, + objectMetadataItem, + recordsToDelete: [cachedRecord], + objectMetadataItems, + }); + }, + }), + ), + ); + }, + [ + apolloClient, + deleteOneRecordMutation, + getRecordFromCache, + objectMetadataItem, + objectMetadataItems, + ], + ); + + return { + createViewSortRecords, + updateViewSortRecords, + deleteViewSortRecords, + }; +}; diff --git a/packages/twenty-front/src/modules/views/hooks/internal/useViewFields.ts b/packages/twenty-front/src/modules/views/hooks/internal/useViewFields.ts deleted file mode 100644 index e3d81affda..0000000000 --- a/packages/twenty-front/src/modules/views/hooks/internal/useViewFields.ts +++ /dev/null @@ -1,160 +0,0 @@ -import { Reference, useApolloClient } from '@apollo/client'; -import { useRecoilCallback } from 'recoil'; - -import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; -import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; -import { ViewField } from '@/views/types/ViewField'; -import { getViewScopedStatesFromSnapshot } from '@/views/utils/getViewScopedStatesFromSnapshot'; -import { getViewScopedStateValuesFromSnapshot } from '@/views/utils/getViewScopedStateValuesFromSnapshot'; - -export const useViewFields = (viewScopeId: string) => { - const { updateOneRecordMutation, createOneRecordMutation } = - useObjectMetadataItem({ - objectNameSingular: CoreObjectNameSingular.ViewField, - }); - - const { modifyRecordFromCache } = useObjectMetadataItem({ - objectNameSingular: CoreObjectNameSingular.View, - }); - - const apolloClient = useApolloClient(); - - const persistViewFields = useRecoilCallback( - ({ snapshot, set }) => - async (viewFieldsToPersist: ViewField[], viewId?: string) => { - const { - viewObjectMetadataId, - currentViewId, - savedViewFieldsByKey, - onViewFieldsChange, - views, - } = getViewScopedStateValuesFromSnapshot({ - snapshot, - viewScopeId, - viewId, - }); - - const { - isPersistingViewState, - currentViewFieldsState, - savedViewFieldsState, - } = getViewScopedStatesFromSnapshot({ - snapshot, - viewScopeId, - viewId, - }); - - const viewIdToPersist = viewId ?? currentViewId; - - if (!currentViewId || !savedViewFieldsByKey || !viewObjectMetadataId) { - return; - } - - const _createViewFields = (viewFieldsToCreate: ViewField[]) => { - if (!viewFieldsToCreate.length) { - return; - } - - return Promise.all( - viewFieldsToCreate.map((viewField) => - apolloClient.mutate({ - mutation: createOneRecordMutation, - variables: { - input: { - fieldMetadataId: viewField.fieldMetadataId, - viewId: viewIdToPersist, - isVisible: viewField.isVisible, - size: viewField.size, - position: viewField.position, - }, - }, - }), - ), - ); - }; - - const _updateViewFields = (viewFieldsToUpdate: ViewField[]) => { - if (!viewFieldsToUpdate.length) { - return; - } - - return Promise.all( - viewFieldsToUpdate.map((viewField) => - apolloClient.mutate({ - mutation: updateOneRecordMutation, - variables: { - idToUpdate: viewField.id, - input: { - isVisible: viewField.isVisible, - size: viewField.size, - position: viewField.position, - }, - }, - }), - ), - ); - }; - - const viewFieldsToCreate = viewFieldsToPersist.filter( - (viewField) => !savedViewFieldsByKey[viewField.fieldMetadataId], - ); - - const viewFieldsToUpdate = viewFieldsToPersist.filter( - (viewFieldToPersit) => - savedViewFieldsByKey[viewFieldToPersit.fieldMetadataId] && - (savedViewFieldsByKey[viewFieldToPersit.fieldMetadataId].size !== - viewFieldToPersit.size || - savedViewFieldsByKey[viewFieldToPersit.fieldMetadataId] - .position !== viewFieldToPersit.position || - savedViewFieldsByKey[viewFieldToPersit.fieldMetadataId] - .isVisible !== viewFieldToPersit.isVisible), - ); - - set(isPersistingViewState, true); - - await _createViewFields(viewFieldsToCreate); - - await _updateViewFields(viewFieldsToUpdate); - - set(isPersistingViewState, false); - set(currentViewFieldsState, viewFieldsToPersist); - set(savedViewFieldsState, viewFieldsToPersist); - - const existingView = views.find((view) => view.id === viewIdToPersist); - - if (!existingView) { - return; - } - - modifyRecordFromCache(viewIdToPersist ?? '', { - viewFields: (viewFieldsRef, { readField }) => { - const edges = readField<{ node: Reference }[]>( - 'edges', - viewFieldsRef, - ); - - if (!edges) return viewFieldsRef; - - return { - ...viewFieldsRef, - edges: viewFieldsToPersist.map((viewField) => ({ - node: viewField, - cursor: '', - })), - }; - }, - }); - - onViewFieldsChange?.(viewFieldsToPersist); - }, - [ - viewScopeId, - modifyRecordFromCache, - apolloClient, - createOneRecordMutation, - updateOneRecordMutation, - ], - ); - - return { persistViewFields }; -}; diff --git a/packages/twenty-front/src/modules/views/hooks/internal/useViewFilters.ts b/packages/twenty-front/src/modules/views/hooks/internal/useViewFilters.ts deleted file mode 100644 index a490c95756..0000000000 --- a/packages/twenty-front/src/modules/views/hooks/internal/useViewFilters.ts +++ /dev/null @@ -1,246 +0,0 @@ -import { Reference, useApolloClient } from '@apollo/client'; -import { produce } from 'immer'; -import { useRecoilCallback } from 'recoil'; - -import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; -import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; -import { Filter } from '@/object-record/object-filter-dropdown/types/Filter'; -import { savedViewFiltersScopedFamilyState } from '@/views/states/savedViewFiltersScopedFamilyState'; -import { ViewFilter } from '@/views/types/ViewFilter'; -import { getViewScopedStateValuesFromSnapshot } from '@/views/utils/getViewScopedStateValuesFromSnapshot'; - -import { useViewScopedStates } from './useViewScopedStates'; - -export const useViewFilters = (viewScopeId: string) => { - const { - updateOneRecordMutation, - createOneRecordMutation, - deleteOneRecordMutation, - } = useObjectMetadataItem({ - objectNameSingular: CoreObjectNameSingular.ViewFilter, - }); - - const { modifyRecordFromCache } = useObjectMetadataItem({ - objectNameSingular: CoreObjectNameSingular.View, - }); - - const apolloClient = useApolloClient(); - - const { currentViewFiltersState } = useViewScopedStates({ - viewScopeId: viewScopeId, - }); - - const persistViewFilters = useRecoilCallback( - ({ snapshot, set }) => - async (viewId?: string) => { - const { - currentViewId, - currentViewFilters, - savedViewFiltersByKey, - views, - } = getViewScopedStateValuesFromSnapshot({ - snapshot, - viewScopeId, - }); - - if (!currentViewId || !currentViewFilters || !savedViewFiltersByKey) { - return; - } - - const createViewFilters = (viewFiltersToCreate: ViewFilter[]) => { - if (!viewFiltersToCreate.length) return; - - return Promise.all( - viewFiltersToCreate.map((viewFilter) => - apolloClient.mutate({ - mutation: createOneRecordMutation, - variables: { - input: { - fieldMetadataId: viewFilter.fieldMetadataId, - viewId: viewId ?? currentViewId, - value: viewFilter.value, - displayValue: viewFilter.displayValue, - operand: viewFilter.operand, - }, - }, - }), - ), - ); - }; - - const updateViewFilters = (viewFiltersToUpdate: ViewFilter[]) => { - if (!viewFiltersToUpdate.length) return; - - return Promise.all( - viewFiltersToUpdate.map((viewFilter) => - apolloClient.mutate({ - mutation: updateOneRecordMutation, - variables: { - idToUpdate: viewFilter.id, - input: { - value: viewFilter.value, - displayValue: viewFilter.displayValue, - operand: viewFilter.operand, - }, - }, - }), - ), - ); - }; - - const deleteViewFilters = (viewFilterIdsToDelete: string[]) => { - if (!viewFilterIdsToDelete.length) return; - - return Promise.all( - viewFilterIdsToDelete.map((viewFilterId) => - apolloClient.mutate({ - mutation: deleteOneRecordMutation, - variables: { - idToDelete: viewFilterId, - }, - }), - ), - ); - }; - - const filtersToCreate = currentViewFilters.filter( - (filter) => !savedViewFiltersByKey[filter.fieldMetadataId], - ); - await createViewFilters(filtersToCreate); - - const filtersToUpdate = currentViewFilters.filter( - (filter) => - savedViewFiltersByKey[filter.fieldMetadataId] && - (savedViewFiltersByKey[filter.fieldMetadataId].operand !== - filter.operand || - savedViewFiltersByKey[filter.fieldMetadataId].value !== - filter.value), - ); - await updateViewFilters(filtersToUpdate); - - const filterKeys = currentViewFilters.map( - (filter) => filter.fieldMetadataId, - ); - const filterKeysToDelete = Object.keys(savedViewFiltersByKey).filter( - (previousFilterKey) => !filterKeys.includes(previousFilterKey), - ); - const filterIdsToDelete = filterKeysToDelete.map( - (filterKeyToDelete) => - savedViewFiltersByKey[filterKeyToDelete].id ?? '', - ); - await deleteViewFilters(filterIdsToDelete); - set( - savedViewFiltersScopedFamilyState({ - scopeId: viewScopeId, - familyKey: viewId ?? currentViewId, - }), - currentViewFilters, - ); - - const existingViewId = viewId ?? currentViewId; - const existingView = views.find((view) => view.id === existingViewId); - - if (!existingView) { - return; - } - - modifyRecordFromCache(existingViewId, { - viewFilters: (viewFiltersRef, { readField }) => { - const edges = readField<{ node: Reference }[]>( - 'edges', - viewFiltersRef, - ); - - if (!edges) return viewFiltersRef; - - return { - ...viewFiltersRef, - edges: currentViewFilters.map((viewFilter) => ({ - node: viewFilter, - cursor: '', - })), - }; - }, - }); - }, - [ - apolloClient, - createOneRecordMutation, - deleteOneRecordMutation, - modifyRecordFromCache, - updateOneRecordMutation, - viewScopeId, - ], - ); - - const upsertViewFilter = useRecoilCallback( - ({ snapshot, set }) => - (filterToUpsert: Filter) => { - const { currentViewId, savedViewFiltersByKey, onViewFiltersChange } = - getViewScopedStateValuesFromSnapshot({ - snapshot, - viewScopeId, - }); - - if (!currentViewId) { - return; - } - - if (!savedViewFiltersByKey) { - return; - } - - const existingSavedFilterId = - savedViewFiltersByKey[filterToUpsert.fieldMetadataId]?.id; - - set(currentViewFiltersState, (filters) => { - const newViewFilters = produce(filters, (filtersDraft) => { - const existingFilterIndex = filtersDraft.findIndex( - (filter) => - filter.fieldMetadataId === filterToUpsert.fieldMetadataId, - ); - - if (existingFilterIndex === -1 && filterToUpsert.value !== '') { - filtersDraft.push({ - ...filterToUpsert, - id: existingSavedFilterId, - }); - return filtersDraft; - } - - filtersDraft[existingFilterIndex] = { - ...filterToUpsert, - id: existingSavedFilterId, - }; - }); - onViewFiltersChange?.(newViewFilters); - return newViewFilters; - }); - }, - [currentViewFiltersState, viewScopeId], - ); - - const removeViewFilter = useRecoilCallback( - ({ snapshot, set }) => - (fieldMetadataId: string) => { - const { currentViewId, currentViewFilters, onViewFiltersChange } = - getViewScopedStateValuesFromSnapshot({ - snapshot, - viewScopeId, - }); - - if (!currentViewId) { - return; - } - - const newViewFilters = currentViewFilters.filter((filter) => { - return filter.fieldMetadataId !== fieldMetadataId; - }); - set(currentViewFiltersState, newViewFilters); - onViewFiltersChange?.(newViewFilters); - }, - [currentViewFiltersState, viewScopeId], - ); - - return { persistViewFilters, removeViewFilter, upsertViewFilter }; -}; diff --git a/packages/twenty-front/src/modules/views/hooks/internal/useFiltersFromQueryParams.ts b/packages/twenty-front/src/modules/views/hooks/internal/useViewFromQueryParams.ts similarity index 89% rename from packages/twenty-front/src/modules/views/hooks/internal/useFiltersFromQueryParams.ts rename to packages/twenty-front/src/modules/views/hooks/internal/useViewFromQueryParams.ts index 2bc3351753..4b7aad26ca 100644 --- a/packages/twenty-front/src/modules/views/hooks/internal/useFiltersFromQueryParams.ts +++ b/packages/twenty-front/src/modules/views/hooks/internal/useViewFromQueryParams.ts @@ -19,17 +19,20 @@ import { isDefined } from '~/utils/isDefined'; import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull'; const filterQueryParamsSchema = z.object({ - filter: z.record( - z.record( - z.nativeEnum(ViewFilterOperand), - z.string().or(z.array(z.string())), - ), - ), + view: z.string().optional(), + filter: z + .record( + z.record( + z.nativeEnum(ViewFilterOperand), + z.string().or(z.array(z.string())), + ), + ) + .optional(), }); export type FilterQueryParams = z.infer; -export const useFiltersFromQueryParams = () => { +export const useViewFromQueryParams = () => { const apolloClient = useApolloClient(); const [searchParams] = useSearchParams(); const { objectNamePlural = '' } = useParams(); @@ -39,15 +42,21 @@ export const useFiltersFromQueryParams = () => { const { objectMetadataItem } = useObjectMetadataItem({ objectNameSingular }); const generateFindManyRecordsQuery = useGenerateFindManyRecordsQuery(); - const filterParamsValidation = filterQueryParamsSchema.safeParse( + const queryParamsValidation = filterQueryParamsSchema.safeParse( qs.parse(searchParams.toString()), ); + const filterQueryParams = useMemo( () => - filterParamsValidation.success ? filterParamsValidation.data.filter : {}, - [filterParamsValidation], + queryParamsValidation.success ? queryParamsValidation.data.filter : {}, + [queryParamsValidation], ); - const hasFiltersQueryParams = filterParamsValidation.success; + const viewIdQueryParam = useMemo( + () => queryParamsValidation.success && queryParamsValidation.data.view, + [queryParamsValidation], + ); + + const hasFiltersQueryParams = filterQueryParams; const getFiltersFromQueryParams = useRecoilCallback( ({ snapshot }) => @@ -129,6 +138,7 @@ export const useFiltersFromQueryParams = () => { : filterValueFromURL; return { + __typename: 'ViewFilter', id: `tmp-${[ fieldName, filterOperandFromURL, @@ -140,6 +150,7 @@ export const useFiltersFromQueryParams = () => { displayValue: relationRecordNames?.join(', ') ?? filterValueAsString, definition: filterDefinition, + persistAction: 'NONE', }; }, ), @@ -156,6 +167,7 @@ export const useFiltersFromQueryParams = () => { ); return { + viewIdQueryParam, hasFiltersQueryParams, getFiltersFromQueryParams, }; diff --git a/packages/twenty-front/src/modules/views/hooks/internal/useViewScopedStates.ts b/packages/twenty-front/src/modules/views/hooks/internal/useViewScopedStates.ts deleted file mode 100644 index ecc4465e99..0000000000 --- a/packages/twenty-front/src/modules/views/hooks/internal/useViewScopedStates.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { useRecoilState } from 'recoil'; - -import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId'; -import { getScopedStateDeprecated } from '@/ui/utilities/recoil-scope/utils/getScopedStateDeprecated'; - -import { UNDEFINED_FAMILY_ITEM_ID } from '../../constants'; -import { ViewScopeInternalContext } from '../../scopes/scope-internal-context/ViewScopeInternalContext'; -import { currentViewIdScopedState } from '../../states/currentViewIdScopedState'; -import { getViewScopedStates } from '../../utils/internal/getViewScopedStates'; - -export const useViewScopedStates = (args?: { viewScopeId?: string }) => { - const { viewScopeId } = args ?? {}; - - const scopeId = useAvailableScopeIdOrThrow( - ViewScopeInternalContext, - viewScopeId, - ); - - // View - const [currentViewId] = useRecoilState( - getScopedStateDeprecated(currentViewIdScopedState, scopeId), - ); - - const viewId = currentViewId ?? UNDEFINED_FAMILY_ITEM_ID; - - const { - availableFieldDefinitionsState, - availableFilterDefinitionsState, - availableSortDefinitionsState, - canPersistFiltersSelector, - canPersistSortsSelector, - currentViewFieldsState, - currentViewFiltersState, - currentViewIdState, - currentViewSelector, - currentViewSortsState, - entityCountInCurrentViewState, - isViewBarExpandedState, - isPersistingViewState, - onViewFieldsChangeState, - onViewFiltersChangeState, - onViewSortsChangeState, - onViewTypeChangeState, - onViewCompactModeChangeState, - savedViewFieldsByKeySelector, - savedViewFieldsState, - savedViewFiltersByKeySelector, - savedViewFiltersState, - savedViewSortsByKeySelector, - savedViewSortsState, - viewEditModeState, - viewObjectMetadataIdState, - viewTypeState, - viewsState, - } = getViewScopedStates({ - viewScopeId: scopeId, - viewId, - }); - - return { - availableFieldDefinitionsState, - availableFilterDefinitionsState, - availableSortDefinitionsState, - canPersistFiltersSelector, - canPersistSortsSelector, - currentViewFieldsState, - currentViewFiltersState, - currentViewIdState, - currentViewSelector, - currentViewSortsState, - entityCountInCurrentViewState, - isViewBarExpandedState, - isPersistingViewState, - onViewFieldsChangeState, - onViewFiltersChangeState, - onViewSortsChangeState, - onViewTypeChangeState, - onViewCompactModeChangeState, - savedViewFieldsByKeySelector, - savedViewFieldsState, - savedViewFiltersByKeySelector, - savedViewFiltersState, - savedViewSortsByKeySelector, - savedViewSortsState, - viewEditModeState, - viewObjectMetadataIdState, - viewTypeState, - viewsState, - }; -}; diff --git a/packages/twenty-front/src/modules/views/hooks/internal/useViewSorts.ts b/packages/twenty-front/src/modules/views/hooks/internal/useViewSorts.ts deleted file mode 100644 index 093e371732..0000000000 --- a/packages/twenty-front/src/modules/views/hooks/internal/useViewSorts.ts +++ /dev/null @@ -1,236 +0,0 @@ -import { Reference, useApolloClient } from '@apollo/client'; -import { produce } from 'immer'; -import { useRecoilCallback } from 'recoil'; - -import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; -import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; -import { Sort } from '@/object-record/object-sort-dropdown/types/Sort'; -import { savedViewSortsScopedFamilyState } from '@/views/states/savedViewSortsScopedFamilyState'; -import { ViewSort } from '@/views/types/ViewSort'; -import { getViewScopedStateValuesFromSnapshot } from '@/views/utils/getViewScopedStateValuesFromSnapshot'; -import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull'; - -import { useViewScopedStates } from './useViewScopedStates'; - -export const useViewSorts = (viewScopeId: string) => { - const { - updateOneRecordMutation, - createOneRecordMutation, - deleteOneRecordMutation, - } = useObjectMetadataItem({ - objectNameSingular: CoreObjectNameSingular.ViewSort, - }); - - const { modifyRecordFromCache } = useObjectMetadataItem({ - objectNameSingular: CoreObjectNameSingular.View, - }); - const apolloClient = useApolloClient(); - - const { currentViewSortsState } = useViewScopedStates({ - viewScopeId: viewScopeId, - }); - - const persistViewSorts = useRecoilCallback( - ({ snapshot, set }) => - async (viewId?: string) => { - const { currentViewId, currentViewSorts, savedViewSortsByKey, views } = - getViewScopedStateValuesFromSnapshot({ - snapshot, - viewScopeId, - }); - - if (!currentViewId) { - return; - } - - if (isUndefinedOrNull(currentViewSorts)) { - return; - } - if (!savedViewSortsByKey) { - return; - } - - const createViewSorts = (viewSortsToCreate: ViewSort[]) => { - if (!viewSortsToCreate.length) return; - - return Promise.all( - viewSortsToCreate.map((viewSort) => - apolloClient.mutate({ - mutation: createOneRecordMutation, - variables: { - input: { - fieldMetadataId: viewSort.fieldMetadataId, - viewId: viewId ?? currentViewId, - direction: viewSort.direction, - }, - }, - }), - ), - ); - }; - - const updateViewSorts = (viewSortsToUpdate: ViewSort[]) => { - if (!viewSortsToUpdate.length) return; - - return Promise.all( - viewSortsToUpdate.map((viewSort) => - apolloClient.mutate({ - mutation: updateOneRecordMutation, - variables: { - idToUpdate: viewSort.id, - input: { - direction: viewSort.direction, - }, - }, - }), - ), - ); - }; - - const deleteViewSorts = (viewSortIdsToDelete: string[]) => { - if (!viewSortIdsToDelete.length) return; - - return Promise.all( - viewSortIdsToDelete.map((viewSortId) => - apolloClient.mutate({ - mutation: deleteOneRecordMutation, - variables: { - idToDelete: viewSortId, - }, - }), - ), - ); - }; - - const sortsToCreate = currentViewSorts.filter( - (sort) => !savedViewSortsByKey[sort.fieldMetadataId], - ); - - await createViewSorts(sortsToCreate); - - const sortsToUpdate = currentViewSorts.filter( - (sort) => - savedViewSortsByKey[sort.fieldMetadataId] && - savedViewSortsByKey[sort.fieldMetadataId].direction !== - sort.direction, - ); - await updateViewSorts(sortsToUpdate); - - const sortKeys = currentViewSorts.map((sort) => sort.fieldMetadataId); - const sortKeysToDelete = Object.keys(savedViewSortsByKey).filter( - (previousSortKey) => !sortKeys.includes(previousSortKey), - ); - const sortIdsToDelete = sortKeysToDelete.map( - (sortKeyToDelete) => savedViewSortsByKey[sortKeyToDelete].id ?? '', - ); - await deleteViewSorts(sortIdsToDelete); - set( - savedViewSortsScopedFamilyState({ - scopeId: viewScopeId, - familyKey: viewId ?? currentViewId, - }), - currentViewSorts, - ); - const existingViewId = viewId ?? currentViewId; - const existingView = views.find((view) => view.id === existingViewId); - - if (!existingView) { - return; - } - - modifyRecordFromCache(existingViewId, { - viewSorts: (viewSortsRef, { readField }) => { - const edges = readField<{ node: Reference }[]>( - 'edges', - viewSortsRef, - ); - - if (!edges) return viewSortsRef; - - return { - ...viewSortsRef, - edges: currentViewSorts.map((viewSort) => ({ - node: viewSort, - cursor: '', - })), - }; - }, - }); - }, - [ - apolloClient, - createOneRecordMutation, - deleteOneRecordMutation, - modifyRecordFromCache, - updateOneRecordMutation, - viewScopeId, - ], - ); - - const upsertViewSort = useRecoilCallback( - ({ snapshot, set }) => - (sortToUpsert: Sort) => { - const { currentViewId, onViewSortsChange, savedViewSortsByKey } = - getViewScopedStateValuesFromSnapshot({ - snapshot, - viewScopeId, - }); - - if (!currentViewId) { - return; - } - - if (!savedViewSortsByKey) { - return; - } - - const existingSavedSortId = - savedViewSortsByKey[sortToUpsert.fieldMetadataId]?.id; - - set(currentViewSortsState, (sorts) => { - const newViewSorts = produce(sorts, (sortsDraft) => { - const existingSortIndex = sortsDraft.findIndex( - (sort) => sort.fieldMetadataId === sortToUpsert.fieldMetadataId, - ); - - if (existingSortIndex === -1) { - sortsDraft.push({ ...sortToUpsert, id: existingSavedSortId }); - return sortsDraft; - } - - sortsDraft[existingSortIndex] = { - ...sortToUpsert, - id: existingSavedSortId, - }; - }); - onViewSortsChange?.(newViewSorts); - return newViewSorts; - }); - }, - [currentViewSortsState, viewScopeId], - ); - - const removeViewSort = useRecoilCallback( - ({ snapshot, set }) => - (fieldMetadataId: string) => { - const { currentViewId, onViewSortsChange, currentViewSorts } = - getViewScopedStateValuesFromSnapshot({ - snapshot, - viewScopeId, - }); - - if (!currentViewId) { - return; - } - - const newViewSorts = currentViewSorts.filter((filter) => { - return filter.fieldMetadataId !== fieldMetadataId; - }); - set(currentViewSortsState, newViewSorts); - onViewSortsChange?.(newViewSorts); - }, - [currentViewSortsState, viewScopeId], - ); - - return { persistViewSorts, upsertViewSort, removeViewSort }; -}; diff --git a/packages/twenty-front/src/modules/views/hooks/internal/useViewStates.ts b/packages/twenty-front/src/modules/views/hooks/internal/useViewStates.ts new file mode 100644 index 0000000000..f5a1a5307b --- /dev/null +++ b/packages/twenty-front/src/modules/views/hooks/internal/useViewStates.ts @@ -0,0 +1,96 @@ +import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId'; +import { extractComponentReadOnlySelector } from '@/ui/utilities/state/component-state/utils/extractComponentReadOnlySelector'; +import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState'; +import { availableFieldDefinitionsComponentState } from '@/views/states/availableFieldDefinitionsComponentState'; +import { availableFilterDefinitionsComponentState } from '@/views/states/availableFilterDefinitionsComponentState'; +import { availableSortDefinitionsComponentState } from '@/views/states/availableSortDefinitionsComponentState'; +import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState'; +import { entityCountInCurrentViewComponentState } from '@/views/states/entityCountInCurrentViewComponentState'; +import { isCurrentViewKeyIndexComponentState } from '@/views/states/isCurrentViewIndexComponentState'; +import { isPersistingViewFieldsComponentState } from '@/views/states/isPersistingViewFieldsComponentState'; +import { isViewBarExpandedComponentState } from '@/views/states/isViewBarExpandedComponentState'; +import { onCurrentViewChangeComponentState } from '@/views/states/onCurrentViewChangeComponentState'; +import { canPersistViewComponentSelector } from '@/views/states/selectors/canPersistViewComponentSelector'; +import { unsavedToDeleteViewFilterIdsComponentState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentState'; +import { unsavedToDeleteViewSortIdsComponentState } from '@/views/states/unsavedToDeleteViewSortIdsComponentState'; +import { unsavedToUpsertViewFiltersComponentState } from '@/views/states/unsavedToUpsertViewFiltersComponentState'; +import { unsavedToUpsertViewSortsComponentState } from '@/views/states/unsavedToUpsertViewSortsComponentState'; +import { viewEditModeComponentState } from '@/views/states/viewEditModeComponentState'; +import { viewObjectMetadataIdComponentState } from '@/views/states/viewObjectMetadataIdComponentState'; + +import { ViewScopeInternalContext } from '../../scopes/scope-internal-context/ViewScopeInternalContext'; + +export const useViewStates = (viewComponentId?: string) => { + const componentId = useAvailableScopeIdOrThrow( + ViewScopeInternalContext, + viewComponentId, + ); + + return { + componentId, + currentViewIdState: extractComponentState( + currentViewIdComponentState, + componentId, + ), + availableFieldDefinitionsState: extractComponentState( + availableFieldDefinitionsComponentState, + componentId, + ), + availableFilterDefinitionsState: extractComponentState( + availableFilterDefinitionsComponentState, + componentId, + ), + availableSortDefinitionsState: extractComponentState( + availableSortDefinitionsComponentState, + componentId, + ), + canPersistViewSelector: extractComponentReadOnlySelector( + canPersistViewComponentSelector, + componentId, + ), + isViewBarExpandedState: extractComponentState( + isViewBarExpandedComponentState, + componentId, + ), + onCurrentViewChangeState: extractComponentState( + onCurrentViewChangeComponentState, + componentId, + ), + entityCountInCurrentViewState: extractComponentState( + entityCountInCurrentViewComponentState, + componentId, + ), + viewEditModeState: extractComponentState( + viewEditModeComponentState, + componentId, + ), + viewObjectMetadataIdState: extractComponentState( + viewObjectMetadataIdComponentState, + componentId, + ), + unsavedToUpsertViewFiltersState: extractComponentState( + unsavedToUpsertViewFiltersComponentState, + componentId, + ), + unsavedToUpsertViewSortsState: extractComponentState( + unsavedToUpsertViewSortsComponentState, + componentId, + ), + unsavedToDeleteViewFilterIdsState: extractComponentState( + unsavedToDeleteViewFilterIdsComponentState, + componentId, + ), + unsavedToDeleteViewSortIdsState: extractComponentState( + unsavedToDeleteViewSortIdsComponentState, + componentId, + ), + isPersistingViewFieldsState: extractComponentState( + isPersistingViewFieldsComponentState, + componentId, + ), + isCurrentViewKeyIndexState: extractComponentState( + isCurrentViewKeyIndexComponentState, + componentId, + ), + }; +}; diff --git a/packages/twenty-front/src/modules/views/hooks/internal/useViews.ts b/packages/twenty-front/src/modules/views/hooks/internal/useViews.ts deleted file mode 100644 index 8bc05a85a7..0000000000 --- a/packages/twenty-front/src/modules/views/hooks/internal/useViews.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { useApolloClient } from '@apollo/client'; -import { useRecoilCallback } from 'recoil'; - -import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; -import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; -import { GraphQLView } from '@/views/types/GraphQLView'; -import { getViewScopedStateValuesFromSnapshot } from '@/views/utils/getViewScopedStateValuesFromSnapshot'; - -export const useViews = (scopeId: string) => { - const { - updateOneRecordMutation: updateOneMutation, - createOneRecordMutation: createOneMutation, - deleteOneRecordMutation: deleteOneMutation, - findManyRecordsQuery: findManyQuery, - } = useObjectMetadataItem({ - objectNameSingular: CoreObjectNameSingular.View, - }); - - const apolloClient = useApolloClient(); - - const createView = useRecoilCallback( - ({ snapshot }) => - async (view: Pick) => { - const { viewObjectMetadataId, viewType } = - getViewScopedStateValuesFromSnapshot({ - snapshot, - viewScopeId: scopeId, - }); - - if (!viewObjectMetadataId || !viewType) { - return; - } - await apolloClient.mutate({ - mutation: createOneMutation, - variables: { - input: { - id: view.id, - name: view.name, - objectMetadataId: viewObjectMetadataId, - type: viewType, - }, - }, - refetchQueries: [findManyQuery], - }); - }, - [scopeId, apolloClient, createOneMutation, findManyQuery], - ); - - const updateView = async (view: GraphQLView) => { - await apolloClient.mutate({ - mutation: updateOneMutation, - variables: { - idToUpdate: view.id, - input: { - id: view.id, - name: view.name, - isCompact: view.isCompact, - }, - }, - refetchQueries: [findManyQuery], - }); - }; - - const deleteView = async (viewId: string) => { - await apolloClient.mutate({ - mutation: deleteOneMutation, - variables: { - idToDelete: viewId, - }, - refetchQueries: [findManyQuery], - }); - }; - - return { - createView, - deleteView, - isFetchingViews: false, - updateView, - }; -}; diff --git a/packages/twenty-front/src/modules/views/hooks/useCombinedViewFilters.ts b/packages/twenty-front/src/modules/views/hooks/useCombinedViewFilters.ts new file mode 100644 index 0000000000..e3eceeed3e --- /dev/null +++ b/packages/twenty-front/src/modules/views/hooks/useCombinedViewFilters.ts @@ -0,0 +1,158 @@ +import { useRecoilCallback } from 'recoil'; +import { v4 } from 'uuid'; + +import { Filter } from '@/object-record/object-filter-dropdown/types/Filter'; +import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; +import { useViewStates } from '@/views/hooks/internal/useViewStates'; +import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache'; +import { ViewFilter } from '@/views/types/ViewFilter'; +import { isDefined } from '~/utils/isDefined'; + +export const useCombinedViewFilters = (viewBarComponentId?: string) => { + const { + unsavedToUpsertViewFiltersState, + unsavedToDeleteViewFilterIdsState, + currentViewIdState, + } = useViewStates(viewBarComponentId); + + const { getViewFromCache } = useGetViewFromCache(); + + const upsertCombinedViewFilter = useRecoilCallback( + ({ snapshot, set }) => + async (upsertedFilter: Filter) => { + const unsavedToUpsertViewFilters = getSnapshotValue( + snapshot, + unsavedToUpsertViewFiltersState, + ); + + const unsavedToDeleteViewFilterIds = getSnapshotValue( + snapshot, + unsavedToDeleteViewFilterIdsState, + ); + + const currentViewId = getSnapshotValue(snapshot, currentViewIdState); + + if (!currentViewId) { + return; + } + + const currentView = await getViewFromCache(currentViewId); + + if (!currentView) { + return; + } + + const matchingFilterInCurrentView = currentView.viewFilters.find( + (viewFilter) => + viewFilter.fieldMetadataId === upsertedFilter.fieldMetadataId, + ); + + const matchingFilterInUnsavedFilters = unsavedToUpsertViewFilters.find( + (viewFilter) => + viewFilter.fieldMetadataId === upsertedFilter.fieldMetadataId, + ); + + if (isDefined(matchingFilterInUnsavedFilters)) { + const updatedFilters = unsavedToUpsertViewFilters.map((viewFilter) => + viewFilter.id === matchingFilterInUnsavedFilters.id + ? { ...viewFilter, ...upsertedFilter } + : viewFilter, + ); + + set(unsavedToUpsertViewFiltersState, updatedFilters); + return; + } + + if (isDefined(matchingFilterInCurrentView)) { + set(unsavedToUpsertViewFiltersState, [ + ...unsavedToUpsertViewFilters, + { ...matchingFilterInCurrentView, ...upsertedFilter }, + ]); + set( + unsavedToDeleteViewFilterIdsState, + unsavedToDeleteViewFilterIds.filter( + (id) => id !== matchingFilterInCurrentView.id, + ), + ); + return; + } + + set(unsavedToUpsertViewFiltersState, [ + ...unsavedToUpsertViewFilters, + { + ...upsertedFilter, + id: v4(), + __typename: 'ViewFilter', + } satisfies ViewFilter, + ]); + }, + [ + currentViewIdState, + getViewFromCache, + unsavedToDeleteViewFilterIdsState, + unsavedToUpsertViewFiltersState, + ], + ); + const removeCombinedViewFilter = useRecoilCallback( + ({ snapshot, set }) => + async (fieldMetadataId: string) => { + const unsavedToUpsertViewFilters = getSnapshotValue( + snapshot, + unsavedToUpsertViewFiltersState, + ); + + const unsavedToDeleteViewFilterIds = getSnapshotValue( + snapshot, + unsavedToDeleteViewFilterIdsState, + ); + + const currentViewId = getSnapshotValue(snapshot, currentViewIdState); + + if (!currentViewId) { + return; + } + + const currentView = await getViewFromCache(currentViewId); + + if (!currentView) { + return; + } + + const matchingFilterInCurrentView = currentView.viewFilters.find( + (viewFilter) => viewFilter.fieldMetadataId === fieldMetadataId, + ); + + const matchingFilterInUnsavedFilters = unsavedToUpsertViewFilters.find( + (viewFilter) => viewFilter.fieldMetadataId === fieldMetadataId, + ); + + if (isDefined(matchingFilterInUnsavedFilters)) { + set( + unsavedToUpsertViewFiltersState, + unsavedToUpsertViewFilters.filter( + (viewFilter) => viewFilter.fieldMetadataId !== fieldMetadataId, + ), + ); + } + + if (isDefined(matchingFilterInCurrentView)) { + set(unsavedToDeleteViewFilterIdsState, [ + ...new Set([ + ...unsavedToDeleteViewFilterIds, + matchingFilterInCurrentView.id, + ]), + ]); + } + }, + [ + currentViewIdState, + getViewFromCache, + unsavedToDeleteViewFilterIdsState, + unsavedToUpsertViewFiltersState, + ], + ); + return { + upsertCombinedViewFilter, + removeCombinedViewFilter, + }; +}; diff --git a/packages/twenty-front/src/modules/views/hooks/useCombinedViewSorts.ts b/packages/twenty-front/src/modules/views/hooks/useCombinedViewSorts.ts new file mode 100644 index 0000000000..6f08d77b17 --- /dev/null +++ b/packages/twenty-front/src/modules/views/hooks/useCombinedViewSorts.ts @@ -0,0 +1,159 @@ +import { useRecoilCallback } from 'recoil'; +import { v4 } from 'uuid'; + +import { Sort } from '@/object-record/object-sort-dropdown/types/Sort'; +import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; +import { useViewStates } from '@/views/hooks/internal/useViewStates'; +import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache'; +import { ViewSort } from '@/views/types/ViewSort'; +import { isDefined } from '~/utils/isDefined'; + +export const useCombinedViewSorts = (viewBarComponentId?: string) => { + const { + unsavedToUpsertViewSortsState, + unsavedToDeleteViewSortIdsState, + currentViewIdState, + } = useViewStates(viewBarComponentId); + + const { getViewFromCache } = useGetViewFromCache(); + + const upsertCombinedViewSort = useRecoilCallback( + ({ snapshot, set }) => + async (upsertedSort: Sort) => { + const unsavedToUpsertViewSorts = getSnapshotValue( + snapshot, + unsavedToUpsertViewSortsState, + ); + + const unsavedToDeleteViewSortIds = getSnapshotValue( + snapshot, + unsavedToDeleteViewSortIdsState, + ); + + const currentViewId = getSnapshotValue(snapshot, currentViewIdState); + + if (!currentViewId) { + return; + } + + const currentView = await getViewFromCache(currentViewId); + + if (!currentView) { + return; + } + + const matchingSortInCurrentView = currentView.viewSorts.find( + (viewSort) => + viewSort.fieldMetadataId === upsertedSort.fieldMetadataId, + ); + + const matchingSortInUnsavedSorts = unsavedToUpsertViewSorts.find( + (viewSort) => + viewSort.fieldMetadataId === upsertedSort.fieldMetadataId, + ); + + if (isDefined(matchingSortInUnsavedSorts)) { + const updatedSorts = unsavedToUpsertViewSorts.map((viewSort) => + viewSort.id === matchingSortInUnsavedSorts.id + ? { ...viewSort, ...upsertedSort } + : viewSort, + ); + + set(unsavedToUpsertViewSortsState, updatedSorts); + return; + } + + if (isDefined(matchingSortInCurrentView)) { + set(unsavedToUpsertViewSortsState, [ + ...unsavedToUpsertViewSorts, + { ...matchingSortInCurrentView, ...upsertedSort }, + ]); + set( + unsavedToDeleteViewSortIdsState, + unsavedToDeleteViewSortIds.filter( + (id) => id !== matchingSortInCurrentView.id, + ), + ); + return; + } + + set(unsavedToUpsertViewSortsState, [ + ...unsavedToUpsertViewSorts, + { + ...upsertedSort, + id: v4(), + __typename: 'ViewSort', + } satisfies ViewSort, + ]); + }, + [ + currentViewIdState, + getViewFromCache, + unsavedToDeleteViewSortIdsState, + unsavedToUpsertViewSortsState, + ], + ); + const removeCombinedViewSort = useRecoilCallback( + ({ snapshot, set }) => + async (fieldMetadataId: string) => { + const unsavedToUpsertViewSorts = getSnapshotValue( + snapshot, + unsavedToUpsertViewSortsState, + ); + + const unsavedToDeleteViewSortIds = getSnapshotValue( + snapshot, + unsavedToDeleteViewSortIdsState, + ); + + const currentViewId = getSnapshotValue(snapshot, currentViewIdState); + + if (!currentViewId) { + return; + } + + const currentView = await getViewFromCache(currentViewId); + + if (!currentView) { + return; + } + + const matchingSortInCurrentView = currentView.viewSorts.find( + (viewSort) => viewSort.fieldMetadataId === fieldMetadataId, + ); + + const matchingSortInUnsavedSorts = unsavedToUpsertViewSorts.find( + (viewSort) => viewSort.fieldMetadataId === fieldMetadataId, + ); + + if (isDefined(matchingSortInUnsavedSorts)) { + set( + unsavedToUpsertViewSortsState, + unsavedToUpsertViewSorts.filter( + (viewSort) => viewSort.fieldMetadataId !== fieldMetadataId, + ), + ); + return; + } + + if (isDefined(matchingSortInCurrentView)) { + set(unsavedToDeleteViewSortIdsState, [ + ...new Set([ + ...unsavedToDeleteViewSortIds, + matchingSortInCurrentView.id, + ]), + ]); + } + }, + [ + currentViewIdState, + getViewFromCache, + unsavedToDeleteViewSortIdsState, + unsavedToUpsertViewSortsState, + ], + ); + return { + upsertCombinedViewSort, + removeCombinedViewSort, + }; +}; diff --git a/packages/twenty-front/src/modules/views/hooks/useGetCurrentView.ts b/packages/twenty-front/src/modules/views/hooks/useGetCurrentView.ts new file mode 100644 index 0000000000..e95a4f2cf2 --- /dev/null +++ b/packages/twenty-front/src/modules/views/hooks/useGetCurrentView.ts @@ -0,0 +1,107 @@ +import { useEffect } from 'react'; +import { useRecoilValue, useSetRecoilState } from 'recoil'; + +import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData'; +import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; +import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId'; +import { useViewStates } from '@/views/hooks/internal/useViewStates'; +import { ViewScopeInternalContext } from '@/views/scopes/scope-internal-context/ViewScopeInternalContext'; +import { GraphQLView } from '@/views/types/GraphQLView'; +import { combinedViewFilters } from '@/views/utils/combinedViewFilters'; +import { combinedViewSorts } from '@/views/utils/combinedViewSorts'; +import { isDefined } from '~/utils/isDefined'; + +export const useGetCurrentView = (viewBarComponentId?: string) => { + const componentId = useAvailableScopeIdOrThrow( + ViewScopeInternalContext, + viewBarComponentId, + ); + + const { records: views } = usePrefetchedData( + PrefetchKey.AllViews, + ); + + const { + currentViewIdState, + viewObjectMetadataIdState, + unsavedToUpsertViewFiltersState, + unsavedToDeleteViewFilterIdsState, + unsavedToDeleteViewSortIdsState, + unsavedToUpsertViewSortsState, + isCurrentViewKeyIndexState, + } = useViewStates(componentId); + + const currentViewId = useRecoilValue(currentViewIdState); + const viewObjectMetadataId = useRecoilValue(viewObjectMetadataIdState); + const setIsCurrentViewKeyIndex = useSetRecoilState( + isCurrentViewKeyIndexState, + ); + + const currentViewFromCurrentViewId = views.find( + (view) => view.id === currentViewId, + ); + const indexView = views.find( + (view) => + view.key === 'INDEX' && view.objectMetadataId === viewObjectMetadataId, + ); + + const currentView = currentViewId ? currentViewFromCurrentViewId : indexView; + + useEffect(() => { + setIsCurrentViewKeyIndex(currentView?.key === 'INDEX'); + }, [currentView, setIsCurrentViewKeyIndex]); + + const viewsOnCurrentObject = views + .filter((view) => view.objectMetadataId === viewObjectMetadataId) + .map((view) => ({ + id: view.id, + name: view.name, + type: view.type, + key: view.key, + objectMetadataId: view.objectMetadataId, + icon: view.icon, + })); + + const unsavedToUpsertViewFilters = useRecoilValue( + unsavedToUpsertViewFiltersState, + ); + const unsavedToUpsertViewSorts = useRecoilValue( + unsavedToUpsertViewSortsState, + ); + const unsavedToDeleteViewFilterIds = useRecoilValue( + unsavedToDeleteViewFilterIdsState, + ); + const unsavedToDeleteViewSortIds = useRecoilValue( + unsavedToDeleteViewSortIdsState, + ); + + if (!isDefined(currentView)) { + return { + componentId, + currentViewWithSavedFiltersAndSorts: undefined, + currentViewWithCombinedFiltersAndSorts: undefined, + viewsOnCurrentObject: viewsOnCurrentObject ?? [], + }; + } + + const currentViewWithCombinedFiltersAndSorts = { + ...currentView, + viewFilters: combinedViewFilters( + currentView.viewFilters, + unsavedToUpsertViewFilters, + unsavedToDeleteViewFilterIds, + ), + viewSorts: combinedViewSorts( + currentView.viewSorts, + unsavedToUpsertViewSorts, + unsavedToDeleteViewSortIds, + ), + }; + + return { + componentId, + currentViewWithSavedFiltersAndSorts: currentView, + currentViewWithCombinedFiltersAndSorts, + viewsOnCurrentObject: viewsOnCurrentObject ?? [], + }; +}; diff --git a/packages/twenty-front/src/modules/views/hooks/useGetViewFromCache.ts b/packages/twenty-front/src/modules/views/hooks/useGetViewFromCache.ts new file mode 100644 index 0000000000..b39e233800 --- /dev/null +++ b/packages/twenty-front/src/modules/views/hooks/useGetViewFromCache.ts @@ -0,0 +1,48 @@ +import { useCallback } from 'react'; +import { useApolloClient } from '@apollo/client'; + +import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; +import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; +import { ObjectRecordEdge } from '@/object-record/types/ObjectRecordEdge'; +import { GraphQLView } from '@/views/types/GraphQLView'; +import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull'; + +export const useGetViewFromCache = () => { + const client = useApolloClient(); + const cache = client.cache; + + const { getRecordFromCache } = useObjectMetadataItem({ + objectNameSingular: CoreObjectNameSingular.View, + }); + + const getViewFromCache = useCallback( + async (viewId: string) => { + // Todo Fix typing once we have figured out record connections + const viewWithConnections = getRecordFromCache(viewId, cache); + + if (isUndefinedOrNull(viewWithConnections)) { + return; + } + + const view = { + ...viewWithConnections, + viewFilters: viewWithConnections.viewFilters?.edges.map( + (edge: ObjectRecordEdge) => edge.node, + ), + viewSorts: viewWithConnections.viewSorts?.edges.map( + (edge: ObjectRecordEdge) => edge.node, + ), + viewFields: viewWithConnections.viewFields?.edges.map( + (edge: ObjectRecordEdge) => edge.node, + ), + } as GraphQLView; + + return view; + }, + [cache, getRecordFromCache], + ); + + return { + getViewFromCache, + }; +}; diff --git a/packages/twenty-front/src/modules/views/hooks/useHandleViews.ts b/packages/twenty-front/src/modules/views/hooks/useHandleViews.ts new file mode 100644 index 0000000000..2d24279f90 --- /dev/null +++ b/packages/twenty-front/src/modules/views/hooks/useHandleViews.ts @@ -0,0 +1,130 @@ +import { useCallback } from 'react'; +import { useSearchParams } from 'react-router-dom'; +import { useRecoilCallback } from 'recoil'; +import { v4 } from 'uuid'; + +import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; +import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord'; +import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord'; +import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; +import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; +import { usePersistViewFieldRecords } from '@/views/hooks/internal/usePersistViewFieldRecords'; +import { useViewStates } from '@/views/hooks/internal/useViewStates'; +import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache'; +import { useResetCurrentView } from '@/views/hooks/useResetCurrentView'; +import { GraphQLView } from '@/views/types/GraphQLView'; +import { isDefined } from '~/utils/isDefined'; +import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull'; + +export const useHandleViews = (viewBarComponentId?: string) => { + const { resetCurrentView } = useResetCurrentView(viewBarComponentId); + + const { currentViewIdState } = useViewStates(viewBarComponentId); + + const { getViewFromCache } = useGetViewFromCache(); + + const { deleteOneRecord } = useDeleteOneRecord({ + objectNameSingular: CoreObjectNameSingular.View, + }); + + const { createOneRecord } = useCreateOneRecord({ + objectNameSingular: CoreObjectNameSingular.View, + }); + + const { updateOneRecord } = useUpdateOneRecord({ + objectNameSingular: CoreObjectNameSingular.View, + }); + + const { createViewFieldRecords } = usePersistViewFieldRecords(); + + const createViewFromCurrent = useRecoilCallback(() => () => {}, []); + + const [_, setSearchParams] = useSearchParams(); + + const removeView = useRecoilCallback( + () => async (viewId: string) => { + await deleteOneRecord(viewId); + }, + [deleteOneRecord], + ); + + const createEmptyView = useRecoilCallback( + ({ snapshot }) => + async (id: string, name: string) => { + const currentViewId = getSnapshotValue(snapshot, currentViewIdState); + + if (!isDefined(currentViewId)) { + return; + } + + const view = await getViewFromCache(currentViewId); + + if (!isDefined(view)) { + return; + } + + const newView = await createOneRecord({ + id: id ?? v4(), + name: name, + objectMetadataId: view.objectMetadataId, + type: view.type, + }); + + if (isUndefinedOrNull(newView)) { + throw new Error('Failed to create view'); + } + + await createViewFieldRecords(view.viewFields, newView); + }, + [ + createOneRecord, + createViewFieldRecords, + currentViewIdState, + getViewFromCache, + ], + ); + + const changeViewInUrl = useCallback( + (viewId: string) => { + setSearchParams((previousSearchParams) => { + previousSearchParams.set('view', viewId); + return previousSearchParams; + }); + }, + [setSearchParams], + ); + + const selectView = useRecoilCallback( + ({ set }) => + async (viewId: string) => { + set(currentViewIdState, viewId); + changeViewInUrl(viewId); + resetCurrentView(); + }, + [changeViewInUrl, currentViewIdState, resetCurrentView], + ); + + const updateCurrentView = useRecoilCallback( + ({ snapshot }) => + async (view: Partial) => { + const currentViewId = snapshot + .getLoadable(currentViewIdState) + .getValue(); + if (isDefined(currentViewId)) { + await updateOneRecord({ + idToUpdate: currentViewId, + updateOneRecordInput: view, + }); + } + }, + [currentViewIdState, updateOneRecord], + ); + + return { + selectView, + updateCurrentView, + removeView, + createEmptyView, + createViewFromCurrent, + }; +}; diff --git a/packages/twenty-front/src/modules/views/hooks/useInitViewBar.ts b/packages/twenty-front/src/modules/views/hooks/useInitViewBar.ts new file mode 100644 index 0000000000..e818028468 --- /dev/null +++ b/packages/twenty-front/src/modules/views/hooks/useInitViewBar.ts @@ -0,0 +1,31 @@ +import { useSetRecoilState } from 'recoil'; + +import { useViewStates } from '@/views/hooks/internal/useViewStates'; + +export const useInitViewBar = (viewBarComponentId?: string) => { + const { + availableFieldDefinitionsState, + availableSortDefinitionsState, + availableFilterDefinitionsState, + viewObjectMetadataIdState, + } = useViewStates(viewBarComponentId); + + const setAvailableFieldDefinitions = useSetRecoilState( + availableFieldDefinitionsState, + ); + const setAvailableSortDefinitions = useSetRecoilState( + availableSortDefinitionsState, + ); + const setAvailableFilterDefinitions = useSetRecoilState( + availableFilterDefinitionsState, + ); + + const setViewObjectMetadataId = useSetRecoilState(viewObjectMetadataIdState); + + return { + setAvailableFieldDefinitions, + setAvailableSortDefinitions, + setAvailableFilterDefinitions, + setViewObjectMetadataId, + }; +}; diff --git a/packages/twenty-front/src/modules/views/hooks/useResetCurrentView.ts b/packages/twenty-front/src/modules/views/hooks/useResetCurrentView.ts new file mode 100644 index 0000000000..d188580ca3 --- /dev/null +++ b/packages/twenty-front/src/modules/views/hooks/useResetCurrentView.ts @@ -0,0 +1,32 @@ +import { useRecoilCallback } from 'recoil'; + +import { useViewStates } from '@/views/hooks/internal/useViewStates'; + +export const useResetCurrentView = (viewBarComponentId?: string) => { + const { + unsavedToDeleteViewSortIdsState, + unsavedToUpsertViewSortsState, + unsavedToDeleteViewFilterIdsState, + unsavedToUpsertViewFiltersState, + } = useViewStates(viewBarComponentId); + + const resetCurrentView = useRecoilCallback( + ({ set }) => + async () => { + set(unsavedToDeleteViewFilterIdsState, []); + set(unsavedToDeleteViewSortIdsState, []); + set(unsavedToUpsertViewFiltersState, []); + set(unsavedToUpsertViewSortsState, []); + }, + [ + unsavedToDeleteViewFilterIdsState, + unsavedToDeleteViewSortIdsState, + unsavedToUpsertViewFiltersState, + unsavedToUpsertViewSortsState, + ], + ); + + return { + resetCurrentView, + }; +}; diff --git a/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFields.ts b/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFields.ts new file mode 100644 index 0000000000..fed1518f1f --- /dev/null +++ b/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFields.ts @@ -0,0 +1,87 @@ +import { useRecoilCallback } from 'recoil'; + +import { usePersistViewFieldRecords } from '@/views/hooks/internal/usePersistViewFieldRecords'; +import { useViewStates } from '@/views/hooks/internal/useViewStates'; +import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache'; +import { ViewField } from '@/views/types/ViewField'; +import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; +import { isDefined } from '~/utils/isDefined'; +import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull'; + +export const useSaveCurrentViewFields = (viewBarComponentId?: string) => { + const { createViewFieldRecords, updateViewFieldRecords } = + usePersistViewFieldRecords(); + + const { getViewFromCache } = useGetViewFromCache(); + + const { isPersistingViewFieldsState, currentViewIdState } = + useViewStates(viewBarComponentId); + + const saveViewFields = useRecoilCallback( + ({ set, snapshot }) => + async (fields: ViewField[]) => { + const currentViewId = snapshot + .getLoadable(currentViewIdState) + .getValue(); + + if (!currentViewId) { + return; + } + + set(isPersistingViewFieldsState, true); + const view = await getViewFromCache(currentViewId); + + if (isUndefinedOrNull(view)) { + return; + } + + const viewFieldsToUpdate = fields + .map((field) => { + const existingField = view.viewFields.find( + (viewField) => viewField.id === field.id, + ); + + if (isUndefinedOrNull(existingField)) { + return undefined; + } + if ( + isDeeplyEqual( + { + position: existingField.position, + size: existingField.size, + isVisible: existingField.isVisible, + }, + { + position: field.position, + size: field.size, + isVisible: field.isVisible, + }, + ) + ) { + return undefined; + } + return field; + }) + .filter(isDefined); + + const viewFieldsToCreate = fields.filter((field) => !field.id); + + await Promise.all([ + createViewFieldRecords(viewFieldsToCreate, view), + updateViewFieldRecords(viewFieldsToUpdate), + ]); + set(isPersistingViewFieldsState, false); + }, + [ + createViewFieldRecords, + currentViewIdState, + getViewFromCache, + isPersistingViewFieldsState, + updateViewFieldRecords, + ], + ); + + return { + saveViewFields, + }; +}; diff --git a/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFiltersAndSorts.ts b/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFiltersAndSorts.ts new file mode 100644 index 0000000000..f351dc1c39 --- /dev/null +++ b/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFiltersAndSorts.ts @@ -0,0 +1,147 @@ +import { useRecoilCallback } from 'recoil'; + +import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; +import { usePersistViewFilterRecords } from '@/views/hooks/internal/usePersistViewFilterRecords'; +import { usePersistViewSortRecords } from '@/views/hooks/internal/usePersistViewSortRecords'; +import { useViewStates } from '@/views/hooks/internal/useViewStates'; +import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache'; +import { useResetCurrentView } from '@/views/hooks/useResetCurrentView'; +import { isDefined } from '~/utils/isDefined'; +import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull'; + +export const useSaveCurrentViewFiltersAndSorts = ( + viewBarComponentId?: string, +) => { + const { getViewFromCache } = useGetViewFromCache(); + + const { + unsavedToDeleteViewSortIdsState, + unsavedToUpsertViewSortsState, + unsavedToDeleteViewFilterIdsState, + unsavedToUpsertViewFiltersState, + currentViewIdState, + } = useViewStates(viewBarComponentId); + + const { + createViewSortRecords, + updateViewSortRecords, + deleteViewSortRecords, + } = usePersistViewSortRecords(); + + const { + createViewFilterRecords, + updateViewFilterRecords, + deleteViewFilterRecords, + } = usePersistViewFilterRecords(); + + const { resetCurrentView } = useResetCurrentView(viewBarComponentId); + + const saveViewSorts = useRecoilCallback( + ({ snapshot }) => + async (viewId: string) => { + const unsavedToDeleteViewSortIds = getSnapshotValue( + snapshot, + unsavedToDeleteViewSortIdsState, + ); + + const unsavedToUpsertViewSorts = getSnapshotValue( + snapshot, + unsavedToUpsertViewSortsState, + ); + + const view = await getViewFromCache(viewId); + + if (isUndefinedOrNull(view)) { + return; + } + + const viewSortsToCreate = unsavedToUpsertViewSorts.filter( + (viewSort) => + !view.viewSorts.some( + (vf) => vf.fieldMetadataId === viewSort.fieldMetadataId, + ), + ); + + const viewSortsToUpdate = unsavedToUpsertViewSorts.filter((viewSort) => + view.viewSorts.some((vf) => vf.id === viewSort.id), + ); + + await createViewSortRecords(viewSortsToCreate, view); + await updateViewSortRecords(viewSortsToUpdate); + await deleteViewSortRecords(unsavedToDeleteViewSortIds); + }, + [ + createViewSortRecords, + deleteViewSortRecords, + getViewFromCache, + unsavedToDeleteViewSortIdsState, + unsavedToUpsertViewSortsState, + updateViewSortRecords, + ], + ); + + const saveViewFilters = useRecoilCallback( + ({ snapshot }) => + async (viewId: string) => { + const unsavedToDeleteViewFilterIds = getSnapshotValue( + snapshot, + unsavedToDeleteViewFilterIdsState, + ); + + const unsavedToUpsertViewFilters = getSnapshotValue( + snapshot, + unsavedToUpsertViewFiltersState, + ); + + const view = await getViewFromCache(viewId); + + if (isUndefinedOrNull(view)) { + return; + } + + const viewFiltersToCreate = unsavedToUpsertViewFilters.filter( + (viewFilter) => + !view.viewFilters.some((vf) => vf.id === viewFilter.id), + ); + + const viewFiltersToUpdate = unsavedToUpsertViewFilters.filter( + (viewFilter) => + view.viewFilters.some((vf) => vf.id === viewFilter.id), + ); + + await createViewFilterRecords(viewFiltersToCreate, view); + await updateViewFilterRecords(viewFiltersToUpdate); + await deleteViewFilterRecords(unsavedToDeleteViewFilterIds); + }, + [ + createViewFilterRecords, + deleteViewFilterRecords, + getViewFromCache, + unsavedToDeleteViewFilterIdsState, + unsavedToUpsertViewFiltersState, + updateViewFilterRecords, + ], + ); + + const saveCurrentViewFilterAndSorts = useRecoilCallback( + ({ snapshot }) => + async () => { + const currentViewId = snapshot + .getLoadable(currentViewIdState) + .getValue(); + + if (!isDefined(currentViewId)) { + return; + } + + await saveViewFilters(currentViewId); + await saveViewSorts(currentViewId); + resetCurrentView(); + }, + [currentViewIdState, resetCurrentView, saveViewFilters, saveViewSorts], + ); + + return { + saveCurrentViewFilterAndSorts, + }; +}; diff --git a/packages/twenty-front/src/modules/views/hooks/useSetRecordCountInCurrentView.ts b/packages/twenty-front/src/modules/views/hooks/useSetRecordCountInCurrentView.ts new file mode 100644 index 0000000000..8deeece5a1 --- /dev/null +++ b/packages/twenty-front/src/modules/views/hooks/useSetRecordCountInCurrentView.ts @@ -0,0 +1,15 @@ +import { useSetRecoilState } from 'recoil'; + +import { useViewStates } from '@/views/hooks/internal/useViewStates'; + +export const useSetRecordCountInCurrentView = (viewBarComponentId?: string) => { + const { entityCountInCurrentViewState } = useViewStates(viewBarComponentId); + + const setEntityCountInCurrentView = useSetRecoilState( + entityCountInCurrentViewState, + ); + + return { + setRecordCountInCurrentView: setEntityCountInCurrentView, + }; +}; diff --git a/packages/twenty-front/src/modules/views/hooks/useViewBar.ts b/packages/twenty-front/src/modules/views/hooks/useViewBar.ts deleted file mode 100644 index ae114e12d9..0000000000 --- a/packages/twenty-front/src/modules/views/hooks/useViewBar.ts +++ /dev/null @@ -1,441 +0,0 @@ -import { useCallback } from 'react'; -import { useSearchParams } from 'react-router-dom'; -import { isNonEmptyString } from '@sniptt/guards'; -import { useRecoilCallback, useRecoilState, useSetRecoilState } from 'recoil'; -import { v4 } from 'uuid'; - -import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId'; -import { ViewField } from '@/views/types/ViewField'; -import { ViewFilter } from '@/views/types/ViewFilter'; -import { ViewSort } from '@/views/types/ViewSort'; -import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; -import { isDefined } from '~/utils/isDefined'; -import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull'; - -import { ViewScopeInternalContext } from '../scopes/scope-internal-context/ViewScopeInternalContext'; -import { currentViewFieldsScopedFamilyState } from '../states/currentViewFieldsScopedFamilyState'; -import { currentViewFiltersScopedFamilyState } from '../states/currentViewFiltersScopedFamilyState'; -import { currentViewSortsScopedFamilyState } from '../states/currentViewSortsScopedFamilyState'; -import { getViewScopedStatesFromSnapshot } from '../utils/getViewScopedStatesFromSnapshot'; -import { getViewScopedStateValuesFromSnapshot } from '../utils/getViewScopedStateValuesFromSnapshot'; - -import { useViewFields } from './internal/useViewFields'; -import { useViewFilters } from './internal/useViewFilters'; -import { useViews } from './internal/useViews'; -import { useViewScopedStates } from './internal/useViewScopedStates'; -import { useViewSorts } from './internal/useViewSorts'; - -type UseViewProps = { - viewBarId?: string; -}; - -export const useViewBar = (props?: UseViewProps) => { - const scopeId = useAvailableScopeIdOrThrow( - ViewScopeInternalContext, - props?.viewBarId, - ); - - const { - currentViewFiltersState, - currentViewIdState, - currentViewSortsState, - viewEditModeState, - availableFieldDefinitionsState, - availableFilterDefinitionsState, - availableSortDefinitionsState, - entityCountInCurrentViewState, - viewObjectMetadataIdState, - } = useViewScopedStates({ - viewScopeId: scopeId, - }); - - const { persistViewSorts, upsertViewSort, removeViewSort } = - useViewSorts(scopeId); - const { persistViewFilters, upsertViewFilter, removeViewFilter } = - useViewFilters(scopeId); - const { persistViewFields } = useViewFields(scopeId); - const { - createView: internalCreateView, - updateView: internalUpdateView, - deleteView: internalDeleteView, - } = useViews(scopeId); - - const [currentViewId, setCurrentViewId] = useRecoilState(currentViewIdState); - - const setAvailableFieldDefinitions = useSetRecoilState( - availableFieldDefinitionsState, - ); - - const setAvailableSortDefinitions = useSetRecoilState( - availableSortDefinitionsState, - ); - - const setAvailableFilterDefinitions = useSetRecoilState( - availableFilterDefinitionsState, - ); - - const setEntityCountInCurrentView = useSetRecoilState( - entityCountInCurrentViewState, - ); - - const setViewEditMode = useSetRecoilState(viewEditModeState); - const setViewObjectMetadataId = useSetRecoilState(viewObjectMetadataIdState); - - const [_, setSearchParams] = useSearchParams(); - - const changeViewInUrl = useCallback( - (viewId: string) => { - setSearchParams((previousSearchParams) => { - previousSearchParams.set('view', viewId); - return previousSearchParams; - }); - }, - [setSearchParams], - ); - - const loadViewFields = useRecoilCallback( - ({ snapshot, set }) => - async (viewFields: ViewField[], currentViewId: string) => { - const { - availableFieldDefinitions, - onViewFieldsChange, - savedViewFields, - isPersistingView, - } = getViewScopedStateValuesFromSnapshot({ - snapshot, - viewScopeId: scopeId, - viewId: currentViewId, - }); - - const { savedViewFieldsState, currentViewFieldsState } = - getViewScopedStatesFromSnapshot({ - snapshot, - viewScopeId: scopeId, - viewId: currentViewId, - }); - - if (isUndefinedOrNull(availableFieldDefinitions)) { - return; - } - - const queriedViewFields = viewFields.filter(isDefined); - - if (isPersistingView) { - return; - } - - if (!isDeeplyEqual(savedViewFields, queriedViewFields)) { - set(currentViewFieldsState, queriedViewFields); - set(savedViewFieldsState, queriedViewFields); - } - - onViewFieldsChange?.(queriedViewFields); - }, - [scopeId], - ); - - const loadViewFilters = useRecoilCallback( - ({ snapshot, set }) => - async (viewFilters: ViewFilter[], currentViewId: string) => { - const { - availableFilterDefinitions, - savedViewFilters, - onViewFiltersChange, - } = getViewScopedStateValuesFromSnapshot({ - snapshot, - viewScopeId: scopeId, - viewId: currentViewId, - }); - - const { savedViewFiltersState, currentViewFiltersState } = - getViewScopedStatesFromSnapshot({ - snapshot, - viewScopeId: scopeId, - viewId: currentViewId, - }); - - if (isUndefinedOrNull(availableFilterDefinitions)) { - return; - } - - const queriedViewFilters = viewFilters - .map((viewFilter) => { - const availableFilterDefinition = availableFilterDefinitions.find( - (filterDefinition) => - filterDefinition.fieldMetadataId === viewFilter.fieldMetadataId, - ); - - if (!availableFilterDefinition) return null; - - return { - ...viewFilter, - displayValue: viewFilter.displayValue ?? viewFilter.value, - definition: availableFilterDefinition, - }; - }) - .filter(isDefined); - - if (!isDeeplyEqual(savedViewFilters, queriedViewFilters)) { - set(savedViewFiltersState, queriedViewFilters); - set(currentViewFiltersState, queriedViewFilters); - } - onViewFiltersChange?.(queriedViewFilters); - }, - [scopeId], - ); - - const loadViewSorts = useRecoilCallback( - ({ snapshot, set }) => - async (viewSorts: Required[], currentViewId: string) => { - const { availableSortDefinitions, savedViewSorts, onViewSortsChange } = - getViewScopedStateValuesFromSnapshot({ - snapshot, - viewScopeId: scopeId, - viewId: currentViewId, - }); - - const { savedViewSortsState, currentViewSortsState } = - getViewScopedStatesFromSnapshot({ - snapshot, - viewScopeId: scopeId, - viewId: currentViewId, - }); - - if (!availableSortDefinitions || !currentViewId) { - return; - } - - const queriedViewSorts = viewSorts - .map((viewSort) => { - const availableSortDefinition = availableSortDefinitions.find( - (sort) => sort.fieldMetadataId === viewSort.fieldMetadataId, - ); - - if (!availableSortDefinition) return null; - - return { - id: viewSort.id, - fieldMetadataId: viewSort.fieldMetadataId, - direction: viewSort.direction, - definition: availableSortDefinition, - }; - }) - .filter(isDefined); - - if (!isDeeplyEqual(savedViewSorts, queriedViewSorts)) { - set(savedViewSortsState, queriedViewSorts); - set(currentViewSortsState, queriedViewSorts); - } - onViewSortsChange?.(queriedViewSorts); - }, - [scopeId], - ); - - const loadView = useRecoilCallback( - ({ snapshot }) => - (viewId: string) => { - setCurrentViewId?.(viewId); - - const { currentView, onViewTypeChange, onViewCompactModeChange } = - getViewScopedStateValuesFromSnapshot({ - snapshot, - viewScopeId: scopeId, - viewId, - }); - - if (!currentView) { - return; - } - - onViewTypeChange?.(currentView.type); - onViewCompactModeChange?.(currentView.isCompact); - loadViewFields(currentView.viewFields, viewId); - loadViewFilters(currentView.viewFilters, viewId); - loadViewSorts(currentView.viewSorts, viewId); - }, - [setCurrentViewId, scopeId, loadViewFields, loadViewFilters, loadViewSorts], - ); - - const resetViewBar = useRecoilCallback( - ({ snapshot, set }) => - () => { - const { - savedViewFilters, - savedViewSorts, - onViewFiltersChange, - onViewSortsChange, - } = getViewScopedStateValuesFromSnapshot({ - snapshot, - viewScopeId: scopeId, - }); - - if (isDefined(savedViewFilters)) { - set(currentViewFiltersState, savedViewFilters); - onViewFiltersChange?.(savedViewFilters); - } - if (isDefined(savedViewSorts)) { - set(currentViewSortsState, savedViewSorts); - onViewSortsChange?.(savedViewSorts); - } - - set(viewEditModeState, 'none'); - }, - [ - currentViewFiltersState, - currentViewSortsState, - scopeId, - viewEditModeState, - ], - ); - - const createView = useRecoilCallback( - ({ snapshot, set }) => - async (name: string) => { - const newViewId = v4(); - await internalCreateView({ id: newViewId, name }); - - const { currentViewFields, currentViewFilters, currentViewSorts } = - getViewScopedStateValuesFromSnapshot({ - snapshot, - viewScopeId: scopeId, - }); - - set( - currentViewFieldsScopedFamilyState({ scopeId, familyKey: newViewId }), - currentViewFields, - ); - - set( - currentViewFiltersScopedFamilyState({ - scopeId, - familyKey: newViewId, - }), - currentViewFilters, - ); - - set( - currentViewSortsScopedFamilyState({ - scopeId, - familyKey: newViewId, - }), - currentViewSorts, - ); - - await persistViewFields(currentViewFields, newViewId); - await persistViewFilters(newViewId); - await persistViewSorts(newViewId); - - changeViewInUrl(newViewId); - }, - [ - changeViewInUrl, - internalCreateView, - persistViewFields, - persistViewFilters, - persistViewSorts, - scopeId, - ], - ); - - const updateCurrentView = async () => { - await persistViewFilters(); - await persistViewSorts(); - }; - - const removeView = useRecoilCallback( - ({ set, snapshot }) => - async (viewIdToDelete: string) => { - const { currentViewId } = getViewScopedStateValuesFromSnapshot({ - snapshot, - viewScopeId: scopeId, - }); - - const { currentViewIdState, viewsState } = - getViewScopedStatesFromSnapshot({ - snapshot, - viewScopeId: scopeId, - }); - - if (currentViewId === viewIdToDelete) { - set(currentViewIdState, undefined); - } - - set(viewsState, (previousViews) => - previousViews.filter((view) => view.id !== viewIdToDelete), - ); - - internalDeleteView(viewIdToDelete); - - if (currentViewId === viewIdToDelete) { - setSearchParams(); - } - }, - [internalDeleteView, scopeId, setSearchParams], - ); - - const handleViewNameSubmit = useRecoilCallback( - ({ snapshot }) => - async (name?: string) => { - if (!name) { - return; - } - - const { viewEditMode, currentView } = - getViewScopedStateValuesFromSnapshot({ - snapshot, - viewScopeId: scopeId, - }); - - if (!currentView) { - return; - } - - if (viewEditMode === 'create' && isNonEmptyString(name)) { - await createView(name); - - // Temporary to force refetch - await internalUpdateView({ - ...currentView, - }); - } else { - await internalUpdateView({ - ...currentView, - name, - }); - } - }, - [createView, internalUpdateView, scopeId], - ); - - return { - scopeId, - currentViewId, - - setCurrentViewId, - updateCurrentView, - createView, - removeView, - resetViewBar, - handleViewNameSubmit, - - setViewEditMode, - setViewObjectMetadataId, - setEntityCountInCurrentView, - setAvailableFieldDefinitions, - - setAvailableSortDefinitions, - upsertViewSort, - removeViewSort, - - setAvailableFilterDefinitions, - upsertViewFilter, - removeViewFilter, - - persistViewFields, - changeViewInUrl, - loadView, - loadViewFields, - loadViewFilters, - loadViewSorts, - }; -}; diff --git a/packages/twenty-front/src/modules/views/hooks/useViewBarEditMode.ts b/packages/twenty-front/src/modules/views/hooks/useViewBarEditMode.ts new file mode 100644 index 0000000000..b24c2e7461 --- /dev/null +++ b/packages/twenty-front/src/modules/views/hooks/useViewBarEditMode.ts @@ -0,0 +1,14 @@ +import { useRecoilState } from 'recoil'; + +import { useViewStates } from '@/views/hooks/internal/useViewStates'; + +export const useViewBarEditMode = (viewBarComponentId?: string) => { + const { viewEditModeState } = useViewStates(viewBarComponentId); + + const [viewEditMode, setViewEditMode] = useRecoilState(viewEditModeState); + + return { + viewEditMode, + setViewEditMode, + }; +}; diff --git a/packages/twenty-front/src/modules/views/scopes/ViewScope.tsx b/packages/twenty-front/src/modules/views/scopes/ViewScope.tsx index 2f83a18238..e70372fab5 100644 --- a/packages/twenty-front/src/modules/views/scopes/ViewScope.tsx +++ b/packages/twenty-front/src/modules/views/scopes/ViewScope.tsx @@ -1,10 +1,6 @@ import { ReactNode } from 'react'; -import { ViewFilter } from '@/views/types/ViewFilter'; -import { ViewSort } from '@/views/types/ViewSort'; -import { ViewType } from '@/views/types/ViewType'; - -import { ViewField } from '../types/ViewField'; +import { GraphQLView } from '@/views/types/GraphQLView'; import { ViewScopeInitEffect } from './init-effect/ViewScopeInitEffect'; import { ViewScopeInternalContext } from './scope-internal-context/ViewScopeInternalContext'; @@ -12,23 +8,13 @@ import { ViewScopeInternalContext } from './scope-internal-context/ViewScopeInte type ViewScopeProps = { children: ReactNode; viewScopeId: string; - onViewSortsChange?: (sorts: ViewSort[]) => void | Promise; - onViewFiltersChange?: (filters: ViewFilter[]) => void | Promise; - onViewFieldsChange?: (fields: ViewField[]) => void | Promise; - onViewTypeChange?: (viewType: ViewType) => void | Promise; - onViewCompactModeChange?: ( - isCompactModeActive: boolean, - ) => void | Promise; + onCurrentViewChange: (view: GraphQLView | undefined) => void | Promise; }; export const ViewScope = ({ children, viewScopeId, - onViewSortsChange, - onViewFiltersChange, - onViewFieldsChange, - onViewTypeChange, - onViewCompactModeChange, + onCurrentViewChange, }: ViewScopeProps) => { return ( {children} diff --git a/packages/twenty-front/src/modules/views/scopes/init-effect/ViewScopeInitEffect.tsx b/packages/twenty-front/src/modules/views/scopes/init-effect/ViewScopeInitEffect.tsx index 2452eab20d..330c270d8f 100644 --- a/packages/twenty-front/src/modules/views/scopes/init-effect/ViewScopeInitEffect.tsx +++ b/packages/twenty-front/src/modules/views/scopes/init-effect/ViewScopeInitEffect.tsx @@ -1,64 +1,24 @@ import { useEffect } from 'react'; import { useSetRecoilState } from 'recoil'; -import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates'; -import { ViewField } from '@/views/types/ViewField'; -import { ViewFilter } from '@/views/types/ViewFilter'; -import { ViewSort } from '@/views/types/ViewSort'; -import { ViewType } from '@/views/types/ViewType'; +import { useViewStates } from '@/views/hooks/internal/useViewStates'; +import { GraphQLView } from '@/views/types/GraphQLView'; type ViewScopeInitEffectProps = { viewScopeId: string; - onViewSortsChange?: (sorts: ViewSort[]) => void | Promise; - onViewFiltersChange?: (filters: ViewFilter[]) => void | Promise; - onViewFieldsChange?: (fields: ViewField[]) => void | Promise; - onViewTypeChange?: (viewType: ViewType) => void | Promise; - onViewCompactModeChange?: ( - isCompactModeActive: boolean, - ) => void | Promise; + onCurrentViewChange: (view: GraphQLView | undefined) => void | Promise; }; export const ViewScopeInitEffect = ({ - onViewSortsChange, - onViewFiltersChange, - onViewFieldsChange, - onViewTypeChange, - onViewCompactModeChange, + onCurrentViewChange, }: ViewScopeInitEffectProps) => { - const { - onViewFieldsChangeState, - onViewFiltersChangeState, - onViewSortsChangeState, - onViewTypeChangeState, - onViewCompactModeChangeState, - } = useViewScopedStates(); + const { onCurrentViewChangeState } = useViewStates(); - const setOnViewSortsChange = useSetRecoilState(onViewSortsChangeState); - const setOnViewFiltersChange = useSetRecoilState(onViewFiltersChangeState); - const setOnViewFieldsChange = useSetRecoilState(onViewFieldsChangeState); - const setOnViewTypeChange = useSetRecoilState(onViewTypeChangeState); - const setOnViewCompactModeChange = useSetRecoilState( - onViewCompactModeChangeState, - ); + const setOnCurrentViewChange = useSetRecoilState(onCurrentViewChangeState); useEffect(() => { - setOnViewSortsChange(() => onViewSortsChange); - setOnViewFiltersChange(() => onViewFiltersChange); - setOnViewFieldsChange(() => onViewFieldsChange); - setOnViewTypeChange(() => onViewTypeChange); - setOnViewCompactModeChange(() => onViewCompactModeChange); - }, [ - onViewCompactModeChange, - onViewFieldsChange, - onViewFiltersChange, - onViewSortsChange, - onViewTypeChange, - setOnViewCompactModeChange, - setOnViewFieldsChange, - setOnViewFiltersChange, - setOnViewSortsChange, - setOnViewTypeChange, - ]); + setOnCurrentViewChange(() => onCurrentViewChange); + }, [onCurrentViewChange, setOnCurrentViewChange]); return <>; }; diff --git a/packages/twenty-front/src/modules/views/states/availableFieldDefinitionsScopedState.ts b/packages/twenty-front/src/modules/views/states/availableFieldDefinitionsComponentState.ts similarity index 72% rename from packages/twenty-front/src/modules/views/states/availableFieldDefinitionsScopedState.ts rename to packages/twenty-front/src/modules/views/states/availableFieldDefinitionsComponentState.ts index 39e08739fa..9f11648305 100644 --- a/packages/twenty-front/src/modules/views/states/availableFieldDefinitionsScopedState.ts +++ b/packages/twenty-front/src/modules/views/states/availableFieldDefinitionsComponentState.ts @@ -2,9 +2,9 @@ import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata' import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition'; import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; -export const availableFieldDefinitionsScopedState = createComponentState< +export const availableFieldDefinitionsComponentState = createComponentState< ColumnDefinition[] >({ - key: 'availableFieldDefinitionsScopedState', + key: 'availableFieldDefinitionsComponentState', defaultValue: [], }); diff --git a/packages/twenty-front/src/modules/views/states/availableFilterDefinitionsScopedState.ts b/packages/twenty-front/src/modules/views/states/availableFilterDefinitionsComponentState.ts similarity index 66% rename from packages/twenty-front/src/modules/views/states/availableFilterDefinitionsScopedState.ts rename to packages/twenty-front/src/modules/views/states/availableFilterDefinitionsComponentState.ts index 8433868e1b..9a3f649ea4 100644 --- a/packages/twenty-front/src/modules/views/states/availableFilterDefinitionsScopedState.ts +++ b/packages/twenty-front/src/modules/views/states/availableFilterDefinitionsComponentState.ts @@ -1,9 +1,9 @@ import { FilterDefinition } from '@/object-record/object-filter-dropdown/types/FilterDefinition'; import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; -export const availableFilterDefinitionsScopedState = createComponentState< +export const availableFilterDefinitionsComponentState = createComponentState< FilterDefinition[] >({ - key: 'availableFilterDefinitionsScopedState', + key: 'availableFilterDefinitionsComponentState', defaultValue: [], }); diff --git a/packages/twenty-front/src/modules/views/states/availableSortDefinitionsScopedState.ts b/packages/twenty-front/src/modules/views/states/availableSortDefinitionsComponentState.ts similarity index 66% rename from packages/twenty-front/src/modules/views/states/availableSortDefinitionsScopedState.ts rename to packages/twenty-front/src/modules/views/states/availableSortDefinitionsComponentState.ts index ad93c30925..9281f1d757 100644 --- a/packages/twenty-front/src/modules/views/states/availableSortDefinitionsScopedState.ts +++ b/packages/twenty-front/src/modules/views/states/availableSortDefinitionsComponentState.ts @@ -1,9 +1,9 @@ import { SortDefinition } from '@/object-record/object-sort-dropdown/types/SortDefinition'; import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; -export const availableSortDefinitionsScopedState = createComponentState< +export const availableSortDefinitionsComponentState = createComponentState< SortDefinition[] >({ - key: 'availableSortDefinitionsScopedState', + key: 'availableSortDefinitionsComponentState', defaultValue: [], }); diff --git a/packages/twenty-front/src/modules/views/states/currentViewFieldsScopedFamilyState.ts b/packages/twenty-front/src/modules/views/states/currentViewFieldsScopedFamilyState.ts deleted file mode 100644 index 2e73a4f2a5..0000000000 --- a/packages/twenty-front/src/modules/views/states/currentViewFieldsScopedFamilyState.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { createComponentFamilyState } from '@/ui/utilities/state/component-state/utils/createComponentFamilyState'; - -import { ViewField } from '../types/ViewField'; - -export const currentViewFieldsScopedFamilyState = createComponentFamilyState< - ViewField[], - string ->({ - key: 'currentViewFieldsScopedFamilyState', - defaultValue: [], -}); diff --git a/packages/twenty-front/src/modules/views/states/currentViewFiltersScopedFamilyState.ts b/packages/twenty-front/src/modules/views/states/currentViewFiltersScopedFamilyState.ts deleted file mode 100644 index 8365c3a021..0000000000 --- a/packages/twenty-front/src/modules/views/states/currentViewFiltersScopedFamilyState.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { createComponentFamilyState } from '@/ui/utilities/state/component-state/utils/createComponentFamilyState'; - -import { ViewFilter } from '../types/ViewFilter'; - -export const currentViewFiltersScopedFamilyState = createComponentFamilyState< - ViewFilter[], - string ->({ - key: 'currentViewFiltersScopedFamilyState', - defaultValue: [], -}); diff --git a/packages/twenty-front/src/modules/views/states/currentViewIdScopedState.ts b/packages/twenty-front/src/modules/views/states/currentViewIdComponentState.ts similarity index 60% rename from packages/twenty-front/src/modules/views/states/currentViewIdScopedState.ts rename to packages/twenty-front/src/modules/views/states/currentViewIdComponentState.ts index 806a02384e..799ba48005 100644 --- a/packages/twenty-front/src/modules/views/states/currentViewIdScopedState.ts +++ b/packages/twenty-front/src/modules/views/states/currentViewIdComponentState.ts @@ -1,8 +1,8 @@ import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; -export const currentViewIdScopedState = createComponentState< +export const currentViewIdComponentState = createComponentState< string | undefined >({ - key: 'currentViewIdScopedState', + key: 'currentViewIdComponentState', defaultValue: undefined, }); diff --git a/packages/twenty-front/src/modules/views/states/currentViewSortsScopedFamilyState.ts b/packages/twenty-front/src/modules/views/states/currentViewSortsScopedFamilyState.ts deleted file mode 100644 index bb209e6d01..0000000000 --- a/packages/twenty-front/src/modules/views/states/currentViewSortsScopedFamilyState.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { createComponentFamilyState } from '@/ui/utilities/state/component-state/utils/createComponentFamilyState'; - -import { ViewSort } from '../types/ViewSort'; - -export const currentViewSortsScopedFamilyState = createComponentFamilyState< - ViewSort[], - string ->({ - key: 'currentViewSortsScopedFamilyState', - defaultValue: [], -}); diff --git a/packages/twenty-front/src/modules/views/states/entityCountInCurrentViewComponentState.ts b/packages/twenty-front/src/modules/views/states/entityCountInCurrentViewComponentState.ts new file mode 100644 index 0000000000..02a42b251b --- /dev/null +++ b/packages/twenty-front/src/modules/views/states/entityCountInCurrentViewComponentState.ts @@ -0,0 +1,7 @@ +import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; + +export const entityCountInCurrentViewComponentState = + createComponentState({ + key: 'entityCountInCurrentViewComponentState', + defaultValue: 0, + }); diff --git a/packages/twenty-front/src/modules/views/states/entityCountInCurrentViewScopedState.ts b/packages/twenty-front/src/modules/views/states/entityCountInCurrentViewScopedState.ts deleted file mode 100644 index e78260b1e6..0000000000 --- a/packages/twenty-front/src/modules/views/states/entityCountInCurrentViewScopedState.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; - -export const entityCountInCurrentViewScopedState = createComponentState( - { - key: 'entityCountInCurrentViewScopedState', - defaultValue: 0, - }, -); diff --git a/packages/twenty-front/src/modules/views/states/isCurrentViewIndexComponentState.ts b/packages/twenty-front/src/modules/views/states/isCurrentViewIndexComponentState.ts new file mode 100644 index 0000000000..ee3252d368 --- /dev/null +++ b/packages/twenty-front/src/modules/views/states/isCurrentViewIndexComponentState.ts @@ -0,0 +1,7 @@ +import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; + +export const isCurrentViewKeyIndexComponentState = + createComponentState({ + key: 'isCurrentViewKeyIndexComponentState', + defaultValue: true, + }); diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/isObjectFilterDropdownOperandSelectUnfoldedScopedState.ts b/packages/twenty-front/src/modules/views/states/isPersistingViewFieldsComponentState.ts similarity index 55% rename from packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/isObjectFilterDropdownOperandSelectUnfoldedScopedState.ts rename to packages/twenty-front/src/modules/views/states/isPersistingViewFieldsComponentState.ts index 5fc86fa889..60cfdd2c05 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/isObjectFilterDropdownOperandSelectUnfoldedScopedState.ts +++ b/packages/twenty-front/src/modules/views/states/isPersistingViewFieldsComponentState.ts @@ -1,7 +1,7 @@ import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; -export const isObjectFilterDropdownOperandSelectUnfoldedScopedState = +export const isPersistingViewFieldsComponentState = createComponentState({ - key: 'isObjectFilterDropdownOperandSelectUnfoldedScopedState', + key: 'isPersistingViewFieldsComponentState', defaultValue: false, }); diff --git a/packages/twenty-front/src/modules/views/states/isPersistingViewScopedState.ts b/packages/twenty-front/src/modules/views/states/isPersistingViewScopedState.ts deleted file mode 100644 index ad648dc44e..0000000000 --- a/packages/twenty-front/src/modules/views/states/isPersistingViewScopedState.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; - -export const isPersistingViewScopedState = createComponentState({ - key: 'isPersistingViewScopedState', - defaultValue: false, -}); diff --git a/packages/twenty-front/src/modules/views/states/isViewBarExpandedScopedState.ts b/packages/twenty-front/src/modules/views/states/isViewBarExpandedComponentState.ts similarity index 51% rename from packages/twenty-front/src/modules/views/states/isViewBarExpandedScopedState.ts rename to packages/twenty-front/src/modules/views/states/isViewBarExpandedComponentState.ts index c809b40872..9742ce77e3 100644 --- a/packages/twenty-front/src/modules/views/states/isViewBarExpandedScopedState.ts +++ b/packages/twenty-front/src/modules/views/states/isViewBarExpandedComponentState.ts @@ -1,6 +1,6 @@ import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; -export const isViewBarExpandedScopedState = createComponentState({ - key: 'isViewBarExpandedScopedState', +export const isViewBarExpandedComponentState = createComponentState({ + key: 'isViewBarExpandedComponentState', defaultValue: true, }); diff --git a/packages/twenty-front/src/modules/views/states/noneScopedFamilyState.ts b/packages/twenty-front/src/modules/views/states/noneScopedFamilyState.ts deleted file mode 100644 index 8e8f45838c..0000000000 --- a/packages/twenty-front/src/modules/views/states/noneScopedFamilyState.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { createComponentFamilyState } from '@/ui/utilities/state/component-state/utils/createComponentFamilyState'; - -export const noneScopedFamilyState = createComponentFamilyState({ - key: 'noneScopedFamilyState', - defaultValue: null, -}); diff --git a/packages/twenty-front/src/modules/views/states/onCurrentViewChangeComponentState.ts b/packages/twenty-front/src/modules/views/states/onCurrentViewChangeComponentState.ts new file mode 100644 index 0000000000..06b503c486 --- /dev/null +++ b/packages/twenty-front/src/modules/views/states/onCurrentViewChangeComponentState.ts @@ -0,0 +1,9 @@ +import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; +import { GraphQLView } from '@/views/types/GraphQLView'; + +export const onCurrentViewChangeComponentState = createComponentState< + ((view: GraphQLView | undefined) => void | Promise) | undefined +>({ + key: 'onCurrentViewChangeComponentState', + defaultValue: undefined, +}); diff --git a/packages/twenty-front/src/modules/views/states/onViewCompactModeChangeScopeState.ts b/packages/twenty-front/src/modules/views/states/onViewCompactModeChangeScopeState.ts deleted file mode 100644 index 267682f96b..0000000000 --- a/packages/twenty-front/src/modules/views/states/onViewCompactModeChangeScopeState.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; - -export const onViewCompactModeChangeScopeState = createComponentState< - ((isCompactModeActive: boolean) => void | Promise) | undefined ->({ - key: 'onViewCompactModeChangeScopeState', - defaultValue: undefined, -}); diff --git a/packages/twenty-front/src/modules/views/states/onViewFieldsChangeScopedState.ts b/packages/twenty-front/src/modules/views/states/onViewFieldsChangeScopedState.ts deleted file mode 100644 index e7e002f35a..0000000000 --- a/packages/twenty-front/src/modules/views/states/onViewFieldsChangeScopedState.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; - -import { ViewField } from '../types/ViewField'; - -export const onViewFieldsChangeScopedState = createComponentState< - ((fields: ViewField[]) => void | Promise) | undefined ->({ - key: 'onViewFieldsChangeScopedState', - defaultValue: undefined, -}); diff --git a/packages/twenty-front/src/modules/views/states/onViewFiltersChangeScopedState.ts b/packages/twenty-front/src/modules/views/states/onViewFiltersChangeScopedState.ts deleted file mode 100644 index 2e16b7ab48..0000000000 --- a/packages/twenty-front/src/modules/views/states/onViewFiltersChangeScopedState.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; -import { ViewFilter } from '@/views/types/ViewFilter'; - -export const onViewFiltersChangeScopedState = createComponentState< - ((filters: ViewFilter[]) => void | Promise) | undefined ->({ - key: 'onViewFiltersChangeScopedState', - defaultValue: undefined, -}); diff --git a/packages/twenty-front/src/modules/views/states/onViewSortsChangeScopedState.ts b/packages/twenty-front/src/modules/views/states/onViewSortsChangeScopedState.ts deleted file mode 100644 index 551c165de6..0000000000 --- a/packages/twenty-front/src/modules/views/states/onViewSortsChangeScopedState.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; -import { ViewSort } from '@/views/types/ViewSort'; - -export const onViewSortsChangeScopedState = createComponentState< - ((sorts: ViewSort[]) => void | Promise) | undefined ->({ - key: 'onViewSortsChangeScopedState', - defaultValue: undefined, -}); diff --git a/packages/twenty-front/src/modules/views/states/onViewTypeChangeScopedState.ts b/packages/twenty-front/src/modules/views/states/onViewTypeChangeScopedState.ts deleted file mode 100644 index b48c3f29e8..0000000000 --- a/packages/twenty-front/src/modules/views/states/onViewTypeChangeScopedState.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; -import { ViewType } from '@/views/types/ViewType'; - -export const onViewTypeChangeScopedState = createComponentState< - ((viewType: ViewType) => void | Promise) | undefined ->({ - key: 'onViewTypeChangeScopedState', - defaultValue: undefined, -}); diff --git a/packages/twenty-front/src/modules/views/states/savedViewFieldsScopedFamilyState.ts b/packages/twenty-front/src/modules/views/states/savedViewFieldsScopedFamilyState.ts deleted file mode 100644 index d0fd3ddac4..0000000000 --- a/packages/twenty-front/src/modules/views/states/savedViewFieldsScopedFamilyState.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { createComponentFamilyState } from '@/ui/utilities/state/component-state/utils/createComponentFamilyState'; - -import { ViewField } from '../types/ViewField'; - -export const savedViewFieldsScopedFamilyState = createComponentFamilyState< - ViewField[], - string ->({ - key: 'savedViewFieldsScopedFamilyState', - defaultValue: [], -}); diff --git a/packages/twenty-front/src/modules/views/states/savedViewFiltersScopedFamilyState.ts b/packages/twenty-front/src/modules/views/states/savedViewFiltersScopedFamilyState.ts deleted file mode 100644 index cc90fa73de..0000000000 --- a/packages/twenty-front/src/modules/views/states/savedViewFiltersScopedFamilyState.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { createComponentFamilyState } from '@/ui/utilities/state/component-state/utils/createComponentFamilyState'; - -import { ViewFilter } from '../types/ViewFilter'; - -export const savedViewFiltersScopedFamilyState = createComponentFamilyState< - ViewFilter[], - string ->({ - key: 'savedViewFiltersScopedFamilyState', - defaultValue: [], -}); diff --git a/packages/twenty-front/src/modules/views/states/savedViewSortsScopedFamilyState.ts b/packages/twenty-front/src/modules/views/states/savedViewSortsScopedFamilyState.ts deleted file mode 100644 index a6d0eceb55..0000000000 --- a/packages/twenty-front/src/modules/views/states/savedViewSortsScopedFamilyState.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { createComponentFamilyState } from '@/ui/utilities/state/component-state/utils/createComponentFamilyState'; - -import { ViewSort } from '../types/ViewSort'; - -export const savedViewSortsScopedFamilyState = createComponentFamilyState< - ViewSort[], - string ->({ - key: 'savedViewSortsScopedFamilyState', - defaultValue: [], -}); diff --git a/packages/twenty-front/src/modules/views/states/selectors/canPersistViewComponentSelector.ts b/packages/twenty-front/src/modules/views/states/selectors/canPersistViewComponentSelector.ts new file mode 100644 index 0000000000..2d28c57359 --- /dev/null +++ b/packages/twenty-front/src/modules/views/states/selectors/canPersistViewComponentSelector.ts @@ -0,0 +1,21 @@ +import { selectorFamily } from 'recoil'; + +import { unsavedToDeleteViewFilterIdsComponentState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentState'; +import { unsavedToDeleteViewSortIdsComponentState } from '@/views/states/unsavedToDeleteViewSortIdsComponentState'; +import { unsavedToUpsertViewFiltersComponentState } from '@/views/states/unsavedToUpsertViewFiltersComponentState'; +import { unsavedToUpsertViewSortsComponentState } from '@/views/states/unsavedToUpsertViewSortsComponentState'; + +export const canPersistViewComponentSelector = selectorFamily({ + key: 'canPersistViewComponentSelector', + get: + ({ scopeId }: { scopeId: string }) => + ({ get }) => { + return ( + get(unsavedToUpsertViewFiltersComponentState({ scopeId })).length > 0 || + get(unsavedToUpsertViewSortsComponentState({ scopeId })).length > 0 || + get(unsavedToDeleteViewFilterIdsComponentState({ scopeId })).length > + 0 || + get(unsavedToDeleteViewSortIdsComponentState({ scopeId })).length > 0 + ); + }, +}); diff --git a/packages/twenty-front/src/modules/views/states/selectors/canPersistViewFiltersScopedFamilySelector.ts b/packages/twenty-front/src/modules/views/states/selectors/canPersistViewFiltersScopedFamilySelector.ts deleted file mode 100644 index b13e6041d3..0000000000 --- a/packages/twenty-front/src/modules/views/states/selectors/canPersistViewFiltersScopedFamilySelector.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { selectorFamily } from 'recoil'; - -import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; - -import { currentViewFiltersScopedFamilyState } from '../currentViewFiltersScopedFamilyState'; -import { savedViewFiltersScopedFamilyState } from '../savedViewFiltersScopedFamilyState'; - -export const canPersistViewFiltersScopedFamilySelector = selectorFamily({ - key: 'canPersistFiltersScopedFamilySelector', - get: - ({ viewScopeId, viewId }: { viewScopeId: string; viewId?: string }) => - ({ get }) => { - if (!viewId) { - return; - } - - return !isDeeplyEqual( - get( - savedViewFiltersScopedFamilyState({ - scopeId: viewScopeId, - familyKey: viewId, - }), - ), - get( - currentViewFiltersScopedFamilyState({ - scopeId: viewScopeId, - familyKey: viewId, - }), - ), - ); - }, -}); diff --git a/packages/twenty-front/src/modules/views/states/selectors/canPersistViewSortsScopedFamilySelector.ts b/packages/twenty-front/src/modules/views/states/selectors/canPersistViewSortsScopedFamilySelector.ts deleted file mode 100644 index 37020a7d1b..0000000000 --- a/packages/twenty-front/src/modules/views/states/selectors/canPersistViewSortsScopedFamilySelector.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { selectorFamily } from 'recoil'; - -import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; - -import { currentViewSortsScopedFamilyState } from '../currentViewSortsScopedFamilyState'; -import { savedViewSortsScopedFamilyState } from '../savedViewSortsScopedFamilyState'; - -export const canPersistViewSortsScopedFamilySelector = selectorFamily({ - key: 'canPersistSortsScopedFamilySelector', - get: - ({ viewScopeId, viewId }: { viewScopeId: string; viewId?: string }) => - ({ get }) => { - if (!viewId) { - return; - } - return !isDeeplyEqual( - get( - savedViewSortsScopedFamilyState({ - scopeId: viewScopeId, - familyKey: viewId, - }), - ), - get( - currentViewSortsScopedFamilyState({ - scopeId: viewScopeId, - familyKey: viewId, - }), - ), - ); - }, -}); diff --git a/packages/twenty-front/src/modules/views/states/selectors/canResetViewComponentSelector.ts b/packages/twenty-front/src/modules/views/states/selectors/canResetViewComponentSelector.ts new file mode 100644 index 0000000000..5ad2bd408d --- /dev/null +++ b/packages/twenty-front/src/modules/views/states/selectors/canResetViewComponentSelector.ts @@ -0,0 +1,22 @@ +import { selectorFamily } from 'recoil'; + +import { unsavedToDeleteViewFilterIdsComponentState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentState'; +import { unsavedToDeleteViewSortIdsComponentState } from '@/views/states/unsavedToDeleteViewSortIdsComponentState'; +import { unsavedToUpsertViewFiltersComponentState } from '@/views/states/unsavedToUpsertViewFiltersComponentState'; +import { unsavedToUpsertViewSortsComponentState } from '@/views/states/unsavedToUpsertViewSortsComponentState'; + +export const canResetViewComponentSelector = selectorFamily({ + key: 'canResetViewComponentSelector', + get: + ({ scopeId }: { scopeId: string }) => + ({ get }) => { + return ( + get(unsavedToUpsertViewFiltersComponentState({ scopeId })).length === + 0 && + get(unsavedToUpsertViewSortsComponentState({ scopeId })).length === 0 && + get(unsavedToDeleteViewFilterIdsComponentState({ scopeId })).length === + 0 && + get(unsavedToDeleteViewSortIdsComponentState({ scopeId })).length === 0 + ); + }, +}); diff --git a/packages/twenty-front/src/modules/views/states/selectors/currentViewComponentSelector.ts b/packages/twenty-front/src/modules/views/states/selectors/currentViewComponentSelector.ts deleted file mode 100644 index 7f8770d6c9..0000000000 --- a/packages/twenty-front/src/modules/views/states/selectors/currentViewComponentSelector.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { createComponentReadOnlySelector } from '@/ui/utilities/state/component-state/utils/createComponentReadOnlySelector'; -import { GraphQLView } from '@/views/types/GraphQLView'; - -import { currentViewIdScopedState } from '../currentViewIdScopedState'; - -import { viewsByIdScopedSelector } from './viewsByIdScopedSelector'; - -export const currentViewComponentSelector = createComponentReadOnlySelector< - GraphQLView | undefined ->({ - key: 'currentViewScopedSelector', - get: - ({ scopeId }: { scopeId: string }) => - ({ get }) => { - const currentViewId = get(currentViewIdScopedState({ scopeId: scopeId })); - - return currentViewId - ? get(viewsByIdScopedSelector(scopeId))[currentViewId] - : undefined; - }, -}); diff --git a/packages/twenty-front/src/modules/views/states/selectors/savedViewFieldByKeyScopedFamilySelector.ts b/packages/twenty-front/src/modules/views/states/selectors/savedViewFieldByKeyScopedFamilySelector.ts deleted file mode 100644 index fc56e7fdee..0000000000 --- a/packages/twenty-front/src/modules/views/states/selectors/savedViewFieldByKeyScopedFamilySelector.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { selectorFamily } from 'recoil'; - -import { ViewField } from '@/views/types/ViewField'; - -import { savedViewFieldsScopedFamilyState } from '../savedViewFieldsScopedFamilyState'; - -export const savedViewFieldByKeyScopedFamilySelector = selectorFamily({ - key: 'savedViewFieldByKeyScopedFamilySelector', - get: - ({ - viewScopeId, - viewId, - }: { - viewScopeId: string; - viewId: string | undefined; - }) => - ({ get }) => { - if (viewId === undefined) { - return undefined; - } - - return get( - savedViewFieldsScopedFamilyState({ - scopeId: viewScopeId, - familyKey: viewId, - }), - ).reduce>( - (result, column) => ({ ...result, [column.fieldMetadataId]: column }), - {}, - ); - }, -}); diff --git a/packages/twenty-front/src/modules/views/states/selectors/savedViewFiltersByKeyScopedFamilySelector.ts b/packages/twenty-front/src/modules/views/states/selectors/savedViewFiltersByKeyScopedFamilySelector.ts deleted file mode 100644 index 235d5375f6..0000000000 --- a/packages/twenty-front/src/modules/views/states/selectors/savedViewFiltersByKeyScopedFamilySelector.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { selectorFamily } from 'recoil'; - -import { ViewFilter } from '@/views/types/ViewFilter'; - -import { savedViewFiltersScopedFamilyState } from '../savedViewFiltersScopedFamilyState'; - -export const savedViewFiltersByKeyScopedFamilySelector = selectorFamily({ - key: 'savedViewFiltersByKeyScopedFamilySelector', - get: - ({ scopeId, viewId }: { scopeId: string; viewId: string | undefined }) => - ({ get }) => { - if (viewId === undefined) { - return undefined; - } - return get( - savedViewFiltersScopedFamilyState({ - scopeId: scopeId, - familyKey: viewId, - }), - ).reduce>( - (result, filter) => ({ ...result, [filter.fieldMetadataId]: filter }), - {}, - ); - }, -}); diff --git a/packages/twenty-front/src/modules/views/states/selectors/savedViewSortsByKeyScopedFamilySelector.ts b/packages/twenty-front/src/modules/views/states/selectors/savedViewSortsByKeyScopedFamilySelector.ts deleted file mode 100644 index 2348464d40..0000000000 --- a/packages/twenty-front/src/modules/views/states/selectors/savedViewSortsByKeyScopedFamilySelector.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { selectorFamily } from 'recoil'; - -import { ViewSort } from '@/views/types/ViewSort'; - -import { savedViewSortsScopedFamilyState } from '../savedViewSortsScopedFamilyState'; - -export const savedViewSortsByKeyScopedFamilySelector = selectorFamily({ - key: 'savedViewSortsByKeyScopedFamilySelector', - get: - ({ scopeId, viewId }: { scopeId: string; viewId: string | undefined }) => - ({ get }) => { - if (viewId === undefined) { - return undefined; - } - return get( - savedViewSortsScopedFamilyState({ - scopeId: scopeId, - familyKey: viewId, - }), - ).reduce>( - (result, sort) => ({ ...result, [sort.fieldMetadataId]: sort }), - {}, - ); - }, -}); diff --git a/packages/twenty-front/src/modules/views/states/selectors/savedViewSortsFamilySelector.ts b/packages/twenty-front/src/modules/views/states/selectors/savedViewSortsFamilySelector.ts deleted file mode 100644 index ee0a983530..0000000000 --- a/packages/twenty-front/src/modules/views/states/selectors/savedViewSortsFamilySelector.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { selectorFamily } from 'recoil'; - -import { savedViewSortsScopedFamilyState } from '../savedViewSortsScopedFamilyState'; - -export const savedViewSortsFamilySelector = selectorFamily({ - key: 'savedViewSortsFamilySelector', - get: - ({ scopeId, viewId }: { scopeId: string; viewId: string }) => - ({ get }) => - get( - savedViewSortsScopedFamilyState({ - scopeId: scopeId, - familyKey: viewId, - }), - ), -}); diff --git a/packages/twenty-front/src/modules/views/states/selectors/viewsByIdScopedSelector.ts b/packages/twenty-front/src/modules/views/states/selectors/viewsByIdScopedSelector.ts deleted file mode 100644 index 0ec9d89192..0000000000 --- a/packages/twenty-front/src/modules/views/states/selectors/viewsByIdScopedSelector.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { selectorFamily } from 'recoil'; - -import { GraphQLView } from '@/views/types/GraphQLView'; - -import { viewsScopedState } from '../viewsScopedState'; - -export const viewsByIdScopedSelector = selectorFamily< - Record, - string ->({ - key: 'viewsByIdScopedSelector', - get: - (scopeId) => - ({ get }) => - get(viewsScopedState({ scopeId: scopeId })).reduce< - Record - >((result, view) => ({ ...result, [view.id]: view }), {}), -}); diff --git a/packages/twenty-front/src/modules/views/states/unsavedToDeleteViewFilterIdsComponentState.ts b/packages/twenty-front/src/modules/views/states/unsavedToDeleteViewFilterIdsComponentState.ts new file mode 100644 index 0000000000..60b89afbbb --- /dev/null +++ b/packages/twenty-front/src/modules/views/states/unsavedToDeleteViewFilterIdsComponentState.ts @@ -0,0 +1,8 @@ +import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; + +export const unsavedToDeleteViewFilterIdsComponentState = createComponentState< + string[] +>({ + key: 'unsavedToDeleteViewFilterIdsComponentState', + defaultValue: [], +}); diff --git a/packages/twenty-front/src/modules/views/states/unsavedToDeleteViewSortIdsComponentState.ts b/packages/twenty-front/src/modules/views/states/unsavedToDeleteViewSortIdsComponentState.ts new file mode 100644 index 0000000000..bb44082bf8 --- /dev/null +++ b/packages/twenty-front/src/modules/views/states/unsavedToDeleteViewSortIdsComponentState.ts @@ -0,0 +1,8 @@ +import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; + +export const unsavedToDeleteViewSortIdsComponentState = createComponentState< + string[] +>({ + key: 'unsavedToDeleteViewSortIdsComponentState', + defaultValue: [], +}); diff --git a/packages/twenty-front/src/modules/views/states/unsavedToUpsertViewFiltersComponentState.ts b/packages/twenty-front/src/modules/views/states/unsavedToUpsertViewFiltersComponentState.ts new file mode 100644 index 0000000000..108ad08479 --- /dev/null +++ b/packages/twenty-front/src/modules/views/states/unsavedToUpsertViewFiltersComponentState.ts @@ -0,0 +1,10 @@ +import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; + +import { ViewFilter } from '../types/ViewFilter'; + +export const unsavedToUpsertViewFiltersComponentState = createComponentState< + ViewFilter[] +>({ + key: 'unsavedToUpsertViewFiltersComponentState', + defaultValue: [], +}); diff --git a/packages/twenty-front/src/modules/views/states/unsavedToUpsertViewSortsComponentState.ts b/packages/twenty-front/src/modules/views/states/unsavedToUpsertViewSortsComponentState.ts new file mode 100644 index 0000000000..57fa5f0b9a --- /dev/null +++ b/packages/twenty-front/src/modules/views/states/unsavedToUpsertViewSortsComponentState.ts @@ -0,0 +1,10 @@ +import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; + +import { ViewSort } from '../types/ViewSort'; + +export const unsavedToUpsertViewSortsComponentState = createComponentState< + ViewSort[] +>({ + key: 'unsavedToUpsertViewSortsComponentState', + defaultValue: [], +}); diff --git a/packages/twenty-front/src/modules/views/states/viewEditModeScopedState.ts b/packages/twenty-front/src/modules/views/states/viewEditModeComponentState.ts similarity index 62% rename from packages/twenty-front/src/modules/views/states/viewEditModeScopedState.ts rename to packages/twenty-front/src/modules/views/states/viewEditModeComponentState.ts index 638502faf4..ffd30511a3 100644 --- a/packages/twenty-front/src/modules/views/states/viewEditModeScopedState.ts +++ b/packages/twenty-front/src/modules/views/states/viewEditModeComponentState.ts @@ -1,8 +1,8 @@ import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; -export const viewEditModeScopedState = createComponentState< +export const viewEditModeComponentState = createComponentState< 'none' | 'edit' | 'create' >({ - key: 'viewEditModeScopedState', + key: 'viewEditModeComponentState', defaultValue: 'none', }); diff --git a/packages/twenty-front/src/modules/views/states/viewObjectMetadataIdScopeState.ts b/packages/twenty-front/src/modules/views/states/viewObjectMetadataIdComponentState.ts similarity index 57% rename from packages/twenty-front/src/modules/views/states/viewObjectMetadataIdScopeState.ts rename to packages/twenty-front/src/modules/views/states/viewObjectMetadataIdComponentState.ts index 12e397f558..a20cbb9016 100644 --- a/packages/twenty-front/src/modules/views/states/viewObjectMetadataIdScopeState.ts +++ b/packages/twenty-front/src/modules/views/states/viewObjectMetadataIdComponentState.ts @@ -1,8 +1,8 @@ import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; -export const viewObjectMetadataIdScopeState = createComponentState< +export const viewObjectMetadataIdComponentState = createComponentState< string | undefined >({ - key: 'viewObjectMetadataIdScopeState', + key: 'viewObjectMetadataIdComponentState', defaultValue: undefined, }); diff --git a/packages/twenty-front/src/modules/views/states/viewTypeScopedState.ts b/packages/twenty-front/src/modules/views/states/viewTypeScopedState.ts deleted file mode 100644 index 899166dd8b..0000000000 --- a/packages/twenty-front/src/modules/views/states/viewTypeScopedState.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; - -import { ViewType } from '../types/ViewType'; - -export const viewTypeScopedState = createComponentState({ - key: 'viewTypeScopedState', - defaultValue: ViewType.Table, -}); diff --git a/packages/twenty-front/src/modules/views/states/viewsScopedState.ts b/packages/twenty-front/src/modules/views/states/viewsScopedState.ts deleted file mode 100644 index 6186528b83..0000000000 --- a/packages/twenty-front/src/modules/views/states/viewsScopedState.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; -import { GraphQLView } from '@/views/types/GraphQLView'; - -export const viewsScopedState = createComponentState({ - key: 'viewsScopedState', - defaultValue: [], -}); diff --git a/packages/twenty-front/src/modules/views/types/ViewField.ts b/packages/twenty-front/src/modules/views/types/ViewField.ts index 0e1d44bb4f..708f2b0343 100644 --- a/packages/twenty-front/src/modules/views/types/ViewField.ts +++ b/packages/twenty-front/src/modules/views/types/ViewField.ts @@ -3,6 +3,7 @@ import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata' import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition'; export type ViewField = { + __typename: 'ViewField'; id: string; fieldMetadataId: string; position: number; diff --git a/packages/twenty-front/src/modules/views/types/ViewFilter.ts b/packages/twenty-front/src/modules/views/types/ViewFilter.ts index 793357ce7c..1a21b111f0 100644 --- a/packages/twenty-front/src/modules/views/types/ViewFilter.ts +++ b/packages/twenty-front/src/modules/views/types/ViewFilter.ts @@ -1,12 +1,13 @@ -import { FilterDefinition } from '@/object-record/object-filter-dropdown/types/FilterDefinition'; - import { ViewFilterOperand } from './ViewFilterOperand'; export type ViewFilter = { + __typename: 'ViewFilter'; id: string; fieldMetadataId: string; operand: ViewFilterOperand; value: string; displayValue: string; - definition: FilterDefinition; + createdAt?: string; + updatedAt?: string; + viewId?: string; }; diff --git a/packages/twenty-front/src/modules/views/types/ViewSort.ts b/packages/twenty-front/src/modules/views/types/ViewSort.ts index c88aaa13a5..67d48fc59e 100644 --- a/packages/twenty-front/src/modules/views/types/ViewSort.ts +++ b/packages/twenty-front/src/modules/views/types/ViewSort.ts @@ -1,9 +1,8 @@ -import { SortDefinition } from '@/object-record/object-sort-dropdown/types/SortDefinition'; import { SortDirection } from '@/object-record/object-sort-dropdown/types/SortDirection'; export type ViewSort = { + __typename: 'ViewSort'; id: string; fieldMetadataId: string; direction: SortDirection; - definition: SortDefinition; }; diff --git a/packages/twenty-front/src/modules/views/utils/__tests__/viewMapFunctions.test.ts b/packages/twenty-front/src/modules/views/utils/__tests__/viewMapFunctions.test.ts index da0a276684..a1c0b58193 100644 --- a/packages/twenty-front/src/modules/views/utils/__tests__/viewMapFunctions.test.ts +++ b/packages/twenty-front/src/modules/views/utils/__tests__/viewMapFunctions.test.ts @@ -12,7 +12,7 @@ import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters'; import { mapViewSortsToSorts } from '@/views/utils/mapViewSortsToSorts'; const baseDefinition = { - fieldMetadataId: 'fieldMetadataId', + fieldMetadataId: '05731f68-6e7a-4903-8374-c0b6a9063482', label: 'label', iconName: 'iconName', }; @@ -21,20 +21,22 @@ describe('mapViewSortsToSorts', () => { it('should map each ViewSort object to a corresponding Sort object', () => { const viewSorts: ViewSort[] = [ { + __typename: 'ViewSort', id: 'id', - fieldMetadataId: 'fieldMetadataId', + fieldMetadataId: '05731f68-6e7a-4903-8374-c0b6a9063482', direction: 'asc', - definition: baseDefinition, }, ]; const expectedSorts: Sort[] = [ { - fieldMetadataId: 'fieldMetadataId', + fieldMetadataId: '05731f68-6e7a-4903-8374-c0b6a9063482', direction: 'asc', definition: baseDefinition, }, ]; - expect(mapViewSortsToSorts(viewSorts)).toEqual(expectedSorts); + expect(mapViewSortsToSorts(viewSorts, [baseDefinition])).toEqual( + expectedSorts, + ); }); }); @@ -42,20 +44,17 @@ describe('mapViewFiltersToFilters', () => { it('should map each ViewFilter object to a corresponding Filter object', () => { const viewFilters: ViewFilter[] = [ { + __typename: 'ViewFilter', id: 'id', - fieldMetadataId: '1', + fieldMetadataId: '05731f68-6e7a-4903-8374-c0b6a9063482', value: 'testValue', displayValue: 'Test Display Value', operand: ViewFilterOperand.Is, - definition: { - ...baseDefinition, - type: 'FULL_NAME', - }, }, ]; const expectedFilters: Filter[] = [ { - fieldMetadataId: '1', + fieldMetadataId: '05731f68-6e7a-4903-8374-c0b6a9063482', value: 'testValue', displayValue: 'Test Display Value', operand: ViewFilterOperand.Is, @@ -65,7 +64,14 @@ describe('mapViewFiltersToFilters', () => { }, }, ]; - expect(mapViewFiltersToFilters(viewFilters)).toEqual(expectedFilters); + expect( + mapViewFiltersToFilters(viewFilters, [ + { + ...baseDefinition, + type: 'FULL_NAME', + }, + ]), + ).toEqual(expectedFilters); }); }); @@ -73,6 +79,7 @@ describe('mapViewFieldsToColumnDefinitions', () => { it('should map visible ViewFields to ColumnDefinitions and filter out missing fieldMetadata', () => { const viewFields: ViewField[] = [ { + __typename: 'ViewField', id: '1', fieldMetadataId: '1', position: 1, @@ -92,6 +99,7 @@ describe('mapViewFieldsToColumnDefinitions', () => { }, }, { + __typename: 'ViewField', id: '2', fieldMetadataId: '2', position: 2, @@ -111,6 +119,7 @@ describe('mapViewFieldsToColumnDefinitions', () => { }, }, { + __typename: 'ViewField', id: '3', fieldMetadataId: '3', position: 3, @@ -209,13 +218,16 @@ describe('mapColumnDefinitionsToViewFields', () => { const expectedViewFields = [ { + __typename: 'ViewField', id: 'custom-id-1', fieldMetadataId: 1, position: 1, isVisible: true, definition: columnDefinitions[0], + size: undefined, }, { + __typename: 'ViewField', id: '', fieldMetadataId: 2, position: 2, diff --git a/packages/twenty-front/src/modules/views/utils/combinedViewFilters.ts b/packages/twenty-front/src/modules/views/utils/combinedViewFilters.ts new file mode 100644 index 0000000000..ac33a83f39 --- /dev/null +++ b/packages/twenty-front/src/modules/views/utils/combinedViewFilters.ts @@ -0,0 +1,34 @@ +import { ViewFilter } from '@/views/types/ViewFilter'; + +export const combinedViewFilters = ( + viewFilter: ViewFilter[], + toUpsertViewFilters: ViewFilter[], + toDeleteViewFilterIds: string[], +): ViewFilter[] => { + const toCreateViewFilters = toUpsertViewFilters.filter( + (toUpsertViewFilter) => + !viewFilter.some((viewFilter) => viewFilter.id === toUpsertViewFilter.id), + ); + + const toUpdateViewFilters = toUpsertViewFilters.filter((toUpsertViewFilter) => + viewFilter.some((viewFilter) => viewFilter.id === toUpsertViewFilter.id), + ); + + const combinedViewFilters = viewFilter + .filter((viewFilter) => !toDeleteViewFilterIds.includes(viewFilter.id)) + .map((viewFilter) => { + const toUpdateViewFilter = toUpdateViewFilters.find( + (toUpdateViewFilter) => toUpdateViewFilter.id === viewFilter.id, + ); + + return toUpdateViewFilter ?? viewFilter; + }) + .concat(toCreateViewFilters); + + return Object.values( + combinedViewFilters.reduce( + (acc, obj) => ({ ...acc, [obj.fieldMetadataId]: obj }), + {}, + ), + ); +}; diff --git a/packages/twenty-front/src/modules/views/utils/combinedViewSorts.ts b/packages/twenty-front/src/modules/views/utils/combinedViewSorts.ts new file mode 100644 index 0000000000..c0fad726aa --- /dev/null +++ b/packages/twenty-front/src/modules/views/utils/combinedViewSorts.ts @@ -0,0 +1,34 @@ +import { ViewSort } from '@/views/types/ViewSort'; + +export const combinedViewSorts = ( + viewSort: ViewSort[], + toUpsertViewSorts: ViewSort[], + toDeleteViewSortIds: string[], +): ViewSort[] => { + const toCreateViewSorts = toUpsertViewSorts.filter( + (toUpsertViewSort) => + !viewSort.some((viewSort) => viewSort.id === toUpsertViewSort.id), + ); + + const toUpdateViewSorts = toUpsertViewSorts.filter((toUpsertViewSort) => + viewSort.some((viewSort) => viewSort.id === toUpsertViewSort.id), + ); + + const combinedViewSorts = viewSort + .filter((viewSort) => !toDeleteViewSortIds.includes(viewSort.id)) + .map((viewSort) => { + const toUpdateViewSort = toUpdateViewSorts.find( + (toUpdateViewSort) => toUpdateViewSort.id === viewSort.id, + ); + + return toUpdateViewSort ?? viewSort; + }) + .concat(toCreateViewSorts); + + return Object.values( + combinedViewSorts.reduce( + (acc, obj) => ({ ...acc, [obj.fieldMetadataId]: obj }), + {}, + ), + ); +}; diff --git a/packages/twenty-front/src/modules/views/utils/getViewScopedStateValuesFromSnapshot.ts b/packages/twenty-front/src/modules/views/utils/getViewScopedStateValuesFromSnapshot.ts deleted file mode 100644 index 3d7b749f01..0000000000 --- a/packages/twenty-front/src/modules/views/utils/getViewScopedStateValuesFromSnapshot.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { Snapshot } from 'recoil'; - -import { getScopedStateDeprecated } from '@/ui/utilities/recoil-scope/utils/getScopedStateDeprecated'; -import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; - -import { UNDEFINED_FAMILY_ITEM_ID } from '../constants'; -import { currentViewIdScopedState } from '../states/currentViewIdScopedState'; - -import { getViewScopedStates } from './internal/getViewScopedStates'; - -export const getViewScopedStateValuesFromSnapshot = ({ - snapshot, - viewScopeId, - viewId, -}: { - snapshot: Snapshot; - viewScopeId: string; - viewId?: string; -}) => { - const currentViewId = getSnapshotValue( - snapshot, - getScopedStateDeprecated(currentViewIdScopedState, viewScopeId), - ); - - const familyItemId = viewId ?? currentViewId ?? UNDEFINED_FAMILY_ITEM_ID; - - const { - availableFieldDefinitionsState, - availableFilterDefinitionsState, - availableSortDefinitionsState, - canPersistFiltersSelector, - canPersistSortsSelector, - currentViewFieldsState, - currentViewFiltersState, - currentViewIdState, - currentViewSelector, - currentViewSortsState, - entityCountInCurrentViewState, - isViewBarExpandedState, - isPersistingViewState, - onViewFieldsChangeState, - onViewFiltersChangeState, - onViewSortsChangeState, - onViewTypeChangeState, - onViewCompactModeChangeState, - savedViewFieldsByKeySelector, - savedViewFieldsState, - savedViewFiltersByKeySelector, - savedViewFiltersState, - savedViewSortsByKeySelector, - savedViewSortsState, - viewEditModeState, - viewObjectMetadataIdState, - viewTypeState, - viewsState, - } = getViewScopedStates({ - viewScopeId, - viewId: familyItemId, - }); - - return { - availableFieldDefinitions: getSnapshotValue( - snapshot, - availableFieldDefinitionsState, - ), - availableFilterDefinitions: getSnapshotValue( - snapshot, - availableFilterDefinitionsState, - ), - availableSortDefinitions: getSnapshotValue( - snapshot, - availableSortDefinitionsState, - ), - canPersistFilters: getSnapshotValue(snapshot, canPersistFiltersSelector), - canPersistSorts: getSnapshotValue(snapshot, canPersistSortsSelector), - currentViewFields: getSnapshotValue(snapshot, currentViewFieldsState), - currentViewFilters: getSnapshotValue(snapshot, currentViewFiltersState), - currentViewId: getSnapshotValue(snapshot, currentViewIdState), - currentView: getSnapshotValue(snapshot, currentViewSelector), - currentViewSorts: getSnapshotValue(snapshot, currentViewSortsState), - entityCountInCurrentView: getSnapshotValue( - snapshot, - entityCountInCurrentViewState, - ), - isViewBarExpanded: getSnapshotValue(snapshot, isViewBarExpandedState), - isPersistingView: getSnapshotValue(snapshot, isPersistingViewState), - onViewFieldsChange: getSnapshotValue(snapshot, onViewFieldsChangeState), - onViewFiltersChange: getSnapshotValue(snapshot, onViewFiltersChangeState), - onViewSortsChange: getSnapshotValue(snapshot, onViewSortsChangeState), - onViewTypeChange: getSnapshotValue(snapshot, onViewTypeChangeState), - onViewCompactModeChange: getSnapshotValue( - snapshot, - onViewCompactModeChangeState, - ), - savedViewFieldsByKey: getSnapshotValue( - snapshot, - savedViewFieldsByKeySelector, - ), - savedViewFields: getSnapshotValue(snapshot, savedViewFieldsState), - savedViewFiltersByKey: getSnapshotValue( - snapshot, - savedViewFiltersByKeySelector, - ), - savedViewFilters: getSnapshotValue(snapshot, savedViewFiltersState), - savedViewSortsByKey: getSnapshotValue( - snapshot, - savedViewSortsByKeySelector, - ), - savedViewSorts: getSnapshotValue(snapshot, savedViewSortsState), - viewEditMode: getSnapshotValue(snapshot, viewEditModeState), - viewObjectMetadataId: getSnapshotValue(snapshot, viewObjectMetadataIdState), - viewType: getSnapshotValue(snapshot, viewTypeState), - views: getSnapshotValue(snapshot, viewsState), - }; -}; diff --git a/packages/twenty-front/src/modules/views/utils/getViewScopedStatesFromSnapshot.ts b/packages/twenty-front/src/modules/views/utils/getViewScopedStatesFromSnapshot.ts deleted file mode 100644 index b6b9f0ea5a..0000000000 --- a/packages/twenty-front/src/modules/views/utils/getViewScopedStatesFromSnapshot.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { Snapshot } from 'recoil'; - -import { getScopedStateDeprecated } from '@/ui/utilities/recoil-scope/utils/getScopedStateDeprecated'; -import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; - -import { UNDEFINED_FAMILY_ITEM_ID } from '../constants'; -import { currentViewIdScopedState } from '../states/currentViewIdScopedState'; - -import { getViewScopedStates } from './internal/getViewScopedStates'; - -export const getViewScopedStatesFromSnapshot = ({ - snapshot, - viewScopeId, - viewId, -}: { - snapshot: Snapshot; - viewScopeId: string; - viewId?: string; -}) => { - const currentViewId = getSnapshotValue( - snapshot, - getScopedStateDeprecated(currentViewIdScopedState, viewScopeId), - ); - - const usedViewId = viewId ?? currentViewId ?? UNDEFINED_FAMILY_ITEM_ID; - - const { - availableFieldDefinitionsState, - availableFilterDefinitionsState, - availableSortDefinitionsState, - canPersistFiltersSelector, - canPersistSortsSelector, - currentViewFieldsState, - currentViewFiltersState, - currentViewIdState, - currentViewSelector, - currentViewSortsState, - entityCountInCurrentViewState, - isViewBarExpandedState, - isPersistingViewState, - onViewFieldsChangeState, - onViewFiltersChangeState, - onViewSortsChangeState, - savedViewFieldsByKeySelector, - savedViewFieldsState, - savedViewFiltersByKeySelector, - savedViewFiltersState, - savedViewSortsByKeySelector, - savedViewSortsState, - viewEditModeState, - viewObjectMetadataIdState, - viewTypeState, - viewsState, - } = getViewScopedStates({ - viewScopeId, - viewId: usedViewId, - }); - - return { - availableFieldDefinitionsState, - availableFilterDefinitionsState, - availableSortDefinitionsState, - canPersistFiltersReadOnlyState: canPersistFiltersSelector, - canPersistSortsReadOnlyState: canPersistSortsSelector, - currentViewFieldsState, - currentViewFiltersState, - currentViewIdState, - currentViewSelector, - currentViewSortsState, - entityCountInCurrentViewState, - isViewBarExpandedState, - isPersistingViewState, - onViewFieldsChangeState, - onViewFiltersChangeState, - onViewSortsChangeState, - savedViewFieldsByKeyReadOnlyState: savedViewFieldsByKeySelector, - savedViewFieldsState, - savedViewFiltersByKeyReadOnlyState: savedViewFiltersByKeySelector, - savedViewFiltersState, - savedViewSortsByKeyReadOnlyState: savedViewSortsByKeySelector, - savedViewSortsState, - viewEditModeState, - viewObjectMetadataIdState, - viewTypeState, - viewsState, - }; -}; diff --git a/packages/twenty-front/src/modules/views/utils/internal/getViewScopedStates.ts b/packages/twenty-front/src/modules/views/utils/internal/getViewScopedStates.ts deleted file mode 100644 index 5e3d5f29b3..0000000000 --- a/packages/twenty-front/src/modules/views/utils/internal/getViewScopedStates.ts +++ /dev/null @@ -1,225 +0,0 @@ -import { getScopedFamilyStateDeprecated } from '@/ui/utilities/recoil-scope/utils/getScopedFamilyStateDeprecated'; -import { getScopedSelectorDeprecated } from '@/ui/utilities/recoil-scope/utils/getScopedSelectorDeprecated'; -import { getScopedStateDeprecated } from '@/ui/utilities/recoil-scope/utils/getScopedStateDeprecated'; -import { currentViewIdScopedState } from '@/views/states/currentViewIdScopedState'; -import { isPersistingViewScopedState } from '@/views/states/isPersistingViewScopedState'; -import { onViewCompactModeChangeScopeState } from '@/views/states/onViewCompactModeChangeScopeState'; -import { onViewTypeChangeScopedState } from '@/views/states/onViewTypeChangeScopedState'; -import { currentViewComponentSelector } from '@/views/states/selectors/currentViewComponentSelector'; -import { savedViewFieldByKeyScopedFamilySelector } from '@/views/states/selectors/savedViewFieldByKeyScopedFamilySelector'; - -import { availableFieldDefinitionsScopedState } from '../../states/availableFieldDefinitionsScopedState'; -import { availableFilterDefinitionsScopedState } from '../../states/availableFilterDefinitionsScopedState'; -import { availableSortDefinitionsScopedState } from '../../states/availableSortDefinitionsScopedState'; -import { currentViewFieldsScopedFamilyState } from '../../states/currentViewFieldsScopedFamilyState'; -import { currentViewFiltersScopedFamilyState } from '../../states/currentViewFiltersScopedFamilyState'; -import { currentViewSortsScopedFamilyState } from '../../states/currentViewSortsScopedFamilyState'; -import { entityCountInCurrentViewScopedState } from '../../states/entityCountInCurrentViewScopedState'; -import { isViewBarExpandedScopedState } from '../../states/isViewBarExpandedScopedState'; -import { onViewFieldsChangeScopedState } from '../../states/onViewFieldsChangeScopedState'; -import { onViewFiltersChangeScopedState } from '../../states/onViewFiltersChangeScopedState'; -import { onViewSortsChangeScopedState } from '../../states/onViewSortsChangeScopedState'; -import { savedViewFieldsScopedFamilyState } from '../../states/savedViewFieldsScopedFamilyState'; -import { savedViewFiltersScopedFamilyState } from '../../states/savedViewFiltersScopedFamilyState'; -import { savedViewSortsScopedFamilyState } from '../../states/savedViewSortsScopedFamilyState'; -import { canPersistViewFiltersScopedFamilySelector } from '../../states/selectors/canPersistViewFiltersScopedFamilySelector'; -import { canPersistViewSortsScopedFamilySelector } from '../../states/selectors/canPersistViewSortsScopedFamilySelector'; -import { savedViewFiltersByKeyScopedFamilySelector } from '../../states/selectors/savedViewFiltersByKeyScopedFamilySelector'; -import { savedViewSortsByKeyScopedFamilySelector } from '../../states/selectors/savedViewSortsByKeyScopedFamilySelector'; -import { viewEditModeScopedState } from '../../states/viewEditModeScopedState'; -import { viewObjectMetadataIdScopeState } from '../../states/viewObjectMetadataIdScopeState'; -import { viewsScopedState } from '../../states/viewsScopedState'; -import { viewTypeScopedState } from '../../states/viewTypeScopedState'; - -export const getViewScopedStates = ({ - viewScopeId, - viewId, -}: { - viewScopeId: string; - viewId: string; -}) => { - const viewEditModeState = getScopedStateDeprecated( - viewEditModeScopedState, - viewScopeId, - ); - - const viewsState = getScopedStateDeprecated(viewsScopedState, viewScopeId); - - const viewObjectMetadataIdState = getScopedStateDeprecated( - viewObjectMetadataIdScopeState, - viewScopeId, - ); - - const viewTypeState = getScopedStateDeprecated( - viewTypeScopedState, - viewScopeId, - ); - - const entityCountInCurrentViewState = getScopedStateDeprecated( - entityCountInCurrentViewScopedState, - viewScopeId, - ); - - const isViewBarExpandedState = getScopedStateDeprecated( - isViewBarExpandedScopedState, - viewScopeId, - ); - - const isPersistingViewState = getScopedStateDeprecated( - isPersistingViewScopedState, - viewScopeId, - ); - - // ViewSorts - const currentViewSortsState = getScopedFamilyStateDeprecated( - currentViewSortsScopedFamilyState, - viewScopeId, - viewId, - ); - - const savedViewSortsState = getScopedFamilyStateDeprecated( - savedViewSortsScopedFamilyState, - viewScopeId, - viewId, - ); - - const savedViewSortsByKeySelector = savedViewSortsByKeyScopedFamilySelector({ - scopeId: viewScopeId, - viewId: viewId, - }); - - const availableSortDefinitionsState = getScopedStateDeprecated( - availableSortDefinitionsScopedState, - viewScopeId, - ); - - const canPersistSortsSelector = canPersistViewSortsScopedFamilySelector({ - viewScopeId: viewScopeId, - viewId: viewId, - }); - - // ViewFilters - const currentViewFiltersState = getScopedFamilyStateDeprecated( - currentViewFiltersScopedFamilyState, - viewScopeId, - viewId, - ); - - const savedViewFiltersState = getScopedFamilyStateDeprecated( - savedViewFiltersScopedFamilyState, - viewScopeId, - viewId, - ); - - const savedViewFiltersByKeySelector = - savedViewFiltersByKeyScopedFamilySelector({ - scopeId: viewScopeId, - viewId: viewId, - }); - - const availableFilterDefinitionsState = getScopedStateDeprecated( - availableFilterDefinitionsScopedState, - viewScopeId, - ); - - const canPersistFiltersSelector = canPersistViewFiltersScopedFamilySelector({ - viewScopeId: viewScopeId, - viewId: viewId, - }); - - // ViewFields - const availableFieldDefinitionsState = getScopedStateDeprecated( - availableFieldDefinitionsScopedState, - viewScopeId, - ); - - const currentViewFieldsState = getScopedFamilyStateDeprecated( - currentViewFieldsScopedFamilyState, - viewScopeId, - viewId, - ); - - const savedViewFieldsState = getScopedFamilyStateDeprecated( - savedViewFieldsScopedFamilyState, - viewScopeId, - viewId, - ); - - const savedViewFieldsByKeySelector = savedViewFieldByKeyScopedFamilySelector({ - viewScopeId, - viewId, - }); - - // ViewChangeHandlers - const onViewSortsChangeState = getScopedStateDeprecated( - onViewSortsChangeScopedState, - viewScopeId, - ); - - const onViewFiltersChangeState = getScopedStateDeprecated( - onViewFiltersChangeScopedState, - viewScopeId, - ); - - const onViewFieldsChangeState = getScopedStateDeprecated( - onViewFieldsChangeScopedState, - viewScopeId, - ); - - const onViewTypeChangeState = getScopedStateDeprecated( - onViewTypeChangeScopedState, - viewScopeId, - ); - - const onViewCompactModeChangeState = getScopedStateDeprecated( - onViewCompactModeChangeScopeState, - viewScopeId, - ); - - const currentViewIdState = getScopedStateDeprecated( - currentViewIdScopedState, - viewScopeId, - ); - - const currentViewSelector = getScopedSelectorDeprecated( - currentViewComponentSelector, - viewScopeId, - ); - - return { - currentViewIdState, - currentViewSelector, - - isViewBarExpandedState, - isPersistingViewState, - - viewsState, - viewEditModeState, - viewObjectMetadataIdState, - viewTypeState, - entityCountInCurrentViewState, - - availableSortDefinitionsState, - currentViewSortsState, - savedViewSortsState, - savedViewSortsByKeySelector, - canPersistSortsSelector, - - availableFilterDefinitionsState, - currentViewFiltersState, - savedViewFiltersState, - savedViewFiltersByKeySelector, - canPersistFiltersSelector, - - availableFieldDefinitionsState, - currentViewFieldsState, - savedViewFieldsByKeySelector, - savedViewFieldsState, - - onViewSortsChangeState, - onViewFiltersChangeState, - onViewFieldsChangeState, - onViewTypeChangeState, - onViewCompactModeChangeState, - }; -}; diff --git a/packages/twenty-front/src/modules/views/utils/mapBoardFieldDefinitionsToViewFields.ts b/packages/twenty-front/src/modules/views/utils/mapBoardFieldDefinitionsToViewFields.ts index bf183ca0f8..873187cb0f 100644 --- a/packages/twenty-front/src/modules/views/utils/mapBoardFieldDefinitionsToViewFields.ts +++ b/packages/twenty-front/src/modules/views/utils/mapBoardFieldDefinitionsToViewFields.ts @@ -1,5 +1,3 @@ -import { v4 } from 'uuid'; - import { RecordBoardFieldDefinition } from '@/object-record/record-board/types/RecordBoardFieldDefinition'; import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata'; import { ViewField } from '@/views/types/ViewField'; @@ -9,7 +7,8 @@ export const mapBoardFieldDefinitionsToViewFields = ( ): ViewField[] => { return fieldsDefinitions.map( (fieldDefinition): ViewField => ({ - id: fieldDefinition.viewFieldId || v4(), + __typename: 'ViewField', + id: fieldDefinition.viewFieldId || '', fieldMetadataId: fieldDefinition.fieldMetadataId, size: 0, position: fieldDefinition.position, diff --git a/packages/twenty-front/src/modules/views/utils/mapColumnDefinitionToViewField.ts b/packages/twenty-front/src/modules/views/utils/mapColumnDefinitionToViewField.ts index 833c1a65b6..7b00889bbd 100644 --- a/packages/twenty-front/src/modules/views/utils/mapColumnDefinitionToViewField.ts +++ b/packages/twenty-front/src/modules/views/utils/mapColumnDefinitionToViewField.ts @@ -7,6 +7,7 @@ export const mapColumnDefinitionsToViewFields = ( columnDefinitions: ColumnDefinition[], ): ViewField[] => { return columnDefinitions.map((columnDefinition) => ({ + __typename: 'ViewField', id: columnDefinition.viewFieldId || '', fieldMetadataId: columnDefinition.fieldMetadataId, position: columnDefinition.position, diff --git a/packages/twenty-front/src/modules/views/utils/mapViewFiltersToFilters.ts b/packages/twenty-front/src/modules/views/utils/mapViewFiltersToFilters.ts index 8cca295406..4df8f1e993 100644 --- a/packages/twenty-front/src/modules/views/utils/mapViewFiltersToFilters.ts +++ b/packages/twenty-front/src/modules/views/utils/mapViewFiltersToFilters.ts @@ -1,17 +1,29 @@ import { Filter } from '@/object-record/object-filter-dropdown/types/Filter'; +import { FilterDefinition } from '@/object-record/object-filter-dropdown/types/FilterDefinition'; +import { isDefined } from '~/utils/isDefined'; import { ViewFilter } from '../types/ViewFilter'; export const mapViewFiltersToFilters = ( viewFilters: ViewFilter[], + availableFilterDefinitions: FilterDefinition[], ): Filter[] => { - return viewFilters.map((viewFilter) => { - return { - fieldMetadataId: viewFilter.fieldMetadataId, - value: viewFilter.value, - displayValue: viewFilter.displayValue, - operand: viewFilter.operand, - definition: viewFilter.definition, - }; - }); + return viewFilters + .map((viewFilter) => { + const availableFilterDefinition = availableFilterDefinitions.find( + (filterDefinition) => + filterDefinition.fieldMetadataId === viewFilter.fieldMetadataId, + ); + + if (!availableFilterDefinition) return null; + + return { + fieldMetadataId: viewFilter.fieldMetadataId, + value: viewFilter.value, + displayValue: viewFilter.displayValue, + operand: viewFilter.operand, + definition: availableFilterDefinition, + }; + }) + .filter(isDefined); }; diff --git a/packages/twenty-front/src/modules/views/utils/mapViewSortsToSorts.ts b/packages/twenty-front/src/modules/views/utils/mapViewSortsToSorts.ts index 7ceec1a622..34e8c2f07c 100644 --- a/packages/twenty-front/src/modules/views/utils/mapViewSortsToSorts.ts +++ b/packages/twenty-front/src/modules/views/utils/mapViewSortsToSorts.ts @@ -1,13 +1,26 @@ import { Sort } from '@/object-record/object-sort-dropdown/types/Sort'; +import { SortDefinition } from '@/object-record/object-sort-dropdown/types/SortDefinition'; +import { isDefined } from '~/utils/isDefined'; import { ViewSort } from '../types/ViewSort'; -export const mapViewSortsToSorts = (viewSorts: ViewSort[]): Sort[] => { - return viewSorts.map((viewSort) => { - return { - fieldMetadataId: viewSort.fieldMetadataId, - direction: viewSort.direction, - definition: viewSort.definition, - }; - }); +export const mapViewSortsToSorts = ( + viewSorts: ViewSort[], + availableSortDefinitions: SortDefinition[], +): Sort[] => { + return viewSorts + .map((viewSort) => { + const availableSortDefinition = availableSortDefinitions.find( + (sortDefinition) => + sortDefinition.fieldMetadataId === viewSort.fieldMetadataId, + ); + + if (!availableSortDefinition) return null; + return { + fieldMetadataId: viewSort.fieldMetadataId, + direction: viewSort.direction, + definition: availableSortDefinition, + }; + }) + .filter(isDefined); }; diff --git a/packages/twenty-front/src/modules/workspace/hooks/useIsFeatureEnabled.ts b/packages/twenty-front/src/modules/workspace/hooks/useIsFeatureEnabled.ts index ac3786d375..31906107de 100644 --- a/packages/twenty-front/src/modules/workspace/hooks/useIsFeatureEnabled.ts +++ b/packages/twenty-front/src/modules/workspace/hooks/useIsFeatureEnabled.ts @@ -4,7 +4,7 @@ import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState'; import { FeatureFlagKey } from '@/workspace/types/FeatureFlagKey'; export const useIsFeatureEnabled = (featureKey: FeatureFlagKey) => { - const currentWorkspace = useRecoilValue(currentWorkspaceState()); + const currentWorkspace = useRecoilValue(currentWorkspaceState); const featureFlag = currentWorkspace?.featureFlags?.find( (flag) => flag.key === featureKey, diff --git a/packages/twenty-front/src/pages/auth/ChooseYourPlan.tsx b/packages/twenty-front/src/pages/auth/ChooseYourPlan.tsx index 235eefd8df..2cb36de502 100644 --- a/packages/twenty-front/src/pages/auth/ChooseYourPlan.tsx +++ b/packages/twenty-front/src/pages/auth/ChooseYourPlan.tsx @@ -43,7 +43,7 @@ const StyledBenefitsContainer = styled.div` `; export const ChooseYourPlan = () => { - const billing = useRecoilValue(billingState()); + const billing = useRecoilValue(billingState); const [planSelected, setPlanSelected] = useState('month'); diff --git a/packages/twenty-front/src/pages/auth/CreateProfile.tsx b/packages/twenty-front/src/pages/auth/CreateProfile.tsx index 554c14beab..edbaa99bcf 100644 --- a/packages/twenty-front/src/pages/auth/CreateProfile.tsx +++ b/packages/twenty-front/src/pages/auth/CreateProfile.tsx @@ -58,7 +58,7 @@ export const CreateProfile = () => { const { enqueueSnackBar } = useSnackBar(); const [currentWorkspaceMember, setCurrentWorkspaceMember] = useRecoilState( - currentWorkspaceMemberState(), + currentWorkspaceMemberState, ); const { updateOneRecord } = useUpdateOneRecord({ diff --git a/packages/twenty-front/src/pages/auth/VerifyEffect.tsx b/packages/twenty-front/src/pages/auth/VerifyEffect.tsx index c4ba1c21b7..cda60b1bc4 100644 --- a/packages/twenty-front/src/pages/auth/VerifyEffect.tsx +++ b/packages/twenty-front/src/pages/auth/VerifyEffect.tsx @@ -10,7 +10,7 @@ import { AppPath } from '@/types/AppPath'; export const VerifyEffect = () => { const [searchParams] = useSearchParams(); const loginToken = searchParams.get('loginToken'); - const currentWorkspace = useRecoilValue(currentWorkspaceState()); + const currentWorkspace = useRecoilValue(currentWorkspaceState); const isLogged = useIsLogged(); const navigate = useNavigate(); diff --git a/packages/twenty-front/src/pages/auth/__stories__/CreateWorkspace.stories.tsx b/packages/twenty-front/src/pages/auth/__stories__/CreateWorkspace.stories.tsx index 1d1fe2f841..61d2f8316f 100644 --- a/packages/twenty-front/src/pages/auth/__stories__/CreateWorkspace.stories.tsx +++ b/packages/twenty-front/src/pages/auth/__stories__/CreateWorkspace.stories.tsx @@ -21,7 +21,7 @@ const meta: Meta = { component: CreateWorkspace, decorators: [ (Story) => { - const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState()); + const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState); setCurrentWorkspace(mockedOnboardingUsersData[1].defaultWorkspace); return ; }, diff --git a/packages/twenty-front/src/pages/impersonate/ImpersonateEffect.tsx b/packages/twenty-front/src/pages/impersonate/ImpersonateEffect.tsx index d8973a776f..897ab095fc 100644 --- a/packages/twenty-front/src/pages/impersonate/ImpersonateEffect.tsx +++ b/packages/twenty-front/src/pages/impersonate/ImpersonateEffect.tsx @@ -14,8 +14,8 @@ export const ImpersonateEffect = () => { const navigate = useNavigate(); const { userId } = useParams(); - const [currentUser, setCurrentUser] = useRecoilState(currentUserState()); - const setTokenPair = useSetRecoilState(tokenPairState()); + const [currentUser, setCurrentUser] = useRecoilState(currentUserState); + const setTokenPair = useSetRecoilState(tokenPairState); const [impersonate] = useImpersonateMutation(); diff --git a/packages/twenty-front/src/pages/object-record/RecordIndexPageHeader.tsx b/packages/twenty-front/src/pages/object-record/RecordIndexPageHeader.tsx index 0ea96ca435..fd24ab76f1 100644 --- a/packages/twenty-front/src/pages/object-record/RecordIndexPageHeader.tsx +++ b/packages/twenty-front/src/pages/object-record/RecordIndexPageHeader.tsx @@ -27,7 +27,7 @@ export const RecordIndexPageHeader = ({ findObjectMetadataItemByNamePlural(objectNamePlural)?.icon, ); - const recordIndexViewType = useRecoilValue(recordIndexViewTypeState()); + const recordIndexViewType = useRecoilValue(recordIndexViewTypeState); return ( diff --git a/packages/twenty-front/src/pages/settings/SettingsWorkspaceMembers.tsx b/packages/twenty-front/src/pages/settings/SettingsWorkspaceMembers.tsx index 48345f869e..bd63e8978a 100644 --- a/packages/twenty-front/src/pages/settings/SettingsWorkspaceMembers.tsx +++ b/packages/twenty-front/src/pages/settings/SettingsWorkspaceMembers.tsx @@ -42,8 +42,8 @@ export const SettingsWorkspaceMembers = () => { const { deleteOneRecord: deleteOneWorkspaceMember } = useDeleteOneRecord({ objectNameSingular: CoreObjectNameSingular.WorkspaceMember, }); - const currentWorkspace = useRecoilValue(currentWorkspaceState()); - const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState()); + const currentWorkspace = useRecoilValue(currentWorkspaceState); + const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); const handleRemoveWorkspaceMember = async (workspaceMemberId: string) => { await deleteOneWorkspaceMember?.(workspaceMemberId); diff --git a/packages/twenty-front/src/pages/settings/accounts/SettingsAccounts.tsx b/packages/twenty-front/src/pages/settings/accounts/SettingsAccounts.tsx index 6b66c48261..72576db59f 100644 --- a/packages/twenty-front/src/pages/settings/accounts/SettingsAccounts.tsx +++ b/packages/twenty-front/src/pages/settings/accounts/SettingsAccounts.tsx @@ -14,7 +14,7 @@ import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; import { SettingsAccountLoader } from '~/pages/settings/accounts/SettingsAccountLoader'; export const SettingsAccounts = () => { - const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState()); + const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); const { records: accounts, loading } = useFindManyRecords({ objectNameSingular: 'connectedAccount', diff --git a/packages/twenty-front/src/pages/settings/accounts/SettingsAccountsCalendars.tsx b/packages/twenty-front/src/pages/settings/accounts/SettingsAccountsCalendars.tsx index d4960b0731..8fb0cb66e1 100644 --- a/packages/twenty-front/src/pages/settings/accounts/SettingsAccountsCalendars.tsx +++ b/packages/twenty-front/src/pages/settings/accounts/SettingsAccountsCalendars.tsx @@ -21,7 +21,7 @@ import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb'; import { mockedConnectedAccounts } from '~/testing/mock-data/accounts'; export const SettingsAccountsCalendars = () => { - const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState()); + const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); const { records: _accounts } = useFindManyRecords({ objectNameSingular: CoreObjectNameSingular.ConnectedAccount, filter: { diff --git a/packages/twenty-front/src/pages/tasks/TasksEffect.tsx b/packages/twenty-front/src/pages/tasks/TasksEffect.tsx index 5c503edcd0..c3d5e2daf7 100644 --- a/packages/twenty-front/src/pages/tasks/TasksEffect.tsx +++ b/packages/twenty-front/src/pages/tasks/TasksEffect.tsx @@ -13,7 +13,7 @@ type TasksEffectProps = { }; export const TasksEffect = ({ filterDropdownId }: TasksEffectProps) => { - const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState()); + const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); const { setSelectedFilter, setAvailableFilterDefinitions, diff --git a/packages/twenty-front/src/testing/decorators/ObjectMetadataItemsDecorator.tsx b/packages/twenty-front/src/testing/decorators/ObjectMetadataItemsDecorator.tsx index ec961a8700..a657c99538 100644 --- a/packages/twenty-front/src/testing/decorators/ObjectMetadataItemsDecorator.tsx +++ b/packages/twenty-front/src/testing/decorators/ObjectMetadataItemsDecorator.tsx @@ -8,9 +8,9 @@ import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadat import { mockWorkspaceMembers } from '~/testing/mock-data/workspace-members'; export const ObjectMetadataItemsDecorator: Decorator = (Story) => { - const objectMetadataItems = useRecoilValue(objectMetadataItemsState()); + const objectMetadataItems = useRecoilValue(objectMetadataItemsState); const setCurrentWorkspaceMember = useSetRecoilState( - currentWorkspaceMemberState(), + currentWorkspaceMemberState, ); useEffect( diff --git a/packages/twenty-server/src/engine/modules/calendar/timeline-calendar-event.service.ts b/packages/twenty-server/src/engine/modules/calendar/timeline-calendar-event.service.ts index 37429daf75..85c4b0ca66 100644 --- a/packages/twenty-server/src/engine/modules/calendar/timeline-calendar-event.service.ts +++ b/packages/twenty-server/src/engine/modules/calendar/timeline-calendar-event.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@nestjs/common'; -import groupBy from 'lodash.groupBy'; +import groupBy from 'lodash.groupby'; import { TIMELINE_CALENDAR_EVENTS_DEFAULT_PAGE_SIZE } from 'src/engine/modules/calendar/constants/calendar.constants'; import { TimelineCalendarEventAttendee } from 'src/engine/modules/calendar/dtos/timeline-calendar-event-attendee.dto'; diff --git a/yarn.lock b/yarn.lock index f8806b2b7a..bfb3bdf8a6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -33367,6 +33367,13 @@ __metadata: languageName: node linkType: hard +"lodash.groupby@npm:^4.6.0": + version: 4.6.0 + resolution: "lodash.groupby@npm:4.6.0" + checksum: 3d136cad438ad6c3a078984ef60e057a3498b1312aa3621b00246ecb99e8f2c4d447e2815460db7a0b661a4fe4e2eeee96c84cb661a824bad04b6cf1f7bc6e9b + languageName: node + linkType: hard + "lodash.includes@npm:^4.3.0": version: 4.3.0 resolution: "lodash.includes@npm:4.3.0" @@ -46010,6 +46017,7 @@ __metadata: libphonenumber-js: "npm:^1.10.26" lodash.camelcase: "npm:^4.3.0" lodash.debounce: "npm:^4.0.8" + lodash.groupby: "npm:^4.6.0" lodash.isempty: "npm:^4.4.0" lodash.isequal: "npm:^4.5.0" lodash.isobject: "npm:^3.0.2"