Implémentation SkydiverId API

This commit is contained in:
Rampeur
2024-05-08 20:32:49 +02:00
parent 6dece821a8
commit 7c3f0c9648
54 changed files with 2323 additions and 1395 deletions
+280 -129
View File
@@ -1,132 +1,283 @@
<div @flyInOut>
<div class="content">
<div class="d-flex">
<div class="flex-fill">
<h1 class="mb-1">{{title}}</h1>
<span [hidden]="!lastJump.numero" class="me-2 fs-6">
Dernier saut enregistré : <span class="fs-5 mx-1 text-primary">{{ lastJump.numero }}<sup>ème</sup></span> à <span class="fs-5 mx-1 text-primary">{{ lastJump.lieu }}</span> le <span class="fs-5 mx-1 text-primary">{{ lastJump.date | date: 'dd/MM/yyyy' }}</span>
</span>
</div>
<span class="flex-spacer"></span>
<div class="align-self-center me-2">
<button mat-icon-button [matMenuTriggerFor]="menuAeronef" aria-label="Menu Aeronef">
<mat-icon fontIcon="more_vert"></mat-icon>
<div class="d-flex">
<div class="flex-fill">
<h1 class="mb-1">
{{title}}
<span class="fs-3 text-accent ms-2">{{ jump.categorie }} {{ jump.module }}</span>
<span class="fs-3 text-muted ms-2">{{ jump.voile }} {{ jump.taille }}</span>
</h1>
<span class="me-2 fs-6">
Le <span class="fs-5 mx-1 text-primary">{{ jump.date | date: 'dd/MM/yyyy' }}</span>
à <span class="fs-5 mx-1 text-primary">{{ jump.lieu }} {{ jump.oaci }}</span>
@if (jump.x2data) {
depuis <span class="fs-5 mx-1 text-primary">{{ jump.aeronef }} {{ jump.imat }}</span>
}
</span>
</div>
<span class="flex-spacer"></span>
<div class="align-self-center me-4">
<button mat-button [routerLink]="['/jump', prevSlug]" aria-label="Saut précédent" color="accent">
<mat-icon fontIcon="navigate_before"></mat-icon> {{ jump.numero - 1}}
</button>
<div class="vr mx-2 fs-3 align-middle"></div>
<span class="mx-2 align-middle">{{ jump.numero }}</span>
<div class="vr mx-2 fs-3 align-middle"></div>
<button mat-button [routerLink]="['/jump', nextSlug]" aria-label="Saut suivant" color="accent">
<mat-icon fontIcon="navigate_next" iconPositionEnd></mat-icon> {{ jump.numero +1}}
</button>
</div>
<div class="align-self-center me-2">
<button mat-icon-button [matMenuTriggerFor]="menuJump" aria-label="Menu saut">
<mat-icon fontIcon="more_vert"></mat-icon>
</button>
<mat-menu #menuJump="matMenu">
@if (jump.x2data) {
<button mat-menu-item>
<mat-icon fontIcon="language" color="accent"></mat-icon>
<span class="text-accent fw-medium">Obtenir le KML</span>
</button>
<mat-menu #menuAeronef="matMenu">
@for (menuitem of menuItems.getMenuPanel(); track menuitem) {
<button mat-menu-item>
<mat-icon [fontIcon]="menuitem.icon"></mat-icon>
<span>{{ menuitem.name }}</span>
</button>
}
</mat-menu>
</div>
</div>
<mat-divider class="my-3"></mat-divider>
<mat-card>
<mat-card-header>
<mat-card-title>{{ subtitle }}</mat-card-title>
</mat-card-header>
<mat-card-content class="mt-2">
@if(displayCharts) {
<div class="row">
<div class="col-xxl-6 col-xs-12">
<app-linearea-chart [headers]="seriesHeader" [names]="seriesName" [values]="seriesRow" [colors]="seriesColor"></app-linearea-chart>
</div>
<div class="col-xxl-6 col-xs-12">
<app-bars-chart [headers]="seriesHeader" [names]="seriesName" [values]="seriesRow" [colors]="seriesColor" [legend]="true"></app-bars-chart>
</div>
</div>
}
<div class="row">
<div class="col-xs-12">
<mat-divider class="mt-3 mb-0"></mat-divider>
<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="{{seriesColorClass[i]}} text-end"> ● {{ seriesName[i] }} </th>
<td *ngFor='let value of values; let i=index' class="font-monospace text-end">
<span *ngIf="value; else elseBlock" class="pr-1">{{ value }}</span>
<ng-template #elseBlock><span class="text-empty pr-1">{{ value }}</span></ng-template>
</td>
<th class="{{seriesColorClass[i]}} 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>
<tr>
<th class="text-end">Moyenne</th>
<th *ngFor='let value of seriesRowAvg; let i=index' class="font-monospace text-end">
<span *ngIf="value; else elseBlock" class="pr-1">{{ value | number : '1.0-1' }}</span>
<ng-template #elseBlock><span class="text-empty pr-1">{{ value | number : '1.0-1' }}</span></ng-template>
</th>
<th class="font-monospace text-end">{{ grandAvg | number : '1.0-1' }}</th>
</tr>
<tr>
<th class="text-end">Moyenne <small>3 dernières années</small></th>
<th *ngFor='let value of seriesRowAvgLastYears; let i=index' class="font-monospace text-end">
<span *ngIf="value; else elseBlock" class="pr-1">{{ value | number : '1.0-1' }}</span>
<ng-template #elseBlock><span class="text-empty pr-1">{{ value | number : '1.0-1' }}</span></ng-template>
</th>
<th class="font-monospace text-end">{{ grandAvgLastYears | number : '1.0-1' }}</th>
</tr>
</tfoot>
</table>
</div>
</div>
</mat-card-content>
</mat-card>
<mat-card class="mt-3">
<mat-card-header>
<mat-card-title>Types de sauts</mat-card-title>
</mat-card-header>
<mat-card-content class="mt-2">
@if(displayCharts) {
<div class="row">
<div class="col-xs-12">
<app-line-chart [headers]="seriesTypesHeader" [names]="seriesTypesName" [values]="seriesTypesRowCumulated" [colors]="seriesTypesColor" [legend]="true"></app-line-chart>
</div>
</div>
<mat-divider class="mt-2 mb-3"></mat-divider>
<div class="row">
@for (item of getCategories(); track $index) {
<div class="col-lg-2 col-sm-4 col-xs-6">
<app-circle-chart [headers]="seriesHeader" [names]="seriesName" [values]="[item.count, (lastJump.numero-item.count)]" [color]="$index" [label]="item.categorie"></app-circle-chart>
</div>
}
@for (item of getModules(); track $index) {
<div class="col-lg-2 col-sm-4 col-xs-6">
<app-circle-chart [headers]="seriesHeader" [names]="seriesName" [values]="[item.count, (lastJump.numero-item.count)]" [color]="getModuleColor($index)" [label]="item.module"></app-circle-chart>
</div>
}
</div>
<mat-divider class="my-3"></mat-divider>
<!--
<div class="row">
<div class="col-xxl-6 col-xs-12">
<app-line-chart [headers]="seriesTypesHeader" [names]="seriesTypesName" [values]="seriesTypesRow" [colors]="seriesTypesColor" [legend]="true"></app-line-chart>
</div>
<div class="col-xxl-6 col-xs-12">
<app-line-chart [headers]="seriesTypesHeader" [names]="seriesTypesName" [values]="seriesTypesRowCumulated" [colors]="seriesTypesColor" [legend]="true"></app-line-chart>
</div>
</div>
-->
}
</mat-card-content>
</mat-card>
<mat-divider></mat-divider>
}
@for (menuitem of menuItems.getMenuJump(); track menuitem) {
<button mat-menu-item>
<mat-icon [fontIcon]="menuitem.icon" [color]="menuitem.color"></mat-icon>
<span class="text-{{menuitem.color}} fw-medium">{{ menuitem.name }}</span>
</button>
}
</mat-menu>
</div>
</div>
<mat-divider class="my-3"></mat-divider>
<mat-card>
<mat-card-content>
<div class="row">
<div class="col-lg-6 col-md-12">
<dl class="dl-horizontal">
<dt class="text-light-info fw-normal">Aeronef:</dt>
<dd>{{ jump.aeronef }} {{ jump.imat }}</dd>
<dt class="text-light-info fw-normal">Voile:</dt>
<dd>{{ jump.voile }} {{ jump.taille }} ft<sup>2</sup></dd>
@if (jump.programme) {
<dt class="text-light-info fw-normal">Programme:</dt>
<dd>{{ jump.programme }}</dd>
}
</dl>
</div>
<div class="col-lg-6 col-md-12">
<dl class="dl-horizontal">
@if (!jump.x2data) {
<dt class="text-light-info fw-normal">Hauteur:</dt>
<dd>{{ jump.hauteur }} m</dd>
<dt class="text-light-info fw-normal">Déploiement:</dt>
<dd>{{ jump.deploiement }} m</dd>
}
@for (file of jump.files; track file) {
<dt class="text-light-info fw-normal">Fichier {{ file.type }}</dt>
<dd>{{ file.name }}</dd>
}
</dl>
</div>
</div>
</mat-card-content>
</mat-card>
@if (jump.x2data) {
<mat-card class="mt-3">
<mat-card-content>
<div class="row my-3">
<div class="col-sm-4 col-xs-12 text-center">
<h6>Hauteur</h6>
@if (jump.x2data.altitude.exit > 4200) {
<mat-icon class="align-middle fs-5 me-2" fontIcon="mood" color="primary"></mat-icon>
}
<span class="text-primary fw-medium fs-5">{{ jump.x2data.altitude.exit }} m</span>
</div>
<div class="col-sm-4 col-xs-12 text-center">
<h6 class="d-flex justify-content-center"><mat-icon fontIcon="timer" class="me-1 fs-5"></mat-icon> Durée de la chute</h6>
<span class="text-primary fw-medium fs-4">{{ formatDuration(jump.x2data.duration.freeFall) }}</span>
</div>
<div class="col-sm-4 col-xs-12 text-center">
<h6>Déploiement</h6>
@if (jump.x2data.altitude.deployment < 650) {
<mat-icon class="align-middle fs-5 me-2" fontIcon="warning" color="raspberry"></mat-icon>
<span class="text-raspberry fw-medium fs-5">{{ jump.x2data.altitude.deployment }} m</span>
}
@else if (jump.x2data.altitude.deployment < 750) {
<mat-icon class="align-middle fs-5 me-2" fontIcon="local_florist" color="warn"></mat-icon>
<span class="text-warn fw-medium fs-5">{{ jump.x2data.altitude.deployment }} m</span>
}
@else if (jump.x2data.altitude.deployment > 1000) {
<mat-icon class="align-middle fs-5 me-2" fontIcon="mood" color="primary"></mat-icon>
<span class="text-primary fw-medium fs-5">{{ jump.x2data.altitude.deployment }} m</span>
}
</div>
</div>
<div class="row mt-4">
<div class="{{ jump.accessoires ? 'col-sm-6 ' : '' }}col-xs-12 text-center">
<h5 class="d-flex justify-content-center mb-4"><mat-icon fontIcon="people" class="me-2"></mat-icon> Participants ({{ jump.sautants.length + 1 }})</h5>
@for (sautant of jump.sautants; track sautant) {
<span class="badge rounded-pill bg-primary mb-2 me-1 pe-3 py-1 fw-normal text-dark">
<mat-icon class="align-middle me-1" fontIcon="person"></mat-icon>
{{ sautant }}
</span>
}
<span class="badge rounded-pill bg-accent mb-2 me-1 pe-3 py-1 fw-normal text-dark">
<mat-icon class="align-middle me-1" fontIcon="person"></mat-icon>
{{ jump.author.username }}
</span>
</div>
@if (jump.accessoires) {
<div class="col-sm-6 col-xs-12 text-center">
<h5 class="d-flex justify-content-center mb-4"><mat-icon fontIcon="auto_awesome" class="me-2"></mat-icon> Accessoires</h5>
<span class="badge rounded-pill bg-navy-light mb-2 me-1 pe-3 py-1 fw-normal">
<mat-icon class="align-middle me-1" fontIcon="auto_awesome"></mat-icon>
{{ jump.accessoires }}
</span>
</div>
}
</div>
</mat-card-content>
</mat-card>
<mat-card class="mt-3">
<mat-card-content>
<div class="row my-3">
<div class="col-xs-12 text-center">
<h5 class="d-flex justify-content-center mb-3"><mat-icon fontIcon="speed" class="me-1"></mat-icon> Vitesse en chute</h5>
</div>
<div class="col-sm-6 hidden-xs text-center">
<h6>Verticale</h6>
</div>
<div class="col-sm-6 hidden-xs text-center">
<h6>Horizontale</h6>
</div>
<div class="col-sm-3 col-xs-12 text-center">
<h6>Vitesse maximale</h6>
<span class="text-primary fw-medium fs-5">{{ (jump.x2data.speed.freeFall.vertical.max / 1000 * 60 * 60) | number : '1.0-0' }} km/h</span>
</div>
<div class="col-sm-3 col-xs-12 text-center">
<h6>Vitesse moyenne</h6>
<span class="text-primary fw-medium fs-5">{{ (jump.x2data.speed.freeFall.vertical.avg / 1000 * 60 * 60) | number : '1.0-0' }} km/h</span>
</div>
<div class="col-sm-3 col-xs-12 text-center">
<h6>Vitesse maximale</h6>
<span class="text-primary fw-medium fs-5">{{ (jump.x2data.speed.freeFall.horizontal.max / 1000 * 60 * 60) | number : '1.0-0' }} km/h</span>
</div>
<div class="col-sm-3 col-xs-12 text-center">
<h6>Vitesse moyenne</h6>
<span class="text-primary fw-medium fs-5">{{ (jump.x2data.speed.freeFall.horizontal.avg / 1000 * 60 * 60) | number : '1.0-0' }} km/h</span>
</div>
</div>
</mat-card-content>
</mat-card>
<mat-card class="mt-3">
<mat-card-content>
<div class="row my-3">
<div class="col-xs-12 text-center">
<h5 class="d-flex justify-content-center mb-3"><mat-icon fontIcon="speed" class="me-1"></mat-icon> Vitesse sous voile</h5>
</div>
<div class="col-sm-6 hidden-xs text-center">
<h6>Verticale</h6>
</div>
<div class="col-sm-6 hidden-xs text-center">
<h6>Horizontale</h6>
</div>
<div class="col-sm-3 col-xs-12 text-center">
<h6>Vitesse maximale</h6>
<span class="text-primary fw-medium fs-5">{{ (jump.x2data.speed.underCanopy.vertical.max / 1000 * 60 * 60) | number : '1.0-0' }} km/h</span>
</div>
<div class="col-sm-3 col-xs-12 text-center">
<h6>Vitesse moyenne</h6>
<span class="text-primary fw-medium fs-5">{{ (jump.x2data.speed.underCanopy.vertical.avg / 1000 * 60 * 60) | number : '1.0-0' }} km/h</span>
</div>
<div class="col-sm-3 col-xs-12 text-center">
<h6>Vitesse maximale</h6>
<span class="text-primary fw-medium fs-5">{{ (jump.x2data.speed.underCanopy.horizontal.max / 1000 * 60 * 60) | number : '1.0-0' }} km/h</span>
</div>
<div class="col-sm-3 col-xs-12 text-center">
<h6>Vitesse moyenne</h6>
<span class="text-primary fw-medium fs-5">{{ (jump.x2data.speed.underCanopy.horizontal.avg / 1000 * 60 * 60) | number : '1.0-0' }} km/h</span>
</div>
</div>
</mat-card-content>
</mat-card>
<mat-card class="mt-3">
<mat-card-content>
<div class="row my-3">
<div class="col-xs-12 text-center">
<h5 class="d-flex justify-content-center mb-3"><mat-icon fontIcon="square_foot" class="me-1"></mat-icon> Finesse</h5>
</div>
<div class="col-sm-6 hidden-xs text-center">
<h6>En chute</h6>
</div>
<div class="col-sm-6 hidden-xs text-center">
<h6>Sous voile</h6>
</div>
<div class="col-sm-3 col-xs-12 text-center">
<h6>Finesse Max</h6>
<span class="text-primary fw-medium fs-5">{{ jump.x2data.glideRatio.freeFall.max | number : '1.2-2' }}</span>
</div>
<div class="col-sm-3 col-xs-12 text-center">
<h6>Finesse Moyenne</h6>
<span class="text-primary fw-medium fs-5">{{ jump.x2data.glideRatio.freeFall.avg | number : '1.2-2' }}</span>
</div>
<div class="col-sm-3 col-xs-12 text-center">
<h6>Finesse Max</h6>
<span class="text-primary fw-medium fs-5">{{ jump.x2data.glideRatio.underCanopy.max | number : '1.2-2' }}</span>
</div>
<div class="col-sm-3 col-xs-12 text-center">
<h6>Finesse Moyenne</h6>
<span class="text-primary fw-medium fs-5">{{ jump.x2data.glideRatio.underCanopy.avg | number : '1.2-2' }}</span>
</div>
</div>
</mat-card-content>
</mat-card>
<mat-card class="mt-3">
<mat-card-content>
<div class="row my-3">
<div class="col-xs-12 text-center">
<h5 class="d-flex justify-content-center mb-3"><mat-icon fontIcon="straighten" class="me-1"></mat-icon> Distance</h5>
</div>
<div class="col-sm-3 col-xs-12 text-center">
<h6>Distance au largage</h6>
<span class="text-primary fw-medium fs-5">{{ jump.x2data.distance.exitFromLandingZone| number : '1.0-0' }} m</span>
</div>
<div class="col-sm-3 col-xs-12 text-center">
<h6>Durée sous voile</h6>
<span class="text-primary fw-medium fs-5">{{ formatDuration(jump.x2data.duration.underCanopy) }}</span>
</div>
<div class="col-sm-3 col-xs-12 text-center">
<h6>Distance totale</h6>
<span class="text-primary fw-medium fs-5">{{ jump.x2data.distance.totalFlying | number : '1.0-0' }} m</span>
</div>
<div class="col-sm-3 col-xs-12 text-center">
<h6>Distance horizontale</h6>
<span class="text-primary fw-medium fs-5">{{ jump.x2data.distance.totalHorizontal | number : '1.0-0' }} m</span>
</div>
</div>
</mat-card-content>
</mat-card>
}
@else {
<mat-card class="mt-3">
<mat-card-content>
<div class="row my-3">
<div class="col-xs-12 text-center">
<h5 class="d-flex justify-content-center mb-4"><mat-icon fontIcon="people" class="me-1"></mat-icon> Participants ({{ jump.sautants.length + 1 }})</h5>
@for (sautant of jump.sautants; track sautant) {
<span class="badge rounded-pill bg-primary mb-2 me-1 pe-3 py-1 fw-normal text-dark">
<mat-icon class="align-middle me-1" fontIcon="person"></mat-icon>
{{ sautant }}
</span>
}
<span class="badge rounded-pill bg-accent mb-2 me-1 pe-3 py-1 fw-normal text-dark">
<mat-icon class="align-middle me-1" fontIcon="person"></mat-icon>
{{ jump.author.username }}
</span>
</div>
</div>
</mat-card-content>
</mat-card>
<mat-card class="mt-3">
<mat-card-content>
<div class="d-flex justify-content-center my-3 fs-5"><mat-icon fontIcon="satellite_alt" class="me-2"></mat-icon> Aucune donnée GPS</div>
</mat-card-content>
</mat-card>
}