From dd59a62e96159a4c3b0fb9beb079b359abf90470 Mon Sep 17 00:00:00 2001 From: Bastian Wagner Date: Wed, 18 Feb 2026 13:56:29 +0100 Subject: [PATCH] Api umgebaut --- api/src/app.module.ts | 2 +- .../modules/cylinder/cylinder.component.ts | 14 +++--- .../handover-dialog.component.html | 4 +- .../handover-dialog.component.ts | 4 +- .../modules/keys/create/create.component.ts | 16 +++---- client/src/app/modules/keys/keys.component.ts | 42 ++++++------------ .../ag-key-actions.component.ts | 16 +++---- client/src/app/shared/api.service.ts | 43 +++++++++++++++++-- 8 files changed, 78 insertions(+), 63 deletions(-) diff --git a/api/src/app.module.ts b/api/src/app.module.ts index bc7cf7f..2c53611 100644 --- a/api/src/app.module.ts +++ b/api/src/app.module.ts @@ -22,7 +22,7 @@ import { LogModule } from './modules/log/log.module'; envFilePath: ['.env'], isGlobal: true, }), - CacheModule.register({ ttl: 5000, isGlobal: true }), + CacheModule.register({ ttl: 1000, isGlobal: true }), DatabaseModule, AuthModule, UserModule, diff --git a/client/src/app/modules/cylinder/cylinder.component.ts b/client/src/app/modules/cylinder/cylinder.component.ts index aef82cf..5e9a986 100644 --- a/client/src/app/modules/cylinder/cylinder.component.ts +++ b/client/src/app/modules/cylinder/cylinder.component.ts @@ -45,17 +45,19 @@ export class CylinderComponent { } loadCylinders() { - this.api.getCylinders().subscribe({ - next: n => { - this.gridApi.setGridOption("rowData", n); - this.gridApi.setGridOption("loading", false); - } - }) + this.gridApi.setGridOption("loading", true); + this.api.refreshCylinders(); } onGridReady(params: GridReadyEvent) { this.gridApi = params.api; this.loadCylinders(); + this.api.cylinders.asObservable().subscribe({ + next: (data) => { + this.gridApi.setGridOption("rowData", data); + this.gridApi.setGridOption("loading", false); + } + }) } openCreateCylinder() { diff --git a/client/src/app/modules/keys/components/handover-dialog/handover-dialog.component.html b/client/src/app/modules/keys/components/handover-dialog/handover-dialog.component.html index 22f68e6..d5765d4 100644 --- a/client/src/app/modules/keys/components/handover-dialog/handover-dialog.component.html +++ b/client/src/app/modules/keys/components/handover-dialog/handover-dialog.component.html @@ -36,7 +36,7 @@ Datum der Übergabe - TT/MM/JJJJ + TT.MM.JJJJ (Beispiel: {{ exampleDate | date:'dd.MM.yyyy'}}) @@ -44,7 +44,7 @@ - diff --git a/client/src/app/modules/keys/components/handover-dialog/handover-dialog.component.ts b/client/src/app/modules/keys/components/handover-dialog/handover-dialog.component.ts index a70fcc9..0ea794b 100644 --- a/client/src/app/modules/keys/components/handover-dialog/handover-dialog.component.ts +++ b/client/src/app/modules/keys/components/handover-dialog/handover-dialog.component.ts @@ -28,7 +28,7 @@ import { MatIconModule } from '@angular/material/icon'; @Component({ selector: 'app-handover-dialog', - imports: [FormsModule, MatTabsModule, AgGridAngular, ReactiveFormsModule, MatDatepickerModule, MatFormFieldModule, MatInputModule, MatButtonModule, MatDialogModule, MatAutocompleteModule, MatProgressSpinnerModule, MatRadioModule, AsyncPipe, MatIconModule], + imports: [FormsModule, MatTabsModule, AgGridAngular, ReactiveFormsModule, MatDatepickerModule, MatFormFieldModule, MatInputModule, MatButtonModule, MatDialogModule, MatAutocompleteModule, MatProgressSpinnerModule, MatRadioModule, AsyncPipe, MatIconModule, DatePipe], providers: [ provideNativeDateAdapter(), { provide: LOCALE_ID, useValue: 'de-DE' }, @@ -47,6 +47,8 @@ export class HandoverDialogComponent { private datePipe = inject(DatePipe); private toast: HotToastService = inject(HotToastService); + public exampleDate = new Date(); + gridApi!: GridApi; gridOptions: GridOptions = { localeText: AG_GRID_LOCALE_DE, diff --git a/client/src/app/modules/keys/create/create.component.ts b/client/src/app/modules/keys/create/create.component.ts index d4bcfa2..eb66256 100644 --- a/client/src/app/modules/keys/create/create.component.ts +++ b/client/src/app/modules/keys/create/create.component.ts @@ -44,6 +44,12 @@ export class CreateKeyComponent { } async doSetup() { + this.api.cylinders.subscribe({ + next: data => { + this.cylinders = data; + this.createForm.controls.cylinder.patchValue(null); + } + }) await this.loadCylinders(); this.filteredCylinders = this.createForm.controls.cylinder.valueChanges.pipe( @@ -63,15 +69,7 @@ export class CreateKeyComponent { } loadCylinders() { - return new Promise(resolve => { - this.api.getCylinders().subscribe({ - next: n => { - this.cylinders = n; - this.createForm.controls.cylinder.patchValue(null); - resolve(null) - } - }); - }) + return this.api.refreshCylinders(); } diff --git a/client/src/app/modules/keys/keys.component.ts b/client/src/app/modules/keys/keys.component.ts index 08f66ab..369e4b2 100644 --- a/client/src/app/modules/keys/keys.component.ts +++ b/client/src/app/modules/keys/keys.component.ts @@ -35,7 +35,7 @@ export class KeysComponent { private dialog: MatDialog = inject(MatDialog); private route: ActivatedRoute = inject(ActivatedRoute) - cylinders: any[] = []; + // cylinders: any[] = []; gridApi!: GridApi; @@ -93,7 +93,6 @@ export class KeysComponent { , width: 140 , cellRenderer: AgKeyActionsComponent , sortable: false - // , onCellClicked: (event) => { this.deleteKey(event.data.id)} ,valueFormatter: (data: any) => { return data; }, } ], @@ -103,30 +102,15 @@ export class KeysComponent { pagination: true, } - - deleteKey(id: string) { - this.api.deleteKey(id).subscribe() - } - editKey(id: string) { } ngOnInit(): void { - this.api.getCylinders().subscribe({ - next: n => { - this.cylinders = n; - - this.setFilterToParams(); - }, - error: () => { - this.cylinders = []; - } - }) } + private setFilterToParams() { - console.log(this.route.snapshot.queryParams); const params = this.route.snapshot.queryParams; if (Object.keys(params).includes('handedOut')) { @@ -143,23 +127,21 @@ export class KeysComponent { loadKeys() { this.gridApi.setGridOption("loading", true); - this.api.getKeys().subscribe({ - next: n => { - this.gridApi.setGridOption("rowData", n); - this.gridApi.setGridOption("loading", false); - }, - error: () => { - this.gridApi.setGridOption("loading", false); - // set error in grid - this.toast.error('Fehler beim Laden der Schlüssel') - } - }) + this.api.refreshKeys(); } onGridReady(params: GridReadyEvent) { this.gridApi = params.api; - this.gridApi.addEventListener("cellEditingStopped", evt => this.cellEditEnd(evt)) + this.gridApi.addEventListener("cellEditingStopped", evt => this.cellEditEnd(evt)); + this.api.keys.asObservable().subscribe({ + next: keys => { + console.log(keys) + this.gridApi.setGridOption("rowData", keys); + this.gridApi.setGridOption("loading", false); + } + }) this.loadKeys(); + this.setFilterToParams(); } cellEditEnd(event: CellEditingStoppedEvent) { diff --git a/client/src/app/shared/ag-grid/components/ag-key-actions/ag-key-actions.component.ts b/client/src/app/shared/ag-grid/components/ag-key-actions/ag-key-actions.component.ts index 988e490..585e9ab 100644 --- a/client/src/app/shared/ag-grid/components/ag-key-actions/ag-key-actions.component.ts +++ b/client/src/app/shared/ag-grid/components/ag-key-actions/ag-key-actions.component.ts @@ -79,7 +79,7 @@ export class AgKeyActionsComponent implements ICellRendererAngularComp { }) ).subscribe({ next: () => { - this.setData(); + this.api.refreshKeys(); }, error: () => { this.params.api.setGridOption("loading", false); @@ -99,6 +99,7 @@ export class AgKeyActionsComponent implements ICellRendererAngularComp { if (n != null) { this.key.handedOut = n; this.params.api.refreshCells(); + this.api.refreshKeys(); } } }) @@ -111,24 +112,17 @@ export class AgKeyActionsComponent implements ICellRendererAngularComp { maxWidth: '100vw', maxHeight: '100vh' }).afterClosed().subscribe({ - next: n => { + next: async n => { if (n != null) { if (n == "") { n = null; } this.key.keyLost = n; this.params.api.refreshCells(); - this.api.updateKey(this.key).subscribe(); - this.setData(); + await this.api.updateKey(this.key).subscribe(); + this.api.refreshKeys(); } } }) } - - private setData() { - let data = this.params.api.getGridOption("rowData"); - data = data?.filter(d => d.id != this.key.id); - this.params.api.setGridOption("rowData", data); - this.params.api.setGridOption("loading", false); - } } diff --git a/client/src/app/shared/api.service.ts b/client/src/app/shared/api.service.ts index 70760c8..41e1f99 100644 --- a/client/src/app/shared/api.service.ts +++ b/client/src/app/shared/api.service.ts @@ -1,15 +1,22 @@ import { HttpClient } from '@angular/common/http'; import { inject, Injectable } from '@angular/core'; -import { Observable } from 'rxjs'; +import { BehaviorSubject, Observable } from 'rxjs'; import { IUser } from '../model/interface/user.interface'; import { IKey } from '../model/interface/key.interface'; import { ICylinder } from '../model/interface/cylinder.interface'; +import { HotToastService } from '@ngxpert/hot-toast'; @Injectable({ providedIn: 'root' }) export class ApiService { private http: HttpClient = inject(HttpClient); + private toast: HotToastService = inject(HotToastService); + + public keys: BehaviorSubject = new BehaviorSubject([]); + public cylinders: BehaviorSubject = new BehaviorSubject([]); + + constructor() { } @@ -26,10 +33,21 @@ export class ApiService { return this.http.get<{id: string, name: string}[]>('/api/role'); } - getKeys(): Observable { + private getKeys(): Observable { return this.http.get('api/key') } + refreshKeys(): void{ + this.getKeys().subscribe({ + next: keys => { + this.keys.next(keys); + }, + error: () => { + this.toast.error('Fehler beim Laden der Schlüssel') + } + }) + } + getLostKeys(): Observable { return this.http.get('api/key/lost') } @@ -82,10 +100,29 @@ export class ApiService { return this.http.put(`api/key/${id}/restore`, null); } - getCylinders(): Observable { + private getCylinders(): Observable { return this.http.get('api/cylinder'); } + /** + * Aktualisiert die Zylinder im Behaviour Subject + * cylinders + * @returns Promise wenn geladen + */ + refreshCylinders(): Promise { + return new Promise(resolve => { + this.getCylinders().subscribe({ + next: data => { + this.cylinders.next(data); + }, + error: () => { + this.toast.error('Fehler beim Laden der Zylinder') + }, + complete: () => resolve() + }) + }) + } + deleteCylinder(cylinder: ICylinder): Observable { return this.http.delete(`api/cylinder/${cylinder.id}`) }