feat(employee): Showing employee-data inside employee-card page. (TV-341)
Squashed commit of the following: commit 4fd71e0d0655a0d75dda59151ac74e2361f187bc Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se> Date: Fri Aug 20 10:59:46 2021 +0200 Updated RoleEnum and mock-data för roles commit f05a93239727ce1245650ece3b48cf75dc7091ca Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se> Date: Fri Aug 20 08:34:20 2021 +0200 Fixed issue with mock-api commit c31e94da6b90e442fd84c5113789db245be81c6d Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se> Date: Fri Aug 20 08:26:14 2021 +0200 Fixed issue with tjanster commit a183a08f0446cdaea7d01c8935d88ac436b0438f Merge: eb310c11e2d925Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se> Date: Fri Aug 20 07:59:06 2021 +0200 Merge branch 'develop' into feature/TV-341-erik commit eb310c10bdf0f4b60032bdda97df75c19bdbf447 Merge: 877b68bfae7d9aAuthor: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se> Date: Fri Aug 20 07:21:39 2021 +0200 Merged develop and fixed conflicts commit 877b68b8827e89cfd230856c9d8247f1cd8db264 Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se> Date: Thu Aug 19 15:01:55 2021 +0200 Now fetching tjanster from mock-api commit 1ecd26595b21ea46ce6fb0c193c6642f66250ae3 Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se> Date: Thu Aug 19 14:24:11 2021 +0200 Some more changes to employee-card commit e42ae254e7aa7b994627fdccb7037493b116d6a2 Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se> 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: c78f3f8d6e4666Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se> 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 <nikola.holst-nikolic@arbetsformedlingen.se> Date: Thu Aug 19 11:19:56 2021 +0200 Authorization commit 9c043720a9cfa5fd6943013f643d948a50c8f135 Merge: 77d6a9cffeb372Author: WP\holno <nikola.holst-nikolic@arbetsformedlingen.se> 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 <nikola.holst-nikolic@arbetsformedlingen.se> Date: Wed Aug 18 10:22:45 2021 +0200 Moved subscription, added icons, refactured markup commit b43c18e28b5aabb8115fa659a98b4ae8c0a7bf40 Author: WP\holno <nikola.holst-nikolic@arbetsformedlingen.se> Date: Tue Aug 17 10:50:02 2021 +0200 unsubscribed commit 9f48cddc75872fc3f740c53de998cd54666b0b1d Author: WP\holno <nikola.holst-nikolic@arbetsformedlingen.se> 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 <nikola.holst-nikolic@arbetsformedlingen.se> Date: Mon Aug 16 16:37:13 2021 +0200 Authorization commit 5fe0b5d5fc725551f9e794cbaa70dc0f077f8717 Author: WP\holno <nikola.holst-nikolic@arbetsformedlingen.se> Date: Fri Aug 13 15:46:50 2021 +0200 - Changed first h2 to h3 - Changed link to routerLink commit fd1cb3c6249535ce84e61df035cae63352b1b00b Author: WP\holno <nikola.holst-nikolic@arbetsformedlingen.se> Date: Fri Aug 13 11:53:36 2021 +0200 Amends after PR commit 13e9881e3680bd829736205b3fef57b2228638d5 Author: WP\holno <nikola.holst-nikolic@arbetsformedlingen.se> Date: Wed Aug 11 16:19:36 2021 +0200 Employee-card amends to look more like the sketch.
This commit is contained in:
@@ -1,93 +1,97 @@
|
||||
<msfa-layout>
|
||||
<section class="employee-card">
|
||||
<digi-typography *ngIf="detailedEmployeeData$ | async as detailedEmployeeData; else loadingRef">
|
||||
<div class="employee-card__editcontainer">
|
||||
<h1>{{ detailedEmployeeData.fullName }}</h1>
|
||||
<span class="employee-card__editbutton">
|
||||
<a href="./administration/redigera-konto/{{detailedEmployeeData.id}}">Redigera</a>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
|
||||
<digi-typography *ngIf="employee$ | async as employee; else loadingRef">
|
||||
<header class="employee-card__header">
|
||||
<a class="employee-card__edit-button" [routerLink]="['/administration/andra-konto', employee.id]">Redigera</a>
|
||||
<h1>{{ employee.fullName }}</h1>
|
||||
</header>
|
||||
<p>Här kan du se och ändra personalkontots behörigheter. Ändra behörighet genom att klicka på redigera.</p>
|
||||
<div class="employee-card__contents">
|
||||
<div class="employee-card__column">
|
||||
<h2>Kontaktuppgifter</h2>
|
||||
|
||||
<dl>
|
||||
<dt>Namn</dt>
|
||||
<dd *ngIf="detailedEmployeeData.fullName; else emptyDD">{{ detailedEmployeeData.fullName }}</dd>
|
||||
<h2>Personuppgifter</h2>
|
||||
<dl class="employee-card__description-list">
|
||||
<dt>Förnamn</dt>
|
||||
<dd *ngIf="employee.firstName; else emptyDD">{{ employee.firstName }}</dd>
|
||||
<dt>Efternamn</dt>
|
||||
<dd *ngIf="employee.lastName; else emptyDD">{{ employee.lastName }}</dd>
|
||||
<dt>Personnummer</dt>
|
||||
<dd *ngIf="detailedEmployeeData.ssn; else emptyDD">
|
||||
<dd *ngIf="employee.ssn; else emptyDD">
|
||||
<msfa-hide-text
|
||||
symbols="********-****"
|
||||
[changingText]="detailedEmployeeData.ssn"
|
||||
[changingText]="employee.ssn"
|
||||
ariaLabelType="personnummer"
|
||||
></msfa-hide-text>
|
||||
</dd>
|
||||
<dt>E-postadress</dt>
|
||||
<dd *ngIf="employee.email; else emptyDD">
|
||||
<a href="mailto:{{employee.email}}">{{employee.email}}</a>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
<div class="employee-card__column">
|
||||
<h2>Tjänst</h2>
|
||||
<ul class="employee-card__list">
|
||||
<ng-container *ngIf="detailedEmployeeData.services.length; else emptyDD">
|
||||
<li class="employee-card__column--listitem" *ngFor="let service of detailedEmployeeData.services">
|
||||
{{ service.name }}
|
||||
</li>
|
||||
</ng-container>
|
||||
<ul class="employee-card__list" *ngIf="employee.tjanster.length; else emptyText">
|
||||
<li *ngFor="let tjanst of employee.tjanster">{{ tjanst.name }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="employee-card__organizations">
|
||||
<h2>Utförande verksamheter och utförande adresser</h2>
|
||||
<ul class="employee-card__list" *ngIf="detailedEmployeeData.organizations?.length">
|
||||
<li class="employee-card__list" *ngFor="let organization of detailedEmployeeData.organizations">
|
||||
{{ organization.name }}
|
||||
<ul>
|
||||
<li class="employee-card__listitem--indent">
|
||||
{{ organization.address.street }} {{ organization.address.postalCode }} {{
|
||||
organization.address.houseNumber }} {{ organization.address.city }}
|
||||
</li>
|
||||
</ul>
|
||||
<p>TODO: Behöver göras så en utförande adress hamnar under rätt utförande verksamhet.</p>
|
||||
<h3>Utförande verksamheter</h3>
|
||||
<ul
|
||||
class="employee-card__list employee-card__list--secondary"
|
||||
*ngIf="employee.utforandeVerksamhetIds.length; else emptyText"
|
||||
>
|
||||
<li class="employee-card__list" *ngFor="let utforandeVerksamhet of employee.utforandeVerksamhetIds">
|
||||
{{ utforandeVerksamhet }}
|
||||
</li>
|
||||
</ul>
|
||||
<h3>Utförande adresser</h3>
|
||||
<ul
|
||||
class="employee-card__list employee-card__list--secondary"
|
||||
*ngIf="employee.utforandeAdressIds.length; else emptyText"
|
||||
>
|
||||
<li class="employee-card__list" *ngFor="let utforandeAdress of employee.utforandeAdressIds">
|
||||
{{ utforandeAdress }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="employee-card__column">
|
||||
<h2>Behörigheter</h2>
|
||||
<ul class="employee-card__list">
|
||||
<ng-container *ngIf="detailedEmployeeData.authorizations.length; else emptyDD">
|
||||
<li *ngFor="let authorization of detailedEmployeeData.authorizations">{{ authorization.name }}</li>
|
||||
</ng-container>
|
||||
<li *ngFor="let role of allRoles">
|
||||
<digi-icon-check-circle
|
||||
*ngIf="employee.roles.includes(role.type); else unauthorized"
|
||||
class="employee-card__authorization-icon employee-card__authorization-icon--authorized"
|
||||
></digi-icon-check-circle>
|
||||
<ng-template #unauthorized>
|
||||
<digi-icon-x-button
|
||||
class="employee-card__authorization-icon employee-card__authorization-icon--unauthorized"
|
||||
></digi-icon-x-button>
|
||||
</ng-template>
|
||||
{{role.name}}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p></p>
|
||||
</digi-typography>
|
||||
<div class="employee-card__footer">
|
||||
<span class="employee-card__secondarybutton">
|
||||
<a href="./administration/personal">Tillbaka till personallistan</a>
|
||||
</span>
|
||||
|
||||
<span class="employee-card__primarybutton">
|
||||
<a href="./administration/skapa-konto">Skapa nytt konto</a>
|
||||
</span>
|
||||
</div>
|
||||
<footer class="employee-card__footer">
|
||||
<msfa-back-link [route]="['/administration/personal']">Tillbaka till deltagarlistan</msfa-back-link>
|
||||
</footer>
|
||||
</section>
|
||||
|
||||
<ng-template #loadingRef>
|
||||
<digi-ng-skeleton-base [afCount]="3" afText="Laddar personalkortet"></digi-ng-skeleton-base>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #emptyDD class="employee-card__list">
|
||||
<dd>
|
||||
<span aria-hidden="true">-</span>
|
||||
<span class="msfa__a11y-sr-only">Info saknas</span>
|
||||
</dd>
|
||||
</ng-template>
|
||||
<ng-template #emptyText>
|
||||
<p>
|
||||
<span aria-hidden="true">-</span>
|
||||
<span class="msfa__a11y-sr-only">Info saknas</span>
|
||||
</p>
|
||||
</ng-template>
|
||||
</msfa-layout>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<string[]>([]);
|
||||
private _employeeId$: Observable<string> = this.activatedRoute.params.pipe(
|
||||
map(({ employeeId }) => employeeId as string)
|
||||
);
|
||||
employee$: Observable<Employee> = this.employeeService.employee$;
|
||||
allRoles: Role[] = Object.entries(RoleEnum).map(([key, value]) => ({ type: key as RoleEnum, name: value }));
|
||||
|
||||
detailedEmployeeData$: Observable<Employee> = 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) : []);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
@@ -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<Employee>;
|
||||
export class EmployeeFormComponent {
|
||||
employee$: Observable<Employee> = this.employeeService.employee$;
|
||||
services$: Observable<Service[]> = this.serviceService.services$;
|
||||
authorizations$: Observable<Authorization[]> = 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 {
|
||||
|
||||
7
apps/mina-sidor-fa/src/app/shared/enums/role.enum.ts
Normal file
7
apps/mina-sidor-fa/src/app/shared/enums/role.enum.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export enum RoleEnum {
|
||||
OrganizationUser = 'OrganizationUser', // Default role
|
||||
ReportAndPlanning = 'ReportAndPlanning',
|
||||
ReceiveDeltagare = 'ReceiveDeltagare',
|
||||
AuthAdmin = 'AuthAdmin',
|
||||
ContactPerson = 'ContactPerson',
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
export interface AvropTjanstResponse {
|
||||
code: string;
|
||||
name: string;
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
export interface TjanstResponse {
|
||||
code: string;
|
||||
id: string;
|
||||
name: string;
|
||||
tjanstekod: string;
|
||||
tjanstId: number;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
@@ -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 || [],
|
||||
};
|
||||
}
|
||||
|
||||
6
apps/mina-sidor-fa/src/app/shared/models/role.model.ts
Normal file
6
apps/mina-sidor-fa/src/app/shared/models/role.model.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { RoleEnum } from '@msfa-enums/role.enum';
|
||||
|
||||
export interface Role {
|
||||
name: string;
|
||||
type: RoleEnum;
|
||||
}
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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<MultiselectFilterOption[]> {
|
||||
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 })))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -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<string>(null);
|
||||
private _limit$ = new BehaviorSubject<number>(20);
|
||||
private _page$ = new BehaviorSubject<number>(1);
|
||||
private _sort$ = new BehaviorSubject<Sort<keyof EmployeeCompactResponse>>({ key: 'name', order: SortOrder.ASC });
|
||||
public sort$: Observable<Sort<keyof EmployeeCompactResponse>> = this._sort$.asObservable();
|
||||
private _searchFilter$ = new BehaviorSubject<string>('');
|
||||
private _onlyEmployeesWithoutAuthorization$ = new BehaviorSubject<boolean>(false);
|
||||
private _employee$ = new BehaviorSubject<Employee>(null);
|
||||
|
||||
public employee$: Observable<Employee> = 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<EmployeesData> = 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<Employee> {
|
||||
private _fetchEmployee$(id: string): Observable<Employee | Partial<Employee>> {
|
||||
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 }))
|
||||
);
|
||||
|
||||
@@ -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<Tjanst[]>(null);
|
||||
|
||||
public tjanster$: Observable<Tjanst[]> = this._tjanster$.asObservable();
|
||||
|
||||
private _fetchTjanster$: Observable<Tjanst[]> = 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);
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -25,4 +25,4 @@ function generateAuthorizations() {
|
||||
|
||||
export default {
|
||||
generate: generateAuthorizations,
|
||||
};
|
||||
};
|
||||
@@ -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) : [],
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
// },
|
||||
];
|
||||
|
||||
|
||||
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user