]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
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'; | |
f67539c2 | 13 | import _ from 'lodash'; |
f91f0fd5 | 14 | import { PluginServiceGlobalRegistrationAndOptions } from 'ng2-charts'; |
11fdf7f2 | 15 | |
f67539c2 TL |
16 | import { ChartTooltip } from '~/app/shared/models/chart-tooltip'; |
17 | import { DimlessBinaryPipe } from '~/app/shared/pipes/dimless-binary.pipe'; | |
18 | import { DimlessPipe } from '~/app/shared/pipes/dimless.pipe'; | |
19 | import styles from '~/styles.scss'; | |
11fdf7f2 TL |
20 | |
21 | @Component({ | |
22 | selector: 'cd-health-pie', | |
23 | templateUrl: './health-pie.component.html', | |
24 | styleUrls: ['./health-pie.component.scss'] | |
25 | }) | |
26 | export class HealthPieComponent implements OnChanges, OnInit { | |
9f95a23c | 27 | @ViewChild('chartCanvas', { static: true }) |
11fdf7f2 | 28 | chartCanvasRef: ElementRef; |
9f95a23c | 29 | @ViewChild('chartTooltip', { static: true }) |
11fdf7f2 TL |
30 | chartTooltipRef: ElementRef; |
31 | ||
32 | @Input() | |
33 | data: any; | |
34 | @Input() | |
81eedcae | 35 | config = {}; |
11fdf7f2 TL |
36 | @Input() |
37 | isBytesData = false; | |
38 | @Input() | |
11fdf7f2 | 39 | tooltipFn: any; |
81eedcae TL |
40 | @Input() |
41 | showLabelAsTooltip = false; | |
11fdf7f2 TL |
42 | @Output() |
43 | prepareFn = new EventEmitter(); | |
44 | ||
45 | chartConfig: any = { | |
f91f0fd5 | 46 | chartType: 'doughnut', |
11fdf7f2 TL |
47 | dataset: [ |
48 | { | |
49 | label: null, | |
50 | borderWidth: 0 | |
51 | } | |
52 | ], | |
f91f0fd5 TL |
53 | colors: [ |
54 | { | |
55 | backgroundColor: [ | |
f67539c2 TL |
56 | styles.chartHealthColorGreen, |
57 | styles.chartHealthColorYellow, | |
58 | styles.chartHealthColorOrange, | |
59 | styles.chartHealthColorRed, | |
60 | styles.chartHealthColorBlue | |
f91f0fd5 TL |
61 | ] |
62 | } | |
63 | ], | |
11fdf7f2 | 64 | options: { |
f91f0fd5 TL |
65 | cutoutPercentage: 90, |
66 | events: ['click', 'mouseout', 'touchstart'], | |
11fdf7f2 | 67 | legend: { |
81eedcae | 68 | display: true, |
11fdf7f2 | 69 | position: 'right', |
f91f0fd5 TL |
70 | labels: { |
71 | boxWidth: 10, | |
72 | usePointStyle: false | |
11fdf7f2 TL |
73 | } |
74 | }, | |
f91f0fd5 TL |
75 | plugins: { |
76 | center_text: true | |
77 | }, | |
11fdf7f2 | 78 | tooltips: { |
f91f0fd5 TL |
79 | enabled: true, |
80 | displayColors: false, | |
f67539c2 | 81 | backgroundColor: styles.chartHealthTootlipBgColor, |
f91f0fd5 TL |
82 | cornerRadius: 0, |
83 | bodyFontSize: 14, | |
84 | bodyFontStyle: '600', | |
85 | position: 'nearest', | |
86 | xPadding: 12, | |
87 | yPadding: 12, | |
88 | callbacks: { | |
89 | label: (item: Record<string, any>, data: Record<string, any>) => { | |
90 | let text = data.labels[item.index]; | |
91 | if (!text.includes('%')) { | |
92 | text = `${text} (${data.datasets[item.datasetIndex].data[item.index]}%)`; | |
93 | } | |
94 | return text; | |
95 | } | |
96 | } | |
81eedcae TL |
97 | }, |
98 | title: { | |
99 | display: false | |
11fdf7f2 TL |
100 | } |
101 | } | |
102 | }; | |
11fdf7f2 | 103 | |
f91f0fd5 TL |
104 | public doughnutChartPlugins: PluginServiceGlobalRegistrationAndOptions[] = [ |
105 | { | |
106 | id: 'center_text', | |
107 | beforeDraw(chart: Chart) { | |
f91f0fd5 TL |
108 | const defaultFontFamily = 'Helvetica Neue, Helvetica, Arial, sans-serif'; |
109 | Chart.defaults.global.defaultFontFamily = defaultFontFamily; | |
110 | const ctx = chart.ctx; | |
111 | if (!chart.options.plugins.center_text || !chart.data.datasets[0].label) { | |
11fdf7f2 TL |
112 | return; |
113 | } | |
114 | ||
f91f0fd5 TL |
115 | ctx.save(); |
116 | const label = chart.data.datasets[0].label.split('\n'); | |
11fdf7f2 | 117 | |
f91f0fd5 TL |
118 | const centerX = (chart.chartArea.left + chart.chartArea.right) / 2; |
119 | const centerY = (chart.chartArea.top + chart.chartArea.bottom) / 2; | |
120 | ctx.textAlign = 'center'; | |
11fdf7f2 TL |
121 | ctx.textBaseline = 'middle'; |
122 | ||
f91f0fd5 | 123 | ctx.font = `24px ${defaultFontFamily}`; |
f67539c2 | 124 | ctx.fillStyle = styles.chartHealthCenterTextColor; |
f91f0fd5 | 125 | ctx.fillText(label[0], centerX, centerY - 10); |
11fdf7f2 | 126 | |
f91f0fd5 TL |
127 | if (label.length > 1) { |
128 | ctx.font = `14px ${defaultFontFamily}`; | |
f67539c2 | 129 | ctx.fillStyle = styles.chartHealthCenterTextDescriptionColor; |
f91f0fd5 TL |
130 | ctx.fillText(label[1], centerX, centerY + 10); |
131 | } | |
132 | ctx.restore(); | |
11fdf7f2 | 133 | } |
f91f0fd5 TL |
134 | } |
135 | ]; | |
136 | ||
137 | constructor(private dimlessBinary: DimlessBinaryPipe, private dimless: DimlessPipe) {} | |
11fdf7f2 | 138 | |
f91f0fd5 | 139 | ngOnInit() { |
9f95a23c | 140 | const getStyleTop = (tooltip: any, positionY: number) => { |
11fdf7f2 TL |
141 | return positionY + tooltip.caretY - tooltip.height - 10 + 'px'; |
142 | }; | |
143 | ||
9f95a23c | 144 | const getStyleLeft = (tooltip: any, positionX: number) => { |
11fdf7f2 TL |
145 | return positionX + tooltip.caretX + 'px'; |
146 | }; | |
147 | ||
148 | const chartTooltip = new ChartTooltip( | |
149 | this.chartCanvasRef, | |
150 | this.chartTooltipRef, | |
151 | getStyleLeft, | |
152 | getStyleTop | |
153 | ); | |
154 | ||
f91f0fd5 | 155 | chartTooltip.getBody = (body: any) => { |
11fdf7f2 TL |
156 | return this.getChartTooltipBody(body); |
157 | }; | |
158 | ||
81eedcae TL |
159 | _.merge(this.chartConfig, this.config); |
160 | ||
11fdf7f2 TL |
161 | this.prepareFn.emit([this.chartConfig, this.data]); |
162 | } | |
163 | ||
164 | ngOnChanges() { | |
165 | this.prepareFn.emit([this.chartConfig, this.data]); | |
11fdf7f2 TL |
166 | this.setChartSliceBorderWidth(); |
167 | } | |
168 | ||
9f95a23c | 169 | private getChartTooltipBody(body: string[]) { |
11fdf7f2 TL |
170 | const bodySplit = body[0].split(': '); |
171 | ||
81eedcae TL |
172 | if (this.showLabelAsTooltip) { |
173 | return bodySplit[0]; | |
11fdf7f2 TL |
174 | } |
175 | ||
81eedcae TL |
176 | bodySplit[1] = this.isBytesData |
177 | ? this.dimlessBinary.transform(bodySplit[1]) | |
178 | : this.dimless.transform(bodySplit[1]); | |
11fdf7f2 | 179 | |
81eedcae | 180 | return bodySplit.join(': '); |
11fdf7f2 TL |
181 | } |
182 | ||
183 | private setChartSliceBorderWidth() { | |
184 | let nonZeroValueSlices = 0; | |
e306af50 | 185 | _.forEach(this.chartConfig.dataset[0].data, function (slice) { |
11fdf7f2 TL |
186 | if (slice > 0) { |
187 | nonZeroValueSlices += 1; | |
188 | } | |
189 | }); | |
190 | ||
191 | this.chartConfig.dataset[0].borderWidth = nonZeroValueSlices > 1 ? 1 : 0; | |
192 | } | |
11fdf7f2 | 193 | } |