From 7c3f0c9648f78d82e53f64e0652dbe41b033ba82 Mon Sep 17 00:00:00 2001 From: Rampeur Date: Wed, 8 May 2024 20:32:49 +0200 Subject: [PATCH] =?UTF-8?q?Impl=C3=A9mentation=20SkydiverId=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/aeronef/aeronef.component.html | 90 ++-- src/app/components/auth/auth.component.html | 2 +- .../calculator/calculator.component.html | 510 +++++++++--------- .../components/canopy/canopy.component.html | 104 ++-- .../dashboard/dashboard.component.html | 66 ++- .../dropzone/dropzone.component.html | 102 ++-- src/app/components/home/home.component.html | 155 +++++- src/app/components/home/home.component.scss | 17 + src/app/components/home/home.component.ts | 8 + src/app/components/index.ts | 1 + src/app/components/jump/jump.component.html | 409 +++++++++----- .../components/jump/jump.component.spec.ts | 10 +- src/app/components/jump/jump.component.ts | 243 ++------- src/app/components/jumps/jumps.component.html | 130 +++++ src/app/components/jumps/jumps.component.scss | 0 .../components/jumps/jumps.component.spec.ts | 21 + src/app/components/jumps/jumps.component.ts | 249 +++++++++ .../logbook/dialogs/jump-add.dialog.html | 2 +- .../logbook/dialogs/jump-edit.dialog.html | 2 +- .../logbook/dialogs/jump-view.dialog.html | 271 +++++++--- .../logbook/dialogs/jump-view.dialog.ts | 16 +- .../components/logbook/logbook.component.html | 196 ++++--- .../components/profile/profile.component.html | 14 +- .../components/profile/profile.component.scss | 1 + src/app/components/qcm/qcm.component.html | 85 +-- src/app/components/qcm/qcm.component.scss | 37 ++ src/app/components/qcm/qcm.component.ts | 93 +++- .../credentials/credentials.component.html | 2 +- .../credentials/credentials.component.scss | 1 + .../settings/settings.component.html | 2 +- .../settings/settings.component.scss | 1 + .../jumps-by-month.component.ts | 3 +- .../helpers-jump/jump-table.component.html | 47 +- .../helpers-jump/jump-table.component.ts | 240 +++++++-- .../shared/layout/full.component.html | 6 +- .../shared/layout/full.component.ts | 1 - .../shared/layout/header.component.html | 128 +---- src/app/components/shared/menu-items.ts | 12 +- src/app/core/models/index.ts | 2 +- src/app/core/models/jump-list-config.model.ts | 2 + src/app/core/models/jump.model.ts | 97 ++++ src/app/core/models/menu.model.ts | 1 + src/app/core/models/shared.model.ts | 30 ++ .../core/resolvers/jump-resolver.service.ts | 4 +- src/app/core/services/applications.service.ts | 4 +- src/app/core/services/calculator.service.ts | 34 +- src/app/core/services/jump-table.service.ts | 4 +- src/app/core/services/jumps.service.ts | 80 ++- src/app/core/services/utilities.service.ts | 2 +- src/app/routes/auth.routes.ts | 27 +- src/assets/images/logo_angular.svg | 22 + src/assets/images/logo_headup.svg | 120 +---- src/assets/images/logo_headup_large.svg | 5 + src/styles/app.scss | 7 +- 54 files changed, 2323 insertions(+), 1395 deletions(-) create mode 100644 src/app/components/jumps/jumps.component.html create mode 100644 src/app/components/jumps/jumps.component.scss create mode 100644 src/app/components/jumps/jumps.component.spec.ts create mode 100644 src/app/components/jumps/jumps.component.ts create mode 100644 src/app/core/models/shared.model.ts create mode 100644 src/assets/images/logo_angular.svg create mode 100644 src/assets/images/logo_headup_large.svg diff --git a/src/app/components/aeronef/aeronef.component.html b/src/app/components/aeronef/aeronef.component.html index 1de33cb..9ab18b9 100644 --- a/src/app/components/aeronef/aeronef.component.html +++ b/src/app/components/aeronef/aeronef.component.html @@ -1,51 +1,49 @@
-
-
-
-

{{title}}

- - Dernier saut enregistré : {{ lastJump.numero }}ème à {{ lastJump.lieu }} le {{ lastJump.date | date: 'dd/MM/yyyy' }} - -
- -
- - - @for (menuitem of menuItems.getMenuPanel(); track menuitem) { - - } - -
+
+
+

{{title}}

+ + Dernier saut enregistré : {{ lastJump.numero }}ème à {{ lastJump.lieu }} le {{ lastJump.date | date: 'dd/MM/yyyy' }} +
- - - - {{ subtitle }} - - - @if (displayCharts) { -
-
- -
-
- - -
-
+ +
+ + + @for (menuitem of menuItems.getMenuPanel(); track menuitem) { + } -
-
- - -
-
- - +
+
+ + + + {{ subtitle }} + + + @if (displayCharts) { +
+
+ +
+
+ + +
+
+ } +
+
+ + +
+
+
+
\ No newline at end of file diff --git a/src/app/components/auth/auth.component.html b/src/app/components/auth/auth.component.html index 3877036..c914655 100644 --- a/src/app/components/auth/auth.component.html +++ b/src/app/components/auth/auth.component.html @@ -1,4 +1,4 @@ -
+

{{ title }}

diff --git a/src/app/components/calculator/calculator.component.html b/src/app/components/calculator/calculator.component.html index e76176c..3214fdb 100644 --- a/src/app/components/calculator/calculator.component.html +++ b/src/app/components/calculator/calculator.component.html @@ -1,259 +1,257 @@
-
-
-
-

{{title}}

- DT48 - 08 février 2024 -
- -
- - - @for (menuitem of menuItems.getMenuCalculator(); track menuitem) { - @if (menuitem.type === 'link') { - - } - } - -
+
+
+

{{title}}

+ DT48 - 08 février 2024 +
+ +
+ + + @for (menuitem of menuItems.getMenuCalculator(); track menuitem) { + @if (menuitem.type === 'link') { + + } + } +
- - - -
- - Nombre de sauts - - - - Poids nu - - - - Poids équipement - - - - Taille actuelle - - -
- -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Taille actuelleTaille minTaille min -11%
Taille de voile en ft2 ● - {{ info.sizesFeet.current }} ● {{ info.sizesFeet.min }} ● {{ info.sizesFeet.min11 }}
Charge alaire{{ info.charges.current | number : '1.2-3' }}{{ info.charges.min | number : '1.2-3' }}{{ info.charges.min11 | number : '1.2-3' }}
Taille de voile en m2{{ info.sizesMeter.current | number : '1.2-3' }}{{ info.sizesMeter.min | number : '1.2-3' }}{{ info.sizesMeter.min11 | number : '1.2-3' }}
Coefficient kilo/livres{{ coeffKgLbs }}
Coefficient pied/mètre{{ coeffFtM }}
Formule charge alaire - ( ( {{ inputs.weight }} + {{ inputs.gear }} ) * {{ coeffKgLbs }} ) / - {{ inputs.current }} = {{ info.charges.current | number : '1.5' }}
- ( ( poids nu en kg + poids equipement en kg ) * coefficient kg/lbs ) / taille de - voile en ft2 -
-
-
- @if (displayCharts) { -
- - -
- } -
-
- -

Tailles de voile pour {{ inputs.weight }} kg

-
- Prochain changement de valeurs dans {{ ((this.currentRange.end + 1) - inputs.jumps) }} - {{ ((this.currentRange.end + 1) - inputs.jumps) > 1 ? 'sauts' : 'saut'}}
-
-
- {{ ((((inputs.jumps - this.currentRange.start) + 1) / ((this.currentRange.end - this.currentRange.start) + 1)) * 100) | number : '1.2-2' }}% - de la tranche actuelle ({{this.currentRange.start}} à {{this.currentRange.end}}) -
- - - - - - @for (header of sizesHeader; track header; let index = $index) { - - } - - - - - - @for (value of sizesValuesFeet; track value; let index = $index) { - - } - - - - @for (value of sizesMinValuesFeet; track value; let index = $index) { - - } - - - - @for (charge of sizesCharges; track charge; let index = $index) { - - } - - - - @for (value of sizesValuesMeter; track value; let index = $index) { - - } - - -
{{ header.name }}
Taille de voile en ft2{{ value }}
Abbattement 11%{{ value }}
Charge alaire - {{ charge | number : '1.2-3' }}
Taille de voile en m2 - {{ value | number : '1.2-2' }}
- -

Tableau des tailles de voile par poids

-
- {{ ((inputs.jumps / 1600) * 100) | number : '1.2-2' }}% de la plage complète (0 à 1600) -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- {{tableHeader[0].name}} - {{element.weight}} - - {{tableHeader[1].name}} {{element.ranges[0].value}} - {{tableHeader[2].name}} {{element.ranges[1].value}} - {{tableHeader[3].name}} {{element.ranges[2].value}} - {{tableHeader[4].name}} {{element.ranges[3].value}} - {{tableHeader[5].name}} {{element.ranges[4].value}} - {{tableHeader[6].name}} {{element.ranges[5].value}} - {{tableHeader[7].name}} {{element.ranges[6].value}} - {{tableHeader[8].name}} {{element.ranges[7].value}} - {{tableHeader[9].name}} {{element.ranges[8].value}}
-
- -
-
-
-
+ + + +
+ + Nombre de sauts + + + + Poids nu + + + + Poids équipement + + + + Taille actuelle + + +
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Taille actuelleTaille minTaille min -11%
Taille de voile en ft2 ● + {{ info.sizesFeet.current }} ● {{ info.sizesFeet.min }} ● {{ info.sizesFeet.min11 }}
Charge alaire{{ info.charges.current | number : '1.2-3' }}{{ info.charges.min | number : '1.2-3' }}{{ info.charges.min11 | number : '1.2-3' }}
Taille de voile en m2{{ info.sizesMeter.current | number : '1.2-3' }}{{ info.sizesMeter.min | number : '1.2-3' }}{{ info.sizesMeter.min11 | number : '1.2-3' }}
Coefficient kilo/livres{{ coeffKgLbs }}
Coefficient pied/mètre{{ coeffFtM }}
Formule charge alaire + ( ( {{ inputs.weight }} + {{ inputs.gear }} ) * {{ coeffKgLbs }} ) / + {{ inputs.current }} = {{ info.charges.current | number : '1.5' }}
+ ( ( poids nu en kg + poids equipement en kg ) * coefficient kg/lbs ) / taille de + voile en ft2 +
+
+
+ @if (displayCharts) { +
+ + +
+ } +
+
+ +

Tailles de voile pour {{ inputs.weight }} kg

+
+ Prochain changement de valeurs dans {{ ((this.currentRange.end + 1) - inputs.jumps) }} + {{ ((this.currentRange.end + 1) - inputs.jumps) > 1 ? 'sauts' : 'saut'}}
+
+
+ {{ ((((inputs.jumps - this.currentRange.start) + 1) / ((this.currentRange.end - this.currentRange.start) + 1)) * 100) | number : '1.2-2' }}% + de la tranche actuelle ({{this.currentRange.start}} à {{this.currentRange.end}}) +
+ + + + + + @for (header of sizesHeader; track header; let index = $index) { + + } + + + + + + @for (value of sizesValuesFeet; track value; let index = $index) { + + } + + + + @for (value of sizesMinValuesFeet; track value; let index = $index) { + + } + + + + @for (charge of sizesCharges; track charge; let index = $index) { + + } + + + + @for (value of sizesValuesMeter; track value; let index = $index) { + + } + + +
{{ header.name }}
Taille de voile en ft2{{ value }}
Abbattement 11%{{ value }}
Charge alaire + {{ charge | number : '1.2-3' }}
Taille de voile en m2 + {{ value | number : '1.2-2' }}
+ +

Tableau des tailles de voile par poids

+
+ {{ ((inputs.jumps / 1600) * 100) | number : '1.2-2' }}% de la plage complète (0 à 1600) +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ {{tableHeader[0].name}} + {{element.weight}} + + {{tableHeader[1].name}} {{element.ranges[0].value}} + {{tableHeader[2].name}} {{element.ranges[1].value}} + {{tableHeader[3].name}} {{element.ranges[2].value}} + {{tableHeader[4].name}} {{element.ranges[3].value}} + {{tableHeader[5].name}} {{element.ranges[4].value}} + {{tableHeader[6].name}} {{element.ranges[5].value}} + {{tableHeader[7].name}} {{element.ranges[6].value}} + {{tableHeader[8].name}} {{element.ranges[7].value}} + {{tableHeader[9].name}} {{element.ranges[8].value}}
+
+ +
+
+
+
\ No newline at end of file diff --git a/src/app/components/canopy/canopy.component.html b/src/app/components/canopy/canopy.component.html index 50acdec..7bdd887 100644 --- a/src/app/components/canopy/canopy.component.html +++ b/src/app/components/canopy/canopy.component.html @@ -1,58 +1,56 @@
-
-
-
-

{{title}}

- - Dernier saut enregistré : {{ lastJump.numero }}ème à {{ lastJump.lieu }} le {{ lastJump.date | date: 'dd/MM/yyyy' }} - -
- -
- - - @for (menuitem of menuItems.getMenuPanel(); track menuitem) { - - } - -
+
+
+

{{title}}

+ + Dernier saut enregistré : {{ lastJump.numero }}ème à {{ lastJump.lieu }} le {{ lastJump.date | date: 'dd/MM/yyyy' }} +
- - - - {{ subtitle }} - - - @if (displayCharts) { -
-
- -
-
- -
-
- - -
-
+ +
+ + + @for (menuitem of menuItems.getMenuPanel(); track menuitem) { + } -
-
- - -
-
- - -
-
- - +
+
+ + + + {{ subtitle }} + + + @if (displayCharts) { +
+
+ +
+
+ +
+
+ + +
+
+ } +
+
+ + +
+
+ + +
+
+
+
\ No newline at end of file diff --git a/src/app/components/dashboard/dashboard.component.html b/src/app/components/dashboard/dashboard.component.html index 71148cd..e05f6dc 100644 --- a/src/app/components/dashboard/dashboard.component.html +++ b/src/app/components/dashboard/dashboard.component.html @@ -1,38 +1,36 @@ -
-

{{title}}

- - Dernier saut enregistré : {{ lastJump.numero }}ème à {{ lastJump.lieu }} le {{ lastJump.date | date: 'dd/MM/yyyy' }} - - - -
-
- -
+

{{title}}

+ + Dernier saut enregistré : {{ lastJump.numero }}ème à {{ lastJump.lieu }} le {{ lastJump.date | date: 'dd/MM/yyyy' }} + + + +
+
+
-
-
- -
-
- -
+
+
+
+
-
-
- -
-
- -
+
+
-
-
- -
-
- -
+
+
+
+
- -
\ No newline at end of file +
+ +
+
+
+
+ +
+
+ +
+
+ \ No newline at end of file diff --git a/src/app/components/dropzone/dropzone.component.html b/src/app/components/dropzone/dropzone.component.html index af44860..c9bbc23 100644 --- a/src/app/components/dropzone/dropzone.component.html +++ b/src/app/components/dropzone/dropzone.component.html @@ -1,57 +1,55 @@
-
-
-
-

{{title}}

- - Dernier saut enregistré : {{ lastJump.numero }}ème à {{ lastJump.lieu }} le {{ lastJump.date | date: 'dd/MM/yyyy' }} - -
- -
- - - @for (menuitem of menuItems.getMenuPanel(); track menuitem) { - - } - -
+
+
+

{{title}}

+ + Dernier saut enregistré : {{ lastJump.numero }}ème à {{ lastJump.lieu }} le {{ lastJump.date | date: 'dd/MM/yyyy' }} +
- - - - {{ subtitle }} - - - @if (displayCharts) { -
-
- -
-
- - -
-
+ +
+ + + @for (menuitem of menuItems.getMenuPanel(); track menuitem) { + } -
-
- - -
-
- - +
+
+ + + + {{ subtitle }} + + + @if (displayCharts) { +
+
+ +
+
+ + +
+
+ } +
+
+ + +
+
+
+
\ No newline at end of file diff --git a/src/app/components/home/home.component.html b/src/app/components/home/home.component.html index 91d2e48..36ce21e 100644 --- a/src/app/components/home/home.component.html +++ b/src/app/components/home/home.component.html @@ -1,26 +1,137 @@
-
-
-
-

{{title}}

- - Dernier saut enregistré : {{ lastJump.numero }}ème à {{ lastJump.lieu }} le {{ lastJump.date | date: 'dd/MM/yyyy' }} - -
- -
-

Home works!

-
+
+
+

{{title}}

+ + Dernier saut enregistré : {{ lastJump.numero }}ème à {{ lastJump.lieu }} le {{ lastJump.date | date: 'dd/MM/yyyy' }} + +
+ +
+ {{ now | date: 'dd/MM/yyyy' }} + @if (!isJumpDay) { +
Aucun saut aujourd'hui + }
- - - - - Card title - - -

Home works!

-
-
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
\ No newline at end of file diff --git a/src/app/components/home/home.component.scss b/src/app/components/home/home.component.scss index e69de29..5fe7004 100644 --- a/src/app/components/home/home.component.scss +++ b/src/app/components/home/home.component.scss @@ -0,0 +1,17 @@ +/* Home */ +//@use 'variable' as var; + + +/* +#FF41F8 +#F0060B +#F0070C +#CC26D5 +#7702FF + +#35A2EB +#B7DDD0 +#B0D9CB +#D9CAAE +#9788C7 +*/ diff --git a/src/app/components/home/home.component.ts b/src/app/components/home/home.component.ts index 5e0ab37..28ad6ac 100644 --- a/src/app/components/home/home.component.ts +++ b/src/app/components/home/home.component.ts @@ -41,6 +41,8 @@ export class HomeComponent implements OnInit { public errors: Errors = { errors: {} }; public lastJump: Jump = {} as Jump; public destroyRef = inject(DestroyRef); + public now = new Date(); + public isJumpDay = false; constructor( private _jumpsService: JumpsService @@ -50,6 +52,12 @@ export class HomeComponent implements OnInit { this._lastjump$ = this._jumpsService.getLastJump().pipe(takeUntilDestroyed(this.destroyRef)); this._lastjump = this._lastjump$.subscribe((jump) => { this.lastJump = jump; + this.isJumpDay = this._isToday(new Date(this.lastJump.date)); }); } + private _isToday(someDate: Date) { + return someDate.getDate() == this.now.getDate() && + someDate.getMonth() == this.now.getMonth() && + someDate.getFullYear() == this.now.getFullYear() + } } diff --git a/src/app/components/index.ts b/src/app/components/index.ts index 8e6ecbb..9f98f67 100644 --- a/src/app/components/index.ts +++ b/src/app/components/index.ts @@ -6,6 +6,7 @@ export * from './dashboard/dashboard.component'; export * from './dropzone/dropzone.component'; export * from './home/home.component'; export * from './jump/jump.component'; +export * from './jumps/jumps.component'; export * from './logbook/logbook.component'; export * from './profile/profile.component'; export * from './qcm/qcm.component'; diff --git a/src/app/components/jump/jump.component.html b/src/app/components/jump/jump.component.html index fd296b1..9726868 100644 --- a/src/app/components/jump/jump.component.html +++ b/src/app/components/jump/jump.component.html @@ -1,132 +1,283 @@ -
-
-
-
-

{{title}}

- - Dernier saut enregistré : {{ lastJump.numero }}ème à {{ lastJump.lieu }} le {{ lastJump.date | date: 'dd/MM/yyyy' }} - -
- -
- +
+ {{ jump.numero }} +
+ +
+
+ + + @if (jump.x2data) { + - - @for (menuitem of menuItems.getMenuPanel(); track menuitem) { - - } - -
-
- - - - {{ subtitle }} - - - @if(displayCharts) { -
-
- -
-
- -
-
- } -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{{ name }} Total
● {{ seriesName[i] }} - {{ value }} - {{ value }} - {{ seriesRowTotal[i] }}
Total - {{ value }} - {{ value }} - {{ grandTotal }}
Moyenne - {{ value | number : '1.0-1' }} - {{ value | number : '1.0-1' }} - {{ grandAvg | number : '1.0-1' }}
Moyenne 3 dernières années - {{ value | number : '1.0-1' }} - {{ value | number : '1.0-1' }} - {{ grandAvgLastYears | number : '1.0-1' }}
-
-
-
-
- - - Types de sauts - - - @if(displayCharts) { -
-
- -
-
- -
- @for (item of getCategories(); track $index) { -
- -
- } - @for (item of getModules(); track $index) { -
- -
- } -
- - - } -
-
+ + } + @for (menuitem of menuItems.getMenuJump(); track menuitem) { + + } +
+ + + +
+
+
+
Aeronef:
+
{{ jump.aeronef }} {{ jump.imat }}
+
Voile:
+
{{ jump.voile }} {{ jump.taille }} ft2
+ @if (jump.programme) { +
Programme:
+
{{ jump.programme }}
+ } +
+
+
+
+ @if (!jump.x2data) { +
Hauteur:
+
{{ jump.hauteur }} m
+
Déploiement:
+
{{ jump.deploiement }} m
+ } + @for (file of jump.files; track file) { +
Fichier {{ file.type }}
+
{{ file.name }}
+ } +
+
+
+
+
+@if (jump.x2data) { + + +
+
+
Hauteur
+ @if (jump.x2data.altitude.exit > 4200) { + + } + {{ jump.x2data.altitude.exit }} m +
+
+
Durée de la chute
+ {{ formatDuration(jump.x2data.duration.freeFall) }} +
+
+
Déploiement
+ @if (jump.x2data.altitude.deployment < 650) { + + {{ jump.x2data.altitude.deployment }} m + } + @else if (jump.x2data.altitude.deployment < 750) { + + {{ jump.x2data.altitude.deployment }} m + } + @else if (jump.x2data.altitude.deployment > 1000) { + + {{ jump.x2data.altitude.deployment }} m + } +
+
+
+
+
Participants ({{ jump.sautants.length + 1 }})
+ @for (sautant of jump.sautants; track sautant) { + + + {{ sautant }} + + } + + + {{ jump.author.username }} + +
+ @if (jump.accessoires) { +
+
Accessoires
+ + + {{ jump.accessoires }} + +
+ } +
+
+
+ + +
+
+
Vitesse en chute
+
+ + +
+
Vitesse maximale
+ {{ (jump.x2data.speed.freeFall.vertical.max / 1000 * 60 * 60) | number : '1.0-0' }} km/h +
+
+
Vitesse moyenne
+ {{ (jump.x2data.speed.freeFall.vertical.avg / 1000 * 60 * 60) | number : '1.0-0' }} km/h +
+
+
Vitesse maximale
+ {{ (jump.x2data.speed.freeFall.horizontal.max / 1000 * 60 * 60) | number : '1.0-0' }} km/h +
+
+
Vitesse moyenne
+ {{ (jump.x2data.speed.freeFall.horizontal.avg / 1000 * 60 * 60) | number : '1.0-0' }} km/h +
+
+
+
+ + +
+
+
Vitesse sous voile
+
+ + +
+
Vitesse maximale
+ {{ (jump.x2data.speed.underCanopy.vertical.max / 1000 * 60 * 60) | number : '1.0-0' }} km/h +
+
+
Vitesse moyenne
+ {{ (jump.x2data.speed.underCanopy.vertical.avg / 1000 * 60 * 60) | number : '1.0-0' }} km/h +
+
+
Vitesse maximale
+ {{ (jump.x2data.speed.underCanopy.horizontal.max / 1000 * 60 * 60) | number : '1.0-0' }} km/h +
+
+
Vitesse moyenne
+ {{ (jump.x2data.speed.underCanopy.horizontal.avg / 1000 * 60 * 60) | number : '1.0-0' }} km/h +
+
+
+
+ + +
+
+
Finesse
+
+ + +
+
Finesse Max
+ {{ jump.x2data.glideRatio.freeFall.max | number : '1.2-2' }} +
+
+
Finesse Moyenne
+ {{ jump.x2data.glideRatio.freeFall.avg | number : '1.2-2' }} +
+
+
Finesse Max
+ {{ jump.x2data.glideRatio.underCanopy.max | number : '1.2-2' }} +
+
+
Finesse Moyenne
+ {{ jump.x2data.glideRatio.underCanopy.avg | number : '1.2-2' }} +
+
+
+
+ + +
+
+
Distance
+
+
+
Distance au largage
+ {{ jump.x2data.distance.exitFromLandingZone| number : '1.0-0' }} m +
+
+
Durée sous voile
+ {{ formatDuration(jump.x2data.duration.underCanopy) }} +
+
+
Distance totale
+ {{ jump.x2data.distance.totalFlying | number : '1.0-0' }} m +
+
+
Distance horizontale
+ {{ jump.x2data.distance.totalHorizontal | number : '1.0-0' }} m +
+
+
+
+} +@else { + + +
+
+
Participants ({{ jump.sautants.length + 1 }})
+ @for (sautant of jump.sautants; track sautant) { + + + {{ sautant }} + + } + + + {{ jump.author.username }} + +
+
+
+
+ + +
Aucune donnée GPS
+
+
+} \ No newline at end of file diff --git a/src/app/components/jump/jump.component.spec.ts b/src/app/components/jump/jump.component.spec.ts index 8915da0..474dc8c 100644 --- a/src/app/components/jump/jump.component.spec.ts +++ b/src/app/components/jump/jump.component.spec.ts @@ -6,10 +6,12 @@ describe('JumpComponent', () => { let component: JumpComponent; let fixture: ComponentFixture; - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [JumpComponent] -}); + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [JumpComponent] + }) + .compileComponents(); + fixture = TestBed.createComponent(JumpComponent); component = fixture.componentInstance; fixture.detectChanges(); diff --git a/src/app/components/jump/jump.component.ts b/src/app/components/jump/jump.component.ts index 241335f..5ef29bf 100644 --- a/src/app/components/jump/jump.component.ts +++ b/src/app/components/jump/jump.component.ts @@ -1,248 +1,71 @@ -import { trigger, state, style, animate, transition } from '@angular/animations'; import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core'; import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; -import { ActivatedRoute } from '@angular/router'; -import { CommonModule } from '@angular/common'; +import { DatePipe, DecimalPipe } from '@angular/common'; +import { ActivatedRoute, RouterLink } from '@angular/router'; import { MatButtonModule } from '@angular/material/button'; import { MatCardModule } from '@angular/material/card'; import { MatDividerModule } from '@angular/material/divider'; -import { MatExpansionModule } from '@angular/material/expansion'; import { MatIconModule } from '@angular/material/icon'; import { MatMenuModule } from '@angular/material/menu'; - import { Observable, Subscription } from 'rxjs'; -import { MenuItems } from 'src/app/components/shared'; -import { BarsChartComponent, CircleChartComponent, LineChartComponent, LineAreaChartComponent } from 'src/app/components/shared/helpers-chart'; -import { UtilitiesService } from 'src/app/core/services'; -import { Jump, JumpByCategorie, JumpByDate, JumpByDateByModule, JumpByModule, JumpsPageData, JumpYears } from 'src/app/core/models'; +import { ListErrorsComponent, MenuItems } from 'src/app/components/shared'; +import { Errors, Jump, JumpPageData } from 'src/app/core/models'; @Component({ selector: 'app-jump', standalone: true, imports: [ - CommonModule, - MatButtonModule, MatCardModule, MatDividerModule, - MatExpansionModule, MatIconModule, MatMenuModule, - BarsChartComponent, CircleChartComponent, LineChartComponent, LineAreaChartComponent + DatePipe, DecimalPipe, RouterLink, + MatButtonModule, MatCardModule, + MatDividerModule, MatIconModule, MatMenuModule, + ListErrorsComponent ], templateUrl: './jump.component.html', - styleUrl: './jump.component.scss', - animations: [ - trigger('flyInOut', [ - state('in', style({ transform: 'translateX(0)' })), - transition('void => *', [ - style({ transform: 'translateX(-100%)' }), - animate(200) - ]), - transition('* => void', [ - style({ transform: 'translateX(100%)' }), - animate(200) - ]) - ]) - ] + styleUrl: './jump.component.scss' }) export class JumpComponent implements OnInit, OnDestroy { private _data: Subscription = new Subscription(); - private _jumpsByCategorie: Array = []; - private _jumpsByModule: Array = []; - private _jumpsByDate: Array = []; - public lastJump: Jump = {} as Jump; - public title: string = 'Sauts'; - public subtitle: string = 'Nombre total de sauts par mois'; - public displayCharts = false; + public title: string = ''; + public errors: Errors = { errors: {} }; public destroyRef = inject(DestroyRef); - public min = 0; - public max = 0; - public grandAvg = 0; - public grandAvgLastYears = 0; - public grandTotal = 0; - public seriesHeader: string[] = []; - public seriesName: string[] = []; - public seriesRow: Array> = []; - public seriesColor: { - backgroundColor: string[], - borderColor: string[] - } = { - backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'), - borderColor: this._utilitiesService.getSeriesColors(1, 'all') - }; - public seriesTypesHeader: string[] = []; - public seriesTypesName: string[] = []; - public seriesTypesRow: Array> = []; - public seriesTypesRowCumulated: Array> = []; - public seriesTypesColor: { - backgroundColor: string[], - borderColor: string[] - } = { - backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'pastels'), - borderColor: this._utilitiesService.getSeriesColors(1, 'pastels') - }; - public seriesColorClass: string[] = this._utilitiesService.getChartColors(); - public seriesRowTotal: number[] = []; - public seriesRowAvg: number[] = []; - public seriesRowAvgLastYears: number[] = []; - public seriesColTotal: number[] = []; - public seriesColTotalClosed: number[] = []; - public seriesColTotalLastYears: number[] = []; + public jump: Jump = {} as Jump; + public prevSlug: string = ''; + public nextSlug: string = ''; constructor( private route: ActivatedRoute, - private _utilitiesService: UtilitiesService, public menuItems: MenuItems ) { } ngOnInit() { - const data$: Observable<{ jumpsPageData: JumpsPageData }> = this.route.data as Observable<{ jumpsPageData: JumpsPageData }>; - this._data = data$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: { jumpsPageData: JumpsPageData }) => { - const pageData: JumpsPageData = data.jumpsPageData; - this.lastJump = pageData.lastjump; - const currentYear: number = new Date().getFullYear(); - const types: Array = ['FF', 'Solo', 'VR', 'Wingsuit']; - const verticals: Array = ['Chutas', 'Head Up', 'Head Down']; - const others: Array = ['Track', 'Trace']; - const modules: Array = [...verticals, ...others]; - this.min = pageData.jumpsByYears[0].year; - this.max = pageData.jumpsByYears[(pageData.jumpsByYears.length-1)].year; - - this.seriesHeader = this._utilitiesService.getMonthsList(); - const values: Array = this.seriesHeader.map(() => 0); - this.seriesColTotal = [...values]; - this.seriesColTotalClosed = [...values]; - this.seriesColTotalLastYears = [...values]; - this.seriesName = pageData.jumpsByYears.map((row: JumpYears) => { - this.seriesRow.push([...values]); - return row.year.toString(); - }); - - this._jumpsByDate = pageData.jumpsByDate.map((row: JumpByDate) => { - this.seriesRow[(row.year-this.min)][(row.month-1)] = row.count; - this.seriesColTotal[(row.month-1)] += row.count; - if (row.year < currentYear) { - this.seriesColTotalClosed[(row.month-1)] += row.count; - } - if (row.year >= (currentYear-3) && row.year < currentYear) { - this.seriesColTotalLastYears[(row.month-1)] += row.count; - } - return row; - }); - this.seriesRow.forEach((row: number[]) => { - const total = row.reduce((partialSum, a) => partialSum + a, 0); - this.seriesRowTotal.push(total); - }); - this.seriesColTotalClosed.forEach((row: number) => { - const value: number = (row/(this.seriesName.length-2)); // -2 pour ne pas compter la première année - this.seriesRowAvg.push(parseInt(value.toFixed(0))); - }); - this.seriesColTotalLastYears.forEach((row: number) => { - const value: number = (row/3); // Les 3 dernières années - this.seriesRowAvgLastYears.push(parseInt(value.toFixed(0))); - }); - this.grandAvg = this.seriesRowAvg.reduce((partialSum, accumulated) => partialSum + accumulated, 0); - this.grandAvgLastYears = this.seriesRowAvgLastYears.reduce((partialSum, accumulated) => partialSum + accumulated, 0); - this.grandTotal = this.seriesColTotal.reduce((partialSum, accumulated) => partialSum + accumulated, 0); - - pageData.jumpsByCategory.forEach((row: JumpByCategorie) => { - if (types.indexOf(row.categorie) !== -1) { - this._jumpsByCategorie.push(row); - } - }); - - //const focus: Array = ['FF', 'Solo']; // ['FF'] - let verticalCount:number = 0; - let otherCount:number = 0; - pageData.jumpsByModule.forEach((row: JumpByModule) => { - //if (focus.indexOf(row.categorie) !== -1 && modules.indexOf(row.module) !== -1) { - if (modules.indexOf(row.module) !== -1) { - if (verticals.indexOf(row.module) !== -1) { - verticalCount += row.count; - } else { - otherCount += row.count; - } - } - }); - if (verticalCount > 0) { - const row:JumpByModule = { - categorie: 'FF', - module: 'Vertical', - count: verticalCount - } - this._jumpsByModule.push(row); - } - if (otherCount > 0) { - const row:JumpByModule = { - categorie: 'FF', - module: 'Track/Trace', - count: otherCount - } - this._jumpsByModule.push(row); - } - - for (let year = 0; year < pageData.jumpsByYears.length; year++) { - for (let index = 0; index < 12; index++) { - const month: string = ((index+1) < 10) ? `0${(index+1)}` : `${(index+1)}`; - this.seriesTypesHeader.push(`${month}-${pageData.jumpsByYears[year].year}`); - } - } - const emptyValues: Array = this.seriesTypesHeader.map(() => 0); - this.seriesTypesName = types; - this.seriesTypesName.forEach(() => { - this.seriesTypesRow.push([...emptyValues]); - }); - pageData.jumpsByDateByModule.forEach((row: JumpByDateByModule) => { - const indexOf: number = this.seriesTypesName.indexOf(row.categorie); - if (indexOf !== -1) { - this.seriesTypesRow[indexOf][(((row.year-this.min)*12)+row.month-1)] += row.count; - } - }); - this.seriesTypesRowCumulated = this.seriesTypesRow.map((row: Array) => { - let accumulated: number = 0; - return row.map((value: number) => { - accumulated += value; - return accumulated; - }); - }); - this.seriesTypesHeader = this.seriesTypesHeader.slice((pageData.jumpsByDateByModule[0].month+1), -(pageData.jumpsByDateByModule[(pageData.jumpsByDateByModule.length-1)].month)); - this.seriesTypesRow = this.seriesTypesRow.map((row: Array) => { - return row.slice((pageData.jumpsByDateByModule[0].month+1), -(pageData.jumpsByDateByModule[(pageData.jumpsByDateByModule.length-1)].month)); - }); - this.seriesTypesRowCumulated = this.seriesTypesRowCumulated.map((row: Array) => { - return row.slice((pageData.jumpsByDateByModule[0].month+1), -(pageData.jumpsByDateByModule[(pageData.jumpsByDateByModule.length-1)].month)); - }); - /* - console.log('this.min', this.min); - console.log('this.max', this.max); - console.log('this.lastJump', this.lastJump); - console.log('this.seriesHeader', this.seriesHeader); - console.log('this.seriesName', this.seriesName); - console.log('this.seriesRow', this.seriesRow); - console.log('this.seriesRowTotal', this.seriesRowTotal); - console.log('this.seriesRowAvg', this.seriesRowAvg); - console.log('this.seriesRowAvgLastYears', this.seriesRowAvgLastYears); - console.log('this._jumpsByCategorie', this._jumpsByCategorie); - console.log('this._jumpsByModule', this._jumpsByModule); - console.log('this.seriesTypesHeader', this.seriesTypesHeader); - console.log('this.seriesTypesName', this.seriesTypesName); - console.log('this.seriesTypesRow', this.seriesTypesRow); - console.log('this.seriesTypesRowCumulated', this.seriesTypesRowCumulated); - */ - this.displayCharts = true; + const data$: Observable<{ pageData: JumpPageData }> = this.route.data as Observable<{ pageData: JumpPageData }>; + this._data = data$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: { pageData: JumpPageData }) => { + this.jump = data.pageData.jump; + this.prevSlug = data.pageData.prevJump?.slug; + this.nextSlug = data.pageData.nextJump?.slug; + this.title = `Saut n° ${this.jump.numero} `; }); + /* + const data$: Observable = this.route.data as Observable; + this._data = data$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: Jump) => { + this.jump = data; + console.log('jump : ', this.jump); + }); + */ } ngOnDestroy() { this._data.unsubscribe(); } - public getCategories(): Array { - return this._jumpsByCategorie; + formatDuration(duration: number): string { + const start = new Date(0); + start.setSeconds(duration); + return start.toISOString().substring(14, 19); } - public getModules(): Array { - return this._jumpsByModule; - } - - public getModuleColor(index: number): number { - return (this._jumpsByCategorie.length + index); + private _resetErrors(): void { + this.errors = { errors: {} }; } } diff --git a/src/app/components/jumps/jumps.component.html b/src/app/components/jumps/jumps.component.html new file mode 100644 index 0000000..e7a89b7 --- /dev/null +++ b/src/app/components/jumps/jumps.component.html @@ -0,0 +1,130 @@ +
+
+
+

{{title}}

+ + Dernier saut enregistré : {{ lastJump.numero }}ème à {{ lastJump.lieu }} le {{ lastJump.date | date: 'dd/MM/yyyy' }} + +
+ +
+ + + @for (menuitem of menuItems.getMenuPanel(); track menuitem) { + + } + +
+
+ + + + {{ subtitle }} + + + @if(displayCharts) { +
+
+ +
+
+ +
+
+ } +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{{ name }} Total
● {{ seriesName[i] }} + {{ value }} + {{ value }} + {{ seriesRowTotal[i] }}
Total + {{ value }} + {{ value }} + {{ grandTotal }}
Moyenne + {{ value | number : '1.0-1' }} + {{ value | number : '1.0-1' }} + {{ grandAvg | number : '1.0-1' }}
Moyenne 3 dernières années + {{ value | number : '1.0-1' }} + {{ value | number : '1.0-1' }} + {{ grandAvgLastYears | number : '1.0-1' }}
+
+
+
+
+ + + Types de sauts + + + @if(displayCharts) { +
+
+ +
+
+ +
+ @for (item of getCategories(); track $index) { +
+ +
+ } + @for (item of getModules(); track $index) { +
+ +
+ } +
+ + + } +
+
+
\ No newline at end of file diff --git a/src/app/components/jumps/jumps.component.scss b/src/app/components/jumps/jumps.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/components/jumps/jumps.component.spec.ts b/src/app/components/jumps/jumps.component.spec.ts new file mode 100644 index 0000000..48c78e8 --- /dev/null +++ b/src/app/components/jumps/jumps.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { JumpsComponent } from './jumps.component'; + +describe('JumpsComponent', () => { + let component: JumpsComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [JumpsComponent] +}); + fixture = TestBed.createComponent(JumpsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/components/jumps/jumps.component.ts b/src/app/components/jumps/jumps.component.ts new file mode 100644 index 0000000..0cfe22c --- /dev/null +++ b/src/app/components/jumps/jumps.component.ts @@ -0,0 +1,249 @@ +import { trigger, state, style, animate, transition } from '@angular/animations'; +import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core'; +import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; +import { ActivatedRoute } from '@angular/router'; +import { CommonModule } from '@angular/common'; +import { MatButtonModule } from '@angular/material/button'; +import { MatCardModule } from '@angular/material/card'; +import { MatDividerModule } from '@angular/material/divider'; +import { MatExpansionModule } from '@angular/material/expansion'; +import { MatIconModule } from '@angular/material/icon'; +import { MatMenuModule } from '@angular/material/menu'; + +import { Observable, Subscription } from 'rxjs'; + +import { MenuItems } from 'src/app/components/shared'; +import { BarsChartComponent, CircleChartComponent, LineChartComponent, LineAreaChartComponent } from 'src/app/components/shared/helpers-chart'; +import { UtilitiesService } from 'src/app/core/services'; +import { Jump, JumpByCategorie, JumpByDate, JumpByDateByModule, JumpByModule, JumpsPageData, JumpYears } from 'src/app/core/models'; + +@Component({ + selector: 'app-jumps', + standalone: true, + imports: [ + CommonModule, + MatButtonModule, MatCardModule, MatDividerModule, + MatExpansionModule, MatIconModule, MatMenuModule, + BarsChartComponent, CircleChartComponent, LineChartComponent, LineAreaChartComponent + ], + templateUrl: './jumps.component.html', + styleUrl: './jumps.component.scss', + animations: [ + trigger('flyInOut', [ + state('in', style({ transform: 'translateX(0)' })), + transition('void => *', [ + style({ transform: 'translateX(-100%)' }), + animate(200) + ]), + transition('* => void', [ + style({ transform: 'translateX(100%)' }), + animate(200) + ]) + ]) + ] +}) +export class JumpsComponent implements OnInit, OnDestroy { + private _data: Subscription = new Subscription(); + private _jumpsByCategorie: Array = []; + private _jumpsByModule: Array = []; + private _jumpsByDate: Array = []; + public lastJump: Jump = {} as Jump; + public title: string = 'Sauts'; + public subtitle: string = 'Nombre total de sauts par mois'; + public displayCharts = false; + public destroyRef = inject(DestroyRef); + public min = 0; + public max = 0; + public grandAvg = 0; + public grandAvgLastYears = 0; + public grandTotal = 0; + public seriesHeader: string[] = []; + public seriesName: string[] = []; + public seriesRow: Array> = []; + public seriesColor: { + backgroundColor: string[], + borderColor: string[] + } = { + backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'), + borderColor: this._utilitiesService.getSeriesColors(1, 'all') + }; + public seriesTypesHeader: string[] = []; + public seriesTypesName: string[] = []; + public seriesTypesRow: Array> = []; + public seriesTypesRowCumulated: Array> = []; + public seriesTypesColor: { + backgroundColor: string[], + borderColor: string[] + } = { + backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'pastels'), + borderColor: this._utilitiesService.getSeriesColors(1, 'pastels') + }; + public seriesColorClass: string[] = this._utilitiesService.getChartColors(); + public seriesRowTotal: number[] = []; + public seriesRowAvg: number[] = []; + public seriesRowAvgLastYears: number[] = []; + public seriesColTotal: number[] = []; + public seriesColTotalClosed: number[] = []; + public seriesColTotalLastYears: number[] = []; + + constructor( + private route: ActivatedRoute, + private _utilitiesService: UtilitiesService, + public menuItems: MenuItems + ) { } + + ngOnInit() { + const data$: Observable<{ pageData: JumpsPageData }> = this.route.data as Observable<{ pageData: JumpsPageData }>; + this._data = data$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: { pageData: JumpsPageData }) => { + const pageData: JumpsPageData = data.pageData; + this.lastJump = pageData.lastjump; + const currentYear: number = new Date().getFullYear(); + const types: Array = ['FF', 'Solo', 'VR', 'Wingsuit']; + const verticals: Array = ['Chutas', 'Head Up', 'Head Down']; + const others: Array = ['Track', 'Trace']; + const modules: Array = [...verticals, ...others]; + const minoration = 2; // -2 pour ne pas compter la première année + this.min = pageData.jumpsByYears[0].year; + this.max = pageData.jumpsByYears[(pageData.jumpsByYears.length-1)].year; + + this.seriesHeader = this._utilitiesService.getMonthsList(); + const values: Array = this.seriesHeader.map(() => 0); + this.seriesColTotal = [...values]; + this.seriesColTotalClosed = [...values]; + this.seriesColTotalLastYears = [...values]; + this.seriesName = pageData.jumpsByYears.map((row: JumpYears) => { + this.seriesRow.push([...values]); + return row.year.toString(); + }); + + this._jumpsByDate = pageData.jumpsByDate.map((row: JumpByDate) => { + this.seriesRow[(row.year-this.min)][(row.month-1)] = row.count; + this.seriesColTotal[(row.month-1)] += row.count; + if (row.year < currentYear) { + this.seriesColTotalClosed[(row.month-1)] += row.count; + } + if (row.year >= (currentYear-3) && row.year < currentYear) { + this.seriesColTotalLastYears[(row.month-1)] += row.count; + } + return row; + }); + this.seriesRow.forEach((row: number[]) => { + const total = row.reduce((partialSum, a) => partialSum + a, 0); + this.seriesRowTotal.push(total); + }); + this.seriesColTotalClosed.forEach((row: number) => { + const value: number = (row/(this.seriesName.length-minoration)); + this.seriesRowAvg.push(parseInt(value.toFixed(0))); + }); + this.seriesColTotalLastYears.forEach((row: number) => { + const value: number = (row/3); // Les 3 dernières années + this.seriesRowAvgLastYears.push(parseInt(value.toFixed(0))); + }); + this.grandAvg = this.seriesRowAvg.reduce((partialSum, accumulated) => partialSum + accumulated, 0); + this.grandAvgLastYears = this.seriesRowAvgLastYears.reduce((partialSum, accumulated) => partialSum + accumulated, 0); + this.grandTotal = this.seriesColTotal.reduce((partialSum, accumulated) => partialSum + accumulated, 0); + + pageData.jumpsByCategory.forEach((row: JumpByCategorie) => { + if (types.indexOf(row.categorie) !== -1) { + this._jumpsByCategorie.push(row); + } + }); + + //const focus: Array = ['FF', 'Solo']; // ['FF'] + let verticalCount:number = 0; + let otherCount:number = 0; + pageData.jumpsByModule.forEach((row: JumpByModule) => { + //if (focus.indexOf(row.categorie) !== -1 && modules.indexOf(row.module) !== -1) { + if (modules.indexOf(row.module) !== -1) { + if (verticals.indexOf(row.module) !== -1) { + verticalCount += row.count; + } else { + otherCount += row.count; + } + } + }); + if (verticalCount > 0) { + const row:JumpByModule = { + categorie: 'FF', + module: 'Vertical', + count: verticalCount + } + this._jumpsByModule.push(row); + } + if (otherCount > 0) { + const row:JumpByModule = { + categorie: 'FF', + module: 'Track/Trace', + count: otherCount + } + this._jumpsByModule.push(row); + } + + for (let year = 0; year < pageData.jumpsByYears.length; year++) { + for (let index = 0; index < 12; index++) { + const month: string = ((index+1) < 10) ? `0${(index+1)}` : `${(index+1)}`; + this.seriesTypesHeader.push(`${month}-${pageData.jumpsByYears[year].year}`); + } + } + const emptyValues: Array = this.seriesTypesHeader.map(() => 0); + this.seriesTypesName = types; + this.seriesTypesName.forEach(() => { + this.seriesTypesRow.push([...emptyValues]); + }); + pageData.jumpsByDateByModule.forEach((row: JumpByDateByModule) => { + const indexOf: number = this.seriesTypesName.indexOf(row.categorie); + if (indexOf !== -1) { + this.seriesTypesRow[indexOf][(((row.year-this.min)*12)+row.month-1)] += row.count; + } + }); + this.seriesTypesRowCumulated = this.seriesTypesRow.map((row: Array) => { + let accumulated: number = 0; + return row.map((value: number) => { + accumulated += value; + return accumulated; + }); + }); + this.seriesTypesHeader = this.seriesTypesHeader.slice((pageData.jumpsByDateByModule[0].month+1), -(pageData.jumpsByDateByModule[(pageData.jumpsByDateByModule.length-1)].month)); + this.seriesTypesRow = this.seriesTypesRow.map((row: Array) => { + return row.slice((pageData.jumpsByDateByModule[0].month+1), -(pageData.jumpsByDateByModule[(pageData.jumpsByDateByModule.length-1)].month)); + }); + this.seriesTypesRowCumulated = this.seriesTypesRowCumulated.map((row: Array) => { + return row.slice((pageData.jumpsByDateByModule[0].month+1), -(pageData.jumpsByDateByModule[(pageData.jumpsByDateByModule.length-1)].month)); + }); + /* + console.log('this.min', this.min); + console.log('this.max', this.max); + console.log('this.lastJump', this.lastJump); + console.log('this.seriesHeader', this.seriesHeader); + console.log('this.seriesName', this.seriesName); + console.log('this.seriesRow', this.seriesRow); + console.log('this.seriesRowTotal', this.seriesRowTotal); + console.log('this.seriesRowAvg', this.seriesRowAvg); + console.log('this.seriesRowAvgLastYears', this.seriesRowAvgLastYears); + console.log('this._jumpsByCategorie', this._jumpsByCategorie); + console.log('this._jumpsByModule', this._jumpsByModule); + console.log('this.seriesTypesHeader', this.seriesTypesHeader); + console.log('this.seriesTypesName', this.seriesTypesName); + console.log('this.seriesTypesRow', this.seriesTypesRow); + console.log('this.seriesTypesRowCumulated', this.seriesTypesRowCumulated); + */ + this.displayCharts = true; + }); + } + + ngOnDestroy() { + this._data.unsubscribe(); + } + + public getCategories(): Array { + return this._jumpsByCategorie; + } + + public getModules(): Array { + return this._jumpsByModule; + } + + public getModuleColor(index: number): number { + return (this._jumpsByCategorie.length + index); + } +} diff --git a/src/app/components/logbook/dialogs/jump-add.dialog.html b/src/app/components/logbook/dialogs/jump-add.dialog.html index 8a7a9b4..4612117 100644 --- a/src/app/components/logbook/dialogs/jump-add.dialog.html +++ b/src/app/components/logbook/dialogs/jump-add.dialog.html @@ -245,7 +245,7 @@ } - ju_solide + {{ lastJump.author.username }}
diff --git a/src/app/components/logbook/dialogs/jump-edit.dialog.html b/src/app/components/logbook/dialogs/jump-edit.dialog.html index 077c239..8a72925 100644 --- a/src/app/components/logbook/dialogs/jump-edit.dialog.html +++ b/src/app/components/logbook/dialogs/jump-edit.dialog.html @@ -180,7 +180,7 @@ } - ju_solide + {{ jump.author.username }}
diff --git a/src/app/components/logbook/dialogs/jump-view.dialog.html b/src/app/components/logbook/dialogs/jump-view.dialog.html index 9059afe..308ea26 100644 --- a/src/app/components/logbook/dialogs/jump-view.dialog.html +++ b/src/app/components/logbook/dialogs/jump-view.dialog.html @@ -1,69 +1,214 @@ -

- Saut n°{{jump.numero}} - +

+ Saut n° {{jump.numero}} +

-
-
Le {{ jump.date | date: 'dd/MM/yyyy' }} à {{ jump.lieu }} :
-
-
-
-
Lieu:
-
{{jump.lieu}}
-
Oaci:
-
{{jump.oaci}}
-
Aeronef:
-
{{jump.aeronef}}
-
Imat:
-
{{jump.imat}}
-
Voile:
-
{{jump.voile}}
-
Taille:
-
{{jump.taille}} ft2
-
Participants:
-
{{jump.participants}}
-
Sautants:
-
- @for (sautant of jump.sautants; track sautant) { - - - {{ sautant }} - - } - - - ju_solide - -
-
-
-
-
-
Hauteur:
-
{{jump.hauteur}} m
-
Deploiement:
-
{{jump.deploiement}} m
-
Categorie:
-
{{jump.categorie}}
-
Module:
-
{{jump.module}}
-
Accessoires:
-
{{jump.accessoires}}
-
Zone:
-
{{jump.zone}}
-
Dossier media:
-
{{jump.dossier}}
-
Video:
-
{{jump.video}}
-
Programme:
-
{{jump.programme}}
-
-
+
+
+
+
Le {{ jump.date | date: 'dd/MM/yyyy' }} à {{ jump.lieu }} {{ jump.zone ? jump.zone : jump.oaci }} :
+
+ +
+ {{ jump.categorie }} + @if (jump.module) { + / + {{ jump.module }} + } +
+
+
+
+
+
Aeronef:
+
{{ jump.aeronef }} {{ jump.imat }}
+
Voile:
+
{{ jump.voile }} {{ jump.taille }} ft2
+ @if (jump.programme) { +
Programme:
+
{{ jump.programme }}
+ } +
+
+
+
+ @if (!jump.x2data) { +
Hauteur:
+
{{ jump.hauteur }} m
+
Déploiement:
+
{{ jump.deploiement }} m
+ } + @for (file of jump.files; track file) { +
Fichier {{ file.type }}
+
{{ file.name }}
+ } +
+
+
+ + @if (jump.x2data) { +
+
+
Hauteur
+ {{ jump.x2data.altitude.exit }} m +
+
+
Durée de la chute
+ {{formatDuration(jump.x2data.duration.freeFall)}} +
+
+
Déploiement
+ {{ jump.x2data.altitude.deployment }} m +
+
+
+
+
Participants ({{ jump.sautants.length + 1 }})
+ @for (sautant of jump.sautants; track sautant) { + + + {{ sautant }} + + } + + + {{ jump.author.username }} + +
+ @if (jump.accessoires) { +
+
Accessoires
+ + + {{ jump.accessoires }} + +
+ } +
+ +
+
+
Vitesse en chute
+
+
+
Max Verticale
+ {{ (jump.x2data.speed.freeFall.vertical.max / 1000 * 60 * 60) | number : '1.0-0' }} km/h +
+
+
Max Horizontale
+ {{ (jump.x2data.speed.freeFall.horizontal.max / 1000 * 60 * 60) | number : '1.0-0' }} km/h +
+
+
Moyenne Verticale
+ {{ (jump.x2data.speed.freeFall.vertical.avg / 1000 * 60 * 60) | number : '1.0-0' }} km/h +
+
+
Moyenne Horizontale
+ {{ (jump.x2data.speed.freeFall.horizontal.avg / 1000 * 60 * 60) | number : '1.0-0' }} km/h +
+
+ + +
+
+
Vitesse sous voile
+
+
+
Max Verticale
+ {{ (jump.x2data.speed.underCanopy.vertical.max / 1000 * 60 * 60) | number : '1.0-0' }} km/h +
+
+
Max Horizontale
+ {{ (jump.x2data.speed.underCanopy.horizontal.max / 1000 * 60 * 60) | number : '1.0-0' }} km/h +
+
+
Moyenne Verticale
+ {{ (jump.x2data.speed.underCanopy.vertical.avg / 1000 * 60 * 60) | number : '1.0-0' }} km/h +
+
+
Moyenne Horizontale
+ {{ (jump.x2data.speed.underCanopy.horizontal.avg / 1000 * 60 * 60) | number : '1.0-0' }} km/h +
+
+ + +
+
+
Finesse
+
+
+
Finesse en chute
+
+
+
Finesse sous voile
+
+
+
+
+
Finesse Max
+ {{ jump.x2data.glideRatio.freeFall.max | number : '1.2-2' }} +
+
+
Finesse Moyenne
+ {{ jump.x2data.glideRatio.freeFall.avg | number : '1.2-2' }} +
+
+
Finesse Max
+ {{ jump.x2data.glideRatio.underCanopy.max | number : '1.2-2' }} +
+
+
Finesse Moyenne
+ {{ jump.x2data.glideRatio.underCanopy.avg | number : '1.2-2' }} +
+
+ + +
+
+
Distance
+
+
+
Distance au largage
+ {{ jump.x2data.distance.exitFromLandingZone| number : '1.0-0' }} m +
+
+
Durée sous voile
+ {{formatDuration(jump.x2data.duration.underCanopy)}} +
+
+
Distance totale
+ {{ jump.x2data.distance.totalFlying | number : '1.0-0' }} m +
+
+
Distance horizontale
+ {{ jump.x2data.distance.totalHorizontal | number : '1.0-0' }} m +
+
+ + } + @else { +
+
+
Participants ({{ jump.sautants.length + 1 }})
+ @for (sautant of jump.sautants; track sautant) { + + + {{ sautant }} + + } + + + {{ jump.author.username }} + +
+
+ +
Aucune donnée GPS
+ + }
- -
- - + + diff --git a/src/app/components/logbook/dialogs/jump-view.dialog.ts b/src/app/components/logbook/dialogs/jump-view.dialog.ts index 1e41a9d..cc59ab8 100644 --- a/src/app/components/logbook/dialogs/jump-view.dialog.ts +++ b/src/app/components/logbook/dialogs/jump-view.dialog.ts @@ -1,5 +1,5 @@ import { Component, Inject } from '@angular/core'; -import { DatePipe } from '@angular/common'; +import { DatePipe, DecimalPipe } from '@angular/common'; import { MatButtonModule } from '@angular/material/button'; import { MatDialogRef, MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog'; import { MatDividerModule } from '@angular/material/divider'; @@ -12,11 +12,9 @@ import { Jump } from 'src/app/core/models'; templateUrl: 'jump-view.dialog.html', standalone: true, imports: [ - DatePipe, - MatButtonModule, - MatDialogModule, - MatDividerModule, - MatIconModule + DatePipe, DecimalPipe, + MatButtonModule, MatDialogModule, + MatDividerModule, MatIconModule ] }) export class JumpViewDialogComponent { @@ -30,4 +28,10 @@ export class JumpViewDialogComponent { // close the dialog without result this.dialogRef.close(); } + + formatDuration(duration: number): string { + const start = new Date(0); + start.setSeconds(duration); + return start.toISOString().substring(14, 19); + } } diff --git a/src/app/components/logbook/logbook.component.html b/src/app/components/logbook/logbook.component.html index a2e2e41..801b42c 100644 --- a/src/app/components/logbook/logbook.component.html +++ b/src/app/components/logbook/logbook.component.html @@ -1,107 +1,105 @@
-
-
-
-

{{title}}

- - Dernier saut enregistré : {{ lastJump.numero }}ème à {{ lastJump.lieu }} le {{ lastJump.date | date: 'dd/MM/yyyy' }} - -
- -
- + + + - - - - @for (menuitem of menuItems.getMenuLogbook(); track menuitem) { - @if (menuitem.type === 'link') { - - } } - -
+ } +
- - @if (jumpsToHundred() <= 20) { -
- - -
- {{ lastJump.numero + jumpsToHundred() }}ème à venir dans {{ jumpsToHundred() }} - {{ jumpsToHundred() > 1 ? 'sauts' : 'saut' }} -
-
- } - - - - - Filtrer les sauts - @if (jumpsCount < lastJump.numero) { - - {{ jumpsCount }} {{ jumpsCount > 1 ? 'sauts' : 'saut' }} sur {{ lastJump.numero }} correspondent à la recherche - - } - -
-
-
- - -
- - - - -
-
-
- - -
- - - - -
-
-
- - -
- - - - -
-
-
- - -
- - - - -
- -
-
-
- - - - -
+ + @if (jumpsToHundred() <= 20) { +
+ + +
+ {{ lastJump.numero + jumpsToHundred() }}ème à venir dans {{ jumpsToHundred() }} + {{ jumpsToHundred() > 1 ? 'sauts' : 'saut' }} +
+
+ } + + + + + Filtrer les sauts + @if (jumpsCount < lastJump.numero) { + + {{ jumpsCount }} {{ jumpsCount > 1 ? 'sauts' : 'saut' }} sur {{ lastJump.numero }} correspondent à la recherche + + } + +
+
+
+ + +
+ + + + +
+
+
+ + +
+ + + + +
+
+
+ + +
+ + + + +
+
+
+ + +
+ + + + +
+ +
+
+
+ + + + +
\ No newline at end of file diff --git a/src/app/components/profile/profile.component.html b/src/app/components/profile/profile.component.html index a580871..c10f68f 100644 --- a/src/app/components/profile/profile.component.html +++ b/src/app/components/profile/profile.component.html @@ -12,14 +12,20 @@
-
-

{{title}}

- +
+
+
+

{{title}}

+
+ +
+
+
- Logo UPT + Logo UPT

Vector 3 - V306 Micron

diff --git a/src/app/components/profile/profile.component.scss b/src/app/components/profile/profile.component.scss index b3806e8..cea222b 100644 --- a/src/app/components/profile/profile.component.scss +++ b/src/app/components/profile/profile.component.scss @@ -4,6 +4,7 @@ .banner { background-color: var.$sidebar-footer; padding: 1.6rem 0 1.3rem 0; + margin: -1.5rem -1.5rem 1.5rem -1.5rem; .user-img { width: var.$user-img-size; height: var.$user-img-size; diff --git a/src/app/components/qcm/qcm.component.html b/src/app/components/qcm/qcm.component.html index 8c8b2fd..7b9904a 100644 --- a/src/app/components/qcm/qcm.component.html +++ b/src/app/components/qcm/qcm.component.html @@ -1,32 +1,43 @@ -
-
-
-

- {{ title }} - {{ questionsCount }} {{ questionsCount > 1 ? 'questions' : 'question' }} -

- {{ subtitle }} -
- -
- - - @for (menuitem of menuItems.getMenuPanel(); track menuitem) { - - } - -
+
+
+

+ {{ title }} + {{ questionsCount }} {{ questionsCount > 1 ? 'questions' : 'question' }} +

+ {{ subtitle }}
- - - - -
+ +
+ + + @for (menuitem of menuItems.getMenuPanel(); track menuitem) { + + } + +
+
+ + +@if (questions.controls.length) { + +
+ + +
    + @for (category of qcm.categories; track category.num) { + @for (question of category.questions; track question.num) { +
  1. {{ question.num }}
  2. + } + } +
+
+ + @for (category of qcm.categories; track category; let index = $index) { @@ -43,9 +54,9 @@ @for (question of category.questions; track question; let index = $index) {
- + @for (choice of question.choices; track choice) { - {{ choice.libelle }} + {{ choice.libelle }} }
@@ -56,5 +67,17 @@ }
+
-
+} diff --git a/src/app/components/qcm/qcm.component.scss b/src/app/components/qcm/qcm.component.scss index e69de29..9b29b2e 100644 --- a/src/app/components/qcm/qcm.component.scss +++ b/src/app/components/qcm/qcm.component.scss @@ -0,0 +1,37 @@ +/* QCM */ +@use 'variable' as var; + +ol.squareItem { + padding: 0; + margin: 1rem 0; + li { + color: var.$primary; + background-color: var.$sidenav-content; //var.$dark; + background-image: none; + border: 1px solid var.$dark; //var.$extra-muted; + cursor: pointer; + float: left; + list-style-type: none; + margin: 0.17em; + padding: 0.34em 0; + text-align: center; + width: 33px; + height: 33px; + &.active { + border-color: var.$info; + } + &.valid { + color: var.$sidenav-content; + border-color: var.$success; + background-color: var.$primary; + } + &.defer { + border-color: var.$info-dark; + background-color: var.$navy-light; + } + &.error { + border-color: var.$purple-light; + background-color: var.$secondary; + } + } +} \ No newline at end of file diff --git a/src/app/components/qcm/qcm.component.ts b/src/app/components/qcm/qcm.component.ts index dfc6de2..b110f81 100644 --- a/src/app/components/qcm/qcm.component.ts +++ b/src/app/components/qcm/qcm.component.ts @@ -8,12 +8,15 @@ import { MatDividerModule } from '@angular/material/divider'; import { MatExpansionModule } from '@angular/material/expansion'; import { MatIconModule } from '@angular/material/icon'; import { MatMenuModule } from '@angular/material/menu'; +import { MatProgressBarModule } from '@angular/material/progress-bar'; import { MatRadioModule } from '@angular/material/radio'; -import { Observable, Subscription } from 'rxjs'; +import { MatSelectModule } from '@angular/material/select'; +import { interval, Observable, Subscription } from 'rxjs'; +import { take } from 'rxjs/operators'; import { MenuItems } from 'src/app/components/shared'; -import { ListErrorsComponent, } from 'src/app/components/shared'; -import { Errors, Qcm, User } from 'src/app/core/models'; +import { ListErrorsComponent } from 'src/app/components/shared'; +import { Errors, Qcm, QcmCategory, QcmQuestion, User } from 'src/app/core/models'; import { QcmService, UserService } from 'src/app/core/services'; import data from 'src/qcm-bpa.json'; @@ -23,7 +26,8 @@ import data from 'src/qcm-bpa.json'; imports: [ FormsModule, ReactiveFormsModule, MatButtonModule, MatCardModule, MatDividerModule, MatExpansionModule, - MatIconModule, MatMenuModule, MatRadioModule, + MatIconModule, MatMenuModule, MatProgressBarModule, MatRadioModule, + MatSelectModule, ListErrorsComponent ], templateUrl: './qcm.component.html', @@ -32,6 +36,8 @@ import data from 'src/qcm-bpa.json'; export class QcmComponent implements OnInit, OnDestroy { private _currentUser: Subscription = new Subscription(); private _data: Subscription = new Subscription(); + private _timer: Subscription = new Subscription(); + private _refresh = 1000; public qcm: Qcm = {} as Qcm; public currentUser: User = {} as User; public canModify = false; @@ -42,6 +48,11 @@ export class QcmComponent implements OnInit, OnDestroy { public expandedIndex = 0; public questionsCount = 0; public qcmForm!: FormGroup; + public loading = true; + public totalAnswer = 0; + public timeProgress = 0; + public timeProgressColor = 'primary'; + public timeMax = (60*45); constructor( private route: ActivatedRoute, @@ -56,15 +67,16 @@ export class QcmComponent implements OnInit, OnDestroy { } get questions(): FormArray { - return this.qcmForm.controls['questions']; + return this.qcmForm.controls['questions'] as FormArray; } ngOnInit() { - //this.importQuestions(); - //this.importChoices(); + //this._importQuestions(); + //this._importChoices(); // Retreive the prefetched QCM const data$: Observable<{ qcm: Qcm }> = this.route.data as Observable<{ qcm: Qcm }>; this._data = data$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: { qcm: Qcm }) => { + this.questionsCount = 0; this.qcm = data.qcm; if (this.qcm.name === 'bpa') { this.title = 'QCM du BPA'; @@ -77,13 +89,7 @@ export class QcmComponent implements OnInit, OnDestroy { this.qcm.categories.forEach(category => { this.questionsCount += category.questions.length; category.questions.forEach(question => { - this.questions.push( - this.fb.group({ - id: new FormControl({ value: question.num, disabled: false }), - choice: [''] - //choice: new FormControl({ value: '', disabled: false }) - }) - ); + this.addQuestion(question); }); }); }); @@ -93,6 +99,7 @@ export class QcmComponent implements OnInit, OnDestroy { this.currentUser = userData; this.canModify = userData.role === 'Admin'; }); + this.loading = false; } ngOnDestroy() { @@ -100,15 +107,61 @@ export class QcmComponent implements OnInit, OnDestroy { this._currentUser.unsubscribe(); } + private _starTimer(): void { + this._timer = interval(1000) + .pipe(take(this.timeMax)) + .subscribe(() => { + this.timeProgress++; + if (this.timeProgress > (this.timeMax/100*70) && this.timeProgress <= (this.timeMax/100*90)) { + this.timeProgressColor = 'warning'; + } else if (this.timeProgress > (this.timeMax/100*90) && this.timeProgress <= (this.timeMax/100*98)) { + this.timeProgressColor = 'danger'; + } else if (this.timeProgress > (this.timeMax/100*98)) { + this.timeProgressColor = 'purple'; + } + if (this.timeProgress >= this.timeMax) { + this.timeProgressColor = 'accent'; + this._timer.unsubscribe(); + } + }); + } + + addQuestion(question: QcmQuestion) { + const item = this.fb.group({ + id: [question.num], + choice: [''] + }); + this.questions.push(item); + } + setExpandedIndex(index: number) { this.expandedIndex = index; } - onChange() { - //this.isDisabled = true; + onChange(category: QcmCategory, question: QcmQuestion, value: unknown) { + //console.log('onChange', category.num, question.num, value); + if (this.timeProgress === 0) { + this._starTimer(); + } + this.qcm.categories[(category.num-1)].questions[(question.num-1)].choices.forEach(choice => { + if (choice.index === value) { + if (choice.correct) { + console.log(`Réponse à la question ${question.num} de la catégorie ${category.num} : correcte`); + } else { + console.log(`Réponse à la question ${question.num} de la catégorie ${category.num} : incorrecte`); + } + } + }); + this.totalAnswer++; + this.questions.controls[(question.num-1)].disable(); + //console.log(this.questions.controls[(question.num-1)].disabled); } - importChoices() { + onSubmit() { + console.log('onSubmit'); + } + + private _importChoices() { try { data.categories.forEach((category) => { category.questions.forEach(question => { @@ -132,7 +185,7 @@ export class QcmComponent implements OnInit, OnDestroy { } } - importQuestions() { + private _importQuestions() { try { data.categories.forEach((category) => { //Object.assign(this.jump, category); @@ -154,4 +207,8 @@ export class QcmComponent implements OnInit, OnDestroy { console.error(error); } } + + private _resetErrors(): void { + this.errors = { errors: {} }; + } } diff --git a/src/app/components/settings/credentials/credentials.component.html b/src/app/components/settings/credentials/credentials.component.html index 85130a5..5b01ab0 100644 --- a/src/app/components/settings/credentials/credentials.component.html +++ b/src/app/components/settings/credentials/credentials.component.html @@ -12,7 +12,7 @@
-
+

{{title}}

diff --git a/src/app/components/settings/credentials/credentials.component.scss b/src/app/components/settings/credentials/credentials.component.scss index a78305d..68affb2 100644 --- a/src/app/components/settings/credentials/credentials.component.scss +++ b/src/app/components/settings/credentials/credentials.component.scss @@ -4,6 +4,7 @@ .banner { background-color: var.$sidebar-footer; padding: 1.6rem 0 1.3rem 0; + margin: -1.5rem -1.5rem 1.5rem -1.5rem; .user-img { width: var.$user-img-size; height: var.$user-img-size; diff --git a/src/app/components/settings/settings.component.html b/src/app/components/settings/settings.component.html index 0f193c5..015953a 100644 --- a/src/app/components/settings/settings.component.html +++ b/src/app/components/settings/settings.component.html @@ -12,7 +12,7 @@
-
+

{{title}}

diff --git a/src/app/components/settings/settings.component.scss b/src/app/components/settings/settings.component.scss index 05665a2..d4b557d 100644 --- a/src/app/components/settings/settings.component.scss +++ b/src/app/components/settings/settings.component.scss @@ -4,6 +4,7 @@ .banner { background-color: var.$sidebar-footer; padding: 1.6rem 0 1.3rem 0; + margin: -1.5rem -1.5rem 1.5rem -1.5rem; /* background-color: mat.get-color-from-palette(var.$md-custom-warn, 700); margin-bottom: 1rem; diff --git a/src/app/components/shared/dashboard-components/jumps-by-month/jumps-by-month.component.ts b/src/app/components/shared/dashboard-components/jumps-by-month/jumps-by-month.component.ts index 18da665..1210d7e 100755 --- a/src/app/components/shared/dashboard-components/jumps-by-month/jumps-by-month.component.ts +++ b/src/app/components/shared/dashboard-components/jumps-by-month/jumps-by-month.component.ts @@ -74,6 +74,7 @@ export class JumpsByMonthComponent implements OnInit, OnDestroy { } private _loadJumpByDate() { + const minoration = 2; // -2 pour ne pas compter la première année this.seriesHeader = this._utilitiesService.getMonthsList(); const values: Array = this.seriesHeader.map(() => 0); this.seriesColTotal = [...values]; @@ -111,7 +112,7 @@ export class JumpsByMonthComponent implements OnInit, OnDestroy { this.seriesRowTotal.push(total); }); this.seriesColTotalClosed.forEach((row: number) => { - const value: number = (row/(this.seriesName.length-2)); // -2 pour ne pas compter la première année + const value: number = (row/(this.seriesName.length-minoration)); this.seriesRowAvg.push(parseInt(value.toFixed(0))); }); this.seriesColTotalLastYears.forEach((row: number) => { diff --git a/src/app/components/shared/helpers-jump/jump-table.component.html b/src/app/components/shared/helpers-jump/jump-table.component.html index 4caf00d..3f6444c 100644 --- a/src/app/components/shared/helpers-jump/jump-table.component.html +++ b/src/app/components/shared/helpers-jump/jump-table.component.html @@ -12,7 +12,7 @@ Aucun saut à afficher pour le moment. - Actualisation des sauts en cours + Chargement des sauts en cours
@@ -224,7 +224,7 @@ --> - + + + + Fichiers + + @if (element.files) { + @for (file of element.files; track $index) { + @switch (file.type) { + @case ('video') { + + } + @case ('image') { + + } + @case ('kml') { + + } + @default { + + } + } + } + } + @if (!element.numero) { + + } + @@ -247,13 +282,17 @@ more_vert + } diff --git a/src/app/components/shared/helpers-jump/jump-table.component.ts b/src/app/components/shared/helpers-jump/jump-table.component.ts index 9ef69c9..da4a1fa 100644 --- a/src/app/components/shared/helpers-jump/jump-table.component.ts +++ b/src/app/components/shared/helpers-jump/jump-table.component.ts @@ -21,7 +21,7 @@ import { take } from 'rxjs/operators'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { FrenchPaginator } from 'src/app/components/shared/french-paginator.component'; -import { ColumnDefinition, Errors, Jump, JumpList, JumpListConfig, jumpColumns } from 'src/app/core/models'; +import { ColumnDefinition, Errors, Jump, JumpByDay, JumpFile, JumpFileType, JumpList, JumpListConfig, jumpColumns } from 'src/app/core/models'; import { JumpsService, JumpTableService } from 'src/app/core/services'; import { JumpAddDialogComponent, JumpDeleteDialogComponent, JumpEditDialogComponent, JumpViewDialogComponent } from 'src/app/components/logbook/dialogs' @@ -41,6 +41,7 @@ import { JumpAddDialogComponent, JumpDeleteDialogComponent, JumpEditDialogCompon }) export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChecked { private _jumps: Subscription = new Subscription(); + private _subscriptions: Array = []; //private _jump: Subscription = new Subscription(); private _query: JumpListConfig = { type: 'all', filters: {} }; //private _lastjump: Jump = {} as Jump; @@ -53,13 +54,13 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe 'numero', 'date', 'lieu', 'oaci', 'aeronef', 'imat', 'hauteur', 'voile', 'taille', 'categorie', 'module', 'participants', 'programme', 'accessoires', - 'zone', 'video', 'actions' + 'zone', 'files', 'actions' ];*/ public displayedColumns: string[] = [ 'numero', 'date', 'lieu', 'aeronef', 'hauteur', 'voile', 'categorie', 'participants', 'zone', 'accessoires', - 'video', 'actions' + 'files', 'actions' ]; //public displayedColumns: string[] = jumpColumns.map((col) => col.key) public columnsSchema: Array = jumpColumns; @@ -115,7 +116,9 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe ngOnDestroy() { this._jumps.unsubscribe(); - //this._jump.unsubscribe(); + this._subscriptions.forEach(subscription => { + subscription.unsubscribe(); + }); } ngAfterContentChecked() { @@ -155,6 +158,9 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe const jumps$: Observable = this._jumpsService.query(this._query); this._jumps = jumps$.subscribe({ next: (data: JumpList) => { + //this.updateJumps(data.jumps); + //this.linkSkydiverIdJumps(); + //this.getKmlJumpFiles(data.jumps); this.loading = false; this.jumps = new MatTableDataSource(data.jumps); this.jumpsCount = data.jumpsCount; @@ -170,12 +176,150 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe }); } + linkSkydiverIdJumps() { + const config: JumpListConfig = { type: 'all', filters: {} } as JumpListConfig; + config.filters.limit = 200; + config.filters.offset = 0; + config.filters.dateRangeStart = '2024-01-01 00:00:00'; + //const year = new Date().getFullYear(); + //config.filters.dateRangeEnd = `${year}-12-31 23:59:59`; + config.filters.dateRangeEnd = '2024-12-31 23:59:59'; + //console.log(config.filters); + const subscription: Subscription = this._jumpsService.getAllByDay(config) + .pipe(take(1)) + .subscribe({ + next: (days) => { + this._resetErrors(); + //console.log('getAllByDay : ', days); + days.forEach(day => { + this.loadSkydiverIdJumps(day, config); + }); + }, + error: (err) => { + this.errors = err; + } + }); + this._subscriptions.push(subscription); + } + + loadSkydiverIdJumps(day: JumpByDay, config: JumpListConfig) { + config.filters.dateRangeStart = `${day.jumps[0].date!.substring(0, 10)} 00:00:00`; + config.filters.dateRangeEnd = `${day.jumps[0].date!.substring(0, 10)} 23:59:59`; + const subscription: Subscription = this._jumpsService.getAllFromSkydiverIdApi(config) + .pipe(take(1)) + .subscribe({ + next: (data) => { + if (data.items.length) { + const diff = day.count - data.items.length; + if (diff < 0) { + console.error(`${diff} ${diff > 1 ? 'données' : 'donnée'} altimètre de trop le ${day.jumps[0].date!.substring(0, 10)}`); + } else { + if (diff > 0) { + console.error(`${diff}/${day.count} ${diff > 1 ? 'données altimètre manquantes' : 'donnée altimètre manquante'} le ${day.jumps[0].date!.substring(0, 10)}`, day.jumps, data.items); + } + console.log(`${day.count} ${day.count > 1 ? 'sauts' : 'saut'} le ${data.items[0].date!.substring(0, 10)}`, day.jumps.sort((a, b) => b.numero! - a.numero!), data.items); + data.items.map((jump, index) => { + const file: JumpFile = { + name: jump.name, + path: `/Volumes/Storage/Skydive/X2_Logs/${day.jumps[index].date!.substring(0, 4)}/`, + type: JumpFileType.CSV + } as JumpFile; + this._subscriptions.push( + this._jumpsService.saveX2Data(day.jumps[index].slug!, file, jump) + .pipe(take(1)) + .subscribe({ + next: (jump) => { + this._resetErrors(); + console.log(`Le fichier ${file.name} a été ajouté au saut n°${jump.numero} !`, 'OK'); + }, + error: (err) => { + this.errors = err; + } + }) + ); + return jump; + }); + } + //console.log(`${day.count} ${day.count > 1 ? 'sauts' : 'saut'} le ${day.jumps[0].date!.substring(0, 10)}`); + //console.log(`${data.items.length} ${data.items.length > 1 ? 'sauts' : 'saut'} le ${data.items[0].date!.substring(0, 10)}`, data); + } else { + console.info('Aucune données altimètre pour le ', day.jumps[0].date!.substring(0, 10)); + } + }, + error: (err) => { + console.error('getAllFromSkydiverIdApi error'); + this.errors = err; + } + }); + this._subscriptions.push(subscription); + } + + updateJumps(jumps: Array) { + jumps.map(jump => { + jump.files = []; + if (jump.dossier !== "" && jump.video !== "") { + const file: JumpFile = { + name: jump.video!, + path: jump.dossier!, + type: JumpFileType.VIDEO + } as JumpFile; + this._subscriptions.push( + this._jumpsService.saveFile(jump.slug, file) + .pipe(take(1)) + .subscribe({ + next: (file) => { + this._resetErrors(); + jump.files.push(file); + console.log(`Le fichier ${file.name} a été ajouté au saut n°${jump.numero} !`, 'OK'); + }, + error: (err) => { + this.errors = err; + } + }) + ); + } + return jump; + }); + } + + getKmlJumpFiles(jumps: Array) { + jumps.map(jump => { + if (jump.x2data !== null) { + //console.log(`Le fichier ${jump.x2data.name} existe pour le saut n°${jump.numero} !`, `https://skydiver.id/api/jump/${jump.x2data.id}/kml`); + const file: JumpFile = { + name: jump.x2data.name.substring(0, -4) + '.kml', + path: `/X2_Kmls/${jump.date.substring(0, 4)}/`, + type: JumpFileType.KML + } as JumpFile; + this._subscriptions.push( + this._jumpsService.saveKml(jump.slug, file) + .pipe(take(1)) + .subscribe({ + next: (file) => { + this._resetErrors(); + console.log(`Le fichier ${file.path}${file.name} a été ajouté au saut n°${jump.numero} !`, 'OK'); + }, + error: (err) => { + this.errors = err; + } + }) + ); + /* + */ + } + return jump; + }); + } + deleteJump(slug: string) { this.isDeleting = true; - this._jumpsService.destroy(slug).pipe(take(1)) + this._subscriptions.push( + this._jumpsService.destroy(slug) + .pipe(take(1)) .subscribe(() => { this.router.navigateByUrl('/'); - }); + }) + ); } openDeleteDialog(jump: Jump): void { @@ -183,12 +327,15 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe width: '60vw', data: jump }); - dialogRef.afterClosed().pipe(take(1)) + this._subscriptions.push( + dialogRef.afterClosed() + .pipe(take(1)) .subscribe(result => { if (result != undefined) { this._onDelete(result.slug); } - }); + }) + ); } openEditDialog(jump: Jump): void { @@ -196,12 +343,15 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe width: '70vw', data: jump }); - dialogRef.afterClosed().pipe(take(1)) - .subscribe(result => { - if (result != undefined) { - this._onEdit(result); - } - }); + this._subscriptions.push( + dialogRef.afterClosed() + .pipe(take(1)) + .subscribe(result => { + if (result != undefined) { + this._onEdit(result); + } + }) + ); } openViewDialog(jump: Jump): void { @@ -230,20 +380,22 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe private _onDelete(slug: string): void { try { this.isDeleting = true; - this._jumpsService.destroy(slug) - .pipe(take(1)) - .subscribe({ - next: () => { - this._resetErrors(); - this._openSnackBar(`Le saut a été supprimé !`, 'OK'); - this.runQuery(); - this.tableRefresh = !this.tableRefresh; - this._jumpTableService.updateTableRefresh(this.tableRefresh); - }, - error: (err) => { - this.errors = err; - } - }); + this._subscriptions.push( + this._jumpsService.destroy(slug) + .pipe(take(1)) + .subscribe({ + next: () => { + this._resetErrors(); + this._openSnackBar(`Le saut a été supprimé !`, 'OK'); + this.runQuery(); + this.tableRefresh = !this.tableRefresh; + this._jumpTableService.updateTableRefresh(this.tableRefresh); + }, + error: (err) => { + this.errors = err; + } + }) + ); } catch (error) { console.error(error); } @@ -252,21 +404,23 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe private _onEdit(jump: Jump): void { try { this.isSubmitting = true; - this._jumpsService.update(jump) - .pipe(take(1)) - .subscribe({ - next: (jump) => { - this._resetErrors(); - this._openSnackBar(`Le saut n°${jump.numero} a été mis à jour !`, 'OK'); - this.runQuery(); - this.tableRefresh = !this.tableRefresh; - this._jumpTableService.updateTableRefresh(this.tableRefresh); - }, - error: (err) => { - this.errors = err; - this.isSubmitting = false; - } - }); + this._subscriptions.push( + this._jumpsService.update(jump) + .pipe(take(1)) + .subscribe({ + next: (jump) => { + this._resetErrors(); + this._openSnackBar(`Le saut n°${jump.numero} a été mis à jour !`, 'OK'); + this.runQuery(); + this.tableRefresh = !this.tableRefresh; + this._jumpTableService.updateTableRefresh(this.tableRefresh); + }, + error: (err) => { + this.errors = err; + this.isSubmitting = false; + } + }) + ); } catch (error) { console.error(error); } diff --git a/src/app/components/shared/layout/full.component.html b/src/app/components/shared/layout/full.component.html index c435754..4901035 100755 --- a/src/app/components/shared/layout/full.component.html +++ b/src/app/components/shared/layout/full.component.html @@ -1,6 +1,6 @@