Refactor RecordPicker part 2 (#10502)

Keep clarifying folders:
- record-picker is now clean
- record-picker-morph-legacy contains activityTarget logic that will be
abstracted later
This commit is contained in:
Charles Bochet
2025-02-26 13:54:16 +01:00
committed by GitHub
parent ec87218b9c
commit 64938d5a05
44 changed files with 126 additions and 99 deletions

View File

@ -1,5 +1,5 @@
<!doctype html>
<html lang="en">
<html lang="en" translate="no">
<head>
<meta charset="UTF-8" />

View File

@ -24,9 +24,9 @@ import {
objectRecordMultiSelectComponentFamilyState,
} from '@/object-record/record-field/states/objectRecordMultiSelectComponentFamilyState';
import { useInlineCell } from '@/object-record/record-inline-cell/hooks/useInlineCell';
import { ActivityTargetInlineCellEditModeMultiRecordsEffect } from '@/object-record/record-picker-morph-legacy/components/ActivityTargetInlineCellEditModeMultiRecordsEffect';
import { ActivityTargetInlineCellEditModeMultiRecordsSearchFilterEffect } from '@/object-record/record-picker-morph-legacy/components/ActivityTargetInlineCellEditModeMultiRecordsSearchFilterEffect';
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 { prefillRecord } from '@/object-record/utils/prefillRecord';

View File

@ -4,8 +4,6 @@ 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 { 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 = ({
@ -20,11 +18,7 @@ export const ObjectMetadataItemsProvider = ({
<ObjectMetadataItemsLoadEffect />
{shouldDisplayChildren ? (
<PreComputedChipGeneratorsProvider>
<RecordPickerComponentInstanceContext.Provider
value={{ instanceId: RelationPickerHotkeyScope.RelationPicker }}
>
{children}
</RecordPickerComponentInstanceContext.Provider>
{children}
</PreComputedChipGeneratorsProvider>
) : (
<UserOrMetadataLoader />

View File

@ -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/record-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray';
import { MultiObjectRecordQueryResult } from '@/object-record/record-picker-morph-legacy/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray';
export const useCombinedFindManyRecords = ({
operationSignatures,

View File

@ -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/record-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray';
import { MultiObjectRecordQueryResult } from '@/object-record/record-picker-morph-legacy/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray';
export const useCombinedGetTotalCount = ({
objectMetadataItems,

View File

@ -7,8 +7,8 @@ import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldM
import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector';
import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState';
import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState';
import { RelationPickerHotkeyScope } from '@/object-record/record-field/meta-types/input/types/RelationPickerHotkeyScope';
import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter';
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';

View File

@ -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/record-picker/legacy/types/RelationPickerHotkeyScope';
import { RecordPickerHotkeyScope } from '@/object-record/record-picker/types/RecordPickerHotkeyScope';
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';
@ -75,7 +75,7 @@ export const ObjectFilterDropdownFilterSelectMenuItem = ({
const filterType = getFilterTypeFromFieldType(fieldMetadataItem.type);
if (filterType === 'RELATION' || filterType === 'SELECT') {
setHotkeyScope(RelationPickerHotkeyScope.RelationPicker);
setHotkeyScope(RecordPickerHotkeyScope.RecordPicker);
}
setSelectedOperandInDropdown(

View File

@ -18,8 +18,9 @@ import { objectFilterDropdownSearchInputComponentState } from '@/object-record/o
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 { RelationPickerHotkeyScope } from '@/object-record/record-field/meta-types/input/types/RelationPickerHotkeyScope';
import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter';
import { RelationPickerHotkeyScope } from '@/object-record/record-picker/legacy/types/RelationPickerHotkeyScope';
import { RecordPickerHotkeyScope } from '@/object-record/record-picker/types/RecordPickerHotkeyScope';
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';
@ -164,7 +165,7 @@ export const ObjectFilterDropdownOptionSelect = () => {
<SelectableList
selectableListId={componentInstanceId}
selectableItemIdArray={objectRecordsIds}
hotkeyScope={RelationPickerHotkeyScope.RelationPicker}
hotkeyScope={RecordPickerHotkeyScope.RecordPicker}
onEnter={(itemId) => {
const option = optionsInDropdown.find((option) => option.id === itemId);
if (isDefined(option)) {

View File

@ -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/record-picker/legacy/types/RelationPickerHotkeyScope';
import { RecordPickerHotkeyScope } from '@/object-record/record-picker/types/RecordPickerHotkeyScope';
import { MultipleSelectDropdown } from '@/object-record/select/components/MultipleSelectDropdown';
import { useRecordsForSelect } from '@/object-record/select/hooks/useRecordsForSelect';
import { SelectableItem } from '@/object-record/select/types/SelectableItem';
@ -232,7 +232,7 @@ export const ObjectFilterDropdownRecordSelect = ({
)}
<MultipleSelectDropdown
selectableListId="object-filter-record-select-id"
hotkeyScope={RelationPickerHotkeyScope.RelationPicker}
hotkeyScope={RecordPickerHotkeyScope.RecordPicker}
itemsToSelect={recordsToSelect}
filteredSelectedItems={filteredSelectedRecords}
selectedItems={selectedRecords}

View File

@ -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/record-picker/legacy/types/RelationPickerHotkeyScope';
import { RecordPickerHotkeyScope } from '@/object-record/record-picker/types/RecordPickerHotkeyScope';
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';
@ -144,7 +144,7 @@ export const ObjectFilterDropdownSourceSelect = ({
return (
<MultipleSelectDropdown
selectableListId="object-filter-source-select-id"
hotkeyScope={RelationPickerHotkeyScope.RelationPicker}
hotkeyScope={RecordPickerHotkeyScope.RecordPicker}
itemsToSelect={sourceTypes.filter(
(item) =>
!filteredSelectedItems.some((selected) => selected.id === item.id),

View File

@ -8,7 +8,7 @@ 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 { RecordPickerHotkeyScope } from '@/object-record/record-picker/types/RecordPickerHotkeyScope';
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
@ -67,7 +67,7 @@ export const useSelectFilterUsedInDropdown = (componentInstanceId?: string) => {
fieldMetadataItem.type === 'RELATION' ||
fieldMetadataItem.type === 'SELECT'
) {
setHotkeyScope(RelationPickerHotkeyScope.RelationPicker);
setHotkeyScope(RecordPickerHotkeyScope.RecordPicker);
}
const filterType = getFilterTypeFromFieldType(fieldMetadataItem.type);

View File

@ -4,6 +4,7 @@ import { useRecordBoardSelection } from '@/object-record/record-board/hooks/useR
import { RecordBoardCardHeaderContainer } from '@/object-record/record-board/record-board-card/components/RecordBoardCardHeaderContainer';
import { StopPropagationContainer } from '@/object-record/record-board/record-board-card/components/StopPropagationContainer';
import { RecordBoardCardContext } from '@/object-record/record-board/record-board-card/contexts/RecordBoardCardContext';
import { RecordBoardColumnContext } from '@/object-record/record-board/record-board-column/contexts/RecordBoardColumnContext';
import { useAddNewCard } from '@/object-record/record-board/record-board-column/hooks/useAddNewCard';
import { RecordBoardScopeInternalContext } from '@/object-record/record-board/scopes/scope-internal-context/RecordBoardScopeInternalContext';
import { isRecordBoardCardSelectedComponentFamilyState } from '@/object-record/record-board/states/isRecordBoardCardSelectedComponentFamilyState';
@ -75,7 +76,11 @@ export const RecordBoardCardHeader = ({
}: RecordBoardCardHeaderProps) => {
const [newLabelValue, setNewLabelValue] = useState('');
const { handleBlur, handleInputEnter } = useAddNewCard();
const columnId = useContext(RecordBoardColumnContext)?.columnId;
const { handleBlur, handleInputEnter } = useAddNewCard({
recordPickerComponentInstanceId: `add-new-card-record-picker-column-${columnId}`,
});
const { recordId } = useContext(RecordBoardCardContext);

View File

@ -3,7 +3,6 @@ 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';
@ -29,7 +28,9 @@ export const RecordBoardColumnNewOpportunity = ({
}),
);
const { handleCreateSuccess, handleEntitySelect } = useAddNewCard();
const { handleCreateSuccess, handleEntitySelect } = useAddNewCard({
recordPickerComponentInstanceId: `add-new-card-record-picker-column-${columnId}`,
});
const { createOneRecord: createCompany } = useCreateOneRecord({
objectNameSingular: CoreObjectNameSingular.Company,
@ -68,9 +69,12 @@ export const RecordBoardColumnNewOpportunity = ({
{newRecord.isCreating && newRecord.position === position && (
<OverlayContainer>
<RecordPickerComponentInstanceContext.Provider
value={{ instanceId: RelationPickerHotkeyScope.RelationPicker }}
value={{
instanceId: `add-new-card-record-picker-column-${columnId}`,
}}
>
<SingleRecordPicker
componentInstanceId={`add-new-card-record-picker-column-${columnId}`}
onCancel={() => handleCreateSuccess(position, columnId, false)}
onRecordSelected={(company) =>
company ? handleEntitySelect(position, company) : null

View File

@ -18,7 +18,9 @@ export const RecordBoardColumnNewRecord = ({
}),
);
const { handleCreateSuccess } = useAddNewCard();
const { handleCreateSuccess } = useAddNewCard({
recordPickerComponentInstanceId: `add-new-card-record-picker-column-${columnId}`,
});
const hasObjectReadOnlyPermission = useHasObjectReadOnlyPermission();

View File

@ -1,8 +1,8 @@
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 { RelationPickerHotkeyScope } from '@/object-record/record-field/meta-types/input/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';
@ -16,13 +16,19 @@ type SetFunction = <T>(
valOrUpdater: T | ((currVal: T) => T),
) => void;
export const useAddNewCard = () => {
type UseAddNewCardProps = {
recordPickerComponentInstanceId: string;
};
export const useAddNewCard = ({
recordPickerComponentInstanceId,
}: UseAddNewCardProps) => {
const columnContext = useContext(RecordBoardColumnContext);
const { createOneRecord, selectFieldMetadataItem, objectMetadataItem } =
useContext(RecordBoardContext);
const { resetSearchFilter } = useRecordSelectSearch({
recordPickerInstanceId: RelationPickerHotkeyScope.RelationPicker,
});
const { resetSearchFilter } = useRecordSelectSearch(
recordPickerComponentInstanceId,
);
const {
goBackToPreviousHotkeyScope,
@ -233,7 +239,6 @@ export const useAddNewCard = () => {
return {
handleAddNewCardClick,
handleCreateSuccess,
handleCreate,
handleBlur,
handleInputEnter,
handleEntitySelect,

View File

@ -11,7 +11,9 @@ export const useColumnNewCardActions = (columnId: string) => {
(field) => field.isLabelIdentifier,
);
const { handleAddNewCardClick } = useAddNewCard();
const { handleAddNewCardClick } = useAddNewCard({
recordPickerComponentInstanceId: `add-new-card-record-picker-column-${columnId}`,
});
const handleNewButtonClick = (
position: 'first' | 'last',

View File

@ -3,12 +3,12 @@ import { useContext } from 'react';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { FieldContext } from '@/object-record/record-field/contexts/FieldContext';
import { RelationFromManyFieldInputMultiRecordsEffect } from '@/object-record/record-field/meta-types/input/components/RelationFromManyFieldInputMultiRecordsEffect';
import { useAddNewRecordAndOpenRightDrawer } from '@/object-record/record-field/meta-types/input/hooks/useAddNewRecordAndOpenRightDrawer';
import { useUpdateRelationFromManyFieldInput } from '@/object-record/record-field/meta-types/input/hooks/useUpdateRelationFromManyFieldInput';
import { FieldDefinition } from '@/object-record/record-field/types/FieldDefinition';
import { FieldInputEvent } from '@/object-record/record-field/types/FieldInputEvent';
import { FieldRelationMetadata } from '@/object-record/record-field/types/FieldMetadata';
import { MultipleRecordPicker } from '@/object-record/record-picker/components/MultipleRecordPicker';
import { useAddNewRecordAndOpenRightDrawer } from '@/object-record/record-picker/hooks/useAddNewRecordAndOpenRightDrawer';
import { RecordPickerComponentInstanceContext } from '@/object-record/record-picker/states/contexts/RecordPickerComponentInstanceContext';
type RelationFromManyFieldInputProps = {

View File

@ -3,12 +3,12 @@ import { IconForbid } from 'twenty-ui';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { FieldContext } from '@/object-record/record-field/contexts/FieldContext';
import { useAddNewRecordAndOpenRightDrawer } from '@/object-record/record-field/meta-types/input/hooks/useAddNewRecordAndOpenRightDrawer';
import { RelationPickerHotkeyScope } from '@/object-record/record-field/meta-types/input/types/RelationPickerHotkeyScope';
import { FieldDefinition } from '@/object-record/record-field/types/FieldDefinition';
import { FieldRelationMetadata } from '@/object-record/record-field/types/FieldMetadata';
import { SearchPickerInitialValueEffect } from '@/object-record/record-picker-morph-legacy/components/SearchPickerInitialValueEffect';
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 = {
@ -64,6 +64,7 @@ export const RelationPicker = ({
recordPickerInstanceId={recordPickerInstanceId}
/>
<SingleRecordPicker
componentInstanceId={recordPickerInstanceId}
EmptyIcon={IconForbid}
emptyLabel={'No ' + fieldDefinition.label}
onCancel={onCancel}

View File

@ -49,7 +49,9 @@ export const RecordIndexPageKanbanAddButton = () => {
const { closeDropdown } = useDropdown(dropdownId);
const { isOpportunitiesCompanyFieldDisabled } =
useIsOpportunitiesCompanyFieldDisabled();
const { handleAddNewCardClick } = useAddNewCard();
const { handleAddNewCardClick } = useAddNewCard({
recordPickerComponentInstanceId: `add-new-card-record-picker`,
});
const handleItemClick = useCallback(
(columnDefinition: RecordGroupDefinition) => {

View File

@ -14,7 +14,7 @@ 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 { RelationPickerHotkeyScope } from '@/object-record/record-field/meta-types/input/types/RelationPickerHotkeyScope';
import { getDropdownFocusIdForRecordField } from '@/object-record/utils/getDropdownFocusIdForRecordField';
import { getRecordFieldInputId } from '@/object-record/utils/getRecordFieldInputId';
import { activeDropdownFocusIdState } from '@/ui/layout/dropdown/states/activeDropdownFocusIdState';

View File

@ -3,8 +3,8 @@ 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/record-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray';
import { useMultiObjectSearch } from '@/object-record/record-picker/hooks/useMultiObjectSearch';
import { useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray } from '@/object-record/record-picker-morph-legacy/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray';
import { useMultiObjectSearch } from '@/object-record/record-picker-morph-legacy/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';

View File

@ -2,7 +2,7 @@ import { act, renderHook } from '@testing-library/react';
import { RecoilRoot, useSetRecoilState } from 'recoil';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray } from '@/object-record/record-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray';
import { useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray } from '@/object-record/record-picker-morph-legacy/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray';
import { RecordPickerComponentInstanceContext } from '@/object-record/record-picker/states/contexts/RecordPickerComponentInstanceContext';
import { generatedMockObjectMetadataItems } from '~/testing/mock-data/generatedMockObjectMetadataItems';

View File

@ -2,7 +2,7 @@ import { act, renderHook } from '@testing-library/react';
import { RecoilRoot, useSetRecoilState } from 'recoil';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { useMultiObjectSearchQueryResultFormattedAsObjectRecordsMap } from '@/object-record/record-picker/hooks/useMultiObjectSearchQueryResultFormattedAsObjectRecordsMap';
import { useMultiObjectSearchQueryResultFormattedAsObjectRecordsMap } from '@/object-record/record-picker-morph-legacy/hooks/useMultiObjectSearchQueryResultFormattedAsObjectRecordsMap';
import { RecordPickerComponentInstanceContext } from '@/object-record/record-picker/states/contexts/RecordPickerComponentInstanceContext';
import { generatedMockObjectMetadataItems } from '~/testing/mock-data/generatedMockObjectMetadataItems';

View File

@ -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/record-picker/utils/formatMultiObjectRecordSearchResults';
import { formatMultiObjectRecordSearchResults } from '@/object-record/record-picker-morph-legacy/utils/formatMultiObjectRecordSearchResults';
import { ObjectRecordForSelect } from '@/object-record/types/ObjectRecordForSelect';
import { isDefined } from 'twenty-shared';

View File

@ -6,7 +6,7 @@ import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadat
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 { MultiObjectRecordQueryResult } from '@/object-record/record-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray';
import { MultiObjectRecordQueryResult } from '@/object-record/record-picker-morph-legacy/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray';
import { isObjectMetadataItemSearchableInCombinedRequest } from '@/object-record/utils/isObjectMetadataItemSearchableInCombinedRequest';
import { isDefined } from 'twenty-shared';

View File

@ -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/record-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray';
import { formatMultiObjectRecordSearchResults } from '@/object-record/record-picker/utils/formatMultiObjectRecordSearchResults';
import { MultiObjectRecordQueryResult } from '@/object-record/record-picker-morph-legacy/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray';
import { formatMultiObjectRecordSearchResults } from '@/object-record/record-picker-morph-legacy/utils/formatMultiObjectRecordSearchResults';
import { ObjectRecordForSelect } from '@/object-record/types/ObjectRecordForSelect';
import { isDefined } from 'twenty-shared';

View File

@ -3,13 +3,13 @@ import { isNonEmptyArray } from '@sniptt/guards';
import { useRecoilValue } from 'recoil';
import { useLimitPerMetadataItem } from '@/object-metadata/hooks/useLimitPerMetadataItem';
import { useOrderByFieldPerMetadataItem } from '@/object-metadata/hooks/useOrderByFieldPerMetadataItem';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { useGenerateCombinedFindManyRecordsQuery } from '@/object-record/multiple-objects/hooks/useGenerateCombinedFindManyRecordsQuery';
import {
MultiObjectRecordQueryResult,
useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray,
} from '@/object-record/record-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray';
import { useOrderByFieldPerMetadataItem } from '@/object-record/record-picker/hooks/useOrderByFieldPerMetadataItem';
} from '@/object-record/record-picker-morph-legacy/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray';
import { SelectedObjectRecordId } from '@/object-record/types/SelectedObjectRecordId';
import { capitalize, isDefined } from 'twenty-shared';

View File

@ -1,4 +1,4 @@
import { MultiObjectRecordQueryResult } from '@/object-record/record-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray';
import { MultiObjectRecordQueryResult } from '@/object-record/record-picker-morph-legacy/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray';
export const formatMultiObjectRecordSearchResults = (
searchResults: MultiObjectRecordQueryResult | undefined | null,

View File

@ -4,12 +4,14 @@ import {
SingleRecordPickerMenuItemsWithSearch,
SingleRecordPickerMenuItemsWithSearchProps,
} from '@/object-record/record-picker/components/SingleRecordPickerMenuItemsWithSearch';
import { RecordPickerComponentInstanceContext } from '@/object-record/record-picker/states/contexts/RecordPickerComponentInstanceContext';
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
import { isDefined } from 'twenty-shared';
export type SingleRecordPickerProps = {
width?: number;
componentInstanceId: string;
} & SingleRecordPickerMenuItemsWithSearchProps;
export const SingleRecordPicker = ({
@ -22,6 +24,7 @@ export const SingleRecordPicker = ({
objectNameSingular,
selectedRecordIds,
width = 200,
componentInstanceId,
}: SingleRecordPickerProps) => {
const containerRef = useRef<HTMLDivElement>(null);
@ -42,19 +45,23 @@ export const SingleRecordPicker = ({
});
return (
<DropdownMenu ref={containerRef} width={width} data-select-disable>
<SingleRecordPickerMenuItemsWithSearch
{...{
EmptyIcon,
emptyLabel,
excludedRecordIds,
onCancel,
onCreate,
onRecordSelected,
objectNameSingular,
selectedRecordIds,
}}
/>
</DropdownMenu>
<RecordPickerComponentInstanceContext.Provider
value={{ instanceId: componentInstanceId }}
>
<DropdownMenu ref={containerRef} width={width} data-select-disable>
<SingleRecordPickerMenuItemsWithSearch
{...{
EmptyIcon,
emptyLabel,
excludedRecordIds,
onCancel,
onCreate,
onRecordSelected,
objectNameSingular,
selectedRecordIds,
}}
/>
</DropdownMenu>
</RecordPickerComponentInstanceContext.Provider>
);
};

View File

@ -13,8 +13,8 @@ import { isDefined } from 'twenty-shared';
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 { RecordPickerHotkeyScope } from '@/object-record/record-picker/types/RecordPickerHotkeyScope';
import { SingleRecordPickerRecord } from '@/object-record/record-picker/types/SingleRecordPickerRecord';
import { RelationPickerHotkeyScope } from '../legacy/types/RelationPickerHotkeyScope';
export type SingleRecordPickerMenuItemsProps = {
EmptyIcon?: IconComponent;
@ -37,7 +37,7 @@ export const SingleRecordPickerMenuItems = ({
onCancel,
onRecordSelected,
selectedRecord,
hotkeyScope = RelationPickerHotkeyScope.RelationPicker,
hotkeyScope = RecordPickerHotkeyScope.RecordPicker,
isFiltered,
shouldSelectEmptyOption,
}: SingleRecordPickerMenuItemsProps) => {

View File

@ -37,6 +37,7 @@ const meta: Meta<typeof SingleRecordPicker> = {
args: {
objectNameSingular: CoreObjectNameSingular.WorkspaceMember,
selectedRecordIds: [],
componentInstanceId: 'single-record-picker',
},
argTypes: {
selectedRecord: {

View File

@ -18,9 +18,7 @@ describe('useRecordSelectSearch', () => {
it('should update searchFilter after change event', async () => {
const { result } = renderHook(
() => {
const recordSelectSearchHook = useRecordSelectSearch({
recordPickerInstanceId: instanceId,
});
const recordSelectSearchHook = useRecordSelectSearch(instanceId);
const internallyStoredFilter = useRecoilComponentValueV2(
recordPickerSearchFilterComponentState,
instanceId,

View File

@ -1,21 +1,27 @@
import { RecordPickerComponentInstanceContext } from '@/object-record/record-picker/states/contexts/RecordPickerComponentInstanceContext';
import { recordPickerPreselectedIdComponentState } from '@/object-record/record-picker/states/recordPickerPreselectedIdComponentState';
import { recordPickerSearchFilterComponentState } from '@/object-record/record-picker/states/recordPickerSearchFilterComponentState';
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { useDebouncedCallback } from 'use-debounce';
export const useRecordSelectSearch = ({
recordPickerInstanceId,
}: {
recordPickerInstanceId?: string;
} = {}) => {
export const useRecordSelectSearch = (
recordPickerComponentInstanceIdFromProps?: string,
) => {
const recordPickerComponentInstanceId =
useAvailableComponentInstanceIdOrThrow(
RecordPickerComponentInstanceContext,
recordPickerComponentInstanceIdFromProps,
);
const setRecordPickerSearchFilter = useSetRecoilComponentStateV2(
recordPickerSearchFilterComponentState,
recordPickerInstanceId,
recordPickerComponentInstanceId,
);
const setRecordPickerPreselectedId = useSetRecoilComponentStateV2(
recordPickerPreselectedIdComponentState,
recordPickerInstanceId,
recordPickerComponentInstanceId,
);
const debouncedSetSearchFilter = useDebouncedCallback(
setRecordPickerSearchFilter,

View File

@ -0,0 +1,3 @@
export enum RecordPickerHotkeyScope {
RecordPicker = 'record-picker',
}

View File

@ -9,11 +9,11 @@ import { FieldContext } from '@/object-record/record-field/contexts/FieldContext
import { useIsFieldValueReadOnly } from '@/object-record/record-field/hooks/useIsFieldValueReadOnly';
import { usePersistField } from '@/object-record/record-field/hooks/usePersistField';
import { RelationFromManyFieldInputMultiRecordsEffect } from '@/object-record/record-field/meta-types/input/components/RelationFromManyFieldInputMultiRecordsEffect';
import { useAddNewRecordAndOpenRightDrawer } from '@/object-record/record-field/meta-types/input/hooks/useAddNewRecordAndOpenRightDrawer';
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';

View File

@ -2,10 +2,10 @@ import { ReactNode, useContext } from 'react';
import { isLabelIdentifierField } from '@/object-metadata/utils/isLabelIdentifierField';
import { FieldContext } from '@/object-record/record-field/contexts/FieldContext';
import { RelationPickerHotkeyScope } from '@/object-record/record-field/meta-types/input/types/RelationPickerHotkeyScope';
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';

View File

@ -3,7 +3,6 @@ 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 { SingleRecordPicker } from '@/object-record/record-picker/components/SingleRecordPicker';
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 { InputLabel } from '@/ui/input/components/InputLabel';
@ -152,24 +151,21 @@ export const WorkflowSingleRecordPicker = ({
/>
}
dropdownComponents={
<RecordPickerComponentInstanceContext.Provider
value={{ instanceId: dropdownId }}
>
<SingleRecordPicker
EmptyIcon={IconForbid}
emptyLabel={'No ' + objectNameSingular}
onCancel={() => closeDropdown()}
onRecordSelected={handleRecordSelected}
objectNameSingular={objectNameSingular}
recordPickerInstanceId={dropdownId}
selectedRecordIds={
draftValue?.value &&
!isStandaloneVariableString(draftValue.value)
? [draftValue.value]
: []
}
/>
</RecordPickerComponentInstanceContext.Provider>
<SingleRecordPicker
componentInstanceId={dropdownId}
EmptyIcon={IconForbid}
emptyLabel={'No ' + objectNameSingular}
onCancel={() => closeDropdown()}
onRecordSelected={handleRecordSelected}
objectNameSingular={objectNameSingular}
recordPickerInstanceId={dropdownId}
selectedRecordIds={
draftValue?.value &&
!isStandaloneVariableString(draftValue.value)
? [draftValue.value]
: []
}
/>
}
dropdownHotkeyScope={{ scope: dropdownId }}
/>