@nvent-addon/app 0.5.15 → 1.0.0-alpha.10
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 +13 -12
- 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
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
</p>
|
|
13
13
|
</div>
|
|
14
14
|
<div
|
|
15
|
-
v-if="isConnected"
|
|
16
15
|
class="flex items-center gap-1.5 text-xs text-emerald-600 dark:text-emerald-400"
|
|
17
16
|
>
|
|
18
17
|
<div class="w-2 h-2 rounded-full bg-emerald-500 animate-pulse" />
|
|
@@ -24,662 +23,10 @@
|
|
|
24
23
|
<!-- Main Content -->
|
|
25
24
|
<div class="flex-1 min-h-0 overflow-y-auto p-6">
|
|
26
25
|
<div class="max-w-7xl mx-auto space-y-6">
|
|
27
|
-
<!-- System Stats Overview -->
|
|
28
|
-
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
29
|
-
<!-- Queues Card -->
|
|
30
|
-
<NventDashboardCard
|
|
31
|
-
icon="i-lucide-app-window"
|
|
32
|
-
title="Active Queues"
|
|
33
|
-
color="blue"
|
|
34
|
-
:primary-stats="[
|
|
35
|
-
{ value: formatNumber(queuesStats?.active || 0), label: 'active' },
|
|
36
|
-
{ value: formatNumber((queuesStats?.waiting || 0) + (queuesStats?.delayed || 0)), label: 'waiting' },
|
|
37
|
-
...queuesStats?.failed > 0 ? [{ value: formatNumber(queuesStats?.failed || 0), label: 'failed' }] : []
|
|
38
|
-
]"
|
|
39
|
-
:secondary-stats="[
|
|
40
|
-
{ value: queuesStats?.total || 0, label: 'queues' },
|
|
41
|
-
{ value: formatNumber(queuesStats?.completed || 0), label: 'completed' }
|
|
42
|
-
]"
|
|
43
|
-
:on-click="() => navigateTo('/queues')"
|
|
44
|
-
/>
|
|
45
|
-
|
|
46
|
-
<!-- Flows Card -->
|
|
47
|
-
<NventDashboardCard
|
|
48
|
-
icon="i-lucide-git-branch"
|
|
49
|
-
title="Registered Flows"
|
|
50
|
-
color="purple"
|
|
51
|
-
:primary-stats="[
|
|
52
|
-
...flowsStats?.running > 0 ? [{ value: flowsStats?.running, label: 'running' }] : [],
|
|
53
|
-
...flowsStats?.awaiting > 0 ? [{ value: flowsStats?.awaiting, label: 'awaiting' }] : [],
|
|
54
|
-
...flowsStats?.success > 0 ? [{ value: formatNumber(flowsStats?.success), label: 'completed' }] : [],
|
|
55
|
-
...flowsStats?.failure > 0 ? [{ value: formatNumber(flowsStats?.failure), label: 'failed' }] : []
|
|
56
|
-
]"
|
|
57
|
-
:secondary-stats="[
|
|
58
|
-
{ value: flowsStats?.total || 0, label: 'flows' },
|
|
59
|
-
{ value: formatNumber(flowsStats?.totalRuns || 0), label: 'total runs' }
|
|
60
|
-
]"
|
|
61
|
-
:on-click="() => navigateTo('/flows')"
|
|
62
|
-
/>
|
|
63
|
-
|
|
64
|
-
<!-- Triggers Card -->
|
|
65
|
-
<NventDashboardCard
|
|
66
|
-
icon="i-lucide-zap"
|
|
67
|
-
title="Active Triggers"
|
|
68
|
-
color="amber"
|
|
69
|
-
:primary-stats="[
|
|
70
|
-
{ value: formatNumber(triggersStats?.totalFires || 0), label: 'fires' }
|
|
71
|
-
]"
|
|
72
|
-
:secondary-stats="[
|
|
73
|
-
{ value: triggersStats?.total || 0, label: 'triggers' },
|
|
74
|
-
{ value: formatNumber(triggersStats?.totalFlowsStarted || 0), label: 'flows started' }
|
|
75
|
-
]"
|
|
76
|
-
:on-click="() => navigateTo('/triggers')"
|
|
77
|
-
/>
|
|
78
|
-
</div>
|
|
79
|
-
|
|
80
|
-
<!-- Quick Actions & Recent Activity -->
|
|
81
|
-
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
82
|
-
<!-- Quick Actions -->
|
|
83
|
-
<div class="bg-white dark:bg-gray-950 rounded-xl border border-gray-200 dark:border-gray-800 p-6">
|
|
84
|
-
<h2 class="text-lg font-semibold text-gray-900 dark:text-gray-100 mb-4 flex items-center gap-2">
|
|
85
|
-
<UIcon
|
|
86
|
-
name="i-lucide-rocket"
|
|
87
|
-
class="w-5 h-5 text-blue-500"
|
|
88
|
-
/>
|
|
89
|
-
Quick Actions
|
|
90
|
-
</h2>
|
|
91
|
-
<div class="space-y-2">
|
|
92
|
-
<button
|
|
93
|
-
class="w-full flex items-center justify-between p-3 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-900 transition-colors text-left group"
|
|
94
|
-
@click="navigateTo('/queues')"
|
|
95
|
-
>
|
|
96
|
-
<div class="flex items-center gap-3">
|
|
97
|
-
<div class="p-2 bg-blue-50 dark:bg-blue-950/50 rounded-lg group-hover:bg-blue-100 dark:group-hover:bg-blue-900/50 transition-colors">
|
|
98
|
-
<UIcon
|
|
99
|
-
name="i-lucide-app-window"
|
|
100
|
-
class="w-4 h-4 text-blue-600 dark:text-blue-400"
|
|
101
|
-
/>
|
|
102
|
-
</div>
|
|
103
|
-
<div>
|
|
104
|
-
<div class="text-sm font-medium text-gray-900 dark:text-gray-100">
|
|
105
|
-
View All Queues
|
|
106
|
-
</div>
|
|
107
|
-
<div class="text-xs text-gray-500 dark:text-gray-400">
|
|
108
|
-
Manage job queues and workers
|
|
109
|
-
</div>
|
|
110
|
-
</div>
|
|
111
|
-
</div>
|
|
112
|
-
<UIcon
|
|
113
|
-
name="i-lucide-chevron-right"
|
|
114
|
-
class="w-4 h-4 text-gray-400 group-hover:text-gray-600 dark:group-hover:text-gray-300"
|
|
115
|
-
/>
|
|
116
|
-
</button>
|
|
117
|
-
|
|
118
|
-
<button
|
|
119
|
-
class="w-full flex items-center justify-between p-3 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-900 transition-colors text-left group"
|
|
120
|
-
@click="navigateTo('/flows')"
|
|
121
|
-
>
|
|
122
|
-
<div class="flex items-center gap-3">
|
|
123
|
-
<div class="p-2 bg-purple-50 dark:bg-purple-950/50 rounded-lg group-hover:bg-purple-100 dark:group-hover:bg-purple-900/50 transition-colors">
|
|
124
|
-
<UIcon
|
|
125
|
-
name="i-lucide-git-branch"
|
|
126
|
-
class="w-4 h-4 text-purple-600 dark:text-purple-400"
|
|
127
|
-
/>
|
|
128
|
-
</div>
|
|
129
|
-
<div>
|
|
130
|
-
<div class="text-sm font-medium text-gray-900 dark:text-gray-100">
|
|
131
|
-
Monitor Flows
|
|
132
|
-
</div>
|
|
133
|
-
<div class="text-xs text-gray-500 dark:text-gray-400">
|
|
134
|
-
Track workflow executions
|
|
135
|
-
</div>
|
|
136
|
-
</div>
|
|
137
|
-
</div>
|
|
138
|
-
<UIcon
|
|
139
|
-
name="i-lucide-chevron-right"
|
|
140
|
-
class="w-4 h-4 text-gray-400 group-hover:text-gray-600 dark:group-hover:text-gray-300"
|
|
141
|
-
/>
|
|
142
|
-
</button>
|
|
143
|
-
|
|
144
|
-
<button
|
|
145
|
-
class="w-full flex items-center justify-between p-3 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-900 transition-colors text-left group"
|
|
146
|
-
@click="navigateTo('/triggers')"
|
|
147
|
-
>
|
|
148
|
-
<div class="flex items-center gap-3">
|
|
149
|
-
<div class="p-2 bg-amber-50 dark:bg-amber-950/50 rounded-lg group-hover:bg-amber-100 dark:group-hover:bg-amber-900/50 transition-colors">
|
|
150
|
-
<UIcon
|
|
151
|
-
name="i-lucide-zap"
|
|
152
|
-
class="w-4 h-4 text-amber-600 dark:text-amber-400"
|
|
153
|
-
/>
|
|
154
|
-
</div>
|
|
155
|
-
<div>
|
|
156
|
-
<div class="text-sm font-medium text-gray-900 dark:text-gray-100">
|
|
157
|
-
Manage Triggers
|
|
158
|
-
</div>
|
|
159
|
-
<div class="text-xs text-gray-500 dark:text-gray-400">
|
|
160
|
-
Configure event triggers
|
|
161
|
-
</div>
|
|
162
|
-
</div>
|
|
163
|
-
</div>
|
|
164
|
-
<UIcon
|
|
165
|
-
name="i-lucide-chevron-right"
|
|
166
|
-
class="w-4 h-4 text-gray-400 group-hover:text-gray-600 dark:group-hover:text-gray-300"
|
|
167
|
-
/>
|
|
168
|
-
</button>
|
|
169
|
-
</div>
|
|
170
|
-
</div>
|
|
171
|
-
|
|
172
|
-
<!-- System Overview -->
|
|
173
|
-
<div class="bg-white dark:bg-gray-950 rounded-xl border border-gray-200 dark:border-gray-800 p-6">
|
|
174
|
-
<h2 class="text-lg font-semibold text-gray-900 dark:text-gray-100 mb-4 flex items-center gap-2">
|
|
175
|
-
<UIcon
|
|
176
|
-
name="i-lucide-activity"
|
|
177
|
-
class="w-5 h-5 text-emerald-500"
|
|
178
|
-
/>
|
|
179
|
-
System Overview
|
|
180
|
-
</h2>
|
|
181
|
-
<div class="space-y-3">
|
|
182
|
-
<!-- Jobs Processed -->
|
|
183
|
-
<div class="flex items-center justify-between p-3 rounded-lg bg-gray-50 dark:bg-gray-900">
|
|
184
|
-
<div class="flex items-center gap-3">
|
|
185
|
-
<div class="p-2 bg-blue-100 dark:bg-blue-950 rounded-lg">
|
|
186
|
-
<UIcon
|
|
187
|
-
name="i-lucide-package"
|
|
188
|
-
class="w-4 h-4 text-blue-600 dark:text-blue-400"
|
|
189
|
-
/>
|
|
190
|
-
</div>
|
|
191
|
-
<div>
|
|
192
|
-
<div class="text-xs text-gray-500 dark:text-gray-400">
|
|
193
|
-
Jobs Processed
|
|
194
|
-
</div>
|
|
195
|
-
<div class="text-sm font-semibold text-gray-900 dark:text-gray-100">
|
|
196
|
-
{{ formatNumber(queuesStats?.completed || 0) }} completed
|
|
197
|
-
</div>
|
|
198
|
-
</div>
|
|
199
|
-
</div>
|
|
200
|
-
<div
|
|
201
|
-
v-if="queuesStats?.failed > 0"
|
|
202
|
-
class="text-xs text-red-600 dark:text-red-400"
|
|
203
|
-
>
|
|
204
|
-
{{ queuesStats?.failed }} failed
|
|
205
|
-
</div>
|
|
206
|
-
</div>
|
|
207
|
-
|
|
208
|
-
<!-- Flow Runs -->
|
|
209
|
-
<div class="flex items-center justify-between p-3 rounded-lg bg-gray-50 dark:bg-gray-900">
|
|
210
|
-
<div class="flex items-center gap-3">
|
|
211
|
-
<div class="p-2 bg-purple-100 dark:bg-purple-950 rounded-lg">
|
|
212
|
-
<UIcon
|
|
213
|
-
name="i-lucide-git-branch"
|
|
214
|
-
class="w-4 h-4 text-purple-600 dark:text-purple-400"
|
|
215
|
-
/>
|
|
216
|
-
</div>
|
|
217
|
-
<div>
|
|
218
|
-
<div class="text-xs text-gray-500 dark:text-gray-400">
|
|
219
|
-
Total Flow Runs
|
|
220
|
-
</div>
|
|
221
|
-
<div class="text-sm font-semibold text-gray-900 dark:text-gray-100">
|
|
222
|
-
{{ formatNumber(flowsStats?.totalRuns || 0) }} runs
|
|
223
|
-
</div>
|
|
224
|
-
</div>
|
|
225
|
-
</div>
|
|
226
|
-
<div
|
|
227
|
-
v-if="flowsStats?.running > 0"
|
|
228
|
-
class="text-xs text-blue-600 dark:text-blue-400 font-semibold"
|
|
229
|
-
>
|
|
230
|
-
{{ flowsStats?.running }} running
|
|
231
|
-
</div>
|
|
232
|
-
</div>
|
|
233
|
-
|
|
234
|
-
<!-- Trigger Fires -->
|
|
235
|
-
<div class="flex items-center justify-between p-3 rounded-lg bg-gray-50 dark:bg-gray-900">
|
|
236
|
-
<div class="flex items-center gap-3">
|
|
237
|
-
<div class="p-2 bg-amber-100 dark:bg-amber-950 rounded-lg">
|
|
238
|
-
<UIcon
|
|
239
|
-
name="i-lucide-zap"
|
|
240
|
-
class="w-4 h-4 text-amber-600 dark:text-amber-400"
|
|
241
|
-
/>
|
|
242
|
-
</div>
|
|
243
|
-
<div>
|
|
244
|
-
<div class="text-xs text-gray-500 dark:text-gray-400">
|
|
245
|
-
Trigger → Flow Starts
|
|
246
|
-
</div>
|
|
247
|
-
<div class="text-sm font-semibold text-gray-900 dark:text-gray-100">
|
|
248
|
-
{{ formatNumber(triggersStats?.totalFlowsStarted || 0) }} flows
|
|
249
|
-
</div>
|
|
250
|
-
</div>
|
|
251
|
-
</div>
|
|
252
|
-
<div class="text-xs text-gray-500 dark:text-gray-400">
|
|
253
|
-
from {{ formatNumber(triggersStats?.totalFires || 0) }} fires
|
|
254
|
-
</div>
|
|
255
|
-
</div>
|
|
256
|
-
</div>
|
|
257
|
-
</div>
|
|
258
|
-
</div>
|
|
259
|
-
|
|
260
|
-
<!-- Recent Items Grid -->
|
|
261
|
-
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
|
262
|
-
<!-- Recent Queues -->
|
|
263
|
-
<div class="bg-white dark:bg-gray-950 rounded-xl border border-gray-200 dark:border-gray-800 p-6">
|
|
264
|
-
<div class="flex items-center justify-between mb-4">
|
|
265
|
-
<h3 class="text-sm font-semibold text-gray-900 dark:text-gray-100 flex items-center gap-2">
|
|
266
|
-
<UIcon
|
|
267
|
-
name="i-lucide-app-window"
|
|
268
|
-
class="w-4 h-4 text-blue-500"
|
|
269
|
-
/>
|
|
270
|
-
Active Queues
|
|
271
|
-
</h3>
|
|
272
|
-
<button
|
|
273
|
-
class="text-xs text-blue-600 dark:text-blue-400 hover:underline"
|
|
274
|
-
@click="navigateTo('/queues')"
|
|
275
|
-
>
|
|
276
|
-
View all
|
|
277
|
-
</button>
|
|
278
|
-
</div>
|
|
279
|
-
<div
|
|
280
|
-
v-if="!recentQueues || recentQueues.length === 0"
|
|
281
|
-
class="text-center py-8 text-sm text-gray-400"
|
|
282
|
-
>
|
|
283
|
-
<UIcon
|
|
284
|
-
name="i-lucide-inbox"
|
|
285
|
-
class="w-8 h-8 mx-auto mb-2 text-gray-300 dark:text-gray-700"
|
|
286
|
-
/>
|
|
287
|
-
<p>No queues found</p>
|
|
288
|
-
</div>
|
|
289
|
-
<div
|
|
290
|
-
v-else
|
|
291
|
-
class="space-y-2"
|
|
292
|
-
>
|
|
293
|
-
<div
|
|
294
|
-
v-for="queue in recentQueues.slice(0, 5)"
|
|
295
|
-
:key="queue.name"
|
|
296
|
-
class="flex items-center justify-between p-2 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-900 transition-colors cursor-pointer"
|
|
297
|
-
@click="navigateTo(`/queues?queue=${encodeURIComponent(queue.name)}`)"
|
|
298
|
-
>
|
|
299
|
-
<div class="flex items-center gap-2 min-w-0">
|
|
300
|
-
<div
|
|
301
|
-
class="w-2 h-2 rounded-full"
|
|
302
|
-
:class="queue.isPaused ? 'bg-gray-400' : 'bg-blue-500'"
|
|
303
|
-
/>
|
|
304
|
-
<span class="text-sm font-medium text-gray-900 dark:text-gray-100 truncate">{{ queue.name }}</span>
|
|
305
|
-
</div>
|
|
306
|
-
<div class="flex items-center gap-2 text-xs text-gray-500 dark:text-gray-400 shrink-0">
|
|
307
|
-
<span
|
|
308
|
-
v-if="(queue.counts?.active || 0) + (queue.counts?.waiting || 0) > 0"
|
|
309
|
-
class="text-blue-600 dark:text-blue-400 font-medium"
|
|
310
|
-
>
|
|
311
|
-
{{ (queue.counts?.active || 0) + (queue.counts?.waiting || 0) }} pending
|
|
312
|
-
</span>
|
|
313
|
-
<span v-else>
|
|
314
|
-
{{ queue.counts?.completed || 0 }} completed
|
|
315
|
-
</span>
|
|
316
|
-
</div>
|
|
317
|
-
</div>
|
|
318
|
-
</div>
|
|
319
|
-
</div>
|
|
320
|
-
|
|
321
|
-
<!-- Recent Flow Runs -->
|
|
322
|
-
<div class="bg-white dark:bg-gray-950 rounded-xl border border-gray-200 dark:border-gray-800 p-6">
|
|
323
|
-
<div class="flex items-center justify-between mb-4">
|
|
324
|
-
<h3 class="text-sm font-semibold text-gray-900 dark:text-gray-100 flex items-center gap-2">
|
|
325
|
-
<UIcon
|
|
326
|
-
name="i-lucide-git-branch"
|
|
327
|
-
class="w-4 h-4 text-purple-500"
|
|
328
|
-
/>
|
|
329
|
-
Recent Flow Runs
|
|
330
|
-
</h3>
|
|
331
|
-
<button
|
|
332
|
-
class="text-xs text-purple-600 dark:text-purple-400 hover:underline"
|
|
333
|
-
@click="navigateTo('/flows')"
|
|
334
|
-
>
|
|
335
|
-
View all
|
|
336
|
-
</button>
|
|
337
|
-
</div>
|
|
338
|
-
<div
|
|
339
|
-
v-if="!recentFlowRuns || recentFlowRuns.length === 0"
|
|
340
|
-
class="text-center py-8 text-sm text-gray-400"
|
|
341
|
-
>
|
|
342
|
-
<UIcon
|
|
343
|
-
name="i-lucide-inbox"
|
|
344
|
-
class="w-8 h-8 mx-auto mb-2 text-gray-300 dark:text-gray-700"
|
|
345
|
-
/>
|
|
346
|
-
<p>No flow runs found</p>
|
|
347
|
-
</div>
|
|
348
|
-
<div
|
|
349
|
-
v-else
|
|
350
|
-
class="space-y-2"
|
|
351
|
-
>
|
|
352
|
-
<div
|
|
353
|
-
v-for="run in recentFlowRuns"
|
|
354
|
-
:key="run.id"
|
|
355
|
-
class="flex items-center justify-between p-2 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-900 transition-colors cursor-pointer"
|
|
356
|
-
@click="navigateTo(`/flows/${encodeURIComponent(run.flowName)}`)"
|
|
357
|
-
>
|
|
358
|
-
<div class="flex items-center gap-2 min-w-0">
|
|
359
|
-
<div
|
|
360
|
-
class="w-2 h-2 rounded-full"
|
|
361
|
-
:class="{
|
|
362
|
-
'bg-purple-500': (run.stats?.running || 0) > 0,
|
|
363
|
-
'bg-amber-500': (run.stats?.awaiting || 0) > 0 && (run.stats?.running || 0) === 0,
|
|
364
|
-
'bg-red-500': (run.stats?.failure || 0) > 0 && (run.stats?.running || 0) === 0 && (run.stats?.awaiting || 0) === 0,
|
|
365
|
-
'bg-emerald-500': (run.stats?.success || 0) > 0 && (run.stats?.running || 0) === 0 && (run.stats?.awaiting || 0) === 0 && (run.stats?.failure || 0) === 0,
|
|
366
|
-
'bg-gray-400': (run.stats?.total || 0) === 0
|
|
367
|
-
}"
|
|
368
|
-
/>
|
|
369
|
-
<span class="text-sm font-medium text-gray-900 dark:text-gray-100 truncate">{{ run.flowDisplayName || run.flowName }}</span>
|
|
370
|
-
</div>
|
|
371
|
-
<div class="flex items-center gap-2 text-xs text-gray-500 dark:text-gray-400 shrink-0">
|
|
372
|
-
<span
|
|
373
|
-
v-if="(run.stats?.running || 0) > 0"
|
|
374
|
-
class="text-purple-600 dark:text-purple-400 font-medium"
|
|
375
|
-
>
|
|
376
|
-
{{ run.stats?.running }} running
|
|
377
|
-
</span>
|
|
378
|
-
<span
|
|
379
|
-
v-else-if="(run.stats?.awaiting || 0) > 0"
|
|
380
|
-
class="text-amber-600 dark:text-amber-400 font-medium"
|
|
381
|
-
>
|
|
382
|
-
{{ run.stats?.awaiting }} awaiting
|
|
383
|
-
</span>
|
|
384
|
-
<span v-else>
|
|
385
|
-
{{ run.stats?.total || 0 }} runs
|
|
386
|
-
</span>
|
|
387
|
-
</div>
|
|
388
|
-
</div>
|
|
389
|
-
</div>
|
|
390
|
-
</div>
|
|
391
|
-
|
|
392
|
-
<!-- Recent Triggers -->
|
|
393
|
-
<div class="bg-white dark:bg-gray-950 rounded-xl border border-gray-200 dark:border-gray-800 p-6">
|
|
394
|
-
<div class="flex items-center justify-between mb-4">
|
|
395
|
-
<h3 class="text-sm font-semibold text-gray-900 dark:text-gray-100 flex items-center gap-2">
|
|
396
|
-
<UIcon
|
|
397
|
-
name="i-lucide-zap"
|
|
398
|
-
class="w-4 h-4 text-amber-500"
|
|
399
|
-
/>
|
|
400
|
-
Active Triggers
|
|
401
|
-
</h3>
|
|
402
|
-
<button
|
|
403
|
-
class="text-xs text-amber-600 dark:text-amber-400 hover:underline"
|
|
404
|
-
@click="navigateTo('/triggers')"
|
|
405
|
-
>
|
|
406
|
-
View all
|
|
407
|
-
</button>
|
|
408
|
-
</div>
|
|
409
|
-
<div
|
|
410
|
-
v-if="!recentTriggers || recentTriggers.length === 0"
|
|
411
|
-
class="text-center py-8 text-sm text-gray-400"
|
|
412
|
-
>
|
|
413
|
-
<UIcon
|
|
414
|
-
name="i-lucide-inbox"
|
|
415
|
-
class="w-8 h-8 mx-auto mb-2 text-gray-300 dark:text-gray-700"
|
|
416
|
-
/>
|
|
417
|
-
<p>No triggers found</p>
|
|
418
|
-
</div>
|
|
419
|
-
<div
|
|
420
|
-
v-else
|
|
421
|
-
class="space-y-2"
|
|
422
|
-
>
|
|
423
|
-
<div
|
|
424
|
-
v-for="trigger in recentTriggers.slice(0, 5)"
|
|
425
|
-
:key="trigger.name"
|
|
426
|
-
class="flex items-center justify-between p-2 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-900 transition-colors cursor-pointer"
|
|
427
|
-
@click="navigateTo(`/triggers/${encodeURIComponent(trigger.name)}`)"
|
|
428
|
-
>
|
|
429
|
-
<div class="flex items-center gap-2 min-w-0">
|
|
430
|
-
<div class="w-2 h-2 rounded-full bg-amber-500" />
|
|
431
|
-
<span class="text-sm font-medium text-gray-900 dark:text-gray-100 truncate">{{ trigger.displayName || trigger.name }}</span>
|
|
432
|
-
</div>
|
|
433
|
-
<span class="text-xs text-gray-500 dark:text-gray-400 shrink-0">{{ trigger.stats?.totalFires || 0 }}</span>
|
|
434
|
-
</div>
|
|
435
|
-
</div>
|
|
436
|
-
</div>
|
|
437
|
-
</div>
|
|
438
26
|
</div>
|
|
439
27
|
</div>
|
|
440
28
|
</div>
|
|
441
29
|
</template>
|
|
442
30
|
|
|
443
|
-
<script setup>
|
|
444
|
-
import { ref, computed, onMounted } from "#imports";
|
|
445
|
-
import { useComponentRouter } from "../composables/useComponentRouter";
|
|
446
|
-
import { useQueuesWebSocket } from "../composables/useQueuesWebSocket";
|
|
447
|
-
import { useFlowWebSocket } from "../composables/useFlowWebSocket";
|
|
448
|
-
import { useTriggerWebSocket } from "../composables/useTriggerWebSocket";
|
|
449
|
-
const router = useComponentRouter();
|
|
450
|
-
const queues = ref([]);
|
|
451
|
-
const flows = ref([]);
|
|
452
|
-
const triggers = ref([]);
|
|
453
|
-
const { connected: queuesConnected, subscribe: subscribeQueue } = useQueuesWebSocket();
|
|
454
|
-
const { connected: flowsConnected, subscribeStats: subscribeFlowStats } = useFlowWebSocket();
|
|
455
|
-
const { connected: triggersConnected, subscribeStats: subscribeTriggerStats } = useTriggerWebSocket();
|
|
456
|
-
onMounted(async () => {
|
|
457
|
-
if (import.meta.server) return;
|
|
458
|
-
const [queuesResponse, flowsResponse, triggersResponse] = await Promise.all([
|
|
459
|
-
$fetch("/api/_queues"),
|
|
460
|
-
$fetch("/api/_flows"),
|
|
461
|
-
$fetch("/api/_triggers")
|
|
462
|
-
]);
|
|
463
|
-
queues.value = Array.isArray(queuesResponse) ? queuesResponse : [];
|
|
464
|
-
const analyzedFlows = Array.isArray(flowsResponse) ? flowsResponse : [];
|
|
465
|
-
flows.value = analyzedFlows.map((flow) => ({
|
|
466
|
-
id: flow.id,
|
|
467
|
-
name: flow.id,
|
|
468
|
-
// Add name property for consistency
|
|
469
|
-
displayName: flow.id,
|
|
470
|
-
entry: flow.entry,
|
|
471
|
-
steps: flow.analyzed?.steps || flow.steps || {},
|
|
472
|
-
levels: flow.analyzed?.levels || [],
|
|
473
|
-
maxLevel: flow.analyzed?.maxLevel || 0,
|
|
474
|
-
stallTimeout: flow.analyzed?.stallTimeout,
|
|
475
|
-
awaitPatterns: flow.analyzed?.awaitPatterns,
|
|
476
|
-
hasAwait: flow.analyzed?.awaitPatterns?.steps?.length > 0 || false,
|
|
477
|
-
timeout: flow.timeout,
|
|
478
|
-
stats: { total: 0, success: 0, failure: 0, cancel: 0, running: 0, awaiting: 0 }
|
|
479
|
-
}));
|
|
480
|
-
triggers.value = (Array.isArray(triggersResponse) ? triggersResponse : []).map((trigger) => ({
|
|
481
|
-
...trigger,
|
|
482
|
-
stats: trigger.stats || {
|
|
483
|
-
totalFires: 0,
|
|
484
|
-
totalFlowsStarted: 0,
|
|
485
|
-
lastFiredAt: null,
|
|
486
|
-
activeSubscribers: 0
|
|
487
|
-
}
|
|
488
|
-
}));
|
|
489
|
-
for (const queue of queues.value) {
|
|
490
|
-
subscribeQueue(
|
|
491
|
-
queue.name,
|
|
492
|
-
(counts) => {
|
|
493
|
-
queues.value = queues.value.map(
|
|
494
|
-
(q) => q.name === queue.name ? { ...q, counts } : q
|
|
495
|
-
);
|
|
496
|
-
}
|
|
497
|
-
);
|
|
498
|
-
}
|
|
499
|
-
subscribeFlowStats({
|
|
500
|
-
onInitial: (data) => {
|
|
501
|
-
updateFlowStats(data);
|
|
502
|
-
},
|
|
503
|
-
onUpdate: (data) => {
|
|
504
|
-
updateFlowStats(data);
|
|
505
|
-
}
|
|
506
|
-
});
|
|
507
|
-
subscribeTriggerStats({
|
|
508
|
-
onInitial: (data) => {
|
|
509
|
-
updateTriggerStats(data);
|
|
510
|
-
},
|
|
511
|
-
onUpdate: (data) => {
|
|
512
|
-
updateTriggerStats(data);
|
|
513
|
-
}
|
|
514
|
-
});
|
|
515
|
-
});
|
|
516
|
-
function updateFlowStats(data) {
|
|
517
|
-
const flowId = data?.id;
|
|
518
|
-
if (!flowId) {
|
|
519
|
-
console.warn("[Dashboard] No flow ID in stats update:", data);
|
|
520
|
-
return;
|
|
521
|
-
}
|
|
522
|
-
if (!flows.value || flows.value.length === 0) {
|
|
523
|
-
console.warn("[Dashboard] Flows array not initialized yet");
|
|
524
|
-
return;
|
|
525
|
-
}
|
|
526
|
-
const flowIndex = flows.value.findIndex((f) => f.id === flowId);
|
|
527
|
-
if (flowIndex === -1) {
|
|
528
|
-
console.warn("[Dashboard] Flow not found in list:", flowId, "available:", flows.value.map((f) => f.id));
|
|
529
|
-
return;
|
|
530
|
-
}
|
|
531
|
-
const metadata = data?.metadata;
|
|
532
|
-
if (!metadata) {
|
|
533
|
-
console.warn("[Dashboard] No metadata in update:", data);
|
|
534
|
-
return;
|
|
535
|
-
}
|
|
536
|
-
const newStats = {
|
|
537
|
-
total: metadata.stats?.total || metadata.total || metadata["stats.total"] || 0,
|
|
538
|
-
success: metadata.stats?.success || metadata.success || metadata["stats.success"] || 0,
|
|
539
|
-
failure: metadata.stats?.failure || metadata.failure || metadata["stats.failure"] || 0,
|
|
540
|
-
cancel: metadata.stats?.cancel || metadata.cancel || metadata["stats.cancel"] || 0,
|
|
541
|
-
running: metadata.stats?.running || metadata.running || metadata["stats.running"] || 0,
|
|
542
|
-
awaiting: metadata.stats?.awaiting || metadata.awaiting || metadata["stats.awaiting"] || 0
|
|
543
|
-
};
|
|
544
|
-
const updatedFlow = {
|
|
545
|
-
...flows.value[flowIndex],
|
|
546
|
-
stats: newStats,
|
|
547
|
-
lastRunAt: metadata.lastRunAt,
|
|
548
|
-
lastCompletedAt: metadata.lastCompletedAt
|
|
549
|
-
};
|
|
550
|
-
flows.value = [
|
|
551
|
-
...flows.value.slice(0, flowIndex),
|
|
552
|
-
updatedFlow,
|
|
553
|
-
...flows.value.slice(flowIndex + 1)
|
|
554
|
-
];
|
|
555
|
-
}
|
|
556
|
-
function updateTriggerStats(data) {
|
|
557
|
-
const triggerName = data?.id;
|
|
558
|
-
if (!triggerName) {
|
|
559
|
-
console.warn("[Dashboard] No trigger name in stats update:", data);
|
|
560
|
-
return;
|
|
561
|
-
}
|
|
562
|
-
if (!triggers.value || triggers.value.length === 0) {
|
|
563
|
-
console.warn("[Dashboard] Triggers array not initialized yet, storing for later");
|
|
564
|
-
return;
|
|
565
|
-
}
|
|
566
|
-
const triggerIndex = triggers.value.findIndex((t) => t.name === triggerName);
|
|
567
|
-
if (triggerIndex === -1) {
|
|
568
|
-
console.warn("[Dashboard] Trigger not found in list:", triggerName, "available:", triggers.value.map((t) => t.name));
|
|
569
|
-
return;
|
|
570
|
-
}
|
|
571
|
-
const metadata = data?.metadata;
|
|
572
|
-
if (!metadata) {
|
|
573
|
-
console.warn("[Dashboard] No metadata in update:", data);
|
|
574
|
-
return;
|
|
575
|
-
}
|
|
576
|
-
const newStats = {
|
|
577
|
-
totalFires: metadata.stats?.totalFires || metadata.totalFires || metadata["stats.totalFires"] || 0,
|
|
578
|
-
totalFlowsStarted: metadata.stats?.totalFlowsStarted || metadata.totalFlowsStarted || metadata["stats.totalFlowsStarted"] || 0,
|
|
579
|
-
last24h: metadata.stats?.last24h || metadata.last24h || metadata["stats.last24h"] || 0,
|
|
580
|
-
successCount: metadata.stats?.successCount || metadata.successCount || metadata["stats.successCount"] || 0,
|
|
581
|
-
failureCount: metadata.stats?.failureCount || metadata.failureCount || metadata["stats.failureCount"] || 0,
|
|
582
|
-
lastFiredAt: metadata.stats?.lastFiredAt || metadata.lastFiredAt || metadata["stats.lastFiredAt"],
|
|
583
|
-
activeSubscribers: metadata.stats?.activeSubscribers || metadata.activeSubscribers || metadata["stats.activeSubscribers"] || 0
|
|
584
|
-
};
|
|
585
|
-
const updatedTrigger = {
|
|
586
|
-
...triggers.value[triggerIndex],
|
|
587
|
-
stats: newStats,
|
|
588
|
-
lastActivityAt: metadata.lastActivityAt
|
|
589
|
-
};
|
|
590
|
-
triggers.value = [
|
|
591
|
-
...triggers.value.slice(0, triggerIndex),
|
|
592
|
-
updatedTrigger,
|
|
593
|
-
...triggers.value.slice(triggerIndex + 1)
|
|
594
|
-
];
|
|
595
|
-
}
|
|
596
|
-
const queuesStats = computed(() => {
|
|
597
|
-
const active = queues.value.reduce((sum, q) => sum + (q.counts?.active || 0), 0);
|
|
598
|
-
const waiting = queues.value.reduce((sum, q) => sum + (q.counts?.waiting || 0), 0);
|
|
599
|
-
const delayed = queues.value.reduce((sum, q) => sum + (q.counts?.delayed || 0), 0);
|
|
600
|
-
const pending = active + waiting + delayed;
|
|
601
|
-
const completed = queues.value.reduce((sum, q) => sum + (q.counts?.completed || 0), 0);
|
|
602
|
-
const failed = queues.value.reduce((sum, q) => sum + (q.counts?.failed || 0), 0);
|
|
603
|
-
return {
|
|
604
|
-
total: queues.value.length,
|
|
605
|
-
active,
|
|
606
|
-
waiting,
|
|
607
|
-
delayed,
|
|
608
|
-
pending,
|
|
609
|
-
completed,
|
|
610
|
-
failed
|
|
611
|
-
};
|
|
612
|
-
});
|
|
613
|
-
const flowsStats = computed(() => {
|
|
614
|
-
const totalRuns = flows.value.reduce((sum, f) => sum + (f.stats?.total || 0), 0);
|
|
615
|
-
const running = flows.value.reduce((sum, f) => sum + (f.stats?.running || 0), 0);
|
|
616
|
-
const awaiting = flows.value.reduce((sum, f) => sum + (f.stats?.awaiting || 0), 0);
|
|
617
|
-
const success = flows.value.reduce((sum, f) => sum + (f.stats?.success || 0), 0);
|
|
618
|
-
const failure = flows.value.reduce((sum, f) => sum + (f.stats?.failure || 0), 0);
|
|
619
|
-
return {
|
|
620
|
-
total: flows.value.length,
|
|
621
|
-
active: flows.value.filter((f) => f.enabled !== false).length,
|
|
622
|
-
totalRuns,
|
|
623
|
-
running,
|
|
624
|
-
awaiting,
|
|
625
|
-
success,
|
|
626
|
-
failure
|
|
627
|
-
};
|
|
628
|
-
});
|
|
629
|
-
const triggersStats = computed(() => {
|
|
630
|
-
const totalFires = triggers.value.reduce((sum, t) => sum + (t.stats?.totalFires || 0), 0);
|
|
631
|
-
const totalFlowsStarted = triggers.value.reduce((sum, t) => sum + (t.stats?.totalFlowsStarted || 0), 0);
|
|
632
|
-
const totalSubscriptions = triggers.value.reduce((sum, t) => sum + (t.subscriptionCount || 0), 0);
|
|
633
|
-
return {
|
|
634
|
-
total: triggers.value.length,
|
|
635
|
-
totalFires,
|
|
636
|
-
totalFlowsStarted,
|
|
637
|
-
totalSubscriptions
|
|
638
|
-
};
|
|
639
|
-
});
|
|
640
|
-
const recentQueues = computed(() => {
|
|
641
|
-
return queues.value.map((q) => ({
|
|
642
|
-
...q,
|
|
643
|
-
displayName: q.name,
|
|
644
|
-
status: q.isPaused ? "paused" : "active"
|
|
645
|
-
})).sort((a, b) => {
|
|
646
|
-
const aPending = (a.counts?.active || 0) + (a.counts?.waiting || 0);
|
|
647
|
-
const bPending = (b.counts?.active || 0) + (b.counts?.waiting || 0);
|
|
648
|
-
return bPending - aPending;
|
|
649
|
-
});
|
|
650
|
-
});
|
|
651
|
-
const recentFlowRuns = computed(() => {
|
|
652
|
-
return [...flows.value].filter((f) => f.stats?.total > 0).sort((a, b) => {
|
|
653
|
-
const aActive = (a.stats?.running || 0) + (a.stats?.awaiting || 0);
|
|
654
|
-
const bActive = (b.stats?.running || 0) + (b.stats?.awaiting || 0);
|
|
655
|
-
if (aActive !== bActive) return bActive - aActive;
|
|
656
|
-
const aTime = a.lastRunAt || 0;
|
|
657
|
-
const bTime = b.lastRunAt || 0;
|
|
658
|
-
return bTime - aTime;
|
|
659
|
-
}).slice(0, 5).map((f) => ({
|
|
660
|
-
id: f.name,
|
|
661
|
-
flowName: f.name,
|
|
662
|
-
flowDisplayName: f.displayName || f.name,
|
|
663
|
-
stats: f.stats
|
|
664
|
-
}));
|
|
665
|
-
});
|
|
666
|
-
const recentTriggers = computed(() => {
|
|
667
|
-
return [...triggers.value].sort((a, b) => {
|
|
668
|
-
const aFires = a.stats?.totalFires || 0;
|
|
669
|
-
const bFires = b.stats?.totalFires || 0;
|
|
670
|
-
return bFires - aFires;
|
|
671
|
-
});
|
|
672
|
-
});
|
|
673
|
-
const isConnected = computed(() => {
|
|
674
|
-
return queuesConnected.value || flowsConnected.value || triggersConnected.value;
|
|
675
|
-
});
|
|
676
|
-
const navigateTo = (path) => {
|
|
677
|
-
router.push(path);
|
|
678
|
-
};
|
|
679
|
-
const formatNumber = (num) => {
|
|
680
|
-
if (num == null) return "0";
|
|
681
|
-
if (num >= 1e6) return `${(num / 1e6).toFixed(1)}M`;
|
|
682
|
-
if (num >= 1e3) return `${(num / 1e3).toFixed(1)}K`;
|
|
683
|
-
return num.toString();
|
|
684
|
-
};
|
|
31
|
+
<script setup lang="ts">
|
|
685
32
|
</script>
|