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
This commit is contained in:
committed by
GitHub
parent
0e1d742f3d
commit
b49ec864b1
@ -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 (
|
||||
<StyledTab
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { WorkflowRunVisualizerContent } from '@/workflow/components/WorkflowRunVisualizerContent';
|
||||
import { useWorkflowRun } from '@/workflow/hooks/useWorkflowRun';
|
||||
import { WorkflowRunDiagramCanvas } from '@/workflow/workflow-diagram/components/WorkflowRunDiagramCanvas';
|
||||
import styled from '@emotion/styled';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
|
||||
@ -19,7 +19,7 @@ export const WorkflowRunVisualizer = ({
|
||||
|
||||
return (
|
||||
<StyledSourceCodeContainer>
|
||||
<WorkflowRunVisualizerContent workflowRun={workflowRun} />
|
||||
<WorkflowRunDiagramCanvas workflowRunStatus={workflowRun.status} />
|
||||
</StyledSourceCodeContainer>
|
||||
);
|
||||
};
|
||||
|
||||
@ -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 <WorkflowRunDiagramCanvas versionStatus={workflowVersion.status} />;
|
||||
};
|
||||
@ -15,6 +15,7 @@ import {
|
||||
workflowRunOutputSchema,
|
||||
workflowRunOutputStepsOutputSchema,
|
||||
workflowRunSchema,
|
||||
workflowRunStatusSchema,
|
||||
workflowSendEmailActionSchema,
|
||||
workflowSendEmailActionSettingsSchema,
|
||||
workflowTriggerSchema,
|
||||
@ -107,6 +108,8 @@ export type WorkflowRunContext = z.infer<typeof workflowRunContextSchema>;
|
||||
|
||||
export type WorkflowRunFlow = WorkflowRunOutput['flow'];
|
||||
|
||||
export type WorkflowRunStatus = z.infer<typeof workflowRunStatusSchema>;
|
||||
|
||||
export type WorkflowRun = z.infer<typeof workflowRunSchema>;
|
||||
|
||||
export type Workflow = {
|
||||
|
||||
@ -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(),
|
||||
|
||||
@ -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}
|
||||
</ReactFlow>
|
||||
|
||||
<StyledStatusTagContainer data-testid="workflow-visualizer-status">
|
||||
<WorkflowVersionStatusTag versionStatus={status} />
|
||||
<StyledStatusTagContainer data-testid={tagContainerTestId}>
|
||||
<Tag color={tagColor} text={tagText} />
|
||||
</StyledStatusTagContainer>
|
||||
</StyledResetReactflowStyles>
|
||||
);
|
||||
|
||||
@ -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 (
|
||||
<ReactFlowProvider>
|
||||
<WorkflowDiagramCanvasBase
|
||||
status={versionStatus}
|
||||
nodeTypes={{
|
||||
default: WorkflowDiagramStepNodeEditable,
|
||||
'create-step': WorkflowDiagramCreateStepNode,
|
||||
@ -24,7 +28,11 @@ export const WorkflowDiagramCanvasEditable = ({
|
||||
edgeTypes={{
|
||||
default: WorkflowDiagramDefaultEdge,
|
||||
}}
|
||||
tagContainerTestId="workflow-visualizer-status"
|
||||
tagColor={tagProps.color}
|
||||
tagText={tagProps.text}
|
||||
/>
|
||||
|
||||
<WorkflowDiagramCanvasEditableEffect />
|
||||
</ReactFlowProvider>
|
||||
);
|
||||
|
||||
@ -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 (
|
||||
<ReactFlowProvider>
|
||||
<WorkflowDiagramCanvasBase
|
||||
status={versionStatus}
|
||||
nodeTypes={{
|
||||
default: WorkflowDiagramStepNodeReadonly,
|
||||
'empty-trigger': WorkflowDiagramEmptyTrigger,
|
||||
@ -24,7 +28,11 @@ export const WorkflowDiagramCanvasReadonly = ({
|
||||
default: WorkflowDiagramDefaultEdge,
|
||||
success: WorkflowDiagramSuccessEdge,
|
||||
}}
|
||||
tagContainerTestId="workflow-visualizer-status"
|
||||
tagColor={tagProps.color}
|
||||
tagText={tagProps.text}
|
||||
/>
|
||||
|
||||
<WorkflowDiagramCanvasReadonlyEffect />
|
||||
</ReactFlowProvider>
|
||||
);
|
||||
|
||||
@ -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 (
|
||||
<ReactFlowProvider>
|
||||
<WorkflowDiagramCanvasBase
|
||||
status={versionStatus}
|
||||
nodeTypes={{
|
||||
default: WorkflowDiagramStepNodeReadonly,
|
||||
}}
|
||||
@ -22,6 +26,9 @@ export const WorkflowRunDiagramCanvas = ({
|
||||
default: WorkflowDiagramDefaultEdge,
|
||||
success: WorkflowDiagramSuccessEdge,
|
||||
}}
|
||||
tagContainerTestId="workflow-run-status"
|
||||
tagColor={tagProps.color}
|
||||
tagText={tagProps.text}
|
||||
/>
|
||||
|
||||
<WorkflowRunDiagramCanvasEffect />
|
||||
|
||||
@ -40,7 +40,10 @@ export const WorkflowRunDiagramCanvasEffect = () => {
|
||||
workflowRunRightDrawerListActiveTabIdState,
|
||||
) as WorkflowRunTabId | null;
|
||||
|
||||
if (activeWorkflowRunRightDrawerTab === 'input') {
|
||||
if (
|
||||
activeWorkflowRunRightDrawerTab === 'input' ||
|
||||
activeWorkflowRunRightDrawerTab === 'output'
|
||||
) {
|
||||
set(workflowRunRightDrawerListActiveTabIdState, 'node');
|
||||
}
|
||||
},
|
||||
|
||||
@ -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 <Tag color="green" text="Active" />;
|
||||
}
|
||||
|
||||
if (versionStatus === 'DRAFT') {
|
||||
return <Tag color="yellow" text="Draft" />;
|
||||
}
|
||||
|
||||
if (versionStatus === 'ARCHIVED') {
|
||||
return <Tag color="gray" text="Archived" />;
|
||||
}
|
||||
|
||||
return <Tag color="gray" text="Deactivated" />;
|
||||
};
|
||||
@ -41,7 +41,6 @@ type Story = StoryObj<typeof WorkflowDiagramCanvasBase>;
|
||||
|
||||
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,
|
||||
|
||||
@ -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<typeof WorkflowVersionStatusTag> = {
|
||||
title: 'Modules/Workflow/WorkflowVersionStatusTag',
|
||||
component: WorkflowVersionStatusTag,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof WorkflowVersionStatusTag>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
versionStatus: 'DRAFT',
|
||||
},
|
||||
decorators: [ComponentDecorator],
|
||||
};
|
||||
|
||||
export const Catalog: CatalogStory<Story, typeof WorkflowVersionStatusTag> = {
|
||||
argTypes: {
|
||||
versionStatus: { table: { disable: true } },
|
||||
},
|
||||
parameters: {
|
||||
catalog: {
|
||||
dimensions: [
|
||||
{
|
||||
name: 'version status',
|
||||
values: [
|
||||
'DRAFT',
|
||||
'ACTIVE',
|
||||
'DEACTIVATED',
|
||||
'ARCHIVED',
|
||||
] satisfies WorkflowVersionStatus[],
|
||||
props: (versionStatus: WorkflowVersionStatus) => ({ versionStatus }),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
decorators: [CatalogDecorator],
|
||||
};
|
||||
@ -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',
|
||||
};
|
||||
};
|
||||
@ -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',
|
||||
};
|
||||
};
|
||||
@ -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' ? (
|
||||
<WorkflowRunStepInputDetail stepId={workflowSelectedNode} />
|
||||
) : null}
|
||||
|
||||
{activeTabId === 'output' ? (
|
||||
<WorkflowRunStepOutputDetail stepId={workflowSelectedNode} />
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@ -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 (
|
||||
<StyledContainer>
|
||||
<JsonTree value={stepOutput} />
|
||||
</StyledContainer>
|
||||
);
|
||||
};
|
||||
@ -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`
|
||||
|
||||
@ -117,7 +117,6 @@ export const InputTabNotExecutedStep: Story = {
|
||||
return <Story />;
|
||||
},
|
||||
],
|
||||
|
||||
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 <Story />;
|
||||
},
|
||||
],
|
||||
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 <Story />;
|
||||
},
|
||||
],
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
const outputTab = await canvas.findByRole('button', { name: 'Output' });
|
||||
|
||||
expect(outputTab).toBeDisabled();
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user