@elevasis/ui 1.19.0 → 1.20.1

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