@c8y/ngx-components 1023.14.154 → 1023.14.157

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.
@@ -1528,8 +1528,9 @@ class ChartRealtimeService {
1528
1528
  this.currentAlarms = [];
1529
1529
  this.currentEvents = [];
1530
1530
  this.activeDatapoints = [];
1531
+ this.outOfSyncDatapoints = new Set();
1531
1532
  }
1532
- startRealtime(echartsInstance, datapoints, timeRange, datapointOutOfSyncCallback, timeRangeChangedCallback, alarmOrEventConfig = [], displayOptions, alarms, events) {
1533
+ startRealtime(echartsInstance, datapoints, timeRange, datapointOutOfSyncCallback, datapointBackInSyncCallback, timeRangeChangedCallback, alarmOrEventConfig = [], displayOptions, alarms, events) {
1533
1534
  this.echartsInstance = echartsInstance;
1534
1535
  this.activeDatapoints = datapoints;
1535
1536
  this.currentTimeRange = {
@@ -1594,9 +1595,11 @@ class ChartRealtimeService {
1594
1595
  const updateThrottleTime = this.getRealtimeUpdateThrottleTime(timeRange);
1595
1596
  const measurement$ = merge(...measurementsForDatapoints);
1596
1597
  const bufferReset$ = merge(measurement$.pipe(throttleTime(updateThrottleTime)), interval(this.INTERVAL).pipe(tap(() => {
1598
+ const windowSize = this.currentTimeRange.dateTo.valueOf() - this.currentTimeRange.dateFrom.valueOf();
1599
+ const now = Date.now();
1597
1600
  this.currentTimeRange = {
1598
- dateFrom: new Date((this.currentTimeRange?.dateFrom?.valueOf() || 0) + this.INTERVAL),
1599
- dateTo: new Date((this.currentTimeRange?.dateTo?.valueOf() || 0) + this.INTERVAL)
1601
+ dateFrom: new Date(now - windowSize),
1602
+ dateTo: new Date(now)
1600
1603
  };
1601
1604
  timeRangeChangedCallback(this.currentTimeRange);
1602
1605
  }), throttleTime(updateThrottleTime))).pipe(throttleTime(this.MIN_REALTIME_TIMEOUT));
@@ -1607,11 +1610,11 @@ class ChartRealtimeService {
1607
1610
  this.pendingAlarmsOrEvents.clear();
1608
1611
  if (alarmsOrEvents.length) {
1609
1612
  alarmsOrEvents.forEach(alarmOrEvent => {
1610
- this.updateChartInstance(measurements, alarmOrEvent, displayOptions, datapointOutOfSyncCallback);
1613
+ this.updateChartInstance(measurements, alarmOrEvent, displayOptions, datapointOutOfSyncCallback, datapointBackInSyncCallback);
1611
1614
  });
1612
1615
  }
1613
1616
  else {
1614
- this.updateChartInstance(measurements, null, displayOptions, datapointOutOfSyncCallback);
1617
+ this.updateChartInstance(measurements, null, displayOptions, datapointOutOfSyncCallback, datapointBackInSyncCallback);
1615
1618
  }
1616
1619
  // Store the last measurements
1617
1620
  measurements.forEach(measurement => {
@@ -1679,7 +1682,7 @@ class ChartRealtimeService {
1679
1682
  }
1680
1683
  return calculatedThrottleTime;
1681
1684
  }
1682
- updateChartInstance(receivedMeasurements, alarmOrEvent, displayOptions, datapointOutOfSyncCallback) {
1685
+ updateChartInstance(receivedMeasurements, alarmOrEvent, displayOptions, datapointOutOfSyncCallback, datapointBackInSyncCallback) {
1683
1686
  const isEvent = (item) => !('severity' in item);
1684
1687
  const isAlarm = (item) => 'severity' in item;
1685
1688
  const seriesDataToUpdate = new Map();
@@ -1714,7 +1717,7 @@ class ChartRealtimeService {
1714
1717
  }
1715
1718
  }
1716
1719
  seriesMatchingDatapoint['data'] = this.removeValuesBeforeTimeRange(seriesMatchingDatapoint);
1717
- this.checkForValuesAfterTimeRange(seriesMatchingDatapoint['data'], datapoint, datapointOutOfSyncCallback);
1720
+ this.checkForValuesAfterTimeRange(seriesMatchingDatapoint['data'], datapoint, datapointOutOfSyncCallback, datapointBackInSyncCallback);
1718
1721
  });
1719
1722
  // Process alarm/event OUTSIDE the measurement loop.
1720
1723
  // Previously this was inside seriesDataToUpdate.forEach(), which meant alarms/events
@@ -1805,26 +1808,32 @@ class ChartRealtimeService {
1805
1808
  /**
1806
1809
  * Detects if a datapoint has measurements with future timestamps (out-of-sync).
1807
1810
  *
1808
- * Why 300ms tolerance?
1811
+ * Why 2000ms tolerance?
1809
1812
  * Device clocks may be slightly ahead of browser time, network latency, or processing delays.
1810
1813
  * Without tolerance, these minor drifts would cause false positive warnings.
1811
1814
  *
1812
1815
  * Example:
1813
1816
  * Browser time: 12:00:00.000
1814
- * Measurement: 12:00:00.200 (device 200ms ahead)
1817
+ * Measurement: 12:00:01.000 (device 1000ms ahead)
1815
1818
  * Without tolerance: flagged as out-of-sync (false positive)
1816
- * With 300ms tolerance: allowed (200ms < 300ms threshold)
1819
+ * With 2000ms tolerance: allowed (1000ms < 2000ms threshold)
1817
1820
  *
1818
1821
  * When triggered, a warning icon appears next to the datapoint in the legend.
1819
1822
  */
1820
- checkForValuesAfterTimeRange(data, datapoint, datapointOutOfSyncCallback) {
1821
- const nowWithTolerance = Date.now() + 300;
1823
+ checkForValuesAfterTimeRange(data, datapoint, datapointOutOfSyncCallback, datapointBackInSyncCallback) {
1824
+ const nowWithTolerance = Date.now() + 2000;
1822
1825
  const valueAfterNowExists = data.some(([dateString]) => {
1823
1826
  return new Date(dateString).valueOf() > nowWithTolerance;
1824
1827
  });
1828
+ const datapointId = datapoint.__target?.id + datapoint.fragment + datapoint.series;
1825
1829
  if (valueAfterNowExists) {
1830
+ this.outOfSyncDatapoints.add(datapointId);
1826
1831
  datapointOutOfSyncCallback(datapoint);
1827
1832
  }
1833
+ else if (this.outOfSyncDatapoints.has(datapointId)) {
1834
+ this.outOfSyncDatapoints.delete(datapointId);
1835
+ datapointBackInSyncCallback(datapoint);
1836
+ }
1828
1837
  }
1829
1838
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: ChartRealtimeService, deps: [{ token: i1.MeasurementRealtimeService }, { token: i1.AlarmRealtimeService }, { token: i1.EventRealtimeService }, { token: EchartsOptionsService }], target: i0.ɵɵFactoryTarget.Injectable }); }
1830
1839
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: ChartRealtimeService }); }
@@ -2062,6 +2071,7 @@ class ChartsComponent {
2062
2071
  this.configChangeOnZoomOut = new EventEmitter();
2063
2072
  this.timeRangeChangeOnRealtime = new EventEmitter();
2064
2073
  this.datapointOutOfSync = new EventEmitter();
2074
+ this.datapointBackInSync = new EventEmitter();
2065
2075
  this.updateAlarmsAndEvents = new EventEmitter();
2066
2076
  this.isMarkedAreaEnabled = new EventEmitter();
2067
2077
  this.finishLoading = new EventEmitter(false);
@@ -2491,7 +2501,7 @@ class ChartsComponent {
2491
2501
  this.config.realtime &&
2492
2502
  this.echartsInstance) {
2493
2503
  const showOnlyAlarmsOrEvents = this.config.alarmsEventsConfigs?.length > 0 && this.activeDatapoints?.length === 0;
2494
- this.chartRealtimeService.startRealtime(this.echartsInstance, this.activeDatapoints, this.getTimeRange(), dp => this.datapointOutOfSync.emit(dp), timeRange => this.timeRangeChangeOnRealtime.emit(timeRange), this.config.alarmsEventsConfigs, {
2504
+ this.chartRealtimeService.startRealtime(this.echartsInstance, this.activeDatapoints, this.getTimeRange(), dp => this.datapointOutOfSync.emit(dp), dp => this.datapointBackInSync.emit(dp), timeRange => this.timeRangeChangeOnRealtime.emit(timeRange), this.config.alarmsEventsConfigs, {
2495
2505
  displayMarkedLine: this.config.displayMarkedLine || false,
2496
2506
  displayMarkedPoint: this.config.displayMarkedPoint || false,
2497
2507
  mergeMatchingDatapoints: this.config.mergeMatchingDatapoints || false,
@@ -2773,7 +2783,7 @@ class ChartsComponent {
2773
2783
  return { dateFrom: timeRange.dateFrom.toISOString(), dateTo: timeRange.dateTo.toISOString() };
2774
2784
  }
2775
2785
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: ChartsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2776
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", 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: [
2786
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: ChartsComponent, isStandalone: true, selector: "c8y-charts", inputs: { config: "config", alerts: "alerts", chartViewContext: "chartViewContext" }, outputs: { configChangeOnZoomOut: "configChangeOnZoomOut", timeRangeChangeOnRealtime: "timeRangeChangeOnRealtime", datapointOutOfSync: "datapointOutOfSync", datapointBackInSync: "datapointBackInSync", updateAlarmsAndEvents: "updateAlarmsAndEvents", isMarkedAreaEnabled: "isMarkedAreaEnabled", finishLoading: "finishLoading", updateActiveDatapoints: "updateActiveDatapoints", updateAggregatedSliderDatapoint: "updateAggregatedSliderDatapoint" }, providers: [
2777
2787
  { provide: NGX_ECHARTS_CONFIG, useFactory: () => ({ echarts: () => import('echarts') }) },
2778
2788
  ChartRealtimeService,
2779
2789
  MeasurementRealtimeService,
@@ -2821,6 +2831,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
2821
2831
  type: Output
2822
2832
  }], datapointOutOfSync: [{
2823
2833
  type: Output
2834
+ }], datapointBackInSync: [{
2835
+ type: Output
2824
2836
  }], updateAlarmsAndEvents: [{
2825
2837
  type: Output
2826
2838
  }], isMarkedAreaEnabled: [{