diff --git a/Front/skydivelogs-app/angular.json b/Front/skydivelogs-app/angular.json
index 80b4071..7a8ddc1 100644
--- a/Front/skydivelogs-app/angular.json
+++ b/Front/skydivelogs-app/angular.json
@@ -4,25 +4,33 @@
"newProjectRoot": "projects",
"projects": {
"skydivelogs-app": {
+ "projectType": "application",
+ "schematics": {
+ "@schematics/angular:component": {
+ "style": "scss"
+ }
+ },
"root": "",
"sourceRoot": "src",
- "projectType": "application",
+ "prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:application",
"options": {
- "outputPath": {
- "base": "dist"
- },
+ "outputPath": "dist",
"index": "src/index.html",
- "tsConfig": "src/tsconfig.app.json",
- "polyfills": [
- "src/polyfills.ts"
- ],
+ "browser": "src/main.ts",
+ "polyfills": ["zone.js"],
+ "tsConfig": "tsconfig.app.json",
+ "inlineStyleLanguage": "scss",
"assets": [
"src/assets",
"src/config",
- "src/favicon.ico"
+ "src/favicon.ico",
+ {
+ "glob": "**/*",
+ "input": "public"
+ }
],
"styles": [
"src/assets/css/styles-app-loading.scss",
@@ -30,26 +38,28 @@
"src/assets/css/new-theme.scss",
"@angular/material/prebuilt-themes/pink-bluegrey.css"
],
- "scripts": [],
- "extractLicenses": false,
- "sourceMap": true,
- "optimization": false,
- "namedChunks": true,
- "browser": "src/main.ts"
+ "scripts": []
},
"configurations": {
"production": {
"budgets": [
+ {
+ "type": "initial",
+ "maximumWarning": "500kB",
+ "maximumError": "1MB"
+ },
{
"type": "anyComponentStyle",
- "maximumWarning": "6kb"
+ "maximumWarning": "4kB",
+ "maximumError": "8kB"
}
],
- "optimization": true,
- "outputHashing": "all",
- "sourceMap": false,
- "namedChunks": false,
- "extractLicenses": true,
+ "outputHashing": "all"
+ },
+ "development": {
+ "optimization": false,
+ "extractLicenses": false,
+ "sourceMap": true,
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
@@ -57,91 +67,41 @@
}
]
}
- }
+ },
+ "defaultConfiguration": "production"
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
- "options": {
- "buildTarget": "skydivelogs-app:build"
- },
"configurations": {
"production": {
"buildTarget": "skydivelogs-app:build:production"
+ },
+ "development": {
+ "buildTarget": "skydivelogs-app:build:development"
}
- }
+ },
+ "defaultConfiguration": "development"
},
"extract-i18n": {
- "builder": "@angular-devkit/build-angular:extract-i18n",
- "options": {
- "buildTarget": "skydivelogs-app:build"
- }
+ "builder": "@angular-devkit/build-angular:extract-i18n"
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
- "main": "src/test.ts",
- "karmaConfig": "./karma.conf.js",
- "polyfills": "src/polyfills.ts",
- "tsConfig": "src/tsconfig.spec.json",
- "scripts": [],
- "styles": [
- "src/styles.css"
- ],
+ "polyfills": ["zone.js", "zone.js/testing"],
+ "tsConfig": "tsconfig.spec.json",
+ "inlineStyleLanguage": "scss",
"assets": [
- "src/assets",
- "src/favicon.ico"
- ]
- }
- },
- "lint": {
- "builder": "@angular-devkit/build-angular:tslint",
- "options": {
- "tsConfig": [
- "src/tsconfig.app.json",
- "src/tsconfig.spec.json"
+ {
+ "glob": "**/*",
+ "input": "public"
+ }
],
- "exclude": [
- "**/node_modules/**"
- ]
- }
- }
- }
- },
- "skydivelogs-app-e2e": {
- "root": "e2e",
- "sourceRoot": "e2e",
- "projectType": "application",
- "architect": {
- "e2e": {
- "builder": "@angular-devkit/build-angular:protractor",
- "options": {
- "protractorConfig": "./protractor.conf.js",
- "devServerTarget": "skydivelogs-app:serve"
- }
- },
- "lint": {
- "builder": "@angular-devkit/build-angular:tslint",
- "options": {
- "tsConfig": [
- "e2e/tsconfig.e2e.json"
- ],
- "exclude": [
- "**/node_modules/**"
- ]
+ "styles": ["src/styles.scss"],
+ "scripts": []
}
}
}
}
- },
- "schematics": {
- "@schematics/angular:component": {
- "prefix": "app"
- },
- "@schematics/angular:directive": {
- "prefix": "app"
- }
- },
- "cli": {
- "analytics": false
}
}
diff --git a/Front/skydivelogs-app/package-lock.json b/Front/skydivelogs-app/package-lock.json
index 46c223f..cbe4742 100644
--- a/Front/skydivelogs-app/package-lock.json
+++ b/Front/skydivelogs-app/package-lock.json
@@ -22,7 +22,7 @@
"@ngx-translate/core": "^15.0.0",
"@ngx-translate/http-loader": "^8.0.0",
"chart.js": "^4.3.0",
- "ng2-charts": "^5.0.2",
+ "ng2-charts": "^8.0.0",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.15.0"
@@ -10714,19 +10714,19 @@
"license": "MIT"
},
"node_modules/ng2-charts": {
- "version": "5.0.4",
- "resolved": "https://registry.npmjs.org/ng2-charts/-/ng2-charts-5.0.4.tgz",
- "integrity": "sha512-AnOZ2KSRw7QjiMMNtXz9tdnO+XrIKP/2MX1TfqEEo2fwFU5c8LFJIYqmkMPkIzAEm/U9y/1psA5TDNmxxjEdgA==",
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/ng2-charts/-/ng2-charts-8.0.0.tgz",
+ "integrity": "sha512-nofsNHI2Zt+EAwT+BJBVg0kgOhNo9ukO4CxULlaIi7VwZSr7I1km38kWSoU41Oq6os6qqIh5srnL+CcV+RFPFA==",
"license": "MIT",
"dependencies": {
"lodash-es": "^4.17.15",
"tslib": "^2.3.0"
},
"peerDependencies": {
- "@angular/cdk": ">=16.0.0",
- "@angular/common": ">=16.0.0",
- "@angular/core": ">=16.0.0",
- "@angular/platform-browser": ">=16.0.0",
+ "@angular/cdk": ">=19.0.0",
+ "@angular/common": ">=19.0.0",
+ "@angular/core": ">=19.0.0",
+ "@angular/platform-browser": ">=19.0.0",
"chart.js": "^3.4.0 || ^4.0.0",
"rxjs": "^6.5.3 || ^7.4.0"
}
diff --git a/Front/skydivelogs-app/package.json b/Front/skydivelogs-app/package.json
index 3ed2027..fa21033 100644
--- a/Front/skydivelogs-app/package.json
+++ b/Front/skydivelogs-app/package.json
@@ -25,7 +25,7 @@
"@ngx-translate/core": "^15.0.0",
"@ngx-translate/http-loader": "^8.0.0",
"chart.js": "^4.3.0",
- "ng2-charts": "^5.0.2",
+ "ng2-charts": "^8.0.0",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.15.0"
diff --git a/Front/skydivelogs-app/src/app/app.module.ts b/Front/skydivelogs-app/src/app/app.module.ts
index 9afb822..76e79d2 100644
--- a/Front/skydivelogs-app/src/app/app.module.ts
+++ b/Front/skydivelogs-app/src/app/app.module.ts
@@ -72,7 +72,7 @@ import { MatRadioModule } from "@angular/material/radio";
import { MatSidenavModule } from "@angular/material/sidenav";
import { MatListModule } from "@angular/material/list";
import { MatToolbarModule } from "@angular/material/toolbar";
-import { NgChartsModule } from "ng2-charts";
+import { provideCharts, withDefaultRegisterables } from "ng2-charts";
import { JwtAuthInterceptor } from "../interceptor/jwt-auth.interceptor";
import { ErrorInterceptor } from "../interceptor/error.interceptor";
@@ -209,7 +209,6 @@ export function initConfig(configService: ConfigurationHelper) {
MatSidenavModule,
MatListModule,
MatToolbarModule,
- NgChartsModule,
],
exports: [HttpClientModule],
providers: [
@@ -229,11 +228,12 @@ export function initConfig(configService: ConfigurationHelper) {
DatePipe,
ServiceCacheApi,
provideAppInitializer(() => {
- const initializerFn = (initConfig)(inject(ConfigurationHelper));
- return initializerFn();
- }),
+ const initializerFn = initConfig(inject(ConfigurationHelper));
+ return initializerFn();
+ }),
{ provide: HTTP_INTERCEPTORS, useClass: JwtAuthInterceptor, multi: true },
{ provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true },
+ provideCharts(withDefaultRegisterables()),
],
bootstrap: [AppComponent],
})
diff --git a/Front/skydivelogs-app/src/app/create-user/create-user.component.html b/Front/skydivelogs-app/src/app/create-user/create-user.component.html
index 9628b7c..af353aa 100644
--- a/Front/skydivelogs-app/src/app/create-user/create-user.component.html
+++ b/Front/skydivelogs-app/src/app/create-user/create-user.component.html
@@ -1,72 +1,102 @@
-
diff --git a/Front/skydivelogs-app/src/app/create-user/create-user.component.ts b/Front/skydivelogs-app/src/app/create-user/create-user.component.ts
index cef19b9..f64e9f6 100644
--- a/Front/skydivelogs-app/src/app/create-user/create-user.component.ts
+++ b/Front/skydivelogs-app/src/app/create-user/create-user.component.ts
@@ -9,10 +9,10 @@ import { AuthenticationService } from "../../services/authentication.service";
import { User } from "../../models/user";
@Component({
- selector: "app-create-user",
- templateUrl: "./create-user.component.html",
- styleUrls: ["./create-user.component.css"],
- standalone: false
+ selector: "app-create-user",
+ templateUrl: "./create-user.component.html",
+ styleUrls: ["./create-user.component.css"],
+ standalone: false,
})
export class CreateUserComponent implements OnInit {
createForm: FormGroup;
@@ -21,11 +21,13 @@ export class CreateUserComponent implements OnInit {
returnUrl: string;
error = "";
- constructor(private formBuilder: FormBuilder,
- private route: ActivatedRoute,
- private router: Router,
- private authenticationService: AuthenticationService,
- private translateService: TranslateService) {
+ constructor(
+ private formBuilder: FormBuilder,
+ private route: ActivatedRoute,
+ private router: Router,
+ private authenticationService: AuthenticationService,
+ private translateService: TranslateService
+ ) {
// redirect to home if already logged in
if (this.authenticationService.currentUserValue) {
this.router.navigate(["/"]);
@@ -38,11 +40,16 @@ export class CreateUserComponent implements OnInit {
username: ["", [Validators.required, Validators.minLength(3)]],
password: [
"",
- [Validators.required, Validators.pattern("^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[@$!%*#?&\-_|]).{8,}$")]
+ [
+ Validators.required,
+ Validators.pattern(
+ "^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[@$!%*#?&-_|]).{8,}$"
+ ),
+ ],
],
firstname: ["", [Validators.required, Validators.minLength(3)]],
lastname: ["", [Validators.required, Validators.minLength(3)]],
- email: ["", [Validators.required, Validators.email]]
+ email: ["", [Validators.required, Validators.email]],
},
{ updateOn: "blur" }
);
@@ -65,23 +72,24 @@ export class CreateUserComponent implements OnInit {
}
let createUser = new User();
- createUser.login = this.formCtrls.username.value;
- createUser.password = this.formCtrls.password.value;
- createUser.firstName = this.formCtrls.firstname.value;
- createUser.lastName = this.formCtrls.lastname.value;
- createUser.email = this.formCtrls.email.value;
+ createUser.login = this.formCtrls["username"].value;
+ createUser.password = this.formCtrls["password"].value;
+ createUser.firstName = this.formCtrls["firstname"].value;
+ createUser.lastName = this.formCtrls["lastname"].value;
+ createUser.email = this.formCtrls["email"].value;
createUser.language = this.translateService.currentLang;
- this.authenticationService.create(createUser)
- .pipe(first())
- .subscribe(
- data => {
- this.router.navigate([this.returnUrl]);
- },
- error => {
- this.error = error;
- this.invalidForm = false;
- }
- );
+ this.authenticationService
+ .create(createUser)
+ .pipe(first())
+ .subscribe(
+ (data) => {
+ this.router.navigate([this.returnUrl]);
+ },
+ (error) => {
+ this.error = error;
+ this.invalidForm = false;
+ }
+ );
}
}
diff --git a/Front/skydivelogs-app/src/app/list-of-tunnel-flights/list-of-tunnel-flights.component.html b/Front/skydivelogs-app/src/app/list-of-tunnel-flights/list-of-tunnel-flights.component.html
index 8d54f86..ec76169 100644
--- a/Front/skydivelogs-app/src/app/list-of-tunnel-flights/list-of-tunnel-flights.component.html
+++ b/Front/skydivelogs-app/src/app/list-of-tunnel-flights/list-of-tunnel-flights.component.html
@@ -42,7 +42,6 @@
baseChart
[data]="barChartData"
[options]="barChartOptions"
- [plugins]="barChartPlugins"
[legend]="barChartLegend"
[type]="barChartType"
>
diff --git a/Front/skydivelogs-app/src/app/list-of-tunnel-flights/list-of-tunnel-flights.component.ts b/Front/skydivelogs-app/src/app/list-of-tunnel-flights/list-of-tunnel-flights.component.ts
index 033ed82..e8ffebf 100644
--- a/Front/skydivelogs-app/src/app/list-of-tunnel-flights/list-of-tunnel-flights.component.ts
+++ b/Front/skydivelogs-app/src/app/list-of-tunnel-flights/list-of-tunnel-flights.component.ts
@@ -1,233 +1,253 @@
-import { Component, OnInit } from '@angular/core';
-import { formatDate } from '@angular/common';
-import { TranslateService } from '@ngx-translate/core';
-import { MatTableDataSource } from '@angular/material/table';
-import { ChartConfiguration, ChartData, ChartType } from 'chart.js';
-import { from, of, groupBy, mergeMap, reduce, map, Observable } from 'rxjs';
+import { Component, OnInit } from "@angular/core";
+import { formatDate } from "@angular/common";
+import { TranslateService } from "@ngx-translate/core";
+import { MatTableDataSource } from "@angular/material/table";
+import { ChartConfiguration, ChartData, ChartType } from "chart.js";
+import { from, of, groupBy, mergeMap, reduce, map, Observable } from "rxjs";
-import { ServiceComm } from '../../services/service-comm.service';
+import { ServiceComm } from "../../services/service-comm.service";
import { TunnelFlightService } from "../../services/tunnel-flight.service";
-import { DateService } from '../../services/date.service';
-import { TunnelFlight, TunnelFlightByMonth } from '../../models/tunnel-flight';
+import { DateService } from "../../services/date.service";
+import { TunnelFlight, TunnelFlightByMonth } from "../../models/tunnel-flight";
@Component({
- selector: 'app-list-of-tunnel-flights',
- templateUrl: './list-of-tunnel-flights.component.html',
- styleUrls: ['./list-of-tunnel-flights.component.css'],
- standalone: false
+ selector: "app-list-of-tunnel-flights",
+ templateUrl: "./list-of-tunnel-flights.component.html",
+ styleUrls: ["./list-of-tunnel-flights.component.css"],
+ standalone: false,
})
export class ListOfTunnelFlightsComponent implements OnInit {
- public barChartLegend = true;
- public barChartPlugins = [];
- public barChartData: ChartData<'bar'>;
- public barChartOptions: ChartConfiguration['options'];
- public barChartType: ChartType;
- public isLoading: boolean = false;
- public selectedPeriod: string;
- public dataSourceTable: MatTableDataSource = new MatTableDataSource();
- public displayedColumns: Array = [
- "id",
- "tunnel",
- "jumpType",
- "nbMinutes",
- "notes",
- "flightDate",
- "actions"
- ];
- public stats: Array<{id: String|Number, values: String|Number}> = [];
+ public barChartLegend = true;
+ public barChartData: ChartData<"bar">;
+ public barChartOptions: ChartConfiguration["options"];
+ public barChartType: ChartType;
+ public isLoading: boolean = false;
+ public selectedPeriod: string;
+ public dataSourceTable: MatTableDataSource =
+ new MatTableDataSource();
+ public displayedColumns: Array = [
+ "id",
+ "tunnel",
+ "jumpType",
+ "nbMinutes",
+ "notes",
+ "flightDate",
+ "actions",
+ ];
+ public stats: Array<{ id: String | Number; values: String | Number }> = [];
- constructor(private serviceComm: ServiceComm,
- private serviceTunnelFlight: TunnelFlightService,
- private translateService: TranslateService,
- private dateService: DateService) { }
+ constructor(
+ private serviceComm: ServiceComm,
+ private serviceTunnelFlight: TunnelFlightService,
+ private translateService: TranslateService,
+ private dateService: DateService
+ ) {}
- ngOnInit() {
- this.serviceComm.forceTranslateTitle.subscribe((data) => {
- if (data === true) {
- this.updateTitle();
- }
- });
+ ngOnInit() {
+ this.serviceComm.forceTranslateTitle.subscribe((data) => {
+ if (data === true) {
this.updateTitle();
+ }
+ });
+ this.updateTitle();
- this.chartConfig();
- this.selectedPeriod = "currentYear"
- this.getDataForGraph();
- }
-
- public onPeriodChange() {
- this.getDataForGraph();
- if (this.dataSourceTable?.data.length > 0){
- this.getDataForTable();
- }
+ this.chartConfig();
+ this.selectedPeriod = "currentYear";
+ this.getDataForGraph();
+ }
+
+ public onPeriodChange() {
+ this.getDataForGraph();
+ if (this.dataSourceTable?.data.length > 0) {
+ this.getDataForTable();
}
+ }
- public onLoadTable() {
- this.getDataForTable();
- }
+ public onLoadTable() {
+ this.getDataForTable();
+ }
- private chartConfig() {
- this.barChartType = "bar";
- this.barChartOptions = {
- responsive: true,
- maintainAspectRatio: true,
- plugins: {
- legend: {
- display: true
- },
- tooltip: {
- callbacks: {
- footer: this.footer,
- }
- }
- },
- interaction: {
- intersect: false,
- mode: 'nearest',
- axis: 'x'
- },
- scales: {
- x: {
- stacked: true
- },
- y: {
- stacked: true
- }
- }
- };
- }
-
- private updateTitle() {
- this.translateService.get("ListTunnelFlight_Title").subscribe(
- data => { this.serviceComm.updatedComponentTitle(data); }
- );
- }
-
- private getDataForTable(): void {
- this.isLoading = true;
-
- // Get data to show in a table
- let endDate = new Date();
- endDate.setHours(0, 0, 0, 0);
- let beginDate = this.computeBeginDateByPeriod(this.selectedPeriod, endDate);
-
- this.serviceTunnelFlight.getTunnelFlights(beginDate, endDate)
- .subscribe((data) => {
- this.dataSourceTable.data = data;
- this.isLoading = false;
- });
- }
-
- private getDataForGraph(): void {
- this.isLoading = true;
-
- // Get data to show in a table
- let endDate = new Date();
- endDate.setHours(0, 0, 0, 0);
- let beginDate = this.computeBeginDateByPeriod(this.selectedPeriod, endDate);
-
- this.serviceTunnelFlight.getTunnelFlightsByMonth(beginDate, endDate)
- .subscribe((data) => {
- const allMonths = this.getMontsBetweenDates(beginDate, endDate)
- const cumulatedTime = this.getCumulatedTimeByTypeByMonth(data, allMonths);
- this.computeTimeByType(data);
- this.barChartData = {
- labels: allMonths,
- datasets: cumulatedTime
- };
-
- this.isLoading = false;
- });
- }
-
- private computeTimeByType(stats: TunnelFlightByMonth[]) {
- this.stats = [];
- from(stats).pipe(
- groupBy((type) => type.type, { element: (p) => p.nb }),
- mergeMap((group$) =>
- group$.pipe(reduce((acc, cur) => [...acc, cur], [`${group$.key}`]))
- ),
- map((arr) => ({ id: arr[0], values: arr.slice(1).reduce((a, b) => Number(a) + Number(b), 0) }))
- )
- .subscribe((p) => {
- console.log(p);
- this.stats.push(p);
- });
- }
-
- private getMontsBetweenDates(beginDate: Date, endDate: Date): Array {
- let results: Array = [];
- let tmpBeginDate = new Date(beginDate.getTime());
- const tmpEndDate = new Date(endDate.getTime());
-
- while (tmpBeginDate < tmpEndDate) {
- results.push(formatDate(tmpBeginDate, "yy-MM", "en"));
- tmpBeginDate.setMonth(tmpBeginDate.getMonth() + 1);
- }
-
- return results;
- }
-
- private getCumulatedTimeByTypeByMonth(stats: TunnelFlightByMonth[], allMonths: string[]): Array {
- let tmpResults = new Map();
-
- const disctintType = Array.from(new Set(stats.map((item) => item.type)));
- disctintType.forEach(type => {
- tmpResults.set(type, Array.from({length: allMonths.length}, (v, k) => 0));
- });
-
- for (let i = 0; i < allMonths.length; i++) {
- const month = allMonths[i];
- let filteredStats = stats.filter((d) => d.month == month);
-
- if (filteredStats.length > 0){
- filteredStats.forEach(fs => {
- tmpResults.get(fs.type)[i] += fs.nb;
- });
- }
- }
-
- const results = Array.from(tmpResults, function (item) {
- return { label: item[0], data: item[1] }
- });
-
- return results;
- }
-
- private footer = (tooltipItems) => {
- let sum = 0;
-
- tooltipItems.forEach(function (tooltipItem) {
- sum += tooltipItem.parsed.y;
- });
-
- return 'Sum: ' + sum;
+ private chartConfig() {
+ this.barChartType = "bar";
+ this.barChartOptions = {
+ responsive: true,
+ maintainAspectRatio: true,
+ plugins: {
+ legend: {
+ display: true,
+ },
+ tooltip: {
+ callbacks: {
+ footer: this.footer,
+ },
+ },
+ },
+ interaction: {
+ intersect: false,
+ mode: "nearest",
+ axis: "x",
+ },
+ scales: {
+ x: {
+ stacked: true,
+ },
+ y: {
+ stacked: true,
+ },
+ },
};
+ }
- private computeBeginDateByPeriod(selectedPeriod: String, endDate: Date): Date {
- let beginDate = new Date();
-
- switch (selectedPeriod) {
- case "currentYear":
- beginDate = new Date(endDate.getFullYear(), 0, 1);
- break;
- case "12Months":
- beginDate = this.dateService.addMonths(endDate, -12);
- beginDate.setDate(1);
- break;
- case "all":
- beginDate = this.dateService.addMonths(endDate, -120);
- beginDate.setDate(1);
- break;
- }
+ private updateTitle() {
+ this.translateService.get("ListTunnelFlight_Title").subscribe((data) => {
+ this.serviceComm.updatedComponentTitle(data);
+ });
+ }
- return beginDate;
- }
+ private getDataForTable(): void {
+ this.isLoading = true;
- public delete(item: TunnelFlight) {
- let data: Array = this.dataSourceTable.data;
- data = data.filter((d) => d.id !== item.id);
+ // Get data to show in a table
+ let endDate = new Date();
+ endDate.setHours(0, 0, 0, 0);
+ let beginDate = this.computeBeginDateByPeriod(this.selectedPeriod, endDate);
+ this.serviceTunnelFlight
+ .getTunnelFlights(beginDate, endDate)
+ .subscribe((data) => {
this.dataSourceTable.data = data;
- this.serviceTunnelFlight.deleteTunnelFlight(item);
+ this.isLoading = false;
+ });
+ }
+
+ private getDataForGraph(): void {
+ this.isLoading = true;
+
+ // Get data to show in a table
+ let endDate = new Date();
+ endDate.setHours(0, 0, 0, 0);
+ let beginDate = this.computeBeginDateByPeriod(this.selectedPeriod, endDate);
+
+ this.serviceTunnelFlight
+ .getTunnelFlightsByMonth(beginDate, endDate)
+ .subscribe((data) => {
+ const allMonths = this.getMontsBetweenDates(beginDate, endDate);
+ const cumulatedTime = this.getCumulatedTimeByTypeByMonth(
+ data,
+ allMonths
+ );
+ this.computeTimeByType(data);
+ this.barChartData = {
+ labels: allMonths,
+ datasets: cumulatedTime,
+ };
+
+ this.isLoading = false;
+ });
+ }
+
+ private computeTimeByType(stats: TunnelFlightByMonth[]) {
+ this.stats = [];
+ from(stats)
+ .pipe(
+ groupBy((type) => type.type, { element: (p) => p.nb }),
+ mergeMap((group$) =>
+ group$.pipe(reduce((acc, cur) => [...acc, cur], [`${group$.key}`]))
+ ),
+ map((arr) => ({
+ id: arr[0],
+ values: arr.slice(1).reduce((a, b) => Number(a) + Number(b), 0),
+ }))
+ )
+ .subscribe((p) => {
+ console.log(p);
+ this.stats.push(p);
+ });
+ }
+
+ private getMontsBetweenDates(beginDate: Date, endDate: Date): Array {
+ let results: Array = [];
+ let tmpBeginDate = new Date(beginDate.getTime());
+ const tmpEndDate = new Date(endDate.getTime());
+
+ while (tmpBeginDate < tmpEndDate) {
+ results.push(formatDate(tmpBeginDate, "yy-MM", "en"));
+ tmpBeginDate.setMonth(tmpBeginDate.getMonth() + 1);
}
+
+ return results;
+ }
+
+ private getCumulatedTimeByTypeByMonth(
+ stats: TunnelFlightByMonth[],
+ allMonths: string[]
+ ): Array {
+ let tmpResults = new Map();
+
+ const disctintType = Array.from(new Set(stats.map((item) => item.type)));
+ disctintType.forEach((type) => {
+ tmpResults.set(
+ type,
+ Array.from({ length: allMonths.length }, (v, k) => 0)
+ );
+ });
+
+ for (let i = 0; i < allMonths.length; i++) {
+ const month = allMonths[i];
+ let filteredStats = stats.filter((d) => d.month == month);
+
+ if (filteredStats.length > 0) {
+ filteredStats.forEach((fs) => {
+ tmpResults.get(fs.type)[i] += fs.nb;
+ });
+ }
+ }
+
+ const results = Array.from(tmpResults, function (item) {
+ return { label: item[0], data: item[1] };
+ });
+
+ return results;
+ }
+
+ private footer = (tooltipItems: any) => {
+ let sum = 0;
+
+ tooltipItems.forEach(function (tooltipItem: any) {
+ sum += tooltipItem.parsed.y;
+ });
+
+ return "Sum: " + sum;
+ };
+
+ private computeBeginDateByPeriod(
+ selectedPeriod: String,
+ endDate: Date
+ ): Date {
+ let beginDate = new Date();
+
+ switch (selectedPeriod) {
+ case "currentYear":
+ beginDate = new Date(endDate.getFullYear(), 0, 1);
+ break;
+ case "12Months":
+ beginDate = this.dateService.addMonths(endDate, -12);
+ beginDate.setDate(1);
+ break;
+ case "all":
+ beginDate = this.dateService.addMonths(endDate, -120);
+ beginDate.setDate(1);
+ break;
+ }
+
+ return beginDate;
+ }
+
+ public delete(item: TunnelFlight) {
+ let data: Array = this.dataSourceTable.data;
+ data = data.filter((d) => d.id !== item.id);
+
+ this.dataSourceTable.data = data;
+ this.serviceTunnelFlight.deleteTunnelFlight(item);
+ }
}
diff --git a/Front/skydivelogs-app/src/app/login-user/login-user.component.html b/Front/skydivelogs-app/src/app/login-user/login-user.component.html
index 4e92fc6..885a037 100644
--- a/Front/skydivelogs-app/src/app/login-user/login-user.component.html
+++ b/Front/skydivelogs-app/src/app/login-user/login-user.component.html
@@ -1,36 +1,50 @@
-
diff --git a/Front/skydivelogs-app/src/app/login-user/login-user.component.ts b/Front/skydivelogs-app/src/app/login-user/login-user.component.ts
index 171db28..6c9773e 100644
--- a/Front/skydivelogs-app/src/app/login-user/login-user.component.ts
+++ b/Front/skydivelogs-app/src/app/login-user/login-user.component.ts
@@ -1,32 +1,34 @@
-import { Component, OnInit, ViewChild, AfterViewInit } from '@angular/core';
-import { Router, ActivatedRoute } from '@angular/router';
-import { FormBuilder, FormGroup, Validators } from '@angular/forms';
-import { MatInput } from '@angular/material/input';
+import { Component, OnInit, ViewChild, AfterViewInit } from "@angular/core";
+import { Router, ActivatedRoute } from "@angular/router";
+import { FormBuilder, FormGroup, Validators } from "@angular/forms";
+import { MatInput } from "@angular/material/input";
-import { first } from 'rxjs/operators';
+import { first } from "rxjs/operators";
-import { AuthenticationService } from '../../services/authentication.service';
+import { AuthenticationService } from "../../services/authentication.service";
@Component({
- selector: 'app-login-user',
- templateUrl: './login-user.component.html',
- styleUrls: ['./login-user.component.css'],
- standalone: false
+ selector: "app-login-user",
+ templateUrl: "./login-user.component.html",
+ styleUrls: ["./login-user.component.css"],
+ standalone: false,
})
export class LoginUserComponent implements OnInit, AfterViewInit {
loginForm: FormGroup;
loading = false;
submitted = false;
returnUrl: string;
- error = '';
- @ViewChild('username') userNameInput: MatInput;
+ error = "";
+ @ViewChild("username") userNameInput: MatInput;
- constructor(private formBuilder: FormBuilder,
- private route: ActivatedRoute,
- private router: Router,
- private authenticationService: AuthenticationService) {
+ constructor(
+ private formBuilder: FormBuilder,
+ private route: ActivatedRoute,
+ private router: Router,
+ private authenticationService: AuthenticationService
+ ) {
if (this.authenticationService.currentUserValue) {
- this.router.navigate(['/']);
+ this.router.navigate(["/"]);
}
}
@@ -37,15 +39,14 @@ export class LoginUserComponent implements OnInit, AfterViewInit {
ngOnInit() {
this.loginForm = this.formBuilder.group(
{
- username: ['', [Validators.required, Validators.minLength(3)]],
- password: ['', [Validators.required]]
+ username: ["", [Validators.required, Validators.minLength(3)]],
+ password: ["", [Validators.required]],
},
- { updateOn: 'submit' }
+ { updateOn: "submit" }
);
// get return url from route parameters or default to '/'
- this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/';
-
+ this.returnUrl = this.route.snapshot.queryParams["returnUrl"] || "/";
}
get formCtrls() {
@@ -57,17 +58,21 @@ export class LoginUserComponent implements OnInit, AfterViewInit {
if (this.loginForm.valid) {
this.loading = true;
- this.authenticationService.login(this.formCtrls.username.value, this.formCtrls.password.value)
- .pipe(first())
- .subscribe(
- data => {
- this.router.navigate([this.returnUrl]);
- },
- error => {
- this.error = error;
- this.loading = false;
- }
- );
+ this.authenticationService
+ .login(
+ this.formCtrls["username"].value,
+ this.formCtrls["password"].value
+ )
+ .pipe(first())
+ .subscribe(
+ (data) => {
+ this.router.navigate([this.returnUrl]);
+ },
+ (error) => {
+ this.error = error;
+ this.loading = false;
+ }
+ );
}
}
}
diff --git a/Front/skydivelogs-app/src/services/request-cache.service.ts b/Front/skydivelogs-app/src/services/request-cache.service.ts
index 589c22f..85b21bc 100644
--- a/Front/skydivelogs-app/src/services/request-cache.service.ts
+++ b/Front/skydivelogs-app/src/services/request-cache.service.ts
@@ -1,5 +1,5 @@
-import { Injectable } from '@angular/core';
-import { HttpRequest, HttpResponse } from '@angular/common/http';
+import { Injectable } from "@angular/core";
+import { HttpRequest, HttpResponse } from "@angular/common/http";
@Injectable()
export class RequestCache {
@@ -10,8 +10,8 @@ export class RequestCache {
}
get(req: HttpRequest): HttpResponse | undefined {
- const splittedUrl = req.urlWithParams.split('/');
- const url = splittedUrl[splittedUrl.length - 1] + '_' + req.method;
+ const splittedUrl = req.urlWithParams.split("/");
+ const url = splittedUrl[splittedUrl.length - 1] + "_" + req.method;
this.clearExpiredEntries();
const cached = this.cache.get(url);
@@ -24,8 +24,8 @@ export class RequestCache {
}
put(req: HttpRequest, response: HttpResponse): void {
- const splittedUrl = req.urlWithParams.split('/');
- const url = splittedUrl[splittedUrl.length - 1] + '_' + req.method;
+ const splittedUrl = req.urlWithParams.split("/");
+ const url = splittedUrl[splittedUrl.length - 1] + "_" + req.method;
const entry = { url, response, lastRead: Date.now() };
this.cache.set(url, entry);
@@ -36,7 +36,7 @@ export class RequestCache {
const maxAge = 30000;
const expired = Date.now() - maxAge;
- this.cache.forEach(expiredEntry => {
+ this.cache.forEach((expiredEntry) => {
if (expiredEntry.lastRead < expired) {
this.cache.delete(expiredEntry.url);
}
diff --git a/Front/skydivelogs-app/src/tsconfig.app.json b/Front/skydivelogs-app/src/tsconfig.app.json
deleted file mode 100644
index c1c97c7..0000000
--- a/Front/skydivelogs-app/src/tsconfig.app.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "extends": "../tsconfig.json",
- "compilerOptions": {
- "outDir": "../out-tsc/app",
- "baseUrl": "./",
- "types": []
- },
- "files": [
- "main.ts",
- "polyfills.ts"
- ]
-}
diff --git a/Front/skydivelogs-app/src/tsconfig.spec.json b/Front/skydivelogs-app/src/tsconfig.spec.json
deleted file mode 100644
index c89454b..0000000
--- a/Front/skydivelogs-app/src/tsconfig.spec.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "extends": "../tsconfig.json",
- "compilerOptions": {
- "outDir": "../out-tsc/spec",
- "baseUrl": "./",
- "types": [
- "jasmine",
- "node"
- ]
- },
- "files": [
- "test.ts",
- "polyfills.ts"
- ],
- "include": [
- "**/*.spec.ts",
- "**/*.d.ts"
- ]
-}
diff --git a/Front/skydivelogs-app/tsconfig.app.json b/Front/skydivelogs-app/tsconfig.app.json
new file mode 100644
index 0000000..3775b37
--- /dev/null
+++ b/Front/skydivelogs-app/tsconfig.app.json
@@ -0,0 +1,15 @@
+/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
+/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "outDir": "./out-tsc/app",
+ "types": []
+ },
+ "files": [
+ "src/main.ts"
+ ],
+ "include": [
+ "src/**/*.d.ts"
+ ]
+}
diff --git a/Front/skydivelogs-app/tsconfig.json b/Front/skydivelogs-app/tsconfig.json
index 4a3997b..263b4d7 100644
--- a/Front/skydivelogs-app/tsconfig.json
+++ b/Front/skydivelogs-app/tsconfig.json
@@ -1,25 +1,29 @@
+/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
+/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
{
"compileOnSave": false,
- "angularCompilerOptions": {
- "strictTemplates": true,
- },
"compilerOptions": {
- "importHelpers": true,
"outDir": "./dist/out-tsc",
+ "strict": true,
+ "noImplicitOverride": true,
+ "noPropertyAccessFromIndexSignature": true,
+ "noImplicitReturns": true,
+ "noFallthroughCasesInSwitch": true,
+ "skipLibCheck": true,
+ "isolatedModules": true,
"esModuleInterop": true,
- "sourceMap": true,
- "declaration": false,
- "moduleResolution": "node",
"experimentalDecorators": true,
- "target": "es2015",
- "typeRoots": [
- "node_modules/@types"
- ],
- "lib": [
- "es2017",
- "dom"
- ],
- "module": "esnext",
- "baseUrl": "./"
+ "moduleResolution": "bundler",
+ "importHelpers": true,
+ "target": "ES2022",
+ "module": "ES2022",
+ "strictPropertyInitialization": false,
+ "strictNullChecks": false
+ },
+ "angularCompilerOptions": {
+ "enableI18nLegacyMessageIdFormat": false,
+ "strictInjectionParameters": true,
+ "strictInputAccessModifiers": true,
+ "strictTemplates": true
}
-}
\ No newline at end of file
+}
diff --git a/Front/skydivelogs-app/tsconfig.spec.json b/Front/skydivelogs-app/tsconfig.spec.json
new file mode 100644
index 0000000..5fb748d
--- /dev/null
+++ b/Front/skydivelogs-app/tsconfig.spec.json
@@ -0,0 +1,15 @@
+/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
+/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "outDir": "./out-tsc/spec",
+ "types": [
+ "jasmine"
+ ]
+ },
+ "include": [
+ "src/**/*.spec.ts",
+ "src/**/*.d.ts"
+ ]
+}