@alepha/ui 0.16.1 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (218) hide show
  1. package/dist/admin/{AdminApiKeys-GMORg-1l.js → AdminApiKeys-CF_qOO3u.js} +20 -19
  2. package/dist/admin/AdminApiKeys-CF_qOO3u.js.map +1 -0
  3. package/dist/admin/{AdminAudits-pkWrjq1Z.js → AdminAudits-BQno3hZG.js} +7 -7
  4. package/dist/admin/AdminAudits-BQno3hZG.js.map +1 -0
  5. package/dist/admin/{AdminFiles-WeQbsCsl.js → AdminFiles-kvuUaASF.js} +3 -4
  6. package/dist/admin/{AdminFiles-WeQbsCsl.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-BqZiXx4H.js → AdminLayout-e-ZP5nWw.js} +6 -9
  14. package/dist/admin/AdminLayout-e-ZP5nWw.js.map +1 -0
  15. package/dist/admin/{AdminNotifications-Ds5Un0NJ.js → AdminNotifications-DeHJFf6W.js} +3 -4
  16. package/dist/admin/{AdminNotifications-Ds5Un0NJ.js.map → AdminNotifications-DeHJFf6W.js.map} +1 -1
  17. package/dist/admin/AdminParameters-iQE8o7a7.js +774 -0
  18. package/dist/admin/AdminParameters-iQE8o7a7.js.map +1 -0
  19. package/dist/admin/{AdminSessions-DzIOxM3b.js → AdminSessions-oKJCbd7w.js} +5 -6
  20. package/dist/admin/AdminSessions-oKJCbd7w.js.map +1 -0
  21. package/dist/admin/{AdminUserAudits-CiUPN2BC.js → AdminUserAudits-BNCEle_E.js} +6 -7
  22. package/dist/admin/AdminUserAudits-BNCEle_E.js.map +1 -0
  23. package/dist/admin/{AdminUserCreate-BwQKr4xE.js → AdminUserCreate-CgqeFwCt.js} +6 -6
  24. package/dist/admin/AdminUserCreate-CgqeFwCt.js.map +1 -0
  25. package/dist/admin/{AdminUserDetails-uqtC5aJ1.js → AdminUserDetails-DDe1A1GP.js} +30 -28
  26. package/dist/admin/AdminUserDetails-DDe1A1GP.js.map +1 -0
  27. package/dist/admin/{AdminUserLayout-CiPay35T.js → AdminUserLayout-HAlobhWf.js} +20 -19
  28. package/dist/admin/AdminUserLayout-HAlobhWf.js.map +1 -0
  29. package/dist/admin/{AdminUserSessions-DAE8Nf1F.js → AdminUserSessions-Bq1LnVLf.js} +5 -6
  30. package/dist/admin/AdminUserSessions-Bq1LnVLf.js.map +1 -0
  31. package/dist/admin/{AdminUserSettings-EbahaV2a.js → AdminUserSettings-BRsBZoxV.js} +10 -9
  32. package/dist/admin/AdminUserSettings-BRsBZoxV.js.map +1 -0
  33. package/dist/admin/{AdminUsers-Dcjh0KNW.js → AdminUsers-D71kIOSn.js} +6 -7
  34. package/dist/admin/AdminUsers-D71kIOSn.js.map +1 -0
  35. package/dist/admin/index.d.ts +21 -85
  36. package/dist/admin/index.d.ts.map +1 -1
  37. package/dist/admin/index.js +66 -88
  38. package/dist/admin/index.js.map +1 -1
  39. package/dist/auth/{AuthLayout-Dj5K4SIN.js → AuthLayout-CdJcrPs4.js} +2 -3
  40. package/dist/auth/{AuthLayout-Dj5K4SIN.js.map → AuthLayout-CdJcrPs4.js.map} +1 -1
  41. package/dist/{demo/IconGoogle-CbBF8Hqq.js → auth/IconGoogle-Bm18QD2q.js} +2 -4
  42. package/dist/auth/{IconGoogle-DpSlPZ1u.js.map → IconGoogle-Bm18QD2q.js.map} +1 -1
  43. package/dist/auth/{Login-BBqTosqZ.js → Login-BS_FYTy0.js} +19 -13
  44. package/dist/auth/Login-BS_FYTy0.js.map +1 -0
  45. package/dist/auth/{Profile-Bxj8Nwom.js → Profile-CjDsW378.js} +17 -12
  46. package/dist/auth/Profile-CjDsW378.js.map +1 -0
  47. package/dist/auth/{Register-Ce675Crg.js → Register-C5eqzAaD.js} +27 -17
  48. package/dist/auth/Register-C5eqzAaD.js.map +1 -0
  49. package/dist/auth/{ResetPassword-DWdt7c40.js → ResetPassword-XifinVao.js} +17 -10
  50. package/dist/auth/ResetPassword-XifinVao.js.map +1 -0
  51. package/dist/auth/{VerifyEmail-CI4JwByV.js → VerifyEmail-DTgbeJOO.js} +9 -6
  52. package/dist/auth/VerifyEmail-DTgbeJOO.js.map +1 -0
  53. package/dist/auth/index.d.ts +18 -14
  54. package/dist/auth/index.d.ts.map +1 -1
  55. package/dist/auth/index.js +19 -18
  56. package/dist/auth/index.js.map +1 -1
  57. package/dist/auth/rolldown-runtime-CjeV3_4I.js +18 -0
  58. package/dist/core/index.d.ts +182 -92
  59. package/dist/core/index.d.ts.map +1 -1
  60. package/dist/core/index.js +789 -476
  61. package/dist/core/index.js.map +1 -1
  62. package/dist/demo/DemoDataTable-lnBKWBf8.js +362 -0
  63. package/dist/demo/DemoDataTable-lnBKWBf8.js.map +1 -0
  64. package/dist/demo/{DemoHome-Cce2bWmg.js → DemoHome-CUMZsYaH.js} +6 -6
  65. package/dist/demo/DemoHome-CUMZsYaH.js.map +1 -0
  66. package/dist/demo/{DemoJsonViewer-Dgdk3Txb.js → DemoJsonViewer-_uokbGaW.js} +18 -19
  67. package/dist/demo/DemoJsonViewer-_uokbGaW.js.map +1 -0
  68. package/dist/demo/{DemoLayout-B20TEuhV.js → DemoLayout-DHVoacE6.js} +4 -5
  69. package/dist/demo/DemoLayout-DHVoacE6.js.map +1 -0
  70. package/dist/demo/{DemoLogin-CvCG2WVh.js → DemoLogin-DjJ9314c.js} +27 -24
  71. package/dist/demo/DemoLogin-DjJ9314c.js.map +1 -0
  72. package/dist/demo/{DemoRegister-CmeHbOAs.js → DemoRegister-DzkJ5M83.js} +39 -32
  73. package/dist/demo/DemoRegister-DzkJ5M83.js.map +1 -0
  74. package/dist/demo/{DemoResetPassword-CKO5iA_6.js → DemoResetPassword-DWh4_BpQ.js} +30 -26
  75. package/dist/demo/DemoResetPassword-DWh4_BpQ.js.map +1 -0
  76. package/dist/demo/{DemoSidebar-MVmQKfMt.js → DemoSidebar-C1csnGhX.js} +4 -5
  77. package/dist/demo/DemoSidebar-C1csnGhX.js.map +1 -0
  78. package/dist/demo/{DemoTypeForm-w-qtfRlC.js → DemoTypeForm-CWz6fJrJ.js} +4 -5
  79. package/dist/demo/DemoTypeForm-CWz6fJrJ.js.map +1 -0
  80. package/dist/demo/{DemoVerifyEmail-C8FFJT5A.js → DemoVerifyEmail-DbU_tCj8.js} +16 -16
  81. package/dist/demo/DemoVerifyEmail-DbU_tCj8.js.map +1 -0
  82. package/dist/{auth/IconGoogle-DpSlPZ1u.js → demo/IconGoogle-Ch1m3Uzl.js} +2 -4
  83. package/dist/demo/{IconGoogle-CbBF8Hqq.js.map → IconGoogle-Ch1m3Uzl.js.map} +1 -1
  84. package/dist/demo/{Showcase-CQrMWars.js → Showcase-BzoXNlCn.js} +11 -13
  85. package/dist/demo/Showcase-BzoXNlCn.js.map +1 -0
  86. package/dist/demo/index.d.ts +3 -70
  87. package/dist/demo/index.d.ts.map +1 -1
  88. package/dist/demo/index.js +11 -15
  89. package/dist/demo/index.js.map +1 -1
  90. package/dist/json/index.js +2 -2
  91. package/dist/json/index.js.map +1 -1
  92. package/package.json +11 -5
  93. package/src/admin/AdminRouter.ts +51 -29
  94. package/src/admin/components/AdminLayout.tsx +6 -9
  95. package/src/admin/components/audits/AdminAudits.tsx +5 -5
  96. package/src/admin/components/jobs/AdminJobDashboard.tsx +455 -0
  97. package/src/admin/components/jobs/AdminJobExecutions.tsx +693 -0
  98. package/src/admin/components/jobs/AdminJobRegistry.tsx +325 -0
  99. package/src/admin/components/keys/AdminApiKeys.tsx +28 -31
  100. package/src/admin/components/parameters/AdminParameters.tsx +156 -78
  101. package/src/admin/components/parameters/ParameterDetails.tsx +173 -108
  102. package/src/admin/components/parameters/ParameterEmptyState.tsx +27 -0
  103. package/src/admin/components/parameters/ParameterHistory.tsx +22 -35
  104. package/src/admin/components/parameters/ParameterTree.tsx +283 -109
  105. package/src/admin/components/parameters/types.ts +3 -3
  106. package/src/admin/components/sessions/AdminSessions.tsx +3 -3
  107. package/src/admin/components/shared/AdminResourceHeader.tsx +20 -16
  108. package/src/admin/components/users/AdminUserAudits.tsx +5 -5
  109. package/src/admin/components/users/AdminUserCreate.tsx +3 -3
  110. package/src/admin/components/users/AdminUserDetails.tsx +51 -53
  111. package/src/admin/components/users/AdminUserLayout.tsx +7 -7
  112. package/src/admin/components/users/AdminUserSessions.tsx +3 -3
  113. package/src/admin/components/users/AdminUserSettings.tsx +9 -9
  114. package/src/admin/components/users/AdminUsers.tsx +5 -5
  115. package/src/admin/components/verifications/AdminVerifications.tsx +3 -3
  116. package/src/admin/index.ts +0 -24
  117. package/src/admin/primitives/$uiAdmin.ts +2 -2
  118. package/src/auth/AuthRouter.ts +1 -0
  119. package/src/auth/components/Login.tsx +13 -13
  120. package/src/auth/components/Profile.tsx +17 -26
  121. package/src/auth/components/Register.tsx +21 -31
  122. package/src/auth/components/ResetPassword.tsx +13 -22
  123. package/src/auth/components/VerifyEmail.tsx +5 -5
  124. package/src/auth/components/buttons/UserButton.tsx +14 -4
  125. package/src/core/components/buttons/ActionButton.tsx +13 -17
  126. package/src/core/components/buttons/DarkModeButton.tsx +8 -4
  127. package/src/core/components/buttons/ToggleSidebarButton.tsx +3 -5
  128. package/src/core/components/data/ErrorViewer.tsx +15 -15
  129. package/src/core/components/dialogs/AlertDialog.tsx +3 -3
  130. package/src/core/components/dialogs/ConfirmDialog.tsx +3 -3
  131. package/src/core/components/dialogs/PromptDialog.tsx +3 -3
  132. package/src/core/components/form/Control.tsx +19 -32
  133. package/src/core/components/form/ControlArray.tsx +206 -96
  134. package/src/core/components/form/ControlObject.tsx +3 -3
  135. package/src/core/components/form/ControlQueryBuilder.tsx +20 -22
  136. package/src/core/components/form/ControlSelect.tsx +4 -0
  137. package/src/core/components/form/TypeForm.browser.spec.tsx +727 -0
  138. package/src/core/components/form/TypeForm.tsx +7 -0
  139. package/src/core/components/layout/AlephaMantineProvider.tsx +1 -0
  140. package/src/core/components/layout/Breadcrumb.tsx +91 -0
  141. package/src/core/components/layout/{AdminShell.tsx → DashboardShell.tsx} +77 -32
  142. package/src/core/components/layout/Omnibar.tsx +2 -1
  143. package/src/core/components/layout/Sidebar.tsx +63 -19
  144. package/src/core/components/table/ColumnPicker.tsx +47 -31
  145. package/src/core/components/table/DataTable.tsx +277 -201
  146. package/src/core/components/table/DataTableFilters.tsx +8 -0
  147. package/src/core/components/table/DataTableToolbar.tsx +98 -5
  148. package/src/core/components/table/FilterPicker.tsx +28 -26
  149. package/src/core/components/table/types.ts +52 -37
  150. package/src/core/components/table/useTableSelection.ts +83 -0
  151. package/src/core/constants/ui.ts +1 -1
  152. package/src/core/helpers/renderIcon.tsx +5 -2
  153. package/src/core/index.ts +9 -5
  154. package/src/core/styles.css +8 -7
  155. package/src/core/utils/parseInput.ts +1 -0
  156. package/src/core/utils/string.ts +28 -4
  157. package/src/demo/components/DemoHome.tsx +5 -5
  158. package/src/demo/components/DemoLayout.tsx +6 -2
  159. package/src/demo/components/core/DemoDataTable.tsx +209 -5
  160. package/src/demo/components/json/DemoJsonViewer.tsx +1 -1
  161. package/src/demo/components/shared/MacWindow.tsx +7 -7
  162. package/src/demo/components/shared/Showcase.tsx +3 -3
  163. package/src/demo/index.ts +0 -11
  164. package/src/json/components/JsonViewer.tsx +3 -3
  165. package/dist/admin/AdminApiKeys-DsmGnHNh.js +0 -3
  166. package/dist/admin/AdminApiKeys-GMORg-1l.js.map +0 -1
  167. package/dist/admin/AdminAudits-8SM96viT.js +0 -3
  168. package/dist/admin/AdminAudits-pkWrjq1Z.js.map +0 -1
  169. package/dist/admin/AdminFiles-B56ocq4H.js +0 -3
  170. package/dist/admin/AdminJobs-B-q9iGO3.js +0 -697
  171. package/dist/admin/AdminJobs-B-q9iGO3.js.map +0 -1
  172. package/dist/admin/AdminJobs-CED1syCn.js +0 -3
  173. package/dist/admin/AdminLayout-BqZiXx4H.js.map +0 -1
  174. package/dist/admin/AdminNotifications-B0B1rdc4.js +0 -3
  175. package/dist/admin/AdminParameters-BU3lATdJ.js +0 -3
  176. package/dist/admin/AdminParameters-CfDUpc78.js +0 -575
  177. package/dist/admin/AdminParameters-CfDUpc78.js.map +0 -1
  178. package/dist/admin/AdminSessions-BDGK2MS6.js +0 -3
  179. package/dist/admin/AdminSessions-DzIOxM3b.js.map +0 -1
  180. package/dist/admin/AdminUserAudits-CiUPN2BC.js.map +0 -1
  181. package/dist/admin/AdminUserAudits-Cj79gENT.js +0 -3
  182. package/dist/admin/AdminUserCreate-BwQKr4xE.js.map +0 -1
  183. package/dist/admin/AdminUserCreate-Cq-mUmBs.js +0 -3
  184. package/dist/admin/AdminUserDetails-DRjVAPFd.js +0 -3
  185. package/dist/admin/AdminUserDetails-uqtC5aJ1.js.map +0 -1
  186. package/dist/admin/AdminUserLayout-CGzmHHby.js +0 -3
  187. package/dist/admin/AdminUserLayout-CiPay35T.js.map +0 -1
  188. package/dist/admin/AdminUserSessions-DAE8Nf1F.js.map +0 -1
  189. package/dist/admin/AdminUserSessions-DcdzuNZ9.js +0 -3
  190. package/dist/admin/AdminUserSettings-D7V6-ceX.js +0 -3
  191. package/dist/admin/AdminUserSettings-EbahaV2a.js.map +0 -1
  192. package/dist/admin/AdminUsers-D9nyzGqQ.js +0 -3
  193. package/dist/admin/AdminUsers-Dcjh0KNW.js.map +0 -1
  194. package/dist/auth/Login-BBqTosqZ.js.map +0 -1
  195. package/dist/auth/Login-CoU63mMR.js +0 -4
  196. package/dist/auth/Profile-Bxj8Nwom.js.map +0 -1
  197. package/dist/auth/Register-BV_oa_AK.js +0 -4
  198. package/dist/auth/Register-Ce675Crg.js.map +0 -1
  199. package/dist/auth/ResetPassword-D5wC8GAA.js +0 -3
  200. package/dist/auth/ResetPassword-DWdt7c40.js.map +0 -1
  201. package/dist/auth/VerifyEmail-CI4JwByV.js.map +0 -1
  202. package/dist/auth/VerifyEmail-DAfqVm5s.js +0 -3
  203. package/dist/demo/DemoDataTable-CguplbR7.js +0 -150
  204. package/dist/demo/DemoDataTable-CguplbR7.js.map +0 -1
  205. package/dist/demo/DemoHome-Cce2bWmg.js.map +0 -1
  206. package/dist/demo/DemoHome-DC9qkMNe.js +0 -3
  207. package/dist/demo/DemoJsonViewer-DIssGVlJ.js +0 -4
  208. package/dist/demo/DemoJsonViewer-Dgdk3Txb.js.map +0 -1
  209. package/dist/demo/DemoLayout-B20TEuhV.js.map +0 -1
  210. package/dist/demo/DemoLayout-DSRyf4qJ.js +0 -3
  211. package/dist/demo/DemoLogin-CvCG2WVh.js.map +0 -1
  212. package/dist/demo/DemoRegister-CmeHbOAs.js.map +0 -1
  213. package/dist/demo/DemoResetPassword-CKO5iA_6.js.map +0 -1
  214. package/dist/demo/DemoSidebar-MVmQKfMt.js.map +0 -1
  215. package/dist/demo/DemoTypeForm-w-qtfRlC.js.map +0 -1
  216. package/dist/demo/DemoVerifyEmail-C8FFJT5A.js.map +0 -1
  217. package/dist/demo/Showcase-CQrMWars.js.map +0 -1
  218. package/src/admin/components/jobs/AdminJobs.tsx +0 -772
@@ -0,0 +1,774 @@
1
+ import { ActionButton, Flex, Text, TypeForm, useToast } from "@alepha/ui";
2
+ import { jsonSchemaToTypeBox, t } from "alepha";
3
+ import { IconArrowLeft, IconChevronDown, IconChevronRight, IconClock, IconFolder, IconFolderOpen, IconHistory, IconRefresh, IconSearch, IconSettings } from "@tabler/icons-react";
4
+ import { Badge, Card, Code, Collapse, Flex as Flex$1, Loader, ScrollArea, TextInput, Timeline, UnstyledButton } from "@mantine/core";
5
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
6
+ import { useClient } from "alepha/react";
7
+ import { useI18n } from "alepha/react/i18n";
8
+ import { memo, useCallback, useEffect, useMemo, useState } from "react";
9
+ import { useForm } from "alepha/react/form";
10
+
11
+ //#region ../../src/admin/components/parameters/types.ts
12
+ const getStatusColor = (status) => {
13
+ switch (status) {
14
+ case "current": return "green";
15
+ case "next": return "blue";
16
+ case "future": return "cyan";
17
+ case "expired": return "gray";
18
+ default: return "gray";
19
+ }
20
+ };
21
+ const formatJson = (obj) => {
22
+ try {
23
+ return JSON.stringify(obj, null, 2);
24
+ } catch {
25
+ return String(obj);
26
+ }
27
+ };
28
+
29
+ //#endregion
30
+ //#region ../../src/admin/components/parameters/ParameterDetails.tsx
31
+ /**
32
+ * Loading state.
33
+ */
34
+ const LoadingState = () => /* @__PURE__ */ jsx(Flex, {
35
+ flex: 1,
36
+ h: "100%",
37
+ p: "md",
38
+ style: {
39
+ overflow: "hidden",
40
+ minWidth: 0,
41
+ display: "flex"
42
+ },
43
+ children: /* @__PURE__ */ jsx(Flex, {
44
+ flex: 1,
45
+ justify: "center",
46
+ align: "center",
47
+ h: "100%",
48
+ children: /* @__PURE__ */ jsx(Loader, { size: "sm" })
49
+ })
50
+ });
51
+ /**
52
+ * The actual form component - only rendered when a config is selected.
53
+ */
54
+ const ConfigForm = ({ selectedConfig, configValue, saving, onSave }) => {
55
+ const { l } = useI18n();
56
+ const currentContent = useMemo(() => {
57
+ if (configValue?.current?.content) return configValue.current.content;
58
+ if (configValue?.currentValue !== void 0) return configValue.currentValue;
59
+ return null;
60
+ }, [configValue]);
61
+ const schemaForForm = useMemo(() => {
62
+ if (!configValue?.schema) return t.object({});
63
+ try {
64
+ return jsonSchemaToTypeBox(configValue.schema);
65
+ } catch {
66
+ return t.object({});
67
+ }
68
+ }, [configValue?.schema]);
69
+ const form = useForm({
70
+ schema: schemaForForm,
71
+ initialValues: currentContent ?? {},
72
+ handler: async (values) => {
73
+ await onSave(values);
74
+ }
75
+ }, [
76
+ selectedConfig,
77
+ schemaForForm,
78
+ currentContent
79
+ ]);
80
+ const hasValidSchema = useMemo(() => {
81
+ const schema = configValue?.schema;
82
+ return schema && typeof schema === "object" && "properties" in schema && Object.keys(schema.properties).length > 0;
83
+ }, [configValue?.schema]);
84
+ const fieldCount = useMemo(() => {
85
+ const schema = configValue?.schema;
86
+ if (schema && typeof schema === "object" && "properties" in schema && schema.properties) return Object.keys(schema.properties).length;
87
+ return 0;
88
+ }, [configValue?.schema]);
89
+ const columns = useMemo(() => {
90
+ if (fieldCount <= 2) return 1;
91
+ if (fieldCount <= 6) return 2;
92
+ return 3;
93
+ }, [fieldCount]);
94
+ return /* @__PURE__ */ jsx(Flex, {
95
+ flex: 1,
96
+ h: "100%",
97
+ style: {
98
+ overflow: "hidden",
99
+ minWidth: 0,
100
+ display: "flex"
101
+ },
102
+ children: /* @__PURE__ */ jsxs(Flex, {
103
+ direction: "column",
104
+ h: "100%",
105
+ w: "100%",
106
+ style: { minHeight: 0 },
107
+ children: [/* @__PURE__ */ jsx(Flex, {
108
+ flex: 1,
109
+ p: "md",
110
+ className: "overflow-auto",
111
+ style: { minHeight: 0 },
112
+ children: currentContent !== null ? /* @__PURE__ */ jsxs(Flex, {
113
+ direction: "column",
114
+ gap: "lg",
115
+ children: [
116
+ /* @__PURE__ */ jsx(Flex, { children: hasValidSchema ? /* @__PURE__ */ jsx(TypeForm, {
117
+ form,
118
+ columns,
119
+ skipSubmitButton: true,
120
+ fill: false
121
+ }) : /* @__PURE__ */ jsxs(Flex, { children: [/* @__PURE__ */ jsx(Text, {
122
+ size: "xs",
123
+ c: "dimmed",
124
+ mb: 4,
125
+ children: "Current Value"
126
+ }), /* @__PURE__ */ jsx(Code, {
127
+ block: true,
128
+ style: { whiteSpace: "pre-wrap" },
129
+ children: formatJson(currentContent)
130
+ })] }) }),
131
+ configValue?.current?.changeDescription && /* @__PURE__ */ jsxs(Flex, { children: [/* @__PURE__ */ jsx(Text, {
132
+ size: "xs",
133
+ c: "dimmed",
134
+ mb: 4,
135
+ children: "Change Description"
136
+ }), /* @__PURE__ */ jsx(Text, {
137
+ size: "sm",
138
+ children: configValue.current.changeDescription
139
+ })] }),
140
+ configValue?.current && /* @__PURE__ */ jsxs(Flex, {
141
+ gap: "xl",
142
+ children: [/* @__PURE__ */ jsxs(Flex, { children: [/* @__PURE__ */ jsx(Text, {
143
+ size: "xs",
144
+ c: "dimmed",
145
+ mb: 2,
146
+ children: "Updated"
147
+ }), /* @__PURE__ */ jsx(Text, {
148
+ size: "sm",
149
+ children: l(configValue.current.updatedAt, { date: "fromNow" })
150
+ })] }), configValue.current.creatorName && /* @__PURE__ */ jsxs(Flex, { children: [/* @__PURE__ */ jsx(Text, {
151
+ size: "xs",
152
+ c: "dimmed",
153
+ mb: 2,
154
+ children: "Updated By"
155
+ }), /* @__PURE__ */ jsx(Text, {
156
+ size: "sm",
157
+ children: configValue.current.creatorName
158
+ })] })]
159
+ }),
160
+ !configValue?.current && configValue?.currentValue !== void 0 && /* @__PURE__ */ jsx(Text, {
161
+ size: "xs",
162
+ c: "dimmed",
163
+ children: "This configuration is using its default value. No versions have been saved to the database yet."
164
+ }),
165
+ configValue?.next && /* @__PURE__ */ jsx(Card, {
166
+ withBorder: true,
167
+ p: "sm",
168
+ bg: "var(--mantine-color-blue-light)",
169
+ children: /* @__PURE__ */ jsxs(Flex, {
170
+ direction: "column",
171
+ gap: "xs",
172
+ children: [
173
+ /* @__PURE__ */ jsxs(Flex, {
174
+ gap: "xs",
175
+ children: [/* @__PURE__ */ jsx(IconClock, {
176
+ size: 14,
177
+ color: "var(--mantine-color-blue-6)"
178
+ }), /* @__PURE__ */ jsxs(Text, {
179
+ size: "xs",
180
+ fw: 500,
181
+ c: "blue",
182
+ children: [
183
+ "Scheduled Update (v",
184
+ configValue.next.version,
185
+ ")"
186
+ ]
187
+ })]
188
+ }),
189
+ /* @__PURE__ */ jsxs(Text, {
190
+ size: "xs",
191
+ c: "dimmed",
192
+ children: [
193
+ "Activates",
194
+ " ",
195
+ l(configValue.next.activationDate, { date: "fromNow" })
196
+ ]
197
+ }),
198
+ /* @__PURE__ */ jsx(Code, {
199
+ block: true,
200
+ style: { whiteSpace: "pre-wrap" },
201
+ fz: "xs",
202
+ children: formatJson(configValue.next.content)
203
+ })
204
+ ]
205
+ })
206
+ })
207
+ ]
208
+ }) : /* @__PURE__ */ jsx(Flex, {
209
+ justify: "center",
210
+ align: "center",
211
+ h: 200,
212
+ children: /* @__PURE__ */ jsx(Text, {
213
+ c: "dimmed",
214
+ size: "sm",
215
+ children: "No current value"
216
+ })
217
+ })
218
+ }), hasValidSchema && currentContent !== null && /* @__PURE__ */ jsx(Flex, {
219
+ p: "md",
220
+ style: {
221
+ flexShrink: 0,
222
+ borderTop: "1px solid var(--mantine-color-default-border)"
223
+ },
224
+ children: /* @__PURE__ */ jsxs(Flex, {
225
+ justify: "flex-end",
226
+ gap: "sm",
227
+ children: [/* @__PURE__ */ jsx(ActionButton, {
228
+ variant: "subtle",
229
+ onClick: () => form.reset({}),
230
+ disabled: saving,
231
+ children: "Reset"
232
+ }), /* @__PURE__ */ jsx(ActionButton, {
233
+ intent: "primary",
234
+ form,
235
+ loading: saving,
236
+ children: "Save Changes"
237
+ })]
238
+ })
239
+ })]
240
+ })
241
+ });
242
+ };
243
+ /**
244
+ * Parameter details panel.
245
+ * Shows loading state or the config form.
246
+ * Note: Empty state is handled by parent (AdminParameters).
247
+ */
248
+ const ParameterDetails = ({ selectedConfig, configValue, loading, saving, onSave }) => {
249
+ if (loading) return /* @__PURE__ */ jsx(LoadingState, {});
250
+ return /* @__PURE__ */ jsx(ConfigForm, {
251
+ selectedConfig,
252
+ configValue,
253
+ saving,
254
+ onSave
255
+ });
256
+ };
257
+
258
+ //#endregion
259
+ //#region ../../src/admin/components/parameters/ParameterEmptyState.tsx
260
+ /**
261
+ * Empty state displayed when no parameter is selected.
262
+ * Invites user to select a parameter from the tree.
263
+ */
264
+ const ParameterEmptyState = () => {
265
+ return /* @__PURE__ */ jsx(Flex$1, {
266
+ flex: 1,
267
+ p: "xl",
268
+ align: "center",
269
+ children: /* @__PURE__ */ jsxs(Flex$1, {
270
+ direction: "column",
271
+ align: "center",
272
+ gap: "md",
273
+ children: [/* @__PURE__ */ jsx(IconArrowLeft, {
274
+ size: 32,
275
+ color: "var(--mantine-color-dimmed)"
276
+ }), /* @__PURE__ */ jsxs(Flex$1, {
277
+ direction: "column",
278
+ align: "center",
279
+ gap: 4,
280
+ children: [/* @__PURE__ */ jsx(Text, {
281
+ fw: 500,
282
+ c: "dimmed",
283
+ children: "No Parameter Selected"
284
+ }), /* @__PURE__ */ jsx(Text, {
285
+ size: "xs",
286
+ c: "dimmed",
287
+ ta: "center",
288
+ maw: 240,
289
+ children: "Choose a parameter from the tree to view and edit its configuration"
290
+ })]
291
+ })]
292
+ })
293
+ });
294
+ };
295
+
296
+ //#endregion
297
+ //#region ../../src/admin/components/parameters/ParameterHistory.tsx
298
+ const ParameterHistory = ({ history, loading, onRollback }) => {
299
+ const { l } = useI18n();
300
+ const renderContent = () => {
301
+ if (loading) return /* @__PURE__ */ jsx(Flex, {
302
+ flex: 1,
303
+ justify: "center",
304
+ align: "center",
305
+ children: /* @__PURE__ */ jsx(Loader, { size: "sm" })
306
+ });
307
+ if (history.length === 0) return /* @__PURE__ */ jsx(Flex, {
308
+ flex: 1,
309
+ justify: "center",
310
+ align: "center",
311
+ children: /* @__PURE__ */ jsx(Text, {
312
+ c: "dimmed",
313
+ size: "xs",
314
+ children: "Empty"
315
+ })
316
+ });
317
+ return /* @__PURE__ */ jsx(ScrollArea, {
318
+ flex: 1,
319
+ offsetScrollbars: true,
320
+ children: /* @__PURE__ */ jsx(Timeline, {
321
+ active: history.findIndex((h) => h.status === "current"),
322
+ bulletSize: 24,
323
+ lineWidth: 2,
324
+ children: history.map((version) => /* @__PURE__ */ jsx(Timeline.Item, {
325
+ bullet: /* @__PURE__ */ jsx(Text, {
326
+ size: "xs",
327
+ fw: 500,
328
+ children: version.version
329
+ }),
330
+ title: /* @__PURE__ */ jsxs(Flex, {
331
+ gap: "xs",
332
+ children: [/* @__PURE__ */ jsxs(Text, {
333
+ size: "xs",
334
+ fw: 500,
335
+ children: ["Version ", version.version]
336
+ }), /* @__PURE__ */ jsx(Badge, {
337
+ size: "xs",
338
+ variant: "light",
339
+ color: getStatusColor(version.status),
340
+ children: version.status
341
+ })]
342
+ }),
343
+ children: /* @__PURE__ */ jsxs(Flex, {
344
+ direction: "column",
345
+ gap: 4,
346
+ mt: 4,
347
+ children: [
348
+ /* @__PURE__ */ jsx(Text, {
349
+ size: "xs",
350
+ c: "dimmed",
351
+ children: l(version.createdAt, { date: "fromNow" })
352
+ }),
353
+ version.changeDescription && /* @__PURE__ */ jsx(Text, {
354
+ size: "xs",
355
+ lineClamp: 2,
356
+ children: version.changeDescription
357
+ }),
358
+ version.creatorName && /* @__PURE__ */ jsxs(Text, {
359
+ size: "xs",
360
+ c: "dimmed",
361
+ children: ["by ", version.creatorName]
362
+ }),
363
+ version.migrationLog && /* @__PURE__ */ jsx(Badge, {
364
+ size: "xs",
365
+ variant: "outline",
366
+ color: "orange",
367
+ children: "Schema Changed"
368
+ }),
369
+ version.status === "expired" && /* @__PURE__ */ jsx(ActionButton, {
370
+ size: "compact-xs",
371
+ variant: "subtle",
372
+ onClick: () => onRollback(version.version),
373
+ children: "Rollback to this version"
374
+ })
375
+ ]
376
+ })
377
+ }, version.id))
378
+ })
379
+ });
380
+ };
381
+ return /* @__PURE__ */ jsx(Flex, {
382
+ w: 160,
383
+ h: "100%",
384
+ p: "xs",
385
+ style: {
386
+ flexShrink: 0,
387
+ overflow: "hidden",
388
+ display: "flex",
389
+ flexDirection: "column",
390
+ borderLeft: "1px solid var(--mantine-color-default-border)"
391
+ },
392
+ children: /* @__PURE__ */ jsxs(Flex, {
393
+ direction: "column",
394
+ gap: "xs",
395
+ h: "100%",
396
+ style: { minHeight: 0 },
397
+ children: [/* @__PURE__ */ jsxs(Flex, {
398
+ gap: "xs",
399
+ children: [/* @__PURE__ */ jsx(IconHistory, {
400
+ size: 16,
401
+ color: "var(--mantine-color-dimmed)"
402
+ }), /* @__PURE__ */ jsx(Text, {
403
+ size: "sm",
404
+ fw: 500,
405
+ children: "History"
406
+ })]
407
+ }), renderContent()]
408
+ })
409
+ });
410
+ };
411
+
412
+ //#endregion
413
+ //#region ../../src/admin/components/parameters/ParameterTree.tsx
414
+ /**
415
+ * Filters tree nodes by search query.
416
+ */
417
+ const filterTree = (nodes, query) => {
418
+ if (!query.trim()) return nodes;
419
+ const lowerQuery = query.toLowerCase();
420
+ return nodes.map((node) => {
421
+ const filteredChildren = filterTree(node.children, query);
422
+ const nameMatches = node.name.toLowerCase().includes(lowerQuery);
423
+ const pathMatches = node.path.toLowerCase().includes(lowerQuery);
424
+ if (nameMatches || pathMatches || filteredChildren.length > 0) return {
425
+ ...node,
426
+ children: filteredChildren
427
+ };
428
+ return null;
429
+ }).filter((node) => node !== null);
430
+ };
431
+ /**
432
+ * Memoized tree node to prevent unnecessary re-renders.
433
+ */
434
+ const TreeNode = memo(({ node, level, selectedConfig, onSelect, expandedNodes, onToggle }) => {
435
+ const [isHovered, setIsHovered] = useState(false);
436
+ const hasChildren = node.children.length > 0;
437
+ const isExpanded = expandedNodes.has(node.path);
438
+ const isSelected = selectedConfig === node.path;
439
+ const isLeaf = !hasChildren;
440
+ return /* @__PURE__ */ jsxs(Flex$1, { children: [/* @__PURE__ */ jsx(UnstyledButton, {
441
+ onClick: useCallback(() => {
442
+ if (hasChildren) onToggle(node.path);
443
+ else onSelect(node.path);
444
+ }, [
445
+ hasChildren,
446
+ node.path,
447
+ onToggle,
448
+ onSelect
449
+ ]),
450
+ onMouseEnter: useCallback(() => setIsHovered(true), []),
451
+ onMouseLeave: useCallback(() => setIsHovered(false), []),
452
+ w: "100%",
453
+ style: { display: "block" },
454
+ children: /* @__PURE__ */ jsxs(Flex$1, {
455
+ gap: 6,
456
+ wrap: "nowrap",
457
+ p: "4px 8px",
458
+ pl: 8 + level * 16,
459
+ style: {
460
+ borderRadius: "var(--mantine-radius-sm)",
461
+ backgroundColor: isSelected || isHovered ? "var(--mantine-color-default-hover)" : void 0
462
+ },
463
+ children: [hasChildren ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Flex$1, {
464
+ style: {
465
+ display: "flex",
466
+ alignItems: "center",
467
+ justifyContent: "center",
468
+ width: 16
469
+ },
470
+ children: isExpanded ? /* @__PURE__ */ jsx(IconChevronDown, {
471
+ size: 14,
472
+ color: "var(--mantine-color-dimmed)"
473
+ }) : /* @__PURE__ */ jsx(IconChevronRight, {
474
+ size: 14,
475
+ color: "var(--mantine-color-dimmed)"
476
+ })
477
+ }), isExpanded ? /* @__PURE__ */ jsx(IconFolderOpen, {
478
+ size: 16,
479
+ color: "var(--mantine-color-dimmed)",
480
+ style: { flexShrink: 0 }
481
+ }) : /* @__PURE__ */ jsx(IconFolder, {
482
+ size: 16,
483
+ color: "var(--mantine-color-dimmed)",
484
+ style: { flexShrink: 0 }
485
+ })] }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Flex$1, { w: 16 }), /* @__PURE__ */ jsx(IconSettings, {
486
+ size: 16,
487
+ color: isSelected ? "var(--mantine-color-blue-6)" : "var(--mantine-color-dimmed)",
488
+ style: { flexShrink: 0 }
489
+ })] }), /* @__PURE__ */ jsx(Text, {
490
+ size: "sm",
491
+ fw: isSelected ? 600 : 400,
492
+ c: isSelected ? void 0 : isLeaf ? void 0 : "dimmed",
493
+ style: {
494
+ whiteSpace: "nowrap",
495
+ overflow: "hidden",
496
+ textOverflow: "ellipsis"
497
+ },
498
+ children: node.name
499
+ })]
500
+ })
501
+ }), hasChildren && /* @__PURE__ */ jsx(Collapse, {
502
+ in: isExpanded,
503
+ children: node.children.map((child) => /* @__PURE__ */ jsx(TreeNode, {
504
+ node: child,
505
+ level: level + 1,
506
+ selectedConfig,
507
+ onSelect,
508
+ expandedNodes,
509
+ onToggle
510
+ }, child.path))
511
+ })] });
512
+ });
513
+ TreeNode.displayName = "TreeNode";
514
+ /**
515
+ * Collects all folder paths to expand by default.
516
+ */
517
+ const collectAllFolderPaths = (nodes) => {
518
+ const paths = /* @__PURE__ */ new Set();
519
+ const traverse = (nodeList) => {
520
+ for (const node of nodeList) if (node.children.length > 0) {
521
+ paths.add(node.path);
522
+ traverse(node.children);
523
+ }
524
+ };
525
+ traverse(nodes);
526
+ return paths;
527
+ };
528
+ const ParameterTree = ({ treeData, selectedConfig, onSelect, onRefresh }) => {
529
+ const [searchQuery, setSearchQuery] = useState("");
530
+ const [expandedNodes, setExpandedNodes] = useState(() => collectAllFolderPaths(treeData));
531
+ const filteredTreeData = useMemo(() => filterTree(treeData, searchQuery), [treeData, searchQuery]);
532
+ const handleToggle = useCallback((path) => {
533
+ setExpandedNodes((prev) => {
534
+ const next = new Set(prev);
535
+ if (next.has(path)) next.delete(path);
536
+ else next.add(path);
537
+ return next;
538
+ });
539
+ }, []);
540
+ const handleSearchChange = useCallback((e) => {
541
+ setSearchQuery(e.currentTarget.value);
542
+ }, []);
543
+ return /* @__PURE__ */ jsx(Flex$1, {
544
+ w: 280,
545
+ h: "100%",
546
+ p: "sm",
547
+ style: {
548
+ flexShrink: 0,
549
+ display: "flex",
550
+ flexDirection: "column",
551
+ borderRight: "1px solid var(--mantine-color-default-border)"
552
+ },
553
+ children: /* @__PURE__ */ jsxs(Flex$1, {
554
+ direction: "column",
555
+ gap: "sm",
556
+ h: "100%",
557
+ style: { minHeight: 0 },
558
+ children: [
559
+ /* @__PURE__ */ jsxs(Flex$1, {
560
+ justify: "space-between",
561
+ gap: "xs",
562
+ children: [/* @__PURE__ */ jsx(Text, {
563
+ size: "sm",
564
+ fw: 600,
565
+ children: "Parameters"
566
+ }), /* @__PURE__ */ jsx(ActionButton, {
567
+ variant: "subtle",
568
+ size: "compact-xs",
569
+ onClick: onRefresh,
570
+ tooltip: "Refresh",
571
+ children: /* @__PURE__ */ jsx(IconRefresh, { size: 14 })
572
+ })]
573
+ }),
574
+ /* @__PURE__ */ jsx(TextInput, {
575
+ placeholder: "Search...",
576
+ size: "xs",
577
+ leftSection: /* @__PURE__ */ jsx(IconSearch, { size: 14 }),
578
+ value: searchQuery,
579
+ onChange: handleSearchChange
580
+ }),
581
+ /* @__PURE__ */ jsx(ScrollArea, {
582
+ flex: 1,
583
+ offsetScrollbars: true,
584
+ style: { minHeight: 0 },
585
+ children: filteredTreeData.length === 0 ? /* @__PURE__ */ jsx(Text, {
586
+ size: "xs",
587
+ c: "dimmed",
588
+ ta: "center",
589
+ py: "md",
590
+ children: searchQuery ? "No matching parameters" : "No parameters"
591
+ }) : /* @__PURE__ */ jsx(Flex$1, {
592
+ direction: "column",
593
+ gap: 0,
594
+ style: { gap: 1 },
595
+ children: filteredTreeData.map((node) => /* @__PURE__ */ jsx(TreeNode, {
596
+ node,
597
+ level: 0,
598
+ selectedConfig,
599
+ onSelect,
600
+ expandedNodes,
601
+ onToggle: handleToggle
602
+ }, node.path))
603
+ })
604
+ })
605
+ ]
606
+ })
607
+ });
608
+ };
609
+
610
+ //#endregion
611
+ //#region ../../src/admin/components/parameters/AdminParameters.tsx
612
+ const AdminParameters = ({ treeData: initialTreeData }) => {
613
+ const client = useClient();
614
+ const toast = useToast();
615
+ const [treeData, setTreeData] = useState(initialTreeData);
616
+ const [selectedConfig, setSelectedConfig] = useState(null);
617
+ const [configValue, setConfigValue] = useState(null);
618
+ const [history, setHistory] = useState([]);
619
+ const [loadingConfig, setLoadingConfig] = useState(false);
620
+ const [loadingHistory, setLoadingHistory] = useState(false);
621
+ const [saving, setSaving] = useState(false);
622
+ const handleRefresh = useCallback(async () => {
623
+ try {
624
+ setTreeData(await client.getParameterTree({}));
625
+ } catch (error) {
626
+ toast.danger({
627
+ title: "Failed to refresh parameters",
628
+ message: error instanceof Error ? error.message : "Unknown error"
629
+ });
630
+ }
631
+ }, [client, toast]);
632
+ const loadConfigDetails = useCallback(async (name) => {
633
+ setLoadingConfig(true);
634
+ setLoadingHistory(true);
635
+ try {
636
+ const [currentResponse, historyResponse] = await Promise.all([client.getCurrent({ params: { name } }), client.getHistory({ params: { name } })]);
637
+ setConfigValue(currentResponse);
638
+ setHistory(historyResponse.versions);
639
+ } catch (error) {
640
+ toast.danger({
641
+ title: "Failed to load configuration",
642
+ message: error instanceof Error ? error.message : "Unknown error"
643
+ });
644
+ setConfigValue(null);
645
+ setHistory([]);
646
+ } finally {
647
+ setLoadingConfig(false);
648
+ setLoadingHistory(false);
649
+ }
650
+ }, [client, toast]);
651
+ const handleSave = useCallback(async (values) => {
652
+ if (!selectedConfig || !configValue) return;
653
+ setSaving(true);
654
+ try {
655
+ await client.createVersion({
656
+ params: { name: selectedConfig },
657
+ body: {
658
+ content: values,
659
+ schemaHash: "",
660
+ changeDescription: "Updated via admin UI"
661
+ }
662
+ });
663
+ toast.success({
664
+ title: "Configuration saved",
665
+ message: `${selectedConfig} has been updated`
666
+ });
667
+ await loadConfigDetails(selectedConfig);
668
+ } catch (error) {
669
+ toast.danger({
670
+ title: "Failed to save configuration",
671
+ message: error instanceof Error ? error.message : "Unknown error"
672
+ });
673
+ throw error;
674
+ } finally {
675
+ setSaving(false);
676
+ }
677
+ }, [
678
+ client,
679
+ selectedConfig,
680
+ configValue,
681
+ loadConfigDetails,
682
+ toast
683
+ ]);
684
+ useEffect(() => {
685
+ if (selectedConfig) loadConfigDetails(selectedConfig);
686
+ else {
687
+ setConfigValue(null);
688
+ setHistory([]);
689
+ }
690
+ }, [selectedConfig, loadConfigDetails]);
691
+ const handleRollback = useCallback(async (version) => {
692
+ if (!selectedConfig) return;
693
+ try {
694
+ await client.rollback({
695
+ params: { name: selectedConfig },
696
+ body: { targetVersion: version }
697
+ });
698
+ toast.success({
699
+ title: "Rollback successful",
700
+ message: `${selectedConfig} rolled back to version ${version}`
701
+ });
702
+ await loadConfigDetails(selectedConfig);
703
+ } catch (error) {
704
+ toast.danger({
705
+ title: "Rollback failed",
706
+ message: error instanceof Error ? error.message : "Unknown error"
707
+ });
708
+ }
709
+ }, [
710
+ client,
711
+ selectedConfig,
712
+ loadConfigDetails,
713
+ toast
714
+ ]);
715
+ if (treeData.length === 0) return /* @__PURE__ */ jsx(Flex$1, {
716
+ flex: 1,
717
+ justify: "center",
718
+ align: "center",
719
+ children: /* @__PURE__ */ jsxs(Flex$1, {
720
+ direction: "column",
721
+ align: "center",
722
+ gap: "xs",
723
+ children: [
724
+ /* @__PURE__ */ jsx(IconSettings, {
725
+ size: 48,
726
+ stroke: 1.5,
727
+ color: "var(--mantine-color-dimmed)"
728
+ }),
729
+ /* @__PURE__ */ jsx(Text, {
730
+ c: "dimmed",
731
+ children: "No Parameters Found"
732
+ }),
733
+ /* @__PURE__ */ jsx(Text, {
734
+ size: "xs",
735
+ c: "dimmed",
736
+ ta: "center",
737
+ maw: 400,
738
+ children: "Define parameters using the $parameter primitive to manage dynamic application settings. Parameters will appear here once created."
739
+ })
740
+ ]
741
+ })
742
+ });
743
+ return /* @__PURE__ */ jsx(Flex$1, {
744
+ flex: 1,
745
+ p: "md",
746
+ children: /* @__PURE__ */ jsxs(Card, {
747
+ withBorder: true,
748
+ p: 0,
749
+ w: "100%",
750
+ style: { flexDirection: "row" },
751
+ children: [/* @__PURE__ */ jsx(ParameterTree, {
752
+ treeData,
753
+ selectedConfig,
754
+ onSelect: setSelectedConfig,
755
+ onRefresh: handleRefresh
756
+ }), selectedConfig ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(ParameterDetails, {
757
+ selectedConfig,
758
+ configValue,
759
+ loading: loadingConfig,
760
+ saving,
761
+ onSave: handleSave
762
+ }), /* @__PURE__ */ jsx(ParameterHistory, {
763
+ selectedConfig,
764
+ history,
765
+ loading: loadingHistory,
766
+ onRollback: handleRollback
767
+ })] }) : /* @__PURE__ */ jsx(ParameterEmptyState, {})]
768
+ })
769
+ });
770
+ };
771
+
772
+ //#endregion
773
+ export { AdminParameters as default };
774
+ //# sourceMappingURL=AdminParameters-iQE8o7a7.js.map