feat: display specific action types in workflow side panel tooltips (#15013)
## What I've Implemented I've added tooltips that show the original action type when you hover over workflow step icons in the side panel. Now even if you rename an action to something custom, you can still see what type of action it actually is by hovering over the icon. ## The Problem This Solves Before this change, once you renamed a workflow action (like changing "Create Record" to "Add New Customer"), there was no way to tell what the original action type was. This made it really confusing when collaborating with others or when coming back to your own workflows after some time - you couldn't tell if an action was a "Create Record" or "Update Record" or something else. ## What Changed Updated action type labels: Instead of showing just "Action" for all record operations, the system now shows specific types like "Create Record", "Update Record", "Delete Record", etc. Added hover tooltips: When you hover over the action icons in the workflow side panel, a tooltip appears showing the original action type, even if you've renamed the step title. ## Before vs After Before: All actions showed "Action" in the side panel, making it impossible to distinguish between different types after renaming. After: Each action shows its specific type in tooltips, so you always know what you're working with. This should make workflow management much clearer, especially when multiple people are collaborating on the same workflow! Resolves #14878 ## Demo Video See it in action: https://www.loom.com/share/c0e0ec24e4524d0685b841e9ceb011d0?t=65&sid=dc05e58a-8869-4969-aa67-9772242fe697 --------- Co-authored-by: Thomas Trompette <thomas.trompette@sfr.fr>
This commit is contained in:
co-authored by
Thomas Trompette
parent
5121fdd265
commit
8369168abe
@@ -3,7 +3,7 @@ import { TitleInput } from '@/ui/input/components/TitleInput';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { useState } from 'react';
|
||||
import { type IconComponent } from 'twenty-ui/display';
|
||||
import { AppTooltip, type IconComponent } from 'twenty-ui/display';
|
||||
|
||||
const StyledHeader = styled.div`
|
||||
background-color: ${({ theme }) => theme.background.secondary};
|
||||
@@ -52,6 +52,7 @@ type SidePanelHeaderProps = {
|
||||
iconColor: string;
|
||||
initialTitle: string;
|
||||
headerType: string;
|
||||
iconTooltip?: string;
|
||||
} & (
|
||||
| {
|
||||
disabled: true;
|
||||
@@ -70,6 +71,7 @@ export const SidePanelHeader = ({
|
||||
headerType,
|
||||
disabled,
|
||||
onTitleChange,
|
||||
iconTooltip,
|
||||
}: SidePanelHeaderProps) => {
|
||||
const theme = useTheme();
|
||||
|
||||
@@ -89,15 +91,24 @@ export const SidePanelHeader = ({
|
||||
});
|
||||
};
|
||||
|
||||
const tooltipId = `side-panel-icon-tooltip-${headerType.replace(/\s+/g, '-')}`;
|
||||
|
||||
return (
|
||||
<StyledHeader data-testid="side-panel-header">
|
||||
<StyledHeaderIconContainer>
|
||||
<StyledHeaderIconContainer id={tooltipId}>
|
||||
<Icon
|
||||
color={iconColor}
|
||||
stroke={theme.icon.stroke.sm}
|
||||
size={theme.icon.size.lg}
|
||||
/>
|
||||
</StyledHeaderIconContainer>
|
||||
{iconTooltip && (
|
||||
<AppTooltip
|
||||
anchorSelect={`#${tooltipId}`}
|
||||
content={iconTooltip}
|
||||
place="top"
|
||||
/>
|
||||
)}
|
||||
<StyledHeaderInfo>
|
||||
<StyledHeaderTitle>
|
||||
<TitleInput
|
||||
|
||||
+6
-2
@@ -4,7 +4,11 @@ import { useTheme } from '@emotion/react';
|
||||
import { useIcons } from 'twenty-ui/display';
|
||||
import { MenuItem } from 'twenty-ui/navigation';
|
||||
|
||||
type Action = { type: WorkflowActionType; label: string; icon: string };
|
||||
type Action = {
|
||||
defaultLabel: string;
|
||||
type: WorkflowActionType;
|
||||
icon: string;
|
||||
};
|
||||
|
||||
export const WorkflowActionMenuItems = ({
|
||||
actions,
|
||||
@@ -34,7 +38,7 @@ export const WorkflowActionMenuItems = ({
|
||||
size={16}
|
||||
/>
|
||||
)}
|
||||
text={action.label}
|
||||
text={action.defaultLabel}
|
||||
onClick={() => onClick(action.type)}
|
||||
/>
|
||||
);
|
||||
|
||||
+3
-1
@@ -6,6 +6,7 @@ import { Select } from '@/ui/input/components/Select';
|
||||
import { type WorkflowAiAgentAction } from '@/workflow/types/Workflow';
|
||||
import { WorkflowStepBody } from '@/workflow/workflow-steps/components/WorkflowStepBody';
|
||||
import { WorkflowStepFooter } from '@/workflow/workflow-steps/components/WorkflowStepFooter';
|
||||
import { AI_AGENT_ACTION } from '@/workflow/workflow-steps/workflow-actions/constants/actions/AiAgentAction';
|
||||
import { useWorkflowActionHeader } from '@/workflow/workflow-steps/workflow-actions/hooks/useWorkflowActionHeader';
|
||||
import { WorkflowVariablePicker } from '@/workflow/workflow-variables/components/WorkflowVariablePicker';
|
||||
import { type AiAgentOutputSchema } from '@/workflow/workflow-variables/types/AiAgentOutputSchema';
|
||||
@@ -44,7 +45,7 @@ export const WorkflowEditActionAiAgent = ({
|
||||
const { headerTitle, headerIcon, headerIconColor, headerType } =
|
||||
useWorkflowActionHeader({
|
||||
action,
|
||||
defaultTitle: 'AI Agent',
|
||||
defaultTitle: AI_AGENT_ACTION.defaultLabel,
|
||||
});
|
||||
|
||||
const { handleOutputSchemaChange, outputFields } = useAiAgentOutputSchema(
|
||||
@@ -111,6 +112,7 @@ export const WorkflowEditActionAiAgent = ({
|
||||
initialTitle={headerTitle}
|
||||
headerType={headerType}
|
||||
disabled={actionOptions.readonly}
|
||||
iconTooltip={AI_AGENT_ACTION.defaultLabel}
|
||||
/>
|
||||
<WorkflowStepBody>
|
||||
<div>
|
||||
|
||||
+3
-1
@@ -40,6 +40,7 @@ import { useLingui } from '@lingui/react/macro';
|
||||
import { SOURCE_FOLDER_NAME } from '@/serverless-functions/constants/SourceFolderName';
|
||||
import { computeNewSources } from '@/serverless-functions/utils/computeNewSources';
|
||||
import { WorkflowStepFooter } from '@/workflow/workflow-steps/components/WorkflowStepFooter';
|
||||
import { CODE_ACTION } from '@/workflow/workflow-steps/workflow-actions/constants/actions/CodeAction';
|
||||
import { type Monaco } from '@monaco-editor/react';
|
||||
import { type editor } from 'monaco-editor';
|
||||
import { AutoTypings } from 'monaco-editor-auto-typings';
|
||||
@@ -326,7 +327,7 @@ export const WorkflowEditActionServerlessFunction = ({
|
||||
|
||||
const headerTitle = isDefined(action.name)
|
||||
? action.name
|
||||
: 'Code - Serverless Function';
|
||||
: CODE_ACTION.defaultLabel;
|
||||
const headerIcon = getActionIcon(action.type);
|
||||
const headerIconColor = useActionIconColorOrThrow(action.type);
|
||||
const headerType = useActionHeaderTypeOrThrow(action.type);
|
||||
@@ -431,6 +432,7 @@ export const WorkflowEditActionServerlessFunction = ({
|
||||
initialTitle={headerTitle}
|
||||
headerType={headerType}
|
||||
disabled={actionOptions.readonly}
|
||||
iconTooltip={CODE_ACTION.defaultLabel}
|
||||
/>
|
||||
<WorkflowStepBody>
|
||||
{activeTabId === WorkflowServerlessFunctionTabId.CODE && (
|
||||
|
||||
+3
-1
@@ -10,6 +10,7 @@ import { useViewOrDefaultViewFromPrefetchedViews } from '@/views/hooks/useViewOr
|
||||
import { type WorkflowCreateRecordAction } from '@/workflow/types/Workflow';
|
||||
import { WorkflowStepBody } from '@/workflow/workflow-steps/components/WorkflowStepBody';
|
||||
import { WorkflowStepFooter } from '@/workflow/workflow-steps/components/WorkflowStepFooter';
|
||||
import { CREATE_RECORD_ACTION } from '@/workflow/workflow-steps/workflow-actions/constants/actions/CreateRecordAction';
|
||||
import { useWorkflowActionHeader } from '@/workflow/workflow-steps/workflow-actions/hooks/useWorkflowActionHeader';
|
||||
import { shouldDisplayFormField } from '@/workflow/workflow-steps/workflow-actions/utils/shouldDisplayFormField';
|
||||
import { WorkflowVariablePicker } from '@/workflow/workflow-variables/components/WorkflowVariablePicker';
|
||||
@@ -198,7 +199,7 @@ export const WorkflowEditActionCreateRecord = ({
|
||||
const { headerTitle, headerIcon, headerIconColor, headerType } =
|
||||
useWorkflowActionHeader({
|
||||
action,
|
||||
defaultTitle: 'Create Record',
|
||||
defaultTitle: CREATE_RECORD_ACTION.defaultLabel,
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -219,6 +220,7 @@ export const WorkflowEditActionCreateRecord = ({
|
||||
initialTitle={headerTitle}
|
||||
headerType={headerType}
|
||||
disabled={isFormDisabled}
|
||||
iconTooltip={CREATE_RECORD_ACTION.defaultLabel}
|
||||
/>
|
||||
<WorkflowStepBody>
|
||||
<Select
|
||||
|
||||
+3
-1
@@ -8,6 +8,7 @@ import { useEffect, useState } from 'react';
|
||||
import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth';
|
||||
import { WorkflowStepBody } from '@/workflow/workflow-steps/components/WorkflowStepBody';
|
||||
import { WorkflowStepFooter } from '@/workflow/workflow-steps/components/WorkflowStepFooter';
|
||||
import { DELETE_RECORD_ACTION } from '@/workflow/workflow-steps/workflow-actions/constants/actions/DeleteRecordAction';
|
||||
import { useWorkflowActionHeader } from '@/workflow/workflow-steps/workflow-actions/hooks/useWorkflowActionHeader';
|
||||
import { WorkflowVariablePicker } from '@/workflow/workflow-variables/components/WorkflowVariablePicker';
|
||||
import { useTheme } from '@emotion/react';
|
||||
@@ -118,7 +119,7 @@ export const WorkflowEditActionDeleteRecord = ({
|
||||
const { headerTitle, headerIcon, headerIconColor, headerType } =
|
||||
useWorkflowActionHeader({
|
||||
action,
|
||||
defaultTitle: 'Delete Record',
|
||||
defaultTitle: DELETE_RECORD_ACTION.defaultLabel,
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -139,6 +140,7 @@ export const WorkflowEditActionDeleteRecord = ({
|
||||
initialTitle={headerTitle}
|
||||
headerType={headerType}
|
||||
disabled={isFormDisabled}
|
||||
iconTooltip={DELETE_RECORD_ACTION.defaultLabel}
|
||||
/>
|
||||
<WorkflowStepBody>
|
||||
<Select
|
||||
|
||||
+3
-1
@@ -19,6 +19,7 @@ import { workflowVisualizerWorkflowIdComponentState } from '@/workflow/states/wo
|
||||
import { type WorkflowSendEmailAction } from '@/workflow/types/Workflow';
|
||||
import { WorkflowStepBody } from '@/workflow/workflow-steps/components/WorkflowStepBody';
|
||||
import { WorkflowStepFooter } from '@/workflow/workflow-steps/components/WorkflowStepFooter';
|
||||
import { SEND_EMAIL_ACTION } from '@/workflow/workflow-steps/workflow-actions/constants/actions/SendEmailAction';
|
||||
import { useWorkflowActionHeader } from '@/workflow/workflow-steps/workflow-actions/hooks/useWorkflowActionHeader';
|
||||
import { WorkflowVariablePicker } from '@/workflow/workflow-variables/components/WorkflowVariablePicker';
|
||||
import { useTheme } from '@emotion/react';
|
||||
@@ -246,7 +247,7 @@ export const WorkflowEditActionSendEmail = ({
|
||||
const { headerTitle, headerIcon, headerIconColor, headerType } =
|
||||
useWorkflowActionHeader({
|
||||
action,
|
||||
defaultTitle: 'Send Email',
|
||||
defaultTitle: SEND_EMAIL_ACTION.defaultLabel,
|
||||
});
|
||||
|
||||
const navigate = useNavigateSettings();
|
||||
@@ -272,6 +273,7 @@ export const WorkflowEditActionSendEmail = ({
|
||||
initialTitle={headerTitle}
|
||||
headerType={headerType}
|
||||
disabled={actionOptions.readonly}
|
||||
iconTooltip={SEND_EMAIL_ACTION.defaultLabel}
|
||||
/>
|
||||
<WorkflowStepBody>
|
||||
<Select
|
||||
|
||||
+3
-1
@@ -3,6 +3,7 @@ import { type WorkflowUpdateRecordAction } from '@/workflow/types/Workflow';
|
||||
import { WorkflowStepFooter } from '@/workflow/workflow-steps/components/WorkflowStepFooter';
|
||||
import { WorkflowUpdateRecordBody } from '@/workflow/workflow-steps/workflow-actions/components/WorkflowUpdateRecordBody';
|
||||
|
||||
import { UPDATE_RECORD_ACTION } from '@/workflow/workflow-steps/workflow-actions/constants/actions/UpdateRecordAction';
|
||||
import { useWorkflowActionHeader } from '@/workflow/workflow-steps/workflow-actions/hooks/useWorkflowActionHeader';
|
||||
import { type UpdateRecordFormData } from '@/workflow/workflow-steps/workflow-actions/types/update-record-form-data.type';
|
||||
import { useIcons } from 'twenty-ui/display';
|
||||
@@ -26,7 +27,7 @@ export const WorkflowEditActionUpdateRecord = ({
|
||||
const { headerTitle, headerIcon, headerIconColor, headerType } =
|
||||
useWorkflowActionHeader({
|
||||
action,
|
||||
defaultTitle: 'Update Record',
|
||||
defaultTitle: UPDATE_RECORD_ACTION.defaultLabel,
|
||||
});
|
||||
|
||||
const { getIcon } = useIcons();
|
||||
@@ -70,6 +71,7 @@ export const WorkflowEditActionUpdateRecord = ({
|
||||
initialTitle={headerTitle}
|
||||
headerType={headerType}
|
||||
disabled={isFormDisabled}
|
||||
iconTooltip={UPDATE_RECORD_ACTION.defaultLabel}
|
||||
/>
|
||||
<WorkflowUpdateRecordBody
|
||||
defaultObjectNameSingular={action.settings.input.objectName}
|
||||
|
||||
+3
-1
@@ -3,6 +3,7 @@ import { type WorkflowUpsertRecordAction } from '@/workflow/types/Workflow';
|
||||
import { WorkflowStepFooter } from '@/workflow/workflow-steps/components/WorkflowStepFooter';
|
||||
import { WorkflowUpdateRecordBody } from '@/workflow/workflow-steps/workflow-actions/components/WorkflowUpdateRecordBody';
|
||||
|
||||
import { UPSERT_RECORD_ACTION } from '@/workflow/workflow-steps/workflow-actions/constants/actions/UpsertRecordAction';
|
||||
import { useWorkflowActionHeader } from '@/workflow/workflow-steps/workflow-actions/hooks/useWorkflowActionHeader';
|
||||
import { type UpdateRecordFormData } from '@/workflow/workflow-steps/workflow-actions/types/update-record-form-data.type';
|
||||
import { useIcons } from 'twenty-ui/display';
|
||||
@@ -26,7 +27,7 @@ export const WorkflowEditActionUpsertRecord = ({
|
||||
const { headerTitle, headerIcon, headerIconColor, headerType } =
|
||||
useWorkflowActionHeader({
|
||||
action,
|
||||
defaultTitle: 'Create or Update Record',
|
||||
defaultTitle: UPSERT_RECORD_ACTION.defaultLabel,
|
||||
});
|
||||
|
||||
const { getIcon } = useIcons();
|
||||
@@ -69,6 +70,7 @@ export const WorkflowEditActionUpsertRecord = ({
|
||||
initialTitle={headerTitle}
|
||||
headerType={headerType}
|
||||
disabled={isFormDisabled}
|
||||
iconTooltip={UPSERT_RECORD_ACTION.defaultLabel}
|
||||
/>
|
||||
<WorkflowUpdateRecordBody
|
||||
defaultObjectNameSingular={action.settings.input.objectName}
|
||||
|
||||
+3
-8
@@ -1,13 +1,8 @@
|
||||
import { type WorkflowActionType } from '@/workflow/types/Workflow';
|
||||
import { AI_AGENT_ACTION } from '@/workflow/workflow-steps/workflow-actions/constants/actions/AiAgentAction';
|
||||
|
||||
export const AI_ACTIONS: Array<{
|
||||
label: string;
|
||||
defaultLabel: string;
|
||||
type: Extract<WorkflowActionType, 'AI_AGENT'>;
|
||||
icon: string;
|
||||
}> = [
|
||||
{
|
||||
label: 'AI Agent',
|
||||
type: 'AI_AGENT',
|
||||
icon: 'IconBrain',
|
||||
},
|
||||
];
|
||||
}> = [AI_AGENT_ACTION];
|
||||
|
||||
+5
-18
@@ -1,23 +1,10 @@
|
||||
import { type WorkflowActionType } from '@/workflow/types/Workflow';
|
||||
import { CODE_ACTION } from '@/workflow/workflow-steps/workflow-actions/constants/actions/CodeAction';
|
||||
import { HTTP_REQUEST_ACTION } from '@/workflow/workflow-steps/workflow-actions/constants/actions/HttpRequestAction';
|
||||
import { SEND_EMAIL_ACTION } from '@/workflow/workflow-steps/workflow-actions/constants/actions/SendEmailAction';
|
||||
|
||||
export const CORE_ACTIONS: Array<{
|
||||
label: string;
|
||||
defaultLabel: string;
|
||||
type: Extract<WorkflowActionType, 'CODE' | 'SEND_EMAIL' | 'HTTP_REQUEST'>;
|
||||
icon: string;
|
||||
}> = [
|
||||
{
|
||||
label: 'Send Email',
|
||||
type: 'SEND_EMAIL',
|
||||
icon: 'IconSend',
|
||||
},
|
||||
{
|
||||
label: 'Code',
|
||||
type: 'CODE',
|
||||
icon: 'IconCode',
|
||||
},
|
||||
{
|
||||
label: 'HTTP Request',
|
||||
type: 'HTTP_REQUEST',
|
||||
icon: 'IconWorld',
|
||||
},
|
||||
];
|
||||
}> = [SEND_EMAIL_ACTION, CODE_ACTION, HTTP_REQUEST_ACTION];
|
||||
|
||||
+5
-18
@@ -1,23 +1,10 @@
|
||||
import { type WorkflowActionType } from '@/workflow/types/Workflow';
|
||||
import { DELAY_ACTION } from '@/workflow/workflow-steps/workflow-actions/constants/actions/DelayAction';
|
||||
import { FILTER_ACTION } from '@/workflow/workflow-steps/workflow-actions/constants/actions/FilterAction';
|
||||
import { ITERATOR_ACTION } from '@/workflow/workflow-steps/workflow-actions/constants/actions/IteratorAction';
|
||||
|
||||
export const FLOW_ACTIONS: Array<{
|
||||
label: string;
|
||||
defaultLabel: string;
|
||||
type: Extract<WorkflowActionType, 'ITERATOR' | 'FILTER' | 'DELAY'>;
|
||||
icon: string;
|
||||
}> = [
|
||||
{
|
||||
label: 'Iterator',
|
||||
type: 'ITERATOR',
|
||||
icon: 'IconRepeat',
|
||||
},
|
||||
{
|
||||
label: 'Filter',
|
||||
type: 'FILTER',
|
||||
icon: 'IconFilter',
|
||||
},
|
||||
{
|
||||
label: 'Delay',
|
||||
type: 'DELAY',
|
||||
icon: 'IconPlayerPause',
|
||||
},
|
||||
];
|
||||
}> = [ITERATOR_ACTION, FILTER_ACTION, DELAY_ACTION];
|
||||
|
||||
+3
-8
@@ -1,13 +1,8 @@
|
||||
import { type WorkflowActionType } from '@/workflow/types/Workflow';
|
||||
import { FORM_ACTION } from '@/workflow/workflow-steps/workflow-actions/constants/actions/FormAction';
|
||||
|
||||
export const HUMAN_INPUT_ACTIONS: Array<{
|
||||
label: string;
|
||||
defaultLabel: string;
|
||||
type: Extract<WorkflowActionType, 'FORM'>;
|
||||
icon: string;
|
||||
}> = [
|
||||
{
|
||||
label: 'Form',
|
||||
type: 'FORM',
|
||||
icon: 'IconForms',
|
||||
},
|
||||
];
|
||||
}> = [FORM_ACTION];
|
||||
|
||||
+11
-26
@@ -1,7 +1,12 @@
|
||||
import { type WorkflowActionType } from '@/workflow/types/Workflow';
|
||||
import { CREATE_RECORD_ACTION } from '@/workflow/workflow-steps/workflow-actions/constants/actions/CreateRecordAction';
|
||||
import { DELETE_RECORD_ACTION } from '@/workflow/workflow-steps/workflow-actions/constants/actions/DeleteRecordAction';
|
||||
import { FIND_RECORDS_ACTION } from '@/workflow/workflow-steps/workflow-actions/constants/actions/FindRecordsAction';
|
||||
import { UPDATE_RECORD_ACTION } from '@/workflow/workflow-steps/workflow-actions/constants/actions/UpdateRecordAction';
|
||||
import { UPSERT_RECORD_ACTION } from '@/workflow/workflow-steps/workflow-actions/constants/actions/UpsertRecordAction';
|
||||
|
||||
export const RECORD_ACTIONS: Array<{
|
||||
label: string;
|
||||
defaultLabel: string;
|
||||
type: Extract<
|
||||
WorkflowActionType,
|
||||
| 'CREATE_RECORD'
|
||||
@@ -12,29 +17,9 @@ export const RECORD_ACTIONS: Array<{
|
||||
>;
|
||||
icon: string;
|
||||
}> = [
|
||||
{
|
||||
label: 'Create Record',
|
||||
type: 'CREATE_RECORD',
|
||||
icon: 'IconPlus',
|
||||
},
|
||||
{
|
||||
label: 'Update Record',
|
||||
type: 'UPDATE_RECORD',
|
||||
icon: 'IconReload',
|
||||
},
|
||||
{
|
||||
label: 'Delete Record',
|
||||
type: 'DELETE_RECORD',
|
||||
icon: 'IconTrash',
|
||||
},
|
||||
{
|
||||
label: 'Search Records',
|
||||
type: 'FIND_RECORDS',
|
||||
icon: 'IconSearch',
|
||||
},
|
||||
{
|
||||
label: 'Create or Update Record',
|
||||
type: 'UPSERT_RECORD',
|
||||
icon: 'IconPencilPlus',
|
||||
},
|
||||
CREATE_RECORD_ACTION,
|
||||
UPDATE_RECORD_ACTION,
|
||||
DELETE_RECORD_ACTION,
|
||||
FIND_RECORDS_ACTION,
|
||||
UPSERT_RECORD_ACTION,
|
||||
];
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { type WorkflowActionType } from '@/workflow/types/Workflow';
|
||||
|
||||
export const AI_AGENT_ACTION: {
|
||||
defaultLabel: string;
|
||||
type: Extract<WorkflowActionType, 'AI_AGENT'>;
|
||||
icon: string;
|
||||
} = {
|
||||
defaultLabel: 'AI Agent',
|
||||
type: 'AI_AGENT',
|
||||
icon: 'IconBrain',
|
||||
};
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { type WorkflowActionType } from '@/workflow/types/Workflow';
|
||||
|
||||
export const CODE_ACTION: {
|
||||
defaultLabel: string;
|
||||
type: Extract<WorkflowActionType, 'CODE'>;
|
||||
icon: string;
|
||||
} = {
|
||||
defaultLabel: 'Code - Serverless Function',
|
||||
type: 'CODE',
|
||||
icon: 'IconCode',
|
||||
};
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { type WorkflowActionType } from '@/workflow/types/Workflow';
|
||||
|
||||
export const CREATE_RECORD_ACTION: {
|
||||
defaultLabel: string;
|
||||
type: Extract<WorkflowActionType, 'CREATE_RECORD'>;
|
||||
icon: string;
|
||||
} = {
|
||||
defaultLabel: 'Create Record',
|
||||
type: 'CREATE_RECORD',
|
||||
icon: 'IconPlus',
|
||||
};
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { type WorkflowActionType } from '@/workflow/types/Workflow';
|
||||
|
||||
export const DELAY_ACTION: {
|
||||
defaultLabel: string;
|
||||
type: Extract<WorkflowActionType, 'DELAY'>;
|
||||
icon: string;
|
||||
} = {
|
||||
defaultLabel: 'Delay',
|
||||
type: 'DELAY',
|
||||
icon: 'IconPlayerPause',
|
||||
};
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { type WorkflowActionType } from '@/workflow/types/Workflow';
|
||||
|
||||
export const DELETE_RECORD_ACTION: {
|
||||
defaultLabel: string;
|
||||
type: Extract<WorkflowActionType, 'DELETE_RECORD'>;
|
||||
icon: string;
|
||||
} = {
|
||||
defaultLabel: 'Delete Record',
|
||||
type: 'DELETE_RECORD',
|
||||
icon: 'IconTrash',
|
||||
};
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { type WorkflowActionType } from '@/workflow/types/Workflow';
|
||||
|
||||
export const FILTER_ACTION: {
|
||||
defaultLabel: string;
|
||||
type: Extract<WorkflowActionType, 'FILTER'>;
|
||||
icon: string;
|
||||
} = {
|
||||
defaultLabel: 'Filter',
|
||||
type: 'FILTER',
|
||||
icon: 'IconFilter',
|
||||
};
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { type WorkflowActionType } from '@/workflow/types/Workflow';
|
||||
|
||||
export const FIND_RECORDS_ACTION: {
|
||||
defaultLabel: string;
|
||||
type: Extract<WorkflowActionType, 'FIND_RECORDS'>;
|
||||
icon: string;
|
||||
} = {
|
||||
defaultLabel: 'Search Records',
|
||||
type: 'FIND_RECORDS',
|
||||
icon: 'IconSearch',
|
||||
};
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { type WorkflowActionType } from '@/workflow/types/Workflow';
|
||||
|
||||
export const FORM_ACTION: {
|
||||
defaultLabel: string;
|
||||
type: Extract<WorkflowActionType, 'FORM'>;
|
||||
icon: string;
|
||||
} = {
|
||||
defaultLabel: 'Form',
|
||||
type: 'FORM',
|
||||
icon: 'IconForms',
|
||||
};
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { type WorkflowActionType } from '@/workflow/types/Workflow';
|
||||
|
||||
export const HTTP_REQUEST_ACTION: {
|
||||
defaultLabel: string;
|
||||
type: Extract<WorkflowActionType, 'HTTP_REQUEST'>;
|
||||
icon: string;
|
||||
} = {
|
||||
defaultLabel: 'HTTP Request',
|
||||
type: 'HTTP_REQUEST',
|
||||
icon: 'IconWorld',
|
||||
};
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { type WorkflowActionType } from '@/workflow/types/Workflow';
|
||||
|
||||
export const ITERATOR_ACTION: {
|
||||
defaultLabel: string;
|
||||
type: Extract<WorkflowActionType, 'ITERATOR'>;
|
||||
icon: string;
|
||||
} = {
|
||||
defaultLabel: 'Iterator',
|
||||
type: 'ITERATOR',
|
||||
icon: 'IconRepeat',
|
||||
};
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { type WorkflowActionType } from '@/workflow/types/Workflow';
|
||||
|
||||
export const SEND_EMAIL_ACTION: {
|
||||
defaultLabel: string;
|
||||
type: Extract<WorkflowActionType, 'SEND_EMAIL'>;
|
||||
icon: string;
|
||||
} = {
|
||||
defaultLabel: 'Send Email',
|
||||
type: 'SEND_EMAIL',
|
||||
icon: 'IconSend',
|
||||
};
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { type WorkflowActionType } from '@/workflow/types/Workflow';
|
||||
|
||||
export const UPDATE_RECORD_ACTION: {
|
||||
defaultLabel: string;
|
||||
type: Extract<WorkflowActionType, 'UPDATE_RECORD'>;
|
||||
icon: string;
|
||||
} = {
|
||||
defaultLabel: 'Update Record',
|
||||
type: 'UPDATE_RECORD',
|
||||
icon: 'IconReload',
|
||||
};
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { type WorkflowActionType } from '@/workflow/types/Workflow';
|
||||
|
||||
export const UPSERT_RECORD_ACTION: {
|
||||
defaultLabel: string;
|
||||
type: Extract<WorkflowActionType, 'UPSERT_RECORD'>;
|
||||
icon: string;
|
||||
} = {
|
||||
defaultLabel: 'Create or Update Record',
|
||||
type: 'UPSERT_RECORD',
|
||||
icon: 'IconPencilPlus',
|
||||
};
|
||||
+3
-1
@@ -6,6 +6,7 @@ import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/Gene
|
||||
import { type WorkflowDelayAction } from '@/workflow/types/Workflow';
|
||||
import { WorkflowStepBody } from '@/workflow/workflow-steps/components/WorkflowStepBody';
|
||||
import { WorkflowStepFooter } from '@/workflow/workflow-steps/components/WorkflowStepFooter';
|
||||
import { DELAY_ACTION } from '@/workflow/workflow-steps/workflow-actions/constants/actions/DelayAction';
|
||||
import { useWorkflowActionHeader } from '@/workflow/workflow-steps/workflow-actions/hooks/useWorkflowActionHeader';
|
||||
import { WorkflowVariablePicker } from '@/workflow/workflow-variables/components/WorkflowVariablePicker';
|
||||
import { t } from '@lingui/core/macro';
|
||||
@@ -34,7 +35,7 @@ export const WorkflowEditActionDelay = ({
|
||||
const { headerTitle, headerIcon, headerIconColor, headerType, getIcon } =
|
||||
useWorkflowActionHeader({
|
||||
action,
|
||||
defaultTitle: 'Delay',
|
||||
defaultTitle: DELAY_ACTION.defaultLabel,
|
||||
});
|
||||
|
||||
const delayOptions: Array<SelectOption<'SCHEDULED_DATE' | 'DURATION'>> = [
|
||||
@@ -157,6 +158,7 @@ export const WorkflowEditActionDelay = ({
|
||||
name: newTitle,
|
||||
});
|
||||
}}
|
||||
iconTooltip={DELAY_ACTION.defaultLabel}
|
||||
/>
|
||||
|
||||
<WorkflowStepBody>
|
||||
|
||||
+3
-1
@@ -1,6 +1,7 @@
|
||||
import { SidePanelHeader } from '@/command-menu/components/SidePanelHeader';
|
||||
import { type WorkflowFilterAction } from '@/workflow/types/Workflow';
|
||||
import { WorkflowStepFooter } from '@/workflow/workflow-steps/components/WorkflowStepFooter';
|
||||
import { FILTER_ACTION } from '@/workflow/workflow-steps/workflow-actions/constants/actions/FilterAction';
|
||||
import { WorkflowEditActionFilterBody } from '@/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowEditActionFilterBody';
|
||||
import { WorkflowEditActionFilterBodyEffect } from '@/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowEditActionFilterBodyEffect';
|
||||
import { StepFilterGroupsComponentInstanceContext } from '@/workflow/workflow-steps/workflow-actions/filter-action/states/context/StepFilterGroupsComponentInstanceContext';
|
||||
@@ -33,7 +34,7 @@ export const WorkflowEditActionFilter = ({
|
||||
const { headerTitle, headerIcon, headerIconColor, headerType } =
|
||||
useWorkflowActionHeader({
|
||||
action,
|
||||
defaultTitle: 'Filter',
|
||||
defaultTitle: FILTER_ACTION.defaultLabel,
|
||||
});
|
||||
|
||||
const { getIcon } = useIcons();
|
||||
@@ -56,6 +57,7 @@ export const WorkflowEditActionFilter = ({
|
||||
initialTitle={headerTitle}
|
||||
headerType={headerType}
|
||||
disabled={actionOptions.readonly}
|
||||
iconTooltip={FILTER_ACTION.defaultLabel}
|
||||
/>
|
||||
<StepFiltersComponentInstanceContext.Provider
|
||||
value={{
|
||||
|
||||
+3
-1
@@ -15,6 +15,7 @@ import { useRecordIndexFieldMetadataDerivedStates } from '@/object-record/record
|
||||
import { InputLabel } from '@/ui/input/components/InputLabel';
|
||||
import { WorkflowStepBody } from '@/workflow/workflow-steps/components/WorkflowStepBody';
|
||||
import { WorkflowStepFooter } from '@/workflow/workflow-steps/components/WorkflowStepFooter';
|
||||
import { FIND_RECORDS_ACTION } from '@/workflow/workflow-steps/workflow-actions/constants/actions/FindRecordsAction';
|
||||
import { WorkflowFindRecordsFilters } from '@/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowFindRecordsFilters';
|
||||
import { WorkflowFindRecordsFiltersEffect } from '@/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowFindRecordsFiltersEffect';
|
||||
import { useWorkflowActionHeader } from '@/workflow/workflow-steps/workflow-actions/hooks/useWorkflowActionHeader';
|
||||
@@ -130,7 +131,7 @@ export const WorkflowEditActionFindRecords = ({
|
||||
const { headerTitle, headerIcon, headerIconColor, headerType } =
|
||||
useWorkflowActionHeader({
|
||||
action,
|
||||
defaultTitle: 'Search Records',
|
||||
defaultTitle: FIND_RECORDS_ACTION.defaultLabel,
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -151,6 +152,7 @@ export const WorkflowEditActionFindRecords = ({
|
||||
initialTitle={headerTitle}
|
||||
headerType={headerType}
|
||||
disabled={isFormDisabled}
|
||||
iconTooltip={FIND_RECORDS_ACTION.defaultLabel}
|
||||
/>
|
||||
<WorkflowStepBody>
|
||||
<Select
|
||||
|
||||
+8
-7
@@ -9,13 +9,12 @@ import { DraggableList } from '@/ui/layout/draggable-list/components/DraggableLi
|
||||
import { type WorkflowFormAction } from '@/workflow/types/Workflow';
|
||||
import { WorkflowStepBody } from '@/workflow/workflow-steps/components/WorkflowStepBody';
|
||||
import { WorkflowStepFooter } from '@/workflow/workflow-steps/components/WorkflowStepFooter';
|
||||
import { FORM_ACTION } from '@/workflow/workflow-steps/workflow-actions/constants/actions/FormAction';
|
||||
import { WorkflowEditActionFormFieldSettings } from '@/workflow/workflow-steps/workflow-actions/form-action/components/WorkflowEditActionFormFieldSettings';
|
||||
import { WorkflowFormEmptyMessage } from '@/workflow/workflow-steps/workflow-actions/form-action/components/WorkflowFormEmptyMessage';
|
||||
import { type WorkflowFormActionField } from '@/workflow/workflow-steps/workflow-actions/form-action/types/WorkflowFormActionField';
|
||||
import { getDefaultFormFieldSettings } from '@/workflow/workflow-steps/workflow-actions/form-action/utils/getDefaultFormFieldSettings';
|
||||
import { useActionHeaderTypeOrThrow } from '@/workflow/workflow-steps/workflow-actions/hooks/useActionHeaderTypeOrThrow';
|
||||
import { useActionIconColorOrThrow } from '@/workflow/workflow-steps/workflow-actions/hooks/useActionIconColorOrThrow';
|
||||
import { getActionIcon } from '@/workflow/workflow-steps/workflow-actions/utils/getActionIcon';
|
||||
import { useWorkflowActionHeader } from '@/workflow/workflow-steps/workflow-actions/hooks/useWorkflowActionHeader';
|
||||
import { css, useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { type OnDragEndResponder } from '@hello-pangea/dnd';
|
||||
@@ -142,10 +141,11 @@ export const WorkflowEditActionFormBuilder = ({
|
||||
|
||||
const [formData, setFormData] = useState<FormData>(action.settings.input);
|
||||
|
||||
const headerTitle = isDefined(action.name) ? action.name : `Form`;
|
||||
const headerIcon = getActionIcon(action.type);
|
||||
const headerIconColor = useActionIconColorOrThrow(action.type);
|
||||
const headerType = useActionHeaderTypeOrThrow(action.type);
|
||||
const { headerTitle, headerIcon, headerIconColor, headerType } =
|
||||
useWorkflowActionHeader({
|
||||
action,
|
||||
defaultTitle: FORM_ACTION.defaultLabel,
|
||||
});
|
||||
|
||||
const [selectedField, setSelectedField] = useState<string | null>(null);
|
||||
const [hoveredField, setHoveredField] = useState<string | null>(null);
|
||||
@@ -239,6 +239,7 @@ export const WorkflowEditActionFormBuilder = ({
|
||||
initialTitle={headerTitle}
|
||||
headerType={headerType}
|
||||
disabled={actionOptions.readonly}
|
||||
iconTooltip={FORM_ACTION.defaultLabel}
|
||||
/>
|
||||
<StyledWorkflowStepBody>
|
||||
{formData.length === 0 && (
|
||||
|
||||
+11
-7
@@ -10,11 +10,11 @@ import { type WorkflowFormAction } from '@/workflow/types/Workflow';
|
||||
import { WorkflowStepBody } from '@/workflow/workflow-steps/components/WorkflowStepBody';
|
||||
import { useUpdateWorkflowRunStep } from '@/workflow/workflow-steps/hooks/useUpdateWorkflowRunStep';
|
||||
import { WorkflowFormFieldInput } from '@/workflow/workflow-steps/workflow-actions/components/WorkflowFormFieldInput';
|
||||
import { FORM_ACTION } from '@/workflow/workflow-steps/workflow-actions/constants/actions/FormAction';
|
||||
import { useSubmitFormStep } from '@/workflow/workflow-steps/workflow-actions/form-action/hooks/useSubmitFormStep';
|
||||
import { type WorkflowFormActionField } from '@/workflow/workflow-steps/workflow-actions/form-action/types/WorkflowFormActionField';
|
||||
import { getDefaultFormFieldSettings } from '@/workflow/workflow-steps/workflow-actions/form-action/utils/getDefaultFormFieldSettings';
|
||||
import { getActionIcon } from '@/workflow/workflow-steps/workflow-actions/utils/getActionIcon';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import { useWorkflowActionHeader } from '@/workflow/workflow-steps/workflow-actions/hooks/useWorkflowActionHeader';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { useIcons } from 'twenty-ui/display';
|
||||
@@ -33,7 +33,6 @@ export const WorkflowEditActionFormFiller = ({
|
||||
action,
|
||||
actionOptions,
|
||||
}: WorkflowEditActionFormFillerProps) => {
|
||||
const theme = useTheme();
|
||||
const { getIcon } = useIcons();
|
||||
const { submitFormStep } = useSubmitFormStep();
|
||||
const [formData, setFormData] = useState<FormData>(action.settings.input);
|
||||
@@ -43,8 +42,12 @@ export const WorkflowEditActionFormFiller = ({
|
||||
const [error, setError] = useState<string | undefined>(undefined);
|
||||
|
||||
const canSubmit = !actionOptions.readonly && !isDefined(error);
|
||||
const headerTitle = isDefined(action.name) ? action.name : `Form`;
|
||||
const headerIcon = getActionIcon(action.type);
|
||||
|
||||
const { headerTitle, headerIcon, headerIconColor, headerType } =
|
||||
useWorkflowActionHeader({
|
||||
action,
|
||||
defaultTitle: FORM_ACTION.defaultLabel,
|
||||
});
|
||||
|
||||
const onFieldUpdate = ({
|
||||
fieldId,
|
||||
@@ -108,10 +111,11 @@ export const WorkflowEditActionFormFiller = ({
|
||||
<>
|
||||
<SidePanelHeader
|
||||
Icon={getIcon(headerIcon)}
|
||||
iconColor={theme.font.color.tertiary}
|
||||
iconColor={headerIconColor}
|
||||
initialTitle={headerTitle}
|
||||
headerType="Action"
|
||||
headerType={headerType}
|
||||
disabled
|
||||
iconTooltip={FORM_ACTION.defaultLabel}
|
||||
/>
|
||||
<WorkflowStepBody>
|
||||
{formData.map((field) => {
|
||||
|
||||
+3
-1
@@ -4,6 +4,7 @@ import { FormTextFieldInput } from '@/object-record/record-field/ui/form-types/c
|
||||
import { Select } from '@/ui/input/components/Select';
|
||||
import { type WorkflowHttpRequestAction } from '@/workflow/types/Workflow';
|
||||
import { WorkflowStepBody } from '@/workflow/workflow-steps/components/WorkflowStepBody';
|
||||
import { HTTP_REQUEST_ACTION } from '@/workflow/workflow-steps/workflow-actions/constants/actions/HttpRequestAction';
|
||||
import { useWorkflowActionHeader } from '@/workflow/workflow-steps/workflow-actions/hooks/useWorkflowActionHeader';
|
||||
|
||||
import { CmdEnterActionButton } from '@/action-menu/components/CmdEnterActionButton';
|
||||
@@ -98,7 +99,7 @@ export const WorkflowEditActionHttpRequest = ({
|
||||
const { headerTitle, headerIcon, headerIconColor, headerType } =
|
||||
useWorkflowActionHeader({
|
||||
action,
|
||||
defaultTitle: 'HTTP Request',
|
||||
defaultTitle: HTTP_REQUEST_ACTION.defaultLabel,
|
||||
});
|
||||
|
||||
const { formData, handleFieldChange, saveAction } = useHttpRequestForm({
|
||||
@@ -152,6 +153,7 @@ export const WorkflowEditActionHttpRequest = ({
|
||||
initialTitle={headerTitle}
|
||||
headerType={headerType}
|
||||
disabled={actionOptions.readonly}
|
||||
iconTooltip={HTTP_REQUEST_ACTION.defaultLabel}
|
||||
/>
|
||||
<WorkflowStepBody>
|
||||
{activeTabId === WorkflowHttpRequestTabId.CONFIGURATION && (
|
||||
|
||||
+3
-1
@@ -5,6 +5,7 @@ import { type WorkflowIteratorAction } from '@/workflow/types/Workflow';
|
||||
import { isStandaloneVariableString } from '@/workflow/utils/isStandaloneVariableString';
|
||||
import { WorkflowStepBody } from '@/workflow/workflow-steps/components/WorkflowStepBody';
|
||||
import { WorkflowStepFooter } from '@/workflow/workflow-steps/components/WorkflowStepFooter';
|
||||
import { ITERATOR_ACTION } from '@/workflow/workflow-steps/workflow-actions/constants/actions/IteratorAction';
|
||||
import { useWorkflowActionHeader } from '@/workflow/workflow-steps/workflow-actions/hooks/useWorkflowActionHeader';
|
||||
import { WorkflowVariablePicker } from '@/workflow/workflow-variables/components/WorkflowVariablePicker';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
@@ -46,7 +47,7 @@ export const WorkflowEditActionIterator = ({
|
||||
const { headerTitle, headerIcon, headerIconColor, headerType, getIcon } =
|
||||
useWorkflowActionHeader({
|
||||
action,
|
||||
defaultTitle: 'Iterator',
|
||||
defaultTitle: ITERATOR_ACTION.defaultLabel,
|
||||
});
|
||||
|
||||
const { t } = useLingui();
|
||||
@@ -119,6 +120,7 @@ export const WorkflowEditActionIterator = ({
|
||||
initialTitle={headerTitle}
|
||||
headerType={headerType}
|
||||
disabled={actionOptions.readonly}
|
||||
iconTooltip={ITERATOR_ACTION.defaultLabel}
|
||||
/>
|
||||
<WorkflowStepBody>
|
||||
<FormArrayFieldInput
|
||||
|
||||
+12
-17
@@ -1,11 +1,11 @@
|
||||
import { getActionHeaderTypeOrThrow } from '../getActionHeaderTypeOrThrow';
|
||||
|
||||
describe('getActionHeaderTypeOrThrow', () => {
|
||||
it('should return "Code" for CODE action type', () => {
|
||||
expect(getActionHeaderTypeOrThrow('CODE').message).toBe('Code');
|
||||
it('should return "Core" for CODE action type', () => {
|
||||
expect(getActionHeaderTypeOrThrow('CODE').message).toBe('Core');
|
||||
});
|
||||
|
||||
it('should return "Action" for record-related action types', () => {
|
||||
it('should return "Record" for record-related action types', () => {
|
||||
const recordActionTypes = [
|
||||
'CREATE_RECORD',
|
||||
'UPDATE_RECORD',
|
||||
@@ -14,28 +14,23 @@ describe('getActionHeaderTypeOrThrow', () => {
|
||||
] as const;
|
||||
|
||||
recordActionTypes.forEach((type) => {
|
||||
expect(getActionHeaderTypeOrThrow(type).message).toBe('Action');
|
||||
expect(getActionHeaderTypeOrThrow(type).message).toBe('Record');
|
||||
});
|
||||
});
|
||||
|
||||
it('should return "Action" for FORM action type', () => {
|
||||
expect(getActionHeaderTypeOrThrow('FORM').message).toBe('Action');
|
||||
it('should return "Human Input" for FORM action type', () => {
|
||||
expect(getActionHeaderTypeOrThrow('FORM').message).toBe('Human Input');
|
||||
});
|
||||
|
||||
it('should return "Action" for SEND_EMAIL action type', () => {
|
||||
expect(getActionHeaderTypeOrThrow('SEND_EMAIL').message).toBe('Action');
|
||||
it('should return "Core" for SEND_EMAIL action type', () => {
|
||||
expect(getActionHeaderTypeOrThrow('SEND_EMAIL').message).toBe('Core');
|
||||
});
|
||||
|
||||
it('should return "HTTP Request" for HTTP_REQUEST action type', () => {
|
||||
expect(getActionHeaderTypeOrThrow('HTTP_REQUEST').message).toBe(
|
||||
'HTTP Request',
|
||||
);
|
||||
it('should return "Core" for HTTP_REQUEST action type', () => {
|
||||
expect(getActionHeaderTypeOrThrow('HTTP_REQUEST').message).toBe('Core');
|
||||
});
|
||||
|
||||
it('should throw error for unknown action type', () => {
|
||||
// @ts-expect-error Testing invalid action type
|
||||
expect(() => getActionHeaderTypeOrThrow('UNKNOWN_ACTION')).toThrow(
|
||||
'Unsupported action type: UNKNOWN_ACTION',
|
||||
);
|
||||
it('should return "AI" for AI_AGENT action type', () => {
|
||||
expect(getActionHeaderTypeOrThrow('AI_AGENT').message).toBe('AI');
|
||||
});
|
||||
});
|
||||
|
||||
+25
-28
@@ -1,34 +1,31 @@
|
||||
import { type WorkflowActionType } from '@/workflow/types/Workflow';
|
||||
import { AI_ACTIONS } from '@/workflow/workflow-steps/workflow-actions/constants/AiActions';
|
||||
import { CORE_ACTIONS } from '@/workflow/workflow-steps/workflow-actions/constants/CoreActions';
|
||||
import { FLOW_ACTIONS } from '@/workflow/workflow-steps/workflow-actions/constants/FlowActions';
|
||||
import { HUMAN_INPUT_ACTIONS } from '@/workflow/workflow-steps/workflow-actions/constants/HumanInputActions';
|
||||
import { RECORD_ACTIONS } from '@/workflow/workflow-steps/workflow-actions/constants/RecordActions';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { assertUnreachable } from 'twenty-shared/utils';
|
||||
|
||||
export const getActionHeaderTypeOrThrow = (actionType: WorkflowActionType) => {
|
||||
switch (actionType) {
|
||||
case 'CODE':
|
||||
return msg`Code`;
|
||||
case 'CREATE_RECORD':
|
||||
case 'UPDATE_RECORD':
|
||||
case 'DELETE_RECORD':
|
||||
case 'UPSERT_RECORD':
|
||||
case 'FIND_RECORDS':
|
||||
case 'FORM':
|
||||
case 'SEND_EMAIL':
|
||||
case 'DELAY':
|
||||
return msg`Action`;
|
||||
case 'HTTP_REQUEST':
|
||||
return msg`HTTP Request`;
|
||||
case 'AI_AGENT':
|
||||
return msg`AI Agent`;
|
||||
case 'FILTER': {
|
||||
return msg`Filter`;
|
||||
}
|
||||
case 'ITERATOR': {
|
||||
return msg`Iterator`;
|
||||
}
|
||||
case 'EMPTY': {
|
||||
return msg`Add an Action`;
|
||||
}
|
||||
default:
|
||||
assertUnreachable(actionType, `Unsupported action type: ${actionType}`);
|
||||
if (FLOW_ACTIONS.some((action) => action.type === actionType)) {
|
||||
return msg`Flow`;
|
||||
}
|
||||
|
||||
if (CORE_ACTIONS.some((action) => action.type === actionType)) {
|
||||
return msg`Core`;
|
||||
}
|
||||
|
||||
if (HUMAN_INPUT_ACTIONS.some((action) => action.type === actionType)) {
|
||||
return msg`Human Input`;
|
||||
}
|
||||
|
||||
if (RECORD_ACTIONS.some((action) => action.type === actionType)) {
|
||||
return msg`Record`;
|
||||
}
|
||||
|
||||
if (AI_ACTIONS.some((action) => action.type === actionType)) {
|
||||
return msg`AI`;
|
||||
}
|
||||
|
||||
return msg`Action`;
|
||||
};
|
||||
|
||||
+1
@@ -82,6 +82,7 @@ export const WorkflowEditTriggerCronForm = ({
|
||||
initialTitle={headerTitle}
|
||||
headerType={headerType}
|
||||
disabled={triggerOptions.readonly}
|
||||
iconTooltip={getTriggerDefaultLabel(trigger)}
|
||||
/>
|
||||
<WorkflowStepBody>
|
||||
<Select
|
||||
|
||||
+1
@@ -190,6 +190,7 @@ export const WorkflowEditTriggerDatabaseEventForm = ({
|
||||
initialTitle={defaultLabel}
|
||||
headerType={headerType}
|
||||
disabled={triggerOptions.readonly}
|
||||
iconTooltip={getTriggerDefaultLabel(trigger)}
|
||||
/>
|
||||
<WorkflowStepBody>
|
||||
<StyledRecordTypeSelectContainer fullWidth>
|
||||
|
||||
+1
@@ -104,6 +104,7 @@ export const WorkflowEditTriggerManual = ({
|
||||
initialTitle={headerTitle}
|
||||
headerType={headerType}
|
||||
disabled={triggerOptions.readonly}
|
||||
iconTooltip={getTriggerDefaultLabel(trigger)}
|
||||
/>
|
||||
<WorkflowStepBody>
|
||||
<Select
|
||||
|
||||
+1
@@ -105,6 +105,7 @@ export const WorkflowEditTriggerWebhookForm = ({
|
||||
initialTitle={headerTitle}
|
||||
headerType={headerType}
|
||||
disabled={triggerOptions.readonly}
|
||||
iconTooltip={getTriggerDefaultLabel(trigger)}
|
||||
/>
|
||||
<WorkflowStepBody>
|
||||
<TextInput
|
||||
|
||||
+9
-25
@@ -1,5 +1,9 @@
|
||||
import { type WorkflowTriggerType } from '@/workflow/types/Workflow';
|
||||
import { DatabaseTriggerDefaultLabel } from '@/workflow/workflow-trigger/constants/DatabaseTriggerDefaultLabel';
|
||||
import { type DatabaseTriggerDefaultLabel } from '@/workflow/workflow-trigger/constants/DatabaseTriggerDefaultLabel';
|
||||
import { RECORD_IS_CREATED_TRIGGER } from '@/workflow/workflow-trigger/constants/triggers/RecordIsCreatedTrigger';
|
||||
import { RECORD_IS_DELETED_TRIGGER } from '@/workflow/workflow-trigger/constants/triggers/RecordIsDeletedTrigger';
|
||||
import { RECORD_IS_UPDATED_TRIGGER } from '@/workflow/workflow-trigger/constants/triggers/RecordIsUpdatedTrigger';
|
||||
import { RECORD_UPSERTED_TRIGGER } from '@/workflow/workflow-trigger/constants/triggers/RecordUpsertedTrigger';
|
||||
|
||||
export const DATABASE_TRIGGER_TYPES: Array<{
|
||||
defaultLabel: DatabaseTriggerDefaultLabel;
|
||||
@@ -7,28 +11,8 @@ export const DATABASE_TRIGGER_TYPES: Array<{
|
||||
icon: string;
|
||||
event: string;
|
||||
}> = [
|
||||
{
|
||||
defaultLabel: DatabaseTriggerDefaultLabel.RECORD_IS_CREATED,
|
||||
type: 'DATABASE_EVENT',
|
||||
icon: 'IconPlaylistAdd',
|
||||
event: 'created',
|
||||
},
|
||||
{
|
||||
defaultLabel: DatabaseTriggerDefaultLabel.RECORD_IS_UPDATED,
|
||||
type: 'DATABASE_EVENT',
|
||||
icon: 'IconRefreshDot',
|
||||
event: 'updated',
|
||||
},
|
||||
{
|
||||
defaultLabel: DatabaseTriggerDefaultLabel.RECORD_IS_DELETED,
|
||||
type: 'DATABASE_EVENT',
|
||||
icon: 'IconTrash',
|
||||
event: 'deleted',
|
||||
},
|
||||
{
|
||||
defaultLabel: DatabaseTriggerDefaultLabel.RECORD_UPSERTED,
|
||||
type: 'DATABASE_EVENT',
|
||||
icon: 'IconPencilPlus',
|
||||
event: 'upserted',
|
||||
},
|
||||
RECORD_IS_CREATED_TRIGGER,
|
||||
RECORD_IS_UPDATED_TRIGGER,
|
||||
RECORD_IS_DELETED_TRIGGER,
|
||||
RECORD_UPSERTED_TRIGGER,
|
||||
];
|
||||
|
||||
+4
-17
@@ -1,23 +1,10 @@
|
||||
import { type WorkflowTriggerType } from '@/workflow/types/Workflow';
|
||||
import { CRON_TRIGGER } from '@/workflow/workflow-trigger/constants/triggers/CronTrigger';
|
||||
import { MANUAL_TRIGGER } from '@/workflow/workflow-trigger/constants/triggers/ManualTrigger';
|
||||
import { WEBHOOK_TRIGGER } from '@/workflow/workflow-trigger/constants/triggers/WebhookTrigger';
|
||||
|
||||
export const OTHER_TRIGGER_TYPES: Array<{
|
||||
defaultLabel: string;
|
||||
type: WorkflowTriggerType;
|
||||
icon: string;
|
||||
}> = [
|
||||
{
|
||||
defaultLabel: 'Launch manually',
|
||||
type: 'MANUAL',
|
||||
icon: 'IconHandMove',
|
||||
},
|
||||
{
|
||||
defaultLabel: 'On a schedule',
|
||||
type: 'CRON',
|
||||
icon: 'IconClock',
|
||||
},
|
||||
{
|
||||
defaultLabel: 'Webhook',
|
||||
type: 'WEBHOOK',
|
||||
icon: 'IconWebhook',
|
||||
},
|
||||
];
|
||||
}> = [MANUAL_TRIGGER, CRON_TRIGGER, WEBHOOK_TRIGGER];
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { type WorkflowTriggerType } from '@/workflow/types/Workflow';
|
||||
|
||||
export const CRON_TRIGGER: {
|
||||
defaultLabel: string;
|
||||
type: WorkflowTriggerType;
|
||||
icon: string;
|
||||
} = {
|
||||
defaultLabel: 'On a schedule',
|
||||
type: 'CRON',
|
||||
icon: 'IconClock',
|
||||
};
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { type WorkflowTriggerType } from '@/workflow/types/Workflow';
|
||||
|
||||
export const MANUAL_TRIGGER: {
|
||||
defaultLabel: string;
|
||||
type: WorkflowTriggerType;
|
||||
icon: string;
|
||||
} = {
|
||||
defaultLabel: 'Launch manually',
|
||||
type: 'MANUAL',
|
||||
icon: 'IconHandMove',
|
||||
};
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
import { type WorkflowTriggerType } from '@/workflow/types/Workflow';
|
||||
import { DatabaseTriggerDefaultLabel } from '@/workflow/workflow-trigger/constants/DatabaseTriggerDefaultLabel';
|
||||
|
||||
export const RECORD_IS_CREATED_TRIGGER: {
|
||||
defaultLabel: DatabaseTriggerDefaultLabel;
|
||||
type: WorkflowTriggerType;
|
||||
icon: string;
|
||||
event: string;
|
||||
} = {
|
||||
defaultLabel: DatabaseTriggerDefaultLabel.RECORD_IS_CREATED,
|
||||
type: 'DATABASE_EVENT',
|
||||
icon: 'IconPlaylistAdd',
|
||||
event: 'created',
|
||||
};
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
import { type WorkflowTriggerType } from '@/workflow/types/Workflow';
|
||||
import { DatabaseTriggerDefaultLabel } from '@/workflow/workflow-trigger/constants/DatabaseTriggerDefaultLabel';
|
||||
|
||||
export const RECORD_IS_DELETED_TRIGGER: {
|
||||
defaultLabel: DatabaseTriggerDefaultLabel;
|
||||
type: WorkflowTriggerType;
|
||||
icon: string;
|
||||
event: string;
|
||||
} = {
|
||||
defaultLabel: DatabaseTriggerDefaultLabel.RECORD_IS_DELETED,
|
||||
type: 'DATABASE_EVENT',
|
||||
icon: 'IconTrash',
|
||||
event: 'deleted',
|
||||
};
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
import { type WorkflowTriggerType } from '@/workflow/types/Workflow';
|
||||
import { DatabaseTriggerDefaultLabel } from '@/workflow/workflow-trigger/constants/DatabaseTriggerDefaultLabel';
|
||||
|
||||
export const RECORD_IS_UPDATED_TRIGGER: {
|
||||
defaultLabel: DatabaseTriggerDefaultLabel;
|
||||
type: WorkflowTriggerType;
|
||||
icon: string;
|
||||
event: string;
|
||||
} = {
|
||||
defaultLabel: DatabaseTriggerDefaultLabel.RECORD_IS_UPDATED,
|
||||
type: 'DATABASE_EVENT',
|
||||
icon: 'IconRefreshDot',
|
||||
event: 'updated',
|
||||
};
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
import { type WorkflowTriggerType } from '@/workflow/types/Workflow';
|
||||
import { DatabaseTriggerDefaultLabel } from '@/workflow/workflow-trigger/constants/DatabaseTriggerDefaultLabel';
|
||||
|
||||
export const RECORD_UPSERTED_TRIGGER: {
|
||||
defaultLabel: DatabaseTriggerDefaultLabel;
|
||||
type: WorkflowTriggerType;
|
||||
icon: string;
|
||||
event: string;
|
||||
} = {
|
||||
defaultLabel: DatabaseTriggerDefaultLabel.RECORD_UPSERTED,
|
||||
type: 'DATABASE_EVENT',
|
||||
icon: 'IconPencilPlus',
|
||||
event: 'upserted',
|
||||
};
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { type WorkflowTriggerType } from '@/workflow/types/Workflow';
|
||||
|
||||
export const WEBHOOK_TRIGGER: {
|
||||
defaultLabel: string;
|
||||
type: WorkflowTriggerType;
|
||||
icon: string;
|
||||
} = {
|
||||
defaultLabel: 'Webhook',
|
||||
type: 'WEBHOOK',
|
||||
icon: 'IconWebhook',
|
||||
};
|
||||
+4
-4
@@ -115,7 +115,7 @@ describe('getTriggerHeaderType', () => {
|
||||
|
||||
const result = getTriggerHeaderType(trigger);
|
||||
|
||||
expect(result).toBe('Trigger');
|
||||
expect(result).toBe('Trigger · Cron');
|
||||
});
|
||||
|
||||
it('returns "Trigger" for cron trigger with HOURS schedule', () => {
|
||||
@@ -134,7 +134,7 @@ describe('getTriggerHeaderType', () => {
|
||||
|
||||
const result = getTriggerHeaderType(trigger);
|
||||
|
||||
expect(result).toBe('Trigger');
|
||||
expect(result).toBe('Trigger · Cron');
|
||||
});
|
||||
|
||||
it('returns "Trigger" for cron trigger with MINUTES schedule', () => {
|
||||
@@ -152,7 +152,7 @@ describe('getTriggerHeaderType', () => {
|
||||
|
||||
const result = getTriggerHeaderType(trigger);
|
||||
|
||||
expect(result).toBe('Trigger');
|
||||
expect(result).toBe('Trigger · Cron');
|
||||
});
|
||||
|
||||
it('returns "Trigger" for cron trigger with CUSTOM schedule', () => {
|
||||
@@ -168,7 +168,7 @@ describe('getTriggerHeaderType', () => {
|
||||
|
||||
const result = getTriggerHeaderType(trigger);
|
||||
|
||||
expect(result).toBe('Trigger');
|
||||
expect(result).toBe('Trigger · Cron');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ import { assertUnreachable } from 'twenty-shared/utils';
|
||||
export const getTriggerHeaderType = (trigger: WorkflowTrigger) => {
|
||||
switch (trigger.type) {
|
||||
case 'CRON': {
|
||||
return 'Trigger';
|
||||
return 'Trigger · Cron';
|
||||
}
|
||||
case 'WEBHOOK': {
|
||||
return 'Trigger · Webhook';
|
||||
|
||||
Reference in New Issue
Block a user