From f9fa2db7f03e5ad7fe4af9aa2b11af45efb7adab Mon Sep 17 00:00:00 2001 From: Thomas Trompette Date: Fri, 8 Aug 2025 12:01:17 +0200 Subject: [PATCH] Display id field input as record picker (#13759) When selecting a record or an id, a text input was appearing. Replacing by a record picker. Before https://github.com/user-attachments/assets/61e7c1fe-4f74-459e-8b50-5ebe2fc7462f After https://github.com/user-attachments/assets/ad7fcf05-b86c-4e10-a8cb-bd3e4a694812 --- .../WorkflowStepFilterFieldSelect.tsx | 36 ++++++++++++++----- .../WorkflowStepFilterValueInput.tsx | 30 +++++++++++++--- .../hooks/useGetFilterFieldMetadataItem.ts | 35 ++++++++++++++++++ 3 files changed, 87 insertions(+), 14 deletions(-) create mode 100644 packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/hooks/useGetFilterFieldMetadataItem.ts diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterFieldSelect.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterFieldSelect.tsx index 862a8dfad0..8823a32a01 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterFieldSelect.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterFieldSelect.tsx @@ -1,8 +1,8 @@ -import { useGetFieldMetadataItemById } from '@/object-metadata/hooks/useGetFieldMetadataItemById'; import { SelectControl } from '@/ui/input/components/SelectControl'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { useWorkflowStepContextOrThrow } from '@/workflow/states/context/WorkflowStepContext'; import { stepsOutputSchemaFamilySelector } from '@/workflow/states/selectors/stepsOutputSchemaFamilySelector'; +import { useGetFilterFieldMetadataItem } from '@/workflow/workflow-steps/workflow-actions/filter-action/hooks/useGetFilterFieldMetadataItem'; import { useUpsertStepFilterSettings } from '@/workflow/workflow-steps/workflow-actions/filter-action/hooks/useUpsertStepFilterSettings'; import { WorkflowStepFilterContext } from '@/workflow/workflow-steps/workflow-actions/filter-action/states/context/WorkflowStepFilterContext'; import { getViewFilterOperands } from '@/workflow/workflow-steps/workflow-actions/filter-action/utils/getStepFilterOperands'; @@ -50,7 +50,7 @@ export const WorkflowStepFilterFieldSelect = ({ }), ); - const { getFieldMetadataItemById } = useGetFieldMetadataItemById(); + const { getFilterFieldMetadataItem } = useGetFilterFieldMetadataItem(); const availableVariablesInWorkflowStep = useAvailableVariablesInWorkflowStep({ shouldDisplayRecordFields, @@ -86,15 +86,31 @@ export const WorkflowStepFilterFieldSelect = ({ isFullRecord: false, }); + const { + fieldMetadataItem: selectedFieldMetadataItem, + objectMetadataItem, + } = isDefined(fieldMetadataId) + ? getFilterFieldMetadataItem(fieldMetadataId) + : { + fieldMetadataItem: undefined, + objectMetadataItem: undefined, + }; + const filterType = isDefined(fieldMetadataId) - ? getFieldMetadataItemById(fieldMetadataId).type + ? (selectedFieldMetadataItem?.type ?? 'unknown') : variableType; + const isFullRecord = + selectedFieldMetadataItem?.name === 'id' && + isDefined(objectMetadataItem?.labelSingular); + upsertStepFilterSettings({ stepFilterToUpsert: { ...stepFilter, stepOutputKey: variableName, - displayValue: variableLabel ?? '', + displayValue: isFullRecord + ? objectMetadataItem.labelSingular + : (variableLabel ?? ''), type: filterType ?? 'unknown', value: '', fieldMetadataId, @@ -110,7 +126,7 @@ export const WorkflowStepFilterFieldSelect = ({ upsertStepFilterSettings, stepFilter, workflowVersionId, - getFieldMetadataItemById, + getFilterFieldMetadataItem, ], ); @@ -125,9 +141,11 @@ export const WorkflowStepFilterFieldSelect = ({ }); const isSelectedFieldNotFound = !isDefined(variableLabel); - const label = isSelectedFieldNotFound - ? t`Select a field from a previous step` - : variableLabel; + const label = + isSelectedFieldNotFound || !isDefined(stepFilter.displayValue) + ? t`Select a field from a previous step` + : stepFilter.displayValue; + const dropdownId = `step-filter-field-${stepFilter.id}`; const isReadonly = readonly ?? false; @@ -141,7 +159,7 @@ export const WorkflowStepFilterFieldSelect = ({ selectedOption={{ value: stepFilter.stepOutputKey, label: isReadonly - ? (variableLabel ?? '') + ? (label ?? '') : t`No available fields to select`, }} isDisabled={true} diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterValueInput.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterValueInput.tsx index 0a59904d38..bb16feb620 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterValueInput.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterValueInput.tsx @@ -1,10 +1,11 @@ -import { useGetFieldMetadataItemById } from '@/object-metadata/hooks/useGetFieldMetadataItemById'; import { configurableViewFilterOperands } from '@/object-record/object-filter-dropdown/utils/configurableViewFilterOperands'; import { FormFieldInput } from '@/object-record/record-field/components/FormFieldInput'; import { FormMultiSelectFieldInput } from '@/object-record/record-field/form-types/components/FormMultiSelectFieldInput'; +import { FormSingleRecordPicker } from '@/object-record/record-field/form-types/components/FormSingleRecordPicker'; import { FormTextFieldInput } from '@/object-record/record-field/form-types/components/FormTextFieldInput'; import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata'; import { WorkflowStepFilterValueCompositeInput } from '@/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterValueCompositeInput'; +import { useGetFilterFieldMetadataItem } from '@/workflow/workflow-steps/workflow-actions/filter-action/hooks/useGetFilterFieldMetadataItem'; import { useUpsertStepFilterSettings } from '@/workflow/workflow-steps/workflow-actions/filter-action/hooks/useUpsertStepFilterSettings'; import { WorkflowStepFilterContext } from '@/workflow/workflow-steps/workflow-actions/filter-action/states/context/WorkflowStepFilterContext'; import { WorkflowVariablePicker } from '@/workflow/workflow-variables/components/WorkflowVariablePicker'; @@ -55,6 +56,7 @@ export const WorkflowStepFilterValueInput = ({ const { readonly } = useContext(WorkflowStepFilterContext); const { upsertStepFilterSettings } = useUpsertStepFilterSettings(); + const { getFilterFieldMetadataItem } = useGetFilterFieldMetadataItem(); const handleValueChange = (value: JsonValue) => { const valueToUpsert = isString(value) @@ -70,7 +72,6 @@ export const WorkflowStepFilterValueInput = ({ }, }); }; - const { getFieldMetadataItemById } = useGetFieldMetadataItemById(); const isDisabled = !stepFilter.operand; @@ -88,14 +89,33 @@ export const WorkflowStepFilterValueInput = ({ compositeFieldSubFieldName, } = stepFilter; - const selectedFieldMetadataItem = isDefined(fieldMetadataId) - ? getFieldMetadataItemById(fieldMetadataId) - : undefined; + const { fieldMetadataItem: selectedFieldMetadataItem, objectMetadataItem } = + isDefined(fieldMetadataId) + ? getFilterFieldMetadataItem(fieldMetadataId) + : { + fieldMetadataItem: undefined, + objectMetadataItem: undefined, + }; const isFilterableByMultiSelectValue = variableType === FieldMetadataType.MULTI_SELECT || variableType === FieldMetadataType.SELECT; + const isFullRecord = + selectedFieldMetadataItem?.name === 'id' && + isDefined(objectMetadataItem?.nameSingular); + + if (isFullRecord) { + return ( + + ); + } + if ( !isDefined(variableType) || !isFilterableFieldMetadataType(variableType) || diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/hooks/useGetFilterFieldMetadataItem.ts b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/hooks/useGetFilterFieldMetadataItem.ts new file mode 100644 index 0000000000..c3ffa5f393 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/hooks/useGetFilterFieldMetadataItem.ts @@ -0,0 +1,35 @@ +import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems'; +import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; +import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; +import { isDefined } from 'twenty-shared/utils'; + +export const useGetFilterFieldMetadataItem = () => { + const { objectMetadataItems } = useObjectMetadataItems(); + + const getFilterFieldMetadataItem = ( + fieldMetadataId: string, + ): { + fieldMetadataItem: FieldMetadataItem | undefined; + objectMetadataItem: ObjectMetadataItem | undefined; + } => { + for (const objectMetadataItem of objectMetadataItems) { + const field = objectMetadataItem.fields.find( + (field) => field.id === fieldMetadataId, + ); + if (isDefined(field)) { + return { + fieldMetadataItem: field, + objectMetadataItem: objectMetadataItem, + }; + } + } + return { + fieldMetadataItem: undefined, + objectMetadataItem: undefined, + }; + }; + + return { + getFilterFieldMetadataItem, + }; +};