@nvent-addon/app 0.5.4 → 0.5.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/module.json +1 -1
- package/dist/module.mjs +9 -1
- package/dist/runtime/app/components/ComponentShell.d.vue.ts +1 -0
- package/dist/runtime/app/components/ComponentShell.vue +13 -3
- package/dist/runtime/app/components/ComponentShell.vue.d.ts +1 -0
- package/dist/runtime/app/components/DashboardCard.d.vue.ts +15 -0
- package/dist/runtime/app/components/DashboardCard.vue +76 -0
- package/dist/runtime/app/components/DashboardCard.vue.d.ts +15 -0
- package/dist/runtime/app/components/TimelineList.vue +222 -31
- package/dist/runtime/app/components/flow/AwaitNode.d.vue.ts +19 -2
- package/dist/runtime/app/components/flow/AwaitNode.vue +317 -29
- package/dist/runtime/app/components/flow/AwaitNode.vue.d.ts +19 -2
- package/dist/runtime/app/components/flow/Diagram.d.vue.ts +2 -1
- package/dist/runtime/app/components/flow/Diagram.vue +138 -74
- package/dist/runtime/app/components/flow/Diagram.vue.d.ts +2 -1
- package/dist/runtime/app/components/flow/NodeCard.d.vue.ts +14 -11
- package/dist/runtime/app/components/flow/NodeCard.vue +119 -35
- package/dist/runtime/app/components/flow/NodeCard.vue.d.ts +14 -11
- package/dist/runtime/app/components/flow/RunOverview.d.vue.ts +1 -0
- package/dist/runtime/app/components/flow/RunOverview.vue +85 -86
- package/dist/runtime/app/components/flow/RunOverview.vue.d.ts +1 -0
- package/dist/runtime/app/components/flow/RunTimeline.vue +51 -22
- package/dist/runtime/app/components/flow/StepSelector.vue +124 -46
- package/dist/runtime/app/composables/useFlowRunTimeline.d.ts +6 -0
- package/dist/runtime/app/composables/useFlowState.d.ts +8 -1
- package/dist/runtime/app/composables/useFlowState.js +34 -59
- package/dist/runtime/app/pages/dashboard.vue +51 -103
- package/dist/runtime/app/pages/flows/[name].vue +26 -3
- package/dist/runtime/app/pages/triggers/[name]/edit.vue +1 -1
- package/package.json +1 -1
|
@@ -102,39 +102,90 @@ const nodes = computed(() => {
|
|
|
102
102
|
const f = props.flow;
|
|
103
103
|
if (!f) return out;
|
|
104
104
|
const states = props.stepStates || {};
|
|
105
|
-
const colWidth =
|
|
106
|
-
const rowHeight =
|
|
107
|
-
const horizontalGap =
|
|
108
|
-
const verticalGap =
|
|
109
|
-
const
|
|
110
|
-
const nodeWidth =
|
|
105
|
+
const colWidth = 320;
|
|
106
|
+
const rowHeight = 180;
|
|
107
|
+
const horizontalGap = 60;
|
|
108
|
+
const verticalGap = 90;
|
|
109
|
+
const awaitRowHeight = 140;
|
|
110
|
+
const nodeWidth = 300;
|
|
111
111
|
let y = 0;
|
|
112
112
|
if (f.entry) {
|
|
113
113
|
const entryState = states[f.entry.step];
|
|
114
114
|
const status = mapStatusToNodeStatus(entryState?.status);
|
|
115
|
+
const entryStepTimeout = f.analyzed?.steps?.[f.entry.step]?.stepTimeout;
|
|
115
116
|
out.push({
|
|
116
117
|
id: `entry:${f.entry.step}`,
|
|
117
118
|
position: { x: -nodeWidth / 2, y },
|
|
118
119
|
data: {
|
|
119
120
|
label: f.entry.step,
|
|
120
121
|
queue: f.entry.queue,
|
|
122
|
+
workerId: f.entry.workerId,
|
|
121
123
|
status,
|
|
122
124
|
attempt: entryState?.attempt,
|
|
123
125
|
error: entryState?.error,
|
|
124
126
|
runtime: f.entry.runtime,
|
|
125
127
|
runtype: f.entry.runtype,
|
|
126
|
-
emits: f.entry.emits
|
|
128
|
+
emits: f.entry.emits,
|
|
129
|
+
awaitBefore: f.entry.awaitBefore,
|
|
130
|
+
awaitAfter: f.entry.awaitAfter,
|
|
131
|
+
stepTimeout: entryStepTimeout
|
|
127
132
|
},
|
|
128
133
|
type: "flow-entry",
|
|
129
134
|
style: { minWidth: `${nodeWidth}px` }
|
|
130
135
|
});
|
|
131
|
-
y += rowHeight +
|
|
136
|
+
y += rowHeight + verticalGap;
|
|
137
|
+
if (f.entry.awaitAfter) {
|
|
138
|
+
const awaitKey = `${f.entry.step}:await-after`;
|
|
139
|
+
const awaitState = states[awaitKey];
|
|
140
|
+
const awaitStatus = awaitState?.status === "waiting" ? "waiting" : awaitState?.status === "completed" ? "resolved" : awaitState?.status === "timeout" ? "timeout" : "idle";
|
|
141
|
+
out.push({
|
|
142
|
+
id: `await:entry-after:${f.entry.step}`,
|
|
143
|
+
position: { x: -120, y },
|
|
144
|
+
data: {
|
|
145
|
+
label: `Await (${f.entry.awaitAfter.type})`,
|
|
146
|
+
awaitType: f.entry.awaitAfter.type,
|
|
147
|
+
awaitConfig: f.entry.awaitAfter,
|
|
148
|
+
awaitData: awaitState?.awaitData,
|
|
149
|
+
status: awaitStatus,
|
|
150
|
+
scheduledTriggerAt: awaitState?.scheduledTriggerAt
|
|
151
|
+
},
|
|
152
|
+
type: "flow-await",
|
|
153
|
+
style: { minWidth: "180px" }
|
|
154
|
+
});
|
|
155
|
+
y += awaitRowHeight + verticalGap;
|
|
156
|
+
}
|
|
132
157
|
}
|
|
133
158
|
const steps = f.steps || {};
|
|
134
159
|
if (f.analyzed?.levels && f.analyzed.levels.length > 0) {
|
|
135
|
-
const levels = f.analyzed.levels.filter((level) => level.length > 0);
|
|
160
|
+
const levels = f.analyzed.levels.slice(1).filter((level) => level.length > 0);
|
|
136
161
|
levels.forEach((levelSteps) => {
|
|
137
162
|
if (levelSteps.length === 0) return;
|
|
163
|
+
const awaitNodesCreated = [];
|
|
164
|
+
levelSteps.forEach((stepName) => {
|
|
165
|
+
const step = steps[stepName];
|
|
166
|
+
if (!step?.awaitBefore) return;
|
|
167
|
+
const awaitState = states[`${stepName}:await-before`];
|
|
168
|
+
const awaitStatus = awaitState?.status === "waiting" ? "waiting" : awaitState?.status === "completed" ? "resolved" : awaitState?.status === "timeout" ? "timeout" : "idle";
|
|
169
|
+
out.push({
|
|
170
|
+
id: `await:step-before:${stepName}`,
|
|
171
|
+
position: { x: 0, y },
|
|
172
|
+
// Temporary position
|
|
173
|
+
data: {
|
|
174
|
+
label: `Await (${step.awaitBefore.type})`,
|
|
175
|
+
awaitType: step.awaitBefore.type,
|
|
176
|
+
awaitConfig: step.awaitBefore,
|
|
177
|
+
awaitData: awaitState?.awaitData,
|
|
178
|
+
status: awaitStatus,
|
|
179
|
+
scheduledTriggerAt: awaitState?.scheduledTriggerAt
|
|
180
|
+
},
|
|
181
|
+
type: "flow-await",
|
|
182
|
+
style: { minWidth: "180px" }
|
|
183
|
+
});
|
|
184
|
+
awaitNodesCreated.push(stepName);
|
|
185
|
+
});
|
|
186
|
+
if (awaitNodesCreated.length > 0) {
|
|
187
|
+
y += awaitRowHeight + verticalGap;
|
|
188
|
+
}
|
|
138
189
|
const cols = Math.min(4, levelSteps.length);
|
|
139
190
|
const rows = Math.ceil(levelSteps.length / cols);
|
|
140
191
|
levelSteps.forEach((stepName, idx) => {
|
|
@@ -150,6 +201,8 @@ const nodes = computed(() => {
|
|
|
150
201
|
const rowStartX = -rowWidth / 2;
|
|
151
202
|
const x = rowStartX + col * (colWidth + horizontalGap);
|
|
152
203
|
const yPos = y + row * (rowHeight + verticalGap);
|
|
204
|
+
const analyzedStep = f.analyzed?.steps?.[stepName];
|
|
205
|
+
const stepStepTimeout = analyzedStep?.stepTimeout;
|
|
153
206
|
out.push({
|
|
154
207
|
id: `step:${stepName}`,
|
|
155
208
|
position: { x, y: yPos },
|
|
@@ -162,13 +215,46 @@ const nodes = computed(() => {
|
|
|
162
215
|
error: stepState?.error,
|
|
163
216
|
runtime: step?.runtime,
|
|
164
217
|
runtype: step?.runtype,
|
|
165
|
-
|
|
218
|
+
subscribes: step?.subscribes,
|
|
219
|
+
emits: step?.emits,
|
|
220
|
+
awaitBefore: step?.awaitBefore,
|
|
221
|
+
awaitAfter: step?.awaitAfter,
|
|
222
|
+
stepTimeout: stepStepTimeout
|
|
166
223
|
},
|
|
167
224
|
type: "flow-step",
|
|
168
225
|
style: { minWidth: `${nodeWidth}px` }
|
|
169
226
|
});
|
|
227
|
+
if (step.awaitBefore) {
|
|
228
|
+
const awaitNode = out.find((n) => n.id === `await:step-before:${stepName}`);
|
|
229
|
+
if (awaitNode) {
|
|
230
|
+
awaitNode.position.x = x - 20;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
if (step.awaitAfter && row === rows - 1 && idx === levelSteps.length - 1) {
|
|
234
|
+
const awaitKey = `${stepName}:await-after`;
|
|
235
|
+
const awaitState = states[awaitKey];
|
|
236
|
+
const awaitStatus = awaitState?.status === "waiting" ? "waiting" : awaitState?.status === "completed" ? "resolved" : awaitState?.status === "timeout" ? "timeout" : "idle";
|
|
237
|
+
out.push({
|
|
238
|
+
id: `await:step-after:${stepName}`,
|
|
239
|
+
position: { x: x - 20, y: yPos + rowHeight + verticalGap },
|
|
240
|
+
data: {
|
|
241
|
+
label: `Await (${step.awaitAfter.type})`,
|
|
242
|
+
awaitType: step.awaitAfter.type,
|
|
243
|
+
awaitConfig: step.awaitAfter,
|
|
244
|
+
awaitData: awaitState?.awaitData,
|
|
245
|
+
status: awaitStatus,
|
|
246
|
+
scheduledTriggerAt: awaitState?.scheduledTriggerAt
|
|
247
|
+
},
|
|
248
|
+
type: "flow-await",
|
|
249
|
+
style: { minWidth: "180px" }
|
|
250
|
+
});
|
|
251
|
+
}
|
|
170
252
|
});
|
|
171
253
|
y += rows * (rowHeight + verticalGap);
|
|
254
|
+
const lastStepName = levelSteps[levelSteps.length - 1];
|
|
255
|
+
if (lastStepName && steps[lastStepName]?.awaitAfter) {
|
|
256
|
+
y += awaitRowHeight + verticalGap;
|
|
257
|
+
}
|
|
172
258
|
});
|
|
173
259
|
} else {
|
|
174
260
|
const names = Object.keys(steps);
|
|
@@ -186,6 +272,8 @@ const nodes = computed(() => {
|
|
|
186
272
|
const rowStartX = -rowWidth / 2;
|
|
187
273
|
const x = rowStartX + col * (colWidth + horizontalGap);
|
|
188
274
|
const yPos = y + row * (rowHeight + verticalGap);
|
|
275
|
+
const analyzedStep = f.analyzed?.steps?.[name];
|
|
276
|
+
const stepStepTimeout = analyzedStep?.stepTimeout;
|
|
189
277
|
out.push({
|
|
190
278
|
id: `step:${name}`,
|
|
191
279
|
position: { x, y: yPos },
|
|
@@ -198,57 +286,15 @@ const nodes = computed(() => {
|
|
|
198
286
|
error: stepState?.error,
|
|
199
287
|
runtime: step?.runtime,
|
|
200
288
|
runtype: step?.runtype,
|
|
201
|
-
emits: step?.emits
|
|
289
|
+
emits: step?.emits,
|
|
290
|
+
stepTimeout: stepStepTimeout
|
|
202
291
|
},
|
|
203
292
|
type: "flow-step",
|
|
204
293
|
style: { minWidth: `${nodeWidth}px` }
|
|
205
294
|
});
|
|
206
295
|
});
|
|
207
296
|
}
|
|
208
|
-
|
|
209
|
-
const awaitGap = 70;
|
|
210
|
-
if (f.entry?.awaitAfter && f.entry) {
|
|
211
|
-
const entryNode = out.find((n) => n.id === `entry:${f.entry.step}`);
|
|
212
|
-
if (entryNode) {
|
|
213
|
-
const awaitKey = `${f.entry.step}:await-after`;
|
|
214
|
-
const awaitState = states[awaitKey];
|
|
215
|
-
const awaitStatus = awaitState?.status === "waiting" ? "waiting" : awaitState?.status === "completed" ? "resolved" : awaitState?.status === "timeout" ? "timeout" : "idle";
|
|
216
|
-
awaitNodes.push({
|
|
217
|
-
id: `await:entry-after:${f.entry.step}`,
|
|
218
|
-
position: { x: -90, y: entryNode.position.y + rowHeight + awaitGap },
|
|
219
|
-
data: {
|
|
220
|
-
label: `Await (${f.entry.awaitAfter.type})`,
|
|
221
|
-
awaitType: f.entry.awaitAfter.type,
|
|
222
|
-
awaitConfig: f.entry.awaitAfter,
|
|
223
|
-
status: awaitStatus
|
|
224
|
-
},
|
|
225
|
-
type: "flow-await",
|
|
226
|
-
style: { minWidth: "180px" }
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
Object.entries(steps).forEach(([stepName, step]) => {
|
|
231
|
-
if (step.awaitBefore) {
|
|
232
|
-
const stepNode = out.find((n) => n.id === `step:${stepName}`);
|
|
233
|
-
if (stepNode) {
|
|
234
|
-
const awaitState = states[`${stepName}:await-before`];
|
|
235
|
-
const awaitStatus = awaitState?.status === "waiting" ? "waiting" : awaitState?.status === "completed" ? "resolved" : awaitState?.status === "timeout" ? "timeout" : "idle";
|
|
236
|
-
awaitNodes.push({
|
|
237
|
-
id: `await:step-before:${stepName}`,
|
|
238
|
-
position: { x: stepNode.position.x + 20, y: stepNode.position.y - awaitGap - 50 },
|
|
239
|
-
data: {
|
|
240
|
-
label: `Await (${step.awaitBefore.type})`,
|
|
241
|
-
awaitType: step.awaitBefore.type,
|
|
242
|
-
awaitConfig: step.awaitBefore,
|
|
243
|
-
status: awaitStatus
|
|
244
|
-
},
|
|
245
|
-
type: "flow-await",
|
|
246
|
-
style: { minWidth: "180px" }
|
|
247
|
-
});
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
});
|
|
251
|
-
return [...out, ...awaitNodes];
|
|
297
|
+
return out;
|
|
252
298
|
});
|
|
253
299
|
function mapStatusToNodeStatus(status) {
|
|
254
300
|
switch (status) {
|
|
@@ -277,22 +323,53 @@ const edges = computed(() => {
|
|
|
277
323
|
function addEdge(source, target, label) {
|
|
278
324
|
const id = `${source}->${target}${label ? `:${label}` : ""}`;
|
|
279
325
|
if (added.has(id)) return;
|
|
280
|
-
const
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
326
|
+
const getNodeState = (nodeId) => {
|
|
327
|
+
if (nodeId.startsWith("await:entry-after:")) {
|
|
328
|
+
const stepName = nodeId.replace("await:entry-after:", "");
|
|
329
|
+
return states[`${stepName}:await-after`];
|
|
330
|
+
}
|
|
331
|
+
if (nodeId.startsWith("await:step-before:")) {
|
|
332
|
+
const stepName = nodeId.replace("await:step-before:", "");
|
|
333
|
+
return states[`${stepName}:await-before`];
|
|
334
|
+
}
|
|
335
|
+
if (nodeId.startsWith("await:step-after:")) {
|
|
336
|
+
const stepName = nodeId.replace("await:step-after:", "");
|
|
337
|
+
return states[`${stepName}:await-after`];
|
|
338
|
+
}
|
|
339
|
+
const parts = nodeId.split(":");
|
|
340
|
+
return parts[1] ? states[parts[1]] : void 0;
|
|
341
|
+
};
|
|
342
|
+
const sourceState = getNodeState(source);
|
|
343
|
+
const targetState = getNodeState(target);
|
|
344
|
+
const shouldAnimate = (props.flowStatus === "running" || props.flowStatus === "awaiting") && (sourceState?.status === "completed" || sourceState?.status === "resolved") && (targetState?.status === "running" || targetState?.status === "pending" || targetState?.status === "waiting" || !targetState);
|
|
285
345
|
added.add(id);
|
|
286
346
|
out.push({ id, source, target, label, animated: shouldAnimate });
|
|
287
347
|
}
|
|
288
348
|
if (f.analyzed?.steps) {
|
|
289
349
|
const analyzedSteps = f.analyzed.steps;
|
|
350
|
+
if (f.entry?.awaitAfter) {
|
|
351
|
+
const entryId = `entry:${f.entry.step}`;
|
|
352
|
+
const entryAwaitId = `await:entry-after:${f.entry.step}`;
|
|
353
|
+
addEdge(entryId, entryAwaitId);
|
|
354
|
+
}
|
|
290
355
|
for (const [stepName, stepInfo] of Object.entries(analyzedSteps)) {
|
|
356
|
+
if (stepName === f.entry?.step) continue;
|
|
291
357
|
const targetStep = steps[stepName];
|
|
292
358
|
const target = `step:${stepName}`;
|
|
359
|
+
if (targetStep?.awaitAfter) {
|
|
360
|
+
const stepId = `step:${stepName}`;
|
|
361
|
+
const awaitAfterId = `await:step-after:${stepName}`;
|
|
362
|
+
addEdge(stepId, awaitAfterId);
|
|
363
|
+
}
|
|
293
364
|
if (stepInfo.dependsOn.length > 0) {
|
|
294
365
|
for (const depName of stepInfo.dependsOn) {
|
|
295
|
-
|
|
366
|
+
let source;
|
|
367
|
+
if (depName === f.entry?.step) {
|
|
368
|
+
source = f.entry.awaitAfter ? `await:entry-after:${depName}` : `entry:${depName}`;
|
|
369
|
+
} else {
|
|
370
|
+
const depStep = steps[depName];
|
|
371
|
+
source = depStep?.awaitAfter ? `await:step-after:${depName}` : `step:${depName}`;
|
|
372
|
+
}
|
|
296
373
|
if (targetStep?.awaitBefore) {
|
|
297
374
|
const awaitNodeId = `await:step-before:${stepName}`;
|
|
298
375
|
addEdge(source, awaitNodeId);
|
|
@@ -301,19 +378,6 @@ const edges = computed(() => {
|
|
|
301
378
|
addEdge(source, target);
|
|
302
379
|
}
|
|
303
380
|
}
|
|
304
|
-
} else if (f.entry) {
|
|
305
|
-
const entryId = `entry:${f.entry.step}`;
|
|
306
|
-
if (f.entry.awaitAfter) {
|
|
307
|
-
const awaitNodeId = `await:entry-after:${f.entry.step}`;
|
|
308
|
-
addEdge(entryId, awaitNodeId);
|
|
309
|
-
addEdge(awaitNodeId, target);
|
|
310
|
-
} else if (targetStep?.awaitBefore) {
|
|
311
|
-
const awaitNodeId = `await:step-before:${stepName}`;
|
|
312
|
-
addEdge(entryId, awaitNodeId);
|
|
313
|
-
addEdge(awaitNodeId, target);
|
|
314
|
-
} else {
|
|
315
|
-
addEdge(entryId, target);
|
|
316
|
-
}
|
|
317
381
|
}
|
|
318
382
|
}
|
|
319
383
|
} else {
|
|
@@ -45,6 +45,7 @@ interface StepStatus {
|
|
|
45
45
|
status: 'pending' | 'running' | 'completed' | 'failed' | 'retrying' | 'waiting' | 'timeout' | 'canceled';
|
|
46
46
|
attempt?: number;
|
|
47
47
|
error?: string;
|
|
48
|
+
scheduledTriggerAt?: string;
|
|
48
49
|
}
|
|
49
50
|
type __VLS_Props = {
|
|
50
51
|
flow?: FlowMeta | null;
|
|
@@ -53,7 +54,7 @@ type __VLS_Props = {
|
|
|
53
54
|
showMiniMap?: boolean;
|
|
54
55
|
showBackground?: boolean;
|
|
55
56
|
stepStates?: Record<string, StepStatus>;
|
|
56
|
-
flowStatus?: 'running' | 'completed' | 'failed' | 'canceled' | 'stalled';
|
|
57
|
+
flowStatus?: 'running' | 'completed' | 'failed' | 'canceled' | 'stalled' | 'awaiting';
|
|
57
58
|
};
|
|
58
59
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
59
60
|
nodeSelected: (payload: {
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
type Status = 'idle' | 'running' | 'error' | 'done' | 'canceled' | string | undefined;
|
|
2
|
+
interface AwaitConfig {
|
|
3
|
+
type: 'time' | 'event' | 'webhook' | 'schedule';
|
|
4
|
+
delay?: number;
|
|
5
|
+
event?: string;
|
|
6
|
+
method?: string;
|
|
7
|
+
timeout?: number;
|
|
8
|
+
timeoutAction?: 'fail' | 'continue';
|
|
9
|
+
cron?: string;
|
|
10
|
+
}
|
|
2
11
|
type __VLS_Props = {
|
|
3
12
|
id: string;
|
|
4
13
|
data: {
|
|
@@ -10,20 +19,14 @@ type __VLS_Props = {
|
|
|
10
19
|
error?: string;
|
|
11
20
|
runtime?: 'nodejs' | 'python';
|
|
12
21
|
runtype?: 'inprocess' | 'task';
|
|
22
|
+
subscribes?: string[];
|
|
13
23
|
emits?: string[];
|
|
24
|
+
awaitBefore?: AwaitConfig;
|
|
25
|
+
awaitAfter?: AwaitConfig;
|
|
26
|
+
stepTimeout?: number;
|
|
14
27
|
};
|
|
15
28
|
kind?: 'entry' | 'step';
|
|
16
29
|
};
|
|
17
|
-
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
18
|
-
action: (payload: {
|
|
19
|
-
id: string;
|
|
20
|
-
action: "run" | "logs" | "details";
|
|
21
|
-
}) => any;
|
|
22
|
-
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
23
|
-
onAction?: ((payload: {
|
|
24
|
-
id: string;
|
|
25
|
-
action: "run" | "logs" | "details";
|
|
26
|
-
}) => any) | undefined;
|
|
27
|
-
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
30
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
28
31
|
declare const _default: typeof __VLS_export;
|
|
29
32
|
export default _default;
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<UCard
|
|
3
|
-
class="min-w-[
|
|
3
|
+
class="min-w-[260px] max-w-[340px]"
|
|
4
4
|
:ui="{
|
|
5
5
|
body: 'p-0',
|
|
6
|
-
header: headerClass
|
|
7
|
-
footer: footerClass
|
|
6
|
+
header: headerClass
|
|
8
7
|
}"
|
|
9
8
|
>
|
|
10
9
|
<template #header>
|
|
@@ -23,24 +22,49 @@
|
|
|
23
22
|
{{ data?.label }}
|
|
24
23
|
</p>
|
|
25
24
|
</div>
|
|
26
|
-
<
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
<div class="flex items-center gap-2">
|
|
26
|
+
<span
|
|
27
|
+
v-if="data?.stepTimeout !== void 0 && data.stepTimeout > 0"
|
|
28
|
+
class="flex items-center gap-1 text-xs opacity-80"
|
|
29
|
+
:title="`Step Execution Timeout: ${formatStepTimeout(data.stepTimeout)}`"
|
|
30
|
+
>
|
|
31
|
+
<UIcon
|
|
32
|
+
name="i-heroicons-clock-20-solid"
|
|
33
|
+
class="size-3"
|
|
34
|
+
/>
|
|
35
|
+
<span>{{ formatStepTimeout(data.stepTimeout) }}</span>
|
|
36
|
+
</span>
|
|
37
|
+
<UBadge
|
|
38
|
+
:label="(data?.status || 'idle').toUpperCase()"
|
|
39
|
+
size="xs"
|
|
40
|
+
:color="statusColor(data?.status)"
|
|
41
|
+
/>
|
|
42
|
+
</div>
|
|
31
43
|
</div>
|
|
32
44
|
</template>
|
|
33
45
|
|
|
34
46
|
<div class="px-3 py-2 text-xs space-y-1">
|
|
35
47
|
<div class="flex items-center justify-between">
|
|
36
|
-
<span class="text-gray-500 dark:text-gray-400">
|
|
48
|
+
<span class="text-gray-500 dark:text-gray-400 flex items-center gap-1">
|
|
49
|
+
<UIcon
|
|
50
|
+
name="i-heroicons-queue-list-20-solid"
|
|
51
|
+
class="size-3"
|
|
52
|
+
/>
|
|
53
|
+
Queue
|
|
54
|
+
</span>
|
|
37
55
|
<span
|
|
38
56
|
class="truncate ml-2 font-mono"
|
|
39
57
|
:title="data?.queue"
|
|
40
58
|
>{{ data?.queue || "-" }}</span>
|
|
41
59
|
</div>
|
|
42
60
|
<div class="flex items-center justify-between">
|
|
43
|
-
<span class="text-gray-500 dark:text-gray-400">
|
|
61
|
+
<span class="text-gray-500 dark:text-gray-400 flex items-center gap-1">
|
|
62
|
+
<UIcon
|
|
63
|
+
name="i-heroicons-cpu-chip-20-solid"
|
|
64
|
+
class="size-3"
|
|
65
|
+
/>
|
|
66
|
+
Worker
|
|
67
|
+
</span>
|
|
44
68
|
<span
|
|
45
69
|
class="truncate ml-2 font-mono"
|
|
46
70
|
:title="data?.workerId"
|
|
@@ -58,11 +82,39 @@
|
|
|
58
82
|
variant="soft"
|
|
59
83
|
/>
|
|
60
84
|
</div>
|
|
85
|
+
<div
|
|
86
|
+
v-if="data?.subscribes && data.subscribes.length > 0"
|
|
87
|
+
class="flex items-start justify-between gap-2"
|
|
88
|
+
>
|
|
89
|
+
<span class="text-gray-500 dark:text-gray-400 flex items-center gap-1">
|
|
90
|
+
<UIcon
|
|
91
|
+
name="i-heroicons-arrow-down-on-square-stack-20-solid"
|
|
92
|
+
class="size-3"
|
|
93
|
+
/>
|
|
94
|
+
Subscribes
|
|
95
|
+
</span>
|
|
96
|
+
<div class="flex flex-wrap gap-1 justify-end">
|
|
97
|
+
<UBadge
|
|
98
|
+
v-for="event in data.subscribes"
|
|
99
|
+
:key="event"
|
|
100
|
+
:label="event"
|
|
101
|
+
size="xs"
|
|
102
|
+
color="blue"
|
|
103
|
+
variant="soft"
|
|
104
|
+
/>
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
61
107
|
<div
|
|
62
108
|
v-if="data?.emits && data.emits.length > 0"
|
|
63
109
|
class="flex items-start justify-between gap-2"
|
|
64
110
|
>
|
|
65
|
-
<span class="text-gray-500 dark:text-gray-400">
|
|
111
|
+
<span class="text-gray-500 dark:text-gray-400 flex items-center gap-1">
|
|
112
|
+
<UIcon
|
|
113
|
+
name="i-heroicons-arrow-up-on-square-stack-20-solid"
|
|
114
|
+
class="size-3"
|
|
115
|
+
/>
|
|
116
|
+
Emits
|
|
117
|
+
</span>
|
|
66
118
|
<div class="flex flex-wrap gap-1 justify-end">
|
|
67
119
|
<UBadge
|
|
68
120
|
v-for="event in data.emits"
|
|
@@ -74,6 +126,42 @@
|
|
|
74
126
|
/>
|
|
75
127
|
</div>
|
|
76
128
|
</div>
|
|
129
|
+
<div
|
|
130
|
+
v-if="data?.awaitBefore"
|
|
131
|
+
class="flex items-center justify-between"
|
|
132
|
+
>
|
|
133
|
+
<span class="text-gray-500 dark:text-gray-400 flex items-center gap-1">
|
|
134
|
+
<UIcon
|
|
135
|
+
name="i-heroicons-clock-20-solid"
|
|
136
|
+
class="size-3"
|
|
137
|
+
/>
|
|
138
|
+
Await Before
|
|
139
|
+
</span>
|
|
140
|
+
<UBadge
|
|
141
|
+
:label="data.awaitBefore.type"
|
|
142
|
+
size="xs"
|
|
143
|
+
color="violet"
|
|
144
|
+
variant="soft"
|
|
145
|
+
/>
|
|
146
|
+
</div>
|
|
147
|
+
<div
|
|
148
|
+
v-if="data?.awaitAfter"
|
|
149
|
+
class="flex items-center justify-between"
|
|
150
|
+
>
|
|
151
|
+
<span class="text-gray-500 dark:text-gray-400 flex items-center gap-1">
|
|
152
|
+
<UIcon
|
|
153
|
+
name="i-heroicons-clock-20-solid"
|
|
154
|
+
class="size-3"
|
|
155
|
+
/>
|
|
156
|
+
Await After
|
|
157
|
+
</span>
|
|
158
|
+
<UBadge
|
|
159
|
+
:label="data.awaitAfter.type"
|
|
160
|
+
size="xs"
|
|
161
|
+
color="violet"
|
|
162
|
+
variant="soft"
|
|
163
|
+
/>
|
|
164
|
+
</div>
|
|
77
165
|
<div
|
|
78
166
|
v-if="data?.attempt && data.attempt > 1"
|
|
79
167
|
class="flex items-center justify-between"
|
|
@@ -95,25 +183,6 @@
|
|
|
95
183
|
</span>
|
|
96
184
|
</div>
|
|
97
185
|
</div>
|
|
98
|
-
|
|
99
|
-
<template #footer>
|
|
100
|
-
<div class="flex items-center justify-center gap-2 w-full">
|
|
101
|
-
<UButton
|
|
102
|
-
size="xs"
|
|
103
|
-
color="neutral"
|
|
104
|
-
label="Logs"
|
|
105
|
-
icon="i-heroicons-document-text-20-solid"
|
|
106
|
-
@click="handleAction('logs')"
|
|
107
|
-
/>
|
|
108
|
-
<UButton
|
|
109
|
-
size="xs"
|
|
110
|
-
color="neutral"
|
|
111
|
-
label="Details"
|
|
112
|
-
icon="i-heroicons-information-circle-20-solid"
|
|
113
|
-
@click="handleAction('details')"
|
|
114
|
-
/>
|
|
115
|
-
</div>
|
|
116
|
-
</template>
|
|
117
186
|
</UCard>
|
|
118
187
|
</template>
|
|
119
188
|
|
|
@@ -124,12 +193,7 @@ const props = defineProps({
|
|
|
124
193
|
data: { type: Object, required: true },
|
|
125
194
|
kind: { type: String, required: false }
|
|
126
195
|
});
|
|
127
|
-
const emit = defineEmits(["action"]);
|
|
128
|
-
function handleAction(action) {
|
|
129
|
-
emit("action", { id: props.id, action });
|
|
130
|
-
}
|
|
131
196
|
const headerClass = computed(() => props.kind === "entry" ? "px-3 py-2 bg-gradient-to-br from-emerald-800 to-emerald-700 text-emerald-50 rounded-t" : "px-3 py-2 bg-gradient-to-br from-gray-800 to-gray-700 text-gray-100 rounded-t");
|
|
132
|
-
const footerClass = computed(() => props.kind === "entry" ? "px-3 pb-2 pt-1" : "px-3 pb-2 pt-1");
|
|
133
197
|
const runnerIcon = computed(() => {
|
|
134
198
|
const runtime = props.data?.runtime;
|
|
135
199
|
if (runtime === "python") {
|
|
@@ -154,4 +218,24 @@ function statusColor(status) {
|
|
|
154
218
|
return "neutral";
|
|
155
219
|
}
|
|
156
220
|
}
|
|
221
|
+
function formatStepTimeout(ms) {
|
|
222
|
+
if (!ms || ms === 0) return "None";
|
|
223
|
+
const seconds = Math.floor(ms / 1e3);
|
|
224
|
+
const minutes = Math.floor(seconds / 60);
|
|
225
|
+
const hours = Math.floor(minutes / 60);
|
|
226
|
+
const days = Math.floor(hours / 24);
|
|
227
|
+
if (days > 0) {
|
|
228
|
+
const remainingHours = hours % 24;
|
|
229
|
+
return remainingHours > 0 ? `${days}d ${remainingHours}h` : `${days}d`;
|
|
230
|
+
}
|
|
231
|
+
if (hours > 0) {
|
|
232
|
+
const remainingMinutes = minutes % 60;
|
|
233
|
+
return remainingMinutes > 0 ? `${hours}h ${remainingMinutes}m` : `${hours}h`;
|
|
234
|
+
}
|
|
235
|
+
if (minutes > 0) {
|
|
236
|
+
const remainingSeconds = seconds % 60;
|
|
237
|
+
return remainingSeconds > 0 ? `${minutes}m ${remainingSeconds}s` : `${minutes}m`;
|
|
238
|
+
}
|
|
239
|
+
return `${seconds}s`;
|
|
240
|
+
}
|
|
157
241
|
</script>
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
type Status = 'idle' | 'running' | 'error' | 'done' | 'canceled' | string | undefined;
|
|
2
|
+
interface AwaitConfig {
|
|
3
|
+
type: 'time' | 'event' | 'webhook' | 'schedule';
|
|
4
|
+
delay?: number;
|
|
5
|
+
event?: string;
|
|
6
|
+
method?: string;
|
|
7
|
+
timeout?: number;
|
|
8
|
+
timeoutAction?: 'fail' | 'continue';
|
|
9
|
+
cron?: string;
|
|
10
|
+
}
|
|
2
11
|
type __VLS_Props = {
|
|
3
12
|
id: string;
|
|
4
13
|
data: {
|
|
@@ -10,20 +19,14 @@ type __VLS_Props = {
|
|
|
10
19
|
error?: string;
|
|
11
20
|
runtime?: 'nodejs' | 'python';
|
|
12
21
|
runtype?: 'inprocess' | 'task';
|
|
22
|
+
subscribes?: string[];
|
|
13
23
|
emits?: string[];
|
|
24
|
+
awaitBefore?: AwaitConfig;
|
|
25
|
+
awaitAfter?: AwaitConfig;
|
|
26
|
+
stepTimeout?: number;
|
|
14
27
|
};
|
|
15
28
|
kind?: 'entry' | 'step';
|
|
16
29
|
};
|
|
17
|
-
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
18
|
-
action: (payload: {
|
|
19
|
-
id: string;
|
|
20
|
-
action: "run" | "logs" | "details";
|
|
21
|
-
}) => any;
|
|
22
|
-
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
23
|
-
onAction?: ((payload: {
|
|
24
|
-
id: string;
|
|
25
|
-
action: "run" | "logs" | "details";
|
|
26
|
-
}) => any) | undefined;
|
|
27
|
-
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
30
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
28
31
|
declare const _default: typeof __VLS_export;
|
|
29
32
|
export default _default;
|
|
@@ -8,6 +8,7 @@ type __VLS_Props = {
|
|
|
8
8
|
triggerName?: string;
|
|
9
9
|
triggerType?: 'manual' | 'event' | 'webhook' | 'schedule';
|
|
10
10
|
flowDef?: any;
|
|
11
|
+
stallTimeout?: number;
|
|
11
12
|
};
|
|
12
13
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
13
14
|
"select-step": (stepKey: string | null) => any;
|