@iotready/nextjs-components-library 1.0.0-preview23 → 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.
@@ -21,6 +21,7 @@ import { ThemeProvider } from '@mui/material/styles';
21
21
  import TimelineIcon from '@mui/icons-material/Timeline';
22
22
  import MuiTooltip from '@mui/material/Tooltip';
23
23
  import EditNoteIcon from '@mui/icons-material/EditNote';
24
+ // import AspectRatioIcon from '@mui/icons-material/AspectRatio';
24
25
  import { FilterTagMode } from '../../server-actions/types';
25
26
  const lineOptions = {
26
27
  parsing: false,
@@ -126,15 +127,6 @@ const chartConfigByPeriod = {
126
127
  scaleUnit: 'year',
127
128
  }
128
129
  };
129
- // function getChartPoints(data: any): Point[] {
130
- // const points: Point[] = data.results[0].series[0].values.map((row: any) => {
131
- // return {
132
- // x: moment.unix(row[0]),
133
- // y: row[1]
134
- // }
135
- // });
136
- // return points;
137
- // }
138
130
  function getPollTime(intervalInSeconds, pollTime) {
139
131
  const CalculatedPollTime = Math.round(intervalInSeconds / 2880);
140
132
  if (CalculatedPollTime <= pollTime) {
@@ -195,8 +187,8 @@ function getCsvData(data, measures) {
195
187
  const TrendChart = ({ deviceId, measures1, annotationsDataFn, measures2, enableDatePicker, handleGetInfluxData, handleGetDwSlotsCB, handleExportDataCB, theme, initialTimeStart, initialTimeEnd }) => {
196
188
  const [chartJsLoaded, setChartJsLoaded] = useState(false);
197
189
  // Dichiarazione di annotationsData come funzione che ritorna una Promise<any>
198
- const [annotationsData, setAnnotationsData] = useState([]);
199
- const [annotentionsEnabled, setAnnotationsEnabled] = useState(true);
190
+ const [annotationsData, setAnnotationsData] = useState(null);
191
+ const [annotationsEnabled, setAnnotationsEnabled] = useState(true);
200
192
  const [dataMeasures, setDataMeasures] = useState(null);
201
193
  const [chartPeriod, setChartPeriod] = useState('1D');
202
194
  const [chartPeriodConfig, setChartPeriodConfig] = useState(chartConfigByPeriod['1D']);
@@ -318,13 +310,13 @@ const TrendChart = ({ deviceId, measures1, annotationsDataFn, measures2, enableD
318
310
  }
319
311
  }, [csvData]);
320
312
  useEffect(() => {
321
- if (annotationsDataFn && annotentionsEnabled) {
313
+ if (annotationsDataFn && annotationsEnabled) {
322
314
  (async () => {
323
315
  const resp = await annotationsDataFn();
324
316
  setAnnotationsData(resp);
325
317
  })();
326
318
  }
327
- }, [annotationsDataFn, annotentionsEnabled]);
319
+ }, [annotationsDataFn, annotationsEnabled]);
328
320
  function getDwSlotsFromValues(dwValues) {
329
321
  const slots = [];
330
322
  let start = null;
@@ -368,11 +360,7 @@ const TrendChart = ({ deviceId, measures1, annotationsDataFn, measures2, enableD
368
360
  dwPoints = rawDwPoints;
369
361
  }
370
362
  }
371
- const stdRaw = await handleGetInfluxData(measure.name, timeStart, timeEnd, deviceId, polltime, !measure.polltime && rawQuery, !measure.polltime ? "none" : "null", 100, FilterTagMode.Exclude);
372
- // Mappa sul formato Point
373
- const stdPoints = stdRaw
374
- .map((r) => ({ x: Number(r.x), y: r.y }))
375
- .filter((p) => p.y !== null);
363
+ const stdPoints = await handleGetInfluxData(measure.name, timeStart, timeEnd, deviceId, polltime, !measure.polltime && rawQuery, !measure.polltime ? "none" : "null", 100, FilterTagMode.Exclude);
376
364
  const filtered = dwSlots.length
377
365
  ? stdPoints.filter((p) => !dwSlots.some(slot => p.x >= slot.start && p.x <= slot.end))
378
366
  : stdPoints;
@@ -443,7 +431,7 @@ const TrendChart = ({ deviceId, measures1, annotationsDataFn, measures2, enableD
443
431
  const { paddedMin: paddedMin2, paddedMax: paddedMax2 } = getPaddedMinMax(min2, max2);
444
432
  // Handle undefined/null annotationsData
445
433
  let dynamicAnnotations = {};
446
- if (Array.isArray(annotationsData) && annotationsData.length > 0 && annotentionsEnabled) {
434
+ if (annotationsData && Array.isArray(annotationsData) && annotationsData.length > 0 && annotationsEnabled) {
447
435
  dynamicAnnotations = annotationsData.reduce((acc, [timestamp, label], index) => {
448
436
  const yVal = paddedMin1 !== null && paddedMin1 !== undefined
449
437
  ? paddedMin1 + 0.01 * (paddedMax1 - paddedMin1)
@@ -579,7 +567,7 @@ const TrendChart = ({ deviceId, measures1, annotationsDataFn, measures2, enableD
579
567
  loadDatasets(chartPeriod).then(() => {
580
568
  setChartLoading(false);
581
569
  });
582
- }, [measures1, timeEnd, timeStart, measures2, annotentionsEnabled, annotationsData]);
570
+ }, [measures1, timeEnd, timeStart, measures2, annotationsEnabled, annotationsData]);
583
571
  useEffect(() => {
584
572
  const loadZoomPlugin = async () => {
585
573
  const zoomPlugin = (await import('chartjs-plugin-zoom')).default;
@@ -671,7 +659,7 @@ const TrendChart = ({ deviceId, measures1, annotationsDataFn, measures2, enableD
671
659
  '& .MuiToggleButton-root': {
672
660
  color: 'text.primary', fontSize: '0.95rem', fontWeight: 'normal', paddingTop: '6px', paddingBottom: '6px'
673
661
  }
674
- }, 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(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(ToggleButton, { value: "check", color: "primary", size: "small", selected: annotentionsEnabled, disabled: chartLoading, onChange: () => setAnnotationsEnabled(!annotentionsEnabled), 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' ?
675
663
  _jsx(_Fragment, { children: dataMeasures && (dataMeasures.length > 1 || (dataMeasures.length === 1 && dataMeasures[0].data?.length)) ?
676
664
  (_jsx(Line, { options: options, data: {
677
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, 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, 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
+ 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(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, 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
- 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);
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 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
- }
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
- 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, 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', 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" }) })
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.map((device) => ({ id: device.id, state: device.state, managers: device.managers })) })] }) }));
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
- 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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iotready/nextjs-components-library",
3
- "version": "1.0.0-preview23",
3
+ "version": "1.0.0-preview25",
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();
@@ -155,7 +155,7 @@ export async function getInfluxDataV1(influxConfig, field, timeStart, timeEnd, d
155
155
  query += ` fill(null)`;
156
156
  }
157
157
  }
158
- if (fill) {
158
+ if (fill !== "null") {
159
159
  // Query to get the last data point before timeStart
160
160
  const preStartQuery = `SELECT last("value") FROM "${influxConfig.measurement}" WHERE "deviceid" = '${deviceID}' AND "valueName" = '${field}'${filterTagCondition} AND time < '${moment
161
161
  .unix(timeStart)
@@ -196,7 +196,7 @@ export async function getInfluxDataV1(influxConfig, field, timeStart, timeEnd, d
196
196
  series.name = field; // Force the series name to be the field name
197
197
  });
198
198
  // 1000000 REMOVED AND ADDED TO MOVE THE POINT AWAY IN THE CHART
199
- if (fill) {
199
+ if (fill !== "null") {
200
200
  if (preStartValue !== null && preStartValue !== undefined) {
201
201
  // Insert the pre-start value at the beginning of the dataset
202
202
  data.results[0].series[0].values.unshift([
@@ -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";