Mise à jour et ajout de 'components'
This commit is contained in:
@@ -46,6 +46,12 @@
|
||||
<mat-error *ngIf="this.authForm.controls['licence'].status === 'INVALID'">{{getErrorMessage('licence')}}</mat-error>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="col-12" *ngIf="authType === 'register'">
|
||||
<mat-form-field appearance="fill" class="w-100">
|
||||
<input matInput type="text" placeholder="Indiquez le poids en Kg" formControlName="poids">
|
||||
<mat-error *ngIf="this.authForm.controls['poids'].status === 'INVALID'">{{getErrorMessage('poids')}}</mat-error>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset [disabled]="isSubmitting" class="w-100">
|
||||
<legend [hidden]="true">Informations de connexion</legend>
|
||||
|
||||
@@ -51,6 +51,7 @@ export class AuthComponent implements OnInit, OnDestroy {
|
||||
lastname: '',
|
||||
phone: '',
|
||||
licence: '',
|
||||
poids: '',
|
||||
password: ['', Validators.required],
|
||||
confirmPassword: ''
|
||||
}, { validators: this.checkPasswords });
|
||||
|
||||
@@ -4,100 +4,181 @@
|
||||
<mat-card-title>Calcul de taille de voile</mat-card-title>
|
||||
<mat-card-subtitle>DT48 - 13 mars 2020</mat-card-subtitle>
|
||||
<span class="flex-spacer"></span>
|
||||
<form #searchFormData="ngForm" class="inputs-form">
|
||||
<mat-form-field class="bg-crystal me-3" subscriptSizing="dynamic">
|
||||
<mat-label>Nombre de sauts</mat-label>
|
||||
<input matInput [(ngModel)]="inputs.jumps" (change)="refresh()" type="number" min="0" name="jumps">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="bg-crystal me-3" subscriptSizing="dynamic">
|
||||
<mat-label>Poids nu</mat-label>
|
||||
<input matInput [(ngModel)]="inputs.weight" (change)="refresh()" type="number" min="60" max="110" name="weight">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="bg-crystal me-3" subscriptSizing="dynamic">
|
||||
<mat-label>Poids équipement</mat-label>
|
||||
<input matInput [(ngModel)]="inputs.gear" (change)="refresh()" type="number" min="0" name="gear">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="bg-crystal me-3" subscriptSizing="dynamic">
|
||||
<mat-label>Taille actuelle</mat-label>
|
||||
<input matInput [(ngModel)]="inputs.current" (change)="refresh()" type="number" min="0" name="current" id="current" placeholder="Taille actuelle" >
|
||||
</mat-form-field>
|
||||
</form>
|
||||
<button mat-icon-button [matMenuTriggerFor]="menuCalculator" aria-label="Menu Calculator">
|
||||
<mat-icon>more_vert</mat-icon>
|
||||
</button>
|
||||
<mat-menu #menuCalculator="matMenu">
|
||||
<button mat-menu-item>
|
||||
<mat-icon>search</mat-icon>
|
||||
<span>Recherche avancée</span>
|
||||
</button>
|
||||
<button mat-menu-item>
|
||||
<mat-icon>person_search</mat-icon>
|
||||
<span>Recherche par participant</span>
|
||||
</button>
|
||||
<button mat-menu-item>
|
||||
<mat-icon>display_settings</mat-icon>
|
||||
<span>Paramètre d'affichage</span>
|
||||
</button>
|
||||
<button mat-menu-item disabled>
|
||||
<mat-icon>upload_file</mat-icon>
|
||||
<span>Import CSV</span>
|
||||
</button>
|
||||
<ng-container *ngFor="let menuitem of menuItems.getMenuCalculator()">
|
||||
<button mat-menu-item [routerLink]="['/', menuitem.state]" *ngIf="menuitem.type === 'link'">
|
||||
<mat-icon [fontIcon]="menuitem.icon"></mat-icon>
|
||||
<span>{{ menuitem.name }}</span>
|
||||
</button>
|
||||
</ng-container>
|
||||
</mat-menu>
|
||||
</mat-card-header>
|
||||
<mat-card-content class="my-4 mx-2">
|
||||
<form #searchFormData="ngForm" class="inputs-form">
|
||||
<mat-form-field class="bg-crystal me-3">
|
||||
<mat-label>Nombre de sauts</mat-label>
|
||||
<input matInput [(ngModel)]="inputs.jumps" (change)="refreshActive()" type="number" min="0" name="jumps">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="bg-crystal me-3">
|
||||
<mat-label>Poids nu</mat-label>
|
||||
<input matInput [(ngModel)]="inputs.weight" (change)="refreshActive()" type="number" min="60" max="110" name="weight">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="bg-crystal me-3">
|
||||
<mat-label>Poids équipement</mat-label>
|
||||
<input matInput [(ngModel)]="inputs.gear" type="number" min="0" name="gear">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="bg-crystal me-3">
|
||||
<mat-label>Taille actuelle</mat-label>
|
||||
<input matInput [(ngModel)]="inputs.current" type="number" min="0" name="current" id="current" placeholder="Taille actuelle" >
|
||||
</mat-form-field>
|
||||
</form>
|
||||
<mat-card-content class="my-4">
|
||||
<div class="row">
|
||||
<div class="col-lg-6 col-md-8 col-sm-12">
|
||||
<div *ngIf="displayCharts" class="linechart position-relative w-100 mt-3">
|
||||
<canvas baseChart class="mx-auto" width="900" height="350"
|
||||
[data]="chartConfig.lineChartData"
|
||||
[options]="chartConfig.lineChartOptions"
|
||||
[legend]="chartConfig.lineChartLegend"
|
||||
[type]="'line'">
|
||||
</canvas>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6 col-md-8 col-sm-12">
|
||||
<table class="table table-striped table-dark table-hover mat-elevation-z2">
|
||||
<thead>
|
||||
<tr class="warn">
|
||||
<th class="first"></th>
|
||||
<th class="text-nowrap">Taille actuelle</th>
|
||||
<th class="text-nowrap">Taille min</th>
|
||||
<th class="text-nowrap">Taille min -11%</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="warn">
|
||||
<th class="first">Taille de voile en ft<sup>2</sup></th>
|
||||
<td class="font-monospace text-{{ info.state.color }}"> ● {{ info.sizesFeet.current }} </td>
|
||||
<td class="font-monospace text-success"> ● {{ info.sizesFeet.min }} </td>
|
||||
<td class="font-monospace text-warning"> ● {{ info.sizesFeet.min11 }} </td>
|
||||
</tr>
|
||||
<tr class="warn">
|
||||
<th class="first">Charge alaire</th>
|
||||
<td class="font-monospace">{{ info.charges.current | number : '1.2-3' }}</td>
|
||||
<td class="font-monospace">{{ info.charges.min | number : '1.2-3' }}</td>
|
||||
<td class="font-monospace">{{ info.charges.min11 | number : '1.2-3' }}</td>
|
||||
</tr>
|
||||
<tr class="warn">
|
||||
<th class="first">Taille de voile en m<sup>2</sup></th>
|
||||
<td class="font-monospace">{{ info.sizesMeter.current | number : '1.2-3' }}</td>
|
||||
<td class="font-monospace">{{ info.sizesMeter.min | number : '1.2-3' }}</td>
|
||||
<td class="font-monospace">{{ info.sizesMeter.min11 | number : '1.2-3' }}</td>
|
||||
</tr>
|
||||
<tr class="warn">
|
||||
<th class="first">Coefficient kilo/livres</th>
|
||||
<td colspan="3" class="font-monospace text-start">{{ coeffKgLbs }}</td>
|
||||
</tr>
|
||||
<tr class="warn">
|
||||
<th class="first">Coefficient pied/mètre</th>
|
||||
<td colspan="3" class="font-monospace text-start">{{ coeffFtM }}</td>
|
||||
</tr>
|
||||
<tr class="warn">
|
||||
<th class="first">Formule charge alaire</th>
|
||||
<td colspan="3" class="font-monospace text-start">
|
||||
( ( {{ inputs.weight }} + {{ inputs.gear }} ) * {{ coeffKgLbs }} ) / {{ inputs.current }} = {{ info.charges.current | number : '1.5' }}<br />
|
||||
( ( poids nu en kg + poids equipement en kg ) * coefficient kg/lbs ) / taille de voile en ft<sup>2</sup>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<h4 class="border-bottom border-secondary py-2 mb-2">Tailles de voile pour {{ inputs.weight }} kg</h4>
|
||||
<table class="table table-striped table-dark table-hover mat-elevation-z2 mb-1">
|
||||
<thead>
|
||||
<tr class="warn">
|
||||
<th class="first"></th>
|
||||
<th *ngFor="let header of sizesHeader; let index = index;" class="pl-3 pr-3 {{ tableHeader[(index+1)].active }}">{{ header.name }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="warn">
|
||||
<th class="first">Taille de voile en ft<sup>2</sup></th>
|
||||
<td *ngFor="let value of sizesValues; let index = index;" class="pl-3 text-nowrap {{ tableHeader[(index+1)].active }}">{{ value }}</td>
|
||||
</tr>
|
||||
<tr class="warn">
|
||||
<th class="first">Abbattement 11%</th>
|
||||
<td *ngFor="let value of sizesMinValues; let index = index;" class="pl-3 text-nowrap {{ tableHeader[(index+1)].active }}">{{ value }}</td>
|
||||
</tr>
|
||||
<tr class="warn">
|
||||
<th class="first">Charge alaire</th>
|
||||
<td *ngFor="let charge of sizesCharges; let index = index;" class="pl-3 text-nowrap {{ tableHeader[(index+1)].active }}">{{ charge | number : '1.2-3' }}</td>
|
||||
</tr>
|
||||
<tr class="warn">
|
||||
<th class="first">Taille de voile en m<sup>2</sup></th>
|
||||
<td *ngFor="let value of sizesValuesM; let index = index;" class="pl-3 text-nowrap {{ tableHeader[(index+1)].active }}">{{ value | number : '1.2-2' }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr />
|
||||
<h4 class="border-bottom border-secondary py-2 mb-2">Tableau des tailles de voile par poids</h4>
|
||||
<table mat-table [dataSource]="canopy_size_table" matSort class="table table-striped table-dark table-hover mat-elevation-z2">
|
||||
<!-- Numero Column -->
|
||||
<ng-container matColumnDef="weight">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header class="{{tableHeader[0].active}}"> {{tableHeader[0].name}} </th>
|
||||
<th mat-cell *matCellDef="let element;" class="text-end pl-3 pr-3">{{element.weight}}</th>
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header class="first {{tableHeader[0].active}}"> {{tableHeader[0].name}} </th>
|
||||
<th mat-cell *matCellDef="let element;" class="text-end ps-3 pe-4 fs-6" role="button" (click)="setCurrentWeight(element.weight)">
|
||||
<span class="text-warn d-block">{{element.weight}}</span>
|
||||
</th>
|
||||
</ng-container>
|
||||
<!-- range_ Column -->
|
||||
<ng-container matColumnDef="range_1">
|
||||
<th class="pl-3" mat-header-cell *matHeaderCellDef class="{{tableHeader[1].active}}"> {{tableHeader[1].name}} </th>
|
||||
<td mat-cell *matCellDef="let element;" class="pl-3 text-nowrap {{element.ranges[0].active}}">{{element.ranges[0].value}}</td>
|
||||
<td mat-cell *matCellDef="let element;" class="pl-3 text-nowrap fs-6 {{element.ranges[0].active}}">{{element.ranges[0].value}}</td>
|
||||
</ng-container>
|
||||
<!-- range_ Column -->
|
||||
<ng-container matColumnDef="range_2">
|
||||
<th class="pl-3" mat-header-cell *matHeaderCellDef class="{{tableHeader[2].active}}"> {{tableHeader[2].name}} </th>
|
||||
<td mat-cell *matCellDef="let element;" class="pl-3 text-nowrap {{element.ranges[1].active}}">{{element.ranges[1].value}}</td>
|
||||
<td mat-cell *matCellDef="let element;" class="pl-3 text-nowrap fs-6 {{element.ranges[1].active}}">{{element.ranges[1].value}}</td>
|
||||
</ng-container>
|
||||
<!-- range_ Column -->
|
||||
<ng-container matColumnDef="range_3">
|
||||
<th class="pl-3" mat-header-cell *matHeaderCellDef class="{{tableHeader[3].active}}"> {{tableHeader[3].name}} </th>
|
||||
<td mat-cell *matCellDef="let element;" class="pl-3 text-nowrap {{element.ranges[2].active}}">{{element.ranges[2].value}}</td>
|
||||
<td mat-cell *matCellDef="let element;" class="pl-3 text-nowrap fs-6 {{element.ranges[2].active}}">{{element.ranges[2].value}}</td>
|
||||
</ng-container>
|
||||
<!-- range_ Column -->
|
||||
<ng-container matColumnDef="range_4">
|
||||
<th class="pl-3" mat-header-cell *matHeaderCellDef class="{{tableHeader[4].active}}"> {{tableHeader[4].name}} </th>
|
||||
<td mat-cell *matCellDef="let element;" class="pl-3 text-nowrap {{element.ranges[3].active}}">{{element.ranges[3].value}}</td>
|
||||
<td mat-cell *matCellDef="let element;" class="pl-3 text-nowrap fs-6 {{element.ranges[3].active}}">{{element.ranges[3].value}}</td>
|
||||
</ng-container>
|
||||
<!-- range_ Column -->
|
||||
<ng-container matColumnDef="range_5">
|
||||
<th class="pl-3" mat-header-cell *matHeaderCellDef class="{{tableHeader[5].active}}"> {{tableHeader[5].name}} </th>
|
||||
<td mat-cell *matCellDef="let element;" class="pl-3 text-nowrap {{element.ranges[4].active}}">{{element.ranges[4].value}}</td>
|
||||
<td mat-cell *matCellDef="let element;" class="pl-3 text-nowrap fs-6 {{element.ranges[4].active}}">{{element.ranges[4].value}}</td>
|
||||
</ng-container>
|
||||
<!-- range_ Column -->
|
||||
<ng-container matColumnDef="range_6">
|
||||
<th class="pl-3" mat-header-cell *matHeaderCellDef class="{{tableHeader[6].active}}"> {{tableHeader[6].name}} </th>
|
||||
<td mat-cell *matCellDef="let element;" class="pl-3 text-nowrap {{element.ranges[5].active}}">{{element.ranges[5].value}}</td>
|
||||
<td mat-cell *matCellDef="let element;" class="pl-3 text-nowrap fs-6 {{element.ranges[5].active}}">{{element.ranges[5].value}}</td>
|
||||
</ng-container>
|
||||
<!-- range_ Column -->
|
||||
<ng-container matColumnDef="range_7">
|
||||
<th class="pl-3" mat-header-cell *matHeaderCellDef class="{{tableHeader[7].active}}"> {{tableHeader[7].name}} </th>
|
||||
<td mat-cell *matCellDef="let element;" class="pl-3 text-nowrap {{element.ranges[6].active}}">{{element.ranges[6].value}}</td>
|
||||
<td mat-cell *matCellDef="let element;" class="pl-3 text-nowrap fs-6 {{element.ranges[6].active}}">{{element.ranges[6].value}}</td>
|
||||
</ng-container>
|
||||
<!-- range_ Column -->
|
||||
<ng-container matColumnDef="range_8">
|
||||
<th class="pl-3" mat-header-cell *matHeaderCellDef class="{{tableHeader[8].active}}"> {{tableHeader[8].name}} </th>
|
||||
<td mat-cell *matCellDef="let element;" class="pl-3 text-nowrap {{element.ranges[7].active}}">{{element.ranges[7].value}}</td>
|
||||
<td mat-cell *matCellDef="let element;" class="pl-3 text-nowrap fs-6 {{element.ranges[7].active}}">{{element.ranges[7].value}}</td>
|
||||
</ng-container>
|
||||
<!-- range_ Column -->
|
||||
<ng-container matColumnDef="range_9">
|
||||
<th class="pl-3" mat-header-cell *matHeaderCellDef class="{{tableHeader[9].active}}"> {{tableHeader[9].name}} </th>
|
||||
<td mat-cell *matCellDef="let element;" class="pl-3 text-nowrap {{element.ranges[8].active}}">{{element.ranges[8].value}}</td>
|
||||
<td mat-cell *matCellDef="let element;" class="pl-3 text-nowrap fs-6 {{element.ranges[8].active}}">{{element.ranges[8].value}}</td>
|
||||
</ng-container>
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true" class="warn"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;" class="text-middle warn {{row.active}}" id="weight_{{row.weight}}"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;" class="text-middle font-monospace warn {{row.active}}" id="weight_{{row.weight}}"></tr>
|
||||
</table>
|
||||
<div class="clearfix">
|
||||
<mat-paginator [pageSize]="50" [pageSizeOptions]="[5, 10, 15, 25, 50]" showFirstLastButtons class="pull-right mb-1 mt-2"></mat-paginator>
|
||||
|
||||
@@ -38,4 +38,9 @@
|
||||
appearance: textfield;
|
||||
-moz-appearance: textfield;
|
||||
}
|
||||
th {
|
||||
&.first {
|
||||
width: 180px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
import { Component, Input, OnInit, OnDestroy, ViewChild } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { RouterLink, RouterModule } from '@angular/router';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatDividerModule } from '@angular/material/divider';
|
||||
@@ -10,70 +12,238 @@ import { MatMenuModule } from '@angular/material/menu';
|
||||
import { MatPaginator, MatPaginatorModule } from '@angular/material/paginator';
|
||||
import { MatSort, MatSortModule } from '@angular/material/sort';
|
||||
import { MatTableDataSource, MatTableModule } from '@angular/material/table';
|
||||
import { NgChartsModule } from 'ng2-charts';
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
|
||||
import { CalcResult, InputParams, Range, WeightSize, weightSizes } from 'src/app/core/models';
|
||||
import { MenuItems } from 'src/app/components/shared';
|
||||
import { CalculatorInfo, CalculatorResult, InputParams, Jump, LineConfig, Range, TableHeader, User, WeightSize, weightSizes } from 'src/app/core/models';
|
||||
import { JumpsService, UserService, UtilitiesService } from 'src/app/core/services';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
imports: [
|
||||
FormsModule,
|
||||
CommonModule, FormsModule, RouterModule,
|
||||
MatButtonModule, MatCardModule, MatDividerModule,
|
||||
MatFormFieldModule, MatInputModule, MatIconModule, MatMenuModule,
|
||||
MatPaginatorModule, MatSortModule, MatTableModule
|
||||
MatPaginatorModule, MatSortModule, MatTableModule,
|
||||
NgChartsModule
|
||||
],
|
||||
selector: 'huapp-calculator',
|
||||
styleUrls: ['./calculator.component.scss'],
|
||||
templateUrl: './calculator.component.html'
|
||||
})
|
||||
export class CalculatorComponent implements OnInit, OnDestroy {
|
||||
title = 'Calcul de taille de voile';
|
||||
subtitle = 'DT48 - 13 mars 2020';
|
||||
displayedColumns: string[] = [
|
||||
"weight",
|
||||
"range_1", "range_2", "range_3",
|
||||
"range_4", "range_5", "range_6",
|
||||
"range_7", "range_8", "range_9"
|
||||
];
|
||||
tableHeader: {name: string, active: string}[] = [
|
||||
{name: "Poids nu", active: ''},
|
||||
{name: "0 à 99", active: ''},
|
||||
{name: "100 à 249", active: ''},
|
||||
{name: "250 à 399", active: ''},
|
||||
{name: "400 à 599", active: ''},
|
||||
{name: "600 à 799", active: ''},
|
||||
{name: "800 à 999", active: ''},
|
||||
{name: "1000 à 1399", active: ''},
|
||||
{name: "1400 à 1799", active: ''},
|
||||
{name: "1800 à 2000", active: ''},
|
||||
];;
|
||||
private _lastjump: Subscription = new Subscription();
|
||||
private _currentUser: Subscription = new Subscription();
|
||||
public title = 'Calcul de taille de voile';
|
||||
public subtitle = 'DT48 - 13 mars 2020';
|
||||
public lastjump: Jump = {} as Jump;
|
||||
public currentUser: User = {} as User;
|
||||
public displayedColumns: string[] = ['weight'];
|
||||
public tableHeader: TableHeader[] = [{name: 'Poids nu en kg', active: ''}];
|
||||
public sizesHeader: TableHeader[] = [];
|
||||
public sizesValues: number[] = [];
|
||||
public sizesMinValues: number[] = [];
|
||||
public sizesCharges: number[] = [];
|
||||
public sizesValuesM: number[] = [];
|
||||
public displayCharts = false;
|
||||
public chartConfig: LineConfig = this._utilitiesService.getLineChartConfig();
|
||||
public info: CalculatorInfo = {
|
||||
charges: {
|
||||
current: 0,
|
||||
min: 0,
|
||||
min11: 0
|
||||
},
|
||||
sizesFeet: {
|
||||
current: 0,
|
||||
min: 0,
|
||||
min11: 0
|
||||
},
|
||||
sizesMeter: {
|
||||
current: 0,
|
||||
min: 0,
|
||||
min11: 0
|
||||
},
|
||||
state: {
|
||||
color: 'danger'
|
||||
}
|
||||
}
|
||||
public coeffKgLbs: number = this._utilitiesService.getCoeffKgLbs();
|
||||
public coeffFtM: number = this._utilitiesService.getCoeffFtM();
|
||||
|
||||
@Input() canopy_size_table!: MatTableDataSource<WeightSize>;
|
||||
@Input() inputs: InputParams = {
|
||||
jumps: 0,
|
||||
weight: 60,
|
||||
gear: 10,
|
||||
current: 175
|
||||
current: 190
|
||||
} as InputParams;
|
||||
|
||||
@ViewChild(MatSort) sort!: MatSort;
|
||||
@ViewChild(MatPaginator) paginator!: MatPaginator;
|
||||
|
||||
constructor() { }
|
||||
constructor(
|
||||
private jumpsService: JumpsService,
|
||||
private userService: UserService,
|
||||
private _utilitiesService: UtilitiesService,
|
||||
public menuItems: MenuItems
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
return this.loadData();
|
||||
const currentUser$: Observable<User> = this.userService.currentUser;
|
||||
const lastjump$: Observable<Jump> = this.jumpsService.getLastJump();
|
||||
this._currentUser = currentUser$.subscribe((userData: User) => {
|
||||
this.currentUser = userData;
|
||||
weightSizes[0].ranges.forEach((range: Range) => {
|
||||
let header: TableHeader = {name: range.label, active: range.active};
|
||||
this.tableHeader.push(header)
|
||||
this.sizesHeader.push(header);
|
||||
this.displayedColumns.push(range.name);
|
||||
});
|
||||
this._lastjump = lastjump$.subscribe((jump) => {
|
||||
this.lastjump = jump;
|
||||
this.inputs.jumps = jump.numero;
|
||||
this.inputs.weight = this.currentUser.poids!;
|
||||
this.inputs.current = jump.taille!;
|
||||
this.canopy_size_table = new MatTableDataSource<WeightSize>(weightSizes);
|
||||
this.refresh();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
//this._scavenger.unsubscribe();
|
||||
this._currentUser.unsubscribe();
|
||||
this._lastjump.unsubscribe();
|
||||
}
|
||||
|
||||
loadData():void {
|
||||
this.refreshActive();
|
||||
this.canopy_size_table = new MatTableDataSource<WeightSize>(weightSizes);
|
||||
private _canopySizeCalc(weight: number, jumps: number): CalculatorResult {
|
||||
let result: CalculatorResult = {
|
||||
min: 0,
|
||||
min11: 0
|
||||
};
|
||||
if (jumps > 2000) {
|
||||
this.info.error = '2000Jumps';
|
||||
return result;
|
||||
}
|
||||
let index: number = (this._getTableLine(weight) - this._getTableLine(0));
|
||||
result.min = weightSizes[index].ranges[this._getTableColumn(jumps)].value;
|
||||
result.min11 = this._reduceLimit(result.min, 11);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
refreshActive():void {
|
||||
private _getCanopyMinSize(weight: number, jumps: number, reduce: number = 0): number {
|
||||
var result: CalculatorResult = this._canopySizeCalc(weight, jumps);
|
||||
let size: number = 0;
|
||||
switch (reduce) {
|
||||
case 11:
|
||||
size = result.min11;
|
||||
break;
|
||||
case 0:
|
||||
default:
|
||||
size = result.min;
|
||||
break;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
private _getCanopySizes(weight: number, eleven = false): number[] {
|
||||
var data: number[] = [];
|
||||
if (weight < 60) {
|
||||
weight = 60;
|
||||
}
|
||||
if (weight > 110) {
|
||||
weight = 110;
|
||||
}
|
||||
if (weight >= 60 && weight <= 110) {
|
||||
const line = (weight - this._getTableLine(0));
|
||||
let data = weightSizes[line];
|
||||
if (eleven) {
|
||||
return data.ranges.map((range: Range) => {
|
||||
return Math.ceil(range.value * (100 - 11) / 100);
|
||||
});
|
||||
} else {
|
||||
return data.ranges.map((range: Range) => {
|
||||
return range.value;
|
||||
});
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
private _getCharge(canopySize: number, nakedWeight: number, equipementWeight: number): number {
|
||||
return (((nakedWeight + equipementWeight) * this.coeffKgLbs) / canopySize);
|
||||
}
|
||||
|
||||
private _getRangeNum(): number {
|
||||
let data: Range[] = weightSizes[0].ranges;
|
||||
let num: number = 1;
|
||||
data.some((range: Range) => {
|
||||
if (range.start <= this.inputs.jumps && range.end >= this.inputs.jumps) {
|
||||
num = range.num;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
return num;
|
||||
}
|
||||
|
||||
private _getTableColumn(jumps: number): number {
|
||||
let column = 0;
|
||||
if (jumps < 100) {
|
||||
column = 0;
|
||||
} else if (jumps < 250) {
|
||||
column = 1;
|
||||
} else if (jumps < 400) {
|
||||
column = 2;
|
||||
} else if (jumps < 600) {
|
||||
column = 3;
|
||||
} else if (jumps < 800) {
|
||||
column = 4;
|
||||
} else if (jumps < 1000) {
|
||||
column = 5;
|
||||
} else if (jumps < 1400) {
|
||||
column = 6;
|
||||
} else if (jumps < 1800) {
|
||||
column = 7;
|
||||
} else {
|
||||
column = 8;
|
||||
}
|
||||
return column;
|
||||
}
|
||||
|
||||
private _getTableLine(weight: number): number {
|
||||
let line;
|
||||
let min = 60;
|
||||
let max = 110;
|
||||
if (weight < min) {
|
||||
line = min;
|
||||
} else if (weight > max) {
|
||||
line = max;
|
||||
} else {
|
||||
line = weight;
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
private _convertFeet2Meters(size: number): number {
|
||||
return (size * this._utilitiesService.getCoeffFtM());
|
||||
}
|
||||
|
||||
private _isInRange(nb: number, range: Range): boolean {
|
||||
return (nb >= range.start && nb < range.end);
|
||||
}
|
||||
|
||||
private _reduceLimit(surface: number, percentOff: number) {
|
||||
return Math.ceil(surface * (100 - percentOff) / 100);
|
||||
}
|
||||
|
||||
public refresh():void {
|
||||
this._refreshActive();
|
||||
this._refreshSizes();
|
||||
}
|
||||
|
||||
private _refreshActive(): void {
|
||||
weightSizes.forEach(element => {
|
||||
element.active = '';
|
||||
element.ranges.forEach(range => {
|
||||
@@ -87,25 +257,80 @@ export class CalculatorComponent implements OnInit, OnDestroy {
|
||||
weightSizes[(this.inputs.weight - 60)].active = 'active';
|
||||
}
|
||||
if (this.inputs.jumps >= 0) {
|
||||
var num = this.getRangeNum();
|
||||
var num = this._getRangeNum();
|
||||
this.tableHeader[num].active = 'active';
|
||||
weightSizes.forEach(element => {
|
||||
element.ranges[(num-1)].active = 'active';
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private getRangeNum(): number {
|
||||
var data: Range[] = weightSizes[0].ranges;
|
||||
var num: number = 1;
|
||||
data.some((range: Range) => {
|
||||
if (range.start <= this.inputs.jumps && range.end >= this.inputs.jumps) {
|
||||
num = range.num;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
private _getStateColor(current: number, min: number, min11: number): string {
|
||||
let color: string = 'danger';
|
||||
if (current >= min11 && current < min) {
|
||||
color = 'warning';
|
||||
}
|
||||
if (current >= min) {
|
||||
color = 'success';
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
private _refreshSizes(): void {
|
||||
this.sizesValues = this._getCanopySizes(this.inputs.weight, false);
|
||||
this.sizesMinValues = this._getCanopySizes(this.inputs.weight, true);
|
||||
this.sizesValues.forEach((value: number, index: number) => {
|
||||
this.sizesCharges[index] = this._getCharge(value, this.inputs.weight, this.inputs.gear);
|
||||
this.sizesValuesM[index] = this._convertFeet2Meters(value);
|
||||
});
|
||||
return num;
|
||||
this.info.sizesFeet = this._canopySizeCalc(this.inputs.weight, this.inputs.jumps);
|
||||
this.info.sizesFeet.current = this.inputs.current;
|
||||
this.info.sizesMeter = {
|
||||
current: this._convertFeet2Meters(this.inputs.current),
|
||||
min: this._convertFeet2Meters(this.info.sizesFeet.min),
|
||||
min11: this._convertFeet2Meters(this.info.sizesFeet.min11)
|
||||
}
|
||||
this.info.charges = {
|
||||
current: this._getCharge(this.inputs.current, this.inputs.weight, this.inputs.gear),
|
||||
min: this._getCharge(this.info.sizesFeet.min, this.inputs.weight, this.inputs.gear),
|
||||
min11: this._getCharge(this.info.sizesFeet.min11, this.inputs.weight, this.inputs.gear)
|
||||
}
|
||||
this.info.state.color = this._getStateColor(this.info.sizesFeet.current, this.info.sizesFeet.min, this.info.sizesFeet.min11);
|
||||
|
||||
this.chartConfig.lineChartData.labels = [...this.sizesHeader.map((
|
||||
data: {
|
||||
name: string;
|
||||
active: string;
|
||||
}
|
||||
): string => {
|
||||
return data.name;
|
||||
})];
|
||||
this.chartConfig.lineChartData.datasets = [
|
||||
{
|
||||
label: 'Tailles min -11%',
|
||||
data: this.sizesMinValues,
|
||||
fill: true,
|
||||
stepped: true,
|
||||
pointStyle: false,
|
||||
borderColor: 'rgba(241, 80, 80, 1)',
|
||||
backgroundColor: 'rgba(241, 80, 80, 0.3)'
|
||||
},
|
||||
{
|
||||
label: 'Tailles min',
|
||||
data: this.sizesValues,
|
||||
fill: true,
|
||||
stepped: true,
|
||||
pointStyle: false,
|
||||
borderColor: 'rgba(32, 182, 252, 1)',
|
||||
backgroundColor: 'rgba(32, 182, 252, 0.3)'
|
||||
}
|
||||
];
|
||||
this.displayCharts = true;
|
||||
}
|
||||
|
||||
public setCurrentWeight(weight: number) {
|
||||
this.inputs.weight = weight;
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+41
-39
@@ -1,44 +1,46 @@
|
||||
<mat-card>
|
||||
<mat-card-content class="mb-0">
|
||||
<mat-card-title>Aéronefs</mat-card-title>
|
||||
<mat-card-subtitle>Nombre total de sauts par avions</mat-card-subtitle>
|
||||
<div class="barchrt">
|
||||
<x-chartist [configuration]="barChartAeronef"></x-chartist>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
<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>
|
||||
<table class="table table-striped table-dark table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th *ngFor='let name of seriesHeader; let i=index' class="text-end"> {{name}} </th>
|
||||
<th class="text-end">Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="font-monospace">
|
||||
<tr *ngFor='let values of seriesRow; let i=index'>
|
||||
<th class="{{seriesColor[i]}} text-end"> ● {{seriesName[i]}} </th>
|
||||
<td *ngFor='let value of values; let i=index' class="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="{{seriesColor[i]}} text-end">
|
||||
<span *ngIf="seriesValue[i]; else elseBlock" class="pr-1">{{seriesValue[i]}}</span>
|
||||
<ng-template #elseBlock><span class="text-empty pr-1">{{seriesValue[i]}}</span></ng-template>
|
||||
</th>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</mat-card-content>
|
||||
<!--<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 *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>-->
|
||||
</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>
|
||||
|
||||
+47
-93
@@ -1,35 +1,48 @@
|
||||
import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { ChartistModule, Configuration } from 'ng-chartist';
|
||||
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 { BackendService, AeronefsService } from 'src/app/core/services';
|
||||
import { chartBar, AeronefByImat, AeronefByYear } from 'src/app/core/models';
|
||||
import { MenuItems, HistoryTableComponent } from 'src/app/components/shared';
|
||||
import { UtilitiesService, AeronefsService } from 'src/app/core/services';
|
||||
import { AeronefByImat, AeronefByYear, BarConfig } from 'src/app/core/models';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
imports: [CommonModule, MatCardModule, ChartistModule],
|
||||
imports: [
|
||||
CommonModule,
|
||||
MatButtonModule, MatCardModule, MatExpansionModule, MatIconModule, MatMenuModule,
|
||||
NgChartsModule,
|
||||
HistoryTableComponent
|
||||
],
|
||||
selector: 'huapp-aeronefs-bar',
|
||||
templateUrl: './aeronefs-bar.component.html'
|
||||
})
|
||||
export class AeronefsBarComponent implements OnInit, OnDestroy {
|
||||
private _aeronefByImat: Subscription = new Subscription();
|
||||
private _aeronefByYear: Subscription = new Subscription();
|
||||
aeronefByImat!: Array<AeronefByImat>;
|
||||
aeronefByYear!: Array<AeronefByYear>;
|
||||
aeronefByImatCount = 0;
|
||||
aeronefByYearCount = 0;
|
||||
seriesName: string[] = [];
|
||||
seriesValue: any[] = [];
|
||||
seriesColor: string[] = this._dataService.getChartColors();
|
||||
seriesHeader: string[] = [];
|
||||
seriesRow: any[] = [];
|
||||
barChartAeronef: Configuration = chartBar;
|
||||
private _aeronefsByImat!: Array<AeronefByImat>;
|
||||
private _aeronefsByYear!: Array<AeronefByYear>;
|
||||
public title: string = 'Aéronefs';
|
||||
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 displayCharts = false;
|
||||
public chartConfig: BarConfig = this._utilitiesService.getHorizontalBarChartConfig();
|
||||
|
||||
constructor(
|
||||
private aeronefsService: AeronefsService,
|
||||
private _dataService: BackendService
|
||||
private _aeronefsService: AeronefsService,
|
||||
private _utilitiesService: UtilitiesService,
|
||||
public menuItems: MenuItems
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
@@ -42,102 +55,43 @@ export class AeronefsBarComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
private _loadAeronefByImat(): void {
|
||||
const aeronefs$: Observable<Array<AeronefByImat>> = this.aeronefsService.getAllByImat();
|
||||
let values: Array<number> = [];
|
||||
const aeronefs$: Observable<Array<AeronefByImat>> = this._aeronefsService.getAllByImat();
|
||||
this._aeronefByImat = aeronefs$.subscribe((aggregate: Array<AeronefByImat>) => {
|
||||
this.aeronefByImat = aggregate;
|
||||
this.aeronefByImatCount = aggregate.length;
|
||||
this.aeronefByImat.forEach((row) => {
|
||||
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.seriesValue.push(row.count);
|
||||
return row;
|
||||
});
|
||||
this.barChartAeronef = {
|
||||
type: 'Bar',
|
||||
data: {
|
||||
"labels": this.seriesName,
|
||||
"series": this.seriesValue
|
||||
},
|
||||
options: {
|
||||
chartPadding: {
|
||||
top: 15,
|
||||
right: 20,
|
||||
bottom: 0,
|
||||
left: 20
|
||||
},
|
||||
seriesBarDistance: 15,
|
||||
horizontalBars: true,
|
||||
axisX: {
|
||||
onlyInteger: true,
|
||||
position: 'end',
|
||||
labelOffset: {
|
||||
x: 0,
|
||||
y: 0
|
||||
},
|
||||
showGrid: true,
|
||||
offset: 20
|
||||
},
|
||||
axisY: {
|
||||
showGrid: false,
|
||||
offset: 0,
|
||||
labelInterpolationFnc: function(): string {
|
||||
return '';
|
||||
}
|
||||
},
|
||||
height: (this.seriesName.length*20)
|
||||
},
|
||||
responsiveOptions: [
|
||||
['screen and (min-width: 1024px)', {
|
||||
axisX: {
|
||||
labelInterpolationFnc: function(value: number, index: number): string {
|
||||
return index % 1 === 0 ? `${value}` : '';
|
||||
}
|
||||
}
|
||||
}],
|
||||
['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[2]}${value[3]}` : '';
|
||||
}
|
||||
}
|
||||
}],
|
||||
['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]}` : '';
|
||||
}
|
||||
}
|
||||
}]
|
||||
]
|
||||
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 {
|
||||
let values: Array<number> = [];
|
||||
this.seriesHeader = ["2018", "2019", "2020", "2021", "2022", "2023"];
|
||||
this.seriesHeader.forEach(() => {
|
||||
values.push(0);
|
||||
});
|
||||
let 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.getAllByDate();
|
||||
this._aeronefByYear = dropzones$.subscribe((aggregate: Array<AeronefByYear>) => {
|
||||
this.aeronefByYear = aggregate;
|
||||
this.aeronefByYearCount = aggregate.length;
|
||||
this.aeronefByYear.forEach((row: 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();
|
||||
this.seriesRow[this.seriesName.indexOf(`${aeronef} ${imat}`)][this.seriesHeader.indexOf(year)] = row.count;
|
||||
return row;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,36 +1,39 @@
|
||||
<mat-card>
|
||||
<mat-card-content>
|
||||
<mat-card-title>Aéronefs</mat-card-title>
|
||||
<mat-card-subtitle>Nombre total de sauts par avions</mat-card-subtitle>
|
||||
<div class="piechart">
|
||||
<x-chartist [configuration]="donuteAeronefs"></x-chartist>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
<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>
|
||||
<table class="table table-striped table-dark table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th *ngFor='let name of seriesHeader; let i=index' class="text-end"> {{name}} </th>
|
||||
<th class="text-end">Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor='let values of seriesRow; let i=index'>
|
||||
<th class="{{seriesColor[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="{{seriesColor[i]}} text-end">
|
||||
<span *ngIf="seriesValue[i]; else elseBlock" class="pr-1">{{seriesValue[i]}}</span>
|
||||
<ng-template #elseBlock><span class="text-empty pr-1">{{seriesValue[i]}}</span></ng-template>
|
||||
</th>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<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">
|
||||
|
||||
@@ -1,36 +1,50 @@
|
||||
import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Router, RouterLink, RouterModule } from '@angular/router';
|
||||
import { MatBadgeModule } from '@angular/material/badge';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { ChartistModule, Configuration } from 'ng-chartist';
|
||||
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 { BackendService, AeronefsService, UserService } from 'src/app/core/services';
|
||||
import { Aeronef, AeronefByImat, AeronefByYear, chartPieDonute } from 'src/app/core/models';
|
||||
import { MenuItems, HistoryTableComponent } from 'src/app/components/shared';
|
||||
import { UtilitiesService, AeronefsService } from 'src/app/core/services';
|
||||
import { AeronefByImat, AeronefByYear, DoughnutConfig } from 'src/app/core/models';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
imports: [CommonModule, MatCardModule, ChartistModule],
|
||||
imports: [
|
||||
CommonModule, RouterModule,
|
||||
MatBadgeModule, MatButtonModule, MatCardModule, MatExpansionModule, MatIconModule, MatMenuModule,
|
||||
NgChartsModule,
|
||||
HistoryTableComponent
|
||||
],
|
||||
selector: 'huapp-aeronefs',
|
||||
templateUrl: './aeronefs.component.html'
|
||||
})
|
||||
export class AeronefsComponent implements OnInit, OnDestroy {
|
||||
private _aeronefByImat: Subscription = new Subscription();
|
||||
private _aeronefByYear: Subscription = new Subscription();
|
||||
aeronefByImat!: Array<AeronefByImat>;
|
||||
aeronefByYear!: Array<AeronefByYear>;
|
||||
aeronefByImatCount = 0;
|
||||
aeronefByYearCount = 0;
|
||||
rows: Object[] = [] as Array<Object>;
|
||||
seriesName: string[] = [];//= ["Arcachon", "Béni-Mellal", "La Réole", "Royan", "Pamiers", "Soulac", "Sables d'Olonne", "Rochefort"];
|
||||
seriesValue: number[] = [];
|
||||
seriesColor: string[] = this._dataService.getChartColors(); //["blue", "red", "turquoise", "orange", "cyan", "purple-dark", "megna", "raspberry"];
|
||||
seriesHeader: string[] = [];
|
||||
seriesRow: any[] = [];
|
||||
donuteAeronefs: Configuration = chartPieDonute;
|
||||
private _aeronefsByImat!: Array<AeronefByImat>;
|
||||
private _aeronefsByYear!: Array<AeronefByYear>;
|
||||
public title: string = 'Aéronefs';
|
||||
public subtitle: string = 'Nombre total de sauts par aéronef';
|
||||
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();
|
||||
|
||||
constructor(
|
||||
private aeronefsService: AeronefsService,
|
||||
private _dataService: BackendService
|
||||
private router: Router,
|
||||
private _aeronefsService: AeronefsService,
|
||||
private _utilitiesService: UtilitiesService,
|
||||
public menuItems: MenuItems
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
@@ -43,54 +57,34 @@ 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();
|
||||
this._aeronefByImat = aeronefs$.subscribe((aggregate: Array<AeronefByImat>) => {
|
||||
this.aeronefByImat = aggregate;
|
||||
this.aeronefByImatCount = aggregate.length;
|
||||
var labels: string[] = [];
|
||||
var series: number[] = [];
|
||||
this.aeronefByImat.forEach((row) => {
|
||||
this.seriesName.push(`${row._id.aeronef} ${row._id.imat}`);
|
||||
this.seriesValue.push(row.count);
|
||||
labels.push(row.count.toString());
|
||||
series.push(row.count);
|
||||
this._aeronefsByImat = aggregate.map((row: AeronefByImat) => {
|
||||
this.chartConfig.doughnutChartLabels.push(`${row._id.aeronef} ${row._id.imat}`);
|
||||
this.chartConfig.doughnutChartDatasets[0].data.push(row.count);
|
||||
return row;
|
||||
});
|
||||
this.donuteAeronefs = {
|
||||
type: 'Pie',
|
||||
data: {
|
||||
"labels": labels,
|
||||
"series": series
|
||||
},
|
||||
options: {
|
||||
donut: true,
|
||||
height: 260,
|
||||
donutWidth: 50,
|
||||
startAngle: 270,
|
||||
showLabel: true
|
||||
}
|
||||
};
|
||||
this.seriesName = [...this.chartConfig.doughnutChartLabels];
|
||||
this.seriesValue = [...this.chartConfig.doughnutChartDatasets[0].data];
|
||||
this.displayCharts = true;
|
||||
this._loadAeronefByYear();
|
||||
});
|
||||
}
|
||||
|
||||
private _loadAeronefByYear(): void {
|
||||
let values: Array<number> = [];
|
||||
this.seriesHeader = ["2018", "2019", "2020", "2021", "2022", "2023"];
|
||||
this.seriesHeader.forEach(() => {
|
||||
values.push(0);
|
||||
});
|
||||
let 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.getAllByDate();
|
||||
this._aeronefByYear = dropzones$.subscribe((aggregate: Array<AeronefByYear>) => {
|
||||
this.aeronefByYear = aggregate;
|
||||
this.aeronefByYearCount = aggregate.length;
|
||||
this.aeronefByYear.forEach((row: 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();
|
||||
this.seriesRow[this.seriesName.indexOf(`${aeronef} ${imat}`)][this.seriesHeader.indexOf(year)] = row.count;
|
||||
return row;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
+32
-29
@@ -1,34 +1,37 @@
|
||||
<mat-card>
|
||||
<mat-card-content>
|
||||
<mat-card-title>Modèles de voile</mat-card-title>
|
||||
<mat-card-subtitle>Nombre total de sauts par modèle</mat-card-subtitle>
|
||||
<div class="piechart">
|
||||
<x-chartist [configuration]="donuteCanopies"></x-chartist>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
<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>
|
||||
<table class="table table-striped table-dark table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th *ngFor='let name of seriesHeader; let i=index' class="text-end"> {{name}} </th>
|
||||
<th class="text-end">Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="font-monospace">
|
||||
<tr *ngFor='let values of seriesRow; let i=index'>
|
||||
<th class="{{seriesColor[i]}} text-end"> ● {{seriesName[i]}} </th>
|
||||
<td *ngFor='let value of values; let i=index' class="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="{{seriesColor[i]}} text-end">
|
||||
<span *ngIf="seriesValue[i]; else elseBlock" class="pr-1">{{seriesValue[i]}}</span>
|
||||
<ng-template #elseBlock><span class="text-empty pr-1">{{seriesValue[i]}}</span></ng-template>
|
||||
</th>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<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>
|
||||
|
||||
+40
-49
@@ -1,37 +1,48 @@
|
||||
import { Component, OnInit, OnDestroy} from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { ChartistModule, Configuration } from 'ng-chartist';
|
||||
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 { BackendService, CanopiesService } from 'src/app/core/services';
|
||||
import { Canopy, CanopyModelBySize, CanopyModelByYear, chartPieDonute } from 'src/app/core/models';
|
||||
import { MenuItems, HistoryTableComponent } from 'src/app/components/shared';
|
||||
import { UtilitiesService, CanopiesService } from 'src/app/core/services';
|
||||
import { CanopyModelBySize, CanopyModelByYear, DoughnutConfig } from 'src/app/core/models';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
imports: [CommonModule, MatCardModule, ChartistModule],
|
||||
imports: [
|
||||
CommonModule,
|
||||
MatButtonModule, MatCardModule, MatExpansionModule, MatIconModule, MatMenuModule,
|
||||
NgChartsModule,
|
||||
HistoryTableComponent
|
||||
],
|
||||
selector: 'huapp-canopy-models',
|
||||
templateUrl: './canopy-models.component.html'
|
||||
})
|
||||
export class CanopyModelsComponent implements OnInit, OnDestroy {
|
||||
private _canopyBySize: Subscription = new Subscription();
|
||||
private _canopyByYear: Subscription = new Subscription();
|
||||
canopyBySize!: Array<CanopyModelBySize>;
|
||||
canopyByYear!: Array<CanopyModelByYear>;
|
||||
canopyBySizeCount = 0;
|
||||
canopyByYearCount = 0;
|
||||
rows: Object[] = [] as Array<Object>;
|
||||
seriesName: string[] = [];
|
||||
seriesValue: number[] = [];
|
||||
seriesColor: string[] = this._dataService.getChartColors();
|
||||
seriesHeader: string[] = [];
|
||||
seriesRow: any[] = [];
|
||||
donuteCanopies: Configuration = chartPieDonute;
|
||||
private _canopiesBySize!: Array<CanopyModelBySize>;
|
||||
private _canopiesByYear!: Array<CanopyModelByYear>;
|
||||
public title: string = 'Modèles de voile';
|
||||
public subtitle: string = 'Nombre total de sauts par modèle';
|
||||
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();
|
||||
|
||||
constructor(
|
||||
private canopiesService: CanopiesService,
|
||||
private _dataService: BackendService
|
||||
private _canopiesService: CanopiesService,
|
||||
private _utilitiesService: UtilitiesService,
|
||||
public menuItems: MenuItems
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
@@ -44,54 +55,34 @@ export class CanopyModelsComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
private _loadCanopyModelBySize(): void {
|
||||
const canopies$: Observable<Array<CanopyModelBySize>> = this.canopiesService.getAllModelBySize();
|
||||
const canopies$: Observable<Array<CanopyModelBySize>> = this._canopiesService.getAllModelBySize();
|
||||
this._canopyBySize = canopies$.subscribe((aggregate: Array<CanopyModelBySize>) => {
|
||||
this.canopyBySize = aggregate;
|
||||
this.canopyBySizeCount = aggregate.length;
|
||||
var labels: string[] = [];
|
||||
var series: number[] = [];
|
||||
this.canopyBySize.forEach((row) => {
|
||||
this.seriesName.push(`${row._id.taille.toString()} - ${row._id.voile}`);
|
||||
this.seriesValue.push(row.count);
|
||||
labels.push(row.count.toString());
|
||||
series.push(row.count);
|
||||
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);
|
||||
return row;
|
||||
});
|
||||
this.donuteCanopies = {
|
||||
type: 'Pie',
|
||||
data: {
|
||||
"labels": labels,
|
||||
"series": series
|
||||
},
|
||||
options: {
|
||||
donut: true,
|
||||
height: 260,
|
||||
donutWidth: 50,
|
||||
startAngle: 270,
|
||||
showLabel: true
|
||||
}
|
||||
};
|
||||
this.seriesName = [...this.chartConfig.doughnutChartLabels];
|
||||
this.seriesValue = [...this.chartConfig.doughnutChartDatasets[0].data];
|
||||
this.displayCharts = true;
|
||||
this._loadCanopyModelByYear();
|
||||
});
|
||||
}
|
||||
|
||||
private _loadCanopyModelByYear(): void {
|
||||
let values: Array<number> = [];
|
||||
this.seriesHeader = ["2018", "2019", "2020", "2021", "2022", "2023"];
|
||||
this.seriesHeader.forEach(() => {
|
||||
values.push(0);
|
||||
});
|
||||
let 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.getAllModelByYear();
|
||||
this._canopyByYear = dropzones$.subscribe((aggregate: Array<CanopyModelByYear>) => {
|
||||
this.canopyByYear = aggregate;
|
||||
this.canopyByYearCount = aggregate.length;
|
||||
this.canopyByYear.forEach((row: 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();
|
||||
this.seriesRow[this.seriesName.indexOf(`${taille} - ${voile}`)][this.seriesHeader.indexOf(year)] = row.count;
|
||||
return row;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
+39
-36
@@ -1,41 +1,44 @@
|
||||
<mat-card>
|
||||
<mat-card-content>
|
||||
<mat-card-title>Taille de voile</mat-card-title>
|
||||
<mat-card-subtitle>Nombre total de sauts par taille</mat-card-subtitle>
|
||||
<div class="piechart">
|
||||
<x-chartist [configuration]="donuteCanopiesSize"></x-chartist>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
<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>
|
||||
<table class="table table-striped table-dark table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th *ngFor='let name of seriesHeader; let i=index' class="text-end"> {{name}} </th>
|
||||
<th class="text-end">Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="font-monospace">
|
||||
<tr *ngFor='let values of seriesRow; let i=index'>
|
||||
<th class="{{seriesColor[i]}} text-end"> ● {{seriesName[i]}} </th>
|
||||
<td *ngFor='let value of values; let i=index' class="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="{{seriesColor[i]}} text-end">
|
||||
<span *ngIf="seriesValue[i]; else elseBlock" class="pr-1">{{seriesValue[i]}}</span>
|
||||
<ng-template #elseBlock><span class="text-empty pr-1">{{seriesValue[i]}}</span></ng-template>
|
||||
</th>
|
||||
</tr>
|
||||
</tbody>
|
||||
</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>-->
|
||||
<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>
|
||||
|
||||
+40
-49
@@ -1,37 +1,48 @@
|
||||
import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { ChartistModule, Configuration } from 'ng-chartist';
|
||||
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 { BackendService, CanopiesService } from 'src/app/core/services';
|
||||
import { chartPieDonute, CanopyBySize, CanopyByYear, ReduceRow } from 'src/app/core/models';
|
||||
import { MenuItems, HistoryTableComponent } from 'src/app/components/shared';
|
||||
import { UtilitiesService, CanopiesService } from 'src/app/core/services';
|
||||
import { CanopyBySize, CanopyByYear, DoughnutConfig } from 'src/app/core/models';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
imports: [CommonModule, MatCardModule, ChartistModule],
|
||||
imports: [
|
||||
CommonModule,
|
||||
MatButtonModule, MatCardModule, MatExpansionModule, MatIconModule, MatMenuModule,
|
||||
NgChartsModule,
|
||||
HistoryTableComponent
|
||||
],
|
||||
selector: 'huapp-canopy-sizes',
|
||||
templateUrl: './canopy-sizes.component.html'
|
||||
})
|
||||
export class CanopySizesComponent implements OnInit, OnDestroy {
|
||||
private _canopyBySize: Subscription = new Subscription();
|
||||
private _canopyByYear: Subscription = new Subscription();
|
||||
canopyBySize!: Array<CanopyBySize>;
|
||||
canopyByYear!: Array<CanopyByYear>;
|
||||
canopyBySizeCount = 0;
|
||||
canopyByYearCount = 0;
|
||||
rows: Object[] = [] as Array<Object>;
|
||||
seriesName: string[] = [];
|
||||
seriesValue: number[] = [];
|
||||
seriesColor: string[] = this._dataService.getChartColors();
|
||||
seriesHeader: string[] = [];
|
||||
seriesRow: any[] = [];
|
||||
donuteCanopiesSize: Configuration = chartPieDonute;
|
||||
private _canopiesBySize!: Array<CanopyBySize>;
|
||||
private _canopiesByYear!: Array<CanopyByYear>;
|
||||
public title: string = 'Tailles de voile';
|
||||
public subtitle: string = 'Nombre total de sauts par taille';
|
||||
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();
|
||||
|
||||
constructor(
|
||||
private canopiesService: CanopiesService,
|
||||
private _dataService: BackendService
|
||||
private _canopiesService: CanopiesService,
|
||||
private _utilitiesService: UtilitiesService,
|
||||
public menuItems: MenuItems
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
@@ -44,53 +55,33 @@ 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();
|
||||
this._canopyBySize = canopies$.subscribe((aggregate: Array<CanopyBySize>) => {
|
||||
this.canopyBySize = aggregate;
|
||||
this.canopyBySizeCount = aggregate.length;
|
||||
var labels: string[] = [];
|
||||
var series: number[] = [];
|
||||
this.canopyBySize.forEach((row) => {
|
||||
this.seriesName.push(row._id.taille.toString());
|
||||
this.seriesValue.push(row.count);
|
||||
labels.push(row.count.toString());
|
||||
series.push(row.count);
|
||||
this._canopiesBySize = aggregate.map((row: CanopyBySize) => {
|
||||
this.chartConfig.doughnutChartLabels.push(row._id.taille.toString());
|
||||
this.chartConfig.doughnutChartDatasets[0].data.push(row.count);
|
||||
return row;
|
||||
});
|
||||
this.donuteCanopiesSize = {
|
||||
type: 'Pie',
|
||||
data: {
|
||||
"labels": labels,
|
||||
"series": series
|
||||
},
|
||||
options: {
|
||||
donut: true,
|
||||
height: 260,
|
||||
donutWidth: 40,
|
||||
startAngle: 330,
|
||||
showLabel: true
|
||||
}
|
||||
};
|
||||
this.seriesName = [...this.chartConfig.doughnutChartLabels];
|
||||
this.seriesValue = [...this.chartConfig.doughnutChartDatasets[0].data];
|
||||
this.displayCharts = true;
|
||||
this._loadCanopyByYear();
|
||||
});
|
||||
}
|
||||
|
||||
private _loadCanopyByYear(): void {
|
||||
let values: Array<number> = [];
|
||||
this.seriesHeader = ["2018", "2019", "2020", "2021", "2022", "2023"];
|
||||
this.seriesHeader.forEach(() => {
|
||||
values.push(0);
|
||||
});
|
||||
let 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.getAllByYear();
|
||||
this._canopyByYear = dropzones$.subscribe((aggregate: Array<CanopyByYear>) => {
|
||||
this.canopyByYear = aggregate;
|
||||
this.canopyByYearCount = aggregate.length;
|
||||
this.canopyByYear.forEach((row: CanopyByYear) => {
|
||||
this._canopiesByYear = aggregate.map((row: CanopyByYear) => {
|
||||
let taille: string = row._id.taille.toString();
|
||||
let year: string = row._id.year.toString();
|
||||
this.seriesRow[this.seriesName.indexOf(taille)][this.seriesHeader.indexOf(year)] = row.count;
|
||||
return row;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
+25
-19
@@ -1,25 +1,31 @@
|
||||
<mat-card>
|
||||
<mat-card-content>
|
||||
<mat-card-title>Les drop zones</mat-card-title>
|
||||
<mat-card-subtitle>Nombre total de sauts par DZ</mat-card-subtitle>
|
||||
<div class="piechart">
|
||||
<x-chartist [configuration]="donuteDropZones"></x-chartist>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
<hr>
|
||||
<mat-card-content class="mb-1">
|
||||
<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="33" fxFlex.gt-md="50" fxFlex.gt-sm="100" fxFlex.gt-xs="25" fxFlex="100">
|
||||
<i class="mdi mdi-checkbox-blank-circle font-10 m-r-10 "></i>{{name}} : {{seriesValue[i]}}
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
<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 class="barchrt bar-xs">
|
||||
<x-chartist [configuration]="barChartDropZones"> </x-chartist>
|
||||
<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>
|
||||
|
||||
+42
-53
@@ -1,39 +1,50 @@
|
||||
import { Component, OnInit, OnDestroy, Input, Output } from '@angular/core';
|
||||
import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
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 { ChartistModule, Configuration } from 'ng-chartist';
|
||||
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
|
||||
import { BackendService, DropZonesService } from 'src/app/core/services';
|
||||
import { chartBar, chartPieDonute, DropZone, DropZoneByOaci, DropZoneByYear } from 'src/app/core/models';
|
||||
import { MenuItems, HistoryTableComponent } from 'src/app/components/shared';
|
||||
import { UtilitiesService, DropZonesService } from 'src/app/core/services';
|
||||
import { DropZoneByOaci, DropZoneByYear } from 'src/app/core/models';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
imports: [CommonModule, MatCardModule, ChartistModule],
|
||||
imports: [
|
||||
CommonModule,
|
||||
MatButtonModule, MatCardModule, MatExpansionModule, MatIconModule, MatMenuModule,
|
||||
NgChartsModule, ChartistModule,
|
||||
HistoryTableComponent
|
||||
],
|
||||
selector: 'huapp-drop-zones-bar',
|
||||
templateUrl: './drop-zones-bar.component.html'
|
||||
})
|
||||
export class DropZonesBarComponent implements OnInit, OnDestroy {
|
||||
private _dropzoneByOaci: Subscription = new Subscription();
|
||||
private _dropzoneByYear: Subscription = new Subscription();
|
||||
dropzoneByOaci!: Array<DropZoneByOaci>;
|
||||
dropzoneByYear!: Array<DropZoneByYear>;
|
||||
dropzoneByOaciCount = 0;
|
||||
dropzoneByYearCount = 0;
|
||||
dropzones: Object[] = [] as Array<Object>;
|
||||
seriesName: string[] = [];
|
||||
seriesValue: number[] = [];
|
||||
seriesColor: string[] = this._dataService.getChartColors();
|
||||
seriesHeader: string[] = [];
|
||||
seriesRow: any[] = [];
|
||||
donuteDropZones: Configuration = chartPieDonute;
|
||||
barChartDropZones: Configuration = chartBar;
|
||||
private _dropzonesByOaci!: Array<DropZoneByOaci>;
|
||||
private _dropzonesByYear!: Array<DropZoneByYear>;
|
||||
public title: string = 'Les dropzones';
|
||||
public subtitle: string = 'Nombre total de sauts par dropzone';
|
||||
public seriesHeader: string[] = [];
|
||||
public seriesName: string[] = [];
|
||||
public seriesValue: number[] = [];
|
||||
public seriesRow: any[] = [];
|
||||
public seriesColor: string[] = this._utilitiesService.getChartColors();
|
||||
public displayCharts = false;
|
||||
public barChartDropZones: Configuration = this._utilitiesService.getBarConfig();
|
||||
|
||||
constructor(
|
||||
private dropzonesService: DropZonesService,
|
||||
private _dataService: BackendService
|
||||
) { }
|
||||
private _dropzonesService: DropZonesService,
|
||||
private _utilitiesService: UtilitiesService,
|
||||
public menuItems: MenuItems
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
this._loadDropZoneByOaci();
|
||||
@@ -45,54 +56,31 @@ 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();
|
||||
this._dropzoneByOaci = dropzones$.subscribe((aggregate: Array<DropZoneByOaci>) => {
|
||||
this.dropzoneByOaci = aggregate;
|
||||
this.dropzoneByOaciCount = aggregate.length;
|
||||
var labels: string[] = [];
|
||||
var series: number[] = [];
|
||||
this.dropzoneByOaci.forEach((row) => {
|
||||
this._dropzonesByOaci = aggregate.map((row: DropZoneByOaci) => {
|
||||
this.seriesName.push(`${row._id.oaci} - ${row._id.lieu}`);
|
||||
this.seriesValue.push(row.count);
|
||||
labels.push(row.count.toString());
|
||||
series.push(row.count);
|
||||
return row;
|
||||
});
|
||||
this.donuteDropZones = {
|
||||
type: 'Pie',
|
||||
data: {
|
||||
"labels": labels,
|
||||
"series": series
|
||||
},
|
||||
options: {
|
||||
donut: true,
|
||||
height: 260,
|
||||
donutWidth: 50,
|
||||
startAngle: 270,
|
||||
showLabel: true
|
||||
}
|
||||
};
|
||||
this._loadDropZoneByYear();
|
||||
});
|
||||
}
|
||||
|
||||
private _loadDropZoneByYear(): void {
|
||||
let values: Array<number> = [];
|
||||
this.seriesHeader = ["2018", "2019", "2020", "2021", "2022", "2023"];
|
||||
this.seriesHeader.forEach(() => {
|
||||
values.push(0);
|
||||
});
|
||||
let 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.getAllByDate();
|
||||
this._dropzoneByYear = dropzones$.subscribe((aggregate: Array<DropZoneByYear>) => {
|
||||
this.dropzoneByYear = aggregate;
|
||||
this.dropzoneByYearCount = aggregate.length;
|
||||
this.dropzoneByYear.forEach((row: 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();
|
||||
this.seriesRow[this.seriesName.indexOf(`${oaci} - ${lieu}`)][this.seriesHeader.indexOf(year)] = row.count;
|
||||
return row;
|
||||
});
|
||||
this.barChartDropZones = {
|
||||
type: 'Bar',
|
||||
@@ -101,9 +89,9 @@ export class DropZonesBarComponent implements OnInit, OnDestroy {
|
||||
"series": this.seriesRow
|
||||
},
|
||||
options: {
|
||||
seriesBarDistance: 9,
|
||||
horizontalBars: true,
|
||||
high: 170,
|
||||
seriesBarDistance: 15,
|
||||
horizontalBars: false,
|
||||
high: 180,
|
||||
axisX: {
|
||||
showGrid: false,
|
||||
offset: 20
|
||||
@@ -112,7 +100,7 @@ export class DropZonesBarComponent implements OnInit, OnDestroy {
|
||||
showGrid: true,
|
||||
offset: 40
|
||||
},
|
||||
height: 207
|
||||
height: 300
|
||||
},
|
||||
responsiveOptions: [
|
||||
['screen and (min-width: 1024px)', {
|
||||
@@ -146,6 +134,7 @@ export class DropZonesBarComponent implements OnInit, OnDestroy {
|
||||
}]
|
||||
]
|
||||
};
|
||||
this.displayCharts = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,34 +1,37 @@
|
||||
<mat-card>
|
||||
<mat-card-content>
|
||||
<mat-card-title>Les drop zones</mat-card-title>
|
||||
<mat-card-subtitle>Nombre total de sauts par DZ</mat-card-subtitle>
|
||||
<div class="piechart">
|
||||
<x-chartist [configuration]="donuteDropZones"></x-chartist>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
<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>
|
||||
<table class="table table-striped table-dark table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th *ngFor='let name of seriesHeader; let i=index' class="text-end"> {{name}} </th>
|
||||
<th class="text-end">Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="font-monospace">
|
||||
<tr *ngFor='let values of seriesRow; let i=index'>
|
||||
<th class="{{seriesColor[i]}} text-end"> ✹ {{seriesName[i]}} </th>
|
||||
<td *ngFor='let value of values; let i=index' class="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="{{seriesColor[i]}} text-end">
|
||||
<span *ngIf="seriesValue[i]; else elseBlock" class="pr-1">{{seriesValue[i]}}</span>
|
||||
<ng-template #elseBlock><span class="text-empty pr-1">{{seriesValue[i]}}</span></ng-template>
|
||||
</th>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<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>
|
||||
|
||||
@@ -1,37 +1,50 @@
|
||||
import { Component, OnInit, OnDestroy, Input, Output } from '@angular/core';
|
||||
import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { ChartistModule, Configuration } from 'ng-chartist';
|
||||
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 { Observable, Subscription } from 'rxjs';
|
||||
|
||||
import { BackendService, DropZonesService } from 'src/app/core/services';
|
||||
import { DropZoneByOaci, DropZoneByYear, chartPieDonute} from 'src/app/core/models';
|
||||
import { MenuItems, HistoryTableComponent } from 'src/app/components/shared';
|
||||
import { UtilitiesService, DropZonesService } from 'src/app/core/services';
|
||||
import { DropZoneByOaci, DropZoneByYear, DoughnutConfig } from 'src/app/core/models';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
imports: [CommonModule, MatCardModule, ChartistModule],
|
||||
imports: [
|
||||
CommonModule,
|
||||
MatButtonModule, MatCardModule, MatExpansionModule, MatIconModule, MatMenuModule,
|
||||
NgChartsModule,
|
||||
HistoryTableComponent
|
||||
],
|
||||
selector: 'huapp-drop-zones',
|
||||
templateUrl: './drop-zones.component.html'
|
||||
})
|
||||
export class DropZonesComponent implements OnInit, OnDestroy {
|
||||
private _dropzoneByOaci: Subscription = new Subscription();
|
||||
private _dropzoneByYear: Subscription = new Subscription();
|
||||
dropzoneByOaci!: Array<DropZoneByOaci>;
|
||||
dropzoneByYear!: Array<DropZoneByYear>;
|
||||
dropzoneByOaciCount = 0;
|
||||
dropzoneByYearCount = 0;
|
||||
seriesName: string[] = [];
|
||||
seriesValue: number[] = [];
|
||||
seriesColor: string[] = this._dataService.getChartColors();
|
||||
seriesHeader: string[] = [];
|
||||
seriesRow: any[] = [];
|
||||
donuteDropZones: Configuration = chartPieDonute;
|
||||
private _dropzonesByOaci!: Array<DropZoneByOaci>;
|
||||
private _dropzonesByYear!: Array<DropZoneByYear>;
|
||||
public title: string = 'Les dropzones';
|
||||
public subtitle: string = 'Nombre total de sauts par dropzone';
|
||||
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();
|
||||
|
||||
constructor(
|
||||
private dropzonesService: DropZonesService,
|
||||
private _dataService: BackendService
|
||||
) { }
|
||||
private _dropzonesService: DropZonesService,
|
||||
private _utilitiesService: UtilitiesService,
|
||||
public menuItems: MenuItems
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
this._loadDropZoneByOaci();
|
||||
@@ -43,54 +56,34 @@ 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();
|
||||
this._dropzoneByOaci = dropzones$.subscribe((aggregate: Array<DropZoneByOaci>) => {
|
||||
this.dropzoneByOaci = aggregate;
|
||||
this.dropzoneByOaciCount = aggregate.length;
|
||||
var labels: string[] = [];
|
||||
var series: number[] = [];
|
||||
this.dropzoneByOaci.forEach((row) => {
|
||||
this.seriesName.push(`${row._id.oaci} - ${row._id.lieu}`);
|
||||
this.seriesValue.push(row.count);
|
||||
labels.push(row.count.toString());
|
||||
series.push(row.count);
|
||||
this._dropzonesByOaci = aggregate.map((row: DropZoneByOaci) => {
|
||||
this.chartConfig.doughnutChartLabels.push(`${row._id.oaci} - ${row._id.lieu}`);
|
||||
this.chartConfig.doughnutChartDatasets[0].data.push(row.count);
|
||||
return row;
|
||||
});
|
||||
this.donuteDropZones = {
|
||||
type: 'Pie',
|
||||
data: {
|
||||
"labels": labels,
|
||||
"series": series
|
||||
},
|
||||
options: {
|
||||
donut: true,
|
||||
height: 260,
|
||||
donutWidth: 50,
|
||||
startAngle: 270,
|
||||
showLabel: true
|
||||
}
|
||||
};
|
||||
this.seriesName = [...this.chartConfig.doughnutChartLabels];
|
||||
this.seriesValue = [...this.chartConfig.doughnutChartDatasets[0].data];
|
||||
this.displayCharts = true;
|
||||
this._loadDropZoneByYear();
|
||||
});
|
||||
}
|
||||
|
||||
private _loadDropZoneByYear(): void {
|
||||
let values: Array<number> = [];
|
||||
this.seriesHeader = ["2018", "2019", "2020", "2021", "2022", "2023"];
|
||||
this.seriesHeader.forEach(() => {
|
||||
values.push(0);
|
||||
});
|
||||
let 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.getAllByDate();
|
||||
this._dropzoneByYear = dropzones$.subscribe((aggregate: Array<DropZoneByYear>) => {
|
||||
this.dropzoneByYear = aggregate;
|
||||
this.dropzoneByYearCount = aggregate.length;
|
||||
this.dropzoneByYear.forEach((row: 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();
|
||||
this.seriesRow[this.seriesName.indexOf(`${oaci} - ${lieu}`)][this.seriesHeader.indexOf(year)] = row.count;
|
||||
return row;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
+59
-46
@@ -1,19 +1,22 @@
|
||||
<mat-card>
|
||||
<mat-card-content class="mb-0">
|
||||
<div class="d-flex flex-wrap">
|
||||
<div>
|
||||
<mat-card-title>Volume mensuel</mat-card-title>
|
||||
<mat-card-subtitle>Nombre total de sauts par mois de {{min}} à {{max}}</mat-card-subtitle>
|
||||
</div>
|
||||
</div>
|
||||
<div class="barchrt">
|
||||
<x-chartist [configuration]="barChartJumps"></x-chartist>
|
||||
<!--
|
||||
<x-chartist class="" [data]="barChartJumps.data" [type]="barChartJumps.type" [options]="barChartJumps.options" [responsiveOptions]="barChartJumps.responsiveOptions"
|
||||
[events]="barChartJumps.events"> </x-chartist>
|
||||
-->
|
||||
</div>
|
||||
<div class="text-center my-3">
|
||||
<mat-card-header>
|
||||
<mat-card-title>{{ title }}</mat-card-title>
|
||||
<mat-card-subtitle>{{ subtitle }} de {{min}} à {{max}}</mat-card-subtitle>
|
||||
<span class="flex-spacer"></span>
|
||||
<button mat-icon-button [matMenuTriggerFor]="menuJumpBar" aria-label="Menu Dropzone Bar">
|
||||
<mat-icon fontIcon="more_vert"></mat-icon>
|
||||
</button>
|
||||
<mat-menu #menuJumpBar="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 class="text-center mb-3">
|
||||
<ul class="list-inline my-0">
|
||||
<li *ngFor='let name of seriesName; let i=index' class="list-inline-item me-lg-3 me-sm-2">
|
||||
<span class="{{seriesColor[i]}} fs-6 m-0">
|
||||
@@ -22,36 +25,46 @@
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
-->
|
||||
<div *ngIf="displayCharts" class="barchart position-relative w-100 my-1">
|
||||
<x-chartist [configuration]="barChartJumps"></x-chartist>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
<mat-card-content class="pt-0">
|
||||
<table class="table table-striped table-dark table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th *ngFor='let name of seriesHeader; let i=index' class="text-end"> {{name}} </th>
|
||||
<th class="text-end">Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor='let values of seriesRow; let i=index'>
|
||||
<th class="{{seriesColor[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>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th class="text-end">Total</th>
|
||||
<th *ngFor='let value of seriesColTotal; 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>
|
||||
</th>
|
||||
<th class="font-monospace text-end">{{grandTotal}}</th>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</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>
|
||||
<table class="table table-striped table-dark table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th *ngFor='let name of seriesHeader; let i=index' class="text-end"> {{name}} </th>
|
||||
<th class="text-end">Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor='let values of seriesRow; let i=index'>
|
||||
<th class="{{seriesColor[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>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th class="text-end">Total</th>
|
||||
<th *ngFor='let value of seriesColTotal; 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>
|
||||
</th>
|
||||
<th class="font-monospace text-end">{{grandTotal}}</th>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</mat-expansion-panel>
|
||||
</mat-accordion>
|
||||
</mat-card>
|
||||
|
||||
+39
-32
@@ -1,42 +1,51 @@
|
||||
import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
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 { Observable, Subscription } from 'rxjs';
|
||||
|
||||
import { BackendService, JumpsService } from 'src/app/core/services';
|
||||
import { chartBar, JumpByDate, ReduceRow } from 'src/app/core/models';
|
||||
|
||||
declare var require: any;
|
||||
const data= require('./data.json');
|
||||
import { MenuItems } from 'src/app/components/shared';
|
||||
import { UtilitiesService, JumpsService } from 'src/app/core/services';
|
||||
import { JumpByDate } from 'src/app/core/models';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
imports: [CommonModule, MatCardModule, ChartistModule],
|
||||
imports: [
|
||||
CommonModule,
|
||||
MatButtonModule, MatCardModule, MatExpansionModule, MatIconModule, MatMenuModule,
|
||||
ChartistModule
|
||||
],
|
||||
selector: 'huapp-jumps-by-month',
|
||||
templateUrl: './jumps-by-month.component.html'
|
||||
})
|
||||
export class JumpsByMonthComponent implements OnInit, OnDestroy {
|
||||
private _jumpByDate: Subscription = new Subscription();
|
||||
jumpByDate!: Array<JumpByDate>;
|
||||
jumpByDateCount = 0;
|
||||
rows: Object[] = [] as Array<Object>;
|
||||
min: number = 0;
|
||||
max: number = 0;
|
||||
grandTotal: number = 0;
|
||||
seriesHeader: string[] = ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"];
|
||||
seriesRow: any[] = [];
|
||||
seriesRowTotal: number[] = [];
|
||||
seriesColTotal: number[] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||
seriesName: String[] = []; // ["2018", "2019", "2020", "2021", "2022", "2023"];
|
||||
seriesColor: String[] = this._dataService.getChartColors();
|
||||
barChartJumps: Configuration = chartBar;
|
||||
private _jumpsByDate!: Array<JumpByDate>;
|
||||
private _jumpsByDateCount = 0;
|
||||
public title: string = 'Volume mensuel';
|
||||
public subtitle: string = 'Nombre total de sauts par mois';
|
||||
public min = 0;
|
||||
public max = 0;
|
||||
public grandTotal = 0;
|
||||
public seriesHeader: string[] = [];
|
||||
public seriesName: String[] = [];
|
||||
public seriesRow: any[] = [];
|
||||
public seriesColor: String[] = this._utilitiesService.getChartColors();
|
||||
public seriesRowTotal: number[] = [];
|
||||
public seriesColTotal: number[] = [];
|
||||
public displayCharts = false;
|
||||
public barChartJumps: Configuration = this._utilitiesService.getBarConfig();
|
||||
|
||||
constructor(
|
||||
private jumpsService: JumpsService,
|
||||
private _dataService: BackendService
|
||||
) { }
|
||||
private _jumpsService: JumpsService,
|
||||
private _utilitiesService: UtilitiesService,
|
||||
public menuItems: MenuItems
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
this._loadJumpByDate();
|
||||
@@ -47,17 +56,13 @@ export class JumpsByMonthComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
private _loadJumpByDate() {
|
||||
let values: Array<number> = [];
|
||||
this.seriesHeader.forEach(() => {
|
||||
values.push(0);
|
||||
});
|
||||
const jumps$: Observable<Array<JumpByDate>> = this.jumpsService.getAllByDate();
|
||||
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.seriesColTotal = [...values];
|
||||
const jumps$: Observable<Array<JumpByDate>> = this._jumpsService.getAllByDate();
|
||||
this._jumpByDate = jumps$.subscribe((aggregate: Array<JumpByDate>) => {
|
||||
this.jumpByDate = aggregate;
|
||||
this.jumpByDateCount = aggregate.length;
|
||||
console.log(this.jumpByDate);
|
||||
console.log(this.jumpByDateCount);
|
||||
this.jumpByDate.forEach((row) => {
|
||||
this._jumpsByDateCount = aggregate.length;
|
||||
this._jumpsByDate = aggregate.map((row: JumpByDate) => {
|
||||
let year = row._id.year.toString();
|
||||
let month = row._id.month;
|
||||
if (this.seriesName.indexOf(year) < 0) {
|
||||
@@ -72,6 +77,7 @@ export class JumpsByMonthComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
this.seriesRow[(this.seriesRow.length-1)][(month-1)] = row.count;
|
||||
this.seriesColTotal[(month-1)] += row.count;
|
||||
return row;
|
||||
});
|
||||
this.seriesRow.forEach((row: number[]) => {
|
||||
const total = row.reduce((partialSum, a) => partialSum + a, 0);
|
||||
@@ -129,6 +135,7 @@ export class JumpsByMonthComponent implements OnInit, OnDestroy {
|
||||
}]
|
||||
]
|
||||
};
|
||||
this.displayCharts = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,50 +1,33 @@
|
||||
<div class="content">
|
||||
<h1>{{title}}</h1>
|
||||
<div *appShowAuthed="true">
|
||||
Connected
|
||||
</div>
|
||||
<div *appShowAuthed="false">
|
||||
Not connected
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-8 col-sm-12">
|
||||
<huapp-jumps-by-month></huapp-jumps-by-month>
|
||||
<hr />
|
||||
<ng-container *appShowAuthed="true">
|
||||
<div class="row">
|
||||
<div class="col-md-8 col-sm-12">
|
||||
<huapp-jumps-by-month></huapp-jumps-by-month>
|
||||
</div>
|
||||
<div class="col-md-4 col-sm-12">
|
||||
<huapp-drop-zones></huapp-drop-zones>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4 col-sm-12">
|
||||
<huapp-drop-zones></huapp-drop-zones>
|
||||
<div class="row mt-sm-2 mt-lg-3">
|
||||
<div class="col-lg-3 col-md-4 col-sm-6 col-xs-12">
|
||||
<huapp-canopy-sizes></huapp-canopy-sizes>
|
||||
</div>
|
||||
<div class="col-lg-3 col-md-4 col-sm-6 col-xs-12">
|
||||
<huapp-canopy-models></huapp-canopy-models>
|
||||
<br />
|
||||
<huapp-aeronefs></huapp-aeronefs>
|
||||
</div>
|
||||
<div class="col-lg-6 col-md-4 col-sm-6 col-xs-12">
|
||||
<huapp-aeronefs-bar></huapp-aeronefs-bar>
|
||||
<br />
|
||||
<huapp-drop-zones-bar></huapp-drop-zones-bar>
|
||||
</div>
|
||||
<div class="col-lg-3 col-md-4 col-sm-6 col-xs-12">
|
||||
</div>
|
||||
<div class="col-lg-3 col-md-4 col-sm-6 col-xs-12">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-sm-2 mt-lg-3">
|
||||
<div class="col-lg-3 col-md-4 col-sm-6 col-xs-12">
|
||||
<huapp-canopy-sizes></huapp-canopy-sizes>
|
||||
</div>
|
||||
<div class="col-lg-3 col-md-4 col-sm-6 col-xs-12">
|
||||
<huapp-canopy-models></huapp-canopy-models>
|
||||
</div>
|
||||
<div class="col-lg-6 col-md-4 col-sm-6 col-xs-12">
|
||||
<huapp-aeronefs-bar></huapp-aeronefs-bar>
|
||||
<!--
|
||||
<huapp-aeronefs></huapp-aeronefs>
|
||||
-->
|
||||
</div>
|
||||
</div>
|
||||
<!--
|
||||
<div fxLayout="row wrap">
|
||||
<div fxFlex.gt-lg="66" fxFlex.gt-md="66" fxFlex.gt-sm="100" fxFlex.gt-xs="100" fxFlex="100">
|
||||
<huapp-jumps-by-month></huapp-jumps-by-month>
|
||||
</div>
|
||||
<div fxFlex.gt-lg="34" fxFlex.gt-md="34" fxFlex.gt-sm="50" fxFlex.gt-xs="100" fxFlex="100">
|
||||
<huapp-drop-zones></huapp-drop-zones>
|
||||
</div>
|
||||
<div fxFlex.gt-lg="30" fxFlex.gt-md="29" fxFlex.gt-sm="50" fxFlex.gt-xs="100" fxFlex="100">
|
||||
<huapp-canopy-sizes></huapp-canopy-sizes>
|
||||
</div>
|
||||
<div fxFlex.gt-lg="30" fxFlex.gt-md="29" fxFlex.gt-sm="50" fxFlex.gt-xs="100" fxFlex="100">
|
||||
<huapp-canopy-models></huapp-canopy-models>
|
||||
</div>
|
||||
<div fxFlex.gt-lg="40" fxFlex.gt-md="42" fxFlex.gt-sm="50" fxFlex.gt-xs="100" fxFlex="100">
|
||||
<huapp-aeronefs-bar></huapp-aeronefs-bar>
|
||||
</div>
|
||||
</div>
|
||||
-->
|
||||
</ng-container>
|
||||
</div>
|
||||
@@ -2,22 +2,22 @@ import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
import { ActivatedRoute, Data, Router } from '@angular/router';
|
||||
|
||||
import { Observable, Observer, Subscription } from 'rxjs';
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
import { take } from 'rxjs/operators';
|
||||
|
||||
import { User, Errors, Aeronef, AeronefByImat, Canopy, CanopyModelBySize, DropZone, DropZoneByYear } from 'src/app/core/models';
|
||||
import { AeronefsService, CanopiesService, DropZonesService, UserService } from 'src/app/core/services';
|
||||
import { ShowAuthedDirective } from 'src/app/components/shared/show-authed.directive';
|
||||
import { AeronefsBarComponent, DropZonesComponent, CanopyModelsComponent, CanopySizesComponent, JumpsByMonthComponent } from './dashboard-components';
|
||||
//import { JumpsByMonthComponent, AeronefsComponent, AeronefsBarComponent, DropZonesComponent, DropZonesBarComponent, CanopySizesComponent, CanopyModelsComponent} from './dashboard-components';
|
||||
import { AeronefsComponent, AeronefsBarComponent, CanopyModelsComponent, CanopySizesComponent, DropZonesComponent, DropZonesBarComponent, JumpsByMonthComponent } from './dashboard-components';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
imports: [
|
||||
ShowAuthedDirective,
|
||||
AeronefsBarComponent, DropZonesComponent, CanopyModelsComponent, CanopySizesComponent, JumpsByMonthComponent
|
||||
//AeronefsComponent, AeronefsBarComponent, DropZonesComponent, DropZonesBarComponent,
|
||||
//CanopySizesComponent, CanopyModelsComponent, JumpsByMonthComponent,
|
||||
AeronefsComponent, AeronefsBarComponent,
|
||||
CanopyModelsComponent, CanopySizesComponent,
|
||||
DropZonesComponent, DropZonesBarComponent,
|
||||
JumpsByMonthComponent
|
||||
],
|
||||
selector: 'huapp-home',
|
||||
templateUrl: './home.component.html',
|
||||
@@ -34,14 +34,13 @@ export class HomeComponent implements OnInit, OnDestroy {
|
||||
isAuthenticated = false;
|
||||
canModify = false;
|
||||
|
||||
aeronefAggregate!: Array<AeronefByImat>
|
||||
aeronefAggregate!: Array<AeronefByImat>;
|
||||
aeronefs!: Array<Aeronef>;
|
||||
aeronefsCount = 0;
|
||||
canopyAggregate!: Array<CanopyModelBySize>
|
||||
canopyAggregate!: Array<CanopyModelBySize>;
|
||||
canopies!: Array<Canopy>;
|
||||
canopiesCount = 0;
|
||||
//dropzoneAggregate!: Array<DropZoneByOaci>
|
||||
dropzoneAggregate!: Array<DropZoneByYear>
|
||||
dropzoneAggregate!: Array<DropZoneByYear>; // Array<DropZoneByOaci>
|
||||
dropzones!: Array<DropZone>;
|
||||
dropzonesCount = 0;
|
||||
|
||||
@@ -59,9 +58,8 @@ export class HomeComponent implements OnInit, OnDestroy {
|
||||
|
||||
ngOnInit() {
|
||||
this.titleService.setTitle(this.title);
|
||||
const data$: Observable<any> = this.route.data.pipe(take(1));
|
||||
const data$: Observable<Data> = this.route.data.pipe(take(1));
|
||||
this._data = data$.subscribe((data: Data) => {
|
||||
//data: Partial<Observer<Data>>
|
||||
this.isAuthenticated = data['isAuthenticated'];
|
||||
if (!this.isAuthenticated) {
|
||||
this.router.navigateByUrl('/login');
|
||||
|
||||
@@ -1,7 +1,37 @@
|
||||
<div class="content">
|
||||
<h1>{{title}}</h1>
|
||||
<!---->
|
||||
<huapp-jump-table #jumpTable [refresh]="refreshInterval" [config]="listConfig" [isUser]="isUser" [showAdd]="canModify" [title]="listTitle">
|
||||
</huapp-jump-table>
|
||||
<!---->
|
||||
<mat-card>
|
||||
<mat-card-header class="bg-accent rounded-top py-3 px-4">
|
||||
<mat-card-title>
|
||||
{{ title }} <span class="fs-5" [hidden]="!lastjump.numero">({{ lastjump.numero }})</span>
|
||||
</mat-card-title>
|
||||
<mat-card-subtitle>
|
||||
<span [hidden]="!lastjump.numero" class="me-2 fst-italic">
|
||||
Dernier saut enregistré : # {{ lastjump.numero }} le {{ lastjump.date | date: 'dd/MM/yyyy' }} à {{ lastjump.lieu }}
|
||||
</span>
|
||||
</mat-card-subtitle>
|
||||
<span class="flex-spacer"></span>
|
||||
<button mat-icon-button (click)="openAddDialog()" aria-label="Ajouter">
|
||||
<mat-icon fontIcon="add_notes"></mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button [matMenuTriggerFor]="menuJump" aria-label="Menu Jump">
|
||||
<mat-icon fontIcon="more_vert"></mat-icon>
|
||||
</button>
|
||||
<mat-menu #menuJump="matMenu">
|
||||
<button mat-menu-item (click)="openAddDialog()">
|
||||
<mat-icon fontIcon="add_notes"></mat-icon>
|
||||
<span>Ajouter un saut</span>
|
||||
</button>
|
||||
<ng-container *ngFor="let menuitem of menuItems.getMenuLogbook()">
|
||||
<button mat-menu-item [routerLink]="['/', menuitem.state]" *ngIf="menuitem.type === 'link'">
|
||||
<mat-icon [fontIcon]="menuitem.icon"></mat-icon>
|
||||
<span>{{ menuitem.name }}</span>
|
||||
</button>
|
||||
</ng-container>
|
||||
</mat-menu>
|
||||
</mat-card-header>
|
||||
<mat-card-content class="my-4">
|
||||
<huapp-jump-table #jumpTable [refresh]="refreshInterval" [config]="listConfig" [isUser]="isUser" [showAdd]="canModify" [title]="title">
|
||||
</huapp-jump-table>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { ActivatedRoute, Router, RouterLink, RouterModule } from '@angular/router';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatDialog, MatDialogModule } from '@angular/material/dialog';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
import { MatSnackBar, MatSnackBarHorizontalPosition, MatSnackBarModule, MatSnackBarVerticalPosition } from '@angular/material/snack-bar';
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
import { take } from 'rxjs/operators';
|
||||
|
||||
import { JumpTableComponent } from 'src/app/components/shared/helpers-jump';
|
||||
import { MenuItems, JumpAddDialogComponent, JumpTableComponent } from 'src/app/components/shared';
|
||||
//import { JumpTableComponent } from 'src/app/components/shared/helpers-jump';
|
||||
import { Errors, Jump, JumpListConfig, User } from 'src/app/core/models';
|
||||
import { JumpsService, UserService } from 'src/app/core/services';
|
||||
import { environment } from 'src/environments/environment';
|
||||
@@ -11,7 +19,12 @@ import data from 'src/jumps.json';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
imports: [JumpTableComponent],
|
||||
imports: [
|
||||
CommonModule, RouterModule,
|
||||
MatButtonModule, MatCardModule, MatIconModule,
|
||||
MatMenuModule, MatDialogModule, MatSnackBarModule,
|
||||
JumpTableComponent
|
||||
],
|
||||
selector: 'huapp-logbook',
|
||||
templateUrl: './logbook.component.html',
|
||||
styleUrls: ['./logbook.component.scss']
|
||||
@@ -19,22 +32,27 @@ import data from 'src/jumps.json';
|
||||
export class LogbookComponent implements OnInit, OnDestroy {
|
||||
private _currentUser: Subscription = new Subscription();
|
||||
private _data: Subscription = new Subscription();
|
||||
errors!: Errors;
|
||||
title = 'Carnet de saut';
|
||||
listTitle = 'Liste des sauts';
|
||||
listConfig: JumpListConfig = { type: 'all', filters: {} };
|
||||
refreshInterval: number = environment.refresh_interval;
|
||||
isAuthenticated = false;
|
||||
isUser = true;
|
||||
canModify = false;
|
||||
jump: Jump = {} as Jump;
|
||||
currentUser: User = {} as User;
|
||||
private _lastjump: Subscription = new Subscription();
|
||||
public errors!: Errors;
|
||||
public title = 'Carnet de sauts';
|
||||
public jump: Jump = {} as Jump;
|
||||
public lastjump: Jump = {} as Jump;
|
||||
public currentUser: User = {} as User;
|
||||
public listConfig: JumpListConfig = { type: 'all', filters: {} };
|
||||
public refreshInterval: number = environment.refresh_interval;
|
||||
public isAuthenticated = false;
|
||||
public isUser = true;
|
||||
public canModify = false;
|
||||
public isSubmitting = false;
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private dialog: MatDialog,
|
||||
private snackBar: MatSnackBar,
|
||||
private jumpsService: JumpsService,
|
||||
private userService: UserService
|
||||
private userService: UserService,
|
||||
public menuItems: MenuItems
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
@@ -51,8 +69,20 @@ export class LogbookComponent implements OnInit, OnDestroy {
|
||||
this.currentUser = userData;
|
||||
this.canModify = this.currentUser.role === 'Admin';
|
||||
});
|
||||
|
||||
const lastjump$: Observable<Jump> = this.jumpsService.getLastJump();
|
||||
this._lastjump = lastjump$.subscribe((jump) => {
|
||||
this.lastjump = jump;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this._data.unsubscribe();
|
||||
this._currentUser.unsubscribe();
|
||||
this._lastjump.unsubscribe();
|
||||
}
|
||||
|
||||
importJumps() {
|
||||
try {
|
||||
data.forEach((entry) => {
|
||||
@@ -75,9 +105,52 @@ export class LogbookComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this._currentUser.unsubscribe();
|
||||
this._data.unsubscribe();
|
||||
openAddDialog(): void {
|
||||
const dialogRef = this.dialog.open(JumpAddDialogComponent, {
|
||||
width: '60vw',
|
||||
data: this.jump
|
||||
});
|
||||
dialogRef.afterClosed().pipe(take(1))
|
||||
.subscribe(result => {
|
||||
if (result != undefined) {
|
||||
this._onEntry(result);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private _onEntry(entry: NonNullable<unknown>): void {
|
||||
try {
|
||||
this.isSubmitting = true;
|
||||
Object.assign(this.jump, entry);
|
||||
this.jumpsService.save(this.jump)
|
||||
.pipe(take(1))
|
||||
.subscribe({
|
||||
next: (jump) => {
|
||||
this._openSnackBar(`Le saut n°${jump.numero} a été ajouté !`, 'OK');
|
||||
this._resetErrors();
|
||||
//this.runQuery();
|
||||
},
|
||||
error: (err) => {
|
||||
this.errors = err;
|
||||
this.isSubmitting = false;
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
private _openSnackBar(content: string, title: string) {
|
||||
this.snackBar.open(content, title, {
|
||||
horizontalPosition: <MatSnackBarHorizontalPosition>'end',
|
||||
verticalPosition: <MatSnackBarVerticalPosition>'bottom',
|
||||
duration: 4000,
|
||||
});
|
||||
}
|
||||
|
||||
private _resetErrors(): void {
|
||||
this.errors = { errors: {} };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -44,6 +44,12 @@
|
||||
<input matInput type="number" placeholder="Indiquez le un nom de votre société" formControlName="licence">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<mat-form-field appearance="fill" class="w-100">
|
||||
<mat-label>Poids</mat-label>
|
||||
<input matInput type="number" placeholder="Indiquez le poids en Kg" formControlName="poids">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<mat-form-field appearance="fill" class="w-100">
|
||||
<mat-label>Photo de profil</mat-label>
|
||||
|
||||
@@ -53,6 +53,7 @@ export class SettingsComponent implements OnInit, OnDestroy {
|
||||
password: ['', Validators.required],
|
||||
confirmPassword: ['', Validators.required],
|
||||
licence: '',
|
||||
poids: '',
|
||||
image: '',
|
||||
bg_image: ''
|
||||
}, { validators: this.checkPasswords });
|
||||
|
||||
@@ -4,74 +4,74 @@
|
||||
<div fxLayout="row wrap">
|
||||
<!-- column -->
|
||||
<div fxFlex.gt-lg="25" fxFlex.gt-md="50" fxFlex.gt-xs="100" fxFlex="100" class="px-2">
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-form-field appearance="fill" class="me-2">
|
||||
<mat-label>Numéro</mat-label>
|
||||
<input matInput [(ngModel)]="jump.numero">
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-form-field appearance="fill" class="me-2">
|
||||
<mat-label>Date</mat-label>
|
||||
<input matInput [(ngModel)]="jump.date">
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-form-field appearance="fill" class="me-2">
|
||||
<mat-label>Lieu</mat-label>
|
||||
<input matInput [(ngModel)]="jump.lieu">
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-form-field appearance="fill" class="me-2">
|
||||
<mat-label>Aeronef</mat-label>
|
||||
<input matInput [(ngModel)]="jump.aeronef">
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-form-field appearance="fill" class="me-2">
|
||||
<mat-label>Hauteur</mat-label>
|
||||
<input matInput [(ngModel)]="jump.hauteur">
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-form-field appearance="fill" class="me-2">
|
||||
<mat-label>Voile</mat-label>
|
||||
<input matInput [(ngModel)]="jump.voile">
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-form-field appearance="fill" class="me-2">
|
||||
<mat-label>Taille</mat-label>
|
||||
<input matInput [(ngModel)]="jump.taille">
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-form-field appearance="fill" class="me-2">
|
||||
<mat-label>Categorie</mat-label>
|
||||
<input matInput [(ngModel)]="jump.categorie">
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-form-field appearance="fill" class="me-2">
|
||||
<mat-label>Module</mat-label>
|
||||
<input matInput [(ngModel)]="jump.module">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<!-- column -->
|
||||
<div fxFlex.gt-lg="25" fxFlex.gt-md="50" fxFlex.gt-xs="100" fxFlex="100" class="px-2">
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-form-field appearance="fill" class="me-2">
|
||||
<mat-label>Participants</mat-label>
|
||||
<input matInput [(ngModel)]="jump.participants">
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-form-field appearance="fill" class="me-2">
|
||||
<mat-label>Programme</mat-label>
|
||||
<input matInput [(ngModel)]="jump.programme">
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-form-field appearance="fill" class="me-2">
|
||||
<mat-label>Oaci</mat-label>
|
||||
<input matInput [(ngModel)]="jump.oaci">
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-form-field appearance="fill" class="me-2">
|
||||
<mat-label>Imat</mat-label>
|
||||
<input matInput [(ngModel)]="jump.imat">
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-form-field appearance="fill" class="me-2">
|
||||
<mat-label>Accessoires</mat-label>
|
||||
<input matInput [(ngModel)]="jump.accessoires">
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-form-field appearance="fill" class="me-2">
|
||||
<mat-label>Zone</mat-label>
|
||||
<input matInput [(ngModel)]="jump.zone">
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-form-field appearance="fill" class="me-2">
|
||||
<mat-label>Dossier</mat-label>
|
||||
<input matInput [(ngModel)]="jump.dossier">
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-form-field appearance="fill" class="me-2">
|
||||
<mat-label>Video</mat-label>
|
||||
<input matInput [(ngModel)]="jump.video">
|
||||
</mat-form-field>
|
||||
@@ -85,6 +85,7 @@
|
||||
</div>
|
||||
</mat-dialog-content>
|
||||
<mat-dialog-actions>
|
||||
<button mat-button (click)="onCloseDialog()">Annuler</button>
|
||||
<span class="flex-spacer"></span>
|
||||
<button mat-button (click)="onCloseDialog()" class="me-1">Annuler</button>
|
||||
<button mat-button color="primary" [mat-dialog-close]="jump" cdkFocusInitial>Enregistrer</button>
|
||||
</mat-dialog-actions>
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
<hr />
|
||||
</mat-dialog-content>
|
||||
<mat-dialog-actions>
|
||||
<button mat-button (click)="onCloseDialog()">Annuler</button>
|
||||
<span class="flex-spacer"></span>
|
||||
<button mat-button (click)="onCloseDialog()" class="me-1">Annuler</button>
|
||||
<button mat-button color="accent" [mat-dialog-close]="jump" cdkFocusInitial>Supprimer</button>
|
||||
</mat-dialog-actions>
|
||||
|
||||
@@ -79,6 +79,7 @@
|
||||
</div>
|
||||
</mat-dialog-content>
|
||||
<mat-dialog-actions>
|
||||
<button mat-button (click)="onCloseDialog()">Annuler</button>
|
||||
<span class="flex-spacer"></span>
|
||||
<button mat-button (click)="onCloseDialog()" class="me-1">Annuler</button>
|
||||
<button mat-button color="primary" [mat-dialog-close]="jump" cdkFocusInitial>Enregistrer</button>
|
||||
</mat-dialog-actions>
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<table class="table table-striped table-dark table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th *ngFor='let name of headers; let i=index' class="text-end"> {{name}} </th>
|
||||
<th class="text-end">Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="font-monospace">
|
||||
<tr *ngFor='let row of rows; let i=index'>
|
||||
<th class="{{colors[i]}} text-end"> ● {{names[i]}} </th>
|
||||
<td *ngFor='let value of row; let i=index' class="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="{{colors[i]}} text-end">
|
||||
<span *ngIf="values[i]; else elseBlock" class="pr-1">{{values[i]}}</span>
|
||||
<ng-template #elseBlock><span class="text-empty pr-1">{{values[i]}}</span></ng-template>
|
||||
</th>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -0,0 +1,22 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { NgIf, NgFor } from '@angular/common';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
imports: [
|
||||
NgIf, NgFor
|
||||
],
|
||||
selector: 'huapp-history-table',
|
||||
templateUrl: './history-table.component.html',
|
||||
styleUrls: []
|
||||
})
|
||||
export class HistoryTableComponent {
|
||||
|
||||
constructor() {}
|
||||
|
||||
@Input() headers: string[] = [];
|
||||
@Input() names: string[] = [];
|
||||
@Input() values: number[] = [];
|
||||
@Input() rows: any[] = [];
|
||||
@Input() colors: string[] = [];
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from './history-table.component';
|
||||
export * from './jump-list.component';
|
||||
export * from './jump-meta.component';
|
||||
export * from './jump-preview.component';
|
||||
|
||||
@@ -1,38 +1,37 @@
|
||||
<div class="clearfix mt-4 mb-1 border-bottom">
|
||||
<h2 class="float-md-start me-3">{{ title }} <span class="fs-4 text-accent" [hidden]="!jumpsCount">({{ jumpsCount }})</span></h2>
|
||||
<mat-spinner class="float-md-start" [diameter]="32" [hidden]="!loading" color="accent"></mat-spinner>
|
||||
<button [hidden]="!showAdd" mat-raised-button color="accent" (click)="openAddDialog()" class="float-md-end">
|
||||
<mat-icon aria-label="Ajouter" fontIcon="add_notes"></mat-icon> Ajouter
|
||||
</button>
|
||||
</div>
|
||||
<span [hidden]="!jumpsCount" class="small mt-2 me-2 fst-italic">Dernier saut enregistré :</span>
|
||||
<span [hidden]="jumpsCount || loading">Aucun saut à afficher pour le moment.</span>
|
||||
<span [hidden]="!loading">Actualisation des sauts en cours</span>
|
||||
|
||||
<div class="row mx-0">
|
||||
<div class="col-md-6 col-xs-12 px-0">
|
||||
<form class="mt-3" [formGroup]="searchForm" (ngSubmit)="submitForm()">
|
||||
<mat-form-field appearance="fill">
|
||||
<input matInput type="number" placeholder="Rechercher un saut" formControlName="numero">
|
||||
<mat-error *ngIf="this.searchForm.controls['numero'].status === 'INVALID'">{{getErrorMessage()}}</mat-error>
|
||||
<mat-error *ngIf="this.searchForm.controls['numero'].status === 'INVALID'">{{getErrorMessage()}}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<button mat-raised-button color="primary" type="submit" class="ms-2">
|
||||
<button mat-raised-button color="accent" type="submit" class="ms-2">
|
||||
<mat-icon aria-label="Rechercher" fontIcon="search"></mat-icon> Rechercher
|
||||
</button>
|
||||
<mat-spinner [diameter]="32" [hidden]="!loading" color="accent" class="align-middle ms-2"></mat-spinner>
|
||||
<span [hidden]="jumpsCount || loading" class="ms-2 fst-italic">Aucun saut à afficher pour le moment.</span>
|
||||
<span [hidden]="!loading" class="ms-2 fst-italic">Actualisation des sauts en cours</span>
|
||||
</form>
|
||||
</div>
|
||||
<div class="col-md-6 col-xs-12 px-0">
|
||||
<mat-paginator [pageSize]="25" [pageSizeOptions]="[10, 25, 50, 100]" showFirstLastButtons class="mb-1 mt-2"></mat-paginator>
|
||||
<mat-paginator [pageSize]="25" [pageSizeOptions]="[10, 25, 50, 100]" showFirstLastButtons class="mb-1 mt-2">
|
||||
</mat-paginator>
|
||||
</div>
|
||||
</div>
|
||||
<table mat-table [dataSource]="jumps" matSort class="table table-dark table-striped table-hover table-condensed mat-elevation-z2">
|
||||
<table mat-table [dataSource]="jumps" matSort
|
||||
class="table table-dark table-striped table-hover table-condensed mat-elevation-z2">
|
||||
<caption [hidden]="jumpsCount || loading">Aucun saut à afficher pour le moment.</caption>
|
||||
<!-- Numero Column -->
|
||||
<ng-container matColumnDef="numero">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Numero </th>
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> # </th>
|
||||
<td class="text-end pl-3 pr-3" mat-cell *matCellDef="let element">
|
||||
<ng-container *ngIf="element.numero"><a [routerLink]="['/jump', element.slug]">{{element.numero}}</a></ng-container>
|
||||
<ng-container *ngIf="!element.numero"><ngx-skeleton-loader [theme]="{width: '30px', height: '13px', marginBottom: '0px'}"></ngx-skeleton-loader></ng-container>
|
||||
<ng-container *ngIf="element.numero"><a [routerLink]="['/jump', element.slug]" class="accent">{{element.numero}}</a>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="!element.numero">
|
||||
<ngx-skeleton-loader [theme]="{width: '30px', height: '13px', marginBottom: '0px'}">
|
||||
</ngx-skeleton-loader>
|
||||
</ng-container>
|
||||
</td>
|
||||
</ng-container>
|
||||
<!-- Date Column -->
|
||||
@@ -40,7 +39,10 @@
|
||||
<th class="pl-3" mat-header-cell *matHeaderCellDef> Date </th>
|
||||
<td class="pl-3 text-nowrap" mat-cell *matCellDef="let element">
|
||||
<ng-container *ngIf="element.date">{{element.date}}</ng-container>
|
||||
<ng-container *ngIf="!element.numero"><ngx-skeleton-loader [theme]="{width: '30px', height: '13px', marginBottom: '0px'}"></ngx-skeleton-loader></ng-container>
|
||||
<ng-container *ngIf="!element.numero">
|
||||
<ngx-skeleton-loader [theme]="{width: '30px', height: '13px', marginBottom: '0px'}">
|
||||
</ngx-skeleton-loader>
|
||||
</ng-container>
|
||||
</td>
|
||||
</ng-container>
|
||||
<!-- Lieu Column -->
|
||||
@@ -48,7 +50,10 @@
|
||||
<th class="pl-3" mat-header-cell *matHeaderCellDef> Lieu </th>
|
||||
<td class="pl-3 text-nowrap" mat-cell *matCellDef="let element">
|
||||
<ng-container *ngIf="element.lieu">{{element.lieu}}</ng-container>
|
||||
<ng-container *ngIf="!element.numero"><ngx-skeleton-loader [theme]="{width: '30px', height: '13px', marginBottom: '0px'}"></ngx-skeleton-loader></ng-container>
|
||||
<ng-container *ngIf="!element.numero">
|
||||
<ngx-skeleton-loader [theme]="{width: '30px', height: '13px', marginBottom: '0px'}">
|
||||
</ngx-skeleton-loader>
|
||||
</ng-container>
|
||||
</td>
|
||||
</ng-container>
|
||||
<!-- Oaci Column -->
|
||||
@@ -56,7 +61,10 @@
|
||||
<th class="pl-3" mat-header-cell *matHeaderCellDef> Oaci </th>
|
||||
<td class="pl-3 text-nowrap" mat-cell *matCellDef="let element">
|
||||
<ng-container *ngIf="element.oaci">{{element.oaci}}</ng-container>
|
||||
<ng-container *ngIf="!element.numero"><ngx-skeleton-loader [theme]="{width: '30px', height: '13px', marginBottom: '0px'}"></ngx-skeleton-loader></ng-container>
|
||||
<ng-container *ngIf="!element.numero">
|
||||
<ngx-skeleton-loader [theme]="{width: '30px', height: '13px', marginBottom: '0px'}">
|
||||
</ngx-skeleton-loader>
|
||||
</ng-container>
|
||||
</td>
|
||||
</ng-container>
|
||||
<!-- Aeronef Column -->
|
||||
@@ -64,7 +72,10 @@
|
||||
<th class="pl-3" mat-header-cell *matHeaderCellDef> Aeronef </th>
|
||||
<td class="pl-3 text-nowrap" mat-cell *matCellDef="let element">
|
||||
<ng-container *ngIf="element.aeronef">{{element.aeronef}}</ng-container>
|
||||
<ng-container *ngIf="!element.numero"><ngx-skeleton-loader [theme]="{width: '30px', height: '13px', marginBottom: '0px'}"></ngx-skeleton-loader></ng-container>
|
||||
<ng-container *ngIf="!element.numero">
|
||||
<ngx-skeleton-loader [theme]="{width: '30px', height: '13px', marginBottom: '0px'}">
|
||||
</ngx-skeleton-loader>
|
||||
</ng-container>
|
||||
</td>
|
||||
</ng-container>
|
||||
<!-- Imat Column -->
|
||||
@@ -72,7 +83,10 @@
|
||||
<th class="pl-3" mat-header-cell *matHeaderCellDef> Imat </th>
|
||||
<td class="pl-3 text-nowrap" mat-cell *matCellDef="let element">
|
||||
<ng-container *ngIf="element.imat">{{element.imat}}</ng-container>
|
||||
<ng-container *ngIf="!element.numero"><ngx-skeleton-loader [theme]="{width: '30px', height: '13px', marginBottom: '0px'}"></ngx-skeleton-loader></ng-container>
|
||||
<ng-container *ngIf="!element.numero">
|
||||
<ngx-skeleton-loader [theme]="{width: '30px', height: '13px', marginBottom: '0px'}">
|
||||
</ngx-skeleton-loader>
|
||||
</ng-container>
|
||||
</td>
|
||||
</ng-container>
|
||||
<!-- Hauteur Column -->
|
||||
@@ -80,7 +94,10 @@
|
||||
<th class="pl-3" mat-header-cell *matHeaderCellDef> Hauteur </th>
|
||||
<td class="pl-3" mat-cell *matCellDef="let element">
|
||||
<ng-container *ngIf="element.hauteur">{{element.hauteur}}</ng-container>
|
||||
<ng-container *ngIf="!element.numero"><ngx-skeleton-loader [theme]="{width: '30px', height: '13px', marginBottom: '0px'}"></ngx-skeleton-loader></ng-container>
|
||||
<ng-container *ngIf="!element.numero">
|
||||
<ngx-skeleton-loader [theme]="{width: '30px', height: '13px', marginBottom: '0px'}">
|
||||
</ngx-skeleton-loader>
|
||||
</ng-container>
|
||||
</td>
|
||||
</ng-container>
|
||||
<!-- Voile Column -->
|
||||
@@ -88,7 +105,10 @@
|
||||
<th class="pl-3" mat-header-cell *matHeaderCellDef> Voile </th>
|
||||
<td class="pl-3 text-nowrap" mat-cell *matCellDef="let element">
|
||||
<ng-container *ngIf="element.voile">{{element.voile}}</ng-container>
|
||||
<ng-container *ngIf="!element.numero"><ngx-skeleton-loader [theme]="{width: '30px', height: '13px', marginBottom: '0px'}"></ngx-skeleton-loader></ng-container>
|
||||
<ng-container *ngIf="!element.numero">
|
||||
<ngx-skeleton-loader [theme]="{width: '30px', height: '13px', marginBottom: '0px'}">
|
||||
</ngx-skeleton-loader>
|
||||
</ng-container>
|
||||
</td>
|
||||
</ng-container>
|
||||
<!-- Taille Column -->
|
||||
@@ -96,7 +116,10 @@
|
||||
<th class="pl-3" mat-header-cell *matHeaderCellDef> Taille </th>
|
||||
<td class="text-nowrap text-end pl-3 pr-3" mat-cell *matCellDef="let element">
|
||||
<ng-container *ngIf="element.taille">{{element.taille}}</ng-container>
|
||||
<ng-container *ngIf="!element.numero"><ngx-skeleton-loader [theme]="{width: '30px', height: '13px', marginBottom: '0px'}"></ngx-skeleton-loader></ng-container>
|
||||
<ng-container *ngIf="!element.numero">
|
||||
<ngx-skeleton-loader [theme]="{width: '30px', height: '13px', marginBottom: '0px'}">
|
||||
</ngx-skeleton-loader>
|
||||
</ng-container>
|
||||
</td>
|
||||
</ng-container>
|
||||
<!-- Categorie Column -->
|
||||
@@ -104,7 +127,10 @@
|
||||
<th class="pl-3" mat-header-cell *matHeaderCellDef> Categorie </th>
|
||||
<td class="pl-3 text-nowrap" mat-cell *matCellDef="let element">
|
||||
<ng-container *ngIf="element.categorie">{{element.categorie}}</ng-container>
|
||||
<ng-container *ngIf="!element.numero"><ngx-skeleton-loader [theme]="{width: '30px', height: '13px', marginBottom: '0px'}"></ngx-skeleton-loader></ng-container>
|
||||
<ng-container *ngIf="!element.numero">
|
||||
<ngx-skeleton-loader [theme]="{width: '30px', height: '13px', marginBottom: '0px'}">
|
||||
</ngx-skeleton-loader>
|
||||
</ng-container>
|
||||
</td>
|
||||
</ng-container>
|
||||
<!-- Module Column -->
|
||||
@@ -112,7 +138,10 @@
|
||||
<th class="pl-3" mat-header-cell *matHeaderCellDef> Module </th>
|
||||
<td class="pl-3 text-nowrap" mat-cell *matCellDef="let element">
|
||||
<ng-container *ngIf="element.module">{{element.module}}</ng-container>
|
||||
<ng-container *ngIf="!element.numero"><ngx-skeleton-loader [theme]="{width: '30px', height: '13px', marginBottom: '0px'}"></ngx-skeleton-loader></ng-container>
|
||||
<ng-container *ngIf="!element.numero">
|
||||
<ngx-skeleton-loader [theme]="{width: '30px', height: '13px', marginBottom: '0px'}">
|
||||
</ngx-skeleton-loader>
|
||||
</ng-container>
|
||||
</td>
|
||||
</ng-container>
|
||||
<!-- Participants Column -->
|
||||
@@ -120,7 +149,10 @@
|
||||
<th class="pl-3" mat-header-cell *matHeaderCellDef> Participants </th>
|
||||
<td class="text-end pl-3 pr-3" mat-cell *matCellDef="let element">
|
||||
<ng-container *ngIf="element.participants">{{element.participants}}</ng-container>
|
||||
<ng-container *ngIf="!element.numero"><ngx-skeleton-loader [theme]="{width: '30px', height: '13px', marginBottom: '0px'}"></ngx-skeleton-loader></ng-container>
|
||||
<ng-container *ngIf="!element.numero">
|
||||
<ngx-skeleton-loader [theme]="{width: '30px', height: '13px', marginBottom: '0px'}">
|
||||
</ngx-skeleton-loader>
|
||||
</ng-container>
|
||||
</td>
|
||||
</ng-container>
|
||||
<!-- Programme Column -->
|
||||
@@ -128,7 +160,10 @@
|
||||
<th class="pl-3" mat-header-cell *matHeaderCellDef> Programme </th>
|
||||
<td class="pl-3" mat-cell *matCellDef="let element">
|
||||
<ng-container *ngIf="element.programme">{{element.programme}}</ng-container>
|
||||
<ng-container *ngIf="!element.numero"><ngx-skeleton-loader [theme]="{width: '30px', height: '13px', marginBottom: '0px'}"></ngx-skeleton-loader></ng-container>
|
||||
<ng-container *ngIf="!element.numero">
|
||||
<ngx-skeleton-loader [theme]="{width: '30px', height: '13px', marginBottom: '0px'}">
|
||||
</ngx-skeleton-loader>
|
||||
</ng-container>
|
||||
</td>
|
||||
</ng-container>
|
||||
<!-- Accessoires Column -->
|
||||
@@ -136,7 +171,10 @@
|
||||
<th class="pl-3" mat-header-cell *matHeaderCellDef> Accessoires </th>
|
||||
<td class="pl-3 text-nowrap" mat-cell *matCellDef="let element">
|
||||
<ng-container *ngIf="element.accessoires">{{element.accessoires}}</ng-container>
|
||||
<ng-container *ngIf="!element.numero"><ngx-skeleton-loader [theme]="{width: '30px', height: '13px', marginBottom: '0px'}"></ngx-skeleton-loader></ng-container>
|
||||
<ng-container *ngIf="!element.numero">
|
||||
<ngx-skeleton-loader [theme]="{width: '30px', height: '13px', marginBottom: '0px'}">
|
||||
</ngx-skeleton-loader>
|
||||
</ng-container>
|
||||
</td>
|
||||
</ng-container>
|
||||
<!-- Zone Column -->
|
||||
@@ -144,7 +182,10 @@
|
||||
<th class="pl-3" mat-header-cell *matHeaderCellDef> Zone </th>
|
||||
<td class="pl-3 text-nowrap" mat-cell *matCellDef="let element">
|
||||
<ng-container *ngIf="element.zone">{{element.zone}}</ng-container>
|
||||
<ng-container *ngIf="!element.numero"><ngx-skeleton-loader [theme]="{width: '30px', height: '13px', marginBottom: '0px'}"></ngx-skeleton-loader></ng-container>
|
||||
<ng-container *ngIf="!element.numero">
|
||||
<ngx-skeleton-loader [theme]="{width: '30px', height: '13px', marginBottom: '0px'}">
|
||||
</ngx-skeleton-loader>
|
||||
</ng-container>
|
||||
</td>
|
||||
</ng-container>
|
||||
<!-- Dossier Column -->
|
||||
@@ -152,7 +193,10 @@
|
||||
<th class="pl-3" mat-header-cell *matHeaderCellDef> Dossier </th>
|
||||
<td class="pl-3 text-nowrap" mat-cell *matCellDef="let element">
|
||||
<ng-container *ngIf="element.dossier">{{element.dossier}}</ng-container>
|
||||
<ng-container *ngIf="!element.numero"><ngx-skeleton-loader [theme]="{width: '30px', height: '13px', marginBottom: '0px'}"></ngx-skeleton-loader></ng-container>
|
||||
<ng-container *ngIf="!element.numero">
|
||||
<ngx-skeleton-loader [theme]="{width: '30px', height: '13px', marginBottom: '0px'}">
|
||||
</ngx-skeleton-loader>
|
||||
</ng-container>
|
||||
</td>
|
||||
</ng-container>
|
||||
<!-- Video Column -->
|
||||
@@ -160,7 +204,10 @@
|
||||
<th class="pl-3" mat-header-cell *matHeaderCellDef> Video </th>
|
||||
<td class="pl-3 text-nowrap" mat-cell *matCellDef="let element">
|
||||
<ng-container *ngIf="element.video">{{element.video}}</ng-container>
|
||||
<ng-container *ngIf="!element.numero"><ngx-skeleton-loader [theme]="{width: '30px', height: '13px', marginBottom: '0px'}"></ngx-skeleton-loader></ng-container>
|
||||
<ng-container *ngIf="!element.numero">
|
||||
<ngx-skeleton-loader [theme]="{width: '30px', height: '13px', marginBottom: '0px'}">
|
||||
</ngx-skeleton-loader>
|
||||
</ng-container>
|
||||
</td>
|
||||
</ng-container>
|
||||
<!-- Actions Column -->
|
||||
@@ -176,12 +223,18 @@
|
||||
</button>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="!element.numero">
|
||||
<ngx-skeleton-loader [hidden]="!showAdd" appearance="circle" [theme]="{width: '32px', height: '32px', marginBottom: '0px', marginRight: '7px'}"></ngx-skeleton-loader>
|
||||
<ngx-skeleton-loader [hidden]="!showAdd" appearance="circle" [theme]="{width: '32px', height: '32px', marginBottom: '0px', marginRight: '7px'}"></ngx-skeleton-loader>
|
||||
<ngx-skeleton-loader appearance="circle" [theme]="{width: '20px', height: '20px', marginBottom: '0px', marginRight: '7px'}"></ngx-skeleton-loader>
|
||||
<ngx-skeleton-loader [hidden]="!showAdd" appearance="circle"
|
||||
[theme]="{width: '32px', height: '32px', marginBottom: '0px', marginRight: '7px'}">
|
||||
</ngx-skeleton-loader>
|
||||
<ngx-skeleton-loader [hidden]="!showAdd" appearance="circle"
|
||||
[theme]="{width: '32px', height: '32px', marginBottom: '0px', marginRight: '7px'}">
|
||||
</ngx-skeleton-loader>
|
||||
<ngx-skeleton-loader appearance="circle"
|
||||
[theme]="{width: '20px', height: '20px', marginBottom: '0px', marginRight: '7px'}">
|
||||
</ngx-skeleton-loader>
|
||||
</ng-container>
|
||||
</td>
|
||||
</ng-container>
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;" class="text-middle"></tr>
|
||||
</table>
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true" class="accent"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;" class="text-middle accent"></tr>
|
||||
</table>
|
||||
|
||||
@@ -24,3 +24,6 @@ mat-card-content {
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
.mat-mdc-progress-spinner {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
@@ -3,10 +3,12 @@ import { NgIf, DecimalPipe, DatePipe } from '@angular/common';
|
||||
import { UntypedFormBuilder, UntypedFormGroup, Validators, FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { Router, RouterLink } from '@angular/router';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatDialog, MatDialogModule } from '@angular/material/dialog';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
import { MatPaginator, MatPaginatorModule } from '@angular/material/paginator';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
import { MatSort, MatSortModule } from '@angular/material/sort';
|
||||
@@ -16,18 +18,17 @@ import { Observable, Subscription } from 'rxjs';
|
||||
import { take } from 'rxjs/operators';
|
||||
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
|
||||
|
||||
import { Errors, Jump, JumpList, JumpListConfig, JumpViewResults } from 'src/app/core/models';
|
||||
import { Errors, Jump, JumpList, JumpListConfig } from 'src/app/core/models';
|
||||
import { JumpsService, BackendService } from 'src/app/core/services';
|
||||
import { JumpAddDialogComponent, JumpDeleteDialogComponent, JumpEditDialogComponent } from 'src/app/components/shared/dialogs'
|
||||
import { environment } from 'src/environments/environment';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
imports: [
|
||||
NgIf, DecimalPipe, DatePipe, RouterLink, FormsModule, ReactiveFormsModule, NgxSkeletonLoaderModule,
|
||||
MatFormFieldModule, MatInputModule,
|
||||
MatProgressSpinnerModule, MatButtonModule, MatIconModule, MatPaginatorModule,
|
||||
MatTableModule, MatSortModule, MatSnackBarModule, MatDialogModule,
|
||||
MatProgressSpinnerModule, MatButtonModule, MatCardModule, MatIconModule, MatMenuModule,
|
||||
MatPaginatorModule, MatTableModule, MatSortModule, MatSnackBarModule, MatDialogModule,
|
||||
JumpAddDialogComponent, JumpDeleteDialogComponent, JumpEditDialogComponent
|
||||
],
|
||||
selector: 'huapp-jump-table',
|
||||
@@ -36,10 +37,12 @@ import { environment } from 'src/environments/environment';
|
||||
})
|
||||
export class JumpTableComponent implements OnChanges, OnDestroy {
|
||||
private _jumps: Subscription = new Subscription();
|
||||
private _lastjump: Subscription = new Subscription();
|
||||
errors!: Errors;
|
||||
query: JumpListConfig = { type: 'all', filters: {} };
|
||||
jump: Jump = {} as Jump;
|
||||
jumps!: MatTableDataSource<Jump>;
|
||||
lastjump: Jump = {} as Jump;
|
||||
jumpsCount = 0;
|
||||
currentPage = 1;
|
||||
displayedColumns: string[] = [
|
||||
@@ -93,14 +96,19 @@ export class JumpTableComponent implements OnChanges, OnDestroy {
|
||||
this.loading = true;
|
||||
this.query = this.config;
|
||||
this.runQuery();
|
||||
//this.loadJumps();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this._jumps.unsubscribe();
|
||||
this._lastjump.unsubscribe();
|
||||
}
|
||||
|
||||
runQuery() {
|
||||
const lastjump$: Observable<Jump> = this.jumpsService.getLastJump();
|
||||
this._lastjump = lastjump$.subscribe((jump) => {
|
||||
this.lastjump = jump;
|
||||
});
|
||||
|
||||
if (this.limit) {
|
||||
this.query.filters.limit = this.limit;
|
||||
this.query.filters.offset = (this.limit * (this.currentPage - 1));
|
||||
@@ -126,27 +134,6 @@ export class JumpTableComponent implements OnChanges, OnDestroy {
|
||||
});
|
||||
}
|
||||
|
||||
loadJumps() {
|
||||
const jumps$: Observable<JumpViewResults> = this._dataService.getJumps();
|
||||
this._jumps = jumps$.subscribe((jumpList) => {
|
||||
//console.log('ngOnInit');
|
||||
//console.log(res);
|
||||
//console.log(res["rows"]);
|
||||
this.jumpsCount = jumpList.total_rows;
|
||||
//this.last_jump = jumpList.rows[0];
|
||||
this.jumps = new MatTableDataSource<Jump>(jumpList.rows)
|
||||
this.jumps.paginator = this.paginator;
|
||||
this.jumps.sort = this.sort;
|
||||
console.log(this.jumps);
|
||||
});
|
||||
/*
|
||||
.subscribe((res) => this.jumps = new MatTableDataSource<Jump>(res["rows"]));
|
||||
*/
|
||||
//
|
||||
//.subscribe((res) => this.jumps = res["rows"]);
|
||||
//.subscribe((res) => console.log(res["rows"]));
|
||||
}
|
||||
|
||||
deleteJump(slug: string) {
|
||||
this.isDeleting = true;
|
||||
this.jumpsService.destroy(slug).pipe(take(1))
|
||||
@@ -209,14 +196,6 @@ export class JumpTableComponent implements OnChanges, OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
private _openSnackBar(content: string, title: string) {
|
||||
this.snackBar.open(content, title, {
|
||||
horizontalPosition: <MatSnackBarHorizontalPosition>'end',
|
||||
verticalPosition: <MatSnackBarVerticalPosition>'bottom',
|
||||
duration: 4000,
|
||||
});
|
||||
}
|
||||
|
||||
private _onDelete(slug: string): void {
|
||||
try {
|
||||
this.isDeleting = true;
|
||||
@@ -280,6 +259,14 @@ export class JumpTableComponent implements OnChanges, OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
private _openSnackBar(content: string, title: string) {
|
||||
this.snackBar.open(content, title, {
|
||||
horizontalPosition: <MatSnackBarHorizontalPosition>'end',
|
||||
verticalPosition: <MatSnackBarVerticalPosition>'bottom',
|
||||
duration: 4000,
|
||||
});
|
||||
}
|
||||
|
||||
private _resetErrors(): void {
|
||||
this.errors = { errors: {} };
|
||||
}
|
||||
|
||||
@@ -16,9 +16,27 @@ const MENUITEMS: Menu[] = [
|
||||
];
|
||||
|
||||
const MENUQCM: Menu[] = [
|
||||
{ state: 'button', type: 'link', name: 'BPA', icon: 'rule' },
|
||||
{ state: 'datepicker', type: 'link', name: 'Brevet C', icon: 'rule' },
|
||||
{ state: 'grid', type: 'link', name: 'Brevet D', icon: 'rule' }
|
||||
{ state: 'qcmbpa', type: 'link', name: 'BPA', icon: 'rule' },
|
||||
{ state: 'qcmc', type: 'link', name: 'Brevet C', icon: 'rule' },
|
||||
{ state: 'qcmd', type: 'link', name: 'Brevet D', icon: 'rule' }
|
||||
];
|
||||
|
||||
const MENUPANEL: Menu[] = [
|
||||
{ state: '#', type: 'link', name: 'Retirer du dashboard', icon: 'add_notes', desc: '' },
|
||||
{ state: '#', type: 'link', name: 'Paramètres d\'affichage', icon: 'display_settings', desc: '' }
|
||||
];
|
||||
|
||||
const MENUCALCULATOR: Menu[] = [
|
||||
{ state: '#', type: 'link', name: 'Recherche avancée', icon: 'search', desc: '' },
|
||||
{ state: '#', type: 'link', name: 'Paramètres d\'affichage', icon: 'display_settings', desc: '' },
|
||||
{ state: '#', type: 'link', name: 'Partager', icon: 'share', desc: '' }
|
||||
];
|
||||
|
||||
const MENULOGBOOK: Menu[] = [
|
||||
{ state: '#', type: 'link', name: 'Recherche avancée', icon: 'search', desc: '' },
|
||||
{ state: '#', type: 'link', name: 'Recherche par participant', icon: 'person_search', desc: '' },
|
||||
{ state: '#', type: 'link', name: 'Paramètres d\'affichage', icon: 'display_settings', desc: '' },
|
||||
{ state: '#', type: 'link', name: 'Import CSV', icon: 'upload_file', desc: '' }
|
||||
];
|
||||
|
||||
@Injectable()
|
||||
@@ -26,10 +44,19 @@ export class MenuItems {
|
||||
getMenuAuth(): Menu[] {
|
||||
return MENUAUTH;
|
||||
}
|
||||
getMenuCalculator(): Menu[] {
|
||||
return MENUCALCULATOR;
|
||||
}
|
||||
getMenuItems(): Menu[] {
|
||||
return MENUITEMS;
|
||||
}
|
||||
getMenuLogbook(): Menu[] {
|
||||
return MENULOGBOOK;
|
||||
}
|
||||
getMenuQCM(): Menu[] {
|
||||
return MENUQCM;
|
||||
}
|
||||
getMenuPanel(): Menu[] {
|
||||
return MENUPANEL;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user