@iotready/nextjs-components-library 1.0.0-preview31 → 1.0.0-preview33

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.
@@ -1,5 +1,5 @@
1
1
  import { AssetType, TrackleDeviceType, UserType } from '../../types';
2
- declare const GroupUpdate: ({ groupInfo, usersGroup, usersList, devicesList, handleAddUserToGroup, handleRemoveUserFromGroup, handleUpdateGroup, handleDeleteGroup, container, containerProps, afterUpdateCallback, afterRemoveCallback, confirmMui }: {
2
+ declare const GroupUpdate: ({ labelEntity, groupInfo, usersGroup, usersList, devicesList, handleAddUserToGroup, handleRemoveUserFromGroup, handleUpdateGroup, handleDeleteGroup, container, containerProps, afterUpdateCallback, afterRemoveCallback, confirmMui }: {
3
3
  userInfo: UserType;
4
4
  groupInfo: any;
5
5
  usersGroup: any[];
@@ -16,5 +16,6 @@ declare const GroupUpdate: ({ groupInfo, usersGroup, usersList, devicesList, han
16
16
  afterUpdateCallback?: (groupInfo: any) => Promise<void>;
17
17
  afterRemoveCallback?: () => Promise<void>;
18
18
  confirmMui?: (options?: any) => Promise<void>;
19
+ labelEntity: string;
19
20
  }) => import("react/jsx-runtime").JSX.Element;
20
21
  export default GroupUpdate;
@@ -8,7 +8,7 @@ import AddIcon from '@mui/icons-material/Add';
8
8
  import CloseIcon from '@mui/icons-material/Close';
9
9
  import DeleteIcon from '@mui/icons-material/Delete';
10
10
  import { LoadingButton } from '@mui/lab';
11
- const GroupUpdate = ({ groupInfo, usersGroup, usersList, devicesList, handleAddUserToGroup, handleRemoveUserFromGroup, handleUpdateGroup, handleDeleteGroup, container = 'Box', containerProps = {}, afterUpdateCallback, afterRemoveCallback, confirmMui }) => {
11
+ const GroupUpdate = ({ labelEntity, groupInfo, usersGroup, usersList, devicesList, handleAddUserToGroup, handleRemoveUserFromGroup, handleUpdateGroup, handleDeleteGroup, container = 'Box', containerProps = {}, afterUpdateCallback, afterRemoveCallback, confirmMui }) => {
12
12
  const [group, setGroup] = useState(groupInfo);
13
13
  const [loadingUpdateButton, setLoadingUpdateButton] = useState(false);
14
14
  const [loadingRemoveUserButton, setLoadingRemoveUserButton] = useState(false);
@@ -97,7 +97,7 @@ const GroupUpdate = ({ groupInfo, usersGroup, usersList, devicesList, handleAddU
97
97
  _jsx(Table, { size: "small", children: _jsx(TableBody, { children: usersGroup.map((ug) => (_jsxs(TableRow, { children: [_jsx(TableCell, { children: _jsx(Typography, { variant: "body1", children: ug.user.fullName }) }), _jsx(TableCell, { align: 'right', children: _jsx(LoadingButton, { size: "small", color: "error", loading: loadingRemoveUserButton, onClick: () => removeUserFromCurrentGroup(ug.user.userId), children: _jsx(CloseIcon, { sx: { m: 0, p: 0 }, fontSize: "small" }) }) })] }, ug.id))) }) })
98
98
  : _jsx(Box, { component: 'div', sx: { mt: 2 }, children: "No members found" }) }), _jsxs(Box, { component: "div", sx: { mt: 4, display: 'flex', alignItems: 'center' }, children: [_jsx(Autocomplete, { fullWidth: true, disablePortal: true, options: usersList || [], value: selectedUser, size: 'small', onChange: (event, newValue) => {
99
99
  setSelectedUser(newValue);
100
- }, renderInput: (params) => _jsx(TextField, { ...params, label: "Select user" }) }), _jsxs(LoadingButton, { variant: "contained", color: "success", loading: loadingAddUserButton, sx: { ml: 2 }, disabled: !selectedUser, onClick: () => addUserToCurrentGroup(), children: [_jsx(AddIcon, { sx: { mr: 1 } }), " Add"] })] }), _jsxs(Box, { component: "div", sx: { mt: 4 }, children: [_jsx(Typography, { variant: 'body1', sx: { fontWeight: 'bold' }, children: "Delete group" }), _jsx(Alert, { severity: "error", sx: { mt: 2 }, action: _jsxs(LoadingButton, { variant: "contained", disabled: devicesList.length > 0, color: "error", loading: loadingDeleteGroupButton, onClick: () => deleteGroup(), size: 'small', children: [_jsx(DeleteIcon, { fontSize: "small", sx: { mr: 1 } }), " Delete"] }), children: devicesList.length === 0 ? 'This action cannot be undone' : 'You must manually remove devices from group before deletion' })] })] }) })] }));
100
+ }, renderInput: (params) => _jsx(TextField, { ...params, label: "Select user" }) }), _jsxs(LoadingButton, { variant: "contained", color: "success", loading: loadingAddUserButton, sx: { ml: 2 }, disabled: !selectedUser, onClick: () => addUserToCurrentGroup(), children: [_jsx(AddIcon, { sx: { mr: 1 } }), " Add"] })] }), _jsxs(Box, { component: "div", sx: { mt: 4 }, children: [_jsxs(Typography, { variant: 'body1', sx: { fontWeight: 'bold' }, children: ["Delete ", labelEntity.toLocaleLowerCase()] }), _jsx(Alert, { severity: "error", sx: { mt: 2 }, action: _jsxs(LoadingButton, { variant: "contained", disabled: devicesList.length > 0, color: "error", loading: loadingDeleteGroupButton, onClick: () => deleteGroup(), size: 'small', children: [_jsx(DeleteIcon, { fontSize: "small", sx: { mr: 1 } }), " Delete"] }), children: devicesList.length === 0 ? `This action cannot be undone` : `You must manually remove devices from ${labelEntity.toLocaleLowerCase()} before deletion` })] })] }) })] }));
101
101
  };
102
102
  return (container === "Card" ? (_jsx(Card, { ...containerProps, children: _jsx(CardContent, { children: renderGroupUpdate() }) })) : (_jsx(Box, { ...containerProps, children: renderGroupUpdate() })));
103
103
  };
@@ -1,6 +1,6 @@
1
1
  import { Theme } from "@emotion/react";
2
2
  import { UserType, AssetType, DevicePositionType, TrackleDeviceType } from "../../types";
3
- declare const GroupsDevices: ({ userInfo, handleGetUsersList, handleAddUserToGroup, handleRemoveUserFromGroup, handleGetGroups, handleGetUsersGroup, handleGetDevices, handleUpdateDevice, handleGetPositions, handleAddDevicesToGroup, handleRemoveDevicesFromGroup, handleCreateGroup, handleDeleteGroup, handleUpdateGroup, group, columnsArray, containerDataGrid, props, propsDatagrid, loadingComponent, containerProps, enableMaps, mapsHeight, mapsClickCallback, theme, confirmMui, propsHeaderGroups, forceGetDevices, customToolbar, groupsLabelAll, addDevicesLabel, groupUpdateRoles }: {
3
+ declare const GroupsDevices: ({ userInfo, handleGetUsersList, handleAddUserToGroup, handleRemoveUserFromGroup, handleGetGroups, handleGetUsersGroup, handleGetDevices, handleUpdateDevice, handleGetPositions, handleAddDevicesToGroup, handleRemoveDevicesFromGroup, handleCreateGroup, handleDeleteGroup, handleUpdateGroup, group, columnsArray, containerDataGrid, props, propsDatagrid, loadingComponent, containerProps, enableMaps, mapsHeight, mapsClickCallback, theme, confirmMui, propsHeaderGroups, forceGetDevices, customToolbar, groupsLabelAll, addDevicesLabel, noDevicesLabel, groupUpdateRoles, isOrg, currentOrg, userGroupsRole }: {
4
4
  userInfo: UserType;
5
5
  handleGetUsersList: ({ page, pageSize }: {
6
6
  page: number;
@@ -22,6 +22,7 @@ declare const GroupsDevices: ({ userInfo, handleGetUsersList, handleAddUserToGro
22
22
  handleUpdateDevice: (id: string, body: any, user: UserType) => Promise<void>;
23
23
  group: string;
24
24
  columnsArray: any[];
25
+ userGroupsRole?: string[];
25
26
  containerDataGrid?: "Card" | "Box";
26
27
  props?: any;
27
28
  propsDatagrid?: any;
@@ -37,6 +38,9 @@ declare const GroupsDevices: ({ userInfo, handleGetUsersList, handleAddUserToGro
37
38
  customToolbar?: string[];
38
39
  groupsLabelAll?: string;
39
40
  addDevicesLabel?: string;
41
+ noDevicesLabel?: string;
40
42
  groupUpdateRoles?: string[];
43
+ isOrg?: boolean;
44
+ currentOrg?: string;
41
45
  }) => string | number | bigint | boolean | import("react/jsx-runtime").JSX.Element | Iterable<import("react").ReactNode> | Promise<import("react").AwaitedReactNode> | null;
42
46
  export default GroupsDevices;
@@ -15,13 +15,13 @@ import GroupUpdate from "./GroupUpdate";
15
15
  import BackIcon from '@mui/icons-material/ArrowBack';
16
16
  import dynamic from "next/dynamic";
17
17
  import { ThemeProvider } from '@mui/material/styles';
18
- const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, handleRemoveUserFromGroup, handleGetGroups, handleGetUsersGroup, handleGetDevices, handleUpdateDevice, handleGetPositions, handleAddDevicesToGroup, handleRemoveDevicesFromGroup, handleCreateGroup, handleDeleteGroup, handleUpdateGroup, group = 'all', columnsArray = [], containerDataGrid = 'Card', props = {}, propsDatagrid = {}, loadingComponent = _jsx(CircularProgress, {}), containerProps = {}, enableMaps = true, mapsHeight = '400px', mapsClickCallback = () => { }, theme, confirmMui, propsHeaderGroups, forceGetDevices, customToolbar, groupsLabelAll, addDevicesLabel, groupUpdateRoles }) => {
18
+ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, handleRemoveUserFromGroup, handleGetGroups, handleGetUsersGroup, handleGetDevices, handleUpdateDevice, handleGetPositions, handleAddDevicesToGroup, handleRemoveDevicesFromGroup, handleCreateGroup, handleDeleteGroup, handleUpdateGroup, group = 'all', columnsArray = [], containerDataGrid = 'Card', props = {}, propsDatagrid = {}, loadingComponent = _jsx(CircularProgress, {}), containerProps = {}, enableMaps = true, mapsHeight = '400px', mapsClickCallback = () => { }, theme, confirmMui, propsHeaderGroups, forceGetDevices = 0, customToolbar, groupsLabelAll, addDevicesLabel, noDevicesLabel, groupUpdateRoles, isOrg = false, currentOrg, userGroupsRole = ['support'] }) => {
19
19
  const [devices, setDevices] = useState([]);
20
20
  const [positions, setPositions] = useState([]);
21
21
  const [loadingDevices, setLoadingDevices] = useState(false);
22
22
  const [loadingGroups, setLoadingGroups] = useState(false);
23
23
  const [loadingAdd, setLoadingAdd] = useState(false);
24
- const [editGroup, setEditGroup] = useState(false);
24
+ const [editGroup, setEditGroup] = useState(isOrg ? true : false);
25
25
  const [checkboxSelection, setCheckboxSelection] = useState(false);
26
26
  const [devicesToAdd, setDevicesToAdd] = useState([]);
27
27
  const [deviceSelectedObjs, setDeviceSelectedObjs] = useState([]);
@@ -37,6 +37,7 @@ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, han
37
37
  const [groupUpdateVisible, setGroupUpdateVisible] = useState(false);
38
38
  const [valueTab, setValueTab] = useState('1');
39
39
  const clickedIdRef = useRef(null);
40
+ const labelEntity = isOrg ? "Organization" : "Group";
40
41
  const handleChangeTab = (event, newValue) => {
41
42
  setValueTab(newValue);
42
43
  };
@@ -63,7 +64,10 @@ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, han
63
64
  page++;
64
65
  }
65
66
  const userGroupsUserIds = usersGroup && usersGroup.map((ug) => ug.user.userId) || [];
66
- setUsersList(usersData.filter((user) => user.role === 'support' && !userGroupsUserIds.includes(user.uid)).map((user) => {
67
+ setUsersList(usersData
68
+ .filter((user) => userGroupsRole.includes(user.role) &&
69
+ !userGroupsUserIds.includes(user.uid))
70
+ .map((user) => {
67
71
  const userName = user.name ? user.name.replace("/", " ") : "";
68
72
  return { label: `${userName} (${user.email})`, id: user.uid };
69
73
  }));
@@ -73,9 +77,16 @@ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, han
73
77
  }
74
78
  };
75
79
  const fetchDevices = async (group, selected) => {
80
+ let groupToUse = group;
81
+ if (currentOrg === 'all' && group === 'all' && selected !== 'all') {
82
+ groupToUse = groupInfo.parent_id;
83
+ }
84
+ else if (currentOrg != undefined && group === 'all') {
85
+ groupToUse = currentOrg;
86
+ }
76
87
  try {
77
88
  setLoadingDevices(true);
78
- const devices = await handleGetDevices(userInfo, group, selected);
89
+ const devices = await handleGetDevices(userInfo, groupToUse, selected);
79
90
  setDevices(devices);
80
91
  if (enableMaps && handleGetPositions) {
81
92
  const positions = await handleGetPositions(devices);
@@ -116,7 +127,7 @@ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, han
116
127
  getUsersList();
117
128
  }, [usersGroup]);
118
129
  useEffect(() => {
119
- if (currentGroup && !checkboxSelection) {
130
+ if (currentGroup && !checkboxSelection && groups !== null) {
120
131
  setSelectedGroup(currentGroup);
121
132
  setGroupInfo(groups && groups.find((g) => g.id === currentGroup));
122
133
  if (currentGroup !== 'all') {
@@ -124,7 +135,7 @@ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, han
124
135
  }
125
136
  fetchDevices(currentGroup, currentGroup);
126
137
  }
127
- }, [currentGroup]);
138
+ }, [currentGroup, groups]);
128
139
  useEffect(() => {
129
140
  if (forceGetDevices !== 0) {
130
141
  fetchDevices(currentGroup, currentGroup);
@@ -143,6 +154,7 @@ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, han
143
154
  setCurrentGroup(id);
144
155
  setGroupInfo({ ...newGroup, id });
145
156
  setSelectedGroup(id);
157
+ getUsersGroup(id);
146
158
  setDevicesToAdd([]), setEditGroup(!editGroup);
147
159
  setCheckboxSelection(!checkboxSelection);
148
160
  fetchDevices(id, id);
@@ -266,8 +278,8 @@ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, han
266
278
  ? columnsArray.filter(col => col.field !== 'id')
267
279
  : columnsArray, slots: {
268
280
  noRowsOverlay: () => (_jsx(Stack, { height: "100%", alignItems: "center", justifyContent: "center", children: currentGroup !== 'all'
269
- ? (_jsxs(_Fragment, { children: [_jsx(Box, { children: "No devices in group" }), editGroup && (_jsxs(Button, { onClick: addDevicesToCurrentGroup, variant: "outlined", color: "primary", size: "small", sx: { mt: 2 }, children: [_jsx(PlaylistAddIcon, { fontSize: "small", sx: { mr: 1 } }), addDevicesLabel || 'Add devices'] }))] }))
270
- : "No devices" })),
281
+ ? (_jsxs(_Fragment, { children: [_jsxs(Box, { children: [noDevicesLabel || 'No devices', " in ", labelEntity.toLocaleLowerCase()] }), editGroup && (_jsxs(Button, { onClick: addDevicesToCurrentGroup, variant: "outlined", color: "primary", size: "small", sx: { mt: 2 }, children: [_jsx(PlaylistAddIcon, { fontSize: "small", sx: { mr: 1 } }), addDevicesLabel || 'Add devices'] }))] }))
282
+ : noDevicesLabel || 'No devices' })),
271
283
  noResultsOverlay: () => (_jsx(Stack, { height: "100%", alignItems: "center", justifyContent: "center", children: "Filter returns no result" })),
272
284
  toolbar: customToolbar && customToolbar.length ? CustomToolbar : GridToolbar,
273
285
  }, slotProps: {
@@ -286,27 +298,27 @@ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, han
286
298
  _jsx(Card, { ...containerProps, children: renderDataGrid }) : _jsx(Box, { ...containerProps, children: renderDataGrid }));
287
299
  if (!userInfo || !groups || !devices)
288
300
  return loadingComponent;
289
- return (_jsx(ThemeProvider, { theme: theme, children: _jsxs(Box, { ...props, children: [_jsxs(Box, { component: "div", sx: { display: 'flex', alignItems: 'center', mb: 1, backgroundColor: editGroup ? 'secondary.light' : '', borderRadius: 3, px: editGroup ? 2 : 0, py: 1, height: 50, ...propsHeaderGroups }, children: [editGroup ? _jsxs(Typography, { variant: 'subtitle1', children: [_jsx(Box, { component: 'span', sx: { display: { xs: 'none' } }, children: "Edit group" }), " ", _jsx("b", { children: groupInfo?.name })] }) : '', groups && !checkboxSelection && !(editGroup && currentGroup === 'all') ?
290
- _jsx(Autocomplete, { disablePortal: true, onChange: handleChangeGroupSelect, value: groupInfo?.name || groupsLabelAll || 'All devices', disableClearable: currentGroup === 'all', isOptionEqualToValue: (o, v) => o.label === v, options: [{ label: groupsLabelAll || 'All devices', id: 'all' }, ...groups.map((grp) => ({ label: grp.name, id: grp.id }))], sx: { width: { xs: 200, sm: 300 }, textAlign: 'left' }, size: 'small', renderInput: (params) => _jsx(TextField, { ...params, label: "Group" }) })
291
- : '', userInfo.role === 'admin' || (groupUpdateRoles && groupUpdateRoles.includes(userInfo.role)) &&
301
+ return (_jsx(ThemeProvider, { theme: theme, children: _jsxs(Box, { ...props, children: [_jsxs(Box, { component: "div", sx: { display: 'flex', alignItems: 'center', mb: 1, backgroundColor: editGroup && !isOrg ? 'secondary.light' : '', borderRadius: 3, px: editGroup ? 2 : 0, py: 1, height: 50, ...propsHeaderGroups }, children: [editGroup ? _jsxs(Typography, { variant: 'subtitle1', children: [_jsxs(Box, { component: 'span', sx: { display: { xs: 'none' } }, children: ["Edit ", labelEntity.toLocaleLowerCase()] }), " ", _jsx("b", { children: groupInfo?.name })] }) : '', groups && !checkboxSelection && !isOrg && !(editGroup && currentGroup === 'all') ?
302
+ _jsx(Autocomplete, { disablePortal: true, onChange: handleChangeGroupSelect, value: groupInfo?.name || groupsLabelAll || 'All devices', disableClearable: currentGroup === 'all', isOptionEqualToValue: (o, v) => o.label === v, options: [{ label: groupsLabelAll || 'All devices', id: 'all' }, ...groups.map((grp) => ({ label: grp.name, id: grp.id }))], sx: { width: { xs: 200, sm: 300 }, textAlign: 'left' }, size: 'small', renderInput: (params) => _jsx(TextField, { ...params, label: labelEntity }) })
303
+ : '', (userInfo.role === 'admin' || (groupUpdateRoles && groupUpdateRoles.includes(userInfo.role))) &&
292
304
  _jsxs(Box, { sx: { ml: 2 }, children: [checkboxSelection ?
293
305
  _jsx(Input, { value: selectedGroup, type: 'hidden', size: 'small' })
294
- : '', selectedGroup === 'all' ? _jsxs(Button, { variant: "contained", color: "primary", onClick: () => { handleOpenAdd(); }, children: [_jsx(AddIcon, { sx: { mr: 1 } }), _jsx(Box, { component: 'span', sx: { display: { xs: 'none', sm: 'inline' } }, children: "Create\u00A0" }), " group"] }) : '', editGroup ?
306
+ : '', selectedGroup === 'all' && (currentOrg !== 'all') ? _jsxs(Button, { variant: "contained", color: "primary", onClick: () => { handleOpenAdd(); }, children: [_jsx(AddIcon, { sx: { mr: 1 } }), _jsx(Box, { component: 'span', sx: { display: { xs: 'none', sm: 'inline' } }, children: "Create\u00A0" }), " ", labelEntity.toLocaleLowerCase()] }) : '', editGroup ?
295
307
  currentGroup === 'all' ?
296
- checkboxSelection ? _jsxs(_Fragment, { children: [_jsxs(Button, { onClick: () => { setGroupUpdateVisible(false); setDevicesToAdd([]); setCurrentGroup(selectedGroup); setCheckboxSelection(true); fetchDevices(selectedGroup, selectedGroup); }, variant: "text", color: "inherit", size: "small", children: [_jsx(BackIcon, { fontSize: "small" }), _jsx(Box, { component: 'span', sx: { display: { xs: 'none', sm: 'inline' } }, children: "\u00A0Back to group" })] }), _jsxs(LoadingButton, { loading: loadingGroups, onClick: () => addToSelectedGroup(), variant: 'contained', size: "small", disabled: devicesToAdd.length === 0 || selectedGroup === 'all' || loadingGroups, sx: { ml: 2 }, children: [_jsx(ReadMoreIcon, { sx: { mr: 1 } }), " Add to group"] })] }) : ''
297
- : devicesToAdd.length === 0 ? groupUpdateVisible ? _jsxs(Button, { onClick: () => setGroupUpdateVisible(false), sx: { ml: 2 }, variant: "text", color: "inherit", size: "small", children: [_jsx(BackIcon, { fontSize: "small" }), _jsx(Box, { component: 'span', sx: { display: { xs: 'none', sm: 'inline' } }, children: "\u00A0Back to group" })] }) :
298
- _jsxs(_Fragment, { children: [_jsxs(Button, { onClick: () => addDevicesToCurrentGroup(), sx: { ml: 2 }, variant: "outlined", color: "primary", size: "small", children: [_jsx(PlaylistAddIcon, { fontSize: "small", sx: { mr: 1 } }), " ", addDevicesLabel || 'Add devices'] }), _jsxs(Button, { onClick: () => setGroupUpdateVisible(true), sx: { ml: 2 }, variant: "outlined", color: "success", size: "small", children: [_jsx(SettingsIcon, { fontSize: "small" }), _jsx(Box, { component: 'span', sx: { display: { xs: 'none', sm: 'inline' } }, children: "\u00A0Manage group" })] })] })
299
- : _jsxs(LoadingButton, { loading: loadingGroups, onClick: async () => { setLoadingGroups(true); await removeFromCurrentGroup(); }, variant: "contained", color: "error", size: "small", disabled: loadingGroups, sx: { ml: 2 }, children: [_jsx(PlaylistRemoveIcon, { fontSize: "small", sx: { mr: 1 } }), " Remove from group"] })
300
- : '', selectedGroup !== 'all' ?
308
+ checkboxSelection ? _jsxs(_Fragment, { children: [_jsxs(Button, { onClick: () => { setGroupUpdateVisible(false); setDevicesToAdd([]); setCurrentGroup(selectedGroup); setCheckboxSelection(true); fetchDevices(selectedGroup, selectedGroup); }, variant: "text", color: "inherit", size: "small", children: [_jsx(BackIcon, { fontSize: "small" }), _jsxs(Box, { component: 'span', sx: { display: { xs: 'none', sm: 'inline' } }, children: ["\u00A0Back to ", labelEntity.toLocaleLowerCase()] })] }), _jsxs(LoadingButton, { loading: loadingGroups, onClick: () => addToSelectedGroup(), variant: 'contained', size: "small", disabled: devicesToAdd.length === 0 || selectedGroup === 'all' || loadingGroups, sx: { ml: 2 }, children: [_jsx(ReadMoreIcon, { sx: { mr: 1 } }), " Add to group"] })] }) : ''
309
+ : devicesToAdd.length === 0 ? groupUpdateVisible ? _jsxs(Button, { onClick: () => setGroupUpdateVisible(false), sx: { ml: 2 }, variant: "text", color: "inherit", size: "small", children: [_jsx(BackIcon, { fontSize: "small" }), _jsxs(Box, { component: 'span', sx: { display: { xs: 'none', sm: 'inline' } }, children: ["\u00A0Back to ", labelEntity.toLocaleLowerCase()] })] }) :
310
+ _jsxs(_Fragment, { children: [_jsxs(Button, { onClick: () => addDevicesToCurrentGroup(), sx: { ml: 2 }, variant: "outlined", color: "primary", size: "small", children: [_jsx(PlaylistAddIcon, { fontSize: "small", sx: { mr: 1 } }), " ", addDevicesLabel || 'Add devices'] }), _jsxs(Button, { onClick: () => setGroupUpdateVisible(true), sx: { ml: 2 }, variant: "outlined", color: "success", size: "small", children: [_jsx(SettingsIcon, { fontSize: "small" }), _jsxs(Box, { component: 'span', sx: { display: { xs: 'none', sm: 'inline' } }, children: ["\u00A0Manage ", labelEntity.toLocaleLowerCase()] })] })] })
311
+ : _jsxs(LoadingButton, { loading: loadingGroups, onClick: async () => { setLoadingGroups(true); await removeFromCurrentGroup(); }, variant: "contained", color: "error", size: "small", disabled: loadingGroups, sx: { ml: 2 }, children: [_jsx(PlaylistRemoveIcon, { fontSize: "small", sx: { mr: 1 } }), " Remove from ", labelEntity.toLocaleLowerCase()] })
312
+ : '', selectedGroup !== 'all' && !isOrg ?
301
313
  _jsx(_Fragment, { children: editGroup ?
302
314
  _jsxs(Button, { variant: "text", color: "inherit", onClick: () => closeEditGroup(), sx: { ml: 2 }, children: [_jsx(CloseIcon, { fontSize: "small" }), _jsx(Box, { component: 'span', sx: { display: { xs: 'none', sm: 'inline' } }, children: "\u00A0Close edit" })] })
303
- : _jsxs(Button, { variant: "contained", color: "secondary", onClick: () => { setDevicesToAdd([]); setEditGroup(!editGroup); setCheckboxSelection(!checkboxSelection); }, children: [_jsx(EditIcon, { sx: { mr: 1 } }), _jsx(Box, { component: 'span', sx: { display: { xs: 'none', sm: 'inline' } }, children: "Edit\u00A0" }), " group"] }) }) : ''] })] }), _jsx(Modal, { open: openAdd, onClose: handleCloseAdd, children: _jsxs(Card, { sx: {
315
+ : _jsxs(Button, { variant: "contained", color: "secondary", onClick: () => { setDevicesToAdd([]); setEditGroup(!editGroup); setCheckboxSelection(!checkboxSelection); }, children: [_jsx(EditIcon, { sx: { mr: 1 } }), _jsx(Box, { component: 'span', sx: { display: { xs: 'none', sm: 'inline' } }, children: "Edit\u00A0" }), " ", labelEntity.toLocaleLowerCase()] }) }) : ''] })] }), _jsx(Modal, { open: openAdd, onClose: handleCloseAdd, children: _jsxs(Card, { sx: {
304
316
  position: 'absolute',
305
317
  top: '50%',
306
318
  left: '50%',
307
319
  transform: 'translate(-50%, -50%)',
308
320
  width: 400,
309
321
  borderRadius: 4
310
- }, children: [_jsx(CardHeader, { title: "New Group", action: _jsx(IconButton, { onClick: handleCloseAdd, children: _jsx(CloseIcon, {}) }) }), _jsx(CardContent, { children: _jsxs("form", { onSubmit: handleSubmit, children: [_jsx(TextField, { fullWidth: true, label: "Group Name", value: groupName, onChange: (e) => setGroupName(e.target.value), required: true }), _jsx(TextField, { fullWidth: true, label: "Description", value: description, onChange: (e) => setDescription(e.target.value), margin: "normal", multiline: true, rows: 4 }), _jsxs(Box, { mt: 2, display: "flex", justifyContent: "space-between", children: [_jsx(Button, { variant: "contained", color: "info", onClick: handleCloseAdd, children: "Cancel" }), _jsx(LoadingButton, { loading: loadingAdd, variant: "contained", color: "primary", type: "submit", children: "Create" })] })] }) })] }) }), !groupUpdateVisible && renderDatagridAndMaps, groupInfo && editGroup && groupUpdateVisible && _jsx(GroupUpdate, { confirmMui: confirmMui, userInfo: userInfo, usersGroup: usersGroup, usersList: usersList, handleGetGroups: handleGetGroups, handleUpdateDevice: handleUpdateDevice, handleAddUserToGroup: handleAddUserToGroup, handleRemoveUserFromGroup: handleRemoveUserFromGroup, groupInfo: groupInfo, afterUpdateCallback: async (groupInfo) => { setGroupInfo(groupInfo); await getGroups(); await getUsersGroup(groupInfo.id); }, afterRemoveCallback: async () => { closeEditGroup(); await getGroups(); setCurrentGroup('all'); }, container: 'Card', handleDeleteGroup: handleDeleteGroup, handleUpdateGroup: handleUpdateGroup, devicesList: devices })] }) }));
322
+ }, children: [_jsx(CardHeader, { title: "new" + labelEntity, action: _jsx(IconButton, { onClick: handleCloseAdd, children: _jsx(CloseIcon, {}) }) }), _jsx(CardContent, { children: _jsxs("form", { onSubmit: handleSubmit, children: [_jsx(TextField, { fullWidth: true, label: labelEntity + " Name", value: groupName, onChange: (e) => setGroupName(e.target.value), required: true }), _jsx(TextField, { fullWidth: true, label: "Description", value: description, onChange: (e) => setDescription(e.target.value), margin: "normal", multiline: true, rows: 4 }), _jsxs(Box, { mt: 2, display: "flex", justifyContent: "space-between", children: [_jsx(Button, { variant: "contained", color: "info", onClick: handleCloseAdd, children: "Cancel" }), _jsx(LoadingButton, { loading: loadingAdd, variant: "contained", color: "primary", type: "submit", children: "Create" })] })] }) })] }) }), !groupUpdateVisible && renderDatagridAndMaps, groupInfo && editGroup && groupUpdateVisible && _jsx(GroupUpdate, { confirmMui: confirmMui, userInfo: userInfo, usersGroup: usersGroup, usersList: usersList, handleGetGroups: handleGetGroups, handleUpdateDevice: handleUpdateDevice, handleAddUserToGroup: handleAddUserToGroup, handleRemoveUserFromGroup: handleRemoveUserFromGroup, groupInfo: groupInfo, afterUpdateCallback: async (groupInfo) => { setGroupInfo(groupInfo); await getGroups(); await getUsersGroup(groupInfo.id); }, afterRemoveCallback: async () => { closeEditGroup(); await getGroups(); setCurrentGroup('all'); }, container: 'Card', handleDeleteGroup: handleDeleteGroup, handleUpdateGroup: handleUpdateGroup, devicesList: devices, labelEntity: labelEntity })] }) }));
311
323
  };
312
324
  export default GroupsDevices;
@@ -17,7 +17,7 @@ declare const UsersDataGrid: ({ handleGetUsersList, pageSize, container, contain
17
17
  }>;
18
18
  pageSize: number;
19
19
  container?: "Card" | "Box";
20
- containerProps?: object | undefined;
20
+ containerProps?: any;
21
21
  props?: object | undefined;
22
22
  loadingComponent?: React.ReactNode;
23
23
  theme: Theme;
@@ -8,7 +8,7 @@ const UsersDataGrid = ({ handleGetUsersList, pageSize, container = 'Box', contai
8
8
  const [usersList, setUsersList] = useState(undefined);
9
9
  const [userCount, setUserCount] = useState(undefined);
10
10
  const filterType = {
11
- email: 'Email',
11
+ email: 'Email Address',
12
12
  name: 'Full name',
13
13
  role: 'Role'
14
14
  };
@@ -85,9 +85,9 @@ const UsersDataGrid = ({ handleGetUsersList, pageSize, container = 'Box', contai
85
85
  showQuickFilter: false,
86
86
  },
87
87
  }, rowCount: userCount, loading: isLoading, pageSizeOptions: [], paginationModel: paginationModel, paginationMode: "server", onPaginationModelChange: setPaginationModel, ...props }) }));
88
- const renderFilter = () => (_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', justifyContent: 'flex-end', mb: 2 }, children: [_jsxs(FormControl, { children: [_jsx(InputLabel, { shrink: true, id: "filter-by-select-label", children: "Filter by" }), _jsx(Select, { value: selectedFilterType || '', onChange: (e) => setSelectedFilterType(e.target.value), labelId: "filter-by-select-label", label: "Filter by", size: "small", sx: { mr: 2 }, children: Object.entries(filterType).map(([key, label]) => (_jsx(MenuItem, { value: key, children: label }, key))) })] }), _jsx(TextField, { value: selectedFilterValue || "", onChange: (e) => handleFilterModelChange(e.target.value), placeholder: "Search...", size: "small", InputProps: {
88
+ const renderFilter = () => (_jsxs(Box, { sx: { position: "absolute", top: 10, right: 10, zIndex: 1 }, children: [_jsxs(FormControl, { children: [_jsx(InputLabel, { shrink: true, id: "filter-by-select-label", children: "Filter by" }), _jsx(Select, { value: selectedFilterType || '', onChange: (e) => setSelectedFilterType(e.target.value), labelId: "filter-by-select-label", label: "Filter by", size: "small", sx: { mr: 2 }, children: Object.entries(filterType).map(([key, label]) => (_jsx(MenuItem, { value: key, children: label }, key))) })] }), _jsx(TextField, { value: selectedFilterValue || "", onChange: (e) => handleFilterModelChange(e.target.value), placeholder: "Search...", size: "small", InputProps: {
89
89
  endAdornment: selectedFilterValue ? (_jsx(IconButton, { size: "small", onClick: () => handleFilterModelChange(""), children: _jsx(ClearIcon, { fontSize: "small" }) })) : null,
90
90
  } })] }));
91
- return _jsx(ThemeProvider, { theme: theme, children: container === "Card" ? (_jsxs(_Fragment, { children: [renderFilter(), _jsx(Card, { ...containerProps, children: renderUsersList() })] })) : (_jsxs(_Fragment, { children: [renderFilter(), _jsx(Box, { ...containerProps, children: renderUsersList() })] })) });
91
+ return _jsx(ThemeProvider, { theme: theme, children: container === "Card" ? (_jsx(_Fragment, { children: _jsxs(Card, { ...containerProps, sx: { position: 'relative', ...(containerProps?.sx) }, children: [renderFilter(), renderUsersList()] }) })) : (_jsxs(_Fragment, { children: [renderFilter(), _jsxs(Box, { ...containerProps, sx: { position: 'relative', ...(containerProps?.sx) }, children: [renderFilter(), renderUsersList()] })] })) });
92
92
  };
93
93
  export default UsersDataGrid;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iotready/nextjs-components-library",
3
- "version": "1.0.0-preview31",
3
+ "version": "1.0.0-preview33",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "build": "rm -rf dist && tsc --project tsconfig.build.json && cp package.json dist/",
@@ -1,5 +1,5 @@
1
1
  import { Firestore } from "firebase-admin/firestore";
2
- export declare const getGroups: (db: Firestore, productID: number, userID?: string, assetID?: string) => Promise<{
2
+ export declare const getGroups: (db: Firestore, productID: number, userID?: string, parentID?: string, assetID?: string) => Promise<{
3
3
  id: string;
4
4
  }[]>;
5
5
  export declare const getGroupById: (db: Firestore, id: string) => Promise<{
@@ -16,3 +16,6 @@ export declare const getGroupsUser: (db: Firestore, userID: string) => Promise<{
16
16
  }[]>;
17
17
  export declare const addUsersGroup: (db: Firestore, groupID: string, userName: string, userID: string) => Promise<string>;
18
18
  export declare const removeUserGroup: (db: Firestore, groupID: string, userID: string) => Promise<string | undefined>;
19
+ export declare const getUserOrganizations: (db: Firestore, productID: number, userID?: string, assetID?: string) => Promise<{
20
+ id: string;
21
+ }[]>;
@@ -1,7 +1,15 @@
1
1
  "use server";
2
2
  // 1. GET GROUPS
3
- export const getGroups = async (db, productID, userID, assetID) => {
3
+ export const getGroups = async (db, productID, userID, parentID, assetID) => {
4
4
  let groupsRef = db.collection("groups").where("productID", "==", productID);
5
+ if (parentID) {
6
+ if (parentID === "all") {
7
+ groupsRef = groupsRef.where("parent_id", "!=", null);
8
+ }
9
+ else {
10
+ groupsRef = groupsRef.where("parent_id", "==", parentID);
11
+ }
12
+ }
5
13
  if (assetID) {
6
14
  groupsRef = groupsRef.where("assets", "array-contains", assetID);
7
15
  }
@@ -106,3 +114,56 @@ export const removeUserGroup = async (db, groupID, userID) => {
106
114
  return doc.id;
107
115
  }
108
116
  };
117
+ // 9. GET ORGANIZATIONS
118
+ export const getUserOrganizations = async (db, productID, userID, assetID) => {
119
+ let groupsRef = db
120
+ .collection("groups")
121
+ .where("productID", "==", productID);
122
+ if (assetID) {
123
+ groupsRef = groupsRef.where("assets", "array-contains", assetID);
124
+ }
125
+ groupsRef = groupsRef.orderBy("created", "desc");
126
+ let groupIds = null;
127
+ if (userID) {
128
+ const userGroupsSnapshot = await db
129
+ .collection("userGroups")
130
+ .where("user.userId", "==", userID)
131
+ .get();
132
+ const userGroupIds = userGroupsSnapshot.docs.map((doc) => doc.data().groupId);
133
+ let parentIds = [];
134
+ if (userGroupIds.length > 0) {
135
+ const chunks = [];
136
+ for (let i = 0; i < userGroupIds.length; i += 10) {
137
+ chunks.push(userGroupIds.slice(i, i + 10));
138
+ }
139
+ for (const chunk of chunks) {
140
+ const groupsSnapshot = await db
141
+ .collection("groups")
142
+ .where("__name__", "in", chunk)
143
+ .get();
144
+ const ids = groupsSnapshot.docs
145
+ .map((doc) => doc.data().parent_id)
146
+ .filter((id) => id !== null && id !== undefined);
147
+ parentIds.push(...ids);
148
+ }
149
+ // Rimuove duplicati
150
+ groupIds = Array.from(new Set(parentIds));
151
+ }
152
+ else {
153
+ groupIds = [];
154
+ }
155
+ }
156
+ const groupsSnapshot = await groupsRef.get();
157
+ const organizations = groupsSnapshot.docs
158
+ .filter((doc) => {
159
+ const data = doc.data();
160
+ const parentId = data.parent_id;
161
+ return (parentId === null || parentId === undefined) &&
162
+ (!groupIds || groupIds.includes(doc.id));
163
+ })
164
+ .map((doc) => ({
165
+ id: doc.id,
166
+ ...doc.data()
167
+ }));
168
+ return organizations;
169
+ };
@@ -37,5 +37,5 @@ export declare function post(trackleConfig: TrackleConfig, id: string, endpoint:
37
37
  export declare function put(trackleConfig: TrackleConfig, id: string, endpoint: string, value: any, productId?: number, uid?: string): Promise<{
38
38
  return_value: number;
39
39
  }>;
40
- export declare function addDevicesToGroup(trackleConfig: TrackleConfig, productId: number, uid: string, group: string, devicesToPatch: TrackleDeviceType[]): Promise<TrackleDeviceType[]>;
41
- export declare function removeDevicesFromGroup(trackleConfig: TrackleConfig, productId: number, uid: string, group: string, devicesToPatch: TrackleDeviceType[]): Promise<TrackleDeviceType[]>;
40
+ export declare function addDevicesToGroup(trackleConfig: TrackleConfig, productId: number, group: string, devicesToPatch: TrackleDeviceType[], uid?: string): Promise<TrackleDeviceType[]>;
41
+ export declare function removeDevicesFromGroup(trackleConfig: TrackleConfig, productId: number, group: string, devicesToPatch: TrackleDeviceType[], uid?: string): Promise<TrackleDeviceType[]>;
@@ -121,7 +121,7 @@ export async function put(trackleConfig, id, endpoint, value, productId, uid) {
121
121
  .setTimeout(trackleConfig.apiTimeout)
122
122
  .json();
123
123
  }
124
- export async function addDevicesToGroup(trackleConfig, productId, uid, group, devicesToPatch) {
124
+ export async function addDevicesToGroup(trackleConfig, productId, group, devicesToPatch, uid) {
125
125
  const devicesPatched = [];
126
126
  for (const device of devicesToPatch) {
127
127
  const newGroups = device.state?.groups && device.state?.groups instanceof Array
@@ -129,19 +129,19 @@ export async function addDevicesToGroup(trackleConfig, productId, uid, group, de
129
129
  : [];
130
130
  if (!newGroups.includes(group)) {
131
131
  newGroups.push(group);
132
- await wretchApi(trackleConfig, uid)
133
- .url(`/products/${productId}/devices/${device.id}/groups`)
134
- .put({
135
- value: newGroups
136
- })
132
+ const api = uid ? wretchApi(trackleConfig, uid) : wretchApi(trackleConfig);
133
+ await api
134
+ .put({ value: newGroups }, uid
135
+ ? `/devices/${device.id}/groups`
136
+ : `/products/${productId}/devices/${device.id}/groups`)
137
137
  .setTimeout(trackleConfig.apiTimeout)
138
- .res();
138
+ .json();
139
139
  devicesPatched.push(device);
140
140
  }
141
141
  }
142
142
  return devicesPatched;
143
143
  }
144
- export async function removeDevicesFromGroup(trackleConfig, productId, uid, group, devicesToPatch) {
144
+ export async function removeDevicesFromGroup(trackleConfig, productId, group, devicesToPatch, uid) {
145
145
  const devicesPatched = [];
146
146
  for (const device of devicesToPatch) {
147
147
  let newGroups = device.state?.groups && device.state?.groups instanceof Array
@@ -149,11 +149,11 @@ export async function removeDevicesFromGroup(trackleConfig, productId, uid, grou
149
149
  : [];
150
150
  if (newGroups.includes(group)) {
151
151
  newGroups = newGroups.filter((newGroup) => newGroup !== group);
152
- await wretchApi(trackleConfig, uid)
153
- .url(`/products/${productId}/devices/${device.id}/groups`)
154
- .put({
155
- value: newGroups
156
- })
152
+ const api = uid ? wretchApi(trackleConfig, uid) : wretchApi(trackleConfig);
153
+ await api
154
+ .put({ value: newGroups }, uid
155
+ ? `/devices/${device.id}/groups`
156
+ : `/products/${productId}/devices/${device.id}/groups`)
157
157
  .setTimeout(trackleConfig.apiTimeout)
158
158
  .res();
159
159
  devicesPatched.push(device);