From a1c7e3279c6877a76ce44a3aed0df0b67eb21ae7 Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Tue, 25 Feb 2025 15:48:25 +0100 Subject: [PATCH] Refactor RecordSingleSelect and RecordMultiSelect to be synchronous (#10469) ## Context We are experiencing a lot of re-rendering / flash on MultiRecordSelect / SingleRecordSelect / RelationPicker. This PR is a first step to refactor this components ## Scope Only move files to uniformize and prepare for the upcoming refactoring ## Vision - SingleRecordPicker - MultipleRecordPicker - sharing RecordPicker tooling (RecordPickerComponentInstanceContext, searchState) Used in other areas: - RelationPicker (which is actually only a subcomponent of RelationToOneFieldInput) - RelationFromManyFieldInput - WorkflowRelationFieldInput - etc. + remove all effects + migrate to the latest APIs + make a pass on re-renders to remove them completely (we likely need to use a bit more familyStates here) --- .../ActivityTargetInlineCellEditMode.tsx | 10 +- .../command-menu/hooks/useSearchRecords.tsx | 4 +- .../ObjectMetadataItemsProvider.tsx | 4 +- .../hooks/useLimitPerMetadataItem.ts | 0 .../constants/TableColumnsDenyList.ts | 0 .../hooks/useCombinedFindManyRecords.ts | 2 +- .../hooks/useCombinedGetTotalCount.ts | 2 +- .../ObjectFilterDropdownBooleanSelect.tsx | 2 +- ...jectFilterDropdownFilterSelectMenuItem.tsx | 2 +- .../ObjectFilterDropdownOptionSelect.tsx | 17 ++- .../ObjectFilterDropdownRecordSelect.tsx | 2 +- .../ObjectFilterDropdownSourceSelect.tsx | 2 +- .../hooks/useSelectFilterUsedInDropdown.ts | 2 +- .../RecordBoardColumnNewOpportunity.tsx | 8 +- .../hooks/useAddNewCard.ts | 10 +- ...NewRecordByColumnIdComponentFamilyState.ts | 4 +- .../components/FormMultiSelectFieldInput.tsx | 9 +- .../components/FormSelectFieldInput.tsx | 8 +- .../FormMultiSelectFieldInputHotKeyScope.ts | 3 + .../record-field/hooks/usePersistField.ts | 4 +- .../meta-types/hooks/useRelationField.ts | 4 +- .../components/MultiSelectFieldInput.tsx | 4 + .../components/RelationFromManyFieldInput.tsx | 12 +- ...onFromManyFieldInputMultiRecordsEffect.tsx | 13 +- .../input}/components/RelationPicker.tsx | 16 +- .../components/RelationToOneFieldInput.tsx | 9 +- .../input/components/SelectFieldInput.tsx | 8 +- .../RelationToOneFieldInput.stories.tsx | 2 +- ...dInputSelectableListComponentInstanceId.ts | 2 + .../record-field/types/FieldMetadata.ts | 6 +- .../components/RecordInlineCell.tsx | 2 +- .../components/MultipleRecordPicker.tsx} | 140 +++++++++--------- .../MultipleRecordPickerMenuItem.tsx} | 8 +- .../components/SingleRecordPicker.tsx} | 16 +- .../SingleRecordPickerMenuItem.tsx} | 18 +-- .../SingleRecordPickerMenuItems.tsx} | 28 ++-- ...SingleRecordPickerMenuItemsWithSearch.tsx} | 33 +++-- .../SingleRecordPicker.stories.tsx} | 14 +- .../RecordPickerClickOutsideListenerId.ts | 2 + ...PickerSelectableListComponentInstanceId.ts | 2 + .../useLimitPerMetadataItem.test.tsx | 4 +- ...attedAsObjectRecordForSelectArray.test.tsx | 4 +- ...ResultFormattedAsObjectRecordsMap.test.tsx | 4 +- .../__tests__/useRecordSelectSearch.test.tsx | 6 +- .../useAddNewRecordAndOpenRightDrawer.ts | 0 ...ltFormattedAsObjectRecordForSelectArray.ts | 2 +- .../hooks/useMultiObjectSearch.ts | 4 +- ...hQueryResultFormattedAsObjectRecordsMap.ts | 4 +- .../useMultiObjectSearchSelectedItemsQuery.ts | 6 +- .../hooks/useOrderByFieldPerMetadataItem.ts | 0 .../hooks/useRecordPickerRecordsOptions.ts | 4 +- .../hooks/useRecordSelectSearch.ts | 15 +- ...etInlineCellEditModeMultiRecordsEffect.tsx | 3 +- ...EditModeMultiRecordsSearchFilterEffect.tsx | 9 +- ...ltipleObjectRecordOnClickOutsideEffect.tsx | 5 +- .../SearchPickerInitialValueEffect.tsx | 3 +- .../types/RelationPickerHotkeyScope.ts | 0 .../RecordPickerComponentInstanceContext.ts | 0 ...recordPickerPreselectedIdComponentState.ts | 2 +- .../recordPickerSearchFilterComponentState.ts | 2 +- .../recordPickerSearchQueryComponentState.ts | 10 ++ .../types/MultipleRecordPickerRecords.ts | 10 ++ .../types/RecordPickerSearchQuery.ts} | 2 +- .../types/SingleRecordPickerRecord.ts} | 2 +- .../formatMultiObjectRecordSearchResults.ts | 2 +- .../RecordDetailRelationSection.tsx | 26 ++-- .../RecordTableCellFieldContextWrapper.tsx | 2 +- ...MultiObjectRecordClickOutsideListenerId.ts | 2 - ...MultiObjectRecordSelectSelectableListId.ts | 2 - .../constants/SingleRecordSelectBaseList.ts | 1 - .../relation-picker/hooks/useRecordPicker.ts | 24 --- .../states/searchQueryComponentState.ts | 10 -- .../types/RecordsForMultipleRecordSelect.ts | 10 -- .../utils/filterAvailableTableColumns.ts | 2 +- .../useFilteredSearchRecordQuery.test.tsx | 4 +- .../hooks/useFilteredSearchRecordQuery.ts | 6 +- .../input/components/MultiSelectInput.tsx | 9 +- .../ui/field/input/components/SelectInput.tsx | 6 +- .../components/WorkflowSingleRecordPicker.tsx | 20 +-- .../decorators/RecordPickerDecorator.tsx | 6 +- 80 files changed, 338 insertions(+), 329 deletions(-) rename packages/twenty-front/src/modules/{object-record/relation-picker => object-metadata}/hooks/useLimitPerMetadataItem.ts (100%) rename packages/twenty-front/src/modules/object-record/{relation-picker => }/constants/TableColumnsDenyList.ts (100%) create mode 100644 packages/twenty-front/src/modules/object-record/record-field/form-types/constants/FormMultiSelectFieldInputHotKeyScope.ts rename packages/twenty-front/src/modules/object-record/{relation-picker => record-field/meta-types/input}/components/RelationPicker.tsx (80%) create mode 100644 packages/twenty-front/src/modules/object-record/record-field/meta-types/input/constants/SelectFieldInputSelectableListComponentInstanceId.ts rename packages/twenty-front/src/modules/object-record/{relation-picker/components/MultiRecordSelect.tsx => record-picker/components/MultipleRecordPicker.tsx} (60%) rename packages/twenty-front/src/modules/object-record/{relation-picker/components/MultipleObjectRecordSelectItem.tsx => record-picker/components/MultipleRecordPickerMenuItem.tsx} (88%) rename packages/twenty-front/src/modules/object-record/{relation-picker/components/SingleRecordSelect.tsx => record-picker/components/SingleRecordPicker.tsx} (76%) rename packages/twenty-front/src/modules/object-record/{relation-picker/components/SelectableMenuItemSelect.tsx => record-picker/components/SingleRecordPickerMenuItem.tsx} (66%) rename packages/twenty-front/src/modules/object-record/{relation-picker/components/SingleRecordSelectMenuItems.tsx => record-picker/components/SingleRecordPickerMenuItems.tsx} (78%) rename packages/twenty-front/src/modules/object-record/{relation-picker/components/SingleRecordSelectMenuItemsWithSearch.tsx => record-picker/components/SingleRecordPickerMenuItemsWithSearch.tsx} (79%) rename packages/twenty-front/src/modules/object-record/{relation-picker/components/__stories__/SingleRecordSelect.stories.tsx => record-picker/components/__stories__/SingleRecordPicker.stories.tsx} (83%) create mode 100644 packages/twenty-front/src/modules/object-record/record-picker/constants/RecordPickerClickOutsideListenerId.ts create mode 100644 packages/twenty-front/src/modules/object-record/record-picker/constants/RecordPickerSelectableListComponentInstanceId.ts rename packages/twenty-front/src/modules/object-record/{relation-picker => record-picker}/hooks/__tests__/useLimitPerMetadataItem.test.tsx (90%) rename packages/twenty-front/src/modules/object-record/{relation-picker => record-picker}/hooks/__tests__/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray.test.tsx (94%) rename packages/twenty-front/src/modules/object-record/{relation-picker => record-picker}/hooks/__tests__/useMultiObjectSearchQueryResultFormattedAsObjectRecordsMap.test.tsx (94%) rename packages/twenty-front/src/modules/object-record/{relation-picker => record-picker}/hooks/__tests__/useRecordSelectSearch.test.tsx (85%) rename packages/twenty-front/src/modules/object-record/{relation-picker => record-picker}/hooks/useAddNewRecordAndOpenRightDrawer.ts (100%) rename packages/twenty-front/src/modules/object-record/{relation-picker => record-picker}/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray.ts (96%) rename packages/twenty-front/src/modules/object-record/{relation-picker => record-picker}/hooks/useMultiObjectSearch.ts (92%) rename packages/twenty-front/src/modules/object-record/{relation-picker => record-picker}/hooks/useMultiObjectSearchQueryResultFormattedAsObjectRecordsMap.ts (93%) rename packages/twenty-front/src/modules/object-record/{relation-picker => record-picker}/hooks/useMultiObjectSearchSelectedItemsQuery.ts (91%) rename packages/twenty-front/src/modules/object-record/{relation-picker => record-picker}/hooks/useOrderByFieldPerMetadataItem.ts (100%) rename packages/twenty-front/src/modules/object-record/{relation-picker => record-picker}/hooks/useRecordPickerRecordsOptions.ts (87%) rename packages/twenty-front/src/modules/object-record/{relation-picker => record-picker}/hooks/useRecordSelectSearch.ts (50%) rename packages/twenty-front/src/modules/object-record/{relation-picker => record-picker/legacy}/components/ActivityTargetInlineCellEditModeMultiRecordsEffect.tsx (96%) rename packages/twenty-front/src/modules/object-record/{relation-picker => record-picker/legacy}/components/ActivityTargetInlineCellEditModeMultiRecordsSearchFilterEffect.tsx (82%) rename packages/twenty-front/src/modules/object-record/{relation-picker => record-picker/legacy}/components/MultipleObjectRecordOnClickOutsideEffect.tsx (81%) rename packages/twenty-front/src/modules/object-record/{relation-picker => record-picker/legacy}/components/SearchPickerInitialValueEffect.tsx (85%) rename packages/twenty-front/src/modules/object-record/{relation-picker => record-picker/legacy}/types/RelationPickerHotkeyScope.ts (100%) rename packages/twenty-front/src/modules/object-record/{relation-picker => record-picker}/states/contexts/RecordPickerComponentInstanceContext.ts (100%) rename packages/twenty-front/src/modules/object-record/{relation-picker => record-picker}/states/recordPickerPreselectedIdComponentState.ts (84%) rename packages/twenty-front/src/modules/object-record/{relation-picker => record-picker}/states/recordPickerSearchFilterComponentState.ts (84%) create mode 100644 packages/twenty-front/src/modules/object-record/record-picker/states/recordPickerSearchQueryComponentState.ts create mode 100644 packages/twenty-front/src/modules/object-record/record-picker/types/MultipleRecordPickerRecords.ts rename packages/twenty-front/src/modules/object-record/{relation-picker/types/SearchQuery.tsx => record-picker/types/RecordPickerSearchQuery.ts} (62%) rename packages/twenty-front/src/modules/object-record/{relation-picker/types/RecordForSelect.ts => record-picker/types/SingleRecordPickerRecord.ts} (73%) rename packages/twenty-front/src/modules/object-record/{relation-picker => record-picker}/utils/formatMultiObjectRecordSearchResults.ts (85%) delete mode 100644 packages/twenty-front/src/modules/object-record/relation-picker/constants/MultiObjectRecordClickOutsideListenerId.ts delete mode 100644 packages/twenty-front/src/modules/object-record/relation-picker/constants/MultiObjectRecordSelectSelectableListId.ts delete mode 100644 packages/twenty-front/src/modules/object-record/relation-picker/constants/SingleRecordSelectBaseList.ts delete mode 100644 packages/twenty-front/src/modules/object-record/relation-picker/hooks/useRecordPicker.ts delete mode 100644 packages/twenty-front/src/modules/object-record/relation-picker/states/searchQueryComponentState.ts delete mode 100644 packages/twenty-front/src/modules/object-record/relation-picker/types/RecordsForMultipleRecordSelect.ts 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 b3c4c6534..85d2771b2 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 @@ -24,11 +24,11 @@ import { objectRecordMultiSelectComponentFamilyState, } from '@/object-record/record-field/states/objectRecordMultiSelectComponentFamilyState'; import { useInlineCell } from '@/object-record/record-inline-cell/hooks/useInlineCell'; +import { MultipleRecordPicker } from '@/object-record/record-picker/components/MultipleRecordPicker'; +import { ActivityTargetInlineCellEditModeMultiRecordsEffect } from '@/object-record/record-picker/legacy/components/ActivityTargetInlineCellEditModeMultiRecordsEffect'; +import { ActivityTargetInlineCellEditModeMultiRecordsSearchFilterEffect } from '@/object-record/record-picker/legacy/components/ActivityTargetInlineCellEditModeMultiRecordsSearchFilterEffect'; +import { RecordPickerComponentInstanceContext } from '@/object-record/record-picker/states/contexts/RecordPickerComponentInstanceContext'; import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState'; -import { ActivityTargetInlineCellEditModeMultiRecordsEffect } from '@/object-record/relation-picker/components/ActivityTargetInlineCellEditModeMultiRecordsEffect'; -import { ActivityTargetInlineCellEditModeMultiRecordsSearchFilterEffect } from '@/object-record/relation-picker/components/ActivityTargetInlineCellEditModeMultiRecordsSearchFilterEffect'; -import { MultiRecordSelect } from '@/object-record/relation-picker/components/MultiRecordSelect'; -import { RecordPickerComponentInstanceContext } from '@/object-record/relation-picker/states/contexts/RecordPickerComponentInstanceContext'; import { prefillRecord } from '@/object-record/utils/prefillRecord'; type ActivityTargetInlineCellEditModeProps = { @@ -269,7 +269,7 @@ export const ActivityTargetInlineCellEditMode = ({ selectedObjectRecordIds={selectedTargetObjectIds} /> - + ); diff --git a/packages/twenty-front/src/modules/command-menu/hooks/useSearchRecords.tsx b/packages/twenty-front/src/modules/command-menu/hooks/useSearchRecords.tsx index dde925398..a7e5063b6 100644 --- a/packages/twenty-front/src/modules/command-menu/hooks/useSearchRecords.tsx +++ b/packages/twenty-front/src/modules/command-menu/hooks/useSearchRecords.tsx @@ -7,8 +7,8 @@ import { CoreObjectNamePlural } from '@/object-metadata/types/CoreObjectNamePlur import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { getCompanyDomainName } from '@/object-metadata/utils/getCompanyDomainName'; import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords'; -import { useMultiObjectSearch } from '@/object-record/relation-picker/hooks/useMultiObjectSearch'; -import { useMultiObjectSearchQueryResultFormattedAsObjectRecordsMap } from '@/object-record/relation-picker/hooks/useMultiObjectSearchQueryResultFormattedAsObjectRecordsMap'; +import { useMultiObjectSearch } from '@/object-record/record-picker/hooks/useMultiObjectSearch'; +import { useMultiObjectSearchQueryResultFormattedAsObjectRecordsMap } from '@/object-record/record-picker/hooks/useMultiObjectSearchQueryResultFormattedAsObjectRecordsMap'; import { makeOrFilterVariables } from '@/object-record/utils/makeOrFilterVariables'; import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; import { t } from '@lingui/core/macro'; 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 d516f3ecf..af5595ff9 100644 --- a/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsProvider.tsx +++ b/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsProvider.tsx @@ -4,8 +4,8 @@ import { useRecoilValue } from 'recoil'; import { ObjectMetadataItemsLoadEffect } from '@/object-metadata/components/ObjectMetadataItemsLoadEffect'; import { PreComputedChipGeneratorsProvider } from '@/object-metadata/components/PreComputedChipGeneratorsProvider'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; -import { RecordPickerComponentInstanceContext } from '@/object-record/relation-picker/states/contexts/RecordPickerComponentInstanceContext'; -import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope'; +import { RelationPickerHotkeyScope } from '@/object-record/record-picker/legacy/types/RelationPickerHotkeyScope'; +import { RecordPickerComponentInstanceContext } from '@/object-record/record-picker/states/contexts/RecordPickerComponentInstanceContext'; import { UserOrMetadataLoader } from '~/loading/components/UserOrMetadataLoader'; export const ObjectMetadataItemsProvider = ({ diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useLimitPerMetadataItem.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useLimitPerMetadataItem.ts similarity index 100% rename from packages/twenty-front/src/modules/object-record/relation-picker/hooks/useLimitPerMetadataItem.ts rename to packages/twenty-front/src/modules/object-metadata/hooks/useLimitPerMetadataItem.ts diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/constants/TableColumnsDenyList.ts b/packages/twenty-front/src/modules/object-record/constants/TableColumnsDenyList.ts similarity index 100% rename from packages/twenty-front/src/modules/object-record/relation-picker/constants/TableColumnsDenyList.ts rename to packages/twenty-front/src/modules/object-record/constants/TableColumnsDenyList.ts diff --git a/packages/twenty-front/src/modules/object-record/multiple-objects/hooks/useCombinedFindManyRecords.ts b/packages/twenty-front/src/modules/object-record/multiple-objects/hooks/useCombinedFindManyRecords.ts index bdfc71f2b..f1126ccd7 100644 --- a/packages/twenty-front/src/modules/object-record/multiple-objects/hooks/useCombinedFindManyRecords.ts +++ b/packages/twenty-front/src/modules/object-record/multiple-objects/hooks/useCombinedFindManyRecords.ts @@ -5,7 +5,7 @@ import { EMPTY_QUERY } from '@/object-record/constants/EmptyQuery'; import { RecordGqlOperationSignature } from '@/object-record/graphql/types/RecordGqlOperationSignature'; import { useCombinedFindManyRecordsQueryVariables } from '@/object-record/multiple-objects/hooks/useCombinedFindManyRecordsQueryVariables'; import { useGenerateCombinedFindManyRecordsQuery } from '@/object-record/multiple-objects/hooks/useGenerateCombinedFindManyRecordsQuery'; -import { MultiObjectRecordQueryResult } from '@/object-record/relation-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray'; +import { MultiObjectRecordQueryResult } from '@/object-record/record-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray'; export const useCombinedFindManyRecords = ({ operationSignatures, diff --git a/packages/twenty-front/src/modules/object-record/multiple-objects/hooks/useCombinedGetTotalCount.ts b/packages/twenty-front/src/modules/object-record/multiple-objects/hooks/useCombinedGetTotalCount.ts index 65dd5ba05..de24981df 100644 --- a/packages/twenty-front/src/modules/object-record/multiple-objects/hooks/useCombinedGetTotalCount.ts +++ b/packages/twenty-front/src/modules/object-record/multiple-objects/hooks/useCombinedGetTotalCount.ts @@ -4,7 +4,7 @@ import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { EMPTY_QUERY } from '@/object-record/constants/EmptyQuery'; import { RecordGqlOperationSignature } from '@/object-record/graphql/types/RecordGqlOperationSignature'; import { useGenerateCombinedFindManyRecordsQuery } from '@/object-record/multiple-objects/hooks/useGenerateCombinedFindManyRecordsQuery'; -import { MultiObjectRecordQueryResult } from '@/object-record/relation-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray'; +import { MultiObjectRecordQueryResult } from '@/object-record/record-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray'; export const useCombinedGetTotalCount = ({ objectMetadataItems, diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownBooleanSelect.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownBooleanSelect.tsx index dee58b082..8600d4fe6 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownBooleanSelect.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownBooleanSelect.tsx @@ -8,7 +8,7 @@ import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-recor import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState'; import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState'; import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter'; -import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope'; +import { RelationPickerHotkeyScope } from '@/object-record/record-picker/legacy/types/RelationPickerHotkeyScope'; import { BooleanDisplay } from '@/ui/field/display/components/BooleanDisplay'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectMenuItem.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectMenuItem.tsx index 6c82acf3d..f868861db 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectMenuItem.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectMenuItem.tsx @@ -12,7 +12,7 @@ import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions'; import { isCompositeField } from '@/object-record/object-filter-dropdown/utils/isCompositeField'; import { getRecordFilterOperands } from '@/object-record/record-filter/utils/getRecordFilterOperands'; -import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope'; +import { RelationPickerHotkeyScope } from '@/object-record/record-picker/legacy/types/RelationPickerHotkeyScope'; import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList'; import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope'; import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2'; 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 70a096b50..7f199d315 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 @@ -5,8 +5,6 @@ import { v4 } from 'uuid'; import { FieldMetadataItemOption } from '@/object-metadata/types/FieldMetadataItem'; import { useOptionsForSelect } from '@/object-record/object-filter-dropdown/hooks/useOptionsForSelect'; -import { MULTI_OBJECT_RECORD_SELECT_SELECTABLE_LIST_ID } from '@/object-record/relation-picker/constants/MultiObjectRecordSelectSelectableListId'; -import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList'; @@ -14,13 +12,16 @@ import { useSelectableListStates } from '@/ui/layout/selectable-list/hooks/inter import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList'; import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions'; +import { ObjectFilterDropdownComponentInstanceContext } from '@/object-record/object-filter-dropdown/states/contexts/ObjectFilterDropdownComponentInstanceContext'; import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector'; import { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState'; import { objectFilterDropdownSelectedOptionValuesComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedOptionValuesComponentState'; import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState'; import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState'; import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter'; +import { RelationPickerHotkeyScope } from '@/object-record/record-picker/legacy/types/RelationPickerHotkeyScope'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; +import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { isDefined } from 'twenty-shared'; import { MenuItem, MenuItemMultiSelect } from 'twenty-ui'; @@ -53,17 +54,19 @@ export const ObjectFilterDropdownOptionSelect = () => { selectedOperandInDropdownComponentState, ); + const componentInstanceId = useAvailableComponentInstanceIdOrThrow( + ObjectFilterDropdownComponentInstanceContext, + ); + const { applyRecordFilter } = useApplyRecordFilter(); const { closeDropdown } = useDropdown(); const { selectedItemIdState } = useSelectableListStates({ - selectableListScopeId: MULTI_OBJECT_RECORD_SELECT_SELECTABLE_LIST_ID, + selectableListScopeId: componentInstanceId, }); - const { resetSelectedItem } = useSelectableList( - MULTI_OBJECT_RECORD_SELECT_SELECTABLE_LIST_ID, - ); + const { resetSelectedItem } = useSelectableList(componentInstanceId); const selectedItemId = useRecoilValue(selectedItemIdState); @@ -159,7 +162,7 @@ export const ObjectFilterDropdownOptionSelect = () => { return ( { 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 c8dd3a7da..39f7025ef 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 @@ -12,7 +12,7 @@ import { selectedFilterComponentState } from '@/object-record/object-filter-drop import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState'; import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter'; import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState'; -import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope'; +import { RelationPickerHotkeyScope } from '@/object-record/record-picker/legacy/types/RelationPickerHotkeyScope'; import { MultipleSelectDropdown } from '@/object-record/select/components/MultipleSelectDropdown'; import { useRecordsForSelect } from '@/object-record/select/hooks/useRecordsForSelect'; import { SelectableItem } from '@/object-record/select/types/SelectableItem'; diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownSourceSelect.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownSourceSelect.tsx index 1b47fb983..429d40f9b 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownSourceSelect.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownSourceSelect.tsx @@ -12,7 +12,7 @@ import { getActorSourceMultiSelectOptions } from '@/object-record/object-filter- import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter'; import { useRemoveRecordFilter } from '@/object-record/record-filter/hooks/useRemoveRecordFilter'; import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState'; -import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope'; +import { RelationPickerHotkeyScope } from '@/object-record/record-picker/legacy/types/RelationPickerHotkeyScope'; import { MultipleSelectDropdown } from '@/object-record/select/components/MultipleSelectDropdown'; import { SelectableItem } from '@/object-record/select/types/SelectableItem'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useSelectFilterUsedInDropdown.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useSelectFilterUsedInDropdown.ts index 45e7d5eda..a8ba4b154 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useSelectFilterUsedInDropdown.ts +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useSelectFilterUsedInDropdown.ts @@ -8,8 +8,8 @@ import { selectedOperandInDropdownComponentState } from '@/object-record/object- import { getInitialFilterValue } from '@/object-record/object-filter-dropdown/utils/getInitialFilterValue'; import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter'; import { getRecordFilterOperands } from '@/object-record/record-filter/utils/getRecordFilterOperands'; +import { RelationPickerHotkeyScope } from '@/object-record/record-picker/legacy/types/RelationPickerHotkeyScope'; -import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope'; import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; diff --git a/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnNewOpportunity.tsx b/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnNewOpportunity.tsx index 64dc0a747..5d3aacafc 100644 --- a/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnNewOpportunity.tsx +++ b/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnNewOpportunity.tsx @@ -2,11 +2,11 @@ import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSi import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord'; import { useAddNewCard } from '@/object-record/record-board/record-board-column/hooks/useAddNewCard'; import { recordBoardNewRecordByColumnIdSelector } from '@/object-record/record-board/states/selectors/recordBoardNewRecordByColumnIdSelector'; +import { SingleRecordPicker } from '@/object-record/record-picker/components/SingleRecordPicker'; +import { RelationPickerHotkeyScope } from '@/object-record/record-picker/legacy/types/RelationPickerHotkeyScope'; +import { RecordPickerComponentInstanceContext } from '@/object-record/record-picker/states/contexts/RecordPickerComponentInstanceContext'; import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState'; import { viewableRecordNameSingularState } from '@/object-record/record-right-drawer/states/viewableRecordNameSingularState'; -import { SingleRecordSelect } from '@/object-record/relation-picker/components/SingleRecordSelect'; -import { RecordPickerComponentInstanceContext } from '@/object-record/relation-picker/states/contexts/RecordPickerComponentInstanceContext'; -import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope'; import { OverlayContainer } from '@/ui/layout/overlay/components/OverlayContainer'; import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer'; import { RightDrawerPages } from '@/ui/layout/right-drawer/types/RightDrawerPages'; @@ -70,7 +70,7 @@ export const RecordBoardColumnNewOpportunity = ({ - handleCreateSuccess(position, columnId, false)} onRecordSelected={(company) => company ? handleEntitySelect(position, company) : null diff --git a/packages/twenty-front/src/modules/object-record/record-board/record-board-column/hooks/useAddNewCard.ts b/packages/twenty-front/src/modules/object-record/record-board/record-board-column/hooks/useAddNewCard.ts index 87e5d7569..59ec23036 100644 --- a/packages/twenty-front/src/modules/object-record/record-board/record-board-column/hooks/useAddNewCard.ts +++ b/packages/twenty-front/src/modules/object-record/record-board/record-board-column/hooks/useAddNewCard.ts @@ -1,9 +1,9 @@ import { RecordBoardContext } from '@/object-record/record-board/contexts/RecordBoardContext'; import { RecordBoardColumnContext } from '@/object-record/record-board/record-board-column/contexts/RecordBoardColumnContext'; import { recordBoardNewRecordByColumnIdSelector } from '@/object-record/record-board/states/selectors/recordBoardNewRecordByColumnIdSelector'; -import { useRecordSelectSearch } from '@/object-record/relation-picker/hooks/useRecordSelectSearch'; -import { RecordForSelect } from '@/object-record/relation-picker/types/RecordForSelect'; -import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope'; +import { useRecordSelectSearch } from '@/object-record/record-picker/hooks/useRecordSelectSearch'; +import { RelationPickerHotkeyScope } from '@/object-record/record-picker/legacy/types/RelationPickerHotkeyScope'; +import { SingleRecordPickerRecord } from '@/object-record/record-picker/types/SingleRecordPickerRecord'; import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope'; import { useCallback, useContext } from 'react'; import { RecoilState, useRecoilCallback } from 'recoil'; @@ -71,7 +71,7 @@ export const useAddNewCard = () => { labelValue: string, position: 'first' | 'last', isOpportunity: boolean, - company?: RecordForSelect, + company?: SingleRecordPickerRecord, ) => { if ( (isOpportunity && company !== null) || @@ -220,7 +220,7 @@ export const useAddNewCard = () => { const handleEntitySelect = useCallback( ( position: 'first' | 'last', - company: RecordForSelect, + company: SingleRecordPickerRecord, columnId?: string, ) => { const columnDefinitionId = getColumnDefinitionId(columnId); diff --git a/packages/twenty-front/src/modules/object-record/record-board/states/recordBoardNewRecordByColumnIdComponentFamilyState.ts b/packages/twenty-front/src/modules/object-record/record-board/states/recordBoardNewRecordByColumnIdComponentFamilyState.ts index df2cdc599..3bdbc7eed 100644 --- a/packages/twenty-front/src/modules/object-record/record-board/states/recordBoardNewRecordByColumnIdComponentFamilyState.ts +++ b/packages/twenty-front/src/modules/object-record/record-board/states/recordBoardNewRecordByColumnIdComponentFamilyState.ts @@ -1,4 +1,4 @@ -import { RecordForSelect } from '@/object-record/relation-picker/types/RecordForSelect'; +import { SingleRecordPickerRecord } from '@/object-record/record-picker/types/SingleRecordPickerRecord'; import { createComponentFamilyState } from '@/ui/utilities/state/component-state/utils/createComponentFamilyState'; export type NewCard = { @@ -7,7 +7,7 @@ export type NewCard = { isCreating: boolean; position: 'first' | 'last'; isOpportunity: boolean; - company: RecordForSelect | null; + company: SingleRecordPickerRecord | null; }; export const recordBoardNewRecordByColumnIdComponentFamilyState = diff --git a/packages/twenty-front/src/modules/object-record/record-field/form-types/components/FormMultiSelectFieldInput.tsx b/packages/twenty-front/src/modules/object-record/record-field/form-types/components/FormMultiSelectFieldInput.tsx index a50f4d147..b99c6ba23 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/form-types/components/FormMultiSelectFieldInput.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/form-types/components/FormMultiSelectFieldInput.tsx @@ -4,9 +4,10 @@ import { FormFieldInputContainer } from '@/object-record/record-field/form-types import { FormFieldInputInputContainer } from '@/object-record/record-field/form-types/components/FormFieldInputInputContainer'; import { FormFieldInputRowContainer } from '@/object-record/record-field/form-types/components/FormFieldInputRowContainer'; import { VariableChipStandalone } from '@/object-record/record-field/form-types/components/VariableChipStandalone'; +import { FormMultiSelectFieldInputHotKeyScope } from '@/object-record/record-field/form-types/constants/FormMultiSelectFieldInputHotKeyScope'; import { VariablePickerComponent } from '@/object-record/record-field/form-types/types/VariablePickerComponent'; +import { SELECT_FIELD_INPUT_SELECTABLE_LIST_COMPONENT_INSTANCE_ID } from '@/object-record/record-field/meta-types/input/constants/SelectFieldInputSelectableListComponentInstanceId'; import { FieldMultiSelectValue } from '@/object-record/record-field/types/FieldMetadata'; -import { MULTI_OBJECT_RECORD_SELECT_SELECTABLE_LIST_ID } from '@/object-record/relation-picker/constants/MultiObjectRecordSelectSelectableListId'; import { SelectOption } from '@/spreadsheet-import/types'; import { MultiSelectDisplay } from '@/ui/field/display/components/MultiSelectDisplay'; import { MultiSelectInput } from '@/ui/field/input/components/MultiSelectInput'; @@ -74,7 +75,8 @@ export const FormMultiSelectFieldInput = ({ const inputId = useId(); const theme = useTheme(); - const hotkeyScope = MULTI_OBJECT_RECORD_SELECT_SELECTABLE_LIST_ID; + const hotkeyScope = + FormMultiSelectFieldInputHotKeyScope.FormMultiSelectFieldInput; const { setHotkeyScopeAndMemorizePreviousScope, @@ -234,6 +236,9 @@ export const FormMultiSelectFieldInput = ({ draftValue.editingMode === 'edit' && ( ([]); const { resetSelectedItem } = useSelectableList( - SINGLE_RECORD_SELECT_BASE_LIST, + SELECT_FIELD_INPUT_SELECTABLE_LIST_COMPONENT_INSTANCE_ID, ); const clearField = () => { @@ -295,7 +295,9 @@ export const FormSelectFieldInput = ({ draftValue.editingMode === 'edit' && ( { ); if (fieldIsRelationToOneObject) { - const value = valueToPersist as RecordForSelect; + const value = valueToPersist as SingleRecordPickerRecord; updateRecord?.({ variables: { where: { id: recordId }, diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/useRelationField.ts b/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/useRelationField.ts index a7e847f27..1904588e1 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/useRelationField.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/useRelationField.ts @@ -5,15 +5,15 @@ import { useGetButtonIcon } from '@/object-record/record-field/hooks/useGetButto import { useRecordFieldInput } from '@/object-record/record-field/hooks/useRecordFieldInput'; import { FieldRelationValue } from '@/object-record/record-field/types/FieldMetadata'; import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector'; -import { RecordForSelect } from '@/object-record/relation-picker/types/RecordForSelect'; import { FieldMetadataType } from '~/generated-metadata/graphql'; +import { SingleRecordPickerRecord } from '@/object-record/record-picker/types/SingleRecordPickerRecord'; import { FieldContext } from '../../contexts/FieldContext'; import { assertFieldMetadata } from '../../types/guards/assertFieldMetadata'; import { isFieldRelation } from '../../types/guards/isFieldRelation'; export const useRelationField = < - T extends RecordForSelect | RecordForSelect[], + T extends SingleRecordPickerRecord | SingleRecordPickerRecord[], >() => { const { recordId, fieldDefinition, maxWidth } = useContext(FieldContext); const button = useGetButtonIcon(); diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/MultiSelectFieldInput.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/MultiSelectFieldInput.tsx index eb8939aa4..be8c2a57d 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/MultiSelectFieldInput.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/MultiSelectFieldInput.tsx @@ -1,4 +1,5 @@ import { useMultiSelectField } from '@/object-record/record-field/meta-types/hooks/useMultiSelectField'; +import { SELECT_FIELD_INPUT_SELECTABLE_LIST_COMPONENT_INSTANCE_ID } from '@/object-record/record-field/meta-types/input/constants/SelectFieldInputSelectableListComponentInstanceId'; import { MultiSelectInput } from '@/ui/field/input/components/MultiSelectInput'; type MultiSelectFieldInputProps = { @@ -13,6 +14,9 @@ export const MultiSelectFieldInput = ({ return ( - diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/RelationFromManyFieldInputMultiRecordsEffect.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/RelationFromManyFieldInputMultiRecordsEffect.tsx index 6ba293fd9..c349a808a 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/RelationFromManyFieldInputMultiRecordsEffect.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/RelationFromManyFieldInputMultiRecordsEffect.tsx @@ -5,15 +5,16 @@ import { useObjectRecordMultiSelectScopedStates } from '@/activities/hooks/useOb import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { useRelationField } from '@/object-record/record-field/meta-types/hooks/useRelationField'; import { objectRecordMultiSelectComponentFamilyState } from '@/object-record/record-field/states/objectRecordMultiSelectComponentFamilyState'; -import { useRecordPickerRecordsOptions } from '@/object-record/relation-picker/hooks/useRecordPickerRecordsOptions'; -import { RecordPickerComponentInstanceContext } from '@/object-record/relation-picker/states/contexts/RecordPickerComponentInstanceContext'; -import { RecordForSelect } from '@/object-record/relation-picker/types/RecordForSelect'; +import { useRecordPickerRecordsOptions } from '@/object-record/record-picker/hooks/useRecordPickerRecordsOptions'; +import { RecordPickerComponentInstanceContext } from '@/object-record/record-picker/states/contexts/RecordPickerComponentInstanceContext'; +import { SingleRecordPickerRecord } from '@/object-record/record-picker/types/SingleRecordPickerRecord'; import { ObjectRecordForSelect } from '@/object-record/types/ObjectRecordForSelect'; import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow'; import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; export const RelationFromManyFieldInputMultiRecordsEffect = () => { - const { fieldValue, fieldDefinition } = useRelationField(); + const { fieldValue, fieldDefinition } = + useRelationField(); const instanceId = useAvailableComponentInstanceIdOrThrow( RecordPickerComponentInstanceContext, ); @@ -113,7 +114,9 @@ export const RelationFromManyFieldInputMultiRecordsEffect = () => { useEffect(() => { setObjectRecordMultiSelectCheckedRecordsIds( fieldValue - ? fieldValue.map((fieldValueItem: RecordForSelect) => fieldValueItem.id) + ? fieldValue.map( + (fieldValueItem: SingleRecordPickerRecord) => fieldValueItem.id, + ) : [], ); }, [fieldValue, setObjectRecordMultiSelectCheckedRecordsIds]); diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/components/RelationPicker.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/RelationPicker.tsx similarity index 80% rename from packages/twenty-front/src/modules/object-record/relation-picker/components/RelationPicker.tsx rename to packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/RelationPicker.tsx index 3de101ad1..c2e297316 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/components/RelationPicker.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/RelationPicker.tsx @@ -5,15 +5,15 @@ import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadata import { FieldContext } from '@/object-record/record-field/contexts/FieldContext'; import { FieldDefinition } from '@/object-record/record-field/types/FieldDefinition'; import { FieldRelationMetadata } from '@/object-record/record-field/types/FieldMetadata'; -import { SearchPickerInitialValueEffect } from '@/object-record/relation-picker/components/SearchPickerInitialValueEffect'; -import { SingleRecordSelect } from '@/object-record/relation-picker/components/SingleRecordSelect'; -import { useAddNewRecordAndOpenRightDrawer } from '@/object-record/relation-picker/hooks/useAddNewRecordAndOpenRightDrawer'; -import { RecordForSelect } from '@/object-record/relation-picker/types/RecordForSelect'; -import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope'; +import { SingleRecordPicker } from '@/object-record/record-picker/components/SingleRecordPicker'; +import { useAddNewRecordAndOpenRightDrawer } from '@/object-record/record-picker/hooks/useAddNewRecordAndOpenRightDrawer'; +import { SearchPickerInitialValueEffect } from '@/object-record/record-picker/legacy/components/SearchPickerInitialValueEffect'; +import { RelationPickerHotkeyScope } from '@/object-record/record-picker/legacy/types/RelationPickerHotkeyScope'; +import { SingleRecordPickerRecord } from '@/object-record/record-picker/types/SingleRecordPickerRecord'; export type RelationPickerProps = { selectedRecordId?: string; - onSubmit: (selectedRecord: RecordForSelect | null) => void; + onSubmit: (selectedRecord: SingleRecordPickerRecord | null) => void; onCancel?: () => void; width?: number; excludedRecordIds?: string[]; @@ -33,7 +33,7 @@ export const RelationPicker = ({ const recordPickerInstanceId = RelationPickerHotkeyScope.RelationPicker; const handleRecordSelected = ( - selectedRecord: RecordForSelect | null | undefined, + selectedRecord: SingleRecordPickerRecord | null | undefined, ) => onSubmit(selectedRecord ?? null); const { objectMetadataItem: relationObjectMetadataItem } = @@ -63,7 +63,7 @@ export const RelationPicker = ({ initialValueForSearchFilter={initialSearchFilter} recordPickerInstanceId={recordPickerInstanceId} /> - { const { fieldDefinition, initialSearchValue, fieldValue } = - useRelationField(); + useRelationField(); const persistField = usePersistField(); - const handleSubmit = (newEntity: RecordForSelect | null) => { + const handleSubmit = (newEntity: SingleRecordPickerRecord | null) => { onSubmit?.(() => persistField(newEntity?.record ?? null)); }; diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/SelectFieldInput.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/SelectFieldInput.tsx index fd454d5fc..df4b17864 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/SelectFieldInput.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/SelectFieldInput.tsx @@ -1,7 +1,7 @@ import { useClearField } from '@/object-record/record-field/hooks/useClearField'; import { useSelectField } from '@/object-record/record-field/meta-types/hooks/useSelectField'; +import { SELECT_FIELD_INPUT_SELECTABLE_LIST_COMPONENT_INSTANCE_ID } from '@/object-record/record-field/meta-types/input/constants/SelectFieldInputSelectableListComponentInstanceId'; import { FieldInputEvent } from '@/object-record/record-field/types/FieldInputEvent'; -import { SINGLE_RECORD_SELECT_BASE_LIST } from '@/object-record/relation-picker/constants/SingleRecordSelectBaseList'; import { SelectOption } from '@/spreadsheet-import/types'; import { SelectInput } from '@/ui/field/input/components/SelectInput'; import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList'; @@ -25,7 +25,7 @@ export const SelectFieldInput = ({ const [filteredOptions, setFilteredOptions] = useState([]); const { resetSelectedItem } = useSelectableList( - SINGLE_RECORD_SELECT_BASE_LIST, + SELECT_FIELD_INPUT_SELECTABLE_LIST_COMPONENT_INSTANCE_ID, ); const clearField = useClearField(); @@ -61,7 +61,9 @@ export const SelectFieldInput = ({ return ( { diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/__stories__/RelationToOneFieldInput.stories.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/__stories__/RelationToOneFieldInput.stories.tsx index ce70f5d51..564f103ba 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/__stories__/RelationToOneFieldInput.stories.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/__stories__/RelationToOneFieldInput.stories.tsx @@ -18,7 +18,7 @@ import { } from '~/testing/mock-data/users'; import { FieldContextProvider } from '@/object-record/record-field/meta-types/components/FieldContextProvider'; -import { RecordPickerComponentInstanceContext } from '@/object-record/relation-picker/states/contexts/RecordPickerComponentInstanceContext'; +import { RecordPickerComponentInstanceContext } from '@/object-record/record-picker/states/contexts/RecordPickerComponentInstanceContext'; import { getCanvasElementForDropdownTesting } from 'twenty-ui'; import { RelationToOneFieldInput, diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/constants/SelectFieldInputSelectableListComponentInstanceId.ts b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/constants/SelectFieldInputSelectableListComponentInstanceId.ts new file mode 100644 index 000000000..400b8a99b --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/constants/SelectFieldInputSelectableListComponentInstanceId.ts @@ -0,0 +1,2 @@ +export const SELECT_FIELD_INPUT_SELECTABLE_LIST_COMPONENT_INSTANCE_ID = + 'select-field-input-selectable-list-component-instance-id'; diff --git a/packages/twenty-front/src/modules/object-record/record-field/types/FieldMetadata.ts b/packages/twenty-front/src/modules/object-record/record-field/types/FieldMetadata.ts index b02d03fb6..5d221e6bf 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/types/FieldMetadata.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/types/FieldMetadata.ts @@ -2,7 +2,7 @@ import { ThemeColor } from 'twenty-ui'; import { RATING_VALUES } from '@/object-record/record-field/meta-types/constants/RatingValues'; import { ZodHelperLiteral } from '@/object-record/record-field/types/ZodHelperLiteral'; -import { RecordForSelect } from '@/object-record/relation-picker/types/RecordForSelect'; +import { SingleRecordPickerRecord } from '@/object-record/record-picker/types/SingleRecordPickerRecord'; import { ConnectedAccountProvider } from 'twenty-shared'; import * as z from 'zod'; import { RelationDefinitionType } from '~/generated-metadata/graphql'; @@ -260,9 +260,9 @@ export type FieldRatingValue = (typeof RATING_VALUES)[number] | null; export type FieldSelectValue = string | null; export type FieldMultiSelectValue = string[] | null; -export type FieldRelationToOneValue = RecordForSelect | null; +export type FieldRelationToOneValue = SingleRecordPickerRecord | null; -export type FieldRelationFromManyValue = RecordForSelect[] | []; +export type FieldRelationFromManyValue = SingleRecordPickerRecord[] | []; export type FieldRelationValue< T extends FieldRelationToOneValue | FieldRelationFromManyValue, diff --git a/packages/twenty-front/src/modules/object-record/record-inline-cell/components/RecordInlineCell.tsx b/packages/twenty-front/src/modules/object-record/record-inline-cell/components/RecordInlineCell.tsx index a8f137771..1940f1fa4 100644 --- a/packages/twenty-front/src/modules/object-record/record-inline-cell/components/RecordInlineCell.tsx +++ b/packages/twenty-front/src/modules/object-record/record-inline-cell/components/RecordInlineCell.tsx @@ -9,12 +9,12 @@ import { useGetButtonIcon } from '@/object-record/record-field/hooks/useGetButto import { useIsFieldInputOnly } from '@/object-record/record-field/hooks/useIsFieldInputOnly'; import { FieldInputEvent } from '@/object-record/record-field/types/FieldInputEvent'; import { isFieldRelation } from '@/object-record/record-field/types/guards/isFieldRelation'; -import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope'; import { useInlineCell } from '../hooks/useInlineCell'; import { useIsFieldValueReadOnly } from '@/object-record/record-field/hooks/useIsFieldValueReadOnly'; import { FieldInputClickOutsideEvent } from '@/object-record/record-field/meta-types/input/components/DateTimeFieldInput'; +import { RelationPickerHotkeyScope } from '@/object-record/record-picker/legacy/types/RelationPickerHotkeyScope'; import { getDropdownFocusIdForRecordField } from '@/object-record/utils/getDropdownFocusIdForRecordField'; import { getRecordFieldInputId } from '@/object-record/utils/getRecordFieldInputId'; import { activeDropdownFocusIdState } from '@/ui/layout/dropdown/states/activeDropdownFocusIdState'; diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/components/MultiRecordSelect.tsx b/packages/twenty-front/src/modules/object-record/record-picker/components/MultipleRecordPicker.tsx similarity index 60% rename from packages/twenty-front/src/modules/object-record/relation-picker/components/MultiRecordSelect.tsx rename to packages/twenty-front/src/modules/object-record/record-picker/components/MultipleRecordPicker.tsx index 7fbab4dc4..c4b0a212a 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/components/MultiRecordSelect.tsx +++ b/packages/twenty-front/src/modules/object-record/record-picker/components/MultipleRecordPicker.tsx @@ -1,9 +1,8 @@ import { useObjectRecordMultiSelectScopedStates } from '@/activities/hooks/useObjectRecordMultiSelectScopedStates'; -import { MultipleObjectRecordOnClickOutsideEffect } from '@/object-record/relation-picker/components/MultipleObjectRecordOnClickOutsideEffect'; -import { MultipleObjectRecordSelectItem } from '@/object-record/relation-picker/components/MultipleObjectRecordSelectItem'; -import { MULTI_OBJECT_RECORD_SELECT_SELECTABLE_LIST_ID } from '@/object-record/relation-picker/constants/MultiObjectRecordSelectSelectableListId'; -import { RecordPickerComponentInstanceContext } from '@/object-record/relation-picker/states/contexts/RecordPickerComponentInstanceContext'; -import { recordPickerSearchFilterComponentState } from '@/object-record/relation-picker/states/recordPickerSearchFilterComponentState'; +import { MultipleRecordPickerMenuItem } from '@/object-record/record-picker/components/MultipleRecordPickerMenuItem'; +import { RECORD_PICKER_SELECTABLE_LIST_COMPONENT_INSTANCE_ID } from '@/object-record/record-picker/constants/RecordPickerSelectableListComponentInstanceId'; +import { RecordPickerComponentInstanceContext } from '@/object-record/record-picker/states/contexts/RecordPickerComponentInstanceContext'; +import { recordPickerSearchFilterComponentState } from '@/object-record/record-picker/states/recordPickerSearchFilterComponentState'; import { useHasObjectReadOnlyPermission } from '@/settings/roles/hooks/useHasObjectReadOnlyPermission'; import { CreateNewButton } from '@/ui/input/relation-picker/components/CreateNewButton'; import { DropdownMenuSkeletonItem } from '@/ui/input/relation-picker/components/skeletons/DropdownMenuSkeletonItem'; @@ -16,13 +15,13 @@ import { SelectableList } from '@/ui/layout/selectable-list/components/Selectabl import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList'; import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; -import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope'; +import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside'; import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; import styled from '@emotion/styled'; import { Placement } from '@floating-ui/react'; -import { useCallback, useEffect, useRef } from 'react'; +import { useCallback, useRef } from 'react'; import { useRecoilValue } from 'recoil'; import { Key } from 'ts-key-enum'; import { isDefined } from 'twenty-shared'; @@ -34,7 +33,7 @@ export const StyledSelectableItem = styled(SelectableItem)` width: 100%; `; -export const MultiRecordSelect = ({ +export const MultipleRecordPicker = ({ onChange, onSubmit, onCreate, @@ -46,7 +45,6 @@ export const MultiRecordSelect = ({ dropdownPlacement?: Placement | null; }) => { const containerRef = useRef(null); - const setHotkeyScope = useSetHotkeyScope(); const { goBackToPreviousHotkeyScope } = usePreviousHotkeyScope(); const instanceId = useAvailableComponentInstanceIdOrThrow( @@ -57,7 +55,7 @@ export const MultiRecordSelect = ({ useObjectRecordMultiSelectScopedStates(instanceId); const { resetSelectedItem } = useSelectableList( - MULTI_OBJECT_RECORD_SELECT_SELECTABLE_LIST_ID, + RECORD_PICKER_SELECTABLE_LIST_COMPONENT_INSTANCE_ID, ); const recordMultiSelectIsLoading = useRecoilValue( recordMultiSelectIsLoadingState, @@ -71,6 +69,7 @@ export const MultiRecordSelect = ({ recordPickerSearchFilterComponentState, instanceId, ); + const recordPickerSearchFilter = useRecoilComponentValueV2( recordPickerSearchFilterComponentState, instanceId, @@ -78,21 +77,28 @@ export const MultiRecordSelect = ({ const hasObjectReadOnlyPermission = useHasObjectReadOnlyPermission(); - useEffect(() => { - setHotkeyScope(instanceId); - }, [setHotkeyScope, instanceId]); + const handleSubmit = () => { + onSubmit?.(); + goBackToPreviousHotkeyScope(); + resetSelectedItem(); + }; useScopedHotkeys( Key.Escape, () => { - onSubmit?.(); - goBackToPreviousHotkeyScope(); - resetSelectedItem(); + handleSubmit(); }, instanceId, - [onSubmit, goBackToPreviousHotkeyScope, resetSelectedItem], + [handleSubmit], ); + useListenClickOutside({ + refs: [containerRef], + callback: handleSubmit, + listenerId: 'MULTI_RECORD_SELECT_LISTENER_ID', + hotkeyScope: instanceId, + }); + const handleFilterChange = useCallback( (event: React.ChangeEvent) => { setSearchFilter(event.currentTarget.value); @@ -104,7 +110,7 @@ export const MultiRecordSelect = ({ const results = ( { @@ -114,7 +120,7 @@ export const MultiRecordSelect = ({ > {objectRecordsIdsMultiSelect?.map((recordId) => { return ( - { @@ -137,61 +143,49 @@ export const MultiRecordSelect = ({ ); return ( - <> - { - onSubmit?.(); - }} + + {dropdownPlacement?.includes('end') && ( + <> + {isDefined(onCreate) && !hasObjectReadOnlyPermission && ( + + {createNewButton} + + )} + + {objectRecordsIdsMultiSelect?.length > 0 && results} + {recordMultiSelectIsLoading && !recordPickerSearchFilter && ( + <> + + + + )} + {objectRecordsIdsMultiSelect?.length > 0 && } + + )} + - - {dropdownPlacement?.includes('end') && ( - <> - {isDefined(onCreate) && !hasObjectReadOnlyPermission && ( - - {createNewButton} - - )} - - {objectRecordsIdsMultiSelect?.length > 0 && results} - {recordMultiSelectIsLoading && !recordPickerSearchFilter && ( - <> - - - - )} - {objectRecordsIdsMultiSelect?.length > 0 && ( + {(dropdownPlacement?.includes('start') || + isUndefinedOrNull(dropdownPlacement)) && ( + <> + + {recordMultiSelectIsLoading && !recordPickerSearchFilter && ( + <> + - )} - - )} - - {(dropdownPlacement?.includes('start') || - isUndefinedOrNull(dropdownPlacement)) && ( - <> - - {recordMultiSelectIsLoading && !recordPickerSearchFilter && ( - <> - - - - )} - {objectRecordsIdsMultiSelect?.length > 0 && results} - {objectRecordsIdsMultiSelect?.length > 0 && ( - - )} - {isDefined(onCreate) && ( - - {createNewButton} - - )} - - )} - - + + )} + {objectRecordsIdsMultiSelect?.length > 0 && results} + {objectRecordsIdsMultiSelect?.length > 0 && } + {isDefined(onCreate) && ( + + {createNewButton} + + )} + + )} + ); }; diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/components/MultipleObjectRecordSelectItem.tsx b/packages/twenty-front/src/modules/object-record/record-picker/components/MultipleRecordPickerMenuItem.tsx similarity index 88% rename from packages/twenty-front/src/modules/object-record/relation-picker/components/MultipleObjectRecordSelectItem.tsx rename to packages/twenty-front/src/modules/object-record/record-picker/components/MultipleRecordPickerMenuItem.tsx index 212b45651..71d10d812 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/components/MultipleObjectRecordSelectItem.tsx +++ b/packages/twenty-front/src/modules/object-record/record-picker/components/MultipleRecordPickerMenuItem.tsx @@ -3,8 +3,8 @@ import { useRecoilValue } from 'recoil'; import { Avatar, MenuItemMultiSelectAvatar } from 'twenty-ui'; import { useObjectRecordMultiSelectScopedStates } from '@/activities/hooks/useObjectRecordMultiSelectScopedStates'; -import { MULTI_OBJECT_RECORD_SELECT_SELECTABLE_LIST_ID } from '@/object-record/relation-picker/constants/MultiObjectRecordSelectSelectableListId'; -import { RecordPickerComponentInstanceContext } from '@/object-record/relation-picker/states/contexts/RecordPickerComponentInstanceContext'; +import { RECORD_PICKER_SELECTABLE_LIST_COMPONENT_INSTANCE_ID } from '@/object-record/record-picker/constants/RecordPickerSelectableListComponentInstanceId'; +import { RecordPickerComponentInstanceContext } from '@/object-record/record-picker/states/contexts/RecordPickerComponentInstanceContext'; import { SelectableItem } from '@/ui/layout/selectable-list/components/SelectableItem'; import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList'; import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow'; @@ -15,7 +15,7 @@ export const StyledSelectableItem = styled(SelectableItem)` width: 100%; `; -export const MultipleObjectRecordSelectItem = ({ +export const MultipleRecordPickerMenuItem = ({ objectRecordId, onChange, }: { @@ -23,7 +23,7 @@ export const MultipleObjectRecordSelectItem = ({ onChange?: (changedRecordForSelectId: string) => void; }) => { const { isSelectedItemIdSelector } = useSelectableList( - MULTI_OBJECT_RECORD_SELECT_SELECTABLE_LIST_ID, + RECORD_PICKER_SELECTABLE_LIST_COMPONENT_INSTANCE_ID, ); const isSelectedByKeyboard = useRecoilValue( diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/components/SingleRecordSelect.tsx b/packages/twenty-front/src/modules/object-record/record-picker/components/SingleRecordPicker.tsx similarity index 76% rename from packages/twenty-front/src/modules/object-record/relation-picker/components/SingleRecordSelect.tsx rename to packages/twenty-front/src/modules/object-record/record-picker/components/SingleRecordPicker.tsx index e2f4ded6e..e6fee93eb 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/components/SingleRecordSelect.tsx +++ b/packages/twenty-front/src/modules/object-record/record-picker/components/SingleRecordPicker.tsx @@ -1,18 +1,18 @@ import { useRef } from 'react'; import { - SingleRecordSelectMenuItemsWithSearch, - SingleRecordSelectMenuItemsWithSearchProps, -} from '@/object-record/relation-picker/components/SingleRecordSelectMenuItemsWithSearch'; + SingleRecordPickerMenuItemsWithSearch, + SingleRecordPickerMenuItemsWithSearchProps, +} from '@/object-record/record-picker/components/SingleRecordPickerMenuItemsWithSearch'; import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu'; import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside'; import { isDefined } from 'twenty-shared'; -export type SingleRecordSelectProps = { +export type SingleRecordPickerProps = { width?: number; -} & SingleRecordSelectMenuItemsWithSearchProps; +} & SingleRecordPickerMenuItemsWithSearchProps; -export const SingleRecordSelect = ({ +export const SingleRecordPicker = ({ EmptyIcon, emptyLabel, excludedRecordIds, @@ -22,7 +22,7 @@ export const SingleRecordSelect = ({ objectNameSingular, selectedRecordIds, width = 200, -}: SingleRecordSelectProps) => { +}: SingleRecordPickerProps) => { const containerRef = useRef(null); useListenClickOutside({ @@ -43,7 +43,7 @@ export const SingleRecordSelect = ({ return ( - void; - selectedRecord?: RecordForSelect; +type SingleRecordPickerMenuItemProps = { + record: SingleRecordPickerRecord; + onRecordSelected: (recordSelected?: SingleRecordPickerRecord) => void; + selectedRecord?: SingleRecordPickerRecord; }; const StyledSelectableItem = styled(SelectableItem)` width: 100%; `; -export const SelectableMenuItemSelect = ({ +export const SingleRecordPickerMenuItem = ({ record, onRecordSelected, selectedRecord, -}: SelectableMenuItemSelectProps) => { +}: SingleRecordPickerMenuItemProps) => { const { isSelectedItemIdSelector } = useSelectableList( - SINGLE_RECORD_SELECT_BASE_LIST, + RECORD_PICKER_SELECTABLE_LIST_COMPONENT_INSTANCE_ID, ); const isSelectedItemId = useRecoilValue(isSelectedItemIdSelector(record.id)); diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/components/SingleRecordSelectMenuItems.tsx b/packages/twenty-front/src/modules/object-record/record-picker/components/SingleRecordPickerMenuItems.tsx similarity index 78% rename from packages/twenty-front/src/modules/object-record/relation-picker/components/SingleRecordSelectMenuItems.tsx rename to packages/twenty-front/src/modules/object-record/record-picker/components/SingleRecordPickerMenuItems.tsx index 5217b7a3f..688556047 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/components/SingleRecordSelectMenuItems.tsx +++ b/packages/twenty-front/src/modules/object-record/record-picker/components/SingleRecordPickerMenuItems.tsx @@ -4,8 +4,6 @@ import { useRecoilValue } from 'recoil'; import { Key } from 'ts-key-enum'; import { IconComponent, MenuItemSelect } from 'twenty-ui'; -import { SelectableMenuItemSelect } from '@/object-record/relation-picker/components/SelectableMenuItemSelect'; -import { SINGLE_RECORD_SELECT_BASE_LIST } from '@/object-record/relation-picker/constants/SingleRecordSelectBaseList'; import { DropdownMenuSkeletonItem } from '@/ui/input/relation-picker/components/skeletons/DropdownMenuSkeletonItem'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList'; @@ -13,23 +11,25 @@ import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectab import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { isDefined } from 'twenty-shared'; -import { RecordForSelect } from '../types/RecordForSelect'; -import { RelationPickerHotkeyScope } from '../types/RelationPickerHotkeyScope'; +import { SingleRecordPickerMenuItem } from '@/object-record/record-picker/components/SingleRecordPickerMenuItem'; +import { RECORD_PICKER_SELECTABLE_LIST_COMPONENT_INSTANCE_ID } from '@/object-record/record-picker/constants/RecordPickerSelectableListComponentInstanceId'; +import { SingleRecordPickerRecord } from '@/object-record/record-picker/types/SingleRecordPickerRecord'; +import { RelationPickerHotkeyScope } from '../legacy/types/RelationPickerHotkeyScope'; -export type SingleRecordSelectMenuItemsProps = { +export type SingleRecordPickerMenuItemsProps = { EmptyIcon?: IconComponent; emptyLabel?: string; - recordsToSelect: RecordForSelect[]; + recordsToSelect: SingleRecordPickerRecord[]; loading?: boolean; onCancel?: () => void; - onRecordSelected: (entity?: RecordForSelect) => void; - selectedRecord?: RecordForSelect; + onRecordSelected: (entity?: SingleRecordPickerRecord) => void; + selectedRecord?: SingleRecordPickerRecord; hotkeyScope?: string; isFiltered: boolean; shouldSelectEmptyOption?: boolean; }; -export const SingleRecordSelectMenuItems = ({ +export const SingleRecordPickerMenuItems = ({ EmptyIcon, emptyLabel, recordsToSelect, @@ -40,7 +40,7 @@ export const SingleRecordSelectMenuItems = ({ hotkeyScope = RelationPickerHotkeyScope.RelationPicker, isFiltered, shouldSelectEmptyOption, -}: SingleRecordSelectMenuItemsProps) => { +}: SingleRecordPickerMenuItemsProps) => { const containerRef = useRef(null); const selectNone = emptyLabel @@ -56,12 +56,12 @@ export const SingleRecordSelectMenuItems = ({ selectedRecord, ...recordsToSelect, ].filter( - (entity): entity is RecordForSelect => + (entity): entity is SingleRecordPickerRecord => isDefined(entity) && isNonEmptyString(entity.name), ); const { isSelectedItemIdSelector, resetSelectedItem } = useSelectableList( - SINGLE_RECORD_SELECT_BASE_LIST, + RECORD_PICKER_SELECTABLE_LIST_COMPONENT_INSTANCE_ID, ); const isSelectedSelectNoneButton = useRecoilValue( @@ -83,7 +83,7 @@ export const SingleRecordSelectMenuItems = ({ return (
{ @@ -118,7 +118,7 @@ export const SingleRecordSelectMenuItems = ({ } default: { return ( - void) | (() => void); objectNameSingular: string; @@ -24,7 +26,7 @@ export type SingleRecordSelectMenuItemsWithSearchProps = { selectedRecordIds: string[]; dropdownPlacement?: Placement | null; } & Pick< - SingleRecordSelectMenuItemsProps, + SingleRecordPickerMenuItemsProps, | 'EmptyIcon' | 'emptyLabel' | 'onCancel' @@ -32,7 +34,7 @@ export type SingleRecordSelectMenuItemsWithSearchProps = { | 'selectedRecord' >; -export const SingleRecordSelectMenuItemsWithSearch = ({ +export const SingleRecordPickerMenuItemsWithSearch = ({ EmptyIcon, emptyLabel, excludedRecordIds, @@ -42,7 +44,7 @@ export const SingleRecordSelectMenuItemsWithSearch = ({ objectNameSingular, selectedRecordIds, dropdownPlacement, -}: SingleRecordSelectMenuItemsWithSearchProps) => { +}: SingleRecordPickerMenuItemsWithSearchProps) => { const { handleSearchFilterChange } = useRecordSelectSearch(); const recordPickerInstanceId = useAvailableComponentInstanceIdOrThrow( @@ -51,7 +53,12 @@ export const SingleRecordSelectMenuItemsWithSearch = ({ const hasObjectReadOnlyPermission = useHasObjectReadOnlyPermission(); - const { records, recordPickerSearchFilter } = useRecordPickerRecordsOptions({ + const recordPickerSearchFilter = useRecoilComponentValueV2( + recordPickerSearchFilterComponentState, + recordPickerInstanceId, + ); + + const { records } = useRecordPickerRecordsOptions({ objectNameSingular, selectedRecordIds, excludedRecordIds, @@ -79,7 +86,7 @@ export const SingleRecordSelectMenuItemsWithSearch = ({ )} {records.recordsToSelect.length > 0 && } {shouldDisplayDropdownMenuItems && ( - {shouldDisplayDropdownMenuItems && ( - ((person) => ({ +const records = peopleMock.map((person) => ({ id: person.id, name: person.name.firstName + ' ' + person.name.lastName, avatarUrl: 'https://picsum.photos/200', @@ -24,9 +24,9 @@ const records = peopleMock.map((person) => ({ record: { ...person, __typename: 'Person' }, })); -const meta: Meta = { - title: 'UI/Input/RelationPicker/SingleRecordSelect', - component: SingleRecordSelect, +const meta: Meta = { + title: 'UI/RecordPicker/SingleRecordPicker', + component: SingleRecordPicker, decorators: [ ComponentDecorator, ComponentWithRecoilScopeDecorator, @@ -53,7 +53,7 @@ const meta: Meta = { }; export default meta; -type Story = StoryObj; +type Story = StoryObj; export const Default: Story = {}; diff --git a/packages/twenty-front/src/modules/object-record/record-picker/constants/RecordPickerClickOutsideListenerId.ts b/packages/twenty-front/src/modules/object-record/record-picker/constants/RecordPickerClickOutsideListenerId.ts new file mode 100644 index 000000000..ec32e3fa3 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-picker/constants/RecordPickerClickOutsideListenerId.ts @@ -0,0 +1,2 @@ +export const RECORD_PICKER_CLICK_OUTSIDE_LISTENER_ID = + 'record-picker-click-outside-listener'; diff --git a/packages/twenty-front/src/modules/object-record/record-picker/constants/RecordPickerSelectableListComponentInstanceId.ts b/packages/twenty-front/src/modules/object-record/record-picker/constants/RecordPickerSelectableListComponentInstanceId.ts new file mode 100644 index 000000000..d41ddf475 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-picker/constants/RecordPickerSelectableListComponentInstanceId.ts @@ -0,0 +1,2 @@ +export const RECORD_PICKER_SELECTABLE_LIST_COMPONENT_INSTANCE_ID = + 'record-picker-selectable-list-component-instance-id'; diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useLimitPerMetadataItem.test.tsx b/packages/twenty-front/src/modules/object-record/record-picker/hooks/__tests__/useLimitPerMetadataItem.test.tsx similarity index 90% rename from packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useLimitPerMetadataItem.test.tsx rename to packages/twenty-front/src/modules/object-record/record-picker/hooks/__tests__/useLimitPerMetadataItem.test.tsx index b28747d6c..6100e8adf 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useLimitPerMetadataItem.test.tsx +++ b/packages/twenty-front/src/modules/object-record/record-picker/hooks/__tests__/useLimitPerMetadataItem.test.tsx @@ -1,9 +1,9 @@ import { renderHook } from '@testing-library/react'; import { RecoilRoot } from 'recoil'; +import { useLimitPerMetadataItem } from '@/object-metadata/hooks/useLimitPerMetadataItem'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; -import { useLimitPerMetadataItem } from '@/object-record/relation-picker/hooks/useLimitPerMetadataItem'; -import { RecordPickerComponentInstanceContext } from '@/object-record/relation-picker/states/contexts/RecordPickerComponentInstanceContext'; +import { RecordPickerComponentInstanceContext } from '@/object-record/record-picker/states/contexts/RecordPickerComponentInstanceContext'; const instanceId = 'instanceId'; const Wrapper = ({ children }: { children: React.ReactNode }) => ( 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/record-picker/hooks/__tests__/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray.test.tsx similarity index 94% rename from packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray.test.tsx rename to packages/twenty-front/src/modules/object-record/record-picker/hooks/__tests__/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray.test.tsx index 0b085cb56..a1f5f881c 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray.test.tsx +++ b/packages/twenty-front/src/modules/object-record/record-picker/hooks/__tests__/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray.test.tsx @@ -2,8 +2,8 @@ import { act, renderHook } from '@testing-library/react'; import { RecoilRoot, useSetRecoilState } from 'recoil'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; -import { useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray } from '@/object-record/relation-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray'; -import { RecordPickerComponentInstanceContext } from '@/object-record/relation-picker/states/contexts/RecordPickerComponentInstanceContext'; +import { useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray } from '@/object-record/record-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray'; +import { RecordPickerComponentInstanceContext } from '@/object-record/record-picker/states/contexts/RecordPickerComponentInstanceContext'; import { generatedMockObjectMetadataItems } from '~/testing/mock-data/generatedMockObjectMetadataItems'; const instanceId = 'instanceId'; diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useMultiObjectSearchQueryResultFormattedAsObjectRecordsMap.test.tsx b/packages/twenty-front/src/modules/object-record/record-picker/hooks/__tests__/useMultiObjectSearchQueryResultFormattedAsObjectRecordsMap.test.tsx similarity index 94% rename from packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useMultiObjectSearchQueryResultFormattedAsObjectRecordsMap.test.tsx rename to packages/twenty-front/src/modules/object-record/record-picker/hooks/__tests__/useMultiObjectSearchQueryResultFormattedAsObjectRecordsMap.test.tsx index b1a30bbfc..bd844ce54 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useMultiObjectSearchQueryResultFormattedAsObjectRecordsMap.test.tsx +++ b/packages/twenty-front/src/modules/object-record/record-picker/hooks/__tests__/useMultiObjectSearchQueryResultFormattedAsObjectRecordsMap.test.tsx @@ -2,8 +2,8 @@ import { act, renderHook } from '@testing-library/react'; import { RecoilRoot, useSetRecoilState } from 'recoil'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; -import { useMultiObjectSearchQueryResultFormattedAsObjectRecordsMap } from '@/object-record/relation-picker/hooks/useMultiObjectSearchQueryResultFormattedAsObjectRecordsMap'; -import { RecordPickerComponentInstanceContext } from '@/object-record/relation-picker/states/contexts/RecordPickerComponentInstanceContext'; +import { useMultiObjectSearchQueryResultFormattedAsObjectRecordsMap } from '@/object-record/record-picker/hooks/useMultiObjectSearchQueryResultFormattedAsObjectRecordsMap'; +import { RecordPickerComponentInstanceContext } from '@/object-record/record-picker/states/contexts/RecordPickerComponentInstanceContext'; import { generatedMockObjectMetadataItems } from '~/testing/mock-data/generatedMockObjectMetadataItems'; const instanceId = 'instanceId'; diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useRecordSelectSearch.test.tsx b/packages/twenty-front/src/modules/object-record/record-picker/hooks/__tests__/useRecordSelectSearch.test.tsx similarity index 85% rename from packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useRecordSelectSearch.test.tsx rename to packages/twenty-front/src/modules/object-record/record-picker/hooks/__tests__/useRecordSelectSearch.test.tsx index 3f521cf18..3f5763367 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useRecordSelectSearch.test.tsx +++ b/packages/twenty-front/src/modules/object-record/record-picker/hooks/__tests__/useRecordSelectSearch.test.tsx @@ -2,9 +2,9 @@ import { act, renderHook } from '@testing-library/react'; import { ChangeEvent } from 'react'; import { RecoilRoot } from 'recoil'; -import { useRecordSelectSearch } from '@/object-record/relation-picker/hooks/useRecordSelectSearch'; -import { RecordPickerComponentInstanceContext } from '@/object-record/relation-picker/states/contexts/RecordPickerComponentInstanceContext'; -import { recordPickerSearchFilterComponentState } from '@/object-record/relation-picker/states/recordPickerSearchFilterComponentState'; +import { useRecordSelectSearch } from '@/object-record/record-picker/hooks/useRecordSelectSearch'; +import { RecordPickerComponentInstanceContext } from '@/object-record/record-picker/states/contexts/RecordPickerComponentInstanceContext'; +import { recordPickerSearchFilterComponentState } from '@/object-record/record-picker/states/recordPickerSearchFilterComponentState'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; const instanceId = 'instanceId'; diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useAddNewRecordAndOpenRightDrawer.ts b/packages/twenty-front/src/modules/object-record/record-picker/hooks/useAddNewRecordAndOpenRightDrawer.ts similarity index 100% rename from packages/twenty-front/src/modules/object-record/relation-picker/hooks/useAddNewRecordAndOpenRightDrawer.ts rename to packages/twenty-front/src/modules/object-record/record-picker/hooks/useAddNewRecordAndOpenRightDrawer.ts diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray.ts b/packages/twenty-front/src/modules/object-record/record-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray.ts similarity index 96% rename from packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray.ts rename to packages/twenty-front/src/modules/object-record/record-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray.ts index a9087624f..698725a94 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray.ts +++ b/packages/twenty-front/src/modules/object-record/record-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray.ts @@ -4,7 +4,7 @@ import { useRecoilValue } from 'recoil'; import { objectMetadataItemsByNamePluralMapSelector } from '@/object-metadata/states/objectMetadataItemsByNamePluralMapSelector'; import { getObjectRecordIdentifier } from '@/object-metadata/utils/getObjectRecordIdentifier'; import { RecordGqlConnection } from '@/object-record/graphql/types/RecordGqlConnection'; -import { formatMultiObjectRecordSearchResults } from '@/object-record/relation-picker/utils/formatMultiObjectRecordSearchResults'; +import { formatMultiObjectRecordSearchResults } from '@/object-record/record-picker/utils/formatMultiObjectRecordSearchResults'; import { ObjectRecordForSelect } from '@/object-record/types/ObjectRecordForSelect'; import { isDefined } from 'twenty-shared'; diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectSearch.ts b/packages/twenty-front/src/modules/object-record/record-picker/hooks/useMultiObjectSearch.ts similarity index 92% rename from packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectSearch.ts rename to packages/twenty-front/src/modules/object-record/record-picker/hooks/useMultiObjectSearch.ts index 6b862a8e2..4f8fbd14d 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectSearch.ts +++ b/packages/twenty-front/src/modules/object-record/record-picker/hooks/useMultiObjectSearch.ts @@ -1,12 +1,12 @@ import { useQuery } from '@apollo/client'; import { useRecoilValue } from 'recoil'; +import { useLimitPerMetadataItem } from '@/object-metadata/hooks/useLimitPerMetadataItem'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { EMPTY_QUERY } from '@/object-record/constants/EmptyQuery'; import { useGenerateCombinedSearchRecordsQuery } from '@/object-record/multiple-objects/hooks/useGenerateCombinedSearchRecordsQuery'; -import { useLimitPerMetadataItem } from '@/object-record/relation-picker/hooks/useLimitPerMetadataItem'; -import { MultiObjectRecordQueryResult } from '@/object-record/relation-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray'; +import { MultiObjectRecordQueryResult } from '@/object-record/record-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray'; import { isObjectMetadataItemSearchableInCombinedRequest } from '@/object-record/utils/isObjectMetadataItemSearchableInCombinedRequest'; import { isDefined } from 'twenty-shared'; diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectSearchQueryResultFormattedAsObjectRecordsMap.ts b/packages/twenty-front/src/modules/object-record/record-picker/hooks/useMultiObjectSearchQueryResultFormattedAsObjectRecordsMap.ts similarity index 93% rename from packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectSearchQueryResultFormattedAsObjectRecordsMap.ts rename to packages/twenty-front/src/modules/object-record/record-picker/hooks/useMultiObjectSearchQueryResultFormattedAsObjectRecordsMap.ts index 2ab5ae565..bc105a01f 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectSearchQueryResultFormattedAsObjectRecordsMap.ts +++ b/packages/twenty-front/src/modules/object-record/record-picker/hooks/useMultiObjectSearchQueryResultFormattedAsObjectRecordsMap.ts @@ -3,8 +3,8 @@ import { useRecoilValue } from 'recoil'; import { objectMetadataItemsByNamePluralMapSelector } from '@/object-metadata/states/objectMetadataItemsByNamePluralMapSelector'; import { getObjectRecordIdentifier } from '@/object-metadata/utils/getObjectRecordIdentifier'; -import { MultiObjectRecordQueryResult } from '@/object-record/relation-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray'; -import { formatMultiObjectRecordSearchResults } from '@/object-record/relation-picker/utils/formatMultiObjectRecordSearchResults'; +import { MultiObjectRecordQueryResult } from '@/object-record/record-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray'; +import { formatMultiObjectRecordSearchResults } from '@/object-record/record-picker/utils/formatMultiObjectRecordSearchResults'; import { ObjectRecordForSelect } from '@/object-record/types/ObjectRecordForSelect'; import { isDefined } from 'twenty-shared'; diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectSearchSelectedItemsQuery.ts b/packages/twenty-front/src/modules/object-record/record-picker/hooks/useMultiObjectSearchSelectedItemsQuery.ts similarity index 91% rename from packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectSearchSelectedItemsQuery.ts rename to packages/twenty-front/src/modules/object-record/record-picker/hooks/useMultiObjectSearchSelectedItemsQuery.ts index 34c2be761..9c44a7ad4 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useMultiObjectSearchSelectedItemsQuery.ts +++ b/packages/twenty-front/src/modules/object-record/record-picker/hooks/useMultiObjectSearchSelectedItemsQuery.ts @@ -2,14 +2,14 @@ import { gql, useQuery } from '@apollo/client'; import { isNonEmptyArray } from '@sniptt/guards'; import { useRecoilValue } from 'recoil'; +import { useLimitPerMetadataItem } from '@/object-metadata/hooks/useLimitPerMetadataItem'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; import { useGenerateCombinedFindManyRecordsQuery } from '@/object-record/multiple-objects/hooks/useGenerateCombinedFindManyRecordsQuery'; -import { useLimitPerMetadataItem } from '@/object-record/relation-picker/hooks/useLimitPerMetadataItem'; import { MultiObjectRecordQueryResult, useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray, -} from '@/object-record/relation-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray'; -import { useOrderByFieldPerMetadataItem } from '@/object-record/relation-picker/hooks/useOrderByFieldPerMetadataItem'; +} from '@/object-record/record-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray'; +import { useOrderByFieldPerMetadataItem } from '@/object-record/record-picker/hooks/useOrderByFieldPerMetadataItem'; import { SelectedObjectRecordId } from '@/object-record/types/SelectedObjectRecordId'; import { capitalize, isDefined } from 'twenty-shared'; diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useOrderByFieldPerMetadataItem.ts b/packages/twenty-front/src/modules/object-record/record-picker/hooks/useOrderByFieldPerMetadataItem.ts similarity index 100% rename from packages/twenty-front/src/modules/object-record/relation-picker/hooks/useOrderByFieldPerMetadataItem.ts rename to packages/twenty-front/src/modules/object-record/record-picker/hooks/useOrderByFieldPerMetadataItem.ts diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useRecordPickerRecordsOptions.ts b/packages/twenty-front/src/modules/object-record/record-picker/hooks/useRecordPickerRecordsOptions.ts similarity index 87% rename from packages/twenty-front/src/modules/object-record/relation-picker/hooks/useRecordPickerRecordsOptions.ts rename to packages/twenty-front/src/modules/object-record/record-picker/hooks/useRecordPickerRecordsOptions.ts index 9064a67ad..9c21f8572 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useRecordPickerRecordsOptions.ts +++ b/packages/twenty-front/src/modules/object-record/record-picker/hooks/useRecordPickerRecordsOptions.ts @@ -1,4 +1,4 @@ -import { recordPickerSearchFilterComponentState } from '@/object-record/relation-picker/states/recordPickerSearchFilterComponentState'; +import { recordPickerSearchFilterComponentState } from '@/object-record/record-picker/states/recordPickerSearchFilterComponentState'; import { useFilteredSearchRecordQuery } from '@/search/hooks/useFilteredSearchRecordQuery'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; @@ -22,5 +22,5 @@ export const useRecordPickerRecordsOptions = ({ objectNameSingular, }); - return { records, recordPickerSearchFilter }; + return { records }; }; diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useRecordSelectSearch.ts b/packages/twenty-front/src/modules/object-record/record-picker/hooks/useRecordSelectSearch.ts similarity index 50% rename from packages/twenty-front/src/modules/object-record/relation-picker/hooks/useRecordSelectSearch.ts rename to packages/twenty-front/src/modules/object-record/record-picker/hooks/useRecordSelectSearch.ts index 1e615cb1f..0d0191ba5 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useRecordSelectSearch.ts +++ b/packages/twenty-front/src/modules/object-record/record-picker/hooks/useRecordSelectSearch.ts @@ -1,15 +1,22 @@ +import { recordPickerPreselectedIdComponentState } from '@/object-record/record-picker/states/recordPickerPreselectedIdComponentState'; +import { recordPickerSearchFilterComponentState } from '@/object-record/record-picker/states/recordPickerSearchFilterComponentState'; +import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; import { useDebouncedCallback } from 'use-debounce'; -import { useRecordPicker } from '@/object-record/relation-picker/hooks/useRecordPicker'; - export const useRecordSelectSearch = ({ recordPickerInstanceId, }: { recordPickerInstanceId?: string; } = {}) => { - const { setRecordPickerSearchFilter, setRecordPickerPreselectedId } = - useRecordPicker({ recordPickerInstanceId }); + const setRecordPickerSearchFilter = useSetRecoilComponentStateV2( + recordPickerSearchFilterComponentState, + recordPickerInstanceId, + ); + const setRecordPickerPreselectedId = useSetRecoilComponentStateV2( + recordPickerPreselectedIdComponentState, + recordPickerInstanceId, + ); const debouncedSetSearchFilter = useDebouncedCallback( setRecordPickerSearchFilter, 100, diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/components/ActivityTargetInlineCellEditModeMultiRecordsEffect.tsx b/packages/twenty-front/src/modules/object-record/record-picker/legacy/components/ActivityTargetInlineCellEditModeMultiRecordsEffect.tsx similarity index 96% rename from packages/twenty-front/src/modules/object-record/relation-picker/components/ActivityTargetInlineCellEditModeMultiRecordsEffect.tsx rename to packages/twenty-front/src/modules/object-record/record-picker/legacy/components/ActivityTargetInlineCellEditModeMultiRecordsEffect.tsx index e95b0aeaa..79ea56f9f 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/components/ActivityTargetInlineCellEditModeMultiRecordsEffect.tsx +++ b/packages/twenty-front/src/modules/object-record/record-picker/legacy/components/ActivityTargetInlineCellEditModeMultiRecordsEffect.tsx @@ -9,12 +9,13 @@ import { import { useObjectRecordMultiSelectScopedStates } from '@/activities/hooks/useObjectRecordMultiSelectScopedStates'; import { objectRecordMultiSelectComponentFamilyState } from '@/object-record/record-field/states/objectRecordMultiSelectComponentFamilyState'; import { objectRecordMultiSelectMatchesFilterRecordsIdsComponentState } from '@/object-record/record-field/states/objectRecordMultiSelectMatchesFilterRecordsIdsComponentState'; -import { RecordPickerComponentInstanceContext } from '@/object-record/relation-picker/states/contexts/RecordPickerComponentInstanceContext'; +import { RecordPickerComponentInstanceContext } from '@/object-record/record-picker/states/contexts/RecordPickerComponentInstanceContext'; import { ObjectRecordForSelect } from '@/object-record/types/ObjectRecordForSelect'; import { SelectedObjectRecordId } from '@/object-record/types/SelectedObjectRecordId'; import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow'; import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; +// Todo: this effect should be deprecated to use sync hooks export const ActivityTargetInlineCellEditModeMultiRecordsEffect = ({ selectedObjectRecordIds, }: { diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/components/ActivityTargetInlineCellEditModeMultiRecordsSearchFilterEffect.tsx b/packages/twenty-front/src/modules/object-record/record-picker/legacy/components/ActivityTargetInlineCellEditModeMultiRecordsSearchFilterEffect.tsx similarity index 82% rename from packages/twenty-front/src/modules/object-record/relation-picker/components/ActivityTargetInlineCellEditModeMultiRecordsSearchFilterEffect.tsx rename to packages/twenty-front/src/modules/object-record/record-picker/legacy/components/ActivityTargetInlineCellEditModeMultiRecordsSearchFilterEffect.tsx index 876c02865..323b4374e 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/components/ActivityTargetInlineCellEditModeMultiRecordsSearchFilterEffect.tsx +++ b/packages/twenty-front/src/modules/object-record/record-picker/legacy/components/ActivityTargetInlineCellEditModeMultiRecordsSearchFilterEffect.tsx @@ -3,13 +3,14 @@ import { useSetRecoilState } from 'recoil'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { objectRecordMultiSelectMatchesFilterRecordsIdsComponentState } from '@/object-record/record-field/states/objectRecordMultiSelectMatchesFilterRecordsIdsComponentState'; -import { useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray } from '@/object-record/relation-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray'; -import { useMultiObjectSearch } from '@/object-record/relation-picker/hooks/useMultiObjectSearch'; -import { RecordPickerComponentInstanceContext } from '@/object-record/relation-picker/states/contexts/RecordPickerComponentInstanceContext'; -import { recordPickerSearchFilterComponentState } from '@/object-record/relation-picker/states/recordPickerSearchFilterComponentState'; +import { useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray } from '@/object-record/record-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray'; +import { useMultiObjectSearch } from '@/object-record/record-picker/hooks/useMultiObjectSearch'; +import { RecordPickerComponentInstanceContext } from '@/object-record/record-picker/states/contexts/RecordPickerComponentInstanceContext'; +import { recordPickerSearchFilterComponentState } from '@/object-record/record-picker/states/recordPickerSearchFilterComponentState'; import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +// Todo: this effect should be deprecated to use sync hooks export const ActivityTargetInlineCellEditModeMultiRecordsSearchFilterEffect = () => { const instanceId = useAvailableComponentInstanceIdOrThrow( diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/components/MultipleObjectRecordOnClickOutsideEffect.tsx b/packages/twenty-front/src/modules/object-record/record-picker/legacy/components/MultipleObjectRecordOnClickOutsideEffect.tsx similarity index 81% rename from packages/twenty-front/src/modules/object-record/relation-picker/components/MultipleObjectRecordOnClickOutsideEffect.tsx rename to packages/twenty-front/src/modules/object-record/record-picker/legacy/components/MultipleObjectRecordOnClickOutsideEffect.tsx index 2fe72f8c7..519771c92 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/components/MultipleObjectRecordOnClickOutsideEffect.tsx +++ b/packages/twenty-front/src/modules/object-record/record-picker/legacy/components/MultipleObjectRecordOnClickOutsideEffect.tsx @@ -1,10 +1,11 @@ import { useEffect } from 'react'; -import { MULTI_OBJECT_RECORD_CLICK_OUTSIDE_LISTENER_ID } from '@/object-record/relation-picker/constants/MultiObjectRecordClickOutsideListenerId'; +import { RECORD_PICKER_CLICK_OUTSIDE_LISTENER_ID } from '@/object-record/record-picker/constants/RecordPickerClickOutsideListenerId'; import { RIGHT_DRAWER_CLICK_OUTSIDE_LISTENER_ID } from '@/ui/layout/right-drawer/constants/RightDrawerClickOutsideListener'; import { useClickOutsideListener } from '@/ui/utilities/pointer-event/hooks/useClickOutsideListener'; import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside'; +// Todo: this effect should be deprecated to use sync hooks export const MultipleObjectRecordOnClickOutsideEffect = ({ containerRef, onClickOutside, @@ -32,7 +33,7 @@ export const MultipleObjectRecordOnClickOutsideEffect = ({ onClickOutside(); }, - listenerId: MULTI_OBJECT_RECORD_CLICK_OUTSIDE_LISTENER_ID, + listenerId: RECORD_PICKER_CLICK_OUTSIDE_LISTENER_ID, }); return <>; diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/components/SearchPickerInitialValueEffect.tsx b/packages/twenty-front/src/modules/object-record/record-picker/legacy/components/SearchPickerInitialValueEffect.tsx similarity index 85% rename from packages/twenty-front/src/modules/object-record/relation-picker/components/SearchPickerInitialValueEffect.tsx rename to packages/twenty-front/src/modules/object-record/record-picker/legacy/components/SearchPickerInitialValueEffect.tsx index 85e2206ae..4aca4ca06 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/components/SearchPickerInitialValueEffect.tsx +++ b/packages/twenty-front/src/modules/object-record/record-picker/legacy/components/SearchPickerInitialValueEffect.tsx @@ -1,7 +1,8 @@ -import { recordPickerSearchFilterComponentState } from '@/object-record/relation-picker/states/recordPickerSearchFilterComponentState'; +import { recordPickerSearchFilterComponentState } from '@/object-record/record-picker/states/recordPickerSearchFilterComponentState'; import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; import { useEffect } from 'react'; +// Todo: this effect should be deprecated to use sync hooks export const SearchPickerInitialValueEffect = ({ initialValueForSearchFilter, recordPickerInstanceId, diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/types/RelationPickerHotkeyScope.ts b/packages/twenty-front/src/modules/object-record/record-picker/legacy/types/RelationPickerHotkeyScope.ts similarity index 100% rename from packages/twenty-front/src/modules/object-record/relation-picker/types/RelationPickerHotkeyScope.ts rename to packages/twenty-front/src/modules/object-record/record-picker/legacy/types/RelationPickerHotkeyScope.ts diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/states/contexts/RecordPickerComponentInstanceContext.ts b/packages/twenty-front/src/modules/object-record/record-picker/states/contexts/RecordPickerComponentInstanceContext.ts similarity index 100% rename from packages/twenty-front/src/modules/object-record/relation-picker/states/contexts/RecordPickerComponentInstanceContext.ts rename to packages/twenty-front/src/modules/object-record/record-picker/states/contexts/RecordPickerComponentInstanceContext.ts diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/states/recordPickerPreselectedIdComponentState.ts b/packages/twenty-front/src/modules/object-record/record-picker/states/recordPickerPreselectedIdComponentState.ts similarity index 84% rename from packages/twenty-front/src/modules/object-record/relation-picker/states/recordPickerPreselectedIdComponentState.ts rename to packages/twenty-front/src/modules/object-record/record-picker/states/recordPickerPreselectedIdComponentState.ts index f03247a20..4967b443b 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/states/recordPickerPreselectedIdComponentState.ts +++ b/packages/twenty-front/src/modules/object-record/record-picker/states/recordPickerPreselectedIdComponentState.ts @@ -1,4 +1,4 @@ -import { RecordPickerComponentInstanceContext } from '@/object-record/relation-picker/states/contexts/RecordPickerComponentInstanceContext'; +import { RecordPickerComponentInstanceContext } from '@/object-record/record-picker/states/contexts/RecordPickerComponentInstanceContext'; import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; export const recordPickerPreselectedIdComponentState = createComponentStateV2< diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/states/recordPickerSearchFilterComponentState.ts b/packages/twenty-front/src/modules/object-record/record-picker/states/recordPickerSearchFilterComponentState.ts similarity index 84% rename from packages/twenty-front/src/modules/object-record/relation-picker/states/recordPickerSearchFilterComponentState.ts rename to packages/twenty-front/src/modules/object-record/record-picker/states/recordPickerSearchFilterComponentState.ts index b0e5efc40..d6fe3b983 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/states/recordPickerSearchFilterComponentState.ts +++ b/packages/twenty-front/src/modules/object-record/record-picker/states/recordPickerSearchFilterComponentState.ts @@ -1,4 +1,4 @@ -import { RecordPickerComponentInstanceContext } from '@/object-record/relation-picker/states/contexts/RecordPickerComponentInstanceContext'; +import { RecordPickerComponentInstanceContext } from '@/object-record/record-picker/states/contexts/RecordPickerComponentInstanceContext'; import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; export const recordPickerSearchFilterComponentState = diff --git a/packages/twenty-front/src/modules/object-record/record-picker/states/recordPickerSearchQueryComponentState.ts b/packages/twenty-front/src/modules/object-record/record-picker/states/recordPickerSearchQueryComponentState.ts new file mode 100644 index 000000000..cf8d9a1b7 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-picker/states/recordPickerSearchQueryComponentState.ts @@ -0,0 +1,10 @@ +import { RecordPickerComponentInstanceContext } from '@/object-record/record-picker/states/contexts/RecordPickerComponentInstanceContext'; +import { RecordPickerSearchQuery } from '@/object-record/record-picker/types/RecordPickerSearchQuery'; +import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; + +export const recordPickerSearchQueryComponentState = + createComponentStateV2({ + key: 'recordPickerSearchQueryComponentState', + defaultValue: null, + componentInstanceContext: RecordPickerComponentInstanceContext, + }); diff --git a/packages/twenty-front/src/modules/object-record/record-picker/types/MultipleRecordPickerRecords.ts b/packages/twenty-front/src/modules/object-record/record-picker/types/MultipleRecordPickerRecords.ts new file mode 100644 index 000000000..ff2c78f10 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-picker/types/MultipleRecordPickerRecords.ts @@ -0,0 +1,10 @@ +import { SingleRecordPickerRecord } from '@/object-record/record-picker/types/SingleRecordPickerRecord'; + +export type MultipleRecordPickerRecords< + CustomRecordForRecordPicker extends SingleRecordPickerRecord, +> = { + selectedRecords: CustomRecordForRecordPicker[]; + filteredSelectedRecords: CustomRecordForRecordPicker[]; + recordsToSelect: CustomRecordForRecordPicker[]; + loading: boolean; +}; diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/types/SearchQuery.tsx b/packages/twenty-front/src/modules/object-record/record-picker/types/RecordPickerSearchQuery.ts similarity index 62% rename from packages/twenty-front/src/modules/object-record/relation-picker/types/SearchQuery.tsx rename to packages/twenty-front/src/modules/object-record/record-picker/types/RecordPickerSearchQuery.ts index 1559ab41d..d622db5a6 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/types/SearchQuery.tsx +++ b/packages/twenty-front/src/modules/object-record/record-picker/types/RecordPickerSearchQuery.ts @@ -1,3 +1,3 @@ -export type SearchQuery = { +export type RecordPickerSearchQuery = { computeFilterFields: (relationPickerType: string) => string[]; }; diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/types/RecordForSelect.ts b/packages/twenty-front/src/modules/object-record/record-picker/types/SingleRecordPickerRecord.ts similarity index 73% rename from packages/twenty-front/src/modules/object-record/relation-picker/types/RecordForSelect.ts rename to packages/twenty-front/src/modules/object-record/record-picker/types/SingleRecordPickerRecord.ts index a2cd90af7..ff7564e5f 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/types/RecordForSelect.ts +++ b/packages/twenty-front/src/modules/object-record/record-picker/types/SingleRecordPickerRecord.ts @@ -1,6 +1,6 @@ import { ObjectRecord } from '@/object-record/types/ObjectRecord'; import { ObjectRecordIdentifier } from '@/object-record/types/ObjectRecordIdentifier'; -export type RecordForSelect = ObjectRecordIdentifier & { +export type SingleRecordPickerRecord = ObjectRecordIdentifier & { record: ObjectRecord; }; diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/utils/formatMultiObjectRecordSearchResults.ts b/packages/twenty-front/src/modules/object-record/record-picker/utils/formatMultiObjectRecordSearchResults.ts similarity index 85% rename from packages/twenty-front/src/modules/object-record/relation-picker/utils/formatMultiObjectRecordSearchResults.ts rename to packages/twenty-front/src/modules/object-record/record-picker/utils/formatMultiObjectRecordSearchResults.ts index 318f12ab7..3de525aea 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/utils/formatMultiObjectRecordSearchResults.ts +++ b/packages/twenty-front/src/modules/object-record/record-picker/utils/formatMultiObjectRecordSearchResults.ts @@ -1,4 +1,4 @@ -import { MultiObjectRecordQueryResult } from '@/object-record/relation-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray'; +import { MultiObjectRecordQueryResult } from '@/object-record/record-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray'; export const formatMultiObjectRecordSearchResults = ( searchResults: MultiObjectRecordQueryResult | undefined | null, 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 6d70fa916..db16b15f6 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 @@ -11,17 +11,17 @@ import { usePersistField } from '@/object-record/record-field/hooks/usePersistFi import { RelationFromManyFieldInputMultiRecordsEffect } from '@/object-record/record-field/meta-types/input/components/RelationFromManyFieldInputMultiRecordsEffect'; import { useUpdateRelationFromManyFieldInput } from '@/object-record/record-field/meta-types/input/hooks/useUpdateRelationFromManyFieldInput'; import { FieldRelationMetadata } from '@/object-record/record-field/types/FieldMetadata'; +import { MultipleRecordPicker } from '@/object-record/record-picker/components/MultipleRecordPicker'; +import { SingleRecordPickerMenuItemsWithSearch } from '@/object-record/record-picker/components/SingleRecordPickerMenuItemsWithSearch'; +import { useAddNewRecordAndOpenRightDrawer } from '@/object-record/record-picker/hooks/useAddNewRecordAndOpenRightDrawer'; +import { RecordPickerComponentInstanceContext } from '@/object-record/record-picker/states/contexts/RecordPickerComponentInstanceContext'; +import { recordPickerSearchFilterComponentState } from '@/object-record/record-picker/states/recordPickerSearchFilterComponentState'; +import { SingleRecordPickerRecord } from '@/object-record/record-picker/types/SingleRecordPickerRecord'; import { RecordDetailRelationRecordsList } from '@/object-record/record-show/record-detail-section/components/RecordDetailRelationRecordsList'; import { RecordDetailSection } from '@/object-record/record-show/record-detail-section/components/RecordDetailSection'; import { RecordDetailSectionHeader } from '@/object-record/record-show/record-detail-section/components/RecordDetailSectionHeader'; import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState'; import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector'; -import { MultiRecordSelect } from '@/object-record/relation-picker/components/MultiRecordSelect'; -import { SingleRecordSelectMenuItemsWithSearch } from '@/object-record/relation-picker/components/SingleRecordSelectMenuItemsWithSearch'; -import { useAddNewRecordAndOpenRightDrawer } from '@/object-record/relation-picker/hooks/useAddNewRecordAndOpenRightDrawer'; -import { useRecordPicker } from '@/object-record/relation-picker/hooks/useRecordPicker'; -import { RecordPickerComponentInstanceContext } from '@/object-record/relation-picker/states/contexts/RecordPickerComponentInstanceContext'; -import { RecordForSelect } from '@/object-record/relation-picker/types/RecordForSelect'; import { ObjectRecord } from '@/object-record/types/ObjectRecord'; import { prefetchIndexViewIdFromObjectMetadataItemFamilySelector } from '@/prefetch/states/selector/prefetchIndexViewIdFromObjectMetadataItemFamilySelector'; import { AppPath } from '@/types/AppPath'; @@ -29,6 +29,7 @@ import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope'; import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; +import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; import { useLingui } from '@lingui/react/macro'; import { RelationDefinitionType } from '~/generated-metadata/graphql'; @@ -84,9 +85,10 @@ export const RecordDetailRelationSection = ({ const { closeDropdown, isDropdownOpen, dropdownPlacement } = useDropdown(dropdownId); - const { setRecordPickerSearchFilter } = useRecordPicker({ - recordPickerInstanceId: dropdownId, - }); + const setRecordPickerSearchFilter = useSetRecoilComponentStateV2( + recordPickerSearchFilterComponentState, + dropdownId, + ); const handleCloseRelationPickerDropdown = useCallback(() => { setRecordPickerSearchFilter(''); @@ -98,7 +100,7 @@ export const RecordDetailRelationSection = ({ }); const handleRelationPickerEntitySelected = ( - selectedRelationEntity?: RecordForSelect, + selectedRelationEntity?: SingleRecordPickerRecord, ) => { closeDropdown(); @@ -204,7 +206,7 @@ export const RecordDetailRelationSection = ({ value={{ instanceId: dropdownId }} > {isToOneObject ? ( - - { closeDropdown(); createNewRecordAndOpenRightDrawer?.(); diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellFieldContextWrapper.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellFieldContextWrapper.tsx index 85dc17ab5..dae0602c0 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellFieldContextWrapper.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellFieldContextWrapper.tsx @@ -5,12 +5,12 @@ import { FieldContext } from '@/object-record/record-field/contexts/FieldContext import { isFieldRelation } from '@/object-record/record-field/types/guards/isFieldRelation'; import { isFieldSelect } from '@/object-record/record-field/types/guards/isFieldSelect'; import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext'; +import { RelationPickerHotkeyScope } from '@/object-record/record-picker/legacy/types/RelationPickerHotkeyScope'; import { RecordUpdateContext } from '@/object-record/record-table/contexts/EntityUpdateMutationHookContext'; import { RecordTableCellContext } from '@/object-record/record-table/contexts/RecordTableCellContext'; import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext'; import { useRecordTableRowContextOrThrow } from '@/object-record/record-table/contexts/RecordTableRowContext'; import { TableHotkeyScope } from '@/object-record/record-table/types/TableHotkeyScope'; -import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope'; import { SelectFieldHotkeyScope } from '@/object-record/select/types/SelectFieldHotkeyScope'; import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull'; diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/constants/MultiObjectRecordClickOutsideListenerId.ts b/packages/twenty-front/src/modules/object-record/relation-picker/constants/MultiObjectRecordClickOutsideListenerId.ts deleted file mode 100644 index a57b630e1..000000000 --- a/packages/twenty-front/src/modules/object-record/relation-picker/constants/MultiObjectRecordClickOutsideListenerId.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const MULTI_OBJECT_RECORD_CLICK_OUTSIDE_LISTENER_ID = - 'multi-object-record-click-outside-listener'; diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/constants/MultiObjectRecordSelectSelectableListId.ts b/packages/twenty-front/src/modules/object-record/relation-picker/constants/MultiObjectRecordSelectSelectableListId.ts deleted file mode 100644 index e611eeaa8..000000000 --- a/packages/twenty-front/src/modules/object-record/relation-picker/constants/MultiObjectRecordSelectSelectableListId.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const MULTI_OBJECT_RECORD_SELECT_SELECTABLE_LIST_ID = - 'multi-object-record-select-selectable-list'; diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/constants/SingleRecordSelectBaseList.ts b/packages/twenty-front/src/modules/object-record/relation-picker/constants/SingleRecordSelectBaseList.ts deleted file mode 100644 index 7f36c7bd0..000000000 --- a/packages/twenty-front/src/modules/object-record/relation-picker/constants/SingleRecordSelectBaseList.ts +++ /dev/null @@ -1 +0,0 @@ -export const SINGLE_RECORD_SELECT_BASE_LIST = 'single-record-select-base-list'; diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useRecordPicker.ts b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useRecordPicker.ts deleted file mode 100644 index 723f4e2a0..000000000 --- a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useRecordPicker.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { recordPickerPreselectedIdComponentState } from '@/object-record/relation-picker/states/recordPickerPreselectedIdComponentState'; -import { recordPickerSearchFilterComponentState } from '@/object-record/relation-picker/states/recordPickerSearchFilterComponentState'; -import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; - -export const useRecordPicker = ({ - recordPickerInstanceId, -}: { - recordPickerInstanceId?: string; -}) => { - const setRecordPickerSearchFilter = useSetRecoilComponentStateV2( - recordPickerSearchFilterComponentState, - recordPickerInstanceId, - ); - - const setRecordPickerPreselectedId = useSetRecoilComponentStateV2( - recordPickerPreselectedIdComponentState, - recordPickerInstanceId, - ); - - return { - setRecordPickerSearchFilter, - setRecordPickerPreselectedId, - }; -}; diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/states/searchQueryComponentState.ts b/packages/twenty-front/src/modules/object-record/relation-picker/states/searchQueryComponentState.ts deleted file mode 100644 index f03a4cd22..000000000 --- a/packages/twenty-front/src/modules/object-record/relation-picker/states/searchQueryComponentState.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { RecordPickerComponentInstanceContext } from '@/object-record/relation-picker/states/contexts/RecordPickerComponentInstanceContext'; -import { SearchQuery } from '@/object-record/relation-picker/types/SearchQuery'; -import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; - -export const searchQueryComponentState = - createComponentStateV2({ - key: 'searchQueryComponentState', - defaultValue: null, - componentInstanceContext: RecordPickerComponentInstanceContext, - }); diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/types/RecordsForMultipleRecordSelect.ts b/packages/twenty-front/src/modules/object-record/relation-picker/types/RecordsForMultipleRecordSelect.ts deleted file mode 100644 index 63cbc38c1..000000000 --- a/packages/twenty-front/src/modules/object-record/relation-picker/types/RecordsForMultipleRecordSelect.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { RecordForSelect } from '@/object-record/relation-picker/types/RecordForSelect'; - -export type RecordsForMultipleRecordSelect< - CustomRecordForSelect extends RecordForSelect, -> = { - selectedRecords: CustomRecordForSelect[]; - filteredSelectedRecords: CustomRecordForSelect[]; - recordsToSelect: CustomRecordForSelect[]; - loading: boolean; -}; diff --git a/packages/twenty-front/src/modules/object-record/utils/filterAvailableTableColumns.ts b/packages/twenty-front/src/modules/object-record/utils/filterAvailableTableColumns.ts index b33f183d8..215f52624 100644 --- a/packages/twenty-front/src/modules/object-record/utils/filterAvailableTableColumns.ts +++ b/packages/twenty-front/src/modules/object-record/utils/filterAvailableTableColumns.ts @@ -1,7 +1,7 @@ +import { TABLE_COLUMNS_DENY_LIST } from '@/object-record/constants/TableColumnsDenyList'; import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata'; import { isFieldRelation } from '@/object-record/record-field/types/guards/isFieldRelation'; import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition'; -import { TABLE_COLUMNS_DENY_LIST } from '@/object-record/relation-picker/constants/TableColumnsDenyList'; import { RelationDefinitionType } from '~/generated-metadata/graphql'; export const filterAvailableTableColumns = ( diff --git a/packages/twenty-front/src/modules/search/hooks/__tests__/useFilteredSearchRecordQuery.test.tsx b/packages/twenty-front/src/modules/search/hooks/__tests__/useFilteredSearchRecordQuery.test.tsx index 05ede72d5..949becf16 100644 --- a/packages/twenty-front/src/modules/search/hooks/__tests__/useFilteredSearchRecordQuery.test.tsx +++ b/packages/twenty-front/src/modules/search/hooks/__tests__/useFilteredSearchRecordQuery.test.tsx @@ -5,9 +5,9 @@ import { RecoilRoot, useSetRecoilState } from 'recoil'; import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; -import { RecordsForMultipleRecordSelect } from '@/object-record/relation-picker/types/RecordsForMultipleRecordSelect'; import { SnackBarProviderScope } from '@/ui/feedback/snack-bar-manager/scopes/SnackBarProviderScope'; +import { MultipleRecordPickerRecords } from '@/object-record/record-picker/types/MultipleRecordPickerRecords'; import { generatedMockObjectMetadataItems } from '~/testing/mock-data/generatedMockObjectMetadataItems'; import { query, @@ -90,7 +90,7 @@ describe('useFilteredSearchRecordQuery', () => { { wrapper: Wrapper }, ); - const expectedResult: RecordsForMultipleRecordSelect = { + const expectedResult: MultipleRecordPickerRecords = { selectedRecords: [], filteredSelectedRecords: [], recordsToSelect: [], diff --git a/packages/twenty-front/src/modules/search/hooks/useFilteredSearchRecordQuery.ts b/packages/twenty-front/src/modules/search/hooks/useFilteredSearchRecordQuery.ts index 927ed81cb..5cab27401 100644 --- a/packages/twenty-front/src/modules/search/hooks/useFilteredSearchRecordQuery.ts +++ b/packages/twenty-front/src/modules/search/hooks/useFilteredSearchRecordQuery.ts @@ -1,8 +1,8 @@ import { useMapToObjectRecordIdentifier } from '@/object-metadata/hooks/useMapToObjectRecordIdentifier'; import { DEFAULT_SEARCH_REQUEST_LIMIT } from '@/object-record/constants/DefaultSearchRequestLimit'; import { useSearchRecords } from '@/object-record/hooks/useSearchRecords'; -import { RecordForSelect } from '@/object-record/relation-picker/types/RecordForSelect'; -import { RecordsForMultipleRecordSelect } from '@/object-record/relation-picker/types/RecordsForMultipleRecordSelect'; +import { MultipleRecordPickerRecords } from '@/object-record/record-picker/types/MultipleRecordPickerRecords'; +import { SingleRecordPickerRecord } from '@/object-record/record-picker/types/SingleRecordPickerRecord'; import { ObjectRecord } from '@/object-record/types/ObjectRecord'; import { isDefined } from 'twenty-shared'; @@ -21,7 +21,7 @@ export const useFilteredSearchRecordQuery = ({ excludedRecordIds?: string[]; objectNameSingular: string; searchFilter?: string; -}): RecordsForMultipleRecordSelect => { +}): MultipleRecordPickerRecords => { const { mapToObjectRecordIdentifier } = useMapToObjectRecordIdentifier({ objectNameSingular, }); diff --git a/packages/twenty-front/src/modules/ui/field/input/components/MultiSelectInput.tsx b/packages/twenty-front/src/modules/ui/field/input/components/MultiSelectInput.tsx index a8e83b81b..bed8f380c 100644 --- a/packages/twenty-front/src/modules/ui/field/input/components/MultiSelectInput.tsx +++ b/packages/twenty-front/src/modules/ui/field/input/components/MultiSelectInput.tsx @@ -3,7 +3,6 @@ import { useRecoilValue } from 'recoil'; import { Key } from 'ts-key-enum'; import { FieldMultiSelectValue } from '@/object-record/record-field/types/FieldMetadata'; -import { MULTI_OBJECT_RECORD_SELECT_SELECTABLE_LIST_ID } from '@/object-record/relation-picker/constants/MultiObjectRecordSelectSelectableListId'; import { SelectOption } from '@/spreadsheet-import/types'; import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; @@ -19,6 +18,7 @@ import { MenuItemMultiSelectTag } from 'twenty-ui'; import { turnIntoEmptyStringIfWhitespacesOnly } from '~/utils/string/turnIntoEmptyStringIfWhitespacesOnly'; type MultiSelectInputProps = { + selectableListComponentInstanceId: string; values: FieldMultiSelectValue; hotkeyScope: string; onCancel?: () => void; @@ -27,6 +27,7 @@ type MultiSelectInputProps = { }; export const MultiSelectInput = ({ + selectableListComponentInstanceId, values, options, hotkeyScope, @@ -34,10 +35,10 @@ export const MultiSelectInput = ({ onOptionSelected, }: MultiSelectInputProps) => { const { selectedItemIdState } = useSelectableListStates({ - selectableListScopeId: MULTI_OBJECT_RECORD_SELECT_SELECTABLE_LIST_ID, + selectableListScopeId: selectableListComponentInstanceId, }); const { resetSelectedItem } = useSelectableList( - MULTI_OBJECT_RECORD_SELECT_SELECTABLE_LIST_ID, + selectableListComponentInstanceId, ); const selectedItemId = useRecoilValue(selectedItemIdState); @@ -96,7 +97,7 @@ export const MultiSelectInput = ({ return ( { diff --git a/packages/twenty-front/src/modules/ui/field/input/components/SelectInput.tsx b/packages/twenty-front/src/modules/ui/field/input/components/SelectInput.tsx index 73749a608..579f4817a 100644 --- a/packages/twenty-front/src/modules/ui/field/input/components/SelectInput.tsx +++ b/packages/twenty-front/src/modules/ui/field/input/components/SelectInput.tsx @@ -3,7 +3,7 @@ import { SelectInput as SelectBaseInput } from '@/ui/input/components/SelectInpu import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList'; type SelectInputProps = { - selectableListId: string; + selectableListComponentInstanceId: string; selectableItemIdArray: string[]; hotkeyScope: string; onEnter: (itemId: string) => void; @@ -17,7 +17,7 @@ type SelectInputProps = { }; export const SelectInput = ({ - selectableListId, + selectableListComponentInstanceId, selectableItemIdArray, hotkeyScope, onEnter, @@ -31,7 +31,7 @@ export const SelectInput = ({ }: SelectInputProps) => { return ( { setRecordPickerSearchFilter(''); }, [setRecordPickerSearchFilter]); const handleRecordSelected = ( - selectedEntity: RecordForSelect | null | undefined, + selectedEntity: SingleRecordPickerRecord | null | undefined, ) => { onChange?.(selectedEntity?.record?.id ?? ''); closeDropdown(); @@ -153,7 +155,7 @@ export const WorkflowSingleRecordPicker = ({ - closeDropdown()} diff --git a/packages/twenty-front/src/testing/decorators/RecordPickerDecorator.tsx b/packages/twenty-front/src/testing/decorators/RecordPickerDecorator.tsx index 6bb82de28..338891f2c 100644 --- a/packages/twenty-front/src/testing/decorators/RecordPickerDecorator.tsx +++ b/packages/twenty-front/src/testing/decorators/RecordPickerDecorator.tsx @@ -1,11 +1,9 @@ +import { RecordPickerComponentInstanceContext } from '@/object-record/record-picker/states/contexts/RecordPickerComponentInstanceContext'; import { Decorator } from '@storybook/react'; -import { RecordPickerComponentInstanceContext } from '@/object-record/relation-picker/states/contexts/RecordPickerComponentInstanceContext'; -import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope'; - export const RecordPickerDecorator: Decorator = (Story) => (