@c8y/ngx-components 1023.14.38 → 1023.14.44

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.
Files changed (35) hide show
  1. package/datapoint-explorer/view/index.d.ts +2 -0
  2. package/datapoint-explorer/view/index.d.ts.map +1 -1
  3. package/echart/index.d.ts +7 -1
  4. package/echart/index.d.ts.map +1 -1
  5. package/fesm2022/c8y-ngx-components-context-dashboard.mjs +1 -1
  6. package/fesm2022/c8y-ngx-components-context-dashboard.mjs.map +1 -1
  7. package/fesm2022/c8y-ngx-components-datapoint-explorer-view.mjs +21 -36
  8. package/fesm2022/c8y-ngx-components-datapoint-explorer-view.mjs.map +1 -1
  9. package/fesm2022/c8y-ngx-components-echart.mjs +127 -83
  10. package/fesm2022/c8y-ngx-components-echart.mjs.map +1 -1
  11. package/fesm2022/c8y-ngx-components-global-context.mjs +21 -6
  12. package/fesm2022/c8y-ngx-components-global-context.mjs.map +1 -1
  13. package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-graph.mjs +3 -3
  14. package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-graph.mjs.map +1 -1
  15. package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-table.mjs +2 -2
  16. package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-table.mjs.map +1 -1
  17. package/fesm2022/c8y-ngx-components-widgets-implementations-map.mjs +1 -1
  18. package/fesm2022/c8y-ngx-components-widgets-implementations-map.mjs.map +1 -1
  19. package/fesm2022/c8y-ngx-components.mjs +18 -6
  20. package/fesm2022/c8y-ngx-components.mjs.map +1 -1
  21. package/global-context/index.d.ts +12 -2
  22. package/global-context/index.d.ts.map +1 -1
  23. package/index.d.ts +2 -1
  24. package/index.d.ts.map +1 -1
  25. package/locales/de.po +5 -2
  26. package/locales/es.po +3 -0
  27. package/locales/fr.po +3 -0
  28. package/locales/ja_JP.po +3 -0
  29. package/locales/ko.po +3 -0
  30. package/locales/nl.po +3 -0
  31. package/locales/pl.po +3 -0
  32. package/locales/pt_BR.po +3 -0
  33. package/locales/zh_CN.po +3 -0
  34. package/locales/zh_TW.po +3 -0
  35. package/package.json +1 -1
@@ -15,7 +15,7 @@ import { INTERVALS } from '@c8y/ngx-components/interval-picker';
15
15
  import * as i5 from '@ngx-translate/core';
16
16
  import * as i1$1 from '@angular/common';
17
17
  import { NgIf, NgForOf, CommonModule as CommonModule$1 } from '@angular/common';
18
- import * as i3$1 from 'ngx-echarts';
18
+ import * as i2$1 from 'ngx-echarts';
19
19
  import { NgxEchartsModule, NGX_ECHARTS_CONFIG } from 'ngx-echarts';
20
20
  import { TooltipModule } from 'ngx-bootstrap/tooltip';
21
21
  import * as i1$3 from 'ngx-bootstrap/popover';
@@ -96,7 +96,7 @@ class YAxisService {
96
96
  this.intlNumberFormatCompliantLocale = this.appStateService.state.lang.replace('_', '-');
97
97
  }
98
98
  getYAxis(datapointsWithValues, YAxisOptions) {
99
- const YAxisPlacement = this.getYAxisPlacement(datapointsWithValues);
99
+ const YAxisPlacement = this.getYAxisPlacement(datapointsWithValues, YAxisOptions);
100
100
  if (YAxisOptions.forceMergeDatapoints) {
101
101
  return {
102
102
  name: Array.from(datapointsWithValues)
@@ -109,14 +109,7 @@ class YAxisService {
109
109
  nameGap: 25,
110
110
  nameTextStyle: {
111
111
  // add rich text to support multiple colors for different dp units
112
- rich: {
113
- ...Array.from(datapointsWithValues).reduce((acc, dp, index) => {
114
- acc[index] = {
115
- color: dp.color || '#6f7079'
116
- };
117
- return acc;
118
- }, {})
119
- }
112
+ rich: this.buildRichTextStyle(datapointsWithValues)
120
113
  },
121
114
  type: 'value',
122
115
  animation: true,
@@ -146,7 +139,6 @@ class YAxisService {
146
139
  ...(YAxisOptions.setYaxisStartToZero === false && { min: 'dataMin' }) // we only set min when the option is false
147
140
  };
148
141
  }
149
- const matchingDpSet = new Set();
150
142
  const firstOccurrence = new Set();
151
143
  return datapointsWithValues.map((dp, index) => {
152
144
  const barValues = dp.lineType === 'bars'
@@ -162,59 +154,32 @@ class YAxisService {
162
154
  const barMinOffset = dp.lineType === 'bars' && allBarsPositive && isDefined(barDataMin) && isDefined(barDataMax)
163
155
  ? (barDataMax - barDataMin) * 0.1 || barDataMin * 0.1
164
156
  : 0;
165
- const isMatchingDp = (dp1, dp2) => dp1.min === dp2.min &&
166
- dp1.max === dp2.max &&
167
- isDefined(dp1.min) &&
168
- isDefined(dp1.max) &&
169
- isDefined(dp2.min) &&
170
- isDefined(dp2.max);
171
- const matchingDpRange = datapointsWithValues.some((dp2, index2) => isMatchingDp(dp, dp2) && index2 < index);
172
- const anyMatchingDp = datapointsWithValues.some((dp2, index2) => isMatchingDp(dp, dp2) && index2 !== index);
157
+ const matchingDpRange = datapointsWithValues.some((dp2, index2) => this.isMatchingDp(dp, dp2) && index2 < index);
158
+ const anyMatchingDp = datapointsWithValues.some((dp2, index2) => this.isMatchingDp(dp, dp2) && index2 !== index);
173
159
  if (anyMatchingDp &&
174
160
  !matchingDpRange &&
175
161
  YAxisOptions.mergeMatchingDatapoints &&
176
162
  !firstOccurrence.has(dp)) {
177
163
  firstOccurrence.add(dp);
178
164
  }
179
- if (firstOccurrence.has(dp)) {
180
- datapointsWithValues.forEach(dp2 => {
181
- if (isMatchingDp(dp, dp2)) {
182
- matchingDpSet.add(dp2);
183
- }
184
- });
185
- }
165
+ const matchingDpSet = firstOccurrence.has(dp)
166
+ ? new Set(datapointsWithValues.filter(dp2 => this.isMatchingDp(dp, dp2)))
167
+ : new Set();
168
+ const uniqueUnitDps = firstOccurrence.has(dp) ? this.getUniqueUnits(matchingDpSet) : [];
186
169
  return {
187
- name: YAxisOptions.showLabelAndUnit
188
- ? YAxisOptions.mergeMatchingDatapoints
189
- ? firstOccurrence.has(dp)
190
- ? Array.from(matchingDpSet)
191
- .map((dp, index) => `{${index}|${dp.unit}}`)
192
- .join(' /')
193
- : matchingDpRange
194
- ? ''
195
- : `${dp.label} [${dp.unit}]`
196
- : `${dp.label} [${dp.unit}]`
197
- : '',
170
+ name: this.buildYAxisNameFromUnits(dp, uniqueUnitDps, matchingDpRange, firstOccurrence.has(dp), YAxisOptions),
198
171
  nameLocation: 'middle',
199
172
  nameTruncate: {
200
173
  maxWidth: 350
201
174
  },
202
175
  nameGap: 25,
203
176
  nameTextStyle: {
204
- // add rich text to support multiple colors for different dp units
205
- rich: {
206
- ...Array.from(matchingDpSet).reduce((acc, dp, index) => {
207
- acc[index] = {
208
- color: dp.color
209
- };
210
- return acc;
211
- }, {})
212
- }
177
+ rich: this.buildRichTextStyle(uniqueUnitDps)
213
178
  },
214
179
  type: 'value',
215
180
  animation: true,
216
181
  axisLine: {
217
- show: matchingDpRange && YAxisOptions.mergeMatchingDatapoints ? false : true,
182
+ show: !(matchingDpRange && YAxisOptions.mergeMatchingDatapoints),
218
183
  lineStyle: {
219
184
  color: firstOccurrence.has(dp) ? '#6f7079' : dp.color
220
185
  },
@@ -224,7 +189,7 @@ class YAxisService {
224
189
  fontSize: 10,
225
190
  show: !matchingDpRange || !YAxisOptions.mergeMatchingDatapoints,
226
191
  formatter: val => {
227
- if (dp.min != undefined && dp.max != undefined) {
192
+ if (this.isDefined(dp.min) && this.isDefined(dp.max)) {
228
193
  const range = dp.max - dp.min;
229
194
  const decimalPlaces = this.getDecimalPlaces(range);
230
195
  return val.toFixed(decimalPlaces);
@@ -246,9 +211,7 @@ class YAxisService {
246
211
  },
247
212
  axisPointer: {
248
213
  show: false,
249
- label: {
250
- show: false
251
- }
214
+ label: { show: false }
252
215
  },
253
216
  ...(isDefined(dp.min)
254
217
  ? { min: dp.min }
@@ -261,6 +224,42 @@ class YAxisService {
261
224
  };
262
225
  });
263
226
  }
227
+ getUniqueUnits(dps) {
228
+ const seenUnits = new Set();
229
+ return Array.from(dps).filter(dp => {
230
+ if (seenUnits.has(dp.unit) || !dp.unit) {
231
+ return false;
232
+ }
233
+ seenUnits.add(dp.unit);
234
+ return true;
235
+ });
236
+ }
237
+ isMatchingDp(dp1, dp2) {
238
+ return (dp1.min === dp2.min &&
239
+ dp1.max === dp2.max &&
240
+ this.isDefined(dp1.min) &&
241
+ this.isDefined(dp1.max) &&
242
+ this.isDefined(dp2.min) &&
243
+ this.isDefined(dp2.max));
244
+ }
245
+ isDefined(value) {
246
+ return value !== null && value !== undefined;
247
+ }
248
+ buildRichTextStyle(dps, fallbackColor = '#6f7079') {
249
+ return Array.from(dps).reduce((acc, dp, index) => {
250
+ acc[index] = { color: dp.color || fallbackColor };
251
+ return acc;
252
+ }, {});
253
+ }
254
+ buildYAxisNameFromUnits(dp, uniqueUnitDps, matchingDpRange, isFirstOccurrence, options) {
255
+ if (!options.showLabelAndUnit || (options.mergeMatchingDatapoints && matchingDpRange)) {
256
+ return '';
257
+ }
258
+ if (!options.mergeMatchingDatapoints || !isFirstOccurrence) {
259
+ return `${dp.label} [${dp.unit}]`;
260
+ }
261
+ return uniqueUnitDps.map((dp, index) => `{${index}|${dp.unit}}`).join(' / ');
262
+ }
264
263
  getDecimalPlaces(num) {
265
264
  const numStr = num.toString();
266
265
  const decimalIndex = numStr.indexOf('.');
@@ -269,18 +268,28 @@ class YAxisService {
269
268
  }
270
269
  return numStr.length - decimalIndex - 1;
271
270
  }
272
- getYAxisPlacement(datapointsWithValues) {
271
+ getYAxisPlacement(datapointsWithValues, YAxisOptions) {
273
272
  const YAxisPositions = new Map();
274
273
  datapointsWithValues.forEach(dp => {
275
274
  const position = this.getYAxisPosition(dp, datapointsWithValues);
276
275
  YAxisPositions.set(dp, { position });
277
276
  });
278
- const dpLeft = datapointsWithValues.filter(dp => YAxisPositions.get(dp).position === 'left');
279
- const dpRight = datapointsWithValues.filter(dp => YAxisPositions.get(dp).position === 'right');
277
+ const dpLeft = datapointsWithValues.filter((dp, index) => YAxisPositions.get(dp).position === 'left' &&
278
+ this.isAxisVisible(dp, index, datapointsWithValues, YAxisOptions));
279
+ const dpRight = datapointsWithValues.filter((dp, index) => YAxisPositions.get(dp).position === 'right' &&
280
+ this.isAxisVisible(dp, index, datapointsWithValues, YAxisOptions));
280
281
  const YAxisPlacement = new Map();
281
- YAxisPositions.forEach(({ position }, key) => {
282
- const offset = (position === 'left' ? dpLeft : dpRight).indexOf(key) * this.Y_AXIS_OFFSET;
283
- YAxisPlacement.set(key, { position: position, offset });
282
+ dpLeft.forEach((dp, index) => {
283
+ YAxisPlacement.set(dp, {
284
+ position: 'left',
285
+ offset: index * this.Y_AXIS_OFFSET
286
+ });
287
+ });
288
+ dpRight.forEach((dp, index) => {
289
+ YAxisPlacement.set(dp, {
290
+ position: 'right',
291
+ offset: index * this.Y_AXIS_OFFSET
292
+ });
284
293
  });
285
294
  return YAxisPlacement;
286
295
  }
@@ -297,6 +306,12 @@ class YAxisService {
297
306
  return 'left';
298
307
  }
299
308
  }
309
+ isAxisVisible(dp, index, dps, options) {
310
+ if (!options.mergeMatchingDatapoints) {
311
+ return true;
312
+ }
313
+ return !dps.some((dp2, index2) => this.isMatchingDp(dp, dp2) && index2 < index);
314
+ }
300
315
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: YAxisService, deps: [{ token: i1.AppStateService }], target: i0.ɵɵFactoryTarget.Injectable }); }
301
316
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: YAxisService }); }
302
317
  }
@@ -1699,10 +1714,25 @@ class ChartRealtimeService {
1699
1714
  series: allDataSeries
1700
1715
  });
1701
1716
  }
1717
+ /**
1718
+ * Detects if a datapoint has measurements with future timestamps (out-of-sync).
1719
+ *
1720
+ * Why 300ms tolerance?
1721
+ * Device clocks may be slightly ahead of browser time, network latency, or processing delays.
1722
+ * Without tolerance, these minor drifts would cause false positive warnings.
1723
+ *
1724
+ * Example:
1725
+ * Browser time: 12:00:00.000
1726
+ * Measurement: 12:00:00.200 (device 200ms ahead)
1727
+ * Without tolerance: flagged as out-of-sync (false positive)
1728
+ * With 300ms tolerance: allowed (200ms < 300ms threshold)
1729
+ *
1730
+ * When triggered, a warning icon appears next to the datapoint in the legend.
1731
+ */
1702
1732
  checkForValuesAfterTimeRange(data, datapoint, datapointOutOfSyncCallback) {
1703
- const now = new Date();
1704
- const valueAfterNowExists = data.some(([dateString, _]) => {
1705
- return new Date(dateString).valueOf() > now.valueOf();
1733
+ const nowWithTolerance = Date.now() + 300;
1734
+ const valueAfterNowExists = data.some(([dateString]) => {
1735
+ return new Date(dateString).valueOf() > nowWithTolerance;
1706
1736
  });
1707
1737
  if (valueAfterNowExists) {
1708
1738
  datapointOutOfSyncCallback(datapoint);
@@ -1932,6 +1962,8 @@ class ChartsComponent {
1932
1962
  this.alarms = [];
1933
1963
  this.events = [];
1934
1964
  this.activeDatapoints = [];
1965
+ /** Internal flag to track when chart data is being fetched */
1966
+ this.isFetching = false;
1935
1967
  this.configChangeOnZoomOut = new EventEmitter();
1936
1968
  this.timeRangeChangeOnRealtime = new EventEmitter();
1937
1969
  this.datapointOutOfSync = new EventEmitter();
@@ -1950,15 +1982,21 @@ class ChartsComponent {
1950
1982
  this.mediator = inject(WidgetTimeContextMediatorService);
1951
1983
  this.widgetTimeContextDateRangeService = inject(WidgetTimeContextDateRangeService);
1952
1984
  this.loadedTimeRange = null;
1953
- this.chartOption$ = this.configChangedSubject.pipe(switchMap(() => this.loadAlarmsAndEvents()), switchMap(() => this.fetchSeriesForDatapoints$()), switchMap((datapointsWithValues) => {
1985
+ /** Tracks if the last data fetch returned truncated data */
1986
+ this.dataWasTruncated = false;
1987
+ /** Tracks if current change originated from zoom interaction */
1988
+ this.isChangeFromZoom = false;
1989
+ this.chartOption$ = this.configChangedSubject.pipe(tap(() => (this.isFetching = true)), switchMap(() => this.loadAlarmsAndEvents()), switchMap(() => this.fetchSeriesForDatapoints$()), switchMap((datapointsWithValues) => {
1954
1990
  if (datapointsWithValues.length === 0 && this.config.alarmsEventsConfigs?.length === 0) {
1955
1991
  this.echartsInstance?.clear();
1956
1992
  this.showLoadMore = false;
1957
1993
  return of(this.getDefaultChartOptions());
1958
1994
  }
1959
- this.loadedTimeRange = { ...this.getTimeRange() };
1995
+ // Use padded range since data is fetched with 60s padding
1996
+ this.loadedTimeRange = { ...this.getTimeRange(60_000) };
1960
1997
  return this.getChartOptions(datapointsWithValues);
1961
1998
  }), tap(v => {
1999
+ this.isFetching = false;
1962
2000
  this.finishLoading.emit(false);
1963
2001
  if (v['empty']) {
1964
2002
  return;
@@ -1979,26 +2017,29 @@ class ChartsComponent {
1979
2017
  this.configChangedSubject.next();
1980
2018
  });
1981
2019
  }
1982
- ngOnChanges(changes) {
1983
- const currentTimeRange = this.getTimeRange();
1984
- if (this.loadedTimeRange &&
1985
- new Date(currentTimeRange.dateFrom) >= new Date(this.loadedTimeRange.dateFrom) &&
1986
- new Date(currentTimeRange.dateTo) <= new Date(this.loadedTimeRange.dateTo) &&
1987
- changes.config.previousValue?.dateFrom !== changes.config.currentValue.dateFrom &&
1988
- changes.config.previousValue?.dateTo !== changes.config.currentValue.dateTo &&
1989
- changes.config.previousValue?.aggregation === changes.config.currentValue?.aggregation) {
1990
- // This is needed for cases when 2 data point graph widgets exist on the same dashboard
1991
- // and one of them changes the time range which is loaded, the other one should update the zoom level accordingly
2020
+ ngOnChanges() {
2021
+ const wasFromZoom = this.isChangeFromZoom;
2022
+ this.isChangeFromZoom = false;
2023
+ if (wasFromZoom) {
2024
+ const currentRange = this.getTimeRange();
2025
+ const isWithinLoadedRange = this.loadedTimeRange &&
2026
+ new Date(currentRange.dateFrom) >= new Date(this.loadedTimeRange.dateFrom) &&
2027
+ new Date(currentRange.dateTo) <= new Date(this.loadedTimeRange.dateTo);
2028
+ // Sync zoom level across multiple data point graph widgets on the same dashboard
1992
2029
  if (this.echartsInstance) {
1993
2030
  this.echartsInstance.dispatchAction({
1994
2031
  type: 'dataZoom',
1995
- startValue: new Date(currentTimeRange.dateFrom).getTime(),
1996
- endValue: new Date(currentTimeRange.dateTo).getTime()
2032
+ startValue: new Date(currentRange.dateFrom).getTime(),
2033
+ endValue: new Date(currentRange.dateTo).getTime()
1997
2034
  }, { silent: true });
1998
2035
  }
1999
- return;
2036
+ if (!isWithinLoadedRange || this.dataWasTruncated) {
2037
+ this.configChangedSubject.next();
2038
+ }
2039
+ }
2040
+ else {
2041
+ this.configChangedSubject.next();
2000
2042
  }
2001
- this.configChangedSubject.next();
2002
2043
  }
2003
2044
  ngOnInit() {
2004
2045
  if (this.alerts) {
@@ -2020,17 +2061,19 @@ class ChartsComponent {
2020
2061
  }
2021
2062
  const options = this.echartsInstance.getOption();
2022
2063
  const dataZoom = options['dataZoom'][0];
2023
- this.configChangeOnZoomOut.emit({
2064
+ this.isChangeFromZoom = true;
2065
+ const zoomDates = {
2024
2066
  dateFrom: new Date(dataZoom['startValue']),
2025
2067
  dateTo: new Date(dataZoom['endValue']),
2026
2068
  interval: 'custom'
2027
- });
2069
+ };
2070
+ this.configChangeOnZoomOut.emit(zoomDates);
2028
2071
  this.echartsInstance.setOption(options);
2029
2072
  this.chartRealtimeService.stopRealtime();
2030
2073
  };
2031
2074
  const debouncedDataZoomHandler = this.config.realtime
2032
2075
  ? dataZoomHandler
2033
- : this.debounce(dataZoomHandler, 1000);
2076
+ : this.debounce(dataZoomHandler, 100);
2034
2077
  this.echartsInstance.on('dataZoom', debouncedDataZoomHandler);
2035
2078
  this.echartsInstance.on('click', this.onChartClick.bind(this));
2036
2079
  let originalFormatter = null;
@@ -2454,7 +2497,8 @@ class ChartsComponent {
2454
2497
  datapointsWithValuesRequests.push(request);
2455
2498
  }
2456
2499
  return forkJoin(datapointsWithValuesRequests).pipe(tap((dpsWithValues) => {
2457
- if (dpsWithValues.some(dp => dp['truncated'])) {
2500
+ this.dataWasTruncated = dpsWithValues.some(dp => dp['truncated']);
2501
+ if (this.dataWasTruncated) {
2458
2502
  this.addTruncatedDataAlert();
2459
2503
  }
2460
2504
  }));
@@ -2550,7 +2594,7 @@ class ChartsComponent {
2550
2594
  return { dateFrom: timeRange.dateFrom.toISOString(), dateTo: timeRange.dateTo.toISOString() };
2551
2595
  }
2552
2596
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ChartsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2553
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: ChartsComponent, isStandalone: true, selector: "c8y-charts", inputs: { config: "config", alerts: "alerts", chartViewContext: "chartViewContext" }, outputs: { configChangeOnZoomOut: "configChangeOnZoomOut", timeRangeChangeOnRealtime: "timeRangeChangeOnRealtime", datapointOutOfSync: "datapointOutOfSync", updateAlarmsAndEvents: "updateAlarmsAndEvents", isMarkedAreaEnabled: "isMarkedAreaEnabled", finishLoading: "finishLoading", updateActiveDatapoints: "updateActiveDatapoints", updateAggregatedSliderDatapoint: "updateAggregatedSliderDatapoint" }, providers: [
2597
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: ChartsComponent, isStandalone: true, selector: "c8y-charts", inputs: { config: "config", alerts: "alerts", chartViewContext: "chartViewContext" }, outputs: { configChangeOnZoomOut: "configChangeOnZoomOut", timeRangeChangeOnRealtime: "timeRangeChangeOnRealtime", datapointOutOfSync: "datapointOutOfSync", updateAlarmsAndEvents: "updateAlarmsAndEvents", isMarkedAreaEnabled: "isMarkedAreaEnabled", finishLoading: "finishLoading", updateActiveDatapoints: "updateActiveDatapoints", updateAggregatedSliderDatapoint: "updateAggregatedSliderDatapoint" }, providers: [
2554
2598
  { provide: NGX_ECHARTS_CONFIG, useFactory: () => ({ echarts: () => import('echarts') }) },
2555
2599
  ChartRealtimeService,
2556
2600
  MeasurementRealtimeService,
@@ -2561,7 +2605,7 @@ class ChartsComponent {
2561
2605
  YAxisService,
2562
2606
  AlarmSeverityToIconPipe,
2563
2607
  AlarmSeverityToLabelPipe
2564
- ], viewQueries: [{ propertyName: "chart", first: true, predicate: ["chart"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"p-relative fit-h chart-container\">\n <div\n class=\"fit-w fit-h\"\n #chart\n echarts\n [options]=\"chartOption$ | async\"\n (chartInit)=\"onChartInit($event)\"\n ></div>\n\n <c8y-chart-alerts [alerts]=\"alerts\"></c8y-chart-alerts>\n\n <div\n class=\"chart-load-more\"\n *ngIf=\"showLoadMore\"\n >\n <button\n class=\"btn btn-primary btn-block\"\n (click)=\"loadMoreData()\"\n >\n <i c8yIcon=\"restore\"></i>\n {{ 'Load more' | translate }}\n </button>\n </div>\n\n <div\n class=\"e-charts--aggregated-datapoint\"\n *ngIf=\"\n activeDatapoints.length > 1 &&\n config?.showSlider &&\n chartViewContext !== CHART_VIEW_CONTEXT.WIDGET_VIEW\n \"\n >\n <c8y-select-aggregated-datapoint\n [value]=\"config?.aggregatedDatapoint || activeDatapoints[0]\"\n (valueChange)=\"updateAggregatedSliderDatapoint.emit($event)\"\n [activeDatapoints]=\"activeDatapoints\"\n ></c8y-select-aggregated-datapoint>\n </div>\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule$1 }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: CoreModule }, { kind: "directive", type: i1.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "ngmodule", type: NgxEchartsModule }, { kind: "directive", type: i3$1.NgxEchartsDirective, selector: "echarts, [echarts]", inputs: ["options", "theme", "initOpts", "merge", "autoResize", "loading", "loadingType", "loadingOpts"], outputs: ["chartInit", "optionsError", "chartClick", "chartDblClick", "chartMouseDown", "chartMouseMove", "chartMouseUp", "chartMouseOver", "chartMouseOut", "chartGlobalOut", "chartContextMenu", "chartHighlight", "chartDownplay", "chartSelectChanged", "chartLegendSelectChanged", "chartLegendSelected", "chartLegendUnselected", "chartLegendLegendSelectAll", "chartLegendLegendInverseSelect", "chartLegendScroll", "chartDataZoom", "chartDataRangeSelected", "chartGraphRoam", "chartGeoRoam", "chartTreeRoam", "chartTimelineChanged", "chartTimelinePlayChanged", "chartRestore", "chartDataViewChanged", "chartMagicTypeChanged", "chartGeoSelectChanged", "chartGeoSelected", "chartGeoUnselected", "chartAxisAreaSelected", "chartBrush", "chartBrushEnd", "chartBrushSelected", "chartGlobalCursorTaken", "chartRendered", "chartFinished"], exportAs: ["echarts"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: ChartAlertsComponent, selector: "c8y-chart-alerts", inputs: ["alerts"] }, { kind: "ngmodule", type: AlarmsModule }, { kind: "component", type: SelectAggregatedDatapointComponent, selector: "c8y-select-aggregated-datapoint", inputs: ["activeDatapoints", "value"], outputs: ["valueChange"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i1.C8yTranslatePipe, name: "translate" }] }); }
2608
+ ], viewQueries: [{ propertyName: "chart", first: true, predicate: ["chart"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"p-relative fit-h chart-container\">\n <div\n class=\"fit-w fit-h\"\n #chart\n echarts\n [options]=\"chartOption$ | async\"\n (chartInit)=\"onChartInit($event)\"\n ></div>\n\n <c8y-chart-alerts [alerts]=\"alerts\"></c8y-chart-alerts>\n\n @if (showLoadMore) {\n <div class=\"chart-load-more\">\n <button\n class=\"btn btn-primary btn-block\"\n [disabled]=\"isFetching\"\n (click)=\"loadMoreData()\"\n >\n <i c8yIcon=\"restore\"></i>\n {{ 'Load more' | translate }}\n </button>\n </div>\n }\n\n @if (\n activeDatapoints.length > 1 &&\n config?.showSlider &&\n chartViewContext !== CHART_VIEW_CONTEXT.WIDGET_VIEW\n ) {\n <div class=\"e-charts--aggregated-datapoint\">\n <c8y-select-aggregated-datapoint\n [value]=\"config?.aggregatedDatapoint || activeDatapoints[0]\"\n (valueChange)=\"updateAggregatedSliderDatapoint.emit($event)\"\n [activeDatapoints]=\"activeDatapoints\"\n ></c8y-select-aggregated-datapoint>\n </div>\n }\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule$1 }, { kind: "ngmodule", type: CoreModule }, { kind: "directive", type: i1.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "ngmodule", type: NgxEchartsModule }, { kind: "directive", type: i2$1.NgxEchartsDirective, selector: "echarts, [echarts]", inputs: ["options", "theme", "initOpts", "merge", "autoResize", "loading", "loadingType", "loadingOpts"], outputs: ["chartInit", "optionsError", "chartClick", "chartDblClick", "chartMouseDown", "chartMouseMove", "chartMouseUp", "chartMouseOver", "chartMouseOut", "chartGlobalOut", "chartContextMenu", "chartHighlight", "chartDownplay", "chartSelectChanged", "chartLegendSelectChanged", "chartLegendSelected", "chartLegendUnselected", "chartLegendLegendSelectAll", "chartLegendLegendInverseSelect", "chartLegendScroll", "chartDataZoom", "chartDataRangeSelected", "chartGraphRoam", "chartGeoRoam", "chartTreeRoam", "chartTimelineChanged", "chartTimelinePlayChanged", "chartRestore", "chartDataViewChanged", "chartMagicTypeChanged", "chartGeoSelectChanged", "chartGeoSelected", "chartGeoUnselected", "chartAxisAreaSelected", "chartBrush", "chartBrushEnd", "chartBrushSelected", "chartGlobalCursorTaken", "chartRendered", "chartFinished"], exportAs: ["echarts"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: ChartAlertsComponent, selector: "c8y-chart-alerts", inputs: ["alerts"] }, { kind: "ngmodule", type: AlarmsModule }, { kind: "component", type: SelectAggregatedDatapointComponent, selector: "c8y-select-aggregated-datapoint", inputs: ["activeDatapoints", "value"], outputs: ["valueChange"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i1.C8yTranslatePipe, name: "translate" }] }); }
2565
2609
  }
2566
2610
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ChartsComponent, decorators: [{
2567
2611
  type: Component,
@@ -2585,7 +2629,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
2585
2629
  ChartAlertsComponent,
2586
2630
  AlarmsModule,
2587
2631
  SelectAggregatedDatapointComponent
2588
- ], template: "<div class=\"p-relative fit-h chart-container\">\n <div\n class=\"fit-w fit-h\"\n #chart\n echarts\n [options]=\"chartOption$ | async\"\n (chartInit)=\"onChartInit($event)\"\n ></div>\n\n <c8y-chart-alerts [alerts]=\"alerts\"></c8y-chart-alerts>\n\n <div\n class=\"chart-load-more\"\n *ngIf=\"showLoadMore\"\n >\n <button\n class=\"btn btn-primary btn-block\"\n (click)=\"loadMoreData()\"\n >\n <i c8yIcon=\"restore\"></i>\n {{ 'Load more' | translate }}\n </button>\n </div>\n\n <div\n class=\"e-charts--aggregated-datapoint\"\n *ngIf=\"\n activeDatapoints.length > 1 &&\n config?.showSlider &&\n chartViewContext !== CHART_VIEW_CONTEXT.WIDGET_VIEW\n \"\n >\n <c8y-select-aggregated-datapoint\n [value]=\"config?.aggregatedDatapoint || activeDatapoints[0]\"\n (valueChange)=\"updateAggregatedSliderDatapoint.emit($event)\"\n [activeDatapoints]=\"activeDatapoints\"\n ></c8y-select-aggregated-datapoint>\n </div>\n</div>\n" }]
2632
+ ], template: "<div class=\"p-relative fit-h chart-container\">\n <div\n class=\"fit-w fit-h\"\n #chart\n echarts\n [options]=\"chartOption$ | async\"\n (chartInit)=\"onChartInit($event)\"\n ></div>\n\n <c8y-chart-alerts [alerts]=\"alerts\"></c8y-chart-alerts>\n\n @if (showLoadMore) {\n <div class=\"chart-load-more\">\n <button\n class=\"btn btn-primary btn-block\"\n [disabled]=\"isFetching\"\n (click)=\"loadMoreData()\"\n >\n <i c8yIcon=\"restore\"></i>\n {{ 'Load more' | translate }}\n </button>\n </div>\n }\n\n @if (\n activeDatapoints.length > 1 &&\n config?.showSlider &&\n chartViewContext !== CHART_VIEW_CONTEXT.WIDGET_VIEW\n ) {\n <div class=\"e-charts--aggregated-datapoint\">\n <c8y-select-aggregated-datapoint\n [value]=\"config?.aggregatedDatapoint || activeDatapoints[0]\"\n (valueChange)=\"updateAggregatedSliderDatapoint.emit($event)\"\n [activeDatapoints]=\"activeDatapoints\"\n ></c8y-select-aggregated-datapoint>\n </div>\n }\n</div>\n" }]
2589
2633
  }], ctorParameters: () => [], propDecorators: { config: [{
2590
2634
  type: Input
2591
2635
  }], alerts: [{