From 67089013afa45c27d5ef38bb3f2f791a63ab56a9 Mon Sep 17 00:00:00 2001 From: FyloZ Date: Tue, 16 Feb 2021 14:34:32 -0500 Subject: [PATCH 1/6] =?UTF-8?q?Ajout=20d'un=20syst=C3=A8me=20de=20gestion?= =?UTF-8?q?=20des=20erreurs=20et=20alertes=20centralis=C3=A9.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/app.component.html | 1 + .../global-alert-handler.component.html | 9 ++ .../global-alert-handler.component.sass | 0 .../global-alert-handler.component.ts | 17 +++ .../modules/shared/service/alert.service.ts | 106 +++++++++++++++++ .../modules/shared/service/error.service.ts | 107 ++++++++++++++++++ src/app/modules/shared/shared.module.ts | 6 +- 7 files changed, 244 insertions(+), 2 deletions(-) create mode 100644 src/app/modules/shared/components/global-alert-handler/global-alert-handler.component.html create mode 100644 src/app/modules/shared/components/global-alert-handler/global-alert-handler.component.sass create mode 100644 src/app/modules/shared/components/global-alert-handler/global-alert-handler.component.ts create mode 100644 src/app/modules/shared/service/alert.service.ts create mode 100644 src/app/modules/shared/service/error.service.ts diff --git a/src/app/app.component.html b/src/app/app.component.html index 4dd83bd..00031de 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,4 +1,5 @@ +
diff --git a/src/app/modules/shared/components/global-alert-handler/global-alert-handler.component.html b/src/app/modules/shared/components/global-alert-handler/global-alert-handler.component.html new file mode 100644 index 0000000..19903b7 --- /dev/null +++ b/src/app/modules/shared/components/global-alert-handler/global-alert-handler.component.html @@ -0,0 +1,9 @@ + +
+ {{alert.alert.message}} +
+
diff --git a/src/app/modules/shared/components/global-alert-handler/global-alert-handler.component.sass b/src/app/modules/shared/components/global-alert-handler/global-alert-handler.component.sass new file mode 100644 index 0000000..e69de29 diff --git a/src/app/modules/shared/components/global-alert-handler/global-alert-handler.component.ts b/src/app/modules/shared/components/global-alert-handler/global-alert-handler.component.ts new file mode 100644 index 0000000..d28c3ba --- /dev/null +++ b/src/app/modules/shared/components/global-alert-handler/global-alert-handler.component.ts @@ -0,0 +1,17 @@ +import {Component} from '@angular/core' +import {AlertHandlerComponent, AlertService, AlertType} from '../../service/alert.service' + +@Component({ + selector: 'cre-global-alert-handler', + templateUrl: './global-alert-handler.component.html', + styleUrls: ['./global-alert-handler.component.sass'] +}) +export class GlobalAlertHandlerComponent extends AlertHandlerComponent { + readonly SUCCESS_ALERT_TYPE = AlertType.Success + readonly WARNING_ALERT_TYPE = AlertType.Warning + readonly ERROR_ALERT_TYPE = AlertType.Error + + constructor(alertService: AlertService) { + super(alertService) + } +} diff --git a/src/app/modules/shared/service/alert.service.ts b/src/app/modules/shared/service/alert.service.ts new file mode 100644 index 0000000..b8e2922 --- /dev/null +++ b/src/app/modules/shared/service/alert.service.ts @@ -0,0 +1,106 @@ +import {Injectable} from '@angular/core' +import {interval} from 'rxjs' + +@Injectable({ + providedIn: 'root' +}) +export class AlertService { + private alertQueue: Alert[] = [] + private activeHandler: AlertHandlerComponent + + constructor() { + // interval(500).subscribe({next: i => this.pushError('Test error ' + i)}) + } + + pushSuccess(message: String) { + this.enqueue(AlertType.Success, message) + } + + pushWarning(message: String) { + this.enqueue(AlertType.Warning, message) + } + + pushError(message: String) { + this.enqueue(AlertType.Error, message) + } + + set activeAlertHandlerComponent(handler: AlertHandlerComponent) { + this.activeHandler = handler + } + + private enqueue(type: AlertType, message: String) { + const alert = {type, message} + if (this.activeHandler && !this.activeHandler.isBufferFull) { + if (this.alertQueue.length == 0) { + this.activeHandler.pushAlert(alert) + } else { + this.activeHandler.pushAlert(this.dequeue()) + this.alertQueue.unshift(alert) + } + } else { + this.alertQueue.unshift(alert) + } + } + + private dequeue(): Alert { + return this.alertQueue.pop() + } +} + +/** + * An alert handler component is a component that will show the alerts pushed by the alert system to the user. + */ +export abstract class AlertHandlerComponent { + protected static readonly DEFAULT_ALERT_BUFFER_SIZE = 3 + protected static readonly DEFAULT_ALERT_DURATION = 5 + + alertBuffer = new Array<{ alert: Alert, time: number }>() + protected alertBufferSize: number = AlertHandlerComponent.DEFAULT_ALERT_BUFFER_SIZE + protected alertDuration: number = AlertHandlerComponent.DEFAULT_ALERT_DURATION + protected alertDurationCounter = 0 + + protected constructor( + protected alertService: AlertService + ) { + alertService.activeAlertHandlerComponent = this + + interval(1000).subscribe({ + next: () => { + this.alertDurationCounter++ + if (this.alertBuffer.length > 1) { + this.alertBuffer + .filter(a => a.time + this.alertDuration < this.alertDurationCounter) + .map(a => this.alertBuffer.indexOf(a)) + .forEach(i => this.alertBuffer.splice(i, 1)) + } + } + }) + } + + pushAlert(alert: Alert) { + this.alertBuffer.unshift({alert: alert, time: this.alertDurationCounter}) + } + + get isBufferFull(): boolean { + return this.alertBuffer.length >= this.alertBufferSize + } +} + +/** + * An alert is a message that will be shown to the user. + * + * An alert can be a success alert, a warning alert of an error alert. + */ +class Alert { + constructor( + public type: AlertType, + public message: String + ) { + } +} + +export enum AlertType { + Success, + Warning, + Error +} diff --git a/src/app/modules/shared/service/error.service.ts b/src/app/modules/shared/service/error.service.ts new file mode 100644 index 0000000..45c61e7 --- /dev/null +++ b/src/app/modules/shared/service/error.service.ts @@ -0,0 +1,107 @@ +import {Injectable} from '@angular/core' +import {AlertService} from './alert.service' +import {AppState} from '../app-state' + +@Injectable({ + providedIn: 'root' +}) +export class ErrorService { + private static readonly UNKNOWN_ERROR_MESSAGE = 'Une erreur inconnue est survenue' + private defaultHandledErrorModels: ErrorModel[] = [{ + filter: error => error.status === 0 && error.statusText === 'Unknown Error' || error.status === 502, + consumer: () => this.appState.isServerOnline = false + }, { + filter: error => error.status === 400, + consumer: error => console.error(error), + messageProducer: () => 'Certaines informations dans la requête étaient invalides' + }, { + filter: error => error.status === 401, + messageProducer: () => 'Vous devez être connecté pour effectuer cette action' + }, { + filter: error => error.status === 403, + messageProducer: () => 'Vous n\'avez pas la permission d\'effectuer cette action' + }, { + filter: error => error.status === 404, + messageProducer: () => 'La resource demandée n\'a pas été trouvée' + }, { + filter: error => error.status === 500, + messageProducer: () => ErrorService.UNKNOWN_ERROR_MESSAGE + }] + + private activeHandler: ErrorHandler + + constructor( + private alertService: AlertService, + private appState: AppState + ) { + } + + handleError(error: any) { + if (!this.activeHandler) { + console.error('An error occurred but no handler was set') + } + + let matchingModels = this.activeHandler.handledErrorModels.filter(m => m.filter(error)) // Find error models whose filter matches the current error + + if (!matchingModels || matchingModels.length == 0) { // If none are found, search in defaults handlers + matchingModels = this.defaultHandledErrorModels.filter(m => m.filter(error)) + } + + if (!matchingModels || matchingModels.length == 0) { // If still none are found, handle as an unknown error + this.consumeUnknownError(error) + return + } + + matchingModels.forEach(m => { + if (m.consumer || m.messageProducer) { + if (m.consumer) { + m.consumer(error) + } + if (m.messageProducer) { + this.alertService.pushError(m.messageProducer(error)) + } + } else { + console.error('An error model has no consumer or message') + } + }) + } + + consumeUnknownError(error: any) { + console.error(error) + this.alertService.pushError(ErrorService.UNKNOWN_ERROR_MESSAGE) + } + + set activeErrorHandler(handler: ErrorHandler) { + this.activeHandler = handler + } +} + +/** + * An error handler, defining models of errors that this type will handle + */ +export abstract class ErrorHandler { + abstract handledErrorModels: ErrorModel[] + + protected constructor( + protected errorService: ErrorService + ) { + this.errorService.activeErrorHandler = this + } +} + +/** + * An error model define how errors matching its filter will be handled. + * + * The consumer will consume matching errors when they occurs. + * The message producer returns a string that will be pushed to the alert system. + * + * To work correctly a model must define at least one handler (consumer or message producer). + */ +export class ErrorModel { + constructor( + public filter: (error: any) => Boolean, + public consumer?: (error: any) => void, + public messageProducer?: (error: any) => String + ) { + } +} diff --git a/src/app/modules/shared/shared.module.ts b/src/app/modules/shared/shared.module.ts index 62c3d95..8ea2b4a 100644 --- a/src/app/modules/shared/shared.module.ts +++ b/src/app/modules/shared/shared.module.ts @@ -27,10 +27,11 @@ import {MatSelectModule} from "@angular/material/select"; import {MatOptionModule} from "@angular/material/core"; import {MaterialFileInputModule} from "ngx-material-file-input"; import { FileButtonComponent } from './file-button/file-button.component'; +import { GlobalAlertHandlerComponent } from './components/global-alert-handler/global-alert-handler.component'; @NgModule({ - declarations: [HeaderComponent, EmployeeInfoComponent, LabeledIconComponent, ConfirmBoxComponent, PermissionsListComponent, PermissionsFieldComponent, NavComponent, EntityListComponent, EntityAddComponent, EntityEditComponent, FileButtonComponent], + declarations: [HeaderComponent, EmployeeInfoComponent, LabeledIconComponent, ConfirmBoxComponent, PermissionsListComponent, PermissionsFieldComponent, NavComponent, EntityListComponent, EntityAddComponent, EntityEditComponent, FileButtonComponent, GlobalAlertHandlerComponent], exports: [ CommonModule, HttpClientModule, @@ -55,7 +56,8 @@ import { FileButtonComponent } from './file-button/file-button.component'; EntityListComponent, EntityAddComponent, EntityEditComponent, - FileButtonComponent + FileButtonComponent, + GlobalAlertHandlerComponent ], imports: [ MatTabsModule, From 1d89ba926e42fa5f45ab4f8fd8f271eca9ac87be Mon Sep 17 00:00:00 2001 From: FyloZ Date: Tue, 16 Feb 2021 17:54:52 -0500 Subject: [PATCH 2/6] Ajout du style des alertes --- .../global-alert-handler.component.html | 6 ++- .../global-alert-handler.component.sass | 28 ++++++++++++++ .../global-alert-handler.component.ts | 18 ++++++++- src/app/pages/catalog/catalog.component.ts | 17 +++++++-- src/custom-theme.scss | 38 +++++++++++++++++-- 5 files changed, 97 insertions(+), 10 deletions(-) diff --git a/src/app/modules/shared/components/global-alert-handler/global-alert-handler.component.html b/src/app/modules/shared/components/global-alert-handler/global-alert-handler.component.html index 19903b7..b4acaa2 100644 --- a/src/app/modules/shared/components/global-alert-handler/global-alert-handler.component.html +++ b/src/app/modules/shared/components/global-alert-handler/global-alert-handler.component.html @@ -1,9 +1,11 @@ - +
{{alert.alert.message}}
- +
diff --git a/src/app/modules/shared/components/global-alert-handler/global-alert-handler.component.sass b/src/app/modules/shared/components/global-alert-handler/global-alert-handler.component.sass index e69de29..56955cd 100644 --- a/src/app/modules/shared/components/global-alert-handler/global-alert-handler.component.sass +++ b/src/app/modules/shared/components/global-alert-handler/global-alert-handler.component.sass @@ -0,0 +1,28 @@ +@import '../../../../../custom-theme' + +.alerts-wrapper + position: absolute + width: 100vw + z-index: 50 + + &.subnav-margin + margin-top: 3rem + + .alert + width: max-content + margin: 1rem auto + + .alert-danger + color: map-get($theme-error, 900) + border-color: map-get($theme-error, 900) + background-color: map-get($theme-error, 100) + + .alert-warning + color: map-get($theme-warning, 900) + border-color: map-get($theme-warning, 900) + background-color: map-get($theme-warning, 100) + + .alert-success + color: map-get($theme-accent, 900) + border-color: map-get($theme-accent, 900) + background-color: map-get($theme-accent, 100) diff --git a/src/app/modules/shared/components/global-alert-handler/global-alert-handler.component.ts b/src/app/modules/shared/components/global-alert-handler/global-alert-handler.component.ts index d28c3ba..f87b246 100644 --- a/src/app/modules/shared/components/global-alert-handler/global-alert-handler.component.ts +++ b/src/app/modules/shared/components/global-alert-handler/global-alert-handler.component.ts @@ -1,12 +1,24 @@ import {Component} from '@angular/core' import {AlertHandlerComponent, AlertService, AlertType} from '../../service/alert.service' +import {animate, state, style, transition, trigger} from '@angular/animations' @Component({ selector: 'cre-global-alert-handler', templateUrl: './global-alert-handler.component.html', - styleUrls: ['./global-alert-handler.component.sass'] + styleUrls: ['./global-alert-handler.component.sass'], + animations: [ + trigger('fadeIn', [ + state('void', style({ + opacity: 0, + transform: 'scale(0.5)' + })), + transition('void <=> *', animate(100)) + ]) + ] }) export class GlobalAlertHandlerComponent extends AlertHandlerComponent { + public static isSubNavOpen = false + readonly SUCCESS_ALERT_TYPE = AlertType.Success readonly WARNING_ALERT_TYPE = AlertType.Warning readonly ERROR_ALERT_TYPE = AlertType.Error @@ -14,4 +26,8 @@ export class GlobalAlertHandlerComponent extends AlertHandlerComponent { constructor(alertService: AlertService) { super(alertService) } + + get isSubNavOpen(): boolean { + return GlobalAlertHandlerComponent.isSubNavOpen + } } diff --git a/src/app/pages/catalog/catalog.component.ts b/src/app/pages/catalog/catalog.component.ts index d7c49db..5b125c2 100644 --- a/src/app/pages/catalog/catalog.component.ts +++ b/src/app/pages/catalog/catalog.component.ts @@ -1,16 +1,25 @@ -import {Component} from '@angular/core'; -import {NavLink} from "../../modules/shared/components/nav/nav.component"; -import {EmployeePermission} from "../../modules/shared/model/employee"; +import {Component, OnDestroy, OnInit} from '@angular/core' +import {NavLink} from '../../modules/shared/components/nav/nav.component' +import {EmployeePermission} from '../../modules/shared/model/employee' +import {GlobalAlertHandlerComponent} from '../../modules/shared/components/global-alert-handler/global-alert-handler.component' @Component({ selector: 'cre-inventory-page', templateUrl: './catalog.component.html', styleUrls: ['./catalog.component.sass'] }) -export class CatalogComponent { +export class CatalogComponent implements OnInit, OnDestroy { links: NavLink[] = [ {route: '/catalog/materialtype', title: 'Types de produit', permission: EmployeePermission.VIEW_MATERIAL_TYPE}, {route: '/catalog/material', title: 'Produits', permission: EmployeePermission.VIEW_MATERIAL}, {route: '/catalog/company', title: 'Bannières', permission: EmployeePermission.VIEW_COMPANY} ] + + ngOnInit(): void { + GlobalAlertHandlerComponent.isSubNavOpen = true + } + + ngOnDestroy(): void { + GlobalAlertHandlerComponent.isSubNavOpen = false + } } diff --git a/src/custom-theme.scss b/src/custom-theme.scss index c6a6653..9f41329 100644 --- a/src/custom-theme.scss +++ b/src/custom-theme.scss @@ -78,12 +78,44 @@ $theme-accent: mat-palette(( A700 : #000000, ) )); +$theme-warning: mat-palette(( + 50 : #fff8e4, + 100 : #feefbd, + 200 : #fee491, + 300 : #fdd964, + 400 : #fcd043, + 500 : #fcc822, + 600 : #fcc21e, + 700 : #fbbb19, + 800 : #fbb414, + 900 : #faa70c, + A100 : #ffffff, + A200 : #fffaf1, + A400 : #ffe6be, + A700 : #ffdca4, + contrast: ( + 50 : #000000, + 100 : #000000, + 200 : #000000, + 300 : #000000, + 400 : #000000, + 500 : #000000, + 600 : #000000, + 700 : #000000, + 800 : #000000, + 900 : #000000, + A100 : #000000, + A200 : #000000, + A400 : #000000, + A700 : #000000, + ) +)); // The warn palette is optional (defaults to red). -$theme-warn: mat-palette($mat-red); +$theme-error: mat-palette($mat-red); // Create the theme object (a Sass map containing all of the palettes). -$color-recipes-explorer-frontend-theme: mat-light-theme($theme-primary, $theme-accent, $theme-warn); +$color-recipes-explorer-frontend-theme: mat-light-theme($theme-primary, $theme-accent, $theme-error); // Include theme styles for core and each component used in your app. // Alternatively, you can import and @include the theme mixins for each component @@ -92,7 +124,7 @@ $color-recipes-explorer-frontend-theme: mat-light-theme($theme-primary, $theme-a $color-primary: map-get($theme-primary, 500); $color-accent: map-get($theme-accent, 500); -$color-warn: map-get($theme-warn, 500); +$color-warn: map-get($theme-error, 500); html, body { From 690803f1df4a730378180288e598037dd78f48d5 Mon Sep 17 00:00:00 2001 From: FyloZ Date: Tue, 16 Feb 2021 17:59:33 -0500 Subject: [PATCH 3/6] =?UTF-8?q?R=C3=A9ajustement=20de=20la=20couleur=20des?= =?UTF-8?q?=20bordures=20des=20alertes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global-alert-handler.component.sass | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/modules/shared/components/global-alert-handler/global-alert-handler.component.sass b/src/app/modules/shared/components/global-alert-handler/global-alert-handler.component.sass index 56955cd..3e16340 100644 --- a/src/app/modules/shared/components/global-alert-handler/global-alert-handler.component.sass +++ b/src/app/modules/shared/components/global-alert-handler/global-alert-handler.component.sass @@ -14,15 +14,15 @@ .alert-danger color: map-get($theme-error, 900) - border-color: map-get($theme-error, 900) + border-color: map-get($theme-error, 200) background-color: map-get($theme-error, 100) .alert-warning color: map-get($theme-warning, 900) - border-color: map-get($theme-warning, 900) + border-color: map-get($theme-warning, 400) background-color: map-get($theme-warning, 100) .alert-success color: map-get($theme-accent, 900) - border-color: map-get($theme-accent, 900) + border-color: map-get($theme-accent, 400) background-color: map-get($theme-accent, 100) From 566f9aa6d462bd2c967fe5c4a9f9ce1e497f0bcd Mon Sep 17 00:00:00 2001 From: FyloZ Date: Tue, 16 Feb 2021 18:10:02 -0500 Subject: [PATCH 4/6] =?UTF-8?q?Le=20AlertHandlerComponent=20va=20maintenan?= =?UTF-8?q?t=20chercher=20les=20alertes=20lui-m=C3=AAme=20pour=20ne=20pas?= =?UTF-8?q?=20=C3=AAtre=20limit=C3=A9=20=C3=A0=20voir=20les=20alertes=20da?= =?UTF-8?q?ns=20la=20queue=20lorsqu'une=20nouvelle=20alerte=20arrive.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../accounts/pages/login/login.component.ts | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/app/modules/accounts/pages/login/login.component.ts b/src/app/modules/accounts/pages/login/login.component.ts index 9f7b3ba..d3c6736 100644 --- a/src/app/modules/accounts/pages/login/login.component.ts +++ b/src/app/modules/accounts/pages/login/login.component.ts @@ -1,14 +1,20 @@ -import {Component, OnInit} from '@angular/core'; -import {FormBuilder, FormControl, FormGroup, Validators} from "@angular/forms"; -import {AccountService} from "../../services/account.service"; -import {Router} from "@angular/router"; +import {Component, OnInit} from '@angular/core' +import {FormBuilder, FormControl, FormGroup, Validators} from '@angular/forms' +import {AccountService} from '../../services/account.service' +import {Router} from '@angular/router' +import {ErrorHandler, ErrorModel, ErrorService} from '../../../shared/service/error.service' @Component({ selector: 'cre-login', templateUrl: './login.component.html', styleUrls: ['./login.component.sass'] }) -export class LoginComponent implements OnInit { +export class LoginComponent extends ErrorHandler implements OnInit { + readonly handledErrorModels: ErrorModel[] = [{ + filter: error => error.status === 401, + messageProducer: () => 'Les identifiants entrés sont invalides.' + }] + form: FormGroup idFormControl: FormControl passwordFormControl: FormControl @@ -18,8 +24,10 @@ export class LoginComponent implements OnInit { constructor( private formBuilder: FormBuilder, private accountService: AccountService, - private router: Router + private router: Router, + errorService: ErrorService ) { + super(errorService) } ngOnInit(): void { @@ -39,8 +47,7 @@ export class LoginComponent implements OnInit { this.accountService.login( this.idFormControl.value, this.passwordFormControl.value, - () => this.router.navigate(["/color"]), - err => this.invalidCredentials = err.status === 401 + () => this.router.navigate(['/color']) ) } } From 1c5f2448115cd8a94467d74725085ba93fca6676 Mon Sep 17 00:00:00 2001 From: FyloZ Date: Wed, 17 Feb 2021 00:12:43 -0500 Subject: [PATCH 5/6] =?UTF-8?q?Utilisation=20du=20syst=C3=A8me=20centralis?= =?UTF-8?q?=C3=A9=20d'erreur=20dans=20toute=20l'application?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/app.component.ts | 21 ++-- .../accounts/pages/login/login.component.html | 3 - .../accounts/pages/login/login.component.ts | 16 +-- .../images-editor/images-editor.component.ts | 22 ++-- .../mix-editor/mix-editor.component.ts | 93 ++++++++-------- .../mix-table/mix-table.component.ts | 71 ++++++++---- .../mixes-card/mixes-card.component.html | 3 +- .../mixes-card/mixes-card.component.ts | 1 - .../colors/pages/add/add.component.html | 2 - .../modules/colors/pages/add/add.component.ts | 32 +++--- .../colors/pages/edit/edit.component.html | 9 -- .../colors/pages/edit/edit.component.ts | 86 +++++++------- .../pages/explore/explore.component.html | 23 +--- .../colors/pages/explore/explore.component.ts | 96 ++++++---------- .../colors/pages/list/list.component.ts | 22 ++-- .../pages/mix/mix-add/mix-add.component.ts | 26 +++-- .../pages/mix/mix-edit/mix-edit.component.ts | 26 +++-- .../company/pages/add/add.component.html | 2 - .../company/pages/add/add.component.ts | 45 ++++---- .../company/pages/edit/edit.component.html | 2 - .../company/pages/edit/edit.component.ts | 69 +++++------- .../company/pages/list/list.component.ts | 17 +-- .../employees/pages/add/add.component.html | 4 - .../employees/pages/add/add.component.ts | 36 +++--- .../employees/pages/edit/edit.component.html | 4 - .../employees/pages/edit/edit.component.ts | 105 +++++++----------- .../employees/pages/list/list.component.ts | 25 +++-- .../password-edit/password-edit.component.ts | 36 +++--- .../employees/services/employee.service.ts | 2 +- .../employees-list.component.ts | 23 ++-- .../groups/pages/add/add.component.html | 4 - .../modules/groups/pages/add/add.component.ts | 29 ++--- .../groups/pages/edit/edit.component.html | 4 - .../groups/pages/edit/edit.component.ts | 66 +++++------ .../groups/pages/list/list.component.ts | 43 +++---- .../modules/groups/services/group.service.ts | 2 +- .../pages/add/add.component.html | 2 - .../material-type/pages/add/add.component.ts | 46 ++++---- .../pages/edit/edit.component.html | 2 - .../pages/edit/edit.component.ts | 76 +++++-------- .../pages/list/list.component.ts | 17 +-- .../service/material-type.service.ts | 2 +- .../material/pages/add/add.component.html | 2 - .../material/pages/add/add.component.ts | 43 ++++--- .../material/pages/edit/edit.component.html | 5 +- .../material/pages/edit/edit.component.ts | 82 ++++++-------- .../material/pages/list/list.component.ts | 37 +++--- .../entity-add/entity-add.component.html | 5 - .../entity-add/entity-add.component.ts | 19 +--- .../entity-edit/entity-edit.component.html | 5 - .../entity-edit/entity-edit.component.ts | 28 ++--- .../entity-list/entity-list.component.ts | 22 ++-- .../global-alert-handler.component.html | 2 +- .../global-alert-handler.component.sass | 2 +- .../global-alert-handler.component.ts | 6 +- .../components/header/header.component.ts | 37 +++--- .../components/subscribing.component.ts | 72 ++++++------ .../modules/shared/service/alert.service.ts | 68 ++++++------ .../modules/shared/service/error.service.ts | 27 +++-- src/app/pages/catalog/catalog.component.ts | 4 +- 60 files changed, 742 insertions(+), 939 deletions(-) diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 69b3e57..df904ac 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,9 +1,9 @@ -import {Component, Inject, PLATFORM_ID} from '@angular/core'; -import {isPlatformBrowser} from "@angular/common"; -import {AppState} from "./modules/shared/app-state"; -import {Observable} from "rxjs"; -import {SubscribingComponent} from "./modules/shared/components/subscribing.component"; -import {ActivatedRoute, Router} from "@angular/router"; +import {Component, Inject, PLATFORM_ID} from '@angular/core' +import {isPlatformBrowser} from '@angular/common' +import {AppState} from './modules/shared/app-state' +import {SubscribingComponent} from './modules/shared/components/subscribing.component' +import {ActivatedRoute, Router} from '@angular/router' +import {ErrorService} from './modules/shared/service/error.service' @Component({ selector: 'cre-root', @@ -17,21 +17,20 @@ export class AppComponent extends SubscribingComponent { constructor( @Inject(PLATFORM_ID) private platformId: object, private appState: AppState, + errorService: ErrorService, router: Router, activatedRoute: ActivatedRoute ) { - super(activatedRoute, router) + super(errorService, activatedRoute, router) } ngOnInit() { this.isOnline = isPlatformBrowser(this.platformId) - super.ngOnInit(); + super.ngOnInit() this.subscribe( this.appState.serverOnline$, - { - next: online => this.isServerOnline = online - } + online => this.isServerOnline = online ) } diff --git a/src/app/modules/accounts/pages/login/login.component.html b/src/app/modules/accounts/pages/login/login.component.html index c02ca51..4f10431 100644 --- a/src/app/modules/accounts/pages/login/login.component.html +++ b/src/app/modules/accounts/pages/login/login.component.html @@ -4,9 +4,6 @@ Connexion au système -
-

Les identifiants entrés sont invalides.

-
Numéro d'employé diff --git a/src/app/modules/accounts/pages/login/login.component.ts b/src/app/modules/accounts/pages/login/login.component.ts index d3c6736..0601ec5 100644 --- a/src/app/modules/accounts/pages/login/login.component.ts +++ b/src/app/modules/accounts/pages/login/login.component.ts @@ -9,28 +9,30 @@ import {ErrorHandler, ErrorModel, ErrorService} from '../../../shared/service/er templateUrl: './login.component.html', styleUrls: ['./login.component.sass'] }) -export class LoginComponent extends ErrorHandler implements OnInit { - readonly handledErrorModels: ErrorModel[] = [{ +export class LoginComponent implements ErrorHandler, OnInit { + handledErrorModels: ErrorModel[] = [{ filter: error => error.status === 401, messageProducer: () => 'Les identifiants entrés sont invalides.' + }, { + filter: error => error.status === 404 || error.status === 403, + consumer: () => console.warn('No default user is defined on this computer') }] form: FormGroup idFormControl: FormControl passwordFormControl: FormControl - invalidCredentials = false - constructor( private formBuilder: FormBuilder, private accountService: AccountService, - private router: Router, - errorService: ErrorService + private errorService: ErrorService, + private router: Router ) { - super(errorService) } ngOnInit(): void { + this.errorService.activeErrorHandler = this + if (this.accountService.isLoggedIn()) { this.router.navigate(['/color']) } diff --git a/src/app/modules/colors/components/images-editor/images-editor.component.ts b/src/app/modules/colors/components/images-editor/images-editor.component.ts index eab25c5..c53a23b 100644 --- a/src/app/modules/colors/components/images-editor/images-editor.component.ts +++ b/src/app/modules/colors/components/images-editor/images-editor.component.ts @@ -1,10 +1,11 @@ -import {Component, Input} from '@angular/core'; -import {Recipe} from "../../../shared/model/recipe.model"; -import {SubscribingComponent} from "../../../shared/components/subscribing.component"; -import {ActivatedRoute, Router} from "@angular/router"; -import {Observable} from "rxjs"; -import {RecipeImageService} from "../../services/recipe-image.service"; -import {environment} from "../../../../../environments/environment"; +import {Component, Input} from '@angular/core' +import {Recipe} from '../../../shared/model/recipe.model' +import {SubscribingComponent} from '../../../shared/components/subscribing.component' +import {ActivatedRoute, Router} from '@angular/router' +import {Observable} from 'rxjs' +import {RecipeImageService} from '../../services/recipe-image.service' +import {environment} from '../../../../../environments/environment' +import {ErrorService} from '../../../shared/service/error.service' @Component({ selector: 'cre-images-editor', @@ -20,10 +21,11 @@ export class ImagesEditorComponent extends SubscribingComponent { constructor( private recipeImageService: RecipeImageService, + errorService: ErrorService, router: Router, activatedRoute: ActivatedRoute ) { - super(activatedRoute, router) + super(errorService, activatedRoute, router) } ngOnInit() { @@ -36,7 +38,7 @@ export class ImagesEditorComponent extends SubscribingComponent { const image = event.target.files[0] this.subscribe( this.recipeImageService.save(image, this.recipe.id), - {next: () => this.loadImagesIds()} + () => this.loadImagesIds() ) } @@ -47,7 +49,7 @@ export class ImagesEditorComponent extends SubscribingComponent { delete(imageId: number) { this.subscribe( this.recipeImageService.delete(imageId, this.recipe.id), - {next: () => this.loadImagesIds()} + () => this.loadImagesIds() ) } diff --git a/src/app/modules/colors/components/mix-editor/mix-editor.component.ts b/src/app/modules/colors/components/mix-editor/mix-editor.component.ts index 5572641..e3e212d 100644 --- a/src/app/modules/colors/components/mix-editor/mix-editor.component.ts +++ b/src/app/modules/colors/components/mix-editor/mix-editor.component.ts @@ -1,20 +1,21 @@ -import {Component, EventEmitter, Input, Output, ViewChild} from '@angular/core'; -import {Mix, MixMaterial, Recipe} from "../../../shared/model/recipe.model"; -import {SubscribingComponent} from "../../../shared/components/subscribing.component"; -import {MixService} from "../../services/mix.service"; -import {Observable} from "rxjs"; -import {RecipeService} from "../../services/recipe.service"; -import {Material} from "../../../shared/model/material.model"; -import {MaterialService} from "../../../material/service/material.service"; -import {MaterialType} from "../../../shared/model/materialtype.model"; -import {MaterialTypeService} from "../../../material-type/service/material-type.service"; -import {FormBuilder, FormControl, FormGroup, Validators} from "@angular/forms"; -import {UNIT_MILLILITER} from "../../../shared/units"; -import {MatTable} from "@angular/material/table"; -import {ActivatedRoute, Router} from "@angular/router"; -import {ConfirmBoxComponent} from "../../../shared/components/confirm-box/confirm-box.component"; -import {AccountService} from "../../../accounts/services/account.service"; -import {EmployeePermission} from "../../../shared/model/employee"; +import {Component, EventEmitter, Input, Output, ViewChild} from '@angular/core' +import {Mix, MixMaterial, Recipe} from '../../../shared/model/recipe.model' +import {SubscribingComponent} from '../../../shared/components/subscribing.component' +import {MixService} from '../../services/mix.service' +import {Observable} from 'rxjs' +import {RecipeService} from '../../services/recipe.service' +import {Material} from '../../../shared/model/material.model' +import {MaterialService} from '../../../material/service/material.service' +import {MaterialType} from '../../../shared/model/materialtype.model' +import {MaterialTypeService} from '../../../material-type/service/material-type.service' +import {FormBuilder, FormControl, FormGroup, Validators} from '@angular/forms' +import {UNIT_MILLILITER} from '../../../shared/units' +import {MatTable} from '@angular/material/table' +import {ActivatedRoute, Router} from '@angular/router' +import {ConfirmBoxComponent} from '../../../shared/components/confirm-box/confirm-box.component' +import {AccountService} from '../../../accounts/services/account.service' +import {EmployeePermission} from '../../../shared/model/employee' +import {ErrorService} from '../../../shared/service/error.service' @Component({ selector: 'cre-mix-editor', @@ -29,7 +30,7 @@ export class MixEditorComponent extends SubscribingComponent { @Input() recipeId: number | null @Input() materials: Material[] - @Output() save = new EventEmitter(); + @Output() save = new EventEmitter() mix: Mix | null recipe: Recipe | null @@ -52,43 +53,43 @@ export class MixEditorComponent extends SubscribingComponent { private materialTypeService: MaterialTypeService, private accountService: AccountService, private formBuilder: FormBuilder, + errorService: ErrorService, router: Router, activatedRoute: ActivatedRoute ) { - super(activatedRoute, router) + super(errorService, activatedRoute, router) } ngOnInit() { - super.ngOnInit(); + super.ngOnInit() this.mixId = this.urlUtils.parseIntUrlParam('id') if (this.mixId) { this.editionMode = true } - this.subscribe( - this.recipeService.getById(this.recipeId), - { - next: r => { - this.recipe = r - if (this.editionMode) { - this.subscribe( - this.mixService.getById(this.mixId), - { - next: m => { - this.mix = m - this.mixMaterials = this.mixService.extractMixMaterials(this.mix) - this.generateForm() - }, error: err => this.handleNotFoundError(err, '/color/list') - } - ) - } else { - this.mixMaterials.push({}) - this.generateForm() - } - }, - error: err => this.handleNotFoundError(err, '/color/list') - } + this.subscribeEntityById( + this.recipeService, + this.recipeId, + r => { + this.recipe = r + if (this.editionMode) { + this.subscribeEntityById( + this.mixService, + this.mixId, + m => { + this.mix = m + this.mixMaterials = this.mixService.extractMixMaterials(this.mix) + this.generateForm() + }, + '/color/list' + ) + } else { + this.mixMaterials.push({}) + this.generateForm() + } + }, + '/color/list' ) this.materialTypes$ = this.materialTypeService.all } @@ -118,8 +119,10 @@ export class MixEditorComponent extends SubscribingComponent { } materialUsePercentages(mixMaterial: any) { - if (!mixMaterial.materialId) return null - const material = this.getMaterialFromId(mixMaterial.materialId); + if (!mixMaterial.materialId) { + return null + } + const material = this.getMaterialFromId(mixMaterial.materialId) mixMaterial.percents = material && material.materialType.usePercentages return mixMaterial.percents } diff --git a/src/app/modules/colors/components/mix-table/mix-table.component.ts b/src/app/modules/colors/components/mix-table/mix-table.component.ts index ca766b9..d4f7da4 100644 --- a/src/app/modules/colors/components/mix-table/mix-table.component.ts +++ b/src/app/modules/colors/components/mix-table/mix-table.component.ts @@ -1,11 +1,13 @@ -import {Component, EventEmitter, Input, Output, ViewChild} from '@angular/core'; -import {Mix, MixMaterial, Recipe} from "../../../shared/model/recipe.model"; -import {Subject} from "rxjs"; -import {SubscribingComponent} from "../../../shared/components/subscribing.component"; -import {convertMixMaterialQuantity, UNIT_MILLILITER} from "../../../shared/units"; -import {ActivatedRoute, Router} from "@angular/router"; -import {PtouchPrinter} from "../../ptouchPrint" -import {ConfirmBoxComponent} from "../../../shared/components/confirm-box/confirm-box.component"; +import {Component, EventEmitter, Input, Output, ViewChild} from '@angular/core' +import {Mix, MixMaterial, Recipe} from '../../../shared/model/recipe.model' +import {Subject} from 'rxjs' +import {SubscribingComponent} from '../../../shared/components/subscribing.component' +import {convertMixMaterialQuantity, UNIT_MILLILITER} from '../../../shared/units' +import {ActivatedRoute, Router} from '@angular/router' +import {PtouchPrinter} from '../../ptouchPrint' +import {ConfirmBoxComponent} from '../../../shared/components/confirm-box/confirm-box.component' +import {ErrorService} from '../../../shared/service/error.service' +import {AlertService} from '../../../shared/service/alert.service' @Component({ selector: 'cre-mix-table', @@ -23,7 +25,6 @@ export class MixTableComponent extends SubscribingComponent { @Input() units$: Subject @Input() deductErrorBody @Input() editionMode: boolean - @Input() printingError = 2 @Output() locationChange = new EventEmitter<{ id: number, location: string }>() @Output() quantityChange = new EventEmitter<{ id: number, materialId: number, quantity: number }>() @Output() deduct = new EventEmitter() @@ -37,14 +38,16 @@ export class MixTableComponent extends SubscribingComponent { printer: PtouchPrinter | null constructor( + private alertService: AlertService, + errorService: ErrorService, router: Router, activatedRoute: ActivatedRoute ) { - super(activatedRoute, router) + super(errorService, activatedRoute, router) } ngOnInit() { - super.ngOnInit(); + super.ngOnInit() if (this.editionMode) { this.mixColumns = this.COLUMNS_STATIC @@ -58,9 +61,7 @@ export class MixTableComponent extends SubscribingComponent { this.subscribe( this.units$, - { - next: u => this.convertQuantities(u) - } + u => this.convertQuantities(u) ) } @@ -90,7 +91,9 @@ export class MixTableComponent extends SubscribingComponent { } getTotalQuantity(index: number = -1): number { - if (index === -1) index = this.computedQuantities.length - 1 + if (index === -1) { + index = this.computedQuantities.length - 1 + } let totalQuantity = 0 for (let i = 0; i <= index; i++) { totalQuantity += this.calculateQuantity(i) @@ -121,16 +124,32 @@ export class MixTableComponent extends SubscribingComponent { return } this.printer = new PtouchPrinter({ - template: "Couleur", + template: 'Couleur', lines: [ - {name: "color", value: this.recipe.name}, - {name: "banner", value: this.recipe.company.name}, - {name: "base", value: base.name}, - {name: "description", value: this.recipe.description} + {name: 'color', value: this.recipe.name}, + {name: 'banner', value: this.recipe.company.name}, + {name: 'base', value: base.name}, + {name: 'description', value: this.recipe.description} ] }) - const errorCode = await this.printer.print() - this.printingErrorChange.emit(errorCode) + const exitCode = await this.printer.print() + switch (exitCode) { + case PrintingExitCode.PrintingInProgress: + this.alertService.pushSuccess('Impression en cours. Cette opération peut prendre quelques secondes') + break + case PrintingExitCode.ExtensionNotInstalled: + this.alertService.pushError('L\'extension b-Pac n\'est pas installée') + break + case PrintingExitCode.NoBaseFound: + this.alertService.pushError('Il n\'y a pas de base dans ce mélange') + break + case PrintingExitCode.GenericPrintingError: + this.alertService.pushError('Une erreur est survenue durant l\'impression') + break + default: + this.errorService.pushUnknownError() + break + } } private emitQuantityChangeEvent(index: number) { @@ -158,3 +177,11 @@ export class MixTableComponent extends SubscribingComponent { return this.computedQuantities[0].quantity * (computedQuantity.quantity / 100) } } + +enum PrintingExitCode { + PrintingInProgress = 1, + + ExtensionNotInstalled = -1, + NoBaseFound = 98, + GenericPrintingError = 99 +} diff --git a/src/app/modules/colors/components/mixes-card/mixes-card.component.html b/src/app/modules/colors/components/mixes-card/mixes-card.component.html index f22e4d6..0c8ffeb 100644 --- a/src/app/modules/colors/components/mixes-card/mixes-card.component.html +++ b/src/app/modules/colors/components/mixes-card/mixes-card.component.html @@ -13,8 +13,7 @@ [editionMode]="editionMode" (quantityChange)="quantityChange.emit($event)" (locationChange)="locationChange.emit($event)" - (deduct)="deduct.emit(mix.id)" - [(printingError)]="printingError">> + (deduct)="deduct.emit(mix.id)">
diff --git a/src/app/modules/colors/components/mixes-card/mixes-card.component.ts b/src/app/modules/colors/components/mixes-card/mixes-card.component.ts index 63ee4e8..920132a 100644 --- a/src/app/modules/colors/components/mixes-card/mixes-card.component.ts +++ b/src/app/modules/colors/components/mixes-card/mixes-card.component.ts @@ -11,7 +11,6 @@ export class MixesCardComponent { @Input() recipe: Recipe @Input() units$: Subject @Input() deductErrorBody: any - @Input() printingError = 2 @Input() editionMode = false @Output() locationChange = new EventEmitter<{ id: number, location: string }>() diff --git a/src/app/modules/colors/pages/add/add.component.html b/src/app/modules/colors/pages/add/add.component.html index f9d4e9d..f95fa2b 100644 --- a/src/app/modules/colors/pages/add/add.component.html +++ b/src/app/modules/colors/pages/add/add.component.html @@ -1,8 +1,6 @@ diff --git a/src/app/modules/colors/pages/add/add.component.ts b/src/app/modules/colors/pages/add/add.component.ts index 3fc5e33..6eef38b 100644 --- a/src/app/modules/colors/pages/add/add.component.ts +++ b/src/app/modules/colors/pages/add/add.component.ts @@ -1,18 +1,19 @@ -import {Component} from '@angular/core'; -import {SubscribingComponent} from "../../../shared/components/subscribing.component"; -import {RecipeService} from "../../services/recipe.service"; -import {FormField} from "../../../shared/components/entity-add/entity-add.component"; -import {FormBuilder, Validators} from "@angular/forms"; -import {CompanyService} from "../../../company/service/company.service"; -import {map} from "rxjs/operators"; -import {ActivatedRoute, Router} from "@angular/router"; +import {Component} from '@angular/core' +import {ErrorHandlingComponent} from '../../../shared/components/subscribing.component' +import {RecipeService} from '../../services/recipe.service' +import {FormField} from '../../../shared/components/entity-add/entity-add.component' +import {Validators} from '@angular/forms' +import {CompanyService} from '../../../company/service/company.service' +import {map} from 'rxjs/operators' +import {ActivatedRoute, Router} from '@angular/router' +import {ErrorModel, ErrorService} from '../../../shared/service/error.service' @Component({ selector: 'cre-add', templateUrl: './add.component.html', styleUrls: ['./add.component.sass'] }) -export class AddComponent extends SubscribingComponent { +export class AddComponent extends ErrorHandlingComponent { formFields: FormField[] = [ { name: 'name', @@ -71,28 +72,21 @@ export class AddComponent extends SubscribingComponent { }))) } ] - unknownError = false - errorMessage: string | null constructor( private recipeService: RecipeService, private companyService: CompanyService, + errorService: ErrorService, router: Router, activatedRoute: ActivatedRoute ) { - super(activatedRoute, router) + super(errorService, activatedRoute, router) } submit(values) { this.subscribe( this.recipeService.save(values.name, values.description, values.sample, values.approbationDate, values.remark, values.company), - { - next: recipe => this.urlUtils.navigateTo(`/color/edit/${recipe.id}`), - error: err => { - this.unknownError = true - console.error(err) - } - } + recipe => this.urlUtils.navigateTo(`/color/edit/${recipe.id}`) ) } } diff --git a/src/app/modules/colors/pages/edit/edit.component.html b/src/app/modules/colors/pages/edit/edit.component.html index 3baa01f..0dba9d5 100644 --- a/src/app/modules/colors/pages/edit/edit.component.html +++ b/src/app/modules/colors/pages/edit/edit.component.html @@ -1,11 +1,4 @@
-
-

Il n'y a aucun mélange dans cette recette

-
-
-

Il n'y a aucune étape dans cette recette

-
-
@@ -33,8 +26,6 @@ deleteConfirmMessage="Voulez-vous vraiment supprimer la couleur {{recipe.name}}?" [entity]="recipe" [formFields]="formFields" - [unknownError]="unknownError" - [customError]="errorMessage" [disableButtons]="true" [noTopMargin]="true"> diff --git a/src/app/modules/colors/pages/edit/edit.component.ts b/src/app/modules/colors/pages/edit/edit.component.ts index a493da4..bbea551 100644 --- a/src/app/modules/colors/pages/edit/edit.component.ts +++ b/src/app/modules/colors/pages/edit/edit.component.ts @@ -1,22 +1,24 @@ -import {Component, ViewChild} from '@angular/core'; -import {SubscribingComponent} from "../../../shared/components/subscribing.component"; -import {Recipe} from "../../../shared/model/recipe.model"; -import {RecipeService} from "../../services/recipe.service"; -import {ActivatedRoute, Router} from "@angular/router"; -import {Validators} from "@angular/forms"; -import {Subject} from "rxjs"; -import {UNIT_GALLON, UNIT_LITER, UNIT_MILLILITER} from "../../../shared/units"; -import {AccountService} from "../../../accounts/services/account.service"; -import {EmployeePermission} from "../../../shared/model/employee"; -import {EntityEditComponent} from "../../../shared/components/entity-edit/entity-edit.component"; -import {ImagesEditorComponent} from "../../components/images-editor/images-editor.component"; +import {Component, ViewChild} from '@angular/core' +import {ErrorHandlingComponent, SubscribingComponent} from '../../../shared/components/subscribing.component' +import {Recipe} from '../../../shared/model/recipe.model' +import {RecipeService} from '../../services/recipe.service' +import {ActivatedRoute, Router} from '@angular/router' +import {Validators} from '@angular/forms' +import {Subject} from 'rxjs' +import {UNIT_GALLON, UNIT_LITER, UNIT_MILLILITER} from '../../../shared/units' +import {AccountService} from '../../../accounts/services/account.service' +import {EmployeePermission} from '../../../shared/model/employee' +import {EntityEditComponent} from '../../../shared/components/entity-edit/entity-edit.component' +import {ImagesEditorComponent} from '../../components/images-editor/images-editor.component' +import {ErrorHandler, ErrorModel, ErrorService} from '../../../shared/service/error.service' +import {AlertService} from '../../../shared/service/alert.service' @Component({ selector: 'cre-edit', templateUrl: './edit.component.html', styleUrls: ['./edit.component.sass'] }) -export class EditComponent extends SubscribingComponent { +export class EditComponent extends ErrorHandlingComponent { readonly unitConstants = {UNIT_MILLILITER, UNIT_LITER, UNIT_GALLON} @ViewChild('imagesEditor') imagesEditor: ImagesEditorComponent @@ -75,36 +77,41 @@ export class EditComponent extends SubscribingComponent { valueFn: recipe => recipe.company.name, } ] - unknownError = false - errorMessage: string | null units$ = new Subject() + submittedValues: any | null + + handledErrorModels: ErrorModel[] = [{ + filter: error => error.status === 409, + messageProducer: () => `Une couleur avec le nom '${this.submittedValues.name}' et la bannière '${this.recipe.company.name}' existe déjà` + }] constructor( private recipeService: RecipeService, private accountService: AccountService, + private alertService: AlertService, + errorService: ErrorService, router: Router, activatedRoute: ActivatedRoute ) { - super(activatedRoute, router) + super(errorService, activatedRoute, router) } ngOnInit() { - super.ngOnInit(); + super.ngOnInit() - const id = parseInt(this.activatedRoute.snapshot.paramMap.get('id')) - this.subscribe( - this.recipeService.getById(id), - { - next: recipe => this.recipe = recipe, - error: err => { - if (err.status === 404) { - this.router.navigate(['/color/list']) - } else { - this.unknownError = true - } + this.subscribeEntityById( + this.recipeService, + parseInt(this.activatedRoute.snapshot.paramMap.get('id')), + recipe => { + this.recipe = recipe + if (this.recipe.mixes.length == 0) { + this.alertService.pushWarning('Il n\'y a aucun mélange dans cette recette') + } + if (this.recipe.steps.length == 0) { + this.alertService.pushWarning('Il n\'y a aucune étape dans cette recette') } }, - 1 + '/color/list' ) } @@ -114,28 +121,17 @@ export class EditComponent extends SubscribingComponent { submit(editComponent: EntityEditComponent) { const values = editComponent.values - this.subscribe( + this.submittedValues = values + this.subscribeAndNavigate( this.recipeService.update(this.recipe.id, values.name, values.description, values.sample, values.approbationDate, values.remark, this.recipe.steps), - { - next: () => this.router.navigate(['/color/list']), - error: err => { - if (err.status === 409) { - this.errorMessage = `Une couleur avec le nom '${values.name}' et la bannière '${this.recipe.company.name}' existe déjà` - } else { - this.unknownError = true - console.error(err) - } - } - } + '/color/list' ) } delete() { - this.subscribe( + this.subscribeAndNavigate( this.recipeService.delete(this.recipe.id), - { - next: () => this.router.navigate(['/color/list']) - } + '/color/list' ) } diff --git a/src/app/modules/colors/pages/explore/explore.component.html b/src/app/modules/colors/pages/explore/explore.component.html index 76cd1bb..9ee5eec 100644 --- a/src/app/modules/colors/pages/explore/explore.component.html +++ b/src/app/modules/colors/pages/explore/explore.component.html @@ -1,26 +1,6 @@
-
-

Une erreur est survenue

-

Certains produit ne sont pas en quantité suffisante dans l'inventaire

-
- -
-

L'extension b-Pac n'est pas installée

-

Il n'y a pas de base dans ce mélange

-

Une erreur est survenue pendant l'impression

-
- -
-

Les modifications ont été enregistrées

-

Les quantités des produits utilisés ont été déduites de l'inventaire

-
- -
-

Impression en cours. Cette opération peut prendre quelques secondes.

-
-
@@ -51,8 +31,7 @@ [units$]="units$" (quantityChange)="changeQuantity($event)" (locationChange)="changeMixLocation($event)" - (deduct)="deductMixQuantities($event)" - [(printingError)]="printingError"> + (deduct)="deductMixQuantities($event)">
diff --git a/src/app/modules/colors/pages/explore/explore.component.ts b/src/app/modules/colors/pages/explore/explore.component.ts index 34348ba..610f44c 100644 --- a/src/app/modules/colors/pages/explore/explore.component.ts +++ b/src/app/modules/colors/pages/explore/explore.component.ts @@ -1,63 +1,65 @@ -import {Component} from '@angular/core'; -import {RecipeService} from "../../services/recipe.service"; -import {ActivatedRoute, Router} from "@angular/router"; -import {SubscribingComponent} from "../../../shared/components/subscribing.component"; -import {Recipe} from "../../../shared/model/recipe.model"; -import {Observable, Subject} from "rxjs"; -import {UNIT_GALLON, UNIT_LITER, UNIT_MILLILITER} from "../../../shared/units"; +import {Component} from '@angular/core' +import {RecipeService} from '../../services/recipe.service' +import {ActivatedRoute, Router} from '@angular/router' +import {ErrorHandlingComponent} from '../../../shared/components/subscribing.component' +import {Recipe} from '../../../shared/model/recipe.model' +import {Observable, Subject} from 'rxjs' +import {ErrorModel, ErrorService} from '../../../shared/service/error.service' +import {AlertService} from '../../../shared/service/alert.service' +import {GlobalAlertHandlerComponent} from '../../../shared/components/global-alert-handler/global-alert-handler.component' @Component({ selector: 'cre-explore', templateUrl: './explore.component.html', styleUrls: ['./explore.component.sass'] }) -export class ExploreComponent extends SubscribingComponent { - readonly unitConstants = {UNIT_MILLILITER, UNIT_LITER, UNIT_GALLON} - +export class ExploreComponent extends ErrorHandlingComponent { recipe: Recipe | null - error: string deductErrorBody = {} - success: string units$ = new Subject() hasModifications = false note: string | null quantitiesChanges = new Map>() mixesLocationChanges = new Map() - printingError = 2 - // Errors - readonly ERROR_UNKNOWN = 'unknown' - readonly ERROR_DEDUCT = 'deduct' - // Success - readonly SUCCESS_SAVE = 'save' - readonly SUCCESS_DEDUCT = 'deduct' + handledErrorModels: ErrorModel[] = [{ + filter: error => error.status === 409, + consumer: error => this.deductErrorBody = error.error, + messageProducer: () => 'Certains produit ne sont pas en quantité suffisante dans l\'inventaire' + }] constructor( private recipeService: RecipeService, + private alertService: AlertService, + errorService: ErrorService, router: Router, activatedRoute: ActivatedRoute ) { - super(activatedRoute, router) + super(errorService, activatedRoute, router) } ngOnInit(): void { super.ngOnInit() + GlobalAlertHandlerComponent.extraTopMarginMultiplier = 2.5 const id = parseInt(this.activatedRoute.snapshot.paramMap.get('id')) - this.subscribe( - this.recipeService.getById(id), - { - next: r => { - this.recipe = r - this.note = r.note - }, - error: err => this.handleNotFoundError(err, '/colors/list') + this.subscribeEntityById( + this.recipeService, + id, + r => { + this.recipe = r + this.note = r.note }, - 1 + '/colors/list' ) } + ngOnDestroy() { + super.ngOnDestroy(); + GlobalAlertHandlerComponent.extraTopMarginMultiplier = 0 + } + changeUnits(unit: string) { this.units$.next(unit) } @@ -68,7 +70,9 @@ export class ExploreComponent extends SubscribingComponent { } changeQuantity(event: { id: number, materialId: number, quantity: number }) { - if (!this.quantitiesChanges.has(event.id)) this.quantitiesChanges.set(event.id, new Map()) + if (!this.quantitiesChanges.has(event.id)) { + this.quantitiesChanges.set(event.id, new Map()) + } this.quantitiesChanges.get(event.id).set(event.materialId, event.quantity) } @@ -80,19 +84,7 @@ export class ExploreComponent extends SubscribingComponent { saveModifications() { this.subscribe( this.recipeService.saveExplorerModifications(this.recipe.id, this.note, this.mixesLocationChanges), - { - next: () => { - this.hasModifications = false - this.error = null - this.success = this.SUCCESS_SAVE - }, - error: err => { - this.success = null - this.error = this.ERROR_UNKNOWN - console.error(err) - } - }, - 1 + () => this.alertService.pushSuccess('Les modifications ont été enregistrées') ) } @@ -107,23 +99,7 @@ export class ExploreComponent extends SubscribingComponent { performDeductQuantities(observable: Observable) { this.subscribe( observable, - { - next: () => { - this.error = null - this.success = this.SUCCESS_DEDUCT - }, - error: err => { - this.success = null - if (err.status === 409) { // There is not enough of one or more materials in the inventory - this.error = this.ERROR_DEDUCT - this.deductErrorBody = err.error - } else { - this.error = this.ERROR_UNKNOWN - console.error(err) - } - } - }, - 1 + () => this.alertService.pushSuccess('Les quantités des produits utilisés ont été déduites de l\'inventaire') ) } } diff --git a/src/app/modules/colors/pages/list/list.component.ts b/src/app/modules/colors/pages/list/list.component.ts index 1107b7e..ca2c87d 100644 --- a/src/app/modules/colors/pages/list/list.component.ts +++ b/src/app/modules/colors/pages/list/list.component.ts @@ -1,30 +1,34 @@ -import {Component} from '@angular/core'; -import {SubscribingComponent} from "../../../shared/components/subscribing.component"; -import {RecipeService} from "../../services/recipe.service"; -import {EmployeePermission} from "../../../shared/model/employee"; -import {AccountService} from "../../../accounts/services/account.service"; -import {Recipe} from "../../../shared/model/recipe.model"; -import {ActivatedRoute, Router} from "@angular/router"; +import {Component} from '@angular/core' +import {ErrorHandlingComponent} from '../../../shared/components/subscribing.component' +import {RecipeService} from '../../services/recipe.service' +import {EmployeePermission} from '../../../shared/model/employee' +import {AccountService} from '../../../accounts/services/account.service' +import {Recipe} from '../../../shared/model/recipe.model' +import {ActivatedRoute, Router} from '@angular/router' +import {ErrorModel, ErrorService} from '../../../shared/service/error.service' @Component({ selector: 'cre-list', templateUrl: './list.component.html', styleUrls: ['./list.component.sass'] }) -export class ListComponent extends SubscribingComponent { +export class ListComponent extends ErrorHandlingComponent { recipes$ = this.recipeService.allSortedByCompany tableCols = ['name', 'description', 'sample', 'iconNotApproved', 'buttonView', 'buttonEdit'] searchQuery = "" panelForcedExpanded = false recipesHidden = [] + handledErrorModels: ErrorModel[] + constructor( private recipeService: RecipeService, private accountService: AccountService, + errorService: ErrorService, router: Router, activatedRoute: ActivatedRoute ) { - super(activatedRoute, router) + super(errorService, activatedRoute, router) } ngOnInit() { diff --git a/src/app/modules/colors/pages/mix/mix-add/mix-add.component.ts b/src/app/modules/colors/pages/mix/mix-add/mix-add.component.ts index ca267d1..3916658 100644 --- a/src/app/modules/colors/pages/mix/mix-add/mix-add.component.ts +++ b/src/app/modules/colors/pages/mix/mix-add/mix-add.component.ts @@ -1,26 +1,30 @@ -import {Component} from '@angular/core'; -import {Material} from "../../../../shared/model/material.model"; -import {MaterialService} from "../../../../material/service/material.service"; -import {ActivatedRoute, Router} from "@angular/router"; -import {SubscribingComponent} from "../../../../shared/components/subscribing.component"; -import {MixService} from "../../../services/mix.service"; +import {Component} from '@angular/core' +import {Material} from '../../../../shared/model/material.model' +import {MaterialService} from '../../../../material/service/material.service' +import {ActivatedRoute, Router} from '@angular/router' +import {ErrorHandlingComponent, SubscribingComponent} from '../../../../shared/components/subscribing.component' +import {MixService} from '../../../services/mix.service' +import {ErrorHandler, ErrorModel, ErrorService} from '../../../../shared/service/error.service' @Component({ selector: 'cre-mix-add', templateUrl: './mix-add.component.html', styleUrls: ['./mix-add.component.sass'] }) -export class MixAddComponent extends SubscribingComponent { +export class MixAddComponent extends ErrorHandlingComponent { recipeId: number | null materials: Material[] | null + handledErrorModels: ErrorModel[] + constructor( private materialService: MaterialService, private mixService: MixService, + errorService: ErrorService, router: Router, activatedRoute: ActivatedRoute ) { - super(activatedRoute, router) + super(errorService, activatedRoute, router) } ngOnInit(): void { @@ -30,14 +34,14 @@ export class MixAddComponent extends SubscribingComponent { this.subscribe( this.materialService.getAllForMixCreation(this.recipeId), - {next: m => this.materials = m} + m => this.materials = m ) } submit(values) { - this.subscribe( + this.subscribeAndNavigate( this.mixService.saveWithUnits(values.name, values.recipeId, values.materialTypeId, values.mixMaterials, values.units), - {next: () => this.urlUtils.navigateTo(`/color/edit/${this.recipeId}`)} + `/color/edit/${this.recipeId}` ) } } diff --git a/src/app/modules/colors/pages/mix/mix-edit/mix-edit.component.ts b/src/app/modules/colors/pages/mix/mix-edit/mix-edit.component.ts index 981998d..f463f5f 100644 --- a/src/app/modules/colors/pages/mix/mix-edit/mix-edit.component.ts +++ b/src/app/modules/colors/pages/mix/mix-edit/mix-edit.component.ts @@ -1,27 +1,31 @@ -import {Component} from '@angular/core'; -import {ActivatedRoute, Router} from "@angular/router"; -import {SubscribingComponent} from "../../../../shared/components/subscribing.component"; -import {Material} from "../../../../shared/model/material.model"; -import {MaterialService} from "../../../../material/service/material.service"; -import {MixService} from "../../../services/mix.service"; +import {Component} from '@angular/core' +import {ActivatedRoute, Router} from '@angular/router' +import {ErrorHandlingComponent} from '../../../../shared/components/subscribing.component' +import {Material} from '../../../../shared/model/material.model' +import {MaterialService} from '../../../../material/service/material.service' +import {MixService} from '../../../services/mix.service' +import {ErrorModel, ErrorService} from '../../../../shared/service/error.service' @Component({ selector: 'cre-mix-edit', templateUrl: './mix-edit.component.html', styleUrls: ['./mix-edit.component.sass'] }) -export class MixEditComponent extends SubscribingComponent { +export class MixEditComponent extends ErrorHandlingComponent { mixId: number | null recipeId: number | null materials: Material[] | null + handledErrorModels: ErrorModel[] + constructor( private materialService: MaterialService, private mixService: MixService, + errorService: ErrorService, router: Router, activatedRoute: ActivatedRoute ) { - super(activatedRoute, router) + super(errorService, activatedRoute, router) } ngOnInit(): void { @@ -32,14 +36,14 @@ export class MixEditComponent extends SubscribingComponent { this.subscribe( this.materialService.getAllForMixUpdate(this.mixId), - {next: m => this.materials = m} + m => this.materials = m ) } submit(values) { - this.subscribe( + this.subscribeAndNavigate( this.mixService.updateWithUnits(this.mixId, values.name, values.materialTypeId, values.mixMaterials, values.units), - {next: () => this.urlUtils.navigateTo(`/color/edit/${this.recipeId}`)} + `/color/edit/${this.recipeId}` ) } } diff --git a/src/app/modules/company/pages/add/add.component.html b/src/app/modules/company/pages/add/add.component.html index 75daec8..a63280a 100644 --- a/src/app/modules/company/pages/add/add.component.html +++ b/src/app/modules/company/pages/add/add.component.html @@ -1,8 +1,6 @@ diff --git a/src/app/modules/company/pages/add/add.component.ts b/src/app/modules/company/pages/add/add.component.ts index fd0db62..0579fe3 100644 --- a/src/app/modules/company/pages/add/add.component.ts +++ b/src/app/modules/company/pages/add/add.component.ts @@ -1,16 +1,17 @@ -import {Component} from '@angular/core'; -import {CompanyService} from "../../service/company.service"; -import {FormBuilder, Validators} from "@angular/forms"; -import {SubscribingComponent} from "../../../shared/components/subscribing.component"; -import {FormField} from "../../../shared/components/entity-add/entity-add.component"; -import {ActivatedRoute, Router} from "@angular/router"; +import {Component} from '@angular/core' +import {CompanyService} from '../../service/company.service' +import {Validators} from '@angular/forms' +import {ErrorHandlingComponent} from '../../../shared/components/subscribing.component' +import {FormField} from '../../../shared/components/entity-add/entity-add.component' +import {ActivatedRoute, Router} from '@angular/router' +import {ErrorModel, ErrorService} from '../../../shared/service/error.service' @Component({ selector: 'cre-add', templateUrl: './add.component.html', styleUrls: ['./add.component.sass'] }) -export class AddComponent extends SubscribingComponent { +export class AddComponent extends ErrorHandlingComponent { formFields: FormField[] = [ { name: 'name', @@ -23,31 +24,31 @@ export class AddComponent extends SubscribingComponent { ] } ] - unknownError = false - errorMessage: string | null + submittedValues: any | null + + handledErrorModels: ErrorModel[] = [{ + filter: error => error.status === 409, + messageProducer: () => `Une bannière avec le nom '${this.submittedValues.name}' existe déjà` + }] constructor( private companyService: CompanyService, + errorService: ErrorService, router: Router, activatedRoute: ActivatedRoute ) { - super(activatedRoute, router) + super(errorService, activatedRoute, router) + } + + ngOnInit() { + super.ngOnInit() } submit(values) { - this.subscribe( + this.submittedValues = values + this.subscribeAndNavigate( this.companyService.save(values.name), - { - next: () => this.router.navigate(['/catalog/company/list']), - error: err => { - if (err.status === 409) { - this.errorMessage = `Une bannière avec le nom '${values.name}' existe déjà` - } else { - this.unknownError = true - console.log(err) - } - } - } + '/catalog/company/list' ) } } diff --git a/src/app/modules/company/pages/edit/edit.component.html b/src/app/modules/company/pages/edit/edit.component.html index d3211cd..04864a7 100644 --- a/src/app/modules/company/pages/edit/edit.component.html +++ b/src/app/modules/company/pages/edit/edit.component.html @@ -6,8 +6,6 @@ deletePermission="REMOVE_COMPANY" [entity]="company" [formFields]="formFields" - [unknownError]="unknownError" - [customError]="errorMessage" (submit)="submit($event)" (delete)="delete()"> diff --git a/src/app/modules/company/pages/edit/edit.component.ts b/src/app/modules/company/pages/edit/edit.component.ts index b828812..af7ebbf 100644 --- a/src/app/modules/company/pages/edit/edit.component.ts +++ b/src/app/modules/company/pages/edit/edit.component.ts @@ -1,17 +1,18 @@ -import {Component} from '@angular/core'; -import {SubscribingComponent} from "../../../shared/components/subscribing.component"; -import {Company} from "../../../shared/model/company.model"; -import {FormField} from "../../../shared/components/entity-add/entity-add.component"; -import {FormBuilder, Validators} from "@angular/forms"; -import {CompanyService} from "../../service/company.service"; -import {ActivatedRoute, Router} from "@angular/router"; +import {Component} from '@angular/core' +import {ErrorHandlingComponent} from '../../../shared/components/subscribing.component' +import {Company} from '../../../shared/model/company.model' +import {FormField} from '../../../shared/components/entity-add/entity-add.component' +import {Validators} from '@angular/forms' +import {CompanyService} from '../../service/company.service' +import {ActivatedRoute, Router} from '@angular/router' +import {ErrorModel, ErrorService} from '../../../shared/service/error.service' @Component({ selector: 'cre-edit', templateUrl: './edit.component.html', styleUrls: ['./edit.component.sass'] }) -export class EditComponent extends SubscribingComponent { +export class EditComponent extends ErrorHandlingComponent { company: Company | null formFields: FormField[] = [ { @@ -25,64 +26,44 @@ export class EditComponent extends SubscribingComponent { ] } ] - unknownError = false - errorMessage: string | null + + handledErrorModels: ErrorModel[] = [{ + filter: error => error.status === 409, + messageProducer: error => `Une bannière avec le nom '${error.error.id}' existe déjà` + }] constructor( private companyService: CompanyService, + errorService: ErrorService, router: Router, activatedRoute: ActivatedRoute ) { - super(activatedRoute, router) + super(errorService, activatedRoute, router) } ngOnInit(): void { super.ngOnInit() const id = parseInt(this.activatedRoute.snapshot.paramMap.get('id')) - this.subscribe( - this.companyService.getById(id), - { - next: company => this.company = company, - error: err => { - if (err.status == 404) { - this.router.navigate(['/catalog/company/list']) - } else { - this.unknownError = true - } - } - }, - 1 + this.subscribeEntityById( + this.companyService, + id, + company => this.company = company, + '/catalog/company/list' ) } submit(values) { - this.subscribe( + this.subscribeAndNavigate( this.companyService.update(this.company.id, values.name), - { - next: () => this.router.navigate(['/catalog/company/list']), - error: err => { - if (err.status == 409) { - this.errorMessage = `Une bannière avec le nom '${values.name}' existe déjà` - } else { - this.unknownError = true - } - console.log(err) - } - } + '/catalog/company/list' ) } delete() { - this.subscribe( + this.subscribeAndNavigate( this.companyService.delete(this.company.id), - { - next: () => this.router.navigate(['/catalog/company/list']), - error: err => { - this.unknownError = true - console.log(err) - } - } + '/catalog/company/list' ) } } diff --git a/src/app/modules/company/pages/list/list.component.ts b/src/app/modules/company/pages/list/list.component.ts index 83c85f0..7f7a88d 100644 --- a/src/app/modules/company/pages/list/list.component.ts +++ b/src/app/modules/company/pages/list/list.component.ts @@ -1,16 +1,16 @@ -import {Component} from '@angular/core'; -import {SubscribingComponent} from "../../../shared/components/subscribing.component"; -import {CompanyService} from "../../service/company.service"; -import {EmployeePermission} from "../../../shared/model/employee"; -import {FormBuilder} from "@angular/forms"; -import {ActivatedRoute, Router} from "@angular/router"; +import {Component} from '@angular/core' +import {ErrorHandlingComponent} from '../../../shared/components/subscribing.component' +import {CompanyService} from '../../service/company.service' +import {EmployeePermission} from '../../../shared/model/employee' +import {ActivatedRoute, Router} from '@angular/router' +import {ErrorService} from '../../../shared/service/error.service' @Component({ selector: 'cre-list', templateUrl: './list.component.html', styleUrls: ['./list.component.sass'] }) -export class ListComponent extends SubscribingComponent { +export class ListComponent extends ErrorHandlingComponent { companies$ = this.companyService.all columns = [ {def: 'name', title: 'Nom', valueFn: c => c.name} @@ -23,9 +23,10 @@ export class ListComponent extends SubscribingComponent { constructor( private companyService: CompanyService, + errorService: ErrorService, router: Router, activatedRoute: ActivatedRoute ) { - super(activatedRoute, router) + super(errorService, activatedRoute, router) } } diff --git a/src/app/modules/employees/pages/add/add.component.html b/src/app/modules/employees/pages/add/add.component.html index 69f1ebe..951e943 100644 --- a/src/app/modules/employees/pages/add/add.component.html +++ b/src/app/modules/employees/pages/add/add.component.html @@ -3,10 +3,6 @@ Création d'un employé -
-

Une erreur est survenue

-
-
Numéro d'employé diff --git a/src/app/modules/employees/pages/add/add.component.ts b/src/app/modules/employees/pages/add/add.component.ts index 3e8cc51..a11377a 100644 --- a/src/app/modules/employees/pages/add/add.component.ts +++ b/src/app/modules/employees/pages/add/add.component.ts @@ -1,20 +1,20 @@ -import {Component, OnDestroy, OnInit, ViewChild} from '@angular/core'; -import {FormBuilder, FormControl, FormGroup, Validators} from "@angular/forms"; -import {PermissionsFieldComponent} from "../../../shared/components/permissions-field/permissions-field.component"; -import {EmployeeGroup} from "../../../shared/model/employee"; -import {Observable, Subject} from "rxjs"; -import {GroupService} from "../../../groups/services/group.service"; -import {take, takeUntil} from "rxjs/operators"; -import {EmployeeService} from "../../services/employee.service"; -import {ActivatedRoute, Router} from "@angular/router"; -import {SubscribingComponent} from "../../../shared/components/subscribing.component"; +import {Component, ViewChild} from '@angular/core' +import {FormControl, FormGroup, Validators} from '@angular/forms' +import {PermissionsFieldComponent} from '../../../shared/components/permissions-field/permissions-field.component' +import {EmployeeGroup} from '../../../shared/model/employee' +import {Observable} from 'rxjs' +import {GroupService} from '../../../groups/services/group.service' +import {EmployeeService} from '../../services/employee.service' +import {ActivatedRoute, Router} from '@angular/router' +import {ErrorHandlingComponent} from '../../../shared/components/subscribing.component' +import {ErrorService} from '../../../shared/service/error.service' @Component({ selector: 'cre-add', templateUrl: './add.component.html', styleUrls: ['./add.component.sass'] }) -export class AddComponent extends SubscribingComponent { +export class AddComponent extends ErrorHandlingComponent { @ViewChild('permissionsField', {static: true}) permissionsField: PermissionsFieldComponent form: FormGroup @@ -23,17 +23,17 @@ export class AddComponent extends SubscribingComponent { lastNameControl: FormControl passwordControl: FormControl groupControl: FormControl - unknownError = false group$: Observable | null constructor( private employeeService: EmployeeService, private groupService: GroupService, + errorService: ErrorService, router: Router, activatedRoute: ActivatedRoute ) { - super(activatedRoute, router) + super(errorService, activatedRoute, router) } ngOnInit(): void { @@ -57,7 +57,7 @@ export class AddComponent extends SubscribingComponent { submit() { if (this.permissionsField.valid() && this.form.valid) { - this.subscribe( + this.subscribeAndNavigate( this.employeeService.save( parseInt(this.idControl.value), this.firstNameControl.value, @@ -66,13 +66,7 @@ export class AddComponent extends SubscribingComponent { this.groupControl.value, this.permissionsField.allEnabledPermissions ), - { - next: () => this.router.navigate(['/employee/list']), - error: err => { - console.error(err) - this.unknownError = true - } - } + '/employee/list' ) } } diff --git a/src/app/modules/employees/pages/edit/edit.component.html b/src/app/modules/employees/pages/edit/edit.component.html index 4aa184b..73bc07f 100644 --- a/src/app/modules/employees/pages/edit/edit.component.html +++ b/src/app/modules/employees/pages/edit/edit.component.html @@ -3,10 +3,6 @@ Modification de l'employé #{{employee.id}} -
-

Une erreur est survenue

-
- Numéro d'employé diff --git a/src/app/modules/employees/pages/edit/edit.component.ts b/src/app/modules/employees/pages/edit/edit.component.ts index 6199b9c..ad45c80 100644 --- a/src/app/modules/employees/pages/edit/edit.component.ts +++ b/src/app/modules/employees/pages/edit/edit.component.ts @@ -1,22 +1,22 @@ -import {Component} from '@angular/core'; -import {PermissionsFieldComponent} from "../../../shared/components/permissions-field/permissions-field.component"; -import {FormBuilder, FormControl, FormGroup, Validators} from "@angular/forms"; -import {EmployeeService} from "../../services/employee.service"; -import {GroupService} from "../../../groups/services/group.service"; -import {ActivatedRoute, Router} from "@angular/router"; -import {Observable} from "rxjs"; -import {Employee, EmployeeGroup, EmployeePermission} from "../../../shared/model/employee"; -import {AccountService} from "../../../accounts/services/account.service"; -import {SubscribingComponent} from "../../../shared/components/subscribing.component"; +import {Component} from '@angular/core' +import {PermissionsFieldComponent} from '../../../shared/components/permissions-field/permissions-field.component' +import {FormBuilder, FormControl, FormGroup, Validators} from '@angular/forms' +import {EmployeeService} from '../../services/employee.service' +import {GroupService} from '../../../groups/services/group.service' +import {ActivatedRoute, Router} from '@angular/router' +import {Observable} from 'rxjs' +import {Employee, EmployeeGroup, EmployeePermission} from '../../../shared/model/employee' +import {AccountService} from '../../../accounts/services/account.service' +import {ErrorHandlingComponent} from '../../../shared/components/subscribing.component' +import {ErrorService} from '../../../shared/service/error.service' @Component({ selector: 'cre-edit', templateUrl: './edit.component.html', styleUrls: ['./edit.component.sass'] }) -export class EditComponent extends SubscribingComponent { +export class EditComponent extends ErrorHandlingComponent { employee: Employee | null - unknownError = false group$: Observable | null @@ -30,27 +30,20 @@ export class EditComponent extends SubscribingComponent { private employeeService: EmployeeService, private groupService: GroupService, private formBuilder: FormBuilder, + errorService: ErrorService, router: Router, activatedRoute: ActivatedRoute ) { - super(activatedRoute, router) + super(errorService, activatedRoute, router) } ngOnInit(): void { - const employeeId = this.activatedRoute.snapshot.paramMap.get("id") - this.subscribe( - this.employeeService.get(parseInt(employeeId)), - { - next: employee => this.employee = employee, - error: err => { - if (err.status === 404) { - this.router.navigate(['/employee/list']) - } else { - this.unknownError = true - } - } - }, - 1 + const id = parseInt(this.activatedRoute.snapshot.paramMap.get('id')) + this.subscribeEntityById( + this.employeeService, + id, + employee => this.employee = employee, + '/employee/list' ) this.group$ = this.groupService.all @@ -65,40 +58,22 @@ export class EditComponent extends SubscribingComponent { this.lastNameControl.value, permissionsField.allEnabledPermissions ), - { - next: () => { - const group = parseInt(this._groupControl.value) - if (!isNaN(group)) { - this.subscribe( - this.groupService.addEmployeeToGroup(group, this.employee), - { - next: () => this.router.navigate(['/employee/list']), - error: err => { - console.error(err) - this.unknownError = true - } - } + () => { + const group = parseInt(this._groupControl.value) + if (!isNaN(group)) { + this.subscribeAndNavigate( + this.groupService.addEmployeeToGroup(group, this.employee), + '/employee/list' + ) + } else { + if (this.employee.group) { + this.subscribeAndNavigate( + this.groupService.removeEmployeeFromGroup(this.employee), + '/employee/list' ) } else { - if (this.employee.group) { - this.subscribe( - this.groupService.removeEmployeeFromGroup(this.employee), - { - next: () => this.router.navigate(['/employee/list']), - error: err => { - console.error(err) - this.unknownError = true - } - } - ) - } else { - this.router.navigate(['/employee/list']) - } + this.router.navigate(['/employee/list']) } - }, - error: err => { - console.error(err) - this.unknownError = true } } ) @@ -106,15 +81,9 @@ export class EditComponent extends SubscribingComponent { } delete() { - this.subscribe( + this.subscribeAndNavigate( this.employeeService.delete(this.employee.id), - { - next: () => this.router.navigate(['/employee/list']), - error: err => { - this.unknownError = true - console.error(err) - } - } + '/employee/list' ) } @@ -148,7 +117,9 @@ export class EditComponent extends SubscribingComponent { } private lazyControl(control: FormControl, provider: () => FormControl): FormControl { - if (control) return control + if (control) { + return control + } if (this.employee) { return provider() } diff --git a/src/app/modules/employees/pages/list/list.component.ts b/src/app/modules/employees/pages/list/list.component.ts index f5c6f02..6805ea6 100644 --- a/src/app/modules/employees/pages/list/list.component.ts +++ b/src/app/modules/employees/pages/list/list.component.ts @@ -1,13 +1,13 @@ -import {Component} from '@angular/core'; -import {Observable} from "rxjs"; -import {EmployeeService} from "../../services/employee.service"; -import {Employee, EmployeePermission} from "../../../shared/model/employee"; -import {takeUntil} from "rxjs/operators"; -import {AccountService} from "../../../accounts/services/account.service"; -import {animate, state, style, transition, trigger} from "@angular/animations"; -import {SubscribingComponent} from "../../../shared/components/subscribing.component"; -import {FormBuilder} from "@angular/forms"; -import {ActivatedRoute, Router} from "@angular/router"; +import {Component} from '@angular/core' +import {Observable} from 'rxjs' +import {EmployeeService} from '../../services/employee.service' +import {Employee, EmployeePermission} from '../../../shared/model/employee' +import {takeUntil} from 'rxjs/operators' +import {AccountService} from '../../../accounts/services/account.service' +import {animate, state, style, transition, trigger} from '@angular/animations' +import {ErrorHandlingComponent} from '../../../shared/components/subscribing.component' +import {ActivatedRoute, Router} from '@angular/router' +import {ErrorService} from '../../../shared/service/error.service' @Component({ selector: 'cre-employees', @@ -21,7 +21,7 @@ import {ActivatedRoute, Router} from "@angular/router"; ]) ] }) -export class ListComponent extends SubscribingComponent { +export class ListComponent extends ErrorHandlingComponent { employees$: Observable columns = ['id', 'name', 'group', 'permissionCount', 'lastLogin', 'editButton', 'editPasswordButton'] @@ -30,10 +30,11 @@ export class ListComponent extends SubscribingComponent { constructor( private employeeService: EmployeeService, private accountService: AccountService, + errorService: ErrorService, router: Router, activatedRoute: ActivatedRoute ) { - super(activatedRoute, router) + super(errorService, activatedRoute, router) } ngOnInit(): void { diff --git a/src/app/modules/employees/pages/password-edit/password-edit.component.ts b/src/app/modules/employees/pages/password-edit/password-edit.component.ts index eda5cc9..0be7343 100644 --- a/src/app/modules/employees/pages/password-edit/password-edit.component.ts +++ b/src/app/modules/employees/pages/password-edit/password-edit.component.ts @@ -1,16 +1,17 @@ -import {Component} from '@angular/core'; -import {SubscribingComponent} from "../../../shared/components/subscribing.component"; -import {EmployeeService} from "../../services/employee.service"; -import {Employee} from "../../../shared/model/employee"; -import {ActivatedRoute, Router} from "@angular/router"; -import {FormBuilder, FormControl, FormGroup, Validators} from "@angular/forms"; +import {Component} from '@angular/core' +import {ErrorHandlingComponent} from '../../../shared/components/subscribing.component' +import {EmployeeService} from '../../services/employee.service' +import {Employee} from '../../../shared/model/employee' +import {ActivatedRoute, Router} from '@angular/router' +import {FormBuilder, FormControl, FormGroup, Validators} from '@angular/forms' +import {ErrorService} from '../../../shared/service/error.service' @Component({ selector: 'cre-password-edit', templateUrl: './password-edit.component.html', styleUrls: ['./password-edit.component.sass'] }) -export class PasswordEditComponent extends SubscribingComponent { +export class PasswordEditComponent extends ErrorHandlingComponent { employee: Employee | null form: FormGroup @@ -19,19 +20,20 @@ export class PasswordEditComponent extends SubscribingComponent { constructor( private employeeService: EmployeeService, private formBuilder: FormBuilder, + errorService: ErrorService, router: Router, activatedRoute: ActivatedRoute ) { - super(activatedRoute, router) + super(errorService, activatedRoute, router) } ngOnInit(): void { - const employeeId = this.activatedRoute.snapshot.paramMap.get('id') - this.subscribe( - this.employeeService.get(parseInt(employeeId)), - { - next: employee => this.employee = employee - } + const id = parseInt(this.activatedRoute.snapshot.paramMap.get('id')) + this.subscribeEntityById( + this.employeeService, + id, + employee => this.employee = employee, + '/employee/list' ) this.form = this.formBuilder.group({ @@ -41,11 +43,9 @@ export class PasswordEditComponent extends SubscribingComponent { submit() { if (this.form.valid) { - this.subscribe( + this.subscribeAndNavigate( this.employeeService.updatePassword(this.employee.id, this.passwordControl.value), - { - next: () => this.router.navigate(['/employee/list']) - } + '/employee/list' ) } } diff --git a/src/app/modules/employees/services/employee.service.ts b/src/app/modules/employees/services/employee.service.ts index 57660fb..1303068 100644 --- a/src/app/modules/employees/services/employee.service.ts +++ b/src/app/modules/employees/services/employee.service.ts @@ -16,7 +16,7 @@ export class EmployeeService { return this.api.get('/employee') } - get(id: number): Observable { + getById(id: number): Observable { return this.api.get(`/employee/${id}`) } diff --git a/src/app/modules/groups/components/employees-list/employees-list.component.ts b/src/app/modules/groups/components/employees-list/employees-list.component.ts index d9133f0..d99d8bc 100644 --- a/src/app/modules/groups/components/employees-list/employees-list.component.ts +++ b/src/app/modules/groups/components/employees-list/employees-list.component.ts @@ -1,22 +1,20 @@ -import {Component, Input, OnDestroy, OnInit} from '@angular/core'; -import {Employee, EmployeeGroup, EmployeePermission} from "../../../shared/model/employee"; -import {GroupService} from "../../services/group.service"; -import {Observable, Subject} from "rxjs"; -import {takeUntil} from "rxjs/operators"; -import {AccountService} from "../../../accounts/services/account.service"; +import {Component, Input, OnInit} from '@angular/core' +import {Employee, EmployeeGroup, EmployeePermission} from '../../../shared/model/employee' +import {GroupService} from '../../services/group.service' +import {AccountService} from '../../../accounts/services/account.service' +import {Observable} from 'rxjs' @Component({ selector: 'cre-employees-list', templateUrl: './employees-list.component.html', styleUrls: ['./employees-list.component.sass'] }) -export class EmployeesListComponent implements OnInit, OnDestroy { +export class EmployeesListComponent implements OnInit { @Input() group: EmployeeGroup + employees$: Observable | null columns = ['id', 'firstName', 'lastName', 'edit'] - private _destroy$ = new Subject() - constructor( private accountService: AccountService, private groupService: GroupService @@ -24,12 +22,7 @@ export class EmployeesListComponent implements OnInit, OnDestroy { } ngOnInit(): void { - this.employees$ = this.groupService.getEmployeesForGroup(this.group.id).pipe(takeUntil(this._destroy$)) - } - - ngOnDestroy(): void { - this._destroy$.next(true) - this._destroy$.complete() + this.employees$ = this.groupService.getEmployeesForGroup(this.group.id) } get canEditEmployee(): boolean { diff --git a/src/app/modules/groups/pages/add/add.component.html b/src/app/modules/groups/pages/add/add.component.html index 37169fb..b00be66 100644 --- a/src/app/modules/groups/pages/add/add.component.html +++ b/src/app/modules/groups/pages/add/add.component.html @@ -3,10 +3,6 @@ Création d'un groupe -
-

Une erreur est survenue

-
- Nom diff --git a/src/app/modules/groups/pages/add/add.component.ts b/src/app/modules/groups/pages/add/add.component.ts index efa8da0..a1a30a6 100644 --- a/src/app/modules/groups/pages/add/add.component.ts +++ b/src/app/modules/groups/pages/add/add.component.ts @@ -1,29 +1,30 @@ -import {Component, ViewChild} from '@angular/core'; -import {FormBuilder, FormControl, FormGroup, Validators} from "@angular/forms"; -import {GroupService} from "../../services/group.service"; -import {ActivatedRoute, Router} from "@angular/router"; -import {PermissionsFieldComponent} from "../../../shared/components/permissions-field/permissions-field.component"; -import {SubscribingComponent} from "../../../shared/components/subscribing.component"; +import {Component, ViewChild} from '@angular/core' +import {FormBuilder, FormControl, FormGroup, Validators} from '@angular/forms' +import {GroupService} from '../../services/group.service' +import {ActivatedRoute, Router} from '@angular/router' +import {PermissionsFieldComponent} from '../../../shared/components/permissions-field/permissions-field.component' +import {ErrorHandlingComponent} from '../../../shared/components/subscribing.component' +import {ErrorService} from '../../../shared/service/error.service' @Component({ selector: 'cre-add', templateUrl: './add.component.html', styleUrls: ['./add.component.sass'] }) -export class AddComponent extends SubscribingComponent { +export class AddComponent extends ErrorHandlingComponent { @ViewChild('permissionsField', {static: true}) permissionsField: PermissionsFieldComponent form: FormGroup nameControl: FormControl - unknownError = false constructor( private formBuilder: FormBuilder, private groupService: GroupService, + errorService: ErrorService, router: Router, activatedRoute: ActivatedRoute ) { - super(activatedRoute, router) + super(errorService, activatedRoute, router) } ngOnInit(): void { @@ -35,15 +36,9 @@ export class AddComponent extends SubscribingComponent { submit() { if (this.form.valid && this.permissionsField.valid()) { - this.subscribe( + this.subscribeAndNavigate( this.groupService.save(this.nameControl.value, this.permissionsField.allEnabledPermissions), - { - next: () => this.router.navigate(['/group/list']), - error: err => { - this.unknownError = true - console.log(err) - } - } + '/group/list' ) } } diff --git a/src/app/modules/groups/pages/edit/edit.component.html b/src/app/modules/groups/pages/edit/edit.component.html index 2f45204..5d99d8b 100644 --- a/src/app/modules/groups/pages/edit/edit.component.html +++ b/src/app/modules/groups/pages/edit/edit.component.html @@ -3,10 +3,6 @@ Modifier le groupe {{group.name}} -
-

Une erreur est survenue

-
- Nom diff --git a/src/app/modules/groups/pages/edit/edit.component.ts b/src/app/modules/groups/pages/edit/edit.component.ts index 0ef4658..f629334 100644 --- a/src/app/modules/groups/pages/edit/edit.component.ts +++ b/src/app/modules/groups/pages/edit/edit.component.ts @@ -1,22 +1,22 @@ -import {Component, ViewChild} from '@angular/core'; -import {ActivatedRoute, Router} from "@angular/router"; -import {EmployeeGroup, EmployeePermission} from "../../../shared/model/employee"; -import {GroupService} from "../../services/group.service"; -import {FormBuilder, FormControl, FormGroup, Validators} from "@angular/forms"; -import {PermissionsFieldComponent} from "../../../shared/components/permissions-field/permissions-field.component"; -import {AccountService} from "../../../accounts/services/account.service"; -import {SubscribingComponent} from "../../../shared/components/subscribing.component"; +import {Component, ViewChild} from '@angular/core' +import {ActivatedRoute, Router} from '@angular/router' +import {EmployeeGroup, EmployeePermission} from '../../../shared/model/employee' +import {GroupService} from '../../services/group.service' +import {FormBuilder, FormControl, FormGroup, Validators} from '@angular/forms' +import {PermissionsFieldComponent} from '../../../shared/components/permissions-field/permissions-field.component' +import {AccountService} from '../../../accounts/services/account.service' +import {ErrorHandlingComponent} from '../../../shared/components/subscribing.component' +import {ErrorService} from '../../../shared/service/error.service' @Component({ selector: 'cre-edit', templateUrl: './edit.component.html', styleUrls: ['./edit.component.sass'] }) -export class EditComponent extends SubscribingComponent { +export class EditComponent extends ErrorHandlingComponent { @ViewChild('permissionsField') permissionsField: PermissionsFieldComponent group: EmployeeGroup | null - unknownError = false private _nameControl: FormControl @@ -24,54 +24,36 @@ export class EditComponent extends SubscribingComponent { private accountService: AccountService, private groupService: GroupService, private formBuilder: FormBuilder, + errorService: ErrorService, router: Router, activatedRoute: ActivatedRoute ) { - super(activatedRoute, router) + super(errorService, activatedRoute, router) } ngOnInit(): void { - const groupId = this.activatedRoute.snapshot.paramMap.get("id") - this.subscribe( - this.groupService.get(parseInt(groupId)), - { - next: group => this.group = group, - error: err => { - if (err.status === 404) { - this.router.navigate(['/group/list']) - } else { - this.unknownError = true - } - } - } + const id = parseInt(this.activatedRoute.snapshot.paramMap.get('id')) + this.subscribeEntityById( + this.groupService, + id, + group => this.group = group, + '/group/list' ) } submit(): void { if (this.form.valid && this.permissionsField.valid()) { - this.subscribe( + this.subscribeAndNavigate( this.groupService.update(this.group.id, this.nameControl.value, this.permissionsField.allEnabledPermissions), - { - next: () => this.router.navigate(['/group/list']), - error: err => { - this.unknownError = true - console.log(err) - } - } + '/group/list' ) } } delete() { - this.subscribe( + this.subscribeAndNavigate( this.groupService.delete(this.group.id), - { - next: () => this.router.navigate(['/group/list']), - error: err => { - this.unknownError = true - console.log(err) - } - } + '/group/list' ) } @@ -86,7 +68,9 @@ export class EditComponent extends SubscribingComponent { } get nameControl(): FormControl { - if (this._nameControl) return this._nameControl + if (this._nameControl) { + return this._nameControl + } if (this.group) { this._nameControl = new FormControl(this.group.name, Validators.compose([Validators.required, Validators.minLength(3)])) return this._nameControl diff --git a/src/app/modules/groups/pages/list/list.component.ts b/src/app/modules/groups/pages/list/list.component.ts index 822c9d0..e6e1565 100644 --- a/src/app/modules/groups/pages/list/list.component.ts +++ b/src/app/modules/groups/pages/list/list.component.ts @@ -1,13 +1,14 @@ -import {Component} from '@angular/core'; -import {Observable} from "rxjs"; -import {GroupService} from "../../services/group.service"; -import {EmployeeGroup, EmployeePermission} from "../../../shared/model/employee"; -import {takeUntil} from "rxjs/operators"; -import {animate, state, style, transition, trigger} from "@angular/animations"; -import {AccountService} from "../../../accounts/services/account.service"; -import {SubscribingComponent} from "../../../shared/components/subscribing.component"; -import {FormBuilder} from "@angular/forms"; -import {ActivatedRoute, Router} from "@angular/router"; +import {Component} from '@angular/core' +import {Observable} from 'rxjs' +import {GroupService} from '../../services/group.service' +import {EmployeeGroup, EmployeePermission} from '../../../shared/model/employee' +import {takeUntil} from 'rxjs/operators' +import {animate, state, style, transition, trigger} from '@angular/animations' +import {AccountService} from '../../../accounts/services/account.service' +import {ErrorHandlingComponent} from '../../../shared/components/subscribing.component' +import {ActivatedRoute, Router} from '@angular/router' +import {ErrorModel, ErrorService} from '../../../shared/service/error.service' +import {AlertService} from '../../../shared/service/alert.service' @Component({ selector: 'cre-groups', @@ -21,40 +22,40 @@ import {ActivatedRoute, Router} from "@angular/router"; ]) ] }) -export class ListComponent extends SubscribingComponent { +export class ListComponent extends ErrorHandlingComponent { groups$: Observable defaultGroup: EmployeeGroup = null columns = ['name', 'permissionCount', 'employeeCount', 'defaultGroup', 'editGroup'] expandedElement: EmployeeGroup | null + handledErrorModels: ErrorModel[] = [{ + filter: error => error.status === 404, + consumer: () => this.alertService.pushWarning('Aucun groupe par défaut n\'a été défini sur cet ordinateur') + }] + constructor( private groupService: GroupService, private accountService: AccountService, + private alertService: AlertService, + errorService: ErrorService, router: Router, activatedRoute: ActivatedRoute ) { - super(activatedRoute, router) + super(errorService, activatedRoute, router) } ngOnInit(): void { this.groups$ = this.groupService.all.pipe(takeUntil(this.destroy$)) this.subscribe( this.groupService.defaultGroup, - { - next: g => this.defaultGroup = g, - error: err => { - if (err.status === 404) { - console.error('No default group is defined on this computer') - } - } - } + group => this.defaultGroup = group, ) } setDefaultGroup(group: EmployeeGroup) { this.subscribe( this.groupService.setDefaultGroup(group), - {next: () => this.defaultGroup = group} + () => this.defaultGroup = group ) } diff --git a/src/app/modules/groups/services/group.service.ts b/src/app/modules/groups/services/group.service.ts index 81b0fc4..7e67017 100644 --- a/src/app/modules/groups/services/group.service.ts +++ b/src/app/modules/groups/services/group.service.ts @@ -16,7 +16,7 @@ export class GroupService { return this.api.get('/employee/group') } - get(id: number): Observable { + getById(id: number): Observable { return this.api.get(`/employee/group/${id}`); } diff --git a/src/app/modules/material-type/pages/add/add.component.html b/src/app/modules/material-type/pages/add/add.component.html index 7e087c8..de4391e 100644 --- a/src/app/modules/material-type/pages/add/add.component.html +++ b/src/app/modules/material-type/pages/add/add.component.html @@ -1,8 +1,6 @@ diff --git a/src/app/modules/material-type/pages/add/add.component.ts b/src/app/modules/material-type/pages/add/add.component.ts index 1e18920..36b19e4 100644 --- a/src/app/modules/material-type/pages/add/add.component.ts +++ b/src/app/modules/material-type/pages/add/add.component.ts @@ -1,16 +1,17 @@ -import {Component} from '@angular/core'; -import {FormField} from "../../../shared/components/entity-add/entity-add.component"; -import {FormBuilder, Validators} from "@angular/forms"; -import {MaterialTypeService} from "../../service/material-type.service"; -import {SubscribingComponent} from "../../../shared/components/subscribing.component"; -import {ActivatedRoute, Router} from "@angular/router"; +import {Component} from '@angular/core' +import {FormField} from '../../../shared/components/entity-add/entity-add.component' +import {Validators} from '@angular/forms' +import {MaterialTypeService} from '../../service/material-type.service' +import {ErrorHandlingComponent} from '../../../shared/components/subscribing.component' +import {ActivatedRoute, Router} from '@angular/router' +import {ErrorModel, ErrorService} from '../../../shared/service/error.service' @Component({ selector: 'cre-add', templateUrl: './add.component.html', styleUrls: ['./add.component.sass'] }) -export class AddComponent extends SubscribingComponent { +export class AddComponent extends ErrorHandlingComponent { formFields: FormField[] = [ { name: 'name', @@ -43,33 +44,30 @@ export class AddComponent extends SubscribingComponent { type: 'checkbox' } ] - unknownError = false - errorMessage: string | null + submittedValues: any | null + + handledErrorModels: ErrorModel[] = [{ + filter: error => error.status === 409 && error.error.id === this.submittedValues.name, + messageProducer: error => `Un type de produit avec le nom '${error.error.id}' existe déjà` + }, { + filter: error => error.status === 409 && error.error.id === this.submittedValues.prefix, + messageProducer: error => `Un type de produit avec le préfixe '${error.error.id}' existe déjà` + }] constructor( private materialTypeService: MaterialTypeService, + errorService: ErrorService, router: Router, activatedRoute: ActivatedRoute ) { - super(activatedRoute, router) + super(errorService, activatedRoute, router) } submit(values) { - this.subscribe( + this.submittedValues = values + this.subscribeAndNavigate( this.materialTypeService.save(values.name, values.prefix, values.usePercentages), - { - next: () => this.router.navigate(['/catalog/materialtype/list']), - error: err => { - if (err.status == 409 && err.error.id === values.name) { - this.errorMessage = `Un type de produit avec le nom '${values.name}' existe déjà` - } else if (err.status == 409 && err.error.id === values.prefix) { - this.errorMessage = `Un type de produit avec le préfixe '${values.prefix}' exists déjà` - } else { - this.unknownError = true - } - console.log(err) - } - } + '/catalog/materialtype/list' ) } } diff --git a/src/app/modules/material-type/pages/edit/edit.component.html b/src/app/modules/material-type/pages/edit/edit.component.html index e54412d..07862c1 100644 --- a/src/app/modules/material-type/pages/edit/edit.component.html +++ b/src/app/modules/material-type/pages/edit/edit.component.html @@ -6,8 +6,6 @@ deletePermission="REMOVE_MATERIAL_TYPE" [entity]="materialType" [formFields]="formFields" - [unknownError]="unknownError" - [customError]="errorMessage" (submit)="submit($event)" (delete)="delete()"> diff --git a/src/app/modules/material-type/pages/edit/edit.component.ts b/src/app/modules/material-type/pages/edit/edit.component.ts index 89ad89e..c110e99 100644 --- a/src/app/modules/material-type/pages/edit/edit.component.ts +++ b/src/app/modules/material-type/pages/edit/edit.component.ts @@ -1,17 +1,18 @@ -import {Component} from '@angular/core'; -import {MaterialType} from "../../../shared/model/materialtype.model"; -import {ActivatedRoute, Router} from "@angular/router"; -import {SubscribingComponent} from "../../../shared/components/subscribing.component"; -import {MaterialTypeService} from "../../service/material-type.service"; -import {FormField} from "../../../shared/components/entity-add/entity-add.component"; -import {FormBuilder, Validators} from "@angular/forms"; +import {Component} from '@angular/core' +import {MaterialType} from '../../../shared/model/materialtype.model' +import {ActivatedRoute, Router} from '@angular/router' +import {ErrorHandlingComponent} from '../../../shared/components/subscribing.component' +import {MaterialTypeService} from '../../service/material-type.service' +import {FormField} from '../../../shared/components/entity-add/entity-add.component' +import {Validators} from '@angular/forms' +import {ErrorModel, ErrorService} from '../../../shared/service/error.service' @Component({ selector: 'cre-edit', templateUrl: './edit.component.html', styleUrls: ['./edit.component.sass'] }) -export class EditComponent extends SubscribingComponent { +export class EditComponent extends ErrorHandlingComponent { materialType: MaterialType | null formFields: FormField[] = [ { @@ -39,66 +40,49 @@ export class EditComponent extends SubscribingComponent { ] } ] - unknownError = false - errorMessage: string | null + submittedValues: any | null + + handledErrorModels: ErrorModel[] = [{ + filter: error => error.status === 409 && error.error.id === this.submittedValues.name, + messageProducer: error => `Un type de produit avec le nom '${error.error.id}' existe déjà` + }, { + filter: error => error.status === 409 && error.error.id === this.submittedValues.prefix, + messageProducer: error => `Un type de produit avec le préfixe '${error.error.id}' existe déjà` + }] constructor( private materialTypeService: MaterialTypeService, + errorService: ErrorService, router: Router, activatedRoute: ActivatedRoute ) { - super(activatedRoute, router) + super(errorService, activatedRoute, router) } ngOnInit() { super.ngOnInit() const id = parseInt(this.activatedRoute.snapshot.paramMap.get('id')) - this.subscribe( - this.materialTypeService.get(id), - { - next: materialType => this.materialType = materialType, - error: err => { - if (err.status === 404) { - this.router.navigate(['/employee/list']) - } else { - this.unknownError = true - } - } - }, - 1 + this.subscribeEntityById( + this.materialTypeService, + id, + materialType => this.materialType = materialType, + '/employee/list' ) } submit(values) { - this.subscribe( + this.submittedValues = values + this.subscribeAndNavigate( this.materialTypeService.update(this.materialType.id, values.name, values.prefix), - { - next: () => this.router.navigate(['/catalog/materialtype/list']), - error: err => { - if (err.status == 409 && err.error.id === values.name) { - this.errorMessage = `Un type de produit avec le nom '${values.name}' existe déjà` - } else if (err.status == 409 && err.error.id === values.prefix) { - this.errorMessage = `Un type de produit avec le préfixe '${values.prefix}' exists déjà` - } else { - this.unknownError = true - } - console.log(err) - } - } + '/catalog/materialtype/list' ) } delete() { - this.subscribe( + this.subscribeAndNavigate( this.materialTypeService.delete(this.materialType.id), - { - next: () => this.router.navigate(['/catalog/materialtype/list']), - error: err => { - this.unknownError = true - console.log(err) - } - } + '/catalog/materialtype/list' ) } } diff --git a/src/app/modules/material-type/pages/list/list.component.ts b/src/app/modules/material-type/pages/list/list.component.ts index a758493..6a9719e 100644 --- a/src/app/modules/material-type/pages/list/list.component.ts +++ b/src/app/modules/material-type/pages/list/list.component.ts @@ -1,16 +1,16 @@ -import {Component} from '@angular/core'; -import {MaterialTypeService} from "../../service/material-type.service"; -import {SubscribingComponent} from "../../../shared/components/subscribing.component"; -import {EmployeePermission} from "../../../shared/model/employee"; -import {FormBuilder} from "@angular/forms"; -import {ActivatedRoute, Router} from "@angular/router"; +import {Component} from '@angular/core' +import {MaterialTypeService} from '../../service/material-type.service' +import {ErrorHandlingComponent} from '../../../shared/components/subscribing.component' +import {EmployeePermission} from '../../../shared/model/employee' +import {ActivatedRoute, Router} from '@angular/router' +import {ErrorService} from '../../../shared/service/error.service' @Component({ selector: 'cre-list', templateUrl: './list.component.html', styleUrls: ['./list.component.sass'] }) -export class ListComponent extends SubscribingComponent { +export class ListComponent extends ErrorHandlingComponent { materialTypes$ = this.materialTypeService.all columns = [ {def: 'name', title: 'Nom', valueFn: t => t.name}, @@ -28,9 +28,10 @@ export class ListComponent extends SubscribingComponent { constructor( private materialTypeService: MaterialTypeService, + errorService: ErrorService, router: Router, activatedRoute: ActivatedRoute ) { - super(activatedRoute, router) + super(errorService, activatedRoute, router) } } diff --git a/src/app/modules/material-type/service/material-type.service.ts b/src/app/modules/material-type/service/material-type.service.ts index fa6119c..1595ada 100644 --- a/src/app/modules/material-type/service/material-type.service.ts +++ b/src/app/modules/material-type/service/material-type.service.ts @@ -16,7 +16,7 @@ export class MaterialTypeService { return this.api.get('/materialtype') } - get(id: number): Observable { + getById(id: number): Observable { return this.api.get(`/materialtype/${id}`) } diff --git a/src/app/modules/material/pages/add/add.component.html b/src/app/modules/material/pages/add/add.component.html index 01034b6..afbcb2f 100644 --- a/src/app/modules/material/pages/add/add.component.html +++ b/src/app/modules/material/pages/add/add.component.html @@ -1,8 +1,6 @@ diff --git a/src/app/modules/material/pages/add/add.component.ts b/src/app/modules/material/pages/add/add.component.ts index b80da7b..a895cb6 100644 --- a/src/app/modules/material/pages/add/add.component.ts +++ b/src/app/modules/material/pages/add/add.component.ts @@ -1,18 +1,19 @@ -import {Component} from '@angular/core'; -import {FormField} from "../../../shared/components/entity-add/entity-add.component"; -import {FormBuilder, Validators} from "@angular/forms"; -import {MaterialService} from "../../service/material.service"; -import {MaterialTypeService} from "../../../material-type/service/material-type.service"; -import {ActivatedRoute, Router} from "@angular/router"; -import {SubscribingComponent} from "../../../shared/components/subscribing.component"; -import {map} from "rxjs/operators"; +import {Component} from '@angular/core' +import {FormField} from '../../../shared/components/entity-add/entity-add.component' +import {Validators} from '@angular/forms' +import {MaterialService} from '../../service/material.service' +import {MaterialTypeService} from '../../../material-type/service/material-type.service' +import {ActivatedRoute, Router} from '@angular/router' +import {ErrorHandlingComponent} from '../../../shared/components/subscribing.component' +import {map} from 'rxjs/operators' +import {ErrorModel, ErrorService} from '../../../shared/service/error.service' @Component({ selector: 'cre-add', templateUrl: './add.component.html', styleUrls: ['./add.component.sass'] }) -export class AddComponent extends SubscribingComponent { +export class AddComponent extends ErrorHandlingComponent { formFields: FormField[] = [ { name: 'name', @@ -57,32 +58,26 @@ export class AddComponent extends SubscribingComponent { fileType: 'application/pdf' } ] - unknownError = false - errorMessage: string | null + + handledErrorModels: ErrorModel[] = [{ + filter: error => error.status === 409, + messageProducer: error => `Un produit avec le nom '${error.error.id}' existe déjà` + }] constructor( private materialService: MaterialService, private materialTypeService: MaterialTypeService, + errorService: ErrorService, router: Router, activatedRoute: ActivatedRoute ) { - super(activatedRoute, router) + super(errorService, activatedRoute, router) } submit(values) { - this.subscribe( + this.subscribeAndNavigate( this.materialService.save(values.name, values.inventoryQuantity, values.materialType, values.simdutFile), - { - next: () => this.router.navigate(['/catalog/material/list']), - error: err => { - if (err.status == 409) { - this.errorMessage = `Un produit avec le nom '${values.name}' existe déjà` - } else { - this.unknownError = true - } - console.log(err) - } - } + '/catalog/material/list' ) } } diff --git a/src/app/modules/material/pages/edit/edit.component.html b/src/app/modules/material/pages/edit/edit.component.html index fae31be..e6d5051 100644 --- a/src/app/modules/material/pages/edit/edit.component.html +++ b/src/app/modules/material/pages/edit/edit.component.html @@ -6,8 +6,6 @@ deletePermission="REMOVE_MATERIAL" [entity]="material" [formFields]="formFields" - [unknownError]="unknownError" - [customError]="errorMessage" (submit)="submit($event)" (delete)="delete()"> @@ -25,11 +23,10 @@ Voir la fiche signalitique + (change)="selectedSimdutFile = $event.target.files[0]">
diff --git a/src/app/modules/material/pages/edit/edit.component.ts b/src/app/modules/material/pages/edit/edit.component.ts index 6a17fc0..0395e5f 100644 --- a/src/app/modules/material/pages/edit/edit.component.ts +++ b/src/app/modules/material/pages/edit/edit.component.ts @@ -1,21 +1,21 @@ -import {Component, ViewChild} from '@angular/core'; -import {FormField} from "../../../shared/components/entity-add/entity-add.component"; -import {Validators} from "@angular/forms"; -import {map} from "rxjs/operators"; -import {MaterialTypeService} from "../../../material-type/service/material-type.service"; -import {MaterialService} from "../../service/material.service"; -import {ActivatedRoute, Router} from "@angular/router"; -import {SubscribingComponent} from "../../../shared/components/subscribing.component"; -import {Material} from "../../../shared/model/material.model"; -import {environment} from "../../../../../environments/environment"; -import {FileButtonComponent} from "../../../shared/file-button/file-button.component"; +import {Component, ViewChild} from '@angular/core' +import {FormField} from '../../../shared/components/entity-add/entity-add.component' +import {Validators} from '@angular/forms' +import {map} from 'rxjs/operators' +import {MaterialTypeService} from '../../../material-type/service/material-type.service' +import {MaterialService} from '../../service/material.service' +import {ActivatedRoute, Router} from '@angular/router' +import {ErrorHandlingComponent} from '../../../shared/components/subscribing.component' +import {Material} from '../../../shared/model/material.model' +import {environment} from '../../../../../environments/environment' +import {ErrorModel, ErrorService} from '../../../shared/service/error.service' @Component({ selector: 'cre-edit', templateUrl: './edit.component.html', styleUrls: ['./edit.component.sass'] }) -export class EditComponent extends SubscribingComponent { +export class EditComponent extends ErrorHandlingComponent { @ViewChild('simdutTemplate', {static: true}) simdutTemplateRef material: Material | null @@ -64,79 +64,59 @@ export class EditComponent extends SubscribingComponent { fileType: 'application/pdf' } ] - unknownError = false - errorMessage: string | null hasSimdut = false selectedSimdutFile: File | null + handledErrorModels: ErrorModel[] = [{ + filter: error => error.status === 409, + messageProducer: error => `Un produit avec le nom '${error.error.id}' existe déjà` + }] + constructor( private materialService: MaterialService, private materialTypeService: MaterialTypeService, + errorService: ErrorService, router: Router, activatedRoute: ActivatedRoute ) { - super(activatedRoute, router) + super(errorService, activatedRoute, router) } ngOnInit() { - super.ngOnInit(); + super.ngOnInit() this.formFields[3].template = this.simdutTemplateRef const id = parseInt(this.activatedRoute.snapshot.paramMap.get('id')) - this.subscribe( - this.materialService.getById(id), - { - next: material => this.material = material, - error: err => { - if (err.status === 404) { - this.router.navigate(['/catalog/material/list']) - } else { - this.unknownError = true - } - } - }, - 1 + this.subscribeEntityById( + this.materialService, + id, + material => this.material = material, + '/catalog/material/list' ) this.subscribe( this.materialService.hasSimdut(id), - {next: b => this.hasSimdut = b} + b => this.hasSimdut = b ) } submit(values) { - this.subscribe( + this.subscribeAndNavigate( this.materialService.update(this.material.id, values.name, values.inventoryQuantity, values.materialType, this.selectedSimdutFile), - { - next: () => this.router.navigate(['/catalog/material/list']), - error: err => { - if (err.status == 409) { - this.errorMessage = `Un produit avec le nom '${values.name}' existe déjà` - } else { - this.unknownError = true - console.error(err) - } - } - } + '/catalog/material/list' ) } delete() { - this.subscribe( + this.subscribeAndNavigate( this.materialService.delete(this.material.id), - { - next: () => this.router.navigate(['/catalog/material/list']), - error: err => { - this.unknownError = true - console.error(err) - } - } + '/catalog/material/list' ) } openSimdutUrl() { const simdutUrl = environment.apiUrl + `/material/${this.material.id}/simdut` - window.open(simdutUrl, "_blank") + window.open(simdutUrl, '_blank') } } diff --git a/src/app/modules/material/pages/list/list.component.ts b/src/app/modules/material/pages/list/list.component.ts index 5fc6e62..7092ac6 100644 --- a/src/app/modules/material/pages/list/list.component.ts +++ b/src/app/modules/material/pages/list/list.component.ts @@ -1,17 +1,17 @@ -import {Component} from '@angular/core'; -import {SubscribingComponent} from "../../../shared/components/subscribing.component"; -import {MaterialService} from "../../service/material.service"; -import {EmployeePermission} from "../../../shared/model/employee"; -import {environment} from "../../../../../environments/environment"; -import {FormBuilder} from "@angular/forms"; -import {ActivatedRoute, Router} from "@angular/router"; +import {Component} from '@angular/core' +import {ErrorHandlingComponent} from '../../../shared/components/subscribing.component' +import {MaterialService} from '../../service/material.service' +import {EmployeePermission} from '../../../shared/model/employee' +import {environment} from '../../../../../environments/environment' +import {ActivatedRoute, Router} from '@angular/router' +import {ErrorService} from '../../../shared/service/error.service' @Component({ selector: 'cre-list', templateUrl: './list.component.html', styleUrls: ['./list.component.sass'] }) -export class ListComponent extends SubscribingComponent { +export class ListComponent extends ErrorHandlingComponent { materials$ = this.materialService.allNotMixType columns = [ {def: 'name', title: 'Code', valueFn: t => t.name}, @@ -42,26 +42,25 @@ export class ListComponent extends SubscribingComponent { constructor( private materialService: MaterialService, + errorService: ErrorService, router: Router, activatedRoute: ActivatedRoute ) { - super(activatedRoute, router) + super(errorService, activatedRoute, router) } ngOnInit() { - super.ngOnInit(); + super.ngOnInit() this.subscribe( this.materials$, - { - next: mArray => { - mArray.forEach(m => { - this.subscribe( - this.materialService.hasSimdut(m.id), - { next: b => this.hasSimdutMap[m.id] = b } - ) - }) - } + mArray => { + mArray.forEach(m => { + this.subscribe( + this.materialService.hasSimdut(m.id), + b => this.hasSimdutMap[m.id] = b + ) + }) }, 1 ) diff --git a/src/app/modules/shared/components/entity-add/entity-add.component.html b/src/app/modules/shared/components/entity-add/entity-add.component.html index 86ffa13..9e0876e 100644 --- a/src/app/modules/shared/components/entity-add/entity-add.component.html +++ b/src/app/modules/shared/components/entity-add/entity-add.component.html @@ -3,11 +3,6 @@ {{title}} -
-

Une erreur est survenue

-

{{customError}}

-
- () form: FormGroup | null constructor( - private formBuilder: FormBuilder, - router: Router, - activatedRoute: ActivatedRoute + private formBuilder: FormBuilder ) { - super(activatedRoute, router) } ngOnInit() { @@ -33,8 +26,6 @@ export class EntityAddComponent extends SubscribingComponent { formGroup[f.name] = new FormControl(null, f.validator) }) this.form = this.formBuilder.group(formGroup) - - super.ngOnInit(); } submitForm() { diff --git a/src/app/modules/shared/components/entity-edit/entity-edit.component.html b/src/app/modules/shared/components/entity-edit/entity-edit.component.html index f4a31d3..a02ea93 100644 --- a/src/app/modules/shared/components/entity-edit/entity-edit.component.html +++ b/src/app/modules/shared/components/entity-edit/entity-edit.component.html @@ -3,11 +3,6 @@ {{title}} -
-

Une erreur est survenue

-

{{customError}}

-
- () @@ -29,21 +25,19 @@ export class EntityEditComponent extends SubscribingComponent { constructor( private accountService: AccountService, - private formBuilder: FormBuilder, - router: Router, - activatedRoute: ActivatedRoute + private formBuilder: FormBuilder ) { - super(activatedRoute, router) } ngOnInit() { const formGroup = {} this.formFields.forEach(f => { - formGroup[f.name] = new FormControl({value: f.valueFn ? f.valueFn(this.entity) : this.entity[f.name], disabled: f.readonly}, f.validator) + formGroup[f.name] = new FormControl({ + value: f.valueFn ? f.valueFn(this.entity) : this.entity[f.name], + disabled: f.readonly + }, f.validator) }) this.form = this.formBuilder.group(formGroup) - - super.ngOnInit(); } submitForm() { diff --git a/src/app/modules/shared/components/entity-list/entity-list.component.ts b/src/app/modules/shared/components/entity-list/entity-list.component.ts index 93eb95a..752a1cb 100644 --- a/src/app/modules/shared/components/entity-list/entity-list.component.ts +++ b/src/app/modules/shared/components/entity-list/entity-list.component.ts @@ -1,17 +1,14 @@ -import {Component, Input} from '@angular/core'; -import {Observable} from "rxjs"; -import {SubscribingComponent} from "../subscribing.component"; -import {AccountService} from "../../../accounts/services/account.service"; -import {EmployeePermission} from "../../model/employee"; -import {FormBuilder} from "@angular/forms"; -import {ActivatedRoute, Router} from "@angular/router"; +import {Component, Input} from '@angular/core' +import {Observable} from 'rxjs' +import {AccountService} from '../../../accounts/services/account.service' +import {EmployeePermission} from '../../model/employee' @Component({ selector: 'cre-entity-list', templateUrl: './entity-list.component.html', styleUrls: ['./entity-list.component.sass'] }) -export class EntityListComponent extends SubscribingComponent { +export class EntityListComponent { @Input() entities$: Observable @Input() columns: TableColumn[] @Input() icons: TableIcon[] @@ -20,11 +17,8 @@ export class EntityListComponent extends SubscribingComponent { @Input() addPermission: EmployeePermission constructor( - private accountService: AccountService, - router: Router, - activatedRoute: ActivatedRoute + private accountService: AccountService ) { - super(activatedRoute, router) } hasPermissionToUseButton(button: TableButton): boolean { @@ -50,7 +44,9 @@ export class EntityListComponent extends SubscribingComponent { } } - if (externalLink) window.open(externalLink, "_blank") + if (externalLink) { + window.open(externalLink, '_blank') + } } get tableCols(): string[] { diff --git a/src/app/modules/shared/components/global-alert-handler/global-alert-handler.component.html b/src/app/modules/shared/components/global-alert-handler/global-alert-handler.component.html index b4acaa2..3c63ac7 100644 --- a/src/app/modules/shared/components/global-alert-handler/global-alert-handler.component.html +++ b/src/app/modules/shared/components/global-alert-handler/global-alert-handler.component.html @@ -1,4 +1,4 @@ -
+
{ - if (data instanceof ResolveEnd) this._activeLink = data.url + data => { + if (data instanceof ResolveEnd) { + this._activeLink = data.url } }, 1 ) // Auth status - this.accountService.checkAuthenticationStatus() this.updateEnabledLinks(this.appState.isAuthenticated, this.appState.authenticatedEmployee) this.subscribe( this.appState.authenticatedUser$, - {next: authentication => this.updateEnabledLinks(authentication.authenticated, authentication.authenticatedUser)} + authentication => this.updateEnabledLinks(authentication.authenticated, authentication.authenticatedUser) ) - - super.ngOnInit() } ngOnDestroy(): void { this.accountService.logout(() => { - console.log("Successfully logged out") + console.log('Successfully logged out') }) super.ngOnDestroy() @@ -77,7 +78,7 @@ export class HeaderComponent extends SubscribingComponent { this.links.forEach(l => { if (l.requiredPermission) { - l.enabled = employee && employee.permissions.indexOf(l.requiredPermission) >= 0; + l.enabled = employee && employee.permissions.indexOf(l.requiredPermission) >= 0 } }) } diff --git a/src/app/modules/shared/components/subscribing.component.ts b/src/app/modules/shared/components/subscribing.component.ts index 16d9a99..d19ce1b 100644 --- a/src/app/modules/shared/components/subscribing.component.ts +++ b/src/app/modules/shared/components/subscribing.component.ts @@ -1,60 +1,50 @@ -import {take, takeUntil} from "rxjs/operators"; -import {OnDestroy, OnInit} from "@angular/core"; -import {Observable, Subject} from "rxjs"; -import {ActivatedRoute, Router} from "@angular/router"; -import {UrlUtils} from "../utils/url.utils"; +import {take, takeUntil} from 'rxjs/operators' +import {OnDestroy, OnInit} from '@angular/core' +import {Observable, Subject} from 'rxjs' +import {ActivatedRoute, Router} from '@angular/router' +import {UrlUtils} from '../utils/url.utils' +import {ErrorHandler, ErrorModel, ErrorService} from '../service/error.service' export abstract class SubscribingComponent implements OnInit, OnDestroy { protected subscribers$ = [] protected destroy$ = new Subject() - unknownError = false protected constructor( + protected errorService: ErrorService, protected activatedRoute: ActivatedRoute, protected router: Router, protected urlUtils = new UrlUtils(activatedRoute, router) ) { } - subscribe(observable: Observable, observer, take_count = -1) { - if (!observer.error) { - observer.error = err => this.handleObserverError(err) - } - + subscribe(observable: Observable, resultConsumer: (T) => void, take_count = -1) { if (take_count >= 0) { observable.pipe(take(take_count), takeUntil(this.destroy$)) } else { observable.pipe(takeUntil(this.destroy$)) } - this.subscribers$.push(observable.subscribe(observer)) + + this.subscribers$.push(observable.subscribe({ + next: resultConsumer, + error: err => this.errorService.handleError(err) + })) } subscribeAndNavigate(observable: Observable, route: string) { this.subscribe( observable, - { - next: () => this.urlUtils.navigateTo(route) - }, + () => this.urlUtils.navigateTo(route), 1 ) } - subscribeEntityByIdFromRoute(service: any, entitySubject: Subject, notFoundRoute: string, paramName: string = 'id') { - const id = this.urlUtils.parseIntUrlParam(paramName) - this.subscribe( - service.getById(id), - { - next: e => entitySubject.next(e), - error: err => { - if (err.status === 404) { - this.urlUtils.navigateTo(notFoundRoute) - } else { - this.handleObserverError(err) - } - } - }, - 1 - ) + subscribeEntityById(service: any, id: number, resultConsumer: (T) => void, notFoundRoute: string) { + this.subscribers$.push(service.getById(id) + .pipe(take(1), takeUntil(this.destroy$)) + .subscribe({ + next: e => resultConsumer(e), + error: err => this.handleNotFoundError(err, notFoundRoute) + })) } ngOnInit(): void { @@ -65,16 +55,24 @@ export abstract class SubscribingComponent implements OnInit, OnDestroy { this.destroy$.complete() } - handleObserverError(error: any) { - console.error(error) - this.unknownError = true - } - handleNotFoundError(error: any, route: string) { if (error.status === 404) { this.urlUtils.navigateTo(route) } else { - this.handleObserverError(error) + this.errorService.handleError(error) } } } + +export abstract class ErrorHandlingComponent extends SubscribingComponent implements ErrorHandler { + handledErrorModels: ErrorModel[] = [] + + protected constructor( + errorService: ErrorService, + activatedRoute: ActivatedRoute, + router: Router + ) { + super(errorService, activatedRoute, router) + this.errorService.activeErrorHandler = this + } +} diff --git a/src/app/modules/shared/service/alert.service.ts b/src/app/modules/shared/service/alert.service.ts index b8e2922..a0ae090 100644 --- a/src/app/modules/shared/service/alert.service.ts +++ b/src/app/modules/shared/service/alert.service.ts @@ -1,5 +1,6 @@ -import {Injectable} from '@angular/core' -import {interval} from 'rxjs' +import {Injectable, OnDestroy} from '@angular/core' +import {interval, Subject} from 'rxjs' +import {takeUntil} from 'rxjs/operators' @Injectable({ providedIn: 'root' @@ -8,10 +9,6 @@ export class AlertService { private alertQueue: Alert[] = [] private activeHandler: AlertHandlerComponent - constructor() { - // interval(500).subscribe({next: i => this.pushError('Test error ' + i)}) - } - pushSuccess(message: String) { this.enqueue(AlertType.Success, message) } @@ -29,20 +26,10 @@ export class AlertService { } private enqueue(type: AlertType, message: String) { - const alert = {type, message} - if (this.activeHandler && !this.activeHandler.isBufferFull) { - if (this.alertQueue.length == 0) { - this.activeHandler.pushAlert(alert) - } else { - this.activeHandler.pushAlert(this.dequeue()) - this.alertQueue.unshift(alert) - } - } else { - this.alertQueue.unshift(alert) - } + this.alertQueue.unshift({type, message}) } - private dequeue(): Alert { + dequeue(): Alert { return this.alertQueue.pop() } } @@ -50,7 +37,7 @@ export class AlertService { /** * An alert handler component is a component that will show the alerts pushed by the alert system to the user. */ -export abstract class AlertHandlerComponent { +export abstract class AlertHandlerComponent implements OnDestroy { protected static readonly DEFAULT_ALERT_BUFFER_SIZE = 3 protected static readonly DEFAULT_ALERT_DURATION = 5 @@ -59,26 +46,45 @@ export abstract class AlertHandlerComponent { protected alertDuration: number = AlertHandlerComponent.DEFAULT_ALERT_DURATION protected alertDurationCounter = 0 + private destroy$ = new Subject() + protected constructor( protected alertService: AlertService ) { alertService.activeAlertHandlerComponent = this - interval(1000).subscribe({ - next: () => { - this.alertDurationCounter++ - if (this.alertBuffer.length > 1) { - this.alertBuffer - .filter(a => a.time + this.alertDuration < this.alertDurationCounter) - .map(a => this.alertBuffer.indexOf(a)) - .forEach(i => this.alertBuffer.splice(i, 1)) + interval(1000) + .pipe(takeUntil(this.destroy$)) + .subscribe({ + next: () => { + this.alertDurationCounter++ + if (!this.isBufferEmpty) { + this.alertBuffer + .filter(a => a.time + this.alertDuration < this.alertDurationCounter) + .map(a => this.alertBuffer.indexOf(a)) + .forEach(i => this.alertBuffer.splice(i, 1)) + } + if (!this.isBufferFull) { + this.pullAlert() + } } - } - }) + }) } - pushAlert(alert: Alert) { - this.alertBuffer.unshift({alert: alert, time: this.alertDurationCounter}) + ngOnDestroy(): void { + this.destroy$.next(true) + this.destroy$.complete() + } + + pullAlert() { + const nextAlert = this.alertService.dequeue() + if (nextAlert) { + this.alertBuffer.unshift({alert: nextAlert, time: this.alertDurationCounter}) + } + } + + get isBufferEmpty(): boolean { + return this.alertBuffer.length == 0 } get isBufferFull(): boolean { diff --git a/src/app/modules/shared/service/error.service.ts b/src/app/modules/shared/service/error.service.ts index 45c61e7..8c16715 100644 --- a/src/app/modules/shared/service/error.service.ts +++ b/src/app/modules/shared/service/error.service.ts @@ -23,6 +23,9 @@ export class ErrorService { }, { filter: error => error.status === 404, messageProducer: () => 'La resource demandée n\'a pas été trouvée' + }, { + filter: error => error.status === 409, + messageProducer: () => 'Un conflit avec une autre resource s\'est produit' }, { filter: error => error.status === 500, messageProducer: () => ErrorService.UNKNOWN_ERROR_MESSAGE @@ -37,11 +40,13 @@ export class ErrorService { } handleError(error: any) { - if (!this.activeHandler) { - console.error('An error occurred but no handler was set') - } + let matchingModels - let matchingModels = this.activeHandler.handledErrorModels.filter(m => m.filter(error)) // Find error models whose filter matches the current error + if (this.activeHandler) { + matchingModels = this.activeHandler.handledErrorModels.filter(m => m.filter(error)) // Find error models whose filter matches the current error + } else { + console.warn('An error occurred but no handler was set') + } if (!matchingModels || matchingModels.length == 0) { // If none are found, search in defaults handlers matchingModels = this.defaultHandledErrorModels.filter(m => m.filter(error)) @@ -68,6 +73,10 @@ export class ErrorService { consumeUnknownError(error: any) { console.error(error) + this.pushUnknownError() + } + + pushUnknownError() { this.alertService.pushError(ErrorService.UNKNOWN_ERROR_MESSAGE) } @@ -79,14 +88,8 @@ export class ErrorService { /** * An error handler, defining models of errors that this type will handle */ -export abstract class ErrorHandler { - abstract handledErrorModels: ErrorModel[] - - protected constructor( - protected errorService: ErrorService - ) { - this.errorService.activeErrorHandler = this - } +export interface ErrorHandler { + handledErrorModels: ErrorModel[] } /** diff --git a/src/app/pages/catalog/catalog.component.ts b/src/app/pages/catalog/catalog.component.ts index 5b125c2..60ca21b 100644 --- a/src/app/pages/catalog/catalog.component.ts +++ b/src/app/pages/catalog/catalog.component.ts @@ -16,10 +16,10 @@ export class CatalogComponent implements OnInit, OnDestroy { ] ngOnInit(): void { - GlobalAlertHandlerComponent.isSubNavOpen = true + GlobalAlertHandlerComponent.extraTopMarginMultiplier = 1 } ngOnDestroy(): void { - GlobalAlertHandlerComponent.isSubNavOpen = false + GlobalAlertHandlerComponent.extraTopMarginMultiplier = 0 } } From 98e5d7f36c19bd3c35f8489ba34a1b11dbfffdc1 Mon Sep 17 00:00:00 2001 From: FyloZ Date: Wed, 17 Feb 2021 00:13:34 -0500 Subject: [PATCH 6/6] =?UTF-8?q?Utilisation=20du=20syst=C3=A8me=20centralis?= =?UTF-8?q?=C3=A9=20d'erreur=20dans=20toute=20l'application?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../accounts/services/account.service.ts | 36 +++++-------------- src/app/modules/shared/service/api.service.ts | 11 ++---- 2 files changed, 10 insertions(+), 37 deletions(-) diff --git a/src/app/modules/accounts/services/account.service.ts b/src/app/modules/accounts/services/account.service.ts index c59dd0d..572d2ce 100644 --- a/src/app/modules/accounts/services/account.service.ts +++ b/src/app/modules/accounts/services/account.service.ts @@ -6,6 +6,7 @@ import {HttpClient, HttpResponse} from '@angular/common/http' import {environment} from '../../../../environments/environment' import {ApiService} from '../../shared/service/api.service' import {Employee, EmployeePermission} from '../../shared/model/employee' +import {ErrorService} from '../../shared/service/error.service' @Injectable({ providedIn: 'root' @@ -16,7 +17,8 @@ export class AccountService implements OnDestroy { constructor( private http: HttpClient, private api: ApiService, - private appState: AppState + private appState: AppState, + private errorService: ErrorService ) { } @@ -38,24 +40,12 @@ export class AccountService implements OnDestroy { takeUntil(this.destroy$), ).subscribe({ next: employee => this.appState.authenticatedEmployee = employee, - error: err => { - if (err.status === 0 && err.statusText === 'Unknown Error' || err.status === 502) { - this.appState.isServerOnline = false - } else { - this.appState.isServerOnline = true - if (err.status === 404 || err.status === 403) { - console.error('No default user is defined on this computer') - } else { - console.error('An error occurred while authenticating the default user') - console.error(err) - } - } - } + error: err => this.errorService.handleError(err) }) } } - login(id: number, password: string, success: () => void, error: (err) => void) { + login(id: number, password: string, success: () => void) { const loginForm = {id, password} this.http.post(`${environment.apiUrl}/login`, loginForm, { withCredentials: true, @@ -72,14 +62,7 @@ export class AccountService implements OnDestroy { this.setLoggedInEmployeeFromApi() success() }, - error: err => { - if (err.status === 0 && err.statusText === 'Unknown Error' || err.status === 502) { - this.appState.isServerOnline = false - } else { - this.appState.isServerOnline = true - error(err) - } - } + error: err => this.errorService.handleError(err) }) } @@ -96,7 +79,7 @@ export class AccountService implements OnDestroy { this.checkAuthenticationStatus() success() }, - error: err => console.error(err) + error: err => this.errorService.handleError(err) }) } @@ -112,10 +95,7 @@ export class AccountService implements OnDestroy { ) .subscribe({ next: employee => this.appState.authenticatedEmployee = employee, - error: err => { - console.error('Could not get the logged in employee from the API: ') - console.error(err) - } + error: err => this.errorService.handleError(err) }) } } diff --git a/src/app/modules/shared/service/api.service.ts b/src/app/modules/shared/service/api.service.ts index 0ae027c..de167a2 100644 --- a/src/app/modules/shared/service/api.service.ts +++ b/src/app/modules/shared/service/api.service.ts @@ -6,6 +6,7 @@ import {AppState} from '../app-state' import {Router} from '@angular/router' import {map, share, takeUntil} from 'rxjs/operators' import {valueOr} from '../utils/optional.utils' +import {ErrorService} from './error.service' @Injectable({ providedIn: 'root' @@ -14,6 +15,7 @@ export class ApiService implements OnDestroy { private _destroy$ = new Subject() constructor( + private errorService: ErrorService, private http: HttpClient, private appState: AppState, private router: Router @@ -85,15 +87,6 @@ export class ApiService implements OnDestroy { : requestFn(httpOptions) .pipe(takeUntil(this._destroy$), map(r => r.body), share()) - const errorCheckSubscription = result$.subscribe({ - next: () => this.appState.isServerOnline = true, - error: err => { - console.error(err) - errorCheckSubscription.unsubscribe() - this.appState.isServerOnline = !(err.status === 0 && err.statusText === 'Unknown Error' || err.status === 502) - } - }) - return result$ }