@firecms/user_management 3.0.0-canary.12 → 3.0.0-canary.120

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, DeleteConfirmationDialog, useNavigationController, useSnackbarController, useCustomizationController, defaultDateFormat } from "@firecms/core";
4
+ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
5
+ import { getColorSchemeForSeed, Chip, Dialog, DialogContent, Typography, TextField, Paper, Table, TableHeader, TableCell, TableBody, TableRow, Tooltip, Checkbox, Button, Select, SelectItem, DialogActions, LoadingButton, DoneIcon, IconButton, DeleteIcon, CenteredView, Container, AddIcon, MultiSelect, MultiSelectItem } from "@firecms/ui";
6
+ import * as Yup from "yup";
7
+ import { useCreateFormex, getIn, Formex } from "@firecms/formex";
8
+ import { format } from "date-fns";
9
+ import * as locales from "date-fns/locale";
10
+ const RESERVED_GROUPS = ["Admin"];
11
+ const DEFAULT_PERMISSIONS = {
12
+ read: false,
13
+ edit: false,
14
+ create: false,
15
+ delete: false
15
16
  };
16
- function 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,
44
+ create: role.isAdmin || role.defaultPermissions?.create,
45
+ edit: role.isAdmin || role.defaultPermissions?.edit,
46
+ delete: role.isAdmin || role.defaultPermissions?.delete
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
+ DeleteConfirmationDialog,
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,81 @@ 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
  {
1015
1268
  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;
1269
+ value: values.roles?.map((r) => r.id) ?? [],
1270
+ onMultiValueChange: (value) => setFieldValue("roles", value.map((id) => roles.find((r) => r.id === id))),
1271
+ renderValue: (value) => {
1272
+ const userRole = roles.find((role) => role.id === value);
1273
+ if (!userRole) return null;
1274
+ return /* @__PURE__ */ jsx("div", { className: "flex flex-wrap space-x-2 space-y-2", children: /* @__PURE__ */ jsx(RoleChip, { role: userRole }, userRole?.id) });
1021
1275
  },
1022
- children: h.map((u) => /* @__PURE__ */ e(
1023
- Te,
1276
+ children: roles.map((userRole) => /* @__PURE__ */ jsx(
1277
+ MultiSelectItem,
1024
1278
  {
1025
- value: u.id,
1026
- children: /* @__PURE__ */ e(Q, { role: u }, u?.id)
1279
+ value: userRole.id,
1280
+ children: /* @__PURE__ */ jsx(RoleChip, { role: userRole }, userRole?.id)
1027
1281
  },
1028
- u.id
1282
+ userRole.id
1029
1283
  ))
1030
1284
  }
1031
1285
  ) })
1032
1286
  ] })
1033
1287
  ] }),
1034
- /* @__PURE__ */ l(me, { children: [
1035
- /* @__PURE__ */ e(
1036
- q,
1288
+ /* @__PURE__ */ jsxs(DialogActions, { children: [
1289
+ /* @__PURE__ */ jsx(
1290
+ Button,
1037
1291
  {
1038
1292
  variant: "text",
1039
1293
  onClick: () => {
1040
- n();
1294
+ handleClose();
1041
1295
  },
1042
1296
  children: "Cancel"
1043
1297
  }
1044
1298
  ),
1045
- /* @__PURE__ */ e(
1046
- he,
1299
+ /* @__PURE__ */ jsx(
1300
+ LoadingButton,
1047
1301
  {
1048
1302
  variant: "filled",
1049
1303
  color: "primary",
1050
1304
  type: "submit",
1051
- disabled: !z,
1052
- loading: I,
1053
- startIcon: /* @__PURE__ */ e(fe, {}),
1054
- children: x ? "Create user" : "Update"
1305
+ disabled: !dirty,
1306
+ loading: isSubmitting,
1307
+ startIcon: /* @__PURE__ */ jsx(DoneIcon, {}),
1308
+ children: isNewUser ? "Create user" : "Update"
1055
1309
  }
1056
1310
  )
1057
1311
  ] })
@@ -1061,79 +1315,98 @@ function tn({
1061
1315
  }
1062
1316
  );
1063
1317
  }
1064
- function rn({ onUserClicked: t }) {
1318
+ function UsersTable({ onUserClicked }) {
1065
1319
  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" })
1320
+ users,
1321
+ saveUser,
1322
+ deleteUser
1323
+ } = useUserManagement();
1324
+ const authController = useAuthController();
1325
+ const snackbarController = useSnackbarController();
1326
+ const customizationController = useCustomizationController();
1327
+ const dateUtilsLocale = customizationController?.locale ? locales[customizationController?.locale] : void 0;
1328
+ const dateFormat = customizationController?.dateTimeFormat ?? defaultDateFormat;
1329
+ const [userToBeDeleted, setUserToBeDeleted] = useState(void 0);
1330
+ const [deleteInProgress, setDeleteInProgress] = useState(false);
1331
+ return /* @__PURE__ */ jsxs("div", { className: "overflow-auto", children: [
1332
+ /* @__PURE__ */ jsxs(Table, { className: "w-full", children: [
1333
+ /* @__PURE__ */ jsxs(TableHeader, { children: [
1334
+ /* @__PURE__ */ jsx(TableCell, { className: "truncate w-16" }),
1335
+ /* @__PURE__ */ jsx(TableCell, { children: "ID" }),
1336
+ /* @__PURE__ */ jsx(TableCell, { children: "Email" }),
1337
+ /* @__PURE__ */ jsx(TableCell, { children: "Name" }),
1338
+ /* @__PURE__ */ jsx(TableCell, { children: "Roles" }),
1339
+ /* @__PURE__ */ jsx(TableCell, { children: "Created on" })
1079
1340
  ] }),
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,
1341
+ /* @__PURE__ */ jsxs(TableBody, { children: [
1342
+ users && users.map((user) => {
1343
+ const userRoles = user.roles;
1344
+ const formattedDate = user.created_on ? format(user.created_on, dateFormat, { locale: dateUtilsLocale }) : "";
1345
+ return /* @__PURE__ */ jsxs(
1346
+ TableRow,
1085
1347
  {
1086
1348
  onClick: () => {
1087
- t(s);
1349
+ onUserClicked(user);
1088
1350
  },
1089
1351
  children: [
1090
- /* @__PURE__ */ e(a, { className: "w-10", children: /* @__PURE__ */ e(V, { title: "Delete this user", children: /* @__PURE__ */ e(
1091
- ge,
1352
+ /* @__PURE__ */ jsx(TableCell, { className: "w-10", children: /* @__PURE__ */ jsx(
1353
+ Tooltip,
1092
1354
  {
1093
- size: "small",
1094
- onClick: (w) => (w.stopPropagation(), d(s)),
1095
- children: /* @__PURE__ */ e(pe, {})
1355
+ asChild: true,
1356
+ title: "Delete this user",
1357
+ children: /* @__PURE__ */ jsx(
1358
+ IconButton,
1359
+ {
1360
+ size: "small",
1361
+ onClick: (event) => {
1362
+ event.stopPropagation();
1363
+ return setUserToBeDeleted(user);
1364
+ },
1365
+ children: /* @__PURE__ */ jsx(DeleteIcon, {})
1366
+ }
1367
+ )
1096
1368
  }
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)
1369
+ ) }),
1370
+ /* @__PURE__ */ jsx(TableCell, { children: user.uid }),
1371
+ /* @__PURE__ */ jsx(TableCell, { children: user.email }),
1372
+ /* @__PURE__ */ jsx(TableCell, { className: "font-medium align-left", children: user.displayName }),
1373
+ /* @__PURE__ */ jsx(TableCell, { className: "align-left", children: userRoles ? /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: userRoles.map(
1374
+ (userRole) => /* @__PURE__ */ jsx(RoleChip, { role: userRole }, userRole?.id)
1103
1375
  ) }) : null }),
1104
- /* @__PURE__ */ e(a, { children: D })
1376
+ /* @__PURE__ */ jsx(TableCell, { children: formattedDate })
1105
1377
  ]
1106
1378
  },
1107
- "row_" + s.uid
1379
+ "row_" + user.uid
1108
1380
  );
1109
1381
  }),
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,
1382
+ (!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: [
1383
+ /* @__PURE__ */ jsx(Typography, { variant: "label", children: "There are no users yet" }),
1384
+ /* @__PURE__ */ jsx(
1385
+ Button,
1114
1386
  {
1115
1387
  variant: "outlined",
1116
1388
  onClick: () => {
1117
- if (!r.user?.uid)
1389
+ if (!authController.user?.uid) {
1118
1390
  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,
1391
+ }
1392
+ saveUser({
1393
+ uid: authController.user?.uid,
1394
+ email: authController.user?.email,
1395
+ displayName: authController.user?.displayName,
1396
+ photoURL: authController.user?.photoURL,
1397
+ providerId: authController.user?.providerId,
1398
+ isAnonymous: authController.user?.isAnonymous,
1126
1399
  roles: [{ id: "admin", name: "Admin" }],
1127
1400
  created_on: /* @__PURE__ */ new Date()
1128
1401
  }).then(() => {
1129
- m.open({
1402
+ snackbarController.open({
1130
1403
  type: "success",
1131
1404
  message: "User added successfully"
1132
1405
  });
1133
- }).catch((s) => {
1134
- m.open({
1406
+ }).catch((error) => {
1407
+ snackbarController.open({
1135
1408
  type: "error",
1136
- message: "Error adding user: " + s.message
1409
+ message: "Error adding user: " + error.message
1137
1410
  });
1138
1411
  });
1139
1412
  },
@@ -1143,132 +1416,212 @@ function rn({ onUserClicked: t }) {
1143
1416
  ] }) }) })
1144
1417
  ] })
1145
1418
  ] }),
1146
- /* @__PURE__ */ e(
1147
- ye,
1419
+ /* @__PURE__ */ jsx(
1420
+ DeleteConfirmationDialog,
1148
1421
  {
1149
- open: !!v,
1150
- loading: I,
1422
+ open: Boolean(userToBeDeleted),
1423
+ loading: deleteInProgress,
1151
1424
  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
1425
+ if (userToBeDeleted) {
1426
+ setDeleteInProgress(true);
1427
+ deleteUser(userToBeDeleted).then(() => {
1428
+ setUserToBeDeleted(void 0);
1429
+ }).catch((error) => {
1430
+ snackbarController.open({
1431
+ type: "error",
1432
+ message: "Error deleting user: " + error.message
1433
+ });
1434
+ }).finally(() => {
1435
+ setDeleteInProgress(false);
1158
1436
  });
1159
- }).finally(() => {
1160
- b(!1);
1161
- }));
1437
+ }
1162
1438
  },
1163
1439
  onCancel: () => {
1164
- d(void 0);
1440
+ setUserToBeDeleted(void 0);
1165
1441
  },
1166
- title: /* @__PURE__ */ e(H, { children: "Delete?" }),
1167
- body: /* @__PURE__ */ e(H, { children: "Are you sure you want to delete this user?" })
1442
+ title: /* @__PURE__ */ jsx(Fragment, { children: "Delete?" }),
1443
+ body: /* @__PURE__ */ jsx(Fragment, { children: "Are you sure you want to delete this user?" })
1168
1444
  }
1169
1445
  )
1170
1446
  ] });
1171
1447
  }
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);
1448
+ const UsersView = function UsersView2({ children }) {
1449
+ const [dialogOpen, setDialogOpen] = useState();
1450
+ const [selectedUser, setSelectedUser] = useState();
1451
+ const { users, usersLimit } = useUserManagement();
1452
+ const reachedUsersLimit = usersLimit !== void 0 && (users && users.length >= usersLimit);
1453
+ const onUserClicked = useCallback((user) => {
1454
+ setSelectedUser(user);
1455
+ setDialogOpen(true);
1456
+ }, []);
1457
+ const handleClose = useCallback(() => {
1458
+ setDialogOpen(false);
1459
+ setSelectedUser(void 0);
1177
1460
  }, []);
1178
- return /* @__PURE__ */ l(ve, { className: "w-full flex flex-col py-4 gap-4", maxWidth: "6xl", children: [
1179
- i,
1180
- /* @__PURE__ */ l(
1461
+ return /* @__PURE__ */ jsxs(Container, { className: "w-full flex flex-col py-4 gap-4", maxWidth: "6xl", children: [
1462
+ children,
1463
+ /* @__PURE__ */ jsxs(
1181
1464
  "div",
1182
1465
  {
1183
1466
  className: "flex items-center mt-12",
1184
1467
  children: [
1185
- /* @__PURE__ */ e(
1186
- O,
1468
+ /* @__PURE__ */ jsx(
1469
+ Typography,
1187
1470
  {
1188
- gutterBottom: !0,
1471
+ gutterBottom: true,
1189
1472
  variant: "h4",
1190
1473
  className: "flex-grow",
1191
1474
  component: "h4",
1192
1475
  children: "Users"
1193
1476
  }
1194
1477
  ),
1195
- /* @__PURE__ */ e(
1196
- q,
1478
+ /* @__PURE__ */ jsx(
1479
+ Button,
1197
1480
  {
1198
1481
  size: "large",
1199
- disabled: x,
1200
- startIcon: /* @__PURE__ */ e(we, {}),
1201
- onClick: () => c(!0),
1482
+ disabled: reachedUsersLimit,
1483
+ startIcon: /* @__PURE__ */ jsx(AddIcon, {}),
1484
+ onClick: () => setDialogOpen(true),
1202
1485
  children: "Add user"
1203
1486
  }
1204
1487
  )
1205
1488
  ]
1206
1489
  }
1207
1490
  ),
1208
- /* @__PURE__ */ e(rn, { onUserClicked: v }),
1209
- /* @__PURE__ */ e(
1210
- tn,
1491
+ /* @__PURE__ */ jsx(UsersTable, { onUserClicked }),
1492
+ /* @__PURE__ */ jsx(
1493
+ UserDetailsForm,
1211
1494
  {
1212
- open: n ?? !1,
1213
- user: r,
1214
- handleClose: d
1495
+ open: dialogOpen ?? false,
1496
+ user: selectedUser,
1497
+ handleClose
1215
1498
  },
1216
- r?.uid ?? "new"
1499
+ selectedUser?.uid ?? "new"
1217
1500
  )
1218
1501
  ] });
1219
1502
  };
1220
- function bn({ userManagement: t }) {
1503
+ function useUserManagementPlugin({ userManagement }) {
1504
+ const noUsers = userManagement.users.length === 0;
1505
+ const noRoles = userManagement.roles.length === 0;
1221
1506
  return {
1222
1507
  key: "user_management",
1223
- loading: t.loading,
1508
+ loading: userManagement.loading,
1509
+ homePage: {
1510
+ additionalChildrenStart: noUsers || noRoles ? /* @__PURE__ */ jsx(
1511
+ IntroWidget,
1512
+ {
1513
+ noUsers,
1514
+ noRoles,
1515
+ userManagement
1516
+ }
1517
+ ) : void 0
1518
+ },
1224
1519
  provider: {
1225
- Component: Ge,
1520
+ Component: UserManagementProvider,
1226
1521
  props: {
1227
- userManagement: t
1522
+ userManagement
1228
1523
  }
1229
1524
  }
1230
1525
  };
1231
1526
  }
1232
- const Nn = [
1527
+ function IntroWidget({
1528
+ noUsers,
1529
+ noRoles,
1530
+ userManagement
1531
+ }) {
1532
+ const authController = useAuthController();
1533
+ const snackbarController = useSnackbarController();
1534
+ 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;
1535
+ return /* @__PURE__ */ jsxs(
1536
+ Paper,
1537
+ {
1538
+ className: "my-4 flex flex-col px-4 py-6 bg-white dark:bg-slate-800 gap-2",
1539
+ children: [
1540
+ /* @__PURE__ */ jsx(Typography, { variant: "subtitle2", className: "uppercase", children: "Create your users and roles" }),
1541
+ /* @__PURE__ */ jsx(Typography, { children: "You have no users or roles defined. You can create default roles and add the current user as admin." }),
1542
+ /* @__PURE__ */ jsxs(Button, { onClick: () => {
1543
+ if (!authController.user?.uid) {
1544
+ throw Error("UsersTable, authController misconfiguration");
1545
+ }
1546
+ if (noUsers) {
1547
+ userManagement.saveUser({
1548
+ uid: authController.user?.uid,
1549
+ email: authController.user?.email,
1550
+ displayName: authController.user?.displayName,
1551
+ photoURL: authController.user?.photoURL,
1552
+ providerId: authController.user?.providerId,
1553
+ isAnonymous: authController.user?.isAnonymous,
1554
+ roles: [{
1555
+ id: "admin",
1556
+ name: "Admin"
1557
+ }],
1558
+ created_on: /* @__PURE__ */ new Date()
1559
+ }).then(() => {
1560
+ snackbarController.open({
1561
+ type: "success",
1562
+ message: "User added successfully"
1563
+ });
1564
+ }).catch((error) => {
1565
+ snackbarController.open({
1566
+ type: "error",
1567
+ message: "Error adding user: " + error.message
1568
+ });
1569
+ });
1570
+ }
1571
+ if (noRoles) {
1572
+ DEFAULT_ROLES.forEach((role) => {
1573
+ userManagement.saveRole(role);
1574
+ });
1575
+ }
1576
+ }, children: [
1577
+ /* @__PURE__ */ jsx(AddIcon, {}),
1578
+ buttonLabel
1579
+ ] })
1580
+ ]
1581
+ }
1582
+ );
1583
+ }
1584
+ const userManagementAdminViews = [
1233
1585
  {
1234
1586
  path: "users",
1235
1587
  name: "CMS Users",
1236
1588
  group: "Admin",
1237
1589
  icon: "face",
1238
- view: /* @__PURE__ */ e(on, {})
1590
+ view: /* @__PURE__ */ jsx(UsersView, {})
1239
1591
  },
1240
1592
  {
1241
1593
  path: "roles",
1242
1594
  name: "Roles",
1243
1595
  group: "Admin",
1244
1596
  icon: "gpp_good",
1245
- view: /* @__PURE__ */ e(Ze, {})
1597
+ view: /* @__PURE__ */ jsx(RolesView, {})
1246
1598
  }
1247
1599
  ];
1248
1600
  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
1601
+ IntroWidget,
1602
+ RESERVED_GROUPS,
1603
+ RoleChip,
1604
+ RoleYupSchema,
1605
+ RolesDetailsForm,
1606
+ RolesTable,
1607
+ RolesView,
1608
+ UserDetailsForm,
1609
+ UserManagementContext,
1610
+ UserManagementProvider,
1611
+ UserYupSchema,
1612
+ UsersTable,
1613
+ UsersView,
1614
+ areRolesEqual,
1615
+ cacheDelegatedLoginToken,
1616
+ clearDelegatedLoginTokensCache,
1617
+ darkenColor,
1618
+ getDelegatedLoginTokenFromCache,
1619
+ getUserRoles,
1620
+ hexToRgbaWithOpacity,
1621
+ resolveUserRolePermissions,
1622
+ useBuildUserManagement,
1623
+ useUserManagement,
1624
+ useUserManagementPlugin,
1625
+ userManagementAdminViews
1273
1626
  };
1274
1627
  //# sourceMappingURL=index.es.js.map