diff --git a/projects/nae-example-app/src/app/app.module.ts b/projects/nae-example-app/src/app/app.module.ts index fe43a6c27..23b8001b4 100644 --- a/projects/nae-example-app/src/app/app.module.ts +++ b/projects/nae-example-app/src/app/app.module.ts @@ -19,7 +19,9 @@ import { ViewService, ProfileModule, Dashboard, - FrontActionModule, NAE_ASYNC_RENDERING_CONFIGURATION + FrontActionModule, + NAE_ASYNC_RENDERING_CONFIGURATION, + ValidationRegistryService } from '@netgrif/components-core'; import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; import {FlexLayoutModule, FlexModule} from '@angular/flex-layout'; @@ -267,7 +269,8 @@ export function HttpLoaderFactory(http: HttpClient) { }) export class AppModule { - constructor(registry: ComponentRegistryService) { + constructor(registry: ComponentRegistryService, + validationRegistry: ValidationRegistryService) { registry.register('email', (injector: Injector) => new ComponentPortal(EmailSubmissionFormComponent, null, injector)); registry.register('workflow-view', (injector: Injector) => new ComponentPortal(WorkflowViewExampleComponent, null, injector)); registry.register('task-view', (injector: Injector) => new ComponentPortal(TaskViewComponent, null, injector)); diff --git a/projects/netgrif-components-core/src/assets/i18n/de.json b/projects/netgrif-components-core/src/assets/i18n/de.json index 8f3e2530d..34e6e95f1 100644 --- a/projects/netgrif-components-core/src/assets/i18n/de.json +++ b/projects/netgrif-components-core/src/assets/i18n/de.json @@ -218,6 +218,7 @@ }, "dataField": { "validations": { + "general": "Der Wert dieses Feldes ist ungültig!", "required": "Dieses Feld ist ein Pflichtfeld!", "requiredTrue": "Der eingegebene Wert muss wahr sein", "odd": "Die eingegebene Nummer muss ungerade sein", @@ -225,15 +226,15 @@ "positive": "Die eingegebene Nummer muss positiv sein", "negative": "Die eingegebene Nummer muss negativ sein", "decimal": "Die eingegebene Nummer muss ein Dezimalzahl sein", - "inrange": "Die eingegebene Nummer muss aus dem gegebenen Nummernbereich {{range}} sein", + "inrange": "Die eingegebene Nummer muss aus dem gegebenen Nummernbereich {{from}},{{to}} sein", "minLength": "Der eingegebene Text muss länger als {{length}} Zeichen sein", "maxLength": "Der eingegebene Text muss kurzer als {{length}} Zeichen sein", "pattern": "Der eingegebene Text ist nicht im richtigen Format", "phone": "Der eingegebene Text muss ein Telefonnummer sein", "email": "Der eingegebene Text muss ein E-Mail sein", - "dateRange": "Das eingegebene Datum muss zwischen {{left}} und {{right}} liegen", - "datePast": "Das eingegebene Datum muss bis {{right}} sein", - "dateFuture": "Das eingegebene Datum muss ab {{left}} sein", + "dateRange": "Das eingegebene Datum muss zwischen {{from}} und {{to}} liegen", + "datePast": "Das eingegebene Datum muss bis {{from}} sein", + "dateFuture": "Das eingegebene Datum muss ab {{to}} sein", "weekend": "Das eingegebene Datum muss das Wochenende sein", "workday": "Das eingegebene Datum muss ein Wochentag sein", "enumeration": "Eine von der angebotenen Optionen muss ausgewählt sein", diff --git a/projects/netgrif-components-core/src/assets/i18n/en.json b/projects/netgrif-components-core/src/assets/i18n/en.json index d0814f3cf..d6a73dd51 100644 --- a/projects/netgrif-components-core/src/assets/i18n/en.json +++ b/projects/netgrif-components-core/src/assets/i18n/en.json @@ -218,6 +218,7 @@ }, "dataField": { "validations": { + "general": "This value in this field is invalid!", "required": "This field is required!", "requiredTrue": "Entered value must be true", "odd": "Entered number must be odd", @@ -225,21 +226,21 @@ "positive": "Entered number must be positive", "negative": "Entered number must be negative", "decimal": "Entered number must be decimal", - "inrange": "Entered number must be in range {{range}}", + "inrange": "Entered number must be in range {{from}},{{to}}", "minLength": "Entered text must be at least {{length}} characters long", "maxLength": "Entered text must be at most {{length}} characters long", "pattern": "Entered text is in a wrong format", "phone": "Entered text must be in telephone number format", "email": "Entered text must be in email format", - "dateRange": "Entered date must be between {{left}} and {{right}}", - "datePast": "Entered date must be earlier than {{right}}", - "dateFuture": "Entered date must be later than {{left}}", + "dateRange": "Entered date must be between {{from}} and {{to}}", + "datePast": "Entered date must be earlier than {{to}}", + "dateFuture": "Entered date must be later than {{from}}", "weekend": "Entered date must be weekend day", "workday": "Entered date must be week day", "enumeration": "One of the options must be selected", "min": "Entered number must be greater than {{length}}", - "translationRequired": "Translation for languages: <{{translation}}> must be entered", - "translationOnly": "Only translation for languages: <{{translation}}> is allowed", + "translationRequired": "Translation for languages: <{{languages}}> must be entered", + "translationOnly": "Only translation for languages: <{{languages}}> is allowed", "requiredI18n": "At least one value must be entered", "requiredUserList": "At least one value must be entered" }, diff --git a/projects/netgrif-components-core/src/assets/i18n/sk.json b/projects/netgrif-components-core/src/assets/i18n/sk.json index 6cc671b42..2c83a4675 100644 --- a/projects/netgrif-components-core/src/assets/i18n/sk.json +++ b/projects/netgrif-components-core/src/assets/i18n/sk.json @@ -218,6 +218,7 @@ }, "dataField": { "validations": { + "general": "Hodnota tohto poľa je neplatná!", "required": "Toto pole je potrebné!", "requiredTrue": "Zadaná hodnota musí byť true", "odd": "Zadané číslo musí byť nepárne", @@ -225,15 +226,15 @@ "positive": "Zadané číslo musí byť kladné", "negative": "Zadané číslo musí byť záporné", "decimal": "Zadané číslo musí byť decimálne", - "inrange": "Zadané číslo musí byť v rozsahu {{range}}", + "inrange": "Zadané číslo musí byť v rozsahu {{from}},{{to}}", "minLength": "Zadaný text musí mať aspoň {{length}} znakov", "maxLength": "Zadaný text môže mať maximálne {{length}} znakov", "pattern": "Zadaný text je v nesprávnom formáte", "phone": "Zadaný text musí byť tel. číslo", "email": "Zadaný text musí byť email", - "dateRange": "Zadaný dátum musí byť v rozsahu {{left}} a {{right}}", - "datePast": "Zadaný dátum musí byť pred {{right}}", - "dateFuture": "Zadaný dátum musí byť po {{left}}", + "dateRange": "Zadaný dátum musí byť v rozsahu {{from}} a {{to}}", + "datePast": "Zadaný dátum musí byť pred {{to}}", + "dateFuture": "Zadaný dátum musí byť po {{from}", "weekend": "Zadaný dátum musí byť víkendový deň", "workday": "Zadaný dátum musí byť pracovný deň", "enumeration": "Musí byť vybraná jedna z možností", diff --git a/projects/netgrif-components-core/src/lib/data-fields/base-component/abstract-base-data-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/base-component/abstract-base-data-field.component.ts index da8699a95..66a97b017 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/base-component/abstract-base-data-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/base-component/abstract-base-data-field.component.ts @@ -3,6 +3,9 @@ import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../models/data-field- import {DataField} from "../models/abstract-data-field"; import {FormControl} from "@angular/forms"; import {WrappedBoolean} from "../data-field-template/models/wrapped-boolean"; +import {ValidationRegistryService} from "../../registry/validation-registry.service"; +import {TranslateService} from "@ngx-translate/core"; +import {FieldConverterService} from "../../task-content/services/field-converter.service"; @Component({ selector: 'ncc-base-data-field', @@ -14,7 +17,9 @@ export abstract class AbstractBaseDataFieldComponent) { + constructor(protected _translate?: TranslateService, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData?: DataFieldPortalData, + protected _validationRegistry?: ValidationRegistryService) { if (!!dataFieldPortalData) { this.dataField = dataFieldPortalData.dataField; this.formControlRef = dataFieldPortalData.formControlRef; @@ -25,11 +30,18 @@ export abstract class AbstractBaseDataFieldComponent v.name === validator.key); + const args = []; + const messageParams = {}; + validator.attributeNames.forEach(atr => { + const attributeValue = validation.arguments[atr].value; + messageParams[atr] = attributeValue; + args.push(attributeValue) + }) + return this.resolveErrorMessage(validator.key, this.translate.instant(validator.defaultErrorMessage(...args), messageParams)); + } + } + } + return ''; + } + + private resolveErrorMessage(search: string, generalMessage: string) { + if (!!this.dataField.validations) { + const validation = this.dataField.validations.find(value => value.name === search); + if (validation.validationMessage && validation.validationMessage !== '') { + return validation.validationMessage; + } + } + return generalMessage; + } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/boolean-field/abstract-boolean-field.component.spec.ts b/projects/netgrif-components-core/src/lib/data-fields/boolean-field/abstract-boolean-field.component.spec.ts index 4e37d2d11..8dbdcc2be 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/boolean-field/abstract-boolean-field.component.spec.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/boolean-field/abstract-boolean-field.component.spec.ts @@ -16,6 +16,9 @@ import {MaterialModule} from '../../material/material.module'; import {AbstractBooleanFieldComponent} from './abstract-boolean-field.component'; import {BooleanField} from './models/boolean-field'; import {NAE_INFORM_ABOUT_INVALID_DATA} from '../models/invalid-data-policy-token'; +import {Validator} from "../../registry/model/validator"; +import {requiredTrueValidation} from "../models/validation-functions"; +import {DataFieldsModule} from "../data-fields.module"; describe('AbstractBooleanFieldComponent', () => { let component: TestBooleanComponent; @@ -28,7 +31,8 @@ describe('AbstractBooleanFieldComponent', () => { AngularResizeEventModule, TranslateLibModule, HttpClientTestingModule, - NoopAnimationsModule + NoopAnimationsModule, + DataFieldsModule ], providers: [ {provide: AuthenticationMethodService, useClass: MockAuthenticationMethodService}, @@ -77,5 +81,8 @@ class TestWrapperComponent { }, undefined, undefined, undefined, - [{validationRule: 'requiredTrue', validationMessage: 'this is custom message'}]); + [{name: 'requiredTrue', validationMessage: 'this is custom message'}], + undefined, + undefined, + new Map([['requiredTrue', requiredTrueValidation]])); } diff --git a/projects/netgrif-components-core/src/lib/data-fields/boolean-field/boolean-default-field/abstract-boolean-default-field.component.spec.ts b/projects/netgrif-components-core/src/lib/data-fields/boolean-field/boolean-default-field/abstract-boolean-default-field.component.spec.ts index 772910a96..80fdc9a46 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/boolean-field/boolean-default-field/abstract-boolean-default-field.component.spec.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/boolean-field/boolean-default-field/abstract-boolean-default-field.component.spec.ts @@ -19,6 +19,10 @@ import {AbstractBooleanDefaultFieldComponent} from "./abstract-boolean-default-f import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-field-portal-data-injection-token"; import {FormControl} from "@angular/forms"; import {WrappedBoolean} from "../../data-field-template/models/wrapped-boolean"; +import {ValidationRegistryService} from "../../../registry/validation-registry.service"; +import {requiredTrueValidation} from "../../models/validation-functions"; +import {Validator} from "../../../registry/model/validator"; +import {DataFieldsModule} from "../../data-fields.module"; describe('AbstractBooleanDefaultFieldComponent', () => { let component: TestBooleanComponent; @@ -31,7 +35,8 @@ describe('AbstractBooleanDefaultFieldComponent', () => { AngularResizeEventModule, TranslateLibModule, HttpClientTestingModule, - NoopAnimationsModule + NoopAnimationsModule, + DataFieldsModule ], providers: [ {provide: AuthenticationMethodService, useClass: MockAuthenticationMethodService}, @@ -44,7 +49,10 @@ describe('AbstractBooleanDefaultFieldComponent', () => { }, undefined, undefined, undefined, - [{validationRule: 'requiredTrue', validationMessage: 'this is custom message'}]), + [{name: 'requiredTrue', validationMessage: 'this is custom message'}], + undefined, + undefined, + new Map([['requiredTrue', requiredTrueValidation]])), formControlRef: new FormControl(), showLargeLayout: new WrappedBoolean() } as DataFieldPortalData @@ -82,8 +90,9 @@ describe('AbstractBooleanDefaultFieldComponent', () => { class TestBooleanComponent extends AbstractBooleanDefaultFieldComponent { constructor(translate: TranslateService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(translate, dataFieldPortalData); + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(translate, dataFieldPortalData, _validationRegistry); } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/boolean-field/boolean-default-field/abstract-boolean-default-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/boolean-field/boolean-default-field/abstract-boolean-default-field.component.ts index dd77d3fac..bb715b695 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/boolean-field/boolean-default-field/abstract-boolean-default-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/boolean-field/boolean-default-field/abstract-boolean-default-field.component.ts @@ -1,8 +1,9 @@ import {Component, Inject, Optional} from "@angular/core"; -import {BooleanField, BooleanFieldValidation} from "../models/boolean-field"; +import {BooleanField} from "../models/boolean-field"; import {TranslateService} from "@ngx-translate/core"; import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-field-portal-data-injection-token"; import {AbstractBaseDataFieldComponent} from "../../base-component/abstract-base-data-field.component"; +import {ValidationRegistryService} from "../../../registry/validation-registry.service"; @Component({ selector: 'ncc-abstract-boolean-default-field', @@ -10,30 +11,13 @@ import {AbstractBaseDataFieldComponent} from "../../base-component/abstract-base }) export abstract class AbstractBooleanDefaultFieldComponent extends AbstractBaseDataFieldComponent { - constructor(protected _translate: TranslateService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(dataFieldPortalData); - } - - public getErrorMessage() { - if (this.formControlRef.hasError(BooleanFieldValidation.REQUIRED)) { - return this._translate.instant('dataField.validations.required'); - } else if (this.formControlRef.hasError(BooleanFieldValidation.REQUIRED_TRUE)) { - return this.resolveErrorMessage(this.dataField, BooleanFieldValidation.REQUIRED_TRUE, - this._translate.instant('dataField.validations.requiredTrue')); - } - return ''; + constructor(_translate: TranslateService, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(_translate, dataFieldPortalData, _validationRegistry); } public createValueLabel(): string { - return this._translate.instant('dataField.values.boolean.' + this.dataField.value); - } - - private resolveErrorMessage(dataField: BooleanField, search: string, generalMessage: string) { - const validation = dataField.validations.find(value => value.validationRule.includes(search)); - if (validation.validationMessage && validation.validationMessage !== '') { - return validation.validationMessage; - } - return generalMessage; + return this.translate.instant('dataField.values.boolean.' + this.dataField.value); } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/boolean-field/models/boolean-field.ts b/projects/netgrif-components-core/src/lib/data-fields/boolean-field/models/boolean-field.ts index 9fd97f364..45a4fa44a 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/boolean-field/models/boolean-field.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/boolean-field/models/boolean-field.ts @@ -1,9 +1,9 @@ import {Behavior} from '../../models/behavior'; -import {AbstractControl, ValidationErrors, ValidatorFn} from '@angular/forms'; import {Layout} from '../../models/layout'; import {Validation} from '../../models/validation'; import {Component, ComponentPrefixes} from '../../models/component'; import {DataField} from '../../models/abstract-data-field'; +import {Validator} from "../../../registry/model/validator"; import {UpdateOnStrategy, UpdateStrategy} from "../../models/update-strategy"; export enum BooleanFieldValidation { @@ -14,8 +14,10 @@ export enum BooleanFieldValidation { export class BooleanField extends DataField { constructor(stringId: string, title: string, value: boolean, behavior: Behavior, placeholder?: string, - description?: string, layout?: Layout, validations?: Array, component?: Component, parentTaskId?: string) { - super(stringId, title, value, behavior, placeholder, description, layout, validations, component, parentTaskId); + description?: string, layout?: Layout, validations?: Array, component?: Component, parentTaskId?: string, + validatorRegister?: Map) { + super(stringId, title, value, behavior, placeholder, description, layout, validations, component, parentTaskId, + undefined, validatorRegister); } public getTypedComponentType(): string { @@ -25,20 +27,4 @@ export class BooleanField extends DataField { public getUpdateOnStrategy(): UpdateOnStrategy { return UpdateStrategy.CHANGE; } - - protected resolveValidations(): Array { - const result = []; - - this.validations.forEach(item => { - if (item.validationRule.includes(BooleanFieldValidation.REQUIRED_TRUE)) { - result.push(this.requiredTrue); - } - }); - - return result; - } - - private requiredTrue(control: AbstractControl): ValidationErrors | null { - return control.value === true ? null : {requiredTrue: true}; - } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/button-field/button-default-field/abstract-button-default-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/button-field/button-default-field/abstract-button-default-field.component.ts index bc2668b39..e01dfffb6 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/button-field/button-default-field/abstract-button-default-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/button-field/button-default-field/abstract-button-default-field.component.ts @@ -13,15 +13,15 @@ import {AbstractBaseDataFieldComponent} from "../../base-component/abstract-base }) export abstract class AbstractButtonDefaultFieldComponent extends AbstractBaseDataFieldComponent { - constructor(protected _translate: TranslateService, + constructor(_translate: TranslateService, protected _dialogService: DialogService, @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(dataFieldPortalData); + super(_translate, dataFieldPortalData); } public getErrorMessage() { if (this.formControlRef.hasError(ButtonFieldValidation.REQUIRED)) { - return this._translate.instant('dataField.validations.required'); + return this.translate.instant('dataField.validations.required'); } } @@ -39,8 +39,8 @@ export abstract class AbstractButtonDefaultFieldComponent extends AbstractBaseDa public resolveValue(): void { if (!!this.dataField.component?.properties?.dialogText && this.dataField.component?.properties?.dialogTitle) { const dialogRef = this._dialogService.openConfirmDialog(this.dataField.component.properties.dialogTitle, - this.dataField.component.properties.dialogText, this._translate.instant('dialog.close'), - this._translate.instant('dialog.submit')); + this.dataField.component.properties.dialogText, this.translate.instant('dialog.close'), + this.translate.instant('dialog.submit')); dialogRef.afterClosed().pipe(take(1)).subscribe(result => { if (result?.confirmed) { this.formControlRef.setValue(this.formControlRef.value + 1); diff --git a/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/case-ref-default/case-ref-default.component.ts b/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/case-ref-default/case-ref-default.component.ts index fc032a847..842437395 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/case-ref-default/case-ref-default.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/case-ref-default/case-ref-default.component.ts @@ -3,6 +3,8 @@ import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-fie import {CaseRefField} from '../model/case-ref-field'; import {Subscription} from 'rxjs'; import {AbstractCaseRefBaseFieldComponent} from '../model/abstract-case-ref-base-field-component'; +import {TranslateService} from "@ngx-translate/core"; +import {ValidationRegistryService} from "../../../registry/validation-registry.service"; @Component({ selector: 'ncc-abstract-case-ref-default', @@ -15,8 +17,10 @@ export abstract class AbstractCaseRefDefaultComponent extends AbstractCaseRefBas protected constructor(protected injector: Injector, protected caseViewType: Type, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(injector, caseViewType, dataFieldPortalData); + _translate: TranslateService, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistryService: ValidationRegistryService) { + super(injector, caseViewType, dataFieldPortalData, _validationRegistryService); } ngAfterViewInit(): void { diff --git a/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/model/abstract-case-ref-base-field-component.ts b/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/model/abstract-case-ref-base-field-component.ts index 0ccb01a1e..f02175029 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/model/abstract-case-ref-base-field-component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/model/abstract-case-ref-base-field-component.ts @@ -12,6 +12,7 @@ import {BaseFilter} from '../../../search/models/base-filter'; import {NAE_VIEW_ID_SEGMENT} from '../../../user/models/view-id-injection-tokens'; import {ViewIdService} from '../../../user/services/view-id.service'; import {DataField} from '../../models/abstract-data-field'; +import {ValidationRegistryService} from "../../../registry/validation-registry.service"; export abstract class AbstractCaseRefBaseFieldComponent> extends AbstractBaseDataFieldComponent { @@ -19,8 +20,9 @@ export abstract class AbstractCaseRefBaseFieldComponent, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(dataFieldPortalData); + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService,) { + super(null, dataFieldPortalData); } createFilter(filterValue: string | string[]) { diff --git a/projects/netgrif-components-core/src/lib/data-fields/data-fields.module.ts b/projects/netgrif-components-core/src/lib/data-fields/data-fields.module.ts index 7e7e9a769..81524951c 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/data-fields.module.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/data-fields.module.ts @@ -11,6 +11,17 @@ import {NgxMatDatetimePickerModule} from '@angular-material-components/datetime- import {NgxMatMomentModule} from '@angular-material-components/moment-adapter'; import {TranslateLibModule} from '../translate/translate-lib.module'; import {DateAdapter} from '@angular/material/core'; +import {ValidationRegistryService} from "../registry/validation-registry.service"; +import { + betweenValidation, + decimalValidation, + emailValidation, evenValidation, inRangeValidation, + maxLengthValidation, + minLengthValidation, negativeValidation, oddValidation, positiveValidation, + regexValidation, requiredTrueValidation, requiredValidation, + telNumberValidation, translationOnlyValidation, translationRequiredValidation, weekendValidation, workdayValidation +} from "./models/validation-functions"; +import {FieldTypeResource} from "../task-content/model/field-type-resource"; @NgModule({ imports: [ @@ -30,5 +41,35 @@ import {DateAdapter} from '@angular/material/core'; ] }) export class DataFieldsModule { + constructor(validationRegistry: ValidationRegistryService) { + validationRegistry.register(FieldTypeResource.TEXT, 'required', requiredValidation) + validationRegistry.register(FieldTypeResource.TEXT, 'minLength', minLengthValidation) + validationRegistry.register(FieldTypeResource.TEXT, 'maxLength', maxLengthValidation) + validationRegistry.register(FieldTypeResource.TEXT, 'regex', regexValidation) + validationRegistry.register(FieldTypeResource.TEXT, 'telNumber', telNumberValidation) + validationRegistry.register(FieldTypeResource.TEXT, 'email', emailValidation) + validationRegistry.register(FieldTypeResource.NUMBER, 'required', requiredValidation) + validationRegistry.register(FieldTypeResource.NUMBER, 'odd', oddValidation) + validationRegistry.register(FieldTypeResource.NUMBER, 'even', evenValidation) + validationRegistry.register(FieldTypeResource.NUMBER, 'positive', positiveValidation) + validationRegistry.register(FieldTypeResource.NUMBER, 'negative', negativeValidation) + validationRegistry.register(FieldTypeResource.NUMBER, 'decimal', decimalValidation) + validationRegistry.register(FieldTypeResource.NUMBER, 'inrange', inRangeValidation) + + validationRegistry.register(FieldTypeResource.BOOLEAN, 'requiredTrue', requiredTrueValidation) + + validationRegistry.register(FieldTypeResource.DATE, 'required', requiredValidation) + validationRegistry.register(FieldTypeResource.DATE, 'between', betweenValidation) + validationRegistry.register(FieldTypeResource.DATE, 'workday', workdayValidation) + validationRegistry.register(FieldTypeResource.DATE, 'weekend', weekendValidation) + validationRegistry.register(FieldTypeResource.DATE_TIME, 'required', requiredValidation) + validationRegistry.register(FieldTypeResource.DATE_TIME, 'between', betweenValidation) + validationRegistry.register(FieldTypeResource.DATE_TIME, 'workday', workdayValidation) + validationRegistry.register(FieldTypeResource.DATE_TIME, 'weekend', weekendValidation) + + validationRegistry.register(FieldTypeResource.I18N, 'required', requiredValidation) + validationRegistry.register(FieldTypeResource.I18N, 'translationRequired', translationRequiredValidation) + validationRegistry.register(FieldTypeResource.I18N, 'translationOnly', translationOnlyValidation) + } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/date-field/abstract-date-field.component.spec.ts b/projects/netgrif-components-core/src/lib/data-fields/date-field/abstract-date-field.component.spec.ts index fa4693976..ef4be07ab 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/date-field/abstract-date-field.component.spec.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/date-field/abstract-date-field.component.spec.ts @@ -17,6 +17,9 @@ import {MockAuthenticationMethodService} from '../../utility/tests/mocks/mock-au import {TranslateLibModule} from '../../translate/translate-lib.module'; import {MaterialModule} from '../../material/material.module'; import {NAE_INFORM_ABOUT_INVALID_DATA} from '../models/invalid-data-policy-token'; +import {Validator} from "../../registry/model/validator"; +import {weekendValidation, workdayValidation} from "../models/validation-functions"; +import {DataFieldsModule} from "../data-fields.module"; import {DateAdapter} from '@angular/material/core'; import {CustomDateAdapter} from './models/custom-date-adapter'; @@ -30,7 +33,9 @@ describe('AbstractDateFieldComponent', () => { MaterialModule, AngularResizeEventModule, TranslateLibModule, - HttpClientTestingModule, NoopAnimationsModule + HttpClientTestingModule, + NoopAnimationsModule, + DataFieldsModule ], providers: [ {provide: AuthenticationMethodService, useClass: MockAuthenticationMethodService}, @@ -82,7 +87,13 @@ class TestWrapperComponent { editable: true, hidden: true }, undefined, undefined, undefined, [ - {validationRule: 'weekend', validationMessage: 'This is custom message!'}, - {validationRule: 'workday', validationMessage: 'This is custom message!'} - ]); + {name: 'weekend', validationMessage: 'This is custom message!'}, + {name: 'workday', validationMessage: 'This is custom message!'} + ], + undefined, + undefined, + new Map([ + ['weekend', weekendValidation], + ['workday', workdayValidation] + ])); } diff --git a/projects/netgrif-components-core/src/lib/data-fields/date-field/date-default-field/abstract-date-default-field.component.spec.ts b/projects/netgrif-components-core/src/lib/data-fields/date-field/date-default-field/abstract-date-default-field.component.spec.ts index ea7031565..a8e0cb6a2 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/date-field/date-default-field/abstract-date-default-field.component.spec.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/date-field/date-default-field/abstract-date-default-field.component.spec.ts @@ -20,10 +20,13 @@ import {AbstractDateDefaultFieldComponent} from "./abstract-date-default-field.c import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-field-portal-data-injection-token"; import {FormControl} from "@angular/forms"; import {WrappedBoolean} from "../../data-field-template/models/wrapped-boolean"; +import {ValidationRegistryService} from "../../../registry/validation-registry.service"; +import {Validator} from "../../../registry/model/validator"; +import {weekendValidation, workdayValidation} from "../../models/validation-functions"; +import {DataFieldsModule} from "../../data-fields.module"; import {DateAdapter, MAT_DATE_LOCALE} from "@angular/material/core"; import {LanguageService} from "../../../translate/language.service"; import {CustomDateAdapter} from "../models/custom-date-adapter"; -import {NgxMatDateAdapter} from "@angular-material-components/datetime-picker"; describe('AbstractDateDefaultFieldComponent', () => { let component: TestDateFieldComponent; @@ -35,7 +38,9 @@ describe('AbstractDateDefaultFieldComponent', () => { MaterialModule, AngularResizeEventModule, TranslateLibModule, - HttpClientTestingModule, NoopAnimationsModule + HttpClientTestingModule, + NoopAnimationsModule, + DataFieldsModule ], providers: [ {provide: AuthenticationMethodService, useClass: MockAuthenticationMethodService}, @@ -50,9 +55,16 @@ describe('AbstractDateDefaultFieldComponent', () => { editable: true, hidden: true }, undefined, undefined, undefined, [ - {validationRule: 'weekend', validationMessage: 'This is custom message!'}, - {validationRule: 'workday', validationMessage: 'This is custom message!'} - ]), + {name: 'weekend', validationMessage: 'This is custom message!'}, + {name: 'workday', validationMessage: 'This is custom message!'} + ], + undefined, + undefined, + new Map([ + ['weekend', weekendValidation], + ['workday', workdayValidation] + ]) + ), formControlRef: new FormControl(), showLargeLayout: new WrappedBoolean() } as DataFieldPortalData @@ -93,8 +105,9 @@ class TestDateFieldComponent extends AbstractDateDefaultFieldComponent { _adapter: DateAdapter, @Inject(MAT_DATE_LOCALE) _locale: string, _languageService: LanguageService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(_translate, _adapter, _locale, _languageService, dataFieldPortalData); + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(_translate, _adapter, _locale, _languageService, dataFieldPortalData, _validationRegistry); } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/date-field/date-default-field/abstract-date-default-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/date-field/date-default-field/abstract-date-default-field.component.ts index d98161505..e6517fbeb 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/date-field/date-default-field/abstract-date-default-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/date-field/date-default-field/abstract-date-default-field.component.ts @@ -5,6 +5,7 @@ import {DateField} from "../models/date-field"; import { AbstractTimeInstanceFieldComponent } from "../../time-instance-abstract-field/abstract-time-instance-field.component"; +import {ValidationRegistryService} from "../../../registry/validation-registry.service"; import {DateAdapter, MAT_DATE_LOCALE} from "@angular/material/core"; import {LanguageService} from "../../../translate/language.service"; @@ -14,15 +15,12 @@ import {LanguageService} from "../../../translate/language.service"; }) export abstract class AbstractDateDefaultFieldComponent extends AbstractTimeInstanceFieldComponent { - constructor(protected _translate: TranslateService, - protected _adapter: DateAdapter, - @Inject(MAT_DATE_LOCALE) protected _locale: string, - protected _languageService: LanguageService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(_translate, _adapter, _locale, _languageService, dataFieldPortalData) - } - - getErrorMessage() { - return this.buildErrorMessage(this.dataField); + constructor(_translate: TranslateService, + _adapter: DateAdapter, + @Inject(MAT_DATE_LOCALE) _locale: string, + _languageService: LanguageService, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(_translate, _adapter, _locale, _languageService, dataFieldPortalData, _validationRegistry) } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/date-field/models/date-field.ts b/projects/netgrif-components-core/src/lib/data-fields/date-field/models/date-field.ts index a382dcf78..d45c1c24a 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/date-field/models/date-field.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/date-field/models/date-field.ts @@ -4,12 +4,14 @@ import {AbstractTimeInstanceField} from '../../time-instance-abstract-field/mode import {Layout} from '../../models/layout'; import {Validation} from '../../models/validation'; import {Component, ComponentPrefixes} from '../../models/component'; +import {Validator} from "../../../registry/model/validator"; export class DateField extends AbstractTimeInstanceField { constructor(stringId: string, title: string, value: Moment, behavior: Behavior, placeholder?: string, - description?: string, layout?: Layout, validations?: Array, component?: Component, parentTaskId?: string) { - super(stringId, title, value, behavior, placeholder, description, layout, validations, component, parentTaskId); + description?: string, layout?: Layout, validations?: Array, component?: Component, parentTaskId?: string, + validatorRegister?: Map) { + super(stringId, title, value, behavior, placeholder, description, layout, validations, component, parentTaskId, validatorRegister); } public getTypedComponentType(): string { diff --git a/projects/netgrif-components-core/src/lib/data-fields/date-time-field/abstract-date-time-field.component.spec.ts b/projects/netgrif-components-core/src/lib/data-fields/date-time-field/abstract-date-time-field.component.spec.ts index 7904f3b60..ee7da5af5 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/date-time-field/abstract-date-time-field.component.spec.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/date-time-field/abstract-date-time-field.component.spec.ts @@ -20,6 +20,9 @@ import {MockUserResourceService} from '../../utility/tests/mocks/mock-user-resou import {TestConfigurationService} from '../../utility/tests/test-config'; import {ConfigurationService} from '../../configuration/configuration.service'; import {NAE_INFORM_ABOUT_INVALID_DATA} from '../models/invalid-data-policy-token'; +import {Validator} from "../../registry/model/validator"; +import {weekendValidation} from "../models/validation-functions"; +import {DataFieldsModule} from "../data-fields.module"; import {DateAdapter} from '@angular/material/core'; import {NgxMatMomentModule} from '@angular-material-components/moment-adapter'; import {CustomDateAdapter} from '../date-field/models/custom-date-adapter'; @@ -38,6 +41,7 @@ describe('AbstractDatetimeFieldComponent', () => { TranslateLibModule, HttpClientTestingModule, NoopAnimationsModule, + DataFieldsModule ], providers: [ {provide: AuthenticationMethodService, useClass: MockAuthenticationMethodService}, @@ -88,9 +92,14 @@ class TestWrapperComponent { editable: true, hidden: true }, undefined, undefined, undefined, [ - {validationRule: 'between today,future', validationMessage: 'This is custom message!'}, - {validationRule: 'between past,today', validationMessage: 'This is custom message!'}, - {validationRule: 'between 2020-03-03,today', validationMessage: 'This is custom message!'}, - ]); + {name: 'between', validationMessage: 'This is custom message!', arguments: {'from': {key: 'from', value: 'today', dynamic: false}, 'to': {key: 'to', value: 'future', dynamic: false}}}, + {name: 'between', validationMessage: 'This is custom message!', arguments: {'from': {key: 'from', value: 'past', dynamic: false}, 'to': {key: 'to', value: 'today', dynamic: false}}}, + {name: 'between', validationMessage: 'This is custom message!', arguments: {'from': {key: 'from', value: '2020-03-03', dynamic: false}, 'to': {key: 'to', value: 'today', dynamic: false}}} + ], + undefined, + undefined, + new Map([ + ['between', weekendValidation] + ])); changedFields = new BehaviorSubject({behavior: {editable: true}, taskId: 'testTaskId'}); } diff --git a/projects/netgrif-components-core/src/lib/data-fields/date-time-field/date-time-default-field/abstract-date-time-default-field.component.spec.ts b/projects/netgrif-components-core/src/lib/data-fields/date-time-field/date-time-default-field/abstract-date-time-default-field.component.spec.ts index dcb4d47c5..c21d6a655 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/date-time-field/date-time-default-field/abstract-date-time-default-field.component.spec.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/date-time-field/date-time-default-field/abstract-date-time-default-field.component.spec.ts @@ -21,6 +21,10 @@ import {AbstractDateTimeDefaultFieldComponent} from "./abstract-date-time-defaul import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-field-portal-data-injection-token"; import {FormControl} from "@angular/forms"; import {WrappedBoolean} from "../../data-field-template/models/wrapped-boolean"; +import {Validator} from "../../../registry/model/validator"; +import {betweenValidation} from "../../models/validation-functions"; +import {ValidationRegistryService} from "../../../registry/validation-registry.service"; +import {DataFieldsModule} from "../../data-fields.module"; import {DateAdapter, MAT_DATE_LOCALE} from "@angular/material/core"; import {CustomDateAdapter} from "../../date-field/models/custom-date-adapter"; import {LanguageService} from "../../../translate/language.service"; @@ -39,7 +43,8 @@ describe('AbstractDatetimeDefaultFieldComponent', () => { TranslateLibModule, NgxMatMomentModule, HttpClientTestingModule, - NoopAnimationsModule + NoopAnimationsModule, + DataFieldsModule ], providers: [ {provide: AuthenticationMethodService, useClass: MockAuthenticationMethodService}, @@ -54,10 +59,15 @@ describe('AbstractDatetimeDefaultFieldComponent', () => { editable: true, hidden: true }, undefined, undefined, undefined, [ - {validationRule: 'between today,future', validationMessage: 'This is custom message!'}, - {validationRule: 'between past,today', validationMessage: 'This is custom message!'}, - {validationRule: 'between 2020-03-03,today', validationMessage: 'This is custom message!'}, - ]), + {name: 'between', validationMessage: 'This is custom message!', arguments: {'from': {key: 'from', value: 'today', dynamic: false}, 'to': {key: 'to', value: 'future', dynamic: false}}}, + {name: 'between', validationMessage: 'This is custom message!', arguments: {'from': {key: 'from', value: 'past', dynamic: false}, 'to': {key: 'to', value: 'today', dynamic: false}}}, + {name: 'between', validationMessage: 'This is custom message!', arguments: {'from': {key: 'from', value: '2020-03-03', dynamic: false}, 'to': {key: 'to', value: 'today', dynamic: false}}} + ], + undefined, + undefined, + new Map([ + ['between', betweenValidation] + ])), formControlRef: new FormControl(), showLargeLayout: new WrappedBoolean() } as DataFieldPortalData @@ -97,8 +107,9 @@ class TestDateTimeFieldComponent extends AbstractDateTimeDefaultFieldComponent { _adapter: NgxMatDateAdapter, @Inject(MAT_DATE_LOCALE) _locale: string, _languageService: LanguageService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(_translate, _adapter, _locale, _languageService, dataFieldPortalData) + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(_translate, _adapter, _locale, _languageService, dataFieldPortalData, _validationRegistry) } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/date-time-field/date-time-default-field/abstract-date-time-default-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/date-time-field/date-time-default-field/abstract-date-time-default-field.component.ts index 0c6517d1c..a6263a364 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/date-time-field/date-time-default-field/abstract-date-time-default-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/date-time-field/date-time-default-field/abstract-date-time-default-field.component.ts @@ -8,6 +8,7 @@ import {DateTimeField} from "../models/date-time-field"; import {NgxMatDateAdapter} from "@angular-material-components/datetime-picker"; import {MAT_DATE_LOCALE} from "@angular/material/core"; import {LanguageService} from "../../../translate/language.service"; +import {ValidationRegistryService} from "../../../registry/validation-registry.service"; @Component({ selector: 'ncc-abstract-date-time-default-field', @@ -15,15 +16,12 @@ import {LanguageService} from "../../../translate/language.service"; }) export abstract class AbstractDateTimeDefaultFieldComponent extends AbstractTimeInstanceFieldComponent { - constructor(protected _translate: TranslateService, - protected _adapter: NgxMatDateAdapter, - @Inject(MAT_DATE_LOCALE) protected _locale: string, - protected _languageService: LanguageService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(_translate, _adapter, _locale, _languageService, dataFieldPortalData) - } - - getErrorMessage() { - return this.buildErrorMessage(this.dataField); + constructor(_translate: TranslateService, + _adapter: NgxMatDateAdapter, + @Inject(MAT_DATE_LOCALE) _locale: string, + _languageService: LanguageService, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(_translate, _adapter, _locale, _languageService, dataFieldPortalData, _validationRegistry); } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/date-time-field/models/date-time-field.ts b/projects/netgrif-components-core/src/lib/data-fields/date-time-field/models/date-time-field.ts index b13fab0be..b341001ba 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/date-time-field/models/date-time-field.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/date-time-field/models/date-time-field.ts @@ -3,13 +3,15 @@ import {Moment} from 'moment'; import {AbstractTimeInstanceField} from '../../time-instance-abstract-field/models/abstract-time-instance-field'; import {Layout} from '../../models/layout'; import {Validation} from '../../models/validation'; +import {Validator} from "../../../registry/model/validator"; import {Component, ComponentPrefixes} from '../../models/component'; export class DateTimeField extends AbstractTimeInstanceField { constructor(stringId: string, title: string, value: Moment, behavior: Behavior, placeholder?: string, - description?: string, layout?: Layout, validations?: Array, component?: Component, parentTaskId?: string) { - super(stringId, title, value, behavior, placeholder, description, layout, validations, component, parentTaskId); + description?: string, layout?: Layout, validations?: Array, component?: Component, parentTaskId?: string, + validatorRegister?: Map) { + super(stringId, title, value, behavior, placeholder, description, layout, validations, component, parentTaskId, validatorRegister); } public getTypedComponentType(): string { diff --git a/projects/netgrif-components-core/src/lib/data-fields/enumeration-field/enumeration-autocomplete-dynamic-field/abstract-enumeration-autocomplete-dynamic-field.component.spec.ts b/projects/netgrif-components-core/src/lib/data-fields/enumeration-field/enumeration-autocomplete-dynamic-field/abstract-enumeration-autocomplete-dynamic-field.component.spec.ts index f8bb75890..a35b1ee25 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/enumeration-field/enumeration-autocomplete-dynamic-field/abstract-enumeration-autocomplete-dynamic-field.component.spec.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/enumeration-field/enumeration-autocomplete-dynamic-field/abstract-enumeration-autocomplete-dynamic-field.component.spec.ts @@ -62,7 +62,7 @@ describe('AbstractEnumerationAutocompleteDynamicFieldComponent', () => { template: '' }) class TestEnumAutoComponent extends AbstractEnumerationAutocompleteDynamicFieldComponent { - constructor(protected _translate: TranslateService, + constructor(_translate: TranslateService, @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { super(_translate, dataFieldPortalData); } diff --git a/projects/netgrif-components-core/src/lib/data-fields/enumeration-field/enumeration-autocomplete-dynamic-field/abstract-enumeration-autocomplete-dynamic-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/enumeration-field/enumeration-autocomplete-dynamic-field/abstract-enumeration-autocomplete-dynamic-field.component.ts index 691606bbb..4f5e874ab 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/enumeration-field/enumeration-autocomplete-dynamic-field/abstract-enumeration-autocomplete-dynamic-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/enumeration-field/enumeration-autocomplete-dynamic-field/abstract-enumeration-autocomplete-dynamic-field.component.ts @@ -26,9 +26,9 @@ export abstract class AbstractEnumerationAutocompleteDynamicFieldComponent exten filteredOptions: Observable>; choiceSubscription: Subscription; - constructor(protected _translate: TranslateService, + constructor(_translate: TranslateService, @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(dataFieldPortalData); + super(_translate, dataFieldPortalData); } ngOnInit() { @@ -68,7 +68,7 @@ export abstract class AbstractEnumerationAutocompleteDynamicFieldComponent exten public buildErrorMessage() { if (this.formControlRef.hasError(EnumerationFieldValidation.REQUIRED)) { - return this._translate.instant('dataField.validations.required'); + return this.translate.instant('dataField.validations.required'); } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/enumeration-field/enumeration-autocomplete-select-field/abstract-enumeration-autocomplete-select-field.component.spec.ts b/projects/netgrif-components-core/src/lib/data-fields/enumeration-field/enumeration-autocomplete-select-field/abstract-enumeration-autocomplete-select-field.component.spec.ts index 805afb6e7..856ea7355 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/enumeration-field/enumeration-autocomplete-select-field/abstract-enumeration-autocomplete-select-field.component.spec.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/enumeration-field/enumeration-autocomplete-select-field/abstract-enumeration-autocomplete-select-field.component.spec.ts @@ -63,7 +63,7 @@ describe('AbstractEnumerationAutocompleteSelectFieldComponent', () => { template: '' }) class TestEnumAutoComponent extends AbstractEnumerationAutocompleteSelectFieldComponent { - constructor(protected _translate: TranslateService, + constructor(_translate: TranslateService, @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { super(_translate, dataFieldPortalData); } diff --git a/projects/netgrif-components-core/src/lib/data-fields/enumeration-field/enumeration-autocomplete-select-field/abstract-enumeration-autocomplete-select-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/enumeration-field/enumeration-autocomplete-select-field/abstract-enumeration-autocomplete-select-field.component.ts index 39587e6e1..6f63577c5 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/enumeration-field/enumeration-autocomplete-select-field/abstract-enumeration-autocomplete-select-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/enumeration-field/enumeration-autocomplete-select-field/abstract-enumeration-autocomplete-select-field.component.ts @@ -16,9 +16,9 @@ export abstract class AbstractEnumerationAutocompleteSelectFieldComponent extend @ViewChild('input') text: ElementRef; filteredOptions: Observable>; - constructor(protected _translate: TranslateService, + constructor(_translate: TranslateService, @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(dataFieldPortalData); + super(_translate, dataFieldPortalData); } ngOnInit() { @@ -89,10 +89,10 @@ export abstract class AbstractEnumerationAutocompleteSelectFieldComponent extend public buildErrorMessage() { if (this.formControlRef.hasError(EnumerationFieldValidation.REQUIRED)) { - return this._translate.instant('dataField.validations.required'); + return this.translate.instant('dataField.validations.required'); } if (this.formControlRef.hasError(EnumerationFieldValidation.WRONG_VALUE)) { - return this._translate.instant('dataField.validations.enumeration'); + return this.translate.instant('dataField.validations.enumeration'); } } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/enumeration-field/enumeration-caseref-field/abstract-enumeration-caseref-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/enumeration-field/enumeration-caseref-field/abstract-enumeration-caseref-field.component.ts index 0b4ac0925..d63823ed8 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/enumeration-field/enumeration-caseref-field/abstract-enumeration-caseref-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/enumeration-field/enumeration-caseref-field/abstract-enumeration-caseref-field.component.ts @@ -2,6 +2,8 @@ import {AfterViewInit, Component, Inject, Injector, OnDestroy, Optional, Type} f import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-field-portal-data-injection-token"; import {EnumerationField} from '../models/enumeration-field'; import {Subscription} from 'rxjs'; +import {TranslateService} from "@ngx-translate/core"; +import {ValidationRegistryService} from "../../../registry/validation-registry.service"; import {AbstractCaseRefBaseFieldComponent} from '../../case-ref-field/model/abstract-case-ref-base-field-component'; @Component({ @@ -15,8 +17,10 @@ export abstract class AbstractEnumerationCaseRefComponent extends AbstractCaseRe protected constructor(protected injector: Injector, protected caseViewType: Type, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(injector, caseViewType, dataFieldPortalData); + _translate: TranslateService, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistryService: ValidationRegistryService) { + super(injector, caseViewType, dataFieldPortalData, _validationRegistryService); } ngAfterViewInit(): void { diff --git a/projects/netgrif-components-core/src/lib/data-fields/enumeration-field/enumeration-icon-field/abstract-enumeration-icon-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/enumeration-field/enumeration-icon-field/abstract-enumeration-icon-field.component.ts index a1564ce01..72045e22c 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/enumeration-field/enumeration-icon-field/abstract-enumeration-icon-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/enumeration-field/enumeration-icon-field/abstract-enumeration-icon-field.component.ts @@ -15,7 +15,7 @@ export abstract class AbstractEnumerationIconFieldComponent extends AbstractBase protected subComp: Subscription; constructor(@Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(dataFieldPortalData); + super(undefined, dataFieldPortalData); } ngOnInit(): void { diff --git a/projects/netgrif-components-core/src/lib/data-fields/enumeration-field/enumeration-list-field/abstract-enumeration-list-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/enumeration-field/enumeration-list-field/abstract-enumeration-list-field.component.ts index 178e461ce..9b7831f20 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/enumeration-field/enumeration-list-field/abstract-enumeration-list-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/enumeration-field/enumeration-list-field/abstract-enumeration-list-field.component.ts @@ -10,7 +10,7 @@ import {AbstractBaseDataFieldComponent} from "../../base-component/abstract-base export abstract class AbstractEnumerationListFieldComponent extends AbstractBaseDataFieldComponent{ constructor(@Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(dataFieldPortalData); + super(undefined, dataFieldPortalData); } resetEnum(): void { diff --git a/projects/netgrif-components-core/src/lib/data-fields/enumeration-field/enumeration-select-field/abstract-enumeration-select-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/enumeration-field/enumeration-select-field/abstract-enumeration-select-field.component.ts index 75c8ee7dc..68be646ee 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/enumeration-field/enumeration-select-field/abstract-enumeration-select-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/enumeration-field/enumeration-select-field/abstract-enumeration-select-field.component.ts @@ -10,7 +10,7 @@ import {AbstractBaseDataFieldComponent} from "../../base-component/abstract-base export abstract class AbstractEnumerationSelectFieldComponent extends AbstractBaseDataFieldComponent{ constructor(@Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(dataFieldPortalData); + super(undefined, dataFieldPortalData); } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/enumeration-field/enumeration-stepper-field/abstract-enumeration-stepper-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/enumeration-field/enumeration-stepper-field/abstract-enumeration-stepper-field.component.ts index a08d6ee67..d1cba441c 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/enumeration-field/enumeration-stepper-field/abstract-enumeration-stepper-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/enumeration-field/enumeration-stepper-field/abstract-enumeration-stepper-field.component.ts @@ -25,7 +25,7 @@ export abstract class AbstractEnumerationStepperFieldComponent extends AbstractB constructor(protected ref: ElementRef, @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(dataFieldPortalData); + super(undefined, dataFieldPortalData); this.arrowStepper = false; } diff --git a/projects/netgrif-components-core/src/lib/data-fields/file-field/file-default-field/abstract-file-default-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/file-field/file-default-field/abstract-file-default-field.component.ts index 690a84ab7..27800033f 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/file-field/file-default-field/abstract-file-default-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/file-field/file-default-field/abstract-file-default-field.component.ts @@ -111,7 +111,7 @@ export abstract class AbstractFileDefaultFieldComponent extends AbstractFileFiel protected constructor(protected _taskResourceService: TaskResourceService, protected _log: LoggerService, protected _snackbar: SnackBarService, - protected _translate: TranslateService, + _translate: TranslateService, protected _eventService: EventService, protected _sanitizer: DomSanitizer, @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { @@ -196,7 +196,7 @@ export abstract class AbstractFileDefaultFieldComponent extends AbstractFileFiel if (this.dataField.value?.name && this.fileUploadEl.nativeElement.files.item(0).name === this.dataField.value?.name) { this._log.error('User chose the same file. Uploading skipped'); - this._snackbar.openErrorSnackBar(this._translate.instant('dataField.snackBar.wontUploadSameFile')); + this._snackbar.openErrorSnackBar(this.translate.instant('dataField.snackBar.wontUploadSameFile')); this.fileUploadEl.nativeElement.value = ''; return; } @@ -231,9 +231,9 @@ export abstract class AbstractFileDefaultFieldComponent extends AbstractFileFiel `File [${this.dataField.stringId}] ${this.fileUploadEl.nativeElement.files.item(0)} uploading has failed!`, response.error ); if (response.error) { - this._snackbar.openErrorSnackBar(this._translate.instant(response.error)); + this._snackbar.openErrorSnackBar(this.translate.instant(response.error)); } else { - this._snackbar.openErrorSnackBar(this._translate.instant('dataField.snackBar.fileUploadFailed')); + this._snackbar.openErrorSnackBar(this.translate.instant('dataField.snackBar.fileUploadFailed')); } } else { const changedFieldsMap: ChangedFieldsMap = this._eventService.parseChangedFieldsFromOutcomeTree(response.outcome); @@ -264,9 +264,9 @@ export abstract class AbstractFileDefaultFieldComponent extends AbstractFileFiel `File [${this.dataField.stringId}] ${this.fileUploadEl.nativeElement.files.item(0)} uploading has failed!`, error ); if (error?.error?.message) { - this._snackbar.openErrorSnackBar(this._translate.instant(error.error.message)); + this._snackbar.openErrorSnackBar(this.translate.instant(error.error.message)); } else { - this._snackbar.openErrorSnackBar(this._translate.instant('dataField.snackBar.fileUploadFailed')); + this._snackbar.openErrorSnackBar(this.translate.instant('dataField.snackBar.fileUploadFailed')); } this.dataField.touch = true; this.dataField.update(); @@ -300,7 +300,7 @@ export abstract class AbstractFileDefaultFieldComponent extends AbstractFileFiel }, error => { this._log.error(`Downloading file [${this.dataField.stringId}] ${this.dataField.value.name} has failed!`, error); this._snackbar.openErrorSnackBar( - this.dataField.value.name + ' ' + this._translate.instant('dataField.snackBar.downloadFail') + this.dataField.value.name + ' ' + this.translate.instant('dataField.snackBar.downloadFail') ); this.state.downloading = false; this.state.progress = 0; @@ -359,7 +359,7 @@ export abstract class AbstractFileDefaultFieldComponent extends AbstractFileFiel } else { this._log.error(`Deleting file [${this.dataField.stringId}] ${this.dataField.value.name} has failed!`, response.error); this._snackbar.openErrorSnackBar( - this.dataField.value.name + ' ' + this._translate.instant('dataField.snackBar.fileDeleteFailed') + this.dataField.value.name + ' ' + this.translate.instant('dataField.snackBar.fileDeleteFailed') ); } }); @@ -397,7 +397,7 @@ export abstract class AbstractFileDefaultFieldComponent extends AbstractFileFiel return this.dataField.placeholder; } } - return this._translate.instant('dataField.file.noFile'); + return this.translate.instant('dataField.file.noFile'); } /** @@ -421,7 +421,7 @@ export abstract class AbstractFileDefaultFieldComponent extends AbstractFileFiel }, error => { this._log.error(`Downloading file [${this.dataField.stringId}] ${this.dataField.value.name} has failed!`, error); this._snackbar.openErrorSnackBar( - this.dataField.value.name + ' ' + this._translate.instant('dataField.snackBar.downloadFail') + this.dataField.value.name + ' ' + this.translate.instant('dataField.snackBar.downloadFail') ); this.state.downloading = false; this.state.progress = 0; @@ -452,7 +452,7 @@ export abstract class AbstractFileDefaultFieldComponent extends AbstractFileFiel }, error => { this._log.error(`Downloading file [${this.dataField.stringId}] ${this.dataField.value.name} has failed!`, error); this._snackbar.openErrorSnackBar( - this.dataField.value.name + ' ' + this._translate.instant('dataField.snackBar.downloadFail') + this.dataField.value.name + ' ' + this.translate.instant('dataField.snackBar.downloadFail') ); this.state.progress = 0; }); diff --git a/projects/netgrif-components-core/src/lib/data-fields/file-list-field/file-list-default-field/abstract-file-list-default-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/file-list-field/file-list-default-field/abstract-file-list-default-field.component.ts index 9fb99c8ee..55ea719bd 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/file-list-field/file-list-default-field/abstract-file-list-default-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/file-list-field/file-list-default-field/abstract-file-list-default-field.component.ts @@ -58,7 +58,7 @@ export abstract class AbstractFileListDefaultFieldComponent extends AbstractFile protected constructor(protected _taskResourceService: TaskResourceService, protected _log: LoggerService, protected _snackbar: SnackBarService, - protected _translate: TranslateService, + _translate: TranslateService, protected _eventService: EventService, @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { super(_log, _snackbar, _translate, dataFieldPortalData); @@ -126,7 +126,7 @@ export abstract class AbstractFileListDefaultFieldComponent extends AbstractFile } if (this.fileUploadEl.nativeElement.files.length + this.uploadedFiles.length > this.maxFilesNumber) { this._snackbar.openErrorSnackBar(this.maxFilesMessage ? this.maxFilesMessage : - this._translate.instant('dataField.snackBar.maxFilesExceeded') + this.maxFilesNumber + this.translate.instant('dataField.snackBar.maxFilesExceeded') + this.maxFilesNumber ); this.fileUploadEl.nativeElement.value = ''; return; @@ -149,7 +149,7 @@ export abstract class AbstractFileListDefaultFieldComponent extends AbstractFile }); if (filesToUpload.length === 0) { this._log.error('User chose the same files that are already uploaded. Uploading skipped'); - this._snackbar.openErrorSnackBar(this._translate.instant('dataField.snackBar.wontUploadSameFiles')); + this._snackbar.openErrorSnackBar(this.translate.instant('dataField.snackBar.wontUploadSameFiles')); this.fileUploadEl.nativeElement.value = ''; return; } @@ -187,9 +187,9 @@ export abstract class AbstractFileListDefaultFieldComponent extends AbstractFile `File [${this.dataField.stringId}] ${this.fileUploadEl.nativeElement.files.item(0)} uploading has failed!`, response.error ); if (response.error) { - this._snackbar.openErrorSnackBar(this._translate.instant(response.error)); + this._snackbar.openErrorSnackBar(this.translate.instant(response.error)); } else { - this._snackbar.openErrorSnackBar(this._translate.instant('dataField.snackBar.fileUploadFailed')); + this._snackbar.openErrorSnackBar(this.translate.instant('dataField.snackBar.fileUploadFailed')); } } else { const changedFieldsMap: ChangedFieldsMap = this._eventService.parseChangedFieldsFromOutcomeTree(response.outcome); @@ -213,9 +213,9 @@ export abstract class AbstractFileListDefaultFieldComponent extends AbstractFile this.state.uploading = false; this.state.progress = 0; if (error?.error?.message) { - this._snackbar.openErrorSnackBar(this._translate.instant(error.error.message)); + this._snackbar.openErrorSnackBar(this.translate.instant(error.error.message)); } else { - this._snackbar.openErrorSnackBar(this._translate.instant('dataField.snackBar.fileUploadFailed')); + this._snackbar.openErrorSnackBar(this.translate.instant('dataField.snackBar.fileUploadFailed')); } this._log.error( `File [${this.dataField.stringId}] ${this.fileUploadEl.nativeElement.files.item(0)} uploading has failed!`, error @@ -252,7 +252,7 @@ export abstract class AbstractFileListDefaultFieldComponent extends AbstractFile } }, error => { this._log.error(`Downloading file [${this.dataField.stringId}] ${fileName} has failed!`, error); - this._snackbar.openErrorSnackBar(fileName + ' ' + this._translate.instant('dataField.snackBar.downloadFail')); + this._snackbar.openErrorSnackBar(fileName + ' ' + this.translate.instant('dataField.snackBar.downloadFail')); this.state.downloading = false; this.state.progress = 0; }); @@ -303,7 +303,7 @@ export abstract class AbstractFileListDefaultFieldComponent extends AbstractFile } else { this._log.error(`Deleting file [${this.dataField.stringId}] ${fileName} has failed!`, response.error); this._snackbar.openErrorSnackBar( - fileName + ' ' + this._translate.instant('dataField.snackBar.fileDeleteFailed') + fileName + ' ' + this.translate.instant('dataField.snackBar.fileDeleteFailed') ); } }); @@ -326,7 +326,7 @@ export abstract class AbstractFileListDefaultFieldComponent extends AbstractFile if (!!this.dataField && !!this.dataField.placeholder) { return this.dataField.placeholder; } - return this._translate.instant('dataField.file.noFile'); + return this.translate.instant('dataField.file.noFile'); } protected parseResponse(): void { diff --git a/projects/netgrif-components-core/src/lib/data-fields/filter-field/filter-default-field/abstract-filter-default-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/filter-field/filter-default-field/abstract-filter-default-field.component.ts index d53abf75e..6f85895c0 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/filter-field/filter-default-field/abstract-filter-default-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/filter-field/filter-default-field/abstract-filter-default-field.component.ts @@ -17,7 +17,7 @@ export abstract class AbstractFilterDefaultFieldComponent extends AbstractBaseDa constructor(protected _parentInjector: Injector, @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(dataFieldPortalData); + super(undefined, dataFieldPortalData); } ngOnInit() { diff --git a/projects/netgrif-components-core/src/lib/data-fields/i18n-field/abstract-i18n-errors.component.ts b/projects/netgrif-components-core/src/lib/data-fields/i18n-field/abstract-i18n-errors.component.ts index 85a8780b5..3d4b4ea50 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/i18n-field/abstract-i18n-errors.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/i18n-field/abstract-i18n-errors.component.ts @@ -4,6 +4,7 @@ import {Component, Inject, Optional} from '@angular/core'; import {LanguageIconsService} from './language-icons.service'; import {AbstractBaseDataFieldComponent} from "../base-component/abstract-base-data-field.component"; import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../models/data-field-portal-data-injection-token"; +import {ValidationRegistryService} from "../../registry/validation-registry.service"; @Component({ @@ -14,58 +15,9 @@ export abstract class AbstractI18nErrorsComponent extends AbstractBaseDataFieldC protected constructor(protected languageIconsService: LanguageIconsService, - protected _translate: TranslateService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(dataFieldPortalData); - } - - getErrorMessage() { - if (this.formControlRef.hasError(I18nFieldValidation.REQUIRED_I18N)) { - return this._translate.instant('dataField.validations.requiredI18n'); - } - if (this.formControlRef.hasError(I18nFieldValidation.TRANSLATION_REQUIRED)) { - const tmp = this.dataField.validations.find(value => - value.validationRule.includes(I18nFieldValidation.TRANSLATION_REQUIRED) - ).validationRule.split(' '); - const missingLanguages = tmp[1] - .replace(' ', '') - .split(',') - .filter(lanCode => !Object.keys(this.formControlRef.value.translations).includes(lanCode)) - .map(lanCode => this.languageIconsService.languageIcons[lanCode].languageName) - .join(', '); - return this.resolveErrorMessage( - I18nFieldValidation.TRANSLATION_REQUIRED, - this._translate.instant( - 'dataField.validations.translationRequired', - {translation: missingLanguages} - ) - ); - } - if (this.formControlRef.hasError(I18nFieldValidation.TRANSLATION_ONLY)) { - const tmp = this.dataField.validations.find(value => - value.validationRule.includes(I18nFieldValidation.TRANSLATION_ONLY) - ).validationRule.split(' '); - const onlyLanguages = tmp[1] - .replace(' ', '') - .split(',') - .map(lanCode => this.languageIconsService.languageIcons[lanCode].languageName) - .join(', '); - return this.resolveErrorMessage( - I18nFieldValidation.TRANSLATION_ONLY, - this._translate.instant( - 'dataField.validations.translationOnly', - {translation: onlyLanguages} - ) - ); - } - return ''; - } - - protected resolveErrorMessage(search: string, generalMessage: string) { - const validation = this.dataField.validations.find(value => value.validationRule.includes(search)); - if (validation.validationMessage && validation.validationMessage !== '') { - return validation.validationMessage; - } - return generalMessage; + _translate: TranslateService, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(_translate, dataFieldPortalData, _validationRegistry); } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/i18n-field/i18n-divider-field/abstract-i18n-divider-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/i18n-field/i18n-divider-field/abstract-i18n-divider-field.component.ts index da83500af..4944d1169 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/i18n-field/i18n-divider-field/abstract-i18n-divider-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/i18n-field/i18n-divider-field/abstract-i18n-divider-field.component.ts @@ -11,7 +11,7 @@ export abstract class AbstractI18nDividerFieldComponent extends AbstractBaseData constructor(@Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(dataFieldPortalData); + super(undefined, dataFieldPortalData); } public getDividerColor(): string { diff --git a/projects/netgrif-components-core/src/lib/data-fields/i18n-field/i18n-text-field/abstract-i18n-text-field.component.spec.ts b/projects/netgrif-components-core/src/lib/data-fields/i18n-field/i18n-text-field/abstract-i18n-text-field.component.spec.ts index d5f0c6eae..cfee7ccb4 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/i18n-field/i18n-text-field/abstract-i18n-text-field.component.spec.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/i18n-field/i18n-text-field/abstract-i18n-text-field.component.spec.ts @@ -22,6 +22,8 @@ import {LanguageIconsService} from '../language-icons.service'; import {DomSanitizer} from '@angular/platform-browser'; import {LanguageService} from '../../../translate/language.service'; import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-field-portal-data-injection-token"; +import {ValidationRegistryService} from "../../../registry/validation-registry.service"; +import {DataFieldsModule} from "../../data-fields.module"; describe('AbstractI18nTextFieldComponent', () => { let component: TestI18nTextComponent; @@ -36,7 +38,8 @@ describe('AbstractI18nTextFieldComponent', () => { BrowserAnimationsModule, TranslateLibModule, HttpClientTestingModule, - NoopAnimationsModule + NoopAnimationsModule, + DataFieldsModule ], providers: [ {provide: AuthenticationMethodService, useClass: MockAuthenticationMethodService}, @@ -86,8 +89,9 @@ class TestI18nTextComponent extends AbstractI18nTextFieldComponent { constructor(protected languageIconsService: LanguageIconsService, protected _translateService: TranslateService, protected _domSanitizer: DomSanitizer, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(languageIconsService, _translateService, _domSanitizer, dataFieldPortalData); + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(languageIconsService, _translateService, _domSanitizer, dataFieldPortalData, _validationRegistry); } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/i18n-field/i18n-text-field/abstract-i18n-text-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/i18n-field/i18n-text-field/abstract-i18n-text-field.component.ts index a2fae7ad4..1036f6f07 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/i18n-field/i18n-text-field/abstract-i18n-text-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/i18n-field/i18n-text-field/abstract-i18n-text-field.component.ts @@ -8,6 +8,7 @@ import {AbstractI18nErrorsComponent} from '../abstract-i18n-errors.component'; import {LanguageIcons} from '../models/language-icons'; import {I18nFieldTranslations} from '../models/i18n-field-value'; import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-field-portal-data-injection-token"; +import {ValidationRegistryService} from "../../../registry/validation-registry.service"; @Component({ selector: 'ncc-abstract-i18n-text-field', @@ -34,9 +35,10 @@ export abstract class AbstractI18nTextFieldComponent extends AbstractI18nErrorsC protected constructor(protected languageIconsService: LanguageIconsService, protected _translateService: TranslateService, protected _domSanitizer: DomSanitizer, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(languageIconsService, _translateService, dataFieldPortalData); - this.selectedLanguage = this._translateService.currentLang; + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(languageIconsService, _translateService, dataFieldPortalData, _validationRegistry); + this.selectedLanguage = this._translateService.currentLang.split('-')[0]; this.languageKeys = Object.keys(this.languageIconsService.languageIcons); } diff --git a/projects/netgrif-components-core/src/lib/data-fields/i18n-field/models/i18n-field.ts b/projects/netgrif-components-core/src/lib/data-fields/i18n-field/models/i18n-field.ts index baa2bfa12..9cd737649 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/i18n-field/models/i18n-field.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/i18n-field/models/i18n-field.ts @@ -6,6 +6,7 @@ import {Component, ComponentPrefixes} from '../../models/component'; import {I18nFieldTranslations, I18nFieldValue} from './i18n-field-value'; import {Observable} from 'rxjs'; import {FormControl, ValidatorFn} from '@angular/forms'; +import {Validator} from "../../../registry/model/validator"; export enum I18nFieldValidation { TRANSLATION_REQUIRED = 'translationRequired', @@ -84,11 +85,13 @@ export class I18nField extends DataField { } constructor(stringId: string, title: string, value: I18nFieldValue | string, behavior: Behavior, placeholder?: string, - description?: string, layout?: Layout, validations?: Array, _component?: Component) { + description?: string, layout?: Layout, validations?: Array, _component?: Component, + validatorRegister?: Map) { if (typeof value === 'string') { value = {defaultValue: value}; } - super(stringId, title, value, behavior, placeholder, description, layout, validations, _component); + super(stringId, title, value, behavior, placeholder, description, layout, validations, _component, undefined, undefined, + validatorRegister); } protected valueEquality(a: I18nFieldValue, b: I18nFieldValue): boolean { diff --git a/projects/netgrif-components-core/src/lib/data-fields/models/abstract-data-field.ts b/projects/netgrif-components-core/src/lib/data-fields/models/abstract-data-field.ts index 9f3b1b19e..0c9e2dc38 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/models/abstract-data-field.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/models/abstract-data-field.ts @@ -8,6 +8,7 @@ import {ConfigurationService} from '../../configuration/configuration.service'; import {Component, DEFAULT} from './component'; import {Validation} from './validation'; import {ElementRef} from "@angular/core"; +import {Validator} from "../../registry/model/validator"; import {UpdateOnStrategy, UpdateStrategy} from "./update-strategy"; /** @@ -146,11 +147,13 @@ export abstract class DataField { * @param _component - component data of datafield * @param _parentTaskId - stringId of parent task, only defined if field is loaded using {@link TaskRefField} * @param _parentCaseId - stringId of parent case, only defined if field is loaded using {@link TaskRefField} + * @param _validatorRegister - validator description to use when validating fields with dynamic and custom validations. */ protected constructor(private _stringId: string, private _title: string, initialValue: T, private _behavior: Behavior, private _placeholder?: string, private _description?: string, private _layout?: Layout, public validations?: Array, - private _component?: Component, private _parentTaskId?: string, private _parentCaseId?: string) { + private _component?: Component, private _parentTaskId?: string, private _parentCaseId?: string, + private _validatorRegister?: Map) { this._value = new BehaviorSubject(initialValue); this._previousValue = new BehaviorSubject(initialValue); this._initialized$ = new BehaviorSubject(false); @@ -376,6 +379,10 @@ export abstract class DataField { this._formControlRef = formControl; } + get validatorRegister(): Map { + return this._validatorRegister; + } + public getUpdateOnStrategy(): UpdateOnStrategy { return UpdateStrategy.BLUR; } @@ -532,7 +539,17 @@ export abstract class DataField { } protected resolveValidations(): Array { - return []; + const result = []; + if (!!this.validations && !!this.validatorRegister) { + this.validations.forEach(item => { + if (this.validatorRegister?.has(item.name)) { + const validator: Validator = this.validatorRegister.get(item.name); + const attributes = validator.attributeNames.map(atr => item.arguments[atr].value) + result.push(validator.fn(...attributes)); + } + }); + } + return result; } /** diff --git a/projects/netgrif-components-core/src/lib/data-fields/models/abstract-file-field-default-component.ts b/projects/netgrif-components-core/src/lib/data-fields/models/abstract-file-field-default-component.ts index a1f93884e..8293e2e81 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/models/abstract-file-field-default-component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/models/abstract-file-field-default-component.ts @@ -28,7 +28,7 @@ export abstract class AbstractFileFieldDefaultComponent) { - super(dataFieldPortalData); + super(null, dataFieldPortalData); } protected checkAllowedTypes(): boolean { diff --git a/projects/netgrif-components-core/src/lib/data-fields/models/validation-functions.ts b/projects/netgrif-components-core/src/lib/data-fields/models/validation-functions.ts new file mode 100644 index 000000000..37b6e0010 --- /dev/null +++ b/projects/netgrif-components-core/src/lib/data-fields/models/validation-functions.ts @@ -0,0 +1,223 @@ +import {Validator} from "../../registry/model/validator"; +import {Validators} from "@angular/forms"; +import {NumberFieldValidation} from "../number-field/models/number-field"; +import moment from "moment/moment"; +import { + AbstractTimeInstanceField, +} from "../time-instance-abstract-field/models/abstract-time-instance-field"; + + +/* General validations */ +export const requiredValidation: Validator = { + key: 'required', + attributeNames: [], + fn: undefined, + validationErrorKey: 'required', + defaultErrorMessage: () => 'dataField.validations.required' +} + +/* Text field validations */ +export const minLengthValidation: Validator = { + key: 'minlength', + attributeNames: ['length'], + fn: (min: string) => { + const length = parseInt(min, 10); + return Validators.minLength(length); + }, + validationErrorKey: 'minlength', + defaultErrorMessage: () => 'dataField.validations.minLength' +} + +export const maxLengthValidation: Validator = { + key: 'maxlength', + attributeNames: ['length'], + fn: (max: string) => { + const length = parseInt(max, 10); + return Validators.maxLength(length); + }, + validationErrorKey: 'maxlength', + defaultErrorMessage: () => 'dataField.validations.maxLength' +} + +export const regexValidation: Validator = { + key: 'regex', + attributeNames: ['expression'], + fn: (regex: string) => { return Validators.pattern(new RegExp(regex)); }, + validationErrorKey: 'pattern', + defaultErrorMessage: () => 'dataField.validations.pattern' +} + +export const emailValidation: Validator = { + key: 'email', + attributeNames: [], + fn: () => { return Validators.email; }, + validationErrorKey: 'email', + defaultErrorMessage: () => 'dataField.validations.email' +} + +export const telNumberValidation: Validator = { + key: 'telnumber', + attributeNames: [], + fn: () => { + return (fc) => { + if (!(new RegExp(/^(?:\+?(\d{1,3}))?([-. (]*(\d{3})[-. )]*)?((\d{3})[-. ]*(\d{2,4})(?:[-.x ]*(\d+))?)$/).test(fc.value))) { + return ({telnumber: true}); + } else { + return null; + } + }; + }, + validationErrorKey: 'telnumber', + defaultErrorMessage: () => 'dataField.validations.phone' +} + +/* Number field validations */ +export const oddValidation: Validator = { + key: 'odd', + attributeNames: [], + fn: () => { return (fc) => {if ((fc.value % 2) === 0) { return ({odd: true}); } else { return (null); }}}, + validationErrorKey: 'odd', + defaultErrorMessage: () => 'dataField.validations.odd' +} + +export const evenValidation: Validator = { + key: 'even', + attributeNames: [], + fn: () => { return (fc) => {if ((fc.value % 2) !== 0) { return ({even: true}); } else { return (null); }}}, + validationErrorKey: 'even', + defaultErrorMessage: () => 'dataField.validations.even' +} + +export const positiveValidation: Validator = { + key: 'positive', + attributeNames: [], + fn: () => { return (fc) => {if (fc.value < 0) { return ({positive: true}); } else { return (null); }}}, + validationErrorKey: 'positive', + defaultErrorMessage: () => 'dataField.validations.positive' +} + +export const negativeValidation: Validator = { + key: 'negative', + attributeNames: [], + fn: () => { return (fc) => {if (fc.value >= 0) { return ({negative: true}); } else { return (null); }}}, + validationErrorKey: 'negative', + defaultErrorMessage: () => 'dataField.validations.negative' +} + +export const decimalValidation: Validator = { + key: 'decimal', + attributeNames: [], + fn: () => { return (fc) => {if (fc.value % 1 !== 0) { return ({decimal: true}); } else { return (null); }}}, + validationErrorKey: 'decimal', + defaultErrorMessage: () => 'dataField.validations.decimal' +} + +export const inRangeValidation: Validator = { + key: 'inrange', + attributeNames: ['from', 'to'], + fn: (from, to) => { + return (fc) => { + const first = parseFloat(from); + const second = parseFloat(to); + if (isNaN(first) && !isNaN(second) && from.includes(NumberFieldValidation.INF)) { + if (fc.value > second) { return ({inrange: true}); } else { return (null); } + } else if (isNaN(second) && !isNaN(first) && to.includes(NumberFieldValidation.INF)) { + if (fc.value < first) { return ({inrange: true}); } else { return (null); } + } else if (!isNaN(first) && !isNaN(second)) { + if (fc.value < first || fc.value > second) { return ({inrange: true}); } else { return (null); } + } + } + }, + validationErrorKey: 'inrange', + defaultErrorMessage: () => 'dataField.validations.inrange' +} + +/* Boolean validations */ +export const requiredTrueValidation: Validator = { + key: 'requiredTrue', + attributeNames: [], + fn: () => { return (fc) => { return fc.value === true ? null : {requiredTrue: true}}}, + validationErrorKey: 'requiredTrue', + defaultErrorMessage: () => 'dataField.validations.decimal' +} + +/* Time instance validations */ +export const betweenValidation: Validator = { + key: 'between', + attributeNames: ['from', 'to'], + fn: (from, to) => { + return (fc) => { + const start = AbstractTimeInstanceField.parseDate(from); + const end = AbstractTimeInstanceField.parseDate(to); + if (start && end) { + if (start === 'past' && moment(end).isValid()) { + return fc.value > moment(end) ? {between: true} : null; + } else if (end === 'future' && moment(start).isValid()) { + return fc.value < moment(start) ? {between: true} : null; + } else if (moment(start).isValid() && moment(end).isValid()) { + return fc.value < moment(start) || fc.value > moment(end) ? {between: true} : null; + } + } + } + }, + validationErrorKey: 'between', + defaultErrorMessage: (from, to) => { + if (from === 'past') { + return 'dataField.validations.datePast'; + } + if (to === 'future') { + return 'dataField.validations.dateFuture' + } + return 'dataField.validations.dateRange' + } +} + +export const workdayValidation: Validator = { + key: 'workday', + attributeNames: [], + fn: () => { return (fc) => { + const dayOfWeek = !!fc.value ? fc.value.weekday() : null; + return dayOfWeek === 6 || dayOfWeek === 0 ? {workday: true} : null; + }}, + validationErrorKey: 'workday', + defaultErrorMessage: () => 'dataField.validations.workday' +} + +export const weekendValidation: Validator = { + key: 'weekend', + attributeNames: [], + fn: () => { return (fc) => { + const dayOfWeek = !!fc.value ? fc.value.weekday() : null; + return dayOfWeek >= 1 && dayOfWeek <= 5 && dayOfWeek !== 0 ? {weekend: true} : null; + }}, + validationErrorKey: 'weekend', + defaultErrorMessage: () => 'dataField.validations.weekend' +} + +/* I18n validations */ +export const translationRequiredValidation: Validator = { + key: 'translationRequired', + attributeNames: ['languages'], + fn: (languages) => { return (fc) => { + const languageCodes = languages.split(','); + return languageCodes.every(languageCode => languageCode in fc.value.translations) + ? null : ({translationRequired: true}); + }}, + validationErrorKey: 'translationRequired', + defaultErrorMessage: () => 'dataField.validations.translationRequired' +} + +export const translationOnlyValidation: Validator = { + key: 'translationOnly', + attributeNames: ['languages'], + fn: (languages) => { + return (fc) => { + const languageCodes = languages.split(','); + return Object.keys(fc.value.translations).every(translation => languageCodes.includes(translation)) + ? null : ({translationOnly: true}); + } + }, + validationErrorKey: 'translationOnly', + defaultErrorMessage: () => 'dataField.validations.translationOnly' +} + diff --git a/projects/netgrif-components-core/src/lib/data-fields/models/validation.ts b/projects/netgrif-components-core/src/lib/data-fields/models/validation.ts index 773064455..76e1d20a9 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/models/validation.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/models/validation.ts @@ -5,11 +5,27 @@ export interface Validation { /** * Value set in the PetriNet model as validation. */ - validationRule: string; + validationRule?: string; /** * Message that should be displayed when the validation fails. * * If the message is empty, some default message will be displayed. */ - validationMessage: string; + validationMessage?: string; + + name: string; + + arguments?: { + [k:string]: Argument; + }; + +} + +export interface Argument { + + value: string; + key: string; + + dynamic: boolean; + } diff --git a/projects/netgrif-components-core/src/lib/data-fields/multichoice-field/multichoice-autocomplete-field/abstract-multichoice-autocomplete-field-component.component.ts b/projects/netgrif-components-core/src/lib/data-fields/multichoice-field/multichoice-autocomplete-field/abstract-multichoice-autocomplete-field-component.component.ts index 8832d3c2f..389a9668a 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/multichoice-field/multichoice-autocomplete-field/abstract-multichoice-autocomplete-field-component.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/multichoice-field/multichoice-autocomplete-field/abstract-multichoice-autocomplete-field-component.component.ts @@ -22,7 +22,7 @@ export abstract class AbstractMultichoiceAutocompleteFieldComponentComponent ext filteredOptions: Observable>; constructor(@Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(dataFieldPortalData); + super(undefined, dataFieldPortalData); } ngOnInit() { diff --git a/projects/netgrif-components-core/src/lib/data-fields/multichoice-field/multichoice-caseref-field/abstract-multichoice-caseref-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/multichoice-field/multichoice-caseref-field/abstract-multichoice-caseref-field.component.ts index 3373e9c24..313d827c4 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/multichoice-field/multichoice-caseref-field/abstract-multichoice-caseref-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/multichoice-field/multichoice-caseref-field/abstract-multichoice-caseref-field.component.ts @@ -4,6 +4,10 @@ import {ComponentPortal} from "@angular/cdk/portal"; import {MultichoiceField} from '../models/multichoice-field'; import {AbstractCaseRefBaseFieldComponent} from '../../case-ref-field/model/abstract-case-ref-base-field-component'; import {Subscription} from 'rxjs'; +import {NAE_CASE_REF_CREATE_CASE, NAE_CASE_REF_SEARCH} from '../../case-ref-field/model/case-ref-injection-tokens'; +import {TranslateService} from "@ngx-translate/core"; +import {EnumerationField} from "../../enumeration-field/models/enumeration-field"; +import {ValidationRegistryService} from "../../../registry/validation-registry.service"; @Component({ selector: 'ncc-abstract-case-ref-default', @@ -17,8 +21,10 @@ export abstract class AbstractMultichoiceCaseRefComponent extends AbstractCaseRe protected constructor(protected injector: Injector, protected caseViewType: Type, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(injector, caseViewType, dataFieldPortalData); + _translate: TranslateService, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistryService: ValidationRegistryService) { + super(injector, caseViewType, dataFieldPortalData, _validationRegistryService); } ngAfterViewInit(): void { diff --git a/projects/netgrif-components-core/src/lib/data-fields/multichoice-field/multichoice-list-field/abstract-multichoice-list-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/multichoice-field/multichoice-list-field/abstract-multichoice-list-field.component.ts index 323105322..97183ca5c 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/multichoice-field/multichoice-list-field/abstract-multichoice-list-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/multichoice-field/multichoice-list-field/abstract-multichoice-list-field.component.ts @@ -14,6 +14,6 @@ export abstract class AbstractMultichoiceListFieldComponent extends AbstractBase validate: FormControl; constructor(@Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(dataFieldPortalData); + super(undefined, dataFieldPortalData); } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/multichoice-field/multichoice-select-field/abstract-multichoice-select-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/multichoice-field/multichoice-select-field/abstract-multichoice-select-field.component.ts index 0321e63e0..d6e4415e4 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/multichoice-field/multichoice-select-field/abstract-multichoice-select-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/multichoice-field/multichoice-select-field/abstract-multichoice-select-field.component.ts @@ -10,7 +10,7 @@ import {AbstractBaseDataFieldComponent} from "../../base-component/abstract-base export abstract class AbstractMultichoiceSelectFieldComponent extends AbstractBaseDataFieldComponent { constructor(@Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(dataFieldPortalData); + super(undefined, dataFieldPortalData); } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/number-field/abstract-number-errors.component.spec.ts b/projects/netgrif-components-core/src/lib/data-fields/number-field/abstract-number-errors.component.spec.ts index 54dfedb66..b3d056f64 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/number-field/abstract-number-errors.component.spec.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/number-field/abstract-number-errors.component.spec.ts @@ -20,6 +20,16 @@ import {LanguageService} from '../../translate/language.service'; import {FormControl} from '@angular/forms'; import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../models/data-field-portal-data-injection-token"; import {WrappedBoolean} from "../data-field-template/models/wrapped-boolean"; +import {Validator} from "../../registry/model/validator"; +import { + decimalValidation, + evenValidation, inRangeValidation, + negativeValidation, + oddValidation, + positiveValidation +} from "../models/validation-functions"; +import {ValidationRegistryService} from "../../registry/validation-registry.service"; +import {DataFieldsModule} from "../data-fields.module"; describe('AbstractNumberErrorsComponent', () => { let component: TestNumErrorComponent; @@ -32,7 +42,8 @@ describe('AbstractNumberErrorsComponent', () => { AngularResizeEventModule, TranslateLibModule, HttpClientTestingModule, - NoopAnimationsModule + NoopAnimationsModule, + DataFieldsModule ], providers: [ {provide: AuthenticationMethodService, useCLass: MockAuthenticationMethodService}, @@ -45,16 +56,30 @@ describe('AbstractNumberErrorsComponent', () => { visible: true, editable: true, hidden: true - }, [ - {validationRule: 'odd', validationMessage: 'This is custom odd message!'}, - {validationRule: 'even', validationMessage: ''}, - {validationRule: 'positive', validationMessage: 'This is custom message!'}, - {validationRule: 'negative', validationMessage: 'This is custom message!'}, - {validationRule: 'decimal', validationMessage: 'This is custom message!'}, - {validationRule: 'inrange inf,0', validationMessage: 'This is custom message!'}, - {validationRule: 'inrange 0,inf', validationMessage: 'This is custom message!'}, - {validationRule: 'inrange -5,0', validationMessage: 'This is custom message!'}, - ]), + },[ + {name: 'odd', validationMessage: 'This is custom odd message!'}, + {name: 'even', validationMessage: ''}, + {name: 'positive', validationMessage: 'This is custom message!'}, + {name: 'negative', validationMessage: 'This is custom message!'}, + {name: 'decimal', validationMessage: 'This is custom message!'}, + {name: 'inrange', validationMessage: 'This is custom message!', arguments: {'from': {key: 'from', value: 'inf', dynamic: false}, 'to': {key: 'to', value: '0', dynamic: false}}}, + {name: 'inrange', validationMessage: 'This is custom message!', arguments: {'from': {key: 'from', value: '0', dynamic: false}, 'to': {key: 'to', value: 'inf', dynamic: false}}}, + {name: 'inrange', validationMessage: 'This is custom message!', arguments: {'from': {key: 'from', value: '-5', dynamic: false}, 'to': {key: 'to', value: '0', dynamic: false}}}, + ], + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + new Map([ + ['odd', oddValidation], + ['even', evenValidation], + ['positive', positiveValidation], + ['negative', negativeValidation], + ['decimal', decimalValidation], + ['inrange', inRangeValidation] + ])), formControlRef: new FormControl(), showLargeLayout: new WrappedBoolean() } as DataFieldPortalData @@ -94,8 +119,9 @@ describe('AbstractNumberErrorsComponent', () => { template: '' }) class TestNumErrorComponent extends AbstractNumberErrorsComponent { - constructor(translate: TranslateService, @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(translate, dataFieldPortalData); + constructor(translate: TranslateService, @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(translate, dataFieldPortalData, _validationRegistry); } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/number-field/abstract-number-errors.component.ts b/projects/netgrif-components-core/src/lib/data-fields/number-field/abstract-number-errors.component.ts index 1e32381d7..92574df01 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/number-field/abstract-number-errors.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/number-field/abstract-number-errors.component.ts @@ -1,8 +1,9 @@ -import {NumberField, NumberFieldValidation} from './models/number-field'; +import {NumberField} from './models/number-field'; import {TranslateService} from '@ngx-translate/core'; import {Component, Inject, Optional} from '@angular/core'; import {AbstractBaseDataFieldComponent} from "../base-component/abstract-base-data-field.component"; import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../models/data-field-portal-data-injection-token"; +import {ValidationRegistryService} from "../../registry/validation-registry.service"; @Component({ selector: 'ncc-abstract-number-errors-field', @@ -10,46 +11,9 @@ import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../models/data-field- }) export abstract class AbstractNumberErrorsComponent extends AbstractBaseDataFieldComponent{ - protected constructor(protected _translate: TranslateService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(dataFieldPortalData); - } - - getErrorMessage() { - if (this.formControlRef.hasError(NumberFieldValidation.REQUIRED)) { - return this._translate.instant('dataField.validations.required'); - } - if (this.formControlRef.hasError(NumberFieldValidation.VALID_ODD)) { - return this.resolveErrorMessage(NumberFieldValidation.ODD, this._translate.instant('dataField.validations.odd')); - } - if (this.formControlRef.hasError(NumberFieldValidation.VALID_EVEN)) { - return this.resolveErrorMessage(NumberFieldValidation.EVEN, this._translate.instant('dataField.validations.even')); - } - if (this.formControlRef.hasError(NumberFieldValidation.VALID_POSITIVE)) { - return this.resolveErrorMessage(NumberFieldValidation.POSITIVE, this._translate.instant('dataField.validations.positive')); - } - if (this.formControlRef.hasError(NumberFieldValidation.VALID_NEGATIVE)) { - return this.resolveErrorMessage(NumberFieldValidation.NEGATIVE, this._translate.instant('dataField.validations.negative')); - } - if (this.formControlRef.hasError(NumberFieldValidation.VALID_DECIMAL)) { - return this.resolveErrorMessage(NumberFieldValidation.DECIMAL, this._translate.instant('dataField.validations.decimal')); - } - if (this.formControlRef.hasError(NumberFieldValidation.VALID_IN_RANGE)) { - const tmp = this.dataField.validations.find(value => - value.validationRule.includes(NumberFieldValidation.IN_RANGE) - ).validationRule.split(' '); - return this.resolveErrorMessage( - NumberFieldValidation.IN_RANGE, this._translate.instant('dataField.validations.inrange', {range: tmp[1]}) - ); - } - return ''; - } - - resolveErrorMessage(search: string, generalMessage: string) { - const validation = this.dataField.validations.find(value => value.validationRule.includes(search)); - if (validation.validationMessage && validation.validationMessage !== '') { - return validation.validationMessage; - } - return generalMessage; + protected constructor(_translate: TranslateService, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(_translate, dataFieldPortalData, _validationRegistry); } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/number-field/abstract-number-field.component.spec.ts b/projects/netgrif-components-core/src/lib/data-fields/number-field/abstract-number-field.component.spec.ts index ebe924878..59abaaad3 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/number-field/abstract-number-field.component.spec.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/number-field/abstract-number-field.component.spec.ts @@ -18,6 +18,15 @@ import {MockUserResourceService} from '../../utility/tests/mocks/mock-user-resou import {TranslateLibModule} from '../../translate/translate-lib.module'; import {MaterialModule} from '../../material/material.module'; import {NAE_INFORM_ABOUT_INVALID_DATA} from '../models/invalid-data-policy-token'; +import {Validator} from "../../registry/model/validator"; +import { + decimalValidation, + evenValidation, inRangeValidation, + negativeValidation, + oddValidation, + positiveValidation +} from "../models/validation-functions"; +import {DataFieldsModule} from "../data-fields.module"; describe('AbstractNumberFieldComponent', () => { let component: TestNumComponent; @@ -30,7 +39,8 @@ describe('AbstractNumberFieldComponent', () => { AngularResizeEventModule, TranslateLibModule, HttpClientTestingModule, - NoopAnimationsModule + NoopAnimationsModule, + DataFieldsModule ], providers: [ {provide: AuthenticationMethodService, useCLass: MockAuthenticationMethodService}, @@ -82,13 +92,27 @@ class TestWrapperComponent { editable: true, hidden: true }, [ - {validationRule: 'odd', validationMessage: 'This is custom odd message!'}, - {validationRule: 'even', validationMessage: ''}, - {validationRule: 'positive', validationMessage: 'This is custom message!'}, - {validationRule: 'negative', validationMessage: 'This is custom message!'}, - {validationRule: 'decimal', validationMessage: 'This is custom message!'}, - {validationRule: 'inrange inf,0', validationMessage: 'This is custom message!'}, - {validationRule: 'inrange 0,inf', validationMessage: 'This is custom message!'}, - {validationRule: 'inrange -5,0', validationMessage: 'This is custom message!'}, - ]); + {name: 'odd', validationMessage: 'This is custom odd message!'}, + {name: 'even', validationMessage: ''}, + {name: 'positive', validationMessage: 'This is custom message!'}, + {name: 'negative', validationMessage: 'This is custom message!'}, + {name: 'decimal', validationMessage: 'This is custom message!'}, + {name: 'inrange', validationMessage: 'This is custom message!', arguments: {'from': {key: 'from', value: 'inf', dynamic: false}, 'to': {key: 'to', value: '0', dynamic: false}}}, + {name: 'inrange', validationMessage: 'This is custom message!', arguments: {'from': {key: 'from', value: '0', dynamic: false}, 'to': {key: 'to', value: 'inf', dynamic: false}}}, + {name: 'inrange', validationMessage: 'This is custom message!', arguments: {'from': {key: 'from', value: '-5', dynamic: false}, 'to': {key: 'to', value: '0', dynamic: false}}}, + ], + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + new Map([ + ['odd', oddValidation], + ['even', evenValidation], + ['positive', positiveValidation], + ['negative', negativeValidation], + ['decimal', decimalValidation], + ['inrange', inRangeValidation] + ])); } diff --git a/projects/netgrif-components-core/src/lib/data-fields/number-field/currency-number-field/abstract-currency-number-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/number-field/currency-number-field/abstract-currency-number-field.component.ts index 1b0d473e6..aa7161c25 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/number-field/currency-number-field/abstract-currency-number-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/number-field/currency-number-field/abstract-currency-number-field.component.ts @@ -2,6 +2,7 @@ import {AfterViewInit, Component, Inject, Optional} from '@angular/core'; import {TranslateService} from '@ngx-translate/core'; import {CurrencyPipe, getCurrencySymbol} from '@angular/common'; import {AbstractNumberErrorsComponent} from '../abstract-number-errors.component'; +import {ValidationRegistryService} from "../../../registry/validation-registry.service"; import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-field-portal-data-injection-token"; import {NumberField} from "../models/number-field"; @@ -18,8 +19,9 @@ export abstract class AbstractCurrencyNumberFieldComponent extends AbstractNumbe public readonly WHITESPACE = ' '; protected constructor(protected _currencyPipe: CurrencyPipe, translateService: TranslateService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(translateService, dataFieldPortalData); + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(translateService, dataFieldPortalData, _validationRegistry); } ngAfterViewInit() { diff --git a/projects/netgrif-components-core/src/lib/data-fields/number-field/models/number-field.spec.ts b/projects/netgrif-components-core/src/lib/data-fields/number-field/models/number-field.spec.ts index 9a86c8d4a..49f847ff5 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/number-field/models/number-field.spec.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/number-field/models/number-field.spec.ts @@ -1,5 +1,13 @@ import {NumberField} from './number-field'; import {TestBed} from '@angular/core/testing'; +import {Validator} from "../../../registry/model/validator"; +import { + decimalValidation, + evenValidation, inRangeValidation, + negativeValidation, + oddValidation, + positiveValidation +} from "../../models/validation-functions"; describe('NumberField', () => { it('should create an instance', () => { @@ -10,15 +18,29 @@ describe('NumberField', () => { editable: true, hidden: true }, [ - {validationRule: 'odd', validationMessage: ''}, - {validationRule: 'even', validationMessage: ''}, - {validationRule: 'positive', validationMessage: ''}, - {validationRule: 'negative', validationMessage: ''}, - {validationRule: 'decimal', validationMessage: ''}, - {validationRule: 'inrange inf,0', validationMessage: ''}, - {validationRule: 'inrange 0,inf', validationMessage: ''}, - {validationRule: 'inrange -5,0', validationMessage: ''}, - ])).toBeTruthy(); + {name: 'odd', validationMessage: 'This is custom message!'}, + {name: 'even', validationMessage: 'This is custom message!'}, + {name: 'positive', validationMessage: 'This is custom message!'}, + {name: 'negative', validationMessage: 'This is custom message!'}, + {name: 'decimal', validationMessage: 'This is custom message!'}, + {name: 'inrange', validationMessage: 'This is custom message!', arguments: {'from': {key: 'from', value: 'inf', dynamic: false}, 'to': {key: 'to', value: '0', dynamic: false}}}, + {name: 'inrange', validationMessage: 'This is custom message!', arguments: {'from': {key: 'from', value: '0', dynamic: false}, 'to': {key: 'to', value: 'inf', dynamic: false}}}, + {name: 'inrange', validationMessage: 'This is custom message!', arguments: {'from': {key: 'from', value: '-5', dynamic: false}, 'to': {key: 'to', value: '0', dynamic: false}}}, + ], + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + new Map([ + ['odd', oddValidation], + ['even', evenValidation], + ['positive', positiveValidation], + ['negative', negativeValidation], + ['decimal', decimalValidation], + ['inrange', inRangeValidation] + ]))).toBeTruthy(); }); afterEach(() => { diff --git a/projects/netgrif-components-core/src/lib/data-fields/number-field/models/number-field.ts b/projects/netgrif-components-core/src/lib/data-fields/number-field/models/number-field.ts index 7ab8ef86d..5b081af4f 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/number-field/models/number-field.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/number-field/models/number-field.ts @@ -5,6 +5,8 @@ import {Validation} from '../../models/validation'; import {FormatFilter} from '../../models/format-filter'; import {Component, ComponentPrefixes} from '../../models/component'; import {DataField} from '../../models/abstract-data-field'; +import {noop} from "rxjs"; +import {Validator} from "../../../registry/model/validator"; export enum NumberFieldValidation { ODD = 'odd', @@ -27,82 +29,14 @@ export class NumberField extends DataField { public _formatFilter: FormatFilter; constructor(stringId: string, title: string, value: number, behavior: Behavior, validations?: Array, placeholder?: string, - description?: string, layout?: Layout, format?: FormatFilter, component?: Component, parentTaskId?: string) { - super(stringId, title, value, behavior, placeholder, description, layout, validations, component, parentTaskId); + description?: string, layout?: Layout, format?: FormatFilter, component?: Component, parentTaskId?: string, + validators?: Map) { + super(stringId, title, value, behavior, placeholder, description, layout, validations, component, parentTaskId, undefined, validators); this._formatFilter = format; } public getTypedComponentType(): string { return ComponentPrefixes.NUMBER + this.getComponentType(); } - protected resolveValidations(): Array { - const result = []; - this.validations.forEach(item => { - if (item.validationRule.includes(NumberFieldValidation.ODD)) { - result.push(this.validOdd); - } else if (item.validationRule.includes(NumberFieldValidation.EVEN)) { - result.push(this.validEven); - } else if (item.validationRule.includes(NumberFieldValidation.POSITIVE)) { - result.push(this.validPositive); - } else if (item.validationRule.includes(NumberFieldValidation.NEGATIVE)) { - result.push(this.validNegative); - } else if (item.validationRule.includes(NumberFieldValidation.DECIMAL)) { - result.push(this.validDecimal); - } else if (item.validationRule.includes(NumberFieldValidation.IN_RANGE)) { - const tmp = item.validationRule.split(' '); - const ranges = tmp[1].split(','); - const first = parseFloat(ranges[0]); - const second = parseFloat(ranges[1]); - - if (isNaN(first) && !isNaN(second) && ranges[0].includes(NumberFieldValidation.INF)) { - result.push(this.validInRangeSmaller(second)); - } else if (isNaN(second) && !isNaN(first) && ranges[1].includes(NumberFieldValidation.INF)) { - result.push(this.validInRangeBigger(first)); - } else if (!isNaN(first) && !isNaN(second)) { - result.push(this.validInRange(first, second)); - } - } - }); - - return result; - } - - private validOdd(fc: FormControl) { - if ((fc.value % 2) === 0) { return ({validOdd: true}); } else { return (null); } - } - - private validEven(fc: FormControl) { - if ((fc.value % 2) !== 0) { return ({validEven: true}); } else { return (null); } - } - - private validPositive(fc: FormControl) { - if (fc.value < 0) { return ({validPositive: true}); } else { return (null); } - } - - private validNegative(fc: FormControl) { - if (fc.value >= 0) { return ({validNegative: true}); } else { return (null); } - } - - private validDecimal(fc: FormControl) { - if (fc.value % 1 !== 0) { return ({validDecimal: true}); } else { return (null); } - } - - private validInRangeSmaller(range: number): ValidatorFn { - return (fc: FormControl): {[key: string]: any} | null => { - if (fc.value > range) { return ({validInRange: true}); } else { return (null); } - }; - } - - private validInRangeBigger(range: number): ValidatorFn { - return (fc: FormControl): {[key: string]: any} | null => { - if (fc.value < range) { return ({validInRange: true}); } else { return (null); } - }; - } - - private validInRange(first: number, second: number): ValidatorFn { - return (fc: FormControl): {[key: string]: any} | null => { - if (fc.value < first || fc.value > second) { return ({validInRange: true}); } else { return (null); } - }; - } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/number-field/number-decimal-field/abstract-number-decimal-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/number-field/number-decimal-field/abstract-number-decimal-field.component.ts index 314e430f4..cb47f30a1 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/number-field/number-decimal-field/abstract-number-decimal-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/number-field/number-decimal-field/abstract-number-decimal-field.component.ts @@ -1,9 +1,10 @@ -import {AfterViewInit, ChangeDetectorRef, Component, Inject, Optional} from "@angular/core"; +import {AfterViewInit, Component, Inject, Optional} from "@angular/core"; import {AbstractNumberErrorsComponent} from "../abstract-number-errors.component"; import {DecimalPipe} from "@angular/common"; import {TranslateService} from "@ngx-translate/core"; import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-field-portal-data-injection-token"; import {NumberField} from "../models/number-field"; +import {ValidationRegistryService} from "../../../registry/validation-registry.service"; @Component({ selector: 'ncc-abstract-number-decimal-field', @@ -19,8 +20,9 @@ export abstract class AbstractNumberDecimalFieldComponent extends AbstractNumber protected constructor(protected _decimalPipe: DecimalPipe, _translate: TranslateService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(_translate, dataFieldPortalData); + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(_translate, dataFieldPortalData, _validationRegistry); } ngAfterViewInit() { diff --git a/projects/netgrif-components-core/src/lib/data-fields/number-field/number-default-field/abstract-default-number-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/number-field/number-default-field/abstract-default-number-field.component.ts index 81dd7e091..8d8240c0e 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/number-field/number-default-field/abstract-default-number-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/number-field/number-default-field/abstract-default-number-field.component.ts @@ -3,6 +3,7 @@ import {AbstractNumberErrorsComponent} from '../abstract-number-errors.component import {Component, Inject, Optional} from '@angular/core'; import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-field-portal-data-injection-token"; import {NumberField} from "../models/number-field"; +import {ValidationRegistryService} from "../../../registry/validation-registry.service"; @Component({ selector: 'ncc-abstract-number-default-field', @@ -11,7 +12,8 @@ import {NumberField} from "../models/number-field"; export abstract class AbstractDefaultNumberFieldComponent extends AbstractNumberErrorsComponent { protected constructor(translateService: TranslateService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(translateService, dataFieldPortalData); + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(translateService, dataFieldPortalData, _validationRegistry); } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/public-api.ts b/projects/netgrif-components-core/src/lib/data-fields/public-api.ts index 16157a386..87366d188 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/public-api.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/public-api.ts @@ -122,3 +122,6 @@ export * from './text-field/dashboard-portal-text-field/dashboard-view-constants /* Services */ export * from './i18n-field/language-icons.service'; + +/* Functions */ +export * from './models/validation-functions'; diff --git a/projects/netgrif-components-core/src/lib/data-fields/string-collection-field/string-collection-default-field/abstract-string-collection-default-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/string-collection-field/string-collection-default-field/abstract-string-collection-default-field.component.ts index ff5a16b3a..b544a6a09 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/string-collection-field/string-collection-default-field/abstract-string-collection-default-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/string-collection-field/string-collection-default-field/abstract-string-collection-default-field.component.ts @@ -5,6 +5,7 @@ import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from '../../models/data-fie import {StringCollectionField} from '../models/string-collection-field'; import {ENTER, COMMA, SEMICOLON} from '@angular/cdk/keycodes'; import {MatChipInputEvent} from '@angular/material/chips'; +import {ValidationRegistryService} from "../../../registry/validation-registry.service"; import {Subscription} from 'rxjs'; @Component({ @@ -17,9 +18,10 @@ export abstract class AbstractStringCollectionDefaultFieldComponent extends Abst public separatorKeysCodes: number[] = [ENTER]; protected subComp: Subscription; - protected constructor(protected _translate: TranslateService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(dataFieldPortalData); + protected constructor(_translate: TranslateService, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(_translate, dataFieldPortalData, _validationRegistry); } ngOnInit() { diff --git a/projects/netgrif-components-core/src/lib/data-fields/task-ref-field/task-ref-dashboard-field/abstract-task-ref-dashboard-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/task-ref-field/task-ref-dashboard-field/abstract-task-ref-dashboard-field.component.ts index 3f1d4ffec..b94fc8cb8 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/task-ref-field/task-ref-dashboard-field/abstract-task-ref-dashboard-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/task-ref-field/task-ref-dashboard-field/abstract-task-ref-dashboard-field.component.ts @@ -6,6 +6,8 @@ import {TaskRefDashboardConstants} from "../model/task-ref-dashboard-constants"; import {TaskRefDashboardTileConstants} from "../model/task-ref-dashboard-tile-constants"; import {AbstractBaseDataFieldComponent} from "../../base-component/abstract-base-data-field.component"; import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-field-portal-data-injection-token"; +import {ValidationRegistryService} from "../../../registry/validation-registry.service"; +import {TranslateService} from "@ngx-translate/core"; @Component({ selector: 'ncc-abstract-task-ref-dashboard', @@ -14,9 +16,11 @@ import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-fie export abstract class AbstractTaskRefDashboardFieldComponent extends AbstractBaseDataFieldComponent implements OnInit { dashboardTiles: Array; - protected constructor(protected _logger: LoggerService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(dataFieldPortalData); + protected constructor(_translate: TranslateService, + protected _logger: LoggerService, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry?: ValidationRegistryService) { + super(_translate, dataFieldPortalData, _validationRegistry); } ngOnInit() { diff --git a/projects/netgrif-components-core/src/lib/data-fields/task-ref-field/task-ref-list-field/abstract-task-ref-list-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/task-ref-field/task-ref-list-field/abstract-task-ref-list-field.component.ts index eb870c8bf..dec094937 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/task-ref-field/task-ref-list-field/abstract-task-ref-list-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/task-ref-field/task-ref-list-field/abstract-task-ref-list-field.component.ts @@ -8,6 +8,8 @@ import {ViewIdService} from "../../../user/services/view-id.service"; import {AbstractBaseDataFieldComponent} from "../../base-component/abstract-base-data-field.component"; import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-field-portal-data-injection-token"; import {ComponentPortal} from "@angular/cdk/portal"; +import {TranslateService} from "@ngx-translate/core"; +import {ValidationRegistryService} from "../../../registry/validation-registry.service"; @Component({ selector: 'ncc-abstract-task-ref-list-field', @@ -19,8 +21,10 @@ export abstract class AbstractTaskRefListFieldComponent extends AbstractBaseData protected constructor(protected injector: Injector, protected taskViewType: Type, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(dataFieldPortalData); + _translate: TranslateService, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(_translate, dataFieldPortalData, _validationRegistry); } ngAfterViewInit(): void { diff --git a/projects/netgrif-components-core/src/lib/data-fields/text-field/abstract-dashboard-text-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/text-field/abstract-dashboard-text-field.component.ts index 891792a10..93fc00409 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/text-field/abstract-dashboard-text-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/text-field/abstract-dashboard-text-field.component.ts @@ -5,6 +5,7 @@ import {CustomCard} from '../../dashboard/cards/model/custom-dashboard-model/cus import {Subscription} from 'rxjs'; import {TranslateService} from '@ngx-translate/core'; import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../models/data-field-portal-data-injection-token"; +import {ValidationRegistryService} from "../../registry/validation-registry.service"; @Component({ selector: 'ncc-abstract-dashboard-text-field', @@ -16,8 +17,9 @@ export abstract class AbstractDashboardTextFieldComponent extends AbstractTextEr protected _sub: Subscription; protected constructor(translate: TranslateService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(translate, dataFieldPortalData); + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(translate, dataFieldPortalData, _validationRegistry); } ngOnInit(): void { @@ -36,8 +38,4 @@ export abstract class AbstractDashboardTextFieldComponent extends AbstractTextEr } protected abstract createCard(textFieldValue: string): CustomCard; - - public getErrorMessage() { - return this.buildErrorMessage(this.dataField, this.formControlRef); - } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/text-field/abstract-text-errors.component.ts b/projects/netgrif-components-core/src/lib/data-fields/text-field/abstract-text-errors.component.ts index 4d29d2ddc..1f49605bd 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/text-field/abstract-text-errors.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/text-field/abstract-text-errors.component.ts @@ -1,10 +1,9 @@ -import {FormControl} from '@angular/forms'; -import {TextField, TextFieldValidation} from './models/text-field'; +import {TextField} from './models/text-field'; import {TranslateService} from '@ngx-translate/core'; -import {TextAreaField} from './models/text-area-field'; import {Component, Inject, Optional} from "@angular/core"; import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../models/data-field-portal-data-injection-token"; import {AbstractBaseDataFieldComponent} from "../base-component/abstract-base-data-field.component"; +import {ValidationRegistryService} from "../../registry/validation-registry.service"; @Component({ selector: 'ncc-text-errors', @@ -12,42 +11,9 @@ import {AbstractBaseDataFieldComponent} from "../base-component/abstract-base-da }) export abstract class AbstractTextErrorsComponent extends AbstractBaseDataFieldComponent{ - protected constructor(protected _translate: TranslateService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(dataFieldPortalData); - } - - protected buildErrorMessage(textField: TextField | TextAreaField, formControlRef: FormControl) { - if (formControlRef.hasError(TextFieldValidation.REQUIRED)) { - return this._translate.instant('dataField.validations.required'); - } - if (formControlRef.hasError(TextFieldValidation.VALID_MIN_LENGTH)) { - return this.resolveErrorMessage(textField, TextFieldValidation.MIN_LENGTH, - this._translate.instant('dataField.validations.minLength', {length: formControlRef.errors.minlength.requiredLength})); - } - if (formControlRef.hasError(TextFieldValidation.VALID_MAX_LENGTH)) { - return this.resolveErrorMessage(textField, TextFieldValidation.MAX_LENGTH, - this._translate.instant('dataField.validations.maxLength', {length: formControlRef.errors.maxlength.requiredLength})); - } - if (formControlRef.hasError(TextFieldValidation.PATTERN)) { - return this.resolveErrorMessage(textField, TextFieldValidation.REGEX, this._translate.instant('dataField.validations.pattern')); - } - if (formControlRef.hasError(TextFieldValidation.VALID_TEL_NUMBER)) { - return this.resolveErrorMessage( - textField, TextFieldValidation.TEL_NUMBER, this._translate.instant('dataField.validations.phone') - ); - } - if (formControlRef.hasError(TextFieldValidation.EMAIL)) { - return this.resolveErrorMessage(textField, TextFieldValidation.EMAIL, this._translate.instant('dataField.validations.email')); - } - return ''; - } - - protected resolveErrorMessage(textField: TextField | TextAreaField, search: string, generalMessage: string) { - const validation = textField.validations.find(value => value.validationRule.includes(search)); - if (validation.validationMessage && validation.validationMessage !== '') { - return validation.validationMessage; - } - return generalMessage; + protected constructor(_translate: TranslateService, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(_translate, dataFieldPortalData, _validationRegistry); } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/text-field/abstract-text-field.component.spec.ts b/projects/netgrif-components-core/src/lib/data-fields/text-field/abstract-text-field.component.spec.ts index 5dcea31fe..8d5cc9661 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/text-field/abstract-text-field.component.spec.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/text-field/abstract-text-field.component.spec.ts @@ -9,6 +9,9 @@ import {MaterialModule} from '../../material/material.module'; import {CovalentModule} from '../../covalent/covalent.module'; import {TranslateLibModule} from '../../translate/translate-lib.module'; import {NAE_INFORM_ABOUT_INVALID_DATA} from '../models/invalid-data-policy-token'; +import {Validator} from "../../registry/model/validator"; +import {emailValidation} from "../models/validation-functions"; +import {DataFieldsModule} from "../data-fields.module"; describe('AbstractTextFieldComponent', () => { let component: TestTextComponent; @@ -17,7 +20,8 @@ describe('AbstractTextFieldComponent', () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [MaterialModule, AngularResizeEventModule, NoopAnimationsModule, - CovalentModule, TranslateLibModule, HttpClientTestingModule], + CovalentModule, TranslateLibModule, HttpClientTestingModule, + DataFieldsModule], declarations: [ TestWrapperComponent ], @@ -59,5 +63,9 @@ class TestWrapperComponent { visible: true, editable: true, hidden: true - }, undefined, undefined, undefined, [{validationRule: 'email', validationMessage: 'custom message'}]); + }, undefined, undefined, undefined, + [{name: 'email', validationMessage: 'custom message'}], + undefined, + undefined, + new Map([['email', emailValidation]])); } diff --git a/projects/netgrif-components-core/src/lib/data-fields/text-field/dashboard-bar-chart-text-field/abstract-dashboard-bar-chart-text-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/text-field/dashboard-bar-chart-text-field/abstract-dashboard-bar-chart-text-field.component.ts index 5f1c57209..ca9e93619 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/text-field/dashboard-bar-chart-text-field/abstract-dashboard-bar-chart-text-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/text-field/dashboard-bar-chart-text-field/abstract-dashboard-bar-chart-text-field.component.ts @@ -6,6 +6,7 @@ import {FilterType} from '../../../filter/models/filter-type'; import {AbstractDashboardTextFieldComponent} from '../abstract-dashboard-text-field.component'; import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-field-portal-data-injection-token"; import {TextField} from "../models/text-field"; +import {ValidationRegistryService} from "../../../registry/validation-registry.service"; @Component({ selector: 'ncc-abstract-dashboard-bar-chart-text-field', @@ -14,8 +15,9 @@ import {TextField} from "../models/text-field"; export abstract class AbstractDashboardBarChartTextFieldComponent extends AbstractDashboardTextFieldComponent { protected constructor(translate: TranslateService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(translate, dataFieldPortalData); + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(translate, dataFieldPortalData, _validationRegistry); } protected createCard(textFieldValue: string): CustomCard { diff --git a/projects/netgrif-components-core/src/lib/data-fields/text-field/dashboard-iframe-text-field/abstract-dashboard-iframe-text-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/text-field/dashboard-iframe-text-field/abstract-dashboard-iframe-text-field.component.ts index cf9638ab6..7b97547a7 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/text-field/dashboard-iframe-text-field/abstract-dashboard-iframe-text-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/text-field/dashboard-iframe-text-field/abstract-dashboard-iframe-text-field.component.ts @@ -5,6 +5,7 @@ import {CustomIframeCard} from '../../../dashboard/cards/model/custom-dashboard- import {AbstractDashboardTextFieldComponent} from '../abstract-dashboard-text-field.component'; import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-field-portal-data-injection-token"; import {TextField} from "../models/text-field"; +import {ValidationRegistryService} from "../../../registry/validation-registry.service"; @Component({ selector: 'ncc-abstract-dashboard-iframe-text-field', @@ -15,8 +16,9 @@ export abstract class AbstractDashboardIframeTextFieldComponent extends Abstract public card?: CustomIframeCard; protected constructor(translate: TranslateService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(translate, dataFieldPortalData); + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(translate, dataFieldPortalData, _validationRegistry); } protected createCard(textFieldValue: string): CustomIframeCard { diff --git a/projects/netgrif-components-core/src/lib/data-fields/text-field/dashboard-line-chart-text-field/abstract-dashboard-line-chart-text-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/text-field/dashboard-line-chart-text-field/abstract-dashboard-line-chart-text-field.component.ts index 273771e33..3a4a6062b 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/text-field/dashboard-line-chart-text-field/abstract-dashboard-line-chart-text-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/text-field/dashboard-line-chart-text-field/abstract-dashboard-line-chart-text-field.component.ts @@ -6,6 +6,7 @@ import {FilterType} from '../../../filter/models/filter-type'; import {AbstractDashboardTextFieldComponent} from '../abstract-dashboard-text-field.component'; import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-field-portal-data-injection-token"; import {TextField} from "../models/text-field"; +import {ValidationRegistryService} from "../../../registry/validation-registry.service"; @Component({ selector: 'ncc-abstract-dashboard-line-chart-text-field', @@ -14,8 +15,9 @@ import {TextField} from "../models/text-field"; export abstract class AbstractDashboardLineChartTextFieldComponent extends AbstractDashboardTextFieldComponent { protected constructor(translate: TranslateService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(translate, dataFieldPortalData); + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(translate, dataFieldPortalData, _validationRegistry); } protected createCard(textFieldValue: string): CustomCard { diff --git a/projects/netgrif-components-core/src/lib/data-fields/text-field/dashboard-pie-chart-text-field/abstract-dashboard-pie-chart-text-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/text-field/dashboard-pie-chart-text-field/abstract-dashboard-pie-chart-text-field.component.ts index 8db44342e..fc4ddb0af 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/text-field/dashboard-pie-chart-text-field/abstract-dashboard-pie-chart-text-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/text-field/dashboard-pie-chart-text-field/abstract-dashboard-pie-chart-text-field.component.ts @@ -6,6 +6,7 @@ import {FilterType} from '../../../filter/models/filter-type'; import {AbstractDashboardTextFieldComponent} from '../abstract-dashboard-text-field.component'; import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-field-portal-data-injection-token"; import {TextField} from "../models/text-field"; +import {ValidationRegistryService} from "../../../registry/validation-registry.service"; @Component({ selector: 'ncc-abstract-dashboard-pie-chart-text-field', @@ -14,8 +15,9 @@ import {TextField} from "../models/text-field"; export abstract class AbstractDashboardPieChartTextFieldComponent extends AbstractDashboardTextFieldComponent { protected constructor(translate: TranslateService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(translate, dataFieldPortalData); + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(translate, dataFieldPortalData, _validationRegistry); } protected createCard(textFieldValue: string): CustomCard { diff --git a/projects/netgrif-components-core/src/lib/data-fields/text-field/dashboard-portal-text-field/abstract-dashboard-portal-text-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/text-field/dashboard-portal-text-field/abstract-dashboard-portal-text-field.component.ts index 1335a7f61..f41978521 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/text-field/dashboard-portal-text-field/abstract-dashboard-portal-text-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/text-field/dashboard-portal-text-field/abstract-dashboard-portal-text-field.component.ts @@ -5,6 +5,7 @@ import {DashboardCardTypes} from '../../../dashboard/cards/model/dashboard-card- import {AbstractDashboardTextFieldComponent} from '../abstract-dashboard-text-field.component'; import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-field-portal-data-injection-token"; import {TextField} from "../models/text-field"; +import {ValidationRegistryService} from "../../../registry/validation-registry.service"; @Component({ selector: 'ncc-abstract-dashboard-pie-chart-text-field', @@ -13,8 +14,9 @@ import {TextField} from "../models/text-field"; export abstract class AbstractDashboardPortalTextFieldComponent extends AbstractDashboardTextFieldComponent { protected constructor(translate: TranslateService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(translate, dataFieldPortalData); + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(translate, dataFieldPortalData, _validationRegistry); } protected createCard(textFieldValue: string): CustomCard { diff --git a/projects/netgrif-components-core/src/lib/data-fields/text-field/html-textarea-field/abstract-html-textarea-field.component.spec.ts b/projects/netgrif-components-core/src/lib/data-fields/text-field/html-textarea-field/abstract-html-textarea-field.component.spec.ts index e8116734a..9e26a6bf5 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/text-field/html-textarea-field/abstract-html-textarea-field.component.spec.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/text-field/html-textarea-field/abstract-html-textarea-field.component.spec.ts @@ -22,6 +22,10 @@ import {DomSanitizer} from '@angular/platform-browser'; import {TextAreaField} from '../models/text-area-field'; import {QuillModule} from 'ngx-quill'; import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-field-portal-data-injection-token"; +import {Validator} from "../../../registry/model/validator"; +import {minLengthValidation} from "../../models/validation-functions"; +import {ValidationRegistryService} from "../../../registry/validation-registry.service"; +import {DataFieldsModule} from "../../data-fields.module"; describe('AbstractHtmlTextareaFieldComponent', () => { let component: TestTextComponent; @@ -36,7 +40,8 @@ describe('AbstractHtmlTextareaFieldComponent', () => { CovalentModule, TranslateLibModule, HttpClientTestingModule, - QuillModule.forRoot() + QuillModule.forRoot(), + DataFieldsModule ], providers: [ {provide: AuthenticationMethodService, useClass: MockAuthenticationMethodService}, @@ -46,7 +51,10 @@ describe('AbstractHtmlTextareaFieldComponent', () => { {provide: DATA_FIELD_PORTAL_DATA, useValue: { dataField: new TextAreaField('', '', 'text', { editable: true - }, undefined, undefined, undefined, [{validationRule: 'regex 5', validationMessage: 'This is custom message!'}]), + }, undefined, undefined, undefined, [{name: 'minlength', validationMessage: 'This is custom message!', arguments: {'length': {key: 'length', value: '5', dynamic: false}}}], + undefined, + undefined, + new Map([['minlength', minLengthValidation]])), formControlRef: new FormControl(), showLargeLayout: new WrappedBoolean() } as DataFieldPortalData @@ -79,9 +87,10 @@ describe('AbstractHtmlTextareaFieldComponent', () => { template: '' }) class TestTextComponent extends AbstractHtmlTextareaFieldComponent { - constructor(protected _translate: TranslateService, protected _sanitizer: DomSanitizer, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(_translate, _sanitizer, dataFieldPortalData); + constructor(_translate: TranslateService, protected _sanitizer: DomSanitizer, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(_translate, _sanitizer, dataFieldPortalData, _validationRegistry); } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/text-field/html-textarea-field/abstract-html-textarea-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/text-field/html-textarea-field/abstract-html-textarea-field.component.ts index 8008bd31d..25eec1c2d 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/text-field/html-textarea-field/abstract-html-textarea-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/text-field/html-textarea-field/abstract-html-textarea-field.component.ts @@ -4,6 +4,7 @@ import {AbstractTextErrorsComponent} from '../abstract-text-errors.component'; import {TextAreaField} from '../models/text-area-field'; import {DomSanitizer, SafeHtml} from '@angular/platform-browser'; import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-field-portal-data-injection-token"; +import {ValidationRegistryService} from "../../../registry/validation-registry.service"; @Component({ selector: 'ncc-abstract-html-area-field', @@ -33,9 +34,10 @@ export abstract class AbstractHtmlTextareaFieldComponent extends AbstractTextErr public disabledDisplay: SafeHtml; - constructor(protected _translate: TranslateService, protected _sanitizer: DomSanitizer, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(_translate, dataFieldPortalData); + constructor(_translate: TranslateService, protected _sanitizer: DomSanitizer, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(_translate, dataFieldPortalData, _validationRegistry); } ngOnInit(): void { @@ -48,8 +50,4 @@ export abstract class AbstractHtmlTextareaFieldComponent extends AbstractTextErr protected sanitizeValue(): SafeHtml { return this._sanitizer.bypassSecurityTrustHtml(this.dataField.value !== undefined ? this.dataField.value : ''); } - - public getErrorMessage() { - return this.buildErrorMessage(this.dataField, this.formControlRef); - } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/text-field/models/text-area-field.ts b/projects/netgrif-components-core/src/lib/data-fields/text-field/models/text-area-field.ts index e4639aff5..444ad0716 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/text-field/models/text-area-field.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/text-field/models/text-area-field.ts @@ -5,13 +5,15 @@ import {TextField} from './text-field'; import {Observable} from 'rxjs'; import {debounceTime} from 'rxjs/operators'; import {Component} from '../../models/component'; +import {Validator} from "../../../registry/model/validator"; export class TextAreaField extends TextField { private SEARCH_DEBOUNCE_TIME = 600; constructor(stringId: string, title: string, value: string, behavior: Behavior, placeholder?: string, description?: string, - layout?: Layout, validations?: Array, component?: Component, parentTaskId?: string) { - super(stringId, title, value, behavior, placeholder, description, layout, validations, component, parentTaskId); + layout?: Layout, validations?: Array, component?: Component, parentTaskId?: string, + validatorRegister?: Map) { + super(stringId, title, value, behavior, placeholder, description, layout, validations, component, parentTaskId, validatorRegister); } public valueChanges(): Observable { diff --git a/projects/netgrif-components-core/src/lib/data-fields/text-field/models/text-field.ts b/projects/netgrif-components-core/src/lib/data-fields/text-field/models/text-field.ts index eab924946..9669022cb 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/text-field/models/text-field.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/text-field/models/text-field.ts @@ -4,6 +4,8 @@ import {Layout} from '../../models/layout'; import {Validation} from '../../models/validation'; import {Component, ComponentPrefixes} from '../../models/component'; import {DataField} from '../../models/abstract-data-field'; +import {Injector} from "@angular/core"; +import {Validator} from "../../../registry/model/validator"; export enum TextFieldView { DEFAULT = 'default', @@ -50,54 +52,12 @@ export class TextField extends DataField { constructor(stringId: string, title: string, value: string, behavior: Behavior, placeholder?: string, description?: string, layout?: Layout, validations?: Array, _component?: Component, - parentTaskId?: string) { - super(stringId, title, value, behavior, placeholder, description, layout, validations, _component, parentTaskId); + parentTaskId?: string, validatorRegister?: Map) { + super(stringId, title, value, behavior, placeholder, description, layout, validations, _component, parentTaskId, + undefined, validatorRegister); } public getTypedComponentType(): string { return ComponentPrefixes.TEXT + this.getComponentType(); } - protected resolveValidations(): Array { - const result = []; - - this.validations.forEach(item => { - if (item.validationRule.includes(TextFieldValidation.MIN_LENGTH)) { - const tmp = item.validationRule.split(' '); - if (tmp[1] !== undefined) { - const length = parseInt(tmp[1], 10); - if (!isNaN(length)) { - result.push(Validators.minLength(length)); - } - } - } else if (item.validationRule.includes(TextFieldValidation.MAX_LENGTH)) { - const tmp = item.validationRule.split(' '); - if (tmp[1] !== undefined) { - const length = parseInt(tmp[1], 10); - if (!isNaN(length)) { - result.push(Validators.maxLength(length)); - } - } - } else if (item.validationRule.includes(TextFieldValidation.REGEX)) { - if (item.validationRule.startsWith('regex ')) { - result.push(Validators.pattern(new RegExp(item.validationRule.substring(6, item.validationRule.length )))); - } else if (item.validationRule.startsWith('regex("')) { - result.push(Validators.pattern(new RegExp(item.validationRule.substring(7, item.validationRule.length - 2)))); - } - } else if (item.validationRule.includes(TextFieldValidation.EMAIL)) { - result.push(Validators.email); - } else if (item.validationRule.includes(TextFieldValidation.TEL_NUMBER)) { - result.push(this.validTelNumber); - } - }); - - return result; - } - - private validTelNumber(fc: FormControl) { - if (!(new RegExp(/^(?:\+?(\d{1,3}))?([-. (]*(\d{3})[-. )]*)?((\d{3})[-. ]*(\d{2,4})(?:[-.x ]*(\d+))?)$/).test(fc.value))) { - return ({validTelNumber: true}); - } else { - return null; - } - } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/text-field/password-text-field/abstract-password-text-field.component.spec.ts b/projects/netgrif-components-core/src/lib/data-fields/text-field/password-text-field/abstract-password-text-field.component.spec.ts index c93060a97..53825b79a 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/text-field/password-text-field/abstract-password-text-field.component.spec.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/text-field/password-text-field/abstract-password-text-field.component.spec.ts @@ -19,6 +19,10 @@ import {TextField} from '../models/text-field'; import {TranslateService} from '@ngx-translate/core'; import {AbstractPasswordTextFieldComponent} from './abstract-password-text-field.component'; import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-field-portal-data-injection-token"; +import {Validator} from "../../../registry/model/validator"; +import {minLengthValidation} from "../../models/validation-functions"; +import {ValidationRegistryService} from "../../../registry/validation-registry.service"; +import {DataFieldsModule} from "../../data-fields.module"; describe('AbstractPasswordTextFieldComponent', () => { let component: TestPasswordTextComponent; @@ -31,7 +35,8 @@ describe('AbstractPasswordTextFieldComponent', () => { AngularResizeEventModule, BrowserAnimationsModule, TranslateLibModule, - HttpClientTestingModule + HttpClientTestingModule, + DataFieldsModule ], providers: [ {provide: AuthenticationMethodService, useClass: MockAuthenticationMethodService}, @@ -45,7 +50,10 @@ describe('AbstractPasswordTextFieldComponent', () => { visible: true, editable: true, hidden: true - }, undefined, undefined, undefined, [{validationRule: 'minLength 5', validationMessage: 'This is custom message!'}]), + }, undefined, undefined, undefined, [{name: 'minlength', validationMessage: 'This is custom message!', arguments: {'length': {key: 'length', value: '5', dynamic: false}}}], + undefined, + undefined, + new Map([['minlength', minLengthValidation]])), formControlRef: new FormControl(), showLargeLayout: new WrappedBoolean() } as DataFieldPortalData @@ -78,9 +86,10 @@ describe('AbstractPasswordTextFieldComponent', () => { template: '' }) class TestPasswordTextComponent extends AbstractPasswordTextFieldComponent { - constructor(protected _translate: TranslateService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(_translate, dataFieldPortalData); + constructor(_translate: TranslateService, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(_translate, dataFieldPortalData, _validationRegistry); } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/text-field/password-text-field/abstract-password-text-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/text-field/password-text-field/abstract-password-text-field.component.ts index f509a4e6f..651dfe41a 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/text-field/password-text-field/abstract-password-text-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/text-field/password-text-field/abstract-password-text-field.component.ts @@ -2,6 +2,7 @@ import {Component, Inject, Optional} from '@angular/core'; import {TextField} from '../models/text-field'; import {TranslateService} from '@ngx-translate/core'; import {AbstractTextErrorsComponent} from '../abstract-text-errors.component'; +import {ValidationRegistryService} from "../../../registry/validation-registry.service"; import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-field-portal-data-injection-token"; @Component({ @@ -10,12 +11,9 @@ import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-fie }) export abstract class AbstractPasswordTextFieldComponent extends AbstractTextErrorsComponent { - constructor(protected _translate: TranslateService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(_translate, dataFieldPortalData); - } - - public getErrorMessage() { - return this.buildErrorMessage(this.dataField, this.formControlRef); + constructor(_translate: TranslateService, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(_translate, dataFieldPortalData, _validationRegistry); } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/text-field/rich-textarea-field/abstract-rich-textarea-field.component.spec.ts b/projects/netgrif-components-core/src/lib/data-fields/text-field/rich-textarea-field/abstract-rich-textarea-field.component.spec.ts index cc031d3ca..37fd4fc4b 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/text-field/rich-textarea-field/abstract-rich-textarea-field.component.spec.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/text-field/rich-textarea-field/abstract-rich-textarea-field.component.spec.ts @@ -20,6 +20,10 @@ import {CovalentModule} from '../../../covalent/covalent.module'; import {MaterialModule} from '../../../material/material.module'; import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-field-portal-data-injection-token"; import {TextAreaField} from "../models/text-area-field"; +import {Validator} from "../../../registry/model/validator"; +import {minLengthValidation} from "../../models/validation-functions"; +import {ValidationRegistryService} from "../../../registry/validation-registry.service"; +import {DataFieldsModule} from "../../data-fields.module"; describe('AbstractRichTextareaFieldComponent', () => { let component: TestTextComponent; @@ -33,7 +37,8 @@ describe('AbstractRichTextareaFieldComponent', () => { CovalentModule, NoopAnimationsModule, TranslateLibModule, - HttpClientTestingModule + HttpClientTestingModule, + DataFieldsModule ], providers: [ {provide: AuthenticationMethodService, useClass: MockAuthenticationMethodService}, @@ -43,7 +48,11 @@ describe('AbstractRichTextareaFieldComponent', () => { {provide: DATA_FIELD_PORTAL_DATA, useValue: { dataField: new TextAreaField('', '', 'text', { editable: true - }, undefined, undefined, undefined, [{validationRule: 'regex 5', validationMessage: 'This is custom message!'}]), + }, undefined, undefined, undefined, + [{name: 'minlength', validationMessage: 'This is custom message!', arguments: {'length': {key: 'length', value: '5', dynamic: false}}}], + undefined, + undefined, + new Map([['minlength', minLengthValidation]])), formControlRef: new FormControl(), showLargeLayout: new WrappedBoolean() } as DataFieldPortalData @@ -76,9 +85,10 @@ describe('AbstractRichTextareaFieldComponent', () => { template: '' }) class TestTextComponent extends AbstractRichTextareaFieldComponent { - constructor(protected _translate: TranslateService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(_translate, dataFieldPortalData); + constructor(_translate: TranslateService, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(_translate, dataFieldPortalData, _validationRegistry); } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/text-field/rich-textarea-field/abstract-rich-textarea-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/text-field/rich-textarea-field/abstract-rich-textarea-field.component.ts index b8245d6dd..d349b942e 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/text-field/rich-textarea-field/abstract-rich-textarea-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/text-field/rich-textarea-field/abstract-rich-textarea-field.component.ts @@ -3,6 +3,7 @@ import {TranslateService} from '@ngx-translate/core'; import {AbstractTextErrorsComponent} from '../abstract-text-errors.component'; import {TextAreaField} from '../models/text-area-field'; import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-field-portal-data-injection-token"; +import {ValidationRegistryService} from "../../../registry/validation-registry.service"; @Component({ selector: 'ncc-abstract-rich-text-field', @@ -11,12 +12,9 @@ import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-fie export abstract class AbstractRichTextareaFieldComponent extends AbstractTextErrorsComponent { // TODO BUG: update on blur dont working, switch back to update on ngModel - constructor(protected _translate: TranslateService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(_translate, dataFieldPortalData); - } - - public getErrorMessage() { - return this.buildErrorMessage(this.dataField, this.formControlRef); + constructor(_translate: TranslateService, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(_translate, dataFieldPortalData, _validationRegistry); } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/text-field/simple-text-field/abstract-simple-text-field.component.spec.ts b/projects/netgrif-components-core/src/lib/data-fields/text-field/simple-text-field/abstract-simple-text-field.component.spec.ts index 15d82cdf1..7064606d2 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/text-field/simple-text-field/abstract-simple-text-field.component.spec.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/text-field/simple-text-field/abstract-simple-text-field.component.spec.ts @@ -19,6 +19,10 @@ import {TextField} from '../models/text-field'; import {TranslateService} from '@ngx-translate/core'; import {AbstractSimpleTextFieldComponent} from './abstract-simple-text-field.component'; import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-field-portal-data-injection-token"; +import {Validator} from "../../../registry/model/validator"; +import {minLengthValidation} from "../../models/validation-functions"; +import {ValidationRegistryService} from "../../../registry/validation-registry.service"; +import {DataFieldsModule} from "../../data-fields.module"; describe('AbstractSimpleTextFieldComponent', () => { let component: TestTextComponent; @@ -31,7 +35,8 @@ describe('AbstractSimpleTextFieldComponent', () => { AngularResizeEventModule, NoopAnimationsModule, TranslateLibModule, - HttpClientTestingModule + HttpClientTestingModule, + DataFieldsModule ], providers: [ {provide: AuthenticationMethodService, useClass: MockAuthenticationMethodService}, @@ -45,7 +50,10 @@ describe('AbstractSimpleTextFieldComponent', () => { visible: true, editable: true, hidden: true - }, undefined, undefined, undefined, [{validationRule: 'minLength 5', validationMessage: 'This is custom message!'}]), + }, undefined, undefined, undefined, [{name: 'minlength', validationMessage: 'This is custom message!', arguments: {'length': {key: 'length', value: '5', dynamic: false}}}], + undefined, + undefined, + new Map([['minlength', minLengthValidation]])), formControlRef: new FormControl(), showLargeLayout: new WrappedBoolean() } as DataFieldPortalData @@ -78,9 +86,10 @@ describe('AbstractSimpleTextFieldComponent', () => { template: '' }) class TestTextComponent extends AbstractSimpleTextFieldComponent { - constructor(protected _translate: TranslateService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(_translate, dataFieldPortalData); + constructor(_translate: TranslateService, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(_translate, dataFieldPortalData, _validationRegistry); } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/text-field/simple-text-field/abstract-simple-text-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/text-field/simple-text-field/abstract-simple-text-field.component.ts index 98d9fb3f0..45f29175a 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/text-field/simple-text-field/abstract-simple-text-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/text-field/simple-text-field/abstract-simple-text-field.component.ts @@ -3,6 +3,7 @@ import {TextField} from '../models/text-field'; import {TranslateService} from '@ngx-translate/core'; import {AbstractTextErrorsComponent} from '../abstract-text-errors.component'; import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-field-portal-data-injection-token"; +import {ValidationRegistryService} from "../../../registry/validation-registry.service"; @Component({ selector: 'ncc-abstract-simple-text-field', @@ -10,12 +11,9 @@ import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-fie }) export abstract class AbstractSimpleTextFieldComponent extends AbstractTextErrorsComponent { - constructor(protected _translate: TranslateService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(_translate, dataFieldPortalData); - } - - public getErrorMessage() { - return this.buildErrorMessage(this.dataField, this.formControlRef); + constructor(_translate: TranslateService, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(_translate, dataFieldPortalData, _validationRegistry); } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/text-field/textarea-field/abstract-textarea-field.component.spec.ts b/projects/netgrif-components-core/src/lib/data-fields/text-field/textarea-field/abstract-textarea-field.component.spec.ts index ef320bb4f..8630dc9f7 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/text-field/textarea-field/abstract-textarea-field.component.spec.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/text-field/textarea-field/abstract-textarea-field.component.spec.ts @@ -20,6 +20,10 @@ import {MaterialModule} from '../../../material/material.module'; import {TranslateService} from '@ngx-translate/core'; import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-field-portal-data-injection-token"; import {TextAreaField} from "../models/text-area-field"; +import {Validator} from "../../../registry/model/validator"; +import {minLengthValidation, requiredTrueValidation} from "../../models/validation-functions"; +import {ValidationRegistryService} from "../../../registry/validation-registry.service"; +import {DataFieldsModule} from "../../data-fields.module"; describe('AbstractTextareaFieldComponent', () => { let component: TestTextComponent; @@ -32,7 +36,8 @@ describe('AbstractTextareaFieldComponent', () => { AngularResizeEventModule, NoopAnimationsModule, TranslateLibModule, - HttpClientTestingModule + HttpClientTestingModule, + DataFieldsModule ], providers: [ {provide: AuthenticationMethodService, useClass: MockAuthenticationMethodService}, @@ -46,7 +51,11 @@ describe('AbstractTextareaFieldComponent', () => { visible: true, editable: true, hidden: true - }, undefined, undefined, undefined, [{validationRule: 'minLength 5', validationMessage: 'This is custom message!'}]), + }, undefined, undefined, undefined, + [{name: 'minlength', validationMessage: 'This is custom message!', arguments: {'length': {key: 'length', value: '5', dynamic: false}}}], + undefined, + undefined, + new Map([['minlength', minLengthValidation]])), formControlRef: new FormControl(), showLargeLayout: new WrappedBoolean() } as DataFieldPortalData @@ -88,9 +97,10 @@ describe('AbstractTextareaFieldComponent', () => { ' cdkAutosizeMinRows="1">' }) class TestTextComponent extends AbstractTextareaFieldComponent { - constructor(protected _translate: TranslateService, protected _ngZone: NgZone, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(_translate, _ngZone, dataFieldPortalData); + constructor(_translate: TranslateService, protected _ngZone: NgZone, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _registryService: ValidationRegistryService) { + super(_translate, _ngZone, dataFieldPortalData, _registryService); } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/text-field/textarea-field/abstract-textarea-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/text-field/textarea-field/abstract-textarea-field.component.ts index 791cbcbfb..4f71ecf47 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/text-field/textarea-field/abstract-textarea-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/text-field/textarea-field/abstract-textarea-field.component.ts @@ -5,6 +5,7 @@ import {TranslateService} from '@ngx-translate/core'; import {take} from 'rxjs/operators'; import {CdkTextareaAutosize} from '@angular/cdk/text-field'; import {AbstractTextErrorsComponent} from '../abstract-text-errors.component'; +import {ValidationRegistryService} from "../../../registry/validation-registry.service"; import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-field-portal-data-injection-token"; import {TextAreaField} from "../models/text-area-field"; @@ -17,9 +18,10 @@ export abstract class AbstractTextareaFieldComponent extends AbstractTextErrorsC @ViewChild('dynamicTextArea') dynamicTextArea: CdkTextareaAutosize; @ViewChild('textArea') textArea: ElementRef; - constructor(protected _translate: TranslateService, protected _ngZone: NgZone, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(_translate, dataFieldPortalData); + constructor(_translate: TranslateService, protected _ngZone: NgZone, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(_translate, dataFieldPortalData, _validationRegistry); } ngAfterViewInit() { @@ -41,8 +43,4 @@ export abstract class AbstractTextareaFieldComponent extends AbstractTextErrorsC this._ngZone.onStable.pipe(take(1)) .subscribe(() => this.dynamicTextArea.resizeToFitContent(true)); } - - public getErrorMessage() { - return this.buildErrorMessage(this.dataField, this.formControlRef); - } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/time-instance-abstract-field/abstract-time-instance-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/time-instance-abstract-field/abstract-time-instance-field.component.ts index 058bd613d..12576ff09 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/time-instance-abstract-field/abstract-time-instance-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/time-instance-abstract-field/abstract-time-instance-field.component.ts @@ -1,8 +1,8 @@ -import {AbstractTimeInstanceField, AbstractTimeInstanceFieldValidation} from './models/abstract-time-instance-field'; +import {AbstractTimeInstanceField} from './models/abstract-time-instance-field'; import {TranslateService} from '@ngx-translate/core'; -import moment, {Moment} from 'moment'; import {AbstractBaseDataFieldComponent} from "../base-component/abstract-base-data-field.component"; import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../models/data-field-portal-data-injection-token"; +import {ValidationRegistryService} from "../../registry/validation-registry.service"; import {Component, Inject, OnDestroy, Optional} from '@angular/core'; import {DateAdapter, MAT_DATE_LOCALE} from '@angular/material/core'; import {LanguageService} from '../../translate/language.service'; @@ -15,12 +15,13 @@ import {Subscription} from 'rxjs'; export abstract class AbstractTimeInstanceFieldComponent extends AbstractBaseDataFieldComponent implements OnDestroy { protected _subLang: Subscription; - protected constructor(protected _translate: TranslateService, + protected constructor(_translate: TranslateService, protected _adapter: DateAdapter, @Inject(MAT_DATE_LOCALE) protected _locale: string, protected _languageService: LanguageService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(dataFieldPortalData); + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(_translate, dataFieldPortalData, _validationRegistry); if (this._locale !== this._languageService.getLanguage()) { this.setLangToAdapter(this._languageService.getLanguage()); } @@ -30,6 +31,7 @@ export abstract class AbstractTimeInstanceFieldComponent - value.validationRule.includes(AbstractTimeInstanceFieldValidation.BETWEEN) - ).validationRule.split(' '); - const parts = tmp[1].split(','); - let left = AbstractTimeInstanceField.parseDate(parts[0]); - let right = AbstractTimeInstanceField.parseDate(parts[1]); - left = moment.isMoment(left) ? (left as Moment).format('DD.MM.YYYY HH:mm:ss') : left; - right = moment.isMoment(right) ? (right as Moment).format('DD.MM.YYYY HH:mm:ss') : right; - if (left === 'past') { - return this.resolveErrorMessage(dataField, AbstractTimeInstanceFieldValidation.BETWEEN, - this._translate.instant('dataField.validations.datePast', {right})); - } - if (right === 'future') { - return this.resolveErrorMessage(dataField, AbstractTimeInstanceFieldValidation.BETWEEN, - this._translate.instant('dataField.validations.dateFuture', {left})); - } - return this.resolveErrorMessage(dataField, AbstractTimeInstanceFieldValidation.BETWEEN, - this._translate.instant('dataField.validations.dateRange', {left, right})); - } - if (this.formControlRef.hasError(AbstractTimeInstanceFieldValidation.VALID_WORKDAY)) { - return this.resolveErrorMessage( - dataField, AbstractTimeInstanceFieldValidation.WORKDAY, this._translate.instant('dataField.validations.workday') - ); - } - if (this.formControlRef.hasError(AbstractTimeInstanceFieldValidation.VALID_WEEKEND)) { - return this.resolveErrorMessage( - dataField, AbstractTimeInstanceFieldValidation.WEEKEND, this._translate.instant('dataField.validations.weekend') - ); - } - return ''; - } - - protected resolveErrorMessage(dataField: AbstractTimeInstanceField, search: string, generalMessage: string) { - const validation = dataField.validations.find(value => value.validationRule.includes(search)); - if (validation.validationMessage && validation.validationMessage !== '') { - return validation.validationMessage; - } - return generalMessage; - } - } diff --git a/projects/netgrif-components-core/src/lib/data-fields/time-instance-abstract-field/models/abstract-time-instance-field.ts b/projects/netgrif-components-core/src/lib/data-fields/time-instance-abstract-field/models/abstract-time-instance-field.ts index 4639ed020..f228df2cd 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/time-instance-abstract-field/models/abstract-time-instance-field.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/time-instance-abstract-field/models/abstract-time-instance-field.ts @@ -4,6 +4,7 @@ import moment, {Moment} from 'moment'; import {Layout} from '../../models/layout'; import {Component} from '../../models/component'; import {DataField} from '../../models/abstract-data-field'; +import {Validator} from "../../../registry/model/validator"; export enum AbstractTimeInstanceFieldValidation { BETWEEN = 'between', @@ -21,8 +22,10 @@ export abstract class AbstractTimeInstanceField extends DataField { public max: Moment; protected constructor(stringId: string, title: string, value: Moment, behavior: Behavior, placeholder?: string, - description?: string, layout?: Layout, validations?: any, component?: Component, parentTaskId?: string) { - super(stringId, title, value, behavior, placeholder, description, layout, validations, component, parentTaskId); + description?: string, layout?: Layout, validations?: any, component?: Component, parentTaskId?: string, + validatorRegister?: Map) { + super(stringId, title, value, behavior, placeholder, description, layout, validations, component, parentTaskId, + undefined, validatorRegister); } public static isEqual(a: Moment, b: Moment, granularity?: moment.unitOfTime.StartOf): boolean { @@ -62,58 +65,21 @@ export abstract class AbstractTimeInstanceField extends DataField { } protected resolveValidations(): Array { - const result = []; + const result = super.resolveValidations(); this.validations.forEach(item => { - if (item.validationRule.includes(AbstractTimeInstanceFieldValidation.BETWEEN)) { - const tmp = item.validationRule.split(' '); - const ranges = tmp[1].split(','); - - const start = AbstractTimeInstanceField.parseDate(ranges[0]); - const end = AbstractTimeInstanceField.parseDate(ranges[1]); - - if (start && end) { - if (start === 'past' && moment(end).isValid()) { - result.push(this.validFromPast(moment(end))); - this.max = moment(end); - } else if (end === 'future' && moment(start).isValid()) { - result.push(this.validToFuture(moment(start))); - this.min = moment(start); - } else if (moment(start).isValid() && moment(end).isValid()) { - result.push(this.validBetween(moment(start), moment(end))); - this.min = moment(start); - this.max = moment(end); - } + if (item.name === AbstractTimeInstanceFieldValidation.BETWEEN) { + const start = AbstractTimeInstanceField.parseDate(item.arguments.from.value); + const end = AbstractTimeInstanceField.parseDate(item.arguments.to.value); + if (!!end && moment(end).isValid()) { + this.max = moment(end); + } + if (!!start && moment(start).isValid()) { + this.min = moment(start); } - } else if (item.validationRule.includes(AbstractTimeInstanceFieldValidation.WORKDAY)) { - result.push(this.validWorkday); - } else if (item.validationRule.includes(AbstractTimeInstanceFieldValidation.WEEKEND)) { - result.push(this.validWeekend); } }); return result; } - - protected validFromPast(range: Moment): ValidatorFn { - return (fc: FormControl): { [key: string]: any } | null => fc.value > range ? {validBetween: true} : null; - } - - protected validToFuture(range: Moment): ValidatorFn { - return (fc: FormControl): { [key: string]: any } | null => fc.value < range ? {validBetween: true} : null; - } - - protected validBetween(first: Moment, second: Moment): ValidatorFn { - return (fc: FormControl): { [key: string]: any } | null => fc.value < first || fc.value > second ? {validBetween: true} : null; - } - - protected validWorkday(fc: FormControl) { - const dayOfWeek = !!fc.value ? fc.value.isoWeekday() : null; - return dayOfWeek === 6 || dayOfWeek === 7 ? {validWorkday: true} : null; - } - - protected validWeekend(fc: FormControl) { - const dayOfWeek = !!fc.value ? fc.value.isoWeekday() : null; - return dayOfWeek >= 1 && dayOfWeek <= 5 ? {validWeekend: true} : null; - } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/user-field/user-default-field/abstract-user-default-field.component.spec.ts b/projects/netgrif-components-core/src/lib/data-fields/user-field/user-default-field/abstract-user-default-field.component.spec.ts index 2ec83a3b5..117e8e341 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/user-field/user-default-field/abstract-user-default-field.component.spec.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/user-field/user-default-field/abstract-user-default-field.component.spec.ts @@ -15,6 +15,7 @@ import {AbstractUserDefaultFieldComponent} from "./abstract-user-default-field.c import {FormControl} from "@angular/forms"; import {WrappedBoolean} from "../../data-field-template/models/wrapped-boolean"; import {MatDialog} from '@angular/material/dialog'; +import {ValidationRegistryService} from "../../../registry/validation-registry.service"; describe('AbstractUserDefaultFieldComponent', () => { let component: TestUserComponent; @@ -72,8 +73,9 @@ class TestUserComponent extends AbstractUserDefaultFieldComponent { constructor(matDialog: MatDialog, snackbar: SnackBarService, translate: TranslateService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(matDialog, snackbar, translate, dataFieldPortalData); + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(matDialog, snackbar, translate, dataFieldPortalData, _validationRegistry); } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/user-field/user-default-field/abstract-user-default-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/user-field/user-default-field/abstract-user-default-field.component.ts index 5a62b55a1..fca607469 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/user-field/user-default-field/abstract-user-default-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/user-field/user-default-field/abstract-user-default-field.component.ts @@ -7,6 +7,7 @@ import {UserValue} from "../models/user-value"; import {UserField} from "../models/user-field"; import {AbstractBaseDataFieldComponent} from "../../base-component/abstract-base-data-field.component"; import {MatDialog} from '@angular/material/dialog'; +import {ValidationRegistryService} from "../../../registry/validation-registry.service"; @Component({ selector: 'ncc-abstract-user-default-field', @@ -27,9 +28,10 @@ export abstract class AbstractUserDefaultFieldComponent extends AbstractBaseData */ protected constructor(protected _dialog: MatDialog, protected _snackbar: SnackBarService, - protected _translate: TranslateService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(dataFieldPortalData); + _translate: TranslateService, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistryService: ValidationRegistryService) { + super(_translate, dataFieldPortalData, _validationRegistryService); } /** @@ -49,12 +51,12 @@ export abstract class AbstractUserDefaultFieldComponent extends AbstractBaseData if ($event.data) { this.dataField.value = $event.data as UserValue; this._snackbar.openGenericSnackBar( - this._translate.instant('dataField.snackBar.userAssigned', {userName: this.dataField.value.fullName}), + this.translate.instant('dataField.snackBar.userAssigned', {userName: this.dataField.value.fullName}), 'how_to_reg' ); valueReturned = true; } else if (!valueReturned) { - this._snackbar.openWarningSnackBar(this._translate.instant('dataField.snackBar.notSelectedUser')); + this._snackbar.openWarningSnackBar(this.translate.instant('dataField.snackBar.notSelectedUser')); } }); } diff --git a/projects/netgrif-components-core/src/lib/data-fields/user-list-field/user-list-default-field/abstract-user-list-default-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/user-list-field/user-list-default-field/abstract-user-list-default-field.component.ts index c72e492b2..f8587d5e8 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/user-list-field/user-list-default-field/abstract-user-list-default-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/user-list-field/user-list-default-field/abstract-user-list-default-field.component.ts @@ -17,9 +17,9 @@ export abstract class AbstractUserListDefaultFieldComponent extends AbstractBase protected constructor(protected _dialog: MatDialog, protected _snackbar: SnackBarService, - protected _translate: TranslateService, + _translate: TranslateService, @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(dataFieldPortalData); + super(_translate, dataFieldPortalData); } /** @@ -39,13 +39,13 @@ export abstract class AbstractUserListDefaultFieldComponent extends AbstractBase if ($event?.data) { this.dataField.value = new UserListValue(new Map(($event.data as Array).map(v => [v.id, v]))); this._snackbar.openGenericSnackBar( - this._translate.instant('dataField.snackBar.userListAssigned', + this.translate.instant('dataField.snackBar.userListAssigned', {userNames: this.dataField.value.toString()}), 'how_to_reg' ); valueReturned = true; } else if (!valueReturned) { - this._snackbar.openWarningSnackBar(this._translate.instant('dataField.snackBar.notSelectedUser')); + this._snackbar.openWarningSnackBar(this.translate.instant('dataField.snackBar.notSelectedUser')); } }); } diff --git a/projects/netgrif-components-core/src/lib/registry/model/validator.ts b/projects/netgrif-components-core/src/lib/registry/model/validator.ts new file mode 100644 index 000000000..e277af56a --- /dev/null +++ b/projects/netgrif-components-core/src/lib/registry/model/validator.ts @@ -0,0 +1,11 @@ +import {ValidatorFn} from "@angular/forms"; +import {FieldTypeResource} from "../../task-content/model/field-type-resource"; + +export interface Validator { + key: string; + attributeNames: string[]; + fn: (...args: string[]) => ValidatorFn; + validationErrorKey: string; + defaultErrorMessage: (...args: string[]) => string; + defaultErrorMessageParams?: Object; +} diff --git a/projects/netgrif-components-core/src/lib/registry/public-api.ts b/projects/netgrif-components-core/src/lib/registry/public-api.ts index 6badff2dd..7146d6ae9 100644 --- a/projects/netgrif-components-core/src/lib/registry/public-api.ts +++ b/projects/netgrif-components-core/src/lib/registry/public-api.ts @@ -1,2 +1,7 @@ +/* Service */ export * from './component-registry.service' +export * from './validation-registry.service' export * from './front-action-registry.service' + +/* Model */ +export * from './model/validator' diff --git a/projects/netgrif-components-core/src/lib/registry/validation-registry.service.spec.ts b/projects/netgrif-components-core/src/lib/registry/validation-registry.service.spec.ts new file mode 100644 index 000000000..31eebfc16 --- /dev/null +++ b/projects/netgrif-components-core/src/lib/registry/validation-registry.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { ValidationRegistryService } from './validation-registry.service'; + +describe('ValidationRegistryService', () => { + let service: ValidationRegistryService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(ValidationRegistryService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/projects/netgrif-components-core/src/lib/registry/validation-registry.service.ts b/projects/netgrif-components-core/src/lib/registry/validation-registry.service.ts new file mode 100644 index 000000000..c5857df56 --- /dev/null +++ b/projects/netgrif-components-core/src/lib/registry/validation-registry.service.ts @@ -0,0 +1,48 @@ +import {Injectable} from '@angular/core'; +import {Validator} from "./model/validator"; +import {FieldTypeResource} from "../task-content/model/field-type-resource"; + +@Injectable({ + providedIn: 'root' +}) +export class ValidationRegistryService { + + private _registry: Map> + + constructor() { + this._registry = new Map>(); + } + + get registry(): Map> { + return this._registry; + } + + set registry(value: Map>) { + this._registry = value; + } + + public register(type: FieldTypeResource, key: string, fn: Validator): void { + if (!this._registry.has(type)) { + this._registry.set(type, new Map()); + } + this._registry.get(type).set(key, fn); + } + + public contains(type: FieldTypeResource, key: string): boolean { + return this._registry.get(type).has(key); + } + + public get(type: FieldTypeResource, key: string): Validator { + if (this._registry.has(type) && this._registry.get(type).has(key)) { + return this._registry.get(type).get(key); + } + return undefined; + } + + public getAllForType(type: FieldTypeResource): Map { + if (this._registry.has(type)) { + return this._registry.get(type); + } + return undefined; + } +} diff --git a/projects/netgrif-components-core/src/lib/task-content/services/field-converter.service.spec.ts b/projects/netgrif-components-core/src/lib/task-content/services/field-converter.service.spec.ts index 7b85e07da..5d8f9f0e3 100644 --- a/projects/netgrif-components-core/src/lib/task-content/services/field-converter.service.spec.ts +++ b/projects/netgrif-components-core/src/lib/task-content/services/field-converter.service.spec.ts @@ -91,52 +91,52 @@ describe('FieldConvertorService', () => { validations: undefined, subType: 'area' }; - expect(service.resolveType(service.toClass(dataField))).toEqual('boolean'); + expect(FieldConverterService.resolveType(service.toClass(dataField))).toEqual('boolean'); dataField.type = FieldTypeResource.TEXT; dataField.value = 'string' as any; - expect(service.resolveType(service.toClass(dataField))).toEqual('text'); + expect(FieldConverterService.resolveType(service.toClass(dataField))).toEqual('text'); dataField.type = FieldTypeResource.NUMBER; dataField.value = 5 as any; - expect(service.resolveType(service.toClass(dataField))).toEqual('number'); + expect(FieldConverterService.resolveType(service.toClass(dataField))).toEqual('number'); dataField.type = FieldTypeResource.ENUMERATION; - expect(service.resolveType(service.toClass(dataField))).toEqual('enumeration'); + expect(FieldConverterService.resolveType(service.toClass(dataField))).toEqual('enumeration'); dataField.type = FieldTypeResource.MULTICHOICE; - expect(service.resolveType(service.toClass(dataField))).toEqual('multichoice'); + expect(FieldConverterService.resolveType(service.toClass(dataField))).toEqual('multichoice'); dataField.type = FieldTypeResource.ENUMERATION; dataField.choices = {abc: 'abc'} as any; - expect(service.resolveType(service.toClass(dataField))).toEqual('enumeration'); + expect(FieldConverterService.resolveType(service.toClass(dataField))).toEqual('enumeration'); dataField.type = FieldTypeResource.MULTICHOICE; - expect(service.resolveType(service.toClass(dataField))).toEqual('multichoice'); + expect(FieldConverterService.resolveType(service.toClass(dataField))).toEqual('multichoice'); dataField.type = FieldTypeResource.DATE; dataField.value = [2020, 3, 3] as any; - expect(service.resolveType(service.toClass(dataField))).toEqual('date'); + expect(FieldConverterService.resolveType(service.toClass(dataField))).toEqual('date'); dataField.type = FieldTypeResource.DATE_TIME; dataField.value = [2020, 3, 3, 3, 30] as any; - expect(service.resolveType(service.toClass(dataField))).toEqual('dateTime'); + expect(FieldConverterService.resolveType(service.toClass(dataField))).toEqual('dateTime'); dataField.type = FieldTypeResource.USER; dataField.value = {id: 5, name: 'name', surname: 'surname', email: 'mail'} as any; - expect(service.resolveType(service.toClass(dataField))).toEqual('user'); + expect(FieldConverterService.resolveType(service.toClass(dataField))).toEqual('user'); dataField.type = FieldTypeResource.BUTTON; dataField.value = 0 as any; - expect(service.resolveType(service.toClass(dataField))).toEqual('button'); + expect(FieldConverterService.resolveType(service.toClass(dataField))).toEqual('button'); dataField.type = FieldTypeResource.FILE; dataField.value = undefined; - expect(service.resolveType(service.toClass(dataField))).toEqual('file'); + expect(FieldConverterService.resolveType(service.toClass(dataField))).toEqual('file'); dataField.type = FieldTypeResource.FILE_LIST; dataField.value = undefined; - expect(service.resolveType(service.toClass(dataField))).toEqual('fileList'); + expect(FieldConverterService.resolveType(service.toClass(dataField))).toEqual('fileList'); }); afterEach(() => { diff --git a/projects/netgrif-components-core/src/lib/task-content/services/field-converter.service.ts b/projects/netgrif-components-core/src/lib/task-content/services/field-converter.service.ts index aec119d6e..ab812e97a 100644 --- a/projects/netgrif-components-core/src/lib/task-content/services/field-converter.service.ts +++ b/projects/netgrif-components-core/src/lib/task-content/services/field-converter.service.ts @@ -24,6 +24,8 @@ import {I18nField} from '../../data-fields/i18n-field/models/i18n-field'; import {UserListField} from '../../data-fields/user-list-field/models/user-list-field'; import {UserListValue} from '../../data-fields/user-list-field/models/user-list-value'; import {decodeBase64, encodeBase64} from "../../utility/base64"; +import {ValidationRegistryService} from "../../registry/validation-registry.service"; +import {Validator} from "../../registry/model/validator"; import {CaseRefField} from '../../data-fields/case-ref-field/model/case-ref-field'; import {StringCollectionField} from '../../data-fields/string-collection-field/models/string-collection-field'; @@ -33,24 +35,28 @@ import {StringCollectionField} from '../../data-fields/string-collection-field/m export class FieldConverterService { private textFieldNames = [ 'richtextarea', 'htmltextarea', 'editor', 'htmlEditor' ] - constructor() { + constructor(protected validationRegistry: ValidationRegistryService) { } public toClass(item: DataFieldResource): DataField { switch (item.type) { case FieldTypeResource.BOOLEAN: return new BooleanField(item.stringId, item.name, item.value as boolean, item.behavior, - item.placeholder, item.description, item.layout, item.validations, item.component, item.parentTaskId); + item.placeholder, item.description, item.layout, item.validations, item.component, item.parentTaskId, + this.getValidators(item.type)); case FieldTypeResource.TEXT: if (this.textFieldNames.includes(item.component?.name)) { return new TextAreaField(item.stringId, item.name, this.resolveTextValue(item, item.value), item.behavior, - item.placeholder, item.description, item.layout, item.validations, item.component, item.parentTaskId); + item.placeholder, item.description, item.layout, item.validations, item.component, item.parentTaskId, + this.getValidators(item.type)); } return new TextField(item.stringId, item.name, this.resolveTextValue(item, item.value), item.behavior, item.placeholder, - item.description, item.layout, item.validations, item.component, item.parentTaskId); + item.description, item.layout, item.validations, item.component, item.parentTaskId, + this.getValidators(item.type)); case FieldTypeResource.NUMBER: return new NumberField(item.stringId, item.name, item.value as number, item.behavior, item.validations, item.placeholder, - item.description, item.layout, item.formatFilter, this.resolveNumberComponent(item), item.parentTaskId); + item.description, item.layout, item.formatFilter, this.resolveNumberComponent(item), item.parentTaskId, + this.getValidators(item.type)); case FieldTypeResource.ENUMERATION: case FieldTypeResource.ENUMERATION_MAP: return this.resolveEnumField(item); @@ -68,14 +74,16 @@ export class FieldConverterService { date = moment(new Date(item.value[0], item.value[1] - 1, item.value[2])); } return new DateField(item.stringId, item.name, date, item.behavior, item.placeholder, - item.description, item.layout, item.validations, item.component, item.parentTaskId); + item.description, item.layout, item.validations, item.component, item.parentTaskId, + this.getValidators(item.type)); case FieldTypeResource.DATE_TIME: let dateTime; if (item.value) { dateTime = moment(new Date(item.value[0], item.value[1] - 1, item.value[2], item.value[3], item.value[4])); } return new DateTimeField(item.stringId, item.name, dateTime, item.behavior, - item.placeholder, item.description, item.layout, item.validations, item.component, item.parentTaskId); + item.placeholder, item.description, item.layout, item.validations, item.component, item.parentTaskId, + this.getValidators(item.type)); case FieldTypeResource.USER: let user; if (item.value) { @@ -113,14 +121,14 @@ export class FieldConverterService { item.behavior, item.placeholder, item.description, item.layout, item.validations, item.component, item.parentTaskId); case FieldTypeResource.I18N: return new I18nField(item.stringId, item.name, item.value ?? {defaultValue: ''}, item.behavior, item.placeholder, - item.description, item.layout, item.validations, item.component); + item.description, item.layout, item.validations, item.component, this.getValidators(item.type)); case FieldTypeResource.STRING_COLLECTION: return new StringCollectionField(item.stringId, item.name, item.value ? item.value : [], item.behavior, item.placeholder, item.description, item.layout, item.validations, item.component, item.parentTaskId); } } - public resolveType(item: DataField): FieldTypeResource { + public static resolveType(item: DataField): FieldTypeResource { if (item instanceof BooleanField) { return FieldTypeResource.BOOLEAN; } else if (item instanceof ButtonField) { @@ -157,10 +165,10 @@ export class FieldConverterService { } public formatValueForBackend(field: DataField, value: any): any { - if (this.resolveType(field) === FieldTypeResource.TEXT && value === null) { + if (FieldConverterService.resolveType(field) === FieldTypeResource.TEXT && value === null) { return null; } - if (this.resolveType(field) === FieldTypeResource.TEXT && field.component && field.component.name === 'password') { + if (FieldConverterService.resolveType(field) === FieldTypeResource.TEXT && field.component && field.component.name === 'password') { return encodeBase64(value); } if (value === null) { @@ -169,18 +177,18 @@ export class FieldConverterService { if (value === undefined) { return; } - if (this.resolveType(field) === FieldTypeResource.DATE) { + if (FieldConverterService.resolveType(field) === FieldTypeResource.DATE) { if (moment.isMoment(value)) { return value.format('YYYY-MM-DD'); } } - if (this.resolveType(field) === FieldTypeResource.USER) { + if (FieldConverterService.resolveType(field) === FieldTypeResource.USER) { return value.id; } - if (this.resolveType(field) === FieldTypeResource.USER_LIST) { + if (FieldConverterService.resolveType(field) === FieldTypeResource.USER_LIST) { return [...value.userValues.keys()]; } - if (this.resolveType(field) === FieldTypeResource.DATE_TIME) { + if (FieldConverterService.resolveType(field) === FieldTypeResource.DATE_TIME) { if (moment.isMoment(value)) { return value.format('DD.MM.YYYY HH:mm:ss'); } @@ -281,19 +289,19 @@ export class FieldConverterService { if (value === undefined) { return; } - if (this.resolveType(field) === FieldTypeResource.TEXT && field.component && field.component.name === 'password') { + if (FieldConverterService.resolveType(field) === FieldTypeResource.TEXT && field.component && field.component.name === 'password') { return decodeBase64(value); } - if (this.resolveType(field) === FieldTypeResource.DATE) { + if (FieldConverterService.resolveType(field) === FieldTypeResource.DATE) { return moment(new Date(value[0], value[1] - 1, value[2])); } - if (this.resolveType(field) === FieldTypeResource.USER) { + if (FieldConverterService.resolveType(field) === FieldTypeResource.USER) { return new UserValue(value.id, value.name, value.surname, value.email); } - if (this.resolveType(field) === FieldTypeResource.DATE_TIME) { + if (FieldConverterService.resolveType(field) === FieldTypeResource.DATE_TIME) { return moment(new Date(value[0], value[1] - 1, value[2], value[3], value[4])); } - if (this.resolveType(field) === FieldTypeResource.MULTICHOICE) { + if (FieldConverterService.resolveType(field) === FieldTypeResource.MULTICHOICE) { const array = []; value.forEach(v => { if (v.defaultValue) { @@ -304,7 +312,7 @@ export class FieldConverterService { }); return array; } - if (this.resolveType(field) === FieldTypeResource.USER_LIST && !!value) { + if (FieldConverterService.resolveType(field) === FieldTypeResource.USER_LIST && !!value) { return new UserListValue(new Map(value.userValues.map(v => [v.id, v]))); } return value; @@ -317,6 +325,10 @@ export class FieldConverterService { return value; } + protected getValidators(type: FieldTypeResource): Map { + return this.validationRegistry.getAllForType(type); + } + protected resolveAllowedTypes(allowTypes: string[]) { return allowTypes?.length > 0 ? (allowTypes.length > 1 ? allowTypes as FileUploadMIMEType[] : allowTypes[0]) : null } diff --git a/projects/netgrif-components-core/src/lib/task-content/services/task-content.service.ts b/projects/netgrif-components-core/src/lib/task-content/services/task-content.service.ts index 39f4ac38f..a3d5d429f 100644 --- a/projects/netgrif-components-core/src/lib/task-content/services/task-content.service.ts +++ b/projects/netgrif-components-core/src/lib/task-content/services/task-content.service.ts @@ -236,7 +236,7 @@ export abstract class TaskContentService implements OnDestroy { } protected updateField(chFields: ChangedFields, field: DataField, frontendActions: Change): void { - if (this._fieldConverterService.resolveType(field) === FieldTypeResource.TASK_REF) { + if (FieldConverterService.resolveType(field) === FieldTypeResource.TASK_REF) { this._taskDataReloadRequest$.next(frontendActions ? frontendActions : undefined); return; } @@ -298,7 +298,7 @@ export abstract class TaskContentService implements OnDestroy { } protected updateReferencedField(chFields: ChangedFields, field: DataField, frontendActions: Change): void { - if (this._fieldConverterService.resolveType(field) === FieldTypeResource.TASK_REF) { + if (FieldConverterService.resolveType(field) === FieldTypeResource.TASK_REF) { this._taskDataReloadRequest$.next(frontendActions ? frontendActions : undefined); return; } diff --git a/projects/netgrif-components-core/src/lib/task-content/task-content/abstract-task-content.component.ts b/projects/netgrif-components-core/src/lib/task-content/task-content/abstract-task-content.component.ts index 78feb4a84..e4c658168 100644 --- a/projects/netgrif-components-core/src/lib/task-content/task-content/abstract-task-content.component.ts +++ b/projects/netgrif-components-core/src/lib/task-content/task-content/abstract-task-content.component.ts @@ -627,7 +627,7 @@ export abstract class AbstractTaskContentComponent implements OnDestroy { localGrid.push(this.newGridRow(subgrid.cols)); } - const fieldElement = subgrid.addField(dataField, this._fieldConverter.resolveType(dataField)); + const fieldElement = subgrid.addField(dataField, FieldConverterService.resolveType(dataField)); this.occupySpace(localGrid, dataField.localLayout.y, dataField.localLayout.x, dataField.localLayout.cols, fieldElement.gridAreaId, dataField.localLayout.rows); }); @@ -816,7 +816,7 @@ export abstract class AbstractTaskContentComponent implements OnDestroy { let xPosition = 0; const localGrid: Array> = []; dataGroup.fields.forEach((dataField, dataFieldCount) => { - const fieldElement = subgrid.addField(dataField, this._fieldConverter.resolveType(dataField)); + const fieldElement = subgrid.addField(dataField, FieldConverterService.resolveType(dataField)); if (dataGroup.stretch) { subgrid.addRow(this.newGridRow(subgrid.cols, fieldElement.gridAreaId)); return; // continue diff --git a/projects/netgrif-components-core/src/lib/task/services/task-data.service.ts b/projects/netgrif-components-core/src/lib/task/services/task-data.service.ts index 73b3b00af..fb835528f 100644 --- a/projects/netgrif-components-core/src/lib/task/services/task-data.service.ts +++ b/projects/netgrif-components-core/src/lib/task/services/task-data.service.ts @@ -340,7 +340,7 @@ export class TaskDataService extends TaskHandlingService implements OnDestroy { protected addFieldToSetDataRequestBody(context: TaskSetDataRequestContext, taskId: string, field: DataField): void { context.body[taskId][field.stringId] = { - type: this._fieldConverterService.resolveType(field), + type: FieldConverterService.resolveType(field), value: this._fieldConverterService.formatValueForBackend(field, field.value) }; context.previousValues[field.stringId] = field.previousValue; diff --git a/projects/netgrif-components/src/lib/data-fields/boolean-field/boolean-default-field/boolean-default-field.component.spec.ts b/projects/netgrif-components/src/lib/data-fields/boolean-field/boolean-default-field/boolean-default-field.component.spec.ts index e9a6daff6..7e1e11acd 100644 --- a/projects/netgrif-components/src/lib/data-fields/boolean-field/boolean-default-field/boolean-default-field.component.spec.ts +++ b/projects/netgrif-components/src/lib/data-fields/boolean-field/boolean-default-field/boolean-default-field.component.spec.ts @@ -13,7 +13,10 @@ import { MockUserResourceService, TestConfigurationService, TranslateLibModule, - UserResourceService, WrappedBoolean + UserResourceService, + WrappedBoolean, + Validator, + requiredTrueValidation } from "@netgrif/components-core"; import {AngularResizeEventModule} from "angular-resize-event"; import {HttpClientTestingModule} from "@angular/common/http/testing"; @@ -43,7 +46,10 @@ describe('BooleanSimpleFieldComponent', () => { }, undefined, undefined, undefined, - [{validationRule: 'requiredTrue', validationMessage: 'this is custom message'}]), + [{name: 'requiredTrue', validationMessage: 'this is custom message'}], + undefined, + undefined, + new Map([['requiredTrue', requiredTrueValidation]])), formControlRef: new FormControl(), showLargeLayout: new WrappedBoolean() } as DataFieldPortalData diff --git a/projects/netgrif-components/src/lib/data-fields/boolean-field/boolean-default-field/boolean-default-field.component.ts b/projects/netgrif-components/src/lib/data-fields/boolean-field/boolean-default-field/boolean-default-field.component.ts index 21f140267..ba51ce045 100644 --- a/projects/netgrif-components/src/lib/data-fields/boolean-field/boolean-default-field/boolean-default-field.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/boolean-field/boolean-default-field/boolean-default-field.component.ts @@ -1,6 +1,10 @@ import {Component, Inject, Optional} from '@angular/core'; import { - AbstractBooleanDefaultFieldComponent, BooleanField, DATA_FIELD_PORTAL_DATA, DataFieldPortalData, + AbstractBooleanDefaultFieldComponent, + BooleanField, + DATA_FIELD_PORTAL_DATA, + DataFieldPortalData, + ValidationRegistryService } from '@netgrif/components-core'; import {TranslateService} from "@ngx-translate/core"; @@ -12,8 +16,9 @@ import {TranslateService} from "@ngx-translate/core"; export class BooleanDefaultFieldComponent extends AbstractBooleanDefaultFieldComponent { constructor(_translate: TranslateService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(_translate, dataFieldPortalData); + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(_translate, dataFieldPortalData, _validationRegistry); } } diff --git a/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-default/case-ref-default.component.ts b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-default/case-ref-default.component.ts index 8ab3d0a3b..cbb2b32f0 100644 --- a/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-default/case-ref-default.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-default/case-ref-default.component.ts @@ -3,11 +3,13 @@ import { AbstractCaseRefDefaultComponent, DATA_FIELD_PORTAL_DATA, DataFieldPortalData, - TaskRefField + TaskRefField, + ValidationRegistryService } from '@netgrif/components-core'; import { DefaultCaseRefListViewComponent } from '../../../navigation/group-navigation-component-resolver/default-components/default-case-ref-list-view/default-case-ref-list-view.component'; +import {TranslateService} from "@ngx-translate/core"; @Component({ selector: 'nc-case-ref-default', @@ -17,8 +19,10 @@ import { export class CaseRefDefaultComponent extends AbstractCaseRefDefaultComponent { constructor(injector: Injector, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(injector, DefaultCaseRefListViewComponent, dataFieldPortalData) + _translate: TranslateService, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(injector, DefaultCaseRefListViewComponent, _translate, dataFieldPortalData, _validationRegistry) } } diff --git a/projects/netgrif-components/src/lib/data-fields/data-fields.module.ts b/projects/netgrif-components/src/lib/data-fields/data-fields.module.ts index 6e7c16928..59c5e26d4 100644 --- a/projects/netgrif-components/src/lib/data-fields/data-fields.module.ts +++ b/projects/netgrif-components/src/lib/data-fields/data-fields.module.ts @@ -4,7 +4,9 @@ import {FlexLayoutModule} from '@angular/flex-layout'; import { CovalentModule, CurrencyModule, - CustomDateAdapter, FrontActionModule, + CustomDateAdapter, + DataFieldsModule, + FrontActionModule, MaterialModule, TranslateLibModule, ComponentRegistryService @@ -79,7 +81,7 @@ import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; import { MultichoiceAutocompleteFieldComponent } from './multichoice-field/multichoice-autocomplete-field/multichoice-autocomplete-field.component'; -import { UserListFieldComponent } from './user-list-field/user-list-field.component'; +import {UserListFieldComponent} from './user-list-field/user-list-field.component'; import { SideMenuMultiUserAssignComponentModule } from "../side-menu/content-components/multi-user-assign/side-menu-multi-user-assign-component.module"; @@ -104,8 +106,10 @@ import { import { DashboardIframeTextFieldComponent } from './text-field/dashboard-iframe-text-field/dashboard-iframe-text-field.component'; -import { RouterModule } from '@angular/router'; -import { FilterFieldTabViewContentComponent } from './filter-field/tab-view-filter-field/filter-field-tab-view-content.component'; +import {RouterModule} from '@angular/router'; +import { + FilterFieldTabViewContentComponent +} from './filter-field/tab-view-filter-field/filter-field-tab-view-content.component'; import { BooleanDefaultFieldComponent } from './boolean-field/boolean-default-field/boolean-default-field.component'; import { ButtonDefaultFieldComponent } from './button-field/button-default-field/button-default-field.component'; import { DateDefaultFieldComponent } from './date-field/date-default-field/date-default-field.component'; @@ -219,6 +223,7 @@ import {ComponentPortal} from "@angular/cdk/portal"; BrowserAnimationsModule, DashboardComponentModule, RouterModule, + DataFieldsModule, FrontActionModule ], providers: [ @@ -227,49 +232,56 @@ import {ComponentPortal} from "@angular/cdk/portal"; }) export class DataFieldsComponentModule { - constructor(registry: ComponentRegistryService) { - registry.register("boolean-default", (injector: Injector) => new ComponentPortal(BooleanDefaultFieldComponent, null, injector)); - registry.register("button-default", (injector: Injector) => new ComponentPortal(ButtonDefaultFieldComponent, null, injector)); - registry.register("date-default", (injector: Injector) => new ComponentPortal(DateDefaultFieldComponent, null, injector)); - registry.register("date-time-default", (injector: Injector) => new ComponentPortal(DateTimeDefaultFieldComponent, null, injector)); - registry.register("enumeration-default", (injector: Injector) => new ComponentPortal(EnumerationSelectFieldComponent, null, injector)); - registry.register("enumeration-autocomplete_dynamic", (injector: Injector) => new ComponentPortal(EnumerationAutocompleteDynamicFieldComponent, null, injector)); - registry.register("enumeration-autocomplete", (injector: Injector) => new ComponentPortal(EnumerationAutocompleteSelectFieldComponent, null, injector)); - registry.register("enumeration-list", (injector: Injector) => new ComponentPortal(EnumerationListFieldComponent, null, injector)); - registry.register("enumeration-stepper", (injector: Injector) => new ComponentPortal(EnumerationStepperFieldComponent, null, injector)); - registry.register("enumeration-icon", (injector: Injector) => new ComponentPortal(EnumerationIconFieldComponent, null, injector)); - registry.register("enumeration-caseref", (injector: Injector) => new ComponentPortal(EnumerationCaserefFieldComponent, null, injector)); - registry.register("file-default", (injector: Injector) => new ComponentPortal(FileDefaultFieldComponent, null, injector)); - registry.register("file-preview", (injector: Injector) => new ComponentPortal(FileDefaultFieldComponent, null, injector)); - registry.register("file-list-default", (injector: Injector) => new ComponentPortal(FileListDefaultFieldComponent, null, injector)); - registry.register("filter-default", (injector: Injector) => new ComponentPortal(FilterDefaultFieldComponent, null, injector)); - registry.register("filter-filter-tab-view", (injector: Injector) => new ComponentPortal(FilterDefaultFieldComponent, null, injector)); - registry.register("i18n-divider", (injector: Injector) => new ComponentPortal(I18nDividerFieldComponent, null, injector)); - registry.register("i18n-text", (injector: Injector) => new ComponentPortal(I18nTextFieldComponent, null, injector)); - registry.register("i18n-default", (injector: Injector) => new ComponentPortal(I18nTextFieldComponent, null, injector)); - registry.register("multichoice-default", (injector: Injector) => new ComponentPortal(MultichoiceSelectFieldComponent, null, injector)); - registry.register("multichoice-list", (injector: Injector) => new ComponentPortal(MultichoiceListFieldComponent, null, injector)); - registry.register("multichoice-caseref", (injector: Injector) => new ComponentPortal(MultichoiceCaserefFieldComponent, null, injector)); - registry.register("multichoice-autocomplete", (injector: Injector) => new ComponentPortal(MultichoiceAutocompleteFieldComponent, null, injector)); - registry.register("number-default", (injector: Injector) => new ComponentPortal(NumberDefaultFieldComponent, null, injector)); - registry.register("number-currency", (injector: Injector) => new ComponentPortal(NumberCurrencyFieldComponent, null, injector)); - registry.register("number-decimal", (injector: Injector) => new ComponentPortal(NumberDecimalFieldComponent, null, injector)); - registry.register("text-default", (injector: Injector) => new ComponentPortal(SimpleTextFieldComponent, null, injector)); - registry.register("text-password", (injector: Injector) => new ComponentPortal(PasswordTextFieldComponent, null, injector)); - registry.register("text-textarea", (injector: Injector) => new ComponentPortal(TextareaFieldComponent, null, injector)); - registry.register("text-richtextarea", (injector: Injector) => new ComponentPortal(RichTextareaFieldComponent, null, injector)); - registry.register("text-htmltextarea", (injector: Injector) => new ComponentPortal(HtmlTextareaFieldComponent, null, injector)); - registry.register("text-signature", (injector: Injector) => new ComponentPortal(SignaturePadFieldComponent, null, injector)); - registry.register("text-dashboard_line_chart", (injector: Injector) => new ComponentPortal(DashboardLineChartTextFieldComponent, null, injector)); - registry.register("text-dashboard_pie_chart", (injector: Injector) => new ComponentPortal(DashboardPieChartTextFieldComponent, null, injector)); - registry.register("text-dashboard_bar_chart", (injector: Injector) => new ComponentPortal(DashboardBarChartTextFieldComponent, null, injector)); - registry.register("text-dashboard_iframe", (injector: Injector) => new ComponentPortal(DashboardIframeTextFieldComponent, null, injector)); - registry.register("text-dashboard_portal", (injector: Injector) => new ComponentPortal(DashboardPortalTextFieldComponent, null, injector)); - registry.register("task-ref-dashboard", (injector: Injector) => new ComponentPortal(TaskRefDashboardFieldComponent, null, injector)); - registry.register("task-ref-task-list", (injector: Injector) => new ComponentPortal(TaskRefListFieldComponent, null, injector)); - registry.register("case-ref-default", (injector: Injector) => new ComponentPortal(CaseRefDefaultComponent, null, injector)); - registry.register("user-default", (injector: Injector) => new ComponentPortal(UserDefaultFieldComponent, null, injector)); - registry.register("user-list-default", (injector: Injector) => new ComponentPortal(UserListDefaultFieldComponent, null, injector)); - registry.register("string-collection-default", (injector: Injector) => new ComponentPortal(StringCollectionDefaultFieldComponent, null, injector)); + constructor(componentRegistry: ComponentRegistryService) { + componentRegistry.register('boolean-default', (injector: Injector) => new ComponentPortal(BooleanDefaultFieldComponent, null, injector)); + componentRegistry.register('button-default', (injector: Injector) => new ComponentPortal(ButtonDefaultFieldComponent, null, injector)); + componentRegistry.register('date-default', (injector: Injector) => new ComponentPortal(DateDefaultFieldComponent, null, injector)); + componentRegistry.register('date-time-default', (injector: Injector) => new ComponentPortal(DateTimeDefaultFieldComponent, null, injector)); + componentRegistry.register('enumeration-default', (injector: Injector) => new ComponentPortal(EnumerationSelectFieldComponent, null, injector)); + componentRegistry.register('enumeration-autocomplete_dynamic', (injector: Injector) => new ComponentPortal(EnumerationAutocompleteDynamicFieldComponent, null, injector)); + componentRegistry.register('enumeration-autocomplete', (injector: Injector) => new ComponentPortal(EnumerationAutocompleteSelectFieldComponent, null, injector)); + componentRegistry.register('enumeration-list', (injector: Injector) => new ComponentPortal(EnumerationListFieldComponent, null, injector)); + componentRegistry.register('enumeration-stepper', (injector: Injector) => new ComponentPortal(EnumerationStepperFieldComponent, null, injector)); + componentRegistry.register('enumeration-icon', (injector: Injector) => new ComponentPortal(EnumerationIconFieldComponent, null, injector)); + componentRegistry.register('enumeration-caseref', (injector: Injector) => new ComponentPortal(EnumerationCaserefFieldComponent, null, injector)); + componentRegistry.register('file-default', (injector: Injector) => new ComponentPortal(FileDefaultFieldComponent, null, injector)); + componentRegistry.register("file-preview", (injector: Injector) => new ComponentPortal(FileDefaultFieldComponent, null, injector)); + componentRegistry.register('file-list-default', (injector: Injector) => new ComponentPortal(FileListDefaultFieldComponent, null, injector)); + componentRegistry.register('filter-default', (injector: Injector) => new ComponentPortal(FilterDefaultFieldComponent, null, injector)); + componentRegistry.register('filter-filter-tab-view', (injector: Injector) => new ComponentPortal(FilterDefaultFieldComponent, null, injector)); + componentRegistry.register('i18n-divider', (injector: Injector) => new ComponentPortal(I18nDividerFieldComponent, null, injector)); + componentRegistry.register('i18n-text', (injector: Injector) => new ComponentPortal(I18nTextFieldComponent, null, injector)); + componentRegistry.register('i18n-default', (injector: Injector) => new ComponentPortal(I18nTextFieldComponent, null, injector)); + componentRegistry.register('multichoice-default', (injector: Injector) => new ComponentPortal(MultichoiceSelectFieldComponent, null, injector)); + componentRegistry.register('multichoice-list', (injector: Injector) => new ComponentPortal(MultichoiceListFieldComponent, null, injector)); + componentRegistry.register('multichoice-caseref', (injector: Injector) => new ComponentPortal(MultichoiceCaserefFieldComponent, null, injector)); + componentRegistry.register('multichoice-autocomplete', (injector: Injector) => new ComponentPortal(MultichoiceAutocompleteFieldComponent, null, injector)); + componentRegistry.register('number-default', (injector: Injector) => new ComponentPortal(NumberDefaultFieldComponent, null, injector)); + componentRegistry.register('number-currency', (injector: Injector) => new ComponentPortal(NumberCurrencyFieldComponent, null, injector)); + componentRegistry.register('number-decimal', (injector: Injector) => new ComponentPortal(NumberDecimalFieldComponent, null, injector)); + componentRegistry.register('text-default', (injector: Injector) => new ComponentPortal(SimpleTextFieldComponent, null, injector)); + componentRegistry.register('text-password', (injector: Injector) => new ComponentPortal(PasswordTextFieldComponent, null, injector)); + componentRegistry.register('text-textarea', (injector: Injector) => new ComponentPortal(TextareaFieldComponent, null, injector)); + componentRegistry.register('text-richtextarea', (injector: Injector) => new ComponentPortal(RichTextareaFieldComponent, null, injector)); + componentRegistry.register('text-htmltextarea', (injector: Injector) => new ComponentPortal(HtmlTextareaFieldComponent, null, injector)); + componentRegistry.register('text-signature', (injector: Injector) => new ComponentPortal(SignaturePadFieldComponent, null, injector)); + componentRegistry.register('text-dashboard_line_chart', (injector: Injector) => new ComponentPortal(DashboardLineChartTextFieldComponent, null, injector)); + componentRegistry.register('text-dashboard_pie_chart', (injector: Injector) => new ComponentPortal(DashboardPieChartTextFieldComponent, null, injector)); + componentRegistry.register('text-dashboard_bar_chart', (injector: Injector) => new ComponentPortal(DashboardBarChartTextFieldComponent, null, injector)); + componentRegistry.register('text-dashboard_iframe', (injector: Injector) => new ComponentPortal(DashboardIframeTextFieldComponent, null, injector)); + componentRegistry.register('text-dashboard_portal', (injector: Injector) => new ComponentPortal(DashboardPortalTextFieldComponent, null, injector)); + componentRegistry.register('task-ref-dashboard', (injector: Injector) => new ComponentPortal(TaskRefDashboardFieldComponent, null, injector)); + componentRegistry.register('task-ref-task-list', (injector: Injector) => new ComponentPortal(TaskRefListFieldComponent, null, injector)); + componentRegistry.register('case-ref-default', (injector: Injector) => new ComponentPortal(CaseRefDefaultComponent, null, injector)); + componentRegistry.register('user-default', (injector: Injector) => new ComponentPortal(UserDefaultFieldComponent, null, injector)); + componentRegistry.register('user-default', (injector: Injector) => new ComponentPortal(UserDefaultFieldComponent, null, injector)); + componentRegistry.register('user-list-default', (injector: Injector) => new ComponentPortal(UserListDefaultFieldComponent, null, injector)); + componentRegistry.register('enumeration-caseref', (injector: Injector) => new ComponentPortal(EnumerationCaserefFieldComponent, null, injector)); + componentRegistry.register('i18n-text', (injector: Injector) => new ComponentPortal(I18nTextFieldComponent, null, injector)); + componentRegistry.register('multichoice-caseref', (injector: Injector) => new ComponentPortal(MultichoiceCaserefFieldComponent, null, injector)); + componentRegistry.register('task-ref-dashboard', (injector: Injector) => new ComponentPortal(TaskRefDashboardFieldComponent, null, injector)); + componentRegistry.register('task-ref-task-list', (injector: Injector) => new ComponentPortal(TaskRefListFieldComponent, null, injector)); + componentRegistry.register('case-ref-default', (injector: Injector) => new ComponentPortal(CaseRefDefaultComponent, null, injector)); + componentRegistry.register('string-collection-default', (injector: Injector) => new ComponentPortal(StringCollectionDefaultFieldComponent, null, injector)); } } diff --git a/projects/netgrif-components/src/lib/data-fields/date-field/date-default-field/date-default-field.component.spec.ts b/projects/netgrif-components/src/lib/data-fields/date-field/date-default-field/date-default-field.component.spec.ts index 66c3b0c76..69181f68b 100644 --- a/projects/netgrif-components/src/lib/data-fields/date-field/date-default-field/date-default-field.component.spec.ts +++ b/projects/netgrif-components/src/lib/data-fields/date-field/date-default-field/date-default-field.component.spec.ts @@ -15,7 +15,10 @@ import { TestConfigurationService, TranslateLibModule, UserResourceService, - WrappedBoolean + WrappedBoolean, + workdayValidation, + weekendValidation, + Validator } from "@netgrif/components-core"; import {AngularResizeEventModule} from "angular-resize-event"; import {HttpClientTestingModule} from "@angular/common/http/testing"; @@ -54,10 +57,16 @@ describe('DateDefaultFieldComponent', () => { visible: true, editable: true, hidden: true - }, undefined, undefined, undefined, [ - {validationRule: 'weekend', validationMessage: 'This is custom message!'}, - {validationRule: 'workday', validationMessage: 'This is custom message!'} - ]), + }, undefined, undefined, undefined,[ + {name: 'weekend', validationMessage: 'This is custom message!'}, + {name: 'workday', validationMessage: 'This is custom message!'} + ], + undefined, + undefined, + new Map([ + ['weekend', weekendValidation], + ['workday', workdayValidation] + ])), formControlRef: new FormControl(), showLargeLayout: new WrappedBoolean() } as DataFieldPortalData diff --git a/projects/netgrif-components/src/lib/data-fields/date-field/date-default-field/date-default-field.component.ts b/projects/netgrif-components/src/lib/data-fields/date-field/date-default-field/date-default-field.component.ts index d74fe27ea..0464121e7 100644 --- a/projects/netgrif-components/src/lib/data-fields/date-field/date-default-field/date-default-field.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/date-field/date-default-field/date-default-field.component.ts @@ -3,7 +3,10 @@ import { AbstractDateDefaultFieldComponent, DATA_FIELD_PORTAL_DATA, DataFieldPortalData, - DATE_FORMAT, LanguageService, DateField + DateField, + ValidationRegistryService, + DATE_FORMAT, + LanguageService } from '@netgrif/components-core'; import {TranslateService} from "@ngx-translate/core"; import {MAT_DATE_FORMATS, MAT_DATE_LOCALE} from "@angular/material/core"; @@ -23,8 +26,9 @@ export class DateDefaultFieldComponent extends AbstractDateDefaultFieldComponent _adapter: NgxMatDateAdapter, @Inject(MAT_DATE_LOCALE) protected _locale: string, _languageService: LanguageService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(_translate, _adapter, _locale, _languageService, dataFieldPortalData); + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(_translate, _adapter, _locale, _languageService, dataFieldPortalData, _validationRegistry); } diff --git a/projects/netgrif-components/src/lib/data-fields/date-field/date-field.component.spec.ts b/projects/netgrif-components/src/lib/data-fields/date-field/date-field.component.spec.ts index 7f03d8f3e..155dd9433 100644 --- a/projects/netgrif-components/src/lib/data-fields/date-field/date-field.component.spec.ts +++ b/projects/netgrif-components/src/lib/data-fields/date-field/date-field.component.spec.ts @@ -17,7 +17,10 @@ import { MockUserResourceService, TestConfigurationService, TranslateLibModule, - UserResourceService + UserResourceService, + Validator, + weekendValidation, + workdayValidation } from '@netgrif/components-core'; import {NoopAnimationsModule} from '@angular/platform-browser/animations'; @@ -74,8 +77,14 @@ class TestWrapperComponent { editable: true, hidden: true }, undefined, undefined, undefined, [ - {validationRule: 'weekend', validationMessage: 'This is custom message!'}, - {validationRule: 'workday', validationMessage: 'This is custom message!'} - ]); + {name: 'weekend', validationMessage: 'This is custom message!'}, + {name: 'workday', validationMessage: 'This is custom message!'} + ], + undefined, + undefined, + new Map([ + ['weekend', weekendValidation], + ['workday', workdayValidation] + ])); } diff --git a/projects/netgrif-components/src/lib/data-fields/date-time-field/date-time-default-field/date-time-default-field.component.spec.ts b/projects/netgrif-components/src/lib/data-fields/date-time-field/date-time-default-field/date-time-default-field.component.spec.ts index 4e6fa4b7b..6656ca4dc 100644 --- a/projects/netgrif-components/src/lib/data-fields/date-time-field/date-time-default-field/date-time-default-field.component.spec.ts +++ b/projects/netgrif-components/src/lib/data-fields/date-time-field/date-time-default-field/date-time-default-field.component.spec.ts @@ -15,7 +15,9 @@ import { TestConfigurationService, TranslateLibModule, UserResourceService, - WrappedBoolean + WrappedBoolean, + Validator, + betweenValidation } from "@netgrif/components-core"; import {AngularResizeEventModule} from "angular-resize-event"; import {NgxMatDatetimePickerModule, NgxMatNativeDateModule} from "@angular-material-components/datetime-picker"; @@ -56,10 +58,15 @@ describe('DateTimeDefaultFieldComponent', () => { editable: true, hidden: true }, undefined, undefined, undefined, [ - {validationRule: 'between today,future', validationMessage: 'This is custom message!'}, - {validationRule: 'between past,today', validationMessage: 'This is custom message!'}, - {validationRule: 'between 2020-03-03,today', validationMessage: 'This is custom message!'}, - ]), + {name: 'between', validationMessage: 'This is custom message!', arguments: {'from': {key: 'from', value: 'today', dynamic: false}, 'to': {key: 'to', value: 'future', dynamic: false}}}, + {name: 'between', validationMessage: 'This is custom message!', arguments: {'from': {key: 'from', value: 'past', dynamic: false}, 'to': {key: 'to', value: 'today', dynamic: false}}}, + {name: 'between', validationMessage: 'This is custom message!', arguments: {'from': {key: 'from', value: '2020-03-03', dynamic: false}, 'to': {key: 'to', value: 'today', dynamic: false}}} + ], + undefined, + undefined, + new Map([ + ['between', betweenValidation] + ])), formControlRef: new FormControl(), showLargeLayout: new WrappedBoolean() } as DataFieldPortalData diff --git a/projects/netgrif-components/src/lib/data-fields/date-time-field/date-time-default-field/date-time-default-field.component.ts b/projects/netgrif-components/src/lib/data-fields/date-time-field/date-time-default-field/date-time-default-field.component.ts index 15507b39f..1674800b7 100644 --- a/projects/netgrif-components/src/lib/data-fields/date-time-field/date-time-default-field/date-time-default-field.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/date-time-field/date-time-default-field/date-time-default-field.component.ts @@ -4,6 +4,7 @@ import { DATA_FIELD_PORTAL_DATA, DataFieldPortalData, DateTimeField, + ValidationRegistryService, DATE_TIME_FORMAT, LanguageService } from '@netgrif/components-core' @@ -21,12 +22,13 @@ import {MAT_DATE_LOCALE} from "@angular/material/core"; }) export class DateTimeDefaultFieldComponent extends AbstractDateTimeDefaultFieldComponent { - constructor(_translate: TranslateService, - _adapter: NgxMatDateAdapter, - @Inject(MAT_DATE_LOCALE) protected _locale: string, - _languageService: LanguageService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(_translate, _adapter, _locale, _languageService, dataFieldPortalData); - } + constructor(_translate: TranslateService, + _adapter: NgxMatDateAdapter, + @Inject(MAT_DATE_LOCALE) protected _locale: string, + _languageService: LanguageService, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(_translate, _adapter, _locale, _languageService, dataFieldPortalData, _validationRegistry); + } } diff --git a/projects/netgrif-components/src/lib/data-fields/enumeration-field/enumeration-autocomplete-dynamic-field/enumeration-autocomplete-dynamic-field.component.ts b/projects/netgrif-components/src/lib/data-fields/enumeration-field/enumeration-autocomplete-dynamic-field/enumeration-autocomplete-dynamic-field.component.ts index f131f75aa..6c99adae5 100644 --- a/projects/netgrif-components/src/lib/data-fields/enumeration-field/enumeration-autocomplete-dynamic-field/enumeration-autocomplete-dynamic-field.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/enumeration-field/enumeration-autocomplete-dynamic-field/enumeration-autocomplete-dynamic-field.component.ts @@ -14,7 +14,7 @@ import {TranslateService} from '@ngx-translate/core'; }) export class EnumerationAutocompleteDynamicFieldComponent extends AbstractEnumerationAutocompleteDynamicFieldComponent { - constructor(protected _translate: TranslateService, + constructor(_translate: TranslateService, @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { super(_translate, dataFieldPortalData); } diff --git a/projects/netgrif-components/src/lib/data-fields/enumeration-field/enumeration-autocomplete-select-field/enumeration-autocomplete-select-field.component.ts b/projects/netgrif-components/src/lib/data-fields/enumeration-field/enumeration-autocomplete-select-field/enumeration-autocomplete-select-field.component.ts index 1dcff8173..dacc33e31 100644 --- a/projects/netgrif-components/src/lib/data-fields/enumeration-field/enumeration-autocomplete-select-field/enumeration-autocomplete-select-field.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/enumeration-field/enumeration-autocomplete-select-field/enumeration-autocomplete-select-field.component.ts @@ -13,7 +13,7 @@ import { }) export class EnumerationAutocompleteSelectFieldComponent extends AbstractEnumerationAutocompleteSelectFieldComponent { - constructor(protected _translate: TranslateService, + constructor(_translate: TranslateService, @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { super(_translate, dataFieldPortalData); } diff --git a/projects/netgrif-components/src/lib/data-fields/enumeration-field/enumeration-caseref-field/enumeration-caseref-field.component.ts b/projects/netgrif-components/src/lib/data-fields/enumeration-field/enumeration-caseref-field/enumeration-caseref-field.component.ts index a1392d0a6..1679a6a68 100644 --- a/projects/netgrif-components/src/lib/data-fields/enumeration-field/enumeration-caseref-field/enumeration-caseref-field.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/enumeration-field/enumeration-caseref-field/enumeration-caseref-field.component.ts @@ -2,11 +2,13 @@ import {Component, Inject, Injector, Optional} from '@angular/core'; import { DATA_FIELD_PORTAL_DATA, DataFieldPortalData, EnumerationField, - AbstractEnumerationCaseRefComponent + AbstractEnumerationCaseRefComponent, + ValidationRegistryService } from '@netgrif/components-core'; import { DefaultCaseRefListViewComponent } from '../../../navigation/group-navigation-component-resolver/default-components/default-case-ref-list-view/default-case-ref-list-view.component'; +import {TranslateService} from "@ngx-translate/core"; @Component({ selector: 'nc-enumeration-caseref-field', @@ -16,7 +18,9 @@ import { export class EnumerationCaserefFieldComponent extends AbstractEnumerationCaseRefComponent { constructor(injector: Injector, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(injector, DefaultCaseRefListViewComponent, dataFieldPortalData) + _translate: TranslateService, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService){ + super(injector, DefaultCaseRefListViewComponent, _translate, dataFieldPortalData, _validationRegistry) } } diff --git a/projects/netgrif-components/src/lib/data-fields/i18n-field/i18n-text-field/i18n-text-field.component.ts b/projects/netgrif-components/src/lib/data-fields/i18n-field/i18n-text-field/i18n-text-field.component.ts index 1453ce64b..6aee4eaac 100644 --- a/projects/netgrif-components/src/lib/data-fields/i18n-field/i18n-text-field/i18n-text-field.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/i18n-field/i18n-text-field/i18n-text-field.component.ts @@ -4,7 +4,8 @@ import { LanguageIconsService, DATA_FIELD_PORTAL_DATA, DataFieldPortalData, - I18nField + I18nField, + ValidationRegistryService } from '@netgrif/components-core'; import {TranslateService} from '@ngx-translate/core'; import {DomSanitizer} from '@angular/platform-browser'; @@ -34,7 +35,8 @@ import {animate, state, style, transition, trigger} from '@angular/animations'; }) export class I18nTextFieldComponent extends AbstractI18nTextFieldComponent { constructor(languageIconsService: LanguageIconsService, translateService: TranslateService, domSanitizer: DomSanitizer, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(languageIconsService, translateService, domSanitizer, dataFieldPortalData); + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(languageIconsService, translateService, domSanitizer, dataFieldPortalData, _validationRegistry); } } diff --git a/projects/netgrif-components/src/lib/data-fields/multichoice-field/multichoice-caseref-field/multichoice-caseref-field.component.ts b/projects/netgrif-components/src/lib/data-fields/multichoice-field/multichoice-caseref-field/multichoice-caseref-field.component.ts index e5bb941de..a805d7a3d 100644 --- a/projects/netgrif-components/src/lib/data-fields/multichoice-field/multichoice-caseref-field/multichoice-caseref-field.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/multichoice-field/multichoice-caseref-field/multichoice-caseref-field.component.ts @@ -3,11 +3,13 @@ import { DATA_FIELD_PORTAL_DATA, DataFieldPortalData, AbstractMultichoiceCaseRefComponent, - MultichoiceField + MultichoiceField, + ValidationRegistryService } from '@netgrif/components-core'; import { DefaultCaseRefListViewComponent } from '../../../navigation/group-navigation-component-resolver/default-components/default-case-ref-list-view/default-case-ref-list-view.component'; +import {TranslateService} from "@ngx-translate/core"; @Component({ selector: 'nc-multichoice-caseref-field', @@ -17,7 +19,9 @@ import { export class MultichoiceCaserefFieldComponent extends AbstractMultichoiceCaseRefComponent { constructor(injector: Injector, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(injector, DefaultCaseRefListViewComponent, dataFieldPortalData) + _translate: TranslateService, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(injector, DefaultCaseRefListViewComponent, _translate, dataFieldPortalData, _validationRegistry) } } diff --git a/projects/netgrif-components/src/lib/data-fields/number-field/number-currency-field/number-currency-field.component.ts b/projects/netgrif-components/src/lib/data-fields/number-field/number-currency-field/number-currency-field.component.ts index 780ba6c48..c7645fac4 100644 --- a/projects/netgrif-components/src/lib/data-fields/number-field/number-currency-field/number-currency-field.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/number-field/number-currency-field/number-currency-field.component.ts @@ -4,7 +4,8 @@ import { AbstractCurrencyNumberFieldComponent, DATA_FIELD_PORTAL_DATA, DataFieldPortalData, - NumberField + NumberField, + ValidationRegistryService } from '@netgrif/components-core'; import {CurrencyPipe} from '@angular/common'; @@ -16,8 +17,9 @@ import {CurrencyPipe} from '@angular/common'; export class NumberCurrencyFieldComponent extends AbstractCurrencyNumberFieldComponent implements AfterViewInit { constructor(currencyPipe: CurrencyPipe, translate: TranslateService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(currencyPipe, translate, dataFieldPortalData); + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(currencyPipe, translate, dataFieldPortalData, _validationRegistry); } ngAfterViewInit() { diff --git a/projects/netgrif-components/src/lib/data-fields/number-field/number-decimal-field/number-decimal-field.component.ts b/projects/netgrif-components/src/lib/data-fields/number-field/number-decimal-field/number-decimal-field.component.ts index e54d77b8d..680950c07 100644 --- a/projects/netgrif-components/src/lib/data-fields/number-field/number-decimal-field/number-decimal-field.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/number-field/number-decimal-field/number-decimal-field.component.ts @@ -4,7 +4,7 @@ import { AbstractNumberDecimalFieldComponent, DATA_FIELD_PORTAL_DATA, DataFieldPortalData, - NumberField + NumberField, ValidationRegistryService } from "@netgrif/components-core"; import {DecimalPipe} from "@angular/common"; import {MatFormFieldAppearance} from "@angular/material/form-field"; @@ -17,9 +17,9 @@ import {MatFormFieldAppearance} from "@angular/material/form-field"; export class NumberDecimalFieldComponent extends AbstractNumberDecimalFieldComponent { constructor(decimalPipe: DecimalPipe, translate: TranslateService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData - ) { - super(decimalPipe, translate, dataFieldPortalData); + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(decimalPipe, translate, dataFieldPortalData, _validationRegistry); } getAppearance(): MatFormFieldAppearance { diff --git a/projects/netgrif-components/src/lib/data-fields/number-field/number-default-field/number-default-field.component.ts b/projects/netgrif-components/src/lib/data-fields/number-field/number-default-field/number-default-field.component.ts index 1deac93a5..5b74272de 100644 --- a/projects/netgrif-components/src/lib/data-fields/number-field/number-default-field/number-default-field.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/number-field/number-default-field/number-default-field.component.ts @@ -3,7 +3,8 @@ import { AbstractDefaultNumberFieldComponent, DATA_FIELD_PORTAL_DATA, DataFieldPortalData, - NumberField + NumberField, + ValidationRegistryService } from '@netgrif/components-core'; import {TranslateService} from '@ngx-translate/core'; @@ -14,7 +15,8 @@ import {TranslateService} from '@ngx-translate/core'; }) export class NumberDefaultFieldComponent extends AbstractDefaultNumberFieldComponent { constructor(translate: TranslateService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(translate, dataFieldPortalData); + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(translate, dataFieldPortalData, _validationRegistry); } } diff --git a/projects/netgrif-components/src/lib/data-fields/string-collection-field/string-collection-default-field/string-collection-default-field.component.ts b/projects/netgrif-components/src/lib/data-fields/string-collection-field/string-collection-default-field/string-collection-default-field.component.ts index 051f5e5f7..efe6795c8 100644 --- a/projects/netgrif-components/src/lib/data-fields/string-collection-field/string-collection-default-field/string-collection-default-field.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/string-collection-field/string-collection-default-field/string-collection-default-field.component.ts @@ -3,7 +3,8 @@ import { AbstractStringCollectionDefaultFieldComponent, DATA_FIELD_PORTAL_DATA, DataFieldPortalData, - TaskRefField + TaskRefField, + ValidationRegistryService } from '@netgrif/components-core'; import {TranslateService} from '@ngx-translate/core'; @@ -14,9 +15,10 @@ import {TranslateService} from '@ngx-translate/core'; }) export class StringCollectionDefaultFieldComponent extends AbstractStringCollectionDefaultFieldComponent { - constructor(protected _translate: TranslateService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(_translate, dataFieldPortalData) + constructor(_translate: TranslateService, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(_translate, dataFieldPortalData, _validationRegistry) } } diff --git a/projects/netgrif-components/src/lib/data-fields/task-ref-field/task-ref-dashboard-field/task-ref-dashboard-field.component.ts b/projects/netgrif-components/src/lib/data-fields/task-ref-field/task-ref-dashboard-field/task-ref-dashboard-field.component.ts index 241781906..9e6274c91 100644 --- a/projects/netgrif-components/src/lib/data-fields/task-ref-field/task-ref-dashboard-field/task-ref-dashboard-field.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/task-ref-field/task-ref-dashboard-field/task-ref-dashboard-field.component.ts @@ -5,8 +5,10 @@ import { DataFieldPortalData, LoggerService, TaskRefDashboardTile, - TaskRefField + TaskRefField, + ValidationRegistryService } from '@netgrif/components-core'; +import {TranslateService} from "@ngx-translate/core"; @Component({ selector: 'nc-task-ref-dashboard-field', @@ -18,8 +20,10 @@ export class TaskRefDashboardFieldComponent extends AbstractTaskRefDashboardFiel @Input() taskContentComponentClassReference: Type; constructor(logger: LoggerService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(logger, dataFieldPortalData); + _translate: TranslateService, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(_translate, logger, dataFieldPortalData, _validationRegistry); } getGridColumns(): string { diff --git a/projects/netgrif-components/src/lib/data-fields/task-ref-field/task-ref-list-field/task-ref-list-field.component.ts b/projects/netgrif-components/src/lib/data-fields/task-ref-field/task-ref-list-field/task-ref-list-field.component.ts index 6fc6fca31..4fd28a837 100644 --- a/projects/netgrif-components/src/lib/data-fields/task-ref-field/task-ref-list-field/task-ref-list-field.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/task-ref-field/task-ref-list-field/task-ref-list-field.component.ts @@ -3,11 +3,13 @@ import { AbstractTaskRefListFieldComponent, DATA_FIELD_PORTAL_DATA, DataFieldPortalData, - TaskRefField + TaskRefField, + ValidationRegistryService } from "@netgrif/components-core"; import { DefaultTaskViewComponent } from "../../../navigation/group-navigation-component-resolver/default-components/default-task-view/default-task-view.component"; +import {TranslateService} from "@ngx-translate/core"; @Component({ selector: 'nc-task-ref-list-field', @@ -17,8 +19,10 @@ import { export class TaskRefListFieldComponent extends AbstractTaskRefListFieldComponent { constructor(injector: Injector, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(injector, DefaultTaskViewComponent, dataFieldPortalData) + _translate: TranslateService, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(injector, DefaultTaskViewComponent, _translate, dataFieldPortalData, _validationRegistry) } } diff --git a/projects/netgrif-components/src/lib/data-fields/text-field/dashboard-bar-chart-text-field/dashboard-bar-chart-text-field.component.ts b/projects/netgrif-components/src/lib/data-fields/text-field/dashboard-bar-chart-text-field/dashboard-bar-chart-text-field.component.ts index 9a347ffcd..1f63f0e83 100644 --- a/projects/netgrif-components/src/lib/data-fields/text-field/dashboard-bar-chart-text-field/dashboard-bar-chart-text-field.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/text-field/dashboard-bar-chart-text-field/dashboard-bar-chart-text-field.component.ts @@ -4,7 +4,8 @@ import { AbstractDashboardBarChartTextFieldComponent, DATA_FIELD_PORTAL_DATA, DataFieldPortalData, - TextField + TextField, + ValidationRegistryService } from '@netgrif/components-core'; @Component({ @@ -15,8 +16,9 @@ import { export class DashboardBarChartTextFieldComponent extends AbstractDashboardBarChartTextFieldComponent { constructor(translate: TranslateService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(translate, dataFieldPortalData); + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(translate, dataFieldPortalData, _validationRegistry); } } diff --git a/projects/netgrif-components/src/lib/data-fields/text-field/dashboard-iframe-text-field/dashboard-iframe-text-field.component.ts b/projects/netgrif-components/src/lib/data-fields/text-field/dashboard-iframe-text-field/dashboard-iframe-text-field.component.ts index 6d5bde3d3..6d69267cc 100644 --- a/projects/netgrif-components/src/lib/data-fields/text-field/dashboard-iframe-text-field/dashboard-iframe-text-field.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/text-field/dashboard-iframe-text-field/dashboard-iframe-text-field.component.ts @@ -3,7 +3,8 @@ import { AbstractDashboardIframeTextFieldComponent, DATA_FIELD_PORTAL_DATA, DataFieldPortalData, - TextField + TextField, + ValidationRegistryService } from '@netgrif/components-core'; import {TranslateService} from '@ngx-translate/core'; @@ -15,8 +16,9 @@ import {TranslateService} from '@ngx-translate/core'; export class DashboardIframeTextFieldComponent extends AbstractDashboardIframeTextFieldComponent { constructor(translate: TranslateService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(translate, dataFieldPortalData); + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(translate, dataFieldPortalData, _validationRegistry); } } diff --git a/projects/netgrif-components/src/lib/data-fields/text-field/dashboard-line-chart-text-field/dashboard-line-chart-text-field.component.ts b/projects/netgrif-components/src/lib/data-fields/text-field/dashboard-line-chart-text-field/dashboard-line-chart-text-field.component.ts index 0f60ebe3e..ce98ad3cb 100644 --- a/projects/netgrif-components/src/lib/data-fields/text-field/dashboard-line-chart-text-field/dashboard-line-chart-text-field.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/text-field/dashboard-line-chart-text-field/dashboard-line-chart-text-field.component.ts @@ -3,7 +3,8 @@ import { AbstractDashboardLineChartTextFieldComponent, DATA_FIELD_PORTAL_DATA, DataFieldPortalData, - TextField + TextField, + ValidationRegistryService } from '@netgrif/components-core'; import {TranslateService} from '@ngx-translate/core'; @@ -15,8 +16,9 @@ import {TranslateService} from '@ngx-translate/core'; export class DashboardLineChartTextFieldComponent extends AbstractDashboardLineChartTextFieldComponent { constructor(translate: TranslateService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(translate, dataFieldPortalData); + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(translate, dataFieldPortalData, _validationRegistry); } } diff --git a/projects/netgrif-components/src/lib/data-fields/text-field/dashboard-pie-chart-text-field/dashboard-pie-chart-text-field.component.ts b/projects/netgrif-components/src/lib/data-fields/text-field/dashboard-pie-chart-text-field/dashboard-pie-chart-text-field.component.ts index 6e28c9d28..972c7f840 100644 --- a/projects/netgrif-components/src/lib/data-fields/text-field/dashboard-pie-chart-text-field/dashboard-pie-chart-text-field.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/text-field/dashboard-pie-chart-text-field/dashboard-pie-chart-text-field.component.ts @@ -3,7 +3,8 @@ import { AbstractDashboardPieChartTextFieldComponent, DATA_FIELD_PORTAL_DATA, DataFieldPortalData, - TextField + TextField, + ValidationRegistryService } from '@netgrif/components-core'; import {TranslateService} from '@ngx-translate/core'; @@ -15,8 +16,9 @@ import {TranslateService} from '@ngx-translate/core'; export class DashboardPieChartTextFieldComponent extends AbstractDashboardPieChartTextFieldComponent { constructor(translate: TranslateService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(translate, dataFieldPortalData); + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(translate, dataFieldPortalData, _validationRegistry); } } diff --git a/projects/netgrif-components/src/lib/data-fields/text-field/dashboard-portal-text-field/dashboard-portal-text-field.component.ts b/projects/netgrif-components/src/lib/data-fields/text-field/dashboard-portal-text-field/dashboard-portal-text-field.component.ts index ae578c5fb..d5caf30fb 100644 --- a/projects/netgrif-components/src/lib/data-fields/text-field/dashboard-portal-text-field/dashboard-portal-text-field.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/text-field/dashboard-portal-text-field/dashboard-portal-text-field.component.ts @@ -4,7 +4,8 @@ import { AbstractDashboardPortalTextFieldComponent, ComponentRegistryService, DATA_FIELD_PORTAL_DATA, DataFieldPortalData, - TextField + TextField, + ValidationRegistryService } from '@netgrif/components-core'; import {TranslateService} from '@ngx-translate/core'; import {Subscription} from 'rxjs'; @@ -21,8 +22,9 @@ export class DashboardPortalTextFieldComponent extends AbstractDashboardPortalTe constructor(translate: TranslateService, private registry: ComponentRegistryService, private injector: Injector, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(translate, dataFieldPortalData); + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(translate, dataFieldPortalData, _validationRegistry); } ngOnInit(): void { diff --git a/projects/netgrif-components/src/lib/data-fields/text-field/html-textarea-field/html-textarea-field.component.ts b/projects/netgrif-components/src/lib/data-fields/text-field/html-textarea-field/html-textarea-field.component.ts index 6d82db868..6d3ad6e85 100644 --- a/projects/netgrif-components/src/lib/data-fields/text-field/html-textarea-field/html-textarea-field.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/text-field/html-textarea-field/html-textarea-field.component.ts @@ -4,6 +4,7 @@ import { DATA_FIELD_PORTAL_DATA, DataFieldPortalData, TextAreaField, + ValidationRegistryService } from '@netgrif/components-core'; import {TranslateService} from '@ngx-translate/core'; import {DomSanitizer} from '@angular/platform-browser'; @@ -14,15 +15,16 @@ import {DomSanitizer} from '@angular/platform-browser'; styleUrls: ['./html-textarea-field.component.scss'] }) export class HtmlTextareaFieldComponent extends AbstractHtmlTextareaFieldComponent implements AfterViewInit { - constructor(protected _translate: TranslateService, protected _sanitizer: DomSanitizer, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(_translate, _sanitizer, dataFieldPortalData); + constructor(_translate: TranslateService, protected _sanitizer: DomSanitizer, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(_translate, _sanitizer, dataFieldPortalData, _validationRegistry); } ngAfterViewInit(): void { setTimeout(() => { if (!this.dataField?.placeholder) { - this.dataField.placeholder = this._translate.instant('dataField.textarea.insertText'); + this.dataField.placeholder = this.translate.instant('dataField.textarea.insertText'); } }) } diff --git a/projects/netgrif-components/src/lib/data-fields/text-field/password-text-field/password-text-field.component.ts b/projects/netgrif-components/src/lib/data-fields/text-field/password-text-field/password-text-field.component.ts index 9019d7321..7fa2225cb 100644 --- a/projects/netgrif-components/src/lib/data-fields/text-field/password-text-field/password-text-field.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/text-field/password-text-field/password-text-field.component.ts @@ -3,7 +3,9 @@ import {TranslateService} from '@ngx-translate/core'; import { AbstractPasswordTextFieldComponent, DATA_FIELD_PORTAL_DATA, - DataFieldPortalData, TextField + DataFieldPortalData, + TextField, + ValidationRegistryService } from '@netgrif/components-core'; @Component({ @@ -15,9 +17,10 @@ export class PasswordTextFieldComponent extends AbstractPasswordTextFieldCompone hide: boolean; - constructor(protected _translate: TranslateService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(_translate, dataFieldPortalData); + constructor(_translate: TranslateService, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(_translate, dataFieldPortalData, _validationRegistry); this.hide = true; } } diff --git a/projects/netgrif-components/src/lib/data-fields/text-field/rich-textarea-field/rich-textarea-field.component.ts b/projects/netgrif-components/src/lib/data-fields/text-field/rich-textarea-field/rich-textarea-field.component.ts index ac8afe0ed..bda8b6ffe 100644 --- a/projects/netgrif-components/src/lib/data-fields/text-field/rich-textarea-field/rich-textarea-field.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/text-field/rich-textarea-field/rich-textarea-field.component.ts @@ -3,7 +3,8 @@ import { AbstractRichTextareaFieldComponent, DATA_FIELD_PORTAL_DATA, DataFieldPortalData, - TextAreaField + TextAreaField, + ValidationRegistryService } from '@netgrif/components-core'; import {TranslateService} from '@ngx-translate/core'; @@ -13,8 +14,9 @@ import {TranslateService} from '@ngx-translate/core'; styleUrls: ['./rich-textarea-field.component.scss'] }) export class RichTextareaFieldComponent extends AbstractRichTextareaFieldComponent { - constructor(protected _translate: TranslateService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(_translate, dataFieldPortalData); + constructor(_translate: TranslateService, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(_translate, dataFieldPortalData, _validationRegistry); } } diff --git a/projects/netgrif-components/src/lib/data-fields/text-field/signature-pad-field/signature-pad-field.component.ts b/projects/netgrif-components/src/lib/data-fields/text-field/signature-pad-field/signature-pad-field.component.ts index b1994e758..ab2855327 100644 --- a/projects/netgrif-components/src/lib/data-fields/text-field/signature-pad-field/signature-pad-field.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/text-field/signature-pad-field/signature-pad-field.component.ts @@ -13,7 +13,8 @@ import { DATA_FIELD_PORTAL_DATA, DataFieldPortalData, TextAreaField, - AbstractSimpleTextFieldComponent + AbstractSimpleTextFieldComponent, + ValidationRegistryService } from '@netgrif/components-core'; import {filter} from 'rxjs/operators'; @@ -35,8 +36,9 @@ export class SignaturePadFieldComponent extends AbstractSimpleTextFieldComponent public aspectRatio = 0.2; constructor(protected _translate: TranslateService, protected _ngZone: NgZone, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(_translate, dataFieldPortalData); + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(_translate, dataFieldPortalData, _validationRegistry); } public ngAfterViewInit(): void { diff --git a/projects/netgrif-components/src/lib/data-fields/text-field/simple-text-field/simple-text-field.component.ts b/projects/netgrif-components/src/lib/data-fields/text-field/simple-text-field/simple-text-field.component.ts index 4b5533df1..bce0f4af0 100644 --- a/projects/netgrif-components/src/lib/data-fields/text-field/simple-text-field/simple-text-field.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/text-field/simple-text-field/simple-text-field.component.ts @@ -3,7 +3,8 @@ import { AbstractSimpleTextFieldComponent, DATA_FIELD_PORTAL_DATA, DataFieldPortalData, - TextField + TextField, + ValidationRegistryService } from '@netgrif/components-core'; import {TranslateService} from '@ngx-translate/core'; @@ -13,8 +14,9 @@ import {TranslateService} from '@ngx-translate/core'; styleUrls: ['./simple-text-field.component.scss'] }) export class SimpleTextFieldComponent extends AbstractSimpleTextFieldComponent { - constructor(protected _translate: TranslateService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(_translate, dataFieldPortalData); + constructor(_translate: TranslateService, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(_translate, dataFieldPortalData, _validationRegistry); } } diff --git a/projects/netgrif-components/src/lib/data-fields/text-field/textarea-field/textarea-field.component.ts b/projects/netgrif-components/src/lib/data-fields/text-field/textarea-field/textarea-field.component.ts index b4e2614ba..c6a85de34 100644 --- a/projects/netgrif-components/src/lib/data-fields/text-field/textarea-field/textarea-field.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/text-field/textarea-field/textarea-field.component.ts @@ -4,7 +4,8 @@ import { AbstractTextareaFieldComponent, DATA_FIELD_PORTAL_DATA, DataFieldPortalData, - TextAreaField + TextAreaField, + ValidationRegistryService } from '@netgrif/components-core'; @Component({ @@ -14,8 +15,9 @@ import { }) export class TextareaFieldComponent extends AbstractTextareaFieldComponent { - constructor(protected _translate: TranslateService, protected _ngZone: NgZone, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(_translate, _ngZone, dataFieldPortalData); + constructor(_translate: TranslateService, protected _ngZone: NgZone, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(_translate, _ngZone, dataFieldPortalData, _validationRegistry); } } diff --git a/projects/netgrif-components/src/lib/data-fields/user-field/user-default-field/user-default-field.component.ts b/projects/netgrif-components/src/lib/data-fields/user-field/user-default-field/user-default-field.component.ts index 83bef5e94..b222e7be4 100644 --- a/projects/netgrif-components/src/lib/data-fields/user-field/user-default-field/user-default-field.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/user-field/user-default-field/user-default-field.component.ts @@ -5,7 +5,8 @@ import { SnackBarService, DataFieldPortalData, UserField, - AbstractUserDefaultFieldComponent + AbstractUserDefaultFieldComponent, + ValidationRegistryService } from '@netgrif/components-core'; import {UserAssignDialogComponent} from '../../../dialog/user-assign-dialog/user-assign-dialog.component'; import {MatDialog} from '@angular/material/dialog'; @@ -20,8 +21,9 @@ export class UserDefaultFieldComponent extends AbstractUserDefaultFieldComponent constructor(dialog: MatDialog, snackbar: SnackBarService, translate: TranslateService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(dialog, snackbar, translate, dataFieldPortalData); + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData, + _validationRegistry: ValidationRegistryService) { + super(dialog, snackbar, translate, dataFieldPortalData, _validationRegistry); } public selectUser() { diff --git a/projects/netgrif-components/src/lib/navigation/breadcrumbs/breadcrumbs.component.ts b/projects/netgrif-components/src/lib/navigation/breadcrumbs/breadcrumbs.component.ts index 7a6b01693..ea80ebbcb 100644 --- a/projects/netgrif-components/src/lib/navigation/breadcrumbs/breadcrumbs.component.ts +++ b/projects/netgrif-components/src/lib/navigation/breadcrumbs/breadcrumbs.component.ts @@ -13,7 +13,7 @@ import {TranslateService} from "@ngx-translate/core"; }) export class BreadcrumbsComponent extends AbstractBreadcrumbsComponent { - constructor(protected _uriService: UriService, + constructor(_uriService: UriService, _caseResourceService: CaseResourceService, _activatedRoute: ActivatedRoute, _router: Router,