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:
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
@@ -1,164 +1,54 @@
|
||||
<msfa-layout>
|
||||
<section class="employee-form">
|
||||
<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"
|
||||
af-heading="Felmeddelanden"
|
||||
>
|
||||
<a *ngFor="let error of formErrors" [routerLink]="" [fragment]="'employee-form-' + error.id"
|
||||
>{{ error.message }}</a
|
||||
>
|
||||
</digi-form-error-list>
|
||||
|
||||
<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>
|
||||
<h1>{{ employee.fullName }}</h1>
|
||||
</digi-typography>
|
||||
<form [formGroup]="formGroup" (ngSubmit)="submitForm()">
|
||||
<digi-form-error-list
|
||||
class="employee-form__error-list"
|
||||
*ngIf="formGroup.invalid && submitted && formErrors.length"
|
||||
af-heading="Felmeddelanden"
|
||||
>
|
||||
<a *ngFor="let error of formErrors" [routerLink]="" [fragment]="'employee-form-' + error.id"
|
||||
>{{ error.message }}</a
|
||||
>
|
||||
</digi-form-error-list>
|
||||
|
||||
<div class="employee-form__block">
|
||||
<!--### Personuppgifter ###-->
|
||||
<div class="employee-form__block">
|
||||
<digi-typography>
|
||||
<h2>Personuppgifter</h2>
|
||||
</digi-typography>
|
||||
|
||||
<ng-container class="employee-form__privateInformation">
|
||||
<digi-typography>
|
||||
<h2>Personuppgifter</h2>
|
||||
<h4>Förnamn</h4>
|
||||
<p>{{employee.firstName}}</p>
|
||||
</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">
|
||||
<digi-typography>
|
||||
<legend>Tjänster</legend>
|
||||
</digi-typography>
|
||||
<digi-typography>
|
||||
<h4>Efternamn</h4>
|
||||
<p>{{employee.lastName}}</p>
|
||||
</digi-typography>
|
||||
<digi-typography>
|
||||
<h4>Personnummer</h4>
|
||||
<msfa-hide-text
|
||||
symbols="********-****"
|
||||
[changingText]="employee.ssn"
|
||||
ariaLabelType="personnummer"
|
||||
></msfa-hide-text>
|
||||
</digi-typography>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
<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>
|
||||
</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>
|
||||
</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>
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
export enum ButtonSize {
|
||||
S = 's',
|
||||
M = 'm',
|
||||
L = 'l',
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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: [],
|
||||
};
|
||||
|
||||
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user