@iotready/nextjs-components-library 1.0.0-preview24 → 1.0.0-preview26
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 +3 -3
- package/components/groups/GroupUpdate.d.ts +3 -7
- package/components/groups/GroupUpdate.js +1 -31
- package/components/groups/GroupsDevices.d.ts +12 -9
- package/components/groups/GroupsDevices.js +82 -78
- package/components/groups/Map.d.ts +3 -8
- package/components/settings/DynamicMenu.d.ts +1 -0
- package/components/settings/DynamicMenu.js +2 -1
- package/package.json +1 -1
- package/server-actions/groups.d.ts +4 -1
- package/server-actions/groups.js +17 -5
- package/server-actions/trackle.d.ts +3 -2
- package/server-actions/trackle.js +8 -4
- package/types/device.d.ts +19 -0
- package/types/device.js +1 -0
- package/types/index.d.ts +1 -0
- package/types/index.js +1 -0
|
@@ -187,7 +187,7 @@ function getCsvData(data, measures) {
|
|
|
187
187
|
const TrendChart = ({ deviceId, measures1, annotationsDataFn, measures2, enableDatePicker, handleGetInfluxData, handleGetDwSlotsCB, handleExportDataCB, theme, initialTimeStart, initialTimeEnd }) => {
|
|
188
188
|
const [chartJsLoaded, setChartJsLoaded] = useState(false);
|
|
189
189
|
// Dichiarazione di annotationsData come funzione che ritorna una Promise<any>
|
|
190
|
-
const [annotationsData, setAnnotationsData] = useState(
|
|
190
|
+
const [annotationsData, setAnnotationsData] = useState(null);
|
|
191
191
|
const [annotationsEnabled, setAnnotationsEnabled] = useState(true);
|
|
192
192
|
const [dataMeasures, setDataMeasures] = useState(null);
|
|
193
193
|
const [chartPeriod, setChartPeriod] = useState('1D');
|
|
@@ -431,7 +431,7 @@ const TrendChart = ({ deviceId, measures1, annotationsDataFn, measures2, enableD
|
|
|
431
431
|
const { paddedMin: paddedMin2, paddedMax: paddedMax2 } = getPaddedMinMax(min2, max2);
|
|
432
432
|
// Handle undefined/null annotationsData
|
|
433
433
|
let dynamicAnnotations = {};
|
|
434
|
-
if (Array.isArray(annotationsData) && annotationsData.length > 0 && annotationsEnabled) {
|
|
434
|
+
if (annotationsData && Array.isArray(annotationsData) && annotationsData.length > 0 && annotationsEnabled) {
|
|
435
435
|
dynamicAnnotations = annotationsData.reduce((acc, [timestamp, label], index) => {
|
|
436
436
|
const yVal = paddedMin1 !== null && paddedMin1 !== undefined
|
|
437
437
|
? paddedMin1 + 0.01 * (paddedMax1 - paddedMin1)
|
|
@@ -659,7 +659,7 @@ const TrendChart = ({ deviceId, measures1, annotationsDataFn, measures2, enableD
|
|
|
659
659
|
'& .MuiToggleButton-root': {
|
|
660
660
|
color: 'text.primary', fontSize: '0.95rem', fontWeight: 'normal', paddingTop: '6px', paddingBottom: '6px'
|
|
661
661
|
}
|
|
662
|
-
}, 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 !==
|
|
662
|
+
}, 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' ?
|
|
663
663
|
_jsx(_Fragment, { children: dataMeasures && (dataMeasures.length > 1 || (dataMeasures.length === 1 && dataMeasures[0].data?.length)) ?
|
|
664
664
|
(_jsx(Line, { options: options, data: {
|
|
665
665
|
// datasets: dataMeasures || [{ data: [] }]
|
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
import { UserType } from '../../types';
|
|
2
|
-
declare const GroupUpdate: ({
|
|
1
|
+
import { AssetType, TrackleDeviceType, UserType } from '../../types';
|
|
2
|
+
declare const GroupUpdate: ({ 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[];
|
|
6
6
|
usersList: any[];
|
|
7
|
-
devicesList:
|
|
8
|
-
id: string;
|
|
9
|
-
state: any;
|
|
10
|
-
managers: any[];
|
|
11
|
-
}[];
|
|
7
|
+
devicesList: AssetType[] | TrackleDeviceType[];
|
|
12
8
|
handleAddUserToGroup: (groupID: string, userName: string, userID: string) => Promise<any>;
|
|
13
9
|
handleRemoveUserFromGroup: (groupID: string, userID: string) => Promise<any>;
|
|
14
10
|
handleUpdateDevice: (id: string, body: any, user: UserType) => Promise<any>;
|
|
@@ -8,15 +8,13 @@ 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 = ({
|
|
11
|
+
const GroupUpdate = ({ 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);
|
|
15
15
|
const [loadingAddUserButton, setLoadingAddUserButton] = useState(false);
|
|
16
16
|
const [loadingDeleteGroupButton, setLoadingDeleteGroupButton] = useState(false);
|
|
17
17
|
const [selectedUser, setSelectedUser] = useState(null);
|
|
18
|
-
const [error, setError] = useState(null);
|
|
19
|
-
const [success, setSuccess] = useState(null);
|
|
20
18
|
function handleChange(event) {
|
|
21
19
|
setGroup({ ...group, [event.target.name]: event.target.value });
|
|
22
20
|
}
|
|
@@ -25,23 +23,6 @@ const GroupUpdate = ({ userInfo, groupInfo, usersGroup, usersList, devicesList,
|
|
|
25
23
|
try {
|
|
26
24
|
const response = await handleRemoveUserFromGroup(group.id, userId);
|
|
27
25
|
if (response) {
|
|
28
|
-
if (devicesList.length > 0) {
|
|
29
|
-
// should check if device is present in other groups the user is member of
|
|
30
|
-
const groupsData = await handleGetGroups({ role: 'support', uid: userId });
|
|
31
|
-
const userGroupIds = groupsData.map((group) => group.id);
|
|
32
|
-
// for all devices in the group set the selectedUser as manager
|
|
33
|
-
for (const device of devicesList) {
|
|
34
|
-
// check device is in a group of user is member of
|
|
35
|
-
const found = device.state.groups.some((gID) => userGroupIds.includes(gID));
|
|
36
|
-
if (!found) {
|
|
37
|
-
// remove user from managers
|
|
38
|
-
const managers = device.managers && device.managers.filter(man => man !== userId) || [];
|
|
39
|
-
await handleUpdateDevice(device.id, {
|
|
40
|
-
managers
|
|
41
|
-
}, userInfo);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
26
|
if (afterUpdateCallback) {
|
|
46
27
|
await afterUpdateCallback(group);
|
|
47
28
|
}
|
|
@@ -60,17 +41,6 @@ const GroupUpdate = ({ userInfo, groupInfo, usersGroup, usersList, devicesList,
|
|
|
60
41
|
try {
|
|
61
42
|
const response = await handleAddUserToGroup(group.id, selectedUser.label, selectedUser.id);
|
|
62
43
|
if (response) {
|
|
63
|
-
if (devicesList.length > 0) {
|
|
64
|
-
for (const device of devicesList) {
|
|
65
|
-
// for all devices in the group set the selectedUser as manager
|
|
66
|
-
await handleUpdateDevice(device.id, {
|
|
67
|
-
managers: [
|
|
68
|
-
...(device?.managers || []),
|
|
69
|
-
selectedUser.id
|
|
70
|
-
]
|
|
71
|
-
}, userInfo);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
44
|
if (afterUpdateCallback) {
|
|
75
45
|
await afterUpdateCallback(group);
|
|
76
46
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { UserType } from '../../types/user';
|
|
2
|
-
import { Position } from "./Map";
|
|
3
1
|
import { Theme } from "@emotion/react";
|
|
4
|
-
|
|
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 }: {
|
|
5
4
|
userInfo: UserType;
|
|
6
5
|
handleGetUsersList: ({ page, pageSize }: {
|
|
7
6
|
page: number;
|
|
@@ -14,24 +13,28 @@ declare const GroupsDevices: ({ userInfo, handleGetUsersList, handleAddUserToGro
|
|
|
14
13
|
handleGetGroups: (userInfo?: UserType) => Promise<any>;
|
|
15
14
|
handleGetUsersGroup: (groupID: string) => Promise<any>;
|
|
16
15
|
handleCreateGroup: (group: any) => Promise<any>;
|
|
17
|
-
handleGetDevices: (user: UserType,
|
|
18
|
-
handleGetPositions
|
|
19
|
-
handleAddDevicesToGroup: (user: UserType, group: string, devicesToPatch:
|
|
20
|
-
handleRemoveDevicesFromGroup: (user: UserType, group: string, devicesToPatch:
|
|
16
|
+
handleGetDevices: (user: UserType, group: string, selectedGroup: string) => Promise<AssetType[] | TrackleDeviceType[]>;
|
|
17
|
+
handleGetPositions?: (devices: any) => Promise<DevicePositionType[]>;
|
|
18
|
+
handleAddDevicesToGroup: (user: UserType, group: string, devicesToPatch: AssetType[] | TrackleDeviceType[]) => Promise<TrackleDeviceType[]>;
|
|
19
|
+
handleRemoveDevicesFromGroup: (user: UserType, group: string, devicesToPatch: AssetType[] | TrackleDeviceType[]) => Promise<TrackleDeviceType[]>;
|
|
21
20
|
handleDeleteGroup: (id: string) => Promise<void>;
|
|
22
21
|
handleUpdateGroup: (id: string, group: any) => Promise<void>;
|
|
23
|
-
handleUpdateDevice: (id: string, body: any, user: UserType) => Promise<
|
|
22
|
+
handleUpdateDevice: (id: string, body: any, user: UserType) => Promise<void>;
|
|
24
23
|
group: string;
|
|
25
24
|
columnsArray: any[];
|
|
26
25
|
containerDataGrid?: "Card" | "Box";
|
|
27
26
|
props?: any;
|
|
28
27
|
propsDatagrid?: any;
|
|
28
|
+
propsHeaderGroups?: any;
|
|
29
29
|
loadingComponent?: React.ReactNode;
|
|
30
30
|
containerProps?: any;
|
|
31
31
|
enableMaps?: boolean;
|
|
32
32
|
mapsHeight: string;
|
|
33
|
-
mapsClickCallback?: (position:
|
|
33
|
+
mapsClickCallback?: (position: DevicePositionType) => void;
|
|
34
34
|
theme: Theme;
|
|
35
35
|
confirmMui?: (options?: any) => Promise<void>;
|
|
36
|
+
forceGetDevices?: number;
|
|
37
|
+
customToolbar?: string[];
|
|
38
|
+
groupsLabelAll?: string;
|
|
36
39
|
}) => string | number | bigint | boolean | import("react/jsx-runtime").JSX.Element | Iterable<import("react").ReactNode> | Promise<import("react").AwaitedReactNode> | null;
|
|
37
40
|
export default GroupsDevices;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { Box, CircularProgress, Autocomplete, TextField, Input, IconButton, Button, Card, CardContent, CardHeader, Modal, Typography, Stack, Tab } from "@mui/material";
|
|
4
|
-
import { cloneElement, isValidElement, useEffect, useMemo, useState } from "react";
|
|
4
|
+
import { cloneElement, isValidElement, useEffect, useMemo, useRef, useState } from "react";
|
|
5
5
|
import AddIcon from '@mui/icons-material/Add';
|
|
6
6
|
import PlaylistAddIcon from '@mui/icons-material/PlaylistAdd';
|
|
7
7
|
import EditIcon from '@mui/icons-material/Edit';
|
|
@@ -10,13 +10,13 @@ import ReadMoreIcon from '@mui/icons-material/ReadMore';
|
|
|
10
10
|
import PlaylistRemoveIcon from '@mui/icons-material/PlaylistRemove';
|
|
11
11
|
import CloseIcon from '@mui/icons-material/Close';
|
|
12
12
|
import { LoadingButton, TabContext, TabList, TabPanel } from "@mui/lab";
|
|
13
|
-
import { DataGrid, GridToolbar } from "@mui/x-data-grid";
|
|
13
|
+
import { DataGrid, GridToolbar, GridToolbarExport, GridToolbarQuickFilter } from "@mui/x-data-grid";
|
|
14
14
|
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 }) => {
|
|
19
|
-
const [devices, setDevices] = useState(
|
|
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 }) => {
|
|
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);
|
|
@@ -24,6 +24,7 @@ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, han
|
|
|
24
24
|
const [editGroup, setEditGroup] = useState(false);
|
|
25
25
|
const [checkboxSelection, setCheckboxSelection] = useState(false);
|
|
26
26
|
const [devicesToAdd, setDevicesToAdd] = useState([]);
|
|
27
|
+
const [deviceSelectedObjs, setDeviceSelectedObjs] = useState([]);
|
|
27
28
|
const [currentGroup, setCurrentGroup] = useState(group);
|
|
28
29
|
const [selectedGroup, setSelectedGroup] = useState(group);
|
|
29
30
|
const [groups, setGroups] = useState(null);
|
|
@@ -35,6 +36,7 @@ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, han
|
|
|
35
36
|
const [description, setDescription] = useState('');
|
|
36
37
|
const [groupUpdateVisible, setGroupUpdateVisible] = useState(false);
|
|
37
38
|
const [valueTab, setValueTab] = useState('1');
|
|
39
|
+
const clickedIdRef = useRef(null);
|
|
38
40
|
const handleChangeTab = (event, newValue) => {
|
|
39
41
|
setValueTab(newValue);
|
|
40
42
|
};
|
|
@@ -73,22 +75,9 @@ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, han
|
|
|
73
75
|
const fetchDevices = async (group, selected) => {
|
|
74
76
|
try {
|
|
75
77
|
setLoadingDevices(true);
|
|
76
|
-
|
|
77
|
-
if (group !== "all") {
|
|
78
|
-
queryParams = `last_handshake_at!=null&state.groups=/${group}/`;
|
|
79
|
-
if (userInfo.role === "admin") {
|
|
80
|
-
queryParams += "&quarantined=false";
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
else if (selected !== "all") {
|
|
84
|
-
queryParams = `last_handshake_at!=null&state.groups!=/${selected}/`;
|
|
85
|
-
if (userInfo.role === "admin") {
|
|
86
|
-
queryParams += "&quarantined=false";
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
const devices = await handleGetDevices(userInfo, queryParams);
|
|
78
|
+
const devices = await handleGetDevices(userInfo, group, selected);
|
|
90
79
|
setDevices(devices);
|
|
91
|
-
if (enableMaps) {
|
|
80
|
+
if (enableMaps && handleGetPositions) {
|
|
92
81
|
const positions = await handleGetPositions(devices);
|
|
93
82
|
setPositions(positions);
|
|
94
83
|
}
|
|
@@ -138,6 +127,11 @@ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, han
|
|
|
138
127
|
fetchDevices(currentGroup, currentGroup);
|
|
139
128
|
}
|
|
140
129
|
}, [currentGroup]);
|
|
130
|
+
useEffect(() => {
|
|
131
|
+
if (forceGetDevices !== 0) {
|
|
132
|
+
fetchDevices(currentGroup, currentGroup);
|
|
133
|
+
}
|
|
134
|
+
}, [forceGetDevices]);
|
|
141
135
|
const handleSubmit = async (e) => {
|
|
142
136
|
e.preventDefault();
|
|
143
137
|
setLoadingAdd(true);
|
|
@@ -186,28 +180,11 @@ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, han
|
|
|
186
180
|
const addToSelectedGroup = async () => {
|
|
187
181
|
setLoadingGroups(true);
|
|
188
182
|
try {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
const userIdsToAdd = usersGroup && usersGroup.map((ug) => ug.user.userId) || [];
|
|
195
|
-
if (userIdsToAdd && userIdsToAdd.length > 0) {
|
|
196
|
-
for (const device of devicesToPatch) {
|
|
197
|
-
// add members to devices managers
|
|
198
|
-
await handleUpdateDevice(device.id, {
|
|
199
|
-
managers: [
|
|
200
|
-
...(device?.managers || []),
|
|
201
|
-
...userIdsToAdd
|
|
202
|
-
]
|
|
203
|
-
}, userInfo);
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
setLoadingGroups(false);
|
|
207
|
-
setCurrentGroup(selectedGroup);
|
|
208
|
-
setDevicesToAdd([...[]]);
|
|
209
|
-
fetchDevices(selectedGroup, selectedGroup);
|
|
210
|
-
}
|
|
183
|
+
await handleAddDevicesToGroup(userInfo, selectedGroup, deviceSelectedObjs);
|
|
184
|
+
setLoadingGroups(false);
|
|
185
|
+
setCurrentGroup(selectedGroup);
|
|
186
|
+
setDevicesToAdd([...[]]);
|
|
187
|
+
fetchDevices(selectedGroup, selectedGroup);
|
|
211
188
|
}
|
|
212
189
|
catch (err) {
|
|
213
190
|
console.error(err);
|
|
@@ -219,32 +196,10 @@ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, han
|
|
|
219
196
|
const removeFromCurrentGroup = async () => {
|
|
220
197
|
setLoadingGroups(true);
|
|
221
198
|
try {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
for (const device of devicesToPatch) {
|
|
227
|
-
if (device.managers && device.managers.length > 0) {
|
|
228
|
-
let managersToKeep = device.managers;
|
|
229
|
-
for (const manager of device.managers) {
|
|
230
|
-
// should check if device is present in other groups the user is member of
|
|
231
|
-
const groupsData = await handleGetGroups({ role: 'support', uid: manager });
|
|
232
|
-
const userGroupIds = groupsData && groupsData.map((group) => group.id) || [];
|
|
233
|
-
const found = device.groups && device.groups.some((gID) => userGroupIds.includes(gID));
|
|
234
|
-
if (!found) {
|
|
235
|
-
// @ts-ignore
|
|
236
|
-
managersToKeep = managersToKeep.filter(man => man !== manager);
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
await handleUpdateDevice(device.id, {
|
|
240
|
-
managers: managersToKeep
|
|
241
|
-
}, userInfo);
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
setLoadingGroups(false);
|
|
245
|
-
setDevicesToAdd([]);
|
|
246
|
-
fetchDevices(currentGroup, selectedGroup);
|
|
247
|
-
}
|
|
199
|
+
await handleRemoveDevicesFromGroup(userInfo, selectedGroup, deviceSelectedObjs);
|
|
200
|
+
setLoadingGroups(false);
|
|
201
|
+
setDevicesToAdd([]);
|
|
202
|
+
fetchDevices(currentGroup, selectedGroup);
|
|
248
203
|
}
|
|
249
204
|
catch (err) {
|
|
250
205
|
console.error(err);
|
|
@@ -261,14 +216,62 @@ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, han
|
|
|
261
216
|
setCheckboxSelection(!checkboxSelection);
|
|
262
217
|
};
|
|
263
218
|
const renderMaps = (_jsx(Map, { positions: positions, mapsClickCallback: mapsClickCallback, height: mapsHeight }));
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
219
|
+
useEffect(() => {
|
|
220
|
+
if (devicesToAdd.length <= 0) {
|
|
221
|
+
setDeviceSelectedObjs([]);
|
|
222
|
+
}
|
|
223
|
+
}, [devicesToAdd]);
|
|
224
|
+
const CustomToolbar = () => (_jsxs("div", { style: { display: 'flex', padding: '8px', justifyContent: 'space-between', paddingTop: '2px' }, children: [_jsxs("div", { style: { display: 'flex', gap: 8, marginRight: '20px' }, children: [customToolbar && customToolbar.includes('filters') ?
|
|
225
|
+
_jsx(GridToolbarExport, { sx: { mr: 2 } })
|
|
226
|
+
: '', customToolbar && customToolbar.includes('export') ?
|
|
227
|
+
_jsx(GridToolbarExport, {})
|
|
228
|
+
: ''] }), customToolbar && customToolbar.includes('quickfilter') && _jsx(GridToolbarQuickFilter, {})] }));
|
|
229
|
+
const renderDataGrid = (_jsx("div", { style: { display: 'flex', flexDirection: 'column', minHeight: 323 }, children: _jsx(DataGrid, { checkboxSelection: checkboxSelection,
|
|
230
|
+
// Se siamo in modalità aggiunta, includi gli ID già nel gruppo
|
|
231
|
+
rowSelectionModel: (checkboxSelection && currentGroup === 'all')
|
|
232
|
+
? [
|
|
233
|
+
...devices
|
|
234
|
+
.filter(d => d.groups?.includes(selectedGroup))
|
|
235
|
+
.map(d => d.id.toString()),
|
|
236
|
+
...devicesToAdd,
|
|
237
|
+
]
|
|
238
|
+
: devicesToAdd,
|
|
239
|
+
// Se siamo in modalità aggiunta, disabilita la selezione per i già nel gruppo
|
|
240
|
+
isRowSelectable: params => {
|
|
241
|
+
return (checkboxSelection && currentGroup === 'all')
|
|
242
|
+
? !params.row.groups?.includes(selectedGroup)
|
|
243
|
+
: true;
|
|
244
|
+
}, onCellClick: (params) => {
|
|
245
|
+
clickedIdRef.current = params.id.toString(); // aggiornamento immediato
|
|
246
|
+
}, onRowSelectionModelChange: (ids) => {
|
|
247
|
+
if (!checkboxSelection || !clickedIdRef.current)
|
|
248
|
+
return;
|
|
249
|
+
const clickedId = clickedIdRef.current;
|
|
250
|
+
clickedIdRef.current = null; // resetta subito dopo l’uso
|
|
251
|
+
setDevicesToAdd(prevIds => {
|
|
252
|
+
const updated = prevIds.includes(clickedId)
|
|
253
|
+
? prevIds.filter(id => id !== clickedId)
|
|
254
|
+
: [...prevIds, clickedId];
|
|
255
|
+
return updated;
|
|
256
|
+
});
|
|
257
|
+
setDeviceSelectedObjs(prevObjs => {
|
|
258
|
+
const isDeselecting = prevObjs.some(d => d.id.toString() === clickedId);
|
|
259
|
+
if (isDeselecting) {
|
|
260
|
+
return prevObjs.filter(d => d.id.toString() !== clickedId);
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
const device = devices.find(d => d.id.toString() === clickedId);
|
|
264
|
+
return device ? [...prevObjs, device] : prevObjs;
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
}, disableDensitySelector: true, disableColumnSelector: true, disableRowSelectionOnClick: true, loading: loadingDevices, rows: devices, columns: checkboxSelection
|
|
268
|
+
? columnsArray.filter(col => col.field !== 'id')
|
|
269
|
+
: columnsArray, slots: {
|
|
270
|
+
noRowsOverlay: () => (_jsx(Stack, { height: "100%", alignItems: "center", justifyContent: "center", children: currentGroup !== 'all'
|
|
271
|
+
? (_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 } }), "Add devices"] }))] }))
|
|
272
|
+
: "No devices" })),
|
|
270
273
|
noResultsOverlay: () => (_jsx(Stack, { height: "100%", alignItems: "center", justifyContent: "center", children: "Filter returns no result" })),
|
|
271
|
-
toolbar: GridToolbar,
|
|
274
|
+
toolbar: customToolbar && customToolbar.length ? CustomToolbar : GridToolbar,
|
|
272
275
|
}, slotProps: {
|
|
273
276
|
toolbar: {
|
|
274
277
|
showQuickFilter: true,
|
|
@@ -279,6 +282,7 @@ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, han
|
|
|
279
282
|
sorting: {
|
|
280
283
|
sortModel: [{ field: 'online', sort: 'desc' }],
|
|
281
284
|
},
|
|
285
|
+
pagination: { paginationModel: { pageSize: 100 } },
|
|
282
286
|
}, ...propsDatagrid }) }));
|
|
283
287
|
const renderTabContext = (_jsxs(TabContext, { value: valueTab, children: [_jsx(Box, { sx: { borderBottom: 1, borderColor: 'divider' }, children: _jsxs(TabList, { onChange: handleChangeTab, sx: { minHeight: 20 }, children: [_jsx(Tab, { label: "List", value: "1", sx: { minHeight: 20 } }), _jsx(Tab, { label: "Map", value: "2", sx: { minHeight: 20 } })] }) }), _jsx(TabPanel, { value: "1", sx: { p: 0 }, children: renderDataGrid }), _jsx(TabPanel, { value: "2", sx: { p: 0 }, children: renderMaps })] }));
|
|
284
288
|
const renderDatagridAndMaps = (enableMaps ?
|
|
@@ -287,10 +291,10 @@ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, han
|
|
|
287
291
|
_jsx(Card, { ...containerProps, children: renderDataGrid }) : _jsx(Box, { ...containerProps, children: renderDataGrid }));
|
|
288
292
|
if (!userInfo || !groups || !devices)
|
|
289
293
|
return loadingComponent;
|
|
290
|
-
return (_jsx(ThemeProvider, { theme: theme, children: _jsxs(Box, { ...props, children: [_jsxs(Box, { component: "div", sx: { display: 'flex', alignItems: 'center',
|
|
291
|
-
_jsx(Autocomplete, { disablePortal: true, onChange: handleChangeGroupSelect, value: groupInfo?.name || 'All devices', disableClearable: currentGroup === 'all', isOptionEqualToValue: (o, v) => o.label === v, options: [{ label: '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" }) })
|
|
294
|
+
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') ?
|
|
295
|
+
_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" }) })
|
|
292
296
|
: '', userInfo.role === 'admin' &&
|
|
293
|
-
_jsxs(Box, { children: [checkboxSelection ?
|
|
297
|
+
_jsxs(Box, { sx: { ml: 2 }, children: [checkboxSelection ?
|
|
294
298
|
_jsx(Input, { value: selectedGroup, type: 'hidden', size: 'small' })
|
|
295
299
|
: '', 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 ?
|
|
296
300
|
currentGroup === 'all' ?
|
|
@@ -308,6 +312,6 @@ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, han
|
|
|
308
312
|
transform: 'translate(-50%, -50%)',
|
|
309
313
|
width: 400,
|
|
310
314
|
borderRadius: 4
|
|
311
|
-
}, 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
|
|
315
|
+
}, 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 })] }) }));
|
|
312
316
|
};
|
|
313
317
|
export default GroupsDevices;
|
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
import 'leaflet/dist/leaflet.css';
|
|
2
2
|
import "leaflet-defaulticon-compatibility";
|
|
3
3
|
import "leaflet-defaulticon-compatibility/dist/leaflet-defaulticon-compatibility.css";
|
|
4
|
-
|
|
5
|
-
deviceID: string;
|
|
6
|
-
name: string;
|
|
7
|
-
lat: number;
|
|
8
|
-
lng: number;
|
|
9
|
-
};
|
|
4
|
+
import { DevicePositionType } from "../../types/device";
|
|
10
5
|
export default function Map({ positions, height, mapsClickCallback }: {
|
|
11
|
-
positions:
|
|
6
|
+
positions: DevicePositionType[];
|
|
12
7
|
height: string;
|
|
13
|
-
mapsClickCallback: (position:
|
|
8
|
+
mapsClickCallback: (position: DevicePositionType) => void;
|
|
14
9
|
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -4,6 +4,7 @@ import { createElement, useState } from "react";
|
|
|
4
4
|
import { Box, Card, CardContent, List, ListItemButton, ListItemText, styled, ThemeProvider } from "@mui/material";
|
|
5
5
|
import Grid from "@mui/material/Grid2";
|
|
6
6
|
import NavigateNextIcon from "@mui/icons-material/NavigateNext";
|
|
7
|
+
import React from "react";
|
|
7
8
|
const ListItemButtonSettings = styled(ListItemButton)(({ theme, selected }) => ({
|
|
8
9
|
backgroundColor: theme.palette.primary.main,
|
|
9
10
|
color: theme.palette.primary.contrastText,
|
|
@@ -37,6 +38,6 @@ const DynamicMenu = ({ menuItems, selectedIndex = null, theme }) => {
|
|
|
37
38
|
const handleMenuClick = (index) => {
|
|
38
39
|
setSelected(index); // Assicurati di non chiamarlo nel rendering
|
|
39
40
|
};
|
|
40
|
-
return (_jsx(ThemeProvider, { theme: theme, children: _jsx(Grid, { container: true, spacing: 2, sx: { width: '100%' }, children: _jsx(Grid, { size: { xs: 12, lg: 9 }, children: _jsx(Card, { sx: { borderRadius: 2 }, children: _jsx(CardContent, { sx: { p: 0, "&:last-child": { p: 0 } }, children: _jsxs(Grid, { container: true, spacing: 2, children: [_jsx(Grid, { size: { xs: 12, sm: 4 }, sx: { display: { xs: selected !== null ? 'none' : 'block', sm: 'block' } }, children: _jsx(List, { sx: { p: 0, height: "100%", backgroundColor: "primary.main" }, children: menuItems.map((item, index) => (_jsxs(ListItemButtonSettings, { selected: selected === index, onClick: () => handleMenuClick(index), children: [item.icon && _jsx(Box, { sx: { mr: 2 }, children: item.icon }), _jsx(ListItemText, { primary: _jsx("b", { children: item.name }), secondary: item.description }), _jsx(NavigateNextIcon, { sx: { display: { xs: "block", sm: "none" } } })] }, index))) }) }), _jsx(Grid, { size: { xs: 12, sm: 8, md: 6 }, sx: { display: { xs: selected === null ? 'none' : 'block', sm: 'block' } }, children: _jsx(Box, { component: "div", sx: { p: { xs: 2 }, py: { sm: 3 } }, children: selected !== null ? createElement(menuItems[selected].page, { handleBack: () => { setSelected(null); } }) : "" }) })] }) }) }) }) }) }));
|
|
41
|
+
return (_jsx(ThemeProvider, { theme: theme, children: _jsx(Grid, { container: true, spacing: 2, sx: { width: '100%' }, children: _jsx(Grid, { size: { xs: 12, lg: 9 }, children: _jsx(Card, { sx: { borderRadius: 2 }, children: _jsx(CardContent, { sx: { p: 0, "&:last-child": { p: 0 } }, children: _jsxs(Grid, { container: true, spacing: 2, children: [_jsx(Grid, { size: { xs: 12, sm: 4 }, sx: { display: { xs: selected !== null ? 'none' : 'block', sm: 'block' } }, children: _jsx(List, { sx: { p: 0, height: "100%", backgroundColor: "primary.main" }, children: menuItems.map((item, index) => (_jsxs(ListItemButtonSettings, { selected: selected === index, onClick: () => handleMenuClick(index), children: [item.icon && _jsx(Box, { sx: { mr: 2 }, children: React.isValidElement(item.icon) ? item.icon : null }), _jsx(ListItemText, { primary: _jsx("b", { children: item.name }), secondary: item.description }), _jsx(NavigateNextIcon, { sx: { display: { xs: "block", sm: "none" } } })] }, index))) }) }), _jsx(Grid, { size: { xs: 12, sm: 8, md: 6 }, sx: { display: { xs: selected === null ? 'none' : 'block', sm: 'block' } }, children: _jsx(Box, { component: "div", sx: { p: { xs: 2 }, py: { sm: 3 } }, children: selected !== null ? createElement(menuItems[selected].page, { handleBack: () => { setSelected(null); } }) : "" }) })] }) }) }) }) }) }));
|
|
41
42
|
};
|
|
42
43
|
export default DynamicMenu;
|
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) => Promise<{
|
|
2
|
+
export declare const getGroups: (db: Firestore, productID: number, userID?: string, assetID?: string) => Promise<{
|
|
3
3
|
id: string;
|
|
4
4
|
}[]>;
|
|
5
5
|
export declare const getGroupById: (db: Firestore, id: string) => Promise<{
|
|
@@ -11,5 +11,8 @@ export declare const deleteGroup: (db: Firestore, id: string) => Promise<void>;
|
|
|
11
11
|
export declare const getUsersGroup: (db: Firestore, groupID: string) => Promise<{
|
|
12
12
|
id: string;
|
|
13
13
|
}[]>;
|
|
14
|
+
export declare const getGroupsUser: (db: Firestore, userID: string) => Promise<{
|
|
15
|
+
id: string;
|
|
16
|
+
}[]>;
|
|
14
17
|
export declare const addUsersGroup: (db: Firestore, groupID: string, userName: string, userID: string) => Promise<string>;
|
|
15
18
|
export declare const removeUserGroup: (db: Firestore, groupID: string, userID: string) => Promise<string | undefined>;
|
package/server-actions/groups.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
"use server";
|
|
2
2
|
// 1. GET GROUPS
|
|
3
|
-
export const getGroups = async (db, productID, userID) => {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
.where("
|
|
7
|
-
|
|
3
|
+
export const getGroups = async (db, productID, userID, assetID) => {
|
|
4
|
+
let groupsRef = db.collection("groups").where("productID", "==", productID);
|
|
5
|
+
if (assetID) {
|
|
6
|
+
groupsRef = groupsRef.where("assets", "array-contains", assetID);
|
|
7
|
+
}
|
|
8
|
+
groupsRef = groupsRef.orderBy("created", "desc");
|
|
8
9
|
let groupIds = null;
|
|
9
10
|
if (userID) {
|
|
10
11
|
const userGroupsSnapshot = await db
|
|
@@ -67,6 +68,17 @@ export const getUsersGroup = async (db, groupID) => {
|
|
|
67
68
|
...doc.data()
|
|
68
69
|
}));
|
|
69
70
|
};
|
|
71
|
+
// 6b. GET GROUPS USER
|
|
72
|
+
export const getGroupsUser = async (db, userID) => {
|
|
73
|
+
const snapshot = await db
|
|
74
|
+
.collection("userGroups")
|
|
75
|
+
.where("user.userId", "==", userID)
|
|
76
|
+
.get();
|
|
77
|
+
return snapshot.docs.map((doc) => ({
|
|
78
|
+
id: doc.id,
|
|
79
|
+
...doc.data()
|
|
80
|
+
}));
|
|
81
|
+
};
|
|
70
82
|
// 7. ADD USER TO GROUP
|
|
71
83
|
export const addUsersGroup = async (db, groupID, userName, userID) => {
|
|
72
84
|
const created = new Date().toISOString();
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { TrackleDeviceType } from "../types";
|
|
1
2
|
export type TrackleConfig = {
|
|
2
3
|
orgName: string;
|
|
3
4
|
apiUrl: string;
|
|
@@ -32,5 +33,5 @@ export declare function post(trackleConfig: TrackleConfig, id: string, endpoint:
|
|
|
32
33
|
export declare function put(trackleConfig: TrackleConfig, id: string, endpoint: string, value: any, productId?: number, uid?: string): Promise<{
|
|
33
34
|
return_value: number;
|
|
34
35
|
}>;
|
|
35
|
-
export declare function addDevicesToGroup(trackleConfig: TrackleConfig, productId: number, uid: string, group: string, devicesToPatch:
|
|
36
|
-
export declare function removeDevicesFromGroup(trackleConfig: TrackleConfig, productId: number, uid: string, group: string, devicesToPatch:
|
|
36
|
+
export declare function addDevicesToGroup(trackleConfig: TrackleConfig, productId: number, uid: string, group: string, devicesToPatch: TrackleDeviceType[]): Promise<TrackleDeviceType[]>;
|
|
37
|
+
export declare function removeDevicesFromGroup(trackleConfig: TrackleConfig, productId: number, uid: string, group: string, devicesToPatch: TrackleDeviceType[]): Promise<TrackleDeviceType[]>;
|
|
@@ -110,7 +110,9 @@ export async function put(trackleConfig, id, endpoint, value, productId, uid) {
|
|
|
110
110
|
export async function addDevicesToGroup(trackleConfig, productId, uid, group, devicesToPatch) {
|
|
111
111
|
const devicesPatched = [];
|
|
112
112
|
for (const device of devicesToPatch) {
|
|
113
|
-
const newGroups = device?.groups && device?.groups instanceof Array
|
|
113
|
+
const newGroups = device.state?.groups && device.state?.groups instanceof Array
|
|
114
|
+
? device.state?.groups
|
|
115
|
+
: [];
|
|
114
116
|
if (!newGroups.includes(group)) {
|
|
115
117
|
newGroups.push(group);
|
|
116
118
|
await wretchApi(trackleConfig, uid)
|
|
@@ -120,7 +122,7 @@ export async function addDevicesToGroup(trackleConfig, productId, uid, group, de
|
|
|
120
122
|
})
|
|
121
123
|
.setTimeout(trackleConfig.apiTimeout)
|
|
122
124
|
.res();
|
|
123
|
-
devicesPatched.push(device
|
|
125
|
+
devicesPatched.push(device);
|
|
124
126
|
}
|
|
125
127
|
}
|
|
126
128
|
return devicesPatched;
|
|
@@ -128,7 +130,9 @@ export async function addDevicesToGroup(trackleConfig, productId, uid, group, de
|
|
|
128
130
|
export async function removeDevicesFromGroup(trackleConfig, productId, uid, group, devicesToPatch) {
|
|
129
131
|
const devicesPatched = [];
|
|
130
132
|
for (const device of devicesToPatch) {
|
|
131
|
-
let newGroups = device?.groups && device?.groups instanceof Array
|
|
133
|
+
let newGroups = device.state?.groups && device.state?.groups instanceof Array
|
|
134
|
+
? device.state?.groups
|
|
135
|
+
: [];
|
|
132
136
|
if (newGroups.includes(group)) {
|
|
133
137
|
newGroups = newGroups.filter((newGroup) => newGroup !== group);
|
|
134
138
|
await wretchApi(trackleConfig, uid)
|
|
@@ -138,7 +142,7 @@ export async function removeDevicesFromGroup(trackleConfig, productId, uid, grou
|
|
|
138
142
|
})
|
|
139
143
|
.setTimeout(trackleConfig.apiTimeout)
|
|
140
144
|
.res();
|
|
141
|
-
devicesPatched.push(device
|
|
145
|
+
devicesPatched.push(device);
|
|
142
146
|
}
|
|
143
147
|
}
|
|
144
148
|
return devicesPatched;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export type AssetType = {
|
|
2
|
+
id: string;
|
|
3
|
+
device?: TrackleDeviceType;
|
|
4
|
+
[key: string]: any;
|
|
5
|
+
};
|
|
6
|
+
export type TrackleDeviceType = {
|
|
7
|
+
id: string;
|
|
8
|
+
state: {
|
|
9
|
+
groups: string[] | null;
|
|
10
|
+
};
|
|
11
|
+
managers: string[] | null;
|
|
12
|
+
[key: string]: any;
|
|
13
|
+
};
|
|
14
|
+
export type DevicePositionType = {
|
|
15
|
+
deviceID: string;
|
|
16
|
+
name: string;
|
|
17
|
+
lat: number;
|
|
18
|
+
lng: number;
|
|
19
|
+
};
|
package/types/device.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/types/index.d.ts
CHANGED
package/types/index.js
CHANGED