@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.
- package/dist/admin/{AdminApiKeys-CoTOTfgU.js → AdminApiKeys-CF_qOO3u.js} +20 -20
- package/dist/admin/AdminApiKeys-CF_qOO3u.js.map +1 -0
- package/dist/admin/{AdminAudits-BmsxFbDa.js → AdminAudits-BQno3hZG.js} +7 -8
- package/dist/admin/AdminAudits-BQno3hZG.js.map +1 -0
- package/dist/admin/{AdminFiles-BBB8knca.js → AdminFiles-kvuUaASF.js} +3 -5
- package/dist/admin/{AdminFiles-BBB8knca.js.map → AdminFiles-kvuUaASF.js.map} +1 -1
- package/dist/admin/AdminJobDashboard-CrPxp0W1.js +485 -0
- package/dist/admin/AdminJobDashboard-CrPxp0W1.js.map +1 -0
- package/dist/admin/AdminJobExecutions-D-b4Zt7W.js +678 -0
- package/dist/admin/AdminJobExecutions-D-b4Zt7W.js.map +1 -0
- package/dist/admin/AdminJobRegistry-CNX5cpDx.js +301 -0
- package/dist/admin/AdminJobRegistry-CNX5cpDx.js.map +1 -0
- package/dist/admin/{AdminLayout-CsjvpeD1.js → AdminLayout-e-ZP5nWw.js} +1 -1
- package/dist/admin/{AdminLayout-CsjvpeD1.js.map → AdminLayout-e-ZP5nWw.js.map} +1 -1
- package/dist/admin/{AdminNotifications-LwR6RKrx.js → AdminNotifications-DeHJFf6W.js} +3 -5
- package/dist/admin/{AdminNotifications-LwR6RKrx.js.map → AdminNotifications-DeHJFf6W.js.map} +1 -1
- package/dist/admin/{AdminParameters-B_83Vie9.js → AdminParameters-iQE8o7a7.js} +43 -36
- package/dist/admin/AdminParameters-iQE8o7a7.js.map +1 -0
- package/dist/admin/{AdminSessions-CWnPosdd.js → AdminSessions-oKJCbd7w.js} +5 -7
- package/dist/admin/AdminSessions-oKJCbd7w.js.map +1 -0
- package/dist/admin/{AdminUserAudits-nHv636E_.js → AdminUserAudits-BNCEle_E.js} +6 -8
- package/dist/admin/AdminUserAudits-BNCEle_E.js.map +1 -0
- package/dist/admin/{AdminUserCreate-CjYD3Kjc.js → AdminUserCreate-CgqeFwCt.js} +6 -7
- package/dist/admin/AdminUserCreate-CgqeFwCt.js.map +1 -0
- package/dist/admin/{AdminUserDetails-Ccq-LsZ0.js → AdminUserDetails-DDe1A1GP.js} +30 -29
- package/dist/admin/AdminUserDetails-DDe1A1GP.js.map +1 -0
- package/dist/admin/{AdminUserLayout-7s41DiF_.js → AdminUserLayout-HAlobhWf.js} +18 -16
- package/dist/admin/AdminUserLayout-HAlobhWf.js.map +1 -0
- package/dist/admin/{AdminUserSessions-Ds3ODq_d.js → AdminUserSessions-Bq1LnVLf.js} +5 -7
- package/dist/admin/AdminUserSessions-Bq1LnVLf.js.map +1 -0
- package/dist/admin/{AdminUserSettings-CGh4gROo.js → AdminUserSettings-BRsBZoxV.js} +10 -10
- package/dist/admin/AdminUserSettings-BRsBZoxV.js.map +1 -0
- package/dist/admin/{AdminUsers-CvPiBzQK.js → AdminUsers-D71kIOSn.js} +6 -8
- package/dist/admin/AdminUsers-D71kIOSn.js.map +1 -0
- package/dist/admin/index.d.ts +7 -83
- package/dist/admin/index.d.ts.map +1 -1
- package/dist/admin/index.js +49 -70
- package/dist/admin/index.js.map +1 -1
- package/dist/auth/{Login-DS_OqA0G.js → Login-BS_FYTy0.js} +13 -8
- package/dist/auth/Login-BS_FYTy0.js.map +1 -0
- package/dist/auth/{Profile-Di7N7HZL.js → Profile-CjDsW378.js} +16 -10
- package/dist/auth/Profile-CjDsW378.js.map +1 -0
- package/dist/auth/{Register-BRR2_gux.js → Register-C5eqzAaD.js} +21 -12
- package/dist/auth/Register-C5eqzAaD.js.map +1 -0
- package/dist/auth/{ResetPassword-oQu72lod.js → ResetPassword-XifinVao.js} +14 -8
- package/dist/auth/ResetPassword-XifinVao.js.map +1 -0
- package/dist/auth/{VerifyEmail-DC6HPZjd.js → VerifyEmail-DTgbeJOO.js} +6 -4
- package/dist/auth/VerifyEmail-DTgbeJOO.js.map +1 -0
- package/dist/auth/index.d.ts +4 -0
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +15 -14
- package/dist/auth/index.js.map +1 -1
- package/dist/core/index.d.ts +37 -26
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +444 -193
- package/dist/core/index.js.map +1 -1
- package/dist/demo/DemoDataTable-lnBKWBf8.js +362 -0
- package/dist/demo/DemoDataTable-lnBKWBf8.js.map +1 -0
- package/dist/demo/{DemoHome-DpRrPlBC.js → DemoHome-CUMZsYaH.js} +6 -7
- package/dist/demo/DemoHome-CUMZsYaH.js.map +1 -0
- package/dist/demo/{DemoJsonViewer-zeucGKHV.js → DemoJsonViewer-_uokbGaW.js} +17 -19
- package/dist/demo/DemoJsonViewer-_uokbGaW.js.map +1 -0
- package/dist/demo/{DemoLayout-PhgbAAiQ.js → DemoLayout-DHVoacE6.js} +2 -4
- package/dist/demo/{DemoLayout-PhgbAAiQ.js.map → DemoLayout-DHVoacE6.js.map} +1 -1
- package/dist/demo/{DemoLogin-DSzP0Lkv.js → DemoLogin-DjJ9314c.js} +22 -17
- package/dist/demo/DemoLogin-DjJ9314c.js.map +1 -0
- package/dist/demo/{DemoRegister-DavFBsCz.js → DemoRegister-DzkJ5M83.js} +34 -25
- package/dist/demo/DemoRegister-DzkJ5M83.js.map +1 -0
- package/dist/demo/{DemoResetPassword-BS2rIAQK.js → DemoResetPassword-DWh4_BpQ.js} +27 -21
- package/dist/demo/DemoResetPassword-DWh4_BpQ.js.map +1 -0
- package/dist/demo/{DemoSidebar-zNkUmHRl.js → DemoSidebar-C1csnGhX.js} +2 -2
- package/dist/demo/{DemoSidebar-zNkUmHRl.js.map → DemoSidebar-C1csnGhX.js.map} +1 -1
- package/dist/demo/{DemoTypeForm-B9q7oT0b.js → DemoTypeForm-CWz6fJrJ.js} +2 -2
- package/dist/demo/{DemoTypeForm-B9q7oT0b.js.map → DemoTypeForm-CWz6fJrJ.js.map} +1 -1
- package/dist/demo/{DemoVerifyEmail-Bi4SdWz0.js → DemoVerifyEmail-DbU_tCj8.js} +13 -11
- package/dist/demo/DemoVerifyEmail-DbU_tCj8.js.map +1 -0
- package/dist/demo/{IconGoogle-CTeZyrek.js → IconGoogle-Ch1m3Uzl.js} +1 -1
- package/dist/demo/{IconGoogle-CTeZyrek.js.map → IconGoogle-Ch1m3Uzl.js.map} +1 -1
- package/dist/demo/{Showcase-C9btr_SJ.js → Showcase-BzoXNlCn.js} +10 -10
- package/dist/demo/Showcase-BzoXNlCn.js.map +1 -0
- package/dist/demo/index.d.ts +1 -68
- package/dist/demo/index.d.ts.map +1 -1
- package/dist/demo/index.js +11 -15
- package/dist/demo/index.js.map +1 -1
- package/dist/json/index.js +2 -2
- package/dist/json/index.js.map +1 -1
- package/package.json +9 -5
- package/src/admin/AdminRouter.ts +36 -5
- package/src/admin/components/audits/AdminAudits.tsx +5 -5
- package/src/admin/components/jobs/AdminJobDashboard.tsx +455 -0
- package/src/admin/components/jobs/AdminJobExecutions.tsx +693 -0
- package/src/admin/components/jobs/AdminJobRegistry.tsx +325 -0
- package/src/admin/components/keys/AdminApiKeys.tsx +28 -31
- package/src/admin/components/parameters/AdminParameters.tsx +3 -3
- package/src/admin/components/parameters/ParameterDetails.tsx +34 -29
- package/src/admin/components/parameters/ParameterEmptyState.tsx +5 -5
- package/src/admin/components/parameters/ParameterHistory.tsx +11 -19
- package/src/admin/components/parameters/ParameterTree.tsx +16 -18
- package/src/admin/components/sessions/AdminSessions.tsx +3 -3
- package/src/admin/components/shared/AdminResourceHeader.tsx +20 -16
- package/src/admin/components/users/AdminUserAudits.tsx +5 -5
- package/src/admin/components/users/AdminUserCreate.tsx +3 -3
- package/src/admin/components/users/AdminUserDetails.tsx +51 -53
- package/src/admin/components/users/AdminUserLayout.tsx +7 -7
- package/src/admin/components/users/AdminUserSessions.tsx +3 -3
- package/src/admin/components/users/AdminUserSettings.tsx +9 -9
- package/src/admin/components/users/AdminUsers.tsx +5 -5
- package/src/admin/components/verifications/AdminVerifications.tsx +3 -3
- package/src/admin/index.ts +0 -24
- package/src/auth/components/Login.tsx +13 -13
- package/src/auth/components/Profile.tsx +17 -26
- package/src/auth/components/Register.tsx +21 -31
- package/src/auth/components/ResetPassword.tsx +13 -22
- package/src/auth/components/VerifyEmail.tsx +5 -5
- package/src/auth/components/buttons/UserButton.tsx +14 -4
- package/src/core/components/buttons/ActionButton.tsx +9 -2
- package/src/core/components/data/ErrorViewer.tsx +15 -15
- package/src/core/components/dialogs/AlertDialog.tsx +3 -3
- package/src/core/components/dialogs/ConfirmDialog.tsx +3 -3
- package/src/core/components/dialogs/PromptDialog.tsx +3 -3
- package/src/core/components/form/Control.tsx +9 -0
- package/src/core/components/form/ControlArray.tsx +6 -7
- package/src/core/components/form/ControlObject.tsx +3 -3
- package/src/core/components/form/ControlQueryBuilder.tsx +20 -22
- package/src/core/components/form/ControlSelect.tsx +4 -0
- package/src/core/components/form/TypeForm.tsx +7 -0
- package/src/core/components/layout/Breadcrumb.tsx +6 -6
- package/src/core/components/layout/Omnibar.tsx +2 -1
- package/src/core/components/layout/Sidebar.tsx +5 -1
- package/src/core/components/table/ColumnPicker.tsx +47 -31
- package/src/core/components/table/DataTable.tsx +277 -201
- package/src/core/components/table/DataTableFilters.tsx +8 -0
- package/src/core/components/table/DataTableToolbar.tsx +98 -5
- package/src/core/components/table/FilterPicker.tsx +28 -26
- package/src/core/components/table/types.ts +52 -37
- package/src/core/components/table/useTableSelection.ts +83 -0
- package/src/core/styles.css +1 -0
- package/src/core/utils/parseInput.ts +1 -0
- package/src/demo/components/DemoHome.tsx +5 -5
- package/src/demo/components/core/DemoDataTable.tsx +209 -5
- package/src/demo/components/json/DemoJsonViewer.tsx +1 -1
- package/src/demo/components/shared/MacWindow.tsx +7 -7
- package/src/demo/components/shared/Showcase.tsx +3 -3
- package/src/demo/index.ts +0 -11
- package/src/json/components/JsonViewer.tsx +3 -3
- package/dist/admin/AdminApiKeys-CoTOTfgU.js.map +0 -1
- package/dist/admin/AdminAudits-BmsxFbDa.js.map +0 -1
- package/dist/admin/AdminJobs-C604joTz.js +0 -698
- package/dist/admin/AdminJobs-C604joTz.js.map +0 -1
- package/dist/admin/AdminParameters-B_83Vie9.js.map +0 -1
- package/dist/admin/AdminSessions-CWnPosdd.js.map +0 -1
- package/dist/admin/AdminUserAudits-nHv636E_.js.map +0 -1
- package/dist/admin/AdminUserCreate-CjYD3Kjc.js.map +0 -1
- package/dist/admin/AdminUserDetails-Ccq-LsZ0.js.map +0 -1
- package/dist/admin/AdminUserLayout-7s41DiF_.js.map +0 -1
- package/dist/admin/AdminUserSessions-Ds3ODq_d.js.map +0 -1
- package/dist/admin/AdminUserSettings-CGh4gROo.js.map +0 -1
- package/dist/admin/AdminUsers-CvPiBzQK.js.map +0 -1
- package/dist/admin/rolldown-runtime-CjeV3_4I.js +0 -18
- package/dist/auth/Login-DS_OqA0G.js.map +0 -1
- package/dist/auth/Profile-Di7N7HZL.js.map +0 -1
- package/dist/auth/Register-BRR2_gux.js.map +0 -1
- package/dist/auth/ResetPassword-oQu72lod.js.map +0 -1
- package/dist/auth/VerifyEmail-DC6HPZjd.js.map +0 -1
- package/dist/demo/DemoDataTable-DCsJq8v5.js +0 -149
- package/dist/demo/DemoDataTable-DCsJq8v5.js.map +0 -1
- package/dist/demo/DemoHome-DpRrPlBC.js.map +0 -1
- package/dist/demo/DemoJsonViewer-zeucGKHV.js.map +0 -1
- package/dist/demo/DemoLogin-DSzP0Lkv.js.map +0 -1
- package/dist/demo/DemoRegister-DavFBsCz.js.map +0 -1
- package/dist/demo/DemoResetPassword-BS2rIAQK.js.map +0 -1
- package/dist/demo/DemoVerifyEmail-Bi4SdWz0.js.map +0 -1
- package/dist/demo/Showcase-C9btr_SJ.js.map +0 -1
- package/dist/demo/rolldown-runtime-CjeV3_4I.js +0 -18
- package/src/admin/components/jobs/AdminJobs.tsx +0 -772
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { t as __exportAll } from "./rolldown-runtime-CjeV3_4I.js";
|
|
2
1
|
import { ActionButton, Flex, Text, TypeForm, useToast } from "@alepha/ui";
|
|
3
2
|
import { jsonSchemaToTypeBox, t } from "alepha";
|
|
4
3
|
import { IconArrowLeft, IconChevronDown, IconChevronRight, IconClock, IconFolder, IconFolderOpen, IconHistory, IconRefresh, IconSearch, IconSettings } from "@tabler/icons-react";
|
|
5
|
-
import { Badge,
|
|
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
6
|
import { useClient } from "alepha/react";
|
|
7
7
|
import { useI18n } from "alepha/react/i18n";
|
|
8
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
9
8
|
import { memo, useCallback, useEffect, useMemo, useState } from "react";
|
|
10
9
|
import { useForm } from "alepha/react/form";
|
|
11
10
|
|
|
@@ -32,7 +31,7 @@ const formatJson = (obj) => {
|
|
|
32
31
|
/**
|
|
33
32
|
* Loading state.
|
|
34
33
|
*/
|
|
35
|
-
const LoadingState = () => /* @__PURE__ */ jsx(
|
|
34
|
+
const LoadingState = () => /* @__PURE__ */ jsx(Flex, {
|
|
36
35
|
flex: 1,
|
|
37
36
|
h: "100%",
|
|
38
37
|
p: "md",
|
|
@@ -92,7 +91,7 @@ const ConfigForm = ({ selectedConfig, configValue, saving, onSave }) => {
|
|
|
92
91
|
if (fieldCount <= 6) return 2;
|
|
93
92
|
return 3;
|
|
94
93
|
}, [fieldCount]);
|
|
95
|
-
return /* @__PURE__ */ jsx(
|
|
94
|
+
return /* @__PURE__ */ jsx(Flex, {
|
|
96
95
|
flex: 1,
|
|
97
96
|
h: "100%",
|
|
98
97
|
style: {
|
|
@@ -105,20 +104,21 @@ const ConfigForm = ({ selectedConfig, configValue, saving, onSave }) => {
|
|
|
105
104
|
h: "100%",
|
|
106
105
|
w: "100%",
|
|
107
106
|
style: { minHeight: 0 },
|
|
108
|
-
children: [/* @__PURE__ */ jsx(
|
|
107
|
+
children: [/* @__PURE__ */ jsx(Flex, {
|
|
109
108
|
flex: 1,
|
|
110
109
|
p: "md",
|
|
111
110
|
className: "overflow-auto",
|
|
112
111
|
style: { minHeight: 0 },
|
|
113
|
-
children: currentContent !== null ? /* @__PURE__ */ jsxs(
|
|
112
|
+
children: currentContent !== null ? /* @__PURE__ */ jsxs(Flex, {
|
|
113
|
+
direction: "column",
|
|
114
114
|
gap: "lg",
|
|
115
115
|
children: [
|
|
116
|
-
/* @__PURE__ */ jsx(
|
|
116
|
+
/* @__PURE__ */ jsx(Flex, { children: hasValidSchema ? /* @__PURE__ */ jsx(TypeForm, {
|
|
117
117
|
form,
|
|
118
118
|
columns,
|
|
119
119
|
skipSubmitButton: true,
|
|
120
120
|
fill: false
|
|
121
|
-
}) : /* @__PURE__ */ jsxs(
|
|
121
|
+
}) : /* @__PURE__ */ jsxs(Flex, { children: [/* @__PURE__ */ jsx(Text, {
|
|
122
122
|
size: "xs",
|
|
123
123
|
c: "dimmed",
|
|
124
124
|
mb: 4,
|
|
@@ -128,7 +128,7 @@ const ConfigForm = ({ selectedConfig, configValue, saving, onSave }) => {
|
|
|
128
128
|
style: { whiteSpace: "pre-wrap" },
|
|
129
129
|
children: formatJson(currentContent)
|
|
130
130
|
})] }) }),
|
|
131
|
-
configValue?.current?.changeDescription && /* @__PURE__ */ jsxs(
|
|
131
|
+
configValue?.current?.changeDescription && /* @__PURE__ */ jsxs(Flex, { children: [/* @__PURE__ */ jsx(Text, {
|
|
132
132
|
size: "xs",
|
|
133
133
|
c: "dimmed",
|
|
134
134
|
mb: 4,
|
|
@@ -137,9 +137,9 @@ const ConfigForm = ({ selectedConfig, configValue, saving, onSave }) => {
|
|
|
137
137
|
size: "sm",
|
|
138
138
|
children: configValue.current.changeDescription
|
|
139
139
|
})] }),
|
|
140
|
-
configValue?.current && /* @__PURE__ */ jsxs(
|
|
140
|
+
configValue?.current && /* @__PURE__ */ jsxs(Flex, {
|
|
141
141
|
gap: "xl",
|
|
142
|
-
children: [/* @__PURE__ */ jsxs(
|
|
142
|
+
children: [/* @__PURE__ */ jsxs(Flex, { children: [/* @__PURE__ */ jsx(Text, {
|
|
143
143
|
size: "xs",
|
|
144
144
|
c: "dimmed",
|
|
145
145
|
mb: 2,
|
|
@@ -147,7 +147,7 @@ const ConfigForm = ({ selectedConfig, configValue, saving, onSave }) => {
|
|
|
147
147
|
}), /* @__PURE__ */ jsx(Text, {
|
|
148
148
|
size: "sm",
|
|
149
149
|
children: l(configValue.current.updatedAt, { date: "fromNow" })
|
|
150
|
-
})] }), configValue.current.creatorName && /* @__PURE__ */ jsxs(
|
|
150
|
+
})] }), configValue.current.creatorName && /* @__PURE__ */ jsxs(Flex, { children: [/* @__PURE__ */ jsx(Text, {
|
|
151
151
|
size: "xs",
|
|
152
152
|
c: "dimmed",
|
|
153
153
|
mb: 2,
|
|
@@ -166,10 +166,11 @@ const ConfigForm = ({ selectedConfig, configValue, saving, onSave }) => {
|
|
|
166
166
|
withBorder: true,
|
|
167
167
|
p: "sm",
|
|
168
168
|
bg: "var(--mantine-color-blue-light)",
|
|
169
|
-
children: /* @__PURE__ */ jsxs(
|
|
169
|
+
children: /* @__PURE__ */ jsxs(Flex, {
|
|
170
|
+
direction: "column",
|
|
170
171
|
gap: "xs",
|
|
171
172
|
children: [
|
|
172
|
-
/* @__PURE__ */ jsxs(
|
|
173
|
+
/* @__PURE__ */ jsxs(Flex, {
|
|
173
174
|
gap: "xs",
|
|
174
175
|
children: [/* @__PURE__ */ jsx(IconClock, {
|
|
175
176
|
size: 14,
|
|
@@ -214,13 +215,13 @@ const ConfigForm = ({ selectedConfig, configValue, saving, onSave }) => {
|
|
|
214
215
|
children: "No current value"
|
|
215
216
|
})
|
|
216
217
|
})
|
|
217
|
-
}), hasValidSchema && currentContent !== null && /* @__PURE__ */ jsx(
|
|
218
|
+
}), hasValidSchema && currentContent !== null && /* @__PURE__ */ jsx(Flex, {
|
|
218
219
|
p: "md",
|
|
219
220
|
style: {
|
|
220
221
|
flexShrink: 0,
|
|
221
222
|
borderTop: "1px solid var(--mantine-color-default-border)"
|
|
222
223
|
},
|
|
223
|
-
children: /* @__PURE__ */ jsxs(
|
|
224
|
+
children: /* @__PURE__ */ jsxs(Flex, {
|
|
224
225
|
justify: "flex-end",
|
|
225
226
|
gap: "sm",
|
|
226
227
|
children: [/* @__PURE__ */ jsx(ActionButton, {
|
|
@@ -265,13 +266,15 @@ const ParameterEmptyState = () => {
|
|
|
265
266
|
flex: 1,
|
|
266
267
|
p: "xl",
|
|
267
268
|
align: "center",
|
|
268
|
-
children: /* @__PURE__ */ jsxs(
|
|
269
|
+
children: /* @__PURE__ */ jsxs(Flex$1, {
|
|
270
|
+
direction: "column",
|
|
269
271
|
align: "center",
|
|
270
272
|
gap: "md",
|
|
271
273
|
children: [/* @__PURE__ */ jsx(IconArrowLeft, {
|
|
272
274
|
size: 32,
|
|
273
275
|
color: "var(--mantine-color-dimmed)"
|
|
274
|
-
}), /* @__PURE__ */ jsxs(
|
|
276
|
+
}), /* @__PURE__ */ jsxs(Flex$1, {
|
|
277
|
+
direction: "column",
|
|
275
278
|
align: "center",
|
|
276
279
|
gap: 4,
|
|
277
280
|
children: [/* @__PURE__ */ jsx(Text, {
|
|
@@ -324,7 +327,7 @@ const ParameterHistory = ({ history, loading, onRollback }) => {
|
|
|
324
327
|
fw: 500,
|
|
325
328
|
children: version.version
|
|
326
329
|
}),
|
|
327
|
-
title: /* @__PURE__ */ jsxs(
|
|
330
|
+
title: /* @__PURE__ */ jsxs(Flex, {
|
|
328
331
|
gap: "xs",
|
|
329
332
|
children: [/* @__PURE__ */ jsxs(Text, {
|
|
330
333
|
size: "xs",
|
|
@@ -337,7 +340,8 @@ const ParameterHistory = ({ history, loading, onRollback }) => {
|
|
|
337
340
|
children: version.status
|
|
338
341
|
})]
|
|
339
342
|
}),
|
|
340
|
-
children: /* @__PURE__ */ jsxs(
|
|
343
|
+
children: /* @__PURE__ */ jsxs(Flex, {
|
|
344
|
+
direction: "column",
|
|
341
345
|
gap: 4,
|
|
342
346
|
mt: 4,
|
|
343
347
|
children: [
|
|
@@ -374,7 +378,7 @@ const ParameterHistory = ({ history, loading, onRollback }) => {
|
|
|
374
378
|
})
|
|
375
379
|
});
|
|
376
380
|
};
|
|
377
|
-
return /* @__PURE__ */ jsx(
|
|
381
|
+
return /* @__PURE__ */ jsx(Flex, {
|
|
378
382
|
w: 160,
|
|
379
383
|
h: "100%",
|
|
380
384
|
p: "xs",
|
|
@@ -385,11 +389,12 @@ const ParameterHistory = ({ history, loading, onRollback }) => {
|
|
|
385
389
|
flexDirection: "column",
|
|
386
390
|
borderLeft: "1px solid var(--mantine-color-default-border)"
|
|
387
391
|
},
|
|
388
|
-
children: /* @__PURE__ */ jsxs(
|
|
392
|
+
children: /* @__PURE__ */ jsxs(Flex, {
|
|
393
|
+
direction: "column",
|
|
389
394
|
gap: "xs",
|
|
390
395
|
h: "100%",
|
|
391
396
|
style: { minHeight: 0 },
|
|
392
|
-
children: [/* @__PURE__ */ jsxs(
|
|
397
|
+
children: [/* @__PURE__ */ jsxs(Flex, {
|
|
393
398
|
gap: "xs",
|
|
394
399
|
children: [/* @__PURE__ */ jsx(IconHistory, {
|
|
395
400
|
size: 16,
|
|
@@ -432,7 +437,7 @@ const TreeNode = memo(({ node, level, selectedConfig, onSelect, expandedNodes, o
|
|
|
432
437
|
const isExpanded = expandedNodes.has(node.path);
|
|
433
438
|
const isSelected = selectedConfig === node.path;
|
|
434
439
|
const isLeaf = !hasChildren;
|
|
435
|
-
return /* @__PURE__ */ jsxs(
|
|
440
|
+
return /* @__PURE__ */ jsxs(Flex$1, { children: [/* @__PURE__ */ jsx(UnstyledButton, {
|
|
436
441
|
onClick: useCallback(() => {
|
|
437
442
|
if (hasChildren) onToggle(node.path);
|
|
438
443
|
else onSelect(node.path);
|
|
@@ -446,7 +451,7 @@ const TreeNode = memo(({ node, level, selectedConfig, onSelect, expandedNodes, o
|
|
|
446
451
|
onMouseLeave: useCallback(() => setIsHovered(false), []),
|
|
447
452
|
w: "100%",
|
|
448
453
|
style: { display: "block" },
|
|
449
|
-
children: /* @__PURE__ */ jsxs(
|
|
454
|
+
children: /* @__PURE__ */ jsxs(Flex$1, {
|
|
450
455
|
gap: 6,
|
|
451
456
|
wrap: "nowrap",
|
|
452
457
|
p: "4px 8px",
|
|
@@ -455,7 +460,7 @@ const TreeNode = memo(({ node, level, selectedConfig, onSelect, expandedNodes, o
|
|
|
455
460
|
borderRadius: "var(--mantine-radius-sm)",
|
|
456
461
|
backgroundColor: isSelected || isHovered ? "var(--mantine-color-default-hover)" : void 0
|
|
457
462
|
},
|
|
458
|
-
children: [hasChildren ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(
|
|
463
|
+
children: [hasChildren ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Flex$1, {
|
|
459
464
|
style: {
|
|
460
465
|
display: "flex",
|
|
461
466
|
alignItems: "center",
|
|
@@ -477,7 +482,7 @@ const TreeNode = memo(({ node, level, selectedConfig, onSelect, expandedNodes, o
|
|
|
477
482
|
size: 16,
|
|
478
483
|
color: "var(--mantine-color-dimmed)",
|
|
479
484
|
style: { flexShrink: 0 }
|
|
480
|
-
})] }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(
|
|
485
|
+
})] }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Flex$1, { w: 16 }), /* @__PURE__ */ jsx(IconSettings, {
|
|
481
486
|
size: 16,
|
|
482
487
|
color: isSelected ? "var(--mantine-color-blue-6)" : "var(--mantine-color-dimmed)",
|
|
483
488
|
style: { flexShrink: 0 }
|
|
@@ -535,7 +540,7 @@ const ParameterTree = ({ treeData, selectedConfig, onSelect, onRefresh }) => {
|
|
|
535
540
|
const handleSearchChange = useCallback((e) => {
|
|
536
541
|
setSearchQuery(e.currentTarget.value);
|
|
537
542
|
}, []);
|
|
538
|
-
return /* @__PURE__ */ jsx(
|
|
543
|
+
return /* @__PURE__ */ jsx(Flex$1, {
|
|
539
544
|
w: 280,
|
|
540
545
|
h: "100%",
|
|
541
546
|
p: "sm",
|
|
@@ -545,12 +550,13 @@ const ParameterTree = ({ treeData, selectedConfig, onSelect, onRefresh }) => {
|
|
|
545
550
|
flexDirection: "column",
|
|
546
551
|
borderRight: "1px solid var(--mantine-color-default-border)"
|
|
547
552
|
},
|
|
548
|
-
children: /* @__PURE__ */ jsxs(
|
|
553
|
+
children: /* @__PURE__ */ jsxs(Flex$1, {
|
|
554
|
+
direction: "column",
|
|
549
555
|
gap: "sm",
|
|
550
556
|
h: "100%",
|
|
551
557
|
style: { minHeight: 0 },
|
|
552
558
|
children: [
|
|
553
|
-
/* @__PURE__ */ jsxs(
|
|
559
|
+
/* @__PURE__ */ jsxs(Flex$1, {
|
|
554
560
|
justify: "space-between",
|
|
555
561
|
gap: "xs",
|
|
556
562
|
children: [/* @__PURE__ */ jsx(Text, {
|
|
@@ -582,7 +588,8 @@ const ParameterTree = ({ treeData, selectedConfig, onSelect, onRefresh }) => {
|
|
|
582
588
|
ta: "center",
|
|
583
589
|
py: "md",
|
|
584
590
|
children: searchQuery ? "No matching parameters" : "No parameters"
|
|
585
|
-
}) : /* @__PURE__ */ jsx(
|
|
591
|
+
}) : /* @__PURE__ */ jsx(Flex$1, {
|
|
592
|
+
direction: "column",
|
|
586
593
|
gap: 0,
|
|
587
594
|
style: { gap: 1 },
|
|
588
595
|
children: filteredTreeData.map((node) => /* @__PURE__ */ jsx(TreeNode, {
|
|
@@ -602,7 +609,6 @@ const ParameterTree = ({ treeData, selectedConfig, onSelect, onRefresh }) => {
|
|
|
602
609
|
|
|
603
610
|
//#endregion
|
|
604
611
|
//#region ../../src/admin/components/parameters/AdminParameters.tsx
|
|
605
|
-
var AdminParameters_exports = /* @__PURE__ */ __exportAll({ default: () => AdminParameters });
|
|
606
612
|
const AdminParameters = ({ treeData: initialTreeData }) => {
|
|
607
613
|
const client = useClient();
|
|
608
614
|
const toast = useToast();
|
|
@@ -710,7 +716,8 @@ const AdminParameters = ({ treeData: initialTreeData }) => {
|
|
|
710
716
|
flex: 1,
|
|
711
717
|
justify: "center",
|
|
712
718
|
align: "center",
|
|
713
|
-
children: /* @__PURE__ */ jsxs(
|
|
719
|
+
children: /* @__PURE__ */ jsxs(Flex$1, {
|
|
720
|
+
direction: "column",
|
|
714
721
|
align: "center",
|
|
715
722
|
gap: "xs",
|
|
716
723
|
children: [
|
|
@@ -763,5 +770,5 @@ const AdminParameters = ({ treeData: initialTreeData }) => {
|
|
|
763
770
|
};
|
|
764
771
|
|
|
765
772
|
//#endregion
|
|
766
|
-
export {
|
|
767
|
-
//# sourceMappingURL=AdminParameters-
|
|
773
|
+
export { AdminParameters as default };
|
|
774
|
+
//# sourceMappingURL=AdminParameters-iQE8o7a7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AdminParameters-iQE8o7a7.js","names":["Flex","Flex","Flex"],"sources":["../../src/admin/components/parameters/types.ts","../../src/admin/components/parameters/ParameterDetails.tsx","../../src/admin/components/parameters/ParameterEmptyState.tsx","../../src/admin/components/parameters/ParameterHistory.tsx","../../src/admin/components/parameters/ParameterTree.tsx","../../src/admin/components/parameters/AdminParameters.tsx"],"sourcesContent":["import type { Parameter } from \"alepha/api/parameters\";\n\nexport interface ParameterValue {\n current?: Parameter;\n next?: Parameter;\n /**\n * Default value from the registered $parameter primitive.\n */\n defaultValue?: unknown;\n /**\n * Current in-memory value (may be default if never saved).\n */\n currentValue?: unknown;\n /**\n * TypeBox/JSON schema for the parameter (as JSON from API).\n */\n schema?: Record<string, unknown>;\n}\n\nexport const getStatusColor = (status: string) => {\n switch (status) {\n case \"current\":\n return \"green\";\n case \"next\":\n return \"blue\";\n case \"future\":\n return \"cyan\";\n case \"expired\":\n return \"gray\";\n default:\n return \"gray\";\n }\n};\n\nexport const formatJson = (obj: unknown): string => {\n try {\n return JSON.stringify(obj, null, 2);\n } catch {\n return String(obj);\n }\n};\n","import { ActionButton, Flex, Text, TypeForm } from \"@alepha/ui\";\nimport { Card, Code, Loader } from \"@mantine/core\";\nimport { IconClock } from \"@tabler/icons-react\";\nimport { jsonSchemaToTypeBox, type TObject, t } from \"alepha\";\nimport { useForm } from \"alepha/react/form\";\nimport { useI18n } from \"alepha/react/i18n\";\nimport { useMemo } from \"react\";\nimport { formatJson, type ParameterValue } from \"./types.ts\";\n\nexport interface ParameterDetailsProps {\n selectedConfig: string | null;\n configValue: ParameterValue | null;\n loading: boolean;\n saving: boolean;\n onSave: (values: Record<string, unknown>) => Promise<void>;\n}\n\n/**\n * Loading state.\n */\nconst LoadingState = () => (\n <Flex\n flex={1}\n h=\"100%\"\n p=\"md\"\n style={{\n overflow: \"hidden\",\n minWidth: 0,\n display: \"flex\",\n }}\n >\n <Flex flex={1} justify=\"center\" align=\"center\" h=\"100%\">\n <Loader size=\"sm\" />\n </Flex>\n </Flex>\n);\n\ninterface ConfigFormProps {\n selectedConfig: string;\n configValue: ParameterValue | null;\n saving: boolean;\n onSave: (values: Record<string, unknown>) => Promise<void>;\n}\n\n/**\n * The actual form component - only rendered when a config is selected.\n */\nconst ConfigForm = ({\n selectedConfig,\n configValue,\n saving,\n onSave,\n}: ConfigFormProps) => {\n const { l } = useI18n();\n\n // Get the current value to display (from saved version or default)\n const currentContent = useMemo(() => {\n if (configValue?.current?.content) {\n return configValue.current.content;\n }\n if (configValue?.currentValue !== undefined) {\n return configValue.currentValue;\n }\n return null;\n }, [configValue]);\n\n // Convert JSON Schema from API to TypeBox schema\n const schemaForForm = useMemo(() => {\n if (!configValue?.schema) {\n return t.object({});\n }\n try {\n return jsonSchemaToTypeBox(configValue.schema) as TObject;\n } catch {\n return t.object({});\n }\n }, [configValue?.schema]);\n\n const form = useForm(\n {\n schema: schemaForForm,\n initialValues: (currentContent ?? {}) as Record<string, unknown>,\n handler: async (values) => {\n await onSave(values as Record<string, unknown>);\n },\n },\n [selectedConfig, schemaForForm, currentContent],\n );\n\n // Check if we have a valid schema with properties\n const hasValidSchema = useMemo(() => {\n const schema = configValue?.schema;\n return (\n schema &&\n typeof schema === \"object\" &&\n \"properties\" in schema &&\n Object.keys(schema.properties as object).length > 0\n );\n }, [configValue?.schema]);\n\n // Count the number of fields to determine column layout\n const fieldCount = useMemo(() => {\n const schema = configValue?.schema;\n if (\n schema &&\n typeof schema === \"object\" &&\n \"properties\" in schema &&\n schema.properties\n ) {\n return Object.keys(schema.properties as object).length;\n }\n return 0;\n }, [configValue?.schema]);\n\n // Determine optimal column count based on field count\n const columns = useMemo(() => {\n if (fieldCount <= 2) return 1;\n if (fieldCount <= 6) return 2;\n return 3;\n }, [fieldCount]);\n\n return (\n <Flex\n flex={1}\n h=\"100%\"\n style={{\n overflow: \"hidden\",\n minWidth: 0,\n display: \"flex\",\n }}\n >\n <Flex direction=\"column\" h=\"100%\" w=\"100%\" style={{ minHeight: 0 }}>\n {/* Content */}\n <Flex\n flex={1}\n p=\"md\"\n className=\"overflow-auto\"\n style={{ minHeight: 0 }}\n >\n {currentContent !== null ? (\n <Flex direction=\"column\" gap=\"lg\">\n {/* Form or JSON view */}\n <Flex>\n {hasValidSchema ? (\n <TypeForm\n form={form}\n columns={columns}\n skipSubmitButton\n fill={false}\n />\n ) : (\n <Flex>\n <Text size=\"xs\" c=\"dimmed\" mb={4}>\n Current Value\n </Text>\n <Code block style={{ whiteSpace: \"pre-wrap\" }}>\n {formatJson(currentContent)}\n </Code>\n </Flex>\n )}\n </Flex>\n\n {/* Metadata */}\n {configValue?.current?.changeDescription && (\n <Flex>\n <Text size=\"xs\" c=\"dimmed\" mb={4}>\n Change Description\n </Text>\n <Text size=\"sm\">{configValue.current.changeDescription}</Text>\n </Flex>\n )}\n\n {configValue?.current && (\n <Flex gap=\"xl\">\n <Flex>\n <Text size=\"xs\" c=\"dimmed\" mb={2}>\n Updated\n </Text>\n <Text size=\"sm\">\n {l(configValue.current.updatedAt, { date: \"fromNow\" })}\n </Text>\n </Flex>\n {configValue.current.creatorName && (\n <Flex>\n <Text size=\"xs\" c=\"dimmed\" mb={2}>\n Updated By\n </Text>\n <Text size=\"sm\">{configValue.current.creatorName}</Text>\n </Flex>\n )}\n </Flex>\n )}\n\n {!configValue?.current &&\n configValue?.currentValue !== undefined && (\n <Text size=\"xs\" c=\"dimmed\">\n This configuration is using its default value. No versions\n have been saved to the database yet.\n </Text>\n )}\n\n {/* Scheduled update preview */}\n {configValue?.next && (\n <Card withBorder p=\"sm\" bg=\"var(--mantine-color-blue-light)\">\n <Flex direction=\"column\" gap=\"xs\">\n <Flex gap=\"xs\">\n <IconClock\n size={14}\n color=\"var(--mantine-color-blue-6)\"\n />\n <Text size=\"xs\" fw={500} c=\"blue\">\n Scheduled Update (v{configValue.next.version})\n </Text>\n </Flex>\n <Text size=\"xs\" c=\"dimmed\">\n Activates{\" \"}\n {l(configValue.next.activationDate, {\n date: \"fromNow\",\n })}\n </Text>\n <Code block style={{ whiteSpace: \"pre-wrap\" }} fz=\"xs\">\n {formatJson(configValue.next.content)}\n </Code>\n </Flex>\n </Card>\n )}\n </Flex>\n ) : (\n <Flex justify=\"center\" align=\"center\" h={200}>\n <Text c=\"dimmed\" size=\"sm\">\n No current value\n </Text>\n </Flex>\n )}\n </Flex>\n\n {/* Footer with actions */}\n {hasValidSchema && currentContent !== null && (\n <Flex\n p=\"md\"\n style={{\n flexShrink: 0,\n borderTop: \"1px solid var(--mantine-color-default-border)\",\n }}\n >\n <Flex justify=\"flex-end\" gap=\"sm\">\n <ActionButton\n variant=\"subtle\"\n onClick={() => form.reset({} as any)}\n disabled={saving}\n >\n Reset\n </ActionButton>\n <ActionButton intent=\"primary\" form={form} loading={saving}>\n Save Changes\n </ActionButton>\n </Flex>\n </Flex>\n )}\n </Flex>\n </Flex>\n );\n};\n\n/**\n * Parameter details panel.\n * Shows loading state or the config form.\n * Note: Empty state is handled by parent (AdminParameters).\n */\nconst ParameterDetails = ({\n selectedConfig,\n configValue,\n loading,\n saving,\n onSave,\n}: ParameterDetailsProps) => {\n // Loading state\n if (loading) {\n return <LoadingState />;\n }\n\n // Config form (selectedConfig is guaranteed to be non-null by parent)\n return (\n <ConfigForm\n selectedConfig={selectedConfig!}\n configValue={configValue}\n saving={saving}\n onSave={onSave}\n />\n );\n};\n\nexport default ParameterDetails;\n","import { Text } from \"@alepha/ui\";\nimport { Flex } from \"@mantine/core\";\nimport { IconArrowLeft } from \"@tabler/icons-react\";\n\n/**\n * Empty state displayed when no parameter is selected.\n * Invites user to select a parameter from the tree.\n */\nconst ParameterEmptyState = () => {\n return (\n <Flex flex={1} p={\"xl\"} align=\"center\">\n <Flex direction=\"column\" align=\"center\" gap=\"md\">\n <IconArrowLeft size={32} color=\"var(--mantine-color-dimmed)\" />\n <Flex direction=\"column\" align=\"center\" gap={4}>\n <Text fw={500} c=\"dimmed\">\n No Parameter Selected\n </Text>\n <Text size=\"xs\" c=\"dimmed\" ta=\"center\" maw={240}>\n Choose a parameter from the tree to view and edit its configuration\n </Text>\n </Flex>\n </Flex>\n </Flex>\n );\n};\n\nexport default ParameterEmptyState;\n","import { ActionButton, Flex, Text } from \"@alepha/ui\";\nimport { Badge, Loader, ScrollArea, Timeline } from \"@mantine/core\";\nimport { IconHistory } from \"@tabler/icons-react\";\nimport type { Parameter } from \"alepha/api/parameters\";\nimport { useI18n } from \"alepha/react/i18n\";\nimport { getStatusColor } from \"./types.ts\";\n\nexport interface ParameterHistoryProps {\n selectedConfig: string | null;\n history: Parameter[];\n loading: boolean;\n onRollback: (version: number) => void;\n}\n\nconst ParameterHistory = ({\n history,\n loading,\n onRollback,\n}: ParameterHistoryProps) => {\n const { l } = useI18n();\n\n const renderContent = () => {\n if (loading) {\n return (\n <Flex flex={1} justify=\"center\" align=\"center\">\n <Loader size=\"sm\" />\n </Flex>\n );\n }\n\n if (history.length === 0) {\n return (\n <Flex flex={1} justify=\"center\" align=\"center\">\n <Text c=\"dimmed\" size=\"xs\">\n Empty\n </Text>\n </Flex>\n );\n }\n\n return (\n <ScrollArea flex={1} offsetScrollbars>\n <Timeline\n active={history.findIndex((h) => h.status === \"current\")}\n bulletSize={24}\n lineWidth={2}\n >\n {history.map((version) => (\n <Timeline.Item\n key={version.id}\n bullet={\n <Text size=\"xs\" fw={500}>\n {version.version}\n </Text>\n }\n title={\n <Flex gap=\"xs\">\n <Text size=\"xs\" fw={500}>\n Version {version.version}\n </Text>\n <Badge\n size=\"xs\"\n variant=\"light\"\n color={getStatusColor(version.status)}\n >\n {version.status}\n </Badge>\n </Flex>\n }\n >\n <Flex direction=\"column\" gap={4} mt={4}>\n <Text size=\"xs\" c=\"dimmed\">\n {l(version.createdAt, { date: \"fromNow\" })}\n </Text>\n {version.changeDescription && (\n <Text size=\"xs\" lineClamp={2}>\n {version.changeDescription}\n </Text>\n )}\n {version.creatorName && (\n <Text size=\"xs\" c=\"dimmed\">\n by {version.creatorName}\n </Text>\n )}\n {version.migrationLog && (\n <Badge size=\"xs\" variant=\"outline\" color=\"orange\">\n Schema Changed\n </Badge>\n )}\n {version.status === \"expired\" && (\n <ActionButton\n size=\"compact-xs\"\n variant=\"subtle\"\n onClick={() => onRollback(version.version)}\n >\n Rollback to this version\n </ActionButton>\n )}\n </Flex>\n </Timeline.Item>\n ))}\n </Timeline>\n </ScrollArea>\n );\n };\n\n return (\n <Flex\n w={160}\n h=\"100%\"\n p=\"xs\"\n style={{\n flexShrink: 0,\n overflow: \"hidden\",\n display: \"flex\",\n flexDirection: \"column\",\n borderLeft: \"1px solid var(--mantine-color-default-border)\",\n }}\n >\n <Flex direction=\"column\" gap=\"xs\" h=\"100%\" style={{ minHeight: 0 }}>\n <Flex gap=\"xs\">\n <IconHistory size={16} color=\"var(--mantine-color-dimmed)\" />\n <Text size=\"sm\" fw={500}>\n History\n </Text>\n </Flex>\n {renderContent()}\n </Flex>\n </Flex>\n );\n};\n\nexport default ParameterHistory;\n","import { ActionButton, Text } from \"@alepha/ui\";\nimport {\n Collapse,\n Flex,\n ScrollArea,\n TextInput,\n UnstyledButton,\n} from \"@mantine/core\";\nimport {\n IconChevronDown,\n IconChevronRight,\n IconFolder,\n IconFolderOpen,\n IconRefresh,\n IconSearch,\n IconSettings,\n} from \"@tabler/icons-react\";\nimport type { ParameterTreeNode } from \"alepha/api/parameters\";\nimport { memo, useCallback, useMemo, useState } from \"react\";\n\nexport interface ParameterTreeProps {\n treeData: ParameterTreeNode[];\n selectedConfig: string | null;\n onSelect: (name: string) => void;\n onRefresh: () => void;\n}\n\n/**\n * Filters tree nodes by search query.\n */\nconst filterTree = (\n nodes: ParameterTreeNode[],\n query: string,\n): ParameterTreeNode[] => {\n if (!query.trim()) return nodes;\n\n const lowerQuery = query.toLowerCase();\n\n return nodes\n .map((node) => {\n const filteredChildren = filterTree(node.children, query);\n const nameMatches = node.name.toLowerCase().includes(lowerQuery);\n const pathMatches = node.path.toLowerCase().includes(lowerQuery);\n\n if (nameMatches || pathMatches || filteredChildren.length > 0) {\n return {\n ...node,\n children: filteredChildren,\n };\n }\n\n return null;\n })\n .filter((node): node is ParameterTreeNode => node !== null);\n};\n\ninterface TreeNodeProps {\n node: ParameterTreeNode;\n level: number;\n selectedConfig: string | null;\n onSelect: (name: string) => void;\n expandedNodes: Set<string>;\n onToggle: (path: string) => void;\n}\n\n/**\n * Memoized tree node to prevent unnecessary re-renders.\n */\nconst TreeNode = memo(\n ({\n node,\n level,\n selectedConfig,\n onSelect,\n expandedNodes,\n onToggle,\n }: TreeNodeProps) => {\n const [isHovered, setIsHovered] = useState(false);\n const hasChildren = node.children.length > 0;\n const isExpanded = expandedNodes.has(node.path);\n const isSelected = selectedConfig === node.path;\n const isLeaf = !hasChildren;\n\n const handleClick = useCallback(() => {\n if (hasChildren) {\n onToggle(node.path);\n } else {\n onSelect(node.path);\n }\n }, [hasChildren, node.path, onToggle, onSelect]);\n\n const handleMouseEnter = useCallback(() => setIsHovered(true), []);\n const handleMouseLeave = useCallback(() => setIsHovered(false), []);\n\n return (\n <Flex>\n <UnstyledButton\n onClick={handleClick}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n w=\"100%\"\n style={{ display: \"block\" }}\n >\n <Flex\n gap={6}\n wrap=\"nowrap\"\n p=\"4px 8px\"\n pl={8 + level * 16}\n style={{\n borderRadius: \"var(--mantine-radius-sm)\",\n backgroundColor:\n isSelected || isHovered\n ? \"var(--mantine-color-default-hover)\"\n : undefined,\n }}\n >\n {hasChildren ? (\n <>\n <Flex\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: 16,\n }}\n >\n {isExpanded ? (\n <IconChevronDown\n size={14}\n color=\"var(--mantine-color-dimmed)\"\n />\n ) : (\n <IconChevronRight\n size={14}\n color=\"var(--mantine-color-dimmed)\"\n />\n )}\n </Flex>\n {isExpanded ? (\n <IconFolderOpen\n size={16}\n color=\"var(--mantine-color-dimmed)\"\n style={{ flexShrink: 0 }}\n />\n ) : (\n <IconFolder\n size={16}\n color=\"var(--mantine-color-dimmed)\"\n style={{ flexShrink: 0 }}\n />\n )}\n </>\n ) : (\n <>\n <Flex w={16} />\n <IconSettings\n size={16}\n color={\n isSelected\n ? \"var(--mantine-color-blue-6)\"\n : \"var(--mantine-color-dimmed)\"\n }\n style={{ flexShrink: 0 }}\n />\n </>\n )}\n <Text\n size=\"sm\"\n fw={isSelected ? 600 : 400}\n c={isSelected ? undefined : isLeaf ? undefined : \"dimmed\"}\n style={{\n whiteSpace: \"nowrap\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n }}\n >\n {node.name}\n </Text>\n </Flex>\n </UnstyledButton>\n\n {hasChildren && (\n <Collapse in={isExpanded}>\n {node.children.map((child: ParameterTreeNode) => (\n <TreeNode\n key={child.path}\n node={child}\n level={level + 1}\n selectedConfig={selectedConfig}\n onSelect={onSelect}\n expandedNodes={expandedNodes}\n onToggle={onToggle}\n />\n ))}\n </Collapse>\n )}\n </Flex>\n );\n },\n);\n\nTreeNode.displayName = \"TreeNode\";\n\n/**\n * Collects all folder paths to expand by default.\n */\nconst collectAllFolderPaths = (nodes: ParameterTreeNode[]): Set<string> => {\n const paths = new Set<string>();\n\n const traverse = (nodeList: ParameterTreeNode[]) => {\n for (const node of nodeList) {\n if (node.children.length > 0) {\n paths.add(node.path);\n traverse(node.children);\n }\n }\n };\n\n traverse(nodes);\n return paths;\n};\n\nconst ParameterTree = ({\n treeData,\n selectedConfig,\n onSelect,\n onRefresh,\n}: ParameterTreeProps) => {\n const [searchQuery, setSearchQuery] = useState(\"\");\n const [expandedNodes, setExpandedNodes] = useState<Set<string>>(() =>\n collectAllFolderPaths(treeData),\n );\n\n // Filter tree by search query\n const filteredTreeData = useMemo(\n () => filterTree(treeData, searchQuery),\n [treeData, searchQuery],\n );\n\n const handleToggle = useCallback((path: string) => {\n setExpandedNodes((prev) => {\n const next = new Set(prev);\n if (next.has(path)) {\n next.delete(path);\n } else {\n next.add(path);\n }\n return next;\n });\n }, []);\n\n const handleSearchChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n setSearchQuery(e.currentTarget.value);\n },\n [],\n );\n\n return (\n <Flex\n w={280}\n h=\"100%\"\n p=\"sm\"\n style={{\n flexShrink: 0,\n display: \"flex\",\n flexDirection: \"column\",\n borderRight: \"1px solid var(--mantine-color-default-border)\",\n }}\n >\n <Flex direction=\"column\" gap=\"sm\" h=\"100%\" style={{ minHeight: 0 }}>\n <Flex justify=\"space-between\" gap=\"xs\">\n <Text size=\"sm\" fw={600}>\n Parameters\n </Text>\n <ActionButton\n variant=\"subtle\"\n size=\"compact-xs\"\n onClick={onRefresh}\n tooltip=\"Refresh\"\n >\n <IconRefresh size={14} />\n </ActionButton>\n </Flex>\n\n <TextInput\n placeholder=\"Search...\"\n size=\"xs\"\n leftSection={<IconSearch size={14} />}\n value={searchQuery}\n onChange={handleSearchChange}\n />\n\n <ScrollArea flex={1} offsetScrollbars style={{ minHeight: 0 }}>\n {filteredTreeData.length === 0 ? (\n <Text size=\"xs\" c=\"dimmed\" ta=\"center\" py=\"md\">\n {searchQuery ? \"No matching parameters\" : \"No parameters\"}\n </Text>\n ) : (\n <Flex direction=\"column\" gap={0} style={{ gap: 1 }}>\n {filteredTreeData.map((node) => (\n <TreeNode\n key={node.path}\n node={node}\n level={0}\n selectedConfig={selectedConfig}\n onSelect={onSelect}\n expandedNodes={expandedNodes}\n onToggle={handleToggle}\n />\n ))}\n </Flex>\n )}\n </ScrollArea>\n </Flex>\n </Flex>\n );\n};\n\nexport default ParameterTree;\n","import { Text, useToast } from \"@alepha/ui\";\nimport { Card, Flex } from \"@mantine/core\";\nimport { IconSettings } from \"@tabler/icons-react\";\nimport type {\n AdminParameterController,\n Parameter,\n ParameterTreeNode,\n} from \"alepha/api/parameters\";\nimport { useClient } from \"alepha/react\";\nimport { useCallback, useEffect, useState } from \"react\";\nimport ParameterDetails from \"./ParameterDetails.tsx\";\nimport ParameterEmptyState from \"./ParameterEmptyState.tsx\";\nimport ParameterHistory from \"./ParameterHistory.tsx\";\nimport ParameterTree from \"./ParameterTree.tsx\";\nimport type { ParameterValue } from \"./types.ts\";\n\nexport interface AdminParametersProps {\n treeData: ParameterTreeNode[];\n}\n\nconst AdminParameters = ({\n treeData: initialTreeData,\n}: AdminParametersProps) => {\n const client = useClient<AdminParameterController>();\n const toast = useToast();\n\n // State\n const [treeData, setTreeData] =\n useState<ParameterTreeNode[]>(initialTreeData);\n const [selectedConfig, setSelectedConfig] = useState<string | null>(null);\n const [configValue, setConfigValue] = useState<ParameterValue | null>(null);\n const [history, setHistory] = useState<Parameter[]>([]);\n const [loadingConfig, setLoadingConfig] = useState(false);\n const [loadingHistory, setLoadingHistory] = useState(false);\n const [saving, setSaving] = useState(false);\n\n // Refresh tree data\n const handleRefresh = useCallback(async () => {\n try {\n const tree = await client.getParameterTree({});\n setTreeData(tree as ParameterTreeNode[]);\n } catch (error) {\n toast.danger({\n title: \"Failed to refresh parameters\",\n message: error instanceof Error ? error.message : \"Unknown error\",\n });\n }\n }, [client, toast]);\n\n // Load config value and history when selection changes\n const loadConfigDetails = useCallback(\n async (name: string) => {\n setLoadingConfig(true);\n setLoadingHistory(true);\n\n try {\n const [currentResponse, historyResponse] = await Promise.all([\n client.getCurrent({ params: { name } }),\n client.getHistory({ params: { name } }),\n ]);\n setConfigValue(currentResponse);\n setHistory(historyResponse.versions);\n } catch (error) {\n toast.danger({\n title: \"Failed to load configuration\",\n message: error instanceof Error ? error.message : \"Unknown error\",\n });\n setConfigValue(null);\n setHistory([]);\n } finally {\n setLoadingConfig(false);\n setLoadingHistory(false);\n }\n },\n [client, toast],\n );\n\n // Handle save\n const handleSave = useCallback(\n async (values: Record<string, unknown>) => {\n if (!selectedConfig || !configValue) return;\n\n setSaving(true);\n try {\n await client.createVersion({\n params: { name: selectedConfig },\n body: {\n content: values,\n schemaHash: \"\", // Schema hash is computed server-side when empty\n changeDescription: \"Updated via admin UI\",\n },\n });\n\n toast.success({\n title: \"Configuration saved\",\n message: `${selectedConfig} has been updated`,\n });\n\n // Reload details\n await loadConfigDetails(selectedConfig);\n } catch (error) {\n toast.danger({\n title: \"Failed to save configuration\",\n message: error instanceof Error ? error.message : \"Unknown error\",\n });\n throw error;\n } finally {\n setSaving(false);\n }\n },\n [client, selectedConfig, configValue, loadConfigDetails, toast],\n );\n\n // Load details when selection changes\n useEffect(() => {\n if (selectedConfig) {\n loadConfigDetails(selectedConfig);\n } else {\n setConfigValue(null);\n setHistory([]);\n }\n }, [selectedConfig, loadConfigDetails]);\n\n // Handle rollback\n const handleRollback = useCallback(\n async (version: number) => {\n if (!selectedConfig) return;\n\n try {\n await client.rollback({\n params: { name: selectedConfig },\n body: { targetVersion: version },\n });\n\n toast.success({\n title: \"Rollback successful\",\n message: `${selectedConfig} rolled back to version ${version}`,\n });\n\n // Reload details\n await loadConfigDetails(selectedConfig);\n } catch (error) {\n toast.danger({\n title: \"Rollback failed\",\n message: error instanceof Error ? error.message : \"Unknown error\",\n });\n }\n },\n [client, selectedConfig, loadConfigDetails, toast],\n );\n\n // Empty state when no configs exist\n if (treeData.length === 0) {\n return (\n <Flex flex={1} justify=\"center\" align=\"center\">\n <Flex direction=\"column\" align=\"center\" gap=\"xs\">\n <IconSettings\n size={48}\n stroke={1.5}\n color=\"var(--mantine-color-dimmed)\"\n />\n <Text c=\"dimmed\">No Parameters Found</Text>\n <Text size=\"xs\" c=\"dimmed\" ta=\"center\" maw={400}>\n Define parameters using the $parameter primitive to manage dynamic\n application settings. Parameters will appear here once created.\n </Text>\n </Flex>\n </Flex>\n );\n }\n\n return (\n <Flex flex={1} p=\"md\">\n <Card\n withBorder\n p={0}\n w={\"100%\"}\n style={{\n flexDirection: \"row\",\n }}\n >\n <ParameterTree\n treeData={treeData}\n selectedConfig={selectedConfig}\n onSelect={setSelectedConfig}\n onRefresh={handleRefresh}\n />\n\n {selectedConfig ? (\n <>\n <ParameterDetails\n selectedConfig={selectedConfig}\n configValue={configValue}\n loading={loadingConfig}\n saving={saving}\n onSave={handleSave}\n />\n\n <ParameterHistory\n selectedConfig={selectedConfig}\n history={history}\n loading={loadingHistory}\n onRollback={handleRollback}\n />\n </>\n ) : (\n <ParameterEmptyState />\n )}\n </Card>\n </Flex>\n );\n};\n\nexport default AdminParameters;\n"],"mappings":"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"}
|
|
@@ -1,17 +1,15 @@
|
|
|
1
|
-
import { t as __exportAll } from "./rolldown-runtime-CjeV3_4I.js";
|
|
2
1
|
import { ActionButton, DataTable, Flex, Text } from "@alepha/ui";
|
|
3
2
|
import { t } from "alepha";
|
|
4
3
|
import { IconDeviceDesktop, IconDeviceMobile, IconDeviceTablet, IconTrash } from "@tabler/icons-react";
|
|
5
4
|
import { useRouter } from "alepha/react/router";
|
|
6
|
-
import { Badge
|
|
5
|
+
import { Badge } from "@mantine/core";
|
|
6
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7
7
|
import { useClient } from "alepha/react";
|
|
8
8
|
import { useI18n } from "alepha/react/i18n";
|
|
9
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
10
9
|
import { useState } from "react";
|
|
11
10
|
import { sessions } from "alepha/api/users";
|
|
12
11
|
|
|
13
12
|
//#region ../../src/admin/components/sessions/AdminSessions.tsx
|
|
14
|
-
var AdminSessions_exports = /* @__PURE__ */ __exportAll({ default: () => AdminSessions });
|
|
15
13
|
const AdminSessions = (props) => {
|
|
16
14
|
const client = useClient();
|
|
17
15
|
const router = useRouter();
|
|
@@ -80,7 +78,7 @@ const AdminSessions = (props) => {
|
|
|
80
78
|
userAgent: {
|
|
81
79
|
label: "Device",
|
|
82
80
|
fit: true,
|
|
83
|
-
value: (item) => /* @__PURE__ */ jsx(
|
|
81
|
+
value: (item) => /* @__PURE__ */ jsx(Flex, {
|
|
84
82
|
gap: 4,
|
|
85
83
|
children: item.userAgent ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Badge, {
|
|
86
84
|
size: "xs",
|
|
@@ -148,5 +146,5 @@ const AdminSessions = (props) => {
|
|
|
148
146
|
};
|
|
149
147
|
|
|
150
148
|
//#endregion
|
|
151
|
-
export {
|
|
152
|
-
//# sourceMappingURL=AdminSessions-
|
|
149
|
+
export { AdminSessions as default };
|
|
150
|
+
//# sourceMappingURL=AdminSessions-oKJCbd7w.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AdminSessions-oKJCbd7w.js","names":[],"sources":["../../src/admin/components/sessions/AdminSessions.tsx"],"sourcesContent":["import { ActionButton, DataTable, Flex, Text } from \"@alepha/ui\";\nimport { Badge } from \"@mantine/core\";\nimport {\n IconDeviceDesktop,\n IconDeviceMobile,\n IconDeviceTablet,\n IconTrash,\n} from \"@tabler/icons-react\";\nimport { type Page, t } from \"alepha\";\nimport {\n type AdminSessionController,\n type SessionEntity,\n sessions,\n} from \"alepha/api/users\";\nimport { useClient } from \"alepha/react\";\nimport { useI18n } from \"alepha/react/i18n\";\nimport { useRouter } from \"alepha/react/router\";\nimport { useState } from \"react\";\nimport type { AdminRouter } from \"../../AdminRouter.ts\";\n\nexport interface AdminSessionsProps {\n userRealmName?: string;\n}\n\nconst AdminSessions = (props: AdminSessionsProps) => {\n const client = useClient<AdminSessionController>();\n const router = useRouter<AdminRouter>();\n const { l } = useI18n();\n const [refreshKey, setRefreshKey] = useState(0);\n\n const filters = t.object({\n userId: t.optional(\n t.uuid({\n $control: {\n query: t.pick(sessions.schema, [\"userId\"]),\n },\n }),\n ),\n });\n\n const getDeviceIcon = (device?: string) => {\n switch (device) {\n case \"MOBILE\":\n return <IconDeviceMobile size={14} />;\n case \"TABLET\":\n return <IconDeviceTablet size={14} />;\n default:\n return <IconDeviceDesktop size={14} />;\n }\n };\n\n const isExpired = (expiresAt: Date | string) => {\n return new Date(expiresAt) < new Date();\n };\n\n const handleDelete = async (sessionId: string) => {\n await client.deleteSession({\n params: { id: sessionId },\n query: { userRealmName: props.userRealmName },\n });\n setRefreshKey((k) => k + 1);\n };\n\n return (\n <Flex flex={1} direction=\"column\">\n <DataTable<SessionEntity, typeof filters>\n key={refreshKey}\n submitOnInit\n defaultSize={10}\n typeFormProps={{\n skipSubmitButton: true,\n columns: 3,\n }}\n tableProps={{\n horizontalSpacing: \"xs\",\n verticalSpacing: \"xs\",\n }}\n onFilterChange={(key, _value, form) => {\n if (key === \"userId\") {\n return form.submit();\n }\n }}\n filters={filters}\n tableTrProps={(item) => {\n if (isExpired(item.expiresAt)) {\n return {\n opacity: 0.5,\n };\n }\n return {};\n }}\n items={async (filters) => {\n const response = await client.findSessions({\n query: {\n ...filters,\n userRealmName: props.userRealmName,\n },\n });\n\n return response as Page<SessionEntity>;\n }}\n columns={{\n userId: {\n label: \"User\",\n value: (item) => (\n <ActionButton\n variant=\"subtle\"\n size=\"xs\"\n href={router.path(\"adminUserDetails\", {\n params: { userId: item.userId },\n })}\n >\n <Text size=\"xs\" ff=\"monospace\">\n {item.userId.slice(0, 8)}...\n </Text>\n </ActionButton>\n ),\n },\n userAgent: {\n label: \"Device\",\n fit: true,\n value: (item) => (\n <Flex gap={4}>\n {item.userAgent ? (\n <>\n <Badge\n size=\"xs\"\n variant=\"light\"\n leftSection={getDeviceIcon(item.userAgent.device)}\n >\n {item.userAgent.device}\n </Badge>\n <Text size=\"xs\" c=\"dimmed\">\n {item.userAgent.browser} / {item.userAgent.os}\n </Text>\n </>\n ) : (\n <Text size=\"xs\" c=\"dimmed\">\n -\n </Text>\n )}\n </Flex>\n ),\n },\n ip: {\n label: \"IP\",\n fit: true,\n value: (item) => (\n <Text size=\"xs\" ff=\"monospace\" c=\"dimmed\">\n {item.ip || \"-\"}\n </Text>\n ),\n },\n expiresAt: {\n label: \"Status\",\n fit: true,\n value: (item) => (\n <Badge\n size=\"sm\"\n variant=\"light\"\n color={isExpired(item.expiresAt) ? \"red\" : \"green\"}\n >\n {isExpired(item.expiresAt) ? \"Expired\" : \"Active\"}\n </Badge>\n ),\n },\n createdAt: {\n label: \"Created\",\n fit: true,\n value: (item) => (\n <Text size=\"xs\" c=\"dimmed\">\n {l(item.createdAt, { date: \"fromNow\" })}\n </Text>\n ),\n },\n actions: {\n label: \"\",\n fit: true,\n value: (item) => (\n <ActionButton\n size=\"xs\"\n variant=\"subtle\"\n color=\"red\"\n onClick={() => handleDelete(item.id)}\n >\n <IconTrash size={14} />\n </ActionButton>\n ),\n },\n }}\n />\n </Flex>\n );\n};\n\nexport default AdminSessions;\n"],"mappings":"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"}
|
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
import { t as __exportAll } from "./rolldown-runtime-CjeV3_4I.js";
|
|
2
1
|
import { DataTable, Flex, Text } from "@alepha/ui";
|
|
3
2
|
import { t } from "alepha";
|
|
4
3
|
import { IconAlertTriangle, IconCheck, IconInfoCircle, IconX } from "@tabler/icons-react";
|
|
5
4
|
import { useRouterState } from "alepha/react/router";
|
|
6
|
-
import { Badge,
|
|
5
|
+
import { Badge, Tooltip } from "@mantine/core";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
7
|
import { useClient } from "alepha/react";
|
|
8
8
|
import { useI18n } from "alepha/react/i18n";
|
|
9
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
9
|
|
|
11
10
|
//#region ../../src/admin/components/users/AdminUserAudits.tsx
|
|
12
|
-
var AdminUserAudits_exports = /* @__PURE__ */ __exportAll({ default: () => AdminUserAudits });
|
|
13
11
|
const getSeverityColor = (severity) => {
|
|
14
12
|
switch (severity) {
|
|
15
13
|
case "critical": return "red";
|
|
@@ -122,7 +120,7 @@ const AdminUserAudits = (_props) => {
|
|
|
122
120
|
success: {
|
|
123
121
|
label: "Status",
|
|
124
122
|
fit: true,
|
|
125
|
-
value: (item) => item.success ? /* @__PURE__ */ jsxs(
|
|
123
|
+
value: (item) => item.success ? /* @__PURE__ */ jsxs(Flex, {
|
|
126
124
|
gap: 4,
|
|
127
125
|
children: [/* @__PURE__ */ jsx(IconCheck, {
|
|
128
126
|
size: 14,
|
|
@@ -134,7 +132,7 @@ const AdminUserAudits = (_props) => {
|
|
|
134
132
|
})]
|
|
135
133
|
}) : /* @__PURE__ */ jsx(Tooltip, {
|
|
136
134
|
label: item.errorMessage || "Failed",
|
|
137
|
-
children: /* @__PURE__ */ jsxs(
|
|
135
|
+
children: /* @__PURE__ */ jsxs(Flex, {
|
|
138
136
|
gap: 4,
|
|
139
137
|
children: [/* @__PURE__ */ jsx(IconX, {
|
|
140
138
|
size: 14,
|
|
@@ -175,5 +173,5 @@ const AdminUserAudits = (_props) => {
|
|
|
175
173
|
};
|
|
176
174
|
|
|
177
175
|
//#endregion
|
|
178
|
-
export {
|
|
179
|
-
//# sourceMappingURL=AdminUserAudits-
|
|
176
|
+
export { AdminUserAudits as default };
|
|
177
|
+
//# sourceMappingURL=AdminUserAudits-BNCEle_E.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AdminUserAudits-BNCEle_E.js","names":[],"sources":["../../src/admin/components/users/AdminUserAudits.tsx"],"sourcesContent":["import { DataTable, Flex, Text } from \"@alepha/ui\";\nimport { Badge, Tooltip } from \"@mantine/core\";\nimport {\n IconAlertTriangle,\n IconCheck,\n IconInfoCircle,\n IconX,\n} from \"@tabler/icons-react\";\nimport { type Page, t } from \"alepha\";\nimport type { AdminAuditController, AuditEntity } from \"alepha/api/audits\";\nimport { useClient } from \"alepha/react\";\nimport { useI18n } from \"alepha/react/i18n\";\nimport { useRouterState } from \"alepha/react/router\";\n\nexport interface AdminUserAuditsProps {\n userRealmName?: string;\n}\n\nconst getSeverityColor = (severity: string) => {\n switch (severity) {\n case \"critical\":\n return \"red\";\n case \"warning\":\n return \"yellow\";\n default:\n return \"blue\";\n }\n};\n\nconst getSeverityIcon = (severity: string) => {\n switch (severity) {\n case \"critical\":\n return <IconAlertTriangle size={12} />;\n case \"warning\":\n return <IconAlertTriangle size={12} />;\n default:\n return <IconInfoCircle size={12} />;\n }\n};\n\nconst AdminUserAudits = (_props: AdminUserAuditsProps) => {\n const state = useRouterState();\n const client = useClient<AdminAuditController>();\n const { l } = useI18n();\n const userId = state.params.userId as string;\n\n const filters = t.object({\n type: t.optional(t.text()),\n action: t.optional(t.text()),\n severity: t.optional(t.enum([\"info\", \"warning\", \"critical\"])),\n success: t.optional(t.boolean()),\n from: t.optional(t.datetime()),\n to: t.optional(t.datetime()),\n });\n\n return (\n <Flex flex={1} direction=\"column\">\n <DataTable<AuditEntity, typeof filters>\n submitOnInit\n defaultSize={15}\n typeFormProps={{\n skipSubmitButton: true,\n columns: 4,\n }}\n tableProps={{\n horizontalSpacing: \"xs\",\n verticalSpacing: \"xs\",\n striped: false,\n highlightOnHover: true,\n }}\n filters={filters}\n items={async (query) => {\n const response = await client.findByUser({\n params: { userId },\n query,\n });\n return response as Page<AuditEntity>;\n }}\n columns={{\n type: {\n label: \"Type\",\n fit: true,\n value: (item) => (\n <Badge size=\"sm\" variant=\"light\" color=\"grape\">\n {item.type}\n </Badge>\n ),\n },\n action: {\n label: \"Action\",\n fit: true,\n value: (item) => (\n <Badge size=\"sm\" variant=\"outline\">\n {item.action}\n </Badge>\n ),\n },\n severity: {\n label: \"Severity\",\n fit: true,\n value: (item) => (\n <Badge\n size=\"sm\"\n variant=\"light\"\n color={getSeverityColor(item.severity)}\n leftSection={getSeverityIcon(item.severity)}\n >\n {item.severity}\n </Badge>\n ),\n },\n description: {\n label: \"Description\",\n value: (item) => (\n <Text size=\"sm\" lineClamp={1}>\n {item.description || \"-\"}\n </Text>\n ),\n },\n resource: {\n label: \"Resource\",\n fit: true,\n value: (item) =>\n item.resourceType ? (\n <Tooltip label={item.resourceId || \"N/A\"}>\n <Badge size=\"xs\" variant=\"dot\" color=\"gray\">\n {item.resourceType}\n </Badge>\n </Tooltip>\n ) : (\n <Text size=\"xs\" c=\"dimmed\">\n -\n </Text>\n ),\n },\n success: {\n label: \"Status\",\n fit: true,\n value: (item) =>\n item.success ? (\n <Flex gap={4}>\n <IconCheck size={14} color=\"var(--mantine-color-green-6)\" />\n <Text size=\"xs\" c=\"green\">\n Success\n </Text>\n </Flex>\n ) : (\n <Tooltip label={item.errorMessage || \"Failed\"}>\n <Flex gap={4}>\n <IconX size={14} color=\"var(--mantine-color-red-6)\" />\n <Text size=\"xs\" c=\"red\">\n Failed\n </Text>\n </Flex>\n </Tooltip>\n ),\n },\n ipAddress: {\n label: \"IP\",\n fit: true,\n value: (item) => (\n <Text size=\"xs\" c=\"dimmed\" ff=\"monospace\">\n {item.ipAddress || \"-\"}\n </Text>\n ),\n },\n createdAt: {\n label: \"Time\",\n fit: true,\n value: (item) => (\n <Tooltip label={l(item.createdAt, { date: \"medium\" })}>\n <Text size=\"xs\" c=\"dimmed\">\n {l(item.createdAt, { date: \"fromNow\" })}\n </Text>\n </Tooltip>\n ),\n },\n }}\n />\n </Flex>\n );\n};\n\nexport default AdminUserAudits;\n"],"mappings":"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"}
|
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
import { t as __exportAll } from "./rolldown-runtime-CjeV3_4I.js";
|
|
2
1
|
import { ActionButton, Control, Flex } from "@alepha/ui";
|
|
3
2
|
import { t } from "alepha";
|
|
4
3
|
import { useRouter } from "alepha/react/router";
|
|
5
|
-
import { Card,
|
|
6
|
-
import { useClient } from "alepha/react";
|
|
4
|
+
import { Card, Text as Text$1 } from "@mantine/core";
|
|
7
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import { useClient } from "alepha/react";
|
|
8
7
|
import { useForm } from "alepha/react/form";
|
|
9
8
|
|
|
10
9
|
//#region ../../src/admin/components/users/AdminUserCreate.tsx
|
|
11
|
-
var AdminUserCreate_exports = /* @__PURE__ */ __exportAll({ default: () => AdminUserCreate });
|
|
12
10
|
const AdminUserCreate = (props) => {
|
|
13
11
|
const client = useClient();
|
|
14
12
|
const router = useRouter();
|
|
@@ -48,7 +46,8 @@ const AdminUserCreate = (props) => {
|
|
|
48
46
|
w: "100%",
|
|
49
47
|
children: /* @__PURE__ */ jsx("form", {
|
|
50
48
|
...form.props,
|
|
51
|
-
children: /* @__PURE__ */ jsxs(
|
|
49
|
+
children: /* @__PURE__ */ jsxs(Flex, {
|
|
50
|
+
direction: "column",
|
|
52
51
|
gap: "md",
|
|
53
52
|
children: [
|
|
54
53
|
/* @__PURE__ */ jsx(Text$1, {
|
|
@@ -101,5 +100,5 @@ const AdminUserCreate = (props) => {
|
|
|
101
100
|
};
|
|
102
101
|
|
|
103
102
|
//#endregion
|
|
104
|
-
export {
|
|
105
|
-
//# sourceMappingURL=AdminUserCreate-
|
|
103
|
+
export { AdminUserCreate as default };
|
|
104
|
+
//# sourceMappingURL=AdminUserCreate-CgqeFwCt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AdminUserCreate-CgqeFwCt.js","names":["Text"],"sources":["../../src/admin/components/users/AdminUserCreate.tsx"],"sourcesContent":["import { ActionButton, Control, Flex } from \"@alepha/ui\";\nimport { Card, Text } from \"@mantine/core\";\nimport { t } from \"alepha\";\nimport type { AdminUserController } from \"alepha/api/users\";\nimport { useClient } from \"alepha/react\";\nimport { useForm } from \"alepha/react/form\";\nimport { useRouter } from \"alepha/react/router\";\nimport type { AdminRouter } from \"../../AdminRouter.ts\";\n\nexport interface AdminUserCreateProps {\n userRealmName?: string;\n}\n\nconst AdminUserCreate = (props: AdminUserCreateProps) => {\n const client = useClient<AdminUserController>();\n const router = useRouter<AdminRouter>();\n\n const form = useForm({\n schema: t.object({\n username: t.optional(\n t.shortText({\n minLength: 3,\n maxLength: 50,\n pattern: \"^[a-zA-Z0-9._-]+$\",\n }),\n ),\n email: t.optional(t.email()),\n phoneNumber: t.optional(t.e164()),\n firstName: t.optional(t.string()),\n lastName: t.optional(t.string()),\n roles: t.optional(t.array(t.string())),\n enabled: t.optional(t.boolean()),\n password: t.optional(t.string({ minLength: 8 })),\n }),\n handler: async (data) => {\n const user = await client.createUser({\n query: {\n userRealmName: props.userRealmName,\n },\n body: {\n ...data,\n enabled: data.enabled ?? true,\n },\n });\n\n await router.push(\"adminUserDetails\", {\n params: { userId: user.id },\n });\n },\n });\n\n return (\n <Flex flex={1} p=\"md\">\n <Card withBorder p=\"lg\" maw={600} w=\"100%\">\n <form {...form.props}>\n <Flex direction=\"column\" gap=\"md\">\n <Text size=\"lg\" fw={500}>\n Create New User\n </Text>\n\n <Control title=\"Username\" input={form.input.username} />\n\n <Control title=\"Email\" input={form.input.email} />\n\n <Control title=\"Phone Number\" input={form.input.phoneNumber} />\n\n <Control title=\"First Name\" input={form.input.firstName} />\n\n <Control title=\"Last Name\" input={form.input.lastName} />\n\n <Control title=\"Password\" input={form.input.password} password />\n\n <Control title=\"Roles\" input={form.input.roles} />\n\n <Control title=\"Enabled\" input={form.input.enabled} />\n\n <ActionButton form={form}>Create User</ActionButton>\n </Flex>\n </form>\n </Card>\n </Flex>\n );\n};\n\nexport default AdminUserCreate;\n"],"mappings":";;;;;;;;;AAaA,MAAM,mBAAmB,UAAgC;CACvD,MAAM,SAAS,WAAgC;CAC/C,MAAM,SAAS,WAAwB;CAEvC,MAAM,OAAO,QAAQ;EACnB,QAAQ,EAAE,OAAO;GACf,UAAU,EAAE,SACV,EAAE,UAAU;IACV,WAAW;IACX,WAAW;IACX,SAAS;IACV,CAAC,CACH;GACD,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC;GAC5B,aAAa,EAAE,SAAS,EAAE,MAAM,CAAC;GACjC,WAAW,EAAE,SAAS,EAAE,QAAQ,CAAC;GACjC,UAAU,EAAE,SAAS,EAAE,QAAQ,CAAC;GAChC,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;GACtC,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC;GAChC,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,GAAG,CAAC,CAAC;GACjD,CAAC;EACF,SAAS,OAAO,SAAS;GACvB,MAAM,OAAO,MAAM,OAAO,WAAW;IACnC,OAAO,EACL,eAAe,MAAM,eACtB;IACD,MAAM;KACJ,GAAG;KACH,SAAS,KAAK,WAAW;KAC1B;IACF,CAAC;AAEF,SAAM,OAAO,KAAK,oBAAoB,EACpC,QAAQ,EAAE,QAAQ,KAAK,IAAI,EAC5B,CAAC;;EAEL,CAAC;AAEF,QACE,oBAAC;EAAK,MAAM;EAAG,GAAE;YACf,oBAAC;GAAK;GAAW,GAAE;GAAK,KAAK;GAAK,GAAE;aAClC,oBAAC;IAAK,GAAI,KAAK;cACb,qBAAC;KAAK,WAAU;KAAS,KAAI;;MAC3B,oBAACA;OAAK,MAAK;OAAK,IAAI;iBAAK;QAElB;MAEP,oBAAC;OAAQ,OAAM;OAAW,OAAO,KAAK,MAAM;QAAY;MAExD,oBAAC;OAAQ,OAAM;OAAQ,OAAO,KAAK,MAAM;QAAS;MAElD,oBAAC;OAAQ,OAAM;OAAe,OAAO,KAAK,MAAM;QAAe;MAE/D,oBAAC;OAAQ,OAAM;OAAa,OAAO,KAAK,MAAM;QAAa;MAE3D,oBAAC;OAAQ,OAAM;OAAY,OAAO,KAAK,MAAM;QAAY;MAEzD,oBAAC;OAAQ,OAAM;OAAW,OAAO,KAAK,MAAM;OAAU;QAAW;MAEjE,oBAAC;OAAQ,OAAM;OAAQ,OAAO,KAAK,MAAM;QAAS;MAElD,oBAAC;OAAQ,OAAM;OAAU,OAAO,KAAK,MAAM;QAAW;MAEtD,oBAAC;OAAmB;iBAAM;QAA0B;;MAC/C;KACF;IACF;GACF"}
|