UI: Added support unicode symbols in chart legend/tooltip

This commit is contained in:
Vladyslav_Prykhodko 2024-06-20 11:34:37 +03:00
parent c4e5ab65ee
commit 19d692c1e1
3 changed files with 18 additions and 9 deletions

View File

@ -106,15 +106,15 @@
(mouseleave)="onLegendKeyLeave(legendKey)" (mouseleave)="onLegendKeyLeave(legendKey)"
(click)="toggleLegendKey(legendKey)"> (click)="toggleLegendKey(legendKey)">
<div class="tb-time-series-chart-legend-item-label-circle" [style]="{background: !legendKey.dataKey.hidden ? legendKey.dataKey.color : null}"></div> <div class="tb-time-series-chart-legend-item-label-circle" [style]="{background: !legendKey.dataKey.hidden ? legendKey.dataKey.color : null}"></div>
<div [style]="!legendKey.dataKey.hidden ? legendLabelStyle : disabledLegendLabelStyle">{{ legendKey.dataKey.label }}</div> <div [style]="!legendKey.dataKey.hidden ? legendLabelStyle : disabledLegendLabelStyle" [innerHTML]="legendKey.dataKey.label | safe: 'html'"></div>
</div> </div>
</div> </div>
</ng-template> </ng-template>
<ng-template #legendDataRow let-label="label" let-type="type"> <ng-template #legendDataRow let-label="label" let-type="type">
<tr> <tr>
<th class="tb-time-series-chart-legend-type-label" [style]="legendColumnTitleStyle">{{ label | translate }}</th> <th class="tb-time-series-chart-legend-type-label" [style]="legendColumnTitleStyle">{{ label | translate }}</th>
<td *ngFor="let legendKey of legendKeys" class="tb-time-series-chart-legend-value" [style]="legendValueStyle"> <td *ngFor="let legendKey of legendKeys" class="tb-time-series-chart-legend-value" [style]="legendValueStyle"
{{ legendData.data[legendKey.dataIndex][type] }} [innerHTML]="legendData.data[legendKey.dataIndex][type] | safe: 'html'">
</td> </td>
</tr> </tr>
</ng-template> </ng-template>

View File

@ -80,7 +80,7 @@ import {
WidgetTimewindow WidgetTimewindow
} from '@shared/models/time/time.models'; } from '@shared/models/time/time.models';
import { UtilsService } from '@core/services/utils.service'; import { UtilsService } from '@core/services/utils.service';
import { Renderer2 } from '@angular/core'; import { Renderer2, SecurityContext } from '@angular/core';
import { import {
chartAnimationDefaultSettings, chartAnimationDefaultSettings,
ChartAnimationSettings, ChartAnimationSettings,
@ -98,6 +98,7 @@ import {
prepareChartThemeColor prepareChartThemeColor
} from '@home/components/widget/lib/chart/chart.models'; } from '@home/components/widget/lib/chart/chart.models';
import { BarSeriesLabelOption } from 'echarts/types/src/chart/bar/BarSeries'; import { BarSeriesLabelOption } from 'echarts/types/src/chart/bar/BarSeries';
import { DomSanitizer } from '@angular/platform-browser';
type TimeSeriesChartDataEntry = [number, any, number, number]; type TimeSeriesChartDataEntry = [number, any, number, number];
@ -261,6 +262,7 @@ export const createTooltipValueFormatFunction =
}; };
export const timeSeriesChartTooltipFormatter = (renderer: Renderer2, export const timeSeriesChartTooltipFormatter = (renderer: Renderer2,
sanitizer: DomSanitizer,
tooltipDateFormat: DateFormatProcessor, tooltipDateFormat: DateFormatProcessor,
settings: TimeSeriesChartTooltipWidgetSettings, settings: TimeSeriesChartTooltipWidgetSettings,
params: CallbackDataParams[] | CallbackDataParams, params: CallbackDataParams[] | CallbackDataParams,
@ -280,8 +282,9 @@ export const timeSeriesChartTooltipFormatter = (renderer: Renderer2,
renderer.setStyle(tooltipElement, 'align-items', 'flex-start'); renderer.setStyle(tooltipElement, 'align-items', 'flex-start');
renderer.setStyle(tooltipElement, 'gap', '16px'); renderer.setStyle(tooltipElement, 'gap', '16px');
buildItemsTooltip(tooltipElement, tooltipParams.items, renderer, tooltipDateFormat, settings, valueFormatFunction, interval); buildItemsTooltip(tooltipElement, tooltipParams.items, renderer, sanitizer, tooltipDateFormat, settings, valueFormatFunction, interval);
buildItemsTooltip(tooltipElement, tooltipParams.comparisonItems, renderer, tooltipDateFormat, settings, valueFormatFunction, interval); buildItemsTooltip(tooltipElement, tooltipParams.comparisonItems, renderer, sanitizer, tooltipDateFormat, settings,
valueFormatFunction, interval);
return tooltipElement; return tooltipElement;
}; };
@ -299,6 +302,7 @@ interface TooltipParams {
const buildItemsTooltip = (tooltipElement: HTMLElement, const buildItemsTooltip = (tooltipElement: HTMLElement,
items: TooltipItem[], items: TooltipItem[],
renderer: Renderer2, renderer: Renderer2,
sanitizer: DomSanitizer,
tooltipDateFormat: DateFormatProcessor, tooltipDateFormat: DateFormatProcessor,
settings: TimeSeriesChartTooltipWidgetSettings, settings: TimeSeriesChartTooltipWidgetSettings,
valueFormatFunction: TimeSeriesChartTooltipValueFormatFunction, valueFormatFunction: TimeSeriesChartTooltipValueFormatFunction,
@ -316,7 +320,7 @@ const buildItemsTooltip = (tooltipElement: HTMLElement,
} }
for (const item of items) { for (const item of items) {
renderer.appendChild(tooltipItemsElement, renderer.appendChild(tooltipItemsElement,
constructTooltipSeriesElement(renderer, settings, item, valueFormatFunction)); constructTooltipSeriesElement(renderer, sanitizer, settings, item, valueFormatFunction));
} }
} }
}; };
@ -396,6 +400,7 @@ const constructTooltipDateElement = (renderer: Renderer2,
}; };
const constructTooltipSeriesElement = (renderer: Renderer2, const constructTooltipSeriesElement = (renderer: Renderer2,
sanitizer: DomSanitizer,
settings: TimeSeriesChartTooltipWidgetSettings, settings: TimeSeriesChartTooltipWidgetSettings,
item: TooltipItem, item: TooltipItem,
valueFormatFunction: TimeSeriesChartTooltipValueFormatFunction): HTMLElement => { valueFormatFunction: TimeSeriesChartTooltipValueFormatFunction): HTMLElement => {
@ -417,7 +422,7 @@ const constructTooltipSeriesElement = (renderer: Renderer2,
renderer.setStyle(circleElement, 'background', item.param.color); renderer.setStyle(circleElement, 'background', item.param.color);
renderer.appendChild(labelElement, circleElement); renderer.appendChild(labelElement, circleElement);
const labelTextElement: HTMLElement = renderer.createElement('div'); const labelTextElement: HTMLElement = renderer.createElement('div');
renderer.appendChild(labelTextElement, renderer.createText(item.param.seriesName)); renderer.setProperty(labelTextElement, 'innerHTML', sanitizer.sanitize(SecurityContext.HTML, item.param.seriesName));
renderer.setStyle(labelTextElement, 'font-family', settings.tooltipLabelFont.family); renderer.setStyle(labelTextElement, 'font-family', settings.tooltipLabelFont.family);
renderer.setStyle(labelTextElement, 'font-size', settings.tooltipLabelFont.size + settings.tooltipLabelFont.sizeUnit); renderer.setStyle(labelTextElement, 'font-size', settings.tooltipLabelFont.size + settings.tooltipLabelFont.sizeUnit);
renderer.setStyle(labelTextElement, 'font-style', settings.tooltipLabelFont.style); renderer.setStyle(labelTextElement, 'font-style', settings.tooltipLabelFont.style);

View File

@ -74,6 +74,7 @@ import { DeepPartial } from '@shared/models/common';
import { BarRenderSharedContext } from '@home/components/widget/lib/chart/time-series-chart-bar.models'; import { BarRenderSharedContext } from '@home/components/widget/lib/chart/time-series-chart-bar.models';
import { TimeSeriesChartStateValueConverter } from '@home/components/widget/lib/chart/time-series-chart-state.models'; import { TimeSeriesChartStateValueConverter } from '@home/components/widget/lib/chart/time-series-chart-state.models';
import { ChartLabelPosition, ChartShape, toAnimationOption } from '@home/components/widget/lib/chart/chart.models'; import { ChartLabelPosition, ChartShape, toAnimationOption } from '@home/components/widget/lib/chart/chart.models';
import { DomSanitizer } from '@angular/platform-browser';
export class TbTimeSeriesChart { export class TbTimeSeriesChart {
@ -153,6 +154,8 @@ export class TbTimeSeriesChart {
private latestData: FormattedData[] = []; private latestData: FormattedData[] = [];
private readonly sanitizer: DomSanitizer;
yMin$ = this.yMinSubject.asObservable(); yMin$ = this.yMinSubject.asObservable();
yMax$ = this.yMaxSubject.asObservable(); yMax$ = this.yMaxSubject.asObservable();
@ -171,6 +174,7 @@ export class TbTimeSeriesChart {
this.stateValueConverter = new TimeSeriesChartStateValueConverter(this.ctx.utilsService, this.settings.states); this.stateValueConverter = new TimeSeriesChartStateValueConverter(this.ctx.utilsService, this.settings.states);
this.tooltipValueFormatFunction = this.stateValueConverter.tooltipFormatter; this.tooltipValueFormatFunction = this.stateValueConverter.tooltipFormatter;
} }
this.sanitizer = this.ctx.sanitizer;
const $dashboardPageElement = this.ctx.$containerParent.parents('.tb-dashboard-page'); const $dashboardPageElement = this.ctx.$containerParent.parents('.tb-dashboard-page');
const dashboardPageElement = $dashboardPageElement.length ? $($dashboardPageElement[$dashboardPageElement.length-1]) : null; const dashboardPageElement = $dashboardPageElement.length ? $($dashboardPageElement[$dashboardPageElement.length-1]) : null;
this.darkMode = this.settings.darkMode || dashboardPageElement?.hasClass('dark'); this.darkMode = this.settings.darkMode || dashboardPageElement?.hasClass('dark');
@ -603,7 +607,7 @@ export class TbTimeSeriesChart {
type: this.noAggregation ? 'line' : 'shadow' type: this.noAggregation ? 'line' : 'shadow'
}, },
formatter: (params: CallbackDataParams[]) => formatter: (params: CallbackDataParams[]) =>
this.settings.showTooltip ? timeSeriesChartTooltipFormatter(this.renderer, this.tooltipDateFormat, this.settings.showTooltip ? timeSeriesChartTooltipFormatter(this.renderer, this.sanitizer, this.tooltipDateFormat,
this.settings, params, this.tooltipValueFormatFunction, this.settings, params, this.tooltipValueFormatFunction,
this.settings.tooltipShowFocusedSeries ? getFocusedSeriesIndex(this.timeSeriesChart) : -1, this.settings.tooltipShowFocusedSeries ? getFocusedSeriesIndex(this.timeSeriesChart) : -1,
this.dataItems, this.noAggregation ? null : this.ctx.timeWindow.interval) : undefined, this.dataItems, this.noAggregation ? null : this.ctx.timeWindow.interval) : undefined,