@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.
- package/components/charts/TrendChart.js +1 -1
- package/components/groups/GroupUpdate.d.ts +2 -1
- package/components/groups/GroupUpdate.js +2 -2
- package/components/groups/GroupsDevices.d.ts +4 -1
- package/components/groups/GroupsDevices.js +88 -35
- package/components/users/UsersDataGrid.d.ts +1 -1
- package/components/users/UsersDataGrid.js +3 -3
- package/package.json +1 -1
- package/server-actions/groups.d.ts +4 -1
- package/server-actions/groups.js +62 -1
- package/server-actions/trackle.d.ts +2 -2
- package/server-actions/trackle.js +13 -13
|
@@ -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: [
|
|
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
|
|
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,
|
|
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
|
|
260
|
+
if (!checkboxSelection)
|
|
246
261
|
return;
|
|
247
|
-
|
|
248
|
-
clickedIdRef.current
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
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
|
|
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 ?
|
|
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:
|
|
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" }), "
|
|
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" }),
|
|
297
|
-
: devicesToAdd.length === 0 ? groupUpdateVisible ? _jsxs(Button, { onClick: () => setGroupUpdateVisible(false), sx: { ml: 2 }, variant: "text", color: "inherit", size: "small", children: [_jsx(BackIcon, { fontSize: "small" }),
|
|
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" }),
|
|
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
|
|
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" }), "
|
|
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
|
|
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?:
|
|
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: {
|
|
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" ? (
|
|
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,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
|
+
}[]>;
|
package/server-actions/groups.js
CHANGED
|
@@ -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,
|
|
41
|
-
export declare function removeDevicesFromGroup(trackleConfig: TrackleConfig, productId: number,
|
|
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,
|
|
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
|
-
|
|
133
|
-
|
|
134
|
-
.put({
|
|
135
|
-
|
|
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
|
-
.
|
|
138
|
+
.json();
|
|
139
139
|
devicesPatched.push(device);
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
142
|
return devicesPatched;
|
|
143
143
|
}
|
|
144
|
-
export async function removeDevicesFromGroup(trackleConfig, productId,
|
|
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
|
-
|
|
153
|
-
|
|
154
|
-
.put({
|
|
155
|
-
|
|
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);
|