From e6f80901eae878c78d6416e597fc88bfa63c77aa Mon Sep 17 00:00:00 2001 From: Erik Tiekstra Date: Fri, 20 Aug 2021 11:01:23 +0200 Subject: [PATCH] feat(employee): Showing employee-data inside employee-card page. (TV-341) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Squashed commit of the following: commit 4fd71e0d0655a0d75dda59151ac74e2361f187bc Author: Erik Tiekstra Date: Fri Aug 20 10:59:46 2021 +0200 Updated RoleEnum and mock-data för roles commit f05a93239727ce1245650ece3b48cf75dc7091ca Author: Erik Tiekstra Date: Fri Aug 20 08:34:20 2021 +0200 Fixed issue with mock-api commit c31e94da6b90e442fd84c5113789db245be81c6d Author: Erik Tiekstra Date: Fri Aug 20 08:26:14 2021 +0200 Fixed issue with tjanster commit a183a08f0446cdaea7d01c8935d88ac436b0438f Merge: eb310c1 1e2d925 Author: Erik Tiekstra Date: Fri Aug 20 07:59:06 2021 +0200 Merge branch 'develop' into feature/TV-341-erik commit eb310c10bdf0f4b60032bdda97df75c19bdbf447 Merge: 877b68b fae7d9a Author: Erik Tiekstra Date: Fri Aug 20 07:21:39 2021 +0200 Merged develop and fixed conflicts commit 877b68b8827e89cfd230856c9d8247f1cd8db264 Author: Erik Tiekstra Date: Thu Aug 19 15:01:55 2021 +0200 Now fetching tjanster from mock-api commit 1ecd26595b21ea46ce6fb0c193c6642f66250ae3 Author: Erik Tiekstra Date: Thu Aug 19 14:24:11 2021 +0200 Some more changes to employee-card commit e42ae254e7aa7b994627fdccb7037493b116d6a2 Author: Erik Tiekstra Date: Thu Aug 19 13:44:23 2021 +0200 Added new enum Role and fixed some issues mapping roles inside employee-card commit 7801831d83feae5ef5e5b92e6421b18863b2a1db Merge: c78f3f8 d6e4666 Author: Erik Tiekstra Date: Thu Aug 19 12:37:56 2021 +0200 Merge branch 'develop' into feature/TV-341-fe-anpassa-personal-kortet-sa-att-den-ar-enligt-skiss commit c78f3f886752477d2dbc4af20356252af4128440 Author: WP\holno Date: Thu Aug 19 11:19:56 2021 +0200 Authorization commit 9c043720a9cfa5fd6943013f643d948a50c8f135 Merge: 77d6a9c ffeb372 Author: WP\holno Date: Thu Aug 19 11:19:43 2021 +0200 Merge branch 'develop' into feature/TV-341-fe-anpassa-personal-kortet-sa-att-den-ar-enligt-skiss # Conflicts: # apps/mina-sidor-fa/src/app/pages/administration/pages/employee-card/employee-card.component.scss # apps/mina-sidor-fa/src/app/pages/administration/pages/employee-card/employee-card.module.ts # apps/mina-sidor-fa/src/app/shared/enums/employee-authorization.enum.ts commit 77d6a9c600e6b42e97fa5431ed37ad430c5febd3 Author: WP\holno Date: Wed Aug 18 10:22:45 2021 +0200 Moved subscription, added icons, refactured markup commit b43c18e28b5aabb8115fa659a98b4ae8c0a7bf40 Author: WP\holno Date: Tue Aug 17 10:50:02 2021 +0200 unsubscribed commit 9f48cddc75872fc3f740c53de998cd54666b0b1d Author: WP\holno Date: Mon Aug 16 16:40:08 2021 +0200 Unsubscription behöver läggas till efter genomgång av hur unsubscribeOnDestroy fungerar commit b2cef346f18482e72c11c09d0a6e629370d01bd5 Author: WP\holno Date: Mon Aug 16 16:37:13 2021 +0200 Authorization commit 5fe0b5d5fc725551f9e794cbaa70dc0f077f8717 Author: WP\holno Date: Fri Aug 13 15:46:50 2021 +0200 - Changed first h2 to h3 - Changed link to routerLink commit fd1cb3c6249535ce84e61df035cae63352b1b00b Author: WP\holno Date: Fri Aug 13 11:53:36 2021 +0200 Amends after PR commit 13e9881e3680bd829736205b3fef57b2228638d5 Author: WP\holno Date: Wed Aug 11 16:19:36 2021 +0200 Employee-card amends to look more like the sketch. --- .../employee-card.component.html | 112 +++++++++--------- .../employee-card.component.scss | 97 +++++++-------- .../employee-card/employee-card.component.ts | 35 ++---- .../employee-card/employee-card.module.ts | 2 + .../employee-form/employee-form.component.ts | 29 ++--- .../src/app/shared/enums/role.enum.ts | 7 ++ .../models/api/avrop-tjanst.response.model.ts | 4 + .../models/api/employee.response.model.ts | 7 +- .../models/api/tjanst.response.model.ts | 4 +- .../app/shared/models/avrop-tjanst.model.ts | 15 +++ .../src/app/shared/models/employee.model.ts | 23 ++-- .../src/app/shared/models/role.model.ts | 6 + .../src/app/shared/models/tjanst.model.ts | 12 +- .../shared/services/api/avrop-api.service.ts | 8 +- .../shared/services/api/employee.service.ts | 71 +++++++++-- .../app/shared/services/api/tjanst.service.ts | 38 ++++++ .../src/styles/mixins/_buttons.scss | 2 +- .../mina-sidor-fa/scripts/authorizations.js | 2 +- mock-api/mina-sidor-fa/scripts/employees.js | 9 +- .../mina-sidor-fa/scripts/generate-api.js | 13 +- mock-api/mina-sidor-fa/scripts/tjanster.js | 24 ++-- mock-api/mina-sidor-fa/server.js | 4 +- 22 files changed, 307 insertions(+), 217 deletions(-) create mode 100644 apps/mina-sidor-fa/src/app/shared/enums/role.enum.ts create mode 100644 apps/mina-sidor-fa/src/app/shared/models/api/avrop-tjanst.response.model.ts create mode 100644 apps/mina-sidor-fa/src/app/shared/models/avrop-tjanst.model.ts create mode 100644 apps/mina-sidor-fa/src/app/shared/models/role.model.ts create mode 100644 apps/mina-sidor-fa/src/app/shared/services/api/tjanst.service.ts diff --git a/apps/mina-sidor-fa/src/app/pages/administration/pages/employee-card/employee-card.component.html b/apps/mina-sidor-fa/src/app/pages/administration/pages/employee-card/employee-card.component.html index 20cd534..9b1b58c 100644 --- a/apps/mina-sidor-fa/src/app/pages/administration/pages/employee-card/employee-card.component.html +++ b/apps/mina-sidor-fa/src/app/pages/administration/pages/employee-card/employee-card.component.html @@ -1,93 +1,97 @@
- -
-

{{ detailedEmployeeData.fullName }}

- - Redigera - -
- -

- Lorem ipsum dolor sit amet consectetur adipisicing elit. Accusamus accusantium sit, reprehenderit, esse suscipit - quis similique harum est eum eveniet aspernatur delectus magni asperiores porro aliquam voluptate! Architecto, - perferendis commodi. -

- + +
+ Redigera +

{{ employee.fullName }}

+
+

Här kan du se och ändra personalkontots behörigheter. Ändra behörighet genom att klicka på redigera.

-

Kontaktuppgifter

- -
-
Namn
-
{{ detailedEmployeeData.fullName }}
+

Personuppgifter

+
+
Förnamn
+
{{ employee.firstName }}
+
Efternamn
+
{{ employee.lastName }}
Personnummer
-
+
+
E-postadress
+
+ {{employee.email}} +
-

Tjänst

-
    - -
  • - {{ service.name }} -
  • -
    +
      +
    • {{ tjanst.name }}
-

Utförande verksamheter och utförande adresser

-
    -
  • - {{ organization.name }} -
      -
    • - {{ organization.address.street }} {{ organization.address.postalCode }} {{ - organization.address.houseNumber }} {{ organization.address.city }} -
    • -
    +

    TODO: Behöver göras så en utförande adress hamnar under rätt utförande verksamhet.

    +

    Utförande verksamheter

    +
      +
    • + {{ utforandeVerksamhet }} +
    • +
    +

    Utförande adresser

    +
      +
    • + {{ utforandeAdress }}

Behörigheter

    - -
  • {{ authorization.name }}
  • -
    +
  • + + + + + {{role.name}} +
- -

- +
+ Tillbaka till deltagarlistan +
- -
Info saknas
+ +

+ + Info saknas +

+
diff --git a/apps/mina-sidor-fa/src/app/pages/administration/pages/employee-card/employee-card.component.scss b/apps/mina-sidor-fa/src/app/pages/administration/pages/employee-card/employee-card.component.scss index 1097620..1ae54b8 100644 --- a/apps/mina-sidor-fa/src/app/pages/administration/pages/employee-card/employee-card.component.scss +++ b/apps/mina-sidor-fa/src/app/pages/administration/pages/employee-card/employee-card.component.scss @@ -7,17 +7,7 @@ &__contents { display: flex; flex-direction: column; - gap: $digi--layout--gutter--xl $digi--layout--gutter--l; - } - - &__editcontainer { - display: flex; - justify-content: space-between; - align-items: center; - } - - &__h2 { - margin-top: 0; + gap: $digi--layout--gutter--l $digi--layout--gutter--l; } &__column { @@ -28,65 +18,60 @@ &__organizations { display: flex; flex-direction: column; - gap: 1.25rem; + } + + &__header, + &__footer { + display: flex; + flex-direction: row-reverse; + align-items: center; + justify-content: space-between; } &__footer { - margin-top: 5rem; + margin-top: $digi--layout--gutter--l; } - //LISTS + &__description-list { + dd { + margin: 0; + } + dt { + font-weight: var(--digi--typography--font-weight--semibold); + } + + dd { + margin-bottom: 0.5rem; + } + } &__list { @include msfa__reset-list; - } - &__listitem--indent { - @include msfa__reset-list; - margin-left: 1rem; - } - - &__description { - margin-left: 0.1rem; - grid-column: 1; - } - - &__term { - margin: 0; - grid-column: 1; - font-weight: var(--digi--typography--font-weight--semibold); - } - - //BUTTONS - - &__primarybutton { - a { - @include msfa_buttontemplate( - $msfa-button--background--primary, - $msfa-button--text--primary, - $msfa-button--hover--primary - ); + li { + margin-bottom: 0.5rem; + display: flex; } } - &__secondarybutton { - a { - @include msfa_buttontemplate( - $msfa-button--background--secondary, - $msfa-button--text--secondary, - $msfa-button--hover--secondary - ); - } + &__edit-button { + @include msfa-button-template( + $msfa-button--background--secondary, + $msfa-button--text--secondary, + $msfa-button--hover--secondary + ); + width: var(--digi-button--width); } - &__editbutton { - a { - @include msfa_buttontemplate( - $msfa-button--background--secondary, - $msfa-button--text--secondary, - $msfa-button--hover--secondary - ); - width: var(--digi-button--width); + &__authorization-icon { + margin-right: var(--digi--layout--gutter--s); + + &--authorized { + color: var(--digi--ui--color--border--success); + } + + &--unauthorized { + color: var(--digi--ui--color--border--error); } } } diff --git a/apps/mina-sidor-fa/src/app/pages/administration/pages/employee-card/employee-card.component.ts b/apps/mina-sidor-fa/src/app/pages/administration/pages/employee-card/employee-card.component.ts index 92e716e..69a050b 100644 --- a/apps/mina-sidor-fa/src/app/pages/administration/pages/employee-card/employee-card.component.ts +++ b/apps/mina-sidor-fa/src/app/pages/administration/pages/employee-card/employee-card.component.ts @@ -1,10 +1,10 @@ import { ChangeDetectionStrategy, Component } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; +import { RoleEnum } from '@msfa-enums/role.enum'; import { Employee } from '@msfa-models/employee.model'; -import { Participant } from '@msfa-models/participant.model'; +import { Role } from '@msfa-models/role.model'; import { EmployeeService } from '@msfa-services/api/employee.service'; import { BehaviorSubject, Observable } from 'rxjs'; -import { map, switchMap } from 'rxjs/operators'; @Component({ selector: 'msfa-employee-card', @@ -14,35 +14,14 @@ import { map, switchMap } from 'rxjs/operators'; }) export class EmployeeCardComponent { private _pendingSelectedParticipants$ = new BehaviorSubject([]); - private _employeeId$: Observable = this.activatedRoute.params.pipe( - map(({ employeeId }) => employeeId as string) - ); + employee$: Observable = this.employeeService.employee$; + allRoles: Role[] = Object.entries(RoleEnum).map(([key, value]) => ({ type: key as RoleEnum, name: value })); - detailedEmployeeData$: Observable = this._employeeId$.pipe( - switchMap(employeeId => this.employeeService.fetchDetailedEmployeeData$(employeeId)) - ); - - constructor(private activatedRoute: ActivatedRoute, private employeeService: EmployeeService) {} + constructor(private activatedRoute: ActivatedRoute, private employeeService: EmployeeService) { + this.employeeService.setCurrentEmployeeId(this.activatedRoute.snapshot.params.employeeId); + } get pendingSelectedParticipants(): string[] { return this._pendingSelectedParticipants$.getValue(); } - - handleChangeEmployee(): void { - console.log('change employee: ', this.pendingSelectedParticipants); - } - - handleChangeParticipant(id: string, checked: boolean): void { - const currentPendingSelectedParticipants = this.pendingSelectedParticipants; - - if (checked) { - this._pendingSelectedParticipants$.next([...this.pendingSelectedParticipants, id]); - } else { - this._pendingSelectedParticipants$.next(currentPendingSelectedParticipants.filter(currentId => currentId !== id)); - } - } - - handleChangeAllParticipants(participants: Participant[], checked: boolean): void { - this._pendingSelectedParticipants$.next(checked ? participants.map(participant => participant.id) : []); - } } diff --git a/apps/mina-sidor-fa/src/app/pages/administration/pages/employee-card/employee-card.module.ts b/apps/mina-sidor-fa/src/app/pages/administration/pages/employee-card/employee-card.module.ts index 1da4a48..a45add4 100644 --- a/apps/mina-sidor-fa/src/app/pages/administration/pages/employee-card/employee-card.module.ts +++ b/apps/mina-sidor-fa/src/app/pages/administration/pages/employee-card/employee-card.module.ts @@ -6,6 +6,7 @@ import { RouterModule } from '@angular/router'; import { HideTextModule } from '@msfa-shared/components/hide-text/hide-text.module'; import { LayoutModule } from '@msfa-shared/components/layout/layout.module'; import { LocalDatePipeModule } from '@msfa-shared/pipes/local-date/local-date.module'; +import { BackLinkModule } from '@msfa-shared/components/back-link/back-link.module'; import { EmployeeCardComponent } from './employee-card.component'; @NgModule({ @@ -19,6 +20,7 @@ import { EmployeeCardComponent } from './employee-card.component'; DigiNgLayoutExpansionPanelModule, LocalDatePipeModule, HideTextModule, + BackLinkModule ], }) export class EmployeeCardModule {} 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 d93821a..8293c90 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 @@ -1,17 +1,17 @@ import { FormSelectBaseItem } from '@af/digi-ng/_form/form-select-base'; -import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; -import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { AbstractControl, FormBuilder, FormGroup } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; -import { UnsubscribeDirective } from '@msfa-directives/unsubscribe.directive'; import { Authorization } from '@msfa-models/authorization.model'; import { Employee } from '@msfa-models/employee.model'; import { Service } from '@msfa-models/service.model'; import { AuthorizationService } from '@msfa-services/api/authorizations.service'; import { EmployeeService } from '@msfa-services/api/employee.service'; import { ServiceService } from '@msfa-services/api/service.service'; +import { EmailValidator } from '@msfa-utils/validators/email.validator'; import { RequiredValidator } from '@msfa-validators/required.validator'; import { Observable } from 'rxjs'; -import { map, switchMap } from 'rxjs/operators'; +import { map } from 'rxjs/operators'; import { EditEmployeeFormData } from './edit-employee-form/edit-employee-form.component'; @Component({ @@ -20,8 +20,8 @@ import { EditEmployeeFormData } from './edit-employee-form/edit-employee-form.co styleUrls: ['./employee-form.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, }) -export class EmployeeFormComponent extends UnsubscribeDirective implements OnInit { - employee$: Observable; +export class EmployeeFormComponent { + employee$: Observable = this.employeeService.employee$; services$: Observable = this.serviceService.services$; authorizations$: Observable = this.authorizationService.authorizations$; employeeCurrentServices: Service[] | null | undefined; @@ -33,7 +33,7 @@ export class EmployeeFormComponent extends UnsubscribeDirective implements OnIni modalAuthInfo: { name: string } = { name: 'Test Behörighetsnamn' }; formGroup: FormGroup = this.formBuilder.group({ - email: this.formBuilder.control('', [Validators.required, Validators.email]), + email: this.formBuilder.control('', [RequiredValidator('E-postadress'), EmailValidator('E-postadress')]), services: this.formBuilder.control([], [RequiredValidator('en tjänst')]), authorizations: new FormGroup({}), }); @@ -48,20 +48,7 @@ export class EmployeeFormComponent extends UnsubscribeDirective implements OnIni private router: Router, private activatedRoute: ActivatedRoute ) { - super(); - super.unsubscribeOnDestroy(); - } - - ngOnInit(): void { - this.employee$ = this.activatedRoute.params.pipe( - switchMap((params: { employeeId: string }) => { - return this.employeeService.fetchDetailedEmployeeData$(params.employeeId); - }) - ); - - this.services$.subscribe(services => { - /* this.employeeCurrentServices = services; */ - }); + this.employeeService.setCurrentEmployeeId(this.activatedRoute.snapshot.params.employeeId); } updateEmployee(editEmployeeFormData: EditEmployeeFormData): void { diff --git a/apps/mina-sidor-fa/src/app/shared/enums/role.enum.ts b/apps/mina-sidor-fa/src/app/shared/enums/role.enum.ts new file mode 100644 index 0000000..d030759 --- /dev/null +++ b/apps/mina-sidor-fa/src/app/shared/enums/role.enum.ts @@ -0,0 +1,7 @@ +export enum RoleEnum { + OrganizationUser = 'OrganizationUser', // Default role + ReportAndPlanning = 'ReportAndPlanning', + ReceiveDeltagare = 'ReceiveDeltagare', + AuthAdmin = 'AuthAdmin', + ContactPerson = 'ContactPerson', +} diff --git a/apps/mina-sidor-fa/src/app/shared/models/api/avrop-tjanst.response.model.ts b/apps/mina-sidor-fa/src/app/shared/models/api/avrop-tjanst.response.model.ts new file mode 100644 index 0000000..f9be422 --- /dev/null +++ b/apps/mina-sidor-fa/src/app/shared/models/api/avrop-tjanst.response.model.ts @@ -0,0 +1,4 @@ +export interface AvropTjanstResponse { + code: string; + name: string; +} diff --git a/apps/mina-sidor-fa/src/app/shared/models/api/employee.response.model.ts b/apps/mina-sidor-fa/src/app/shared/models/api/employee.response.model.ts index 6dfa418..44c4857 100644 --- a/apps/mina-sidor-fa/src/app/shared/models/api/employee.response.model.ts +++ b/apps/mina-sidor-fa/src/app/shared/models/api/employee.response.model.ts @@ -1,3 +1,4 @@ +import { RoleEnum } from '@msfa-enums/role.enum'; import { PaginationMeta } from '@msfa-models/pagination-meta.model'; export interface EmployeeCompactResponse { @@ -13,10 +14,10 @@ export interface EmployeeResponse { lastName: string; email: string; personnummer: string; - roles: string[]; + roles: RoleEnum[]; tjansteKoder: string[]; - utforandeVerksamhetIds: string[]; - adressIds: string[]; + utforandeVerksamhetIds: number[]; + adressIds: number[]; } export interface EmployeesApiResponse { diff --git a/apps/mina-sidor-fa/src/app/shared/models/api/tjanst.response.model.ts b/apps/mina-sidor-fa/src/app/shared/models/api/tjanst.response.model.ts index 7066160..e5c00d6 100644 --- a/apps/mina-sidor-fa/src/app/shared/models/api/tjanst.response.model.ts +++ b/apps/mina-sidor-fa/src/app/shared/models/api/tjanst.response.model.ts @@ -1,4 +1,6 @@ export interface TjanstResponse { - code: string; + id: string; name: string; + tjanstekod: string; + tjanstId: number; } diff --git a/apps/mina-sidor-fa/src/app/shared/models/avrop-tjanst.model.ts b/apps/mina-sidor-fa/src/app/shared/models/avrop-tjanst.model.ts new file mode 100644 index 0000000..b74528c --- /dev/null +++ b/apps/mina-sidor-fa/src/app/shared/models/avrop-tjanst.model.ts @@ -0,0 +1,15 @@ +import { AvropTjanstResponse } from './api/avrop-tjanst.response.model'; + +export interface AvropTjanst { + code: string; + name: string; +} + +export function mapResponseToAvropTjanst(data: AvropTjanstResponse): AvropTjanst { + const { code, name } = data; + + return { + code, + name, + }; +} diff --git a/apps/mina-sidor-fa/src/app/shared/models/employee.model.ts b/apps/mina-sidor-fa/src/app/shared/models/employee.model.ts index 00f2ba0..31366df 100644 --- a/apps/mina-sidor-fa/src/app/shared/models/employee.model.ts +++ b/apps/mina-sidor-fa/src/app/shared/models/employee.model.ts @@ -1,5 +1,7 @@ +import { RoleEnum } from '@msfa-enums/role.enum'; import { EmployeeCompactResponse, EmployeeResponse } from './api/employee.response.model'; import { PaginationMeta } from './pagination-meta.model'; +import { Tjanst } from './tjanst.model'; export interface EmployeeCompact { id: string; @@ -12,12 +14,14 @@ export interface Employee { id: string; firstName: string; lastName: string; + fullName: string; email: string; ssn: string; - roles: string[]; + roles: RoleEnum[]; tjanstCodes: string[]; - utforandeVerksamhetIds: string[]; - utforandeAdressIds: string[]; + tjanster?: Tjanst[]; + utforandeVerksamhetIds: number[]; + utforandeAdressIds: number[]; } export interface EmployeesData { @@ -29,8 +33,8 @@ export interface EmployeeRequestData { email: string; roles: string[]; tjansteKoder: string[]; - utforandeVerksamhetIds: string[]; - adressIds: string[]; + utforandeVerksamhetIds: number[]; + adressIds: number[]; } export function mapEmployeeToRequestData(data: Employee): EmployeeRequestData { @@ -71,11 +75,12 @@ export function mapResponseToEmployee(data: EmployeeResponse): Employee { id: ciamUserId, firstName, lastName, + fullName: `${firstName} ${lastName}`, email, ssn: personnummer, - roles, - tjanstCodes: tjansteKoder, - utforandeVerksamhetIds, - utforandeAdressIds: adressIds, + roles: roles || [], + tjanstCodes: tjansteKoder || [], + utforandeVerksamhetIds: utforandeVerksamhetIds || [], + utforandeAdressIds: adressIds || [], }; } diff --git a/apps/mina-sidor-fa/src/app/shared/models/role.model.ts b/apps/mina-sidor-fa/src/app/shared/models/role.model.ts new file mode 100644 index 0000000..949ab65 --- /dev/null +++ b/apps/mina-sidor-fa/src/app/shared/models/role.model.ts @@ -0,0 +1,6 @@ +import { RoleEnum } from '@msfa-enums/role.enum'; + +export interface Role { + name: string; + type: RoleEnum; +} diff --git a/apps/mina-sidor-fa/src/app/shared/models/tjanst.model.ts b/apps/mina-sidor-fa/src/app/shared/models/tjanst.model.ts index 53907be..7f91666 100644 --- a/apps/mina-sidor-fa/src/app/shared/models/tjanst.model.ts +++ b/apps/mina-sidor-fa/src/app/shared/models/tjanst.model.ts @@ -1,15 +1,19 @@ import { TjanstResponse } from './api/tjanst.response.model'; export interface Tjanst { - code: string; + id: string; name: string; + code: string; + tjanstId: number; } -export function mapTjanstResponseToTjanst(data: TjanstResponse): Tjanst { - const { code, name } = data; +export function mapResponseToTjanst(data: TjanstResponse): Tjanst { + const { id, name, tjanstekod, tjanstId } = data; return { - code, + id, name, + code: tjanstekod, + tjanstId, }; } 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 ad9b21e..82f7647 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 @@ -1,14 +1,14 @@ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { environment } from '@msfa-environment'; +import { AvropTjanstResponse } from '@msfa-models/api/avrop-tjanst.response.model'; import { AvropResponse } from '@msfa-models/api/avrop.response.model'; import { KommunResponse } from '@msfa-models/api/kommun.response.model'; -import { TjanstResponse } from '@msfa-models/api/tjanst.response.model'; import { UtforandeVerksamhetResponse } from '@msfa-models/api/utforande-verksamhet.response.model'; +import { mapResponseToAvropTjanst } from '@msfa-models/avrop-tjanst.model'; import { Avrop, mapAvropResponseToAvrop } from '@msfa-models/avrop.model'; import { mapKommunResponseToKommun } from '@msfa-models/kommun.model'; import { MultiselectFilterOption } from '@msfa-models/multiselect-filter-option'; -import { mapTjanstResponseToTjanst } from '@msfa-models/tjanst.model'; import { mapUtforandeVerksamhetResponseToUtforandeVerksamhet } from '@msfa-models/utforande-verksamhet.model'; import { Observable, of } from 'rxjs'; import { delay, filter, map } from 'rxjs/operators'; @@ -56,9 +56,9 @@ export class AvropApiService { selectedKommuner: MultiselectFilterOption[], selectedUtforandeVerksamheter: MultiselectFilterOption[] ): Observable { - return this.httpClient.get<{ data: TjanstResponse[] }>(`${this._apiBaseUrl}/tjanster`).pipe( + return this.httpClient.get<{ data: AvropTjanstResponse[] }>(`${this._apiBaseUrl}/tjanster`).pipe( filter(response => !!response?.data), - map(({ data }) => data.map(tjanster => ({ label: mapTjanstResponseToTjanst(tjanster).name }))) + map(({ data }) => data.map(tjanster => ({ label: mapResponseToAvropTjanst(tjanster).name }))) ); } 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 aa31653..c2bc232 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 @@ -1,10 +1,11 @@ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; +import { UnsubscribeDirective } from '@msfa-directives/unsubscribe.directive'; import { ErrorType } from '@msfa-enums/error-type.enum'; import { SortOrder } from '@msfa-enums/sort-order.enum'; import { environment } from '@msfa-environment'; -import { EmployeeInviteMockApiResponse } from '@msfa-models/api/employee-invite.response.model'; import { DeleteEmployeeMockApiResponse } from '@msfa-models/api/delete-employee.response.model'; +import { EmployeeInviteMockApiResponse } from '@msfa-models/api/employee-invite.response.model'; import { EmployeeCompactResponse, EmployeeResponse, @@ -18,23 +19,62 @@ import { mapResponseToEmployee, mapResponseToEmployeeCompact, } from '@msfa-models/employee.model'; +import { errorToCustomError } from '@msfa-models/error/custom-error'; import { Sort } from '@msfa-models/sort.model'; -import { BehaviorSubject, combineLatest, Observable, throwError } from 'rxjs'; -import { catchError, map, switchMap, take } from 'rxjs/operators'; +import { ErrorService } from '@msfa-services/error.service'; +import { BehaviorSubject, combineLatest, Observable, of, throwError } from 'rxjs'; +import { catchError, filter, map, switchMap, take } from 'rxjs/operators'; +import { TjanstService } from './tjanst.service'; const API_HEADERS = { headers: environment.api.headers }; @Injectable({ providedIn: 'root', }) -export class EmployeeService { +export class EmployeeService extends UnsubscribeDirective { private _apiUrl = `${environment.api.url}/users`; + private _currentEmployeeId$ = new BehaviorSubject(null); private _limit$ = new BehaviorSubject(20); private _page$ = new BehaviorSubject(1); private _sort$ = new BehaviorSubject>({ key: 'name', order: SortOrder.ASC }); public sort$: Observable> = this._sort$.asObservable(); private _searchFilter$ = new BehaviorSubject(''); private _onlyEmployeesWithoutAuthorization$ = new BehaviorSubject(false); + private _employee$ = new BehaviorSubject(null); + + public employee$: Observable = this._employee$.asObservable(); + constructor( + private httpClient: HttpClient, + private errorService: ErrorService, + private tjanstService: TjanstService + ) { + super(); + super.unsubscribeOnDestroy( + this._currentEmployeeId$ + .pipe( + filter(currentEmployeeId => !!currentEmployeeId), + switchMap(currentEmployeeId => + combineLatest([this._fetchEmployee$(currentEmployeeId), this.tjanstService.tjanster$]).pipe( + filter(([employee, allTjanster]) => !!(employee && allTjanster?.length)), + map(([employee, allTjanster]) => { + const tjanster = []; + employee.tjanstCodes.forEach(code => { + const currentTjanst = allTjanster.find(tjanst => tjanst.code === code); + + if (currentTjanst) { + tjanster.push(currentTjanst); + } + }); + return { ...employee, tjanster }; + }) + ) + ) + ) + .subscribe(employee => { + this._employee$.next(employee as Employee); + }) + ); + } public employeesData$: Observable = combineLatest([ this._limit$, @@ -48,6 +88,13 @@ export class EmployeeService { ) ); + public setCurrentEmployeeId(currentEmployeeId: string): void { + if (this._currentEmployeeId$.getValue() !== currentEmployeeId) { + this._employee$.next(null); + this._currentEmployeeId$.next(currentEmployeeId); + } + } + private _fetchEmployees$( limit: number, page: number, @@ -82,14 +129,18 @@ export class EmployeeService { ); } - public fetchDetailedEmployeeData$(id: string): Observable { + private _fetchEmployee$(id: string): Observable> { return this.httpClient .get<{ data: EmployeeResponse }>(`${this._apiUrl}/${id}`, { ...API_HEADERS }) - .pipe(map(result => mapResponseToEmployee(result.data))); + .pipe( + map(({ data }) => mapResponseToEmployee(data)), + catchError(error => { + this.errorService.add(errorToCustomError(error)); + return of({}); + }) + ); } - constructor(private httpClient: HttpClient) {} - public setSearchFilter(value: string): void { this._searchFilter$.next(value); } @@ -107,8 +158,8 @@ export class EmployeeService { map(response => { return { status: response.status || 200, // mockresponse - message: response.message || 'deleted succeeded' // mockresponse - } + message: response.message || 'deleted succeeded', // mockresponse + }; }), catchError(error => throwError({ message: error as string, type: ErrorType.API })) ); diff --git a/apps/mina-sidor-fa/src/app/shared/services/api/tjanst.service.ts b/apps/mina-sidor-fa/src/app/shared/services/api/tjanst.service.ts new file mode 100644 index 0000000..14d79cf --- /dev/null +++ b/apps/mina-sidor-fa/src/app/shared/services/api/tjanst.service.ts @@ -0,0 +1,38 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { UnsubscribeDirective } from '@msfa-directives/unsubscribe.directive'; +import { environment } from '@msfa-environment'; +import { TjanstResponse } from '@msfa-models/api/tjanst.response.model'; +import { mapResponseToTjanst, Tjanst } from '@msfa-models/tjanst.model'; +import { BehaviorSubject, Observable } from 'rxjs'; +import { filter, map, switchMap } from 'rxjs/operators'; + +const API_HEADERS = { headers: environment.api.headers }; + +@Injectable({ + providedIn: 'root', +}) +export class TjanstService extends UnsubscribeDirective { + private _apiUrl = `${environment.api.url}/tjanster`; + private _tjanster$ = new BehaviorSubject(null); + + public tjanster$: Observable = this._tjanster$.asObservable(); + + private _fetchTjanster$: Observable = this.tjanster$.pipe( + filter(tjanster => !tjanster?.length), + switchMap(() => + this.httpClient + .get<{ data: TjanstResponse[] }>(this._apiUrl, API_HEADERS) + .pipe(map(({ data }) => data.map(tjanst => mapResponseToTjanst(tjanst)))) + ) + ); + + constructor(private httpClient: HttpClient) { + super(); + super.unsubscribeOnDestroy( + this._fetchTjanster$.subscribe(tjanster => { + this._tjanster$.next(tjanster); + }) + ); + } +} diff --git a/apps/mina-sidor-fa/src/styles/mixins/_buttons.scss b/apps/mina-sidor-fa/src/styles/mixins/_buttons.scss index bd7a573..70043c8 100644 --- a/apps/mina-sidor-fa/src/styles/mixins/_buttons.scss +++ b/apps/mina-sidor-fa/src/styles/mixins/_buttons.scss @@ -13,7 +13,7 @@ $msfa-button--font-font-size: var(--digi-button--font-size); //A basic link button -@mixin msfa_buttontemplate($backgroundcolor, $textcolor, $hovercolor) { +@mixin msfa-button-template($backgroundcolor, $textcolor, $hovercolor) { background: $backgroundcolor; padding: $msfa-button--padding; margin: $msfa-button--margin; diff --git a/mock-api/mina-sidor-fa/scripts/authorizations.js b/mock-api/mina-sidor-fa/scripts/authorizations.js index 4bcc0dc..e962638 100644 --- a/mock-api/mina-sidor-fa/scripts/authorizations.js +++ b/mock-api/mina-sidor-fa/scripts/authorizations.js @@ -25,4 +25,4 @@ function generateAuthorizations() { export default { generate: generateAuthorizations, -}; +}; \ No newline at end of file diff --git a/mock-api/mina-sidor-fa/scripts/employees.js b/mock-api/mina-sidor-fa/scripts/employees.js index ec1706e..a918dae 100644 --- a/mock-api/mina-sidor-fa/scripts/employees.js +++ b/mock-api/mina-sidor-fa/scripts/employees.js @@ -7,6 +7,7 @@ faker.locale = 'sv'; const TJANSTER = tjanster.generate(); const ORGANIZATIONS = organizations.generate(); +const ROLES = ['ReportAndPlanning', 'ReceiveDeltagare', 'AuthAdmin', 'ContactPerson']; function generateEmployees(amount = 10) { const employees = []; @@ -31,10 +32,12 @@ function generateEmployees(amount = 10) { min: 1000, max: 9999, })}`, - email: '', - roles: hasBehorigheter ? ['Admin'] : [], + email: faker.internet.email(firstName.toLowerCase(), lastName.toLowerCase()), + roles: hasBehorigheter + ? ['OrganizationUser', ...chooseRandom(ROLES, faker.datatype.number({ min: 1, max: ROLES.length }))] + : ['OrganizationUser'], tjanst: hasBehorigheter ? currentTjanster.map(tjanst => tjanst.name) : [], - tjansteKoder: hasBehorigheter ? currentTjanster.map(tjanst => tjanst.code) : [], + tjansteKoder: hasBehorigheter ? currentTjanster.map(tjanst => tjanst.tjanstekod) : [], utforandeVerksamhet: hasBehorigheter ? currentOrganizations.map(organization => organization.name) : [], utforandeVerksamhetIds: hasBehorigheter ? currentOrganizations.map(organization => organization.id) : [], }; diff --git a/mock-api/mina-sidor-fa/scripts/generate-api.js b/mock-api/mina-sidor-fa/scripts/generate-api.js index a2e303c..ceae58f 100644 --- a/mock-api/mina-sidor-fa/scripts/generate-api.js +++ b/mock-api/mina-sidor-fa/scripts/generate-api.js @@ -1,23 +1,23 @@ import fs from 'fs'; import { authTokens } from './auth-tokens.js'; -import authorizations from './authorizations.js'; import avrop from './avrop.js'; import currentUser from './current-user.js'; import deltagare from './deltagare.js'; import employees from './employees.js'; import languages from './languages.js'; import participants from './participants.js'; +import tjanster from './tjanster.js'; const generatedEmployees = employees.generate(50); const generatedDeltagare = deltagare.generate(50); const generatedAvrop = avrop.generate(10, generatedDeltagare.slice(0, 10)); -const auths = authorizations.generate(); -const tjanster = []; +const generatedTjanster = tjanster.generate(); +const avropTjanster = []; const organizations = []; const kommuner = []; generatedAvrop.forEach(({ tjanstekod, tjansteNamn, utforandeVerksamhetId, utforandeverksamhet, kommunKod, kommun }) => { - const tjanstExists = tjanster.find(tjanst => tjanst.code === tjanstekod); + const tjanstExists = avropTjanster.find(tjanst => tjanst.code === tjanstekod); const organizationExists = organizations.find(organization => organization.id === utforandeVerksamhetId); const kommunExists = kommuner.find(kommun => kommun.kommunCode === kommunKod); @@ -29,7 +29,7 @@ generatedAvrop.forEach(({ tjanstekod, tjansteNamn, utforandeVerksamhetId, utfora tjanstExists.related_kommunCodes.push(kommunKod); } } else { - tjanster.push({ + avropTjanster.push({ code: tjanstekod, name: tjansteNamn, related_utforandeverksamhetIds: [utforandeVerksamhetId], @@ -72,7 +72,8 @@ const apiData = { languages: languages.generate(), employees: generatedEmployees, avrop: generatedAvrop, - tjanster, + avropTjanster, + tjanster: generatedTjanster, organizations, kommuner, deltagare: generatedDeltagare, diff --git a/mock-api/mina-sidor-fa/scripts/tjanster.js b/mock-api/mina-sidor-fa/scripts/tjanster.js index 6712748..edd8ad5 100644 --- a/mock-api/mina-sidor-fa/scripts/tjanster.js +++ b/mock-api/mina-sidor-fa/scripts/tjanster.js @@ -5,24 +5,20 @@ faker.locale = 'sv'; function generateTjanster() { const tjanster = [ { - code: faker.datatype.uuid(), + id: 'A012', name: 'Kundval Rusta och matcha', + tjanstekod: 'A012', + tjanstId: 25, + count: 8, // Behövs för avrop-tjanst + label: 'Kundval Rusta och matcha', // Behövs för avrop-tjanst }, // { - // code: faker.datatype.uuid(), + // id: 'KVL', // name: 'Karriärvägledning', - // }, - // { - // code: faker.datatype.uuid(), - // name: 'STOM', - // }, - // { - // code: faker.datatype.uuid(), - // name: 'YSM', - // }, - // { - // code: faker.datatype.uuid(), - // name: 'AUB', + // tjanstekod: 'KVL', + // tjanstId: 33, + // count: 8, // Behövs för avrop-tjanst + // label: 'Karriärvägledning', // Behövs för avrop-tjanst // }, ]; diff --git a/mock-api/mina-sidor-fa/server.js b/mock-api/mina-sidor-fa/server.js index 3e10009..43ddd34 100644 --- a/mock-api/mina-sidor-fa/server.js +++ b/mock-api/mina-sidor-fa/server.js @@ -14,7 +14,7 @@ server.use( '/users/:id': '/employees?ciamUserId=:id', '/users*': '/employees$1', '/employees*search=*': '/employees$1fullName_like=$2', - '/employees*onlyEmployeesWithoutAuthorization=*': '/employees$1roles.length_lte=0', + '/employees*onlyEmployeesWithoutAuthorization=*': '/employees$1roles.length_lte=1', '/employees/invite': '/invites', '/employees*': '/employees$1', '/services*': '/tjanster$1', @@ -22,7 +22,7 @@ server.use( '/participant/:id': '/participants/:id?_embed=employees', '/auth/userinfo': '/currentUser', '/auth/organizations': '/currentUser', - '/avrop/tjanster*': '/tjanster$1', + '/avrop/tjanster*': '/avropTjanster$1', '/avrop/utforandeverksamheter*': '/organizations$1', '/avrop/kommuner*': '/kommuner$1', '/deltagare?*': '/avrop?$1',