]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/blob
3da4334210de03d56f9b97dc369fb3b395e1690d
[ceph-ci.git] /
1 import { AfterViewInit, Component, Input, OnChanges, OnInit, ViewChild } from '@angular/core';
2
3 import { CssHelper } from '~/app/shared/classes/css-helper';
4 import { DimlessBinaryPipe } from '~/app/shared/pipes/dimless-binary.pipe';
5 import { DimlessBinaryPerSecondPipe } from '~/app/shared/pipes/dimless-binary-per-second.pipe';
6 import { FormatterService } from '~/app/shared/services/formatter.service';
7 import { BaseChartDirective, PluginServiceGlobalRegistrationAndOptions } from 'ng2-charts';
8 import { DimlessPipe } from '~/app/shared/pipes/dimless.pipe';
9
10 @Component({
11   selector: 'cd-dashboard-area-chart',
12   templateUrl: './dashboard-area-chart.component.html',
13   styleUrls: ['./dashboard-area-chart.component.scss']
14 })
15 export class DashboardAreaChartComponent implements OnInit, OnChanges, AfterViewInit {
16   @ViewChild(BaseChartDirective) chart: BaseChartDirective;
17
18   @Input()
19   chartTitle: string;
20   @Input()
21   maxValue?: any;
22   @Input()
23   dataUnits: string;
24   @Input()
25   data: any;
26   @Input()
27   data2?: any;
28   @Input()
29   label: any;
30   @Input()
31   label2?: any;
32
33   currentDataUnits: string;
34   currentData: number;
35   currentDataUnits2?: string;
36   currentData2?: number;
37
38   chartData: any = {
39     dataset: [
40       {
41         label: '',
42         data: [{ x: 0, y: 0 }],
43         tension: 0,
44         pointBackgroundColor: this.cssHelper.propertyValue('chart-color-strong-blue'),
45         backgroundColor: this.cssHelper.propertyValue('chart-color-translucent-blue'),
46         borderColor: this.cssHelper.propertyValue('chart-color-strong-blue')
47       },
48       {
49         label: '',
50         data: [],
51         tension: 0,
52         pointBackgroundColor: this.cssHelper.propertyValue('chart-color-orange'),
53         backgroundColor: this.cssHelper.propertyValue('chart-color-yellow'),
54         borderColor: this.cssHelper.propertyValue('chart-color-orange')
55       }
56     ]
57   };
58
59   options: any = {
60     responsive: true,
61     maintainAspectRatio: false,
62     elements: {
63       point: {
64         radius: 0
65       }
66     },
67     legend: {
68       display: false
69     },
70     tooltips: {
71       intersect: false,
72       displayColors: true,
73       backgroundColor: this.cssHelper.propertyValue('chart-color-tooltip-background'),
74       callbacks: {
75         title: function (tooltipItem: any): any {
76           return tooltipItem[0].xLabel;
77         }
78       }
79     },
80     hover: {
81       intersect: false
82     },
83     scales: {
84       xAxes: [
85         {
86           display: false,
87           type: 'time',
88           gridLines: {
89             display: false
90           },
91           time: {
92             tooltipFormat: 'YYYY/MM/DD hh:mm:ss'
93           }
94         }
95       ],
96       yAxes: [
97         {
98           gridLines: {
99             display: false
100           },
101           ticks: {
102             beginAtZero: true,
103             maxTicksLimit: 3,
104             callback: (value: any) => {
105               if (value === 0) {
106                 return null;
107               }
108               return this.fillString(this.convertUnits(value));
109             }
110           }
111         }
112       ]
113     },
114     plugins: {
115       borderArea: true,
116       chartAreaBorder: {
117         borderColor: this.cssHelper.propertyValue('chart-color-slight-dark-gray'),
118         borderWidth: 2
119       }
120     }
121   };
122
123   public chartAreaBorderPlugin: PluginServiceGlobalRegistrationAndOptions[] = [
124     {
125       beforeDraw(chart: Chart) {
126         if (!chart.options.plugins.borderArea) {
127           return;
128         }
129         const {
130           ctx,
131           chartArea: { left, top, right, bottom }
132         } = chart;
133         ctx.save();
134         ctx.strokeStyle = chart.options.plugins.chartAreaBorder.borderColor;
135         ctx.lineWidth = chart.options.plugins.chartAreaBorder.borderWidth;
136         ctx.setLineDash(chart.options.plugins.chartAreaBorder.borderDash || []);
137         ctx.lineDashOffset = chart.options.plugins.chartAreaBorder.borderDashOffset;
138         ctx.strokeRect(left, top, right - left - 1, bottom);
139         ctx.restore();
140       }
141     }
142   ];
143
144   constructor(
145     private cssHelper: CssHelper,
146     private dimlessBinary: DimlessBinaryPipe,
147     private dimlessBinaryPerSecond: DimlessBinaryPerSecondPipe,
148     private dimlessPipe: DimlessPipe,
149     private formatter: FormatterService
150   ) {}
151
152   ngOnInit(): void {
153     this.currentData = Number(
154       this.chartData.dataset[0].data[this.chartData.dataset[0].data.length - 1].y
155     );
156     if (this.data2) {
157       this.currentData2 = Number(
158         this.chartData.dataset[1].data[this.chartData.dataset[1].data.length - 1].y
159       );
160     }
161   }
162
163   ngOnChanges(): void {
164     if (this.data) {
165       this.setChartTicks();
166       this.chartData.dataset[0].data = this.formatData(this.data);
167       this.chartData.dataset[0].label = this.label;
168       [this.currentData, this.currentDataUnits] = this.convertUnits(
169         this.data[this.data.length - 1][1]
170       ).split(' ');
171     }
172     if (this.data2) {
173       this.chartData.dataset[1].data = this.formatData(this.data2);
174       this.chartData.dataset[1].label = this.label2;
175       [this.currentData2, this.currentDataUnits2] = this.convertUnits(
176         this.data2[this.data2.length - 1][1]
177       ).split(' ');
178     }
179   }
180
181   ngAfterViewInit(): void {
182     if (this.data) {
183       this.setChartTicks();
184     }
185   }
186
187   private formatData(array: Array<any>): any {
188     let formattedData = {};
189     formattedData = array.map((data: any) => ({
190       x: data[0] * 1000,
191       y: Number(this.convertUnits(data[1]).replace(/[^\d,.]+/g, ''))
192     }));
193     return formattedData;
194   }
195
196   private convertUnits(data: any): any {
197     let dataWithUnits: string;
198     if (this.dataUnits === 'bytes') {
199       dataWithUnits = this.dimlessBinary.transform(data);
200     } else if (this.dataUnits === 'bytesPerSecond') {
201       dataWithUnits = this.dimlessBinaryPerSecond.transform(data);
202     } else if (this.dataUnits === 'ms') {
203       dataWithUnits = this.formatter.format_number(data, 1000, ['ms', 's']);
204     } else {
205       dataWithUnits = this.dimlessPipe.transform(data);
206     }
207     return dataWithUnits;
208   }
209
210   private fillString(str: string): string {
211     let maxNumberOfChar: number = 8;
212     let numberOfChars: number = str.length;
213     if (str.length < 4) {
214       maxNumberOfChar = 11;
215     }
216     for (; numberOfChars < maxNumberOfChar; numberOfChars++) {
217       str = '\u00A0' + str;
218     }
219     return str + '\u00A0\u00A0';
220   }
221
222   private setChartTicks() {
223     if (this.chart && this.maxValue) {
224       let [maxValue, maxValueDataUnits] = this.convertUnits(this.maxValue).split(' ');
225       this.chart.chart.options.scales.yAxes[0].ticks.suggestedMax = maxValue;
226       this.chart.chart.options.scales.yAxes[0].ticks.suggestedMin = 0;
227       this.chart.chart.options.scales.yAxes[0].ticks.stepSize = Number((maxValue / 2).toFixed(0));
228       this.chart.chart.options.scales.yAxes[0].ticks.callback = (value: any) => {
229         if (value === 0) {
230           return null;
231         }
232         return this.fillString(`${value} ${maxValueDataUnits}`);
233       };
234       this.chart.chart.update();
235     } else if (this.chart && this.data) {
236       let maxValue = 0,
237         maxValueDataUnits = '';
238       let maxValueData = Math.max(...this.data.map((values: any) => values[1]));
239       if (this.data2) {
240         var maxValueData2 = Math.max(...this.data2.map((values: any) => values[1]));
241         [maxValue, maxValueDataUnits] = this.convertUnits(
242           Math.max(maxValueData, maxValueData2)
243         ).split(' ');
244       } else {
245         [maxValue, maxValueDataUnits] = this.convertUnits(Math.max(maxValueData)).split(' ');
246       }
247
248       this.chart.chart.options.scales.yAxes[0].ticks.suggestedMax = maxValue * 1.2;
249       this.chart.chart.options.scales.yAxes[0].ticks.suggestedMin = 0;
250       this.chart.chart.options.scales.yAxes[0].ticks.stepSize = Number(
251         ((maxValue * 1.2) / 2).toFixed(0)
252       );
253       this.chart.chart.options.scales.yAxes[0].ticks.callback = (value: any) => {
254         if (value === 0) {
255           return null;
256         }
257         if (!maxValueDataUnits) {
258           return this.fillString(`${value}`);
259         }
260         return this.fillString(`${value} ${maxValueDataUnits}`);
261       };
262       this.chart.chart.update();
263     }
264   }
265 }