@firecms/user_management 3.0.0-3.0.0-canary.27.0 → 3.0.0-beta.10

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