@c8y/ngx-components 1023.14.157 → 1023.14.160

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.
package/echart/index.d.ts CHANGED
@@ -306,15 +306,17 @@ declare class ChartsComponent implements OnChanges, OnInit, OnDestroy {
306
306
  loadMoreData(): void;
307
307
  debounce<T extends (...args: any[]) => void>(func: T, wait: number): (...args: Parameters<T>) => void;
308
308
  /**
309
- * Toggles the visibility of a series in the chart based on the provided datapoint.
310
- * Uses explicit legendSelect/legendUnSelect based on __active state.
309
+ * Toggles datapoint series visibility via legendSelect/legendUnSelect.
310
+ * Also syncs mark-point (icon) visibility: hidden when the datapoint is hidden
311
+ * (icon has nothing to attach to), re-shown only if the alarm/event is still visible.
312
+ * Mark-lines (vertical lines) are left untouched — they stay visible regardless.
311
313
  * @param datapoint - The datapoint to toggle visibility for.
312
314
  */
313
315
  toggleDatapointSeriesVisibility(datapoint: DatapointsGraphKPIDetails): void;
314
316
  /**
315
- * Toggles the visibility of alarm/event series in the chart.
316
- * Uses explicit legendSelect/legendUnSelect based on __hidden state.
317
- * Targets specific device's series using type + deviceId.
317
+ * Toggles alarm/event series visibility via legendSelect/legendUnSelect.
318
+ * Matches all mark-line and mark-point series for the alarm type across every axis,
319
+ * because getAlarmOrEventSeries creates one series per datapoint axis.
318
320
  * @param alarmOrEvent - The alarm or event to toggle visibility for.
319
321
  */
320
322
  toggleAlarmEventSeriesVisibility(alarmOrEvent: AlarmOrEventExtended): void;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sources":["../../echart/models/datapoints-graph-widget.model.ts","../../echart/models/chart.model.ts","../../echart/models/svg-icons.model.ts","../../echart/charts.component.ts","../../echart/services/chart-alarms.service.ts","../../echart/services/chart-events.service.ts","../../echart/services/chart-helpers.service.ts","../../echart/select-aggregated-datapoint/select-aggregated-datapoint.component.ts"],"sourcesContent":[null,null,null,null,null,null,null,null],"names":[],"mappings":";;;;;;;;;;;;;;AAoBM;;;;AAKA;AACJ;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;;;;;;;;AASA;;AAEA;AACA;AACA;AACA;AACA;;;AAGA;;;;;;;;;;AAWI;;;;;;;;;;AAUJ;;;AAII;;AAEJ;AACA;;AAGI;;;AAIN;;AAEG;;AAGG;AAIN;AACE;AACA;AACD;AAED;AACM;;AAEL;AAED;;;;AAIM;;;;;;;AAQL;AAED;;;;;AAUE;;;;;AAGD;;AAGC;;AAEA;;AAEE;;AAEF;;;AACD;;;;;;;AAQC;AACA;AACD;AAEK;AACA;AAEA;AAEA;AAEN;;;;AAKA;;;;;;;;;;;;;AAcM;AACA;AAEA;;;;AAKA;;;;;;;;;;;;AAaL;AAED;;;;;;;;AAUE;AACA;AACD;;ACtND;;;;;;AAMG;AACH;AACE;;;;AAIA;;;AACD;;;AAIA;;;AAIA;AAEK;AACA;AACJ;AACE;AACD;AACF;;AAGC;AACA;AACD;AAED;AACE;AACA;AACA;AACD;;AC3CD;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACD;AAED;;;;;;;;;;;AC2DA;AA4BE;;AAEA;;;;;;;;AAQA;;;;;;AAMK;AACK;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEV;;;;;AAgBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;AA4DA;;;;;AAoKuB;;;AAA4B;AAiDnD;AAOA;AAIA;AAwBA;AA6BA;AAWA;;;;AAIG;AACH;AAcA;;;;;AAKG;AACH;AAgCA;AAeA;AA0BA;;AA8DA;;;AAsNA;AAiEA;AAsDA;AAmBA;AAWA;AAYA;;;AA6BD;;ACjiCD;AAEc;AAAQ;AAEpB;;;;;AAKG;AACG;;;AAqCP;;AC/CD;AAEc;AAAQ;AAEpB;;;;;AAKG;AACG;;;AAuBP;;AChCD;AAEE;;;;AAIG;;;;;;;;;;;AAcH;AAcA;;;AAGD;;ACtBD;;AAqBW;AACC;AAEV;;AAGA;;;AAiBA;;;AAgBD;;;"}
1
+ {"version":3,"file":"index.d.ts","sources":["../../echart/models/datapoints-graph-widget.model.ts","../../echart/models/chart.model.ts","../../echart/models/svg-icons.model.ts","../../echart/charts.component.ts","../../echart/services/chart-alarms.service.ts","../../echart/services/chart-events.service.ts","../../echart/services/chart-helpers.service.ts","../../echart/select-aggregated-datapoint/select-aggregated-datapoint.component.ts"],"sourcesContent":[null,null,null,null,null,null,null,null],"names":[],"mappings":";;;;;;;;;;;;;;AAoBM;;;;AAKA;AACJ;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;;;;;;;;AASA;;AAEA;AACA;AACA;AACA;AACA;;;AAGA;;;;;;;;;;AAWI;;;;;;;;;;AAUJ;;;AAII;;AAEJ;AACA;;AAGI;;;AAIN;;AAEG;;AAGG;AAIN;AACE;AACA;AACD;AAED;AACM;;AAEL;AAED;;;;AAIM;;;;;;;AAQL;AAED;;;;;AAUE;;;;;AAGD;;AAGC;;AAEA;;AAEE;;AAEF;;;AACD;;;;;;;AAQC;AACA;AACD;AAEK;AACA;AAEA;AAEA;AAEN;;;;AAKA;;;;;;;;;;;;;AAcM;AACA;AAEA;;;;AAKA;;;;;;;;;;;;AAaL;AAED;;;;;;;;AAUE;AACA;AACD;;ACtND;;;;;;AAMG;AACH;AACE;;;;AAIA;;;AACD;;;AAIA;;;AAIA;AAEK;AACA;AACJ;AACE;AACD;AACF;;AAGC;AACA;AACD;AAED;AACE;AACA;AACA;AACD;;AC3CD;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACD;AAED;;;;;;;;;;;AC2DA;AA4BE;;AAEA;;;;;;;;AAQA;;;;;;AAMK;AACK;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEV;;;;;AAgBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;AA4DA;;;;;AAoKuB;;;AAA4B;AAiDnD;AAOA;AAIA;AAwBA;AA6BA;AAWA;;;;;;AAMG;AACH;AAoCA;;;;;AAKG;AACH;AA4BA;AAeA;AA0BA;;AA8DA;;;AA4OA;AAiEA;AAsDA;AAmBA;AAWA;AAYA;;;AA6BD;;AC3kCD;AAEc;AAAQ;AAEpB;;;;;AAKG;AACG;;;AAqCP;;AC/CD;AAEc;AAAQ;AAEpB;;;;;AAKG;AACG;;;AAuBP;;AChCD;AAEE;;;;AAIG;;;;;;;;;;;AAcH;AAcA;;;AAGD;;ACtBD;;AAqBW;AACC;AAEV;;AAGA;;;AAiBA;;;AAgBD;;;"}
@@ -565,8 +565,8 @@ class EchartsOptionsService {
565
565
  show: false
566
566
  },
567
567
  xAxis: {
568
- min: Object.keys(aggregatedDatapoint.values || {}).length > 0
569
- ? Math.min(Object.keys(aggregatedDatapoint.values)
568
+ min: Object.keys(aggregatedDatapoint?.values || {}).length > 0
569
+ ? Math.min(Object.keys(aggregatedDatapoint?.values || {})
570
570
  .map(date => new Date(date).valueOf())
571
571
  .sort((a, b) => a - b)[0], new Date(timeRange.dateFrom).valueOf())
572
572
  : new Date(timeRange.dateFrom).valueOf() - intervalInMs,
@@ -662,6 +662,9 @@ class EchartsOptionsService {
662
662
  return intervalInMs;
663
663
  }
664
664
  getAggregatedSeries(aggregatedDatapoint, displayOptions) {
665
+ if (!aggregatedDatapoint) {
666
+ return { type: 'line', data: [], id: 'aggregated-empty' };
667
+ }
665
668
  const series = [];
666
669
  const renderType = aggregatedDatapoint?.renderType || 'min';
667
670
  const idx = 0;
@@ -1116,6 +1119,25 @@ class EchartsOptionsService {
1116
1119
  eventSeries = [...eventSeries, ...newEventSeries];
1117
1120
  alarmSeries = [...alarmSeries, ...newAlarmSeries];
1118
1121
  });
1122
+ // markLine series are x-axis-only vertical lines: they render identically regardless of
1123
+ // yAxisIndex. getAlarmOrEventSeries creates one per datapoint (as a side-effect of always
1124
+ // pairing markLine with markPoint), so with N datapoints there are N redundant copies.
1125
+ // Deduplicate to one per alarm/event type before the selectedDatapoint deduplication below.
1126
+ const deduplicateMarkLines = (seriesList) => {
1127
+ const seenTypes = new Set();
1128
+ return seriesList.filter(s => {
1129
+ const id = s.id;
1130
+ if (!id.endsWith('-markLine')) {
1131
+ return true;
1132
+ }
1133
+ const [type] = id.split('/');
1134
+ const isFirstOfType = !seenTypes.has(type);
1135
+ seenTypes.add(type);
1136
+ return isFirstOfType;
1137
+ });
1138
+ };
1139
+ alarmSeries = deduplicateMarkLines(alarmSeries);
1140
+ eventSeries = deduplicateMarkLines(eventSeries);
1119
1141
  const deduplicateFilterCallback = (obj1, i, arr) => {
1120
1142
  const duplicates = arr.filter(obj2 => obj1['id'] === obj2['id'] && i !== arr.indexOf(obj2));
1121
1143
  if (duplicates.length > 0) {
@@ -1530,7 +1552,7 @@ class ChartRealtimeService {
1530
1552
  this.activeDatapoints = [];
1531
1553
  this.outOfSyncDatapoints = new Set();
1532
1554
  }
1533
- startRealtime(echartsInstance, datapoints, timeRange, datapointOutOfSyncCallback, datapointBackInSyncCallback, timeRangeChangedCallback, alarmOrEventConfig = [], displayOptions, alarms, events) {
1555
+ startRealtime(echartsInstance, datapoints, timeRange, datapointOutOfSyncCallback, datapointBackInSyncCallback, timeRangeChangedCallback, alarmOrEventConfig = [], displayOptions, alarms, events, alarmOrEventReceivedCallback) {
1534
1556
  this.echartsInstance = echartsInstance;
1535
1557
  this.activeDatapoints = datapoints;
1536
1558
  this.currentTimeRange = {
@@ -1631,6 +1653,7 @@ class ChartRealtimeService {
1631
1653
  alarmOrEvent['selectedDatapoint'] = foundAlarmOrEvent.selectedDatapoint;
1632
1654
  const key = String(alarmOrEvent.id || alarmOrEvent.creationTime);
1633
1655
  this.pendingAlarmsOrEvents.set(key, alarmOrEvent);
1656
+ alarmOrEventReceivedCallback?.(alarmOrEvent);
1634
1657
  }
1635
1658
  return null;
1636
1659
  }))
@@ -1770,15 +1793,16 @@ class ChartRealtimeService {
1770
1793
  allDataSeries.push(...newEventSeries);
1771
1794
  }
1772
1795
  else if (isAlarm(alarmOrEvent)) {
1773
- // For alarms, remove existing series for this alarm type + device before adding.
1774
- // This ensures alarm status changes (e.g., ACTIVE CLEARED) are reflected.
1775
- // Series ID format: ${alarmType}/${deviceId}-markPoint/markLine
1796
+ // For alarms, remove ALL existing series for this alarm type before adding the updated
1797
+ // series. The markLine series is keyed to whichever datapoint was first in the initial
1798
+ // render loop not necessarily the alarm source device. Filtering by the alarm's
1799
+ // source device ID alone would miss it, leaving a stale markLine on the chart.
1776
1800
  const alarm = alarmOrEvent;
1777
1801
  const alarmType = alarm.type;
1778
- const datapointTargetId = datapoint.__target?.id;
1779
1802
  allDataSeries = allDataSeries.filter((series) => {
1780
1803
  const seriesId = series['id'];
1781
- return !seriesId?.startsWith(`${alarmType}/${datapointTargetId}`);
1804
+ return !(seriesId?.startsWith(`${alarmType}/`) &&
1805
+ (seriesId?.endsWith('-markLine') || seriesId?.endsWith('-markPoint')));
1782
1806
  });
1783
1807
  // For alarms, pass null as id - we want one series per alarm type/device.
1784
1808
  // Series ID will be: alarmType/deviceId-markPoint (no unique suffix).
@@ -2366,24 +2390,46 @@ class ChartsComponent {
2366
2390
  };
2367
2391
  }
2368
2392
  /**
2369
- * Toggles the visibility of a series in the chart based on the provided datapoint.
2370
- * Uses explicit legendSelect/legendUnSelect based on __active state.
2393
+ * Toggles datapoint series visibility via legendSelect/legendUnSelect.
2394
+ * Also syncs mark-point (icon) visibility: hidden when the datapoint is hidden
2395
+ * (icon has nothing to attach to), re-shown only if the alarm/event is still visible.
2396
+ * Mark-lines (vertical lines) are left untouched — they stay visible regardless.
2371
2397
  * @param datapoint - The datapoint to toggle visibility for.
2372
2398
  */
2373
2399
  toggleDatapointSeriesVisibility(datapoint) {
2374
- const series = this.echartsInstance.getOption().series;
2375
- const seriesToUpdate = series.find(s => s.datapointId === `${datapoint.__target?.id}${datapoint.fragment}${datapoint.series}`);
2400
+ const allSeries = this.echartsInstance.getOption().series;
2401
+ const seriesToUpdate = allSeries.find(s => s.datapointId === `${datapoint.__target?.id}${datapoint.fragment}${datapoint.series}`);
2376
2402
  if (seriesToUpdate) {
2377
2403
  this.echartsInstance.dispatchAction({
2378
2404
  type: datapoint.__active ? 'legendSelect' : 'legendUnSelect',
2379
2405
  name: seriesToUpdate.name
2380
2406
  });
2381
2407
  }
2408
+ const deviceId = datapoint.__target?.id;
2409
+ const isHiding = !datapoint.__active;
2410
+ const visibleTypes = new Set(this.config.alarmsEventsConfigs
2411
+ ?.filter(ae => !ae.__hidden && ae.__active)
2412
+ .map(ae => ae.filters.type));
2413
+ allSeries
2414
+ .filter(s => typeof s.name === 'string' && s.name.endsWith(`/${deviceId}-markPoint`))
2415
+ .forEach(s => {
2416
+ const name = s.name;
2417
+ if (isHiding) {
2418
+ this.echartsInstance.dispatchAction({ type: 'legendUnSelect', name });
2419
+ }
2420
+ else {
2421
+ // Re-show only if the alarm/event is itself still visible
2422
+ const type = name.split('/')[0];
2423
+ if (visibleTypes?.has(type)) {
2424
+ this.echartsInstance.dispatchAction({ type: 'legendSelect', name });
2425
+ }
2426
+ }
2427
+ });
2382
2428
  }
2383
2429
  /**
2384
- * Toggles the visibility of alarm/event series in the chart.
2385
- * Uses explicit legendSelect/legendUnSelect based on __hidden state.
2386
- * Targets specific device's series using type + deviceId.
2430
+ * Toggles alarm/event series visibility via legendSelect/legendUnSelect.
2431
+ * Matches all mark-line and mark-point series for the alarm type across every axis,
2432
+ * because getAlarmOrEventSeries creates one series per datapoint axis.
2387
2433
  * @param alarmOrEvent - The alarm or event to toggle visibility for.
2388
2434
  */
2389
2435
  toggleAlarmEventSeriesVisibility(alarmOrEvent) {
@@ -2396,13 +2442,9 @@ class ChartsComponent {
2396
2442
  return;
2397
2443
  }
2398
2444
  const type = alarmOrEvent.filters.type;
2399
- const deviceId = alarmOrEvent.__target?.id;
2400
2445
  const actionType = alarmOrEvent.__hidden ? 'legendUnSelect' : 'legendSelect';
2401
- // Series names are: ${type}/${deviceId}-markPoint and ${type}/${deviceId}-markLine
2402
- const markPointName = `${type}/${deviceId}-markPoint`;
2403
- const markLineName = `${type}/${deviceId}-markLine`;
2404
- // Find series matching this specific alarm type + device
2405
- const matchingSeries = allSeries.filter(s => s.name === markPointName || s.name === markLineName);
2446
+ const matchingSeries = allSeries.filter(s => s.name?.startsWith(`${type}/`) &&
2447
+ (s.name?.endsWith('-markLine') || s.name?.endsWith('-markPoint')));
2406
2448
  matchingSeries.forEach(series => {
2407
2449
  this.echartsInstance.dispatchAction({
2408
2450
  type: actionType,
@@ -2510,7 +2552,27 @@ class ChartsComponent {
2510
2552
  showLabelAndUnit: this.config.showLabelAndUnit || false,
2511
2553
  showSlider: this.config.showSlider || false,
2512
2554
  showOnlyAlarmsOrEvents
2513
- }, this.alarms, this.events);
2555
+ }, this.alarms, this.events,
2556
+ // Keep this.alarms/events in sync with realtime updates so that
2557
+ // isAlarmOrEventClick() and the tooltip formatter have current data.
2558
+ alarmOrEvent => {
2559
+ if ('severity' in alarmOrEvent) {
2560
+ const alarm = alarmOrEvent;
2561
+ const existingIdx = this.alarms.findIndex(a => a.id === alarm.id);
2562
+ if (existingIdx !== -1) {
2563
+ this.alarms[existingIdx] = alarm;
2564
+ }
2565
+ else {
2566
+ this.alarms.push(alarm);
2567
+ }
2568
+ }
2569
+ else {
2570
+ const event = alarmOrEvent;
2571
+ if (!this.events.some(e => e.id === event.id)) {
2572
+ this.events.push(event);
2573
+ }
2574
+ }
2575
+ });
2514
2576
  }
2515
2577
  }
2516
2578
  /*
@@ -2568,10 +2630,12 @@ class ChartsComponent {
2568
2630
  });
2569
2631
  const extendedDateFrom = new Date(new Date(timeRange.dateFrom).valueOf() - extendedIntervalMs).toISOString();
2570
2632
  this.widgetTimeContextDateRangeService.updateInitialTimeRange(timeRange);
2571
- const aggregatedDatapoints = await lastValueFrom(this.fetchAggregatedSeriesForSelectedDatapoint$({
2572
- dateFrom: extendedDateFrom,
2573
- dateTo: timeRange.dateTo
2574
- }, this.config.aggregatedDatapoint));
2633
+ const aggregatedDatapoint = this.config.showSlider
2634
+ ? await lastValueFrom(this.fetchAggregatedSeriesForSelectedDatapoint$({
2635
+ dateFrom: extendedDateFrom,
2636
+ dateTo: timeRange.dateTo
2637
+ }, this.config.aggregatedDatapoint))
2638
+ : undefined;
2575
2639
  return this.echartsOptionsService.getChartOptions(datapointsWithValues, timeRange, {
2576
2640
  YAxis: this.config.yAxisSplitLines || false,
2577
2641
  XAxis: this.config.xAxisSplitLines || false
@@ -2586,7 +2650,7 @@ class ChartsComponent {
2586
2650
  numberOfDecimalPlaces: this.config.numberOfDecimalPlaces ?? 2,
2587
2651
  axisColor: this.axisColor,
2588
2652
  sliderPositionMode
2589
- }, undefined, aggregatedDatapoints);
2653
+ }, undefined, aggregatedDatapoint);
2590
2654
  }
2591
2655
  else {
2592
2656
  const cachedTimeRange = this.widgetTimeContextDateRangeService.initialTimeRange();
@@ -2596,10 +2660,12 @@ class ChartsComponent {
2596
2660
  dateTo: cachedTimeRange.dateTo
2597
2661
  });
2598
2662
  const initialExtendedDateFrom = new Date(initialDateFromValue - calculateInitialIntervalInMs).toISOString();
2599
- const aggregatedDatapoints = await lastValueFrom(this.fetchAggregatedSeriesForSelectedDatapoint$({
2600
- dateFrom: initialExtendedDateFrom,
2601
- dateTo: new Date(this.widgetTimeContextDateRangeService.initialTimeRange().dateTo).toISOString()
2602
- }, this.config.aggregatedDatapoint));
2663
+ const aggregatedDatapoint = this.config.showSlider
2664
+ ? await lastValueFrom(this.fetchAggregatedSeriesForSelectedDatapoint$({
2665
+ dateFrom: initialExtendedDateFrom,
2666
+ dateTo: new Date(this.widgetTimeContextDateRangeService.initialTimeRange().dateTo).toISOString()
2667
+ }, this.config.aggregatedDatapoint))
2668
+ : undefined;
2603
2669
  // we need to update the initial time range by adding the refresh interval to the dateFrom and dateTo
2604
2670
  const initialTimeRange = this.widgetTimeContextDateRangeService.initialTimeRange();
2605
2671
  // needed due to a race condition where the time range is updated before the chart options are fetched...
@@ -2626,7 +2692,7 @@ class ChartsComponent {
2626
2692
  numberOfDecimalPlaces: this.config.numberOfDecimalPlaces ?? 2,
2627
2693
  axisColor: this.axisColor,
2628
2694
  sliderPositionMode
2629
- }, timeRange, aggregatedDatapoints, true);
2695
+ }, timeRange, aggregatedDatapoint, true);
2630
2696
  }
2631
2697
  }
2632
2698
  fetchSeriesForDatapoints$() {