@iotready/nextjs-components-library 1.0.0-preview3 → 1.0.0-preview5
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.
@@ -6,7 +6,7 @@ type Measure = {
|
|
6
6
|
polltime: number;
|
7
7
|
unit: string;
|
8
8
|
};
|
9
|
-
declare const TrendChart: ({ deviceId, measures, enableExportData, enableDatePicker, handleGetInfluxData,
|
9
|
+
declare const TrendChart: ({ deviceId, measures, enableExportData, enableDatePicker, handleGetInfluxData, theme, ...props }: {
|
10
10
|
deviceId: string;
|
11
11
|
measures: Array<Measure>;
|
12
12
|
enableenableExportData: boolean;
|
@@ -37,7 +37,7 @@ const lineOptions = {
|
|
37
37
|
tooltip: {
|
38
38
|
callbacks: {
|
39
39
|
label: (context) => {
|
40
|
-
return `${context.dataset.label}: ${context.parsed.y.toFixed(
|
40
|
+
return `${context.dataset.label}: ${context.parsed.y.toFixed(3)} ${context.dataset.unit}`;
|
41
41
|
}
|
42
42
|
},
|
43
43
|
},
|
@@ -162,8 +162,11 @@ function getCsvData(data, measures) {
|
|
162
162
|
});
|
163
163
|
});
|
164
164
|
});
|
165
|
-
//
|
166
|
-
Object.
|
165
|
+
// Sort timestamps in ascending order
|
166
|
+
const sortedTimestamps = Object.keys(timestampMap).sort((a, b) => new Date(a).getTime() - new Date(b).getTime());
|
167
|
+
// Create rows from sorted timestampMap
|
168
|
+
sortedTimestamps.forEach(timestamp => {
|
169
|
+
const entry = timestampMap[timestamp];
|
167
170
|
const row = [entry.timestamp];
|
168
171
|
measures.forEach(measure => {
|
169
172
|
// Push the corresponding value or an empty string if undefined
|
@@ -171,7 +174,7 @@ function getCsvData(data, measures) {
|
|
171
174
|
});
|
172
175
|
// Check if the row contains only empty values (besides the timestamp)
|
173
176
|
const hasNonEmptyValues = row.slice(1).some(value => value !== null && value !== '' && value !== undefined);
|
174
|
-
// If the row has at least one non-empty value
|
177
|
+
// If the row has at least one non-empty value, add it to csvData
|
175
178
|
if (hasNonEmptyValues || row.length === 1) {
|
176
179
|
csvData.push(row);
|
177
180
|
}
|
@@ -180,16 +183,18 @@ function getCsvData(data, measures) {
|
|
180
183
|
return csvData.map(row => row.join(',')).join('\n');
|
181
184
|
}
|
182
185
|
// eslint-disable-next-line no-unused-vars
|
183
|
-
const TrendChart = ({ deviceId, measures, enableExportData, enableDatePicker, handleGetInfluxData,
|
186
|
+
const TrendChart = ({ deviceId, measures, enableExportData, enableDatePicker, handleGetInfluxData, theme, ...props }) => {
|
184
187
|
const [chartJsLoaded, setChartJsLoaded] = useState(false);
|
185
188
|
const [dataMeasures, setDataMeasures] = useState(null);
|
186
189
|
const [chartPeriod, setChartPeriod] = useState('1D');
|
187
190
|
const [chartPeriodConfig, setChartPeriodConfig] = useState(chartConfigByPeriod['1D']);
|
188
191
|
const [chartLoading, setChartLoading] = useState(false);
|
192
|
+
const [timeStartPicker, setTimeStartPicker] = useState(moment().subtract(1, 'day').unix());
|
189
193
|
const [timeStart, setTimeStart] = useState(moment().subtract(1, 'day').unix());
|
190
194
|
const [timeEnd, setTimeEnd] = useState(moment().unix());
|
191
|
-
const [firstTimestamp, setFirstTimestamp] = useState();
|
192
195
|
const [datePickerUsed, setDatePickerUsed] = useState(false);
|
196
|
+
const [pickerTimeStart, setPickerTimeStart] = useState(moment().subtract(1, 'day').unix());
|
197
|
+
const [pickerTimeEnd, setPickerTimeEnd] = useState(moment().unix());
|
193
198
|
const [loadingButton, setLoadingButton] = useState(false);
|
194
199
|
const csvLinkRef = useRef(null);
|
195
200
|
const [csvData, setCsvData] = useState('');
|
@@ -244,7 +249,7 @@ const TrendChart = ({ deviceId, measures, enableExportData, enableDatePicker, ha
|
|
244
249
|
setDatePickerUsed(false);
|
245
250
|
setCsvData('');
|
246
251
|
if (newPeriod === "ALL") {
|
247
|
-
setTimeStart(
|
252
|
+
setTimeStart(1577854800);
|
248
253
|
setTimeEnd(moment().unix());
|
249
254
|
setChartPeriod(newPeriod);
|
250
255
|
return;
|
@@ -259,10 +264,8 @@ const TrendChart = ({ deviceId, measures, enableExportData, enableDatePicker, ha
|
|
259
264
|
};
|
260
265
|
const handleExportData = async () => {
|
261
266
|
setLoadingButton(true);
|
262
|
-
const intervalInSeconds = timeEnd - timeStart;
|
263
267
|
const data = await Promise.all(measures.map(async (measure) => {
|
264
|
-
|
265
|
-
return await handleGetInfluxData(measure.name, timeStart, timeEnd, deviceId, polltime, true);
|
268
|
+
return await handleGetInfluxData(measure.name, timeStart, timeEnd, deviceId, "0s", true);
|
266
269
|
}));
|
267
270
|
const csvData = getCsvData(data, measures);
|
268
271
|
setCsvData(csvData);
|
@@ -275,22 +278,22 @@ const TrendChart = ({ deviceId, measures, enableExportData, enableDatePicker, ha
|
|
275
278
|
}, [csvData]);
|
276
279
|
const loadDatasets = async (chartPeriod) => {
|
277
280
|
setChartLoading(true);
|
278
|
-
|
281
|
+
let intervalInSeconds = chartPeriod === "ALL" && !datePickerUsed && !zoomed ? 31536000 : timeEnd - timeStart;
|
282
|
+
const rawQuery = intervalInSeconds < 86400; //
|
279
283
|
// Inizializza un array di promesse per ottenere i dati per ciascuna misura
|
280
284
|
const datasetsPromises = measures.map(async (measure) => {
|
281
|
-
const polltime = getPollTime(intervalInSeconds, measure.polltime);
|
282
|
-
const influxData = await handleGetInfluxData(measure.name, timeStart, timeEnd, deviceId, polltime,
|
285
|
+
const polltime = getPollTime(intervalInSeconds, measure.polltime || 30);
|
286
|
+
const influxData = await handleGetInfluxData(measure.name, timeStart, timeEnd, deviceId, polltime, !measure.polltime && rawQuery);
|
283
287
|
const points = GetPoints(influxData);
|
284
288
|
return {
|
285
289
|
label: measure.name,
|
286
290
|
data: points,
|
287
291
|
unit: measure.unit,
|
288
|
-
// borderColor: `hsl(${index * 50}, 70%, 50%)`, // Colore unico per ogni dataset
|
289
292
|
borderWidth: 2,
|
290
293
|
pointRadius: 1,
|
291
294
|
pointHoverRadius: 5,
|
292
295
|
pointHoverBackgroundColor: 'rgba(52, 125, 236, 0.5)',
|
293
|
-
//
|
296
|
+
// showLine: measure.polltime ? true : false, //<- set this
|
294
297
|
fill: false
|
295
298
|
};
|
296
299
|
});
|
@@ -298,15 +301,21 @@ const TrendChart = ({ deviceId, measures, enableExportData, enableDatePicker, ha
|
|
298
301
|
const datasets = await Promise.all(datasetsPromises);
|
299
302
|
let min = null;
|
300
303
|
let max = null;
|
301
|
-
let
|
304
|
+
let time;
|
305
|
+
let minTime = null;
|
302
306
|
datasets.forEach(dataset => {
|
303
|
-
values =
|
307
|
+
const values = dataset.data.map((point) => point.y).filter((data) => data !== null);
|
308
|
+
if (chartPeriod === "ALL" && !datePickerUsed && !zoomed && values.length) {
|
309
|
+
time = dataset.data.filter((data) => data.y !== null).map((data) => data.x)[0];
|
310
|
+
}
|
304
311
|
const datasetMin = Math.min(...values);
|
305
312
|
const datasetMax = Math.max(...values);
|
306
313
|
if (min === null || datasetMin < min)
|
307
314
|
min = datasetMin;
|
308
315
|
if (max === null || datasetMax > max)
|
309
316
|
max = datasetMax;
|
317
|
+
if (time && (minTime === null || time.unix() < minTime))
|
318
|
+
minTime = time.unix() - 86400;
|
310
319
|
});
|
311
320
|
let paddedMin = null;
|
312
321
|
let paddedMax = null;
|
@@ -316,6 +325,7 @@ const TrendChart = ({ deviceId, measures, enableExportData, enableDatePicker, ha
|
|
316
325
|
paddedMax = max + diff;
|
317
326
|
}
|
318
327
|
setDataMeasures([...datasets]);
|
328
|
+
setTimeStartPicker(minTime || timeStart);
|
319
329
|
setOptions({
|
320
330
|
...options,
|
321
331
|
scales: {
|
@@ -327,27 +337,14 @@ const TrendChart = ({ deviceId, measures, enableExportData, enableDatePicker, ha
|
|
327
337
|
},
|
328
338
|
x: {
|
329
339
|
...options.scales.x,
|
330
|
-
min: moment.unix(timeStart).toString(),
|
331
|
-
max: moment.unix(timeEnd).toString()
|
332
|
-
time: {
|
333
|
-
...options.scales.x.time,
|
334
|
-
unit: chartPeriod.scaleUnit
|
335
|
-
}
|
340
|
+
min: moment.unix(minTime || timeStart).toString(),
|
341
|
+
max: moment.unix(timeEnd).toString()
|
336
342
|
}
|
337
343
|
}
|
338
344
|
});
|
339
345
|
};
|
340
346
|
useEffect(() => {
|
341
|
-
const
|
342
|
-
const response = await handleGetFirstTimestamp(deviceId);
|
343
|
-
if (response) {
|
344
|
-
setFirstTimestamp(response);
|
345
|
-
}
|
346
|
-
};
|
347
|
-
fetchFirstTimestamp();
|
348
|
-
}, []);
|
349
|
-
useEffect(() => {
|
350
|
-
const timeDifference = Math.abs(moment(timeStart).valueOf() - moment(timeEnd).valueOf()); // Convert milliseconds to seconds
|
347
|
+
const timeDifference = Math.abs(moment(timeEnd).valueOf() - moment(timeStart).valueOf()); // Convert milliseconds to seconds
|
351
348
|
let newChartPeriod = '1D'; // Default to 1 day
|
352
349
|
if (timeDifference < 86400) { // Less than 1 day
|
353
350
|
newChartPeriod = '1H'; // Set to 1 day
|
@@ -355,16 +352,16 @@ const TrendChart = ({ deviceId, measures, enableExportData, enableDatePicker, ha
|
|
355
352
|
else if (timeDifference < 604800) { // Less than 1 week
|
356
353
|
newChartPeriod = '1D'; // Set to 1 day
|
357
354
|
}
|
358
|
-
else if (timeDifference <
|
355
|
+
else if (timeDifference < 2678400) { // Less than 1 month
|
359
356
|
newChartPeriod = '1W'; // Set to 1 week
|
360
357
|
}
|
361
|
-
else if (timeDifference <
|
358
|
+
else if (timeDifference < 8035200) { // Less than 3 months
|
362
359
|
newChartPeriod = '1M'; // Set to 1 month
|
363
360
|
}
|
364
|
-
else if (timeDifference <
|
361
|
+
else if (timeDifference < 16070400) { // Less than 6 months
|
365
362
|
newChartPeriod = '3M'; // Set to 3 months
|
366
363
|
}
|
367
|
-
else if (timeDifference <
|
364
|
+
else if (timeDifference < 31536000) { // Less than 1 year
|
368
365
|
newChartPeriod = '6M'; // Set to 6 months
|
369
366
|
}
|
370
367
|
else {
|
@@ -403,16 +400,18 @@ const TrendChart = ({ deviceId, measures, enableExportData, enableDatePicker, ha
|
|
403
400
|
loadZoomPlugin();
|
404
401
|
resetChart();
|
405
402
|
}, []);
|
406
|
-
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(
|
407
|
-
|
408
|
-
|
409
|
-
|
403
|
+
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) => {
|
404
|
+
setDatePickerUsed(true);
|
405
|
+
setZoomed(false);
|
406
|
+
setPickerTimeStart(moment(newValue).unix());
|
407
|
+
setTimeStart(moment(newValue).unix());
|
410
408
|
}, maxDateTime: moment(timeEnd * 1000), slotProps: {
|
411
409
|
textField: { size: 'small', sx: { width: { sm: 210 } } }
|
412
|
-
} }), " \u00A0\u00A0 ", _jsx(Box, { children: "\u2013" }), " \u00A0\u00A0", _jsx(DateTimePicker, { value: moment(timeEnd * 1000),
|
413
|
-
|
414
|
-
|
415
|
-
|
410
|
+
} }), " \u00A0\u00A0 ", _jsx(Box, { children: "\u2013" }), " \u00A0\u00A0", _jsx(DateTimePicker, { value: moment(timeEnd * 1000), onChange: (newValue) => {
|
411
|
+
setDatePickerUsed(true);
|
412
|
+
setZoomed(false);
|
413
|
+
setPickerTimeEnd(moment(newValue).unix());
|
414
|
+
setTimeEnd(moment(newValue).unix());
|
416
415
|
}, minDateTime: moment(timeStart * 1000), slotProps: {
|
417
416
|
textField: { size: 'small', sx: { width: { sm: 210 } } }
|
418
417
|
} })] }) });
|
@@ -421,16 +420,18 @@ const TrendChart = ({ deviceId, measures, enableExportData, enableDatePicker, ha
|
|
421
420
|
, {
|
422
421
|
//@ts-ignore
|
423
422
|
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: () => {
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
setZoomed(false);
|
423
|
+
setZoomed(false);
|
424
|
+
if (chartPeriod === "ALL") {
|
425
|
+
setDatePickerUsed(false);
|
426
|
+
setTimeStart(1577854800);
|
429
427
|
setTimeEnd(moment().unix());
|
430
|
-
|
428
|
+
}
|
429
|
+
else if (datePickerUsed) {
|
430
|
+
setTimeStart(pickerTimeStart);
|
431
|
+
setTimeEnd(pickerTimeEnd);
|
431
432
|
}
|
432
433
|
else {
|
433
|
-
|
434
|
+
setDatePickerUsed(false);
|
434
435
|
setChartPeriodConfig(chartConfigByPeriod[chartPeriod]);
|
435
436
|
setTimeStart(chartPeriodConfig.from?.days
|
436
437
|
? moment()
|
@@ -439,7 +440,7 @@ const TrendChart = ({ deviceId, measures, enableExportData, enableDatePicker, ha
|
|
439
440
|
: moment().subtract(1, 'day').unix());
|
440
441
|
setTimeEnd(moment().unix());
|
441
442
|
}
|
442
|
-
}, children: [_jsx(ZoomOut, { fontSize: 'small' }), _jsx(Box, { sx: { display: { xs: 'none',
|
443
|
+
}, 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",
|
443
444
|
// sx={{ boxShadow: 1 }}
|
444
445
|
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: { height: { xs: enableDatePicker && props.height ? `calc(${props.height} - 50px)` : props.height, lg: props.height }, minHeight: 300, mt: 2 }, children: chartJsLoaded && !chartLoading && typeof window !== 'undefined' ?
|
445
446
|
_jsx(_Fragment, { children: dataMeasures && dataMeasures[0]?.data?.length ?
|