Ajout du composant 'jump' (détail d'un saut)

This commit is contained in:
Julien Gautier
2023-10-04 14:16:29 +02:00
parent b0c9dbd647
commit 37cbba6cad
10 changed files with 303 additions and 3 deletions
+4
View File
@@ -10,6 +10,10 @@ const routes: Routes = [
path: 'dashboard',
loadChildren: () => import('./components/dashboard/dashboard.module').then(m => m.DashboardModule)
},
{
path: 'jump',
loadChildren: () => import('./components/jump/jump.module').then(m => m.JumpModule)
},
{
path: 'logbook',
loadChildren: () => import('./components/logbook/logbook.module').then(m => m.LogbookModule)
+2 -3
View File
@@ -11,8 +11,7 @@ import { AuthModule } from './components/auth/auth.module';
import { DashboardModule } from './components/dashboard/dashboard.module';
import { SpinnerComponent } from './components/shared';
import { FullComponent } from 'src/app/components/shared/layout';
//import { FullComponent } from 'src/app/components/shared/layout/full.component';
//import { HeaderComponent, FooterComponent, FullComponent } from 'src/app/components/shared/layout';
//import { HeaderComponent, FooterComponent } from 'src/app/components/shared/layout';
registerLocaleData(localeFr);
@@ -26,8 +25,8 @@ registerLocaleData(localeFr);
BrowserAnimationsModule,
SpinnerComponent,
FullComponent,
//HeaderComponent, FooterComponent, FullComponent,
DashboardModule
//HeaderComponent, FooterComponent
],
providers: [ Title, { provide: LOCALE_ID, useValue: 'fr-FR' } ],
bootstrap: [ AppComponent ]
+1
View File
@@ -1,6 +1,7 @@
export * from './auth/auth.component';
export * from './calculator/calculator.component';
export * from './dashboard/dashboard.component';
export * from './jump/jump.component';
export * from './logbook/logbook.component';
export * from './profile/profile.component';
export * from './shared';
@@ -0,0 +1,24 @@
import { Injectable, } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs';
import { Jump } from 'src/app/core/models';
import { JumpsService } from 'src/app/core/services';
import { catchError } from 'rxjs/operators';
@Injectable()
export class JumpResolver implements Resolve<Jump> {
constructor(
private _jumpsService: JumpsService,
private router: Router
) { }
resolve(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<any> {
return this._jumpsService.get(route.params['slug'])
.pipe(catchError(() => this.router.navigateByUrl('/')));
}
}
@@ -0,0 +1,22 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { JumpComponent } from './jump.component';
import { JumpResolver } from './jump-resolver.service';
import { AuthGuard } from 'src/app/core/services';
const routes: Routes = [
{
path: ':slug',
component: JumpComponent,
canActivate: [AuthGuard],
resolve: {
jump: JumpResolver
}
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class JumpRoutingModule { }
@@ -0,0 +1,71 @@
<div class="content">
<h1 class="my-0">Saut n°{{ jump.numero }} <small class="text-muted">le {{ jump.date | date: 'dd/MM/yyyy' }} à {{ jump.lieu }}</small></h1>
<hr />
<section class="row mb-3">
<div class="col-lg-6 col-md-12">
<dl class="dl-horizontal">
<dt class="text-accent fw-normal">Lieu:</dt>
<dd>{{jump.lieu}}</dd>
<dt class="text-accent fw-normal">Oaci:</dt>
<dd>{{jump.oaci}}</dd>
<dt class="text-accent fw-normal">Aeronef:</dt>
<dd>{{jump.aeronef}}</dd>
<dt class="text-accent fw-normal">Imat:</dt>
<dd>{{jump.imat}}</dd>
<dt class="text-accent fw-normal">Voile:</dt>
<dd>{{jump.voile}}</dd>
<dt class="text-accent fw-normal">Taille:</dt>
<dd>{{jump.taille}} ft<sup>2</sup></dd>
<dt class="text-accent fw-normal">Programme:</dt>
<dd>{{jump.programme}}</dd>
<dt class="text-accent fw-normal">Participants:</dt>
<dd>{{jump.participants}}</dd>
</dl>
</div>
<div class="col-lg-6 col-md-12">
<dl class="dl-horizontal">
<dt class="text-accent fw-normal">Hauteur:</dt>
<dd>{{jump.hauteur}} m</dd>
<dt class="text-accent fw-normal">Deploiement:</dt>
<dd>{{jump.deploiement}} m</dd>
<dt class="text-accent fw-normal">Categorie:</dt>
<dd>{{jump.categorie}}</dd>
<dt class="text-accent fw-normal">Module:</dt>
<dd>{{jump.module}}</dd>
<dt class="text-accent fw-normal">Accessoires:</dt>
<dd>{{jump.accessoires}}</dd>
<dt class="text-accent fw-normal">Zone:</dt>
<dd>{{jump.zone}}</dd>
<dt class="text-accent fw-normal">Video:</dt>
<dd>{{jump.dossier}}{{jump.video}}</dd>
</dl>
</div>
<div class="col-xs-12 mb-2">
<span *ngFor="let sautant of jump.sautants" class="badge rounded-pill bg-primary mb-2 me-1 pe-3 py-1 fw-normal text-dark">
<mat-icon class="align-middle me-1" fontIcon="person"></mat-icon>
{{ sautant }}
</span>
<span class="badge rounded-pill bg-accent mb-2 me-1 pe-3 py-1 fw-normal text-dark">
<mat-icon class="align-middle me-1" fontIcon="person"></mat-icon>
ju_solide
</span>
</div>
</section>
<section class="border-top pt-4 d-flex">
<!--
<huapp-jump-meta [jump]="jump" class="me-2"></huapp-jump-meta>
<span class="flex-spacer"></span>
-->
<span class="flex-spacer"></span>
<span [hidden]="!canModify">
<button mat-button color="primary" (click)="openEditDialog(jump)" class="me-1">
<mat-icon aria-label="Modifier" fontIcon="edit"></mat-icon>
Modifier
</button>
<button mat-button color="danger" (click)="openDeleteDialog(jump)">
<mat-icon aria-label="Supprimer" fontIcon="delete"></mat-icon>
Supprimer
</button>
</span>
</section>
</div>
@@ -0,0 +1,21 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { JumpComponent } from './jump.component';
describe('JumpComponent', () => {
let component: JumpComponent;
let fixture: ComponentFixture<JumpComponent>;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [JumpComponent]
});
fixture = TestBed.createComponent(JumpComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
+139
View File
@@ -0,0 +1,139 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
import { MatButtonModule } from '@angular/material/button';
import { MatNativeDateModule } from '@angular/material/core';
import { MatDialog, MatDialogModule } from '@angular/material/dialog';
import { MatIconModule } from '@angular/material/icon';
import { MatSnackBar, MatSnackBarHorizontalPosition, MatSnackBarModule, MatSnackBarVerticalPosition } from '@angular/material/snack-bar';
import { Observable, Subscription } from 'rxjs';
import { take } from 'rxjs/operators';
import { Errors, Jump, User } from 'src/app/core/models';
import { JumpsService, UserService } from 'src/app/core/services';
import { JumpDeleteDialogComponent, JumpEditDialogComponent } from 'src/app/components/shared/dialogs'
@Component({
standalone: true,
imports: [
CommonModule, RouterModule,
MatButtonModule, MatDialogModule, MatIconModule, MatNativeDateModule, MatSnackBarModule,
JumpDeleteDialogComponent, JumpEditDialogComponent
],
selector: 'huapp-jump',
templateUrl: './jump.component.html',
styleUrls: ['./jump.component.scss']
})
export class JumpComponent implements OnInit, OnDestroy {
private _currentUser: Subscription = new Subscription();
private _data: Subscription = new Subscription();
public errors!: Errors;
public jump: Jump = {} as Jump;
public currentUser: User = {} as User;
public canModify = false;
constructor(
private route: ActivatedRoute,
private router: Router,
private dialog: MatDialog,
private _jumpsService: JumpsService,
private _userService: UserService,
private _snackBar: MatSnackBar
) { }
ngOnInit() {
// Retreive the prefetched jump
const data$: Observable<any> = this.route.data;
this._data = data$.subscribe((data: { jump: Jump }) => {
this.jump = data.jump;
});
// Load the current user's data
const currentUser$: Observable<User> = this._userService.currentUser;
this._currentUser = currentUser$.subscribe((userData: User) => {
this.currentUser = userData;
this.canModify = this.currentUser.username === this.jump.author.username;
});
}
ngOnDestroy() {
this._data.unsubscribe();
this._currentUser.unsubscribe();
}
openDeleteDialog(jump: Jump): void {
const dialogRef = this.dialog.open(JumpDeleteDialogComponent, {
width: '60vw',
data: jump
});
dialogRef.afterClosed().pipe(take(1))
.subscribe(result => {
if (result != undefined) {
this._onDelete(result.slug);
}
});
}
openEditDialog(jump: Jump): void {
const dialogRef = this.dialog.open(JumpEditDialogComponent, {
width: '70vw',
data: jump
});
dialogRef.afterClosed().pipe(take(1))
.subscribe(result => {
if (result != undefined) {
this._onEdit(result);
}
});
}
private _onDelete(slug: string): void {
try {
this._jumpsService.destroy(slug)
.pipe(take(1))
.subscribe({
next: () => {
this.router.navigateByUrl('/logbook');
},
error: (err) => {
this.errors = err;
}
});
} catch (error) {
console.error(error);
}
}
private _onEdit(jump: Jump): void {
try {
let previousValues: Jump = {} as Jump;
Object.assign(previousValues, this.jump);
this._jumpsService.update(jump)
.pipe(take(1))
.subscribe({
next: (jump) => {
this._resetErrors();
this._openSnackBar(`Le saut n°${jump.numero} a été mis à jour !`, 'Annuler');
this.jump = jump;
},
error: (err) => {
this.errors = err;
}
});
} catch (error) {
console.error(error);
}
}
private _openSnackBar(content: string, title: string) {
this._snackBar.open(content, title, {
horizontalPosition: <MatSnackBarHorizontalPosition>'end',
verticalPosition: <MatSnackBarVerticalPosition>'bottom',
duration: 4000,
});
}
private _resetErrors(): void {
this.errors = { errors: {} };
}
}
+19
View File
@@ -0,0 +1,19 @@
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { JumpComponent } from './jump.component';
import { JumpResolver } from './jump-resolver.service';
import { JumpRoutingModule } from './jump-routing.module';
@NgModule({
imports: [
JumpRoutingModule,
JumpComponent
],
providers: [
JumpResolver
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class JumpModule { }