diff --git a/CHANGELOG.md b/CHANGELOG.md index 0101a51..12cd822 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### Bug Fixes - **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) diff --git a/apps/mina-sidor-fa/src/app/pages/avrop/avrop.component.html b/apps/mina-sidor-fa/src/app/pages/avrop/avrop.component.html index ed58f5c..137d150 100644 --- a/apps/mina-sidor-fa/src/app/pages/avrop/avrop.component.html +++ b/apps/mina-sidor-fa/src/app/pages/avrop/avrop.component.html @@ -1,131 +1,143 @@ -
- -
-

Nya deltagare

-

- Här ser du alla nya deltagare. Deltagarna ska tilldelas en handledare innan tjänstens start. Kryssa för de - deltagare du vill tilldela en handledare. Du kan välja en, eller flera personer samtidigt, genom att kryssa i - boxarna nedan. -

+ + + +
+
+

Nya deltagare

+

+ Här ser du alla nya deltagare. Deltagarna ska tilldelas en handledare innan tjänstens start. Kryssa för de + deltagare du vill tilldela en handledare. Du kan välja en, eller flera personer samtidigt, genom att + kryssa i boxarna nedan. +

- -

Tilldelningen är nu skickad till {{selectedHandledare.fullName}}.

-
-
- -
-
-

- - Välj deltagare att tilldela - Tilldela handledare - Förehandsgranska och tilldela - Tilldelade delgare - -

- -
- Steg {{ currentStep }} av {{ totalAmountOfSteps }}: - -
-
- -
-
-

Filter

- -
-
- - - - - - -

Inga handledare har behörighet till markerade deltagare

-
-
-
- -

Välj deltagare att tilldela handledare

- -
- -
-
- - Nästa - - - Tillbaka - Tilldela - - - Tillbaka - Bekräfta tilldelning - - - Tillbaka till nya deltagare - +
+
+

+ + Välj deltagare att tilldela + Tilldela handledare + Förehandsgranska och tilldela + Tilldelade delgare + +

+ +
+ Steg {{ currentStep }} av {{ totalAmountOfSteps }}: + +
-
- - -
-
+
+
+

Filter

+ +
+
+ + + + - - - - - - - -

Det finns för tillfället inga nya deltagare att tilldela.

-
+ +

Inga handledare har behörighet till markerade deltagare

+
+
+
+ +

Välj deltagare att tilldela handledare

+ +
+ + + + + + +
+ + + + + + + + + + + + + + +

Det finns för tillfället inga nya deltagare att tilldela.

+
+ + + + 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 256e889..c466bcb 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 @@ -13,7 +13,6 @@ import { Observable } from 'rxjs'; export class AvropComponent { readonly totalAmountOfSteps = 3; currentStep$: Observable = this.avropService.currentStep$; - error$: Observable = this.avropService.error$; avropData$: Observable = this.avropService.avropData$; selectedAvrop$: Observable = this.avropService.selectedAvrop$; @@ -23,6 +22,7 @@ export class AvropComponent { handledareConfirmed$: Observable = this.avropService.handledareIsConfirmed$; avropIsSubmitted$: Observable = this.avropService.avropIsSubmitted$; avropLoading$: Observable = this.avropService.avropLoading$; + showUnauthorizedError$: Observable = this.avropService.showUnauthorizedError$; constructor(private avropService: AvropService) {} diff --git a/apps/mina-sidor-fa/src/app/pages/avrop/avrop.module.ts b/apps/mina-sidor-fa/src/app/pages/avrop/avrop.module.ts index 615c24c..15e0fe2 100644 --- a/apps/mina-sidor-fa/src/app/pages/avrop/avrop.module.ts +++ b/apps/mina-sidor-fa/src/app/pages/avrop/avrop.module.ts @@ -4,10 +4,11 @@ import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; 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 { AvropFiltersModule } from './components/avrop-filters/avrop-filters.module'; import { AvropListModule } from './components/avrop-list/avrop-list.module'; -import { LoaderModule } from '@msfa-shared/components/loader/loader.module'; @NgModule({ schemas: [CUSTOM_ELEMENTS_SCHEMA], @@ -21,6 +22,7 @@ import { LoaderModule } from '@msfa-shared/components/loader/loader.module'; DigiNgProgressProgressbarModule, DigiNgSkeletonBaseModule, LoaderModule, + UnauthorizedAlertModule, ], }) export class AvropModule {} diff --git a/apps/mina-sidor-fa/src/app/pages/deltagare/deltagare.component.html b/apps/mina-sidor-fa/src/app/pages/deltagare/deltagare.component.html index 9400755..5340bad 100644 --- a/apps/mina-sidor-fa/src/app/pages/deltagare/deltagare.component.html +++ b/apps/mina-sidor-fa/src/app/pages/deltagare/deltagare.component.html @@ -1,23 +1,23 @@ -
-
-

Deltagarlista

-

- Här ser du en lista på de deltagare som tillhör din organisation. Klicka på deltagarens namn för att öppna och - se mer information om deltagarna. -

-
-
- -
- - + +
+
+

Deltagarlista

+

+ Här ser du en lista på de deltagare som tillhör din organisation. Klicka på deltagarens namn för att öppna + och se mer information om deltagarna. +

+
+
+ +
+ {{showUnauthorizedError$ | async}} - - - - - -
+
+
+ + + +

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.' }}

+ + + + diff --git a/apps/mina-sidor-fa/src/app/pages/deltagare/deltagare.component.ts b/apps/mina-sidor-fa/src/app/pages/deltagare/deltagare.component.ts index 2e7710a..06202a7 100644 --- a/apps/mina-sidor-fa/src/app/pages/deltagare/deltagare.component.ts +++ b/apps/mina-sidor-fa/src/app/pages/deltagare/deltagare.component.ts @@ -15,6 +15,7 @@ export class DeltagareComponent { sort$: Observable> = this.deltagareService.sort$; onlyMyDeltagare$: Observable = this.deltagareService.onlyMyDeltagare$; deltagareLoading$: Observable = this.deltagareService.deltagareLoading$; + showUnauthorizedError$: Observable = this.deltagareService.showUnauthorizedError$; constructor(private deltagareService: DeltagareService) {} diff --git a/apps/mina-sidor-fa/src/app/pages/deltagare/deltagare.module.ts b/apps/mina-sidor-fa/src/app/pages/deltagare/deltagare.module.ts index 2a2a29d..91f9d44 100644 --- a/apps/mina-sidor-fa/src/app/pages/deltagare/deltagare.module.ts +++ b/apps/mina-sidor-fa/src/app/pages/deltagare/deltagare.module.ts @@ -1,14 +1,22 @@ +import { DigiNgSkeletonBaseModule } from '@af/digi-ng/_skeleton/skeleton-base'; import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; 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 { DeltagareRoutingModule } from './deltagare-routing.module'; import { DeltagareComponent } from './deltagare.component'; -import { DigiNgSkeletonBaseModule } from '@af/digi-ng/_skeleton/skeleton-base'; @NgModule({ schemas: [CUSTOM_ELEMENTS_SCHEMA], declarations: [DeltagareComponent], - imports: [CommonModule, DeltagareRoutingModule, LayoutModule, DeltagareListModule, DigiNgSkeletonBaseModule], + imports: [ + CommonModule, + DeltagareRoutingModule, + LayoutModule, + DeltagareListModule, + UnauthorizedAlertModule, + DigiNgSkeletonBaseModule, + ], }) export class DeltagareModule {} diff --git a/apps/mina-sidor-fa/src/app/shared/components/unauthorized-alert/unauthorized-alert.component.html b/apps/mina-sidor-fa/src/app/shared/components/unauthorized-alert/unauthorized-alert.component.html new file mode 100644 index 0000000..d331c87 --- /dev/null +++ b/apps/mina-sidor-fa/src/app/shared/components/unauthorized-alert/unauthorized-alert.component.html @@ -0,0 +1,7 @@ + +

+ 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. +

+
diff --git a/apps/mina-sidor-fa/src/app/shared/components/unauthorized-alert/unauthorized-alert.component.scss b/apps/mina-sidor-fa/src/app/shared/components/unauthorized-alert/unauthorized-alert.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/apps/mina-sidor-fa/src/app/shared/components/unauthorized-alert/unauthorized-alert.component.spec.ts b/apps/mina-sidor-fa/src/app/shared/components/unauthorized-alert/unauthorized-alert.component.spec.ts new file mode 100644 index 0000000..2db903b --- /dev/null +++ b/apps/mina-sidor-fa/src/app/shared/components/unauthorized-alert/unauthorized-alert.component.spec.ts @@ -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; + + 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(); + }); +}); diff --git a/apps/mina-sidor-fa/src/app/shared/components/unauthorized-alert/unauthorized-alert.component.ts b/apps/mina-sidor-fa/src/app/shared/components/unauthorized-alert/unauthorized-alert.component.ts new file mode 100644 index 0000000..bed312a --- /dev/null +++ b/apps/mina-sidor-fa/src/app/shared/components/unauthorized-alert/unauthorized-alert.component.ts @@ -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 {} diff --git a/apps/mina-sidor-fa/src/app/shared/components/unauthorized-alert/unauthorized-alert.module.ts b/apps/mina-sidor-fa/src/app/shared/components/unauthorized-alert/unauthorized-alert.module.ts new file mode 100644 index 0000000..9f62dc4 --- /dev/null +++ b/apps/mina-sidor-fa/src/app/shared/components/unauthorized-alert/unauthorized-alert.module.ts @@ -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 {} 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 340863b..4bc39fd 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 @@ -7,9 +7,10 @@ import { HandledareResponse } from '@msfa-models/api/handledare.response.model'; import { Params } from '@msfa-models/api/params.model'; import { AvropFilter, mapResponseToAvropFilter } from '@msfa-models/avrop-filter.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 { BehaviorSubject, Observable, of } from 'rxjs'; -import { filter, map, tap } from 'rxjs/operators'; +import { catchError, filter, map, tap } from 'rxjs/operators'; @Injectable({ providedIn: 'root', @@ -18,6 +19,8 @@ export class AvropApiService { private _apiBaseUrl = `${environment.api.url}/avrop`; private _lockedAvropSnapshot$ = new BehaviorSubject(null); private _availableHandledareSnapshot$ = new BehaviorSubject(null); + private _showUnauthorizedError$ = new BehaviorSubject(false); + public showUnauthorizedError$: Observable = this._showUnauthorizedError$.asObservable(); constructor(private httpClient: HttpClient) {} @@ -28,7 +31,19 @@ export class AvropApiService { fetchAvrop$(params: Params): Observable { return this.httpClient .get(`${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 { 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 6b576a5..bb9ce68 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 @@ -34,6 +34,8 @@ export class DeltagareApiService { private _apiBaseUrl = `${environment.api.url}/deltagare`; private _deltagareLoading$ = new BehaviorSubject(false); public deltagareLoading$: Observable = this._deltagareLoading$.asObservable(); + private _showUnauthorizedError$ = new BehaviorSubject(false); + public showUnauthorizedError$: Observable = this._showUnauthorizedError$.asObservable(); constructor(private httpClient: HttpClient) {} @@ -65,10 +67,15 @@ export class DeltagareApiService { this._deltagareLoading$.next(false); return { data: data.map(deltagare => mapResponseToDeltagareCompact(deltagare)), meta }; }), - catchError((error: Error) => { - throw new CustomError( - errorToCustomError({ ...error, message: `Kunde inte hämta deltagare.\n\n${error.message}` }) - ); + 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}` }) + ); + } }) ); } 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 33e883e..3a2bbe0 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 @@ -45,7 +45,7 @@ export class AvropService { public handledareIsConfirmed$: Observable = this._handledareIsConfirmed$.asObservable(); public avropIsSubmitted$: Observable = this._avropIsSubmitted$.asObservable(); public error$: Observable = this._error$.asObservable(); - + public showUnauthorizedError$: Observable = this.avropApiService.showUnauthorizedError$; public avropData$: Observable = combineLatest([ this._filteredTjanster$, this._filteredUtforandeVerksamheter$, diff --git a/apps/mina-sidor-fa/src/app/shared/services/deltagare.service.ts b/apps/mina-sidor-fa/src/app/shared/services/deltagare.service.ts index e415d04..1f39dea 100644 --- a/apps/mina-sidor-fa/src/app/shared/services/deltagare.service.ts +++ b/apps/mina-sidor-fa/src/app/shared/services/deltagare.service.ts @@ -16,6 +16,7 @@ export class DeltagareService { public sort$: Observable> = this._sort$.asObservable(); private _onlyMyDeltagare$ = new BehaviorSubject(false); public onlyMyDeltagare$: Observable = this._onlyMyDeltagare$.asObservable(); + public showUnauthorizedError$: Observable = this.deltagareApiService.showUnauthorizedError$; public deltagareLoading$: Observable = this.deltagareApiService.deltagareLoading$; public allDeltagareData$: Observable = combineLatest([ this._limit$, diff --git a/apps/mina-sidor-fa/src/assets/CHANGELOG.md b/apps/mina-sidor-fa/src/assets/CHANGELOG.md index 0101a51..12cd822 100644 --- a/apps/mina-sidor-fa/src/assets/CHANGELOG.md +++ b/apps/mina-sidor-fa/src/assets/CHANGELOG.md @@ -3,6 +3,7 @@ ### Bug Fixes - **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)