@nvent-addon/app 0.5.14 → 1.0.0-alpha.1
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 +3 -2
- package/dist/runtime/app/components/DashboardCard.d.vue.ts +1 -1
- package/dist/runtime/app/components/DashboardCard.vue.d.ts +1 -1
- package/dist/runtime/app/composables/useWorkers.d.ts +57 -0
- package/dist/runtime/app/composables/useWorkers.js +42 -0
- package/dist/runtime/app/pages/dashboard.vue +1 -654
- package/dist/runtime/app/pages/index.vue +25 -41
- package/dist/runtime/app/pages/workers.vue +458 -0
- package/dist/runtime/server/api/_workers/index.get.d.ts +8 -0
- package/dist/runtime/server/api/_workers/index.get.js +14 -0
- package/package.json +12 -11
- package/dist/runtime/app/components/ComponentRouter.d.vue.ts +0 -46
- package/dist/runtime/app/components/ComponentRouter.vue +0 -26
- package/dist/runtime/app/components/ComponentRouter.vue.d.ts +0 -46
- package/dist/runtime/app/components/ComponentShell.d.vue.ts +0 -23
- package/dist/runtime/app/components/ComponentShell.vue +0 -97
- package/dist/runtime/app/components/ComponentShell.vue.d.ts +0 -23
- package/dist/runtime/app/components/ConfirmDialog.d.vue.ts +0 -33
- package/dist/runtime/app/components/ConfirmDialog.vue +0 -120
- package/dist/runtime/app/components/ConfirmDialog.vue.d.ts +0 -33
- package/dist/runtime/app/composables/useComponentRouter.d.ts +0 -46
- package/dist/runtime/app/composables/useComponentRouter.js +0 -248
- package/dist/runtime/app/pages/flows/[name].vue +0 -750
- package/dist/runtime/app/pages/flows/index.d.vue.ts +0 -3
- package/dist/runtime/app/pages/flows/index.vue +0 -381
- package/dist/runtime/app/pages/flows/index.vue.d.ts +0 -3
- package/dist/runtime/app/pages/queues/index.d.vue.ts +0 -3
- package/dist/runtime/app/pages/queues/index.vue +0 -236
- package/dist/runtime/app/pages/queues/index.vue.d.ts +0 -3
- package/dist/runtime/app/pages/queues/job.d.vue.ts +0 -3
- package/dist/runtime/app/pages/queues/job.vue +0 -261
- package/dist/runtime/app/pages/queues/job.vue.d.ts +0 -3
- package/dist/runtime/app/pages/queues/jobs.d.vue.ts +0 -3
- package/dist/runtime/app/pages/queues/jobs.vue +0 -595
- package/dist/runtime/app/pages/queues/jobs.vue.d.ts +0 -3
- package/dist/runtime/app/pages/settings/scheduler.d.vue.ts +0 -3
- package/dist/runtime/app/pages/settings/scheduler.vue +0 -310
- package/dist/runtime/app/pages/settings/scheduler.vue.d.ts +0 -3
- package/dist/runtime/app/pages/triggers/[name]/edit.d.vue.ts +0 -3
- package/dist/runtime/app/pages/triggers/[name]/edit.vue +0 -429
- package/dist/runtime/app/pages/triggers/[name]/edit.vue.d.ts +0 -3
- package/dist/runtime/app/pages/triggers/[name].d.vue.ts +0 -3
- package/dist/runtime/app/pages/triggers/[name].vue +0 -870
- package/dist/runtime/app/pages/triggers/[name].vue.d.ts +0 -3
- package/dist/runtime/app/pages/triggers/index.d.vue.ts +0 -3
- package/dist/runtime/app/pages/triggers/index.vue +0 -525
- package/dist/runtime/app/pages/triggers/index.vue.d.ts +0 -3
- package/dist/runtime/app/pages/triggers/new.d.vue.ts +0 -3
- package/dist/runtime/app/pages/triggers/new.vue +0 -610
- package/dist/runtime/app/pages/triggers/new.vue.d.ts +0 -3
- package/dist/runtime/server/api/_flows/[name]/clear-history.delete.d.ts +0 -10
- package/dist/runtime/server/api/_flows/[name]/clear-history.delete.js +0 -49
- package/dist/runtime/server/api/_flows/[name]/runs/[runId]/cancel.post.d.ts +0 -2
- package/dist/runtime/server/api/_flows/[name]/runs/[runId]/cancel.post.js +0 -21
- package/dist/runtime/server/api/_flows/[name]/runs/[runId]/restart.post.d.ts +0 -2
- package/dist/runtime/server/api/_flows/[name]/runs/[runId]/restart.post.js +0 -21
- package/dist/runtime/server/api/_flows/[name]/runs.get.d.ts +0 -17
- package/dist/runtime/server/api/_flows/[name]/runs.get.js +0 -64
- package/dist/runtime/server/api/_flows/[name]/start.post.d.ts +0 -2
- package/dist/runtime/server/api/_flows/[name]/start.post.js +0 -9
- package/dist/runtime/server/api/_flows/index.get.d.ts +0 -7
- package/dist/runtime/server/api/_flows/index.get.js +0 -5
- package/dist/runtime/server/api/_flows/recent-runs.get.d.ts +0 -15
- package/dist/runtime/server/api/_flows/recent-runs.get.js +0 -67
- package/dist/runtime/server/api/_flows/ws.d.ts +0 -80
- package/dist/runtime/server/api/_flows/ws.js +0 -309
- package/dist/runtime/server/api/_queues/[name]/job/[id].get.d.ts +0 -2
- package/dist/runtime/server/api/_queues/[name]/job/[id].get.js +0 -14
- package/dist/runtime/server/api/_queues/[name]/job/index.get.d.ts +0 -2
- package/dist/runtime/server/api/_queues/[name]/job/index.get.js +0 -39
- package/dist/runtime/server/api/_queues/index.get.d.ts +0 -2
- package/dist/runtime/server/api/_queues/index.get.js +0 -106
- package/dist/runtime/server/api/_queues/ws.d.ts +0 -48
- package/dist/runtime/server/api/_queues/ws.js +0 -215
- package/dist/runtime/server/api/_scheduler/jobs.get.d.ts +0 -19
- package/dist/runtime/server/api/_scheduler/jobs.get.js +0 -36
- package/dist/runtime/server/api/_triggers/[name]/events.get.d.ts +0 -6
- package/dist/runtime/server/api/_triggers/[name]/events.get.js +0 -43
- package/dist/runtime/server/api/_triggers/[name]/index.get.d.ts +0 -6
- package/dist/runtime/server/api/_triggers/[name]/index.get.js +0 -76
- package/dist/runtime/server/api/_triggers/[name].delete.d.ts +0 -7
- package/dist/runtime/server/api/_triggers/[name].delete.js +0 -37
- package/dist/runtime/server/api/_triggers/[name].patch.d.ts +0 -7
- package/dist/runtime/server/api/_triggers/[name].patch.js +0 -117
- package/dist/runtime/server/api/_triggers/index.get.d.ts +0 -6
- package/dist/runtime/server/api/_triggers/index.get.js +0 -44
- package/dist/runtime/server/api/_triggers/index.post.d.ts +0 -7
- package/dist/runtime/server/api/_triggers/index.post.js +0 -124
- package/dist/runtime/server/api/_triggers/stats.get.d.ts +0 -6
- package/dist/runtime/server/api/_triggers/stats.get.js +0 -41
- package/dist/runtime/server/api/_triggers/ws.d.ts +0 -74
- package/dist/runtime/server/api/_triggers/ws.js +0 -315
- /package/dist/runtime/app/pages/{flows/[name].d.vue.ts → workers.d.vue.ts} +0 -0
- /package/dist/runtime/app/pages/{flows/[name].vue.d.ts → workers.vue.d.ts} +0 -0
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
2
|
-
declare const _default: typeof __VLS_export;
|
|
3
|
-
export default _default;
|
|
@@ -1,381 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="h-full flex flex-col overflow-hidden">
|
|
3
|
-
<!-- Header -->
|
|
4
|
-
<div class="border-b border-gray-200 dark:border-gray-800 px-6 py-3 shrink-0">
|
|
5
|
-
<div class="flex items-center justify-between">
|
|
6
|
-
<div class="flex items-center gap-4">
|
|
7
|
-
<h1 class="text-lg font-semibold">
|
|
8
|
-
Flows
|
|
9
|
-
</h1>
|
|
10
|
-
</div>
|
|
11
|
-
<LiveIndicator
|
|
12
|
-
:is-connected="flowWs.connected.value"
|
|
13
|
-
:is-reconnecting="flowWs.reconnecting.value"
|
|
14
|
-
/>
|
|
15
|
-
</div>
|
|
16
|
-
</div>
|
|
17
|
-
|
|
18
|
-
<!-- Main Content -->
|
|
19
|
-
<div class="flex-1 min-h-0 overflow-y-auto">
|
|
20
|
-
<div class="max-w-7xl mx-auto p-6">
|
|
21
|
-
<!-- Stats Overview -->
|
|
22
|
-
<div class="grid grid-cols-2 md:grid-cols-6 gap-4 mb-6">
|
|
23
|
-
<StatCard
|
|
24
|
-
icon="i-lucide-git-branch"
|
|
25
|
-
:count="flows?.length || 0"
|
|
26
|
-
label="Total Flows"
|
|
27
|
-
variant="gray"
|
|
28
|
-
/>
|
|
29
|
-
<StatCard
|
|
30
|
-
icon="i-lucide-play"
|
|
31
|
-
:count="totalRuns"
|
|
32
|
-
label="Total Runs"
|
|
33
|
-
variant="blue"
|
|
34
|
-
/>
|
|
35
|
-
<StatCard
|
|
36
|
-
icon="i-lucide-check-circle"
|
|
37
|
-
:count="totalSuccess"
|
|
38
|
-
label="Success"
|
|
39
|
-
variant="emerald"
|
|
40
|
-
/>
|
|
41
|
-
<StatCard
|
|
42
|
-
icon="i-lucide-x-circle"
|
|
43
|
-
:count="totalFailure"
|
|
44
|
-
label="Failures"
|
|
45
|
-
variant="red"
|
|
46
|
-
/>
|
|
47
|
-
<StatCard
|
|
48
|
-
icon="i-lucide-loader"
|
|
49
|
-
:count="totalRunning"
|
|
50
|
-
label="Running"
|
|
51
|
-
variant="purple"
|
|
52
|
-
/>
|
|
53
|
-
<StatCard
|
|
54
|
-
icon="i-lucide-pause"
|
|
55
|
-
:count="totalAwaiting"
|
|
56
|
-
label="Awaiting"
|
|
57
|
-
variant="amber"
|
|
58
|
-
/>
|
|
59
|
-
</div>
|
|
60
|
-
|
|
61
|
-
<!-- Filters -->
|
|
62
|
-
<div class="mb-4">
|
|
63
|
-
<UInput
|
|
64
|
-
v-model="searchQuery"
|
|
65
|
-
icon="i-lucide-search"
|
|
66
|
-
placeholder="Search flows..."
|
|
67
|
-
size="sm"
|
|
68
|
-
/>
|
|
69
|
-
</div>
|
|
70
|
-
|
|
71
|
-
<!-- Flows List -->
|
|
72
|
-
<div
|
|
73
|
-
v-if="!filteredFlows || filteredFlows.length === 0"
|
|
74
|
-
class="bg-white dark:bg-gray-900 rounded-lg border border-gray-200 dark:border-gray-800 p-8 text-center text-gray-500"
|
|
75
|
-
>
|
|
76
|
-
<div v-if="searchQuery">
|
|
77
|
-
<UIcon
|
|
78
|
-
name="i-lucide-search-x"
|
|
79
|
-
class="w-12 h-12 animate-spin mx-auto mb-3 opacity-50"
|
|
80
|
-
/>
|
|
81
|
-
<p>No flows match your search</p>
|
|
82
|
-
<UButton
|
|
83
|
-
size="xs"
|
|
84
|
-
color="neutral"
|
|
85
|
-
variant="ghost"
|
|
86
|
-
class="mt-2"
|
|
87
|
-
@click="searchQuery = ''"
|
|
88
|
-
>
|
|
89
|
-
Clear Search
|
|
90
|
-
</UButton>
|
|
91
|
-
</div>
|
|
92
|
-
<div v-else>
|
|
93
|
-
<UIcon
|
|
94
|
-
name="i-lucide-git-branch"
|
|
95
|
-
class="w-12 h-12 mx-auto mb-3 opacity-50"
|
|
96
|
-
/>
|
|
97
|
-
<p>No flows found</p>
|
|
98
|
-
</div>
|
|
99
|
-
</div>
|
|
100
|
-
<div
|
|
101
|
-
v-else
|
|
102
|
-
class="bg-white dark:bg-gray-900 rounded-lg border border-gray-200 dark:border-gray-800 overflow-hidden"
|
|
103
|
-
>
|
|
104
|
-
<div class="divide-y divide-gray-100 dark:divide-gray-800">
|
|
105
|
-
<div
|
|
106
|
-
v-for="flow in filteredFlows"
|
|
107
|
-
:key="flow.id"
|
|
108
|
-
class="px-6 py-4 hover:bg-gray-50 dark:hover:bg-gray-900/50 transition-colors cursor-pointer"
|
|
109
|
-
@click="openFlow(flow.id)"
|
|
110
|
-
>
|
|
111
|
-
<div class="flex items-start justify-between gap-4">
|
|
112
|
-
<!-- Left: Flow Info -->
|
|
113
|
-
<div class="flex-1 min-w-0">
|
|
114
|
-
<div class="flex items-center gap-2 mb-2">
|
|
115
|
-
<UIcon
|
|
116
|
-
name="i-lucide-git-branch"
|
|
117
|
-
class="w-4 h-4 shrink-0 text-blue-500"
|
|
118
|
-
/>
|
|
119
|
-
<h3 class="text-sm font-semibold text-gray-900 dark:text-gray-100 truncate">
|
|
120
|
-
{{ flow.id }}
|
|
121
|
-
</h3>
|
|
122
|
-
<UBadge
|
|
123
|
-
v-if="flow.hasAwait"
|
|
124
|
-
label="await"
|
|
125
|
-
color="purple"
|
|
126
|
-
variant="subtle"
|
|
127
|
-
size="xs"
|
|
128
|
-
>
|
|
129
|
-
<template #leading>
|
|
130
|
-
<UIcon
|
|
131
|
-
name="i-lucide-pause"
|
|
132
|
-
class="w-3 h-3"
|
|
133
|
-
/>
|
|
134
|
-
</template>
|
|
135
|
-
</UBadge>
|
|
136
|
-
</div>
|
|
137
|
-
|
|
138
|
-
<div class="flex items-center gap-4 text-xs text-gray-500 dark:text-gray-400">
|
|
139
|
-
<div class="flex items-center gap-1">
|
|
140
|
-
<UIcon
|
|
141
|
-
name="i-lucide-layers"
|
|
142
|
-
class="w-3 h-3"
|
|
143
|
-
/>
|
|
144
|
-
<span>{{ getStepCount(flow) }} step{{ getStepCount(flow) === 1 ? "" : "s" }}</span>
|
|
145
|
-
</div>
|
|
146
|
-
<div class="flex items-center gap-1">
|
|
147
|
-
<UIcon
|
|
148
|
-
name="i-lucide-bar-chart-3"
|
|
149
|
-
class="w-3 h-3"
|
|
150
|
-
/>
|
|
151
|
-
<span>{{ getLevelCount(flow) }} level{{ getLevelCount(flow) === 1 ? "" : "s" }}</span>
|
|
152
|
-
</div>
|
|
153
|
-
<div
|
|
154
|
-
v-if="flow.stats && flow.stats.total > 0"
|
|
155
|
-
class="flex items-center gap-2"
|
|
156
|
-
>
|
|
157
|
-
<div class="flex items-center gap-1">
|
|
158
|
-
<UIcon
|
|
159
|
-
name="i-lucide-play"
|
|
160
|
-
class="w-3 h-3"
|
|
161
|
-
/>
|
|
162
|
-
<span>{{ flow.stats.total }}</span>
|
|
163
|
-
</div>
|
|
164
|
-
<div
|
|
165
|
-
v-if="flow.stats.running > 0"
|
|
166
|
-
class="flex items-center gap-1 text-purple-600 dark:text-purple-400"
|
|
167
|
-
>
|
|
168
|
-
<UIcon
|
|
169
|
-
name="i-lucide-loader"
|
|
170
|
-
class="w-3 h-3"
|
|
171
|
-
/>
|
|
172
|
-
<span>{{ flow.stats.running }}</span>
|
|
173
|
-
</div>
|
|
174
|
-
</div>
|
|
175
|
-
<div
|
|
176
|
-
v-if="flow.timeout"
|
|
177
|
-
class="flex items-center gap-1"
|
|
178
|
-
>
|
|
179
|
-
<UIcon
|
|
180
|
-
name="i-lucide-clock"
|
|
181
|
-
class="w-3 h-3"
|
|
182
|
-
/>
|
|
183
|
-
<span>{{ formatTimeout(flow.timeout) }} timeout</span>
|
|
184
|
-
</div>
|
|
185
|
-
<!-- Runtime Badges -->
|
|
186
|
-
<div
|
|
187
|
-
v-if="getRuntimes(flow).length > 0"
|
|
188
|
-
class="flex items-center gap-1"
|
|
189
|
-
>
|
|
190
|
-
<UIcon
|
|
191
|
-
name="i-lucide-cpu"
|
|
192
|
-
class="w-3 h-3"
|
|
193
|
-
/>
|
|
194
|
-
<span>{{ getRuntimes(flow).join(", ") }}</span>
|
|
195
|
-
</div>
|
|
196
|
-
</div>
|
|
197
|
-
</div>
|
|
198
|
-
|
|
199
|
-
<!-- Right: Action -->
|
|
200
|
-
<UButton
|
|
201
|
-
icon="i-lucide-arrow-right"
|
|
202
|
-
size="xs"
|
|
203
|
-
color="neutral"
|
|
204
|
-
variant="ghost"
|
|
205
|
-
square
|
|
206
|
-
/>
|
|
207
|
-
</div>
|
|
208
|
-
</div>
|
|
209
|
-
</div>
|
|
210
|
-
</div>
|
|
211
|
-
|
|
212
|
-
<!-- Footer Info -->
|
|
213
|
-
<div
|
|
214
|
-
v-if="filteredFlows && filteredFlows.length > 0"
|
|
215
|
-
class="mt-4 text-center text-sm text-gray-500 dark:text-gray-400"
|
|
216
|
-
>
|
|
217
|
-
Showing {{ filteredFlows.length }} flow{{ filteredFlows.length === 1 ? "" : "s" }}
|
|
218
|
-
</div>
|
|
219
|
-
</div>
|
|
220
|
-
</div>
|
|
221
|
-
</div>
|
|
222
|
-
</template>
|
|
223
|
-
|
|
224
|
-
<script setup>
|
|
225
|
-
import { ref, computed, onMounted, onBeforeUnmount } from "#imports";
|
|
226
|
-
import { useComponentRouter } from "../../composables/useComponentRouter";
|
|
227
|
-
import { useFlowWebSocket } from "../../composables/useFlowWebSocket";
|
|
228
|
-
import StatCard from "../../components/StatCard.vue";
|
|
229
|
-
import LiveIndicator from "../../components/LiveIndicator.vue";
|
|
230
|
-
const router = useComponentRouter();
|
|
231
|
-
const flows = ref([]);
|
|
232
|
-
const loading = ref(true);
|
|
233
|
-
const flowWs = useFlowWebSocket();
|
|
234
|
-
async function fetchAnalyzedFlows() {
|
|
235
|
-
try {
|
|
236
|
-
const data = await $fetch("/api/_flows");
|
|
237
|
-
const analyzedFlows = data;
|
|
238
|
-
flows.value = analyzedFlows.map((flow) => ({
|
|
239
|
-
id: flow.id,
|
|
240
|
-
entry: flow.entry,
|
|
241
|
-
steps: flow.analyzed?.steps || flow.steps || {},
|
|
242
|
-
levels: flow.analyzed?.levels || [],
|
|
243
|
-
maxLevel: flow.analyzed?.maxLevel || 0,
|
|
244
|
-
stallTimeout: flow.analyzed?.stallTimeout,
|
|
245
|
-
awaitPatterns: flow.analyzed?.awaitPatterns,
|
|
246
|
-
hasAwait: flow.analyzed?.awaitPatterns?.steps?.length > 0 || false,
|
|
247
|
-
timeout: flow.timeout,
|
|
248
|
-
stats: { total: 0, success: 0, failure: 0, cancel: 0, running: 0, awaiting: 0 }
|
|
249
|
-
}));
|
|
250
|
-
} catch (err) {
|
|
251
|
-
console.error("Error fetching analyzed flows:", err);
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
function updateFlowStats(data) {
|
|
255
|
-
const flowId = data?.id;
|
|
256
|
-
if (!flowId || !flows.value)
|
|
257
|
-
return;
|
|
258
|
-
const flowIndex = flows.value.findIndex((f) => f.id === flowId);
|
|
259
|
-
if (flowIndex === -1) {
|
|
260
|
-
console.warn("[Flow Stats] Flow not found in list:", flowId);
|
|
261
|
-
return;
|
|
262
|
-
}
|
|
263
|
-
const metadata = data?.metadata;
|
|
264
|
-
if (!metadata) {
|
|
265
|
-
console.warn("[Flow Stats] No metadata in update:", data);
|
|
266
|
-
return;
|
|
267
|
-
}
|
|
268
|
-
const stats = metadata.stats || {
|
|
269
|
-
total: metadata["stats.total"] || 0,
|
|
270
|
-
success: metadata["stats.success"] || 0,
|
|
271
|
-
failure: metadata["stats.failure"] || 0,
|
|
272
|
-
cancel: metadata["stats.cancel"] || 0,
|
|
273
|
-
running: metadata["stats.running"] || 0,
|
|
274
|
-
awaiting: metadata["stats.awaiting"] || 0
|
|
275
|
-
};
|
|
276
|
-
const flow = flows.value[flowIndex];
|
|
277
|
-
flow.stats = {
|
|
278
|
-
total: stats.total || 0,
|
|
279
|
-
success: stats.success || 0,
|
|
280
|
-
failure: stats.failure || 0,
|
|
281
|
-
cancel: stats.cancel || 0,
|
|
282
|
-
running: stats.running || 0,
|
|
283
|
-
awaiting: stats.awaiting || 0
|
|
284
|
-
};
|
|
285
|
-
flow.lastRunAt = metadata.lastRunAt;
|
|
286
|
-
flow.lastCompletedAt = metadata.lastCompletedAt;
|
|
287
|
-
}
|
|
288
|
-
onMounted(async () => {
|
|
289
|
-
await fetchAnalyzedFlows();
|
|
290
|
-
if (import.meta.client) {
|
|
291
|
-
flowWs.subscribeStats(
|
|
292
|
-
{
|
|
293
|
-
onInitial: (data) => {
|
|
294
|
-
updateFlowStats(data);
|
|
295
|
-
},
|
|
296
|
-
onUpdate: (data) => {
|
|
297
|
-
updateFlowStats(data);
|
|
298
|
-
}
|
|
299
|
-
},
|
|
300
|
-
{
|
|
301
|
-
autoReconnect: true,
|
|
302
|
-
onOpen: () => {
|
|
303
|
-
loading.value = false;
|
|
304
|
-
},
|
|
305
|
-
onError: (err) => {
|
|
306
|
-
console.error("[Flow Stats] Error:", err);
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
);
|
|
310
|
-
}
|
|
311
|
-
});
|
|
312
|
-
onBeforeUnmount(() => {
|
|
313
|
-
flowWs.unsubscribeStats();
|
|
314
|
-
flowWs.stop();
|
|
315
|
-
});
|
|
316
|
-
const searchQuery = ref("");
|
|
317
|
-
const filteredFlows = computed(() => {
|
|
318
|
-
if (!flows.value)
|
|
319
|
-
return [];
|
|
320
|
-
if (searchQuery.value) {
|
|
321
|
-
const query = searchQuery.value.toLowerCase();
|
|
322
|
-
return flows.value.filter(
|
|
323
|
-
(flow) => flow.id.toLowerCase().includes(query)
|
|
324
|
-
);
|
|
325
|
-
}
|
|
326
|
-
return flows.value;
|
|
327
|
-
});
|
|
328
|
-
const totalRuns = computed(() => {
|
|
329
|
-
if (!flows.value)
|
|
330
|
-
return 0;
|
|
331
|
-
return flows.value.reduce((acc, flow) => acc + (flow.stats?.total || 0), 0);
|
|
332
|
-
});
|
|
333
|
-
const totalSuccess = computed(() => {
|
|
334
|
-
if (!flows.value)
|
|
335
|
-
return 0;
|
|
336
|
-
return flows.value.reduce((acc, flow) => acc + (flow.stats?.success || 0), 0);
|
|
337
|
-
});
|
|
338
|
-
const totalFailure = computed(() => {
|
|
339
|
-
if (!flows.value)
|
|
340
|
-
return 0;
|
|
341
|
-
return flows.value.reduce((acc, flow) => acc + (flow.stats?.failure || 0), 0);
|
|
342
|
-
});
|
|
343
|
-
const totalRunning = computed(() => {
|
|
344
|
-
if (!flows.value)
|
|
345
|
-
return 0;
|
|
346
|
-
return flows.value.reduce((acc, flow) => acc + (flow.stats?.running || 0), 0);
|
|
347
|
-
});
|
|
348
|
-
const totalAwaiting = computed(() => {
|
|
349
|
-
if (!flows.value)
|
|
350
|
-
return 0;
|
|
351
|
-
return flows.value.reduce((acc, flow) => acc + (flow.stats?.awaiting || 0), 0);
|
|
352
|
-
});
|
|
353
|
-
const getStepCount = (flow) => {
|
|
354
|
-
if (!flow.steps) return 0;
|
|
355
|
-
return Object.keys(flow.steps).length;
|
|
356
|
-
};
|
|
357
|
-
const getLevelCount = (flow) => {
|
|
358
|
-
if (!flow.levels) return 0;
|
|
359
|
-
return Array.isArray(flow.levels) ? flow.levels.length : 0;
|
|
360
|
-
};
|
|
361
|
-
const getRuntimes = (flow) => {
|
|
362
|
-
const runtimes = /* @__PURE__ */ new Set();
|
|
363
|
-
if (!flow.steps) return [];
|
|
364
|
-
for (const step of Object.values(flow.steps)) {
|
|
365
|
-
if (step.runtime) {
|
|
366
|
-
runtimes.add(step.runtime);
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
return Array.from(runtimes);
|
|
370
|
-
};
|
|
371
|
-
function formatTimeout(ms) {
|
|
372
|
-
if (ms < 1e3)
|
|
373
|
-
return `${ms}ms`;
|
|
374
|
-
if (ms < 6e4)
|
|
375
|
-
return `${ms / 1e3}s`;
|
|
376
|
-
return `${ms / 6e4}m`;
|
|
377
|
-
}
|
|
378
|
-
function openFlow(flowId) {
|
|
379
|
-
router.push(`/flows/${flowId}`);
|
|
380
|
-
}
|
|
381
|
-
</script>
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
2
|
-
declare const _default: typeof __VLS_export;
|
|
3
|
-
export default _default;
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
2
|
-
declare const _default: typeof __VLS_export;
|
|
3
|
-
export default _default;
|
|
@@ -1,236 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="h-full flex flex-col overflow-hidden">
|
|
3
|
-
<!-- Header -->
|
|
4
|
-
<div class="border-b border-gray-200 dark:border-gray-800 px-6 py-3 shrink-0">
|
|
5
|
-
<div class="flex items-center justify-between">
|
|
6
|
-
<div class="flex items-center gap-4">
|
|
7
|
-
<h1 class="text-lg font-semibold">
|
|
8
|
-
Queues
|
|
9
|
-
</h1>
|
|
10
|
-
</div>
|
|
11
|
-
<LiveIndicator
|
|
12
|
-
:is-connected="isConnected"
|
|
13
|
-
:is-reconnecting="isReconnecting"
|
|
14
|
-
/>
|
|
15
|
-
</div>
|
|
16
|
-
</div>
|
|
17
|
-
|
|
18
|
-
<!-- Main Content -->
|
|
19
|
-
<div class="flex-1 min-h-0 overflow-y-auto">
|
|
20
|
-
<div class="max-w-7xl mx-auto p-6">
|
|
21
|
-
<!-- Stats Overview -->
|
|
22
|
-
<div class="grid grid-cols-2 md:grid-cols-5 gap-4 mb-6">
|
|
23
|
-
<StatCard
|
|
24
|
-
icon="i-lucide-inbox"
|
|
25
|
-
:count="queuesWithLive?.length || 0"
|
|
26
|
-
label="Total Queues"
|
|
27
|
-
variant="gray"
|
|
28
|
-
/>
|
|
29
|
-
<StatCard
|
|
30
|
-
icon="i-lucide-clock"
|
|
31
|
-
:count="totalWaiting"
|
|
32
|
-
label="Waiting"
|
|
33
|
-
variant="blue"
|
|
34
|
-
/>
|
|
35
|
-
<StatCard
|
|
36
|
-
icon="i-lucide-loader-2"
|
|
37
|
-
:count="totalActive"
|
|
38
|
-
label="Active"
|
|
39
|
-
variant="amber"
|
|
40
|
-
/>
|
|
41
|
-
<StatCard
|
|
42
|
-
icon="i-lucide-check-circle"
|
|
43
|
-
:count="totalCompleted"
|
|
44
|
-
label="Completed"
|
|
45
|
-
variant="emerald"
|
|
46
|
-
/>
|
|
47
|
-
<StatCard
|
|
48
|
-
icon="i-lucide-x-circle"
|
|
49
|
-
:count="totalFailed"
|
|
50
|
-
label="Failed"
|
|
51
|
-
variant="red"
|
|
52
|
-
/>
|
|
53
|
-
</div>
|
|
54
|
-
|
|
55
|
-
<!-- Queues List -->
|
|
56
|
-
<div
|
|
57
|
-
v-if="!queuesWithLive || queuesWithLive.length === 0"
|
|
58
|
-
class="bg-white dark:bg-gray-900 rounded-lg border border-gray-200 dark:border-gray-800 p-8 text-center text-gray-500"
|
|
59
|
-
>
|
|
60
|
-
<UIcon
|
|
61
|
-
name="i-lucide-inbox"
|
|
62
|
-
class="w-12 h-12 mx-auto mb-3 opacity-50"
|
|
63
|
-
/>
|
|
64
|
-
<div>No queues found</div>
|
|
65
|
-
</div>
|
|
66
|
-
<div
|
|
67
|
-
v-else
|
|
68
|
-
class="bg-white dark:bg-gray-900 rounded-lg border border-gray-200 dark:border-gray-800 overflow-hidden"
|
|
69
|
-
>
|
|
70
|
-
<div class="divide-y divide-gray-100 dark:divide-gray-800">
|
|
71
|
-
<div
|
|
72
|
-
v-for="queue in paginatedQueues"
|
|
73
|
-
:key="queue.name"
|
|
74
|
-
class="px-6 py-4 hover:bg-gray-50 dark:hover:bg-gray-900/50 transition-colors cursor-pointer"
|
|
75
|
-
@click="selectQueue(queue.name)"
|
|
76
|
-
>
|
|
77
|
-
<div class="flex items-start justify-between gap-4">
|
|
78
|
-
<!-- Left: Queue Info -->
|
|
79
|
-
<div class="flex-1 min-w-0">
|
|
80
|
-
<div class="flex items-center gap-2 mb-2">
|
|
81
|
-
<UIcon
|
|
82
|
-
name="i-lucide-inbox"
|
|
83
|
-
class="w-4 h-4 shrink-0 text-blue-500"
|
|
84
|
-
/>
|
|
85
|
-
<h3 class="text-sm font-semibold text-gray-900 dark:text-gray-100 truncate">
|
|
86
|
-
{{ queue.name }}
|
|
87
|
-
</h3>
|
|
88
|
-
<UBadge
|
|
89
|
-
:label="queue.isPaused ? 'Paused' : 'Running'"
|
|
90
|
-
:color="queue.isPaused ? 'warning' : 'success'"
|
|
91
|
-
variant="subtle"
|
|
92
|
-
size="xs"
|
|
93
|
-
/>
|
|
94
|
-
</div>
|
|
95
|
-
|
|
96
|
-
<div class="flex items-center gap-4 text-xs">
|
|
97
|
-
<div
|
|
98
|
-
class="flex items-center gap-1"
|
|
99
|
-
:class="queue.counts.waiting > 0 ? 'text-blue-600 dark:text-blue-400' : 'text-gray-400 dark:text-gray-600'"
|
|
100
|
-
>
|
|
101
|
-
<UIcon
|
|
102
|
-
name="i-lucide-clock"
|
|
103
|
-
class="w-3 h-3"
|
|
104
|
-
/>
|
|
105
|
-
<span>{{ queue.counts.waiting }} waiting</span>
|
|
106
|
-
</div>
|
|
107
|
-
<div
|
|
108
|
-
class="flex items-center gap-1"
|
|
109
|
-
:class="queue.counts.active > 0 ? 'text-amber-600 dark:text-amber-400' : 'text-gray-400 dark:text-gray-600'"
|
|
110
|
-
>
|
|
111
|
-
<UIcon
|
|
112
|
-
name="i-lucide-loader-2"
|
|
113
|
-
class="w-3 h-3"
|
|
114
|
-
/>
|
|
115
|
-
<span>{{ queue.counts.active }} active</span>
|
|
116
|
-
</div>
|
|
117
|
-
<div
|
|
118
|
-
class="flex items-center gap-1"
|
|
119
|
-
:class="queue.counts.completed > 0 ? 'text-emerald-600 dark:text-emerald-400' : 'text-gray-400 dark:text-gray-600'"
|
|
120
|
-
>
|
|
121
|
-
<UIcon
|
|
122
|
-
name="i-lucide-check-circle"
|
|
123
|
-
class="w-3 h-3"
|
|
124
|
-
/>
|
|
125
|
-
<span>{{ queue.counts.completed }} completed</span>
|
|
126
|
-
</div>
|
|
127
|
-
<div
|
|
128
|
-
class="flex items-center gap-1"
|
|
129
|
-
:class="queue.counts.failed > 0 ? 'text-red-600 dark:text-red-400' : 'text-gray-400 dark:text-gray-600'"
|
|
130
|
-
>
|
|
131
|
-
<UIcon
|
|
132
|
-
name="i-lucide-x-circle"
|
|
133
|
-
class="w-3 h-3"
|
|
134
|
-
/>
|
|
135
|
-
<span>{{ queue.counts.failed }} failed</span>
|
|
136
|
-
</div>
|
|
137
|
-
<div
|
|
138
|
-
class="flex items-center gap-1"
|
|
139
|
-
:class="queue.counts.delayed > 0 ? 'text-purple-600 dark:text-purple-400' : 'text-gray-400 dark:text-gray-600'"
|
|
140
|
-
>
|
|
141
|
-
<UIcon
|
|
142
|
-
name="i-lucide-timer"
|
|
143
|
-
class="w-3 h-3"
|
|
144
|
-
/>
|
|
145
|
-
<span>{{ queue.counts.delayed }} delayed</span>
|
|
146
|
-
</div>
|
|
147
|
-
</div>
|
|
148
|
-
</div>
|
|
149
|
-
|
|
150
|
-
<!-- Right: Actions -->
|
|
151
|
-
<div class="flex items-center gap-3">
|
|
152
|
-
<!-- Arrow Button -->
|
|
153
|
-
<UButton
|
|
154
|
-
icon="i-lucide-arrow-right"
|
|
155
|
-
size="xs"
|
|
156
|
-
color="neutral"
|
|
157
|
-
variant="ghost"
|
|
158
|
-
square
|
|
159
|
-
/>
|
|
160
|
-
</div>
|
|
161
|
-
</div>
|
|
162
|
-
</div>
|
|
163
|
-
</div>
|
|
164
|
-
|
|
165
|
-
<!-- Pagination -->
|
|
166
|
-
<div
|
|
167
|
-
v-if="totalPages > 1"
|
|
168
|
-
class="border-t border-gray-200 dark:border-gray-800 px-6 py-4 flex items-center justify-center"
|
|
169
|
-
>
|
|
170
|
-
<UPagination
|
|
171
|
-
v-model="currentPage"
|
|
172
|
-
:total="queuesWithLive.length"
|
|
173
|
-
:items-per-page="itemsPerPage"
|
|
174
|
-
/>
|
|
175
|
-
</div>
|
|
176
|
-
</div>
|
|
177
|
-
|
|
178
|
-
<!-- Footer Info -->
|
|
179
|
-
<div
|
|
180
|
-
v-if="queuesWithLive && queuesWithLive.length > 0"
|
|
181
|
-
class="mt-4 text-center text-sm text-gray-500 dark:text-gray-400"
|
|
182
|
-
>
|
|
183
|
-
Showing {{ startIndex + 1 }}-{{ endIndex }} of {{ queuesWithLive.length }} queue{{ queuesWithLive.length === 1 ? "" : "s" }}
|
|
184
|
-
</div>
|
|
185
|
-
</div>
|
|
186
|
-
</div>
|
|
187
|
-
</div>
|
|
188
|
-
</template>
|
|
189
|
-
|
|
190
|
-
<script setup>
|
|
191
|
-
import { ref, computed } from "#imports";
|
|
192
|
-
import { useQueues } from "../../composables/useQueues";
|
|
193
|
-
import { useQueuesLive } from "../../composables/useQueuesLive";
|
|
194
|
-
import { useComponentRouter } from "../../composables/useComponentRouter";
|
|
195
|
-
import StatCard from "../../components/StatCard.vue";
|
|
196
|
-
import LiveIndicator from "../../components/LiveIndicator.vue";
|
|
197
|
-
const { queues } = useQueues();
|
|
198
|
-
const { queues: queuesWithLive, isConnected, isReconnecting } = useQueuesLive(queues);
|
|
199
|
-
const router = useComponentRouter();
|
|
200
|
-
const selectQueue = (queueName) => {
|
|
201
|
-
router.push(`/queues/${queueName}/jobs`);
|
|
202
|
-
};
|
|
203
|
-
const currentPage = ref(1);
|
|
204
|
-
const itemsPerPage = 10;
|
|
205
|
-
const totalPages = computed(() => {
|
|
206
|
-
if (!queuesWithLive.value) return 0;
|
|
207
|
-
return Math.ceil(queuesWithLive.value.length / itemsPerPage);
|
|
208
|
-
});
|
|
209
|
-
const startIndex = computed(() => {
|
|
210
|
-
return (currentPage.value - 1) * itemsPerPage;
|
|
211
|
-
});
|
|
212
|
-
const endIndex = computed(() => {
|
|
213
|
-
if (!queuesWithLive.value) return 0;
|
|
214
|
-
return Math.min(startIndex.value + itemsPerPage, queuesWithLive.value.length);
|
|
215
|
-
});
|
|
216
|
-
const paginatedQueues = computed(() => {
|
|
217
|
-
if (!queuesWithLive.value) return [];
|
|
218
|
-
return queuesWithLive.value.slice(startIndex.value, endIndex.value);
|
|
219
|
-
});
|
|
220
|
-
const totalWaiting = computed(() => {
|
|
221
|
-
if (!queuesWithLive.value) return 0;
|
|
222
|
-
return queuesWithLive.value.reduce((sum, q) => sum + q.counts.waiting, 0);
|
|
223
|
-
});
|
|
224
|
-
const totalActive = computed(() => {
|
|
225
|
-
if (!queuesWithLive.value) return 0;
|
|
226
|
-
return queuesWithLive.value.reduce((sum, q) => sum + q.counts.active, 0);
|
|
227
|
-
});
|
|
228
|
-
const totalCompleted = computed(() => {
|
|
229
|
-
if (!queuesWithLive.value) return 0;
|
|
230
|
-
return queuesWithLive.value.reduce((sum, q) => sum + q.counts.completed, 0);
|
|
231
|
-
});
|
|
232
|
-
const totalFailed = computed(() => {
|
|
233
|
-
if (!queuesWithLive.value) return 0;
|
|
234
|
-
return queuesWithLive.value.reduce((sum, q) => sum + q.counts.failed, 0);
|
|
235
|
-
});
|
|
236
|
-
</script>
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
2
|
-
declare const _default: typeof __VLS_export;
|
|
3
|
-
export default _default;
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
2
|
-
declare const _default: typeof __VLS_export;
|
|
3
|
-
export default _default;
|