Add Manual Triggers (#8024)

In this PR:

- Add support for manual triggers in the backend
- Add a right drawer to let users select the type of trigger they want
- Create a specific right drawer for database event triggers
- Create a right drawer for manual triggers; let the user select where
the manual trigger should be made available
- Create a default trigger as soon as the user selects the type of
trigger they want. It prevents the user to see empty selects for record
type and event type. By default, the database event trigger will be set
to "company.created". It should be visible enough for users to
understand what happens and choose another record type or event type.



https://github.com/user-attachments/assets/29a21985-1823-4890-9eb3-e4f876459c7a
This commit is contained in:
Baptiste Devessier
2024-10-25 14:24:56 +02:00
committed by GitHub
parent bf2ba25a6e
commit 0144553667
31 changed files with 609 additions and 205 deletions

View File

@ -55,6 +55,7 @@ describe('getWorkflowVersionDiagram', () => {
data: {
label: 'Company is Created',
nodeType: 'trigger',
triggerType: 'DATABASE_EVENT',
},
id: 'trigger',
position: { x: 0, y: 0 },

View File

@ -5,6 +5,7 @@ import {
WorkflowDiagramEdge,
WorkflowDiagramNode,
} from '@/workflow/types/WorkflowDiagram';
import { assertUnreachable } from '@/workflow/utils/assertUnreachable';
import { splitWorkflowTriggerEventName } from '@/workflow/utils/splitWorkflowTriggerEventName';
import { MarkerType } from '@xyflow/react';
import { isDefined } from 'twenty-ui';
@ -59,15 +60,37 @@ export const generateWorkflowDiagram = ({
const triggerNodeId = TRIGGER_STEP_ID;
if (isDefined(trigger)) {
const triggerEvent = splitWorkflowTriggerEventName(
trigger.settings.eventName,
);
let triggerLabel: string;
switch (trigger.type) {
case 'MANUAL': {
triggerLabel = 'Manual Trigger';
break;
}
case 'DATABASE_EVENT': {
const triggerEvent = splitWorkflowTriggerEventName(
trigger.settings.eventName,
);
triggerLabel = `${capitalize(triggerEvent.objectType)} is ${capitalize(triggerEvent.event)}`;
break;
}
default: {
return assertUnreachable(
trigger,
`Expected the trigger "${JSON.stringify(trigger)}" to be supported.`,
);
}
}
nodes.push({
id: triggerNodeId,
data: {
nodeType: 'trigger',
label: `${capitalize(triggerEvent.objectType)} is ${capitalize(triggerEvent.event)}`,
triggerType: trigger.type,
label: triggerLabel,
},
position: {
x: 0,

View File

@ -0,0 +1,29 @@
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import {
WorkflowManualTriggerAvailability,
WorkflowManualTriggerSettings,
} from '@/workflow/types/Workflow';
import { assertUnreachable } from '@/workflow/utils/assertUnreachable';
export const getManualTriggerDefaultSettings = ({
availability,
activeObjectMetadataItems,
}: {
availability: WorkflowManualTriggerAvailability;
activeObjectMetadataItems: ObjectMetadataItem[];
}): WorkflowManualTriggerSettings => {
switch (availability) {
case 'EVERYWHERE': {
return {
objectType: undefined,
};
}
case 'WHEN_RECORD_SELECTED': {
return {
objectType: activeObjectMetadataItems[0].nameSingular,
};
}
}
return assertUnreachable(availability);
};

View File

@ -1,4 +1,5 @@
import { WorkflowStep, WorkflowStepType } from '@/workflow/types/Workflow';
import { assertUnreachable } from '@/workflow/utils/assertUnreachable';
import { v4 } from 'uuid';
export const getStepDefaultDefinition = (
@ -53,7 +54,7 @@ export const getStepDefaultDefinition = (
};
}
default: {
throw new Error(`Unknown type: ${type}`);
return assertUnreachable(type, `Unknown type: ${type}`);
}
}
};

View File

@ -0,0 +1,45 @@
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { OBJECT_EVENT_TRIGGERS } from '@/workflow/constants/ObjectEventTriggers';
import {
WorkflowTrigger,
WorkflowTriggerType,
} from '@/workflow/types/Workflow';
import { assertUnreachable } from '@/workflow/utils/assertUnreachable';
import { getManualTriggerDefaultSettings } from '@/workflow/utils/getManualTriggerDefaultSettings';
export const getTriggerDefaultDefinition = ({
type,
activeObjectMetadataItems,
}: {
type: WorkflowTriggerType;
activeObjectMetadataItems: ObjectMetadataItem[];
}): WorkflowTrigger => {
if (activeObjectMetadataItems.length === 0) {
throw new Error(
'This function need to receive at least one object metadata item to run.',
);
}
switch (type) {
case 'DATABASE_EVENT': {
return {
type,
settings: {
eventName: `${activeObjectMetadataItems[0].nameSingular}.${OBJECT_EVENT_TRIGGERS[0].value}`,
},
};
}
case 'MANUAL': {
return {
type,
settings: getManualTriggerDefaultSettings({
availability: 'WHEN_RECORD_SELECTED',
activeObjectMetadataItems,
}),
};
}
default: {
return assertUnreachable(type, `Unknown type: ${type}`);
}
}
};