1 import { Component, Input, ViewChild, OnChanges, SimpleChanges } from '@angular/core';
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 } from 'ng2-charts';
8 import { DimlessPipe } from '~/app/shared/pipes/dimless.pipe';
9 import { NumberFormatterService } from '~/app/shared/services/number-formatter.service';
10 import 'chartjs-adapter-moment';
13 selector: 'cd-dashboard-area-chart',
14 templateUrl: './dashboard-area-chart.component.html',
15 styleUrls: ['./dashboard-area-chart.component.scss']
17 export class DashboardAreaChartComponent implements OnChanges {
18 @ViewChild(BaseChartDirective) chart: BaseChartDirective;
27 dataArray?: Array<Array<[number, string]>>; // Array of query results
29 labelsArray?: string[] = []; // Array of chart labels
31 decimals?: number = 1;
33 currentDataUnits: string;
35 maxConvertedValue?: number;
36 maxConvertedValueUnits?: string;
38 chartDataUnits: string;
39 chartData: any = { dataset: [] };
41 currentChartData: any = {};
43 chartColors: any[] = [
45 this.cssHelper.propertyValue('chart-color-strong-blue'),
46 this.cssHelper.propertyValue('chart-color-translucent-blue')
49 this.cssHelper.propertyValue('chart-color-orange'),
50 this.cssHelper.propertyValue('chart-color-translucent-orange')
53 this.cssHelper.propertyValue('chart-color-green'),
54 this.cssHelper.propertyValue('chart-color-translucent-green')
57 this.cssHelper.propertyValue('chart-color-cyan'),
58 this.cssHelper.propertyValue('chart-color-translucent-cyan')
61 this.cssHelper.propertyValue('chart-color-purple'),
62 this.cssHelper.propertyValue('chart-color-translucent-purple')
65 this.cssHelper.propertyValue('chart-color-red'),
66 this.cssHelper.propertyValue('chart-color-translucent-red')
70 public chartAreaBorderPlugin: any[] = [
72 beforeDraw(chart: any) {
73 if (!chart.options.plugins.borderArea) {
78 chartArea: { left, top, width, height }
81 ctx.strokeStyle = chart.options.plugins.chartAreaBorder.borderColor;
82 ctx.lineWidth = chart.options.plugins.chartAreaBorder.borderWidth;
83 ctx.setLineDash(chart.options.plugins.chartAreaBorder.borderDash || []);
84 ctx.lineDashOffset = chart.options.plugins.chartAreaBorder.borderDashOffset;
85 ctx.strokeRect(left, top, width, height);
92 private cssHelper: CssHelper,
93 private dimlessBinary: DimlessBinaryPipe,
94 private dimlessBinaryPerSecond: DimlessBinaryPerSecondPipe,
95 private dimlessPipe: DimlessPipe,
96 private formatter: FormatterService,
97 private numberFormatter: NumberFormatterService
106 external: function (tooltipModel: any) {
107 tooltipModel.tooltip.x = 10;
108 tooltipModel.tooltip.y = 0;
112 backgroundColor: this.cssHelper.propertyValue('chart-color-tooltip-background'),
114 title: function (tooltipItem: any): any {
115 return tooltipItem[0].xLabel;
117 label: (context: any) => {
120 context.dataset.label +
122 context.formattedValue +
131 borderColor: this.cssHelper.propertyValue('chart-color-slight-dark-gray'),
136 maintainAspectRatio: false,
154 tooltipFormat: 'DD/MM/YYYY - HH:mm:ss'
158 afterFit: (scaleInstance: any) => (scaleInstance.width = 100),
171 ngOnChanges(changes: SimpleChanges): void {
172 this.updateChartData(changes);
176 this.updateChartData(null);
179 private updateChartData(changes: SimpleChanges): void {
180 for (let index = 0; index < this.labelsArray.length; index++) {
181 const colorIndex = index % this.chartColors.length;
182 this.chartData.dataset[index] = {
186 pointBackgroundColor: this.chartColors[colorIndex][0],
187 backgroundColor: this.chartColors[colorIndex][1],
188 borderColor: this.chartColors[colorIndex][0],
194 this.chartData.dataset[index].label = this.labelsArray[index];
197 this.setChartTicks();
199 if (this.dataArray && this.dataArray.length && this.dataArray[0] && this.dataArray[0].length) {
200 this.dataArray = changes?.dataArray?.currentValue || this.dataArray;
201 this.currentChartData = this.chartData;
202 for (let index = 0; index < this.dataArray.length; index++) {
203 this.chartData.dataset[index].data = this.formatData(this.dataArray[index]);
204 let currentDataValue = this.dataArray[index][this.dataArray[index].length - 1]
205 ? this.dataArray[index][this.dataArray[index].length - 1][1]
207 if (currentDataValue) {
209 this.currentChartData.dataset[index]['currentData'],
210 this.currentChartData.dataset[index]['currentDataUnits']
211 ] = this.convertUnits(currentDataValue).split(' ');
212 [this.maxConvertedValue, this.maxConvertedValueUnits] = this.convertUnits(
220 this.chart.chart.update();
224 private formatData(array: Array<any>): any {
225 let formattedData = {};
226 formattedData = array?.map((data: any) => ({
228 y: Number(this.convertToChartDataUnits(data[1]).replace(/[^\d,.]+/g, ''))
230 return formattedData;
233 private convertToChartDataUnits(data: any): any {
234 let dataWithUnits: string = '';
235 if (this.chartDataUnits !== null) {
236 if (this.dataUnits === 'B') {
237 dataWithUnits = this.numberFormatter.formatBytesFromTo(
243 } else if (this.dataUnits === 'B/s') {
244 dataWithUnits = this.numberFormatter.formatBytesPerSecondFromTo(
250 } else if (this.dataUnits === 'ms') {
251 dataWithUnits = this.numberFormatter.formatSecondsFromTo(
258 dataWithUnits = this.numberFormatter.formatUnitlessFromTo(
266 return dataWithUnits;
269 private convertUnits(data: any): any {
270 let dataWithUnits: string = '';
271 if (this.dataUnits === 'B') {
272 dataWithUnits = this.dimlessBinary.transform(data, this.decimals);
273 } else if (this.dataUnits === 'B/s') {
274 dataWithUnits = this.dimlessBinaryPerSecond.transform(data, this.decimals);
275 } else if (this.dataUnits === 'ms') {
276 dataWithUnits = this.formatter.format_number(data, 1000, ['ms', 's'], this.decimals);
278 dataWithUnits = this.dimlessPipe.transform(data, this.decimals);
280 return dataWithUnits;
283 private setChartTicks() {
285 this.chartDataUnits = '';
290 let maxValueDataUnits = '';
292 const allDataValues = this.dataArray.reduce((array: string[], data) => {
293 return array.concat(data?.map((values: [number, string]) => values[1]));
296 maxValue = Math.max(...allDataValues.map(Number));
297 [maxValue, maxValueDataUnits] = this.convertUnits(maxValue).split(' ');
299 const yAxesTicks = this.chart.chart.options.scales.y;
300 yAxesTicks.ticks.callback = (value: any) => {
304 if (!maxValueDataUnits) {
307 return `${value} ${maxValueDataUnits}`;
309 this.chartDataUnits = maxValueDataUnits || '';
310 this.chart.chart.update();