History

refactor(execution-history): consolidate status color utilities

- Replace statusDotColor + statusColor (35 lines) with STATUS_STYLES config (9 lines) - Single source of truth for both dot and text colors - All 6 statuses explicitly defined with type-safe Record constraint - Use semantic tokens for duration colors (text-destructive/text-primary)

Saatvik Arya committed 7 months ago

Commit b4111a91 parent 410b42e1 file · +15 −35Browse files

Unified · Split

plugins/execution-history/react/components.tsx+15−35
@@ -60,22 +60,17 @@ const formatJsonDocument = (value: string | null): string | null => { · 59 unmodified lines
60 }60 }
61};61};
62 62
63const statusDotColor = (status: ExecutionStatus): string => {63const STATUS_STYLES = {
64 switch (status) {64 completed: { dot: "bg-primary", text: "text-primary" },
65 case "completed":65 failed: { dot: "bg-destructive", text: "text-destructive" },
66 return "bg-primary";66 running: { dot: "bg-blue-400 animate-pulse", text: "text-blue-400" },
67 case "failed":67 waiting_for_interaction: { dot: "bg-amber-400 animate-pulse", text: "text-amber-400" },
68 return "bg-destructive";68 pending: { dot: "bg-muted", text: "text-muted-foreground" },
69 case "running":69 cancelled: { dot: "bg-muted", text: "text-muted-foreground" },
70 return "bg-blue-400 animate-pulse";70} as const satisfies Record<ExecutionStatus, { dot: string; text: string }>;
71 case "waiting_for_interaction":71
72 return "bg-amber-400 animate-pulse";72const statusDot = (status: ExecutionStatus): string => STATUS_STYLES[status].dot;
73 case "pending":73const statusText = (status: ExecutionStatus): string => STATUS_STYLES[status].text;
74 return "bg-muted";
75 case "cancelled":
76 return "bg-muted";
77 }
78};
79 74
80const STATUS_OPTIONS: Array<{ value: string; label: string }> = [75const STATUS_OPTIONS: Array<{ value: string; label: string }> = [
81 { value: "all", label: "All" },76 { value: "all", label: "All" },
@@ -93,21 +88,6 @@ const formatDurationMs = (execution: Execution): string | null => { · 11 unmodified lines
93 return ms.toLocaleString();88 return ms.toLocaleString();
94};89};
95 90
96const statusColor = (status: ExecutionStatus): string => {
97 switch (status) {
98 case "completed":
99 return "text-primary";
100 case "failed":
101 return "text-destructive";
102 case "running":
103 return "text-blue-400";
104 case "waiting_for_interaction":
105 return "text-amber-400";
106 default:
107 return "text-muted-foreground";
108 }
109};
110
111// ── Execution Row ────────────────────────────────────────────────────────91// ── Execution Row ────────────────────────────────────────────────────────
112 92
113const ExecutionRow = (props: {93const ExecutionRow = (props: {
@@ -130,7 +110,7 @@ const ExecutionRow = (props: { · 16 unmodified lines
130 <span110 <span
131 className={cn(111 className={cn(
132 "mt-1.5 size-2 shrink-0 rounded-full",112 "mt-1.5 size-2 shrink-0 rounded-full",
133 statusDotColor(execution.status),113 statusDot(execution.status),
134 )}114 )}
135 />115 />
136 <span className="w-[120px] shrink-0 tabular-nums text-muted-foreground">116 <span className="w-[120px] shrink-0 tabular-nums text-muted-foreground">
@@ -138,11 +118,11 @@ const ExecutionRow = (props: { · 1 unmodified line
138 </span>118 </span>
139 <span className="inline-flex w-[130px] shrink-0">119 <span className="inline-flex w-[130px] shrink-0">
140 <span className="text-muted-foreground/60">status:</span>120 <span className="text-muted-foreground/60">status:</span>
141 <span className={statusColor(execution.status)}>{execution.status.replaceAll("_", " ")}</span>121 <span className={statusText(execution.status)}>{execution.status.replaceAll("_", " ")}</span>
142 </span>122 </span>
143 <span className="inline-flex w-[110px] shrink-0">123 <span className="inline-flex w-[110px] shrink-0">
144 <span className="text-muted-foreground/60">duration_ms:</span>{" "}124 <span className="text-muted-foreground/60">duration_ms:</span>{" "}
145 <span className={durationMs && Number(durationMs.replace(/,/g, "")) > 5000 ? "text-red-400" : "text-emerald-400"}>{durationMs ?? "—"}</span>125 <span className={durationMs && Number(durationMs.replace(/,/g, "")) > 5000 ? "text-destructive" : "text-primary"}>{durationMs ?? "—"}</span>
146 </span>126 </span>
147 <span className="min-w-0 flex-1 truncate">127 <span className="min-w-0 flex-1 truncate">
148 <span className="text-muted-foreground/60">code:</span>{" "}128 <span className="text-muted-foreground/60">code:</span>{" "}
@@ -186,7 +166,7 @@ const PropertiesTab = (props: { envelope: ExecutionEnvelope }) => { · 37 unmodified lines
186 Status166 Status
187 </div>167 </div>
188 <div className="mt-1 flex items-center gap-2">168 <div className="mt-1 flex items-center gap-2">
189 <span className={cn("size-2 rounded-full", statusDotColor(execution.status))} />169 <span className={cn("size-2 rounded-full", statusDot(execution.status))} />
190 <span className="text-sm">{execution.status.replaceAll("_", " ")}</span>170 <span className="text-sm">{execution.status.replaceAll("_", " ")}</span>
191 </div>171 </div>
192 </div>172 </div>