@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
@@ -4,6 +4,6 @@ import { useConfig } from '../../../config';
4
4
  import Groups from '../../../components/groups/Groups';
5
5
  const GroupsPage = () => {
6
6
  const config = useConfig();
7
- return <Groups apiUrl={config.generalProperties.apiURL}/>;
7
+ return React.createElement(Groups, { apiUrl: config.generalProperties.apiURL });
8
8
  };
9
9
  export default GroupsPage;
@@ -18,8 +18,7 @@ export default function RootLayout({ children, }) {
18
18
  },
19
19
  },
20
20
  });
21
- return (<QueryClientProvider client={queryClient}>
22
- <PageProvider>{children}</PageProvider>
23
- <ReactQueryDevtools initialIsOpen={false} buttonPosition='bottom-right'/>
24
- </QueryClientProvider>);
21
+ return (React.createElement(QueryClientProvider, { client: queryClient },
22
+ React.createElement(PageProvider, null, children),
23
+ React.createElement(ReactQueryDevtools, { initialIsOpen: false, buttonPosition: 'bottom-right' })));
25
24
  }
@@ -4,6 +4,6 @@ import { useConfig } from '../../../config';
4
4
  import Users from '../../../components/users/Users';
5
5
  const UsersPage = () => {
6
6
  const config = useConfig();
7
- return <Users apiUrl={config.generalProperties.apiURL}/>;
7
+ return React.createElement(Users, { apiUrl: config.generalProperties.apiURL, editUsername: true });
8
8
  };
9
9
  export default UsersPage;
@@ -6,7 +6,7 @@ import '@fontsource/raleway/600.css';
6
6
  import '@fontsource/raleway/700.css';
7
7
  import { ConfigProvider } from '../config';
8
8
  export const metadata = {
9
- title: 'Rossini Authentication',
9
+ title: 'Rossini Identity Management',
10
10
  };
11
11
  export default function RootLayout({ children, }) {
12
12
  const publicRuntimeEnv = {
@@ -14,11 +14,7 @@ export default function RootLayout({ children, }) {
14
14
  LOGOUT_URL: process.env.LOGOUT_URL || '',
15
15
  ACCOUNT_SETTINGS_URL: process.env.ACCOUNT_SETTINGS_URL || '',
16
16
  };
17
- return (<html lang='en'>
18
- <body>
19
- <ConfigProvider publicRuntimeEnv={publicRuntimeEnv}>
20
- {children}
21
- </ConfigProvider>
22
- </body>
23
- </html>);
17
+ return (React.createElement("html", { lang: 'en' },
18
+ React.createElement("body", null,
19
+ React.createElement(ConfigProvider, { publicRuntimeEnv: publicRuntimeEnv }, children))));
24
20
  }
@@ -0,0 +1,45 @@
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 (React.createElement(Dialog, { open: open, fullWidth: true, maxWidth: 'sm', onClose: onClose },
29
+ React.createElement(DialogTitle, null, title[locale]),
30
+ React.createElement(DialogContent, null,
31
+ React.createElement(Autocomplete
32
+ // multiple
33
+ , {
34
+ // multiple
35
+ options: options ?? [], getOptionLabel: (option) => option.label, getOptionKey: (option) => option.value, isOptionEqualToValue: (option, value) => option.value === value.value, renderInput: (params) => (React.createElement(TextField, { ...params, label: translations.search[locale], placeholder: '' })), onChange: (event, newValue) => {
36
+ setValue(newValue);
37
+ }, value: value })),
38
+ React.createElement(DialogActions, null,
39
+ React.createElement(Button, { size: 'small', variant: 'outlined', onClick: onClose }, translations.cancel[locale]),
40
+ React.createElement(Button, { variant: 'contained', onClick: () => {
41
+ onConfirm(value);
42
+ onClose();
43
+ } }, translations.ok[locale]))));
44
+ };
45
+ export default AddItemDialog;
@@ -0,0 +1,35 @@
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 (React.createElement(Dialog, { open: open, fullWidth: true, maxWidth: 'sm', onClose: onClose },
25
+ React.createElement(DialogTitle, null, translations.title[locale]),
26
+ React.createElement(DialogContent, null,
27
+ React.createElement(Typography, { variant: 'caption' }, translations.message[locale])),
28
+ React.createElement(DialogActions, null,
29
+ React.createElement(Button, { size: 'small', variant: 'outlined', onClick: onClose }, translations.no[locale]),
30
+ React.createElement(Button, { size: 'small', variant: 'contained', onClick: () => {
31
+ onConfirm();
32
+ onClose();
33
+ } }, translations.yes[locale]))));
34
+ };
35
+ export default DeleteConfirmationDialog;
@@ -0,0 +1,16 @@
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 (React.createElement(React.Fragment, null,
8
+ React.createElement(TextField, { size: 'small', placeholder: placeholder, value: value, onChange: (evt) => {
9
+ setValue(evt.target.value);
10
+ onSearch(evt.target.value);
11
+ }, ...props, InputProps: {
12
+ endAdornment: (React.createElement(IconButton, { size: 'small', onClick: () => onSearch(value) },
13
+ React.createElement(SearchIcon, null))),
14
+ } })));
15
+ };
16
+ export default SearchField;
@@ -1,8 +1,10 @@
1
1
  import React from 'react';
2
+ import { Group } from '../../types/groups';
2
3
  export interface CreateGroupDialogProps {
3
4
  open: boolean;
4
5
  onClose: () => void;
6
+ onGroupCreate?: (newGroup: Group) => void;
5
7
  }
6
- declare const CreateGroupDialog: ({ open, onClose }: CreateGroupDialogProps) => React.JSX.Element;
8
+ declare const CreateGroupDialog: ({ open, onClose, onGroupCreate, }: CreateGroupDialogProps) => React.JSX.Element;
7
9
  export default CreateGroupDialog;
8
10
  //# sourceMappingURL=CreateGroupDialog.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CreateGroupDialog.d.ts","sourceRoot":"","sources":["../../../src/components/groups/CreateGroupDialog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAW1B,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,QAAA,MAAM,iBAAiB,sBAAuB,sBAAsB,sBAoBnE,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
1
+ {"version":3,"file":"CreateGroupDialog.d.ts","sourceRoot":"","sources":["../../../src/components/groups/CreateGroupDialog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAM1B,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAK3C,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,KAAK,IAAI,CAAC;CAC3C;AAED,QAAA,MAAM,iBAAiB,sCAIpB,sBAAsB,sBAuBxB,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
@@ -6,20 +6,21 @@ import groupsTranslations from '../../lang/groups';
6
6
  import { useAddGroup } from '../../utils/hooks/groups';
7
7
  import GroupForm from './GroupForm';
8
8
  import { useAPIClient } from '../../utils/hooks/useAPIClient';
9
- const CreateGroupDialog = ({ open, onClose }) => {
9
+ const CreateGroupDialog = ({ open, onClose, onGroupCreate, }) => {
10
10
  const locale = useLocale();
11
11
  const apiClient = useAPIClient();
12
12
  const queryClient = useQueryClient();
13
13
  const { mutate: addGroup } = useAddGroup(queryClient, apiClient);
14
14
  const handleSave = (group) => {
15
15
  addGroup(group);
16
+ if (typeof onGroupCreate === 'function') {
17
+ onGroupCreate(group);
18
+ }
16
19
  onClose();
17
20
  };
18
- return (<Dialog open={open} fullWidth maxWidth='sm' onClose={onClose}>
19
- <DialogTitle>{groupsTranslations.create[locale]}</DialogTitle>
20
- <DialogContent>
21
- <GroupForm 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, groupsTranslations.create[locale]),
23
+ React.createElement(DialogContent, null,
24
+ React.createElement(GroupForm, { mode: 'create', onSave: handleSave, onCancel: onClose }))));
24
25
  };
25
26
  export default CreateGroupDialog;
@@ -2,7 +2,9 @@ import React from 'react';
2
2
  import { Group } from '../../types/groups';
3
3
  export interface GroupDetailsProps {
4
4
  group: Group;
5
+ onGroupUpdate?: (newGroup: Group, oldGroup: Group) => void;
6
+ editName?: boolean;
5
7
  }
6
- declare const GroupDetails: ({ group }: GroupDetailsProps) => React.JSX.Element;
8
+ declare const GroupDetails: ({ group, onGroupUpdate, editName, }: GroupDetailsProps) => React.JSX.Element;
7
9
  export default GroupDetails;
8
10
  //# sourceMappingURL=GroupDetails.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"GroupDetails.d.ts","sourceRoot":"","sources":["../../../src/components/groups/GroupDetails.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAK3C,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,KAAK,CAAC;CACd;AAED,QAAA,MAAM,YAAY,cAAe,iBAAiB,sBAmBjD,CAAC;AAEF,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"GroupDetails.d.ts","sourceRoot":"","sources":["../../../src/components/groups/GroupDetails.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAK3C,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,KAAK,CAAC;IACb,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,KAAK,IAAI,CAAC;IAC3D,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,QAAA,MAAM,YAAY,wCAIf,iBAAiB,sBAuBnB,CAAC;AAEF,eAAe,YAAY,CAAC"}
@@ -0,0 +1,19 @@
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, onGroupUpdate, editName, }) => {
7
+ const apiClient = useAPIClient();
8
+ const queryClient = useQueryClient();
9
+ const { mutate: updateGroup } = useUpdateGroup(queryClient, apiClient);
10
+ const handleUpdate = (updatedGroup) => {
11
+ updateGroup(updatedGroup);
12
+ if (typeof onGroupUpdate === 'function') {
13
+ onGroupUpdate(updatedGroup, group);
14
+ }
15
+ };
16
+ return (React.createElement(React.Fragment, null,
17
+ React.createElement(GroupForm, { mode: 'modify', group: group, onSave: handleUpdate, onCancel: () => { }, editName: editName })));
18
+ };
19
+ export default GroupDetails;
@@ -5,7 +5,8 @@ export interface GroupFormProps {
5
5
  onSave: (group: Group) => void;
6
6
  group?: Group;
7
7
  mode: 'create' | 'modify';
8
+ editName?: boolean;
8
9
  }
9
- declare const GroupForm: ({ group, onCancel, onSave, mode }: GroupFormProps) => React.JSX.Element;
10
+ declare const GroupForm: ({ group, onCancel, onSave, mode, editName, }: GroupFormProps) => React.JSX.Element;
10
11
  export default GroupForm;
11
12
  //# sourceMappingURL=GroupForm.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"GroupForm.d.ts","sourceRoot":"","sources":["../../../src/components/groups/GroupForm.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAQ1B,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAC/B,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAC;CAC3B;AAED,QAAA,MAAM,SAAS,sCAAuC,cAAc,sBAkEnE,CAAC;AAEF,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"GroupForm.d.ts","sourceRoot":"","sources":["../../../src/components/groups/GroupForm.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAQ1B,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAC/B,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,QAAA,MAAM,SAAS,iDAMZ,cAAc,sBAmEhB,CAAC;AAEF,eAAe,SAAS,CAAC"}
@@ -0,0 +1,38 @@
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, editName, }) => {
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 (React.createElement("form", { onSubmit: (event) => void handleSubmit(onSubmit)(event) },
25
+ React.createElement(Grid, { container: true, spacing: 2, sx: { mt: 2, maxWidth: 'sm' }, justifyContent: 'stretch' },
26
+ React.createElement(Grid, { item: true, xs: 12 },
27
+ React.createElement(Controller, { name: 'name', control: control, render: ({ field }) => (React.createElement(TextField, { size: 'small', fullWidth: true, label: groupsTranslations.name[locale], disabled: mode === 'modify' && !editName, sx: { flexShrink: 0 }, ...field })) })),
28
+ React.createElement(Grid, { item: true, sx: {
29
+ mt: 2,
30
+ display: 'flex',
31
+ justifyContent: 'flex-end',
32
+ gap: 2,
33
+ width: '100%',
34
+ } },
35
+ mode === 'create' && (React.createElement(Button, { variant: 'outlined', onClick: onCancel }, groupsTranslations.cancel[locale])),
36
+ React.createElement(Button, { variant: 'contained', type: 'submit' }, groupsTranslations.save[locale])))));
37
+ };
38
+ export default GroupForm;
@@ -10,7 +10,9 @@ export interface GroupTab {
10
10
  export interface GroupTabsProps {
11
11
  group: Group;
12
12
  additionalTabs?: GroupTab[];
13
+ onGroupUpdate?: (newGroup: Group, oldGroup: Group) => void;
14
+ editName?: boolean;
13
15
  }
14
- declare const GroupTabs: ({ group, additionalTabs }: GroupTabsProps) => React.JSX.Element;
16
+ declare const GroupTabs: ({ group, additionalTabs, onGroupUpdate, editName, }: GroupTabsProps) => React.JSX.Element;
15
17
  export default GroupTabs;
16
18
  //# sourceMappingURL=GroupTabs.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"GroupTabs.d.ts","sourceRoot":"","sources":["../../../src/components/groups/GroupTabs.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAGxC,OAAO,EAAE,iBAAiB,EAAa,MAAM,oBAAoB,CAAC;AAClE,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAK3C,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,iBAAiB,CAAC;IACzB,SAAS,EAAE,KAAK,CAAC,iBAAiB,CAAC;QAAE,KAAK,EAAE,KAAK,CAAA;KAAE,CAAC,CAAC;CACtD;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,KAAK,CAAC;IACb,cAAc,CAAC,EAAE,QAAQ,EAAE,CAAC;CAC7B;AAED,QAAA,MAAM,SAAS,8BAAoC,cAAc,sBA4ChE,CAAC;AAEF,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"GroupTabs.d.ts","sourceRoot":"","sources":["../../../src/components/groups/GroupTabs.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAGxC,OAAO,EAAE,iBAAiB,EAAa,MAAM,oBAAoB,CAAC;AAClE,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAK3C,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,iBAAiB,CAAC;IACzB,SAAS,EAAE,KAAK,CAAC,iBAAiB,CAAC;QAAE,KAAK,EAAE,KAAK,CAAA;KAAE,CAAC,CAAC;CACtD;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,KAAK,CAAC;IACb,cAAc,CAAC,EAAE,QAAQ,EAAE,CAAC;IAC5B,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,KAAK,IAAI,CAAC;IAC3D,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,QAAA,MAAM,SAAS,wDAKZ,cAAc,sBAkDhB,CAAC;AAEF,eAAe,SAAS,CAAC"}
@@ -0,0 +1,29 @@
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 = [], onGroupUpdate, editName, }) => {
9
+ const locale = useLocale();
10
+ const [selectedTab, setSelectedTab] = useState('DETAILS');
11
+ return (React.createElement(Box, { sx: {
12
+ flexGrow: 1,
13
+ maxWidth: '100%',
14
+ overflowX: 'hidden',
15
+ alignSelf: 'stretch',
16
+ } },
17
+ React.createElement(Box, { sx: { borderBottom: 1, borderColor: 'divider' } },
18
+ React.createElement(Tabs, { value: selectedTab, onChange: (_evt, newValue) => {
19
+ setSelectedTab(newValue);
20
+ }, "aria-label": 'basic tabs example' },
21
+ React.createElement(Tab, { label: groupsTranslations.details[locale], value: 'DETAILS' }),
22
+ React.createElement(Tab, { label: groupsTranslations.users[locale], value: 'USERS' }),
23
+ additionalTabs.map((tab, index) => (React.createElement(Tab, { key: `tab${index}`, label: tab.title[locale], value: `ADDITIONAL_TAB_${index}` }))))),
24
+ React.createElement(Box, { sx: { p: 1 } },
25
+ selectedTab === 'DETAILS' && (React.createElement(GroupDetails, { group: group, onGroupUpdate: onGroupUpdate, editName: editName })),
26
+ selectedTab === 'USERS' && React.createElement(GroupUsers, { group: group }),
27
+ additionalTabs.map((tab, index) => selectedTab === `ADDITIONAL_TAB_${index}` && (React.createElement(tab.component, { key: `tab${index}`, group: group }))))));
28
+ };
29
+ export default GroupTabs;
@@ -0,0 +1,73 @@
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 (React.createElement(React.Fragment, null,
40
+ groupUsers && groupUsers.length > 0 && (React.createElement(Box, { maxWidth: 'md' },
41
+ React.createElement(TableContainer, null,
42
+ React.createElement(Table, { size: 'small' },
43
+ React.createElement(TableHead, null,
44
+ React.createElement(TableRow, null,
45
+ groupUsersTableColumns.map((col) => (React.createElement(TableCell, { key: col.id, align: col.align || 'inherit' }, isStringTranslation(col.label)
46
+ ? col.label[locale]
47
+ : col.label))),
48
+ React.createElement(TableCell, { padding: 'none' }, ''))),
49
+ React.createElement(TableBody, null, groupUsers?.map((user, rowIdx) => (React.createElement(TableRow, { key: rowIdx },
50
+ React.createElement(TableCell, null, user.username),
51
+ React.createElement(TableCell, null, user.firstName),
52
+ React.createElement(TableCell, null, user.lastName),
53
+ React.createElement(TableCell, { padding: 'none', align: 'right' },
54
+ React.createElement(IconButton, { size: 'small', onClick: (evt) => {
55
+ evt.stopPropagation();
56
+ setOpenConfirmationDialog(true);
57
+ setDeleteId(user.id);
58
+ } },
59
+ React.createElement(DeleteIcon, null))))))))))),
60
+ React.createElement(Button, { variant: 'outlined', startIcon: React.createElement(AddIcon, null), onClick: () => setOpenAddUserDialog(true), sx: { marginTop: 2 } }, groupsTranslations.addUser[locale]),
61
+ React.createElement(AddItemDialog, { open: openAddUserDialog, onClose: () => setOpenAddUserDialog(false), onConfirm: (value) => {
62
+ if (value) {
63
+ addUserToGroup({ userId: value?.value, groupId: group.id });
64
+ }
65
+ }, title: groupsTranslations.addUser, options: users?.map((user) => ({
66
+ value: user.id,
67
+ label: user.username || '',
68
+ })) }),
69
+ React.createElement(DeleteConfirmationDialog, { open: openConfirmationDialog, onClose: () => setOpenConfirmationDialog(false), onConfirm: () => deleteId
70
+ ? removeUserFromGroup({ userId: deleteId, groupId: group.id })
71
+ : {} })));
72
+ };
73
+ export default GroupUsers;
@@ -1,9 +1,14 @@
1
1
  import React from 'react';
2
+ import { Group } from '../../types/groups';
2
3
  import { GroupTab } from './GroupTabs';
3
4
  interface GroupsProps {
4
5
  apiUrl: string;
5
6
  additionalTabs?: GroupTab[];
7
+ onGroupUpdate?: (newGroup: Group, oldGroup: Group) => void;
8
+ onGroupCreate?: (newGroup: Group) => void;
9
+ onGroupDelete?: (group: Group) => void;
10
+ editName?: boolean;
6
11
  }
7
- declare const Groups: ({ apiUrl, additionalTabs }: GroupsProps) => React.JSX.Element;
12
+ declare const Groups: ({ apiUrl, additionalTabs, onGroupUpdate, onGroupCreate, onGroupDelete, editName, }: GroupsProps) => React.JSX.Element;
8
13
  export default Groups;
9
14
  //# sourceMappingURL=Groups.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Groups.d.ts","sourceRoot":"","sources":["../../../src/components/groups/Groups.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAanD,OAAkB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAIlD,UAAU,WAAW;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,QAAQ,EAAE,CAAC;CAC7B;AAED,QAAA,MAAM,MAAM,+BAAqC,WAAW,sBAuH3D,CAAC;AAEF,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"Groups.d.ts","sourceRoot":"","sources":["../../../src/components/groups/Groups.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAWnD,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,OAAkB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAIlD,UAAU,WAAW;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,QAAQ,EAAE,CAAC;IAE5B,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,KAAK,IAAI,CAAC;IAE3D,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,KAAK,IAAI,CAAC;IAE1C,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAEvC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,QAAA,MAAM,MAAM,uFAOT,WAAW,sBAgIb,CAAC;AAEF,eAAe,MAAM,CAAC"}
@@ -0,0 +1,83 @@
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 = [], onGroupUpdate, onGroupCreate, onGroupDelete, editName, }) => {
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 = (group) => {
35
+ deleteGroup(group.id);
36
+ if (typeof onGroupDelete === 'function') {
37
+ onGroupDelete(group);
38
+ }
39
+ setSelectedGroup(undefined);
40
+ };
41
+ return (React.createElement(APIClientProvider, { baseURL: apiUrl },
42
+ React.createElement(Box, { sx: {
43
+ flexGrow: 1,
44
+ maxWidth: '100%',
45
+ overflowX: 'hidden',
46
+ paddingTop: 3,
47
+ paddingLeft: 3,
48
+ paddingRight: 3,
49
+ } },
50
+ !selectedGroup && (React.createElement(React.Fragment, null,
51
+ React.createElement(Grid, { container: true, spacing: 2, sx: { marginBottom: 2 } },
52
+ React.createElement(Grid, { item: true },
53
+ React.createElement(SearchField, { placeholder: groupsTranslations.search[locale], onSearch: (value) => setSearchString(value) })),
54
+ React.createElement(Grid, { item: true },
55
+ React.createElement(Button, { variant: 'contained', startIcon: React.createElement(GroupAddIcon, null), onClick: () => {
56
+ setOpenGroupDialog(true);
57
+ setSelectedGroup(undefined);
58
+ } }, groupsTranslations.new[locale]))),
59
+ React.createElement(GroupsTable, { groups: filteredGroups, selectedGroup: selectedGroup, setSelectedGroup: (group) => {
60
+ setSelectedGroup(group);
61
+ }, onDelete: handleDelete }))),
62
+ selectedGroup && (React.createElement(Box, { sx: {
63
+ display: 'flex',
64
+ flexDirection: 'column',
65
+ alignItems: 'flex-start',
66
+ width: '100%',
67
+ } },
68
+ React.createElement(Box, { sx: {
69
+ display: 'flex',
70
+ flexDirection: 'row',
71
+ alignItems: 'center',
72
+ } },
73
+ React.createElement(IconButton, { "aria-label": 'delete', color: 'primary', onClick: () => setSelectedGroup(undefined), sx: { mr: 2 } },
74
+ React.createElement(ArrowBackIcon, null)),
75
+ React.createElement(Link, { underline: 'none', href: '#', onClick: () => setSelectedGroup(undefined) }, groupsTranslations.title[locale]),
76
+ React.createElement(KeyboardArrowRightIcon, null),
77
+ selectedGroup.name),
78
+ React.createElement(GroupTabs, { group: selectedGroup, additionalTabs: additionalTabs, onGroupUpdate: onGroupUpdate, editName: editName }))),
79
+ React.createElement(CreateGroupDialog, { open: openGroupDialog, onClose: () => {
80
+ setOpenGroupDialog(false);
81
+ }, onGroupCreate: onGroupCreate }))));
82
+ };
83
+ export default Groups;
@@ -4,7 +4,7 @@ export interface TableProps {
4
4
  groups?: Group[];
5
5
  selectedGroup?: Group;
6
6
  setSelectedGroup: (group: Group) => void;
7
- onDelete: (id: string) => void;
7
+ onDelete: (group: Group) => void;
8
8
  }
9
9
  declare const GroupsTable: ({ groups, selectedGroup, setSelectedGroup, onDelete, }: TableProps) => React.JSX.Element;
10
10
  export default GroupsTable;
@@ -1 +1 @@
1
- {"version":3,"file":"GroupsTable.d.ts","sourceRoot":"","sources":["../../../src/components/groups/GroupsTable.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAe1B,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAW3C,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;IACjB,aAAa,CAAC,EAAE,KAAK,CAAC;IACtB,gBAAgB,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACzC,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CAChC;AAED,QAAA,MAAM,WAAW,2DAKd,UAAU,sBA8DZ,CAAC;AAEF,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"GroupsTable.d.ts","sourceRoot":"","sources":["../../../src/components/groups/GroupsTable.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAe1B,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAW3C,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;IACjB,aAAa,CAAC,EAAE,KAAK,CAAC;IACtB,gBAAgB,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACzC,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAED,QAAA,MAAM,WAAW,2DAKd,UAAU,sBA8DZ,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -0,0 +1,43 @@
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 [deleteGroup, setDeleteGroup] = useState();
18
+ return (React.createElement(React.Fragment, null,
19
+ React.createElement(TableContainer, null,
20
+ React.createElement(Table, { size: 'small' },
21
+ React.createElement(TableHead, null,
22
+ React.createElement(TableRow, null,
23
+ groupsTableColumns.map((col) => (React.createElement(TableCell, { key: col.id, align: col.align || 'inherit' }, isStringTranslation(col.label)
24
+ ? col.label[locale]
25
+ : col.label))),
26
+ React.createElement(TableCell, { padding: 'none' }, ''))),
27
+ React.createElement(TableBody, null, groups.map((group, rowIdx) => (React.createElement(TableRow, { key: rowIdx, onClick: () => setSelectedGroup(group), sx: {
28
+ cursor: 'pointer',
29
+ background: selectedGroup && group.id === selectedGroup.id
30
+ ? muiTheme.palette.primary.light
31
+ : undefined,
32
+ } },
33
+ React.createElement(TableCell, null, group.name),
34
+ React.createElement(TableCell, { padding: 'none', align: 'right' },
35
+ React.createElement(IconButton, { size: 'small', onClick: (evt) => {
36
+ evt.stopPropagation();
37
+ setOpenConfirmationDialog(true);
38
+ setDeleteGroup(group);
39
+ } },
40
+ React.createElement(DeleteIcon, null))))))))),
41
+ React.createElement(DeleteConfirmationDialog, { open: openConfirmationDialog, onClose: () => setOpenConfirmationDialog(false), onConfirm: () => (deleteGroup ? onDelete(deleteGroup) : {}) })));
42
+ };
43
+ export default GroupsTable;
@@ -1,8 +1,10 @@
1
1
  import React from 'react';
2
+ import { User } from '../../types/users';
2
3
  export interface CreateUserDialogProps {
3
4
  open: boolean;
4
5
  onClose: () => void;
6
+ onUserCreate?: (newUser: User) => void;
5
7
  }
6
- declare const CreateUserDialog: ({ open, onClose }: CreateUserDialogProps) => React.JSX.Element;
8
+ declare const CreateUserDialog: ({ open, onClose, onUserCreate, }: CreateUserDialogProps) => React.JSX.Element;
7
9
  export default CreateUserDialog;
8
10
  //# sourceMappingURL=CreateUserDialog.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CreateUserDialog.d.ts","sourceRoot":"","sources":["../../../src/components/users/CreateUserDialog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAS1B,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,QAAA,MAAM,gBAAgB,sBAAuB,qBAAqB,sBAoBjE,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
1
+ {"version":3,"file":"CreateUserDialog.d.ts","sourceRoot":"","sources":["../../../src/components/users/CreateUserDialog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAQ1B,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEzC,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,KAAK,IAAI,CAAC;CACxC;AAED,QAAA,MAAM,gBAAgB,qCAInB,qBAAqB,sBAuBvB,CAAC;AAEF,eAAe,gBAAgB,CAAC"}