From ffa8a2c63f33e46ad599bba1c56b09d37d8923e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Grabowski?= Date: Thu, 7 Aug 2025 16:31:50 +0200 Subject: [PATCH 1/6] IBX-10471: [Inputs] Inputs Validators Base --- .../src/internal/hooks/useValidatorManager.ts | 13 +++++++ .../src/validators/BaseValidator.ts | 15 +++++++ .../src/validators/IsEmptyStringValidator.ts | 13 +++++++ .../src/validators/ValidatorManager.ts | 39 +++++++++++++++++++ 4 files changed, 80 insertions(+) create mode 100644 packages/components/src/internal/hooks/useValidatorManager.ts create mode 100644 packages/components/src/validators/BaseValidator.ts create mode 100644 packages/components/src/validators/IsEmptyStringValidator.ts create mode 100644 packages/components/src/validators/ValidatorManager.ts diff --git a/packages/components/src/internal/hooks/useValidatorManager.ts b/packages/components/src/internal/hooks/useValidatorManager.ts new file mode 100644 index 0000000..fcf0b3b --- /dev/null +++ b/packages/components/src/internal/hooks/useValidatorManager.ts @@ -0,0 +1,13 @@ +import { useContext, useRef } from 'react'; + +import { TranslatorContext } from '@ids-context/Translator'; + +import BaseValidator from '../../validators/BaseValidator'; +import ValidatorManager from '../../validators/ValidatorManager'; + +export default (validators: BaseValidator[] = []) => { + const translator = useContext(TranslatorContext); + const validatorManagerInstance = useRef(new ValidatorManager(validators, { translator })); + + return validatorManagerInstance.current; +}; diff --git a/packages/components/src/validators/BaseValidator.ts b/packages/components/src/validators/BaseValidator.ts new file mode 100644 index 0000000..8befc85 --- /dev/null +++ b/packages/components/src/validators/BaseValidator.ts @@ -0,0 +1,15 @@ +import { TranslatorType } from '@ids-context/Translator'; + +export default abstract class BaseValidator { + protected _translator!: TranslatorType; + + setTranslator(translator: TranslatorType) { + this._translator = translator; + } + + abstract getErrorMessage(): string; + + abstract validate(_value: unknown): boolean; +} + +export type BaseValidatorType = typeof BaseValidator; diff --git a/packages/components/src/validators/IsEmptyStringValidator.ts b/packages/components/src/validators/IsEmptyStringValidator.ts new file mode 100644 index 0000000..a0f43d8 --- /dev/null +++ b/packages/components/src/validators/IsEmptyStringValidator.ts @@ -0,0 +1,13 @@ +import BaseValidator from './BaseValidator'; + +export default class IsEmptyStringValidator extends BaseValidator { + getErrorMessage(): string { + const Translator = this._translator; + + return Translator.trans(/*@Desc("This field cannot be empty.")*/ 'ibexa.validators.is_empty_string'); + } + + validate(value: string): boolean { + return value.trim() !== ''; + } +} diff --git a/packages/components/src/validators/ValidatorManager.ts b/packages/components/src/validators/ValidatorManager.ts new file mode 100644 index 0000000..17c7463 --- /dev/null +++ b/packages/components/src/validators/ValidatorManager.ts @@ -0,0 +1,39 @@ +import { TranslatorType } from '@ids-context/Translator/Translator.types'; + +import BaseValidator from './BaseValidator'; + +interface ValidatorManagerOptions { + translator: TranslatorType; +} + +export default class ValidatorManager { + private _validators: BaseValidator[]; + private _translator: TranslatorType; + + constructor(validators: BaseValidator[] = [], { translator }: ValidatorManagerOptions) { + validators.forEach((validator) => { + validator.setTranslator(translator); + }); + + this._validators = validators; + this._translator = translator; + } + + addValidator(validator: BaseValidator): void { + validator.setTranslator(this._translator); + + this._validators.push(validator); + } + + removeValidator(validator: BaseValidator): void { + this._validators = this._validators.filter((savedValidator) => savedValidator !== validator); + } + + validate(value: unknown) { + const errors = this._validators + .filter((validator: BaseValidator) => !validator.validate(value)) + .map((validator: BaseValidator) => validator.getErrorMessage()); + + return { isValid: !errors.length, messages: errors }; + } +} From 6f65e4df66165cb1209d238825fdffe69f19ae80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Grabowski?= Date: Mon, 18 Aug 2025 13:40:53 +0200 Subject: [PATCH 2/6] copilot suggestion fixes --- .../src/internal/hooks/useValidatorManager.ts | 4 ++-- .../src/validators/BaseValidator.ts | 7 +++---- .../src/validators/IsEmptyStringValidator.ts | 2 +- .../src/validators/ValidatorManager.ts | 21 ++++++++++++------- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/packages/components/src/internal/hooks/useValidatorManager.ts b/packages/components/src/internal/hooks/useValidatorManager.ts index fcf0b3b..cfe22d8 100644 --- a/packages/components/src/internal/hooks/useValidatorManager.ts +++ b/packages/components/src/internal/hooks/useValidatorManager.ts @@ -5,9 +5,9 @@ import { TranslatorContext } from '@ids-context/Translator'; import BaseValidator from '../../validators/BaseValidator'; import ValidatorManager from '../../validators/ValidatorManager'; -export default (validators: BaseValidator[] = []) => { +export default (validators: BaseValidator[] = []) => { const translator = useContext(TranslatorContext); - const validatorManagerInstance = useRef(new ValidatorManager(validators, { translator })); + const validatorManagerInstance = useRef(new ValidatorManager(validators, { translator })); return validatorManagerInstance.current; }; diff --git a/packages/components/src/validators/BaseValidator.ts b/packages/components/src/validators/BaseValidator.ts index 8befc85..5199a45 100644 --- a/packages/components/src/validators/BaseValidator.ts +++ b/packages/components/src/validators/BaseValidator.ts @@ -1,6 +1,7 @@ import { TranslatorType } from '@ids-context/Translator'; -export default abstract class BaseValidator { +// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters +export default abstract class BaseValidator { protected _translator!: TranslatorType; setTranslator(translator: TranslatorType) { @@ -9,7 +10,5 @@ export default abstract class BaseValidator { abstract getErrorMessage(): string; - abstract validate(_value: unknown): boolean; + abstract validate(_value: T): boolean; } - -export type BaseValidatorType = typeof BaseValidator; diff --git a/packages/components/src/validators/IsEmptyStringValidator.ts b/packages/components/src/validators/IsEmptyStringValidator.ts index a0f43d8..4ce3fc4 100644 --- a/packages/components/src/validators/IsEmptyStringValidator.ts +++ b/packages/components/src/validators/IsEmptyStringValidator.ts @@ -1,6 +1,6 @@ import BaseValidator from './BaseValidator'; -export default class IsEmptyStringValidator extends BaseValidator { +export default class IsEmptyStringValidator extends BaseValidator { getErrorMessage(): string { const Translator = this._translator; diff --git a/packages/components/src/validators/ValidatorManager.ts b/packages/components/src/validators/ValidatorManager.ts index 17c7463..90693f0 100644 --- a/packages/components/src/validators/ValidatorManager.ts +++ b/packages/components/src/validators/ValidatorManager.ts @@ -6,11 +6,16 @@ interface ValidatorManagerOptions { translator: TranslatorType; } -export default class ValidatorManager { - private _validators: BaseValidator[]; +export interface ValidateReturnType { + isValid: boolean; + messages: string[]; +} + +export default class ValidatorManager { + private _validators: BaseValidator[]; private _translator: TranslatorType; - constructor(validators: BaseValidator[] = [], { translator }: ValidatorManagerOptions) { + constructor(validators: BaseValidator[] = [], { translator }: ValidatorManagerOptions) { validators.forEach((validator) => { validator.setTranslator(translator); }); @@ -19,20 +24,20 @@ export default class ValidatorManager { this._translator = translator; } - addValidator(validator: BaseValidator): void { + addValidator(validator: BaseValidator): void { validator.setTranslator(this._translator); this._validators.push(validator); } - removeValidator(validator: BaseValidator): void { + removeValidator(validator: BaseValidator): void { this._validators = this._validators.filter((savedValidator) => savedValidator !== validator); } - validate(value: unknown) { + validate(value: T): ValidateReturnType { const errors = this._validators - .filter((validator: BaseValidator) => !validator.validate(value)) - .map((validator: BaseValidator) => validator.getErrorMessage()); + .filter((validator: BaseValidator) => !validator.validate(value)) + .map((validator: BaseValidator) => validator.getErrorMessage()); return { isValid: !errors.length, messages: errors }; } From 2d269575fdba7616502a1612b9a1cdb6413014c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Grabowski?= Date: Wed, 20 Aug 2025 13:35:15 +0200 Subject: [PATCH 3/6] redo validators --- .../src/internal/hooks/useValidatorManager.ts | 13 ------ .../src/internal/shared/validators.ts | 14 ++++++ .../src/validators/BaseValidator.ts | 5 +-- .../src/validators/ValidatorManager.ts | 44 ------------------- 4 files changed, 16 insertions(+), 60 deletions(-) delete mode 100644 packages/components/src/internal/hooks/useValidatorManager.ts create mode 100644 packages/components/src/internal/shared/validators.ts delete mode 100644 packages/components/src/validators/ValidatorManager.ts diff --git a/packages/components/src/internal/hooks/useValidatorManager.ts b/packages/components/src/internal/hooks/useValidatorManager.ts deleted file mode 100644 index cfe22d8..0000000 --- a/packages/components/src/internal/hooks/useValidatorManager.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { useContext, useRef } from 'react'; - -import { TranslatorContext } from '@ids-context/Translator'; - -import BaseValidator from '../../validators/BaseValidator'; -import ValidatorManager from '../../validators/ValidatorManager'; - -export default (validators: BaseValidator[] = []) => { - const translator = useContext(TranslatorContext); - const validatorManagerInstance = useRef(new ValidatorManager(validators, { translator })); - - return validatorManagerInstance.current; -}; diff --git a/packages/components/src/internal/shared/validators.ts b/packages/components/src/internal/shared/validators.ts new file mode 100644 index 0000000..666df3d --- /dev/null +++ b/packages/components/src/internal/shared/validators.ts @@ -0,0 +1,14 @@ +import BaseValidator from '../../validators/BaseValidator'; + +export interface ValidateReturnType { + isValid: boolean; + messages: string[]; +} + +export const validateInput = (value: T, validators: BaseValidator[]): ValidateReturnType => { + const errors = validators + .filter((validator: BaseValidator) => !validator.validate(value)) + .map((validator: BaseValidator) => validator.getErrorMessage()); + + return { isValid: !errors.length, messages: errors }; +}; diff --git a/packages/components/src/validators/BaseValidator.ts b/packages/components/src/validators/BaseValidator.ts index 5199a45..30d76d0 100644 --- a/packages/components/src/validators/BaseValidator.ts +++ b/packages/components/src/validators/BaseValidator.ts @@ -1,10 +1,9 @@ import { TranslatorType } from '@ids-context/Translator'; -// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters export default abstract class BaseValidator { - protected _translator!: TranslatorType; + protected _translator: TranslatorType; - setTranslator(translator: TranslatorType) { + constructor(translator: TranslatorType) { this._translator = translator; } diff --git a/packages/components/src/validators/ValidatorManager.ts b/packages/components/src/validators/ValidatorManager.ts deleted file mode 100644 index 90693f0..0000000 --- a/packages/components/src/validators/ValidatorManager.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { TranslatorType } from '@ids-context/Translator/Translator.types'; - -import BaseValidator from './BaseValidator'; - -interface ValidatorManagerOptions { - translator: TranslatorType; -} - -export interface ValidateReturnType { - isValid: boolean; - messages: string[]; -} - -export default class ValidatorManager { - private _validators: BaseValidator[]; - private _translator: TranslatorType; - - constructor(validators: BaseValidator[] = [], { translator }: ValidatorManagerOptions) { - validators.forEach((validator) => { - validator.setTranslator(translator); - }); - - this._validators = validators; - this._translator = translator; - } - - addValidator(validator: BaseValidator): void { - validator.setTranslator(this._translator); - - this._validators.push(validator); - } - - removeValidator(validator: BaseValidator): void { - this._validators = this._validators.filter((savedValidator) => savedValidator !== validator); - } - - validate(value: T): ValidateReturnType { - const errors = this._validators - .filter((validator: BaseValidator) => !validator.validate(value)) - .map((validator: BaseValidator) => validator.getErrorMessage()); - - return { isValid: !errors.length, messages: errors }; - } -} From f31e969b8530cf5dc8bdee342849f7f104aaf123 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Grabowski?= Date: Fri, 22 Aug 2025 13:58:41 +0200 Subject: [PATCH 4/6] after CR --- .../components/src/internal/shared/validators.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/components/src/internal/shared/validators.ts b/packages/components/src/internal/shared/validators.ts index 666df3d..17fffa9 100644 --- a/packages/components/src/internal/shared/validators.ts +++ b/packages/components/src/internal/shared/validators.ts @@ -1,14 +1,19 @@ import BaseValidator from '../../validators/BaseValidator'; -export interface ValidateReturnType { +export interface ValidationResult { isValid: boolean; messages: string[]; } -export const validateInput = (value: T, validators: BaseValidator[]): ValidateReturnType => { +export const validateInput = (value: T, validators: BaseValidator[]): ValidationResult => { const errors = validators - .filter((validator: BaseValidator) => !validator.validate(value)) - .map((validator: BaseValidator) => validator.getErrorMessage()); + .reduce((errorsAcc: string[], validator) => { + if (!validator.validate(value)) { + return [...errorsAcc, validator.getErrorMessage()]; + } + + return errorsAcc; + }, []); return { isValid: !errors.length, messages: errors }; }; From 670a18f2f3fa75cf987db64097a2546f82ee2243 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Grabowski?= Date: Fri, 22 Aug 2025 14:06:30 +0200 Subject: [PATCH 5/6] linter --- .../components/src/internal/shared/validators.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/components/src/internal/shared/validators.ts b/packages/components/src/internal/shared/validators.ts index 17fffa9..d3d2962 100644 --- a/packages/components/src/internal/shared/validators.ts +++ b/packages/components/src/internal/shared/validators.ts @@ -6,14 +6,13 @@ export interface ValidationResult { } export const validateInput = (value: T, validators: BaseValidator[]): ValidationResult => { - const errors = validators - .reduce((errorsAcc: string[], validator) => { - if (!validator.validate(value)) { - return [...errorsAcc, validator.getErrorMessage()]; - } + const errors = validators.reduce((errorsAcc: string[], validator) => { + if (!validator.validate(value)) { + return [...errorsAcc, validator.getErrorMessage()]; + } - return errorsAcc; - }, []); + return errorsAcc; + }, []); return { isValid: !errors.length, messages: errors }; }; From da562417e842eebb3b45a092d4c44fa8c2a34fd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Grabowski?= Date: Mon, 25 Aug 2025 09:53:56 +0200 Subject: [PATCH 6/6] removed _ --- packages/components/src/validators/BaseValidator.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/validators/BaseValidator.ts b/packages/components/src/validators/BaseValidator.ts index 30d76d0..db41311 100644 --- a/packages/components/src/validators/BaseValidator.ts +++ b/packages/components/src/validators/BaseValidator.ts @@ -9,5 +9,5 @@ export default abstract class BaseValidator { abstract getErrorMessage(): string; - abstract validate(_value: T): boolean; + abstract validate(value: T): boolean; }