@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.
Files changed (95) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +3 -2
  3. package/dist/runtime/app/components/DashboardCard.d.vue.ts +1 -1
  4. package/dist/runtime/app/components/DashboardCard.vue.d.ts +1 -1
  5. package/dist/runtime/app/composables/useWorkers.d.ts +57 -0
  6. package/dist/runtime/app/composables/useWorkers.js +42 -0
  7. package/dist/runtime/app/pages/dashboard.vue +1 -654
  8. package/dist/runtime/app/pages/index.vue +25 -41
  9. package/dist/runtime/app/pages/workers.vue +458 -0
  10. package/dist/runtime/server/api/_workers/index.get.d.ts +8 -0
  11. package/dist/runtime/server/api/_workers/index.get.js +14 -0
  12. package/package.json +13 -12
  13. package/dist/runtime/app/components/ComponentRouter.d.vue.ts +0 -46
  14. package/dist/runtime/app/components/ComponentRouter.vue +0 -26
  15. package/dist/runtime/app/components/ComponentRouter.vue.d.ts +0 -46
  16. package/dist/runtime/app/components/ComponentShell.d.vue.ts +0 -23
  17. package/dist/runtime/app/components/ComponentShell.vue +0 -97
  18. package/dist/runtime/app/components/ComponentShell.vue.d.ts +0 -23
  19. package/dist/runtime/app/components/ConfirmDialog.d.vue.ts +0 -33
  20. package/dist/runtime/app/components/ConfirmDialog.vue +0 -120
  21. package/dist/runtime/app/components/ConfirmDialog.vue.d.ts +0 -33
  22. package/dist/runtime/app/composables/useComponentRouter.d.ts +0 -46
  23. package/dist/runtime/app/composables/useComponentRouter.js +0 -248
  24. package/dist/runtime/app/pages/flows/[name].vue +0 -750
  25. package/dist/runtime/app/pages/flows/index.d.vue.ts +0 -3
  26. package/dist/runtime/app/pages/flows/index.vue +0 -381
  27. package/dist/runtime/app/pages/flows/index.vue.d.ts +0 -3
  28. package/dist/runtime/app/pages/queues/index.d.vue.ts +0 -3
  29. package/dist/runtime/app/pages/queues/index.vue +0 -236
  30. package/dist/runtime/app/pages/queues/index.vue.d.ts +0 -3
  31. package/dist/runtime/app/pages/queues/job.d.vue.ts +0 -3
  32. package/dist/runtime/app/pages/queues/job.vue +0 -261
  33. package/dist/runtime/app/pages/queues/job.vue.d.ts +0 -3
  34. package/dist/runtime/app/pages/queues/jobs.d.vue.ts +0 -3
  35. package/dist/runtime/app/pages/queues/jobs.vue +0 -595
  36. package/dist/runtime/app/pages/queues/jobs.vue.d.ts +0 -3
  37. package/dist/runtime/app/pages/settings/scheduler.d.vue.ts +0 -3
  38. package/dist/runtime/app/pages/settings/scheduler.vue +0 -310
  39. package/dist/runtime/app/pages/settings/scheduler.vue.d.ts +0 -3
  40. package/dist/runtime/app/pages/triggers/[name]/edit.d.vue.ts +0 -3
  41. package/dist/runtime/app/pages/triggers/[name]/edit.vue +0 -429
  42. package/dist/runtime/app/pages/triggers/[name]/edit.vue.d.ts +0 -3
  43. package/dist/runtime/app/pages/triggers/[name].d.vue.ts +0 -3
  44. package/dist/runtime/app/pages/triggers/[name].vue +0 -870
  45. package/dist/runtime/app/pages/triggers/[name].vue.d.ts +0 -3
  46. package/dist/runtime/app/pages/triggers/index.d.vue.ts +0 -3
  47. package/dist/runtime/app/pages/triggers/index.vue +0 -525
  48. package/dist/runtime/app/pages/triggers/index.vue.d.ts +0 -3
  49. package/dist/runtime/app/pages/triggers/new.d.vue.ts +0 -3
  50. package/dist/runtime/app/pages/triggers/new.vue +0 -610
  51. package/dist/runtime/app/pages/triggers/new.vue.d.ts +0 -3
  52. package/dist/runtime/server/api/_flows/[name]/clear-history.delete.d.ts +0 -10
  53. package/dist/runtime/server/api/_flows/[name]/clear-history.delete.js +0 -49
  54. package/dist/runtime/server/api/_flows/[name]/runs/[runId]/cancel.post.d.ts +0 -2
  55. package/dist/runtime/server/api/_flows/[name]/runs/[runId]/cancel.post.js +0 -21
  56. package/dist/runtime/server/api/_flows/[name]/runs/[runId]/restart.post.d.ts +0 -2
  57. package/dist/runtime/server/api/_flows/[name]/runs/[runId]/restart.post.js +0 -21
  58. package/dist/runtime/server/api/_flows/[name]/runs.get.d.ts +0 -17
  59. package/dist/runtime/server/api/_flows/[name]/runs.get.js +0 -64
  60. package/dist/runtime/server/api/_flows/[name]/start.post.d.ts +0 -2
  61. package/dist/runtime/server/api/_flows/[name]/start.post.js +0 -9
  62. package/dist/runtime/server/api/_flows/index.get.d.ts +0 -7
  63. package/dist/runtime/server/api/_flows/index.get.js +0 -5
  64. package/dist/runtime/server/api/_flows/recent-runs.get.d.ts +0 -15
  65. package/dist/runtime/server/api/_flows/recent-runs.get.js +0 -67
  66. package/dist/runtime/server/api/_flows/ws.d.ts +0 -80
  67. package/dist/runtime/server/api/_flows/ws.js +0 -309
  68. package/dist/runtime/server/api/_queues/[name]/job/[id].get.d.ts +0 -2
  69. package/dist/runtime/server/api/_queues/[name]/job/[id].get.js +0 -14
  70. package/dist/runtime/server/api/_queues/[name]/job/index.get.d.ts +0 -2
  71. package/dist/runtime/server/api/_queues/[name]/job/index.get.js +0 -39
  72. package/dist/runtime/server/api/_queues/index.get.d.ts +0 -2
  73. package/dist/runtime/server/api/_queues/index.get.js +0 -106
  74. package/dist/runtime/server/api/_queues/ws.d.ts +0 -48
  75. package/dist/runtime/server/api/_queues/ws.js +0 -215
  76. package/dist/runtime/server/api/_scheduler/jobs.get.d.ts +0 -19
  77. package/dist/runtime/server/api/_scheduler/jobs.get.js +0 -36
  78. package/dist/runtime/server/api/_triggers/[name]/events.get.d.ts +0 -6
  79. package/dist/runtime/server/api/_triggers/[name]/events.get.js +0 -43
  80. package/dist/runtime/server/api/_triggers/[name]/index.get.d.ts +0 -6
  81. package/dist/runtime/server/api/_triggers/[name]/index.get.js +0 -76
  82. package/dist/runtime/server/api/_triggers/[name].delete.d.ts +0 -7
  83. package/dist/runtime/server/api/_triggers/[name].delete.js +0 -37
  84. package/dist/runtime/server/api/_triggers/[name].patch.d.ts +0 -7
  85. package/dist/runtime/server/api/_triggers/[name].patch.js +0 -117
  86. package/dist/runtime/server/api/_triggers/index.get.d.ts +0 -6
  87. package/dist/runtime/server/api/_triggers/index.get.js +0 -44
  88. package/dist/runtime/server/api/_triggers/index.post.d.ts +0 -7
  89. package/dist/runtime/server/api/_triggers/index.post.js +0 -124
  90. package/dist/runtime/server/api/_triggers/stats.get.d.ts +0 -6
  91. package/dist/runtime/server/api/_triggers/stats.get.js +0 -41
  92. package/dist/runtime/server/api/_triggers/ws.d.ts +0 -74
  93. package/dist/runtime/server/api/_triggers/ws.js +0 -315
  94. /package/dist/runtime/app/pages/{flows/[name].d.vue.ts → workers.d.vue.ts} +0 -0
  95. /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>