@c8y/ngx-components 1023.14.102 → 1023.14.103
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 +5 -2
- package/echart/index.d.ts.map +1 -1
- package/fesm2022/c8y-ngx-components-echart.mjs +96 -42
- package/fesm2022/c8y-ngx-components-echart.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-graph.mjs +55 -51
- package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-graph.mjs.map +1 -1
- package/package.json +1 -1
- package/widgets/implementations/datapoints-graph/index.d.ts +6 -3
- package/widgets/implementations/datapoints-graph/index.d.ts.map +1 -1
package/echart/index.d.ts
CHANGED
|
@@ -293,14 +293,17 @@ declare class ChartsComponent implements OnChanges, OnInit, OnDestroy {
|
|
|
293
293
|
debounce<T extends (...args: any[]) => void>(func: T, wait: number): (...args: Parameters<T>) => void;
|
|
294
294
|
/**
|
|
295
295
|
* Toggles the visibility of a series in the chart based on the provided datapoint.
|
|
296
|
+
* Uses explicit legendSelect/legendUnSelect based on __active state.
|
|
296
297
|
* @param datapoint - The datapoint to toggle visibility for.
|
|
297
298
|
*/
|
|
298
299
|
toggleDatapointSeriesVisibility(datapoint: DatapointsGraphKPIDetails): void;
|
|
299
300
|
/**
|
|
300
|
-
* Toggles the visibility of
|
|
301
|
+
* Toggles the visibility of alarm/event series in the chart.
|
|
302
|
+
* Uses explicit legendSelect/legendUnSelect based on __hidden state.
|
|
303
|
+
* Targets specific device's series using type + deviceId.
|
|
301
304
|
* @param alarmOrEvent - The alarm or event to toggle visibility for.
|
|
302
305
|
*/
|
|
303
|
-
toggleAlarmEventSeriesVisibility(alarmOrEvent:
|
|
306
|
+
toggleAlarmEventSeriesVisibility(alarmOrEvent: AlarmOrEventExtended): void;
|
|
304
307
|
private getDefaultChartOptions;
|
|
305
308
|
private getMarkedAreaData;
|
|
306
309
|
private getMarkedLineData;
|
package/echart/index.d.ts.map
CHANGED
|
@@ -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":";;;;;;;;;;;;;;AAmBM;;;;AAKA;AACJ;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;;;;;;AAOA;;AAEA;AACA;AACA;AACA;;;AAGA;;;;;;;;;AAUI;;;;;;;;;;AAUJ;;AAGI;;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;;;;;;;;;;;AAYL;AAED;;;;;;;;AAUE;AACA;AACD;;AC9MD;;;;;;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;;;;;;;;;;;ACwDA;AA4BE;;AAEA;;;;;;;;AAQA;;;;;;AAMK;AACK;AAGA;AACA;AACA;AACA;AACA;AACA;;AAEV;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;AAgDA;;;;;AA2IuB;;;AAA4B;AAiDnD;AAOA;AAIA;AAwBA;AA6BA;AAWA
|
|
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":";;;;;;;;;;;;;;AAmBM;;;;AAKA;AACJ;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;;;;;;AAOA;;AAEA;AACA;AACA;AACA;;;AAGA;;;;;;;;;AAUI;;;;;;;;;;AAUJ;;AAGI;;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;;;;;;;;;;;AAYL;AAED;;;;;;;;AAUE;AACA;AACD;;AC9MD;;;;;;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;;;;;;;;;;;ACwDA;AA4BE;;AAEA;;;;;;;;AAQA;;;;;;AAMK;AACK;AAGA;AACA;AACA;AACA;AACA;AACA;;AAEV;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;AAgDA;;;;;AA2IuB;;;AAA4B;AAiDnD;AAOA;AAIA;AAwBA;AA6BA;AAWA;;;;AAIG;AACH;AAcA;;;;;AAKG;AACH;AAgCA;AAeA;AA0BA;;AA8DA;;;AA8MA;AA0DA;AA0CA;AAkBA;AAWA;AAYA;;;AA6BD;;AC98BD;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;;;"}
|
|
@@ -736,8 +736,8 @@ class EchartsOptionsService {
|
|
|
736
736
|
}, []);
|
|
737
737
|
// Construct series with markPoint
|
|
738
738
|
const seriesWithMarkPoint = {
|
|
739
|
-
id: `${type}/${dp.__target?.id}
|
|
740
|
-
name: `${type}-markPoint`,
|
|
739
|
+
id: `${type}/${dp.__target?.id}${id ? '+' + id : ''}-markPoint`,
|
|
740
|
+
name: `${type}/${dp.__target?.id}-markPoint`,
|
|
741
741
|
typeOfSeries: itemType,
|
|
742
742
|
data: mainData,
|
|
743
743
|
isDpTemplateSelected,
|
|
@@ -754,8 +754,8 @@ class EchartsOptionsService {
|
|
|
754
754
|
const markLineData = this.createMarkLine(itemsOfType, itemType);
|
|
755
755
|
// Construct series with markLine
|
|
756
756
|
const seriesWithMarkLine = {
|
|
757
|
-
id: `${type}/${dp.__target?.id}
|
|
758
|
-
name: `${type}-markLine`,
|
|
757
|
+
id: `${type}/${dp.__target?.id}${id ? '+' + id : ''}-markLine`,
|
|
758
|
+
name: `${type}/${dp.__target?.id}-markLine`,
|
|
759
759
|
typeOfSeries: itemType,
|
|
760
760
|
isDpTemplateSelected,
|
|
761
761
|
data: mainData,
|
|
@@ -1511,9 +1511,11 @@ class ChartRealtimeService {
|
|
|
1511
1511
|
this.pendingAlarmsOrEvents = new Map();
|
|
1512
1512
|
this.currentAlarms = [];
|
|
1513
1513
|
this.currentEvents = [];
|
|
1514
|
+
this.activeDatapoints = [];
|
|
1514
1515
|
}
|
|
1515
1516
|
startRealtime(echartsInstance, datapoints, timeRange, datapointOutOfSyncCallback, timeRangeChangedCallback, alarmOrEventConfig = [], displayOptions, alarms, events) {
|
|
1516
1517
|
this.echartsInstance = echartsInstance;
|
|
1518
|
+
this.activeDatapoints = datapoints;
|
|
1517
1519
|
this.currentTimeRange = {
|
|
1518
1520
|
dateFrom: new Date(timeRange.dateFrom),
|
|
1519
1521
|
dateTo: new Date(timeRange.dateTo)
|
|
@@ -1602,7 +1604,9 @@ class ChartRealtimeService {
|
|
|
1602
1604
|
});
|
|
1603
1605
|
this.realtimeSubscriptionAlarmsEvents = allAlarmsAndEvents$
|
|
1604
1606
|
.pipe(map(alarmOrEvent => {
|
|
1605
|
-
|
|
1607
|
+
// Match by both type AND device source
|
|
1608
|
+
const foundAlarmOrEvent = activeAlarmsOrEvents.find(aOrE => aOrE.filters.type === alarmOrEvent.type &&
|
|
1609
|
+
aOrE.__target?.id === alarmOrEvent.source?.id);
|
|
1606
1610
|
if (foundAlarmOrEvent) {
|
|
1607
1611
|
alarmOrEvent['color'] = foundAlarmOrEvent.color;
|
|
1608
1612
|
alarmOrEvent['selectedDatapoint'] = foundAlarmOrEvent.selectedDatapoint;
|
|
@@ -1670,6 +1674,7 @@ class ChartRealtimeService {
|
|
|
1670
1674
|
seriesDataToUpdate.get(datapoint)?.push(measurement);
|
|
1671
1675
|
});
|
|
1672
1676
|
let allDataSeries = this.echartsInstance?.getOption()['series'];
|
|
1677
|
+
// Process measurements for each datapoint
|
|
1673
1678
|
seriesDataToUpdate.forEach((measurements, datapoint) => {
|
|
1674
1679
|
const newValues = measurements.map(m => [
|
|
1675
1680
|
m.time,
|
|
@@ -1683,46 +1688,80 @@ class ChartRealtimeService {
|
|
|
1683
1688
|
const seriesDataToUpdate = seriesMatchingDatapoint['data'];
|
|
1684
1689
|
seriesDataToUpdate.push(...newValues);
|
|
1685
1690
|
seriesMatchingDatapoint['data'] = this.removeValuesBeforeTimeRange(seriesMatchingDatapoint);
|
|
1686
|
-
|
|
1691
|
+
this.checkForValuesAfterTimeRange(seriesMatchingDatapoint['data'], datapoint, datapointOutOfSyncCallback);
|
|
1692
|
+
});
|
|
1693
|
+
// Process alarm/event OUTSIDE the measurement loop.
|
|
1694
|
+
// Previously this was inside seriesDataToUpdate.forEach(), which meant alarms/events
|
|
1695
|
+
// were only processed when measurements existed for that datapoint. This caused
|
|
1696
|
+
// alarms/events to not appear on the chart when no measurements arrived in the interval.
|
|
1697
|
+
if (alarmOrEvent) {
|
|
1698
|
+
// The alarm config's selectedDatapoint is a partial object { target, fragment, series },
|
|
1699
|
+
// not a full DatapointsGraphKPIDetails. We need to find the matching full datapoint.
|
|
1700
|
+
const selectedDp = alarmOrEvent['selectedDatapoint'];
|
|
1701
|
+
// Find the correct datapoint to position this alarm/event on the chart:
|
|
1702
|
+
// 1. Use selectedDatapoint from alarm config (user-configured)
|
|
1703
|
+
// 2. Match by alarm's source device ID
|
|
1704
|
+
// 3. Fall back to first datapoint
|
|
1705
|
+
let datapoint = selectedDp
|
|
1706
|
+
? this.activeDatapoints.find(dp => dp.__target?.id === selectedDp.target &&
|
|
1707
|
+
dp.fragment === selectedDp.fragment &&
|
|
1708
|
+
dp.series === selectedDp.series)
|
|
1709
|
+
: undefined;
|
|
1710
|
+
if (!datapoint && alarmOrEvent['source']?.id) {
|
|
1711
|
+
datapoint = this.activeDatapoints.find(dp => dp.__target?.id === alarmOrEvent['source'].id);
|
|
1712
|
+
}
|
|
1713
|
+
if (!datapoint) {
|
|
1714
|
+
datapoint = this.activeDatapoints[0];
|
|
1715
|
+
}
|
|
1716
|
+
if (datapoint) {
|
|
1717
|
+
const datapointId = datapoint.__target?.id + datapoint.fragment + datapoint.series;
|
|
1718
|
+
const matchingSeries = allDataSeries.find(s => s['datapointId'] === datapointId);
|
|
1719
|
+
const seriesData = matchingSeries ? matchingSeries['data'] : [];
|
|
1720
|
+
// Convert ECharts series data format to the format expected by getAlarmOrEventSeries.
|
|
1721
|
+
// ECharts: [[timestamp, value], ...] → Expected: { [timestamp]: [{min, max}] }
|
|
1722
|
+
const values = {};
|
|
1723
|
+
seriesData.forEach(([timestamp, value]) => {
|
|
1724
|
+
values[timestamp] = [{ min: value, max: value }];
|
|
1725
|
+
});
|
|
1687
1726
|
const renderType = datapoint.renderType || 'min';
|
|
1688
1727
|
const dp = {
|
|
1689
1728
|
...datapoint,
|
|
1690
|
-
values
|
|
1729
|
+
values
|
|
1691
1730
|
};
|
|
1692
1731
|
if (isEvent(alarmOrEvent)) {
|
|
1693
|
-
// if event
|
|
1694
|
-
const eventExists = allDataSeries.some(series => series['data']
|
|
1732
|
+
// Check if event already exists on chart to avoid duplicates
|
|
1733
|
+
const eventExists = allDataSeries.some(series => series['data']?.some(data => data[0] === alarmOrEvent.creationTime));
|
|
1695
1734
|
if (eventExists) {
|
|
1696
1735
|
return;
|
|
1697
1736
|
}
|
|
1737
|
+
// For events, pass creationTime as unique id to create unique series per event.
|
|
1738
|
+
// This allows multiple events of the same type/device to coexist on the chart.
|
|
1739
|
+
// Series ID will be: eventType/deviceId+creationTime-markPoint
|
|
1698
1740
|
const newEventSeries = this.echartsOptionsService.getAlarmOrEventSeries(dp, renderType, false, [alarmOrEvent], 'event', displayOptions, alarmOrEvent.creationTime, null, true);
|
|
1699
1741
|
allDataSeries.push(...newEventSeries);
|
|
1700
1742
|
}
|
|
1701
1743
|
else if (isAlarm(alarmOrEvent)) {
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1744
|
+
// For alarms, remove existing series for this alarm type + device before adding.
|
|
1745
|
+
// This ensures alarm status changes (e.g., ACTIVE → CLEARED) are reflected.
|
|
1746
|
+
// Series ID format: ${alarmType}/${deviceId}-markPoint/markLine
|
|
1747
|
+
const alarm = alarmOrEvent;
|
|
1748
|
+
const alarmType = alarm.type;
|
|
1749
|
+
const datapointTargetId = datapoint.__target?.id;
|
|
1750
|
+
allDataSeries = allDataSeries.filter((series) => {
|
|
1751
|
+
const seriesId = series['id'];
|
|
1752
|
+
return !seriesId?.startsWith(`${alarmType}/${datapointTargetId}`);
|
|
1705
1753
|
});
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
// remove all matching alarm series which are in the array
|
|
1712
|
-
alarmSeries.forEach(series => {
|
|
1713
|
-
allDataSeries = allDataSeries.filter(s => s['id'] !== series['id']);
|
|
1714
|
-
});
|
|
1715
|
-
const newAlarmSeries = this.echartsOptionsService.getAlarmOrEventSeries(dp, renderType, false, [alarmOrEvent], 'alarm', displayOptions, alarmOrEvent.creationTime, null, true);
|
|
1716
|
-
allDataSeries.push(...newAlarmSeries);
|
|
1717
|
-
}
|
|
1718
|
-
else {
|
|
1719
|
-
const newAlarmSeries = this.echartsOptionsService.getAlarmOrEventSeries(dp, renderType, false, [alarmOrEvent], 'alarm', displayOptions, alarmOrEvent.id, null, true);
|
|
1720
|
-
allDataSeries.push(...newAlarmSeries);
|
|
1721
|
-
}
|
|
1754
|
+
// For alarms, pass null as id - we want one series per alarm type/device.
|
|
1755
|
+
// Series ID will be: alarmType/deviceId-markPoint (no unique suffix).
|
|
1756
|
+
// We already removed the old series above, so this replaces it.
|
|
1757
|
+
const newAlarmSeries = this.echartsOptionsService.getAlarmOrEventSeries(dp, renderType, false, [alarm], 'alarm', displayOptions, null, null, true);
|
|
1758
|
+
allDataSeries.push(...newAlarmSeries);
|
|
1722
1759
|
}
|
|
1723
1760
|
}
|
|
1724
|
-
|
|
1725
|
-
|
|
1761
|
+
}
|
|
1762
|
+
// Use replaceMerge for series to ensure removed alarm series don't persist.
|
|
1763
|
+
// Without this, ECharts merges the new series array with existing ones,
|
|
1764
|
+
// which can leave stale alarm/event series on the chart.
|
|
1726
1765
|
this.echartsInstance?.setOption({
|
|
1727
1766
|
dataZoom: [
|
|
1728
1767
|
{
|
|
@@ -1735,7 +1774,7 @@ class ChartRealtimeService {
|
|
|
1735
1774
|
max: this.currentTimeRange?.dateTo
|
|
1736
1775
|
},
|
|
1737
1776
|
series: allDataSeries
|
|
1738
|
-
});
|
|
1777
|
+
}, { replaceMerge: ['series'] });
|
|
1739
1778
|
}
|
|
1740
1779
|
/**
|
|
1741
1780
|
* Detects if a datapoint has measurements with future timestamps (out-of-sync).
|
|
@@ -2247,6 +2286,7 @@ class ChartsComponent {
|
|
|
2247
2286
|
}
|
|
2248
2287
|
/**
|
|
2249
2288
|
* Toggles the visibility of a series in the chart based on the provided datapoint.
|
|
2289
|
+
* Uses explicit legendSelect/legendUnSelect based on __active state.
|
|
2250
2290
|
* @param datapoint - The datapoint to toggle visibility for.
|
|
2251
2291
|
*/
|
|
2252
2292
|
toggleDatapointSeriesVisibility(datapoint) {
|
|
@@ -2254,26 +2294,40 @@ class ChartsComponent {
|
|
|
2254
2294
|
const seriesToUpdate = series.find(s => s.datapointId === `${datapoint.__target?.id}${datapoint.fragment}${datapoint.series}`);
|
|
2255
2295
|
if (seriesToUpdate) {
|
|
2256
2296
|
this.echartsInstance.dispatchAction({
|
|
2257
|
-
type: '
|
|
2297
|
+
type: datapoint.__active ? 'legendSelect' : 'legendUnSelect',
|
|
2258
2298
|
name: seriesToUpdate.name
|
|
2259
2299
|
});
|
|
2260
2300
|
}
|
|
2261
2301
|
}
|
|
2262
2302
|
/**
|
|
2263
|
-
* Toggles the visibility of
|
|
2303
|
+
* Toggles the visibility of alarm/event series in the chart.
|
|
2304
|
+
* Uses explicit legendSelect/legendUnSelect based on __hidden state.
|
|
2305
|
+
* Targets specific device's series using type + deviceId.
|
|
2264
2306
|
* @param alarmOrEvent - The alarm or event to toggle visibility for.
|
|
2265
2307
|
*/
|
|
2266
2308
|
toggleAlarmEventSeriesVisibility(alarmOrEvent) {
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
if (seriesToUpdate) {
|
|
2270
|
-
seriesToUpdate.forEach(s => {
|
|
2271
|
-
this.echartsInstance.dispatchAction({
|
|
2272
|
-
type: 'legendToggleSelect',
|
|
2273
|
-
name: s.name
|
|
2274
|
-
});
|
|
2275
|
-
});
|
|
2309
|
+
if (!this.echartsInstance) {
|
|
2310
|
+
return;
|
|
2276
2311
|
}
|
|
2312
|
+
const options = this.echartsInstance.getOption();
|
|
2313
|
+
const allSeries = options.series;
|
|
2314
|
+
if (!allSeries || allSeries.length === 0) {
|
|
2315
|
+
return;
|
|
2316
|
+
}
|
|
2317
|
+
const type = alarmOrEvent.filters.type;
|
|
2318
|
+
const deviceId = alarmOrEvent.__target?.id;
|
|
2319
|
+
const actionType = alarmOrEvent.__hidden ? 'legendUnSelect' : 'legendSelect';
|
|
2320
|
+
// Series names are: ${type}/${deviceId}-markPoint and ${type}/${deviceId}-markLine
|
|
2321
|
+
const markPointName = `${type}/${deviceId}-markPoint`;
|
|
2322
|
+
const markLineName = `${type}/${deviceId}-markLine`;
|
|
2323
|
+
// Find series matching this specific alarm type + device
|
|
2324
|
+
const matchingSeries = allSeries.filter(s => s.name === markPointName || s.name === markLineName);
|
|
2325
|
+
matchingSeries.forEach(series => {
|
|
2326
|
+
this.echartsInstance.dispatchAction({
|
|
2327
|
+
type: actionType,
|
|
2328
|
+
name: series.name
|
|
2329
|
+
});
|
|
2330
|
+
});
|
|
2277
2331
|
}
|
|
2278
2332
|
getDefaultChartOptions() {
|
|
2279
2333
|
return {
|