diff --git a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/add-management-rules/add-management-rules.component.spec.ts b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/add-management-rules/add-management-rules.component.spec.ts index e481ffa456f..8f4ed284a77 100644 --- a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/add-management-rules/add-management-rules.component.spec.ts +++ b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/add-management-rules/add-management-rules.component.spec.ts @@ -181,7 +181,6 @@ const updateUnitManagementRuleServiceMock = jasmine.createSpyObj('UpdateUnitMana const managementRulesValidatorServiceMock = jasmine.createSpyObj('ManagementRulesValidatorService', { uniquePreventRuleId: () => of({}), uniqueRuleId: () => of({}), - ruleIdPattern: () => of({}), checkRuleIdExistence: () => of({}), }); diff --git a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/add-management-rules/add-management-rules.component.ts b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/add-management-rules/add-management-rules.component.ts index bbeb154fdc3..a25944c741b 100644 --- a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/add-management-rules/add-management-rules.component.ts +++ b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/add-management-rules/add-management-rules.component.ts @@ -45,7 +45,7 @@ import { CriteriaDataType, CriteriaOperator, diff, - ManagementRuleValidators, + MiscValidators, Rule, RuleService, SearchCriteriaDto, @@ -136,7 +136,7 @@ export class AddManagementRulesComponent implements OnDestroy, OnInit { this.ruleDetailsForm = this.formBuilder.group({ rule: [ null, - [Validators.required, ManagementRuleValidators.ruleIdPattern], + [Validators.required, MiscValidators.requiredIdentifier], [this.managementRulesValidatorService.uniqueRuleId(this.ruleCategory), this.managementRulesValidatorService.checkRuleIdExistence()], ], startDate: [null], diff --git a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/block-rules-inheritance/block-rules-inheritance.component.spec.ts b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/block-rules-inheritance/block-rules-inheritance.component.spec.ts index 741fa361610..db85a0d95a8 100644 --- a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/block-rules-inheritance/block-rules-inheritance.component.spec.ts +++ b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/block-rules-inheritance/block-rules-inheritance.component.spec.ts @@ -128,7 +128,6 @@ const managementRulesSharedDataServiceMock = { const managementRulesValidatorServiceMock = jasmine.createSpyObj('ManagementRulesValidatorService', { uniquePreventRuleId: () => of({}), uniqueRuleId: () => of({}), - ruleIdPattern: () => of({}), checkRuleIdExistence: () => of({}), }); diff --git a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/block-rules-inheritance/block-rules-inheritance.component.ts b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/block-rules-inheritance/block-rules-inheritance.component.ts index 3dca60d1992..07ac29d50e2 100644 --- a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/block-rules-inheritance/block-rules-inheritance.component.ts +++ b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/block-rules-inheritance/block-rules-inheritance.component.ts @@ -40,10 +40,10 @@ import { MatDialog } from '@angular/material/dialog'; import { ManagementRulesSharedDataService } from 'projects/archive-search/src/app/core/management-rules-shared-data.service'; import { merge, Observable, Subscription } from 'rxjs'; import { debounceTime, filter, map } from 'rxjs/operators'; -import { diff, ManagementRuleValidators, Rule, RuleService, SearchCriteriaDto, VitamuiSelectOptions } from 'vitamui-library'; import { ArchiveSearchConstsEnum } from '../../../../../models/archive-search-consts-enum'; import { ManagementRules, RuleAction, RuleActionsEnum, RuleCategoryAction } from '../../../../../models/ruleAction.interface'; import { ManagementRulesValidatorService } from '../../../../../validators/management-rules-validator.service'; +import { diff, MiscValidators, Rule, RuleService, SearchCriteriaDto, VitamuiSelectOptions } from 'vitamui-library'; @Component({ selector: 'app-block-rules-inheritance', @@ -98,7 +98,7 @@ export class BlockRulesInheritanceComponent implements OnDestroy, OnInit { this.ruleDetailsForm = this.formBuilder.group({ rule: [ null, - [Validators.required, ManagementRuleValidators.ruleIdPattern], + [Validators.required, MiscValidators.requiredIdentifier], [this.managementRulesValidatorService.uniquePreventRuleId(), this.managementRulesValidatorService.checkRuleIdExistence()], ], }); diff --git a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/delete-unit-rules/delete-unit-rules.component.spec.ts b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/delete-unit-rules/delete-unit-rules.component.spec.ts index 7a723e18a8b..d0cf55d0150 100644 --- a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/delete-unit-rules/delete-unit-rules.component.spec.ts +++ b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/delete-unit-rules/delete-unit-rules.component.spec.ts @@ -181,7 +181,6 @@ const updateUnitManagementRuleServiceMock = jasmine.createSpyObj('UpdateUnitMana const managementRulesValidatorServiceMock = jasmine.createSpyObj('ManagementRulesValidatorService', { uniquePreventRuleId: () => of({}), uniqueRuleId: () => of({}), - ruleIdPattern: () => of({}), checkRuleIdExistence: () => of({}), }); diff --git a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/delete-unit-rules/delete-unit-rules.component.ts b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/delete-unit-rules/delete-unit-rules.component.ts index 9acc8a96a5c..5f0b50abcde 100644 --- a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/delete-unit-rules/delete-unit-rules.component.ts +++ b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/delete-unit-rules/delete-unit-rules.component.ts @@ -40,18 +40,18 @@ import { MatDialog } from '@angular/material/dialog'; import { TranslateService } from '@ngx-translate/core'; import { cloneDeep } from 'lodash-es'; import { ManagementRulesSharedDataService } from 'projects/archive-search/src/app/core/management-rules-shared-data.service'; -import { merge, Subscription, Observable } from 'rxjs'; +import { merge, Observable, Subscription } from 'rxjs'; import { debounceTime, filter, map } from 'rxjs/operators'; import { CriteriaDataType, CriteriaOperator, - ManagementRuleValidators, + diff, + MiscValidators, Rule, RuleService, SearchCriteriaDto, SearchCriteriaEltDto, VitamuiSelectOptions, - diff, } from 'vitamui-library'; import { ArchiveService } from '../../../../../archive.service'; import { UpdateUnitManagementRuleService } from '../../../../../common-services/update-unit-management-rule.service'; @@ -127,7 +127,7 @@ export class DeleteUnitRulesComponent implements OnDestroy, OnInit { this.ruleDetailsForm = this.formBuilder.group({ rule: [ null, - [Validators.required, ManagementRuleValidators.ruleIdPattern], + [Validators.required, MiscValidators.requiredIdentifier], [this.managementRulesValidatorService.uniqueRuleId(), this.managementRulesValidatorService.checkRuleIdExistence()], ], }); diff --git a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/unlock-rules-inheritance/unlock-rules-inheritance.component.spec.ts b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/unlock-rules-inheritance/unlock-rules-inheritance.component.spec.ts index a8b58b186a2..bff72828ed5 100644 --- a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/unlock-rules-inheritance/unlock-rules-inheritance.component.spec.ts +++ b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/unlock-rules-inheritance/unlock-rules-inheritance.component.spec.ts @@ -181,7 +181,6 @@ const updateUnitManagementRuleServiceMock = jasmine.createSpyObj('UpdateUnitMana const managementRulesValidatorServiceMock = jasmine.createSpyObj('ManagementRulesValidatorService', { uniquePreventRuleId: () => of({}), uniqueRuleId: () => of({}), - ruleIdPattern: () => of({}), checkRuleIdExistence: () => of({}), }); diff --git a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/unlock-rules-inheritance/unlock-rules-inheritance.component.ts b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/unlock-rules-inheritance/unlock-rules-inheritance.component.ts index 1239131d34b..7d27873b15b 100644 --- a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/unlock-rules-inheritance/unlock-rules-inheritance.component.ts +++ b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/unlock-rules-inheritance/unlock-rules-inheritance.component.ts @@ -47,7 +47,7 @@ import { CriteriaDataType, CriteriaOperator, diff, - ManagementRuleValidators, + MiscValidators, Rule, RuleService, SearchCriteriaDto, @@ -129,7 +129,7 @@ export class UnlockRulesInheritanceComponent implements OnDestroy, OnInit { this.ruleDetailsForm = this.formBuilder.group({ rule: [ null, - [Validators.required, ManagementRuleValidators.ruleIdPattern], + [Validators.required, MiscValidators.requiredIdentifier], [this.managementRulesValidatorService.uniquePreventRuleId(), this.managementRulesValidatorService.checkRuleIdExistence()], ], }); diff --git a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/update-unit-rules/update-unit-rules.component.spec.ts b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/update-unit-rules/update-unit-rules.component.spec.ts index 1481728a4c5..cbeee0f42c1 100644 --- a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/update-unit-rules/update-unit-rules.component.spec.ts +++ b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/update-unit-rules/update-unit-rules.component.spec.ts @@ -181,7 +181,6 @@ const updateUnitManagementRuleServiceMock = jasmine.createSpyObj('UpdateUnitMana const managementRulesValidatorServiceMock = jasmine.createSpyObj('ManagementRulesValidatorService', { uniquePreventRuleId: () => of({}), uniqueRuleId: () => of({}), - ruleIdPattern: () => of({}), checkRuleIdExistence: () => of({}), }); diff --git a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/update-unit-rules/update-unit-rules.component.ts b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/update-unit-rules/update-unit-rules.component.ts index f0beea5cc2d..b86c2f06fe2 100644 --- a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/update-unit-rules/update-unit-rules.component.ts +++ b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/additional-actions-search/management-rules/archive-unit-rules/update-unit-rules/update-unit-rules.component.ts @@ -41,23 +41,23 @@ import { TranslateService } from '@ngx-translate/core'; import { cloneDeep } from 'lodash-es'; import { finalize, merge, Observable, Subscription } from 'rxjs'; import { debounceTime, filter, map } from 'rxjs/operators'; +import { ManagementRulesSharedDataService } from '../../../../../../core/management-rules-shared-data.service'; +import { ArchiveService } from '../../../../../archive.service'; +import { UpdateUnitManagementRuleService } from '../../../../../common-services/update-unit-management-rule.service'; +import { ArchiveSearchConstsEnum } from '../../../../../models/archive-search-consts-enum'; +import { ManagementRules, RuleAction, RuleActionsEnum, RuleCategoryAction } from '../../../../../models/ruleAction.interface'; +import { ManagementRulesValidatorService } from '../../../../../validators/management-rules-validator.service'; import { CriteriaDataType, CriteriaOperator, diff, - ManagementRuleValidators, + MiscValidators, Rule, RuleService, SearchCriteriaDto, SearchCriteriaEltDto, VitamuiSelectOptions, } from 'vitamui-library'; -import { ManagementRulesSharedDataService } from '../../../../../../core/management-rules-shared-data.service'; -import { ArchiveService } from '../../../../../archive.service'; -import { UpdateUnitManagementRuleService } from '../../../../../common-services/update-unit-management-rule.service'; -import { ArchiveSearchConstsEnum } from '../../../../../models/archive-search-consts-enum'; -import { ManagementRules, RuleAction, RuleActionsEnum, RuleCategoryAction } from '../../../../../models/ruleAction.interface'; -import { ManagementRulesValidatorService } from '../../../../../validators/management-rules-validator.service'; const MANAGEMENT_RULE_IDENTIFIER = 'MANAGEMENT_RULE_IDENTIFIER'; const ORIGIN_HAS_AT_LEAST_ONE = 'ORIGIN_HAS_AT_LEAST_ONE'; @@ -154,10 +154,10 @@ export class UpdateUnitRulesComponent implements OnDestroy, OnInit { { oldRule: [ null, - [Validators.required, ManagementRuleValidators.ruleIdPattern], + [Validators.required, MiscValidators.requiredIdentifier], [this.managementRulesValidatorService.uniqueRuleId(), this.managementRulesValidatorService.checkRuleIdExistence()], ], - newRule: [null, [ManagementRuleValidators.ruleIdPattern], [this.managementRulesValidatorService.checkRuleIdExistence()]], + newRule: [null, [MiscValidators.requiredIdentifier], [this.managementRulesValidatorService.checkRuleIdExistence()]], startDate: [null], endDate: [{ value: null, disabled: true }], ruleUpdated: [{ value: false, disabled: true }], diff --git a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/archive-search-by-mgt-rules/access-rule-search/access-rule-search.component.spec.ts b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/archive-search-by-mgt-rules/access-rule-search/access-rule-search.component.spec.ts index 9370b9764f0..7f11ba699fd 100644 --- a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/archive-search-by-mgt-rules/access-rule-search/access-rule-search.component.spec.ts +++ b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/archive-search-by-mgt-rules/access-rule-search/access-rule-search.component.spec.ts @@ -50,8 +50,8 @@ import { CriteriaValue, InjectorModule, LoggerModule, - WINDOW_LOCATION, Rule, + WINDOW_LOCATION, } from 'vitamui-library'; import { VitamUICommonTestModule } from 'vitamui-library/testing'; import { RuleValidator } from '../../rule.validator'; @@ -62,7 +62,6 @@ const matDialogRefSpy = jasmine.createSpyObj('MatDialogRef', ['close']); const matDialogSpy = jasmine.createSpyObj('MatDialog', ['open']); const ruleValidatorMock = jasmine.createSpyObj('RuleValidator', { - ruleIdPattern: () => of(), uniqueRuleId: () => of(), }); diff --git a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/archive-search-by-mgt-rules/appraisal-rule-search/appraisal-rule-search.component.spec.ts b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/archive-search-by-mgt-rules/appraisal-rule-search/appraisal-rule-search.component.spec.ts index b634ae1d40a..58cfc359689 100644 --- a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/archive-search-by-mgt-rules/appraisal-rule-search/appraisal-rule-search.component.spec.ts +++ b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/archive-search-by-mgt-rules/appraisal-rule-search/appraisal-rule-search.component.spec.ts @@ -50,8 +50,8 @@ import { CriteriaValue, InjectorModule, LoggerModule, - WINDOW_LOCATION, Rule, + WINDOW_LOCATION, } from 'vitamui-library'; import { VitamUICommonTestModule } from 'vitamui-library/testing'; import { RuleValidator } from '../../rule.validator'; @@ -62,7 +62,6 @@ const matDialogRefSpy = jasmine.createSpyObj('MatDialogRef', ['close']); const matDialogSpy = jasmine.createSpyObj('MatDialog', ['open']); const ruleValidatorMock = jasmine.createSpyObj('RuleValidator', { - ruleIdPattern: () => of(), uniqueRuleId: () => of(), }); diff --git a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/archive-search-by-mgt-rules/dissemination-rule-search/dissemination-rule-search.component.spec.ts b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/archive-search-by-mgt-rules/dissemination-rule-search/dissemination-rule-search.component.spec.ts index b65049d0189..b496de90f3e 100644 --- a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/archive-search-by-mgt-rules/dissemination-rule-search/dissemination-rule-search.component.spec.ts +++ b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/archive-search-by-mgt-rules/dissemination-rule-search/dissemination-rule-search.component.spec.ts @@ -50,8 +50,8 @@ import { CriteriaValue, InjectorModule, LoggerModule, - WINDOW_LOCATION, Rule, + WINDOW_LOCATION, } from 'vitamui-library'; import { VitamUICommonTestModule } from 'vitamui-library/testing'; import { RuleValidator } from '../../rule.validator'; @@ -62,7 +62,6 @@ const matDialogRefSpy = jasmine.createSpyObj('MatDialogRef', ['close']); const matDialogSpy = jasmine.createSpyObj('MatDialog', ['open']); const ruleValidatorMock = jasmine.createSpyObj('RuleValidator', { - ruleIdPattern: () => of(), uniqueRuleId: () => of(), }); diff --git a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/archive-search-by-mgt-rules/reuse-rule-search/reuse-rule-search.component.spec.ts b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/archive-search-by-mgt-rules/reuse-rule-search/reuse-rule-search.component.spec.ts index 81ff6df3e69..d432582f239 100644 --- a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/archive-search-by-mgt-rules/reuse-rule-search/reuse-rule-search.component.spec.ts +++ b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/archive-search-by-mgt-rules/reuse-rule-search/reuse-rule-search.component.spec.ts @@ -50,8 +50,8 @@ import { CriteriaValue, InjectorModule, LoggerModule, - WINDOW_LOCATION, Rule, + WINDOW_LOCATION, } from 'vitamui-library'; import { VitamUICommonTestModule } from 'vitamui-library/testing'; import { RuleValidator } from '../../rule.validator'; @@ -62,7 +62,6 @@ const matDialogRefSpy = jasmine.createSpyObj('MatDialogRef', ['close']); const matDialogSpy = jasmine.createSpyObj('MatDialog', ['open']); const ruleValidatorMock = jasmine.createSpyObj('RuleValidator', { - ruleIdPattern: () => of(), uniqueRuleId: () => of(), }); diff --git a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/archive-search-by-mgt-rules/storage-rule-search/storage-rule-search.component.spec.ts b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/archive-search-by-mgt-rules/storage-rule-search/storage-rule-search.component.spec.ts index 6297d33b9b2..6c842f50387 100644 --- a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/archive-search-by-mgt-rules/storage-rule-search/storage-rule-search.component.spec.ts +++ b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-search/archive-search-by-mgt-rules/storage-rule-search/storage-rule-search.component.spec.ts @@ -50,8 +50,8 @@ import { CriteriaValue, InjectorModule, LoggerModule, - WINDOW_LOCATION, Rule, + WINDOW_LOCATION, } from 'vitamui-library'; import { VitamUICommonTestModule } from 'vitamui-library/testing'; import { RuleValidator } from '../../rule.validator'; @@ -62,7 +62,6 @@ const matDialogRefSpy = jasmine.createSpyObj('MatDialogRef', ['close']); const matDialogSpy = jasmine.createSpyObj('MatDialog', ['open']); const ruleValidatorMock = jasmine.createSpyObj('RuleValidator', { - ruleIdPattern: () => of(), uniqueRuleId: () => of(), }); diff --git a/ui/ui-frontend/projects/design-system/src/app/components/molecules/inputs/input/design-system-input.component.ts b/ui/ui-frontend/projects/design-system/src/app/components/molecules/inputs/input/design-system-input.component.ts index 8104d43be7a..cf39b5df94c 100644 --- a/ui/ui-frontend/projects/design-system/src/app/components/molecules/inputs/input/design-system-input.component.ts +++ b/ui/ui-frontend/projects/design-system/src/app/components/molecules/inputs/input/design-system-input.component.ts @@ -35,7 +35,7 @@ * knowledge of the CeCILL-C license and that you accept its terms. */ import { Component } from '@angular/core'; -import { InputComponent } from 'vitamui-library'; +import { InputComponent, MiscValidators } from 'vitamui-library'; import { FormControl, ReactiveFormsModule, Validators } from '@angular/forms'; @Component({ @@ -110,7 +110,7 @@ export class DesignSystemInputComponent { } private createControl(config?: { disabled?: boolean; error?: boolean; value?: any }): FormControl { - const validators = config?.error ? [Validators.required, Validators.pattern('.*TextContent.*')] : []; + const validators = config?.error ? [MiscValidators.requiredNotBlank, Validators.pattern('.*TextContent.*')] : []; const fc = new FormControl(null, validators); if (config?.disabled) fc.disable(); diff --git a/ui/ui-frontend/projects/vitamui-library/src/lib/validators/management-rule.validators.spec.ts b/ui/ui-frontend/projects/pastis/src/app/profile/profile-preview/profile-information-tab/profile-information-tab/profile-information-tab.component.spec.ts similarity index 58% rename from ui/ui-frontend/projects/vitamui-library/src/lib/validators/management-rule.validators.spec.ts rename to ui/ui-frontend/projects/pastis/src/app/profile/profile-preview/profile-information-tab/profile-information-tab/profile-information-tab.component.spec.ts index 8cf1c518728..bc089f31812 100644 --- a/ui/ui-frontend/projects/vitamui-library/src/lib/validators/management-rule.validators.spec.ts +++ b/ui/ui-frontend/projects/pastis/src/app/profile/profile-preview/profile-information-tab/profile-information-tab/profile-information-tab.component.spec.ts @@ -34,38 +34,34 @@ * The fact that you are presently reading this means that you have had * knowledge of the CeCILL-C license and that you accept its terms. */ -import { TestBed } from '@angular/core/testing'; -import { FormBuilder, ReactiveFormsModule } from '@angular/forms'; -import { ManagementRuleValidators } from './management-rule.validators'; +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { ReactiveFormsModule } from '@angular/forms'; +import { ProfileInformationTabComponent } from './profile-information-tab.component'; +import { ProfileService } from '../../../../core/services/profile.service'; +import { MiscValidators, SnackBarService } from 'vitamui-library'; +import { TranslateModule } from '@ngx-translate/core'; -describe('ManagementRuleValidators', () => { - let formBuilder: FormBuilder; +describe('ProfileInformationTabComponent', () => { + let fixture: ComponentFixture; + let component: ProfileInformationTabComponent; - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [ReactiveFormsModule], - }).compileComponents(); - - formBuilder = TestBed.inject(FormBuilder); - }); + beforeEach(waitForAsync(() => { + const profileServiceMock = jasmine.createSpyObj('ProfileService', ['updateProfilePa', 'updateProfilePua', 'refreshListProfiles']); - describe('ruleIdPattern', () => { - it('should detect allowed rule id pattern', () => { - const formGroup = formBuilder.group({ - id: ['azerty', ManagementRuleValidators.ruleIdPattern], - }); - - expect(formGroup.valid).toBeTruthy('Form group must be valid'); - expect(formGroup.get('id').errors).toBeNull('Id control must not have errors'); - }); + TestBed.configureTestingModule({ + imports: [ReactiveFormsModule, TranslateModule.forRoot()], + declarations: [ProfileInformationTabComponent], + providers: [ + { provide: ProfileService, useValue: profileServiceMock }, + { provide: SnackBarService, useValue: {} }, + ], + }).compileComponents(); - it('should detect not allowed rule id pattern', () => { - const formGroup = formBuilder.group({ - id: ['ÀÖØöøÿ ', ManagementRuleValidators.ruleIdPattern], - }); + fixture = TestBed.createComponent(ProfileInformationTabComponent); + component = fixture.componentInstance; + })); - expect(formGroup.invalid).toBeTruthy('Form group must be invalid'); - expect(formGroup.get('id').errors).toBeTruthy('Id control must have errors'); - }); + it('applies MiscValidators.requiredIdentifier to identifier control', () => { + expect(component.form.get('identifier').hasValidator(MiscValidators.requiredIdentifier)).toBeTruthy(); }); }); diff --git a/ui/ui-frontend/projects/pastis/src/app/profile/profile-preview/profile-information-tab/profile-information-tab/profile-information-tab.component.ts b/ui/ui-frontend/projects/pastis/src/app/profile/profile-preview/profile-information-tab/profile-information-tab/profile-information-tab.component.ts index 21af7a9c547..e3ab04cc5bf 100644 --- a/ui/ui-frontend/projects/pastis/src/app/profile/profile-preview/profile-information-tab/profile-information-tab/profile-information-tab.component.ts +++ b/ui/ui-frontend/projects/pastis/src/app/profile/profile-preview/profile-information-tab/profile-information-tab/profile-information-tab.component.ts @@ -81,7 +81,7 @@ export class ProfileInformationTabComponent { private snackBarService: SnackBarService, ) { this.form = this.formBuilder.group({ - identifier: [null, [Validators.required, Validators.minLength(2), Validators.maxLength(10), MiscValidators.allowedIdentifier]], + identifier: [null, [MiscValidators.requiredIdentifier, Validators.minLength(2), Validators.maxLength(10)]], id: [null, Validators.required], type: [null], description: [null], diff --git a/ui/ui-frontend/projects/pastis/src/app/user-actions/create-notice/create-notice.component.spec.ts b/ui/ui-frontend/projects/pastis/src/app/user-actions/create-notice/create-notice.component.spec.ts index 725603a8d09..3f171d3d20b 100644 --- a/ui/ui-frontend/projects/pastis/src/app/user-actions/create-notice/create-notice.component.spec.ts +++ b/ui/ui-frontend/projects/pastis/src/app/user-actions/create-notice/create-notice.component.spec.ts @@ -41,7 +41,7 @@ import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dial import { RouterTestingModule } from '@angular/router/testing'; import { TranslateModule } from '@ngx-translate/core'; import { of } from 'rxjs'; -import { BASE_URL, LoggerModule, WINDOW_LOCATION } from 'vitamui-library'; +import { BASE_URL, LoggerModule, MiscValidators, WINDOW_LOCATION } from 'vitamui-library'; import { PastisConfiguration } from '../../core/classes/pastis-configuration'; import { ProfileService } from '../../core/services/profile.service'; @@ -95,4 +95,8 @@ describe('CreateNoticeComponent', () => { it('should create', () => { expect(component).toBeTruthy(); }); + + it('applies MiscValidators.requiredIdentifier to identifier control', () => { + expect(component.form.get('identifier').hasValidator(MiscValidators.requiredIdentifier)).toBeTruthy(); + }); }); diff --git a/ui/ui-frontend/projects/pastis/src/app/user-actions/create-notice/create-notice.component.ts b/ui/ui-frontend/projects/pastis/src/app/user-actions/create-notice/create-notice.component.ts index 800cafe185b..3b328e4b6b2 100644 --- a/ui/ui-frontend/projects/pastis/src/app/user-actions/create-notice/create-notice.component.ts +++ b/ui/ui-frontend/projects/pastis/src/app/user-actions/create-notice/create-notice.component.ts @@ -115,7 +115,7 @@ export class CreateNoticeComponent implements OnInit, OnDestroy { this.form = this.formBuilder.group({ identifier: [ { value: this.notice.identifier, disabled: this.editNotice }, - [Validators.required, Validators.minLength(2), Validators.maxLength(100), MiscValidators.allowedIdentifier], + [MiscValidators.requiredIdentifier, Validators.minLength(2), Validators.maxLength(100)], ], name: [this.notice.name, Validators.required], status: [this.notice.status], diff --git a/ui/ui-frontend/projects/referential/src/app/access-contract/access-contract-create/access-contract-create.component.spec.ts b/ui/ui-frontend/projects/referential/src/app/access-contract/access-contract-create/access-contract-create.component.spec.ts index adcc6bf032b..04e79833d41 100644 --- a/ui/ui-frontend/projects/referential/src/app/access-contract/access-contract-create/access-contract-create.component.spec.ts +++ b/ui/ui-frontend/projects/referential/src/app/access-contract/access-contract-create/access-contract-create.component.spec.ts @@ -53,6 +53,7 @@ import { ConfirmDialogService, ExternalParametersService, LoggerModule, + MiscValidators, } from 'vitamui-library'; import { VitamUICommonTestModule } from 'vitamui-library/testing'; import { AccessContractCreateComponent } from './access-contract-create.component'; @@ -78,22 +79,22 @@ const expectedAccessContract = { excludedRootUnits: [''], }; -let component: AccessContractCreateComponent; -let fixture: ComponentFixture; - class Page { + constructor(private fixture: ComponentFixture) {} get submit() { - return fixture.nativeElement.querySelector('button[type=submit]'); + return this.fixture.nativeElement.querySelector('button[type=submit]'); } control(name: string) { - return fixture.nativeElement.querySelector('[formControlName=' + name + ']'); + return this.fixture.nativeElement.querySelector('[formControlName=' + name + ']'); } } -let page: Page; - describe('AccessContractCreateComponent', () => { + let component: AccessContractCreateComponent; + let fixture: ComponentFixture; + let page: Page; + beforeEach(async () => { const matDialogRefSpy = jasmine.createSpyObj('MatDialogRef', ['close']); const agencyServiceSpy = jasmine.createSpyObj('AgencyService', { getOriginatingAgenciesAsOptions: of([]) }); @@ -145,7 +146,7 @@ describe('AccessContractCreateComponent', () => { component = fixture.componentInstance; component.allNodes.setValue(true); fixture.detectChanges(); - page = new Page(); + page = new Page(fixture); }); it('should create', () => { @@ -176,6 +177,10 @@ describe('AccessContractCreateComponent', () => { }); describe('Form', () => { + it('applies MiscValidators.requiredIdentifier to identifier control', () => { + expect(component.form.get('identifier').hasValidator(MiscValidators.requiredIdentifier)).toBeTruthy(); + }); + it('should be invalid when empty', () => { expect(component.form.invalid).toBeTruthy(); }); diff --git a/ui/ui-frontend/projects/referential/src/app/access-contract/access-contract-create/access-contract-create.component.ts b/ui/ui-frontend/projects/referential/src/app/access-contract/access-contract-create/access-contract-create.component.ts index 7af175eff1b..35af5af9266 100644 --- a/ui/ui-frontend/projects/referential/src/app/access-contract/access-contract-create/access-contract-create.component.ts +++ b/ui/ui-frontend/projects/referential/src/app/access-contract/access-contract-create/access-contract-create.component.ts @@ -40,12 +40,13 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { AccessContract, AccessContractService, + AgencyService, ConfirmDialogService, FilingPlanMode, + MiscValidators, Option, Status, VitamuiSelectOptions, - AgencyService, } from 'vitamui-library'; import { AccessContractCreateValidators } from './access-contract-create.validators'; @@ -137,17 +138,17 @@ export class AccessContractCreateComponent implements OnInit, OnDestroy { private initForm(): void { this.form = this.formBuilder.group({ - identifier: [ - null, - [Validators.required, Validators.minLength(2), Validators.maxLength(100)], - this.accessContractCreateValidators.uniqueIdentifier(), - ], status: [false], name: [ null, - [Validators.required, Validators.minLength(2), Validators.maxLength(100)], + [MiscValidators.requiredNotBlank, Validators.minLength(2), Validators.maxLength(100)], this.accessContractCreateValidators.uniqueName(), ], + identifier: [ + null, + [MiscValidators.requiredIdentifier, Validators.minLength(2), Validators.maxLength(100)], + this.accessContractCreateValidators.uniqueIdentifier(), + ], description: [null], accessLog: [false], /* <- step 3 -> */ diff --git a/ui/ui-frontend/projects/referential/src/app/access-contract/access-contract-preview/access-contract-information-tab/access-contract-information-tab.component.ts b/ui/ui-frontend/projects/referential/src/app/access-contract/access-contract-preview/access-contract-information-tab/access-contract-information-tab.component.ts index 53d856fcd8e..fec74254b7d 100644 --- a/ui/ui-frontend/projects/referential/src/app/access-contract/access-contract-preview/access-contract-information-tab/access-contract-information-tab.component.ts +++ b/ui/ui-frontend/projects/referential/src/app/access-contract/access-contract-preview/access-contract-information-tab/access-contract-information-tab.component.ts @@ -39,7 +39,7 @@ import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms' import { Observable, of } from 'rxjs'; import { catchError, filter, map, switchMap } from 'rxjs/operators'; import { extend, isEmpty } from 'underscore'; -import { AccessContract, AccessContractService, diff, Option } from 'vitamui-library'; +import { AccessContract, AccessContractService, diff, MiscValidators, Option } from 'vitamui-library'; import { RULE_TYPES } from '../../../rule/rules.constants'; import { AccessContractCreateValidators } from '../../access-contract-create/access-contract-create.validators'; @@ -152,7 +152,7 @@ export class AccessContractInformationTabComponent { status: ['ACTIVE'], name: [ null, - [Validators.required, Validators.minLength(2), Validators.maxLength(100)], + [MiscValidators.requiredNotBlank, Validators.minLength(2), Validators.maxLength(100)], this.accessContractCreateValidators.uniqueNameWhileEdit(this.previousValue), ], description: [null], diff --git a/ui/ui-frontend/projects/referential/src/app/admin-dsl/admin-dsl.component.spec.ts b/ui/ui-frontend/projects/referential/src/app/admin-dsl/admin-dsl.component.spec.ts index 631646c8622..06e24dc8834 100644 --- a/ui/ui-frontend/projects/referential/src/app/admin-dsl/admin-dsl.component.spec.ts +++ b/ui/ui-frontend/projects/referential/src/app/admin-dsl/admin-dsl.component.spec.ts @@ -56,7 +56,7 @@ describe('AdminDslComponent', () => { id: 'id', accessContract: 'AC-000001', dslQueryType: DslQueryType.ARCHIVE_UNIT, - dsl: {}, + dsl: '', response: {}, }; diff --git a/ui/ui-frontend/projects/referential/src/app/admin-dsl/admin-dsl.component.ts b/ui/ui-frontend/projects/referential/src/app/admin-dsl/admin-dsl.component.ts index 362fe08b5e3..257b3008586 100644 --- a/ui/ui-frontend/projects/referential/src/app/admin-dsl/admin-dsl.component.ts +++ b/ui/ui-frontend/projects/referential/src/app/admin-dsl/admin-dsl.component.ts @@ -39,7 +39,7 @@ import { Component } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { ActivatedRoute } from '@angular/router'; import { Observable } from 'rxjs'; -import { AppRootComponent, DslQueryType, Option, SnackBarService, AccessContractService } from 'vitamui-library'; +import { AccessContractService, AppRootComponent, DslQueryType, MiscValidators, Option, SnackBarService } from 'vitamui-library'; import { AdminDslService } from './admin-dsl.service'; import { TranslateService } from '@ngx-translate/core'; @@ -85,7 +85,7 @@ export class AdminDslComponent extends AppRootComponent { dslQueryType: [null, Validators.required], id: [null, [Validators.minLength(36), Validators.maxLength(36)]], accessContract: [null, Validators.required], - dsl: [null, Validators.required], + dsl: [null, MiscValidators.requiredNotBlank], response: null, }); } diff --git a/ui/ui-frontend/projects/referential/src/app/agency/agency-create/agency-create.component.html b/ui/ui-frontend/projects/referential/src/app/agency/agency-create/agency-create.component.html index 839ab00a068..d8481fea5d8 100644 --- a/ui/ui-frontend/projects/referential/src/app/agency/agency-create/agency-create.component.html +++ b/ui/ui-frontend/projects/referential/src/app/agency/agency-create/agency-create.component.html @@ -11,7 +11,6 @@ [placeholder]="'AGENCY.CREATE_DIALOG.IDENTIFIER' | translate" [errorMessageMap]="{ identifierExists: 'AGENCY.CREATE_DIALOG.IDENTIFIER_ALREADY_EXISTS' | translate, - onlyWhitespaces: 'AGENCY.CREATE_DIALOG.INVALID_FIELD' | translate, }" > @@ -21,7 +20,6 @@ [placeholder]="'AGENCY.CREATE_DIALOG.NAME' | translate" [errorMessageMap]="{ nameExists: 'AGENCY.CREATE_DIALOG.NAME_ALREADY_EXISTS' | translate, - onlyWhitespaces: 'AGENCY.CREATE_DIALOG.INVALID_FIELD' | translate, }" > diff --git a/ui/ui-frontend/projects/referential/src/app/agency/agency-create/agency-create.component.spec.ts b/ui/ui-frontend/projects/referential/src/app/agency/agency-create/agency-create.component.spec.ts index 5352edd0cc9..4c5d9d3646a 100644 --- a/ui/ui-frontend/projects/referential/src/app/agency/agency-create/agency-create.component.spec.ts +++ b/ui/ui-frontend/projects/referential/src/app/agency/agency-create/agency-create.component.spec.ts @@ -46,7 +46,7 @@ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { MatSelectModule } from '@angular/material/select'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { EMPTY, of } from 'rxjs'; -import { ConfirmDialogService, AgencyService } from 'vitamui-library'; +import { AgencyService, ConfirmDialogService, MiscValidators } from 'vitamui-library'; import { VitamUICommonTestModule } from 'vitamui-library/testing'; import { AgencyCreateComponent } from './agency-create.component'; import { AgencyCreateValidators } from './agency-create.validators'; @@ -81,22 +81,22 @@ const expectedAgency = { description: 'My Beautiful description', }; -let component: AgencyCreateComponent; -let fixture: ComponentFixture; - class Page { + constructor(private fixture: ComponentFixture) {} get submit() { - return fixture.nativeElement.querySelector('button[type=submit]'); + return this.fixture.nativeElement.querySelector('button[type=submit]'); } control(name: string) { - return fixture.nativeElement.querySelector('[formControlName=' + name + ']'); + return this.fixture.nativeElement.querySelector('[formControlName=' + name + ']'); } } -let page: Page; - describe('AgencyCreateComponent', () => { + let component: AgencyCreateComponent; + let fixture: ComponentFixture; + let page: Page; + beforeEach(async () => { const matDialogRefSpy = jasmine.createSpyObj('MatDialogRef', ['close']); @@ -104,7 +104,6 @@ describe('AgencyCreateComponent', () => { const agencyValidatorSpy = jasmine.createSpyObj('AgencyCreateValidators', { uniqueIdentifier: () => of(null), uniqueName: () => of(null), - onlyWhitespaces: () => {}, }); await TestBed.configureTestingModule({ imports: [ @@ -133,7 +132,7 @@ describe('AgencyCreateComponent', () => { fixture = TestBed.createComponent(AgencyCreateComponent); component = fixture.componentInstance; fixture.detectChanges(); - page = new Page(); + page = new Page(fixture); }); it('should create', () => { @@ -157,6 +156,10 @@ describe('AgencyCreateComponent', () => { }); describe('Form', () => { + it('applies MiscValidators.requiredIdentifier to identifier control', () => { + expect(component.form.get('identifier').hasValidator(MiscValidators.requiredIdentifier)).toBeTruthy(); + }); + it('should be invalid when empty', () => { expect(component.form.invalid).toBeTruthy(); }); diff --git a/ui/ui-frontend/projects/referential/src/app/agency/agency-create/agency-create.component.ts b/ui/ui-frontend/projects/referential/src/app/agency/agency-create/agency-create.component.ts index 9d125c0f903..04d6fba1f4f 100644 --- a/ui/ui-frontend/projects/referential/src/app/agency/agency-create/agency-create.component.ts +++ b/ui/ui-frontend/projects/referential/src/app/agency/agency-create/agency-create.component.ts @@ -35,9 +35,9 @@ * knowledge of the CeCILL-C license and that you accept its terms. */ import { Component, Inject, OnInit } from '@angular/core'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { FormBuilder, FormGroup } from '@angular/forms'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; -import { Agency, ConfirmDialogService, AgencyService } from 'vitamui-library'; +import { Agency, AgencyService, ConfirmDialogService, MiscValidators } from 'vitamui-library'; import { AgencyCreateValidators } from './agency-create.validators'; @Component({ @@ -61,12 +61,8 @@ export class AgencyCreateComponent implements OnInit { ngOnInit() { this.form = this.formBuilder.group({ - name: [null, [Validators.required, this.agencyCreateValidators.onlyWhitespaces], this.agencyCreateValidators.uniqueName()], - identifier: [ - null, - [Validators.required, this.agencyCreateValidators.onlyWhitespaces], - this.agencyCreateValidators.uniqueIdentifier(), - ], + name: [null, [MiscValidators.requiredNotBlank], this.agencyCreateValidators.uniqueName()], + identifier: [null, [MiscValidators.requiredIdentifier], this.agencyCreateValidators.uniqueIdentifier()], description: [null], }); } diff --git a/ui/ui-frontend/projects/referential/src/app/agency/agency-create/agency-create.validators.spec.ts b/ui/ui-frontend/projects/referential/src/app/agency/agency-create/agency-create.validators.spec.ts index d5875f22dfb..ef77613d5bf 100644 --- a/ui/ui-frontend/projects/referential/src/app/agency/agency-create/agency-create.validators.spec.ts +++ b/ui/ui-frontend/projects/referential/src/app/agency/agency-create/agency-create.validators.spec.ts @@ -69,14 +69,6 @@ describe('Agency Create Validators', () => { expect(agencyServiceSpy.existsProperties).toHaveBeenCalledWith({ name: '123456' }); })); - it('should return { onlyWhitespaces: true }', fakeAsync(() => { - const agencyServiceSpy = jasmine.createSpyObj('AgencyService', ['']); - const agencyCreateValidators = new AgencyCreateValidators(agencyServiceSpy); - expect(agencyCreateValidators.onlyWhitespaces(new FormControl(' '))).toEqual({ - onlyWhitespaces: true, - }); - })); - it('should not call the service', fakeAsync(() => { const agencyServiceSpy = jasmine.createSpyObj('AgencyService', ['existsProperties']); agencyServiceSpy.existsProperties.and.returnValue(of(true)); diff --git a/ui/ui-frontend/projects/referential/src/app/agency/agency-create/agency-create.validators.ts b/ui/ui-frontend/projects/referential/src/app/agency/agency-create/agency-create.validators.ts index 34003997058..8f33c89ec5c 100644 --- a/ui/ui-frontend/projects/referential/src/app/agency/agency-create/agency-create.validators.ts +++ b/ui/ui-frontend/projects/referential/src/app/agency/agency-create/agency-create.validators.ts @@ -35,7 +35,7 @@ * knowledge of the CeCILL-C license and that you accept its terms. */ import { Injectable } from '@angular/core'; -import { AbstractControl, AsyncValidatorFn, ValidatorFn } from '@angular/forms'; +import { AbstractControl, AsyncValidatorFn } from '@angular/forms'; import { of, timer } from 'rxjs'; import { map, switchMap, take } from 'rxjs/operators'; @@ -57,11 +57,6 @@ export class AgencyCreateValidators { return this.uniqueFields('identifier', 'identifierExists', identifierToIgnore); }; - onlyWhitespaces: ValidatorFn = (control: AbstractControl) => { - const regExp = /^\s+$/; - return regExp.test(control.value) ? { onlyWhitespaces: true } : null; - }; - private uniqueFields(field: string, existTag: string, valueToIgnore?: string) { return (control: AbstractControl) => { const properties: any = {}; diff --git a/ui/ui-frontend/projects/referential/src/app/agency/agency-preview/agency-information-tab/agency-information-tab.component.html b/ui/ui-frontend/projects/referential/src/app/agency/agency-preview/agency-information-tab/agency-information-tab.component.html index 4e9be1e5ecc..e30b79d7faf 100644 --- a/ui/ui-frontend/projects/referential/src/app/agency/agency-preview/agency-information-tab/agency-information-tab.component.html +++ b/ui/ui-frontend/projects/referential/src/app/agency/agency-preview/agency-information-tab/agency-information-tab.component.html @@ -6,7 +6,6 @@ [placeholder]="'AGENCY.TAB.NAME' | translate" [errorMessageMap]="{ nameExists: 'AGENCY.CREATE_DIALOG.NAME_ALREADY_EXISTS' | translate, - onlyWhitespaces: 'AGENCY.CREATE_DIALOG.INVALID_FIELD' | translate, }" > diff --git a/ui/ui-frontend/projects/referential/src/app/agency/agency-preview/agency-information-tab/agency-information-tab.component.ts b/ui/ui-frontend/projects/referential/src/app/agency/agency-preview/agency-information-tab/agency-information-tab.component.ts index d02c07a17a4..92974b1d8be 100644 --- a/ui/ui-frontend/projects/referential/src/app/agency/agency-preview/agency-information-tab/agency-information-tab.component.ts +++ b/ui/ui-frontend/projects/referential/src/app/agency/agency-preview/agency-information-tab/agency-information-tab.component.ts @@ -35,12 +35,12 @@ * knowledge of the CeCILL-C license and that you accept its terms. */ import { Component, EventEmitter, Input, Output } from '@angular/core'; -import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms'; +import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms'; import { ActivatedRoute } from '@angular/router'; import { finalize, Observable, of } from 'rxjs'; import { catchError, filter, map, switchMap } from 'rxjs/operators'; import { isEmpty } from 'underscore'; -import { Agency, ApplicationId, diff, Role, SecurityService, AgencyService, VitamUICommonModule } from 'vitamui-library'; +import { Agency, AgencyService, ApplicationId, diff, MiscValidators, Role, SecurityService, VitamUICommonModule } from 'vitamui-library'; import { TranslatePipe } from '@ngx-translate/core'; import { AsyncPipe, NgIf } from '@angular/common'; import { AgencyCreateValidators } from '../../agency-create/agency-create.validators'; @@ -99,7 +99,7 @@ export class AgencyInformationTabComponent { private agencyCreateValidators: AgencyCreateValidators, ) { this.form = this.formBuilder.group({ - name: [null, [Validators.required, agencyCreateValidators.onlyWhitespaces]], + name: [null, [MiscValidators.requiredNotBlank]], description: [null], }); diff --git a/ui/ui-frontend/projects/referential/src/app/audit/audit-create/audit-create.component.html b/ui/ui-frontend/projects/referential/src/app/audit/audit-create/audit-create.component.html index 6c08db8764a..dab0a3d6fcd 100644 --- a/ui/ui-frontend/projects/referential/src/app/audit/audit-create/audit-create.component.html +++ b/ui/ui-frontend/projects/referential/src/app/audit/audit-create/audit-create.component.html @@ -65,8 +65,8 @@ } @else if (enterIngestOperationsIdentifiers()) { diff --git a/ui/ui-frontend/projects/referential/src/app/audit/audit-create/audit-create.component.ts b/ui/ui-frontend/projects/referential/src/app/audit/audit-create/audit-create.component.ts index efb3ac411ad..791c9b53596 100644 --- a/ui/ui-frontend/projects/referential/src/app/audit/audit-create/audit-create.component.ts +++ b/ui/ui-frontend/projects/referential/src/app/audit/audit-create/audit-create.component.ts @@ -94,7 +94,6 @@ export class AuditCreateComponent implements OnInit, OnDestroy { public allProducerServices = new FormControl(false); public selectedNodes = new FormControl({ included: [], excluded: [] }); public producerServicesMultiSelect = new FormControl(); - public ingestOperationsEntries = new FormControl(); public startDateControl = new FormControl(''); public endDateControl = new FormControl(''); public accessContractId: string = null; @@ -187,10 +186,6 @@ export class AuditCreateComponent implements OnInit, OnDestroy { .pipe(takeUntil(this.destroyer$)) .subscribe((value) => this.updateOriginatingAgencyIdsOnChange(value)); - this.ingestOperationsEntries.valueChanges - .pipe(takeUntil(this.destroyer$)) - .subscribe((value) => this.updateIngestOperationsEntriesOnChange(value)); - this.form.controls.evidenceAudit.valueChanges.pipe(takeUntil(this.destroyer$)).subscribe((value) => { if (this.form.get('auditActions').value === AuditAction.AUDIT_FILE_RECTIFICATION) { this.form.controls.objectId.setValue(value); @@ -307,7 +302,7 @@ export class AuditCreateComponent implements OnInit, OnDestroy { this.form.get('startDate').markAsUntouched(); this.producerServicesMultiSelect.setValue([]); - this.ingestOperationsEntries.setValue([]); + this.form.get('ingestOperationIds').setValue([]); this.startDateControl.setValue(null); this.endDateControl.setValue(null); this.allProducerServices.setValue(false); @@ -365,7 +360,7 @@ export class AuditCreateComponent implements OnInit, OnDestroy { this.clearField('ingestOperationIds'); } this.producerServicesMultiSelect.setValue([]); - this.ingestOperationsEntries.setValue([]); + this.form.get('ingestOperationIds').setValue([]); this.allProducerServices.setValue(false); this.startDateControl.setValue(null); this.endDateControl.setValue(null); @@ -379,15 +374,6 @@ export class AuditCreateComponent implements OnInit, OnDestroy { this.form.updateValueAndValidity(); } - private updateIngestOperationsEntriesOnChange(value: string) { - if (value.length > 0) { - const values = value.split(','); - this.form.controls.ingestOperationIds.setValue(values); - } else { - this.form.controls.ingestOperationIds.setValue([]); - } - } - private updateOriginatingAgencyIdsOnChange(values: Array) { this.form.controls.originatingAgencyIds.setValue(values); } diff --git a/ui/ui-frontend/projects/referential/src/app/context/context-create/context-create.component.html b/ui/ui-frontend/projects/referential/src/app/context/context-create/context-create.component.html index 0107b3738cd..011e2f88f89 100644 --- a/ui/ui-frontend/projects/referential/src/app/context/context-create/context-create.component.html +++ b/ui/ui-frontend/projects/referential/src/app/context/context-create/context-create.component.html @@ -29,7 +29,6 @@ [placeholder]="'CONTEXTS_APP.CREATE_DIALOG.INFORMATION.IDENTIFIER' | translate" [errorMessageMap]="{ identifierExists: 'CONTEXTS_APP.CREATE_DIALOG.INFORMATION.IDENTIFIER_ALREADY_EXISTS' | translate, - incorrectIdentifier: 'CONTEXTS_APP.CREATE_DIALOG.INFORMATION.INCORRECT_IDENTIFIER' | translate, }" > diff --git a/ui/ui-frontend/projects/referential/src/app/context/context-create/context-create.component.spec.ts b/ui/ui-frontend/projects/referential/src/app/context/context-create/context-create.component.spec.ts index c8eb25ca8ac..583fc67b125 100644 --- a/ui/ui-frontend/projects/referential/src/app/context/context-create/context-create.component.spec.ts +++ b/ui/ui-frontend/projects/referential/src/app/context/context-create/context-create.component.spec.ts @@ -39,18 +39,21 @@ import { Component, forwardRef, Input, NO_ERRORS_SCHEMA } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ControlValueAccessor, NG_VALUE_ACCESSOR, ReactiveFormsModule } from '@angular/forms'; import { MatButtonToggleModule } from '@angular/material/button-toggle'; -import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { MAT_DIALOG_DATA, MatDialogActions, MatDialogRef } from '@angular/material/dialog'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatProgressBarModule } from '@angular/material/progress-bar'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { MatSelectModule } from '@angular/material/select'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { EMPTY, of } from 'rxjs'; -import { ConfirmDialogService, OtpState } from 'vitamui-library'; +import { BASE_URL, ConfirmDialogService, LoggerModule, MiscValidators, SelectComponent } from 'vitamui-library'; import { VitamUICommonTestModule } from 'vitamui-library/testing'; import { ContextService } from '../context.service'; import { ContextCreateComponent } from './context-create.component'; import { ContextCreateValidators } from './context-create.validators'; +import { SecurityProfileService } from '../../security-profile/security-profile.service'; +import { TranslateModule } from '@ngx-translate/core'; +import { ContextEditPermissionModule } from './context-edit-permission/context-edit-permission.module'; @Component({ selector: 'app-owner-form', @@ -75,79 +78,62 @@ class OwnerFormStubComponent implements ControlValueAccessor { } const expectedContext = { - enabled: true, - code: '424242', + status: 'INACTIVE', name: 'John Doe', - companyName: 'John Co.', - hasCustomGraphicIdentity: false, - passwordRevocationDelay: 3, - otp: OtpState.OPTIONAL, - address: { - street: 'street', - zipCode: '12345', - city: 'New York', - country: 'US', - }, - language: 'en', - emailDomains: ['test.com', 'toto.co.uk'], - defaultEmailDomain: 'test.com', - owners: [ - { - code: '666666', - name: 'Alice Vans', - companyName: 'Vans', - address: { - street: 'street2', - zipCode: '43121', - city: 'Paris', - country: 'FR', - }, - }, - ], + identifier: 'jdoe', + securityProfile: 'securityProfile', + enableControl: false, + permissions: [] as unknown[], }; -let component: ContextCreateComponent; -let fixture: ComponentFixture; - class Page { + constructor(private fixture: ComponentFixture) {} get submit() { - return fixture.nativeElement.querySelector('button[type=submit]'); + return this.fixture.nativeElement.querySelector('button[type=submit]'); } control(name: string) { - return fixture.nativeElement.querySelector('[formControlName=' + name + ']'); + return this.fixture.nativeElement.querySelector('[formControlName=' + name + ']'); } } -let page: Page; +const securityProfileServiceMock = { + getAll: () => of([]), +}; + +describe('ContextCreateComponent', () => { + let component: ContextCreateComponent; + let fixture: ComponentFixture; + let page: Page; -// TODO gafou : boom tomorrow -xdescribe('ContextCreateComponent', () => { beforeEach(async () => { const matDialogRefSpy = jasmine.createSpyObj('MatDialogRef', ['close']); - const contextServiceSpy = jasmine.createSpyObj('ContextService', { create: of({}) }); - const contextCreateValidatorsSpy = jasmine.createSpyObj('ContextCreateValidators', { - uniqueCode: () => of(null), - uniqueDomain: of(null), - }); + const contextServiceSpy = jasmine.createSpyObj('ContextService', { create: of({}), existsProperties: of({}) }); await TestBed.configureTestingModule({ imports: [ - ReactiveFormsModule, - MatFormFieldModule, - MatSelectModule, + ContextEditPermissionModule, + LoggerModule.forRoot(), MatButtonToggleModule, + MatDialogActions, + MatFormFieldModule, MatProgressBarModule, - NoopAnimationsModule, MatProgressSpinnerModule, + MatSelectModule, + NoopAnimationsModule, + ReactiveFormsModule, + SelectComponent, + TranslateModule.forRoot(), VitamUICommonTestModule, ], declarations: [ContextCreateComponent, OwnerFormStubComponent], providers: [ + { provide: BASE_URL, useValue: '/fake-api' }, { provide: MatDialogRef, useValue: matDialogRefSpy }, { provide: MAT_DIALOG_DATA, useValue: {} }, { provide: ContextService, useValue: contextServiceSpy }, - { provide: ContextCreateValidators, useValue: contextCreateValidatorsSpy }, + ContextCreateValidators, { provide: ConfirmDialogService, useValue: { listenToEscapeKeyPress: () => EMPTY } }, + { provide: SecurityProfileService, useValue: securityProfileServiceMock }, ], schemas: [NO_ERRORS_SCHEMA], }).compileComponents(); @@ -157,98 +143,24 @@ xdescribe('ContextCreateComponent', () => { fixture = TestBed.createComponent(ContextCreateComponent); component = fixture.componentInstance; fixture.detectChanges(); - page = new Page(); + page = new Page(fixture); }); it('should create', () => { expect(component).toBeTruthy(); }); + it('applies MiscValidators.requiredIdentifier to identifier control', () => { + expect(component.form.get('identifier').hasValidator(MiscValidators.requiredIdentifier)).toBeTruthy(); + }); + describe('Template', () => { it('should have the right inputs', () => { - expect(page.control('code')).toBeTruthy(); expect(page.control('name')).toBeTruthy(); - expect(page.control('companyName')).toBeTruthy(); - expect(page.control('street')).toBeTruthy(); - expect(page.control('zipCode')).toBeTruthy(); - expect(page.control('city')).toBeTruthy(); - expect(page.control('country')).toBeTruthy(); - expect(page.control('language')).toBeTruthy(); - expect(page.control('passwordRevocationDelay')).toBeTruthy(); - expect(page.control('otp')).toBeTruthy(); - expect(page.control('emailDomains')).toBeTruthy(); - // expect(page.control('hasCustomGraphicIdentity')).toBeTruthy(); }); it('should have a submit button', () => { expect(page.submit).toBeTruthy(); - expect(page.submit.attributes.disabled).toBeTruthy(); - component.form.setValue(expectedContext); - fixture.detectChanges(); - expect(page.submit.attributes.disabled).toBeFalsy(); - }); - }); - - describe('Form', () => { - it('should be invalid when empty', () => { - expect(component.form.invalid).toBeTruthy(); - }); - - it('should be valid', () => { - component.form.setValue(expectedContext); - expect(component.form.valid).toBeTruthy(); - }); - - describe('Validators', () => { - describe('code', () => { - it('should check the code format', () => { - expect(setControlValue('code', '').invalid).toBeTruthy(); - expect(setControlValue('code', 'A1A1AazZ').invalid).toBeTruthy(); - expect(setControlValue('code', '1234567890123456789012345').invalid).toBeTruthy(); - expect(setControlValue('code', '123456789012345678901').invalid).toBeTruthy(); - expect(setControlValue('code', '12345678901234567890').valid).toBeTruthy('12345678901234567890'); - expect(setControlValue('code', '000000000').valid).toBeTruthy('000000000'); - expect(setControlValue('code', '999999').valid).toBeTruthy('999999'); - }); - }); - - describe('fields', () => { - it('should be required', () => { - expect(setControlValue('name', '').invalid).toBeTruthy(); - expect(setControlValue('name', 'n').valid).toBeTruthy(); - - expect(setControlValue('companyName', '').invalid).toBeTruthy(); - expect(setControlValue('companyName', 't').valid).toBeTruthy(); - - expect(setControlValue('address.street', '').invalid).toBeTruthy(); - expect(setControlValue('address.street', 't').valid).toBeTruthy(); - - expect(setControlValue('address.zipCode', '').invalid).toBeTruthy(); - expect(setControlValue('address.zipCode', 't').valid).toBeTruthy(); - - expect(setControlValue('address.city', '').invalid).toBeTruthy(); - expect(setControlValue('address.city', 't').valid).toBeTruthy(); - - expect(setControlValue('address.country', '').invalid).toBeTruthy(); - expect(setControlValue('address.country', 't').valid).toBeTruthy(); - - expect(setControlValue('language', '').invalid).toBeTruthy(); - expect(setControlValue('language', 't').valid).toBeTruthy(); - - expect(setControlValue('emailDomains', '').invalid).toBeTruthy(); - expect(setControlValue('emailDomains', 't').valid).toBeTruthy(); - - expect(setControlValue('defaultEmailDomain', '').invalid).toBeTruthy(); - expect(setControlValue('defaultEmailDomain', 't').valid).toBeTruthy(); - }); - }); - - function setControlValue(name: string | Array, value: any) { - const control = component.form.get(name); - control.setValue(value); - - return control; - } }); }); diff --git a/ui/ui-frontend/projects/referential/src/app/context/context-create/context-create.component.ts b/ui/ui-frontend/projects/referential/src/app/context/context-create/context-create.component.ts index 4ba6acaf2e1..f0c4edb1b48 100644 --- a/ui/ui-frontend/projects/referential/src/app/context/context-create/context-create.component.ts +++ b/ui/ui-frontend/projects/referential/src/app/context/context-create/context-create.component.ts @@ -38,7 +38,7 @@ import { Component, Inject, Input, OnDestroy, OnInit, ViewChild } from '@angular import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { Subscription } from 'rxjs'; -import { ConfirmDialogService, Context, Option } from 'vitamui-library'; +import { ConfirmDialogService, Context, MiscValidators, Option } from 'vitamui-library'; import { SecurityProfileService } from '../../security-profile/security-profile.service'; import { ContextService } from '../context.service'; import { ContextCreateValidators } from './context-create.validators'; @@ -86,7 +86,7 @@ export class ContextCreateComponent implements OnInit, OnDestroy { ], identifier: [ null, - [Validators.required, Validators.minLength(2), Validators.maxLength(100), this.contextCreateValidators.allowedIdentifier()], + [MiscValidators.requiredIdentifier, Validators.minLength(2), Validators.maxLength(100)], this.contextCreateValidators.uniqueIdentifier(), ], securityProfile: [null, Validators.required], diff --git a/ui/ui-frontend/projects/referential/src/app/context/context-create/context-create.validators.ts b/ui/ui-frontend/projects/referential/src/app/context/context-create/context-create.validators.ts index ddbf4283e74..d77071f39fe 100644 --- a/ui/ui-frontend/projects/referential/src/app/context/context-create/context-create.validators.ts +++ b/ui/ui-frontend/projects/referential/src/app/context/context-create/context-create.validators.ts @@ -105,10 +105,4 @@ export class ContextCreateValidators { return !control.value || control.value.match('^[a-zA-Z0-9+=@_-]*$') ? null : { incorrectName: true }; }; }; - - allowedIdentifier = (): ValidatorFn => { - return (control: AbstractControl): ValidationErrors => { - return !control.value || control.value.match('^[a-zA-Z0-9+=@_-]*$') ? null : { incorrectIdentifier: true }; - }; - }; } diff --git a/ui/ui-frontend/projects/referential/src/app/file-format/file-format-create/file-format-create.component.spec.ts b/ui/ui-frontend/projects/referential/src/app/file-format/file-format-create/file-format-create.component.spec.ts index 418ab449e46..5dcd6b9889e 100644 --- a/ui/ui-frontend/projects/referential/src/app/file-format/file-format-create/file-format-create.component.spec.ts +++ b/ui/ui-frontend/projects/referential/src/app/file-format/file-format-create/file-format-create.component.spec.ts @@ -46,12 +46,13 @@ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { MatSelectModule } from '@angular/material/select'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { EMPTY, of } from 'rxjs'; -import { ConfirmDialogService } from 'vitamui-library'; +import { ConfirmDialogService, MiscValidators, SelectComponent, StartupService } from 'vitamui-library'; import { VitamUICommonTestModule } from 'vitamui-library/testing'; import { FileFormatService } from '../file-format.service'; import { FileFormatCreateComponent } from './file-format-create.component'; import { FileFormatCreateValidators } from './file-format-create.validators'; +import { TranslateModule } from '@ngx-translate/core'; const expectedFileFormat = { puid: '424242', @@ -59,27 +60,28 @@ const expectedFileFormat = { name: 'Test', mimeType: 'application/test', extensions: '.test, .tst', + hasPriorityOverFileFormatIDs: false, }; -let component: FileFormatCreateComponent; -let fixture: ComponentFixture; - class Page { + constructor(private fixture: ComponentFixture) {} get submit() { - return fixture.nativeElement.querySelector('button[type=submit]'); + return this.fixture.nativeElement.querySelector('button[type=submit]'); } control(name: string) { - return fixture.nativeElement.querySelector('[formControlName=' + name + ']'); + return this.fixture.nativeElement.querySelector('[formControlName=' + name + ']'); } } -let page: Page; +describe('FileFormatCreateComponent', () => { + let component: FileFormatCreateComponent; + let fixture: ComponentFixture; + let page: Page; -xdescribe(' FileFormatCreateComponent', () => { beforeEach(async () => { const matDialogRefSpy = jasmine.createSpyObj('MatDialogRef', ['close']); - const fileFormatServiceSpy = jasmine.createSpyObj('FileFormatService', { create: of({}) }); + const fileFormatServiceSpy = jasmine.createSpyObj('FileFormatService', { create: of({}), getAllForTenant: of({}) }); const fileFormatCreateValidatorsSpy = jasmine.createSpyObj('FileFormatCreateValidators', { uniquePuid: () => of(null), uniqueName: () => of(null), @@ -93,12 +95,15 @@ xdescribe(' FileFormatCreateComponent', () => { MatProgressBarModule, NoopAnimationsModule, MatProgressSpinnerModule, + SelectComponent, + TranslateModule.forRoot(), VitamUICommonTestModule, ], declarations: [FileFormatCreateComponent], providers: [ { provide: MatDialogRef, useValue: matDialogRefSpy }, { provide: MAT_DIALOG_DATA, useValue: {} }, + { provide: StartupService, useValue: { getTenantIdentifier: () => of(1) } }, { provide: FileFormatService, useValue: fileFormatServiceSpy }, { provide: FileFormatCreateValidators, useValue: fileFormatCreateValidatorsSpy }, { provide: ConfirmDialogService, useValue: { listenToEscapeKeyPress: () => EMPTY } }, @@ -111,13 +116,17 @@ xdescribe(' FileFormatCreateComponent', () => { fixture = TestBed.createComponent(FileFormatCreateComponent); component = fixture.componentInstance; fixture.detectChanges(); - page = new Page(); + page = new Page(fixture); }); it('should create', () => { expect(component).toBeTruthy(); }); + it('applies MiscValidators.requiredIdentifier to puid control', () => { + expect(component.form.get('puid').hasValidator(MiscValidators.requiredIdentifier)).toBeTruthy(); + }); + describe('Template', () => { it('should have the right inputs', () => { expect(page.control('puid')).toBeTruthy(); diff --git a/ui/ui-frontend/projects/referential/src/app/file-format/file-format-create/file-format-create.component.ts b/ui/ui-frontend/projects/referential/src/app/file-format/file-format-create/file-format-create.component.ts index 21ce6372930..e0a477cad32 100644 --- a/ui/ui-frontend/projects/referential/src/app/file-format/file-format-create/file-format-create.component.ts +++ b/ui/ui-frontend/projects/referential/src/app/file-format/file-format-create/file-format-create.component.ts @@ -43,6 +43,7 @@ import { ConfirmDialogService, FILE_FORMAT_EXTERNAL_PREFIX, FileFormat, + MiscValidators, Option, StartupService, VitamuiSelectOptions, @@ -84,11 +85,19 @@ export class FileFormatCreateComponent implements OnInit, OnDestroy { ngOnInit() { this.form = this.formBuilder.group({ - name: [null, [Validators.required, Validators.minLength(2), Validators.maxLength(100)], this.fileFormatCreateValidators.uniqueName()], - puid: [null, [Validators.required, Validators.minLength(2), Validators.maxLength(100)], this.fileFormatCreateValidators.uniquePuid()], - version: [null, Validators.required], + name: [ + null, + [MiscValidators.requiredNotBlank, Validators.minLength(2), Validators.maxLength(100)], + this.fileFormatCreateValidators.uniqueName(), + ], + puid: [ + null, + [MiscValidators.requiredIdentifier, Validators.minLength(2), Validators.maxLength(100)], + this.fileFormatCreateValidators.uniquePuid(), + ], + version: [null, MiscValidators.requiredNotBlank], mimeType: [null], - extensions: [null, Validators.required], + extensions: [null, MiscValidators.requiredNotBlank], hasPriorityOverFileFormatIDs: [null], }); diff --git a/ui/ui-frontend/projects/referential/src/app/file-format/file-format-preview/file-format-information-tab/file-format-information-tab.component.spec.ts b/ui/ui-frontend/projects/referential/src/app/file-format/file-format-preview/file-format-information-tab/file-format-information-tab.component.spec.ts index c7b67f03c6e..88905f4c78e 100644 --- a/ui/ui-frontend/projects/referential/src/app/file-format/file-format-preview/file-format-information-tab/file-format-information-tab.component.spec.ts +++ b/ui/ui-frontend/projects/referential/src/app/file-format/file-format-preview/file-format-information-tab/file-format-information-tab.component.spec.ts @@ -36,12 +36,11 @@ */ import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing'; -import { NO_ERRORS_SCHEMA } from '@angular/core'; import { ReactiveFormsModule } from '@angular/forms'; import { ActivatedRoute } from '@angular/router'; import { TranslateModule } from '@ngx-translate/core'; import { of } from 'rxjs'; -import { FileFormat, SecurityService, StartupService, WINDOW_LOCATION } from 'vitamui-library'; +import { FileFormat, MiscValidators, SecurityService, StartupService, WINDOW_LOCATION } from 'vitamui-library'; import { FileFormatService } from '../../file-format.service'; import { FileFormatInformationTabComponent } from './file-format-information-tab.component'; import { VitamUICommonTestModule } from 'vitamui-library/testing'; @@ -107,7 +106,6 @@ describe('FileFormatInformationTabComponent', () => { { provide: WINDOW_LOCATION, useValue: window.location }, { provide: FileFormatService, useValue: fileFormatServiceMock }, ], - schemas: [NO_ERRORS_SCHEMA], }).compileComponents(); }); @@ -123,4 +121,8 @@ describe('FileFormatInformationTabComponent', () => { tick(); expect(component).toBeTruthy(); })); + + it('applies MiscValidators.requiredIdentifier to puid control', () => { + expect(component.form.get('puid').hasValidator(MiscValidators.requiredIdentifier)).toBeTruthy(); + }); }); diff --git a/ui/ui-frontend/projects/referential/src/app/file-format/file-format-preview/file-format-information-tab/file-format-information-tab.component.ts b/ui/ui-frontend/projects/referential/src/app/file-format/file-format-preview/file-format-information-tab/file-format-information-tab.component.ts index 8d5422ed490..36f82699863 100644 --- a/ui/ui-frontend/projects/referential/src/app/file-format/file-format-preview/file-format-information-tab/file-format-information-tab.component.ts +++ b/ui/ui-frontend/projects/referential/src/app/file-format/file-format-preview/file-format-information-tab/file-format-information-tab.component.ts @@ -36,12 +36,21 @@ */ import { formatDate } from '@angular/common'; import { Component, EventEmitter, Inject, Input, LOCALE_ID, Output } from '@angular/core'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { FormBuilder, FormGroup } from '@angular/forms'; import { ActivatedRoute } from '@angular/router'; import { BehaviorSubject, combineLatest, Observable, of, Subscription } from 'rxjs'; import { catchError, filter, map, switchMap, tap } from 'rxjs/operators'; import { extend, isEmpty, omit } from 'underscore'; -import { ApplicationId, diff, FILE_FORMAT_EXTERNAL_PREFIX, FileFormat, Role, SecurityService, VitamuiSelectOptions } from 'vitamui-library'; +import { + ApplicationId, + diff, + FILE_FORMAT_EXTERNAL_PREFIX, + FileFormat, + MiscValidators, + Role, + SecurityService, + VitamuiSelectOptions, +} from 'vitamui-library'; import { FileFormatService } from '../../file-format.service'; @Component({ @@ -139,12 +148,12 @@ export class FileFormatInformationTabComponent { private securityService: SecurityService, ) { this.form = this.formBuilder.group({ - puid: [{ value: null, disabled: true }, Validators.required], - name: [{ value: null }, Validators.required], - mimeType: [{ value: null }], - version: [{ value: null }, Validators.required], - extensions: [{ value: null }], - hasPriorityOverFileFormatIDs: [{ value: null }], + puid: [{ value: null, disabled: true }, MiscValidators.requiredIdentifier], + name: [null, MiscValidators.requiredNotBlank], + mimeType: [null], + version: [null, MiscValidators.requiredNotBlank], + extensions: [null, MiscValidators.requiredNotBlank], + hasPriorityOverFileFormatIDs: [null], createdDate: [{ value: null, disabled: true }], updateDate: [{ value: null, disabled: true }], versionPronom: [{ value: null, disabled: true }], diff --git a/ui/ui-frontend/projects/referential/src/app/ingest-contract/ingest-contract-create/ingest-contract-create.component.spec.ts b/ui/ui-frontend/projects/referential/src/app/ingest-contract/ingest-contract-create/ingest-contract-create.component.spec.ts index 43154a313a8..f9159378e48 100644 --- a/ui/ui-frontend/projects/referential/src/app/ingest-contract/ingest-contract-create/ingest-contract-create.component.spec.ts +++ b/ui/ui-frontend/projects/referential/src/app/ingest-contract/ingest-contract-create/ingest-contract-create.component.spec.ts @@ -50,6 +50,7 @@ import { ExternalParameters, ExternalParametersService, LoggerModule, + MiscValidators, } from 'vitamui-library'; import { VitamUICommonTestModule } from 'vitamui-library/testing'; import { ArchiveProfileApiService } from '../../core/api/archive-profile-api.service'; @@ -123,4 +124,8 @@ describe('IngestContractCreateComponent', () => { it('should create', () => { expect(component).toBeTruthy(); }); + + it('applies MiscValidators.requiredIdentifier to identifier control', () => { + expect(component.form.get('identifier').hasValidator(MiscValidators.requiredIdentifier)).toBeTruthy(); + }); }); diff --git a/ui/ui-frontend/projects/referential/src/app/ingest-contract/ingest-contract-create/ingest-contract-create.component.ts b/ui/ui-frontend/projects/referential/src/app/ingest-contract/ingest-contract-create/ingest-contract-create.component.ts index cd4fcd0b959..ec2aeda4139 100644 --- a/ui/ui-frontend/projects/referential/src/app/ingest-contract/ingest-contract-create/ingest-contract-create.component.ts +++ b/ui/ui-frontend/projects/referential/src/app/ingest-contract/ingest-contract-create/ingest-contract-create.component.ts @@ -43,11 +43,12 @@ import { ConfirmDialogService, FilingPlanMode, IngestContract, + MiscValidators, Option, SignaturePolicy, SignedDocumentPolicyEnum, - VitamuiSelectOptions, VitamuiHttpHeaders, + VitamuiSelectOptions, } from 'vitamui-library'; import { ArchiveProfileApiService } from '../../core/api/archive-profile-api.service'; import { ManagementContractApiService } from '../../core/api/management-contract-api.service'; @@ -106,18 +107,18 @@ export class IngestContractCreateComponent implements OnInit, OnDestroy { ngOnInit() { this.form = this.formBuilder.group({ + status: ['INACTIVE'], identifier: [ null, - [Validators.required, Validators.minLength(2), Validators.maxLength(100)], + [MiscValidators.requiredIdentifier, Validators.minLength(2), Validators.maxLength(100)], this.ingestContractCreateValidators.uniqueIdentifier(), ], - status: ['INACTIVE'], name: [ null, - [Validators.required, Validators.minLength(2), Validators.maxLength(100)], + [MiscValidators.requiredNotBlank, Validators.minLength(2), Validators.maxLength(100)], this.ingestContractCreateValidators.uniqueName(), ], - description: [null, Validators.required], + description: [null, MiscValidators.requiredNotBlank], /* <- step 2 -> */ archiveProfiles: [new Array() /* Validators.required */], managementContractId: [null], diff --git a/ui/ui-frontend/projects/referential/src/app/ingest-contract/ingest-contract-preview/ingest-contract-information-tab/ingest-contract-information-tab.component.spec.ts b/ui/ui-frontend/projects/referential/src/app/ingest-contract/ingest-contract-preview/ingest-contract-information-tab/ingest-contract-information-tab.component.spec.ts new file mode 100644 index 00000000000..1f557df1b99 --- /dev/null +++ b/ui/ui-frontend/projects/referential/src/app/ingest-contract/ingest-contract-preview/ingest-contract-information-tab/ingest-contract-information-tab.component.spec.ts @@ -0,0 +1,141 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2019-2022) + * and the signatories of the "VITAM - Accord du Contributeur" agreement. + * + * contact@programmevitam.fr + * + * This software is a computer program whose purpose is to implement + * implement a digital archiving front-office system for the secure and + * efficient high volumetry VITAM solution. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing'; + +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { ActivatedRoute } from '@angular/router'; +import { TranslateModule } from '@ngx-translate/core'; +import { of } from 'rxjs'; +import { + IngestContract, + MiscValidators, + SecurityService, + SelectComponent, + SignedDocumentPolicyEnum, + WINDOW_LOCATION, +} from 'vitamui-library'; +import { VitamUICommonTestModule } from 'vitamui-library/testing'; +import { IngestContractInformationTabComponent } from './ingest-contract-information-tab.component'; +import { IngestContractService } from '../../ingest-contract.service'; +import { ManagementContractApiService } from '../../../core/api/management-contract-api.service'; +import { ArchiveProfileApiService } from '../../../core/api/archive-profile-api.service'; + +describe('IngestContractInformationTabComponent', () => { + let component: IngestContractInformationTabComponent; + let fixture: ComponentFixture; + + const fileFormatValue: Partial = { + identifier: 'ingestId', + status: 'ACTIVE', + name: 'Name', + description: 'description', + archiveProfiles: [], + managementContractId: 'managementContractId', + }; + + const previousValue: IngestContract = { + id: 'xxx', + tenant: 1, + version: 1, + identifier: 'ingestId', + status: 'ACTIVE', + name: 'Name', + description: 'description', + creationDate: '', + lastUpdate: '', + activationDate: '', + deactivationDate: '', + checkParentLink: '', + linkParentId: '', + checkParentId: [], + masterMandatory: false, + everyDataObjectVersion: false, + dataObjectVersion: [], + formatUnidentifiedAuthorized: false, + everyFormatType: false, + formatType: [], + archiveProfiles: [], + managementContractId: 'managementContractId', + computeInheritedRulesAtIngest: false, + signaturePolicy: { + signedDocument: SignedDocumentPolicyEnum.ALLOWED, + declaredSignature: false, + declaredTimestamp: false, + declaredAdditionalProof: false, + }, + }; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot(), FormsModule, ReactiveFormsModule, SelectComponent, VitamUICommonTestModule], + declarations: [IngestContractInformationTabComponent], + providers: [ + { + provide: ActivatedRoute, + useValue: { params: of({ tenantIdentifier: 1 }), data: of({ appId: 'MANAGEMENT_CONTRACT_APP' }) }, + }, + { + provide: SecurityService, + useValue: { + hasRole$: () => of(true), + }, + }, + { provide: IngestContractService, useValue: {} }, + { provide: ManagementContractApiService, useValue: { getAllByParams: () => of({}) } }, + { provide: ArchiveProfileApiService, useValue: { getAllByParams: () => of({}) } }, + { provide: WINDOW_LOCATION, useValue: window.location }, + ], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(IngestContractInformationTabComponent); + component = fixture.componentInstance; + component.ingestContract = previousValue; + component.form.setValue(fileFormatValue); + fixture.detectChanges(); + }); + + it('should create', fakeAsync(() => { + tick(); + expect(component).toBeTruthy(); + })); + + it('applies MiscValidators.requiredIdentifier to identifier control', () => { + expect(component.form.get('identifier').hasValidator(MiscValidators.requiredIdentifier)).toBeTruthy(); + }); +}); diff --git a/ui/ui-frontend/projects/referential/src/app/ingest-contract/ingest-contract-preview/ingest-contract-information-tab/ingest-contract-information-tab.component.ts b/ui/ui-frontend/projects/referential/src/app/ingest-contract/ingest-contract-preview/ingest-contract-information-tab/ingest-contract-information-tab.component.ts index d958aef08f4..877f67b9344 100644 --- a/ui/ui-frontend/projects/referential/src/app/ingest-contract/ingest-contract-preview/ingest-contract-information-tab/ingest-contract-information-tab.component.ts +++ b/ui/ui-frontend/projects/referential/src/app/ingest-contract/ingest-contract-preview/ingest-contract-information-tab/ingest-contract-information-tab.component.ts @@ -36,11 +36,11 @@ */ import { HttpHeaders, HttpParams } from '@angular/common/http'; import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; -import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms'; +import { FormBuilder, FormControl, FormGroup } from '@angular/forms'; import { Observable, of } from 'rxjs'; import { catchError, filter, map, switchMap } from 'rxjs/operators'; import { extend, isEmpty } from 'underscore'; -import { diff, IngestContract, Option, VitamuiHttpHeaders } from 'vitamui-library'; +import { diff, IngestContract, MiscValidators, Option, VitamuiHttpHeaders } from 'vitamui-library'; import { ArchiveProfileApiService } from '../../../core/api/archive-profile-api.service'; import { ManagementContractApiService } from '../../../core/api/management-contract-api.service'; @@ -122,10 +122,10 @@ export class IngestContractInformationTabComponent implements OnInit { private ingestContractCreateValidators: IngestContractCreateValidators, ) { this.form = this.formBuilder.group({ - identifier: [null, Validators.required], + identifier: [null, MiscValidators.requiredIdentifier], status: ['ACTIVE'], - name: [null, Validators.required, this.ingestContractCreateValidators.uniqueNameWhileEdit(this.previousValue)], - description: [null, Validators.required], + name: [null, MiscValidators.requiredNotBlank, this.ingestContractCreateValidators.uniqueNameWhileEdit(this.previousValue)], + description: [null, MiscValidators.requiredNotBlank], archiveProfiles: [new Array() /* Validators.required */], managementContractId: [null], }); diff --git a/ui/ui-frontend/projects/referential/src/app/logbook-management-operation/logbook-management-operation-preview/logbook-management-operation-preview.component.ts b/ui/ui-frontend/projects/referential/src/app/logbook-management-operation/logbook-management-operation-preview/logbook-management-operation-preview.component.ts index 589038a1a0a..040893e0a62 100644 --- a/ui/ui-frontend/projects/referential/src/app/logbook-management-operation/logbook-management-operation-preview/logbook-management-operation-preview.component.ts +++ b/ui/ui-frontend/projects/referential/src/app/logbook-management-operation/logbook-management-operation-preview/logbook-management-operation-preview.component.ts @@ -41,6 +41,7 @@ import { filter } from 'rxjs/operators'; import { OperationDetails } from '../../models/operation-response.interface'; import { LogbookManagementOperationService } from '../logbook-management-operation.service'; import { FormControl, Validators } from '@angular/forms'; +import { MiscValidators } from 'vitamui-library'; @Component({ selector: 'app-logbook-management-operation-preview', @@ -72,7 +73,7 @@ export class LogbookManagementOperationPreviewComponent implements OnInit, OnDes } ngOnInit(): void { - this.reason = new FormControl('', [Validators.required, Validators.maxLength(500), Validators.minLength(3)]); + this.reason = new FormControl('', [MiscValidators.requiredNotBlank, Validators.maxLength(500), Validators.minLength(3)]); if (this.logbookManagementOperationService.operationUpdated) { this.operationUpdatedSub = this.logbookManagementOperationService.operationUpdated.subscribe((updatedOperation: OperationDetails) => { this.operation = updatedOperation; diff --git a/ui/ui-frontend/projects/referential/src/app/management-contract/management-contract-create/management-contract-create.component.spec.ts b/ui/ui-frontend/projects/referential/src/app/management-contract/management-contract-create/management-contract-create.component.spec.ts index 14b7f711417..2ff2efc368a 100644 --- a/ui/ui-frontend/projects/referential/src/app/management-contract/management-contract-create/management-contract-create.component.spec.ts +++ b/ui/ui-frontend/projects/referential/src/app/management-contract/management-contract-create/management-contract-create.component.spec.ts @@ -52,6 +52,7 @@ import { InjectorModule, LoggerModule, ManagementContract, + MiscValidators, VitamUILibraryModule, WINDOW_LOCATION, } from 'vitamui-library'; @@ -138,6 +139,10 @@ describe('ManagementContractCreateComponent', () => { expect(component.form.get('identifier')).toBeTruthy(); }); + it('applies MiscValidators.requiredIdentifier to identifier control', () => { + expect(component.form.get('identifier').hasValidator(MiscValidators.requiredIdentifier)).toBeTruthy(); + }); + it('isDisabledButton should be true then false after calling create service', fakeAsync(() => { const managementContractForm: any = { identifier: 'contract_id', diff --git a/ui/ui-frontend/projects/referential/src/app/management-contract/management-contract-create/management-contract-create.component.ts b/ui/ui-frontend/projects/referential/src/app/management-contract/management-contract-create/management-contract-create.component.ts index 9725539c114..a946d535adc 100644 --- a/ui/ui-frontend/projects/referential/src/app/management-contract/management-contract-create/management-contract-create.component.ts +++ b/ui/ui-frontend/projects/referential/src/app/management-contract/management-contract-create/management-contract-create.component.ts @@ -43,6 +43,7 @@ import { ConfirmDialogService, Logger, ManagementContract, + MiscValidators, Option, PersistentIdentifierPolicy, PersistentIdentifierPolicyTypeEnum, @@ -98,7 +99,7 @@ export class ManagementContractCreateComponent implements OnInit, OnDestroy { ? { identifier: [ null, - [Validators.required, Validators.minLength(5), Validators.maxLength(100)], + [MiscValidators.requiredIdentifier, Validators.minLength(5), Validators.maxLength(100)], this.managementContractCreateValidators.uniqueIdentifier(), ], } @@ -106,15 +107,15 @@ export class ManagementContractCreateComponent implements OnInit, OnDestroy { status: [true], name: [ null, - [Validators.required, Validators.minLength(3), Validators.maxLength(100)], + [MiscValidators.requiredNotBlank, Validators.minLength(3), Validators.maxLength(100)], this.managementContractCreateValidators.uniqueName(), ], description: [null], // Step 2 storage: this.formBuilder.group({ - unitStrategy: ['default', Validators.required], - objectGroupStrategy: ['default', Validators.required], - objectStrategy: ['default', Validators.required], + unitStrategy: ['default', MiscValidators.requiredNotBlank], + objectGroupStrategy: ['default', MiscValidators.requiredNotBlank], + objectStrategy: ['default', MiscValidators.requiredNotBlank], }), // Step 3 persistentIdentifierPolicies: this.getDefaultPersistentIdentifierPolicies(), diff --git a/ui/ui-frontend/projects/referential/src/app/management-contract/management-contract-preview/management-contract-information-tab/management-contract-information-tab.component.spec.ts b/ui/ui-frontend/projects/referential/src/app/management-contract/management-contract-preview/management-contract-information-tab/management-contract-information-tab.component.spec.ts index 87d9c85875e..3f435400b1d 100644 --- a/ui/ui-frontend/projects/referential/src/app/management-contract/management-contract-preview/management-contract-information-tab/management-contract-information-tab.component.spec.ts +++ b/ui/ui-frontend/projects/referential/src/app/management-contract/management-contract-preview/management-contract-information-tab/management-contract-information-tab.component.spec.ts @@ -43,7 +43,15 @@ import { MatSidenavModule } from '@angular/material/sidenav'; import { RouterTestingModule } from '@angular/router/testing'; import { TranslateModule } from '@ngx-translate/core'; import { of } from 'rxjs'; -import { BASE_URL, InjectorModule, IntermediaryVersionEnum, LoggerModule, ManagementContract, WINDOW_LOCATION } from 'vitamui-library'; +import { + BASE_URL, + InjectorModule, + IntermediaryVersionEnum, + LoggerModule, + ManagementContract, + MiscValidators, + WINDOW_LOCATION, +} from 'vitamui-library'; import { InputStubComponent, VitamUICommonTestModule } from 'vitamui-library/testing'; import { ManagementContractService } from '../../management-contract.service'; import { ManagementContractInformationTabComponent } from './management-contract-information-tab.component'; @@ -272,4 +280,8 @@ describe('ManagementContractInformationTabComponent', () => { deactivationDate: jasmine.any(String), }); }); + + it('applies MiscValidators.requiredIdentifier to identifier control', () => { + expect(component.form.get('identifier').hasValidator(MiscValidators.requiredIdentifier)).toBeTruthy(); + }); }); diff --git a/ui/ui-frontend/projects/referential/src/app/management-contract/management-contract-preview/management-contract-information-tab/management-contract-information-tab.component.ts b/ui/ui-frontend/projects/referential/src/app/management-contract/management-contract-preview/management-contract-information-tab/management-contract-information-tab.component.ts index 54c5f11b7de..3de8ab8bd89 100644 --- a/ui/ui-frontend/projects/referential/src/app/management-contract/management-contract-preview/management-contract-information-tab/management-contract-information-tab.component.ts +++ b/ui/ui-frontend/projects/referential/src/app/management-contract/management-contract-preview/management-contract-information-tab/management-contract-information-tab.component.ts @@ -35,11 +35,11 @@ * knowledge of the CeCILL-C license and that you accept its terms. */ import { Component, EventEmitter, Input, Output } from '@angular/core'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { FormBuilder, FormGroup } from '@angular/forms'; import { Observable, of } from 'rxjs'; import { catchError, filter, map, switchMap } from 'rxjs/operators'; import { extend, isEmpty } from 'underscore'; -import { ManagementContract, diff } from 'vitamui-library'; +import { diff, ManagementContract, MiscValidators } from 'vitamui-library'; import { ManagementContractService } from '../../management-contract.service'; @Component({ @@ -77,8 +77,8 @@ export class ManagementContractInformationTabComponent { private managementContractService: ManagementContractService, ) { this.form = this.formBuilder.group({ - identifier: [{ value: null, disabled: true }, Validators.required], - name: [null, Validators.required], + identifier: [{ value: null, disabled: true }, MiscValidators.requiredIdentifier], + name: [null, MiscValidators.requiredNotBlank], description: [''], status: [null], }); diff --git a/ui/ui-frontend/projects/referential/src/app/management-contract/management-contract-preview/management-contract-storage-tab/management-contract-storage-tab.component.ts b/ui/ui-frontend/projects/referential/src/app/management-contract/management-contract-preview/management-contract-storage-tab/management-contract-storage-tab.component.ts index e9a92c12a91..80f8d47da65 100644 --- a/ui/ui-frontend/projects/referential/src/app/management-contract/management-contract-preview/management-contract-storage-tab/management-contract-storage-tab.component.ts +++ b/ui/ui-frontend/projects/referential/src/app/management-contract/management-contract-preview/management-contract-storage-tab/management-contract-storage-tab.component.ts @@ -35,11 +35,11 @@ * knowledge of the CeCILL-C license and that you accept its terms. */ import { Component, EventEmitter, Input, OnDestroy, Output } from '@angular/core'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { Observable, Subscription, of } from 'rxjs'; +import { FormBuilder, FormGroup } from '@angular/forms'; +import { Observable, of, Subscription } from 'rxjs'; import { catchError, filter, map, switchMap } from 'rxjs/operators'; import { extend, isEmpty } from 'underscore'; -import { ManagementContract, StorageStrategy, diff } from 'vitamui-library'; +import { diff, ManagementContract, MiscValidators, StorageStrategy } from 'vitamui-library'; import { ManagementContractService } from '../../management-contract.service'; @Component({ @@ -98,9 +98,9 @@ export class ManagementContractStorageTabComponent implements OnDestroy { private managementContractService: ManagementContractService, ) { this.form = this.formBuilder.group({ - unitStrategy: [null, Validators.required], - objectGroupStrategy: [null, Validators.required], - objectStrategy: [null, Validators.required], + unitStrategy: [null, MiscValidators.requiredNotBlank], + objectGroupStrategy: [null, MiscValidators.requiredNotBlank], + objectStrategy: [null, MiscValidators.requiredNotBlank], }); } diff --git a/ui/ui-frontend/projects/referential/src/app/ontology/ontology-create/ontology-create.component.ts b/ui/ui-frontend/projects/referential/src/app/ontology/ontology-create/ontology-create.component.ts index f6e11f8253e..7a590ae9be8 100644 --- a/ui/ui-frontend/projects/referential/src/app/ontology/ontology-create/ontology-create.component.ts +++ b/ui/ui-frontend/projects/referential/src/app/ontology/ontology-create/ontology-create.component.ts @@ -38,7 +38,13 @@ import { Component, Inject, OnDestroy, OnInit, ViewChild } from '@angular/core'; import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms'; import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog'; import { Subscription } from 'rxjs'; -import { ConfirmDialogService, setTypeDetailAndStringSize, VitamUICommonModule, VitamUILibraryModule } from 'vitamui-library'; +import { + ConfirmDialogService, + MiscValidators, + setTypeDetailAndStringSize, + VitamUICommonModule, + VitamUILibraryModule, +} from 'vitamui-library'; import { OntologyService } from '../ontology.service'; import { OntologyCreateValidators } from './ontology-create.validators'; import { collections, sizes, types } from '../ontology-form-options'; @@ -82,7 +88,7 @@ export class OntologyCreateComponent implements OnInit, OnDestroy { [Validators.required, Validators.minLength(2), Validators.maxLength(100), this.ontologyCreateValidator.patternID()], this.ontologyCreateValidator.uniqueID(), ], - shortName: [null, [Validators.required, Validators.minLength(2), Validators.maxLength(100)]], + shortName: [null, [MiscValidators.requiredNotBlank, Validators.minLength(2), Validators.maxLength(100)]], type: [null, Validators.required], typeDetail: [null], stringSize: [null], diff --git a/ui/ui-frontend/projects/referential/src/app/ontology/ontology-preview/ontology-information-tab/ontology-information-tab.component.ts b/ui/ui-frontend/projects/referential/src/app/ontology/ontology-preview/ontology-information-tab/ontology-information-tab.component.ts index 3c3c840cf82..f03a8e9018a 100644 --- a/ui/ui-frontend/projects/referential/src/app/ontology/ontology-preview/ontology-information-tab/ontology-information-tab.component.ts +++ b/ui/ui-frontend/projects/referential/src/app/ontology/ontology-preview/ontology-information-tab/ontology-information-tab.component.ts @@ -41,6 +41,7 @@ import { catchError, switchMap } from 'rxjs/operators'; import { ApplicationId, diff, + MiscValidators, Ontology, Option, Role, @@ -119,7 +120,7 @@ export class OntologyInformationTabComponent { ) { this.form = this.formBuilder.group({ identifier: [{ value: null, disabled: true }, Validators.required], - shortName: [{ value: null, disabled: true }, Validators.required], + shortName: [{ value: null, disabled: true }, MiscValidators.requiredNotBlank], type: [{ value: null, disabled: true }, Validators.required], typeDetail: [{ value: null, disabled: true }], stringSize: [{ value: null, disabled: true }], diff --git a/ui/ui-frontend/projects/referential/src/app/ontology/ontology-preview/schema-information-tab/schema-information-tab.component.ts b/ui/ui-frontend/projects/referential/src/app/ontology/ontology-preview/schema-information-tab/schema-information-tab.component.ts index d9cfa3e31b2..9b67ae00ee3 100644 --- a/ui/ui-frontend/projects/referential/src/app/ontology/ontology-preview/schema-information-tab/schema-information-tab.component.ts +++ b/ui/ui-frontend/projects/referential/src/app/ontology/ontology-preview/schema-information-tab/schema-information-tab.component.ts @@ -36,13 +36,11 @@ */ import { Component, Input } from '@angular/core'; import { FormBuilder, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'; -import { SchemaElement, SchemaService, Option } from 'vitamui-library'; +import { MiscValidators, Option, SchemaElement, SchemaService, VitamUICommonModule, VitamUILibraryModule } from 'vitamui-library'; import { sizes, types } from '../../ontology-form-options'; import { CommonModule } from '@angular/common'; import { TranslateModule } from '@ngx-translate/core'; -import { VitamUICommonModule, VitamUILibraryModule } from 'vitamui-library'; - @Component({ selector: 'app-schema-information-tab', templateUrl: './schema-information-tab.component.html', @@ -111,13 +109,13 @@ export class SchemaInformationTabComponent { public schemaService: SchemaService, ) { this.form = this.formBuilder.group({ - Path: [{ value: '', disabled: true }, [Validators.required]], - ApiPath: [{ value: '', disabled: true }, [Validators.required]], + Path: [{ value: '', disabled: true }, [MiscValidators.requiredNotBlank]], + ApiPath: [{ value: '', disabled: true }, [MiscValidators.requiredNotBlank]], ShortName: [{ value: '', disabled: true }], - FieldName: [{ value: '', disabled: true }, [Validators.required]], + FieldName: [{ value: '', disabled: true }, [MiscValidators.requiredNotBlank]], SedaField: [{ value: '', disabled: true }], ApiField: [{ value: '', disabled: true }], - Description: [{ value: '', disabled: true }, [Validators.required]], + Description: [{ value: '', disabled: true }, [MiscValidators.requiredNotBlank]], Type: [{ value: '', disabled: true }, [Validators.required]], DataType: [{ value: '', disabled: true }, [Validators.required]], Collection: [{ value: '', disabled: true }, [Validators.required]], diff --git a/ui/ui-frontend/projects/referential/src/app/rule/rule-create/rule-create.component.html b/ui/ui-frontend/projects/referential/src/app/rule/rule-create/rule-create.component.html index 2b131305809..e9cb6165be0 100644 --- a/ui/ui-frontend/projects/referential/src/app/rule/rule-create/rule-create.component.html +++ b/ui/ui-frontend/projects/referential/src/app/rule/rule-create/rule-create.component.html @@ -12,7 +12,6 @@ [placeholder]="'RULES_APP.CREATE_DIALOG.IDENTIFIER' | translate" [errorMessageMap]="{ ruleIdExists: 'RULES_APP.CREATE_DIALOG.IDENTIFIER_ALREADY_EXISTS' | translate, - ruleIdPattern: 'RULES_APP.CREATE_DIALOG.IDENTIFIER_NO_COMPLIANT' | translate, }" > diff --git a/ui/ui-frontend/projects/referential/src/app/rule/rule-create/rule-create.component.spec.ts b/ui/ui-frontend/projects/referential/src/app/rule/rule-create/rule-create.component.spec.ts index 67b3c43cc7e..3687db14710 100644 --- a/ui/ui-frontend/projects/referential/src/app/rule/rule-create/rule-create.component.spec.ts +++ b/ui/ui-frontend/projects/referential/src/app/rule/rule-create/rule-create.component.spec.ts @@ -46,7 +46,7 @@ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { MatSelectModule } from '@angular/material/select'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { EMPTY, of } from 'rxjs'; -import { ConfirmDialogService, ManagementRuleValidators, RuleService, VitamUILibraryModule } from 'vitamui-library'; +import { ConfirmDialogService, MiscValidators, RuleService, VitamUILibraryModule } from 'vitamui-library'; import { VitamUICommonTestModule } from 'vitamui-library/testing'; import { RULE_MEASUREMENTS, RULE_TYPES } from '../rules.constants'; import { RuleCreateComponent } from './rule-create.component'; @@ -95,7 +95,6 @@ describe('RuleCreateComponent', () => { }); const ruleCreateValidatorsSpy = jasmine.createSpyObj('RuleCreateValidators', { uniqueRuleId: () => of(null), - ruleIdPattern: ManagementRuleValidators.ruleIdPattern, }); await TestBed.configureTestingModule({ @@ -135,6 +134,10 @@ describe('RuleCreateComponent', () => { expect(component).toBeTruthy(); }); + it('applies MiscValidators.requiredIdentifier to ruleId control', () => { + expect(component.form.get('ruleId').hasValidator(MiscValidators.requiredIdentifier)).toBeTruthy(); + }); + describe('Template', () => { it('should have the right inputs', () => { expect(page.control('ruleId')).toBeTruthy(); @@ -172,29 +175,33 @@ describe('RuleCreateComponent', () => { describe('Validators', () => { describe('fields', () => { it('should be required', () => { - expect(setControlValue('ruleId', '').invalid).toBeTruthy('empty ruleId invalid'); - expect(setControlValue('ruleId', 'ÀÖØöøÿ ').invalid).toBeTruthy('ruleId pattern invalid'); - expect(setControlValue('ruleId', 'azerty').valid).toBeTruthy('ruleId valid'); + expect(setControlValue('ruleId', '').invalid).withContext('empty ruleId invalid').toBeTruthy(); + expect(setControlValue('ruleId', 'ÀÖØöøÿ ').invalid).withContext('ruleId pattern invalid').toBeTruthy(); + expect(setControlValue('ruleId', 'azerty').valid).withContext('ruleId valid').toBeTruthy(); - expect(setControlValue('ruleType', '').invalid).toBeTruthy('empty ruleType invalid'); - expect(setControlValue('ruleType', RULE_TYPES[0].key).valid).toBeTruthy('ruleType valid'); + expect(setControlValue('ruleType', '').invalid).withContext('empty ruleType invalid').toBeTruthy(); + expect(setControlValue('ruleType', RULE_TYPES[0].key).valid).withContext('ruleType valid').toBeTruthy(); - expect(setControlValue('ruleValue', '').invalid).toBeTruthy('empty ruleValue invalid'); - expect(setControlValue('ruleValue', '111').valid).toBeTruthy('ruleValue valid'); + expect(setControlValue('ruleValue', '').invalid).withContext('empty ruleValue invalid').toBeTruthy(); + expect(setControlValue('ruleValue', '111').valid).withContext('ruleValue valid').toBeTruthy(); - expect(setControlValue('ruleDuration', '').invalid).toBeTruthy('empty ruleDuration invalid'); - expect(setControlValue('ruleDuration', '10').valid).toBeTruthy('ruleDuration valid'); + expect(setControlValue('ruleDuration', '').invalid).withContext('empty ruleDuration invalid').toBeTruthy(); + expect(setControlValue('ruleDuration', '10').valid).withContext('ruleDuration valid').toBeTruthy(); - expect(setControlValue('ruleDescription', '').invalid).toBeTruthy('empty ruleDescription invalid'); - expect(setControlValue('ruleDescription', 'azerty').valid).toBeTruthy('ruleDescription valid'); + expect(setControlValue('ruleDescription', '').invalid).withContext('empty ruleDescription invalid').toBeTruthy(); + expect(setControlValue('ruleDescription', 'azerty').valid).withContext('ruleDescription valid').toBeTruthy(); - expect(setControlValue('ruleMeasurement', '').invalid).toBeTruthy('empty ruleMeasurement invalid'); - expect(setControlValue('ruleMeasurement', RULE_MEASUREMENTS[0].key).valid).toBeTruthy('ruleMeasurement valid'); + expect(setControlValue('ruleMeasurement', '').invalid).withContext('empty ruleMeasurement invalid').toBeTruthy(); + expect(setControlValue('ruleMeasurement', RULE_MEASUREMENTS[0].key).valid).withContext('ruleMeasurement valid').toBeTruthy(); }); it('should the requested ruleId be valid', () => { - expect(setControlValue('ruleId', '123456789').valid).toBeTruthy('ruleId valid'); - expect(setControlValue('ruleId', 'APP//??').valid).toBeTruthy('ruleId valid'); + expect(setControlValue('ruleId', '123456789').valid).withContext('ruleId valid').toBeTruthy(); + expect(setControlValue('ruleId', 'cafe . - _ 1234').valid).withContext('ruleId valid').toBeTruthy(); + }); + + it('should the requested ruleId be invalid', () => { + expect(setControlValue('ruleId', 'APP//??').valid).withContext('ruleId valid').toBeFalsy(); }); }); diff --git a/ui/ui-frontend/projects/referential/src/app/rule/rule-create/rule-create.component.ts b/ui/ui-frontend/projects/referential/src/app/rule/rule-create/rule-create.component.ts index 65c8929d8b1..f2d190d50a2 100644 --- a/ui/ui-frontend/projects/referential/src/app/rule/rule-create/rule-create.component.ts +++ b/ui/ui-frontend/projects/referential/src/app/rule/rule-create/rule-create.component.ts @@ -38,7 +38,7 @@ import { Component, Inject, OnDestroy, OnInit, ViewChild } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { Subscription } from 'rxjs'; -import { ConfirmDialogService, ManagementRuleValidators, Rule, RuleService } from 'vitamui-library'; +import { ConfirmDialogService, MiscValidators, Rule, RuleService } from 'vitamui-library'; import { RULE_MEASUREMENTS, RULE_TYPES } from '../rules.constants'; import { RuleCreateValidators } from './rule-create.validators'; import { sizes } from '../../ontology/ontology-form-options'; @@ -77,7 +77,7 @@ export class RuleCreateComponent implements OnInit, OnDestroy { this.form = this.formBuilder.group({ ruleId: [ null, - [Validators.required, Validators.minLength(2), Validators.maxLength(100), ManagementRuleValidators.ruleIdPattern], + [Validators.required, Validators.minLength(2), Validators.maxLength(100), MiscValidators.requiredIdentifier], this.ruleCreateValidator.uniqueRuleId(), ], ruleType: [null, Validators.required], diff --git a/ui/ui-frontend/projects/referential/src/app/security-profile/security-profile-create/security-profile-create.component.spec.ts b/ui/ui-frontend/projects/referential/src/app/security-profile/security-profile-create/security-profile-create.component.spec.ts index 29c9cbaa836..514e6296775 100644 --- a/ui/ui-frontend/projects/referential/src/app/security-profile/security-profile-create/security-profile-create.component.spec.ts +++ b/ui/ui-frontend/projects/referential/src/app/security-profile/security-profile-create/security-profile-create.component.spec.ts @@ -82,7 +82,7 @@ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { MatSelectModule } from '@angular/material/select'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { EMPTY, of } from 'rxjs'; -import { ConfirmDialogService } from 'vitamui-library'; +import { ConfirmDialogService, MiscValidators } from 'vitamui-library'; import { VitamUICommonTestModule } from 'vitamui-library/testing'; import { SecurityProfileService } from '../security-profile.service'; import { SecurityProfileCreateComponent } from './security-profile-create.component'; @@ -139,22 +139,22 @@ const expectedSecurityProfile = { permissions: [''], }; -let component: SecurityProfileCreateComponent; -let fixture: ComponentFixture; - class Page { + constructor(private fixture: ComponentFixture) {} get submit() { - return fixture.nativeElement.querySelector('button[type=submit]'); + return this.fixture.nativeElement.querySelector('button[type=submit]'); } control(name: string) { - return fixture.nativeElement.querySelector('[formControlName=' + name + ']'); + return this.fixture.nativeElement.querySelector('[formControlName=' + name + ']'); } } -let page: Page; - describe('SecurityProfileCreateComponent', () => { + let component: SecurityProfileCreateComponent; + let fixture: ComponentFixture; + let page: Page; + beforeEach(async () => { const matDialogRefSpy = jasmine.createSpyObj('MatDialogRef', ['close']); const customerServiceSpy = jasmine.createSpyObj('SecurityProfileService', { create: of({}) }); @@ -190,13 +190,17 @@ describe('SecurityProfileCreateComponent', () => { fixture = TestBed.createComponent(SecurityProfileCreateComponent); component = fixture.componentInstance; fixture.detectChanges(); - page = new Page(); + page = new Page(fixture); }); it('should create', () => { expect(component).toBeTruthy(); }); + it('applies MiscValidators.requiredIdentifier to identifier control', () => { + expect(component.form.get('identifier').hasValidator(MiscValidators.requiredIdentifier)).toBeTruthy(); + }); + describe('Template', () => { it('should have the right inputs', () => { expect(page.control('name')).toBeTruthy(); diff --git a/ui/ui-frontend/projects/referential/src/app/security-profile/security-profile-create/security-profile-create.component.ts b/ui/ui-frontend/projects/referential/src/app/security-profile/security-profile-create/security-profile-create.component.ts index ad2a26dfb81..8b6c0f3131c 100644 --- a/ui/ui-frontend/projects/referential/src/app/security-profile/security-profile-create/security-profile-create.component.ts +++ b/ui/ui-frontend/projects/referential/src/app/security-profile/security-profile-create/security-profile-create.component.ts @@ -38,7 +38,7 @@ import { Component, Inject, Input, OnDestroy, OnInit, ViewChild } from '@angular import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { Subscription } from 'rxjs'; -import { ConfirmDialogService } from 'vitamui-library'; +import { ConfirmDialogService, MiscValidators } from 'vitamui-library'; import { SecurityProfileService } from '../security-profile.service'; import { SecurityProfileCreateValidators } from './security-profile-create.validators'; @@ -79,7 +79,7 @@ export class SecurityProfileCreateComponent implements OnInit, OnDestroy { ], identifier: [ null, - [Validators.required, Validators.minLength(2), Validators.maxLength(100)], + [MiscValidators.requiredIdentifier, Validators.minLength(2), Validators.maxLength(100)], this.securityProfileCreateValidators.uniqueIdentifier(), ], fullAccess: [true], diff --git a/ui/ui-frontend/projects/referential/src/assets/i18n/en.json b/ui/ui-frontend/projects/referential/src/assets/i18n/en.json index 4dff1631ad6..26382403dd3 100644 --- a/ui/ui-frontend/projects/referential/src/assets/i18n/en.json +++ b/ui/ui-frontend/projects/referential/src/assets/i18n/en.json @@ -462,8 +462,7 @@ "TENANT_TOGGLE_TOOLTIP_TRUE": "A check is performed on the tenants and contracts defined in the application context when an external application connects to the service", "NAME_ALREADY_EXISTS": "Name already in use", "IDENTIFIER_ALREADY_EXISTS": "Identifier already in use", - "INCORRECT_NAME": "This name contains one or many unauthorized characters", - "INCORRECT_IDENTIFIER": "This identifier contains one or many unauthorized characters" + "INCORRECT_NAME": "This name contains one or many unauthorized characters" }, "PERMISSION": { "TITLE": "Permissions", @@ -640,8 +639,7 @@ "IDENTIFIER_TOOLTIP": "The identifier is unique per type of rule. It must not include spaces or accented characters", "TYPE_TOOLTIP": "StorageRule : Current useful life - AppraisalRule : Administrative useful life - AccessRule : Communicability delay - ReuseRule: Duration of reuse - DisseminationRule : Broadcast delay - ClassificationRule : Classification duration", "NAME_ALREADY_EXISTS": "Name already in use", - "IDENTIFIER_ALREADY_EXISTS": "The rule code entered already exists", - "IDENTIFIER_NO_COMPLIANT": "Non-compliant identifier" + "IDENTIFIER_ALREADY_EXISTS": "The rule code entered already exists" }, "TAB": { "INFORMATION": { @@ -1070,7 +1068,7 @@ "EVIDENCE_AUDIT_IDENTIFIER": "Consistency audit identifier", "CHOOSE_ATTACHMENT_POSITION": "Choose attachment position", "ENTER_INGEST_OPERATIONS_IDENTIFIERS": "Enter ingest operations identifiers", - "ENTER_INGEST_OPERATIONS_IDENTIFIERS_PLACEHOLDER": "Comma-separated ingest operations identifiers", + "ENTER_INGEST_OPERATIONS_IDENTIFIERS_PLACEHOLDER": "Ingest operations identifier(s)", "CHOOSE_ORIGINATING_AGENCY": "Choose producer services", "EVIDENCE_AUDIT_NOT_FOUND": "The consistency audit identifier entered does not exist", "CHOOSE_INGEST_OPERATIONS_PERIOD": "Choose ingest operation period", diff --git a/ui/ui-frontend/projects/referential/src/assets/i18n/fr.json b/ui/ui-frontend/projects/referential/src/assets/i18n/fr.json index 27fc5ab4ea4..a9e44265ff7 100644 --- a/ui/ui-frontend/projects/referential/src/assets/i18n/fr.json +++ b/ui/ui-frontend/projects/referential/src/assets/i18n/fr.json @@ -462,8 +462,7 @@ "TENANT_TOGGLE_TOOLTIP_TRUE": "Un contrôle est effectué sur les tenants et contrats définis dans le contexte applicatif quand une application externe se connecte au service", "NAME_ALREADY_EXISTS": "Nom déjà utilisé", "IDENTIFIER_ALREADY_EXISTS": "Identifiant déjà utilisé", - "INCORRECT_NAME": "Ce nom contient un ou des caractères non autorisés", - "INCORRECT_IDENTIFIER": "Cet identifiant contient un ou des caractères non autorisés" + "INCORRECT_NAME": "Ce nom contient un ou des caractères non autorisés" }, "PERMISSION": { "TITLE": "Permissions", @@ -640,8 +639,7 @@ "IDENTIFIER_TOOLTIP": "L'identifiant est unique par type de règle. Il ne doit pas comprendre d'espace ou de caractère accentué", "TYPE_TOOLTIP": "StorageRule : Durée d'utilité courante - AppraisalRule : Durée d'utilité administrative - AccessRule : Délai de communicabilité - ReuseRule: Durée de réutilisation - DisseminationRule : Délai de diffusion - ClassificationRule : Durée de classification", "NAME_ALREADY_EXISTS": "Nom déjà utilisé", - "IDENTIFIER_ALREADY_EXISTS": "Le code de la règle renseigné existe déjà", - "IDENTIFIER_NO_COMPLIANT": "Identifiant non conforme" + "IDENTIFIER_ALREADY_EXISTS": "Le code de la règle renseigné existe déjà" }, "TAB": { "INFORMATION": { @@ -1070,7 +1068,7 @@ "EVIDENCE_AUDIT_IDENTIFIER": "Identifiant de l'audit de cohérence", "CHOOSE_ATTACHMENT_POSITION": "Choisir une position de rattachement", "ENTER_INGEST_OPERATIONS_IDENTIFIERS": "Saisir le(s) identifiant(s) d'opération d'entrée", - "ENTER_INGEST_OPERATIONS_IDENTIFIERS_PLACEHOLDER": "Identifiant(s) d'opération d'entrée séparés par des virgules", + "ENTER_INGEST_OPERATIONS_IDENTIFIERS_PLACEHOLDER": "Identifiant(s) d'opération d'entrée", "CHOOSE_ORIGINATING_AGENCY": "Choisir le(s) service(s) producteur(s)", "EVIDENCE_AUDIT_NOT_FOUND": "L'identifiant d'audit de cohérence saisi n'existe pas", "CHOOSE_INGEST_OPERATIONS_PERIOD": "Choisir une période d'opération d'entrée", diff --git a/ui/ui-frontend/projects/vitamui-library/src/lib/components/abstract-form-input.directive.ts b/ui/ui-frontend/projects/vitamui-library/src/lib/components/abstract-form-input.directive.ts index cd55a3d7efa..30ff61278bb 100644 --- a/ui/ui-frontend/projects/vitamui-library/src/lib/components/abstract-form-input.directive.ts +++ b/ui/ui-frontend/projects/vitamui-library/src/lib/components/abstract-form-input.directive.ts @@ -142,7 +142,11 @@ export class AbstractFormInputDirective implements ControlValueAccessor, OnInit, writeValue(_obj: any) {} isRequired(): boolean { - return this.control.hasValidator(Validators.required) || this.control.hasValidator(MiscValidators.requiredNotBlank); + return ( + this.control.hasValidator(Validators.required) || + this.control.hasValidator(MiscValidators.requiredNotBlank) || + this.control.hasValidator(MiscValidators.requiredIdentifier) + ); } private updateValidators() { diff --git a/ui/ui-frontend/projects/vitamui-library/src/lib/validators/management-rule.validators.ts b/ui/ui-frontend/projects/vitamui-library/src/lib/validators/management-rule.validators.ts deleted file mode 100644 index 5b8f8d08510..00000000000 --- a/ui/ui-frontend/projects/vitamui-library/src/lib/validators/management-rule.validators.ts +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2019-2022) - * and the signatories of the "VITAM - Accord du Contributeur" agreement. - * - * contact@programmevitam.fr - * - * This software is a computer program whose purpose is to implement - * implement a digital archiving front-office system for the secure and - * efficient high volumetry VITAM solution. - * - * This software is governed by the CeCILL-C license under French law and - * abiding by the rules of distribution of free software. You can use, - * modify and/ or redistribute the software under the terms of the CeCILL-C - * license as circulated by CEA, CNRS and INRIA at the following URL - * "http://www.cecill.info". - * - * As a counterpart to the access to the source code and rights to copy, - * modify and redistribute granted by the license, users are provided only - * with a limited warranty and the software's author, the holder of the - * economic rights, and the successive licensors have only limited - * liability. - * - * In this respect, the user's attention is drawn to the risks associated - * with loading, using, modifying and/or developing or reproducing the - * software by the user in light of its specific status of free software, - * that may mean that it is complicated to manipulate, and that also - * therefore means that it is reserved for developers and experienced - * professionals having in-depth computer knowledge. Users are therefore - * encouraged to load and test the software's suitability as regards their - * requirements in conditions enabling the security of their systems and/or - * data to be ensured and, more generally, to use and operate it in the - * same conditions as regards security. - * - * The fact that you are presently reading this means that you have had - * knowledge of the CeCILL-C license and that you accept its terms. - */ -import { ValidatorFn } from '@angular/forms'; - -export interface Validators { - readonly ruleIdPattern: ValidatorFn; -} - -export const RULE_ID_PATTERN_ERROR_KEY = 'ruleIdPattern'; - -export const ManagementRuleValidators: Validators = { - ruleIdPattern: (control) => (/[À-ÖØ-öø-ÿ ]/.test(control.value) ? { [RULE_ID_PATTERN_ERROR_KEY]: true } : null), -}; diff --git a/ui/ui-frontend/projects/vitamui-library/src/lib/validators/misc.validators.spec.ts b/ui/ui-frontend/projects/vitamui-library/src/lib/validators/misc.validators.spec.ts index 2a66043a841..425d3100460 100644 --- a/ui/ui-frontend/projects/vitamui-library/src/lib/validators/misc.validators.spec.ts +++ b/ui/ui-frontend/projects/vitamui-library/src/lib/validators/misc.validators.spec.ts @@ -35,7 +35,7 @@ * knowledge of the CeCILL-C license and that you accept its terms. */ import { TestBed } from '@angular/core/testing'; -import { FormBuilder, ReactiveFormsModule } from '@angular/forms'; +import { FormBuilder, ReactiveFormsModule, ValidatorFn } from '@angular/forms'; import { MiscValidators } from './misc.validators'; describe('MiscValidators', () => { @@ -50,24 +50,64 @@ describe('MiscValidators', () => { }); describe('requiredNotBlank', () => { - const expectValid = (str: string) => () => { + const expectValid = expectValidBuilder(MiscValidators.requiredNotBlank); + const expectInvalid = expectInvalidBuilder(MiscValidators.requiredNotBlank); + + it('should allow non blank field without spaces', expectValid('azerty')); + it('should allow non blank field with spaces', expectValid(' azer ty ')); + it('should not allow null fields', expectInvalid(null)); + it('should not allow empty fields', expectInvalid('')); + it('should not allow blank fields', expectInvalid(' ')); + + it('should allow non blank fields without spaces', expectValid(['aaa', 'bbb'])); + it('should allow non blank fields with spaces', expectValid(['a a a', ' b b b '])); + it('should not allow only an empty field', expectInvalid([''])); + it('should not allow an empty list', expectInvalid([])); + it('should not allow an empty field in the list', expectInvalid(['aaa', ''])); + it('should not allow only a blank field', expectInvalid([' '])); + it('should not allow a blank field in the list', expectInvalid(['aaa', ' '])); + }); + + describe('requiredIdentifier', () => { + const expectValid = expectValidBuilder(MiscValidators.requiredIdentifier); + const expectInvalid = expectInvalidBuilder(MiscValidators.requiredIdentifier); + + it('should allow non special characters', expectValid('AzErTy042')); + it('should allow spaces', expectValid(' AzEr Ty 042 ')); + it('should allow ".", "-", "=", "@", "_", "/", "+"', expectValid('A.z-E=r@T_y/0+42')); // FIXME: maybe we should prevent "/" and "+" + + it('should not allow null fields', expectInvalid(null)); + it('should not allow empty fields', expectInvalid('')); + it('should not allow accents', expectInvalid('café')); + it( + 'should not allow other special chars', + expectInvalid('test!') && + expectInvalid('test$') && + expectInvalid('test*') && + expectInvalid('test?') && + expectInvalid('test;') && + expectInvalid('test:') && + expectInvalid('test#'), + ); + }); + + function expectValidBuilder(validatorFn: ValidatorFn) { + return (value: string | string[]) => () => { const formGroup = formBuilder.group({ - field: [str, MiscValidators.requiredNotBlank], + field: [value, validatorFn], }); - expect(formGroup.valid).withContext('Form group must be valid').toBeTruthy(); + expect(formGroup.valid).withContext(`Value "${value}" should be considered valid`).toBeTruthy(); expect(formGroup.get('field').errors).withContext('Field control must not have errors').toBeNull(); }; - const expectInvalid = (str: string | null) => () => { + } + + function expectInvalidBuilder(validatorFn: ValidatorFn) { + return (value: string | string[] | null) => () => { const formGroup = formBuilder.group({ - field: [str, MiscValidators.requiredNotBlank], + field: [value, validatorFn], }); - expect(formGroup.invalid).withContext('Form group must be invalid').toBeTruthy(); + expect(formGroup.invalid).withContext(`Value "${value}" should be considered invalid`).toBeTruthy(); expect(formGroup.get('field').errors).withContext('Field control must have errors').toBeTruthy(); }; - it('should allow non blank field without spaces', expectValid('azerty')); - it('should allow non blank field with spaces', expectValid(' azer ty ')); - it('should not allow null fields', expectInvalid(null)); - it('should not allow empty fields', expectInvalid('')); - it('should not allow blank fields', expectInvalid(' ')); - }); + } }); diff --git a/ui/ui-frontend/projects/vitamui-library/src/lib/validators/misc.validators.ts b/ui/ui-frontend/projects/vitamui-library/src/lib/validators/misc.validators.ts index 212adbc2aba..b33554a7c49 100644 --- a/ui/ui-frontend/projects/vitamui-library/src/lib/validators/misc.validators.ts +++ b/ui/ui-frontend/projects/vitamui-library/src/lib/validators/misc.validators.ts @@ -38,10 +38,16 @@ import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms'; export interface MiscValidators { readonly requiredNotBlank: ValidatorFn; - readonly allowedIdentifier: ValidatorFn; + readonly requiredIdentifier: ValidatorFn; } export const MiscValidators: MiscValidators = { - requiredNotBlank: (control) => (control.value == null || control.value.trim().length === 0 ? { requiredNotBlank: true } : null), - allowedIdentifier: (control: AbstractControl): ValidationErrors => - !control.value || control.value.match('^[a-zA-Z0-9+=@_-]*$') ? null : { incorrectIdentifier: true }, + requiredNotBlank: (control: AbstractControl) => + control.value == null || + (control.value instanceof Array && !control.value.length) || + (control.value instanceof Array ? control.value : [control.value]).some((v) => v.trim().length === 0) + ? { requiredNotBlank: true } + : null, + // Based on HTTPParameterValue ESAPI Validator in Vitam Core + requiredIdentifier: (control: AbstractControl): ValidationErrors => + control.value ? (control.value.match('^[a-zA-Z0-9.\\-\\/+=@_ ]*$') ? null : { incorrectIdentifier: true }) : { required: true }, // FIXME: maybe we should prevent "/" and "+" }; diff --git a/ui/ui-frontend/projects/vitamui-library/src/public-api.ts b/ui/ui-frontend/projects/vitamui-library/src/public-api.ts index dfb0b8220cd..c5d283f3b03 100644 --- a/ui/ui-frontend/projects/vitamui-library/src/public-api.ts +++ b/ui/ui-frontend/projects/vitamui-library/src/public-api.ts @@ -101,7 +101,6 @@ export * from './lib/utils/string.util'; export * from './lib/vitamui-library.module'; export * from './lib/vitamui-library.service'; -export * from './lib/validators/management-rule.validators'; export * from './lib/validators/misc.validators'; /* Previous ui-frontend-common */