Merge branch 'next' into develop

This commit is contained in:
Erik Tiekstra
2021-09-27 15:11:21 +02:00
17 changed files with 262 additions and 157 deletions
+1
View File
@@ -3,6 +3,7 @@
### Bug Fixes ### Bug Fixes
- **deltagare:** Now fetching data using "genomforandeReferens" instead of "sokandeId" to avoid wrong data. [TV-692](https://jira.arbetsformedlingen.se/browse/TV-692) - **deltagare:** Now fetching data using "genomforandeReferens" instead of "sokandeId" to avoid wrong data. [TV-692](https://jira.arbetsformedlingen.se/browse/TV-692)
- **authorization:** Whenever the API throws a "403 Forbidden" error we now show an unauthorized message. [TV-695](https://jira.arbetsformedlingen.se/browse/TV-695)
## [2.0.0](https://bitbucket.arbetsformedlingen.se/projects/tea/repos/mina-sidor-fa-web/compare/diff?targetBranch=refs%2Ftags%2Fv1.5.0&sourceBranch=refs%2Ftags%2Fv2.0.0) (2021-09-24) ## [2.0.0](https://bitbucket.arbetsformedlingen.se/projects/tea/repos/mina-sidor-fa-web/compare/diff?targetBranch=refs%2Ftags%2Fv1.5.0&sourceBranch=refs%2Ftags%2Fv2.0.0) (2021-09-24)
@@ -1,131 +1,143 @@
<msfa-layout> <msfa-layout>
<section class="avrop" *ngIf="currentStep$ | async as currentStep"> <digi-typography>
<digi-typography> <ng-container *ngIf="(showUnauthorizedError$ | async) === false; else roleError">
<header class="avrop__header"> <ng-container *ngIf="avropData$ | async as avropData; else skeletonRef">
<h1>Nya deltagare</h1> <section class="avrop" *ngIf="currentStep$ | async as currentStep">
<p> <header class="avrop__header">
Här ser du alla nya deltagare. Deltagarna ska tilldelas en handledare innan tjänstens start. Kryssa för de <h1>Nya deltagare</h1>
deltagare du vill tilldela en handledare. Du kan välja en, eller flera personer samtidigt, genom att kryssa i <p>
boxarna nedan. Här ser du alla nya deltagare. Deltagarna ska tilldelas en handledare innan tjänstens start. Kryssa för de
</p> deltagare du vill tilldela en handledare. Du kan välja en, eller flera personer samtidigt, genom att
kryssa i boxarna nedan.
</p>
<digi-notification-alert
*ngIf="currentStep === 4 && selectedHandledare$ | async as selectedHandledare"
af-heading="Allt gick bra"
af-variation="success"
>
<p>Tilldelningen är nu skickad till {{selectedHandledare.fullName}}.</p>
</digi-notification-alert>
</header>
<main class="avrop__steps">
<div class="avrop__step-header">
<h2 class="avrop__sub-heading">
<ng-container [ngSwitch]="currentStep">
<ng-container *ngSwitchCase="1">Välj deltagare att tilldela</ng-container>
<ng-container *ngSwitchCase="2">Tilldela handledare</ng-container>
<ng-container *ngSwitchCase="3">Förehandsgranska och tilldela</ng-container>
<ng-container *ngSwitchCase="4">Tilldelade delgare</ng-container>
</ng-container>
</h2>
<div class="avrop__progress-bar" *ngIf="currentStep < 4">
<span>Steg {{ currentStep }} av {{ totalAmountOfSteps }}:</span>
<digi-ng-progress-progressbar
[afSteps]="totalAmountOfSteps"
[afActiveStep]="currentStep"
></digi-ng-progress-progressbar>
</div>
</div>
<ng-container *ngIf="avropData$ | async as avropData">
<div class="avrop__content" *ngIf="avropData.data.length; else noAvrop">
<div class="avrop__filter" *ngIf="currentStep === 1">
<h3>Filter</h3>
<msfa-avrop-filters></msfa-avrop-filters>
</div>
<div class="avrop__select-handledare" *ngIf="currentStep === 2">
<ng-container *ngIf="availableHandledare$ | async as availableHandledare; else loadingRef">
<digi-form-select
*ngIf="availableHandledare?.length; else noAvailabeHandledare"
af-label="Välj handledare att tilldela"
af-placeholder="Välj handledare"
[afRequired]="true"
af-validation="error"
(afOnChange)="changeHandledare($event.detail)"
>
<option
*ngFor="let availableHandledare of availableHandledare"
[value]="availableHandledare.ciamUserId"
>
{{ availableHandledare.fullName }}
</option>
</digi-form-select>
<ng-template #noAvailableHandledare>
<p>Inga handledare har behörighet till markerade deltagare</p>
</ng-template>
</ng-container>
</div>
<h3>Välj deltagare att tilldela handledare</h3>
<msfa-avrop-list
[availableAvrop]="avropData.data"
[paginationMeta]="avropData.meta"
[selectedAvrop]="selectedAvrop$ | async"
[isLocked]="avropIsLocked$ | async"
[isSubmitted]="avropIsSubmitted$ | async"
[handledare]="selectedHandledare$ | async"
[handledareConfirmed]="handledareConfirmed$ | async"
[avropLoading]="avropLoading$ | async"
(selectionChanged)="updateSelectedAvrop($event, currentStep)"
(paginated)="setNewPage($event)"
></msfa-avrop-list>
</div>
<div class="avrop__footer" *ngIf="avropData.data.length" [ngSwitch]="currentStep">
<digi-notification-alert <digi-notification-alert
*ngIf="error$ | async as error" *ngIf="currentStep === 4 && selectedHandledare$ | async as selectedHandledare"
af-heading="Felmeddelande" af-heading="Allt gick bra"
af-variation="danger" af-variation="success"
af-closeable="true"
(afOnClose)="resetError()"
> >
<p>{{error}}</p> <p>Tilldelningen är nu skickad till {{selectedHandledare.fullName}}.</p>
</digi-notification-alert> </digi-notification-alert>
</header>
<div class="avrop__cta-wrapper"> <main class="avrop__steps">
<ng-container *ngSwitchCase="1"> <div class="avrop__step-header">
<digi-button af-size="m" (afOnClick)="lockSelectedAvrop()">Nästa</digi-button> <h2 class="avrop__sub-heading">
</ng-container> <ng-container [ngSwitch]="currentStep">
<ng-container *ngSwitchCase="2"> <ng-container *ngSwitchCase="1">Välj deltagare att tilldela</ng-container>
<digi-button af-variation="secondary" af-size="m" (afOnClick)="unlockSelectedAvrop()" <ng-container *ngSwitchCase="2">Tilldela handledare</ng-container>
>Tillbaka</digi-button <ng-container *ngSwitchCase="3">Förehandsgranska och tilldela</ng-container>
> <ng-container *ngSwitchCase="4">Tilldelade delgare</ng-container>
<digi-button af-size="m" (afOnClick)="confirmHandledare()">Tilldela</digi-button> </ng-container>
</ng-container> </h2>
<ng-container *ngSwitchCase="3">
<digi-button af-variation="secondary" af-size="m" (afOnClick)="unconfirmHandledare()" <div class="avrop__progress-bar" *ngIf="currentStep < 4">
>Tillbaka</digi-button <span>Steg {{ currentStep }} av {{ totalAmountOfSteps }}:</span>
> <digi-ng-progress-progressbar
<digi-button af-size="m" (afOnClick)="save()">Bekräfta tilldelning</digi-button> [afSteps]="totalAmountOfSteps"
</ng-container> [afActiveStep]="currentStep"
<ng-container *ngSwitchCase="4"> ></digi-ng-progress-progressbar>
<digi-button af-size="m" (afOnClick)="returnToStep1()">Tillbaka till nya deltagare</digi-button> </div>
</ng-container>
</div> </div>
</div> <div class="avrop__content" *ngIf="avropData.data.length; else noAvrop">
</ng-container> <div class="avrop__filter" *ngIf="currentStep === 1">
</main> <h3>Filter</h3>
</digi-typography> <msfa-avrop-filters></msfa-avrop-filters>
</section> </div>
<div class="avrop__select-handledare" *ngIf="currentStep === 2">
<ng-container *ngIf="availableHandledare$ | async as availableHandledare; else loadingRef">
<digi-form-select
*ngIf="availableHandledare?.length; else noAvailabeHandledare"
af-label="Välj handledare att tilldela"
af-placeholder="Välj handledare"
[afRequired]="true"
af-validation="error"
(afOnChange)="changeHandledare($event.detail)"
>
<option
*ngFor="let availableHandledare of availableHandledare"
[value]="availableHandledare.ciamUserId"
>
{{ availableHandledare.fullName }}
</option>
</digi-form-select>
<ng-template #loadingRef> <ng-template #noAvailableHandledare>
<msfa-loader></msfa-loader> <p>Inga handledare har behörighet till markerade deltagare</p>
</ng-template> </ng-template>
<ng-template #noAvailabeHandledare> </ng-container>
<!-- lägg in lämpligt innehåll --> </div>
</ng-template>
<ng-template #noAvrop> <h3>Välj deltagare att tilldela handledare</h3>
<p>Det finns för tillfället inga nya deltagare att tilldela.</p> <msfa-avrop-list
</ng-template> [availableAvrop]="avropData.data"
[paginationMeta]="avropData.meta"
[selectedAvrop]="selectedAvrop$ | async"
[isLocked]="avropIsLocked$ | async"
[isSubmitted]="avropIsSubmitted$ | async"
[handledare]="selectedHandledare$ | async"
[handledareConfirmed]="handledareConfirmed$ | async"
[avropLoading]="avropLoading$ | async"
(selectionChanged)="updateSelectedAvrop($event, currentStep)"
(paginated)="setNewPage($event)"
></msfa-avrop-list>
</div>
<div class="avrop__footer" *ngIf="avropData.data.length" [ngSwitch]="currentStep">
<digi-notification-alert
*ngIf="error$ | async as error"
af-heading="Felmeddelande"
af-variation="danger"
af-closeable="true"
(afOnClose)="resetError()"
>
<p>{{error}}</p>
</digi-notification-alert>
<div class="avrop__cta-wrapper">
<ng-container *ngSwitchCase="1">
<digi-button af-size="m" (afOnClick)="lockSelectedAvrop()">Nästa</digi-button>
</ng-container>
<ng-container *ngSwitchCase="2">
<digi-button af-variation="secondary" af-size="m" (afOnClick)="unlockSelectedAvrop()"
>Tillbaka
</digi-button>
<digi-button af-size="m" (afOnClick)="confirmHandledare()">Tilldela</digi-button>
</ng-container>
<ng-container *ngSwitchCase="3">
<digi-button af-variation="secondary" af-size="m" (afOnClick)="unconfirmHandledare()"
>Tillbaka
</digi-button>
<digi-button af-size="m" (afOnClick)="save()">Bekräfta tilldelning</digi-button>
</ng-container>
<ng-container *ngSwitchCase="4">
<digi-button af-size="m" (afOnClick)="returnToStep1()">Tillbaka till nya deltagare</digi-button>
</ng-container>
</div>
</div>
</main>
</section>
</ng-container>
</ng-container>
</digi-typography>
</msfa-layout> </msfa-layout>
<ng-template #loadingRef>
<msfa-loader></msfa-loader>
</ng-template>
<ng-template #skeletonRef>
<digi-ng-skeleton-base [afCount]="3" afText="Laddar nya deltagare"></digi-ng-skeleton-base>
</ng-template>
<ng-template #noAvailabeHandledare>
<!-- lägg in lämpligt innehåll -->
</ng-template>
<ng-template #noAvrop>
<p>Det finns för tillfället inga nya deltagare att tilldela.</p>
</ng-template>
<ng-template #roleError>
<msfa-unauthorized-alert></msfa-unauthorized-alert>
</ng-template>
@@ -13,7 +13,6 @@ import { Observable } from 'rxjs';
export class AvropComponent { export class AvropComponent {
readonly totalAmountOfSteps = 3; readonly totalAmountOfSteps = 3;
currentStep$: Observable<number> = this.avropService.currentStep$; currentStep$: Observable<number> = this.avropService.currentStep$;
error$: Observable<string> = this.avropService.error$; error$: Observable<string> = this.avropService.error$;
avropData$: Observable<AvropCompactData> = this.avropService.avropData$; avropData$: Observable<AvropCompactData> = this.avropService.avropData$;
selectedAvrop$: Observable<AvropCompact[]> = this.avropService.selectedAvrop$; selectedAvrop$: Observable<AvropCompact[]> = this.avropService.selectedAvrop$;
@@ -23,6 +22,7 @@ export class AvropComponent {
handledareConfirmed$: Observable<boolean> = this.avropService.handledareIsConfirmed$; handledareConfirmed$: Observable<boolean> = this.avropService.handledareIsConfirmed$;
avropIsSubmitted$: Observable<boolean> = this.avropService.avropIsSubmitted$; avropIsSubmitted$: Observable<boolean> = this.avropService.avropIsSubmitted$;
avropLoading$: Observable<boolean> = this.avropService.avropLoading$; avropLoading$: Observable<boolean> = this.avropService.avropLoading$;
showUnauthorizedError$: Observable<boolean> = this.avropService.showUnauthorizedError$;
constructor(private avropService: AvropService) {} constructor(private avropService: AvropService) {}
@@ -4,10 +4,11 @@ import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { RouterModule } from '@angular/router'; import { RouterModule } from '@angular/router';
import { LayoutModule } from '@msfa-shared/components/layout/layout.module'; import { LayoutModule } from '@msfa-shared/components/layout/layout.module';
import { LoaderModule } from '@msfa-shared/components/loader/loader.module';
import { UnauthorizedAlertModule } from '@msfa-shared/components/unauthorized-alert/unauthorized-alert.module';
import { AvropComponent } from './avrop.component'; import { AvropComponent } from './avrop.component';
import { AvropFiltersModule } from './components/avrop-filters/avrop-filters.module'; import { AvropFiltersModule } from './components/avrop-filters/avrop-filters.module';
import { AvropListModule } from './components/avrop-list/avrop-list.module'; import { AvropListModule } from './components/avrop-list/avrop-list.module';
import { LoaderModule } from '@msfa-shared/components/loader/loader.module';
@NgModule({ @NgModule({
schemas: [CUSTOM_ELEMENTS_SCHEMA], schemas: [CUSTOM_ELEMENTS_SCHEMA],
@@ -21,6 +22,7 @@ import { LoaderModule } from '@msfa-shared/components/loader/loader.module';
DigiNgProgressProgressbarModule, DigiNgProgressProgressbarModule,
DigiNgSkeletonBaseModule, DigiNgSkeletonBaseModule,
LoaderModule, LoaderModule,
UnauthorizedAlertModule,
], ],
}) })
export class AvropModule {} export class AvropModule {}
@@ -1,23 +1,23 @@
<msfa-layout> <msfa-layout>
<digi-typography> <digi-typography>
<section class="deltagare"> <ng-container *ngIf="(showUnauthorizedError$ | async) === false; else roleError">
<header class="deltagare__header"> <section class="deltagare" *ngIf="allDeltagareData$ | async as allDeltagareData; else loadingRef">
<h1>Deltagarlista</h1> <header class="deltagare__header">
<p> <h1>Deltagarlista</h1>
Här ser du en lista på de deltagare som tillhör din organisation. Klicka på deltagarens namn för att öppna och <p>
se mer information om deltagarna. Här ser du en lista på de deltagare som tillhör din organisation. Klicka på deltagarens namn för att öppna
</p> och se mer information om deltagarna.
</header> </p>
<div class="deltagare__filter"> </header>
<digi-form-checkbox <div class="deltagare__filter">
class="deltagare__only-my-deltagare" <digi-form-checkbox
af-label="Visa endast mina tilldelade deltagare" class="deltagare__only-my-deltagare"
[afChecked]="onlyMyDeltagare$ | async" af-label="Visa endast mina tilldelade deltagare"
(afOnChange)="setOnlyMyDeltagare($event.detail.target.checked)" [afChecked]="onlyMyDeltagare$ | async"
></digi-form-checkbox> (afOnChange)="setOnlyMyDeltagare($event.detail.target.checked)"
</div> ></digi-form-checkbox>
</div>
<ng-container *ngIf="allDeltagareData$ | async as allDeltagareData; else loadingRef"> {{showUnauthorizedError$ | async}}
<ng-container *ngIf="(deltagareLoading$ | async) === false; else loadingRef"> <ng-container *ngIf="(deltagareLoading$ | async) === false; else loadingRef">
<msfa-deltagare-list <msfa-deltagare-list
*ngIf="allDeltagareData.data.length; else noDeltagare" *ngIf="allDeltagareData.data.length; else noDeltagare"
@@ -28,18 +28,22 @@
(paginated)="setNewPage($event)" (paginated)="setNewPage($event)"
></msfa-deltagare-list> ></msfa-deltagare-list>
</ng-container> </ng-container>
</ng-container> </section>
</ng-container>
<ng-template #loadingRef>
<digi-ng-skeleton-base [afCount]="3" afText="Laddar deltagare"></digi-ng-skeleton-base>
</ng-template>
</section>
</digi-typography> </digi-typography>
</msfa-layout> </msfa-layout>
<ng-template #loadingRef>
<digi-ng-skeleton-base [afCount]="3" afText="Laddar deltagare"></digi-ng-skeleton-base>
</ng-template>
<ng-template #noDeltagare> <ng-template #noDeltagare>
<p> <p>
Inga deltagare hittades{{(onlyMyDeltagare$ | async) ? '. Bocka ur "Visa endast mina tilldelade deltagare" för att se Inga deltagare hittades{{(onlyMyDeltagare$ | async) ? '. Bocka ur "Visa endast mina tilldelade deltagare" för att se
deltagare som tillhör din organisation.' : ' som tillhör din organisation.' }} deltagare som tillhör din organisation.' : ' som tillhör din organisation.' }}
</p> </p>
</ng-template> </ng-template>
<ng-template #roleError>
<msfa-unauthorized-alert></msfa-unauthorized-alert>
</ng-template>
@@ -15,6 +15,7 @@ export class DeltagareComponent {
sort$: Observable<Sort<keyof DeltagareCompact>> = this.deltagareService.sort$; sort$: Observable<Sort<keyof DeltagareCompact>> = this.deltagareService.sort$;
onlyMyDeltagare$: Observable<boolean> = this.deltagareService.onlyMyDeltagare$; onlyMyDeltagare$: Observable<boolean> = this.deltagareService.onlyMyDeltagare$;
deltagareLoading$: Observable<boolean> = this.deltagareService.deltagareLoading$; deltagareLoading$: Observable<boolean> = this.deltagareService.deltagareLoading$;
showUnauthorizedError$: Observable<boolean> = this.deltagareService.showUnauthorizedError$;
constructor(private deltagareService: DeltagareService) {} constructor(private deltagareService: DeltagareService) {}
@@ -1,14 +1,22 @@
import { DigiNgSkeletonBaseModule } from '@af/digi-ng/_skeleton/skeleton-base';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { LayoutModule } from '@msfa-shared/components/layout/layout.module'; import { LayoutModule } from '@msfa-shared/components/layout/layout.module';
import { UnauthorizedAlertModule } from '@msfa-shared/components/unauthorized-alert/unauthorized-alert.module';
import { DeltagareListModule } from './components/deltagare-list/deltagare-list.module'; import { DeltagareListModule } from './components/deltagare-list/deltagare-list.module';
import { DeltagareRoutingModule } from './deltagare-routing.module'; import { DeltagareRoutingModule } from './deltagare-routing.module';
import { DeltagareComponent } from './deltagare.component'; import { DeltagareComponent } from './deltagare.component';
import { DigiNgSkeletonBaseModule } from '@af/digi-ng/_skeleton/skeleton-base';
@NgModule({ @NgModule({
schemas: [CUSTOM_ELEMENTS_SCHEMA], schemas: [CUSTOM_ELEMENTS_SCHEMA],
declarations: [DeltagareComponent], declarations: [DeltagareComponent],
imports: [CommonModule, DeltagareRoutingModule, LayoutModule, DeltagareListModule, DigiNgSkeletonBaseModule], imports: [
CommonModule,
DeltagareRoutingModule,
LayoutModule,
DeltagareListModule,
UnauthorizedAlertModule,
DigiNgSkeletonBaseModule,
],
}) })
export class DeltagareModule {} export class DeltagareModule {}
@@ -0,0 +1,7 @@
<digi-notification-alert af-heading="Personalkontot saknar behörigheter!" af-variation="danger">
<p>
Ditt personalkonto behöver tilldelas en tjänst och utförande verksamheter för att det ska fungera korrekt. Ändra
ditt personalkonto via personallistan eller kontakta din behörighetsadministratör om du inte kan ändra dina egna
behörigheter.
</p>
</digi-notification-alert>
@@ -0,0 +1,26 @@
/* tslint:disable:no-unused-variable */
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { UnauthorizedAlertComponent } from './unauthorized-alert.component';
describe('UnauthorizedAlertComponent', () => {
let component: UnauthorizedAlertComponent;
let fixture: ComponentFixture<UnauthorizedAlertComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [UnauthorizedAlertComponent],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
}).compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(UnauthorizedAlertComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,9 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
@Component({
selector: 'msfa-unauthorized-alert',
templateUrl: './unauthorized-alert.component.html',
styleUrls: ['./unauthorized-alert.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class UnauthorizedAlertComponent {}
@@ -0,0 +1,11 @@
import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { UnauthorizedAlertComponent } from './unauthorized-alert.component';
@NgModule({
schemas: [CUSTOM_ELEMENTS_SCHEMA],
declarations: [UnauthorizedAlertComponent],
imports: [CommonModule],
exports: [UnauthorizedAlertComponent],
})
export class UnauthorizedAlertModule {}
@@ -7,9 +7,10 @@ import { HandledareResponse } from '@msfa-models/api/handledare.response.model';
import { Params } from '@msfa-models/api/params.model'; import { Params } from '@msfa-models/api/params.model';
import { AvropFilter, mapResponseToAvropFilter } from '@msfa-models/avrop-filter.model'; import { AvropFilter, mapResponseToAvropFilter } from '@msfa-models/avrop-filter.model';
import { AvropCompact, AvropCompactData, mapAvropResponseToAvrop } from '@msfa-models/avrop.model'; import { AvropCompact, AvropCompactData, mapAvropResponseToAvrop } from '@msfa-models/avrop.model';
import { CustomError, errorToCustomError } from '@msfa-models/error/custom-error';
import { Handledare, mapHandledareResponseToHandledare } from '@msfa-models/handledare.model'; import { Handledare, mapHandledareResponseToHandledare } from '@msfa-models/handledare.model';
import { BehaviorSubject, Observable, of } from 'rxjs'; import { BehaviorSubject, Observable, of } from 'rxjs';
import { filter, map, tap } from 'rxjs/operators'; import { catchError, filter, map, tap } from 'rxjs/operators';
@Injectable({ @Injectable({
providedIn: 'root', providedIn: 'root',
@@ -18,6 +19,8 @@ export class AvropApiService {
private _apiBaseUrl = `${environment.api.url}/avrop`; private _apiBaseUrl = `${environment.api.url}/avrop`;
private _lockedAvropSnapshot$ = new BehaviorSubject<AvropCompact[]>(null); private _lockedAvropSnapshot$ = new BehaviorSubject<AvropCompact[]>(null);
private _availableHandledareSnapshot$ = new BehaviorSubject<Handledare[]>(null); private _availableHandledareSnapshot$ = new BehaviorSubject<Handledare[]>(null);
private _showUnauthorizedError$ = new BehaviorSubject<boolean>(false);
public showUnauthorizedError$: Observable<boolean> = this._showUnauthorizedError$.asObservable();
constructor(private httpClient: HttpClient) {} constructor(private httpClient: HttpClient) {}
@@ -28,7 +31,19 @@ export class AvropApiService {
fetchAvrop$(params: Params): Observable<AvropCompactData> { fetchAvrop$(params: Params): Observable<AvropCompactData> {
return this.httpClient return this.httpClient
.get<AvropApiResponse>(`${this._apiBaseUrl}`, { params }) .get<AvropApiResponse>(`${this._apiBaseUrl}`, { params })
.pipe(map(({ data, meta }) => ({ data: data.map(avrop => mapAvropResponseToAvrop(avrop)), meta }))); .pipe(
map(({ data, meta }) => ({ data: data.map(avrop => mapAvropResponseToAvrop(avrop)), meta })),
catchError((error: Error & { status: number }) => {
if (error.status === 403) {
this._showUnauthorizedError$.next(true);
return of(null);
} else {
throw new CustomError(
errorToCustomError({ ...error, message: `Kunde inte hämta deltagare.\n\n${error.message}` })
);
}
})
);
} }
fetchAvailableHandledare$(avrop: AvropCompact[]): Observable<Handledare[]> { fetchAvailableHandledare$(avrop: AvropCompact[]): Observable<Handledare[]> {
@@ -34,6 +34,8 @@ export class DeltagareApiService {
private _apiBaseUrl = `${environment.api.url}/deltagare`; private _apiBaseUrl = `${environment.api.url}/deltagare`;
private _deltagareLoading$ = new BehaviorSubject<boolean>(false); private _deltagareLoading$ = new BehaviorSubject<boolean>(false);
public deltagareLoading$: Observable<boolean> = this._deltagareLoading$.asObservable(); public deltagareLoading$: Observable<boolean> = this._deltagareLoading$.asObservable();
private _showUnauthorizedError$ = new BehaviorSubject<boolean>(false);
public showUnauthorizedError$: Observable<boolean> = this._showUnauthorizedError$.asObservable();
constructor(private httpClient: HttpClient) {} constructor(private httpClient: HttpClient) {}
@@ -65,10 +67,15 @@ export class DeltagareApiService {
this._deltagareLoading$.next(false); this._deltagareLoading$.next(false);
return { data: data.map(deltagare => mapResponseToDeltagareCompact(deltagare)), meta }; return { data: data.map(deltagare => mapResponseToDeltagareCompact(deltagare)), meta };
}), }),
catchError((error: Error) => { catchError((error: Error & { status: number }) => {
throw new CustomError( if (error.status === 403) {
errorToCustomError({ ...error, message: `Kunde inte hämta deltagare.\n\n${error.message}` }) this._showUnauthorizedError$.next(true);
); return of(null);
} else {
throw new CustomError(
errorToCustomError({ ...error, message: `Kunde inte hämta deltagare.\n\n${error.message}` })
);
}
}) })
); );
} }
@@ -45,7 +45,7 @@ export class AvropService {
public handledareIsConfirmed$: Observable<boolean> = this._handledareIsConfirmed$.asObservable(); public handledareIsConfirmed$: Observable<boolean> = this._handledareIsConfirmed$.asObservable();
public avropIsSubmitted$: Observable<boolean> = this._avropIsSubmitted$.asObservable(); public avropIsSubmitted$: Observable<boolean> = this._avropIsSubmitted$.asObservable();
public error$: Observable<string> = this._error$.asObservable(); public error$: Observable<string> = this._error$.asObservable();
public showUnauthorizedError$: Observable<boolean> = this.avropApiService.showUnauthorizedError$;
public avropData$: Observable<AvropCompactData> = combineLatest([ public avropData$: Observable<AvropCompactData> = combineLatest([
this._filteredTjanster$, this._filteredTjanster$,
this._filteredUtforandeVerksamheter$, this._filteredUtforandeVerksamheter$,
@@ -16,6 +16,7 @@ export class DeltagareService {
public sort$: Observable<Sort<keyof DeltagareCompact>> = this._sort$.asObservable(); public sort$: Observable<Sort<keyof DeltagareCompact>> = this._sort$.asObservable();
private _onlyMyDeltagare$ = new BehaviorSubject<boolean>(false); private _onlyMyDeltagare$ = new BehaviorSubject<boolean>(false);
public onlyMyDeltagare$: Observable<boolean> = this._onlyMyDeltagare$.asObservable(); public onlyMyDeltagare$: Observable<boolean> = this._onlyMyDeltagare$.asObservable();
public showUnauthorizedError$: Observable<boolean> = this.deltagareApiService.showUnauthorizedError$;
public deltagareLoading$: Observable<boolean> = this.deltagareApiService.deltagareLoading$; public deltagareLoading$: Observable<boolean> = this.deltagareApiService.deltagareLoading$;
public allDeltagareData$: Observable<DeltagareCompactData> = combineLatest([ public allDeltagareData$: Observable<DeltagareCompactData> = combineLatest([
this._limit$, this._limit$,
@@ -3,6 +3,7 @@
### Bug Fixes ### Bug Fixes
- **deltagare:** Now fetching data using "genomforandeReferens" instead of "sokandeId" to avoid wrong data. [TV-692](https://jira.arbetsformedlingen.se/browse/TV-692) - **deltagare:** Now fetching data using "genomforandeReferens" instead of "sokandeId" to avoid wrong data. [TV-692](https://jira.arbetsformedlingen.se/browse/TV-692)
- **authorization:** Whenever the API throws a "403 Forbidden" error we now show an unauthorized message. [TV-695](https://jira.arbetsformedlingen.se/browse/TV-695)
## [2.0.0](https://bitbucket.arbetsformedlingen.se/projects/tea/repos/mina-sidor-fa-web/compare/diff?targetBranch=refs%2Ftags%2Fv1.5.0&sourceBranch=refs%2Ftags%2Fv2.0.0) (2021-09-24) ## [2.0.0](https://bitbucket.arbetsformedlingen.se/projects/tea/repos/mina-sidor-fa-web/compare/diff?targetBranch=refs%2Ftags%2Fv1.5.0&sourceBranch=refs%2Ftags%2Fv2.0.0) (2021-09-24)