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 truncateLabel = false;
35 currentDataUnits: string;
37 maxConvertedValue?: number;
38 maxConvertedValueUnits?: string;
40 chartDataUnits: string;
41 chartData: any = { dataset: [] };
43 currentChartData: any = {};
45 chartColors: any[] = [
47 this.cssHelper.propertyValue('chart-color-strong-blue'),
48 this.cssHelper.propertyValue('chart-color-translucent-blue')
51 this.cssHelper.propertyValue('chart-color-orange'),
52 this.cssHelper.propertyValue('chart-color-translucent-orange')
55 this.cssHelper.propertyValue('chart-color-green'),
56 this.cssHelper.propertyValue('chart-color-translucent-green')
59 this.cssHelper.propertyValue('chart-color-cyan'),
60 this.cssHelper.propertyValue('chart-color-translucent-cyan')
63 this.cssHelper.propertyValue('chart-color-purple'),
64 this.cssHelper.propertyValue('chart-color-translucent-purple')
67 this.cssHelper.propertyValue('chart-color-red'),
68 this.cssHelper.propertyValue('chart-color-translucent-red')
72 public chartAreaBorderPlugin: any[] = [
74 beforeDraw(chart: any) {
75 if (!chart.options.plugins.borderArea) {
80 chartArea: { left, top, width, height }
83 ctx.strokeStyle = chart.options.plugins.chartAreaBorder.borderColor;
84 ctx.lineWidth = chart.options.plugins.chartAreaBorder.borderWidth;
85 ctx.setLineDash(chart.options.plugins.chartAreaBorder.borderDash || []);
86 ctx.lineDashOffset = chart.options.plugins.chartAreaBorder.borderDashOffset;
87 ctx.strokeRect(left, top, width, height);
94 private cssHelper: CssHelper,
95 private dimlessBinary: DimlessBinaryPipe,
96 private dimlessBinaryPerSecond: DimlessBinaryPerSecondPipe,
97 private dimlessPipe: DimlessPipe,
98 private formatter: FormatterService,
99 private numberFormatter: NumberFormatterService
108 external: function (tooltipModel: any) {
109 tooltipModel.tooltip.x = 10;
110 tooltipModel.tooltip.y = 0;
114 backgroundColor: this.cssHelper.propertyValue('chart-color-tooltip-background'),
116 title: function (tooltipItem: any): any {
117 return tooltipItem[0].xLabel;
119 label: (context: any) => {
122 context.dataset.label +
124 context.formattedValue +
133 borderColor: this.cssHelper.propertyValue('chart-color-slight-dark-gray'),
138 maintainAspectRatio: false,
156 tooltipFormat: 'DD/MM/YYYY - HH:mm:ss'
160 afterFit: (scaleInstance: any) => (scaleInstance.width = 100),
173 ngOnChanges(changes: SimpleChanges): void {
174 this.updateChartData(changes);
178 this.updateChartData(null);
181 private updateChartData(changes: SimpleChanges): void {
182 for (let index = 0; index < this.labelsArray.length; index++) {
183 const colorIndex = index % this.chartColors.length;
184 this.chartData.dataset[index] = {
188 pointBackgroundColor: this.chartColors[colorIndex][0],
189 backgroundColor: this.chartColors[colorIndex][1],
190 borderColor: this.chartColors[colorIndex][0],
196 this.chartData.dataset[index].label = this.labelsArray[index];
199 this.setChartTicks();
201 if (this.dataArray && this.dataArray.length && this.dataArray[0] && this.dataArray[0].length) {
202 this.dataArray = changes?.dataArray?.currentValue || this.dataArray;
203 this.currentChartData = this.chartData;
204 for (let index = 0; index < this.dataArray.length; index++) {
205 this.chartData.dataset[index].data = this.formatData(this.dataArray[index]);
206 let currentDataValue = this.dataArray?.[index]?.[this.dataArray[index]?.length - 1]
207 ? this.dataArray[index][this.dataArray[index]?.length - 1][1]
209 if (currentDataValue) {
211 this.currentChartData.dataset[index]['currentData'],
212 this.currentChartData.dataset[index]['currentDataUnits']
213 ] = this.convertUnits(currentDataValue).split(' ');
214 [this.maxConvertedValue, this.maxConvertedValueUnits] = this.convertUnits(
222 this.chart.chart.update();
226 private formatData(array: Array<any>): any {
227 let formattedData = {};
228 formattedData = array?.map((data: any) => ({
230 y: Number(this.convertToChartDataUnits(data[1]).replace(/[^\d,.]+/g, ''))
232 return formattedData;
235 private convertToChartDataUnits(data: any): any {
236 let dataWithUnits: string = '';
237 if (this.chartDataUnits !== null) {
238 if (this.dataUnits === 'B') {
239 dataWithUnits = this.numberFormatter.formatBytesFromTo(
245 } else if (this.dataUnits === 'B/s') {
246 dataWithUnits = this.numberFormatter.formatBytesPerSecondFromTo(
252 } else if (this.dataUnits === 'ms') {
253 dataWithUnits = this.numberFormatter.formatSecondsFromTo(
260 dataWithUnits = this.numberFormatter.formatUnitlessFromTo(
268 return dataWithUnits;
271 private convertUnits(data: any): any {
272 let dataWithUnits: string = '';
273 if (this.dataUnits === 'B') {
274 dataWithUnits = this.dimlessBinary.transform(data, this.decimals);
275 } else if (this.dataUnits === 'B/s') {
276 dataWithUnits = this.dimlessBinaryPerSecond.transform(data, this.decimals);
277 } else if (this.dataUnits === 'ms') {
278 dataWithUnits = this.formatter.format_number(data, 1000, ['ms', 's'], this.decimals);
280 dataWithUnits = this.dimlessPipe.transform(data, this.decimals);
282 return dataWithUnits;
285 private setChartTicks() {
287 this.chartDataUnits = '';
292 let maxValueDataUnits = '';
294 const allDataValues = this.dataArray.reduce((array: string[], data) => {
295 return array.concat(data?.map((values: [number, string]) => values[1]));
298 maxValue = Math.max(...allDataValues.map(Number));
299 [maxValue, maxValueDataUnits] = this.convertUnits(maxValue).split(' ');
301 const yAxesTicks = this.chart.chart.options.scales.y;
302 yAxesTicks.ticks.callback = (value: any) => {
306 if (!maxValueDataUnits) {
309 return `${value} ${maxValueDataUnits}`;
311 this.chartDataUnits = maxValueDataUnits || '';
312 this.chart.chart.update();