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