@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, handleGetFirstTimestamp, theme, ...props }: {
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(2)} ${context.dataset.unit}`;
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
- // Create rows from timestampMap
166
- Object.values(timestampMap).forEach((entry) => {
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 or just the timestamp, add it to csvData
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, handleGetFirstTimestamp, theme, ...props }) => {
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(firstTimestamp - 86400);
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
- const polltime = getPollTime(intervalInSeconds, measure.polltime);
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
- const intervalInSeconds = timeEnd - timeStart;
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, false);
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
- // spanGaps: false,
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 values = [];
304
+ let time;
305
+ let minTime = null;
302
306
  datasets.forEach(dataset => {
303
- values = [...values, ...dataset.data.map((point) => point.y).filter((data) => data !== null)];
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 fetchFirstTimestamp = async () => {
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 < 2629800) { // Less than 1 month
355
+ else if (timeDifference < 2678400) { // Less than 1 month
359
356
  newChartPeriod = '1W'; // Set to 1 week
360
357
  }
361
- else if (timeDifference < 7889400) { // Less than 3 months
358
+ else if (timeDifference < 8035200) { // Less than 3 months
362
359
  newChartPeriod = '1M'; // Set to 1 month
363
360
  }
364
- else if (timeDifference < 15778440) { // Less than 6 months
361
+ else if (timeDifference < 16070400) { // Less than 6 months
365
362
  newChartPeriod = '3M'; // Set to 3 months
366
363
  }
367
- else if (timeDifference < 31556926) { // Less than 1 year
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(timeStart * 1000),
407
- // format="DD/MM/YY hh:mm A"
408
- onChange: (newValue) => {
409
- setTimeStart((moment(newValue).unix()));
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
- // format="DD/MM/YY hh:mm A"
414
- onChange: (newValue) => {
415
- setTimeEnd((moment(newValue).unix()));
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
- if (datePickerUsed) {
425
- setZoomed(false);
426
- }
427
- else if (chartPeriod === "ALL") {
428
- setZoomed(false);
423
+ setZoomed(false);
424
+ if (chartPeriod === "ALL") {
425
+ setDatePickerUsed(false);
426
+ setTimeStart(1577854800);
429
427
  setTimeEnd(moment().unix());
430
- setTimeStart(firstTimestamp - 86400);
428
+ }
429
+ else if (datePickerUsed) {
430
+ setTimeStart(pickerTimeStart);
431
+ setTimeEnd(pickerTimeEnd);
431
432
  }
432
433
  else {
433
- setZoomed(false);
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', xl: '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: chartPeriod, exclusive: true, onChange: handleChange, size: "small",
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 ?
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iotready/nextjs-components-library",
3
- "version": "1.0.0-preview3",
3
+ "version": "1.0.0-preview5",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "build": "rm -rf dist && tsc --project tsconfig.build.json && cp package.json dist/",