@alepha/ui 0.16.2 → 0.17.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 (175) hide show
  1. package/dist/admin/{AdminApiKeys-CoTOTfgU.js → AdminApiKeys-CF_qOO3u.js} +20 -20
  2. package/dist/admin/AdminApiKeys-CF_qOO3u.js.map +1 -0
  3. package/dist/admin/{AdminAudits-BmsxFbDa.js → AdminAudits-BQno3hZG.js} +7 -8
  4. package/dist/admin/AdminAudits-BQno3hZG.js.map +1 -0
  5. package/dist/admin/{AdminFiles-BBB8knca.js → AdminFiles-kvuUaASF.js} +3 -5
  6. package/dist/admin/{AdminFiles-BBB8knca.js.map → AdminFiles-kvuUaASF.js.map} +1 -1
  7. package/dist/admin/AdminJobDashboard-CrPxp0W1.js +485 -0
  8. package/dist/admin/AdminJobDashboard-CrPxp0W1.js.map +1 -0
  9. package/dist/admin/AdminJobExecutions-D-b4Zt7W.js +678 -0
  10. package/dist/admin/AdminJobExecutions-D-b4Zt7W.js.map +1 -0
  11. package/dist/admin/AdminJobRegistry-CNX5cpDx.js +301 -0
  12. package/dist/admin/AdminJobRegistry-CNX5cpDx.js.map +1 -0
  13. package/dist/admin/{AdminLayout-CsjvpeD1.js → AdminLayout-e-ZP5nWw.js} +1 -1
  14. package/dist/admin/{AdminLayout-CsjvpeD1.js.map → AdminLayout-e-ZP5nWw.js.map} +1 -1
  15. package/dist/admin/{AdminNotifications-LwR6RKrx.js → AdminNotifications-DeHJFf6W.js} +3 -5
  16. package/dist/admin/{AdminNotifications-LwR6RKrx.js.map → AdminNotifications-DeHJFf6W.js.map} +1 -1
  17. package/dist/admin/{AdminParameters-B_83Vie9.js → AdminParameters-iQE8o7a7.js} +43 -36
  18. package/dist/admin/AdminParameters-iQE8o7a7.js.map +1 -0
  19. package/dist/admin/{AdminSessions-CWnPosdd.js → AdminSessions-oKJCbd7w.js} +5 -7
  20. package/dist/admin/AdminSessions-oKJCbd7w.js.map +1 -0
  21. package/dist/admin/{AdminUserAudits-nHv636E_.js → AdminUserAudits-BNCEle_E.js} +6 -8
  22. package/dist/admin/AdminUserAudits-BNCEle_E.js.map +1 -0
  23. package/dist/admin/{AdminUserCreate-CjYD3Kjc.js → AdminUserCreate-CgqeFwCt.js} +6 -7
  24. package/dist/admin/AdminUserCreate-CgqeFwCt.js.map +1 -0
  25. package/dist/admin/{AdminUserDetails-Ccq-LsZ0.js → AdminUserDetails-DDe1A1GP.js} +30 -29
  26. package/dist/admin/AdminUserDetails-DDe1A1GP.js.map +1 -0
  27. package/dist/admin/{AdminUserLayout-7s41DiF_.js → AdminUserLayout-HAlobhWf.js} +18 -16
  28. package/dist/admin/AdminUserLayout-HAlobhWf.js.map +1 -0
  29. package/dist/admin/{AdminUserSessions-Ds3ODq_d.js → AdminUserSessions-Bq1LnVLf.js} +5 -7
  30. package/dist/admin/AdminUserSessions-Bq1LnVLf.js.map +1 -0
  31. package/dist/admin/{AdminUserSettings-CGh4gROo.js → AdminUserSettings-BRsBZoxV.js} +10 -10
  32. package/dist/admin/AdminUserSettings-BRsBZoxV.js.map +1 -0
  33. package/dist/admin/{AdminUsers-CvPiBzQK.js → AdminUsers-D71kIOSn.js} +6 -8
  34. package/dist/admin/AdminUsers-D71kIOSn.js.map +1 -0
  35. package/dist/admin/index.d.ts +7 -83
  36. package/dist/admin/index.d.ts.map +1 -1
  37. package/dist/admin/index.js +49 -70
  38. package/dist/admin/index.js.map +1 -1
  39. package/dist/auth/{Login-DS_OqA0G.js → Login-BS_FYTy0.js} +13 -8
  40. package/dist/auth/Login-BS_FYTy0.js.map +1 -0
  41. package/dist/auth/{Profile-Di7N7HZL.js → Profile-CjDsW378.js} +16 -10
  42. package/dist/auth/Profile-CjDsW378.js.map +1 -0
  43. package/dist/auth/{Register-BRR2_gux.js → Register-C5eqzAaD.js} +21 -12
  44. package/dist/auth/Register-C5eqzAaD.js.map +1 -0
  45. package/dist/auth/{ResetPassword-oQu72lod.js → ResetPassword-XifinVao.js} +14 -8
  46. package/dist/auth/ResetPassword-XifinVao.js.map +1 -0
  47. package/dist/auth/{VerifyEmail-DC6HPZjd.js → VerifyEmail-DTgbeJOO.js} +6 -4
  48. package/dist/auth/VerifyEmail-DTgbeJOO.js.map +1 -0
  49. package/dist/auth/index.d.ts +4 -0
  50. package/dist/auth/index.d.ts.map +1 -1
  51. package/dist/auth/index.js +15 -14
  52. package/dist/auth/index.js.map +1 -1
  53. package/dist/core/index.d.ts +37 -26
  54. package/dist/core/index.d.ts.map +1 -1
  55. package/dist/core/index.js +444 -193
  56. package/dist/core/index.js.map +1 -1
  57. package/dist/demo/DemoDataTable-lnBKWBf8.js +362 -0
  58. package/dist/demo/DemoDataTable-lnBKWBf8.js.map +1 -0
  59. package/dist/demo/{DemoHome-DpRrPlBC.js → DemoHome-CUMZsYaH.js} +6 -7
  60. package/dist/demo/DemoHome-CUMZsYaH.js.map +1 -0
  61. package/dist/demo/{DemoJsonViewer-zeucGKHV.js → DemoJsonViewer-_uokbGaW.js} +17 -19
  62. package/dist/demo/DemoJsonViewer-_uokbGaW.js.map +1 -0
  63. package/dist/demo/{DemoLayout-PhgbAAiQ.js → DemoLayout-DHVoacE6.js} +2 -4
  64. package/dist/demo/{DemoLayout-PhgbAAiQ.js.map → DemoLayout-DHVoacE6.js.map} +1 -1
  65. package/dist/demo/{DemoLogin-DSzP0Lkv.js → DemoLogin-DjJ9314c.js} +22 -17
  66. package/dist/demo/DemoLogin-DjJ9314c.js.map +1 -0
  67. package/dist/demo/{DemoRegister-DavFBsCz.js → DemoRegister-DzkJ5M83.js} +34 -25
  68. package/dist/demo/DemoRegister-DzkJ5M83.js.map +1 -0
  69. package/dist/demo/{DemoResetPassword-BS2rIAQK.js → DemoResetPassword-DWh4_BpQ.js} +27 -21
  70. package/dist/demo/DemoResetPassword-DWh4_BpQ.js.map +1 -0
  71. package/dist/demo/{DemoSidebar-zNkUmHRl.js → DemoSidebar-C1csnGhX.js} +2 -2
  72. package/dist/demo/{DemoSidebar-zNkUmHRl.js.map → DemoSidebar-C1csnGhX.js.map} +1 -1
  73. package/dist/demo/{DemoTypeForm-B9q7oT0b.js → DemoTypeForm-CWz6fJrJ.js} +2 -2
  74. package/dist/demo/{DemoTypeForm-B9q7oT0b.js.map → DemoTypeForm-CWz6fJrJ.js.map} +1 -1
  75. package/dist/demo/{DemoVerifyEmail-Bi4SdWz0.js → DemoVerifyEmail-DbU_tCj8.js} +13 -11
  76. package/dist/demo/DemoVerifyEmail-DbU_tCj8.js.map +1 -0
  77. package/dist/demo/{IconGoogle-CTeZyrek.js → IconGoogle-Ch1m3Uzl.js} +1 -1
  78. package/dist/demo/{IconGoogle-CTeZyrek.js.map → IconGoogle-Ch1m3Uzl.js.map} +1 -1
  79. package/dist/demo/{Showcase-C9btr_SJ.js → Showcase-BzoXNlCn.js} +10 -10
  80. package/dist/demo/Showcase-BzoXNlCn.js.map +1 -0
  81. package/dist/demo/index.d.ts +1 -68
  82. package/dist/demo/index.d.ts.map +1 -1
  83. package/dist/demo/index.js +11 -15
  84. package/dist/demo/index.js.map +1 -1
  85. package/dist/json/index.js +2 -2
  86. package/dist/json/index.js.map +1 -1
  87. package/package.json +9 -5
  88. package/src/admin/AdminRouter.ts +36 -5
  89. package/src/admin/components/audits/AdminAudits.tsx +5 -5
  90. package/src/admin/components/jobs/AdminJobDashboard.tsx +455 -0
  91. package/src/admin/components/jobs/AdminJobExecutions.tsx +693 -0
  92. package/src/admin/components/jobs/AdminJobRegistry.tsx +325 -0
  93. package/src/admin/components/keys/AdminApiKeys.tsx +28 -31
  94. package/src/admin/components/parameters/AdminParameters.tsx +3 -3
  95. package/src/admin/components/parameters/ParameterDetails.tsx +34 -29
  96. package/src/admin/components/parameters/ParameterEmptyState.tsx +5 -5
  97. package/src/admin/components/parameters/ParameterHistory.tsx +11 -19
  98. package/src/admin/components/parameters/ParameterTree.tsx +16 -18
  99. package/src/admin/components/sessions/AdminSessions.tsx +3 -3
  100. package/src/admin/components/shared/AdminResourceHeader.tsx +20 -16
  101. package/src/admin/components/users/AdminUserAudits.tsx +5 -5
  102. package/src/admin/components/users/AdminUserCreate.tsx +3 -3
  103. package/src/admin/components/users/AdminUserDetails.tsx +51 -53
  104. package/src/admin/components/users/AdminUserLayout.tsx +7 -7
  105. package/src/admin/components/users/AdminUserSessions.tsx +3 -3
  106. package/src/admin/components/users/AdminUserSettings.tsx +9 -9
  107. package/src/admin/components/users/AdminUsers.tsx +5 -5
  108. package/src/admin/components/verifications/AdminVerifications.tsx +3 -3
  109. package/src/admin/index.ts +0 -24
  110. package/src/auth/components/Login.tsx +13 -13
  111. package/src/auth/components/Profile.tsx +17 -26
  112. package/src/auth/components/Register.tsx +21 -31
  113. package/src/auth/components/ResetPassword.tsx +13 -22
  114. package/src/auth/components/VerifyEmail.tsx +5 -5
  115. package/src/auth/components/buttons/UserButton.tsx +14 -4
  116. package/src/core/components/buttons/ActionButton.tsx +9 -2
  117. package/src/core/components/data/ErrorViewer.tsx +15 -15
  118. package/src/core/components/dialogs/AlertDialog.tsx +3 -3
  119. package/src/core/components/dialogs/ConfirmDialog.tsx +3 -3
  120. package/src/core/components/dialogs/PromptDialog.tsx +3 -3
  121. package/src/core/components/form/Control.tsx +9 -0
  122. package/src/core/components/form/ControlArray.tsx +6 -7
  123. package/src/core/components/form/ControlObject.tsx +3 -3
  124. package/src/core/components/form/ControlQueryBuilder.tsx +20 -22
  125. package/src/core/components/form/ControlSelect.tsx +4 -0
  126. package/src/core/components/form/TypeForm.tsx +7 -0
  127. package/src/core/components/layout/Breadcrumb.tsx +6 -6
  128. package/src/core/components/layout/Omnibar.tsx +2 -1
  129. package/src/core/components/layout/Sidebar.tsx +5 -1
  130. package/src/core/components/table/ColumnPicker.tsx +47 -31
  131. package/src/core/components/table/DataTable.tsx +277 -201
  132. package/src/core/components/table/DataTableFilters.tsx +8 -0
  133. package/src/core/components/table/DataTableToolbar.tsx +98 -5
  134. package/src/core/components/table/FilterPicker.tsx +28 -26
  135. package/src/core/components/table/types.ts +52 -37
  136. package/src/core/components/table/useTableSelection.ts +83 -0
  137. package/src/core/styles.css +1 -0
  138. package/src/core/utils/parseInput.ts +1 -0
  139. package/src/demo/components/DemoHome.tsx +5 -5
  140. package/src/demo/components/core/DemoDataTable.tsx +209 -5
  141. package/src/demo/components/json/DemoJsonViewer.tsx +1 -1
  142. package/src/demo/components/shared/MacWindow.tsx +7 -7
  143. package/src/demo/components/shared/Showcase.tsx +3 -3
  144. package/src/demo/index.ts +0 -11
  145. package/src/json/components/JsonViewer.tsx +3 -3
  146. package/dist/admin/AdminApiKeys-CoTOTfgU.js.map +0 -1
  147. package/dist/admin/AdminAudits-BmsxFbDa.js.map +0 -1
  148. package/dist/admin/AdminJobs-C604joTz.js +0 -698
  149. package/dist/admin/AdminJobs-C604joTz.js.map +0 -1
  150. package/dist/admin/AdminParameters-B_83Vie9.js.map +0 -1
  151. package/dist/admin/AdminSessions-CWnPosdd.js.map +0 -1
  152. package/dist/admin/AdminUserAudits-nHv636E_.js.map +0 -1
  153. package/dist/admin/AdminUserCreate-CjYD3Kjc.js.map +0 -1
  154. package/dist/admin/AdminUserDetails-Ccq-LsZ0.js.map +0 -1
  155. package/dist/admin/AdminUserLayout-7s41DiF_.js.map +0 -1
  156. package/dist/admin/AdminUserSessions-Ds3ODq_d.js.map +0 -1
  157. package/dist/admin/AdminUserSettings-CGh4gROo.js.map +0 -1
  158. package/dist/admin/AdminUsers-CvPiBzQK.js.map +0 -1
  159. package/dist/admin/rolldown-runtime-CjeV3_4I.js +0 -18
  160. package/dist/auth/Login-DS_OqA0G.js.map +0 -1
  161. package/dist/auth/Profile-Di7N7HZL.js.map +0 -1
  162. package/dist/auth/Register-BRR2_gux.js.map +0 -1
  163. package/dist/auth/ResetPassword-oQu72lod.js.map +0 -1
  164. package/dist/auth/VerifyEmail-DC6HPZjd.js.map +0 -1
  165. package/dist/demo/DemoDataTable-DCsJq8v5.js +0 -149
  166. package/dist/demo/DemoDataTable-DCsJq8v5.js.map +0 -1
  167. package/dist/demo/DemoHome-DpRrPlBC.js.map +0 -1
  168. package/dist/demo/DemoJsonViewer-zeucGKHV.js.map +0 -1
  169. package/dist/demo/DemoLogin-DSzP0Lkv.js.map +0 -1
  170. package/dist/demo/DemoRegister-DavFBsCz.js.map +0 -1
  171. package/dist/demo/DemoResetPassword-BS2rIAQK.js.map +0 -1
  172. package/dist/demo/DemoVerifyEmail-Bi4SdWz0.js.map +0 -1
  173. package/dist/demo/Showcase-C9btr_SJ.js.map +0 -1
  174. package/dist/demo/rolldown-runtime-CjeV3_4I.js +0 -18
  175. package/src/admin/components/jobs/AdminJobs.tsx +0 -772
@@ -1,698 +0,0 @@
1
- import { t as __exportAll } from "./rolldown-runtime-CjeV3_4I.js";
2
- import { ActionButton, DataTable, Flex, Text, useDialog, useToast } from "@alepha/ui";
3
- import { t } from "alepha";
4
- import { IconAlertTriangle, IconCircleCheck, IconCircleX, IconClock, IconPlayerPlay, IconRefresh, IconTerminal2 } from "@tabler/icons-react";
5
- import { ActionIcon, Badge, Box, Card, Group, Paper, Progress, RingProgress, ScrollArea, SimpleGrid, Skeleton, Stack, Tabs, ThemeIcon, Tooltip, useMantineTheme } from "@mantine/core";
6
- import { useClient } from "alepha/react";
7
- import { useI18n } from "alepha/react/i18n";
8
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
9
- import { jobExecutions } from "alepha/api/jobs";
10
- import { useCallback, useEffect, useState } from "react";
11
-
12
- //#region ../../src/admin/components/jobs/AdminJobs.tsx
13
- var AdminJobs_exports = /* @__PURE__ */ __exportAll({ default: () => AdminJobs });
14
- const formatDuration = (start, end) => {
15
- const startTime = new Date(start).getTime();
16
- const duration = (end ? new Date(end).getTime() : Date.now()) - startTime;
17
- if (duration < 1e3) return `${duration}ms`;
18
- if (duration < 6e4) return `${(duration / 1e3).toFixed(1)}s`;
19
- if (duration < 36e5) return `${Math.floor(duration / 6e4)}m ${Math.floor(duration % 6e4 / 1e3)}s`;
20
- return `${Math.floor(duration / 36e5)}h ${Math.floor(duration % 36e5 / 6e4)}m`;
21
- };
22
- const getStatusColor = (status) => {
23
- switch (status) {
24
- case "COMPLETED": return "teal";
25
- case "FAILED": return "red";
26
- case "STARTED": return "blue";
27
- default: return "gray";
28
- }
29
- };
30
- const getStatusIcon = (status, size = 14) => {
31
- switch (status) {
32
- case "COMPLETED": return /* @__PURE__ */ jsx(IconCircleCheck, { size });
33
- case "FAILED": return /* @__PURE__ */ jsx(IconCircleX, { size });
34
- case "STARTED": return /* @__PURE__ */ jsx(IconPlayerPlay, { size });
35
- default: return /* @__PURE__ */ jsx(IconClock, { size });
36
- }
37
- };
38
- const getLogLevelColor = (level) => {
39
- switch (level) {
40
- case "ERROR": return "red";
41
- case "WARN": return "yellow";
42
- case "INFO": return "blue";
43
- case "DEBUG": return "gray";
44
- case "TRACE": return "dimmed";
45
- default: return "dimmed";
46
- }
47
- };
48
- const JobCard = (props) => {
49
- const { job, stats, isTriggering, onTrigger, onSelect, isSelected } = props;
50
- const theme = useMantineTheme();
51
- stats && stats.total > 0 && stats.completed / stats.total * 100;
52
- return /* @__PURE__ */ jsxs(Card, {
53
- p: "md",
54
- radius: "md",
55
- withBorder: true,
56
- onClick: () => onSelect(job),
57
- style: {
58
- cursor: "pointer",
59
- borderColor: isSelected ? theme.colors.blue[6] : void 0,
60
- backgroundColor: isSelected ? "var(--mantine-color-blue-light)" : void 0,
61
- transition: "all 150ms ease"
62
- },
63
- children: [/* @__PURE__ */ jsxs(Group, {
64
- justify: "space-between",
65
- mb: "xs",
66
- children: [/* @__PURE__ */ jsxs(Group, {
67
- gap: "xs",
68
- children: [/* @__PURE__ */ jsx(ThemeIcon, {
69
- size: "sm",
70
- radius: "sm",
71
- variant: "light",
72
- color: stats?.lastStatus ? getStatusColor(stats.lastStatus) : "gray",
73
- children: /* @__PURE__ */ jsx(IconTerminal2, { size: 14 })
74
- }), /* @__PURE__ */ jsx(Text, {
75
- size: "sm",
76
- fw: 600,
77
- ff: "monospace",
78
- children: job
79
- })]
80
- }), /* @__PURE__ */ jsx(Tooltip, {
81
- label: "Trigger job manually",
82
- position: "left",
83
- children: /* @__PURE__ */ jsx(ActionIcon, {
84
- size: "sm",
85
- variant: "light",
86
- color: "blue",
87
- loading: isTriggering,
88
- onClick: (e) => {
89
- e.stopPropagation();
90
- onTrigger(job);
91
- },
92
- children: /* @__PURE__ */ jsx(IconPlayerPlay, { size: 12 })
93
- })
94
- })]
95
- }), stats ? /* @__PURE__ */ jsxs(Fragment, { children: [
96
- /* @__PURE__ */ jsxs(Group, {
97
- gap: "lg",
98
- mb: "xs",
99
- children: [
100
- /* @__PURE__ */ jsxs(Box, { children: [/* @__PURE__ */ jsx(Text, {
101
- size: "xs",
102
- c: "dimmed",
103
- tt: "uppercase",
104
- fw: 500,
105
- children: "Total"
106
- }), /* @__PURE__ */ jsx(Text, {
107
- size: "lg",
108
- fw: 700,
109
- ff: "monospace",
110
- children: stats.total
111
- })] }),
112
- /* @__PURE__ */ jsxs(Box, { children: [/* @__PURE__ */ jsx(Text, {
113
- size: "xs",
114
- c: "dimmed",
115
- tt: "uppercase",
116
- fw: 500,
117
- children: "Success"
118
- }), /* @__PURE__ */ jsx(Text, {
119
- size: "lg",
120
- fw: 700,
121
- ff: "monospace",
122
- c: "teal",
123
- children: stats.completed
124
- })] }),
125
- /* @__PURE__ */ jsxs(Box, { children: [/* @__PURE__ */ jsx(Text, {
126
- size: "xs",
127
- c: "dimmed",
128
- tt: "uppercase",
129
- fw: 500,
130
- children: "Failed"
131
- }), /* @__PURE__ */ jsx(Text, {
132
- size: "lg",
133
- fw: 700,
134
- ff: "monospace",
135
- c: "red",
136
- children: stats.failed
137
- })] })
138
- ]
139
- }),
140
- /* @__PURE__ */ jsxs(Progress.Root, {
141
- size: "sm",
142
- radius: "xs",
143
- children: [
144
- /* @__PURE__ */ jsx(Tooltip, {
145
- label: `${stats.completed} completed`,
146
- children: /* @__PURE__ */ jsx(Progress.Section, {
147
- value: stats.completed / Math.max(stats.total, 1) * 100,
148
- color: "teal"
149
- })
150
- }),
151
- /* @__PURE__ */ jsx(Tooltip, {
152
- label: `${stats.failed} failed`,
153
- children: /* @__PURE__ */ jsx(Progress.Section, {
154
- value: stats.failed / Math.max(stats.total, 1) * 100,
155
- color: "red"
156
- })
157
- }),
158
- /* @__PURE__ */ jsx(Tooltip, {
159
- label: `${stats.running} running`,
160
- children: /* @__PURE__ */ jsx(Progress.Section, {
161
- value: stats.running / Math.max(stats.total, 1) * 100,
162
- color: "blue"
163
- })
164
- })
165
- ]
166
- }),
167
- stats.lastRun && /* @__PURE__ */ jsxs(Text, {
168
- size: "xs",
169
- c: "dimmed",
170
- mt: "xs",
171
- children: [
172
- "Last run: ",
173
- formatDuration(stats.lastRun, /* @__PURE__ */ new Date()),
174
- " ago"
175
- ]
176
- })
177
- ] }) : /* @__PURE__ */ jsxs(Stack, {
178
- gap: "xs",
179
- children: [/* @__PURE__ */ jsx(Skeleton, {
180
- height: 8,
181
- radius: "xl"
182
- }), /* @__PURE__ */ jsx(Skeleton, {
183
- height: 8,
184
- width: "70%",
185
- radius: "xl"
186
- })]
187
- })]
188
- });
189
- };
190
- const ExecutionLogViewer = (props) => {
191
- const { logs, error } = props;
192
- if (!logs?.length && !error) return /* @__PURE__ */ jsx(Box, {
193
- p: "md",
194
- children: /* @__PURE__ */ jsx(Text, {
195
- size: "sm",
196
- c: "dimmed",
197
- ta: "center",
198
- children: "No logs available"
199
- })
200
- });
201
- return /* @__PURE__ */ jsx(ScrollArea, {
202
- h: 300,
203
- type: "auto",
204
- children: /* @__PURE__ */ jsxs(Box, {
205
- p: "md",
206
- style: {
207
- fontFamily: "var(--mantine-font-family-monospace)",
208
- fontSize: "12px",
209
- lineHeight: 1.6
210
- },
211
- children: [error && /* @__PURE__ */ jsx(Paper, {
212
- p: "sm",
213
- mb: "md",
214
- bg: "var(--mantine-color-red-light)",
215
- radius: "sm",
216
- children: /* @__PURE__ */ jsxs(Group, {
217
- gap: "xs",
218
- align: "flex-start",
219
- children: [/* @__PURE__ */ jsx(IconAlertTriangle, {
220
- size: 14,
221
- color: "var(--mantine-color-red-filled)"
222
- }), /* @__PURE__ */ jsx(Text, {
223
- size: "xs",
224
- c: "red",
225
- style: {
226
- whiteSpace: "pre-wrap",
227
- wordBreak: "break-word"
228
- },
229
- children: error
230
- })]
231
- })
232
- }), logs?.map((log, index) => /* @__PURE__ */ jsxs(Group, {
233
- gap: "sm",
234
- align: "flex-start",
235
- mb: 4,
236
- wrap: "nowrap",
237
- children: [
238
- /* @__PURE__ */ jsx(Text, {
239
- size: "xs",
240
- c: "dimmed",
241
- style: {
242
- minWidth: 80,
243
- flexShrink: 0
244
- },
245
- children: new Date(log.timestamp).toLocaleTimeString()
246
- }),
247
- /* @__PURE__ */ jsx(Badge, {
248
- size: "xs",
249
- variant: "light",
250
- color: getLogLevelColor(log.level),
251
- style: { minWidth: 50 },
252
- children: log.level
253
- }),
254
- /* @__PURE__ */ jsx(Text, {
255
- size: "xs",
256
- c: "dimmed",
257
- style: {
258
- minWidth: 100,
259
- flexShrink: 0
260
- },
261
- children: log.module
262
- }),
263
- /* @__PURE__ */ jsx(Text, {
264
- size: "xs",
265
- style: { wordBreak: "break-word" },
266
- children: log.message
267
- })
268
- ]
269
- }, index))]
270
- })
271
- });
272
- };
273
- const AdminJobs = () => {
274
- const client = useClient();
275
- const { l } = useI18n();
276
- const toast = useToast();
277
- const dialog = useDialog();
278
- const [jobs, setJobs] = useState([]);
279
- const [jobStats, setJobStats] = useState(/* @__PURE__ */ new Map());
280
- const [selectedJob, setSelectedJob] = useState(null);
281
- const [triggeringJobs, setTriggeringJobs] = useState(/* @__PURE__ */ new Set());
282
- const [refreshKey, setRefreshKey] = useState(0);
283
- const [loading, setLoading] = useState(true);
284
- const [activeTab, setActiveTab] = useState("overview");
285
- useEffect(() => {
286
- const loadJobs = async () => {
287
- try {
288
- const jobList = await client.getJobs();
289
- setJobs(jobList);
290
- const statsMap = /* @__PURE__ */ new Map();
291
- for (const job of jobList) {
292
- const items = (await client.getJobExecutions({ query: {
293
- job,
294
- size: 100
295
- } })).content || [];
296
- const completed = items.filter((e) => e.status === "COMPLETED").length;
297
- const failed = items.filter((e) => e.status === "FAILED").length;
298
- const running = items.filter((e) => e.status === "STARTED").length;
299
- const completedItems = items.filter((e) => e.status === "COMPLETED" && e.finishedAt);
300
- const avgDuration = completedItems.length > 0 ? completedItems.reduce((acc, e) => {
301
- return acc + (new Date(e.finishedAt).getTime() - new Date(e.createdAt).getTime());
302
- }, 0) / completedItems.length : 0;
303
- const lastItem = items[0];
304
- statsMap.set(job, {
305
- name: job,
306
- total: items.length,
307
- completed,
308
- failed,
309
- running,
310
- avgDuration,
311
- lastRun: lastItem?.createdAt ? new Date(lastItem.createdAt) : void 0,
312
- lastStatus: lastItem?.status
313
- });
314
- }
315
- setJobStats(statsMap);
316
- } catch (error) {
317
- toast.danger("Failed to load jobs");
318
- } finally {
319
- setLoading(false);
320
- }
321
- };
322
- loadJobs();
323
- }, [refreshKey]);
324
- const handleTriggerJob = useCallback(async (job) => {
325
- if (!await dialog.confirm({
326
- title: "Trigger Job",
327
- message: `Are you sure you want to trigger "${job}" manually?`,
328
- confirmLabel: "Trigger",
329
- confirmColor: "blue"
330
- })) return;
331
- setTriggeringJobs((prev) => new Set(prev).add(job));
332
- try {
333
- await client.triggerJob({ body: { name: job } });
334
- toast.success(`Job "${job}" triggered successfully`);
335
- setRefreshKey((k) => k + 1);
336
- } catch (error) {
337
- toast.danger(`Failed to trigger job "${job}"`);
338
- } finally {
339
- setTriggeringJobs((prev) => {
340
- const next = new Set(prev);
341
- next.delete(job);
342
- return next;
343
- });
344
- }
345
- }, [
346
- client,
347
- dialog,
348
- toast
349
- ]);
350
- const filters = t.object({
351
- job: t.optional(t.string({ $control: { query: t.pick(jobExecutions.schema, ["job"]) } })),
352
- status: t.optional(t.enum([
353
- "STARTED",
354
- "FAILED",
355
- "COMPLETED"
356
- ]))
357
- });
358
- const globalStats = {
359
- total: Array.from(jobStats.values()).reduce((acc, s) => acc + s.total, 0),
360
- completed: Array.from(jobStats.values()).reduce((acc, s) => acc + s.completed, 0),
361
- failed: Array.from(jobStats.values()).reduce((acc, s) => acc + s.failed, 0),
362
- running: Array.from(jobStats.values()).reduce((acc, s) => acc + s.running, 0)
363
- };
364
- const successRate = globalStats.total > 0 ? Math.round(globalStats.completed / globalStats.total * 100) : 0;
365
- return /* @__PURE__ */ jsxs(Flex, {
366
- flex: 1,
367
- direction: "column",
368
- gap: "md",
369
- children: [/* @__PURE__ */ jsxs(SimpleGrid, {
370
- cols: {
371
- base: 2,
372
- sm: 4
373
- },
374
- spacing: "md",
375
- children: [
376
- /* @__PURE__ */ jsx(Paper, {
377
- p: "md",
378
- radius: "md",
379
- withBorder: true,
380
- children: /* @__PURE__ */ jsxs(Group, {
381
- justify: "space-between",
382
- children: [/* @__PURE__ */ jsxs(Box, { children: [/* @__PURE__ */ jsx(Text, {
383
- size: "xs",
384
- c: "dimmed",
385
- tt: "uppercase",
386
- fw: 600,
387
- children: "Total Jobs"
388
- }), /* @__PURE__ */ jsx(Text, {
389
- size: "xl",
390
- fw: 700,
391
- ff: "monospace",
392
- children: jobs.length
393
- })] }), /* @__PURE__ */ jsx(ThemeIcon, {
394
- size: "lg",
395
- radius: "md",
396
- variant: "light",
397
- color: "blue",
398
- children: /* @__PURE__ */ jsx(IconTerminal2, { size: 20 })
399
- })]
400
- })
401
- }),
402
- /* @__PURE__ */ jsx(Paper, {
403
- p: "md",
404
- radius: "md",
405
- withBorder: true,
406
- children: /* @__PURE__ */ jsxs(Group, {
407
- justify: "space-between",
408
- children: [/* @__PURE__ */ jsxs(Box, { children: [/* @__PURE__ */ jsx(Text, {
409
- size: "xs",
410
- c: "dimmed",
411
- tt: "uppercase",
412
- fw: 600,
413
- children: "Executions"
414
- }), /* @__PURE__ */ jsx(Text, {
415
- size: "xl",
416
- fw: 700,
417
- ff: "monospace",
418
- children: globalStats.total
419
- })] }), /* @__PURE__ */ jsx(ThemeIcon, {
420
- size: "lg",
421
- radius: "md",
422
- variant: "light",
423
- color: "gray",
424
- children: /* @__PURE__ */ jsx(IconClock, { size: 20 })
425
- })]
426
- })
427
- }),
428
- /* @__PURE__ */ jsx(Paper, {
429
- p: "md",
430
- radius: "md",
431
- withBorder: true,
432
- children: /* @__PURE__ */ jsxs(Group, {
433
- justify: "space-between",
434
- children: [/* @__PURE__ */ jsxs(Box, { children: [/* @__PURE__ */ jsx(Text, {
435
- size: "xs",
436
- c: "dimmed",
437
- tt: "uppercase",
438
- fw: 600,
439
- children: "Success Rate"
440
- }), /* @__PURE__ */ jsxs(Text, {
441
- size: "xl",
442
- fw: 700,
443
- ff: "monospace",
444
- c: successRate >= 90 ? "teal" : successRate >= 70 ? "yellow" : "red",
445
- children: [successRate, "%"]
446
- })] }), /* @__PURE__ */ jsx(RingProgress, {
447
- size: 48,
448
- thickness: 4,
449
- roundCaps: true,
450
- sections: [{
451
- value: successRate,
452
- color: successRate >= 90 ? "teal" : successRate >= 70 ? "yellow" : "red"
453
- }]
454
- })]
455
- })
456
- }),
457
- /* @__PURE__ */ jsx(Paper, {
458
- p: "md",
459
- radius: "md",
460
- withBorder: true,
461
- children: /* @__PURE__ */ jsxs(Group, {
462
- justify: "space-between",
463
- children: [/* @__PURE__ */ jsxs(Box, { children: [/* @__PURE__ */ jsx(Text, {
464
- size: "xs",
465
- c: "dimmed",
466
- tt: "uppercase",
467
- fw: 600,
468
- children: "Running Now"
469
- }), /* @__PURE__ */ jsx(Text, {
470
- size: "xl",
471
- fw: 700,
472
- ff: "monospace",
473
- c: "blue",
474
- children: globalStats.running
475
- })] }), /* @__PURE__ */ jsx(ThemeIcon, {
476
- size: "lg",
477
- radius: "md",
478
- variant: "light",
479
- color: globalStats.running > 0 ? "blue" : "gray",
480
- children: /* @__PURE__ */ jsx(IconPlayerPlay, { size: 20 })
481
- })]
482
- })
483
- })
484
- ]
485
- }), /* @__PURE__ */ jsxs(Tabs, {
486
- value: activeTab,
487
- onChange: setActiveTab,
488
- children: [
489
- /* @__PURE__ */ jsxs(Tabs.List, { children: [/* @__PURE__ */ jsx(Tabs.Tab, {
490
- value: "overview",
491
- leftSection: /* @__PURE__ */ jsx(IconTerminal2, { size: 14 }),
492
- children: "Jobs Overview"
493
- }), /* @__PURE__ */ jsx(Tabs.Tab, {
494
- value: "executions",
495
- leftSection: /* @__PURE__ */ jsx(IconClock, { size: 14 }),
496
- children: "Execution History"
497
- })] }),
498
- /* @__PURE__ */ jsxs(Tabs.Panel, {
499
- value: "overview",
500
- pt: "md",
501
- children: [/* @__PURE__ */ jsxs(Group, {
502
- justify: "space-between",
503
- mb: "md",
504
- children: [/* @__PURE__ */ jsxs(Text, {
505
- size: "sm",
506
- c: "dimmed",
507
- children: [
508
- jobs.length,
509
- " registered job",
510
- jobs.length !== 1 ? "s" : ""
511
- ]
512
- }), /* @__PURE__ */ jsx(ActionButton, {
513
- size: "xs",
514
- variant: "light",
515
- leftSection: /* @__PURE__ */ jsx(IconRefresh, { size: 14 }),
516
- onClick: () => setRefreshKey((k) => k + 1),
517
- children: "Refresh"
518
- })]
519
- }), loading ? /* @__PURE__ */ jsx(SimpleGrid, {
520
- cols: {
521
- base: 1,
522
- sm: 2,
523
- lg: 3
524
- },
525
- spacing: "md",
526
- children: [
527
- 1,
528
- 2,
529
- 3
530
- ].map((i) => /* @__PURE__ */ jsx(Skeleton, {
531
- height: 150,
532
- radius: "md"
533
- }, i))
534
- }) : jobs.length === 0 ? /* @__PURE__ */ jsxs(Paper, {
535
- p: "xl",
536
- radius: "md",
537
- withBorder: true,
538
- ta: "center",
539
- children: [
540
- /* @__PURE__ */ jsx(IconTerminal2, {
541
- size: 48,
542
- color: "var(--mantine-color-dimmed)"
543
- }),
544
- /* @__PURE__ */ jsx(Text, {
545
- size: "lg",
546
- fw: 500,
547
- mt: "md",
548
- children: "No jobs registered"
549
- }),
550
- /* @__PURE__ */ jsx(Text, {
551
- size: "sm",
552
- c: "dimmed",
553
- mt: "xs",
554
- children: "Jobs will appear here once they are defined using $job primitive"
555
- })
556
- ]
557
- }) : /* @__PURE__ */ jsx(SimpleGrid, {
558
- cols: {
559
- base: 1,
560
- sm: 2,
561
- lg: 3
562
- },
563
- spacing: "md",
564
- children: jobs.map((job) => /* @__PURE__ */ jsx(JobCard, {
565
- job,
566
- stats: jobStats.get(job),
567
- isTriggering: triggeringJobs.has(job),
568
- onTrigger: handleTriggerJob,
569
- onSelect: setSelectedJob,
570
- isSelected: selectedJob === job
571
- }, job))
572
- })]
573
- }),
574
- /* @__PURE__ */ jsx(Tabs.Panel, {
575
- value: "executions",
576
- pt: "md",
577
- children: /* @__PURE__ */ jsx(DataTable, {
578
- submitOnInit: true,
579
- defaultSize: 15,
580
- typeFormProps: {
581
- skipSubmitButton: true,
582
- columns: 3
583
- },
584
- tableProps: {
585
- horizontalSpacing: "sm",
586
- verticalSpacing: "sm",
587
- highlightOnHover: true
588
- },
589
- onFilterChange: (key, _value, form) => {
590
- if (key === "job" || key === "status") return form.submit();
591
- },
592
- filters,
593
- items: async (filters) => {
594
- return await client.getJobExecutions({ query: {
595
- ...filters,
596
- job: selectedJob || filters.job
597
- } });
598
- },
599
- columns: {
600
- job: {
601
- label: "Job",
602
- value: (item) => /* @__PURE__ */ jsx(Text, {
603
- size: "sm",
604
- fw: 500,
605
- ff: "monospace",
606
- children: item.job
607
- })
608
- },
609
- status: {
610
- label: "Status",
611
- fit: true,
612
- value: (item) => /* @__PURE__ */ jsx(Badge, {
613
- size: "sm",
614
- variant: "light",
615
- color: getStatusColor(item.status),
616
- leftSection: getStatusIcon(item.status, 12),
617
- children: item.status
618
- })
619
- },
620
- duration: {
621
- label: "Duration",
622
- fit: true,
623
- value: (item) => /* @__PURE__ */ jsx(Text, {
624
- size: "xs",
625
- c: "dimmed",
626
- ff: "monospace",
627
- children: formatDuration(item.createdAt, item.finishedAt)
628
- })
629
- },
630
- logs: {
631
- label: "Logs",
632
- fit: true,
633
- value: (item) => {
634
- const logCount = item.logs?.length || 0;
635
- const errorCount = item.logs?.filter((log) => log.level === "ERROR").length || 0;
636
- return /* @__PURE__ */ jsxs(Group, {
637
- gap: 4,
638
- children: [/* @__PURE__ */ jsxs(Badge, {
639
- size: "xs",
640
- variant: "light",
641
- color: "gray",
642
- children: [logCount, " logs"]
643
- }), errorCount > 0 && /* @__PURE__ */ jsxs(Badge, {
644
- size: "xs",
645
- variant: "light",
646
- color: "red",
647
- children: [errorCount, " errors"]
648
- })]
649
- });
650
- }
651
- },
652
- error: {
653
- label: "Error",
654
- value: (item) => item.error ? /* @__PURE__ */ jsx(Tooltip, {
655
- label: item.error,
656
- multiline: true,
657
- w: 300,
658
- children: /* @__PURE__ */ jsx(Text, {
659
- size: "xs",
660
- c: "red",
661
- lineClamp: 1,
662
- children: item.error
663
- })
664
- }) : /* @__PURE__ */ jsx(Text, {
665
- size: "xs",
666
- c: "dimmed",
667
- children: "—"
668
- })
669
- },
670
- createdAt: {
671
- label: "Started",
672
- fit: true,
673
- value: (item) => /* @__PURE__ */ jsx(Text, {
674
- size: "xs",
675
- c: "dimmed",
676
- children: l(item.createdAt, { date: "fromNow" })
677
- })
678
- }
679
- },
680
- panel: (item) => /* @__PURE__ */ jsx(Box, {
681
- bg: "var(--mantine-color-dark-7)",
682
- p: 0,
683
- children: /* @__PURE__ */ jsx(ExecutionLogViewer, {
684
- logs: item.logs,
685
- error: item.error
686
- })
687
- }),
688
- canPanel: (item) => Boolean(item.logs?.length || item.error)
689
- }, refreshKey)
690
- })
691
- ]
692
- })]
693
- });
694
- };
695
-
696
- //#endregion
697
- export { AdminJobs_exports as n, AdminJobs as t };
698
- //# sourceMappingURL=AdminJobs-C604joTz.js.map