@alepha/ui 0.13.6 → 0.13.7

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 (157) hide show
  1. package/dist/admin/AdminAudits-CwvH8e8c.js +215 -0
  2. package/dist/admin/AdminAudits-CwvH8e8c.js.map +1 -0
  3. package/dist/admin/AdminAudits-Dv8Vk_6r.js +3 -0
  4. package/dist/admin/AdminFiles-5CPA3lQk.js +3 -0
  5. package/dist/admin/{AdminFiles-B_jfB_Py.js → AdminFiles-C_w1tb_x.js} +4 -3
  6. package/dist/admin/AdminFiles-C_w1tb_x.js.map +1 -0
  7. package/dist/admin/AdminLayout-BnSmtA4x.js +3 -0
  8. package/dist/admin/AdminLayout-XiSivwWH.js +39 -0
  9. package/dist/admin/AdminLayout-XiSivwWH.js.map +1 -0
  10. package/dist/admin/AdminNotifications-DLjmZWtf.js +3 -0
  11. package/dist/admin/{AdminNotifications-BFEjqpqx.js → AdminNotifications-DuYy74AN.js} +3 -3
  12. package/dist/admin/AdminNotifications-DuYy74AN.js.map +1 -0
  13. package/dist/admin/AdminParameters-DYg48Jwe.js +3 -0
  14. package/dist/admin/AdminParameters-YagqWTG3.js +575 -0
  15. package/dist/admin/AdminParameters-YagqWTG3.js.map +1 -0
  16. package/dist/admin/{AdminSessions-D7DESfWK.js → AdminSessions-BCjgJ-93.js} +4 -4
  17. package/dist/admin/AdminSessions-BCjgJ-93.js.map +1 -0
  18. package/dist/admin/AdminSessions-DEh2uN-4.js +3 -0
  19. package/dist/admin/AdminUserAudits-B_PUXCKC.js +177 -0
  20. package/dist/admin/AdminUserAudits-B_PUXCKC.js.map +1 -0
  21. package/dist/admin/AdminUserAudits-D7cTcElL.js +3 -0
  22. package/dist/admin/{AdminUserCreate-Bhxsn92l.js → AdminUserCreate-DzfRbGZ4.js} +4 -4
  23. package/dist/admin/AdminUserCreate-DzfRbGZ4.js.map +1 -0
  24. package/dist/admin/{AdminUserCreate-CYI_xW5T.js → AdminUserCreate-oUA1KDIl.js} +1 -1
  25. package/dist/admin/{AdminUserDetails-C2y1Ig4n.js → AdminUserDetails-DeTrJm-t.js} +5 -5
  26. package/dist/admin/AdminUserDetails-DeTrJm-t.js.map +1 -0
  27. package/dist/admin/{AdminUserDetails-Cmzx9HxH.js → AdminUserDetails-y1H5DW8Y.js} +1 -1
  28. package/dist/admin/{AdminUserLayout-sW6cjZL0.js → AdminUserLayout-CsfrrZkD.js} +4 -7
  29. package/dist/admin/AdminUserLayout-CsfrrZkD.js.map +1 -0
  30. package/dist/admin/{AdminUserLayout-DGSf612u.js → AdminUserLayout-Dejnz13m.js} +1 -1
  31. package/dist/admin/AdminUserSessions-Bbhcpz4k.js +3 -0
  32. package/dist/admin/{AdminUserSessions-CvN15wPe.js → AdminUserSessions-DO9H85O-.js} +4 -4
  33. package/dist/admin/AdminUserSessions-DO9H85O-.js.map +1 -0
  34. package/dist/admin/{AdminUserSettings-DvaaxgcV.js → AdminUserSettings-B3jA8g3p.js} +4 -4
  35. package/dist/admin/AdminUserSettings-B3jA8g3p.js.map +1 -0
  36. package/dist/admin/AdminUserSettings-CE0xpbQc.js +3 -0
  37. package/dist/admin/AdminUsers-CegGZDhW.js +3 -0
  38. package/dist/admin/{AdminUsers-BR3C-jrg.js → AdminUsers-ebbrJBT0.js} +13 -17
  39. package/dist/admin/AdminUsers-ebbrJBT0.js.map +1 -0
  40. package/dist/admin/index.d.ts +2044 -1044
  41. package/dist/admin/index.js +65 -62
  42. package/dist/admin/index.js.map +1 -1
  43. package/dist/auth/AuthLayout-BAZJHzDG.js +23 -0
  44. package/dist/auth/AuthLayout-BAZJHzDG.js.map +1 -0
  45. package/dist/auth/{Login-7HlBjDeV.js → Login-CeNZZjrr.js} +80 -44
  46. package/dist/auth/Login-CeNZZjrr.js.map +1 -0
  47. package/dist/auth/Login-hQcu1nlu.js +4 -0
  48. package/dist/auth/Register-B6HBNVHS.js +4 -0
  49. package/dist/auth/{Register-CuQr3kgi.js → Register-s4ENeyiE.js} +131 -91
  50. package/dist/auth/Register-s4ENeyiE.js.map +1 -0
  51. package/dist/auth/ResetPassword-Cjd-W-Nu.js +3 -0
  52. package/dist/auth/ResetPassword-GLIFkJT7.js +278 -0
  53. package/dist/auth/ResetPassword-GLIFkJT7.js.map +1 -0
  54. package/dist/auth/index.d.ts +471 -426
  55. package/dist/auth/index.js +26 -18
  56. package/dist/auth/index.js.map +1 -1
  57. package/dist/core/index.d.ts +400 -130
  58. package/dist/core/index.js +1751 -1369
  59. package/dist/core/index.js.map +1 -1
  60. package/package.json +15 -11
  61. package/src/admin/AdminRouter.ts +70 -16
  62. package/src/admin/components/AdminLayout.tsx +41 -61
  63. package/src/admin/components/audits/AdminAudits.tsx +240 -0
  64. package/src/admin/components/{AdminFiles.tsx → files/AdminFiles.tsx} +1 -1
  65. package/src/admin/components/{AdminJobs.tsx → jobs/AdminJobs.tsx} +1 -1
  66. package/src/admin/components/parameters/AdminParameters.tsx +137 -0
  67. package/src/admin/components/parameters/ParameterDetails.tsx +228 -0
  68. package/src/admin/components/parameters/ParameterHistory.tsx +146 -0
  69. package/src/admin/components/parameters/ParameterTree.tsx +146 -0
  70. package/src/admin/components/parameters/types.ts +35 -0
  71. package/src/admin/components/{AdminSessions.tsx → sessions/AdminSessions.tsx} +1 -1
  72. package/src/admin/components/users/AdminUserAudits.tsx +183 -0
  73. package/src/admin/components/{AdminUserCreate.tsx → users/AdminUserCreate.tsx} +1 -1
  74. package/src/admin/components/{AdminUserLayout.tsx → users/AdminUserLayout.tsx} +1 -4
  75. package/src/admin/components/{AdminUserSettings.tsx → users/AdminUserSettings.tsx} +1 -1
  76. package/src/admin/components/{AdminUsers.tsx → users/AdminUsers.tsx} +10 -12
  77. package/src/admin/index.ts +24 -16
  78. package/src/auth/AuthRouter.ts +23 -17
  79. package/src/auth/components/AuthLayout.tsx +6 -3
  80. package/src/auth/components/Login.tsx +109 -47
  81. package/src/auth/components/Register.tsx +158 -94
  82. package/src/auth/components/ResetPassword.tsx +51 -5
  83. package/src/auth/components/buttons/UserButton.tsx +2 -0
  84. package/src/core/atoms/alephaThemeAtom.ts +13 -0
  85. package/src/core/atoms/alephaThemeListAtom.ts +10 -0
  86. package/src/core/atoms/themes/default.ts +6 -0
  87. package/src/core/{themes → atoms/themes}/midnight.ts +3 -5
  88. package/src/core/components/buttons/ActionButton.tsx +33 -26
  89. package/src/core/components/buttons/DarkModeButton.tsx +0 -1
  90. package/src/core/components/buttons/ThemeButton.tsx +10 -7
  91. package/src/core/components/buttons/ToggleSidebarButton.tsx +19 -16
  92. package/src/core/components/data/ErrorViewer.tsx +171 -0
  93. package/src/core/components/data/JsonViewer.tsx +147 -138
  94. package/src/core/components/form/Control.tsx +95 -18
  95. package/src/core/components/form/ControlArray.tsx +377 -0
  96. package/src/core/components/form/ControlObject.tsx +127 -0
  97. package/src/core/components/form/TypeForm.tsx +99 -37
  98. package/src/core/components/layout/AdminShell.tsx +14 -1
  99. package/src/core/components/layout/AlephaMantineProvider.tsx +7 -3
  100. package/src/core/components/layout/Omnibar.tsx +1 -1
  101. package/src/core/components/layout/Sidebar.tsx +47 -14
  102. package/src/core/components/table/ColumnPicker.tsx +126 -0
  103. package/src/core/components/table/DataTable.tsx +354 -181
  104. package/src/core/components/table/DataTableFilters.tsx +64 -0
  105. package/src/core/components/table/DataTablePagination.tsx +59 -0
  106. package/src/core/components/table/DataTableToolbar.tsx +126 -0
  107. package/src/core/components/table/FilterPicker.tsx +138 -0
  108. package/src/core/components/table/types.ts +199 -0
  109. package/src/core/helpers/isComponentType.ts +9 -0
  110. package/src/core/helpers/renderIcon.tsx +13 -0
  111. package/src/core/hooks/useTheme.ts +24 -18
  112. package/src/core/index.ts +24 -3
  113. package/src/core/interfaces/AlephaTheme.ts +8 -0
  114. package/src/core/providers/ThemeProvider.ts +44 -62
  115. package/src/core/services/DialogService.tsx +24 -0
  116. package/src/core/utils/parseInput.ts +2 -2
  117. package/styles.css +1 -1
  118. package/dist/admin/AdminFiles-B-0UcHVV.js +0 -3
  119. package/dist/admin/AdminFiles-B_jfB_Py.js.map +0 -1
  120. package/dist/admin/AdminLayout-BMtiXAzS.js +0 -396
  121. package/dist/admin/AdminLayout-BMtiXAzS.js.map +0 -1
  122. package/dist/admin/AdminLayout-BNo3GoHR.js +0 -3
  123. package/dist/admin/AdminNotifications-BFEjqpqx.js.map +0 -1
  124. package/dist/admin/AdminNotifications-DJs2ZjNj.js +0 -3
  125. package/dist/admin/AdminSessions-D7DESfWK.js.map +0 -1
  126. package/dist/admin/AdminSessions-PS2M8iXi.js +0 -3
  127. package/dist/admin/AdminUserCreate-Bhxsn92l.js.map +0 -1
  128. package/dist/admin/AdminUserDetails-C2y1Ig4n.js.map +0 -1
  129. package/dist/admin/AdminUserLayout-sW6cjZL0.js.map +0 -1
  130. package/dist/admin/AdminUserSessions-CvN15wPe.js.map +0 -1
  131. package/dist/admin/AdminUserSessions-D-aOcZgV.js +0 -3
  132. package/dist/admin/AdminUserSettings-CEMhIYrI.js +0 -3
  133. package/dist/admin/AdminUserSettings-DvaaxgcV.js.map +0 -1
  134. package/dist/admin/AdminUsers-BR3C-jrg.js.map +0 -1
  135. package/dist/admin/AdminUsers-CMW9vN09.js +0 -3
  136. package/dist/auth/AuthLayout-CzwUKD9y.js +0 -19
  137. package/dist/auth/AuthLayout-CzwUKD9y.js.map +0 -1
  138. package/dist/auth/Login-7HlBjDeV.js.map +0 -1
  139. package/dist/auth/Login-C-e27DGb.js +0 -4
  140. package/dist/auth/Register-CuQr3kgi.js.map +0 -1
  141. package/dist/auth/Register-DbvXwgbG.js +0 -4
  142. package/dist/auth/ResetPassword-BzU-cdd4.js +0 -243
  143. package/dist/auth/ResetPassword-BzU-cdd4.js.map +0 -1
  144. package/dist/auth/ResetPassword-DSvrdpaA.js +0 -3
  145. package/src/admin/AdminSidebar.ts +0 -31
  146. package/src/admin/components/AdminParameters.tsx +0 -24
  147. package/src/core/themes/aurora.ts +0 -107
  148. package/src/core/themes/crystal.ts +0 -107
  149. package/src/core/themes/default.ts +0 -7
  150. package/src/core/themes/ember.ts +0 -107
  151. package/src/core/themes/index.ts +0 -7
  152. package/src/core/themes/remoraid.ts +0 -278
  153. package/src/core/themes/slate.ts +0 -81
  154. /package/src/admin/components/{AdminNotifications.tsx → notifications/AdminNotifications.tsx} +0 -0
  155. /package/src/admin/components/{AdminUserDetails.tsx → users/AdminUserDetails.tsx} +0 -0
  156. /package/src/admin/components/{AdminUserSessions.tsx → users/AdminUserSessions.tsx} +0 -0
  157. /package/src/admin/components/{AdminVerifications.tsx → verifications/AdminVerifications.tsx} +0 -0
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "mantine"
8
8
  ],
9
9
  "author": "Nicolas Foures",
10
- "version": "0.13.6",
10
+ "version": "0.13.7",
11
11
  "type": "module",
12
12
  "engines": {
13
13
  "node": ">=22.0.0"
@@ -22,21 +22,25 @@
22
22
  "styles.css"
23
23
  ],
24
24
  "dependencies": {
25
- "@alepha/react": "0.13.6",
26
- "@mantine/core": "^8.3.9",
27
- "@mantine/dates": "^8.3.9",
28
- "@mantine/hooks": "^8.3.9",
29
- "@mantine/modals": "^8.3.9",
30
- "@mantine/notifications": "^8.3.9",
31
- "@mantine/nprogress": "^8.3.9",
32
- "@mantine/spotlight": "^8.3.9",
25
+ "@alepha/react": "0.13.7",
26
+ "@mantine/core": "^8.3.10",
27
+ "@mantine/dates": "^8.3.10",
28
+ "@mantine/hooks": "^8.3.10",
29
+ "@mantine/modals": "^8.3.10",
30
+ "@mantine/notifications": "^8.3.10",
31
+ "@mantine/nprogress": "^8.3.10",
32
+ "@mantine/spotlight": "^8.3.10",
33
33
  "@tabler/icons-react": "^3.35.0",
34
- "alepha": "0.13.6",
34
+ "alepha": "0.13.7",
35
35
  "dayjs": "^1.11.19"
36
36
  },
37
37
  "devDependencies": {
38
+ "@biomejs/biome": "^2.3.8",
38
39
  "react": "^19.2.1",
39
- "react-dom": "^19.2.1"
40
+ "react-dom": "^19.2.1",
41
+ "typescript": "^5.9.3",
42
+ "vite": "^7.2.7",
43
+ "vitest": "^4.0.15"
40
44
  },
41
45
  "peerDependencies": {
42
46
  "react": "*",
@@ -1,17 +1,22 @@
1
1
  import { $page, ReactRouter, Redirection } from "@alepha/react";
2
2
  import { ReactAuth } from "@alepha/react/auth";
3
+ import type { AdminShellProps } from "@alepha/ui";
3
4
  import { AuthRouter } from "@alepha/ui/auth";
4
5
  import {
5
6
  IconBell,
6
7
  IconDevices,
7
8
  IconFile,
9
+ IconHistory,
8
10
  IconPlus,
11
+ IconSettings,
9
12
  IconUser,
10
13
  IconUsers,
11
14
  } from "@tabler/icons-react";
12
15
  import { $inject } from "alepha";
16
+ import type { AuditController } from "alepha/api/audits";
13
17
  import type { FileController } from "alepha/api/files";
14
18
  import type { NotificationController } from "alepha/api/notifications";
19
+ import type { ConfigController } from "alepha/api/parameters";
15
20
  import type { SessionController, UserController } from "alepha/api/users";
16
21
  import { $client } from "alepha/server/links";
17
22
 
@@ -23,6 +28,22 @@ export class AdminRouter {
23
28
  protected readonly sessionCtrl = $client<SessionController>();
24
29
  protected readonly notificationCtrl = $client<NotificationController>();
25
30
  protected readonly fileCtrl = $client<FileController>();
31
+ protected readonly configCtrl = $client<ConfigController>();
32
+ protected readonly auditCtrl = $client<AuditController>();
33
+
34
+ protected adminShellProps(): AdminShellProps {
35
+ return {};
36
+ }
37
+
38
+ protected onNotAuthorized(url: URL) {
39
+ return new Redirection(
40
+ this.router.path(this.authRouter.login.name, {
41
+ query: {
42
+ r: url.pathname,
43
+ },
44
+ }),
45
+ );
46
+ }
26
47
 
27
48
  // ─────────────────────────────────────────────────────────────────────────────
28
49
  // Layout
@@ -33,15 +54,12 @@ export class AdminRouter {
33
54
  path: "/admin",
34
55
  label: "Admin",
35
56
  lazy: () => import("./components/AdminLayout.tsx"),
57
+ props: () => ({
58
+ adminShellProps: this.adminShellProps(),
59
+ }),
36
60
  resolve: ({ user, url }) => {
37
61
  if (!user) {
38
- throw new Redirection(
39
- this.router.path(this.authRouter.login.name, {
40
- query: {
41
- r: url.pathname,
42
- },
43
- }),
44
- );
62
+ throw this.onNotAuthorized(url);
45
63
  }
46
64
  return {};
47
65
  },
@@ -57,7 +75,7 @@ export class AdminRouter {
57
75
  path: "/users",
58
76
  label: "Users",
59
77
  description: "Manage application users and their roles.",
60
- lazy: () => import("./components/AdminUsers.tsx"),
78
+ lazy: () => import("./components/users/AdminUsers.tsx"),
61
79
  can: () => this.userCtrl.findUsers.can(),
62
80
  });
63
81
 
@@ -67,7 +85,7 @@ export class AdminRouter {
67
85
  path: "/users/create",
68
86
  label: "Create User",
69
87
  description: "Create a new user account.",
70
- lazy: () => import("./components/AdminUserCreate.tsx"),
88
+ lazy: () => import("./components/users/AdminUserCreate.tsx"),
71
89
  can: () => this.userCtrl.createUser.can(),
72
90
  });
73
91
 
@@ -76,7 +94,7 @@ export class AdminRouter {
76
94
  parent: this.layout,
77
95
  path: "/users/:userId",
78
96
  label: "User",
79
- lazy: () => import("./components/AdminUserLayout.tsx"),
97
+ lazy: () => import("./components/users/AdminUserLayout.tsx"),
80
98
  can: () => this.userCtrl.getUser.can(),
81
99
  });
82
100
 
@@ -84,21 +102,43 @@ export class AdminRouter {
84
102
  parent: this.adminUserLayout,
85
103
  path: "/details",
86
104
  label: "Details",
87
- lazy: () => import("./components/AdminUserDetails.tsx"),
105
+ lazy: () => import("./components/users/AdminUserDetails.tsx"),
88
106
  });
89
107
 
90
108
  public readonly adminUserSessions = $page({
91
109
  parent: this.adminUserLayout,
92
110
  path: "/sessions",
93
111
  label: "Sessions",
94
- lazy: () => import("./components/AdminUserSessions.tsx"),
112
+ lazy: () => import("./components/users/AdminUserSessions.tsx"),
95
113
  });
96
114
 
97
115
  public readonly adminUserSettings = $page({
98
116
  parent: this.adminUserLayout,
99
117
  path: "/settings",
100
118
  label: "Settings",
101
- lazy: () => import("./components/AdminUserSettings.tsx"),
119
+ lazy: () => import("./components/users/AdminUserSettings.tsx"),
120
+ });
121
+
122
+ public readonly adminUserAudits = $page({
123
+ parent: this.adminUserLayout,
124
+ path: "/audits",
125
+ label: "Audit Log",
126
+ lazy: () => import("./components/users/AdminUserAudits.tsx"),
127
+ can: () => this.auditCtrl.findByUser.can(),
128
+ });
129
+
130
+ // ─────────────────────────────────────────────────────────────────────────────
131
+ // Audits (Global)
132
+ // ─────────────────────────────────────────────────────────────────────────────
133
+
134
+ public readonly adminAudits = $page({
135
+ icon: IconHistory,
136
+ parent: this.layout,
137
+ path: "/audits",
138
+ label: "Audit Log",
139
+ description: "View system-wide audit trail and activity logs.",
140
+ lazy: () => import("./components/audits/AdminAudits.tsx"),
141
+ can: () => this.auditCtrl.findAudits.can(),
102
142
  });
103
143
 
104
144
  // ─────────────────────────────────────────────────────────────────────────────
@@ -111,7 +151,7 @@ export class AdminRouter {
111
151
  path: "/sessions",
112
152
  label: "Sessions",
113
153
  description: "View and manage all active sessions.",
114
- lazy: () => import("./components/AdminSessions.tsx"),
154
+ lazy: () => import("./components/sessions/AdminSessions.tsx"),
115
155
  can: () => this.sessionCtrl.findSessions.can(),
116
156
  });
117
157
 
@@ -125,7 +165,7 @@ export class AdminRouter {
125
165
  path: "/notifications",
126
166
  label: "Notifications",
127
167
  description: "View notification history and status.",
128
- lazy: () => import("./components/AdminNotifications.tsx"),
168
+ lazy: () => import("./components/notifications/AdminNotifications.tsx"),
129
169
  can: () => this.notificationCtrl.findNotifications.can(),
130
170
  });
131
171
 
@@ -139,7 +179,21 @@ export class AdminRouter {
139
179
  path: "/files",
140
180
  label: "Files",
141
181
  description: "Manage uploaded files and storage.",
142
- lazy: () => import("./components/AdminFiles.tsx"),
182
+ lazy: () => import("./components/files/AdminFiles.tsx"),
143
183
  can: () => this.fileCtrl.findFiles.can(),
144
184
  });
185
+
186
+ // ─────────────────────────────────────────────────────────────────────────────
187
+ // Parameters
188
+ // ─────────────────────────────────────────────────────────────────────────────
189
+
190
+ public readonly adminParameters = $page({
191
+ icon: IconSettings,
192
+ parent: this.layout,
193
+ path: "/parameters",
194
+ label: "Parameters",
195
+ description: "View and manage application configuration parameters.",
196
+ lazy: () => import("./components/parameters/AdminParameters.tsx"),
197
+ can: () => this.configCtrl.getConfigTree.can(),
198
+ });
145
199
  }
@@ -1,75 +1,55 @@
1
- import { NestedView, useInject, useRouter } from "@alepha/react";
2
1
  import {
3
2
  ActionButton,
4
3
  AdminShell,
4
+ type AdminShellProps,
5
+ AlephaMantineProvider,
5
6
  OmnibarButton,
6
- ThemeButton,
7
7
  } from "@alepha/ui";
8
8
  import { UserButton } from "@alepha/ui/auth";
9
- import { Flex } from "@mantine/core";
10
9
  import { IconArrowLeft } from "@tabler/icons-react";
11
- import type { AdminRouter } from "../AdminRouter.ts";
12
- import { AdminSidebar } from "../AdminSidebar.ts";
13
10
 
14
- const AdminLayout = () => {
15
- const router = useRouter<AdminRouter>();
16
- const sidebar = useInject(AdminSidebar);
11
+ export interface AdminLayoutProps {
12
+ adminShellProps?: AdminShellProps;
13
+ }
17
14
 
15
+ const AdminLayout = (props: AdminLayoutProps) => {
18
16
  return (
19
- <AdminShell
20
- appShellMainProps={{
21
- bg: "var(--alepha-surface)",
22
- }}
23
- appShellHeaderProps={{
24
- bg: "var(--alepha-background)",
25
- }}
26
- appShellNavbarProps={
27
- {
28
- // bg: "var(--alepha-background)",
29
- }
30
- }
31
- appShellProps={
32
- {
33
- // withBorder: false,
34
- }
35
- }
36
- appShellFooterProps={{
37
- bg: "var(--alepha-background)",
38
- }}
39
- footer={<Flex h={12} />}
40
- appBarProps={{
41
- items: [
42
- {
43
- element: <ActionButton icon={IconArrowLeft} href={"/"} />,
44
- position: "left",
17
+ <AlephaMantineProvider>
18
+ <AdminShell
19
+ appBarProps={{
20
+ items: [
21
+ {
22
+ element: (
23
+ <ActionButton
24
+ variant={"subtle"}
25
+ icon={IconArrowLeft}
26
+ href={"/"}
27
+ />
28
+ ),
29
+ position: "left",
30
+ },
31
+ {
32
+ element: <OmnibarButton />,
33
+ position: "center",
34
+ },
35
+ {
36
+ element: <UserButton />,
37
+ position: "right",
38
+ },
39
+ {
40
+ type: "dark",
41
+ position: "right",
42
+ },
43
+ ],
44
+ }}
45
+ sidebarProps={{
46
+ autoPopulateMenu: {
47
+ startsWith: "/admin",
45
48
  },
46
- {
47
- element: <OmnibarButton actionProps={{ variant: "outline" }} />,
48
- position: "right",
49
- },
50
- {
51
- element: <UserButton />,
52
- position: "right",
53
- },
54
- {
55
- element: <ThemeButton />,
56
- position: "right",
57
- },
58
- {
59
- type: "dark",
60
- position: "right",
61
- },
62
- ],
63
- }}
64
- sidebarProps={{
65
- gap: "xs",
66
- menu: sidebar.menu(router),
67
- }}
68
- >
69
- <Flex flex={1} bg={"var(--alepha-surface)"}>
70
- <NestedView />
71
- </Flex>
72
- </AdminShell>
49
+ }}
50
+ {...props.adminShellProps}
51
+ />
52
+ </AlephaMantineProvider>
73
53
  );
74
54
  };
75
55
 
@@ -0,0 +1,240 @@
1
+ import { useClient, useRouter } from "@alepha/react";
2
+ import { useI18n } from "@alepha/react/i18n";
3
+ import { DataTable, Flex, Text } from "@alepha/ui";
4
+ import { Badge, Group, Stack, Tooltip } from "@mantine/core";
5
+ import {
6
+ IconAlertTriangle,
7
+ IconCheck,
8
+ IconInfoCircle,
9
+ IconUser,
10
+ IconX,
11
+ } from "@tabler/icons-react";
12
+ import { type Page, t } from "alepha";
13
+ import type { AuditController, AuditEntity } from "alepha/api/audits";
14
+ import type { AdminRouter } from "../../AdminRouter.ts";
15
+
16
+ export interface AdminAuditsProps {
17
+ userRealmName?: string;
18
+ }
19
+
20
+ const getSeverityColor = (severity: string) => {
21
+ switch (severity) {
22
+ case "critical":
23
+ return "red";
24
+ case "warning":
25
+ return "yellow";
26
+ default:
27
+ return "blue";
28
+ }
29
+ };
30
+
31
+ const getSeverityIcon = (severity: string) => {
32
+ switch (severity) {
33
+ case "critical":
34
+ return <IconAlertTriangle size={12} />;
35
+ case "warning":
36
+ return <IconAlertTriangle size={12} />;
37
+ default:
38
+ return <IconInfoCircle size={12} />;
39
+ }
40
+ };
41
+
42
+ const getTypeColor = (type: string) => {
43
+ switch (type) {
44
+ case "auth":
45
+ return "blue";
46
+ case "user":
47
+ return "grape";
48
+ case "security":
49
+ return "red";
50
+ case "system":
51
+ return "orange";
52
+ case "access":
53
+ return "cyan";
54
+ case "payment":
55
+ return "green";
56
+ case "order":
57
+ return "teal";
58
+ default:
59
+ return "gray";
60
+ }
61
+ };
62
+
63
+ const AdminAudits = (props: AdminAuditsProps) => {
64
+ const client = useClient<AuditController>();
65
+ const router = useRouter<AdminRouter>();
66
+ const { l } = useI18n();
67
+
68
+ const filters = t.object({
69
+ type: t.optional(t.text()),
70
+ action: t.optional(t.text()),
71
+ severity: t.optional(t.enum(["info", "warning", "critical"])),
72
+ success: t.optional(t.boolean()),
73
+ resourceType: t.optional(t.text()),
74
+ search: t.optional(t.text()),
75
+ from: t.optional(t.datetime()),
76
+ to: t.optional(t.datetime()),
77
+ });
78
+
79
+ return (
80
+ <Flex flex={1} direction="column">
81
+ <DataTable<AuditEntity, typeof filters>
82
+ submitOnInit
83
+ defaultSize={20}
84
+ typeFormProps={{
85
+ skipSubmitButton: true,
86
+ columns: 4,
87
+ }}
88
+ tableProps={{
89
+ horizontalSpacing: "xs",
90
+ verticalSpacing: "xs",
91
+ striped: false,
92
+ highlightOnHover: true,
93
+ }}
94
+ filters={filters}
95
+ tableTrProps={(item) => ({
96
+ style: {
97
+ cursor: item.userId ? "pointer" : "default",
98
+ opacity: item.success ? 1 : 0.85,
99
+ },
100
+ onClick: () => {
101
+ if (item.userId) {
102
+ router.go("adminUserDetails", {
103
+ params: { userId: item.userId },
104
+ });
105
+ }
106
+ },
107
+ })}
108
+ items={async (query) => {
109
+ const response = await client.findAudits({
110
+ query: {
111
+ ...query,
112
+ userRealm: props.userRealmName,
113
+ },
114
+ });
115
+ return response as Page<AuditEntity>;
116
+ }}
117
+ columns={{
118
+ type: {
119
+ label: "Type",
120
+ fit: true,
121
+ value: (item) => (
122
+ <Badge size="sm" variant="light" color={getTypeColor(item.type)}>
123
+ {item.type}
124
+ </Badge>
125
+ ),
126
+ },
127
+ action: {
128
+ label: "Action",
129
+ fit: true,
130
+ value: (item) => (
131
+ <Badge size="sm" variant="outline">
132
+ {item.action}
133
+ </Badge>
134
+ ),
135
+ },
136
+ severity: {
137
+ label: "Severity",
138
+ fit: true,
139
+ value: (item) => (
140
+ <Badge
141
+ size="xs"
142
+ variant="light"
143
+ color={getSeverityColor(item.severity)}
144
+ leftSection={getSeverityIcon(item.severity)}
145
+ >
146
+ {item.severity}
147
+ </Badge>
148
+ ),
149
+ },
150
+ user: {
151
+ label: "User",
152
+ fit: true,
153
+ value: (item) =>
154
+ item.userId ? (
155
+ <Tooltip
156
+ label={
157
+ <Stack gap={2}>
158
+ <Text size="xs">{item.userEmail || "No email"}</Text>
159
+ <Text size="xs" c="dimmed">
160
+ {item.userRealm || "default"}
161
+ </Text>
162
+ </Stack>
163
+ }
164
+ >
165
+ <Group gap={4}>
166
+ <IconUser size={12} />
167
+ <Text size="xs" lineClamp={1} maw={100}>
168
+ {item.userEmail?.split("@")[0] || item.userId.slice(0, 8)}
169
+ </Text>
170
+ </Group>
171
+ </Tooltip>
172
+ ) : (
173
+ <Text size="xs" c="dimmed">
174
+ System
175
+ </Text>
176
+ ),
177
+ },
178
+ description: {
179
+ label: "Description",
180
+ value: (item) => (
181
+ <Text size="sm" lineClamp={1}>
182
+ {item.description || "-"}
183
+ </Text>
184
+ ),
185
+ },
186
+ resource: {
187
+ label: "Resource",
188
+ fit: true,
189
+ value: (item) =>
190
+ item.resourceType ? (
191
+ <Tooltip label={`${item.resourceType}: ${item.resourceId}`}>
192
+ <Badge size="xs" variant="dot" color="gray">
193
+ {item.resourceType}
194
+ </Badge>
195
+ </Tooltip>
196
+ ) : (
197
+ <Text size="xs" c="dimmed">
198
+ -
199
+ </Text>
200
+ ),
201
+ },
202
+ success: {
203
+ label: "Status",
204
+ fit: true,
205
+ value: (item) =>
206
+ item.success ? (
207
+ <IconCheck size={14} color="var(--mantine-color-green-6)" />
208
+ ) : (
209
+ <Tooltip label={item.errorMessage || "Failed"}>
210
+ <IconX size={14} color="var(--mantine-color-red-6)" />
211
+ </Tooltip>
212
+ ),
213
+ },
214
+ ipAddress: {
215
+ label: "IP",
216
+ fit: true,
217
+ value: (item) => (
218
+ <Text size="xs" c="dimmed" ff="monospace">
219
+ {item.ipAddress || "-"}
220
+ </Text>
221
+ ),
222
+ },
223
+ createdAt: {
224
+ label: "Time",
225
+ fit: true,
226
+ value: (item) => (
227
+ <Tooltip label={l(item.createdAt, { date: "medium" })}>
228
+ <Text size="xs" c="dimmed">
229
+ {l(item.createdAt, { date: "fromNow" })}
230
+ </Text>
231
+ </Tooltip>
232
+ ),
233
+ },
234
+ }}
235
+ />
236
+ </Flex>
237
+ );
238
+ };
239
+
240
+ export default AdminAudits;
@@ -29,7 +29,7 @@ const AdminFiles = () => {
29
29
  };
30
30
 
31
31
  return (
32
- <Flex flex={1}>
32
+ <Flex flex={1} direction={"column"}>
33
33
  <DataTable<FileEntity, typeof filters>
34
34
  submitOnInit
35
35
  defaultSize={10}
@@ -70,7 +70,7 @@ const AdminJobs = () => {
70
70
  };
71
71
 
72
72
  return (
73
- <Flex flex={1}>
73
+ <Flex flex={1} direction={"column"}>
74
74
  <DataTable<JobExecutionEntity, typeof filters>
75
75
  submitOnInit
76
76
  defaultSize={10}