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 2020e4e..3acae70 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 @@ -57,20 +57,15 @@
- - - - +

Inga handledare har behörighet till markerade deltagare

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 15e0fe2..83d04c4 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 @@ -3,6 +3,7 @@ import { DigiNgSkeletonBaseModule } from '@af/digi-ng/_skeleton/skeleton-base'; import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; +import { HandledarePickerFormModule } from '@msfa-shared/components/handledare-picker-form/handledare-picker-form.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'; @@ -22,6 +23,7 @@ import { AvropListModule } from './components/avrop-list/avrop-list.module'; DigiNgProgressProgressbarModule, DigiNgSkeletonBaseModule, LoaderModule, + HandledarePickerFormModule, UnauthorizedAlertModule, ], }) diff --git a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-card/components/deltagare-tab-personal-information/deltagare-tab-personal-information.component.html b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-card/components/deltagare-tab-personal-information/deltagare-tab-personal-information.component.html index 8da1008..446187f 100644 --- a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-card/components/deltagare-tab-personal-information/deltagare-tab-personal-information.component.html +++ b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-card/components/deltagare-tab-personal-information/deltagare-tab-personal-information.component.html @@ -26,15 +26,6 @@ {{ address.postalCode }} {{ address.city }} -
Telefon:
@@ -81,6 +72,15 @@
Tilldelad handledare:
{{ avropInformation.handledare }}
+ + +
@@ -88,3 +88,6 @@
Info saknas
+ + + diff --git a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-card/components/deltagare-tab-personal-information/deltagare-tab-personal-information.component.ts b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-card/components/deltagare-tab-personal-information/deltagare-tab-personal-information.component.ts index ba5b9b9..0abc60a 100644 --- a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-card/components/deltagare-tab-personal-information/deltagare-tab-personal-information.component.ts +++ b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-card/components/deltagare-tab-personal-information/deltagare-tab-personal-information.component.ts @@ -1,6 +1,8 @@ import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; import { Avrop } from '@msfa-models/avrop.model'; import { ContactInformation } from '@msfa-models/contact-information.model'; +import { Handledare } from '@msfa-models/handledare.model'; +import { Role } from '@msfa-models/role.model'; @Component({ selector: 'msfa-deltagare-tab-personal-information', @@ -11,4 +13,7 @@ import { ContactInformation } from '@msfa-models/contact-information.model'; export class DeltagareTabPersonalInformationComponent { @Input() contactInformation: ContactInformation; @Input() avropInformation: Avrop; + @Input() availableHandledare: Handledare[]; + @Input() userRoles: Role[]; + @Input() handledarePickerVisible: boolean; } diff --git a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-card/components/deltagare-tab-reports/deltagare-tab-reports.component.spec.ts b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-card/components/deltagare-tab-reports/deltagare-tab-reports.component.spec.ts index 27456af..e0f1ea3 100644 --- a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-card/components/deltagare-tab-reports/deltagare-tab-reports.component.spec.ts +++ b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-card/components/deltagare-tab-reports/deltagare-tab-reports.component.spec.ts @@ -1,11 +1,12 @@ +import { DigiNgFormSelectModule } from '@af/digi-ng/_form/form-select'; import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ReactiveFormsModule } from '@angular/forms'; import { RouterTestingModule } from '@angular/router/testing'; import { LoaderModule } from '@msfa-shared/components/loader/loader.module'; +import { DeltagareCardService } from '../../services/deltagare-card.service'; import { DeltagareTabReportsComponent } from './deltagare-tab-reports.component'; -import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; -import { DigiNgFormSelectModule } from '@af/digi-ng/_form/form-select'; describe('DeltagareTabReportsComponent', () => { let component: DeltagareTabReportsComponent; @@ -21,6 +22,7 @@ describe('DeltagareTabReportsComponent', () => { LoaderModule, DigiNgFormSelectModule, ], + providers: [DeltagareCardService], schemas: [CUSTOM_ELEMENTS_SCHEMA], }).compileComponents(); }); diff --git a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-card/components/deltagare-tab-reports/deltagare-tab-reports.component.ts b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-card/components/deltagare-tab-reports/deltagare-tab-reports.component.ts index f05a081..4893b1c 100644 --- a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-card/components/deltagare-tab-reports/deltagare-tab-reports.component.ts +++ b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-card/components/deltagare-tab-reports/deltagare-tab-reports.component.ts @@ -3,9 +3,9 @@ import { ChangeDetectionStrategy, Component } from '@angular/core'; import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; import { ReportsData } from '@msfa-models/reports.model'; -import { DeltagareCardService } from '@msfa-services/deltagare-card.service'; import { BehaviorSubject, combineLatest, Observable } from 'rxjs'; import { distinctUntilChanged, map, shareReplay, switchMap } from 'rxjs/operators'; +import { DeltagareCardService } from '../../services/deltagare-card.service'; @Component({ selector: 'msfa-deltagare-tab-reports', diff --git a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-card/deltagare-card.component.html b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-card/deltagare-card.component.html index ad9d54c..246e81f 100644 --- a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-card/deltagare-card.component.html +++ b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-card/deltagare-card.component.html @@ -18,6 +18,8 @@ class="deltagare-card__tab-contents" [contactInformation]="contactInformation$ | async" [avropInformation]="avropInformation$ | async" + [availableHandledare]="availableHandledare$ | async" + [handledarePickerVisible]="handledarePickerVisible" > diff --git a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-card/deltagare-card.component.spec.ts b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-card/deltagare-card.component.spec.ts index e12814f..6935444 100644 --- a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-card/deltagare-card.component.spec.ts +++ b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-card/deltagare-card.component.spec.ts @@ -4,6 +4,7 @@ import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { LayoutComponent } from '@msfa-shared/components/layout/layout.component'; import { DeltagareCardComponent } from './deltagare-card.component'; +import { DeltagareCardService } from './services/deltagare-card.service'; describe('DeltagareCardComponent', () => { let component: DeltagareCardComponent; @@ -14,6 +15,7 @@ describe('DeltagareCardComponent', () => { void TestBed.configureTestingModule({ declarations: [DeltagareCardComponent, LayoutComponent], imports: [RouterTestingModule, HttpClientTestingModule], + providers: [DeltagareCardService], schemas: [CUSTOM_ELEMENTS_SCHEMA], }).compileComponents(); }) diff --git a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-card/deltagare-card.component.ts b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-card/deltagare-card.component.ts index e240bde..c157ede 100644 --- a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-card/deltagare-card.component.ts +++ b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-card/deltagare-card.component.ts @@ -8,13 +8,15 @@ import { ContactInformation } from '@msfa-models/contact-information.model'; import { Disability } from '@msfa-models/disability.model'; import { DriversLicense } from '@msfa-models/drivers-license.model'; import { Education } from '@msfa-models/education.model'; +import { Handledare } from '@msfa-models/handledare.model'; import { HighestEducation } from '@msfa-models/highest-education.model'; import { Role } from '@msfa-models/role.model'; import { WorkExperience } from '@msfa-models/work-experience.model'; import { UserService } from '@msfa-services/api/user.service'; -import { DeltagareCardService } from '@msfa-services/deltagare-card.service'; +import { HandledareService } from '@msfa-services/handledare.service'; import { BehaviorSubject, combineLatest, Observable } from 'rxjs'; -import { distinctUntilChanged, map, shareReplay, startWith, switchMap } from 'rxjs/operators'; +import { distinctUntilChanged, filter, map, shareReplay, startWith, switchMap } from 'rxjs/operators'; +import { DeltagareCardService } from './services/deltagare-card.service'; @Component({ selector: 'msfa-deltagare-card', @@ -27,8 +29,9 @@ export class DeltagareCardComponent { private _activeTab$ = new BehaviorSubject('0'); private _userRoles: Role[] = this.userService.userRolesSnapshot; - public activeTab$: Observable = this._activeTab$.asObservable(); - public currentGenomforandeReferens$: Observable = this.activatedRoute.params.pipe( + activeTab$: Observable = this._activeTab$.asObservable(); + + currentGenomforandeReferens$: Observable = this.activatedRoute.params.pipe( map(params => params.genomforandeReferens as string), distinctUntilChanged( ([prevGenomforandeReferens], [currGenomforandeReferens]) => prevGenomforandeReferens === currGenomforandeReferens @@ -67,6 +70,11 @@ export class DeltagareCardComponent { switchMap(genomforandeReferens => this.deltagareCardService.fetchDisabilities$(genomforandeReferens)), shareReplay(1) ); + availableHandledare$: Observable = this.avropInformation$.pipe( + filter(() => !!this.handledarePickerVisible), + distinctUntilChanged((prevAvrop, currAvrop) => prevAvrop.id === currAvrop.id), + switchMap(avropInformation => this.handledareService.fetchAvailableHandledare$([avropInformation.id])) + ); tab0Loading$: Observable = combineLatest([this.contactInformation$, this.avropInformation$]).pipe( map(([contactInformation, avropInformation]) => !(contactInformation && avropInformation)), @@ -99,6 +107,9 @@ export class DeltagareCardComponent { role => role.type === RoleEnum.MSFA_ReportAndPlanning || role.type === RoleEnum.MSFA_ReceiveDeltagare ); } + get handledarePickerVisible(): boolean { + return this._userRoles?.some(role => role.type === RoleEnum.MSFA_ReceiveDeltagare); + } get reportingTabVisible(): boolean { return ( this._activeFeatures.includes(Feature.REPORTING) && @@ -118,6 +129,7 @@ export class DeltagareCardComponent { constructor( private activatedRoute: ActivatedRoute, private deltagareCardService: DeltagareCardService, + private handledareService: HandledareService, private userService: UserService ) {} diff --git a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-card/deltagare-card.module.ts b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-card/deltagare-card.module.ts index 7b8056d..0a3cfb2 100644 --- a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-card/deltagare-card.module.ts +++ b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-card/deltagare-card.module.ts @@ -7,6 +7,7 @@ import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; import { ReactiveFormsModule } from '@angular/forms'; import { RouterModule } from '@angular/router'; import { BackLinkModule } from '@msfa-shared/components/back-link/back-link.module'; +import { HandledarePickerFormModule } from '@msfa-shared/components/handledare-picker-form/handledare-picker-form.module'; import { HideTextModule } from '@msfa-shared/components/hide-text/hide-text.module'; import { LayoutModule } from '@msfa-shared/components/layout/layout.module'; import { LoaderModule } from '@msfa-shared/components/loader/loader.module'; @@ -16,6 +17,7 @@ import { DeltagareTabReportsComponent } from './components/deltagare-tab-reports import { DeltagareTabSensitiveInformationComponent } from './components/deltagare-tab-sensitive-information/deltagare-tab-sensitive-information.component'; import { ReportsModule } from './components/reports/reports.module'; import { DeltagareCardComponent } from './deltagare-card.component'; +import { DeltagareCardService } from './services/deltagare-card.service'; @NgModule({ schemas: [CUSTOM_ELEMENTS_SCHEMA], @@ -35,11 +37,13 @@ import { DeltagareCardComponent } from './deltagare-card.component'; BackLinkModule, HideTextModule, LoaderModule, + HandledarePickerFormModule, DigiNgLayoutExpansionPanelModule, DigiNgPopoverModule, DigiNgLinkButtonModule, DigiNgFormSelectModule, ], + providers: [DeltagareCardService], exports: [DeltagareCardComponent], }) export class DeltagareCardModule {} diff --git a/apps/mina-sidor-fa/src/app/shared/services/deltagare-card.service.ts b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-card/services/deltagare-card.service.ts similarity index 78% rename from apps/mina-sidor-fa/src/app/shared/services/deltagare-card.service.ts rename to apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-card/services/deltagare-card.service.ts index 9e7f649..56414f4 100644 --- a/apps/mina-sidor-fa/src/app/shared/services/deltagare-card.service.ts +++ b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-card/services/deltagare-card.service.ts @@ -7,20 +7,24 @@ import { Education } from '@msfa-models/education.model'; import { HighestEducation } from '@msfa-models/highest-education.model'; import { ReportsData } from '@msfa-models/reports.model'; import { WorkExperience } from '@msfa-models/work-experience.model'; +import { DeltagareApiService } from '@msfa-services/api/deltagare.api.service'; +import { HandledareService } from '@msfa-services/handledare.service'; import { Observable } from 'rxjs'; -import { DeltagareApiService } from './api/deltagare.api.service'; +import { mapTo, switchMap } from 'rxjs/operators'; -@Injectable({ - providedIn: 'root', -}) +@Injectable() export class DeltagareCardService { - constructor(private deltagareApiService: DeltagareApiService) {} + avropNeedsUpdate$: Observable = this.handledareService.lastSavedHandledare$.pipe(mapTo(undefined as void)); + + constructor(private deltagareApiService: DeltagareApiService, private handledareService: HandledareService) {} public fetchContactInformation$(genomforandeReferens: number): Observable { return this.deltagareApiService.fetchContactInformation$(genomforandeReferens); } public fetchAvropInformation$(genomforandeReferens: number): Observable { - return this.deltagareApiService.fetchAvropInformation$(genomforandeReferens); + return this.avropNeedsUpdate$.pipe( + switchMap(() => this.deltagareApiService.fetchAvropInformation$(genomforandeReferens)) + ); } public fetchWorkExperiences$(genomforandeReferens: number): Observable { return this.deltagareApiService.fetchWorkExperiences$(genomforandeReferens); diff --git a/apps/mina-sidor-fa/src/app/shared/components/handledare-picker-form/handledare-picker-form.component.html b/apps/mina-sidor-fa/src/app/shared/components/handledare-picker-form/handledare-picker-form.component.html new file mode 100644 index 0000000..98a4129 --- /dev/null +++ b/apps/mina-sidor-fa/src/app/shared/components/handledare-picker-form/handledare-picker-form.component.html @@ -0,0 +1,35 @@ +
+ + + + {{submitText}} + + + +
diff --git a/apps/mina-sidor-fa/src/app/shared/components/handledare-picker-form/handledare-picker-form.component.scss b/apps/mina-sidor-fa/src/app/shared/components/handledare-picker-form/handledare-picker-form.component.scss new file mode 100644 index 0000000..5383fe7 --- /dev/null +++ b/apps/mina-sidor-fa/src/app/shared/components/handledare-picker-form/handledare-picker-form.component.scss @@ -0,0 +1,35 @@ +@import 'variables/gutters'; + +.handledare-picker-form { + position: relative; + display: grid; + grid-template-columns: 1fr auto; + column-gap: $digi--layout--gutter; + row-gap: $digi--layout--gutter--s; + grid-template-areas: + 'select select' + 'validation validation' + 'submit .'; + + &__select { + grid-area: select; + } + + &__submit { + grid-area: submit; + align-self: end; + } + + &__validation-wrapper { + grid-area: validation; + } + + &__validation-message { + display: block; + margin-bottom: $digi--layout--gutter--s; + } + + ::ng-deep .digi-ng-form-select__footer { + display: none !important; + } +} diff --git a/apps/mina-sidor-fa/src/app/shared/components/handledare-picker-form/handledare-picker-form.component.spec.ts b/apps/mina-sidor-fa/src/app/shared/components/handledare-picker-form/handledare-picker-form.component.spec.ts new file mode 100644 index 0000000..34b4386 --- /dev/null +++ b/apps/mina-sidor-fa/src/app/shared/components/handledare-picker-form/handledare-picker-form.component.spec.ts @@ -0,0 +1,29 @@ +import { DigiNgFormSelectModule } from '@af/digi-ng/_form/form-select'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { HandledarePickerFormComponent } from './handledare-picker-form.component'; + +describe('HandledarePickerFormComponent', () => { + let component: HandledarePickerFormComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ReactiveFormsModule, HttpClientTestingModule, FormsModule, DigiNgFormSelectModule], + declarations: [HandledarePickerFormComponent], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(HandledarePickerFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/apps/mina-sidor-fa/src/app/shared/components/handledare-picker-form/handledare-picker-form.component.ts b/apps/mina-sidor-fa/src/app/shared/components/handledare-picker-form/handledare-picker-form.component.ts new file mode 100644 index 0000000..7ff599f --- /dev/null +++ b/apps/mina-sidor-fa/src/app/shared/components/handledare-picker-form/handledare-picker-form.component.ts @@ -0,0 +1,77 @@ +import { FormSelectItem } from '@af/digi-ng/_form/form-select'; +import { + ChangeDetectionStrategy, + Component, + EventEmitter, + Input, + OnChanges, + Output, + SimpleChanges, +} from '@angular/core'; +import { AbstractControl, FormControl, FormGroup } from '@angular/forms'; +import { Handledare } from '@msfa-models/handledare.model'; +import { HandledareService } from '@msfa-services/handledare.service'; +import { RequiredValidator } from '@msfa-utils/validators/required.validator'; +import { Observable } from 'rxjs'; + +@Component({ + selector: 'msfa-handledare-picker-form', + templateUrl: './handledare-picker-form.component.html', + styleUrls: ['./handledare-picker-form.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class HandledarePickerFormComponent implements OnChanges { + @Input() selectedHandledareId: string; + @Input() handledare: Handledare[]; + @Input() avropIds: string[]; + @Input() label = 'Välj handledare'; + @Input() submitText = 'Spara handledare'; + @Input() skipSubmit = false; + @Input() invalid = false; + @Output() selectedHandledareChanged = new EventEmitter(); + formGroup: FormGroup = new FormGroup({ + handledare: new FormControl(null, [RequiredValidator('Handledare')]), + }); + selectableHandledare: FormSelectItem[] = []; + submitted = false; + lastSavedHandledare$: Observable = this.handledareService.lastSavedHandledare$; + submitHandledareLoading$: Observable = this.handledareService.submitHandledareLoading$; + + constructor(private handledareService: HandledareService) {} + + ngOnChanges(changes: SimpleChanges): void { + if (changes.selectedHandledareId) { + this.handledareFormControl.patchValue(this.selectedHandledareId); + } + if (changes.handledare && this.handledare?.length) { + this.selectableHandledare = this.handledare.map(({ ciamUserId, fullName }) => ({ + name: fullName, + value: ciamUserId, + })); + } + } + + get handledareFormControl(): AbstractControl { + return this.formGroup.get('handledare'); + } + + handledareChanged(): void { + this.submitted = false; + this.selectedHandledareChanged.emit(this.handledareFormControl.value); + } + + onFormSubmitted(): void { + this.submitted = true; + this.formGroup.markAllAsTouched(); + + if (this.formGroup.invalid || this.handledareFormControl.value === this.selectedHandledareId) { + return; + } + + const newHandledare = this.handledare.find( + handledare => handledare.ciamUserId === this.handledareFormControl.value + ); + + this.handledareService.assignHandledare(this.avropIds, newHandledare); + } +} diff --git a/apps/mina-sidor-fa/src/app/shared/components/handledare-picker-form/handledare-picker-form.module.ts b/apps/mina-sidor-fa/src/app/shared/components/handledare-picker-form/handledare-picker-form.module.ts new file mode 100644 index 0000000..742ea47 --- /dev/null +++ b/apps/mina-sidor-fa/src/app/shared/components/handledare-picker-form/handledare-picker-form.module.ts @@ -0,0 +1,14 @@ +import { DigiNgFormSelectModule } from '@af/digi-ng/_form/form-select'; +import { CommonModule } from '@angular/common'; +import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; +import { ReactiveFormsModule } from '@angular/forms'; +import { LoaderModule } from '../loader/loader.module'; +import { HandledarePickerFormComponent } from './handledare-picker-form.component'; + +@NgModule({ + schemas: [CUSTOM_ELEMENTS_SCHEMA], + declarations: [HandledarePickerFormComponent], + imports: [CommonModule, ReactiveFormsModule, LoaderModule, DigiNgFormSelectModule], + exports: [HandledarePickerFormComponent], +}) +export class HandledarePickerFormModule {} diff --git a/apps/mina-sidor-fa/src/app/shared/components/loader/loader.component.html b/apps/mina-sidor-fa/src/app/shared/components/loader/loader.component.html index 7ff866f..889ea9a 100644 --- a/apps/mina-sidor-fa/src/app/shared/components/loader/loader.component.html +++ b/apps/mina-sidor-fa/src/app/shared/components/loader/loader.component.html @@ -1,3 +1,3 @@ -
- +
+
diff --git a/apps/mina-sidor-fa/src/app/shared/components/loader/loader.component.scss b/apps/mina-sidor-fa/src/app/shared/components/loader/loader.component.scss index 70aa16a..850c27d 100644 --- a/apps/mina-sidor-fa/src/app/shared/components/loader/loader.component.scss +++ b/apps/mina-sidor-fa/src/app/shared/components/loader/loader.component.scss @@ -28,5 +28,9 @@ &__spinner { display: inline-flex; animation: spinning 1s linear infinite; + + &--s { + width: 2.5rem; + } } } diff --git a/apps/mina-sidor-fa/src/app/shared/components/loader/loader.component.ts b/apps/mina-sidor-fa/src/app/shared/components/loader/loader.component.ts index 0a4b831..279ddef 100644 --- a/apps/mina-sidor-fa/src/app/shared/components/loader/loader.component.ts +++ b/apps/mina-sidor-fa/src/app/shared/components/loader/loader.component.ts @@ -10,11 +10,16 @@ import { LoaderType } from '@msfa-enums/loader-type.enum'; export class LoaderComponent { private readonly _defaultClass = 'loader'; @Input() type: LoaderType; + @Input() size: 's' | 'm' = 'm'; - get classes(): string { + get loaderClass(): string { if (this.type) { return `${this._defaultClass} ${this._defaultClass}--${this.type as string}`; } return this._defaultClass; } + + get spinnerClass(): string { + return `${this._defaultClass}__spinner ${this._defaultClass}__spinner--${this.size}`; + } } diff --git a/apps/mina-sidor-fa/src/app/shared/models/avrop.model.ts b/apps/mina-sidor-fa/src/app/shared/models/avrop.model.ts index cb04f72..6e55df1 100644 --- a/apps/mina-sidor-fa/src/app/shared/models/avrop.model.ts +++ b/apps/mina-sidor-fa/src/app/shared/models/avrop.model.ts @@ -41,7 +41,6 @@ export function mapAvropResponseToAvrop(data: AvropResponse): Avrop { sprakstod, adress, sparkod, - sparNamn, genomforandeReferens, deltagandeGrad, utforandeverksamhet, 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 aed50ae..17d08d3 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 @@ -3,14 +3,13 @@ import { Injectable } from '@angular/core'; import { environment } from '@msfa-environment'; import { AvropFilterResponse } from '@msfa-models/api/avrop-filter.response.model'; import { AvropApiResponse } from '@msfa-models/api/avrop.response.model'; -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 { Handledare } from '@msfa-models/handledare.model'; import { BehaviorSubject, Observable, of } from 'rxjs'; -import { catchError, filter, map, tap } from 'rxjs/operators'; +import { catchError, filter, map } from 'rxjs/operators'; @Injectable({ providedIn: 'root', @@ -46,30 +45,6 @@ export class AvropApiService { ); } - fetchAvailableHandledare$(avrop: AvropCompact[]): Observable { - const lockedAvropIsEqual = this.lockedAvropValue?.every( - (lockedAvrop, index) => lockedAvrop.id === avrop[index]?.id - ); - - // Checking to see if we really need to make a new api-request - if (lockedAvropIsEqual) { - return of(this._availableHandledareSnapshot$.getValue()); - } - - this._lockedAvropSnapshot$.next(avrop); - - return this.httpClient - .get<{ data: HandledareResponse[] }>(`${this._apiBaseUrl}/handledare`, { - params: { avropIds: avrop.map(a => a.id) }, - }) - .pipe( - map(({ data }) => data.map(handledare => mapHandledareResponseToHandledare(handledare))), - tap(handledare => { - this._availableHandledareSnapshot$.next(handledare); - }) - ); - } - fetchAvailableTjanster$(params: Params): Observable { return this.httpClient .get<{ data: AvropFilterResponse[] }>(`${this._apiBaseUrl}/tjanster`, { params }) diff --git a/apps/mina-sidor-fa/src/app/shared/services/api/handledare.api.service.ts b/apps/mina-sidor-fa/src/app/shared/services/api/handledare.api.service.ts new file mode 100644 index 0000000..a11fa97 --- /dev/null +++ b/apps/mina-sidor-fa/src/app/shared/services/api/handledare.api.service.ts @@ -0,0 +1,43 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { environment } from '@msfa-environment'; +import { HandledareResponse } from '@msfa-models/api/handledare.response.model'; +import { Params } from '@msfa-models/api/params.model'; +import { CustomError, errorToCustomError } from '@msfa-models/error/custom-error'; +import { Handledare, mapHandledareResponseToHandledare } from '@msfa-models/handledare.model'; +import { Observable } from 'rxjs'; +import { catchError, map } from 'rxjs/operators'; + +@Injectable({ + providedIn: 'root', +}) +export class HandledareApiService { + private _apiBaseUrl = `${environment.api.url}/avrop/handledare`; + + constructor(private httpClient: HttpClient) {} + + public fetchAvailableHandledare$(avropIds: string[]): Observable { + return this.httpClient + .get<{ data: HandledareResponse[] }>(`${this._apiBaseUrl}`, { + params: { avropIds }, + }) + .pipe( + map(({ data }) => data.map(handledare => mapHandledareResponseToHandledare(handledare))), + catchError((error: Error) => { + throw new CustomError( + errorToCustomError({ ...error, message: `Kunde inte hämta handledare.\n\n${error.message}` }) + ); + }) + ); + } + + async assignHandledare(avropIds: string[], handledare: Handledare): Promise { + const params: Params = { + avropIds, + ciamUserId: handledare.ciamUserId, + }; + return this.httpClient + .patch(`${this._apiBaseUrl}/assign`, null, { params }) + .toPromise(); + } +} 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 05c4fd0..9b75ee9 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 @@ -6,6 +6,7 @@ import { AvropApiService } from '@msfa-services/api/avrop-api.service'; import { MultiselectFilterOption } from '@msfa-shared/components/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'; type Step = 1 | 2 | 3 | 4; @@ -103,7 +104,9 @@ export class AvropService { public availableHandledare$: Observable = this._lockedAvrop$.pipe( filter(lockedAvrop => !!lockedAvrop?.length), - switchMap(lockedAvrop => this.avropApiService.fetchAvailableHandledare$(lockedAvrop)) + map(lockedAvrop => lockedAvrop.map(avrop => avrop.id)), + switchMap(lockedAvrop => this.handledareApiService.fetchAvailableHandledare$(lockedAvrop)), + shareReplay(1) ); public currentStep$: Observable = combineLatest([ @@ -194,7 +197,7 @@ export class AvropService { this._selectedAvrop$.next(deltagare); } - constructor(private avropApiService: AvropApiService) {} + constructor(private avropApiService: AvropApiService, private handledareApiService: HandledareApiService) {} public resetError(): void { this._error$.next(null); diff --git a/apps/mina-sidor-fa/src/app/shared/services/handledare.service.ts b/apps/mina-sidor-fa/src/app/shared/services/handledare.service.ts new file mode 100644 index 0000000..0dfbf73 --- /dev/null +++ b/apps/mina-sidor-fa/src/app/shared/services/handledare.service.ts @@ -0,0 +1,43 @@ +import { Injectable } from '@angular/core'; +import { errorToCustomError } from '@msfa-models/error/custom-error'; +import { Handledare } from '@msfa-models/handledare.model'; +import { BehaviorSubject, Observable } from 'rxjs'; +import { HandledareApiService } from './api/handledare.api.service'; +import { ErrorService } from './error.service'; + +@Injectable({ + providedIn: 'root', +}) +export class HandledareService { + private _lastSavedHandledare$ = new BehaviorSubject(null); + public lastSavedHandledare$: Observable = this._lastSavedHandledare$.asObservable(); + private _submitHandledareLoading$ = new BehaviorSubject(false); + public submitHandledareLoading$: Observable = this._submitHandledareLoading$.asObservable(); + + constructor(private handledareApiService: HandledareApiService, private errorService: ErrorService) {} + + public resetLastSavedHandledare(): void { + this._lastSavedHandledare$.next(null); + } + + public fetchAvailableHandledare$(avropIds: string[]): Observable { + return this.handledareApiService.fetchAvailableHandledare$(avropIds); + } + + public assignHandledare(avropIds: string[], handledare: Handledare): void { + this._submitHandledareLoading$.next(true); + this.handledareApiService + .assignHandledare(avropIds, handledare) + .then(() => { + this._lastSavedHandledare$.next(handledare); + }) + .catch((error: Error) => { + this.errorService.add( + errorToCustomError({ ...error, message: `Kunde inte tilldela handledare.\n\n${error.message}` }) + ); + }) + .finally(() => { + this._submitHandledareLoading$.next(false); + }); + } +}