@c8y/ngx-components 1023.82.4 → 1023.83.2
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/context-dashboard/index.d.ts +7 -0
- package/context-dashboard/index.d.ts.map +1 -1
- package/echart/index.d.ts +19 -0
- package/echart/index.d.ts.map +1 -1
- package/events/index.d.ts.map +1 -1
- package/fesm2022/c8y-ngx-components-context-dashboard.mjs +9 -6
- package/fesm2022/c8y-ngx-components-context-dashboard.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-echart.mjs +119 -11
- package/fesm2022/c8y-ngx-components-echart.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-events.mjs +1 -1
- package/fesm2022/c8y-ngx-components-events.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-implementations-asset-table.mjs +82 -31
- package/fesm2022/c8y-ngx-components-widgets-implementations-asset-table.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components.mjs +1 -5
- package/fesm2022/c8y-ngx-components.mjs.map +1 -1
- package/index.d.ts +0 -1
- package/index.d.ts.map +1 -1
- package/locales/locales.pot +14 -6
- package/package.json +1 -1
- package/widgets/implementations/asset-table/index.d.ts +5 -1
- package/widgets/implementations/asset-table/index.d.ts.map +1 -1
|
@@ -456,6 +456,7 @@ class EchartsOptionsService {
|
|
|
456
456
|
this.severityLabelPipe = severityLabelPipe;
|
|
457
457
|
this.translate = translate;
|
|
458
458
|
this.router = router;
|
|
459
|
+
this.highlightedSeriesName = null;
|
|
459
460
|
this.AGGREGATED_SERIES_TYPE = 'aggr';
|
|
460
461
|
this.TOOLTIP_WIDTH = 300;
|
|
461
462
|
}
|
|
@@ -1464,7 +1465,7 @@ class EchartsOptionsService {
|
|
|
1464
1465
|
data,
|
|
1465
1466
|
...(displayOptions.forceMergeDatapoints ? {} : { yAxisIndex: idx }),
|
|
1466
1467
|
...this.chartTypesService.getSeriesOptions(dp, isMinMaxChart, renderType),
|
|
1467
|
-
...(isLine && { smooth: displayOptions.smoothLines ?? false })
|
|
1468
|
+
...(isLine && { smooth: displayOptions.smoothLines ?? false, triggerLineEvent: true })
|
|
1468
1469
|
};
|
|
1469
1470
|
}
|
|
1470
1471
|
/**
|
|
@@ -1527,10 +1528,12 @@ class EchartsOptionsService {
|
|
|
1527
1528
|
`</div></div>`;
|
|
1528
1529
|
}
|
|
1529
1530
|
const itemStyle = series['itemStyle'];
|
|
1530
|
-
|
|
1531
|
+
const isDimmed = this.highlightedSeriesName !== null && series['name'] !== this.highlightedSeriesName;
|
|
1532
|
+
YAxisReadings.push(`<div style="opacity: ${isDimmed ? 0.4 : 1}">` +
|
|
1533
|
+
`<div class="d-flex a-i-center p-b-8 text-default"><span class='dlt-c8y-icon-circle m-r-4' style='color: ${echarts.format.encodeHTML(itemStyle.color)}'></span>` + // color circle
|
|
1531
1534
|
`<strong class="text-truncate">${echarts.format.encodeHTML(series['datapointLabel'])}</strong></div>` + // name
|
|
1532
|
-
`${value}` // single value or min-max range
|
|
1533
|
-
|
|
1535
|
+
`${value}` + // single value or min-max range
|
|
1536
|
+
`</div>`);
|
|
1534
1537
|
});
|
|
1535
1538
|
return `<div inner-e-cbg-component style="width: ${this.TOOLTIP_WIDTH}px">${YAxisReadings.join('')}</div>`;
|
|
1536
1539
|
};
|
|
@@ -1747,6 +1750,14 @@ class ChartRealtimeService {
|
|
|
1747
1750
|
if (!seriesMatchingDatapoint) {
|
|
1748
1751
|
return;
|
|
1749
1752
|
}
|
|
1753
|
+
// If the datapoint already has a unit (e.g. from config), keep it. Otherwise, try to get it from the realtime measurement.
|
|
1754
|
+
if (!seriesMatchingDatapoint['datapointUnit'] && measurements.length > 0) {
|
|
1755
|
+
const unit = measurements[0]?.[datapoint.fragment]?.[datapoint.series].unit;
|
|
1756
|
+
if (unit) {
|
|
1757
|
+
const renderType = datapoint.renderType || 'min';
|
|
1758
|
+
seriesMatchingDatapoint['datapointUnit'] = renderType !== 'count' ? unit : '';
|
|
1759
|
+
}
|
|
1760
|
+
}
|
|
1750
1761
|
const seriesDataToUpdate = seriesMatchingDatapoint['data'];
|
|
1751
1762
|
let lastExistingTimestamp = seriesDataToUpdate.length
|
|
1752
1763
|
? new Date(seriesDataToUpdate[seriesDataToUpdate.length - 1][0]).valueOf()
|
|
@@ -2143,6 +2154,8 @@ class ChartsComponent {
|
|
|
2143
2154
|
this.isChangeFromZoom = false;
|
|
2144
2155
|
/** Tracks if the slider is being dragged — suppresses config updates mid-drag */
|
|
2145
2156
|
this.isSliderDragging = false;
|
|
2157
|
+
/** Tracks the currently highlighted series name, null when nothing is highlighted */
|
|
2158
|
+
this.highlightedSeriesName = null;
|
|
2146
2159
|
this.chartOption$ = this.configChangedSubject.pipe(tap(() => (this.isFetching = true)), switchMap(() => this.loadAlarmsAndEvents()), switchMap(() => this.fetchSeriesForDatapoints$()), switchMap((datapointsWithValues) => {
|
|
2147
2160
|
if (datapointsWithValues.length === 0 && this.config.alarmsEventsConfigs?.length === 0) {
|
|
2148
2161
|
this.echartsInstance?.clear();
|
|
@@ -2152,22 +2165,28 @@ class ChartsComponent {
|
|
|
2152
2165
|
// Use padded range since data is fetched with 60s padding
|
|
2153
2166
|
this.loadedTimeRange = { ...this.getTimeRange(60_000) };
|
|
2154
2167
|
return this.getChartOptions(datapointsWithValues);
|
|
2155
|
-
}), tap(
|
|
2168
|
+
}), tap(options => {
|
|
2156
2169
|
this.isFetching = false;
|
|
2157
2170
|
this.finishLoading.emit(false);
|
|
2158
|
-
if (
|
|
2171
|
+
if (options['empty']) {
|
|
2159
2172
|
return;
|
|
2160
2173
|
}
|
|
2161
2174
|
this.chartRealtimeService.stopRealtime();
|
|
2162
2175
|
this.startRealtimeIfPossible();
|
|
2163
2176
|
if (this.echartsInstance) {
|
|
2177
|
+
// If a series is highlighted, set the opacity into the chart options before
|
|
2178
|
+
// rendering so the lazy setOption already carries the correct visual state.
|
|
2179
|
+
// This avoids any async race — the render itself is the source of truth.
|
|
2180
|
+
if (this.highlightedSeriesName) {
|
|
2181
|
+
this.applyHighlightToChartOptions(options, this.highlightedSeriesName);
|
|
2182
|
+
}
|
|
2164
2183
|
/**
|
|
2165
2184
|
* * Set the chart options
|
|
2166
2185
|
* First parameter is the options to set
|
|
2167
2186
|
* Second parameter is a boolean to indicate that the chart should be re-rendered as we do not want to merge.
|
|
2168
2187
|
* Third parameter is a boolean to indicate that we want to lazy load the chart.
|
|
2169
2188
|
*/
|
|
2170
|
-
this.echartsInstance.setOption(
|
|
2189
|
+
this.echartsInstance.setOption(options, true, true);
|
|
2171
2190
|
}
|
|
2172
2191
|
}));
|
|
2173
2192
|
this.widgetTimeContextDateRangeService.fullReload$
|
|
@@ -2307,6 +2326,12 @@ class ChartsComponent {
|
|
|
2307
2326
|
tooltip: { triggerOn: 'mousemove' },
|
|
2308
2327
|
series: [{ markArea: { data: [] }, markLine: { data: [] } }]
|
|
2309
2328
|
});
|
|
2329
|
+
if (params.componentType === 'series' && params.seriesName) {
|
|
2330
|
+
this.toggleStickyHighlight(params.seriesName);
|
|
2331
|
+
}
|
|
2332
|
+
else {
|
|
2333
|
+
this.setStickyHighlight(null);
|
|
2334
|
+
}
|
|
2310
2335
|
return;
|
|
2311
2336
|
}
|
|
2312
2337
|
const clickedAlarms = this.alarms.filter(alarm => alarm.type === params.data.itemType);
|
|
@@ -2344,8 +2369,8 @@ class ChartsComponent {
|
|
|
2344
2369
|
this.echartsInstance.setOption(updatedOptions);
|
|
2345
2370
|
}
|
|
2346
2371
|
isAlarmOrEventClick(params) {
|
|
2347
|
-
return (this.alarms.some(alarm => alarm.type === params.data
|
|
2348
|
-
this.events.some(event => event.type === params.data
|
|
2372
|
+
return (this.alarms.some(alarm => alarm.type === params.data?.itemType) ||
|
|
2373
|
+
this.events.some(event => event.type === params.data?.itemType));
|
|
2349
2374
|
}
|
|
2350
2375
|
hasMarkArea(options) {
|
|
2351
2376
|
return options?.series?.[0]?.markArea?.data?.length > 0;
|
|
@@ -2453,15 +2478,91 @@ class ChartsComponent {
|
|
|
2453
2478
|
}
|
|
2454
2479
|
const type = alarmOrEvent.filters.type;
|
|
2455
2480
|
const actionType = alarmOrEvent.__hidden ? 'legendUnSelect' : 'legendSelect';
|
|
2456
|
-
const matchingSeries = allSeries.filter(s => s.name
|
|
2457
|
-
|
|
2481
|
+
const matchingSeries = allSeries.filter(s => typeof s.name === 'string' &&
|
|
2482
|
+
s.name.startsWith(`${type}/`) &&
|
|
2483
|
+
(s.name.endsWith('-markLine') || s.name.endsWith('-markPoint')));
|
|
2458
2484
|
matchingSeries.forEach(series => {
|
|
2485
|
+
if (typeof series.name !== 'string') {
|
|
2486
|
+
return;
|
|
2487
|
+
}
|
|
2459
2488
|
this.echartsInstance.dispatchAction({
|
|
2460
2489
|
type: actionType,
|
|
2461
2490
|
name: series.name
|
|
2462
2491
|
});
|
|
2463
2492
|
});
|
|
2464
2493
|
}
|
|
2494
|
+
getDataSeriesNames() {
|
|
2495
|
+
const series = this.echartsInstance.getOption().series;
|
|
2496
|
+
const allSeries = Array.isArray(series) ? series : [series];
|
|
2497
|
+
return allSeries
|
|
2498
|
+
.filter(s => s.name &&
|
|
2499
|
+
s['typeOfSeries'] !== 'alarm' &&
|
|
2500
|
+
s['typeOfSeries'] !== 'event' &&
|
|
2501
|
+
s['typeOfSeries'] !== 'fake' &&
|
|
2502
|
+
s['datapointId'] !== 'aggregated')
|
|
2503
|
+
.map(s => s.name);
|
|
2504
|
+
}
|
|
2505
|
+
/**
|
|
2506
|
+
* Applies highlight opacity directly to an EChartsOption object's series array.
|
|
2507
|
+
* Used to set the highlight into chart options before setOption.
|
|
2508
|
+
* @param options - The chart options object to mutate in-place.
|
|
2509
|
+
* @param highlightedName - The series name that should remain at full opacity.
|
|
2510
|
+
*/
|
|
2511
|
+
applyHighlightToChartOptions(options, highlightedName) {
|
|
2512
|
+
if (!Array.isArray(options.series)) {
|
|
2513
|
+
return;
|
|
2514
|
+
}
|
|
2515
|
+
const series = options.series;
|
|
2516
|
+
const dataSeriesNames = this.getDataSeriesNames();
|
|
2517
|
+
series.forEach(s => {
|
|
2518
|
+
const updatedSeries = this.changeSeriesOpacity(dataSeriesNames, highlightedName, s);
|
|
2519
|
+
Object.assign(s, updatedSeries);
|
|
2520
|
+
});
|
|
2521
|
+
}
|
|
2522
|
+
/**
|
|
2523
|
+
* Applies or removes a sticky highlight by directly setting opacity on series styles.
|
|
2524
|
+
* @param seriesName - The series to pin as highlighted, or null to restore all.
|
|
2525
|
+
*/
|
|
2526
|
+
setStickyHighlight(seriesName) {
|
|
2527
|
+
this.highlightedSeriesName = seriesName;
|
|
2528
|
+
this.echartsOptionsService.highlightedSeriesName = seriesName;
|
|
2529
|
+
const allSeries = this.echartsInstance.getOption().series;
|
|
2530
|
+
const dataSeriesNames = this.getDataSeriesNames();
|
|
2531
|
+
this.echartsInstance.setOption({
|
|
2532
|
+
series: allSeries.map(s => {
|
|
2533
|
+
return this.changeSeriesOpacity(dataSeriesNames, seriesName, s);
|
|
2534
|
+
})
|
|
2535
|
+
});
|
|
2536
|
+
}
|
|
2537
|
+
changeSeriesOpacity(dataSeriesName, seriesName, series) {
|
|
2538
|
+
const dataSeriesNames = new Set(dataSeriesName);
|
|
2539
|
+
if (typeof series.name !== 'string' || !dataSeriesNames.has(series.name)) {
|
|
2540
|
+
return series;
|
|
2541
|
+
}
|
|
2542
|
+
const isDimmed = seriesName !== null && series.name !== seriesName;
|
|
2543
|
+
const opacity = isDimmed ? 0.2 : 1;
|
|
2544
|
+
return {
|
|
2545
|
+
...series,
|
|
2546
|
+
lineStyle: { ...(series.lineStyle ?? {}), opacity },
|
|
2547
|
+
itemStyle: { ...(series.itemStyle ?? {}), opacity },
|
|
2548
|
+
emphasis: {
|
|
2549
|
+
...(series.emphasis ?? {}),
|
|
2550
|
+
// Disable ECharts' automatic focus-blur so hovering other series
|
|
2551
|
+
// does not override the pinned opacity we set here.
|
|
2552
|
+
focus: 'none',
|
|
2553
|
+
lineStyle: { ...(series.emphasis?.lineStyle ?? {}), opacity },
|
|
2554
|
+
itemStyle: { ...(series.emphasis?.itemStyle ?? {}), opacity }
|
|
2555
|
+
}
|
|
2556
|
+
};
|
|
2557
|
+
}
|
|
2558
|
+
toggleStickyHighlight(seriesName) {
|
|
2559
|
+
if (this.highlightedSeriesName === seriesName) {
|
|
2560
|
+
// Same series clicked again — remove the lock
|
|
2561
|
+
this.setStickyHighlight(null);
|
|
2562
|
+
return;
|
|
2563
|
+
}
|
|
2564
|
+
this.setStickyHighlight(seriesName);
|
|
2565
|
+
}
|
|
2465
2566
|
get displayOptions() {
|
|
2466
2567
|
const chartDefaults = CHART_DISPLAY_OPTION_DEFAULTS;
|
|
2467
2568
|
return {
|
|
@@ -2743,6 +2844,13 @@ class ChartsComponent {
|
|
|
2743
2844
|
this.alerts.clear();
|
|
2744
2845
|
}
|
|
2745
2846
|
}
|
|
2847
|
+
// If the datapoint already has a unit (e.g. from config), keep it. Otherwise, try to get it from the series response.
|
|
2848
|
+
if (!dp.unit) {
|
|
2849
|
+
const unitFromSeries = res.data.series[0]?.unit;
|
|
2850
|
+
if (unitFromSeries) {
|
|
2851
|
+
dp.unit = unitFromSeries;
|
|
2852
|
+
}
|
|
2853
|
+
}
|
|
2746
2854
|
return { ...dp, values, truncated: res.data.truncated };
|
|
2747
2855
|
}));
|
|
2748
2856
|
datapointsWithValuesRequests.push(request);
|