@voyantjs/workflows-ui 0.66.0 → 0.68.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/workflow-schedules-page.d.ts +21 -0
- package/dist/components/workflow-schedules-page.d.ts.map +1 -0
- package/dist/components/workflow-schedules-page.js +131 -0
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +38 -0
- package/dist/i18n/messages.d.ts +38 -0
- package/dist/i18n/messages.d.ts.map +1 -1
- package/dist/i18n/ro.d.ts.map +1 -1
- package/dist/i18n/ro.js +38 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/schedules-client.d.ts +2 -0
- package/dist/schedules-client.d.ts.map +1 -0
- package/dist/schedules-client.js +1 -0
- package/package.json +7 -7
- package/src/components/workflow-schedules-page.tsx +368 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { WorkflowSchedulesApi } from "../schedules-client.js";
|
|
2
|
+
import type { WorkflowRunsApi } from "../types.js";
|
|
3
|
+
export interface WorkflowSchedulesPageProps {
|
|
4
|
+
/** Schedules API — backed by `/api/schedules/:env`. */
|
|
5
|
+
schedulesApi: WorkflowSchedulesApi;
|
|
6
|
+
/** Optional runs API — when provided, the page joins each row with the most recent matching run. */
|
|
7
|
+
runsApi?: WorkflowRunsApi;
|
|
8
|
+
/**
|
|
9
|
+
* Optional trigger callback. When provided, each row renders a
|
|
10
|
+
* "Trigger now" button that calls this with the workflow id + the
|
|
11
|
+
* schedule's recorded `input` payload (if any).
|
|
12
|
+
*/
|
|
13
|
+
onTriggerNow?: (workflowId: string, input: unknown) => Promise<void>;
|
|
14
|
+
/** Manifest environment to inspect. Defaults to "production". */
|
|
15
|
+
environment?: "production" | "preview" | "development";
|
|
16
|
+
/** Auto-refresh interval (ms). Defaults to 30s. Pass 0 to disable. */
|
|
17
|
+
pollIntervalMs?: number;
|
|
18
|
+
className?: string;
|
|
19
|
+
}
|
|
20
|
+
export declare function WorkflowSchedulesPage({ schedulesApi, runsApi, onTriggerNow, environment, pollIntervalMs, className, }: WorkflowSchedulesPageProps): import("react/jsx-runtime").JSX.Element;
|
|
21
|
+
//# sourceMappingURL=workflow-schedules-page.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-schedules-page.d.ts","sourceRoot":"","sources":["../../src/components/workflow-schedules-page.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAIV,oBAAoB,EACrB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,KAAK,EAAkC,eAAe,EAAE,MAAM,aAAa,CAAA;AAKlF,MAAM,WAAW,0BAA0B;IACzC,uDAAuD;IACvD,YAAY,EAAE,oBAAoB,CAAA;IAClC,oGAAoG;IACpG,OAAO,CAAC,EAAE,eAAe,CAAA;IACzB;;;;OAIG;IACH,YAAY,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACpE,iEAAiE;IACjE,WAAW,CAAC,EAAE,YAAY,GAAG,SAAS,GAAG,aAAa,CAAA;IACtD,sEAAsE;IACtE,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,qBAAqB,CAAC,EACpC,YAAY,EACZ,OAAO,EACP,YAAY,EACZ,WAA0B,EAC1B,cAAuB,EACvB,SAAS,GACV,EAAE,0BAA0B,2CA0L5B"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Badge } from "@voyantjs/ui/components/badge";
|
|
4
|
+
import { Button } from "@voyantjs/ui/components/button";
|
|
5
|
+
import { Card, CardContent } from "@voyantjs/ui/components/card";
|
|
6
|
+
import { AlertTriangle, CalendarClock, RefreshCw } from "lucide-react";
|
|
7
|
+
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
8
|
+
import { useWorkflowRunsUiMessagesOrDefault } from "../i18n/index.js";
|
|
9
|
+
import { formatRelative, StatusIcon } from "./common.js";
|
|
10
|
+
export function WorkflowSchedulesPage({ schedulesApi, runsApi, onTriggerNow, environment = "production", pollIntervalMs = 30_000, className, }) {
|
|
11
|
+
const rootMessages = useWorkflowRunsUiMessagesOrDefault();
|
|
12
|
+
const messages = rootMessages.schedules;
|
|
13
|
+
const [response, setResponse] = useState(null);
|
|
14
|
+
const [lastRuns, setLastRuns] = useState({});
|
|
15
|
+
const [loading, setLoading] = useState(false);
|
|
16
|
+
const [error, setError] = useState(null);
|
|
17
|
+
const [triggering, setTriggering] = useState({});
|
|
18
|
+
const [triggerNotice, setTriggerNotice] = useState(null);
|
|
19
|
+
const refresh = useCallback(async () => {
|
|
20
|
+
setLoading(true);
|
|
21
|
+
try {
|
|
22
|
+
const next = await schedulesApi.listSchedules(environment);
|
|
23
|
+
setResponse(next);
|
|
24
|
+
setError(null);
|
|
25
|
+
if (runsApi) {
|
|
26
|
+
const uniqueIds = Array.from(new Set(next.data.map((entry) => entry.workflowId)));
|
|
27
|
+
const results = await Promise.all(uniqueIds.map(async (workflowId) => {
|
|
28
|
+
try {
|
|
29
|
+
const runs = await runsApi.listRuns({ workflowName: workflowId, limit: 1 });
|
|
30
|
+
return [workflowId, runs.data[0] ?? null];
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return [workflowId, null];
|
|
34
|
+
}
|
|
35
|
+
}));
|
|
36
|
+
setLastRuns(Object.fromEntries(results));
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
setError(err instanceof Error ? err.message : messages.loadError);
|
|
41
|
+
}
|
|
42
|
+
finally {
|
|
43
|
+
setLoading(false);
|
|
44
|
+
}
|
|
45
|
+
}, [environment, messages.loadError, runsApi, schedulesApi]);
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
void refresh();
|
|
48
|
+
if (!pollIntervalMs)
|
|
49
|
+
return;
|
|
50
|
+
const interval = setInterval(() => void refresh(), pollIntervalMs);
|
|
51
|
+
return () => clearInterval(interval);
|
|
52
|
+
}, [pollIntervalMs, refresh]);
|
|
53
|
+
const showEnvFlag = response?.schedulesEnabledByEnv !== undefined;
|
|
54
|
+
const envFlagOn = response?.schedulesEnabledByEnv === true;
|
|
55
|
+
const triggerRow = useCallback(async (entry) => {
|
|
56
|
+
if (!onTriggerNow)
|
|
57
|
+
return;
|
|
58
|
+
setTriggering((prev) => ({ ...prev, [entry.scheduleId]: true }));
|
|
59
|
+
setTriggerNotice(null);
|
|
60
|
+
try {
|
|
61
|
+
await onTriggerNow(entry.workflowId, entry.schedule.input);
|
|
62
|
+
setTriggerNotice({ kind: "success", text: messages.triggerSuccess });
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
setTriggerNotice({
|
|
66
|
+
kind: "error",
|
|
67
|
+
text: err instanceof Error ? err.message : messages.triggerFailed,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
finally {
|
|
71
|
+
setTriggering((prev) => ({ ...prev, [entry.scheduleId]: false }));
|
|
72
|
+
}
|
|
73
|
+
}, [messages.triggerFailed, messages.triggerSuccess, onTriggerNow]);
|
|
74
|
+
const rows = useMemo(() => response?.data ?? [], [response]);
|
|
75
|
+
return (_jsxs("div", { className: `flex min-h-screen flex-col bg-background ${className ?? ""}`, children: [_jsx("header", { className: "sticky top-0 z-10 border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60", children: _jsxs("div", { className: "container mx-auto flex flex-wrap items-center gap-3 px-4 py-3", children: [_jsx(CalendarClock, { className: "h-5 w-5" }), _jsxs("div", { className: "min-w-0", children: [_jsx("h1", { className: "font-semibold text-base", children: messages.title }), _jsx("p", { className: "text-muted-foreground text-xs", children: messages.subtitle })] }), _jsxs("div", { className: "ml-auto flex items-center gap-2 text-muted-foreground text-xs", children: [_jsxs("span", { children: [messages.environmentLabel, ": ", _jsx("span", { className: "font-mono", children: environment })] }), response?.versionId ? (_jsxs("span", { children: [messages.versionLabel, ":", " ", _jsx("span", { className: "font-mono", children: response.versionId.slice(0, 12) })] })) : null, _jsxs(Button, { type: "button", variant: "outline", size: "sm", onClick: () => void refresh(), disabled: loading, children: [_jsx(RefreshCw, { className: `h-3.5 w-3.5 ${loading ? "animate-spin" : ""}`, "aria-hidden": "true" }), messages.refresh] })] })] }) }), _jsxs("main", { className: "container mx-auto flex flex-1 flex-col gap-4 px-4 py-6", children: [showEnvFlag && !envFlagOn ? (_jsx(Card, { className: "border-amber-500/40 bg-amber-500/5", children: _jsxs(CardContent, { className: "flex items-center gap-2 pt-4 text-amber-700 text-sm dark:text-amber-300", children: [_jsx(AlertTriangle, { className: "h-4 w-4", "aria-hidden": "true" }), messages.envFlagOff] }) })) : null, triggerNotice ? (_jsx(Card, { className: triggerNotice.kind === "success"
|
|
76
|
+
? "border-emerald-500/40 bg-emerald-500/5"
|
|
77
|
+
: "border-destructive/40 bg-destructive/5", children: _jsx(CardContent, { className: `pt-4 text-sm ${triggerNotice.kind === "success"
|
|
78
|
+
? "text-emerald-600 dark:text-emerald-300"
|
|
79
|
+
: "text-destructive"}`, children: triggerNotice.text }) })) : null, error ? (_jsx(Card, { className: "border-destructive/40", children: _jsx(CardContent, { className: "pt-4 text-destructive text-sm", children: error }) })) : null, !error && rows.length === 0 && !loading ? (_jsx(Card, { children: _jsx(CardContent, { className: "pt-4 text-muted-foreground text-sm", children: messages.empty }) })) : null, rows.length > 0 ? (_jsx("div", { className: "overflow-hidden rounded-md border", children: _jsxs("table", { className: "w-full text-sm", children: [_jsx("thead", { className: "bg-muted/40 text-left text-xs uppercase", children: _jsxs("tr", { children: [_jsx("th", { className: "px-3 py-2 font-medium", children: messages.workflowColumn }), _jsx("th", { className: "px-3 py-2 font-medium", children: messages.scheduleColumn }), _jsx("th", { className: "px-3 py-2 font-medium", children: messages.nextRunColumn }), _jsx("th", { className: "px-3 py-2 font-medium", children: messages.lastRunColumn }), _jsx("th", { className: "px-3 py-2 font-medium", children: messages.statusColumn }), onTriggerNow ? (_jsx("th", { className: "px-3 py-2 font-medium", children: messages.actionsColumn })) : null] }) }), _jsx("tbody", { children: rows.map((row) => (_jsx(ScheduleRow, { row: row, lastRun: lastRuns[row.workflowId] ?? null, triggering: !!triggering[row.scheduleId], onTriggerNow: onTriggerNow ? () => void triggerRow(row) : undefined, envFlagDisabled: showEnvFlag && !envFlagOn, rootMessages: rootMessages }, row.scheduleId))) })] }) })) : null] })] }));
|
|
80
|
+
}
|
|
81
|
+
function ScheduleRow({ row, lastRun, triggering, onTriggerNow, envFlagDisabled, rootMessages, }) {
|
|
82
|
+
const messages = rootMessages.schedules;
|
|
83
|
+
return (_jsxs("tr", { className: "border-t", children: [_jsx("td", { className: "px-3 py-2 font-mono text-xs", children: row.workflowId }), _jsx("td", { className: "px-3 py-2 font-mono text-xs", children: formatScheduleDecl(row.schedule, messages) }), _jsx("td", { className: "px-3 py-2 text-xs text-muted-foreground", children: formatNextRun(row, messages, rootMessages) }), _jsx("td", { className: "px-3 py-2 text-xs", children: formatLastRun(lastRun, messages, rootMessages) }), _jsx("td", { className: "px-3 py-2", children: _jsx(StatusPill, { row: row, envFlagDisabled: envFlagDisabled, messages: messages }) }), onTriggerNow ? (_jsx("td", { className: "px-3 py-2", children: _jsx(Button, { type: "button", size: "sm", variant: "outline", onClick: onTriggerNow, disabled: triggering, children: triggering ? messages.triggering : messages.triggerNow }) })) : null] }));
|
|
84
|
+
}
|
|
85
|
+
function StatusPill({ row, envFlagDisabled, messages, }) {
|
|
86
|
+
if (envFlagDisabled) {
|
|
87
|
+
return (_jsx(Badge, { variant: "outline", className: "border-muted-foreground/30 text-muted-foreground", children: messages.disabledByEnvFlag }));
|
|
88
|
+
}
|
|
89
|
+
if (row.disabledReason === "registration_disabled") {
|
|
90
|
+
return (_jsx(Badge, { variant: "outline", className: "border-muted-foreground/30 text-muted-foreground", children: messages.disabledByRegistration }));
|
|
91
|
+
}
|
|
92
|
+
if (row.disabledReason === "env_filtered") {
|
|
93
|
+
return (_jsx(Badge, { variant: "outline", className: "border-muted-foreground/30 text-muted-foreground", children: messages.disabledByEnvironment }));
|
|
94
|
+
}
|
|
95
|
+
return (_jsx(Badge, { variant: "outline", className: "border-emerald-500/40 bg-emerald-500/10 text-emerald-600 dark:text-emerald-300", children: messages.enabled }));
|
|
96
|
+
}
|
|
97
|
+
function formatScheduleDecl(decl, messages) {
|
|
98
|
+
if (decl.cron)
|
|
99
|
+
return messages.cron(decl.cron, decl.timezone ?? "UTC");
|
|
100
|
+
if (decl.every !== undefined)
|
|
101
|
+
return messages.every(String(decl.every));
|
|
102
|
+
if (decl.at)
|
|
103
|
+
return messages.at(decl.at);
|
|
104
|
+
return messages.eventDriven;
|
|
105
|
+
}
|
|
106
|
+
function formatNextRun(row, messages, rootMessages) {
|
|
107
|
+
if (!row.enabled || row.nextRunAt === null)
|
|
108
|
+
return messages.notScheduled;
|
|
109
|
+
const delta = row.nextRunAt - Date.now();
|
|
110
|
+
const relative = formatRelative(new Date(row.nextRunAt).toISOString(), rootMessages);
|
|
111
|
+
return delta >= 0 ? messages.inFuture(relative) : messages.inPast(relative);
|
|
112
|
+
}
|
|
113
|
+
function formatLastRun(lastRun, messages, rootMessages) {
|
|
114
|
+
if (!lastRun)
|
|
115
|
+
return _jsx("span", { className: "text-muted-foreground", children: messages.lastRunNone });
|
|
116
|
+
const relative = formatRelative(lastRun.startedAt, rootMessages);
|
|
117
|
+
const label = lastRunLabel(lastRun.status, relative, messages);
|
|
118
|
+
return (_jsxs("span", { className: "inline-flex items-center gap-1.5", children: [_jsx(StatusIcon, { status: lastRun.status }), label] }));
|
|
119
|
+
}
|
|
120
|
+
function lastRunLabel(status, relative, messages) {
|
|
121
|
+
switch (status) {
|
|
122
|
+
case "succeeded":
|
|
123
|
+
return messages.lastRunSucceeded(relative);
|
|
124
|
+
case "failed":
|
|
125
|
+
return messages.lastRunFailed(relative);
|
|
126
|
+
case "running":
|
|
127
|
+
return messages.lastRunRunning;
|
|
128
|
+
case "cancelled":
|
|
129
|
+
return messages.lastRunCancelled(relative);
|
|
130
|
+
}
|
|
131
|
+
}
|
package/dist/i18n/en.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"en.d.ts","sourceRoot":"","sources":["../../src/i18n/en.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAA;AAE3D,eAAO,MAAM,gBAAgB,EAAE,
|
|
1
|
+
{"version":3,"file":"en.d.ts","sourceRoot":"","sources":["../../src/i18n/en.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAA;AAE3D,eAAO,MAAM,gBAAgB,EAAE,sBAwI9B,CAAA;AAED,eAAO,MAAM,aAAa,wBAAmB,CAAA"}
|
package/dist/i18n/en.js
CHANGED
|
@@ -92,5 +92,43 @@ export const workflowRunsUiEn = {
|
|
|
92
92
|
format: {
|
|
93
93
|
relativeNow: "now",
|
|
94
94
|
},
|
|
95
|
+
schedules: {
|
|
96
|
+
title: "Workflow schedules",
|
|
97
|
+
subtitle: "Registered cron, interval, and one-shot schedules.",
|
|
98
|
+
environmentLabel: "Environment",
|
|
99
|
+
versionLabel: "Manifest",
|
|
100
|
+
workflowColumn: "Workflow",
|
|
101
|
+
scheduleColumn: "Schedule",
|
|
102
|
+
nextRunColumn: "Next run",
|
|
103
|
+
lastRunColumn: "Last run",
|
|
104
|
+
statusColumn: "Status",
|
|
105
|
+
actionsColumn: "Actions",
|
|
106
|
+
enabled: "Enabled",
|
|
107
|
+
disabledByRegistration: "Disabled",
|
|
108
|
+
disabledByEnvironment: "Disabled (env filtered)",
|
|
109
|
+
disabledByEnvFlag: "Disabled (env flag)",
|
|
110
|
+
envFlagOff: "Schedules disabled by environment flag — no schedules will fire.",
|
|
111
|
+
envFlagOn: "Schedules enabled.",
|
|
112
|
+
eventDriven: "event-driven",
|
|
113
|
+
cron: (expr, timezone) => `${expr} (${timezone})`,
|
|
114
|
+
every: (interval) => `every ${interval}`,
|
|
115
|
+
at: (timestamp) => `at ${timestamp}`,
|
|
116
|
+
triggerNow: "Trigger now",
|
|
117
|
+
triggering: "Triggering...",
|
|
118
|
+
triggerSuccess: "Run started.",
|
|
119
|
+
triggerFailed: "Trigger failed.",
|
|
120
|
+
refresh: "Refresh",
|
|
121
|
+
loading: "Loading schedules...",
|
|
122
|
+
loadError: "Could not load workflow schedules.",
|
|
123
|
+
empty: "No schedules registered for this environment.",
|
|
124
|
+
inFuture: (relative) => `in ${relative}`,
|
|
125
|
+
inPast: (relative) => `${relative} ago`,
|
|
126
|
+
notScheduled: "—",
|
|
127
|
+
lastRunSucceeded: (relative) => `succeeded ${relative} ago`,
|
|
128
|
+
lastRunFailed: (relative) => `failed ${relative} ago`,
|
|
129
|
+
lastRunRunning: "running",
|
|
130
|
+
lastRunCancelled: (relative) => `cancelled ${relative} ago`,
|
|
131
|
+
lastRunNone: "never run",
|
|
132
|
+
},
|
|
95
133
|
};
|
|
96
134
|
export const workflowsUiEn = workflowRunsUiEn;
|
package/dist/i18n/messages.d.ts
CHANGED
|
@@ -82,5 +82,43 @@ export type WorkflowRunsUiMessages = {
|
|
|
82
82
|
format: {
|
|
83
83
|
relativeNow: string;
|
|
84
84
|
};
|
|
85
|
+
schedules: {
|
|
86
|
+
title: string;
|
|
87
|
+
subtitle: string;
|
|
88
|
+
environmentLabel: string;
|
|
89
|
+
versionLabel: string;
|
|
90
|
+
workflowColumn: string;
|
|
91
|
+
scheduleColumn: string;
|
|
92
|
+
nextRunColumn: string;
|
|
93
|
+
lastRunColumn: string;
|
|
94
|
+
statusColumn: string;
|
|
95
|
+
actionsColumn: string;
|
|
96
|
+
enabled: string;
|
|
97
|
+
disabledByRegistration: string;
|
|
98
|
+
disabledByEnvironment: string;
|
|
99
|
+
disabledByEnvFlag: string;
|
|
100
|
+
envFlagOff: string;
|
|
101
|
+
envFlagOn: string;
|
|
102
|
+
eventDriven: string;
|
|
103
|
+
cron: (expr: string, timezone: string) => string;
|
|
104
|
+
every: (interval: string) => string;
|
|
105
|
+
at: (timestamp: string) => string;
|
|
106
|
+
triggerNow: string;
|
|
107
|
+
triggering: string;
|
|
108
|
+
triggerSuccess: string;
|
|
109
|
+
triggerFailed: string;
|
|
110
|
+
refresh: string;
|
|
111
|
+
loading: string;
|
|
112
|
+
loadError: string;
|
|
113
|
+
empty: string;
|
|
114
|
+
inFuture: (relative: string) => string;
|
|
115
|
+
inPast: (relative: string) => string;
|
|
116
|
+
notScheduled: string;
|
|
117
|
+
lastRunSucceeded: (relative: string) => string;
|
|
118
|
+
lastRunFailed: (relative: string) => string;
|
|
119
|
+
lastRunRunning: string;
|
|
120
|
+
lastRunCancelled: (relative: string) => string;
|
|
121
|
+
lastRunNone: string;
|
|
122
|
+
};
|
|
85
123
|
};
|
|
86
124
|
//# sourceMappingURL=messages.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/i18n/messages.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/i18n/messages.ts"],"names":[],"mappings":"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"}
|
package/dist/i18n/ro.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ro.d.ts","sourceRoot":"","sources":["../../src/i18n/ro.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAA;AAE3D,eAAO,MAAM,gBAAgB,EAAE,
|
|
1
|
+
{"version":3,"file":"ro.d.ts","sourceRoot":"","sources":["../../src/i18n/ro.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAA;AAE3D,eAAO,MAAM,gBAAgB,EAAE,sBA0I9B,CAAA;AAED,eAAO,MAAM,aAAa,wBAAmB,CAAA"}
|
package/dist/i18n/ro.js
CHANGED
|
@@ -94,5 +94,43 @@ export const workflowRunsUiRo = {
|
|
|
94
94
|
format: {
|
|
95
95
|
relativeNow: "acum",
|
|
96
96
|
},
|
|
97
|
+
schedules: {
|
|
98
|
+
title: "Programari workflow",
|
|
99
|
+
subtitle: "Programari cron, interval si one-shot inregistrate.",
|
|
100
|
+
environmentLabel: "Mediu",
|
|
101
|
+
versionLabel: "Manifest",
|
|
102
|
+
workflowColumn: "Workflow",
|
|
103
|
+
scheduleColumn: "Programare",
|
|
104
|
+
nextRunColumn: "Urmatoarea rulare",
|
|
105
|
+
lastRunColumn: "Ultima rulare",
|
|
106
|
+
statusColumn: "Status",
|
|
107
|
+
actionsColumn: "Actiuni",
|
|
108
|
+
enabled: "Activ",
|
|
109
|
+
disabledByRegistration: "Dezactivat",
|
|
110
|
+
disabledByEnvironment: "Dezactivat (filtrat dupa mediu)",
|
|
111
|
+
disabledByEnvFlag: "Dezactivat (flag de mediu)",
|
|
112
|
+
envFlagOff: "Programarile sunt dezactivate de flag-ul de mediu — nimic nu va rula.",
|
|
113
|
+
envFlagOn: "Programarile sunt active.",
|
|
114
|
+
eventDriven: "declansat de eveniment",
|
|
115
|
+
cron: (expr, timezone) => `${expr} (${timezone})`,
|
|
116
|
+
every: (interval) => `la fiecare ${interval}`,
|
|
117
|
+
at: (timestamp) => `la ${timestamp}`,
|
|
118
|
+
triggerNow: "Declanseaza acum",
|
|
119
|
+
triggering: "Se declanseaza...",
|
|
120
|
+
triggerSuccess: "Rulare pornita.",
|
|
121
|
+
triggerFailed: "Declansarea a esuat.",
|
|
122
|
+
refresh: "Reincarca",
|
|
123
|
+
loading: "Se incarca programarile...",
|
|
124
|
+
loadError: "Programarile nu au putut fi incarcate.",
|
|
125
|
+
empty: "Nu exista programari inregistrate pentru acest mediu.",
|
|
126
|
+
inFuture: (relative) => `in ${relative}`,
|
|
127
|
+
inPast: (relative) => `acum ${relative}`,
|
|
128
|
+
notScheduled: "—",
|
|
129
|
+
lastRunSucceeded: (relative) => `reusita acum ${relative}`,
|
|
130
|
+
lastRunFailed: (relative) => `esuata acum ${relative}`,
|
|
131
|
+
lastRunRunning: "in rulare",
|
|
132
|
+
lastRunCancelled: (relative) => `anulata acum ${relative}`,
|
|
133
|
+
lastRunNone: "nu a rulat niciodata",
|
|
134
|
+
},
|
|
97
135
|
};
|
|
98
136
|
export const workflowsUiRo = workflowRunsUiRo;
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ export type { WorkflowRunsApiClientOptions } from "./client.js";
|
|
|
2
2
|
export { createWorkflowRunsApiClient } from "./client.js";
|
|
3
3
|
export { WorkflowRunDetailPage, type WorkflowRunDetailPageProps, } from "./components/workflow-run-detail-page.js";
|
|
4
4
|
export { WorkflowRunsPage, type WorkflowRunsPageProps, WorkflowRunsPageSkeleton, } from "./components/workflow-runs-page.js";
|
|
5
|
+
export { WorkflowSchedulesPage, type WorkflowSchedulesPageProps, } from "./components/workflow-schedules-page.js";
|
|
5
6
|
export { getWorkflowRunsUiI18n, getWorkflowRunsUiI18n as getWorkflowsUiI18n, resolveWorkflowRunsUiMessages, resolveWorkflowRunsUiMessages as resolveWorkflowsUiMessages, useWorkflowRunsUiI18n, useWorkflowRunsUiI18n as useWorkflowsUiI18n, useWorkflowRunsUiI18nOrDefault, useWorkflowRunsUiI18nOrDefault as useWorkflowsUiI18nOrDefault, useWorkflowRunsUiMessages, useWorkflowRunsUiMessages as useWorkflowsUiMessages, useWorkflowRunsUiMessagesOrDefault, useWorkflowRunsUiMessagesOrDefault as useWorkflowsUiMessagesOrDefault, type WorkflowRunsUiMessageOverrides, type WorkflowRunsUiMessageOverrides as WorkflowsUiMessageOverrides, type WorkflowRunsUiMessages, type WorkflowRunsUiMessages as WorkflowsUiMessages, WorkflowRunsUiMessagesProvider, WorkflowRunsUiMessagesProvider as WorkflowsUiMessagesProvider, workflowRunsUiEn, workflowRunsUiEn as workflowsUiEn, workflowRunsUiMessageDefinitions, workflowRunsUiMessageDefinitions as workflowsUiMessageDefinitions, workflowRunsUiRo, workflowRunsUiRo as workflowsUiRo, } from "./i18n/index.js";
|
|
7
|
+
export { createWorkflowSchedulesApiClient, type ListWorkflowSchedulesResponse, type WorkflowScheduleDecl, type WorkflowScheduleSummary, type WorkflowSchedulesApi, type WorkflowSchedulesApiClientOptions, } from "./schedules-client.js";
|
|
6
8
|
export type { ListWorkflowRunsQuery, ListWorkflowRunsResponse, WorkflowRun, WorkflowRunActionError, WorkflowRunActionResponse, WorkflowRunActionResult, WorkflowRunDetailResponse, WorkflowRunErrorPayload, WorkflowRunStatus, WorkflowRunStep, WorkflowRunStepStatus, WorkflowRunsApi, } from "./types.js";
|
|
7
9
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,4BAA4B,EAAE,MAAM,aAAa,CAAA;AAC/D,OAAO,EAAE,2BAA2B,EAAE,MAAM,aAAa,CAAA;AACzD,OAAO,EACL,qBAAqB,EACrB,KAAK,0BAA0B,GAChC,MAAM,0CAA0C,CAAA;AACjD,OAAO,EACL,gBAAgB,EAChB,KAAK,qBAAqB,EAC1B,wBAAwB,GACzB,MAAM,oCAAoC,CAAA;AAC3C,OAAO,EACL,qBAAqB,EACrB,qBAAqB,IAAI,kBAAkB,EAC3C,6BAA6B,EAC7B,6BAA6B,IAAI,0BAA0B,EAC3D,qBAAqB,EACrB,qBAAqB,IAAI,kBAAkB,EAC3C,8BAA8B,EAC9B,8BAA8B,IAAI,2BAA2B,EAC7D,yBAAyB,EACzB,yBAAyB,IAAI,sBAAsB,EACnD,kCAAkC,EAClC,kCAAkC,IAAI,+BAA+B,EACrE,KAAK,8BAA8B,EACnC,KAAK,8BAA8B,IAAI,2BAA2B,EAClE,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,IAAI,mBAAmB,EAClD,8BAA8B,EAC9B,8BAA8B,IAAI,2BAA2B,EAC7D,gBAAgB,EAChB,gBAAgB,IAAI,aAAa,EACjC,gCAAgC,EAChC,gCAAgC,IAAI,6BAA6B,EACjE,gBAAgB,EAChB,gBAAgB,IAAI,aAAa,GAClC,MAAM,iBAAiB,CAAA;AACxB,YAAY,EACV,qBAAqB,EACrB,wBAAwB,EACxB,WAAW,EACX,sBAAsB,EACtB,yBAAyB,EACzB,uBAAuB,EACvB,yBAAyB,EACzB,uBAAuB,EACvB,iBAAiB,EACjB,eAAe,EACf,qBAAqB,EACrB,eAAe,GAChB,MAAM,YAAY,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,4BAA4B,EAAE,MAAM,aAAa,CAAA;AAC/D,OAAO,EAAE,2BAA2B,EAAE,MAAM,aAAa,CAAA;AACzD,OAAO,EACL,qBAAqB,EACrB,KAAK,0BAA0B,GAChC,MAAM,0CAA0C,CAAA;AACjD,OAAO,EACL,gBAAgB,EAChB,KAAK,qBAAqB,EAC1B,wBAAwB,GACzB,MAAM,oCAAoC,CAAA;AAC3C,OAAO,EACL,qBAAqB,EACrB,KAAK,0BAA0B,GAChC,MAAM,yCAAyC,CAAA;AAChD,OAAO,EACL,qBAAqB,EACrB,qBAAqB,IAAI,kBAAkB,EAC3C,6BAA6B,EAC7B,6BAA6B,IAAI,0BAA0B,EAC3D,qBAAqB,EACrB,qBAAqB,IAAI,kBAAkB,EAC3C,8BAA8B,EAC9B,8BAA8B,IAAI,2BAA2B,EAC7D,yBAAyB,EACzB,yBAAyB,IAAI,sBAAsB,EACnD,kCAAkC,EAClC,kCAAkC,IAAI,+BAA+B,EACrE,KAAK,8BAA8B,EACnC,KAAK,8BAA8B,IAAI,2BAA2B,EAClE,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,IAAI,mBAAmB,EAClD,8BAA8B,EAC9B,8BAA8B,IAAI,2BAA2B,EAC7D,gBAAgB,EAChB,gBAAgB,IAAI,aAAa,EACjC,gCAAgC,EAChC,gCAAgC,IAAI,6BAA6B,EACjE,gBAAgB,EAChB,gBAAgB,IAAI,aAAa,GAClC,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,gCAAgC,EAChC,KAAK,6BAA6B,EAClC,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,EACzB,KAAK,iCAAiC,GACvC,MAAM,uBAAuB,CAAA;AAC9B,YAAY,EACV,qBAAqB,EACrB,wBAAwB,EACxB,WAAW,EACX,sBAAsB,EACtB,yBAAyB,EACzB,uBAAuB,EACvB,yBAAyB,EACzB,uBAAuB,EACvB,iBAAiB,EACjB,eAAe,EACf,qBAAqB,EACrB,eAAe,GAChB,MAAM,YAAY,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export { createWorkflowRunsApiClient } from "./client.js";
|
|
2
2
|
export { WorkflowRunDetailPage, } from "./components/workflow-run-detail-page.js";
|
|
3
3
|
export { WorkflowRunsPage, WorkflowRunsPageSkeleton, } from "./components/workflow-runs-page.js";
|
|
4
|
+
export { WorkflowSchedulesPage, } from "./components/workflow-schedules-page.js";
|
|
4
5
|
export { getWorkflowRunsUiI18n, getWorkflowRunsUiI18n as getWorkflowsUiI18n, resolveWorkflowRunsUiMessages, resolveWorkflowRunsUiMessages as resolveWorkflowsUiMessages, useWorkflowRunsUiI18n, useWorkflowRunsUiI18n as useWorkflowsUiI18n, useWorkflowRunsUiI18nOrDefault, useWorkflowRunsUiI18nOrDefault as useWorkflowsUiI18nOrDefault, useWorkflowRunsUiMessages, useWorkflowRunsUiMessages as useWorkflowsUiMessages, useWorkflowRunsUiMessagesOrDefault, useWorkflowRunsUiMessagesOrDefault as useWorkflowsUiMessagesOrDefault, WorkflowRunsUiMessagesProvider, WorkflowRunsUiMessagesProvider as WorkflowsUiMessagesProvider, workflowRunsUiEn, workflowRunsUiEn as workflowsUiEn, workflowRunsUiMessageDefinitions, workflowRunsUiMessageDefinitions as workflowsUiMessageDefinitions, workflowRunsUiRo, workflowRunsUiRo as workflowsUiRo, } from "./i18n/index.js";
|
|
6
|
+
export { createWorkflowSchedulesApiClient, } from "./schedules-client.js";
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { createWorkflowSchedulesApiClient, type ListWorkflowSchedulesResponse, type WorkflowScheduleDecl, type WorkflowScheduleSummary, type WorkflowSchedulesApi, type WorkflowSchedulesApiClientOptions, } from "@voyantjs/workflows-react/workflow-schedules-client";
|
|
2
|
+
//# sourceMappingURL=schedules-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schedules-client.d.ts","sourceRoot":"","sources":["../src/schedules-client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gCAAgC,EAChC,KAAK,6BAA6B,EAClC,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,EACzB,KAAK,iCAAiC,GACvC,MAAM,qDAAqD,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { createWorkflowSchedulesApiClient, } from "@voyantjs/workflows-react/workflow-schedules-client";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voyantjs/workflows-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.68.0",
|
|
4
4
|
"description": "Importable React admin UI for Voyant workflow run observability.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -46,14 +46,14 @@
|
|
|
46
46
|
}
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@voyantjs/i18n": "0.
|
|
50
|
-
"@voyantjs/workflows-react": "0.
|
|
49
|
+
"@voyantjs/i18n": "0.68.0",
|
|
50
|
+
"@voyantjs/workflows-react": "0.68.0"
|
|
51
51
|
},
|
|
52
52
|
"peerDependencies": {
|
|
53
53
|
"lucide-react": "^0.475.0 || ^1.0.0",
|
|
54
54
|
"react": "^19.0.0",
|
|
55
55
|
"react-dom": "^19.0.0",
|
|
56
|
-
"@voyantjs/ui": "0.
|
|
56
|
+
"@voyantjs/ui": "0.68.0"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
59
|
"@types/react": "^19.2.14",
|
|
@@ -63,9 +63,9 @@
|
|
|
63
63
|
"react-dom": "^19.2.4",
|
|
64
64
|
"typescript": "^6.0.2",
|
|
65
65
|
"vitest": "^4.1.2",
|
|
66
|
-
"@voyantjs/
|
|
67
|
-
"@voyantjs/
|
|
68
|
-
"@voyantjs/
|
|
66
|
+
"@voyantjs/ui": "0.68.0",
|
|
67
|
+
"@voyantjs/voyant-typescript-config": "0.1.0",
|
|
68
|
+
"@voyantjs/i18n": "0.68.0"
|
|
69
69
|
},
|
|
70
70
|
"files": [
|
|
71
71
|
"dist",
|
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { Badge } from "@voyantjs/ui/components/badge"
|
|
4
|
+
import { Button } from "@voyantjs/ui/components/button"
|
|
5
|
+
import { Card, CardContent } from "@voyantjs/ui/components/card"
|
|
6
|
+
import { AlertTriangle, CalendarClock, RefreshCw } from "lucide-react"
|
|
7
|
+
import { useCallback, useEffect, useMemo, useState } from "react"
|
|
8
|
+
|
|
9
|
+
import { useWorkflowRunsUiMessagesOrDefault, type WorkflowRunsUiMessages } from "../i18n/index.js"
|
|
10
|
+
import type {
|
|
11
|
+
ListWorkflowSchedulesResponse,
|
|
12
|
+
WorkflowScheduleDecl,
|
|
13
|
+
WorkflowScheduleSummary,
|
|
14
|
+
WorkflowSchedulesApi,
|
|
15
|
+
} from "../schedules-client.js"
|
|
16
|
+
import type { WorkflowRun, WorkflowRunStatus, WorkflowRunsApi } from "../types.js"
|
|
17
|
+
import { formatRelative, StatusIcon } from "./common.js"
|
|
18
|
+
|
|
19
|
+
type SchedulesMessages = WorkflowRunsUiMessages["schedules"]
|
|
20
|
+
|
|
21
|
+
export interface WorkflowSchedulesPageProps {
|
|
22
|
+
/** Schedules API — backed by `/api/schedules/:env`. */
|
|
23
|
+
schedulesApi: WorkflowSchedulesApi
|
|
24
|
+
/** Optional runs API — when provided, the page joins each row with the most recent matching run. */
|
|
25
|
+
runsApi?: WorkflowRunsApi
|
|
26
|
+
/**
|
|
27
|
+
* Optional trigger callback. When provided, each row renders a
|
|
28
|
+
* "Trigger now" button that calls this with the workflow id + the
|
|
29
|
+
* schedule's recorded `input` payload (if any).
|
|
30
|
+
*/
|
|
31
|
+
onTriggerNow?: (workflowId: string, input: unknown) => Promise<void>
|
|
32
|
+
/** Manifest environment to inspect. Defaults to "production". */
|
|
33
|
+
environment?: "production" | "preview" | "development"
|
|
34
|
+
/** Auto-refresh interval (ms). Defaults to 30s. Pass 0 to disable. */
|
|
35
|
+
pollIntervalMs?: number
|
|
36
|
+
className?: string
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function WorkflowSchedulesPage({
|
|
40
|
+
schedulesApi,
|
|
41
|
+
runsApi,
|
|
42
|
+
onTriggerNow,
|
|
43
|
+
environment = "production",
|
|
44
|
+
pollIntervalMs = 30_000,
|
|
45
|
+
className,
|
|
46
|
+
}: WorkflowSchedulesPageProps) {
|
|
47
|
+
const rootMessages = useWorkflowRunsUiMessagesOrDefault()
|
|
48
|
+
const messages = rootMessages.schedules
|
|
49
|
+
const [response, setResponse] = useState<ListWorkflowSchedulesResponse | null>(null)
|
|
50
|
+
const [lastRuns, setLastRuns] = useState<Record<string, WorkflowRun | null>>({})
|
|
51
|
+
const [loading, setLoading] = useState(false)
|
|
52
|
+
const [error, setError] = useState<string | null>(null)
|
|
53
|
+
const [triggering, setTriggering] = useState<Record<string, boolean>>({})
|
|
54
|
+
const [triggerNotice, setTriggerNotice] = useState<{
|
|
55
|
+
kind: "success" | "error"
|
|
56
|
+
text: string
|
|
57
|
+
} | null>(null)
|
|
58
|
+
|
|
59
|
+
const refresh = useCallback(async () => {
|
|
60
|
+
setLoading(true)
|
|
61
|
+
try {
|
|
62
|
+
const next = await schedulesApi.listSchedules(environment)
|
|
63
|
+
setResponse(next)
|
|
64
|
+
setError(null)
|
|
65
|
+
if (runsApi) {
|
|
66
|
+
const uniqueIds = Array.from(new Set(next.data.map((entry) => entry.workflowId)))
|
|
67
|
+
const results = await Promise.all(
|
|
68
|
+
uniqueIds.map(async (workflowId) => {
|
|
69
|
+
try {
|
|
70
|
+
const runs = await runsApi.listRuns({ workflowName: workflowId, limit: 1 })
|
|
71
|
+
return [workflowId, runs.data[0] ?? null] as const
|
|
72
|
+
} catch {
|
|
73
|
+
return [workflowId, null] as const
|
|
74
|
+
}
|
|
75
|
+
}),
|
|
76
|
+
)
|
|
77
|
+
setLastRuns(Object.fromEntries(results))
|
|
78
|
+
}
|
|
79
|
+
} catch (err) {
|
|
80
|
+
setError(err instanceof Error ? err.message : messages.loadError)
|
|
81
|
+
} finally {
|
|
82
|
+
setLoading(false)
|
|
83
|
+
}
|
|
84
|
+
}, [environment, messages.loadError, runsApi, schedulesApi])
|
|
85
|
+
|
|
86
|
+
useEffect(() => {
|
|
87
|
+
void refresh()
|
|
88
|
+
if (!pollIntervalMs) return
|
|
89
|
+
const interval = setInterval(() => void refresh(), pollIntervalMs)
|
|
90
|
+
return () => clearInterval(interval)
|
|
91
|
+
}, [pollIntervalMs, refresh])
|
|
92
|
+
|
|
93
|
+
const showEnvFlag = response?.schedulesEnabledByEnv !== undefined
|
|
94
|
+
const envFlagOn = response?.schedulesEnabledByEnv === true
|
|
95
|
+
|
|
96
|
+
const triggerRow = useCallback(
|
|
97
|
+
async (entry: WorkflowScheduleSummary) => {
|
|
98
|
+
if (!onTriggerNow) return
|
|
99
|
+
setTriggering((prev) => ({ ...prev, [entry.scheduleId]: true }))
|
|
100
|
+
setTriggerNotice(null)
|
|
101
|
+
try {
|
|
102
|
+
await onTriggerNow(entry.workflowId, entry.schedule.input)
|
|
103
|
+
setTriggerNotice({ kind: "success", text: messages.triggerSuccess })
|
|
104
|
+
} catch (err) {
|
|
105
|
+
setTriggerNotice({
|
|
106
|
+
kind: "error",
|
|
107
|
+
text: err instanceof Error ? err.message : messages.triggerFailed,
|
|
108
|
+
})
|
|
109
|
+
} finally {
|
|
110
|
+
setTriggering((prev) => ({ ...prev, [entry.scheduleId]: false }))
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
[messages.triggerFailed, messages.triggerSuccess, onTriggerNow],
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
const rows = useMemo(() => response?.data ?? [], [response])
|
|
117
|
+
|
|
118
|
+
return (
|
|
119
|
+
<div className={`flex min-h-screen flex-col bg-background ${className ?? ""}`}>
|
|
120
|
+
<header className="sticky top-0 z-10 border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
|
|
121
|
+
<div className="container mx-auto flex flex-wrap items-center gap-3 px-4 py-3">
|
|
122
|
+
<CalendarClock className="h-5 w-5" />
|
|
123
|
+
<div className="min-w-0">
|
|
124
|
+
<h1 className="font-semibold text-base">{messages.title}</h1>
|
|
125
|
+
<p className="text-muted-foreground text-xs">{messages.subtitle}</p>
|
|
126
|
+
</div>
|
|
127
|
+
<div className="ml-auto flex items-center gap-2 text-muted-foreground text-xs">
|
|
128
|
+
<span>
|
|
129
|
+
{messages.environmentLabel}: <span className="font-mono">{environment}</span>
|
|
130
|
+
</span>
|
|
131
|
+
{response?.versionId ? (
|
|
132
|
+
<span>
|
|
133
|
+
{messages.versionLabel}:{" "}
|
|
134
|
+
<span className="font-mono">{response.versionId.slice(0, 12)}</span>
|
|
135
|
+
</span>
|
|
136
|
+
) : null}
|
|
137
|
+
<Button
|
|
138
|
+
type="button"
|
|
139
|
+
variant="outline"
|
|
140
|
+
size="sm"
|
|
141
|
+
onClick={() => void refresh()}
|
|
142
|
+
disabled={loading}
|
|
143
|
+
>
|
|
144
|
+
<RefreshCw
|
|
145
|
+
className={`h-3.5 w-3.5 ${loading ? "animate-spin" : ""}`}
|
|
146
|
+
aria-hidden="true"
|
|
147
|
+
/>
|
|
148
|
+
{messages.refresh}
|
|
149
|
+
</Button>
|
|
150
|
+
</div>
|
|
151
|
+
</div>
|
|
152
|
+
</header>
|
|
153
|
+
|
|
154
|
+
<main className="container mx-auto flex flex-1 flex-col gap-4 px-4 py-6">
|
|
155
|
+
{showEnvFlag && !envFlagOn ? (
|
|
156
|
+
<Card className="border-amber-500/40 bg-amber-500/5">
|
|
157
|
+
<CardContent className="flex items-center gap-2 pt-4 text-amber-700 text-sm dark:text-amber-300">
|
|
158
|
+
<AlertTriangle className="h-4 w-4" aria-hidden="true" />
|
|
159
|
+
{messages.envFlagOff}
|
|
160
|
+
</CardContent>
|
|
161
|
+
</Card>
|
|
162
|
+
) : null}
|
|
163
|
+
|
|
164
|
+
{triggerNotice ? (
|
|
165
|
+
<Card
|
|
166
|
+
className={
|
|
167
|
+
triggerNotice.kind === "success"
|
|
168
|
+
? "border-emerald-500/40 bg-emerald-500/5"
|
|
169
|
+
: "border-destructive/40 bg-destructive/5"
|
|
170
|
+
}
|
|
171
|
+
>
|
|
172
|
+
<CardContent
|
|
173
|
+
className={`pt-4 text-sm ${
|
|
174
|
+
triggerNotice.kind === "success"
|
|
175
|
+
? "text-emerald-600 dark:text-emerald-300"
|
|
176
|
+
: "text-destructive"
|
|
177
|
+
}`}
|
|
178
|
+
>
|
|
179
|
+
{triggerNotice.text}
|
|
180
|
+
</CardContent>
|
|
181
|
+
</Card>
|
|
182
|
+
) : null}
|
|
183
|
+
|
|
184
|
+
{error ? (
|
|
185
|
+
<Card className="border-destructive/40">
|
|
186
|
+
<CardContent className="pt-4 text-destructive text-sm">{error}</CardContent>
|
|
187
|
+
</Card>
|
|
188
|
+
) : null}
|
|
189
|
+
|
|
190
|
+
{!error && rows.length === 0 && !loading ? (
|
|
191
|
+
<Card>
|
|
192
|
+
<CardContent className="pt-4 text-muted-foreground text-sm">
|
|
193
|
+
{messages.empty}
|
|
194
|
+
</CardContent>
|
|
195
|
+
</Card>
|
|
196
|
+
) : null}
|
|
197
|
+
|
|
198
|
+
{rows.length > 0 ? (
|
|
199
|
+
<div className="overflow-hidden rounded-md border">
|
|
200
|
+
<table className="w-full text-sm">
|
|
201
|
+
<thead className="bg-muted/40 text-left text-xs uppercase">
|
|
202
|
+
<tr>
|
|
203
|
+
<th className="px-3 py-2 font-medium">{messages.workflowColumn}</th>
|
|
204
|
+
<th className="px-3 py-2 font-medium">{messages.scheduleColumn}</th>
|
|
205
|
+
<th className="px-3 py-2 font-medium">{messages.nextRunColumn}</th>
|
|
206
|
+
<th className="px-3 py-2 font-medium">{messages.lastRunColumn}</th>
|
|
207
|
+
<th className="px-3 py-2 font-medium">{messages.statusColumn}</th>
|
|
208
|
+
{onTriggerNow ? (
|
|
209
|
+
<th className="px-3 py-2 font-medium">{messages.actionsColumn}</th>
|
|
210
|
+
) : null}
|
|
211
|
+
</tr>
|
|
212
|
+
</thead>
|
|
213
|
+
<tbody>
|
|
214
|
+
{rows.map((row) => (
|
|
215
|
+
<ScheduleRow
|
|
216
|
+
key={row.scheduleId}
|
|
217
|
+
row={row}
|
|
218
|
+
lastRun={lastRuns[row.workflowId] ?? null}
|
|
219
|
+
triggering={!!triggering[row.scheduleId]}
|
|
220
|
+
onTriggerNow={onTriggerNow ? () => void triggerRow(row) : undefined}
|
|
221
|
+
envFlagDisabled={showEnvFlag && !envFlagOn}
|
|
222
|
+
rootMessages={rootMessages}
|
|
223
|
+
/>
|
|
224
|
+
))}
|
|
225
|
+
</tbody>
|
|
226
|
+
</table>
|
|
227
|
+
</div>
|
|
228
|
+
) : null}
|
|
229
|
+
</main>
|
|
230
|
+
</div>
|
|
231
|
+
)
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function ScheduleRow({
|
|
235
|
+
row,
|
|
236
|
+
lastRun,
|
|
237
|
+
triggering,
|
|
238
|
+
onTriggerNow,
|
|
239
|
+
envFlagDisabled,
|
|
240
|
+
rootMessages,
|
|
241
|
+
}: {
|
|
242
|
+
row: WorkflowScheduleSummary
|
|
243
|
+
lastRun: WorkflowRun | null
|
|
244
|
+
triggering: boolean
|
|
245
|
+
onTriggerNow?: () => void
|
|
246
|
+
envFlagDisabled: boolean
|
|
247
|
+
rootMessages: WorkflowRunsUiMessages
|
|
248
|
+
}) {
|
|
249
|
+
const messages = rootMessages.schedules
|
|
250
|
+
|
|
251
|
+
return (
|
|
252
|
+
<tr className="border-t">
|
|
253
|
+
<td className="px-3 py-2 font-mono text-xs">{row.workflowId}</td>
|
|
254
|
+
<td className="px-3 py-2 font-mono text-xs">{formatScheduleDecl(row.schedule, messages)}</td>
|
|
255
|
+
<td className="px-3 py-2 text-xs text-muted-foreground">
|
|
256
|
+
{formatNextRun(row, messages, rootMessages)}
|
|
257
|
+
</td>
|
|
258
|
+
<td className="px-3 py-2 text-xs">{formatLastRun(lastRun, messages, rootMessages)}</td>
|
|
259
|
+
<td className="px-3 py-2">
|
|
260
|
+
<StatusPill row={row} envFlagDisabled={envFlagDisabled} messages={messages} />
|
|
261
|
+
</td>
|
|
262
|
+
{onTriggerNow ? (
|
|
263
|
+
<td className="px-3 py-2">
|
|
264
|
+
<Button
|
|
265
|
+
type="button"
|
|
266
|
+
size="sm"
|
|
267
|
+
variant="outline"
|
|
268
|
+
onClick={onTriggerNow}
|
|
269
|
+
disabled={triggering}
|
|
270
|
+
>
|
|
271
|
+
{triggering ? messages.triggering : messages.triggerNow}
|
|
272
|
+
</Button>
|
|
273
|
+
</td>
|
|
274
|
+
) : null}
|
|
275
|
+
</tr>
|
|
276
|
+
)
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function StatusPill({
|
|
280
|
+
row,
|
|
281
|
+
envFlagDisabled,
|
|
282
|
+
messages,
|
|
283
|
+
}: {
|
|
284
|
+
row: WorkflowScheduleSummary
|
|
285
|
+
envFlagDisabled: boolean
|
|
286
|
+
messages: SchedulesMessages
|
|
287
|
+
}) {
|
|
288
|
+
if (envFlagDisabled) {
|
|
289
|
+
return (
|
|
290
|
+
<Badge variant="outline" className="border-muted-foreground/30 text-muted-foreground">
|
|
291
|
+
{messages.disabledByEnvFlag}
|
|
292
|
+
</Badge>
|
|
293
|
+
)
|
|
294
|
+
}
|
|
295
|
+
if (row.disabledReason === "registration_disabled") {
|
|
296
|
+
return (
|
|
297
|
+
<Badge variant="outline" className="border-muted-foreground/30 text-muted-foreground">
|
|
298
|
+
{messages.disabledByRegistration}
|
|
299
|
+
</Badge>
|
|
300
|
+
)
|
|
301
|
+
}
|
|
302
|
+
if (row.disabledReason === "env_filtered") {
|
|
303
|
+
return (
|
|
304
|
+
<Badge variant="outline" className="border-muted-foreground/30 text-muted-foreground">
|
|
305
|
+
{messages.disabledByEnvironment}
|
|
306
|
+
</Badge>
|
|
307
|
+
)
|
|
308
|
+
}
|
|
309
|
+
return (
|
|
310
|
+
<Badge
|
|
311
|
+
variant="outline"
|
|
312
|
+
className="border-emerald-500/40 bg-emerald-500/10 text-emerald-600 dark:text-emerald-300"
|
|
313
|
+
>
|
|
314
|
+
{messages.enabled}
|
|
315
|
+
</Badge>
|
|
316
|
+
)
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
function formatScheduleDecl(decl: WorkflowScheduleDecl, messages: SchedulesMessages): string {
|
|
320
|
+
if (decl.cron) return messages.cron(decl.cron, decl.timezone ?? "UTC")
|
|
321
|
+
if (decl.every !== undefined) return messages.every(String(decl.every))
|
|
322
|
+
if (decl.at) return messages.at(decl.at)
|
|
323
|
+
return messages.eventDriven
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
function formatNextRun(
|
|
327
|
+
row: WorkflowScheduleSummary,
|
|
328
|
+
messages: SchedulesMessages,
|
|
329
|
+
rootMessages: WorkflowRunsUiMessages,
|
|
330
|
+
): string {
|
|
331
|
+
if (!row.enabled || row.nextRunAt === null) return messages.notScheduled
|
|
332
|
+
const delta = row.nextRunAt - Date.now()
|
|
333
|
+
const relative = formatRelative(new Date(row.nextRunAt).toISOString(), rootMessages)
|
|
334
|
+
return delta >= 0 ? messages.inFuture(relative) : messages.inPast(relative)
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
function formatLastRun(
|
|
338
|
+
lastRun: WorkflowRun | null,
|
|
339
|
+
messages: SchedulesMessages,
|
|
340
|
+
rootMessages: WorkflowRunsUiMessages,
|
|
341
|
+
) {
|
|
342
|
+
if (!lastRun) return <span className="text-muted-foreground">{messages.lastRunNone}</span>
|
|
343
|
+
const relative = formatRelative(lastRun.startedAt, rootMessages)
|
|
344
|
+
const label = lastRunLabel(lastRun.status, relative, messages)
|
|
345
|
+
return (
|
|
346
|
+
<span className="inline-flex items-center gap-1.5">
|
|
347
|
+
<StatusIcon status={lastRun.status} />
|
|
348
|
+
{label}
|
|
349
|
+
</span>
|
|
350
|
+
)
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
function lastRunLabel(
|
|
354
|
+
status: WorkflowRunStatus,
|
|
355
|
+
relative: string,
|
|
356
|
+
messages: SchedulesMessages,
|
|
357
|
+
): string {
|
|
358
|
+
switch (status) {
|
|
359
|
+
case "succeeded":
|
|
360
|
+
return messages.lastRunSucceeded(relative)
|
|
361
|
+
case "failed":
|
|
362
|
+
return messages.lastRunFailed(relative)
|
|
363
|
+
case "running":
|
|
364
|
+
return messages.lastRunRunning
|
|
365
|
+
case "cancelled":
|
|
366
|
+
return messages.lastRunCancelled(relative)
|
|
367
|
+
}
|
|
368
|
+
}
|