fix(webui): collapse automation run history by default

This commit is contained in:
chengyongru
2026-06-15 21:03:48 +08:00
parent 85a3ff1372
commit acf408ced2
11 changed files with 57 additions and 74 deletions
+51 -54
View File
@@ -3965,67 +3965,64 @@ function AutomationRunHistory({
tx: (key: string, fallback: string, values?: Record<string, unknown>) => string;
}) {
if (!history.length) return null;
const visible = expanded ? [...history].reverse() : history.slice(-4).reverse();
const hiddenCount = history.length - visible.length;
const visible = [...history].reverse();
return (
<section className="rounded-[18px] bg-muted/32 px-3 py-3">
<div className="mb-3 flex items-center justify-between gap-3">
<h4 className="text-[12px] font-medium leading-none text-foreground">
<button
type="button"
className="flex w-full items-center justify-between gap-3 text-left"
aria-expanded={expanded}
onClick={() => onExpandedChange(!expanded)}
>
<span className="text-[12px] font-medium leading-none text-foreground">
{tx("settings.automations.history.timeline", "Run history")}
</h4>
<span className="text-[11px] leading-none text-muted-foreground tabular-nums">
{history.length}
</span>
</div>
<div className="space-y-2">
{visible.map((run) => {
const status = automationRunStatusLabel(run.status, tx);
const duration = run.duration_ms === undefined
? null
: formatAutomationRunDuration(run.duration_ms, locale, tx);
return (
<div
key={`${run.run_at_ms}:${run.status}:${run.duration_ms ?? "none"}`}
className="grid grid-cols-[auto_minmax(0,1fr)_auto] items-start gap-2 rounded-[14px] bg-background/62 px-3 py-2"
>
<span
className={cn("mt-1.5 h-1.5 w-1.5 rounded-full", automationRunDotClass(run.status))}
aria-hidden
/>
<span className="min-w-0">
<span className="inline-flex items-center gap-2 text-[11px] leading-none text-muted-foreground">
<span className="tabular-nums">{history.length}</span>
<ChevronDown
className={cn("h-3.5 w-3.5 transition-transform", expanded && "rotate-180")}
aria-hidden
/>
</span>
</button>
{expanded ? (
<div className="mt-3 space-y-2">
{visible.map((run) => {
const status = automationRunStatusLabel(run.status, tx);
const duration = run.duration_ms === undefined
? null
: formatAutomationRunDuration(run.duration_ms, locale, tx);
return (
<div
key={`${run.run_at_ms}:${run.status}:${run.duration_ms ?? "none"}`}
className="grid grid-cols-[auto_minmax(0,1fr)_auto] items-start gap-2 rounded-[14px] bg-background/62 px-3 py-2"
>
<span
className="block line-clamp-2 text-[12.5px] leading-5 text-foreground/82"
title={run.error ?? undefined}
>
{status}
{run.error ? ` · ${run.error}` : ""}
className={cn("mt-1.5 h-1.5 w-1.5 rounded-full", automationRunDotClass(run.status))}
aria-hidden
/>
<span className="min-w-0">
<span
className="block line-clamp-2 text-[12.5px] leading-5 text-foreground/82"
title={run.error ?? undefined}
>
{status}
{run.error ? ` · ${run.error}` : ""}
</span>
<span className="block truncate text-[11.5px] leading-4 text-muted-foreground">
{fmtDateTime(run.run_at_ms, locale)}
</span>
</span>
<span className="block truncate text-[11.5px] leading-4 text-muted-foreground">
{fmtDateTime(run.run_at_ms, locale)}
</span>
</span>
{duration ? (
<span className="rounded-full bg-muted px-2 py-0.5 text-[11px] leading-4 text-muted-foreground">
{duration}
</span>
) : null}
</div>
);
})}
</div>
{history.length > 4 ? (
<button
type="button"
className="mt-3 inline-flex text-[12px] font-medium text-muted-foreground underline-offset-2 hover:text-foreground hover:underline"
onClick={() => onExpandedChange(!expanded)}
>
{expanded
? tx("settings.automations.history.showRecent", "Show recent runs")
: tx("settings.automations.history.showMore", "Show {{count}} more", {
count: hiddenCount,
})}
</button>
{duration ? (
<span className="rounded-full bg-muted px-2 py-0.5 text-[11px] leading-4 text-muted-foreground">
{duration}
</span>
) : null}
</div>
);
})}
</div>
) : null}
</section>
);
-2
View File
@@ -582,8 +582,6 @@
"skipped": "Skipped",
"recent": "Last result",
"timeline": "Run history",
"showMore": "Show {{count}} more",
"showRecent": "Show recent runs",
"statusWithDuration": "{{status}} · {{duration}}"
},
"message": {
-2
View File
@@ -582,8 +582,6 @@
"skipped": "Omitida",
"recent": "Último resultado",
"timeline": "Historial de ejecuciones",
"showMore": "Mostrar {{count}} más",
"showRecent": "Mostrar ejecuciones recientes",
"statusWithDuration": "{{status}} · {{duration}}"
},
"message": {
-2
View File
@@ -582,8 +582,6 @@
"skipped": "Ignorée",
"recent": "Dernier résultat",
"timeline": "Historique dexécution",
"showMore": "Afficher {{count}} de plus",
"showRecent": "Afficher les exécutions récentes",
"statusWithDuration": "{{status}} · {{duration}}"
},
"message": {
-2
View File
@@ -582,8 +582,6 @@
"skipped": "Dilewati",
"recent": "Hasil terakhir",
"timeline": "Riwayat eksekusi",
"showMore": "Tampilkan {{count}} lagi",
"showRecent": "Tampilkan eksekusi terbaru",
"statusWithDuration": "{{status}} · {{duration}}"
},
"message": {
-2
View File
@@ -582,8 +582,6 @@
"skipped": "スキップ",
"recent": "最新結果",
"timeline": "実行履歴",
"showMore": "さらに {{count}} 件表示",
"showRecent": "最近の実行のみ表示",
"statusWithDuration": "{{status}} · {{duration}}"
},
"message": {
-2
View File
@@ -582,8 +582,6 @@
"skipped": "건너뜀",
"recent": "최근 결과",
"timeline": "실행 기록",
"showMore": "{{count}}개 더 보기",
"showRecent": "최근 실행만 보기",
"statusWithDuration": "{{status}} · {{duration}}"
},
"message": {
-2
View File
@@ -582,8 +582,6 @@
"skipped": "Đã bỏ qua",
"recent": "Kết quả gần nhất",
"timeline": "Lịch sử chạy",
"showMore": "Hiển thị thêm {{count}}",
"showRecent": "Chỉ hiển thị lần chạy gần đây",
"statusWithDuration": "{{status}} · {{duration}}"
},
"message": {
-2
View File
@@ -582,8 +582,6 @@
"skipped": "已跳过",
"recent": "最近结果",
"timeline": "运行记录",
"showMore": "再显示 {{count}} 条",
"showRecent": "只看最近记录",
"statusWithDuration": "{{status}} · {{duration}}"
},
"message": {
-2
View File
@@ -582,8 +582,6 @@
"skipped": "已略過",
"recent": "最近結果",
"timeline": "執行記錄",
"showMore": "再顯示 {{count}} 筆",
"showRecent": "只看最近記錄",
"statusWithDuration": "{{status}} · {{duration}}"
},
"message": {
+6 -2
View File
@@ -629,9 +629,13 @@ describe("App layout", () => {
expect(message!).not.toHaveClass("line-clamp-6");
expect(screen.queryByText(/oldest failure/)).not.toBeInTheDocument();
fireEvent.click(within(detailPanel).getByRole("button", { name: "Show 2 more" }));
const historyToggle = within(detailPanel).getByRole("button", { name: /Run history/ });
expect(historyToggle).toHaveAttribute("aria-expanded", "false");
fireEvent.click(historyToggle);
expect(historyToggle).toHaveAttribute("aria-expanded", "true");
expect(screen.getAllByText(/oldest failure/)).toHaveLength(2);
fireEvent.click(within(detailPanel).getByRole("button", { name: "Show recent runs" }));
fireEvent.click(historyToggle);
expect(historyToggle).toHaveAttribute("aria-expanded", "false");
expect(screen.queryByText(/oldest failure/)).not.toBeInTheDocument();
});