Skip to content

Commit fc6c9ff

Browse files
committed
unify status better
1 parent d322699 commit fc6c9ff

File tree

18 files changed

+742
-128
lines changed

18 files changed

+742
-128
lines changed

src/components/Home/RunSection/RunRow.tsx

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,8 @@ import { useNavigate } from "@tanstack/react-router";
22
import { type MouseEvent } from "react";
33

44
import type { PipelineRunResponse } from "@/api/types.gen";
5-
import { StatusBar, StatusIcon, StatusText } from "@/components/shared/Status";
5+
import { StatusBar, StatusIcon } from "@/components/shared/Status";
66
import { Button } from "@/components/ui/button";
7-
import {
8-
HoverCard,
9-
HoverCardContent,
10-
HoverCardTrigger,
11-
} from "@/components/ui/hover-card";
127
import { TableCell, TableRow } from "@/components/ui/table";
138
import {
149
Tooltip,
@@ -20,9 +15,11 @@ import useToastNotification from "@/hooks/useToastNotification";
2015
import { APP_ROUTES } from "@/routes/router";
2116
import {
2217
convertExecutionStatsToStatusCounts,
23-
getRunStatus,
2418
} from "@/services/executionService";
2519
import { convertUTCToLocalTime, formatDate } from "@/utils/date";
20+
import {
21+
getOverallExecutionStatusFromStats,
22+
} from "@/utils/executionStatus";
2623

2724
const RunRow = ({ run }: { run: PipelineRunResponse }) => {
2825
const navigate = useNavigate();
@@ -45,6 +42,9 @@ const RunRow = ({ run }: { run: PipelineRunResponse }) => {
4542
const statusCounts = convertExecutionStatsToStatusCounts(
4643
run.execution_status_stats,
4744
);
45+
const overallStatus = getOverallExecutionStatusFromStats(
46+
run.execution_status_stats ?? undefined,
47+
);
4848

4949
const clickThroughUrl = `${APP_ROUTES.RUNS}/${runId}`;
5050

@@ -77,26 +77,19 @@ const RunRow = ({ run }: { run: PipelineRunResponse }) => {
7777
className="cursor-pointer text-gray-500 text-xs"
7878
>
7979
<TableCell className="text-sm flex items-center gap-2">
80-
<StatusIcon status={getRunStatus(statusCounts)} />
80+
<StatusIcon status={overallStatus} />
8181
<Paragraph className="truncate max-w-[400px]" title={name}>
8282
{name}
8383
</Paragraph>
8484
<span>{`#${runId}`}</span>
8585
</TableCell>
8686
<TableCell>
87-
<HoverCard openDelay={100}>
88-
<HoverCardTrigger>
89-
<div className="w-2/3">
90-
<StatusBar statusCounts={statusCounts} />
91-
</div>
92-
</HoverCardTrigger>
93-
<HoverCardContent>
94-
<div className="flex flex-col gap-2">
95-
<div className="text-sm font-bold">Status</div>
96-
<StatusText statusCounts={statusCounts} />
97-
</div>
98-
</HoverCardContent>
99-
</HoverCard>
87+
<div className="w-2/3">
88+
<StatusBar
89+
statusCounts={statusCounts}
90+
executionStatusStats={run.execution_status_stats}
91+
/>
92+
</div>
10093
</TableCell>
10194
<TableCell>
10295
{run.created_at

src/components/PipelineRun/RunDetails.tsx

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ import { Frown } from "lucide-react";
22

33
import { ArtifactsList } from "@/components/shared/ArtifactsList/ArtifactsList";
44
import { CopyText } from "@/components/shared/CopyText/CopyText";
5+
import { InfoBox } from "@/components/shared/InfoBox";
6+
import { StatusBar } from "@/components/shared/Status";
7+
import { TaskImplementation } from "@/components/shared/TaskDetails";
58
import { BlockStack, InlineStack } from "@/components/ui/layout";
69
import { Spinner } from "@/components/ui/spinner";
710
import { Text } from "@/components/ui/typography";
@@ -10,16 +13,13 @@ import { useUserDetails } from "@/hooks/useUserDetails";
1013
import { useBackend } from "@/providers/BackendProvider";
1114
import { useComponentSpec } from "@/providers/ComponentSpecProvider";
1215
import { useExecutionData } from "@/providers/ExecutionDataProvider";
16+
import { convertExecutionStatsToStatusCounts } from "@/services/executionService";
1317
import {
14-
countTaskStatuses,
15-
getRunStatus,
16-
isStatusComplete,
17-
isStatusInProgress,
18-
} from "@/services/executionService";
19-
20-
import { InfoBox } from "../shared/InfoBox";
21-
import { StatusBar, StatusText } from "../shared/Status";
22-
import { TaskImplementation } from "../shared/TaskDetails";
18+
type ExecutionStatusStats,
19+
getExecutionStatusLabel,
20+
getOverallExecutionStatusFromStats,
21+
} from "@/utils/executionStatus";
22+
2323
import { CancelPipelineRunButton } from "./components/CancelPipelineRunButton";
2424
import { ClonePipelineButton } from "./components/ClonePipelineButton";
2525
import { InspectPipelineButton } from "./components/InspectPipelineButton";
@@ -78,11 +78,33 @@ export const RunDetails = () => {
7878
);
7979
}
8080

81-
const statusCounts = countTaskStatuses(details, state);
82-
const runStatus = getRunStatus(statusCounts);
83-
const hasRunningTasks = statusCounts.running > 0;
84-
const isInProgress = isStatusInProgress(runStatus) || hasRunningTasks;
85-
const isComplete = isStatusComplete(runStatus);
81+
const executionStatusStats: ExecutionStatusStats =
82+
metadata?.execution_status_stats ??
83+
Object.values(state.child_execution_status_stats ?? {}).reduce<
84+
ExecutionStatusStats
85+
>((acc, stats) => {
86+
if (!stats) return acc;
87+
for (const [status, count] of Object.entries(stats)) {
88+
if (!count) continue;
89+
acc[status] = (acc[status] ?? 0) + count;
90+
}
91+
return acc;
92+
}, {});
93+
94+
const statusCounts = convertExecutionStatsToStatusCounts(executionStatusStats);
95+
const overallStatus = getOverallExecutionStatusFromStats(executionStatusStats);
96+
const statusLabel = getExecutionStatusLabel(overallStatus);
97+
98+
const inProgressCount =
99+
(executionStatusStats.RUNNING ?? 0) +
100+
(executionStatusStats.PENDING ?? 0) +
101+
(executionStatusStats.QUEUED ?? 0) +
102+
(executionStatusStats.WAITING_FOR_UPSTREAM ?? 0) +
103+
(executionStatusStats.CANCELLING ?? 0) +
104+
(executionStatusStats.UNINITIALIZED ?? 0);
105+
106+
const isInProgress = inProgressCount > 0;
107+
const isComplete = !isInProgress && statusCounts.total > 0;
86108

87109
const annotations = componentSpec.metadata?.annotations || {};
88110

@@ -175,11 +197,13 @@ export const RunDetails = () => {
175197
</Text>
176198
<InlineStack gap="2" blockAlign="center" className="mb-1">
177199
<Text size="sm" weight="semibold">
178-
{runStatus}
200+
{statusLabel}
179201
</Text>
180-
<StatusText statusCounts={statusCounts} />
181202
</InlineStack>
182-
<StatusBar statusCounts={statusCounts} />
203+
<StatusBar
204+
statusCounts={statusCounts}
205+
executionStatusStats={executionStatusStats}
206+
/>
183207
</BlockStack>
184208

185209
{Object.keys(annotations).length > 0 && (

src/components/shared/ReactFlow/FlowCanvas/TaskNode/StatusIndicator.tsx

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,13 @@ import {
66
XCircleIcon,
77
} from "lucide-react";
88

9-
import type { ContainerExecutionStatus } from "@/api/types.gen";
109
import { Icon } from "@/components/ui/icon";
1110
import { QuickTooltip } from "@/components/ui/tooltip";
1211
import { cn } from "@/lib/utils";
13-
import type { RunStatus } from "@/types/pipelineRun";
12+
import { getExecutionStatusLabel } from "@/utils/executionStatus";
1413

1514
type StatusIndicatorProps = {
16-
status: ContainerExecutionStatus | RunStatus;
15+
status: string;
1716
disabledCache?: boolean;
1817
};
1918

@@ -46,70 +45,72 @@ export const StatusIndicator = ({
4645
);
4746
};
4847

49-
const getStatusMetadata = (status: ContainerExecutionStatus | RunStatus) => {
48+
const getStatusMetadata = (status: string) => {
49+
const text = getExecutionStatusLabel(status);
50+
5051
switch (status) {
5152
case "SUCCEEDED":
5253
return {
5354
style: "bg-emerald-500",
54-
text: "Succeeded",
55+
text,
5556
icon: <CheckCircleIcon className="w-2 h-2" />,
5657
};
5758
case "FAILED":
5859
case "SYSTEM_ERROR":
5960
case "INVALID":
6061
return {
6162
style: "bg-red-700",
62-
text: "Failed",
63+
text,
6364
icon: <XCircleIcon className="w-2 h-2" />,
6465
};
6566
case "RUNNING":
6667
return {
6768
style: "bg-sky-500",
68-
text: "Running",
69+
text,
6970
icon: <Loader2Icon className="w-2 h-2 animate-spin" />,
7071
};
7172
case "PENDING":
7273
return {
7374
style: "bg-yellow-500",
74-
text: "Pending",
75+
text,
7576
icon: <ClockIcon className="w-2 h-2 animate-spin duration-2000" />,
7677
};
7778
case "CANCELLING":
7879
case "CANCELLED":
7980
return {
8081
style: "bg-gray-800",
81-
text: status === "CANCELLING" ? "Cancelling" : "Cancelled",
82+
text,
8283
icon: <XCircleIcon className="w-2 h-2" />,
8384
};
8485
case "SKIPPED":
8586
return {
8687
style: "bg-slate-400",
87-
text: "Skipped",
88+
text,
8889
icon: <XCircleIcon className="w-2 h-2" />,
8990
};
9091
case "QUEUED":
9192
return {
9293
style: "bg-yellow-500",
93-
text: "Queued",
94+
text,
9495
icon: <ClockIcon className="w-2 h-2 animate-spin duration-2000" />,
9596
};
9697
case "WAITING_FOR_UPSTREAM":
9798
return {
9899
style: "bg-slate-500",
99-
text: "Waiting for upstream",
100+
text,
100101
icon: <ClockIcon className="w-2 h-2 animate-spin duration-2000" />,
101102
};
102103
case "WAITING":
103104
case "UNINITIALIZED":
104105
return {
105106
style: "bg-yellow-500",
106-
text: "Pending",
107+
text,
107108
icon: <ClockIcon className="w-2 h-2 animate-spin duration-2000" />,
108109
};
109110
default:
110111
return {
111112
style: "bg-slate-300",
112-
text: "Unknown",
113+
text,
113114
icon: <CircleDashedIcon className="w-2 h-2" />,
114115
};
115116
}

src/components/shared/ReactFlow/FlowCanvas/TaskNode/TaskNode.tsx

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { memo, useMemo } from "react";
33

44
import { useExecutionDataOptional } from "@/providers/ExecutionDataProvider";
55
import { TaskNodeProvider } from "@/providers/TaskNodeProvider";
6-
import { getRunStatus } from "@/services/executionService";
76
import type { TaskNodeData } from "@/types/taskNode";
87
import { isCacheDisabled } from "@/utils/cache";
98

@@ -17,14 +16,8 @@ const TaskNode = ({ data, selected }: NodeProps) => {
1716

1817
const status = useMemo(() => {
1918
const taskId = typedData.taskId ?? "";
20-
const statusCounts = executionData?.taskStatusCountsMap.get(taskId);
21-
22-
if (!statusCounts) {
23-
return undefined;
24-
}
25-
26-
return getRunStatus(statusCounts);
27-
}, [executionData?.taskStatusCountsMap, typedData.taskId]);
19+
return executionData?.taskExecutionStatusMap.get(taskId);
20+
}, [executionData?.taskExecutionStatusMap, typedData.taskId]);
2821

2922
const disabledCache = isCacheDisabled(typedData.taskSpec);
3023

src/components/shared/ReactFlow/FlowCanvas/TaskNode/TaskOverview/logs.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
import { useQuery } from "@tanstack/react-query";
22
import { useEffect, useState } from "react";
33

4-
import type { ContainerExecutionStatus } from "@/api/types.gen";
54
import { CodeViewer } from "@/components/shared/CodeViewer";
65
import { InfoBox } from "@/components/shared/InfoBox";
76
import { Link } from "@/components/ui/link";
87
import { Spinner } from "@/components/ui/spinner";
98
import { useBackend } from "@/providers/BackendProvider";
10-
import type { RunStatus } from "@/types/pipelineRun";
119
import { getBackendStatusString } from "@/utils/backend";
1210

1311
const LogDisplay = ({
@@ -53,7 +51,7 @@ const LogDisplay = ({
5351
};
5452

5553
const isStatusActivelyLogging = (
56-
status?: ContainerExecutionStatus | RunStatus,
54+
status?: string,
5755
): boolean => {
5856
if (!status) {
5957
return false;
@@ -71,7 +69,7 @@ const isStatusActivelyLogging = (
7169
};
7270

7371
const shouldStatusHaveLogs = (
74-
status?: ContainerExecutionStatus | RunStatus,
72+
status?: string,
7573
): boolean => {
7674
if (!status) {
7775
return false;
@@ -104,7 +102,7 @@ const Logs = ({
104102
status,
105103
}: {
106104
executionId?: string | number;
107-
status?: ContainerExecutionStatus | RunStatus;
105+
status?: string;
108106
}) => {
109107
const { backendUrl, configured, available } = useBackend();
110108

@@ -194,7 +192,7 @@ export const OpenLogsInNewWindowLink = ({
194192
status,
195193
}: {
196194
executionId: string;
197-
status?: ContainerExecutionStatus | RunStatus;
195+
status?: string;
198196
}) => {
199197
const { backendUrl, available } = useBackend();
200198
const logsUrl = `${backendUrl}/api/executions/${executionId}/stream_container_log`;

src/components/shared/Status/StatusIcon.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
TooltipContent,
1414
TooltipTrigger,
1515
} from "@/components/ui/tooltip";
16+
import { getExecutionStatusLabel } from "@/utils/executionStatus";
1617

1718
const StatusIcon = ({
1819
status,
@@ -25,7 +26,8 @@ const StatusIcon = ({
2526
}) => {
2627
if (tooltip) {
2728
const capitalizedLabel = label.charAt(0).toUpperCase() + label.slice(1);
28-
const tooltipText = `${capitalizedLabel} ${status?.toLowerCase() ?? "unknown"}`;
29+
const displayStatus = getExecutionStatusLabel(status);
30+
const tooltipText = `${capitalizedLabel} ${displayStatus}`;
2931
return (
3032
<Tooltip>
3133
<TooltipTrigger asChild>

src/components/shared/Status/StatusText.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@ const STATUS_COLORS: Record<string, string> = {
55
succeeded: "text-green-500",
66
failed: "text-red-500",
77
running: "text-blue-500",
8+
pending: "text-yellow-600",
9+
waiting: "text-slate-600",
810
skipped: "text-gray-800",
9-
waiting: "text-yellow-600",
1011
cancelled: "text-gray-800",
1112
};
1213

1314
const STATUS_DISPLAY_NAMES: Record<string, string> = {
14-
waiting: "pending",
15+
pending: "pending",
16+
waiting: "waiting",
1517
};
1618

1719
const StatusText = ({

0 commit comments

Comments
 (0)