@firecms/user_management 3.0.0-beta.8 → 3.0.0-beta.9

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/index.es.js CHANGED
@@ -1,319 +1,476 @@
1
- import F, { useEffect as ce, useCallback as k, useContext as Fe, useState as A } from "react";
2
- import { getFirestore as Y, onSnapshot as ue, collection as ee, setDoc as me, doc as H, addDoc as Ae, deleteDoc as he } from "@firebase/firestore";
3
- import { jsx as e, jsxs as s, Fragment as K } from "react/jsx-runtime";
4
- import { getColorSchemeForSeed as Pe, Chip as Te, Dialog as fe, DialogContent as ge, Typography as P, TextField as Q, Paper as pe, Table as re, TableHeader as ie, TableCell as d, TableBody as oe, TableRow as W, Tooltip as V, Checkbox as I, Select as ne, SelectItem as L, DialogActions as Ce, Button as O, LoadingButton as ve, DoneIcon as we, IconButton as ye, DeleteIcon as be, CenteredView as Ne, Container as Ue, AddIcon as le, MultiSelect as Le, MultiSelectItem as Be } from "@firecms/ui";
5
- import * as M from "yup";
6
- import { toSnakeCase as _e, FieldCaption as B, DeleteConfirmationDialog as xe, useNavigationController as Ve, useSnackbarController as se, useAuthController as ae, useCustomizationController as Me, defaultDateFormat as Oe } from "@firecms/core";
7
- import { useCreateFormex as Re, getIn as J, Formex as De } from "@firecms/formex";
8
- import { format as $e } from "date-fns";
9
- import * as qe from "date-fns/locale";
10
- const gn = ["Admin"], Ye = {
11
- read: !1,
12
- edit: !1,
13
- create: !1,
14
- delete: !1
1
+ import React, { useEffect, useCallback, useContext, useState } from "react";
2
+ import equal from "react-fast-compare";
3
+ import { removeUndefined, useAuthController, toSnakeCase, FieldCaption, DeleteConfirmationDialog, useNavigationController, useSnackbarController, useCustomizationController, defaultDateFormat } from "@firecms/core";
4
+ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
5
+ import { getColorSchemeForSeed, Chip, Dialog, DialogContent, Typography, TextField, Paper, Table, TableHeader, TableCell, TableBody, TableRow, Tooltip, Checkbox, Button, Select, SelectItem, DialogActions, LoadingButton, DoneIcon, IconButton, DeleteIcon, CenteredView, Container, AddIcon, MultiSelect, MultiSelectItem } from "@firecms/ui";
6
+ import * as Yup from "yup";
7
+ import { useCreateFormex, getIn, Formex } from "@firecms/formex";
8
+ import { format } from "date-fns";
9
+ import * as locales from "date-fns/locale";
10
+ const RESERVED_GROUPS = ["Admin"];
11
+ const DEFAULT_PERMISSIONS = {
12
+ read: false,
13
+ edit: false,
14
+ create: false,
15
+ delete: false
15
16
  };
16
- function We({
17
- collection: t,
18
- user: r
17
+ function resolveUserRolePermissions({
18
+ collection,
19
+ user
19
20
  }) {
20
- const n = r?.roles;
21
- if (n) {
22
- if (t.ownerId === r?.uid)
23
- return {
24
- read: !0,
25
- create: !0,
26
- edit: !0,
27
- delete: !0
28
- };
29
- {
30
- const l = {
31
- read: !1,
32
- create: !1,
33
- edit: !1,
34
- delete: !1
35
- };
36
- return n.map((i) => je(i, t.id)).reduce(te, l);
37
- }
38
- } else return Ye;
21
+ const roles = user?.roles;
22
+ if (!roles) {
23
+ return DEFAULT_PERMISSIONS;
24
+ } else if (collection.ownerId === user?.uid) {
25
+ return {
26
+ read: true,
27
+ create: true,
28
+ edit: true,
29
+ delete: true
30
+ };
31
+ } else {
32
+ const basePermissions = {
33
+ read: false,
34
+ create: false,
35
+ edit: false,
36
+ delete: false
37
+ };
38
+ return roles.map((role) => resolveCollectionRole(role, collection.id)).reduce(mergePermissions, basePermissions);
39
+ }
39
40
  }
40
- function je(t, r) {
41
- const n = {
42
- read: t.isAdmin || t.defaultPermissions?.read,
43
- create: t.isAdmin || t.defaultPermissions?.create,
44
- edit: t.isAdmin || t.defaultPermissions?.edit,
45
- delete: t.isAdmin || t.defaultPermissions?.delete
41
+ function resolveCollectionRole(role, id) {
42
+ const basePermissions = {
43
+ read: (role.isAdmin || role.defaultPermissions?.read) ?? false,
44
+ create: (role.isAdmin || role.defaultPermissions?.create) ?? false,
45
+ edit: (role.isAdmin || role.defaultPermissions?.edit) ?? false,
46
+ delete: (role.isAdmin || role.defaultPermissions?.delete) ?? false
46
47
  };
47
- return t.collectionPermissions && t.collectionPermissions[r] ? te(t.collectionPermissions[r], n) : t.defaultPermissions ? te(t.defaultPermissions, n) : n;
48
+ const thisCollectionPermissions = role.collectionPermissions?.[id];
49
+ if (thisCollectionPermissions) {
50
+ return mergePermissions(thisCollectionPermissions, basePermissions);
51
+ } else if (role.defaultPermissions) {
52
+ return mergePermissions(role.defaultPermissions, basePermissions);
53
+ } else {
54
+ return basePermissions;
55
+ }
48
56
  }
49
- const te = (t, r) => ({
50
- read: t.read || r.read,
51
- create: t.create || r.create,
52
- edit: t.edit || r.edit,
53
- delete: t.delete || r.delete
54
- });
55
- function pn(t, r) {
56
- return t ? r.roles ? r.roles.map((n) => t.find((l) => l.id === n.id)).filter(Boolean) : [] : void 0;
57
+ const mergePermissions = (permA, permB) => {
58
+ return {
59
+ read: permA.read || permB.read,
60
+ create: permA.create || permB.create,
61
+ edit: permA.edit || permB.edit,
62
+ delete: permA.delete || permB.delete
63
+ };
64
+ };
65
+ function getUserRoles(roles, fireCMSUser) {
66
+ return !roles ? void 0 : fireCMSUser.roles ? fireCMSUser.roles.map((role) => roles.find((r) => r.id === role.id)).filter(Boolean) : [];
57
67
  }
58
- const ze = (t, r) => {
59
- const n = t.map((i) => i.id), l = r.map((i) => i.id);
60
- return n.length === r.length && n.every((i) => l.includes(i));
68
+ const areRolesEqual = (rolesA, rolesB) => {
69
+ const rolesAIds = rolesA.map((r) => r.id);
70
+ const rolesBIds = rolesB.map((r) => r.id);
71
+ return rolesAIds.length === rolesB.length && rolesAIds.every((role) => rolesBIds.includes(role));
61
72
  };
62
- function Cn(t, r) {
63
- if (!r)
73
+ function cacheDelegatedLoginToken(projectId, delegatedToken) {
74
+ if (!delegatedToken) {
64
75
  return;
65
- const n = Je(r), l = new Date(n.exp * 1e3);
66
- localStorage.setItem(`auth_token::${t}`, JSON.stringify({
67
- token: r,
68
- expiry: l
76
+ }
77
+ const data = parseJwt(delegatedToken);
78
+ const expiry = new Date(data.exp * 1e3);
79
+ localStorage.setItem(`auth_token::${projectId}`, JSON.stringify({
80
+ token: delegatedToken,
81
+ expiry
69
82
  }));
70
83
  }
71
- function vn(t) {
72
- const r = localStorage.getItem(`auth_token::${t}`);
73
- if (r) {
74
- const n = JSON.parse(r);
75
- if (n.expiry = new Date(n.expiry), n.expiry > /* @__PURE__ */ new Date())
76
- return n.token;
84
+ function getDelegatedLoginTokenFromCache(projectId) {
85
+ const entry = localStorage.getItem(`auth_token::${projectId}`);
86
+ if (entry) {
87
+ const data = JSON.parse(entry);
88
+ data.expiry = new Date(data.expiry);
89
+ if (data.expiry > /* @__PURE__ */ new Date()) {
90
+ return data.token;
91
+ }
77
92
  }
93
+ return void 0;
78
94
  }
79
- function wn() {
80
- for (let t = 0; t < localStorage.length; t++) {
81
- const r = localStorage.key(t);
82
- r?.startsWith("auth_token::") && localStorage.removeItem(r);
95
+ function clearDelegatedLoginTokensCache() {
96
+ for (let i = 0; i < localStorage.length; i++) {
97
+ const key = localStorage.key(i);
98
+ if (key?.startsWith("auth_token::")) {
99
+ localStorage.removeItem(key);
100
+ }
83
101
  }
84
102
  }
85
- function Je(t) {
86
- if (!t)
103
+ function parseJwt(token) {
104
+ if (!token) {
87
105
  throw new Error("No JWT token");
88
- const n = t.split(".")[1].replace(/-/g, "+").replace(/_/g, "/"), l = decodeURIComponent(window.atob(n).split("").map(function(i) {
89
- return "%" + ("00" + i.charCodeAt(0).toString(16)).slice(-2);
106
+ }
107
+ const base64Url = token.split(".")[1];
108
+ const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
109
+ const jsonPayload = decodeURIComponent(window.atob(base64).split("").map(function(c) {
110
+ return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
90
111
  }).join(""));
91
- return JSON.parse(l);
112
+ return JSON.parse(jsonPayload);
92
113
  }
93
- function yn(t, r = 10) {
94
- if (!/^#([0-9A-Fa-f]{3}){1,2}$/.test(t))
114
+ function darkenColor(hexColor, darkenBy = 10) {
115
+ if (!/^#([0-9A-Fa-f]{3}){1,2}$/.test(hexColor)) {
95
116
  throw new Error("Invalid color format");
96
- let n = t.substring(1).split("");
97
- n.length === 3 && (n = [n[0], n[0], n[1], n[1], n[2], n[2]]);
98
- let l = parseInt(n[0] + n[1], 16), i = parseInt(n[2] + n[3], 16), m = parseInt(n[4] + n[5], 16);
99
- return l = Math.floor(l * (1 - r / 100)), i = Math.floor(i * (1 - r / 100)), m = Math.floor(m * (1 - r / 100)), "#" + (l < 16 ? "0" : "") + l.toString(16) + (i < 16 ? "0" : "") + i.toString(16) + (m < 16 ? "0" : "") + m.toString(16);
117
+ }
118
+ let color = hexColor.substring(1).split("");
119
+ if (color.length === 3) {
120
+ color = [color[0], color[0], color[1], color[1], color[2], color[2]];
121
+ }
122
+ let r = parseInt(color[0] + color[1], 16);
123
+ let g = parseInt(color[2] + color[3], 16);
124
+ let b = parseInt(color[4] + color[5], 16);
125
+ r = Math.floor(r * (1 - darkenBy / 100));
126
+ g = Math.floor(g * (1 - darkenBy / 100));
127
+ b = Math.floor(b * (1 - darkenBy / 100));
128
+ return "#" + (r < 16 ? "0" : "") + r.toString(16) + (g < 16 ? "0" : "") + g.toString(16) + (b < 16 ? "0" : "") + b.toString(16);
100
129
  }
101
- function bn(t, r = 10) {
102
- if (!/^#([0-9A-Fa-f]{3}){1,2}$/.test(t))
130
+ function hexToRgbaWithOpacity(hexColor, opacity = 10) {
131
+ if (!/^#([0-9A-Fa-f]{3}){1,2}$/.test(hexColor)) {
103
132
  throw new Error("Invalid color format");
104
- let n = t.substring(1).split("");
105
- n.length === 3 && (n = [n[0], n[0], n[1], n[1], n[2], n[2]]);
106
- const l = parseInt(n[0] + n[1], 16), i = parseInt(n[2] + n[3], 16), m = parseInt(n[4] + n[5], 16), g = r / 100;
107
- return `rgba(${l}, ${i}, ${m}, ${g})`;
133
+ }
134
+ let color = hexColor.substring(1).split("");
135
+ if (color.length === 3) {
136
+ color = [color[0], color[0], color[1], color[1], color[2], color[2]];
137
+ }
138
+ const r = parseInt(color[0] + color[1], 16);
139
+ const g = parseInt(color[2] + color[3], 16);
140
+ const b = parseInt(color[4] + color[5], 16);
141
+ const alpha = opacity / 100;
142
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`;
108
143
  }
109
- function Nn({
110
- firebaseApp: t,
111
- usersPath: r = "__FIRECMS/config/users",
112
- rolesPath: n = "__FIRECMS/config/roles",
113
- usersLimit: l,
114
- canEditRoles: i = !0,
115
- allowDefaultRolesCreation: m,
116
- includeCollectionConfigPermissions: g
144
+ function useBuildUserManagement({
145
+ dataSourceDelegate,
146
+ usersPath = "__FIRECMS/config/users",
147
+ rolesPath = "__FIRECMS/config/roles",
148
+ usersLimit,
149
+ canEditRoles = true,
150
+ allowDefaultRolesCreation,
151
+ includeCollectionConfigPermissions
117
152
  }) {
118
- const [v, R] = F.useState(!0), [w, c] = F.useState(!0), [E, U] = F.useState([]), [a, C] = F.useState([]), y = a.map((f) => ({
119
- ...f,
120
- roles: E.filter((p) => f.roles?.includes(p.id))
121
- })), [b, _] = F.useState(), [z, u] = F.useState(), h = v || w;
122
- ce(() => {
123
- if (!t || !n) return;
124
- const f = Y(t);
125
- return ue(
126
- ee(f, n),
127
- {
128
- next: (p) => {
129
- _(void 0);
130
- try {
131
- const N = He(p.docs);
132
- U(N);
133
- } catch (N) {
134
- console.error("Error loading roles", N), _(N);
135
- }
136
- R(!1);
137
- },
138
- error: (p) => {
139
- console.error("Error loading roles", p), _(p), R(!1);
153
+ const [rolesLoading, setRolesLoading] = React.useState(true);
154
+ const [usersLoading, setUsersLoading] = React.useState(true);
155
+ const [roles, setRoles] = React.useState([]);
156
+ const [usersWithRoleIds, setUsersWithRoleIds] = React.useState([]);
157
+ const users = usersWithRoleIds.map((u) => ({
158
+ ...u,
159
+ roles: roles.filter((r) => u.roles?.includes(r.id))
160
+ }));
161
+ const [rolesError, setRolesError] = React.useState();
162
+ const [usersError, setUsersError] = React.useState();
163
+ const loading = rolesLoading || usersLoading;
164
+ useEffect(() => {
165
+ if (!dataSourceDelegate || !rolesPath) return;
166
+ if (dataSourceDelegate.initialised !== void 0 && !dataSourceDelegate.initialised) return;
167
+ if (dataSourceDelegate.authenticated !== void 0 && !dataSourceDelegate.authenticated) {
168
+ setRolesLoading(false);
169
+ return;
170
+ }
171
+ setRolesLoading(true);
172
+ return dataSourceDelegate.listenCollection?.({
173
+ path: rolesPath,
174
+ onUpdate(entities) {
175
+ setRolesError(void 0);
176
+ try {
177
+ const newRoles = entityToRoles(entities);
178
+ if (!equal(newRoles, roles))
179
+ setRoles(newRoles);
180
+ } catch (e) {
181
+ setRoles([]);
182
+ console.error("Error loading roles", e);
183
+ setRolesError(e);
140
184
  }
185
+ setRolesLoading(false);
186
+ },
187
+ onError(e) {
188
+ setRoles([]);
189
+ console.error("Error loading roles", e);
190
+ setRolesError(e);
191
+ setRolesLoading(false);
141
192
  }
142
- );
143
- }, [t, n]), ce(() => {
144
- if (!t || !r) return;
145
- const f = Y(t);
146
- return ue(
147
- ee(f, r),
148
- {
149
- next: (p) => {
150
- u(void 0);
151
- try {
152
- const N = Ge(p.docs);
153
- C(N);
154
- } catch (N) {
155
- console.error("Error loading users", N), u(N);
156
- }
157
- c(!1);
158
- },
159
- error: (p) => {
160
- console.error("Error loading users", p), u(p), c(!1);
193
+ });
194
+ }, [dataSourceDelegate?.initialised, dataSourceDelegate?.authenticated, rolesPath]);
195
+ useEffect(() => {
196
+ if (!dataSourceDelegate || !usersPath) return;
197
+ if (dataSourceDelegate.initialised !== void 0 && !dataSourceDelegate.initialised) return;
198
+ if (dataSourceDelegate.authenticated !== void 0 && !dataSourceDelegate.authenticated) {
199
+ setUsersLoading(false);
200
+ return;
201
+ }
202
+ setUsersLoading(true);
203
+ return dataSourceDelegate.listenCollection?.({
204
+ path: usersPath,
205
+ onUpdate(entities) {
206
+ setUsersError(void 0);
207
+ try {
208
+ const newUsers = entitiesToUsers(entities);
209
+ if (!equal(newUsers, usersWithRoleIds))
210
+ setUsersWithRoleIds(newUsers);
211
+ } catch (e) {
212
+ setUsersWithRoleIds([]);
213
+ console.error("Error loading users", e);
214
+ setUsersError(e);
161
215
  }
216
+ setUsersLoading(false);
217
+ },
218
+ onError(e) {
219
+ setUsersWithRoleIds([]);
220
+ console.error("Error loading users", e);
221
+ setUsersError(e);
222
+ setUsersLoading(false);
162
223
  }
163
- );
164
- }, [t, r]);
165
- const x = k(async (f) => {
166
- if (!t) throw Error("useFirestoreUserManagement Firebase not initialised");
167
- const p = Y(t);
168
- if (!p || !r) throw Error("useFirestoreUserManagement Firestore not initialised");
169
- console.debug("Persisting user", f);
170
- const N = f.roles?.map((Ie) => Ie.id), {
171
- uid: q,
172
- ...Z
173
- } = f, de = {
174
- ...Z,
175
- roles: N
224
+ });
225
+ }, [dataSourceDelegate?.initialised, dataSourceDelegate?.authenticated, usersPath]);
226
+ const saveUser = useCallback(async (user) => {
227
+ if (!dataSourceDelegate) throw Error("useBuildUserManagement Firebase not initialised");
228
+ if (!usersPath) throw Error("useBuildUserManagement Firestore not initialised");
229
+ console.debug("Persisting user", user);
230
+ const roleIds = user.roles?.map((r) => r.id);
231
+ const email = user.email?.toLowerCase().trim();
232
+ if (!email) throw Error("Email is required");
233
+ const userExists = users.find((u) => u.email?.toLowerCase() === email);
234
+ const data = {
235
+ ...user,
236
+ roles: roleIds ?? []
176
237
  };
177
- return q ? me(H(p, r, q), de, { merge: !0 }).then(() => f) : Ae(ee(p, r), de).then(() => f);
178
- }, [r, t]), D = k((f) => {
179
- if (!t) throw Error("useFirestoreUserManagement Firebase not initialised");
180
- const p = Y(t);
181
- if (!p || !n) throw Error("useFirestoreUserManagement Firestore not initialised");
182
- console.debug("Persisting role", f);
238
+ if (!userExists) {
239
+ data.created_on = /* @__PURE__ */ new Date();
240
+ }
241
+ return dataSourceDelegate.saveEntity({
242
+ status: "existing",
243
+ path: usersPath,
244
+ entityId: email,
245
+ values: removeUndefined(data)
246
+ }).then(() => user);
247
+ }, [usersPath, dataSourceDelegate?.initialised]);
248
+ const saveRole = useCallback((role) => {
249
+ if (!dataSourceDelegate) throw Error("useBuildUserManagement Firebase not initialised");
250
+ if (!rolesPath) throw Error("useBuildUserManagement Firestore not initialised");
251
+ console.debug("Persisting role", role);
183
252
  const {
184
- id: N,
185
- ...q
186
- } = f, Z = H(p, n, N);
187
- return me(Z, q, { merge: !0 });
188
- }, [n, t]), T = k(async (f) => {
189
- if (!t) throw Error("useFirestoreUserManagement Firebase not initialised");
190
- const p = Y(t);
191
- if (!p || !r) throw Error("useFirestoreUserManagement Firestore not initialised");
192
- console.debug("Deleting", f);
193
- const { uid: N } = f;
194
- return he(H(p, r, N));
195
- }, [r, t]), o = k((f) => {
196
- if (!t) throw Error("useFirestoreUserManagement Firebase not initialised");
197
- const p = Y(t);
198
- if (!p || !n) throw Error("useFirestoreUserManagement Firestore not initialised");
199
- console.debug("Deleting", f);
200
- const { id: N } = f, q = H(p, n, N);
201
- return he(q);
202
- }, [n, t]), S = k(({
203
- collection: f,
204
- user: p
205
- }) => We({
206
- collection: f,
207
- user: p
208
- }), []), $ = k((f) => {
209
- if (!y) throw Error("Users not loaded");
210
- return y.find((N) => N.email?.toLowerCase() === f?.email?.toLowerCase())?.roles;
211
- }, [y]), G = k(({ user: f }) => {
212
- if (console.debug("Authenticating user", f), h)
213
- return console.warn("User management is still loading"), !1;
214
- if (y.length === 0 || y.find((N) => N.email?.toLowerCase() === f?.email?.toLowerCase()))
215
- return !0;
253
+ id,
254
+ ...roleData
255
+ } = role;
256
+ return dataSourceDelegate.saveEntity({
257
+ status: "existing",
258
+ path: rolesPath,
259
+ entityId: id,
260
+ values: removeUndefined(roleData)
261
+ }).then(() => {
262
+ return;
263
+ });
264
+ }, [rolesPath, dataSourceDelegate?.initialised]);
265
+ const deleteUser = useCallback(async (user) => {
266
+ if (!dataSourceDelegate) throw Error("useBuildUserManagement Firebase not initialised");
267
+ if (!usersPath) throw Error("useBuildUserManagement Firestore not initialised");
268
+ console.debug("Deleting", user);
269
+ const { uid } = user;
270
+ const entity = {
271
+ path: usersPath,
272
+ id: uid,
273
+ values: {}
274
+ };
275
+ await dataSourceDelegate.deleteEntity({ entity });
276
+ }, [usersPath, dataSourceDelegate?.initialised]);
277
+ const deleteRole = useCallback(async (role) => {
278
+ if (!dataSourceDelegate) throw Error("useBuildUserManagement Firebase not initialised");
279
+ if (!rolesPath) throw Error("useBuildUserManagement Firestore not initialised");
280
+ console.debug("Deleting", role);
281
+ const { id } = role;
282
+ const entity = {
283
+ path: rolesPath,
284
+ id,
285
+ values: {}
286
+ };
287
+ await dataSourceDelegate.deleteEntity({ entity });
288
+ }, [rolesPath, dataSourceDelegate?.initialised]);
289
+ const collectionPermissions = useCallback(({
290
+ collection,
291
+ user
292
+ }) => resolveUserRolePermissions({
293
+ collection,
294
+ user
295
+ }), []);
296
+ const defineRolesFor = useCallback((user) => {
297
+ if (!users) throw Error("Users not loaded");
298
+ const mgmtUser = users.find((u) => u.email?.toLowerCase() === user?.email?.toLowerCase());
299
+ return mgmtUser?.roles;
300
+ }, [users]);
301
+ const authenticator = useCallback(({ user }) => {
302
+ console.debug("Authenticating user", user);
303
+ if (loading) {
304
+ console.warn("User management is still loading");
305
+ return false;
306
+ }
307
+ if (users.length === 0) {
308
+ return true;
309
+ }
310
+ const mgmtUser = users.find((u) => u.email?.toLowerCase() === user?.email?.toLowerCase());
311
+ if (mgmtUser) {
312
+ return true;
313
+ }
216
314
  throw Error("Could not find a user with the provided email in the user management system.");
217
- }, [h, y]), ke = E.some((f) => f.id === "admin");
315
+ }, [loading, users, usersError, rolesError]);
316
+ const isAdmin = roles.some((r) => r.id === "admin");
218
317
  return {
219
- loading: h,
220
- roles: E,
221
- users: y,
222
- saveUser: x,
223
- saveRole: D,
224
- rolesError: b,
225
- deleteUser: T,
226
- deleteRole: o,
227
- usersLimit: l,
228
- usersError: z,
229
- isAdmin: ke,
230
- canEditRoles: i === void 0 ? !0 : i,
231
- allowDefaultRolesCreation: m === void 0 ? !0 : m,
232
- includeCollectionConfigPermissions: !!g,
233
- collectionPermissions: S,
234
- defineRolesFor: $,
235
- authenticator: G
318
+ loading,
319
+ roles,
320
+ users,
321
+ saveUser,
322
+ saveRole,
323
+ rolesError,
324
+ deleteUser,
325
+ deleteRole,
326
+ usersLimit,
327
+ usersError,
328
+ isAdmin,
329
+ canEditRoles: canEditRoles === void 0 ? true : canEditRoles,
330
+ allowDefaultRolesCreation: allowDefaultRolesCreation === void 0 ? true : allowDefaultRolesCreation,
331
+ includeCollectionConfigPermissions: Boolean(includeCollectionConfigPermissions),
332
+ collectionPermissions,
333
+ defineRolesFor,
334
+ authenticator
236
335
  };
237
336
  }
238
- const Ge = (t) => t.map((r) => {
239
- const n = r.data();
240
- return {
241
- uid: r.id,
242
- ...n,
243
- created_on: n?.created_on?.toDate(),
244
- updated_on: n?.updated_on?.toDate()
245
- };
246
- }), He = (t) => t.map((r) => ({
247
- id: r.id,
248
- ...r.data()
249
- })), Ee = F.createContext({});
250
- function Ke({
251
- children: t,
252
- userManagement: r
337
+ const entitiesToUsers = (docs) => {
338
+ return docs.map((doc) => {
339
+ const data = doc.values;
340
+ const newVar = {
341
+ uid: doc.id,
342
+ ...data,
343
+ created_on: data?.created_on,
344
+ updated_on: data?.updated_on
345
+ };
346
+ return newVar;
347
+ });
348
+ };
349
+ const entityToRoles = (entities) => {
350
+ return entities.map((doc) => ({
351
+ id: doc.id,
352
+ ...doc.values
353
+ }));
354
+ };
355
+ const UserManagementContext = React.createContext({});
356
+ function UserManagementProvider({
357
+ children,
358
+ userManagement
253
359
  }) {
254
- return /* @__PURE__ */ e(Ee.Provider, { value: r, children: t });
360
+ return /* @__PURE__ */ jsx(UserManagementContext.Provider, { value: userManagement, children });
255
361
  }
256
- const j = () => Fe(Ee);
257
- function X({ role: t }) {
258
- let r;
259
- return t.isAdmin ? r = "blueDarker" : t.id === "editor" ? r = "yellowLight" : t.id === "viewer" ? r = "grayLight" : r = Pe(t.id), /* @__PURE__ */ e(
260
- Te,
362
+ const useUserManagement = () => useContext(UserManagementContext);
363
+ function RoleChip({ role }) {
364
+ let colorScheme;
365
+ if (role.isAdmin) {
366
+ colorScheme = "blueDarker";
367
+ } else if (role.id === "editor") {
368
+ colorScheme = "yellowLight";
369
+ } else if (role.id === "viewer") {
370
+ colorScheme = "grayLight";
371
+ } else {
372
+ colorScheme = getColorSchemeForSeed(role.id);
373
+ }
374
+ return /* @__PURE__ */ jsx(
375
+ Chip,
261
376
  {
262
- colorScheme: r,
263
- children: t.name
377
+ colorScheme,
378
+ children: role.name
264
379
  },
265
- t.id
380
+ role.id
266
381
  );
267
382
  }
268
- const Qe = M.object().shape({
269
- id: M.string().required("Required"),
270
- name: M.string().required("Required")
383
+ const RoleYupSchema = Yup.object().shape({
384
+ id: Yup.string().required("Required"),
385
+ name: Yup.string().required("Required")
271
386
  });
272
- function Xe({
273
- open: t,
274
- role: r,
275
- editable: n,
276
- handleClose: l,
277
- collections: i
387
+ function canRoleBeEdited(loggedUser) {
388
+ const loggedUserIsAdmin = loggedUser.roles?.map((r) => r.id).includes("admin");
389
+ if (!loggedUserIsAdmin) {
390
+ throw new Error("Only admins can edit roles");
391
+ }
392
+ return true;
393
+ }
394
+ function RolesDetailsForm({
395
+ open,
396
+ role,
397
+ editable,
398
+ handleClose,
399
+ collections
278
400
  }) {
279
- const { saveRole: m } = j(), g = !r, [v, R] = A(), w = k((o) => (R(void 0), m(o)), [m]), c = Re({
280
- initialValues: r ?? {
401
+ const { saveRole } = useUserManagement();
402
+ const isNewRole = !role;
403
+ const {
404
+ user: loggedInUser
405
+ } = useAuthController();
406
+ const [savingError, setSavingError] = useState();
407
+ const onRoleUpdated = useCallback((role2) => {
408
+ setSavingError(void 0);
409
+ if (!loggedInUser) throw new Error("User not found");
410
+ canRoleBeEdited(loggedInUser);
411
+ return saveRole(role2);
412
+ }, [saveRole, loggedInUser]);
413
+ const formex = useCreateFormex({
414
+ initialValues: role ?? {
281
415
  name: ""
282
416
  },
283
- onSubmit: (o, S) => w(o).then(() => {
284
- S.resetForm({
285
- values: o
286
- }), l();
287
- }).catch(($) => R($)),
288
- validation: (o) => Qe.validate(o, { abortEarly: !1 }).then(() => ({})).catch((S) => {
289
- const $ = {};
290
- return S.inner.forEach((G) => {
291
- $[G.path] = G.message;
292
- }), $;
293
- })
294
- }), {
295
- isSubmitting: E,
296
- touched: U,
297
- values: a,
298
- errors: C,
299
- handleChange: y,
300
- setFieldValue: b,
301
- dirty: _,
302
- setFieldTouched: z
303
- } = c, u = a.isAdmin ?? !1, h = a.defaultPermissions?.create ?? !1, x = a.defaultPermissions?.read ?? !1, D = a.defaultPermissions?.edit ?? !1, T = a.defaultPermissions?.delete ?? !1;
304
- return F.useEffect(() => {
305
- !J(U, "id") && a.name && b("id", _e(a.name));
306
- }, [U, a.name]), /* @__PURE__ */ e(
307
- fe,
417
+ onSubmit: (role2, formexController) => {
418
+ try {
419
+ return onRoleUpdated(role2).then(() => {
420
+ formexController.resetForm({
421
+ values: role2
422
+ });
423
+ handleClose();
424
+ }).catch((e) => {
425
+ setSavingError(e);
426
+ });
427
+ } catch (e) {
428
+ setSavingError(e);
429
+ return Promise.resolve();
430
+ }
431
+ },
432
+ validation: (values2) => {
433
+ return RoleYupSchema.validate(values2, { abortEarly: false }).then(() => ({})).catch((e) => {
434
+ const errors2 = {};
435
+ e.inner.forEach((error) => {
436
+ errors2[error.path] = error.message;
437
+ });
438
+ return errors2;
439
+ });
440
+ }
441
+ });
442
+ const {
443
+ isSubmitting,
444
+ touched,
445
+ values,
446
+ errors,
447
+ handleChange,
448
+ setFieldValue,
449
+ dirty,
450
+ setFieldTouched
451
+ } = formex;
452
+ const isAdmin = values.isAdmin ?? false;
453
+ const defaultCreate = values.defaultPermissions?.create ?? false;
454
+ const defaultRead = values.defaultPermissions?.read ?? false;
455
+ const defaultEdit = values.defaultPermissions?.edit ?? false;
456
+ const defaultDelete = values.defaultPermissions?.delete ?? false;
457
+ React.useEffect(() => {
458
+ const idTouched = getIn(touched, "id");
459
+ if (!idTouched && values.name) {
460
+ setFieldValue("id", toSnakeCase(values.name));
461
+ }
462
+ }, [touched, values.name]);
463
+ return /* @__PURE__ */ jsx(
464
+ Dialog,
308
465
  {
309
- open: t,
466
+ open,
310
467
  maxWidth: "4xl",
311
- children: /* @__PURE__ */ e(De, { value: c, children: /* @__PURE__ */ s(
468
+ children: /* @__PURE__ */ jsx(Formex, { value: formex, children: /* @__PURE__ */ jsxs(
312
469
  "form",
313
470
  {
314
- noValidate: !0,
471
+ noValidate: true,
315
472
  autoComplete: "off",
316
- onSubmit: c.handleSubmit,
473
+ onSubmit: formex.handleSubmit,
317
474
  style: {
318
475
  display: "flex",
319
476
  flexDirection: "column",
@@ -321,13 +478,13 @@ function Xe({
321
478
  height: "100%"
322
479
  },
323
480
  children: [
324
- /* @__PURE__ */ s(ge, { className: "flex-grow", children: [
325
- /* @__PURE__ */ e(
481
+ /* @__PURE__ */ jsxs(DialogContent, { className: "flex-grow", children: [
482
+ /* @__PURE__ */ jsx(
326
483
  "div",
327
484
  {
328
485
  className: "flex flex-row pt-12 pb-8",
329
- children: /* @__PURE__ */ e(
330
- P,
486
+ children: /* @__PURE__ */ jsx(
487
+ Typography,
331
488
  {
332
489
  variant: "h4",
333
490
  className: "flex-grow",
@@ -336,262 +493,296 @@ function Xe({
336
493
  )
337
494
  }
338
495
  ),
339
- /* @__PURE__ */ s("div", { className: "grid grid-cols-12 gap-8", children: [
340
- /* @__PURE__ */ s("div", { className: "col-span-12 md:col-span-8", children: [
341
- /* @__PURE__ */ e(
342
- Q,
496
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-12 gap-8", children: [
497
+ /* @__PURE__ */ jsxs("div", { className: "col-span-12 md:col-span-8", children: [
498
+ /* @__PURE__ */ jsx(
499
+ TextField,
343
500
  {
344
501
  name: "name",
345
- required: !0,
346
- error: U.name && !!C.name,
347
- value: a.name,
348
- disabled: u || !n,
349
- onChange: y,
502
+ required: true,
503
+ error: touched.name && Boolean(errors.name),
504
+ value: values.name,
505
+ disabled: isAdmin || !editable,
506
+ onChange: handleChange,
350
507
  "aria-describedby": "name-helper-text",
351
508
  label: "Name"
352
509
  }
353
510
  ),
354
- /* @__PURE__ */ e(B, { children: U.name && C.name ? C.name : "Name of this role" })
511
+ /* @__PURE__ */ jsx(FieldCaption, { children: touched.name && Boolean(errors.name) ? errors.name : "Name of this role" })
355
512
  ] }),
356
- /* @__PURE__ */ s("div", { className: "col-span-12 md:col-span-4", children: [
357
- /* @__PURE__ */ e(
358
- Q,
513
+ /* @__PURE__ */ jsxs("div", { className: "col-span-12 md:col-span-4", children: [
514
+ /* @__PURE__ */ jsx(
515
+ TextField,
359
516
  {
360
517
  name: "id",
361
- required: !0,
362
- error: U.id && !!C.id,
363
- value: a.id,
364
- disabled: !g || !n,
365
- onChange: (o) => {
366
- y(o), z("id", !0);
518
+ required: true,
519
+ error: touched.id && Boolean(errors.id),
520
+ value: values.id,
521
+ disabled: !isNewRole || !editable,
522
+ onChange: (e) => {
523
+ handleChange(e);
524
+ setFieldTouched("id", true);
367
525
  },
368
526
  "aria-describedby": "id-helper-text",
369
527
  label: "ID"
370
528
  }
371
529
  ),
372
- /* @__PURE__ */ e(B, { children: U.id && C.id ? C.id : "ID of this role" })
530
+ /* @__PURE__ */ jsx(FieldCaption, { children: touched.id && Boolean(errors.id) ? errors.id : "ID of this role" })
373
531
  ] }),
374
- /* @__PURE__ */ s("div", { className: "col-span-12", children: [
375
- /* @__PURE__ */ e(
376
- pe,
377
- {
378
- className: "bg-inherit",
379
- children: /* @__PURE__ */ s(re, { children: [
380
- /* @__PURE__ */ s(ie, { children: [
381
- /* @__PURE__ */ e(d, {}),
382
- /* @__PURE__ */ e(
383
- d,
384
- {
385
- align: "center",
386
- children: "Create entities"
387
- }
388
- ),
389
- /* @__PURE__ */ e(
390
- d,
391
- {
392
- align: "center",
393
- children: "Read entities"
394
- }
395
- ),
396
- /* @__PURE__ */ e(
397
- d,
398
- {
399
- align: "center",
400
- children: "Update entities"
401
- }
402
- ),
403
- /* @__PURE__ */ e(
404
- d,
405
- {
406
- align: "center",
407
- children: "Delete entities"
408
- }
409
- )
410
- ] }),
411
- /* @__PURE__ */ s(oe, { children: [
412
- /* @__PURE__ */ s(W, { children: [
413
- /* @__PURE__ */ e(
414
- d,
415
- {
416
- scope: "row",
417
- children: /* @__PURE__ */ e("strong", { children: "All collections" })
418
- }
419
- ),
420
- /* @__PURE__ */ e(
421
- d,
532
+ /* @__PURE__ */ jsxs("div", { className: "col-span-12", children: [
533
+ /* @__PURE__ */ jsx(Paper, { className: "bg-inherit overflow-hidden", children: /* @__PURE__ */ jsxs(Table, { className: "w-full rounded-md", children: [
534
+ /* @__PURE__ */ jsxs(TableHeader, { className: "rounded-md", children: [
535
+ /* @__PURE__ */ jsx(TableCell, {}),
536
+ /* @__PURE__ */ jsx(
537
+ TableCell,
538
+ {
539
+ align: "center",
540
+ children: "Create entities"
541
+ }
542
+ ),
543
+ /* @__PURE__ */ jsx(
544
+ TableCell,
545
+ {
546
+ align: "center",
547
+ children: "Read entities"
548
+ }
549
+ ),
550
+ /* @__PURE__ */ jsx(
551
+ TableCell,
552
+ {
553
+ align: "center",
554
+ children: "Update entities"
555
+ }
556
+ ),
557
+ /* @__PURE__ */ jsx(
558
+ TableCell,
559
+ {
560
+ align: "center",
561
+ children: "Delete entities"
562
+ }
563
+ ),
564
+ /* @__PURE__ */ jsx(
565
+ TableCell,
566
+ {
567
+ align: "center"
568
+ }
569
+ )
570
+ ] }),
571
+ /* @__PURE__ */ jsxs(TableBody, { children: [
572
+ /* @__PURE__ */ jsxs(TableRow, { children: [
573
+ /* @__PURE__ */ jsx(
574
+ TableCell,
575
+ {
576
+ scope: "row",
577
+ children: /* @__PURE__ */ jsx("strong", { children: "All collections" })
578
+ }
579
+ ),
580
+ /* @__PURE__ */ jsx(
581
+ TableCell,
582
+ {
583
+ align: "center",
584
+ children: /* @__PURE__ */ jsx(
585
+ Tooltip,
422
586
  {
423
- align: "center",
424
- children: /* @__PURE__ */ e(
425
- V,
587
+ title: "Create entities in collections",
588
+ children: /* @__PURE__ */ jsx(
589
+ Checkbox,
426
590
  {
427
- title: "Create entities in collections",
428
- children: /* @__PURE__ */ e(
429
- I,
430
- {
431
- disabled: u || !n,
432
- checked: (u || h) ?? !1,
433
- onCheckedChange: (o) => b("defaultPermissions.create", o)
434
- }
435
- )
591
+ disabled: isAdmin || !editable,
592
+ checked: (isAdmin || defaultCreate) ?? false,
593
+ onCheckedChange: (checked) => setFieldValue("defaultPermissions.create", checked)
436
594
  }
437
595
  )
438
596
  }
439
- ),
440
- /* @__PURE__ */ e(
441
- d,
597
+ )
598
+ }
599
+ ),
600
+ /* @__PURE__ */ jsx(
601
+ TableCell,
602
+ {
603
+ align: "center",
604
+ children: /* @__PURE__ */ jsx(
605
+ Tooltip,
442
606
  {
443
- align: "center",
444
- children: /* @__PURE__ */ e(
445
- V,
607
+ title: "Access all data in every collection",
608
+ children: /* @__PURE__ */ jsx(
609
+ Checkbox,
446
610
  {
447
- title: "Access all data in every collection",
448
- children: /* @__PURE__ */ e(
449
- I,
450
- {
451
- disabled: u || !n,
452
- checked: (u || x) ?? !1,
453
- onCheckedChange: (o) => b("defaultPermissions.read", o)
454
- }
455
- )
611
+ disabled: isAdmin || !editable,
612
+ checked: (isAdmin || defaultRead) ?? false,
613
+ onCheckedChange: (checked) => setFieldValue("defaultPermissions.read", checked)
456
614
  }
457
615
  )
458
616
  }
459
- ),
460
- /* @__PURE__ */ e(
461
- d,
617
+ )
618
+ }
619
+ ),
620
+ /* @__PURE__ */ jsx(
621
+ TableCell,
622
+ {
623
+ align: "center",
624
+ children: /* @__PURE__ */ jsx(
625
+ Tooltip,
462
626
  {
463
- align: "center",
464
- children: /* @__PURE__ */ e(
465
- V,
627
+ title: "Update data in any collection",
628
+ children: /* @__PURE__ */ jsx(
629
+ Checkbox,
466
630
  {
467
- title: "Update data in any collection",
468
- children: /* @__PURE__ */ e(
469
- I,
470
- {
471
- disabled: u || !n,
472
- checked: (u || D) ?? !1,
473
- onCheckedChange: (o) => b("defaultPermissions.edit", o)
474
- }
475
- )
631
+ disabled: isAdmin || !editable,
632
+ checked: (isAdmin || defaultEdit) ?? false,
633
+ onCheckedChange: (checked) => setFieldValue("defaultPermissions.edit", checked)
476
634
  }
477
635
  )
478
636
  }
479
- ),
480
- /* @__PURE__ */ e(
481
- d,
637
+ )
638
+ }
639
+ ),
640
+ /* @__PURE__ */ jsx(
641
+ TableCell,
642
+ {
643
+ align: "center",
644
+ children: /* @__PURE__ */ jsx(
645
+ Tooltip,
482
646
  {
483
- align: "center",
484
- children: /* @__PURE__ */ e(
485
- V,
647
+ title: "Delete data in any collection",
648
+ children: /* @__PURE__ */ jsx(
649
+ Checkbox,
486
650
  {
487
- title: "Delete data in any collection",
488
- children: /* @__PURE__ */ e(
489
- I,
490
- {
491
- disabled: u || !n,
492
- checked: (u || T) ?? !1,
493
- onCheckedChange: (o) => b("defaultPermissions.delete", o)
494
- }
495
- )
651
+ disabled: isAdmin || !editable,
652
+ checked: (isAdmin || defaultDelete) ?? false,
653
+ onCheckedChange: (checked) => setFieldValue("defaultPermissions.delete", checked)
496
654
  }
497
655
  )
498
656
  }
499
657
  )
500
- ] }),
501
- i && i.map((o) => /* @__PURE__ */ s(W, { children: [
502
- /* @__PURE__ */ e(
503
- d,
658
+ }
659
+ ),
660
+ /* @__PURE__ */ jsx(
661
+ TableCell,
662
+ {
663
+ align: "center"
664
+ }
665
+ )
666
+ ] }),
667
+ collections && collections.map((col) => /* @__PURE__ */ jsxs(TableRow, { children: [
668
+ /* @__PURE__ */ jsx(
669
+ TableCell,
670
+ {
671
+ scope: "row",
672
+ children: col.name
673
+ }
674
+ ),
675
+ /* @__PURE__ */ jsx(
676
+ TableCell,
677
+ {
678
+ align: "center",
679
+ children: /* @__PURE__ */ jsx(
680
+ Checkbox,
504
681
  {
505
- scope: "row",
506
- children: o.name
682
+ disabled: isAdmin || defaultCreate || !editable,
683
+ checked: (isAdmin || defaultCreate || getIn(values, `collectionPermissions.${col.id}.create`)) ?? false,
684
+ onCheckedChange: (checked) => setFieldValue(`collectionPermissions.${col.id}.create`, checked)
507
685
  }
508
- ),
509
- /* @__PURE__ */ e(
510
- d,
686
+ )
687
+ }
688
+ ),
689
+ /* @__PURE__ */ jsx(
690
+ TableCell,
691
+ {
692
+ align: "center",
693
+ children: /* @__PURE__ */ jsx(
694
+ Checkbox,
511
695
  {
512
- align: "center",
513
- children: /* @__PURE__ */ e(
514
- I,
515
- {
516
- disabled: u || h || !n,
517
- checked: (u || h || J(a, `collectionPermissions.${o.path}.create`)) ?? !1,
518
- onCheckedChange: (S) => b(`collectionPermissions.${o.path}.create`, S)
519
- }
520
- )
696
+ disabled: isAdmin || defaultRead || !editable,
697
+ checked: (isAdmin || defaultRead || getIn(values, `collectionPermissions.${col.id}.read`)) ?? false,
698
+ onCheckedChange: (checked) => setFieldValue(`collectionPermissions.${col.id}.read`, checked)
521
699
  }
522
- ),
523
- /* @__PURE__ */ e(
524
- d,
700
+ )
701
+ }
702
+ ),
703
+ /* @__PURE__ */ jsx(
704
+ TableCell,
705
+ {
706
+ align: "center",
707
+ children: /* @__PURE__ */ jsx(
708
+ Checkbox,
525
709
  {
526
- align: "center",
527
- children: /* @__PURE__ */ e(
528
- I,
529
- {
530
- disabled: u || x || !n,
531
- checked: (u || x || J(a, `collectionPermissions.${o.path}.read`)) ?? !1,
532
- onCheckedChange: (S) => b(`collectionPermissions.${o.path}.read`, S)
533
- }
534
- )
710
+ disabled: isAdmin || defaultEdit || !editable,
711
+ checked: (isAdmin || defaultEdit || getIn(values, `collectionPermissions.${col.id}.edit`)) ?? false,
712
+ onCheckedChange: (checked) => setFieldValue(`collectionPermissions.${col.id}.edit`, checked)
535
713
  }
536
- ),
537
- /* @__PURE__ */ e(
538
- d,
714
+ )
715
+ }
716
+ ),
717
+ /* @__PURE__ */ jsx(
718
+ TableCell,
719
+ {
720
+ align: "center",
721
+ children: /* @__PURE__ */ jsx(
722
+ Checkbox,
539
723
  {
540
- align: "center",
541
- children: /* @__PURE__ */ e(
542
- I,
543
- {
544
- disabled: u || D || !n,
545
- checked: (u || D || J(a, `collectionPermissions.${o.path}.edit`)) ?? !1,
546
- onCheckedChange: (S) => b(`collectionPermissions.${o.path}.edit`, S)
547
- }
548
- )
724
+ disabled: isAdmin || defaultDelete || !editable,
725
+ checked: (isAdmin || defaultDelete || getIn(values, `collectionPermissions.${col.id}.delete`)) ?? false,
726
+ onCheckedChange: (checked) => setFieldValue(`collectionPermissions.${col.id}.delete`, checked)
549
727
  }
550
- ),
551
- /* @__PURE__ */ e(
552
- d,
728
+ )
729
+ }
730
+ ),
731
+ /* @__PURE__ */ jsx(
732
+ TableCell,
733
+ {
734
+ align: "center",
735
+ children: /* @__PURE__ */ jsx(
736
+ Tooltip,
553
737
  {
554
- align: "center",
555
- children: /* @__PURE__ */ e(
556
- I,
738
+ title: "Allow all permissions in this collections",
739
+ children: /* @__PURE__ */ jsx(
740
+ Button,
557
741
  {
558
- disabled: u || T || !n,
559
- checked: (u || T || J(a, `collectionPermissions.${o.path}.delete`)) ?? !1,
560
- onCheckedChange: (S) => b(`collectionPermissions.${o.path}.delete`, S)
742
+ className: "color-inherit",
743
+ onClick: () => {
744
+ setFieldValue(`collectionPermissions.${col.id}.create`, true);
745
+ setFieldValue(`collectionPermissions.${col.id}.read`, true);
746
+ setFieldValue(`collectionPermissions.${col.id}.edit`, true);
747
+ setFieldValue(`collectionPermissions.${col.id}.delete`, true);
748
+ },
749
+ disabled: isAdmin || !editable,
750
+ variant: "text",
751
+ children: "All"
561
752
  }
562
753
  )
563
754
  }
564
755
  )
565
- ] }, o.name))
566
- ] })
567
- ] })
568
- }
569
- ),
570
- /* @__PURE__ */ e(B, { children: "You can customise the permissions that the users related to this role can perform in the entities of each collection" })
756
+ }
757
+ )
758
+ ] }, col.name))
759
+ ] })
760
+ ] }) }),
761
+ /* @__PURE__ */ jsx(FieldCaption, { children: "You can customise the permissions that the users related to this role can perform in the entities of each collection" })
571
762
  ] }),
572
- /* @__PURE__ */ s("div", { className: "col-span-12 md:col-span-4", children: [
573
- /* @__PURE__ */ s(
574
- ne,
763
+ /* @__PURE__ */ jsxs("div", { className: "col-span-12 md:col-span-4", children: [
764
+ /* @__PURE__ */ jsxs(
765
+ Select,
575
766
  {
576
- error: U.config && !!C.config,
767
+ error: touched.config && Boolean(errors.config),
577
768
  id: "createCollections",
578
769
  name: "createCollections",
579
770
  label: "Create collections",
580
771
  position: "item-aligned",
581
- disabled: u || !n,
582
- onChange: (o) => b("config.createCollections", o.target.value === "true"),
583
- value: u || a.config?.createCollections ? "true" : "false",
584
- renderValue: (o) => o === "true" ? "Yes" : "No",
772
+ disabled: isAdmin || !editable,
773
+ onChange: (event) => setFieldValue("config.createCollections", event.target.value === "true"),
774
+ value: isAdmin || values.config?.createCollections ? "true" : "false",
775
+ renderValue: (value) => value === "true" ? "Yes" : "No",
585
776
  children: [
586
- /* @__PURE__ */ e(
587
- L,
777
+ /* @__PURE__ */ jsx(
778
+ SelectItem,
588
779
  {
589
780
  value: "true",
590
781
  children: " Yes "
591
782
  }
592
783
  ),
593
- /* @__PURE__ */ e(
594
- L,
784
+ /* @__PURE__ */ jsx(
785
+ SelectItem,
595
786
  {
596
787
  value: "false",
597
788
  children: " No "
@@ -600,38 +791,38 @@ function Xe({
600
791
  ]
601
792
  }
602
793
  ),
603
- /* @__PURE__ */ e(B, { children: U.config && C.config ? C.config : "Can the user create collections" })
794
+ /* @__PURE__ */ jsx(FieldCaption, { children: touched.config && Boolean(errors.config) ? errors.config : "Can the user create collections" })
604
795
  ] }),
605
- /* @__PURE__ */ s("div", { className: "col-span-12 md:col-span-4", children: [
606
- /* @__PURE__ */ s(
607
- ne,
796
+ /* @__PURE__ */ jsxs("div", { className: "col-span-12 md:col-span-4", children: [
797
+ /* @__PURE__ */ jsxs(
798
+ Select,
608
799
  {
609
- error: U.config && !!C.config,
800
+ error: touched.config && Boolean(errors.config),
610
801
  id: "editCollections",
611
802
  name: "editCollections",
612
803
  label: "Edit collections",
613
- disabled: u || !n,
804
+ disabled: isAdmin || !editable,
614
805
  position: "item-aligned",
615
- onChange: (o) => b("config.editCollections", o.target.value === "own" ? "own" : o.target.value === "true"),
616
- value: u ? "true" : a.config?.editCollections === "own" ? "own" : a.config?.editCollections ? "true" : "false",
617
- renderValue: (o) => o === "own" ? "Own" : o === "true" ? "Yes" : "No",
806
+ onChange: (event) => setFieldValue("config.editCollections", event.target.value === "own" ? "own" : event.target.value === "true"),
807
+ value: isAdmin ? "true" : values.config?.editCollections === "own" ? "own" : values.config?.editCollections ? "true" : "false",
808
+ renderValue: (value) => value === "own" ? "Own" : value === "true" ? "Yes" : "No",
618
809
  children: [
619
- /* @__PURE__ */ e(
620
- L,
810
+ /* @__PURE__ */ jsx(
811
+ SelectItem,
621
812
  {
622
813
  value: "true",
623
814
  children: " Yes "
624
815
  }
625
816
  ),
626
- /* @__PURE__ */ e(
627
- L,
817
+ /* @__PURE__ */ jsx(
818
+ SelectItem,
628
819
  {
629
820
  value: "false",
630
821
  children: " No "
631
822
  }
632
823
  ),
633
- /* @__PURE__ */ e(
634
- L,
824
+ /* @__PURE__ */ jsx(
825
+ SelectItem,
635
826
  {
636
827
  value: "own",
637
828
  children: " Only his/her own "
@@ -640,38 +831,38 @@ function Xe({
640
831
  ]
641
832
  }
642
833
  ),
643
- /* @__PURE__ */ e(B, { children: U.config && C.config ? C.config : "Can the user edit collections" })
834
+ /* @__PURE__ */ jsx(FieldCaption, { children: touched.config && Boolean(errors.config) ? errors.config : "Can the user edit collections" })
644
835
  ] }),
645
- /* @__PURE__ */ s("div", { className: "col-span-12 md:col-span-4", children: [
646
- /* @__PURE__ */ s(
647
- ne,
836
+ /* @__PURE__ */ jsxs("div", { className: "col-span-12 md:col-span-4", children: [
837
+ /* @__PURE__ */ jsxs(
838
+ Select,
648
839
  {
649
- error: U.config && !!C.config,
840
+ error: touched.config && Boolean(errors.config),
650
841
  id: "deleteCollections",
651
842
  name: "deleteCollections",
652
843
  label: "Delete collections",
653
- disabled: u || !n,
844
+ disabled: isAdmin || !editable,
654
845
  position: "item-aligned",
655
- onChange: (o) => b("config.deleteCollections", o.target.value === "own" ? "own" : o.target.value === "true"),
656
- value: u ? "true" : a.config?.deleteCollections === "own" ? "own" : a.config?.deleteCollections ? "true" : "false",
657
- renderValue: (o) => o === "own" ? "Own" : o === "true" ? "Yes" : "No",
846
+ onChange: (event) => setFieldValue("config.deleteCollections", event.target.value === "own" ? "own" : event.target.value === "true"),
847
+ value: isAdmin ? "true" : values.config?.deleteCollections === "own" ? "own" : values.config?.deleteCollections ? "true" : "false",
848
+ renderValue: (value) => value === "own" ? "Own" : value === "true" ? "Yes" : "No",
658
849
  children: [
659
- /* @__PURE__ */ e(
660
- L,
850
+ /* @__PURE__ */ jsx(
851
+ SelectItem,
661
852
  {
662
853
  value: "true",
663
854
  children: " Yes "
664
855
  }
665
856
  ),
666
- /* @__PURE__ */ e(
667
- L,
857
+ /* @__PURE__ */ jsx(
858
+ SelectItem,
668
859
  {
669
860
  value: "false",
670
861
  children: " No "
671
862
  }
672
863
  ),
673
- /* @__PURE__ */ e(
674
- L,
864
+ /* @__PURE__ */ jsx(
865
+ SelectItem,
675
866
  {
676
867
  value: "own",
677
868
  children: " Only his/her own "
@@ -680,32 +871,32 @@ function Xe({
680
871
  ]
681
872
  }
682
873
  ),
683
- /* @__PURE__ */ e(B, { children: U.config && C.config ? C.config : "Can the user delete collections" })
874
+ /* @__PURE__ */ jsx(FieldCaption, { children: touched.config && Boolean(errors.config) ? errors.config : "Can the user delete collections" })
684
875
  ] })
685
876
  ] })
686
877
  ] }),
687
- /* @__PURE__ */ s(Ce, { position: "sticky", children: [
688
- v && /* @__PURE__ */ e(P, { className: "text-red-500", children: "There was an error saving this role" }),
689
- /* @__PURE__ */ e(
690
- O,
878
+ /* @__PURE__ */ jsxs(DialogActions, { position: "sticky", children: [
879
+ savingError && /* @__PURE__ */ jsx(Typography, { className: "text-red-500 dark:text-red-500", children: savingError.message ?? "There was an error saving this role" }),
880
+ /* @__PURE__ */ jsx(
881
+ Button,
691
882
  {
692
883
  variant: "text",
693
884
  onClick: () => {
694
- l();
885
+ handleClose();
695
886
  },
696
887
  children: "Cancel"
697
888
  }
698
889
  ),
699
- /* @__PURE__ */ e(
700
- ve,
890
+ /* @__PURE__ */ jsx(
891
+ LoadingButton,
701
892
  {
702
893
  variant: "filled",
703
894
  color: "primary",
704
895
  type: "submit",
705
- disabled: !_,
706
- loading: E,
707
- startIcon: /* @__PURE__ */ e(we, {}),
708
- children: g ? "Create role" : "Update"
896
+ disabled: !dirty,
897
+ loading: isSubmitting,
898
+ startIcon: /* @__PURE__ */ jsx(DoneIcon, {}),
899
+ children: isNewRole ? "Create role" : "Update"
709
900
  }
710
901
  )
711
902
  ] })
@@ -715,24 +906,24 @@ function Xe({
715
906
  }
716
907
  );
717
908
  }
718
- const Se = [
909
+ const DEFAULT_ROLES = [
719
910
  {
720
911
  id: "admin",
721
912
  name: "Admin",
722
- isAdmin: !0
913
+ isAdmin: true
723
914
  },
724
915
  {
725
916
  id: "editor",
726
917
  name: "Editor",
727
- isAdmin: !1,
918
+ isAdmin: false,
728
919
  defaultPermissions: {
729
- read: !0,
730
- create: !0,
731
- edit: !0,
732
- delete: !0
920
+ read: true,
921
+ create: true,
922
+ edit: true,
923
+ delete: true
733
924
  },
734
925
  config: {
735
- createCollections: !0,
926
+ createCollections: true,
736
927
  editCollections: "own",
737
928
  deleteCollections: "own"
738
929
  }
@@ -740,78 +931,93 @@ const Se = [
740
931
  {
741
932
  id: "viewer",
742
933
  name: "Viewer",
743
- isAdmin: !1,
934
+ isAdmin: false,
744
935
  defaultPermissions: {
745
- read: !0,
746
- create: !1,
747
- edit: !1,
748
- delete: !1
936
+ read: true,
937
+ create: false,
938
+ edit: false,
939
+ delete: false
749
940
  }
750
941
  }
751
942
  ];
752
- function Ze({
753
- onRoleClicked: t,
754
- editable: r
943
+ function RolesTable({
944
+ onRoleClicked,
945
+ editable
755
946
  }) {
756
947
  const {
757
- roles: n,
758
- saveRole: l,
759
- deleteRole: i,
760
- allowDefaultRolesCreation: m
761
- } = j(), [g, v] = A(void 0), [R, w] = A(!1);
762
- return /* @__PURE__ */ s(
948
+ roles,
949
+ saveRole,
950
+ deleteRole,
951
+ allowDefaultRolesCreation
952
+ } = useUserManagement();
953
+ const [roleToBeDeleted, setRoleToBeDeleted] = useState(void 0);
954
+ const [deleteInProgress, setDeleteInProgress] = useState(false);
955
+ return /* @__PURE__ */ jsxs(
763
956
  "div",
764
957
  {
765
958
  className: "w-full overflow-auto",
766
959
  children: [
767
- /* @__PURE__ */ s(re, { children: [
768
- /* @__PURE__ */ s(ie, { children: [
769
- /* @__PURE__ */ e(d, { header: !0, className: "w-16" }),
770
- /* @__PURE__ */ e(d, { header: !0, children: "Role" }),
771
- /* @__PURE__ */ e(d, { header: !0, className: "items-center", children: "Is Admin" }),
772
- /* @__PURE__ */ e(d, { header: !0, children: "Default permissions" })
960
+ /* @__PURE__ */ jsxs(Table, { className: "w-full", children: [
961
+ /* @__PURE__ */ jsxs(TableHeader, { children: [
962
+ /* @__PURE__ */ jsx(TableCell, { header: true, className: "w-16" }),
963
+ /* @__PURE__ */ jsx(TableCell, { header: true, children: "Role" }),
964
+ /* @__PURE__ */ jsx(TableCell, { header: true, className: "items-center", children: "Is Admin" }),
965
+ /* @__PURE__ */ jsx(TableCell, { header: true, children: "Default permissions" })
773
966
  ] }),
774
- /* @__PURE__ */ s(oe, { children: [
775
- n && n.map((c) => {
776
- const E = c.isAdmin || c.defaultPermissions?.create, U = c.isAdmin || c.defaultPermissions?.read, a = c.isAdmin || c.defaultPermissions?.edit, C = c.isAdmin || c.defaultPermissions?.delete;
777
- return /* @__PURE__ */ s(
778
- W,
967
+ /* @__PURE__ */ jsxs(TableBody, { children: [
968
+ roles && roles.map((role) => {
969
+ const canCreateAll = role.isAdmin || role.defaultPermissions?.create;
970
+ const canReadAll = role.isAdmin || role.defaultPermissions?.read;
971
+ const canUpdateAll = role.isAdmin || role.defaultPermissions?.edit;
972
+ const canDeleteAll = role.isAdmin || role.defaultPermissions?.delete;
973
+ return /* @__PURE__ */ jsxs(
974
+ TableRow,
779
975
  {
780
976
  onClick: () => {
781
- t(c);
977
+ onRoleClicked(role);
782
978
  },
783
979
  children: [
784
- /* @__PURE__ */ e(d, { style: { width: "64px" }, children: !c.isAdmin && /* @__PURE__ */ e(V, { title: "Delete this role", children: /* @__PURE__ */ e(
785
- ye,
980
+ /* @__PURE__ */ jsx(TableCell, { style: { width: "64px" }, children: !role.isAdmin && /* @__PURE__ */ jsx(
981
+ Tooltip,
786
982
  {
787
- size: "small",
788
- disabled: !r,
789
- onClick: (y) => (y.stopPropagation(), v(c)),
790
- children: /* @__PURE__ */ e(be, {})
983
+ asChild: true,
984
+ title: "Delete this role",
985
+ children: /* @__PURE__ */ jsx(
986
+ IconButton,
987
+ {
988
+ size: "small",
989
+ disabled: !editable,
990
+ onClick: (event) => {
991
+ event.stopPropagation();
992
+ return setRoleToBeDeleted(role);
993
+ },
994
+ children: /* @__PURE__ */ jsx(DeleteIcon, {})
995
+ }
996
+ )
791
997
  }
792
- ) }) }),
793
- /* @__PURE__ */ e(d, { children: /* @__PURE__ */ e(X, { role: c }) }),
794
- /* @__PURE__ */ e(d, { className: "items-center", children: /* @__PURE__ */ e(I, { checked: c.isAdmin ?? !1 }) }),
795
- /* @__PURE__ */ e(d, { children: /* @__PURE__ */ s("ul", { children: [
796
- E && /* @__PURE__ */ e("li", { children: "Create" }),
797
- U && /* @__PURE__ */ e("li", { children: "Read" }),
798
- a && /* @__PURE__ */ e("li", { children: "Update" }),
799
- C && /* @__PURE__ */ e("li", { children: "Delete" })
998
+ ) }),
999
+ /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(RoleChip, { role }) }),
1000
+ /* @__PURE__ */ jsx(TableCell, { className: "items-center", children: /* @__PURE__ */ jsx(Checkbox, { checked: role.isAdmin ?? false }) }),
1001
+ /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsxs("ul", { children: [
1002
+ canCreateAll && /* @__PURE__ */ jsx("li", { children: "Create" }),
1003
+ canReadAll && /* @__PURE__ */ jsx("li", { children: "Read" }),
1004
+ canUpdateAll && /* @__PURE__ */ jsx("li", { children: "Update" }),
1005
+ canDeleteAll && /* @__PURE__ */ jsx("li", { children: "Delete" })
800
1006
  ] }) })
801
1007
  ]
802
1008
  },
803
- c.name
1009
+ role.name
804
1010
  );
805
1011
  }),
806
- (!n || n.length === 0) && /* @__PURE__ */ e(W, { children: /* @__PURE__ */ e(d, { colspan: 4, children: /* @__PURE__ */ s(Ne, { className: "flex flex-col gap-4 my-8 items-center", children: [
807
- /* @__PURE__ */ e(P, { variant: "label", children: "You don't have any roles yet." }),
808
- m && /* @__PURE__ */ e(
809
- O,
1012
+ (!roles || roles.length === 0) && /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colspan: 4, children: /* @__PURE__ */ jsxs(CenteredView, { className: "flex flex-col gap-4 my-8 items-center", children: [
1013
+ /* @__PURE__ */ jsx(Typography, { variant: "label", children: "You don't have any roles yet." }),
1014
+ allowDefaultRolesCreation && /* @__PURE__ */ jsx(
1015
+ Button,
810
1016
  {
811
1017
  variant: "outlined",
812
1018
  onClick: () => {
813
- Se.forEach((c) => {
814
- l(c);
1019
+ DEFAULT_ROLES.forEach((role) => {
1020
+ saveRole(role);
815
1021
  });
816
1022
  },
817
1023
  children: "Create default roles"
@@ -820,146 +1026,189 @@ function Ze({
820
1026
  ] }) }) })
821
1027
  ] })
822
1028
  ] }),
823
- /* @__PURE__ */ e(
824
- xe,
1029
+ /* @__PURE__ */ jsx(
1030
+ DeleteConfirmationDialog,
825
1031
  {
826
- open: !!g,
827
- loading: R,
1032
+ open: Boolean(roleToBeDeleted),
1033
+ loading: deleteInProgress,
828
1034
  onAccept: () => {
829
- g && (w(!0), i(g).then(() => {
830
- v(void 0);
831
- }).finally(() => {
832
- w(!1);
833
- }));
1035
+ if (roleToBeDeleted) {
1036
+ setDeleteInProgress(true);
1037
+ deleteRole(roleToBeDeleted).then(() => {
1038
+ setRoleToBeDeleted(void 0);
1039
+ }).finally(() => {
1040
+ setDeleteInProgress(false);
1041
+ });
1042
+ }
834
1043
  },
835
1044
  onCancel: () => {
836
- v(void 0);
1045
+ setRoleToBeDeleted(void 0);
837
1046
  },
838
- title: /* @__PURE__ */ e(K, { children: "Delete?" }),
839
- body: /* @__PURE__ */ e(K, { children: "Are you sure you want to delete this role?" })
1047
+ title: /* @__PURE__ */ jsx(Fragment, { children: "Delete?" }),
1048
+ body: /* @__PURE__ */ jsx(Fragment, { children: "Are you sure you want to delete this role?" })
840
1049
  }
841
1050
  )
842
1051
  ]
843
1052
  }
844
1053
  );
845
1054
  }
846
- const en = F.memo(
847
- function({ children: r }) {
848
- const { collections: n } = Ve(), [l, i] = A(!1), [m, g] = A(), { canEditRoles: v } = j(), R = k((c) => {
849
- i(!0), g(c);
1055
+ const RolesView = React.memo(
1056
+ function RolesView2({ children }) {
1057
+ const { collections } = useNavigationController();
1058
+ const [dialogOpen, setDialogOpen] = useState(false);
1059
+ const [selectedRole, setSelectedRole] = useState();
1060
+ const { canEditRoles } = useUserManagement();
1061
+ const onRoleClicked = useCallback((user) => {
1062
+ setDialogOpen(true);
1063
+ setSelectedRole(user);
850
1064
  }, []);
851
- return /* @__PURE__ */ s(Ue, { className: "w-full flex flex-col py-4 gap-4", maxWidth: "6xl", children: [
852
- r,
853
- /* @__PURE__ */ s("div", { className: "flex items-center mt-12", children: [
854
- /* @__PURE__ */ e(
855
- P,
1065
+ const handleClose = () => {
1066
+ setSelectedRole(void 0);
1067
+ setDialogOpen(false);
1068
+ };
1069
+ return /* @__PURE__ */ jsxs(Container, { className: "w-full flex flex-col py-4 gap-4", maxWidth: "6xl", children: [
1070
+ children,
1071
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center mt-12", children: [
1072
+ /* @__PURE__ */ jsx(
1073
+ Typography,
856
1074
  {
857
- gutterBottom: !0,
1075
+ gutterBottom: true,
858
1076
  variant: "h4",
859
1077
  className: "flex-grow",
860
1078
  component: "h4",
861
1079
  children: "Roles"
862
1080
  }
863
1081
  ),
864
- /* @__PURE__ */ e(V, { title: v ? void 0 : "Update plans to customise roles", children: /* @__PURE__ */ e(
865
- O,
1082
+ /* @__PURE__ */ jsx(
1083
+ Tooltip,
866
1084
  {
867
- size: "large",
868
- disabled: !v,
869
- startIcon: /* @__PURE__ */ e(le, {}),
870
- onClick: () => i(!0),
871
- children: "Add role"
1085
+ asChild: true,
1086
+ title: !canEditRoles ? "Update plans to customise roles" : void 0,
1087
+ children: /* @__PURE__ */ jsx(
1088
+ Button,
1089
+ {
1090
+ size: "large",
1091
+ disabled: !canEditRoles,
1092
+ startIcon: /* @__PURE__ */ jsx(AddIcon, {}),
1093
+ onClick: () => setDialogOpen(true),
1094
+ children: "Add role"
1095
+ }
1096
+ )
872
1097
  }
873
- ) })
1098
+ )
874
1099
  ] }),
875
- /* @__PURE__ */ e(Ze, { onRoleClicked: R, editable: !!v }),
876
- /* @__PURE__ */ e(
877
- Xe,
1100
+ /* @__PURE__ */ jsx(RolesTable, { onRoleClicked, editable: Boolean(canEditRoles) }),
1101
+ /* @__PURE__ */ jsx(
1102
+ RolesDetailsForm,
878
1103
  {
879
- open: l,
880
- role: m,
881
- editable: v,
882
- collections: n,
883
- handleClose: () => {
884
- g(void 0), i(!1);
885
- }
1104
+ open: dialogOpen,
1105
+ role: selectedRole,
1106
+ editable: canEditRoles,
1107
+ collections,
1108
+ handleClose
886
1109
  },
887
- m?.id ?? "new"
1110
+ selectedRole?.id ?? "new"
888
1111
  )
889
1112
  ] });
890
1113
  }
891
- ), nn = M.object().shape({
892
- displayName: M.string().required("Required"),
893
- email: M.string().email().required("Required"),
894
- roles: M.array().min(1)
1114
+ );
1115
+ const UserYupSchema = Yup.object().shape({
1116
+ displayName: Yup.string().required("Required"),
1117
+ email: Yup.string().email().required("Required"),
1118
+ roles: Yup.array().min(1)
895
1119
  });
896
- function tn(t, r, n, l, i) {
897
- const m = n.filter((w) => w.roles?.map((c) => c.id).includes("admin")), g = t.roles?.map((w) => w.id).includes("admin");
898
- if ((!i || !ze(i.roles ?? [], r.roles ?? [])) && !g)
1120
+ function canUserBeEdited(loggedUser, user, users, roles, prevUser) {
1121
+ const admins = users.filter((u) => u.roles?.map((r) => r.id).includes("admin"));
1122
+ const loggedUserIsAdmin = loggedUser.roles?.map((r) => r.id).includes("admin");
1123
+ const didRolesChange = !prevUser || !areRolesEqual(prevUser.roles ?? [], user.roles ?? []);
1124
+ if (didRolesChange && !loggedUserIsAdmin) {
899
1125
  throw new Error("Only admins can change roles");
900
- if (i && i.roles?.map((w) => w.id).includes("admin") && !r.roles?.map((w) => w.id).includes("admin") && m.length === 1)
1126
+ }
1127
+ const adminRoleRemoved = prevUser && prevUser.roles?.map((r) => r.id).includes("admin") && !user.roles?.map((r) => r.id).includes("admin");
1128
+ if (adminRoleRemoved && admins.length === 1) {
901
1129
  throw new Error("There must be at least one admin");
902
- return !0;
1130
+ }
1131
+ return true;
903
1132
  }
904
- function rn({
905
- open: t,
906
- user: r,
907
- handleClose: n
1133
+ function UserDetailsForm({
1134
+ open,
1135
+ user: userProp,
1136
+ handleClose
908
1137
  }) {
909
- const l = se(), {
910
- user: i
911
- } = ae(), {
912
- saveUser: m,
913
- users: g,
914
- roles: v
915
- } = j(), R = !r, w = k((h) => {
916
- if (!i)
1138
+ const snackbarController = useSnackbarController();
1139
+ const {
1140
+ user: loggedInUser
1141
+ } = useAuthController();
1142
+ const {
1143
+ saveUser,
1144
+ users,
1145
+ roles
1146
+ } = useUserManagement();
1147
+ const isNewUser = !userProp;
1148
+ const onUserUpdated = useCallback((savedUser) => {
1149
+ if (!loggedInUser) {
917
1150
  throw new Error("Logged user not found");
1151
+ }
918
1152
  try {
919
- return tn(i, h, g, v, r), m(h);
920
- } catch (x) {
921
- return Promise.reject(x);
1153
+ canUserBeEdited(loggedInUser, savedUser, users, roles, userProp);
1154
+ return saveUser(savedUser);
1155
+ } catch (e) {
1156
+ return Promise.reject(e);
922
1157
  }
923
- }, [v, m, r, g, i]), c = Re({
924
- initialValues: r ?? {
1158
+ }, [roles, saveUser, userProp, users, loggedInUser]);
1159
+ const formex = useCreateFormex({
1160
+ initialValues: userProp ?? {
925
1161
  displayName: "",
926
1162
  email: "",
927
- roles: v.filter((h) => h.id === "editor")
1163
+ roles: roles.filter((r) => r.id === "editor")
928
1164
  },
929
- validation: (h) => nn.validate(h, { abortEarly: !1 }).then(() => ({})).catch((x) => x.inner.reduce((D, T) => (D[T.path] = T.message, D), {})),
930
- onSubmit: (h, x) => w(h).then(() => {
931
- n(), x.resetForm({
932
- values: h
1165
+ validation: (values2) => {
1166
+ return UserYupSchema.validate(values2, { abortEarly: false }).then(() => {
1167
+ return {};
1168
+ }).catch((e) => {
1169
+ return e.inner.reduce((acc, error) => {
1170
+ acc[error.path] = error.message;
1171
+ return acc;
1172
+ }, {});
933
1173
  });
934
- }).catch((D) => {
935
- l.open({
936
- type: "error",
937
- message: D.message
1174
+ },
1175
+ onSubmit: (user, formexController) => {
1176
+ return onUserUpdated(user).then(() => {
1177
+ handleClose();
1178
+ formexController.resetForm({
1179
+ values: user
1180
+ });
1181
+ }).catch((e) => {
1182
+ snackbarController.open({
1183
+ type: "error",
1184
+ message: e.message
1185
+ });
938
1186
  });
939
- })
940
- }), {
941
- isSubmitting: E,
942
- touched: U,
943
- handleChange: a,
944
- values: C,
945
- errors: y,
946
- setFieldValue: b,
947
- dirty: _,
948
- handleSubmit: z,
949
- submitCount: u
950
- } = c;
951
- return /* @__PURE__ */ e(
952
- fe,
1187
+ }
1188
+ });
1189
+ const {
1190
+ isSubmitting,
1191
+ touched,
1192
+ handleChange,
1193
+ values,
1194
+ errors,
1195
+ setFieldValue,
1196
+ dirty,
1197
+ handleSubmit,
1198
+ submitCount
1199
+ } = formex;
1200
+ return /* @__PURE__ */ jsx(
1201
+ Dialog,
953
1202
  {
954
- open: t,
955
- onOpenChange: (h) => h ? void 0 : n(),
1203
+ open,
1204
+ onOpenChange: (open2) => !open2 ? handleClose() : void 0,
956
1205
  maxWidth: "4xl",
957
- children: /* @__PURE__ */ e(De, { value: c, children: /* @__PURE__ */ s(
1206
+ children: /* @__PURE__ */ jsx(Formex, { value: formex, children: /* @__PURE__ */ jsxs(
958
1207
  "form",
959
1208
  {
960
- onSubmit: z,
1209
+ onSubmit: handleSubmit,
961
1210
  autoComplete: "off",
962
- noValidate: !0,
1211
+ noValidate: true,
963
1212
  style: {
964
1213
  display: "flex",
965
1214
  flexDirection: "column",
@@ -967,13 +1216,13 @@ function rn({
967
1216
  height: "100%"
968
1217
  },
969
1218
  children: [
970
- /* @__PURE__ */ s(ge, { className: "h-full flex-grow", children: [
971
- /* @__PURE__ */ e(
1219
+ /* @__PURE__ */ jsxs(DialogContent, { className: "h-full flex-grow", children: [
1220
+ /* @__PURE__ */ jsx(
972
1221
  "div",
973
1222
  {
974
1223
  className: "flex flex-row pt-4 pb-4",
975
- children: /* @__PURE__ */ e(
976
- P,
1224
+ children: /* @__PURE__ */ jsx(
1225
+ Typography,
977
1226
  {
978
1227
  variant: "h4",
979
1228
  className: "flex-grow",
@@ -982,80 +1231,77 @@ function rn({
982
1231
  )
983
1232
  }
984
1233
  ),
985
- /* @__PURE__ */ s("div", { className: "grid grid-cols-12 gap-8", children: [
986
- /* @__PURE__ */ s("div", { className: "col-span-12", children: [
987
- /* @__PURE__ */ e(
988
- Q,
1234
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-12 gap-8", children: [
1235
+ /* @__PURE__ */ jsxs("div", { className: "col-span-12", children: [
1236
+ /* @__PURE__ */ jsx(
1237
+ TextField,
989
1238
  {
990
1239
  name: "displayName",
991
- required: !0,
992
- error: u > 0 && !!y.displayName,
993
- value: C.displayName ?? "",
994
- onChange: a,
1240
+ required: true,
1241
+ error: submitCount > 0 && Boolean(errors.displayName),
1242
+ value: values.displayName ?? "",
1243
+ onChange: handleChange,
995
1244
  "aria-describedby": "name-helper-text",
996
1245
  label: "Name"
997
1246
  }
998
1247
  ),
999
- /* @__PURE__ */ e(B, { children: u > 0 && y.displayName ? y.displayName : "Name of this user" })
1248
+ /* @__PURE__ */ jsx(FieldCaption, { children: submitCount > 0 && Boolean(errors.displayName) ? errors.displayName : "Name of this user" })
1000
1249
  ] }),
1001
- /* @__PURE__ */ s("div", { className: "col-span-12", children: [
1002
- /* @__PURE__ */ e(
1003
- Q,
1250
+ /* @__PURE__ */ jsxs("div", { className: "col-span-12", children: [
1251
+ /* @__PURE__ */ jsx(
1252
+ TextField,
1004
1253
  {
1005
- required: !0,
1006
- error: u > 0 && !!y.email,
1254
+ required: true,
1255
+ error: submitCount > 0 && Boolean(errors.email),
1007
1256
  name: "email",
1008
- value: C.email ?? "",
1009
- onChange: a,
1257
+ value: values.email ?? "",
1258
+ onChange: handleChange,
1010
1259
  "aria-describedby": "email-helper-text",
1011
1260
  label: "Email"
1012
1261
  }
1013
1262
  ),
1014
- /* @__PURE__ */ e(B, { children: u > 0 && y.email ? y.email : "Email of this user" })
1263
+ /* @__PURE__ */ jsx(FieldCaption, { children: submitCount > 0 && Boolean(errors.email) ? errors.email : "Email of this user" })
1015
1264
  ] }),
1016
- /* @__PURE__ */ e("div", { className: "col-span-12", children: /* @__PURE__ */ e(
1017
- Le,
1265
+ /* @__PURE__ */ jsx("div", { className: "col-span-12", children: /* @__PURE__ */ jsx(
1266
+ MultiSelect,
1018
1267
  {
1268
+ className: "w-full",
1019
1269
  label: "Roles",
1020
- value: C.roles?.map((h) => h.id) ?? [],
1021
- onMultiValueChange: (h) => b("roles", h.map((x) => v.find((D) => D.id === x))),
1022
- renderValue: (h) => {
1023
- const x = v.find((D) => D.id === h);
1024
- return x ? /* @__PURE__ */ e("div", { className: "flex flex-wrap space-x-2 space-y-2", children: /* @__PURE__ */ e(X, { role: x }, x?.id) }) : null;
1025
- },
1026
- children: v.map((h) => /* @__PURE__ */ e(
1027
- Be,
1270
+ value: values.roles?.map((r) => r.id) ?? [],
1271
+ onValueChange: (value) => setFieldValue("roles", value.map((id) => roles.find((r) => r.id === id))),
1272
+ children: roles.map((userRole) => /* @__PURE__ */ jsx(
1273
+ MultiSelectItem,
1028
1274
  {
1029
- value: h.id,
1030
- children: /* @__PURE__ */ e(X, { role: h }, h?.id)
1275
+ value: userRole.id,
1276
+ children: /* @__PURE__ */ jsx(RoleChip, { role: userRole }, userRole?.id)
1031
1277
  },
1032
- h.id
1278
+ userRole.id
1033
1279
  ))
1034
1280
  }
1035
1281
  ) })
1036
1282
  ] })
1037
1283
  ] }),
1038
- /* @__PURE__ */ s(Ce, { children: [
1039
- /* @__PURE__ */ e(
1040
- O,
1284
+ /* @__PURE__ */ jsxs(DialogActions, { children: [
1285
+ /* @__PURE__ */ jsx(
1286
+ Button,
1041
1287
  {
1042
1288
  variant: "text",
1043
1289
  onClick: () => {
1044
- n();
1290
+ handleClose();
1045
1291
  },
1046
1292
  children: "Cancel"
1047
1293
  }
1048
1294
  ),
1049
- /* @__PURE__ */ e(
1050
- ve,
1295
+ /* @__PURE__ */ jsx(
1296
+ LoadingButton,
1051
1297
  {
1052
1298
  variant: "filled",
1053
1299
  color: "primary",
1054
1300
  type: "submit",
1055
- disabled: !_,
1056
- loading: E,
1057
- startIcon: /* @__PURE__ */ e(we, {}),
1058
- children: R ? "Create user" : "Update"
1301
+ disabled: !dirty,
1302
+ loading: isSubmitting,
1303
+ startIcon: /* @__PURE__ */ jsx(DoneIcon, {}),
1304
+ children: isNewUser ? "Create user" : "Update"
1059
1305
  }
1060
1306
  )
1061
1307
  ] })
@@ -1065,79 +1311,98 @@ function rn({
1065
1311
  }
1066
1312
  );
1067
1313
  }
1068
- function on({ onUserClicked: t }) {
1314
+ function UsersTable({ onUserClicked }) {
1069
1315
  const {
1070
- users: r,
1071
- saveUser: n,
1072
- deleteUser: l
1073
- } = j(), i = ae(), m = se(), g = Me(), v = g?.locale ? qe[g?.locale] : void 0, R = g?.dateTimeFormat ?? Oe, [w, c] = A(void 0), [E, U] = A(!1);
1074
- return /* @__PURE__ */ s("div", { className: "overflow-auto", children: [
1075
- /* @__PURE__ */ s(re, { children: [
1076
- /* @__PURE__ */ s(ie, { children: [
1077
- /* @__PURE__ */ e(d, { className: "truncate w-16" }),
1078
- /* @__PURE__ */ e(d, { children: "ID" }),
1079
- /* @__PURE__ */ e(d, { children: "Email" }),
1080
- /* @__PURE__ */ e(d, { children: "Name" }),
1081
- /* @__PURE__ */ e(d, { children: "Roles" }),
1082
- /* @__PURE__ */ e(d, { children: "Created on" })
1316
+ users,
1317
+ saveUser,
1318
+ deleteUser
1319
+ } = useUserManagement();
1320
+ const authController = useAuthController();
1321
+ const snackbarController = useSnackbarController();
1322
+ const customizationController = useCustomizationController();
1323
+ const dateUtilsLocale = customizationController?.locale ? locales[customizationController?.locale] : void 0;
1324
+ const dateFormat = customizationController?.dateTimeFormat ?? defaultDateFormat;
1325
+ const [userToBeDeleted, setUserToBeDeleted] = useState(void 0);
1326
+ const [deleteInProgress, setDeleteInProgress] = useState(false);
1327
+ return /* @__PURE__ */ jsxs("div", { className: "overflow-auto", children: [
1328
+ /* @__PURE__ */ jsxs(Table, { className: "w-full", children: [
1329
+ /* @__PURE__ */ jsxs(TableHeader, { children: [
1330
+ /* @__PURE__ */ jsx(TableCell, { className: "truncate w-16" }),
1331
+ /* @__PURE__ */ jsx(TableCell, { children: "ID" }),
1332
+ /* @__PURE__ */ jsx(TableCell, { children: "Email" }),
1333
+ /* @__PURE__ */ jsx(TableCell, { children: "Name" }),
1334
+ /* @__PURE__ */ jsx(TableCell, { children: "Roles" }),
1335
+ /* @__PURE__ */ jsx(TableCell, { children: "Created on" })
1083
1336
  ] }),
1084
- /* @__PURE__ */ s(oe, { children: [
1085
- r && r.map((a) => {
1086
- const C = a.roles, y = a.created_on ? $e(a.created_on, R, { locale: v }) : "";
1087
- return /* @__PURE__ */ s(
1088
- W,
1337
+ /* @__PURE__ */ jsxs(TableBody, { children: [
1338
+ users && users.map((user) => {
1339
+ const userRoles = user.roles;
1340
+ const formattedDate = user.created_on ? format(user.created_on, dateFormat, { locale: dateUtilsLocale }) : "";
1341
+ return /* @__PURE__ */ jsxs(
1342
+ TableRow,
1089
1343
  {
1090
1344
  onClick: () => {
1091
- t(a);
1345
+ onUserClicked(user);
1092
1346
  },
1093
1347
  children: [
1094
- /* @__PURE__ */ e(d, { className: "w-10", children: /* @__PURE__ */ e(V, { title: "Delete this user", children: /* @__PURE__ */ e(
1095
- ye,
1348
+ /* @__PURE__ */ jsx(TableCell, { className: "w-10", children: /* @__PURE__ */ jsx(
1349
+ Tooltip,
1096
1350
  {
1097
- size: "small",
1098
- onClick: (b) => (b.stopPropagation(), c(a)),
1099
- children: /* @__PURE__ */ e(be, {})
1351
+ asChild: true,
1352
+ title: "Delete this user",
1353
+ children: /* @__PURE__ */ jsx(
1354
+ IconButton,
1355
+ {
1356
+ size: "small",
1357
+ onClick: (event) => {
1358
+ event.stopPropagation();
1359
+ return setUserToBeDeleted(user);
1360
+ },
1361
+ children: /* @__PURE__ */ jsx(DeleteIcon, {})
1362
+ }
1363
+ )
1100
1364
  }
1101
- ) }) }),
1102
- /* @__PURE__ */ e(d, { children: a.uid }),
1103
- /* @__PURE__ */ e(d, { children: a.email }),
1104
- /* @__PURE__ */ e(d, { className: "font-medium align-left", children: a.displayName }),
1105
- /* @__PURE__ */ e(d, { className: "align-left", children: C ? /* @__PURE__ */ e("div", { className: "flex flex-wrap gap-2", children: C.map(
1106
- (b) => /* @__PURE__ */ e(X, { role: b }, b?.id)
1365
+ ) }),
1366
+ /* @__PURE__ */ jsx(TableCell, { children: user.uid }),
1367
+ /* @__PURE__ */ jsx(TableCell, { children: user.email }),
1368
+ /* @__PURE__ */ jsx(TableCell, { className: "font-medium align-left", children: user.displayName }),
1369
+ /* @__PURE__ */ jsx(TableCell, { className: "align-left", children: userRoles ? /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: userRoles.map(
1370
+ (userRole) => /* @__PURE__ */ jsx(RoleChip, { role: userRole }, userRole?.id)
1107
1371
  ) }) : null }),
1108
- /* @__PURE__ */ e(d, { children: y })
1372
+ /* @__PURE__ */ jsx(TableCell, { children: formattedDate })
1109
1373
  ]
1110
1374
  },
1111
- "row_" + a.uid
1375
+ "row_" + user.uid
1112
1376
  );
1113
1377
  }),
1114
- (!r || r.length === 0) && /* @__PURE__ */ e(W, { children: /* @__PURE__ */ e(d, { colspan: 6, children: /* @__PURE__ */ s(Ne, { className: "flex flex-col gap-4 my-8 items-center", children: [
1115
- /* @__PURE__ */ e(P, { variant: "label", children: "There are no users yet" }),
1116
- /* @__PURE__ */ e(
1117
- O,
1378
+ (!users || users.length === 0) && /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colspan: 6, children: /* @__PURE__ */ jsxs(CenteredView, { className: "flex flex-col gap-4 my-8 items-center", children: [
1379
+ /* @__PURE__ */ jsx(Typography, { variant: "label", children: "There are no users yet" }),
1380
+ /* @__PURE__ */ jsx(
1381
+ Button,
1118
1382
  {
1119
1383
  variant: "outlined",
1120
1384
  onClick: () => {
1121
- if (!i.user?.uid)
1385
+ if (!authController.user?.uid) {
1122
1386
  throw Error("UsersTable, authController misconfiguration");
1123
- n({
1124
- uid: i.user?.uid,
1125
- email: i.user?.email,
1126
- displayName: i.user?.displayName,
1127
- photoURL: i.user?.photoURL,
1128
- providerId: i.user?.providerId,
1129
- isAnonymous: i.user?.isAnonymous,
1387
+ }
1388
+ saveUser({
1389
+ uid: authController.user?.uid,
1390
+ email: authController.user?.email,
1391
+ displayName: authController.user?.displayName,
1392
+ photoURL: authController.user?.photoURL,
1393
+ providerId: authController.user?.providerId,
1394
+ isAnonymous: authController.user?.isAnonymous,
1130
1395
  roles: [{ id: "admin", name: "Admin" }],
1131
1396
  created_on: /* @__PURE__ */ new Date()
1132
1397
  }).then(() => {
1133
- m.open({
1398
+ snackbarController.open({
1134
1399
  type: "success",
1135
1400
  message: "User added successfully"
1136
1401
  });
1137
- }).catch((a) => {
1138
- m.open({
1402
+ }).catch((error) => {
1403
+ snackbarController.open({
1139
1404
  type: "error",
1140
- message: "Error adding user: " + a.message
1405
+ message: "Error adding user: " + error.message
1141
1406
  });
1142
1407
  });
1143
1408
  },
@@ -1147,193 +1412,212 @@ function on({ onUserClicked: t }) {
1147
1412
  ] }) }) })
1148
1413
  ] })
1149
1414
  ] }),
1150
- /* @__PURE__ */ e(
1151
- xe,
1415
+ /* @__PURE__ */ jsx(
1416
+ DeleteConfirmationDialog,
1152
1417
  {
1153
- open: !!w,
1154
- loading: E,
1418
+ open: Boolean(userToBeDeleted),
1419
+ loading: deleteInProgress,
1155
1420
  onAccept: () => {
1156
- w && (U(!0), l(w).then(() => {
1157
- c(void 0);
1158
- }).catch((a) => {
1159
- m.open({
1160
- type: "error",
1161
- message: "Error deleting user: " + a.message
1421
+ if (userToBeDeleted) {
1422
+ setDeleteInProgress(true);
1423
+ deleteUser(userToBeDeleted).then(() => {
1424
+ setUserToBeDeleted(void 0);
1425
+ }).catch((error) => {
1426
+ snackbarController.open({
1427
+ type: "error",
1428
+ message: "Error deleting user: " + error.message
1429
+ });
1430
+ }).finally(() => {
1431
+ setDeleteInProgress(false);
1162
1432
  });
1163
- }).finally(() => {
1164
- U(!1);
1165
- }));
1433
+ }
1166
1434
  },
1167
1435
  onCancel: () => {
1168
- c(void 0);
1436
+ setUserToBeDeleted(void 0);
1169
1437
  },
1170
- title: /* @__PURE__ */ e(K, { children: "Delete?" }),
1171
- body: /* @__PURE__ */ e(K, { children: "Are you sure you want to delete this user?" })
1438
+ title: /* @__PURE__ */ jsx(Fragment, { children: "Delete?" }),
1439
+ body: /* @__PURE__ */ jsx(Fragment, { children: "Are you sure you want to delete this user?" })
1172
1440
  }
1173
1441
  )
1174
1442
  ] });
1175
1443
  }
1176
- const ln = function({ children: r }) {
1177
- const [n, l] = A(), [i, m] = A(), { users: g, usersLimit: v } = j(), R = v !== void 0 && g && g.length >= v, w = k((E) => {
1178
- m(E), l(!0);
1179
- }, []), c = k(() => {
1180
- l(!1), m(void 0);
1444
+ const UsersView = function UsersView2({ children }) {
1445
+ const [dialogOpen, setDialogOpen] = useState();
1446
+ const [selectedUser, setSelectedUser] = useState();
1447
+ const { users, usersLimit } = useUserManagement();
1448
+ const reachedUsersLimit = usersLimit !== void 0 && (users && users.length >= usersLimit);
1449
+ const onUserClicked = useCallback((user) => {
1450
+ setSelectedUser(user);
1451
+ setDialogOpen(true);
1452
+ }, []);
1453
+ const handleClose = useCallback(() => {
1454
+ setDialogOpen(false);
1455
+ setSelectedUser(void 0);
1181
1456
  }, []);
1182
- return /* @__PURE__ */ s(Ue, { className: "w-full flex flex-col py-4 gap-4", maxWidth: "6xl", children: [
1183
- r,
1184
- /* @__PURE__ */ s(
1457
+ return /* @__PURE__ */ jsxs(Container, { className: "w-full flex flex-col py-4 gap-4", maxWidth: "6xl", children: [
1458
+ children,
1459
+ /* @__PURE__ */ jsxs(
1185
1460
  "div",
1186
1461
  {
1187
1462
  className: "flex items-center mt-12",
1188
1463
  children: [
1189
- /* @__PURE__ */ e(
1190
- P,
1464
+ /* @__PURE__ */ jsx(
1465
+ Typography,
1191
1466
  {
1192
- gutterBottom: !0,
1467
+ gutterBottom: true,
1193
1468
  variant: "h4",
1194
1469
  className: "flex-grow",
1195
1470
  component: "h4",
1196
1471
  children: "Users"
1197
1472
  }
1198
1473
  ),
1199
- /* @__PURE__ */ e(
1200
- O,
1474
+ /* @__PURE__ */ jsx(
1475
+ Button,
1201
1476
  {
1202
1477
  size: "large",
1203
- disabled: R,
1204
- startIcon: /* @__PURE__ */ e(le, {}),
1205
- onClick: () => l(!0),
1478
+ disabled: reachedUsersLimit,
1479
+ startIcon: /* @__PURE__ */ jsx(AddIcon, {}),
1480
+ onClick: () => setDialogOpen(true),
1206
1481
  children: "Add user"
1207
1482
  }
1208
1483
  )
1209
1484
  ]
1210
1485
  }
1211
1486
  ),
1212
- /* @__PURE__ */ e(on, { onUserClicked: w }),
1213
- /* @__PURE__ */ e(
1214
- rn,
1487
+ /* @__PURE__ */ jsx(UsersTable, { onUserClicked }),
1488
+ /* @__PURE__ */ jsx(
1489
+ UserDetailsForm,
1215
1490
  {
1216
- open: n ?? !1,
1217
- user: i,
1218
- handleClose: c
1491
+ open: dialogOpen ?? false,
1492
+ user: selectedUser,
1493
+ handleClose
1219
1494
  },
1220
- i?.uid ?? "new"
1495
+ selectedUser?.uid ?? "new"
1221
1496
  )
1222
1497
  ] });
1223
1498
  };
1224
- function Un({ userManagement: t }) {
1225
- const r = t.users.length === 0, n = t.roles.length === 0;
1499
+ function useUserManagementPlugin({ userManagement }) {
1500
+ const noUsers = userManagement.users.length === 0;
1501
+ const noRoles = userManagement.roles.length === 0;
1226
1502
  return {
1227
1503
  key: "user_management",
1228
- loading: t.loading,
1504
+ loading: userManagement.loading,
1229
1505
  homePage: {
1230
- additionalChildrenStart: r || n ? /* @__PURE__ */ e(
1231
- sn,
1506
+ additionalChildrenStart: noUsers || noRoles ? /* @__PURE__ */ jsx(
1507
+ IntroWidget,
1232
1508
  {
1233
- noUsers: r,
1234
- noRoles: n,
1235
- userManagement: t
1509
+ noUsers,
1510
+ noRoles,
1511
+ userManagement
1236
1512
  }
1237
1513
  ) : void 0
1238
1514
  },
1239
1515
  provider: {
1240
- Component: Ke,
1516
+ Component: UserManagementProvider,
1241
1517
  props: {
1242
- userManagement: t
1518
+ userManagement
1243
1519
  }
1244
1520
  }
1245
1521
  };
1246
1522
  }
1247
- function sn({
1248
- noUsers: t,
1249
- noRoles: r,
1250
- userManagement: n
1523
+ function IntroWidget({
1524
+ noUsers,
1525
+ noRoles,
1526
+ userManagement
1251
1527
  }) {
1252
- const l = ae(), i = se();
1253
- return /* @__PURE__ */ s(
1254
- pe,
1528
+ const authController = useAuthController();
1529
+ const snackbarController = useSnackbarController();
1530
+ const buttonLabel = noUsers && noRoles ? "Create default roles and add current user as admin" : noUsers ? "Add current user as admin" : noRoles ? "Create default roles" : void 0;
1531
+ return /* @__PURE__ */ jsxs(
1532
+ Paper,
1255
1533
  {
1256
1534
  className: "my-4 flex flex-col px-4 py-6 bg-white dark:bg-slate-800 gap-2",
1257
1535
  children: [
1258
- /* @__PURE__ */ e(P, { variant: "subtitle2", className: "uppercase", children: "Create your users and roles" }),
1259
- /* @__PURE__ */ e(P, { children: "You have no users or roles defined. You can create default roles and add the current user as admin." }),
1260
- /* @__PURE__ */ s(O, { onClick: () => {
1261
- if (!l.user?.uid)
1536
+ /* @__PURE__ */ jsx(Typography, { variant: "subtitle2", className: "uppercase", children: "Create your users and roles" }),
1537
+ /* @__PURE__ */ jsx(Typography, { children: "You have no users or roles defined. You can create default roles and add the current user as admin." }),
1538
+ /* @__PURE__ */ jsxs(Button, { onClick: () => {
1539
+ if (!authController.user?.uid) {
1262
1540
  throw Error("UsersTable, authController misconfiguration");
1263
- t && n.saveUser({
1264
- uid: l.user?.uid,
1265
- email: l.user?.email,
1266
- displayName: l.user?.displayName,
1267
- photoURL: l.user?.photoURL,
1268
- providerId: l.user?.providerId,
1269
- isAnonymous: l.user?.isAnonymous,
1270
- roles: [{
1271
- id: "admin",
1272
- name: "Admin"
1273
- }],
1274
- created_on: /* @__PURE__ */ new Date()
1275
- }).then(() => {
1276
- i.open({
1277
- type: "success",
1278
- message: "User added successfully"
1541
+ }
1542
+ if (noUsers) {
1543
+ userManagement.saveUser({
1544
+ uid: authController.user?.uid,
1545
+ email: authController.user?.email,
1546
+ displayName: authController.user?.displayName,
1547
+ photoURL: authController.user?.photoURL,
1548
+ providerId: authController.user?.providerId,
1549
+ isAnonymous: authController.user?.isAnonymous,
1550
+ roles: [{
1551
+ id: "admin",
1552
+ name: "Admin"
1553
+ }],
1554
+ created_on: /* @__PURE__ */ new Date()
1555
+ }).then(() => {
1556
+ snackbarController.open({
1557
+ type: "success",
1558
+ message: "User added successfully"
1559
+ });
1560
+ }).catch((error) => {
1561
+ snackbarController.open({
1562
+ type: "error",
1563
+ message: "Error adding user: " + error.message
1564
+ });
1279
1565
  });
1280
- }).catch((g) => {
1281
- i.open({
1282
- type: "error",
1283
- message: "Error adding user: " + g.message
1566
+ }
1567
+ if (noRoles) {
1568
+ DEFAULT_ROLES.forEach((role) => {
1569
+ userManagement.saveRole(role);
1284
1570
  });
1285
- }), r && Se.forEach((g) => {
1286
- n.saveRole(g);
1287
- });
1571
+ }
1288
1572
  }, children: [
1289
- /* @__PURE__ */ e(le, {}),
1290
- t && r ? "Create default roles and add current user as admin" : t ? "Add current user as admin" : r ? "Create default roles" : void 0
1573
+ /* @__PURE__ */ jsx(AddIcon, {}),
1574
+ buttonLabel
1291
1575
  ] })
1292
1576
  ]
1293
1577
  }
1294
1578
  );
1295
1579
  }
1296
- const xn = [
1580
+ const userManagementAdminViews = [
1297
1581
  {
1298
1582
  path: "users",
1299
1583
  name: "CMS Users",
1300
1584
  group: "Admin",
1301
1585
  icon: "face",
1302
- view: /* @__PURE__ */ e(ln, {})
1586
+ view: /* @__PURE__ */ jsx(UsersView, {})
1303
1587
  },
1304
1588
  {
1305
1589
  path: "roles",
1306
1590
  name: "Roles",
1307
1591
  group: "Admin",
1308
1592
  icon: "gpp_good",
1309
- view: /* @__PURE__ */ e(en, {})
1593
+ view: /* @__PURE__ */ jsx(RolesView, {})
1310
1594
  }
1311
1595
  ];
1312
1596
  export {
1313
- sn as IntroWidget,
1314
- gn as RESERVED_GROUPS,
1315
- X as RoleChip,
1316
- Qe as RoleYupSchema,
1317
- Xe as RolesDetailsForm,
1318
- Ze as RolesTable,
1319
- en as RolesView,
1320
- rn as UserDetailsForm,
1321
- Ee as UserManagementContext,
1322
- Ke as UserManagementProvider,
1323
- nn as UserYupSchema,
1324
- on as UsersTable,
1325
- ln as UsersView,
1326
- ze as areRolesEqual,
1327
- Cn as cacheDelegatedLoginToken,
1328
- wn as clearDelegatedLoginTokensCache,
1329
- yn as darkenColor,
1330
- vn as getDelegatedLoginTokenFromCache,
1331
- pn as getUserRoles,
1332
- bn as hexToRgbaWithOpacity,
1333
- We as resolveUserRolePermissions,
1334
- Nn as useFirestoreUserManagement,
1335
- j as useUserManagement,
1336
- Un as useUserManagementPlugin,
1337
- xn as userManagementAdminViews
1597
+ IntroWidget,
1598
+ RESERVED_GROUPS,
1599
+ RoleChip,
1600
+ RoleYupSchema,
1601
+ RolesDetailsForm,
1602
+ RolesTable,
1603
+ RolesView,
1604
+ UserDetailsForm,
1605
+ UserManagementContext,
1606
+ UserManagementProvider,
1607
+ UserYupSchema,
1608
+ UsersTable,
1609
+ UsersView,
1610
+ areRolesEqual,
1611
+ cacheDelegatedLoginToken,
1612
+ clearDelegatedLoginTokensCache,
1613
+ darkenColor,
1614
+ getDelegatedLoginTokenFromCache,
1615
+ getUserRoles,
1616
+ hexToRgbaWithOpacity,
1617
+ resolveUserRolePermissions,
1618
+ useBuildUserManagement,
1619
+ useUserManagement,
1620
+ useUserManagementPlugin,
1621
+ userManagementAdminViews
1338
1622
  };
1339
1623
  //# sourceMappingURL=index.es.js.map