Surface block failure_reason in UI for all block types (#SKY-7620) (#4672)
This commit is contained in:
@@ -12,6 +12,7 @@ import { useWorkflowRunTimelineQuery } from "../hooks/useWorkflowRunTimelineQuer
|
|||||||
import { Status } from "@/api/types";
|
import { Status } from "@/api/types";
|
||||||
import { AutoResizingTextarea } from "@/components/AutoResizingTextarea/AutoResizingTextarea";
|
import { AutoResizingTextarea } from "@/components/AutoResizingTextarea/AutoResizingTextarea";
|
||||||
import { isTaskVariantBlock } from "../types/workflowTypes";
|
import { isTaskVariantBlock } from "../types/workflowTypes";
|
||||||
|
import { statusIsAFailureType } from "@/routes/tasks/types";
|
||||||
|
|
||||||
function DebuggerRunOutput() {
|
function DebuggerRunOutput() {
|
||||||
const { data: workflowRunTimeline, isLoading: workflowRunTimelineIsLoading } =
|
const { data: workflowRunTimeline, isLoading: workflowRunTimelineIsLoading } =
|
||||||
@@ -49,6 +50,12 @@ function DebuggerRunOutput() {
|
|||||||
isTaskVariantBlock(activeBlock) &&
|
isTaskVariantBlock(activeBlock) &&
|
||||||
activeBlock.status === Status.Completed;
|
activeBlock.status === Status.Completed;
|
||||||
|
|
||||||
|
const showFailureReason =
|
||||||
|
activeBlock &&
|
||||||
|
activeBlock.status !== null &&
|
||||||
|
(statusIsAFailureType({ status: activeBlock.status }) ||
|
||||||
|
activeBlock.status === Status.Canceled);
|
||||||
|
|
||||||
const outputs = workflowRun?.outputs;
|
const outputs = workflowRun?.outputs;
|
||||||
const fileUrls = workflowRun?.downloaded_file_urls ?? [];
|
const fileUrls = workflowRun?.downloaded_file_urls ?? [];
|
||||||
const observerOutput = workflowRun?.task_v2?.output;
|
const observerOutput = workflowRun?.task_v2?.output;
|
||||||
@@ -72,41 +79,36 @@ function DebuggerRunOutput() {
|
|||||||
<div className="rounded bg-slate-elevation2 p-6">
|
<div className="rounded bg-slate-elevation2 p-6">
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<h1 className="text-sm font-bold">Block Outputs</h1>
|
<h1 className="text-sm font-bold">Block Outputs</h1>
|
||||||
{activeBlock.output === null ? (
|
{showFailureReason ? (
|
||||||
<div className="text-sm">This block has no outputs</div>
|
|
||||||
) : isTaskVariantBlock(activeBlock) ? (
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<h2 className="text-sm">
|
<h2 className="text-sm">Failure Reason</h2>
|
||||||
{showExtractedInformation
|
<AutoResizingTextarea
|
||||||
? "Extracted Information"
|
value={
|
||||||
: "Failure Reason"}
|
activeBlock.status === "canceled"
|
||||||
</h2>
|
? "This block was cancelled"
|
||||||
{showExtractedInformation ? (
|
: activeBlock.failure_reason ?? ""
|
||||||
<CodeEditor
|
}
|
||||||
language="json"
|
readOnly
|
||||||
value={JSON.stringify(
|
/>
|
||||||
(hasExtractedInformation(activeBlock.output) &&
|
|
||||||
activeBlock.output.extracted_information) ??
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
2,
|
|
||||||
)}
|
|
||||||
minHeight="96px"
|
|
||||||
maxHeight="200px"
|
|
||||||
readOnly
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<AutoResizingTextarea
|
|
||||||
value={
|
|
||||||
activeBlock.status === "canceled"
|
|
||||||
? "This block was cancelled"
|
|
||||||
: activeBlock.failure_reason ?? ""
|
|
||||||
}
|
|
||||||
readOnly
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : showExtractedInformation ? (
|
||||||
|
<div className="space-y-2">
|
||||||
|
<h2 className="text-sm">Extracted Information</h2>
|
||||||
|
<CodeEditor
|
||||||
|
language="json"
|
||||||
|
value={JSON.stringify(
|
||||||
|
(hasExtractedInformation(activeBlock.output) &&
|
||||||
|
activeBlock.output.extracted_information) ??
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
2,
|
||||||
|
)}
|
||||||
|
minHeight="96px"
|
||||||
|
maxHeight="200px"
|
||||||
|
readOnly
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : activeBlock.output !== null ? (
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<h2 className="text-sm">Output</h2>
|
<h2 className="text-sm">Output</h2>
|
||||||
<CodeEditor
|
<CodeEditor
|
||||||
@@ -117,6 +119,8 @@ function DebuggerRunOutput() {
|
|||||||
readOnly
|
readOnly
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="text-sm">This block has no outputs</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { useWorkflowRunTimelineQuery } from "../hooks/useWorkflowRunTimelineQuer
|
|||||||
import { Status } from "@/api/types";
|
import { Status } from "@/api/types";
|
||||||
import { AutoResizingTextarea } from "@/components/AutoResizingTextarea/AutoResizingTextarea";
|
import { AutoResizingTextarea } from "@/components/AutoResizingTextarea/AutoResizingTextarea";
|
||||||
import { isTaskVariantBlock } from "../types/workflowTypes";
|
import { isTaskVariantBlock } from "../types/workflowTypes";
|
||||||
|
import { statusIsAFailureType } from "@/routes/tasks/types";
|
||||||
|
|
||||||
function WorkflowRunOutput() {
|
function WorkflowRunOutput() {
|
||||||
const { data: workflowRunTimeline, isLoading: workflowRunTimelineIsLoading } =
|
const { data: workflowRunTimeline, isLoading: workflowRunTimelineIsLoading } =
|
||||||
@@ -49,6 +50,12 @@ function WorkflowRunOutput() {
|
|||||||
isTaskVariantBlock(activeBlock) &&
|
isTaskVariantBlock(activeBlock) &&
|
||||||
activeBlock.status === Status.Completed;
|
activeBlock.status === Status.Completed;
|
||||||
|
|
||||||
|
const showFailureReason =
|
||||||
|
activeBlock &&
|
||||||
|
activeBlock.status !== null &&
|
||||||
|
(statusIsAFailureType({ status: activeBlock.status }) ||
|
||||||
|
activeBlock.status === Status.Canceled);
|
||||||
|
|
||||||
const outputs = workflowRun?.outputs;
|
const outputs = workflowRun?.outputs;
|
||||||
const fileUrls = workflowRun?.downloaded_file_urls ?? [];
|
const fileUrls = workflowRun?.downloaded_file_urls ?? [];
|
||||||
const observerOutput = workflowRun?.task_v2?.output;
|
const observerOutput = workflowRun?.task_v2?.output;
|
||||||
@@ -72,41 +79,36 @@ function WorkflowRunOutput() {
|
|||||||
<div className="rounded bg-slate-elevation2 p-6">
|
<div className="rounded bg-slate-elevation2 p-6">
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<h1 className="text-lg font-bold">Block Outputs</h1>
|
<h1 className="text-lg font-bold">Block Outputs</h1>
|
||||||
{activeBlock.output === null ? (
|
{showFailureReason ? (
|
||||||
<div>This block has no outputs</div>
|
|
||||||
) : isTaskVariantBlock(activeBlock) ? (
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<h2>
|
<h2>Failure Reason</h2>
|
||||||
{showExtractedInformation
|
<AutoResizingTextarea
|
||||||
? "Extracted Information"
|
value={
|
||||||
: "Failure Reason"}
|
activeBlock.status === "canceled"
|
||||||
</h2>
|
? "This block was cancelled"
|
||||||
{showExtractedInformation ? (
|
: activeBlock.failure_reason ?? ""
|
||||||
<CodeEditor
|
}
|
||||||
language="json"
|
readOnly
|
||||||
value={JSON.stringify(
|
/>
|
||||||
(hasExtractedInformation(activeBlock.output) &&
|
|
||||||
activeBlock.output.extracted_information) ??
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
2,
|
|
||||||
)}
|
|
||||||
minHeight="96px"
|
|
||||||
maxHeight="200px"
|
|
||||||
readOnly
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<AutoResizingTextarea
|
|
||||||
value={
|
|
||||||
activeBlock.status === "canceled"
|
|
||||||
? "This block was cancelled"
|
|
||||||
: activeBlock.failure_reason ?? ""
|
|
||||||
}
|
|
||||||
readOnly
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : showExtractedInformation ? (
|
||||||
|
<div className="space-y-2">
|
||||||
|
<h2>Extracted Information</h2>
|
||||||
|
<CodeEditor
|
||||||
|
language="json"
|
||||||
|
value={JSON.stringify(
|
||||||
|
(hasExtractedInformation(activeBlock.output) &&
|
||||||
|
activeBlock.output.extracted_information) ??
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
2,
|
||||||
|
)}
|
||||||
|
minHeight="96px"
|
||||||
|
maxHeight="200px"
|
||||||
|
readOnly
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : activeBlock.output !== null ? (
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<h2>Output</h2>
|
<h2>Output</h2>
|
||||||
<CodeEditor
|
<CodeEditor
|
||||||
@@ -117,6 +119,8 @@ function WorkflowRunOutput() {
|
|||||||
readOnly
|
readOnly
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
) : (
|
||||||
|
<div>This block has no outputs</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -57,7 +57,9 @@ function WorkflowRunTimelineItemInfoSection({ activeItem }: Props) {
|
|||||||
if (isWorkflowRunBlock(item)) {
|
if (isWorkflowRunBlock(item)) {
|
||||||
const showExtractedInformationTab = item.status === Status.Completed;
|
const showExtractedInformationTab = item.status === Status.Completed;
|
||||||
const showFailureReasonTab =
|
const showFailureReasonTab =
|
||||||
item.status && statusIsAFailureType({ status: item.status });
|
item.status &&
|
||||||
|
(statusIsAFailureType({ status: item.status }) ||
|
||||||
|
item.status === Status.Canceled);
|
||||||
const defaultTab = showExtractedInformationTab
|
const defaultTab = showExtractedInformationTab
|
||||||
? "extracted_information"
|
? "extracted_information"
|
||||||
: showFailureReasonTab
|
: showFailureReasonTab
|
||||||
@@ -81,7 +83,7 @@ function WorkflowRunTimelineItemInfoSection({ activeItem }: Props) {
|
|||||||
Extracted Information
|
Extracted Information
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
)}
|
)}
|
||||||
{item.status && statusIsAFailureType({ status: item.status }) && (
|
{showFailureReasonTab && (
|
||||||
<TabsTrigger value="failure_reason">Failure Reason</TabsTrigger>
|
<TabsTrigger value="failure_reason">Failure Reason</TabsTrigger>
|
||||||
)}
|
)}
|
||||||
<TabsTrigger value="navigation_goal">Navigation Goal</TabsTrigger>
|
<TabsTrigger value="navigation_goal">Navigation Goal</TabsTrigger>
|
||||||
@@ -116,7 +118,7 @@ function WorkflowRunTimelineItemInfoSection({ activeItem }: Props) {
|
|||||||
/>
|
/>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
)}
|
)}
|
||||||
{item.status && statusIsAFailureType({ status: item.status }) && (
|
{showFailureReasonTab && (
|
||||||
<TabsContent value="failure_reason">
|
<TabsContent value="failure_reason">
|
||||||
<AutoResizingTextarea
|
<AutoResizingTextarea
|
||||||
value={
|
value={
|
||||||
@@ -212,12 +214,30 @@ function WorkflowRunTimelineItemInfoSection({ activeItem }: Props) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fallbackDefaultTab = showFailureReasonTab
|
||||||
|
? "failure_reason"
|
||||||
|
: "output";
|
||||||
return (
|
return (
|
||||||
<div className="rounded bg-slate-elevation1 p-4">
|
<div className="rounded bg-slate-elevation1 p-4">
|
||||||
<Tabs key={item.block_type} defaultValue="output">
|
<Tabs key={item.block_type} defaultValue={fallbackDefaultTab}>
|
||||||
<TabsList>
|
<TabsList>
|
||||||
|
{showFailureReasonTab && (
|
||||||
|
<TabsTrigger value="failure_reason">Failure Reason</TabsTrigger>
|
||||||
|
)}
|
||||||
<TabsTrigger value="output">Output</TabsTrigger>
|
<TabsTrigger value="output">Output</TabsTrigger>
|
||||||
</TabsList>
|
</TabsList>
|
||||||
|
{showFailureReasonTab && (
|
||||||
|
<TabsContent value="failure_reason">
|
||||||
|
<AutoResizingTextarea
|
||||||
|
value={
|
||||||
|
item.status === "canceled"
|
||||||
|
? "This block was cancelled"
|
||||||
|
: item.failure_reason ?? ""
|
||||||
|
}
|
||||||
|
readOnly
|
||||||
|
/>
|
||||||
|
</TabsContent>
|
||||||
|
)}
|
||||||
<TabsContent value="output">
|
<TabsContent value="output">
|
||||||
<CodeEditor
|
<CodeEditor
|
||||||
value={JSON.stringify(item.output, null, 2)}
|
value={JSON.stringify(item.output, null, 2)}
|
||||||
|
|||||||
Reference in New Issue
Block a user