import { Component, AfterContentChecked, Input, ViewChild, OnChanges, OnDestroy, computed, Signal, WritableSignal } from '@angular/core'; import { CommonModule, DecimalPipe, DatePipe } from '@angular/common'; import { UntypedFormBuilder, UntypedFormGroup, Validators, FormsModule, ReactiveFormsModule } from '@angular/forms'; import { Router, RouterLink } from '@angular/router'; import { MatButtonModule } from '@angular/material/button'; import { MatCardModule } from '@angular/material/card'; import { MatDialog, MatDialogModule } from '@angular/material/dialog'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatIconModule } from '@angular/material/icon'; import { MatInputModule } from '@angular/material/input'; import { MatMenuModule } from '@angular/material/menu'; import { MatNativeDateModule } from '@angular/material/core'; import { MatPaginator, MatPaginatorModule } from '@angular/material/paginator'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { MatSort, MatSortModule } from '@angular/material/sort'; import { MatTableDataSource, MatTableModule } from '@angular/material/table'; import { MatSnackBar, MatSnackBarHorizontalPosition, MatSnackBarModule, MatSnackBarVerticalPosition } from '@angular/material/snack-bar'; import { Observable, Subject, Subscription } from 'rxjs'; import { take } from 'rxjs/operators'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { ColumnDefinition, Errors, Jump, JumpList, JumpListConfig, jumpColumns } from 'src/app/core/models'; import { JumpsService, JumpTableService } from 'src/app/core/services'; import { JumpAddDialogComponent, JumpDeleteDialogComponent, JumpEditDialogComponent } from 'src/app/components/shared/dialogs' @Component({ standalone: true, imports: [ CommonModule, DecimalPipe, DatePipe, RouterLink, FormsModule, ReactiveFormsModule, NgxSkeletonLoaderModule, MatButtonModule, MatCardModule, MatDialogModule, MatFormFieldModule, MatIconModule, MatInputModule, MatNativeDateModule, MatMenuModule, MatPaginatorModule, MatProgressSpinnerModule, MatSnackBarModule, MatSortModule, MatTableModule, JumpAddDialogComponent, JumpDeleteDialogComponent, JumpEditDialogComponent ], selector: 'huapp-jump-table', styleUrls: ['./jump-table.component.scss'], templateUrl: './jump-table.component.html' }) export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChecked { private _subject: Subject = new Subject(); private _jumps: Subscription = new Subscription(); private _jump: Subscription = new Subscription(); private _query: JumpListConfig = { type: 'all', filters: {} }; private _lastjump: Jump = {} as Jump; private _currentPage = 1; public errors!: Errors; public jump: Jump = {} as Jump; public jumps!: MatTableDataSource; public jumpsCount = 0; public displayedColumns: string[] = [ 'numero', 'date', 'lieu', 'oaci', 'aeronef', 'imat', 'hauteur', 'voile', 'taille', 'categorie', 'module', 'participants', 'programme', 'accessoires', 'zone', 'video', 'actions' ]; //public displayedColumns: string[] = jumpColumns.map((col) => col.key) public columnsSchema: Array = jumpColumns; public loading = false; public isSubmitting = false; public isDeleting = false; public searchForm: UntypedFormGroup; public valid: any = {}; public tableRefresh = false; public jumpRefresh = false; @ViewChild(MatSort) sort!: MatSort; @ViewChild(MatPaginator) paginator!: MatPaginator; constructor( private router: Router, private _jumpsService: JumpsService, private _jumpTableService: JumpTableService, private dialog: MatDialog, private fb: UntypedFormBuilder, private snackBar: MatSnackBar ) { this._resetErrors(); this.searchForm = this.fb.group({ //numero: ['', Validators.required] numero: '' }); } @Input() title = ''; @Input() limit = 0; @Input() refresh = false; @Input() showAdd = false; @Input() isUser = false; @Input() set config(config: JumpListConfig) { if (config) { this._query = config; this._currentPage = 1; } } get config(): JumpListConfig { return this._query; } ngOnChanges() { this.loading = true; this._query = this.config; this.runQuery(); //this.refresh = false; console.log('ngOnChanges event in jump-table component'); } ngOnDestroy() { this._jumps.unsubscribe(); this._jump.unsubscribe(); } ngAfterContentChecked() { //console.log('jump-table ngAfterContentChecked', this.tableRefresh, this._jumpTableService.tableRefresh); /*if (this.tableRefresh != this._jumpTableService.tableRefresh) { this.tableRefresh = this._jumpTableService.tableRefresh; console.log('refresh table', this.tableRefresh, this._jumpTableService.tableRefresh); }*/ if (this.jumpRefresh != this._jumpTableService.jumpRefresh) { this.jumpRefresh = this._jumpTableService.jumpRefresh; this.runQuery(); console.log('table has been refreshed in jump-table component'); } } runQuery() { const jump$: Observable = this._jumpsService.getLastJump(); this._jump = jump$.subscribe((jump) => { this._lastjump = jump; }); if (this.limit) { this._query.filters.limit = this.limit; this._query.filters.offset = (this.limit * (this._currentPage - 1)); } else { this._query.filters.limit = 0; this._query.filters.offset = 0; } const jumps$: Observable = this._jumpsService.query(this._query); this._jumps = jumps$.subscribe({ next: (data: JumpList) => { this.loading = false; this.jumps = new MatTableDataSource(data.jumps); this.jumpsCount = data.jumpsCount; this.paginator.length = data.jumpsCount; this.jumps.paginator = this.paginator; this.jumps.sort = this.sort; this._resetErrors(); //this.tableRefresh = !this.tableRefresh; //this._jumpTableService.updateJumpRefresh(this.tableRefresh); }, error: (err) => { this.errors = err; } }); } deleteJump(slug: string) { this.isDeleting = true; this._jumpsService.destroy(slug).pipe(take(1)) .subscribe(() => { this.router.navigateByUrl('/'); }); } openAddDialog(): void { const dialogRef = this.dialog.open(JumpAddDialogComponent, { width: '70vw', data: this.jump }); dialogRef.afterClosed().pipe(take(1)) .subscribe(result => { if (result != undefined) { this._onEntry(result); } }); } 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); } }); } getErrorMessage() { if (this.searchForm.controls['numero'].errors !== null) { return 'Vous devez indiquer une valeur'; } return ''; } submitForm() { if (this.searchForm.valid) { this._query.filters.numero = this.searchForm.value.numero; this._resetErrors(); this.runQuery(); } } 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; } }); } catch (error) { console.error(error); } } private _onEdit(jump: Jump): void { try { this.isSubmitting = true; console.log(jump); 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); } } private _onEntry(entry: NonNullable): void { try { this.isSubmitting = true; Object.assign(this.jump, entry); this._jumpsService.save(this.jump) .pipe(take(1)) .subscribe({ next: (jump) => { this._openSnackBar(`Le saut n°${jump.numero} a été ajouté !`, 'OK'); this._resetErrors(); this.runQuery(); }, error: (err) => { this.errors = err; this.isSubmitting = false; } }); } catch (error) { console.error(error); } } private _openSnackBar(content: string, title: string) { this.snackBar.open(content, title, { horizontalPosition: 'end', verticalPosition: 'bottom', duration: 4000, }); } private _resetErrors(): void { this.errors = { errors: {} }; } inputHandler(e: any, id: number, key: string) { if (!this.valid[id]) { this.valid[id] = {} } this.valid[id][key] = e.target.validity.valid } disableSubmit(id: number) { if (this.valid[id]) { return Object.values(this.valid[id]).some((item) => item === false) } return false } /* isAllSelected() { return this.jumps.data.every((item) => item.isSelected) } isAnySelected() { return this.jumps.data.some((item) => item.isSelected) } selectAll(event: any) { this.jumps.data = this.jumps.data.map((item) => ({ ...item, isSelected: event.checked, })) } */ }