@burdenoff/fluidgrids-fe-sdk 2026.1112.4 → 2026.1112.5
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/{AiStudioPage-C-jio5Bz.js → AiStudioPage-BNmXx6LB.js} +10 -10
- package/dist/{ApprovalInboxPage-D8vhnloO.js → ApprovalInboxPage-QAJim81n.js} +3 -2
- package/dist/{DataSinkDashboardPage-CRBsNjoS.js → DataSinkDashboardPage-kyzcjpzL.js} +4 -4
- package/dist/{DataTablesPage-DoVBkb_T.js → DataTablesPage-Dm-dzVPD.js} +4 -4
- package/dist/{EntityTagPicker-Dk3CufFt.js → EntityTagPicker-dxfzv8aO.js} +1 -1
- package/dist/{ExecutionDetailPage-Cw4zyaIG.js → ExecutionDetailPage-B9eEep77.js} +977 -509
- package/dist/{ExecutionsListPage-BgeqwVr2.js → ExecutionsListPage-DuuPSVEj.js} +831 -146
- package/dist/{FailureTriagePanel-BzD4UJU5.js → FailureTriagePanel-D4lJ4zqQ.js} +1 -1
- package/dist/{FluidGridsProvider-BFfTxl9m.js → FluidGridsProvider-B1hgCbxG.js} +7 -7
- package/dist/{HistoryPage-DktteURI.js → HistoryPage-C7NwkVNC.js} +4 -4
- package/dist/{HumanRequestCard-mOhr-Ic9.js → HumanRequestCard-lbWDpWd7.js} +4 -216
- package/dist/{InsightsPage-2jnYlozA.js → InsightsPage-D9B_qW8e.js} +10 -10
- package/dist/{MissingNodesInstallModal-C0wPwR0Q.js → MissingNodesInstallModal-BkkgeFeN.js} +1 -1
- package/dist/{NodesPage-Dhg5Q2R5.js → NodesPage-BEeUbIts.js} +4 -4
- package/dist/{QuotaExhaustedDialog-BKZ9moP8.js → QuotaExhaustedDialog-Bj7AG_0y.js} +1 -1
- package/dist/{RunnersPage-CLCOCclc.js → RunnersPage-D9Bgod_d.js} +4 -4
- package/dist/{SettingsPage-BaM98QU_.js → SettingsPage-k21044-Z.js} +16 -16
- package/dist/{TagFilterSelect-VC6JMK3F.js → TagFilterSelect-CqhxcDjh.js} +1 -1
- package/dist/{TaskQueuesPage-C3R5ZoKs.js → TaskQueuesPage-B86p51gH.js} +2 -2
- package/dist/{TemplateCard-DYDVNYo6.js → TemplateCard-DanOe65C.js} +3 -3
- package/dist/{TemplateConfigurationModal-BzdkGWim.js → TemplateConfigurationModal-CeMpPEhT.js} +3 -3
- package/dist/{TemplateDetailPanel-s4EqQhra.js → TemplateDetailPanel-DnoA6mC3.js} +2 -2
- package/dist/{TemplatePreview-B_-zS_Mm.js → TemplatePreview-CBwvi0ga.js} +4 -4
- package/dist/{TemplatesPage-OIMd6cIl.js → TemplatesPage-C7f2xq12.js} +14 -14
- package/dist/{VariablesPage-67WR_lVE.js → VariablesPage-BtoLjmUA.js} +1 -1
- package/dist/{VersionDiffDialog-Cp2doV3f.js → VersionDiffDialog-pLpG_I1r.js} +4 -4
- package/dist/{WorkflowBuilder-B2tIOPi0.js → WorkflowBuilder-DDgWgnwH.js} +7 -7
- package/dist/{WorkflowBuilder-DD4UIAjC.js → WorkflowBuilder-DmYS5JEY.js} +12 -12
- package/dist/{WorkflowProposalCard-U31u1qcw.js → WorkflowProposalCard-BjYAZH3q.js} +1 -1
- package/dist/{WorkflowSearchRedirect-BhXzWDj7.js → WorkflowSearchRedirect-iPQBL6WO.js} +1 -1
- package/dist/{WorkflowShareDialog-Dv46nAyh.js → WorkflowShareDialog-DB-qJLB2.js} +1 -1
- package/dist/{WorkflowsList-BV-2J_gG.js → WorkflowsList-rOxlI49U.js} +13 -13
- package/dist/{agentTools-EVdEThES.js → agentTools-B4Gjf8R7.js} +4 -4
- package/dist/{api-DwaHAJtA.js → api-Dvitj1aT.js} +1 -1
- package/dist/{api-C8WmUejq.js → api-JpNuowX4.js} +1 -1
- package/dist/{canvasNoteTools-C5Vf0pxu.js → canvasNoteTools-Bve4Fo7R.js} +3 -3
- package/dist/{code-editor-field-o7qp9eTq.js → code-editor-field-yJZEDJBi.js} +2 -2
- package/dist/{constants-B2lhWNoN.js → constants-dcxg6zG6.js} +2 -2
- package/dist/{definition-canvas-F8DGty5m.js → definition-canvas-Bshn_dSP.js} +1 -1
- package/dist/executions.js +2 -2
- package/dist/{flow-builder-Dn4PCWuf.js → flow-builder-BPe5YNF6.js} +48 -48
- package/dist/{graphql-operation-types-BdU65FNm.js → graphql-operation-types-z2oXfQvM.js} +10 -1
- package/dist/history.js +1 -1
- package/dist/{index-DbTgk7dK.d.ts → index-u-kM0seP.d.ts} +3 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +40 -39
- package/dist/{node-detail-view-kWiwJEKr.js → node-detail-view-oAotM2EI.js} +18 -18
- package/dist/{node-editor-tab-body-C71Y0fRJ.js → node-editor-tab-body-DIcmar84.js} +6 -6
- package/dist/{node-endpoint-configs-BrzQMy10.js → node-endpoint-configs-typvqw2c.js} +1 -1
- package/dist/{node-operation-selection-icAhaNza.js → node-operation-selection-DAbS6jSY.js} +4 -4
- package/dist/nodes.js +1 -1
- package/dist/observability.d.ts +1 -1
- package/dist/observability.js +2 -2
- package/dist/{popover-v7g8TWmm.js → popover-DOeSGQOG.js} +3 -3
- package/dist/{quick-config-panel-C84vsDYD.js → quick-config-panel-Pm5nkZVr.js} +6 -6
- package/dist/{schedule-panel-BrNKy9DY.js → schedule-panel-Dizqz9eA.js} +29 -29
- package/dist/settings.js +1 -1
- package/dist/{sidebar-node-editor-D-2lPHwq.js → sidebar-node-editor-BNub2vUq.js} +4 -4
- package/dist/templates.js +2 -2
- package/dist/{useAgentDefinitions-DSU8Eek4.js → useAgentDefinitions-Uy6nhpKN.js} +1 -1
- package/dist/{useDurableParity-fFmfa97r.js → useDurableParity-Cb9nOdE8.js} +191 -4
- package/dist/{useEntityTags-C8rPBi6W.js → useEntityTags-D5C0tdLs.js} +1 -1
- package/dist/{useExecutions-DNGW4yxG.js → useExecutions-DJXtbA15.js} +59 -48
- package/dist/useHumanRequests-ZiR0sSzS.js +218 -0
- package/dist/{useObservability-u-MZCWUV.js → useObservability-Dfgh4yjv.js} +1 -1
- package/dist/{useRunHistory-x9bVUB9T.js → useRunHistory-BZQ3t68Q.js} +2 -2
- package/dist/{useWorkflowCodeExport-CV3SZeKm.js → useWorkflowCodeExport-D0zapXXm.js} +2 -2
- package/dist/{useWorkflows-CVb5zXKt.js → useWorkflows-CP-d3ygY.js} +2 -2
- package/dist/workflow-builder.js +5 -5
- package/dist/workflow-host.js +1 -1
- package/dist/workflow-pages.d.ts +1 -1
- package/dist/workflow-pages.js +19 -19
- package/dist/workflow-preview.js +4 -4
- package/dist/workflows-list.js +1 -1
- package/package.json +1 -1
|
@@ -1,30 +1,32 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { t as __exportAll } from "./rolldown-runtime-hDbaFkMy.js";
|
|
3
3
|
import { M as DEFAULT_EXECUTIONS_FILTER, N as useExecutionsStore, m as describeOperationError, n as getFluidGridsClient } from "./client-C9XSzSXr.js";
|
|
4
|
-
import { c as
|
|
4
|
+
import { b as validateDateRange, c as EMPTY_SEARCH_FILTER, d as searchFilterConflicts, i as useExecutionStats, l as OPERATORS_BY_TYPE, o as useExecutionsWithStore, r as useExecutionActions, t as useAutoRefresh, u as buildSearchAttributeFilter } from "./useExecutions-DJXtbA15.js";
|
|
5
5
|
import { c as useDurableParityEnabled, f as usePhaseCFlags } from "./feature-flags-DM5myWaD.js";
|
|
6
6
|
import { r as useTr } from "./TranslationBridge-Da-TPgQm.js";
|
|
7
7
|
import { n as useFluidGridsPageControls } from "./pageControlsBridge-0pX9s-3k.js";
|
|
8
8
|
import { t as executionsControls } from "./pageControlSpecs-DZJ9K37m.js";
|
|
9
|
-
import { t as TagFilterSelect } from "./TagFilterSelect-
|
|
10
|
-
import {
|
|
9
|
+
import { t as TagFilterSelect } from "./TagFilterSelect-CqhxcDjh.js";
|
|
10
|
+
import { n as useNavigationV2 } from "./useNavigationV2-C2WeqN7d.js";
|
|
11
|
+
import { a as useRunStatusCounts, c as TechnicalDetails, d as errorAdvice, g as RUN_STATUS_CONFIG, h as runStatusLabels, l as Disclosure, o as ConfirmStopRunDialog, p as ExecutionStatusBadge, s as RunActionsMenu, u as ADVICE_ERROR_TYPES } from "./useDurableParity-Cb9nOdE8.js";
|
|
11
12
|
import { n as formatRunVersion } from "./run-display-BycKYSU0.js";
|
|
12
|
-
import { dn as runDurationMs, ln as formatElapsedMs } from "./FluidGridsProvider-
|
|
13
|
+
import { dn as runDurationMs, ln as formatElapsedMs } from "./FluidGridsProvider-B1hgCbxG.js";
|
|
14
|
+
import { r as useRunHumanRequests } from "./useHumanRequests-ZiR0sSzS.js";
|
|
13
15
|
import { n as runListLinkKey, t as runListFilterFromSearch } from "./run-list-links-eUhZB1ju.js";
|
|
14
|
-
import { h as useWorkflowDefinitions } from "./useWorkflows-
|
|
16
|
+
import { h as useWorkflowDefinitions } from "./useWorkflows-CP-d3ygY.js";
|
|
15
17
|
import { t as FluidGridsDocsLink } from "./FluidGridsDocsLink-JxkBpOeb.js";
|
|
16
|
-
import { s as useFluidGridsPermission, t as FLUIDGRIDS_PERMISSIONS } from "./constants-
|
|
17
|
-
import { C as jsonArg, F as startBatchOperation, I as startBatchTerminate, P as startBatchExport, m as fetchBatchOperations, n as cancelBatchOperation, p as fetchBatchOperation, x as fetchSearchAttributes } from "./api-
|
|
18
|
+
import { s as useFluidGridsPermission, t as FLUIDGRIDS_PERMISSIONS } from "./constants-dcxg6zG6.js";
|
|
19
|
+
import { C as jsonArg, F as startBatchOperation, I as startBatchTerminate, P as startBatchExport, m as fetchBatchOperations, n as cancelBatchOperation, p as fetchBatchOperation, x as fetchSearchAttributes } from "./api-Dvitj1aT.js";
|
|
18
20
|
import { a as RUN_CONTROL_DIALOG_STYLE, c as parseJsonInput, i as NativeSelect, o as StatusPill, r as JsonField, t as FieldError, u as useResource } from "./shared-CMfn30xT.js";
|
|
19
|
-
import { Cr as WorkflowBatchOperationUpdatedDocument } from "./graphql-operation-types-
|
|
21
|
+
import { Cr as WorkflowBatchOperationUpdatedDocument } from "./graphql-operation-types-z2oXfQvM.js";
|
|
20
22
|
import { $F as WorkflowBatchOperationType, vI as WorkflowResetType } from "./graphql-types-v6CTGwA0.js";
|
|
21
|
-
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
23
|
+
import { Fragment, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
22
24
|
import { useNavigate, useSearchParams } from "react-router";
|
|
23
25
|
import { Icon } from "@iconify/react";
|
|
24
26
|
import { cn } from "@burdenoff/fe-libs/utils";
|
|
25
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
27
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
26
28
|
import { toast } from "sonner";
|
|
27
|
-
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, Input, Label, Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle } from "@burdenoff/fe-libs/ui";
|
|
29
|
+
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, EmptyState, Input, Label, ResponsiveTable, Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle } from "@burdenoff/fe-libs/ui";
|
|
28
30
|
import { Button as Button$1 } from "@burdenoff/fe-libs/button";
|
|
29
31
|
|
|
30
32
|
// src/modules/executions/utils/active-filters.ts
|
|
@@ -78,6 +80,7 @@ function FailedNodeTypeChip({ nodeType, onClear }) {
|
|
|
78
80
|
}
|
|
79
81
|
function ExecutionFilters({ workflows = [], onRefresh }) {
|
|
80
82
|
const tr = useTr();
|
|
83
|
+
const v2 = useNavigationV2();
|
|
81
84
|
const statusOptions = useMemo(() => [
|
|
82
85
|
{
|
|
83
86
|
value: "all",
|
|
@@ -112,7 +115,7 @@ function ExecutionFilters({ workflows = [], onRefresh }) {
|
|
|
112
115
|
label: tr("fluidgrids.executions.executionFilters.statusTerminated", "Terminated")
|
|
113
116
|
}
|
|
114
117
|
], [tr]);
|
|
115
|
-
const
|
|
118
|
+
const rawErrorOptions = [
|
|
116
119
|
{
|
|
117
120
|
value: "TIMEOUT",
|
|
118
121
|
label: tr("fluidgrids.executions.executionFilters.errorTimeout", "TIMEOUT")
|
|
@@ -142,6 +145,10 @@ function ExecutionFilters({ workflows = [], onRefresh }) {
|
|
|
142
145
|
label: tr("fluidgrids.executions.executionFilters.errorUnknown", "UNKNOWN")
|
|
143
146
|
}
|
|
144
147
|
];
|
|
148
|
+
const errorOptions = v2 ? ADVICE_ERROR_TYPES.map((value) => ({
|
|
149
|
+
value,
|
|
150
|
+
label: errorAdvice(tr, value)
|
|
151
|
+
})) : rawErrorOptions;
|
|
145
152
|
const datePresets = [
|
|
146
153
|
{
|
|
147
154
|
value: "all",
|
|
@@ -173,6 +180,10 @@ function ExecutionFilters({ workflows = [], onRefresh }) {
|
|
|
173
180
|
}
|
|
174
181
|
];
|
|
175
182
|
const { filter, setStatusFilter, setWorkflowFilter, setDateRange, setSearchQuery, setTriggerTypeFilter, setDurationFilter, setErrorTypeFilter, setNodeFilter, setFailedNodeTypeFilter, setTagFilter, resetFilters, autoRefresh, setAutoRefresh } = useExecutionsStore();
|
|
183
|
+
const levelOneDatePresets = v2 ? datePresets.filter(({ value }) => value !== "custom" || filter.dateRange.preset === "custom") : datePresets;
|
|
184
|
+
const MORE_STATUSES = ["PENDING", "TERMINATED"];
|
|
185
|
+
const primaryStatusOptions = v2 ? statusOptions.filter(({ value }) => value === "all" || !MORE_STATUSES.includes(value)) : statusOptions;
|
|
186
|
+
const moreStatusOptions = v2 ? statusOptions.filter(({ value }) => MORE_STATUSES.includes(value)) : [];
|
|
176
187
|
const [showCustomDate, setShowCustomDate] = useState(() => filter.dateRange.preset === "custom");
|
|
177
188
|
const handleDatePresetChange = useCallback((preset) => {
|
|
178
189
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -215,6 +226,7 @@ function ExecutionFilters({ workflows = [], onRefresh }) {
|
|
|
215
226
|
}, [setDateRange]);
|
|
216
227
|
const parityEnabled = useDurableParityEnabled();
|
|
217
228
|
const activeFiltersCount = countActiveFilters(filter, parityEnabled);
|
|
229
|
+
const hasMoreFiltersSet = filter.tagId !== "" || filter.triggerType !== "all" || filter.errorType !== "all" || filter.nodeId !== "" || filter.failedNodeType !== "" || filter.durationMinSeconds !== null || filter.durationMaxSeconds !== null || filter.dateRange.preset === "custom";
|
|
218
230
|
const assistantControls = useMemo(() => executionsControls({
|
|
219
231
|
page: tr("fluidgrids.executions.executionsList.title", "Executions"),
|
|
220
232
|
search: setSearchQuery,
|
|
@@ -277,15 +289,21 @@ function ExecutionFilters({ workflows = [], onRefresh }) {
|
|
|
277
289
|
})
|
|
278
290
|
]
|
|
279
291
|
}),
|
|
280
|
-
/* @__PURE__ */
|
|
292
|
+
/* @__PURE__ */ jsxs("select", {
|
|
281
293
|
value: filter.status,
|
|
282
294
|
onChange: (e) => setStatusFilter(e.target.value),
|
|
283
295
|
className: "px-3 py-2 bg-bg-surface border border-border-default rounded-lg text-text-primary focus:outline-none focus:ring-2 focus:ring-action-primary-bg scheme-normal dark:scheme-dark",
|
|
284
|
-
children:
|
|
296
|
+
children: [primaryStatusOptions.map((option) => /* @__PURE__ */ jsx("option", {
|
|
285
297
|
value: option.value,
|
|
286
298
|
className: "bg-bg-surface text-text-primary",
|
|
287
299
|
children: option.label
|
|
288
|
-
}, option.value))
|
|
300
|
+
}, option.value)), moreStatusOptions.length > 0 && /* @__PURE__ */ jsx("optgroup", {
|
|
301
|
+
label: tr("fluidgrids.executions.executionFilters.moreStatuses", "More statuses"),
|
|
302
|
+
children: moreStatusOptions.map((option) => /* @__PURE__ */ jsx("option", {
|
|
303
|
+
value: option.value,
|
|
304
|
+
children: option.label
|
|
305
|
+
}, option.value))
|
|
306
|
+
})]
|
|
289
307
|
}),
|
|
290
308
|
workflows.length > 0 && /* @__PURE__ */ jsxs("select", {
|
|
291
309
|
value: filter.workflowKey,
|
|
@@ -301,7 +319,7 @@ function ExecutionFilters({ workflows = [], onRefresh }) {
|
|
|
301
319
|
children: wf.name
|
|
302
320
|
}, wf.workflowKey))]
|
|
303
321
|
}),
|
|
304
|
-
/* @__PURE__ */ jsx(TagFilterSelect, {
|
|
322
|
+
!v2 && /* @__PURE__ */ jsx(TagFilterSelect, {
|
|
305
323
|
value: filter.tagId,
|
|
306
324
|
onChange: setTagFilter,
|
|
307
325
|
className: "max-w-[200px]"
|
|
@@ -310,7 +328,7 @@ function ExecutionFilters({ workflows = [], onRefresh }) {
|
|
|
310
328
|
value: filter.dateRange.preset,
|
|
311
329
|
onChange: (e) => handleDatePresetChange(e.target.value),
|
|
312
330
|
className: "px-3 py-2 bg-bg-surface border border-border-default rounded-lg text-text-primary focus:outline-none focus:ring-2 focus:ring-action-primary-bg scheme-normal dark:scheme-dark",
|
|
313
|
-
children:
|
|
331
|
+
children: levelOneDatePresets.map((option) => /* @__PURE__ */ jsx("option", {
|
|
314
332
|
value: option.value,
|
|
315
333
|
className: "bg-bg-surface text-text-primary",
|
|
316
334
|
children: option.label
|
|
@@ -318,7 +336,119 @@ function ExecutionFilters({ workflows = [], onRefresh }) {
|
|
|
318
336
|
})
|
|
319
337
|
]
|
|
320
338
|
}),
|
|
321
|
-
/* @__PURE__ */
|
|
339
|
+
v2 ? /* @__PURE__ */ jsx(Disclosure, {
|
|
340
|
+
closedLabel: tr("fluidgrids.executions.executionFilters.moreFilters", "More filters"),
|
|
341
|
+
openLabel: tr("fluidgrids.executions.executionFilters.fewerFilters", "Fewer filters"),
|
|
342
|
+
defaultOpen: hasMoreFiltersSet,
|
|
343
|
+
"data-testid": "runs-more-filters",
|
|
344
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
345
|
+
className: "grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-5",
|
|
346
|
+
children: [
|
|
347
|
+
/* @__PURE__ */ jsx(TagFilterSelect, {
|
|
348
|
+
value: filter.tagId,
|
|
349
|
+
onChange: setTagFilter,
|
|
350
|
+
className: "max-w-[200px]"
|
|
351
|
+
}),
|
|
352
|
+
/* @__PURE__ */ jsxs("select", {
|
|
353
|
+
"aria-label": tr("fluidgrids.executions.executionFilters.triggerType", "Trigger type"),
|
|
354
|
+
value: filter.triggerType,
|
|
355
|
+
onChange: (e) => setTriggerTypeFilter(e.target.value),
|
|
356
|
+
className: "px-3 py-2 bg-bg-surface border border-border-default rounded-lg text-text-primary focus:outline-none focus:ring-2 focus:ring-action-primary-bg scheme-normal dark:scheme-dark",
|
|
357
|
+
children: [
|
|
358
|
+
/* @__PURE__ */ jsx("option", {
|
|
359
|
+
value: "all",
|
|
360
|
+
children: tr("fluidgrids.executions.executionFilters.allTriggers", "All trigger types")
|
|
361
|
+
}),
|
|
362
|
+
/* @__PURE__ */ jsx("option", {
|
|
363
|
+
value: "MANUAL",
|
|
364
|
+
children: tr("fluidgrids.executions.executionFilters.manual", "Manual")
|
|
365
|
+
}),
|
|
366
|
+
/* @__PURE__ */ jsx("option", {
|
|
367
|
+
value: "WEBHOOK",
|
|
368
|
+
children: tr("fluidgrids.executions.executionFilters.webhook", "Webhook")
|
|
369
|
+
}),
|
|
370
|
+
/* @__PURE__ */ jsx("option", {
|
|
371
|
+
value: "SCHEDULE",
|
|
372
|
+
children: tr("fluidgrids.executions.executionFilters.schedule", "Schedule")
|
|
373
|
+
}),
|
|
374
|
+
/* @__PURE__ */ jsx("option", {
|
|
375
|
+
value: "EVENT",
|
|
376
|
+
children: tr("fluidgrids.executions.executionFilters.event", "Event")
|
|
377
|
+
})
|
|
378
|
+
]
|
|
379
|
+
}),
|
|
380
|
+
/* @__PURE__ */ jsxs("select", {
|
|
381
|
+
"aria-label": tr("fluidgrids.executions.executionFilters.errorType", "Error type"),
|
|
382
|
+
value: filter.errorType,
|
|
383
|
+
onChange: (e) => setErrorTypeFilter(e.target.value),
|
|
384
|
+
className: "px-3 py-2 bg-bg-surface border border-border-default rounded-lg text-text-primary focus:outline-none focus:ring-2 focus:ring-action-primary-bg scheme-normal dark:scheme-dark",
|
|
385
|
+
children: [
|
|
386
|
+
/* @__PURE__ */ jsx("option", {
|
|
387
|
+
value: "all",
|
|
388
|
+
children: tr("fluidgrids.executions.executionFilters.allErrors", "All error types")
|
|
389
|
+
}),
|
|
390
|
+
errorOptions.map(({ value, label }) => /* @__PURE__ */ jsx("option", {
|
|
391
|
+
value,
|
|
392
|
+
children: label
|
|
393
|
+
}, value)),
|
|
394
|
+
/* @__PURE__ */ jsx(LinkedErrorTypeOption, {
|
|
395
|
+
errorType: filter.errorType,
|
|
396
|
+
offered: errorOptions
|
|
397
|
+
})
|
|
398
|
+
]
|
|
399
|
+
}),
|
|
400
|
+
/* @__PURE__ */ jsx(FailedNodeTypeChip, {
|
|
401
|
+
nodeType: filter.failedNodeType,
|
|
402
|
+
onClear: () => setFailedNodeTypeFilter("")
|
|
403
|
+
}),
|
|
404
|
+
/* @__PURE__ */ jsx("input", {
|
|
405
|
+
type: "text",
|
|
406
|
+
value: filter.nodeId,
|
|
407
|
+
onChange: (e) => setNodeFilter(e.target.value),
|
|
408
|
+
placeholder: tr("fluidgrids.executions.executionFilters.nodePlaceholder", "Node ID"),
|
|
409
|
+
"aria-label": tr("fluidgrids.executions.executionFilters.nodeId", "Node ID"),
|
|
410
|
+
className: "px-3 py-2 bg-bg-surface border border-border-default rounded-lg text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-action-primary-bg"
|
|
411
|
+
}),
|
|
412
|
+
/* @__PURE__ */ jsx("input", {
|
|
413
|
+
type: "number",
|
|
414
|
+
min: 0,
|
|
415
|
+
value: filter.durationMinSeconds ?? "",
|
|
416
|
+
onChange: (e) => setDurationFilter(e.target.value ? Number(e.target.value) : null, filter.durationMaxSeconds),
|
|
417
|
+
placeholder: tr("fluidgrids.executions.executionFilters.durationMin", "Min seconds"),
|
|
418
|
+
"aria-label": tr("fluidgrids.executions.executionFilters.durationMin", "Minimum duration in seconds"),
|
|
419
|
+
className: "px-3 py-2 bg-bg-surface border border-border-default rounded-lg text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-action-primary-bg"
|
|
420
|
+
}),
|
|
421
|
+
/* @__PURE__ */ jsx("input", {
|
|
422
|
+
type: "number",
|
|
423
|
+
min: 0,
|
|
424
|
+
value: filter.durationMaxSeconds ?? "",
|
|
425
|
+
onChange: (e) => setDurationFilter(filter.durationMinSeconds, e.target.value ? Number(e.target.value) : null),
|
|
426
|
+
placeholder: tr("fluidgrids.executions.executionFilters.durationMax", "Max seconds"),
|
|
427
|
+
"aria-label": tr("fluidgrids.executions.executionFilters.durationMax", "Maximum duration in seconds"),
|
|
428
|
+
className: "px-3 py-2 bg-bg-surface border border-border-default rounded-lg text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-action-primary-bg"
|
|
429
|
+
}),
|
|
430
|
+
/* @__PURE__ */ jsx("button", {
|
|
431
|
+
type: "button",
|
|
432
|
+
onClick: () => handleDatePresetChange("custom"),
|
|
433
|
+
className: "px-3 py-2 border border-border-default rounded-lg text-text-primary text-left hover:bg-background-tertiary",
|
|
434
|
+
"data-testid": "runs-custom-range",
|
|
435
|
+
children: tr("fluidgrids.executions.executionFilters.dateCustomRange", "Custom Range")
|
|
436
|
+
}),
|
|
437
|
+
/* @__PURE__ */ jsxs("label", {
|
|
438
|
+
className: "inline-flex items-center gap-2 cursor-pointer",
|
|
439
|
+
children: [/* @__PURE__ */ jsx("input", {
|
|
440
|
+
type: "checkbox",
|
|
441
|
+
checked: autoRefresh,
|
|
442
|
+
onChange: (e) => setAutoRefresh(e.target.checked),
|
|
443
|
+
className: "w-4 h-4 rounded border-border-secondary text-action-primary-bg focus:ring-action-primary-bg"
|
|
444
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
445
|
+
className: "text-sm text-text-secondary",
|
|
446
|
+
children: tr("fluidgrids.executions.executionFilters.liveUpdates", "Live updates")
|
|
447
|
+
})]
|
|
448
|
+
})
|
|
449
|
+
]
|
|
450
|
+
})
|
|
451
|
+
}) : /* @__PURE__ */ jsxs("div", {
|
|
322
452
|
className: "grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-5",
|
|
323
453
|
children: [
|
|
324
454
|
/* @__PURE__ */ jsxs("select", {
|
|
@@ -453,7 +583,7 @@ function ExecutionFilters({ workflows = [], onRefresh }) {
|
|
|
453
583
|
className: "flex flex-wrap items-center justify-between gap-3",
|
|
454
584
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
455
585
|
className: "flex items-center gap-3",
|
|
456
|
-
children: [/* @__PURE__ */ jsxs("label", {
|
|
586
|
+
children: [!v2 && /* @__PURE__ */ jsxs("label", {
|
|
457
587
|
className: "inline-flex items-center gap-2 cursor-pointer",
|
|
458
588
|
children: [/* @__PURE__ */ jsx("input", {
|
|
459
589
|
type: "checkbox",
|
|
@@ -539,11 +669,12 @@ function StatCard({ label, value, icon, color, trend, onClick }) {
|
|
|
539
669
|
]
|
|
540
670
|
});
|
|
541
671
|
}
|
|
542
|
-
function ExecutionStats({ stats, loading, onFilterByStatus }) {
|
|
672
|
+
function ExecutionStats({ stats, loading, scoped = false, onFilterByStatus }) {
|
|
543
673
|
const tr = useTr();
|
|
674
|
+
const v2 = useNavigationV2();
|
|
544
675
|
if (loading) return /* @__PURE__ */ jsx("div", {
|
|
545
676
|
className: "grid grid-cols-2 sm:grid-cols-4 lg:grid-cols-6 gap-4",
|
|
546
|
-
children: [...Array(6)].map((_, i) => /* @__PURE__ */ jsx("div", { className: "h-24 bg-background-secondary rounded-lg border border-border-secondary animate-pulse" }, i))
|
|
677
|
+
children: [...Array(v2 ? 4 : 6)].map((_, i) => /* @__PURE__ */ jsx("div", { className: "h-24 bg-background-secondary rounded-lg border border-border-secondary animate-pulse" }, i))
|
|
547
678
|
});
|
|
548
679
|
if (!stats) return null;
|
|
549
680
|
const formatDuration = (seconds) => {
|
|
@@ -551,6 +682,81 @@ function ExecutionStats({ stats, loading, onFilterByStatus }) {
|
|
|
551
682
|
if (seconds < 3600) return `${Math.round(seconds / 60)}m`;
|
|
552
683
|
return `${Math.round(seconds / 3600)}h`;
|
|
553
684
|
};
|
|
685
|
+
if (v2) {
|
|
686
|
+
const words = runStatusLabels(tr);
|
|
687
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
688
|
+
className: "space-y-3",
|
|
689
|
+
"data-testid": "runs-stats",
|
|
690
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
691
|
+
className: "grid grid-cols-2 lg:grid-cols-4 gap-4",
|
|
692
|
+
children: [
|
|
693
|
+
/* @__PURE__ */ jsx(StatCard, {
|
|
694
|
+
label: tr("fluidgrids.executions.executionStats.totalRuns", "Total Runs"),
|
|
695
|
+
value: stats.total.toLocaleString(),
|
|
696
|
+
icon: "mdi:play-box-multiple",
|
|
697
|
+
color: "text-text-primary",
|
|
698
|
+
onClick: () => onFilterByStatus?.("all")
|
|
699
|
+
}),
|
|
700
|
+
/* @__PURE__ */ jsx(StatCard, {
|
|
701
|
+
label: words.RUNNING,
|
|
702
|
+
value: stats.running,
|
|
703
|
+
icon: "mdi:play-circle",
|
|
704
|
+
color: "text-[var(--color-status-info-text)]",
|
|
705
|
+
onClick: () => onFilterByStatus?.("RUNNING")
|
|
706
|
+
}),
|
|
707
|
+
/* @__PURE__ */ jsx(StatCard, {
|
|
708
|
+
label: words.COMPLETED,
|
|
709
|
+
value: stats.completed.toLocaleString(),
|
|
710
|
+
icon: "mdi:check-circle",
|
|
711
|
+
color: "text-[var(--color-status-success-text)]",
|
|
712
|
+
onClick: () => onFilterByStatus?.("COMPLETED")
|
|
713
|
+
}),
|
|
714
|
+
/* @__PURE__ */ jsx(StatCard, {
|
|
715
|
+
label: words.FAILED,
|
|
716
|
+
value: stats.failed,
|
|
717
|
+
icon: "mdi:alert-circle",
|
|
718
|
+
color: "text-[var(--color-status-error-text)]",
|
|
719
|
+
onClick: () => onFilterByStatus?.("FAILED")
|
|
720
|
+
})
|
|
721
|
+
]
|
|
722
|
+
}), /* @__PURE__ */ jsx(Disclosure, {
|
|
723
|
+
closedLabel: tr("fluidgrids.executions.executionStats.moreNumbers", "More numbers"),
|
|
724
|
+
openLabel: tr("fluidgrids.executions.executionStats.fewerNumbers", "Fewer numbers"),
|
|
725
|
+
"data-testid": "runs-more-numbers",
|
|
726
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
727
|
+
className: "grid grid-cols-2 lg:grid-cols-4 gap-4",
|
|
728
|
+
children: [
|
|
729
|
+
/* @__PURE__ */ jsx(StatCard, {
|
|
730
|
+
label: tr("fluidgrids.executions.executionStats.successRate", "Success Rate"),
|
|
731
|
+
value: `${(stats.successRate ?? 0).toFixed(1)}%`,
|
|
732
|
+
icon: "mdi:percent",
|
|
733
|
+
color: "text-accent"
|
|
734
|
+
}),
|
|
735
|
+
!scoped && /* @__PURE__ */ jsx(StatCard, {
|
|
736
|
+
label: tr("fluidgrids.executions.executionStats.avgDuration", "Avg Duration"),
|
|
737
|
+
value: formatDuration(stats.avgDuration ?? 0),
|
|
738
|
+
icon: "mdi:timer",
|
|
739
|
+
color: "text-[var(--color-status-warning-text)]"
|
|
740
|
+
}),
|
|
741
|
+
/* @__PURE__ */ jsx(StatCard, {
|
|
742
|
+
label: words.CANCELLED,
|
|
743
|
+
value: stats.cancelled,
|
|
744
|
+
icon: "mdi:cancel",
|
|
745
|
+
color: "text-[var(--color-status-warning-text)]",
|
|
746
|
+
onClick: () => onFilterByStatus?.("CANCELLED")
|
|
747
|
+
}),
|
|
748
|
+
/* @__PURE__ */ jsx(StatCard, {
|
|
749
|
+
label: words.WAITING,
|
|
750
|
+
value: stats.waiting,
|
|
751
|
+
icon: "mdi:timer-sand",
|
|
752
|
+
color: "text-text-primary",
|
|
753
|
+
onClick: () => onFilterByStatus?.("WAITING")
|
|
754
|
+
})
|
|
755
|
+
]
|
|
756
|
+
})
|
|
757
|
+
})]
|
|
758
|
+
});
|
|
759
|
+
}
|
|
554
760
|
return /* @__PURE__ */ jsxs("div", {
|
|
555
761
|
className: "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-6 gap-4",
|
|
556
762
|
children: [
|
|
@@ -598,8 +804,70 @@ function ExecutionStats({ stats, loading, onFilterByStatus }) {
|
|
|
598
804
|
});
|
|
599
805
|
}
|
|
600
806
|
|
|
807
|
+
// src/modules/executions/utils/run-actions.ts
|
|
808
|
+
/** Run statuses a bulk or row "Retry" (a new run of the same version) applies to. */
|
|
809
|
+
const RETRYABLE_STATUSES = ["FAILED"];
|
|
810
|
+
/** How many selected runs one bulk retry starts. */
|
|
811
|
+
const BULK_RETRY_LIMIT = 10;
|
|
812
|
+
/**
|
|
813
|
+
* The quick actions for a run, in display order.
|
|
814
|
+
*
|
|
815
|
+
* `resumeOffered` is the answer to "would the run page offer Resume?": a run
|
|
816
|
+
* that is still waiting on a person's answer cannot be resumed (the service
|
|
817
|
+
* refuses), so the list must not offer it either.
|
|
818
|
+
*/
|
|
819
|
+
function runQuickActions(status, { resumeOffered }) {
|
|
820
|
+
switch (status) {
|
|
821
|
+
case "RUNNING": return ["pause", "cancel"];
|
|
822
|
+
case "WAITING": return resumeOffered ? ["resume", "cancel"] : ["cancel"];
|
|
823
|
+
case "FAILED": return ["retry"];
|
|
824
|
+
case "PENDING": return ["cancel"];
|
|
825
|
+
default: return [];
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
/**
|
|
829
|
+
* Which of the selected runs a bulk retry starts: only runs that failed (a
|
|
830
|
+
* retry of a succeeded run would silently run it again), and at most the first
|
|
831
|
+
* {@link BULK_RETRY_LIMIT}. What was left out is counted so the page can say so.
|
|
832
|
+
*/
|
|
833
|
+
function planBulkRetry(selectedIds, runs) {
|
|
834
|
+
const statusById = new Map(runs.map((run) => [run.id, run.status]));
|
|
835
|
+
const failed = selectedIds.filter((id) => {
|
|
836
|
+
const status = statusById.get(id);
|
|
837
|
+
return status !== void 0 && RETRYABLE_STATUSES.includes(status);
|
|
838
|
+
});
|
|
839
|
+
return {
|
|
840
|
+
runIds: failed.slice(0, 10),
|
|
841
|
+
skippedNotFailed: selectedIds.length - failed.length,
|
|
842
|
+
skippedOverLimit: Math.max(0, failed.length - 10)
|
|
843
|
+
};
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
// src/modules/executions/hooks/useResumeOffered.ts
|
|
847
|
+
/**
|
|
848
|
+
* Whether the Runs list may offer "Resume" on a row. The run page offers it
|
|
849
|
+
* only once the run's asks are known to be answered (a run waiting on a person
|
|
850
|
+
* continues only with their answer, and the service refuses a generic resume),
|
|
851
|
+
* so the list asks the same question for WAITING rows and nothing otherwise
|
|
852
|
+
* (BOFF-11846). Until the asks have been read, Resume is not offered.
|
|
853
|
+
*/
|
|
854
|
+
function useResumeOffered(run) {
|
|
855
|
+
const waiting = run.status === "WAITING";
|
|
856
|
+
const { items, loaded } = useRunHumanRequests(waiting ? run.id : void 0);
|
|
857
|
+
return waiting && loaded && !items.some((item) => item.status === "PENDING");
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
// src/modules/executions/components/WithResumeOffered.tsx
|
|
861
|
+
/**
|
|
862
|
+
* Lets a list row (which is rendered inside a `.map`, where hooks cannot be
|
|
863
|
+
* called) ask whether Resume may be offered for its run (BOFF-11846).
|
|
864
|
+
*/
|
|
865
|
+
function WithResumeOffered({ run, children }) {
|
|
866
|
+
return /* @__PURE__ */ jsx(Fragment$1, { children: children(useResumeOffered(run)) });
|
|
867
|
+
}
|
|
868
|
+
|
|
601
869
|
// src/modules/executions/components/ExecutionTable.tsx
|
|
602
|
-
function ExecutionTable({ executions, workflowNames, loading, onRowClick, onAction }) {
|
|
870
|
+
function ExecutionTable({ executions, workflowNames, loading, canExecute = true, onRowClick, onAction }) {
|
|
603
871
|
const tr = useTr();
|
|
604
872
|
const navigate = useNavigate();
|
|
605
873
|
const { selection, toggleSelectRun, selectAll, expandedRows, toggleRowExpanded } = useExecutionsStore();
|
|
@@ -619,47 +887,29 @@ function ExecutionTable({ executions, workflowNames, loading, onRowClick, onActi
|
|
|
619
887
|
minute: "2-digit"
|
|
620
888
|
});
|
|
621
889
|
};
|
|
622
|
-
const getRowActions = (execution) => {
|
|
623
|
-
const
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
action: "pause"
|
|
630
|
-
});
|
|
631
|
-
actions.push({
|
|
632
|
-
icon: "mdi:stop",
|
|
633
|
-
label: tr("fluidgrids.executions.executionTable.actionCancel", "Cancel"),
|
|
634
|
-
action: "cancel"
|
|
635
|
-
});
|
|
636
|
-
break;
|
|
637
|
-
case "WAITING":
|
|
638
|
-
actions.push({
|
|
639
|
-
icon: "mdi:play",
|
|
640
|
-
label: tr("fluidgrids.executions.executionTable.actionResume", "Resume"),
|
|
641
|
-
action: "resume"
|
|
642
|
-
});
|
|
643
|
-
actions.push({
|
|
644
|
-
icon: "mdi:stop",
|
|
645
|
-
label: tr("fluidgrids.executions.executionTable.actionCancel", "Cancel"),
|
|
646
|
-
action: "cancel"
|
|
647
|
-
});
|
|
648
|
-
break;
|
|
649
|
-
case "FAILED":
|
|
650
|
-
actions.push({
|
|
651
|
-
icon: "mdi:refresh",
|
|
652
|
-
label: tr("fluidgrids.executions.executionTable.actionRetry", "Retry"),
|
|
653
|
-
action: "retry"
|
|
654
|
-
});
|
|
655
|
-
break;
|
|
656
|
-
case "PENDING": actions.push({
|
|
890
|
+
const getRowActions = (execution, resumeOffered) => {
|
|
891
|
+
const labels = {
|
|
892
|
+
pause: {
|
|
893
|
+
icon: "mdi:pause",
|
|
894
|
+
label: tr("fluidgrids.executions.executionTable.actionPause", "Pause")
|
|
895
|
+
},
|
|
896
|
+
cancel: {
|
|
657
897
|
icon: "mdi:stop",
|
|
658
|
-
label: tr("fluidgrids.executions.executionTable.actionCancel", "Cancel")
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
898
|
+
label: tr("fluidgrids.executions.executionTable.actionCancel", "Cancel")
|
|
899
|
+
},
|
|
900
|
+
resume: {
|
|
901
|
+
icon: "mdi:play",
|
|
902
|
+
label: tr("fluidgrids.executions.executionTable.actionResume", "Resume")
|
|
903
|
+
},
|
|
904
|
+
retry: {
|
|
905
|
+
icon: "mdi:refresh",
|
|
906
|
+
label: tr("fluidgrids.executions.executionTable.actionRetry", "Retry")
|
|
907
|
+
}
|
|
908
|
+
};
|
|
909
|
+
return runQuickActions(execution.status, { resumeOffered }).map((action) => ({
|
|
910
|
+
action,
|
|
911
|
+
...labels[action]
|
|
912
|
+
}));
|
|
663
913
|
};
|
|
664
914
|
if (loading && executions.length === 0) return /* @__PURE__ */ jsx("div", {
|
|
665
915
|
className: "bg-background-secondary rounded-lg border border-border-secondary overflow-hidden",
|
|
@@ -780,7 +1030,6 @@ function ExecutionTable({ executions, workflowNames, loading, onRowClick, onActi
|
|
|
780
1030
|
children: executions.map((execution) => {
|
|
781
1031
|
const isSelected = selection.runIds.includes(execution.id);
|
|
782
1032
|
const isExpanded = expandedRows.has(execution.id);
|
|
783
|
-
const actions = getRowActions(execution);
|
|
784
1033
|
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("tr", {
|
|
785
1034
|
className: `
|
|
786
1035
|
hover:bg-background-tertiary/50 cursor-pointer transition-colors
|
|
@@ -866,27 +1115,36 @@ function ExecutionTable({ executions, workflowNames, loading, onRowClick, onActi
|
|
|
866
1115
|
className: "flex items-center gap-1",
|
|
867
1116
|
children: [
|
|
868
1117
|
/* @__PURE__ */ jsx("button", {
|
|
1118
|
+
type: "button",
|
|
869
1119
|
onClick: () => toggleRowExpanded(execution.id),
|
|
1120
|
+
"aria-expanded": isExpanded,
|
|
1121
|
+
"aria-label": isExpanded ? tr("fluidgrids.executions.executionTable.collapseRow", "Hide run details") : tr("fluidgrids.executions.executionTable.expandRow", "Show run details"),
|
|
870
1122
|
className: "p-1.5 rounded hover:bg-background-tertiary text-text-secondary",
|
|
871
1123
|
children: /* @__PURE__ */ jsx(Icon, {
|
|
872
1124
|
icon: isExpanded ? "mdi:chevron-up" : "mdi:chevron-down",
|
|
873
1125
|
width: 18
|
|
874
1126
|
})
|
|
875
1127
|
}),
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
1128
|
+
/* @__PURE__ */ jsx(WithResumeOffered, {
|
|
1129
|
+
run: execution,
|
|
1130
|
+
children: (resumeOffered) => (canExecute ? getRowActions(execution, resumeOffered) : []).slice(0, 2).map((action) => /* @__PURE__ */ jsx("button", {
|
|
1131
|
+
"data-agent": "confirm",
|
|
1132
|
+
type: "button",
|
|
1133
|
+
onClick: () => onAction?.(action.action, execution),
|
|
1134
|
+
className: "p-1.5 rounded hover:bg-background-tertiary text-text-secondary",
|
|
1135
|
+
title: action.label,
|
|
1136
|
+
"aria-label": action.label,
|
|
1137
|
+
children: /* @__PURE__ */ jsx(Icon, {
|
|
1138
|
+
icon: action.icon,
|
|
1139
|
+
width: 18
|
|
1140
|
+
})
|
|
1141
|
+
}, action.action))
|
|
1142
|
+
}),
|
|
886
1143
|
/* @__PURE__ */ jsx("button", {
|
|
887
1144
|
onClick: () => navigate(`../runs/${execution.id}`),
|
|
888
1145
|
className: "p-1.5 rounded hover:bg-background-tertiary text-text-secondary",
|
|
889
1146
|
title: tr("fluidgrids.executions.executionTable.viewDetails", "View Details"),
|
|
1147
|
+
"aria-label": tr("fluidgrids.executions.executionTable.viewDetails", "View Details"),
|
|
890
1148
|
children: /* @__PURE__ */ jsx(Icon, {
|
|
891
1149
|
icon: "mdi:arrow-right",
|
|
892
1150
|
width: 18
|
|
@@ -960,7 +1218,7 @@ function ExecutionTable({ executions, workflowNames, loading, onRowClick, onActi
|
|
|
960
1218
|
})] })
|
|
961
1219
|
]
|
|
962
1220
|
})
|
|
963
|
-
}) }, `${execution.id}-expanded`)] });
|
|
1221
|
+
}) }, `${execution.id}-expanded`)] }, execution.id);
|
|
964
1222
|
})
|
|
965
1223
|
})]
|
|
966
1224
|
})
|
|
@@ -988,6 +1246,29 @@ function formatRelativeTime(dateStr) {
|
|
|
988
1246
|
if (diffHours < 24) return `${diffHours}h ago`;
|
|
989
1247
|
return `${Math.floor(diffHours / 24)}d ago`;
|
|
990
1248
|
}
|
|
1249
|
+
/** Icon, label and hover colour of each card action. */
|
|
1250
|
+
const CARD_ACTIONS = (tr) => ({
|
|
1251
|
+
pause: {
|
|
1252
|
+
icon: "mdi:pause",
|
|
1253
|
+
label: tr("fluidgrids.executions.executionCards.pauseButton", "Pause"),
|
|
1254
|
+
hover: "hover:bg-status-warning-bg-subtle hover:text-status-warning-text"
|
|
1255
|
+
},
|
|
1256
|
+
cancel: {
|
|
1257
|
+
icon: "mdi:stop",
|
|
1258
|
+
label: tr("fluidgrids.executions.executionCards.cancelButton", "Cancel"),
|
|
1259
|
+
hover: "hover:bg-status-error-bg-subtle hover:text-status-error-text"
|
|
1260
|
+
},
|
|
1261
|
+
resume: {
|
|
1262
|
+
icon: "mdi:play",
|
|
1263
|
+
label: tr("fluidgrids.executions.executionTable.actionResume", "Resume"),
|
|
1264
|
+
hover: "hover:bg-status-info-bg-subtle hover:text-status-info-text"
|
|
1265
|
+
},
|
|
1266
|
+
retry: {
|
|
1267
|
+
icon: "mdi:refresh",
|
|
1268
|
+
label: tr("fluidgrids.executions.executionTable.actionRetry", "Retry"),
|
|
1269
|
+
hover: "hover:bg-status-info-bg-subtle hover:text-status-info-text"
|
|
1270
|
+
}
|
|
1271
|
+
});
|
|
991
1272
|
function getProgressColor(status) {
|
|
992
1273
|
switch (status) {
|
|
993
1274
|
case "COMPLETED": return "bg-status-success-bg";
|
|
@@ -1040,8 +1321,6 @@ function ExecutionCards({ executions, workflowNames, loading, onCardClick, onAct
|
|
|
1040
1321
|
className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4",
|
|
1041
1322
|
children: executions.map((execution) => {
|
|
1042
1323
|
const config = RUN_STATUS_CONFIG[execution.status];
|
|
1043
|
-
const canCancel = execution.status === "RUNNING" || execution.status === "PENDING";
|
|
1044
|
-
const canPause = execution.status === "RUNNING";
|
|
1045
1324
|
return /* @__PURE__ */ jsxs("div", {
|
|
1046
1325
|
onClick: () => onCardClick(execution),
|
|
1047
1326
|
className: `
|
|
@@ -1125,39 +1404,35 @@ function ExecutionCards({ executions, workflowNames, loading, onCardClick, onAct
|
|
|
1125
1404
|
}), formatElapsedMs(runDurationMs(execution), "--")]
|
|
1126
1405
|
}), /* @__PURE__ */ jsx("span", { children: formatRelativeTime(execution.startedAt ?? execution.createdAt) })]
|
|
1127
1406
|
}),
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
children:
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
" ",
|
|
1158
|
-
tr("fluidgrids.executions.executionCards.cancelButton", "Cancel")
|
|
1159
|
-
]
|
|
1160
|
-
})]
|
|
1407
|
+
/* @__PURE__ */ jsx(WithResumeOffered, {
|
|
1408
|
+
run: execution,
|
|
1409
|
+
children: (resumeOffered) => {
|
|
1410
|
+
const actions = runQuickActions(execution.status, { resumeOffered });
|
|
1411
|
+
if (actions.length === 0) return null;
|
|
1412
|
+
return /* @__PURE__ */ jsx("div", {
|
|
1413
|
+
className: "flex gap-1 mt-2 pt-2 border-t border-border-secondary",
|
|
1414
|
+
children: actions.map((action) => {
|
|
1415
|
+
const { icon, label, hover } = CARD_ACTIONS(tr)[action];
|
|
1416
|
+
return /* @__PURE__ */ jsxs("button", {
|
|
1417
|
+
type: "button",
|
|
1418
|
+
"data-agent": "confirm",
|
|
1419
|
+
onClick: (e) => {
|
|
1420
|
+
e.stopPropagation();
|
|
1421
|
+
onAction(action, execution);
|
|
1422
|
+
},
|
|
1423
|
+
className: `flex items-center gap-1 text-xs px-2 py-1 rounded bg-background-tertiary text-text-secondary transition-colors ${hover}`,
|
|
1424
|
+
children: [
|
|
1425
|
+
/* @__PURE__ */ jsx(Icon, {
|
|
1426
|
+
icon,
|
|
1427
|
+
width: 12
|
|
1428
|
+
}),
|
|
1429
|
+
" ",
|
|
1430
|
+
label
|
|
1431
|
+
]
|
|
1432
|
+
}, action);
|
|
1433
|
+
})
|
|
1434
|
+
});
|
|
1435
|
+
}
|
|
1161
1436
|
})
|
|
1162
1437
|
]
|
|
1163
1438
|
}, execution.id);
|
|
@@ -1208,7 +1483,7 @@ function groupByDate(executions) {
|
|
|
1208
1483
|
}
|
|
1209
1484
|
return groups;
|
|
1210
1485
|
}
|
|
1211
|
-
function ExecutionTimeline({ executions, loading, onItemClick, onAction }) {
|
|
1486
|
+
function ExecutionTimeline({ executions, workflowNames, loading, onItemClick, onAction }) {
|
|
1212
1487
|
const tr = useTr();
|
|
1213
1488
|
if (loading) return /* @__PURE__ */ jsx("div", {
|
|
1214
1489
|
className: "space-y-6 pl-8",
|
|
@@ -1295,10 +1570,10 @@ function ExecutionTimeline({ executions, loading, onItemClick, onAction }) {
|
|
|
1295
1570
|
className: "flex items-center gap-2",
|
|
1296
1571
|
children: [/* @__PURE__ */ jsx("span", {
|
|
1297
1572
|
className: "text-sm font-semibold text-text-primary truncate",
|
|
1298
|
-
children: execution.workflowKey
|
|
1299
|
-
}), /* @__PURE__ */
|
|
1573
|
+
children: execution.workflow?.name || workflowNames?.[execution.workflowKey] || execution.workflowKey
|
|
1574
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
1300
1575
|
className: "text-xs text-text-tertiary",
|
|
1301
|
-
children:
|
|
1576
|
+
children: formatRunVersion(execution.version)
|
|
1302
1577
|
})]
|
|
1303
1578
|
}),
|
|
1304
1579
|
/* @__PURE__ */ jsxs("div", {
|
|
@@ -1350,8 +1625,9 @@ function ExecutionTimeline({ executions, loading, onItemClick, onAction }) {
|
|
|
1350
1625
|
e.stopPropagation();
|
|
1351
1626
|
onAction("cancel", execution);
|
|
1352
1627
|
},
|
|
1353
|
-
className: "opacity-
|
|
1628
|
+
className: "p-1 rounded opacity-60 group-hover:opacity-100 focus-visible:opacity-100 hover:bg-status-error-bg-subtle text-text-tertiary hover:text-status-error-text transition-all",
|
|
1354
1629
|
title: tr("fluidgrids.executions.executionTimeline.cancelTooltip", "Cancel execution"),
|
|
1630
|
+
"aria-label": tr("fluidgrids.executions.executionTimeline.cancelTooltip", "Cancel execution"),
|
|
1355
1631
|
children: /* @__PURE__ */ jsx(Icon, {
|
|
1356
1632
|
icon: "mdi:stop",
|
|
1357
1633
|
width: 14
|
|
@@ -1504,6 +1780,261 @@ function Pagination({ totalItems, showPageSize = true }) {
|
|
|
1504
1780
|
});
|
|
1505
1781
|
}
|
|
1506
1782
|
|
|
1783
|
+
// src/modules/executions/components/RunsPlainTable.tsx
|
|
1784
|
+
/**
|
|
1785
|
+
* The Runs list as one plain table (BOFF-11846, Navigation v2 only): Status,
|
|
1786
|
+
* Workflow (with a one-line plain error under a failed run), Started and
|
|
1787
|
+
* Progress, with Run again / Stop / View on each row, and Pause / Resume under
|
|
1788
|
+
* "⋯". Phones get cards (fe-libs `ResponsiveTable`). Run ids, versions,
|
|
1789
|
+
* durations, the expand row and the selection checkboxes are in the full table
|
|
1790
|
+
* behind "Show run details" on the list page.
|
|
1791
|
+
*/
|
|
1792
|
+
/** Run statuses a row offers "Run again" on. */
|
|
1793
|
+
const RERUNNABLE = /* @__PURE__ */ new Set([
|
|
1794
|
+
"FAILED",
|
|
1795
|
+
"CANCELLED",
|
|
1796
|
+
"TERMINATED"
|
|
1797
|
+
]);
|
|
1798
|
+
/** Run statuses a row offers "Stop" on. */
|
|
1799
|
+
const STOPPABLE = /* @__PURE__ */ new Set([
|
|
1800
|
+
"RUNNING",
|
|
1801
|
+
"WAITING",
|
|
1802
|
+
"PENDING"
|
|
1803
|
+
]);
|
|
1804
|
+
/** The page's language (the app sets it), else the browser's. */
|
|
1805
|
+
function pageLocale() {
|
|
1806
|
+
if (typeof document === "undefined") return void 0;
|
|
1807
|
+
return document.documentElement.lang || void 0;
|
|
1808
|
+
}
|
|
1809
|
+
/** One relative-time formatter per page language, built once (not per row). */
|
|
1810
|
+
const relativeFormats = /* @__PURE__ */ new Map();
|
|
1811
|
+
function relativeFormat(locale) {
|
|
1812
|
+
const cacheKey = locale ?? "";
|
|
1813
|
+
let format = relativeFormats.get(cacheKey);
|
|
1814
|
+
if (!format) {
|
|
1815
|
+
format = new Intl.RelativeTimeFormat(locale, {
|
|
1816
|
+
numeric: "always",
|
|
1817
|
+
style: "narrow"
|
|
1818
|
+
});
|
|
1819
|
+
relativeFormats.set(cacheKey, format);
|
|
1820
|
+
}
|
|
1821
|
+
return format;
|
|
1822
|
+
}
|
|
1823
|
+
/**
|
|
1824
|
+
* "Just now", then "5m ago" / "3h ago" / "2d ago" in the page's language
|
|
1825
|
+
* (Intl's narrow relative time: the same English as before, translated in the
|
|
1826
|
+
* other locales), then a short date.
|
|
1827
|
+
*/
|
|
1828
|
+
function formatStarted(tr, dateStr) {
|
|
1829
|
+
if (!dateStr) return "-";
|
|
1830
|
+
const date = new Date(dateStr);
|
|
1831
|
+
const diff = Date.now() - date.getTime();
|
|
1832
|
+
if (diff < 6e4) return tr("fluidgrids.executions.executionTable.justNow", "Just now");
|
|
1833
|
+
const locale = pageLocale();
|
|
1834
|
+
const relative = relativeFormat(locale);
|
|
1835
|
+
if (diff < 36e5) return relative.format(-Math.round(diff / 6e4), "minute");
|
|
1836
|
+
if (diff < 864e5) return relative.format(-Math.round(diff / 36e5), "hour");
|
|
1837
|
+
if (diff < 6048e5) return relative.format(-Math.round(diff / 864e5), "day");
|
|
1838
|
+
return date.toLocaleDateString(locale, {
|
|
1839
|
+
month: "short",
|
|
1840
|
+
day: "numeric",
|
|
1841
|
+
hour: "2-digit",
|
|
1842
|
+
minute: "2-digit"
|
|
1843
|
+
});
|
|
1844
|
+
}
|
|
1845
|
+
function RowActions({ run, canExecute, onAction }) {
|
|
1846
|
+
const tr = useTr();
|
|
1847
|
+
const resumeOffered = useResumeOffered(run);
|
|
1848
|
+
const menuItems = [];
|
|
1849
|
+
if (canExecute && run.status === "RUNNING") menuItems.push({
|
|
1850
|
+
id: "pause",
|
|
1851
|
+
icon: "mdi:pause",
|
|
1852
|
+
label: tr("fluidgrids.executions.executionTable.actionPause", "Pause"),
|
|
1853
|
+
onSelect: () => onAction("pause", run)
|
|
1854
|
+
});
|
|
1855
|
+
if (canExecute && run.status === "WAITING" && resumeOffered) menuItems.push({
|
|
1856
|
+
id: "resume",
|
|
1857
|
+
icon: "mdi:play",
|
|
1858
|
+
label: tr("fluidgrids.executions.executionTable.actionResume", "Resume"),
|
|
1859
|
+
onSelect: () => onAction("resume", run)
|
|
1860
|
+
});
|
|
1861
|
+
const viewLabel = tr("fluidgrids.executions.executionTable.viewDetails", "View Details");
|
|
1862
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
1863
|
+
className: "flex items-center gap-1",
|
|
1864
|
+
onClick: (event) => event.stopPropagation(),
|
|
1865
|
+
children: [
|
|
1866
|
+
canExecute && RERUNNABLE.has(run.status) && /* @__PURE__ */ jsxs(Button$1, {
|
|
1867
|
+
"data-agent": "confirm",
|
|
1868
|
+
variant: "outline",
|
|
1869
|
+
size: "sm",
|
|
1870
|
+
onClick: () => onAction("retry", run),
|
|
1871
|
+
"data-testid": "run-row-run-again",
|
|
1872
|
+
children: [/* @__PURE__ */ jsx(Icon, {
|
|
1873
|
+
icon: "mdi:refresh",
|
|
1874
|
+
className: "mr-1",
|
|
1875
|
+
width: 14
|
|
1876
|
+
}), tr("fluidgrids.executions.executionTable.actionRetry", "Retry")]
|
|
1877
|
+
}),
|
|
1878
|
+
canExecute && STOPPABLE.has(run.status) && /* @__PURE__ */ jsxs(Button$1, {
|
|
1879
|
+
"data-agent": "confirm",
|
|
1880
|
+
variant: "outline",
|
|
1881
|
+
size: "sm",
|
|
1882
|
+
onClick: () => onAction("cancel", run),
|
|
1883
|
+
"data-testid": "run-row-stop",
|
|
1884
|
+
children: [/* @__PURE__ */ jsx(Icon, {
|
|
1885
|
+
icon: "mdi:stop",
|
|
1886
|
+
className: "mr-1",
|
|
1887
|
+
width: 14
|
|
1888
|
+
}), tr("fluidgrids.executions.executionTable.actionCancel", "Cancel")]
|
|
1889
|
+
}),
|
|
1890
|
+
/* @__PURE__ */ jsx(RunActionsMenu, {
|
|
1891
|
+
items: menuItems,
|
|
1892
|
+
label: tr("fluidgrids.executions.executionTable.moreActions", "More actions"),
|
|
1893
|
+
"data-testid": `run-row-menu-${run.id}`
|
|
1894
|
+
}),
|
|
1895
|
+
/* @__PURE__ */ jsx(Button$1, {
|
|
1896
|
+
variant: "ghost",
|
|
1897
|
+
size: "sm",
|
|
1898
|
+
onClick: () => onAction("view", run),
|
|
1899
|
+
"aria-label": viewLabel,
|
|
1900
|
+
title: viewLabel,
|
|
1901
|
+
children: /* @__PURE__ */ jsx(Icon, {
|
|
1902
|
+
icon: "mdi:arrow-right",
|
|
1903
|
+
width: 18
|
|
1904
|
+
})
|
|
1905
|
+
})
|
|
1906
|
+
]
|
|
1907
|
+
});
|
|
1908
|
+
}
|
|
1909
|
+
function RunsPlainTable({ executions, workflowNames, loading, canExecute = true, onRowClick, onAction }) {
|
|
1910
|
+
const tr = useTr();
|
|
1911
|
+
if (loading && executions.length === 0) return /* @__PURE__ */ jsx("div", {
|
|
1912
|
+
className: "space-y-2",
|
|
1913
|
+
"aria-busy": "true",
|
|
1914
|
+
children: [...Array(5)].map((_, i) => /* @__PURE__ */ jsx("div", { className: "h-12 rounded-lg bg-background-tertiary animate-pulse" }, i))
|
|
1915
|
+
});
|
|
1916
|
+
return /* @__PURE__ */ jsx("div", {
|
|
1917
|
+
"data-testid": "runs-plain-table",
|
|
1918
|
+
children: /* @__PURE__ */ jsx(ResponsiveTable, {
|
|
1919
|
+
data: executions,
|
|
1920
|
+
rowKey: (run) => run.id,
|
|
1921
|
+
onRowClick,
|
|
1922
|
+
rowActionsLabel: tr("fluidgrids.executions.executionTable.colActions", "Actions"),
|
|
1923
|
+
rowActions: (run) => /* @__PURE__ */ jsx(RowActions, {
|
|
1924
|
+
run,
|
|
1925
|
+
canExecute,
|
|
1926
|
+
onAction
|
|
1927
|
+
}),
|
|
1928
|
+
columns: [
|
|
1929
|
+
{
|
|
1930
|
+
key: "status",
|
|
1931
|
+
header: tr("fluidgrids.executions.executionTable.colStatus", "Status"),
|
|
1932
|
+
priority: "primary",
|
|
1933
|
+
cell: (run) => /* @__PURE__ */ jsxs("span", {
|
|
1934
|
+
className: "inline-flex items-center gap-2",
|
|
1935
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
1936
|
+
title: run.status,
|
|
1937
|
+
children: /* @__PURE__ */ jsx(ExecutionStatusBadge, {
|
|
1938
|
+
status: run.status,
|
|
1939
|
+
size: "sm"
|
|
1940
|
+
})
|
|
1941
|
+
}), run.mode === "TEST" && /* @__PURE__ */ jsx("span", {
|
|
1942
|
+
className: "px-1.5 py-0.5 text-xs border border-border-default text-text-secondary rounded",
|
|
1943
|
+
"data-testid": "run-row-test-badge",
|
|
1944
|
+
children: tr("fluidgrids.executions.executionTable.testBadge", "Test")
|
|
1945
|
+
})]
|
|
1946
|
+
})
|
|
1947
|
+
},
|
|
1948
|
+
{
|
|
1949
|
+
key: "workflow",
|
|
1950
|
+
header: tr("fluidgrids.executions.executionTable.colWorkflow", "Workflow"),
|
|
1951
|
+
priority: "primary",
|
|
1952
|
+
cell: (run) => /* @__PURE__ */ jsxs("div", {
|
|
1953
|
+
className: "flex flex-col",
|
|
1954
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
1955
|
+
className: "text-sm font-medium text-text-primary",
|
|
1956
|
+
children: run.workflow?.name || workflowNames?.[run.workflowKey] || run.workflowKey
|
|
1957
|
+
}), run.status === "FAILED" && /* @__PURE__ */ jsx("span", {
|
|
1958
|
+
className: "text-xs text-[var(--color-status-error-text)]",
|
|
1959
|
+
"data-testid": "run-row-error",
|
|
1960
|
+
children: errorAdvice(tr, run.errorType)
|
|
1961
|
+
})]
|
|
1962
|
+
})
|
|
1963
|
+
},
|
|
1964
|
+
{
|
|
1965
|
+
key: "started",
|
|
1966
|
+
header: tr("fluidgrids.executions.executionTable.colStarted", "Started"),
|
|
1967
|
+
priority: "primary",
|
|
1968
|
+
cell: (run) => /* @__PURE__ */ jsx("span", {
|
|
1969
|
+
className: "text-sm text-text-secondary",
|
|
1970
|
+
children: formatStarted(tr, run.startedAt || run.createdAt)
|
|
1971
|
+
})
|
|
1972
|
+
},
|
|
1973
|
+
{
|
|
1974
|
+
key: "progress",
|
|
1975
|
+
header: tr("fluidgrids.executions.executionTable.colProgress", "Progress"),
|
|
1976
|
+
priority: "secondary",
|
|
1977
|
+
cell: (run) => /* @__PURE__ */ jsxs("span", {
|
|
1978
|
+
className: "text-xs text-text-secondary",
|
|
1979
|
+
children: [
|
|
1980
|
+
run.completedNodes ?? 0,
|
|
1981
|
+
"/",
|
|
1982
|
+
run.totalNodes ?? 0
|
|
1983
|
+
]
|
|
1984
|
+
})
|
|
1985
|
+
}
|
|
1986
|
+
]
|
|
1987
|
+
})
|
|
1988
|
+
});
|
|
1989
|
+
}
|
|
1990
|
+
|
|
1991
|
+
// src/modules/executions/components/RunsEmptyState.tsx
|
|
1992
|
+
/**
|
|
1993
|
+
* The Runs list's two empty states (BOFF-11846, Navigation v2 only): "no runs
|
|
1994
|
+
* yet" (the workspace has never run anything: point to My Workflows and
|
|
1995
|
+
* templates) versus "no matches" (filters hide everything: offer Clear
|
|
1996
|
+
* filters). Today's list says the filters are wrong to a person with none.
|
|
1997
|
+
*/
|
|
1998
|
+
function RunsEmptyState({ filtered, onClearFilters, onOpenWorkflows, onBrowseTemplates }) {
|
|
1999
|
+
const tr = useTr();
|
|
2000
|
+
if (filtered) return /* @__PURE__ */ jsx("div", {
|
|
2001
|
+
"data-testid": "runs-empty-no-matches",
|
|
2002
|
+
children: /* @__PURE__ */ jsx(EmptyState, {
|
|
2003
|
+
icon: /* @__PURE__ */ jsx(Icon, {
|
|
2004
|
+
icon: "mdi:filter-off-outline",
|
|
2005
|
+
width: 48
|
|
2006
|
+
}),
|
|
2007
|
+
title: tr("fluidgrids.executions.executionTable.noMatchesTitle", "No matches"),
|
|
2008
|
+
description: tr("fluidgrids.executions.executionTable.noMatchesDescription", "No runs match these filters."),
|
|
2009
|
+
action: /* @__PURE__ */ jsx(Button$1, {
|
|
2010
|
+
variant: "outline",
|
|
2011
|
+
onClick: onClearFilters,
|
|
2012
|
+
children: tr("fluidgrids.executions.executionFilters.clearFilters", "Clear Filters")
|
|
2013
|
+
})
|
|
2014
|
+
})
|
|
2015
|
+
});
|
|
2016
|
+
return /* @__PURE__ */ jsx("div", {
|
|
2017
|
+
"data-testid": "runs-empty-no-runs",
|
|
2018
|
+
children: /* @__PURE__ */ jsx(EmptyState, {
|
|
2019
|
+
icon: /* @__PURE__ */ jsx(Icon, {
|
|
2020
|
+
icon: "mdi:play-box-outline",
|
|
2021
|
+
width: 48
|
|
2022
|
+
}),
|
|
2023
|
+
title: tr("fluidgrids.executions.executionTable.noRunsTitle", "No runs yet"),
|
|
2024
|
+
description: tr("fluidgrids.executions.executionTable.noRunsDescription", "Your workflows haven't run yet. Open one and press Run, or start from a template."),
|
|
2025
|
+
action: /* @__PURE__ */ jsx(Button$1, {
|
|
2026
|
+
onClick: onOpenWorkflows,
|
|
2027
|
+
children: tr("fluidgrids.executions.executionTable.myWorkflows", "My Workflows")
|
|
2028
|
+
}),
|
|
2029
|
+
secondaryAction: /* @__PURE__ */ jsx(Button$1, {
|
|
2030
|
+
variant: "outline",
|
|
2031
|
+
onClick: onBrowseTemplates,
|
|
2032
|
+
children: tr("fluidgrids.executions.executionTable.browseTemplates", "Browse templates")
|
|
2033
|
+
})
|
|
2034
|
+
})
|
|
2035
|
+
});
|
|
2036
|
+
}
|
|
2037
|
+
|
|
1507
2038
|
// src/modules/run-control/components/SearchAttributeFilterBar.tsx
|
|
1508
2039
|
/**
|
|
1509
2040
|
* The Runs list's search-attribute filter builder (BOFF-9906, spec code-first
|
|
@@ -1939,7 +2470,7 @@ function BatchOperationDialog({ type, input, selection, onClose, onStarted }) {
|
|
|
1939
2470
|
/* @__PURE__ */ jsxs("div", {
|
|
1940
2471
|
className: "space-y-3",
|
|
1941
2472
|
children: [
|
|
1942
|
-
type === "SIGNAL" && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
|
|
2473
|
+
type === "SIGNAL" && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("div", {
|
|
1943
2474
|
className: "space-y-1.5",
|
|
1944
2475
|
children: [/* @__PURE__ */ jsx(Label, {
|
|
1945
2476
|
htmlFor: "batch-signal-name",
|
|
@@ -2298,7 +2829,7 @@ function RunsParityBar({ workflowId, onWorkflowIdChange, total, counts, countsEr
|
|
|
2298
2829
|
" ",
|
|
2299
2830
|
countsError
|
|
2300
2831
|
]
|
|
2301
|
-
}) : /* @__PURE__ */ jsxs(Fragment, { children: [total !== null && /* @__PURE__ */ jsx("button", {
|
|
2832
|
+
}) : /* @__PURE__ */ jsxs(Fragment$1, { children: [total !== null && /* @__PURE__ */ jsx("button", {
|
|
2302
2833
|
type: "button",
|
|
2303
2834
|
onClick: () => onSelectStatus("all"),
|
|
2304
2835
|
className: cn("rounded-full border px-2.5 py-1 text-xs", selectedStatus === "all" ? "border-action-primary-bg bg-action-primary-bg text-action-primary-text" : "border-border-secondary text-text-secondary hover:text-text-primary"),
|
|
@@ -2325,8 +2856,11 @@ var ExecutionsListPage_exports = /* @__PURE__ */ __exportAll({ ExecutionsListPag
|
|
|
2325
2856
|
function ExecutionsListPage() {
|
|
2326
2857
|
const tr = useTr();
|
|
2327
2858
|
const navigate = useNavigate();
|
|
2328
|
-
const
|
|
2329
|
-
const [
|
|
2859
|
+
const v2 = useNavigationV2();
|
|
2860
|
+
const [showDetails, setShowDetails] = useState(false);
|
|
2861
|
+
const [confirmStop, setConfirmStop] = useState(null);
|
|
2862
|
+
const { viewMode, setViewMode, setSelectedExecution, selection, clearSelection, setStatusFilter, setWorkflowFilter, setWorkflowIdFilter, updateFilter, resetFilters, filter, autoRefresh, autoRefreshInterval } = useExecutionsStore();
|
|
2863
|
+
const [searchParams, setSearchParams] = useSearchParams();
|
|
2330
2864
|
const workflowKeyParam = searchParams.get("workflowKey") ?? "";
|
|
2331
2865
|
const lastWorkflowKeyParam = useRef(null);
|
|
2332
2866
|
const linkKey = runListLinkKey(searchParams);
|
|
@@ -2377,21 +2911,42 @@ function ExecutionsListPage() {
|
|
|
2377
2911
|
canDeleteRuns
|
|
2378
2912
|
]);
|
|
2379
2913
|
const statusCounts = useRunStatusCounts(input, parityEnabled);
|
|
2914
|
+
const scopedKey = v2 ? filter.workflowKey : "";
|
|
2915
|
+
const scopedCounts = useRunStatusCounts({ workflowKey: scopedKey }, scopedKey !== "");
|
|
2380
2916
|
const refetchCounts = statusCounts.refetch;
|
|
2917
|
+
const refetchScopedCounts = scopedCounts.refetch;
|
|
2381
2918
|
const { stats, loading: statsLoading, refetch: refetchStats } = useExecutionStats();
|
|
2382
2919
|
const { workflows } = useWorkflowDefinitions({ limit: 100 });
|
|
2383
|
-
const {
|
|
2920
|
+
const { controlExecution, retryExecution, retryExecutions } = useExecutionActions();
|
|
2384
2921
|
useAutoRefresh(useCallback(() => {
|
|
2385
2922
|
refetch();
|
|
2386
2923
|
refetchStats();
|
|
2387
2924
|
refetchCounts();
|
|
2925
|
+
refetchScopedCounts();
|
|
2388
2926
|
}, [
|
|
2389
2927
|
refetch,
|
|
2390
2928
|
refetchStats,
|
|
2391
|
-
refetchCounts
|
|
2929
|
+
refetchCounts,
|
|
2930
|
+
refetchScopedCounts
|
|
2392
2931
|
]), autoRefresh, autoRefreshInterval);
|
|
2393
2932
|
const executionStats = useMemo(() => {
|
|
2394
2933
|
if (!stats) return null;
|
|
2934
|
+
if (scopedKey !== "" && scopedCounts.total !== null && !scopedCounts.error) {
|
|
2935
|
+
const count = (status) => scopedCounts.counts.find((entry) => entry.status === status)?.count ?? 0;
|
|
2936
|
+
const completed = count("COMPLETED");
|
|
2937
|
+
const failed = count("FAILED");
|
|
2938
|
+
return {
|
|
2939
|
+
total: scopedCounts.total,
|
|
2940
|
+
running: count("RUNNING"),
|
|
2941
|
+
completed,
|
|
2942
|
+
failed,
|
|
2943
|
+
cancelled: count("CANCELLED"),
|
|
2944
|
+
pending: count("PENDING"),
|
|
2945
|
+
waiting: count("WAITING"),
|
|
2946
|
+
successRate: completed + failed > 0 ? completed / (completed + failed) * 100 : 0,
|
|
2947
|
+
avgDuration: stats.avgWorkflowExecutionTimeSeconds
|
|
2948
|
+
};
|
|
2949
|
+
}
|
|
2395
2950
|
return {
|
|
2396
2951
|
total: stats.runsCountTotal,
|
|
2397
2952
|
running: stats.runsRunningCount,
|
|
@@ -2403,7 +2958,14 @@ function ExecutionsListPage() {
|
|
|
2403
2958
|
successRate: stats.workflowSuccessRate,
|
|
2404
2959
|
avgDuration: stats.avgWorkflowExecutionTimeSeconds
|
|
2405
2960
|
};
|
|
2406
|
-
}, [
|
|
2961
|
+
}, [
|
|
2962
|
+
stats,
|
|
2963
|
+
scopedKey,
|
|
2964
|
+
scopedCounts.total,
|
|
2965
|
+
scopedCounts.counts,
|
|
2966
|
+
scopedCounts.error
|
|
2967
|
+
]);
|
|
2968
|
+
const statsScoped = scopedKey !== "" && scopedCounts.total !== null && !scopedCounts.error;
|
|
2407
2969
|
const workflowOptions = useMemo(() => workflows.map((w) => ({
|
|
2408
2970
|
workflowKey: w.workflowKey,
|
|
2409
2971
|
name: w.name
|
|
@@ -2426,16 +2988,32 @@ function ExecutionsListPage() {
|
|
|
2426
2988
|
toast.success(tr("fluidgrids.executions.executionsList.retryStarted", "New run started"));
|
|
2427
2989
|
navigate(`../runs/${result.run.runId}`);
|
|
2428
2990
|
};
|
|
2991
|
+
const controlFailedTitle = (action) => {
|
|
2992
|
+
switch (action) {
|
|
2993
|
+
case "pause": return tr("fluidgrids.executions.executionsList.pauseFailed", "Could not pause this run");
|
|
2994
|
+
case "resume": return tr("fluidgrids.executions.executionsList.resumeFailed", "Could not resume this run");
|
|
2995
|
+
case "cancel": return tr("fluidgrids.executions.executionsList.cancelFailed", "Could not cancel this run");
|
|
2996
|
+
}
|
|
2997
|
+
};
|
|
2998
|
+
const handleControl = async (action, execution) => {
|
|
2999
|
+
const result = await controlExecution(action, execution.id);
|
|
3000
|
+
if (!result.ok) toast.error(controlFailedTitle(action), { description: result.message });
|
|
3001
|
+
};
|
|
2429
3002
|
const handleAction = async (action, execution) => {
|
|
2430
3003
|
switch (action) {
|
|
2431
3004
|
case "cancel":
|
|
2432
|
-
|
|
3005
|
+
if (v2) {
|
|
3006
|
+
setConfirmStop({
|
|
3007
|
+
kind: "row",
|
|
3008
|
+
run: execution
|
|
3009
|
+
});
|
|
3010
|
+
return;
|
|
3011
|
+
}
|
|
3012
|
+
await handleControl(action, execution);
|
|
2433
3013
|
break;
|
|
2434
3014
|
case "pause":
|
|
2435
|
-
await pauseExecution(execution.id);
|
|
2436
|
-
break;
|
|
2437
3015
|
case "resume":
|
|
2438
|
-
await
|
|
3016
|
+
await handleControl(action, execution);
|
|
2439
3017
|
break;
|
|
2440
3018
|
case "retry":
|
|
2441
3019
|
await handleRetry(execution);
|
|
@@ -2449,30 +3027,73 @@ function ExecutionsListPage() {
|
|
|
2449
3027
|
};
|
|
2450
3028
|
const handleBulkRetry = async () => {
|
|
2451
3029
|
if (selection.runIds.length === 0) return;
|
|
2452
|
-
const
|
|
3030
|
+
const plan = planBulkRetry(selection.runIds, executions);
|
|
3031
|
+
if (plan.runIds.length === 0) {
|
|
3032
|
+
toast.info(tr("fluidgrids.executions.executionsList.bulkRetryNoneFailed", "None of the selected runs failed, so there is nothing to run again."));
|
|
3033
|
+
return;
|
|
3034
|
+
}
|
|
3035
|
+
const retried = await retryExecutions(plan.runIds);
|
|
2453
3036
|
if (retried.length === 0) {
|
|
2454
3037
|
toast.error(tr("fluidgrids.executions.executionsList.bulkRetryFailed", "Could not retry the selected runs"));
|
|
2455
3038
|
return;
|
|
2456
3039
|
}
|
|
2457
3040
|
toast.success(tr("fluidgrids.executions.executionsList.bulkRetryStarted", `${retried.length} new run${retried.length === 1 ? "" : "s"} started`));
|
|
3041
|
+
if (plan.skippedNotFailed > 0 || plan.skippedOverLimit > 0) toast.info(tr("fluidgrids.executions.executionsList.bulkRetrySkipped", "Only failed runs are run again, and at most {{limit}} at a time. Left out: {{notFailed}} that did not fail, {{overLimit}} over the limit.", {
|
|
3042
|
+
limit: 10,
|
|
3043
|
+
notFailed: plan.skippedNotFailed,
|
|
3044
|
+
overLimit: plan.skippedOverLimit
|
|
3045
|
+
}));
|
|
2458
3046
|
clearSelection();
|
|
2459
3047
|
refetch();
|
|
2460
3048
|
};
|
|
3049
|
+
const handleConfirmedStop = async () => {
|
|
3050
|
+
const pending = confirmStop;
|
|
3051
|
+
setConfirmStop(null);
|
|
3052
|
+
if (!pending) return;
|
|
3053
|
+
if (pending.kind === "row") {
|
|
3054
|
+
await handleControl("cancel", pending.run);
|
|
3055
|
+
refetch();
|
|
3056
|
+
} else await handleBulkAction("cancel");
|
|
3057
|
+
};
|
|
2461
3058
|
const handleBulkAction = async (action) => {
|
|
2462
3059
|
if (selection.runIds.length === 0) return;
|
|
2463
|
-
const
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
});
|
|
2470
|
-
const results = await Promise.allSettled(promises);
|
|
2471
|
-
const failures = results.filter((r) => r.status === "rejected");
|
|
2472
|
-
if (failures.length > 0) console.error(`Bulk action partially failed: ${failures.length}/${results.length} failed`);
|
|
3060
|
+
const results = await Promise.all(selection.runIds.map((id) => controlExecution(action, id)));
|
|
3061
|
+
const failed = results.filter((result) => !result.ok);
|
|
3062
|
+
if (failed.length > 0) toast.error(tr("fluidgrids.executions.executionsList.bulkActionFailed", "{{failed}} of {{total}} runs could not be changed", {
|
|
3063
|
+
failed: failed.length,
|
|
3064
|
+
total: results.length
|
|
3065
|
+
}));
|
|
2473
3066
|
clearSelection();
|
|
2474
3067
|
refetch();
|
|
2475
3068
|
};
|
|
3069
|
+
const viewLabel = (mode) => mode === "table" ? tr("fluidgrids.executions.executionsList.tableViewTooltip", "Table View") : mode === "cards" ? tr("fluidgrids.executions.executionsList.cardViewTooltip", "Card View") : tr("fluidgrids.executions.executionsList.timelineViewTooltip", "Timeline View");
|
|
3070
|
+
const viewMenuItems = [
|
|
3071
|
+
"table",
|
|
3072
|
+
"cards",
|
|
3073
|
+
"timeline"
|
|
3074
|
+
].map((mode) => ({
|
|
3075
|
+
id: `view-${mode}`,
|
|
3076
|
+
icon: viewMode === mode ? "mdi:check" : void 0,
|
|
3077
|
+
label: viewLabel(mode),
|
|
3078
|
+
onSelect: () => setViewMode(mode)
|
|
3079
|
+
}));
|
|
3080
|
+
const viewMenuToggles = [{
|
|
3081
|
+
id: "details",
|
|
3082
|
+
label: tr("fluidgrids.executions.executionsList.showRunDetails", "Show run details and bulk actions"),
|
|
3083
|
+
checked: showDetails,
|
|
3084
|
+
onCheckedChange: setShowDetails
|
|
3085
|
+
}];
|
|
3086
|
+
const filtersActive = countActiveFilters(filter, parityEnabled) > 0 || searchFilter !== null;
|
|
3087
|
+
const showEmptyState = v2 && !loading && !error && executions.length === 0;
|
|
3088
|
+
const scopedWorkflowName = workflowKeyParam ? workflowNames[workflowKeyParam] ?? workflowKeyParam : null;
|
|
3089
|
+
const showAllWorkflows = () => {
|
|
3090
|
+
setWorkflowFilter("");
|
|
3091
|
+
setSearchParams((params) => {
|
|
3092
|
+
const next = new URLSearchParams(params);
|
|
3093
|
+
next.delete("workflowKey");
|
|
3094
|
+
return next;
|
|
3095
|
+
}, { replace: true });
|
|
3096
|
+
};
|
|
2476
3097
|
return /* @__PURE__ */ jsxs("div", {
|
|
2477
3098
|
className: "p-4 sm:p-6 bg-background-primary min-h-screen",
|
|
2478
3099
|
children: [
|
|
@@ -2494,11 +3115,18 @@ function ExecutionsListPage() {
|
|
|
2494
3115
|
})
|
|
2495
3116
|
] }), /* @__PURE__ */ jsxs("div", {
|
|
2496
3117
|
className: "flex flex-wrap items-center gap-3",
|
|
2497
|
-
children: [/* @__PURE__ */
|
|
3118
|
+
children: [v2 ? /* @__PURE__ */ jsx(RunActionsMenu, {
|
|
3119
|
+
items: viewMenuItems,
|
|
3120
|
+
toggles: viewMenuToggles,
|
|
3121
|
+
label: tr("fluidgrids.executions.executionsList.moreOptions", "More options"),
|
|
3122
|
+
"data-testid": "runs-view-menu"
|
|
3123
|
+
}) : /* @__PURE__ */ jsxs("div", {
|
|
2498
3124
|
className: "flex items-center bg-background-secondary rounded-lg border border-border-secondary p-1",
|
|
2499
3125
|
children: [
|
|
2500
3126
|
/* @__PURE__ */ jsx("button", {
|
|
2501
3127
|
onClick: () => setViewMode("table"),
|
|
3128
|
+
"aria-pressed": viewMode === "table",
|
|
3129
|
+
"aria-label": tr("fluidgrids.executions.executionsList.tableViewTooltip", "Table View"),
|
|
2502
3130
|
className: `p-2 rounded ${viewMode === "table" ? "bg-background-tertiary text-text-primary" : "text-text-secondary hover:text-text-primary"}`,
|
|
2503
3131
|
title: tr("fluidgrids.executions.executionsList.tableViewTooltip", "Table View"),
|
|
2504
3132
|
children: /* @__PURE__ */ jsx(Icon, {
|
|
@@ -2508,6 +3136,8 @@ function ExecutionsListPage() {
|
|
|
2508
3136
|
}),
|
|
2509
3137
|
/* @__PURE__ */ jsx("button", {
|
|
2510
3138
|
onClick: () => setViewMode("cards"),
|
|
3139
|
+
"aria-pressed": viewMode === "cards",
|
|
3140
|
+
"aria-label": tr("fluidgrids.executions.executionsList.cardViewTooltip", "Card View"),
|
|
2511
3141
|
className: `p-2 rounded ${viewMode === "cards" ? "bg-background-tertiary text-text-primary" : "text-text-secondary hover:text-text-primary"}`,
|
|
2512
3142
|
title: tr("fluidgrids.executions.executionsList.cardViewTooltip", "Card View"),
|
|
2513
3143
|
children: /* @__PURE__ */ jsx(Icon, {
|
|
@@ -2517,6 +3147,8 @@ function ExecutionsListPage() {
|
|
|
2517
3147
|
}),
|
|
2518
3148
|
/* @__PURE__ */ jsx("button", {
|
|
2519
3149
|
onClick: () => setViewMode("timeline"),
|
|
3150
|
+
"aria-pressed": viewMode === "timeline",
|
|
3151
|
+
"aria-label": tr("fluidgrids.executions.executionsList.timelineViewTooltip", "Timeline View"),
|
|
2520
3152
|
className: `p-2 rounded ${viewMode === "timeline" ? "bg-background-tertiary text-text-primary" : "text-text-secondary hover:text-text-primary"}`,
|
|
2521
3153
|
title: tr("fluidgrids.executions.executionsList.timelineViewTooltip", "Timeline View"),
|
|
2522
3154
|
children: /* @__PURE__ */ jsx(Icon, {
|
|
@@ -2536,12 +3168,27 @@ function ExecutionsListPage() {
|
|
|
2536
3168
|
})]
|
|
2537
3169
|
})]
|
|
2538
3170
|
}),
|
|
3171
|
+
v2 && scopedWorkflowName && /* @__PURE__ */ jsxs("p", {
|
|
3172
|
+
className: "mb-3 text-sm text-text-secondary",
|
|
3173
|
+
"data-testid": "runs-of-workflow",
|
|
3174
|
+
children: [
|
|
3175
|
+
tr("fluidgrids.executions.executionsList.runsOfWorkflow", "Runs of {{workflow}}", { workflow: scopedWorkflowName }),
|
|
3176
|
+
" · ",
|
|
3177
|
+
/* @__PURE__ */ jsx("button", {
|
|
3178
|
+
type: "button",
|
|
3179
|
+
onClick: showAllWorkflows,
|
|
3180
|
+
className: "text-text-link hover:text-text-linkHover hover:underline",
|
|
3181
|
+
children: tr("fluidgrids.executions.executionsList.showAll", "Show all")
|
|
3182
|
+
})
|
|
3183
|
+
]
|
|
3184
|
+
}),
|
|
2539
3185
|
/* @__PURE__ */ jsx("div", {
|
|
2540
3186
|
className: "mb-6",
|
|
2541
3187
|
"data-tour": "fluidgrids-runs-stats",
|
|
2542
3188
|
children: /* @__PURE__ */ jsx(ExecutionStats, {
|
|
2543
3189
|
stats: executionStats,
|
|
2544
|
-
loading: statsLoading,
|
|
3190
|
+
loading: v2 ? statsLoading && !executionStats : statsLoading,
|
|
3191
|
+
scoped: statsScoped,
|
|
2545
3192
|
onFilterByStatus: handleFilterByStatus
|
|
2546
3193
|
})
|
|
2547
3194
|
}),
|
|
@@ -2581,7 +3228,7 @@ function ExecutionsListPage() {
|
|
|
2581
3228
|
}), tr("fluidgrids.runControl.batch.jobs", "Batch jobs")]
|
|
2582
3229
|
})
|
|
2583
3230
|
}),
|
|
2584
|
-
selection.runIds.length > 0 && /* @__PURE__ */ jsxs("div", {
|
|
3231
|
+
selection.runIds.length > 0 && (!v2 || canExecuteRuns) && /* @__PURE__ */ jsxs("div", {
|
|
2585
3232
|
className: "mb-4 p-3 bg-action-primary-bg/10 rounded-lg flex flex-wrap items-center gap-3",
|
|
2586
3233
|
children: [
|
|
2587
3234
|
/* @__PURE__ */ jsxs("span", {
|
|
@@ -2610,7 +3257,7 @@ function ExecutionsListPage() {
|
|
|
2610
3257
|
"data-agent": "confirm",
|
|
2611
3258
|
variant: "outline",
|
|
2612
3259
|
size: "sm",
|
|
2613
|
-
onClick: () => handleBulkAction("cancel"),
|
|
3260
|
+
onClick: () => v2 ? setConfirmStop({ kind: "bulk" }) : handleBulkAction("cancel"),
|
|
2614
3261
|
children: [/* @__PURE__ */ jsx(Icon, {
|
|
2615
3262
|
icon: "mdi:stop",
|
|
2616
3263
|
className: "mr-1",
|
|
@@ -2641,7 +3288,7 @@ function ExecutionsListPage() {
|
|
|
2641
3288
|
})
|
|
2642
3289
|
]
|
|
2643
3290
|
}),
|
|
2644
|
-
phaseC.runControl && /* @__PURE__ */ jsxs(Fragment, { children: [selection.allSelected && total > selection.runIds.length && /* @__PURE__ */ jsx("button", {
|
|
3291
|
+
phaseC.runControl && /* @__PURE__ */ jsxs(Fragment$1, { children: [selection.allSelected && total > selection.runIds.length && /* @__PURE__ */ jsx("button", {
|
|
2645
3292
|
type: "button",
|
|
2646
3293
|
onClick: () => setAllMatching((current) => !current),
|
|
2647
3294
|
className: "text-sm text-action-primary-text hover:underline",
|
|
@@ -2678,7 +3325,14 @@ function ExecutionsListPage() {
|
|
|
2678
3325
|
}),
|
|
2679
3326
|
/* @__PURE__ */ jsx("p", {
|
|
2680
3327
|
className: "mt-1 text-sm text-[var(--color-status-error-text)]",
|
|
2681
|
-
children:
|
|
3328
|
+
children: tr("fluidgrids.executions.executionsList.loadErrorDescription", "We couldn't load your runs. Try again in a moment.")
|
|
3329
|
+
}),
|
|
3330
|
+
/* @__PURE__ */ jsx(TechnicalDetails, {
|
|
3331
|
+
className: "mt-2 text-[var(--color-status-error-text)]",
|
|
3332
|
+
children: /* @__PURE__ */ jsx("p", {
|
|
3333
|
+
className: "text-sm font-mono break-words",
|
|
3334
|
+
children: error.message
|
|
3335
|
+
})
|
|
2682
3336
|
}),
|
|
2683
3337
|
/* @__PURE__ */ jsx(Button$1, {
|
|
2684
3338
|
variant: "outline",
|
|
@@ -2689,27 +3343,58 @@ function ExecutionsListPage() {
|
|
|
2689
3343
|
})
|
|
2690
3344
|
]
|
|
2691
3345
|
}),
|
|
2692
|
-
|
|
3346
|
+
showEmptyState && /* @__PURE__ */ jsx(RunsEmptyState, {
|
|
3347
|
+
filtered: filtersActive,
|
|
3348
|
+
onClearFilters: () => {
|
|
3349
|
+
setSearchFilter(null);
|
|
3350
|
+
resetFilters();
|
|
3351
|
+
},
|
|
3352
|
+
onOpenWorkflows: () => navigate("../list"),
|
|
3353
|
+
onBrowseTemplates: () => navigate("../templates")
|
|
3354
|
+
}),
|
|
3355
|
+
!showEmptyState && viewMode === "table" && v2 && !showDetails && /* @__PURE__ */ jsx(RunsPlainTable, {
|
|
2693
3356
|
workflowNames,
|
|
2694
3357
|
executions,
|
|
2695
3358
|
loading,
|
|
3359
|
+
canExecute: canExecuteRuns,
|
|
2696
3360
|
onRowClick: handleRowClick,
|
|
2697
3361
|
onAction: handleAction
|
|
2698
3362
|
}),
|
|
2699
|
-
viewMode === "
|
|
3363
|
+
!showEmptyState && viewMode === "table" && (!v2 || showDetails) && /* @__PURE__ */ jsx(ExecutionTable, {
|
|
3364
|
+
workflowNames,
|
|
3365
|
+
executions,
|
|
3366
|
+
loading,
|
|
3367
|
+
canExecute: !v2 || canExecuteRuns,
|
|
3368
|
+
onRowClick: handleRowClick,
|
|
3369
|
+
onAction: handleAction
|
|
3370
|
+
}),
|
|
3371
|
+
!showEmptyState && viewMode === "cards" && /* @__PURE__ */ jsx(ExecutionCards, {
|
|
2700
3372
|
workflowNames,
|
|
2701
3373
|
executions,
|
|
2702
3374
|
loading,
|
|
2703
3375
|
onCardClick: handleRowClick,
|
|
2704
3376
|
onAction: handleAction
|
|
2705
3377
|
}),
|
|
2706
|
-
viewMode === "timeline" && /* @__PURE__ */ jsx(ExecutionTimeline, {
|
|
3378
|
+
!showEmptyState && viewMode === "timeline" && /* @__PURE__ */ jsx(ExecutionTimeline, {
|
|
3379
|
+
workflowNames,
|
|
2707
3380
|
executions,
|
|
2708
3381
|
loading,
|
|
2709
3382
|
onItemClick: handleRowClick,
|
|
2710
3383
|
onAction: handleAction
|
|
2711
3384
|
}),
|
|
2712
|
-
/* @__PURE__ */ jsx(Pagination, {
|
|
3385
|
+
/* @__PURE__ */ jsx(Pagination, {
|
|
3386
|
+
totalItems: total,
|
|
3387
|
+
showPageSize: !v2 || showDetails
|
|
3388
|
+
}),
|
|
3389
|
+
v2 && /* @__PURE__ */ jsx(ConfirmStopRunDialog, {
|
|
3390
|
+
open: confirmStop !== null,
|
|
3391
|
+
workflowName: confirmStop?.kind === "row" ? confirmStop.run.workflow?.name || workflowNames[confirmStop.run.workflowKey] || confirmStop.run.workflowKey : null,
|
|
3392
|
+
count: selection.runIds.length,
|
|
3393
|
+
onConfirm: () => void handleConfirmedStop(),
|
|
3394
|
+
onOpenChange: (open) => {
|
|
3395
|
+
if (!open) setConfirmStop(null);
|
|
3396
|
+
}
|
|
3397
|
+
}),
|
|
2713
3398
|
batchType && /* @__PURE__ */ jsx(BatchOperationDialog, {
|
|
2714
3399
|
type: batchType,
|
|
2715
3400
|
input,
|