@iotready/nextjs-components-library 1.0.0-preview1 → 1.0.0-preview10

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.
@@ -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: () => Promise<void>;
5
+ handleClick: () => void;
6
6
  handleSignOut: () => Promise<void>;
7
7
  accountRoute?: string;
8
8
  theme: Theme;
@@ -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;
@@ -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(2)} ${context.dataset.unit}`;
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 GetPoints(data) {
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
- // Create rows from timestampMap
164
- Object.values(timestampMap).forEach((entry) => {
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 or just the timestamp, add it to csvData
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, handleGetFirstTimestamp, theme, ...props }) => {
178
+ const TrendChart = ({ deviceId, measures, enableExportData, enableDatePicker, handleGetInfluxData, theme, ...props }) => {
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(firstTimestamp - 86400);
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
- const polltime = getPollTime(intervalInSeconds, measure.polltime);
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,22 @@ const TrendChart = ({ deviceId, measures, enableExportData, enableDatePicker, ha
264
271
  }
265
272
  }, [csvData]);
266
273
  const loadDatasets = async (chartPeriod) => {
267
- setChartLoading(true);
268
- const intervalInSeconds = timeEnd - timeStart;
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, false);
273
- const points = GetPoints(influxData);
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
- spanGaps: false,
289
+ change: !measure.polltime,
284
290
  fill: false
285
291
  };
286
292
  });
@@ -288,24 +294,31 @@ const TrendChart = ({ deviceId, measures, enableExportData, enableDatePicker, ha
288
294
  const datasets = await Promise.all(datasetsPromises);
289
295
  let min = null;
290
296
  let max = null;
291
- let values = [];
297
+ let time;
298
+ let minTime = null;
292
299
  datasets.forEach(dataset => {
293
- values = [...values, ...dataset.data.map((point) => point.y).filter((data) => data !== null)];
300
+ const values = dataset.data.map((point) => point.y).filter((data) => data !== null);
301
+ if (chartPeriod === "ALL" && !datePickerUsed && !zoomed && values.length) {
302
+ time = dataset.data.filter((data) => data.y !== null).map((data) => data.x)[0];
303
+ }
294
304
  const datasetMin = Math.min(...values);
295
305
  const datasetMax = Math.max(...values);
296
306
  if (min === null || datasetMin < min)
297
307
  min = datasetMin;
298
308
  if (max === null || datasetMax > max)
299
309
  max = datasetMax;
310
+ if (time && (minTime === null || time.unix() < minTime))
311
+ minTime = time.unix() - 86400;
300
312
  });
301
313
  let paddedMin = null;
302
314
  let paddedMax = null;
303
315
  if (min !== null && max !== null) {
304
- const diff = Math.round((max - min) / 3) || 1;
305
- paddedMin = min - diff;
306
- paddedMax = max + diff;
316
+ const diff = ((max - min) * 0.2) < 0.1 ? 0.1 : (max - min) * 0.2;
317
+ paddedMin = Math.floor((min - diff) * 10) / 10;
318
+ paddedMax = Math.ceil((max + diff) * 10) / 10;
307
319
  }
308
320
  setDataMeasures([...datasets]);
321
+ setTimeStartPicker(minTime || timeStart);
309
322
  setOptions({
310
323
  ...options,
311
324
  scales: {
@@ -317,27 +330,14 @@ const TrendChart = ({ deviceId, measures, enableExportData, enableDatePicker, ha
317
330
  },
318
331
  x: {
319
332
  ...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
- }
333
+ min: moment.unix(minTime || timeStart).toString(),
334
+ max: moment.unix(timeEnd).toString()
326
335
  }
327
336
  }
328
337
  });
329
338
  };
330
339
  useEffect(() => {
331
- const fetchFirstTimestamp = async () => {
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
340
+ const timeDifference = Math.abs(moment(timeEnd).valueOf() - moment(timeStart).valueOf()); // Convert milliseconds to seconds
341
341
  let newChartPeriod = '1D'; // Default to 1 day
342
342
  if (timeDifference < 86400) { // Less than 1 day
343
343
  newChartPeriod = '1H'; // Set to 1 day
@@ -345,26 +345,33 @@ const TrendChart = ({ deviceId, measures, enableExportData, enableDatePicker, ha
345
345
  else if (timeDifference < 604800) { // Less than 1 week
346
346
  newChartPeriod = '1D'; // Set to 1 day
347
347
  }
348
- else if (timeDifference < 2629800) { // Less than 1 month
348
+ else if (timeDifference < 2678400) { // Less than 1 month
349
349
  newChartPeriod = '1W'; // Set to 1 week
350
350
  }
351
- else if (timeDifference < 7889400) { // Less than 3 months
351
+ else if (timeDifference < 8035200) { // Less than 3 months
352
352
  newChartPeriod = '1M'; // Set to 1 month
353
353
  }
354
- else if (timeDifference < 15778440) { // Less than 6 months
354
+ else if (timeDifference < 16070400) { // Less than 6 months
355
355
  newChartPeriod = '3M'; // Set to 3 months
356
356
  }
357
- else if (timeDifference < 31556926) { // Less than 1 year
357
+ else if (timeDifference < 31536000) { // Less than 1 year
358
358
  newChartPeriod = '6M'; // Set to 6 months
359
359
  }
360
360
  else {
361
361
  newChartPeriod = '1Y'; // Set to 1 year
362
362
  }
363
363
  setChartPeriodConfig(chartConfigByPeriod[newChartPeriod]);
364
+ // check prev measures value in order to show the loader
365
+ // hide the loader if measure is the same (for interval get measure value)
366
+ const prevMeasuresValue = prevMeasures.current;
367
+ prevMeasures.current = measures;
368
+ if (!prevMeasuresValue || prevMeasuresValue.length !== measures.length || (prevMeasuresValue[0] && prevMeasuresValue[0].name !== measures[0].name)) {
369
+ setChartLoading(true);
370
+ }
364
371
  loadDatasets(chartPeriod).then(() => {
365
372
  setChartLoading(false);
366
373
  });
367
- }, [timeEnd, timeStart]);
374
+ }, [measures, timeEnd, timeStart]);
368
375
  useEffect(() => {
369
376
  const loadZoomPlugin = async () => {
370
377
  const zoomPlugin = (await import('chartjs-plugin-zoom')).default;
@@ -393,34 +400,41 @@ const TrendChart = ({ deviceId, measures, enableExportData, enableDatePicker, ha
393
400
  loadZoomPlugin();
394
401
  resetChart();
395
402
  }, []);
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(timeStart * 1000),
397
- // format="DD/MM/YY hh:mm A"
398
- onChange: (newValue) => {
399
- setTimeStart((moment(newValue).unix()));
400
- }, maxDate: moment(timeEnd * 1000), slotProps: {
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
+ setChartLoading(true);
405
+ setDatePickerUsed(true);
406
+ setZoomed(false);
407
+ setPickerTimeStart(moment(newValue).unix());
408
+ setTimeStart(moment(newValue).unix());
409
+ }, maxDateTime: moment(timeEnd * 1000), slotProps: {
401
410
  textField: { size: 'small', sx: { width: { sm: 210 } } }
402
- } }), " \u00A0\u00A0 ", _jsx(Box, { children: "\u2013" }), " \u00A0\u00A0", _jsx(DateTimePicker, { value: moment(timeEnd * 1000),
403
- // format="DD/MM/YY hh:mm A"
404
- onChange: (newValue) => {
405
- setTimeEnd((moment(newValue).unix()));
406
- }, minDate: moment(timeStart * 1000), slotProps: {
411
+ } }), " \u00A0\u00A0 ", _jsx(Box, { children: "\u2013" }), " \u00A0\u00A0", _jsx(DateTimePicker, { value: moment(timeEnd * 1000), onChange: (newValue) => {
412
+ setChartLoading(true);
413
+ setDatePickerUsed(true);
414
+ setZoomed(false);
415
+ setPickerTimeEnd(moment(newValue).unix());
416
+ setTimeEnd(moment(newValue).unix());
417
+ }, minDateTime: moment(timeStart * 1000), slotProps: {
407
418
  textField: { size: 'small', sx: { width: { sm: 210 } } }
408
419
  } })] }) });
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
420
+ 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
421
  //@ts-ignore
411
422
  , {
412
423
  //@ts-ignore
413
424
  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
- if (datePickerUsed) {
415
- setZoomed(false);
416
- }
417
- else if (chartPeriod === "ALL") {
418
- setZoomed(false);
425
+ setChartLoading(true);
426
+ setZoomed(false);
427
+ if (chartPeriod === "ALL") {
428
+ setDatePickerUsed(false);
429
+ setTimeStart(1577854800);
419
430
  setTimeEnd(moment().unix());
420
- setTimeStart(firstTimestamp - 86400);
431
+ }
432
+ else if (datePickerUsed) {
433
+ setTimeStart(pickerTimeStart);
434
+ setTimeEnd(pickerTimeEnd);
421
435
  }
422
436
  else {
423
- setZoomed(false);
437
+ setDatePickerUsed(false);
424
438
  setChartPeriodConfig(chartConfigByPeriod[chartPeriod]);
425
439
  setTimeStart(chartPeriodConfig.from?.days
426
440
  ? moment()
@@ -429,12 +443,13 @@ const TrendChart = ({ deviceId, measures, enableExportData, enableDatePicker, ha
429
443
  : moment().subtract(1, 'day').unix());
430
444
  setTimeEnd(moment().unix());
431
445
  }
432
- }, 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",
446
+ }, 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
447
  // 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" })] })] })] }), _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' ?
435
- _jsx(_Fragment, { children: dataMeasures && dataMeasures[0]?.data?.length ?
448
+ 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' ?
449
+ _jsx(_Fragment, { children: dataMeasures && (dataMeasures.length > 1 || (dataMeasures.length === 1 && dataMeasures[0].data?.length)) ?
436
450
  (_jsx(Line, { options: options, data: {
437
- datasets: dataMeasures || [{ data: [] }]
451
+ // datasets: dataMeasures || [{ data: [] }]
452
+ datasets: dataMeasures.map(d => ({ ...d, showLine: spanGapsOption || !d.change })) || [{ data: [] }]
438
453
  } })) : _jsxs(Box, { sx: {
439
454
  display: 'flex',
440
455
  flexDirection: 'column',
@@ -448,7 +463,7 @@ const TrendChart = ({ deviceId, measures, enableExportData, enableDatePicker, ha
448
463
  alignItems: 'center',
449
464
  justifyContent: 'center',
450
465
  textAlign: 'center',
451
- height: '100%'
466
+ height: 'calc(100% - 50px)'
452
467
  }, children: _jsx(CircularProgress, {}) })) })] }));
453
468
  };
454
469
  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, group: string, selected: string) => Promise<any>;
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
- const devices = await handleGetDevices(userInfo, group, selected);
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
- getUsersGroup(currentGroup);
135
+ if (currentGroup !== 'all') {
136
+ getUsersGroup(currentGroup);
137
+ }
123
138
  fetchDevices(currentGroup, currentGroup);
124
139
  }
125
140
  }, [currentGroup]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iotready/nextjs-components-library",
3
- "version": "1.0.0-preview1",
3
+ "version": "1.0.0-preview10",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "build": "rm -rf dist && tsc --project tsconfig.build.json && cp package.json dist/",
@@ -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, group?: string, selected?: string): Promise<{
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, group, selected) {
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?${queryParams}`
76
- : `/products/${productId}/devices?${queryParams}`)
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);