@deix/rossini-identity-management 0.1.1 → 0.2.1

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 +97 -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 +103 -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
@@ -1 +1 @@
1
- {"version":3,"file":"groups.d.ts","sourceRoot":"","sources":["../../../src/utils/hooks/groups.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,cAAc,EAGf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAGtC,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAUzC,eAAO,MAAM,SAAS,cACT,aAAa,KACvB,eAAe,KAAK,EAAE,GAAG,SAAS,EAAE,KAAK,CAM3C,CAAC;AAcF,eAAO,MAAM,WAAW,gBACT,WAAW,aACb,aAAa,oDA6BzB,CAAC;AAiBF,eAAO,MAAM,cAAc,gBACZ,WAAW,aACb,aAAa,oDA8BzB,CAAC;AAkBF,eAAO,MAAM,cAAc,gBACZ,WAAW,aACb,aAAa,6EA6BzB,CAAC;AAgBF,eAAO,MAAM,aAAa,OACpB,MAAM,GAAG,SAAS,aACX,aAAa,KACvB,eAAe,IAAI,EAAE,GAAG,SAAS,EAAE,KAAK,CAM1C,CAAC"}
1
+ {"version":3,"file":"groups.d.ts","sourceRoot":"","sources":["../../../src/utils/hooks/groups.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,cAAc,EAGf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAGtC,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAUzC,eAAO,MAAM,SAAS,cACT,aAAa,KACvB,eAAe,KAAK,EAAE,GAAG,SAAS,EAAE,KAAK,CAM3C,CAAC;AAcF,eAAO,MAAM,WAAW,gBACT,WAAW,aACb,aAAa,oDA6BzB,CAAC;AAiBF,eAAO,MAAM,cAAc,gBACZ,WAAW,aACb,aAAa,oDA8BzB,CAAC;AAgBF,eAAO,MAAM,cAAc,gBACZ,WAAW,aACb,aAAa,6EA6BzB,CAAC;AAgBF,eAAO,MAAM,aAAa,OACpB,MAAM,GAAG,SAAS,aACX,aAAa,KACvB,eAAe,IAAI,EAAE,GAAG,SAAS,EAAE,KAAK,CAM1C,CAAC"}
@@ -81,9 +81,7 @@ export const useUpdateGroup = (queryClient, apiClient) => {
81
81
  // Delete group
82
82
  const deleteGroup = async ({ id, apiClient, }) => {
83
83
  if (id) {
84
- console.log('hey delete', id);
85
84
  const { data } = await apiClient.delete(`/groups/${id}`);
86
- console.log(data);
87
85
  return data;
88
86
  }
89
87
  };
@@ -6,13 +6,11 @@ const APIContext = createContext(axios.create({
6
6
  },
7
7
  }));
8
8
  export const APIClientProvider = ({ baseURL, children, }) => {
9
- return (<APIContext.Provider value={axios.create({
9
+ return (React.createElement(APIContext.Provider, { value: axios.create({
10
10
  baseURL,
11
11
  headers: {
12
12
  Accept: 'application/json',
13
13
  },
14
- })}>
15
- {children}
16
- </APIContext.Provider>);
14
+ }) }, children));
17
15
  };
18
16
  export const useAPIClient = () => useContext(APIContext);
@@ -1 +1 @@
1
- {"version":3,"file":"users.d.ts","sourceRoot":"","sources":["../../../src/utils/hooks/users.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,cAAc,EAGf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAGtC,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAUjE,eAAO,MAAM,QAAQ,cACR,aAAa,KACvB,eAAe,IAAI,EAAE,GAAG,SAAS,EAAE,KAAK,CAM1C,CAAC;AAQF,eAAO,MAAM,OAAO,OACd,MAAM,aACC,aAAa,KACvB,eAAe,IAAI,GAAG,SAAS,EAAE,KAAK,CAMxC,CAAC;AAyBF,eAAO,MAAM,UAAU,gBACR,WAAW,aACb,aAAa,4DAgCzB,CAAC;AAiBF,eAAO,MAAM,aAAa,gBACX,WAAW,aACb,aAAa,kDA6BzB,CAAC;AAgBF,eAAO,MAAM,aAAa,gBACX,WAAW,aACb,aAAa,4EA6BzB,CAAC;AAcF,eAAO,MAAM,aAAa,OACpB,MAAM,GAAG,SAAS,aACX,aAAa,KACvB,eAAe,KAAK,EAAE,GAAG,SAAS,EAAE,KAAK,CAM3C,CAAC;AAmBF,eAAO,MAAM,iBAAiB,gBACf,WAAW,aACb,aAAa;;;;YAIsB,MAAM;aAAW,MAAM;WA8BtE,CAAC;AAmBF,eAAO,MAAM,sBAAsB,gBACpB,WAAW,aACb,aAAa;;;;YAIsB,MAAM;aAAW,MAAM;WA8BtE,CAAC;AAkBF,eAAO,MAAM,0BAA0B,gBACxB,WAAW,aACb,aAAa;;0BAoBzB,CAAC"}
1
+ {"version":3,"file":"users.d.ts","sourceRoot":"","sources":["../../../src/utils/hooks/users.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,cAAc,EAGf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAGtC,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAUjE,eAAO,MAAM,QAAQ,cACR,aAAa,KACvB,eAAe,IAAI,EAAE,GAAG,SAAS,EAAE,KAAK,CAM1C,CAAC;AAQF,eAAO,MAAM,OAAO,OACd,MAAM,aACC,aAAa,KACvB,eAAe,IAAI,GAAG,SAAS,EAAE,KAAK,CAMxC,CAAC;AAwBF,eAAO,MAAM,UAAU,gBACR,WAAW,aACb,aAAa,4DAgCzB,CAAC;AAiBF,eAAO,MAAM,aAAa,gBACX,WAAW,aACb,aAAa,kDA6BzB,CAAC;AAgBF,eAAO,MAAM,aAAa,gBACX,WAAW,aACb,aAAa,4EA6BzB,CAAC;AAcF,eAAO,MAAM,aAAa,OACpB,MAAM,GAAG,SAAS,aACX,aAAa,KACvB,eAAe,KAAK,EAAE,GAAG,SAAS,EAAE,KAAK,CAM3C,CAAC;AAmBF,eAAO,MAAM,iBAAiB,gBACf,WAAW,aACb,aAAa;;;;YAIsB,MAAM;aAAW,MAAM;WA8BtE,CAAC;AAmBF,eAAO,MAAM,sBAAsB,gBACpB,WAAW,aACb,aAAa;;;;YAIsB,MAAM;aAAW,MAAM;WA8BtE,CAAC;AAkBF,eAAO,MAAM,0BAA0B,gBACxB,WAAW,aACb,aAAa;;0BAoBzB,CAAC"}
@@ -36,7 +36,6 @@ const addUser = async ({ newUser, sendEmailOnCreation, apiClient, }) => {
36
36
  // it in order to get its ID and send the email
37
37
  const users = await getUsers(apiClient, newUser.username);
38
38
  if (users.length > 0) {
39
- console.log(users[0].id);
40
39
  await sendUpdatePasswordEmail({ userId: users[0].id, apiClient });
41
40
  }
42
41
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deix/rossini-identity-management",
3
- "version": "0.1.1",
3
+ "version": "0.2.1",
4
4
  "main": "lib/index.js",
5
5
  "repository": {
6
6
  "type": "git",
@@ -87,12 +87,9 @@
87
87
  }
88
88
  },
89
89
  "dependencies": {
90
- "@deix/rossini-form": "^2.0.0",
91
- "@formatjs/intl-localematcher": "^0.5.2",
90
+ "@deix/rossini-core": "^2.1.5",
92
91
  "@mui/icons-material": "^5.11.0",
93
92
  "@mui/material": "^5.11.8",
94
- "@types/negotiator": "^0.6.3",
95
- "negotiator": "^0.6.3",
96
93
  "notistack": "^3.0.1",
97
94
  "react-hook-form": "^7.49.3"
98
95
  }
@@ -1,50 +0,0 @@
1
- import React from 'react';
2
- import { Autocomplete, Button, Dialog, DialogActions, DialogContent, DialogTitle, TextField, } from '@mui/material';
3
- import { useLocale } from '@deix/rossini-core';
4
- import { useEffect, useState } from 'react';
5
- const translations = {
6
- ok: {
7
- en: 'Add',
8
- it: 'Aggiungi',
9
- },
10
- cancel: {
11
- en: 'Cancel',
12
- it: 'Annulla',
13
- },
14
- search: {
15
- en: 'Search...',
16
- it: 'Cerca...',
17
- },
18
- };
19
- const AddItemDialog = ({ title, options, open, onClose, onConfirm, }) => {
20
- const locale = useLocale();
21
- const [value, setValue] = useState(null);
22
- // Reset the value when the dialog is closed
23
- useEffect(() => {
24
- if (!open) {
25
- setValue(null);
26
- }
27
- }, [open]);
28
- return (<Dialog open={open} fullWidth maxWidth='sm' onClose={onClose}>
29
- <DialogTitle>{title[locale]}</DialogTitle>
30
- <DialogContent>
31
- <Autocomplete
32
- // multiple
33
- options={options ?? []} getOptionLabel={(option) => option.label} getOptionKey={(option) => option.value} isOptionEqualToValue={(option, value) => option.value === value.value} renderInput={(params) => (<TextField {...params} label={translations.search[locale]} placeholder=''/>)} onChange={(event, newValue) => {
34
- setValue(newValue);
35
- }} value={value}/>
36
- </DialogContent>
37
- <DialogActions>
38
- <Button size='small' variant='outlined' onClick={onClose}>
39
- {translations.cancel[locale]}
40
- </Button>
41
- <Button variant='contained' onClick={() => {
42
- onConfirm(value);
43
- onClose();
44
- }}>
45
- {translations.ok[locale]}
46
- </Button>
47
- </DialogActions>
48
- </Dialog>);
49
- };
50
- export default AddItemDialog;
@@ -1,44 +0,0 @@
1
- import React from 'react';
2
- import { Button, Dialog, DialogActions, DialogContent, DialogTitle, Typography, } from '@mui/material';
3
- import { useLocale } from '@deix/rossini-core';
4
- const translations = {
5
- title: {
6
- en: 'Delete item?',
7
- it: 'Cancellare elemento?',
8
- },
9
- message: {
10
- en: 'This is a permanent action',
11
- it: "Questa è un'azione permanente",
12
- },
13
- yes: {
14
- en: 'Yes',
15
- it: 'Si',
16
- },
17
- no: {
18
- en: 'No',
19
- it: 'No',
20
- },
21
- };
22
- const DeleteConfirmationDialog = ({ open, onClose, onConfirm, }) => {
23
- const locale = useLocale();
24
- return (<Dialog open={open} fullWidth maxWidth='sm' onClose={onClose}>
25
- <DialogTitle>{translations.title[locale]}</DialogTitle>
26
- <DialogContent>
27
- <Typography variant='caption'>
28
- {translations.message[locale]}
29
- </Typography>
30
- </DialogContent>
31
- <DialogActions>
32
- <Button size='small' variant='outlined' onClick={onClose}>
33
- {translations.no[locale]}
34
- </Button>
35
- <Button size='small' variant='contained' onClick={() => {
36
- onConfirm();
37
- onClose();
38
- }}>
39
- {translations.yes[locale]}
40
- </Button>
41
- </DialogActions>
42
- </Dialog>);
43
- };
44
- export default DeleteConfirmationDialog;
@@ -1,18 +0,0 @@
1
- import React from 'react';
2
- import SearchIcon from '@mui/icons-material/Search';
3
- import { IconButton, TextField, } from '@mui/material';
4
- import { useState } from 'react';
5
- const SearchField = ({ placeholder = 'Search...', onSearch, ...props }) => {
6
- const [value, setValue] = useState('');
7
- return (<>
8
- <TextField size='small' placeholder={placeholder} value={value} onChange={(evt) => {
9
- setValue(evt.target.value);
10
- onSearch(evt.target.value);
11
- }} {...props} InputProps={{
12
- endAdornment: (<IconButton size='small' onClick={() => onSearch(value)}>
13
- <SearchIcon />
14
- </IconButton>),
15
- }}/>
16
- </>);
17
- };
18
- export default SearchField;
@@ -1,17 +0,0 @@
1
- import React from 'react';
2
- import { useQueryClient } from '@tanstack/react-query';
3
- import { useUpdateGroup } from '../../utils/hooks/groups';
4
- import GroupForm from './GroupForm';
5
- import { useAPIClient } from '../../utils/hooks/useAPIClient';
6
- const GroupDetails = ({ group }) => {
7
- const apiClient = useAPIClient();
8
- const queryClient = useQueryClient();
9
- const { mutate: updateGroup } = useUpdateGroup(queryClient, apiClient);
10
- const handleUpdate = (group) => {
11
- updateGroup(group);
12
- };
13
- return (<>
14
- <GroupForm mode='modify' group={group} onSave={handleUpdate} onCancel={() => { }}/>
15
- </>);
16
- };
17
- export default GroupDetails;
@@ -1,46 +0,0 @@
1
- import React from 'react';
2
- import { useLocale } from '@deix/rossini-core';
3
- import { Button, Grid, TextField } from '@mui/material';
4
- import { Controller, useForm } from 'react-hook-form';
5
- import { useEffect } from 'react';
6
- import groupsTranslations from '../../lang/groups';
7
- const GroupForm = ({ group, onCancel, onSave, mode }) => {
8
- const locale = useLocale();
9
- const { control, handleSubmit, setValue } = useForm({
10
- defaultValues: {
11
- id: group?.id,
12
- name: group?.name,
13
- },
14
- });
15
- useEffect(() => {
16
- if (group) {
17
- setValue('id', group?.id);
18
- setValue('name', group?.name);
19
- }
20
- }, [group, setValue]);
21
- const onSubmit = (data) => {
22
- onSave(data);
23
- };
24
- return (<form onSubmit={(event) => void handleSubmit(onSubmit)(event)}>
25
- <Grid container spacing={2} sx={{ mt: 2, maxWidth: 'sm' }} justifyContent='stretch'>
26
- <Grid item xs={12}>
27
- <Controller name='name' control={control} render={({ field }) => (<TextField size='small' fullWidth label={groupsTranslations.name[locale]} sx={{ flexShrink: 0 }} {...field}/>)}/>
28
- </Grid>
29
- <Grid item sx={{
30
- mt: 2,
31
- display: 'flex',
32
- justifyContent: 'flex-end',
33
- gap: 2,
34
- width: '100%',
35
- }}>
36
- {mode === 'create' && (<Button variant='outlined' onClick={onCancel}>
37
- {groupsTranslations.cancel[locale]}
38
- </Button>)}
39
- <Button variant='contained' type='submit'>
40
- {groupsTranslations.save[locale]}
41
- </Button>
42
- </Grid>
43
- </Grid>
44
- </form>);
45
- };
46
- export default GroupForm;
@@ -1,33 +0,0 @@
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 GroupDetails from './GroupDetails';
6
- import groupsTranslations from '../../lang/groups';
7
- import GroupUsers from './GroupUsers';
8
- const GroupTabs = ({ group, additionalTabs = [] }) => {
9
- const locale = useLocale();
10
- const [selectedTab, setSelectedTab] = useState('DETAILS');
11
- return (<Box sx={{
12
- flexGrow: 1,
13
- maxWidth: '100%',
14
- overflowX: 'hidden',
15
- alignSelf: 'stretch',
16
- }}>
17
- <Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
18
- <Tabs value={selectedTab} onChange={(_evt, newValue) => {
19
- setSelectedTab(newValue);
20
- }} aria-label='basic tabs example'>
21
- <Tab label={groupsTranslations.details[locale]} value='DETAILS'/>
22
- <Tab label={groupsTranslations.users[locale]} value='USERS'/>
23
- {additionalTabs.map((tab, index) => (<Tab key={`tab${index}`} label={tab.title[locale]} value={`ADDITIONAL_TAB_${index}`}/>))}
24
- </Tabs>
25
- </Box>
26
- <Box sx={{ p: 1 }}>
27
- {selectedTab === 'DETAILS' && <GroupDetails group={group}/>}
28
- {selectedTab === 'USERS' && <GroupUsers group={group}/>}
29
- {additionalTabs.map((tab, index) => selectedTab === `ADDITIONAL_TAB_${index}` && (<tab.component key={`tab${index}`} group={group}/>))}
30
- </Box>
31
- </Box>);
32
- };
33
- export default GroupTabs;
@@ -1,88 +0,0 @@
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, useUsers, } from '../../utils/hooks/users';
7
- import { useState } from 'react';
8
- import DeleteConfirmationDialog from '../DeleteConfirmationDialog';
9
- import { useQueryClient } from '@tanstack/react-query';
10
- import AddItemDialog from '../AddItemDialog';
11
- import { useGroupUsers } from '../../utils/hooks/groups';
12
- import groupsTranslations from '../../lang/groups';
13
- import { useAPIClient } from '../../utils/hooks/useAPIClient';
14
- const groupUsersTableColumns = [
15
- {
16
- id: 'username',
17
- label: { en: 'Username', it: 'Username' },
18
- },
19
- {
20
- id: 'firstName',
21
- label: { en: 'First name', it: 'Nome' },
22
- },
23
- {
24
- id: 'lastName',
25
- label: { en: 'Last name', it: 'Cognome' },
26
- },
27
- ];
28
- const GroupUsers = ({ group }) => {
29
- const locale = useLocale();
30
- const apiClient = useAPIClient();
31
- const queryClient = useQueryClient();
32
- const { data: users } = useUsers(apiClient);
33
- const { data: groupUsers } = useGroupUsers(group?.id, apiClient);
34
- const { mutate: addUserToGroup } = useAddUserToGroup(queryClient, apiClient);
35
- const { mutate: removeUserFromGroup } = useRemoveUserFromGroup(queryClient, apiClient);
36
- const [openAddUserDialog, setOpenAddUserDialog] = useState(false);
37
- const [openConfirmationDialog, setOpenConfirmationDialog] = useState(false);
38
- const [deleteId, setDeleteId] = useState();
39
- return (<>
40
- {groupUsers && groupUsers.length > 0 && (<Box maxWidth='md'>
41
- <TableContainer>
42
- <Table size='small'>
43
- <TableHead>
44
- <TableRow>
45
- {groupUsersTableColumns.map((col) => (<TableCell key={col.id} align={col.align || 'inherit'}>
46
- {isStringTranslation(col.label)
47
- ? col.label[locale]
48
- : col.label}
49
- </TableCell>))}
50
- <TableCell padding='none'>{''}</TableCell>
51
- </TableRow>
52
- </TableHead>
53
- <TableBody>
54
- {groupUsers?.map((user, rowIdx) => (<TableRow key={rowIdx}>
55
- <TableCell>{user.username}</TableCell>
56
- <TableCell>{user.firstName}</TableCell>
57
- <TableCell>{user.lastName}</TableCell>
58
- <TableCell padding='none' align='right'>
59
- <IconButton size='small' onClick={(evt) => {
60
- evt.stopPropagation();
61
- setOpenConfirmationDialog(true);
62
- setDeleteId(user.id);
63
- }}>
64
- <DeleteIcon />
65
- </IconButton>
66
- </TableCell>
67
- </TableRow>))}
68
- </TableBody>
69
- </Table>
70
- </TableContainer>
71
- </Box>)}
72
- <Button variant='outlined' startIcon={<AddIcon />} onClick={() => setOpenAddUserDialog(true)} sx={{ marginTop: 2 }}>
73
- {groupsTranslations.addUser[locale]}
74
- </Button>
75
- <AddItemDialog open={openAddUserDialog} onClose={() => setOpenAddUserDialog(false)} onConfirm={(value) => {
76
- if (value) {
77
- addUserToGroup({ userId: value?.value, groupId: group.id });
78
- }
79
- }} title={groupsTranslations.addUser} options={users?.map((user) => ({
80
- value: user.id,
81
- label: user.username || '',
82
- }))}/>
83
- <DeleteConfirmationDialog open={openConfirmationDialog} onClose={() => setOpenConfirmationDialog(false)} onConfirm={() => deleteId
84
- ? removeUserFromGroup({ userId: deleteId, groupId: group.id })
85
- : {}}/>
86
- </>);
87
- };
88
- export default GroupUsers;
@@ -1,93 +0,0 @@
1
- 'use client';
2
- import React, { useEffect, useState } from 'react';
3
- import GroupAddIcon from '@mui/icons-material/GroupAdd';
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 { SearchField } from '..';
9
- import CreateGroupDialog from './CreateGroupDialog';
10
- import GroupsTable from './GroupsTable';
11
- import groupsTranslations from '../../lang/groups';
12
- import { useDeleteGroup, useGroups } from '../../utils/hooks/groups';
13
- import GroupTabs from './GroupTabs';
14
- import { useQueryClient } from '@tanstack/react-query';
15
- import { APIClientProvider } from '../../utils/hooks/useAPIClient';
16
- const Groups = ({ apiUrl, additionalTabs = [] }) => {
17
- const locale = useLocale();
18
- const apiClient = useAPI(apiUrl);
19
- const queryClient = useQueryClient();
20
- const { data: groups } = useGroups(apiClient);
21
- const { mutate: deleteGroup } = useDeleteGroup(queryClient, apiClient);
22
- const [searchString, setSearchString] = useState('');
23
- const [filteredGroups, setFilteredGroups] = useState();
24
- const [selectedGroup, setSelectedGroup] = useState();
25
- const [openGroupDialog, setOpenGroupDialog] = useState(false);
26
- useEffect(() => {
27
- if (groups && searchString === '') {
28
- setFilteredGroups(groups);
29
- }
30
- else if (groups && searchString !== '') {
31
- setFilteredGroups(groups.filter((group) => group.name.includes(searchString)));
32
- }
33
- }, [searchString, groups, setFilteredGroups]);
34
- const handleDelete = (id) => {
35
- deleteGroup(id);
36
- setSelectedGroup(undefined);
37
- };
38
- return (<APIClientProvider baseURL={apiUrl}>
39
- <Box sx={{
40
- flexGrow: 1,
41
- maxWidth: '100%',
42
- overflowX: 'hidden',
43
- paddingTop: 3,
44
- paddingLeft: 3,
45
- paddingRight: 3,
46
- }}>
47
- {!selectedGroup && (<>
48
- <Grid container spacing={2} sx={{ marginBottom: 2 }}>
49
- <Grid item>
50
- <SearchField placeholder={groupsTranslations.search[locale]} onSearch={(value) => setSearchString(value)}/>
51
- </Grid>
52
- <Grid item>
53
- <Button variant='contained' startIcon={<GroupAddIcon />} onClick={() => {
54
- setOpenGroupDialog(true);
55
- setSelectedGroup(undefined);
56
- }}>
57
- {groupsTranslations.new[locale]}
58
- </Button>
59
- </Grid>
60
- </Grid>
61
- <GroupsTable groups={filteredGroups} selectedGroup={selectedGroup} setSelectedGroup={(group) => {
62
- setSelectedGroup(group);
63
- }} onDelete={handleDelete}/>
64
- </>)}
65
- {selectedGroup && (<Box sx={{
66
- display: 'flex',
67
- flexDirection: 'column',
68
- alignItems: 'flex-start',
69
- width: '100%',
70
- }}>
71
- <Box sx={{
72
- display: 'flex',
73
- flexDirection: 'row',
74
- alignItems: 'center',
75
- }}>
76
- <IconButton aria-label='delete' color='primary' onClick={() => setSelectedGroup(undefined)} sx={{ mr: 2 }}>
77
- <ArrowBackIcon />
78
- </IconButton>
79
- <Link underline='none' href='#' onClick={() => setSelectedGroup(undefined)}>
80
- {groupsTranslations.title[locale]}
81
- </Link>
82
- <KeyboardArrowRightIcon />
83
- {selectedGroup.name}
84
- </Box>
85
- <GroupTabs group={selectedGroup} additionalTabs={additionalTabs}/>
86
- </Box>)}
87
- <CreateGroupDialog open={openGroupDialog} onClose={() => {
88
- setOpenGroupDialog(false);
89
- }}/>
90
- </Box>
91
- </APIClientProvider>);
92
- };
93
- export default Groups;
@@ -1,55 +0,0 @@
1
- import React from 'react';
2
- import { isStringTranslation, useLocale } from '@deix/rossini-core';
3
- import DeleteIcon from '@mui/icons-material/Delete';
4
- import { IconButton, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, useTheme, } from '@mui/material';
5
- import { useState } from 'react';
6
- import DeleteConfirmationDialog from '../DeleteConfirmationDialog';
7
- const groupsTableColumns = [
8
- {
9
- id: 'name',
10
- label: { en: 'Name', it: 'Nome' },
11
- },
12
- ];
13
- const GroupsTable = ({ groups = [], selectedGroup, setSelectedGroup, onDelete, }) => {
14
- const locale = useLocale();
15
- const muiTheme = useTheme();
16
- const [openConfirmationDialog, setOpenConfirmationDialog] = useState(false);
17
- const [deleteId, setDeleteId] = useState();
18
- return (<>
19
- <TableContainer>
20
- <Table size='small'>
21
- <TableHead>
22
- <TableRow>
23
- {groupsTableColumns.map((col) => (<TableCell key={col.id} align={col.align || 'inherit'}>
24
- {isStringTranslation(col.label)
25
- ? col.label[locale]
26
- : col.label}
27
- </TableCell>))}
28
- <TableCell padding='none'>{''}</TableCell>
29
- </TableRow>
30
- </TableHead>
31
- <TableBody>
32
- {groups.map((group, rowIdx) => (<TableRow key={rowIdx} onClick={() => setSelectedGroup(group)} sx={{
33
- cursor: 'pointer',
34
- background: selectedGroup && group.id === selectedGroup.id
35
- ? muiTheme.palette.primary.light
36
- : undefined,
37
- }}>
38
- <TableCell>{group.name}</TableCell>
39
- <TableCell padding='none' align='right'>
40
- <IconButton size='small' onClick={(evt) => {
41
- evt.stopPropagation();
42
- setOpenConfirmationDialog(true);
43
- setDeleteId(group.id);
44
- }}>
45
- <DeleteIcon />
46
- </IconButton>
47
- </TableCell>
48
- </TableRow>))}
49
- </TableBody>
50
- </Table>
51
- </TableContainer>
52
- <DeleteConfirmationDialog open={openConfirmationDialog} onClose={() => setOpenConfirmationDialog(false)} onConfirm={() => (deleteId ? onDelete(deleteId) : {})}/>
53
- </>);
54
- };
55
- export default GroupsTable;
@@ -1,17 +0,0 @@
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 }) => {
7
- const apiClient = useAPIClient();
8
- const queryClient = useQueryClient();
9
- const { mutate: updateUser } = useUpdateUser(queryClient, apiClient);
10
- const handleUpdate = (user) => {
11
- updateUser(user);
12
- };
13
- return (<>
14
- <UserForm mode='modify' user={user} onSave={handleUpdate} onCancel={() => { }}/>
15
- </>);
16
- };
17
- export default UserDetails;
@@ -1,75 +0,0 @@
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', }) => {
8
- const locale = useLocale();
9
- const { control, 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 (<form onSubmit={(event) => void handleSubmit(onSubmit)(event)}>
39
- <Grid container spacing={2} sx={{ mt: 2, maxWidth: 'sm' }} justifyContent='stretch'>
40
- <Grid item xs={12}>
41
- <Controller name='username' control={control} render={({ field }) => (<TextField size='small' fullWidth label={usersTranslations.username[locale]} disabled={mode === 'modify'} sx={{ flexShrink: 0 }} {...field}/>)}/>
42
- </Grid>
43
- <Grid item xs={12}>
44
- <Controller name='firstName' control={control} render={({ field }) => (<TextField size='small' fullWidth label={usersTranslations.firstName[locale]} sx={{ flexShrink: 0 }} {...field}/>)}/>
45
- </Grid>
46
- <Grid item xs={12}>
47
- <Controller name='lastName' control={control} render={({ field }) => (<TextField size='small' fullWidth label={usersTranslations.lastName[locale]} sx={{ flexShrink: 0 }} {...field}/>)}/>
48
- </Grid>
49
- <Grid item xs={12}>
50
- <Controller name='email' control={control} render={({ field }) => (<TextField size='small' fullWidth label={usersTranslations.email[locale]} sx={{ flexShrink: 0 }} {...field}/>)}/>
51
- </Grid>
52
- <Grid item xs={12}>
53
- <Controller name='enabled' control={control} render={({ field }) => (<FormControlLabel sx={{ ml: 1 }} control={<Switch checked={field.value} size='small' {...field}/>} label={usersTranslations.enabled[locale]}/>)}/>
54
- </Grid>
55
- {mode === 'create' && (<Grid item xs={12}>
56
- <Controller name='sendEmailOnCreation' control={control} render={({ field }) => (<FormControlLabel sx={{ ml: 1 }} control={<Switch checked={field.value} size='small' {...field}/>} label={usersTranslations.sendResetPasswordEmail[locale]}/>)}/>
57
- </Grid>)}
58
- <Grid item sx={{
59
- mt: 2,
60
- display: 'flex',
61
- justifyContent: 'flex-end',
62
- gap: 2,
63
- width: '100%',
64
- }}>
65
- {mode === 'create' && (<Button variant='outlined' onClick={onCancel}>
66
- {usersTranslations.cancel[locale]}
67
- </Button>)}
68
- <Button variant='contained' type='submit'>
69
- {usersTranslations.save[locale]}
70
- </Button>
71
- </Grid>
72
- </Grid>
73
- </form>);
74
- };
75
- export default UserForm;