feat(employee): Now possible to edit employee and remove data, also changed validation-rules. (TV-631)
Squashed commit of the following:
commit 082d573764be4306255d5b99f28095f96691ec43
Merge: 528b858 5846c2c
Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se>
Date: Wed Sep 22 07:32:17 2021 +0200
Merged develop and fixed conflict
commit 528b858f17919836ce0aaa0e09e100855ad00762
Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se>
Date: Wed Sep 22 07:25:08 2021 +0200
Updated validation
commit 28d37a1eb95a8df2520b3e7967c91e7da9e508f6
Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se>
Date: Tue Sep 21 08:20:36 2021 +0200
Updated validation functionality to support submit without tjänster or utförande verksamheter
This commit is contained in:
@@ -15,10 +15,16 @@
|
|||||||
afLabel="E-post adress"
|
afLabel="E-post adress"
|
||||||
afType="email"
|
afType="email"
|
||||||
[formControlName]="emailFormControlName"
|
[formControlName]="emailFormControlName"
|
||||||
[afInvalidMessage]="emailFormControl?.errors?.required ? 'Du måste ange E-post' : 'E-post adressen är ogiltig'"
|
|
||||||
[afDisableValidStyle]="true"
|
[afDisableValidStyle]="true"
|
||||||
[afInvalid]="emailFormControl.invalid && emailFormControl.touched"
|
[afInvalid]="editEmployeeFormGroup.errors?.email && emailFormControl.touched"
|
||||||
></digi-ng-form-input>
|
></digi-ng-form-input>
|
||||||
|
<div aria-atomic="true" role="alert">
|
||||||
|
<digi-form-validation-message
|
||||||
|
*ngIf="editEmployeeFormGroup.errors?.email && emailFormControl.touched"
|
||||||
|
af-variation="error"
|
||||||
|
>{{editEmployeeFormGroup.errors.email}}</digi-form-validation-message
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="edit-employee-form__contents">
|
<div class="edit-employee-form__contents">
|
||||||
<div class="edit-employee-form__block">
|
<div class="edit-employee-form__block">
|
||||||
@@ -35,16 +41,18 @@
|
|||||||
[afPlaceholder]="'Välj tjänst'"
|
[afPlaceholder]="'Välj tjänst'"
|
||||||
[afSelectItems]="selectableTjansterFormItems"
|
[afSelectItems]="selectableTjansterFormItems"
|
||||||
[afDisableValidStyle]="true"
|
[afDisableValidStyle]="true"
|
||||||
[afInvalid]="tjansterFormControl.invalid && tjansterFormControl.touched"
|
[afInvalid]="editEmployeeFormGroup.errors?.tjanster && tjansterFormControl.touched"
|
||||||
[afId]="tjansterElementId"
|
[afId]="tjansterElementId"
|
||||||
(afOnChange)="toggleTjanst()"
|
(afOnChange)="toggleTjanst()"
|
||||||
></digi-ng-form-select>
|
></digi-ng-form-select>
|
||||||
<digi-form-validation-message
|
<div aria-atomic="true" role="alert">
|
||||||
*ngIf="tjansterFormControl.invalid && tjansterFormControl.touched"
|
<digi-form-validation-message
|
||||||
af-variation="error"
|
*ngIf="editEmployeeFormGroup.errors?.tjanster && tjansterFormControl.touched"
|
||||||
>
|
af-variation="error"
|
||||||
Du måste välja minst en tjänst
|
>
|
||||||
</digi-form-validation-message>
|
{{editEmployeeFormGroup.errors.tjanster}}
|
||||||
|
</digi-form-validation-message>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="edit-employee-form__block">
|
<div class="edit-employee-form__block">
|
||||||
@@ -59,6 +67,7 @@
|
|||||||
class="edit-employee-form__choose-all-utforande-verksamheter"
|
class="edit-employee-form__choose-all-utforande-verksamheter"
|
||||||
[formControl]="selectAllUtforandeVerksamheterFormControl"
|
[formControl]="selectAllUtforandeVerksamheterFormControl"
|
||||||
[afLabel]="'Välj alla utförande verksamheter och alla utförande adresser'"
|
[afLabel]="'Välj alla utförande verksamheter och alla utförande adresser'"
|
||||||
|
[afInvalid]="editEmployeeFormGroup.errors?.utforandeVerksamheter && (selectAllUtforandeVerksamheterFormControl.touched || utforandeVerksamheterFormControl.touched)"
|
||||||
></digi-ng-form-checkbox>
|
></digi-ng-form-checkbox>
|
||||||
|
|
||||||
<msfa-tree-nodes-selector
|
<msfa-tree-nodes-selector
|
||||||
@@ -66,16 +75,16 @@
|
|||||||
[buttonElementId]="utforandeVerksamhetElementId"
|
[buttonElementId]="utforandeVerksamhetElementId"
|
||||||
[headingText]="'Välj utförande verksamheter och adresser'"
|
[headingText]="'Välj utförande verksamheter och adresser'"
|
||||||
[formControlName]="utforandeVerksamheterFormControlName"
|
[formControlName]="utforandeVerksamheterFormControlName"
|
||||||
[isInvalid]="editEmployeeFormGroup.invalid && editEmployeeFormGroup.errors?.noUtforandeVerksamhetSelected"
|
[isInvalid]="editEmployeeFormGroup.errors?.utforandeVerksamheter"
|
||||||
[showValidation]="utforandeVerksamheterFormControl?.touched"
|
[showValidation]="editEmployeeFormGroup.errors?.utforandeVerksamheter && (utforandeVerksamheterFormControl?.touched || selectAllUtforandeVerksamheterFormControl.touched)"
|
||||||
[validationMessages]="editEmployeeFormGroup.errors?.noUtforandeVerksamhetSelected ? [utforandeVerksamhetRequiredMessage] : []"
|
[validationMessages]="[editEmployeeFormGroup.errors?.utforandeVerksamheter]"
|
||||||
(selectedTreeNodesChanged)="updateToggleAllUtforandeVerksamheter()"
|
(selectedTreeNodesChanged)="updateToggleAllUtforandeVerksamheter()"
|
||||||
></msfa-tree-nodes-selector>
|
></msfa-tree-nodes-selector>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-template #loadingUtforandeVerksamheterTemplate>
|
<ng-template #loadingUtforandeVerksamheterTemplate>
|
||||||
<digi-ng-loader-spinner
|
<digi-ng-loader-spinner
|
||||||
*ngIf="isLoadingUtforandeVerksamheter"
|
*ngIf="isLoadingUtforandeVerksamheter"
|
||||||
[afLabel]="'Läser in utförande verksamheter för vald/a tjänster...'"
|
[afLabel]="'Läser in utförande verksamheter för valda tjänster...'"
|
||||||
></digi-ng-loader-spinner>
|
></digi-ng-loader-spinner>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -24,9 +24,7 @@ import { UtforandeVerksamheterService } from '@msfa-services/utforande-verksamhe
|
|||||||
import { ValidationErrorLink } from '@msfa-shared/components/error-list/error-list.component';
|
import { ValidationErrorLink } from '@msfa-shared/components/error-list/error-list.component';
|
||||||
import { TreeNodesSelectorService } from '@msfa-shared/components/tree-nodes-selector/services/tree-nodes-selector.service';
|
import { TreeNodesSelectorService } from '@msfa-shared/components/tree-nodes-selector/services/tree-nodes-selector.service';
|
||||||
import { uuid } from '@msfa-utils/uuid';
|
import { uuid } from '@msfa-utils/uuid';
|
||||||
import { EmailValidator } from '@msfa-utils/validators/email.validator';
|
|
||||||
import { EmployeeValidator } from '@msfa-utils/validators/employee.validator';
|
import { EmployeeValidator } from '@msfa-utils/validators/employee.validator';
|
||||||
import { RequiredValidator } from '@msfa-utils/validators/required.validator';
|
|
||||||
import { EmployeeFormService } from '../services/employee-form.service';
|
import { EmployeeFormService } from '../services/employee-form.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -162,27 +160,21 @@ export class EditEmployeeFormComponent implements OnInit, OnChanges {
|
|||||||
|
|
||||||
this.editEmployeeFormGroup = new FormGroup(
|
this.editEmployeeFormGroup = new FormGroup(
|
||||||
{
|
{
|
||||||
email: new FormControl(this.employee.email, [
|
email: new FormControl(this.employee.email),
|
||||||
RequiredValidator('E-postadress'),
|
tjanster: new FormControl(tjanstId),
|
||||||
EmailValidator('e-postadress'),
|
|
||||||
]),
|
|
||||||
tjanster: new FormControl(tjanstId, [RequiredValidator('Tjänst')]),
|
|
||||||
roles: this.employeeFormService.getRolesFormGroup(this.availableRoles, this.employee.roles),
|
roles: this.employeeFormService.getRolesFormGroup(this.availableRoles, this.employee.roles),
|
||||||
utforandeVerksamheter: new FormControl(
|
utforandeVerksamheter: new FormControl(
|
||||||
this.utforandeVerksamheterService.getTreeNodeDataFromUtforandeVerksamheter(
|
this.utforandeVerksamheterService.getTreeNodeDataFromUtforandeVerksamheter(
|
||||||
this.availableUtforandeVerksamheter,
|
this.availableUtforandeVerksamheter,
|
||||||
this.employee?.utforandeVerksamheter
|
this.employee?.utforandeVerksamheter
|
||||||
),
|
)
|
||||||
[]
|
|
||||||
),
|
),
|
||||||
allaUtforandeVerksamheter: new FormControl(this.employee.allaUtforandeVerksamheter),
|
allaUtforandeVerksamheter: new FormControl(this.employee.allaUtforandeVerksamheter),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
validators: EmployeeValidator.HasSelectedAtLeastOneUtforandeVerksamhet(
|
validators: [
|
||||||
this.utforandeVerksamheterFormControlName,
|
EmployeeValidator.isEmployeeValid(this.utforandeVerksamheterService.hasSelectedUtforandeVerksamhet),
|
||||||
this.selectAllUtforandeVerksamheterFormControlName,
|
],
|
||||||
this.utforandeVerksamheterService.hasSelectedUtforandeVerksamhet
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -198,11 +190,26 @@ export class EditEmployeeFormComponent implements OnInit, OnChanges {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onFormSubmitted(saveWithoutRoles = false): void {
|
onFormSubmitted(saveWithoutRoles = false): void {
|
||||||
this._submitted = true;
|
|
||||||
if (!this.editEmployeeFormGroup || this.isLoadingUtforandeVerksamheter) {
|
if (!this.editEmployeeFormGroup || this.isLoadingUtforandeVerksamheter) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const roles = this.employeeFormService.getRolesFromFormGroup(this.rolesFormGroup, this.availableRoles);
|
||||||
|
|
||||||
|
if (!roles.length && !saveWithoutRoles) {
|
||||||
|
this.displayEditWithoutRolesDialog = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._submitted = true;
|
||||||
|
|
||||||
|
if (!roles.length && saveWithoutRoles) {
|
||||||
|
this.utforandeVerksamheterFormControl.clearValidators();
|
||||||
|
this.utforandeVerksamheterFormControl.updateValueAndValidity();
|
||||||
|
this.tjansterFormControl.clearValidators();
|
||||||
|
this.tjansterFormControl.updateValueAndValidity();
|
||||||
|
}
|
||||||
|
|
||||||
this.editEmployeeFormGroup.markAllAsTouched();
|
this.editEmployeeFormGroup.markAllAsTouched();
|
||||||
|
|
||||||
if (this.editEmployeeFormGroup.invalid) {
|
if (this.editEmployeeFormGroup.invalid) {
|
||||||
@@ -217,30 +224,21 @@ export class EditEmployeeFormComponent implements OnInit, OnChanges {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const roles = this.employeeFormService.getRolesFromFormGroup(this.rolesFormGroup, this.availableRoles);
|
|
||||||
|
|
||||||
if (!roles.length && !saveWithoutRoles) {
|
|
||||||
this.displayEditWithoutRolesDialog = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.formSubmitted.emit({
|
this.formSubmitted.emit({
|
||||||
email: this.emailFormControl?.value as string,
|
email: this.emailFormControl?.value as string,
|
||||||
tjanstIds: this.employeeFormService
|
tjanstIds: !roles.length
|
||||||
.getSelectedTjanster(this.availableTjanster, +this.tjansterFormControl?.value)
|
|
||||||
.map(tjanst => tjanst.tjanstId),
|
|
||||||
roles: [
|
|
||||||
...new Set([
|
|
||||||
...this.employeeFormService.getRolesFromFormGroup(this.rolesFormGroup, this.availableRoles),
|
|
||||||
RoleEnum.MSFA_Standard,
|
|
||||||
]),
|
|
||||||
],
|
|
||||||
adressIds: this.selectAllUtforandeVerksamheterFormControl.value
|
|
||||||
? []
|
? []
|
||||||
: this.utforandeVerksamheterService.getSelectedAdressIdsFromTreeNode(
|
: this.employeeFormService
|
||||||
this.utforandeVerksamheterFormControl?.value
|
.getSelectedTjanster(this.availableTjanster, +this.tjansterFormControl?.value)
|
||||||
),
|
.map(tjanst => tjanst.tjanstId),
|
||||||
allaUtforandeVerksamheter: !!this.selectAllUtforandeVerksamheterFormControl.value,
|
roles: [...new Set([...roles, RoleEnum.MSFA_Standard])],
|
||||||
|
adressIds:
|
||||||
|
!roles.length || this.selectAllUtforandeVerksamheterFormControl.value
|
||||||
|
? []
|
||||||
|
: this.utforandeVerksamheterService.getSelectedAdressIdsFromTreeNode(
|
||||||
|
this.utforandeVerksamheterFormControl?.value
|
||||||
|
),
|
||||||
|
allaUtforandeVerksamheter: !roles.length ? false : !!this.selectAllUtforandeVerksamheterFormControl.value,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,25 +248,26 @@ export class EditEmployeeFormComponent implements OnInit, OnChanges {
|
|||||||
if (!this.editEmployeeFormGroup) {
|
if (!this.editEmployeeFormGroup) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const { email, tjanster, utforandeVerksamheter } = this.editEmployeeFormGroup.errors || {};
|
||||||
|
|
||||||
if (this.emailFormControl?.errors) {
|
if (email) {
|
||||||
validationErrorLinks = validationErrorLinks.concat({
|
validationErrorLinks = validationErrorLinks.concat({
|
||||||
elementId: this.emailElementId,
|
elementId: this.emailElementId,
|
||||||
text: this.emailFormControl?.errors?.message as string,
|
text: email as string,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.tjansterFormControl?.errors) {
|
if (tjanster) {
|
||||||
validationErrorLinks = validationErrorLinks.concat({
|
validationErrorLinks = validationErrorLinks.concat({
|
||||||
elementId: this.tjansterElementId,
|
elementId: this.tjansterElementId,
|
||||||
text: this.tjansterFormControl?.errors?.message as string,
|
text: tjanster as string,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.editEmployeeFormGroup.errors?.noUtforandeVerksamhetSelected) {
|
if (utforandeVerksamheter) {
|
||||||
validationErrorLinks = validationErrorLinks.concat({
|
validationErrorLinks = validationErrorLinks.concat({
|
||||||
elementId: this.utforandeVerksamhetElementId,
|
elementId: this.utforandeVerksamhetElementId,
|
||||||
text: this.utforandeVerksamhetRequiredMessage,
|
text: utforandeVerksamheter as string,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,9 +34,12 @@
|
|||||||
</msfa-tree-nodes-selector-panel>
|
</msfa-tree-nodes-selector-panel>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ul class="tree-nodes-selector__validation-messages" *ngIf="showValidation && validationMessages">
|
|
||||||
<li *ngFor="let validationMessage of validationMessages">
|
<div aria-atomic="true" role="alert">
|
||||||
<digi-form-validation-message af-variation="error"> {{validationMessage}} </digi-form-validation-message>
|
<ul class="tree-nodes-selector__validation-messages" *ngIf="showValidation && validationMessages">
|
||||||
</li>
|
<li *ngFor="let validationMessage of validationMessages">
|
||||||
</ul>
|
<digi-form-validation-message af-variation="error"> {{validationMessage}} </digi-form-validation-message>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
1
apps/mina-sidor-fa/src/app/shared/constants/regex.ts
Normal file
1
apps/mina-sidor-fa/src/app/shared/constants/regex.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export const EMAIL_REGEX = /^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$/;
|
||||||
@@ -1,14 +1,17 @@
|
|||||||
import { AbstractControl, ValidatorFn } from '@angular/forms';
|
import { AbstractControl, ValidatorFn } from '@angular/forms';
|
||||||
|
import { EMAIL_REGEX } from '@msfa-constants/regex';
|
||||||
import { ValidationError } from '@msfa-models/validation-error.model';
|
import { ValidationError } from '@msfa-models/validation-error.model';
|
||||||
|
|
||||||
const EMAIL_REGEX = /^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$/;
|
export function emailIsValid(email: string): boolean {
|
||||||
|
return EMAIL_REGEX.test(email.toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
export function EmailValidator(label = 'Fältet'): ValidatorFn {
|
export function EmailValidator(label = 'Fältet'): ValidatorFn {
|
||||||
return (control: AbstractControl): ValidationError => {
|
return (control: AbstractControl): ValidationError => {
|
||||||
if (control && control.value) {
|
if (control && control.value) {
|
||||||
const value: string = control.value as string;
|
const value: string = control.value as string;
|
||||||
|
|
||||||
if (!EMAIL_REGEX.test(value.toLowerCase())) {
|
if (!emailIsValid(value)) {
|
||||||
return { type: 'invalid', message: `Ogiltig ${label}` };
|
return { type: 'invalid', message: `Ogiltig ${label}` };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +1,50 @@
|
|||||||
import { FormGroup, ValidatorFn } from '@angular/forms';
|
import { AbstractControl, ValidatorFn } from '@angular/forms';
|
||||||
|
import { RoleEnum } from '@msfa-enums/role.enum';
|
||||||
import { TreeNode } from '@msfa-shared/components/tree-nodes-selector/services/tree-nodes-selector.service';
|
import { TreeNode } from '@msfa-shared/components/tree-nodes-selector/services/tree-nodes-selector.service';
|
||||||
|
import { emailIsValid } from './email.validator';
|
||||||
|
|
||||||
export class EmployeeValidator {
|
export class EmployeeValidator {
|
||||||
static HasSelectedAtLeastOneRole(roleFormControlNames: Array<string>): ValidatorFn {
|
static isEmployeeValid(hasSelectedUtforandeVerksamhetFn: (treeNode: TreeNode) => boolean): ValidatorFn {
|
||||||
return (fg: FormGroup): { [key: string]: unknown } => {
|
return (c: AbstractControl): { [key: string]: string } => {
|
||||||
if (!roleFormControlNames || roleFormControlNames.length === 0) {
|
let errors: { [key: string]: string } = null;
|
||||||
return { noRoleSelected: true };
|
const email = c.get('email')?.value as string;
|
||||||
|
const roles = c.get('roles')?.value as { [key: string]: boolean };
|
||||||
|
const tjanster = c.get('tjanster')?.value as string;
|
||||||
|
const allaUtforandeVerksamheter = c.get('allaUtforandeVerksamheter')?.value as boolean;
|
||||||
|
const utforandeVerksamheter = c.get('utforandeVerksamheter').value as TreeNode;
|
||||||
|
const rolesWithObligatoryFormElements = Object.entries(roles)
|
||||||
|
.filter(([key, value]) => !!(value && key !== RoleEnum.MSFA_AuthAdmin))
|
||||||
|
.map(([key]) => key);
|
||||||
|
|
||||||
|
if (!email) {
|
||||||
|
errors = {
|
||||||
|
...errors,
|
||||||
|
email: 'E-postadress är obligatoriskt',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (email && !emailIsValid(email)) {
|
||||||
|
errors = {
|
||||||
|
...errors,
|
||||||
|
email: 'Ogiltig e-postadress',
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return roleFormControlNames.some(roleFormControlName => fg?.controls[roleFormControlName]?.value)
|
if (rolesWithObligatoryFormElements.length) {
|
||||||
? null
|
if (!tjanster) {
|
||||||
: { noRoleSelected: true };
|
errors = {
|
||||||
};
|
...errors,
|
||||||
}
|
tjanster: 'Minst en tjänst behöver väljas',
|
||||||
|
};
|
||||||
static HasSelectedAtLeastOneUtforandeVerksamhet(
|
}
|
||||||
utforandeVerksamheterFormControlName: string,
|
if (!allaUtforandeVerksamheter && !hasSelectedUtforandeVerksamhetFn(utforandeVerksamheter)) {
|
||||||
selectAllUtforandeVerksamheterFormControlName: string,
|
errors = {
|
||||||
validationFn: (treeNode: TreeNode | null | undefined) => boolean
|
...errors,
|
||||||
): ValidatorFn {
|
utforandeVerksamheter: 'Minst en utförande verksamhet och adress behöver väljas',
|
||||||
return (fg: FormGroup): { [key: string]: unknown } => {
|
};
|
||||||
if (fg?.get(selectAllUtforandeVerksamheterFormControlName)?.value) {
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return validationFn(fg?.get(utforandeVerksamheterFormControlName)?.value)
|
return errors;
|
||||||
? null
|
|
||||||
: { noUtforandeVerksamhetSelected: true };
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user