Add networkerror notify

This commit is contained in:
rubikscraft
2022-03-20 22:11:17 +01:00
parent 26c3918bcc
commit 8c88c5f24e
12 changed files with 87 additions and 38 deletions

View File

@@ -87,7 +87,6 @@ export class UserManageController {
@Post('info') @Post('info')
async getUser(@Body() body: UserInfoRequest): Promise<UserInfoResponse> { async getUser(@Body() body: UserInfoRequest): Promise<UserInfoResponse> {
console.log(body);
const user = await this.usersService.findOne(body.username); const user = await this.usersService.findOne(body.username);
if (HasFailed(user)) { if (HasFailed(user)) {
this.logger.warn(user.getReason()); this.logger.warn(user.getReason());

View File

@@ -8,6 +8,7 @@ import { AppRoutingModule } from './app.routing.module';
import { FooterModule } from './components/footer/footer.module'; import { FooterModule } from './components/footer/footer.module';
import { HeaderModule } from './components/header/header.module'; import { HeaderModule } from './components/header/header.module';
import { GuardsModule } from './guards/guards.module'; import { GuardsModule } from './guards/guards.module';
import { UtilModule } from './util/util.module';
@NgModule({ @NgModule({
declarations: [AppComponent], declarations: [AppComponent],
@@ -17,6 +18,7 @@ import { GuardsModule } from './guards/guards.module';
PortalModule, PortalModule,
MatSidenavModule, MatSidenavModule,
UtilModule.forRoot(),
GuardsModule, GuardsModule,
AppRoutingModule, AppRoutingModule,

View File

@@ -3,7 +3,6 @@ import { NgModule } from '@angular/core';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon'; import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input'; import { MatInputModule } from '@angular/material/input';
import { UtilModule } from 'src/app/util/util.module';
import { CopyFieldComponent } from './copyfield.component'; import { CopyFieldComponent } from './copyfield.component';
@NgModule({ @NgModule({
declarations: [CopyFieldComponent], declarations: [CopyFieldComponent],
@@ -12,7 +11,6 @@ import { CopyFieldComponent } from './copyfield.component';
MatInputModule, MatInputModule,
MatIconModule, MatIconModule,
MatButtonModule, MatButtonModule,
UtilModule,
], ],
exports: [CopyFieldComponent], exports: [CopyFieldComponent],
}) })

View File

@@ -5,7 +5,6 @@ import { MatIconModule } from '@angular/material/icon';
import { MatMenuModule } from '@angular/material/menu'; import { MatMenuModule } from '@angular/material/menu';
import { MatToolbarModule } from '@angular/material/toolbar'; import { MatToolbarModule } from '@angular/material/toolbar';
import { RouterModule } from '@angular/router'; import { RouterModule } from '@angular/router';
import { UtilModule } from 'src/app/util/util.module';
import { HeaderComponent } from './header.component'; import { HeaderComponent } from './header.component';
@NgModule({ @NgModule({
@@ -16,7 +15,6 @@ import { HeaderComponent } from './header.component';
RouterModule, RouterModule,
MatIconModule, MatIconModule,
MatMenuModule, MatMenuModule,
UtilModule,
], ],
declarations: [HeaderComponent], declarations: [HeaderComponent],
exports: [HeaderComponent], exports: [HeaderComponent],

View File

@@ -24,12 +24,12 @@ export class PermissionGuard implements CanActivate, CanActivateChild {
childRoute: ActivatedRouteSnapshot, childRoute: ActivatedRouteSnapshot,
state: RouterStateSnapshot state: RouterStateSnapshot
) { ) {
console.log('canActivateChild'); //console.log('canActivateChild');
return await this.can(childRoute, state); return await this.can(childRoute, state);
} }
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
console.log('canActivate'); //console.log('canActivate');
return await this.can(route, state); return await this.can(route, state);
} }

View File

@@ -0,0 +1,4 @@
export interface ApiError {
error: any;
url: RequestInfo;
}

View File

@@ -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 { AutoUnsubscribe } from 'ngx-auto-unsubscribe-decorator';
import { SysPreferenceResponse } from 'picsur-shared/dist/dto/api/pref.dto'; import { SysPreferenceResponse } from 'picsur-shared/dist/dto/api/pref.dto';
import { SysprefService as SysPrefService } from 'src/app/services/api/syspref.service'; 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({ @Component({
templateUrl: './settings-syspref.component.html', templateUrl: './settings-syspref.component.html',
}) })
export class SettingsSysprefComponent implements OnInit, OnChanges { export class SettingsSysprefComponent implements OnInit {
render = true; render = true;
preferences: SysPreferenceResponse[] = []; 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 { private compareFlatObjectArray(a: any[], b: any[]): boolean {
if (a.length !== b.length) { if (a.length !== b.length) {
return false; return false;

View File

@@ -32,12 +32,12 @@ export class SettingsUsersComponent implements OnInit {
return this.updateSubject return this.updateSubject
.pipe(throttleTime(500, undefined, { leading: true, trailing: true })) .pipe(throttleTime(500, undefined, { leading: true, trailing: true }))
.subscribe(async (pageEvent: PageEvent) => { .subscribe(async (pageEvent: PageEvent) => {
let amount = await this.fetchUsers( let success = await this.fetchUsers(
pageEvent.pageSize, pageEvent.pageSize,
pageEvent.pageIndex pageEvent.pageIndex
); );
if (amount === 0) { if (!success) {
if ( pageEvent.previousPageIndex === pageEvent.pageIndex - 1){ if (pageEvent.previousPageIndex === pageEvent.pageIndex - 1) {
this.paginator.previousPage(); this.paginator.previousPage();
} else { } else {
this.paginator.firstPage(); this.paginator.firstPage();
@@ -49,12 +49,15 @@ export class SettingsUsersComponent implements OnInit {
private async fetchUsers( private async fetchUsers(
pageSize: number, pageSize: number,
pageIndex: number pageIndex: number
): Promise<number> { ): Promise<boolean> {
const result = await this.userManageService.getUsers(pageSize, pageIndex); 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;
} }
} }

View File

@@ -3,6 +3,8 @@ import { ClassConstructor, plainToClass } from 'class-transformer';
import { ApiResponse, ApiSuccessResponse } from 'picsur-shared/dist/dto/api'; import { ApiResponse, ApiSuccessResponse } from 'picsur-shared/dist/dto/api';
import { AsyncFailable, Fail, HasFailed } from 'picsur-shared/dist/types'; import { AsyncFailable, Fail, HasFailed } from 'picsur-shared/dist/types';
import { strictValidate } from 'picsur-shared/dist/util/validate'; 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 { MultiPartRequest } from '../../models/multi-part-request';
import { KeyService } from './key.service'; import { KeyService } from './key.service';
@@ -12,6 +14,12 @@ import { KeyService } from './key.service';
export class ApiService { export class ApiService {
private readonly logger = console; private readonly logger = console;
private errorSubject = new Subject<ApiError>();
public get networkErrors() {
return this.errorSubject.asObservable();
}
constructor(private keyService: KeyService) {} constructor(private keyService: KeyService) {}
public async get<T extends Object>( public async get<T extends Object>(
@@ -128,9 +136,12 @@ export class ApiService {
options.headers = headers; options.headers = headers;
return await window.fetch(url, options); return await window.fetch(url, options);
} catch (e: any) { } catch (error: any) {
this.logger.warn(e); this.errorSubject.next({
return Fail('Something went wrong'); error,
url,
});
return Fail('Network Error');
} }
} }
} }

View File

@@ -111,7 +111,6 @@ export class SysprefService {
} }
private sync() { private sync() {
console.warn('System preferences have been flushed');
this.sysprefObservable.next( this.sysprefObservable.next(
([] as SysPreferenceResponse[]).concat(this.snapshot) ([] as SysPreferenceResponse[]).concat(this.snapshot)
); );

View File

@@ -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);
});
}
}

View File

@@ -1,24 +1,31 @@
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core'; import { ModuleWithProviders, NgModule } from '@angular/core';
import { import {
MatSnackBarModule, MatSnackBarModule,
MAT_SNACK_BAR_DEFAULT_OPTIONS MAT_SNACK_BAR_DEFAULT_OPTIONS
} from '@angular/material/snack-bar'; } from '@angular/material/snack-bar';
import { RouterModule } from '@angular/router'; import { RouterModule } from '@angular/router';
import { UtilService } from './util.service'; import { ApiErrorService } from './apierror.service';
@NgModule({ @NgModule({
declarations: [],
providers: [
UtilService,
{
provide: MAT_SNACK_BAR_DEFAULT_OPTIONS,
useValue: {
duration: 4000,
horizontalPosition: 'left',
},
},
],
imports: [CommonModule, MatSnackBarModule, RouterModule], imports: [CommonModule, MatSnackBarModule, RouterModule],
}) })
export class UtilModule {} export class UtilModule {
static forRoot(): ModuleWithProviders<UtilModule> {
return {
ngModule: UtilModule,
providers: [
{
provide: MAT_SNACK_BAR_DEFAULT_OPTIONS,
useValue: {
duration: 4000,
horizontalPosition: 'left',
},
},
],
};
}
// Start apiErrorService
constructor(private apiErrorService: ApiErrorService) {}
}