Add a page to show the hours of tunnel

This commit is contained in:
Sébastien ANDRE
2023-06-22 14:28:46 +02:00
parent d651d365b7
commit ef15986db3
12 changed files with 271 additions and 73 deletions

View File

@@ -31,6 +31,10 @@
<a routerLink="/newjump" routerLinkActive="active" (click)="snav.toggle()" skipLocationChange>{{ 'App_Nav_NewJump' | translate }}</a>
<hr class="splitter">
</mat-nav-list>
<mat-nav-list>
<mat-icon aria-hidden="false" aria-label="List of tunnel flights">list_alt</mat-icon>
<a routerLink="/tunnelFlights" routerLinkActive="active" (click)="snav.toggle()" skipLocationChange>{{ 'App_Nav_TunnelFlights' | translate }}</a>
</mat-nav-list>
<mat-nav-list>
<mat-icon aria-hidden="false" aria-label="Add flights in tunnel">add_circle</mat-icon>
<a routerLink="/newTunnelFlight" routerLinkActive="active" (click)="snav.toggle()" skipLocationChange>{{ 'App_Nav_NewTunnelFlight' | translate }}</a>

View File

@@ -28,6 +28,7 @@ import { UserProfileComponent } from "./user-profile/user-profile.component";
import { ListOfImagesComponent } from "./list-of-images/list-of-images.component";
import { JumpInfosComponent } from './jump-infos/jump-infos.component';
import { NewTunnelFlightComponent } from './new-tunnel-flight/new-tunnel-flight.component';
import { ListOfTunnelFlightsComponent } from './list-of-tunnel-flights/list-of-tunnel-flights.component';
import { DateService } from "../services/date.service";
import { AircraftService } from "../services/aircraft.service";
@@ -67,6 +68,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 { JwtAuthInterceptor } from "../interceptor/jwt-auth.interceptor";
import { ErrorInterceptor } from "../interceptor/error.interceptor";
@@ -118,6 +120,12 @@ const appRoutes: Routes = [
component: NewTunnelFlightComponent,
canActivate: [AuthGuardService]
},
{
path: "tunnelFlights",
component: ListOfTunnelFlightsComponent,
canActivate: [AuthGuardService]
},
{ path: "login", component: LoginComponent },
];
@@ -152,7 +160,8 @@ export function initConfig(configService: ConfigurationHelper) {
UserProfileComponent,
ListOfImagesComponent,
JumpInfosComponent,
NewTunnelFlightComponent
NewTunnelFlightComponent,
ListOfTunnelFlightsComponent
],
imports: [
RouterModule.forRoot(
@@ -191,7 +200,8 @@ export function initConfig(configService: ConfigurationHelper) {
MatRadioModule,
MatSidenavModule,
MatListModule,
MatToolbarModule
MatToolbarModule,
NgChartsModule
],
exports: [HttpClientModule],
providers: [

View File

@@ -1,76 +1,82 @@
<div class="content">
<div>
<button mat-raised-button color="accent" [routerLink]="['/newjump']" [routerLinkActive]="['active']" skipLocationChange>{{ 'List_Jump_Add' | translate }}</button>
</div>
<div>
<button mat-raised-button color="accent" [routerLink]="['/newjump']" [routerLinkActive]="['active']"
skipLocationChange>{{ 'List_Jump_Add' | translate }}</button>
</div>
<mat-progress-bar [mode]="'indeterminate'" *ngIf="isLoading"></mat-progress-bar>
<mat-progress-bar [mode]="'indeterminate'" *ngIf="isLoading"></mat-progress-bar>
<div>
<table mat-table [dataSource]="dataSourceTable">
<ng-container matColumnDef="infos">
<th mat-header-cell *matHeaderCellDef style="min-width: 80px;"></th>
<td mat-cell *matCellDef="let element" style="text-align: left;">
<mat-icon aria-hidden="false" aria-label="Additional informations of the jump"
style="cursor: pointer;" (click)='openDialog(element, false)'>info</mat-icon>
<mat-icon aria-hidden="false" aria-label="Special jump" [style.visibility]="element.notes != undefined ? 'visible' : 'hidden'">sticky_note_2</mat-icon>
<mat-icon aria-hidden="false" aria-label="Special jump" [style.visibility]="element.isSpecial ? 'visible' : 'hidden'">celebration</mat-icon>
</td>
</ng-container>
<div>
<table mat-table [dataSource]="dataSourceTable">
<ng-container matColumnDef="infos">
<th mat-header-cell *matHeaderCellDef style="min-width: 80px;"></th>
<td mat-cell *matCellDef="let element" style="text-align: left;">
<mat-icon aria-hidden="false" aria-label="Additional informations of the jump"
style="cursor: pointer;" (click)='openDialog(element, false)'>info</mat-icon>
<mat-icon aria-hidden="false" aria-label="Special jump"
[style.visibility]="element.notes != undefined ? 'visible' : 'hidden'">sticky_note_2</mat-icon>
<mat-icon aria-hidden="false" aria-label="Special jump"
[style.visibility]="element.isSpecial ? 'visible' : 'hidden'">celebration</mat-icon>
</td>
</ng-container>
<ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef style="min-width: 70px;">{{ 'List_Jump_Header_Num' | translate }}</th>
<td mat-cell *matCellDef="let element; let i = index">
{{ paginator.length - ( (paginator.pageIndex * paginator.pageSize ) + i ) }}
</td>
</ng-container>
<ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef style="min-width: 70px;">{{ 'List_Jump_Header_Num' | translate }}
</th>
<td mat-cell *matCellDef="let element; let i = index">
{{ paginator.length - ( (paginator.pageIndex * paginator.pageSize ) + i ) }}
</td>
</ng-container>
<ng-container matColumnDef="jumpDate">
<th mat-header-cell *matHeaderCellDef>{{ 'List_Jump_Header_Date' | translate }}</th>
<td mat-cell *matCellDef="let element">
<span class="smallSpanWithBreakWord" [innerHTML]="element.jumpDate | date: 'yyyy-MM-dd'"></span>
</td>
</ng-container>
<ng-container matColumnDef="jumpDate">
<th mat-header-cell *matHeaderCellDef>{{ 'List_Jump_Header_Date' | translate }}</th>
<td mat-cell *matCellDef="let element">
<span class="smallSpanWithBreakWord" [innerHTML]="element.jumpDate | date: 'yyyy-MM-dd'"></span>
</td>
</ng-container>
<ng-container matColumnDef="jumpType">
<th mat-header-cell *matHeaderCellDef style="min-width: 100px;">{{ 'List_Jump_Header_JumpType' | translate }}</th>
<td mat-cell *matCellDef="let element">
<span class="smallSpanWithBreakWord" [innerHTML]="element.jumpType.name"></span>
</td>
</ng-container>
<ng-container matColumnDef="jumpType">
<th mat-header-cell *matHeaderCellDef style="min-width: 100px;">{{ 'List_Jump_Header_JumpType' |
translate }}</th>
<td mat-cell *matCellDef="let element">
<span class="smallSpanWithBreakWord" [innerHTML]="element.jumpType.name"></span>
</td>
</ng-container>
<ng-container matColumnDef="aircraft">
<th mat-header-cell *matHeaderCellDef style="min-width: 110px;">{{ 'List_Jump_Header_Aircraft' | translate }}</th>
<td mat-cell *matCellDef="let element">
<span class="smallSpanWithBreakWord" [innerHTML]="element.aircraft.name"></span>
</td>
</ng-container>
<ng-container matColumnDef="aircraft">
<th mat-header-cell *matHeaderCellDef style="min-width: 110px;">{{ 'List_Jump_Header_Aircraft' |
translate }}</th>
<td mat-cell *matCellDef="let element">
<span class="smallSpanWithBreakWord" [innerHTML]="element.aircraft.name"></span>
</td>
</ng-container>
<ng-container matColumnDef="dropZone">
<th mat-header-cell *matHeaderCellDef>{{ 'List_Jump_Header_Dz' | translate }}</th>
<td mat-cell *matCellDef="let element">
<span class="spanWithBreakWord" [innerHTML]="element.dropZone.name"></span>
</td>
</ng-container>
<ng-container matColumnDef="dropZone">
<th mat-header-cell *matHeaderCellDef>{{ 'List_Jump_Header_Dz' | translate }}</th>
<td mat-cell *matCellDef="let element">
<span class="spanWithBreakWord" [innerHTML]="element.dropZone.name"></span>
</td>
</ng-container>
<ng-container matColumnDef="gear">
<th mat-header-cell *matHeaderCellDef>{{ 'List_Jump_Header_Id' | translate }}</th>
<td mat-cell *matCellDef="let element">{{element.gear.name}}</td>
</ng-container>
<ng-container matColumnDef="gear">
<th mat-header-cell *matHeaderCellDef>{{ 'List_Jump_Header_Id' | translate }}</th>
<td mat-cell *matCellDef="let element">{{element.gear.name}}</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef style="min-width: 70px;"></th>
<td mat-cell *matCellDef="let element" style="text-align: left;">
<mat-icon aria-hidden="false" aria-label="Delete this jump" style="cursor: pointer;"
(click)='delete(element)'>delete</mat-icon>
<mat-icon aria-hidden="false" aria-label="Update some informations of the jump" style="cursor: pointer; margin-left: 10px;"
(click)='openDialog(element, true)'>edit</mat-icon>
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef style="min-width: 70px;"></th>
<td mat-cell *matCellDef="let element" style="text-align: left;">
<mat-icon aria-hidden="false" aria-label="Delete this jump" style="cursor: pointer;"
(click)='delete(element)'>delete</mat-icon>
<mat-icon aria-hidden="false" aria-label="Update some informations of the jump"
style="cursor: pointer; margin-left: 10px;" (click)='openDialog(element, true)'>edit</mat-icon>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
</div>
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
</div>
<mat-paginator #paginator [pageSize]="20" (page)="pageChanged($event)" showFirstLastButtons></mat-paginator>
</div>
<mat-paginator #paginator [pageSize]="20" (page)="pageChanged($event)" showFirstLastButtons></mat-paginator>
</div>

View File

@@ -0,0 +1,13 @@
<div class="content">
<mat-progress-bar [mode]="'indeterminate'" *ngIf="isLoading"></mat-progress-bar>
<div>
<canvas baseChart style="width: 50%;"
[data]="barChartData"
[options]="barChartOptions"
[plugins]="barChartPlugins"
[legend]="barChartLegend"
[type]="barChartType" >
</canvas>
</div>
</div>

View File

@@ -0,0 +1,21 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ListOfTunnelFlightsComponent } from './list-of-tunnel-flights.component';
describe('ListOfTunnelFlightsComponent', () => {
let component: ListOfTunnelFlightsComponent;
let fixture: ComponentFixture<ListOfTunnelFlightsComponent>;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [ListOfTunnelFlightsComponent]
});
fixture = TestBed.createComponent(ListOfTunnelFlightsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,93 @@
import { Component, OnInit } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { ChartConfiguration, ChartData } from 'chart.js';
import { TunnelService } from '../../services/tunnel.service';
import { ServiceComm } from '../../services/service-comm.service';
import { TunnelFlightService } from "../../services/tunnel-flight.service";
@Component({
selector: 'app-list-of-tunnel-flights',
templateUrl: './list-of-tunnel-flights.component.html',
styleUrls: ['./list-of-tunnel-flights.component.css']
})
export class ListOfTunnelFlightsComponent implements OnInit {
public barChartLegend = true;
public barChartPlugins = [];
public barChartData: ChartData<'bar'>;
public barChartOptions: ChartConfiguration['options'];
public barChartType: string;
public isLoading: boolean = false;
constructor(private serviceComm: ServiceComm,
private serviceTunnel: TunnelService,
private serviceTunnelFlight: TunnelFlightService,
private translateService: TranslateService) { }
ngOnInit() {
this.serviceComm.forceTranslateTitle.subscribe((data) => {
if (data === true) {
this.updateTitle();
}
});
this.updateTitle();
this.isLoading = true;
this.getData();
}
private updateTitle() {
this.translateService.get("ListTunnelFlight_Title").subscribe(
data => { this.serviceComm.UpdatedComponentTitle(data); }
);
}
private getData(): void {
this.barChartType = "bar";
this.barChartData = {
labels: ['2006', '2007', '2008', '2009', '2010', '2011', '2012'],
datasets: [
{ data: [65, 59, 80, 81, 56, 55, 40], label: 'Series A' },
{ data: [28, 48, 40, 19, 86, 27, 90], label: 'Series B' }
]
};
this.barChartOptions = {
responsive: false,
plugins: {
legend: {
display: true
},
tooltip: {
callbacks: {
footer: this.footer,
}
}
},
interaction: {
intersect: false,
mode: 'nearest',
axis: 'x'
},
scales: {
x: {
stacked: true
},
y: {
stacked: true
}
}
};
this.isLoading = false;
}
private footer = (tooltipItems) => {
let sum = 0;
tooltipItems.forEach(function (tooltipItem) {
sum += tooltipItem.parsed.y;
});
return 'Sum: ' + sum;
};
}

View File

@@ -47,10 +47,10 @@ export class NewTunnelFlightComponent implements OnInit {
private pendingAddRequest: boolean;
constructor(private serviceComm: ServiceComm,
private serviceTunnel: TunnelService,
private serviceTunnelFlight: TunnelFlightService,
private translateService: TranslateService,
private statsService: StatsService) { }
private serviceTunnel: TunnelService,
private serviceTunnelFlight: TunnelFlightService,
private translateService: TranslateService,
private statsService: StatsService) { }
ngOnInit() {
this.serviceComm.forceTranslateTitle.subscribe((data) => {

View File

@@ -37,6 +37,7 @@
"ListGears_Title" : "List of gears",
"ListAircrafts_Title" : "List of aircrafts",
"NewTunnelFlight_Title" : "New tunnel flights",
"ListTunnelFlight_Title" : "List of hours of tunnel",
"App_Footer" : "Web software to log your skydive jumps - v",
"App_Nav_Summary" : "Summary",
@@ -48,6 +49,7 @@
"App_Nav_Gears" : "List of gears",
"App_Nav_Logout" : "Logout",
"App_Nav_NewTunnelFlight" : "Add tunnel time",
"App_Nav_TunnelFlights": "The tunnel flights",
"List_Aircrafts_Add" : "Add a aircraft",
"List_Aircrafts_Header_Id" : "ID",
@@ -116,5 +118,8 @@
"NewTunnelFlight_ChooseTunnel": "Choose the tunnel",
"NewTunnelFlight_Minutes": "Minutes of the flight",
"NewTunnelFlight_Comments": "Comments",
"NewTunnelFlight_Submit": "Submit"
"NewTunnelFlight_Submit": "Submit",
"NewTunnelFlight_Comments_Lbl": "Comments",
"NewTunnelFlight_Minutes_Lbl": "Time of flight (minutes)",
"NewTunnelFlight_Date_Lbl": "Date of flight"
}

View File

@@ -37,6 +37,7 @@
"ListGears_Title" : "Liste des pièges",
"ListAircrafts_Title" : "Liste des avions",
"NewTunnelFlight_Title" : "Nouveaux créneaux de soufflerie",
"ListTunnelFlight_Title" : "Heures de tunnel",
"App_Footer" : "Application pour enregistrer ses sauts de parachutisme - v",
"App_Nav_Summary" : "Récapitulatif",
@@ -48,6 +49,7 @@
"App_Nav_Gears" : "Pièges",
"App_Nav_Logout" : "Se déconnecter",
"App_Nav_NewTunnelFlight" : "Ajouter du temps en tunnel",
"App_Nav_TunnelFlights": "Les vols en soufflerie",
"List_Aircrafts_Add" : "Ajouter un avion",
"List_Aircrafts_Header_Id" : "ID",
@@ -116,5 +118,8 @@
"NewTunnelFlight_ChooseTunnel": "Choisir le tunnel",
"NewTunnelFlight_Minutes": "Temps de vol(minutes)",
"NewTunnelFlight_Comments": "Commentaires",
"NewTunnelFlight_Submit": "Ajouter"
"NewTunnelFlight_Submit": "Ajouter",
"NewTunnelFlight_Comments_Lbl": "Commentaires",
"NewTunnelFlight_Minutes_Lbl": "Temps de vol(minutes)",
"NewTunnelFlight_Date_Lbl": "Date des vols"
}