From b4b71efe2cd0eb85bbc770b8140cc924c5af3bf8 Mon Sep 17 00:00:00 2001
From: Erik Tiekstra
Date: Thu, 12 Aug 2021 15:28:33 +0200
Subject: [PATCH] feat(deltagare): Added avrop-information to deltagare card.
(TV-324)
Squashed commit of the following:
commit 7ed848709ff02565de4d7377e75dee804b2752ff
Merge: 1dd9593 35213d6
Author: Erik Tiekstra
Date: Thu Aug 12 13:24:28 2021 +0200
Merged develop and resolved conflict
commit 1dd959342bd93110339db56035552c9560451b09
Author: Erik Tiekstra
Date: Thu Aug 12 08:39:52 2021 +0200
Refactored custom error mapping
commit a456ddc6a3df6851b9bb894c6bf1af9884cc4870
Author: Erik Tiekstra
Date: Wed Aug 11 15:52:04 2021 +0200
Updates regarding fetching deltagare
commit c320848ada6082ae06e8789d7b2569b269032a10
Author: Erik Tiekstra
Date: Wed Aug 11 07:00:30 2021 +0200
Added some error-handling for deltagare service
commit b5591427114f080083026babd9c60ae7e8eec4a3
Author: Erik Tiekstra
Date: Tue Aug 10 11:30:40 2021 +0200
Added mock-data and request inside service. Also changed view with updated properties
---
.../pages/deltagare/deltagare.component.html | 7 +-
.../deltagare-card.component.html | 36 +++--
.../deltagare-card.component.ts | 13 +-
.../models/api/deltagare.response.model.ts | 2 +
.../src/app/shared/models/deltagare.model.ts | 23 ++-
.../app/shared/models/error/custom-error.ts | 18 +--
.../shared/services/api/deltagare.service.ts | 140 +++++++++++++-----
mock-api/dafa-web/scripts/avrop.js | 2 +-
mock-api/dafa-web/server.js | 11 +-
9 files changed, 170 insertions(+), 82 deletions(-)
diff --git a/apps/dafa-web/src/app/pages/deltagare/deltagare.component.html b/apps/dafa-web/src/app/pages/deltagare/deltagare.component.html
index 65d7ebb..e1c73c4 100644
--- a/apps/dafa-web/src/app/pages/deltagare/deltagare.component.html
+++ b/apps/dafa-web/src/app/pages/deltagare/deltagare.component.html
@@ -7,7 +7,12 @@
information om deltagarna.
- Klicka för att gå till en test-deltagare från API:et
+
- {{deltagare.fullName}}
diff --git a/apps/dafa-web/src/app/pages/deltagare/pages/deltagare-card/deltagare-card.component.html b/apps/dafa-web/src/app/pages/deltagare/pages/deltagare-card/deltagare-card.component.html
index 24f31b4..8f310bd 100644
--- a/apps/dafa-web/src/app/pages/deltagare/pages/deltagare-card/deltagare-card.component.html
+++ b/apps/dafa-web/src/app/pages/deltagare/pages/deltagare-card/deltagare-card.component.html
@@ -32,7 +32,7 @@
- Telefon:
-
+
- {{ phoneNumber.type }}: {{phoneNumber.number}}
@@ -66,27 +66,33 @@
Om tjänsten
- Tillhörande tjänst:
- - {{ deltagare.service }}
+ -
+ {{ deltagare.avropInformation.tjanst }}
+
- Datum för tjänstens början:
- - {{ deltagare.startDate | localDate }}
+ -
+
+
- Datum för tjänstens slut:
- - {{ deltagare.endDate | localDate }}
+ -
+
+
- Deltagandefrekvens:
- - {{ deltagare.service.frequency }}
+ -
+ {{ deltagare.avropInformation.participationFrequency }}
+
- Utförande verksamhet:
- - {{ deltagare.service.organisation }}
+ -
+ {{ deltagare.avropInformation.utforandeVerksamhet }}
+
- Utförande adress:
- -
- {{ deltagare.service.organisation.adress }}
+
-
+ {{ deltagare.avropInformation.utforandeAdress }}
- Genomförandereferens:
- - {{ deltagare.service.reference }}
+ -
+ {{ deltagare.avropInformation.genomforandeReferens }}
+
diff --git a/apps/dafa-web/src/app/pages/deltagare/pages/deltagare-card/deltagare-card.component.ts b/apps/dafa-web/src/app/pages/deltagare/pages/deltagare-card/deltagare-card.component.ts
index 733fb64..d318bfe 100644
--- a/apps/dafa-web/src/app/pages/deltagare/pages/deltagare-card/deltagare-card.component.ts
+++ b/apps/dafa-web/src/app/pages/deltagare/pages/deltagare-card/deltagare-card.component.ts
@@ -5,7 +5,7 @@ import { Deltagare } from '@dafa-models/deltagare.model';
import { WorkExperience } from '@dafa-models/work-experience.model';
import { DeltagareService } from '@dafa-services/api/deltagare.service';
import { Observable } from 'rxjs';
-import { map, switchMap } from 'rxjs/operators';
+import { map } from 'rxjs/operators';
@Component({
selector: 'dafa-deltagare-card',
@@ -14,12 +14,7 @@ import { map, switchMap } from 'rxjs/operators';
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class DeltagareCardComponent {
- private _deltagareId$: Observable = this.activatedRoute.params.pipe(
- map(({ deltagareId }) => deltagareId as string)
- );
- deltagare$: Observable = this._deltagareId$.pipe(
- switchMap(deltagareId => this.deltagaresService.deltagare$(deltagareId))
- );
+ deltagare$: Observable = this.deltagareService.deltagare$;
firstVisibleWorkExperiences$: Observable = this.deltagare$.pipe(
map(deltagare => deltagare.workExperiences.slice(0, 2))
);
@@ -30,7 +25,9 @@ export class DeltagareCardComponent {
iconType = IconType;
accordionExpanded = false;
- constructor(private activatedRoute: ActivatedRoute, private deltagaresService: DeltagareService) {}
+ constructor(private activatedRoute: ActivatedRoute, private deltagareService: DeltagareService) {
+ this.deltagareService.setCurrentDeltagareId(this.activatedRoute.snapshot.params.deltagareId);
+ }
toggleAccordionExpanded(): void {
this.accordionExpanded = !this.accordionExpanded;
diff --git a/apps/dafa-web/src/app/shared/models/api/deltagare.response.model.ts b/apps/dafa-web/src/app/shared/models/api/deltagare.response.model.ts
index e0fbac3..9562663 100644
--- a/apps/dafa-web/src/app/shared/models/api/deltagare.response.model.ts
+++ b/apps/dafa-web/src/app/shared/models/api/deltagare.response.model.ts
@@ -1,3 +1,4 @@
+import { AvropResponse } from './avrop.response.model';
import { ContactInformationResponse } from './contact-information.response.model';
import { DisabilitiesResponse } from './disabilities.response.model';
import { DriversLicenseResponse } from './drivers-license.response.model';
@@ -23,4 +24,5 @@ export interface DeltagareResponse {
workLanguages: WorkLanguagesResponse;
disabilities: DisabilitiesResponse;
workExperiences: WorkExperiencesResponse;
+ avropInformation: AvropResponse;
}
diff --git a/apps/dafa-web/src/app/shared/models/deltagare.model.ts b/apps/dafa-web/src/app/shared/models/deltagare.model.ts
index cc73748..0a98e97 100644
--- a/apps/dafa-web/src/app/shared/models/deltagare.model.ts
+++ b/apps/dafa-web/src/app/shared/models/deltagare.model.ts
@@ -1,5 +1,7 @@
import { Address } from './address.model';
-import { DeltagareCompactResponse, DeltagareResponse } from './api/deltagare.response.model';
+import { AvropResponse } from './api/avrop.response.model';
+import { DeltagareResponse } from './api/deltagare.response.model';
+import { Avrop, mapAvropResponseToAvrop } from './avrop.model';
import { mapResponseToContactInformation } from './contact-information.model';
import { Disability, mapResponseToDisability } from './disability.model';
import { DriversLicense, mapResponseToDriversLicense } from './drivers-license.model';
@@ -11,10 +13,13 @@ import { mapResponseToWorkExperience, WorkExperience } from './work-experience.m
export interface DeltagareCompact {
id: string;
fullName: string;
- kommun?: string;
+ utforandeVerksamhet: string;
+ utforandeAdress: string;
}
-export interface Deltagare extends DeltagareCompact {
+export interface Deltagare {
+ id: string;
+ fullName: string;
firstName: string;
lastName: string;
ssn: string;
@@ -28,14 +33,16 @@ export interface Deltagare extends DeltagareCompact {
disabilities: Disability[];
workLanguages: string[];
workExperiences: WorkExperience[];
+ avropInformation: Avrop;
}
-export function mapResponseToDeltagareCompact(data: DeltagareCompactResponse): DeltagareCompact {
- const { sokandeId, deltagare, kommun } = data;
+export function mapResponseToDeltagareCompact(data: AvropResponse): DeltagareCompact {
+ const { sokandeId, deltagare, adress, utforandeverksamhet } = data;
return {
- id: sokandeId,
+ id: sokandeId.toString(),
fullName: deltagare,
- kommun,
+ utforandeVerksamhet: utforandeverksamhet,
+ utforandeAdress: adress,
};
}
@@ -50,6 +57,7 @@ export function mapResponseToDeltagare(data: DeltagareResponse): Deltagare {
workLanguages,
disabilities,
workExperiences,
+ avropInformation,
} = data;
return {
@@ -65,5 +73,6 @@ export function mapResponseToDeltagare(data: DeltagareResponse): Deltagare {
workExperiences:
workExperiences &&
workExperiences.arbetslivserfarenheter.map(workExperience => mapResponseToWorkExperience(workExperience)),
+ avropInformation: avropInformation && mapAvropResponseToAvrop(avropInformation),
};
}
diff --git a/apps/dafa-web/src/app/shared/models/error/custom-error.ts b/apps/dafa-web/src/app/shared/models/error/custom-error.ts
index 66a2f56..9abfb09 100644
--- a/apps/dafa-web/src/app/shared/models/error/custom-error.ts
+++ b/apps/dafa-web/src/app/shared/models/error/custom-error.ts
@@ -28,6 +28,9 @@ export class CustomError implements Error {
if (!error) {
return '';
}
+ if (typeof error === 'string') {
+ return error;
+ }
if ('stack' in error) {
return error.stack;
@@ -39,18 +42,13 @@ export class CustomError implements Error {
}
static getErrorType(error: Error | (Error & { type: ErrorType })): ErrorType {
- let type: ErrorType;
- if ('type' in error) {
- type = error.type;
- } else {
- type = ErrorType.UNKNOWN;
+ if (typeof error === 'object' && 'type' in error) {
+ return error.type;
+ } else if (error.name === 'HttpErrorResponse') {
+ return ErrorType.API;
}
- if (error.name === 'HttpErrorResponse') {
- type = ErrorType.API;
- }
-
- return type;
+ return ErrorType.UNKNOWN;
}
}
diff --git a/apps/dafa-web/src/app/shared/services/api/deltagare.service.ts b/apps/dafa-web/src/app/shared/services/api/deltagare.service.ts
index bb935f9..43d21d3 100644
--- a/apps/dafa-web/src/app/shared/services/api/deltagare.service.ts
+++ b/apps/dafa-web/src/app/shared/services/api/deltagare.service.ts
@@ -1,8 +1,9 @@
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
+import { UnsubscribeDirective } from '@dafa-directives/unsubscribe.directive';
import { environment } from '@dafa-environment';
+import { AvropResponse } from '@dafa-models/api/avrop.response.model';
import { ContactInformationResponse } from '@dafa-models/api/contact-information.response.model';
-import { DeltagareCompactResponse } from '@dafa-models/api/deltagare.response.model';
import { DisabilityResponse } from '@dafa-models/api/disability.response.model';
import { DriversLicenseResponse } from '@dafa-models/api/drivers-license.response.model';
import { EducationsResponse } from '@dafa-models/api/educations.response.model';
@@ -10,55 +11,90 @@ import { HighestEducationResponse } from '@dafa-models/api/highest-education.res
import { TranslatorResponse } from '@dafa-models/api/translator.response.model';
import { WorkExperiencesResponse } from '@dafa-models/api/work-experiences.response.model';
import { WorkLanguagesResponse } from '@dafa-models/api/work-languages.response.model';
+import { Avrop, mapAvropResponseToAvrop } from '@dafa-models/avrop.model';
import { ContactInformation, mapResponseToContactInformation } from '@dafa-models/contact-information.model';
import { Deltagare, DeltagareCompact, mapResponseToDeltagareCompact } from '@dafa-models/deltagare.model';
import { Disability, mapResponseToDisability } from '@dafa-models/disability.model';
import { DriversLicense, mapResponseToDriversLicense } from '@dafa-models/drivers-license.model';
import { Education, mapResponseToEducation } from '@dafa-models/education.model';
+import { errorToCustomError } from '@dafa-models/error/custom-error';
import { HighestEducation, mapResponseToHighestEducation } from '@dafa-models/highest-education.model';
import { mapResponseToWorkExperience, WorkExperience } from '@dafa-models/work-experience.model';
+import { ErrorService } from '@dafa-services/error.service';
import { sortFromToDates } from '@dafa-utils/sort.util';
-import { combineLatest, Observable } from 'rxjs';
-import { map } from 'rxjs/operators';
+import { BehaviorSubject, combineLatest, Observable, of } from 'rxjs';
+import { catchError, filter, map, switchMap } from 'rxjs/operators';
const API_HEADERS = { headers: environment.api.headers };
@Injectable({
providedIn: 'root',
})
-export class DeltagareService {
+export class DeltagareService extends UnsubscribeDirective {
private _apiBaseUrl = `${environment.api.url}/customerinfo`;
private _apiAvropUrl = `${environment.api.url}/avrop`;
+ private _currentDeltagareId$ = new BehaviorSubject(null);
- // private _fetchAllDeltagare: Observable = this.httpClient
- // .get<{ data: DeltagareCompactResponse[] }>(`${this._apiAvropUrl}`, { ...API_HEADERS })
- // .pipe(map(response => response.data));
+ constructor(private httpClient: HttpClient, private errorService: ErrorService) {
+ super();
+ this.unsubscribeOnDestroy(
+ this._currentDeltagareId$
+ .pipe(
+ filter(currentDeltagareId => !!currentDeltagareId),
+ switchMap(currentDeltagareId => this.fetchDeltagare$(currentDeltagareId))
+ )
+ .subscribe(deltagare => {
+ this._deltagare$.next(deltagare);
+ })
+ );
+ }
- private _fetchAllDeltagare: Observable = this.httpClient.get(
- `${this._apiAvropUrl}`,
- { ...API_HEADERS }
- );
+ private _deltagare$ = new BehaviorSubject(null);
+ public deltagare$: Observable = this._deltagare$.asObservable();
- public allDeltagare$: Observable = this._fetchAllDeltagare.pipe(
- map(data => data.map(deltagare => mapResponseToDeltagareCompact(deltagare)))
- );
+ public allDeltagare$: Observable = this.httpClient
+ .get<{ data: AvropResponse[] }>(`${this._apiAvropUrl}`, { ...API_HEADERS })
+ .pipe(map(response => response.data.map(deltagare => mapResponseToDeltagareCompact(deltagare))));
- private _fetchContactInformation$(id: string): Observable {
+ public setCurrentDeltagareId(currentDeltagareId: string): void {
+ this._deltagare$.next(null);
+ this._currentDeltagareId$.next(currentDeltagareId);
+ }
+
+ private _fetchContactInformation$(id: string): Observable> {
return this.httpClient
.get<{ data: ContactInformationResponse }>(`${this._apiBaseUrl}/contact/${id}`, { ...API_HEADERS })
- .pipe(map(response => mapResponseToContactInformation(response.data)));
+ .pipe(
+ map(response => mapResponseToContactInformation(response.data)),
+ catchError(error => {
+ this.errorService.add(errorToCustomError(error));
+ return of({});
+ })
+ );
}
- private _fetchDriversLicense$(id: string): Observable {
+ private _fetchDriversLicense$(id: string): Observable> {
return this.httpClient
.get<{ data: DriversLicenseResponse }>(`${this._apiBaseUrl}/driverlicense/${id}`, { ...API_HEADERS })
- .pipe(map(response => mapResponseToDriversLicense(response.data)));
+ .pipe(
+ map(response => mapResponseToDriversLicense(response.data)),
+ catchError(error => {
+ this.errorService.add(errorToCustomError(error));
+ return of({});
+ })
+ );
}
- private _fetchHighestEducation$(id: string): Observable {
+ private _fetchHighestEducation$(id: string): Observable> {
return this.httpClient
.get<{ data: HighestEducationResponse }>(`${this._apiBaseUrl}/education/highest/${id}`, { ...API_HEADERS })
- .pipe(map(response => mapResponseToHighestEducation(response.data)));
+ .pipe(
+ map(response => mapResponseToHighestEducation(response.data)),
+ catchError(error => {
+ this.errorService.add(errorToCustomError(error));
+ return of({});
+ })
+ );
}
private _fetchEducations$(id: string): Observable {
@@ -73,20 +109,38 @@ export class DeltagareService {
}
return [];
}),
- map(educations => educations.map(utbildning => mapResponseToEducation(utbildning)))
+ map(
+ educations => educations.map(utbildning => mapResponseToEducation(utbildning)),
+ catchError(error => {
+ this.errorService.add(errorToCustomError(error));
+ return of([]);
+ })
+ )
);
}
private _fetchTranslator$(id: string): Observable {
return this.httpClient
.get<{ data: TranslatorResponse }>(`${this._apiBaseUrl}/translator/${id}`, { ...API_HEADERS })
- .pipe(map(response => (response.data.sprak ? response.data.sprak.beskrivning : null)));
+ .pipe(
+ map(response => (response.data.sprak ? response.data.sprak.beskrivning : null)),
+ catchError(error => {
+ this.errorService.add(errorToCustomError(error));
+ return of('');
+ })
+ );
}
private _fetchWorkLanguages$(id: string): Observable {
return this.httpClient
.get<{ data: WorkLanguagesResponse }>(`${this._apiBaseUrl}/work/languages/${id}`, { ...API_HEADERS })
- .pipe(map(response => (response.data.sprak ? response.data.sprak.map(sprak => sprak.beskrivning) : [])));
+ .pipe(
+ map(response => (response.data.sprak ? response.data.sprak.map(sprak => sprak.beskrivning) : [])),
+ catchError(error => {
+ this.errorService.add(errorToCustomError(error));
+ return of([]);
+ })
+ );
}
private _fetchDisabilities$(id: string): Observable {
@@ -97,7 +151,11 @@ export class DeltagareService {
response.data.length
? response.data.map(funktionsnedsattning => mapResponseToDisability(funktionsnedsattning))
: []
- )
+ ),
+ catchError(error => {
+ this.errorService.add(errorToCustomError(error));
+ return of([]);
+ })
);
}
@@ -113,23 +171,31 @@ export class DeltagareService {
}
return [];
}),
- map(workExperiences => workExperiences.map(erfarenhet => mapResponseToWorkExperience(erfarenhet)))
+ map(workExperiences => workExperiences.map(erfarenhet => mapResponseToWorkExperience(erfarenhet))),
+ catchError(error => {
+ this.errorService.add(errorToCustomError(error));
+ return of([]);
+ })
);
}
- public deltagareCompact$(id: string): Observable {
- return this._fetchContactInformation$(id).pipe(
- map(contactInformation => ({
- id,
- fullName: contactInformation.fullName,
- }))
- );
+ private _fetchAvropInformation$(id: string): Observable> {
+ return this.httpClient
+ .get<{ data: AvropResponse }>(`${this._apiAvropUrl}/${id}`, { ...API_HEADERS })
+ .pipe(
+ filter(response => !!response.data),
+ map(response => mapAvropResponseToAvrop(response.data)),
+ catchError(error => {
+ this.errorService.add(errorToCustomError(error));
+ return of({});
+ })
+ );
}
// As TypeScript has some limitations regarding combining Observables this way,
// we need to type it manually when exceeding 6 Observables inside a combineLatest.
// Read: https://github.com/ReactiveX/rxjs/issues/3601#issuecomment-384711601
- public deltagare$(id: string): Observable {
+ public fetchDeltagare$(id: string): Observable {
return combineLatest([
this._fetchContactInformation$(id),
this._fetchDriversLicense$(id),
@@ -139,6 +205,7 @@ export class DeltagareService {
this._fetchWorkLanguages$(id),
this._fetchDisabilities$(id),
this._fetchWorkExperiences$(id),
+ this._fetchAvropInformation$(id),
]).pipe(
map(
([
@@ -150,6 +217,7 @@ export class DeltagareService {
workLanguages,
disabilities,
workExperiences,
+ avropInformation,
]: [
ContactInformation,
DriversLicense,
@@ -158,7 +226,8 @@ export class DeltagareService {
string,
string[],
Disability[],
- WorkExperience[]
+ WorkExperience[],
+ Avrop
]) => ({
id,
...contactInformation,
@@ -169,10 +238,9 @@ export class DeltagareService {
workLanguages,
disabilities,
workExperiences,
+ avropInformation,
})
)
);
}
-
- constructor(private httpClient: HttpClient) {}
}
diff --git a/mock-api/dafa-web/scripts/avrop.js b/mock-api/dafa-web/scripts/avrop.js
index 76d3e56..948c1e9 100644
--- a/mock-api/dafa-web/scripts/avrop.js
+++ b/mock-api/dafa-web/scripts/avrop.js
@@ -25,7 +25,7 @@ function generateAvrop(amount = 10, deltagare) {
avrop.push({
id: faker.datatype.uuid(),
- deltagare: currentDeltagare.fullName,
+ deltagare: `${currentDeltagare.contact.fornamn} ${currentDeltagare.contact.efternamn}`,
genomforandeReferens: faker.datatype.number({ min: 100000000, max: 999999999 }),
orgId: faker.datatype.uuid(),
leverantorId: faker.datatype.number({ min: 1000, max: 99999 }),
diff --git a/mock-api/dafa-web/server.js b/mock-api/dafa-web/server.js
index c8ce794..f8dd81b 100644
--- a/mock-api/dafa-web/server.js
+++ b/mock-api/dafa-web/server.js
@@ -21,6 +21,7 @@ server.use(
'/avrop/tjanster*': '/tjanster$1',
'/avrop/utforandeverksamheter*': '/organizations$1',
'/avrop/kommuner*': '/kommuner$1',
+ '/avrop/:sokandeId': '/avrop?sokandeId=:sokandeId',
'*page=*': '$1_page=$2',
'*limit=*': '$1_limit=$2',
'*sort=*': '$1_sort=$2',
@@ -57,7 +58,7 @@ router.render = (req, res) => {
let data = res.locals.data;
const deltagareRegex = /(?:\/customerinfo\/)(contact|driverlicense|education\/highest|education|translator|work\/disability|work\/languages|work\/experience)/g;
const isDeltagarePath = deltagareRegex.exec(pathname);
- const avropRegex = /(?:\/avrop\/)(tjanster|utforandeverksamheter|kommuner)/g;
+ const avropRegex = /(?:\/avrop\/)(tjanster|utforandeverksamheter|kommuner|\d)/g;
const isAvropPath = avropRegex.exec(pathname);
if (isDeltagarePath) {
@@ -75,6 +76,8 @@ router.render = (req, res) => {
});
data = newData.filter((value, index, arr) => arr.findIndex(item => item.code === value.code) === index);
+ } else if (isAvropPath[1]) {
+ data = data[0];
}
}
@@ -91,9 +94,9 @@ server.listen(8000, () => {
});
function appendMetaData(params, res) {
- if (params && params.has('_page')) {
- const limit = +params.get('_limit');
- const page = +params.get('_page');
+ if (params && params.has('page')) {
+ const limit = +params.get('limit');
+ const page = +params.get('page');
const count = res.get('X-Total-Count');
const totalPages = Math.ceil(count / limit);
return {