chore(deps): upgrade Angular 18 → 19

- ng update @angular/core@19 @angular/cli@19 @angular/material@19 @angular-eslint/schematics@19
- Migration: remove standalone:true (now default in v19) from 60 components
- Migration: zone.js 0.14 → 0.15
- Fix pre-existing build budget error: raise initial bundle limit to 5mb (app ships large static JSON assets)
This commit is contained in:
2026-04-26 06:25:02 +02:00
parent b8eb8a9393
commit 5400294d45
65 changed files with 5875 additions and 4710 deletions
+4 -1
View File
@@ -6,7 +6,10 @@
"Bash(grep -A3 \" FAILED$\")", "Bash(grep -A3 \" FAILED$\")",
"Bash(grep -v \"Executed\\\\|^--$\")", "Bash(grep -v \"Executed\\\\|^--$\")",
"Bash(grep -E \"TOTAL:|FAILED$\")", "Bash(grep -E \"TOTAL:|FAILED$\")",
"Bash(node -e \"const c = require\\('chart.js'\\); console.log\\(Object.keys\\(c\\).filter\\(k => k.includes\\('Doughnut'\\) || k.includes\\('Controller'\\)\\)\\)\")" "Bash(node -e \"const c = require\\('chart.js'\\); console.log\\(Object.keys\\(c\\).filter\\(k => k.includes\\('Doughnut'\\) || k.includes\\('Controller'\\)\\)\\)\")",
"Bash(npm list *)",
"Bash(ng update *)",
"Bash(npm run *)"
] ]
} }
} }
+11 -35
View File
@@ -4,9 +4,7 @@
"cli": { "cli": {
"packageManager": "npm", "packageManager": "npm",
"analytics": false, "analytics": false,
"schematicCollections": [ "schematicCollections": ["@angular-eslint/schematics"]
"@angular-eslint/schematics"
]
}, },
"newProjectRoot": "projects", "newProjectRoot": "projects",
"projects": { "projects": {
@@ -32,10 +30,7 @@
}, },
"index": "src/index.html", "index": "src/index.html",
"tsConfig": "tsconfig.app.json", "tsConfig": "tsconfig.app.json",
"polyfills": [ "polyfills": ["@angular/localize/init", "zone.js"],
"@angular/localize/init",
"zone.js"
],
"inlineStyleLanguage": "scss", "inlineStyleLanguage": "scss",
"assets": [ "assets": [
"src/favicon.ico", "src/favicon.ico",
@@ -47,14 +42,9 @@
"output": "/" "output": "/"
} }
], ],
"styles": [ "styles": ["node_modules/chartist/dist/index.scss", "src/styles/styles.scss"],
"node_modules/chartist/dist/index.scss",
"src/styles/styles.scss"
],
"stylePreprocessorOptions": { "stylePreprocessorOptions": {
"includePaths": [ "includePaths": ["src/styles"]
"src/styles"
]
}, },
"scripts": [], "scripts": [],
"browser": "src/main.ts" "browser": "src/main.ts"
@@ -69,8 +59,8 @@
"budgets": [ "budgets": [
{ {
"type": "initial", "type": "initial",
"maximumWarning": "500kb", "maximumWarning": "3mb",
"maximumError": "1mb" "maximumError": "5mb"
}, },
{ {
"type": "anyComponentStyle", "type": "anyComponentStyle",
@@ -142,35 +132,21 @@
"test": { "test": {
"builder": "@angular-devkit/build-angular:karma", "builder": "@angular-devkit/build-angular:karma",
"options": { "options": {
"polyfills": [ "polyfills": ["zone.js", "zone.js/testing"],
"zone.js",
"zone.js/testing"
],
"tsConfig": "tsconfig.spec.json", "tsConfig": "tsconfig.spec.json",
"inlineStyleLanguage": "scss", "inlineStyleLanguage": "scss",
"assets": [ "assets": ["src/favicon.ico", "src/assets", "src/manifest.webmanifest"],
"src/favicon.ico", "styles": ["src/styles/styles.scss"],
"src/assets",
"src/manifest.webmanifest"
],
"styles": [
"src/styles/styles.scss"
],
"scripts": [], "scripts": [],
"stylePreprocessorOptions": { "stylePreprocessorOptions": {
"includePaths": [ "includePaths": ["src/styles"]
"src/styles"
]
} }
} }
}, },
"lint": { "lint": {
"builder": "@angular-eslint/builder:lint", "builder": "@angular-eslint/builder:lint",
"options": { "options": {
"lintFilePatterns": [ "lintFilePatterns": ["src/**/*.ts", "src/**/*.html"]
"src/**/*.ts",
"src/**/*.html"
]
} }
} }
} }
+2663 -1919
View File
File diff suppressed because it is too large Load Diff
+20 -20
View File
@@ -21,18 +21,18 @@
}, },
"private": true, "private": true,
"dependencies": { "dependencies": {
"@angular/animations": "^18.2.14", "@angular/animations": "^19.2.21",
"@angular/cdk": "^18.2.14", "@angular/cdk": "^19.2.19",
"@angular/common": "^18.2.14", "@angular/common": "^19.2.21",
"@angular/compiler": "^18.2.14", "@angular/compiler": "^19.2.21",
"@angular/core": "^18.2.14", "@angular/core": "^19.2.21",
"@angular/forms": "^18.2.14", "@angular/forms": "^19.2.21",
"@angular/google-maps": "^17.3.8", "@angular/google-maps": "^17.3.8",
"@angular/localize": "^18.2.14", "@angular/localize": "^19.2.21",
"@angular/material": "^18.2.14", "@angular/material": "^19.2.19",
"@angular/platform-browser": "^18.2.14", "@angular/platform-browser": "^19.2.21",
"@angular/platform-browser-dynamic": "^18.2.14", "@angular/platform-browser-dynamic": "^19.2.21",
"@angular/router": "^18.2.14", "@angular/router": "^19.2.21",
"bootstrap": "^5.3.7", "bootstrap": "^5.3.7",
"chart.js": "^4.4.2", "chart.js": "^4.4.2",
"chartist": "^1.3.0", "chartist": "^1.3.0",
@@ -41,17 +41,17 @@
"ngx-skeleton-loader": "^9.0.0", "ngx-skeleton-loader": "^9.0.0",
"rxjs": "~7.8.0", "rxjs": "~7.8.0",
"tslib": "^2.3.0", "tslib": "^2.3.0",
"zone.js": "^0.14.10" "zone.js": "^0.15.1"
}, },
"devDependencies": { "devDependencies": {
"@angular-devkit/build-angular": "^18.2.21", "@angular-devkit/build-angular": "^19.2.24",
"@angular-eslint/builder": "18.4.3", "@angular-eslint/builder": "19.8.1",
"@angular-eslint/eslint-plugin": "18.4.3", "@angular-eslint/eslint-plugin": "19.8.1",
"@angular-eslint/eslint-plugin-template": "18.4.3", "@angular-eslint/eslint-plugin-template": "19.8.1",
"@angular-eslint/schematics": "18.4.3", "@angular-eslint/schematics": "19.8.1",
"@angular-eslint/template-parser": "18.4.3", "@angular-eslint/template-parser": "19.8.1",
"@angular/cli": "^18.2.21", "@angular/cli": "^19.2.24",
"@angular/compiler-cli": "^18.2.14", "@angular/compiler-cli": "^19.2.21",
"@types/jasmine": "~5.1.0", "@types/jasmine": "~5.1.0",
"@typescript-eslint/eslint-plugin": "7.2.0", "@typescript-eslint/eslint-plugin": "7.2.0",
"@typescript-eslint/parser": "7.2.0", "@typescript-eslint/parser": "7.2.0",
+8 -8
View File
@@ -3,7 +3,7 @@ import { MAT_DATE_LOCALE, MAT_DATE_FORMATS, provideNativeDateAdapter } from '@an
import { Title } from '@angular/platform-browser'; import { Title } from '@angular/platform-browser';
import { FullComponent } from '@components/shared/layout'; import { FullComponent } from '@components/shared/layout';
import { UserService } from "@services"; import { UserService } from '@services';
export const MY_FORMATS = { export const MY_FORMATS = {
parse: { parse: {
@@ -19,23 +19,23 @@ export const MY_FORMATS = {
@Component({ @Component({
selector: 'app-root', selector: 'app-root',
standalone: true, imports: [FullComponent],
imports: [
FullComponent
],
providers: [ providers: [
{ provide: MAT_DATE_LOCALE, useValue: 'fr-FR' }, { provide: MAT_DATE_LOCALE, useValue: 'fr-FR' },
{ provide: MAT_DATE_FORMATS, useValue: MY_FORMATS }, { provide: MAT_DATE_FORMATS, useValue: MY_FORMATS },
provideNativeDateAdapter(MY_FORMATS) provideNativeDateAdapter(MY_FORMATS),
], ],
templateUrl: './app.component.html', templateUrl: './app.component.html',
styleUrl: './app.component.scss' styleUrl: './app.component.scss',
}) })
export class AppComponent implements OnInit, AfterContentInit { export class AppComponent implements OnInit, AfterContentInit {
public title = 'Ad Astra'; public title = 'Ad Astra';
public appClass = 'grayscale'; public appClass = 'grayscale';
constructor(private userService: UserService, private titleService: Title) { } constructor(
private userService: UserService,
private titleService: Title,
) {}
ngOnInit() { ngOnInit() {
this.userService.populate(); this.userService.populate();
@@ -1,7 +1,7 @@
import { DatePipe } from '@angular/common'; import { DatePipe } from '@angular/common';
import { trigger, state, style, animate, transition } from '@angular/animations'; import { trigger, state, style, animate, transition } from '@angular/animations';
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core'; import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { ActivatedRoute } from '@angular/router'; import { ActivatedRoute } from '@angular/router';
import { MatBadgeModule } from '@angular/material/badge'; import { MatBadgeModule } from '@angular/material/badge';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
@@ -22,28 +22,29 @@ import { AeronefByImat, AeronefByYear } from '@models';
@Component({ @Component({
selector: 'app-aeronefs', selector: 'app-aeronefs',
standalone: true,
imports: [ imports: [
DatePipe, DatePipe,
MatBadgeModule, MatButtonModule, MatCardModule, MatDividerModule, MatBadgeModule,
MatExpansionModule, MatGridListModule, MatIconModule, MatMenuModule, MatButtonModule,
BarsChartComponent, HistoryTableComponent, PieChartComponent MatCardModule,
MatDividerModule,
MatExpansionModule,
MatGridListModule,
MatIconModule,
MatMenuModule,
BarsChartComponent,
HistoryTableComponent,
PieChartComponent,
], ],
templateUrl: './aeronefs.component.html', templateUrl: './aeronefs.component.html',
styleUrl: './aeronefs.component.scss', styleUrl: './aeronefs.component.scss',
animations: [ animations: [
trigger('flyInOut', [ trigger('flyInOut', [
state('in', style({ transform: 'translateX(0)' })), state('in', style({ transform: 'translateX(0)' })),
transition('void => *', [ transition('void => *', [style({ transform: 'translateX(-100%)' }), animate(200)]),
style({ transform: 'translateX(-100%)' }), transition('* => void', [style({ transform: 'translateX(100%)' }), animate(200)]),
animate(200)
]), ]),
transition('* => void', [ ],
style({ transform: 'translateX(100%)' }),
animate(200)
])
])
]
}) })
export class AeronefsComponent implements OnInit, OnDestroy { export class AeronefsComponent implements OnInit, OnDestroy {
private _data: Subscription = new Subscription(); private _data: Subscription = new Subscription();
@@ -59,23 +60,27 @@ export class AeronefsComponent implements OnInit, OnDestroy {
public seriesValue: number[] = []; public seriesValue: number[] = [];
public seriesRow: Array<Array<number>> = []; public seriesRow: Array<Array<number>> = [];
public seriesColor: { public seriesColor: {
backgroundColor: string[], backgroundColor: string[];
borderColor: string[] borderColor: string[];
} = { } = {
backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'), backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'),
borderColor: this._utilitiesService.getSeriesColors(1, 'all') borderColor: this._utilitiesService.getSeriesColors(1, 'all'),
}; };
public seriesColorClass: string[] = this._utilitiesService.getChartColors(); public seriesColorClass: string[] = this._utilitiesService.getChartColors();
constructor( constructor(
private route: ActivatedRoute, private route: ActivatedRoute,
private _utilitiesService: UtilitiesService, private _utilitiesService: UtilitiesService,
public menuItems: MenuItems public menuItems: MenuItems,
) { } ) {}
ngOnInit() { ngOnInit() {
const data$: Observable<{ aeronefsPageData: AeronefsPageData }> = this.route.data as Observable<{ aeronefsPageData: AeronefsPageData }>; const data$: Observable<{ aeronefsPageData: AeronefsPageData }> = this.route.data as Observable<{
this._data = data$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: { aeronefsPageData: AeronefsPageData }) => { aeronefsPageData: AeronefsPageData;
}>;
this._data = data$
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe((data: { aeronefsPageData: AeronefsPageData }) => {
const pageData: AeronefsPageData = data.aeronefsPageData; const pageData: AeronefsPageData = data.aeronefsPageData;
this.lastJump = pageData.lastjump; this.lastJump = pageData.lastjump;
this._loadAeronefByImat(pageData); this._loadAeronefByImat(pageData);
+23 -15
View File
@@ -1,6 +1,15 @@
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core'; import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { UntypedFormBuilder, UntypedFormGroup, AbstractControl, Validators, ValidatorFn, ValidationErrors, FormsModule, ReactiveFormsModule } from '@angular/forms'; import {
UntypedFormBuilder,
UntypedFormGroup,
AbstractControl,
Validators,
ValidatorFn,
ValidationErrors,
FormsModule,
ReactiveFormsModule,
} from '@angular/forms';
import { Title } from '@angular/platform-browser'; import { Title } from '@angular/platform-browser';
import { ActivatedRoute, Router, RouterLink } from '@angular/router'; import { ActivatedRoute, Router, RouterLink } from '@angular/router';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
@@ -15,7 +24,6 @@ import { UserService } from '@services';
import { ListErrorsComponent, ShowAuthedDirective } from '@components/shared'; import { ListErrorsComponent, ShowAuthedDirective } from '@components/shared';
@Component({ @Component({
standalone: true,
imports: [ imports: [
RouterLink, RouterLink,
FormsModule, FormsModule,
@@ -24,11 +32,11 @@ import { ListErrorsComponent, ShowAuthedDirective } from '@components/shared';
MatInputModule, MatInputModule,
MatButtonModule, MatButtonModule,
ListErrorsComponent, ListErrorsComponent,
ShowAuthedDirective ShowAuthedDirective,
], ],
selector: 'app-auth', selector: 'app-auth',
templateUrl: './auth.component.html', templateUrl: './auth.component.html',
styleUrl: './auth.component.scss' styleUrl: './auth.component.scss',
}) })
export class AuthComponent implements OnInit, OnDestroy { export class AuthComponent implements OnInit, OnDestroy {
private _url: Subscription = new Subscription(); private _url: Subscription = new Subscription();
@@ -46,7 +54,7 @@ export class AuthComponent implements OnInit, OnDestroy {
private router: Router, private router: Router,
private titleService: Title, private titleService: Title,
private userService: UserService, private userService: UserService,
private fb: UntypedFormBuilder private fb: UntypedFormBuilder,
) { ) {
this._resetErrors(); this._resetErrors();
// use FormBuilder to create a form group // use FormBuilder to create a form group
@@ -59,7 +67,7 @@ export class AuthComponent implements OnInit, OnDestroy {
licence: '', licence: '',
poids: '', poids: '',
password: ['', Validators.required], password: ['', Validators.required],
confirmPassword: '' confirmPassword: '',
}; };
this.authForm = this.fb.group(controlsConfig, { validators: this.checkPasswords }); this.authForm = this.fb.group(controlsConfig, { validators: this.checkPasswords });
} }
@@ -68,8 +76,7 @@ export class AuthComponent implements OnInit, OnDestroy {
// you would normally unsubscribe from this observable subscription // you would normally unsubscribe from this observable subscription
// the active route observables are exemptions from unsubribe always rule // the active route observables are exemptions from unsubribe always rule
// see notes on: https://angular.io/guide/router#observable-parammap-and-component-reuse // see notes on: https://angular.io/guide/router#observable-parammap-and-component-reuse
this.route.url.pipe(take(1)) this.route.url.pipe(take(1)).subscribe((data) => {
.subscribe(data => {
// Get the last piece of the URL (it's either 'login' or 'register') // Get the last piece of the URL (it's either 'login' or 'register')
this.authType = data[data.length - 1].path; this.authType = data[data.length - 1].path;
// Set a title for the page accordingly // Set a title for the page accordingly
@@ -104,14 +111,16 @@ export class AuthComponent implements OnInit, OnDestroy {
if (this.authForm.valid) { if (this.authForm.valid) {
this._resetErrors(); this._resetErrors();
const credentials = this.authForm.value; const credentials = this.authForm.value;
const user$ = this.userService.attemptAuth(this.authType, credentials).pipe(takeUntilDestroyed(this.destroyRef)); const user$ = this.userService
.attemptAuth(this.authType, credentials)
.pipe(takeUntilDestroyed(this.destroyRef));
this._user = user$.subscribe({ this._user = user$.subscribe({
next: () => void this.router.navigateByUrl('/'), next: () => void this.router.navigateByUrl('/'),
error: (err) => { error: (err) => {
console.log(err); console.log(err);
this.errors = err; this.errors = err;
this.isSubmitting = false; this.isSubmitting = false;
} },
}); });
} }
} }
@@ -157,12 +166,11 @@ export class AuthComponent implements OnInit, OnDestroy {
return null; return null;
} }
const pass = group.get('password')!.value; const pass = group.get('password')!.value;
const confirmPass = group.get('confirmPassword')!.value const confirmPass = group.get('confirmPassword')!.value;
return (pass === confirmPass && pass !== '') ? null : { notSame: true } return pass === confirmPass && pass !== '' ? null : { notSame: true };
} };
private _resetErrors(): void { private _resetErrors(): void {
this.errors = { errors: {} }; this.errors = { errors: {} };
} }
} }
@@ -18,34 +18,49 @@ import { BaseChartDirective } from 'ng2-charts';
import { Observable, Subscription } from 'rxjs'; import { Observable, Subscription } from 'rxjs';
import { MenuItems } from '@components/shared'; import { MenuItems } from '@components/shared';
import { CalculatorInfo, CalculatorResult, CalculatorState, InputParams, Jump, LineConfig, WeightSizeRange, TableHeader, User, WeightSize, weightSizes } from '@models'; import {
CalculatorInfo,
CalculatorResult,
CalculatorState,
InputParams,
Jump,
LineConfig,
WeightSizeRange,
TableHeader,
User,
WeightSize,
weightSizes,
} from '@models';
import { CalculatorService, JumpsService, UserService, UtilitiesService } from '@services'; import { CalculatorService, JumpsService, UserService, UtilitiesService } from '@services';
@Component({ @Component({
selector: 'app-calculator', selector: 'app-calculator',
standalone: true,
imports: [ imports: [
CommonModule, FormsModule, RouterModule, CommonModule,
MatButtonModule, MatCardModule, MatDividerModule, FormsModule,
MatFormFieldModule, MatInputModule, MatIconModule, MatMenuModule, RouterModule,
MatPaginatorModule, MatProgressBarModule, MatSortModule, MatTableModule, MatButtonModule,
BaseChartDirective MatCardModule,
MatDividerModule,
MatFormFieldModule,
MatInputModule,
MatIconModule,
MatMenuModule,
MatPaginatorModule,
MatProgressBarModule,
MatSortModule,
MatTableModule,
BaseChartDirective,
], ],
templateUrl: './calculator.component.html', templateUrl: './calculator.component.html',
styleUrl: './calculator.component.scss', styleUrl: './calculator.component.scss',
animations: [ animations: [
trigger('flyInOut', [ trigger('flyInOut', [
state('in', style({ transform: 'translateY(0)' })), state('in', style({ transform: 'translateY(0)' })),
transition('void => *', [ transition('void => *', [style({ transform: 'translateY(-100%)' }), animate(200)]),
style({ transform: 'translateY(-100%)' }), transition('* => void', [style({ transform: 'translateY(100%)' }), animate(200)]),
animate(200)
]), ]),
transition('* => void', [ ],
style({ transform: 'translateY(100%)' }),
animate(200)
])
])
]
}) })
export class CalculatorComponent implements OnInit, OnDestroy { export class CalculatorComponent implements OnInit, OnDestroy {
//private _lastjump!: Subscription; // = new Subscription(); //private _lastjump!: Subscription; // = new Subscription();
@@ -57,7 +72,7 @@ export class CalculatorComponent implements OnInit, OnDestroy {
public currentRange: WeightSizeRange = {} as WeightSizeRange; public currentRange: WeightSizeRange = {} as WeightSizeRange;
public currentUser: User = {} as User; public currentUser: User = {} as User;
public displayedColumns: Array<string> = ['weight']; public displayedColumns: Array<string> = ['weight'];
public tableHeader: Array<TableHeader> = [<TableHeader>{name: 'Poids nu en kg', active: ''}]; public tableHeader: Array<TableHeader> = [<TableHeader>{ name: 'Poids nu en kg', active: '' }];
public sizesHeader: Array<TableHeader> = []; public sizesHeader: Array<TableHeader> = [];
public sizesValuesFeet: Array<number> = []; public sizesValuesFeet: Array<number> = [];
public sizesMinValuesFeet: Array<number> = []; public sizesMinValuesFeet: Array<number> = [];
@@ -71,16 +86,16 @@ export class CalculatorComponent implements OnInit, OnDestroy {
charges: <CalculatorResult>{ current: 0, min: 0, min11: 0 }, charges: <CalculatorResult>{ current: 0, min: 0, min11: 0 },
sizesFeet: <CalculatorResult>{ current: 0, min: 0, min11: 0 }, sizesFeet: <CalculatorResult>{ current: 0, min: 0, min11: 0 },
sizesMeter: <CalculatorResult>{ current: 0, min: 0, min11: 0 }, sizesMeter: <CalculatorResult>{ current: 0, min: 0, min11: 0 },
state: <CalculatorState>{ color: 'danger' } state: <CalculatorState>{ color: 'danger' },
} };
@Input() canopy_size_table!: MatTableDataSource<WeightSize>; @Input() canopy_size_table!: MatTableDataSource<WeightSize>;
@Input() inputs: InputParams = <InputParams>{ @Input() inputs: InputParams = (<InputParams>{
jumps: 0, jumps: 0,
weight: 60, weight: 60,
gear: 10, gear: 10,
current: 190 current: 190,
} as InputParams; }) as InputParams;
@ViewChild(MatSort) sort!: MatSort; @ViewChild(MatSort) sort!: MatSort;
@ViewChild(MatPaginator) paginator!: MatPaginator; @ViewChild(MatPaginator) paginator!: MatPaginator;
@@ -90,22 +105,20 @@ export class CalculatorComponent implements OnInit, OnDestroy {
private _jumpsService: JumpsService, private _jumpsService: JumpsService,
private _userService: UserService, private _userService: UserService,
private _utilitiesService: UtilitiesService, private _utilitiesService: UtilitiesService,
public menuItems: MenuItems public menuItems: MenuItems,
) { } ) {}
ngOnInit() { ngOnInit() {
const currentUser$: Observable<User> = this._userService.currentUser; const currentUser$: Observable<User> = this._userService.currentUser;
const lastjump$: Observable<Jump> = this._jumpsService.getLastJump(); const lastjump$: Observable<Jump> = this._jumpsService.getLastJump();
weightSizes[0].ranges.forEach((range: WeightSizeRange) => { weightSizes[0].ranges.forEach((range: WeightSizeRange) => {
const header: TableHeader = {name: range.label, active: range.active}; const header: TableHeader = { name: range.label, active: range.active };
this.tableHeader.push(header) this.tableHeader.push(header);
this.sizesHeader.push(header); this.sizesHeader.push(header);
this.displayedColumns.push(range.name); this.displayedColumns.push(range.name);
}); });
this.chartConfig.lineChartData.labels = [...this.sizesHeader.map( this.chartConfig.lineChartData.labels = [...this.sizesHeader.map((data: TableHeader): string => data.name)];
(data: TableHeader): string => data.name
)];
this.chartConfig.lineChartData.datasets = [ this.chartConfig.lineChartData.datasets = [
{ {
label: 'Tailles min -11%', label: 'Tailles min -11%',
@@ -114,7 +127,7 @@ export class CalculatorComponent implements OnInit, OnDestroy {
stepped: true, stepped: true,
pointStyle: false, pointStyle: false,
borderColor: 'rgba(241, 80, 80, 1)', borderColor: 'rgba(241, 80, 80, 1)',
backgroundColor: 'rgba(241, 80, 80, 0.3)' backgroundColor: 'rgba(241, 80, 80, 0.3)',
}, },
{ {
label: 'Tailles min', label: 'Tailles min',
@@ -123,8 +136,8 @@ export class CalculatorComponent implements OnInit, OnDestroy {
stepped: true, stepped: true,
pointStyle: false, pointStyle: false,
borderColor: 'rgba(32, 182, 252, 1)', borderColor: 'rgba(32, 182, 252, 1)',
backgroundColor: 'rgba(32, 182, 252, 0.3)' backgroundColor: 'rgba(32, 182, 252, 0.3)',
} },
]; ];
this._subscriptions.push( this._subscriptions.push(
currentUser$.subscribe((userData: User) => { currentUser$.subscribe((userData: User) => {
@@ -137,9 +150,9 @@ export class CalculatorComponent implements OnInit, OnDestroy {
this.inputs.current = jump.taille!; this.inputs.current = jump.taille!;
this.canopy_size_table = new MatTableDataSource<WeightSize>(weightSizes); this.canopy_size_table = new MatTableDataSource<WeightSize>(weightSizes);
this.refresh(); this.refresh();
}) }),
); );
}) }),
); );
} }
@@ -149,7 +162,7 @@ export class CalculatorComponent implements OnInit, OnDestroy {
}); });
} }
public refresh():void { public refresh(): void {
this._refreshActive(); this._refreshActive();
this._refreshSizes(); this._refreshSizes();
} }
@@ -159,25 +172,25 @@ export class CalculatorComponent implements OnInit, OnDestroy {
if (this.inputs.weight < 60) { if (this.inputs.weight < 60) {
weight = 60; weight = 60;
} }
weightSizes.forEach(element => { weightSizes.forEach((element) => {
element.active = ''; element.active = '';
element.ranges.forEach(range => { element.ranges.forEach((range) => {
range.active = ''; range.active = '';
}); });
}); });
this.tableHeader.forEach(element => { this.tableHeader.forEach((element) => {
element.active = ''; element.active = '';
}); });
if (weight >= 60 && weight <= 110) { if (weight >= 60 && weight <= 110) {
weightSizes[(weight - 60)].active = 'active'; weightSizes[weight - 60].active = 'active';
} }
if (this.inputs.jumps >= 0) { if (this.inputs.jumps >= 0) {
const num = this._calculatorService.getRangeNum(this.inputs.jumps); const num = this._calculatorService.getRangeNum(this.inputs.jumps);
this.tableHeader[num].active = 'active'; this.tableHeader[num].active = 'active';
weightSizes.forEach(element => { weightSizes.forEach((element) => {
element.ranges[(num-1)].active = 'active'; element.ranges[num - 1].active = 'active';
}); });
this.currentRange = weightSizes[0].ranges[(num-1)]; this.currentRange = weightSizes[0].ranges[num - 1];
} }
} }
@@ -200,13 +213,13 @@ export class CalculatorComponent implements OnInit, OnDestroy {
this.info.sizesMeter = { this.info.sizesMeter = {
current: this._calculatorService.convertFeet2Meters(this.inputs.current), current: this._calculatorService.convertFeet2Meters(this.inputs.current),
min: this._calculatorService.convertFeet2Meters(this.info.sizesFeet.min), min: this._calculatorService.convertFeet2Meters(this.info.sizesFeet.min),
min11: this._calculatorService.convertFeet2Meters(this.info.sizesFeet.min11) min11: this._calculatorService.convertFeet2Meters(this.info.sizesFeet.min11),
} };
this.info.charges = { this.info.charges = {
current: this._calculatorService.getCharge(this.inputs.current, this.inputs.weight, this.inputs.gear), current: this._calculatorService.getCharge(this.inputs.current, this.inputs.weight, this.inputs.gear),
min: this._calculatorService.getCharge(this.info.sizesFeet.min, this.inputs.weight, this.inputs.gear), min: this._calculatorService.getCharge(this.info.sizesFeet.min, this.inputs.weight, this.inputs.gear),
min11: this._calculatorService.getCharge(this.info.sizesFeet.min11, this.inputs.weight, this.inputs.gear) min11: this._calculatorService.getCharge(this.info.sizesFeet.min11, this.inputs.weight, this.inputs.gear),
} };
this.info.state.color = this._calculatorService.getStateColor(this.info.sizesFeet); this.info.state.color = this._calculatorService.getStateColor(this.info.sizesFeet);
this.chartConfig.lineChartData.datasets[0].data = this.sizesMinValuesFeet; this.chartConfig.lineChartData.datasets[0].data = this.sizesMinValuesFeet;
@@ -218,5 +231,4 @@ export class CalculatorComponent implements OnInit, OnDestroy {
this.inputs.weight = weight; this.inputs.weight = weight;
this.refresh(); this.refresh();
} }
} }
@@ -1,7 +1,7 @@
import { DatePipe } from '@angular/common'; import { DatePipe } from '@angular/common';
import { trigger, state, style, animate, transition } from '@angular/animations'; import { trigger, state, style, animate, transition } from '@angular/animations';
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core'; import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { ActivatedRoute } from '@angular/router'; import { ActivatedRoute } from '@angular/router';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card'; import { MatCardModule } from '@angular/material/card';
@@ -21,28 +21,28 @@ import { CanopyBySize, CanopyByYear, CanopyModelBySize, CanopyModelByYear } from
@Component({ @Component({
selector: 'app-canopies', selector: 'app-canopies',
standalone: true,
imports: [ imports: [
DatePipe, DatePipe,
MatButtonModule, MatCardModule, MatDividerModule, MatExpansionModule, MatButtonModule,
MatGridListModule, MatIconModule, MatMenuModule, MatCardModule,
HistoryTableComponent, BarsChartComponent, PieChartComponent MatDividerModule,
MatExpansionModule,
MatGridListModule,
MatIconModule,
MatMenuModule,
HistoryTableComponent,
BarsChartComponent,
PieChartComponent,
], ],
templateUrl: './canopies.component.html', templateUrl: './canopies.component.html',
styleUrl: './canopies.component.scss', styleUrl: './canopies.component.scss',
animations: [ animations: [
trigger('flyInOut', [ trigger('flyInOut', [
state('in', style({ transform: 'translateX(0)' })), state('in', style({ transform: 'translateX(0)' })),
transition('void => *', [ transition('void => *', [style({ transform: 'translateX(-100%)' }), animate(200)]),
style({ transform: 'translateX(-100%)' }), transition('* => void', [style({ transform: 'translateX(100%)' }), animate(200)]),
animate(200)
]), ]),
transition('* => void', [ ],
style({ transform: 'translateX(100%)' }),
animate(200)
])
])
]
}) })
export class CanopiesComponent implements OnInit, OnDestroy { export class CanopiesComponent implements OnInit, OnDestroy {
private _data: Subscription = new Subscription(); private _data: Subscription = new Subscription();
@@ -64,23 +64,27 @@ export class CanopiesComponent implements OnInit, OnDestroy {
public seriesSizeValue: number[] = []; public seriesSizeValue: number[] = [];
public seriesSizeRow: Array<Array<number>> = []; public seriesSizeRow: Array<Array<number>> = [];
public seriesColor: { public seriesColor: {
backgroundColor: string[], backgroundColor: string[];
borderColor: string[] borderColor: string[];
} = { } = {
backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'), backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'),
borderColor: this._utilitiesService.getSeriesColors(1, 'all') borderColor: this._utilitiesService.getSeriesColors(1, 'all'),
}; };
public seriesColorClass: string[] = this._utilitiesService.getChartColors(); public seriesColorClass: string[] = this._utilitiesService.getChartColors();
constructor( constructor(
private route: ActivatedRoute, private route: ActivatedRoute,
private _utilitiesService: UtilitiesService, private _utilitiesService: UtilitiesService,
public menuItems: MenuItems public menuItems: MenuItems,
) { } ) {}
ngOnInit() { ngOnInit() {
const data$: Observable<{ canopiesPageData: CanopiesPageData }> = this.route.data as Observable<{ canopiesPageData: CanopiesPageData }>; const data$: Observable<{ canopiesPageData: CanopiesPageData }> = this.route.data as Observable<{
this._data = data$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: { canopiesPageData: CanopiesPageData }) => { canopiesPageData: CanopiesPageData;
}>;
this._data = data$
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe((data: { canopiesPageData: CanopiesPageData }) => {
const pageData: CanopiesPageData = data.canopiesPageData; const pageData: CanopiesPageData = data.canopiesPageData;
this.lastJump = pageData.lastjump; this.lastJump = pageData.lastjump;
this._loadCanopyBySize(pageData); this._loadCanopyBySize(pageData);
@@ -134,7 +138,9 @@ export class CanopiesComponent implements OnInit, OnDestroy {
const voile: string = row.voile; const voile: string = row.voile;
const taille: string = row.taille.toString(); const taille: string = row.taille.toString();
const year: string = row.year.toString(); const year: string = row.year.toString();
this.seriesModelRow[this.seriesModelName.indexOf(`${taille} - ${voile}`)][this.seriesModelHeader.indexOf(year)] = row.count; this.seriesModelRow[this.seriesModelName.indexOf(`${taille} - ${voile}`)][
this.seriesModelHeader.indexOf(year)
] = row.count;
return row; return row;
}); });
this.displayCharts = true; this.displayCharts = true;
@@ -7,29 +7,46 @@ import { ActivatedRoute, Data, Router } from '@angular/router';
import { Observable, Subscription } from 'rxjs'; import { Observable, Subscription } from 'rxjs';
import { take } from 'rxjs/operators'; import { take } from 'rxjs/operators';
import { Aeronef, AeronefByImat, Canopy, CanopyModelBySize, DropZone, DropZoneByYear, Errors, Jump, User } from '@models'; import {
Aeronef,
AeronefByImat,
Canopy,
CanopyModelBySize,
DropZone,
DropZoneByYear,
Errors,
Jump,
User,
} from '@models';
//import { AeronefsService, CanopiesService, DropZonesService, UserService } from '@services'; //import { AeronefsService, CanopiesService, DropZonesService, UserService } from '@services';
import { JumpsService, UserService } from '@services'; import { JumpsService, UserService } from '@services';
import { ShowAuthedDirective } from '@components/shared/show-authed.directive'; import { ShowAuthedDirective } from '@components/shared/show-authed.directive';
import { import {
AeronefsPieComponent, AeronefsBarComponent, AeronefsPieComponent,
CanopiesModelsComponent, CanopiesSizesComponent, AeronefsBarComponent,
DropzonesPieComponent, DropzonesBarComponent, CanopiesModelsComponent,
JumpsByMonthComponent CanopiesSizesComponent,
DropzonesPieComponent,
DropzonesBarComponent,
JumpsByMonthComponent,
} from '@components/shared/dashboard-components'; } from '@components/shared/dashboard-components';
@Component({ @Component({
standalone: true,
imports: [ imports: [
DatePipe, ShowAuthedDirective, MatDividerModule, DatePipe,
AeronefsPieComponent, AeronefsBarComponent, ShowAuthedDirective,
CanopiesModelsComponent, CanopiesSizesComponent, MatDividerModule,
DropzonesPieComponent, DropzonesBarComponent, AeronefsPieComponent,
JumpsByMonthComponent AeronefsBarComponent,
CanopiesModelsComponent,
CanopiesSizesComponent,
DropzonesPieComponent,
DropzonesBarComponent,
JumpsByMonthComponent,
], ],
selector: 'app-dashboard', selector: 'app-dashboard',
templateUrl: './dashboard.component.html', templateUrl: './dashboard.component.html',
styleUrl: './dashboard.component.scss' styleUrl: './dashboard.component.scss',
}) })
export class DashboardComponent implements OnInit, OnDestroy { export class DashboardComponent implements OnInit, OnDestroy {
private _currentUser: Subscription = new Subscription(); private _currentUser: Subscription = new Subscription();
@@ -61,7 +78,7 @@ export class DashboardComponent implements OnInit, OnDestroy {
private router: Router, private router: Router,
private titleService: Title, private titleService: Title,
private _userService: UserService, private _userService: UserService,
private _jumpsService: JumpsService private _jumpsService: JumpsService,
/* /*
private aeronefsService: AeronefsService, private aeronefsService: AeronefsService,
private canopiesService: CanopiesService, private canopiesService: CanopiesService,
@@ -95,7 +112,6 @@ export class DashboardComponent implements OnInit, OnDestroy {
this._loadCanopies(); this._loadCanopies();
this._loadDropzones(); this._loadDropzones();
*/ */
} }
ngOnDestroy() { ngOnDestroy() {
+73 -19
View File
@@ -1,5 +1,5 @@
import { Component, OnInit, OnDestroy } from '@angular/core'; import { Component, OnInit, OnDestroy } from '@angular/core';
import {CdkDragDrop, CdkDropList, CdkDrag, CdkDragPlaceholder, moveItemInArray} from '@angular/cdk/drag-drop'; import { CdkDragDrop, CdkDropList, CdkDrag, CdkDragPlaceholder, moveItemInArray } from '@angular/cdk/drag-drop';
import { Title } from '@angular/platform-browser'; import { Title } from '@angular/platform-browser';
import { RouterLink } from '@angular/router'; import { RouterLink } from '@angular/router';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
@@ -17,30 +17,85 @@ import { ListErrorsComponent } from '@components/shared';
@Component({ @Component({
selector: 'app-demo', selector: 'app-demo',
standalone: true,
imports: [ imports: [
CdkDropList, CdkDrag, CdkDragPlaceholder, RouterLink, CdkDropList,
MatButtonModule, MatCardModule, MatDividerModule, CdkDrag,
MatIconModule, MatProgressBarModule, MatSliderModule, CdkDragPlaceholder,
ListErrorsComponent RouterLink,
MatButtonModule,
MatCardModule,
MatDividerModule,
MatIconModule,
MatProgressBarModule,
MatSliderModule,
ListErrorsComponent,
], ],
templateUrl: './demo.component.html', templateUrl: './demo.component.html',
styleUrl: './demo.component.scss' styleUrl: './demo.component.scss',
}) })
export class DemoComponent implements OnInit, OnDestroy { export class DemoComponent implements OnInit, OnDestroy {
private _user: Subscription = new Subscription(); private _user: Subscription = new Subscription();
private _colors: string[] = [ private _colors: string[] = [
"primary", "accent", "warn", "secondary", "megna", "raspberry", "success", "info", 'primary',
"warning", "danger", "red", "orange", "yellow", "green", "teal", "turquoise", "cyan", 'accent',
"blue", "navy", "navy-light", "pink", "magenta", "purple", "purple-light", "grey", "muted" 'warn',
'secondary',
'megna',
'raspberry',
'success',
'info',
'warning',
'danger',
'red',
'orange',
'yellow',
'green',
'teal',
'turquoise',
'cyan',
'blue',
'navy',
'navy-light',
'pink',
'magenta',
'purple',
'purple-light',
'grey',
'muted',
]; ];
private _icons: string[] = [ private _icons: string[] = [
'mode_edit', 'delete', 'bookmark', 'settings', 'home', 'person', 'mode_edit',
'share', 'account_circle', 'public', 'search', 'favorite', 'done', 'delete',
'numbers', 'attach_file', 'insert_comment', 'format_list_bulleted', 'bookmark',
'filter', 'crop', 'edit_attributes', 'upload', 'download', 'expand_less', 'settings',
'expand_more', 'chevron_left', 'chevron_right', 'sync', 'power', 'home',
'power_off', 'notifications', 'emoji_emotions', 'person_add', 'block' 'person',
'share',
'account_circle',
'public',
'search',
'favorite',
'done',
'numbers',
'attach_file',
'insert_comment',
'format_list_bulleted',
'filter',
'crop',
'edit_attributes',
'upload',
'download',
'expand_less',
'expand_more',
'chevron_left',
'chevron_right',
'sync',
'power',
'power_off',
'notifications',
'emoji_emotions',
'person_add',
'block',
]; ];
title = 'Demo'; title = 'Demo';
@@ -51,8 +106,8 @@ export class DemoComponent implements OnInit, OnDestroy {
constructor( constructor(
private titleService: Title, private titleService: Title,
private userService: UserService private userService: UserService,
) { } ) {}
ngOnInit() { ngOnInit() {
this.titleService.setTitle(`Ad Astra - ${this.title}`); this.titleService.setTitle(`Ad Astra - ${this.title}`);
@@ -79,5 +134,4 @@ export class DemoComponent implements OnInit, OnDestroy {
drop(event: CdkDragDrop<string[]>) { drop(event: CdkDragDrop<string[]>) {
moveItemInArray(this._colors, event.previousIndex, event.currentIndex); moveItemInArray(this._colors, event.previousIndex, event.currentIndex);
} }
} }
@@ -1,8 +1,8 @@
import { DatePipe } from '@angular/common'; import { DatePipe } from '@angular/common';
import { trigger, state, style, animate, transition } from '@angular/animations'; import { trigger, state, style, animate, transition } from '@angular/animations';
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core'; import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { GoogleMap, MapKmlLayer} from '@angular/google-maps'; import { GoogleMap, MapKmlLayer } from '@angular/google-maps';
import { ActivatedRoute } from '@angular/router'; import { ActivatedRoute } from '@angular/router';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card'; import { MatCardModule } from '@angular/material/card';
@@ -23,29 +23,31 @@ import { UtilitiesService } from '@services';
@Component({ @Component({
selector: 'app-dropzones', selector: 'app-dropzones',
standalone: true,
imports: [ imports: [
DatePipe, GoogleMap, MapKmlLayer, DatePipe,
MatButtonModule, MatCardModule, MatDividerModule, MatExpansionModule, GoogleMap,
MatGridListModule, MatIconModule, MatMenuModule, MapKmlLayer,
MatButtonModule,
MatCardModule,
MatDividerModule,
MatExpansionModule,
MatGridListModule,
MatIconModule,
MatMenuModule,
//ChartistModule, //ChartistModule,
HistoryTableComponent, BarsChartComponent, PieChartComponent HistoryTableComponent,
BarsChartComponent,
PieChartComponent,
], ],
templateUrl: './dropzones.component.html', templateUrl: './dropzones.component.html',
styleUrl: './dropzones.component.scss', styleUrl: './dropzones.component.scss',
animations: [ animations: [
trigger('flyInOut', [ trigger('flyInOut', [
state('in', style({ transform: 'translateX(0)' })), state('in', style({ transform: 'translateX(0)' })),
transition('void => *', [ transition('void => *', [style({ transform: 'translateX(-100%)' }), animate(200)]),
style({ transform: 'translateX(-100%)' }), transition('* => void', [style({ transform: 'translateX(100%)' }), animate(200)]),
animate(200)
]), ]),
transition('* => void', [ ],
style({ transform: 'translateX(100%)' }),
animate(200)
])
])
]
}) })
export class DropzonesComponent implements OnInit, OnDestroy { export class DropzonesComponent implements OnInit, OnDestroy {
private _data: Subscription = new Subscription(); private _data: Subscription = new Subscription();
@@ -62,16 +64,16 @@ export class DropzonesComponent implements OnInit, OnDestroy {
public seriesValue: number[] = []; public seriesValue: number[] = [];
public seriesRow: Array<Array<number>> = []; public seriesRow: Array<Array<number>> = [];
public seriesColor: { public seriesColor: {
backgroundColor: string[], backgroundColor: string[];
borderColor: string[] borderColor: string[];
} = { } = {
backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'), backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'),
borderColor: this._utilitiesService.getSeriesColors(1, 'all') borderColor: this._utilitiesService.getSeriesColors(1, 'all'),
}; };
public seriesColorClass: string[] = this._utilitiesService.getChartColors(); public seriesColorClass: string[] = this._utilitiesService.getChartColors();
//public chartBarConfig: Configuration = this._utilitiesService.getBarConfig(); //public chartBarConfig: Configuration = this._utilitiesService.getBarConfig();
public center: google.maps.LatLngLiteral = {lat: 44.596408, lng: -1.115958}; public center: google.maps.LatLngLiteral = { lat: 44.596408, lng: -1.115958 };
public zoom = 16; public zoom = 16;
public kmlUrl = 'https://rampeur.com/assets/kmls/dropzones.kml?v=6'; public kmlUrl = 'https://rampeur.com/assets/kmls/dropzones.kml?v=6';
//public mapTypeId: google.maps.MapTypeId = google.maps.MapTypeId.SATELLITE; //public mapTypeId: google.maps.MapTypeId = google.maps.MapTypeId.SATELLITE;
@@ -82,7 +84,7 @@ export class DropzonesComponent implements OnInit, OnDestroy {
mapTypeId: 'satellite', mapTypeId: 'satellite',
disableDoubleClickZoom: true, disableDoubleClickZoom: true,
maxZoom: 20, maxZoom: 20,
minZoom: 3 minZoom: 3,
}; };
// Arcachon : 44.596408,-1.115958 // Arcachon : 44.596408,-1.115958
// La Réole : 44.566309,-0.054606 // La Réole : 44.566309,-0.054606
@@ -98,12 +100,16 @@ export class DropzonesComponent implements OnInit, OnDestroy {
constructor( constructor(
private route: ActivatedRoute, private route: ActivatedRoute,
private _utilitiesService: UtilitiesService, private _utilitiesService: UtilitiesService,
public menuItems: MenuItems public menuItems: MenuItems,
) { } ) {}
ngOnInit() { ngOnInit() {
const data$: Observable<{ dropZonesPageData: DropZonesPageData }> = this.route.data as Observable<{ dropZonesPageData: DropZonesPageData }>; const data$: Observable<{ dropZonesPageData: DropZonesPageData }> = this.route.data as Observable<{
this._data = data$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: { dropZonesPageData: DropZonesPageData }) => { dropZonesPageData: DropZonesPageData;
}>;
this._data = data$
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe((data: { dropZonesPageData: DropZonesPageData }) => {
const pageData: DropZonesPageData = data.dropZonesPageData; const pageData: DropZonesPageData = data.dropZonesPageData;
this.lastJump = pageData.lastjump; this.lastJump = pageData.lastjump;
this._loadDropZoneByOaci(pageData); this._loadDropZoneByOaci(pageData);
@@ -23,7 +23,6 @@ export class GuildRaidStepperIntl extends MatStepperIntl {
} }
@Component({ @Component({
selector: 'app-herowars-guildraid', selector: 'app-herowars-guildraid',
standalone: true,
providers: [ providers: [
{ {
provide: STEPPER_GLOBAL_OPTIONS, provide: STEPPER_GLOBAL_OPTIONS,
@@ -11,7 +11,12 @@ import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input'; import { MatInputModule } from '@angular/material/input';
import { MatTabsModule } from '@angular/material/tabs'; import { MatTabsModule } from '@angular/material/tabs';
import { CardContainerComponent, ListErrorsComponent, GuildwarAttackComponent, GuildwarDefenceComponent } from '@components/shared'; import {
CardContainerComponent,
ListErrorsComponent,
GuildwarAttackComponent,
GuildwarDefenceComponent,
} from '@components/shared';
import { CardColors, Errors, HWActivityStat, HWGuildClan, HWMember } from '@models'; import { CardColors, Errors, HWActivityStat, HWGuildClan, HWMember } from '@models';
import { ClanViewModel, MembersViewModel } from '@viewmodels/herowars'; import { ClanViewModel, MembersViewModel } from '@viewmodels/herowars';
import { HWClanService, HWMemberService, UtilitiesService } from '@services'; import { HWClanService, HWMemberService, UtilitiesService } from '@services';
@@ -22,28 +27,31 @@ import guildStatistics from '@data/hw-guild-statistics.json'; // page Overview -
@Component({ @Component({
selector: 'app-herowars-guildwar', selector: 'app-herowars-guildwar',
standalone: true,
imports: [ imports: [
DatePipe, DecimalPipe, FormsModule, CardContainerComponent, ListErrorsComponent, DatePipe,
MatButtonModule, MatCardModule, MatDividerModule, MatFormFieldModule, DecimalPipe,
MatIconModule, MatInputModule, MatTabsModule, FormsModule,
GuildwarAttackComponent, GuildwarDefenceComponent CardContainerComponent,
ListErrorsComponent,
MatButtonModule,
MatCardModule,
MatDividerModule,
MatFormFieldModule,
MatIconModule,
MatInputModule,
MatTabsModule,
GuildwarAttackComponent,
GuildwarDefenceComponent,
], ],
templateUrl: './herowars-guildwar.component.html', templateUrl: './herowars-guildwar.component.html',
styleUrl: './herowars-guildwar.component.scss', styleUrl: './herowars-guildwar.component.scss',
animations: [ animations: [
trigger('flyInOut', [ trigger('flyInOut', [
state('in', style({ transform: 'translateY(0)' })), state('in', style({ transform: 'translateY(0)' })),
transition('void => *', [ transition('void => *', [style({ transform: 'translateY(-100%)' }), animate(200)]),
style({ transform: 'translateY(-100%)' }), transition('* => void', [style({ transform: 'translateY(100%)' }), animate(200)]),
animate(200)
]), ]),
transition('* => void', [ ],
style({ transform: 'translateY(100%)' }),
animate(200)
])
])
]
}) })
export class HerowarsGuildwarComponent implements OnInit { export class HerowarsGuildwarComponent implements OnInit {
public destroyRef = inject(DestroyRef); public destroyRef = inject(DestroyRef);
@@ -67,8 +75,8 @@ export class HerowarsGuildwarComponent implements OnInit {
private _titleService: Title, private _titleService: Title,
private _utilitiesService: UtilitiesService, private _utilitiesService: UtilitiesService,
private _clanService: HWClanService, private _clanService: HWClanService,
private _memberService: HWMemberService private _memberService: HWMemberService,
) { } ) {}
ngOnInit() { ngOnInit() {
this._titleService.setTitle(this.title); this._titleService.setTitle(this.title);
@@ -103,7 +111,7 @@ export class HerowarsGuildwarComponent implements OnInit {
this._guildClan = this._clanService.loadClan(); this._guildClan = this._clanService.loadClan();
this._guildMembers = this._memberService.loadMembers(this._guildClan); this._guildMembers = this._memberService.loadMembers(this._guildClan);
this._guildClan = this._clanService.loadClanStats(this._guildClan, this._guildMembers); this._guildClan = this._clanService.loadClanStats(this._guildClan, this._guildMembers);
this.daysToWarn = (parseInt(this._guildClan.daysToKick) / 2); this.daysToWarn = parseInt(this._guildClan.daysToKick) / 2;
this.clanViewModel = new ClanViewModel(this._guildClan); this.clanViewModel = new ClanViewModel(this._guildClan);
this.clanLoaded = true; this.clanLoaded = true;
this.membersViewModel = new MembersViewModel(this._guildMembers); this.membersViewModel = new MembersViewModel(this._guildMembers);
@@ -132,5 +140,4 @@ export class HerowarsGuildwarComponent implements OnInit {
console.log(this._guildMembers); console.log(this._guildMembers);
console.log(guildStatistics); console.log(guildStatistics);
} }
} }
@@ -10,8 +10,13 @@ import { MatTabsModule } from '@angular/material/tabs';
import { import {
ListErrorsComponent, ListErrorsComponent,
GuildCardComponent, GuildraidsLogComponent, GuildwarChampionsComponent, GuildCardComponent,
GuildwarAttackComponent, GuildwarDefenceComponent, GuildwarTeamsComponent, MembersStatisticsComponent GuildraidsLogComponent,
GuildwarChampionsComponent,
GuildwarAttackComponent,
GuildwarDefenceComponent,
GuildwarTeamsComponent,
MembersStatisticsComponent,
} from '@components/shared'; } from '@components/shared';
import { Errors, HWMember } from '@models'; import { Errors, HWMember } from '@models';
import guildData from 'src/files-data/hw-guild-data.json'; // page Membres import guildData from 'src/files-data/hw-guild-data.json'; // page Membres
@@ -21,29 +26,30 @@ import guildData from 'src/files-data/hw-guild-data.json'; // page Membres
@Component({ @Component({
selector: 'app-herowars', selector: 'app-herowars',
standalone: true,
imports: [ imports: [
DatePipe, DatePipe,
MatCardModule, MatDividerModule, MatIconModule, MatTabsModule, MatCardModule,
MatDividerModule,
MatIconModule,
MatTabsModule,
ListErrorsComponent, ListErrorsComponent,
GuildCardComponent, GuildraidsLogComponent, GuildwarChampionsComponent, GuildCardComponent,
GuildwarAttackComponent, GuildwarDefenceComponent, GuildwarTeamsComponent, MembersStatisticsComponent GuildraidsLogComponent,
GuildwarChampionsComponent,
GuildwarAttackComponent,
GuildwarDefenceComponent,
GuildwarTeamsComponent,
MembersStatisticsComponent,
], ],
templateUrl: './herowars.component.html', templateUrl: './herowars.component.html',
styleUrl: './herowars.component.scss', styleUrl: './herowars.component.scss',
animations: [ animations: [
trigger('flyInOut', [ trigger('flyInOut', [
state('in', style({ transform: 'translateY(0)' })), state('in', style({ transform: 'translateY(0)' })),
transition('void => *', [ transition('void => *', [style({ transform: 'translateY(-100%)' }), animate(200)]),
style({ transform: 'translateY(-100%)' }), transition('* => void', [style({ transform: 'translateY(100%)' }), animate(200)]),
animate(200)
]), ]),
transition('* => void', [ ],
style({ transform: 'translateY(100%)' }),
animate(200)
])
])
]
}) })
export class HerowarsComponent implements OnInit { export class HerowarsComponent implements OnInit {
public title = 'HeroWars GM Tools'; public title = 'HeroWars GM Tools';
@@ -53,9 +59,7 @@ export class HerowarsComponent implements OnInit {
public now = new Date(); public now = new Date();
private _guildMembers: HWMember[] = []; private _guildMembers: HWMember[] = [];
constructor( constructor(private _titleService: Title) {}
private _titleService: Title
) { }
ngOnInit() { ngOnInit() {
try { try {
@@ -68,8 +72,8 @@ export class HerowarsComponent implements OnInit {
} else { } else {
member.champion = false; member.champion = false;
} }
member.heroes = { power: 0, teams: []}; member.heroes = { power: 0, teams: [] };
member.titans = { power: 0, teams: []}; member.titans = { power: 0, teams: [] };
this._guildMembers.push(member); this._guildMembers.push(member);
} }
} catch (error) { } catch (error) {
@@ -80,5 +84,4 @@ export class HerowarsComponent implements OnInit {
getMembers(): HWMember[] { getMembers(): HWMember[] {
return this._guildMembers; return this._guildMembers;
} }
} }
+6 -18
View File
@@ -12,31 +12,20 @@ import { Errors } from '@models';
//import { UserService } from '@services'; //import { UserService } from '@services';
@Component({ @Component({
selector: 'app-home', selector: 'app-home',
standalone: true, imports: [DatePipe, MatCardModule, MatDividerModule, MatIconModule, ListErrorsComponent],
imports: [
DatePipe,
MatCardModule, MatDividerModule, MatIconModule,
ListErrorsComponent
],
templateUrl: './home.component.html', templateUrl: './home.component.html',
styleUrl: './home.component.scss', styleUrl: './home.component.scss',
animations: [ animations: [
trigger('flyInOut', [ trigger('flyInOut', [
state('in', style({ transform: 'translateY(0)' })), state('in', style({ transform: 'translateY(0)' })),
transition('void => *', [ transition('void => *', [style({ transform: 'translateY(-100%)' }), animate(200)]),
style({ transform: 'translateY(-100%)' }), transition('* => void', [style({ transform: 'translateY(100%)' }), animate(200)]),
animate(200)
]), ]),
transition('* => void', [ ],
style({ transform: 'translateY(100%)' }),
animate(200)
])
])
]
}) })
export class HomeComponent implements OnInit { export class HomeComponent implements OnInit {
public title = 'Shop bientôt disponible!'; public title = 'Shop bientôt disponible!';
public description = 'Encore un peu de patience, notre shop sera mis en ligne d\'ici peu.'; public description = "Encore un peu de patience, notre shop sera mis en ligne d'ici peu.";
public errors: Errors = { errors: {} }; public errors: Errors = { errors: {} };
public destroyRef = inject(DestroyRef); public destroyRef = inject(DestroyRef);
public now = new Date(); public now = new Date();
@@ -45,10 +34,9 @@ export class HomeComponent implements OnInit {
private _titleService: Title, private _titleService: Title,
//private _utilitiesService: UtilitiesService //private _utilitiesService: UtilitiesService
//private _userService: UserService //private _userService: UserService
) { } ) {}
ngOnInit() { ngOnInit() {
this._titleService.setTitle(this.title); this._titleService.setTitle(this.title);
/* /*
type CreateArrayWithLengthX< type CreateArrayWithLengthX<
+13 -9
View File
@@ -1,5 +1,5 @@
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core'; import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { DatePipe, DecimalPipe } from '@angular/common'; import { DatePipe, DecimalPipe } from '@angular/common';
import { ActivatedRoute, RouterLink } from '@angular/router'; import { ActivatedRoute, RouterLink } from '@angular/router';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
@@ -14,15 +14,19 @@ import { Errors, Jump, JumpPageData } from '@models';
@Component({ @Component({
selector: 'app-jump', selector: 'app-jump',
standalone: true,
imports: [ imports: [
DatePipe, DecimalPipe, RouterLink, DatePipe,
MatButtonModule, MatCardModule, DecimalPipe,
MatDividerModule, MatIconModule, MatMenuModule, RouterLink,
ListErrorsComponent MatButtonModule,
MatCardModule,
MatDividerModule,
MatIconModule,
MatMenuModule,
ListErrorsComponent,
], ],
templateUrl: './jump.component.html', templateUrl: './jump.component.html',
styleUrl: './jump.component.scss' styleUrl: './jump.component.scss',
}) })
export class JumpComponent implements OnInit, OnDestroy { export class JumpComponent implements OnInit, OnDestroy {
private _data: Subscription = new Subscription(); private _data: Subscription = new Subscription();
@@ -35,8 +39,8 @@ export class JumpComponent implements OnInit, OnDestroy {
constructor( constructor(
private route: ActivatedRoute, private route: ActivatedRoute,
public menuItems: MenuItems public menuItems: MenuItems,
) { } ) {}
ngOnInit() { ngOnInit() {
const data$: Observable<{ pageData: JumpPageData }> = this.route.data as Observable<{ pageData: JumpPageData }>; const data$: Observable<{ pageData: JumpPageData }> = this.route.data as Observable<{ pageData: JumpPageData }>;
+66 -47
View File
@@ -1,6 +1,6 @@
import { trigger, state, style, animate, transition } from '@angular/animations'; import { trigger, state, style, animate, transition } from '@angular/animations';
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core'; import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { ActivatedRoute } from '@angular/router'; import { ActivatedRoute } from '@angular/router';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
@@ -13,34 +13,39 @@ import { MatMenuModule } from '@angular/material/menu';
import { Observable, Subscription } from 'rxjs'; import { Observable, Subscription } from 'rxjs';
import { MenuItems } from '@components/shared'; import { MenuItems } from '@components/shared';
import { BarsChartComponent, CircleChartComponent, LineChartComponent, LineAreaChartComponent } from '@components/shared/helpers-chart'; import {
BarsChartComponent,
CircleChartComponent,
LineChartComponent,
LineAreaChartComponent,
} from '@components/shared/helpers-chart';
import { UtilitiesService } from '@services'; import { UtilitiesService } from '@services';
import { Jump, JumpByCategorie, JumpByDate, JumpByDateByModule, JumpByModule, JumpsPageData, JumpYears } from '@models'; import { Jump, JumpByCategorie, JumpByDate, JumpByDateByModule, JumpByModule, JumpsPageData, JumpYears } from '@models';
@Component({ @Component({
selector: 'app-jumps', selector: 'app-jumps',
standalone: true,
imports: [ imports: [
CommonModule, CommonModule,
MatButtonModule, MatCardModule, MatDividerModule, MatButtonModule,
MatExpansionModule, MatIconModule, MatMenuModule, MatCardModule,
BarsChartComponent, CircleChartComponent, LineChartComponent, LineAreaChartComponent MatDividerModule,
MatExpansionModule,
MatIconModule,
MatMenuModule,
BarsChartComponent,
CircleChartComponent,
LineChartComponent,
LineAreaChartComponent,
], ],
templateUrl: './jumps.component.html', templateUrl: './jumps.component.html',
styleUrl: './jumps.component.scss', styleUrl: './jumps.component.scss',
animations: [ animations: [
trigger('flyInOut', [ trigger('flyInOut', [
state('in', style({ transform: 'translateX(0)' })), state('in', style({ transform: 'translateX(0)' })),
transition('void => *', [ transition('void => *', [style({ transform: 'translateX(-100%)' }), animate(200)]),
style({ transform: 'translateX(-100%)' }), transition('* => void', [style({ transform: 'translateX(100%)' }), animate(200)]),
animate(200)
]), ]),
transition('* => void', [ ],
style({ transform: 'translateX(100%)' }),
animate(200)
])
])
]
}) })
export class JumpsComponent implements OnInit, OnDestroy { export class JumpsComponent implements OnInit, OnDestroy {
private _data: Subscription = new Subscription(); private _data: Subscription = new Subscription();
@@ -61,22 +66,22 @@ export class JumpsComponent implements OnInit, OnDestroy {
public seriesName: string[] = []; public seriesName: string[] = [];
public seriesRow: Array<Array<number>> = []; public seriesRow: Array<Array<number>> = [];
public seriesColor: { public seriesColor: {
backgroundColor: string[], backgroundColor: string[];
borderColor: string[] borderColor: string[];
} = { } = {
backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'), backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'),
borderColor: this._utilitiesService.getSeriesColors(1, 'all') borderColor: this._utilitiesService.getSeriesColors(1, 'all'),
}; };
public seriesTypesHeader: string[] = []; public seriesTypesHeader: string[] = [];
public seriesTypesName: string[] = []; public seriesTypesName: string[] = [];
public seriesTypesRow: Array<Array<number>> = []; public seriesTypesRow: Array<Array<number>> = [];
public seriesTypesRowCumulated: Array<Array<number>> = []; public seriesTypesRowCumulated: Array<Array<number>> = [];
public seriesTypesColor: { public seriesTypesColor: {
backgroundColor: string[], backgroundColor: string[];
borderColor: string[] borderColor: string[];
} = { } = {
backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'pastels'), backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'pastels'),
borderColor: this._utilitiesService.getSeriesColors(1, 'pastels') borderColor: this._utilitiesService.getSeriesColors(1, 'pastels'),
}; };
public seriesColorClass: string[] = this._utilitiesService.getChartColors(); public seriesColorClass: string[] = this._utilitiesService.getChartColors();
public seriesRowTotal: number[] = []; public seriesRowTotal: number[] = [];
@@ -89,11 +94,13 @@ export class JumpsComponent implements OnInit, OnDestroy {
constructor( constructor(
private route: ActivatedRoute, private route: ActivatedRoute,
private _utilitiesService: UtilitiesService, private _utilitiesService: UtilitiesService,
public menuItems: MenuItems public menuItems: MenuItems,
) { } ) {}
ngOnInit() { ngOnInit() {
const data$: Observable<{ pageData: JumpsPageData }> = this.route.data as Observable<{ pageData: JumpsPageData }>; const data$: Observable<{ pageData: JumpsPageData }> = this.route.data as Observable<{
pageData: JumpsPageData;
}>;
this._data = data$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: { pageData: JumpsPageData }) => { this._data = data$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: { pageData: JumpsPageData }) => {
const pageData: JumpsPageData = data.pageData; const pageData: JumpsPageData = data.pageData;
this.lastJump = pageData.lastjump; this.lastJump = pageData.lastjump;
@@ -104,7 +111,7 @@ export class JumpsComponent implements OnInit, OnDestroy {
const modules: Array<string> = [...verticals, ...others]; const modules: Array<string> = [...verticals, ...others];
const minoration = 2; // -2 pour ne pas compter la première année const minoration = 2; // -2 pour ne pas compter la première année
this.min = pageData.jumpsByYears[0].year; this.min = pageData.jumpsByYears[0].year;
this.max = pageData.jumpsByYears[(pageData.jumpsByYears.length-1)].year; this.max = pageData.jumpsByYears[pageData.jumpsByYears.length - 1].year;
this.seriesHeader = this._utilitiesService.getMonthsList(); this.seriesHeader = this._utilitiesService.getMonthsList();
const values: Array<number> = this.seriesHeader.map(() => 0); const values: Array<number> = this.seriesHeader.map(() => 0);
@@ -117,13 +124,13 @@ export class JumpsComponent implements OnInit, OnDestroy {
}); });
this._jumpsByDate = pageData.jumpsByDate.map((row: JumpByDate) => { this._jumpsByDate = pageData.jumpsByDate.map((row: JumpByDate) => {
this.seriesRow[(row.year-this.min)][(row.month-1)] = row.count; this.seriesRow[row.year - this.min][row.month - 1] = row.count;
this.seriesColTotal[(row.month-1)] += row.count; this.seriesColTotal[row.month - 1] += row.count;
if (row.year < currentYear) { if (row.year < currentYear) {
this.seriesColTotalClosed[(row.month-1)] += row.count; this.seriesColTotalClosed[row.month - 1] += row.count;
} }
if (row.year >= (currentYear-3) && row.year < currentYear) { if (row.year >= currentYear - 3 && row.year < currentYear) {
this.seriesColTotalLastYears[(row.month-1)] += row.count; this.seriesColTotalLastYears[row.month - 1] += row.count;
} }
return row; return row;
}); });
@@ -132,15 +139,18 @@ export class JumpsComponent implements OnInit, OnDestroy {
this.seriesRowTotal.push(total); this.seriesRowTotal.push(total);
}); });
this.seriesColTotalClosed.forEach((row: number) => { this.seriesColTotalClosed.forEach((row: number) => {
const value: number = (row/(this.seriesName.length-minoration)); const value: number = row / (this.seriesName.length - minoration);
this.seriesRowAvg.push(parseInt(value.toFixed(0))); this.seriesRowAvg.push(parseInt(value.toFixed(0)));
}); });
this.seriesColTotalLastYears.forEach((row: number) => { this.seriesColTotalLastYears.forEach((row: number) => {
const value: number = (row/3); // Les 3 dernières années const value: number = row / 3; // Les 3 dernières années
this.seriesRowAvgLastYears.push(parseInt(value.toFixed(0))); this.seriesRowAvgLastYears.push(parseInt(value.toFixed(0)));
}); });
this.grandAvg = this.seriesRowAvg.reduce((partialSum, accumulated) => partialSum + accumulated, 0); this.grandAvg = this.seriesRowAvg.reduce((partialSum, accumulated) => partialSum + accumulated, 0);
this.grandAvgLastYears = this.seriesRowAvgLastYears.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); this.grandTotal = this.seriesColTotal.reduce((partialSum, accumulated) => partialSum + accumulated, 0);
pageData.jumpsByCategory.forEach((row: JumpByCategorie) => { pageData.jumpsByCategory.forEach((row: JumpByCategorie) => {
@@ -150,8 +160,8 @@ export class JumpsComponent implements OnInit, OnDestroy {
}); });
//const focus: Array<string> = ['FF', 'Solo']; // ['FF'] //const focus: Array<string> = ['FF', 'Solo']; // ['FF']
let verticalCount:number = 0; let verticalCount: number = 0;
let otherCount:number = 0; let otherCount: number = 0;
pageData.jumpsByModule.forEach((row: JumpByModule) => { pageData.jumpsByModule.forEach((row: JumpByModule) => {
//if (focus.indexOf(row.categorie) !== -1 && modules.indexOf(row.module) !== -1) { //if (focus.indexOf(row.categorie) !== -1 && modules.indexOf(row.module) !== -1) {
if (modules.indexOf(row.module) !== -1) { if (modules.indexOf(row.module) !== -1) {
@@ -163,25 +173,25 @@ export class JumpsComponent implements OnInit, OnDestroy {
} }
}); });
if (verticalCount > 0) { if (verticalCount > 0) {
const row:JumpByModule = { const row: JumpByModule = {
categorie: 'FF', categorie: 'FF',
module: 'Vertical', module: 'Vertical',
count: verticalCount count: verticalCount,
} };
this._jumpsByModule.push(row); this._jumpsByModule.push(row);
} }
if (otherCount > 0) { if (otherCount > 0) {
const row:JumpByModule = { const row: JumpByModule = {
categorie: 'FF', categorie: 'FF',
module: 'Track/Trace', module: 'Track/Trace',
count: otherCount count: otherCount,
} };
this._jumpsByModule.push(row); this._jumpsByModule.push(row);
} }
for (let year = 0; year < pageData.jumpsByYears.length; year++) { for (let year = 0; year < pageData.jumpsByYears.length; year++) {
for (let index = 0; index < 12; index++) { for (let index = 0; index < 12; index++) {
const month: string = ((index+1) < 10) ? `0${(index+1)}` : `${(index+1)}`; const month: string = index + 1 < 10 ? `0${index + 1}` : `${index + 1}`;
this.seriesTypesHeader.push(`${month}-${pageData.jumpsByYears[year].year}`); this.seriesTypesHeader.push(`${month}-${pageData.jumpsByYears[year].year}`);
} }
} }
@@ -193,7 +203,7 @@ export class JumpsComponent implements OnInit, OnDestroy {
pageData.jumpsByDateByModule.forEach((row: JumpByDateByModule) => { pageData.jumpsByDateByModule.forEach((row: JumpByDateByModule) => {
const indexOf: number = this.seriesTypesName.indexOf(row.categorie); const indexOf: number = this.seriesTypesName.indexOf(row.categorie);
if (indexOf !== -1) { if (indexOf !== -1) {
this.seriesTypesRow[indexOf][(((row.year-this.min)*12)+row.month-1)] += row.count; this.seriesTypesRow[indexOf][(row.year - this.min) * 12 + row.month - 1] += row.count;
} }
}); });
this.seriesTypesRowCumulated = this.seriesTypesRow.map((row: Array<number>) => { this.seriesTypesRowCumulated = this.seriesTypesRow.map((row: Array<number>) => {
@@ -203,12 +213,21 @@ export class JumpsComponent implements OnInit, OnDestroy {
return accumulated; return accumulated;
}); });
}); });
this.seriesTypesHeader = this.seriesTypesHeader.slice((pageData.jumpsByDateByModule[0].month+1), -(pageData.jumpsByDateByModule[(pageData.jumpsByDateByModule.length-1)].month)); this.seriesTypesHeader = this.seriesTypesHeader.slice(
pageData.jumpsByDateByModule[0].month + 1,
-pageData.jumpsByDateByModule[pageData.jumpsByDateByModule.length - 1].month,
);
this.seriesTypesRow = this.seriesTypesRow.map((row: Array<number>) => { this.seriesTypesRow = this.seriesTypesRow.map((row: Array<number>) => {
return row.slice((pageData.jumpsByDateByModule[0].month+1), -(pageData.jumpsByDateByModule[(pageData.jumpsByDateByModule.length-1)].month)); return row.slice(
pageData.jumpsByDateByModule[0].month + 1,
-pageData.jumpsByDateByModule[pageData.jumpsByDateByModule.length - 1].month,
);
}); });
this.seriesTypesRowCumulated = this.seriesTypesRowCumulated.map((row: Array<number>) => { this.seriesTypesRowCumulated = this.seriesTypesRowCumulated.map((row: Array<number>) => {
return row.slice((pageData.jumpsByDateByModule[0].month+1), -(pageData.jumpsByDateByModule[(pageData.jumpsByDateByModule.length-1)].month)); return row.slice(
pageData.jumpsByDateByModule[0].month + 1,
-pageData.jumpsByDateByModule[pageData.jumpsByDateByModule.length - 1].month,
);
}); });
/* /*
console.log('this.min', this.min); console.log('this.min', this.min);
@@ -244,6 +263,6 @@ export class JumpsComponent implements OnInit, OnDestroy {
} }
public getModuleColor(index: number): number { public getModuleColor(index: number): number {
return (this._jumpsByCategorie.length + index); return this._jumpsByCategorie.length + index;
} }
} }
@@ -14,13 +14,22 @@ import { MatSelectModule } from '@angular/material/select';
import { Observable, Subscription } from 'rxjs'; import { Observable, Subscription } from 'rxjs';
import { map, startWith, take } from 'rxjs/operators'; import { map, startWith, take } from 'rxjs/operators';
import { AeronefByImat, CanopyModelBySize, DropZoneByOaci, Errors, Jump, JumpAddParams, JumpByModule, JumpFile, JumpFileType } from '@models'; import {
AeronefByImat,
CanopyModelBySize,
DropZoneByOaci,
Errors,
Jump,
JumpAddParams,
JumpByModule,
JumpFile,
JumpFileType,
} from '@models';
import { AeronefsService, CanopiesService, DropZonesService, JumpsService } from '@services'; import { AeronefsService, CanopiesService, DropZonesService, JumpsService } from '@services';
@Component({ @Component({
selector: 'app-jump-add-dialog', selector: 'app-jump-add-dialog',
templateUrl: 'jump-add.dialog.html', templateUrl: 'jump-add.dialog.html',
standalone: true,
imports: [ imports: [
AsyncPipe, AsyncPipe,
DatePipe, DatePipe,
@@ -35,8 +44,8 @@ import { AeronefsService, CanopiesService, DropZonesService, JumpsService } from
MatIconModule, MatIconModule,
MatInputModule, MatInputModule,
MatSelectModule, MatSelectModule,
MatOptionModule MatOptionModule,
] ],
}) })
export class JumpAddDialogComponent implements OnDestroy { export class JumpAddDialogComponent implements OnDestroy {
private _formChanges: Array<Subscription> = []; private _formChanges: Array<Subscription> = [];
@@ -46,7 +55,7 @@ export class JumpAddDialogComponent implements OnDestroy {
private _dropZoneByOaci: Subscription = new Subscription(); private _dropZoneByOaci: Subscription = new Subscription();
private _jumpByModule: Subscription = new Subscription(); private _jumpByModule: Subscription = new Subscription();
public errors!: Errors; public errors!: Errors;
public tagField = new FormControl<string>('', { nonNullable: true}); public tagField = new FormControl<string>('', { nonNullable: true });
public jumpForm: FormGroup; public jumpForm: FormGroup;
public jump: Jump; public jump: Jump;
public lastJump: Jump; public lastJump: Jump;
@@ -73,7 +82,7 @@ export class JumpAddDialogComponent implements OnDestroy {
dropzone: false, dropzone: false,
groupe: false, groupe: false,
programme: false, programme: false,
voile: false voile: false,
}; };
public inputOptions: { public inputOptions: {
aeronefs: Array<AeronefByImat>; aeronefs: Array<AeronefByImat>;
@@ -99,17 +108,17 @@ export class JumpAddDialogComponent implements OnDestroy {
private _canopiesService: CanopiesService, private _canopiesService: CanopiesService,
private _dropZonesService: DropZonesService, private _dropZonesService: DropZonesService,
private _jumpsService: JumpsService, private _jumpsService: JumpsService,
@Inject(MAT_DIALOG_DATA) public data: {jump: Jump, lastJump: Jump} @Inject(MAT_DIALOG_DATA) public data: { jump: Jump; lastJump: Jump },
) { ) {
this.inputOptions = { aeronefs: [], canopies: [], dropzones: [], categories: [] }; this.inputOptions = { aeronefs: [], canopies: [], dropzones: [], categories: [] };
//this.filteredOptions.aeronefs = this._aeronefsService.getAllByImat(); //this.filteredOptions.aeronefs = this._aeronefsService.getAllByImat();
this.jump = data.jump; this.jump = data.jump;
this.lastJump = data.lastJump; this.lastJump = data.lastJump;
this.nextJump = (this.lastJump.numero + 1); this.nextJump = this.lastJump.numero + 1;
this.params = { this.params = {
numeros: this.nextJump.toString(), numeros: this.nextJump.toString(),
date: '', date: '',
video: true video: true,
}; };
this.jump.numero = this.nextJump; this.jump.numero = this.nextJump;
const controlsConfig = { const controlsConfig = {
@@ -131,7 +140,7 @@ export class JumpAddDialogComponent implements OnDestroy {
accessoires: '', accessoires: '',
zone: '', zone: '',
dossier: '', dossier: '',
video: '' video: '',
}; };
this.jumpForm = this.fb.group(controlsConfig); this.jumpForm = this.fb.group(controlsConfig);
this.filename = this._computeFilename(); this.filename = this._computeFilename();
@@ -142,7 +151,7 @@ export class JumpAddDialogComponent implements OnDestroy {
}), }),
this.jumpForm.controls['numero'].valueChanges.subscribe(() => { this.jumpForm.controls['numero'].valueChanges.subscribe(() => {
this.filename = this._computeFilename(); this.filename = this._computeFilename();
}) }),
); );
/* /*
this.filteredAeronefOptions = this.jumpForm.controls['aeronef'].valueChanges.pipe( this.filteredAeronefOptions = this.jumpForm.controls['aeronef'].valueChanges.pipe(
@@ -164,60 +173,60 @@ export class JumpAddDialogComponent implements OnDestroy {
this.filteredOptions = { this.filteredOptions = {
aeronefs: this.jumpForm.controls['aeronef'].valueChanges.pipe( aeronefs: this.jumpForm.controls['aeronef'].valueChanges.pipe(
startWith(''), startWith(''),
map(value => { map((value) => {
const aeronef = typeof value === 'string' ? value : value?.aeronef; const aeronef = typeof value === 'string' ? value : value?.aeronef;
return aeronef ? this._filterImat(aeronef as string) : this.inputOptions.aeronefs.slice(); return aeronef ? this._filterImat(aeronef as string) : this.inputOptions.aeronefs.slice();
}), }),
), ),
imats: this.jumpForm.controls['imat'].valueChanges.pipe( imats: this.jumpForm.controls['imat'].valueChanges.pipe(
startWith(''), startWith(''),
map(value => { map((value) => {
const imat = typeof value === 'string' ? value : value?.imat; const imat = typeof value === 'string' ? value : value?.imat;
return imat ? this._filterImat(imat as string) : this.inputOptions.aeronefs.slice(); return imat ? this._filterImat(imat as string) : this.inputOptions.aeronefs.slice();
}), }),
), ),
canopies: this.jumpForm.controls['voile'].valueChanges.pipe( canopies: this.jumpForm.controls['voile'].valueChanges.pipe(
startWith(''), startWith(''),
map(value => { map((value) => {
const voile = typeof value === 'string' ? value : value?.voile; const voile = typeof value === 'string' ? value : value?.voile;
return voile ? this._filterTaille(voile as string) : this.inputOptions.canopies.slice(); return voile ? this._filterTaille(voile as string) : this.inputOptions.canopies.slice();
}), }),
), ),
tailles: this.jumpForm.controls['taille'].valueChanges.pipe( tailles: this.jumpForm.controls['taille'].valueChanges.pipe(
startWith(''), startWith(''),
map(value => { map((value) => {
const taille = typeof value === 'string' ? value : value?.taille.toString(); const taille = typeof value === 'string' ? value : value?.taille.toString();
return taille ? this._filterTaille(taille as string) : this.inputOptions.canopies.slice(); return taille ? this._filterTaille(taille as string) : this.inputOptions.canopies.slice();
}), }),
), ),
dropzones: this.jumpForm.controls['lieu'].valueChanges.pipe( dropzones: this.jumpForm.controls['lieu'].valueChanges.pipe(
startWith(''), startWith(''),
map(value => { map((value) => {
const lieu = typeof value === 'string' ? value : value?.lieu; const lieu = typeof value === 'string' ? value : value?.lieu;
return lieu ? this._filterOaci(lieu as string) : this.inputOptions.dropzones.slice(); return lieu ? this._filterOaci(lieu as string) : this.inputOptions.dropzones.slice();
}), }),
), ),
oaci: this.jumpForm.controls['oaci'].valueChanges.pipe( oaci: this.jumpForm.controls['oaci'].valueChanges.pipe(
startWith(''), startWith(''),
map(value => { map((value) => {
const oaci = typeof value === 'string' ? value : value?.oaci; const oaci = typeof value === 'string' ? value : value?.oaci;
return oaci ? this._filterOaci(oaci as string) : this.inputOptions.dropzones.slice(); return oaci ? this._filterOaci(oaci as string) : this.inputOptions.dropzones.slice();
}), }),
), ),
categories: this.jumpForm.controls['categorie'].valueChanges.pipe( categories: this.jumpForm.controls['categorie'].valueChanges.pipe(
startWith(''), startWith(''),
map(value => { map((value) => {
const category = typeof value === 'string' ? value : value?.categorie; const category = typeof value === 'string' ? value : value?.categorie;
return category ? this._filterModule(category as string) : this.inputOptions.categories.slice(); return category ? this._filterModule(category as string) : this.inputOptions.categories.slice();
}), }),
), ),
modules: this.jumpForm.controls['module'].valueChanges.pipe( modules: this.jumpForm.controls['module'].valueChanges.pipe(
startWith(''), startWith(''),
map(value => { map((value) => {
const module = typeof value === 'string' ? value : value?.module; const module = typeof value === 'string' ? value : value?.module;
return module ? this._filterModule(module as string) : this.inputOptions.categories.slice(); return module ? this._filterModule(module as string) : this.inputOptions.categories.slice();
}), }),
) ),
}; };
this._loadAeronefByImat(); this._loadAeronefByImat();
this._loadCanopyModelBySize(); this._loadCanopyModelBySize();
@@ -244,7 +253,7 @@ export class JumpAddDialogComponent implements OnDestroy {
const timestamp: number = Date.parse(this.jumpForm.controls['date'].value); const timestamp: number = Date.parse(this.jumpForm.controls['date'].value);
if (isNaN(timestamp) == false) { if (isNaN(timestamp) == false) {
const date: Date = new Date(timestamp); const date: Date = new Date(timestamp);
file += `${(date.getFullYear() + '').padStart(2, '0')}-${((date.getMonth() + 1) + '').padStart(2, '0')}-${(date.getDate() + '').padStart(2, '0')}_`; file += `${(date.getFullYear() + '').padStart(2, '0')}-${(date.getMonth() + 1 + '').padStart(2, '0')}-${(date.getDate() + '').padStart(2, '0')}_`;
} }
if (numero !== undefined) { if (numero !== undefined) {
numero = (numero + '').padStart(5, '0'); numero = (numero + '').padStart(5, '0');
@@ -261,7 +270,10 @@ export class JumpAddDialogComponent implements OnDestroy {
let path: string = '/Volumes/Storage/Skydive/Videos/'; let path: string = '/Volumes/Storage/Skydive/Videos/';
if (this.jumpForm.controls['module'].value != '') { if (this.jumpForm.controls['module'].value != '') {
//path += `${this.jumpForm.controls['module'].value}/`; //path += `${this.jumpForm.controls['module'].value}/`;
path += typeof this.jumpForm.controls['module'].value === 'string' ? `${this.jumpForm.controls['module'].value}/` : `${this.jumpForm.controls['module'].value?.module}/`; path +=
typeof this.jumpForm.controls['module'].value === 'string'
? `${this.jumpForm.controls['module'].value}/`
: `${this.jumpForm.controls['module'].value?.module}/`;
} }
this.jumpForm.controls['dossier'].setValue(path); this.jumpForm.controls['dossier'].setValue(path);
@@ -270,35 +282,48 @@ export class JumpAddDialogComponent implements OnDestroy {
private _isLastForAllSections() { private _isLastForAllSections() {
return ( return (
this.useLast.aeronef this.useLast.aeronef &&
&& this.useLast.altitude this.useLast.altitude &&
&& this.useLast.discipline this.useLast.discipline &&
&& this.useLast.divers this.useLast.divers &&
&& this.useLast.dropzone this.useLast.dropzone &&
&& this.useLast.groupe this.useLast.groupe &&
&& this.useLast.programme this.useLast.programme &&
&& this.useLast.voile this.useLast.voile
); );
} }
private _filterImat(imat: string): Array<AeronefByImat> { private _filterImat(imat: string): Array<AeronefByImat> {
const filterValue = imat.toLowerCase(); const filterValue = imat.toLowerCase();
return this.inputOptions.aeronefs.filter(option => (option.aeronef.toLowerCase().includes(filterValue) || option.imat.toLowerCase().includes(filterValue))); return this.inputOptions.aeronefs.filter(
(option) =>
option.aeronef.toLowerCase().includes(filterValue) || option.imat.toLowerCase().includes(filterValue),
);
} }
private _filterModule(module: string): Array<JumpByModule> { private _filterModule(module: string): Array<JumpByModule> {
const filterValue = module.toLowerCase(); const filterValue = module.toLowerCase();
return this.inputOptions.categories.filter(option => (option.categorie.toLowerCase().includes(filterValue) || option.module.toLowerCase().includes(filterValue))); return this.inputOptions.categories.filter(
(option) =>
option.categorie.toLowerCase().includes(filterValue) ||
option.module.toLowerCase().includes(filterValue),
);
} }
private _filterOaci(oaci: string): Array<DropZoneByOaci> { private _filterOaci(oaci: string): Array<DropZoneByOaci> {
const filterValue = oaci.toLowerCase(); const filterValue = oaci.toLowerCase();
return this.inputOptions.dropzones.filter(option => (option.lieu.toLowerCase().includes(filterValue) || option.oaci.toLowerCase().includes(filterValue))); return this.inputOptions.dropzones.filter(
(option) =>
option.lieu.toLowerCase().includes(filterValue) || option.oaci.toLowerCase().includes(filterValue),
);
} }
private _filterTaille(taille: string): Array<CanopyModelBySize> { private _filterTaille(taille: string): Array<CanopyModelBySize> {
const filterValue = taille.toLowerCase(); const filterValue = taille.toLowerCase();
return this.inputOptions.canopies.filter(option => (option.voile.toLowerCase().includes(filterValue) || option.taille.toString().includes(filterValue))); return this.inputOptions.canopies.filter(
(option) =>
option.voile.toLowerCase().includes(filterValue) || option.taille.toString().includes(filterValue),
);
} }
private _loadAeronefByImat(): void { private _loadAeronefByImat(): void {
@@ -376,7 +401,7 @@ export class JumpAddDialogComponent implements OnDestroy {
if (tag != null && tag.trim() !== '') { if (tag != null && tag.trim() !== '') {
if (tag.includes(',') === true) { if (tag.includes(',') === true) {
const tags = tag.split(','); const tags = tag.split(',');
tags.forEach(sautant => { tags.forEach((sautant) => {
if (this.jump.sautants.indexOf(sautant.trim()) < 0) { if (this.jump.sautants.indexOf(sautant.trim()) < 0) {
this.jump.sautants.push(sautant.trim()); this.jump.sautants.push(sautant.trim());
} }
@@ -386,7 +411,7 @@ export class JumpAddDialogComponent implements OnDestroy {
} }
} }
this.tagField.reset(''); this.tagField.reset('');
const participants = (this.jump.sautants.length + 1); const participants = this.jump.sautants.length + 1;
this.jumpForm.controls['participants'].setValue(participants); this.jumpForm.controls['participants'].setValue(participants);
} }
@@ -562,7 +587,7 @@ export class JumpAddDialogComponent implements OnDestroy {
this.useLast.groupe = false; this.useLast.groupe = false;
this.useLast.all = this._isLastForAllSections(); this.useLast.all = this._isLastForAllSections();
this.jump.sautants = this.jump.sautants.filter((sautant) => sautant !== index); this.jump.sautants = this.jump.sautants.filter((sautant) => sautant !== index);
const participants = (this.jump.sautants.length + 1); const participants = this.jump.sautants.length + 1;
this.jumpForm.controls['participants'].setValue(participants); this.jumpForm.controls['participants'].setValue(participants);
} }
@@ -766,17 +791,17 @@ export class JumpAddDialogComponent implements OnDestroy {
const elements: string[] = this.jumpForm.controls['numero'].value.split(';'); const elements: string[] = this.jumpForm.controls['numero'].value.split(';');
elements.forEach((element: string) => { elements.forEach((element: string) => {
if (element == '') { if (element == '') {
jumpNum ++; jumpNum++;
element = jumpNum.toString(); element = jumpNum.toString();
} }
const values: string[] = element.split('-'); const values: string[] = element.split('-');
if (values.length == 2) { if (values.length == 2) {
const start: number = parseInt(values[0]); const start: number = parseInt(values[0]);
const stop: number = parseInt(values[1]); const stop: number = parseInt(values[1]);
const diff: number = (stop - start); const diff: number = stop - start;
/* Ajout de saut par plage */ /* Ajout de saut par plage */
for (let index = 0; index <= diff; index++) { for (let index = 0; index <= diff; index++) {
jumpNum = (start + index); jumpNum = start + index;
numeros.push(jumpNum); numeros.push(jumpNum);
} }
} else { } else {
@@ -785,7 +810,7 @@ export class JumpAddDialogComponent implements OnDestroy {
/* Ajout de sauts par quantité */ /* Ajout de sauts par quantité */
//const start: number = jumpNum; //const start: number = jumpNum;
for (let index = 1; index <= parseInt(quantity[1]); index++) { for (let index = 1; index <= parseInt(quantity[1]); index++) {
jumpNum ++; jumpNum++;
numeros.push(jumpNum); numeros.push(jumpNum);
} }
} else { } else {
@@ -802,14 +827,38 @@ export class JumpAddDialogComponent implements OnDestroy {
/* Valeurs communes aux 1 à n saut(s) à ajouter */ /* Valeurs communes aux 1 à n saut(s) à ajouter */
jump.date = date.toISOString(); jump.date = date.toISOString();
jump.lieu = typeof this.jumpForm.controls['lieu'].value === 'string' ? this.jumpForm.controls['lieu'].value : this.jumpForm.controls['lieu'].value.lieu; jump.lieu =
jump.oaci = typeof this.jumpForm.controls['oaci'].value === 'string' ? this.jumpForm.controls['oaci'].value : this.jumpForm.controls['oaci'].value.oaci; typeof this.jumpForm.controls['lieu'].value === 'string'
jump.aeronef = typeof this.jumpForm.controls['aeronef'].value === 'string' ? this.jumpForm.controls['aeronef'].value : this.jumpForm.controls['aeronef'].value.aeronef; ? this.jumpForm.controls['lieu'].value
jump.imat = typeof this.jumpForm.controls['imat'].value === 'string' ? this.jumpForm.controls['imat'].value : this.jumpForm.controls['imat'].value.imat; : this.jumpForm.controls['lieu'].value.lieu;
jump.voile = typeof this.jumpForm.controls['voile'].value === 'string' ? this.jumpForm.controls['voile'].value : this.jumpForm.controls['voile'].value.voile; jump.oaci =
jump.taille = typeof this.jumpForm.controls['taille'].value === 'string' ? this.jumpForm.controls['taille'].value : this.jumpForm.controls['taille'].value.taille; typeof this.jumpForm.controls['oaci'].value === 'string'
jump.categorie = typeof this.jumpForm.controls['categorie'].value === 'string' ? this.jumpForm.controls['categorie'].value : this.jumpForm.controls['categorie'].value.categorie; ? this.jumpForm.controls['oaci'].value
jump.module = typeof this.jumpForm.controls['module'].value === 'string' ? this.jumpForm.controls['module'].value : this.jumpForm.controls['module'].value.module; : this.jumpForm.controls['oaci'].value.oaci;
jump.aeronef =
typeof this.jumpForm.controls['aeronef'].value === 'string'
? this.jumpForm.controls['aeronef'].value
: this.jumpForm.controls['aeronef'].value.aeronef;
jump.imat =
typeof this.jumpForm.controls['imat'].value === 'string'
? this.jumpForm.controls['imat'].value
: this.jumpForm.controls['imat'].value.imat;
jump.voile =
typeof this.jumpForm.controls['voile'].value === 'string'
? this.jumpForm.controls['voile'].value
: this.jumpForm.controls['voile'].value.voile;
jump.taille =
typeof this.jumpForm.controls['taille'].value === 'string'
? this.jumpForm.controls['taille'].value
: this.jumpForm.controls['taille'].value.taille;
jump.categorie =
typeof this.jumpForm.controls['categorie'].value === 'string'
? this.jumpForm.controls['categorie'].value
: this.jumpForm.controls['categorie'].value.categorie;
jump.module =
typeof this.jumpForm.controls['module'].value === 'string'
? this.jumpForm.controls['module'].value
: this.jumpForm.controls['module'].value.module;
jump.hauteur = this.jumpForm.controls['hauteur'].value; jump.hauteur = this.jumpForm.controls['hauteur'].value;
jump.deploiement = this.jumpForm.controls['deploiement'].value; jump.deploiement = this.jumpForm.controls['deploiement'].value;
jump.participants = this.jumpForm.controls['participants'].value; jump.participants = this.jumpForm.controls['participants'].value;
@@ -832,10 +881,11 @@ export class JumpAddDialogComponent implements OnDestroy {
const file: JumpFile = { const file: JumpFile = {
name: item.video, name: item.video,
path: item.dossier, path: item.dossier,
type: JumpFileType.VIDEO type: JumpFileType.VIDEO,
} as JumpFile; } as JumpFile;
this._subscriptions.push( this._subscriptions.push(
this._jumpsService.saveFile(item.slug, file) this._jumpsService
.saveFile(item.slug, file)
.pipe(take(1)) .pipe(take(1))
.subscribe({ .subscribe({
next: (file) => { next: (file) => {
@@ -844,8 +894,8 @@ export class JumpAddDialogComponent implements OnDestroy {
}, },
error: (err) => { error: (err) => {
this.errors = err; this.errors = err;
} },
}) }),
); );
} }
jumps.push(item); jumps.push(item);
@@ -9,17 +9,13 @@ import { Jump } from '@models';
@Component({ @Component({
selector: 'app-jump-delete-dialog', selector: 'app-jump-delete-dialog',
templateUrl: 'jump-delete.dialog.html', templateUrl: 'jump-delete.dialog.html',
standalone: true, imports: [DatePipe, MatDialogModule, MatButtonModule, MatIconModule],
imports: [
DatePipe,
MatDialogModule, MatButtonModule, MatIconModule
]
}) })
export class JumpDeleteDialogComponent { export class JumpDeleteDialogComponent {
constructor( constructor(
public dialogRef: MatDialogRef<JumpDeleteDialogComponent>, public dialogRef: MatDialogRef<JumpDeleteDialogComponent>,
@Inject(MAT_DIALOG_DATA) public jump: Jump @Inject(MAT_DIALOG_DATA) public jump: Jump,
) { } ) {}
closeDialog(): void { closeDialog(): void {
this.dialogRef.close(); this.dialogRef.close();
@@ -20,7 +20,6 @@ import { AeronefsService, CanopiesService, DropZonesService, JumpsService } from
@Component({ @Component({
selector: 'app-jump-edit-dialog', selector: 'app-jump-edit-dialog',
templateUrl: 'jump-edit.dialog.html', templateUrl: 'jump-edit.dialog.html',
standalone: true,
imports: [ imports: [
AsyncPipe, AsyncPipe,
DatePipe, DatePipe,
@@ -35,15 +34,15 @@ import { AeronefsService, CanopiesService, DropZonesService, JumpsService } from
MatIconModule, MatIconModule,
MatInputModule, MatInputModule,
MatSelectModule, MatSelectModule,
MatOptionModule MatOptionModule,
] ],
}) })
export class JumpEditDialogComponent implements OnDestroy { export class JumpEditDialogComponent implements OnDestroy {
private _aeronefByImat: Subscription = new Subscription(); private _aeronefByImat: Subscription = new Subscription();
private _canopyModelBySize: Subscription = new Subscription(); private _canopyModelBySize: Subscription = new Subscription();
private _dropZoneByOaci: Subscription = new Subscription(); private _dropZoneByOaci: Subscription = new Subscription();
private _jumpByModule: Subscription = new Subscription(); private _jumpByModule: Subscription = new Subscription();
public tagField = new FormControl<string>('', { nonNullable: true}); public tagField = new FormControl<string>('', { nonNullable: true });
public jumpForm: FormGroup; public jumpForm: FormGroup;
public inputOptions: { public inputOptions: {
aeronefs: Array<AeronefByImat>; aeronefs: Array<AeronefByImat>;
@@ -69,7 +68,7 @@ export class JumpEditDialogComponent implements OnDestroy {
private _canopiesService: CanopiesService, private _canopiesService: CanopiesService,
private _dropZonesService: DropZonesService, private _dropZonesService: DropZonesService,
private _jumpsService: JumpsService, private _jumpsService: JumpsService,
@Inject(MAT_DIALOG_DATA) public jump: Jump @Inject(MAT_DIALOG_DATA) public jump: Jump,
) { ) {
this.inputOptions = { aeronefs: [], canopies: [], dropzones: [], categories: [] }; this.inputOptions = { aeronefs: [], canopies: [], dropzones: [], categories: [] };
const controlsConfig = { const controlsConfig = {
@@ -91,67 +90,67 @@ export class JumpEditDialogComponent implements OnDestroy {
accessoires: this.jump.accessoires, accessoires: this.jump.accessoires,
zone: this.jump.zone, zone: this.jump.zone,
dossier: this.jump.dossier, dossier: this.jump.dossier,
video: this.jump.video video: this.jump.video,
}; };
this.jumpForm = this.fb.group(controlsConfig); this.jumpForm = this.fb.group(controlsConfig);
this.filteredOptions = { this.filteredOptions = {
aeronefs: this.jumpForm.controls['aeronef'].valueChanges.pipe( aeronefs: this.jumpForm.controls['aeronef'].valueChanges.pipe(
startWith(''), startWith(''),
map(value => { map((value) => {
const aeronef = typeof value === 'string' ? value : value?.aeronef; const aeronef = typeof value === 'string' ? value : value?.aeronef;
return aeronef ? this._filterImat(aeronef as string) : this.inputOptions.aeronefs.slice(); return aeronef ? this._filterImat(aeronef as string) : this.inputOptions.aeronefs.slice();
}), }),
), ),
imats: this.jumpForm.controls['imat'].valueChanges.pipe( imats: this.jumpForm.controls['imat'].valueChanges.pipe(
startWith(''), startWith(''),
map(value => { map((value) => {
const imat = typeof value === 'string' ? value : value?.imat; const imat = typeof value === 'string' ? value : value?.imat;
return imat ? this._filterImat(imat as string) : this.inputOptions.aeronefs.slice(); return imat ? this._filterImat(imat as string) : this.inputOptions.aeronefs.slice();
}), }),
), ),
canopies: this.jumpForm.controls['voile'].valueChanges.pipe( canopies: this.jumpForm.controls['voile'].valueChanges.pipe(
startWith(''), startWith(''),
map(value => { map((value) => {
const voile = typeof value === 'string' ? value : value?.voile; const voile = typeof value === 'string' ? value : value?.voile;
return voile ? this._filterTaille(voile as string) : this.inputOptions.canopies.slice(); return voile ? this._filterTaille(voile as string) : this.inputOptions.canopies.slice();
}), }),
), ),
tailles: this.jumpForm.controls['taille'].valueChanges.pipe( tailles: this.jumpForm.controls['taille'].valueChanges.pipe(
startWith(''), startWith(''),
map(value => { map((value) => {
const taille = typeof value === 'string' ? value : value?.taille.toString(); const taille = typeof value === 'string' ? value : value?.taille.toString();
return taille ? this._filterTaille(taille as string) : this.inputOptions.canopies.slice(); return taille ? this._filterTaille(taille as string) : this.inputOptions.canopies.slice();
}), }),
), ),
dropzones: this.jumpForm.controls['lieu'].valueChanges.pipe( dropzones: this.jumpForm.controls['lieu'].valueChanges.pipe(
startWith(''), startWith(''),
map(value => { map((value) => {
const lieu = typeof value === 'string' ? value : value?.lieu; const lieu = typeof value === 'string' ? value : value?.lieu;
return lieu ? this._filterOaci(lieu as string) : this.inputOptions.dropzones.slice(); return lieu ? this._filterOaci(lieu as string) : this.inputOptions.dropzones.slice();
}), }),
), ),
oaci: this.jumpForm.controls['oaci'].valueChanges.pipe( oaci: this.jumpForm.controls['oaci'].valueChanges.pipe(
startWith(''), startWith(''),
map(value => { map((value) => {
const oaci = typeof value === 'string' ? value : value?.oaci; const oaci = typeof value === 'string' ? value : value?.oaci;
return oaci ? this._filterOaci(oaci as string) : this.inputOptions.dropzones.slice(); return oaci ? this._filterOaci(oaci as string) : this.inputOptions.dropzones.slice();
}), }),
), ),
categories: this.jumpForm.controls['categorie'].valueChanges.pipe( categories: this.jumpForm.controls['categorie'].valueChanges.pipe(
startWith(''), startWith(''),
map(value => { map((value) => {
const category = typeof value === 'string' ? value : value?.categorie; const category = typeof value === 'string' ? value : value?.categorie;
return category ? this._filterModule(category as string) : this.inputOptions.categories.slice(); return category ? this._filterModule(category as string) : this.inputOptions.categories.slice();
}), }),
), ),
modules: this.jumpForm.controls['module'].valueChanges.pipe( modules: this.jumpForm.controls['module'].valueChanges.pipe(
startWith(''), startWith(''),
map(value => { map((value) => {
const module = typeof value === 'string' ? value : value?.module; const module = typeof value === 'string' ? value : value?.module;
return module ? this._filterModule(module as string) : this.inputOptions.categories.slice(); return module ? this._filterModule(module as string) : this.inputOptions.categories.slice();
}), }),
) ),
}; };
this._loadAeronefByImat(); this._loadAeronefByImat();
this._loadCanopyModelBySize(); this._loadCanopyModelBySize();
@@ -168,22 +167,35 @@ export class JumpEditDialogComponent implements OnDestroy {
private _filterImat(imat: string): Array<AeronefByImat> { private _filterImat(imat: string): Array<AeronefByImat> {
const filterValue = imat.toLowerCase(); const filterValue = imat.toLowerCase();
return this.inputOptions.aeronefs.filter(option => (option.aeronef.toLowerCase().includes(filterValue) || option.imat.toLowerCase().includes(filterValue))); return this.inputOptions.aeronefs.filter(
(option) =>
option.aeronef.toLowerCase().includes(filterValue) || option.imat.toLowerCase().includes(filterValue),
);
} }
private _filterModule(module: string): Array<JumpByModule> { private _filterModule(module: string): Array<JumpByModule> {
const filterValue = module.toLowerCase(); const filterValue = module.toLowerCase();
return this.inputOptions.categories.filter(option => (option.categorie.toLowerCase().includes(filterValue) || option.module.toLowerCase().includes(filterValue))); return this.inputOptions.categories.filter(
(option) =>
option.categorie.toLowerCase().includes(filterValue) ||
option.module.toLowerCase().includes(filterValue),
);
} }
private _filterOaci(oaci: string): Array<DropZoneByOaci> { private _filterOaci(oaci: string): Array<DropZoneByOaci> {
const filterValue = oaci.toLowerCase(); const filterValue = oaci.toLowerCase();
return this.inputOptions.dropzones.filter(option => (option.lieu.toLowerCase().includes(filterValue) || option.oaci.toLowerCase().includes(filterValue))); return this.inputOptions.dropzones.filter(
(option) =>
option.lieu.toLowerCase().includes(filterValue) || option.oaci.toLowerCase().includes(filterValue),
);
} }
private _filterTaille(taille: string): Array<CanopyModelBySize> { private _filterTaille(taille: string): Array<CanopyModelBySize> {
const filterValue = taille.toLowerCase(); const filterValue = taille.toLowerCase();
return this.inputOptions.canopies.filter(option => (option.voile.toLowerCase().includes(filterValue) || option.taille.toString().includes(filterValue))); return this.inputOptions.canopies.filter(
(option) =>
option.voile.toLowerCase().includes(filterValue) || option.taille.toString().includes(filterValue),
);
} }
private _loadAeronefByImat(): void { private _loadAeronefByImat(): void {
@@ -219,7 +231,7 @@ export class JumpEditDialogComponent implements OnDestroy {
if (tag != null && tag.trim() !== '' && this.jump.sautants.indexOf(tag) < 0) { if (tag != null && tag.trim() !== '' && this.jump.sautants.indexOf(tag) < 0) {
this.jump.sautants.push(tag); this.jump.sautants.push(tag);
} }
const participants = (this.jump.sautants.length + 1); const participants = this.jump.sautants.length + 1;
this.jumpForm.controls['participants'].setValue(participants); this.jumpForm.controls['participants'].setValue(participants);
this.tagField.reset(''); this.tagField.reset('');
} }
@@ -382,21 +394,45 @@ export class JumpEditDialogComponent implements OnDestroy {
removeSautant(index: string): void { removeSautant(index: string): void {
this.jump.sautants = this.jump.sautants.filter((sautant) => sautant !== index); this.jump.sautants = this.jump.sautants.filter((sautant) => sautant !== index);
const participants = (this.jump.sautants.length + 1); const participants = this.jump.sautants.length + 1;
this.jumpForm.controls['participants'].setValue(participants); this.jumpForm.controls['participants'].setValue(participants);
} }
submitForm(): void { submitForm(): void {
// update the model // update the model
this.updateJump(this.jumpForm.value); this.updateJump(this.jumpForm.value);
this.jump.lieu = typeof this.jumpForm.controls['lieu'].value === 'string' ? this.jumpForm.controls['lieu'].value : this.jumpForm.controls['lieu'].value.lieu; this.jump.lieu =
this.jump.oaci = typeof this.jumpForm.controls['oaci'].value === 'string' ? this.jumpForm.controls['oaci'].value : this.jumpForm.controls['oaci'].value.oaci; typeof this.jumpForm.controls['lieu'].value === 'string'
this.jump.aeronef = typeof this.jumpForm.controls['aeronef'].value === 'string' ? this.jumpForm.controls['aeronef'].value : this.jumpForm.controls['aeronef'].value.aeronef; ? this.jumpForm.controls['lieu'].value
this.jump.imat = typeof this.jumpForm.controls['imat'].value === 'string' ? this.jumpForm.controls['imat'].value : this.jumpForm.controls['imat'].value.imat; : this.jumpForm.controls['lieu'].value.lieu;
this.jump.voile = typeof this.jumpForm.controls['voile'].value === 'string' ? this.jumpForm.controls['voile'].value : this.jumpForm.controls['voile'].value.voile; this.jump.oaci =
this.jump.taille = typeof this.jumpForm.controls['taille'].value === 'string' ? this.jumpForm.controls['taille'].value : this.jumpForm.controls['taille'].value.taille; typeof this.jumpForm.controls['oaci'].value === 'string'
this.jump.categorie = typeof this.jumpForm.controls['categorie'].value === 'string' ? this.jumpForm.controls['categorie'].value : this.jumpForm.controls['categorie'].value.categorie; ? this.jumpForm.controls['oaci'].value
this.jump.module = typeof this.jumpForm.controls['module'].value === 'string' ? this.jumpForm.controls['module'].value : this.jumpForm.controls['module'].value.module; : this.jumpForm.controls['oaci'].value.oaci;
this.jump.aeronef =
typeof this.jumpForm.controls['aeronef'].value === 'string'
? this.jumpForm.controls['aeronef'].value
: this.jumpForm.controls['aeronef'].value.aeronef;
this.jump.imat =
typeof this.jumpForm.controls['imat'].value === 'string'
? this.jumpForm.controls['imat'].value
: this.jumpForm.controls['imat'].value.imat;
this.jump.voile =
typeof this.jumpForm.controls['voile'].value === 'string'
? this.jumpForm.controls['voile'].value
: this.jumpForm.controls['voile'].value.voile;
this.jump.taille =
typeof this.jumpForm.controls['taille'].value === 'string'
? this.jumpForm.controls['taille'].value
: this.jumpForm.controls['taille'].value.taille;
this.jump.categorie =
typeof this.jumpForm.controls['categorie'].value === 'string'
? this.jumpForm.controls['categorie'].value
: this.jumpForm.controls['categorie'].value.categorie;
this.jump.module =
typeof this.jumpForm.controls['module'].value === 'string'
? this.jumpForm.controls['module'].value
: this.jumpForm.controls['module'].value.module;
// close the dialog with result // close the dialog with result
this.dialogRef.close(this.jump); this.dialogRef.close(this.jump);
} }
@@ -10,19 +10,13 @@ import { Jump } from '@models';
@Component({ @Component({
selector: 'app-jump-view-dialog', selector: 'app-jump-view-dialog',
templateUrl: 'jump-view.dialog.html', templateUrl: 'jump-view.dialog.html',
standalone: true, imports: [DatePipe, DecimalPipe, MatButtonModule, MatDialogModule, MatDividerModule, MatIconModule],
imports: [
DatePipe, DecimalPipe,
MatButtonModule, MatDialogModule,
MatDividerModule, MatIconModule
]
}) })
export class JumpViewDialogComponent { export class JumpViewDialogComponent {
constructor( constructor(
public dialogRef: MatDialogRef<JumpViewDialogComponent>, public dialogRef: MatDialogRef<JumpViewDialogComponent>,
@Inject(MAT_DIALOG_DATA) public jump: Jump @Inject(MAT_DIALOG_DATA) public jump: Jump,
) { } ) {}
closeDialog(): void { closeDialog(): void {
// close the dialog without result // close the dialog without result
+95 -66
View File
@@ -12,7 +12,13 @@ import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input'; import { MatInputModule } from '@angular/material/input';
import { MatMenuModule } from '@angular/material/menu'; import { MatMenuModule } from '@angular/material/menu';
import { MatSliderModule } from '@angular/material/slider'; import { MatSliderModule } from '@angular/material/slider';
import { MatSnackBar, MatSnackBarConfig, MatSnackBarHorizontalPosition, MatSnackBarModule, MatSnackBarVerticalPosition } from '@angular/material/snack-bar'; import {
MatSnackBar,
MatSnackBarConfig,
MatSnackBarHorizontalPosition,
MatSnackBarModule,
MatSnackBarVerticalPosition,
} from '@angular/material/snack-bar';
import { Observable, Subscription } from 'rxjs'; import { Observable, Subscription } from 'rxjs';
import { take } from 'rxjs/operators'; import { take } from 'rxjs/operators';
@@ -24,13 +30,21 @@ import data from 'src/jumps.json';
//import data from 'src/jumps_02.json'; //import data from 'src/jumps_02.json';
@Component({ @Component({
standalone: true,
imports: [ imports: [
CommonModule, RouterModule, FormsModule, CommonModule,
MatButtonModule, MatCardModule, MatDividerModule, MatExpansionModule, RouterModule,
MatIconModule, MatInputModule, MatMenuModule, MatDialogModule, FormsModule,
MatSliderModule, MatSnackBarModule, MatButtonModule,
JumpTableComponent MatCardModule,
MatDividerModule,
MatExpansionModule,
MatIconModule,
MatInputModule,
MatMenuModule,
MatDialogModule,
MatSliderModule,
MatSnackBarModule,
JumpTableComponent,
], ],
selector: 'app-logbook', selector: 'app-logbook',
templateUrl: './logbook.component.html', templateUrl: './logbook.component.html',
@@ -38,16 +52,10 @@ import data from 'src/jumps.json';
animations: [ animations: [
trigger('flyInOut', [ trigger('flyInOut', [
state('in', style({ transform: 'translateY(0)' })), state('in', style({ transform: 'translateY(0)' })),
transition('void => *', [ transition('void => *', [style({ transform: 'translateY(-100%)' }), animate(200)]),
style({ transform: 'translateY(-100%)' }), transition('* => void', [style({ transform: 'translateY(100%)' }), animate(200)]),
animate(200)
]), ]),
transition('* => void', [ ],
style({ transform: 'translateY(100%)' }),
animate(200)
])
])
]
}) })
export class LogbookComponent implements OnInit, OnDestroy, AfterContentChecked { export class LogbookComponent implements OnInit, OnDestroy, AfterContentChecked {
private _currentUser: Subscription = new Subscription(); private _currentUser: Subscription = new Subscription();
@@ -77,11 +85,11 @@ export class LogbookComponent implements OnInit, OnDestroy, AfterContentChecked
hauteur: Range; hauteur: Range;
year: Range; year: Range;
} = { } = {
numero: {start: 1, end: 100000}, numero: { start: 1, end: 100000 },
taille: {start: 1, end: 400}, taille: { start: 1, end: 400 },
participants: {start: 1, end: 200}, participants: { start: 1, end: 200 },
hauteur: {start: 0, end: 10000}, hauteur: { start: 0, end: 10000 },
year: {start: 1970, end: 2020} year: { start: 1970, end: 2020 },
}; };
constructor( constructor(
@@ -92,13 +100,16 @@ export class LogbookComponent implements OnInit, OnDestroy, AfterContentChecked
private _jumpsService: JumpsService, private _jumpsService: JumpsService,
private _jumpTableService: JumpTableService, private _jumpTableService: JumpTableService,
private _userService: UserService, private _userService: UserService,
public menuItems: MenuItems public menuItems: MenuItems,
) { } ) {}
ngOnInit() { ngOnInit() {
//this.importJumps(); //this.importJumps();
const data$: Observable<{isAuthenticated: boolean, lastjump: Jump}> = this.route.data as Observable<{isAuthenticated: boolean, lastjump: Jump}>; const data$: Observable<{ isAuthenticated: boolean; lastjump: Jump }> = this.route.data as Observable<{
this._data = data$.subscribe((data: {isAuthenticated: boolean, lastjump: Jump}) => { isAuthenticated: boolean;
lastjump: Jump;
}>;
this._data = data$.subscribe((data: { isAuthenticated: boolean; lastjump: Jump }) => {
this.isAuthenticated = data.isAuthenticated; this.isAuthenticated = data.isAuthenticated;
if (!this.isAuthenticated) { if (!this.isAuthenticated) {
this.router.navigateByUrl('/login'); this.router.navigateByUrl('/login');
@@ -114,24 +125,24 @@ export class LogbookComponent implements OnInit, OnDestroy, AfterContentChecked
const currentYear: number = new Date().getFullYear(); const currentYear: number = new Date().getFullYear();
this.lastJump = data['lastjump']; this.lastJump = data['lastjump'];
this.rangesMinMax = { this.rangesMinMax = {
numero: {start: 1, end: data.lastjump.numero}, numero: { start: 1, end: data.lastjump.numero },
taille: {start: data.lastjump.taille!, end: 230}, taille: { start: data.lastjump.taille!, end: 230 },
participants: {start: 1, end: 20}, participants: { start: 1, end: 20 },
hauteur: {start: 1000, end: 8000}, hauteur: { start: 1000, end: 8000 },
year: {start: 2018, end: currentYear} year: { start: 2018, end: currentYear },
} };
this.listConfig.filters.numeroRangeStart = this.rangesMinMax.numero.start; this.listConfig.filters.numeroRangeStart = this.rangesMinMax.numero.start;
this.listConfig.filters.numeroRangeEnd = this.rangesMinMax.numero.end; this.listConfig.filters.numeroRangeEnd = this.rangesMinMax.numero.end;
this.listConfig.filters.tailleRangeStart = this.rangesMinMax.taille.start; this.listConfig.filters.tailleRangeStart = this.rangesMinMax.taille.start;
this.listConfig.filters.tailleRangeEnd = this.rangesMinMax.taille.end; this.listConfig.filters.tailleRangeEnd = this.rangesMinMax.taille.end;
this.listConfig.filters.participantsRangeStart = this.rangesMinMax.participants.start; this.listConfig.filters.participantsRangeStart = this.rangesMinMax.participants.start;
this.listConfig.filters.participantsRangeEnd = (this.rangesMinMax.participants.end / 2); this.listConfig.filters.participantsRangeEnd = this.rangesMinMax.participants.end / 2;
this.listConfig.filters.hauteurRangeStart = this.rangesMinMax.hauteur.start; this.listConfig.filters.hauteurRangeStart = this.rangesMinMax.hauteur.start;
this.listConfig.filters.hauteurRangeEnd = this.rangesMinMax.hauteur.end; this.listConfig.filters.hauteurRangeEnd = this.rangesMinMax.hauteur.end;
this.listConfig.filters.yearRangeStart = this.rangesMinMax.year.start; this.listConfig.filters.yearRangeStart = this.rangesMinMax.year.start;
this.listConfig.filters.yearRangeEnd = this.rangesMinMax.year.end; this.listConfig.filters.yearRangeEnd = this.rangesMinMax.year.end;
this.jumpsSinceHundred = computed(() => (this.lastJump.numero % 100)); this.jumpsSinceHundred = computed(() => this.lastJump.numero % 100);
this.jumpsToHundred = computed(() => (100 - this.jumpsSinceHundred())); this.jumpsToHundred = computed(() => 100 - this.jumpsSinceHundred());
/* /*
this._lastjump$ = this._jumpsService.getLastJump(); this._lastjump$ = this._jumpsService.getLastJump();
this._lastjump = this._lastjump$.subscribe((jump) => { this._lastjump = this._lastjump$.subscribe((jump) => {
@@ -165,7 +176,7 @@ export class LogbookComponent implements OnInit, OnDestroy, AfterContentChecked
this._data.unsubscribe(); this._data.unsubscribe();
this._currentUser.unsubscribe(); this._currentUser.unsubscribe();
this._lastjump.unsubscribe(); this._lastjump.unsubscribe();
this._subscriptions.forEach(subscription => { this._subscriptions.forEach((subscription) => {
subscription.unsubscribe(); subscription.unsubscribe();
}); });
} }
@@ -185,7 +196,8 @@ export class LogbookComponent implements OnInit, OnDestroy, AfterContentChecked
try { try {
data.forEach((entry) => { data.forEach((entry) => {
Object.assign(this.jump, entry); Object.assign(this.jump, entry);
this._jumpsService.save(this.jump) this._jumpsService
.save(this.jump)
.pipe(take(1)) .pipe(take(1))
.subscribe({ .subscribe({
next: (jump) => { next: (jump) => {
@@ -194,7 +206,7 @@ export class LogbookComponent implements OnInit, OnDestroy, AfterContentChecked
error: (err) => { error: (err) => {
console.log(`Le saut n'a pas été ajouté !`, 'Error', err); console.log(`Le saut n'a pas été ajouté !`, 'Error', err);
this.errors = err; this.errors = err;
} },
}); });
}); });
} catch (error) { } catch (error) {
@@ -204,15 +216,17 @@ export class LogbookComponent implements OnInit, OnDestroy, AfterContentChecked
openAddDialog(): void { openAddDialog(): void {
this.jump = <Jump>{}; this.jump = <Jump>{};
this.jump.numero = (this.lastJump.numero + 1); this.jump.numero = this.lastJump.numero + 1;
this.jump.sautants = []; this.jump.sautants = [];
this.jump.participants = 1; this.jump.participants = 1;
const dialogRef = this.dialog.open(JumpAddDialogComponent, { const dialogRef = this.dialog.open(JumpAddDialogComponent, {
width: '70vw', width: '70vw',
data: {jump: this.jump, lastJump: this.lastJump} data: { jump: this.jump, lastJump: this.lastJump },
}); });
dialogRef.afterClosed().pipe(take(1)) dialogRef
.subscribe(result => { .afterClosed()
.pipe(take(1))
.subscribe((result) => {
if (result != undefined) { if (result != undefined) {
this._onEntry(result); this._onEntry(result);
} }
@@ -229,19 +243,30 @@ export class LogbookComponent implements OnInit, OnDestroy, AfterContentChecked
config.filters.offset = 0; config.filters.offset = 0;
config.filters.dateRangeStart = `${jumps[0].date!.substring(0, 10)} 00:00:00`; config.filters.dateRangeStart = `${jumps[0].date!.substring(0, 10)} 00:00:00`;
config.filters.dateRangeEnd = `${jumps[0].date!.substring(0, 10)} 23:59:59`; config.filters.dateRangeEnd = `${jumps[0].date!.substring(0, 10)} 23:59:59`;
const subscription: Subscription = this._jumpsService.getAllFromSkydiverIdApi(config) const subscription: Subscription = this._jumpsService
.getAllFromSkydiverIdApi(config)
.pipe(take(1)) .pipe(take(1))
.subscribe({ .subscribe({
next: (data) => { next: (data) => {
if (data.items.length) { if (data.items.length) {
const diff = jumps.length - data.items.length; const diff = jumps.length - data.items.length;
if (diff < 0) { if (diff < 0) {
console.error(`${diff} ${diff > 1 ? 'données' : 'donnée'} altimètre de trop le ${jumps[0].date!.substring(0, 10)}`); console.error(
`${diff} ${diff > 1 ? 'données' : 'donnée'} altimètre de trop le ${jumps[0].date!.substring(0, 10)}`,
);
} }
if (diff > 0) { if (diff > 0) {
console.error(`${diff}/${jumps.length} ${diff > 1 ? 'données altimètre manquantes' : 'donnée altimètre manquante'} le ${jumps[0].date!.substring(0, 10)}`, jumps, data.items); console.error(
`${diff}/${jumps.length} ${diff > 1 ? 'données altimètre manquantes' : 'donnée altimètre manquante'} le ${jumps[0].date!.substring(0, 10)}`,
jumps,
data.items,
);
} }
console.log(`${jumps.length} ${jumps.length > 1 ? 'sauts' : 'saut'} le ${data.items[0].date!.substring(0, 10)}`, jumps.sort((a, b) => b.numero! - a.numero!), data.items); console.log(
`${jumps.length} ${jumps.length > 1 ? 'sauts' : 'saut'} le ${data.items[0].date!.substring(0, 10)}`,
jumps.sort((a, b) => b.numero! - a.numero!),
data.items,
);
this._addX2Data(data.items, jumps); this._addX2Data(data.items, jumps);
} else { } else {
console.info('Aucune données altimètre pour le ', jumps[0].date!.substring(0, 10)); console.info('Aucune données altimètre pour le ', jumps[0].date!.substring(0, 10));
@@ -250,13 +275,14 @@ export class LogbookComponent implements OnInit, OnDestroy, AfterContentChecked
error: (err) => { error: (err) => {
console.error('getAllFromSkydiverIdApi error'); console.error('getAllFromSkydiverIdApi error');
this.errors = err; this.errors = err;
} },
}); });
this._subscriptions.push(subscription); this._subscriptions.push(subscription);
} }
private _addJump(jumps: Array<Jump>, index: number = 0) { private _addJump(jumps: Array<Jump>, index: number = 0) {
this._jumpsService.save(jumps[index]) this._jumpsService
.save(jumps[index])
.pipe(take(1)) .pipe(take(1))
.subscribe({ .subscribe({
next: (jump) => { next: (jump) => {
@@ -265,16 +291,16 @@ export class LogbookComponent implements OnInit, OnDestroy, AfterContentChecked
Object.assign(this.jump, jump); Object.assign(this.jump, jump);
this._openSnackBar(`Le saut n°${jump.numero} a été ajouté !`, 'Annuler'); this._openSnackBar(`Le saut n°${jump.numero} a été ajouté !`, 'Annuler');
this._resetErrors(); this._resetErrors();
if (jumps.length == (index + 1)) { if (jumps.length == index + 1) {
this._loadSkydiverIdJumps(jumps); this._loadSkydiverIdJumps(jumps);
} else { } else {
this._addJump(jumps, (index + 1)); this._addJump(jumps, index + 1);
} }
}, },
error: (err) => { error: (err) => {
this.errors = err; this.errors = err;
this.isSubmitting = false; this.isSubmitting = false;
} },
}); });
} }
@@ -282,26 +308,26 @@ export class LogbookComponent implements OnInit, OnDestroy, AfterContentChecked
const file: JumpFile = { const file: JumpFile = {
name: x2data[index].name, name: x2data[index].name,
path: `/Volumes/Storage/Skydive/X2_Logs/${x2data[index].date!.substring(0, 4)}/`, path: `/Volumes/Storage/Skydive/X2_Logs/${x2data[index].date!.substring(0, 4)}/`,
type: JumpFileType.CSV type: JumpFileType.CSV,
} as JumpFile; } as JumpFile;
this._subscriptions.push( this._subscriptions.push(
this._jumpsService.saveX2Data(jumps[index].slug!, file, x2data[index]) this._jumpsService
.saveX2Data(jumps[index].slug!, file, x2data[index])
.pipe(take(1)) .pipe(take(1))
.subscribe({ .subscribe({
next: (jump) => { next: (jump) => {
jumps[index] = jump; jumps[index] = jump;
console.log(`Le fichier ${file.name} a été ajouté au saut n°${jump.numero} !`, 'OK'); console.log(`Le fichier ${file.name} a été ajouté au saut n°${jump.numero} !`, 'OK');
if (jumps.length == (index + 1) || x2data.length == (index + 1)) { if (jumps.length == index + 1 || x2data.length == index + 1) {
this._addKmlFile(jumps); this._addKmlFile(jumps);
} else { } else {
this._addX2Data(x2data, jumps, (index + 1)); this._addX2Data(x2data, jumps, index + 1);
} }
}, },
error: (err) => { error: (err) => {
this.errors = err; this.errors = err;
} },
}) }),
); );
} }
@@ -311,15 +337,19 @@ export class LogbookComponent implements OnInit, OnDestroy, AfterContentChecked
const file: JumpFile = { const file: JumpFile = {
name: jumps[index].x2data.name.substring(0, -4) + '.kml', name: jumps[index].x2data.name.substring(0, -4) + '.kml',
path: `/Volumes/Storage/Skydive/X2_Kmls/${jumps[index].date.substring(0, 4)}/`, path: `/Volumes/Storage/Skydive/X2_Kmls/${jumps[index].date.substring(0, 4)}/`,
type: JumpFileType.KML type: JumpFileType.KML,
} as JumpFile; } as JumpFile;
this._subscriptions.push( this._subscriptions.push(
this._jumpsService.saveKml(jumps[index].slug, file) this._jumpsService
.saveKml(jumps[index].slug, file)
.pipe(take(1)) .pipe(take(1))
.subscribe({ .subscribe({
next: (file) => { next: (file) => {
console.log(`Le fichier ${file.path}${file.name} a été ajouté au saut n°${jumps[index].numero} !`, 'OK'); console.log(
if (jumps.length == (index + 1)) { `Le fichier ${file.path}${file.name} a été ajouté au saut n°${jumps[index].numero} !`,
'OK',
);
if (jumps.length == index + 1) {
this._resetErrors(); this._resetErrors();
this.jumpRefresh = !this.jumpRefresh; this.jumpRefresh = !this.jumpRefresh;
this._jumpTableService.updateJumpRefresh(this.jumpRefresh); this._jumpTableService.updateJumpRefresh(this.jumpRefresh);
@@ -328,13 +358,13 @@ export class LogbookComponent implements OnInit, OnDestroy, AfterContentChecked
this.lastJump = jump; this.lastJump = jump;
}); });
} else { } else {
this._addKmlFile(jumps, (index + 1)); this._addKmlFile(jumps, index + 1);
} }
}, },
error: (err) => { error: (err) => {
this.errors = err; this.errors = err;
} },
}) }),
); );
} }
} }
@@ -387,7 +417,7 @@ export class LogbookComponent implements OnInit, OnDestroy, AfterContentChecked
const config: MatSnackBarConfig = { const config: MatSnackBarConfig = {
horizontalPosition: <MatSnackBarHorizontalPosition>'end', horizontalPosition: <MatSnackBarHorizontalPosition>'end',
verticalPosition: <MatSnackBarVerticalPosition>'bottom', verticalPosition: <MatSnackBarVerticalPosition>'bottom',
duration: 4000 duration: 4000,
}; };
this.snackBar.open(content, title, config); this.snackBar.open(content, title, config);
} }
@@ -395,5 +425,4 @@ export class LogbookComponent implements OnInit, OnDestroy, AfterContentChecked
private _resetErrors(): void { private _resetErrors(): void {
this.errors = { errors: {} }; this.errors = { errors: {} };
} }
} }
+15 -22
View File
@@ -1,7 +1,7 @@
import { Title } from '@angular/platform-browser'; import { Title } from '@angular/platform-browser';
import { trigger, state, style, animate, transition } from '@angular/animations'; import { trigger, state, style, animate, transition } from '@angular/animations';
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core'; import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { DatePipe } from '@angular/common'; import { DatePipe } from '@angular/common';
import { ActivatedRoute, RouterLink } from '@angular/router'; import { ActivatedRoute, RouterLink } from '@angular/router';
import { MatCardModule } from '@angular/material/card'; import { MatCardModule } from '@angular/material/card';
@@ -9,49 +9,42 @@ import { MatDividerModule } from '@angular/material/divider';
import { MatIconModule } from '@angular/material/icon'; import { MatIconModule } from '@angular/material/icon';
import { Observable, Subscription } from 'rxjs'; import { Observable, Subscription } from 'rxjs';
import { ListErrorsComponent, } from '@components/shared'; import { ListErrorsComponent } from '@components/shared';
import { Errors, Article, ArticlePageData } from '@models'; import { Errors, Article, ArticlePageData } from '@models';
@Component({ @Component({
selector: 'app-page', selector: 'app-page',
standalone: true, imports: [DatePipe, RouterLink, MatCardModule, MatDividerModule, MatIconModule, ListErrorsComponent],
imports: [
DatePipe, RouterLink,
MatCardModule, MatDividerModule, MatIconModule,
ListErrorsComponent
],
templateUrl: './page.component.html', templateUrl: './page.component.html',
styleUrl: './page.component.scss', styleUrl: './page.component.scss',
animations: [ animations: [
trigger('flyInOut', [ trigger('flyInOut', [
state('in', style({ transform: 'translateY(0)' })), state('in', style({ transform: 'translateY(0)' })),
transition('void => *', [ transition('void => *', [style({ transform: 'translateY(-100%)' }), animate(200)]),
style({ transform: 'translateY(-100%)' }), transition('* => void', [style({ transform: 'translateY(100%)' }), animate(200)]),
animate(200)
]), ]),
transition('* => void', [ ],
style({ transform: 'translateY(100%)' }),
animate(200)
])
])
]
}) })
export class PageComponent implements OnInit, OnDestroy { export class PageComponent implements OnInit, OnDestroy {
private _data: Subscription = new Subscription(); private _data: Subscription = new Subscription();
public title = 'Shop bientôt disponible!'; public title = 'Shop bientôt disponible!';
public description = 'Encore un peu de patience, notre shop sera mis en ligne d\'ici peu.'; public description = "Encore un peu de patience, notre shop sera mis en ligne d'ici peu.";
public errors: Errors = { errors: {} }; public errors: Errors = { errors: {} };
public destroyRef = inject(DestroyRef); public destroyRef = inject(DestroyRef);
public article: Article = {} as Article; public article: Article = {} as Article;
constructor( constructor(
private route: ActivatedRoute, private route: ActivatedRoute,
private titleService: Title private titleService: Title,
) { } ) {}
ngOnInit() { ngOnInit() {
const data$: Observable<{ pageData: ArticlePageData }> = this.route.data as Observable<{ pageData: ArticlePageData }>; const data$: Observable<{ pageData: ArticlePageData }> = this.route.data as Observable<{
this._data = data$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: { pageData: ArticlePageData }) => { pageData: ArticlePageData;
}>;
this._data = data$
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe((data: { pageData: ArticlePageData }) => {
this.article = data.pageData.article; this.article = data.pageData.article;
this.title = this.article.title; this.title = this.article.title;
this.titleService.setTitle(this.article.title); this.titleService.setTitle(this.article.title);
+2 -5
View File
@@ -2,11 +2,8 @@ import { Component } from '@angular/core';
@Component({ @Component({
selector: 'app-pages', selector: 'app-pages',
standalone: true,
imports: [], imports: [],
templateUrl: './pages.component.html', templateUrl: './pages.component.html',
styleUrl: './pages.component.scss' styleUrl: './pages.component.scss',
}) })
export class PagesComponent { export class PagesComponent {}
}
+15 -22
View File
@@ -1,7 +1,7 @@
import { Title } from '@angular/platform-browser'; import { Title } from '@angular/platform-browser';
import { trigger, state, style, animate, transition } from '@angular/animations'; import { trigger, state, style, animate, transition } from '@angular/animations';
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core'; import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { DatePipe, DecimalPipe } from '@angular/common'; import { DatePipe, DecimalPipe } from '@angular/common';
import { ActivatedRoute, RouterLink } from '@angular/router'; import { ActivatedRoute, RouterLink } from '@angular/router';
import { MatCardModule } from '@angular/material/card'; import { MatCardModule } from '@angular/material/card';
@@ -9,49 +9,42 @@ import { MatDividerModule } from '@angular/material/divider';
import { MatIconModule } from '@angular/material/icon'; import { MatIconModule } from '@angular/material/icon';
import { Observable, Subscription } from 'rxjs'; import { Observable, Subscription } from 'rxjs';
import { ListErrorsComponent, } from '@components/shared'; import { ListErrorsComponent } from '@components/shared';
import { Errors, Product, ProductPageData } from '@models'; import { Errors, Product, ProductPageData } from '@models';
@Component({ @Component({
selector: 'app-product', selector: 'app-product',
standalone: true, imports: [DatePipe, DecimalPipe, RouterLink, MatCardModule, MatDividerModule, MatIconModule, ListErrorsComponent],
imports: [
DatePipe, DecimalPipe, RouterLink,
MatCardModule, MatDividerModule, MatIconModule,
ListErrorsComponent
],
templateUrl: './product.component.html', templateUrl: './product.component.html',
styleUrl: './product.component.scss', styleUrl: './product.component.scss',
animations: [ animations: [
trigger('flyInOut', [ trigger('flyInOut', [
state('in', style({ transform: 'translateY(0)' })), state('in', style({ transform: 'translateY(0)' })),
transition('void => *', [ transition('void => *', [style({ transform: 'translateY(-100%)' }), animate(200)]),
style({ transform: 'translateY(-100%)' }), transition('* => void', [style({ transform: 'translateY(100%)' }), animate(200)]),
animate(200)
]), ]),
transition('* => void', [ ],
style({ transform: 'translateY(100%)' }),
animate(200)
])
])
]
}) })
export class ProductComponent implements OnInit, OnDestroy { export class ProductComponent implements OnInit, OnDestroy {
private _data: Subscription = new Subscription(); private _data: Subscription = new Subscription();
public title = 'Ad Astra - Produit'; public title = 'Ad Astra - Produit';
public description = 'Encore un peu de patience, notre shop sera mis en ligne d\'ici peu.'; public description = "Encore un peu de patience, notre shop sera mis en ligne d'ici peu.";
public errors: Errors = { errors: {} }; public errors: Errors = { errors: {} };
public destroyRef = inject(DestroyRef); public destroyRef = inject(DestroyRef);
public product: Product = {} as Product; public product: Product = {} as Product;
constructor( constructor(
private route: ActivatedRoute, private route: ActivatedRoute,
private titleService: Title private titleService: Title,
) { } ) {}
ngOnInit() { ngOnInit() {
const data$: Observable<{ pageData: ProductPageData }> = this.route.data as Observable<{ pageData: ProductPageData }>; const data$: Observable<{ pageData: ProductPageData }> = this.route.data as Observable<{
this._data = data$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: { pageData: ProductPageData }) => { pageData: ProductPageData;
}>;
this._data = data$
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe((data: { pageData: ProductPageData }) => {
this.product = data.pageData.product; this.product = data.pageData.product;
this.title = this.product.name; this.title = this.product.name;
this.description = this.product.description; this.description = this.product.description;
@@ -1,7 +1,7 @@
import { Title } from '@angular/platform-browser'; import { Title } from '@angular/platform-browser';
import { trigger, state, style, animate, transition } from '@angular/animations'; import { trigger, state, style, animate, transition } from '@angular/animations';
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core'; import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { DatePipe, DecimalPipe } from '@angular/common'; import { DatePipe, DecimalPipe } from '@angular/common';
import { ActivatedRoute, RouterLink } from '@angular/router'; import { ActivatedRoute, RouterLink } from '@angular/router';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
@@ -10,37 +10,35 @@ import { MatDividerModule } from '@angular/material/divider';
import { MatIconModule } from '@angular/material/icon'; import { MatIconModule } from '@angular/material/icon';
import { Observable, Subscription } from 'rxjs'; import { Observable, Subscription } from 'rxjs';
import { ListErrorsComponent, } from '@components/shared'; import { ListErrorsComponent } from '@components/shared';
import { Errors, Product, ProductsPageData } from '@models'; import { Errors, Product, ProductsPageData } from '@models';
@Component({ @Component({
selector: 'app-products', selector: 'app-products',
standalone: true,
imports: [ imports: [
DatePipe, DecimalPipe, RouterLink, DatePipe,
MatButtonModule, MatCardModule, MatDividerModule, MatIconModule, DecimalPipe,
ListErrorsComponent RouterLink,
MatButtonModule,
MatCardModule,
MatDividerModule,
MatIconModule,
ListErrorsComponent,
], ],
templateUrl: './products.component.html', templateUrl: './products.component.html',
styleUrl: './products.component.scss', styleUrl: './products.component.scss',
animations: [ animations: [
trigger('flyInOut', [ trigger('flyInOut', [
state('in', style({ transform: 'translateY(0)' })), state('in', style({ transform: 'translateY(0)' })),
transition('void => *', [ transition('void => *', [style({ transform: 'translateY(-100%)' }), animate(200)]),
style({ transform: 'translateY(-100%)' }), transition('* => void', [style({ transform: 'translateY(100%)' }), animate(200)]),
animate(200)
]), ]),
transition('* => void', [ ],
style({ transform: 'translateY(100%)' }),
animate(200)
])
])
]
}) })
export class ProductsComponent implements OnInit, OnDestroy { export class ProductsComponent implements OnInit, OnDestroy {
private _data: Subscription = new Subscription(); private _data: Subscription = new Subscription();
public title = 'Ad Astra - Produit'; public title = 'Ad Astra - Produit';
public description = 'Encore un peu de patience, notre shop sera mis en ligne d\'ici peu.'; public description = "Encore un peu de patience, notre shop sera mis en ligne d'ici peu.";
public errors: Errors = { errors: {} }; public errors: Errors = { errors: {} };
public destroyRef = inject(DestroyRef); public destroyRef = inject(DestroyRef);
public products: Array<Product> = []; public products: Array<Product> = [];
@@ -48,12 +46,16 @@ export class ProductsComponent implements OnInit, OnDestroy {
constructor( constructor(
private route: ActivatedRoute, private route: ActivatedRoute,
private titleService: Title private titleService: Title,
) { } ) {}
ngOnInit() { ngOnInit() {
const data$: Observable<{ pageData: ProductsPageData }> = this.route.data as Observable<{ pageData: ProductsPageData }>; const data$: Observable<{ pageData: ProductsPageData }> = this.route.data as Observable<{
this._data = data$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: { pageData: ProductsPageData }) => { pageData: ProductsPageData;
}>;
this._data = data$
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe((data: { pageData: ProductsPageData }) => {
this.products = data.pageData.products; this.products = data.pageData.products;
this.productsCount = data.pageData.count; this.productsCount = data.pageData.count;
//this.title = 'Fleurs CBD'; //this.title = 'Fleurs CBD';
@@ -68,5 +70,4 @@ export class ProductsComponent implements OnInit, OnDestroy {
ngOnDestroy() { ngOnDestroy() {
this._data.unsubscribe(); this._data.unsubscribe();
} }
} }
@@ -13,15 +13,10 @@ import { UserService } from '@services';
import { ListErrorsComponent } from '@components/shared'; import { ListErrorsComponent } from '@components/shared';
@Component({ @Component({
standalone: true, imports: [RouterLink, MatButtonModule, MatCardModule, MatDividerModule, MatIconModule, ListErrorsComponent],
imports: [
RouterLink,
MatButtonModule, MatCardModule, MatDividerModule, MatIconModule,
ListErrorsComponent
],
selector: 'app-profile', selector: 'app-profile',
templateUrl: './profile.component.html', templateUrl: './profile.component.html',
styleUrl: './profile.component.scss' styleUrl: './profile.component.scss',
}) })
export class ProfileComponent implements OnInit, OnDestroy { export class ProfileComponent implements OnInit, OnDestroy {
private _user: Subscription = new Subscription(); private _user: Subscription = new Subscription();
@@ -33,8 +28,8 @@ export class ProfileComponent implements OnInit, OnDestroy {
constructor( constructor(
private titleService: Title, private titleService: Title,
private userService: UserService private userService: UserService,
) { } ) {}
ngOnInit() { ngOnInit() {
this.titleService.setTitle(`Ad Astra - ${this.title}`); this.titleService.setTitle(`Ad Astra - ${this.title}`);
@@ -49,5 +44,4 @@ export class ProfileComponent implements OnInit, OnDestroy {
ngOnDestroy() { ngOnDestroy() {
this._user.unsubscribe(); this._user.unsubscribe();
} }
} }
+36 -25
View File
@@ -1,5 +1,5 @@
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core'; import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { /*FormControl,*/ FormGroup, FormBuilder, FormArray, FormsModule, ReactiveFormsModule } from '@angular/forms'; import { /*FormControl,*/ FormGroup, FormBuilder, FormArray, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { ActivatedRoute } from '@angular/router'; import { ActivatedRoute } from '@angular/router';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
@@ -22,16 +22,22 @@ import data from 'src/qcm-bpa.json';
@Component({ @Component({
selector: 'app-qcm', selector: 'app-qcm',
standalone: true,
imports: [ imports: [
FormsModule, ReactiveFormsModule, FormsModule,
MatButtonModule, MatCardModule, MatDividerModule, MatExpansionModule, ReactiveFormsModule,
MatIconModule, MatMenuModule, MatProgressBarModule, MatRadioModule, MatButtonModule,
MatCardModule,
MatDividerModule,
MatExpansionModule,
MatIconModule,
MatMenuModule,
MatProgressBarModule,
MatRadioModule,
MatSelectModule, MatSelectModule,
ListErrorsComponent ListErrorsComponent,
], ],
templateUrl: './qcm.component.html', templateUrl: './qcm.component.html',
styleUrl: './qcm.component.scss' styleUrl: './qcm.component.scss',
}) })
export class QcmComponent implements OnInit, OnDestroy { export class QcmComponent implements OnInit, OnDestroy {
private _currentUser: Subscription = new Subscription(); private _currentUser: Subscription = new Subscription();
@@ -53,17 +59,17 @@ export class QcmComponent implements OnInit, OnDestroy {
public totalAnswer = 0; public totalAnswer = 0;
public timeProgress = 0; public timeProgress = 0;
public timeProgressColor = 'primary'; public timeProgressColor = 'primary';
public timeMax = (60*45); public timeMax = 60 * 45;
constructor( constructor(
private route: ActivatedRoute, private route: ActivatedRoute,
private fb: FormBuilder, private fb: FormBuilder,
private _qcmService: QcmService, private _qcmService: QcmService,
private _userService: UserService, private _userService: UserService,
public menuItems: MenuItems public menuItems: MenuItems,
) { ) {
this.qcmForm = this.fb.group({ this.qcmForm = this.fb.group({
questions: this.fb.array([]) questions: this.fb.array([]),
}); });
} }
@@ -87,9 +93,9 @@ export class QcmComponent implements OnInit, OnDestroy {
this.subtitle = `Préparation au questionnaire du brevet ${this.qcm.name.toUpperCase()}`; this.subtitle = `Préparation au questionnaire du brevet ${this.qcm.name.toUpperCase()}`;
} }
//console.log(this.title, this.qcm); //console.log(this.title, this.qcm);
this.qcm.categories.forEach(category => { this.qcm.categories.forEach((category) => {
this.questionsCount += category.questions.length; this.questionsCount += category.questions.length;
category.questions.forEach(question => { category.questions.forEach((question) => {
this.addQuestion(question); this.addQuestion(question);
}); });
}); });
@@ -113,11 +119,14 @@ export class QcmComponent implements OnInit, OnDestroy {
.pipe(take(this.timeMax)) .pipe(take(this.timeMax))
.subscribe(() => { .subscribe(() => {
this.timeProgress++; this.timeProgress++;
if (this.timeProgress > (this.timeMax/100*70) && this.timeProgress <= (this.timeMax/100*90)) { if (this.timeProgress > (this.timeMax / 100) * 70 && this.timeProgress <= (this.timeMax / 100) * 90) {
this.timeProgressColor = 'warning'; this.timeProgressColor = 'warning';
} else if (this.timeProgress > (this.timeMax/100*90) && this.timeProgress <= (this.timeMax/100*98)) { } else if (
this.timeProgress > (this.timeMax / 100) * 90 &&
this.timeProgress <= (this.timeMax / 100) * 98
) {
this.timeProgressColor = 'danger'; this.timeProgressColor = 'danger';
} else if (this.timeProgress > (this.timeMax/100*98)) { } else if (this.timeProgress > (this.timeMax / 100) * 98) {
this.timeProgressColor = 'purple'; this.timeProgressColor = 'purple';
} }
if (this.timeProgress >= this.timeMax) { if (this.timeProgress >= this.timeMax) {
@@ -130,7 +139,7 @@ export class QcmComponent implements OnInit, OnDestroy {
addQuestion(question: QcmQuestion) { addQuestion(question: QcmQuestion) {
const item = this.fb.group({ const item = this.fb.group({
id: [question.num], id: [question.num],
choice: [''] choice: [''],
}); });
this.answers.push(QcmQuestionState.UNANSWERED); this.answers.push(QcmQuestionState.UNANSWERED);
this.questions.push(item); this.questions.push(item);
@@ -145,19 +154,19 @@ export class QcmComponent implements OnInit, OnDestroy {
if (this.timeProgress === 0) { if (this.timeProgress === 0) {
this._starTimer(); this._starTimer();
} }
this.qcm.categories[(category.num-1)].questions[(question.num-1)].choices.forEach(choice => { this.qcm.categories[category.num - 1].questions[question.num - 1].choices.forEach((choice) => {
if (choice.index === value) { if (choice.index === value) {
if (choice.correct) { if (choice.correct) {
this.answers[(question.num-1)] = QcmQuestionState.VALID; this.answers[question.num - 1] = QcmQuestionState.VALID;
console.log(`Réponse à la question ${question.num} de la catégorie ${category.num} : correcte`); console.log(`Réponse à la question ${question.num} de la catégorie ${category.num} : correcte`);
} else { } else {
this.answers[(question.num-1)] = QcmQuestionState.ERROR; this.answers[question.num - 1] = QcmQuestionState.ERROR;
console.log(`Réponse à la question ${question.num} de la catégorie ${category.num} : incorrecte`); console.log(`Réponse à la question ${question.num} de la catégorie ${category.num} : incorrecte`);
} }
} }
}); });
this.totalAnswer++; this.totalAnswer++;
this.questions.controls[(question.num-1)].disable(); this.questions.controls[question.num - 1].disable();
//console.log(this.questions.controls[(question.num-1)].disabled); //console.log(this.questions.controls[(question.num-1)].disabled);
} }
@@ -168,8 +177,9 @@ export class QcmComponent implements OnInit, OnDestroy {
private _importChoices() { private _importChoices() {
try { try {
data.categories.forEach((category) => { data.categories.forEach((category) => {
category.questions.forEach(question => { category.questions.forEach((question) => {
this._qcmService.saveChoices(question) this._qcmService
.saveChoices(question)
.pipe(takeUntilDestroyed(this.destroyRef)) .pipe(takeUntilDestroyed(this.destroyRef))
.subscribe({ .subscribe({
next: (question) => { next: (question) => {
@@ -180,7 +190,7 @@ export class QcmComponent implements OnInit, OnDestroy {
console.log('err : ', err); console.log('err : ', err);
//console.log(`Le saut n'a pas été ajouté !`, 'Error', err); //console.log(`Le saut n'a pas été ajouté !`, 'Error', err);
this.errors = err; this.errors = err;
} },
}); });
}); });
}); });
@@ -193,7 +203,8 @@ export class QcmComponent implements OnInit, OnDestroy {
try { try {
data.categories.forEach((category) => { data.categories.forEach((category) => {
//Object.assign(this.jump, category); //Object.assign(this.jump, category);
this._qcmService.saveQuestions(category) this._qcmService
.saveQuestions(category)
.pipe(takeUntilDestroyed(this.destroyRef)) .pipe(takeUntilDestroyed(this.destroyRef))
.subscribe({ .subscribe({
next: (category) => { next: (category) => {
@@ -204,7 +215,7 @@ export class QcmComponent implements OnInit, OnDestroy {
console.log('err : ', err); console.log('err : ', err);
//console.log(`Le saut n'a pas été ajouté !`, 'Error', err); //console.log(`Le saut n'a pas été ajouté !`, 'Error', err);
this.errors = err; this.errors = err;
} },
}); });
}); });
} catch (error) { } catch (error) {
@@ -1,6 +1,15 @@
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core'; import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { AbstractControl, FormsModule, ReactiveFormsModule, UntypedFormBuilder, UntypedFormGroup, Validators, ValidatorFn, ValidationErrors } from '@angular/forms'; import {
AbstractControl,
FormsModule,
ReactiveFormsModule,
UntypedFormBuilder,
UntypedFormGroup,
Validators,
ValidatorFn,
ValidationErrors,
} from '@angular/forms';
import { Router, RouterLink } from '@angular/router'; import { Router, RouterLink } from '@angular/router';
import { Title } from '@angular/platform-browser'; import { Title } from '@angular/platform-browser';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
@@ -17,14 +26,19 @@ import { ListErrorsComponent } from '@components/shared';
@Component({ @Component({
selector: 'app-credentials', selector: 'app-credentials',
standalone: true,
imports: [ imports: [
RouterLink, FormsModule, ReactiveFormsModule, RouterLink,
MatButtonModule, MatIconModule, MatFormFieldModule, MatInputModule, MatDividerModule, FormsModule,
ListErrorsComponent ReactiveFormsModule,
MatButtonModule,
MatIconModule,
MatFormFieldModule,
MatInputModule,
MatDividerModule,
ListErrorsComponent,
], ],
templateUrl: './credentials.component.html', templateUrl: './credentials.component.html',
styleUrl: './credentials.component.scss' styleUrl: './credentials.component.scss',
}) })
export class CredentialsComponent implements OnInit, OnDestroy { export class CredentialsComponent implements OnInit, OnDestroy {
private _user: Subscription = new Subscription(); private _user: Subscription = new Subscription();
@@ -42,12 +56,15 @@ export class CredentialsComponent implements OnInit, OnDestroy {
private router: Router, private router: Router,
private titleService: Title, private titleService: Title,
private userService: UserService, private userService: UserService,
private fb: UntypedFormBuilder private fb: UntypedFormBuilder,
) { ) {
this.credentialsForm = this.fb.group({ this.credentialsForm = this.fb.group(
{
password: ['', Validators.required], password: ['', Validators.required],
confirmPassword: ['', Validators.required] confirmPassword: ['', Validators.required],
}, { validators: this.checkPasswords }); },
{ validators: this.checkPasswords },
);
} }
get f() { get f() {
@@ -72,13 +89,15 @@ export class CredentialsComponent implements OnInit, OnDestroy {
submitForm() { submitForm() {
this.isSubmitting = true; this.isSubmitting = true;
this.updateUser(this.credentialsForm.value); this.updateUser(this.credentialsForm.value);
const user$: Observable<{ user: User }> = this.userService.update(this.user).pipe(takeUntilDestroyed(this.destroyRef)); const user$: Observable<{ user: User }> = this.userService
.update(this.user)
.pipe(takeUntilDestroyed(this.destroyRef));
this._user = user$.subscribe({ this._user = user$.subscribe({
next: ({ user }) => void this.router.navigateByUrl('/profile/' + user.username), next: ({ user }) => void this.router.navigateByUrl('/profile/' + user.username),
error: (err) => { error: (err) => {
this.errors = err; this.errors = err;
this.isSubmitting = false; this.isSubmitting = false;
} },
}); });
} }
@@ -88,8 +107,7 @@ export class CredentialsComponent implements OnInit, OnDestroy {
checkPasswords: ValidatorFn = (group: AbstractControl): ValidationErrors | null => { checkPasswords: ValidatorFn = (group: AbstractControl): ValidationErrors | null => {
const pass = group.get('password')!.value; const pass = group.get('password')!.value;
const confirmPass = group.get('confirmPassword')!.value const confirmPass = group.get('confirmPassword')!.value;
return pass === confirmPass ? null : { notSame: true } return pass === confirmPass ? null : { notSame: true };
} };
} }
@@ -1,5 +1,5 @@
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core'; import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { FormsModule, ReactiveFormsModule, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; import { FormsModule, ReactiveFormsModule, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { Router, RouterLink } from '@angular/router'; import { Router, RouterLink } from '@angular/router';
import { Title } from '@angular/platform-browser'; import { Title } from '@angular/platform-browser';
@@ -18,14 +18,20 @@ import { ListErrorsComponent } from '@components/shared';
@Component({ @Component({
selector: 'app-settings-page', selector: 'app-settings-page',
standalone: true,
imports: [ imports: [
RouterLink, FormsModule, ReactiveFormsModule, RouterLink,
MatButtonModule, MatIconModule, MatDividerModule, MatFormFieldModule, MatInputModule, MatSelectModule, FormsModule,
ListErrorsComponent ReactiveFormsModule,
MatButtonModule,
MatIconModule,
MatDividerModule,
MatFormFieldModule,
MatInputModule,
MatSelectModule,
ListErrorsComponent,
], ],
styleUrl: './settings.component.scss', styleUrl: './settings.component.scss',
templateUrl: './settings.component.html' templateUrl: './settings.component.html',
}) })
export class SettingsComponent implements OnInit, OnDestroy { export class SettingsComponent implements OnInit, OnDestroy {
private _user: Subscription = new Subscription(); private _user: Subscription = new Subscription();
@@ -42,21 +48,29 @@ export class SettingsComponent implements OnInit, OnDestroy {
imgPath = '/assets/images/avatars/'; imgPath = '/assets/images/avatars/';
imgExt = '.jpg'; imgExt = '.jpg';
avatars = [ avatars = [
`${this.imgPath}animal_001${this.imgExt}`, `${this.imgPath}animal_002${this.imgExt}`, `${this.imgPath}animal_001${this.imgExt}`,
`${this.imgPath}animal_003${this.imgExt}`, `${this.imgPath}animal_004${this.imgExt}`, `${this.imgPath}animal_002${this.imgExt}`,
`${this.imgPath}animal_005${this.imgExt}`, `${this.imgPath}animal_006${this.imgExt}`, `${this.imgPath}animal_003${this.imgExt}`,
`${this.imgPath}animal_007${this.imgExt}`, `${this.imgPath}animal_008${this.imgExt}`, `${this.imgPath}animal_004${this.imgExt}`,
`${this.imgPath}animal_009${this.imgExt}`, `${this.imgPath}animal_010${this.imgExt}`, `${this.imgPath}animal_005${this.imgExt}`,
`${this.imgPath}animal_011${this.imgExt}`, `${this.imgPath}animal_012${this.imgExt}`, `${this.imgPath}animal_006${this.imgExt}`,
`${this.imgPath}animal_013${this.imgExt}`, `${this.imgPath}animal_014${this.imgExt}`, `${this.imgPath}animal_007${this.imgExt}`,
`${this.imgPath}animal_015${this.imgExt}`, `${this.imgPath}animal_016${this.imgExt}` `${this.imgPath}animal_008${this.imgExt}`,
`${this.imgPath}animal_009${this.imgExt}`,
`${this.imgPath}animal_010${this.imgExt}`,
`${this.imgPath}animal_011${this.imgExt}`,
`${this.imgPath}animal_012${this.imgExt}`,
`${this.imgPath}animal_013${this.imgExt}`,
`${this.imgPath}animal_014${this.imgExt}`,
`${this.imgPath}animal_015${this.imgExt}`,
`${this.imgPath}animal_016${this.imgExt}`,
]; ];
constructor( constructor(
private router: Router, private router: Router,
private titleService: Title, private titleService: Title,
private userService: UserService, private userService: UserService,
private fb: UntypedFormBuilder private fb: UntypedFormBuilder,
) { ) {
// create form group using the form builder // create form group using the form builder
this.settingsForm = this.fb.group({ this.settingsForm = this.fb.group({
@@ -65,7 +79,7 @@ export class SettingsComponent implements OnInit, OnDestroy {
firstname: ['', Validators.required], firstname: ['', Validators.required],
lastname: ['', Validators.required], lastname: ['', Validators.required],
phone: ['', Validators.required], phone: ['', Validators.required],
image: '' image: '',
}); });
// Optional: subscribe to changes on the form : // Optional: subscribe to changes on the form :
// this.settingsForm.valueChanges.pipe(this._scavenger.collect()).subscribe(values => this.updateUser(values)); // this.settingsForm.valueChanges.pipe(this._scavenger.collect()).subscribe(values => this.updateUser(values));
@@ -110,18 +124,19 @@ export class SettingsComponent implements OnInit, OnDestroy {
} }
this.updateUser(this.settingsForm.value); this.updateUser(this.settingsForm.value);
const user$: Observable<{ user: User }> = this.userService.update(this.user).pipe(takeUntilDestroyed(this.destroyRef)); const user$: Observable<{ user: User }> = this.userService
.update(this.user)
.pipe(takeUntilDestroyed(this.destroyRef));
this._user = user$.subscribe({ this._user = user$.subscribe({
next: ({ user }) => void this.router.navigateByUrl('/profile/' + user.username), next: ({ user }) => void this.router.navigateByUrl('/profile/' + user.username),
error: (err) => { error: (err) => {
this.errors = err; this.errors = err;
this.isSubmitting = false; this.isSubmitting = false;
} },
}); });
} }
updateUser(values: NonNullable<unknown>) { updateUser(values: NonNullable<unknown>) {
Object.assign(this.user, values); Object.assign(this.user, values);
} }
} }
@@ -1,5 +1,5 @@
import { Component, Input } from '@angular/core'; import { Component, Input } from '@angular/core';
import { NgForOf, NgIf } from "@angular/common"; import { NgForOf, NgIf } from '@angular/common';
import { MatCardModule } from '@angular/material/card'; import { MatCardModule } from '@angular/material/card';
import { CardColors } from 'src/app/core'; import { CardColors } from 'src/app/core';
@@ -7,8 +7,7 @@ import { CardColors } from 'src/app/core';
@Component({ @Component({
selector: 'app-card-container', selector: 'app-card-container',
templateUrl: './card-container.component.html', templateUrl: './card-container.component.html',
standalone: true, imports: [NgIf, NgForOf, MatCardModule],
imports: [NgIf, NgForOf, MatCardModule]
}) })
export class CardContainerComponent { export class CardContainerComponent {
errorList: string[] = []; errorList: string[] = [];
@@ -1,5 +1,5 @@
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core'; import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card'; import { MatCardModule } from '@angular/material/card';
import { MatDividerModule } from '@angular/material/divider'; import { MatDividerModule } from '@angular/material/divider';
@@ -16,13 +16,17 @@ import { AeronefByImat, AeronefByYear } from '@models';
@Component({ @Component({
selector: 'app-aeronefs-bar', selector: 'app-aeronefs-bar',
standalone: true,
imports: [ imports: [
MatButtonModule, MatCardModule, MatDividerModule, MatButtonModule,
MatExpansionModule, MatIconModule, MatMenuModule, MatCardModule,
BarHorizontalChartComponent, HistoryTableComponent MatDividerModule,
MatExpansionModule,
MatIconModule,
MatMenuModule,
BarHorizontalChartComponent,
HistoryTableComponent,
], ],
templateUrl: './aeronefs-bar.component.html' templateUrl: './aeronefs-bar.component.html',
}) })
export class AeronefsBarComponent implements OnInit, OnDestroy { export class AeronefsBarComponent implements OnInit, OnDestroy {
private _aeronefByImat: Subscription = new Subscription(); private _aeronefByImat: Subscription = new Subscription();
@@ -36,11 +40,11 @@ export class AeronefsBarComponent implements OnInit, OnDestroy {
public seriesValue: number[] = []; public seriesValue: number[] = [];
public seriesRow: Array<Array<number>> = []; public seriesRow: Array<Array<number>> = [];
public seriesColor: { public seriesColor: {
backgroundColor: string[], backgroundColor: string[];
borderColor: string[] borderColor: string[];
} = { } = {
backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'), backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'),
borderColor: this._utilitiesService.getSeriesColors(1, 'all') borderColor: this._utilitiesService.getSeriesColors(1, 'all'),
}; };
public seriesColorClass: string[] = this._utilitiesService.getChartColors(); public seriesColorClass: string[] = this._utilitiesService.getChartColors();
public displayCharts = false; public displayCharts = false;
@@ -49,8 +53,8 @@ export class AeronefsBarComponent implements OnInit, OnDestroy {
constructor( constructor(
private _aeronefsService: AeronefsService, private _aeronefsService: AeronefsService,
private _utilitiesService: UtilitiesService, private _utilitiesService: UtilitiesService,
public menuItems: MenuItems public menuItems: MenuItems,
) { } ) {}
ngOnInit() { ngOnInit() {
this._loadAeronefByImat(); this._loadAeronefByImat();
@@ -62,7 +66,9 @@ export class AeronefsBarComponent implements OnInit, OnDestroy {
} }
private _loadAeronefByImat(): void { private _loadAeronefByImat(): void {
const aeronefs$: Observable<Array<AeronefByImat>> = this._aeronefsService.getAllByImat().pipe(takeUntilDestroyed(this.destroyRef)); const aeronefs$: Observable<Array<AeronefByImat>> = this._aeronefsService
.getAllByImat()
.pipe(takeUntilDestroyed(this.destroyRef));
this._aeronefByImat = aeronefs$.subscribe((aggregate: Array<AeronefByImat>) => { this._aeronefByImat = aeronefs$.subscribe((aggregate: Array<AeronefByImat>) => {
this._aeronefsByImat = aggregate.map((row: AeronefByImat) => { this._aeronefsByImat = aggregate.map((row: AeronefByImat) => {
//this.chartConfig.barChartData.labels!.push(`${row.aeronef} ${row.imat}`); //this.chartConfig.barChartData.labels!.push(`${row.aeronef} ${row.imat}`);
@@ -80,13 +86,16 @@ export class AeronefsBarComponent implements OnInit, OnDestroy {
this.seriesName.forEach(() => { this.seriesName.forEach(() => {
this.seriesRow.push([...values]); this.seriesRow.push([...values]);
}); });
const dropzones$: Observable<Array<AeronefByYear>> = this._aeronefsService.getAllByImatByYear().pipe(takeUntilDestroyed(this.destroyRef)); const dropzones$: Observable<Array<AeronefByYear>> = this._aeronefsService
.getAllByImatByYear()
.pipe(takeUntilDestroyed(this.destroyRef));
this._aeronefByYear = dropzones$.subscribe((aggregate: Array<AeronefByYear>) => { this._aeronefByYear = dropzones$.subscribe((aggregate: Array<AeronefByYear>) => {
this._aeronefsByYear = aggregate.map((row: AeronefByYear) => { this._aeronefsByYear = aggregate.map((row: AeronefByYear) => {
const aeronef: string = row.aeronef; const aeronef: string = row.aeronef;
const imat: string = row.imat; const imat: string = row.imat;
const year: string = row.year.toString(); const year: string = row.year.toString();
this.seriesRow[this.seriesName.indexOf(`${aeronef} ${imat}`)][this.seriesHeader.indexOf(year)] = row.count; this.seriesRow[this.seriesName.indexOf(`${aeronef} ${imat}`)][this.seriesHeader.indexOf(year)] =
row.count;
return row; return row;
}); });
this.displayCharts = true; this.displayCharts = true;
@@ -1,5 +1,5 @@
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core'; import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { MatBadgeModule } from '@angular/material/badge'; import { MatBadgeModule } from '@angular/material/badge';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card'; import { MatCardModule } from '@angular/material/card';
@@ -17,13 +17,18 @@ import { AeronefByImat, AeronefByYear } from '@models';
@Component({ @Component({
selector: 'app-aeronefs-pie', selector: 'app-aeronefs-pie',
standalone: true,
imports: [ imports: [
MatBadgeModule, MatButtonModule, MatCardModule, MatDividerModule, MatBadgeModule,
MatExpansionModule, MatIconModule, MatMenuModule, MatButtonModule,
HistoryTableComponent, PieChartComponent MatCardModule,
MatDividerModule,
MatExpansionModule,
MatIconModule,
MatMenuModule,
HistoryTableComponent,
PieChartComponent,
], ],
templateUrl: './aeronefs-pie.component.html' templateUrl: './aeronefs-pie.component.html',
}) })
export class AeronefsPieComponent implements OnInit, OnDestroy { export class AeronefsPieComponent implements OnInit, OnDestroy {
private _aeronefByImat: Subscription = new Subscription(); private _aeronefByImat: Subscription = new Subscription();
@@ -37,11 +42,11 @@ export class AeronefsPieComponent implements OnInit, OnDestroy {
public seriesValue: number[] = []; public seriesValue: number[] = [];
public seriesRow: Array<Array<number>> = []; public seriesRow: Array<Array<number>> = [];
public seriesColor: { public seriesColor: {
backgroundColor: string[], backgroundColor: string[];
borderColor: string[] borderColor: string[];
} = { } = {
backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'), backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'),
borderColor: this._utilitiesService.getSeriesColors(1, 'all') borderColor: this._utilitiesService.getSeriesColors(1, 'all'),
}; };
public seriesColorClass: string[] = this._utilitiesService.getChartColors(); public seriesColorClass: string[] = this._utilitiesService.getChartColors();
public destroyRef = inject(DestroyRef); public destroyRef = inject(DestroyRef);
@@ -49,8 +54,8 @@ export class AeronefsPieComponent implements OnInit, OnDestroy {
constructor( constructor(
private _aeronefsService: AeronefsService, private _aeronefsService: AeronefsService,
private _utilitiesService: UtilitiesService, private _utilitiesService: UtilitiesService,
public menuItems: MenuItems public menuItems: MenuItems,
) { } ) {}
ngOnInit() { ngOnInit() {
this._loadAeronefByImat(); this._loadAeronefByImat();
@@ -62,7 +67,9 @@ export class AeronefsPieComponent implements OnInit, OnDestroy {
} }
private _loadAeronefByImat(): void { private _loadAeronefByImat(): void {
const aeronefs$: Observable<Array<AeronefByImat>> = this._aeronefsService.getAllByImat().pipe(takeUntilDestroyed(this.destroyRef)); const aeronefs$: Observable<Array<AeronefByImat>> = this._aeronefsService
.getAllByImat()
.pipe(takeUntilDestroyed(this.destroyRef));
this._aeronefByImat = aeronefs$.subscribe((aggregate: Array<AeronefByImat>) => { this._aeronefByImat = aeronefs$.subscribe((aggregate: Array<AeronefByImat>) => {
this._aeronefsByImat = aggregate.map((row: AeronefByImat) => { this._aeronefsByImat = aggregate.map((row: AeronefByImat) => {
this.seriesName.push(`${row.aeronef} ${row.imat}`); this.seriesName.push(`${row.aeronef} ${row.imat}`);
@@ -79,13 +86,16 @@ export class AeronefsPieComponent implements OnInit, OnDestroy {
this.seriesName.forEach(() => { this.seriesName.forEach(() => {
this.seriesRow.push([...values]); this.seriesRow.push([...values]);
}); });
const dropzones$: Observable<Array<AeronefByYear>> = this._aeronefsService.getAllByImatByYear().pipe(takeUntilDestroyed(this.destroyRef)); const dropzones$: Observable<Array<AeronefByYear>> = this._aeronefsService
.getAllByImatByYear()
.pipe(takeUntilDestroyed(this.destroyRef));
this._aeronefByYear = dropzones$.subscribe((aggregate: Array<AeronefByYear>) => { this._aeronefByYear = dropzones$.subscribe((aggregate: Array<AeronefByYear>) => {
this._aeronefsByYear = aggregate.map((row: AeronefByYear) => { this._aeronefsByYear = aggregate.map((row: AeronefByYear) => {
const aeronef: string = row.aeronef; const aeronef: string = row.aeronef;
const imat: string = row.imat; const imat: string = row.imat;
const year: string = row.year.toString(); const year: string = row.year.toString();
this.seriesRow[this.seriesName.indexOf(`${aeronef} ${imat}`)][this.seriesHeader.indexOf(year)] = row.count; this.seriesRow[this.seriesName.indexOf(`${aeronef} ${imat}`)][this.seriesHeader.indexOf(year)] =
row.count;
return row; return row;
}); });
}); });
@@ -1,5 +1,5 @@
import { Component, DestroyRef, inject, OnInit, OnDestroy} from '@angular/core'; import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card'; import { MatCardModule } from '@angular/material/card';
import { MatDividerModule } from '@angular/material/divider'; import { MatDividerModule } from '@angular/material/divider';
@@ -16,13 +16,17 @@ import { CanopyModelBySize, CanopyModelByYear } from '@models';
@Component({ @Component({
selector: 'app-canopies-models', selector: 'app-canopies-models',
standalone: true,
imports: [ imports: [
MatButtonModule, MatCardModule, MatDividerModule, MatButtonModule,
MatExpansionModule, MatIconModule, MatMenuModule, MatCardModule,
PieChartComponent, HistoryTableComponent MatDividerModule,
MatExpansionModule,
MatIconModule,
MatMenuModule,
PieChartComponent,
HistoryTableComponent,
], ],
templateUrl: './canopies-models.component.html' templateUrl: './canopies-models.component.html',
}) })
export class CanopiesModelsComponent implements OnInit, OnDestroy { export class CanopiesModelsComponent implements OnInit, OnDestroy {
private _canopyBySize: Subscription = new Subscription(); private _canopyBySize: Subscription = new Subscription();
@@ -36,11 +40,11 @@ export class CanopiesModelsComponent implements OnInit, OnDestroy {
public seriesValue: number[] = []; public seriesValue: number[] = [];
public seriesRow: Array<Array<number>> = []; public seriesRow: Array<Array<number>> = [];
public seriesColor: { public seriesColor: {
backgroundColor: string[], backgroundColor: string[];
borderColor: string[] borderColor: string[];
} = { } = {
backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'), backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'),
borderColor: this._utilitiesService.getSeriesColors(1, 'all') borderColor: this._utilitiesService.getSeriesColors(1, 'all'),
}; };
public seriesColorClass: string[] = this._utilitiesService.getChartColors(); public seriesColorClass: string[] = this._utilitiesService.getChartColors();
public destroyRef = inject(DestroyRef); public destroyRef = inject(DestroyRef);
@@ -48,8 +52,8 @@ export class CanopiesModelsComponent implements OnInit, OnDestroy {
constructor( constructor(
private _canopiesService: CanopiesService, private _canopiesService: CanopiesService,
private _utilitiesService: UtilitiesService, private _utilitiesService: UtilitiesService,
public menuItems: MenuItems public menuItems: MenuItems,
) { } ) {}
ngOnInit() { ngOnInit() {
this._loadCanopyModelBySize(); this._loadCanopyModelBySize();
@@ -61,7 +65,9 @@ export class CanopiesModelsComponent implements OnInit, OnDestroy {
} }
private _loadCanopyModelBySize(): void { private _loadCanopyModelBySize(): void {
const canopies$: Observable<Array<CanopyModelBySize>> = this._canopiesService.getAllBySizeByModel().pipe(takeUntilDestroyed(this.destroyRef)); const canopies$: Observable<Array<CanopyModelBySize>> = this._canopiesService
.getAllBySizeByModel()
.pipe(takeUntilDestroyed(this.destroyRef));
this._canopyBySize = canopies$.subscribe((aggregate: Array<CanopyModelBySize>) => { this._canopyBySize = canopies$.subscribe((aggregate: Array<CanopyModelBySize>) => {
this._canopiesBySize = aggregate.map((row: CanopyModelBySize) => { this._canopiesBySize = aggregate.map((row: CanopyModelBySize) => {
this.seriesName.push(`${row.taille.toString()} - ${row.voile}`); this.seriesName.push(`${row.taille.toString()} - ${row.voile}`);
@@ -78,13 +84,16 @@ export class CanopiesModelsComponent implements OnInit, OnDestroy {
this.seriesName.forEach(() => { this.seriesName.forEach(() => {
this.seriesRow.push([...values]); this.seriesRow.push([...values]);
}); });
const dropzones$: Observable<Array<CanopyModelByYear>> = this._canopiesService.getAllBySizeByModelByYear().pipe(takeUntilDestroyed(this.destroyRef)); const dropzones$: Observable<Array<CanopyModelByYear>> = this._canopiesService
.getAllBySizeByModelByYear()
.pipe(takeUntilDestroyed(this.destroyRef));
this._canopyByYear = dropzones$.subscribe((aggregate: Array<CanopyModelByYear>) => { this._canopyByYear = dropzones$.subscribe((aggregate: Array<CanopyModelByYear>) => {
this._canopiesByYear = aggregate.map((row: CanopyModelByYear) => { this._canopiesByYear = aggregate.map((row: CanopyModelByYear) => {
const voile: string = row.voile; const voile: string = row.voile;
const taille: string = row.taille.toString(); const taille: string = row.taille.toString();
const year: string = row.year.toString(); const year: string = row.year.toString();
this.seriesRow[this.seriesName.indexOf(`${taille} - ${voile}`)][this.seriesHeader.indexOf(year)] = row.count; this.seriesRow[this.seriesName.indexOf(`${taille} - ${voile}`)][this.seriesHeader.indexOf(year)] =
row.count;
return row; return row;
}); });
}); });
@@ -1,5 +1,5 @@
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core'; import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card'; import { MatCardModule } from '@angular/material/card';
import { MatDividerModule } from '@angular/material/divider'; import { MatDividerModule } from '@angular/material/divider';
@@ -17,13 +17,17 @@ import { CanopyBySize, CanopyByYear } from '@models';
@Component({ @Component({
selector: 'app-canopies-sizes', selector: 'app-canopies-sizes',
standalone: true,
imports: [ imports: [
MatButtonModule, MatCardModule, MatDividerModule, MatButtonModule,
MatExpansionModule, MatIconModule, MatMenuModule, MatCardModule,
PieChartComponent, HistoryTableComponent MatDividerModule,
MatExpansionModule,
MatIconModule,
MatMenuModule,
PieChartComponent,
HistoryTableComponent,
], ],
templateUrl: './canopies-sizes.component.html' templateUrl: './canopies-sizes.component.html',
}) })
export class CanopiesSizesComponent implements OnInit, OnDestroy { export class CanopiesSizesComponent implements OnInit, OnDestroy {
private _canopyBySize: Subscription = new Subscription(); private _canopyBySize: Subscription = new Subscription();
@@ -37,11 +41,11 @@ export class CanopiesSizesComponent implements OnInit, OnDestroy {
public seriesValue: number[] = []; public seriesValue: number[] = [];
public seriesRow: Array<Array<number>> = []; public seriesRow: Array<Array<number>> = [];
public seriesColor: { public seriesColor: {
backgroundColor: string[], backgroundColor: string[];
borderColor: string[] borderColor: string[];
} = { } = {
backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'), backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'),
borderColor: this._utilitiesService.getSeriesColors(1, 'all') borderColor: this._utilitiesService.getSeriesColors(1, 'all'),
}; };
public seriesColorClass: string[] = this._utilitiesService.getChartColors(); public seriesColorClass: string[] = this._utilitiesService.getChartColors();
public destroyRef = inject(DestroyRef); public destroyRef = inject(DestroyRef);
@@ -49,8 +53,8 @@ export class CanopiesSizesComponent implements OnInit, OnDestroy {
constructor( constructor(
private _canopiesService: CanopiesService, private _canopiesService: CanopiesService,
private _utilitiesService: UtilitiesService, private _utilitiesService: UtilitiesService,
public menuItems: MenuItems public menuItems: MenuItems,
) { } ) {}
ngOnInit() { ngOnInit() {
this._loadCanopyBySize(); this._loadCanopyBySize();
@@ -62,7 +66,9 @@ export class CanopiesSizesComponent implements OnInit, OnDestroy {
} }
private _loadCanopyBySize(): void { private _loadCanopyBySize(): void {
const canopies$: Observable<Array<CanopyBySize>> = this._canopiesService.getAllBySize().pipe(takeUntilDestroyed(this.destroyRef)); const canopies$: Observable<Array<CanopyBySize>> = this._canopiesService
.getAllBySize()
.pipe(takeUntilDestroyed(this.destroyRef));
this._canopyBySize = canopies$.subscribe((aggregate: Array<CanopyBySize>) => { this._canopyBySize = canopies$.subscribe((aggregate: Array<CanopyBySize>) => {
this._canopiesBySize = aggregate.map((row: CanopyBySize) => { this._canopiesBySize = aggregate.map((row: CanopyBySize) => {
this.seriesName.push(row.taille.toString()); this.seriesName.push(row.taille.toString());
@@ -79,7 +85,9 @@ export class CanopiesSizesComponent implements OnInit, OnDestroy {
this.seriesName.forEach(() => { this.seriesName.forEach(() => {
this.seriesRow.push([...values]); this.seriesRow.push([...values]);
}); });
const dropzones$: Observable<Array<CanopyByYear>> = this._canopiesService.getAllBySizeByYear().pipe(takeUntilDestroyed(this.destroyRef)); const dropzones$: Observable<Array<CanopyByYear>> = this._canopiesService
.getAllBySizeByYear()
.pipe(takeUntilDestroyed(this.destroyRef));
this._canopyByYear = dropzones$.subscribe((aggregate: Array<CanopyByYear>) => { this._canopyByYear = dropzones$.subscribe((aggregate: Array<CanopyByYear>) => {
this._canopiesByYear = aggregate.map((row: CanopyByYear) => { this._canopiesByYear = aggregate.map((row: CanopyByYear) => {
const taille: string = row.taille.toString(); const taille: string = row.taille.toString();
@@ -1,5 +1,5 @@
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core'; import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card'; import { MatCardModule } from '@angular/material/card';
import { MatDividerModule } from '@angular/material/divider'; import { MatDividerModule } from '@angular/material/divider';
@@ -18,14 +18,18 @@ import { DropZoneByOaci, DropZoneByYear } from '@models';
@Component({ @Component({
selector: 'app-dropzones-bar', selector: 'app-dropzones-bar',
standalone: true,
imports: [ imports: [
MatButtonModule, MatCardModule, MatDividerModule, MatButtonModule,
MatExpansionModule, MatIconModule, MatMenuModule, MatCardModule,
BaseChartDirective, ChartistModule, MatDividerModule,
HistoryTableComponent MatExpansionModule,
MatIconModule,
MatMenuModule,
BaseChartDirective,
ChartistModule,
HistoryTableComponent,
], ],
templateUrl: './dropzones-bar.component.html' templateUrl: './dropzones-bar.component.html',
}) })
export class DropzonesBarComponent implements OnInit, OnDestroy { export class DropzonesBarComponent implements OnInit, OnDestroy {
private _dropzoneByOaci: Subscription = new Subscription(); private _dropzoneByOaci: Subscription = new Subscription();
@@ -39,11 +43,11 @@ export class DropzonesBarComponent implements OnInit, OnDestroy {
public seriesValue: number[] = []; public seriesValue: number[] = [];
public seriesRow: Array<Array<number>> = []; public seriesRow: Array<Array<number>> = [];
public seriesColor: { public seriesColor: {
backgroundColor: string[], backgroundColor: string[];
borderColor: string[] borderColor: string[];
} = { } = {
backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'), backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'),
borderColor: this._utilitiesService.getSeriesColors(1, 'all') borderColor: this._utilitiesService.getSeriesColors(1, 'all'),
}; };
public seriesColorClass: string[] = this._utilitiesService.getChartColors(); public seriesColorClass: string[] = this._utilitiesService.getChartColors();
public displayCharts = false; public displayCharts = false;
@@ -53,8 +57,8 @@ export class DropzonesBarComponent implements OnInit, OnDestroy {
constructor( constructor(
private _dropzonesService: DropZonesService, private _dropzonesService: DropZonesService,
private _utilitiesService: UtilitiesService, private _utilitiesService: UtilitiesService,
public menuItems: MenuItems public menuItems: MenuItems,
) { } ) {}
ngOnInit() { ngOnInit() {
this._loadDropZoneByOaci(); this._loadDropZoneByOaci();
@@ -66,7 +70,9 @@ export class DropzonesBarComponent implements OnInit, OnDestroy {
} }
private _loadDropZoneByOaci(): void { private _loadDropZoneByOaci(): void {
const dropzones$: Observable<Array<DropZoneByOaci>> = this._dropzonesService.getAllByOaci().pipe(takeUntilDestroyed(this.destroyRef)); const dropzones$: Observable<Array<DropZoneByOaci>> = this._dropzonesService
.getAllByOaci()
.pipe(takeUntilDestroyed(this.destroyRef));
this._dropzoneByOaci = dropzones$.subscribe((aggregate: Array<DropZoneByOaci>) => { this._dropzoneByOaci = dropzones$.subscribe((aggregate: Array<DropZoneByOaci>) => {
this._dropzonesByOaci = aggregate.map((row: DropZoneByOaci) => { this._dropzonesByOaci = aggregate.map((row: DropZoneByOaci) => {
this.seriesName.push(`${row.oaci} - ${row.lieu}`); this.seriesName.push(`${row.oaci} - ${row.lieu}`);
@@ -83,25 +89,28 @@ export class DropzonesBarComponent implements OnInit, OnDestroy {
this.seriesName.forEach(() => { this.seriesName.forEach(() => {
this.seriesRow.push([...values]); this.seriesRow.push([...values]);
}); });
const dropzones$: Observable<Array<DropZoneByYear>> = this._dropzonesService.getAllByOaciByYear().pipe(takeUntilDestroyed(this.destroyRef)); const dropzones$: Observable<Array<DropZoneByYear>> = this._dropzonesService
.getAllByOaciByYear()
.pipe(takeUntilDestroyed(this.destroyRef));
this._dropzoneByYear = dropzones$.subscribe((aggregate: Array<DropZoneByYear>) => { this._dropzoneByYear = dropzones$.subscribe((aggregate: Array<DropZoneByYear>) => {
this._dropzonesByYear = aggregate.map((row: DropZoneByYear) => { this._dropzonesByYear = aggregate.map((row: DropZoneByYear) => {
const lieu: string = row.lieu; const lieu: string = row.lieu;
const oaci: string = row.oaci; const oaci: string = row.oaci;
const year: string = row.year.toString(); const year: string = row.year.toString();
this.seriesRow[this.seriesName.indexOf(`${oaci} - ${lieu}`)][this.seriesHeader.indexOf(year)] = row.count; this.seriesRow[this.seriesName.indexOf(`${oaci} - ${lieu}`)][this.seriesHeader.indexOf(year)] =
row.count;
return row; return row;
}); });
const axisX: AxisOptions = { const axisX: AxisOptions = {
labelInterpolationFnc: function(value: Label, index: number): string { labelInterpolationFnc: function (value: Label, index: number): string {
return index % 1 === 0 ? `${value.toString()}` : ''; return index % 1 === 0 ? `${value.toString()}` : '';
} },
} };
this.barChartDropZones = { this.barChartDropZones = {
type: 'Bar', type: 'Bar',
data: { data: {
'labels': this.seriesHeader, labels: this.seriesHeader,
'series': this.seriesRow series: this.seriesRow,
}, },
options: { options: {
seriesBarDistance: 15, seriesBarDistance: 15,
@@ -109,33 +118,42 @@ export class DropzonesBarComponent implements OnInit, OnDestroy {
high: 180, high: 180,
axisX: { axisX: {
showGrid: false, showGrid: false,
offset: 20 offset: 20,
}, },
axisY: { axisY: {
showGrid: true, showGrid: true,
offset: 40 offset: 40,
}, },
height: 300 height: 300,
}, },
responsiveOptions: [ responsiveOptions: [
['screen and (min-width: 1024px)', { [
axisX: axisX 'screen and (min-width: 1024px)',
}], {
['screen and (min-width: 641px) and (max-width: 1024px)', { axisX: axisX,
},
],
[
'screen and (min-width: 641px) and (max-width: 1024px)',
{
seriesBarDistance: 7, seriesBarDistance: 7,
axisY: { axisY: {
offset: 30 offset: 30,
}, },
axisX: axisX axisX: axisX,
}], },
['screen and (max-width: 640px)', { ],
[
'screen and (max-width: 640px)',
{
seriesBarDistance: 5, seriesBarDistance: 5,
axisY: { axisY: {
offset: 20 offset: 20,
}, },
axisX: axisX axisX: axisX,
}] },
] ],
],
}; };
this.displayCharts = true; this.displayCharts = true;
}); });
@@ -1,5 +1,5 @@
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core'; import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card'; import { MatCardModule } from '@angular/material/card';
import { MatDividerModule } from '@angular/material/divider'; import { MatDividerModule } from '@angular/material/divider';
@@ -17,13 +17,17 @@ import { DropZoneByOaci, DropZoneByYear } from '@models';
@Component({ @Component({
selector: 'app-dropzones-pie', selector: 'app-dropzones-pie',
standalone: true,
imports: [ imports: [
MatButtonModule, MatCardModule, MatDividerModule, MatButtonModule,
MatExpansionModule, MatIconModule, MatMenuModule, MatCardModule,
PieChartComponent, HistoryTableComponent MatDividerModule,
MatExpansionModule,
MatIconModule,
MatMenuModule,
PieChartComponent,
HistoryTableComponent,
], ],
templateUrl: './dropzones-pie.component.html' templateUrl: './dropzones-pie.component.html',
}) })
export class DropzonesPieComponent implements OnInit, OnDestroy { export class DropzonesPieComponent implements OnInit, OnDestroy {
private _dropzoneByOaci: Subscription = new Subscription(); private _dropzoneByOaci: Subscription = new Subscription();
@@ -37,11 +41,11 @@ export class DropzonesPieComponent implements OnInit, OnDestroy {
public seriesValue: number[] = []; public seriesValue: number[] = [];
public seriesRow: Array<Array<number>> = []; public seriesRow: Array<Array<number>> = [];
public seriesColor: { public seriesColor: {
backgroundColor: string[], backgroundColor: string[];
borderColor: string[] borderColor: string[];
} = { } = {
backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'), backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'),
borderColor: this._utilitiesService.getSeriesColors(1, 'all') borderColor: this._utilitiesService.getSeriesColors(1, 'all'),
}; };
public seriesColorClass: string[] = this._utilitiesService.getChartColors(); public seriesColorClass: string[] = this._utilitiesService.getChartColors();
public destroyRef = inject(DestroyRef); public destroyRef = inject(DestroyRef);
@@ -49,8 +53,8 @@ export class DropzonesPieComponent implements OnInit, OnDestroy {
constructor( constructor(
private _dropzonesService: DropZonesService, private _dropzonesService: DropZonesService,
private _utilitiesService: UtilitiesService, private _utilitiesService: UtilitiesService,
public menuItems: MenuItems public menuItems: MenuItems,
) { } ) {}
ngOnInit() { ngOnInit() {
this._loadDropZoneByOaci(); this._loadDropZoneByOaci();
@@ -62,7 +66,9 @@ export class DropzonesPieComponent implements OnInit, OnDestroy {
} }
private _loadDropZoneByOaci(): void { private _loadDropZoneByOaci(): void {
const dropzones$: Observable<Array<DropZoneByOaci>> = this._dropzonesService.getAllByOaci().pipe(takeUntilDestroyed(this.destroyRef)); const dropzones$: Observable<Array<DropZoneByOaci>> = this._dropzonesService
.getAllByOaci()
.pipe(takeUntilDestroyed(this.destroyRef));
this._dropzoneByOaci = dropzones$.subscribe((aggregate: Array<DropZoneByOaci>) => { this._dropzoneByOaci = dropzones$.subscribe((aggregate: Array<DropZoneByOaci>) => {
this._dropzonesByOaci = aggregate.map((row: DropZoneByOaci) => { this._dropzonesByOaci = aggregate.map((row: DropZoneByOaci) => {
this.seriesName.push(`${row.oaci} - ${row.lieu}`); this.seriesName.push(`${row.oaci} - ${row.lieu}`);
@@ -79,13 +85,16 @@ export class DropzonesPieComponent implements OnInit, OnDestroy {
this.seriesName.forEach(() => { this.seriesName.forEach(() => {
this.seriesRow.push([...values]); this.seriesRow.push([...values]);
}); });
const dropzones$: Observable<Array<DropZoneByYear>> = this._dropzonesService.getAllByOaciByYear().pipe(takeUntilDestroyed(this.destroyRef)); const dropzones$: Observable<Array<DropZoneByYear>> = this._dropzonesService
.getAllByOaciByYear()
.pipe(takeUntilDestroyed(this.destroyRef));
this._dropzoneByYear = dropzones$.subscribe((aggregate: Array<DropZoneByYear>) => { this._dropzoneByYear = dropzones$.subscribe((aggregate: Array<DropZoneByYear>) => {
this._dropzonesByYear = aggregate.map((row: DropZoneByYear) => { this._dropzonesByYear = aggregate.map((row: DropZoneByYear) => {
const lieu: string = row.lieu; const lieu: string = row.lieu;
const oaci: string = row.oaci; const oaci: string = row.oaci;
const year: string = row.year.toString(); const year: string = row.year.toString();
this.seriesRow[this.seriesName.indexOf(`${oaci} - ${lieu}`)][this.seriesHeader.indexOf(year)] = row.count; this.seriesRow[this.seriesName.indexOf(`${oaci} - ${lieu}`)][this.seriesHeader.indexOf(year)] =
row.count;
return row; return row;
}); });
}); });
@@ -1,5 +1,5 @@
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core'; import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card'; import { MatCardModule } from '@angular/material/card';
@@ -18,14 +18,17 @@ import { JumpByDate } from '@models';
@Component({ @Component({
selector: 'app-jumps-by-month', selector: 'app-jumps-by-month',
standalone: true,
imports: [ imports: [
CommonModule, CommonModule,
MatButtonModule, MatCardModule, MatDividerModule, MatButtonModule,
MatExpansionModule, MatIconModule, MatMenuModule, MatCardModule,
ChartistModule MatDividerModule,
MatExpansionModule,
MatIconModule,
MatMenuModule,
ChartistModule,
], ],
templateUrl: './jumps-by-month.component.html' templateUrl: './jumps-by-month.component.html',
}) })
export class JumpsByMonthComponent implements OnInit, OnDestroy { export class JumpsByMonthComponent implements OnInit, OnDestroy {
private _jumpByDate: Subscription = new Subscription(); private _jumpByDate: Subscription = new Subscription();
@@ -42,11 +45,11 @@ export class JumpsByMonthComponent implements OnInit, OnDestroy {
public seriesName: string[] = []; public seriesName: string[] = [];
public seriesRow: Array<Array<number>> = []; public seriesRow: Array<Array<number>> = [];
public seriesColor: { public seriesColor: {
backgroundColor: string[], backgroundColor: string[];
borderColor: string[] borderColor: string[];
} = { } = {
backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'), backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'),
borderColor: this._utilitiesService.getSeriesColors(1, 'all') borderColor: this._utilitiesService.getSeriesColors(1, 'all'),
}; };
public seriesColorClass: string[] = this._utilitiesService.getChartColors(); public seriesColorClass: string[] = this._utilitiesService.getChartColors();
public seriesRowTotal: number[] = []; public seriesRowTotal: number[] = [];
@@ -62,8 +65,8 @@ export class JumpsByMonthComponent implements OnInit, OnDestroy {
constructor( constructor(
private _jumpsService: JumpsService, private _jumpsService: JumpsService,
private _utilitiesService: UtilitiesService, private _utilitiesService: UtilitiesService,
public menuItems: MenuItems public menuItems: MenuItems,
) { } ) {}
ngOnInit() { ngOnInit() {
this._loadJumpByDate(); this._loadJumpByDate();
@@ -80,7 +83,9 @@ export class JumpsByMonthComponent implements OnInit, OnDestroy {
this.seriesColTotal = [...values]; this.seriesColTotal = [...values];
this.seriesColTotalClosed = [...values]; this.seriesColTotalClosed = [...values];
this.seriesColTotalLastYears = [...values]; this.seriesColTotalLastYears = [...values];
const jumps$: Observable<Array<JumpByDate>> = this._jumpsService.getAllByDate().pipe(takeUntilDestroyed(this.destroyRef)); const jumps$: Observable<Array<JumpByDate>> = this._jumpsService
.getAllByDate()
.pipe(takeUntilDestroyed(this.destroyRef));
this._jumpByDate = jumps$.subscribe((aggregate: Array<JumpByDate>) => { this._jumpByDate = jumps$.subscribe((aggregate: Array<JumpByDate>) => {
this._jumpsByDateCount = aggregate.length; this._jumpsByDateCount = aggregate.length;
this._jumpsByDate = aggregate.map((row: JumpByDate) => { this._jumpsByDate = aggregate.map((row: JumpByDate) => {
@@ -97,13 +102,13 @@ export class JumpsByMonthComponent implements OnInit, OnDestroy {
} }
this.seriesRow.push([...values]); this.seriesRow.push([...values]);
} }
this.seriesRow[(this.seriesRow.length-1)][(month-1)] = row.count; this.seriesRow[this.seriesRow.length - 1][month - 1] = row.count;
this.seriesColTotal[(month-1)] += row.count; this.seriesColTotal[month - 1] += row.count;
if (row.year < currentYear) { if (row.year < currentYear) {
this.seriesColTotalClosed[(month-1)] += row.count; this.seriesColTotalClosed[month - 1] += row.count;
} }
if (row.year >= (currentYear-3) && row.year < currentYear) { if (row.year >= currentYear - 3 && row.year < currentYear) {
this.seriesColTotalLastYears[(month-1)] += row.count; this.seriesColTotalLastYears[month - 1] += row.count;
} }
return row; return row;
}); });
@@ -112,59 +117,71 @@ export class JumpsByMonthComponent implements OnInit, OnDestroy {
this.seriesRowTotal.push(total); this.seriesRowTotal.push(total);
}); });
this.seriesColTotalClosed.forEach((row: number) => { this.seriesColTotalClosed.forEach((row: number) => {
const value: number = (row/(this.seriesName.length-minoration)); const value: number = row / (this.seriesName.length - minoration);
this.seriesRowAvg.push(parseInt(value.toFixed(0))); this.seriesRowAvg.push(parseInt(value.toFixed(0)));
}); });
this.seriesColTotalLastYears.forEach((row: number) => { this.seriesColTotalLastYears.forEach((row: number) => {
const value: number = (row/3); // Les 3 dernières années const value: number = row / 3; // Les 3 dernières années
this.seriesRowAvgLastYears.push(parseInt(value.toFixed(0))); this.seriesRowAvgLastYears.push(parseInt(value.toFixed(0)));
}); });
this.grandAvg = this.seriesRowAvg.reduce((partialSum, accumulated) => partialSum + accumulated, 0); this.grandAvg = this.seriesRowAvg.reduce((partialSum, accumulated) => partialSum + accumulated, 0);
this.grandAvgLastYears = this.seriesRowAvgLastYears.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); this.grandTotal = this.seriesColTotal.reduce((partialSum, accumulated) => partialSum + accumulated, 0);
const axisX: AxisOptions = { const axisX: AxisOptions = {
labelInterpolationFnc: function(value: Label, index: number): string { labelInterpolationFnc: function (value: Label, index: number): string {
return index % 1 === 0 ? `${value.toString()}` : ''; return index % 1 === 0 ? `${value.toString()}` : '';
} },
} };
this.barChartJumps = { this.barChartJumps = {
type: 'Bar', type: 'Bar',
data: { data: {
'labels': this.seriesHeader, labels: this.seriesHeader,
'series': this.seriesRow series: this.seriesRow,
}, },
options: { options: {
seriesBarDistance: 15, seriesBarDistance: 15,
high: 70, high: 70,
axisX: { axisX: {
showGrid: false, showGrid: false,
offset: 20 offset: 20,
}, },
axisY: { axisY: {
showGrid: true, showGrid: true,
offset: 40 offset: 40,
}, },
height: 300 height: 300,
}, },
responsiveOptions: [ responsiveOptions: [
['screen and (min-width: 1024px)', { [
axisX: axisX 'screen and (min-width: 1024px)',
}], {
['screen and (min-width: 641px) and (max-width: 1024px)', { axisX: axisX,
},
],
[
'screen and (min-width: 641px) and (max-width: 1024px)',
{
seriesBarDistance: 10, seriesBarDistance: 10,
axisY: { axisY: {
offset: 30 offset: 30,
}, },
axisX: axisX axisX: axisX,
}], },
['screen and (max-width: 640px)', { ],
[
'screen and (max-width: 640px)',
{
seriesBarDistance: 5, seriesBarDistance: 5,
axisY: { axisY: {
offset: 20 offset: 20,
}, },
axisX: axisX axisX: axisX,
}] },
] ],
],
}; };
this.displayCharts = true; this.displayCharts = true;
}); });
@@ -7,29 +7,24 @@ import { BarConfig } from '@models';
@Component({ @Component({
selector: 'app-bar-chart', selector: 'app-bar-chart',
standalone: true, imports: [BaseChartDirective],
imports: [ templateUrl: './bar-chart.component.html',
BaseChartDirective
],
templateUrl: './bar-chart.component.html'
}) })
export class BarChartComponent implements OnChanges { export class BarChartComponent implements OnChanges {
public displayCharts = false; public displayCharts = false;
public chartConfig: BarConfig = this._utilitiesService.getBarChartConfig(); public chartConfig: BarConfig = this._utilitiesService.getBarChartConfig();
constructor( constructor(private _utilitiesService: UtilitiesService) {}
private _utilitiesService: UtilitiesService
) { }
@Input() names: string[] = []; @Input() names: string[] = [];
@Input() values: number[] = []; @Input() values: number[] = [];
@Input() headers: string[] = []; @Input() headers: string[] = [];
@Input() colors: { @Input() colors: {
backgroundColor: string[], backgroundColor: string[];
borderColor: string[] borderColor: string[];
} = { } = {
backgroundColor: this._utilitiesService.getSeriesColors(0.8), backgroundColor: this._utilitiesService.getSeriesColors(0.8),
borderColor: this._utilitiesService.getSeriesColors(1) borderColor: this._utilitiesService.getSeriesColors(1),
}; };
@Input() label: string = 'Nombre total de sauts'; @Input() label: string = 'Nombre total de sauts';
@Input() legend: boolean = false; @Input() legend: boolean = false;
@@ -44,7 +39,7 @@ export class BarChartComponent implements OnChanges {
label: this.label, label: this.label,
backgroundColor: this.colors.backgroundColor, backgroundColor: this.colors.backgroundColor,
borderColor: this.colors.borderColor, borderColor: this.colors.borderColor,
borderWidth: 1 borderWidth: 1,
}; };
this.chartConfig.barChartData.labels = [...this.names]; this.chartConfig.barChartData.labels = [...this.names];
this.chartConfig.barChartData.datasets!.push(dataset); this.chartConfig.barChartData.datasets!.push(dataset);
@@ -7,29 +7,24 @@ import { BarConfig } from '@models';
@Component({ @Component({
selector: 'app-bar-horizontal-chart', selector: 'app-bar-horizontal-chart',
standalone: true, imports: [BaseChartDirective],
imports: [ templateUrl: './bar-horizontal-chart.component.html',
BaseChartDirective
],
templateUrl: './bar-horizontal-chart.component.html'
}) })
export class BarHorizontalChartComponent implements OnChanges { export class BarHorizontalChartComponent implements OnChanges {
public displayCharts = false; public displayCharts = false;
public chartConfig: BarConfig = this._utilitiesService.getHorizontalBarChartConfig(); public chartConfig: BarConfig = this._utilitiesService.getHorizontalBarChartConfig();
constructor( constructor(private _utilitiesService: UtilitiesService) {}
private _utilitiesService: UtilitiesService
) { }
@Input() names: string[] = []; @Input() names: string[] = [];
@Input() values: number[] = []; @Input() values: number[] = [];
@Input() headers: string[] = []; @Input() headers: string[] = [];
@Input() colors: { @Input() colors: {
backgroundColor: string[], backgroundColor: string[];
borderColor: string[] borderColor: string[];
} = { } = {
backgroundColor: this._utilitiesService.getSeriesColors(0.8), backgroundColor: this._utilitiesService.getSeriesColors(0.8),
borderColor: this._utilitiesService.getSeriesColors(1) borderColor: this._utilitiesService.getSeriesColors(1),
}; };
@Input() label: string = 'Nombre total de sauts'; @Input() label: string = 'Nombre total de sauts';
@Input() legend: boolean = false; @Input() legend: boolean = false;
@@ -44,7 +39,7 @@ export class BarHorizontalChartComponent implements OnChanges {
label: this.label, label: this.label,
backgroundColor: this.colors.backgroundColor, backgroundColor: this.colors.backgroundColor,
borderColor: this.colors.borderColor, borderColor: this.colors.borderColor,
borderWidth: 1 borderWidth: 1,
}; };
this.chartConfig.barChartData.labels = [...this.names]; this.chartConfig.barChartData.labels = [...this.names];
this.chartConfig.barChartData.datasets!.push(dataset); this.chartConfig.barChartData.datasets!.push(dataset);
@@ -7,29 +7,24 @@ import { BarConfig } from '@models';
@Component({ @Component({
selector: 'app-bars-chart', selector: 'app-bars-chart',
standalone: true, imports: [BaseChartDirective],
imports: [ templateUrl: './bars-chart.component.html',
BaseChartDirective
],
templateUrl: './bars-chart.component.html'
}) })
export class BarsChartComponent implements OnChanges, AfterContentChecked { export class BarsChartComponent implements OnChanges, AfterContentChecked {
public displayCharts = false; public displayCharts = false;
public chartConfig: BarConfig = this._utilitiesService.getBarChartConfig(); public chartConfig: BarConfig = this._utilitiesService.getBarChartConfig();
constructor( constructor(private _utilitiesService: UtilitiesService) {}
private _utilitiesService: UtilitiesService
) { }
@Input() names: string[] = []; @Input() names: string[] = [];
@Input() values: Array<Array<number>> = []; @Input() values: Array<Array<number>> = [];
@Input() headers: string[] = []; @Input() headers: string[] = [];
@Input() colors: { @Input() colors: {
backgroundColor: string[], backgroundColor: string[];
borderColor: string[] borderColor: string[];
} = { } = {
backgroundColor: this._utilitiesService.getSeriesColors(0.8), backgroundColor: this._utilitiesService.getSeriesColors(0.8),
borderColor: this._utilitiesService.getSeriesColors(1) borderColor: this._utilitiesService.getSeriesColors(1),
}; };
@Input() legend: boolean = false; @Input() legend: boolean = false;
@@ -52,15 +47,25 @@ export class BarsChartComponent implements OnChanges, AfterContentChecked {
//stacked: true, //stacked: true,
beginAtZero: true, beginAtZero: true,
ticks: { color: 'rgba(255,255,255,0.3)' }, ticks: { color: 'rgba(255,255,255,0.3)' },
grid: { color: 'rgba(255,255,255,0.1)', display: true, tickBorderDash: [1,2], tickBorderDashOffset: 2 } grid: {
color: 'rgba(255,255,255,0.1)',
display: true,
tickBorderDash: [1, 2],
tickBorderDashOffset: 2,
},
}, },
y: { y: {
display: true, display: true,
//stacked: true, //stacked: true,
beginAtZero: true, beginAtZero: true,
ticks: { color: 'rgba(255,255,255,0.3)' }, ticks: { color: 'rgba(255,255,255,0.3)' },
grid: { color: 'rgba(255,255,255,0.2)', tickBorderDash: [1,2], tickBorderDashOffset: 2, display: true } grid: {
} color: 'rgba(255,255,255,0.2)',
tickBorderDash: [1, 2],
tickBorderDashOffset: 2,
display: true,
},
},
}; };
this.names.forEach((label: string, index: number) => { this.names.forEach((label: string, index: number) => {
const dataset: ChartDataset<'bar'> = { const dataset: ChartDataset<'bar'> = {
@@ -7,19 +7,14 @@ import { CircleConfig } from '@models';
@Component({ @Component({
selector: 'app-circle-chart', selector: 'app-circle-chart',
standalone: true, imports: [BaseChartDirective],
imports: [ templateUrl: './circle-chart.component.html',
BaseChartDirective
],
templateUrl: './circle-chart.component.html'
}) })
export class CircleChartComponent implements OnChanges { export class CircleChartComponent implements OnChanges {
public displayCharts = false; public displayCharts = false;
public chartConfig: CircleConfig = this._utilitiesService.getCircleChartConfig(); public chartConfig: CircleConfig = this._utilitiesService.getCircleChartConfig();
constructor( constructor(private _utilitiesService: UtilitiesService) {}
private _utilitiesService: UtilitiesService
) { }
@Input() names: string[] = []; @Input() names: string[] = [];
@Input() values: number[] = []; @Input() values: number[] = [];
@@ -38,11 +33,11 @@ export class CircleChartComponent implements OnChanges {
this.chartConfig.circleChartDatasets[0].label = this.label; this.chartConfig.circleChartDatasets[0].label = this.label;
this.chartConfig.circleChartDatasets[0].backgroundColor = [ this.chartConfig.circleChartDatasets[0].backgroundColor = [
this._utilitiesService.getSeriesColors(0.9, 'pastels')[this.color], this._utilitiesService.getSeriesColors(0.9, 'pastels')[this.color],
'rgba(255, 255, 255, 0.05)' 'rgba(255, 255, 255, 0.05)',
]; ];
this.chartConfig.circleChartDatasets[0].borderColor = [ this.chartConfig.circleChartDatasets[0].borderColor = [
this._utilitiesService.getSeriesColors(1, 'pastels')[this.color], this._utilitiesService.getSeriesColors(1, 'pastels')[this.color],
'rgba(255, 255, 255, 0.05)' 'rgba(255, 255, 255, 0.05)',
]; ];
this.chartConfig.circleChartDatasets[0].borderWidth = 0; this.chartConfig.circleChartDatasets[0].borderWidth = 0;
this.chartConfig.circleChartLegend = this.legend; this.chartConfig.circleChartLegend = this.legend;
@@ -7,29 +7,24 @@ import { LineConfig } from '@models';
@Component({ @Component({
selector: 'app-line-chart', selector: 'app-line-chart',
standalone: true, imports: [BaseChartDirective],
imports: [ templateUrl: './line-chart.component.html',
BaseChartDirective
],
templateUrl: './line-chart.component.html'
}) })
export class LineChartComponent implements OnChanges { export class LineChartComponent implements OnChanges {
public displayCharts = false; public displayCharts = false;
public chartConfig: LineConfig = this._utilitiesService.getLineChartConfig(); public chartConfig: LineConfig = this._utilitiesService.getLineChartConfig();
constructor( constructor(private _utilitiesService: UtilitiesService) {}
private _utilitiesService: UtilitiesService
) { }
@Input() headers: string[] = []; @Input() headers: string[] = [];
@Input() names: string[] = []; @Input() names: string[] = [];
@Input() values: Array<Array<number>> = []; @Input() values: Array<Array<number>> = [];
@Input() colors: { @Input() colors: {
backgroundColor: string[], backgroundColor: string[];
borderColor: string[] borderColor: string[];
} = { } = {
backgroundColor: this._utilitiesService.getSeriesColors(0.8), backgroundColor: this._utilitiesService.getSeriesColors(0.8),
borderColor: this._utilitiesService.getSeriesColors(1) borderColor: this._utilitiesService.getSeriesColors(1),
}; };
@Input() legend: boolean = false; @Input() legend: boolean = false;
@Input() hideZero: boolean = false; @Input() hideZero: boolean = false;
@@ -41,9 +36,9 @@ export class LineChartComponent implements OnChanges {
private _loadLineChart(): void { private _loadLineChart(): void {
this.chartConfig.lineChartData.labels = [...this.headers]; this.chartConfig.lineChartData.labels = [...this.headers];
this.names.forEach((label: string, index: number) => { this.names.forEach((label: string, index: number) => {
let data: Array<(number | Point | null)> = []; let data: Array<number | Point | null> = [];
if (this.hideZero) { if (this.hideZero) {
data = [...this.values[index].map(value => value === 0 ? null : value)]; data = [...this.values[index].map((value) => (value === 0 ? null : value))];
} else { } else {
data = [...this.values[index]]; data = [...this.values[index]];
} }
@@ -54,7 +49,7 @@ export class LineChartComponent implements OnChanges {
borderColor: this.colors.borderColor[index], borderColor: this.colors.borderColor[index],
borderWidth: 2, borderWidth: 2,
cubicInterpolationMode: 'monotone', cubicInterpolationMode: 'monotone',
tension: 0 tension: 0,
}; };
this.chartConfig.lineChartData.datasets!.push(dataset); this.chartConfig.lineChartData.datasets!.push(dataset);
}); });
@@ -7,29 +7,24 @@ import { LineConfig } from '@models';
@Component({ @Component({
selector: 'app-linearea-chart', selector: 'app-linearea-chart',
standalone: true, imports: [BaseChartDirective],
imports: [ templateUrl: './linearea-chart.component.html',
BaseChartDirective
],
templateUrl: './linearea-chart.component.html'
}) })
export class LineAreaChartComponent implements OnChanges { export class LineAreaChartComponent implements OnChanges {
public displayCharts = false; public displayCharts = false;
public chartConfig: LineConfig = this._utilitiesService.getStackedLineAreaChartConfig(); public chartConfig: LineConfig = this._utilitiesService.getStackedLineAreaChartConfig();
constructor( constructor(private _utilitiesService: UtilitiesService) {}
private _utilitiesService: UtilitiesService
) { }
@Input() headers: string[] = []; @Input() headers: string[] = [];
@Input() names: string[] = []; @Input() names: string[] = [];
@Input() values: Array<Array<number>> = []; @Input() values: Array<Array<number>> = [];
@Input() colors: { @Input() colors: {
backgroundColor: string[], backgroundColor: string[];
borderColor: string[] borderColor: string[];
} = { } = {
backgroundColor: this._utilitiesService.getSeriesColors(0.8), backgroundColor: this._utilitiesService.getSeriesColors(0.8),
borderColor: this._utilitiesService.getSeriesColors(1) borderColor: this._utilitiesService.getSeriesColors(1),
}; };
@Input() legend: boolean = false; @Input() legend: boolean = false;
@@ -53,7 +48,7 @@ export class LineAreaChartComponent implements OnChanges {
fill: fill, fill: fill,
//stepped: true, //stepped: true,
cubicInterpolationMode: 'monotone', cubicInterpolationMode: 'monotone',
tension: 0 tension: 0,
}; };
this.chartConfig.lineChartData.datasets!.push(dataset); this.chartConfig.lineChartData.datasets!.push(dataset);
}); });
@@ -7,29 +7,24 @@ import { DoughnutConfig } from '@models';
@Component({ @Component({
selector: 'app-pie-chart', selector: 'app-pie-chart',
standalone: true, imports: [BaseChartDirective],
imports: [ templateUrl: './pie-chart.component.html',
BaseChartDirective
],
templateUrl: './pie-chart.component.html'
}) })
export class PieChartComponent implements OnChanges { export class PieChartComponent implements OnChanges {
public displayCharts = false; public displayCharts = false;
public chartConfig: DoughnutConfig = this._utilitiesService.getDoughnutChartConfig(); public chartConfig: DoughnutConfig = this._utilitiesService.getDoughnutChartConfig();
constructor( constructor(private _utilitiesService: UtilitiesService) {}
private _utilitiesService: UtilitiesService
) { }
@Input() names: string[] = []; @Input() names: string[] = [];
@Input() values: number[] = []; @Input() values: number[] = [];
@Input() headers: string[] = []; @Input() headers: string[] = [];
@Input() colors: { @Input() colors: {
backgroundColor: string[], backgroundColor: string[];
borderColor: string[] borderColor: string[];
} = { } = {
backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'), backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'),
borderColor: this._utilitiesService.getSeriesColors(1, 'all') borderColor: this._utilitiesService.getSeriesColors(1, 'all'),
}; };
@Input() legend: boolean = false; @Input() legend: boolean = false;
@@ -2,13 +2,10 @@ import { Component, Input, AfterContentChecked } from '@angular/core';
import { NgIf, NgFor } from '@angular/common'; import { NgIf, NgFor } from '@angular/common';
@Component({ @Component({
standalone: true, imports: [NgIf, NgFor],
imports: [
NgIf, NgFor
],
selector: 'app-history-table', selector: 'app-history-table',
templateUrl: './history-table.component.html', templateUrl: './history-table.component.html',
styleUrls: [] styleUrls: [],
}) })
export class HistoryTableComponent implements AfterContentChecked { export class HistoryTableComponent implements AfterContentChecked {
public seriesColTotal: number[] = []; public seriesColTotal: number[] = [];
@@ -38,7 +35,7 @@ export class HistoryTableComponent implements AfterContentChecked {
this.seriesColTotal = [...values]; this.seriesColTotal = [...values];
this.rows.forEach((row: number[], rowIndex: number) => { this.rows.forEach((row: number[], rowIndex: number) => {
row.forEach((value: number, index: number) => { row.forEach((value: number, index: number) => {
this.seriesColTotal[index] = (this.seriesColTotal[index] + this.rows[rowIndex][index]); this.seriesColTotal[index] = this.seriesColTotal[index] + this.rows[rowIndex][index];
}); });
this.grandTotal = this.seriesColTotal.reduce((partialSum, a) => partialSum + a, 0); this.grandTotal = this.seriesColTotal.reduce((partialSum, a) => partialSum + a, 0);
}); });
@@ -13,7 +13,6 @@ import { JumpPreviewComponent } from './jump-preview.component';
@Component({ @Component({
selector: 'app-jump-list', selector: 'app-jump-list',
templateUrl: './jump-list.component.html', templateUrl: './jump-list.component.html',
standalone: true,
imports: [ imports: [
NgClass, NgClass,
DatePipe, DatePipe,
@@ -21,8 +20,8 @@ import { JumpPreviewComponent } from './jump-preview.component';
MatButtonModule, MatButtonModule,
RouterLink, RouterLink,
MatIconModule, MatIconModule,
JumpPreviewComponent JumpPreviewComponent,
] ],
}) })
export class JumpListComponent implements OnInit, OnDestroy { export class JumpListComponent implements OnInit, OnDestroy {
private _jumps: Subscription = new Subscription(); private _jumps: Subscription = new Subscription();
@@ -35,9 +34,7 @@ export class JumpListComponent implements OnInit, OnDestroy {
pages: Array<number> = [1]; pages: Array<number> = [1];
lastUpdate: Date = new Date(); lastUpdate: Date = new Date();
constructor( constructor(private jumpsService: JumpsService) {}
private jumpsService: JumpsService
) { }
@Input() limit = 0; @Input() limit = 0;
@Input() refresh = 30000; @Input() refresh = 30000;
@@ -70,7 +67,7 @@ export class JumpListComponent implements OnInit, OnDestroy {
runQuery() { runQuery() {
if (this.limit) { if (this.limit) {
this.query.filters.limit = this.limit; this.query.filters.limit = this.limit;
this.query.filters.offset = (this.limit * (this.currentPage - 1)); this.query.filters.offset = this.limit * (this.currentPage - 1);
} }
const jumps$: Observable<JumpList> = this.jumpsService.query(this.query); const jumps$: Observable<JumpList> = this.jumpsService.query(this.query);
@@ -85,7 +82,7 @@ export class JumpListComponent implements OnInit, OnDestroy {
}, },
error: (err) => { error: (err) => {
this.errors = err; this.errors = err;
} },
}); });
} }
@@ -6,10 +6,9 @@ import { Jump } from '@models';
@Component({ @Component({
selector: 'app-jump-meta', selector: 'app-jump-meta',
standalone: true, imports: [RouterLink, DatePipe],
imports: [ RouterLink, DatePipe ],
styleUrl: './jump-meta.component.scss', styleUrl: './jump-meta.component.scss',
templateUrl: './jump-meta.component.html' templateUrl: './jump-meta.component.html',
}) })
export class JumpMetaComponent { export class JumpMetaComponent {
@Input() jump!: Jump; @Input() jump!: Jump;
@@ -12,14 +12,9 @@ import { JumpsService } from '@services';
@Component({ @Component({
selector: 'app-jump-preview', selector: 'app-jump-preview',
standalone: true, imports: [DecimalPipe, RouterLink, MatDividerModule, MatButtonModule, MatCardModule, JumpMetaComponent],
imports: [
DecimalPipe, RouterLink,
MatDividerModule, MatButtonModule, MatCardModule,
JumpMetaComponent
],
styleUrl: './jump-preview.component.scss', styleUrl: './jump-preview.component.scss',
templateUrl: './jump-preview.component.html' templateUrl: './jump-preview.component.html',
}) })
export class JumpPreviewComponent implements OnDestroy { export class JumpPreviewComponent implements OnDestroy {
@Input() jump!: Jump; @Input() jump!: Jump;
@@ -30,8 +25,8 @@ export class JumpPreviewComponent implements OnDestroy {
constructor( constructor(
private router: Router, private router: Router,
private jumpsService: JumpsService private jumpsService: JumpsService,
) { } ) {}
ngOnDestroy() { ngOnDestroy() {
this._jump.unsubscribe(); this._jump.unsubscribe();
@@ -43,7 +38,7 @@ export class JumpPreviewComponent implements OnDestroy {
this._jump = jump$.subscribe({ this._jump = jump$.subscribe({
next: () => { next: () => {
this.router.navigateByUrl('/'); this.router.navigateByUrl('/');
} },
}); });
} }
} }
@@ -1,4 +1,13 @@
import { AfterContentChecked, Component, EventEmitter, Input, Output, OnChanges, OnDestroy, ViewChild } from '@angular/core'; import {
AfterContentChecked,
Component,
EventEmitter,
Input,
Output,
OnChanges,
OnDestroy,
ViewChild,
} from '@angular/core';
import { CommonModule, DecimalPipe, DatePipe } from '@angular/common'; import { CommonModule, DecimalPipe, DatePipe } from '@angular/common';
import { UntypedFormBuilder, UntypedFormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms'; import { UntypedFormBuilder, UntypedFormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { Router, RouterLink } from '@angular/router'; import { Router, RouterLink } from '@angular/router';
@@ -15,29 +24,68 @@ import { MatProgressBarModule } from '@angular/material/progress-bar';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatSort, MatSortModule } from '@angular/material/sort'; import { MatSort, MatSortModule } from '@angular/material/sort';
import { MatTableDataSource, MatTableModule } from '@angular/material/table'; import { MatTableDataSource, MatTableModule } from '@angular/material/table';
import { MatSnackBar, MatSnackBarHorizontalPosition, MatSnackBarModule, MatSnackBarVerticalPosition } from '@angular/material/snack-bar'; import {
MatSnackBar,
MatSnackBarHorizontalPosition,
MatSnackBarModule,
MatSnackBarVerticalPosition,
} from '@angular/material/snack-bar';
import { Observable, Subscription } from 'rxjs'; import { Observable, Subscription } from 'rxjs';
import { take } from 'rxjs/operators'; import { take } from 'rxjs/operators';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
import { FrenchPaginator } from '@components/shared/french-paginator.component'; import { FrenchPaginator } from '@components/shared/french-paginator.component';
import { ColumnDefinition, Errors, Jump, JumpByDay, JumpFile, JumpFileType, JumpList, JumpListConfig, jumpColumns } from '@models'; import {
ColumnDefinition,
Errors,
Jump,
JumpByDay,
JumpFile,
JumpFileType,
JumpList,
JumpListConfig,
jumpColumns,
} from '@models';
import { JumpsService, JumpTableService } from '@services'; import { JumpsService, JumpTableService } from '@services';
import { JumpAddDialogComponent, JumpDeleteDialogComponent, JumpEditDialogComponent, JumpViewDialogComponent } from '@components/logbook/dialogs' import {
JumpAddDialogComponent,
JumpDeleteDialogComponent,
JumpEditDialogComponent,
JumpViewDialogComponent,
} from '@components/logbook/dialogs';
@Component({ @Component({
standalone: true,
imports: [ imports: [
CommonModule, DecimalPipe, DatePipe, RouterLink, FormsModule, ReactiveFormsModule, NgxSkeletonLoaderModule, CommonModule,
MatButtonModule, MatCardModule, MatDialogModule, DecimalPipe,
MatFormFieldModule, MatIconModule, MatInputModule, MatNativeDateModule, MatMenuModule, DatePipe,
MatPaginatorModule, MatProgressBarModule, MatProgressSpinnerModule, MatSnackBarModule, MatSortModule, MatTableModule, RouterLink,
JumpAddDialogComponent, JumpDeleteDialogComponent, JumpEditDialogComponent, JumpViewDialogComponent FormsModule,
ReactiveFormsModule,
NgxSkeletonLoaderModule,
MatButtonModule,
MatCardModule,
MatDialogModule,
MatFormFieldModule,
MatIconModule,
MatInputModule,
MatNativeDateModule,
MatMenuModule,
MatPaginatorModule,
MatProgressBarModule,
MatProgressSpinnerModule,
MatSnackBarModule,
MatSortModule,
MatTableModule,
JumpAddDialogComponent,
JumpDeleteDialogComponent,
JumpEditDialogComponent,
JumpViewDialogComponent,
], ],
selector: 'app-jump-table', selector: 'app-jump-table',
styleUrl: './jump-table.component.scss', styleUrl: './jump-table.component.scss',
templateUrl: './jump-table.component.html', templateUrl: './jump-table.component.html',
providers: [{provide: MatPaginatorIntl, useClass: FrenchPaginator}] providers: [{ provide: MatPaginatorIntl, useClass: FrenchPaginator }],
}) })
export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChecked { export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChecked {
private _jumps: Subscription = new Subscription(); private _jumps: Subscription = new Subscription();
@@ -57,10 +105,18 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe
'zone', 'files', 'actions' 'zone', 'files', 'actions'
];*/ ];*/
public displayedColumns: string[] = [ public displayedColumns: string[] = [
'numero', 'date', 'lieu', 'aeronef', 'numero',
'hauteur', 'voile', 'categorie', 'date',
'participants', 'zone', 'accessoires', 'lieu',
'files', 'actions' 'aeronef',
'hauteur',
'voile',
'categorie',
'participants',
'zone',
'accessoires',
'files',
'actions',
]; ];
//public displayedColumns: string[] = jumpColumns.map((col) => col.key) //public displayedColumns: string[] = jumpColumns.map((col) => col.key)
public columnsSchema: Array<ColumnDefinition> = jumpColumns; public columnsSchema: Array<ColumnDefinition> = jumpColumns;
@@ -81,12 +137,12 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe
private _jumpTableService: JumpTableService, private _jumpTableService: JumpTableService,
private dialog: MatDialog, private dialog: MatDialog,
private fb: UntypedFormBuilder, private fb: UntypedFormBuilder,
private snackBar: MatSnackBar private snackBar: MatSnackBar,
) { ) {
this._resetErrors(); this._resetErrors();
this.searchForm = this.fb.group({ this.searchForm = this.fb.group({
//numero: ['', Validators.required] //numero: ['', Validators.required]
numero: '' numero: '',
}); });
} }
@@ -116,7 +172,7 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe
ngOnDestroy() { ngOnDestroy() {
this._jumps.unsubscribe(); this._jumps.unsubscribe();
this._subscriptions.forEach(subscription => { this._subscriptions.forEach((subscription) => {
subscription.unsubscribe(); subscription.unsubscribe();
}); });
} }
@@ -139,7 +195,7 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe
if (this.limit) { if (this.limit) {
this._query.filters.limit = this.limit; this._query.filters.limit = this.limit;
this._query.filters.offset = (this.limit * (this._currentPage - 1)); this._query.filters.offset = this.limit * (this._currentPage - 1);
} else { } else {
this._query.filters.limit = 0; this._query.filters.limit = 0;
this._query.filters.offset = 0; this._query.filters.offset = 0;
@@ -172,7 +228,7 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe
}, },
error: (err) => { error: (err) => {
this.errors = err; this.errors = err;
} },
}); });
} }
@@ -185,19 +241,20 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe
//config.filters.dateRangeEnd = `${year}-12-31 23:59:59`; //config.filters.dateRangeEnd = `${year}-12-31 23:59:59`;
config.filters.dateRangeEnd = '2024-12-31 23:59:59'; config.filters.dateRangeEnd = '2024-12-31 23:59:59';
//console.log(config.filters); //console.log(config.filters);
const subscription: Subscription = this._jumpsService.getAllByDay(config) const subscription: Subscription = this._jumpsService
.getAllByDay(config)
.pipe(take(1)) .pipe(take(1))
.subscribe({ .subscribe({
next: (days) => { next: (days) => {
this._resetErrors(); this._resetErrors();
//console.log('getAllByDay : ', days); //console.log('getAllByDay : ', days);
days.forEach(day => { days.forEach((day) => {
this.loadSkydiverIdJumps(day, config); this.loadSkydiverIdJumps(day, config);
}); });
}, },
error: (err) => { error: (err) => {
this.errors = err; this.errors = err;
} },
}); });
this._subscriptions.push(subscription); this._subscriptions.push(subscription);
} }
@@ -205,37 +262,52 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe
loadSkydiverIdJumps(day: JumpByDay, config: JumpListConfig) { loadSkydiverIdJumps(day: JumpByDay, config: JumpListConfig) {
config.filters.dateRangeStart = `${day.jumps[0].date!.substring(0, 10)} 00:00:00`; 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`; config.filters.dateRangeEnd = `${day.jumps[0].date!.substring(0, 10)} 23:59:59`;
const subscription: Subscription = this._jumpsService.getAllFromSkydiverIdApi(config) const subscription: Subscription = this._jumpsService
.getAllFromSkydiverIdApi(config)
.pipe(take(1)) .pipe(take(1))
.subscribe({ .subscribe({
next: (data) => { next: (data) => {
if (data.items.length) { if (data.items.length) {
const diff = day.count - data.items.length; const diff = day.count - data.items.length;
if (diff < 0) { if (diff < 0) {
console.error(`${diff} ${diff > 1 ? 'données' : 'donnée'} altimètre de trop le ${day.jumps[0].date!.substring(0, 10)}`); console.error(
`${diff} ${diff > 1 ? 'données' : 'donnée'} altimètre de trop le ${day.jumps[0].date!.substring(0, 10)}`,
);
} else { } else {
if (diff > 0) { 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.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); 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) => { data.items.map((jump, index) => {
const file: JumpFile = { const file: JumpFile = {
name: jump.name, name: jump.name,
path: `/Volumes/Storage/Skydive/X2_Logs/${day.jumps[index].date!.substring(0, 4)}/`, path: `/Volumes/Storage/Skydive/X2_Logs/${day.jumps[index].date!.substring(0, 4)}/`,
type: JumpFileType.CSV type: JumpFileType.CSV,
} as JumpFile; } as JumpFile;
this._subscriptions.push( this._subscriptions.push(
this._jumpsService.saveX2Data(day.jumps[index].slug!, file, jump) this._jumpsService
.saveX2Data(day.jumps[index].slug!, file, jump)
.pipe(take(1)) .pipe(take(1))
.subscribe({ .subscribe({
next: (jump) => { next: (jump) => {
this._resetErrors(); this._resetErrors();
console.log(`Le fichier ${file.name} a été ajouté au saut n°${jump.numero} !`, 'OK'); console.log(
`Le fichier ${file.name} a été ajouté au saut n°${jump.numero} !`,
'OK',
);
}, },
error: (err) => { error: (err) => {
this.errors = err; this.errors = err;
} },
}) }),
); );
return jump; return jump;
}); });
@@ -249,22 +321,23 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe
error: (err) => { error: (err) => {
console.error('getAllFromSkydiverIdApi error'); console.error('getAllFromSkydiverIdApi error');
this.errors = err; this.errors = err;
} },
}); });
this._subscriptions.push(subscription); this._subscriptions.push(subscription);
} }
updateJumps(jumps: Array<Jump>) { updateJumps(jumps: Array<Jump>) {
jumps.map(jump => { jumps.map((jump) => {
jump.files = []; jump.files = [];
if (jump.dossier !== "" && jump.video !== "") { if (jump.dossier !== '' && jump.video !== '') {
const file: JumpFile = { const file: JumpFile = {
name: jump.video!, name: jump.video!,
path: jump.dossier!, path: jump.dossier!,
type: JumpFileType.VIDEO type: JumpFileType.VIDEO,
} as JumpFile; } as JumpFile;
this._subscriptions.push( this._subscriptions.push(
this._jumpsService.saveFile(jump.slug, file) this._jumpsService
.saveFile(jump.slug, file)
.pipe(take(1)) .pipe(take(1))
.subscribe({ .subscribe({
next: (file) => { next: (file) => {
@@ -274,8 +347,8 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe
}, },
error: (err) => { error: (err) => {
this.errors = err; this.errors = err;
} },
}) }),
); );
} }
return jump; return jump;
@@ -283,26 +356,30 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe
} }
getKmlJumpFiles(jumps: Array<Jump>) { getKmlJumpFiles(jumps: Array<Jump>) {
jumps.map(jump => { jumps.map((jump) => {
if (jump.x2data !== null) { 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`); //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 = { const file: JumpFile = {
name: jump.x2data.name.substring(0, -4) + '.kml', name: jump.x2data.name.substring(0, -4) + '.kml',
path: `/X2_Kmls/${jump.date.substring(0, 4)}/`, path: `/X2_Kmls/${jump.date.substring(0, 4)}/`,
type: JumpFileType.KML type: JumpFileType.KML,
} as JumpFile; } as JumpFile;
this._subscriptions.push( this._subscriptions.push(
this._jumpsService.saveKml(jump.slug, file) this._jumpsService
.saveKml(jump.slug, file)
.pipe(take(1)) .pipe(take(1))
.subscribe({ .subscribe({
next: (file) => { next: (file) => {
this._resetErrors(); this._resetErrors();
console.log(`Le fichier ${file.path}${file.name} a été ajouté au saut n°${jump.numero} !`, 'OK'); console.log(
`Le fichier ${file.path}${file.name} a été ajouté au saut n°${jump.numero} !`,
'OK',
);
}, },
error: (err) => { error: (err) => {
this.errors = err; this.errors = err;
} },
}) }),
); );
} }
return jump; return jump;
@@ -312,50 +389,53 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe
deleteJump(slug: string) { deleteJump(slug: string) {
this.isDeleting = true; this.isDeleting = true;
this._subscriptions.push( this._subscriptions.push(
this._jumpsService.destroy(slug) this._jumpsService
.destroy(slug)
.pipe(take(1)) .pipe(take(1))
.subscribe(() => { .subscribe(() => {
this.router.navigateByUrl('/'); this.router.navigateByUrl('/');
}) }),
); );
} }
openDeleteDialog(jump: Jump): void { openDeleteDialog(jump: Jump): void {
const dialogRef = this.dialog.open(JumpDeleteDialogComponent, { const dialogRef = this.dialog.open(JumpDeleteDialogComponent, {
width: '60vw', width: '60vw',
data: jump data: jump,
}); });
this._subscriptions.push( this._subscriptions.push(
dialogRef.afterClosed() dialogRef
.afterClosed()
.pipe(take(1)) .pipe(take(1))
.subscribe(result => { .subscribe((result) => {
if (result != undefined) { if (result != undefined) {
this._onDelete(result.slug); this._onDelete(result.slug);
} }
}) }),
); );
} }
openEditDialog(jump: Jump): void { openEditDialog(jump: Jump): void {
const dialogRef = this.dialog.open(JumpEditDialogComponent, { const dialogRef = this.dialog.open(JumpEditDialogComponent, {
width: '70vw', width: '70vw',
data: jump data: jump,
}); });
this._subscriptions.push( this._subscriptions.push(
dialogRef.afterClosed() dialogRef
.afterClosed()
.pipe(take(1)) .pipe(take(1))
.subscribe(result => { .subscribe((result) => {
if (result != undefined) { if (result != undefined) {
this._onEdit(result); this._onEdit(result);
} }
}) }),
); );
} }
openViewDialog(jump: Jump): void { openViewDialog(jump: Jump): void {
const dialogRef = this.dialog.open(JumpViewDialogComponent, { const dialogRef = this.dialog.open(JumpViewDialogComponent, {
width: '60vw', width: '60vw',
data: jump data: jump,
}); });
dialogRef.afterClosed(); dialogRef.afterClosed();
} }
@@ -379,7 +459,8 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe
try { try {
this.isDeleting = true; this.isDeleting = true;
this._subscriptions.push( this._subscriptions.push(
this._jumpsService.destroy(slug) this._jumpsService
.destroy(slug)
.pipe(take(1)) .pipe(take(1))
.subscribe({ .subscribe({
next: () => { next: () => {
@@ -391,8 +472,8 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe
}, },
error: (err) => { error: (err) => {
this.errors = err; this.errors = err;
} },
}) }),
); );
} catch (error) { } catch (error) {
console.error(error); console.error(error);
@@ -403,7 +484,8 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe
try { try {
this.isSubmitting = true; this.isSubmitting = true;
this._subscriptions.push( this._subscriptions.push(
this._jumpsService.update(jump) this._jumpsService
.update(jump)
.pipe(take(1)) .pipe(take(1))
.subscribe({ .subscribe({
next: (jump) => { next: (jump) => {
@@ -416,8 +498,8 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe
error: (err) => { error: (err) => {
this.errors = err; this.errors = err;
this.isSubmitting = false; this.isSubmitting = false;
} },
}) }),
); );
} catch (error) { } catch (error) {
console.error(error); console.error(error);
@@ -468,5 +550,4 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe
})) }))
} }
*/ */
} }
@@ -12,11 +12,7 @@ import { HWGuildWarFortification, HWMember } from '@models';
selector: 'app-fortification-card-content', selector: 'app-fortification-card-content',
templateUrl: './fortification-card-content.component.html', templateUrl: './fortification-card-content.component.html',
styleUrl: './fortification-card-content.component.scss', styleUrl: './fortification-card-content.component.scss',
standalone: true, imports: [DecimalPipe, MatCardModule, MatChipsModule, MatIconModule],
imports: [
DecimalPipe,
MatCardModule, MatChipsModule, MatIconModule
]
}) })
export class FortificationCardContentComponent { export class FortificationCardContentComponent {
public data: HWGuildWarFortification = {} as HWGuildWarFortification; public data: HWGuildWarFortification = {} as HWGuildWarFortification;
@@ -10,13 +10,9 @@ import guildData from 'src/files-data/hw-guild-data.json'; // page Membres
@Component({ @Component({
selector: 'app-guild-card', selector: 'app-guild-card',
standalone: true, imports: [DatePipe, DecimalPipe, MatCardModule, MatDividerModule, MatIconModule],
imports: [
DatePipe, DecimalPipe,
MatCardModule, MatDividerModule, MatIconModule
],
templateUrl: './guild-card.component.html', templateUrl: './guild-card.component.html',
styleUrl: './guild-card.component.scss' styleUrl: './guild-card.component.scss',
}) })
export class GuildCardComponent implements OnInit { export class GuildCardComponent implements OnInit {
public guildData: HWGuildData = {} as HWGuildData; public guildData: HWGuildData = {} as HWGuildData;
@@ -23,21 +23,29 @@ export class StepperIntl extends MatStepperIntl {
} }
@Component({ @Component({
selector: 'app-guildraids-log', selector: 'app-guildraids-log',
standalone: true,
providers: [ providers: [
{ {
provide: STEPPER_GLOBAL_OPTIONS, provide: STEPPER_GLOBAL_OPTIONS,
useValue: {displayDefaultIndicatorType: false}, useValue: { displayDefaultIndicatorType: false },
}, },
], ],
imports: [ imports: [
DatePipe, DecimalPipe, FormsModule, ReactiveFormsModule, DatePipe,
MatButtonModule, MatCardModule, MatDatepickerModule, MatDividerModule, DecimalPipe,
MatFormFieldModule, MatIconModule, MatInputModule, MatTooltipModule, FormsModule,
MatStepperModule ReactiveFormsModule,
MatButtonModule,
MatCardModule,
MatDatepickerModule,
MatDividerModule,
MatFormFieldModule,
MatIconModule,
MatInputModule,
MatTooltipModule,
MatStepperModule,
], ],
templateUrl: './guildraids-log.component.html', templateUrl: './guildraids-log.component.html',
styleUrl: './guildraids-log.component.scss' styleUrl: './guildraids-log.component.scss',
}) })
export class GuildraidsLogComponent implements OnInit { export class GuildraidsLogComponent implements OnInit {
public now: Date; public now: Date;
@@ -49,18 +57,16 @@ export class GuildraidsLogComponent implements OnInit {
private _matStepperIntl = inject(MatStepperIntl); private _matStepperIntl = inject(MatStepperIntl);
private _guildRaids: HWGuildRaid[] = []; private _guildRaids: HWGuildRaid[] = [];
private _raidStages: HWGuildRaidStage[] = [ private _raidStages: HWGuildRaidStage[] = [
{num: 1, name: 'Stage 1', maxPower: 350000, duration: 8, startTime: 0, endTime: 0}, { num: 1, name: 'Stage 1', maxPower: 350000, duration: 8, startTime: 0, endTime: 0 },
{num: 2, name: 'Stage 2', maxPower: 550000, duration: 8, startTime: 0, endTime: 0}, { num: 2, name: 'Stage 2', maxPower: 550000, duration: 8, startTime: 0, endTime: 0 },
{num: 3, name: 'Stage 3', maxPower: 0, duration: 0, startTime: 0, endTime: 0} { num: 3, name: 'Stage 3', maxPower: 0, duration: 0, startTime: 0, endTime: 0 },
]; ];
@Input() set members(value: HWMember[]) { @Input() set members(value: HWMember[]) {
this.guildMembers = value; this.guildMembers = value;
} }
constructor( constructor(private fb: FormBuilder) {
private fb: FormBuilder
) {
this.now = new Date(); this.now = new Date();
const raidsDate = new Date(); const raidsDate = new Date();
const startHour = 4; const startHour = 4;
@@ -71,7 +77,7 @@ export class GuildraidsLogComponent implements OnInit {
maxPower: 350, maxPower: 350,
duration: 8, duration: 8,
startTime: [raidsDate.getTime(), Validators.required], startTime: [raidsDate.getTime(), Validators.required],
endTime: 0 endTime: 0,
}; };
this.raidsForm = this.fb.group(controlsConfig); this.raidsForm = this.fb.group(controlsConfig);
} }
@@ -82,11 +88,11 @@ export class GuildraidsLogComponent implements OnInit {
raidsDate.setHours(startHour, 0, 0, 0); raidsDate.setHours(startHour, 0, 0, 0);
this._raidStages[0].startTime = raidsDate.getTime(); this._raidStages[0].startTime = raidsDate.getTime();
raidsDate.setHours((startHour + this._raidStages[0].duration), 0, 0, 0); raidsDate.setHours(startHour + this._raidStages[0].duration, 0, 0, 0);
this._raidStages[0].endTime = raidsDate.getTime(); this._raidStages[0].endTime = raidsDate.getTime();
this._raidStages[1].startTime = raidsDate.getTime(); this._raidStages[1].startTime = raidsDate.getTime();
raidsDate.setHours((startHour + this._raidStages[0].duration + this._raidStages[1].duration), 0, 0, 0); raidsDate.setHours(startHour + this._raidStages[0].duration + this._raidStages[1].duration, 0, 0, 0);
this._raidStages[1].endTime = raidsDate.getTime(); this._raidStages[1].endTime = raidsDate.getTime();
this._raidStages[2].startTime = raidsDate.getTime(); this._raidStages[2].startTime = raidsDate.getTime();
@@ -101,19 +107,19 @@ export class GuildraidsLogComponent implements OnInit {
data.raids = []; data.raids = [];
data.raidsInfo = { data.raidsInfo = {
variationAvg: 0, variationAvg: 0,
variationSum: 0 variationSum: 0,
}; };
return data; return data;
}); });
for (const member of Object.entries(guildRaids)) { for (const member of Object.entries(guildRaids)) {
const index = this.guildMembers.findIndex(item => item.id === member[0]); const index = this.guildMembers.findIndex((item) => item.id === member[0]);
const memberRaids: HWGuildRaid[] = []; const memberRaids: HWGuildRaid[] = [];
if (index !== -1) { if (index !== -1) {
for (const data of Object.entries(member[1])) { for (const data of Object.entries(member[1])) {
const raid: HWGuildRaid = {} as HWGuildRaid; const raid: HWGuildRaid = {} as HWGuildRaid;
Object.assign(raid, data[1]); Object.assign(raid, data[1]);
const startTime: number = (parseInt(raid.startTime) * 1000); const startTime: number = parseInt(raid.startTime) * 1000;
if (this._guildRaids.length === 0) { if (this._guildRaids.length === 0) {
this._setStagesTime(startTime); this._setStagesTime(startTime);
} }
@@ -139,14 +145,14 @@ export class GuildraidsLogComponent implements OnInit {
const attacker: HWGuildRaidAttacker = { const attacker: HWGuildRaidAttacker = {
id: item[1].id, id: item[1].id,
power: item[1].power, power: item[1].power,
type: item[1].type type: item[1].type,
} as HWGuildRaidAttacker; } as HWGuildRaidAttacker;
raid.power += attacker.power; raid.power += attacker.power;
raid.attackers.push(attacker); raid.attackers.push(attacker);
} }
let percent = 0; let percent = 0;
if (raid.stage.maxPower > 0) { if (raid.stage.maxPower > 0) {
percent = (((raid.power / raid.stage.maxPower) - 1) * 100); percent = (raid.power / raid.stage.maxPower - 1) * 100;
} }
let color = 'default'; let color = 'default';
let value = 0; let value = 0;
@@ -158,12 +164,12 @@ export class GuildraidsLogComponent implements OnInit {
} else if (percent > 5) { } else if (percent > 5) {
color = 'orange'; color = 'orange';
} }
value = (raid.power - raid.stage.maxPower) value = raid.power - raid.stage.maxPower;
} }
raid.variation = { raid.variation = {
value: value, value: value,
percent: percent, percent: percent,
color: color color: color,
}; };
raid.tooltip = Math.floor(raid.variation.value / 1000) + 'k'; raid.tooltip = Math.floor(raid.variation.value / 1000) + 'k';
//console.log(raid.attackers); //console.log(raid.attackers);
@@ -172,17 +178,24 @@ export class GuildraidsLogComponent implements OnInit {
this._guildRaids.push(raid); this._guildRaids.push(raid);
} }
this.guildMembers[index].raids = memberRaids; this.guildMembers[index].raids = memberRaids;
const varSum = memberRaids.reduce((accumulator, currentValue) => accumulator + currentValue.variation.percent, 0); const varSum = memberRaids.reduce(
(accumulator, currentValue) => accumulator + currentValue.variation.percent,
0,
);
this.guildMembers[index].raidsInfo = { this.guildMembers[index].raidsInfo = {
variationAvg: (varSum / memberRaids.length), variationAvg: varSum / memberRaids.length,
variationSum: varSum variationSum: varSum,
}; };
} }
} }
this._guildRaids.sort((a, b) => (a.startTime < b.startTime ? -1 : 1)).map((data) => { this._guildRaids
.sort((a, b) => (a.startTime < b.startTime ? -1 : 1))
.map((data) => {
return data; return data;
}); });
this.guildMembers.sort((a, b) => (a.raidsInfo.variationAvg > b.raidsInfo.variationAvg ? -1 : 1));/*.map((data) => { this.guildMembers.sort((a, b) =>
a.raidsInfo.variationAvg > b.raidsInfo.variationAvg ? -1 : 1,
); /*.map((data) => {
console.log(data.name, data.raidsInfo.variationAvg, data.raids.length); console.log(data.name, data.raidsInfo.variationAvg, data.raids.length);
return data; return data;
});*/ });*/
@@ -190,11 +203,13 @@ export class GuildraidsLogComponent implements OnInit {
public getMembers(): HWMember[] { public getMembers(): HWMember[] {
//return this.guildMembers; //return this.guildMembers;
return this.minVarPct ? this.guildMembers.filter(member => (member.raidsInfo.variationAvg >= this.minVarPct) === true) : this.guildMembers; return this.minVarPct
? this.guildMembers.filter((member) => member.raidsInfo.variationAvg >= this.minVarPct === true)
: this.guildMembers;
} }
public getRaidsLog(stageNum: number): HWGuildRaid[] { public getRaidsLog(stageNum: number): HWGuildRaid[] {
return this._guildRaids.filter(raid => (raid.stage.num === stageNum) === true); return this._guildRaids.filter((raid) => (raid.stage.num === stageNum) === true);
} }
public getStagesTime(stageNum: number): HWGuildRaidStage { public getStagesTime(stageNum: number): HWGuildRaidStage {
@@ -208,7 +223,5 @@ export class GuildraidsLogComponent implements OnInit {
} }
} }
submitForm(): void { submitForm(): void {}
}
} }
@@ -6,8 +6,13 @@ import { MatIconModule } from '@angular/material/icon';
import { FortificationCardContentComponent } from '../fortification-card-content/fortification-card-content.component'; import { FortificationCardContentComponent } from '../fortification-card-content/fortification-card-content.component';
import { import {
HWGuildWarEnemySlot, HWGuildWarEnemyTeam, HWGuildWarFortification, HWGuildWarEnemySlot,
HWGuildWarHeroTeam, HWGuildWarTitanTeam, HWGuildWarSlots, HWMember HWGuildWarEnemyTeam,
HWGuildWarFortification,
HWGuildWarHeroTeam,
HWGuildWarTitanTeam,
HWGuildWarSlots,
HWMember,
} from '@models'; } from '@models';
/* JSON data */ /* JSON data */
@@ -18,14 +23,9 @@ import guildWarSlots from 'src/files-data/hw-guild-war-slots.json'; // no pages
@Component({ @Component({
selector: 'app-guildwar-attack', selector: 'app-guildwar-attack',
standalone: true, imports: [DatePipe, DecimalPipe, MatCardModule, MatDividerModule, MatIconModule, FortificationCardContentComponent],
imports: [
DatePipe, DecimalPipe,
MatCardModule, MatDividerModule, MatIconModule,
FortificationCardContentComponent
],
templateUrl: './guildwar-attack.component.html', templateUrl: './guildwar-attack.component.html',
styleUrl: './guildwar-attack.component.scss' styleUrl: './guildwar-attack.component.scss',
}) })
export class GuildwarAttackComponent implements OnInit { export class GuildwarAttackComponent implements OnInit {
private _championsByPower: HWMember[] = []; private _championsByPower: HWMember[] = [];
@@ -35,12 +35,13 @@ export class GuildwarAttackComponent implements OnInit {
public title = 'Fortifications'; public title = 'Fortifications';
public subtitle = 'Guild War Attack'; public subtitle = 'Guild War Attack';
public now = new Date(); public now = new Date();
public warInfo: { day: number, clanEnemyName: string, endTime: number, nextWarTime: number, nextLockTime: number } = { public warInfo: { day: number; clanEnemyName: string; endTime: number; nextWarTime: number; nextLockTime: number } =
{
day: 0, day: 0,
clanEnemyName: '', clanEnemyName: '',
endTime: 0, endTime: 0,
nextWarTime: 0, nextWarTime: 0,
nextLockTime: 0 nextLockTime: 0,
}; };
@Input() set members(value: HWMember[]) { @Input() set members(value: HWMember[]) {
@@ -50,9 +51,9 @@ export class GuildwarAttackComponent implements OnInit {
ngOnInit() { ngOnInit() {
this.warInfo.day = parseInt(guildWarInfo.day); this.warInfo.day = parseInt(guildWarInfo.day);
this.warInfo.clanEnemyName = guildWarInfo.enemyClan.title; this.warInfo.clanEnemyName = guildWarInfo.enemyClan.title;
this.warInfo.endTime = (guildWarInfo.endTime * 1000); this.warInfo.endTime = guildWarInfo.endTime * 1000;
this.warInfo.nextWarTime = (guildWarInfo.nextWarTime * 1000); this.warInfo.nextWarTime = guildWarInfo.nextWarTime * 1000;
this.warInfo.nextLockTime = (guildWarInfo.nextLockTime * 1000); this.warInfo.nextLockTime = guildWarInfo.nextLockTime * 1000;
this._setChampionsByPower(); this._setChampionsByPower();
this._setEnemies(); this._setEnemies();
} }
@@ -81,7 +82,7 @@ export class GuildwarAttackComponent implements OnInit {
count: count, count: count,
teams: teams, teams: teams,
positions: this._enemySlots, positions: this._enemySlots,
slots: slots[name] slots: slots[name],
}; };
} }
@@ -89,10 +90,10 @@ export class GuildwarAttackComponent implements OnInit {
const teams: HWMember[] = []; const teams: HWMember[] = [];
const slots: HWGuildWarSlots = guildWarSlots.slots; const slots: HWGuildWarSlots = guildWarSlots.slots;
let count = 0; let count = 0;
slots[name].forEach(slot => { slots[name].forEach((slot) => {
let enemies: HWMember[] = []; let enemies: HWMember[] = [];
let team: HWMember = {} as HWMember; let team: HWMember = {} as HWMember;
enemies = this.guildEnemies.filter(enemy => parseInt(enemy.id) === this._enemySlots[slot]); enemies = this.guildEnemies.filter((enemy) => parseInt(enemy.id) === this._enemySlots[slot]);
if (enemies.length) { if (enemies.length) {
team = enemies[0]; team = enemies[0];
teams.push(team); teams.push(team);
@@ -115,7 +116,7 @@ export class GuildwarAttackComponent implements OnInit {
count: count, count: count,
teams: teams, teams: teams,
positions: this._enemySlots, positions: this._enemySlots,
slots: slots[name] slots: slots[name],
}; };
} }
@@ -132,8 +133,8 @@ export class GuildwarAttackComponent implements OnInit {
} else { } else {
enemy.champion = false; enemy.champion = false;
} }
enemy.heroes = { power: 0, teams: []}; enemy.heroes = { power: 0, teams: [] };
enemy.titans = { power: 0, teams: []}; enemy.titans = { power: 0, teams: [] };
//console.log(guildWarInfo.enemySlots); //console.log(guildWarInfo.enemySlots);
@@ -187,13 +188,15 @@ export class GuildwarAttackComponent implements OnInit {
return false; return false;
}); });
} }
this.guildEnemies.sort((a, b) => ((a.heroes.power + a.titans.power) > (b.heroes.power + b.titans.power) ? -1 : 1)); // Descending this.guildEnemies.sort((a, b) =>
a.heroes.power + a.titans.power > b.heroes.power + b.titans.power ? -1 : 1,
); // Descending
} }
} }
private _setChampionsByPower(): void { private _setChampionsByPower(): void {
for (const [teamId, teamValues] of Object.entries(guildWarData.teams)) { for (const [teamId, teamValues] of Object.entries(guildWarData.teams)) {
const index = this.guildMembers.findIndex(member => member.id === teamId); const index = this.guildMembers.findIndex((member) => member.id === teamId);
if (index === -1) continue; if (index === -1) continue;
let totalHeroPower = 0; let totalHeroPower = 0;
let totalTitanPower = 0; let totalTitanPower = 0;
@@ -211,8 +214,8 @@ export class GuildwarAttackComponent implements OnInit {
this.guildMembers[index].heroes = { power: totalHeroPower, teams: heroes }; this.guildMembers[index].heroes = { power: totalHeroPower, teams: heroes };
this.guildMembers[index].titans = { power: totalTitanPower, teams: titans }; this.guildMembers[index].titans = { power: totalTitanPower, teams: titans };
} }
this.guildMembers.sort((a, b) => ((a.heroes.power + a.titans.power) > (b.heroes.power + b.titans.power) ? -1 : 1)); // Descending this.guildMembers.sort((a, b) => (a.heroes.power + a.titans.power > b.heroes.power + b.titans.power ? -1 : 1)); // Descending
this._championsByPower = this.guildMembers.filter(member => member.champion === true); this._championsByPower = this.guildMembers.filter((member) => member.champion === true);
} }
getEnemies(): HWMember[] { getEnemies(): HWMember[] {
@@ -282,5 +285,4 @@ export class GuildwarAttackComponent implements OnInit {
//return this._getFortification(indexes, 'titans', 'Spring Of Elements'); //return this._getFortification(indexes, 'titans', 'Spring Of Elements');
return this._getDefense('titans', 'Spring Of Elements'); return this._getDefense('titans', 'Spring Of Elements');
} }
} }
@@ -9,13 +9,9 @@ import { HWMember } from '@models';
@Component({ @Component({
selector: 'app-guildwar-champions', selector: 'app-guildwar-champions',
standalone: true, imports: [DecimalPipe, MatCardModule, MatDividerModule, MatIconModule],
imports: [
DecimalPipe,
MatCardModule, MatDividerModule, MatIconModule
],
templateUrl: './guildwar-champions.component.html', templateUrl: './guildwar-champions.component.html',
styleUrl: './guildwar-champions.component.scss' styleUrl: './guildwar-champions.component.scss',
}) })
export class GuildwarChampionsComponent implements OnInit { export class GuildwarChampionsComponent implements OnInit {
private _championsByPower: HWMember[] = []; private _championsByPower: HWMember[] = [];
@@ -39,13 +35,13 @@ export class GuildwarChampionsComponent implements OnInit {
this.color = 'navy'; this.color = 'navy';
this.subtitle = 'heroes power'; this.subtitle = 'heroes power';
this.guildMembers.sort((a, b) => (a.heroes.power > b.heroes.power ? -1 : 1)); // Descending this.guildMembers.sort((a, b) => (a.heroes.power > b.heroes.power ? -1 : 1)); // Descending
this._championsByPower = this.guildMembers.filter(member => member.champion === true); this._championsByPower = this.guildMembers.filter((member) => member.champion === true);
break; break;
case 'titans': case 'titans':
this.color = 'purple'; this.color = 'purple';
this.subtitle = 'titans power'; this.subtitle = 'titans power';
this.guildMembers.sort((a, b) => (a.titans.power > b.titans.power ? -1 : 1)); // Descending this.guildMembers.sort((a, b) => (a.titans.power > b.titans.power ? -1 : 1)); // Descending
this._championsByPower = this.guildMembers.filter(member => member.champion === true); this._championsByPower = this.guildMembers.filter((member) => member.champion === true);
break; break;
default: default:
break; break;
@@ -14,13 +14,9 @@ import guildWarSlots from 'src/files-data/hw-guild-war-slots.json'; // no pages
@Component({ @Component({
selector: 'app-guildwar-defence', selector: 'app-guildwar-defence',
standalone: true, imports: [MatCardModule, MatDividerModule, MatIconModule, FortificationCardContentComponent],
imports: [
MatCardModule, MatDividerModule, MatIconModule,
FortificationCardContentComponent
],
templateUrl: './guildwar-defence.component.html', templateUrl: './guildwar-defence.component.html',
styleUrl: './guildwar-defence.component.scss' styleUrl: './guildwar-defence.component.scss',
}) })
export class GuildwarDefenceComponent implements OnInit { export class GuildwarDefenceComponent implements OnInit {
private _championsByPower: HWMember[] = []; private _championsByPower: HWMember[] = [];
@@ -40,7 +36,7 @@ export class GuildwarDefenceComponent implements OnInit {
ngOnInit() { ngOnInit() {
for (const [teamId, teamValues] of Object.entries(guildWarData.teams)) { for (const [teamId, teamValues] of Object.entries(guildWarData.teams)) {
const index = this.guildMembers.findIndex(member => member.id === teamId); const index = this.guildMembers.findIndex((member) => member.id === teamId);
if (index === -1) continue; if (index === -1) continue;
let totalHeroPower = 0; let totalHeroPower = 0;
let totalTitanPower = 0; let totalTitanPower = 0;
@@ -75,7 +71,7 @@ export class GuildwarDefenceComponent implements OnInit {
default: default:
break; break;
} }
this._championsByPower = this.guildMembers.filter(member => member.champion === true); this._championsByPower = this.guildMembers.filter((member) => member.champion === true);
} }
private _getFortification(indexes: number[], type: string, name: string): HWGuildWarFortification { private _getFortification(indexes: number[], type: string, name: string): HWGuildWarFortification {
@@ -104,7 +100,7 @@ export class GuildwarDefenceComponent implements OnInit {
count: count, count: count,
teams: teams, teams: teams,
positions: this._championSlots, positions: this._championSlots,
slots: slots[name] slots: slots[name],
}; };
} }
@@ -10,13 +10,9 @@ import guildWarData from 'src/files-data/hw-guild-war.json'; // page Overview ->
@Component({ @Component({
selector: 'app-guildwar-teams', selector: 'app-guildwar-teams',
standalone: true, imports: [DecimalPipe, MatCardModule, MatDividerModule, MatIconModule],
imports: [
DecimalPipe,
MatCardModule, MatDividerModule, MatIconModule
],
templateUrl: './guildwar-teams.component.html', templateUrl: './guildwar-teams.component.html',
styleUrl: './guildwar-teams.component.scss' styleUrl: './guildwar-teams.component.scss',
}) })
export class GuildwarTeamsComponent implements OnInit { export class GuildwarTeamsComponent implements OnInit {
private _championsByPower: HWMember[] = []; private _championsByPower: HWMember[] = [];
@@ -33,8 +29,8 @@ export class GuildwarTeamsComponent implements OnInit {
} }
ngOnInit() { ngOnInit() {
this.guildMembers
this.guildMembers.sort((a, b) => (((a.heroes.power + a.titans.power) / 2) > ((b.heroes.power + b.titans.power) / 2) ? -1 : 1)) .sort((a, b) => ((a.heroes.power + a.titans.power) / 2 > (b.heroes.power + b.titans.power) / 2 ? -1 : 1))
.map((data) => { .map((data) => {
/* /*
this.guildTotalHeroesPower += data.heroes.power; this.guildTotalHeroesPower += data.heroes.power;
@@ -47,7 +43,7 @@ export class GuildwarTeamsComponent implements OnInit {
}); });
for (const [teamId, teamValues] of Object.entries(guildWarData.teams)) { for (const [teamId, teamValues] of Object.entries(guildWarData.teams)) {
const index = this._championsByPower.findIndex(member => member.id === teamId); const index = this._championsByPower.findIndex((member) => member.id === teamId);
if (index === -1) continue; if (index === -1) continue;
let totalHeroPower = 0; let totalHeroPower = 0;
let totalTitanPower = 0; let totalTitanPower = 0;
@@ -66,14 +62,15 @@ export class GuildwarTeamsComponent implements OnInit {
this._championsByPower[index].titans = { power: totalTitanPower, teams: titans }; this._championsByPower[index].titans = { power: totalTitanPower, teams: titans };
this.guildTotalHeroesPower += totalHeroPower; this.guildTotalHeroesPower += totalHeroPower;
this.guildTotalTitansPower += totalTitanPower; this.guildTotalTitansPower += totalTitanPower;
this._championsByPower[index].rewards = Math.floor((this._championsByPower[index].scoreGifts + this._championsByPower[index].warGifts)); this._championsByPower[index].rewards = Math.floor(
this._championsByPower[index].scoreGifts + this._championsByPower[index].warGifts,
);
} }
this.guildAverageHeroesPower = Math.floor((this.guildTotalHeroesPower / this._championsByPower.length)); this.guildAverageHeroesPower = Math.floor(this.guildTotalHeroesPower / this._championsByPower.length);
this.guildAverageTitansPower = Math.floor((this.guildTotalTitansPower / this._championsByPower.length)); this.guildAverageTitansPower = Math.floor(this.guildTotalTitansPower / this._championsByPower.length);
} }
getChampionsByPower(): HWMember[] { getChampionsByPower(): HWMember[] {
return this._championsByPower; return this._championsByPower;
} }
} }
@@ -12,56 +12,99 @@ import guildStatistics from 'src/files-data/hw-guild-statistics.json'; // page O
@Component({ @Component({
selector: 'app-members-statistics', selector: 'app-members-statistics',
standalone: true, imports: [DatePipe, DecimalPipe, MatCardModule, MatDividerModule, MatIconModule],
imports: [
DatePipe, DecimalPipe,
MatCardModule, MatDividerModule, MatIconModule
],
templateUrl: './members-statistics.component.html', templateUrl: './members-statistics.component.html',
styleUrl: './members-statistics.component.scss' styleUrl: './members-statistics.component.scss',
}) })
export class MembersStatisticsComponent implements OnInit { export class MembersStatisticsComponent implements OnInit {
public guildMembers: HWMember[] = []; public guildMembers: HWMember[] = [];
public title = 'Members'; public title = 'Members';
public subtitle = 'statistics'; public subtitle = 'statistics';
public daysToWarn = 1; public daysToWarn = 1;
public guildSumAverages: HWActivityStat = { activity: 0, prestige: 0, titanite: 0, war: 0, adventure: 0, gifts: 0, score: 0, scoreGifts: 0, warGifts: 0, rewards: 0 }; public guildSumAverages: HWActivityStat = {
public guildTodayAverages: HWActivityStat = { activity: 0, prestige: 0, titanite: 0, war: 0, adventure: 0, gifts: 0, score: 0, scoreGifts: 0, warGifts: 0, rewards: 0 }; activity: 0,
public guildSumTotal: HWActivityStat = { activity: 0, prestige: 0, titanite: 0, war: 0, adventure: 0, gifts: 0, score: 0, scoreGifts: 0, warGifts: 0, rewards: 0 }; prestige: 0,
public guildTodayTotal: HWActivityStat = { activity: 0, prestige: 0, titanite: 0, war: 0, adventure: 0, gifts: 0, score: 0, scoreGifts: 0, warGifts: 0, rewards: 0 }; titanite: 0,
war: 0,
adventure: 0,
gifts: 0,
score: 0,
scoreGifts: 0,
warGifts: 0,
rewards: 0,
};
public guildTodayAverages: HWActivityStat = {
activity: 0,
prestige: 0,
titanite: 0,
war: 0,
adventure: 0,
gifts: 0,
score: 0,
scoreGifts: 0,
warGifts: 0,
rewards: 0,
};
public guildSumTotal: HWActivityStat = {
activity: 0,
prestige: 0,
titanite: 0,
war: 0,
adventure: 0,
gifts: 0,
score: 0,
scoreGifts: 0,
warGifts: 0,
rewards: 0,
};
public guildTodayTotal: HWActivityStat = {
activity: 0,
prestige: 0,
titanite: 0,
war: 0,
adventure: 0,
gifts: 0,
score: 0,
scoreGifts: 0,
warGifts: 0,
rewards: 0,
};
public guildData: HWGuildData = {} as HWGuildData; public guildData: HWGuildData = {} as HWGuildData;
private _guildClan: HWGuildClan = {} as HWGuildClan; private _guildClan: HWGuildClan = {} as HWGuildClan;
private _membersByName: HWMember[] = []; private _membersByName: HWMember[] = [];
private _deviations: { activity: number[], prestige: number[], titanite: number[] } = { activity: [], prestige: [], titanite: [] }; private _deviations: { activity: number[]; prestige: number[]; titanite: number[] } = {
activity: [],
prestige: [],
titanite: [],
};
@Input() set members(value: HWMember[]) { @Input() set members(value: HWMember[]) {
this.guildMembers = value; this.guildMembers = value;
} }
constructor( constructor(private _utilitiesService: UtilitiesService) {}
private _utilitiesService: UtilitiesService
) { }
ngOnInit() { ngOnInit() {
const oneDayInSec = 24 * 60 * 60;
const oneDayInSec = (24 * 60 * 60);
const today = new Date(); const today = new Date();
const daysToKick = parseInt(guildData.clan.daysToKick); const daysToKick = parseInt(guildData.clan.daysToKick);
this.daysToWarn = (parseInt(guildData.clan.daysToKick) / 2); this.daysToWarn = parseInt(guildData.clan.daysToKick) / 2;
this.guildMembers.sort((a, b) => (a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1)).map((data) => { this.guildMembers
const last = new Date((parseInt(data.lastLoginTime) * 1000)); .sort((a, b) => (a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1))
const exp = new Date(last.getTime() + ((daysToKick * oneDayInSec) * 1000)); .map((data) => {
const diff = Math.floor(((exp.getTime() - today.getTime()) / 1000)); const last = new Date(parseInt(data.lastLoginTime) * 1000);
const daysLeft = Math.floor((diff / oneDayInSec)); const exp = new Date(last.getTime() + daysToKick * oneDayInSec * 1000);
const diff = Math.floor((exp.getTime() - today.getTime()) / 1000);
const daysLeft = Math.floor(diff / oneDayInSec);
let timeLeft = diff; let timeLeft = diff;
if (daysLeft >= 1) { if (daysLeft >= 1) {
timeLeft = (diff - (daysLeft * oneDayInSec)); timeLeft = diff - daysLeft * oneDayInSec;
} }
data.inactivity = { data.inactivity = {
daysLeft: daysLeft, daysLeft: daysLeft,
timeLeft: timeLeft, timeLeft: timeLeft,
dropDelay: `${daysLeft}d, ${this._utilitiesService.secondsToDuration(timeLeft)}`, dropDelay: `${daysLeft}d, ${this._utilitiesService.secondsToDuration(timeLeft)}`,
dropDate: Math.floor((exp.getTime() / 1000)) dropDate: Math.floor(exp.getTime() / 1000),
}; };
this._membersByName.push(data); this._membersByName.push(data);
return data; return data;
@@ -72,11 +115,20 @@ export class MembersStatisticsComponent implements OnInit {
this.guildData.membersStat = guildData.membersStat; this.guildData.membersStat = guildData.membersStat;
for (const item of Object.entries(guildStatistics.stat)) { for (const item of Object.entries(guildStatistics.stat)) {
const index = this._membersByName.findIndex(member => member.id === item[1].id); const index = this._membersByName.findIndex((member) => member.id === item[1].id);
if (index !== -1) { if (index !== -1) {
this._membersByName[index].adventureSum = item[1].adventureStat.reduce((accumulator, currentValue) => accumulator + currentValue, 0); this._membersByName[index].adventureSum = item[1].adventureStat.reduce(
this._membersByName[index].clanGiftsSum = item[1].clanGifts.reduce((accumulator, currentValue) => accumulator + currentValue, 0); (accumulator, currentValue) => accumulator + currentValue,
this._membersByName[index].clanWarSum = item[1].clanWarStat.reduce((accumulator, currentValue) => accumulator + currentValue, 0); 0,
);
this._membersByName[index].clanGiftsSum = item[1].clanGifts.reduce(
(accumulator, currentValue) => accumulator + currentValue,
0,
);
this._membersByName[index].clanWarSum = item[1].clanWarStat.reduce(
(accumulator, currentValue) => accumulator + currentValue,
0,
);
this.guildSumTotal.adventure += this._membersByName[index].adventureSum; this.guildSumTotal.adventure += this._membersByName[index].adventureSum;
this.guildSumTotal.gifts += this._membersByName[index].clanGiftsSum; this.guildSumTotal.gifts += this._membersByName[index].clanGiftsSum;
this.guildSumTotal.war += this._membersByName[index].clanWarSum; this.guildSumTotal.war += this._membersByName[index].clanWarSum;
@@ -91,19 +143,26 @@ export class MembersStatisticsComponent implements OnInit {
for (const data of Object.entries(guildData.membersStat)) { for (const data of Object.entries(guildData.membersStat)) {
const stat: HWMemberStat = {} as HWMemberStat; const stat: HWMemberStat = {} as HWMemberStat;
Object.assign(stat, data[1]); Object.assign(stat, data[1]);
const index = this._membersByName.findIndex(member => member.id === data[1].userId); const index = this._membersByName.findIndex((member) => member.id === data[1].userId);
if (index !== -1) { if (index !== -1) {
this._membersByName[index].stat = stat; this._membersByName[index].stat = stat;
} else { } else {
continue; continue;
} }
this._membersByName[index].score = (this._membersByName[index].stat.dungeonActivitySum + this._membersByName[index].stat.activitySum + this._membersByName[index].stat.prestigeSum); this._membersByName[index].score =
this._membersByName[index].warGifts = (((guildData.clan.giftsCount / 2) * ((this._membersByName[index].clanWarSum * 10) / 100)) / 20); this._membersByName[index].stat.dungeonActivitySum +
this._membersByName[index].stat.activitySum +
this._membersByName[index].stat.prestigeSum;
this._membersByName[index].warGifts =
((guildData.clan.giftsCount / 2) * ((this._membersByName[index].clanWarSum * 10) / 100)) / 20;
this.guildTodayTotal.activity += stat.todayActivity; this.guildTodayTotal.activity += stat.todayActivity;
this.guildTodayTotal.prestige += stat.todayPrestige; this.guildTodayTotal.prestige += stat.todayPrestige;
this.guildTodayTotal.titanite += stat.todayDungeonActivity; this.guildTodayTotal.titanite += stat.todayDungeonActivity;
this.guildTodayTotal.score += (this._membersByName[index].stat.todayDungeonActivity + this._membersByName[index].stat.todayActivity + this._membersByName[index].stat.todayPrestige); this.guildTodayTotal.score +=
this._membersByName[index].stat.todayDungeonActivity +
this._membersByName[index].stat.todayActivity +
this._membersByName[index].stat.todayPrestige;
this.guildSumTotal.activity += stat.activitySum; this.guildSumTotal.activity += stat.activitySum;
this.guildSumTotal.prestige += stat.prestigeSum; this.guildSumTotal.prestige += stat.prestigeSum;
this.guildSumTotal.titanite += stat.dungeonActivitySum; this.guildSumTotal.titanite += stat.dungeonActivitySum;
@@ -114,26 +173,26 @@ export class MembersStatisticsComponent implements OnInit {
this._deviations.titanite.push(stat.dungeonActivitySum); this._deviations.titanite.push(stat.dungeonActivitySum);
//this.guildSumTotal.warGifts += ((this._membersByName[index].score / this.guildSumTotal.score) * (guildData.clan.giftsCount / 2)) //this.guildSumTotal.warGifts += ((this._membersByName[index].score / this.guildSumTotal.score) * (guildData.clan.giftsCount / 2))
} }
this.guildSumTotal.scoreGifts = (guildData.clan.giftsCount - Math.floor(this.guildSumTotal.warGifts)); this.guildSumTotal.scoreGifts = guildData.clan.giftsCount - Math.floor(this.guildSumTotal.warGifts);
this.guildTodayAverages.activity = (this.guildTodayTotal.activity / this._membersByName.length); this.guildTodayAverages.activity = this.guildTodayTotal.activity / this._membersByName.length;
this.guildTodayAverages.prestige = (this.guildTodayTotal.prestige / this._membersByName.length); this.guildTodayAverages.prestige = this.guildTodayTotal.prestige / this._membersByName.length;
this.guildTodayAverages.titanite = (this.guildTodayTotal.titanite / this._membersByName.length); this.guildTodayAverages.titanite = this.guildTodayTotal.titanite / this._membersByName.length;
this.guildTodayAverages.score = (this.guildTodayTotal.score / this._membersByName.length); this.guildTodayAverages.score = this.guildTodayTotal.score / this._membersByName.length;
this.guildSumAverages.activity = (this.guildSumTotal.activity / this._membersByName.length); this.guildSumAverages.activity = this.guildSumTotal.activity / this._membersByName.length;
this.guildSumAverages.prestige = (this.guildSumTotal.prestige / this._membersByName.length); this.guildSumAverages.prestige = this.guildSumTotal.prestige / this._membersByName.length;
this.guildSumAverages.titanite = (this.guildSumTotal.titanite / this._membersByName.length); this.guildSumAverages.titanite = this.guildSumTotal.titanite / this._membersByName.length;
this.guildSumAverages.war = (this.guildSumTotal.war / 20); this.guildSumAverages.war = this.guildSumTotal.war / 20;
this.guildSumAverages.adventure = (this.guildSumTotal.adventure / this._membersByName.length); this.guildSumAverages.adventure = this.guildSumTotal.adventure / this._membersByName.length;
this.guildSumAverages.gifts = (this.guildSumTotal.gifts / this._membersByName.length); this.guildSumAverages.gifts = this.guildSumTotal.gifts / this._membersByName.length;
this.guildSumAverages.score = (this.guildSumTotal.score / this._membersByName.length); this.guildSumAverages.score = this.guildSumTotal.score / this._membersByName.length;
this._membersByName.map((data) => { this._membersByName.map((data) => {
data.scoreGifts = ((data.score / this.guildSumTotal.score) * this.guildSumTotal.scoreGifts); data.scoreGifts = (data.score / this.guildSumTotal.score) * this.guildSumTotal.scoreGifts;
data.rewards = Math.floor((data.scoreGifts + data.warGifts)); data.rewards = Math.floor(data.scoreGifts + data.warGifts);
this.guildSumTotal.rewards += data.rewards; this.guildSumTotal.rewards += data.rewards;
return data; return data;
}); });
this.guildSumAverages.rewards = (this.guildSumTotal.rewards / this._membersByName.length); this.guildSumAverages.rewards = this.guildSumTotal.rewards / this._membersByName.length;
} }
getMembersByName(): HWMember[] { getMembersByName(): HWMember[] {
@@ -143,7 +202,7 @@ export class MembersStatisticsComponent implements OnInit {
private _standardDeviation(array: number[]): number { private _standardDeviation(array: number[]): number {
const n = array.length; const n = array.length;
const mean = array.reduce((a, b) => a + b) / n; const mean = array.reduce((a, b) => a + b) / n;
return Math.sqrt(array.map(x => Math.pow(x - mean, 2)).reduce((a, b) => a + b) / n); return Math.sqrt(array.map((x) => Math.pow(x - mean, 2)).reduce((a, b) => a + b) / n);
} }
getStandardDeviationActivity(): number { getStandardDeviationActivity(): number {
@@ -157,5 +216,4 @@ export class MembersStatisticsComponent implements OnInit {
getStandardDeviationTitanite(): number { getStandardDeviationTitanite(): number {
return this._standardDeviation(this._deviations.titanite); return this._standardDeviation(this._deviations.titanite);
} }
} }
@@ -4,8 +4,7 @@ import { DatePipe } from '@angular/common';
@Component({ @Component({
selector: 'app-layout-footer', selector: 'app-layout-footer',
templateUrl: './footer.component.html', templateUrl: './footer.component.html',
standalone: true, imports: [DatePipe],
imports: [ DatePipe ]
}) })
export class FooterComponent { export class FooterComponent {
today: number = Date.now(); today: number = Date.now();
@@ -13,30 +13,42 @@ import { Observable, Subscription } from 'rxjs';
import { Menu, User } from '@models'; import { Menu, User } from '@models';
import { UserService } from '@services'; import { UserService } from '@services';
import { MenuItems, ShowAuthedDirective, AccordionAnchorDirective, AccordionLinkDirective, AccordionDirective } from '@components/shared'; import {
MenuItems,
ShowAuthedDirective,
AccordionAnchorDirective,
AccordionLinkDirective,
AccordionDirective,
} from '@components/shared';
//import { SpinnerComponent } from '@components/shared'; //import { SpinnerComponent } from '@components/shared';
//import { HeaderComponent, FooterComponent } from '@components/shared/layout'; //import { HeaderComponent, FooterComponent } from '@components/shared/layout';
import { FooterComponent } from '@components/shared/layout'; import { FooterComponent } from '@components/shared/layout';
/** @title Responsive sidenav */ /** @title Responsive sidenav */
@Component({ @Component({
selector: 'app-full-layout', selector: 'app-full-layout',
standalone: true,
imports: [ imports: [
RouterModule, RouterOutlet, RouterModule,
MatBadgeModule, MatButtonModule, MatDividerModule, RouterOutlet,
MatIconModule, MatListModule, MatMenuModule, MatBadgeModule,
MatSidenavModule, MatToolbarModule, MatButtonModule,
ShowAuthedDirective, AccordionAnchorDirective, MatDividerModule,
AccordionLinkDirective, AccordionDirective, MatIconModule,
FooterComponent MatListModule,
MatMenuModule,
MatSidenavModule,
MatToolbarModule,
ShowAuthedDirective,
AccordionAnchorDirective,
AccordionLinkDirective,
AccordionDirective,
FooterComponent,
//HeaderComponent, //HeaderComponent,
//SpinnerComponent //SpinnerComponent
], ],
providers: [ MenuItems ], providers: [MenuItems],
templateUrl: 'full.component.html', templateUrl: 'full.component.html',
styleUrls: [] styleUrls: [],
}) })
export class FullComponent implements OnInit, OnDestroy { export class FullComponent implements OnInit, OnDestroy {
private _currentUser: Subscription = new Subscription(); private _currentUser: Subscription = new Subscription();
@@ -56,7 +68,7 @@ export class FullComponent implements OnInit, OnDestroy {
private userService: UserService, private userService: UserService,
changeDetectorRef: ChangeDetectorRef, changeDetectorRef: ChangeDetectorRef,
media: MediaMatcher, media: MediaMatcher,
public menuItems: MenuItems public menuItems: MenuItems,
) { ) {
this.mobileQuery = media.matchMedia('(min-width: 768px)'); this.mobileQuery = media.matchMedia('(min-width: 768px)');
this._mobileQueryListener = () => changeDetectorRef.detectChanges(); this._mobileQueryListener = () => changeDetectorRef.detectChanges();
@@ -65,8 +77,7 @@ export class FullComponent implements OnInit, OnDestroy {
ngOnInit() { ngOnInit() {
const user$: Observable<User> = this.userService.currentUser; const user$: Observable<User> = this.userService.currentUser;
this._currentUser = user$.subscribe( this._currentUser = user$.subscribe((userData) => {
(userData) => {
this.currentUser = userData; this.currentUser = userData;
if (this.currentUser.role === 'Admin') { if (this.currentUser.role === 'Admin') {
this.links = this.menuItems.getMenuItemsAdmin(); this.links = this.menuItems.getMenuItemsAdmin();
@@ -74,8 +85,7 @@ export class FullComponent implements OnInit, OnDestroy {
} else { } else {
this.links = this.menuItems.getMenuItems(); this.links = this.menuItems.getMenuItems();
} }
} });
);
} }
getMenuItems(): Menu[] { getMenuItems(): Menu[] {
@@ -6,7 +6,7 @@ import { MatDividerModule } from '@angular/material/divider';
import { MatIconModule } from '@angular/material/icon'; import { MatIconModule } from '@angular/material/icon';
import { MatMenuModule } from '@angular/material/menu'; import { MatMenuModule } from '@angular/material/menu';
import { MatToolbarModule } from '@angular/material/toolbar'; import { MatToolbarModule } from '@angular/material/toolbar';
import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { Observable, Subscription } from 'rxjs'; import { Observable, Subscription } from 'rxjs';
import { User } from '@models'; import { User } from '@models';
@@ -15,15 +15,17 @@ import { UserService } from '@services';
@Component({ @Component({
selector: 'app-layout-header', selector: 'app-layout-header',
templateUrl: './header.component.html', templateUrl: './header.component.html',
standalone: true,
imports: [ imports: [
RouterLink, RouterLinkActive, RouterLink,
MatToolbarModule, MatButtonModule, MatDividerModule, RouterLinkActive,
MatIconModule, MatMenuModule MatToolbarModule,
] MatButtonModule,
MatDividerModule,
MatIconModule,
MatMenuModule,
],
}) })
export class HeaderComponent implements OnInit { export class HeaderComponent implements OnInit {
private _currentUser: Subscription = new Subscription(); private _currentUser: Subscription = new Subscription();
private _isAuthenticated: Subscription = new Subscription(); private _isAuthenticated: Subscription = new Subscription();
private isAuthenticated = false; private isAuthenticated = false;
@@ -32,22 +34,18 @@ export class HeaderComponent implements OnInit {
constructor( constructor(
private router: Router, private router: Router,
private userService: UserService private userService: UserService,
) { } ) {}
ngOnInit() { ngOnInit() {
const user$: Observable<User> = this.userService.currentUser.pipe(takeUntilDestroyed(this.destroyRef)); const user$: Observable<User> = this.userService.currentUser.pipe(takeUntilDestroyed(this.destroyRef));
this._currentUser = user$.subscribe( this._currentUser = user$.subscribe((userData) => {
(userData) => {
this.currentUser = userData; this.currentUser = userData;
} });
);
const auth$: Observable<boolean> = this.userService.isAuthenticated.pipe(takeUntilDestroyed(this.destroyRef)); const auth$: Observable<boolean> = this.userService.isAuthenticated.pipe(takeUntilDestroyed(this.destroyRef));
this._isAuthenticated = auth$.subscribe( this._isAuthenticated = auth$.subscribe((value) => {
(value) => {
this.isAuthenticated = value; this.isAuthenticated = value;
} });
);
} }
goToGitHub() { goToGitHub() {
@@ -1,5 +1,5 @@
import { Component, Input } from '@angular/core'; import { Component, Input } from '@angular/core';
import { NgForOf, NgIf } from "@angular/common"; import { NgForOf, NgIf } from '@angular/common';
import { MatCardModule } from '@angular/material/card'; import { MatCardModule } from '@angular/material/card';
import { Errors } from 'src/app/core'; import { Errors } from 'src/app/core';
@@ -7,17 +7,14 @@ import { Errors } from 'src/app/core';
@Component({ @Component({
selector: 'app-list-errors', selector: 'app-list-errors',
templateUrl: './list-errors.component.html', templateUrl: './list-errors.component.html',
standalone: true, imports: [NgIf, NgForOf, MatCardModule],
imports: [NgIf, NgForOf, MatCardModule]
}) })
export class ListErrorsComponent { export class ListErrorsComponent {
errorList: string[] = []; errorList: string[] = [];
@Input() set errors(errorList: Errors | null) { @Input() set errors(errorList: Errors | null) {
this.errorList = errorList this.errorList = errorList
? Object.keys(errorList.errors || {}).map( ? Object.keys(errorList.errors || {}).map((key) => `${key} ${errorList.errors[key]}`)
(key) => `${key} ${errorList.errors[key]}`,
)
: []; : [];
} }
} }
@@ -5,10 +5,9 @@ import { DOCUMENT } from '@angular/common';
@Component({ @Component({
selector: 'app-spinner', selector: 'app-spinner',
standalone: true,
imports: [], imports: [],
templateUrl: './spinner.component.html', templateUrl: './spinner.component.html',
encapsulation: ViewEncapsulation.None encapsulation: ViewEncapsulation.None,
}) })
export class SpinnerComponent implements OnDestroy { export class SpinnerComponent implements OnDestroy {
public isSpinnerVisible = true; public isSpinnerVisible = true;
@@ -18,10 +17,10 @@ export class SpinnerComponent implements OnDestroy {
constructor( constructor(
private router: Router, private router: Router,
@Inject(DOCUMENT) private document: Document @Inject(DOCUMENT) private document: Document,
) { ) {
this.router.events.subscribe( this.router.events.subscribe(
event => { (event) => {
if (event instanceof NavigationStart) { if (event instanceof NavigationStart) {
this.isSpinnerVisible = true; this.isSpinnerVisible = true;
} else if ( } else if (
@@ -34,7 +33,7 @@ export class SpinnerComponent implements OnDestroy {
}, },
() => { () => {
this.isSpinnerVisible = false; this.isSpinnerVisible = false;
} },
); );
} }
+32 -24
View File
@@ -4,18 +4,18 @@ Author: UnEspace
Email: rampeur@gmail.com Email: rampeur@gmail.com
File: scss File: scss
*/ */
@use 'sass:color'; @use "sass:color";
@use 'sass:map'; @use "sass:map";
@use './components'; @use "./components";
@use '@angular/material' as mat; @use "@angular/material" as mat;
/* Bootstrap */ /* Bootstrap */
// Functions first // Functions first
@import "bootstrap/scss/functions"; @import "bootstrap/scss/functions";
// Variable overrides second // Variable overrides second
@import 'variable'; @import "variable";
@import 'palettes'; @import "palettes";
// Required Bootstrap imports // Required Bootstrap imports
@import "bootstrap/scss/variables"; @import "bootstrap/scss/variables";
@@ -42,7 +42,8 @@ File: scss
// Utilities // Utilities
@import "bootstrap/scss/utilities/api"; @import "bootstrap/scss/utilities/api";
@include mat.core(); @include mat.elevation-classes();
@include mat.app-background();
// Define the palettes for your theme using the Material Design palettes available in palette.scss // Define the palettes for your theme using the Material Design palettes available in palette.scss
// (imported above). For each palette, you can optionally specify a default, lighter, and darker // (imported above). For each palette, you can optionally specify a default, lighter, and darker
@@ -82,35 +83,37 @@ $adastra_app-grey: mat.m2-define-palette(mat.$m2-grey-palette, 400);
$adastra_app-muted: mat.m2-define-palette(mat.$m2-grey-palette, 300); $adastra_app-muted: mat.m2-define-palette(mat.$m2-grey-palette, 300);
$custom-typography: mat.m2-define-typography-config( $custom-typography: mat.m2-define-typography-config(
$font-family: 'Barlow, sans-serif', $font-family: "Barlow, sans-serif",
$body-1: mat.m2-define-typography-level( $body-1: mat.m2-define-typography-level(
$font-family: 'Barlow, sans-serif', $font-family: "Barlow, sans-serif",
$font-weight: 400, $font-weight: 400,
$font-size: 14px, $font-size: 14px,
$line-height: 1.42857143, $line-height: 1.42857143,
$letter-spacing: normal, $letter-spacing: normal,
), ),
$body-2: mat.m2-define-typography-level( $body-2: mat.m2-define-typography-level(
$font-family: 'Barlow, sans-serif', $font-family: "Barlow, sans-serif",
$font-weight: 500, $font-weight: 500,
$font-size: 14px, $font-size: 14px,
$line-height: 22px, $line-height: 22px,
$letter-spacing: normal, $letter-spacing: normal,
) ),
); );
// Create the theme object. A theme consists of configurations for individual // Create the theme object. A theme consists of configurations for individual
// theming systems such as "color" or "typography". // theming systems such as "color" or "typography".
//$adastra_app-theme: mat.m2-define-dark-theme(( //$adastra_app-theme: mat.m2-define-dark-theme((
$adastra_app-theme: mat.m2-define-light-theme(( $adastra_app-theme: mat.m2-define-light-theme(
(
color: ( color: (
primary: $adastra_app-primary, primary: $adastra_app-primary,
accent: $adastra_app-accent, accent: $adastra_app-accent,
warn: $adastra_app-warn, warn: $adastra_app-warn,
), ),
typography: $custom-typography, typography: $custom-typography,
density: 0 density: 0,
)); )
);
$adastra_app-variants: ( $adastra_app-variants: (
secondary: $adastra_app-secondary, secondary: $adastra_app-secondary,
@@ -135,7 +138,7 @@ $adastra_app-variants: (
magenta: $adastra_app-magenta, magenta: $adastra_app-magenta,
pink: $adastra_app-pink, pink: $adastra_app-pink,
grey: $adastra_app-grey, grey: $adastra_app-grey,
muted: $adastra_app-muted muted: $adastra_app-muted,
); );
/* /*
$config: mat.m2-get-color-config($adastra_app-theme); $config: mat.m2-get-color-config($adastra_app-theme);
@@ -176,7 +179,12 @@ $background: map.get($adastra_app-theme, background);
@each $variant, $var-color in $grays { @each $variant, $var-color in $grays {
.bg-gray-#{"" + $variant} { .bg-gray-#{"" + $variant} {
--#{$prefix}-bg-opacity: 1; --#{$prefix}-bg-opacity: 1;
background-color: RGBA(color.red($var-color), color.green($var-color), color.blue($var-color), var(--#{$prefix}bg-opacity, 1)) !important; background-color: RGBA(
color.red($var-color),
color.green($var-color),
color.blue($var-color),
var(--#{$prefix}bg-opacity, 1)
) !important;
/* background-color: RGBA(color.channel($var-color, "red"), color.channel($var-color, "green"), color.channel($var-color, "blue"), var(--#{$prefix}bg-opacity, 1)) !important; */ /* background-color: RGBA(color.channel($var-color, "red"), color.channel($var-color, "green"), color.channel($var-color, "blue"), var(--#{$prefix}bg-opacity, 1)) !important; */
} }
} }
@@ -187,13 +195,13 @@ $background: map.get($adastra_app-theme, background);
} }
} }
@import 'spinner'; @import "spinner";
@import 'icomoon'; @import "icomoon";
@import 'header'; @import "header";
@import 'sidebar'; @import "sidebar";
@import 'tables'; @import "tables";
@import 'charts'; @import "charts";
@import 'responsive'; @import "responsive";
@import 'app'; @import "app";
//@import "../styles/icons/material-design-iconic-font/css/materialdesignicons.min.css"; //@import "../styles/icons/material-design-iconic-font/css/materialdesignicons.min.css";