@elevasis/ui 1.26.0 → 1.27.0

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 (53) hide show
  1. package/dist/charts/index.js +2 -2
  2. package/dist/{chunk-AWT255UH.js → chunk-2IJCM3VQ.js} +37 -37
  3. package/dist/chunk-5COLSYBE.js +199 -0
  4. package/dist/{chunk-RMPXGBNI.js → chunk-5JSR6TL5.js} +2 -2
  5. package/dist/chunk-BAGYETKM.js +635 -0
  6. package/dist/{chunk-L3GVDMCA.js → chunk-C27LLJM6.js} +3 -195
  7. package/dist/{chunk-O4UB5DQQ.js → chunk-F2J7675J.js} +1 -1
  8. package/dist/chunk-ITCEULI5.js +238 -0
  9. package/dist/{chunk-4WKWLFBZ.js → chunk-P5EWG45B.js} +1 -1
  10. package/dist/{chunk-BS4J2LAW.js → chunk-QTD5HPKD.js} +1 -1
  11. package/dist/{chunk-ZVJKIJFG.js → chunk-RCQPWA5X.js} +13 -42
  12. package/dist/chunk-TLAIQC7B.js +6382 -0
  13. package/dist/{chunk-FEZZ3IDU.js → chunk-TXPUIHX2.js} +10 -10
  14. package/dist/{chunk-L4XXM55J.js → chunk-W4VYXIN7.js} +142 -3
  15. package/dist/chunk-WJ7W7JU4.js +2115 -0
  16. package/dist/{chunk-YNGQ7U5H.js → chunk-WLNEJ6JJ.js} +2 -2
  17. package/dist/{chunk-4INR75ZS.js → chunk-Y2SYGFRF.js} +589 -65
  18. package/dist/components/index.d.ts +333 -73
  19. package/dist/components/index.js +838 -686
  20. package/dist/features/auth/index.d.ts +125 -0
  21. package/dist/features/auth/index.js +2 -2
  22. package/dist/features/dashboard/index.d.ts +28 -2
  23. package/dist/features/dashboard/index.js +21 -635
  24. package/dist/features/monitoring/index.d.ts +28 -1
  25. package/dist/features/monitoring/index.js +19 -529
  26. package/dist/features/operations/index.d.ts +51 -8
  27. package/dist/features/operations/index.js +25 -3760
  28. package/dist/features/settings/index.d.ts +153 -1
  29. package/dist/features/settings/index.js +19 -1438
  30. package/dist/hooks/index.d.ts +262 -25
  31. package/dist/hooks/index.js +12 -8
  32. package/dist/hooks/published.d.ts +137 -25
  33. package/dist/hooks/published.js +11 -7
  34. package/dist/index.d.ts +310 -28
  35. package/dist/index.js +12 -11
  36. package/dist/initialization/index.d.ts +125 -0
  37. package/dist/layout/index.d.ts +2 -0
  38. package/dist/layout/index.js +6 -5
  39. package/dist/organization/index.js +1 -2
  40. package/dist/profile/index.d.ts +125 -0
  41. package/dist/provider/index.d.ts +48 -3
  42. package/dist/provider/index.js +10 -4
  43. package/dist/provider/published.d.ts +48 -3
  44. package/dist/provider/published.js +8 -2
  45. package/dist/supabase/index.d.ts +242 -0
  46. package/dist/theme/index.js +2 -2
  47. package/dist/types/index.d.ts +126 -1
  48. package/package.json +1 -1
  49. package/dist/chunk-LR4WVA7W.js +0 -682
  50. package/dist/chunk-R7WLWGPO.js +0 -126
  51. package/dist/chunk-TCKIAHDC.js +0 -2626
  52. package/dist/chunk-V7XHGJQZ.js +0 -145
  53. package/dist/{chunk-WWEMNIHW.js → chunk-YYBM5LNJ.js} +1 -1
@@ -1,649 +1,35 @@
1
- import { ResourceHealthChart } from '../../chunk-LGKLC5MG.js';
2
- import { ExecutionStats } from '../../chunk-O4UB5DQQ.js';
3
- import { HeroStatsRow, useCyberColors } from '../../chunk-JHVKGZ2P.js';
4
- import { CardHeader, EmptyState, PageTitleCaption, TabCountBadge, GlowDot } from '../../chunk-MCA6LOGM.js';
1
+ export { Dashboard, RecentExecutionsByResource, ResourceOverview, UnresolvedErrorsTeaser, dashboardManifest } from '../../chunk-BAGYETKM.js';
2
+ import '../../chunk-LGKLC5MG.js';
3
+ import '../../chunk-F2J7675J.js';
4
+ import '../../chunk-JHVKGZ2P.js';
5
+ import '../../chunk-MCA6LOGM.js';
5
6
  import '../../chunk-3KMDHCAR.js';
6
7
  import '../../chunk-NNKKBSJN.js';
7
- import { AppShellCenteredContainer, AppShellLoader } from '../../chunk-WWEMNIHW.js';
8
- import '../../chunk-QJ2S46NI.js';
9
- import { useTimeRangeDates } from '../../chunk-YNGQ7U5H.js';
10
- import { useDashboardMetrics, useResources, useUnresolvedErrors, useRecentExecutionsByResource, useCommandQueue, useScheduledTasks, useResourcesHealth } from '../../chunk-ZVJKIJFG.js';
11
- import { getTimeRangeDates } from '../../chunk-LXHZYSMQ.js';
12
- import '../../chunk-MHW43EOH.js';
8
+ import '../../chunk-YYBM5LNJ.js';
9
+ import '../../chunk-WLNEJ6JJ.js';
10
+ import '../../chunk-RCQPWA5X.js';
11
+ import '../../chunk-LXHZYSMQ.js';
13
12
  import '../../chunk-F6RBK7NJ.js';
14
13
  import '../../chunk-XA34RETF.js';
15
- import { ResourceStatusColors } from '../../chunk-ELJIFLCB.js';
16
- import '../../chunk-L4XXM55J.js';
17
- import '../../chunk-SLVC5OJ2.js';
18
- import '../../chunk-RNP5R5I3.js';
19
- import '../../chunk-RMPXGBNI.js';
14
+ import '../../chunk-ELJIFLCB.js';
15
+ import '../../chunk-5JSR6TL5.js';
20
16
  import '../../chunk-SZHARWKU.js';
21
- import '../../chunk-FEZZ3IDU.js';
17
+ import '../../chunk-TXPUIHX2.js';
22
18
  import '../../chunk-CYXZHBP4.js';
23
- import '../../chunk-R7WLWGPO.js';
19
+ import '../../chunk-ITCEULI5.js';
20
+ import '../../chunk-5COLSYBE.js';
24
21
  import '../../chunk-NVOCKXUQ.js';
25
- import '../../chunk-V7XHGJQZ.js';
22
+ import '../../chunk-MHW43EOH.js';
23
+ import '../../chunk-W4VYXIN7.js';
26
24
  import '../../chunk-QJ2KCHKX.js';
27
- import { formatTimeAgo, formatRelativeTime } from '../../chunk-IOKL7BKE.js';
25
+ import '../../chunk-QJ2S46NI.js';
26
+ import '../../chunk-SLVC5OJ2.js';
27
+ import '../../chunk-RNP5R5I3.js';
28
+ import '../../chunk-IOKL7BKE.js';
28
29
  import '../../chunk-RWQIFKMJ.js';
29
30
  import '../../chunk-ALA56RGZ.js';
30
- import { useInitialization } from '../../chunk-TUXTSEAF.js';
31
+ import '../../chunk-TUXTSEAF.js';
31
32
  import '../../chunk-DD3CCMCZ.js';
32
33
  import '../../chunk-QEPXAWE2.js';
33
34
  import '../../chunk-BRJ3QZ4E.js';
34
35
  import '../../chunk-Q7DJKLEN.js';
35
- import { useMemo, useState } from 'react';
36
- import { Paper, Group, Badge, ActionIcon, Center, Loader, SimpleGrid, Stack, Title, Text, Tabs, Box, Card, Grid, ThemeIcon } from '@mantine/core';
37
- import { IconArrowUpRight, IconLayoutDashboard, IconActivity, IconAlertTriangle, IconHandStop, IconCalendarEvent, IconPlayerPlay, IconCircleCheck, IconBrain, IconGitBranch } from '@tabler/icons-react';
38
- import '@mantine/charts/styles.css';
39
- import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
40
-
41
- var DEFAULT_LIMIT = 6;
42
- var typeIcons = {
43
- workflow: IconGitBranch,
44
- agent: IconBrain
45
- };
46
- function ResourceCard({ resource, onClick }) {
47
- const [hovered, setHovered] = useState(false);
48
- const Icon = typeIcons[resource.type] ?? IconActivity;
49
- const cyberColors = useCyberColors();
50
- return /* @__PURE__ */ jsxs(
51
- Card,
52
- {
53
- withBorder: true,
54
- style: {
55
- cursor: "pointer",
56
- transition: "all 150ms ease",
57
- borderColor: hovered ? "color-mix(in srgb, var(--color-primary) 40%, var(--color-border))" : "var(--color-border)",
58
- boxShadow: hovered ? "var(--card-shadow), 0 0 12px color-mix(in srgb, var(--color-primary) 25%, transparent)" : "var(--card-shadow)",
59
- transform: hovered ? "translateY(-1px)" : "none"
60
- },
61
- onMouseEnter: () => setHovered(true),
62
- onMouseLeave: () => setHovered(false),
63
- onClick,
64
- children: [
65
- /* @__PURE__ */ jsxs(Group, { justify: "space-between", mb: "sm", wrap: "nowrap", align: "flex-start", children: [
66
- /* @__PURE__ */ jsxs(Group, { gap: "sm", wrap: "nowrap", style: { minWidth: 0 }, children: [
67
- /* @__PURE__ */ jsx(ThemeIcon, { size: 32, radius: "md", variant: "light", children: /* @__PURE__ */ jsx(Icon, { size: 18 }) }),
68
- /* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, truncate: true, children: resource.name })
69
- ] }),
70
- resource.active && resource.execution ? (() => {
71
- const rate = resource.execution.successRate;
72
- const color = rate >= 95 ? cyberColors.green : rate >= 80 ? cyberColors.yellow : cyberColors.red;
73
- return /* @__PURE__ */ jsxs(Group, { gap: 8, wrap: "nowrap", style: { flexShrink: 0 }, children: [
74
- /* @__PURE__ */ jsxs(Text, { size: "xs", fw: 500, style: { color, letterSpacing: "0.03em" }, children: [
75
- rate.toFixed(0),
76
- "%"
77
- ] }),
78
- /* @__PURE__ */ jsx(GlowDot, { size: "md", color })
79
- ] });
80
- })() : null
81
- ] }),
82
- /* @__PURE__ */ jsxs(Group, { justify: "space-between", wrap: "nowrap", children: [
83
- /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
84
- /* @__PURE__ */ jsx(Badge, { size: "xs", variant: "light", children: resource.type }),
85
- /* @__PURE__ */ jsx(
86
- Badge,
87
- {
88
- size: "xs",
89
- variant: "light",
90
- color: ResourceStatusColors[resource.status],
91
- children: resource.status
92
- }
93
- )
94
- ] }),
95
- resource.active && resource.execution ? /* @__PURE__ */ jsxs(Group, { gap: 4, wrap: "nowrap", style: { flexShrink: 0 }, children: [
96
- /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
97
- resource.execution.totalExecutions,
98
- " runs"
99
- ] }),
100
- /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "\xB7" }),
101
- /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
102
- "Last run ",
103
- formatTimeAgo(resource.execution.lastExecution)
104
- ] })
105
- ] }) : /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "No recent activity" })
106
- ] })
107
- ]
108
- }
109
- );
110
- }
111
- function ResourceOverview({
112
- recentExecutions,
113
- allResources,
114
- isLoading,
115
- limit = DEFAULT_LIMIT,
116
- onResourceClick
117
- }) {
118
- const { displayResources, totalCount } = useMemo(() => {
119
- const items = [];
120
- const seenIds = /* @__PURE__ */ new Set();
121
- const resourceLookup = /* @__PURE__ */ new Map();
122
- if (allResources) {
123
- for (const r of [...allResources.workflows, ...allResources.agents]) {
124
- resourceLookup.set(r.resourceId, r);
125
- }
126
- }
127
- if (recentExecutions) {
128
- for (const exec of recentExecutions) {
129
- const def = resourceLookup.get(exec.resourceId);
130
- items.push({
131
- resourceId: exec.resourceId,
132
- name: def?.name ?? exec.resourceName ?? exec.resourceId,
133
- type: def?.type ?? exec.resourceType ?? "",
134
- status: def?.status ?? "dev",
135
- active: true,
136
- execution: exec
137
- });
138
- seenIds.add(exec.resourceId);
139
- }
140
- }
141
- if (allResources) {
142
- for (const r of [...allResources.workflows, ...allResources.agents]) {
143
- if (!seenIds.has(r.resourceId)) {
144
- items.push({
145
- resourceId: r.resourceId,
146
- name: r.name,
147
- type: r.type,
148
- status: r.status,
149
- active: false
150
- });
151
- seenIds.add(r.resourceId);
152
- }
153
- }
154
- }
155
- return { displayResources: items.slice(0, limit), totalCount: items.length };
156
- }, [recentExecutions, allResources, limit]);
157
- const handleClick = (resource) => {
158
- onResourceClick?.(resource);
159
- };
160
- return /* @__PURE__ */ jsxs(Paper, { withBorder: true, children: [
161
- /* @__PURE__ */ jsx(
162
- CardHeader,
163
- {
164
- icon: /* @__PURE__ */ jsx(IconLayoutDashboard, { size: 18 }),
165
- title: "Resources",
166
- subtitle: totalCount > limit ? `Showing ${limit} of ${totalCount}` : void 0,
167
- rightSection: /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
168
- totalCount > 0 && /* @__PURE__ */ jsxs(Badge, { variant: "light", size: "sm", children: [
169
- totalCount,
170
- " total"
171
- ] }),
172
- /* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", size: "sm", onClick: () => onResourceClick?.(displayResources[0]), children: /* @__PURE__ */ jsx(IconArrowUpRight, { size: 16 }) })
173
- ] })
174
- }
175
- ),
176
- isLoading ? /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, {}) }) : displayResources.length === 0 ? /* @__PURE__ */ jsx(EmptyState, { icon: IconLayoutDashboard, title: "No resources registered" }) : /* @__PURE__ */ jsx(SimpleGrid, { cols: { base: 1, sm: 2, lg: 3 }, children: displayResources.map((resource) => /* @__PURE__ */ jsx(ResourceCard, { resource, onClick: () => handleClick(resource) }, resource.resourceId)) })
177
- ] });
178
- }
179
- var severityColor = {
180
- critical: "red",
181
- warning: "yellow",
182
- info: "blue"
183
- };
184
- function Dashboard({
185
- timeRange,
186
- onResourceClick,
187
- onErrorsNavigate,
188
- onCommandQueueNavigate,
189
- onScheduledTasksNavigate,
190
- renderTrendChart
191
- }) {
192
- const { organizationReady, error: initError } = useInitialization();
193
- const { data: dashboardDataRaw, isLoading, error } = useDashboardMetrics(timeRange);
194
- const dashboardData = dashboardDataRaw;
195
- const { data: resourcesData, isLoading: resourcesLoading } = useResources();
196
- const { startDate, endDate } = useTimeRangeDates(timeRange);
197
- const { data: errorData, isLoading: errorsLoading } = useUnresolvedErrors({ startDate, endDate });
198
- const { data: recentExecData, isLoading: recentExecLoading } = useRecentExecutionsByResource({
199
- timeRange,
200
- limit: 6
201
- });
202
- if (initError?.layer === "organization") {
203
- return /* @__PURE__ */ jsx(AppShellCenteredContainer, { children: /* @__PURE__ */ jsxs(Stack, { align: "center", justify: "center", children: [
204
- /* @__PURE__ */ jsx(Title, { order: 3, c: "dimmed", children: "No organization detected" }),
205
- /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: initError?.message })
206
- ] }) });
207
- }
208
- if (!organizationReady || isLoading || resourcesLoading) return /* @__PURE__ */ jsx(AppShellLoader, {});
209
- return /* @__PURE__ */ jsxs(Fragment, { children: [
210
- /* @__PURE__ */ jsx(PageTitleCaption, { title: "Dashboard", caption: "AI Operations Health & Performance" }),
211
- /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
212
- /* @__PURE__ */ jsx(
213
- HeroStatsRow,
214
- {
215
- resourcesData,
216
- resourcesLoading,
217
- dashboardData,
218
- dashboardLoading: isLoading,
219
- unresolvedErrorCount: errorData?.total ?? null,
220
- errorsLoading
221
- }
222
- ),
223
- renderTrendChart?.(dashboardData?.executionHealth, isLoading, error ?? void 0)
224
- ] }),
225
- /* @__PURE__ */ jsx(
226
- ResourceOverview,
227
- {
228
- recentExecutions: recentExecData?.resources,
229
- allResources: resourcesData,
230
- isLoading: resourcesLoading || recentExecLoading,
231
- limit: 6,
232
- onResourceClick: onResourceClick ? (resource) => onResourceClick({
233
- resourceId: resource.resourceId,
234
- resourceType: resource.type
235
- }) : void 0
236
- }
237
- ),
238
- /* @__PURE__ */ jsx(
239
- OperationalOverview,
240
- {
241
- timeRange,
242
- onErrorsNavigate,
243
- onCommandQueueNavigate,
244
- onScheduledTasksNavigate
245
- }
246
- )
247
- ] });
248
- }
249
- function OperationalOverview({
250
- timeRange,
251
- onErrorsNavigate,
252
- onCommandQueueNavigate,
253
- onScheduledTasksNavigate
254
- }) {
255
- const { startDate, endDate } = useTimeRangeDates(timeRange);
256
- const { data: errorData, isLoading: errorsLoading } = useUnresolvedErrors({ startDate, endDate });
257
- const errors = errorData?.errors ?? [];
258
- const errorCount = errorData?.total ?? 0;
259
- const { data: allCommands } = useCommandQueue({ status: "pending", limit: 100 });
260
- const commands = allCommands ?? [];
261
- const commandCount = commands.length;
262
- const { data: allTasks, isLoading: tasksLoading } = useScheduledTasks();
263
- const tasks = allTasks ?? [];
264
- const now = /* @__PURE__ */ new Date();
265
- const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
266
- const { totalScheduled, upcomingTasks } = useMemo(() => {
267
- const totalScheduled2 = tasks.filter((t) => t.status === "active").length;
268
- const upcomingTasks2 = tasks.filter((t) => t.status === "active" && t.nextRunAt).sort((a, b) => new Date(a.nextRunAt).getTime() - new Date(b.nextRunAt).getTime()).slice(0, 5);
269
- return { totalScheduled: totalScheduled2, upcomingTasks: upcomingTasks2 };
270
- }, [tasks]);
271
- const defaultTab = useMemo(() => {
272
- if (errorCount > 0) return "errors";
273
- if (commandCount > 0) return "commands";
274
- if (totalScheduled > 0) return "scheduled";
275
- return "errors";
276
- }, [errorCount, commandCount, totalScheduled]);
277
- const [activeTab, setActiveTab] = useState(null);
278
- const effectiveTab = activeTab ?? defaultTab;
279
- const formatDaysUntil = (runAt) => {
280
- const diffMs = runAt.getTime() - now.getTime();
281
- const diffDays = Math.floor(diffMs / (1e3 * 60 * 60 * 24));
282
- const diffHours = Math.floor(diffMs / (1e3 * 60 * 60));
283
- if (diffHours < 0) return "Overdue";
284
- if (diffHours < 1) return "Soon";
285
- if (diffDays === 0) return "Today";
286
- if (diffDays === 1) return "Tomorrow";
287
- if (diffDays <= 7) return `In ${diffDays}d`;
288
- return `In ${Math.floor(diffDays / 7)}w`;
289
- };
290
- return /* @__PURE__ */ jsxs(Paper, { withBorder: true, children: [
291
- /* @__PURE__ */ jsx(CardHeader, { icon: /* @__PURE__ */ jsx(IconActivity, { size: 18 }), title: "Operational Overview" }),
292
- /* @__PURE__ */ jsxs(Tabs, { value: effectiveTab, onChange: setActiveTab, variant: "default", children: [
293
- /* @__PURE__ */ jsxs(Tabs.List, { children: [
294
- /* @__PURE__ */ jsx(
295
- Tabs.Tab,
296
- {
297
- value: "errors",
298
- leftSection: /* @__PURE__ */ jsx(IconAlertTriangle, { size: 16 }),
299
- rightSection: /* @__PURE__ */ jsx(TabCountBadge, { count: errorCount, isLoading: errorsLoading }),
300
- children: "Unresolved Errors"
301
- }
302
- ),
303
- /* @__PURE__ */ jsx(
304
- Tabs.Tab,
305
- {
306
- value: "commands",
307
- leftSection: /* @__PURE__ */ jsx(IconHandStop, { size: 16 }),
308
- rightSection: /* @__PURE__ */ jsx(TabCountBadge, { count: commandCount }),
309
- children: "Command Queue"
310
- }
311
- ),
312
- /* @__PURE__ */ jsx(
313
- Tabs.Tab,
314
- {
315
- value: "scheduled",
316
- leftSection: /* @__PURE__ */ jsx(IconCalendarEvent, { size: 16 }),
317
- rightSection: /* @__PURE__ */ jsx(TabCountBadge, { count: totalScheduled, isLoading: tasksLoading }),
318
- children: "Scheduled Tasks"
319
- }
320
- )
321
- ] }),
322
- /* @__PURE__ */ jsx(Tabs.Panel, { value: "errors", pt: "sm", children: errorsLoading ? /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, {}) }) : errors.length === 0 ? /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "No unresolved errors" }) : /* @__PURE__ */ jsxs(Stack, { gap: 4, children: [
323
- errors.map((error) => /* @__PURE__ */ jsx(
324
- Box,
325
- {
326
- px: "sm",
327
- py: 6,
328
- onClick: onErrorsNavigate,
329
- style: {
330
- borderRadius: 4,
331
- cursor: onErrorsNavigate ? "pointer" : "default"
332
- },
333
- children: /* @__PURE__ */ jsxs(Group, { justify: "space-between", wrap: "nowrap", children: [
334
- /* @__PURE__ */ jsxs(Group, { gap: "xs", wrap: "nowrap", style: { minWidth: 200, width: 200, flexShrink: 0 }, children: [
335
- /* @__PURE__ */ jsx(
336
- Box,
337
- {
338
- style: {
339
- width: 8,
340
- height: 8,
341
- borderRadius: "50%",
342
- backgroundColor: `var(--mantine-color-${severityColor[error.severity]}-6)`,
343
- flexShrink: 0
344
- }
345
- }
346
- ),
347
- /* @__PURE__ */ jsxs(Stack, { gap: 0, style: { minWidth: 0 }, children: [
348
- /* @__PURE__ */ jsx(Text, { size: "xs", lineClamp: 1, children: error.resourceName || error.resourceId }),
349
- /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", lineClamp: 1, children: error.errorType })
350
- ] })
351
- ] }),
352
- /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", lineClamp: 1, style: { flex: "1 1 auto", minWidth: 0 }, children: error.message }),
353
- /* @__PURE__ */ jsxs(Group, { gap: 4, wrap: "nowrap", style: { flexShrink: 0 }, children: [
354
- /* @__PURE__ */ jsx(Badge, { size: "xs", variant: "light", color: severityColor[error.severity], children: error.severity }),
355
- /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: formatTimeAgo(error.timestamp) })
356
- ] })
357
- ] })
358
- },
359
- error.id
360
- )),
361
- errorCount > 5 && /* @__PURE__ */ jsx(
362
- Group,
363
- {
364
- gap: 4,
365
- justify: "center",
366
- pt: 4,
367
- onClick: onErrorsNavigate,
368
- style: { cursor: onErrorsNavigate ? "pointer" : "default" },
369
- children: /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "See all errors" })
370
- }
371
- )
372
- ] }) }),
373
- /* @__PURE__ */ jsx(Tabs.Panel, { value: "commands", pt: "sm", children: commands.length === 0 ? /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "No pending decisions" }) : /* @__PURE__ */ jsx(Stack, { gap: 4, children: commands.slice(0, 5).map((task) => /* @__PURE__ */ jsx(
374
- Box,
375
- {
376
- px: "sm",
377
- py: 6,
378
- onClick: onCommandQueueNavigate,
379
- style: {
380
- borderRadius: 4,
381
- cursor: onCommandQueueNavigate ? "pointer" : "default"
382
- },
383
- children: /* @__PURE__ */ jsxs(Group, { justify: "space-between", wrap: "nowrap", children: [
384
- /* @__PURE__ */ jsxs(Group, { gap: "xs", wrap: "nowrap", style: { minWidth: 0 }, children: [
385
- /* @__PURE__ */ jsx(
386
- Box,
387
- {
388
- style: {
389
- width: 8,
390
- height: 8,
391
- borderRadius: "50%",
392
- backgroundColor: `var(--mantine-color-${task.priority >= 8 ? "red" : task.priority >= 4 ? "yellow" : "blue"}-6)`,
393
- flexShrink: 0
394
- }
395
- }
396
- ),
397
- /* @__PURE__ */ jsx(Text, { size: "xs", lineClamp: 1, children: task.description || "No description" })
398
- ] }),
399
- /* @__PURE__ */ jsx(Badge, { size: "xs", variant: "light", children: task.status })
400
- ] })
401
- },
402
- task.id
403
- )) }) }),
404
- /* @__PURE__ */ jsx(Tabs.Panel, { value: "scheduled", pt: "sm", children: tasksLoading ? /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, {}) }) : upcomingTasks.length === 0 ? /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "No scheduled tasks" }) : /* @__PURE__ */ jsx(Stack, { gap: 4, children: upcomingTasks.map((task) => {
405
- const runAt = new Date(task.nextRunAt);
406
- const daysUntilNum = Math.floor((runAt.getTime() - today.getTime()) / (1e3 * 60 * 60 * 24));
407
- return /* @__PURE__ */ jsx(
408
- Box,
409
- {
410
- px: "sm",
411
- py: 6,
412
- onClick: onScheduledTasksNavigate,
413
- style: {
414
- borderRadius: 4,
415
- cursor: onScheduledTasksNavigate ? "pointer" : "default"
416
- },
417
- children: /* @__PURE__ */ jsxs(Group, { justify: "space-between", wrap: "nowrap", children: [
418
- /* @__PURE__ */ jsxs(Group, { gap: "xs", wrap: "nowrap", style: { minWidth: 0 }, children: [
419
- /* @__PURE__ */ jsx(
420
- Box,
421
- {
422
- style: {
423
- width: 8,
424
- height: 8,
425
- borderRadius: "50%",
426
- backgroundColor: `var(--mantine-color-${daysUntilNum < 0 ? "red" : daysUntilNum <= 1 ? "yellow" : "blue"}-6)`,
427
- flexShrink: 0
428
- }
429
- }
430
- ),
431
- /* @__PURE__ */ jsx(Text, { size: "xs", truncate: true, children: task.name || task.target.resourceId })
432
- ] }),
433
- /* @__PURE__ */ jsx(Badge, { size: "xs", variant: "light", color: daysUntilNum <= 1 ? void 0 : "gray", children: formatDaysUntil(runAt) })
434
- ] })
435
- },
436
- task.id
437
- );
438
- }) }) })
439
- ] })
440
- ] });
441
- }
442
- var entityTypeConfig = {
443
- workflow: { icon: IconGitBranch, hasPath: true },
444
- agent: { icon: IconBrain, hasPath: true }
445
- };
446
- function getEntityConfig(entityType) {
447
- return entityTypeConfig[entityType] || { icon: IconActivity, hasPath: false };
448
- }
449
- function RecentExecutionsByResource({ timeRange, limit = 5, onResourceClick }) {
450
- const { data, isLoading, isFetching, error } = useRecentExecutionsByResource({
451
- timeRange,
452
- limit
453
- });
454
- const showLoading = (isLoading || isFetching) && !data;
455
- const { data: resourcesData } = useResources();
456
- const resourceDefLookup = useMemo(() => {
457
- if (!resourcesData) return /* @__PURE__ */ new Map();
458
- const allResources = [...resourcesData.workflows || [], ...resourcesData.agents || []];
459
- return new Map(allResources.map((r) => [r.resourceId, r]));
460
- }, [resourcesData]);
461
- const enrichedExecutions = useMemo(() => {
462
- if (!data?.resources) return [];
463
- return data.resources.map((exec) => {
464
- const resourceDef = resourceDefLookup.get(exec.resourceId);
465
- return {
466
- ...exec,
467
- resourceType: resourceDef?.type || "",
468
- resourceName: resourceDef?.name || exec.resourceId
469
- };
470
- });
471
- }, [data, resourceDefLookup]);
472
- const resourceIds = useMemo(
473
- () => enrichedExecutions.map((r) => ({
474
- entityType: r.resourceType,
475
- entityId: r.resourceId
476
- })),
477
- [enrichedExecutions]
478
- );
479
- const { startDate, endDate } = useMemo(() => getTimeRangeDates(timeRange), [timeRange]);
480
- const granularity = timeRange === "1h" || timeRange === "24h" ? "hour" : "day";
481
- const { data: healthData } = useResourcesHealth({
482
- resources: resourceIds,
483
- startDate,
484
- endDate,
485
- granularity
486
- });
487
- const healthLookup = useMemo(() => {
488
- if (!healthData?.resources) return /* @__PURE__ */ new Map();
489
- return new Map(healthData.resources.map((r) => [`${r.entityType}-${r.entityId}`, r]));
490
- }, [healthData]);
491
- const handleResourceClick = (resource) => {
492
- const config = getEntityConfig(resource.resourceType);
493
- if (config.hasPath) {
494
- onResourceClick?.({ resourceType: resource.resourceType, resourceId: resource.resourceId });
495
- }
496
- };
497
- if (showLoading) {
498
- return /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, {}) });
499
- }
500
- if (error) {
501
- return /* @__PURE__ */ jsx(Center, { py: "md", children: /* @__PURE__ */ jsxs(Text, { size: "sm", c: "red.6", children: [
502
- "Failed to load: ",
503
- error.message
504
- ] }) });
505
- }
506
- if (enrichedExecutions.length === 0) {
507
- return /* @__PURE__ */ jsx(EmptyState, { icon: IconPlayerPlay, title: "No executions in this time range" });
508
- }
509
- return /* @__PURE__ */ jsx(Stack, { gap: "sm", children: enrichedExecutions.map((resource) => {
510
- const config = getEntityConfig(resource.resourceType);
511
- const Icon = config.icon;
512
- const resourceKey = `${resource.resourceType}-${resource.resourceId}`;
513
- const resourceHealth = healthLookup.get(resourceKey);
514
- const resourceDef = resourceDefLookup.get(resource.resourceId);
515
- return /* @__PURE__ */ jsx(
516
- Card,
517
- {
518
- withBorder: true,
519
- style: {
520
- cursor: config.hasPath ? "pointer" : "default",
521
- transition: "box-shadow var(--duration-fast) var(--easing)"
522
- },
523
- onClick: () => handleResourceClick(resource),
524
- children: /* @__PURE__ */ jsxs(Grid, { gutter: "sm", align: "center", children: [
525
- /* @__PURE__ */ jsx(Grid.Col, { span: 8, children: /* @__PURE__ */ jsxs(Group, { gap: "sm", wrap: "nowrap", children: [
526
- /* @__PURE__ */ jsx(Icon, { size: 24, color: "var(--color-primary)" }),
527
- /* @__PURE__ */ jsxs(Stack, { gap: 4, style: { flex: 1, minWidth: 0 }, children: [
528
- /* @__PURE__ */ jsx(Text, { size: "sm", fw: 500, truncate: true, children: resource.resourceName }),
529
- resourceDef?.description && /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", truncate: true, children: resourceDef.description }),
530
- /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
531
- resourceDef?.version && /* @__PURE__ */ jsxs(Badge, { variant: "outline", size: "xs", children: [
532
- "v",
533
- resourceDef.version
534
- ] }),
535
- resourceDef?.status && /* @__PURE__ */ jsx(Badge, { color: ResourceStatusColors[resourceDef.status], variant: "outline", size: "xs", children: resourceDef.status.toUpperCase() })
536
- ] }),
537
- /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
538
- "Last run ",
539
- formatRelativeTime(resource.lastExecution)
540
- ] })
541
- ] })
542
- ] }) }),
543
- /* @__PURE__ */ jsx(Grid.Col, { span: 4, children: /* @__PURE__ */ jsxs(Group, { justify: "flex-end", gap: "md", wrap: "nowrap", children: [
544
- /* @__PURE__ */ jsx(
545
- ExecutionStats,
546
- {
547
- totalExecutions: resource.totalExecutions,
548
- successCount: resource.successCount,
549
- failureCount: resource.failureCount,
550
- warningCount: resource.warningCount,
551
- successRate: resource.successRate
552
- }
553
- ),
554
- /* @__PURE__ */ jsx(
555
- ResourceHealthChart,
556
- {
557
- healthData: resourceHealth,
558
- hasExecutions: resource.totalExecutions > 0,
559
- width: 300,
560
- height: 60
561
- }
562
- )
563
- ] }) })
564
- ] })
565
- },
566
- resource.resourceId
567
- );
568
- }) });
569
- }
570
- var severityColor2 = {
571
- critical: "red",
572
- warning: "yellow",
573
- info: "blue"
574
- };
575
- function UnresolvedErrorsTeaser({ timeRange, onNavigateToAllErrors }) {
576
- const { startDate, endDate } = useTimeRangeDates(timeRange);
577
- const { data, isLoading } = useUnresolvedErrors({ startDate, endDate });
578
- const errors = data?.errors ?? [];
579
- const total = data?.total ?? 0;
580
- if (isLoading) {
581
- return /* @__PURE__ */ jsx(
582
- Paper,
583
- {
584
- style: {
585
- background: "var(--glass-background)",
586
- backdropFilter: "var(--glass-blur)",
587
- border: "1px solid var(--color-border)",
588
- borderRadius: 8
589
- },
590
- children: /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, {}) })
591
- }
592
- );
593
- }
594
- return /* @__PURE__ */ jsxs(
595
- Paper,
596
- {
597
- style: {
598
- background: "var(--glass-background)",
599
- backdropFilter: "var(--glass-blur)",
600
- border: "1px solid var(--color-border)",
601
- borderRadius: 8
602
- },
603
- children: [
604
- /* @__PURE__ */ jsxs(Group, { justify: "space-between", mb: errors.length > 0 ? "sm" : 0, children: [
605
- /* @__PURE__ */ jsxs(Group, { gap: "sm", children: [
606
- /* @__PURE__ */ jsx(ThemeIcon, { size: 28, radius: "md", variant: "light", color: total > 0 ? "red" : "green", children: total > 0 ? /* @__PURE__ */ jsx(IconAlertTriangle, { size: 16 }) : /* @__PURE__ */ jsx(IconCircleCheck, { size: 16 }) }),
607
- /* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, children: "Unresolved Errors" })
608
- ] }),
609
- /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
610
- total > 0 && /* @__PURE__ */ jsxs(Badge, { size: "xs", variant: "light", color: "red", children: [
611
- total,
612
- " unresolved"
613
- ] }),
614
- /* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", size: "sm", onClick: onNavigateToAllErrors, children: /* @__PURE__ */ jsx(IconArrowUpRight, { size: 14 }) })
615
- ] })
616
- ] }),
617
- errors.length === 0 && /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "No unresolved errors" }),
618
- errors.length > 0 && /* @__PURE__ */ jsx(Stack, { gap: 4, children: errors.map((error) => /* @__PURE__ */ jsx(
619
- Box,
620
- {
621
- px: "sm",
622
- py: 6,
623
- onClick: onNavigateToAllErrors,
624
- style: {
625
- borderLeft: `2px solid var(--mantine-color-${severityColor2[error.severity]}-6)`,
626
- borderRadius: 4,
627
- cursor: onNavigateToAllErrors ? "pointer" : "default",
628
- textDecoration: "none",
629
- color: "inherit"
630
- },
631
- children: /* @__PURE__ */ jsxs(Group, { justify: "space-between", wrap: "nowrap", children: [
632
- /* @__PURE__ */ jsxs(Stack, { gap: 0, style: { minWidth: 0 }, children: [
633
- /* @__PURE__ */ jsx(Text, { size: "xs", lineClamp: 1, children: error.resourceName || error.resourceId }),
634
- /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", lineClamp: 1, children: error.errorType })
635
- ] }),
636
- /* @__PURE__ */ jsxs(Group, { gap: 4, wrap: "nowrap", style: { flexShrink: 0 }, children: [
637
- /* @__PURE__ */ jsx(Badge, { size: "xs", variant: "light", color: severityColor2[error.severity], children: error.severity }),
638
- /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: formatTimeAgo(error.timestamp) })
639
- ] })
640
- ] })
641
- },
642
- error.id
643
- )) })
644
- ]
645
- }
646
- );
647
- }
648
-
649
- export { Dashboard, RecentExecutionsByResource, ResourceOverview, UnresolvedErrorsTeaser };