diff --git a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-version-step/utils/__tests__/remove-step.spec.ts b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-version-step/utils/__tests__/remove-step.spec.ts index 23807ec83b..5954274b33 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-version-step/utils/__tests__/remove-step.spec.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-version-step/utils/__tests__/remove-step.spec.ts @@ -194,4 +194,52 @@ describe('removeStep', () => { expect(result.updatedTrigger).toEqual(null); expect(result.updatedSteps).toEqual([step2, step3]); }); + + it('should remove filter step if it has no children', () => { + const step1 = { + id: '1', + name: 'Step 1', + type: WorkflowActionType.FILTER, + nextStepIds: ['2'], + } as WorkflowAction; + const step2 = createMockAction('2', ['3']); + const step3 = { + id: '3', + name: 'Step 3', + type: WorkflowActionType.FILTER, + nextStepIds: ['4'], + } as WorkflowAction; + const step4 = createMockAction('4'); + + const result = removeStep({ + existingTrigger: mockTrigger, + existingSteps: [step1, step2, step3, step4], + stepIdToDelete: '4', + }); + + expect(result.updatedTrigger).toEqual(mockTrigger); + expect(result.updatedSteps).toEqual([step1, { ...step2, nextStepIds: [] }]); + }); + + it('should remove filter step if it is the last step', () => { + const step1 = { + id: '1', + name: 'Step 1', + type: WorkflowActionType.FILTER, + nextStepIds: ['2'], + } as WorkflowAction; + const step2 = createMockAction('2'); + + const result = removeStep({ + existingTrigger: mockTrigger, + existingSteps: [step1, step2], + stepIdToDelete: '2', + }); + + expect(result.updatedTrigger).toEqual({ + ...mockTrigger, + nextStepIds: [], + }); + expect(result.updatedSteps).toEqual([]); + }); }); diff --git a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-version-step/utils/remove-step.ts b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-version-step/utils/remove-step.ts index deed95d759..75569b7edb 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-version-step/utils/remove-step.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-version-step/utils/remove-step.ts @@ -8,15 +8,15 @@ import { WorkflowTrigger } from 'src/modules/workflow/workflow-trigger/types/wor const computeUpdatedNextStepIds = ({ existingNextStepIds, - stepIdToDelete, + stepIdToRemove, stepToDeleteChildrenIds, }: { existingNextStepIds: string[]; - stepIdToDelete: string; + stepIdToRemove: string; stepToDeleteChildrenIds?: string[]; }): string[] => { const filteredNextStepIds = isDefined(existingNextStepIds) - ? existingNextStepIds.filter((id) => id !== stepIdToDelete) + ? existingNextStepIds.filter((id) => id !== stepIdToRemove) : []; return [ @@ -28,6 +28,60 @@ const computeUpdatedNextStepIds = ({ ]; }; +const removeOneStep = ({ + existingTrigger, + existingSteps, + stepIdToDelete, + stepToDeleteChildrenIds, +}: { + existingTrigger: WorkflowTrigger | null; + existingSteps: WorkflowAction[]; + stepIdToDelete: string; + stepToDeleteChildrenIds?: string[]; +}): { + updatedSteps: WorkflowAction[]; + updatedTrigger: WorkflowTrigger | null; + removedStepIds: string[]; +} => { + const updatedSteps = existingSteps + .filter((step) => step.id !== stepIdToDelete) + .map((step) => { + if (step.nextStepIds?.includes(stepIdToDelete)) { + return { + ...step, + nextStepIds: computeUpdatedNextStepIds({ + existingNextStepIds: step.nextStepIds, + stepIdToRemove: stepIdToDelete, + stepToDeleteChildrenIds: stepToDeleteChildrenIds, + }), + }; + } + + return step; + }); + + let updatedTrigger = existingTrigger; + + if (isDefined(existingTrigger)) { + if (existingTrigger.nextStepIds?.includes(stepIdToDelete)) { + updatedTrigger = { + ...existingTrigger, + nextStepIds: computeUpdatedNextStepIds({ + existingNextStepIds: existingTrigger.nextStepIds, + stepIdToRemove: stepIdToDelete, + stepToDeleteChildrenIds, + }), + }; + } + } + + return { + updatedSteps, + updatedTrigger, + removedStepIds: [stepIdToDelete], + }; +}; + const removeRegularStep = ({ existingTrigger, existingSteps, @@ -43,59 +97,66 @@ const removeRegularStep = ({ updatedTrigger: WorkflowTrigger | null; removedStepIds: string[]; } => { - const stepIdsToRemove = [stepIdToDelete]; - const stepIdsToRemoveChildrenIds = - stepToDeleteChildrenIds - ?.map((id) => { - const step = existingSteps.find((step) => step.id === id); + let { updatedSteps, updatedTrigger, removedStepIds } = removeOneStep({ + existingTrigger, + existingSteps, + stepIdToDelete, + stepToDeleteChildrenIds, + }); - if (step?.type === WorkflowActionType.FILTER) { - stepIdsToRemove.push(step.id); + for (const stepId of stepToDeleteChildrenIds ?? []) { + const step = existingSteps.find((step) => step.id === stepId); - return step.nextStepIds; - } + if (step?.type === WorkflowActionType.FILTER) { + const { + updatedSteps: stepsAfterRemovingChildFilter, + updatedTrigger: triggerAfterRemovingChildFilter, + removedStepIds: removedStepIdsAfterRemovingChildFilter, + } = removeOneStep({ + existingTrigger: updatedTrigger, + existingSteps: updatedSteps, + stepIdToDelete: stepId, + stepToDeleteChildrenIds: step.nextStepIds, + }); - return id; - }) - .filter(isDefined) - .flat() ?? []; + updatedSteps = stepsAfterRemovingChildFilter; + updatedTrigger = triggerAfterRemovingChildFilter; + removedStepIds = [ + ...removedStepIds, + ...removedStepIdsAfterRemovingChildFilter, + ]; + } + } - const updatedSteps = existingSteps - .filter((step) => !stepIdsToRemove.includes(step.id)) - .map((step) => { - if (step.nextStepIds?.includes(stepIdToDelete)) { - return { - ...step, - nextStepIds: computeUpdatedNextStepIds({ - existingNextStepIds: step.nextStepIds, - stepIdToDelete, - stepToDeleteChildrenIds: stepIdsToRemoveChildrenIds, - }), - }; - } + for (const step of updatedSteps) { + if ( + step?.type === WorkflowActionType.FILTER && + (!isDefined(step?.nextStepIds) || step.nextStepIds?.length === 0) + ) { + const { + updatedSteps: stepsAfterRemovingFilterWithoutChildren, + updatedTrigger: triggerAfterRemovingFilterWithoutChildren, + removedStepIds: removedStepIdsAfterRemovingFilterWithoutChildren, + } = removeOneStep({ + existingTrigger: updatedTrigger, + existingSteps: updatedSteps, + stepIdToDelete: step.id, + stepToDeleteChildrenIds: step.nextStepIds, + }); - return step; - }); - - let updatedTrigger = existingTrigger; - - if (isDefined(existingTrigger)) { - if (existingTrigger.nextStepIds?.includes(stepIdToDelete)) { - updatedTrigger = { - ...existingTrigger, - nextStepIds: computeUpdatedNextStepIds({ - existingNextStepIds: existingTrigger.nextStepIds, - stepIdToDelete, - stepToDeleteChildrenIds: stepIdsToRemoveChildrenIds, - }), - }; + updatedSteps = stepsAfterRemovingFilterWithoutChildren; + updatedTrigger = triggerAfterRemovingFilterWithoutChildren; + removedStepIds = [ + ...removedStepIds, + ...removedStepIdsAfterRemovingFilterWithoutChildren, + ]; } } return { - updatedTrigger, updatedSteps, - removedStepIds: stepIdsToRemove, + updatedTrigger, + removedStepIds, }; };