Make workflow step name editable (#8677)

- Use TextInput in header title
- add onTitleChange prop
- rename field name instead of label

To fix :
- padding right on title comes from current TextInput component. It
needs to be refactored


https://github.com/user-attachments/assets/535cd6d3-866b-4a61-9c5d-cdbe7710396a
This commit is contained in:
Thomas Trompette
2024-11-22 16:25:01 +01:00
committed by GitHub
parent 4d8445a34a
commit 5ec6cb0e6f
24 changed files with 217 additions and 157 deletions

View File

@ -19,10 +19,19 @@ type TextInputProps = {
onEscape: (newText: string) => void; onEscape: (newText: string) => void;
onTab?: (newText: string) => void; onTab?: (newText: string) => void;
onShiftTab?: (newText: string) => void; onShiftTab?: (newText: string) => void;
onClickOutside: (event: MouseEvent | TouchEvent, inputValue: string) => void; onClickOutside?: (event: MouseEvent | TouchEvent, inputValue: string) => void;
hotkeyScope: string; hotkeyScope: string;
onChange?: (newText: string) => void; onChange?: (newText: string) => void;
copyButton?: boolean; copyButton?: boolean;
shouldTrim?: boolean;
};
const getValue = (value: string, shouldTrim: boolean) => {
if (shouldTrim) {
return value.trim();
}
return value;
}; };
export const TextInput = ({ export const TextInput = ({
@ -37,6 +46,7 @@ export const TextInput = ({
onClickOutside, onClickOutside,
onChange, onChange,
copyButton = true, copyButton = true,
shouldTrim = true,
}: TextInputProps) => { }: TextInputProps) => {
const [internalText, setInternalText] = useState(value); const [internalText, setInternalText] = useState(value);
@ -44,12 +54,12 @@ export const TextInput = ({
const copyRef = useRef<HTMLDivElement>(null); const copyRef = useRef<HTMLDivElement>(null);
const handleChange = (event: ChangeEvent<HTMLInputElement>) => { const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
setInternalText(event.target.value.trim()); setInternalText(getValue(event.target.value, shouldTrim));
onChange?.(event.target.value.trim()); onChange?.(getValue(event.target.value, shouldTrim));
}; };
useEffect(() => { useEffect(() => {
setInternalText(value.trim()); setInternalText(getValue(value, shouldTrim));
}, [value]); }, [value, shouldTrim]);
useRegisterInputEvents({ useRegisterInputEvents({
inputRef: wrapperRef, inputRef: wrapperRef,

View File

@ -39,7 +39,7 @@ export const RightDrawerWorkflowSelectTriggerTypeContent = ({
<MenuItem <MenuItem
key={action.type} key={action.type}
LeftIcon={action.icon} LeftIcon={action.icon}
text={action.label} text={action.name}
onClick={async () => { onClick={async () => {
await updateTrigger( await updateTrigger(
getTriggerDefaultDefinition({ getTriggerDefaultDefinition({

View File

@ -2,7 +2,7 @@ import { WorkflowDiagramStepNodeData } from '@/workflow/types/WorkflowDiagram';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { Handle, Position } from '@xyflow/react'; import { Handle, Position } from '@xyflow/react';
import React from 'react'; import React from 'react';
import { isDefined } from 'twenty-ui'; import { isDefined, OverflowingTextWithTooltip } from 'twenty-ui';
import { capitalize } from '~/utils/string/capitalize'; import { capitalize } from '~/utils/string/capitalize';
type Variant = 'placeholder'; type Variant = 'placeholder';
@ -68,6 +68,7 @@ const StyledStepNodeLabel = styled.div<{ variant?: Variant }>`
variant === 'placeholder' variant === 'placeholder'
? theme.font.color.extraLight ? theme.font.color.extraLight
: theme.font.color.primary}; : theme.font.color.primary};
max-width: 200px;
`; `;
const StyledSourceHandle = styled(Handle)` const StyledSourceHandle = styled(Handle)`
@ -90,13 +91,13 @@ const StyledRightFloatingElementContainer = styled.div`
export const WorkflowDiagramBaseStepNode = ({ export const WorkflowDiagramBaseStepNode = ({
nodeType, nodeType,
label, name,
variant, variant,
Icon, Icon,
RightFloatingElement, RightFloatingElement,
}: { }: {
nodeType: WorkflowDiagramStepNodeData['nodeType']; nodeType: WorkflowDiagramStepNodeData['nodeType'];
label: string; name: string;
variant?: Variant; variant?: Variant;
Icon?: React.ReactNode; Icon?: React.ReactNode;
RightFloatingElement?: React.ReactNode; RightFloatingElement?: React.ReactNode;
@ -113,7 +114,7 @@ export const WorkflowDiagramBaseStepNode = ({
<StyledStepNodeLabel variant={variant}> <StyledStepNodeLabel variant={variant}>
{Icon} {Icon}
{label} <OverflowingTextWithTooltip text={name} />
</StyledStepNodeLabel> </StyledStepNodeLabel>
{isDefined(RightFloatingElement) ? ( {isDefined(RightFloatingElement) ? (

View File

@ -17,7 +17,7 @@ export const WorkflowDiagramEmptyTrigger = () => {
return ( return (
<WorkflowDiagramBaseStepNode <WorkflowDiagramBaseStepNode
label="Add a Trigger" name="Add a Trigger"
nodeType="trigger" nodeType="trigger"
variant="placeholder" variant="placeholder"
Icon={ Icon={

View File

@ -100,8 +100,8 @@ export const WorkflowDiagramStepNodeBase = ({
return ( return (
<WorkflowDiagramBaseStepNode <WorkflowDiagramBaseStepNode
name={data.name}
nodeType={data.nodeType} nodeType={data.nodeType}
label={data.label}
Icon={renderStepIcon()} Icon={renderStepIcon()}
RightFloatingElement={RightFloatingElement} RightFloatingElement={RightFloatingElement}
/> />

View File

@ -119,15 +119,27 @@ export const WorkflowEditActionFormRecordCreate = ({
}; };
}, [saveAction]); }, [saveAction]);
const headerTitle = isDefined(action.name) ? action.name : `Create Record`;
return ( return (
<WorkflowEditGenericFormBase <WorkflowEditGenericFormBase
onTitleChange={(newName: string) => {
if (actionOptions.readonly === true) {
return;
}
actionOptions.onActionUpdate({
...action,
name: newName,
});
}}
HeaderIcon={ HeaderIcon={
<IconAddressBook <IconAddressBook
color={theme.font.color.tertiary} color={theme.font.color.tertiary}
stroke={theme.icon.stroke.sm} stroke={theme.icon.stroke.sm}
/> />
} }
headerTitle="Record Create" headerTitle={headerTitle}
headerType="Action" headerType="Action"
> >
<Select <Select

View File

@ -166,11 +166,23 @@ export const WorkflowEditActionFormSendEmail = ({
} }
}); });
const headerTitle = isDefined(action.name) ? action.name : 'Send Email';
return ( return (
!loading && ( !loading && (
<WorkflowEditGenericFormBase <WorkflowEditGenericFormBase
onTitleChange={(newName: string) => {
if (actionOptions.readonly === true) {
return;
}
actionOptions.onActionUpdate({
...action,
name: newName,
});
}}
HeaderIcon={<IconMail color={theme.color.blue} />} HeaderIcon={<IconMail color={theme.color.blue} />}
headerTitle="Send Email" headerTitle={headerTitle}
headerType="Email" headerType="Email"
> >
<Controller <Controller

View File

@ -217,10 +217,24 @@ export const WorkflowEditActionFormServerlessFunctionInner = ({
}); });
}; };
const headerTitle = isDefined(action.name)
? action.name
: 'Code - Serverless Function';
return ( return (
<WorkflowEditGenericFormBase <WorkflowEditGenericFormBase
onTitleChange={(newName: string) => {
if (actionOptions.readonly === true) {
return;
}
actionOptions?.onActionUpdate({
...action,
name: newName,
});
}}
HeaderIcon={<IconCode color={theme.color.orange} />} HeaderIcon={<IconCode color={theme.color.orange} />}
headerTitle="Code - Serverless Function" headerTitle={headerTitle}
headerType="Code" headerType="Code"
> >
<Select <Select

View File

@ -1,5 +1,7 @@
import { TextInput } from '@/ui/field/input/components/TextInput';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import React from 'react'; import React from 'react';
import { useDebouncedCallback } from 'use-debounce';
const StyledHeader = styled.div` const StyledHeader = styled.div`
background-color: ${({ theme }) => theme.background.secondary}; background-color: ${({ theme }) => theme.background.secondary};
@ -40,22 +42,36 @@ const StyledContentContainer = styled.div`
`; `;
export const WorkflowEditGenericFormBase = ({ export const WorkflowEditGenericFormBase = ({
onTitleChange,
HeaderIcon, HeaderIcon,
headerTitle, headerTitle,
headerType, headerType,
children, children,
}: { }: {
onTitleChange: (newTitle: string) => void;
HeaderIcon: React.ReactNode; HeaderIcon: React.ReactNode;
headerTitle: string; headerTitle: string;
headerType: string; headerType: string;
children: React.ReactNode; children: React.ReactNode;
}) => { }) => {
const debouncedOnTitleChange = useDebouncedCallback(onTitleChange, 100);
return ( return (
<> <>
<StyledHeader> <StyledHeader>
<StyledHeaderIconContainer>{HeaderIcon}</StyledHeaderIconContainer> <StyledHeaderIconContainer>{HeaderIcon}</StyledHeaderIconContainer>
<StyledHeaderTitle>{headerTitle}</StyledHeaderTitle> <StyledHeaderTitle>
<TextInput
value={headerTitle}
copyButton={false}
hotkeyScope="workflow-step-title"
onEnter={onTitleChange}
onEscape={onTitleChange}
onChange={debouncedOnTitleChange}
shouldTrim={false}
/>
</StyledHeaderTitle>
<StyledHeaderType>{headerType}</StyledHeaderType> <StyledHeaderType>{headerType}</StyledHeaderType>
</StyledHeader> </StyledHeader>

View File

@ -1,50 +1,12 @@
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems'; import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
import { Select, SelectOption } from '@/ui/input/components/Select'; import { Select, SelectOption } from '@/ui/input/components/Select';
import { WorkflowEditGenericFormBase } from '@/workflow/components/WorkflowEditGenericFormBase';
import { OBJECT_EVENT_TRIGGERS } from '@/workflow/constants/ObjectEventTriggers'; import { OBJECT_EVENT_TRIGGERS } from '@/workflow/constants/ObjectEventTriggers';
import { WorkflowDatabaseEventTrigger } from '@/workflow/types/Workflow'; import { WorkflowDatabaseEventTrigger } from '@/workflow/types/Workflow';
import { splitWorkflowTriggerEventName } from '@/workflow/utils/splitWorkflowTriggerEventName'; import { splitWorkflowTriggerEventName } from '@/workflow/utils/splitWorkflowTriggerEventName';
import { useTheme } from '@emotion/react'; import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { IconPlaylistAdd, isDefined } from 'twenty-ui'; import { IconPlaylistAdd, isDefined } from 'twenty-ui';
const StyledTriggerHeader = styled.div`
background-color: ${({ theme }) => theme.background.secondary};
border-bottom: 1px solid ${({ theme }) => theme.border.color.medium};
display: flex;
flex-direction: column;
padding: ${({ theme }) => theme.spacing(6)};
`;
const StyledTriggerHeaderTitle = styled.p`
color: ${({ theme }) => theme.font.color.primary};
font-weight: ${({ theme }) => theme.font.weight.semiBold};
font-size: ${({ theme }) => theme.font.size.xl};
margin: ${({ theme }) => theme.spacing(3)} 0;
`;
const StyledTriggerHeaderType = styled.p`
color: ${({ theme }) => theme.font.color.tertiary};
margin: 0;
`;
const StyledTriggerHeaderIconContainer = styled.div`
align-self: flex-start;
display: flex;
justify-content: center;
align-items: center;
background-color: ${({ theme }) => theme.background.transparent.light};
border-radius: ${({ theme }) => theme.border.radius.xs};
padding: ${({ theme }) => theme.spacing(1)};
`;
const StyledTriggerSettings = styled.div`
padding: ${({ theme }) => theme.spacing(6)};
display: flex;
flex-direction: column;
row-gap: ${({ theme }) => theme.spacing(4)};
`;
type WorkflowEditTriggerDatabaseEventFormProps = { type WorkflowEditTriggerDatabaseEventFormProps = {
trigger: WorkflowDatabaseEventTrigger; trigger: WorkflowDatabaseEventTrigger;
triggerOptions: triggerOptions:
@ -87,92 +49,98 @@ export const WorkflowEditTriggerDatabaseEventForm = ({
) )
: undefined; : undefined;
const headerTitle = isDefined(trigger.name)
? trigger.name
: isDefined(recordTypeMetadata) && isDefined(selectedEvent)
? `When a ${recordTypeMetadata.labelSingular} is ${selectedEvent.label}`
: '-';
const headerType = isDefined(selectedEvent)
? `Trigger · Record is ${selectedEvent.label}`
: '-';
return ( return (
<> <WorkflowEditGenericFormBase
<StyledTriggerHeader> onTitleChange={(newName: string) => {
<StyledTriggerHeaderIconContainer> if (triggerOptions.readonly === true) {
<IconPlaylistAdd color={theme.font.color.tertiary} /> return;
</StyledTriggerHeaderIconContainer> }
<StyledTriggerHeaderTitle> triggerOptions.onTriggerUpdate({
{isDefined(recordTypeMetadata) && isDefined(selectedEvent) ...trigger,
? `When a ${recordTypeMetadata.labelSingular} is ${selectedEvent.label}` name: newName,
: '-'} });
</StyledTriggerHeaderTitle> }}
HeaderIcon={<IconPlaylistAdd color={theme.font.color.tertiary} />}
headerTitle={headerTitle}
headerType={headerType}
>
<Select
dropdownId="workflow-edit-trigger-record-type"
label="Record Type"
fullWidth
disabled={triggerOptions.readonly}
value={triggerEvent?.objectType}
emptyOption={{ label: 'Select an option', value: '' }}
options={availableMetadata}
onChange={(updatedRecordType) => {
if (triggerOptions.readonly === true) {
return;
}
<StyledTriggerHeaderType> triggerOptions.onTriggerUpdate(
{isDefined(selectedEvent) isDefined(trigger) && isDefined(triggerEvent)
? `Trigger · Record is ${selectedEvent.label}` ? {
: '-'} ...trigger,
</StyledTriggerHeaderType> settings: {
</StyledTriggerHeader> ...trigger.settings,
eventName: `${updatedRecordType}.${triggerEvent.event}`,
<StyledTriggerSettings>
<Select
dropdownId="workflow-edit-trigger-record-type"
label="Record Type"
fullWidth
disabled={triggerOptions.readonly}
value={triggerEvent?.objectType}
emptyOption={{ label: 'Select an option', value: '' }}
options={availableMetadata}
onChange={(updatedRecordType) => {
if (triggerOptions.readonly === true) {
return;
}
triggerOptions.onTriggerUpdate(
isDefined(trigger) && isDefined(triggerEvent)
? {
...trigger,
settings: {
...trigger.settings,
eventName: `${updatedRecordType}.${triggerEvent.event}`,
},
}
: {
type: 'DATABASE_EVENT',
settings: {
eventName: `${updatedRecordType}.${OBJECT_EVENT_TRIGGERS[0].value}`,
outputSchema: {},
},
}, },
); }
}} : {
/> name: headerTitle,
<Select type: 'DATABASE_EVENT',
dropdownId="workflow-edit-trigger-event-type" settings: {
label="Event type" eventName: `${updatedRecordType}.${OBJECT_EVENT_TRIGGERS[0].value}`,
fullWidth outputSchema: {},
value={triggerEvent?.event}
emptyOption={{ label: 'Select an option', value: '' }}
options={OBJECT_EVENT_TRIGGERS}
disabled={triggerOptions.readonly}
onChange={(updatedEvent) => {
if (triggerOptions.readonly === true) {
return;
}
triggerOptions.onTriggerUpdate(
isDefined(trigger) && isDefined(triggerEvent)
? {
...trigger,
settings: {
...trigger.settings,
eventName: `${triggerEvent.objectType}.${updatedEvent}`,
},
}
: {
type: 'DATABASE_EVENT',
settings: {
eventName: `${availableMetadata[0].value}.${updatedEvent}`,
outputSchema: {},
},
}, },
); },
}} );
/> }}
</StyledTriggerSettings> />
</> <Select
dropdownId="workflow-edit-trigger-event-type"
label="Event type"
fullWidth
value={triggerEvent?.event}
emptyOption={{ label: 'Select an option', value: '' }}
options={OBJECT_EVENT_TRIGGERS}
disabled={triggerOptions.readonly}
onChange={(updatedEvent) => {
if (triggerOptions.readonly === true) {
return;
}
triggerOptions.onTriggerUpdate(
isDefined(trigger) && isDefined(triggerEvent)
? {
...trigger,
settings: {
...trigger.settings,
eventName: `${triggerEvent.objectType}.${updatedEvent}`,
},
}
: {
name: headerTitle,
type: 'DATABASE_EVENT',
settings: {
eventName: `${availableMetadata[0].value}.${updatedEvent}`,
outputSchema: {},
},
},
);
}}
/>
</WorkflowEditGenericFormBase>
); );
}; };

View File

@ -44,10 +44,22 @@ export const WorkflowEditTriggerManualForm = ({
? 'WHEN_RECORD_SELECTED' ? 'WHEN_RECORD_SELECTED'
: 'EVERYWHERE'; : 'EVERYWHERE';
const headerTitle = isDefined(trigger.name) ? trigger.name : 'Manual Trigger';
return ( return (
<WorkflowEditGenericFormBase <WorkflowEditGenericFormBase
onTitleChange={(newName: string) => {
if (triggerOptions.readonly === true) {
return;
}
triggerOptions.onTriggerUpdate({
...trigger,
name: newName,
});
}}
HeaderIcon={<IconHandMove color={theme.font.color.tertiary} />} HeaderIcon={<IconHandMove color={theme.font.color.tertiary} />}
headerTitle="Manual Trigger" headerTitle={headerTitle}
headerType="Trigger · Manual" headerType="Trigger · Manual"
> >
<Select <Select

View File

@ -2,17 +2,17 @@ import { WorkflowTriggerType } from '@/workflow/types/Workflow';
import { IconComponent, IconSettingsAutomation } from 'twenty-ui'; import { IconComponent, IconSettingsAutomation } from 'twenty-ui';
export const TRIGGER_TYPES: Array<{ export const TRIGGER_TYPES: Array<{
label: string; name: string;
type: WorkflowTriggerType; type: WorkflowTriggerType;
icon: IconComponent; icon: IconComponent;
}> = [ }> = [
{ {
label: 'Database Event', name: 'Database Event',
type: 'DATABASE_EVENT', type: 'DATABASE_EVENT',
icon: IconSettingsAutomation, icon: IconSettingsAutomation,
}, },
{ {
label: 'Manual', name: 'Manual Trigger',
type: 'MANUAL', type: 'MANUAL',
icon: IconSettingsAutomation, icon: IconSettingsAutomation,
}, },

View File

@ -49,7 +49,9 @@ export const useAvailableVariablesInWorkflowStep = (): StepOutputSchema[] => {
) { ) {
result.push({ result.push({
id: 'trigger', id: 'trigger',
name: getTriggerStepName(workflow.currentVersion.trigger), name: isDefined(workflow.currentVersion.trigger.name)
? workflow.currentVersion.trigger.name
: getTriggerStepName(workflow.currentVersion.trigger),
outputSchema: workflow.currentVersion.trigger.settings.outputSchema, outputSchema: workflow.currentVersion.trigger.settings.outputSchema,
}); });
} }

View File

@ -109,8 +109,8 @@ export type WorkflowActionType =
export type WorkflowStepType = WorkflowActionType; export type WorkflowStepType = WorkflowActionType;
type BaseTrigger = { type BaseTrigger = {
name?: string;
type: string; type: string;
input?: object;
}; };
export type WorkflowDatabaseEventTrigger = BaseTrigger & { export type WorkflowDatabaseEventTrigger = BaseTrigger & {

View File

@ -16,12 +16,12 @@ export type WorkflowDiagramStepNodeData =
| { | {
nodeType: 'trigger'; nodeType: 'trigger';
triggerType: WorkflowTriggerType; triggerType: WorkflowTriggerType;
label: string; name: string;
} }
| { | {
nodeType: 'action'; nodeType: 'action';
actionType: WorkflowActionType; actionType: WorkflowActionType;
label: string; name: string;
}; };
export type WorkflowDiagramCreateStepNodeData = { export type WorkflowDiagramCreateStepNodeData = {

View File

@ -5,6 +5,7 @@ import { addCreateStepNodes } from '../addCreateStepNodes';
describe('addCreateStepNodes', () => { describe('addCreateStepNodes', () => {
it("adds a create step node to the end of a single-branch flow and doesn't change the shape of other nodes", () => { it("adds a create step node to the end of a single-branch flow and doesn't change the shape of other nodes", () => {
const trigger: WorkflowTrigger = { const trigger: WorkflowTrigger = {
name: 'Company created',
type: 'DATABASE_EVENT', type: 'DATABASE_EVENT',
settings: { settings: {
eventName: 'company.created', eventName: 'company.created',

View File

@ -4,6 +4,7 @@ import { generateWorkflowDiagram } from '../generateWorkflowDiagram';
describe('generateWorkflowDiagram', () => { describe('generateWorkflowDiagram', () => {
it('should generate a single trigger node when no step is provided', () => { it('should generate a single trigger node when no step is provided', () => {
const trigger: WorkflowTrigger = { const trigger: WorkflowTrigger = {
name: 'Company created',
type: 'DATABASE_EVENT', type: 'DATABASE_EVENT',
settings: { settings: {
eventName: 'company.created', eventName: 'company.created',
@ -19,7 +20,6 @@ describe('generateWorkflowDiagram', () => {
expect(result.nodes[0]).toMatchObject({ expect(result.nodes[0]).toMatchObject({
data: { data: {
label: 'Company is Created',
nodeType: 'trigger', nodeType: 'trigger',
}, },
}); });
@ -27,6 +27,7 @@ describe('generateWorkflowDiagram', () => {
it('should generate a diagram with nodes and edges corresponding to the steps', () => { it('should generate a diagram with nodes and edges corresponding to the steps', () => {
const trigger: WorkflowTrigger = { const trigger: WorkflowTrigger = {
name: 'Company created',
type: 'DATABASE_EVENT', type: 'DATABASE_EVENT',
settings: { settings: {
eventName: 'company.created', eventName: 'company.created',
@ -85,13 +86,14 @@ describe('generateWorkflowDiagram', () => {
expect(stepNodes[index].data).toEqual({ expect(stepNodes[index].data).toEqual({
nodeType: 'action', nodeType: 'action',
actionType: 'CODE', actionType: 'CODE',
label: step.name, name: step.name,
}); });
} }
}); });
it('should correctly link nodes with edges', () => { it('should correctly link nodes with edges', () => {
const trigger: WorkflowTrigger = { const trigger: WorkflowTrigger = {
name: 'Company created',
type: 'DATABASE_EVENT', type: 'DATABASE_EVENT',
settings: { settings: {
eventName: 'company.created', eventName: 'company.created',

View File

@ -42,6 +42,7 @@ describe('getWorkflowVersionDiagram', () => {
name: '', name: '',
steps: null, steps: null,
trigger: { trigger: {
name: 'Company created',
settings: { eventName: 'company.created', outputSchema: {} }, settings: { eventName: 'company.created', outputSchema: {} },
type: 'DATABASE_EVENT', type: 'DATABASE_EVENT',
}, },
@ -53,7 +54,7 @@ describe('getWorkflowVersionDiagram', () => {
nodes: [ nodes: [
{ {
data: { data: {
label: 'Company is Created', name: 'Company created',
nodeType: 'trigger', nodeType: 'trigger',
triggerType: 'DATABASE_EVENT', triggerType: 'DATABASE_EVENT',
}, },
@ -93,6 +94,7 @@ describe('getWorkflowVersionDiagram', () => {
}, },
], ],
trigger: { trigger: {
name: 'Company created',
settings: { eventName: 'company.created', outputSchema: {} }, settings: { eventName: 'company.created', outputSchema: {} },
type: 'DATABASE_EVENT', type: 'DATABASE_EVENT',
}, },

View File

@ -11,6 +11,7 @@ describe('insertStep', () => {
name: '', name: '',
steps: [], steps: [],
trigger: { trigger: {
name: 'Company created',
settings: { eventName: 'company.created', outputSchema: {} }, settings: { eventName: 'company.created', outputSchema: {} },
type: 'DATABASE_EVENT', type: 'DATABASE_EVENT',
}, },
@ -54,6 +55,7 @@ describe('insertStep', () => {
name: '', name: '',
steps: [], steps: [],
trigger: { trigger: {
name: 'Company created',
settings: { eventName: 'company.created', outputSchema: {} }, settings: { eventName: 'company.created', outputSchema: {} },
type: 'DATABASE_EVENT', type: 'DATABASE_EVENT',
}, },
@ -135,6 +137,7 @@ describe('insertStep', () => {
}, },
], ],
trigger: { trigger: {
name: 'Company created',
settings: { eventName: 'company.created', outputSchema: {} }, settings: { eventName: 'company.created', outputSchema: {} },
type: 'DATABASE_EVENT', type: 'DATABASE_EVENT',
}, },
@ -220,6 +223,7 @@ describe('insertStep', () => {
}, },
], ],
trigger: { trigger: {
name: 'Company created',
settings: { eventName: 'company.created', outputSchema: {} }, settings: { eventName: 'company.created', outputSchema: {} },
type: 'DATABASE_EVENT', type: 'DATABASE_EVENT',
}, },

View File

@ -5,7 +5,7 @@ it('Preserves the properties defined in the previous version but not in the next
const previousDiagram: WorkflowDiagram = { const previousDiagram: WorkflowDiagram = {
nodes: [ nodes: [
{ {
data: { nodeType: 'action', label: '', actionType: 'CODE' }, data: { nodeType: 'action', name: '', actionType: 'CODE' },
id: '1', id: '1',
position: { x: 0, y: 0 }, position: { x: 0, y: 0 },
selected: true, selected: true,
@ -16,7 +16,7 @@ it('Preserves the properties defined in the previous version but not in the next
const nextDiagram: WorkflowDiagram = { const nextDiagram: WorkflowDiagram = {
nodes: [ nodes: [
{ {
data: { nodeType: 'action', label: '', actionType: 'CODE' }, data: { nodeType: 'action', name: '', actionType: 'CODE' },
id: '1', id: '1',
position: { x: 0, y: 0 }, position: { x: 0, y: 0 },
}, },
@ -27,7 +27,7 @@ it('Preserves the properties defined in the previous version but not in the next
expect(mergeWorkflowDiagrams(previousDiagram, nextDiagram)).toEqual({ expect(mergeWorkflowDiagrams(previousDiagram, nextDiagram)).toEqual({
nodes: [ nodes: [
{ {
data: { nodeType: 'action', label: '', actionType: 'CODE' }, data: { nodeType: 'action', name: '', actionType: 'CODE' },
id: '1', id: '1',
position: { x: 0, y: 0 }, position: { x: 0, y: 0 },
selected: true, selected: true,
@ -41,7 +41,7 @@ it('Replaces duplicated properties with the next value', () => {
const previousDiagram: WorkflowDiagram = { const previousDiagram: WorkflowDiagram = {
nodes: [ nodes: [
{ {
data: { nodeType: 'action', label: '', actionType: 'CODE' }, data: { nodeType: 'action', name: '', actionType: 'CODE' },
id: '1', id: '1',
position: { x: 0, y: 0 }, position: { x: 0, y: 0 },
}, },
@ -51,7 +51,7 @@ it('Replaces duplicated properties with the next value', () => {
const nextDiagram: WorkflowDiagram = { const nextDiagram: WorkflowDiagram = {
nodes: [ nodes: [
{ {
data: { nodeType: 'action', label: '2', actionType: 'CODE' }, data: { nodeType: 'action', name: '2', actionType: 'CODE' },
id: '1', id: '1',
position: { x: 0, y: 0 }, position: { x: 0, y: 0 },
}, },
@ -62,7 +62,7 @@ it('Replaces duplicated properties with the next value', () => {
expect(mergeWorkflowDiagrams(previousDiagram, nextDiagram)).toEqual({ expect(mergeWorkflowDiagrams(previousDiagram, nextDiagram)).toEqual({
nodes: [ nodes: [
{ {
data: { nodeType: 'action', label: '2', actionType: 'CODE' }, data: { nodeType: 'action', name: '2', actionType: 'CODE' },
id: '1', id: '1',
position: { x: 0, y: 0 }, position: { x: 0, y: 0 },
}, },

View File

@ -28,6 +28,7 @@ it('returns a deep copy of the provided steps array instead of mutating it', ()
name: '', name: '',
steps: [stepToBeRemoved], steps: [stepToBeRemoved],
trigger: { trigger: {
name: 'Company created',
settings: { eventName: 'company.created', outputSchema: {} }, settings: { eventName: 'company.created', outputSchema: {} },
type: 'DATABASE_EVENT', type: 'DATABASE_EVENT',
}, },
@ -108,6 +109,7 @@ it('removes a step in a non-empty steps array', () => {
}, },
], ],
trigger: { trigger: {
name: 'Company created',
settings: { eventName: 'company.created', outputSchema: {} }, settings: { eventName: 'company.created', outputSchema: {} },
type: 'DATABASE_EVENT', type: 'DATABASE_EVENT',
}, },

View File

@ -29,6 +29,7 @@ describe('replaceStep', () => {
name: '', name: '',
steps: [stepToBeReplaced], steps: [stepToBeReplaced],
trigger: { trigger: {
name: 'Company created',
settings: { eventName: 'company.created', outputSchema: {} }, settings: { eventName: 'company.created', outputSchema: {} },
type: 'DATABASE_EVENT', type: 'DATABASE_EVENT',
}, },
@ -123,6 +124,7 @@ describe('replaceStep', () => {
}, },
], ],
trigger: { trigger: {
name: 'Company created',
settings: { settings: {
eventName: 'company.created', eventName: 'company.created',
outputSchema: {}, outputSchema: {},

View File

@ -53,7 +53,7 @@ export const generateWorkflowDiagram = ({
data: { data: {
nodeType: 'action', nodeType: 'action',
actionType: nodeActionType, actionType: nodeActionType,
label: nodeLabel, name: isDefined(step.name) ? step.name : nodeLabel,
}, },
position: { position: {
x: xPos, x: xPos,
@ -110,7 +110,7 @@ export const generateWorkflowDiagram = ({
data: { data: {
nodeType: 'trigger', nodeType: 'trigger',
triggerType: trigger.type, triggerType: trigger.type,
label: triggerLabel, name: isDefined(trigger.name) ? trigger.name : triggerLabel,
}, },
position: { position: {
x: 0, x: 0,

View File

@ -65,7 +65,7 @@ export const getStepDefaultDefinition = ({
case 'RECORD_CRUD.CREATE': { case 'RECORD_CRUD.CREATE': {
return { return {
id: newStepId, id: newStepId,
name: 'Record Create', name: 'Create Record',
type: 'RECORD_CRUD', type: 'RECORD_CRUD',
valid: false, valid: false,
settings: { settings: {