diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.html
index 8d660a7884..c58dfdc90d 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.html
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.html
@@ -22,13 +22,13 @@
-
+
-
-
{{ legendItem.label }}
+
+
{{ legendKey.label }}
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.ts
index e2779f2821..5aaa2671ea 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.ts
@@ -28,45 +28,18 @@ import {
ViewEncapsulation
} from '@angular/core';
import { WidgetContext } from '@home/models/widget-component.models';
-import {
- backgroundStyle,
- ComponentStyle,
- DateFormatProcessor,
- overlayStyle,
- textStyle
-} from '@shared/models/widget-settings.models';
-import { ResizeObserver } from '@juggle/resize-observer';
-import { formatValue } from '@core/utils';
+import { backgroundStyle, ComponentStyle, overlayStyle, textStyle } from '@shared/models/widget-settings.models';
import { Observable } from 'rxjs';
import { ImagePipe } from '@shared/pipe/image.pipe';
import { DomSanitizer } from '@angular/platform-browser';
import {
barChartWithLabelsDefaultSettings,
+ barChartWithLabelsTimeSeriesKeySettings,
+ barChartWithLabelsTimeSeriesSettings,
BarChartWithLabelsWidgetSettings
} from '@home/components/widget/lib/chart/bar-chart-with-labels-widget.models';
-
-import * as echarts from 'echarts/core';
-import { CustomSeriesOption } from 'echarts/charts';
-import { CallbackDataParams, CustomSeriesRenderItem, LabelLayoutOptionCallback } from 'echarts/types/dist/shared';
-
-import {
- ECharts,
- echartsModule,
- EChartsOption,
- EChartsSeriesItem,
- echartsTooltipFormatter, timeAxisBandWidthCalculator,
- toNamedData
-} from '@home/components/widget/lib/chart/echarts-widget.models';
-import { AggregationType, IntervalMath } from '@shared/models/time/time.models';
-
-type BarChartDataItem = EChartsSeriesItem;
-
-interface BarChartLegendItem {
- id: string;
- color: string;
- label: string;
- enabled: boolean;
-}
+import { TbTimeSeriesChart } from '@home/components/widget/lib/chart/time-series-chart';
+import { DataKey } from '@shared/models/widget.models';
@Component({
selector: 'tb-bar-chart-with-labels-widget',
@@ -93,29 +66,11 @@ export class BarChartWithLabelsWidgetComponent implements OnInit, OnDestroy, Aft
backgroundStyle$: Observable
;
overlayStyle: ComponentStyle = {};
- legendItems: BarChartLegendItem[];
+ legendKeys: DataKey[];
legendLabelStyle: ComponentStyle;
disabledLegendLabelStyle: ComponentStyle;
- private get noAggregation(): boolean {
- return this.ctx.defaultSubscription.timeWindowConfig?.aggregation?.type === AggregationType.NONE;
- }
-
- private shapeResize$: ResizeObserver;
-
- private decimals = 0;
- private units = '';
-
- private dataItems: BarChartDataItem[] = [];
-
- private drawChartPending = false;
- private barChart: ECharts;
- private barChartOptions: EChartsOption;
-
- private tooltipDateFormat: DateFormatProcessor;
-
- private barRenderItem: CustomSeriesRenderItem;
- private barLabelLayoutCallback: LabelLayoutOptionCallback;
+ private timeSeriesChart: TbTimeSeriesChart;
constructor(private imagePipe: ImagePipe,
private sanitizer: DomSanitizer,
@@ -127,356 +82,62 @@ export class BarChartWithLabelsWidgetComponent implements OnInit, OnDestroy, Aft
this.ctx.$scope.barChartWidget = this;
this.settings = {...barChartWithLabelsDefaultSettings, ...this.ctx.settings};
- this.decimals = this.ctx.decimals;
- this.units = this.ctx.units;
-
this.backgroundStyle$ = backgroundStyle(this.settings.background, this.imagePipe, this.sanitizer);
this.overlayStyle = overlayStyle(this.settings.background.overlay);
this.showLegend = this.settings.showLegend;
if (this.showLegend) {
- this.legendItems = [];
+ this.legendKeys = [];
this.legendClass = `legend-${this.settings.legendPosition}`;
this.legendLabelStyle = textStyle(this.settings.legendLabelFont);
this.disabledLegendLabelStyle = textStyle(this.settings.legendLabelFont);
this.legendLabelStyle.color = this.settings.legendLabelColor;
}
- let counter = 0;
- if (this.ctx.datasources.length) {
- for (const datasource of this.ctx.datasources) {
- const dataKeys = datasource.dataKeys;
- for (const dataKey of dataKeys) {
- const id = counter++;
- const datasourceData = this.ctx.data ? this.ctx.data.find(d => d.dataKey === dataKey) : null;
- const namedData = datasourceData?.data ? toNamedData(datasourceData.data) : [];
- this.dataItems.push({
- id: id+'',
- dataKey,
- data: namedData,
- enabled: true
- });
- if (this.showLegend) {
- this.legendItems.push(
- {
- id: id+'',
- label: dataKey.label,
- color: dataKey.color,
- enabled: true
- }
- );
- }
+ const barSettings = barChartWithLabelsTimeSeriesKeySettings(this.settings, this.ctx.decimals);
+ for (const datasource of this.ctx.datasources) {
+ const dataKeys = datasource.dataKeys;
+ for (const dataKey of dataKeys) {
+ dataKey.settings = barSettings;
+ if (this.showLegend) {
+ this.legendKeys.push(dataKey);
}
}
}
-
- if (this.settings.showTooltip && this.settings.tooltipShowDate) {
- this.tooltipDateFormat = DateFormatProcessor.fromSettings(this.ctx.$injector, this.settings.tooltipDateFormat);
- }
-
- const barValueStyle: ComponentStyle = textStyle(this.settings.barValueFont);
- delete barValueStyle.lineHeight;
- barValueStyle.fontSize = this.settings.barValueFont.size;
- barValueStyle.fill = this.settings.barValueColor;
-
- const barLabelStyle: ComponentStyle = textStyle(this.settings.barLabelFont);
- delete barLabelStyle.lineHeight;
- barLabelStyle.fontSize = this.settings.barLabelFont.size;
- barLabelStyle.fill = this.settings.barLabelColor;
-
- this.barRenderItem = (params, api) => {
-
- const time = api.value(0) as number;
- let start = api.value(2) as number;
- const end = api.value(3) as number;
- let interval = end - start;
- if (!start || !end || !interval) {
- interval = IntervalMath.numberValue(this.ctx.timeWindow.interval);
- start = time - interval / 2;
- }
- const enabledDataItems = this.dataItems.filter(d => d.enabled);
- const barInterval = interval / (enabledDataItems.length + 1);
- const intervalGap = barInterval / 2;
-
- const index = enabledDataItems.findIndex(d => d.id === params.seriesId);
- const value = api.value(1);
- const startTime = start + intervalGap + barInterval * index;
- const delta = barInterval;
- const lowerLeft = api.coord([startTime, value >= 0 ? value : 0]);
- const height = api.size([delta, value])[1];
- const width = api.size([delta, 10])[0];
-
- const coordSys: {x: number; y: number; width: number; height: number} = params.coordSys as any;
-
- const rectShape = echarts.graphic.clipRectByRect({
- x: lowerLeft[0],
- y: lowerLeft[1],
- width,
- height
- }, {
- x: coordSys.x,
- y: coordSys.y,
- width: coordSys.width,
- height: coordSys.height
- });
-
- const zeroPos = api.coord([0, 0]);
- const labelParts: string[] = [];
- if (this.settings.showBarValue) {
- const labelValue = formatValue(value, this.decimals, '', false);
- labelParts.push(`{value|${labelValue}}`);
- }
- if (this.settings.showBarLabel) {
- labelParts.push(`{label|${params.seriesName}}`);
- }
- const barLabel = labelParts.join(' ');
- return rectShape && {
- type: 'rect',
- id: time + '',
- shape: rectShape,
- style: {
- fill: api.visual('color'),
- text: barLabel,
- textPosition: 'insideBottom',
- textRotation: Math.PI / 2,
- textDistance: 15,
- textStrokeWidth: 0,
- textAlign: 'left',
- textVerticalAlign: 'middle',
- rich: {
- value: barValueStyle,
- label: barLabelStyle
- }
- },
- focus: 'series',
- transition: 'all',
- enterFrom: {
- style: { opacity: 0 },
- shape: { height: 0, y: zeroPos[1] }
- }
- };
- };
-
- this.barLabelLayoutCallback = (params) => {
- if (params.rect.width - params.labelRect.width < 2) {
- return {
- y: '100000%',
- };
- } else {
- return {
- hideOverlap: true
- };
- }
- };
}
ngAfterViewInit() {
- if (this.drawChartPending) {
- this.drawChart();
- }
+ const settings = barChartWithLabelsTimeSeriesSettings(this.settings);
+ this.timeSeriesChart = new TbTimeSeriesChart(this.ctx, settings, this.chartShape.nativeElement, this.renderer);
}
ngOnDestroy() {
- if (this.shapeResize$) {
- this.shapeResize$.disconnect();
- }
- if (this.barChart) {
- this.barChart.dispose();
+ if (this.timeSeriesChart) {
+ this.timeSeriesChart.destroy();
}
}
public onInit() {
const borderRadius = this.ctx.$widgetElement.css('borderRadius');
this.overlayStyle = {...this.overlayStyle, ...{borderRadius}};
- if (this.chartShape) {
- this.drawChart();
- } else {
- this.drawChartPending = true;
- }
this.cd.detectChanges();
}
public onDataUpdated() {
- for (const item of this.dataItems) {
- const datasourceData = this.ctx.data ? this.ctx.data.find(d => d.dataKey === item.dataKey) : null;
- item.data = datasourceData?.data ? toNamedData(datasourceData.data) : [];
- }
- if (this.barChart) {
- (this.barChartOptions.xAxis as any).min = this.ctx.defaultSubscription.timeWindow.minTime;
- (this.barChartOptions.xAxis as any).max = this.ctx.defaultSubscription.timeWindow.maxTime;
- (this.barChartOptions.xAxis as any).tbTimeWindow = this.ctx.defaultSubscription.timeWindow;
- this.barChartOptions.series = this.updateSeries();
- this.barChart.setOption(this.barChartOptions);
+ if (this.timeSeriesChart) {
+ this.timeSeriesChart.update();
}
}
- private updateSeries(): Array {
- const series: Array = [];
- for (const item of this.dataItems) {
- if (item.enabled) {
- const seriesOption: CustomSeriesOption = {
- type: 'custom',
- id: item.id,
- name: item.dataKey.label,
- color: item.dataKey.color,
- data: item.data,
- renderItem: this.barRenderItem,
- labelLayout: this.barLabelLayoutCallback,
- dimensions: [
- {name: 'intervalStart', type: 'number'},
- {name: 'intervalEnd', type: 'number'}
- ],
- encode: {
- intervalStart: 2,
- intervalEnd: 3
- }
- };
- series.push(seriesOption);
- }
- }
- return series;
+ public onLegendKeyEnter(key: DataKey) {
+ this.timeSeriesChart.keyEnter(key);
}
-
- public onLegendItemEnter(item: BarChartLegendItem) {
- this.barChart.dispatchAction({
- type: 'highlight',
- seriesId: item.id
- });
- }
-
- public onLegendItemLeave(item: BarChartLegendItem) {
- this.barChart.dispatchAction({
- type: 'downplay',
- seriesId: item.id
- });
- }
-
- public toggleLegendItem(item: BarChartLegendItem) {
- const enable = !item.enabled;
- const dataItem = this.dataItems.find(d => d.id === item.id);
- if (dataItem) {
- dataItem.enabled = enable;
- if (!enable) {
- this.barChart.dispatchAction({
- type: 'downplay',
- seriesId: item.id
- });
- }
- this.barChartOptions.series = this.updateSeries();
- this.barChart.setOption(this.barChartOptions, {replaceMerge: ['series']});
- item.enabled = enable;
- if (enable) {
- this.barChart.dispatchAction({
- type: 'highlight',
- seriesId: item.id
- });
- }
- }
+ public onLegendKeyLeave(key: DataKey) {
+ this.timeSeriesChart.keyLeave(key);
}
- private drawChart() {
- echartsModule.init();
- this.barChart = echarts.init(this.chartShape.nativeElement, null, {
- renderer: 'canvas',
- });
- this.barChartOptions = {
- tooltip: {
- trigger: 'axis',
- confine: true,
- appendTo: 'body',
- axisPointer: {
- type: 'shadow'
- },
- formatter: (params: CallbackDataParams[]) => {
- if (this.settings.showTooltip) {
- const focusedSeriesIndex = this.focusedSeriesIndex();
- return echartsTooltipFormatter(this.renderer, this.tooltipDateFormat,
- this.settings, params, this.decimals, this.units, focusedSeriesIndex, null,
- this.noAggregation ? null : this.ctx.timeWindow.interval);
- } else {
- return undefined;
- }
- },
- padding: [8, 12],
- backgroundColor: this.settings.tooltipBackgroundColor,
- borderWidth: 0,
- extraCssText: `line-height: 1; backdrop-filter: blur(${this.settings.tooltipBackgroundBlur}px);`
- },
- grid: {
- containLabel: true,
- top: '30',
- left: 0,
- right: 0,
- bottom: 0
- },
- xAxis: {
- type: 'time',
- scale: true,
- axisTick: {
- show: false
- },
- axisLabel: {
- hideOverlap: true,
- fontSize: 10
- },
- axisLine: {
- onZero: false
- },
- min: this.ctx.defaultSubscription.timeWindow.minTime,
- max: this.ctx.defaultSubscription.timeWindow.maxTime,
- bandWidthCalculator: timeAxisBandWidthCalculator
- },
- yAxis: {
- type: 'value',
- axisLabel: {
- formatter: (value: any) => formatValue(value, this.decimals, this.units, false)
- }
- }
- };
-
- (this.barChartOptions.xAxis as any).tbTimeWindow = this.ctx.defaultSubscription.timeWindow;
-
- this.barChartOptions.series = this.updateSeries();
-
- this.barChart.setOption(this.barChartOptions);
-
- this.shapeResize$ = new ResizeObserver(() => {
- this.onResize();
- });
- this.shapeResize$.observe(this.chartShape.nativeElement);
- this.onResize();
- }
-
- private focusedSeriesIndex(): number {
- let index = - 1;
- const views: any[] = (this.barChart as any)._chartsViews;
- if (views) {
- const hasBlurredView = !!views.find(view => {
- const graphicEls: any[] = view._data._graphicEls;
- return !!graphicEls.find(el => el?.currentStates.includes('blur'));
- });
- if (hasBlurredView) {
- const focusedView = views.find(view => {
- const graphicEls: any[] = view._data._graphicEls;
- return !!graphicEls.find(el => !el?.currentStates.includes('blur'));
- });
- if (focusedView) {
- index = !!focusedView._model ?
- focusedView._model.seriesIndex : (!!focusedView.__model ? focusedView.__model.seriesIndex : -1);
- }
- }
- }
- return index;
- }
-
- private onResize() {
- const width = this.barChart.getWidth();
- const height = this.barChart.getHeight();
- const shapeWidth = this.chartShape.nativeElement.offsetWidth;
- const shapeHeight = this.chartShape.nativeElement.offsetHeight;
- if (width !== shapeWidth || height !== shapeHeight) {
- this.barChart.resize();
- }
+ public toggleLegendKey(key: DataKey) {
+ this.timeSeriesChart.toggleKey(key);
}
}
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.models.ts
index 99ea088c92..153a038d1e 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.models.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.models.ts
@@ -14,9 +14,23 @@
/// limitations under the License.
///
-import { BackgroundSettings, BackgroundType, customDateFormat, Font } from '@shared/models/widget-settings.models';
+import {
+ BackgroundSettings,
+ BackgroundType,
+ ComponentStyle,
+ customDateFormat,
+ Font, textStyle
+} from '@shared/models/widget-settings.models';
import { LegendPosition } from '@shared/models/widget.models';
import { EChartsTooltipWidgetSettings } from '@home/components/widget/lib/chart/echarts-widget.models';
+import { DeepPartial } from '@shared/models/common';
+import {
+ TimeSeriesChartKeySettings, TimeSeriesChartSeriesType,
+ TimeSeriesChartSettings
+} from '@home/components/widget/lib/chart/time-series-chart.models';
+import { CallbackDataParams, LabelLayoutOptionCallbackParams } from 'echarts/types/dist/shared';
+import { formatValue } from '@core/utils';
+import { LabelLayoutOption } from 'echarts/types/src/util/types';
export interface BarChartWithLabelsWidgetSettings extends EChartsTooltipWidgetSettings {
showBarLabel: boolean;
@@ -98,3 +112,94 @@ export const barChartWithLabelsDefaultSettings: BarChartWithLabelsWidgetSettings
}
}
};
+
+export const barChartWithLabelsTimeSeriesSettings = (settings: BarChartWithLabelsWidgetSettings): DeepPartial => ({
+ dataZoom: false,
+ yAxes: {
+ default: {
+ show: true,
+ showLine: false,
+ showTicks: false,
+ showTickLabels: true,
+ showSplitLines: true,
+ }
+ },
+ xAxis: {
+ show: true,
+ showLine: true,
+ showTicks: false,
+ showTickLabels: true,
+ showSplitLines: false
+ },
+ barWidthSettings: {
+ barGap: 0,
+ intervalGap: 0.5
+ },
+ showTooltip: settings.showTooltip,
+ tooltipValueFont: settings.tooltipValueFont,
+ tooltipValueColor: settings.tooltipValueColor,
+ tooltipShowDate: settings.tooltipShowDate,
+ tooltipDateInterval: settings.tooltipDateInterval,
+ tooltipDateFormat: settings.tooltipDateFormat,
+ tooltipDateFont: settings.tooltipDateFont,
+ tooltipDateColor: settings.tooltipDateColor,
+ tooltipBackgroundColor: settings.tooltipBackgroundColor,
+ tooltipBackgroundBlur: settings.tooltipBackgroundBlur,
+ tooltipShowFocusedSeries: true
+});
+
+export const barChartWithLabelsTimeSeriesKeySettings = (settings: BarChartWithLabelsWidgetSettings,
+ decimals: number): DeepPartial => {
+ const barValueStyle: ComponentStyle = textStyle(settings.barValueFont);
+ delete barValueStyle.lineHeight;
+ barValueStyle.fontSize = settings.barValueFont.size;
+ barValueStyle.fill = settings.barValueColor;
+
+ const barLabelStyle: ComponentStyle = textStyle(settings.barLabelFont);
+ delete barLabelStyle.lineHeight;
+ barLabelStyle.fontSize = settings.barLabelFont.size;
+ barLabelStyle.fill = settings.barLabelColor;
+ return {
+ type: TimeSeriesChartSeriesType.bar,
+ barSettings: {
+ showBorder: false,
+ borderWidth: 0,
+ borderRadius: 0,
+ showLabel: settings.showBarLabel,
+ labelPosition: 'insideBottom',
+ labelFormatter: (params: CallbackDataParams): string => {
+ const labelParts: string[] = [];
+ if (settings.showBarValue) {
+ const labelValue = formatValue(params.value[1], decimals, '', false);
+ labelParts.push(`{value|${labelValue}}`);
+ }
+ if (settings.showBarLabel) {
+ labelParts.push(`{label|${params.seriesName}}`);
+ }
+ return labelParts.join(' ');
+ },
+ labelLayout: (params: LabelLayoutOptionCallbackParams): LabelLayoutOption => {
+ if (params.rect.width - params.labelRect.width < 2) {
+ return {
+ y: '100000%',
+ };
+ } else {
+ return {
+ hideOverlap: true
+ };
+ }
+ },
+ additionalLabelOption: {
+ textRotation: Math.PI / 2,
+ textDistance: 15,
+ textStrokeWidth: 0,
+ textAlign: 'left',
+ textVerticalAlign: 'middle',
+ rich: {
+ value: barValueStyle,
+ label: barLabelStyle
+ }
+ }
+ }
+ };
+};
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/echarts-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/echarts-widget.models.ts
index 816f45a7e8..c9c4b319cc 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/echarts-widget.models.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/echarts-widget.models.ts
@@ -266,6 +266,48 @@ export const getAxisExtent = (chart: ECharts, axisId: string): [number, number]
return [0,0];
};
+let componentBlurredKey: string;
+
+const isBlurred = (model: SeriesModel): boolean => {
+ if (!componentBlurredKey) {
+ const innerKeys = Object.keys(model).filter(k => k.startsWith('__ec_inner_'));
+ for (const k of innerKeys) {
+ const obj = model[k];
+ if (obj.hasOwnProperty('isBlured')) {
+ componentBlurredKey = k;
+ break;
+ }
+ }
+ }
+ if (componentBlurredKey) {
+ const obj = model[componentBlurredKey];
+ return !!obj?.isBlured;
+ } else {
+ return false;
+ }
+};
+
+export const getFocusedSeriesIndex = (chart: ECharts): number => {
+ const model: GlobalModel = (chart as any).getModel();
+ const models = model.queryComponents({mainType: 'series'});
+ if (models) {
+ let hasBlurred = false;
+ let notBlurredIndex = -1;
+ for (const _model of models) {
+ const seriesModel = _model as SeriesModel;
+ const blurred = isBlurred(seriesModel);
+ if (!blurred) {
+ notBlurredIndex = seriesModel.seriesIndex;
+ }
+ hasBlurred = blurred || hasBlurred;
+ }
+ if (hasBlurred) {
+ return notBlurredIndex;
+ }
+ }
+ return -1;
+};
+
export const toNamedData = (data: DataSet): NamedDataSet => {
if (!data?.length) {
return [];
@@ -304,6 +346,7 @@ export const tooltipTriggerTranslationMap = new Map
return thresholdValue;
};
-const generateChartThresholds = (thresholdItems: TimeSeriesChartThresholdItem[], darkMode: boolean): Array => {
+const generateChartThresholds = (thresholdItems: TimeSeriesChartThresholdItem[]): Array => {
const series: Array = [];
for (const item of thresholdItems) {
if (isDefinedAndNotNull(item.value)) {
@@ -1215,7 +1231,8 @@ const createTimeSeriesChartSeries = (item: TimeSeriesChartDataItem,
const lineSeriesOption = seriesOption as LineSeriesOption;
lineSeriesOption.type = 'line';
lineSeriesOption.label = createSeriesLabelOption(item, lineSettings.showPointLabel,
- lineSettings.pointLabelFont, lineSettings.pointLabelColor, lineSettings.pointLabelPosition, darkMode);
+ lineSettings.pointLabelFont, lineSettings.pointLabelColor, lineSettings.pointLabelPosition,
+ lineSettings.pointLabelFormatter, darkMode);
lineSeriesOption.step = lineSettings.step ? lineSettings.stepType : false;
lineSeriesOption.smooth = lineSettings.smooth;
if (lineSettings.smooth) {
@@ -1256,9 +1273,11 @@ const createTimeSeriesChartSeries = (item: TimeSeriesChartDataItem,
}
item.barRenderContext.visualSettings = barVisualSettings;
item.barRenderContext.labelOption = createSeriesLabelOption(item, barSettings.showLabel,
- barSettings.labelFont, barSettings.labelColor, barSettings.labelPosition, darkMode);
+ barSettings.labelFont, barSettings.labelColor, barSettings.labelPosition, barSettings.labelFormatter, darkMode);
+ item.barRenderContext.additionalLabelOption = barSettings.additionalLabelOption;
barSeriesOption.renderItem = (params, api) =>
renderTimeSeriesBar(params, api, item.barRenderContext);
+ barSeriesOption.labelLayout = barSettings.labelLayout;
}
}
seriesOption.data = item.data;
@@ -1266,19 +1285,41 @@ const createTimeSeriesChartSeries = (item: TimeSeriesChartDataItem,
};
const createSeriesLabelOption = (item: TimeSeriesChartDataItem, show: boolean,
- labelFont: Font, labelColor: string, position: SeriesLabelPosition,
+ labelFont: Font, labelColor: string, position: SeriesLabelPosition | BuiltinTextPosition,
+ labelFormatter: string | LabelFormatterCallback,
darkMode: boolean): SeriesLabelOption => {
let labelStyle: ComponentStyle = {};
if (show) {
labelStyle = createChartTextStyle(labelFont, labelColor, darkMode, 'series.label');
}
+ let formatter: LabelFormatterCallback;
+ if (labelFormatter) {
+ if (isFunction(labelFormatter)) {
+ formatter = labelFormatter as LabelFormatterCallback;
+ } else if (labelFormatter.length) {
+ const formatFunction = parseFunction(labelFormatter, ['value']);
+ formatter = (params): string => {
+ let result: string;
+ try {
+ result = formatFunction(params.value[1]);
+ } catch (_e) {
+ }
+ if (isUndefined(result)) {
+ result = formatValue(params.value[1], item.decimals, item.units, false);
+ }
+ return `{value|${result}}`;
+ };
+ } else {
+ formatter = (params): string => {
+ const value = formatValue(params.value[1], item.decimals, item.units, false);
+ return `{value|${value}}`;
+ };
+ }
+ }
return {
show,
position,
- formatter: (params): string => {
- const value = formatValue(params.value[1], item.decimals, item.units, false);
- return `{value|${value}}`;
- },
+ formatter,
rich: {
value: labelStyle
}
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts
index bd9005c497..c14cd66b56 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts
@@ -51,7 +51,7 @@ import {
EChartsOption,
echartsTooltipFormatter,
EChartsTooltipTrigger,
- getAxisExtent,
+ getAxisExtent, getFocusedSeriesIndex,
measureXAxisNameHeight,
measureYAxisNameWidth,
toNamedData
@@ -300,6 +300,8 @@ export class TbTimeSeriesChart {
const targetBarWidth = noAggregationBarWidthSettings.strategy === TimeSeriesChartNoAggregationBarWidthStrategy.group ?
noAggregationBarWidthSettings.groupWidth : noAggregationBarWidthSettings.barWidth;
this.barRenderSharedContext = {
+ barGap: this.settings.barWidthSettings.barGap,
+ intervalGap: this.settings.barWidthSettings.intervalGap,
timeInterval: this.ctx.timeWindow?.interval,
noAggregationBarWidthStrategy: noAggregationBarWidthSettings.strategy,
noAggregationWidthRelative: targetBarWidth.relative,
@@ -492,8 +494,9 @@ export class TbTimeSeriesChart {
},
formatter: (params: CallbackDataParams[]) =>
this.settings.showTooltip ? echartsTooltipFormatter(this.renderer, this.tooltipDateFormat,
- this.settings, params, 0, '', -1, this.dataItems,
- this.noAggregation ? null : this.ctx.timeWindow.interval) : undefined,
+ this.settings, params, 0, '',
+ this.settings.tooltipShowFocusedSeries ? getFocusedSeriesIndex(this.timeSeriesChart) : -1,
+ this.dataItems, this.noAggregation ? null : this.ctx.timeWindow.interval) : undefined,
padding: [8, 12],
backgroundColor: this.settings.tooltipBackgroundColor,
borderWidth: 0,