@iotready/nextjs-components-library 1.0.0-preview32 → 1.0.0-preview34

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.
@@ -850,7 +850,7 @@ const TrendChart = ({ filter, measures1, annotationsDataFn, measures2, enableDat
850
850
  '& .MuiToggleButton-root': {
851
851
  color: 'text.primary', fontSize: '0.95rem', fontWeight: 'normal', paddingTop: '6px', paddingBottom: '6px'
852
852
  }
853
- }, disabled: chartLoading, children: [_jsx(ToggleButton, { value: "1D", sx: { px: 1 }, children: "1d" }), _jsx(ToggleButton, { value: "1W", sx: { px: 1 }, children: "1w" }), _jsx(ToggleButton, { value: "1M", sx: { px: 1 }, children: "1M" }), _jsx(ToggleButton, { value: "3M", sx: { px: 1 }, children: "3M" }), _jsx(ToggleButton, { value: "6M", sx: { px: 1 }, children: "6M" }), _jsx(ToggleButton, { value: "1Y", sx: { px: 1 }, children: "1Y" }), _jsx(ToggleButton, { value: "ALL", sx: { px: 1 }, children: "ALL" })] }), _jsx(MuiTooltip, { placement: "top", arrow: true, title: "Connect point values", children: _jsx("span", { children: _jsx(ToggleButton, { value: "check", color: "primary", size: "small", selected: spanGapsOption, disabled: chartLoading, onChange: () => handleSpanGaps(!spanGapsOption), sx: { ml: 1 }, children: _jsx(TimelineIcon, {}) }) }) }), annotationsData !== null && (_jsx(MuiTooltip, { placement: "top", arrow: true, title: "Show annotations", children: _jsx("span", { children: _jsx(ToggleButton, { value: "check", color: "primary", size: "small", selected: annotationsEnabled, disabled: chartLoading, onChange: () => setAnnotationsEnabled(!annotationsEnabled), sx: { ml: 1 }, children: _jsx(EditNoteIcon, {}) }) }) }))] })] }), _jsx(Box, { component: 'div', className: "chart-container", sx: { mt: 2, height: '100%' }, children: chartJsLoaded && !chartLoading && typeof window !== 'undefined' ?
853
+ }, disabled: chartLoading, children: [_jsx(ToggleButton, { value: "1D", sx: { px: 1 }, children: "1d" }), _jsx(ToggleButton, { value: "1W", sx: { px: 1 }, children: "1w" }), _jsx(ToggleButton, { value: "1M", sx: { px: 1 }, children: "1M" }), _jsx(ToggleButton, { value: "3M", sx: { px: 1 }, children: "3M" }), _jsx(ToggleButton, { value: "6M", sx: { px: 1 }, children: "6M" }), _jsx(ToggleButton, { value: "1Y", sx: { px: 1 }, children: "1Y" }), _jsx(ToggleButton, { value: "ALL", sx: { px: 1 }, children: "ALL" })] }), _jsx(MuiTooltip, { placement: "top", arrow: true, title: "Connect point values", children: _jsx("span", { children: _jsx(ToggleButton, { value: "check", color: "primary", size: "small", selected: spanGapsOption, disabled: chartLoading, onChange: () => handleSpanGaps(!spanGapsOption), sx: { ml: 1 }, children: _jsx(TimelineIcon, {}) }) }) }), annotationsDataFn && annotationsData !== null && (_jsx(MuiTooltip, { placement: "top", arrow: true, title: "Show annotations", children: _jsx("span", { children: _jsx(ToggleButton, { value: "check", color: "primary", size: "small", selected: annotationsEnabled, disabled: chartLoading, onChange: () => setAnnotationsEnabled(!annotationsEnabled), sx: { ml: 1 }, children: _jsx(EditNoteIcon, {}) }) }) }))] })] }), _jsx(Box, { component: 'div', className: "chart-container", sx: { mt: 2, height: '100%' }, children: chartJsLoaded && !chartLoading && typeof window !== 'undefined' ?
854
854
  _jsx(_Fragment, { children: dataMeasures && (dataMeasures.length > 1 || (dataMeasures.length === 1 && dataMeasures[0].data?.length)) ?
855
855
  (_jsx(Line, { options: options, data: {
856
856
  // datasets: dataMeasures || [{ data: [] }]
@@ -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, noDevicesLabel, 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;
@@ -39,5 +40,7 @@ declare const GroupsDevices: ({ userInfo, handleGetUsersList, handleAddUserToGro
39
40
  addDevicesLabel?: string;
40
41
  noDevicesLabel?: string;
41
42
  groupUpdateRoles?: string[];
43
+ isOrg?: boolean;
44
+ currentOrg?: string;
42
45
  }) => string | number | bigint | boolean | import("react/jsx-runtime").JSX.Element | Iterable<import("react").ReactNode> | Promise<import("react").AwaitedReactNode> | null;
43
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, noDevicesLabel, 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,15 +127,18 @@ 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') {
123
134
  getUsersGroup(currentGroup);
124
135
  }
125
136
  fetchDevices(currentGroup, currentGroup);
137
+ if (isOrg) {
138
+ setCheckboxSelection(true);
139
+ }
126
140
  }
127
- }, [currentGroup]);
141
+ }, [currentGroup, groups]);
128
142
  useEffect(() => {
129
143
  if (forceGetDevices !== 0) {
130
144
  fetchDevices(currentGroup, currentGroup);
@@ -143,6 +157,7 @@ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, han
143
157
  setCurrentGroup(id);
144
158
  setGroupInfo({ ...newGroup, id });
145
159
  setSelectedGroup(id);
160
+ getUsersGroup(id);
146
161
  setDevicesToAdd([]), setEditGroup(!editGroup);
147
162
  setCheckboxSelection(!checkboxSelection);
148
163
  fetchDevices(id, id);
@@ -242,31 +257,69 @@ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, han
242
257
  }, onCellClick: (params) => {
243
258
  clickedIdRef.current = params.id.toString(); // aggiornamento immediato
244
259
  }, onRowSelectionModelChange: (ids) => {
245
- if (!checkboxSelection || !clickedIdRef.current)
260
+ if (!checkboxSelection)
246
261
  return;
247
- const clickedId = clickedIdRef.current;
248
- clickedIdRef.current = null; // resetta subito dopo l’uso
249
- setDevicesToAdd(prevIds => {
250
- const updated = prevIds.includes(clickedId)
251
- ? prevIds.filter(id => id !== clickedId)
252
- : [...prevIds, clickedId];
253
- return updated;
254
- });
255
- setDeviceSelectedObjs(prevObjs => {
256
- const isDeselecting = prevObjs.some(d => d.id.toString() === clickedId);
257
- if (isDeselecting) {
258
- return prevObjs.filter(d => d.id.toString() !== clickedId);
259
- }
260
- else {
261
- const device = devices.find(d => d.id.toString() === clickedId);
262
- return device ? [...prevObjs, device] : prevObjs;
262
+ // Se abbiamo un clickedIdRef, gestiamo il click individuale
263
+ if (clickedIdRef.current) {
264
+ const clickedId = clickedIdRef.current;
265
+ clickedIdRef.current = null; // resetta subito dopo l'uso
266
+ setDevicesToAdd(prevIds => {
267
+ const updated = prevIds.includes(clickedId)
268
+ ? prevIds.filter(id => id !== clickedId)
269
+ : [...prevIds, clickedId];
270
+ return updated;
271
+ });
272
+ setDeviceSelectedObjs(prevObjs => {
273
+ const isDeselecting = prevObjs.some(d => d.id.toString() === clickedId);
274
+ if (isDeselecting) {
275
+ return prevObjs.filter(d => d.id.toString() !== clickedId);
276
+ }
277
+ else {
278
+ const device = devices.find(d => d.id.toString() === clickedId);
279
+ return device ? [...prevObjs, device] : prevObjs;
280
+ }
281
+ });
282
+ }
283
+ else {
284
+ // Gestione del "check all" - confronta con il modello di selezione attuale
285
+ const currentSelection = (checkboxSelection && currentGroup === 'all')
286
+ ? [
287
+ ...devices
288
+ .filter(d => d.groups?.includes(selectedGroup))
289
+ .map(d => d.id.toString()),
290
+ ...devicesToAdd,
291
+ ]
292
+ : devicesToAdd;
293
+ // Se la selezione è diversa, aggiorna devicesToAdd
294
+ if (JSON.stringify(ids.sort()) !== JSON.stringify(currentSelection.sort())) {
295
+ // Filtra solo i dispositivi che non sono già nel gruppo
296
+ const selectableDevices = devices
297
+ .filter(d => !d.groups?.includes(selectedGroup))
298
+ .map(d => d.id.toString());
299
+ // Calcola i nuovi dispositivi da aggiungere
300
+ const newDevicesToAdd = ids.filter(id => selectableDevices.includes(id) && !devicesToAdd.includes(id));
301
+ // Calcola i dispositivi da rimuovere dalla selezione
302
+ const devicesToRemove = devicesToAdd.filter(id => !ids.includes(id));
303
+ // Aggiorna devicesToAdd
304
+ setDevicesToAdd(prevIds => {
305
+ return prevIds
306
+ .filter(id => !devicesToRemove.includes(id))
307
+ .concat(newDevicesToAdd);
308
+ });
309
+ // Aggiorna deviceSelectedObjs
310
+ setDeviceSelectedObjs(prevObjs => {
311
+ return prevObjs
312
+ .filter(d => !devicesToRemove.includes(d.id.toString()))
313
+ .concat(devices.filter(d => newDevicesToAdd.includes(d.id.toString()) &&
314
+ !prevObjs.some(obj => obj.id.toString() === d.id.toString())));
315
+ });
263
316
  }
264
- });
317
+ }
265
318
  }, disableDensitySelector: true, disableColumnSelector: true, disableRowSelectionOnClick: true, loading: loadingDevices, rows: devices, columns: checkboxSelection
266
319
  ? columnsArray.filter(col => col.field !== 'id')
267
320
  : columnsArray, slots: {
268
321
  noRowsOverlay: () => (_jsx(Stack, { height: "100%", alignItems: "center", justifyContent: "center", children: currentGroup !== 'all'
269
- ? (_jsxs(_Fragment, { children: [_jsxs(Box, { children: [noDevicesLabel || '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'] }))] }))
322
+ ? (_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'] }))] }))
270
323
  : noDevicesLabel || 'No devices' })),
271
324
  noResultsOverlay: () => (_jsx(Stack, { height: "100%", alignItems: "center", justifyContent: "center", children: "Filter returns no result" })),
272
325
  toolbar: customToolbar && customToolbar.length ? CustomToolbar : GridToolbar,
@@ -286,27 +339,27 @@ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, han
286
339
  _jsx(Card, { ...containerProps, children: renderDataGrid }) : _jsx(Box, { ...containerProps, children: renderDataGrid }));
287
340
  if (!userInfo || !groups || !devices)
288
341
  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" }) })
342
+ 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 ? _jsx(Typography, { variant: isOrg ? 'h6' : 'subtitle1', children: _jsxs("b", { children: [labelEntity, " \"", groupInfo?.name, "\""] }) }) : '', groups && !checkboxSelection && !isOrg && !(editGroup && currentGroup === 'all') ?
343
+ _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 }) })
291
344
  : '', (userInfo.role === 'admin' || (groupUpdateRoles && groupUpdateRoles.includes(userInfo.role))) &&
292
345
  _jsxs(Box, { sx: { ml: 2 }, children: [checkboxSelection ?
293
346
  _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 ?
347
+ : '', 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
348
  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' ?
349
+ 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"] })] }) : ''
350
+ : 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()] })] }) :
351
+ _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()] })] })] })
352
+ : _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()] })
353
+ : '', selectedGroup !== 'all' && !isOrg ?
301
354
  _jsx(_Fragment, { children: editGroup ?
302
355
  _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: {
356
+ : _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
357
  position: 'absolute',
305
358
  top: '50%',
306
359
  left: '50%',
307
360
  transform: 'translate(-50%, -50%)',
308
361
  width: 400,
309
362
  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 })] }) }));
363
+ }, 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
364
  };
312
365
  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-preview32",
3
+ "version": "1.0.0-preview34",
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);