@iotready/nextjs-components-library 1.0.0-preview1 → 1.0.0-preview11
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/accounts/AccountMenu.d.ts +1 -1
- package/components/charts/TrendChart.d.ts +4 -2
- package/components/charts/TrendChart.js +93 -76
- package/components/groups/GroupsDevices.d.ts +1 -1
- package/components/groups/GroupsDevices.js +18 -3
- package/package.json +1 -1
- package/server-actions/trackle.d.ts +1 -1
- package/server-actions/trackle.js +3 -16
@@ -2,7 +2,7 @@ import { UserType } from '../../types/user';
|
|
2
2
|
import { Theme } from "@emotion/react";
|
3
3
|
export default function UserMenuAccount({ userInfo, handleClick, handleSignOut, accountRoute, theme }: {
|
4
4
|
userInfo: UserType;
|
5
|
-
handleClick: () =>
|
5
|
+
handleClick: () => void;
|
6
6
|
handleSignOut: () => Promise<void>;
|
7
7
|
accountRoute?: string;
|
8
8
|
theme: Theme;
|
@@ -5,13 +5,15 @@ type Measure = {
|
|
5
5
|
name: string;
|
6
6
|
polltime: number;
|
7
7
|
unit: string;
|
8
|
+
stepped: boolean;
|
8
9
|
};
|
9
|
-
declare const TrendChart: ({ deviceId, measures, enableExportData, enableDatePicker, handleGetInfluxData,
|
10
|
+
declare const TrendChart: ({ deviceId, measures, enableExportData, enableDatePicker, handleGetInfluxData, theme }: {
|
10
11
|
deviceId: string;
|
11
12
|
measures: Array<Measure>;
|
12
13
|
enableenableExportData: boolean;
|
14
|
+
enableExportData: boolean;
|
13
15
|
enableDatePicker: boolean;
|
14
16
|
handleGetInfluxData: (measure: string, timeStart: number, timeEnd: number, deviceId: string, timeGroup: string, raw: boolean) => Promise<any>;
|
15
17
|
theme: Theme;
|
16
|
-
}
|
18
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
17
19
|
export default TrendChart;
|
@@ -18,6 +18,8 @@ import 'moment/locale/it';
|
|
18
18
|
// import 'moment/locale/en-gb'; // TODO set locale based on browser
|
19
19
|
import { AdapterMoment } from '@mui/x-date-pickers/AdapterMoment';
|
20
20
|
import { ThemeProvider } from '@mui/material/styles';
|
21
|
+
import TimelineIcon from '@mui/icons-material/Timeline';
|
22
|
+
import MuiTooltip from '@mui/material/Tooltip';
|
21
23
|
const lineOptions = {
|
22
24
|
parsing: false,
|
23
25
|
normalized: true,
|
@@ -35,7 +37,7 @@ const lineOptions = {
|
|
35
37
|
tooltip: {
|
36
38
|
callbacks: {
|
37
39
|
label: (context) => {
|
38
|
-
return `${context.dataset.label}: ${context.parsed.y.toFixed(
|
40
|
+
return `${context.dataset.label}: ${context.parsed.y.toFixed(3)} ${context.dataset.unit}`;
|
39
41
|
}
|
40
42
|
},
|
41
43
|
},
|
@@ -74,15 +76,7 @@ const lineOptions = {
|
|
74
76
|
drawOnChartArea: false,
|
75
77
|
}
|
76
78
|
},
|
77
|
-
y: {
|
78
|
-
ticks: {
|
79
|
-
callback: function (value) {
|
80
|
-
if (Math.floor(value) === value) {
|
81
|
-
return value;
|
82
|
-
}
|
83
|
-
}
|
84
|
-
}
|
85
|
-
},
|
79
|
+
y: {},
|
86
80
|
},
|
87
81
|
};
|
88
82
|
const chartConfigByPeriod = {
|
@@ -119,7 +113,7 @@ const chartConfigByPeriod = {
|
|
119
113
|
scaleUnit: 'year',
|
120
114
|
}
|
121
115
|
};
|
122
|
-
function
|
116
|
+
function getChartPoints(data) {
|
123
117
|
const points = data.results[0].series[0].values.map((row) => {
|
124
118
|
return {
|
125
119
|
x: moment.unix(row[0]),
|
@@ -160,8 +154,11 @@ function getCsvData(data, measures) {
|
|
160
154
|
});
|
161
155
|
});
|
162
156
|
});
|
163
|
-
//
|
164
|
-
Object.
|
157
|
+
// Sort timestamps in ascending order
|
158
|
+
const sortedTimestamps = Object.keys(timestampMap).sort((a, b) => new Date(a).getTime() - new Date(b).getTime());
|
159
|
+
// Create rows from sorted timestampMap
|
160
|
+
sortedTimestamps.forEach(timestamp => {
|
161
|
+
const entry = timestampMap[timestamp];
|
165
162
|
const row = [entry.timestamp];
|
166
163
|
measures.forEach(measure => {
|
167
164
|
// Push the corresponding value or an empty string if undefined
|
@@ -169,7 +166,7 @@ function getCsvData(data, measures) {
|
|
169
166
|
});
|
170
167
|
// Check if the row contains only empty values (besides the timestamp)
|
171
168
|
const hasNonEmptyValues = row.slice(1).some(value => value !== null && value !== '' && value !== undefined);
|
172
|
-
// If the row has at least one non-empty value
|
169
|
+
// If the row has at least one non-empty value, add it to csvData
|
173
170
|
if (hasNonEmptyValues || row.length === 1) {
|
174
171
|
csvData.push(row);
|
175
172
|
}
|
@@ -178,19 +175,22 @@ function getCsvData(data, measures) {
|
|
178
175
|
return csvData.map(row => row.join(',')).join('\n');
|
179
176
|
}
|
180
177
|
// eslint-disable-next-line no-unused-vars
|
181
|
-
const TrendChart = ({ deviceId, measures, enableExportData, enableDatePicker, handleGetInfluxData,
|
178
|
+
const TrendChart = ({ deviceId, measures, enableExportData, enableDatePicker, handleGetInfluxData, theme }) => {
|
182
179
|
const [chartJsLoaded, setChartJsLoaded] = useState(false);
|
183
180
|
const [dataMeasures, setDataMeasures] = useState(null);
|
184
181
|
const [chartPeriod, setChartPeriod] = useState('1D');
|
185
182
|
const [chartPeriodConfig, setChartPeriodConfig] = useState(chartConfigByPeriod['1D']);
|
186
183
|
const [chartLoading, setChartLoading] = useState(false);
|
184
|
+
const [timeStartPicker, setTimeStartPicker] = useState(moment().subtract(1, 'day').unix());
|
187
185
|
const [timeStart, setTimeStart] = useState(moment().subtract(1, 'day').unix());
|
188
186
|
const [timeEnd, setTimeEnd] = useState(moment().unix());
|
189
|
-
const [firstTimestamp, setFirstTimestamp] = useState();
|
190
187
|
const [datePickerUsed, setDatePickerUsed] = useState(false);
|
188
|
+
const [pickerTimeStart, setPickerTimeStart] = useState(moment().subtract(1, 'day').unix());
|
189
|
+
const [pickerTimeEnd, setPickerTimeEnd] = useState(moment().unix());
|
191
190
|
const [loadingButton, setLoadingButton] = useState(false);
|
192
191
|
const csvLinkRef = useRef(null);
|
193
192
|
const [csvData, setCsvData] = useState('');
|
193
|
+
const [spanGapsOption, setSpanGapsOption] = useState(true);
|
194
194
|
const [options, setOptions] = useState({
|
195
195
|
...lineOptions,
|
196
196
|
plugins: {
|
@@ -214,6 +214,7 @@ const TrendChart = ({ deviceId, measures, enableExportData, enableDatePicker, ha
|
|
214
214
|
}
|
215
215
|
});
|
216
216
|
const [zoomed, setZoomed] = useState(false);
|
217
|
+
const prevMeasures = useRef();
|
217
218
|
const resetChart = () => {
|
218
219
|
setOptions({
|
219
220
|
...options,
|
@@ -229,12 +230,20 @@ const TrendChart = ({ deviceId, measures, enableExportData, enableDatePicker, ha
|
|
229
230
|
setDataMeasures([...[]]);
|
230
231
|
setCsvData("");
|
231
232
|
};
|
233
|
+
const handleSpanGaps = (spanG) => {
|
234
|
+
setOptions({
|
235
|
+
...options,
|
236
|
+
spanGaps: spanG,
|
237
|
+
});
|
238
|
+
setSpanGapsOption(spanG);
|
239
|
+
};
|
232
240
|
const handleChange = (event, newPeriod) => {
|
241
|
+
setChartLoading(true);
|
233
242
|
setZoomed(false);
|
234
243
|
setDatePickerUsed(false);
|
235
244
|
setCsvData('');
|
236
245
|
if (newPeriod === "ALL") {
|
237
|
-
setTimeStart(
|
246
|
+
setTimeStart(1577854800);
|
238
247
|
setTimeEnd(moment().unix());
|
239
248
|
setChartPeriod(newPeriod);
|
240
249
|
return;
|
@@ -249,10 +258,8 @@ const TrendChart = ({ deviceId, measures, enableExportData, enableDatePicker, ha
|
|
249
258
|
};
|
250
259
|
const handleExportData = async () => {
|
251
260
|
setLoadingButton(true);
|
252
|
-
const intervalInSeconds = timeEnd - timeStart;
|
253
261
|
const data = await Promise.all(measures.map(async (measure) => {
|
254
|
-
|
255
|
-
return await handleGetInfluxData(measure.name, timeStart, timeEnd, deviceId, polltime, true);
|
262
|
+
return await handleGetInfluxData(measure.name, timeStart, timeEnd, deviceId, "0s", true);
|
256
263
|
}));
|
257
264
|
const csvData = getCsvData(data, measures);
|
258
265
|
setCsvData(csvData);
|
@@ -264,23 +271,23 @@ const TrendChart = ({ deviceId, measures, enableExportData, enableDatePicker, ha
|
|
264
271
|
}
|
265
272
|
}, [csvData]);
|
266
273
|
const loadDatasets = async (chartPeriod) => {
|
267
|
-
|
268
|
-
const
|
274
|
+
let intervalInSeconds = chartPeriod === "ALL" && !datePickerUsed && !zoomed ? 31536000 : timeEnd - timeStart;
|
275
|
+
const rawQuery = intervalInSeconds < 86400; //
|
269
276
|
// Inizializza un array di promesse per ottenere i dati per ciascuna misura
|
270
277
|
const datasetsPromises = measures.map(async (measure) => {
|
271
|
-
const polltime = getPollTime(intervalInSeconds, measure.polltime);
|
272
|
-
const influxData = await handleGetInfluxData(measure.name, timeStart, timeEnd, deviceId, polltime,
|
273
|
-
const points =
|
278
|
+
const polltime = getPollTime(intervalInSeconds, measure.polltime || 30);
|
279
|
+
const influxData = await handleGetInfluxData(measure.name, timeStart, timeEnd, deviceId, polltime, !measure.polltime && rawQuery);
|
280
|
+
const points = getChartPoints(influxData);
|
274
281
|
return {
|
275
282
|
label: measure.name,
|
276
283
|
data: points,
|
277
284
|
unit: measure.unit,
|
278
|
-
// borderColor: `hsl(${index * 50}, 70%, 50%)`, // Colore unico per ogni dataset
|
279
285
|
borderWidth: 2,
|
280
286
|
pointRadius: 1,
|
281
287
|
pointHoverRadius: 5,
|
282
288
|
pointHoverBackgroundColor: 'rgba(52, 125, 236, 0.5)',
|
283
|
-
|
289
|
+
change: !measure.polltime,
|
290
|
+
stepped: measure.stepped,
|
284
291
|
fill: false
|
285
292
|
};
|
286
293
|
});
|
@@ -288,24 +295,31 @@ const TrendChart = ({ deviceId, measures, enableExportData, enableDatePicker, ha
|
|
288
295
|
const datasets = await Promise.all(datasetsPromises);
|
289
296
|
let min = null;
|
290
297
|
let max = null;
|
291
|
-
let
|
298
|
+
let time;
|
299
|
+
let minTime = null;
|
292
300
|
datasets.forEach(dataset => {
|
293
|
-
values =
|
301
|
+
const values = dataset.data.map((point) => point.y).filter((data) => data !== null);
|
302
|
+
if (chartPeriod === "ALL" && !datePickerUsed && !zoomed && values.length) {
|
303
|
+
time = dataset.data.filter((data) => data.y !== null).map((data) => data.x)[0];
|
304
|
+
}
|
294
305
|
const datasetMin = Math.min(...values);
|
295
306
|
const datasetMax = Math.max(...values);
|
296
307
|
if (min === null || datasetMin < min)
|
297
308
|
min = datasetMin;
|
298
309
|
if (max === null || datasetMax > max)
|
299
310
|
max = datasetMax;
|
311
|
+
if (time && (minTime === null || time.unix() < minTime))
|
312
|
+
minTime = time.unix() - 86400;
|
300
313
|
});
|
301
314
|
let paddedMin = null;
|
302
315
|
let paddedMax = null;
|
303
316
|
if (min !== null && max !== null) {
|
304
|
-
const diff =
|
305
|
-
paddedMin = min - diff;
|
306
|
-
paddedMax = max + diff;
|
317
|
+
const diff = ((max - min) * 0.2) < 0.1 ? 0.1 : (max - min) * 0.2;
|
318
|
+
paddedMin = Math.floor((min - diff) * 10) / 10;
|
319
|
+
paddedMax = Math.ceil((max + diff) * 10) / 10;
|
307
320
|
}
|
308
321
|
setDataMeasures([...datasets]);
|
322
|
+
setTimeStartPicker(minTime || timeStart);
|
309
323
|
setOptions({
|
310
324
|
...options,
|
311
325
|
scales: {
|
@@ -317,27 +331,14 @@ const TrendChart = ({ deviceId, measures, enableExportData, enableDatePicker, ha
|
|
317
331
|
},
|
318
332
|
x: {
|
319
333
|
...options.scales.x,
|
320
|
-
min: moment.unix(timeStart).toString(),
|
321
|
-
max: moment.unix(timeEnd).toString()
|
322
|
-
time: {
|
323
|
-
...options.scales.x.time,
|
324
|
-
unit: chartPeriod.scaleUnit
|
325
|
-
}
|
334
|
+
min: moment.unix(minTime || timeStart).toString(),
|
335
|
+
max: moment.unix(timeEnd).toString()
|
326
336
|
}
|
327
337
|
}
|
328
338
|
});
|
329
339
|
};
|
330
340
|
useEffect(() => {
|
331
|
-
const
|
332
|
-
const response = await handleGetFirstTimestamp(deviceId);
|
333
|
-
if (response) {
|
334
|
-
setFirstTimestamp(response);
|
335
|
-
}
|
336
|
-
};
|
337
|
-
fetchFirstTimestamp();
|
338
|
-
}, []);
|
339
|
-
useEffect(() => {
|
340
|
-
const timeDifference = Math.abs(moment(timeStart).valueOf() - moment(timeEnd).valueOf()); // Convert milliseconds to seconds
|
341
|
+
const timeDifference = Math.abs(moment(timeEnd).valueOf() - moment(timeStart).valueOf()); // Convert milliseconds to seconds
|
341
342
|
let newChartPeriod = '1D'; // Default to 1 day
|
342
343
|
if (timeDifference < 86400) { // Less than 1 day
|
343
344
|
newChartPeriod = '1H'; // Set to 1 day
|
@@ -345,26 +346,34 @@ const TrendChart = ({ deviceId, measures, enableExportData, enableDatePicker, ha
|
|
345
346
|
else if (timeDifference < 604800) { // Less than 1 week
|
346
347
|
newChartPeriod = '1D'; // Set to 1 day
|
347
348
|
}
|
348
|
-
else if (timeDifference <
|
349
|
+
else if (timeDifference < 2678400) { // Less than 1 month
|
349
350
|
newChartPeriod = '1W'; // Set to 1 week
|
350
351
|
}
|
351
|
-
else if (timeDifference <
|
352
|
+
else if (timeDifference < 8035200) { // Less than 3 months
|
352
353
|
newChartPeriod = '1M'; // Set to 1 month
|
353
354
|
}
|
354
|
-
else if (timeDifference <
|
355
|
+
else if (timeDifference < 16070400) { // Less than 6 months
|
355
356
|
newChartPeriod = '3M'; // Set to 3 months
|
356
357
|
}
|
357
|
-
else if (timeDifference <
|
358
|
+
else if (timeDifference < 31536000) { // Less than 1 year
|
358
359
|
newChartPeriod = '6M'; // Set to 6 months
|
359
360
|
}
|
360
361
|
else {
|
361
362
|
newChartPeriod = '1Y'; // Set to 1 year
|
362
363
|
}
|
363
364
|
setChartPeriodConfig(chartConfigByPeriod[newChartPeriod]);
|
365
|
+
// check prev measures value in order to show the loader
|
366
|
+
// hide the loader if measure is the same (for interval get measure value)
|
367
|
+
const prevMeasuresValue = prevMeasures.current || [];
|
368
|
+
//@ts-ignore
|
369
|
+
prevMeasures.current = measures;
|
370
|
+
if (!prevMeasuresValue || prevMeasuresValue.length !== measures.length || (prevMeasuresValue[0] && prevMeasuresValue[0].name !== measures[0].name)) {
|
371
|
+
setChartLoading(true);
|
372
|
+
}
|
364
373
|
loadDatasets(chartPeriod).then(() => {
|
365
374
|
setChartLoading(false);
|
366
375
|
});
|
367
|
-
}, [timeEnd, timeStart]);
|
376
|
+
}, [measures, timeEnd, timeStart]);
|
368
377
|
useEffect(() => {
|
369
378
|
const loadZoomPlugin = async () => {
|
370
379
|
const zoomPlugin = (await import('chartjs-plugin-zoom')).default;
|
@@ -393,34 +402,41 @@ const TrendChart = ({ deviceId, measures, enableExportData, enableDatePicker, ha
|
|
393
402
|
loadZoomPlugin();
|
394
403
|
resetChart();
|
395
404
|
}, []);
|
396
|
-
const datePicker = _jsx(Box, { sx: { display: 'flex', alignItems: 'center', mr: { xs: 0, lg: 2 } }, children: _jsxs(LocalizationProvider, { dateAdapter: AdapterMoment, adapterLocale: "it", children: [_jsx(DateTimePicker, { value: moment(
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
405
|
+
const datePicker = _jsx(Box, { sx: { display: 'flex', alignItems: 'center', mr: { xs: 0, lg: 2 } }, children: _jsxs(LocalizationProvider, { dateAdapter: AdapterMoment, adapterLocale: "it", children: [_jsx(DateTimePicker, { value: moment(timeStartPicker * 1000), onChange: (newValue) => {
|
406
|
+
setChartLoading(true);
|
407
|
+
setDatePickerUsed(true);
|
408
|
+
setZoomed(false);
|
409
|
+
setPickerTimeStart(moment(newValue).unix());
|
410
|
+
setTimeStart(moment(newValue).unix());
|
411
|
+
}, maxDateTime: moment(timeEnd * 1000), slotProps: {
|
401
412
|
textField: { size: 'small', sx: { width: { sm: 210 } } }
|
402
|
-
} }), " \u00A0\u00A0 ", _jsx(Box, { children: "\u2013" }), " \u00A0\u00A0", _jsx(DateTimePicker, { value: moment(timeEnd * 1000),
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
413
|
+
} }), " \u00A0\u00A0 ", _jsx(Box, { children: "\u2013" }), " \u00A0\u00A0", _jsx(DateTimePicker, { value: moment(timeEnd * 1000), onChange: (newValue) => {
|
414
|
+
setChartLoading(true);
|
415
|
+
setDatePickerUsed(true);
|
416
|
+
setZoomed(false);
|
417
|
+
setPickerTimeEnd(moment(newValue).unix());
|
418
|
+
setTimeEnd(moment(newValue).unix());
|
419
|
+
}, minDateTime: moment(timeStart * 1000), slotProps: {
|
407
420
|
textField: { size: 'small', sx: { width: { sm: 210 } } }
|
408
421
|
} })] }) });
|
409
|
-
return (_jsxs(ThemeProvider, { theme: theme, children: [enableDatePicker && _jsx(Box, { sx: { display: { xs: 'flex', lg: 'none', justifyContent: 'flex-end' }, mb: 2 }, children: datePicker }), _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', justifyContent: 'space-between' }, children: [_jsxs(Box, { children: [enableExportData && (_jsxs(_Fragment, { children: [_jsxs(LoadingButton, { sx: { minWidth: '40px !important', mr: 1, px: 1 }, loading: loadingButton, type: "submit", variant: "text", color: "primary", onClick: handleExportData, disabled: !dataMeasures || !dataMeasures.length, size: 'small', children: [_jsx(LoginIcon, { fontSize: 'small', style: { transform: "rotate(90deg)" } }), _jsx(Box, { sx: { display: { xs: 'none', xl: 'block' }, ml: { md: 1 } }, children: "Export" })] }), _jsx(CSVLink
|
422
|
+
return (_jsxs(ThemeProvider, { theme: theme, children: [enableDatePicker && _jsx(Box, { sx: { display: { xs: 'flex', lg: 'none', justifyContent: 'flex-end' }, mb: 2 }, children: datePicker }), _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', justifyContent: 'space-between' }, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center' }, children: [!enableExportData && measures && measures.length === 1 ? _jsx(Typography, { variant: 'body1', sx: { mr: 2 }, children: measures[0].name }) : '', enableExportData && (_jsxs(_Fragment, { children: [_jsxs(LoadingButton, { sx: { minWidth: '40px !important', mr: 1, px: 1 }, loading: loadingButton, type: "submit", variant: "text", color: "primary", onClick: handleExportData, disabled: !dataMeasures || !dataMeasures.length, size: 'small', children: [_jsx(LoginIcon, { fontSize: 'small', style: { transform: "rotate(90deg)" } }), _jsx(Box, { sx: { display: { xs: 'none', xl: 'block' }, ml: { md: 1 } }, children: "Export" })] }), _jsx(CSVLink
|
410
423
|
//@ts-ignore
|
411
424
|
, {
|
412
425
|
//@ts-ignore
|
413
426
|
ref: csvLinkRef, data: csvData, filename: `export_${moment().toISOString()}.csv`, separator: ';' })] })), zoomed && (_jsxs(Button, { sx: { minWidth: '40px !important', boxShadow: 1, px: 1 }, variant: "contained", color: "secondary", size: 'small', onClick: () => {
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
427
|
+
setChartLoading(true);
|
428
|
+
setZoomed(false);
|
429
|
+
if (chartPeriod === "ALL") {
|
430
|
+
setDatePickerUsed(false);
|
431
|
+
setTimeStart(1577854800);
|
419
432
|
setTimeEnd(moment().unix());
|
420
|
-
|
433
|
+
}
|
434
|
+
else if (datePickerUsed) {
|
435
|
+
setTimeStart(pickerTimeStart);
|
436
|
+
setTimeEnd(pickerTimeEnd);
|
421
437
|
}
|
422
438
|
else {
|
423
|
-
|
439
|
+
setDatePickerUsed(false);
|
424
440
|
setChartPeriodConfig(chartConfigByPeriod[chartPeriod]);
|
425
441
|
setTimeStart(chartPeriodConfig.from?.days
|
426
442
|
? moment()
|
@@ -429,12 +445,13 @@ const TrendChart = ({ deviceId, measures, enableExportData, enableDatePicker, ha
|
|
429
445
|
: moment().subtract(1, 'day').unix());
|
430
446
|
setTimeEnd(moment().unix());
|
431
447
|
}
|
432
|
-
}, children: [_jsx(ZoomOut, { fontSize: 'small' }), _jsx(Box, { sx: { display: { xs: 'none',
|
448
|
+
}, children: [_jsx(ZoomOut, { fontSize: 'small' }), _jsx(Box, { sx: { display: { xs: 'none', lg: 'block' }, ml: { md: 1 } }, children: "Reset" })] }))] }), _jsxs(Box, { sx: { display: 'flex', justifyContent: 'flex-end' }, children: [enableDatePicker && _jsx(Box, { sx: { display: { xs: 'none', lg: 'flex' } }, children: datePicker }), _jsxs(ToggleButtonGroup, { color: "primary", value: !datePickerUsed && !zoomed ? chartPeriod : null, exclusive: true, onChange: handleChange, size: "small",
|
433
449
|
// sx={{ boxShadow: 1 }}
|
434
|
-
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" })] })
|
435
|
-
_jsx(_Fragment, { children: dataMeasures && dataMeasures[0]
|
450
|
+
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: 2 }, children: _jsx(TimelineIcon, {}) }) })] })] }), _jsx(Box, { component: 'div', className: "chart-container", sx: { mt: 2, height: '100%' }, children: chartJsLoaded && !chartLoading && typeof window !== 'undefined' ?
|
451
|
+
_jsx(_Fragment, { children: dataMeasures && (dataMeasures.length > 1 || (dataMeasures.length === 1 && dataMeasures[0].data?.length)) ?
|
436
452
|
(_jsx(Line, { options: options, data: {
|
437
|
-
datasets: dataMeasures || [{ data: [] }]
|
453
|
+
// datasets: dataMeasures || [{ data: [] }]
|
454
|
+
datasets: dataMeasures.map(d => ({ ...d, showLine: spanGapsOption || !d.change })) || [{ data: [] }]
|
438
455
|
} })) : _jsxs(Box, { sx: {
|
439
456
|
display: 'flex',
|
440
457
|
flexDirection: 'column',
|
@@ -448,7 +465,7 @@ const TrendChart = ({ deviceId, measures, enableExportData, enableDatePicker, ha
|
|
448
465
|
alignItems: 'center',
|
449
466
|
justifyContent: 'center',
|
450
467
|
textAlign: 'center',
|
451
|
-
height: '100%'
|
468
|
+
height: 'calc(100% - 50px)'
|
452
469
|
}, children: _jsx(CircularProgress, {}) })) })] }));
|
453
470
|
};
|
454
471
|
export default TrendChart;
|
@@ -14,7 +14,7 @@ declare const GroupsDevices: ({ userInfo, handleGetUsersList, handleAddUserToGro
|
|
14
14
|
handleGetGroups: (productID: number, userInfo?: UserType) => Promise<any>;
|
15
15
|
handleGetUsersGroup: (groupID: string) => Promise<any>;
|
16
16
|
handleCreateGroup: (group: any) => Promise<any>;
|
17
|
-
handleGetDevices: (user: UserType,
|
17
|
+
handleGetDevices: (user: UserType, query: string) => Promise<any>;
|
18
18
|
handleGetPositions: (devices: any) => Promise<any>;
|
19
19
|
handleAddDevicesToGroup: (user: UserType, group: string, devicesToPatch: any[]) => Promise<any>;
|
20
20
|
handleRemoveDevicesFromGroup: (user: UserType, group: string, devicesToPatch: any[]) => Promise<any>;
|
@@ -28,7 +28,7 @@ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, han
|
|
28
28
|
const [selectedGroup, setSelectedGroup] = useState(group);
|
29
29
|
const [groups, setGroups] = useState(null);
|
30
30
|
const [usersList, setUsersList] = useState([]);
|
31
|
-
const [usersGroup, setUsersGroup] = useState(
|
31
|
+
const [usersGroup, setUsersGroup] = useState(null);
|
32
32
|
const [groupInfo, setGroupInfo] = useState(null);
|
33
33
|
const [openAdd, setOpenAdd] = useState(false);
|
34
34
|
const [groupName, setGroupName] = useState('');
|
@@ -73,7 +73,20 @@ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, han
|
|
73
73
|
const fetchDevices = async (group, selected) => {
|
74
74
|
try {
|
75
75
|
setLoadingDevices(true);
|
76
|
-
|
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);
|
77
90
|
setDevices(devices);
|
78
91
|
if (enableMaps) {
|
79
92
|
const positions = await handleGetPositions(devices);
|
@@ -119,7 +132,9 @@ const GroupsDevices = ({ userInfo, handleGetUsersList, handleAddUserToGroup, han
|
|
119
132
|
if (currentGroup && !checkboxSelection) {
|
120
133
|
setSelectedGroup(currentGroup);
|
121
134
|
setGroupInfo(groups && groups.find((g) => g.id === currentGroup));
|
122
|
-
|
135
|
+
if (currentGroup !== 'all') {
|
136
|
+
getUsersGroup(currentGroup);
|
137
|
+
}
|
123
138
|
fetchDevices(currentGroup, currentGroup);
|
124
139
|
}
|
125
140
|
}, [currentGroup]);
|
package/package.json
CHANGED
@@ -13,7 +13,7 @@ export declare function createCustomer(trackleConfig: TrackleConfig, uid: string
|
|
13
13
|
organization: string;
|
14
14
|
uid: string;
|
15
15
|
}>;
|
16
|
-
export declare function getDevices(trackleConfig: TrackleConfig, productId?: number, uid?: string,
|
16
|
+
export declare function getDevices(trackleConfig: TrackleConfig, productId?: number, uid?: string, query?: string): Promise<{
|
17
17
|
devices: any[];
|
18
18
|
}>;
|
19
19
|
export declare function getDevice(trackleConfig: TrackleConfig, id: string, productId?: number, uid?: string): Promise<{
|
@@ -55,25 +55,12 @@ export async function createCustomer(trackleConfig, uid) {
|
|
55
55
|
.post({ uid })
|
56
56
|
.json();
|
57
57
|
}
|
58
|
-
export async function getDevices(trackleConfig, productId, uid,
|
59
|
-
let queryParams = "last_handshake_at!=null";
|
60
|
-
if (group !== "all") {
|
61
|
-
queryParams = `last_handshake_at!=null&state.groups=/${group}/`;
|
62
|
-
if (!uid) {
|
63
|
-
queryParams += "&quarantined=false";
|
64
|
-
}
|
65
|
-
}
|
66
|
-
else if (selected !== "all") {
|
67
|
-
queryParams = `last_handshake_at!=null&state.groups!=/${selected}/`;
|
68
|
-
if (!uid) {
|
69
|
-
queryParams += "&quarantined=false";
|
70
|
-
}
|
71
|
-
}
|
58
|
+
export async function getDevices(trackleConfig, productId, uid, query) {
|
72
59
|
const api = uid ? wretchApi(trackleConfig, uid) : wretchApi(trackleConfig);
|
73
60
|
const response = await api
|
74
61
|
.get(uid
|
75
|
-
? `/devices
|
76
|
-
: `/products/${productId}/devices
|
62
|
+
? `/devices${query ? "?" + query : ""}`
|
63
|
+
: `/products/${productId}/devices${query ? "?" + query : ""}`)
|
77
64
|
.setTimeout(trackleConfig.apiTimeout)
|
78
65
|
.json();
|
79
66
|
return (uid ? { devices: response } : response);
|