forked from twentyhq/twenty
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Delete workflow step (twentyhq#7373)
- Allows the deletion of triggers and steps in workflows. If the workflow can not be edited right now, we create a new draft version. - The workflow right drawer can now render nothing. It's necessary to behave that way because a deleted step will still be displayed for a short amount of time in the drawer. The drawer will be filled with blank content when it disappears. https://github.com/user-attachments/assets/abd5184e-d3db-4fe7-8870-ccc78ff23d41 Closes twentyhq#7057
- Loading branch information
1 parent
24dbd1e
commit 8d6063f
Showing
8 changed files
with
308 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
76 changes: 76 additions & 0 deletions
76
packages/twenty-front/src/modules/workflow/hooks/useDeleteOneStep.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; | ||
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; | ||
import { TRIGGER_STEP_ID } from '@/workflow/constants/TriggerStepId'; | ||
import { useCreateNewWorkflowVersion } from '@/workflow/hooks/useCreateNewWorkflowVersion'; | ||
import { | ||
WorkflowVersion, | ||
WorkflowWithCurrentVersion, | ||
} from '@/workflow/types/Workflow'; | ||
import { removeStep } from '@/workflow/utils/removeStep'; | ||
|
||
export const useDeleteOneStep = ({ | ||
stepId, | ||
workflow, | ||
}: { | ||
stepId: string; | ||
workflow: WorkflowWithCurrentVersion; | ||
}) => { | ||
const { updateOneRecord: updateOneWorkflowVersion } = | ||
useUpdateOneRecord<WorkflowVersion>({ | ||
objectNameSingular: CoreObjectNameSingular.WorkflowVersion, | ||
}); | ||
|
||
const { createNewWorkflowVersion } = useCreateNewWorkflowVersion({ | ||
workflowId: workflow.id, | ||
}); | ||
|
||
const deleteOneStep = async () => { | ||
if (workflow.currentVersion.status !== 'DRAFT') { | ||
const newVersionName = `v${workflow.versions.length + 1}`; | ||
|
||
if (stepId === TRIGGER_STEP_ID) { | ||
await createNewWorkflowVersion({ | ||
name: newVersionName, | ||
status: 'DRAFT', | ||
trigger: null, | ||
steps: workflow.currentVersion.steps, | ||
}); | ||
} else { | ||
await createNewWorkflowVersion({ | ||
name: newVersionName, | ||
status: 'DRAFT', | ||
trigger: workflow.currentVersion.trigger, | ||
steps: removeStep({ | ||
steps: workflow.currentVersion.steps ?? [], | ||
stepId, | ||
}), | ||
}); | ||
} | ||
|
||
return; | ||
} | ||
|
||
if (stepId === TRIGGER_STEP_ID) { | ||
await updateOneWorkflowVersion({ | ||
idToUpdate: workflow.currentVersion.id, | ||
updateOneRecordInput: { | ||
trigger: null, | ||
}, | ||
}); | ||
} else { | ||
await updateOneWorkflowVersion({ | ||
idToUpdate: workflow.currentVersion.id, | ||
updateOneRecordInput: { | ||
steps: removeStep({ | ||
steps: workflow.currentVersion.steps ?? [], | ||
stepId, | ||
}), | ||
}, | ||
}); | ||
} | ||
}; | ||
|
||
return { | ||
deleteOneStep, | ||
}; | ||
}; |
108 changes: 108 additions & 0 deletions
108
packages/twenty-front/src/modules/workflow/utils/__tests__/removeStep.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
import { WorkflowStep, WorkflowVersion } from '@/workflow/types/Workflow'; | ||
import { removeStep } from '../removeStep'; | ||
|
||
it('returns a deep copy of the provided steps array instead of mutating it', () => { | ||
const stepToBeRemoved = { | ||
id: 'step-1', | ||
name: '', | ||
settings: { | ||
errorHandlingOptions: { | ||
retryOnFailure: { value: true }, | ||
continueOnFailure: { value: false }, | ||
}, | ||
serverlessFunctionId: 'first', | ||
}, | ||
type: 'CODE', | ||
valid: true, | ||
} satisfies WorkflowStep; | ||
const workflowVersionInitial = { | ||
__typename: 'WorkflowVersion', | ||
status: 'ACTIVE', | ||
createdAt: '', | ||
id: '1', | ||
name: '', | ||
steps: [stepToBeRemoved], | ||
trigger: { | ||
settings: { eventName: 'company.created' }, | ||
type: 'DATABASE_EVENT', | ||
}, | ||
updatedAt: '', | ||
workflowId: '', | ||
} satisfies WorkflowVersion; | ||
|
||
const stepsUpdated = removeStep({ | ||
steps: workflowVersionInitial.steps, | ||
stepId: stepToBeRemoved.id, | ||
}); | ||
|
||
expect(workflowVersionInitial.steps).not.toBe(stepsUpdated); | ||
}); | ||
|
||
it('removes a step in a non-empty steps array', () => { | ||
const stepToBeRemoved: WorkflowStep = { | ||
id: 'step-2', | ||
name: '', | ||
settings: { | ||
errorHandlingOptions: { | ||
retryOnFailure: { value: true }, | ||
continueOnFailure: { value: false }, | ||
}, | ||
serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997', | ||
}, | ||
type: 'CODE', | ||
valid: true, | ||
}; | ||
const workflowVersionInitial = { | ||
__typename: 'WorkflowVersion', | ||
status: 'ACTIVE', | ||
createdAt: '', | ||
id: '1', | ||
name: '', | ||
steps: [ | ||
{ | ||
id: 'step-1', | ||
name: '', | ||
settings: { | ||
errorHandlingOptions: { | ||
retryOnFailure: { value: true }, | ||
continueOnFailure: { value: false }, | ||
}, | ||
serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997', | ||
}, | ||
type: 'CODE', | ||
valid: true, | ||
}, | ||
stepToBeRemoved, | ||
{ | ||
id: 'step-3', | ||
name: '', | ||
settings: { | ||
errorHandlingOptions: { | ||
retryOnFailure: { value: true }, | ||
continueOnFailure: { value: false }, | ||
}, | ||
serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997', | ||
}, | ||
type: 'CODE', | ||
valid: true, | ||
}, | ||
], | ||
trigger: { | ||
settings: { eventName: 'company.created' }, | ||
type: 'DATABASE_EVENT', | ||
}, | ||
updatedAt: '', | ||
workflowId: '', | ||
} satisfies WorkflowVersion; | ||
|
||
const stepsUpdated = removeStep({ | ||
steps: workflowVersionInitial.steps, | ||
stepId: stepToBeRemoved.id, | ||
}); | ||
|
||
const expectedUpdatedSteps: Array<WorkflowStep> = [ | ||
workflowVersionInitial.steps[0], | ||
workflowVersionInitial.steps[2], | ||
]; | ||
expect(stepsUpdated).toEqual(expectedUpdatedSteps); | ||
}); |
41 changes: 41 additions & 0 deletions
41
packages/twenty-front/src/modules/workflow/utils/findStepPosition.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { TRIGGER_STEP_ID } from '@/workflow/constants/TriggerStepId'; | ||
import { WorkflowStep } from '@/workflow/types/Workflow'; | ||
import { isDefined } from 'twenty-ui'; | ||
|
||
/** | ||
* This function returns the reference of the array where the step should be positioned | ||
* and at which index. | ||
*/ | ||
export const findStepPosition = ({ | ||
steps, | ||
stepId, | ||
}: { | ||
steps: Array<WorkflowStep>; | ||
stepId: string | undefined; | ||
}): { steps: Array<WorkflowStep>; index: number } | undefined => { | ||
if (!isDefined(stepId) || stepId === TRIGGER_STEP_ID) { | ||
return { | ||
steps, | ||
index: 0, | ||
}; | ||
} | ||
|
||
for (const [index, step] of steps.entries()) { | ||
if (step.id === stepId) { | ||
return { | ||
steps, | ||
index, | ||
}; | ||
} | ||
|
||
// TODO: When condition will have been implemented, put recursivity here. | ||
// if (step.type === "CONDITION") { | ||
// return findNodePosition({ | ||
// workflowSteps: step.conditions, | ||
// stepId, | ||
// }) | ||
// } | ||
} | ||
|
||
return undefined; | ||
}; |
Oops, something went wrong.