From 8bd61e52b76ec8c64a7de894fb165e303db8a532 Mon Sep 17 00:00:00 2001 From: Alexis Hernandez Date: Sun, 11 Mar 2018 12:27:44 -0600 Subject: [PATCH] web-ui: Add ErrorService --- web-ui/src/app/app.component.ts | 1 + web-ui/src/app/app.module.ts | 2 + web-ui/src/app/services/error.service.ts | 92 ++++++++++++++++++++++++ 3 files changed, 95 insertions(+) create mode 100644 web-ui/src/app/services/error.service.ts diff --git a/web-ui/src/app/app.component.ts b/web-ui/src/app/app.component.ts index 78a8b03..99e38a8 100644 --- a/web-ui/src/app/app.component.ts +++ b/web-ui/src/app/app.component.ts @@ -24,6 +24,7 @@ export class AppComponent { englishLang(): Object { return { + 'message.serverUnavailable': 'The server unavailable, please try again in a minute', 'action.find': 'Find', 'label.transactionId': 'Transaction Id' }; diff --git a/web-ui/src/app/app.module.ts b/web-ui/src/app/app.module.ts index e8380fb..283ca0d 100644 --- a/web-ui/src/app/app.module.ts +++ b/web-ui/src/app/app.module.ts @@ -12,6 +12,7 @@ import { ToastrModule } from 'ngx-toastr'; import { NgHttpLoaderModule } from 'ng-http-loader/ng-http-loader.module' +import { ErrorService } from './services/error.service'; import { LanguageService } from './services/language.service'; import { NotificationService } from './services/notification.service'; import { TransactionsService } from './services/transactions.service'; @@ -50,6 +51,7 @@ import { TransactionFinderComponent } from './components/transaction-finder/tran TranslateModule.forRoot(), ], providers: [ + ErrorService, LanguageService, NotificationService, TransactionsService diff --git a/web-ui/src/app/services/error.service.ts b/web-ui/src/app/services/error.service.ts new file mode 100644 index 0000000..a7a5051 --- /dev/null +++ b/web-ui/src/app/services/error.service.ts @@ -0,0 +1,92 @@ +import { Injectable } from '@angular/core'; +import { AbstractControl, FormGroup } from '@angular/forms/src/model'; + +import { TranslateService } from '@ngx-translate/core'; + +import { NotificationService } from './notification.service'; + +@Injectable() +export class ErrorService { + + constructor( + private translateService: TranslateService, + private notificationService: NotificationService) { } + + renderServerErrors(form: FormGroup, response: any) { + if (response.error.errors == null) { + // server error responses are consistent, if the errors array is not defined + // it is very likely that there are issues with the server. + this.translateService.get('message.serverUnavailable') + .subscribe(msg => this.notificationService.error(msg)); + + return; + } + + response.error.errors.forEach((element: any) => { + // field errors are handled here, different errors should be handled globally + if (element.type === 'field-validation-error') { + const fieldName = element.field; + const message = element.message; + if (form == null || !this.hasFieldName(form, fieldName)) { + this.notificationService.error(`${fieldName}: ${message}`); + } else { + this.setFieldError(form, fieldName, message); + } + } else { + const message = element.message; + this.notificationService.error(message); + } + }); + } + + hasWrongValue(form: FormGroup, fieldName: string): boolean { + return this.getFieldErrors(form, fieldName).length > 0; + } + + // a field is correct only if it is filled and have no errors + hasCorrectValue(form: FormGroup, fieldName: string): boolean { + const control = this.findFieldControl(form, fieldName); + // field found && user changed it && it doesn't hold a wrong value + const isCorrect = control && !control.pristine && !this.hasWrongValue(form, fieldName); + + return isCorrect; + } + + // right now we are rendering one error only for a field + getFieldError(form: FormGroup, fieldName: string): string { + return this.getFieldErrors(form, fieldName)[0]; + } + + getFieldErrors(form: FormGroup, fieldName: string): string[] { + const control = this.findFieldControl(form, fieldName); + if (control && control.touched && control.errors) { + return this.getErrors(control); + } else { + return []; + } + } + + getErrors(control: AbstractControl): string[] { + return Object.keys(control.errors) + .filter((error: any) => control.errors[error]) + .map((error: any) => { + const params = control.errors[error]; + return error; + }); + } + + private hasFieldName(form: FormGroup, fieldName: string): boolean { + const control = this.findFieldControl(form, fieldName); + return control != null; + } + + private setFieldError(form: FormGroup, fieldName: string, message: string) { + const control = this.findFieldControl(form, fieldName); + const errors = { [message]: true }; + control.setErrors(errors); + } + + private findFieldControl(form: FormGroup, fieldName: string): AbstractControl { + return form.get(fieldName); + } +}