Implémentation SkydiverId API

This commit is contained in:
Rampeur
2024-05-08 20:32:49 +02:00
parent 6dece821a8
commit 7c3f0c9648
54 changed files with 2323 additions and 1395 deletions
@@ -12,7 +12,7 @@
</button>
<mat-spinner [diameter]="32" [hidden]="!loading" color="accent" class="align-middle ms-2"></mat-spinner>
<span [hidden]="jumpsCount || loading" class="ms-2 fst-italic">Aucun saut à afficher pour le moment.</span>
<span [hidden]="!loading" class="ms-2 fst-italic">Actualisation des sauts en cours</span>
<span [hidden]="!loading" class="ms-2 fst-italic">Chargement des sauts en cours</span>
</form>
</div>
<div class="col-md-6 col-xs-12 px-0">
@@ -224,7 +224,7 @@
</ng-container>
</td>
</ng-container> -->
<!-- Video Column -->
<!-- Video Column
<ng-container matColumnDef="video">
<th class="pl-3" mat-header-cell *matHeaderCellDef> Video </th>
<td class="pl-3 text-nowrap" mat-cell *matCellDef="let element">
@@ -236,6 +236,41 @@
</ngx-skeleton-loader>
}
</td>
</ng-container> -->
<!-- Files Column -->
<ng-container matColumnDef="files">
<th class="pl-3" mat-header-cell *matHeaderCellDef> Fichiers </th>
<td class="pl-3 text-nowrap" mat-cell *matCellDef="let element">
@if (element.files) {
@for (file of element.files; track $index) {
@switch (file.type) {
@case ('video') {
<button mat-button (click)="openViewDialog(element)" color="navy-light">
<mat-icon fontIcon="videocam me-2"></mat-icon> {{ file.type }}
</button>
}
@case ('image') {
<button mat-button (click)="openViewDialog(element)" color="navy-light">
<mat-icon fontIcon="image me-2"></mat-icon> {{ file.type }}
</button>
}
@case ('kml') {
<button mat-button (click)="openViewDialog(element)" color="navy-light">
<mat-icon fontIcon="language me-2"></mat-icon> {{ file.type }}
</button>
}
@default {
<button mat-button (click)="openViewDialog(element)" color="navy-light">
<mat-icon fontIcon="description me-2"></mat-icon> {{ file.type }}
</button>
}
}
}
}
@if (!element.numero) {
<ngx-skeleton-loader [theme]="{width: '30px', height: '13px', marginBottom: '0px'}"></ngx-skeleton-loader>
}
</td>
</ng-container>
<!-- Actions Column -->
<ng-container matColumnDef="actions">
@@ -247,13 +282,17 @@
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu [hidden]="!showAdd" #actionMenu="matMenu">
<button mat-menu-item [routerLink]="['/jump', element.slug]">
<mat-icon aria-label="Voir" fontIcon="visibility" color="info" class="mini"></mat-icon>
<span class="text-info">Détails</span>
</button>
<button mat-menu-item (click)="openEditDialog(element)">
<mat-icon aria-label="Modifier" fontIcon="edit" color="primary" class="mini"></mat-icon>
<span class="text-primary">Modifier</span>
</button>
<button mat-menu-item (click)="openDeleteDialog(element)">
<mat-icon aria-label="Supprimer" fontIcon="delete" color="danger" class="mini"></mat-icon>
<span class="text-danger">Supprimer</span>
<mat-icon aria-label="Supprimer" fontIcon="delete" color="raspberry" class="mini"></mat-icon>
<span class="text-raspberry">Supprimer</span>
</button>
</mat-menu>
}
@@ -21,7 +21,7 @@ import { take } from 'rxjs/operators';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
import { FrenchPaginator } from 'src/app/components/shared/french-paginator.component';
import { ColumnDefinition, Errors, Jump, JumpList, JumpListConfig, jumpColumns } from 'src/app/core/models';
import { ColumnDefinition, Errors, Jump, JumpByDay, JumpFile, JumpFileType, JumpList, JumpListConfig, jumpColumns } from 'src/app/core/models';
import { JumpsService, JumpTableService } from 'src/app/core/services';
import { JumpAddDialogComponent, JumpDeleteDialogComponent, JumpEditDialogComponent, JumpViewDialogComponent } from 'src/app/components/logbook/dialogs'
@@ -41,6 +41,7 @@ import { JumpAddDialogComponent, JumpDeleteDialogComponent, JumpEditDialogCompon
})
export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChecked {
private _jumps: Subscription = new Subscription();
private _subscriptions: Array<Subscription> = [];
//private _jump: Subscription = new Subscription();
private _query: JumpListConfig = { type: 'all', filters: {} };
//private _lastjump: Jump = {} as Jump;
@@ -53,13 +54,13 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe
'numero', 'date', 'lieu', 'oaci', 'aeronef',
'imat', 'hauteur', 'voile', 'taille', 'categorie',
'module', 'participants', 'programme', 'accessoires',
'zone', 'video', 'actions'
'zone', 'files', 'actions'
];*/
public displayedColumns: string[] = [
'numero', 'date', 'lieu', 'aeronef',
'hauteur', 'voile', 'categorie',
'participants', 'zone', 'accessoires',
'video', 'actions'
'files', 'actions'
];
//public displayedColumns: string[] = jumpColumns.map((col) => col.key)
public columnsSchema: Array<ColumnDefinition> = jumpColumns;
@@ -115,7 +116,9 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe
ngOnDestroy() {
this._jumps.unsubscribe();
//this._jump.unsubscribe();
this._subscriptions.forEach(subscription => {
subscription.unsubscribe();
});
}
ngAfterContentChecked() {
@@ -155,6 +158,9 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe
const jumps$: Observable<JumpList> = this._jumpsService.query(this._query);
this._jumps = jumps$.subscribe({
next: (data: JumpList) => {
//this.updateJumps(data.jumps);
//this.linkSkydiverIdJumps();
//this.getKmlJumpFiles(data.jumps);
this.loading = false;
this.jumps = new MatTableDataSource<Jump>(data.jumps);
this.jumpsCount = data.jumpsCount;
@@ -170,12 +176,150 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe
});
}
linkSkydiverIdJumps() {
const config: JumpListConfig = { type: 'all', filters: {} } as JumpListConfig;
config.filters.limit = 200;
config.filters.offset = 0;
config.filters.dateRangeStart = '2024-01-01 00:00:00';
//const year = new Date().getFullYear();
//config.filters.dateRangeEnd = `${year}-12-31 23:59:59`;
config.filters.dateRangeEnd = '2024-12-31 23:59:59';
//console.log(config.filters);
const subscription: Subscription = this._jumpsService.getAllByDay(config)
.pipe(take(1))
.subscribe({
next: (days) => {
this._resetErrors();
//console.log('getAllByDay : ', days);
days.forEach(day => {
this.loadSkydiverIdJumps(day, config);
});
},
error: (err) => {
this.errors = err;
}
});
this._subscriptions.push(subscription);
}
loadSkydiverIdJumps(day: JumpByDay, config: JumpListConfig) {
config.filters.dateRangeStart = `${day.jumps[0].date!.substring(0, 10)} 00:00:00`;
config.filters.dateRangeEnd = `${day.jumps[0].date!.substring(0, 10)} 23:59:59`;
const subscription: Subscription = this._jumpsService.getAllFromSkydiverIdApi(config)
.pipe(take(1))
.subscribe({
next: (data) => {
if (data.items.length) {
const diff = day.count - data.items.length;
if (diff < 0) {
console.error(`${diff} ${diff > 1 ? 'données' : 'donnée'} altimètre de trop le ${day.jumps[0].date!.substring(0, 10)}`);
} else {
if (diff > 0) {
console.error(`${diff}/${day.count} ${diff > 1 ? 'données altimètre manquantes' : 'donnée altimètre manquante'} le ${day.jumps[0].date!.substring(0, 10)}`, day.jumps, data.items);
}
console.log(`${day.count} ${day.count > 1 ? 'sauts' : 'saut'} le ${data.items[0].date!.substring(0, 10)}`, day.jumps.sort((a, b) => b.numero! - a.numero!), data.items);
data.items.map((jump, index) => {
const file: JumpFile = {
name: jump.name,
path: `/Volumes/Storage/Skydive/X2_Logs/${day.jumps[index].date!.substring(0, 4)}/`,
type: JumpFileType.CSV
} as JumpFile;
this._subscriptions.push(
this._jumpsService.saveX2Data(day.jumps[index].slug!, file, jump)
.pipe(take(1))
.subscribe({
next: (jump) => {
this._resetErrors();
console.log(`Le fichier ${file.name} a été ajouté au saut n°${jump.numero} !`, 'OK');
},
error: (err) => {
this.errors = err;
}
})
);
return jump;
});
}
//console.log(`${day.count} ${day.count > 1 ? 'sauts' : 'saut'} le ${day.jumps[0].date!.substring(0, 10)}`);
//console.log(`${data.items.length} ${data.items.length > 1 ? 'sauts' : 'saut'} le ${data.items[0].date!.substring(0, 10)}`, data);
} else {
console.info('Aucune données altimètre pour le ', day.jumps[0].date!.substring(0, 10));
}
},
error: (err) => {
console.error('getAllFromSkydiverIdApi error');
this.errors = err;
}
});
this._subscriptions.push(subscription);
}
updateJumps(jumps: Array<Jump>) {
jumps.map(jump => {
jump.files = [];
if (jump.dossier !== "" && jump.video !== "") {
const file: JumpFile = {
name: jump.video!,
path: jump.dossier!,
type: JumpFileType.VIDEO
} as JumpFile;
this._subscriptions.push(
this._jumpsService.saveFile(jump.slug, file)
.pipe(take(1))
.subscribe({
next: (file) => {
this._resetErrors();
jump.files.push(file);
console.log(`Le fichier ${file.name} a été ajouté au saut n°${jump.numero} !`, 'OK');
},
error: (err) => {
this.errors = err;
}
})
);
}
return jump;
});
}
getKmlJumpFiles(jumps: Array<Jump>) {
jumps.map(jump => {
if (jump.x2data !== null) {
//console.log(`Le fichier ${jump.x2data.name} existe pour le saut n°${jump.numero} !`, `https://skydiver.id/api/jump/${jump.x2data.id}/kml`);
const file: JumpFile = {
name: jump.x2data.name.substring(0, -4) + '.kml',
path: `/X2_Kmls/${jump.date.substring(0, 4)}/`,
type: JumpFileType.KML
} as JumpFile;
this._subscriptions.push(
this._jumpsService.saveKml(jump.slug, file)
.pipe(take(1))
.subscribe({
next: (file) => {
this._resetErrors();
console.log(`Le fichier ${file.path}${file.name} a été ajouté au saut n°${jump.numero} !`, 'OK');
},
error: (err) => {
this.errors = err;
}
})
);
/*
*/
}
return jump;
});
}
deleteJump(slug: string) {
this.isDeleting = true;
this._jumpsService.destroy(slug).pipe(take(1))
this._subscriptions.push(
this._jumpsService.destroy(slug)
.pipe(take(1))
.subscribe(() => {
this.router.navigateByUrl('/');
});
})
);
}
openDeleteDialog(jump: Jump): void {
@@ -183,12 +327,15 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe
width: '60vw',
data: jump
});
dialogRef.afterClosed().pipe(take(1))
this._subscriptions.push(
dialogRef.afterClosed()
.pipe(take(1))
.subscribe(result => {
if (result != undefined) {
this._onDelete(result.slug);
}
});
})
);
}
openEditDialog(jump: Jump): void {
@@ -196,12 +343,15 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe
width: '70vw',
data: jump
});
dialogRef.afterClosed().pipe(take(1))
.subscribe(result => {
if (result != undefined) {
this._onEdit(result);
}
});
this._subscriptions.push(
dialogRef.afterClosed()
.pipe(take(1))
.subscribe(result => {
if (result != undefined) {
this._onEdit(result);
}
})
);
}
openViewDialog(jump: Jump): void {
@@ -230,20 +380,22 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe
private _onDelete(slug: string): void {
try {
this.isDeleting = true;
this._jumpsService.destroy(slug)
.pipe(take(1))
.subscribe({
next: () => {
this._resetErrors();
this._openSnackBar(`Le saut a été supprimé !`, 'OK');
this.runQuery();
this.tableRefresh = !this.tableRefresh;
this._jumpTableService.updateTableRefresh(this.tableRefresh);
},
error: (err) => {
this.errors = err;
}
});
this._subscriptions.push(
this._jumpsService.destroy(slug)
.pipe(take(1))
.subscribe({
next: () => {
this._resetErrors();
this._openSnackBar(`Le saut a été supprimé !`, 'OK');
this.runQuery();
this.tableRefresh = !this.tableRefresh;
this._jumpTableService.updateTableRefresh(this.tableRefresh);
},
error: (err) => {
this.errors = err;
}
})
);
} catch (error) {
console.error(error);
}
@@ -252,21 +404,23 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe
private _onEdit(jump: Jump): void {
try {
this.isSubmitting = true;
this._jumpsService.update(jump)
.pipe(take(1))
.subscribe({
next: (jump) => {
this._resetErrors();
this._openSnackBar(`Le saut n°${jump.numero} a été mis à jour !`, 'OK');
this.runQuery();
this.tableRefresh = !this.tableRefresh;
this._jumpTableService.updateTableRefresh(this.tableRefresh);
},
error: (err) => {
this.errors = err;
this.isSubmitting = false;
}
});
this._subscriptions.push(
this._jumpsService.update(jump)
.pipe(take(1))
.subscribe({
next: (jump) => {
this._resetErrors();
this._openSnackBar(`Le saut n°${jump.numero} a été mis à jour !`, 'OK');
this.runQuery();
this.tableRefresh = !this.tableRefresh;
this._jumpTableService.updateTableRefresh(this.tableRefresh);
},
error: (err) => {
this.errors = err;
this.isSubmitting = false;
}
})
);
} catch (error) {
console.error(error);
}