Only display Flow for Workflow Runs and display Output tab for triggers (#11520)

> [!WARNING]
> I refactored a bunch of components into utility functions to make it
possible to display the `WorkflowStepHeader` component for **triggers**
in the `CommandMenuWorkflowRunViewStep` component. Previously, we were
asserting that we were displaying the header in `Output` and `Input`
tabs only for **actions**. Handling triggers too required a bunch of
changes. We can think of making a bigger refactor of this part.

In this PR:

- Only display the Flow for Workflow Runs; removed the Code Editor tab
- Allows users to see the Output of trigger nodes
- Prevent impossible states by manually setting the selected tab when
selecting a node

## Demo

### Success, Running and Not Executed steps


https://github.com/user-attachments/assets/c6bebd0f-5da2-4ccc-aef2-d9890eafa59a

### Failed step


https://github.com/user-attachments/assets/e1f4e13a-2f5e-4792-a089-928e4d6b1ac0

Closes https://github.com/twentyhq/core-team-issues/issues/709
This commit is contained in:
Baptiste Devessier
2025-04-11 14:31:34 +02:00
committed by GitHub
parent c8011da4d7
commit e8488e1da0
25 changed files with 268 additions and 234 deletions

View File

@ -20,7 +20,6 @@ import { getShowPageTabListComponentId } from '@/ui/layout/show-page/utils/getSh
import { activeTabIdComponentState } from '@/ui/layout/tab/states/activeTabIdComponentState';
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
import { WORKFLOW_RUN_STEP_SIDE_PANEL_TAB_LIST_COMPONENT_ID } from '@/workflow/workflow-steps/constants/WorkflowRunStepSidePanelTabListComponentId';
import { WorkflowRunTabId } from '@/workflow/workflow-steps/types/WorkflowRunTabId';
import { WORKFLOW_SERVERLESS_FUNCTION_TAB_LIST_COMPONENT_ID } from '@/workflow/workflow-steps/workflow-actions/code-action/constants/WorkflowServerlessFunctionTabListComponentId';
import { WorkflowServerlessFunctionTabId } from '@/workflow/workflow-steps/workflow-actions/code-action/types/WorkflowServerlessFunctionTabId';
import { useRecoilCallback } from 'recoil';
@ -66,7 +65,7 @@ export const useCommandMenuCloseAnimationCompleteCleanup = () => {
activeTabIdComponentState.atomFamily({
instanceId: WORKFLOW_RUN_STEP_SIDE_PANEL_TAB_LIST_COMPONENT_ID,
}),
WorkflowRunTabId.NODE,
null,
);
set(
activeTabIdComponentState.atomFamily({

View File

@ -1,3 +1,5 @@
import { getIsInputTabDisabled } from '@/command-menu/pages/workflow/step/view-run/utils/getIsInputTabDisabled';
import { getIsOutputTabDisabled } from '@/command-menu/pages/workflow/step/view-run/utils/getIsOutputTabDisabled';
import { SingleTabProps, TabList } from '@/ui/layout/tab/components/TabList';
import { activeTabIdComponentState } from '@/ui/layout/tab/states/activeTabIdComponentState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
@ -15,7 +17,6 @@ import {
WorkflowRunTabIdType,
} from '@/workflow/workflow-steps/types/WorkflowRunTabId';
import { getWorkflowRunStepExecutionStatus } from '@/workflow/workflow-steps/utils/getWorkflowRunStepExecutionStatus';
import { TRIGGER_STEP_ID } from '@/workflow/workflow-trigger/constants/TriggerStepId';
import styled from '@emotion/styled';
import { isDefined } from 'twenty-shared/utils';
import { IconLogin2, IconLogout, IconStepInto } from 'twenty-ui/display';
@ -45,38 +46,39 @@ export const CommandMenuWorkflowRunViewStep = () => {
WORKFLOW_RUN_STEP_SIDE_PANEL_TAB_LIST_COMPONENT_ID,
);
const stepExecutionStatus = isDefined(workflowRun)
? getWorkflowRunStepExecutionStatus({
workflowRunOutput: workflowRun.output,
stepId: workflowSelectedNode,
})
: undefined;
if (!isDefined(workflowRun)) {
return null;
}
const areInputAndOutputTabsDisabled =
workflowSelectedNode === TRIGGER_STEP_ID ||
stepExecutionStatus === 'running' ||
stepExecutionStatus === 'not-executed';
const stepExecutionStatus = getWorkflowRunStepExecutionStatus({
workflowRunOutput: workflowRun.output,
stepId: workflowSelectedNode,
});
const isInputTabDisabled = getIsInputTabDisabled({
stepExecutionStatus,
workflowSelectedNode,
});
const isOutputTabDisabled = getIsOutputTabDisabled({
stepExecutionStatus,
});
const tabs: SingleTabProps<TabId>[] = [
{
id: WorkflowRunTabId.OUTPUT,
title: 'Output',
Icon: IconLogout,
disabled: isOutputTabDisabled,
},
{ id: WorkflowRunTabId.NODE, title: 'Node', Icon: IconStepInto },
{
id: WorkflowRunTabId.INPUT,
title: 'Input',
Icon: IconLogin2,
disabled: areInputAndOutputTabsDisabled,
},
{
id: WorkflowRunTabId.OUTPUT,
title: 'Output',
Icon: IconLogout,
disabled: areInputAndOutputTabsDisabled,
disabled: isInputTabDisabled,
},
];
if (!isDefined(workflowRun)) {
return null;
}
return (
<WorkflowStepContextProvider
value={{
@ -93,6 +95,13 @@ export const CommandMenuWorkflowRunViewStep = () => {
}
/>
{activeTabId === WorkflowRunTabId.OUTPUT ? (
<WorkflowRunStepOutputDetail
key={workflowSelectedNode}
stepId={workflowSelectedNode}
/>
) : null}
{activeTabId === WorkflowRunTabId.NODE ? (
<WorkflowRunStepNodeDetail
stepId={workflowSelectedNode}
@ -108,13 +117,6 @@ export const CommandMenuWorkflowRunViewStep = () => {
stepId={workflowSelectedNode}
/>
) : null}
{activeTabId === WorkflowRunTabId.OUTPUT ? (
<WorkflowRunStepOutputDetail
key={workflowSelectedNode}
stepId={workflowSelectedNode}
/>
) : null}
</StyledContainer>
</WorkflowStepContextProvider>
);

View File

@ -0,0 +1,15 @@
import { WorkflowDiagramRunStatus } from '@/workflow/workflow-diagram/types/WorkflowDiagram';
import { TRIGGER_STEP_ID } from '@/workflow/workflow-trigger/constants/TriggerStepId';
export const getIsInputTabDisabled = ({
stepExecutionStatus,
workflowSelectedNode,
}: {
workflowSelectedNode: string;
stepExecutionStatus: WorkflowDiagramRunStatus;
}) => {
return (
workflowSelectedNode === TRIGGER_STEP_ID ||
stepExecutionStatus === 'not-executed'
);
};

View File

@ -0,0 +1,11 @@
import { WorkflowDiagramRunStatus } from '@/workflow/workflow-diagram/types/WorkflowDiagram';
export const getIsOutputTabDisabled = ({
stepExecutionStatus,
}: {
stepExecutionStatus: WorkflowDiagramRunStatus;
}) => {
return (
stepExecutionStatus === 'running' || stepExecutionStatus === 'not-executed'
);
};