From a4755684026b497d20d76bb0b39a1b31de6e6c9e Mon Sep 17 00:00:00 2001 From: Artyom Hackimullin Date: Tue, 15 Apr 2025 14:43:59 +0300 Subject: [PATCH] SUPPORT-9111: commit --- .../css/components-business-metrics.css | 27 ++++++++++ .../ErvuChartTooltip.html | 10 ++++ .../ervu_business_metrics/ErvuChartV2.html | 4 ++ .../component/chart/ErvuChartTooltip.ts | 51 +++++++++++++++++++ .../component/chart/ErvuChartV2.ts | 50 +++++++++++++----- frontend/src/ts/modules/app/app.module.ts | 4 +- 6 files changed, 131 insertions(+), 15 deletions(-) create mode 100644 frontend/src/resources/template/ervu_business_metrics/ErvuChartTooltip.html create mode 100644 frontend/src/ts/ervu_business_metrics/component/chart/ErvuChartTooltip.ts diff --git a/frontend/src/resources/css/components-business-metrics.css b/frontend/src/resources/css/components-business-metrics.css index 62c4e33..5c6b33c 100644 --- a/frontend/src/resources/css/components-business-metrics.css +++ b/frontend/src/resources/css/components-business-metrics.css @@ -420,6 +420,33 @@ width: 35%; padding-right: 0; } +/* Default Tooltip Styles in Chart.js */ +.webbpm.ervu_business_metrics #chartjs-tooltip { + position: absolute; + color: white; + border-radius: 4px; + padding: 6px; + font: normal 12px 'Golos'; + line-height: 1.2; + transition: all .1s ease; + pointer-events: none; + background-color: rgba(0, 0, 0, 0.9); + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3); + z-index: 1; +} +.webbpm.ervu_business_metrics #chartjs-tooltip .tooltip-color { + display: inline-block; + width: 10px; + height: 10px; + margin-right: 4px; + border-radius: 10px; + border-color: var(--color-text-primary); +} +.webbpm.ervu_business_metrics #chartjs-tooltip .tooltip-list { + list-style: none; + margin: 0; + padding: 0; +} .webbpm.ervu_business_metrics .graph-row-left ervu-chart-v2 { margin-top: -30px; } diff --git a/frontend/src/resources/template/ervu_business_metrics/ErvuChartTooltip.html b/frontend/src/resources/template/ervu_business_metrics/ErvuChartTooltip.html new file mode 100644 index 0000000..86c2c58 --- /dev/null +++ b/frontend/src/resources/template/ervu_business_metrics/ErvuChartTooltip.html @@ -0,0 +1,10 @@ +
+
+
    +
  • + + {{ item.body }} +
  • +
+
+
\ No newline at end of file diff --git a/frontend/src/resources/template/ervu_business_metrics/ErvuChartV2.html b/frontend/src/resources/template/ervu_business_metrics/ErvuChartV2.html index a14d3c6..92adc08 100644 --- a/frontend/src/resources/template/ervu_business_metrics/ErvuChartV2.html +++ b/frontend/src/resources/template/ervu_business_metrics/ErvuChartV2.html @@ -1,3 +1,7 @@
+ +
diff --git a/frontend/src/ts/ervu_business_metrics/component/chart/ErvuChartTooltip.ts b/frontend/src/ts/ervu_business_metrics/component/chart/ErvuChartTooltip.ts new file mode 100644 index 0000000..8c29cd4 --- /dev/null +++ b/frontend/src/ts/ervu_business_metrics/component/chart/ErvuChartTooltip.ts @@ -0,0 +1,51 @@ +import { + ChangeDetectionStrategy, + Component, + Input, + OnChanges, + SimpleChanges +} from '@angular/core'; +import {Visible} from "@webbpm/base-package"; +import {TooltipModel} from "chart.js"; +import {color} from "chart.js/helpers"; + +@Component({ + moduleId: module.id, + selector: 'ervu-chart-tooltip', + templateUrl: `./../../../../../src/resources/template/ervu_business_metrics/ErvuChartTooltip.html`, + changeDetection: ChangeDetectionStrategy.OnPush + }) +export class ErvuChartTooltip implements OnChanges { + @Input() + public tooltipModel: TooltipModel; + @Input() + public position: any; + + @Visible("false") + public visible: boolean = false; + @Visible("false") + public items: any[]; + + ngOnChanges(changes: SimpleChanges): void { + if ('position' in changes) { + if (!this.tooltipModel || this.tooltipModel.opacity == 0 || this.tooltipModel.body.length == 0) { + this.visible = false; + return; + } + this.visible = true; + this.refreshContent(); + } + } + + public refreshContent() { + const tooltipModel: TooltipModel = this.tooltipModel; + const titleLines: string[] = tooltipModel.title || []; + const bodyLines: any = tooltipModel.body.map((bodyItem) => bodyItem.lines); + + this.items = bodyLines.map((body, i) => ({ + title: titleLines[i] || '', + body: body, + color: this.tooltipModel.labelColors[i].backgroundColor + })); + } +} diff --git a/frontend/src/ts/ervu_business_metrics/component/chart/ErvuChartV2.ts b/frontend/src/ts/ervu_business_metrics/component/chart/ErvuChartV2.ts index a1db042..fa07bfa 100644 --- a/frontend/src/ts/ervu_business_metrics/component/chart/ErvuChartV2.ts +++ b/frontend/src/ts/ervu_business_metrics/component/chart/ErvuChartV2.ts @@ -4,10 +4,11 @@ import { ChangeDetectorRef, Component, ElementRef, - Input + Input, + ViewChild } from "@angular/core"; -import {Chart as ChartJs, ChartType, DefaultDataPoint} from "chart.js"; +import {Chart as ChartJs, ChartType, DefaultDataPoint, TooltipModel} from "chart.js"; import "chartjs-adapter-moment"; import { AdvancedProperty, ChartConfigDto, @@ -23,6 +24,7 @@ import {ChartLegendSettings} from "./model/ChartLegendSettings"; import {Options} from "./model/Options"; import {ChartPlugin} from "./plugin/ChartPlugin"; import {ChartUtils} from "./ChartUtils"; +import {ErvuChartTooltip} from "./ErvuChartTooltip"; @Component({ moduleId: module.id, @@ -88,6 +90,14 @@ export class ErvuChartV2 extends Control implements Filterable { @AdvancedProperty() public noDataStyle: string = "rgb(100,100,100)"; + @ViewChild(ErvuChartTooltip) + @Visible("false") + public chartTooltip: ErvuChartTooltip; + @Visible("false") + public tooltipPosition: any; + @Visible("false") + public tooltipModel: TooltipModel; + private chartRpcService: ChartV2RpcService; private filterMap: { [key: string]: Filter } = {}; private loadEnabled: boolean = true; @@ -214,7 +224,7 @@ export class ErvuChartV2 extends Control implements Filterable { chartOptions.plugins = chartOptions.plugins ? chartOptions.plugins : {}; chartOptions.plugins.legend = this.legend ? this.legend : {}; - chartOptions.plugins.tooltip = {enabled: this.showTooltip}; + chartOptions.plugins.tooltip = this.getTooltipConfiguration(); if (this.title && this.title.text) { chartOptions.plugins.title = this.title; @@ -303,17 +313,6 @@ export class ErvuChartV2 extends Control implements Filterable { } } - chartConfig.tooltips = { - callbacks: { - title: function (tooltipItem, data) { - return data.labels[tooltipItem[0].index] - }, - label: function (tooltipItem, data) { - let dataset = data.datasets[tooltipItem.datasetIndex]; - return dataset.label + ": " + dataset.data[tooltipItem.index]; - } - } - }; this.chartConfig = chartConfig; } @@ -414,6 +413,29 @@ export class ErvuChartV2 extends Control implements Filterable { this.chart = new ChartJs(canvasEl, jQuery.extend(true, chartConfig, chartData)); } + //General config tooltip. + private getTooltipConfiguration() { + return { + enabled: false, + external: (context) => { + if (this.showTooltip) { + if (!context || !this.chartTooltip) { + return; + } + const positionX = this.chart.canvas.offsetLeft; + const positionY = this.chart.canvas.offsetTop; + + this.tooltipModel = context.tooltip; + this.tooltipPosition = { + 'left': positionX + context.tooltip.caretX, + 'top': positionY + context.tooltip.caretY + } + this.cd.markForCheck(); + } + } + }; + } + clear() { //todo SUPPORT-4909 throw new UnsupportedOperationError("Unsupported operation"); } diff --git a/frontend/src/ts/modules/app/app.module.ts b/frontend/src/ts/modules/app/app.module.ts index 4da7ddc..e82cc22 100644 --- a/frontend/src/ts/modules/app/app.module.ts +++ b/frontend/src/ts/modules/app/app.module.ts @@ -24,6 +24,7 @@ import {TokenInterceptor} from "./interceptor/token-interceptor.service"; import {DropdownTreeViewComponent} from "../../component/field/DropdownTreeViewComponent"; import {DropdownTreeviewSelectComponent} from "../../component/external/ngx-treeview/dropdown-treeview-select/dropdown-treeview-select.component"; import {TreeviewModule} from "ngx-treeview"; +import {ErvuChartTooltip} from "../../ervu_business_metrics/component/chart/ErvuChartTooltip"; registerLocaleData(localeRu); export const DIRECTIVES = [ @@ -34,7 +35,8 @@ export const DIRECTIVES = [ forwardRef(() => ErvuChartV2), forwardRef(() => FilterContainer), forwardRef(() => DropdownTreeViewComponent), - forwardRef(() => DropdownTreeviewSelectComponent) + forwardRef(() => DropdownTreeviewSelectComponent), + forwardRef(() => ErvuChartTooltip) ]; @NgModule({