Merge pull request #59 in TEA/dafa-web-monorepo from feature/TV-244 to develop

Squashed commit of the following:

commit b8ea6da64b2fbdc1bbc0d7546c6ce859ce6981cd
Author: Aden Hassan <aden.hassan@arbetsformedlingen.se>
Date:   Thu Aug 19 15:17:39 2021 +0200

    minor changes to get correct employee data from mock-api

commit 715eff33a8f3cccd7ddce8bd32996190dc6597f3
Author: Aden Hassan <aden.hassan@arbetsformedlingen.se>
Date:   Thu Aug 19 15:05:26 2021 +0200

    minor changes and added employee email to mock-data (TV-244)

commit 454641e1fd486e4aee271d63406a28f47c299b45
Merge: f5e0950 ecb929a
Author: Aden Hassan <aden.hassan@arbetsformedlingen.se>
Date:   Thu Aug 19 14:52:39 2021 +0200

    merged with develop and fixed conflicts (TV-244)

commit f5e0950da2de0465fb6eaee39a0e1c13b1c52281
Author: Aden Hassan <aden.hassan@arbetsformedlingen.se>
Date:   Thu Aug 19 13:31:01 2021 +0200

    flyttat över grundstrukturen till edit-employee-form componenten

commit bcce2e41646b45c65929d057248b6767a832d807
Author: Aden Hassan <aden.hassan@arbetsformedlingen.se>
Date:   Thu Aug 19 12:42:12 2021 +0200

    pre-populated email-input and minor changes to employee model and moch-api

commit 088ed6efb0cebdea86d25094ca1fd55827f938d2
Author: arbetsformedlingen_garcn <christian.gardebrink@arbetsformedlingen.se>
Date:   Thu Aug 19 11:12:57 2021 +0200

    TV-244 small adjustments.

commit be17adf5d898b42467a557832e728ca3827f58d6
Author: arbetsformedlingen_garcn <christian.gardebrink@arbetsformedlingen.se>
Date:   Thu Aug 19 10:43:26 2021 +0200

    TV-244 extended emplyee authorizations to a list with two random authorizations.

commit cc57a6d2ceae4069d48aa670a6fea95c21ebd628
Author: Aden Hassan <aden.hassan@arbetsformedlingen.se>
Date:   Thu Aug 19 10:25:42 2021 +0200

    minor changes and re-wrote the mock-api to similar data for authorizations and employee-auth

commit 0a22b310729e2a359aa9f1c9d475ac875b6b2301
Author: arbetsformedlingen_garcn <christian.gardebrink@arbetsformedlingen.se>
Date:   Thu Aug 19 05:37:05 2021 +0200

    TV-244 wip

commit 0e80b5bc4ac14b74f1a8c58ec257ca1f6453e119
Author: arbetsformedlingen_garcn <christian.gardebrink@arbetsformedlingen.se>
Date:   Wed Aug 18 17:14:48 2021 +0200

    TV-244 WIP
This commit is contained in:
Christian Gårdebrink
2021-08-19 15:56:00 +02:00
parent ecb929a808
commit fae7d9ad8c
13 changed files with 574 additions and 202 deletions

View File

@@ -4,7 +4,7 @@
<div class="employee-card__editcontainer">
<h1>{{ detailedEmployeeData.fullName }}</h1>
<span class="employee-card__editbutton">
<a href="./administration/skapa-konto">Redigera</a>
<a href="./administration/redigera-konto/{{detailedEmployeeData.id}}">Redigera</a>
</span>
</div>

View File

@@ -0,0 +1,145 @@
<digi-typography>
<form
class="edit-employee-form"
*ngIf="editEmployeeFormGroup"
[formGroup]="editEmployeeFormGroup"
(ngSubmit)="onFormSubmitted()"
>
<digi-ng-form-input
class="edit-employee-form__input"
afId="edit-employee-form-email"
afLabel="E-post adress"
afType="email"
[formControlName]="emailFormControlName"
[afInvalidMessage]="emailFormControl?.errors?.required ? 'Du måste ange E-post' : 'E-post adressen är ogiltig'"
[afDisableValidStyle]="true"
[afInvalid]="emailFormControl.invalid && emailFormControl.touched"
></digi-ng-form-input>
<fieldset *ngIf="authorizationsFormGroup && selectableAuthorizations" [formGroup]="authorizationsFormGroup">
<legend>Tjänster</legend>
<p>
Välj de tjänster du vill ge personalen tillgång till.
</p>
<digi-ng-form-select
[formControl]=""
afLabel="Välj tjänster"
[afSelectItems]="[{'name': 'Välj tjänst', 'value': ''}]"
[afDescription]="description"
[afDisableValidStyle]="true"
[afDisableValidation]="disableValidation"
[afValidMessage]="validMessage"
[afDisabled]="disabled"
[afInvalidMessage]="invalidMessage"
[afInvalid]="invalid"
(afOnChange)="toggleService(selectableServices, $event)"
></digi-ng-form-select>
<div class="employee-form__service-tag">
<ng-container *ngFor="let employeeService of currentEmployeeServices">
<digi-tag
class="employee-form__service-tag--item"
[attr.af-text]="employeeService.name"
af-no-icon="false"
af-size="s"
(click)="unselectEmployeeService()"
>
</digi-tag>
</ng-container>
</div>
</fieldset>
<fieldset *ngIf="authorizationsFormGroup && selectableAuthorizations" [formGroup]="authorizationsFormGroup">
<legend>Utförande verksamheter och adresser</legend>
<p>
Välj de utförandeverksamheter och utförande adresser du vill ge personalen behörighet till.
</p>
<div class="edit-employee-form__choose_all-utforande-verksamh">
<digi-form-checkbox
af-variation="primary"
[afLabel]="'Välj alla utförade verksamheter och alla utförande adresser'"
[afValue]=""
(afOnChange)="selectAllUtforandeVerksamheter($event.detail.target.checked)"
></digi-form-checkbox>
</div>
<div
style="
display: flex;
border: 1px solid;
background-color: #eee;
padding: 5px;
justify-content: space-between;
"
>
Plats för digi-select-form-item för utförande verksamheter
<digi-icon-arrow-down></digi-icon-arrow-down>
</div>
</fieldset>
<fieldset *ngIf="authorizationsFormGroup && selectableAuthorizations" [formGroup]="authorizationsFormGroup">
<legend>Behörigheter</legend>
<p>
Här tilldelar du specifika behörigheter i systemet. Välj nedan vilka arbetsuppgifter som användaren ska kunna
utföra. Tänk på att behörigheten i systemet är begränsad till de utförande verksamheter och adresser som
användaren hör till. Användaren kan därför endast utföra uppgifter och se information inom den/ de utförande
adresser som tilldelats användaren.
<digi-ng-button
class="edit-employee-form__open-authorization-dialog-btn"
[afVariation]="ButtonVariation.TERTIARY"
[afType]="ButtonType.BUTTON"
[afSize]="ButtonSize.S"
[afAriaControls]="'authorization-dialog'"
[afAriaLabel]="'Öppnar en dialog med information om behörigheter'"
(afOnClick)="openAuthorizationDialog()"
>
Läs mer om behörigheter här
</digi-ng-button>
</p>
<ul class="edit-employee-form__authorizations">
<li class="edit-employee-form__authorization-item" *ngFor="let authorization of selectableAuthorizations">
<digi-ng-form-checkbox
[afLabel]="authorization.name"
[formControlName]="getFormControlName(authorization)"
></digi-ng-form-checkbox>
</li>
</ul>
</fieldset>
<div class="edit-employee-form__footer">
<a class="edit-employee-form__link-btn edit-employee-form__link-btn--secondary" routerLink="/administration/">
Avbryt
</a>
<digi-button af-type="submit">Spara ändringar</digi-button>
</div>
</form>
</digi-typography>
<digi-ng-dialog
id="authorization-dialog"
[afActive]="displayAuthorizationDialog"
(afOnInactive)="closeAuthorizationDialog()"
(afOnPrimaryClick)="closeAuthorizationDialog()"
[afHeading]="'Behörighet'"
afHeadingLevel="h1"
afPrimaryButtonText="Stäng"
afSecondaryButtonText=""
>
<p>
Behörigheten passar personer som arbetar nära deltagare. Behörigheten kan användas av exempelvis handledare,
coacher, studie- och yrkesvägledare, lärare eller annan roll som behöver kunna se information om deltager, kontakta
deltagare, planera aktiviteter med deltagre och hantera rapporter för deltagre.
</p>
<p>Behörigheten ger tillgång till och utföra aktiviteter i följande funktioner i systemet:</p>
<p>
- Deltagarlista <br />
- Information om deltagare <br />
- Resultatrapporter <br />
- Slutredovisning <br />
- Informativ rapport <br />
- Skicka välkomstbrev * <br />
- Planera deltagares aktiviteter <br />
- Deltagares schema <br />
- Avvikelserapporter <br />
- Närvaro- och frånvarorapporter <br /><br />
</p>
</digi-ng-dialog>

View File

@@ -0,0 +1,92 @@
@import 'mixins/list';
@import 'variables/gutters';
@import '~@digi/core/dist/collection/components/_button/button/button.css';
.edit-employee-form {
max-width: var(--digi--typography--text--max-width);
fieldset {
margin: 2.5rem 0;
padding: 0;
border: 0 none transparent;
}
legend {
width: 100%;
padding: 0;
display: flex;
align-items: center;
font-weight: var(--digi--typography--font-weight--semibold);
font-size: var(--digi--typography--font-size--h2--desktop);
margin-bottom: var(--digi-typography--margin--h2);
}
&__input {
display: block;
width: 100%;
margin-bottom: var(--digi--layout--gutter);
}
&__authorizations {
@include msfa__reset-list;
margin-bottom: var(--digi--layout--gutter);
}
&__authorization-item {
margin-top: var(--digi--layout--gutter);
::ng-deep label {
display: block !important;
}
}
&__open-authorization-dialog-btn {
::ng-deep button {
padding: 0 !important;
}
}
&__footer {
margin-top: $digi--layout--gutter--xl;
display: flex;
gap: var(--digi--layout--gutter);
}
&__link-btn {
font-family: var(--digi-button--font-family);
background: var(--digi-button--background);
color: var(--digi-button--color);
padding: var(--digi-button--padding);
border-radius: var(--digi-button--border-radius);
border: var(--digi-button--border);
border-color: var(--digi-button--border-color);
font-weight: var(--digi-button--font-weight);
font-size: var(--digi-button--font-size);
outline: var(--digi-button--outline);
text-align: var(--digi-button--text-align);
cursor: pointer;
width: var(--digi-button--width);
display: var(--digi-button--display);
text-align: var(--digi-button--text-align);
text-decoration: none;
}
&__link-btn--secondary {
--digi-button--background: var(--digi-button--background--secondary);
--digi-button--background--hover: var(--digi-button--background--secondary--hover);
--digi-button--color: var(--digi-button--color--secondary);
--digi-button--color--hover: var(--digi-button--color--secondary);
--digi-button--border-color--disabled: var(--digi-button--border-color--secondary--disabled);
&:focus,
&:hover {
--digi-button--background: var(--digi-button--background--hover);
--digi-button--border-color: var(--digi-button--border-color--hover);
--digi-button--color: var(--digi-button--color--hover);
--digi-button--outline: var(--digi-button--outline--focus);
}
}
&__choose_all-utforande-verksamh {
margin: 1.5rem 0;
}
}

View File

@@ -0,0 +1,42 @@
import { DigiNgFormCheckboxModule } from '@af/digi-ng/_form/form-checkbox';
import { DigiNgFormDatepickerModule } from '@af/digi-ng/_form/form-datepicker';
import { DigiNgFormInputModule } from '@af/digi-ng/_form/form-input';
import { DigiNgFormRadiobuttonGroupModule } from '@af/digi-ng/_form/form-radiobutton-group';
import { DigiNgFormSelectModule } from '@af/digi-ng/_form/form-select';
import { DigiNgPopoverModule } from '@af/digi-ng/_popover/popover';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ReactiveFormsModule } from '@angular/forms';
import { EditEmployeeFormComponent } from './edit-employee-form.component';
describe('EditEmployeeFormComponent', () => {
let component: EditEmployeeFormComponent;
let fixture: ComponentFixture<EditEmployeeFormComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [EditEmployeeFormComponent],
imports: [
ReactiveFormsModule,
DigiNgFormInputModule,
DigiNgFormRadiobuttonGroupModule,
DigiNgFormDatepickerModule,
DigiNgFormSelectModule,
DigiNgPopoverModule,
DigiNgFormCheckboxModule,
],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
}).compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(EditEmployeeFormComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,175 @@
import { ButtonSize, ButtonType, ButtonVariation } from '@af/digi-ng/_button/button';
import { FormSelectItem } from '@af/digi-ng/_form/form-select';
import {
Component,
OnInit,
ChangeDetectionStrategy,
Input,
OnChanges,
SimpleChanges,
EventEmitter,
Output,
} from '@angular/core';
import { AbstractControl, FormControl, FormGroup, Validators } from '@angular/forms';
import { Authorization } from '@msfa-models/authorization.model';
import { Service } from '@msfa-models/service.model';
export interface EditEmployeeFormData {
email: string;
authorizations: Array<Authorization>;
}
@Component({
selector: 'msfa-edit-employee-form',
templateUrl: './edit-employee-form.component.html',
styleUrls: ['./edit-employee-form.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class EditEmployeeFormComponent implements OnInit, OnChanges {
@Input() currentEmail: string | null = null;
@Input() selectableAuthorizations: Array<Authorization> | null = null;
@Input() currentEmployeeAuthorizations: Array<Authorization> | null = null;
@Output() formSubmitted = new EventEmitter<EditEmployeeFormData>();
@Input() selectableServices: Array<Service> | null = null;
@Input() currentEmployeeServices: Array<Service> | null = null;
readonly ButtonVariation = ButtonVariation;
readonly ButtonType = ButtonType;
readonly ButtonSize = ButtonSize;
readonly emailFormControlName = 'email';
editEmployeeFormGroup: FormGroup | null = null;
authorizationsFormGroup: FormGroup | null = null;
displayAuthorizationDialog = false;
constructor() {}
ngOnInit(): void {
console.log(':::::::', this.selectableServices);
console.log('!!!!!!!', this.currentEmployeeServices);
this.initializeEditEmployeeFormGroup();
}
ngOnChanges(changes: SimpleChanges): void {
if (changes.selectableAuthorizations) {
this.initializeEditEmployeeFormGroup();
}
if (changes.currentEmployeeAuthorizations) {
this.updateAuthorizationFormGroup();
}
if (changes.currentEmail) {
this.editEmployeeFormGroup.patchValue(Object.fromEntries([[this.emailFormControlName, this.currentEmail]]));
}
}
get emailFormControl(): AbstractControl | null {
return this.editEmployeeFormGroup?.get(this.emailFormControlName);
}
onFormSubmitted(): void {
if (!this.editEmployeeFormGroup) {
return;
}
this.editEmployeeFormGroup.markAllAsTouched();
if (this.editEmployeeFormGroup.invalid) {
return;
}
this.formSubmitted.emit({
email: this.emailFormControl?.value,
authorizations: this.getAuthorizationsFromFormGroup(this.authorizationsFormGroup, this.selectableAuthorizations),
});
}
getFormControlName(authorization: Authorization): string {
return authorization?.id?.replace(/[^a-zA-Z0-9]/g, '');
}
openAuthorizationDialog(): void {
this.displayAuthorizationDialog = true;
}
closeAuthorizationDialog(): void {
this.displayAuthorizationDialog = false;
}
private initializeEditEmployeeFormGroup(): void {
this.authorizationsFormGroup = this.getAuthorizationFormGroup(
this.selectableAuthorizations,
this.currentEmployeeAuthorizations
);
this.editEmployeeFormGroup = new FormGroup({
email: new FormControl(this.currentEmail, [Validators.required, Validators.email]),
authorizations: this.authorizationsFormGroup,
});
}
private updateAuthorizationFormGroup(): void {
if (!this.authorizationsFormGroup || !this.selectableAuthorizations) {
return;
}
this.authorizationsFormGroup.patchValue(
Object.fromEntries(
this.selectableAuthorizations.map(authorization => [
this.getFormControlName(authorization),
this.isSelectedAuthorization(authorization, this.currentEmployeeAuthorizations),
])
)
);
}
private getAuthorizationsFromFormGroup(
formGroup: FormGroup | null,
authorizations: Array<Authorization> | null
): Array<Authorization> {
if (!formGroup || !authorizations) {
return;
}
return authorizations.filter(
authorization => formGroup.get(this.getFormControlName(authorization))?.value === true
);
}
private getAuthorizationFormGroup(
authorizations: Array<Authorization> | null,
selectedAuthorizations: Array<Authorization> | null
): FormGroup {
if (!authorizations) {
return new FormGroup({});
}
return new FormGroup(
Object.fromEntries(
authorizations.map(authorization => [
this.getFormControlName(authorization),
new FormControl(this.isSelectedAuthorization(authorization, selectedAuthorizations), []),
])
)
);
}
private isSelectedAuthorization(
authorization: Authorization,
selectedAuthorizations: Array<Authorization> | null
): boolean {
if (!selectedAuthorizations || !authorization) {
return false;
}
return selectedAuthorizations.some(selectedAuthorization => selectedAuthorization.id === authorization.id);
}
// Services helper methods
unselectEmployeeService() {
console.log('Unselect the service from list and tag will get removed');
}
}

View File

@@ -1,14 +1,6 @@
<msfa-layout>
<section class="employee-form">
<digi-typography>
<h1>Skapa nytt konto</h1>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam magna neque, interdum vel massa eget, condimentum
rutrum velit. Sed vitae ullamcorper sem. Aliquam malesuada nunc sed purus mollis scelerisque. Curabitur bibendum
leo quis ante porttitor tincidunt. Nam tincidunt imperdiet tortor eu suscipit. Maecenas ut dui est.
</p>
</digi-typography>
<form [formGroup]="formGroup" (ngSubmit)="submitForm()">
<section class="employee-form" *ngIf="employee$ | async as employee">
<!--### Errormeddelanden ###-->
<digi-form-error-list
class="employee-form__error-list"
*ngIf="formGroup.invalid && submitted && formErrors.length"
@@ -19,146 +11,44 @@
>
</digi-form-error-list>
<digi-typography>
<h1>{{ employee.fullName }}</h1>
</digi-typography>
<!--### Personuppgifter ###-->
<div class="employee-form__block">
<digi-typography>
<h2>Personuppgifter</h2>
</digi-typography>
<digi-ng-form-input
afId="employee-form-firstName"
class="employee-form__input"
formControlName="firstName"
afLabel="Förnamn"
afInvalidMessage="Förnamn är obligatoriskt"
[afDisableValidStyle]="true"
[afInvalid]="firstNameControl.invalid && firstNameControl.dirty"
></digi-ng-form-input>
<digi-ng-form-input
afId="employee-form-lastName"
class="employee-form__input"
formControlName="lastName"
afLabel="Efternamn"
afInvalidMessage="Efternamn är obligatoriskt"
[afDisableValidStyle]="true"
[afInvalid]="lastNameControl.invalid && lastNameControl.dirty"
></digi-ng-form-input>
<digi-ng-form-input
afId="employee-form-ssn"
class="employee-form__input"
formControlName="ssn"
afLabel="Personnummer"
[afInvalidMessage]="ssnControl.errors?.message || ''"
[afDisableValidStyle]="true"
[afInvalid]="ssnControl.invalid && ssnControl.dirty"
></digi-ng-form-input>
</div>
<div class="employee-form__block" *ngIf="services$ | async as services">
<fieldset class="employee-form__fieldset">
<ng-container class="employee-form__privateInformation">
<digi-typography>
<legend>Tjänster</legend>
<h4>Förnamn</h4>
<p>{{employee.firstName}}</p>
</digi-typography>
<ul class="employee-form__services">
<li *ngFor="let service of services; let first = first" class="employee-form__service-item">
<digi-form-checkbox
[afId]="(first && 'employee-form-services') || undefined"
af-variation="primary"
[afValidation]="servicesControl.invalid && servicesControl.dirty && 'error'"
[afLabel]="service.name"
[afValue]="service.id"
[afChecked]="servicesControl.value.includes(service)"
(afOnChange)="toggleService(service, $event.detail.target.checked)"
></digi-form-checkbox>
</li>
</ul>
<digi-form-validation-message
class="employee-form__validation-message"
*ngIf="servicesControl.invalid && servicesControl.dirty"
af-variation="error"
>
{{ servicesControl.errors.message }}
</digi-form-validation-message>
</fieldset>
</div>
<div class="employee-form__block" *ngIf="authorizations$ | async as authorizations">
<fieldset class="employee-form__fieldset">
<digi-typography>
<legend>Tilldela behörigheter</legend>
<h4>Efternamn</h4>
<p>{{employee.lastName}}</p>
</digi-typography>
<ul class="employee-form__authorizations">
<li
*ngFor="let authorization of authorizations; let first = first"
class="employee-form__authorization-item"
>
<digi-form-checkbox
class="employee-form__digi-checkbox"
[afId]="(first && 'employee-form-authorizations') || undefined"
af-variation="primary"
[afValidation]="authorizationsControl.invalid && authorizationsControl.dirty && 'error'"
[afLabel]="authorization.name"
[afValue]="authorization.id"
[afChecked]="authorizationsControl.value.includes(authorization)"
(afOnChange)="toggleAuthorization(authorization, $event.detail.target.checked)"
></digi-form-checkbox>
<digi-button
af-variation="secondary"
[afAriaLabel]="'Läs mer om ' + authorization.name"
af-size="s"
class="employee-form__read-more"
(afOnClick)="openDialog(true, authorization.name)"
>
Läs mer
</digi-button>
</li>
</ul>
<digi-form-validation-message
class="employee-form__validation-message"
*ngIf="authorizationsControl.invalid && authorizationsControl.dirty"
af-variation="error"
>
{{ authorizationsControl.errors.message }}
</digi-form-validation-message>
</fieldset>
<digi-typography>
<h4>Personnummer</h4>
<msfa-hide-text
symbols="********-****"
[changingText]="employee.ssn"
ariaLabelType="personnummer"
></msfa-hide-text>
</digi-typography>
</ng-container>
</div>
<div class="employee-form__footer">
<digi-button af-type="reset" af-variation="secondary" (afOnClick)="resetForm($event.detail)"
>Avbryt</digi-button
>
<digi-button af-type="submit">Registrera konto</digi-button>
</div>
<!-- Modal/ Dialog window -->
<digi-ng-dialog
[afActive]="toggleDialog"
(afOnInactive)="openDialog(false)"
(afOnPrimaryClick)="openDialog(false)"
[afHeading]="modalAuthInfo.name"
afHeadingLevel="h3"
afPrimaryButtonText="Stäng"
>
<p>
Behörigheten passar personer som arbetar nära deltagare. Behörigheten kan användas av exempelvis handledare,
coacher, studie- och yrkesvägledare, lärare eller annan roll som behöver kunna se information om deltager,
kontakta deltagare, planera aktiviteter med deltagre och hantera rapporter för deltagre.
</p>
<p>Behörigheten ger tillgång till och utföra aktiviteter i följande funktioner i systemet:</p>
<p>
- Deltagarlista <br />
- Information om deltagare <br />
- Resultatrapporter <br />
- Slutredovisning <br />
- Informativ rapport <br />
- Skicka välkomstbrev * <br />
- Planera deltagares aktiviteter <br />
- Deltagares schema <br />
- Avvikelserapporter <br />
- Närvaro- och frånvarorapporter <br /><br />
</p>
</digi-ng-dialog>
</form>
<!-- Component för att hantera formuläret -->
<msfa-edit-employee-form
[currentEmail]="employee?.email"
[selectableAuthorizations]="authorizations$ | async"
[currentEmployeeAuthorizations]="employee?.authorizations"
[selectableServices]="services$ | async"
[currentEmployeeServices]="employee.services"
(formSubmitted)="updateEmployee($event)"
></msfa-edit-employee-form>
</section>
</msfa-layout>

View File

@@ -1,16 +1,18 @@
import { FormSelectBaseItem } from '@af/digi-ng/_form/form-select-base';
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { AbstractControl, FormBuilder, FormGroup } from '@angular/forms';
import { Router } from '@angular/router';
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { AbstractControl, FormBuilder, FormGroup, Validators } 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 { SocialSecurityNumberValidator } from '@msfa-utils/validators/social-security-number.validator';
import { RequiredValidator } from '@msfa-validators/required.validator';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { map, switchMap } from 'rxjs/operators';
import { EditEmployeeFormData } from './edit-employee-form/edit-employee-form.component';
@Component({
selector: 'msfa-employee-form',
@@ -18,9 +20,12 @@ import { map } from 'rxjs/operators';
styleUrls: ['./employee-form.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class EmployeeFormComponent {
export class EmployeeFormComponent extends UnsubscribeDirective implements OnInit {
employee$: Observable<Employee>;
services$: Observable<Service[]> = this.serviceService.services$;
authorizations$: Observable<Authorization[]> = this.authorizationService.authorizations$;
employeeCurrentServices: Service[] | null | undefined;
servicesSelectItems$: Observable<FormSelectBaseItem[]> = this.services$.pipe(
map(services => services.map(({ name, id }) => ({ name, value: id })))
);
@@ -28,11 +33,9 @@ export class EmployeeFormComponent {
modalAuthInfo: { name: string } = { name: 'Test Behörighetsnamn' };
formGroup: FormGroup = this.formBuilder.group({
firstName: this.formBuilder.control('', [RequiredValidator('Förnamn')]),
lastName: this.formBuilder.control('', [RequiredValidator('Efternamn')]),
ssn: this.formBuilder.control('', [RequiredValidator('Personnummer'), SocialSecurityNumberValidator()]),
email: this.formBuilder.control('', [Validators.required, Validators.email]),
services: this.formBuilder.control([], [RequiredValidator('en tjänst')]),
authorizations: this.formBuilder.control([], [RequiredValidator('en behörighet')]),
authorizations: new FormGroup({}),
});
todaysDate = new Date();
submitted = false;
@@ -42,24 +45,32 @@ export class EmployeeFormComponent {
private employeeService: EmployeeService,
private serviceService: ServiceService,
private authorizationService: AuthorizationService,
private router: Router
) {}
private router: Router,
private activatedRoute: ActivatedRoute
) {
super();
super.unsubscribeOnDestroy();
}
get firstNameControl(): AbstractControl {
return this.formGroup.get('firstName');
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; */
});
}
get lastNameControl(): AbstractControl {
return this.formGroup.get('lastName');
}
get ssnControl(): AbstractControl {
return this.formGroup.get('ssn');
updateEmployee(editEmployeeFormData: EditEmployeeFormData): void {
console.log(editEmployeeFormData);
}
get servicesControl(): AbstractControl {
return this.formGroup.get('services');
}
get authorizationsControl(): AbstractControl {
return this.formGroup.get('authorizations');
}
get formErrors(): { id: string; message: string }[] {
const controlsWithErrors = Object.keys(this.formGroup.controls).filter(
@@ -80,26 +91,25 @@ export class EmployeeFormComponent {
});
}
toggleAuthorization(authorization: Authorization, checked: boolean): void {
const currentAuthorizations = this.authorizationsControl.value as { id: unknown }[];
toggleService(service: Service, id: string): void {
/* //const currentServices = this.servicesControl.value as { id: unknown }[];
const selectedServiceObject = this.employeeCurrentServices.find(obj => obj.id === id);
const serviceObjectExists = selectedServiceObject
? this.employeeCurrentServices.some(obj => obj.id === selectedServiceObject.id)
: false;
if (checked) {
this.authorizationsControl.patchValue([...currentAuthorizations, authorization]);
} else {
this.authorizationsControl.patchValue(
currentAuthorizations.filter(currentAuthorization => currentAuthorization.id !== authorization.id)
);
}
if (!serviceObjectExists && selectedServiceObject !== undefined) {
this.employeeCurrentServices.push(selectedServiceObject);
} */
}
toggleService(service: Service, checked: boolean): void {
const currentServices = this.servicesControl.value as { id: unknown }[];
if (checked) {
this.servicesControl.patchValue([...currentServices, service]);
} else {
this.servicesControl.patchValue(currentServices.filter(currentService => currentService.id !== service.id));
}
unselectService(id: string, service: Service) {
/* const selectedServiceObject = this.employeeCurrentServices.find(obj => obj.id === id);
const serviceObjectExists = this.employeeCurrentServices?.some(x => (x.id = id));
console.log('employeeCurrentServices', this.employeeCurrentServices);
if (serviceObjectExists && selectedServiceObject !== undefined) {
this.employeeCurrentServices.splice(this.employeeCurrentServices.indexOf(selectedServiceObject), 1);
} */
}
openDialog(val: boolean, authName?: string): void {

View File

@@ -5,6 +5,7 @@ import { DigiNgFormInputModule } from '@af/digi-ng/_form/form-input';
import { DigiNgFormRadiobuttonGroupModule } from '@af/digi-ng/_form/form-radiobutton-group';
import { DigiNgFormSelectModule } from '@af/digi-ng/_form/form-select';
import { DigiNgPopoverModule } from '@af/digi-ng/_popover/popover';
import { DigiNgButtonModule } from '@af/digi-ng/_button/button';
import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms';
@@ -12,14 +13,15 @@ import { RouterModule } from '@angular/router';
import { LayoutModule } from '@msfa-shared/components/layout/layout.module';
import { LocalDatePipeModule } from '@msfa-shared/pipes/local-date/local-date.module';
import { EmployeeFormComponent } from './employee-form.component';
import { EditEmployeeFormComponent } from './edit-employee-form/edit-employee-form.component';
import { HideTextModule } from '@msfa-shared/components/hide-text/hide-text.module';
@NgModule({
schemas: [CUSTOM_ELEMENTS_SCHEMA],
declarations: [EmployeeFormComponent],
declarations: [EmployeeFormComponent, EditEmployeeFormComponent],
imports: [
CommonModule,
RouterModule.forChild([{ path: '', component: EmployeeFormComponent }]),
LayoutModule,
ReactiveFormsModule,
LocalDatePipeModule,
DigiNgFormInputModule,
@@ -29,6 +31,9 @@ import { EmployeeFormComponent } from './employee-form.component';
DigiNgPopoverModule,
DigiNgFormCheckboxModule,
DigiNgDialogModule,
DigiNgButtonModule,
LayoutModule,
HideTextModule,
],
})
export class EmployeeFormModule {}

View File

@@ -0,0 +1,5 @@
export enum ButtonSize {
S = 's',
M = 'm',
L = 'l',
}

View File

@@ -1,8 +1,6 @@
import { Authorization as AuthorizationEnum } from '@msfa-enums/authorization.enum';
export interface Authorization {
id: string;
name: AuthorizationEnum;
name: string;
}
export interface AuthorizationApiResponse {
@@ -11,7 +9,7 @@ export interface AuthorizationApiResponse {
export interface AuthorizationApiResponseData {
id: string;
name: AuthorizationEnum;
name: string;
}
export function mapAuthorizationApiResponseToAuthorization(data: AuthorizationApiResponseData): Authorization {

View File

@@ -31,6 +31,7 @@ function generateEmployees(amount = 10) {
min: 1000,
max: 9999,
})}`,
email: '',
roles: hasBehorigheter ? ['Admin'] : [],
tjanst: hasBehorigheter ? currentTjanster.map(tjanst => tjanst.name) : [],
tjansteKoder: hasBehorigheter ? currentTjanster.map(tjanst => tjanst.code) : [],
@@ -38,6 +39,7 @@ function generateEmployees(amount = 10) {
utforandeVerksamhetIds: hasBehorigheter ? currentOrganizations.map(organization => organization.id) : [],
};
employee.email = `${employee.firstName}.${employee.lastName}@private-epost.se`.toLowerCase();
employees.push(employee);
}

View File

@@ -11,6 +11,7 @@ import participants from './participants.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 organizations = [];
const kommuner = [];
@@ -67,6 +68,12 @@ generatedAvrop.forEach(({ tjanstekod, tjansteNamn, utforandeVerksamhetId, utfora
}
});
generatedEmployees.forEach(employee => {
employee.authorizations = [
auths[Math.floor(Math.random() * auths.length)],
auths[Math.floor(Math.random() * auths.length)],
];
});
const apiData = {
languages: languages.generate(),
employees: generatedEmployees,
@@ -80,7 +87,7 @@ const apiData = {
employeeId: generatedEmployees[Math.floor(Math.random() * generatedEmployees.length)].id,
})),
currentUser: currentUser.generate(),
authorizations: authorizations.generate(),
authorizations: auths,
getTokenFullAccess: authTokens.auth_code_from_CIAM_with_all_permissions,
invites: [],
};

View File

@@ -17,6 +17,7 @@ server.use(
'/employees*onlyEmployeesWithoutAuthorization=*': '/employees$1roles.length_lte=0',
'/employees/invite': '/invites',
'/employees*': '/employees$1',
'/services*': '/tjanster$1',
'/participants': '/participants?_embed=employees',
'/participant/:id': '/participants/:id?_embed=employees',
'/auth/userinfo': '/currentUser',