From 8c88c5f24eab51b17759ffafc0fe67394082be15 Mon Sep 17 00:00:00 2001 From: rubikscraft Date: Sun, 20 Mar 2022 22:11:17 +0100 Subject: [PATCH] Add networkerror notify --- .../routes/api/user/usermanage.controller.ts | 1 - frontend/src/app/app.module.ts | 2 ++ .../components/copyfield/copyfield.module.ts | 2 -- .../app/components/header/header.module.ts | 2 -- frontend/src/app/guards/permission.guard.ts | 4 +-- frontend/src/app/models/api-error.ts | 4 +++ .../settings-syspref.component.ts | 8 ++--- .../settings-users.component.ts | 17 +++++---- frontend/src/app/services/api/api.service.ts | 17 +++++++-- .../src/app/services/api/syspref.service.ts | 1 - frontend/src/app/util/apierror.service.ts | 32 +++++++++++++++++ frontend/src/app/util/util.module.ts | 35 +++++++++++-------- 12 files changed, 87 insertions(+), 38 deletions(-) create mode 100644 frontend/src/app/models/api-error.ts create mode 100644 frontend/src/app/util/apierror.service.ts diff --git a/backend/src/routes/api/user/usermanage.controller.ts b/backend/src/routes/api/user/usermanage.controller.ts index 56a9e9f..75c4ed5 100644 --- a/backend/src/routes/api/user/usermanage.controller.ts +++ b/backend/src/routes/api/user/usermanage.controller.ts @@ -87,7 +87,6 @@ export class UserManageController { @Post('info') async getUser(@Body() body: UserInfoRequest): Promise { - console.log(body); const user = await this.usersService.findOne(body.username); if (HasFailed(user)) { this.logger.warn(user.getReason()); diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts index a288ec9..ca1b89d 100644 --- a/frontend/src/app/app.module.ts +++ b/frontend/src/app/app.module.ts @@ -8,6 +8,7 @@ import { AppRoutingModule } from './app.routing.module'; import { FooterModule } from './components/footer/footer.module'; import { HeaderModule } from './components/header/header.module'; import { GuardsModule } from './guards/guards.module'; +import { UtilModule } from './util/util.module'; @NgModule({ declarations: [AppComponent], @@ -17,6 +18,7 @@ import { GuardsModule } from './guards/guards.module'; PortalModule, MatSidenavModule, + UtilModule.forRoot(), GuardsModule, AppRoutingModule, diff --git a/frontend/src/app/components/copyfield/copyfield.module.ts b/frontend/src/app/components/copyfield/copyfield.module.ts index 2d321a2..a672f1b 100644 --- a/frontend/src/app/components/copyfield/copyfield.module.ts +++ b/frontend/src/app/components/copyfield/copyfield.module.ts @@ -3,7 +3,6 @@ import { NgModule } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatIconModule } from '@angular/material/icon'; import { MatInputModule } from '@angular/material/input'; -import { UtilModule } from 'src/app/util/util.module'; import { CopyFieldComponent } from './copyfield.component'; @NgModule({ declarations: [CopyFieldComponent], @@ -12,7 +11,6 @@ import { CopyFieldComponent } from './copyfield.component'; MatInputModule, MatIconModule, MatButtonModule, - UtilModule, ], exports: [CopyFieldComponent], }) diff --git a/frontend/src/app/components/header/header.module.ts b/frontend/src/app/components/header/header.module.ts index b63bf5e..feb76ae 100644 --- a/frontend/src/app/components/header/header.module.ts +++ b/frontend/src/app/components/header/header.module.ts @@ -5,7 +5,6 @@ import { MatIconModule } from '@angular/material/icon'; import { MatMenuModule } from '@angular/material/menu'; import { MatToolbarModule } from '@angular/material/toolbar'; import { RouterModule } from '@angular/router'; -import { UtilModule } from 'src/app/util/util.module'; import { HeaderComponent } from './header.component'; @NgModule({ @@ -16,7 +15,6 @@ import { HeaderComponent } from './header.component'; RouterModule, MatIconModule, MatMenuModule, - UtilModule, ], declarations: [HeaderComponent], exports: [HeaderComponent], diff --git a/frontend/src/app/guards/permission.guard.ts b/frontend/src/app/guards/permission.guard.ts index bc46c3e..a41a730 100644 --- a/frontend/src/app/guards/permission.guard.ts +++ b/frontend/src/app/guards/permission.guard.ts @@ -24,12 +24,12 @@ export class PermissionGuard implements CanActivate, CanActivateChild { childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot ) { - console.log('canActivateChild'); + //console.log('canActivateChild'); return await this.can(childRoute, state); } async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { - console.log('canActivate'); + //console.log('canActivate'); return await this.can(route, state); } diff --git a/frontend/src/app/models/api-error.ts b/frontend/src/app/models/api-error.ts new file mode 100644 index 0000000..ed7633b --- /dev/null +++ b/frontend/src/app/models/api-error.ts @@ -0,0 +1,4 @@ +export interface ApiError { + error: any; + url: RequestInfo; +} diff --git a/frontend/src/app/routes/settings/settings-syspref/settings-syspref.component.ts b/frontend/src/app/routes/settings/settings-syspref/settings-syspref.component.ts index 63555e8..1ed06cb 100644 --- a/frontend/src/app/routes/settings/settings-syspref/settings-syspref.component.ts +++ b/frontend/src/app/routes/settings/settings-syspref/settings-syspref.component.ts @@ -1,4 +1,4 @@ -import { Component, OnChanges, OnInit, SimpleChanges } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; import { AutoUnsubscribe } from 'ngx-auto-unsubscribe-decorator'; import { SysPreferenceResponse } from 'picsur-shared/dist/dto/api/pref.dto'; import { SysprefService as SysPrefService } from 'src/app/services/api/syspref.service'; @@ -6,7 +6,7 @@ import { SysprefService as SysPrefService } from 'src/app/services/api/syspref.s @Component({ templateUrl: './settings-syspref.component.html', }) -export class SettingsSysprefComponent implements OnInit, OnChanges { +export class SettingsSysprefComponent implements OnInit { render = true; preferences: SysPreferenceResponse[] = []; @@ -32,10 +32,6 @@ export class SettingsSysprefComponent implements OnInit, OnChanges { }); } - ngOnChanges(changes: SimpleChanges): void { - console.log('cahnges', changes); - } - private compareFlatObjectArray(a: any[], b: any[]): boolean { if (a.length !== b.length) { return false; diff --git a/frontend/src/app/routes/settings/settings-users/settings-users.component.ts b/frontend/src/app/routes/settings/settings-users/settings-users.component.ts index 108407d..ca43bce 100644 --- a/frontend/src/app/routes/settings/settings-users/settings-users.component.ts +++ b/frontend/src/app/routes/settings/settings-users/settings-users.component.ts @@ -32,12 +32,12 @@ export class SettingsUsersComponent implements OnInit { return this.updateSubject .pipe(throttleTime(500, undefined, { leading: true, trailing: true })) .subscribe(async (pageEvent: PageEvent) => { - let amount = await this.fetchUsers( + let success = await this.fetchUsers( pageEvent.pageSize, pageEvent.pageIndex ); - if (amount === 0) { - if ( pageEvent.previousPageIndex === pageEvent.pageIndex - 1){ + if (!success) { + if (pageEvent.previousPageIndex === pageEvent.pageIndex - 1) { this.paginator.previousPage(); } else { this.paginator.firstPage(); @@ -49,12 +49,15 @@ export class SettingsUsersComponent implements OnInit { private async fetchUsers( pageSize: number, pageIndex: number - ): Promise { + ): Promise { const result = await this.userManageService.getUsers(pageSize, pageIndex); - if (HasFailed(result)) return 0; + if (HasFailed(result)) return false; - this.dataSubject.next(result); + if (result.length > 0) { + this.dataSubject.next(result); + return true; + } - return result.length; + return false; } } diff --git a/frontend/src/app/services/api/api.service.ts b/frontend/src/app/services/api/api.service.ts index 84983b7..8b35cd6 100644 --- a/frontend/src/app/services/api/api.service.ts +++ b/frontend/src/app/services/api/api.service.ts @@ -3,6 +3,8 @@ import { ClassConstructor, plainToClass } from 'class-transformer'; import { ApiResponse, ApiSuccessResponse } from 'picsur-shared/dist/dto/api'; import { AsyncFailable, Fail, HasFailed } from 'picsur-shared/dist/types'; import { strictValidate } from 'picsur-shared/dist/util/validate'; +import { Subject } from 'rxjs'; +import { ApiError } from 'src/app/models/api-error'; import { MultiPartRequest } from '../../models/multi-part-request'; import { KeyService } from './key.service'; @@ -12,6 +14,12 @@ import { KeyService } from './key.service'; export class ApiService { private readonly logger = console; + private errorSubject = new Subject(); + + public get networkErrors() { + return this.errorSubject.asObservable(); + } + constructor(private keyService: KeyService) {} public async get( @@ -128,9 +136,12 @@ export class ApiService { options.headers = headers; return await window.fetch(url, options); - } catch (e: any) { - this.logger.warn(e); - return Fail('Something went wrong'); + } catch (error: any) { + this.errorSubject.next({ + error, + url, + }); + return Fail('Network Error'); } } } diff --git a/frontend/src/app/services/api/syspref.service.ts b/frontend/src/app/services/api/syspref.service.ts index 6fbec89..25aabc0 100644 --- a/frontend/src/app/services/api/syspref.service.ts +++ b/frontend/src/app/services/api/syspref.service.ts @@ -111,7 +111,6 @@ export class SysprefService { } private sync() { - console.warn('System preferences have been flushed'); this.sysprefObservable.next( ([] as SysPreferenceResponse[]).concat(this.snapshot) ); diff --git a/frontend/src/app/util/apierror.service.ts b/frontend/src/app/util/apierror.service.ts new file mode 100644 index 0000000..46daea0 --- /dev/null +++ b/frontend/src/app/util/apierror.service.ts @@ -0,0 +1,32 @@ +import { Injectable } from '@angular/core'; +import { AutoUnsubscribe } from 'ngx-auto-unsubscribe-decorator'; +import { SnackBarType } from '../models/snack-bar-type'; +import { ApiService } from '../services/api/api.service'; +import { UtilService } from './util.service'; + +@Injectable({ + providedIn: 'root', +}) +export class ApiErrorService { + constructor( + private apiSerivce: ApiService, + private utilService: UtilService + ) { + this.subscribeErrors(); + } + + @AutoUnsubscribe() + private subscribeErrors() { + return this.apiSerivce.networkErrors.subscribe((error) => { + let url = ''; + if (typeof error.url === 'string') url = error.url; + else url = error.url.url; + + if (url.startsWith('/api')) { + this.utilService.showSnackBar('Network Error', SnackBarType.Error); + } + + console.warn(error.error); + }); + } +} diff --git a/frontend/src/app/util/util.module.ts b/frontend/src/app/util/util.module.ts index 46dd8ad..f857f95 100644 --- a/frontend/src/app/util/util.module.ts +++ b/frontend/src/app/util/util.module.ts @@ -1,24 +1,31 @@ import { CommonModule } from '@angular/common'; -import { NgModule } from '@angular/core'; +import { ModuleWithProviders, NgModule } from '@angular/core'; import { MatSnackBarModule, MAT_SNACK_BAR_DEFAULT_OPTIONS } from '@angular/material/snack-bar'; import { RouterModule } from '@angular/router'; -import { UtilService } from './util.service'; +import { ApiErrorService } from './apierror.service'; @NgModule({ - declarations: [], - providers: [ - UtilService, - { - provide: MAT_SNACK_BAR_DEFAULT_OPTIONS, - useValue: { - duration: 4000, - horizontalPosition: 'left', - }, - }, - ], imports: [CommonModule, MatSnackBarModule, RouterModule], }) -export class UtilModule {} +export class UtilModule { + static forRoot(): ModuleWithProviders { + return { + ngModule: UtilModule, + providers: [ + { + provide: MAT_SNACK_BAR_DEFAULT_OPTIONS, + useValue: { + duration: 4000, + horizontalPosition: 'left', + }, + }, + ], + }; + } + + // Start apiErrorService + constructor(private apiErrorService: ApiErrorService) {} +}