@firecms/user_management 3.0.0-canary.13 → 3.0.0-canary.130

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