@micha.bigler/ui-core-micha 2.2.7 → 2.2.8

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.
@@ -6,7 +6,7 @@ import DeleteIcon from '@mui/icons-material/Delete';
6
6
  import { useTranslation } from 'react-i18next';
7
7
  import { fetchUsersList, deleteUser, updateUserRole } from '../auth/authApi';
8
8
  const DEFAULT_ROLES = ['none', 'student', 'teacher', 'admin'];
9
- export function UserListComponent({ roles = DEFAULT_ROLES, currentUser, extraColumns = [], extraRowActions = [], extraContext = null, refreshTrigger = 0, canEditUser, }) {
9
+ export function UserListComponent({ roles = DEFAULT_ROLES, currentUser, extraColumns = [], extraRowActions = [], extraContext = null, refreshTrigger = 0, canEditUser, showRoleColumn = true, onChangeRole = null, showDeleteAction = true, canDeleteUser = null, onDeleteUser = null, }) {
10
10
  const { t } = useTranslation();
11
11
  const [users, setUsers] = useState([]);
12
12
  const [loading, setLoading] = useState(true);
@@ -44,7 +44,12 @@ export function UserListComponent({ roles = DEFAULT_ROLES, currentUser, extraCol
44
44
  if (!window.confirm(t('UserList.DELETE_CONFIRM', 'Are you sure you want to delete this user?')))
45
45
  return;
46
46
  try {
47
- await deleteUser(userId);
47
+ if (typeof onDeleteUser === 'function') {
48
+ await onDeleteUser({ userId, currentUser, extraContext, t, reloadUsers: loadUsers });
49
+ }
50
+ else {
51
+ await deleteUser(userId);
52
+ }
48
53
  setUsers(prev => prev.filter(u => u.id !== userId));
49
54
  }
50
55
  catch (err) {
@@ -53,7 +58,19 @@ export function UserListComponent({ roles = DEFAULT_ROLES, currentUser, extraCol
53
58
  };
54
59
  const handleChangeRole = async (userId, newRole) => {
55
60
  try {
56
- await updateUserRole(userId, newRole);
61
+ if (typeof onChangeRole === 'function') {
62
+ await onChangeRole({
63
+ userId,
64
+ newRole,
65
+ currentUser,
66
+ extraContext,
67
+ t,
68
+ reloadUsers: loadUsers,
69
+ });
70
+ }
71
+ else {
72
+ await updateUserRole(userId, newRole);
73
+ }
57
74
  await loadUsers();
58
75
  }
59
76
  catch (err) {
@@ -84,6 +101,12 @@ export function UserListComponent({ roles = DEFAULT_ROLES, currentUser, extraCol
84
101
  }
85
102
  return defaultCanEdit(targetUser);
86
103
  };
104
+ const canDelete = (targetUser) => {
105
+ if (typeof canDeleteUser === 'function') {
106
+ return Boolean(canDeleteUser({ targetUser, currentUser, extraContext }));
107
+ }
108
+ return canEdit(targetUser);
109
+ };
87
110
  const listContext = useMemo(() => ({
88
111
  currentUser,
89
112
  extraContext,
@@ -207,7 +230,9 @@ export function UserListComponent({ roles = DEFAULT_ROLES, currentUser, extraCol
207
230
  : t('Common.NO', 'No') }));
208
231
  },
209
232
  },
210
- {
233
+ ];
234
+ if (showRoleColumn) {
235
+ baseColumns.push({
211
236
  field: 'role',
212
237
  headerName: t('UserList.ROLE', 'Role'),
213
238
  minWidth: 180,
@@ -217,8 +242,8 @@ export function UserListComponent({ roles = DEFAULT_ROLES, currentUser, extraCol
217
242
  const user = params.row;
218
243
  return (_jsx(FormControl, { size: "small", fullWidth: true, sx: controlSx, disabled: !canEdit(user), children: _jsx(Select, { value: user.role || 'none', onChange: (event) => handleChangeRole(user.id, event.target.value), variant: "outlined", children: roles.map((role) => _jsx(MenuItem, { value: role, children: role }, role)) }) }));
219
244
  },
220
- },
221
- ];
245
+ });
246
+ }
222
247
  const mappedExtraColumns = visibleExtraColumns.map((column) => ({
223
248
  field: `extra:${column.key}`,
224
249
  headerName: typeof column.label === 'function' ? column.label(listContext) : column.label,
@@ -237,10 +262,14 @@ export function UserListComponent({ roles = DEFAULT_ROLES, currentUser, extraCol
237
262
  reloadUsers: loadUsers,
238
263
  }),
239
264
  }));
265
+ const hasActionColumn = showDeleteAction || visibleRowActions.length > 0;
266
+ if (!hasActionColumn) {
267
+ return [...baseColumns, ...mappedExtraColumns];
268
+ }
240
269
  const actionColumn = {
241
270
  field: 'actions',
242
271
  headerName: t('Common.ACTIONS', 'Actions'),
243
- minWidth: Math.max(220, 110 + visibleRowActions.length * 110),
272
+ minWidth: Math.max(220, 110 + (visibleRowActions.length + (showDeleteAction ? 1 : 0)) * 110),
244
273
  flex: 1.4,
245
274
  sortable: false,
246
275
  filterable: false,
@@ -262,13 +291,15 @@ export function UserListComponent({ roles = DEFAULT_ROLES, currentUser, extraCol
262
291
  return (_jsx(Button, { size: "small", variant: "outlined", onClick: () => runRowAction(action, user), disabled: isBusy || isDisabled, sx: actionButtonSx, children: typeof action.label === 'function'
263
292
  ? action.label({ user, t, currentUser, canEdit: canEdit(user) })
264
293
  : action.label }, `${action.key}-${user.id}`));
265
- }), _jsx(Tooltip, { title: t('Common.DELETE', 'Delete'), children: _jsx("span", { children: _jsx(Button, { size: "small", variant: "outlined", color: "error", startIcon: _jsx(DeleteIcon, {}), onClick: () => handleDelete(user.id), disabled: !canEdit(user), sx: actionButtonSx, children: t('Common.DELETE', 'Delete') }) }) })] }));
294
+ }), showDeleteAction && (_jsx(Tooltip, { title: t('Common.DELETE', 'Delete'), children: _jsx("span", { children: _jsx(Button, { size: "small", variant: "outlined", color: "error", startIcon: _jsx(DeleteIcon, {}), onClick: () => handleDelete(user.id), disabled: !canDelete(user), sx: actionButtonSx, children: t('Common.DELETE', 'Delete') }) }) }))] }));
266
295
  },
267
296
  };
268
297
  return [...baseColumns, ...mappedExtraColumns, actionColumn];
269
298
  }, [
270
299
  t,
271
300
  roles,
301
+ showRoleColumn,
302
+ showDeleteAction,
272
303
  visibleExtraColumns,
273
304
  visibleRowActions,
274
305
  listContext,
@@ -277,6 +308,7 @@ export function UserListComponent({ roles = DEFAULT_ROLES, currentUser, extraCol
277
308
  extraContext,
278
309
  loadUsers,
279
310
  canEdit,
311
+ canDelete,
280
312
  ]);
281
313
  return (_jsxs(Box, { children: [_jsx(Typography, { variant: "h6", gutterBottom: true, children: t('UserList.TITLE', 'All Users') }), _jsx(Box, { sx: { mb: 2, maxWidth: 420 }, children: _jsx(TextField, { fullWidth: true, size: "small", label: t('Common.SEARCH', 'Search'), placeholder: t('UserList.SEARCH_PLACEHOLDER', 'Search users...'), value: searchQuery, onChange: (event) => setSearchQuery(event.target.value) }) }), error && _jsx(Alert, { severity: "error", sx: { mb: 2 }, children: t(error) }), loading && (_jsx(Box, { sx: { display: 'flex', justifyContent: 'center', p: 3 }, children: _jsx(CircularProgress, {}) })), !loading && (_jsx(Box, { sx: { width: '100%', minHeight: 520 }, children: _jsx(DataGrid, { rows: filteredUsers, columns: columns, disableRowSelectionOnClick: true, showToolbar: true, getRowHeight: () => 'auto', pageSizeOptions: [10, 25, 50, 100], initialState: {
282
314
  sorting: { sortModel: [{ field: 'email', sort: 'asc' }] },
@@ -21,7 +21,7 @@ import { QrSignupValidityManager } from '../components/QrSignupValidityManager';
21
21
  import { SupportRecoveryRequestsTab } from '../components/SupportRecoveryRequestsTab';
22
22
  import { BulkInviteCsvTab } from '../components/BulkInviteCsvTab';
23
23
  import { fetchAuthPolicy, updateUserProfile } from '../auth/authApi'; // Ggf. Pfad anpassen
24
- export function AccountPage({ userListExtraColumns = [], userListExtraRowActions = [], userListExtraContext = null, userListRefreshTrigger = 0, userListCanEditUser = null, showBulkInviteCsvTab = false, bulkInviteCsvProps = {}, extraTabs = [], }) {
24
+ export function AccountPage({ userListExtraColumns = [], userListExtraRowActions = [], userListExtraContext = null, userListRefreshTrigger = 0, userListCanEditUser = null, userListShowRoleColumn = true, userListOnChangeRole = null, userListShowDeleteAction = true, userListCanDeleteUser = null, userListOnDeleteUser = null, showBulkInviteCsvTab = false, bulkInviteCsvProps = {}, extraTabs = [], }) {
25
25
  var _a;
26
26
  const { t } = useTranslation();
27
27
  const { user, login, loading } = useContext(AuthContext);
@@ -129,5 +129,5 @@ export function AccountPage({ userListExtraColumns = [], userListExtraRowActions
129
129
  const activeExtraTab = builtInTabValues.has(safeTab)
130
130
  ? null
131
131
  : extraTabs.find((tab) => tab.value === safeTab);
132
- return (_jsxs(WidePage, { title: t('Account.TITLE', 'Account & Administration'), children: [_jsx(Helmet, { children: _jsxs("title", { children: [t('Account.PAGE_TITLE', 'Account'), " \u2013 ", user.email] }) }), _jsx(Tabs, { value: safeTab, onChange: handleTabChange, variant: "scrollable", scrollButtons: "auto", sx: { mb: 3, borderBottom: 1, borderColor: 'divider' }, children: tabs.map((tab) => (_jsx(Tab, { label: tab.label, value: tab.value }, tab.value))) }), safeTab === 'profile' && (_jsx(Box, { sx: { mt: 2 }, children: _jsx(ProfileComponent, { onSubmit: handleProfileSubmit, showName: true, showPrivacy: true, showCookies: true }) })), safeTab === 'security' && (_jsx(Box, { sx: { mt: 2 }, children: _jsx(SecurityComponent, { fromRecovery: fromRecovery, fromWeakLogin: fromWeakLogin }) })), safeTab === 'users' && (_jsx(Box, { sx: { mt: 2 }, children: _jsx(UserListComponent, { roles: activeRoles, currentUser: user, extraColumns: userListExtraColumns, extraRowActions: userListExtraRowActions, extraContext: userListExtraContext, refreshTrigger: userListRefreshTrigger, canEditUser: userListCanEditUser }) })), safeTab === 'invite' && (_jsx(Box, { sx: { mt: 2 }, children: _jsxs(Stack, { spacing: 2.5, children: [canViewAuthPolicy && (_jsx(Paper, { variant: "outlined", sx: { p: 2.5, borderRadius: 2 }, children: _jsx(AuthFactorRequirementCard, { canEdit: canWriteAuthPolicy, policy: authPolicy }) })), canViewAuthPolicy && (_jsx(Paper, { variant: "outlined", sx: { p: 2.5, borderRadius: 2 }, children: _jsx(RegistrationMethodsManager, { policy: authPolicy, error: authPolicyError, onPolicyChange: setAuthPolicy, canEdit: canWriteAuthPolicy }) })), canSendInvites && Boolean(authPolicy === null || authPolicy === void 0 ? void 0 : authPolicy.allow_admin_invite) && (_jsx(Paper, { variant: "outlined", sx: { p: 2.5, borderRadius: 2 }, children: _jsx(UserInviteComponent, {}) })), canManageAccessCodes && Boolean(authPolicy === null || authPolicy === void 0 ? void 0 : authPolicy.allow_self_signup_access_code) && (_jsxs(Paper, { variant: "outlined", sx: { p: 2.5, borderRadius: 2 }, children: [_jsx(Typography, { variant: "h6", gutterBottom: true, children: t('Auth.ACCESS_CODE_MANAGER_TITLE', 'Access Codes') }), _jsx(Typography, { variant: "body2", sx: { mb: 2, color: 'text.secondary' }, children: t('Account.ACCESS_CODES_HINT', 'Manage access codes for self-registration.') }), _jsx(AccessCodeManager, {})] })), canSendInvites && showBulkInviteCsvTab && Boolean(authPolicy === null || authPolicy === void 0 ? void 0 : authPolicy.allow_admin_invite) && (_jsx(Paper, { variant: "outlined", sx: { p: 2.5, borderRadius: 2 }, children: _jsx(BulkInviteCsvTab, Object.assign({}, bulkInviteCsvProps)) })), canViewAuthPolicy && Boolean(authPolicy === null || authPolicy === void 0 ? void 0 : authPolicy.allow_self_signup_email_domain) && (_jsx(Paper, { variant: "outlined", sx: { p: 2.5, borderRadius: 2 }, children: _jsx(AllowedEmailDomainsManager, { enabled: Boolean(authPolicy === null || authPolicy === void 0 ? void 0 : authPolicy.allow_self_signup_email_domain), domains: (authPolicy === null || authPolicy === void 0 ? void 0 : authPolicy.allowed_email_domains) || [], onPolicyChange: setAuthPolicy, canEdit: canWriteAuthPolicy }) })), canViewAuthPolicy && Boolean(authPolicy === null || authPolicy === void 0 ? void 0 : authPolicy.allow_self_signup_qr) && (_jsx(Paper, { variant: "outlined", sx: { p: 2.5, borderRadius: 2 }, children: _jsx(QrSignupValidityManager, { enabled: Boolean(authPolicy === null || authPolicy === void 0 ? void 0 : authPolicy.allow_self_signup_qr), expiryDays: authPolicy === null || authPolicy === void 0 ? void 0 : authPolicy.signup_qr_expiry_days, onPolicyChange: setAuthPolicy, canEdit: canWriteAuthPolicy }) })), canManageSignupQr && Boolean(authPolicy === null || authPolicy === void 0 ? void 0 : authPolicy.allow_self_signup_qr) && (_jsx(Paper, { variant: "outlined", sx: { p: 2.5, borderRadius: 2 }, children: _jsx(QrSignupManager, { enabled: Boolean(authPolicy === null || authPolicy === void 0 ? void 0 : authPolicy.allow_self_signup_qr), expiryDays: authPolicy === null || authPolicy === void 0 ? void 0 : authPolicy.signup_qr_expiry_days }) }))] }) })), safeTab === 'support' && (_jsx(Box, { sx: { mt: 2 }, children: _jsx(SupportRecoveryRequestsTab, {}) })), activeExtraTab && (_jsx(Box, { sx: { mt: 2 }, children: (_a = activeExtraTab.render) === null || _a === void 0 ? void 0 : _a.call(activeExtraTab, { user, perms, isSuperUser, t }) }))] }));
132
+ return (_jsxs(WidePage, { title: t('Account.TITLE', 'Account & Administration'), children: [_jsx(Helmet, { children: _jsxs("title", { children: [t('Account.PAGE_TITLE', 'Account'), " \u2013 ", user.email] }) }), _jsx(Tabs, { value: safeTab, onChange: handleTabChange, variant: "scrollable", scrollButtons: "auto", sx: { mb: 3, borderBottom: 1, borderColor: 'divider' }, children: tabs.map((tab) => (_jsx(Tab, { label: tab.label, value: tab.value }, tab.value))) }), safeTab === 'profile' && (_jsx(Box, { sx: { mt: 2 }, children: _jsx(ProfileComponent, { onSubmit: handleProfileSubmit, showName: true, showPrivacy: true, showCookies: true }) })), safeTab === 'security' && (_jsx(Box, { sx: { mt: 2 }, children: _jsx(SecurityComponent, { fromRecovery: fromRecovery, fromWeakLogin: fromWeakLogin }) })), safeTab === 'users' && (_jsx(Box, { sx: { mt: 2 }, children: _jsx(UserListComponent, { roles: activeRoles, currentUser: user, extraColumns: userListExtraColumns, extraRowActions: userListExtraRowActions, extraContext: userListExtraContext, refreshTrigger: userListRefreshTrigger, canEditUser: userListCanEditUser, showRoleColumn: userListShowRoleColumn, onChangeRole: userListOnChangeRole, showDeleteAction: userListShowDeleteAction, canDeleteUser: userListCanDeleteUser, onDeleteUser: userListOnDeleteUser }) })), safeTab === 'invite' && (_jsx(Box, { sx: { mt: 2 }, children: _jsxs(Stack, { spacing: 2.5, children: [canViewAuthPolicy && (_jsx(Paper, { variant: "outlined", sx: { p: 2.5, borderRadius: 2 }, children: _jsx(AuthFactorRequirementCard, { canEdit: canWriteAuthPolicy, policy: authPolicy }) })), canViewAuthPolicy && (_jsx(Paper, { variant: "outlined", sx: { p: 2.5, borderRadius: 2 }, children: _jsx(RegistrationMethodsManager, { policy: authPolicy, error: authPolicyError, onPolicyChange: setAuthPolicy, canEdit: canWriteAuthPolicy }) })), canSendInvites && Boolean(authPolicy === null || authPolicy === void 0 ? void 0 : authPolicy.allow_admin_invite) && (_jsx(Paper, { variant: "outlined", sx: { p: 2.5, borderRadius: 2 }, children: _jsx(UserInviteComponent, {}) })), canManageAccessCodes && Boolean(authPolicy === null || authPolicy === void 0 ? void 0 : authPolicy.allow_self_signup_access_code) && (_jsxs(Paper, { variant: "outlined", sx: { p: 2.5, borderRadius: 2 }, children: [_jsx(Typography, { variant: "h6", gutterBottom: true, children: t('Auth.ACCESS_CODE_MANAGER_TITLE', 'Access Codes') }), _jsx(Typography, { variant: "body2", sx: { mb: 2, color: 'text.secondary' }, children: t('Account.ACCESS_CODES_HINT', 'Manage access codes for self-registration.') }), _jsx(AccessCodeManager, {})] })), canSendInvites && showBulkInviteCsvTab && Boolean(authPolicy === null || authPolicy === void 0 ? void 0 : authPolicy.allow_admin_invite) && (_jsx(Paper, { variant: "outlined", sx: { p: 2.5, borderRadius: 2 }, children: _jsx(BulkInviteCsvTab, Object.assign({}, bulkInviteCsvProps)) })), canViewAuthPolicy && Boolean(authPolicy === null || authPolicy === void 0 ? void 0 : authPolicy.allow_self_signup_email_domain) && (_jsx(Paper, { variant: "outlined", sx: { p: 2.5, borderRadius: 2 }, children: _jsx(AllowedEmailDomainsManager, { enabled: Boolean(authPolicy === null || authPolicy === void 0 ? void 0 : authPolicy.allow_self_signup_email_domain), domains: (authPolicy === null || authPolicy === void 0 ? void 0 : authPolicy.allowed_email_domains) || [], onPolicyChange: setAuthPolicy, canEdit: canWriteAuthPolicy }) })), canViewAuthPolicy && Boolean(authPolicy === null || authPolicy === void 0 ? void 0 : authPolicy.allow_self_signup_qr) && (_jsx(Paper, { variant: "outlined", sx: { p: 2.5, borderRadius: 2 }, children: _jsx(QrSignupValidityManager, { enabled: Boolean(authPolicy === null || authPolicy === void 0 ? void 0 : authPolicy.allow_self_signup_qr), expiryDays: authPolicy === null || authPolicy === void 0 ? void 0 : authPolicy.signup_qr_expiry_days, onPolicyChange: setAuthPolicy, canEdit: canWriteAuthPolicy }) })), canManageSignupQr && Boolean(authPolicy === null || authPolicy === void 0 ? void 0 : authPolicy.allow_self_signup_qr) && (_jsx(Paper, { variant: "outlined", sx: { p: 2.5, borderRadius: 2 }, children: _jsx(QrSignupManager, { enabled: Boolean(authPolicy === null || authPolicy === void 0 ? void 0 : authPolicy.allow_self_signup_qr), expiryDays: authPolicy === null || authPolicy === void 0 ? void 0 : authPolicy.signup_qr_expiry_days }) }))] }) })), safeTab === 'support' && (_jsx(Box, { sx: { mt: 2 }, children: _jsx(SupportRecoveryRequestsTab, {}) })), activeExtraTab && (_jsx(Box, { sx: { mt: 2 }, children: (_a = activeExtraTab.render) === null || _a === void 0 ? void 0 : _a.call(activeExtraTab, { user, perms, isSuperUser, t }) }))] }));
133
133
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@micha.bigler/ui-core-micha",
3
- "version": "2.2.7",
3
+ "version": "2.2.8",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.js",
6
6
  "private": false,
@@ -26,6 +26,11 @@ export function UserListComponent({
26
26
  extraContext = null,
27
27
  refreshTrigger = 0,
28
28
  canEditUser,
29
+ showRoleColumn = true,
30
+ onChangeRole = null,
31
+ showDeleteAction = true,
32
+ canDeleteUser = null,
33
+ onDeleteUser = null,
29
34
  }) {
30
35
  const { t } = useTranslation();
31
36
  const [users, setUsers] = useState([]);
@@ -63,7 +68,11 @@ export function UserListComponent({
63
68
  const handleDelete = async (userId) => {
64
69
  if (!window.confirm(t('UserList.DELETE_CONFIRM', 'Are you sure you want to delete this user?'))) return;
65
70
  try {
66
- await deleteUser(userId);
71
+ if (typeof onDeleteUser === 'function') {
72
+ await onDeleteUser({ userId, currentUser, extraContext, t, reloadUsers: loadUsers });
73
+ } else {
74
+ await deleteUser(userId);
75
+ }
67
76
  setUsers(prev => prev.filter(u => u.id !== userId));
68
77
  } catch (err) {
69
78
  alert(t(err.code || 'Auth.USER_DELETE_FAILED'));
@@ -72,7 +81,18 @@ export function UserListComponent({
72
81
 
73
82
  const handleChangeRole = async (userId, newRole) => {
74
83
  try {
75
- await updateUserRole(userId, newRole);
84
+ if (typeof onChangeRole === 'function') {
85
+ await onChangeRole({
86
+ userId,
87
+ newRole,
88
+ currentUser,
89
+ extraContext,
90
+ t,
91
+ reloadUsers: loadUsers,
92
+ });
93
+ } else {
94
+ await updateUserRole(userId, newRole);
95
+ }
76
96
  await loadUsers();
77
97
  } catch (err) {
78
98
  alert(t(err.code || 'Auth.USER_ROLE_UPDATE_FAILED'));
@@ -102,6 +122,13 @@ export function UserListComponent({
102
122
  return defaultCanEdit(targetUser);
103
123
  };
104
124
 
125
+ const canDelete = (targetUser) => {
126
+ if (typeof canDeleteUser === 'function') {
127
+ return Boolean(canDeleteUser({ targetUser, currentUser, extraContext }));
128
+ }
129
+ return canEdit(targetUser);
130
+ };
131
+
105
132
  const listContext = useMemo(() => ({
106
133
  currentUser,
107
134
  extraContext,
@@ -247,7 +274,10 @@ export function UserListComponent({
247
274
  </Typography>
248
275
  ),
249
276
  },
250
- {
277
+ ];
278
+
279
+ if (showRoleColumn) {
280
+ baseColumns.push({
251
281
  field: 'role',
252
282
  headerName: t('UserList.ROLE', 'Role'),
253
283
  minWidth: 180,
@@ -267,8 +297,8 @@ export function UserListComponent({
267
297
  </FormControl>
268
298
  );
269
299
  },
270
- },
271
- ];
300
+ });
301
+ }
272
302
 
273
303
  const mappedExtraColumns = visibleExtraColumns.map((column) => ({
274
304
  field: `extra:${column.key}`,
@@ -290,10 +320,16 @@ export function UserListComponent({
290
320
  }),
291
321
  }));
292
322
 
323
+ const hasActionColumn = showDeleteAction || visibleRowActions.length > 0;
324
+
325
+ if (!hasActionColumn) {
326
+ return [...baseColumns, ...mappedExtraColumns];
327
+ }
328
+
293
329
  const actionColumn = {
294
330
  field: 'actions',
295
331
  headerName: t('Common.ACTIONS', 'Actions'),
296
- minWidth: Math.max(220, 110 + visibleRowActions.length * 110),
332
+ minWidth: Math.max(220, 110 + (visibleRowActions.length + (showDeleteAction ? 1 : 0)) * 110),
297
333
  flex: 1.4,
298
334
  sortable: false,
299
335
  filterable: false,
@@ -332,21 +368,23 @@ export function UserListComponent({
332
368
  );
333
369
  })}
334
370
 
335
- <Tooltip title={t('Common.DELETE', 'Delete')}>
336
- <span>
337
- <Button
338
- size="small"
339
- variant="outlined"
340
- color="error"
341
- startIcon={<DeleteIcon />}
342
- onClick={() => handleDelete(user.id)}
343
- disabled={!canEdit(user)}
344
- sx={actionButtonSx}
345
- >
346
- {t('Common.DELETE', 'Delete')}
347
- </Button>
348
- </span>
349
- </Tooltip>
371
+ {showDeleteAction && (
372
+ <Tooltip title={t('Common.DELETE', 'Delete')}>
373
+ <span>
374
+ <Button
375
+ size="small"
376
+ variant="outlined"
377
+ color="error"
378
+ startIcon={<DeleteIcon />}
379
+ onClick={() => handleDelete(user.id)}
380
+ disabled={!canDelete(user)}
381
+ sx={actionButtonSx}
382
+ >
383
+ {t('Common.DELETE', 'Delete')}
384
+ </Button>
385
+ </span>
386
+ </Tooltip>
387
+ )}
350
388
  </Box>
351
389
  );
352
390
  },
@@ -356,6 +394,8 @@ export function UserListComponent({
356
394
  }, [
357
395
  t,
358
396
  roles,
397
+ showRoleColumn,
398
+ showDeleteAction,
359
399
  visibleExtraColumns,
360
400
  visibleRowActions,
361
401
  listContext,
@@ -364,6 +404,7 @@ export function UserListComponent({
364
404
  extraContext,
365
405
  loadUsers,
366
406
  canEdit,
407
+ canDelete,
367
408
  ]);
368
409
 
369
410
  return (
@@ -38,6 +38,11 @@ export function AccountPage({
38
38
  userListExtraContext = null,
39
39
  userListRefreshTrigger = 0,
40
40
  userListCanEditUser = null,
41
+ userListShowRoleColumn = true,
42
+ userListOnChangeRole = null,
43
+ userListShowDeleteAction = true,
44
+ userListCanDeleteUser = null,
45
+ userListOnDeleteUser = null,
41
46
  showBulkInviteCsvTab = false,
42
47
  bulkInviteCsvProps = {},
43
48
  extraTabs = [],
@@ -227,6 +232,11 @@ export function AccountPage({
227
232
  extraContext={userListExtraContext}
228
233
  refreshTrigger={userListRefreshTrigger}
229
234
  canEditUser={userListCanEditUser}
235
+ showRoleColumn={userListShowRoleColumn}
236
+ onChangeRole={userListOnChangeRole}
237
+ showDeleteAction={userListShowDeleteAction}
238
+ canDeleteUser={userListCanDeleteUser}
239
+ onDeleteUser={userListOnDeleteUser}
230
240
  />
231
241
  </Box>
232
242
  )}