---|qcm| Mise à jour V17 et QCM

This commit is contained in:
Rampeur
2024-05-04 02:08:04 +02:00
parent fa93c0c8f2
commit 6dece821a8
241 changed files with 27526 additions and 6520 deletions
@@ -1,46 +1,42 @@
<mat-card>
<mat-card-header>
<mat-card-title>{{ title }}</mat-card-title>
<mat-card-subtitle>{{ subtitle }}</mat-card-subtitle>
<span class="flex-spacer"></span>
<button mat-icon-button [matMenuTriggerFor]="menuAeronefBar" aria-label="Menu Aeronef Bar">
<mat-icon fontIcon="more_vert"></mat-icon>
</button>
<mat-menu #menuAeronefBar="matMenu">
<button mat-menu-item *ngFor="let menuitem of menuItems.getMenuPanel()">
<mat-icon [fontIcon]="menuitem.icon"></mat-icon>
<span>{{ menuitem.name }}</span>
</button>
</mat-menu>
</mat-card-header>
<hr>
<mat-card-content>
<div *ngIf="displayCharts" class="barchart position-relative w-100 my-1">
<canvas baseChart
[data]="chartConfig.barChartData"
[options]="chartConfig.barChartOptions"
[plugins]="chartConfig.barChartPlugins"
[legend]="chartConfig.barChartLegend"
[type]="'bar'">
</canvas>
</div>
</mat-card-content>
<hr class="mb-0">
<mat-accordion>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>Historique annuel</mat-panel-title>
</mat-expansion-panel-header>
<huapp-history-table [headers]="seriesHeader" [names]="seriesName" [values]="seriesValue" [rows]="seriesRow" [colors]="seriesColor"></huapp-history-table>
<!--
<div fxLayout="row wrap">
<div *ngFor='let name of seriesName; let i=index' fxFlex.gt-lg="33" fxFlex.gt-md="50" fxFlex.gt-xs="20" fxFlex="100">
<h6 class="{{seriesColor[i]}} m-0">
<i class="mdi mdi-checkbox-blank-circle font-10 m-r-10 "></i>{{name}} - {{seriesValue[i]}}
</h6>
</div>
</div>
-->
</mat-expansion-panel>
</mat-accordion>
</mat-card>
<mat-card>
<mat-card-header>
<mat-card-title>{{ title }}</mat-card-title>
<mat-card-subtitle>{{ subtitle }}</mat-card-subtitle>
<span class="flex-spacer"></span>
<button mat-icon-button [matMenuTriggerFor]="menuAeronefBar" aria-label="Menu Aeronef Bar">
<mat-icon fontIcon="more_vert"></mat-icon>
</button>
<mat-menu #menuAeronefBar="matMenu">
@for (menuitem of menuItems.getMenuPanel(); track menuitem) {
<button mat-menu-item>
<mat-icon [fontIcon]="menuitem.icon"></mat-icon>
<span>{{ menuitem.name }}</span>
</button>
}
</mat-menu>
</mat-card-header>
<mat-divider class="my-3"></mat-divider>
<mat-card-content>
@if (displayCharts) {
<app-bar-horizontal-chart [headers]="seriesHeader" [names]="seriesName" [values]="seriesValue" [colors]="seriesColor" label="Nombre total de sauts" [legend]="false"></app-bar-horizontal-chart>
}
</mat-card-content>
<mat-divider class="mt-3 mb-0"></mat-divider>
<mat-accordion>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>Historique annuel</mat-panel-title>
</mat-expansion-panel-header>
<app-history-table [headers]="seriesHeader" [names]="seriesName" [values]="seriesValue" [rows]="seriesRow" [colors]="seriesColorClass"></app-history-table>
<!--
<div fxLayout="row wrap">
<div *ngFor='let name of seriesName; let i=index' fxFlex.gt-lg="33" fxFlex.gt-md="50" fxFlex.gt-xs="20" fxFlex="100">
<h6 class="{{seriesColor[i]}} m-0">
<i class="mdi mdi-checkbox-blank-circle font-10 m-r-10 "></i>{{name}} - {{seriesValue[i]}}
</h6>
</div>
</div>
-->
</mat-expansion-panel>
</mat-accordion>
</mat-card>
@@ -7,9 +7,9 @@ describe('AeronefsBarComponent', () => {
let fixture: ComponentFixture<AeronefsBarComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ AeronefsBarComponent ]
})
TestBed.configureTestingModule({
imports: [AeronefsBarComponent]
})
.compileComponents();
}));
@@ -1,27 +1,27 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatDividerModule } from '@angular/material/divider';
import { MatExpansionModule } from '@angular/material/expansion';
import { MatIconModule } from '@angular/material/icon';
import { MatMenuModule } from '@angular/material/menu';
import { ChartDataset } from 'chart.js';
import { NgChartsModule } from 'ng2-charts';
import { Observable, Subscription } from 'rxjs';
import { MenuItems, HistoryTableComponent } from 'src/app/components/shared';
import { MenuItems } from 'src/app/components/shared';
import { BarHorizontalChartComponent } from 'src/app/components/shared/helpers-chart';
import { HistoryTableComponent } from 'src/app/components/shared/helpers-jump';
import { UtilitiesService, AeronefsService } from 'src/app/core/services';
import { AeronefByImat, AeronefByYear, BarConfig } from 'src/app/core/models';
import { AeronefByImat, AeronefByYear } from 'src/app/core/models';
@Component({
selector: 'app-aeronefs-bar',
standalone: true,
imports: [
CommonModule,
MatButtonModule, MatCardModule, MatExpansionModule, MatIconModule, MatMenuModule,
NgChartsModule,
HistoryTableComponent
MatButtonModule, MatCardModule, MatDividerModule,
MatExpansionModule, MatIconModule, MatMenuModule,
BarHorizontalChartComponent, HistoryTableComponent
],
selector: 'huapp-aeronefs-bar',
templateUrl: './aeronefs-bar.component.html'
})
export class AeronefsBarComponent implements OnInit, OnDestroy {
@@ -33,11 +33,18 @@ export class AeronefsBarComponent implements OnInit, OnDestroy {
public subtitle: string = 'Nombre total de sauts par aéronef';
public seriesHeader: string[] = [];
public seriesName: string[] = [];
public seriesValue: any[] = [];
public seriesRow: any[] = [];
public seriesColor: string[] = this._utilitiesService.getChartColors();
public seriesValue: number[] = [];
public seriesRow: Array<Array<number>> = [];
public seriesColor: {
backgroundColor: string[],
borderColor: string[]
} = {
backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'),
borderColor: this._utilitiesService.getSeriesColors(1, 'all')
};
public seriesColorClass: string[] = this._utilitiesService.getChartColors();
public displayCharts = false;
public chartConfig: BarConfig = this._utilitiesService.getHorizontalBarChartConfig();
public destroyRef = inject(DestroyRef);
constructor(
private _aeronefsService: AeronefsService,
@@ -55,44 +62,34 @@ export class AeronefsBarComponent implements OnInit, OnDestroy {
}
private _loadAeronefByImat(): void {
let values: Array<number> = [];
const aeronefs$: Observable<Array<AeronefByImat>> = this._aeronefsService.getAllByImat();
const aeronefs$: Observable<Array<AeronefByImat>> = this._aeronefsService.getAllByImat().pipe(takeUntilDestroyed(this.destroyRef));
this._aeronefByImat = aeronefs$.subscribe((aggregate: Array<AeronefByImat>) => {
this._aeronefsByImat = aggregate.map((row: AeronefByImat) => {
//this.chartConfig.barChartData.labels!.push(`${row._id.aeronef} ${row._id.imat}`);
this.seriesName.push(`${row._id.aeronef} ${row._id.imat}`);
//this.chartConfig.barChartData.labels!.push(`${row.aeronef} ${row.imat}`);
this.seriesName.push(`${row.aeronef} ${row.imat}`);
this.seriesValue.push(row.count);
return row;
});
let data: ChartDataset<'bar'> = {
data: [...this.seriesValue],
label: 'Nombre total de sauts',
backgroundColor: this._utilitiesService.getSeriesColors(0.9),
borderColor: 'rgba(255, 255, 255, 1)', //this._utilitiesService.getSeriesColors(1),
borderWidth: 0
};
this.chartConfig.barChartData.labels = [...this.seriesName];
this.chartConfig.barChartData.datasets!.push(data);
this.displayCharts = true;
this._loadAeronefByYear();
});
}
private _loadAeronefByYear(): void {
this.seriesHeader = ["2018", "2019", "2020", "2021", "2022", "2023"];
let values: Array<number> = this.seriesHeader.map(() => 0);
this.seriesHeader = ['2018', '2019', '2020', '2021', '2022', '2023', '2024'];
const values: Array<number> = this.seriesHeader.map(() => 0);
this.seriesName.forEach(() => {
this.seriesRow.push([...values]);
});
const dropzones$: Observable<Array<AeronefByYear>> = this._aeronefsService.getAllByDate();
const dropzones$: Observable<Array<AeronefByYear>> = this._aeronefsService.getAllByImatByYear().pipe(takeUntilDestroyed(this.destroyRef));
this._aeronefByYear = dropzones$.subscribe((aggregate: Array<AeronefByYear>) => {
this._aeronefsByYear = aggregate.map((row: AeronefByYear) => {
let aeronef: string = row._id.aeronef;
let imat: string = row._id.imat;
let year: string = row._id.year.toString();
const aeronef: string = row.aeronef;
const imat: string = row.imat;
const year: string = row.year.toString();
this.seriesRow[this.seriesName.indexOf(`${aeronef} ${imat}`)][this.seriesHeader.indexOf(year)] = row.count;
return row;
});
this.displayCharts = true;
});
}
}
@@ -1,47 +1,42 @@
<mat-card>
<mat-card-header>
<mat-card-title>{{ title }}</mat-card-title>
<mat-card-subtitle>{{ subtitle }}</mat-card-subtitle>
<span class="flex-spacer"></span>
<button mat-icon-button [matMenuTriggerFor]="menuAeronef" aria-label="Menu Aeronef">
<mat-icon fontIcon="more_vert"></mat-icon>
</button>
<mat-menu #menuAeronef="matMenu">
<button mat-menu-item *ngFor="let menuitem of menuItems.getMenuPanel()">
<mat-icon [fontIcon]="menuitem.icon"></mat-icon>
<span>{{ menuitem.name }}</span>
</button>
</mat-menu>
</mat-card-header>
<hr>
<mat-card-content>
<div *ngIf="displayCharts" class="piechart position-relative w-100 my-1">
<canvas baseChart class="mx-auto"
[labels]="chartConfig.doughnutChartLabels"
[datasets]="chartConfig.doughnutChartDatasets"
[options]="chartConfig.doughnutChartOptions"
[legend]="chartConfig.doughnutChartLegend"
[type]="'doughnut'">
</canvas>
</div>
</mat-card-content>
<hr class="mb-0">
<mat-accordion>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>Historique annuel</mat-panel-title>
</mat-expansion-panel-header>
<huapp-history-table [headers]="seriesHeader" [names]="seriesName" [values]="seriesValue" [rows]="seriesRow" [colors]="seriesColor"></huapp-history-table>
</mat-expansion-panel>
</mat-accordion>
<!--<hr>
<mat-card-content>
<div fxLayout="row wrap">
<div *ngFor='let name of seriesName; let i=index' fxFlex.gt-lg="33" fxFlex.gt-md="50" fxFlex.gt-xs="20" fxFlex="100">
<h6 class="{{seriesColor[i]}} m-0">
<i class="mdi mdi-checkbox-blank-circle font-10 m-r-10 "></i>{{name}} - {{seriesValue[i]}}
</h6>
</div>
</div>
</mat-card-content>-->
</mat-card>
<mat-card>
<mat-card-header>
<mat-card-title>{{ title }}</mat-card-title>
<mat-card-subtitle>{{ subtitle }}</mat-card-subtitle>
<span class="flex-spacer"></span>
<button mat-icon-button [matMenuTriggerFor]="menuAeronef" aria-label="Menu Aeronef">
<mat-icon fontIcon="more_vert"></mat-icon>
</button>
<mat-menu #menuAeronef="matMenu">
@for (menuitem of menuItems.getMenuPanel(); track menuitem) {
<button mat-menu-item>
<mat-icon [fontIcon]="menuitem.icon"></mat-icon>
<span>{{ menuitem.name }}</span>
</button>
}
</mat-menu>
</mat-card-header>
<mat-divider class="my-3"></mat-divider>
<mat-card-content>
<app-pie-chart [headers]="seriesHeader" [names]="seriesName" [values]="seriesValue" [colors]="seriesColor"></app-pie-chart>
</mat-card-content>
<mat-divider class="mt-3 mb-0"></mat-divider>
<mat-accordion>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>Historique annuel</mat-panel-title>
</mat-expansion-panel-header>
<app-history-table [headers]="seriesHeader" [names]="seriesName" [values]="seriesValue" [rows]="seriesRow" [colors]="seriesColorClass"></app-history-table>
</mat-expansion-panel>
</mat-accordion>
<!--
<mat-divider class="my-3"></mat-divider>
<mat-card-content>
<div fxLayout="row wrap">
<div *ngFor='let name of seriesName; let i=index' fxFlex.gt-lg="33" fxFlex.gt-md="50" fxFlex.gt-xs="20" fxFlex="100">
<h6 class="{{seriesColor[i]}} m-0">
<i class="mdi mdi-checkbox-blank-circle font-10 m-r-10 "></i>{{name}} - {{seriesValue[i]}}
</h6>
</div>
</div>
</mat-card-content>-->
</mat-card>
@@ -7,9 +7,9 @@ describe('AeronefsComponent', () => {
let fixture: ComponentFixture<AeronefsComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ AeronefsComponent ]
})
TestBed.configureTestingModule({
imports: [AeronefsComponent]
})
.compileComponents();
}));
@@ -1,28 +1,28 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Router, RouterLink, RouterModule } from '@angular/router';
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
import { MatBadgeModule } from '@angular/material/badge';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatDividerModule } from '@angular/material/divider';
import { MatExpansionModule } from '@angular/material/expansion';
import { MatIconModule } from '@angular/material/icon';
import { MatMenuModule } from '@angular/material/menu';
import { NgChartsModule } from 'ng2-charts';
import { Observable, Subscription } from 'rxjs';
import { MenuItems, HistoryTableComponent } from 'src/app/components/shared';
import { MenuItems } from 'src/app/components/shared';
import { HistoryTableComponent } from 'src/app/components/shared/helpers-jump';
import { PieChartComponent } from 'src/app/components/shared/helpers-chart';
import { UtilitiesService, AeronefsService } from 'src/app/core/services';
import { AeronefByImat, AeronefByYear, DoughnutConfig } from 'src/app/core/models';
import { AeronefByImat, AeronefByYear } from 'src/app/core/models';
@Component({
selector: 'app-aeronefs',
standalone: true,
imports: [
CommonModule, RouterModule,
MatBadgeModule, MatButtonModule, MatCardModule, MatExpansionModule, MatIconModule, MatMenuModule,
NgChartsModule,
HistoryTableComponent
MatBadgeModule, MatButtonModule, MatCardModule, MatDividerModule,
MatExpansionModule, MatIconModule, MatMenuModule,
HistoryTableComponent, PieChartComponent
],
selector: 'huapp-aeronefs',
templateUrl: './aeronefs.component.html'
})
export class AeronefsComponent implements OnInit, OnDestroy {
@@ -35,13 +35,18 @@ export class AeronefsComponent implements OnInit, OnDestroy {
public seriesHeader: string[] = [];
public seriesName: string[] = [];
public seriesValue: number[] = [];
public seriesRow: any[] = [];
public seriesColor: string[] = this._utilitiesService.getChartColors();
public displayCharts = false;
public chartConfig: DoughnutConfig = this._utilitiesService.getDoughnutChartConfig();
public seriesRow: Array<Array<number>> = [];
public seriesColor: {
backgroundColor: string[],
borderColor: string[]
} = {
backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'),
borderColor: this._utilitiesService.getSeriesColors(1, 'all')
};
public seriesColorClass: string[] = this._utilitiesService.getChartColors();
public destroyRef = inject(DestroyRef);
constructor(
private router: Router,
private _aeronefsService: AeronefsService,
private _utilitiesService: UtilitiesService,
public menuItems: MenuItems
@@ -57,32 +62,29 @@ export class AeronefsComponent implements OnInit, OnDestroy {
}
private _loadAeronefByImat(): void {
const aeronefs$: Observable<Array<AeronefByImat>> = this._aeronefsService.getAllByImat();
const aeronefs$: Observable<Array<AeronefByImat>> = this._aeronefsService.getAllByImat().pipe(takeUntilDestroyed(this.destroyRef));
this._aeronefByImat = aeronefs$.subscribe((aggregate: Array<AeronefByImat>) => {
this._aeronefsByImat = aggregate.map((row: AeronefByImat) => {
this.chartConfig.doughnutChartLabels.push(`${row._id.aeronef} ${row._id.imat}`);
this.chartConfig.doughnutChartDatasets[0].data.push(row.count);
this.seriesName.push(`${row.aeronef} ${row.imat}`);
this.seriesValue.push(row.count);
return row;
});
this.seriesName = [...this.chartConfig.doughnutChartLabels];
this.seriesValue = [...this.chartConfig.doughnutChartDatasets[0].data];
this.displayCharts = true;
this._loadAeronefByYear();
});
}
private _loadAeronefByYear(): void {
this.seriesHeader = ["2018", "2019", "2020", "2021", "2022", "2023"];
let values: Array<number> = this.seriesHeader.map(() => 0);
this.seriesHeader = ['2018', '2019', '2020', '2021', '2022', '2023', '2024'];
const values: Array<number> = this.seriesHeader.map(() => 0);
this.seriesName.forEach(() => {
this.seriesRow.push([...values]);
});
const dropzones$: Observable<Array<AeronefByYear>> = this._aeronefsService.getAllByDate();
const dropzones$: Observable<Array<AeronefByYear>> = this._aeronefsService.getAllByImatByYear().pipe(takeUntilDestroyed(this.destroyRef));
this._aeronefByYear = dropzones$.subscribe((aggregate: Array<AeronefByYear>) => {
this._aeronefsByYear = aggregate.map((row: AeronefByYear) => {
let aeronef: string = row._id.aeronef;
let imat: string = row._id.imat;
let year: string = row._id.year.toString();
const aeronef: string = row.aeronef;
const imat: string = row.imat;
const year: string = row.year.toString();
this.seriesRow[this.seriesName.indexOf(`${aeronef} ${imat}`)][this.seriesHeader.indexOf(year)] = row.count;
return row;
});
@@ -1,37 +1,31 @@
<mat-card>
<mat-card-header>
<mat-card-title>{{ title }}</mat-card-title>
<mat-card-subtitle>{{ subtitle }}</mat-card-subtitle>
<span class="flex-spacer"></span>
<button mat-icon-button [matMenuTriggerFor]="menuCanopyModel" aria-label="Menu Canopy Model">
<mat-icon fontIcon="more_vert"></mat-icon>
</button>
<mat-menu #menuCanopyModel="matMenu">
<button mat-menu-item *ngFor="let menuitem of menuItems.getMenuPanel()">
<mat-icon [fontIcon]="menuitem.icon"></mat-icon>
<span>{{ menuitem.name }}</span>
</button>
</mat-menu>
</mat-card-header>
<hr>
<mat-card-content>
<div *ngIf="displayCharts" class="piechart position-relative w-100 my-1">
<canvas baseChart class="mx-auto"
[labels]="chartConfig.doughnutChartLabels"
[datasets]="chartConfig.doughnutChartDatasets"
[options]="chartConfig.doughnutChartOptions"
[legend]="chartConfig.doughnutChartLegend"
[type]="'doughnut'">
</canvas>
</div>
</mat-card-content>
<hr class="mb-0">
<mat-accordion>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>Historique annuel</mat-panel-title>
</mat-expansion-panel-header>
<huapp-history-table [headers]="seriesHeader" [names]="seriesName" [values]="seriesValue" [rows]="seriesRow" [colors]="seriesColor"></huapp-history-table>
</mat-expansion-panel>
</mat-accordion>
</mat-card>
<mat-card>
<mat-card-header>
<mat-card-title>{{ title }}</mat-card-title>
<mat-card-subtitle>{{ subtitle }}</mat-card-subtitle>
<span class="flex-spacer"></span>
<button mat-icon-button [matMenuTriggerFor]="menuCanopyModel" aria-label="Menu Canopy Model">
<mat-icon fontIcon="more_vert"></mat-icon>
</button>
<mat-menu #menuCanopyModel="matMenu">
@for (menuitem of menuItems.getMenuPanel(); track menuitem) {
<button mat-menu-item>
<mat-icon [fontIcon]="menuitem.icon"></mat-icon>
<span>{{ menuitem.name }}</span>
</button>
}
</mat-menu>
</mat-card-header>
<mat-divider class="my-3"></mat-divider>
<mat-card-content>
<app-pie-chart [headers]="seriesHeader" [names]="seriesName" [values]="seriesValue" [colors]="seriesColor"></app-pie-chart>
</mat-card-content>
<mat-divider class="mt-3 mb-0"></mat-divider>
<mat-accordion>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>Historique annuel</mat-panel-title>
</mat-expansion-panel-header>
<app-history-table [headers]="seriesHeader" [names]="seriesName" [values]="seriesValue" [rows]="seriesRow" [colors]="seriesColorClass"></app-history-table>
</mat-expansion-panel>
</mat-accordion>
</mat-card>
@@ -7,9 +7,9 @@ describe('CanopyModelsComponent', () => {
let fixture: ComponentFixture<CanopyModelsComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ CanopyModelsComponent ]
})
TestBed.configureTestingModule({
imports: [CanopyModelsComponent]
})
.compileComponents();
}));
@@ -1,27 +1,27 @@
import { Component, OnInit, OnDestroy} from '@angular/core';
import { CommonModule } from '@angular/common';
import { Component, DestroyRef, inject, OnInit, OnDestroy} from '@angular/core';
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatDividerModule } from '@angular/material/divider';
import { MatExpansionModule } from '@angular/material/expansion';
import { MatIconModule } from '@angular/material/icon';
import { MatMenuModule } from '@angular/material/menu';
import { NgChartsModule } from 'ng2-charts';
import { Observable, Subscription } from 'rxjs';
import { MenuItems, HistoryTableComponent } from 'src/app/components/shared';
import { MenuItems } from 'src/app/components/shared';
import { PieChartComponent } from 'src/app/components/shared/helpers-chart';
import { HistoryTableComponent } from 'src/app/components/shared/helpers-jump';
import { UtilitiesService, CanopiesService } from 'src/app/core/services';
import { CanopyModelBySize, CanopyModelByYear, DoughnutConfig } from 'src/app/core/models';
import { CanopyModelBySize, CanopyModelByYear } from 'src/app/core/models';
@Component({
selector: 'app-canopy-models',
standalone: true,
imports: [
CommonModule,
MatButtonModule, MatCardModule, MatExpansionModule, MatIconModule, MatMenuModule,
NgChartsModule,
HistoryTableComponent
MatButtonModule, MatCardModule, MatDividerModule,
MatExpansionModule, MatIconModule, MatMenuModule,
PieChartComponent, HistoryTableComponent
],
selector: 'huapp-canopy-models',
templateUrl: './canopy-models.component.html'
})
export class CanopyModelsComponent implements OnInit, OnDestroy {
@@ -34,10 +34,16 @@ export class CanopyModelsComponent implements OnInit, OnDestroy {
public seriesHeader: string[] = [];
public seriesName: string[] = [];
public seriesValue: number[] = [];
public seriesRow: any[] = [];
public seriesColor: string[] = this._utilitiesService.getChartColors();
public displayCharts = false;
public chartConfig: DoughnutConfig = this._utilitiesService.getDoughnutChartConfig();
public seriesRow: Array<Array<number>> = [];
public seriesColor: {
backgroundColor: string[],
borderColor: string[]
} = {
backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'),
borderColor: this._utilitiesService.getSeriesColors(1, 'all')
};
public seriesColorClass: string[] = this._utilitiesService.getChartColors();
public destroyRef = inject(DestroyRef);
constructor(
private _canopiesService: CanopiesService,
@@ -55,32 +61,29 @@ export class CanopyModelsComponent implements OnInit, OnDestroy {
}
private _loadCanopyModelBySize(): void {
const canopies$: Observable<Array<CanopyModelBySize>> = this._canopiesService.getAllModelBySize();
const canopies$: Observable<Array<CanopyModelBySize>> = this._canopiesService.getAllBySizeByModel().pipe(takeUntilDestroyed(this.destroyRef));
this._canopyBySize = canopies$.subscribe((aggregate: Array<CanopyModelBySize>) => {
this._canopiesBySize = aggregate.map((row: CanopyModelBySize) => {
this.chartConfig.doughnutChartLabels.push(`${row._id.taille.toString()} - ${row._id.voile}`);
this.chartConfig.doughnutChartDatasets[0].data.push(row.count);
this.seriesName.push(`${row.taille.toString()} - ${row.voile}`);
this.seriesValue.push(row.count);
return row;
});
this.seriesName = [...this.chartConfig.doughnutChartLabels];
this.seriesValue = [...this.chartConfig.doughnutChartDatasets[0].data];
this.displayCharts = true;
this._loadCanopyModelByYear();
});
}
private _loadCanopyModelByYear(): void {
this.seriesHeader = ["2018", "2019", "2020", "2021", "2022", "2023"];
let values: Array<number> = this.seriesHeader.map(() => 0);
this.seriesHeader = ['2018', '2019', '2020', '2021', '2022', '2023', '2024'];
const values: Array<number> = this.seriesHeader.map(() => 0);
this.seriesName.forEach(() => {
this.seriesRow.push([...values]);
});
const dropzones$: Observable<Array<CanopyModelByYear>> = this._canopiesService.getAllModelByYear();
const dropzones$: Observable<Array<CanopyModelByYear>> = this._canopiesService.getAllBySizeByModelByYear().pipe(takeUntilDestroyed(this.destroyRef));
this._canopyByYear = dropzones$.subscribe((aggregate: Array<CanopyModelByYear>) => {
this._canopiesByYear = aggregate.map((row: CanopyModelByYear) => {
let voile: string = row._id.voile;
let taille: string = row._id.taille.toString();
let year: string = row._id.year.toString();
const voile: string = row.voile;
const taille: string = row.taille.toString();
const year: string = row.year.toString();
this.seriesRow[this.seriesName.indexOf(`${taille} - ${voile}`)][this.seriesHeader.indexOf(year)] = row.count;
return row;
});
@@ -1,44 +1,42 @@
<mat-card>
<mat-card-header>
<mat-card-title>{{ title }}</mat-card-title>
<mat-card-subtitle>{{ subtitle }}</mat-card-subtitle>
<span class="flex-spacer"></span>
<button mat-icon-button [matMenuTriggerFor]="menuCanopySize" aria-label="Menu Canopy Size">
<mat-icon fontIcon="more_vert"></mat-icon>
</button>
<mat-menu #menuCanopySize="matMenu">
<button mat-menu-item *ngFor="let menuitem of menuItems.getMenuPanel()">
<mat-icon [fontIcon]="menuitem.icon"></mat-icon>
<span>{{ menuitem.name }}</span>
</button>
</mat-menu>
</mat-card-header>
<hr>
<mat-card-content>
<div *ngIf="displayCharts" class="piechart position-relative w-100 my-1">
<canvas baseChart class="mx-auto"
[labels]="chartConfig.doughnutChartLabels"
[datasets]="chartConfig.doughnutChartDatasets"
[options]="chartConfig.doughnutChartOptions"
[legend]="chartConfig.doughnutChartLegend"
[type]="'doughnut'">
</canvas>
</div>
</mat-card-content>
<hr class="mb-0">
<mat-accordion>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>Historique annuel</mat-panel-title>
</mat-expansion-panel-header>
<huapp-history-table [headers]="seriesHeader" [names]="seriesName" [values]="seriesValue" [rows]="seriesRow" [colors]="seriesColor"></huapp-history-table>
<!--<div fxLayout="row wrap">
<div fxLayout="row wrap">
<h4 class="{{seriesColor[i]}} m-0" *ngFor='let name of seriesName; let i=index' fxFlex.gt-lg="25" fxFlex.gt-md="50" fxFlex.gt-sm="50" fxFlex.gt-xs="25" fxFlex="100">
<i class="mdi mdi-checkbox-blank-circle font-10 m-r-10 "></i>{{name}} ft² : {{seriesValue[i]}}
</h4>
</div>
</div>-->
</mat-expansion-panel>
</mat-accordion>
</mat-card>
<mat-card>
<mat-card-header>
<mat-card-title>{{ title }}</mat-card-title>
<mat-card-subtitle>{{ subtitle }}</mat-card-subtitle>
<span class="flex-spacer"></span>
<button mat-icon-button [matMenuTriggerFor]="menuCanopySize" aria-label="Menu Canopy Size">
<mat-icon fontIcon="more_vert"></mat-icon>
</button>
<mat-menu #menuCanopySize="matMenu">
@for (menuitem of menuItems.getMenuPanel(); track menuitem) {
<button mat-menu-item>
<mat-icon [fontIcon]="menuitem.icon"></mat-icon>
<span>{{ menuitem.name }}</span>
</button>
}
</mat-menu>
</mat-card-header>
<mat-divider class="my-3"></mat-divider>
<mat-card-content>
<app-pie-chart [headers]="seriesHeader" [names]="seriesName" [values]="seriesValue" [colors]="seriesColor">
</app-pie-chart>
</mat-card-content>
<mat-divider class="mt-3 mb-0"></mat-divider>
<mat-accordion>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>Historique annuel</mat-panel-title>
</mat-expansion-panel-header>
<app-history-table [headers]="seriesHeader" [names]="seriesName" [values]="seriesValue" [rows]="seriesRow"
[colors]="seriesColorClass"></app-history-table>
<!--
<div fxLayout="row wrap">
<div fxLayout="row wrap">
<h4 class="{{seriesColor[i]}} m-0" *ngFor='let name of seriesName; let i=index' fxFlex.gt-lg="25" fxFlex.gt-md="50" fxFlex.gt-sm="50" fxFlex.gt-xs="25" fxFlex="100">
<i class="mdi mdi-checkbox-blank-circle font-10 m-r-10 "></i>{{name}} ft² : {{seriesValue[i]}}
</h4>
</div>
</div>
-->
</mat-expansion-panel>
</mat-accordion>
</mat-card>
@@ -7,9 +7,9 @@ describe('CanopySizesComponent', () => {
let fixture: ComponentFixture<CanopySizesComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ CanopySizesComponent ]
})
TestBed.configureTestingModule({
imports: [CanopySizesComponent]
})
.compileComponents();
}));
@@ -1,27 +1,28 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatDividerModule } from '@angular/material/divider';
import { MatExpansionModule } from '@angular/material/expansion';
import { MatIconModule } from '@angular/material/icon';
import { MatMenuModule } from '@angular/material/menu';
import { NgChartsModule } from 'ng2-charts';
import { Observable, Subscription } from 'rxjs';
import { MenuItems, HistoryTableComponent } from 'src/app/components/shared';
import { MenuItems } from 'src/app/components/shared';
import { PieChartComponent } from 'src/app/components/shared/helpers-chart';
import { HistoryTableComponent } from 'src/app/components/shared/helpers-jump';
import { UtilitiesService, CanopiesService } from 'src/app/core/services';
import { CanopyBySize, CanopyByYear, DoughnutConfig } from 'src/app/core/models';
import { CanopyBySize, CanopyByYear } from 'src/app/core/models';
@Component({
selector: 'app-canopy-sizes',
standalone: true,
imports: [
CommonModule,
MatButtonModule, MatCardModule, MatExpansionModule, MatIconModule, MatMenuModule,
NgChartsModule,
HistoryTableComponent
MatButtonModule, MatCardModule, MatDividerModule,
MatExpansionModule, MatIconModule, MatMenuModule,
PieChartComponent, HistoryTableComponent
],
selector: 'huapp-canopy-sizes',
templateUrl: './canopy-sizes.component.html'
})
export class CanopySizesComponent implements OnInit, OnDestroy {
@@ -34,10 +35,16 @@ export class CanopySizesComponent implements OnInit, OnDestroy {
public seriesHeader: string[] = [];
public seriesName: string[] = [];
public seriesValue: number[] = [];
public seriesRow: any[] = [];
public seriesColor: string[] = this._utilitiesService.getChartColors();
public displayCharts = false;
public chartConfig: DoughnutConfig = this._utilitiesService.getDoughnutChartConfig();
public seriesRow: Array<Array<number>> = [];
public seriesColor: {
backgroundColor: string[],
borderColor: string[]
} = {
backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'),
borderColor: this._utilitiesService.getSeriesColors(1, 'all')
};
public seriesColorClass: string[] = this._utilitiesService.getChartColors();
public destroyRef = inject(DestroyRef);
constructor(
private _canopiesService: CanopiesService,
@@ -55,31 +62,28 @@ export class CanopySizesComponent implements OnInit, OnDestroy {
}
private _loadCanopyBySize(): void {
const canopies$: Observable<Array<CanopyBySize>> = this._canopiesService.getAllBySize();
const canopies$: Observable<Array<CanopyBySize>> = this._canopiesService.getAllBySize().pipe(takeUntilDestroyed(this.destroyRef));
this._canopyBySize = canopies$.subscribe((aggregate: Array<CanopyBySize>) => {
this._canopiesBySize = aggregate.map((row: CanopyBySize) => {
this.chartConfig.doughnutChartLabels.push(row._id.taille.toString());
this.chartConfig.doughnutChartDatasets[0].data.push(row.count);
this.seriesName.push(row.taille.toString());
this.seriesValue.push(row.count);
return row;
});
this.seriesName = [...this.chartConfig.doughnutChartLabels];
this.seriesValue = [...this.chartConfig.doughnutChartDatasets[0].data];
this.displayCharts = true;
this._loadCanopyByYear();
});
}
private _loadCanopyByYear(): void {
this.seriesHeader = ["2018", "2019", "2020", "2021", "2022", "2023"];
let values: Array<number> = this.seriesHeader.map(() => 0);
this.seriesHeader = ['2018', '2019', '2020', '2021', '2022', '2023', '2024'];
const values: Array<number> = this.seriesHeader.map(() => 0);
this.seriesName.forEach(() => {
this.seriesRow.push([...values]);
});
const dropzones$: Observable<Array<CanopyByYear>> = this._canopiesService.getAllByYear();
const dropzones$: Observable<Array<CanopyByYear>> = this._canopiesService.getAllBySizeByYear().pipe(takeUntilDestroyed(this.destroyRef));
this._canopyByYear = dropzones$.subscribe((aggregate: Array<CanopyByYear>) => {
this._canopiesByYear = aggregate.map((row: CanopyByYear) => {
let taille: string = row._id.taille.toString();
let year: string = row._id.year.toString();
const taille: string = row.taille.toString();
const year: string = row.year.toString();
this.seriesRow[this.seriesName.indexOf(taille)][this.seriesHeader.indexOf(year)] = row.count;
return row;
});
@@ -1,31 +1,35 @@
<mat-card>
<mat-card-header>
<mat-card-title>{{ title }}</mat-card-title>
<mat-card-subtitle>{{ subtitle }}</mat-card-subtitle>
<span class="flex-spacer"></span>
<button mat-icon-button [matMenuTriggerFor]="menuDropzoneBar" aria-label="Menu Dropzone Bar">
<mat-icon fontIcon="more_vert"></mat-icon>
</button>
<mat-menu #menuDropzoneBar="matMenu">
<button mat-menu-item *ngFor="let menuitem of menuItems.getMenuPanel()">
<mat-icon [fontIcon]="menuitem.icon"></mat-icon>
<span>{{ menuitem.name }}</span>
</button>
</mat-menu>
</mat-card-header>
<hr>
<mat-card-content>
<div *ngIf="displayCharts" class="barchart position-relative w-100 my-1">
<x-chartist [configuration]="barChartDropZones"></x-chartist>
</div>
</mat-card-content>
<hr class="mb-0">
<mat-accordion>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>Historique annuel</mat-panel-title>
</mat-expansion-panel-header>
<huapp-history-table [headers]="seriesHeader" [names]="seriesName" [values]="seriesValue" [rows]="seriesRow" [colors]="seriesColor"></huapp-history-table>
</mat-expansion-panel>
</mat-accordion>
</mat-card>
<mat-card>
<mat-card-header>
<mat-card-title>{{ title }}</mat-card-title>
<mat-card-subtitle>{{ subtitle }}</mat-card-subtitle>
<span class="flex-spacer"></span>
<button mat-icon-button [matMenuTriggerFor]="menuDropzoneBar" aria-label="Menu Dropzone Bar">
<mat-icon fontIcon="more_vert"></mat-icon>
</button>
<mat-menu #menuDropzoneBar="matMenu">
@for (menuitem of menuItems.getMenuPanel(); track menuitem) {
<button mat-menu-item>
<mat-icon [fontIcon]="menuitem.icon"></mat-icon>
<span>{{ menuitem.name }}</span>
</button>
}
</mat-menu>
</mat-card-header>
<mat-divider class="my-3"></mat-divider>
<mat-card-content>
@if (displayCharts) {
<div class="barchart position-relative w-100 my-1">
<x-chartist [configuration]="barChartDropZones"></x-chartist>
</div>
}
</mat-card-content>
<mat-divider class="mt-3 mb-0"></mat-divider>
<mat-accordion>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>Historique annuel</mat-panel-title>
</mat-expansion-panel-header>
<app-history-table [headers]="seriesHeader" [names]="seriesName" [values]="seriesValue" [rows]="seriesRow" [colors]="seriesColorClass"></app-history-table>
</mat-expansion-panel>
</mat-accordion>
</mat-card>
@@ -7,9 +7,9 @@ describe('DropZonesBarComponent', () => {
let fixture: ComponentFixture<DropZonesBarComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ DropZonesBarComponent ]
})
TestBed.configureTestingModule({
imports: [DropZonesBarComponent]
})
.compileComponents();
}));
@@ -1,28 +1,30 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatDividerModule } from '@angular/material/divider';
import { MatExpansionModule } from '@angular/material/expansion';
import { MatIconModule } from '@angular/material/icon';
import { MatMenuModule } from '@angular/material/menu';
import { NgChartsModule, baseColors } from 'ng2-charts';
import { BaseChartDirective } from 'ng2-charts';
import { ChartistModule, Configuration } from 'ng-chartist';
import { AxisOptions, Label } from 'chartist';
import { Observable, Subscription } from 'rxjs';
import { MenuItems, HistoryTableComponent } from 'src/app/components/shared';
import { MenuItems } from 'src/app/components/shared';
import { HistoryTableComponent } from 'src/app/components/shared/helpers-jump';
import { UtilitiesService, DropZonesService } from 'src/app/core/services';
import { DropZoneByOaci, DropZoneByYear } from 'src/app/core/models';
@Component({
selector: 'app-drop-zones-bar',
standalone: true,
imports: [
CommonModule,
MatButtonModule, MatCardModule, MatExpansionModule, MatIconModule, MatMenuModule,
NgChartsModule, ChartistModule,
MatButtonModule, MatCardModule, MatDividerModule,
MatExpansionModule, MatIconModule, MatMenuModule,
BaseChartDirective, ChartistModule,
HistoryTableComponent
],
selector: 'huapp-drop-zones-bar',
templateUrl: './drop-zones-bar.component.html'
})
export class DropZonesBarComponent implements OnInit, OnDestroy {
@@ -35,10 +37,18 @@ export class DropZonesBarComponent implements OnInit, OnDestroy {
public seriesHeader: string[] = [];
public seriesName: string[] = [];
public seriesValue: number[] = [];
public seriesRow: any[] = [];
public seriesColor: string[] = this._utilitiesService.getChartColors();
public seriesRow: Array<Array<number>> = [];
public seriesColor: {
backgroundColor: string[],
borderColor: string[]
} = {
backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'),
borderColor: this._utilitiesService.getSeriesColors(1, 'all')
};
public seriesColorClass: string[] = this._utilitiesService.getChartColors();
public displayCharts = false;
public barChartDropZones: Configuration = this._utilitiesService.getBarConfig();
public destroyRef = inject(DestroyRef);
constructor(
private _dropzonesService: DropZonesService,
@@ -56,10 +66,10 @@ export class DropZonesBarComponent implements OnInit, OnDestroy {
}
private _loadDropZoneByOaci(): void {
const dropzones$: Observable<Array<DropZoneByOaci>> = this._dropzonesService.getAllByOaci();
const dropzones$: Observable<Array<DropZoneByOaci>> = this._dropzonesService.getAllByOaci().pipe(takeUntilDestroyed(this.destroyRef));
this._dropzoneByOaci = dropzones$.subscribe((aggregate: Array<DropZoneByOaci>) => {
this._dropzonesByOaci = aggregate.map((row: DropZoneByOaci) => {
this.seriesName.push(`${row._id.oaci} - ${row._id.lieu}`);
this.seriesName.push(`${row.oaci} - ${row.lieu}`);
this.seriesValue.push(row.count);
return row;
});
@@ -68,25 +78,30 @@ export class DropZonesBarComponent implements OnInit, OnDestroy {
}
private _loadDropZoneByYear(): void {
this.seriesHeader = ["2018", "2019", "2020", "2021", "2022", "2023"];
let values: Array<number> = this.seriesHeader.map(() => 0);
this.seriesHeader = ['2018', '2019', '2020', '2021', '2022', '2023', '2024'];
const values: Array<number> = this.seriesHeader.map(() => 0);
this.seriesName.forEach(() => {
this.seriesRow.push([...values]);
});
const dropzones$: Observable<Array<DropZoneByYear>> = this._dropzonesService.getAllByDate();
const dropzones$: Observable<Array<DropZoneByYear>> = this._dropzonesService.getAllByOaciByYear().pipe(takeUntilDestroyed(this.destroyRef));
this._dropzoneByYear = dropzones$.subscribe((aggregate: Array<DropZoneByYear>) => {
this._dropzonesByYear = aggregate.map((row: DropZoneByYear) => {
let lieu: string = row._id.lieu;
let oaci: string = row._id.oaci;
let year: string = row._id.year.toString();
const lieu: string = row.lieu;
const oaci: string = row.oaci;
const year: string = row.year.toString();
this.seriesRow[this.seriesName.indexOf(`${oaci} - ${lieu}`)][this.seriesHeader.indexOf(year)] = row.count;
return row;
});
const axisX: AxisOptions = {
labelInterpolationFnc: function(value: Label, index: number): string {
return index % 1 === 0 ? `${value.toString()}` : '';
}
}
this.barChartDropZones = {
type: 'Bar',
data: {
"labels": this.seriesHeader,
"series": this.seriesRow
'labels': this.seriesHeader,
'series': this.seriesRow
},
options: {
seriesBarDistance: 15,
@@ -104,33 +119,21 @@ export class DropZonesBarComponent implements OnInit, OnDestroy {
},
responsiveOptions: [
['screen and (min-width: 1024px)', {
axisX: {
labelInterpolationFnc: function(value: number, index: number): string {
return index % 1 === 0 ? `${value}` : '';
}
}
axisX: axisX
}],
['screen and (min-width: 641px) and (max-width: 1024px)', {
seriesBarDistance: 7,
axisY: {
offset: 30
},
axisX: {
labelInterpolationFnc: function(value: any, index: number): string {
return index % 1 === 0 ? `${value[2]}${value[3]}` : '';
}
}
axisX: axisX
}],
['screen and (max-width: 640px)', {
seriesBarDistance: 5,
axisY: {
offset: 20
},
axisX: {
labelInterpolationFnc: function(value: any, index: number): string {
return index % 1 === 0 ? `${value[2]}${value[3]}` : '';
}
}
axisX: axisX
}]
]
};
@@ -1,37 +1,31 @@
<mat-card>
<mat-card-header>
<mat-card-title>{{ title }}</mat-card-title>
<mat-card-subtitle>{{ subtitle }}</mat-card-subtitle>
<span class="flex-spacer"></span>
<button mat-icon-button [matMenuTriggerFor]="menuDropzone" aria-label="Menu Dropzone">
<mat-icon fontIcon="more_vert"></mat-icon>
</button>
<mat-menu #menuDropzone="matMenu">
<button mat-menu-item *ngFor="let menuitem of menuItems.getMenuPanel()">
<mat-icon [fontIcon]="menuitem.icon"></mat-icon>
<span>{{ menuitem.name }}</span>
</button>
</mat-menu>
</mat-card-header>
<hr>
<mat-card-content>
<div *ngIf="displayCharts" class="piechart position-relative w-100 my-1">
<canvas baseChart class="mx-auto"
[labels]="chartConfig.doughnutChartLabels"
[datasets]="chartConfig.doughnutChartDatasets"
[options]="chartConfig.doughnutChartOptions"
[legend]="chartConfig.doughnutChartLegend"
[type]="'doughnut'">
</canvas>
</div>
</mat-card-content>
<hr class="mb-0">
<mat-accordion>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>Historique annuel</mat-panel-title>
</mat-expansion-panel-header>
<huapp-history-table [headers]="seriesHeader" [names]="seriesName" [values]="seriesValue" [rows]="seriesRow" [colors]="seriesColor"></huapp-history-table>
</mat-expansion-panel>
</mat-accordion>
</mat-card>
<mat-card>
<mat-card-header>
<mat-card-title>{{ title }}</mat-card-title>
<mat-card-subtitle>{{ subtitle }}</mat-card-subtitle>
<span class="flex-spacer"></span>
<button mat-icon-button [matMenuTriggerFor]="menuDropzone" aria-label="Menu Dropzone">
<mat-icon fontIcon="more_vert"></mat-icon>
</button>
<mat-menu #menuDropzone="matMenu">
@for (menuitem of menuItems.getMenuPanel(); track menuitem) {
<button mat-menu-item>
<mat-icon [fontIcon]="menuitem.icon"></mat-icon>
<span>{{ menuitem.name }}</span>
</button>
}
</mat-menu>
</mat-card-header>
<mat-divider class="my-3"></mat-divider>
<mat-card-content>
<app-pie-chart [headers]="seriesHeader" [names]="seriesName" [values]="seriesValue" [colors]="seriesColor"></app-pie-chart>
</mat-card-content>
<mat-divider class="mt-3 mb-0"></mat-divider>
<mat-accordion>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>Historique annuel</mat-panel-title>
</mat-expansion-panel-header>
<app-history-table [headers]="seriesHeader" [names]="seriesName" [values]="seriesValue" [rows]="seriesRow" [colors]="seriesColorClass"></app-history-table>
</mat-expansion-panel>
</mat-accordion>
</mat-card>
@@ -7,9 +7,9 @@ describe('DropZonesComponent', () => {
let fixture: ComponentFixture<DropZonesComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ DropZonesComponent ]
})
TestBed.configureTestingModule({
imports: [DropZonesComponent]
})
.compileComponents();
}));
@@ -1,28 +1,28 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatDividerModule } from '@angular/material/divider';
import { MatExpansionModule } from '@angular/material/expansion';
import { MatIconModule } from '@angular/material/icon';
import { MatMenuModule } from '@angular/material/menu';
import { ChartConfiguration } from 'chart.js';
import { NgChartsModule } from 'ng2-charts';
//import { ChartConfiguration } from 'chart.js';
import { Observable, Subscription } from 'rxjs';
import { MenuItems, HistoryTableComponent } from 'src/app/components/shared';
import { MenuItems } from 'src/app/components/shared';
import { PieChartComponent } from 'src/app/components/shared/helpers-chart';
import { HistoryTableComponent } from 'src/app/components/shared/helpers-jump';
import { UtilitiesService, DropZonesService } from 'src/app/core/services';
import { DropZoneByOaci, DropZoneByYear, DoughnutConfig } from 'src/app/core/models';
import { DropZoneByOaci, DropZoneByYear } from 'src/app/core/models';
@Component({
selector: 'app-drop-zones',
standalone: true,
imports: [
CommonModule,
MatButtonModule, MatCardModule, MatExpansionModule, MatIconModule, MatMenuModule,
NgChartsModule,
HistoryTableComponent
MatButtonModule, MatCardModule, MatDividerModule,
MatExpansionModule, MatIconModule, MatMenuModule,
PieChartComponent, HistoryTableComponent
],
selector: 'huapp-drop-zones',
templateUrl: './drop-zones.component.html'
})
export class DropZonesComponent implements OnInit, OnDestroy {
@@ -35,10 +35,16 @@ export class DropZonesComponent implements OnInit, OnDestroy {
public seriesHeader: string[] = [];
public seriesName: string[] = [];
public seriesValue: number[] = [];
public seriesRow: any[] = [];
public seriesColor: string[] = this._utilitiesService.getChartColors();
public displayCharts = false;
public chartConfig: DoughnutConfig = this._utilitiesService.getDoughnutChartConfig();
public seriesRow: Array<Array<number>> = [];
public seriesColor: {
backgroundColor: string[],
borderColor: string[]
} = {
backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'),
borderColor: this._utilitiesService.getSeriesColors(1, 'all')
};
public seriesColorClass: string[] = this._utilitiesService.getChartColors();
public destroyRef = inject(DestroyRef);
constructor(
private _dropzonesService: DropZonesService,
@@ -56,32 +62,29 @@ export class DropZonesComponent implements OnInit, OnDestroy {
}
private _loadDropZoneByOaci(): void {
const dropzones$: Observable<Array<DropZoneByOaci>> = this._dropzonesService.getAllByOaci();
const dropzones$: Observable<Array<DropZoneByOaci>> = this._dropzonesService.getAllByOaci().pipe(takeUntilDestroyed(this.destroyRef));
this._dropzoneByOaci = dropzones$.subscribe((aggregate: Array<DropZoneByOaci>) => {
this._dropzonesByOaci = aggregate.map((row: DropZoneByOaci) => {
this.chartConfig.doughnutChartLabels.push(`${row._id.oaci} - ${row._id.lieu}`);
this.chartConfig.doughnutChartDatasets[0].data.push(row.count);
this.seriesName.push(`${row.oaci} - ${row.lieu}`);
this.seriesValue.push(row.count);
return row;
});
this.seriesName = [...this.chartConfig.doughnutChartLabels];
this.seriesValue = [...this.chartConfig.doughnutChartDatasets[0].data];
this.displayCharts = true;
this._loadDropZoneByYear();
});
}
private _loadDropZoneByYear(): void {
this.seriesHeader = ["2018", "2019", "2020", "2021", "2022", "2023"];
let values: Array<number> = this.seriesHeader.map(() => 0);
this.seriesHeader = ['2018', '2019', '2020', '2021', '2022', '2023', '2024'];
const values: Array<number> = this.seriesHeader.map(() => 0);
this.seriesName.forEach(() => {
this.seriesRow.push([...values]);
});
const dropzones$: Observable<Array<DropZoneByYear>> = this._dropzonesService.getAllByDate();
const dropzones$: Observable<Array<DropZoneByYear>> = this._dropzonesService.getAllByOaciByYear().pipe(takeUntilDestroyed(this.destroyRef));
this._dropzoneByYear = dropzones$.subscribe((aggregate: Array<DropZoneByYear>) => {
this._dropzonesByYear = aggregate.map((row: DropZoneByYear) => {
let lieu: string = row._id.lieu;
let oaci: string = row._id.oaci;
let year: string = row._id.year.toString();
const lieu: string = row.lieu;
const oaci: string = row.oaci;
const year: string = row.year.toString();
this.seriesRow[this.seriesName.indexOf(`${oaci} - ${lieu}`)][this.seriesHeader.indexOf(year)] = row.count;
return row;
});
@@ -13,7 +13,7 @@
</button>
</mat-menu>
</mat-card-header>
<hr>
<mat-divider class="my-3"></mat-divider>
<mat-card-content>
<!--
<div class="text-center mb-3">
@@ -30,7 +30,7 @@
<x-chartist [configuration]="barChartJumps"></x-chartist>
</div>
</mat-card-content>
<hr class="mb-0">
<mat-divider class="mt-3 mb-0"></mat-divider>
<mat-accordion>
<mat-expansion-panel>
<mat-expansion-panel-header>
@@ -46,12 +46,12 @@
</thead>
<tbody>
<tr *ngFor='let values of seriesRow; let i=index'>
<th class="{{seriesColor[i]}} text-end"> ● {{ seriesName[i] }} </th>
<th class="{{seriesColorClass[i]}} text-end"> ● {{ seriesName[i] }} </th>
<td *ngFor='let value of values; let i=index' class="font-monospace text-end">
<span *ngIf="value; else elseBlock" class="pr-1">{{ value }}</span>
<ng-template #elseBlock><span class="text-empty pr-1">{{ value }}</span></ng-template>
</td>
<th class="font-monospace text-end">{{ seriesRowTotal[i] }}</th>
<th class="{{seriesColorClass[i]}} font-monospace text-end">{{ seriesRowTotal[i] }}</th>
</tr>
</tbody>
<tfoot>
@@ -66,10 +66,18 @@
<tr>
<th class="text-end">Moyenne</th>
<th *ngFor='let value of seriesRowAvg; let i=index' class="font-monospace text-end">
<span *ngIf="value; else elseBlock" class="pr-1">{{ value }}</span>
<ng-template #elseBlock><span class="text-empty pr-1">{{ value }}</span></ng-template>
<span *ngIf="value; else elseBlock" class="pr-1">{{ value | number : '1.0-1' }}</span>
<ng-template #elseBlock><span class="text-empty pr-1">{{ value | number : '1.0-1' }}</span></ng-template>
</th>
<th class="font-monospace text-end">{{ grandAvg }}</th>
<th class="font-monospace text-end">{{ grandAvg | number : '1.0-1' }}</th>
</tr>
<tr>
<th class="text-end">Moyenne <small>3 dernières années</small></th>
<th *ngFor='let value of seriesRowAvgLastYears; let i=index' class="font-monospace text-end">
<span *ngIf="value; else elseBlock" class="pr-1">{{ value | number : '1.0-1' }}</span>
<ng-template #elseBlock><span class="text-empty pr-1">{{ value | number : '1.0-1' }}</span></ng-template>
</th>
<th class="font-monospace text-end">{{ grandAvgLastYears | number : '1.0-1' }}</th>
</tr>
</tfoot>
</table>
@@ -7,9 +7,9 @@ describe('JumpsByMonthComponent', () => {
let fixture: ComponentFixture<JumpsByMonthComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ JumpsByMonthComponent ]
})
TestBed.configureTestingModule({
imports: [JumpsByMonthComponent]
})
.compileComponents();
}));
@@ -1,11 +1,14 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
import { CommonModule } from '@angular/common';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatDividerModule } from '@angular/material/divider';
import { MatExpansionModule } from '@angular/material/expansion';
import { MatIconModule } from '@angular/material/icon';
import { MatMenuModule } from '@angular/material/menu';
import { ChartistModule, Configuration } from 'ng-chartist';
import { AxisOptions, Label } from 'chartist';
import { Observable, Subscription } from 'rxjs';
@@ -14,13 +17,14 @@ import { UtilitiesService, JumpsService } from 'src/app/core/services';
import { JumpByDate } from 'src/app/core/models';
@Component({
selector: 'app-jumps-by-month',
standalone: true,
imports: [
CommonModule,
MatButtonModule, MatCardModule, MatExpansionModule, MatIconModule, MatMenuModule,
MatButtonModule, MatCardModule, MatDividerModule,
MatExpansionModule, MatIconModule, MatMenuModule,
ChartistModule
],
selector: 'huapp-jumps-by-month',
templateUrl: './jumps-by-month.component.html'
})
export class JumpsByMonthComponent implements OnInit, OnDestroy {
@@ -32,16 +36,28 @@ export class JumpsByMonthComponent implements OnInit, OnDestroy {
public min = 0;
public max = 0;
public grandAvg = 0;
public grandAvgLastYears = 0;
public grandTotal = 0;
public seriesHeader: string[] = [];
public seriesName: String[] = [];
public seriesRow: any[] = [];
public seriesColor: String[] = this._utilitiesService.getChartColors();
public seriesName: string[] = [];
public seriesRow: Array<Array<number>> = [];
public seriesColor: {
backgroundColor: string[],
borderColor: string[]
} = {
backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'),
borderColor: this._utilitiesService.getSeriesColors(1, 'all')
};
public seriesColorClass: string[] = this._utilitiesService.getChartColors();
public seriesRowTotal: number[] = [];
public seriesRowAvg: number[] = [];
public seriesRowAvgLastYears: number[] = [];
public seriesColTotal: number[] = [];
public seriesColTotalClosed: number[] = [];
public seriesColTotalLastYears: number[] = [];
public displayCharts = false;
public barChartJumps: Configuration = this._utilitiesService.getBarConfig();
public destroyRef = inject(DestroyRef);
constructor(
private _jumpsService: JumpsService,
@@ -58,44 +74,63 @@ export class JumpsByMonthComponent implements OnInit, OnDestroy {
}
private _loadJumpByDate() {
this.seriesHeader = ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"];
let values: Array<number> = this.seriesHeader.map(() => 0);
this.seriesHeader = this._utilitiesService.getMonthsList();
const values: Array<number> = this.seriesHeader.map(() => 0);
this.seriesColTotal = [...values];
const jumps$: Observable<Array<JumpByDate>> = this._jumpsService.getAllByDate();
this.seriesColTotalClosed = [...values];
this.seriesColTotalLastYears = [...values];
const jumps$: Observable<Array<JumpByDate>> = this._jumpsService.getAllByDate().pipe(takeUntilDestroyed(this.destroyRef));
this._jumpByDate = jumps$.subscribe((aggregate: Array<JumpByDate>) => {
this._jumpsByDateCount = aggregate.length;
this._jumpsByDate = aggregate.map((row: JumpByDate) => {
let year = row._id.year.toString();
let month = row._id.month;
const currentYear: number = new Date().getFullYear();
const year = row.year.toString();
const month = row.month;
if (this.seriesName.indexOf(year) < 0) {
this.seriesName.push(year);
if (row._id.year < this.min || this.min == 0) {
this.min = row._id.year;
if (row.year < this.min || this.min == 0) {
this.min = row.year;
}
if (row._id.year > this.max) {
this.max = row._id.year;
if (row.year > this.max) {
this.max = row.year;
}
this.seriesRow.push([...values]);
}
this.seriesRow[(this.seriesRow.length-1)][(month-1)] = row.count;
this.seriesColTotal[(month-1)] += row.count;
if (row.year < currentYear) {
this.seriesColTotalClosed[(month-1)] += row.count;
}
if (row.year >= (currentYear-3) && row.year < currentYear) {
this.seriesColTotalLastYears[(month-1)] += row.count;
}
return row;
});
this.seriesRow.forEach((row: number[]) => {
const total = row.reduce((partialSum, a) => partialSum + a, 0);
this.seriesRowTotal.push(total);
});
this.seriesRowTotal.forEach((row: number) => {
let value: number = (row/this.seriesName.length);
this.seriesRowAvg.push(value);
this.seriesColTotalClosed.forEach((row: number) => {
const value: number = (row/(this.seriesName.length-2)); // -2 pour ne pas compter la première année
this.seriesRowAvg.push(parseInt(value.toFixed(0)));
});
this.seriesColTotalLastYears.forEach((row: number) => {
const value: number = (row/3); // Les 3 dernières années
this.seriesRowAvgLastYears.push(parseInt(value.toFixed(0)));
});
this.grandAvg = this.seriesRowAvg.reduce((partialSum, accumulated) => partialSum + accumulated, 0);
this.grandAvgLastYears = this.seriesRowAvgLastYears.reduce((partialSum, accumulated) => partialSum + accumulated, 0);
this.grandTotal = this.seriesColTotal.reduce((partialSum, accumulated) => partialSum + accumulated, 0);
const axisX: AxisOptions = {
labelInterpolationFnc: function(value: Label, index: number): string {
return index % 1 === 0 ? `${value.toString()}` : '';
}
}
this.barChartJumps = {
type: 'Bar',
data: {
"labels": this.seriesHeader,
"series": this.seriesRow
'labels': this.seriesHeader,
'series': this.seriesRow
},
options: {
seriesBarDistance: 15,
@@ -112,33 +147,21 @@ export class JumpsByMonthComponent implements OnInit, OnDestroy {
},
responsiveOptions: [
['screen and (min-width: 1024px)', {
axisX: {
labelInterpolationFnc: function(value: number, index: number): string {
return index % 1 === 0 ? `${value}` : '';
}
}
axisX: axisX
}],
['screen and (min-width: 641px) and (max-width: 1024px)', {
seriesBarDistance: 10,
axisY: {
offset: 30
},
axisX: {
labelInterpolationFnc: function(value: any, index: number): string {
return index % 1 === 0 ? `${value[0]}` : '';
}
}
axisX: axisX
}],
['screen and (max-width: 640px)', {
seriesBarDistance: 5,
axisY: {
offset: 20
},
axisX: {
labelInterpolationFnc: function(value: any, index: number): string {
return index % 1 === 0 ? `${value[0]}` : '';
}
}
axisX: axisX
}]
]
};