diff --git a/apps/mina-sidor-fa/src/app/app.module.ts b/apps/mina-sidor-fa/src/app/app.module.ts
index bfc2062..9a7779b 100644
--- a/apps/mina-sidor-fa/src/app/app.module.ts
+++ b/apps/mina-sidor-fa/src/app/app.module.ts
@@ -19,6 +19,7 @@ const providers: Provider[] = [
ApmErrorHandler,
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true },
{ provide: LOCALE_ID, useValue: 'sv-SE' },
+ { provide: ErrorHandler, useClass: CustomErrorHandler },
];
// Skip error handler in Dev until "Uncaught Error: ApplicationRef.tick is called recursively" is fixed
diff --git a/apps/mina-sidor-fa/src/app/components/toast-list/toast-list.component.html b/apps/mina-sidor-fa/src/app/components/toast-list/toast-list.component.html
index 7887427..a4518c5 100644
--- a/apps/mina-sidor-fa/src/app/components/toast-list/toast-list.component.html
+++ b/apps/mina-sidor-fa/src/app/components/toast-list/toast-list.component.html
@@ -8,7 +8,7 @@
{{ errors.length }} fel har uppstått!
- - {{ error.name }}: {{ error.message }}
+ - {{ error.type }}: {{ error.message }}
diff --git a/apps/mina-sidor-fa/src/app/components/toast-list/toast/toast.component.html b/apps/mina-sidor-fa/src/app/components/toast-list/toast/toast.component.html
index 26132aa..9b6d587 100644
--- a/apps/mina-sidor-fa/src/app/components/toast-list/toast/toast.component.html
+++ b/apps/mina-sidor-fa/src/app/components/toast-list/toast/toast.component.html
@@ -16,7 +16,8 @@
-
{{ error.name }}
+ {{ error.type }}
{{ error.message }}
+ Error id: {{error.id}}
diff --git a/apps/mina-sidor-fa/src/app/components/toast-list/toast/toast.component.scss b/apps/mina-sidor-fa/src/app/components/toast-list/toast/toast.component.scss
index 0e35d60..68e7d0e 100644
--- a/apps/mina-sidor-fa/src/app/components/toast-list/toast/toast.component.scss
+++ b/apps/mina-sidor-fa/src/app/components/toast-list/toast/toast.component.scss
@@ -62,4 +62,10 @@
padding: var(--digi--layout--gutter--s);
color: var(--digi--typography--color--text);
}
+
+ &__error-id {
+ align-self: flex-end;
+ font-size: var(--digi--typography--font-size--s);
+ margin-top: var(--digi--layout--gutter--s);
+ }
}
diff --git a/apps/mina-sidor-fa/src/app/components/toast-list/toast/toast.component.ts b/apps/mina-sidor-fa/src/app/components/toast-list/toast/toast.component.ts
index debe007..70089f2 100644
--- a/apps/mina-sidor-fa/src/app/components/toast-list/toast/toast.component.ts
+++ b/apps/mina-sidor-fa/src/app/components/toast-list/toast/toast.component.ts
@@ -1,8 +1,8 @@
import { AfterViewInit, ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
import { ErrorSeverity } from '@msfa-enums/error-severity.enum';
-import { UiIconType } from '@ui/icon/icon-type.enum';
import { CustomError } from '@msfa-models/error/custom-error';
import { UiIconSize } from '@ui/icon/icon-size.enum';
+import { UiIconType } from '@ui/icon/icon-type.enum';
@Component({
selector: 'msfa-toast',
@@ -19,11 +19,11 @@ export class ToastComponent implements AfterViewInit {
ErrorSeverity = ErrorSeverity;
ngAfterViewInit(): void {
- if (this.error.removeAfter) {
- setTimeout(() => {
- this.closeToast.emit(this.error);
- }, this.error.removeAfter);
- }
+ // if (this.error.removeAfter) {
+ // setTimeout(() => {
+ // this.closeToast.emit(this.error);
+ // }, this.error.removeAfter);
+ // }
}
get className(): string {
diff --git a/apps/mina-sidor-fa/src/app/logging.module.ts b/apps/mina-sidor-fa/src/app/logging.module.ts
index e6cc3c5..7d71926 100644
--- a/apps/mina-sidor-fa/src/app/logging.module.ts
+++ b/apps/mina-sidor-fa/src/app/logging.module.ts
@@ -10,6 +10,7 @@ import { environment } from '@msfa-environment';
export class LoggingModule {
private _elasticConfig = environment.elastic;
private _activeFeatures = environment.activeFeatures;
+ private _version = environment.version;
constructor(private apmService: ApmService) {
if (this._elasticConfig && this._activeFeatures.includes(Feature.LOGGING)) {
@@ -18,6 +19,7 @@ export class LoggingModule {
serviceName,
serverUrl,
environment: this.currentEnvironment,
+ serviceVersion: this._version,
});
}
}
diff --git a/apps/mina-sidor-fa/src/app/pages/administration/pages/employee-form/employee-form.component.ts b/apps/mina-sidor-fa/src/app/pages/administration/pages/employee-form/employee-form.component.ts
index ae63d8e..861e02b 100644
--- a/apps/mina-sidor-fa/src/app/pages/administration/pages/employee-form/employee-form.component.ts
+++ b/apps/mina-sidor-fa/src/app/pages/administration/pages/employee-form/employee-form.component.ts
@@ -59,8 +59,9 @@ export class EmployeeFormComponent implements OnInit {
next: () => {
void this.router.navigateByUrl(`/administration/personal/${this.employeeId}`);
},
- error: error => {
+ error: (error: CustomError) => {
this._errorWhileUpdating$.next(error);
+ throw error;
},
complete: () => {
updateEmployeeSubscription.unsubscribe();
diff --git a/apps/mina-sidor-fa/src/app/pages/avrop/avrop.component.ts b/apps/mina-sidor-fa/src/app/pages/avrop/avrop.component.ts
index 5e8dfa7..1ea4952 100644
--- a/apps/mina-sidor-fa/src/app/pages/avrop/avrop.component.ts
+++ b/apps/mina-sidor-fa/src/app/pages/avrop/avrop.component.ts
@@ -2,7 +2,7 @@ import { ChangeDetectionStrategy, Component, OnDestroy } from '@angular/core';
import { Avrop, AvropAndMeta } from '@msfa-models/avrop.model';
import { Handledare } from '@msfa-models/handledare.model';
import { AvropService } from '@msfa-services/avrop.service';
-import { Observable, BehaviorSubject } from 'rxjs';
+import { BehaviorSubject, Observable } from 'rxjs';
@Component({
selector: 'msfa-avrop',
diff --git a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/report-forms/avvikelse-report-form/avvikelse-report-form.service.ts b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/report-forms/avvikelse-report-form/avvikelse-report-form.service.ts
index 630a9c2..12e37d7 100644
--- a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/report-forms/avvikelse-report-form/avvikelse-report-form.service.ts
+++ b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/report-forms/avvikelse-report-form/avvikelse-report-form.service.ts
@@ -14,9 +14,10 @@ export class AvvikelseReportFormService {
.fetchAvvikelseQuestions$()
.pipe(shareReplay(1));
- fetchAvvikelseReasons$: Observable = this.avvikelseApiService
- .fetchAvvikelseReasons$()
- .pipe(map(reasons => sortAvvikelseReasons(reasons)));
+ fetchAvvikelseReasons$: Observable = this.avvikelseApiService.fetchAvvikelseReasons$().pipe(
+ map(reasons => sortAvvikelseReasons(reasons)),
+ shareReplay(1)
+ );
constructor(private avvikelseApiService: AvvikelseApiService, private deltagareApiService: DeltagareApiService) {}
diff --git a/apps/mina-sidor-fa/src/app/shared/interceptors/custom-error-handler.ts b/apps/mina-sidor-fa/src/app/shared/interceptors/custom-error-handler.ts
index f2ca72d..76eca6e 100644
--- a/apps/mina-sidor-fa/src/app/shared/interceptors/custom-error-handler.ts
+++ b/apps/mina-sidor-fa/src/app/shared/interceptors/custom-error-handler.ts
@@ -1,15 +1,27 @@
import { ErrorHandler, Injectable } from '@angular/core';
-import { ApmErrorHandler } from '@elastic/apm-rum-angular';
+import { ApmErrorHandler, ApmService } from '@elastic/apm-rum-angular';
import { Feature } from '@msfa-enums/feature.enum';
import { environment } from '@msfa-environment';
import { CustomError } from '@msfa-models/error/custom-error';
import { ErrorService } from '@msfa-services/error.service';
+interface ApmError {
+ id: string;
+ name: string;
+ message: string;
+ type: string;
+ method: string;
+ timestamp: Date;
+}
@Injectable()
export class CustomErrorHandler implements ErrorHandler {
private _elasticConfig = environment.elastic;
private _activeFeatures = environment.activeFeatures;
- constructor(private errorService: ErrorService, public apmErrorHandler: ApmErrorHandler) {}
+ constructor(
+ private errorService: ErrorService,
+ public apmErrorHandler: ApmErrorHandler,
+ private apmService: ApmService
+ ) {}
handleError(customError: CustomError & { ngDebugContext: unknown }): void {
if (!customError.avoidToast) {
@@ -17,7 +29,11 @@ export class CustomErrorHandler implements ErrorHandler {
}
if (this._elasticConfig && this._activeFeatures.includes(Feature.LOGGING)) {
- this.apmErrorHandler.handleError(customError);
+ const { id, method, name, type, message, timestamp, data } = customError;
+ const apmError: ApmError = { id, method, name, type, message, timestamp };
+
+ this.apmService.apm.addLabels({ id, method, data });
+ this.apmService.apm.captureError(apmError);
}
}
}
diff --git a/apps/mina-sidor-fa/src/app/shared/models/authorization.model.ts b/apps/mina-sidor-fa/src/app/shared/models/authorization.model.ts
deleted file mode 100644
index 635436b..0000000
--- a/apps/mina-sidor-fa/src/app/shared/models/authorization.model.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-export interface Authorization {
- id: string;
- name: string;
-}
-
-export interface AuthorizationApiResponse {
- data: AuthorizationApiResponseData[];
-}
-
-export interface AuthorizationApiResponseData {
- id: string;
- name: string;
-}
-
-export function mapAuthorizationApiResponseToAuthorization(data: AuthorizationApiResponseData): Authorization {
- const { id, name } = data;
- return {
- id,
- name,
- };
-}
diff --git a/apps/mina-sidor-fa/src/app/shared/models/error/custom-error.ts b/apps/mina-sidor-fa/src/app/shared/models/error/custom-error.ts
index 94494e2..26ac563 100644
--- a/apps/mina-sidor-fa/src/app/shared/models/error/custom-error.ts
+++ b/apps/mina-sidor-fa/src/app/shared/models/error/custom-error.ts
@@ -1,3 +1,4 @@
+import { HttpErrorResponse } from '@angular/common/http';
import { ErrorSeverity } from '@msfa-enums/error-severity.enum';
import { ErrorType } from '@msfa-enums/error-type.enum';
@@ -7,15 +8,20 @@ export class CustomError implements Error {
message: string;
stack: string;
type: ErrorType;
+ data: string;
+ method: string;
severity: ErrorSeverity;
timestamp: Date;
- error: Error;
+ error: Error | HttpErrorResponse;
removeAfter: number;
avoidToast?: boolean;
constructor(args: {
- error: Error;
+ error: Error | HttpErrorResponse;
type?: ErrorType;
+ name?: string;
+ data?: unknown;
+ method?: string;
message?: string;
severity?: ErrorSeverity;
stack?: string;
@@ -23,7 +29,10 @@ export class CustomError implements Error {
}) {
this.timestamp = new Date();
this.id = this.timestamp.getTime().toString();
- this.type = this.name = args.type || CustomError.getErrorType(args.error);
+ this.type = args.type || CustomError.getErrorType(args.error);
+ this.name = args.name || args.error?.name || this.type;
+ this.method = args.method || '';
+ this.data = JSON.stringify(args.data);
this.message = args.message || args.error.message;
this.severity = args.severity || ErrorSeverity.HIGH;
this.stack = args.stack || CustomError.getStack(args.error);
diff --git a/apps/mina-sidor-fa/src/app/shared/services/api/authentication.service.ts b/apps/mina-sidor-fa/src/app/shared/services/api/authentication.service.ts
index 89d8d7a..65722ba 100644
--- a/apps/mina-sidor-fa/src/app/shared/services/api/authentication.service.ts
+++ b/apps/mina-sidor-fa/src/app/shared/services/api/authentication.service.ts
@@ -11,6 +11,7 @@ import {
import { environment } from '@msfa-environment';
import { AuthenticationResponse } from '@msfa-models/api/authentication.response.model';
import { Authentication, mapAuthApiResponseToAuthenticationResult } from '@msfa-models/authentication.model';
+import { CustomError } from '@msfa-models/error/custom-error';
import { add, isAfter, isBefore, sub } from 'date-fns';
import { BehaviorSubject, Observable, of } from 'rxjs';
import { catchError, distinctUntilChanged, map, tap } from 'rxjs/operators';
@@ -103,12 +104,22 @@ export class AuthenticationService {
login$(authorizationCodeFromCiam: string): Observable {
this.removeLocalStorageData();
+ const apiUrl = AuthenticationService._authTokenApiUrl(authorizationCodeFromCiam);
+
return this.httpClient
.get<{ data: AuthenticationResponse }>(AuthenticationService._authTokenApiUrl(authorizationCodeFromCiam))
.pipe(
map(({ data }) => mapAuthApiResponseToAuthenticationResult(data)),
tap(authenticationResult => {
this._setSession(authenticationResult);
+ }),
+ catchError((error: Error) => {
+ throw new CustomError({
+ error,
+ message: `Kunde inte logga in.\n\n${error.message}`,
+ name: `GET ${apiUrl}`,
+ method: 'AuthenticationService.login$',
+ });
})
);
}
diff --git a/apps/mina-sidor-fa/src/app/shared/services/api/authorizations.service.ts b/apps/mina-sidor-fa/src/app/shared/services/api/authorizations.service.ts
deleted file mode 100644
index 62679bf..0000000
--- a/apps/mina-sidor-fa/src/app/shared/services/api/authorizations.service.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import { HttpClient } from '@angular/common/http';
-import { Injectable } from '@angular/core';
-import { environment } from '@msfa-environment';
-import {
- Authorization,
- AuthorizationApiResponse,
- mapAuthorizationApiResponseToAuthorization,
-} from '@msfa-models/authorization.model';
-import { Observable } from 'rxjs';
-import { map } from 'rxjs/operators';
-
-@Injectable({
- providedIn: 'root',
-})
-export class AuthorizationService {
- private _apiBaseUrl = `${environment.api.url}/authorizations`;
- public authorizations$: Observable = this.httpClient
- .get(this._apiBaseUrl)
- .pipe(map(({ data }) => data.map(authorization => mapAuthorizationApiResponseToAuthorization(authorization))));
-
- constructor(private httpClient: HttpClient) {}
-}
diff --git a/apps/mina-sidor-fa/src/app/shared/services/api/avrop-api.service.ts b/apps/mina-sidor-fa/src/app/shared/services/api/avrop-api.service.ts
index cfba0f2..daeea7e 100644
--- a/apps/mina-sidor-fa/src/app/shared/services/api/avrop-api.service.ts
+++ b/apps/mina-sidor-fa/src/app/shared/services/api/avrop-api.service.ts
@@ -6,7 +6,7 @@ import { AvropAndMetaResponse } from '@msfa-models/api/avrop.response.model';
import { Params } from '@msfa-models/api/params.model';
import { AvropFilter, mapResponseToAvropFilter } from '@msfa-models/avrop-filter.model';
import { Avrop, AvropAndMeta, mapResponseToAvrop } from '@msfa-models/avrop.model';
-import { CustomError, errorToCustomError } from '@msfa-models/error/custom-error';
+import { CustomError } from '@msfa-models/error/custom-error';
import { BehaviorSubject, Observable, of } from 'rxjs';
import { catchError, filter, map } from 'rxjs/operators';
@@ -27,7 +27,7 @@ export class AvropApiService {
fetchAvrop$(params: Params): Observable {
return this.httpClient
- .get(`${this._apiBaseUrl}`, { params })
+ .get(this._apiBaseUrl, { params })
.pipe(
map(({ data, meta }) => ({ data: data.map(avrop => mapResponseToAvrop(avrop)), meta })),
catchError((error: Error & { status: number }) => {
@@ -35,48 +35,68 @@ export class AvropApiService {
this._showUnauthorizedError$.next(true);
return of(null as null);
} else {
- throw new CustomError(
- errorToCustomError({ ...error, message: `Kunde inte hämta nya deltagare.\n\n${error.message}` })
- );
+ throw new CustomError({
+ error,
+ message: `Kunde inte hämta nya deltagare.\n\n${error.message}`,
+ name: `GET ${this._apiBaseUrl}`,
+ method: 'AvropApiService.fetchAvrop$',
+ });
}
})
);
}
fetchAvailableTjanster$(params: Params): Observable {
+ const apiUrl = `${this._apiBaseUrl}/tjanster`;
return this.httpClient
- .get<{ data: AvropFilterResponse[] }>(`${this._apiBaseUrl}/tjanster`, { params })
+ .get<{ data: AvropFilterResponse[] }>(apiUrl, { params })
.pipe(
filter(response => !!response?.data),
- map(({ data }) => data.map(tjanster => mapResponseToAvropFilter(tjanster)))
+ map(({ data }) => data.map(tjanster => mapResponseToAvropFilter(tjanster))),
+ catchError((error: Error) => {
+ throw new CustomError({
+ error,
+ message: `Kunde inte hämta tjänster.\n\n${error.message}`,
+ name: `GET ${apiUrl}`,
+ method: 'AvropApiService.fetchAvailableTjanster$',
+ });
+ })
);
}
fetchAvailableUtforandeVerksamheter$(params: Params): Observable {
+ const apiUrl = `${this._apiBaseUrl}/utforandeverksamheter`;
return this.httpClient
- .get<{ data: AvropFilterResponse[] }>(`${this._apiBaseUrl}/utforandeverksamheter`, { params })
+ .get<{ data: AvropFilterResponse[] }>(apiUrl, { params })
.pipe(
filter(response => !!response?.data),
- map(({ data }) => data.map(utforandeverksamheter => mapResponseToAvropFilter(utforandeverksamheter)))
+ map(({ data }) => data.map(utforandeverksamheter => mapResponseToAvropFilter(utforandeverksamheter))),
+ catchError((error: Error) => {
+ throw new CustomError({
+ error,
+ message: `Kunde inte hämta utförande verksamheter.\n\n${error.message}`,
+ name: `GET ${apiUrl}`,
+ method: 'AvropApiService.fetchAvailableUtforandeVerksamheter$',
+ });
+ })
);
}
fetchAvailableKommuner$(params: Params): Observable {
+ const apiUrl = `${this._apiBaseUrl}/kommuner`;
return this.httpClient
- .get<{ data: AvropFilterResponse[] }>(`${this._apiBaseUrl}/kommuner`, { params })
+ .get<{ data: AvropFilterResponse[] }>(apiUrl, { params })
.pipe(
filter(response => !!response?.data),
- map(({ data }) => data.map(kommun => mapResponseToAvropFilter(kommun)))
+ map(({ data }) => data.map(kommun => mapResponseToAvropFilter(kommun))),
+ catchError((error: Error) => {
+ throw new CustomError({
+ error,
+ message: `Kunde inte hämta kommuner.\n\n${error.message}`,
+ name: `GET ${apiUrl}`,
+ method: 'AvropApiService.fetchAvailableKommuner$',
+ });
+ })
);
}
-
- async assignHandledare(avrop: Avrop[], handledareId: string): Promise {
- const params: Params = {
- avropIds: avrop.map(deltagare => deltagare.id),
- ciamUserId: handledareId,
- };
- return this.httpClient
- .patch(`${this._apiBaseUrl}/handledare/assign`, null, { params })
- .toPromise();
- }
}
diff --git a/apps/mina-sidor-fa/src/app/shared/services/api/avvikelse-api.service.ts b/apps/mina-sidor-fa/src/app/shared/services/api/avvikelse-api.service.ts
index f720bbb..3ec5395 100644
--- a/apps/mina-sidor-fa/src/app/shared/services/api/avvikelse-api.service.ts
+++ b/apps/mina-sidor-fa/src/app/shared/services/api/avvikelse-api.service.ts
@@ -1,6 +1,5 @@
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
-import { ErrorType } from '@msfa-enums/error-type.enum';
import { environment } from '@msfa-environment';
import { AvvikelseQuestionsResponse } from '@msfa-models/api/avvikelse-question.response.model';
import { AvvikelseReasonResponse } from '@msfa-models/api/avvikelse-reason.response.model';
@@ -20,26 +19,47 @@ export class AvvikelseApiService {
constructor(private httpClient: HttpClient) {}
public fetchAvvikelseReasons$(): Observable {
- return this.httpClient.get<{ data: AvvikelseReasonResponse[] }>(`${this._apiBaseUrl}/orsakskoderavvikelse`).pipe(
+ const apiUrl = `${this._apiBaseUrl}/orsakskoderavvikelse`;
+ return this.httpClient.get<{ data: AvvikelseReasonResponse[] }>(apiUrl).pipe(
filter(response => !!response?.data),
- map(({ data }) => data.map(avvikelse => mapResponseToAvvikelseReason(avvikelse)))
+ map(({ data }) => data.map(avvikelse => mapResponseToAvvikelseReason(avvikelse))),
+ catchError((error: Error) => {
+ throw new CustomError({
+ error,
+ message: `Kunde inte hämta orsaker till avvikelse.\n\n${error.message}`,
+ name: `GET ${apiUrl}`,
+ method: 'AvvikelseApiService.fetchAvvikelseReasons$',
+ });
+ })
);
}
public fetchAvvikelseQuestions$(): Observable {
- return this.httpClient.get<{ data: AvvikelseQuestionsResponse[] }>(`${this._apiBaseUrl}/fragorforavvikelser`).pipe(
+ const apiUrl = `${this._apiBaseUrl}/fragorforavvikelser`;
+ return this.httpClient.get<{ data: AvvikelseQuestionsResponse[] }>(apiUrl).pipe(
filter(response => !!response?.data),
- map(({ data }) => data.map(fraga => mapResponseToAvvikelseQuestion(fraga)))
+ map(({ data }) => data.map(fraga => mapResponseToAvvikelseQuestion(fraga))),
+ catchError((error: Error) => {
+ throw new CustomError({
+ error,
+ message: `Kunde inte hämta avvikelse frågor.\n\n${error.message}`,
+ name: `GET ${apiUrl}`,
+ method: 'AvvikelseApiService.fetchAvvikelseQuestions$',
+ });
+ })
);
}
public createAvvikelse$(avvikelse: AvvikelseReportRequest): Observable {
- return this.httpClient.post(`${this._apiBaseUrl}/avvikelse`, avvikelse).pipe(
+ const apiUrl = `${this._apiBaseUrl}/avvikelse`;
+ return this.httpClient.post(apiUrl, avvikelse).pipe(
catchError((error: Error) => {
throw new CustomError({
error,
message: `Kunde inte spara Avvikelserapport (avvikelse).\n\n${error.message}`,
- type: ErrorType.API,
+ name: `POST ${apiUrl}`,
+ data: avvikelse,
+ method: 'AvvikelseApiService.createAvvikelse$',
});
})
);
diff --git a/apps/mina-sidor-fa/src/app/shared/services/api/deltagare-handelser-api.service.ts b/apps/mina-sidor-fa/src/app/shared/services/api/deltagare-handelser-api.service.ts
index aab6803..296f268 100644
--- a/apps/mina-sidor-fa/src/app/shared/services/api/deltagare-handelser-api.service.ts
+++ b/apps/mina-sidor-fa/src/app/shared/services/api/deltagare-handelser-api.service.ts
@@ -7,8 +7,10 @@ import {
DeltagareHandelserApiResponse,
mapDeltagareHandelseApiResponse,
} from '@msfa-models/deltagare-handelse.model';
+import { CustomError } from '@msfa-models/error/custom-error';
+import { replaceGenomforandereferensFromUrl } from '@msfa-shared/utils/replace-genomforandereferens-from-url.util';
import { Observable } from 'rxjs';
-import { map } from 'rxjs/operators';
+import { catchError, filter, map } from 'rxjs/operators';
@Injectable({
providedIn: 'root',
@@ -19,26 +21,31 @@ export class DeltagareHandelserApiService {
constructor(private httpClient: HttpClient) {}
fetchDeltagareHandelser$(
- genomforandeReferens: number,
+ genomforandereferens: number,
handelserParams: PaginationParams
): Observable {
- if (!genomforandeReferens) {
+ if (!genomforandereferens) {
throw new Error('Genomförandereferens kunde inte hittas.');
}
const params: Params = { page: handelserParams.page.toString() };
-
+ const apiUrl = `${this._apiBaseUrl}/deltagare/${genomforandereferens}/handelser`;
return this.httpClient
- .get(`${this._apiBaseUrl}/deltagare/${genomforandeReferens}/handelser`, { params })
+ .get(apiUrl, { params })
.pipe(
- map(({ data, meta }) => {
- if (data) {
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
- return {
- data: data.map(genomforandeHandelse => mapDeltagareHandelseApiResponse(genomforandeHandelse)),
- meta,
- };
- }
+ filter(({ data }) => !!data),
+ map(({ data, meta }) => ({
+ data: data.map(genomforandeHandelse => mapDeltagareHandelseApiResponse(genomforandeHandelse)),
+ meta,
+ })),
+ catchError((error: Error) => {
+ throw new CustomError({
+ error,
+ message: `Kunde inte hämta händelser.\n\n${error.message}`,
+ name: `GET ${replaceGenomforandereferensFromUrl(apiUrl)}`,
+ data: { genomforandereferens },
+ method: 'DeltagareHandelserApiService.fetchDeltagareHandelser$',
+ });
})
);
}
diff --git a/apps/mina-sidor-fa/src/app/shared/services/api/deltagare.api.service.ts b/apps/mina-sidor-fa/src/app/shared/services/api/deltagare.api.service.ts
index ed91e6c..70d91cb 100644
--- a/apps/mina-sidor-fa/src/app/shared/services/api/deltagare.api.service.ts
+++ b/apps/mina-sidor-fa/src/app/shared/services/api/deltagare.api.service.ts
@@ -19,10 +19,11 @@ import { DeltagareCompactData, mapResponseToDeltagareCompact } from '@msfa-model
import { Disability, mapResponseToDisability } from '@msfa-models/disability.model';
import { DriversLicense, mapResponseToDriversLicense } from '@msfa-models/drivers-license.model';
import { Education, mapResponseToEducation } from '@msfa-models/education.model';
-import { CustomError, errorToCustomError } from '@msfa-models/error/custom-error';
+import { CustomError } from '@msfa-models/error/custom-error';
import { HighestEducation, mapResponseToHighestEducation } from '@msfa-models/highest-education.model';
import { mapResponseToReport, ReportsData } from '@msfa-models/report.model';
import { mapResponseToWorkExperience, WorkExperience } from '@msfa-models/work-experience.model';
+import { replaceGenomforandereferensFromUrl } from '@msfa-shared/utils/replace-genomforandereferens-from-url.util';
import { sortFromToDates } from '@msfa-utils/sort.util';
import { BehaviorSubject, Observable, of } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
@@ -69,18 +70,21 @@ export class DeltagareApiService {
this._showUnauthorizedError$.next(true);
return of(null as null);
} else {
- throw new CustomError(
- errorToCustomError({ ...error, message: `Kunde inte hämta deltagare.\n\n${error.message}` })
- );
+ throw new CustomError({
+ error,
+ message: `Kunde inte hämta deltagare.\n\n${error.message}`,
+ name: `GET ${this._apiBaseUrl}`,
+ method: 'DeltagareApiService.fetchAllDeltagare$',
+ });
}
})
);
}
- public fetchReports$(genomforandeReferens: number, paginationParams: PaginationParams): Observable {
+ public fetchReports$(genomforandereferens: number, paginationParams: PaginationParams): Observable {
const { page, limit } = paginationParams;
const params: { [param: string]: string | string[] } = {
- genomforandeReferens: genomforandeReferens.toString(),
+ genomforandeReferens: genomforandereferens.toString(),
page: page.toString(),
limit: limit.toString(),
};
@@ -90,143 +94,170 @@ export class DeltagareApiService {
.pipe(
map(({ data, meta }) => ({ data: data.map(report => mapResponseToReport(report)), meta })),
catchError((error: Error) => {
- throw new CustomError(
- errorToCustomError({ ...error, message: `Kunde inte hämta rapporter.\n\n${error.message}` })
- );
+ throw new CustomError({
+ error,
+ message: `Kunde inte hämta rapporter.\n\n${error.message}`,
+ name: `GET ${this._apiReportUrl}`,
+ method: 'DeltagareApiService.fetchReports$',
+ });
})
);
}
- public fetchContactInformation$(genomforandeReferens: number): Observable {
- return this.httpClient
- .get<{ data: ContactInformationResponse }>(`${this._apiBaseUrl}/${genomforandeReferens}/contact`)
- .pipe(
- map(({ data }) => mapResponseToContactInformation(data)),
- catchError((error: Error) => {
- throw new CustomError(
- errorToCustomError({ ...error, message: `Kunde inte hämta kontaktinformation.\n\n${error.message}` })
- );
- })
- );
+ public fetchContactInformation$(genomforandereferens: number): Observable {
+ const apiUrl = `${this._apiBaseUrl}/${genomforandereferens}/contact`;
+ return this.httpClient.get<{ data: ContactInformationResponse }>(apiUrl).pipe(
+ map(({ data }) => mapResponseToContactInformation(data)),
+ catchError((error: Error) => {
+ throw new CustomError({
+ error,
+ message: `Kunde inte hämta kontaktinformation.\n\n${error.message}`,
+ name: `GET ${replaceGenomforandereferensFromUrl(apiUrl)}`,
+ data: { genomforandereferens },
+ method: 'DeltagareApiService.fetchContactInformation$',
+ });
+ })
+ );
}
- public fetchDriversLicense$(genomforandeReferens: number): Observable {
- return this.httpClient
- .get<{ data: DriversLicenseResponse }>(`${this._apiBaseUrl}/${genomforandeReferens}/driverlicense`)
- .pipe(
- map(({ data }) => mapResponseToDriversLicense(data)),
- catchError((error: Error) => {
- throw new CustomError(
- errorToCustomError({ ...error, message: `Kunde inte hämta körkortsinformation.\n\n${error.message}` })
- );
- })
- );
+ public fetchDriversLicense$(genomforandereferens: number): Observable {
+ const apiUrl = `${this._apiBaseUrl}/${genomforandereferens}/driverlicense`;
+ return this.httpClient.get<{ data: DriversLicenseResponse }>(apiUrl).pipe(
+ map(({ data }) => mapResponseToDriversLicense(data)),
+ catchError((error: Error) => {
+ throw new CustomError({
+ error,
+ message: `Kunde inte hämta körkortsinformation.\n\n${error.message}`,
+ name: `GET ${replaceGenomforandereferensFromUrl(apiUrl)}`,
+ data: { genomforandereferens },
+ method: 'DeltagareApiService.fetchDriversLicense$',
+ });
+ })
+ );
}
- public fetchHighestEducation$(genomforandeReferens: number): Observable {
- return this.httpClient
- .get<{ data: HighestEducationResponse }>(`${this._apiBaseUrl}/${genomforandeReferens}/educationlevels/highest`)
- .pipe(
- map(({ data }) => mapResponseToHighestEducation(data)),
- catchError((error: Error) => {
- throw new CustomError(
- errorToCustomError({ ...error, message: `Kunde inte hämta högsta utbildning.\n\n${error.message}` })
- );
- })
- );
+ public fetchHighestEducation$(genomforandereferens: number): Observable {
+ const apiUrl = `${this._apiBaseUrl}/${genomforandereferens}/educationlevels/highest`;
+ return this.httpClient.get<{ data: HighestEducationResponse }>(apiUrl).pipe(
+ map(({ data }) => mapResponseToHighestEducation(data)),
+ catchError((error: Error) => {
+ throw new CustomError({
+ error,
+ message: `Kunde inte hämta högsta utbildning.\n\n${error.message}`,
+ name: `GET ${replaceGenomforandereferensFromUrl(apiUrl)}`,
+ data: { genomforandereferens },
+ method: 'DeltagareApiService.fetchHighestEducation$',
+ });
+ })
+ );
}
- public fetchEducations$(genomforandeReferens: number): Observable {
- return this.httpClient
- .get<{ data: EducationsResponse }>(`${this._apiBaseUrl}/${genomforandeReferens}/educations`)
- .pipe(
- map(({ data }) =>
- data.utbildningar
- ? data.utbildningar.sort((a, b) =>
- sortFromToDates({ from: a.period_from, to: a.period_tom }, { from: b.period_from, to: b.period_tom })
- )
- : []
- ),
- map(educations => educations.map(utbildning => mapResponseToEducation(utbildning))),
- catchError((error: Error) => {
- throw new CustomError(
- errorToCustomError({ ...error, message: `Kunde inte hämta utbildningar.\n\n${error.message}` })
- );
- })
- );
- }
-
- public fetchTranslator$(genomforandeReferens: number): Observable {
- return this.httpClient
- .get<{ data: TranslatorResponse }>(`${this._apiBaseUrl}/${genomforandeReferens}/translator`)
- .pipe(
- map(({ data }) => data.sprak?.beskrivning || null),
- catchError((error: Error) => {
- throw new CustomError(
- errorToCustomError({ ...error, message: `Kunde inte hämta tolkinformation.\n\n${error.message}` })
- );
- })
- );
- }
-
- public fetchWorkLanguages$(genomforandeReferens: number): Observable {
- return this.httpClient
- .get<{ data: WorkLanguagesResponse }>(`${this._apiBaseUrl}/${genomforandeReferens}/work/languages`)
- .pipe(
- map(({ data }) => data?.sprak?.map(sprak => sprak.beskrivning) || []),
- catchError((error: Error) => {
- throw new CustomError(
- errorToCustomError({
- ...error,
- message: `Kunde inte hämta språk som kan användas på jobbet.\n\n${error.message}`,
- })
- );
- })
- );
- }
-
- public fetchDisabilities$(genomforandeReferens: number): Observable {
- return this.httpClient
- .get<{ data: DisabilityResponse[] }>(`${this._apiBaseUrl}/${genomforandeReferens}/work/disabilities`)
- .pipe(
- map(({ data }) => data?.map(funktionsnedsattning => mapResponseToDisability(funktionsnedsattning)) || []),
- catchError((error: Error) => {
- throw new CustomError(
- errorToCustomError({ ...error, message: `Kunde inte hämta funktionsnedsättningar.\n\n${error.message}` })
- );
- })
- );
- }
-
- public fetchWorkExperiences$(genomforandeReferens: number): Observable {
- return this.httpClient
- .get<{ data: WorkExperiencesResponse }>(`${this._apiBaseUrl}/${genomforandeReferens}/work/experiences`)
- .pipe(
- map(
- ({ data }) =>
- data?.arbetslivserfarenheter?.sort((a, b) =>
+ public fetchEducations$(genomforandereferens: number): Observable {
+ const apiUrl = `${this._apiBaseUrl}/${genomforandereferens}/educations`;
+ return this.httpClient.get<{ data: EducationsResponse }>(apiUrl).pipe(
+ map(({ data }) =>
+ data.utbildningar
+ ? data.utbildningar.sort((a, b) =>
sortFromToDates({ from: a.period_from, to: a.period_tom }, { from: b.period_from, to: b.period_tom })
- ) || []
- ),
- map(workExperiences => workExperiences.map(erfarenhet => mapResponseToWorkExperience(erfarenhet))),
- catchError((error: Error) => {
- throw new CustomError(
- errorToCustomError({ ...error, message: `Kunde inte hämta arbetslivserfarenheter.\n\n${error.message}` })
- );
- })
- );
+ )
+ : []
+ ),
+ map(educations => educations.map(utbildning => mapResponseToEducation(utbildning))),
+ catchError((error: Error) => {
+ throw new CustomError({
+ error,
+ message: `Kunde inte hämta utbildningar.\n\n${error.message}`,
+ name: `GET ${replaceGenomforandereferensFromUrl(apiUrl)}`,
+ data: { genomforandereferens },
+ method: 'DeltagareApiService.fetchEducations$',
+ });
+ })
+ );
}
- public fetchAvropInformation$(genomforandeReferens: number): Observable {
- return this.httpClient
- .get<{ data: DeltagareAvropResponse }>(`${this._apiBaseUrl}/${genomforandeReferens}/avrop`)
- .pipe(
- map(({ data }) => mapResponseToDeltagareAvrop(data)),
- catchError((error: Error) => {
- throw new CustomError(
- errorToCustomError({ ...error, message: `Kunde inte hämta avropsinformation.\n\n${error.message}` })
- );
- })
- );
+ public fetchTranslator$(genomforandereferens: number): Observable {
+ const apiUrl = `${this._apiBaseUrl}/${genomforandereferens}/translator`;
+ return this.httpClient.get<{ data: TranslatorResponse }>(apiUrl).pipe(
+ map(({ data }) => data.sprak?.beskrivning || null),
+ catchError((error: Error) => {
+ throw new CustomError({
+ error,
+ message: `Kunde inte hämta tolkinformation.\n\n${error.message}`,
+ name: `GET ${replaceGenomforandereferensFromUrl(apiUrl)}`,
+ data: { genomforandereferens },
+ method: 'DeltagareApiService.fetchTranslator$',
+ });
+ })
+ );
+ }
+
+ public fetchWorkLanguages$(genomforandereferens: number): Observable {
+ const apiUrl = `${this._apiBaseUrl}/${genomforandereferens}/work/languages`;
+ return this.httpClient.get<{ data: WorkLanguagesResponse }>(apiUrl).pipe(
+ map(({ data }) => data?.sprak?.map(sprak => sprak.beskrivning) || []),
+ catchError((error: Error) => {
+ throw new CustomError({
+ error,
+ message: `Kunde inte hämta språk som kan användas på jobbet.\n\n${error.message}`,
+ name: `GET ${replaceGenomforandereferensFromUrl(apiUrl)}`,
+ data: { genomforandereferens },
+ method: 'DeltagareApiService.fetchWorkLanguages$',
+ });
+ })
+ );
+ }
+
+ public fetchDisabilities$(genomforandereferens: number): Observable {
+ const apiUrl = `${this._apiBaseUrl}/${genomforandereferens}/work/disabilities`;
+ return this.httpClient.get<{ data: DisabilityResponse[] }>(apiUrl).pipe(
+ map(({ data }) => data?.map(funktionsnedsattning => mapResponseToDisability(funktionsnedsattning)) || []),
+ catchError((error: Error) => {
+ throw new CustomError({
+ error,
+ message: `Kunde inte hämta funktionsnedsättningar.\n\n${error.message}`,
+ name: `GET ${replaceGenomforandereferensFromUrl(apiUrl)}`,
+ data: { genomforandereferens },
+ method: 'DeltagareApiService.fetchDisabilities$',
+ });
+ })
+ );
+ }
+
+ public fetchWorkExperiences$(genomforandereferens: number): Observable {
+ const apiUrl = `${this._apiBaseUrl}/${genomforandereferens}/work/experiences`;
+ return this.httpClient.get<{ data: WorkExperiencesResponse }>(apiUrl).pipe(
+ map(
+ ({ data }) =>
+ data?.arbetslivserfarenheter?.sort((a, b) =>
+ sortFromToDates({ from: a.period_from, to: a.period_tom }, { from: b.period_from, to: b.period_tom })
+ ) || []
+ ),
+ map(workExperiences => workExperiences.map(erfarenhet => mapResponseToWorkExperience(erfarenhet))),
+ catchError((error: Error) => {
+ throw new CustomError({
+ error,
+ message: `Kunde inte hämta arbetslivserfarenheter.\n\n${error.message}`,
+ name: `GET ${replaceGenomforandereferensFromUrl(apiUrl)}`,
+ data: { genomforandereferens },
+ method: 'DeltagareApiService.fetchWorkExperiences$',
+ });
+ })
+ );
+ }
+
+ public fetchAvropInformation$(genomforandereferens: number): Observable {
+ const apiUrl = `${this._apiBaseUrl}/${genomforandereferens}/avrop`;
+ return this.httpClient.get<{ data: DeltagareAvropResponse }>(apiUrl).pipe(
+ map(({ data }) => mapResponseToDeltagareAvrop(data)),
+ catchError((error: Error) => {
+ throw new CustomError({
+ error,
+ message: `Kunde inte hämta avropsinformation.\n\n${error.message}`,
+ name: `GET ${replaceGenomforandereferensFromUrl(apiUrl)}`,
+ data: { genomforandereferens },
+ method: 'DeltagareApiService.fetchAvropInformation$',
+ });
+ })
+ );
}
}
diff --git a/apps/mina-sidor-fa/src/app/shared/services/api/employee.service.ts b/apps/mina-sidor-fa/src/app/shared/services/api/employee.service.ts
index 55cd030..9574746 100644
--- a/apps/mina-sidor-fa/src/app/shared/services/api/employee.service.ts
+++ b/apps/mina-sidor-fa/src/app/shared/services/api/employee.service.ts
@@ -17,10 +17,10 @@ import {
mapResponseToEmployee,
mapResponseToEmployeeCompact,
} from '@msfa-models/employee.model';
-import { errorToCustomError } from '@msfa-models/error/custom-error';
+import { CustomError } from '@msfa-models/error/custom-error';
import { Sort } from '@msfa-models/sort.model';
import { ErrorService } from '@msfa-services/error.service';
-import { BehaviorSubject, combineLatest, Observable, of, throwError } from 'rxjs';
+import { BehaviorSubject, combineLatest, Observable } from 'rxjs';
import { catchError, distinctUntilChanged, filter, map, switchMap, take, tap } from 'rxjs/operators';
const DEFAULT_PARAMS: EmployeeParams = {
@@ -119,16 +119,30 @@ export class EmployeeService extends UnsubscribeDirective {
map(({ data, meta }) => {
this._employeesLoading$.next(false);
return { data: data.map(employee => mapResponseToEmployeeCompact(employee)), meta };
+ }),
+ catchError((error: Error) => {
+ throw new CustomError({
+ error,
+ message: `Kunde inte hämta personal.\n\n${error.message}`,
+ name: `GET ${this._apiBaseUrl}`,
+ method: 'EmployeeService._fetchEmployees$',
+ });
})
);
}
- private _fetchEmployee$(id: string): Observable> {
- return this.httpClient.get<{ data: EmployeeResponse }>(`${this._apiBaseUrl}/${id}`).pipe(
+ private _fetchEmployee$(ciamUserId: string): Observable {
+ const apiUrl = `${this._apiBaseUrl}/${ciamUserId}`;
+ return this.httpClient.get<{ data: EmployeeResponse }>(apiUrl).pipe(
map(({ data }) => mapResponseToEmployee(data)),
- catchError(error => {
- this.errorService.add(errorToCustomError(error));
- return of({});
+ catchError((error: Error) => {
+ throw new CustomError({
+ error,
+ message: `Kunde inte hämta personal.\n\n${error.message}`,
+ name: `GET ${this._apiBaseUrl}/{ciamUserId}`,
+ data: { ciamUserId },
+ method: 'EmployeeService._fetchEmployee$',
+ });
})
);
}
@@ -153,13 +167,20 @@ export class EmployeeService extends UnsubscribeDirective {
this._employeeToDelete$.next(employee);
}
- public deleteEmployee(employee: Employee): Observable> {
+ public deleteEmployee(employee: Employee): Observable {
return this.httpClient.delete(`${this._apiBaseUrl}/${employee.id}`).pipe(
tap(() => {
this._lastDeletedEmployee$.next(employee);
}),
map(() => employee),
- catchError(error => throwError(errorToCustomError(error)))
+ catchError((error: Error) => {
+ throw new CustomError({
+ error,
+ message: `Kunde inte ta bort personal.\n\n${error.message}`,
+ name: `DELETE ${this._apiBaseUrl}/{ciamUserId}`,
+ method: 'EmployeeService.deleteEmployee',
+ });
+ })
);
}
@@ -175,28 +196,40 @@ export class EmployeeService extends UnsubscribeDirective {
}
public postEmployeeInvitation(emails: string[]): Observable {
+ const apiUrl = `${this._apiBaseUrl}/invite`;
return this.httpClient
- .patch<{ data: EmployeeInviteResponse }>(`${this._apiBaseUrl}/invite`, { emails })
+ .patch<{ data: EmployeeInviteResponse }>(apiUrl, { emails })
.pipe(
take(1),
map(({ data }) => data),
- catchError(error => {
- this.errorService.add(errorToCustomError(error));
- return throwError(errorToCustomError(error));
+ catchError((error: Error) => {
+ throw new CustomError({
+ error,
+ message: `Kunde inte bjuda in personal.\n\n${error.message}`,
+ name: `PATCH ${apiUrl}`,
+ data: { emails },
+ method: 'EmployeeService.postEmployeeInvitation',
+ });
})
);
}
- public updateEmployee$(id: string, data: EmployeeEditRequest): Observable {
- return this.httpClient.put(`${this._apiBaseUrl}/${id}`, data).pipe(
+ public updateEmployee$(ciamUserId: string, data: EmployeeEditRequest): Observable {
+ return this.httpClient.put(`${this._apiBaseUrl}/${ciamUserId}`, data).pipe(
take(1),
tap(() => {
this._employee$.next(null);
- this._lastUpdatedEmployeeId$.next(id);
+ this._lastUpdatedEmployeeId$.next(ciamUserId);
}),
map(() => true),
- catchError(error => {
- return throwError(errorToCustomError(error));
+ catchError((error: Error) => {
+ throw new CustomError({
+ error,
+ message: `Kunde inte redigera personal.\n\n${error.message}`,
+ name: `PATCH ${this._apiBaseUrl}/{ciamUserId}`,
+ data: { ciamUserId },
+ method: 'EmployeeService.updateEmployee$',
+ });
})
);
}
diff --git a/apps/mina-sidor-fa/src/app/shared/services/api/user.service.ts b/apps/mina-sidor-fa/src/app/shared/services/api/user.service.ts
index e3813fb..f292774 100644
--- a/apps/mina-sidor-fa/src/app/shared/services/api/user.service.ts
+++ b/apps/mina-sidor-fa/src/app/shared/services/api/user.service.ts
@@ -1,5 +1,6 @@
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
+import { ApmService } from '@elastic/apm-rum-angular';
import { SELECTED_ORGANIZATION_NUMBER_KEY } from '@msfa-constants/local-storage-keys';
import { UnsubscribeDirective } from '@msfa-directives/unsubscribe.directive';
import { environment } from '@msfa-environment';
@@ -38,7 +39,11 @@ export class UserService extends UnsubscribeDirective {
return this._userRoles$.getValue();
}
- constructor(private httpClient: HttpClient, private authenticationService: AuthenticationService) {
+ constructor(
+ private httpClient: HttpClient,
+ private authenticationService: AuthenticationService,
+ private apmService: ApmService
+ ) {
super();
this._selectedOrganizationNumber$.next(this._selectedOrganizationNumber);
super.unsubscribeOnDestroy(
@@ -64,6 +69,8 @@ export class UserService extends UnsubscribeDirective {
this._user$.next(currentUser);
this._userLoading$.next(false);
this._userRolesLoading$.next(false);
+
+ this.apmService.apm.setUserContext({ id: currentUser.id });
})
);
}
diff --git a/apps/mina-sidor-fa/src/app/shared/services/avrop.service.ts b/apps/mina-sidor-fa/src/app/shared/services/avrop.service.ts
index 16ea609..930cd87 100644
--- a/apps/mina-sidor-fa/src/app/shared/services/avrop.service.ts
+++ b/apps/mina-sidor-fa/src/app/shared/services/avrop.service.ts
@@ -3,10 +3,10 @@ import { AvropParams, Params } from '@msfa-models/api/params.model';
import { Avrop, AvropAndMeta } from '@msfa-models/avrop.model';
import { Handledare } from '@msfa-models/handledare.model';
import { AvropApiService } from '@msfa-services/api/avrop-api.service';
+import { MultiselectFilterOption } from '@ui/multiselect/multiselect-filter-option';
import { BehaviorSubject, combineLatest, Observable, of } from 'rxjs';
import { distinctUntilChanged, filter, map, shareReplay, switchMap, tap } from 'rxjs/operators';
import { HandledareApiService } from './api/handledare.api.service';
-import { MultiselectFilterOption } from '@ui/multiselect/multiselect-filter-option';
type Step = 1 | 2 | 3 | 4;
@@ -249,7 +249,12 @@ export class AvropService {
return;
}
- await this.avropApiService.assignHandledare(this._selectedAvrop$.value, this._selectedHandledareId$.value);
+ const avrop: Avrop[] = this._selectedAvrop$.getValue();
+
+ await this.handledareApiService.assignHandledare(
+ avrop.map(deltagare => deltagare.id),
+ { ciamUserId: this._selectedHandledareId$.value } as Handledare
+ );
this._avropIsSubmitted$.next(true);
}
diff --git a/apps/mina-sidor-fa/src/app/shared/utils/replace-genomforandereferens-from-url.util.ts b/apps/mina-sidor-fa/src/app/shared/utils/replace-genomforandereferens-from-url.util.ts
new file mode 100644
index 0000000..e94aa3e
--- /dev/null
+++ b/apps/mina-sidor-fa/src/app/shared/utils/replace-genomforandereferens-from-url.util.ts
@@ -0,0 +1,4 @@
+export function replaceGenomforandereferensFromUrl(url: string): string {
+ const regex = /\/\d*\//;
+ return url.replace(regex, '/{genomforandereferens}/');
+}