@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.
- package/README.md +149 -0
- package/dist/ExecutionDetailPage-3EVS3WEC.js +6 -0
- package/dist/ExecutionDetailPage-3EVS3WEC.js.map +1 -0
- package/dist/ExecutionsListPage-NH2JLL2D.js +8 -0
- package/dist/ExecutionsListPage-NH2JLL2D.js.map +1 -0
- package/dist/TemplateConfigurationModal-UJAGRE7X.js +258 -0
- package/dist/TemplateConfigurationModal-UJAGRE7X.js.map +1 -0
- package/dist/TemplateDetailPanel-UXH6KPCH.js +172 -0
- package/dist/TemplateDetailPanel-UXH6KPCH.js.map +1 -0
- package/dist/WorkflowBuilder-BMKFLHVE.js +15 -0
- package/dist/WorkflowBuilder-BMKFLHVE.js.map +1 -0
- package/dist/WorkflowsList-CLI32VRE.js +8 -0
- package/dist/WorkflowsList-CLI32VRE.js.map +1 -0
- package/dist/chunk-4FFPGQD3.js +584 -0
- package/dist/chunk-4FFPGQD3.js.map +1 -0
- package/dist/chunk-5BDQNSP3.js +107 -0
- package/dist/chunk-5BDQNSP3.js.map +1 -0
- package/dist/chunk-6PHBYAEG.js +11494 -0
- package/dist/chunk-6PHBYAEG.js.map +1 -0
- package/dist/chunk-BQXHJIER.js +45 -0
- package/dist/chunk-BQXHJIER.js.map +1 -0
- package/dist/chunk-BXDSTMUA.js +8848 -0
- package/dist/chunk-BXDSTMUA.js.map +1 -0
- package/dist/chunk-CGKBAJMM.js +292 -0
- package/dist/chunk-CGKBAJMM.js.map +1 -0
- package/dist/chunk-FGYVIXQ7.js +979 -0
- package/dist/chunk-FGYVIXQ7.js.map +1 -0
- package/dist/chunk-G7B4SYFM.js +22 -0
- package/dist/chunk-G7B4SYFM.js.map +1 -0
- package/dist/chunk-GSJOLO3A.js +251 -0
- package/dist/chunk-GSJOLO3A.js.map +1 -0
- package/dist/chunk-GSS5PHRL.js +386 -0
- package/dist/chunk-GSS5PHRL.js.map +1 -0
- package/dist/chunk-GY66IQWN.js +524 -0
- package/dist/chunk-GY66IQWN.js.map +1 -0
- package/dist/chunk-LUGJJ7LL.js +297 -0
- package/dist/chunk-LUGJJ7LL.js.map +1 -0
- package/dist/chunk-NDJSUC4W.js +155 -0
- package/dist/chunk-NDJSUC4W.js.map +1 -0
- package/dist/chunk-UOCR65PI.js +262 -0
- package/dist/chunk-UOCR65PI.js.map +1 -0
- package/dist/chunk-WD52O45G.js +2015 -0
- package/dist/chunk-WD52O45G.js.map +1 -0
- package/dist/chunk-WWU2O2SR.js +52 -0
- package/dist/chunk-WWU2O2SR.js.map +1 -0
- package/dist/chunk-XQP33UJR.js +57 -0
- package/dist/chunk-XQP33UJR.js.map +1 -0
- package/dist/chunk-Z54K22LP.js +82 -0
- package/dist/chunk-Z54K22LP.js.map +1 -0
- package/dist/client-AMUUS7VE.js +3 -0
- package/dist/client-AMUUS7VE.js.map +1 -0
- package/dist/config-E4E7M6IN.js +3 -0
- package/dist/config-E4E7M6IN.js.map +1 -0
- package/dist/global-client-OW43ZRDR.js +3 -0
- package/dist/global-client-OW43ZRDR.js.map +1 -0
- package/dist/global-operations-WPTEYCJM.js +3 -0
- package/dist/global-operations-WPTEYCJM.js.map +1 -0
- package/dist/index.d.ts +56706 -0
- package/dist/index.js +6564 -0
- package/dist/index.js.map +1 -0
- package/dist/styles.css +139 -0
- package/dist/template-input-applicator-657KE4DM.js +3 -0
- package/dist/template-input-applicator-657KE4DM.js.map +1 -0
- package/dist/useImportWorkflowTemplate-2HS5D2OP.js +11 -0
- package/dist/useImportWorkflowTemplate-2HS5D2OP.js.map +1 -0
- package/dist/useTemplateDetail-NK63V3PC.js +6 -0
- package/dist/useTemplateDetail-NK63V3PC.js.map +1 -0
- 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
|