@deix/rossini-identity-management 0.1.1 → 0.2.0

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.
Files changed (71) hide show
  1. package/lib/app/[locale]/groups/{page.jsx → page.js} +1 -1
  2. package/lib/app/[locale]/{layout.jsx → layout.js} +3 -4
  3. package/lib/app/[locale]/users/{page.jsx → page.js} +1 -1
  4. package/lib/app/{layout.jsx → layout.js} +4 -8
  5. package/lib/components/AddItemDialog.js +45 -0
  6. package/lib/components/DeleteConfirmationDialog.js +35 -0
  7. package/lib/components/SearchField.js +16 -0
  8. package/lib/components/groups/CreateGroupDialog.d.ts +3 -1
  9. package/lib/components/groups/CreateGroupDialog.d.ts.map +1 -1
  10. package/lib/components/groups/{CreateGroupDialog.jsx → CreateGroupDialog.js} +8 -7
  11. package/lib/components/groups/GroupDetails.d.ts +3 -1
  12. package/lib/components/groups/GroupDetails.d.ts.map +1 -1
  13. package/lib/components/groups/GroupDetails.js +19 -0
  14. package/lib/components/groups/GroupForm.d.ts +2 -1
  15. package/lib/components/groups/GroupForm.d.ts.map +1 -1
  16. package/lib/components/groups/GroupForm.js +38 -0
  17. package/lib/components/groups/GroupTabs.d.ts +3 -1
  18. package/lib/components/groups/GroupTabs.d.ts.map +1 -1
  19. package/lib/components/groups/GroupTabs.js +29 -0
  20. package/lib/components/groups/GroupUsers.js +73 -0
  21. package/lib/components/groups/Groups.d.ts +6 -1
  22. package/lib/components/groups/Groups.d.ts.map +1 -1
  23. package/lib/components/groups/Groups.js +83 -0
  24. package/lib/components/groups/GroupsTable.d.ts +1 -1
  25. package/lib/components/groups/GroupsTable.d.ts.map +1 -1
  26. package/lib/components/groups/GroupsTable.js +43 -0
  27. package/lib/components/users/CreateUserDialog.d.ts +3 -1
  28. package/lib/components/users/CreateUserDialog.d.ts.map +1 -1
  29. package/lib/components/users/{CreateUserDialog.jsx → CreateUserDialog.js} +8 -7
  30. package/lib/components/users/{UserCredentials.jsx → UserCredentials.js} +2 -5
  31. package/lib/components/users/UserDetails.d.ts +3 -1
  32. package/lib/components/users/UserDetails.d.ts.map +1 -1
  33. package/lib/components/users/UserDetails.js +22 -0
  34. package/lib/components/users/UserForm.d.ts +2 -1
  35. package/lib/components/users/UserForm.d.ts.map +1 -1
  36. package/lib/components/users/UserForm.js +64 -0
  37. package/lib/components/users/UserGroups.js +63 -0
  38. package/lib/components/users/Users.d.ts +6 -1
  39. package/lib/components/users/Users.d.ts.map +1 -1
  40. package/lib/components/users/Users.js +89 -0
  41. package/lib/components/users/UsersTable.d.ts +1 -1
  42. package/lib/components/users/UsersTable.d.ts.map +1 -1
  43. package/lib/components/users/UsersTable.js +62 -0
  44. package/lib/components/users/UsersTabs.d.ts +3 -1
  45. package/lib/components/users/UsersTabs.d.ts.map +1 -1
  46. package/lib/components/users/UsersTabs.js +32 -0
  47. package/lib/config/{index.jsx → index.js} +1 -3
  48. package/lib/lang/users.d.ts.map +1 -1
  49. package/lib/lang/users.js +4 -0
  50. package/lib/tsconfig.tsbuildinfo +1 -1
  51. package/lib/utils/hooks/groups.d.ts.map +1 -1
  52. package/lib/utils/hooks/groups.js +0 -2
  53. package/lib/utils/hooks/{useAPIClient.jsx → useAPIClient.js} +2 -4
  54. package/lib/utils/hooks/users.d.ts.map +1 -1
  55. package/lib/utils/hooks/users.js +0 -1
  56. package/package.json +2 -5
  57. package/lib/components/AddItemDialog.jsx +0 -50
  58. package/lib/components/DeleteConfirmationDialog.jsx +0 -44
  59. package/lib/components/SearchField.jsx +0 -18
  60. package/lib/components/groups/GroupDetails.jsx +0 -17
  61. package/lib/components/groups/GroupForm.jsx +0 -46
  62. package/lib/components/groups/GroupTabs.jsx +0 -33
  63. package/lib/components/groups/GroupUsers.jsx +0 -88
  64. package/lib/components/groups/Groups.jsx +0 -93
  65. package/lib/components/groups/GroupsTable.jsx +0 -55
  66. package/lib/components/users/UserDetails.jsx +0 -17
  67. package/lib/components/users/UserForm.jsx +0 -75
  68. package/lib/components/users/UserGroups.jsx +0 -78
  69. package/lib/components/users/Users.jsx +0 -99
  70. package/lib/components/users/UsersTable.jsx +0 -76
  71. package/lib/components/users/UsersTabs.jsx +0 -36
@@ -6,20 +6,21 @@ import { useAddUser } from '../../utils/hooks/users';
6
6
  import UserForm from './UserForm';
7
7
  import usersTranslations from '../../lang/users';
8
8
  import { useAPIClient } from '../../utils/hooks/useAPIClient';
9
- const CreateUserDialog = ({ open, onClose }) => {
9
+ const CreateUserDialog = ({ open, onClose, onUserCreate, }) => {
10
10
  const locale = useLocale();
11
11
  const apiClient = useAPIClient();
12
12
  const queryClient = useQueryClient();
13
13
  const { mutate: addUser } = useAddUser(queryClient, apiClient);
14
14
  const handleSave = (userFormData) => {
15
15
  addUser(userFormData);
16
+ if (typeof onUserCreate === 'function') {
17
+ onUserCreate(userFormData);
18
+ }
16
19
  onClose();
17
20
  };
18
- return (<Dialog open={open} fullWidth maxWidth='sm' onClose={onClose}>
19
- <DialogTitle>{usersTranslations.create[locale]}</DialogTitle>
20
- <DialogContent>
21
- <UserForm mode='create' onSave={handleSave} onCancel={onClose}/>
22
- </DialogContent>
23
- </Dialog>);
21
+ return (React.createElement(Dialog, { open: open, fullWidth: true, maxWidth: 'sm', onClose: onClose },
22
+ React.createElement(DialogTitle, null, usersTranslations.create[locale]),
23
+ React.createElement(DialogContent, null,
24
+ React.createElement(UserForm, { mode: 'create', onSave: handleSave, onCancel: onClose }))));
24
25
  };
25
26
  export default CreateUserDialog;
@@ -10,10 +10,7 @@ const UserCredentials = ({ user }) => {
10
10
  const apiClient = useAPIClient();
11
11
  const queryClient = useQueryClient();
12
12
  const { mutate: sendResetPasswordEmail } = useSendUpdatePasswordEmail(queryClient, apiClient);
13
- return (<Box sx={{ mt: 2 }}>
14
- <Button variant='contained' onClick={() => sendResetPasswordEmail(user.id)}>
15
- {usersTranslations.sendResetPasswordEmail[locale]}
16
- </Button>
17
- </Box>);
13
+ return (React.createElement(Box, { sx: { mt: 2 } },
14
+ React.createElement(Button, { variant: 'contained', onClick: () => sendResetPasswordEmail(user.id) }, usersTranslations.sendResetPasswordEmail[locale])));
18
15
  };
19
16
  export default UserCredentials;
@@ -2,7 +2,9 @@ import React from 'react';
2
2
  import { User } from '../../types/users';
3
3
  export interface UserDetailsProps {
4
4
  user: User;
5
+ onUserUpdate?: (newUser: User, oldUser: User) => void;
6
+ editUsername?: boolean;
5
7
  }
6
- declare const UserDetails: ({ user }: UserDetailsProps) => React.JSX.Element;
8
+ declare const UserDetails: ({ user, onUserUpdate, editUsername, }: UserDetailsProps) => React.JSX.Element;
7
9
  export default UserDetails;
8
10
  //# sourceMappingURL=UserDetails.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"UserDetails.d.ts","sourceRoot":"","sources":["../../../src/components/users/UserDetails.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAKzC,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,IAAI,CAAC;CACZ;AAED,QAAA,MAAM,WAAW,aAAc,gBAAgB,sBAmB9C,CAAC;AAEF,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"UserDetails.d.ts","sourceRoot":"","sources":["../../../src/components/users/UserDetails.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAKzC,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,IAAI,CAAC;IACX,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,KAAK,IAAI,CAAC;IACtD,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,QAAA,MAAM,WAAW,0CAId,gBAAgB,sBA0BlB,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -0,0 +1,22 @@
1
+ import React from 'react';
2
+ import { useQueryClient } from '@tanstack/react-query';
3
+ import { useUpdateUser } from '../../utils/hooks/users';
4
+ import UserForm from './UserForm';
5
+ import { useAPIClient } from '../../utils/hooks/useAPIClient';
6
+ const UserDetails = ({ user, onUserUpdate, editUsername, }) => {
7
+ const apiClient = useAPIClient();
8
+ const queryClient = useQueryClient();
9
+ const { mutate: updateUser } = useUpdateUser(queryClient, apiClient);
10
+ const handleUpdate = (updatedUser) => {
11
+ // We need to remove sendEmailOnCreation or keycloak will complain
12
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
13
+ const { sendEmailOnCreation, ...user } = updatedUser;
14
+ updateUser(user);
15
+ if (typeof onUserUpdate === 'function') {
16
+ onUserUpdate(updatedUser, user);
17
+ }
18
+ };
19
+ return (React.createElement(React.Fragment, null,
20
+ React.createElement(UserForm, { mode: 'modify', user: user, onSave: handleUpdate, onCancel: () => { }, editUsername: editUsername })));
21
+ };
22
+ export default UserDetails;
@@ -8,7 +8,8 @@ export interface UserFormProps {
8
8
  onCancel?: () => void;
9
9
  user?: User;
10
10
  mode?: 'create' | 'modify';
11
+ editUsername?: boolean;
11
12
  }
12
- declare const UserForm: ({ user, onSave, onCancel, mode, }: UserFormProps) => React.JSX.Element;
13
+ declare const UserForm: ({ user, onSave, onCancel, mode, editUsername, }: UserFormProps) => React.JSX.Element;
13
14
  export default UserForm;
14
15
  //# sourceMappingURL=UserForm.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"UserForm.d.ts","sourceRoot":"","sources":["../../../src/components/users/UserForm.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAc1B,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEzC,MAAM,WAAW,cAAe,SAAQ,IAAI;IAC1C,mBAAmB,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IACvC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;CAC5B;AAED,QAAA,MAAM,QAAQ,sCAKX,aAAa,sBA8Jf,CAAC;AAEF,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"UserForm.d.ts","sourceRoot":"","sources":["../../../src/components/users/UserForm.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAc1B,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEzC,MAAM,WAAW,cAAe,SAAQ,IAAI;IAC1C,mBAAmB,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IACvC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC3B,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,QAAA,MAAM,QAAQ,oDAMX,aAAa,sBA0Kf,CAAC;AAEF,eAAe,QAAQ,CAAC"}
@@ -0,0 +1,64 @@
1
+ import React from 'react';
2
+ import { useLocale } from '@deix/rossini-core';
3
+ import { Button, FormControlLabel, Grid, Switch, TextField, } from '@mui/material';
4
+ import { Controller, useForm } from 'react-hook-form';
5
+ import { useEffect } from 'react';
6
+ import usersTranslations from '../../lang/users';
7
+ const UserForm = ({ user, onSave, onCancel, mode = 'create', editUsername, }) => {
8
+ const locale = useLocale();
9
+ const { control, formState: { errors }, handleSubmit, setValue, } = useForm({
10
+ defaultValues: {
11
+ id: user?.id,
12
+ username: user?.username || '',
13
+ firstName: user?.firstName || '',
14
+ lastName: user?.lastName || '',
15
+ email: user?.email || '',
16
+ emailVerified: user?.emailVerified || true,
17
+ enabled: user?.enabled || true,
18
+ sendEmailOnCreation: true,
19
+ },
20
+ });
21
+ useEffect(() => {
22
+ if (user) {
23
+ setValue('id', user?.id);
24
+ setValue('username', user?.username);
25
+ setValue('firstName', user?.firstName);
26
+ setValue('lastName', user?.lastName);
27
+ setValue('email', user?.email);
28
+ setValue('emailVerified', user?.emailVerified);
29
+ setValue('enabled', user?.enabled);
30
+ setValue('groups', user?.groups);
31
+ // The user already exists, we don't want to send an email
32
+ setValue('sendEmailOnCreation', false);
33
+ }
34
+ }, [user, setValue]);
35
+ const onSubmit = (data) => {
36
+ onSave(data);
37
+ };
38
+ return (React.createElement("form", { onSubmit: (event) => void handleSubmit(onSubmit)(event) },
39
+ React.createElement(Grid, { container: true, spacing: 2, sx: { mt: 2, maxWidth: 'sm' }, justifyContent: 'stretch' },
40
+ React.createElement(Grid, { item: true, xs: 12 },
41
+ React.createElement(Controller, { name: 'username', control: control, render: ({ field }) => (React.createElement(TextField, { size: 'small', fullWidth: true, label: usersTranslations.username[locale], disabled: mode === 'modify' && !editUsername, sx: { flexShrink: 0 }, ...field })) })),
42
+ React.createElement(Grid, { item: true, xs: 12 },
43
+ React.createElement(Controller, { name: 'firstName', control: control, render: ({ field }) => (React.createElement(TextField, { size: 'small', fullWidth: true, label: usersTranslations.firstName[locale], sx: { flexShrink: 0 }, ...field })) })),
44
+ React.createElement(Grid, { item: true, xs: 12 },
45
+ React.createElement(Controller, { name: 'lastName', control: control, render: ({ field }) => (React.createElement(TextField, { size: 'small', fullWidth: true, label: usersTranslations.lastName[locale], sx: { flexShrink: 0 }, ...field })) })),
46
+ React.createElement(Grid, { item: true, xs: 12 },
47
+ React.createElement(Controller, { name: 'email', control: control, rules: { required: true }, render: ({ field }) => (React.createElement(TextField, { size: 'small', fullWidth: true, error: !!errors.email, helperText: errors.email
48
+ ? usersTranslations.requiredField[locale]
49
+ : undefined, label: usersTranslations.email[locale], sx: { flexShrink: 0 }, ...field })) })),
50
+ React.createElement(Grid, { item: true, xs: 12 },
51
+ React.createElement(Controller, { name: 'enabled', control: control, render: ({ field }) => (React.createElement(FormControlLabel, { sx: { ml: 1 }, control: React.createElement(Switch, { checked: field.value, size: 'small', ...field }), label: usersTranslations.enabled[locale] })) })),
52
+ mode === 'create' && (React.createElement(Grid, { item: true, xs: 12 },
53
+ React.createElement(Controller, { name: 'sendEmailOnCreation', control: control, render: ({ field }) => (React.createElement(FormControlLabel, { sx: { ml: 1 }, control: React.createElement(Switch, { checked: field.value, size: 'small', ...field }), label: usersTranslations.sendResetPasswordEmail[locale] })) }))),
54
+ React.createElement(Grid, { item: true, sx: {
55
+ mt: 2,
56
+ display: 'flex',
57
+ justifyContent: 'flex-end',
58
+ gap: 2,
59
+ width: '100%',
60
+ } },
61
+ mode === 'create' && (React.createElement(Button, { variant: 'outlined', onClick: onCancel }, usersTranslations.cancel[locale])),
62
+ React.createElement(Button, { variant: 'contained', type: 'submit' }, usersTranslations.save[locale])))));
63
+ };
64
+ export default UserForm;
@@ -0,0 +1,63 @@
1
+ import React from 'react';
2
+ import { Box, Button, IconButton, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, } from '@mui/material';
3
+ import AddIcon from '@mui/icons-material/Add';
4
+ import DeleteIcon from '@mui/icons-material/Delete';
5
+ import { isStringTranslation, useLocale } from '@deix/rossini-core';
6
+ import { useAddUserToGroup, useRemoveUserFromGroup, useUserGroups, } from '../../utils/hooks/users';
7
+ import { useState } from 'react';
8
+ import DeleteConfirmationDialog from '../DeleteConfirmationDialog';
9
+ import { useQueryClient } from '@tanstack/react-query';
10
+ import usersTranslations from '../../lang/users';
11
+ import AddItemDialog from '../AddItemDialog';
12
+ import { useGroups } from '../../utils/hooks/groups';
13
+ import { useAPIClient } from '../../utils/hooks/useAPIClient';
14
+ const userGroupsTableColumns = [
15
+ {
16
+ id: 'name',
17
+ label: { en: 'Group', it: 'Gruppo' },
18
+ },
19
+ ];
20
+ const UserGroups = ({ user }) => {
21
+ const locale = useLocale();
22
+ const apiClient = useAPIClient();
23
+ const queryClient = useQueryClient();
24
+ const { data: groups } = useGroups(apiClient);
25
+ const { data: userGroups } = useUserGroups(user?.id, apiClient);
26
+ const { mutate: addUserToGroup } = useAddUserToGroup(queryClient, apiClient);
27
+ const { mutate: removeUserFromGroup } = useRemoveUserFromGroup(queryClient, apiClient);
28
+ const [openAddGroupDialog, setOpenAddGroupDialog] = useState(false);
29
+ const [openConfirmationDialog, setOpenConfirmationDialog] = useState(false);
30
+ const [deleteId, setDeleteId] = useState();
31
+ return (React.createElement(React.Fragment, null,
32
+ userGroups && userGroups.length > 0 && (React.createElement(Box, { maxWidth: 'sm' },
33
+ React.createElement(TableContainer, null,
34
+ React.createElement(Table, { size: 'small' },
35
+ React.createElement(TableHead, null,
36
+ React.createElement(TableRow, null,
37
+ userGroupsTableColumns.map((col) => (React.createElement(TableCell, { key: col.id, align: col.align || 'inherit' }, isStringTranslation(col.label)
38
+ ? col.label[locale]
39
+ : col.label))),
40
+ React.createElement(TableCell, { padding: 'none' }, ''))),
41
+ React.createElement(TableBody, null, userGroups?.map((group, rowIdx) => (React.createElement(TableRow, { key: rowIdx },
42
+ React.createElement(TableCell, null, group.name),
43
+ React.createElement(TableCell, { padding: 'none', align: 'right' },
44
+ React.createElement(IconButton, { size: 'small', onClick: (evt) => {
45
+ evt.stopPropagation();
46
+ setOpenConfirmationDialog(true);
47
+ setDeleteId(group.id);
48
+ } },
49
+ React.createElement(DeleteIcon, null))))))))))),
50
+ React.createElement(Button, { variant: 'outlined', startIcon: React.createElement(AddIcon, null), onClick: () => setOpenAddGroupDialog(true), sx: { marginTop: 2 } }, usersTranslations.addGroup[locale]),
51
+ React.createElement(AddItemDialog, { open: openAddGroupDialog, onClose: () => setOpenAddGroupDialog(false), onConfirm: (value) => {
52
+ if (value) {
53
+ addUserToGroup({ userId: user.id, groupId: value?.value });
54
+ }
55
+ }, title: usersTranslations.addGroup, options: groups?.map((group) => ({
56
+ value: group.id,
57
+ label: group.name,
58
+ })) }),
59
+ React.createElement(DeleteConfirmationDialog, { open: openConfirmationDialog, onClose: () => setOpenConfirmationDialog(false), onConfirm: () => deleteId
60
+ ? removeUserFromGroup({ userId: user.id, groupId: deleteId })
61
+ : {} })));
62
+ };
63
+ export default UserGroups;
@@ -1,9 +1,14 @@
1
1
  import React from 'react';
2
+ import { User } from '../../types/users';
2
3
  import { UserTab } from './UsersTabs';
3
4
  interface UsersProps {
4
5
  apiUrl: string;
5
6
  additionalTabs?: UserTab[];
7
+ onUserUpdate?: (newUser: User, oldUser: User) => void;
8
+ onUserCreate?: (newUser: User) => void;
9
+ onUserDelete?: (user: User) => void;
10
+ editUsername?: boolean;
6
11
  }
7
- declare const Users: ({ apiUrl, additionalTabs }: UsersProps) => React.JSX.Element;
12
+ declare const Users: ({ apiUrl, additionalTabs, onUserCreate, onUserUpdate, onUserDelete, editUsername, }: UsersProps) => React.JSX.Element;
8
13
  export default Users;
9
14
  //# sourceMappingURL=Users.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Users.d.ts","sourceRoot":"","sources":["../../../src/components/users/Users.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAanD,OAAiB,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGhD,UAAU,UAAU;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,OAAO,EAAE,CAAC;CAC5B;AAED,QAAA,MAAM,KAAK,+BAAqC,UAAU,sBAgIzD,CAAC;AAEF,eAAe,KAAK,CAAC"}
1
+ {"version":3,"file":"Users.d.ts","sourceRoot":"","sources":["../../../src/components/users/Users.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAWnD,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEzC,OAAiB,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGhD,UAAU,UAAU;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,OAAO,EAAE,CAAC;IAE3B,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,KAAK,IAAI,CAAC;IAEtD,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,KAAK,IAAI,CAAC;IAEvC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IAEpC,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,QAAA,MAAM,KAAK,wFAOR,UAAU,sBAyIZ,CAAC;AAEF,eAAe,KAAK,CAAC"}
@@ -0,0 +1,89 @@
1
+ 'use client';
2
+ import React, { useEffect, useState } from 'react';
3
+ import PersonAddIcon from '@mui/icons-material/PersonAdd';
4
+ import { Box, Button, Grid, IconButton, Link } from '@mui/material';
5
+ import ArrowBackIcon from '@mui/icons-material/ArrowBack';
6
+ import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight';
7
+ import { useAPI, useLocale } from '@deix/rossini-core';
8
+ import { useQueryClient } from '@tanstack/react-query';
9
+ import { SearchField } from '../../components';
10
+ import CreateUserDialog from './CreateUserDialog';
11
+ import UsersTable from './UsersTable';
12
+ import usersTranslations from '../../lang/users';
13
+ import { useDeleteUser, useUsers } from '../../utils/hooks/users';
14
+ import UserTabs from './UsersTabs';
15
+ import { APIClientProvider } from '../../utils/hooks/useAPIClient';
16
+ const Users = ({ apiUrl, additionalTabs = [], onUserCreate, onUserUpdate, onUserDelete, editUsername, }) => {
17
+ const locale = useLocale();
18
+ const apiClient = useAPI(apiUrl);
19
+ const queryClient = useQueryClient();
20
+ const { data: users } = useUsers(apiClient);
21
+ const { mutate: deleteUser } = useDeleteUser(queryClient, apiClient);
22
+ const [searchString, setSearchString] = useState('');
23
+ const [filteredUsers, setFilteredUsers] = useState();
24
+ const [selectedUser, setSelectedUser] = useState();
25
+ const [openCreateUserDialog, setOpenCreateUserDialog] = useState(false);
26
+ useEffect(() => {
27
+ if (users && searchString === '') {
28
+ setFilteredUsers(users);
29
+ }
30
+ else if (users && searchString !== '') {
31
+ setFilteredUsers(users.filter((user) => user.username?.toLowerCase().includes(searchString.toLowerCase()) ||
32
+ user.firstName
33
+ ?.toLowerCase()
34
+ .includes(searchString.toLowerCase()) ||
35
+ user.lastName
36
+ ?.toLocaleLowerCase()
37
+ .includes(searchString.toLowerCase())));
38
+ }
39
+ }, [searchString, users, setFilteredUsers]);
40
+ const handleDelete = (user) => {
41
+ deleteUser(user.id);
42
+ if (typeof onUserDelete === 'function') {
43
+ onUserDelete(user);
44
+ }
45
+ setSelectedUser(undefined);
46
+ };
47
+ return (React.createElement(APIClientProvider, { baseURL: apiUrl },
48
+ React.createElement(Box, { sx: {
49
+ flexGrow: 1,
50
+ maxWidth: '100%',
51
+ overflowX: 'hidden',
52
+ paddingTop: 3,
53
+ paddingLeft: 3,
54
+ paddingRight: 3,
55
+ } },
56
+ !selectedUser && (React.createElement(React.Fragment, null,
57
+ React.createElement(Grid, { container: true, spacing: 2, sx: { marginBottom: 2 } },
58
+ React.createElement(Grid, { item: true },
59
+ React.createElement(SearchField, { placeholder: usersTranslations.search[locale], onSearch: (value) => setSearchString(value) })),
60
+ React.createElement(Grid, { item: true },
61
+ React.createElement(Button, { variant: 'contained', startIcon: React.createElement(PersonAddIcon, null), onClick: () => {
62
+ setOpenCreateUserDialog(true);
63
+ setSelectedUser(undefined);
64
+ } }, usersTranslations.new[locale]))),
65
+ React.createElement(UsersTable, { users: filteredUsers, selectedUser: selectedUser, setSelectedUser: (user) => {
66
+ setSelectedUser(user);
67
+ }, onDelete: handleDelete }))),
68
+ selectedUser && (React.createElement(Box, { sx: {
69
+ display: 'flex',
70
+ flexDirection: 'column',
71
+ alignItems: 'flex-start',
72
+ width: '100%',
73
+ } },
74
+ React.createElement(Box, { sx: {
75
+ display: 'flex',
76
+ flexDirection: 'row',
77
+ alignItems: 'center',
78
+ } },
79
+ React.createElement(IconButton, { "aria-label": 'delete', color: 'primary', onClick: () => setSelectedUser(undefined), sx: { mr: 2 } },
80
+ React.createElement(ArrowBackIcon, null)),
81
+ React.createElement(Link, { underline: 'none', href: '#', onClick: () => setSelectedUser(undefined) }, usersTranslations.title[locale]),
82
+ React.createElement(KeyboardArrowRightIcon, null),
83
+ selectedUser.username),
84
+ React.createElement(UserTabs, { user: selectedUser, additionalTabs: additionalTabs, onUserUpdate: onUserUpdate, editUsername: editUsername }))),
85
+ React.createElement(CreateUserDialog, { open: openCreateUserDialog, onClose: () => {
86
+ setOpenCreateUserDialog(false);
87
+ }, onUserCreate: onUserCreate }))));
88
+ };
89
+ export default Users;
@@ -6,7 +6,7 @@ export interface TableProps {
6
6
  groups?: Group[];
7
7
  selectedUser?: User;
8
8
  setSelectedUser: (user: User) => void;
9
- onDelete: (id: string) => void;
9
+ onDelete: (user: User) => void;
10
10
  }
11
11
  declare const UsersTable: ({ users, selectedUser, setSelectedUser, onDelete, }: TableProps) => React.JSX.Element;
12
12
  export default UsersTable;
@@ -1 +1 @@
1
- {"version":3,"file":"UsersTable.d.ts","sourceRoot":"","sources":["../../../src/components/users/UsersTable.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAiB1B,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAuBzC,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IACf,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;IACjB,YAAY,CAAC,EAAE,IAAI,CAAC;IACpB,eAAe,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IACtC,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CAChC;AAED,QAAA,MAAM,UAAU,wDAKb,UAAU,sBAoEZ,CAAC;AAEF,eAAe,UAAU,CAAC"}
1
+ {"version":3,"file":"UsersTable.d.ts","sourceRoot":"","sources":["../../../src/components/users/UsersTable.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAiB1B,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAuBzC,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IACf,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;IACjB,YAAY,CAAC,EAAE,IAAI,CAAC;IACpB,eAAe,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IACtC,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;CAChC;AAED,QAAA,MAAM,UAAU,wDAKb,UAAU,sBAoEZ,CAAC;AAEF,eAAe,UAAU,CAAC"}
@@ -0,0 +1,62 @@
1
+ import React from 'react';
2
+ import { isStringTranslation, useLocale } from '@deix/rossini-core';
3
+ import CheckIcon from '@mui/icons-material/Check';
4
+ import CloseIcon from '@mui/icons-material/Close';
5
+ import DeleteIcon from '@mui/icons-material/Delete';
6
+ import { IconButton, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, useTheme, } from '@mui/material';
7
+ import { useState } from 'react';
8
+ import DeleteConfirmationDialog from '../DeleteConfirmationDialog';
9
+ const usersTableColumns = [
10
+ {
11
+ id: 'firstName',
12
+ label: { en: 'First Name', it: 'Nome' },
13
+ },
14
+ {
15
+ id: 'lastName',
16
+ label: { en: 'Last Name', it: 'Cognome' },
17
+ },
18
+ {
19
+ id: 'username',
20
+ label: { en: 'Username', it: 'Username' },
21
+ },
22
+ { id: 'email', label: 'Email' },
23
+ {
24
+ id: 'enabled',
25
+ label: { en: 'Enabled', it: 'Utente Abilitato' },
26
+ },
27
+ ];
28
+ const UsersTable = ({ users = [], selectedUser, setSelectedUser, onDelete, }) => {
29
+ const locale = useLocale();
30
+ const muiTheme = useTheme();
31
+ const [openConfirmationDialog, setOpenConfirmationDialog] = useState(false);
32
+ const [deleteUser, setDeleteUser] = useState();
33
+ return (React.createElement(React.Fragment, null,
34
+ React.createElement(TableContainer, null,
35
+ React.createElement(Table, { size: 'small' },
36
+ React.createElement(TableHead, null,
37
+ React.createElement(TableRow, null,
38
+ usersTableColumns.map((col) => (React.createElement(TableCell, { key: col.id, align: col.align || 'inherit' }, isStringTranslation(col.label)
39
+ ? col.label[locale]
40
+ : col.label))),
41
+ React.createElement(TableCell, { padding: 'none' }, ''))),
42
+ React.createElement(TableBody, null, users.map((user, rowIdx) => (React.createElement(TableRow, { key: rowIdx, onClick: () => setSelectedUser(user), sx: {
43
+ cursor: 'pointer',
44
+ background: selectedUser && user.id === selectedUser.id
45
+ ? muiTheme.palette.primary.light
46
+ : undefined,
47
+ } },
48
+ React.createElement(TableCell, null, user.firstName),
49
+ React.createElement(TableCell, null, user.lastName),
50
+ React.createElement(TableCell, null, user.username),
51
+ React.createElement(TableCell, null, user.email),
52
+ React.createElement(TableCell, null, user.enabled ? React.createElement(CheckIcon, null) : React.createElement(CloseIcon, null)),
53
+ React.createElement(TableCell, { padding: 'none', align: 'right' },
54
+ React.createElement(IconButton, { size: 'small', onClick: (evt) => {
55
+ evt.stopPropagation();
56
+ setOpenConfirmationDialog(true);
57
+ setDeleteUser(user);
58
+ } },
59
+ React.createElement(DeleteIcon, null))))))))),
60
+ React.createElement(DeleteConfirmationDialog, { open: openConfirmationDialog, onClose: () => setOpenConfirmationDialog(false), onConfirm: () => (deleteUser ? onDelete(deleteUser) : {}) })));
61
+ };
62
+ export default UsersTable;
@@ -10,7 +10,9 @@ export interface UserTab {
10
10
  export interface UserTabsProps {
11
11
  user: User;
12
12
  additionalTabs?: UserTab[];
13
+ onUserUpdate?: (newUser: User, oldUser: User) => void;
14
+ editUsername?: boolean;
13
15
  }
14
- declare const UserTabs: ({ user, additionalTabs }: UserTabsProps) => React.JSX.Element;
16
+ declare const UserTabs: ({ user, additionalTabs, onUserUpdate, editUsername, }: UserTabsProps) => React.JSX.Element;
15
17
  export default UserTabs;
16
18
  //# sourceMappingURL=UsersTabs.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"UsersTabs.d.ts","sourceRoot":"","sources":["../../../src/components/users/UsersTabs.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAExC,OAAO,EAAE,iBAAiB,EAAa,MAAM,oBAAoB,CAAC;AAElE,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAKzC,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,iBAAiB,CAAC;IACzB,SAAS,EAAE,KAAK,CAAC,iBAAiB,CAAC;QAAE,IAAI,EAAE,IAAI,CAAA;KAAE,CAAC,CAAC;CACpD;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,IAAI,CAAC;IACX,cAAc,CAAC,EAAE,OAAO,EAAE,CAAC;CAC5B;AAED,QAAA,MAAM,QAAQ,6BAAmC,aAAa,sBAoD7D,CAAC;AAEF,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"UsersTabs.d.ts","sourceRoot":"","sources":["../../../src/components/users/UsersTabs.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAExC,OAAO,EAAE,iBAAiB,EAAa,MAAM,oBAAoB,CAAC;AAElE,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAKzC,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,iBAAiB,CAAC;IACzB,SAAS,EAAE,KAAK,CAAC,iBAAiB,CAAC;QAAE,IAAI,EAAE,IAAI,CAAA;KAAE,CAAC,CAAC;CACpD;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,IAAI,CAAC;IACX,cAAc,CAAC,EAAE,OAAO,EAAE,CAAC;IAC3B,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,KAAK,IAAI,CAAC;IACtD,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,QAAA,MAAM,QAAQ,0DAKX,aAAa,sBA0Df,CAAC;AAEF,eAAe,QAAQ,CAAC"}
@@ -0,0 +1,32 @@
1
+ 'use client';
2
+ import React, { useState } from 'react';
3
+ import { Box, Tab, Tabs } from '@mui/material';
4
+ import { useLocale } from '@deix/rossini-core';
5
+ import usersTranslations from '../../lang/users';
6
+ import UserDetails from './UserDetails';
7
+ import UserGroups from './UserGroups';
8
+ import UserCredentials from './UserCredentials';
9
+ const UserTabs = ({ user, additionalTabs = [], onUserUpdate, editUsername, }) => {
10
+ const locale = useLocale();
11
+ const [selectedTab, setSelectedTab] = useState('DETAILS');
12
+ return (React.createElement(Box, { sx: {
13
+ flexGrow: 1,
14
+ maxWidth: '100%',
15
+ overflowX: 'hidden',
16
+ alignSelf: 'stretch',
17
+ } },
18
+ React.createElement(Box, { sx: { borderBottom: 1, borderColor: 'divider' } },
19
+ React.createElement(Tabs, { value: selectedTab, onChange: (_evt, newValue) => {
20
+ setSelectedTab(newValue);
21
+ }, "aria-label": 'basic tabs example' },
22
+ React.createElement(Tab, { label: usersTranslations.details[locale], value: 'DETAILS' }),
23
+ React.createElement(Tab, { label: usersTranslations.userGroups[locale], value: 'USER_GROUPS' }),
24
+ React.createElement(Tab, { label: usersTranslations.credentials[locale], value: 'CREDENTIALS' }),
25
+ additionalTabs.map((tab, index) => (React.createElement(Tab, { key: `tab${index}`, label: tab.title[locale], value: `ADDITIONAL_TAB_${index}` }))))),
26
+ React.createElement(Box, { sx: { p: 1 } },
27
+ selectedTab === 'DETAILS' && (React.createElement(UserDetails, { user: user, onUserUpdate: onUserUpdate, editUsername: editUsername })),
28
+ selectedTab === 'USER_GROUPS' && React.createElement(UserGroups, { user: user }),
29
+ selectedTab === 'CREDENTIALS' && React.createElement(UserCredentials, { user: user }),
30
+ additionalTabs.map((tab, index) => selectedTab === `ADDITIONAL_TAB_${index}` && (React.createElement(tab.component, { key: `tab${index}`, user: user }))))));
31
+ };
32
+ export default UserTabs;
@@ -13,8 +13,6 @@ export const getConfig = (publicRuntimeEnv) => ({
13
13
  // read at runtime
14
14
  const ConfigContext = createContext(getConfig({}));
15
15
  export const ConfigProvider = ({ publicRuntimeEnv, children, }) => {
16
- return (<ConfigContext.Provider value={getConfig(publicRuntimeEnv)}>
17
- {children}
18
- </ConfigContext.Provider>);
16
+ return (React.createElement(ConfigContext.Provider, { value: getConfig(publicRuntimeEnv) }, children));
19
17
  };
20
18
  export const useConfig = () => useContext(ConfigContext);
@@ -1 +1 @@
1
- {"version":3,"file":"users.d.ts","sourceRoot":"","sources":["../../src/lang/users.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAEvD,QAAA,MAAM,iBAAiB;;CAyHkB,CAAC;AAE1C,eAAe,iBAAiB,CAAC"}
1
+ {"version":3,"file":"users.d.ts","sourceRoot":"","sources":["../../src/lang/users.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAEvD,QAAA,MAAM,iBAAiB;;CA6HkB,CAAC;AAE1C,eAAe,iBAAiB,CAAC"}
package/lib/lang/users.js CHANGED
@@ -71,6 +71,10 @@ const usersTranslations = {
71
71
  en: 'Save',
72
72
  it: 'Salva',
73
73
  },
74
+ requiredField: {
75
+ en: 'Required',
76
+ it: 'Obbligatorio',
77
+ },
74
78
  addUserSuccess: {
75
79
  en: 'User created successfully',
76
80
  it: 'Utente creato con successo',