Added error handling for edit employee

This commit is contained in:
Erik Tiekstra
2021-09-07 14:44:14 +02:00
parent bb4d88a8e0
commit 39a0090881
6 changed files with 91 additions and 64 deletions

View File

@@ -99,7 +99,19 @@
</digi-form-validation-message> </digi-form-validation-message>
</fieldset> </fieldset>
<div class="edit-employee-form__footer"> <digi-notification-alert
*ngIf="errorWhileUpdating"
af-variation="danger"
af-heading="Kunde inte spara"
af-heading-level="h2"
[afCloseable]="true"
(afOnClose)="emitCloseError()"
>
<p>Personalkontot för {{employee.fullName}} kunde inte redigeras. Vänligen försök igen.</p>
<p class="msfa__small-text" *ngIf="errorWhileUpdating.message">{{errorWhileUpdating.message}}</p>
</digi-notification-alert>
<footer class="edit-employee-form__footer">
<a <a
class="edit-employee-form__link-btn edit-employee-form__link-btn--secondary" class="edit-employee-form__link-btn edit-employee-form__link-btn--secondary"
[routerLink]="['/administration/personal', employee.id]" [routerLink]="['/administration/personal', employee.id]"
@@ -107,7 +119,7 @@
Avbryt Avbryt
</a> </a>
<digi-button af-type="submit">Spara ändringar</digi-button> <digi-button af-type="submit">Spara ändringar</digi-button>
</div> </footer>
</form> </form>
</digi-typography> </digi-typography>

View File

@@ -8,8 +8,8 @@ import { HttpClientTestingModule } from '@angular/common/http/testing';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ReactiveFormsModule } from '@angular/forms'; import { ReactiveFormsModule } from '@angular/forms';
import { RouterTestingModule } from '@angular/router/testing';
import { TreeNodesSelectorModule } from '@msfa-shared/components/tree-nodes-selector/tree-nodes-selector.module'; import { TreeNodesSelectorModule } from '@msfa-shared/components/tree-nodes-selector/tree-nodes-selector.module';
import { EditEmployeeFormComponent } from './edit-employee-form.component'; import { EditEmployeeFormComponent } from './edit-employee-form.component';
describe('EditEmployeeFormComponent', () => { describe('EditEmployeeFormComponent', () => {
@@ -29,6 +29,7 @@ describe('EditEmployeeFormComponent', () => {
DigiNgFormCheckboxModule, DigiNgFormCheckboxModule,
HttpClientTestingModule, HttpClientTestingModule,
TreeNodesSelectorModule, TreeNodesSelectorModule,
RouterTestingModule,
], ],
schemas: [CUSTOM_ELEMENTS_SCHEMA], schemas: [CUSTOM_ELEMENTS_SCHEMA],
}).compileComponents(); }).compileComponents();
@@ -37,6 +38,22 @@ describe('EditEmployeeFormComponent', () => {
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(EditEmployeeFormComponent); fixture = TestBed.createComponent(EditEmployeeFormComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
component.employee = {
id: 'string',
firstName: 'string',
lastName: 'string',
fullName: 'string',
email: 'string',
ssn: 'string',
roles: [],
tjanster: [],
allaUtforandeVerksamheter: false,
utforandeVerksamheter: [],
tjanstCodes: [],
utforandeVerksamhetIds: [],
utforandeAdressIds: [],
};
fixture.detectChanges(); fixture.detectChanges();
}); });

View File

@@ -13,6 +13,7 @@ import {
import { AbstractControl, FormControl, FormGroup } from '@angular/forms'; import { AbstractControl, FormControl, FormGroup } from '@angular/forms';
import { EmployeeEditRequest } from '@msfa-models/api/employee-edit.request.model'; import { EmployeeEditRequest } from '@msfa-models/api/employee-edit.request.model';
import { Employee } from '@msfa-models/employee.model'; import { Employee } from '@msfa-models/employee.model';
import { CustomError } from '@msfa-models/error/custom-error';
import { Role } from '@msfa-models/role.model'; import { Role } from '@msfa-models/role.model';
import { Tjanst } from '@msfa-models/tjanst.model'; import { Tjanst } from '@msfa-models/tjanst.model';
import { import {
@@ -46,8 +47,10 @@ export class EditEmployeeFormComponent implements OnInit, OnChanges {
@Input() availableRoles: Role[]; @Input() availableRoles: Role[];
@Input() availableTjanster: Tjanst[]; @Input() availableTjanster: Tjanst[];
@Input() availableUtforandeVerksamheter: UtforandeVerksamhet[]; @Input() availableUtforandeVerksamheter: UtforandeVerksamhet[];
@Input() errorWhileUpdating: CustomError;
@Output() tjansterSelected = new EventEmitter<Tjanst[]>(); @Output() tjansterSelected = new EventEmitter<Tjanst[]>();
@Output() closeError = new EventEmitter<void>();
@Output() formSubmitted = new EventEmitter<EmployeeEditRequest>(); @Output() formSubmitted = new EventEmitter<EmployeeEditRequest>();
readonly ButtonVariation = ButtonVariation; readonly ButtonVariation = ButtonVariation;
@@ -226,4 +229,8 @@ export class EditEmployeeFormComponent implements OnInit, OnChanges {
Object.fromEntries([[this.toggleAllUtforandeVerksamhetFormControlName, hasSelectedAllLeafNodes]]) Object.fromEntries([[this.toggleAllUtforandeVerksamhetFormControlName, hasSelectedAllLeafNodes]])
); );
} }
emitCloseError(): void {
this.closeError.emit();
}
} }

View File

@@ -1,6 +1,6 @@
<msfa-layout> <msfa-layout>
<section class="employee-form" *ngIf="employee$ | async as employee"> <digi-typography>
<digi-typography> <section class="employee-form" *ngIf="employee$ | async as employee">
<header class="employee-form__header"> <header class="employee-form__header">
<h1>Redigera personalkonto</h1> <h1>Redigera personalkonto</h1>
<msfa-employee-delete [returnToEmployeeList]="true"></msfa-employee-delete> <msfa-employee-delete [returnToEmployeeList]="true"></msfa-employee-delete>
@@ -13,39 +13,44 @@
Ta bort konto Ta bort konto
</digi-button> --> </digi-button> -->
</header> </header>
</digi-typography>
<div class="employee-form__block"> <div class="employee-form__block">
<digi-typography>
<h2>Personuppgifter</h2> <h2>Personuppgifter</h2>
</digi-typography> <dl>
<dt>Förnamn</dt>
<ng-container class="employee-form__privateInformation"> <dd>{{employee.firstName}}</dd>
<digi-typography> </dl>
<h4>Förnamn</h4> <dl>
<p>{{employee.firstName}}</p> <dt>Förnamn</dt>
</digi-typography> <dd>{{employee.firstName}}</dd>
<digi-typography> </dl>
<h4>Efternamn</h4> <dl>
<p>{{employee.lastName}}</p> <dt>Efternamn</dt>
</digi-typography> <dd>{{employee.lastName}}</dd>
<digi-typography> </dl>
<h4>Personnummer</h4> <dl>
<msfa-hide-text <dt>Personnummer</dt>
symbols="********-****" <dd>
[changingText]="employee.ssn" <msfa-hide-text
ariaLabelType="personnummer" symbols="********-****"
></msfa-hide-text> [changingText]="employee.ssn"
</digi-typography> ariaLabelType="personnummer"
</ng-container> ></msfa-hide-text>
</div> </dd>
<msfa-edit-employee-form </dl>
[employee]="employee" </div>
[availableRoles]="availableRoles" <div class="employee-form__block">
[availableTjanster]="tjanster$ | async" <msfa-edit-employee-form
[availableUtforandeVerksamheter]="availableUtforandeVerksamheter$ | async" [employee]="employee"
(tjansterSelected)="setupAvailableUtforandeVerksamheter($event)" [availableRoles]="availableRoles"
(formSubmitted)="updateEmployee($event)" [availableTjanster]="tjanster$ | async"
></msfa-edit-employee-form> [availableUtforandeVerksamheter]="availableUtforandeVerksamheter$ | async"
</section> [errorWhileUpdating]="errorWhileUpdating$ | async"
(tjansterSelected)="setupAvailableUtforandeVerksamheter($event)"
(formSubmitted)="updateEmployee($event)"
(closeError)="closeError()"
></msfa-edit-employee-form>
</div>
</section>
</digi-typography>
</msfa-layout> </msfa-layout>

View File

@@ -2,6 +2,7 @@ import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
import { EmployeeEditRequest } from '@msfa-models/api/employee-edit.request.model'; import { EmployeeEditRequest } from '@msfa-models/api/employee-edit.request.model';
import { Employee } from '@msfa-models/employee.model'; import { Employee } from '@msfa-models/employee.model';
import { CustomError } from '@msfa-models/error/custom-error';
import { Role } from '@msfa-models/role.model'; import { Role } from '@msfa-models/role.model';
import { Tjanst } from '@msfa-models/tjanst.model'; import { Tjanst } from '@msfa-models/tjanst.model';
import { EmployeeService } from '@msfa-services/api/employee.service'; import { EmployeeService } from '@msfa-services/api/employee.service';
@@ -22,6 +23,8 @@ import { filter, switchMap } from 'rxjs/operators';
export class EmployeeFormComponent implements OnInit { export class EmployeeFormComponent implements OnInit {
private _employeeId$ = new BehaviorSubject<string>(this.activatedRoute.snapshot.params['employeeId']); private _employeeId$ = new BehaviorSubject<string>(this.activatedRoute.snapshot.params['employeeId']);
private _selectedTjanstIds$ = new BehaviorSubject<number[]>(null); private _selectedTjanstIds$ = new BehaviorSubject<number[]>(null);
private _errorWhileUpdating$ = new BehaviorSubject<CustomError>(null);
errorWhileUpdating$: Observable<CustomError> = this._errorWhileUpdating$.asObservable();
employee$ = this.employeeService.employee$; employee$ = this.employeeService.employee$;
tjanster$: Observable<Tjanst[]> = this.tjanstService.tjanster$; tjanster$: Observable<Tjanst[]> = this.tjanstService.tjanster$;
availableUtforandeVerksamheter$: Observable<UtforandeVerksamhet[]> = this._selectedTjanstIds$.pipe( availableUtforandeVerksamheter$: Observable<UtforandeVerksamhet[]> = this._selectedTjanstIds$.pipe(
@@ -54,6 +57,9 @@ export class EmployeeFormComponent implements OnInit {
next: () => { next: () => {
void this.router.navigateByUrl(`/administration/personal/${this.employeeId}`); void this.router.navigateByUrl(`/administration/personal/${this.employeeId}`);
}, },
error: error => {
this._errorWhileUpdating$.next(error);
},
complete: () => { complete: () => {
updateEmployeeSubscription.unsubscribe(); updateEmployeeSubscription.unsubscribe();
}, },
@@ -66,4 +72,8 @@ export class EmployeeFormComponent implements OnInit {
setEmployeeToDelete(employee: Employee): void { setEmployeeToDelete(employee: Employee): void {
this.employeeService.setEmployeeToDelete(employee); this.employeeService.setEmployeeToDelete(employee);
} }
closeError(): void {
this._errorWhileUpdating$.next(null);
}
} }

View File

@@ -82,29 +82,6 @@ export class EmployeeService extends UnsubscribeDirective {
.subscribe(employee => { .subscribe(employee => {
this._employee$.next(employee as Employee); this._employee$.next(employee as Employee);
}) })
// this._currentEmployeeId$
// .pipe(
// filter(currentEmployeeId => !!currentEmployeeId),
// switchMap(currentEmployeeId =>
// combineLatest([this._fetchEmployee$(currentEmployeeId), this.tjanstService.tjanster$]).pipe(
// filter(([employee, allTjanster]) => !!(employee && allTjanster?.length)),
// map(([employee, allTjanster]) => {
// const tjanster = [];
// employee.tjanstCodes?.forEach(code => {
// const currentTjanst = allTjanster.find(tjanst => tjanst.code === code);
// if (currentTjanst) {
// tjanster.push(currentTjanst);
// }
// });
// return { ...employee, tjanster };
// })
// )
// )
// )
// .subscribe(employee => {
// this._employee$.next(employee as Employee);
// })
); );
} }
@@ -215,7 +192,7 @@ export class EmployeeService extends UnsubscribeDirective {
map(({ data }) => data), map(({ data }) => data),
catchError(error => { catchError(error => {
this.errorService.add(errorToCustomError(error)); this.errorService.add(errorToCustomError(error));
return of(null); return throwError(errorToCustomError(error));
}) })
); );
} }
@@ -229,8 +206,7 @@ export class EmployeeService extends UnsubscribeDirective {
}), }),
map(() => true), map(() => true),
catchError(error => { catchError(error => {
this.errorService.add(errorToCustomError(error)); return throwError(errorToCustomError(error));
return of(false);
}) })
); );
} }