diff --git a/packages/twenty-front/src/generated-metadata/graphql.ts b/packages/twenty-front/src/generated-metadata/graphql.ts index ff77e5c050..0f081a0a51 100644 --- a/packages/twenty-front/src/generated-metadata/graphql.ts +++ b/packages/twenty-front/src/generated-metadata/graphql.ts @@ -1343,6 +1343,7 @@ export enum FeatureFlagKey { IS_APPLICATION_ENABLED = 'IS_APPLICATION_ENABLED', IS_DASHBOARD_V2_ENABLED = 'IS_DASHBOARD_V2_ENABLED', IS_EMAILING_DOMAIN_ENABLED = 'IS_EMAILING_DOMAIN_ENABLED', + IS_IF_ELSE_ENABLED = 'IS_IF_ELSE_ENABLED', IS_JSON_FILTER_ENABLED = 'IS_JSON_FILTER_ENABLED', IS_PAGE_LAYOUT_ENABLED = 'IS_PAGE_LAYOUT_ENABLED', IS_POSTGRESQL_INTEGRATION_ENABLED = 'IS_POSTGRESQL_INTEGRATION_ENABLED', @@ -5010,6 +5011,7 @@ export enum WorkflowActionType { FIND_RECORDS = 'FIND_RECORDS', FORM = 'FORM', HTTP_REQUEST = 'HTTP_REQUEST', + IF_ELSE = 'IF_ELSE', ITERATOR = 'ITERATOR', SEND_EMAIL = 'SEND_EMAIL', UPDATE_RECORD = 'UPDATE_RECORD', diff --git a/packages/twenty-front/src/generated/graphql.ts b/packages/twenty-front/src/generated/graphql.ts index adbefbfbfd..2529543053 100644 --- a/packages/twenty-front/src/generated/graphql.ts +++ b/packages/twenty-front/src/generated/graphql.ts @@ -1326,6 +1326,7 @@ export enum FeatureFlagKey { IS_APPLICATION_ENABLED = 'IS_APPLICATION_ENABLED', IS_DASHBOARD_V2_ENABLED = 'IS_DASHBOARD_V2_ENABLED', IS_EMAILING_DOMAIN_ENABLED = 'IS_EMAILING_DOMAIN_ENABLED', + IS_IF_ELSE_ENABLED = 'IS_IF_ELSE_ENABLED', IS_JSON_FILTER_ENABLED = 'IS_JSON_FILTER_ENABLED', IS_PAGE_LAYOUT_ENABLED = 'IS_PAGE_LAYOUT_ENABLED', IS_POSTGRESQL_INTEGRATION_ENABLED = 'IS_POSTGRESQL_INTEGRATION_ENABLED', @@ -4829,6 +4830,7 @@ export enum WorkflowActionType { FIND_RECORDS = 'FIND_RECORDS', FORM = 'FORM', HTTP_REQUEST = 'HTTP_REQUEST', + IF_ELSE = 'IF_ELSE', ITERATOR = 'ITERATOR', SEND_EMAIL = 'SEND_EMAIL', UPDATE_RECORD = 'UPDATE_RECORD', diff --git a/packages/twenty-front/src/modules/command-menu/pages/workflow/action/components/CommandMenuWorkflowSelectAction.tsx b/packages/twenty-front/src/modules/command-menu/pages/workflow/action/components/CommandMenuWorkflowSelectAction.tsx index b2c9a87640..0aff503a28 100644 --- a/packages/twenty-front/src/modules/command-menu/pages/workflow/action/components/CommandMenuWorkflowSelectAction.tsx +++ b/packages/twenty-front/src/modules/command-menu/pages/workflow/action/components/CommandMenuWorkflowSelectAction.tsx @@ -17,6 +17,9 @@ export const CommandMenuWorkflowSelectAction = ({ onActionSelected: (actionType: WorkflowActionType) => void; }) => { const isAiEnabled = useIsFeatureEnabled(FeatureFlagKey.IS_AI_ENABLED); + const isIfElseEnabled = useIsFeatureEnabled( + FeatureFlagKey.IS_IF_ELSE_ENABLED, + ); const { t } = useLingui(); @@ -46,7 +49,9 @@ export const CommandMenuWorkflowSelectAction = ({ {t`Flow`} action.type !== 'IF_ELSE' || isIfElseEnabled, + )} onClick={onActionSelected} /> diff --git a/packages/twenty-front/src/modules/workflow/types/Workflow.ts b/packages/twenty-front/src/modules/workflow/types/Workflow.ts index a0fabeb719..6885c89c8d 100644 --- a/packages/twenty-front/src/modules/workflow/types/Workflow.ts +++ b/packages/twenty-front/src/modules/workflow/types/Workflow.ts @@ -13,6 +13,7 @@ import { type workflowFindRecordsActionSchema, type workflowFormActionSchema, type workflowHttpRequestActionSchema, + type workflowIfElseActionSchema, type workflowIteratorActionSchema, type workflowManualTriggerSchema, type workflowRunSchema, @@ -50,6 +51,7 @@ export type WorkflowFindRecordsAction = z.infer< export type WorkflowDelayAction = z.infer; export type WorkflowFilterAction = z.infer; export type WorkflowFormAction = z.infer; +export type WorkflowIfElseAction = z.infer; export type WorkflowHttpRequestAction = z.infer< typeof workflowHttpRequestActionSchema >; @@ -68,6 +70,7 @@ export type WorkflowAction = | WorkflowUpsertRecordAction | WorkflowFindRecordsAction | WorkflowFilterAction + | WorkflowIfElseAction | WorkflowFormAction | WorkflowHttpRequestAction | WorkflowAiAgentAction diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/utils/generateNodesAndEdgesForIfElseNode.ts b/packages/twenty-front/src/modules/workflow/workflow-diagram/utils/generateNodesAndEdgesForIfElseNode.ts new file mode 100644 index 0000000000..153d4c9f0f --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/utils/generateNodesAndEdgesForIfElseNode.ts @@ -0,0 +1,117 @@ +import { + type WorkflowIfElseAction, + type WorkflowStep, +} from '@/workflow/types/Workflow'; +import { type WorkflowContext } from '@/workflow/workflow-diagram/types/WorkflowContext'; +import { + type WorkflowDiagramEdge, + type WorkflowDiagramNode, + type WorkflowDiagramStepNodeData, +} from '@/workflow/workflow-diagram/types/WorkflowDiagram'; +import { getEdgePathStrategy } from '@/workflow/workflow-diagram/utils/getEdgePathStrategy'; +import { getEdgeTypeBetweenTwoNodes } from '@/workflow/workflow-diagram/utils/getEdgeTypeBetweenTwoNodes'; +import { WORKFLOW_VISUALIZER_EDGE_DEFAULT_CONFIGURATION } from '@/workflow/workflow-diagram/workflow-edges/constants/WorkflowVisualizerEdgeDefaultConfiguration'; +import { WORKFLOW_DIAGRAM_NODE_DEFAULT_SOURCE_HANDLE_ID } from '@/workflow/workflow-diagram/workflow-nodes/constants/WorkflowDiagramNodeDefaultSourceHandleId'; +import { WORKFLOW_DIAGRAM_NODE_DEFAULT_TARGET_HANDLE_ID } from '@/workflow/workflow-diagram/workflow-nodes/constants/WorkflowDiagramNodeDefaultTargetHandleId'; +import { getBranchLabel } from '@/workflow/workflow-steps/workflow-actions/if-else-action/utils/getBranchLabel'; +import { Position } from '@xyflow/react'; +import { isDefined } from 'twenty-shared/utils'; +import { v4 } from 'uuid'; + +export const generateNodesAndEdgesForIfElseNode = ({ + step, + steps, + xPos, + yPos, + nodes, + edges, + workflowContext, +}: { + step: WorkflowIfElseAction; + steps: WorkflowStep[]; + yPos: number; + xPos: number; + nodes: readonly WorkflowDiagramNode[]; + edges: readonly WorkflowDiagramEdge[]; + workflowContext: WorkflowContext; +}): { + nodes: Array; + edges: Array; +} => { + const edgeTypeBetweenTwoNodes = getEdgeTypeBetweenTwoNodes({ + workflowContext, + }); + + const updatedNodes = [...nodes]; + const updatedEdges = [...edges]; + + const ifElseNode: WorkflowDiagramNode = { + id: step.id, + data: { + nodeType: 'action', + actionType: step.type, + name: step.name, + hasNextStepIds: true, + stepId: step.id, + position: step.position ?? { + x: xPos, + y: yPos, + }, + } satisfies WorkflowDiagramStepNodeData, + position: step.position ?? { + x: xPos, + y: yPos, + }, + }; + + updatedNodes.push(ifElseNode); + + const branches = step.settings.input.branches; + const totalBranches = branches.length; + + branches.forEach((branch, branchIndex) => { + const label = getBranchLabel({ + branchIndex, + totalBranches, + branch, + }); + + const nextStepIds = branch.nextStepIds; + for (const nextStepId of nextStepIds) { + const nextStep = steps.find((s) => s.id === nextStepId); + if (!isDefined(nextStep)) { + continue; + } + + updatedEdges.push({ + ...WORKFLOW_VISUALIZER_EDGE_DEFAULT_CONFIGURATION, + type: edgeTypeBetweenTwoNodes, + id: v4(), + source: step.id, + sourceHandle: WORKFLOW_DIAGRAM_NODE_DEFAULT_SOURCE_HANDLE_ID, + target: nextStepId, + deletable: false, + selectable: false, + reconnectable: false, + targetHandle: WORKFLOW_DIAGRAM_NODE_DEFAULT_TARGET_HANDLE_ID, + data: { + ...WORKFLOW_VISUALIZER_EDGE_DEFAULT_CONFIGURATION.data, + labelOptions: { + position: Position.Bottom, + label, + }, + edgePathStrategy: getEdgePathStrategy({ + step, + steps, + nextStepId, + }), + }, + }); + } + }); + + return { + nodes: updatedNodes, + edges: updatedEdges, + }; +}; diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/utils/generateWorkflowDiagram.ts b/packages/twenty-front/src/modules/workflow/workflow-diagram/utils/generateWorkflowDiagram.ts index 09519fe302..78b7ca10eb 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/utils/generateWorkflowDiagram.ts +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/utils/generateWorkflowDiagram.ts @@ -12,6 +12,7 @@ import { type WorkflowDiagramNode, } from '@/workflow/workflow-diagram/types/WorkflowDiagram'; import { generateNodesAndEdgesForDefaultNode } from '@/workflow/workflow-diagram/utils/generateNodesAndEdgesForDefaultNode'; +import { generateNodesAndEdgesForIfElseNode } from '@/workflow/workflow-diagram/utils/generateNodesAndEdgesForIfElseNode'; import { generateNodesAndEdgesForIteratorNode } from '@/workflow/workflow-diagram/utils/generateNodesAndEdgesForIteratorNode'; import { getEdgeTypeBetweenTwoNodes } from '@/workflow/workflow-diagram/utils/getEdgeTypeBetweenTwoNodes'; import { getWorkflowDiagramTriggerNode } from '@/workflow/workflow-diagram/utils/getWorkflowDiagramTriggerNode'; @@ -87,6 +88,23 @@ export const generateWorkflowDiagram = ({ break; } + case 'IF_ELSE': { + const { nodes: ifElseNodes, edges: ifElseEdges } = + generateNodesAndEdgesForIfElseNode({ + step, + steps, + xPos, + yPos: levelYPos, + nodes, + edges, + workflowContext, + }); + + nodes = ifElseNodes; + edges = ifElseEdges; + + break; + } default: { const { nodes: defaultNodes, edges: defaultEdges } = generateNodesAndEdgesForDefaultNode({ diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-edges/components/WorkflowDiagramDefaultEdgeEditable.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-edges/components/WorkflowDiagramDefaultEdgeEditable.tsx index 7facd18aae..18ce5172d2 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-edges/components/WorkflowDiagramDefaultEdgeEditable.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-edges/components/WorkflowDiagramDefaultEdgeEditable.tsx @@ -34,11 +34,14 @@ export const WorkflowDiagramDefaultEdgeEditable = ({ markerStart, markerEnd, data, + deletable, }: WorkflowDiagramDefaultEdgeEditableProps) => { const { i18n } = useLingui(); const { isEdgeHovered } = useEdgeState(); + const isEditable = deletable !== false; + const { segments, overlayPosition: [labelX, labelY], @@ -107,42 +110,48 @@ export const WorkflowDiagramDefaultEdgeEditable = ({ sourceX={sourceX} sourceY={sourceY} position={data.labelOptions.position} + centerX={labelX} + centerY={labelY} > )} - - - - - + + + + + )} ); diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-edges/components/WorkflowDiagramDefaultEdgeReadonly.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-edges/components/WorkflowDiagramDefaultEdgeReadonly.tsx index 21fe59ee68..5388e9848b 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-edges/components/WorkflowDiagramDefaultEdgeReadonly.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-edges/components/WorkflowDiagramDefaultEdgeReadonly.tsx @@ -23,7 +23,10 @@ export const WorkflowDiagramDefaultEdgeReadonly = ({ }: WorkflowDiagramDefaultEdgeReadonlyProps) => { const theme = useTheme(); - const { segments } = getEdgePath({ + const { + segments, + overlayPosition: [labelX, labelY], + } = getEdgePath({ sourceX, sourceY, sourcePosition, @@ -53,6 +56,8 @@ export const WorkflowDiagramDefaultEdgeReadonly = ({ sourceX={sourceX} sourceY={sourceY} position={data.labelOptions.position} + centerX={labelX} + centerY={labelY} > diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-edges/components/WorkflowDiagramEdgeLabelContainer.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-edges/components/WorkflowDiagramEdgeLabelContainer.tsx index 80129c99ed..efb9590a18 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-edges/components/WorkflowDiagramEdgeLabelContainer.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-edges/components/WorkflowDiagramEdgeLabelContainer.tsx @@ -1,16 +1,25 @@ import { css } from '@emotion/react'; import styled from '@emotion/styled'; import { Position } from '@xyflow/react'; +import { isDefined } from 'twenty-shared/utils'; const StyledWorkflowDiagramEdgeLabelContainer = styled.div<{ sourceX: number; sourceY: number; position: Position; + centerX?: number; + centerY?: number; }>` position: absolute; width: fit-content; - ${({ position, sourceX, sourceY }) => { + ${({ position, sourceX, sourceY, centerX, centerY }) => { + if (isDefined(centerX) && isDefined(centerY)) { + return css` + transform: translate(-50%, -50%) translate(${centerX}px, ${centerY}px); + `; + } + switch (position) { case Position.Right: { return css` 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/components/WorkflowDropdownStepOutputItems.tsx similarity index 98% rename from packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowDropdownStepOutputItems.tsx rename to packages/twenty-front/src/modules/workflow/workflow-steps/components/WorkflowDropdownStepOutputItems.tsx index 974282c402..df56fab5ca 100644 --- 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/components/WorkflowDropdownStepOutputItems.tsx @@ -10,8 +10,8 @@ import { DropdownMenuHeaderLeftComponent } from '@/ui/layout/dropdown/components 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 { useUpsertStepFilterSettings } from '@/workflow/workflow-steps/filters/hooks/useUpsertStepFilterSettings'; +import { getStepFilterOperands } from '@/workflow/workflow-steps/filters/utils/getStepFilterOperands'; import { useVariableDropdown } from '@/workflow/workflow-variables/hooks/useVariableDropdown'; import { isRecordOutputSchemaV2 } from '@/workflow/workflow-variables/types/guards/isRecordOutputSchemaV2'; import { type StepOutputSchemaV2 } from '@/workflow/workflow-variables/types/StepOutputSchemaV2'; diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/components/WorkflowRunStepNodeDetail.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/components/WorkflowRunStepNodeDetail.tsx index 964fa0e3da..f820ff250a 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-steps/components/WorkflowRunStepNodeDetail.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/components/WorkflowRunStepNodeDetail.tsx @@ -15,6 +15,7 @@ import { WorkflowEditActionUpsertRecord } from '@/workflow/workflow-steps/workfl import { WorkflowEditActionDelay } from '@/workflow/workflow-steps/workflow-actions/delay-actions/components/WorkflowEditActionDelay'; import { WorkflowEditActionFilter } from '@/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowEditActionFilter'; import { WorkflowEditActionFindRecords } from '@/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowEditActionFindRecords'; +import { WorkflowEditActionIfElse } from '@/workflow/workflow-steps/workflow-actions/if-else-action/components/WorkflowEditActionIfElse'; import { WorkflowEditActionFormFiller } from '@/workflow/workflow-steps/workflow-actions/form-action/components/WorkflowEditActionFormFiller'; import { WorkflowEditActionHttpRequest } from '@/workflow/workflow-steps/workflow-actions/http-request-action/components/WorkflowEditActionHttpRequest'; import { WorkflowEditActionIterator } from '@/workflow/workflow-steps/workflow-actions/iterator-action/components/WorkflowEditActionIterator'; @@ -230,6 +231,17 @@ export const WorkflowRunStepNodeDetail = ({ /> ); } + case 'IF_ELSE': { + return ( + + ); + } case 'ITERATOR': { return ( ); } + case 'IF_ELSE': { + return ( + + ); + } case 'ITERATOR': { return ( { const { readonly } = useContext(WorkflowStepFilterContext); + const stepFilterGroups = useRecoilComponentValue( + currentStepFilterGroupsComponentState, + ); + + const rootStepFilterGroup = stepFilterGroups?.find( + (filterGroup) => !isDefined(filterGroup.parentStepFilterGroupId), + ); + + const { childStepFilters, childStepFilterGroups } = + useChildStepFiltersAndChildStepFilterGroups({ + stepFilterGroupId: rootStepFilterGroup?.id ?? '', + }); + + const isLastFilterInIfBranch = + isIfBranch && + isDefined(rootStepFilterGroup) && + stepFilter.stepFilterGroupId === rootStepFilterGroup.id && + childStepFilters.length === 1 && + childStepFilterGroups.length === 0; + + const shouldShowDropdown = !readonly && !isLastFilterInIfBranch; + return ( - {!readonly && ( + {shouldShowDropdown && ( )} 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/filters/components/WorkflowStepFilterFieldSelect.tsx similarity index 96% rename from packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterFieldSelect.tsx rename to packages/twenty-front/src/modules/workflow/workflow-steps/filters/components/WorkflowStepFilterFieldSelect.tsx index 7ef4aa4fbe..4a83956f1f 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/filters/components/WorkflowStepFilterFieldSelect.tsx @@ -2,8 +2,8 @@ import { useFieldMetadataItemById } from '@/object-metadata/hooks/useFieldMetada import { SelectControl } from '@/ui/input/components/SelectControl'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; 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 { WorkflowDropdownStepOutputItems } from '@/workflow/workflow-steps/components/WorkflowDropdownStepOutputItems'; +import { WorkflowStepFilterContext } from '@/workflow/workflow-steps/filters/states/context/WorkflowStepFilterContext'; import { WorkflowVariablesDropdownSteps } from '@/workflow/workflow-variables/components/WorkflowVariablesDropdownSteps'; import { useAvailableVariablesInWorkflowStep } from '@/workflow/workflow-variables/hooks/useAvailableVariablesInWorkflowStep'; import { useSearchVariable } from '@/workflow/workflow-variables/hooks/useSearchVariable'; diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterGroupChildren.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/filters/components/WorkflowStepFilterGroupChildren.tsx similarity index 84% rename from packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterGroupChildren.tsx rename to packages/twenty-front/src/modules/workflow/workflow-steps/filters/components/WorkflowStepFilterGroupChildren.tsx index d504c9276e..3ed2dbd832 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterGroupChildren.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/filters/components/WorkflowStepFilterGroupChildren.tsx @@ -1,7 +1,7 @@ -import { WorkflowStepFilterAddFilterRuleSelect } from '@/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterAddFilterRuleSelect'; -import { WorkflowStepFilterColumn } from '@/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterColumn'; -import { useChildStepFiltersAndChildStepFilterGroups } from '@/workflow/workflow-steps/workflow-actions/filter-action/hooks/useChildStepFiltersAndChildStepFilterGroups'; -import { WorkflowStepFilterContext } from '@/workflow/workflow-steps/workflow-actions/filter-action/states/context/WorkflowStepFilterContext'; +import { WorkflowStepFilterAddFilterRuleSelect } from '@/workflow/workflow-steps/filters/components/WorkflowStepFilterAddFilterRuleSelect'; +import { WorkflowStepFilterColumn } from '@/workflow/workflow-steps/filters/components/WorkflowStepFilterColumn'; +import { useChildStepFiltersAndChildStepFilterGroups } from '@/workflow/workflow-steps/filters/hooks/useChildStepFiltersAndChildStepFilterGroups'; +import { WorkflowStepFilterContext } from '@/workflow/workflow-steps/filters/states/context/WorkflowStepFilterContext'; import styled from '@emotion/styled'; import { useContext } from 'react'; import { isDefined } from 'twenty-shared/utils'; diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterGroupColumn.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/filters/components/WorkflowStepFilterGroupColumn.tsx similarity index 81% rename from packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterGroupColumn.tsx rename to packages/twenty-front/src/modules/workflow/workflow-steps/filters/components/WorkflowStepFilterGroupColumn.tsx index d4072478ac..3ed98a276f 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterGroupColumn.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/filters/components/WorkflowStepFilterGroupColumn.tsx @@ -1,8 +1,8 @@ import { AdvancedFilterCommandMenuColumn } from '@/object-record/advanced-filter/command-menu/components/AdvancedFilterCommandMenuColumn'; -import { WorkflowStepFilterGroupChildren } from '@/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterGroupChildren'; -import { WorkflowStepFilterGroupOptionsDropdown } from '@/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterGroupOptionsDropdown'; -import { WorkflowStepFilterLogicalOperatorCell } from '@/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterLogicalOperatorCell'; -import { WorkflowStepFilterContext } from '@/workflow/workflow-steps/workflow-actions/filter-action/states/context/WorkflowStepFilterContext'; +import { WorkflowStepFilterGroupChildren } from '@/workflow/workflow-steps/filters/components/WorkflowStepFilterGroupChildren'; +import { WorkflowStepFilterGroupOptionsDropdown } from '@/workflow/workflow-steps/filters/components/WorkflowStepFilterGroupOptionsDropdown'; +import { WorkflowStepFilterLogicalOperatorCell } from '@/workflow/workflow-steps/filters/components/WorkflowStepFilterLogicalOperatorCell'; +import { WorkflowStepFilterContext } from '@/workflow/workflow-steps/filters/states/context/WorkflowStepFilterContext'; import styled from '@emotion/styled'; import { useContext } from 'react'; import { type StepFilterGroup } from 'twenty-shared/types'; diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterGroupOptionsDropdown.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/filters/components/WorkflowStepFilterGroupOptionsDropdown.tsx similarity index 92% rename from packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterGroupOptionsDropdown.tsx rename to packages/twenty-front/src/modules/workflow/workflow-steps/filters/components/WorkflowStepFilterGroupOptionsDropdown.tsx index 5ae2bba7aa..6daf32b5b5 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterGroupOptionsDropdown.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/filters/components/WorkflowStepFilterGroupOptionsDropdown.tsx @@ -2,8 +2,8 @@ import { DEFAULT_ADVANCED_FILTER_DROPDOWN_OFFSET } from '@/object-record/advance import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; -import { useRemoveStepFilterGroup } from '@/workflow/workflow-steps/workflow-actions/filter-action/hooks/useRemoveStepFilterGroup'; -import { WorkflowStepFilterContext } from '@/workflow/workflow-steps/workflow-actions/filter-action/states/context/WorkflowStepFilterContext'; +import { useRemoveStepFilterGroup } from '@/workflow/workflow-steps/filters/hooks/useRemoveStepFilterGroup'; +import { WorkflowStepFilterContext } from '@/workflow/workflow-steps/filters/states/context/WorkflowStepFilterContext'; import { useContext } from 'react'; import { t } from '@lingui/core/macro'; import { IconDotsVertical, IconTrash } from 'twenty-ui/display'; diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterLogicalOperatorCell.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/filters/components/WorkflowStepFilterLogicalOperatorCell.tsx similarity index 91% rename from packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterLogicalOperatorCell.tsx rename to packages/twenty-front/src/modules/workflow/workflow-steps/filters/components/WorkflowStepFilterLogicalOperatorCell.tsx index a50e237b95..763c67bc30 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterLogicalOperatorCell.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/filters/components/WorkflowStepFilterLogicalOperatorCell.tsx @@ -1,11 +1,11 @@ import { DEFAULT_ADVANCED_FILTER_DROPDOWN_OFFSET } from '@/object-record/advanced-filter/constants/DefaultAdvancedFilterDropdownOffset'; 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 { useUpsertStepFilterSettings } from '@/workflow/workflow-steps/filters/hooks/useUpsertStepFilterSettings'; +import { WorkflowStepFilterContext } from '@/workflow/workflow-steps/filters/states/context/WorkflowStepFilterContext'; -import { useLingui } from '@lingui/react/macro'; import styled from '@emotion/styled'; +import { useLingui } from '@lingui/react/macro'; import { useContext, useMemo } from 'react'; import { StepLogicalOperator, type StepFilterGroup } from 'twenty-shared/types'; import { capitalize } from 'twenty-shared/utils'; @@ -27,14 +27,17 @@ const StyledContainer = styled.div` type WorkflowStepFilterLogicalOperatorCellProps = { index: number; stepFilterGroup: StepFilterGroup; + firstFilterLabel?: string; }; export const WorkflowStepFilterLogicalOperatorCell = ({ index, stepFilterGroup, + firstFilterLabel, }: WorkflowStepFilterLogicalOperatorCellProps) => { const { readonly } = useContext(WorkflowStepFilterContext); const { t } = useLingui(); + const defaultFirstFilterLabel = t`Where`; const { upsertStepFilterSettings } = useUpsertStepFilterSettings(); @@ -66,7 +69,7 @@ export const WorkflowStepFilterLogicalOperatorCell = ({ return ( {index === 0 ? ( - {t`Where`} + {firstFilterLabel ?? defaultFirstFilterLabel} ) : index === 1 ? ( readonly ? (