1 import { Component, Input, OnChanges, OnInit } from '@angular/core';
3 import * as Chart from 'chart.js';
4 import _ from 'lodash';
5 import { PluginServiceGlobalRegistrationAndOptions } from 'ng2-charts';
7 import { CssHelper } from '~/app/shared/classes/css-helper';
8 import { DimlessBinaryPipe } from '~/app/shared/pipes/dimless-binary.pipe';
11 selector: 'cd-dashboard-pie',
12 templateUrl: './dashboard-pie.component.html',
13 styleUrls: ['./dashboard-pie.component.scss']
15 export class DashboardPieComponent implements OnChanges, OnInit {
19 highThreshold: number;
26 chartType: 'doughnut',
32 this.cssHelper.propertyValue('chart-color-light-gray'),
33 this.cssHelper.propertyValue('chart-color-slight-dark-gray'),
34 this.cssHelper.propertyValue('chart-color-dark-gray')
41 this.cssHelper.propertyValue('chart-color-blue'),
42 this.cssHelper.propertyValue('chart-color-white')
48 events: ['click', 'mouseout', 'touchstart'],
55 generateLabels: (chart: any) => {
56 const labels = { 0: {}, 1: {}, 2: {} };
58 text: $localize`Used: ${chart.data.datasets[1].data[2]}`,
59 fillStyle: chart.data.datasets[1].backgroundColor[0],
60 strokeStyle: chart.data.datasets[1].backgroundColor[0]
63 text: $localize`Warning: ${chart.data.datasets[0].data[0]}%`,
64 fillStyle: chart.data.datasets[0].backgroundColor[1],
65 strokeStyle: chart.data.datasets[0].backgroundColor[1]
68 text: $localize`Danger: ${
69 chart.data.datasets[0].data[0] + chart.data.datasets[0].data[1]
71 fillStyle: chart.data.datasets[0].backgroundColor[2],
72 strokeStyle: chart.data.datasets[0].backgroundColor[2]
85 backgroundColor: this.cssHelper.propertyValue('chart-color-tooltip-background'),
92 filter: (tooltipItem: any) => {
93 return tooltipItem.datasetIndex === 1;
96 label: (item: Record<string, any>, data: Record<string, any>) => {
97 let text = data.labels[item.index];
98 if (!text.includes('%')) {
99 text = `${text} (${data.datasets[item.datasetIndex].data[item.index]}%)`;
111 public doughnutChartPlugins: PluginServiceGlobalRegistrationAndOptions[] = [
114 beforeDraw(chart: Chart) {
115 const cssHelper = new CssHelper();
116 const defaultFontFamily = 'Helvetica Neue, Helvetica, Arial, sans-serif';
117 Chart.defaults.global.defaultFontFamily = defaultFontFamily;
118 const ctx = chart.ctx;
119 if (!chart.options.plugins.center_text || !chart.data.datasets[0].label) {
124 const label = chart.data.datasets[0].label[0].split('\n');
126 const centerX = (chart.chartArea.left + chart.chartArea.right) / 2;
127 const centerY = (chart.chartArea.top + chart.chartArea.bottom) / 2;
128 ctx.textAlign = 'center';
129 ctx.textBaseline = 'middle';
131 ctx.font = `24px ${defaultFontFamily}`;
132 ctx.fillText(label[0], centerX, centerY - 10);
134 if (label.length > 1) {
135 ctx.font = `14px ${defaultFontFamily}`;
136 ctx.fillStyle = cssHelper.propertyValue('chart-color-center-text-description');
137 ctx.fillText(label[1], centerX, centerY + 10);
144 constructor(private cssHelper: CssHelper, private dimlessBinary: DimlessBinaryPipe) {}
147 this.prepareRawUsage(this.chartConfig, this.data);
151 this.prepareRawUsage(this.chartConfig, this.data);
154 private prepareRawUsage(chart: Record<string, any>, data: Record<string, any>) {
155 const nearFullRatioPercent = this.lowThreshold * 100;
156 const fullRatioPercent = this.highThreshold * 100;
157 const percentAvailable = this.calcPercentage(data.max - data.current, data.max);
158 const percentUsed = this.calcPercentage(data.current, data.max);
159 if (percentUsed >= fullRatioPercent) {
160 this.color = 'chart-color-red';
161 } else if (percentUsed >= nearFullRatioPercent) {
162 this.color = 'chart-color-yellow';
164 this.color = 'chart-color-blue';
167 chart.dataset[0].data = [
168 Math.round(nearFullRatioPercent),
169 Math.round(Math.abs(nearFullRatioPercent - fullRatioPercent)),
170 Math.round(100 - fullRatioPercent)
173 chart.dataset[1].data = [
176 this.dimlessBinary.transform(data.current)
178 chart.dataset[1].backgroundColor[0] = this.cssHelper.propertyValue(this.color);
180 chart.dataset[0].label = [`${percentUsed}%\nof ${this.dimlessBinary.transform(data.max)}`];
183 private calcPercentage(dividend: number, divisor: number) {
184 if (!_.isNumber(dividend) || !_.isNumber(divisor) || divisor === 0) {
187 return Math.ceil((dividend / divisor) * 100 * 100) / 100;