feat: Add If/Else node (#16833)

Closes [#1265](https://github.com/twentyhq/core-team-issues/issues/1265)
This commit is contained in:
Abdul Rahman
2026-01-01 19:35:56 +05:30
committed by GitHub
parent 5d5fd5fca5
commit dff5e3cd7b
95 changed files with 1523 additions and 163 deletions
@@ -34,12 +34,16 @@ export const useCreateStep = () => {
nextStepId,
position,
connectionOptions,
shouldSelectNode = true,
workflowVersionId: providedWorkflowVersionId,
}: {
newStepType: WorkflowActionType;
parentStepId: string | undefined;
nextStepId: string | undefined;
position?: { x: number; y: number };
connectionOptions?: WorkflowStepConnectionOptions;
shouldSelectNode?: boolean;
workflowVersionId?: string;
}) => {
if (isLoading === true) {
return;
@@ -48,7 +52,8 @@ export const useCreateStep = () => {
setIsLoading(true);
try {
const workflowVersionId = await getUpdatableWorkflowVersion();
const workflowVersionId =
providedWorkflowVersionId ?? (await getUpdatableWorkflowVersion());
const id = v4();
const workflowVersionStepChanges = (
@@ -77,7 +82,9 @@ export const useCreateStep = () => {
throw new Error("Couldn't create step");
}
setWorkflowSelectedNode(id);
if (shouldSelectNode) {
setWorkflowSelectedNode(id);
}
setWorkflowLastCreatedStepId(id);
return isDefined(createdFirstStepDiff)
@@ -3,8 +3,10 @@ import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/ho
import { useGetUpdatableWorkflowVersionOrThrow } from '@/workflow/hooks/useGetUpdatableWorkflowVersionOrThrow';
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
import { workflowVisualizerWorkflowIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowIdComponentState';
import { type WorkflowIfElseAction } from '@/workflow/types/Workflow';
import { useDeleteWorkflowVersionStep } from '@/workflow/workflow-steps/hooks/useDeleteWorkflowVersionStep';
import { useResetWorkflowAiAgentPermissionsStateOnCommandMenuClose } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/hooks/useResetWorkflowAiAgentPermissionsStateOnCommandMenuClose';
import { getEmptyChildStepIds } from '@/workflow/workflow-steps/workflow-actions/if-else-action/utils/getEmptyChildStepIds';
import { useStepsOutputSchema } from '@/workflow/workflow-variables/hooks/useStepsOutputSchema';
import { isDefined } from 'twenty-shared/utils';
@@ -25,11 +27,35 @@ export const useDeleteStep = () => {
const deleteStep = async (stepId: string) => {
const workflowVersionId = await getUpdatableWorkflowVersion();
const isAiAgentStep =
isDefined(workflow?.currentVersion?.steps) &&
workflow.currentVersion.steps.some(
(step) => step.id === stepId && step.type === 'AI_AGENT',
);
const steps = workflow?.currentVersion?.steps;
const stepToDelete = isDefined(steps)
? steps.find((step) => step.id === stepId)
: undefined;
if (
isDefined(stepToDelete) &&
isDefined(steps) &&
stepToDelete.type === 'IF_ELSE'
) {
const emptyChildStepIds = getEmptyChildStepIds({
ifElseAction: stepToDelete as WorkflowIfElseAction,
allSteps: steps,
});
for (const emptyChildStepId of emptyChildStepIds) {
await deleteWorkflowVersionStep({
workflowVersionId,
stepId: emptyChildStepId,
});
}
if (emptyChildStepIds.length > 0) {
deleteStepsOutputSchema({
stepIds: emptyChildStepIds,
workflowVersionId,
});
}
}
await deleteWorkflowVersionStep({
workflowVersionId,
@@ -43,7 +69,7 @@ export const useDeleteStep = () => {
workflowVersionId,
});
if (isAiAgentStep) {
if (isDefined(stepToDelete) && stepToDelete.type === 'AI_AGENT') {
resetPermissionState();
}
};