@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
@@ -0,0 +1,678 @@
1
+ import { ActionButton, DataTable, Text, useDialog, useToast } from "@alepha/ui";
2
+ import { t } from "alepha";
3
+ import { IconAlertTriangle, IconCircleCheck, IconCircleX, IconClock, IconPlayerPlay, IconRefresh } from "@tabler/icons-react";
4
+ import { Badge, Code, Flex as Flex$1, Paper, Table } from "@mantine/core";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ import { useClient } from "alepha/react";
7
+ import { useI18n } from "alepha/react/i18n";
8
+ import { useCallback, useEffect, useState } from "react";
9
+
10
+ //#region ../../src/admin/components/jobs/AdminJobExecutions.tsx
11
+ const PRIORITY_LABELS = {
12
+ 0: "Critical",
13
+ 1: "High",
14
+ 2: "Normal",
15
+ 3: "Low"
16
+ };
17
+ const formatDuration = (start, end) => {
18
+ const startTime = new Date(start).getTime();
19
+ const duration = (end ? new Date(end).getTime() : Date.now()) - startTime;
20
+ if (duration < 1e3) return `${duration}ms`;
21
+ if (duration < 6e4) return `${(duration / 1e3).toFixed(1)}s`;
22
+ if (duration < 36e5) return `${Math.floor(duration / 6e4)}m ${Math.floor(duration % 6e4 / 1e3)}s`;
23
+ return `${Math.floor(duration / 36e5)}h ${Math.floor(duration % 36e5 / 6e4)}m`;
24
+ };
25
+ const getStatusColor = (status) => {
26
+ switch (status) {
27
+ case "completed": return "teal";
28
+ case "running": return "blue";
29
+ case "failed":
30
+ case "dead": return "red";
31
+ case "cancelled": return "orange";
32
+ case "scheduled": return "violet";
33
+ case "retrying": return "yellow";
34
+ case "pending": return "gray";
35
+ default: return "gray";
36
+ }
37
+ };
38
+ const getStatusIcon = (status, size = 14) => {
39
+ switch (status) {
40
+ case "completed": return /* @__PURE__ */ jsx(IconCircleCheck, { size });
41
+ case "failed":
42
+ case "dead": return /* @__PURE__ */ jsx(IconCircleX, { size });
43
+ case "running": return /* @__PURE__ */ jsx(IconPlayerPlay, { size });
44
+ case "cancelled": return /* @__PURE__ */ jsx(IconAlertTriangle, { size });
45
+ default: return /* @__PURE__ */ jsx(IconClock, { size });
46
+ }
47
+ };
48
+ const getLogLevelColor = (level) => {
49
+ switch (level) {
50
+ case "ERROR": return "red";
51
+ case "WARN": return "orange";
52
+ case "INFO": return "blue";
53
+ case "DEBUG": return "gray";
54
+ case "TRACE": return "dimmed";
55
+ default: return "gray";
56
+ }
57
+ };
58
+ const executionFilters = t.object({
59
+ job: t.optional(t.string()),
60
+ status: t.optional(t.enum([
61
+ "pending",
62
+ "scheduled",
63
+ "retrying",
64
+ "running",
65
+ "completed",
66
+ "failed",
67
+ "dead",
68
+ "cancelled"
69
+ ])),
70
+ priority: t.optional(t.enum([
71
+ "critical",
72
+ "high",
73
+ "normal",
74
+ "low"
75
+ ]))
76
+ });
77
+ const AdminJobExecutions = () => {
78
+ const client = useClient();
79
+ const { l } = useI18n();
80
+ const toast = useToast();
81
+ const dialog = useDialog();
82
+ const [refreshKey, setRefreshKey] = useState(0);
83
+ const handleRetry = useCallback(async (id) => {
84
+ try {
85
+ await client.retryExecution({ params: { id } });
86
+ toast.success("Execution retried");
87
+ setRefreshKey((k) => k + 1);
88
+ } catch {
89
+ toast.danger("Failed to retry execution");
90
+ }
91
+ }, [client, toast]);
92
+ const handleCancel = useCallback(async (id) => {
93
+ if (!await dialog.confirm({
94
+ title: "Cancel Execution",
95
+ message: "Are you sure you want to cancel this execution?",
96
+ confirmLabel: "Cancel",
97
+ confirmColor: "red"
98
+ })) return;
99
+ try {
100
+ await client.cancelExecution({ params: { id } });
101
+ toast.success("Execution cancelled");
102
+ setRefreshKey((k) => k + 1);
103
+ } catch {
104
+ toast.danger("Failed to cancel execution");
105
+ }
106
+ }, [
107
+ client,
108
+ dialog,
109
+ toast
110
+ ]);
111
+ return /* @__PURE__ */ jsx(Flex$1, {
112
+ flex: 1,
113
+ direction: "column",
114
+ gap: "md",
115
+ children: /* @__PURE__ */ jsx(DataTable, {
116
+ submitOnInit: true,
117
+ defaultSize: 20,
118
+ typeFormProps: {
119
+ skipSubmitButton: true,
120
+ columns: 3
121
+ },
122
+ tableProps: {
123
+ horizontalSpacing: "sm",
124
+ verticalSpacing: "sm",
125
+ highlightOnHover: true
126
+ },
127
+ onFilterChange: (key, _value, form) => {
128
+ if (key === "job" || key === "status" || key === "priority") return form.submit();
129
+ },
130
+ filters: executionFilters,
131
+ defaultFilters: ["job", "status"],
132
+ items: async (filters) => {
133
+ return await client.findExecutions({ query: { ...filters } });
134
+ },
135
+ columns: {
136
+ status: {
137
+ label: "Status",
138
+ fit: true,
139
+ value: (item) => /* @__PURE__ */ jsx(Badge, {
140
+ size: "sm",
141
+ variant: "light",
142
+ color: getStatusColor(item.status),
143
+ leftSection: getStatusIcon(item.status, 12),
144
+ children: item.status
145
+ })
146
+ },
147
+ jobName: {
148
+ label: "Job",
149
+ value: (item) => /* @__PURE__ */ jsx(Text, {
150
+ size: "sm",
151
+ fw: 500,
152
+ ff: "monospace",
153
+ children: item.jobName
154
+ })
155
+ },
156
+ priority: {
157
+ label: "Priority",
158
+ fit: true,
159
+ value: (item) => /* @__PURE__ */ jsx(Text, {
160
+ size: "xs",
161
+ c: "dimmed",
162
+ children: PRIORITY_LABELS[item.priority] ?? item.priority
163
+ })
164
+ },
165
+ attempt: {
166
+ label: "Attempt",
167
+ fit: true,
168
+ value: (item) => /* @__PURE__ */ jsxs(Text, {
169
+ size: "sm",
170
+ ff: "monospace",
171
+ children: [
172
+ item.attempt,
173
+ "/",
174
+ item.maxAttempts
175
+ ]
176
+ })
177
+ },
178
+ triggeredByName: {
179
+ label: "Trigger",
180
+ fit: true,
181
+ defaultHidden: true,
182
+ value: (item) => /* @__PURE__ */ jsx(Text, {
183
+ size: "xs",
184
+ c: "dimmed",
185
+ children: item.triggeredByName ?? "—"
186
+ })
187
+ },
188
+ createdAt: {
189
+ label: "Created",
190
+ fit: true,
191
+ defaultHidden: true,
192
+ value: (item) => /* @__PURE__ */ jsx(Text, {
193
+ size: "xs",
194
+ c: "dimmed",
195
+ children: l(item.createdAt, { date: "fromNow" })
196
+ })
197
+ },
198
+ startedAt: {
199
+ label: "Started",
200
+ fit: true,
201
+ value: (item) => /* @__PURE__ */ jsx(Text, {
202
+ size: "xs",
203
+ c: "dimmed",
204
+ children: item.startedAt ? l(item.startedAt, { date: "fromNow" }) : "—"
205
+ })
206
+ },
207
+ duration: {
208
+ label: "Duration",
209
+ fit: true,
210
+ value: (item) => /* @__PURE__ */ jsx(Text, {
211
+ size: "xs",
212
+ c: "dimmed",
213
+ ff: "monospace",
214
+ children: item.startedAt && (item.completedAt || item.status === "running") ? formatDuration(item.startedAt, item.completedAt) : "—"
215
+ })
216
+ },
217
+ error: {
218
+ label: "Error",
219
+ defaultHidden: true,
220
+ value: (item) => /* @__PURE__ */ jsx(Text, {
221
+ size: "xs",
222
+ c: "red",
223
+ lineClamp: 1,
224
+ children: item.error ?? "—"
225
+ })
226
+ },
227
+ key: {
228
+ label: "Key",
229
+ fit: true,
230
+ defaultHidden: true,
231
+ value: (item) => /* @__PURE__ */ jsx(Text, {
232
+ size: "xs",
233
+ c: "dimmed",
234
+ ff: "monospace",
235
+ children: item.key ?? "—"
236
+ })
237
+ },
238
+ workerId: {
239
+ label: "Worker",
240
+ fit: true,
241
+ defaultHidden: true,
242
+ value: (item) => /* @__PURE__ */ jsx(Text, {
243
+ size: "xs",
244
+ c: "dimmed",
245
+ ff: "monospace",
246
+ children: item.workerId ?? "—"
247
+ })
248
+ },
249
+ actions: {
250
+ label: "",
251
+ fit: true,
252
+ actions: (item) => [{
253
+ tooltip: "Retry",
254
+ color: "blue",
255
+ icon: IconRefresh,
256
+ onClick: () => handleRetry(item.id),
257
+ visible: item.can?.retry
258
+ }, {
259
+ tooltip: "Cancel",
260
+ color: "red",
261
+ icon: IconCircleX,
262
+ onClick: () => handleCancel(item.id),
263
+ visible: item.can?.cancel
264
+ }]
265
+ }
266
+ },
267
+ panel: {
268
+ can: (item) => Boolean(item.error || item.key || item.workerId),
269
+ render: (item) => /* @__PURE__ */ jsxs(Flex$1, {
270
+ direction: "column",
271
+ gap: "sm",
272
+ p: "sm",
273
+ children: [item.error && /* @__PURE__ */ jsxs(Flex$1, {
274
+ direction: "column",
275
+ gap: 2,
276
+ children: [/* @__PURE__ */ jsx(Text, {
277
+ size: "xs",
278
+ c: "dimmed",
279
+ tt: "uppercase",
280
+ fw: 600,
281
+ children: "Error"
282
+ }), /* @__PURE__ */ jsx(Paper, {
283
+ p: "xs",
284
+ bg: "var(--mantine-color-red-light)",
285
+ radius: "sm",
286
+ children: /* @__PURE__ */ jsx(Text, {
287
+ size: "xs",
288
+ c: "red",
289
+ style: {
290
+ whiteSpace: "pre-wrap",
291
+ wordBreak: "break-word"
292
+ },
293
+ children: item.error
294
+ })
295
+ })]
296
+ }), /* @__PURE__ */ jsxs(Flex$1, {
297
+ gap: "lg",
298
+ wrap: "wrap",
299
+ children: [
300
+ /* @__PURE__ */ jsxs(Flex$1, {
301
+ direction: "column",
302
+ gap: 2,
303
+ children: [/* @__PURE__ */ jsx(Text, {
304
+ size: "xs",
305
+ c: "dimmed",
306
+ tt: "uppercase",
307
+ fw: 600,
308
+ children: "ID"
309
+ }), /* @__PURE__ */ jsx(Text, {
310
+ size: "xs",
311
+ ff: "monospace",
312
+ children: item.id
313
+ })]
314
+ }),
315
+ item.key && /* @__PURE__ */ jsxs(Flex$1, {
316
+ direction: "column",
317
+ gap: 2,
318
+ children: [/* @__PURE__ */ jsx(Text, {
319
+ size: "xs",
320
+ c: "dimmed",
321
+ tt: "uppercase",
322
+ fw: 600,
323
+ children: "Key"
324
+ }), /* @__PURE__ */ jsx(Text, {
325
+ size: "xs",
326
+ ff: "monospace",
327
+ children: item.key
328
+ })]
329
+ }),
330
+ item.workerId && /* @__PURE__ */ jsxs(Flex$1, {
331
+ direction: "column",
332
+ gap: 2,
333
+ children: [/* @__PURE__ */ jsx(Text, {
334
+ size: "xs",
335
+ c: "dimmed",
336
+ tt: "uppercase",
337
+ fw: 600,
338
+ children: "Worker"
339
+ }), /* @__PURE__ */ jsx(Text, {
340
+ size: "xs",
341
+ ff: "monospace",
342
+ children: item.workerId
343
+ })]
344
+ }),
345
+ item.triggeredByName && /* @__PURE__ */ jsxs(Flex$1, {
346
+ direction: "column",
347
+ gap: 2,
348
+ children: [/* @__PURE__ */ jsx(Text, {
349
+ size: "xs",
350
+ c: "dimmed",
351
+ tt: "uppercase",
352
+ fw: 600,
353
+ children: "Triggered By"
354
+ }), /* @__PURE__ */ jsx(Text, {
355
+ size: "xs",
356
+ children: item.triggeredByName
357
+ })]
358
+ })
359
+ ]
360
+ })]
361
+ })
362
+ },
363
+ drawer: (item) => /* @__PURE__ */ jsx(ExecutionDetailContent, {
364
+ item,
365
+ onRetry: handleRetry,
366
+ onCancel: handleCancel
367
+ })
368
+ }, `executions-${refreshKey}`)
369
+ });
370
+ };
371
+ const ExecutionDetailContent = ({ item, onRetry, onCancel }) => {
372
+ const client = useClient();
373
+ const { l } = useI18n();
374
+ const toast = useToast();
375
+ const [detail, setDetail] = useState(null);
376
+ const [loading, setLoading] = useState(false);
377
+ const [expandedLogs, setExpandedLogs] = useState(/* @__PURE__ */ new Set());
378
+ const loadDetail = useCallback(async (execId) => {
379
+ setDetail(null);
380
+ setExpandedLogs(/* @__PURE__ */ new Set());
381
+ setLoading(true);
382
+ try {
383
+ setDetail(await client.getExecution({ params: { id: execId } }));
384
+ } catch {
385
+ toast.danger("Failed to load execution details");
386
+ } finally {
387
+ setLoading(false);
388
+ }
389
+ }, [client, toast]);
390
+ useEffect(() => {
391
+ loadDetail(item.id);
392
+ }, [item.id, loadDetail]);
393
+ const handleRetry = useCallback(async () => {
394
+ await onRetry(item.id);
395
+ loadDetail(item.id);
396
+ }, [
397
+ item.id,
398
+ onRetry,
399
+ loadDetail
400
+ ]);
401
+ const handleCancel = useCallback(async () => {
402
+ await onCancel(item.id);
403
+ loadDetail(item.id);
404
+ }, [
405
+ item.id,
406
+ onCancel,
407
+ loadDetail
408
+ ]);
409
+ const toggleLogExpand = useCallback((index) => {
410
+ setExpandedLogs((prev) => {
411
+ const next = new Set(prev);
412
+ if (next.has(index)) next.delete(index);
413
+ else next.add(index);
414
+ return next;
415
+ });
416
+ }, []);
417
+ if (loading) return /* @__PURE__ */ jsx(Flex$1, {
418
+ align: "center",
419
+ justify: "center",
420
+ py: "xl",
421
+ children: /* @__PURE__ */ jsx(Text, {
422
+ c: "dimmed",
423
+ children: "Loading..."
424
+ })
425
+ });
426
+ if (!detail) return null;
427
+ return /* @__PURE__ */ jsxs(Flex$1, {
428
+ direction: "column",
429
+ gap: "md",
430
+ children: [
431
+ /* @__PURE__ */ jsxs(Flex$1, {
432
+ align: "center",
433
+ gap: "sm",
434
+ children: [
435
+ /* @__PURE__ */ jsx(Text, {
436
+ fw: 600,
437
+ ff: "monospace",
438
+ children: detail.jobName
439
+ }),
440
+ /* @__PURE__ */ jsx(Badge, {
441
+ size: "sm",
442
+ variant: "light",
443
+ color: getStatusColor(detail.status),
444
+ leftSection: getStatusIcon(detail.status, 12),
445
+ children: detail.status
446
+ }),
447
+ /* @__PURE__ */ jsxs(Text, {
448
+ size: "xs",
449
+ c: "dimmed",
450
+ children: [
451
+ detail.attempt,
452
+ "/",
453
+ detail.maxAttempts
454
+ ]
455
+ })
456
+ ]
457
+ }),
458
+ /* @__PURE__ */ jsxs(Flex$1, {
459
+ gap: "xs",
460
+ children: [
461
+ /* @__PURE__ */ jsx(ActionButton, {
462
+ tooltip: "Refresh",
463
+ variant: "light",
464
+ size: "xs",
465
+ icon: IconRefresh,
466
+ onClick: () => loadDetail(item.id)
467
+ }),
468
+ detail.can?.retry && /* @__PURE__ */ jsx(ActionButton, {
469
+ tooltip: "Retry",
470
+ variant: "light",
471
+ size: "xs",
472
+ color: "blue",
473
+ icon: IconRefresh,
474
+ onClick: handleRetry
475
+ }),
476
+ detail.can?.cancel && /* @__PURE__ */ jsx(ActionButton, {
477
+ tooltip: "Cancel",
478
+ variant: "light",
479
+ size: "xs",
480
+ color: "red",
481
+ icon: IconCircleX,
482
+ onClick: handleCancel
483
+ })
484
+ ]
485
+ }),
486
+ /* @__PURE__ */ jsxs(Paper, {
487
+ p: "sm",
488
+ radius: "md",
489
+ withBorder: true,
490
+ children: [/* @__PURE__ */ jsx(Text, {
491
+ size: "sm",
492
+ fw: 600,
493
+ mb: "xs",
494
+ children: "Details"
495
+ }), /* @__PURE__ */ jsxs(Flex$1, {
496
+ gap: "lg",
497
+ wrap: "wrap",
498
+ children: [
499
+ /* @__PURE__ */ jsx(DetailField, {
500
+ label: "ID",
501
+ value: detail.id,
502
+ monospace: true,
503
+ copyable: true
504
+ }),
505
+ /* @__PURE__ */ jsx(DetailField, {
506
+ label: "Status",
507
+ value: detail.status,
508
+ capitalize: true
509
+ }),
510
+ /* @__PURE__ */ jsx(DetailField, {
511
+ label: "Priority",
512
+ value: PRIORITY_LABELS[detail.priority] ?? "Normal"
513
+ }),
514
+ /* @__PURE__ */ jsx(DetailField, {
515
+ label: "Attempt",
516
+ value: `${detail.attempt}/${detail.maxAttempts}`,
517
+ monospace: true
518
+ }),
519
+ detail.workerId && /* @__PURE__ */ jsx(DetailField, {
520
+ label: "Worker",
521
+ value: detail.workerId,
522
+ monospace: true
523
+ }),
524
+ detail.key && /* @__PURE__ */ jsx(DetailField, {
525
+ label: "Key",
526
+ value: detail.key,
527
+ monospace: true
528
+ }),
529
+ /* @__PURE__ */ jsx(DetailField, {
530
+ label: "Created",
531
+ value: String(l(detail.createdAt, { date: "lll" }))
532
+ }),
533
+ detail.startedAt && /* @__PURE__ */ jsx(DetailField, {
534
+ label: "Started",
535
+ value: String(l(detail.startedAt, { date: "lll" }))
536
+ }),
537
+ detail.startedAt && (detail.completedAt || detail.status === "running") && /* @__PURE__ */ jsx(DetailField, {
538
+ label: "Duration",
539
+ value: formatDuration(detail.startedAt, detail.completedAt),
540
+ monospace: true
541
+ }),
542
+ detail.triggeredByName && /* @__PURE__ */ jsx(DetailField, {
543
+ label: "Triggered By",
544
+ value: detail.triggeredByName
545
+ }),
546
+ detail.cancelledByName && /* @__PURE__ */ jsx(DetailField, {
547
+ label: "Cancelled By",
548
+ value: detail.cancelledByName
549
+ })
550
+ ]
551
+ })]
552
+ }),
553
+ detail.payload && /* @__PURE__ */ jsxs(Paper, {
554
+ p: "sm",
555
+ radius: "md",
556
+ withBorder: true,
557
+ children: [/* @__PURE__ */ jsx(Text, {
558
+ size: "sm",
559
+ fw: 600,
560
+ mb: "xs",
561
+ children: "Payload"
562
+ }), /* @__PURE__ */ jsx(Code, {
563
+ block: true,
564
+ children: JSON.stringify(detail.payload, null, 2)
565
+ })]
566
+ }),
567
+ detail.error && /* @__PURE__ */ jsxs(Paper, {
568
+ p: "sm",
569
+ radius: "md",
570
+ withBorder: true,
571
+ children: [/* @__PURE__ */ jsx(Text, {
572
+ size: "sm",
573
+ fw: 600,
574
+ mb: "xs",
575
+ c: "red",
576
+ children: "Error"
577
+ }), /* @__PURE__ */ jsx(Paper, {
578
+ p: "xs",
579
+ bg: "var(--mantine-color-red-light)",
580
+ radius: "sm",
581
+ children: /* @__PURE__ */ jsx(Text, {
582
+ size: "sm",
583
+ c: "red",
584
+ style: {
585
+ whiteSpace: "pre-wrap",
586
+ wordBreak: "break-word"
587
+ },
588
+ children: detail.error
589
+ })
590
+ })]
591
+ }),
592
+ detail.logs && detail.logs.length > 0 && /* @__PURE__ */ jsxs(Paper, {
593
+ p: "sm",
594
+ radius: "md",
595
+ withBorder: true,
596
+ children: [/* @__PURE__ */ jsxs(Text, {
597
+ size: "sm",
598
+ fw: 600,
599
+ mb: "xs",
600
+ children: [
601
+ "Logs (",
602
+ detail.logs.length,
603
+ ")"
604
+ ]
605
+ }), /* @__PURE__ */ jsx(Flex$1, {
606
+ direction: "column",
607
+ style: {
608
+ maxHeight: 400,
609
+ overflowY: "auto"
610
+ },
611
+ children: /* @__PURE__ */ jsxs(Table, {
612
+ highlightOnHover: true,
613
+ children: [/* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
614
+ /* @__PURE__ */ jsx(Table.Th, {
615
+ style: { width: 60 },
616
+ children: "Level"
617
+ }),
618
+ /* @__PURE__ */ jsx(Table.Th, {
619
+ style: { width: 90 },
620
+ children: "Time"
621
+ }),
622
+ /* @__PURE__ */ jsx(Table.Th, { children: "Message" })
623
+ ] }) }), /* @__PURE__ */ jsx(Table.Tbody, { children: detail.logs.map((log, i) => /* @__PURE__ */ jsxs(Table.Tr, {
624
+ style: log.data ? { cursor: "pointer" } : void 0,
625
+ onClick: log.data ? () => toggleLogExpand(i) : void 0,
626
+ children: [
627
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, {
628
+ size: "xs",
629
+ variant: "light",
630
+ color: getLogLevelColor(log.level),
631
+ children: log.level
632
+ }) }),
633
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, {
634
+ size: "xs",
635
+ c: "dimmed",
636
+ ff: "monospace",
637
+ children: new Date(log.timestamp).toLocaleTimeString()
638
+ }) }),
639
+ /* @__PURE__ */ jsxs(Table.Td, { children: [/* @__PURE__ */ jsx(Text, {
640
+ size: "xs",
641
+ children: log.message
642
+ }), expandedLogs.has(i) && log.data && /* @__PURE__ */ jsx(Code, {
643
+ block: true,
644
+ mt: "xs",
645
+ children: JSON.stringify(log.data, null, 2)
646
+ })] })
647
+ ]
648
+ }, i)) })]
649
+ })
650
+ })]
651
+ })
652
+ ]
653
+ });
654
+ };
655
+ const DetailField = ({ label, value, monospace, capitalize, copyable }) => /* @__PURE__ */ jsxs(Flex$1, {
656
+ direction: "column",
657
+ gap: 2,
658
+ children: [/* @__PURE__ */ jsx(Text, {
659
+ size: "xs",
660
+ c: "dimmed",
661
+ tt: "uppercase",
662
+ fw: 600,
663
+ children: label
664
+ }), /* @__PURE__ */ jsx(Text, {
665
+ size: "sm",
666
+ ff: monospace ? "monospace" : void 0,
667
+ tt: capitalize ? "capitalize" : void 0,
668
+ style: copyable ? {
669
+ cursor: "pointer",
670
+ userSelect: "all"
671
+ } : void 0,
672
+ children: value
673
+ })]
674
+ });
675
+
676
+ //#endregion
677
+ export { AdminJobExecutions as default };
678
+ //# sourceMappingURL=AdminJobExecutions-D-b4Zt7W.js.map