diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowDropdownStepOutputItems.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowDropdownStepOutputItems.tsx new file mode 100644 index 0000000000..6b6130ff06 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowDropdownStepOutputItems.tsx @@ -0,0 +1,238 @@ +import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader/DropdownMenuHeader'; +import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; +import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput'; +import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator'; +import { type StepOutputSchema } from '@/workflow/workflow-variables/types/StepOutputSchema'; + +import { useGetFieldMetadataItemByIdOrThrow } from '@/object-metadata/hooks/useGetFieldMetadataItemById'; +import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent'; +import { DropdownMenuHeaderLeftComponent } from '@/ui/layout/dropdown/components/DropdownMenuHeader/internal/DropdownMenuHeaderLeftComponent'; +import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth'; +import { useWorkflowVersionIdOrThrow } from '@/workflow/hooks/useWorkflowVersionIdOrThrow'; +import { stepsOutputSchemaFamilySelector } from '@/workflow/states/selectors/stepsOutputSchemaFamilySelector'; +import { useUpsertStepFilterSettings } from '@/workflow/workflow-steps/workflow-actions/filter-action/hooks/useUpsertStepFilterSettings'; +import { getStepFilterOperands } from '@/workflow/workflow-steps/workflow-actions/filter-action/utils/getStepFilterOperands'; +import { useVariableDropdown } from '@/workflow/workflow-variables/hooks/useVariableDropdown'; +import { extractRawVariableNamePart } from '@/workflow/workflow-variables/utils/extractRawVariableNamePart'; +import { getCurrentSubStepFromPath } from '@/workflow/workflow-variables/utils/getCurrentSubStepFromPath'; +import { getStepHeaderLabel } from '@/workflow/workflow-variables/utils/getStepHeaderLabel'; +import { getVariableTemplateFromPath } from '@/workflow/workflow-variables/utils/getVariableTemplateFromPath'; +import { isRecordOutputSchema } from '@/workflow/workflow-variables/utils/isRecordOutputSchema'; +import { searchVariableThroughOutputSchema } from '@/workflow/workflow-variables/utils/searchVariableThroughOutputSchema'; +import { useLingui } from '@lingui/react/macro'; +import { useRecoilCallback } from 'recoil'; +import { type StepFilter } from 'twenty-shared/types'; +import { isDefined } from 'twenty-shared/utils'; +import { + IconChevronLeft, + OverflowingTextWithTooltip, + useIcons, +} from 'twenty-ui/display'; +import { MenuItemSelect } from 'twenty-ui/navigation'; + +type WorkflowDropdownStepOutputItemsProps = { + stepFilter: StepFilter; + step: StepOutputSchema; + onSelect: () => void; + onBack: () => void; +}; + +export const WorkflowDropdownStepOutputItems = ({ + stepFilter, + step, + onSelect, + onBack, +}: WorkflowDropdownStepOutputItemsProps) => { + const { t } = useLingui(); + const { getIcon } = useIcons(); + + const { upsertStepFilterSettings } = useUpsertStepFilterSettings(); + const { getFieldMetadataItemByIdOrThrow } = + useGetFieldMetadataItemByIdOrThrow(); + + const workflowVersionId = useWorkflowVersionIdOrThrow(); + + const updateStepFilter = useRecoilCallback( + ({ snapshot }) => + ({ + rawVariableName, + isFullRecord, + }: { + rawVariableName: string; + isFullRecord: boolean; + }) => { + const stepId = extractRawVariableNamePart({ + rawVariableName, + part: 'stepId', + }); + const [currentStepOutputSchema] = snapshot + .getLoadable( + stepsOutputSchemaFamilySelector({ + workflowVersionId, + stepIds: [stepId], + }), + ) + .getValue(); + + const { variableType, fieldMetadataId, compositeFieldSubFieldName } = + searchVariableThroughOutputSchema({ + stepOutputSchema: currentStepOutputSchema, + rawVariableName, + isFullRecord: false, + }); + + const { fieldMetadataItem: filterFieldMetadataItem } = isDefined( + fieldMetadataId, + ) + ? getFieldMetadataItemByIdOrThrow(fieldMetadataId) + : { fieldMetadataItem: undefined }; + + const filterType = isDefined(fieldMetadataId) + ? (filterFieldMetadataItem?.type ?? 'unknown') + : variableType; + + const availableOperandsForFilter = getStepFilterOperands({ + filterType, + subFieldName: compositeFieldSubFieldName, + }); + const defaultOperand = availableOperandsForFilter[0]; + + upsertStepFilterSettings({ + stepFilterToUpsert: { + ...stepFilter, + stepOutputKey: rawVariableName, + isFullRecord, + type: filterType ?? 'unknown', + value: '', + fieldMetadataId, + compositeFieldSubFieldName, + operand: defaultOperand, + }, + }); + }, + [ + workflowVersionId, + getFieldMetadataItemByIdOrThrow, + upsertStepFilterSettings, + stepFilter, + ], + ); + + const handleStepFilterFieldSelect = (key: string) => { + updateStepFilter({ + rawVariableName: key, + isFullRecord: false, + }); + onSelect(); + }; + + const { + searchInputValue, + setSearchInputValue, + handleSelectField, + goBack, + filteredOptions, + currentPath, + } = useVariableDropdown({ + step, + onSelect: handleStepFilterFieldSelect, + onBack, + }); + + const getDisplayedSubStepObject = () => { + const currentSubStep = getCurrentSubStepFromPath(step, currentPath); + + if (!isRecordOutputSchema(currentSubStep)) { + return; + } + + return currentSubStep.object; + }; + + const handleSelectObject = () => { + const currentSubStep = getCurrentSubStepFromPath(step, currentPath); + + if (!isRecordOutputSchema(currentSubStep)) { + return; + } + + updateStepFilter({ + rawVariableName: getVariableTemplateFromPath({ + stepId: step.id, + path: [...currentPath, currentSubStep.object.fieldIdName], + }), + isFullRecord: true, + }); + onSelect(); + }; + + const displayedSubStepObject = getDisplayedSubStepObject(); + + const shouldDisplaySubStepObject = searchInputValue + ? displayedSubStepObject?.label && + displayedSubStepObject.label + .toLowerCase() + .includes(searchInputValue.toLowerCase()) + : true; + + const shouldDisplayObject = + shouldDisplaySubStepObject && displayedSubStepObject?.label; + const nameSingular = displayedSubStepObject?.nameSingular; + + return ( + + + } + > + + + setSearchInputValue(event.target.value)} + /> + + + {shouldDisplayObject && ( + + )} + {filteredOptions.length > 0 && shouldDisplayObject && ( + + )} + {filteredOptions.map(([key, subStep]) => ( + handleSelectField(key)} + text={subStep.label || key} + hasSubMenu={!subStep.isLeaf} + LeftIcon={subStep.icon ? getIcon(subStep.icon) : undefined} + contextualText={ + subStep.isLeaf ? subStep?.value?.toString() : undefined + } + /> + ))} + + + ); +}; diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterAddFilterRuleSelect.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterAddFilterRuleSelect.tsx index abe0877f9e..cb019d8222 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterAddFilterRuleSelect.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterAddFilterRuleSelect.tsx @@ -137,7 +137,6 @@ export const WorkflowStepFilterAddFilterRuleSelect = ({ } - dropdownOffset={{ y: 8, x: 0 }} dropdownPlacement="bottom-start" /> ); 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 d02ac2544a..251d4e25fc 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,19 +1,18 @@ import { useFieldMetadataItemById } from '@/object-metadata/hooks/useFieldMetadataItemById'; -import { useGetFieldMetadataItemByIdOrThrow } from '@/object-metadata/hooks/useGetFieldMetadataItemById'; import { SelectControl } from '@/ui/input/components/SelectControl'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; -import { useWorkflowVersionIdOrThrow } from '@/workflow/hooks/useWorkflowVersionIdOrThrow'; -import { stepsOutputSchemaFamilySelector } from '@/workflow/states/selectors/stepsOutputSchemaFamilySelector'; -import { useUpsertStepFilterSettings } from '@/workflow/workflow-steps/workflow-actions/filter-action/hooks/useUpsertStepFilterSettings'; +import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown'; +import { WorkflowDropdownStepOutputItems } from '@/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowDropdownStepOutputItems'; 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'; -import { WorkflowVariablesDropdown } from '@/workflow/workflow-variables/components/WorkflowVariablesDropdown'; +import { WorkflowVariablesDropdownWorkflowStepItems } from '@/workflow/workflow-variables/components/WorkflowVariablesDropdownWorkflowStepItems'; import { useAvailableVariablesInWorkflowStep } from '@/workflow/workflow-variables/hooks/useAvailableVariablesInWorkflowStep'; +import { useSearchVariable } from '@/workflow/workflow-variables/hooks/useSearchVariable'; + +import { type StepOutputSchema } from '@/workflow/workflow-variables/types/StepOutputSchema'; import { extractRawVariableNamePart } from '@/workflow/workflow-variables/utils/extractRawVariableNamePart'; -import { searchVariableThroughOutputSchema } from '@/workflow/workflow-variables/utils/searchVariableThroughOutputSchema'; +import { useTheme } from '@emotion/react'; import { useLingui } from '@lingui/react/macro'; -import { useContext } from 'react'; -import { useRecoilCallback, useRecoilValue } from 'recoil'; +import { useContext, useState } from 'react'; import { type StepFilter } from 'twenty-shared/types'; import { isDefined } from 'twenty-shared/utils'; import { useIcons } from 'twenty-ui/display'; @@ -34,139 +33,76 @@ export const WorkflowStepFilterFieldSelect = ({ stepFilter, }: WorkflowStepFilterFieldSelectProps) => { const { readonly } = useContext(WorkflowStepFilterContext); - const shouldDisplayRecordFields = true; - const shouldDisplayRecordObjects = true; - - const { upsertStepFilterSettings } = useUpsertStepFilterSettings(); - const { t } = useLingui(); - const workflowVersionId = useWorkflowVersionIdOrThrow(); + const theme = useTheme(); + const { closeDropdown } = useCloseDropdown(); + const { getIcon } = useIcons(); + + const availableVariablesInWorkflowStep = useAvailableVariablesInWorkflowStep({ + shouldDisplayRecordFields: true, + shouldDisplayRecordObjects: true, + fieldTypesToExclude: NON_SELECTABLE_FIELD_TYPES, + }); + const noAvailableVariables = availableVariablesInWorkflowStep.length === 0; + + const initialStep = + availableVariablesInWorkflowStep.length === 1 + ? availableVariablesInWorkflowStep[0] + : undefined; + + const [selectedStep, setSelectedStep] = useState< + StepOutputSchema | undefined + >(initialStep); const stepId = extractRawVariableNamePart({ rawVariableName: stepFilter.stepOutputKey, part: 'stepId', }); - const stepsOutputSchema = useRecoilValue( - stepsOutputSchemaFamilySelector({ - workflowVersionId, - stepIds: [stepId], - }), - ); - - const { getIcon } = useIcons(); + const { variableLabel } = useSearchVariable({ + stepId, + rawVariableName: stepFilter.stepOutputKey, + isFullRecord: stepFilter.isFullRecord ?? false, + }); const { fieldMetadataItem: filterFieldMetadataItem, objectMetadataItem: filterObjectMetadataItem, } = useFieldMetadataItemById(stepFilter.fieldMetadataId ?? ''); - const { getFieldMetadataItemByIdOrThrow } = - useGetFieldMetadataItemByIdOrThrow(); + const dropdownId = `step-filter-field-${stepFilter.id}`; - const availableVariablesInWorkflowStep = useAvailableVariablesInWorkflowStep({ - shouldDisplayRecordFields, - shouldDisplayRecordObjects, - }); + const handleStepSelect = (stepId: string) => { + setSelectedStep( + availableVariablesInWorkflowStep.find((step) => step.id === stepId), + ); + }; - const noAvailableVariables = availableVariablesInWorkflowStep.length === 0; + const handleSubItemSelect = () => { + setSelectedStep(initialStep); + closeDropdown(dropdownId); + }; - const handleChange = useRecoilCallback( - ({ snapshot }) => - (variableName: string) => { - const stepId = extractRawVariableNamePart({ - rawVariableName: variableName, - part: 'stepId', - }); - const [currentStepOutputSchema] = snapshot - .getLoadable( - stepsOutputSchemaFamilySelector({ - workflowVersionId, - stepIds: [stepId], - }), - ) - .getValue(); - - const { - variableLabel, - variableType, - fieldMetadataId, - compositeFieldSubFieldName, - } = searchVariableThroughOutputSchema({ - stepOutputSchema: currentStepOutputSchema, - rawVariableName: variableName, - isFullRecord: false, - }); - - const { - fieldMetadataItem: filterFieldMetadataItem, - objectMetadataItem: filterObjectMetadataItem, - } = isDefined(fieldMetadataId) - ? getFieldMetadataItemByIdOrThrow(fieldMetadataId) - : { fieldMetadataItem: undefined, objectMetadataItem: undefined }; - - const filterType = isDefined(fieldMetadataId) - ? (filterFieldMetadataItem?.type ?? 'unknown') - : variableType; - - const isFullRecord = - filterFieldMetadataItem?.name === 'id' && - isDefined(filterObjectMetadataItem?.labelSingular); - - upsertStepFilterSettings({ - stepFilterToUpsert: { - ...stepFilter, - stepOutputKey: variableName, - displayValue: isFullRecord - ? filterObjectMetadataItem.labelSingular - : (variableLabel ?? ''), - type: filterType ?? 'unknown', - value: '', - fieldMetadataId, - compositeFieldSubFieldName, - operand: getViewFilterOperands({ - filterType, - subFieldName: compositeFieldSubFieldName, - })?.[0], - }, - }); - }, - [ - workflowVersionId, - getFieldMetadataItemByIdOrThrow, - upsertStepFilterSettings, - stepFilter, - ], - ); - - if (!isDefined(stepId)) { - return null; - } - - const isFullRecord = - filterFieldMetadataItem?.name === 'id' && - isDefined(filterObjectMetadataItem?.labelSingular); - - const { variableLabel } = searchVariableThroughOutputSchema({ - stepOutputSchema: stepsOutputSchema?.[0], - rawVariableName: stepFilter.stepOutputKey, - isFullRecord, - }); + const handleBack = () => { + setSelectedStep(undefined); + }; const isSelectedFieldNotFound = !isDefined(variableLabel); const label = isSelectedFieldNotFound ? t`Select a field from a previous step` : variableLabel; - const icon = isFullRecord + const icon = stepFilter.isFullRecord ? getIcon(filterObjectMetadataItem?.icon) : filterFieldMetadataItem?.icon ? getIcon(filterFieldMetadataItem.icon) : undefined; - const dropdownId = `step-filter-field-${stepFilter.id}`; + if (readonly || noAvailableVariables) { + const disabledLabel = noAvailableVariables + ? t`No available fields to select` + : label; - if (noAvailableVariables) { return ( - } - dropdownComponents={[]} - /> - ); - } - - if (readonly === true) { - return ( - - + } + dropdownComponents={ + !isDefined(selectedStep) ? ( + - } - shouldDisplayRecordFields={shouldDisplayRecordFields} - shouldDisplayRecordObjects={shouldDisplayRecordObjects} - shouldEnableSelectRelationObject={true} - fieldTypesToExclude={NON_SELECTABLE_FIELD_TYPES} - /> - + ) : ( + + ) + } + dropdownPlacement="bottom-end" + dropdownOffset={{ + x: parseInt(theme.spacing(0.5), 10), + y: parseInt(theme.spacing(1), 10), + }} + /> ); }; diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterOperandSelect.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterOperandSelect.tsx index 1a8c02be77..fc0c85c55b 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterOperandSelect.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterOperandSelect.tsx @@ -4,7 +4,7 @@ import { Select } from '@/ui/input/components/Select'; import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth'; 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'; +import { getStepFilterOperands } from '@/workflow/workflow-steps/workflow-actions/filter-action/utils/getStepFilterOperands'; import { useContext } from 'react'; import { type StepFilter, type ViewFilterOperand } from 'twenty-shared/types'; @@ -18,7 +18,7 @@ export const WorkflowStepFilterOperandSelect = ({ const { readonly } = useContext(WorkflowStepFilterContext); const { upsertStepFilterSettings } = useUpsertStepFilterSettings(); - const operands = getViewFilterOperands({ + const operands = getStepFilterOperands({ filterType: stepFilter.type, subFieldName: stepFilter.compositeFieldSubFieldName, }); 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 f28a0bf4c2..14783f24cd 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 @@ -102,7 +102,8 @@ export const WorkflowStepFilterValueInput = ({ variableType === FieldMetadataType.SELECT; const isFullRecord = - selectedFieldMetadataItem?.name === 'id' && + isDefined(stepFilter.isFullRecord) && + stepFilter.isFullRecord && isDefined(objectMetadataItem?.nameSingular); const isDateField = diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/__stories__/WorkflowStepFilterColumn.stories.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/__stories__/WorkflowStepFilterColumn.stories.tsx index 61521351ef..b7f2dd744f 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/__stories__/WorkflowStepFilterColumn.stories.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/__stories__/WorkflowStepFilterColumn.stories.tsx @@ -24,9 +24,7 @@ const TEXT_STEP_FILTER: StepFilter = { id: 'filter-1', stepFilterGroupId: 'filter-group-1', stepOutputKey: 'company.name', - displayValue: 'Company Name', type: 'text', - label: 'Company Name', value: 'Acme', operand: ViewFilterOperand.Contains, }; diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/__stories__/WorkflowStepFilterFieldSelect.stories.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/__stories__/WorkflowStepFilterFieldSelect.stories.tsx index 1514bbe52d..f96aa94121 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/__stories__/WorkflowStepFilterFieldSelect.stories.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/__stories__/WorkflowStepFilterFieldSelect.stories.tsx @@ -13,9 +13,7 @@ const DEFAULT_STEP_FILTER: StepFilter = { id: 'filter-1', stepFilterGroupId: 'filter-group-1', stepOutputKey: '', - displayValue: '', type: 'text', - label: 'New Filter', operand: ViewFilterOperand.Is, value: '', positionInStepFilterGroup: 0, diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/__stories__/WorkflowStepFilterOperandSelect.stories.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/__stories__/WorkflowStepFilterOperandSelect.stories.tsx index 99226499cc..23e02faec1 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/__stories__/WorkflowStepFilterOperandSelect.stories.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/__stories__/WorkflowStepFilterOperandSelect.stories.tsx @@ -14,9 +14,7 @@ const DEFAULT_STEP_FILTER: StepFilter = { id: 'filter-1', stepFilterGroupId: 'filter-group-1', stepOutputKey: 'company.name', - displayValue: 'Company Name', type: 'text', - label: 'Company Name', operand: ViewFilterOperand.Contains, value: '', positionInStepFilterGroup: 0, @@ -26,9 +24,7 @@ const GREATER_THAN_FILTER: StepFilter = { id: 'filter-1', stepFilterGroupId: 'filter-group-1', stepOutputKey: 'company.employees', - displayValue: 'Employee Count', type: 'number', - label: 'Employee Count', operand: ViewFilterOperand.GreaterThanOrEqual, value: '100', positionInStepFilterGroup: 0, diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/__stories__/WorkflowStepFilterValueInput.stories.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/__stories__/WorkflowStepFilterValueInput.stories.tsx index a7a91c42bc..7ef34351ad 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/__stories__/WorkflowStepFilterValueInput.stories.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/__stories__/WorkflowStepFilterValueInput.stories.tsx @@ -14,9 +14,7 @@ const TEXT_FILTER: StepFilter = { id: 'filter-1', stepFilterGroupId: 'filter-group-1', stepOutputKey: 'company.name', - displayValue: 'Company Name', type: 'text', - label: 'Company Name', operand: ViewFilterOperand.Contains, value: 'Acme', positionInStepFilterGroup: 0, @@ -26,9 +24,7 @@ const NUMBER_FILTER: StepFilter = { id: 'filter-2', stepFilterGroupId: 'filter-group-1', stepOutputKey: 'company.employees', - displayValue: 'Employee Count', type: 'number', - label: 'Employee Count', operand: ViewFilterOperand.GreaterThanOrEqual, value: '100', positionInStepFilterGroup: 0, diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/hooks/useAddRootStepFilter.ts b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/hooks/useAddRootStepFilter.ts index 774be2619a..c80e9f41df 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/hooks/useAddRootStepFilter.ts +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/hooks/useAddRootStepFilter.ts @@ -49,10 +49,8 @@ export const useAddRootStepFilter = () => { const newStepFilter: StepFilter = { id: v4(), type: 'unknown', - label: 'New Filter', value: '', operand: ViewFilterOperand.Is, - displayValue: '', stepFilterGroupId: newStepFilterGroup.id, stepOutputKey: '', positionInStepFilterGroup: 0, diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/utils/getStepFilterOperands.ts b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/utils/getStepFilterOperands.ts index f48d7d58f6..4e288605b1 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/utils/getStepFilterOperands.ts +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/utils/getStepFilterOperands.ts @@ -85,7 +85,7 @@ export const COMPOSITE_FIELD_FILTER_OPERANDS_MAP = { }, }; -export const getViewFilterOperands = ({ +export const getStepFilterOperands = ({ filterType, subFieldName, }: { diff --git a/packages/twenty-front/src/modules/workflow/workflow-variables/components/WorkflowVariablesDropdown.tsx b/packages/twenty-front/src/modules/workflow/workflow-variables/components/WorkflowVariablesDropdown.tsx index 340cf9ac66..3f066846b5 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-variables/components/WorkflowVariablesDropdown.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-variables/components/WorkflowVariablesDropdown.tsx @@ -39,7 +39,6 @@ export const WorkflowVariablesDropdown = ({ shouldDisplayRecordFields, shouldDisplayRecordObjects, fieldTypesToExclude, - shouldEnableSelectRelationObject, multiline, clickableComponent, }: { @@ -48,7 +47,6 @@ export const WorkflowVariablesDropdown = ({ shouldDisplayRecordFields: boolean; shouldDisplayRecordObjects: boolean; fieldTypesToExclude?: InputSchemaPropertyType[]; - shouldEnableSelectRelationObject?: boolean; disabled?: boolean; multiline?: boolean; clickableComponent?: React.ReactNode; @@ -134,7 +132,6 @@ export const WorkflowVariablesDropdown = ({ step={selectedStep} onSelect={handleSubItemSelect} onBack={handleBack} - shouldEnableSelectRelationObject={shouldEnableSelectRelationObject} /> ) : ( void; onBack: () => void; - shouldEnableSelectRelationObject?: boolean; }; export const WorkflowVariablesDropdownAllItems = ({ step, onSelect, onBack, - shouldEnableSelectRelationObject, }: WorkflowVariablesDropdownAllItemsProps) => { const { t } = useLingui(); const { getIcon } = useIcons(); @@ -65,25 +63,12 @@ export const WorkflowVariablesDropdownAllItems = ({ return; } - const isRelationField = currentSubStep.object.isRelationField ?? false; - const isRelationObjectSelectable = - shouldEnableSelectRelationObject ?? false; - - if (isRelationField && isRelationObjectSelectable) { - onSelect( - getVariableTemplateFromPath({ - stepId: step.id, - path: currentPath, - }), - ); - } else { - onSelect( - getVariableTemplateFromPath({ - stepId: step.id, - path: [...currentPath, currentSubStep.object.fieldIdName], - }), - ); - } + onSelect( + getVariableTemplateFromPath({ + stepId: step.id, + path: [...currentPath, currentSubStep.object.fieldIdName], + }), + ); }; const displayedSubStepObject = getDisplayedSubStepObject(); diff --git a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/types/output-schema.type.ts b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/types/output-schema.type.ts index e614b4c5a9..1651c8c884 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/types/output-schema.type.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/types/output-schema.type.ts @@ -37,10 +37,8 @@ export type FieldOutputSchema = export type RecordOutputSchema = { object: { - nameSingular: string; fieldIdName: string; objectMetadataId: string; - isRelationField?: boolean; } & Leaf; fields: Record; _outputSchemaType: 'RECORD'; diff --git a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/__tests__/generate-fake-form-response.spec.ts b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/__tests__/generate-fake-form-response.spec.ts index 3785f60fab..80466fd0c8 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/__tests__/generate-fake-form-response.spec.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/__tests__/generate-fake-form-response.spec.ts @@ -116,7 +116,6 @@ describe('generateFakeFormResponse', () => { icon: 'test-company-icon', isLeaf: true, label: 'Company', - nameSingular: 'company', objectMetadataId: '20202020-c03c-45d6-a4b0-04afe1357c5c', value: 'A company', }, diff --git a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/__tests__/generate-fake-object-record-event.spec.ts b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/__tests__/generate-fake-object-record-event.spec.ts index 5fad881942..38beaf878d 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/__tests__/generate-fake-object-record-event.spec.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/__tests__/generate-fake-object-record-event.spec.ts @@ -61,7 +61,6 @@ describe('generateFakeObjectRecordEvent', () => { icon: 'test-company-icon', label: 'Company', value: 'A company', - nameSingular: 'company', fieldIdName: 'properties.after.id', objectMetadataId: '20202020-c03c-45d6-a4b0-04afe1357c5c', }, @@ -93,7 +92,6 @@ describe('generateFakeObjectRecordEvent', () => { icon: 'test-company-icon', label: 'Company', value: 'A company', - nameSingular: 'company', fieldIdName: 'properties.after.id', objectMetadataId: '20202020-c03c-45d6-a4b0-04afe1357c5c', }, @@ -125,7 +123,6 @@ describe('generateFakeObjectRecordEvent', () => { icon: 'test-company-icon', label: 'Company', value: 'A company', - nameSingular: 'company', fieldIdName: 'properties.before.id', objectMetadataId: '20202020-c03c-45d6-a4b0-04afe1357c5c', }, @@ -157,7 +154,6 @@ describe('generateFakeObjectRecordEvent', () => { icon: 'test-company-icon', label: 'Company', value: 'A company', - nameSingular: 'company', fieldIdName: 'properties.before.id', objectMetadataId: '20202020-c03c-45d6-a4b0-04afe1357c5c', }, diff --git a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/__tests__/generate-fake-object-record.spec.ts b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/__tests__/generate-fake-object-record.spec.ts index 4eb175dc41..d0b8eaa4a3 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/__tests__/generate-fake-object-record.spec.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/__tests__/generate-fake-object-record.spec.ts @@ -41,7 +41,6 @@ describe('generateFakeObjectRecord', () => { icon: 'test-company-icon', label: 'Company', value: 'A company', - nameSingular: 'company', fieldIdName: 'id', objectMetadataId: '20202020-c03c-45d6-a4b0-04afe1357c5c', }, diff --git a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/generate-fake-object-record-event.ts b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/generate-fake-object-record-event.ts index 4496013bf9..8a243c3905 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/generate-fake-object-record-event.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/generate-fake-object-record-event.ts @@ -30,8 +30,6 @@ const generateFakeObjectRecordEventWithPrefix = ({ objectMetadataInfo.objectMetadataItemWithFieldsMaps.icon ?? undefined, label: objectMetadataInfo.objectMetadataItemWithFieldsMaps.labelSingular, value: objectMetadataInfo.objectMetadataItemWithFieldsMaps.description, - nameSingular: - objectMetadataInfo.objectMetadataItemWithFieldsMaps.nameSingular, fieldIdName: `${prefix}.id`, objectMetadataId: objectMetadataInfo.objectMetadataItemWithFieldsMaps.id, }, diff --git a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/generate-fake-object-record.ts b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/generate-fake-object-record.ts index 8b0a5353a9..1dcc8118fb 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/generate-fake-object-record.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/generate-fake-object-record.ts @@ -5,11 +5,9 @@ import { generateObjectRecordFields } from 'src/modules/workflow/workflow-builde export const generateFakeObjectRecord = ({ objectMetadataInfo, depth = 0, - isRelationField, }: { objectMetadataInfo: ObjectMetadataInfo; depth?: number; - isRelationField?: boolean; }): RecordOutputSchema => { return { object: { @@ -18,11 +16,8 @@ export const generateFakeObjectRecord = ({ objectMetadataInfo.objectMetadataItemWithFieldsMaps.icon ?? undefined, label: objectMetadataInfo.objectMetadataItemWithFieldsMaps.labelSingular, value: objectMetadataInfo.objectMetadataItemWithFieldsMaps.description, - nameSingular: - objectMetadataInfo.objectMetadataItemWithFieldsMaps.nameSingular, fieldIdName: 'id', objectMetadataId: objectMetadataInfo.objectMetadataItemWithFieldsMaps.id, - isRelationField, }, fields: generateObjectRecordFields({ objectMetadataInfo, diff --git a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/generate-object-record-fields.ts b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/generate-object-record-fields.ts index 69c9959d43..59bf3fa9d6 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/generate-object-record-fields.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/generate-object-record-fields.ts @@ -60,7 +60,6 @@ export const generateObjectRecordFields = ({ objectMetadataMaps: objectMetadataInfo.objectMetadataMaps, }, depth: depth + 1, - isRelationField: true, }), }; } diff --git a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/filter/utils/__tests__/evaluate-filter-conditions.util.spec.ts b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/filter/utils/__tests__/evaluate-filter-conditions.util.spec.ts index 779b9fc9b0..7a5b518b7a 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/filter/utils/__tests__/evaluate-filter-conditions.util.spec.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/filter/utils/__tests__/evaluate-filter-conditions.util.spec.ts @@ -21,10 +21,8 @@ describe('evaluateFilterConditions', () => { ): ResolvedFilter => ({ id: 'filter1', type: type, - label: 'Test Filter', rightOperand, operand, - displayValue: String(rightOperand), stepFilterGroupId: 'group1', leftOperand, }); @@ -784,10 +782,8 @@ describe('evaluateFilterConditions', () => { const filter: ResolvedFilter = { id: 'filter1', type: 'CURRENCY', - label: 'Currency Filter', rightOperand: 'USD', operand: ViewFilterOperand.Is, - displayValue: 'USD', stepFilterGroupId: 'group1', leftOperand: 'USD', compositeFieldSubFieldName: 'currencyCode', @@ -800,10 +796,8 @@ describe('evaluateFilterConditions', () => { const filter: ResolvedFilter = { id: 'filter1', type: 'CURRENCY', - label: 'Currency Filter', rightOperand: 100, operand: ViewFilterOperand.GreaterThanOrEqual, - displayValue: '100', stepFilterGroupId: 'group1', leftOperand: 150, compositeFieldSubFieldName: 'amountMicros', @@ -1215,20 +1209,16 @@ describe('evaluateFilterConditions', () => { { id: 'filter1', type: 'RELATION', - label: 'Name Filter', rightOperand: 'John', operand: ViewFilterOperand.Is, - displayValue: 'John', stepFilterGroupId: 'group1', leftOperand: 'John', }, { id: 'filter2', type: 'NUMBER', - label: 'Age Filter', rightOperand: 25, operand: ViewFilterOperand.GreaterThanOrEqual, - displayValue: '25', stepFilterGroupId: 'group1', leftOperand: 30, }, @@ -1244,20 +1234,16 @@ describe('evaluateFilterConditions', () => { { id: 'filter1', type: 'RELATION', - label: 'Name Filter', rightOperand: 'John', operand: ViewFilterOperand.Is, - displayValue: 'John', stepFilterGroupId: 'group1', leftOperand: 'John', }, { id: 'filter2', type: 'NUMBER', - label: 'Age Filter', rightOperand: 25, operand: ViewFilterOperand.GreaterThanOrEqual, - displayValue: '25', stepFilterGroupId: 'group1', leftOperand: 20, // This will fail }, @@ -1283,20 +1269,16 @@ describe('evaluateFilterConditions', () => { { id: 'filter1', type: 'RELATION', - label: 'Name Filter', rightOperand: 'John', operand: ViewFilterOperand.Is, - displayValue: 'John', stepFilterGroupId: 'group1', leftOperand: 'John', }, { id: 'filter2', type: 'NUMBER', - label: 'Age Filter', rightOperand: 25, operand: ViewFilterOperand.GreaterThanOrEqual, - displayValue: '25', stepFilterGroupId: 'group1', leftOperand: 30, }, @@ -1319,20 +1301,16 @@ describe('evaluateFilterConditions', () => { { id: 'filter1', type: 'RELATION', - label: 'Name Filter', rightOperand: 'John', operand: ViewFilterOperand.Is, - displayValue: 'John', stepFilterGroupId: 'group1', leftOperand: 'Jane', // This will fail }, { id: 'filter2', type: 'NUMBER', - label: 'Age Filter', rightOperand: 25, operand: ViewFilterOperand.GreaterThanOrEqual, - displayValue: '25', stepFilterGroupId: 'group1', leftOperand: 30, }, @@ -1357,20 +1335,16 @@ describe('evaluateFilterConditions', () => { { id: 'filter1', type: 'RELATION', - label: 'Name Filter', rightOperand: 'John', operand: ViewFilterOperand.Is, - displayValue: 'John', stepFilterGroupId: 'group1', leftOperand: 'Jane', // This will fail }, { id: 'filter2', type: 'NUMBER', - label: 'Age Filter', rightOperand: 25, operand: ViewFilterOperand.GreaterThanOrEqual, - displayValue: '25', stepFilterGroupId: 'group1', leftOperand: 30, // This will pass }, @@ -1393,20 +1367,16 @@ describe('evaluateFilterConditions', () => { { id: 'filter1', type: 'RELATION', - label: 'Name Filter', rightOperand: 'John', operand: ViewFilterOperand.Is, - displayValue: 'John', stepFilterGroupId: 'group1', leftOperand: 'Jane', // This will fail }, { id: 'filter2', type: 'NUMBER', - label: 'Age Filter', rightOperand: 25, operand: ViewFilterOperand.GreaterThanOrEqual, - displayValue: '25', stepFilterGroupId: 'group1', leftOperand: 20, // This will fail }, @@ -1435,20 +1405,16 @@ describe('evaluateFilterConditions', () => { { id: 'filter1', type: 'RELATION', - label: 'Name Filter', rightOperand: 'John', operand: ViewFilterOperand.Is, - displayValue: 'John', stepFilterGroupId: 'group1', leftOperand: 'John', }, { id: 'filter2', type: 'NUMBER', - label: 'Age Filter', rightOperand: 25, operand: ViewFilterOperand.GreaterThanOrEqual, - displayValue: '25', stepFilterGroupId: 'group2', leftOperand: 30, }, @@ -1485,30 +1451,24 @@ describe('evaluateFilterConditions', () => { { id: 'filter1', type: 'RELATION', - label: 'Filter 1', rightOperand: 'John', operand: ViewFilterOperand.Is, - displayValue: 'John', stepFilterGroupId: 'child1', leftOperand: 'Jane', // This will fail }, { id: 'filter2', type: 'RELATION', - label: 'Filter 2', rightOperand: 'Smith', operand: ViewFilterOperand.Is, - displayValue: 'Smith', stepFilterGroupId: 'child1', leftOperand: 'Smith', // This will pass (OR group passes) }, { id: 'filter3', type: 'NUMBER', - label: 'Filter 3', rightOperand: 25, operand: ViewFilterOperand.GreaterThanOrEqual, - displayValue: '25', stepFilterGroupId: 'child2', leftOperand: 30, // This will pass (AND group passes) }, @@ -1548,10 +1508,8 @@ describe('evaluateFilterConditions', () => { { id: 'filter1', type: 'RELATION', - label: 'Name Filter', rightOperand: 'John', operand: ViewFilterOperand.Is, - displayValue: 'John', stepFilterGroupId: 'nonexistent', leftOperand: 'John', }, diff --git a/packages/twenty-server/src/modules/workflow/workflow-trigger/utils/__tests__/assert-form-step-is-valid.util.spec.ts b/packages/twenty-server/src/modules/workflow/workflow-trigger/utils/__tests__/assert-form-step-is-valid.util.spec.ts index 2e0567da36..372beafe74 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-trigger/utils/__tests__/assert-form-step-is-valid.util.spec.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-trigger/utils/__tests__/assert-form-step-is-valid.util.spec.ts @@ -49,7 +49,6 @@ const settings: WorkflowFormActionSettings = { value: 'A company', isLeaf: true, fieldIdName: 'id', - nameSingular: 'company', objectMetadataId: '123e4567-e89b-12d3-a456-426614174000', }, _outputSchemaType: 'RECORD', diff --git a/packages/twenty-shared/src/types/StepFilters.ts b/packages/twenty-shared/src/types/StepFilters.ts index bc8549f64d..145a276bc0 100644 --- a/packages/twenty-shared/src/types/StepFilters.ts +++ b/packages/twenty-shared/src/types/StepFilters.ts @@ -15,13 +15,12 @@ export type StepFilterGroup = { export type StepFilter = { id: string; type: string; - label: string; stepOutputKey: string; operand: ViewFilterOperand; value: string; - displayValue: string; stepFilterGroupId: string; positionInStepFilterGroup?: number; fieldMetadataId?: string; compositeFieldSubFieldName?: string; + isFullRecord?: boolean; };