]> git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health-pie/health-pie.component.ts
import ceph nautilus 14.2.2
[ceph.git] / ceph / src / pybind / mgr / dashboard / frontend / src / app / ceph / dashboard / health-pie / health-pie.component.ts
1 import {
2 Component,
3 ElementRef,
4 EventEmitter,
5 Input,
6 OnChanges,
7 OnInit,
8 Output,
9 ViewChild
10 } from '@angular/core';
11
12 import * as Chart from 'chart.js';
13 import * as _ from 'lodash';
14
15 import { ChartTooltip } from '../../../shared/models/chart-tooltip';
16 import { DimlessBinaryPipe } from '../../../shared/pipes/dimless-binary.pipe';
17 import { DimlessPipe } from '../../../shared/pipes/dimless.pipe';
18 import { HealthPieColor } from './health-pie-color.enum';
19
20 @Component({
21 selector: 'cd-health-pie',
22 templateUrl: './health-pie.component.html',
23 styleUrls: ['./health-pie.component.scss']
24 })
25 export class HealthPieComponent implements OnChanges, OnInit {
26 @ViewChild('chartCanvas')
27 chartCanvasRef: ElementRef;
28 @ViewChild('chartTooltip')
29 chartTooltipRef: ElementRef;
30
31 @Input()
32 data: any;
33 @Input()
34 config = {};
35 @Input()
36 isBytesData = false;
37 @Input()
38 tooltipFn: any;
39 @Input()
40 showLabelAsTooltip = false;
41 @Output()
42 prepareFn = new EventEmitter();
43
44 chartConfig: any = {
45 chartType: 'pie',
46 dataset: [
47 {
48 label: null,
49 borderWidth: 0
50 }
51 ],
52 options: {
53 legend: {
54 display: true,
55 position: 'right',
56 labels: { usePointStyle: true },
57 onClick: (event, legendItem) => {
58 this.onLegendClick(event, legendItem);
59 }
60 },
61 animation: { duration: 0 },
62 tooltips: {
63 enabled: false
64 },
65 title: {
66 display: false
67 }
68 }
69 };
70 private hiddenSlices = [];
71
72 constructor(private dimlessBinary: DimlessBinaryPipe, private dimless: DimlessPipe) {}
73
74 ngOnInit() {
75 // An extension to Chart.js to enable rendering some
76 // text in the middle of a doughnut
77 Chart.pluginService.register({
78 beforeDraw: function(chart) {
79 if (!chart.options.center_text) {
80 return;
81 }
82
83 const width = chart.chart.width,
84 height = chart.chart.height,
85 ctx = chart.chart.ctx;
86
87 ctx.restore();
88 const fontSize = (height / 114).toFixed(2);
89 ctx.font = fontSize + 'em sans-serif';
90 ctx.textBaseline = 'middle';
91
92 const text = chart.options.center_text,
93 textX = Math.round((width - ctx.measureText(text).width) / 2),
94 textY = height / 2;
95
96 ctx.fillText(text, textX, textY);
97 ctx.save();
98 }
99 });
100
101 const getStyleTop = (tooltip, positionY) => {
102 return positionY + tooltip.caretY - tooltip.height - 10 + 'px';
103 };
104
105 const getStyleLeft = (tooltip, positionX) => {
106 return positionX + tooltip.caretX + 'px';
107 };
108
109 const chartTooltip = new ChartTooltip(
110 this.chartCanvasRef,
111 this.chartTooltipRef,
112 getStyleLeft,
113 getStyleTop
114 );
115
116 const getBody = (body) => {
117 return this.getChartTooltipBody(body);
118 };
119
120 chartTooltip.getBody = getBody;
121
122 this.chartConfig.options.tooltips.custom = (tooltip) => {
123 chartTooltip.customTooltips(tooltip);
124 };
125
126 this.chartConfig.colors = [
127 {
128 backgroundColor: [
129 HealthPieColor.DEFAULT_RED,
130 HealthPieColor.DEFAULT_BLUE,
131 HealthPieColor.DEFAULT_ORANGE,
132 HealthPieColor.DEFAULT_GREEN,
133 HealthPieColor.DEFAULT_MAGENTA
134 ]
135 }
136 ];
137
138 _.merge(this.chartConfig, this.config);
139
140 this.prepareFn.emit([this.chartConfig, this.data]);
141 }
142
143 ngOnChanges() {
144 this.prepareFn.emit([this.chartConfig, this.data]);
145 this.hideSlices();
146 this.setChartSliceBorderWidth();
147 }
148
149 private getChartTooltipBody(body) {
150 const bodySplit = body[0].split(': ');
151
152 if (this.showLabelAsTooltip) {
153 return bodySplit[0];
154 }
155
156 bodySplit[1] = this.isBytesData
157 ? this.dimlessBinary.transform(bodySplit[1])
158 : this.dimless.transform(bodySplit[1]);
159
160 return bodySplit.join(': ');
161 }
162
163 private setChartSliceBorderWidth() {
164 let nonZeroValueSlices = 0;
165 _.forEach(this.chartConfig.dataset[0].data, function(slice) {
166 if (slice > 0) {
167 nonZeroValueSlices += 1;
168 }
169 });
170
171 this.chartConfig.dataset[0].borderWidth = nonZeroValueSlices > 1 ? 1 : 0;
172 }
173
174 private onLegendClick(event, legendItem) {
175 event.stopPropagation();
176 this.hiddenSlices[legendItem.index] = !legendItem.hidden;
177 this.ngOnChanges();
178 }
179
180 private hideSlices() {
181 _.forEach(this.chartConfig.dataset[0].data, (_slice, sliceIndex) => {
182 if (this.hiddenSlices[sliceIndex]) {
183 this.chartConfig.dataset[0].data[sliceIndex] = undefined;
184 }
185 });
186 }
187 }