@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.
@@ -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 !== undefined && (_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' ?
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: ({ userInfo, groupInfo, usersGroup, usersList, devicesList, handleAddUserToGroup, handleRemoveUserFromGroup, handleGetGroups, handleUpdateGroup, handleUpdateDevice, handleDeleteGroup, container, containerProps, afterUpdateCallback, afterRemoveCallback, confirmMui }: {
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 = ({ userInfo, groupInfo, usersGroup, usersList, devicesList, handleAddUserToGroup, handleRemoveUserFromGroup, handleGetGroups, handleUpdateGroup, handleUpdateDevice, handleDeleteGroup, container = 'Box', containerProps = {}, afterUpdateCallback, afterRemoveCallback, confirmMui }) => {
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
- 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 }: {
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, query: string) => Promise<any>;
18
- handleGetPositions: (devices: any) => Promise<any>;
19
- handleAddDevicesToGroup: (user: UserType, group: string, devicesToPatch: any[]) => Promise<any>;
20
- handleRemoveDevicesFromGroup: (user: UserType, group: string, devicesToPatch: any[]) => Promise<any>;
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<any>;
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: Position) => void;
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(null);
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
- let queryParams = "last_handshake_at!=null";
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
- const selectedData = devices.filter((row) => devicesToAdd.includes(row.id));
190
- const devicesToPatch = selectedData?.map((device) => ({ id: device.id, groups: device.state.groups, managers: device.managers }));
191
- const devicesPatched = await handleAddDevicesToGroup(userInfo, selectedGroup, devicesToPatch);
192
- if (devicesPatched && devicesPatched.length > 0) {
193
- // get all members of the group
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
- const devicesToRemove = devices.filter((row) => devicesToAdd.includes(row.id));
223
- const devicesToPatch = devicesToRemove?.map((device) => ({ id: device.id, groups: device.state.groups, managers: device.managers }));
224
- const devicesPatched = await handleRemoveDevicesFromGroup(userInfo, selectedGroup, devicesToPatch);
225
- if (devicesPatched && devicesPatched.length > 0) {
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
- const renderDataGrid = (_jsx("div", { style: { display: 'flex', flexDirection: 'column', minHeight: 323 }, children: _jsx(DataGrid, { checkboxSelection: checkboxSelection, onRowSelectionModelChange: (ids) => {
265
- if (checkboxSelection) {
266
- setDevicesToAdd(ids);
267
- }
268
- }, rowSelectionModel: devicesToAdd, disableDensitySelector: true, disableColumnSelector: true, disableRowSelectionOnClick: true, loading: loadingDevices, rows: devices, columns: checkboxSelection ? columnsArray.filter(col => col.field !== 'id') : columnsArray, slots: {
269
- noRowsOverlay: () => (_jsx(Stack, { height: "100%", alignItems: "center", justifyContent: "center", children: currentGroup !== 'all' ? _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"] }) : ''] }) : "No devices" })),
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', justifyContent: 'space-between', mb: 1, backgroundColor: editGroup ? 'secondary.light' : '', borderRadius: 3, px: editGroup ? 2 : 0, py: 1, height: 50 }, 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') ?
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.map((device) => ({ id: device.id, state: device.state, managers: device.managers })) })] }) }));
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
- export type Position = {
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: Position[];
6
+ positions: DevicePositionType[];
12
7
  height: string;
13
- mapsClickCallback: (position: Position) => void;
8
+ mapsClickCallback: (position: DevicePositionType) => void;
14
9
  }): import("react/jsx-runtime").JSX.Element;
@@ -1,5 +1,6 @@
1
1
  import { SvgIconProps } from "@mui/material/SvgIcon";
2
2
  import { Theme } from "@emotion/react";
3
+ import React from "react";
3
4
  interface MenuItem {
4
5
  name: string;
5
6
  description: string;
@@ -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,6 +1,6 @@
1
1
  {
2
2
  "name": "@iotready/nextjs-components-library",
3
- "version": "1.0.0-preview24",
3
+ "version": "1.0.0-preview26",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "build": "rm -rf dist && tsc --project tsconfig.build.json && cp package.json dist/",
@@ -1,5 +1,5 @@
1
1
  import { Firestore } from "firebase-admin/firestore";
2
- export declare const getGroups: (db: Firestore, productID: number, userID?: string) => 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>;
@@ -1,10 +1,11 @@
1
1
  "use server";
2
2
  // 1. GET GROUPS
3
- export const getGroups = async (db, productID, userID) => {
4
- const groupsRef = db
5
- .collection("groups")
6
- .where("productID", "==", productID)
7
- .orderBy("created", "desc");
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: any[]): Promise<string[]>;
36
- export declare function removeDevicesFromGroup(trackleConfig: TrackleConfig, productId: number, uid: string, group: string, devicesToPatch: any[]): Promise<string[]>;
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 ? device?.groups : [];
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.id);
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 ? device?.groups : [];
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.id);
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
+ };
@@ -0,0 +1 @@
1
+ export {};
package/types/index.d.ts CHANGED
@@ -1 +1,2 @@
1
1
  export * from "./user";
2
+ export * from "./device";
package/types/index.js CHANGED
@@ -1 +1,2 @@
1
1
  export * from "./user";
2
+ export * from "./device";