1 import { Component, Input, OnChanges, OnInit } from '@angular/core';
3 import * as Chart from 'chart.js';
4 import _ from 'lodash';
6 import { CssHelper } from '~/app/shared/classes/css-helper';
7 import { DimlessBinaryPipe } from '~/app/shared/pipes/dimless-binary.pipe';
10 selector: 'cd-dashboard-pie',
11 templateUrl: './dashboard-pie.component.html',
12 styleUrls: ['./dashboard-pie.component.scss']
14 export class DashboardPieComponent implements OnChanges, OnInit {
18 highThreshold: number;
26 public doughnutChartPlugins: any[] = [
29 beforeDraw(chart: any) {
30 const cssHelper = new CssHelper();
31 const defaultFontFamily = 'Helvetica Neue, Helvetica, Arial, sans-serif';
32 Chart.defaults.font.family = defaultFontFamily;
33 const ctx = chart.ctx;
34 if (!chart.options.plugins.center_text || !chart.data.datasets[0].label) {
39 const label = chart.data.datasets[0].label[0].split('\n');
41 const centerX = (chart.chartArea.left + chart.chartArea.right) / 2;
42 const centerY = (chart.chartArea.top + chart.chartArea.bottom) / 2;
43 ctx.textAlign = 'center';
44 ctx.textBaseline = 'middle';
46 ctx.font = `24px ${defaultFontFamily}`;
47 ctx.fillText(label[0], centerX, centerY - 10);
49 if (label.length > 1) {
50 ctx.font = `14px ${defaultFontFamily}`;
51 ctx.fillStyle = cssHelper.propertyValue('chart-color-center-text-description');
52 ctx.fillText(label[1], centerX, centerY + 10);
59 constructor(private cssHelper: CssHelper, private dimlessBinary: DimlessBinaryPipe) {
61 chartType: 'doughnut',
67 this.cssHelper.propertyValue('chart-color-light-gray'),
68 this.cssHelper.propertyValue('chart-color-slight-dark-gray'),
69 this.cssHelper.propertyValue('chart-color-dark-gray')
76 this.cssHelper.propertyValue('chart-color-blue'),
77 this.cssHelper.propertyValue('chart-color-white')
83 events: ['click', 'mouseout', 'touchstart'],
93 generateLabels: (chart: any) => {
94 let labels = chart.data.labels.slice(0, this.chartConfig.labels.length);
96 text: $localize`Used: ${chart.data.datasets[1].data[2]}`,
97 fillStyle: chart.data.datasets[1].backgroundColor[0],
98 strokeStyle: chart.data.datasets[1].backgroundColor[0]
101 text: $localize`Warning: ${chart.data.datasets[0].data[0]}%`,
102 fillStyle: chart.data.datasets[0].backgroundColor[1],
103 strokeStyle: chart.data.datasets[0].backgroundColor[1]
106 text: $localize`Danger: ${
107 chart.data.datasets[0].data[0] + chart.data.datasets[0].data[1]
109 fillStyle: chart.data.datasets[0].backgroundColor[2],
110 strokeStyle: chart.data.datasets[0].backgroundColor[2]
119 displayColors: false,
120 backgroundColor: this.cssHelper.propertyValue('chart-color-tooltip-background'),
123 bodyFontStyle: '600',
127 filter: (tooltipItem: any) => {
128 return tooltipItem.datasetIndex === 1;
131 label: (item: Record<string, any>, data: Record<string, any>) => {
132 let text = data.labels[item.index];
133 if (!text.includes('%')) {
134 text = `${text} (${data.datasets[item.datasetIndex].data[item.index]}%)`;
149 this.prepareRawUsage(this.chartConfig, this.data);
153 this.prepareRawUsage(this.chartConfig, this.data);
156 private prepareRawUsage(chart: Record<string, any>, data: Record<string, any>) {
157 const nearFullRatioPercent = this.lowThreshold * 100;
158 const fullRatioPercent = this.highThreshold * 100;
159 const percentAvailable = this.calcPercentage(data.max - data.current, data.max);
160 const percentUsed = this.calcPercentage(data.current, data.max);
161 if (percentUsed >= fullRatioPercent) {
162 this.color = 'chart-color-red';
163 } else if (percentUsed >= nearFullRatioPercent) {
164 this.color = 'chart-color-yellow';
166 this.color = 'chart-color-blue';
169 chart.dataset[0].data = [
170 Math.round(nearFullRatioPercent),
171 Math.round(Math.abs(nearFullRatioPercent - fullRatioPercent)),
172 Math.round(100 - fullRatioPercent)
175 chart.dataset[1].data = [
178 this.dimlessBinary.transform(data.current)
180 chart.dataset[1].backgroundColor[0] = this.cssHelper.propertyValue(this.color);
182 chart.dataset[0].label = [`${percentUsed}%\nof ${this.dimlessBinary.transform(data.max)}`];
185 private calcPercentage(dividend: number, divisor: number) {
186 if (!_.isNumber(dividend) || !_.isNumber(divisor) || divisor === 0) {
189 return Math.ceil((dividend / divisor) * 100 * 100) / 100;