Fix if-else node drag-to-create (#16944)

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
This commit is contained in:
Abdul Rahman
2026-01-06 17:58:29 +05:30
committed by GitHub
parent 3539f5cb7a
commit e51cf607c9
4 changed files with 141 additions and 7 deletions
@@ -3,11 +3,17 @@ import { CommandMenuWorkflowSelectAction } from '@/command-menu/pages/workflow/a
import { commandMenuNavigationStackState } from '@/command-menu/states/commandMenuNavigationStackState';
import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
import { workflowVisualizerWorkflowIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowIdComponentState';
import { type WorkflowActionType } from '@/workflow/types/Workflow';
import {
type WorkflowActionType,
type WorkflowIfElseAction,
} from '@/workflow/types/Workflow';
import { useCloseRightClickMenu } from '@/workflow/workflow-diagram/hooks/useCloseRightClickMenu';
import { useCreateStep } from '@/workflow/workflow-steps/hooks/useCreateStep';
import { useUpdateStep } from '@/workflow/workflow-steps/hooks/useUpdateStep';
import { workflowInsertStepIdsComponentState } from '@/workflow/workflow-steps/states/workflowInsertStepIdsComponentState';
import { prepareIfElseStepWithNewBranch } from '@/workflow/workflow-steps/workflow-actions/if-else-action/utils/prepareIfElseStepWithNewBranch';
import { getActionIcon } from '@/workflow/workflow-steps/workflow-actions/utils/getActionIcon';
import { useSetRecoilState } from 'recoil';
import { isDefined } from 'twenty-shared/utils';
@@ -20,6 +26,10 @@ export const CommandMenuWorkflowCreateStepContent = () => {
);
const { createStep } = useCreateStep();
const { updateStep } = useUpdateStep();
const workflowWithCurrentVersion = useWorkflowWithCurrentVersion(
workflowVisualizerWorkflowId,
);
const { openWorkflowEditStepInCommandMenu } = useWorkflowCommandMenu();
const { closeRightClickMenu } = useCloseRightClickMenu();
@@ -30,6 +40,21 @@ export const CommandMenuWorkflowCreateStepContent = () => {
const [workflowInsertStepIds, setWorkflowInsertStepIds] =
useRecoilComponentState(workflowInsertStepIdsComponentState);
const handleIfElseParentStep = async ({
parentStep,
createdStepId,
}: {
parentStep: WorkflowIfElseAction;
createdStepId: string;
}) => {
const updatedStep = prepareIfElseStepWithNewBranch({
parentStep,
targetStepId: createdStepId,
});
await updateStep(updatedStep);
};
const handleCreateStep = async (actionType: WorkflowActionType) => {
if (!isDefined(workflowVisualizerWorkflowId)) {
throw new Error(
@@ -52,6 +77,19 @@ export const CommandMenuWorkflowCreateStepContent = () => {
return;
}
const steps = workflowWithCurrentVersion?.currentVersion?.steps;
const parentStep =
isDefined(parentStepId) && isDefined(steps) && isDefined(position)
? steps.find((step) => step.id === parentStepId)
: undefined;
if (parentStep?.type === 'IF_ELSE') {
await handleIfElseParentStep({
parentStep,
createdStepId: createdStep.id,
});
}
setWorkflowInsertStepIds({
parentStepId: undefined,
nextStepId: undefined,
@@ -23,6 +23,7 @@ import { WorkflowDiagramStepNodeEditable } from '@/workflow/workflow-diagram/wor
import { useCreateEdge } from '@/workflow/workflow-steps/hooks/useCreateEdge';
import { useDeleteEdge } from '@/workflow/workflow-steps/hooks/useDeleteEdge';
import { useUpdateStep } from '@/workflow/workflow-steps/hooks/useUpdateStep';
import { prepareIfElseStepWithNewBranch } from '@/workflow/workflow-steps/workflow-actions/if-else-action/utils/prepareIfElseStepWithNewBranch';
import { useUpdateWorkflowVersionTrigger } from '@/workflow/workflow-trigger/hooks/useUpdateWorkflowVersionTrigger';
import {
addEdge,
@@ -60,7 +61,21 @@ export const WorkflowDiagramCanvasEditable = () => {
const { startNodeCreation } = useStartNodeCreation();
const onConnect = (edgeConnect: WorkflowConnection) => {
const onConnect = async (edgeConnect: WorkflowConnection) => {
const steps = workflowWithCurrentVersion?.currentVersion?.steps;
const sourceStep = isDefined(steps)
? steps.find((step) => step.id === edgeConnect.source)
: undefined;
if (sourceStep?.type === 'IF_ELSE') {
const updatedStep = prepareIfElseStepWithNewBranch({
parentStep: sourceStep,
targetStepId: edgeConnect.target,
});
await updateStep(updatedStep);
}
setWorkflowDiagram((diagram) => {
if (isDefined(diagram) === false) {
throw new Error(
@@ -74,6 +89,10 @@ export const WorkflowDiagramCanvasEditable = () => {
};
});
if (sourceStep?.type === 'IF_ELSE') {
return;
}
createEdge({
source: edgeConnect.source,
target: edgeConnect.target,
@@ -1,4 +1,5 @@
import { useRecoilComponentFamilyState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
import { currentStepFilterGroupsComponentState } from '@/workflow/workflow-steps/filters/states/currentStepFilterGroupsComponentState';
import { currentStepFiltersComponentState } from '@/workflow/workflow-steps/filters/states/currentStepFiltersComponentState';
@@ -13,6 +14,7 @@ import {
convertViewFilterOperandToCoreOperand,
isDefined,
} from 'twenty-shared/utils';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
type FilterSettingsWithPotentiallyDeprecatedOperand = {
stepFilterGroups?: StepFilterGroup[];
@@ -42,6 +44,13 @@ export const WorkflowEditActionFilterBodyEffect = ({
{ stepId },
);
const currentStepFilters = useRecoilComponentValue(
currentStepFiltersComponentState,
);
const currentStepFilterGroups = useRecoilComponentValue(
currentStepFilterGroupsComponentState,
);
const setCurrentStepFilters = useSetRecoilComponentState(
currentStepFiltersComponentState,
);
@@ -58,8 +67,20 @@ export const WorkflowEditActionFilterBodyEffect = ({
}, [defaultValue?.stepFilters]);
useEffect(() => {
if (!hasInitializedCurrentStepFilters && isDefined(stepFiltersConverted)) {
setCurrentStepFilters(stepFiltersConverted ?? []);
if (!isDefined(stepFiltersConverted)) {
return;
}
if (
hasInitializedCurrentStepFilters &&
isDeeplyEqual(currentStepFilters, stepFiltersConverted)
) {
return;
}
setCurrentStepFilters(stepFiltersConverted ?? []);
if (!hasInitializedCurrentStepFilters) {
setHasInitializedCurrentStepFilters(true);
}
}, [
@@ -67,15 +88,34 @@ export const WorkflowEditActionFilterBodyEffect = ({
hasInitializedCurrentStepFilters,
setHasInitializedCurrentStepFilters,
stepFiltersConverted,
currentStepFilters,
]);
useEffect(() => {
if (!isDefined(defaultValue?.stepFilterGroups)) {
return;
}
if (
!hasInitializedCurrentStepFilterGroups &&
isDefined(defaultValue?.stepFilterGroups) &&
defaultValue.stepFilterGroups.length > 0
defaultValue.stepFilterGroups.length === 0
) {
setCurrentStepFilterGroups(defaultValue.stepFilterGroups ?? []);
return;
}
if (
hasInitializedCurrentStepFilterGroups &&
isDeeplyEqual(
currentStepFilterGroups,
defaultValue.stepFilterGroups ?? [],
)
) {
return;
}
setCurrentStepFilterGroups(defaultValue.stepFilterGroups ?? []);
if (!hasInitializedCurrentStepFilterGroups) {
setHasInitializedCurrentStepFilterGroups(true);
}
}, [
@@ -83,6 +123,7 @@ export const WorkflowEditActionFilterBodyEffect = ({
hasInitializedCurrentStepFilterGroups,
setHasInitializedCurrentStepFilterGroups,
defaultValue?.stepFilterGroups,
currentStepFilterGroups,
]);
return null;
@@ -0,0 +1,36 @@
import { type WorkflowIfElseAction } from '@/workflow/types/Workflow';
import { createElseIfBranch } from './createElseIfBranch';
export const prepareIfElseStepWithNewBranch = ({
parentStep,
targetStepId,
}: {
parentStep: WorkflowIfElseAction;
targetStepId: string;
}): WorkflowIfElseAction => {
const branches = parentStep.settings.input.branches;
const stepFilterGroups = parentStep.settings.input.stepFilterGroups;
const stepFilters = parentStep.settings.input.stepFilters;
const { filterGroup, filter, branchId, filterGroupId } = createElseIfBranch();
const updatedBranches = [...branches];
updatedBranches.splice(branches.length - 1, 0, {
id: branchId,
filterGroupId,
nextStepIds: [targetStepId],
});
return {
...parentStep,
settings: {
...parentStep.settings,
input: {
...parentStep.settings.input,
stepFilterGroups: [...stepFilterGroups, filterGroup],
stepFilters: [...stepFilters, filter],
branches: updatedBranches,
},
},
};
};