From fd163bf46b0dc0686efaf37979400b72870027b5 Mon Sep 17 00:00:00 2001 From: Ruslan Rabadanov <ruslanrabadanov2101@gmail.com> Date: Fri, 7 Mar 2025 20:55:23 +0100 Subject: [PATCH] FE-6 Fix Y axis for protocol chart; move component logic to chart service --- .../dashboard-chart-frames.component.ts | 45 ++---- ...hboard-chart-information-rate.component.ts | 44 ++---- .../dashboard-chart-protocol.component.ts | 64 ++------- src/app/interceptor/mock-interceptor.ts | 4 +- src/app/service/.gitkeep | 0 src/app/service/chart.service.ts | 131 ++++++++++++++++++ 6 files changed, 158 insertions(+), 130 deletions(-) delete mode 100644 src/app/service/.gitkeep create mode 100644 src/app/service/chart.service.ts diff --git a/src/app/components/dashboard-chart-frames/dashboard-chart-frames.component.ts b/src/app/components/dashboard-chart-frames/dashboard-chart-frames.component.ts index b713d95..7c79268 100644 --- a/src/app/components/dashboard-chart-frames/dashboard-chart-frames.component.ts +++ b/src/app/components/dashboard-chart-frames/dashboard-chart-frames.component.ts @@ -15,6 +15,7 @@ import { MatFormField, MatLabel } from '@angular/material/form-field'; import { MatInput } from '@angular/material/input'; import { MatSlider, MatSliderThumb } from '@angular/material/slider'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { ChartService } from '../../service/chart.service'; @Component({ selector: 'app-dashboard-chart-frames', @@ -34,40 +35,20 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms'; }) export class DashboardChartFramesComponent { readonly #dashboardApi = inject(DashboardApi); - recordsLimit = input<number>(20); + readonly #chartService = inject(ChartService); + recordsLimit = input<number>(60); recordsInterval = signal<number>(1); framesHistory = signal<ChartFrames[]>([]); data = computed(() => { const frames = this.framesHistory(); if (!frames) return; - return { - labels: this.getFrameLabels().map(date => date.toLocaleTimeString()), - datasets: [ - { - label: 'Valid Frames', - data: frames.map(frame => frame.valid), - fill: true, - backgroundColor: 'rgb(76, 175, 80, 0.2)', - tension: 0.4, - borderColor: '#4CAF50', - }, - { - label: 'Invalid Frames', - data: frames.map(frame => frame.invalid), - fill: true, - tension: 0.4, - borderColor: '#f34d52', - backgroundColor: 'rgb(243, 77, 82, 0.2)', - }, - ], - }; + return this.#chartService.getFramesChartDataConfig( + frames, + this.recordsInterval() + ); }); - options = { - animation: { - duration: 0, - }, - }; + readonly options = this.#chartService.getDefaultChartOptions(); private stopFetching = new Subject(); @@ -93,14 +74,4 @@ export class DashboardChartFramesComponent { }); }); } - - private getFrameLabels(): Date[] { - const labelsNumber = this.framesHistory().length; - const now = new Date().getTime(); - return Array.from( - { length: labelsNumber }, - (_, index) => - new Date(now - (labelsNumber - index) * 1000 * this.recordsInterval()) - ); - } } diff --git a/src/app/components/dashboard-chart-information-rate/dashboard-chart-information-rate.component.ts b/src/app/components/dashboard-chart-information-rate/dashboard-chart-information-rate.component.ts index c60ee31..99d01f1 100644 --- a/src/app/components/dashboard-chart-information-rate/dashboard-chart-information-rate.component.ts +++ b/src/app/components/dashboard-chart-information-rate/dashboard-chart-information-rate.component.ts @@ -9,13 +9,13 @@ import { } from '@angular/core'; import { UIChart } from 'primeng/chart'; import { DashboardApi } from '../../api/dashboard.api'; -import { ChartFrames } from '../../models/chart-frames'; import { interval, shareReplay, Subject, switchMap, takeUntil } from 'rxjs'; import { ChartInformationRate } from '../../models/chart-information-rate'; import { MatFormField, MatLabel } from '@angular/material/form-field'; import { MatInput } from '@angular/material/input'; import { MatSlider, MatSliderThumb } from '@angular/material/slider'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { ChartService } from '../../service/chart.service'; @Component({ selector: 'app-dashboard-chart-information-rate', @@ -35,38 +35,20 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms'; }) export class DashboardChartInformationRateComponent { readonly #dashboardApi = inject(DashboardApi); - recordsLimit = input<number>(20); + readonly #chartService = inject(ChartService); + recordsLimit = input<number>(60); recordsInterval = signal<number>(1); irHistory = signal<ChartInformationRate[]>([]); data = computed(() => { const informationRates = this.irHistory(); if (!informationRates) return; - return { - labels: this.getFrameLabels().map(date => date.toLocaleTimeString()), - datasets: [ - { - label: 'Current IR', - data: informationRates.map(ir => ir.current), - fill: true, - backgroundColor: 'rgba(144,147,239,0.32)', - tension: 0.4, - borderColor: '#5b70f8', - }, - { - label: 'Average IR', - data: informationRates.map(ir => ir.average), - tension: 0.4, - borderColor: '#535353', - }, - ], - }; + return this.#chartService.getIRChartDataConfig( + informationRates, + this.recordsInterval() + ); }); - options = { - animation: { - duration: 0, - }, - }; + readonly options = this.#chartService.getDefaultChartOptions(); private stopFetching = new Subject(); @@ -93,14 +75,4 @@ export class DashboardChartInformationRateComponent { }); }); } - - private getFrameLabels(): Date[] { - const labelsNumber = this.irHistory().length; - const now = new Date().getTime(); - return Array.from( - { length: labelsNumber }, - (_, index) => - new Date(now - (labelsNumber - index) * 1000 * this.recordsInterval()) - ); - } } diff --git a/src/app/components/dashboard-chart-protocol/dashboard-chart-protocol.component.ts b/src/app/components/dashboard-chart-protocol/dashboard-chart-protocol.component.ts index 39c14d3..aae9f5d 100644 --- a/src/app/components/dashboard-chart-protocol/dashboard-chart-protocol.component.ts +++ b/src/app/components/dashboard-chart-protocol/dashboard-chart-protocol.component.ts @@ -13,9 +13,9 @@ import { MatInput } from '@angular/material/input'; import { MatSlider, MatSliderThumb } from '@angular/material/slider'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { DashboardApi } from '../../api/dashboard.api'; -import { ChartInformationRate } from '../../models/chart-information-rate'; -import { interval, shareReplay, Subject, switchMap, takeUntil } from 'rxjs'; import { ChartProtocol } from '../../models/chart-protocol'; +import { interval, shareReplay, Subject, switchMap, takeUntil } from 'rxjs'; +import { ChartService } from '../../service/chart.service'; @Component({ selector: 'app-dashboard-chart-protocol', @@ -35,57 +35,21 @@ import { ChartProtocol } from '../../models/chart-protocol'; }) export class DashboardChartProtocolComponent { readonly #dashboardApi = inject(DashboardApi); + readonly #chartService = inject(ChartService); protocolName = input.required<string>(); - recordsLimit = input<number>(20); + recordsLimit = input<number>(60); recordsInterval = signal<number>(1); protocolHistory = signal<ChartProtocol[]>([]); data = computed(() => { const protocols = this.protocolHistory(); if (!protocols) return; - console.log(protocols); - return { - labels: this.getFrameLabels().map(date => date.toLocaleTimeString()), - datasets: [ - { - label: 'Bytes', - data: protocols.map(protocol => protocol.bytes), - yAxisId: 'y', - tension: 0.4, - borderColor: '#4464e3', - }, - // @todo: fix Y1 axis - { - label: 'Packets', - data: protocols.map(protocol => protocol.packets), - yAxisId: 'y1', - tension: 0.4, - borderColor: '#61aa48', - }, - ], - }; + return this.#chartService.getProtocolChartDataConfig( + protocols, + this.recordsInterval() + ); }); - options = { - animation: { - duration: 0, - }, - stacked: false, - scales: { - y: { - type: 'linear', - display: true, - position: 'left', - }, - y1: { - type: 'linear', - display: true, - position: 'right', - grid: { - drawOnChartArea: false, - }, - }, - }, - }; + readonly options = this.#chartService.getMultipleYAxesChartOptions(); private stopFetching = new Subject(); @@ -114,14 +78,4 @@ export class DashboardChartProtocolComponent { }); }); } - - private getFrameLabels(): Date[] { - const labelsNumber = this.protocolHistory().length; - const now = new Date().getTime(); - return Array.from( - { length: labelsNumber }, - (_, index) => - new Date(now - (labelsNumber - index) * 1000 * this.recordsInterval()) - ); - } } diff --git a/src/app/interceptor/mock-interceptor.ts b/src/app/interceptor/mock-interceptor.ts index 3947067..0ce7c4c 100644 --- a/src/app/interceptor/mock-interceptor.ts +++ b/src/app/interceptor/mock-interceptor.ts @@ -7,7 +7,7 @@ import { ChartInformationRate } from '../models/chart-information-rate'; import { ChartProtocol } from '../models/chart-protocol'; export const MockInterceptor: HttpInterceptorFn = (req, next) => { - const { url, method } = req; + const { url } = req; for (const element of urls) { let body = (element.json() as any).default; @@ -52,7 +52,7 @@ function getRandomProtocolRecord(): { data: ChartProtocol } { return { data: { packets: packets, - bytes: packets * Math.floor(Math.random() * 512), + bytes: packets * Math.floor(Math.random() * Math.sqrt(packets) * 16), }, }; } diff --git a/src/app/service/.gitkeep b/src/app/service/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/app/service/chart.service.ts b/src/app/service/chart.service.ts new file mode 100644 index 0000000..861c9e0 --- /dev/null +++ b/src/app/service/chart.service.ts @@ -0,0 +1,131 @@ +import { Injectable } from '@angular/core'; +import { ChartInformationRate } from '../models/chart-information-rate'; +import { ChartFrames } from '../models/chart-frames'; +import { ChartProtocol } from '../models/chart-protocol'; + +@Injectable({ + providedIn: 'root', +}) +export class ChartService { + getChartLabels( + labelsNumber: number, + labelTimeInterval: number, + labelsStep: number = 5 + ): string[] { + const now = new Date().getTime(); + return Array.from({ length: labelsNumber }, (_, index) => { + if (index % labelsStep && index != 0 && index != labelsNumber - 1) { + return ''; + } + return new Date( + now - (labelsNumber - index) * 1000 * labelTimeInterval + ).toLocaleTimeString(); + }); + } + + getIRChartDataConfig( + informationRates: ChartInformationRate[], + recordsInterval: number + ) { + return { + labels: this.getChartLabels(informationRates.length, recordsInterval), + datasets: [ + { + label: 'Current IR', + data: informationRates.map(ir => ir.current), + fill: true, + backgroundColor: 'rgba(144,147,239,0.32)', + tension: 0.4, + borderColor: '#5b70f8', + }, + { + label: 'Average IR', + data: informationRates.map(ir => ir.average), + tension: 0.4, + borderColor: '#535353', + }, + ], + }; + } + + getFramesChartDataConfig(frames: ChartFrames[], recordsInterval: number) { + return { + labels: this.getChartLabels(frames.length, recordsInterval), + datasets: [ + { + label: 'Valid Frames', + data: frames.map(frame => frame.valid), + fill: true, + backgroundColor: 'rgb(76, 175, 80, 0.2)', + tension: 0.4, + borderColor: '#4CAF50', + }, + { + label: 'Invalid Frames', + data: frames.map(frame => frame.invalid), + fill: true, + tension: 0.4, + borderColor: '#f34d52', + backgroundColor: 'rgb(243, 77, 82, 0.2)', + }, + ], + }; + } + + getProtocolChartDataConfig( + protocols: ChartProtocol[], + recordsInterval: number + ) { + return { + labels: this.getChartLabels(protocols.length, recordsInterval), + datasets: [ + { + label: 'Bytes', + fill: false, + yAxisID: 'y', + tension: 0.4, + data: protocols.map(protocol => protocol.bytes), + }, + { + label: 'Packets', + fill: false, + yAxisID: 'y1', + tension: 0.4, + data: protocols.map(protocol => protocol.packets), + }, + ], + }; + } + + getDefaultChartOptions() { + return { + animation: { + duration: 0, + }, + }; + } + + getMultipleYAxesChartOptions() { + return { + animation: { + duration: 0, + }, + stacked: false, + scales: { + y: { + type: 'linear', + display: true, + position: 'left', + }, + y1: { + type: 'linear', + display: true, + position: 'right', + grid: { + drawOnChartArea: false, + }, + }, + }, + }; + } +} -- GitLab