Workflow command menu fixes (#15234)

- Move trash button to command menu footer
<img width="132" height="102" alt="Capture d’écran 2025-10-21 à 18 12
19"
src="https://github.com/user-attachments/assets/ad6a9374-a28f-4498-b8f3-ca576981693c"
/>

- Add footer to triggers + on missing steps
- Catch step body errors so the user can still delete the step when an
error happens
<img width="529" height="419" alt="Capture d’écran 2025-10-21 à 18 13
17"
src="https://github.com/user-attachments/assets/0ac07511-f4ad-40c4-98f1-afb53c0f7a89"
/>
This commit is contained in:
Thomas Trompette
2025-10-22 10:17:06 +02:00
committed by GitHub
parent c5564d9bd0
commit bf3c3fc5a5
32 changed files with 136 additions and 92 deletions
@@ -30,7 +30,7 @@ export const COMMAND_MENU_PAGES_CONFIG = new Map<
[CommandMenuPages.ViewCalendarEvent, <CommandMenuCalendarEventPage />],
[CommandMenuPages.EditRichText, <CommandMenuEditRichTextPage />],
[
CommandMenuPages.WorkflowStepSelectTriggerType,
CommandMenuPages.WorkflowTriggerSelectType,
<CommandMenuWorkflowSelectTriggerType />,
],
[CommandMenuPages.WorkflowStepCreate, <CommandMenuWorkflowCreateStep />],
@@ -147,7 +147,7 @@ describe('useWorkflowCommandMenu', () => {
expect(result.current.workflowId).toBe('test-workflow-id');
expect(mockNavigateCommandMenu).toHaveBeenCalledWith({
page: CommandMenuPages.WorkflowStepSelectTriggerType,
page: CommandMenuPages.WorkflowTriggerSelectType,
pageTitle: t`Trigger Type`,
pageIcon: IconBolt,
pageId: 'mocked-uuid',
@@ -32,7 +32,7 @@ export const useWorkflowCommandMenu = () => {
);
navigateCommandMenu({
page: CommandMenuPages.WorkflowStepSelectTriggerType,
page: CommandMenuPages.WorkflowTriggerSelectType,
pageTitle: t`Trigger Type`,
pageIcon: IconBolt,
pageId,
@@ -13,7 +13,6 @@ import { useWorkflowRun } from '@/workflow/hooks/useWorkflowRun';
import { useWorkflowRunIdOrThrow } from '@/workflow/hooks/useWorkflowRunIdOrThrow';
import { getStepDefinitionOrThrow } from '@/workflow/utils/getStepDefinitionOrThrow';
import { workflowSelectedNodeComponentState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeComponentState';
import { WorkflowIteratorSubStepSwitcher } from '@/workflow/workflow-steps/components/WorkflowIteratorSubStepSwitcher';
import { WorkflowRunStepInputDetail } from '@/workflow/workflow-steps/components/WorkflowRunStepInputDetail';
import { WorkflowRunStepNodeDetail } from '@/workflow/workflow-steps/components/WorkflowRunStepNodeDetail';
import { WorkflowRunStepOutputDetail } from '@/workflow/workflow-steps/components/WorkflowRunStepOutputDetail';
@@ -22,6 +21,7 @@ import {
type WorkflowRunTabIdType,
} from '@/workflow/workflow-steps/types/WorkflowRunTabId';
import { getWorkflowRunStepExecutionStatus } from '@/workflow/workflow-steps/utils/getWorkflowRunStepExecutionStatus';
import { WorkflowIteratorSubStepSwitcher } from '@/workflow/workflow-steps/workflow-actions/iterator-action/components/WorkflowIteratorSubStepSwitcher';
import styled from '@emotion/styled';
import { isNull } from '@sniptt/guards';
import { isDefined } from 'twenty-shared/utils';
@@ -1,17 +1,10 @@
import { useCommandMenuWorkflowIdOrThrow } from '@/command-menu/pages/workflow/hooks/useCommandMenuWorkflowIdOrThrow';
import { CommandMenuWorkflowSelectTriggerTypeContent } from '@/command-menu/pages/workflow/trigger-type/components/CommandMenuWorkflowSelectTriggerTypeContent';
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
import { getWorkflowVisualizerComponentInstanceId } from '@/workflow/utils/getWorkflowVisualizerComponentInstanceId';
import { WorkflowVisualizerComponentInstanceContext } from '@/workflow/workflow-diagram/states/contexts/WorkflowVisualizerComponentInstanceContext';
import { isDefined } from 'twenty-shared/utils';
export const CommandMenuWorkflowSelectTriggerType = () => {
const workflowId = useCommandMenuWorkflowIdOrThrow();
const workflow = useWorkflowWithCurrentVersion(workflowId);
if (!isDefined(workflow)) {
return null;
}
return (
<WorkflowVisualizerComponentInstanceContext.Provider
@@ -21,7 +14,7 @@ export const CommandMenuWorkflowSelectTriggerType = () => {
}),
}}
>
<CommandMenuWorkflowSelectTriggerTypeContent workflow={workflow} />
<CommandMenuWorkflowSelectTriggerTypeContent />
</WorkflowVisualizerComponentInstanceContext.Provider>
);
};
@@ -1,9 +1,11 @@
import { useWorkflowCommandMenu } from '@/command-menu/hooks/useWorkflowCommandMenu';
import { useCommandMenuWorkflowIdOrThrow } from '@/command-menu/pages/workflow/hooks/useCommandMenuWorkflowIdOrThrow';
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
import { useFlowOrThrow } from '@/workflow/hooks/useFlowOrThrow';
import {
type WorkflowTrigger,
type WorkflowTriggerType,
type WorkflowWithCurrentVersion,
} from '@/workflow/types/Workflow';
import { workflowSelectedNodeComponentState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeComponentState';
import { RightDrawerStepListContainer } from '@/workflow/workflow-steps/components/RightDrawerWorkflowSelectStepContainer';
@@ -13,16 +15,14 @@ import { OTHER_TRIGGER_TYPES } from '@/workflow/workflow-trigger/constants/Other
import { useUpdateWorkflowVersionTrigger } from '@/workflow/workflow-trigger/hooks/useUpdateWorkflowVersionTrigger';
import { getTriggerDefaultDefinition } from '@/workflow/workflow-trigger/utils/getTriggerDefaultDefinition';
import { useTheme } from '@emotion/react';
import { isDefined } from 'twenty-shared/utils';
import { TRIGGER_STEP_ID } from 'twenty-shared/workflow';
import { useIcons } from 'twenty-ui/display';
import { MenuItem } from 'twenty-ui/navigation';
export const CommandMenuWorkflowSelectTriggerTypeContent = ({
workflow,
}: {
workflow: WorkflowWithCurrentVersion;
}) => {
export const CommandMenuWorkflowSelectTriggerTypeContent = () => {
const { getIcon } = useIcons();
const workflowId = useCommandMenuWorkflowIdOrThrow();
const { updateTrigger } = useUpdateWorkflowVersionTrigger();
const { activeNonSystemObjectMetadataItems } =
@@ -32,6 +32,7 @@ export const CommandMenuWorkflowSelectTriggerTypeContent = ({
workflowSelectedNodeComponentState,
);
const { openWorkflowEditStepInCommandMenu } = useWorkflowCommandMenu();
const flow = useFlowOrThrow();
const handleTriggerTypeClick = ({
type,
@@ -43,18 +44,26 @@ export const CommandMenuWorkflowSelectTriggerTypeContent = ({
icon: string;
}) => {
return async () => {
await updateTrigger(
getTriggerDefaultDefinition({
defaultLabel,
type,
activeNonSystemObjectMetadataItems,
}),
);
let updatedTrigger: WorkflowTrigger | null = getTriggerDefaultDefinition({
defaultLabel,
type,
activeNonSystemObjectMetadataItems,
});
if (isDefined(flow.trigger)) {
updatedTrigger = {
...updatedTrigger,
position: flow.trigger.position,
nextStepIds: flow.trigger.nextStepIds,
};
}
await updateTrigger(updatedTrigger);
setWorkflowSelectedNode(TRIGGER_STEP_ID);
openWorkflowEditStepInCommandMenu(
workflow.id,
workflowId,
defaultLabel,
getIcon(icon),
);
@@ -6,7 +6,7 @@ export enum CommandMenuPages {
ViewCalendarEvent = 'view-calendar-event',
EditRichText = 'edit-rich-text',
Copilot = 'copilot',
WorkflowStepSelectTriggerType = 'workflow-step-select-trigger-type',
WorkflowTriggerSelectType = 'workflow-trigger-select-type',
WorkflowStepCreate = 'workflow-step-create',
WorkflowStepEditType = 'workflow-step-edit-type',
WorkflowStepView = 'workflow-step-view',