From b49ec864b14057b970d7b07a4acb4d4153cb39fc Mon Sep 17 00:00:00 2001 From: Baptiste Devessier Date: Fri, 7 Mar 2025 17:35:39 +0100 Subject: [PATCH] Visualize workflow run step output (#10730) - Displays the output of the selected step in the `Output` tab - Access to the `Output` tab is prevented when the selected node is currently executed or was skipped - Display the status of the workflow run instead of the status of the workflow version at the top left corner of the workflow run visualizer - Fixed the icon's color for disabled tabs - Use text/primary color for the step's name even when the input is disabled ## Demo: Successful execution https://github.com/user-attachments/assets/02e492f3-1589-48e9-926e-7edb031d9210 ## Demo: Failed execution https://github.com/user-attachments/assets/73e5ec86-5f38-4306-aa9a-46b2e73950da Closes https://github.com/twentyhq/core-team-issues/issues/434 --- .../modules/ui/layout/tab/components/Tab.tsx | 4 +- .../components/WorkflowRunVisualizer.tsx | 4 +- .../WorkflowRunVisualizerContent.tsx | 17 ------- .../src/modules/workflow/types/Workflow.ts | 3 ++ .../validation-schemas/workflowSchema.ts | 8 ++++ .../components/WorkflowDiagramCanvasBase.tsx | 20 ++++---- .../WorkflowDiagramCanvasEditable.tsx | 10 +++- .../WorkflowDiagramCanvasReadonly.tsx | 10 +++- .../components/WorkflowRunDiagramCanvas.tsx | 15 ++++-- .../WorkflowRunDiagramCanvasEffect.tsx | 5 +- .../components/WorkflowVersionStatusTag.tsx | 22 --------- .../WorkflowDiagramCustomMarkers.stories.tsx | 2 - .../WorkflowVersionStatusTag.stories.tsx | 43 ----------------- .../utils/getWorkflowRunStatusTagProps.ts | 34 +++++++++++++ .../utils/getWorkflowVersionStatusTagProps.ts | 34 +++++++++++++ .../RightDrawerWorkflowRunViewStep.tsx | 16 +++++-- .../WorkflowRunStepOutputDetail.tsx | 27 +++++++++++ .../components/WorkflowStepHeader.tsx | 4 ++ ...RightDrawerWorkflowRunViewStep.stories.tsx | 48 ++++++++++++++++++- 19 files changed, 219 insertions(+), 107 deletions(-) delete mode 100644 packages/twenty-front/src/modules/workflow/components/WorkflowRunVisualizerContent.tsx delete mode 100644 packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowVersionStatusTag.tsx delete mode 100644 packages/twenty-front/src/modules/workflow/workflow-diagram/components/__stories__/WorkflowVersionStatusTag.stories.tsx create mode 100644 packages/twenty-front/src/modules/workflow/workflow-diagram/utils/getWorkflowRunStatusTagProps.ts create mode 100644 packages/twenty-front/src/modules/workflow/workflow-diagram/utils/getWorkflowVersionStatusTagProps.ts create mode 100644 packages/twenty-front/src/modules/workflow/workflow-steps/components/WorkflowRunStepOutputDetail.tsx diff --git a/packages/twenty-front/src/modules/ui/layout/tab/components/Tab.tsx b/packages/twenty-front/src/modules/ui/layout/tab/components/Tab.tsx index 68c7c7a62..6474b4a9b 100644 --- a/packages/twenty-front/src/modules/ui/layout/tab/components/Tab.tsx +++ b/packages/twenty-front/src/modules/ui/layout/tab/components/Tab.tsx @@ -83,7 +83,9 @@ export const Tab = ({ const theme = useTheme(); const iconColor = active ? theme.font.color.primary - : theme.font.color.secondary; + : disabled + ? theme.font.color.light + : theme.font.color.secondary; return ( - + ); }; diff --git a/packages/twenty-front/src/modules/workflow/components/WorkflowRunVisualizerContent.tsx b/packages/twenty-front/src/modules/workflow/components/WorkflowRunVisualizerContent.tsx deleted file mode 100644 index eb2afbcec..000000000 --- a/packages/twenty-front/src/modules/workflow/components/WorkflowRunVisualizerContent.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { useWorkflowVersion } from '@/workflow/hooks/useWorkflowVersion'; -import { WorkflowRun } from '@/workflow/types/Workflow'; -import { WorkflowRunDiagramCanvas } from '@/workflow/workflow-diagram/components/WorkflowRunDiagramCanvas'; -import { isDefined } from 'twenty-shared'; - -export const WorkflowRunVisualizerContent = ({ - workflowRun, -}: { - workflowRun: WorkflowRun; -}) => { - const workflowVersion = useWorkflowVersion(workflowRun.workflowVersionId); - if (!isDefined(workflowVersion)) { - return null; - } - - return ; -}; diff --git a/packages/twenty-front/src/modules/workflow/types/Workflow.ts b/packages/twenty-front/src/modules/workflow/types/Workflow.ts index 44c9b6104..6b96fd16d 100644 --- a/packages/twenty-front/src/modules/workflow/types/Workflow.ts +++ b/packages/twenty-front/src/modules/workflow/types/Workflow.ts @@ -15,6 +15,7 @@ import { workflowRunOutputSchema, workflowRunOutputStepsOutputSchema, workflowRunSchema, + workflowRunStatusSchema, workflowSendEmailActionSchema, workflowSendEmailActionSettingsSchema, workflowTriggerSchema, @@ -107,6 +108,8 @@ export type WorkflowRunContext = z.infer; export type WorkflowRunFlow = WorkflowRunOutput['flow']; +export type WorkflowRunStatus = z.infer; + export type WorkflowRun = z.infer; export type Workflow = { diff --git a/packages/twenty-front/src/modules/workflow/validation-schemas/workflowSchema.ts b/packages/twenty-front/src/modules/workflow/validation-schemas/workflowSchema.ts index b6ab3b21a..13eaa986b 100644 --- a/packages/twenty-front/src/modules/workflow/validation-schemas/workflowSchema.ts +++ b/packages/twenty-front/src/modules/workflow/validation-schemas/workflowSchema.ts @@ -197,6 +197,13 @@ export const workflowRunOutputSchema = z.object({ export const workflowRunContextSchema = z.record(z.any()); +export const workflowRunStatusSchema = z.enum([ + 'NOT_STARTED', + 'RUNNING', + 'COMPLETED', + 'FAILED', +]); + export const workflowRunSchema = z .object({ __typename: z.literal('WorkflowRun'), @@ -204,6 +211,7 @@ export const workflowRunSchema = z workflowVersionId: z.string(), output: workflowRunOutputSchema.nullable(), context: workflowRunContextSchema.nullable(), + status: workflowRunStatusSchema, createdAt: z.string(), deletedAt: z.string().nullable(), endedAt: z.string().nullable(), diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCanvasBase.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCanvasBase.tsx index 02c32427f..add12217e 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCanvasBase.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCanvasBase.tsx @@ -1,8 +1,6 @@ import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu'; import { useListenRightDrawerClose } from '@/ui/layout/right-drawer/hooks/useListenRightDrawerClose'; -import { WorkflowVersionStatus } from '@/workflow/types/Workflow'; import { WorkflowDiagramCustomMarkers } from '@/workflow/workflow-diagram/components/WorkflowDiagramCustomMarkers'; -import { WorkflowVersionStatusTag } from '@/workflow/workflow-diagram/components/WorkflowVersionStatusTag'; import { useRightDrawerState } from '@/workflow/workflow-diagram/hooks/useRightDrawerState'; import { workflowDiagramState } from '@/workflow/workflow-diagram/states/workflowDiagramState'; import { workflowReactFlowRefState } from '@/workflow/workflow-diagram/states/workflowReactFlowRefState'; @@ -16,6 +14,8 @@ import { getOrganizedDiagram } from '@/workflow/workflow-diagram/utils/getOrgani import { useTheme } from '@emotion/react'; import styled from '@emotion/styled'; import { + applyEdgeChanges, + applyNodeChanges, Background, EdgeChange, EdgeProps, @@ -23,15 +23,13 @@ import { NodeChange, NodeProps, ReactFlow, - applyEdgeChanges, - applyNodeChanges, useReactFlow, } from '@xyflow/react'; import '@xyflow/react/dist/style.css'; import React, { useEffect, useMemo, useRef } from 'react'; import { useRecoilValue, useSetRecoilState } from 'recoil'; import { isDefined } from 'twenty-shared'; -import { THEME_COMMON } from 'twenty-ui'; +import { Tag, TagColor, THEME_COMMON } from 'twenty-ui'; const StyledResetReactflowStyles = styled.div` height: 100%; @@ -83,12 +81,13 @@ const defaultFitViewOptions = { } satisfies FitViewOptions; export const WorkflowDiagramCanvasBase = ({ - status, nodeTypes, edgeTypes, children, + tagContainerTestId, + tagColor, + tagText, }: { - status: WorkflowVersionStatus; nodeTypes: Partial< Record< WorkflowDiagramNodeType, @@ -112,6 +111,9 @@ export const WorkflowDiagramCanvasBase = ({ > >; children?: React.ReactNode; + tagContainerTestId: string; + tagColor: TagColor; + tagText: string; }) => { const theme = useTheme(); @@ -258,8 +260,8 @@ export const WorkflowDiagramCanvasBase = ({ {children} - - + + ); diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCanvasEditable.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCanvasEditable.tsx index 5fbcad3a4..db22a3440 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCanvasEditable.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCanvasEditable.tsx @@ -5,6 +5,7 @@ import { WorkflowDiagramCreateStepNode } from '@/workflow/workflow-diagram/compo import { WorkflowDiagramDefaultEdge } from '@/workflow/workflow-diagram/components/WorkflowDiagramDefaultEdge'; import { WorkflowDiagramEmptyTrigger } from '@/workflow/workflow-diagram/components/WorkflowDiagramEmptyTrigger'; import { WorkflowDiagramStepNodeEditable } from '@/workflow/workflow-diagram/components/WorkflowDiagramStepNodeEditable'; +import { getWorkflowVersionStatusTagProps } from '@/workflow/workflow-diagram/utils/getWorkflowVersionStatusTagProps'; import { ReactFlowProvider } from '@xyflow/react'; export const WorkflowDiagramCanvasEditable = ({ @@ -12,10 +13,13 @@ export const WorkflowDiagramCanvasEditable = ({ }: { versionStatus: WorkflowVersionStatus; }) => { + const tagProps = getWorkflowVersionStatusTagProps({ + workflowVersionStatus: versionStatus, + }); + return ( + ); diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCanvasReadonly.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCanvasReadonly.tsx index b608b2af8..cc7e2ec4a 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCanvasReadonly.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCanvasReadonly.tsx @@ -5,6 +5,7 @@ import { WorkflowDiagramDefaultEdge } from '@/workflow/workflow-diagram/componen import { WorkflowDiagramEmptyTrigger } from '@/workflow/workflow-diagram/components/WorkflowDiagramEmptyTrigger'; import { WorkflowDiagramStepNodeReadonly } from '@/workflow/workflow-diagram/components/WorkflowDiagramStepNodeReadonly'; import { WorkflowDiagramSuccessEdge } from '@/workflow/workflow-diagram/components/WorkflowDiagramSuccessEdge'; +import { getWorkflowVersionStatusTagProps } from '@/workflow/workflow-diagram/utils/getWorkflowVersionStatusTagProps'; import { ReactFlowProvider } from '@xyflow/react'; export const WorkflowDiagramCanvasReadonly = ({ @@ -12,10 +13,13 @@ export const WorkflowDiagramCanvasReadonly = ({ }: { versionStatus: WorkflowVersionStatus; }) => { + const tagProps = getWorkflowVersionStatusTagProps({ + workflowVersionStatus: versionStatus, + }); + return ( + ); diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowRunDiagramCanvas.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowRunDiagramCanvas.tsx index 348c5c8d9..2c4c9c5a2 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowRunDiagramCanvas.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowRunDiagramCanvas.tsx @@ -1,20 +1,24 @@ -import { WorkflowVersionStatus } from '@/workflow/types/Workflow'; +import { WorkflowRunStatus } from '@/workflow/types/Workflow'; import { WorkflowDiagramCanvasBase } from '@/workflow/workflow-diagram/components/WorkflowDiagramCanvasBase'; import { WorkflowDiagramDefaultEdge } from '@/workflow/workflow-diagram/components/WorkflowDiagramDefaultEdge'; import { WorkflowDiagramStepNodeReadonly } from '@/workflow/workflow-diagram/components/WorkflowDiagramStepNodeReadonly'; import { WorkflowDiagramSuccessEdge } from '@/workflow/workflow-diagram/components/WorkflowDiagramSuccessEdge'; import { WorkflowRunDiagramCanvasEffect } from '@/workflow/workflow-diagram/components/WorkflowRunDiagramCanvasEffect'; +import { getWorkflowRunStatusTagProps } from '@/workflow/workflow-diagram/utils/getWorkflowRunStatusTagProps'; import { ReactFlowProvider } from '@xyflow/react'; export const WorkflowRunDiagramCanvas = ({ - versionStatus, + workflowRunStatus, }: { - versionStatus: WorkflowVersionStatus; + workflowRunStatus: WorkflowRunStatus; }) => { + const tagProps = getWorkflowRunStatusTagProps({ + workflowRunStatus, + }); + return ( diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowRunDiagramCanvasEffect.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowRunDiagramCanvasEffect.tsx index 6048220c3..fc1c17794 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowRunDiagramCanvasEffect.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowRunDiagramCanvasEffect.tsx @@ -40,7 +40,10 @@ export const WorkflowRunDiagramCanvasEffect = () => { workflowRunRightDrawerListActiveTabIdState, ) as WorkflowRunTabId | null; - if (activeWorkflowRunRightDrawerTab === 'input') { + if ( + activeWorkflowRunRightDrawerTab === 'input' || + activeWorkflowRunRightDrawerTab === 'output' + ) { set(workflowRunRightDrawerListActiveTabIdState, 'node'); } }, diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowVersionStatusTag.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowVersionStatusTag.tsx deleted file mode 100644 index a917d8055..000000000 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowVersionStatusTag.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { WorkflowVersionStatus } from '@/workflow/types/Workflow'; -import { Tag } from 'twenty-ui'; - -export const WorkflowVersionStatusTag = ({ - versionStatus, -}: { - versionStatus: WorkflowVersionStatus; -}) => { - if (versionStatus === 'ACTIVE') { - return ; - } - - if (versionStatus === 'DRAFT') { - return ; - } - - if (versionStatus === 'ARCHIVED') { - return ; - } - - return ; -}; diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/__stories__/WorkflowDiagramCustomMarkers.stories.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/__stories__/WorkflowDiagramCustomMarkers.stories.tsx index b86dac5fb..ef15e5e7d 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/__stories__/WorkflowDiagramCustomMarkers.stories.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/__stories__/WorkflowDiagramCustomMarkers.stories.tsx @@ -41,7 +41,6 @@ type Story = StoryObj; export const DefaultEdge: Story = { args: { - status: 'DRAFT', nodeTypes: { default: WorkflowDiagramStepNodeReadonly, 'create-step': WorkflowDiagramCreateStepNode, @@ -116,7 +115,6 @@ export const DefaultEdge: Story = { export const SuccessEdge: Story = { args: { - status: 'DRAFT', nodeTypes: { default: WorkflowDiagramStepNodeReadonly, 'create-step': WorkflowDiagramCreateStepNode, diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/__stories__/WorkflowVersionStatusTag.stories.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/__stories__/WorkflowVersionStatusTag.stories.tsx deleted file mode 100644 index 0ea2cd94c..000000000 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/__stories__/WorkflowVersionStatusTag.stories.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import { Meta, StoryObj } from '@storybook/react'; -import { CatalogDecorator, CatalogStory, ComponentDecorator } from 'twenty-ui'; - -import { WorkflowVersionStatus } from '@/workflow/types/Workflow'; -import { WorkflowVersionStatusTag } from '../WorkflowVersionStatusTag'; - -const meta: Meta = { - title: 'Modules/Workflow/WorkflowVersionStatusTag', - component: WorkflowVersionStatusTag, -}; - -export default meta; -type Story = StoryObj; - -export const Default: Story = { - args: { - versionStatus: 'DRAFT', - }, - decorators: [ComponentDecorator], -}; - -export const Catalog: CatalogStory = { - argTypes: { - versionStatus: { table: { disable: true } }, - }, - parameters: { - catalog: { - dimensions: [ - { - name: 'version status', - values: [ - 'DRAFT', - 'ACTIVE', - 'DEACTIVATED', - 'ARCHIVED', - ] satisfies WorkflowVersionStatus[], - props: (versionStatus: WorkflowVersionStatus) => ({ versionStatus }), - }, - ], - }, - }, - decorators: [CatalogDecorator], -}; diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/utils/getWorkflowRunStatusTagProps.ts b/packages/twenty-front/src/modules/workflow/workflow-diagram/utils/getWorkflowRunStatusTagProps.ts new file mode 100644 index 000000000..59e506b80 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/utils/getWorkflowRunStatusTagProps.ts @@ -0,0 +1,34 @@ +import { WorkflowRunStatus } from '@/workflow/types/Workflow'; +import { TagColor } from 'twenty-ui'; + +export const getWorkflowRunStatusTagProps = ({ + workflowRunStatus, +}: { + workflowRunStatus: WorkflowRunStatus; +}): { color: TagColor; text: string } => { + if (workflowRunStatus === 'NOT_STARTED') { + return { + color: 'gray', + text: 'Not started', + }; + } + + if (workflowRunStatus === 'RUNNING') { + return { + color: 'yellow', + text: 'Running', + }; + } + + if (workflowRunStatus === 'COMPLETED') { + return { + color: 'green', + text: 'Completed', + }; + } + + return { + color: 'red', + text: 'Failed', + }; +}; diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/utils/getWorkflowVersionStatusTagProps.ts b/packages/twenty-front/src/modules/workflow/workflow-diagram/utils/getWorkflowVersionStatusTagProps.ts new file mode 100644 index 000000000..e73831b31 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/utils/getWorkflowVersionStatusTagProps.ts @@ -0,0 +1,34 @@ +import { WorkflowVersionStatus } from '@/workflow/types/Workflow'; +import { TagColor } from 'twenty-ui'; + +export const getWorkflowVersionStatusTagProps = ({ + workflowVersionStatus, +}: { + workflowVersionStatus: WorkflowVersionStatus; +}): { color: TagColor; text: string } => { + if (workflowVersionStatus === 'ARCHIVED') { + return { + color: 'gray', + text: 'Archived', + }; + } + + if (workflowVersionStatus === 'DRAFT') { + return { + color: 'yellow', + text: 'Draft', + }; + } + + if (workflowVersionStatus === 'ACTIVE') { + return { + color: 'green', + text: 'Active', + }; + } + + return { + color: 'gray', + text: 'Deactivated', + }; +}; diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/components/RightDrawerWorkflowRunViewStep.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/components/RightDrawerWorkflowRunViewStep.tsx index 1667632ca..b52f33114 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-steps/components/RightDrawerWorkflowRunViewStep.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/components/RightDrawerWorkflowRunViewStep.tsx @@ -6,6 +6,7 @@ import { useWorkflowRun } from '@/workflow/hooks/useWorkflowRun'; import { useWorkflowRunIdOrThrow } from '@/workflow/hooks/useWorkflowRunIdOrThrow'; import { useWorkflowSelectedNodeOrThrow } from '@/workflow/workflow-diagram/hooks/useWorkflowSelectedNodeOrThrow'; import { WorkflowRunStepInputDetail } from '@/workflow/workflow-steps/components/WorkflowRunStepInputDetail'; +import { WorkflowRunStepOutputDetail } from '@/workflow/workflow-steps/components/WorkflowRunStepOutputDetail'; import { WorkflowStepDetail } from '@/workflow/workflow-steps/components/WorkflowStepDetail'; import { WORKFLOW_RUN_STEP_SIDE_PANEL_TAB_LIST_COMPONENT_ID } from '@/workflow/workflow-steps/constants/WorkflowRunStepSidePanelTabListComponentId'; import { getWorkflowRunStepExecutionStatus } from '@/workflow/workflow-steps/utils/getWorkflowRunStepExecutionStatus'; @@ -38,7 +39,7 @@ export const RightDrawerWorkflowRunViewStep = () => { }) : undefined; - const isInputTabDisabled = + const areInputAndOutputTabsDisabled = workflowSelectedNode === TRIGGER_STEP_ID || stepExecutionStatus === 'running' || stepExecutionStatus === 'not-executed'; @@ -49,9 +50,14 @@ export const RightDrawerWorkflowRunViewStep = () => { id: 'input', title: 'Input', Icon: IconLogin2, - disabled: isInputTabDisabled, + disabled: areInputAndOutputTabsDisabled, + }, + { + id: 'output', + title: 'Output', + Icon: IconLogout, + disabled: areInputAndOutputTabsDisabled, }, - { id: 'output', title: 'Output', Icon: IconLogout }, ]; if (!isDefined(workflowRun)) { @@ -80,6 +86,10 @@ export const RightDrawerWorkflowRunViewStep = () => { {activeTabId === 'input' ? ( ) : null} + + {activeTabId === 'output' ? ( + + ) : null} ); }; diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/components/WorkflowRunStepOutputDetail.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/components/WorkflowRunStepOutputDetail.tsx new file mode 100644 index 000000000..288b1374b --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/components/WorkflowRunStepOutputDetail.tsx @@ -0,0 +1,27 @@ +import { JsonTree } from '@/workflow/components/json-visualizer/components/JsonTree'; +import { useWorkflowRun } from '@/workflow/hooks/useWorkflowRun'; +import { useWorkflowRunIdOrThrow } from '@/workflow/hooks/useWorkflowRunIdOrThrow'; +import styled from '@emotion/styled'; +import { isDefined } from 'twenty-shared'; + +const StyledContainer = styled.div` + padding-block: ${({ theme }) => theme.spacing(4)}; + padding-inline: ${({ theme }) => theme.spacing(3)}; +`; + +export const WorkflowRunStepOutputDetail = ({ stepId }: { stepId: string }) => { + const workflowRunId = useWorkflowRunIdOrThrow(); + const workflowRun = useWorkflowRun({ workflowRunId }); + + if (!isDefined(workflowRun?.output?.stepsOutput)) { + return null; + } + + const stepOutput = workflowRun.output.stepsOutput[stepId]; + + return ( + + + + ); +}; diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/components/WorkflowStepHeader.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/components/WorkflowStepHeader.tsx index 6e17ad94b..05ad3fda7 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-steps/components/WorkflowStepHeader.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/components/WorkflowStepHeader.tsx @@ -26,6 +26,10 @@ const StyledHeaderTitle = styled.div` font-size: ${({ theme }) => theme.font.size.xl}; width: 420px; overflow: hidden; + + & > input:disabled { + color: ${({ theme }) => theme.font.color.primary}; + } `; const StyledHeaderType = styled.div` diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/components/__stories__/RightDrawerWorkflowRunViewStep.stories.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/components/__stories__/RightDrawerWorkflowRunViewStep.stories.tsx index 23b65af67..ded32c24e 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-steps/components/__stories__/RightDrawerWorkflowRunViewStep.stories.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/components/__stories__/RightDrawerWorkflowRunViewStep.stories.tsx @@ -117,7 +117,6 @@ export const InputTabNotExecutedStep: Story = { return ; }, ], - play: async ({ canvasElement }) => { const canvas = within(canvasElement); @@ -138,5 +137,52 @@ export const OutputTab: Story = { await waitFor(() => { expect(canvas.queryByText('Create Record')).not.toBeInTheDocument(); }); + + expect(await canvas.findByText('result')).toBeVisible(); + }, +}; + +export const OutputTabDisabledForTrigger: Story = { + decorators: [ + (Story) => { + const setWorkflowSelectedNode = useSetRecoilState( + workflowSelectedNodeState, + ); + + setWorkflowSelectedNode(TRIGGER_STEP_ID); + + return ; + }, + ], + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const outputTab = await canvas.findByRole('button', { name: 'Output' }); + + expect(outputTab).toBeDisabled(); + }, +}; + +export const OutputTabNotExecutedStep: Story = { + decorators: [ + (Story) => { + const setWorkflowSelectedNode = useSetRecoilState( + workflowSelectedNodeState, + ); + + setWorkflowSelectedNode( + oneFailedWorkflowRunQueryResult.workflowRun.output.flow.steps.at(-1)! + .id, + ); + + return ; + }, + ], + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const outputTab = await canvas.findByRole('button', { name: 'Output' }); + + expect(outputTab).toBeDisabled(); }, };