@burdenoff/fluidgrids-fe-sdk 2026.510.105

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.
Files changed (68) hide show
  1. package/README.md +149 -0
  2. package/dist/ExecutionDetailPage-3EVS3WEC.js +6 -0
  3. package/dist/ExecutionDetailPage-3EVS3WEC.js.map +1 -0
  4. package/dist/ExecutionsListPage-NH2JLL2D.js +8 -0
  5. package/dist/ExecutionsListPage-NH2JLL2D.js.map +1 -0
  6. package/dist/TemplateConfigurationModal-UJAGRE7X.js +258 -0
  7. package/dist/TemplateConfigurationModal-UJAGRE7X.js.map +1 -0
  8. package/dist/TemplateDetailPanel-UXH6KPCH.js +172 -0
  9. package/dist/TemplateDetailPanel-UXH6KPCH.js.map +1 -0
  10. package/dist/WorkflowBuilder-BMKFLHVE.js +15 -0
  11. package/dist/WorkflowBuilder-BMKFLHVE.js.map +1 -0
  12. package/dist/WorkflowsList-CLI32VRE.js +8 -0
  13. package/dist/WorkflowsList-CLI32VRE.js.map +1 -0
  14. package/dist/chunk-4FFPGQD3.js +584 -0
  15. package/dist/chunk-4FFPGQD3.js.map +1 -0
  16. package/dist/chunk-5BDQNSP3.js +107 -0
  17. package/dist/chunk-5BDQNSP3.js.map +1 -0
  18. package/dist/chunk-6PHBYAEG.js +11494 -0
  19. package/dist/chunk-6PHBYAEG.js.map +1 -0
  20. package/dist/chunk-BQXHJIER.js +45 -0
  21. package/dist/chunk-BQXHJIER.js.map +1 -0
  22. package/dist/chunk-BXDSTMUA.js +8848 -0
  23. package/dist/chunk-BXDSTMUA.js.map +1 -0
  24. package/dist/chunk-CGKBAJMM.js +292 -0
  25. package/dist/chunk-CGKBAJMM.js.map +1 -0
  26. package/dist/chunk-FGYVIXQ7.js +979 -0
  27. package/dist/chunk-FGYVIXQ7.js.map +1 -0
  28. package/dist/chunk-G7B4SYFM.js +22 -0
  29. package/dist/chunk-G7B4SYFM.js.map +1 -0
  30. package/dist/chunk-GSJOLO3A.js +251 -0
  31. package/dist/chunk-GSJOLO3A.js.map +1 -0
  32. package/dist/chunk-GSS5PHRL.js +386 -0
  33. package/dist/chunk-GSS5PHRL.js.map +1 -0
  34. package/dist/chunk-GY66IQWN.js +524 -0
  35. package/dist/chunk-GY66IQWN.js.map +1 -0
  36. package/dist/chunk-LUGJJ7LL.js +297 -0
  37. package/dist/chunk-LUGJJ7LL.js.map +1 -0
  38. package/dist/chunk-NDJSUC4W.js +155 -0
  39. package/dist/chunk-NDJSUC4W.js.map +1 -0
  40. package/dist/chunk-UOCR65PI.js +262 -0
  41. package/dist/chunk-UOCR65PI.js.map +1 -0
  42. package/dist/chunk-WD52O45G.js +2015 -0
  43. package/dist/chunk-WD52O45G.js.map +1 -0
  44. package/dist/chunk-WWU2O2SR.js +52 -0
  45. package/dist/chunk-WWU2O2SR.js.map +1 -0
  46. package/dist/chunk-XQP33UJR.js +57 -0
  47. package/dist/chunk-XQP33UJR.js.map +1 -0
  48. package/dist/chunk-Z54K22LP.js +82 -0
  49. package/dist/chunk-Z54K22LP.js.map +1 -0
  50. package/dist/client-AMUUS7VE.js +3 -0
  51. package/dist/client-AMUUS7VE.js.map +1 -0
  52. package/dist/config-E4E7M6IN.js +3 -0
  53. package/dist/config-E4E7M6IN.js.map +1 -0
  54. package/dist/global-client-OW43ZRDR.js +3 -0
  55. package/dist/global-client-OW43ZRDR.js.map +1 -0
  56. package/dist/global-operations-WPTEYCJM.js +3 -0
  57. package/dist/global-operations-WPTEYCJM.js.map +1 -0
  58. package/dist/index.d.ts +56706 -0
  59. package/dist/index.js +6564 -0
  60. package/dist/index.js.map +1 -0
  61. package/dist/styles.css +139 -0
  62. package/dist/template-input-applicator-657KE4DM.js +3 -0
  63. package/dist/template-input-applicator-657KE4DM.js.map +1 -0
  64. package/dist/useImportWorkflowTemplate-2HS5D2OP.js +11 -0
  65. package/dist/useImportWorkflowTemplate-2HS5D2OP.js.map +1 -0
  66. package/dist/useTemplateDetail-NK63V3PC.js +6 -0
  67. package/dist/useTemplateDetail-NK63V3PC.js.map +1 -0
  68. package/package.json +148 -0
@@ -0,0 +1,2015 @@
1
+ import { ExecutionDetailDocument, ExecutionLogsDocument, ExecutionStatsDocument, PauseExecutionDocument, ResumeExecutionDocument, CancelExecutionDocument, RetryNodeDocument, TerminateExecutionDocument, ExecutionsListDocument } from './chunk-FGYVIXQ7.js';
2
+ import { getFluidGridsClient } from './chunk-5BDQNSP3.js';
3
+ import { Icon } from '@iconify/react';
4
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
5
+ import { create } from 'zustand';
6
+ import { useState, useCallback, useMemo, useEffect } from 'react';
7
+ import { Button } from '@burdenoff/fe-libs/button';
8
+ import { useNavigate } from 'react-router-dom';
9
+ import { gql } from '@apollo/client';
10
+
11
+ // src/modules/executions/types/index.ts
12
+ var RUN_STATUS_CONFIG = {
13
+ PENDING: {
14
+ label: "Pending",
15
+ color: "text-gray-600 dark:text-gray-400",
16
+ bgColor: "bg-gray-50 dark:bg-gray-800",
17
+ borderColor: "border-gray-200 dark:border-gray-700",
18
+ icon: "mdi:clock-outline"
19
+ },
20
+ RUNNING: {
21
+ label: "Running",
22
+ color: "text-blue-600 dark:text-blue-400",
23
+ bgColor: "bg-blue-50 dark:bg-blue-900/20",
24
+ borderColor: "border-blue-200 dark:border-blue-800",
25
+ icon: "mdi:play-circle-outline"
26
+ },
27
+ COMPLETED: {
28
+ label: "Completed",
29
+ color: "text-green-600 dark:text-green-400",
30
+ bgColor: "bg-green-50 dark:bg-green-900/20",
31
+ borderColor: "border-green-200 dark:border-green-800",
32
+ icon: "mdi:check-circle-outline"
33
+ },
34
+ FAILED: {
35
+ label: "Failed",
36
+ color: "text-red-600 dark:text-red-400",
37
+ bgColor: "bg-red-50 dark:bg-red-900/20",
38
+ borderColor: "border-red-200 dark:border-red-800",
39
+ icon: "mdi:alert-circle-outline"
40
+ },
41
+ CANCELLED: {
42
+ label: "Cancelled",
43
+ color: "text-orange-600 dark:text-orange-400",
44
+ bgColor: "bg-orange-50 dark:bg-orange-900/20",
45
+ borderColor: "border-orange-200 dark:border-orange-800",
46
+ icon: "mdi:cancel"
47
+ },
48
+ WAITING: {
49
+ label: "Waiting",
50
+ color: "text-purple-600 dark:text-purple-400",
51
+ bgColor: "bg-purple-50 dark:bg-purple-900/20",
52
+ borderColor: "border-purple-200 dark:border-purple-800",
53
+ icon: "mdi:timer-sand"
54
+ },
55
+ TERMINATED: {
56
+ label: "Terminated",
57
+ color: "text-gray-600 dark:text-gray-400",
58
+ bgColor: "bg-gray-50 dark:bg-gray-800",
59
+ borderColor: "border-gray-300 dark:border-gray-600",
60
+ icon: "mdi:stop-circle-outline"
61
+ }
62
+ };
63
+ var NODE_STATUS_CONFIG = {
64
+ PENDING: {
65
+ label: "Pending",
66
+ color: "text-gray-600 dark:text-gray-400",
67
+ bgColor: "bg-gray-50 dark:bg-gray-800",
68
+ borderColor: "border-gray-200 dark:border-gray-700",
69
+ icon: "mdi:clock-outline"
70
+ },
71
+ RUNNING: {
72
+ label: "Running",
73
+ color: "text-blue-600 dark:text-blue-400",
74
+ bgColor: "bg-blue-50 dark:bg-blue-900/20",
75
+ borderColor: "border-blue-200 dark:border-blue-800",
76
+ icon: "mdi:play-circle-outline"
77
+ },
78
+ COMPLETED: {
79
+ label: "Completed",
80
+ color: "text-green-600 dark:text-green-400",
81
+ bgColor: "bg-green-50 dark:bg-green-900/20",
82
+ borderColor: "border-green-200 dark:border-green-800",
83
+ icon: "mdi:check-circle-outline"
84
+ },
85
+ FAILED: {
86
+ label: "Failed",
87
+ color: "text-red-600 dark:text-red-400",
88
+ bgColor: "bg-red-50 dark:bg-red-900/20",
89
+ borderColor: "border-red-200 dark:border-red-800",
90
+ icon: "mdi:alert-circle-outline"
91
+ },
92
+ SKIPPED: {
93
+ label: "Skipped",
94
+ color: "text-gray-500 dark:text-gray-500",
95
+ bgColor: "bg-gray-100 dark:bg-gray-700",
96
+ borderColor: "border-gray-200 dark:border-gray-600",
97
+ icon: "mdi:skip-next"
98
+ },
99
+ DELAYED: {
100
+ label: "Delayed",
101
+ color: "text-yellow-600 dark:text-yellow-400",
102
+ bgColor: "bg-yellow-50 dark:bg-yellow-900/20",
103
+ borderColor: "border-yellow-200 dark:border-yellow-800",
104
+ icon: "mdi:clock-alert-outline"
105
+ },
106
+ CANCELLED: {
107
+ label: "Cancelled",
108
+ color: "text-orange-600 dark:text-orange-400",
109
+ bgColor: "bg-orange-50 dark:bg-orange-900/20",
110
+ borderColor: "border-orange-200 dark:border-orange-800",
111
+ icon: "mdi:cancel"
112
+ },
113
+ TIMEOUT: {
114
+ label: "Timeout",
115
+ color: "text-red-600 dark:text-red-400",
116
+ bgColor: "bg-red-50 dark:bg-red-900/20",
117
+ borderColor: "border-red-200 dark:border-red-800",
118
+ icon: "mdi:timer-off-outline"
119
+ },
120
+ WAITING_SUBWORKFLOW: {
121
+ label: "Waiting",
122
+ color: "text-purple-600 dark:text-purple-400",
123
+ bgColor: "bg-purple-50 dark:bg-purple-900/20",
124
+ borderColor: "border-purple-200 dark:border-purple-800",
125
+ icon: "mdi:subdirectory-arrow-right"
126
+ }
127
+ };
128
+ function ExecutionStatusBadge({
129
+ status,
130
+ size = "md",
131
+ showIcon = true,
132
+ showLabel = true,
133
+ animated = true
134
+ }) {
135
+ const config = RUN_STATUS_CONFIG[status];
136
+ const sizeClasses = {
137
+ sm: "px-1.5 py-0.5 text-xs gap-1",
138
+ md: "px-2 py-1 text-sm gap-1.5",
139
+ lg: "px-3 py-1.5 text-base gap-2"
140
+ };
141
+ const iconSizes = {
142
+ sm: 12,
143
+ md: 14,
144
+ lg: 16
145
+ };
146
+ const isRunning = status === "RUNNING";
147
+ return /* @__PURE__ */ jsxs(
148
+ "span",
149
+ {
150
+ className: `
151
+ inline-flex items-center rounded-full font-medium
152
+ ${config.bgColor} ${config.color} border ${config.borderColor}
153
+ ${sizeClasses[size]}
154
+ ${animated && isRunning ? "animate-pulse" : ""}
155
+ `,
156
+ children: [
157
+ showIcon && /* @__PURE__ */ jsx(
158
+ Icon,
159
+ {
160
+ icon: config.icon,
161
+ width: iconSizes[size],
162
+ height: iconSizes[size],
163
+ className: animated && isRunning ? "animate-spin" : ""
164
+ }
165
+ ),
166
+ showLabel && /* @__PURE__ */ jsx("span", { children: config.label })
167
+ ]
168
+ }
169
+ );
170
+ }
171
+ function NodeStatusBadge({
172
+ status,
173
+ size = "md",
174
+ showIcon = true,
175
+ showLabel = true,
176
+ animated = true
177
+ }) {
178
+ const config = NODE_STATUS_CONFIG[status];
179
+ const sizeClasses = {
180
+ sm: "px-1.5 py-0.5 text-xs gap-1",
181
+ md: "px-2 py-1 text-sm gap-1.5",
182
+ lg: "px-3 py-1.5 text-base gap-2"
183
+ };
184
+ const iconSizes = {
185
+ sm: 12,
186
+ md: 14,
187
+ lg: 16
188
+ };
189
+ const isRunning = status === "RUNNING";
190
+ return /* @__PURE__ */ jsxs(
191
+ "span",
192
+ {
193
+ className: `
194
+ inline-flex items-center rounded-full font-medium
195
+ ${config.bgColor} ${config.color} border ${config.borderColor}
196
+ ${sizeClasses[size]}
197
+ ${animated && isRunning ? "animate-pulse" : ""}
198
+ `,
199
+ children: [
200
+ showIcon && /* @__PURE__ */ jsx(
201
+ Icon,
202
+ {
203
+ icon: config.icon,
204
+ width: iconSizes[size],
205
+ height: iconSizes[size],
206
+ className: animated && isRunning ? "animate-spin" : ""
207
+ }
208
+ ),
209
+ showLabel && /* @__PURE__ */ jsx("span", { children: config.label })
210
+ ]
211
+ }
212
+ );
213
+ }
214
+ var defaultFilter = {
215
+ status: "all",
216
+ workflowKey: "",
217
+ dateRange: {
218
+ start: null,
219
+ end: null,
220
+ preset: "all"
221
+ },
222
+ search: ""
223
+ };
224
+ var defaultPagination = {
225
+ page: 1,
226
+ pageSize: 25,
227
+ total: 0
228
+ };
229
+ var useExecutionsStore = create((set) => ({
230
+ // Initial state
231
+ viewMode: "table",
232
+ selectedExecution: null,
233
+ expandedRows: /* @__PURE__ */ new Set(),
234
+ selection: {
235
+ runIds: [],
236
+ allSelected: false
237
+ },
238
+ filter: defaultFilter,
239
+ pagination: defaultPagination,
240
+ isFilterPanelOpen: false,
241
+ isDetailsPanelOpen: false,
242
+ autoRefresh: true,
243
+ autoRefreshInterval: 5e3,
244
+ liveRunIds: /* @__PURE__ */ new Set(),
245
+ // Actions - View
246
+ setViewMode: (mode) => set({ viewMode: mode }),
247
+ setSelectedExecution: (execution) => set({
248
+ selectedExecution: execution,
249
+ isDetailsPanelOpen: execution !== null
250
+ }),
251
+ toggleRowExpanded: (runId) => set((state) => {
252
+ const newExpanded = new Set(state.expandedRows);
253
+ if (newExpanded.has(runId)) {
254
+ newExpanded.delete(runId);
255
+ } else {
256
+ newExpanded.add(runId);
257
+ }
258
+ return { expandedRows: newExpanded };
259
+ }),
260
+ // Actions - Selection
261
+ setSelection: (selection) => set({ selection }),
262
+ toggleSelectRun: (runId) => set((state) => {
263
+ const isSelected = state.selection.runIds.includes(runId);
264
+ const newRunIds = isSelected ? state.selection.runIds.filter((id) => id !== runId) : [...state.selection.runIds, runId];
265
+ return {
266
+ selection: {
267
+ runIds: newRunIds,
268
+ allSelected: false
269
+ }
270
+ };
271
+ }),
272
+ selectAll: (runIds) => set((state) => ({
273
+ selection: {
274
+ runIds: state.selection.allSelected ? [] : runIds,
275
+ allSelected: !state.selection.allSelected
276
+ }
277
+ })),
278
+ clearSelection: () => set({
279
+ selection: {
280
+ runIds: [],
281
+ allSelected: false
282
+ }
283
+ }),
284
+ // Actions - Filter
285
+ updateFilter: (filterUpdate) => set((state) => ({
286
+ filter: { ...state.filter, ...filterUpdate },
287
+ pagination: { ...state.pagination, page: 1 }
288
+ })),
289
+ setStatusFilter: (status) => set((state) => ({
290
+ filter: { ...state.filter, status },
291
+ pagination: { ...state.pagination, page: 1 }
292
+ })),
293
+ setWorkflowFilter: (workflowKey) => set((state) => ({
294
+ filter: { ...state.filter, workflowKey },
295
+ pagination: { ...state.pagination, page: 1 }
296
+ })),
297
+ setDateRange: (dateRange) => set((state) => ({
298
+ filter: { ...state.filter, dateRange },
299
+ pagination: { ...state.pagination, page: 1 }
300
+ })),
301
+ setSearchQuery: (search) => set((state) => ({
302
+ filter: { ...state.filter, search },
303
+ pagination: { ...state.pagination, page: 1 }
304
+ })),
305
+ resetFilters: () => set({
306
+ filter: defaultFilter,
307
+ pagination: { ...defaultPagination }
308
+ }),
309
+ // Actions - Pagination
310
+ setPage: (page) => set((state) => ({
311
+ pagination: { ...state.pagination, page }
312
+ })),
313
+ setPageSize: (pageSize) => set((state) => ({
314
+ pagination: { ...state.pagination, pageSize, page: 1 }
315
+ })),
316
+ setTotal: (total) => set((state) => ({
317
+ pagination: { ...state.pagination, total }
318
+ })),
319
+ // Actions - UI
320
+ toggleFilterPanel: () => set((state) => ({
321
+ isFilterPanelOpen: !state.isFilterPanelOpen
322
+ })),
323
+ toggleDetailsPanel: () => set((state) => ({
324
+ isDetailsPanelOpen: !state.isDetailsPanelOpen
325
+ })),
326
+ setAutoRefresh: (enabled) => set({ autoRefresh: enabled }),
327
+ setAutoRefreshInterval: (interval) => set({ autoRefreshInterval: interval }),
328
+ // Actions - Real-time
329
+ addLiveRun: (runId) => set((state) => {
330
+ const newLiveRunIds = new Set(state.liveRunIds);
331
+ newLiveRunIds.add(runId);
332
+ return { liveRunIds: newLiveRunIds };
333
+ }),
334
+ removeLiveRun: (runId) => set((state) => {
335
+ const newLiveRunIds = new Set(state.liveRunIds);
336
+ newLiveRunIds.delete(runId);
337
+ return { liveRunIds: newLiveRunIds };
338
+ }),
339
+ clearLiveRuns: () => set({ liveRunIds: /* @__PURE__ */ new Set() })
340
+ }));
341
+ var STATUS_OPTIONS = [
342
+ { value: "all", label: "All Statuses" },
343
+ { value: "RUNNING", label: "Running" },
344
+ { value: "COMPLETED", label: "Completed" },
345
+ { value: "FAILED", label: "Failed" },
346
+ { value: "PENDING", label: "Pending" },
347
+ { value: "CANCELLED", label: "Cancelled" },
348
+ { value: "WAITING", label: "Waiting" },
349
+ { value: "TERMINATED", label: "Terminated" }
350
+ ];
351
+ var DATE_PRESETS = [
352
+ { value: "all", label: "All Time" },
353
+ { value: "today", label: "Today" },
354
+ { value: "yesterday", label: "Yesterday" },
355
+ { value: "7days", label: "Last 7 Days" },
356
+ { value: "30days", label: "Last 30 Days" },
357
+ { value: "90days", label: "Last 90 Days" },
358
+ { value: "custom", label: "Custom Range" }
359
+ ];
360
+ function ExecutionFilters({
361
+ workflows = [],
362
+ onRefresh
363
+ }) {
364
+ const {
365
+ filter,
366
+ setStatusFilter,
367
+ setWorkflowFilter,
368
+ setDateRange,
369
+ setSearchQuery,
370
+ resetFilters,
371
+ autoRefresh,
372
+ setAutoRefresh
373
+ } = useExecutionsStore();
374
+ const [showCustomDate, setShowCustomDate] = useState(false);
375
+ const handleDatePresetChange = useCallback(
376
+ (preset) => {
377
+ const now = /* @__PURE__ */ new Date();
378
+ let start = null;
379
+ let end = null;
380
+ switch (preset) {
381
+ case "today":
382
+ start = new Date(now.getFullYear(), now.getMonth(), now.getDate());
383
+ end = now;
384
+ break;
385
+ case "yesterday":
386
+ start = new Date(
387
+ now.getFullYear(),
388
+ now.getMonth(),
389
+ now.getDate() - 1
390
+ );
391
+ end = new Date(now.getFullYear(), now.getMonth(), now.getDate());
392
+ break;
393
+ case "7days":
394
+ start = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1e3);
395
+ end = now;
396
+ break;
397
+ case "30days":
398
+ start = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1e3);
399
+ end = now;
400
+ break;
401
+ case "90days":
402
+ start = new Date(now.getTime() - 90 * 24 * 60 * 60 * 1e3);
403
+ end = now;
404
+ break;
405
+ case "custom":
406
+ setShowCustomDate(true);
407
+ return;
408
+ default:
409
+ start = null;
410
+ end = null;
411
+ }
412
+ setShowCustomDate(false);
413
+ setDateRange({ start, end, preset });
414
+ },
415
+ [setDateRange]
416
+ );
417
+ const activeFiltersCount = [
418
+ filter.status !== "all",
419
+ filter.workflowKey !== "",
420
+ filter.dateRange.preset !== "all",
421
+ filter.search !== ""
422
+ ].filter(Boolean).length;
423
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
424
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row gap-3", children: [
425
+ /* @__PURE__ */ jsxs("div", { className: "relative flex-1", children: [
426
+ /* @__PURE__ */ jsx(
427
+ Icon,
428
+ {
429
+ icon: "mdi:magnify",
430
+ className: "absolute left-3 top-1/2 -translate-y-1/2 text-text-secondary",
431
+ width: 18
432
+ }
433
+ ),
434
+ /* @__PURE__ */ jsx(
435
+ "input",
436
+ {
437
+ type: "text",
438
+ placeholder: "Search by workflow name or run ID...",
439
+ value: filter.search,
440
+ onChange: (e) => setSearchQuery(e.target.value),
441
+ className: "w-full pl-[3.25rem] pr-4 py-2 bg-background-secondary border border-border-secondary rounded-lg text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-action-primary-bg focus:border-transparent"
442
+ }
443
+ ),
444
+ filter.search && /* @__PURE__ */ jsx(
445
+ "button",
446
+ {
447
+ onClick: () => setSearchQuery(""),
448
+ className: "absolute right-3 top-1/2 -translate-y-1/2 text-text-secondary hover:text-text-primary",
449
+ children: /* @__PURE__ */ jsx(Icon, { icon: "mdi:close", width: 18 })
450
+ }
451
+ )
452
+ ] }),
453
+ /* @__PURE__ */ jsx(
454
+ "select",
455
+ {
456
+ value: filter.status,
457
+ onChange: (e) => setStatusFilter(e.target.value),
458
+ className: "px-3 py-2 bg-background-secondary border border-border-secondary rounded-lg text-text-primary focus:outline-none focus:ring-2 focus:ring-action-primary-bg",
459
+ children: STATUS_OPTIONS.map((option) => /* @__PURE__ */ jsx("option", { value: option.value, children: option.label }, option.value))
460
+ }
461
+ ),
462
+ workflows.length > 0 && /* @__PURE__ */ jsxs(
463
+ "select",
464
+ {
465
+ value: filter.workflowKey,
466
+ onChange: (e) => setWorkflowFilter(e.target.value),
467
+ className: "px-3 py-2 bg-background-secondary border border-border-secondary rounded-lg text-text-primary focus:outline-none focus:ring-2 focus:ring-action-primary-bg max-w-[200px]",
468
+ children: [
469
+ /* @__PURE__ */ jsx("option", { value: "", children: "All Workflows" }),
470
+ workflows.map((wf) => /* @__PURE__ */ jsx("option", { value: wf.workflowKey, children: wf.name }, wf.workflowKey))
471
+ ]
472
+ }
473
+ ),
474
+ /* @__PURE__ */ jsx(
475
+ "select",
476
+ {
477
+ value: filter.dateRange.preset,
478
+ onChange: (e) => handleDatePresetChange(e.target.value),
479
+ className: "px-3 py-2 bg-background-secondary border border-border-secondary rounded-lg text-text-primary focus:outline-none focus:ring-2 focus:ring-action-primary-bg",
480
+ children: DATE_PRESETS.map((option) => /* @__PURE__ */ jsx("option", { value: option.value, children: option.label }, option.value))
481
+ }
482
+ )
483
+ ] }),
484
+ showCustomDate && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-3 items-center p-3 bg-background-secondary rounded-lg border border-border-secondary", children: [
485
+ /* @__PURE__ */ jsx("label", { className: "text-sm text-text-secondary", children: "From:" }),
486
+ /* @__PURE__ */ jsx(
487
+ "input",
488
+ {
489
+ type: "datetime-local",
490
+ value: filter.dateRange.start?.toISOString().slice(0, 16) ?? "",
491
+ onChange: (e) => setDateRange({
492
+ ...filter.dateRange,
493
+ start: e.target.value ? new Date(e.target.value) : null,
494
+ preset: "custom"
495
+ }),
496
+ className: "px-3 py-1.5 bg-background-primary border border-border-secondary rounded text-text-primary text-sm"
497
+ }
498
+ ),
499
+ /* @__PURE__ */ jsx("label", { className: "text-sm text-text-secondary", children: "To:" }),
500
+ /* @__PURE__ */ jsx(
501
+ "input",
502
+ {
503
+ type: "datetime-local",
504
+ value: filter.dateRange.end?.toISOString().slice(0, 16) ?? "",
505
+ onChange: (e) => setDateRange({
506
+ ...filter.dateRange,
507
+ end: e.target.value ? new Date(e.target.value) : null,
508
+ preset: "custom"
509
+ }),
510
+ className: "px-3 py-1.5 bg-background-primary border border-border-secondary rounded text-text-primary text-sm"
511
+ }
512
+ ),
513
+ /* @__PURE__ */ jsx(
514
+ "button",
515
+ {
516
+ onClick: () => setShowCustomDate(false),
517
+ className: "text-text-secondary hover:text-text-primary",
518
+ children: /* @__PURE__ */ jsx(Icon, { icon: "mdi:close", width: 18 })
519
+ }
520
+ )
521
+ ] }),
522
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [
523
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
524
+ /* @__PURE__ */ jsxs("label", { className: "inline-flex items-center gap-2 cursor-pointer", children: [
525
+ /* @__PURE__ */ jsx(
526
+ "input",
527
+ {
528
+ type: "checkbox",
529
+ checked: autoRefresh,
530
+ onChange: (e) => setAutoRefresh(e.target.checked),
531
+ className: "w-4 h-4 rounded border-border-secondary text-action-primary-bg focus:ring-action-primary-bg"
532
+ }
533
+ ),
534
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-text-secondary", children: "Auto-refresh" })
535
+ ] }),
536
+ onRefresh && /* @__PURE__ */ jsxs(
537
+ Button,
538
+ {
539
+ variant: "outline",
540
+ size: "sm",
541
+ onClick: onRefresh,
542
+ className: "gap-1.5",
543
+ children: [
544
+ /* @__PURE__ */ jsx(Icon, { icon: "mdi:refresh", width: 16 }),
545
+ "Refresh"
546
+ ]
547
+ }
548
+ )
549
+ ] }),
550
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
551
+ activeFiltersCount > 0 && /* @__PURE__ */ jsxs("span", { className: "text-sm text-text-secondary", children: [
552
+ activeFiltersCount,
553
+ " filter",
554
+ activeFiltersCount > 1 ? "s" : "",
555
+ " ",
556
+ "active"
557
+ ] }),
558
+ activeFiltersCount > 0 && /* @__PURE__ */ jsxs(
559
+ Button,
560
+ {
561
+ variant: "ghost",
562
+ size: "sm",
563
+ onClick: resetFilters,
564
+ className: "gap-1.5",
565
+ children: [
566
+ /* @__PURE__ */ jsx(Icon, { icon: "mdi:filter-remove", width: 16 }),
567
+ "Clear Filters"
568
+ ]
569
+ }
570
+ )
571
+ ] })
572
+ ] })
573
+ ] });
574
+ }
575
+ function StatCard({
576
+ label,
577
+ value,
578
+ icon,
579
+ color,
580
+ trend,
581
+ onClick
582
+ }) {
583
+ return /* @__PURE__ */ jsxs(
584
+ "button",
585
+ {
586
+ onClick,
587
+ disabled: !onClick,
588
+ className: `
589
+ flex flex-col p-4 bg-background-secondary rounded-lg border border-border-secondary
590
+ hover:border-border-primary transition-colors
591
+ ${onClick ? "cursor-pointer" : "cursor-default"}
592
+ text-left w-full
593
+ `,
594
+ children: [
595
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-2", children: [
596
+ /* @__PURE__ */ jsx(Icon, { icon, className: color, width: 24 }),
597
+ trend && /* @__PURE__ */ jsxs(
598
+ "span",
599
+ {
600
+ className: `text-xs font-medium ${trend.isPositive ? "text-[var(--color-status-success-text)]" : "text-[var(--color-status-error-text)]"}`,
601
+ children: [
602
+ trend.isPositive ? "+" : "-",
603
+ Math.abs(trend.value),
604
+ "%"
605
+ ]
606
+ }
607
+ )
608
+ ] }),
609
+ /* @__PURE__ */ jsx("div", { className: "text-2xl font-bold text-text-primary", children: value }),
610
+ /* @__PURE__ */ jsx("div", { className: "text-sm text-text-secondary mt-1", children: label })
611
+ ]
612
+ }
613
+ );
614
+ }
615
+ function ExecutionStats({
616
+ stats,
617
+ loading,
618
+ onFilterByStatus
619
+ }) {
620
+ if (loading) {
621
+ return /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 sm:grid-cols-4 lg:grid-cols-6 gap-4", children: [...Array(6)].map((_, i) => /* @__PURE__ */ jsx(
622
+ "div",
623
+ {
624
+ className: "h-24 bg-background-secondary rounded-lg border border-border-secondary animate-pulse"
625
+ },
626
+ i
627
+ )) });
628
+ }
629
+ if (!stats) {
630
+ return null;
631
+ }
632
+ const formatDuration3 = (seconds) => {
633
+ if (seconds < 60) return `${Math.round(seconds)}s`;
634
+ if (seconds < 3600) return `${Math.round(seconds / 60)}m`;
635
+ return `${Math.round(seconds / 3600)}h`;
636
+ };
637
+ return /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-6 gap-4", children: [
638
+ /* @__PURE__ */ jsx(
639
+ StatCard,
640
+ {
641
+ label: "Total Runs",
642
+ value: stats.total.toLocaleString(),
643
+ icon: "mdi:play-box-multiple",
644
+ color: "text-text-primary",
645
+ onClick: () => onFilterByStatus?.("all")
646
+ }
647
+ ),
648
+ /* @__PURE__ */ jsx(
649
+ StatCard,
650
+ {
651
+ label: "Running",
652
+ value: stats.running,
653
+ icon: "mdi:play-circle",
654
+ color: "text-[var(--color-status-info-text)]",
655
+ onClick: () => onFilterByStatus?.("RUNNING")
656
+ }
657
+ ),
658
+ /* @__PURE__ */ jsx(
659
+ StatCard,
660
+ {
661
+ label: "Completed",
662
+ value: stats.completed.toLocaleString(),
663
+ icon: "mdi:check-circle",
664
+ color: "text-[var(--color-status-success-text)]",
665
+ onClick: () => onFilterByStatus?.("COMPLETED")
666
+ }
667
+ ),
668
+ /* @__PURE__ */ jsx(
669
+ StatCard,
670
+ {
671
+ label: "Failed",
672
+ value: stats.failed,
673
+ icon: "mdi:alert-circle",
674
+ color: "text-[var(--color-status-error-text)]",
675
+ onClick: () => onFilterByStatus?.("FAILED")
676
+ }
677
+ ),
678
+ /* @__PURE__ */ jsx(
679
+ StatCard,
680
+ {
681
+ label: "Success Rate",
682
+ value: `${(stats.successRate ?? 0).toFixed(1)}%`,
683
+ icon: "mdi:percent",
684
+ color: "text-accent"
685
+ }
686
+ ),
687
+ /* @__PURE__ */ jsx(
688
+ StatCard,
689
+ {
690
+ label: "Avg Duration",
691
+ value: formatDuration3(stats.avgDuration ?? 0),
692
+ icon: "mdi:timer",
693
+ color: "text-[var(--color-status-warning-text)]"
694
+ }
695
+ )
696
+ ] });
697
+ }
698
+ function ExecutionTable({
699
+ executions,
700
+ loading,
701
+ onRowClick,
702
+ onAction
703
+ }) {
704
+ const navigate = useNavigate();
705
+ const {
706
+ selection,
707
+ toggleSelectRun,
708
+ selectAll,
709
+ expandedRows,
710
+ toggleRowExpanded
711
+ } = useExecutionsStore();
712
+ const allRunIds = useMemo(() => executions.map((e) => e.id), [executions]);
713
+ const formatDuration3 = (ms) => {
714
+ if (!ms) return "-";
715
+ if (ms < 1e3) return `${ms}ms`;
716
+ if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`;
717
+ if (ms < 36e5)
718
+ return `${Math.round(ms / 6e4)}m ${Math.round(ms % 6e4 / 1e3)}s`;
719
+ return `${Math.round(ms / 36e5)}h ${Math.round(ms % 36e5 / 6e4)}m`;
720
+ };
721
+ const formatDate2 = (dateStr) => {
722
+ if (!dateStr) return "-";
723
+ const date = new Date(dateStr);
724
+ const now = /* @__PURE__ */ new Date();
725
+ const diff = now.getTime() - date.getTime();
726
+ if (diff < 6e4) return "Just now";
727
+ if (diff < 36e5) return `${Math.round(diff / 6e4)}m ago`;
728
+ if (diff < 864e5) return `${Math.round(diff / 36e5)}h ago`;
729
+ if (diff < 6048e5) return `${Math.round(diff / 864e5)}d ago`;
730
+ return date.toLocaleDateString("en-US", {
731
+ month: "short",
732
+ day: "numeric",
733
+ hour: "2-digit",
734
+ minute: "2-digit"
735
+ });
736
+ };
737
+ const getRowActions = (execution) => {
738
+ const actions = [];
739
+ switch (execution.status) {
740
+ case "RUNNING":
741
+ actions.push({ icon: "mdi:pause", label: "Pause", action: "pause" });
742
+ actions.push({ icon: "mdi:stop", label: "Cancel", action: "cancel" });
743
+ break;
744
+ case "WAITING":
745
+ actions.push({ icon: "mdi:play", label: "Resume", action: "resume" });
746
+ actions.push({ icon: "mdi:stop", label: "Cancel", action: "cancel" });
747
+ break;
748
+ case "FAILED":
749
+ actions.push({ icon: "mdi:refresh", label: "Retry", action: "retry" });
750
+ break;
751
+ case "PENDING":
752
+ actions.push({ icon: "mdi:stop", label: "Cancel", action: "cancel" });
753
+ break;
754
+ }
755
+ return actions;
756
+ };
757
+ if (loading && executions.length === 0) {
758
+ return /* @__PURE__ */ jsx("div", { className: "bg-background-secondary rounded-lg border border-border-secondary overflow-hidden", children: /* @__PURE__ */ jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs("table", { className: "w-full min-w-[800px]", children: [
759
+ /* @__PURE__ */ jsx("thead", { className: "bg-background-tertiary border-b border-border-secondary", children: /* @__PURE__ */ jsxs("tr", { children: [
760
+ /* @__PURE__ */ jsx("th", { className: "w-10 px-4 py-3" }),
761
+ /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-medium text-text-secondary uppercase", children: "Status" }),
762
+ /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-medium text-text-secondary uppercase", children: "Workflow" }),
763
+ /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-medium text-text-secondary uppercase", children: "Run ID" }),
764
+ /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-medium text-text-secondary uppercase", children: "Started" }),
765
+ /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-medium text-text-secondary uppercase", children: "Duration" }),
766
+ /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-medium text-text-secondary uppercase", children: "Progress" }),
767
+ /* @__PURE__ */ jsx("th", { className: "px-4 py-3" })
768
+ ] }) }),
769
+ /* @__PURE__ */ jsx("tbody", { children: [...Array(5)].map((_, i) => /* @__PURE__ */ jsx("tr", { className: "border-b border-border-secondary", children: /* @__PURE__ */ jsx("td", { colSpan: 8, className: "px-4 py-4", children: /* @__PURE__ */ jsx("div", { className: "h-8 bg-background-tertiary rounded animate-pulse" }) }) }, i)) })
770
+ ] }) }) });
771
+ }
772
+ if (executions.length === 0) {
773
+ return /* @__PURE__ */ jsxs("div", { className: "bg-background-secondary rounded-lg border border-border-secondary p-12 text-center", children: [
774
+ /* @__PURE__ */ jsx(
775
+ Icon,
776
+ {
777
+ icon: "mdi:play-box-outline",
778
+ className: "mx-auto text-text-secondary mb-4",
779
+ width: 48
780
+ }
781
+ ),
782
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-medium text-text-primary mb-2", children: "No executions found" }),
783
+ /* @__PURE__ */ jsx("p", { className: "text-text-secondary mb-4", children: "There are no workflow executions matching your filters." }),
784
+ /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: () => navigate("../list"), children: "View Workflows" })
785
+ ] });
786
+ }
787
+ return /* @__PURE__ */ jsxs("div", { className: "bg-background-secondary rounded-lg border border-border-secondary overflow-hidden", children: [
788
+ /* @__PURE__ */ jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs("table", { className: "w-full min-w-[800px]", children: [
789
+ /* @__PURE__ */ jsx("thead", { className: "bg-background-tertiary border-b border-border-secondary", children: /* @__PURE__ */ jsxs("tr", { children: [
790
+ /* @__PURE__ */ jsx("th", { className: "w-10 px-4 py-3", children: /* @__PURE__ */ jsx(
791
+ "input",
792
+ {
793
+ type: "checkbox",
794
+ checked: selection.allSelected,
795
+ onChange: () => selectAll(allRunIds),
796
+ className: "w-4 h-4 rounded border-border-secondary"
797
+ }
798
+ ) }),
799
+ /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-medium text-text-secondary uppercase tracking-wider", children: "Status" }),
800
+ /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-medium text-text-secondary uppercase tracking-wider", children: "Workflow" }),
801
+ /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-medium text-text-secondary uppercase tracking-wider", children: "Run ID" }),
802
+ /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-medium text-text-secondary uppercase tracking-wider", children: "Started" }),
803
+ /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-medium text-text-secondary uppercase tracking-wider", children: "Duration" }),
804
+ /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-medium text-text-secondary uppercase tracking-wider", children: "Progress" }),
805
+ /* @__PURE__ */ jsx("th", { className: "px-4 py-3 w-32" })
806
+ ] }) }),
807
+ /* @__PURE__ */ jsx("tbody", { className: "divide-y divide-border-secondary", children: executions.map((execution) => {
808
+ const isSelected = selection.runIds.includes(execution.id);
809
+ const isExpanded = expandedRows.has(execution.id);
810
+ const actions = getRowActions(execution);
811
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
812
+ /* @__PURE__ */ jsxs(
813
+ "tr",
814
+ {
815
+ className: `
816
+ hover:bg-background-tertiary/50 cursor-pointer transition-colors
817
+ ${isSelected ? "bg-action-primary-bg/10" : ""}
818
+ `,
819
+ onClick: () => onRowClick?.(execution),
820
+ children: [
821
+ /* @__PURE__ */ jsx(
822
+ "td",
823
+ {
824
+ className: "px-4 py-3",
825
+ onClick: (e) => e.stopPropagation(),
826
+ children: /* @__PURE__ */ jsx(
827
+ "input",
828
+ {
829
+ type: "checkbox",
830
+ checked: isSelected,
831
+ onChange: () => toggleSelectRun(execution.id),
832
+ className: "w-4 h-4 rounded border-border-secondary"
833
+ }
834
+ )
835
+ }
836
+ ),
837
+ /* @__PURE__ */ jsx("td", { className: "px-4 py-3", children: /* @__PURE__ */ jsx(
838
+ ExecutionStatusBadge,
839
+ {
840
+ status: execution.status,
841
+ size: "sm"
842
+ }
843
+ ) }),
844
+ /* @__PURE__ */ jsx("td", { className: "px-4 py-3", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
845
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-text-primary", children: execution.workflow?.name || execution.workflowKey }),
846
+ /* @__PURE__ */ jsxs("span", { className: "text-xs text-text-secondary", children: [
847
+ "v",
848
+ execution.version
849
+ ] })
850
+ ] }) }),
851
+ /* @__PURE__ */ jsx("td", { className: "px-4 py-3", children: /* @__PURE__ */ jsxs("span", { className: "text-sm font-mono text-text-secondary", children: [
852
+ execution.id.slice(0, 8),
853
+ "..."
854
+ ] }) }),
855
+ /* @__PURE__ */ jsx("td", { className: "px-4 py-3", children: /* @__PURE__ */ jsx("span", { className: "text-sm text-text-secondary", children: formatDate2(execution.startedAt || execution.createdAt) }) }),
856
+ /* @__PURE__ */ jsx("td", { className: "px-4 py-3", children: /* @__PURE__ */ jsx("span", { className: "text-sm text-text-secondary", children: formatDuration3(execution.duration) }) }),
857
+ /* @__PURE__ */ jsx("td", { className: "px-4 py-3", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
858
+ /* @__PURE__ */ jsx("div", { className: "flex-1 h-2 bg-background-tertiary rounded-full overflow-hidden max-w-[100px]", children: /* @__PURE__ */ jsx(
859
+ "div",
860
+ {
861
+ className: `h-full transition-all ${execution.status === "FAILED" ? "bg-[var(--color-status-error-bg)]" : execution.status === "COMPLETED" ? "bg-[var(--color-status-success-bg)]" : "bg-[var(--color-status-info-bg)]"}`,
862
+ style: { width: `${execution.progress}%` }
863
+ }
864
+ ) }),
865
+ /* @__PURE__ */ jsxs("span", { className: "text-xs text-text-secondary min-w-[45px]", children: [
866
+ execution.completedNodes ?? 0,
867
+ "/",
868
+ execution.totalNodes ?? 0
869
+ ] })
870
+ ] }) }),
871
+ /* @__PURE__ */ jsx(
872
+ "td",
873
+ {
874
+ className: "px-4 py-3",
875
+ onClick: (e) => e.stopPropagation(),
876
+ children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
877
+ /* @__PURE__ */ jsx(
878
+ "button",
879
+ {
880
+ onClick: () => toggleRowExpanded(execution.id),
881
+ className: "p-1.5 rounded hover:bg-background-tertiary text-text-secondary",
882
+ children: /* @__PURE__ */ jsx(
883
+ Icon,
884
+ {
885
+ icon: isExpanded ? "mdi:chevron-up" : "mdi:chevron-down",
886
+ width: 18
887
+ }
888
+ )
889
+ }
890
+ ),
891
+ actions.slice(0, 2).map((action) => /* @__PURE__ */ jsx(
892
+ "button",
893
+ {
894
+ onClick: () => onAction?.(action.action, execution),
895
+ className: "p-1.5 rounded hover:bg-background-tertiary text-text-secondary",
896
+ title: action.label,
897
+ children: /* @__PURE__ */ jsx(Icon, { icon: action.icon, width: 18 })
898
+ },
899
+ action.action
900
+ )),
901
+ /* @__PURE__ */ jsx(
902
+ "button",
903
+ {
904
+ onClick: () => navigate(`../runs/${execution.id}`),
905
+ className: "p-1.5 rounded hover:bg-background-tertiary text-text-secondary",
906
+ title: "View Details",
907
+ children: /* @__PURE__ */ jsx(Icon, { icon: "mdi:arrow-right", width: 18 })
908
+ }
909
+ )
910
+ ] })
911
+ }
912
+ )
913
+ ]
914
+ },
915
+ execution.id
916
+ ),
917
+ isExpanded && /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx(
918
+ "td",
919
+ {
920
+ colSpan: 8,
921
+ className: "px-4 py-4 bg-background-tertiary/30",
922
+ children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 lg:grid-cols-4 gap-4", children: [
923
+ /* @__PURE__ */ jsxs("div", { children: [
924
+ /* @__PURE__ */ jsx("div", { className: "text-xs text-text-secondary mb-1", children: "Trigger Node" }),
925
+ /* @__PURE__ */ jsx("div", { className: "text-sm text-text-primary font-medium", children: execution.triggerNodeId })
926
+ ] }),
927
+ /* @__PURE__ */ jsxs("div", { children: [
928
+ /* @__PURE__ */ jsx("div", { className: "text-xs text-text-secondary mb-1", children: "Node Stats" }),
929
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-2 text-sm", children: [
930
+ /* @__PURE__ */ jsxs("span", { className: "text-[var(--color-status-success-text)]", children: [
931
+ execution.completedNodes ?? 0,
932
+ " completed"
933
+ ] }),
934
+ (execution.failedNodes ?? 0) > 0 && /* @__PURE__ */ jsxs("span", { className: "text-[var(--color-status-error-text)]", children: [
935
+ execution.failedNodes,
936
+ " failed"
937
+ ] }),
938
+ (execution.skippedNodes ?? 0) > 0 && /* @__PURE__ */ jsxs("span", { className: "text-tertiary", children: [
939
+ execution.skippedNodes,
940
+ " skipped"
941
+ ] })
942
+ ] })
943
+ ] }),
944
+ execution.errorMessage && /* @__PURE__ */ jsxs("div", { className: "col-span-2", children: [
945
+ /* @__PURE__ */ jsx("div", { className: "text-xs text-text-secondary mb-1", children: "Error" }),
946
+ /* @__PURE__ */ jsx("div", { className: "text-sm text-[var(--color-status-error-text)] bg-[var(--color-status-error-bg-subtle)] p-2 rounded", children: execution.errorMessage })
947
+ ] }),
948
+ /* @__PURE__ */ jsxs("div", { children: [
949
+ /* @__PURE__ */ jsx("div", { className: "text-xs text-text-secondary mb-1", children: "Full Run ID" }),
950
+ /* @__PURE__ */ jsx("div", { className: "text-sm font-mono text-text-secondary break-all", children: execution.id })
951
+ ] })
952
+ ] })
953
+ }
954
+ ) }, `${execution.id}-expanded`)
955
+ ] });
956
+ }) })
957
+ ] }) }),
958
+ /* @__PURE__ */ jsx("div", { className: "sm:hidden px-4 py-2 bg-background-tertiary border-t border-border-secondary text-xs text-text-secondary text-center", children: "Swipe to see more columns" })
959
+ ] });
960
+ }
961
+ function formatDuration(ms) {
962
+ if (!ms) return "--";
963
+ if (ms < 1e3) return `${ms}ms`;
964
+ if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`;
965
+ const mins = Math.floor(ms / 6e4);
966
+ const secs = Math.floor(ms % 6e4 / 1e3);
967
+ return `${mins}m ${secs}s`;
968
+ }
969
+ function formatRelativeTime(dateStr) {
970
+ if (!dateStr) return "--";
971
+ const date = new Date(dateStr);
972
+ const now = /* @__PURE__ */ new Date();
973
+ const diffMs = now.getTime() - date.getTime();
974
+ const diffMins = Math.floor(diffMs / 6e4);
975
+ if (diffMins < 1) return "just now";
976
+ if (diffMins < 60) return `${diffMins}m ago`;
977
+ const diffHours = Math.floor(diffMins / 60);
978
+ if (diffHours < 24) return `${diffHours}h ago`;
979
+ const diffDays = Math.floor(diffHours / 24);
980
+ return `${diffDays}d ago`;
981
+ }
982
+ function getProgressColor(status) {
983
+ switch (status) {
984
+ case "COMPLETED":
985
+ return "bg-green-500";
986
+ case "FAILED":
987
+ case "TERMINATED":
988
+ return "bg-red-500";
989
+ case "RUNNING":
990
+ return "bg-blue-500";
991
+ case "CANCELLED":
992
+ return "bg-orange-500";
993
+ default:
994
+ return "bg-gray-400";
995
+ }
996
+ }
997
+ function ExecutionCards({
998
+ executions,
999
+ loading,
1000
+ onCardClick,
1001
+ onAction
1002
+ }) {
1003
+ if (loading) {
1004
+ return /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsxs(
1005
+ "div",
1006
+ {
1007
+ className: "rounded-lg border border-border-secondary bg-background-secondary p-4 animate-pulse",
1008
+ children: [
1009
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between mb-3", children: [
1010
+ /* @__PURE__ */ jsx("div", { className: "h-4 bg-background-tertiary rounded w-32" }),
1011
+ /* @__PURE__ */ jsx("div", { className: "h-5 bg-background-tertiary rounded-full w-20" })
1012
+ ] }),
1013
+ /* @__PURE__ */ jsx("div", { className: "h-3 bg-background-tertiary rounded w-48 mb-2" }),
1014
+ /* @__PURE__ */ jsx("div", { className: "h-2 bg-background-tertiary rounded w-full mb-3" }),
1015
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
1016
+ /* @__PURE__ */ jsx("div", { className: "h-3 bg-background-tertiary rounded w-16" }),
1017
+ /* @__PURE__ */ jsx("div", { className: "h-3 bg-background-tertiary rounded w-24" })
1018
+ ] })
1019
+ ]
1020
+ },
1021
+ i
1022
+ )) });
1023
+ }
1024
+ if (executions.length === 0) {
1025
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center py-16 text-text-secondary", children: [
1026
+ /* @__PURE__ */ jsx(
1027
+ Icon,
1028
+ {
1029
+ icon: "mdi:play-circle-outline",
1030
+ width: 48,
1031
+ className: "mb-3 opacity-40"
1032
+ }
1033
+ ),
1034
+ /* @__PURE__ */ jsx("p", { className: "text-lg font-medium", children: "No executions found" }),
1035
+ /* @__PURE__ */ jsx("p", { className: "text-sm mt-1", children: "Run a workflow to see results here" })
1036
+ ] });
1037
+ }
1038
+ return /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4", children: executions.map((execution) => {
1039
+ const config = RUN_STATUS_CONFIG[execution.status];
1040
+ const canCancel = execution.status === "RUNNING" || execution.status === "PENDING";
1041
+ const canPause = execution.status === "RUNNING";
1042
+ return /* @__PURE__ */ jsxs(
1043
+ "div",
1044
+ {
1045
+ onClick: () => onCardClick(execution),
1046
+ className: `
1047
+ rounded-lg border bg-background-secondary p-4 cursor-pointer
1048
+ transition-all duration-200 hover:shadow-md hover:border-border-primary
1049
+ ${config.borderColor}
1050
+ `,
1051
+ children: [
1052
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between mb-3", children: [
1053
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1 mr-2", children: [
1054
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-text-primary truncate", children: execution.workflowKey }),
1055
+ /* @__PURE__ */ jsxs("p", { className: "text-xs text-text-tertiary mt-0.5", children: [
1056
+ "v",
1057
+ execution.version
1058
+ ] })
1059
+ ] }),
1060
+ /* @__PURE__ */ jsx(ExecutionStatusBadge, { status: execution.status, size: "sm" })
1061
+ ] }),
1062
+ /* @__PURE__ */ jsxs("div", { className: "mb-3", children: [
1063
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between text-xs text-text-tertiary mb-1", children: [
1064
+ /* @__PURE__ */ jsx("span", { children: "Progress" }),
1065
+ /* @__PURE__ */ jsxs("span", { children: [
1066
+ Math.round(execution.progress),
1067
+ "%"
1068
+ ] })
1069
+ ] }),
1070
+ /* @__PURE__ */ jsx("div", { className: "h-1.5 bg-background-tertiary rounded-full overflow-hidden", children: /* @__PURE__ */ jsx(
1071
+ "div",
1072
+ {
1073
+ className: `h-full rounded-full transition-all duration-500 ${getProgressColor(execution.status)}`,
1074
+ style: { width: `${Math.min(execution.progress, 100)}%` }
1075
+ }
1076
+ ) })
1077
+ ] }),
1078
+ (execution.totalNodes ?? 0) > 0 && /* @__PURE__ */ jsxs("div", { className: "flex gap-3 text-xs text-text-secondary mb-3", children: [
1079
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1", children: [
1080
+ /* @__PURE__ */ jsx(
1081
+ Icon,
1082
+ {
1083
+ icon: "mdi:check-circle",
1084
+ width: 12,
1085
+ className: "text-green-500"
1086
+ }
1087
+ ),
1088
+ execution.completedNodes ?? 0
1089
+ ] }),
1090
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1", children: [
1091
+ /* @__PURE__ */ jsx(
1092
+ Icon,
1093
+ {
1094
+ icon: "mdi:alert-circle",
1095
+ width: 12,
1096
+ className: "text-red-500"
1097
+ }
1098
+ ),
1099
+ execution.failedNodes ?? 0
1100
+ ] }),
1101
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1", children: [
1102
+ /* @__PURE__ */ jsx(
1103
+ Icon,
1104
+ {
1105
+ icon: "mdi:skip-next",
1106
+ width: 12,
1107
+ className: "text-gray-400"
1108
+ }
1109
+ ),
1110
+ execution.skippedNodes ?? 0
1111
+ ] }),
1112
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1 ml-auto", children: [
1113
+ /* @__PURE__ */ jsx(Icon, { icon: "mdi:sigma", width: 12 }),
1114
+ execution.totalNodes
1115
+ ] })
1116
+ ] }),
1117
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-xs text-text-tertiary pt-2 border-t border-border-secondary", children: [
1118
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1", children: [
1119
+ /* @__PURE__ */ jsx(Icon, { icon: "mdi:timer-outline", width: 12 }),
1120
+ formatDuration(execution.duration ?? void 0)
1121
+ ] }),
1122
+ /* @__PURE__ */ jsx("span", { children: formatRelativeTime(execution.startedAt ?? execution.createdAt) })
1123
+ ] }),
1124
+ (canCancel || canPause) && /* @__PURE__ */ jsxs("div", { className: "flex gap-1 mt-2 pt-2 border-t border-border-secondary", children: [
1125
+ canPause && /* @__PURE__ */ jsxs(
1126
+ "button",
1127
+ {
1128
+ type: "button",
1129
+ onClick: (e) => {
1130
+ e.stopPropagation();
1131
+ onAction("pause", execution);
1132
+ },
1133
+ className: "flex items-center gap-1 text-xs px-2 py-1 rounded bg-background-tertiary hover:bg-yellow-50 dark:hover:bg-yellow-900/20 text-text-secondary hover:text-yellow-600 transition-colors",
1134
+ children: [
1135
+ /* @__PURE__ */ jsx(Icon, { icon: "mdi:pause", width: 12 }),
1136
+ " Pause"
1137
+ ]
1138
+ }
1139
+ ),
1140
+ canCancel && /* @__PURE__ */ jsxs(
1141
+ "button",
1142
+ {
1143
+ type: "button",
1144
+ onClick: (e) => {
1145
+ e.stopPropagation();
1146
+ onAction("cancel", execution);
1147
+ },
1148
+ className: "flex items-center gap-1 text-xs px-2 py-1 rounded bg-background-tertiary hover:bg-red-50 dark:hover:bg-red-900/20 text-text-secondary hover:text-red-600 transition-colors",
1149
+ children: [
1150
+ /* @__PURE__ */ jsx(Icon, { icon: "mdi:stop", width: 12 }),
1151
+ " Cancel"
1152
+ ]
1153
+ }
1154
+ )
1155
+ ] })
1156
+ ]
1157
+ },
1158
+ execution.id
1159
+ );
1160
+ }) });
1161
+ }
1162
+ function formatTime(dateStr) {
1163
+ if (!dateStr) return "--";
1164
+ return new Date(dateStr).toLocaleTimeString(void 0, {
1165
+ hour: "2-digit",
1166
+ minute: "2-digit",
1167
+ second: "2-digit"
1168
+ });
1169
+ }
1170
+ function formatDate(dateStr) {
1171
+ if (!dateStr) return "";
1172
+ return new Date(dateStr).toLocaleDateString(void 0, {
1173
+ weekday: "short",
1174
+ month: "short",
1175
+ day: "numeric"
1176
+ });
1177
+ }
1178
+ function formatDuration2(ms) {
1179
+ if (!ms) return "--";
1180
+ if (ms < 1e3) return `${ms}ms`;
1181
+ if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`;
1182
+ const mins = Math.floor(ms / 6e4);
1183
+ const secs = Math.floor(ms % 6e4 / 1e3);
1184
+ return `${mins}m ${secs}s`;
1185
+ }
1186
+ function getStatusDotColor(status) {
1187
+ switch (status) {
1188
+ case "COMPLETED":
1189
+ return "bg-green-500";
1190
+ case "FAILED":
1191
+ case "TERMINATED":
1192
+ return "bg-red-500";
1193
+ case "RUNNING":
1194
+ return "bg-blue-500 animate-pulse";
1195
+ case "CANCELLED":
1196
+ return "bg-orange-500";
1197
+ case "WAITING":
1198
+ return "bg-purple-500";
1199
+ case "PENDING":
1200
+ default:
1201
+ return "bg-gray-400";
1202
+ }
1203
+ }
1204
+ function groupByDate(executions) {
1205
+ const groups = /* @__PURE__ */ new Map();
1206
+ for (const exec of executions) {
1207
+ const dateKey = formatDate(exec.startedAt ?? exec.createdAt);
1208
+ if (!groups.has(dateKey)) {
1209
+ groups.set(dateKey, []);
1210
+ }
1211
+ groups.get(dateKey).push(exec);
1212
+ }
1213
+ return groups;
1214
+ }
1215
+ function ExecutionTimeline({
1216
+ executions,
1217
+ loading,
1218
+ onItemClick,
1219
+ onAction
1220
+ }) {
1221
+ if (loading) {
1222
+ return /* @__PURE__ */ jsx("div", { className: "space-y-6 pl-8", children: Array.from({ length: 4 }).map((_, i) => /* @__PURE__ */ jsxs("div", { className: "flex gap-4 animate-pulse", children: [
1223
+ /* @__PURE__ */ jsx("div", { className: "w-3 h-3 rounded-full bg-background-tertiary mt-1.5 shrink-0" }),
1224
+ /* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
1225
+ /* @__PURE__ */ jsx("div", { className: "h-4 bg-background-tertiary rounded w-48 mb-2" }),
1226
+ /* @__PURE__ */ jsx("div", { className: "h-3 bg-background-tertiary rounded w-32 mb-1" }),
1227
+ /* @__PURE__ */ jsx("div", { className: "h-3 bg-background-tertiary rounded w-24" })
1228
+ ] })
1229
+ ] }, i)) });
1230
+ }
1231
+ if (executions.length === 0) {
1232
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center py-16 text-text-secondary", children: [
1233
+ /* @__PURE__ */ jsx(Icon, { icon: "mdi:timeline", width: 48, className: "mb-3 opacity-40" }),
1234
+ /* @__PURE__ */ jsx("p", { className: "text-lg font-medium", children: "No executions found" }),
1235
+ /* @__PURE__ */ jsx("p", { className: "text-sm mt-1", children: "Run a workflow to see the timeline" })
1236
+ ] });
1237
+ }
1238
+ const grouped = groupByDate(executions);
1239
+ return /* @__PURE__ */ jsx("div", { className: "space-y-8", children: Array.from(grouped.entries()).map(([dateLabel, dateExecutions]) => /* @__PURE__ */ jsxs("div", { children: [
1240
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-4", children: [
1241
+ /* @__PURE__ */ jsx(
1242
+ Icon,
1243
+ {
1244
+ icon: "mdi:calendar",
1245
+ width: 14,
1246
+ className: "text-text-tertiary"
1247
+ }
1248
+ ),
1249
+ /* @__PURE__ */ jsx("span", { className: "text-xs font-semibold text-text-tertiary uppercase tracking-wider", children: dateLabel }),
1250
+ /* @__PURE__ */ jsx("div", { className: "flex-1 h-px bg-border-secondary" }),
1251
+ /* @__PURE__ */ jsxs("span", { className: "text-xs text-text-tertiary", children: [
1252
+ dateExecutions.length,
1253
+ " runs"
1254
+ ] })
1255
+ ] }),
1256
+ /* @__PURE__ */ jsxs("div", { className: "relative ml-4", children: [
1257
+ /* @__PURE__ */ jsx("div", { className: "absolute left-[5px] top-0 bottom-0 w-px bg-border-secondary" }),
1258
+ /* @__PURE__ */ jsx("div", { className: "space-y-4", children: dateExecutions.map((execution, idx) => {
1259
+ const isLast = idx === dateExecutions.length - 1;
1260
+ const canCancel = execution.status === "RUNNING" || execution.status === "PENDING";
1261
+ return /* @__PURE__ */ jsxs(
1262
+ "div",
1263
+ {
1264
+ onClick: () => onItemClick(execution),
1265
+ className: "relative flex gap-4 cursor-pointer group",
1266
+ children: [
1267
+ /* @__PURE__ */ jsx("div", { className: "relative z-10 shrink-0 mt-1.5", children: /* @__PURE__ */ jsx(
1268
+ "div",
1269
+ {
1270
+ className: `w-[11px] h-[11px] rounded-full border-2 border-background-primary ${getStatusDotColor(execution.status)}`
1271
+ }
1272
+ ) }),
1273
+ /* @__PURE__ */ jsxs(
1274
+ "div",
1275
+ {
1276
+ className: `
1277
+ flex-1 rounded-lg border border-border-secondary bg-background-secondary p-3
1278
+ transition-all duration-200 group-hover:shadow-sm group-hover:border-border-primary
1279
+ ${isLast ? "" : "mb-0"}
1280
+ `,
1281
+ children: [
1282
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-2", children: [
1283
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
1284
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1285
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-text-primary truncate", children: execution.workflowKey }),
1286
+ /* @__PURE__ */ jsxs("span", { className: "text-xs text-text-tertiary", children: [
1287
+ "v",
1288
+ execution.version
1289
+ ] })
1290
+ ] }),
1291
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 mt-1 text-xs text-text-secondary", children: [
1292
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1", children: [
1293
+ /* @__PURE__ */ jsx(Icon, { icon: "mdi:clock-outline", width: 12 }),
1294
+ formatTime(
1295
+ execution.startedAt ?? execution.createdAt
1296
+ )
1297
+ ] }),
1298
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1", children: [
1299
+ /* @__PURE__ */ jsx(Icon, { icon: "mdi:timer-outline", width: 12 }),
1300
+ formatDuration2(execution.duration ?? void 0)
1301
+ ] }),
1302
+ (execution.totalNodes ?? 0) > 0 && /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1", children: [
1303
+ /* @__PURE__ */ jsx(Icon, { icon: "mdi:puzzle-outline", width: 12 }),
1304
+ execution.completedNodes ?? 0,
1305
+ "/",
1306
+ execution.totalNodes,
1307
+ " nodes"
1308
+ ] })
1309
+ ] }),
1310
+ execution.errorMessage && /* @__PURE__ */ jsx("p", { className: "mt-1.5 text-xs text-red-500 dark:text-red-400 truncate max-w-sm", children: execution.errorMessage })
1311
+ ] }),
1312
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 shrink-0", children: [
1313
+ /* @__PURE__ */ jsx(
1314
+ ExecutionStatusBadge,
1315
+ {
1316
+ status: execution.status,
1317
+ size: "sm"
1318
+ }
1319
+ ),
1320
+ canCancel && /* @__PURE__ */ jsx(
1321
+ "button",
1322
+ {
1323
+ type: "button",
1324
+ onClick: (e) => {
1325
+ e.stopPropagation();
1326
+ onAction("cancel", execution);
1327
+ },
1328
+ className: "opacity-0 group-hover:opacity-100 p-1 rounded hover:bg-red-50 dark:hover:bg-red-900/20 text-text-tertiary hover:text-red-600 transition-all",
1329
+ title: "Cancel execution",
1330
+ children: /* @__PURE__ */ jsx(Icon, { icon: "mdi:stop", width: 14 })
1331
+ }
1332
+ )
1333
+ ] })
1334
+ ] }),
1335
+ execution.status === "RUNNING" && /* @__PURE__ */ jsx("div", { className: "mt-2", children: /* @__PURE__ */ jsx("div", { className: "h-1 bg-background-tertiary rounded-full overflow-hidden", children: /* @__PURE__ */ jsx(
1336
+ "div",
1337
+ {
1338
+ className: "h-full bg-blue-500 rounded-full transition-all duration-500 animate-pulse",
1339
+ style: {
1340
+ width: `${Math.min(execution.progress, 100)}%`
1341
+ }
1342
+ }
1343
+ ) }) })
1344
+ ]
1345
+ }
1346
+ )
1347
+ ]
1348
+ },
1349
+ execution.id
1350
+ );
1351
+ }) })
1352
+ ] })
1353
+ ] }, dateLabel)) });
1354
+ }
1355
+ function NodeTimeline({
1356
+ nodeStates,
1357
+ loading,
1358
+ onRetryNode,
1359
+ onViewChildRun
1360
+ }) {
1361
+ const [expandedNodes, setExpandedNodes] = useState(/* @__PURE__ */ new Set());
1362
+ const [selectedTab, setSelectedTab] = useState("output");
1363
+ const toggleNode = (nodeId) => {
1364
+ setExpandedNodes((prev) => {
1365
+ const newSet = new Set(prev);
1366
+ if (newSet.has(nodeId)) {
1367
+ newSet.delete(nodeId);
1368
+ } else {
1369
+ newSet.add(nodeId);
1370
+ }
1371
+ return newSet;
1372
+ });
1373
+ };
1374
+ const formatDuration3 = (ms) => {
1375
+ if (!ms) return "-";
1376
+ if (ms < 1e3) return `${ms}ms`;
1377
+ return `${(ms / 1e3).toFixed(2)}s`;
1378
+ };
1379
+ const formatTime2 = (dateStr) => {
1380
+ if (!dateStr) return "-";
1381
+ const date = new Date(dateStr);
1382
+ return date.toLocaleTimeString("en-US", {
1383
+ hour: "2-digit",
1384
+ minute: "2-digit",
1385
+ second: "2-digit",
1386
+ hour12: false
1387
+ });
1388
+ };
1389
+ const formatJsonData = (data) => {
1390
+ if (data === null || data === void 0) return "No data";
1391
+ try {
1392
+ return JSON.stringify(data, null, 2);
1393
+ } catch {
1394
+ return "Unable to display data";
1395
+ }
1396
+ };
1397
+ const hasMetadata = (metadata) => {
1398
+ if (!metadata || typeof metadata !== "object") return false;
1399
+ return Object.keys(metadata).length > 0;
1400
+ };
1401
+ const sortedNodes = [...nodeStates].sort((a, b) => {
1402
+ if (!a.startTime && !b.startTime) return 0;
1403
+ if (!a.startTime) return 1;
1404
+ if (!b.startTime) return -1;
1405
+ return new Date(a.startTime).getTime() - new Date(b.startTime).getTime();
1406
+ });
1407
+ if (loading) {
1408
+ return /* @__PURE__ */ jsx("div", { className: "space-y-4", children: [...Array(4)].map((_, i) => /* @__PURE__ */ jsxs("div", { className: "flex gap-4 animate-pulse", children: [
1409
+ /* @__PURE__ */ jsx("div", { className: "w-8 h-8 bg-background-tertiary rounded-full" }),
1410
+ /* @__PURE__ */ jsx("div", { className: "flex-1 h-20 bg-background-tertiary rounded-lg" })
1411
+ ] }, i)) });
1412
+ }
1413
+ if (nodeStates.length === 0) {
1414
+ return /* @__PURE__ */ jsxs("div", { className: "text-center py-8 text-text-secondary", children: [
1415
+ /* @__PURE__ */ jsx(Icon, { icon: "mdi:timeline-outline", className: "mx-auto mb-2", width: 32 }),
1416
+ /* @__PURE__ */ jsx("p", { children: "No node executions yet" })
1417
+ ] });
1418
+ }
1419
+ return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
1420
+ /* @__PURE__ */ jsx("div", { className: "absolute left-4 top-8 bottom-8 w-0.5 bg-border-secondary" }),
1421
+ /* @__PURE__ */ jsx("div", { className: "space-y-4", children: sortedNodes.map((node, index) => {
1422
+ const isExpanded = expandedNodes.has(node.id);
1423
+ const nodeError = node.error;
1424
+ const hasError = node.status === "FAILED" || Boolean(nodeError);
1425
+ const isRunning = node.status === "RUNNING";
1426
+ const isWaitingSubworkflow = node.status === "WAITING_SUBWORKFLOW";
1427
+ const hasChildRun = Boolean(node.childRunId);
1428
+ return /* @__PURE__ */ jsxs("div", { className: "relative flex gap-4", children: [
1429
+ /* @__PURE__ */ jsxs(
1430
+ "div",
1431
+ {
1432
+ className: `
1433
+ relative z-10 w-8 h-8 rounded-full flex items-center justify-center flex-shrink-0
1434
+ ${node.status === "COMPLETED" ? "bg-[var(--color-status-success-bg-subtle)] text-[var(--color-status-success-text)]" : node.status === "FAILED" ? "bg-[var(--color-status-error-bg-subtle)] text-[var(--color-status-error-text)]" : node.status === "RUNNING" ? "bg-[var(--color-status-info-bg-subtle)] text-[var(--color-status-info-text)]" : node.status === "SKIPPED" ? "bg-muted text-tertiary" : "bg-muted text-tertiary"}
1435
+ `,
1436
+ children: [
1437
+ /* @__PURE__ */ jsx("span", { className: "text-xs font-bold", children: index + 1 }),
1438
+ isRunning && /* @__PURE__ */ jsx("span", { className: "absolute inset-0 rounded-full border-2 border-[var(--color-status-info-text)] animate-ping" })
1439
+ ]
1440
+ }
1441
+ ),
1442
+ /* @__PURE__ */ jsxs(
1443
+ "div",
1444
+ {
1445
+ className: `
1446
+ flex-1 rounded-lg border transition-all
1447
+ ${hasError ? "bg-[var(--color-status-error-bg-subtle)] border-[var(--color-status-error-border)]" : isRunning ? "bg-[var(--color-status-info-bg-subtle)] border-[var(--color-status-info-border)]" : "bg-background-secondary border-border-secondary"}
1448
+ `,
1449
+ children: [
1450
+ /* @__PURE__ */ jsxs(
1451
+ "button",
1452
+ {
1453
+ onClick: () => toggleNode(node.id),
1454
+ className: "w-full px-4 py-3 flex items-center justify-between text-left",
1455
+ children: [
1456
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 min-w-0", children: [
1457
+ /* @__PURE__ */ jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsx(
1458
+ NodeStatusBadge,
1459
+ {
1460
+ status: node.status,
1461
+ size: "sm",
1462
+ showLabel: false
1463
+ }
1464
+ ) }),
1465
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
1466
+ /* @__PURE__ */ jsx("div", { className: "font-medium text-text-primary truncate", children: node.nodeId }),
1467
+ /* @__PURE__ */ jsxs("div", { className: "text-xs text-text-secondary", children: [
1468
+ node.nodeType,
1469
+ " v",
1470
+ node.nodeVersion
1471
+ ] })
1472
+ ] })
1473
+ ] }),
1474
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4 flex-shrink-0", children: [
1475
+ /* @__PURE__ */ jsxs("div", { className: "text-right text-xs text-text-secondary hidden sm:block", children: [
1476
+ /* @__PURE__ */ jsx("div", { children: formatTime2(node.startTime) }),
1477
+ /* @__PURE__ */ jsx("div", { children: formatDuration3(node.duration) })
1478
+ ] }),
1479
+ hasChildRun && /* @__PURE__ */ jsxs("span", { className: "px-2 py-0.5 text-xs bg-indigo-100 text-indigo-700 rounded flex items-center gap-1", children: [
1480
+ /* @__PURE__ */ jsx(Icon, { icon: "mdi:sitemap", width: 12 }),
1481
+ "Sub-workflow"
1482
+ ] }),
1483
+ isWaitingSubworkflow && /* @__PURE__ */ jsx("span", { className: "px-2 py-0.5 text-xs bg-purple-100 text-purple-700 rounded animate-pulse", children: "Waiting..." }),
1484
+ node.attemptCount > 1 && /* @__PURE__ */ jsxs("span", { className: "px-2 py-0.5 text-xs bg-[var(--color-status-warning-bg-subtle)] text-[var(--color-status-warning-text)] rounded", children: [
1485
+ "Attempt ",
1486
+ node.attemptCount
1487
+ ] }),
1488
+ /* @__PURE__ */ jsx(
1489
+ Icon,
1490
+ {
1491
+ icon: isExpanded ? "mdi:chevron-up" : "mdi:chevron-down",
1492
+ className: "text-text-secondary",
1493
+ width: 20
1494
+ }
1495
+ )
1496
+ ] })
1497
+ ]
1498
+ }
1499
+ ),
1500
+ isExpanded && /* @__PURE__ */ jsxs("div", { className: "px-4 pb-4 border-t border-border-secondary/50", children: [
1501
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-2 mt-3 mb-3", children: [
1502
+ /* @__PURE__ */ jsx(
1503
+ "button",
1504
+ {
1505
+ onClick: () => setSelectedTab("output"),
1506
+ className: `px-3 py-1.5 text-sm rounded ${selectedTab === "output" ? "bg-action-primary-bg text-white" : "bg-background-tertiary text-text-secondary"}`,
1507
+ children: "Output"
1508
+ }
1509
+ ),
1510
+ /* @__PURE__ */ jsx(
1511
+ "button",
1512
+ {
1513
+ onClick: () => setSelectedTab("input"),
1514
+ className: `px-3 py-1.5 text-sm rounded ${selectedTab === "input" ? "bg-action-primary-bg text-white" : "bg-background-tertiary text-text-secondary"}`,
1515
+ children: "Input"
1516
+ }
1517
+ )
1518
+ ] }),
1519
+ /* @__PURE__ */ jsx("div", { className: "bg-background-primary rounded p-3 max-h-64 overflow-auto", children: /* @__PURE__ */ jsx("pre", { className: "text-xs text-text-primary whitespace-pre-wrap break-words font-mono", children: selectedTab === "output" ? formatJsonData(node.output) : formatJsonData(node.inputArgs) }) }),
1520
+ node.error && /* @__PURE__ */ jsxs("div", { className: "mt-3 p-3 bg-[var(--color-status-error-bg-subtle)] border border-[var(--color-status-error-border)] rounded", children: [
1521
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-[var(--color-status-error-text)] mb-1", children: [
1522
+ /* @__PURE__ */ jsx(Icon, { icon: "mdi:alert-circle", width: 16 }),
1523
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-sm", children: "Error" }),
1524
+ node.errorType && /* @__PURE__ */ jsx("span", { className: "text-xs bg-[var(--color-status-error-bg)] px-2 py-0.5 rounded", children: node.errorType })
1525
+ ] }),
1526
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-[var(--color-status-error-text)]", children: node.error })
1527
+ ] }),
1528
+ /* @__PURE__ */ jsxs("div", { className: "mt-3 flex justify-end gap-2", children: [
1529
+ hasChildRun && onViewChildRun && /* @__PURE__ */ jsxs(
1530
+ "button",
1531
+ {
1532
+ onClick: () => onViewChildRun(node.childRunId),
1533
+ className: "px-3 py-1.5 text-sm bg-indigo-600 text-white rounded hover:bg-indigo-700 flex items-center gap-1.5",
1534
+ children: [
1535
+ /* @__PURE__ */ jsx(Icon, { icon: "mdi:sitemap", width: 16 }),
1536
+ "View Sub-Workflow Run"
1537
+ ]
1538
+ }
1539
+ ),
1540
+ node.status === "FAILED" && onRetryNode && /* @__PURE__ */ jsxs(
1541
+ "button",
1542
+ {
1543
+ onClick: () => onRetryNode(node.nodeId),
1544
+ className: "px-3 py-1.5 text-sm bg-action-primary-bg text-white rounded hover:bg-action-primary-bg/90 flex items-center gap-1.5",
1545
+ children: [
1546
+ /* @__PURE__ */ jsx(Icon, { icon: "mdi:refresh", width: 16 }),
1547
+ "Retry Node"
1548
+ ]
1549
+ }
1550
+ )
1551
+ ] }),
1552
+ hasMetadata(node.metadata) && /* @__PURE__ */ jsxs("details", { className: "mt-3", children: [
1553
+ /* @__PURE__ */ jsx("summary", { className: "text-xs text-text-secondary cursor-pointer hover:text-text-primary", children: "Metadata" }),
1554
+ /* @__PURE__ */ jsx("pre", { className: "mt-2 text-xs text-text-secondary bg-background-tertiary p-2 rounded overflow-auto max-h-32", children: formatJsonData(node.metadata) })
1555
+ ] })
1556
+ ] })
1557
+ ]
1558
+ }
1559
+ )
1560
+ ] }, node.id);
1561
+ }) })
1562
+ ] });
1563
+ }
1564
+ function Pagination({
1565
+ totalItems,
1566
+ showPageSize = true
1567
+ }) {
1568
+ const { pagination, setPage, setPageSize } = useExecutionsStore();
1569
+ const { page, pageSize, total } = pagination;
1570
+ const totalPages = Math.ceil((totalItems ?? total) / pageSize);
1571
+ const startItem = (page - 1) * pageSize + 1;
1572
+ const endItem = Math.min(page * pageSize, totalItems ?? total);
1573
+ const pageSizeOptions = [10, 25, 50, 100];
1574
+ const goToPage = (newPage) => {
1575
+ if (newPage >= 1 && newPage <= totalPages) {
1576
+ setPage(newPage);
1577
+ }
1578
+ };
1579
+ const getPageNumbers = () => {
1580
+ const pages = [];
1581
+ const showEllipsisThreshold = 7;
1582
+ if (totalPages <= showEllipsisThreshold) {
1583
+ for (let i = 1; i <= totalPages; i++) {
1584
+ pages.push(i);
1585
+ }
1586
+ } else {
1587
+ pages.push(1);
1588
+ if (page > 3) {
1589
+ pages.push("ellipsis");
1590
+ }
1591
+ const start = Math.max(2, page - 1);
1592
+ const end = Math.min(totalPages - 1, page + 1);
1593
+ for (let i = start; i <= end; i++) {
1594
+ pages.push(i);
1595
+ }
1596
+ if (page < totalPages - 2) {
1597
+ pages.push("ellipsis");
1598
+ }
1599
+ pages.push(totalPages);
1600
+ }
1601
+ return pages;
1602
+ };
1603
+ if (totalPages <= 1 && !showPageSize) {
1604
+ return null;
1605
+ }
1606
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row items-center justify-between gap-4 py-4", children: [
1607
+ /* @__PURE__ */ jsxs("div", { className: "text-sm text-text-secondary", children: [
1608
+ "Showing",
1609
+ " ",
1610
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-text-primary", children: startItem }),
1611
+ " to",
1612
+ " ",
1613
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-text-primary", children: endItem }),
1614
+ " of",
1615
+ " ",
1616
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-text-primary", children: totalItems ?? total }),
1617
+ " ",
1618
+ "results"
1619
+ ] }),
1620
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4", children: [
1621
+ showPageSize && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1622
+ /* @__PURE__ */ jsx("label", { className: "text-sm text-text-secondary", children: "Show" }),
1623
+ /* @__PURE__ */ jsx(
1624
+ "select",
1625
+ {
1626
+ value: pageSize,
1627
+ onChange: (e) => setPageSize(Number(e.target.value)),
1628
+ className: "px-2 py-1 bg-background-secondary border border-border-secondary rounded text-sm text-text-primary",
1629
+ children: pageSizeOptions.map((size) => /* @__PURE__ */ jsx("option", { value: size, children: size }, size))
1630
+ }
1631
+ )
1632
+ ] }),
1633
+ totalPages > 1 && /* @__PURE__ */ jsxs("nav", { className: "flex items-center gap-1", children: [
1634
+ /* @__PURE__ */ jsx(
1635
+ "button",
1636
+ {
1637
+ onClick: () => goToPage(page - 1),
1638
+ disabled: page === 1,
1639
+ className: "p-2 rounded hover:bg-background-tertiary disabled:opacity-50 disabled:cursor-not-allowed",
1640
+ children: /* @__PURE__ */ jsx(
1641
+ Icon,
1642
+ {
1643
+ icon: "mdi:chevron-left",
1644
+ width: 20,
1645
+ className: "text-text-secondary"
1646
+ }
1647
+ )
1648
+ }
1649
+ ),
1650
+ /* @__PURE__ */ jsx("div", { className: "hidden sm:flex items-center gap-1", children: getPageNumbers().map(
1651
+ (pageNum, index) => pageNum === "ellipsis" ? /* @__PURE__ */ jsx(
1652
+ "span",
1653
+ {
1654
+ className: "px-2 text-text-secondary",
1655
+ children: "..."
1656
+ },
1657
+ `ellipsis-${index}`
1658
+ ) : /* @__PURE__ */ jsx(
1659
+ "button",
1660
+ {
1661
+ onClick: () => goToPage(pageNum),
1662
+ className: `
1663
+ min-w-[32px] h-8 px-2 rounded text-sm font-medium
1664
+ ${pageNum === page ? "bg-action-primary-bg text-white" : "hover:bg-background-tertiary text-text-secondary"}
1665
+ `,
1666
+ children: pageNum
1667
+ },
1668
+ pageNum
1669
+ )
1670
+ ) }),
1671
+ /* @__PURE__ */ jsxs("span", { className: "sm:hidden px-3 text-sm text-text-secondary", children: [
1672
+ page,
1673
+ " / ",
1674
+ totalPages
1675
+ ] }),
1676
+ /* @__PURE__ */ jsx(
1677
+ "button",
1678
+ {
1679
+ onClick: () => goToPage(page + 1),
1680
+ disabled: page === totalPages,
1681
+ className: "p-2 rounded hover:bg-background-tertiary disabled:opacity-50 disabled:cursor-not-allowed",
1682
+ children: /* @__PURE__ */ jsx(
1683
+ Icon,
1684
+ {
1685
+ icon: "mdi:chevron-right",
1686
+ width: 20,
1687
+ className: "text-text-secondary"
1688
+ }
1689
+ )
1690
+ }
1691
+ )
1692
+ ] })
1693
+ ] })
1694
+ ] });
1695
+ }
1696
+ gql`
1697
+ subscription NodeStateUpdated($runId: String!) {
1698
+ _empty
1699
+ }
1700
+ `;
1701
+ gql`
1702
+ subscription WorkflowCompleted($runId: String!) {
1703
+ _empty
1704
+ }
1705
+ `;
1706
+ gql`
1707
+ subscription WorkflowError($runId: String!) {
1708
+ _empty
1709
+ }
1710
+ `;
1711
+ gql`
1712
+ subscription ExecutionUpdated($runId: String!) {
1713
+ _empty
1714
+ }
1715
+ `;
1716
+ gql`
1717
+ subscription ExecutionNodeStateUpdated($runId: String!) {
1718
+ _empty
1719
+ }
1720
+ `;
1721
+ gql`
1722
+ subscription ExecutionCompleted($runId: String!) {
1723
+ _empty
1724
+ }
1725
+ `;
1726
+ gql`
1727
+ subscription ExecutionError($runId: String!) {
1728
+ _empty
1729
+ }
1730
+ `;
1731
+
1732
+ // src/modules/executions/hooks/useExecutions.ts
1733
+ function useExecutions(input = {}) {
1734
+ const [executions, setExecutions] = useState([]);
1735
+ const [total, setTotal] = useState(0);
1736
+ const [hasMore, setHasMore] = useState(false);
1737
+ const [loading, setLoading] = useState(true);
1738
+ const [error, setError] = useState(null);
1739
+ const inputKey = JSON.stringify(input);
1740
+ const fetchData = useCallback(async () => {
1741
+ setLoading(true);
1742
+ setError(null);
1743
+ try {
1744
+ const client = getFluidGridsClient();
1745
+ const result = await client.query({
1746
+ query: ExecutionsListDocument,
1747
+ variables: { input: JSON.parse(inputKey) },
1748
+ fetchPolicy: "network-only"
1749
+ });
1750
+ setExecutions(result.data?.workflowRuns?.items ?? []);
1751
+ setTotal(result.data?.workflowRuns?.total ?? 0);
1752
+ setHasMore(result.data?.workflowRuns?.hasMore ?? false);
1753
+ } catch (err) {
1754
+ setError(err);
1755
+ } finally {
1756
+ setLoading(false);
1757
+ }
1758
+ }, [inputKey]);
1759
+ useEffect(() => {
1760
+ fetchData();
1761
+ }, [fetchData]);
1762
+ return {
1763
+ executions,
1764
+ total,
1765
+ hasMore,
1766
+ loading,
1767
+ error,
1768
+ refetch: fetchData
1769
+ };
1770
+ }
1771
+ function useExecution(id) {
1772
+ const [execution, setExecution] = useState(null);
1773
+ const [loading, setLoading] = useState(true);
1774
+ const [error, setError] = useState(null);
1775
+ const fetchData = useCallback(async () => {
1776
+ if (!id) {
1777
+ setLoading(false);
1778
+ return;
1779
+ }
1780
+ setLoading(true);
1781
+ setError(null);
1782
+ try {
1783
+ const client = getFluidGridsClient();
1784
+ const result = await client.query({
1785
+ query: ExecutionDetailDocument,
1786
+ variables: { id },
1787
+ fetchPolicy: "network-only"
1788
+ });
1789
+ setExecution(result.data?.workflowRun ?? null);
1790
+ } catch (err) {
1791
+ setError(err);
1792
+ } finally {
1793
+ setLoading(false);
1794
+ }
1795
+ }, [id]);
1796
+ useEffect(() => {
1797
+ fetchData();
1798
+ }, [fetchData]);
1799
+ return {
1800
+ execution,
1801
+ loading,
1802
+ error,
1803
+ refetch: fetchData
1804
+ };
1805
+ }
1806
+ function useExecutionLogs(runId, limit = 100) {
1807
+ const [logs, setLogs] = useState([]);
1808
+ const [loading, setLoading] = useState(true);
1809
+ const [error, setError] = useState(null);
1810
+ const fetchData = useCallback(async () => {
1811
+ if (!runId) {
1812
+ setLoading(false);
1813
+ return;
1814
+ }
1815
+ setLoading(true);
1816
+ setError(null);
1817
+ try {
1818
+ const client = getFluidGridsClient();
1819
+ const result = await client.query({
1820
+ query: ExecutionLogsDocument,
1821
+ variables: { runId, limit },
1822
+ fetchPolicy: "network-only"
1823
+ });
1824
+ setLogs(result.data?.workflowExecutionLogs ?? []);
1825
+ } catch (err) {
1826
+ setError(err);
1827
+ } finally {
1828
+ setLoading(false);
1829
+ }
1830
+ }, [runId, limit]);
1831
+ useEffect(() => {
1832
+ fetchData();
1833
+ }, [fetchData]);
1834
+ return {
1835
+ logs,
1836
+ loading,
1837
+ error,
1838
+ refetch: fetchData
1839
+ };
1840
+ }
1841
+ function useExecutionStats(options = {}) {
1842
+ const [stats, setStats] = useState(null);
1843
+ const [loading, setLoading] = useState(true);
1844
+ const [error, setError] = useState(null);
1845
+ const optionsKey = JSON.stringify(options);
1846
+ const fetchData = useCallback(async () => {
1847
+ setLoading(true);
1848
+ setError(null);
1849
+ try {
1850
+ const client = getFluidGridsClient();
1851
+ const result = await client.query({
1852
+ query: ExecutionStatsDocument,
1853
+ variables: JSON.parse(optionsKey),
1854
+ fetchPolicy: "network-only"
1855
+ });
1856
+ setStats(result.data?.dashboardSummary ?? null);
1857
+ } catch (err) {
1858
+ setError(err);
1859
+ } finally {
1860
+ setLoading(false);
1861
+ }
1862
+ }, [optionsKey]);
1863
+ useEffect(() => {
1864
+ fetchData();
1865
+ }, [fetchData]);
1866
+ return {
1867
+ stats,
1868
+ loading,
1869
+ error,
1870
+ refetch: fetchData
1871
+ };
1872
+ }
1873
+ function useExecutionActions() {
1874
+ const [loading, setLoading] = useState(false);
1875
+ const [error, setError] = useState(null);
1876
+ const pauseExecution = useCallback(async (id) => {
1877
+ setLoading(true);
1878
+ setError(null);
1879
+ try {
1880
+ const client = getFluidGridsClient();
1881
+ const result = await client.mutate({
1882
+ mutation: PauseExecutionDocument,
1883
+ variables: { id }
1884
+ });
1885
+ return result.data?.pauseWorkflowRun ?? null;
1886
+ } catch (err) {
1887
+ setError(err);
1888
+ return null;
1889
+ } finally {
1890
+ setLoading(false);
1891
+ }
1892
+ }, []);
1893
+ const resumeExecution = useCallback(async (id) => {
1894
+ setLoading(true);
1895
+ setError(null);
1896
+ try {
1897
+ const client = getFluidGridsClient();
1898
+ const result = await client.mutate({
1899
+ mutation: ResumeExecutionDocument,
1900
+ variables: { id }
1901
+ });
1902
+ return result.data?.resumeWorkflowRun ?? null;
1903
+ } catch (err) {
1904
+ setError(err);
1905
+ return null;
1906
+ } finally {
1907
+ setLoading(false);
1908
+ }
1909
+ }, []);
1910
+ const cancelExecution = useCallback(async (id) => {
1911
+ setLoading(true);
1912
+ setError(null);
1913
+ try {
1914
+ const client = getFluidGridsClient();
1915
+ const result = await client.mutate({
1916
+ mutation: CancelExecutionDocument,
1917
+ variables: { id }
1918
+ });
1919
+ return result.data?.cancelWorkflowRun ?? null;
1920
+ } catch (err) {
1921
+ setError(err);
1922
+ return null;
1923
+ } finally {
1924
+ setLoading(false);
1925
+ }
1926
+ }, []);
1927
+ const retryNode = useCallback(async (runId, nodeId) => {
1928
+ setLoading(true);
1929
+ setError(null);
1930
+ try {
1931
+ const client = getFluidGridsClient();
1932
+ const result = await client.mutate({
1933
+ mutation: RetryNodeDocument,
1934
+ variables: { id: runId, nodeId }
1935
+ });
1936
+ return result.data?.retryNode ?? null;
1937
+ } catch (err) {
1938
+ setError(err);
1939
+ return null;
1940
+ } finally {
1941
+ setLoading(false);
1942
+ }
1943
+ }, []);
1944
+ const terminateExecution = useCallback(
1945
+ async (runId, reason) => {
1946
+ setLoading(true);
1947
+ setError(null);
1948
+ try {
1949
+ const client = getFluidGridsClient();
1950
+ const result = await client.mutate({
1951
+ mutation: TerminateExecutionDocument,
1952
+ variables: { runId, reason }
1953
+ });
1954
+ return result.data?.terminateWorkflow ?? null;
1955
+ } catch (err) {
1956
+ setError(err);
1957
+ return null;
1958
+ } finally {
1959
+ setLoading(false);
1960
+ }
1961
+ },
1962
+ []
1963
+ );
1964
+ return {
1965
+ pauseExecution,
1966
+ resumeExecution,
1967
+ cancelExecution,
1968
+ retryNode,
1969
+ terminateExecution,
1970
+ loading,
1971
+ error
1972
+ };
1973
+ }
1974
+ function useExecutionsWithStore() {
1975
+ const { filter, pagination, setTotal } = useExecutionsStore();
1976
+ const input = useMemo(() => {
1977
+ const baseInput = {
1978
+ limit: pagination.pageSize,
1979
+ offset: (pagination.page - 1) * pagination.pageSize
1980
+ };
1981
+ if (filter.status !== "all") {
1982
+ baseInput.status = filter.status;
1983
+ }
1984
+ if (filter.workflowKey) {
1985
+ baseInput.workflowKey = filter.workflowKey;
1986
+ }
1987
+ if (filter.dateRange.start) {
1988
+ baseInput.startDate = filter.dateRange.start.toISOString();
1989
+ }
1990
+ if (filter.dateRange.end) {
1991
+ baseInput.endDate = filter.dateRange.end.toISOString();
1992
+ }
1993
+ return baseInput;
1994
+ }, [filter, pagination.page, pagination.pageSize]);
1995
+ const result = useExecutions(input);
1996
+ useEffect(() => {
1997
+ if (result.total !== pagination.total) {
1998
+ setTotal(result.total);
1999
+ }
2000
+ }, [result.total, pagination.total, setTotal]);
2001
+ return result;
2002
+ }
2003
+ function useAutoRefresh(refetchFn, enabled = true, interval = 5e3) {
2004
+ useEffect(() => {
2005
+ if (!enabled) return;
2006
+ const timer = setInterval(() => {
2007
+ refetchFn();
2008
+ }, interval);
2009
+ return () => clearInterval(timer);
2010
+ }, [enabled, interval, refetchFn]);
2011
+ }
2012
+
2013
+ export { ExecutionCards, ExecutionFilters, ExecutionStats, ExecutionStatusBadge, ExecutionTable, ExecutionTimeline, NodeTimeline, Pagination, useAutoRefresh, useExecution, useExecutionActions, useExecutionLogs, useExecutionStats, useExecutionsStore, useExecutionsWithStore };
2014
+ //# sourceMappingURL=chunk-WD52O45G.js.map
2015
+ //# sourceMappingURL=chunk-WD52O45G.js.map