import { Component, OnInit } from "@angular/core"; import { RouterLink, RouterModule } from "@angular/router"; import { formatDate } from "@angular/common"; import { TranslateModule, TranslateService } from "@ngx-translate/core"; import { MatTableDataSource, MatTableModule } from "@angular/material/table"; import { CommonModule } from "@angular/common"; import { MatIconModule } from "@angular/material/icon"; import { MatListModule } from "@angular/material/list"; import { MatProgressSpinnerModule } from "@angular/material/progress-spinner"; import { MatRadioModule } from "@angular/material/radio"; import { MatProgressBarModule } from "@angular/material/progress-bar"; import { FormsModule } from "@angular/forms"; import { MatButtonModule } from "@angular/material/button"; import { ChartConfiguration, ChartData, ChartType } from "chart.js"; import { from, groupBy, mergeMap, reduce, map } from "rxjs"; import { BaseChartDirective } from "ng2-charts"; import { ServiceComm } from "../../services/service-comm.service"; import { TunnelFlightService } from "../../services/tunnel-flight.service"; import { DateService } from "../../services/date.service"; import { TunnelFlight, TunnelFlightByMonth } from "../../models/tunnel-flight"; @Component({ selector: "app-list-of-tunnel-flights", templateUrl: "./list-of-tunnel-flights.component.html", styleUrls: ["./list-of-tunnel-flights.component.css"], imports: [ TranslateModule, BaseChartDirective, CommonModule, MatIconModule, MatListModule, MatProgressSpinnerModule, RouterLink, MatRadioModule, MatProgressBarModule, FormsModule, RouterModule, MatTableModule, MatButtonModule, ], }) export class ListOfTunnelFlightsComponent implements OnInit { public barChartLegend = true; public barChartData: ChartData<"bar">; public barChartOptions: ChartConfiguration["options"]; public barChartType: ChartType; public isLoading: boolean = false; public selectedPeriod: string; public dataSourceTable: MatTableDataSource = new MatTableDataSource(); public displayedColumns: Array = [ "id", "tunnel", "jumpType", "nbMinutes", "notes", "flightDate", "actions", ]; public stats: Array<{ id: String | Number; values: String | Number }> = []; constructor( private serviceComm: ServiceComm, private serviceTunnelFlight: TunnelFlightService, private translateService: TranslateService, private dateService: DateService, ) {} ngOnInit() { this.serviceComm.forceTranslateTitle.subscribe((data) => { if (data === true) { this.updateTitle(); } }); this.updateTitle(); this.chartConfig(); this.selectedPeriod = "currentYear"; this.getDataForGraph(); } public onPeriodChange() { this.getDataForGraph(); if (this.dataSourceTable?.data.length > 0) { this.getDataForTable(); } } public onLoadTable() { this.getDataForTable(); } private chartConfig() { this.barChartType = "bar"; this.barChartOptions = { responsive: true, maintainAspectRatio: true, plugins: { legend: { display: true, }, tooltip: { callbacks: { footer: this.footer, }, }, }, interaction: { intersect: false, mode: "nearest", axis: "x", }, scales: { x: { stacked: true, }, y: { stacked: true, }, }, }; } private updateTitle() { this.translateService .get("ListTunnelFlight_Title") .subscribe((data) => { this.serviceComm.updatedComponentTitle(data); }); } private getDataForTable(): void { this.isLoading = true; // Get data to show in a table let endDate = new Date(); endDate.setHours(0, 0, 0, 0); let beginDate = this.computeBeginDateByPeriod( this.selectedPeriod, endDate, ); this.serviceTunnelFlight .getTunnelFlights(beginDate, endDate) .subscribe((data) => { this.dataSourceTable.data = data; this.isLoading = false; }); } private getDataForGraph(): void { this.isLoading = true; // Get data to show in a table let endDate = new Date(); endDate.setHours(0, 0, 0, 0); let beginDate = this.computeBeginDateByPeriod( this.selectedPeriod, endDate, ); this.serviceTunnelFlight .getTunnelFlightsByMonth(beginDate, endDate) .subscribe((data) => { const allMonths = this.getMontsBetweenDates(beginDate, endDate); const cumulatedTime = this.getCumulatedTimeByTypeByMonth( data, allMonths, ); this.computeTimeByType(data); this.barChartData = { labels: allMonths, datasets: cumulatedTime, }; this.isLoading = false; }); } private computeTimeByType(stats: TunnelFlightByMonth[]) { this.stats = []; from(stats) .pipe( groupBy((type) => type.type, { element: (p) => p.nb }), mergeMap((group$) => group$.pipe( reduce((acc, cur) => [...acc, cur], [`${group$.key}`]), ), ), map((arr) => ({ id: arr[0], values: arr .slice(1) .reduce((a, b) => Number(a) + Number(b), 0), })), ) .subscribe((p) => { console.log(p); this.stats.push(p); }); } private getMontsBetweenDates( beginDate: Date, endDate: Date, ): Array { let results: Array = []; let tmpBeginDate = new Date(beginDate.getTime()); const tmpEndDate = new Date(endDate.getTime()); while (tmpBeginDate < tmpEndDate) { results.push(formatDate(tmpBeginDate, "yy-MM", "en")); tmpBeginDate.setMonth(tmpBeginDate.getMonth() + 1); } return results; } private getCumulatedTimeByTypeByMonth( stats: TunnelFlightByMonth[], allMonths: string[], ): Array { let tmpResults = new Map(); const disctintType = Array.from( new Set(stats.map((item) => item.type)), ); disctintType.forEach((type) => { tmpResults.set( type, Array.from({ length: allMonths.length }, (v, k) => 0), ); }); for (let i = 0; i < allMonths.length; i++) { const month = allMonths[i]; let filteredStats = stats.filter((d) => d.month == month); if (filteredStats.length > 0) { filteredStats.forEach((fs) => { tmpResults.get(fs.type)[i] += fs.nb; }); } } const results = Array.from(tmpResults, function (item) { return { label: item[0], data: item[1] }; }); return results; } private footer = (tooltipItems: any) => { let sum = 0; tooltipItems.forEach(function (tooltipItem: any) { sum += tooltipItem.parsed.y; }); return "Sum: " + sum; }; private computeBeginDateByPeriod( selectedPeriod: String, endDate: Date, ): Date { let beginDate = new Date(); switch (selectedPeriod) { case "currentYear": beginDate = new Date(endDate.getFullYear(), 0, 1); break; case "12Months": beginDate = this.dateService.addMonths(endDate, -12); beginDate.setDate(1); break; case "all": beginDate = this.dateService.addMonths(endDate, -120); beginDate.setDate(1); break; } return beginDate; } public delete(item: TunnelFlight) { let data: Array = this.dataSourceTable.data; data = data.filter((d) => d.id !== item.id); this.dataSourceTable.data = data; this.serviceTunnelFlight.deleteTunnelFlight(item); } }