@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.
@@ -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;
@@ -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, handleGetFirstTimestamp, theme, ...props }: {
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
- } & any) => import("react/jsx-runtime").JSX.Element;
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(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 }) => {
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,23 @@ 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,
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 values = [];
298
+ let time;
299
+ let minTime = null;
292
300
  datasets.forEach(dataset => {
293
- values = [...values, ...dataset.data.map((point) => point.y).filter((data) => data !== null)];
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 = Math.round((max - min) / 3) || 1;
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 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
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 < 2629800) { // Less than 1 month
349
+ else if (timeDifference < 2678400) { // Less than 1 month
349
350
  newChartPeriod = '1W'; // Set to 1 week
350
351
  }
351
- else if (timeDifference < 7889400) { // Less than 3 months
352
+ else if (timeDifference < 8035200) { // Less than 3 months
352
353
  newChartPeriod = '1M'; // Set to 1 month
353
354
  }
354
- else if (timeDifference < 15778440) { // Less than 6 months
355
+ else if (timeDifference < 16070400) { // Less than 6 months
355
356
  newChartPeriod = '3M'; // Set to 3 months
356
357
  }
357
- else if (timeDifference < 31556926) { // Less than 1 year
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(timeStart * 1000),
397
- // format="DD/MM/YY hh:mm A"
398
- onChange: (newValue) => {
399
- setTimeStart((moment(newValue).unix()));
400
- }, maxDate: moment(timeEnd * 1000), slotProps: {
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
- // format="DD/MM/YY hh:mm A"
404
- onChange: (newValue) => {
405
- setTimeEnd((moment(newValue).unix()));
406
- }, minDate: moment(timeStart * 1000), slotProps: {
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
- if (datePickerUsed) {
415
- setZoomed(false);
416
- }
417
- else if (chartPeriod === "ALL") {
418
- setZoomed(false);
427
+ setChartLoading(true);
428
+ setZoomed(false);
429
+ if (chartPeriod === "ALL") {
430
+ setDatePickerUsed(false);
431
+ setTimeStart(1577854800);
419
432
  setTimeEnd(moment().unix());
420
- setTimeStart(firstTimestamp - 86400);
433
+ }
434
+ else if (datePickerUsed) {
435
+ setTimeStart(pickerTimeStart);
436
+ setTimeEnd(pickerTimeEnd);
421
437
  }
422
438
  else {
423
- setZoomed(false);
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', 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",
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" })] })] })] }), _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 ?
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, 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-preview11",
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);