@firecms/user_management 3.0.0-canary.15 → 3.0.0-canary.151

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