@iotready/nextjs-components-library 1.0.0-preview24 → 1.0.0-preview25
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 +11 -9
- package/components/groups/GroupsDevices.js +24 -68
- package/components/groups/Map.d.ts +3 -8
- 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, groupsLabelAll }: {
|
|
5
4
|
userInfo: UserType;
|
|
6
5
|
handleGetUsersList: ({ page, pageSize }: {
|
|
7
6
|
page: number;
|
|
@@ -14,24 +13,27 @@ 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
|
+
groupsLabelAll?: string;
|
|
36
38
|
}) => string | number | bigint | boolean | import("react/jsx-runtime").JSX.Element | Iterable<import("react").ReactNode> | Promise<import("react").AwaitedReactNode> | null;
|
|
37
39
|
export default GroupsDevices;
|
|
@@ -15,8 +15,8 @@ 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, 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);
|
|
@@ -73,22 +73,9 @@ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, han
|
|
|
73
73
|
const fetchDevices = async (group, selected) => {
|
|
74
74
|
try {
|
|
75
75
|
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);
|
|
76
|
+
const devices = await handleGetDevices(userInfo, group, selected);
|
|
90
77
|
setDevices(devices);
|
|
91
|
-
if (enableMaps) {
|
|
78
|
+
if (enableMaps && handleGetPositions) {
|
|
92
79
|
const positions = await handleGetPositions(devices);
|
|
93
80
|
setPositions(positions);
|
|
94
81
|
}
|
|
@@ -138,6 +125,11 @@ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, han
|
|
|
138
125
|
fetchDevices(currentGroup, currentGroup);
|
|
139
126
|
}
|
|
140
127
|
}, [currentGroup]);
|
|
128
|
+
useEffect(() => {
|
|
129
|
+
if (forceGetDevices !== 0) {
|
|
130
|
+
fetchDevices(currentGroup, currentGroup);
|
|
131
|
+
}
|
|
132
|
+
}, [forceGetDevices]);
|
|
141
133
|
const handleSubmit = async (e) => {
|
|
142
134
|
e.preventDefault();
|
|
143
135
|
setLoadingAdd(true);
|
|
@@ -186,28 +178,12 @@ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, han
|
|
|
186
178
|
const addToSelectedGroup = async () => {
|
|
187
179
|
setLoadingGroups(true);
|
|
188
180
|
try {
|
|
189
|
-
const
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
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
|
-
}
|
|
181
|
+
const devicesToPatch = devices.filter((row) => devicesToAdd.includes(row.id));
|
|
182
|
+
await handleAddDevicesToGroup(userInfo, selectedGroup, devicesToPatch);
|
|
183
|
+
setLoadingGroups(false);
|
|
184
|
+
setCurrentGroup(selectedGroup);
|
|
185
|
+
setDevicesToAdd([...[]]);
|
|
186
|
+
fetchDevices(selectedGroup, selectedGroup);
|
|
211
187
|
}
|
|
212
188
|
catch (err) {
|
|
213
189
|
console.error(err);
|
|
@@ -220,31 +196,10 @@ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, han
|
|
|
220
196
|
setLoadingGroups(true);
|
|
221
197
|
try {
|
|
222
198
|
const devicesToRemove = devices.filter((row) => devicesToAdd.includes(row.id));
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
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, devicesToRemove);
|
|
200
|
+
setLoadingGroups(false);
|
|
201
|
+
setDevicesToAdd([]);
|
|
202
|
+
fetchDevices(currentGroup, selectedGroup);
|
|
248
203
|
}
|
|
249
204
|
catch (err) {
|
|
250
205
|
console.error(err);
|
|
@@ -279,6 +234,7 @@ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, han
|
|
|
279
234
|
sorting: {
|
|
280
235
|
sortModel: [{ field: 'online', sort: 'desc' }],
|
|
281
236
|
},
|
|
237
|
+
pagination: { paginationModel: { pageSize: 100 } }
|
|
282
238
|
}, ...propsDatagrid }) }));
|
|
283
239
|
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
240
|
const renderDatagridAndMaps = (enableMaps ?
|
|
@@ -287,10 +243,10 @@ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, han
|
|
|
287
243
|
_jsx(Card, { ...containerProps, children: renderDataGrid }) : _jsx(Box, { ...containerProps, children: renderDataGrid }));
|
|
288
244
|
if (!userInfo || !groups || !devices)
|
|
289
245
|
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" }) })
|
|
246
|
+
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') ?
|
|
247
|
+
_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
248
|
: '', userInfo.role === 'admin' &&
|
|
293
|
-
_jsxs(Box, { children: [checkboxSelection ?
|
|
249
|
+
_jsxs(Box, { sx: { ml: 2 }, children: [checkboxSelection ?
|
|
294
250
|
_jsx(Input, { value: selectedGroup, type: 'hidden', size: 'small' })
|
|
295
251
|
: '', 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
252
|
currentGroup === 'all' ?
|
|
@@ -308,6 +264,6 @@ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, han
|
|
|
308
264
|
transform: 'translate(-50%, -50%)',
|
|
309
265
|
width: 400,
|
|
310
266
|
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
|
|
267
|
+
}, 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
268
|
};
|
|
313
269
|
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;
|
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