@alepha/ui 0.13.2 → 0.13.4

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 (122) hide show
  1. package/dist/admin/{AdminFiles-BjofP3OC.js → AdminFiles-8CC9mVsc.js} +3 -3
  2. package/dist/admin/{AdminFiles-BjofP3OC.js.map → AdminFiles-8CC9mVsc.js.map} +1 -1
  3. package/dist/admin/AdminFiles-BRLMP_7y.js +3 -0
  4. package/dist/admin/AdminLayout-Cm-Y4YTQ.js +396 -0
  5. package/dist/admin/AdminLayout-Cm-Y4YTQ.js.map +1 -0
  6. package/dist/admin/AdminLayout-D5M9kSiV.js +3 -0
  7. package/dist/admin/AdminNotifications-DxBKi2RO.js +3 -0
  8. package/dist/admin/AdminNotifications-d-gw5Uie.js +154 -0
  9. package/dist/admin/AdminNotifications-d-gw5Uie.js.map +1 -0
  10. package/dist/admin/{AdminSessions-CmDVneE2.js → AdminSessions-CpVusqmd.js} +37 -10
  11. package/dist/admin/AdminSessions-CpVusqmd.js.map +1 -0
  12. package/dist/admin/AdminSessions-DA285-5Q.js +3 -0
  13. package/dist/admin/AdminUserCreate-CQIrSslj.js +3 -0
  14. package/dist/admin/AdminUserCreate-DH7u_yJj.js +103 -0
  15. package/dist/admin/AdminUserCreate-DH7u_yJj.js.map +1 -0
  16. package/dist/admin/AdminUserDetails-DVmFCDsU.js +221 -0
  17. package/dist/admin/AdminUserDetails-DVmFCDsU.js.map +1 -0
  18. package/dist/admin/AdminUserDetails-T3nkXSdz.js +3 -0
  19. package/dist/admin/AdminUserLayout-DdtZGX8n.js +3 -0
  20. package/dist/admin/AdminUserLayout-gpOyn0Y7.js +153 -0
  21. package/dist/admin/AdminUserLayout-gpOyn0Y7.js.map +1 -0
  22. package/dist/admin/AdminUserSessions-CWYzjB3D.js +3 -0
  23. package/dist/admin/AdminUserSessions-CdVwoM-h.js +129 -0
  24. package/dist/admin/AdminUserSessions-CdVwoM-h.js.map +1 -0
  25. package/dist/admin/AdminUserSettings-S7gZvvjO.js +164 -0
  26. package/dist/admin/AdminUserSettings-S7gZvvjO.js.map +1 -0
  27. package/dist/admin/AdminUserSettings-jCzVYw_2.js +3 -0
  28. package/dist/admin/{AdminUsers-88De5pev.js → AdminUsers-9qEzxqAL.js} +33 -15
  29. package/dist/admin/AdminUsers-9qEzxqAL.js.map +1 -0
  30. package/dist/admin/AdminUsers-BcSUxV01.js +3 -0
  31. package/dist/admin/index.d.ts +5568 -418
  32. package/dist/admin/index.js +302 -42
  33. package/dist/admin/index.js.map +1 -1
  34. package/dist/auth/AuthLayout-BSL8ZHgr.js +19 -0
  35. package/dist/auth/AuthLayout-BSL8ZHgr.js.map +1 -0
  36. package/dist/auth/{Login-OCrvjs9U.js → Login-AlVPPqQp.js} +6 -5
  37. package/dist/auth/Login-AlVPPqQp.js.map +1 -0
  38. package/dist/auth/Login-otdWVvVU.js +4 -0
  39. package/dist/auth/{Register-Ei34GSba.js → Register-BxJmOqpF.js} +9 -6
  40. package/dist/auth/Register-BxJmOqpF.js.map +1 -0
  41. package/dist/auth/Register-D10MnlQc.js +4 -0
  42. package/dist/auth/{ResetPassword-tO0oMzfo.js → ResetPassword-BhyZ9ek4.js} +3 -3
  43. package/dist/auth/ResetPassword-BhyZ9ek4.js.map +1 -0
  44. package/dist/auth/ResetPassword-llBG-STp.js +3 -0
  45. package/dist/auth/VerifyEmail-BvOG-IUC.js +3 -0
  46. package/dist/auth/VerifyEmail-DeLct3oQ.js +131 -0
  47. package/dist/auth/VerifyEmail-DeLct3oQ.js.map +1 -0
  48. package/dist/auth/index.d.ts +2412 -2254
  49. package/dist/auth/index.js +97 -20
  50. package/dist/auth/index.js.map +1 -1
  51. package/dist/core/index.d.ts +280 -95
  52. package/dist/core/index.js +1375 -394
  53. package/dist/core/index.js.map +1 -1
  54. package/package.json +7 -6
  55. package/src/admin/AdminRouter.ts +116 -29
  56. package/src/admin/AdminSidebar.ts +31 -0
  57. package/src/admin/MainRouter.ts +23 -0
  58. package/src/admin/components/AdminLayout.tsx +66 -104
  59. package/src/admin/components/AdminNotifications.tsx +196 -12
  60. package/src/admin/components/AdminSessions.tsx +43 -7
  61. package/src/admin/components/AdminUserCreate.tsx +84 -0
  62. package/src/admin/components/AdminUserDetails.tsx +180 -0
  63. package/src/admin/components/AdminUserLayout.tsx +172 -0
  64. package/src/admin/components/AdminUserSessions.tsx +158 -0
  65. package/src/admin/components/AdminUserSettings.tsx +165 -0
  66. package/src/admin/components/AdminUsers.tsx +29 -9
  67. package/src/admin/index.ts +15 -3
  68. package/src/auth/AuthI18n.ts +22 -0
  69. package/src/auth/AuthRouter.ts +82 -8
  70. package/src/auth/components/AuthLayout.tsx +12 -0
  71. package/src/auth/components/Login.tsx +14 -12
  72. package/src/auth/components/Register.tsx +6 -5
  73. package/src/auth/components/ResetPassword.tsx +1 -1
  74. package/src/auth/components/VerifyEmail.tsx +102 -0
  75. package/src/auth/components/buttons/UserButton.tsx +12 -2
  76. package/src/auth/index.ts +1 -0
  77. package/src/core/components/buttons/ActionButton.tsx +12 -4
  78. package/src/core/components/buttons/DarkModeButton.tsx +1 -1
  79. package/src/core/components/buttons/ThemeButton.tsx +31 -0
  80. package/src/core/components/layout/AdminShell.tsx +4 -2
  81. package/src/core/components/layout/AlephaMantineProvider.tsx +10 -4
  82. package/src/core/components/layout/Omnibar.tsx +27 -15
  83. package/src/core/components/layout/Sidebar.tsx +33 -17
  84. package/src/core/components/table/DataTable.tsx +9 -5
  85. package/src/core/hooks/useTheme.ts +25 -0
  86. package/src/core/index.ts +8 -3
  87. package/src/core/providers/ThemeProvider.ts +90 -0
  88. package/src/core/themes/aurora.ts +107 -0
  89. package/src/core/themes/crystal.ts +107 -0
  90. package/src/core/themes/default.ts +7 -0
  91. package/src/core/themes/ember.ts +107 -0
  92. package/src/core/themes/index.ts +7 -0
  93. package/src/core/themes/midnight.ts +98 -0
  94. package/src/core/themes/remoraid.ts +278 -0
  95. package/src/core/themes/slate.ts +81 -0
  96. package/styles.css +84 -0
  97. package/dist/admin/AdminFiles-DldZB7oo.js +0 -3
  98. package/dist/admin/AdminJobs-BOq6AZOW.js +0 -3
  99. package/dist/admin/AdminJobs-CDnVxEv6.js +0 -125
  100. package/dist/admin/AdminJobs-CDnVxEv6.js.map +0 -1
  101. package/dist/admin/AdminLayout-Bgx25J8m.js +0 -3
  102. package/dist/admin/AdminLayout-CervL8LV.js +0 -88
  103. package/dist/admin/AdminLayout-CervL8LV.js.map +0 -1
  104. package/dist/admin/AdminNotifications-BDQXt3-e.js +0 -3
  105. package/dist/admin/AdminNotifications-DvI2989x.js +0 -40
  106. package/dist/admin/AdminNotifications-DvI2989x.js.map +0 -1
  107. package/dist/admin/AdminParameters-D_v0GAvI.js +0 -3
  108. package/dist/admin/AdminParameters-P1LB6ZI1.js +0 -40
  109. package/dist/admin/AdminParameters-P1LB6ZI1.js.map +0 -1
  110. package/dist/admin/AdminSessions-CmDVneE2.js.map +0 -1
  111. package/dist/admin/AdminSessions-Dkk_fzWK.js +0 -3
  112. package/dist/admin/AdminUsers-88De5pev.js.map +0 -1
  113. package/dist/admin/AdminUsers-oyAXqZ5l.js +0 -3
  114. package/dist/admin/AdminVerifications-D93TKymL.js +0 -3
  115. package/dist/admin/AdminVerifications-DBVEoqJe.js +0 -40
  116. package/dist/admin/AdminVerifications-DBVEoqJe.js.map +0 -1
  117. package/dist/auth/Login-BC2jTczq.js +0 -4
  118. package/dist/auth/Login-OCrvjs9U.js.map +0 -1
  119. package/dist/auth/Register-Dh0lsQmI.js +0 -4
  120. package/dist/auth/Register-Ei34GSba.js.map +0 -1
  121. package/dist/auth/ResetPassword-BnlAQAOE.js +0 -3
  122. package/dist/auth/ResetPassword-tO0oMzfo.js.map +0 -1
@@ -1,65 +1,315 @@
1
- import { t as AdminFiles_default } from "./AdminFiles-BjofP3OC.js";
2
- import { t as AdminJobs_default } from "./AdminJobs-CDnVxEv6.js";
3
- import { t as AdminLayout_default } from "./AdminLayout-CervL8LV.js";
4
- import { t as AdminNotifications_default } from "./AdminNotifications-DvI2989x.js";
5
- import { t as AdminParameters_default } from "./AdminParameters-P1LB6ZI1.js";
6
- import { t as AdminSessions_default } from "./AdminSessions-CmDVneE2.js";
7
- import { t as AdminUsers_default } from "./AdminUsers-88De5pev.js";
8
- import { t as AdminVerifications_default } from "./AdminVerifications-DBVEoqJe.js";
9
- import { AlephaUI } from "@alepha/ui";
10
- import { $module } from "alepha";
11
- import { $page } from "@alepha/react";
1
+ import { n as AdminSidebar, t as AdminLayout_default } from "./AdminLayout-Cm-Y4YTQ.js";
2
+ import { t as AdminFiles_default } from "./AdminFiles-8CC9mVsc.js";
3
+ import { t as AdminNotifications_default } from "./AdminNotifications-d-gw5Uie.js";
4
+ import { t as AdminSessions_default } from "./AdminSessions-CpVusqmd.js";
5
+ import { t as AdminUserCreate_default } from "./AdminUserCreate-DH7u_yJj.js";
6
+ import { t as AdminUserDetails_default } from "./AdminUserDetails-DVmFCDsU.js";
7
+ import { t as AdminUserLayout_default } from "./AdminUserLayout-gpOyn0Y7.js";
8
+ import { t as AdminUserSessions_default } from "./AdminUserSessions-CdVwoM-h.js";
9
+ import { t as AdminUserSettings_default } from "./AdminUserSettings-S7gZvvjO.js";
10
+ import { t as AdminUsers_default } from "./AdminUsers-9qEzxqAL.js";
11
+ import { AlephaMantineProvider, AlephaUI, DataTable, Flex, Text } from "@alepha/ui";
12
+ import { AlephaUIAuth, AuthRouter } from "@alepha/ui/auth";
13
+ import { $inject, $module, t } from "alepha";
14
+ import { $page, ReactRouter, Redirection, useClient } from "@alepha/react";
15
+ import { ReactAuth } from "@alepha/react/auth";
16
+ import { IconBell, IconCheck, IconClock, IconDevices, IconFile, IconPlayerPlay, IconPlus, IconSettings, IconShieldCheck, IconUser, IconUsers, IconX } from "@tabler/icons-react";
17
+ import { $client } from "alepha/server/links";
18
+ import { Badge, Stack } from "@mantine/core";
19
+ import { jsx, jsxs } from "react/jsx-runtime";
20
+ import { useI18n } from "@alepha/react/i18n";
21
+ import { jobExecutions } from "alepha/api/jobs";
12
22
 
13
23
  //#region src/admin/AdminRouter.ts
14
24
  var AdminRouter = class {
15
- admin = $page({
25
+ router = $inject(ReactRouter);
26
+ authRouter = $inject(AuthRouter);
27
+ auth = $inject(ReactAuth);
28
+ userCtrl = $client();
29
+ sessionCtrl = $client();
30
+ notificationCtrl = $client();
31
+ fileCtrl = $client();
32
+ layout = $page({
33
+ name: "AdminLayout",
16
34
  path: "/admin",
17
35
  label: "Admin",
18
- lazy: () => import("./AdminLayout-Bgx25J8m.js")
36
+ lazy: () => import("./AdminLayout-D5M9kSiV.js"),
37
+ resolve: ({ user, url }) => {
38
+ if (!user) throw new Redirection(this.router.path(this.authRouter.login.name, { query: { r: url.pathname } }));
39
+ return {};
40
+ }
19
41
  });
20
42
  adminUsers = $page({
21
- parent: this.admin,
43
+ icon: IconUsers,
44
+ parent: this.layout,
22
45
  path: "/users",
23
46
  label: "Users",
24
- lazy: () => import("./AdminUsers-oyAXqZ5l.js")
47
+ description: "Manage application users and their roles.",
48
+ lazy: () => import("./AdminUsers-BcSUxV01.js"),
49
+ can: () => this.userCtrl.findUsers.can()
25
50
  });
26
- adminNotifications = $page({
27
- parent: this.admin,
28
- path: "/notifications",
29
- label: "Notifications",
30
- lazy: () => import("./AdminNotifications-BDQXt3-e.js")
51
+ adminUserCreate = $page({
52
+ icon: IconPlus,
53
+ parent: this.layout,
54
+ path: "/users/create",
55
+ label: "Create User",
56
+ description: "Create a new user account.",
57
+ lazy: () => import("./AdminUserCreate-CQIrSslj.js"),
58
+ can: () => this.userCtrl.createUser.can()
31
59
  });
32
- adminSessions = $page({
33
- parent: this.admin,
60
+ adminUserLayout = $page({
61
+ icon: IconUser,
62
+ parent: this.layout,
63
+ path: "/users/:userId",
64
+ label: "User",
65
+ lazy: () => import("./AdminUserLayout-DdtZGX8n.js"),
66
+ can: () => this.userCtrl.getUser.can()
67
+ });
68
+ adminUserDetails = $page({
69
+ parent: this.adminUserLayout,
70
+ path: "/details",
71
+ label: "Details",
72
+ lazy: () => import("./AdminUserDetails-T3nkXSdz.js")
73
+ });
74
+ adminUserSessions = $page({
75
+ parent: this.adminUserLayout,
34
76
  path: "/sessions",
35
77
  label: "Sessions",
36
- lazy: () => import("./AdminSessions-Dkk_fzWK.js")
78
+ lazy: () => import("./AdminUserSessions-CWYzjB3D.js")
37
79
  });
38
- adminVerifications = $page({
39
- parent: this.admin,
40
- path: "/verifications",
41
- label: "Verifications",
42
- lazy: () => import("./AdminVerifications-D93TKymL.js")
80
+ adminUserSettings = $page({
81
+ parent: this.adminUserLayout,
82
+ path: "/settings",
83
+ label: "Settings",
84
+ lazy: () => import("./AdminUserSettings-jCzVYw_2.js")
43
85
  });
44
- adminJobs = $page({
45
- parent: this.admin,
46
- path: "/jobs",
47
- label: "Jobs",
48
- lazy: () => import("./AdminJobs-BOq6AZOW.js")
86
+ adminSessions = $page({
87
+ icon: IconDevices,
88
+ parent: this.layout,
89
+ path: "/sessions",
90
+ label: "Sessions",
91
+ description: "View and manage all active sessions.",
92
+ lazy: () => import("./AdminSessions-DA285-5Q.js"),
93
+ can: () => this.sessionCtrl.findSessions.can()
49
94
  });
50
- adminParameters = $page({
51
- parent: this.admin,
52
- path: "/parameters",
53
- label: "Parameters",
54
- lazy: () => import("./AdminParameters-D_v0GAvI.js")
95
+ adminNotifications = $page({
96
+ icon: IconBell,
97
+ parent: this.layout,
98
+ path: "/notifications",
99
+ label: "Notifications",
100
+ description: "View notification history and status.",
101
+ lazy: () => import("./AdminNotifications-DxBKi2RO.js"),
102
+ can: () => this.notificationCtrl.findNotifications.can()
55
103
  });
56
104
  adminFiles = $page({
57
- parent: this.admin,
105
+ icon: IconFile,
106
+ parent: this.layout,
58
107
  path: "/files",
59
108
  label: "Files",
60
- lazy: () => import("./AdminFiles-DldZB7oo.js")
109
+ description: "Manage uploaded files and storage.",
110
+ lazy: () => import("./AdminFiles-BRLMP_7y.js"),
111
+ can: () => this.fileCtrl.findFiles.can()
112
+ });
113
+ };
114
+
115
+ //#endregion
116
+ //#region src/admin/MainRouter.ts
117
+ /**
118
+ * Main application router that combines Auth and Admin routers.
119
+ *
120
+ * We assume that the main application router will always have Admin and Auth routers.
121
+ *
122
+ * This is basically a convenience class to avoid having to inject these routers everywhere.
123
+ * Code is lightweight enough that we can just copy it if needed.
124
+ */
125
+ var MainRouter = class {
126
+ auth = $inject(AuthRouter);
127
+ admin = $inject(AdminRouter);
128
+ layout = $page({
129
+ component: AlephaMantineProvider,
130
+ children: () => [this.auth.layout, this.admin.layout]
131
+ });
132
+ };
133
+
134
+ //#endregion
135
+ //#region src/admin/components/AdminJobs.tsx
136
+ const AdminJobs = () => {
137
+ const client = useClient();
138
+ const { l } = useI18n();
139
+ const filters = t.object({
140
+ job: t.optional(t.string({ $control: { query: t.pick(jobExecutions.schema, ["job"]) } })),
141
+ status: t.optional(t.enum([
142
+ "STARTED",
143
+ "FAILED",
144
+ "COMPLETED"
145
+ ]))
146
+ });
147
+ const getStatusColor = (status) => {
148
+ switch (status) {
149
+ case "COMPLETED": return "green";
150
+ case "FAILED": return "red";
151
+ case "STARTED": return "blue";
152
+ default: return "gray";
153
+ }
154
+ };
155
+ const getStatusIcon = (status) => {
156
+ switch (status) {
157
+ case "COMPLETED": return /* @__PURE__ */ jsx(IconCheck, { size: 12 });
158
+ case "FAILED": return /* @__PURE__ */ jsx(IconX, { size: 12 });
159
+ case "STARTED": return /* @__PURE__ */ jsx(IconPlayerPlay, { size: 12 });
160
+ default: return /* @__PURE__ */ jsx(IconClock, { size: 12 });
161
+ }
162
+ };
163
+ const formatDuration = (start, end) => {
164
+ const startTime = new Date(start).getTime();
165
+ const duration = (end ? new Date(end).getTime() : Date.now()) - startTime;
166
+ if (duration < 1e3) return `${duration}ms`;
167
+ if (duration < 6e4) return `${(duration / 1e3).toFixed(1)}s`;
168
+ return `${Math.floor(duration / 6e4)}m ${Math.floor(duration % 6e4 / 1e3)}s`;
169
+ };
170
+ return /* @__PURE__ */ jsx(Flex, {
171
+ flex: 1,
172
+ children: /* @__PURE__ */ jsx(DataTable, {
173
+ submitOnInit: true,
174
+ defaultSize: 10,
175
+ typeFormProps: {
176
+ skipSubmitButton: true,
177
+ columns: 3
178
+ },
179
+ tableProps: {
180
+ horizontalSpacing: "xs",
181
+ verticalSpacing: "xs"
182
+ },
183
+ onFilterChange: (key, _value, form) => {
184
+ if (key === "job" || key === "status") return form.submit();
185
+ },
186
+ filters,
187
+ items: async (filters$1) => {
188
+ return await client.getJobExecutions({ query: filters$1 });
189
+ },
190
+ columns: {
191
+ job: {
192
+ label: "Job",
193
+ value: (item) => /* @__PURE__ */ jsx(Text, {
194
+ size: "sm",
195
+ fw: 500,
196
+ children: item.job
197
+ })
198
+ },
199
+ status: {
200
+ label: "Status",
201
+ fit: true,
202
+ value: (item) => /* @__PURE__ */ jsx(Badge, {
203
+ size: "sm",
204
+ variant: "light",
205
+ color: getStatusColor(item.status),
206
+ leftSection: getStatusIcon(item.status),
207
+ children: item.status
208
+ })
209
+ },
210
+ duration: {
211
+ label: "Duration",
212
+ fit: true,
213
+ value: (item) => /* @__PURE__ */ jsx(Text, {
214
+ size: "xs",
215
+ c: "dimmed",
216
+ ff: "monospace",
217
+ children: formatDuration(item.createdAt, item.finishedAt)
218
+ })
219
+ },
220
+ error: {
221
+ label: "Error",
222
+ value: (item) => item.error ? /* @__PURE__ */ jsx(Text, {
223
+ size: "xs",
224
+ c: "red",
225
+ lineClamp: 1,
226
+ children: item.error
227
+ }) : /* @__PURE__ */ jsx(Text, {
228
+ size: "xs",
229
+ c: "dimmed",
230
+ children: "-"
231
+ })
232
+ },
233
+ createdAt: {
234
+ label: "Started",
235
+ fit: true,
236
+ value: (item) => /* @__PURE__ */ jsx(Text, {
237
+ size: "xs",
238
+ c: "dimmed",
239
+ children: l(item.createdAt, { date: "fromNow" })
240
+ })
241
+ }
242
+ }
243
+ })
244
+ });
245
+ };
246
+ var AdminJobs_default = AdminJobs;
247
+
248
+ //#endregion
249
+ //#region src/admin/components/AdminParameters.tsx
250
+ const AdminParameters = () => {
251
+ return /* @__PURE__ */ jsx(Flex, {
252
+ flex: 1,
253
+ justify: "center",
254
+ align: "center",
255
+ children: /* @__PURE__ */ jsxs(Stack, {
256
+ align: "center",
257
+ gap: "xs",
258
+ children: [
259
+ /* @__PURE__ */ jsx(IconSettings, {
260
+ size: 48,
261
+ stroke: 1.5,
262
+ color: "var(--mantine-color-dimmed)"
263
+ }),
264
+ /* @__PURE__ */ jsx(Text, {
265
+ c: "dimmed",
266
+ children: "Parameter Management"
267
+ }),
268
+ /* @__PURE__ */ jsx(Text, {
269
+ size: "xs",
270
+ c: "dimmed",
271
+ ta: "center",
272
+ maw: 400,
273
+ children: "Application parameters and configuration settings. Define parameters using the $config primitive to manage dynamic application settings."
274
+ })
275
+ ]
276
+ })
277
+ });
278
+ };
279
+ var AdminParameters_default = AdminParameters;
280
+
281
+ //#endregion
282
+ //#region src/admin/components/AdminVerifications.tsx
283
+ const AdminVerifications = () => {
284
+ return /* @__PURE__ */ jsx(Flex, {
285
+ flex: 1,
286
+ justify: "center",
287
+ align: "center",
288
+ children: /* @__PURE__ */ jsxs(Stack, {
289
+ align: "center",
290
+ gap: "xs",
291
+ children: [
292
+ /* @__PURE__ */ jsx(IconShieldCheck, {
293
+ size: 48,
294
+ stroke: 1.5,
295
+ color: "var(--mantine-color-dimmed)"
296
+ }),
297
+ /* @__PURE__ */ jsx(Text, {
298
+ c: "dimmed",
299
+ children: "Verification Management"
300
+ }),
301
+ /* @__PURE__ */ jsx(Text, {
302
+ size: "xs",
303
+ c: "dimmed",
304
+ ta: "center",
305
+ maw: 400,
306
+ children: "Verifications are automatically managed by the system. Email and SMS verification codes are generated and validated through the verification API endpoints."
307
+ })
308
+ ]
309
+ })
61
310
  });
62
311
  };
312
+ var AdminVerifications_default = AdminVerifications;
63
313
 
64
314
  //#endregion
65
315
  //#region src/admin/index.ts
@@ -70,9 +320,19 @@ var AdminRouter = class {
70
320
  */
71
321
  const AlephaUIAdmin = $module({
72
322
  name: "alepha.ui.admin",
73
- services: [AlephaUI, AdminRouter]
323
+ services: [
324
+ AlephaUI,
325
+ AlephaUIAuth,
326
+ AdminRouter,
327
+ MainRouter,
328
+ AdminSidebar
329
+ ],
330
+ register: (alepha) => {
331
+ alepha.with(AdminRouter);
332
+ alepha.with(AdminSidebar);
333
+ }
74
334
  });
75
335
 
76
336
  //#endregion
77
- export { AdminFiles_default as AdminFiles, AdminJobs_default as AdminJobs, AdminLayout_default as AdminLayout, AdminNotifications_default as AdminNotifications, AdminParameters_default as AdminParameters, AdminRouter, AdminSessions_default as AdminSessions, AdminUsers_default as AdminUsers, AdminVerifications_default as AdminVerifications, AlephaUIAdmin };
337
+ export { AdminFiles_default as AdminFiles, AdminJobs_default as AdminJobs, AdminLayout_default as AdminLayout, AdminNotifications_default as AdminNotifications, AdminParameters_default as AdminParameters, AdminRouter, AdminSessions_default as AdminSessions, AdminSidebar, AdminUserCreate_default as AdminUserCreate, AdminUserDetails_default as AdminUserDetails, AdminUserLayout_default as AdminUserLayout, AdminUserSessions_default as AdminUserSessions, AdminUserSettings_default as AdminUserSettings, AdminUsers_default as AdminUsers, AdminVerifications_default as AdminVerifications, AlephaUIAdmin, MainRouter };
78
338
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/admin/AdminRouter.ts","../../src/admin/index.ts"],"sourcesContent":["import { $page } from \"@alepha/react\";\n\nexport class AdminRouter {\n admin = $page({\n path: \"/admin\",\n label: \"Admin\",\n lazy: () => import(\"./components/AdminLayout.tsx\"),\n });\n\n adminUsers = $page({\n parent: this.admin,\n path: \"/users\",\n label: \"Users\",\n lazy: () => import(\"./components/AdminUsers.tsx\"),\n });\n\n adminNotifications = $page({\n parent: this.admin,\n path: \"/notifications\",\n label: \"Notifications\",\n lazy: () => import(\"./components/AdminNotifications.tsx\"),\n });\n\n adminSessions = $page({\n parent: this.admin,\n path: \"/sessions\",\n label: \"Sessions\",\n lazy: () => import(\"./components/AdminSessions.tsx\"),\n });\n\n adminVerifications = $page({\n parent: this.admin,\n path: \"/verifications\",\n label: \"Verifications\",\n lazy: () => import(\"./components/AdminVerifications.tsx\"),\n });\n\n adminJobs = $page({\n parent: this.admin,\n path: \"/jobs\",\n label: \"Jobs\",\n lazy: () => import(\"./components/AdminJobs.tsx\"),\n });\n\n adminParameters = $page({\n parent: this.admin,\n path: \"/parameters\",\n label: \"Parameters\",\n lazy: () => import(\"./components/AdminParameters.tsx\"),\n });\n\n adminFiles = $page({\n parent: this.admin,\n path: \"/files\",\n label: \"Files\",\n lazy: () => import(\"./components/AdminFiles.tsx\"),\n });\n}\n","import { AlephaUI } from \"@alepha/ui\";\nimport { $module } from \"alepha\";\nimport { AdminRouter } from \"./AdminRouter.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport { AdminRouter } from \"./AdminRouter.ts\";\nexport { default as AdminFiles } from \"./components/AdminFiles.tsx\";\nexport { default as AdminJobs } from \"./components/AdminJobs.tsx\";\nexport { default as AdminLayout } from \"./components/AdminLayout.tsx\";\nexport { default as AdminNotifications } from \"./components/AdminNotifications.tsx\";\nexport { default as AdminParameters } from \"./components/AdminParameters.tsx\";\nexport type { AdminSessionsProps } from \"./components/AdminSessions.tsx\";\nexport { default as AdminSessions } from \"./components/AdminSessions.tsx\";\nexport type { AdminUsersProps } from \"./components/AdminUsers.tsx\";\nexport { default as AdminUsers } from \"./components/AdminUsers.tsx\";\nexport { default as AdminVerifications } from \"./components/AdminVerifications.tsx\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Admin panel UI Module\n *\n * @module alepha.ui.admin\n */\nexport const AlephaUIAdmin = $module({\n name: \"alepha.ui.admin\",\n services: [AlephaUI, AdminRouter],\n});\n"],"mappings":";;;;;;;;;;;;;AAEA,IAAa,cAAb,MAAyB;CACvB,QAAQ,MAAM;EACZ,MAAM;EACN,OAAO;EACP,YAAY,OAAO;EACpB,CAAC;CAEF,aAAa,MAAM;EACjB,QAAQ,KAAK;EACb,MAAM;EACN,OAAO;EACP,YAAY,OAAO;EACpB,CAAC;CAEF,qBAAqB,MAAM;EACzB,QAAQ,KAAK;EACb,MAAM;EACN,OAAO;EACP,YAAY,OAAO;EACpB,CAAC;CAEF,gBAAgB,MAAM;EACpB,QAAQ,KAAK;EACb,MAAM;EACN,OAAO;EACP,YAAY,OAAO;EACpB,CAAC;CAEF,qBAAqB,MAAM;EACzB,QAAQ,KAAK;EACb,MAAM;EACN,OAAO;EACP,YAAY,OAAO;EACpB,CAAC;CAEF,YAAY,MAAM;EAChB,QAAQ,KAAK;EACb,MAAM;EACN,OAAO;EACP,YAAY,OAAO;EACpB,CAAC;CAEF,kBAAkB,MAAM;EACtB,QAAQ,KAAK;EACb,MAAM;EACN,OAAO;EACP,YAAY,OAAO;EACpB,CAAC;CAEF,aAAa,MAAM;EACjB,QAAQ,KAAK;EACb,MAAM;EACN,OAAO;EACP,YAAY,OAAO;EACpB,CAAC;;;;;;;;;;AC/BJ,MAAa,gBAAgB,QAAQ;CACnC,MAAM;CACN,UAAU,CAAC,UAAU,YAAY;CAClC,CAAC"}
1
+ {"version":3,"file":"index.js","names":["filters"],"sources":["../../src/admin/AdminRouter.ts","../../src/admin/MainRouter.ts","../../src/admin/components/AdminJobs.tsx","../../src/admin/components/AdminParameters.tsx","../../src/admin/components/AdminVerifications.tsx","../../src/admin/index.ts"],"sourcesContent":["import { $page, ReactRouter, Redirection } from \"@alepha/react\";\nimport { ReactAuth } from \"@alepha/react/auth\";\nimport { AuthRouter } from \"@alepha/ui/auth\";\nimport {\n IconBell,\n IconDevices,\n IconFile,\n IconPlus,\n IconUser,\n IconUsers,\n} from \"@tabler/icons-react\";\nimport { $inject } from \"alepha\";\nimport type { FileController } from \"alepha/api/files\";\nimport type { NotificationController } from \"alepha/api/notifications\";\nimport type { SessionController, UserController } from \"alepha/api/users\";\nimport { $client } from \"alepha/server/links\";\n\nexport class AdminRouter {\n protected readonly router = $inject(ReactRouter);\n protected readonly authRouter = $inject(AuthRouter);\n protected readonly auth = $inject(ReactAuth);\n protected readonly userCtrl = $client<UserController>();\n protected readonly sessionCtrl = $client<SessionController>();\n protected readonly notificationCtrl = $client<NotificationController>();\n protected readonly fileCtrl = $client<FileController>();\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Layout\n // ─────────────────────────────────────────────────────────────────────────────\n\n public readonly layout = $page({\n name: \"AdminLayout\",\n path: \"/admin\",\n label: \"Admin\",\n lazy: () => import(\"./components/AdminLayout.tsx\"),\n resolve: ({ user, url }) => {\n if (!user) {\n throw new Redirection(\n this.router.path(this.authRouter.login.name, {\n query: {\n r: url.pathname,\n },\n }),\n );\n }\n return {};\n },\n });\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Users\n // ─────────────────────────────────────────────────────────────────────────────\n\n public readonly adminUsers = $page({\n icon: IconUsers,\n parent: this.layout,\n path: \"/users\",\n label: \"Users\",\n description: \"Manage application users and their roles.\",\n lazy: () => import(\"./components/AdminUsers.tsx\"),\n can: () => this.userCtrl.findUsers.can(),\n });\n\n public readonly adminUserCreate = $page({\n icon: IconPlus,\n parent: this.layout,\n path: \"/users/create\",\n label: \"Create User\",\n description: \"Create a new user account.\",\n lazy: () => import(\"./components/AdminUserCreate.tsx\"),\n can: () => this.userCtrl.createUser.can(),\n });\n\n public readonly adminUserLayout = $page({\n icon: IconUser,\n parent: this.layout,\n path: \"/users/:userId\",\n label: \"User\",\n lazy: () => import(\"./components/AdminUserLayout.tsx\"),\n can: () => this.userCtrl.getUser.can(),\n });\n\n public readonly adminUserDetails = $page({\n parent: this.adminUserLayout,\n path: \"/details\",\n label: \"Details\",\n lazy: () => import(\"./components/AdminUserDetails.tsx\"),\n });\n\n public readonly adminUserSessions = $page({\n parent: this.adminUserLayout,\n path: \"/sessions\",\n label: \"Sessions\",\n lazy: () => import(\"./components/AdminUserSessions.tsx\"),\n });\n\n public readonly adminUserSettings = $page({\n parent: this.adminUserLayout,\n path: \"/settings\",\n label: \"Settings\",\n lazy: () => import(\"./components/AdminUserSettings.tsx\"),\n });\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Sessions\n // ─────────────────────────────────────────────────────────────────────────────\n\n public readonly adminSessions = $page({\n icon: IconDevices,\n parent: this.layout,\n path: \"/sessions\",\n label: \"Sessions\",\n description: \"View and manage all active sessions.\",\n lazy: () => import(\"./components/AdminSessions.tsx\"),\n can: () => this.sessionCtrl.findSessions.can(),\n });\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Notifications\n // ─────────────────────────────────────────────────────────────────────────────\n\n public readonly adminNotifications = $page({\n icon: IconBell,\n parent: this.layout,\n path: \"/notifications\",\n label: \"Notifications\",\n description: \"View notification history and status.\",\n lazy: () => import(\"./components/AdminNotifications.tsx\"),\n can: () => this.notificationCtrl.findNotifications.can(),\n });\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Files\n // ─────────────────────────────────────────────────────────────────────────────\n\n public readonly adminFiles = $page({\n icon: IconFile,\n parent: this.layout,\n path: \"/files\",\n label: \"Files\",\n description: \"Manage uploaded files and storage.\",\n lazy: () => import(\"./components/AdminFiles.tsx\"),\n can: () => this.fileCtrl.findFiles.can(),\n });\n}\n","import { $page } from \"@alepha/react\";\nimport { AlephaMantineProvider } from \"@alepha/ui\";\nimport { AuthRouter } from \"@alepha/ui/auth\";\nimport { $inject } from \"alepha\";\nimport { AdminRouter } from \"./AdminRouter.ts\";\n\n/**\n * Main application router that combines Auth and Admin routers.\n *\n * We assume that the main application router will always have Admin and Auth routers.\n *\n * This is basically a convenience class to avoid having to inject these routers everywhere.\n * Code is lightweight enough that we can just copy it if needed.\n */\nexport class MainRouter {\n auth = $inject(AuthRouter);\n admin = $inject(AdminRouter);\n\n layout = $page({\n component: AlephaMantineProvider,\n children: () => [this.auth.layout, this.admin.layout],\n });\n}\n","import { useClient } from \"@alepha/react\";\nimport { useI18n } from \"@alepha/react/i18n\";\nimport { DataTable, Flex, Text } from \"@alepha/ui\";\nimport { Badge } from \"@mantine/core\";\nimport {\n IconCheck,\n IconClock,\n IconPlayerPlay,\n IconX,\n} from \"@tabler/icons-react\";\nimport { type Page, t } from \"alepha\";\nimport {\n type JobController,\n type JobExecutionEntity,\n jobExecutions,\n} from \"alepha/api/jobs\";\n\nconst AdminJobs = () => {\n const client = useClient<JobController>();\n const { l } = useI18n();\n\n const filters = t.object({\n job: t.optional(\n t.string({\n $control: {\n query: t.pick(jobExecutions.schema, [\"job\"]),\n },\n }),\n ),\n status: t.optional(t.enum([\"STARTED\", \"FAILED\", \"COMPLETED\"])),\n });\n\n const getStatusColor = (status: string) => {\n switch (status) {\n case \"COMPLETED\":\n return \"green\";\n case \"FAILED\":\n return \"red\";\n case \"STARTED\":\n return \"blue\";\n default:\n return \"gray\";\n }\n };\n\n const getStatusIcon = (status: string) => {\n switch (status) {\n case \"COMPLETED\":\n return <IconCheck size={12} />;\n case \"FAILED\":\n return <IconX size={12} />;\n case \"STARTED\":\n return <IconPlayerPlay size={12} />;\n default:\n return <IconClock size={12} />;\n }\n };\n\n const formatDuration = (\n start: Date | string,\n end?: Date | string | null,\n ): string => {\n const startTime = new Date(start).getTime();\n const endTime = end ? new Date(end).getTime() : Date.now();\n const duration = endTime - startTime;\n\n if (duration < 1000) return `${duration}ms`;\n if (duration < 60000) return `${(duration / 1000).toFixed(1)}s`;\n return `${Math.floor(duration / 60000)}m ${Math.floor((duration % 60000) / 1000)}s`;\n };\n\n return (\n <Flex flex={1}>\n <DataTable<JobExecutionEntity, typeof filters>\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 === \"job\" || key === \"status\") {\n return form.submit();\n }\n }}\n filters={filters}\n items={async (filters) => {\n const response = await client.getJobExecutions({\n query: filters,\n });\n\n return response as Page<JobExecutionEntity>;\n }}\n columns={{\n job: {\n label: \"Job\",\n value: (item) => (\n <Text size=\"sm\" fw={500}>\n {item.job}\n </Text>\n ),\n },\n status: {\n label: \"Status\",\n fit: true,\n value: (item) => (\n <Badge\n size=\"sm\"\n variant=\"light\"\n color={getStatusColor(item.status)}\n leftSection={getStatusIcon(item.status)}\n >\n {item.status}\n </Badge>\n ),\n },\n duration: {\n label: \"Duration\",\n fit: true,\n value: (item) => (\n <Text size=\"xs\" c=\"dimmed\" ff=\"monospace\">\n {formatDuration(item.createdAt, item.finishedAt)}\n </Text>\n ),\n },\n error: {\n label: \"Error\",\n value: (item) =>\n item.error ? (\n <Text size=\"xs\" c=\"red\" lineClamp={1}>\n {item.error}\n </Text>\n ) : (\n <Text size=\"xs\" c=\"dimmed\">\n -\n </Text>\n ),\n },\n createdAt: {\n label: \"Started\",\n fit: true,\n value: (item) => (\n <Text size=\"xs\" c=\"dimmed\">\n {l(item.createdAt, { date: \"fromNow\" })}\n </Text>\n ),\n },\n }}\n />\n </Flex>\n );\n};\n\nexport default AdminJobs;\n","import { Flex, Text } from \"@alepha/ui\";\nimport { Stack } from \"@mantine/core\";\nimport { IconSettings } from \"@tabler/icons-react\";\n\nconst AdminParameters = () => {\n return (\n <Flex flex={1} justify=\"center\" align=\"center\">\n <Stack align=\"center\" gap=\"xs\">\n <IconSettings\n size={48}\n stroke={1.5}\n color=\"var(--mantine-color-dimmed)\"\n />\n <Text c=\"dimmed\">Parameter Management</Text>\n <Text size=\"xs\" c=\"dimmed\" ta=\"center\" maw={400}>\n Application parameters and configuration settings. Define parameters\n using the $config primitive to manage dynamic application settings.\n </Text>\n </Stack>\n </Flex>\n );\n};\n\nexport default AdminParameters;\n","import { Flex, Text } from \"@alepha/ui\";\nimport { Stack } from \"@mantine/core\";\nimport { IconShieldCheck } from \"@tabler/icons-react\";\n\nconst AdminVerifications = () => {\n return (\n <Flex flex={1} justify=\"center\" align=\"center\">\n <Stack align=\"center\" gap=\"xs\">\n <IconShieldCheck\n size={48}\n stroke={1.5}\n color=\"var(--mantine-color-dimmed)\"\n />\n <Text c=\"dimmed\">Verification Management</Text>\n <Text size=\"xs\" c=\"dimmed\" ta=\"center\" maw={400}>\n Verifications are automatically managed by the system. Email and SMS\n verification codes are generated and validated through the\n verification API endpoints.\n </Text>\n </Stack>\n </Flex>\n );\n};\n\nexport default AdminVerifications;\n","import { AlephaUI } from \"@alepha/ui\";\nimport { AlephaUIAuth } from \"@alepha/ui/auth\";\nimport { $module } from \"alepha\";\nimport { AdminRouter } from \"./AdminRouter.ts\";\nimport { AdminSidebar } from \"./AdminSidebar.ts\";\nimport { MainRouter } from \"./MainRouter.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport { AdminRouter } from \"./AdminRouter.ts\";\nexport { AdminSidebar } from \"./AdminSidebar.ts\";\nexport { default as AdminFiles } from \"./components/AdminFiles.tsx\";\nexport { default as AdminJobs } from \"./components/AdminJobs.tsx\";\nexport { default as AdminLayout } from \"./components/AdminLayout.tsx\";\nexport { default as AdminNotifications } from \"./components/AdminNotifications.tsx\";\nexport { default as AdminParameters } from \"./components/AdminParameters.tsx\";\nexport { default as AdminSessions } from \"./components/AdminSessions.tsx\";\nexport { default as AdminUserCreate } from \"./components/AdminUserCreate.tsx\";\nexport { default as AdminUserDetails } from \"./components/AdminUserDetails.tsx\";\nexport { default as AdminUserLayout } from \"./components/AdminUserLayout.tsx\";\nexport { default as AdminUserSessions } from \"./components/AdminUserSessions.tsx\";\nexport { default as AdminUserSettings } from \"./components/AdminUserSettings.tsx\";\nexport { default as AdminUsers } from \"./components/AdminUsers.tsx\";\nexport { default as AdminVerifications } from \"./components/AdminVerifications.tsx\";\nexport { MainRouter } from \"./MainRouter.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Admin panel UI Module\n *\n * @module alepha.ui.admin\n */\nexport const AlephaUIAdmin = $module({\n name: \"alepha.ui.admin\",\n services: [AlephaUI, AlephaUIAuth, AdminRouter, MainRouter, AdminSidebar],\n register: (alepha) => {\n alepha.with(AdminRouter);\n alepha.with(AdminSidebar);\n },\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAiBA,IAAa,cAAb,MAAyB;CACvB,AAAmB,SAAS,QAAQ,YAAY;CAChD,AAAmB,aAAa,QAAQ,WAAW;CACnD,AAAmB,OAAO,QAAQ,UAAU;CAC5C,AAAmB,WAAW,SAAyB;CACvD,AAAmB,cAAc,SAA4B;CAC7D,AAAmB,mBAAmB,SAAiC;CACvE,AAAmB,WAAW,SAAyB;CAMvD,AAAgB,SAAS,MAAM;EAC7B,MAAM;EACN,MAAM;EACN,OAAO;EACP,YAAY,OAAO;EACnB,UAAU,EAAE,MAAM,UAAU;AAC1B,OAAI,CAAC,KACH,OAAM,IAAI,YACR,KAAK,OAAO,KAAK,KAAK,WAAW,MAAM,MAAM,EAC3C,OAAO,EACL,GAAG,IAAI,UACR,EACF,CAAC,CACH;AAEH,UAAO,EAAE;;EAEZ,CAAC;CAMF,AAAgB,aAAa,MAAM;EACjC,MAAM;EACN,QAAQ,KAAK;EACb,MAAM;EACN,OAAO;EACP,aAAa;EACb,YAAY,OAAO;EACnB,WAAW,KAAK,SAAS,UAAU,KAAK;EACzC,CAAC;CAEF,AAAgB,kBAAkB,MAAM;EACtC,MAAM;EACN,QAAQ,KAAK;EACb,MAAM;EACN,OAAO;EACP,aAAa;EACb,YAAY,OAAO;EACnB,WAAW,KAAK,SAAS,WAAW,KAAK;EAC1C,CAAC;CAEF,AAAgB,kBAAkB,MAAM;EACtC,MAAM;EACN,QAAQ,KAAK;EACb,MAAM;EACN,OAAO;EACP,YAAY,OAAO;EACnB,WAAW,KAAK,SAAS,QAAQ,KAAK;EACvC,CAAC;CAEF,AAAgB,mBAAmB,MAAM;EACvC,QAAQ,KAAK;EACb,MAAM;EACN,OAAO;EACP,YAAY,OAAO;EACpB,CAAC;CAEF,AAAgB,oBAAoB,MAAM;EACxC,QAAQ,KAAK;EACb,MAAM;EACN,OAAO;EACP,YAAY,OAAO;EACpB,CAAC;CAEF,AAAgB,oBAAoB,MAAM;EACxC,QAAQ,KAAK;EACb,MAAM;EACN,OAAO;EACP,YAAY,OAAO;EACpB,CAAC;CAMF,AAAgB,gBAAgB,MAAM;EACpC,MAAM;EACN,QAAQ,KAAK;EACb,MAAM;EACN,OAAO;EACP,aAAa;EACb,YAAY,OAAO;EACnB,WAAW,KAAK,YAAY,aAAa,KAAK;EAC/C,CAAC;CAMF,AAAgB,qBAAqB,MAAM;EACzC,MAAM;EACN,QAAQ,KAAK;EACb,MAAM;EACN,OAAO;EACP,aAAa;EACb,YAAY,OAAO;EACnB,WAAW,KAAK,iBAAiB,kBAAkB,KAAK;EACzD,CAAC;CAMF,AAAgB,aAAa,MAAM;EACjC,MAAM;EACN,QAAQ,KAAK;EACb,MAAM;EACN,OAAO;EACP,aAAa;EACb,YAAY,OAAO;EACnB,WAAW,KAAK,SAAS,UAAU,KAAK;EACzC,CAAC;;;;;;;;;;;;;ACjIJ,IAAa,aAAb,MAAwB;CACtB,OAAO,QAAQ,WAAW;CAC1B,QAAQ,QAAQ,YAAY;CAE5B,SAAS,MAAM;EACb,WAAW;EACX,gBAAgB,CAAC,KAAK,KAAK,QAAQ,KAAK,MAAM,OAAO;EACtD,CAAC;;;;;ACJJ,MAAM,kBAAkB;CACtB,MAAM,SAAS,WAA0B;CACzC,MAAM,EAAE,MAAM,SAAS;CAEvB,MAAM,UAAU,EAAE,OAAO;EACvB,KAAK,EAAE,SACL,EAAE,OAAO,EACP,UAAU,EACR,OAAO,EAAE,KAAK,cAAc,QAAQ,CAAC,MAAM,CAAC,EAC7C,EACF,CAAC,CACH;EACD,QAAQ,EAAE,SAAS,EAAE,KAAK;GAAC;GAAW;GAAU;GAAY,CAAC,CAAC;EAC/D,CAAC;CAEF,MAAM,kBAAkB,WAAmB;AACzC,UAAQ,QAAR;GACE,KAAK,YACH,QAAO;GACT,KAAK,SACH,QAAO;GACT,KAAK,UACH,QAAO;GACT,QACE,QAAO;;;CAIb,MAAM,iBAAiB,WAAmB;AACxC,UAAQ,QAAR;GACE,KAAK,YACH,QAAO,oBAAC,aAAU,MAAM,KAAM;GAChC,KAAK,SACH,QAAO,oBAAC,SAAM,MAAM,KAAM;GAC5B,KAAK,UACH,QAAO,oBAAC,kBAAe,MAAM,KAAM;GACrC,QACE,QAAO,oBAAC,aAAU,MAAM,KAAM;;;CAIpC,MAAM,kBACJ,OACA,QACW;EACX,MAAM,YAAY,IAAI,KAAK,MAAM,CAAC,SAAS;EAE3C,MAAM,YADU,MAAM,IAAI,KAAK,IAAI,CAAC,SAAS,GAAG,KAAK,KAAK,IAC/B;AAE3B,MAAI,WAAW,IAAM,QAAO,GAAG,SAAS;AACxC,MAAI,WAAW,IAAO,QAAO,IAAI,WAAW,KAAM,QAAQ,EAAE,CAAC;AAC7D,SAAO,GAAG,KAAK,MAAM,WAAW,IAAM,CAAC,IAAI,KAAK,MAAO,WAAW,MAAS,IAAK,CAAC;;AAGnF,QACE,oBAAC;EAAK,MAAM;YACV,oBAAC;GACC;GACA,aAAa;GACb,eAAe;IACb,kBAAkB;IAClB,SAAS;IACV;GACD,YAAY;IACV,mBAAmB;IACnB,iBAAiB;IAClB;GACD,iBAAiB,KAAK,QAAQ,SAAS;AACrC,QAAI,QAAQ,SAAS,QAAQ,SAC3B,QAAO,KAAK,QAAQ;;GAGf;GACT,OAAO,OAAO,cAAY;AAKxB,WAJiB,MAAM,OAAO,iBAAiB,EAC7C,OAAOA,WACR,CAAC;;GAIJ,SAAS;IACP,KAAK;KACH,OAAO;KACP,QAAQ,SACN,oBAAC;MAAK,MAAK;MAAK,IAAI;gBACjB,KAAK;OACD;KAEV;IACD,QAAQ;KACN,OAAO;KACP,KAAK;KACL,QAAQ,SACN,oBAAC;MACC,MAAK;MACL,SAAQ;MACR,OAAO,eAAe,KAAK,OAAO;MAClC,aAAa,cAAc,KAAK,OAAO;gBAEtC,KAAK;OACA;KAEX;IACD,UAAU;KACR,OAAO;KACP,KAAK;KACL,QAAQ,SACN,oBAAC;MAAK,MAAK;MAAK,GAAE;MAAS,IAAG;gBAC3B,eAAe,KAAK,WAAW,KAAK,WAAW;OAC3C;KAEV;IACD,OAAO;KACL,OAAO;KACP,QAAQ,SACN,KAAK,QACH,oBAAC;MAAK,MAAK;MAAK,GAAE;MAAM,WAAW;gBAChC,KAAK;OACD,GAEP,oBAAC;MAAK,MAAK;MAAK,GAAE;gBAAS;OAEpB;KAEZ;IACD,WAAW;KACT,OAAO;KACP,KAAK;KACL,QAAQ,SACN,oBAAC;MAAK,MAAK;MAAK,GAAE;gBACf,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;OAClC;KAEV;IACF;IACD;GACG;;AAIX,wBAAe;;;;ACzJf,MAAM,wBAAwB;AAC5B,QACE,oBAAC;EAAK,MAAM;EAAG,SAAQ;EAAS,OAAM;YACpC,qBAAC;GAAM,OAAM;GAAS,KAAI;;IACxB,oBAAC;KACC,MAAM;KACN,QAAQ;KACR,OAAM;MACN;IACF,oBAAC;KAAK,GAAE;eAAS;MAA2B;IAC5C,oBAAC;KAAK,MAAK;KAAK,GAAE;KAAS,IAAG;KAAS,KAAK;eAAK;MAG1C;;IACD;GACH;;AAIX,8BAAe;;;;ACnBf,MAAM,2BAA2B;AAC/B,QACE,oBAAC;EAAK,MAAM;EAAG,SAAQ;EAAS,OAAM;YACpC,qBAAC;GAAM,OAAM;GAAS,KAAI;;IACxB,oBAAC;KACC,MAAM;KACN,QAAQ;KACR,OAAM;MACN;IACF,oBAAC;KAAK,GAAE;eAAS;MAA8B;IAC/C,oBAAC;KAAK,MAAK;KAAK,GAAE;KAAS,IAAG;KAAS,KAAK;eAAK;MAI1C;;IACD;GACH;;AAIX,iCAAe;;;;;;;;;ACSf,MAAa,gBAAgB,QAAQ;CACnC,MAAM;CACN,UAAU;EAAC;EAAU;EAAc;EAAa;EAAY;EAAa;CACzE,WAAW,WAAW;AACpB,SAAO,KAAK,YAAY;AACxB,SAAO,KAAK,aAAa;;CAE5B,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { NestedView } from "@alepha/react";
2
+ import { Flex } from "@mantine/core";
3
+ import { jsx } from "react/jsx-runtime";
4
+
5
+ //#region src/auth/components/AuthLayout.tsx
6
+ const AuthLayout = () => {
7
+ return /* @__PURE__ */ jsx(Flex, {
8
+ flex: 1,
9
+ align: "center",
10
+ h: "100vh",
11
+ justify: "center",
12
+ children: /* @__PURE__ */ jsx(NestedView, {})
13
+ });
14
+ };
15
+ var AuthLayout_default = AuthLayout;
16
+
17
+ //#endregion
18
+ export { AuthLayout_default as default };
19
+ //# sourceMappingURL=AuthLayout-BSL8ZHgr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthLayout-BSL8ZHgr.js","names":[],"sources":["../../src/auth/components/AuthLayout.tsx"],"sourcesContent":["import { NestedView } from \"@alepha/react\";\nimport { Flex } from \"@mantine/core\";\n\nconst AuthLayout = () => {\n return (\n <Flex flex={1} align={\"center\"} h={\"100vh\"} justify={\"center\"}>\n <NestedView />\n </Flex>\n );\n};\n\nexport default AuthLayout;\n"],"mappings":";;;;;AAGA,MAAM,mBAAmB;AACvB,QACE,oBAAC;EAAK,MAAM;EAAG,OAAO;EAAU,GAAG;EAAS,SAAS;YACnD,oBAAC,eAAa;GACT;;AAIX,yBAAe"}
@@ -4,8 +4,8 @@ import { useI18n } from "@alepha/react/i18n";
4
4
  import { ActionButton, Control, capitalize } from "@alepha/ui";
5
5
  import { t } from "alepha";
6
6
  import { useRouter } from "@alepha/react";
7
- import { Card, Flex, Group, Stack, Text } from "@mantine/core";
8
7
  import { IconLock, IconUser } from "@tabler/icons-react";
8
+ import { Card, Flex, Group, Stack, Text } from "@mantine/core";
9
9
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
10
10
  import { FormValidationError, useForm } from "@alepha/react/form";
11
11
  import { HttpError } from "alepha/server";
@@ -16,7 +16,7 @@ const Login = (props) => {
16
16
  const auth = useAuth();
17
17
  const router = useRouter();
18
18
  const { tr } = useI18n();
19
- const redirect = router.query.redirect || "/";
19
+ const redirect = router.query.r || "/";
20
20
  const hasUsernamePassword = props.realmConfig.authenticationMethods.find((it) => it.type === "CREDENTIALS");
21
21
  const settings = props.realmConfig.settings;
22
22
  const loginMethods = useMemo(() => {
@@ -95,6 +95,7 @@ const Login = (props) => {
95
95
  password: { autoComplete: "current-password" }
96
96
  }),
97
97
  /* @__PURE__ */ jsx(ActionButton, {
98
+ color: "blue",
98
99
  variant: "filled",
99
100
  form,
100
101
  children: tr("loginSignIn")
@@ -142,7 +143,7 @@ const Login = (props) => {
142
143
  children: tr("loginContinueWith", { args: [capitalize(method.name)] })
143
144
  }, method.type))
144
145
  }),
145
- /* @__PURE__ */ jsxs(Text, {
146
+ settings.registrationAllowed && /* @__PURE__ */ jsxs(Text, {
146
147
  size: "sm",
147
148
  ta: "center",
148
149
  children: [
@@ -159,7 +160,7 @@ const Login = (props) => {
159
160
  })
160
161
  }), /* @__PURE__ */ jsx(ActionButton, {
161
162
  variant: "subtle",
162
- href: redirect,
163
+ href: "/",
163
164
  children: tr("loginCancel")
164
165
  })]
165
166
  })
@@ -173,4 +174,4 @@ const leftSection = (name) => {
173
174
 
174
175
  //#endregion
175
176
  export { Login_default as t };
176
- //# sourceMappingURL=Login-OCrvjs9U.js.map
177
+ //# sourceMappingURL=Login-AlVPPqQp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Login-AlVPPqQp.js","names":["IconGoogle","IconGithub"],"sources":["../../src/auth/components/Login.tsx"],"sourcesContent":["import { useRouter } from \"@alepha/react\";\nimport { useAuth } from \"@alepha/react/auth\";\nimport { FormValidationError, useForm } from \"@alepha/react/form\";\nimport { useI18n } from \"@alepha/react/i18n\";\nimport { ActionButton, Control, capitalize } from \"@alepha/ui\";\nimport { Card, Flex, Group, Stack, Text } from \"@mantine/core\";\nimport { IconLock, IconUser } from \"@tabler/icons-react\";\nimport { t } from \"alepha\";\nimport type { UserRealmConfig } from \"alepha/api/users\";\nimport { HttpError } from \"alepha/server\";\nimport { useMemo } from \"react\";\nimport type { AuthI18n } from \"../AuthI18n.ts\";\nimport type { AuthRouter } from \"../AuthRouter.ts\";\nimport IconGithub from \"./icons/IconGithub.tsx\";\nimport IconGoogle from \"./icons/IconGoogle.tsx\";\n\nexport interface LoginProps {\n realmConfig: UserRealmConfig;\n}\n\nconst Login = (props: LoginProps) => {\n const auth = useAuth();\n const router = useRouter<AuthRouter>();\n const { tr } = useI18n<AuthI18n, \"en\">();\n const redirect = router.query.r || \"/\";\n\n const hasUsernamePassword = props.realmConfig.authenticationMethods.find(\n (it) => it.type === \"CREDENTIALS\",\n );\n\n const settings = props.realmConfig.settings;\n\n // Determine what login methods are available\n const loginMethods = useMemo(() => {\n const methods = [];\n if (settings.usernameEnabled !== false) methods.push(\"username\");\n if (settings.emailEnabled !== false) methods.push(\"email\");\n if (settings.phoneEnabled === true) methods.push(\"phone\");\n return methods;\n }, [settings]);\n\n // Create identifier title based on enabled methods\n const identifierTitle = useMemo(() => {\n if (loginMethods.length === 0) return tr(\"loginUsername\");\n if (loginMethods.length === 1) {\n if (loginMethods[0] === \"username\") return tr(\"loginUsername\");\n if (loginMethods[0] === \"email\") return tr(\"loginEmail\");\n if (loginMethods[0] === \"phone\") return tr(\"loginPhone\");\n }\n const labels = loginMethods.map((m) => {\n if (m === \"username\") return tr(\"loginUsername\").toLowerCase();\n if (m === \"email\") return tr(\"loginEmail\").toLowerCase();\n if (m === \"phone\") return tr(\"loginPhone\").toLowerCase();\n return m;\n });\n return capitalize(\n `${labels.slice(0, -1).join(\", \")} or ${labels[labels.length - 1]}`,\n );\n }, [loginMethods, tr]);\n\n const form = useForm({\n schema: t.object({\n identifier: t.string({\n minLength: 1,\n }),\n password: t.string({\n minLength: settings.passwordPolicy?.minLength || 6,\n }),\n }),\n handler: async (data) => {\n try {\n await auth.login(\"credentials\", {\n username: data.identifier,\n password: data.password,\n });\n await router.go(router.query.r || \"/\");\n } catch (error) {\n if (\n error instanceof HttpError &&\n error.error === \"InvalidCredentialsError\"\n ) {\n throw new FormValidationError({\n message: \"Invalid identifier or password\",\n path: \"/password\",\n });\n }\n throw error;\n }\n },\n });\n\n return (\n <Flex flex={1} justify={\"center\"} align={\"center\"}>\n <Stack gap={\"sm\"} w={360}>\n <Card withBorder p={\"lg\"} bg={\"var(--alepha-elevated)\"}>\n <Stack gap={\"md\"}>\n {hasUsernamePassword && (\n <>\n <form {...form.props}>\n <Stack flex={1} gap={\"md\"}>\n <Control\n title={identifierTitle}\n input={form.input.identifier}\n icon={IconUser}\n text={{\n autoComplete: loginMethods.includes(\"email\")\n ? \"email\"\n : \"username\",\n }}\n />\n <Control\n title={tr(\"loginPassword\")}\n input={form.input.password}\n icon={IconLock}\n password={{\n autoComplete: \"current-password\",\n }}\n />\n <ActionButton color={\"blue\"} variant={\"filled\"} form={form}>\n {tr(\"loginSignIn\")}\n </ActionButton>\n </Stack>\n </form>\n <Stack gap=\"xs\">\n {settings.resetPasswordAllowed && (\n <Text size=\"sm\" ta=\"center\">\n <ActionButton\n href={router.path(\"resetPassword\")}\n anchorProps={{ inherit: true }}\n >\n {tr(\"loginForgotPassword\")}\n </ActionButton>\n </Text>\n )}\n <Group align=\"center\" justify=\"center\" gap={\"md\"}>\n <Flex flex={1} h={\"1px\"} bg={\"var(--alepha-text-muted)\"} />\n <Text size=\"xs\">{tr(\"loginOr\")}</Text>\n <Flex flex={1} h={\"1px\"} bg={\"var(--alepha-text-muted)\"} />\n </Group>\n </Stack>\n </>\n )}\n <Stack gap={\"sm\"}>\n {props.realmConfig.authenticationMethods.map(\n (method) =>\n method.type !== \"CREDENTIALS\" && (\n <ActionButton\n variant={\"default\"}\n key={method.type}\n leftSection={leftSection(method.name.toLowerCase())}\n onClick={() =>\n auth.login(method.name, {\n redirect,\n })\n }\n >\n {tr(\"loginContinueWith\", {\n args: [capitalize(method.name)],\n })}\n </ActionButton>\n ),\n )}\n </Stack>\n {settings.registrationAllowed && (\n <Text size=\"sm\" ta=\"center\">\n {tr(\"loginNoAccount\")}{\" \"}\n <ActionButton\n href={router.path(\"register\")}\n anchorProps={{ inherit: true }}\n >\n {tr(\"loginSignUp\")}\n </ActionButton>\n </Text>\n )}\n </Stack>\n </Card>\n <ActionButton variant={\"subtle\"} href={\"/\"}>\n {tr(\"loginCancel\")}\n </ActionButton>\n </Stack>\n </Flex>\n );\n};\n\nexport default Login;\n\nconst leftSection = (name: string) => {\n if (name === \"google\") {\n return <IconGoogle />;\n }\n\n if (name === \"github\") {\n return <IconGithub />;\n }\n};\n"],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import "./IconGoogle-v_58os2T.js";
2
+ import { t as Login_default } from "./Login-AlVPPqQp.js";
3
+
4
+ export { Login_default as default };
@@ -4,8 +4,8 @@ import { useI18n } from "@alepha/react/i18n";
4
4
  import { ActionButton, Control, capitalize } from "@alepha/ui";
5
5
  import { TypeBoxError, t } from "alepha";
6
6
  import { useClient, useRouter } from "@alepha/react";
7
- import { Alert, Card, Flex, Group, PinInput, Stack, Text } from "@mantine/core";
8
7
  import { IconAlertCircle, IconLock, IconMail, IconPhone, IconUser } from "@tabler/icons-react";
8
+ import { Alert, Card, Flex, Group, PinInput, Stack, Text } from "@mantine/core";
9
9
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
10
10
  import { useForm } from "@alepha/react/form";
11
11
  import { useMemo, useState } from "react";
@@ -16,7 +16,7 @@ const Register = (props) => {
16
16
  const userCtrl = useClient();
17
17
  const router = useRouter();
18
18
  const { tr } = useI18n();
19
- const redirect = router.query.redirect || "/";
19
+ const redirect = router.query.r || "/";
20
20
  const [registrationState, setRegistrationState] = useState({ phase: "form" });
21
21
  const [emailCode, setEmailCode] = useState("");
22
22
  const [phoneCode, setPhoneCode] = useState("");
@@ -141,7 +141,7 @@ const Register = (props) => {
141
141
  children: [/* @__PURE__ */ jsx(Text, {
142
142
  size: "sm",
143
143
  fw: 500,
144
- children: tr("registerEmailCode") ?? "Email verification code"
144
+ children: tr("registerEmailCode")
145
145
  }), /* @__PURE__ */ jsx(Flex, {
146
146
  justify: "center",
147
147
  children: /* @__PURE__ */ jsx(PinInput, {
@@ -159,7 +159,7 @@ const Register = (props) => {
159
159
  children: [/* @__PURE__ */ jsx(Text, {
160
160
  size: "sm",
161
161
  fw: 500,
162
- children: tr("registerPhoneCode") ?? "Phone verification code"
162
+ children: tr("registerPhoneCode")
163
163
  }), /* @__PURE__ */ jsx(Flex, {
164
164
  justify: "center",
165
165
  children: /* @__PURE__ */ jsx(PinInput, {
@@ -173,10 +173,11 @@ const Register = (props) => {
173
173
  })]
174
174
  }),
175
175
  /* @__PURE__ */ jsx(ActionButton, {
176
+ color: "blue",
176
177
  onClick: handleVerificationSubmit,
177
178
  loading: isSubmitting,
178
179
  disabled: !canSubmitVerification(),
179
- children: tr("registerVerifySubmit") ?? "Complete Registration"
180
+ children: tr("registerVerifySubmit")
180
181
  }),
181
182
  /* @__PURE__ */ jsx(ActionButton, {
182
183
  variant: "subtle",
@@ -253,6 +254,8 @@ const Register = (props) => {
253
254
  }),
254
255
  /* @__PURE__ */ jsx(ActionButton, {
255
256
  form,
257
+ color: "blue",
258
+ variant: "filled",
256
259
  children: tr("registerCreateAccount")
257
260
  })
258
261
  ]
@@ -315,4 +318,4 @@ const leftSection = (name) => {
315
318
 
316
319
  //#endregion
317
320
  export { Register_default as t };
318
- //# sourceMappingURL=Register-Ei34GSba.js.map
321
+ //# sourceMappingURL=Register-BxJmOqpF.js.map