diff --git a/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramStepNodeBase.tsx b/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramStepNodeBase.tsx index 859d22ee4..b2138d89b 100644 --- a/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramStepNodeBase.tsx +++ b/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramStepNodeBase.tsx @@ -76,8 +76,9 @@ export const WorkflowDiagramStepNodeBase = ({ ); } - case 'RECORD_CRUD.UPDATE': - case 'RECORD_CRUD.CREATE': { + case 'CREATE_RECORD': + case 'UPDATE_RECORD': + case 'DELETE_RECORD': { return ( ); } - - case 'RECORD_CRUD.DELETE': { - return null; - } } } } diff --git a/packages/twenty-front/src/modules/workflow/components/WorkflowStepDetail.tsx b/packages/twenty-front/src/modules/workflow/components/WorkflowStepDetail.tsx index 1319673bf..59e6228e4 100644 --- a/packages/twenty-front/src/modules/workflow/components/WorkflowStepDetail.tsx +++ b/packages/twenty-front/src/modules/workflow/components/WorkflowStepDetail.tsx @@ -7,13 +7,10 @@ import { } from '@/workflow/types/Workflow'; import { assertUnreachable } from '@/workflow/utils/assertUnreachable'; import { getStepDefinitionOrThrow } from '@/workflow/utils/getStepDefinitionOrThrow'; -import { WorkflowEditActionFormRecordCreate } from '@/workflow/workflow-actions/components/WorkflowEditActionFormRecordCreate'; -import { WorkflowEditActionFormRecordDelete } from '@/workflow/workflow-actions/components/WorkflowEditActionFormRecordDelete'; -import { WorkflowEditActionFormRecordUpdate } from '@/workflow/workflow-actions/components/WorkflowEditActionFormRecordUpdate'; +import { WorkflowEditActionFormCreateRecord } from '@/workflow/workflow-actions/components/WorkflowEditActionFormCreateRecord'; +import { WorkflowEditActionFormDeleteRecord } from '@/workflow/workflow-actions/components/WorkflowEditActionFormDeleteRecord'; import { WorkflowEditActionFormSendEmail } from '@/workflow/workflow-actions/components/WorkflowEditActionFormSendEmail'; -import { isWorkflowRecordCreateAction } from '@/workflow/workflow-actions/utils/isWorkflowRecordCreateAction'; -import { isWorkflowRecordDeleteAction } from '@/workflow/workflow-actions/utils/isWorkflowRecordDeleteAction'; -import { isWorkflowRecordUpdateAction } from '@/workflow/workflow-actions/utils/isWorkflowRecordUpdateAction'; +import { WorkflowEditActionFormUpdateRecord } from '@/workflow/workflow-actions/components/WorkflowEditActionFormUpdateRecord'; import { lazy, Suspense } from 'react'; import { isDefined } from 'twenty-ui'; import { RightDrawerSkeletonLoader } from '~/loading/components/RightDrawerSkeletonLoader'; @@ -107,42 +104,35 @@ export const WorkflowStepDetail = ({ /> ); } - case 'RECORD_CRUD': { - if (isWorkflowRecordCreateAction(stepDefinition.definition)) { - return ( - - ); - } + case 'CREATE_RECORD': { + return ( + + ); + } - if (isWorkflowRecordUpdateAction(stepDefinition.definition)) { - return ( - - ); - } + case 'UPDATE_RECORD': { + return ( + + ); + } - if (isWorkflowRecordDeleteAction(stepDefinition.definition)) { - return ( - - ); - } - - return null; + case 'DELETE_RECORD': { + return ( + + ); } } - return assertUnreachable( - stepDefinition.definition, - `Expected the step to have an handler; ${JSON.stringify(stepDefinition)}`, - ); + return null; } } diff --git a/packages/twenty-front/src/modules/workflow/constants/Actions.ts b/packages/twenty-front/src/modules/workflow/constants/Actions.ts index 4f5b2c2ba..2302af495 100644 --- a/packages/twenty-front/src/modules/workflow/constants/Actions.ts +++ b/packages/twenty-front/src/modules/workflow/constants/Actions.ts @@ -22,17 +22,17 @@ export const ACTIONS: Array<{ }, { label: 'Create Record', - type: 'RECORD_CRUD.CREATE', + type: 'CREATE_RECORD', icon: IconAddressBook, }, { label: 'Update Record', - type: 'RECORD_CRUD.UPDATE', + type: 'UPDATE_RECORD', icon: IconAddressBook, }, { label: 'Delete Record', - type: 'RECORD_CRUD.DELETE', + type: 'DELETE_RECORD', icon: IconAddressBook, }, ]; diff --git a/packages/twenty-front/src/modules/workflow/types/Workflow.ts b/packages/twenty-front/src/modules/workflow/types/Workflow.ts index 0005fb4fb..65286e5f2 100644 --- a/packages/twenty-front/src/modules/workflow/types/Workflow.ts +++ b/packages/twenty-front/src/modules/workflow/types/Workflow.ts @@ -32,34 +32,26 @@ export type WorkflowSendEmailActionSettings = BaseWorkflowActionSettings & { type ObjectRecord = Record; -export type WorkflowCreateRecordActionInput = { - type: 'CREATE'; - objectName: string; - objectRecord: ObjectRecord; +export type WorkflowCreateRecordActionSettings = BaseWorkflowActionSettings & { + input: { + objectName: string; + objectRecord: ObjectRecord; + }; }; -export type WorkflowUpdateRecordActionInput = { - type: 'UPDATE'; - objectName: string; - objectRecord: ObjectRecord; - objectRecordId: string; +export type WorkflowUpdateRecordActionSettings = BaseWorkflowActionSettings & { + input: { + objectName: string; + objectRecord: ObjectRecord; + objectRecordId: string; + }; }; -export type WorkflowDeleteRecordActionInput = { - type: 'DELETE'; - objectName: string; - objectRecordId: string; -}; - -export type WorkflowRecordCRUDActionInput = - | WorkflowCreateRecordActionInput - | WorkflowUpdateRecordActionInput - | WorkflowDeleteRecordActionInput; - -export type WorkflowRecordCRUDType = WorkflowRecordCRUDActionInput['type']; - -export type WorkflowRecordCRUDActionSettings = BaseWorkflowActionSettings & { - input: WorkflowRecordCRUDActionInput; +export type WorkflowDeleteRecordActionSettings = BaseWorkflowActionSettings & { + input: { + objectName: string; + objectRecordId: string; + }; }; type BaseWorkflowAction = { @@ -78,35 +70,33 @@ export type WorkflowSendEmailAction = BaseWorkflowAction & { settings: WorkflowSendEmailActionSettings; }; -export type WorkflowRecordCRUDAction = BaseWorkflowAction & { - type: 'RECORD_CRUD'; - settings: WorkflowRecordCRUDActionSettings; +export type WorkflowCreateRecordAction = BaseWorkflowAction & { + type: 'CREATE_RECORD'; + settings: WorkflowCreateRecordActionSettings; }; -export type WorkflowRecordCreateAction = WorkflowRecordCRUDAction & { - settings: { input: { type: 'CREATE' } }; +export type WorkflowUpdateRecordAction = BaseWorkflowAction & { + type: 'UPDATE_RECORD'; + settings: WorkflowUpdateRecordActionSettings; }; -export type WorkflowRecordUpdateAction = WorkflowRecordCRUDAction & { - settings: { input: { type: 'UPDATE' } }; -}; - -export type WorkflowRecordDeleteAction = WorkflowRecordCRUDAction & { - settings: { input: { type: 'DELETE' } }; +export type WorkflowDeleteRecordAction = BaseWorkflowAction & { + type: 'DELETE_RECORD'; + settings: WorkflowDeleteRecordActionSettings; }; export type WorkflowAction = | WorkflowCodeAction | WorkflowSendEmailAction - | WorkflowRecordCRUDAction; + | WorkflowCreateRecordAction + | WorkflowUpdateRecordAction + | WorkflowDeleteRecordAction; + +export type WorkflowActionType = WorkflowAction['type']; export type WorkflowStep = WorkflowAction; -export type WorkflowActionType = - | Exclude - | `${WorkflowRecordCRUDAction['type']}.${WorkflowRecordCRUDType}`; - -export type WorkflowStepType = WorkflowActionType; +export type WorkflowStepType = WorkflowStep['type']; type BaseTrigger = { name?: string; diff --git a/packages/twenty-front/src/modules/workflow/utils/generateWorkflowDiagram.ts b/packages/twenty-front/src/modules/workflow/utils/generateWorkflowDiagram.ts index 8b701b944..abb470489 100644 --- a/packages/twenty-front/src/modules/workflow/utils/generateWorkflowDiagram.ts +++ b/packages/twenty-front/src/modules/workflow/utils/generateWorkflowDiagram.ts @@ -1,9 +1,5 @@ import { TRIGGER_STEP_ID } from '@/workflow/constants/TriggerStepId'; -import { - WorkflowActionType, - WorkflowStep, - WorkflowTrigger, -} from '@/workflow/types/Workflow'; +import { WorkflowStep, WorkflowTrigger } from '@/workflow/types/Workflow'; import { WorkflowDiagram, WorkflowDiagramEdge, @@ -35,25 +31,12 @@ export const generateWorkflowDiagram = ({ ) => { const nodeId = step.id; - let nodeActionType: WorkflowActionType; - if (step.type === 'RECORD_CRUD') { - nodeActionType = `RECORD_CRUD.${step.settings.input.type}`; - } else { - nodeActionType = step.type; - } - - let nodeLabel = step.name; - if (step.type === 'RECORD_CRUD') { - // FIXME: use activeObjectMetadataItems to get labelSingular - nodeLabel = `${capitalize(step.settings.input.type.toLowerCase())} ${capitalize(step.settings.input.objectName)}`; - } - nodes.push({ id: nodeId, data: { nodeType: 'action', - actionType: nodeActionType, - name: isDefined(step.name) ? step.name : nodeLabel, + actionType: step.type, + name: step.name, }, position: { x: xPos, diff --git a/packages/twenty-front/src/modules/workflow/workflow-actions/components/WorkflowEditActionFormRecordCreate.tsx b/packages/twenty-front/src/modules/workflow/workflow-actions/components/WorkflowEditActionFormCreateRecord.tsx similarity index 93% rename from packages/twenty-front/src/modules/workflow/workflow-actions/components/WorkflowEditActionFormRecordCreate.tsx rename to packages/twenty-front/src/modules/workflow/workflow-actions/components/WorkflowEditActionFormCreateRecord.tsx index 2e60adc42..fe186bede 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-actions/components/WorkflowEditActionFormRecordCreate.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-actions/components/WorkflowEditActionFormCreateRecord.tsx @@ -5,7 +5,7 @@ import { FormFieldInput } from '@/object-record/record-field/components/FormFiel import { Select, SelectOption } from '@/ui/input/components/Select'; import { WorkflowEditGenericFormBase } from '@/workflow/components/WorkflowEditGenericFormBase'; import { WorkflowVariablePicker } from '@/workflow/components/WorkflowVariablePicker'; -import { WorkflowRecordCreateAction } from '@/workflow/types/Workflow'; +import { WorkflowCreateRecordAction } from '@/workflow/types/Workflow'; import { useTheme } from '@emotion/react'; import { useEffect, useState } from 'react'; import { @@ -18,15 +18,15 @@ import { JsonValue } from 'type-fest'; import { useDebouncedCallback } from 'use-debounce'; import { FieldMetadataType } from '~/generated/graphql'; -type WorkflowEditActionFormRecordCreateProps = { - action: WorkflowRecordCreateAction; +type WorkflowEditActionFormCreateRecordProps = { + action: WorkflowCreateRecordAction; actionOptions: | { readonly: true; } | { readonly?: false; - onActionUpdate: (action: WorkflowRecordCreateAction) => void; + onActionUpdate: (action: WorkflowCreateRecordAction) => void; }; }; @@ -35,10 +35,10 @@ type CreateRecordFormData = { [field: string]: unknown; }; -export const WorkflowEditActionFormRecordCreate = ({ +export const WorkflowEditActionFormCreateRecord = ({ action, actionOptions, -}: WorkflowEditActionFormRecordCreateProps) => { +}: WorkflowEditActionFormCreateRecordProps) => { const theme = useTheme(); const { getIcon } = useIcons(); @@ -118,7 +118,6 @@ export const WorkflowEditActionFormRecordCreate = ({ settings: { ...action.settings, input: { - type: 'CREATE', objectName: updatedObjectName, objectRecord: updatedOtherFields, }, diff --git a/packages/twenty-front/src/modules/workflow/workflow-actions/components/WorkflowEditActionFormRecordDelete.tsx b/packages/twenty-front/src/modules/workflow/workflow-actions/components/WorkflowEditActionFormDeleteRecord.tsx similarity index 92% rename from packages/twenty-front/src/modules/workflow/workflow-actions/components/WorkflowEditActionFormRecordDelete.tsx rename to packages/twenty-front/src/modules/workflow/workflow-actions/components/WorkflowEditActionFormDeleteRecord.tsx index 3ca50035f..b01aab32c 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-actions/components/WorkflowEditActionFormRecordDelete.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-actions/components/WorkflowEditActionFormDeleteRecord.tsx @@ -2,7 +2,7 @@ import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilte import { Select, SelectOption } from '@/ui/input/components/Select'; import { WorkflowEditGenericFormBase } from '@/workflow/components/WorkflowEditGenericFormBase'; import { WorkflowSingleRecordPicker } from '@/workflow/components/WorkflowSingleRecordPicker'; -import { WorkflowRecordDeleteAction } from '@/workflow/types/Workflow'; +import { WorkflowDeleteRecordAction } from '@/workflow/types/Workflow'; import { useTheme } from '@emotion/react'; import { useEffect, useState } from 'react'; import { @@ -15,15 +15,15 @@ import { import { JsonValue } from 'type-fest'; import { useDebouncedCallback } from 'use-debounce'; -type WorkflowEditActionFormRecordDeleteProps = { - action: WorkflowRecordDeleteAction; +type WorkflowEditActionFormDeleteRecordProps = { + action: WorkflowDeleteRecordAction; actionOptions: | { readonly: true; } | { readonly?: false; - onActionUpdate: (action: WorkflowRecordDeleteAction) => void; + onActionUpdate: (action: WorkflowDeleteRecordAction) => void; }; }; @@ -32,10 +32,10 @@ type DeleteRecordFormData = { objectRecordId: string; }; -export const WorkflowEditActionFormRecordDelete = ({ +export const WorkflowEditActionFormDeleteRecord = ({ action, actionOptions, -}: WorkflowEditActionFormRecordDeleteProps) => { +}: WorkflowEditActionFormDeleteRecordProps) => { const theme = useTheme(); const { getIcon } = useIcons(); @@ -100,7 +100,6 @@ export const WorkflowEditActionFormRecordDelete = ({ settings: { ...action.settings, input: { - type: 'DELETE', objectName: updatedObjectName, objectRecordId: updatedObjectRecordId ?? '', }, diff --git a/packages/twenty-front/src/modules/workflow/workflow-actions/components/WorkflowEditActionFormRecordUpdate.tsx b/packages/twenty-front/src/modules/workflow/workflow-actions/components/WorkflowEditActionFormUpdateRecord.tsx similarity index 92% rename from packages/twenty-front/src/modules/workflow/workflow-actions/components/WorkflowEditActionFormRecordUpdate.tsx rename to packages/twenty-front/src/modules/workflow/workflow-actions/components/WorkflowEditActionFormUpdateRecord.tsx index ea81e2b9a..71900f069 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-actions/components/WorkflowEditActionFormRecordUpdate.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-actions/components/WorkflowEditActionFormUpdateRecord.tsx @@ -2,7 +2,7 @@ import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilte import { Select, SelectOption } from '@/ui/input/components/Select'; import { WorkflowEditGenericFormBase } from '@/workflow/components/WorkflowEditGenericFormBase'; import { WorkflowSingleRecordPicker } from '@/workflow/components/WorkflowSingleRecordPicker'; -import { WorkflowRecordUpdateAction } from '@/workflow/types/Workflow'; +import { WorkflowUpdateRecordAction } from '@/workflow/types/Workflow'; import { useTheme } from '@emotion/react'; import { useEffect, useState } from 'react'; import { @@ -15,15 +15,15 @@ import { import { JsonValue } from 'type-fest'; import { useDebouncedCallback } from 'use-debounce'; -type WorkflowEditActionFormRecordUpdateProps = { - action: WorkflowRecordUpdateAction; +type WorkflowEditActionFormUpdateRecordProps = { + action: WorkflowUpdateRecordAction; actionOptions: | { readonly: true; } | { readonly?: false; - onActionUpdate: (action: WorkflowRecordUpdateAction) => void; + onActionUpdate: (action: WorkflowUpdateRecordAction) => void; }; }; @@ -33,10 +33,10 @@ type UpdateRecordFormData = { [field: string]: unknown; }; -export const WorkflowEditActionFormRecordUpdate = ({ +export const WorkflowEditActionFormUpdateRecord = ({ action, actionOptions, -}: WorkflowEditActionFormRecordUpdateProps) => { +}: WorkflowEditActionFormUpdateRecordProps) => { const theme = useTheme(); const { getIcon } = useIcons(); @@ -104,7 +104,6 @@ export const WorkflowEditActionFormRecordUpdate = ({ settings: { ...action.settings, input: { - type: 'UPDATE', objectName: updatedObjectName, objectRecordId: updatedObjectRecordId ?? '', objectRecord: updatedOtherFields, diff --git a/packages/twenty-front/src/modules/workflow/workflow-actions/utils/__tests__/isWorkflowRecordCreateAction.test.ts b/packages/twenty-front/src/modules/workflow/workflow-actions/utils/__tests__/isWorkflowRecordCreateAction.test.ts deleted file mode 100644 index 980f7755f..000000000 --- a/packages/twenty-front/src/modules/workflow/workflow-actions/utils/__tests__/isWorkflowRecordCreateAction.test.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { - WorkflowCodeAction, - WorkflowRecordCRUDAction, -} from '@/workflow/types/Workflow'; -import { isWorkflowRecordCreateAction } from '../isWorkflowRecordCreateAction'; - -describe('isWorkflowRecordCreateAction', () => { - it('returns false when providing an action that is not Record Create', () => { - const action: WorkflowCodeAction = { - type: 'CODE', - id: '', - name: '', - settings: { - errorHandlingOptions: { - continueOnFailure: { - value: false, - }, - retryOnFailure: { - value: false, - }, - }, - input: { - serverlessFunctionId: '', - serverlessFunctionVersion: '', - serverlessFunctionInput: {}, - }, - outputSchema: {}, - }, - valid: true, - }; - - expect(isWorkflowRecordCreateAction(action)).toBe(false); - }); - - it('returns false for Record Update', () => { - const action: WorkflowRecordCRUDAction = { - type: 'RECORD_CRUD', - id: '', - name: '', - settings: { - errorHandlingOptions: { - continueOnFailure: { value: false }, - retryOnFailure: { value: false }, - }, - input: { - type: 'UPDATE', - objectName: '', - objectRecord: {}, - objectRecordId: '', - }, - outputSchema: {}, - }, - valid: true, - }; - - expect(isWorkflowRecordCreateAction(action)).toBe(false); - }); - - it('returns true for Record Create', () => { - const action: WorkflowRecordCRUDAction = { - type: 'RECORD_CRUD', - id: '', - name: '', - settings: { - errorHandlingOptions: { - continueOnFailure: { value: false }, - retryOnFailure: { value: false }, - }, - input: { - type: 'CREATE', - objectName: '', - objectRecord: {}, - }, - outputSchema: {}, - }, - valid: true, - }; - - expect(isWorkflowRecordCreateAction(action)).toBe(true); - }); -}); diff --git a/packages/twenty-front/src/modules/workflow/workflow-actions/utils/__tests__/isWorkflowRecordDeleteAction.test.ts b/packages/twenty-front/src/modules/workflow/workflow-actions/utils/__tests__/isWorkflowRecordDeleteAction.test.ts deleted file mode 100644 index 0dc70f3a2..000000000 --- a/packages/twenty-front/src/modules/workflow/workflow-actions/utils/__tests__/isWorkflowRecordDeleteAction.test.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { - WorkflowCodeAction, - WorkflowRecordCRUDAction, -} from '@/workflow/types/Workflow'; -import { isWorkflowRecordDeleteAction } from '../isWorkflowRecordDeleteAction'; - -describe('isWorkflowRecordDeleteAction', () => { - it('returns false when providing an action that is not Record Delete', () => { - const action: WorkflowCodeAction = { - type: 'CODE', - id: '', - name: '', - settings: { - errorHandlingOptions: { - continueOnFailure: { - value: false, - }, - retryOnFailure: { - value: false, - }, - }, - input: { - serverlessFunctionId: '', - serverlessFunctionVersion: '', - serverlessFunctionInput: {}, - }, - outputSchema: {}, - }, - valid: true, - }; - - expect(isWorkflowRecordDeleteAction(action)).toBe(false); - }); - - it('returns false for Record Update', () => { - const action: WorkflowRecordCRUDAction = { - type: 'RECORD_CRUD', - id: '', - name: '', - settings: { - errorHandlingOptions: { - continueOnFailure: { value: false }, - retryOnFailure: { value: false }, - }, - input: { - type: 'UPDATE', - objectName: '', - objectRecord: {}, - objectRecordId: '', - }, - outputSchema: {}, - }, - valid: true, - }; - - expect(isWorkflowRecordDeleteAction(action)).toBe(false); - }); - - it('returns true for Record Delete', () => { - const action: WorkflowRecordCRUDAction = { - type: 'RECORD_CRUD', - id: '', - name: '', - settings: { - errorHandlingOptions: { - continueOnFailure: { value: false }, - retryOnFailure: { value: false }, - }, - input: { - type: 'DELETE', - objectName: '', - objectRecordId: '', - }, - outputSchema: {}, - }, - valid: true, - }; - - expect(isWorkflowRecordDeleteAction(action)).toBe(true); - }); -}); diff --git a/packages/twenty-front/src/modules/workflow/workflow-actions/utils/__tests__/isWorkflowRecordUpdateAction.test.ts b/packages/twenty-front/src/modules/workflow/workflow-actions/utils/__tests__/isWorkflowRecordUpdateAction.test.ts deleted file mode 100644 index 363c7c148..000000000 --- a/packages/twenty-front/src/modules/workflow/workflow-actions/utils/__tests__/isWorkflowRecordUpdateAction.test.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { - WorkflowCodeAction, - WorkflowRecordCRUDAction, -} from '@/workflow/types/Workflow'; -import { isWorkflowRecordUpdateAction } from '../isWorkflowRecordUpdateAction'; - -describe('isWorkflowRecordUpdateAction', () => { - it('returns false when providing an action that is not Record Create', () => { - const action: WorkflowCodeAction = { - type: 'CODE', - id: '', - name: '', - settings: { - errorHandlingOptions: { - continueOnFailure: { - value: false, - }, - retryOnFailure: { - value: false, - }, - }, - input: { - serverlessFunctionId: '', - serverlessFunctionVersion: '', - serverlessFunctionInput: {}, - }, - outputSchema: {}, - }, - valid: true, - }; - - expect(isWorkflowRecordUpdateAction(action)).toBe(false); - }); - - it('returns true for Record Update', () => { - const action: WorkflowRecordCRUDAction = { - type: 'RECORD_CRUD', - id: '', - name: '', - settings: { - errorHandlingOptions: { - continueOnFailure: { value: false }, - retryOnFailure: { value: false }, - }, - input: { - type: 'UPDATE', - objectName: '', - objectRecord: {}, - objectRecordId: '', - }, - outputSchema: {}, - }, - valid: true, - }; - - expect(isWorkflowRecordUpdateAction(action)).toBe(true); - }); - - it('returns false for Record Create', () => { - const action: WorkflowRecordCRUDAction = { - type: 'RECORD_CRUD', - id: '', - name: '', - settings: { - errorHandlingOptions: { - continueOnFailure: { value: false }, - retryOnFailure: { value: false }, - }, - input: { - type: 'CREATE', - objectName: '', - objectRecord: {}, - }, - outputSchema: {}, - }, - valid: true, - }; - - expect(isWorkflowRecordUpdateAction(action)).toBe(false); - }); -}); diff --git a/packages/twenty-front/src/modules/workflow/workflow-actions/utils/isWorkflowRecordCreateAction.ts b/packages/twenty-front/src/modules/workflow/workflow-actions/utils/isWorkflowRecordCreateAction.ts deleted file mode 100644 index 774a2a397..000000000 --- a/packages/twenty-front/src/modules/workflow/workflow-actions/utils/isWorkflowRecordCreateAction.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { - WorkflowAction, - WorkflowRecordCreateAction, -} from '@/workflow/types/Workflow'; - -export const isWorkflowRecordCreateAction = ( - action: WorkflowAction, -): action is WorkflowRecordCreateAction => { - return ( - action.type === 'RECORD_CRUD' && action.settings.input.type === 'CREATE' - ); -}; diff --git a/packages/twenty-front/src/modules/workflow/workflow-actions/utils/isWorkflowRecordDeleteAction.ts b/packages/twenty-front/src/modules/workflow/workflow-actions/utils/isWorkflowRecordDeleteAction.ts deleted file mode 100644 index 4112965eb..000000000 --- a/packages/twenty-front/src/modules/workflow/workflow-actions/utils/isWorkflowRecordDeleteAction.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { - WorkflowAction, - WorkflowRecordDeleteAction, -} from '@/workflow/types/Workflow'; - -export const isWorkflowRecordDeleteAction = ( - action: WorkflowAction, -): action is WorkflowRecordDeleteAction => { - return ( - action.type === 'RECORD_CRUD' && action.settings.input.type === 'DELETE' - ); -}; diff --git a/packages/twenty-front/src/modules/workflow/workflow-actions/utils/isWorkflowRecordUpdateAction.ts b/packages/twenty-front/src/modules/workflow/workflow-actions/utils/isWorkflowRecordUpdateAction.ts deleted file mode 100644 index 732ba25a6..000000000 --- a/packages/twenty-front/src/modules/workflow/workflow-actions/utils/isWorkflowRecordUpdateAction.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { - WorkflowAction, - WorkflowRecordUpdateAction, -} from '@/workflow/types/Workflow'; - -export const isWorkflowRecordUpdateAction = ( - action: WorkflowAction, -): action is WorkflowRecordUpdateAction => { - return ( - action.type === 'RECORD_CRUD' && action.settings.input.type === 'UPDATE' - ); -}; diff --git a/packages/twenty-server/src/modules/workflow/common/workspace-services/workflow-version-step.workspace-service.ts b/packages/twenty-server/src/modules/workflow/common/workspace-services/workflow-version-step.workspace-service.ts index d117580d0..45ce11840 100644 --- a/packages/twenty-server/src/modules/workflow/common/workspace-services/workflow-version-step.workspace-service.ts +++ b/packages/twenty-server/src/modules/workflow/common/workspace-services/workflow-version-step.workspace-service.ts @@ -18,7 +18,6 @@ import { } from 'src/modules/workflow/common/exceptions/workflow-version-step.exception'; import { WorkflowVersionWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity'; import { WorkflowBuilderWorkspaceService } from 'src/modules/workflow/workflow-builder/workflow-builder.workspace-service'; -import { WorkflowRecordCRUDType } from 'src/modules/workflow/workflow-executor/workflow-actions/record-crud/types/workflow-record-crud-action-input.type'; import { BaseWorkflowActionSettings } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action-settings.type'; import { WorkflowAction, @@ -126,7 +125,7 @@ export class WorkflowVersionStepWorkspaceService { }, }; } - case `${WorkflowActionType.RECORD_CRUD}.${WorkflowRecordCRUDType.CREATE}`: { + case WorkflowActionType.CREATE_RECORD: { const activeObjectMetadataItem = await this.objectMetadataRepository.findOne({ where: { workspaceId, isActive: true, isSystem: false }, @@ -135,19 +134,18 @@ export class WorkflowVersionStepWorkspaceService { return { id: newStepId, name: 'Create Record', - type: WorkflowActionType.RECORD_CRUD, + type: WorkflowActionType.CREATE_RECORD, valid: false, settings: { ...BASE_STEP_DEFINITION, input: { - type: WorkflowRecordCRUDType.CREATE, objectName: activeObjectMetadataItem?.nameSingular || '', objectRecord: {}, }, }, }; } - case `${WorkflowActionType.RECORD_CRUD}.${WorkflowRecordCRUDType.UPDATE}`: { + case WorkflowActionType.UPDATE_RECORD: { const activeObjectMetadataItem = await this.objectMetadataRepository.findOne({ where: { workspaceId, isActive: true, isSystem: false }, @@ -156,12 +154,11 @@ export class WorkflowVersionStepWorkspaceService { return { id: newStepId, name: 'Update Record', - type: WorkflowActionType.RECORD_CRUD, + type: WorkflowActionType.UPDATE_RECORD, valid: false, settings: { ...BASE_STEP_DEFINITION, input: { - type: WorkflowRecordCRUDType.UPDATE, objectName: activeObjectMetadataItem?.nameSingular || '', objectRecord: {}, objectRecordId: '', @@ -169,7 +166,7 @@ export class WorkflowVersionStepWorkspaceService { }, }; } - case `${WorkflowActionType.RECORD_CRUD}.${WorkflowRecordCRUDType.DELETE}`: { + case WorkflowActionType.DELETE_RECORD: { const activeObjectMetadataItem = await this.objectMetadataRepository.findOne({ where: { workspaceId, isActive: true, isSystem: false }, @@ -178,12 +175,11 @@ export class WorkflowVersionStepWorkspaceService { return { id: newStepId, name: 'Delete Record', - type: WorkflowActionType.RECORD_CRUD, + type: WorkflowActionType.DELETE_RECORD, valid: false, settings: { ...BASE_STEP_DEFINITION, input: { - type: WorkflowRecordCRUDType.DELETE, objectName: activeObjectMetadataItem?.nameSingular || '', objectRecordId: '', }, diff --git a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-builder.workspace-service.ts b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-builder.workspace-service.ts index fdaec14b0..5d393e93d 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-builder.workspace-service.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-builder.workspace-service.ts @@ -20,7 +20,6 @@ import { } from 'src/modules/workflow/workflow-builder/types/output-schema.type'; import { generateFakeObjectRecord } from 'src/modules/workflow/workflow-builder/utils/generate-fake-object-record'; import { generateFakeObjectRecordEvent } from 'src/modules/workflow/workflow-builder/utils/generate-fake-object-record-event'; -import { WorkflowRecordCRUDType } from 'src/modules/workflow/workflow-executor/workflow-actions/record-crud/types/workflow-record-crud-action-input.type'; import { WorkflowAction, WorkflowActionType, @@ -85,10 +84,17 @@ export class WorkflowBuilderWorkspaceService { codeIntrospectionService: this.codeIntrospectionService, }); } - case WorkflowActionType.RECORD_CRUD: - return this.computeRecordCrudOutputSchema({ + case WorkflowActionType.CREATE_RECORD: + case WorkflowActionType.UPDATE_RECORD: + case WorkflowActionType.DELETE_RECORD: + return this.computeRecordOutputSchema({ + objectType: step.settings.input.objectName, + workspaceId, + objectMetadataRepository: this.objectMetadataRepository, + }); + case WorkflowActionType.FIND_RECORDS: + return this.computeFindRecordsOutputSchema({ objectType: step.settings.input.objectName, - operationType: step.settings.input.type, workspaceId, objectMetadataRepository: this.objectMetadataRepository, }); @@ -130,14 +136,12 @@ export class WorkflowBuilderWorkspaceService { ); } - private async computeRecordCrudOutputSchema({ + private async computeFindRecordsOutputSchema({ objectType, - operationType, workspaceId, objectMetadataRepository, }: { objectType: string; - operationType: string; workspaceId: string; objectMetadataRepository: Repository; }): Promise { @@ -147,24 +151,20 @@ export class WorkflowBuilderWorkspaceService { objectMetadataRepository, }); - if (operationType === WorkflowRecordCRUDType.READ) { - return { - first: { - isLeaf: false, - icon: 'IconAlpha', - value: recordOutputSchema, - }, - last: { isLeaf: false, icon: 'IconOmega', value: recordOutputSchema }, - totalCount: { - isLeaf: true, - icon: 'IconSum', - type: 'number', - value: generateFakeValue('number'), - }, - }; - } - - return recordOutputSchema; + return { + first: { + isLeaf: false, + icon: 'IconAlpha', + value: recordOutputSchema, + }, + last: { isLeaf: false, icon: 'IconOmega', value: recordOutputSchema }, + totalCount: { + isLeaf: true, + icon: 'IconSum', + type: 'number', + value: generateFakeValue('number'), + }, + }; } private async computeRecordOutputSchema({ diff --git a/packages/twenty-server/src/modules/workflow/workflow-executor/factories/workflow-action.factory.ts b/packages/twenty-server/src/modules/workflow/workflow-executor/factories/workflow-action.factory.ts index c3592568a..5b98cd3a5 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-executor/factories/workflow-action.factory.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-executor/factories/workflow-action.factory.ts @@ -8,7 +8,10 @@ import { } from 'src/modules/workflow/workflow-executor/exceptions/workflow-step-executor.exception'; import { CodeWorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/code/code.workflow-action'; import { SendEmailWorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/mail-sender/send-email.workflow-action'; -import { RecordCRUDWorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/record-crud/record-crud.workflow-action'; +import { CreateRecordWorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/record-crud/create-record.workflow-action'; +import { DeleteRecordWorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/record-crud/delete-record.workflow-action'; +import { FindRecordsWorflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/record-crud/find-records.workflow-action'; +import { UpdateRecordWorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/record-crud/update-record.workflow-action'; import { WorkflowActionType } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type'; @Injectable() @@ -16,7 +19,10 @@ export class WorkflowActionFactory { constructor( private readonly codeWorkflowAction: CodeWorkflowAction, private readonly sendEmailWorkflowAction: SendEmailWorkflowAction, - private readonly recordCRUDWorkflowAction: RecordCRUDWorkflowAction, + private readonly createRecordWorkflowAction: CreateRecordWorkflowAction, + private readonly updateRecordWorkflowAction: UpdateRecordWorkflowAction, + private readonly deleteRecordWorkflowAction: DeleteRecordWorkflowAction, + private readonly findRecordsWorflowAction: FindRecordsWorflowAction, ) {} get(stepType: WorkflowActionType): WorkflowAction { @@ -25,8 +31,14 @@ export class WorkflowActionFactory { return this.codeWorkflowAction; case WorkflowActionType.SEND_EMAIL: return this.sendEmailWorkflowAction; - case WorkflowActionType.RECORD_CRUD: - return this.recordCRUDWorkflowAction; + case WorkflowActionType.CREATE_RECORD: + return this.createRecordWorkflowAction; + case WorkflowActionType.UPDATE_RECORD: + return this.updateRecordWorkflowAction; + case WorkflowActionType.DELETE_RECORD: + return this.deleteRecordWorkflowAction; + case WorkflowActionType.FIND_RECORDS: + return this.findRecordsWorflowAction; default: throw new WorkflowStepExecutorException( `Workflow step executor not found for step type '${stepType}'`, diff --git a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/create-record.workflow-action.ts b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/create-record.workflow-action.ts new file mode 100644 index 000000000..f2da2ba15 --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/create-record.workflow-action.ts @@ -0,0 +1,30 @@ +import { Injectable } from '@nestjs/common'; + +import { WorkflowAction } from 'src/modules/workflow/workflow-executor/interfaces/workflow-action.interface'; + +import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; +import { WorkflowCreateRecordActionInput } from 'src/modules/workflow/workflow-executor/workflow-actions/record-crud/types/workflow-record-crud-action-input.type'; +import { WorkflowActionResult } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action-result.type'; + +@Injectable() +export class CreateRecordWorkflowAction implements WorkflowAction { + constructor(private readonly twentyORMManager: TwentyORMManager) {} + + async execute( + workflowActionInput: WorkflowCreateRecordActionInput, + ): Promise { + const repository = await this.twentyORMManager.getRepository( + workflowActionInput.objectName, + ); + + const objectRecord = await repository.create( + workflowActionInput.objectRecord, + ); + + await repository.save(objectRecord); + + return { + result: objectRecord, + }; + } +} diff --git a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/delete-record.workflow-action.ts b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/delete-record.workflow-action.ts new file mode 100644 index 000000000..ecfa32955 --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/delete-record.workflow-action.ts @@ -0,0 +1,45 @@ +import { Injectable } from '@nestjs/common'; + +import { WorkflowAction } from 'src/modules/workflow/workflow-executor/interfaces/workflow-action.interface'; + +import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; +import { + RecordCRUDActionException, + RecordCRUDActionExceptionCode, +} from 'src/modules/workflow/workflow-executor/workflow-actions/record-crud/exceptions/record-crud-action.exception'; +import { WorkflowDeleteRecordActionInput } from 'src/modules/workflow/workflow-executor/workflow-actions/record-crud/types/workflow-record-crud-action-input.type'; +import { WorkflowActionResult } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action-result.type'; + +@Injectable() +export class DeleteRecordWorkflowAction implements WorkflowAction { + constructor(private readonly twentyORMManager: TwentyORMManager) {} + + async execute( + workflowActionInput: WorkflowDeleteRecordActionInput, + ): Promise { + const repository = await this.twentyORMManager.getRepository( + workflowActionInput.objectName, + ); + + const objectRecord = await repository.findOne({ + where: { + id: workflowActionInput.objectRecordId, + }, + }); + + if (!objectRecord) { + throw new RecordCRUDActionException( + `Failed to delete: Record ${workflowActionInput.objectName} with id ${workflowActionInput.objectRecordId} not found`, + RecordCRUDActionExceptionCode.RECORD_NOT_FOUND, + ); + } + + await repository.update(workflowActionInput.objectRecordId, { + deletedAt: new Date(), + }); + + return { + result: objectRecord, + }; + } +} diff --git a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/record-crud.workflow-action.ts b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/find-records.workflow-action.ts similarity index 64% rename from packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/record-crud.workflow-action.ts rename to packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/find-records.workflow-action.ts index 3fc725b7b..007ead779 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/record-crud.workflow-action.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/find-records.workflow-action.ts @@ -24,18 +24,11 @@ import { RecordCRUDActionException, RecordCRUDActionExceptionCode, } from 'src/modules/workflow/workflow-executor/workflow-actions/record-crud/exceptions/record-crud-action.exception'; -import { - WorkflowCreateRecordActionInput, - WorkflowDeleteRecordActionInput, - WorkflowReadRecordActionInput, - WorkflowRecordCRUDActionInput, - WorkflowRecordCRUDType, - WorkflowUpdateRecordActionInput, -} from 'src/modules/workflow/workflow-executor/workflow-actions/record-crud/types/workflow-record-crud-action-input.type'; +import { WorkflowFindRecordsActionInput } from 'src/modules/workflow/workflow-executor/workflow-actions/record-crud/types/workflow-record-crud-action-input.type'; import { WorkflowActionResult } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action-result.type'; @Injectable() -export class RecordCRUDWorkflowAction implements WorkflowAction { +export class FindRecordsWorflowAction implements WorkflowAction { constructor( private readonly twentyORMManager: TwentyORMManager, private readonly workspaceCacheStorageService: WorkspaceCacheStorageService, @@ -43,106 +36,7 @@ export class RecordCRUDWorkflowAction implements WorkflowAction { ) {} async execute( - workflowActionInput: WorkflowRecordCRUDActionInput, - ): Promise { - switch (workflowActionInput.type) { - case WorkflowRecordCRUDType.CREATE: - return this.createRecord(workflowActionInput); - case WorkflowRecordCRUDType.DELETE: - return this.deleteRecord(workflowActionInput); - case WorkflowRecordCRUDType.UPDATE: - return this.updateRecord(workflowActionInput); - case WorkflowRecordCRUDType.READ: - return this.findRecords(workflowActionInput); - default: - throw new RecordCRUDActionException( - `Unknown record operation type`, - RecordCRUDActionExceptionCode.INVALID_REQUEST, - ); - } - } - - private async createRecord( - workflowActionInput: WorkflowCreateRecordActionInput, - ): Promise { - const repository = await this.twentyORMManager.getRepository( - workflowActionInput.objectName, - ); - - const objectRecord = await repository.create( - workflowActionInput.objectRecord, - ); - - await repository.save(objectRecord); - - return { - result: objectRecord, - }; - } - - private async updateRecord( - workflowActionInput: WorkflowUpdateRecordActionInput, - ): Promise { - const repository = await this.twentyORMManager.getRepository( - workflowActionInput.objectName, - ); - - const objectRecord = await repository.findOne({ - where: { - id: workflowActionInput.objectRecordId, - }, - }); - - if (!objectRecord) { - throw new RecordCRUDActionException( - `Failed to update: Record ${workflowActionInput.objectName} with id ${workflowActionInput.objectRecordId} not found`, - RecordCRUDActionExceptionCode.RECORD_NOT_FOUND, - ); - } - - await repository.update(workflowActionInput.objectRecordId, { - ...workflowActionInput.objectRecord, - }); - - return { - result: { - ...objectRecord, - ...workflowActionInput.objectRecord, - }, - }; - } - - private async deleteRecord( - workflowActionInput: WorkflowDeleteRecordActionInput, - ): Promise { - const repository = await this.twentyORMManager.getRepository( - workflowActionInput.objectName, - ); - - const objectRecord = await repository.findOne({ - where: { - id: workflowActionInput.objectRecordId, - }, - }); - - if (!objectRecord) { - throw new RecordCRUDActionException( - `Failed to delete: Record ${workflowActionInput.objectName} with id ${workflowActionInput.objectRecordId} not found`, - RecordCRUDActionExceptionCode.RECORD_NOT_FOUND, - ); - } - - await repository.update(workflowActionInput.objectRecordId, { - deletedAt: new Date(), - }); - - return { - result: objectRecord, - }; - } - - private async findRecords( - workflowActionInput: WorkflowReadRecordActionInput, + workflowActionInput: WorkflowFindRecordsActionInput, ): Promise { const repository = await this.twentyORMManager.getRepository( workflowActionInput.objectName, @@ -221,7 +115,7 @@ export class RecordCRUDWorkflowAction implements WorkflowAction { } private async getObjectRecords( - workflowActionInput: WorkflowReadRecordActionInput, + workflowActionInput: WorkflowFindRecordsActionInput, objectMetadataItemWithFieldsMaps: ObjectMetadataItemWithFieldMaps, objectMetadataMaps: ObjectMetadataMaps, repository: WorkspaceRepository, @@ -261,7 +155,7 @@ export class RecordCRUDWorkflowAction implements WorkflowAction { } private async getTotalCount( - workflowActionInput: WorkflowReadRecordActionInput, + workflowActionInput: WorkflowFindRecordsActionInput, repository: WorkspaceRepository, graphqlQueryParser: GraphqlQueryParser, ) { diff --git a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/record-crud-action.module.ts b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/record-crud-action.module.ts index 03a1a693c..fb3e6d78c 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/record-crud-action.module.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/record-crud-action.module.ts @@ -2,11 +2,25 @@ import { Module } from '@nestjs/common'; import { ScopedWorkspaceContextFactory } from 'src/engine/twenty-orm/factories/scoped-workspace-context.factory'; import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module'; -import { RecordCRUDWorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/record-crud/record-crud.workflow-action'; +import { CreateRecordWorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/record-crud/create-record.workflow-action'; +import { DeleteRecordWorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/record-crud/delete-record.workflow-action'; +import { FindRecordsWorflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/record-crud/find-records.workflow-action'; +import { UpdateRecordWorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/record-crud/update-record.workflow-action'; @Module({ imports: [WorkspaceCacheStorageModule], - providers: [RecordCRUDWorkflowAction, ScopedWorkspaceContextFactory], - exports: [RecordCRUDWorkflowAction], + providers: [ + ScopedWorkspaceContextFactory, + CreateRecordWorkflowAction, + UpdateRecordWorkflowAction, + DeleteRecordWorkflowAction, + FindRecordsWorflowAction, + ], + exports: [ + CreateRecordWorkflowAction, + UpdateRecordWorkflowAction, + DeleteRecordWorkflowAction, + FindRecordsWorflowAction, + ], }) export class RecordCRUDActionModule {} diff --git a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/types/workflow-record-crud-action-input.type.ts b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/types/workflow-record-crud-action-input.type.ts index 357ac5603..cfb58e9b3 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/types/workflow-record-crud-action-input.type.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/types/workflow-record-crud-action-input.type.ts @@ -5,42 +5,25 @@ import { type ObjectRecord = Record; -export enum WorkflowRecordCRUDType { - CREATE = 'CREATE', - UPDATE = 'UPDATE', - DELETE = 'DELETE', - READ = 'READ', -} - export type WorkflowCreateRecordActionInput = { - type: WorkflowRecordCRUDType.CREATE; objectName: string; objectRecord: ObjectRecord; }; export type WorkflowUpdateRecordActionInput = { - type: WorkflowRecordCRUDType.UPDATE; objectName: string; objectRecord: ObjectRecord; objectRecordId: string; }; export type WorkflowDeleteRecordActionInput = { - type: WorkflowRecordCRUDType.DELETE; objectName: string; objectRecordId: string; }; -export type WorkflowReadRecordActionInput = { - type: WorkflowRecordCRUDType.READ; +export type WorkflowFindRecordsActionInput = { objectName: string; filter?: Partial; orderBy?: Partial; limit?: number; }; - -export type WorkflowRecordCRUDActionInput = - | WorkflowCreateRecordActionInput - | WorkflowUpdateRecordActionInput - | WorkflowDeleteRecordActionInput - | WorkflowReadRecordActionInput; diff --git a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/types/workflow-record-crud-action-settings.type.ts b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/types/workflow-record-crud-action-settings.type.ts index cfda46c08..db2d09e1f 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/types/workflow-record-crud-action-settings.type.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/types/workflow-record-crud-action-settings.type.ts @@ -1,6 +1,23 @@ -import { WorkflowRecordCRUDActionInput } from 'src/modules/workflow/workflow-executor/workflow-actions/record-crud/types/workflow-record-crud-action-input.type'; +import { + WorkflowCreateRecordActionInput, + WorkflowDeleteRecordActionInput, + WorkflowFindRecordsActionInput, + WorkflowUpdateRecordActionInput, +} from 'src/modules/workflow/workflow-executor/workflow-actions/record-crud/types/workflow-record-crud-action-input.type'; import { BaseWorkflowActionSettings } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action-settings.type'; -export type WorkflowRecordCRUDActionSettings = BaseWorkflowActionSettings & { - input: WorkflowRecordCRUDActionInput; +export type WorkflowCreateRecordActionSettings = BaseWorkflowActionSettings & { + input: WorkflowCreateRecordActionInput; +}; + +export type WorkflowUpdateRecordActionSettings = BaseWorkflowActionSettings & { + input: WorkflowUpdateRecordActionInput; +}; + +export type WorkflowDeleteRecordActionSettings = BaseWorkflowActionSettings & { + input: WorkflowDeleteRecordActionInput; +}; + +export type WorkflowFindRecordsActionSettings = BaseWorkflowActionSettings & { + input: WorkflowFindRecordsActionInput; }; diff --git a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/update-record.workflow-action.ts b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/update-record.workflow-action.ts new file mode 100644 index 000000000..0974d6841 --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/update-record.workflow-action.ts @@ -0,0 +1,48 @@ +import { Injectable } from '@nestjs/common'; + +import { WorkflowAction } from 'src/modules/workflow/workflow-executor/interfaces/workflow-action.interface'; + +import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; +import { + RecordCRUDActionException, + RecordCRUDActionExceptionCode, +} from 'src/modules/workflow/workflow-executor/workflow-actions/record-crud/exceptions/record-crud-action.exception'; +import { WorkflowUpdateRecordActionInput } from 'src/modules/workflow/workflow-executor/workflow-actions/record-crud/types/workflow-record-crud-action-input.type'; +import { WorkflowActionResult } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action-result.type'; + +@Injectable() +export class UpdateRecordWorkflowAction implements WorkflowAction { + constructor(private readonly twentyORMManager: TwentyORMManager) {} + + async execute( + workflowActionInput: WorkflowUpdateRecordActionInput, + ): Promise { + const repository = await this.twentyORMManager.getRepository( + workflowActionInput.objectName, + ); + + const objectRecord = await repository.findOne({ + where: { + id: workflowActionInput.objectRecordId, + }, + }); + + if (!objectRecord) { + throw new RecordCRUDActionException( + `Failed to update: Record ${workflowActionInput.objectName} with id ${workflowActionInput.objectRecordId} not found`, + RecordCRUDActionExceptionCode.RECORD_NOT_FOUND, + ); + } + + await repository.update(workflowActionInput.objectRecordId, { + ...workflowActionInput.objectRecord, + }); + + return { + result: { + ...objectRecord, + ...workflowActionInput.objectRecord, + }, + }; + } +} diff --git a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action-settings.type.ts b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action-settings.type.ts index f5d78e33e..2dfdf84c4 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action-settings.type.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action-settings.type.ts @@ -1,7 +1,12 @@ +import { OutputSchema } from 'src/modules/workflow/workflow-builder/types/output-schema.type'; import { WorkflowCodeActionSettings } from 'src/modules/workflow/workflow-executor/workflow-actions/code/types/workflow-code-action-settings.type'; import { WorkflowSendEmailActionSettings } from 'src/modules/workflow/workflow-executor/workflow-actions/mail-sender/types/workflow-send-email-action-settings.type'; -import { WorkflowRecordCRUDActionSettings } from 'src/modules/workflow/workflow-executor/workflow-actions/record-crud/types/workflow-record-crud-action-settings.type'; -import { OutputSchema } from 'src/modules/workflow/workflow-builder/types/output-schema.type'; +import { + WorkflowCreateRecordActionSettings, + WorkflowDeleteRecordActionSettings, + WorkflowFindRecordsActionSettings, + WorkflowUpdateRecordActionSettings, +} from 'src/modules/workflow/workflow-executor/workflow-actions/record-crud/types/workflow-record-crud-action-settings.type'; export type BaseWorkflowActionSettings = { input: object; @@ -19,4 +24,7 @@ export type BaseWorkflowActionSettings = { export type WorkflowActionSettings = | WorkflowSendEmailActionSettings | WorkflowCodeActionSettings - | WorkflowRecordCRUDActionSettings; + | WorkflowCreateRecordActionSettings + | WorkflowUpdateRecordActionSettings + | WorkflowDeleteRecordActionSettings + | WorkflowFindRecordsActionSettings; diff --git a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type.ts b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type.ts index 1ce3baefa..0f18596e5 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type.ts @@ -1,12 +1,20 @@ import { WorkflowCodeActionSettings } from 'src/modules/workflow/workflow-executor/workflow-actions/code/types/workflow-code-action-settings.type'; import { WorkflowSendEmailActionSettings } from 'src/modules/workflow/workflow-executor/workflow-actions/mail-sender/types/workflow-send-email-action-settings.type'; -import { WorkflowRecordCRUDActionSettings } from 'src/modules/workflow/workflow-executor/workflow-actions/record-crud/types/workflow-record-crud-action-settings.type'; +import { + WorkflowCreateRecordActionSettings, + WorkflowDeleteRecordActionSettings, + WorkflowFindRecordsActionSettings, + WorkflowUpdateRecordActionSettings, +} from 'src/modules/workflow/workflow-executor/workflow-actions/record-crud/types/workflow-record-crud-action-settings.type'; import { WorkflowActionSettings } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action-settings.type'; export enum WorkflowActionType { CODE = 'CODE', SEND_EMAIL = 'SEND_EMAIL', - RECORD_CRUD = 'RECORD_CRUD', + CREATE_RECORD = 'CREATE_RECORD', + UPDATE_RECORD = 'UPDATE_RECORD', + DELETE_RECORD = 'DELETE_RECORD', + FIND_RECORDS = 'FIND_RECORDS', } type BaseWorkflowAction = { @@ -27,12 +35,30 @@ export type WorkflowSendEmailAction = BaseWorkflowAction & { settings: WorkflowSendEmailActionSettings; }; -export type WorkflowRecordCRUDAction = BaseWorkflowAction & { - type: WorkflowActionType.RECORD_CRUD; - settings: WorkflowRecordCRUDActionSettings; +export type WorkflowCreateRecordAction = BaseWorkflowAction & { + type: WorkflowActionType.CREATE_RECORD; + settings: WorkflowCreateRecordActionSettings; +}; + +export type WorkflowUpdateRecordAction = BaseWorkflowAction & { + type: WorkflowActionType.UPDATE_RECORD; + settings: WorkflowUpdateRecordActionSettings; +}; + +export type WorkflowDeleteRecordAction = BaseWorkflowAction & { + type: WorkflowActionType.DELETE_RECORD; + settings: WorkflowDeleteRecordActionSettings; +}; + +export type WorkflowFindRecordsAction = BaseWorkflowAction & { + type: WorkflowActionType.FIND_RECORDS; + settings: WorkflowFindRecordsActionSettings; }; export type WorkflowAction = | WorkflowCodeAction | WorkflowSendEmailAction - | WorkflowRecordCRUDAction; + | WorkflowCreateRecordAction + | WorkflowUpdateRecordAction + | WorkflowDeleteRecordAction + | WorkflowFindRecordsAction;