From 0ef3a740a8a666767bfe1920ecacdb3992cdd83b Mon Sep 17 00:00:00 2001 From: BennoDev Date: Tue, 21 Sep 2021 16:54:41 +0200 Subject: [PATCH 01/14] updated multieditor [wip] --- .../multieditor-ts/src/core/signUpEditor.ts | 8 +- .../react/develop/multieditor-ts/yarn.lock | 16 +- .../core/src/computed/computed.tracker.ts | 2 +- packages/multieditor/src/multieditor/index.ts | 5 +- .../src/multieditor/multieditor.ts | 3 +- .../multieditor/src/status/status.tracker.ts | 51 ++++++ packages/multieditor/src/status/status.ts | 25 +-- .../src/validator/types/general.ts | 23 +++ .../multieditor/src/validator/types/number.ts | 0 .../src/validator/types/number.validator.ts | 145 --------------- .../multieditor/src/validator/types/string.ts | 0 .../src/validator/types/string.validator.ts | 171 ------------------ .../multieditor/src/validator/validator.ts | 154 ++++------------ 13 files changed, 126 insertions(+), 477 deletions(-) create mode 100644 packages/multieditor/src/status/status.tracker.ts create mode 100644 packages/multieditor/src/validator/types/general.ts create mode 100644 packages/multieditor/src/validator/types/number.ts delete mode 100644 packages/multieditor/src/validator/types/number.validator.ts create mode 100644 packages/multieditor/src/validator/types/string.ts delete mode 100644 packages/multieditor/src/validator/types/string.validator.ts diff --git a/examples/react/develop/multieditor-ts/src/core/signUpEditor.ts b/examples/react/develop/multieditor-ts/src/core/signUpEditor.ts index cf17f812..e21a0478 100644 --- a/examples/react/develop/multieditor-ts/src/core/signUpEditor.ts +++ b/examples/react/develop/multieditor-ts/src/core/signUpEditor.ts @@ -7,7 +7,8 @@ export const isValidNameValidator = new Validator() .string() .min(2) .max(10) - .matches(/^([^0-9]*)$/, 'No Numbers allowed!'); + .matches(/^([^0-9]*)$/, 'No Numbers allowed!') + .main(); export const signUpEditor = createMultieditor((editor) => ({ data: { @@ -38,19 +39,20 @@ export const signUpEditor = createMultieditor((editor) => ({ editor.setStatus(key, 'error', 'Sry only the name Jeff is allowed!'); return isValid; }), - email: editor.Validator().required().string().email(), + email: editor.Validator().required().string().email().main(), aboutYou: editor .Validator() .required() .string() .min(10) + .main() .addValidationMethod(async (key, value, editor) => { const isValid = typeof value === 'string' && !value.includes('fuck'); if (!isValid) editor.setStatus(key, 'error', 'The word fuck is not allowed!'); return isValid; }), - age: editor.Validator().required().number().min(18).max(100), + age: editor.Validator().required().number().min(18).max(100).main(), gender: editor.Validator().required(), image: editor .Validator() diff --git a/examples/react/develop/multieditor-ts/yarn.lock b/examples/react/develop/multieditor-ts/yarn.lock index 05539362..268a94d3 100644 --- a/examples/react/develop/multieditor-ts/yarn.lock +++ b/examples/react/develop/multieditor-ts/yarn.lock @@ -3,20 +3,20 @@ "@agile-ts/core@file:.yalc/@agile-ts/core": - version "0.2.3" + version "0.2.5" dependencies: - "@agile-ts/utils" "^0.0.8" + "@agile-ts/utils" "^0.0.9" "@agile-ts/multieditor@file:.yalc/@agile-ts/multieditor": - version "0.0.21" + version "0.0.22" "@agile-ts/react@file:.yalc/@agile-ts/react": - version "0.2.0" + version "0.2.1" -"@agile-ts/utils@^0.0.8": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@agile-ts/utils/-/utils-0.0.8.tgz#ab9e1eeaddf282340936bddeb74421a2f77de804" - integrity sha512-ex19gPIS5imgV+rzs5HE2CNAIkQ162hPWH5u3HKNZnHiVU6FX62sikH5tG2oQocbDb7FkeB16D7v9ihQeuKYug== +"@agile-ts/utils@^0.0.9": + version "0.0.9" + resolved "https://registry.yarnpkg.com/@agile-ts/utils/-/utils-0.0.9.tgz#b20d03cc450d1a916bb7d8836c3451cb06cc882c" + integrity sha512-M9/QQjX+I5r11MwztfK371/kfInmJS7kLlAKmG8ZkgqG/x8LdCxD7tOTwqMa9Dc1p1ZJqSvNzL/Y8l7boi/3IQ== "@babel/code-frame@7.8.3": version "7.8.3" diff --git a/packages/core/src/computed/computed.tracker.ts b/packages/core/src/computed/computed.tracker.ts index 44d16906..48152ffa 100644 --- a/packages/core/src/computed/computed.tracker.ts +++ b/packages/core/src/computed/computed.tracker.ts @@ -23,7 +23,7 @@ export class ComputedTracker { } /** - * Tracks the passed Observer and caches it + * Tracks the specified Observer and caches it * when the Computed Tracker is actively tracking. * * @internal diff --git a/packages/multieditor/src/multieditor/index.ts b/packages/multieditor/src/multieditor/index.ts index 5cb43fef..011117c6 100644 --- a/packages/multieditor/src/multieditor/index.ts +++ b/packages/multieditor/src/multieditor/index.ts @@ -12,11 +12,8 @@ export function createMultieditor< config: EditorConfig, agileInstance: Agile = shared ): Multieditor { - config = defineConfig(config, { - agileInstance: shared, - }); return new Multieditor( config, - agileInstance as any + agileInstance ); } diff --git a/packages/multieditor/src/multieditor/multieditor.ts b/packages/multieditor/src/multieditor/multieditor.ts index 4d2b1400..e5666440 100644 --- a/packages/multieditor/src/multieditor/multieditor.ts +++ b/packages/multieditor/src/multieditor/multieditor.ts @@ -1,12 +1,11 @@ import { Agile, ComputeValueMethod, - copy, getAgileInstance, LogCodeManager, Observer, - defineConfig, } from '@agile-ts/core'; +import { defineConfig, copy } from '@agile-ts/utils'; import { ValidationMethodInterface, Validator } from '../validator'; import { Item } from '../item'; import { StatusInterface, StatusType } from '../status'; diff --git a/packages/multieditor/src/status/status.tracker.ts b/packages/multieditor/src/status/status.tracker.ts new file mode 100644 index 00000000..6e8c76b1 --- /dev/null +++ b/packages/multieditor/src/status/status.tracker.ts @@ -0,0 +1,51 @@ +import { StatusInterface } from './status'; + +export class StatusTracker { + isTracking = false; + trackedStatuses: Set = new Set(); + + /** + * Helper Class for automatic tracking set Statuses in validation methods. + * + * @internal + */ + constructor() { + // empty + } + + /** + * Activates Computed Tracker to globally track used Statuses. + * + * @internal + */ + track(): void { + this.isTracking = true; + } + + /** + * Tracks the specified Status and caches it + * when the Computed Tracker is actively tracking. + * + * @internal + * @param status - Status + */ + tracked(status: StatusInterface) { + if (this.isTracking) this.trackedStatuses.add(status); + } + + /** + * Returns the latest tracked Statuses + * and stops the Status Tracker from tracking any more Statuses. + * + * @internal + */ + getTrackedStatuses(): Array { + const trackedStatuses = Array.from(this.trackedStatuses); + + // Reset Computed Tracker + this.isTracking = false; + this.trackedStatuses = new Set(); + + return trackedStatuses; + } +} diff --git a/packages/multieditor/src/status/status.ts b/packages/multieditor/src/status/status.ts index 235fafd4..2790c4ff 100644 --- a/packages/multieditor/src/status/status.ts +++ b/packages/multieditor/src/status/status.ts @@ -1,6 +1,7 @@ import { Agile, copy, RuntimeJobConfigInterface } from '@agile-ts/core'; import { Item } from '../item'; import { StatusObserver } from './status.observer'; +import { StatusTracker } from './status.tracker'; export class Status { public agileInstance: () => Agile; @@ -13,9 +14,7 @@ export class Status { public nextValue: StatusInterface | null; // The last set Value public activeValues: Set = new Set(); // All Values that got set during the validation Time of the Validator - // Tracking - public track = false; - public foundValues: Set = new Set(); + public statusTracker: StatusTracker; /** * @public @@ -28,6 +27,7 @@ export class Status { this._value = null; this.nextValue = null; this.observer = new StatusObserver(this.agileInstance(), this); + this.statusTracker = new StatusTracker(); } /** @@ -51,7 +51,7 @@ export class Status { this.nextValue = copy(value); // Track Status - if (this.track && value) this.foundValues.add(value); + if (value != null) this.statusTracker.tracked(value); // Assign Status to Item if (this.item.editor().canAssignStatusToItemOnChange(this.item)) @@ -71,23 +71,6 @@ export class Status { public assign(config: RuntimeJobConfigInterface = {}) { this.observer.assign(config); } - - //========================================================================================================= - // Get Tracked Statuses - //========================================================================================================= - /** - * @internal - * Returns tracked Values and stops Status from tracking anymore Values - */ - public getTrackedValues(): Set { - const finalFoundStatuses = this.foundValues; - - // Reset tracking - this.track = false; - this.foundValues = new Set(); - - return finalFoundStatuses; - } } export type StatusType = 'error' | 'success'; diff --git a/packages/multieditor/src/validator/types/general.ts b/packages/multieditor/src/validator/types/general.ts new file mode 100644 index 00000000..b19ed27f --- /dev/null +++ b/packages/multieditor/src/validator/types/general.ts @@ -0,0 +1,23 @@ +import { ValidatorMethodConfigInterface } from '../validator'; +import { defineConfig } from '@agile-ts/core'; + +export async function isRequired( + config: ValidatorMethodConfigInterface +) { + config = defineConfig(config, { + key: 'isRequired', + errorMessage: `${config.key} is a required field`, + }); + + const isValid = !!config.value; + + if (!isValid) { + config.editor.setStatus( + config.key as any, + 'error', + config.errorMessage as any + ); + } + + return isValid; +} diff --git a/packages/multieditor/src/validator/types/number.ts b/packages/multieditor/src/validator/types/number.ts new file mode 100644 index 00000000..e69de29b diff --git a/packages/multieditor/src/validator/types/number.validator.ts b/packages/multieditor/src/validator/types/number.validator.ts deleted file mode 100644 index 660d4792..00000000 --- a/packages/multieditor/src/validator/types/number.validator.ts +++ /dev/null @@ -1,145 +0,0 @@ -import { copy } from '@agile-ts/core'; -import { Validator } from '../validator'; - -export class NumberValidator extends Validator { - /** - * @public - * Number Validator - * @param validator - Validator - * @param errorMessage - Error Message - */ - constructor(validator: Validator, errorMessage?: string) { - super({ key: validator.key, prefix: 'number' }); - - // Copy ValidationMethods of old Validator into this Validator - for (const key in validator.validationMethods) { - this.validationMethods[key] = copy(validator.validationMethods[key]); - } - - // Add Number Validation Method - this.addValidationMethod( - this.getValidationMethodKey('isNumber'), - async (key, value, editor) => { - const isValid = typeof value === 'number'; - if (!isValid) { - editor.setStatus( - key, - 'error', - errorMessage || `${key} is no valid Number!` - ); - } - return isValid; - } - ); - } - - //========================================================================================================= - // Max Number - //========================================================================================================= - /** - * @public - * Checks if Editor Value is to large - * @param number - max Number - * @param errorMessage - Error Message - */ - public max(number: number, errorMessage?: string): this { - this.addValidationMethod( - this.getValidationMethodKey('maxNumber'), - async (key, value, editor) => { - if (!value || typeof value !== 'number') return false; - const isValid = value <= number; - if (!isValid) { - editor.setStatus( - key, - 'error', - errorMessage || `${key} has to be smaller than ${number}` - ); - } - return isValid; - } - ); - return this; - } - - //========================================================================================================= - // Min Number - //========================================================================================================= - /** - * @public - * Checks if Editor Value is to small - * @param number - min Number - * @param errorMessage - Error Message - */ - public min(number: number, errorMessage?: string): this { - this.addValidationMethod( - this.getValidationMethodKey('minNumber'), - async (key, value, editor) => { - if (!value || typeof value !== 'number') return false; - const isValid = value >= number; - if (!isValid) { - editor.setStatus( - key, - 'error', - errorMessage || `${key} has to be larger than ${number}` - ); - } - return isValid; - } - ); - return this; - } - - //========================================================================================================= - // Positive - //========================================================================================================= - /** - * @public - * Checks if Editor Value is positive - * @param errorMessage - Error Message - */ - public positive(errorMessage?: string): this { - this.addValidationMethod( - this.getValidationMethodKey('positive'), - async (key, value, editor) => { - if (!value || typeof value !== 'number') return false; - const isValid = value >= 0; - if (!isValid) { - editor.setStatus( - key, - 'error', - errorMessage || `${key} has to be positive` - ); - } - return isValid; - } - ); - return this; - } - - //========================================================================================================= - // Negative - //========================================================================================================= - /** - * @public - * Checks if Editor Value is negative - * @param errorMessage - Error Message - */ - public negative(errorMessage?: string): this { - this.addValidationMethod( - this.getValidationMethodKey('negative'), - async (key, value, editor) => { - if (!value || typeof value !== 'number') return false; - const isValid = value < 0; - if (!isValid) { - editor.setStatus( - key, - 'error', - errorMessage || `${key} has to be negative` - ); - } - return isValid; - } - ); - return this; - } -} diff --git a/packages/multieditor/src/validator/types/string.ts b/packages/multieditor/src/validator/types/string.ts new file mode 100644 index 00000000..e69de29b diff --git a/packages/multieditor/src/validator/types/string.validator.ts b/packages/multieditor/src/validator/types/string.validator.ts deleted file mode 100644 index 0fe73901..00000000 --- a/packages/multieditor/src/validator/types/string.validator.ts +++ /dev/null @@ -1,171 +0,0 @@ -import { copy } from '@agile-ts/utils'; -import { Validator } from '../validator'; - -export class StringValidator extends Validator { - /** - * @public - * String Validator - * @param validator - Validator - * @param errorMessage - Error Message - */ - constructor(validator: Validator, errorMessage?: string) { - super({ key: validator.key, prefix: 'string' }); - - // Copy ValidationMethods of old Validator into this Validator - for (const key in validator.validationMethods) - this.validationMethods[key] = copy(validator.validationMethods[key]); - - // Add String Validation Method - this.addValidationMethod( - this.getValidationMethodKey('isString'), - async (key, value, editor) => { - const isValid = typeof value === 'string'; - if (!isValid) { - editor.setStatus( - key, - 'error', - errorMessage || `${key} is no valid String!` - ); - } - return isValid; - } - ); - } - - //========================================================================================================= - // Max Length - //========================================================================================================= - /** - * @public - * Checks if Editor Value is to long - * @param length - max Length - * @param errorMessage - Error Message - */ - public max(length: number, errorMessage?: string): this { - this.addValidationMethod( - this.getValidationMethodKey('maxLength'), - async (key, value, editor) => { - if (!value || typeof value !== 'string') return false; - const isValid = value.length <= length; - if (!isValid) { - editor.setStatus( - key, - 'error', - errorMessage || `${key} has more than ${length} characters` - ); - } - return isValid; - } - ); - return this; - } - - //========================================================================================================= - // Min Length - //========================================================================================================= - /** - * @public - * Checks if Editor Value is to short - * @param length - min Length - * @param errorMessage - Error Message - */ - public min(length: number, errorMessage?: string): this { - this.addValidationMethod( - this.getValidationMethodKey('minLength'), - async (key, value, editor) => { - if (!value || typeof value !== 'string') return false; - const isValid = value.length >= length; - if (!isValid) { - editor.setStatus( - key, - 'error', - errorMessage || `${key} needs at least ${length} characters` - ); - } - return isValid; - } - ); - return this; - } - - //========================================================================================================= - // Email - //========================================================================================================= - /** - * @public - * Checks that the Editor Value is a valid Email - * @param errorMessage - Error Message - */ - public email(errorMessage?: string): this { - this.addValidationMethod( - this.getValidationMethodKey('email'), - async (key, value, editor) => { - if (!value || typeof value !== 'string') return false; - const emailRegex = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; - const isValid = emailRegex.test(value.toLowerCase()); - if (!isValid) { - editor.setStatus( - key, - 'error', - errorMessage || `${key} is no valid email` - ); - } - return isValid; - } - ); - return this; - } - - //========================================================================================================= - // Url - //========================================================================================================= - /** - * @public - * Checks that the Editor Value is a valid Url - * @param errorMessage - Error Message - */ - public url(errorMessage?: string): this { - this.addValidationMethod( - this.getValidationMethodKey('email'), - async (key, value, editor) => { - if (!value || typeof value !== 'string') return false; - const urlRegex = /[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)?/gi; - const isValid = urlRegex.test(value.toLowerCase()); - if (!isValid) { - editor.setStatus( - key, - 'error', - errorMessage || `${key} is no valid url` - ); - } - return isValid; - } - ); - return this; - } - - //========================================================================================================= - // Regex - //========================================================================================================= - /** - * @public - * Checks that the Editor Value matches a specific Regex - * @param regex - Regex the Value should match - * @param errorMessage - Error Message - */ - public matches(regex: RegExp, errorMessage?: string): this { - this.addValidationMethod(async (key, value, editor) => { - if (!value || typeof value !== 'string') return false; - const isValid = regex.test(value.toLowerCase()); - if (!isValid) { - editor.setStatus( - key, - 'error', - errorMessage || `${key} doesn't follow defined regex` - ); - } - return isValid; - }); - return this; - } -} diff --git a/packages/multieditor/src/validator/validator.ts b/packages/multieditor/src/validator/validator.ts index c0dd21b0..a7008de4 100644 --- a/packages/multieditor/src/validator/validator.ts +++ b/packages/multieditor/src/validator/validator.ts @@ -6,13 +6,13 @@ import { defineConfig, } from '@agile-ts/core'; import { DataObject, ItemKey, Multieditor } from '../multieditor'; -import { StringValidator } from './types/string.validator'; -import { NumberValidator } from './types/number.validator'; +import { normalizeArray } from '@agile-ts/utils'; export class Validator { public _key?: ValidatorKey; public config: ValidatorConfigInterface = {}; - public validationMethods: DataObject = {}; + public validationMethods: DataObject> = + {}; /** * @public @@ -42,16 +42,6 @@ export class Validator { return this._key; } - //========================================================================================================= - // Validate - //========================================================================================================= - /** - * @public - * Validates Item Value at Key and updates its Status - * @param key - Key/Name of Item - * @param value - Value that gets validated - * @param editor - MultiEditor that holds the Item which gets validated - */ public async validate( key: ItemKey, value: DataType, @@ -59,46 +49,32 @@ export class Validator { ): Promise { let isValid = true; const item = editor.getItemById(key); - if (!item) return false; + if (item == null) return false; - // Reverse because the first validation Method should have the highest weight (needs to be called as last to overwrite the Status) + // Reverse validation methods because the first method should have the highest weight const validationMethodKeys = Object.keys(this.validationMethods).reverse(); // Track created Statuses during the Validation Time - item.status.track = true; + item.status.statusTracker.track(); - // Call validationMethods (Validation Time) + // Call validation methods (-> validate Item at specified key) for (const validationMethodKey of validationMethodKeys) isValid = - (await this.validationMethods[validationMethodKey]( + (await this.validationMethods[validationMethodKey]({ key, value, - editor - )) && isValid; + editor, + })) && isValid; // Handle tracked Statuses - const foundStatuses = item.status.getTrackedValues(); - item.status.activeValues = new Set(foundStatuses); - if (foundStatuses.size <= 0) editor.resetStatus(key); + const trackedStatuses = item.status.statusTracker.getTrackedStatuses(); + item.status.activeValues = new Set(trackedStatuses); + if (trackedStatuses.length <= 0) editor.resetStatus(key); return isValid; } - //========================================================================================================= - // Add Validation Method - //========================================================================================================= - /** - * @public - * Adds Validation Method to Validator - * @param method - Validation Method - */ public addValidationMethod(method: ValidationMethodInterface): this; - /** - * @public - * Adds Validation Method to Validator - * @param key - Key of Validation Method - * @param method - Validation Method - */ public addValidationMethod( key: ItemKey, method: ValidationMethodInterface @@ -127,100 +103,23 @@ export class Validator { return this; } - // Check if Validation Method already exists - if (this.validationMethods[key]) { - LogCodeManager.getLogger()?.error( - `Validation Method with the key/name '${key}' already exists!` - ); - return this; - } - this.validationMethods[key] = _method; - return this; - } - //========================================================================================================= - // String - //========================================================================================================= - /** - * @public - * Get String Validator - */ - public string(): StringValidator { - return new StringValidator(this); - } - - //========================================================================================================= - // Number - //========================================================================================================= - /** - * @public - * Get Number Validator - */ - public number(): NumberValidator { - return new NumberValidator(this); - } - - //========================================================================================================= - // Clone - //========================================================================================================= - /** - * @public - * Get a fresh clone of this Validator - */ - public clone(): Validator { - const clone = new Validator(); - clone.validationMethods = copy(this.validationMethods); - clone._key = this._key; - clone.config = copy(this.config); - return clone; - } - - //========================================================================================================= - // Required - //========================================================================================================= - /** - * @public - * Checks if the Editor Value exists - * @param errorMessage - Error Message - */ - public required(errorMessage?: string): this { - this.addValidationMethod( - this.getValidationMethodKey('required'), - async (key: ItemKey, value: DataType, editor) => { - const isValid = !!value; - if (!isValid) { - editor.setStatus( - key, - 'error', - errorMessage || `${key} is a required field` - ); - } - return isValid; - } - ); return this; } - //========================================================================================================= - // Get Validation Method Key - //========================================================================================================= - /** - * @internal - * Creates Validation Method Key from provided key - * @param key - Key that gets converted into a Validation Method Key - */ - public getValidationMethodKey(key: string): string { - return `_${this.config.prefix}_${key}`; + public registerValidationMethods( + validationMethods: ValidationMethodInterface[] | ValidationMethodInterface + ): this { + const _validationMethods = normalizeArray(validationMethods); + _validationMethods.forEach((validatorMethod) => { + this.addValidationMethod(generateId(), validatorMethod); + }); + return this; } } export type ValidatorKey = string | number; -export type ValidationMethodInterface = ( - key: ItemKey, - value: DataType, - editor: Multieditor -) => Promise; /** * @param key - Key/Name of Validator @@ -230,3 +129,14 @@ export interface ValidatorConfigInterface { key?: ValidatorKey; prefix?: string; } + +export type ValidationMethodInterface = ( + config: ValidatorMethodConfigInterface +) => boolean; + +export interface ValidatorMethodConfigInterface { + key?: ItemKey; + value: DataType; + editor: Multieditor; + errorMessage?: string; +} From 9f4dd70fa8699dc1676da18d5197a1126d6fe4a7 Mon Sep 17 00:00:00 2001 From: Benno Kohrs Date: Tue, 21 Sep 2021 20:17:04 +0200 Subject: [PATCH 02/14] updated multieditor validation method --- .../multieditor-ts/src/core/signUpEditor.ts | 152 ++++++++++-------- packages/multieditor/src/multieditor/index.ts | 1 - .../src/multieditor/multieditor.ts | 31 +++- packages/multieditor/src/validator/index.ts | 5 +- .../src/validator/types/general.ts | 39 +++-- .../multieditor/src/validator/types/number.ts | 42 +++++ .../multieditor/src/validator/types/string.ts | 20 +++ .../multieditor/src/validator/validator.ts | 106 ++++++------ 8 files changed, 257 insertions(+), 139 deletions(-) diff --git a/examples/react/develop/multieditor-ts/src/core/signUpEditor.ts b/examples/react/develop/multieditor-ts/src/core/signUpEditor.ts index e21a0478..800888ff 100644 --- a/examples/react/develop/multieditor-ts/src/core/signUpEditor.ts +++ b/examples/react/develop/multieditor-ts/src/core/signUpEditor.ts @@ -1,79 +1,103 @@ -import { createMultieditor, Validator } from '@agile-ts/multieditor'; +import { + createMultieditor, + isNumber, + isRequired, + isString, + max, + Validator, +} from '@agile-ts/multieditor'; import { generateColor, generateId, isLight } from './utils'; import { globalBind } from '@agile-ts/core'; - -export const isValidNameValidator = new Validator() - .required() - .string() - .min(2) - .max(10) - .matches(/^([^0-9]*)$/, 'No Numbers allowed!') - .main(); +// +// export const isValidNameValidator = new Validator() +// .required() +// .string() +// .min(2) +// .max(10) +// .matches(/^([^0-9]*)$/, 'No Numbers allowed!') +// .main(); +// +// export const signUpEditor = createMultieditor((editor) => ({ +// data: { +// id: 'myCoolId', +// firstName: 'Jeff', +// lastName: '', +// gender: undefined, +// userName: '', +// email: '', +// aboutYou: '', +// age: undefined, +// image: { +// id: generateId(), +// color: generateColor(), +// }, +// }, +// onSubmit: async (preparedData) => { +// alert(JSON.stringify(preparedData)); +// }, +// validateMethods: { +// firstName: isValidNameValidator, +// lastName: isValidNameValidator, +// userName: isValidNameValidator +// .clone() +// .addValidationMethod(async (key, value, editor) => { +// const isValid = value === 'Jeff'; +// if (!isValid) +// editor.setStatus(key, 'error', 'Sry only the name Jeff is allowed!'); +// return isValid; +// }), +// email: editor.Validator().required().string().email().main(), +// aboutYou: editor +// .Validator() +// .required() +// .string() +// .min(10) +// .main() +// .addValidationMethod(async (key, value, editor) => { +// const isValid = typeof value === 'string' && !value.includes('fuck'); +// if (!isValid) +// editor.setStatus(key, 'error', 'The word fuck is not allowed!'); +// return isValid; +// }), +// age: editor.Validator().required().number().min(18).max(100).main(), +// gender: editor.Validator().required(), +// image: editor +// .Validator() +// .required() +// .addValidationMethod(async (key, value, editor) => { +// const isValid = isLight(value.color); +// if (!isValid) editor.setStatus(key, 'error', 'The Image is to dark!'); +// return isValid; +// }), +// }, +// computeMethods: { +// lastName: (value) => { +// return value && typeof value === 'string' ? value.toUpperCase() : value; +// }, +// age: (value) => { +// return Number(value) || value; +// }, +// }, +// fixedProperties: ['id'], +// reValidateMode: 'afterFirstSubmit', +// })); +// +// // For better debugging +// globalBind('__core__', { isValidNameValidator, signUpEditor }); export const signUpEditor = createMultieditor((editor) => ({ data: { id: 'myCoolId', - firstName: 'Jeff', - lastName: '', - gender: undefined, - userName: '', - email: '', - aboutYou: '', - age: undefined, - image: { - id: generateId(), - color: generateColor(), - }, + name: 'jeff', + age: 10, }, onSubmit: async (preparedData) => { alert(JSON.stringify(preparedData)); }, validateMethods: { - firstName: isValidNameValidator, - lastName: isValidNameValidator, - userName: isValidNameValidator - .clone() - .addValidationMethod(async (key, value, editor) => { - const isValid = value === 'Jeff'; - if (!isValid) - editor.setStatus(key, 'error', 'Sry only the name Jeff is allowed!'); - return isValid; - }), - email: editor.Validator().required().string().email().main(), - aboutYou: editor - .Validator() - .required() - .string() - .min(10) - .main() - .addValidationMethod(async (key, value, editor) => { - const isValid = typeof value === 'string' && !value.includes('fuck'); - if (!isValid) - editor.setStatus(key, 'error', 'The word fuck is not allowed!'); - return isValid; - }), - age: editor.Validator().required().number().min(18).max(100).main(), - gender: editor.Validator().required(), - image: editor - .Validator() - .required() - .addValidationMethod(async (key, value, editor) => { - const isValid = isLight(value.color); - if (!isValid) editor.setStatus(key, 'error', 'The Image is to dark!'); - return isValid; - }), - }, - computeMethods: { - lastName: (value) => { - return value && typeof value === 'string' ? value.toUpperCase() : value; - }, - age: (value) => { - return Number(value) || value; - }, + name: editor.Validator(isRequired, isString), + age: editor.Validator(isRequired, isNumber, max(10)), }, fixedProperties: ['id'], reValidateMode: 'afterFirstSubmit', })); - -// For better debugging -globalBind('__core__', { isValidNameValidator, signUpEditor }); diff --git a/packages/multieditor/src/multieditor/index.ts b/packages/multieditor/src/multieditor/index.ts index 011117c6..569bb55d 100644 --- a/packages/multieditor/src/multieditor/index.ts +++ b/packages/multieditor/src/multieditor/index.ts @@ -1,5 +1,4 @@ import { Agile, shared } from '@agile-ts/core'; -import { defineConfig } from '@agile-ts/utils'; import { EditorConfig, Multieditor } from './multieditor'; export * from './multieditor'; diff --git a/packages/multieditor/src/multieditor/multieditor.ts b/packages/multieditor/src/multieditor/multieditor.ts index e5666440..ddcce0fe 100644 --- a/packages/multieditor/src/multieditor/multieditor.ts +++ b/packages/multieditor/src/multieditor/multieditor.ts @@ -5,8 +5,17 @@ import { LogCodeManager, Observer, } from '@agile-ts/core'; -import { defineConfig, copy } from '@agile-ts/utils'; -import { ValidationMethodInterface, Validator } from '../validator'; +import { + defineConfig, + copy, + normalizeArray, + generateId, +} from '@agile-ts/utils'; +import { + ValidationMethodInterface, + ValidationMethodObjectInterface, + Validator, +} from '../validator'; import { Item } from '../item'; import { StatusInterface, StatusType } from '../status'; @@ -141,8 +150,20 @@ export class Multieditor< * @public * Validator - Create validation Conditions for an Item */ - public Validator(): Validator { - return new Validator(this as any); + public Validator( + ...validationMethods: ( + | ValidationMethodObjectInterface + | (() => ValidationMethodObjectInterface) + )[] + ): Validator { + const _validationMethods = normalizeArray(validationMethods); + const validator = new Validator(); + + _validationMethods.forEach((validatorMethod) => { + validator.addValidationMethod(generateId(), validatorMethod); + }); + + return validator; } //========================================================================================================= @@ -405,7 +426,7 @@ export class Multieditor< } else { return new Validator({ key: key, - }).addValidationMethod(validation); + }).addValidationMethod({ method: validation }); } } return new Validator({ key: key }); diff --git a/packages/multieditor/src/validator/index.ts b/packages/multieditor/src/validator/index.ts index c1cadac5..1158a7ff 100644 --- a/packages/multieditor/src/validator/index.ts +++ b/packages/multieditor/src/validator/index.ts @@ -1,4 +1,5 @@ export * from './validator'; -export * from './types/number.validator'; -export * from './types/string.validator'; +export * from './types/general'; +export * from './types/number'; +export * from './types/string'; diff --git a/packages/multieditor/src/validator/types/general.ts b/packages/multieditor/src/validator/types/general.ts index b19ed27f..66d6ce16 100644 --- a/packages/multieditor/src/validator/types/general.ts +++ b/packages/multieditor/src/validator/types/general.ts @@ -1,23 +1,20 @@ -import { ValidatorMethodConfigInterface } from '../validator'; -import { defineConfig } from '@agile-ts/core'; +import { ValidationMethodObjectInterface } from '../validator'; -export async function isRequired( - config: ValidatorMethodConfigInterface -) { - config = defineConfig(config, { - key: 'isRequired', - errorMessage: `${config.key} is a required field`, - }); - - const isValid = !!config.value; - - if (!isValid) { - config.editor.setStatus( - config.key as any, - 'error', - config.errorMessage as any - ); - } - - return isValid; +export function isRequired( + errorMessage?: string +): ValidationMethodObjectInterface { + return { + name: 'isRequired', + method: (toValidateItemKey, value, editor): boolean => { + const isValid = !!value; + if (!isValid) { + editor.setStatus( + toValidateItemKey as any, + 'error', + errorMessage || `${toValidateItemKey} is a required field` + ); + } + return isValid; + }, + }; } diff --git a/packages/multieditor/src/validator/types/number.ts b/packages/multieditor/src/validator/types/number.ts index e69de29b..28347a21 100644 --- a/packages/multieditor/src/validator/types/number.ts +++ b/packages/multieditor/src/validator/types/number.ts @@ -0,0 +1,42 @@ +import { ValidationMethodObjectInterface } from '../validator'; + +export function isNumber( + errorMessage?: string +): ValidationMethodObjectInterface { + return { + name: 'isNumber', + method: (toValidateItemKey, value, editor): boolean => { + const isValid = typeof value === 'number'; + if (!isValid) { + editor.setStatus( + toValidateItemKey, + 'error', + errorMessage || `${toValidateItemKey} is no valid Number!` + ); + } + return isValid; + }, + }; +} + +export function max( + maxNumber: number, + errorMessage?: string +): ValidationMethodObjectInterface { + return { + name: 'max', + method: (toValidateItemKey, value, editor): boolean => { + if (!value || typeof value !== 'number') return false; + const isValid = value <= maxNumber; + if (!isValid) { + editor.setStatus( + toValidateItemKey, + 'error', + errorMessage || + `${toValidateItemKey} has to be smaller than ${maxNumber}` + ); + } + return isValid; + }, + }; +} diff --git a/packages/multieditor/src/validator/types/string.ts b/packages/multieditor/src/validator/types/string.ts index e69de29b..54383940 100644 --- a/packages/multieditor/src/validator/types/string.ts +++ b/packages/multieditor/src/validator/types/string.ts @@ -0,0 +1,20 @@ +import { ValidationMethodObjectInterface } from '../validator'; + +export function isString( + errorMessage?: string +): ValidationMethodObjectInterface { + return { + name: 'isString', + method: (toValidateItemKey, value, editor): boolean => { + const isValid = typeof value === 'string'; + if (!isValid) { + editor.setStatus( + toValidateItemKey, + 'error', + errorMessage || `${toValidateItemKey} is no valid String!` + ); + } + return isValid; + }, + }; +} diff --git a/packages/multieditor/src/validator/validator.ts b/packages/multieditor/src/validator/validator.ts index a7008de4..853d18ef 100644 --- a/packages/multieditor/src/validator/validator.ts +++ b/packages/multieditor/src/validator/validator.ts @@ -1,18 +1,12 @@ -import { - copy, - generateId, - isFunction, - LogCodeManager, - defineConfig, -} from '@agile-ts/core'; -import { DataObject, ItemKey, Multieditor } from '../multieditor'; -import { normalizeArray } from '@agile-ts/utils'; +import { generateId, isFunction, LogCodeManager } from '@agile-ts/core'; +import { ItemKey, Multieditor } from '../multieditor'; export class Validator { public _key?: ValidatorKey; public config: ValidatorConfigInterface = {}; - public validationMethods: DataObject> = - {}; + public validationMethods: { + [key: string]: ValidationMethodInterface; + } = {}; /** * @public @@ -20,9 +14,6 @@ export class Validator { * @param config - Config */ constructor(config: ValidatorConfigInterface = {}) { - this.config = defineConfig(config, { - prefix: 'default', - }); this._key = this.config.key; } @@ -42,6 +33,16 @@ export class Validator { return this._key; } + //========================================================================================================= + // Validate + //========================================================================================================= + /** + * @public + * Validates Item Value at Key and updates its Status + * @param key - Key/Name of Item + * @param value - Value that gets validated + * @param editor - MultiEditor that holds the Item which gets validated + */ public async validate( key: ItemKey, value: DataType, @@ -60,11 +61,11 @@ export class Validator { // Call validation methods (-> validate Item at specified key) for (const validationMethodKey of validationMethodKeys) isValid = - (await this.validationMethods[validationMethodKey]({ + (await this.validationMethods[validationMethodKey]( key, value, - editor, - })) && isValid; + editor + )) && isValid; // Handle tracked Statuses const trackedStatuses = item.status.statusTracker.getTrackedStatuses(); @@ -74,69 +75,82 @@ export class Validator { return isValid; } - public addValidationMethod(method: ValidationMethodInterface): this; + //========================================================================================================= + // Add Validation Method + //========================================================================================================= + /** + * @public + * Adds Validation Method to Validator + * @param method - Validation Method + */ public addValidationMethod( - key: ItemKey, - method: ValidationMethodInterface + method: AddValidationMethodMethodType + ): this; + public addValidationMethod( + key: ValidationMethodKey, + method: AddValidationMethodMethodType ): this; public addValidationMethod( - keyOrMethod: ItemKey | ValidationMethodInterface, - method?: ValidationMethodInterface + keyOrMethod: ValidationMethodKey | AddValidationMethodMethodType, + method?: AddValidationMethodMethodType ): this { const generateKey = isFunction(keyOrMethod); - let _method: ValidationMethodInterface; - let key: ItemKey; + let validationMethodObject: AddValidationMethodMethodType; + let key: ValidationMethodKey; if (generateKey) { key = generateId(); - _method = keyOrMethod as ValidationMethodInterface; + validationMethodObject = keyOrMethod as AddValidationMethodMethodType< + DataType + >; } else { key = keyOrMethod as string; - _method = method as ValidationMethodInterface; + validationMethodObject = method as AddValidationMethodMethodType< + DataType + >; } - // Check if Validation Method is a Function - if (!isFunction(_method)) { + // Resolve validation method + if (typeof validationMethodObject !== 'object') { + validationMethodObject = validationMethodObject(); + } + + if (!isFunction(validationMethodObject.method)) { LogCodeManager.getLogger()?.error( 'A Validation Method has to be a function!' ); return this; } - this.validationMethods[key] = _method; - - return this; - } + this.validationMethods[key] = validationMethodObject.method; - public registerValidationMethods( - validationMethods: ValidationMethodInterface[] | ValidationMethodInterface - ): this { - const _validationMethods = normalizeArray(validationMethods); - _validationMethods.forEach((validatorMethod) => { - this.addValidationMethod(generateId(), validatorMethod); - }); return this; } } export type ValidatorKey = string | number; +export type AddValidationMethodMethodType = + | ValidationMethodObjectInterface + | (() => ValidationMethodObjectInterface); + /** * @param key - Key/Name of Validator * @param prefix - Validation Method Prefix */ export interface ValidatorConfigInterface { key?: ValidatorKey; - prefix?: string; } export type ValidationMethodInterface = ( - config: ValidatorMethodConfigInterface + toValidateItemKey: ItemKey, + value: DataType, + editor: Multieditor ) => boolean; -export interface ValidatorMethodConfigInterface { - key?: ItemKey; - value: DataType; - editor: Multieditor; - errorMessage?: string; +export type ValidationMethodKey = string | number; + +export interface ValidationMethodObjectInterface { + name?: string; + method: ValidationMethodInterface; } From d9b8d96db043a5c80b04702bd52eef3a3a1f267c Mon Sep 17 00:00:00 2001 From: Benno Kohrs Date: Wed, 22 Sep 2021 08:08:49 +0200 Subject: [PATCH 03/14] fixed typos --- .../react/develop/multieditor-ts/package.json | 7 +- .../multieditor-ts/src/core/signUpEditor.ts | 15 +- .../react/develop/multieditor-ts/yarn.lock | 183 +++++++++++++++++- packages/multieditor/src/item.ts | 18 +- .../src/multieditor/multieditor.ts | 81 ++++---- .../src/validator/resolvers/yup/index.ts | 0 .../validator/{types => schemas}/general.ts | 0 .../validator/{types => schemas}/number.ts | 0 .../validator/{types => schemas}/string.ts | 0 .../multieditor/src/validator/validator.ts | 28 ++- 10 files changed, 253 insertions(+), 79 deletions(-) create mode 100644 packages/multieditor/src/validator/resolvers/yup/index.ts rename packages/multieditor/src/validator/{types => schemas}/general.ts (100%) rename packages/multieditor/src/validator/{types => schemas}/number.ts (100%) rename packages/multieditor/src/validator/{types => schemas}/string.ts (100%) diff --git a/examples/react/develop/multieditor-ts/package.json b/examples/react/develop/multieditor-ts/package.json index ba83cc52..9d4d41ef 100644 --- a/examples/react/develop/multieditor-ts/package.json +++ b/examples/react/develop/multieditor-ts/package.json @@ -11,7 +11,8 @@ "react-dom": "^16.13.1", "react-router-dom": "^5.2.0", "react-scripts": "3.4.3", - "typescript": "^3.9.7" + "typescript": "^3.9.7", + "yup": "^0.32.9" }, "devDependencies": { "@testing-library/react": "^9.3.2", @@ -19,13 +20,15 @@ "@types/node": "^12.0.0", "@types/react": "^16.9.0", "@types/react-dom": "^16.9.0", - "@types/react-router-dom": "^5.1.5" + "@types/react-router-dom": "^5.1.5", + "source-map-explorer": "^2.5.2" }, "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject", + "analyze": "yarn run build && source-map-explorer 'build/static/js/*.js'", "install:dev:agile": "yalc add @agile-ts/core @agile-ts/react @agile-ts/multieditor & yarn install", "install:prod:agile": "yalc add @agile-ts/core @agile-ts/react @agile-ts/multieditor & yarn install" }, diff --git a/examples/react/develop/multieditor-ts/src/core/signUpEditor.ts b/examples/react/develop/multieditor-ts/src/core/signUpEditor.ts index 800888ff..616508de 100644 --- a/examples/react/develop/multieditor-ts/src/core/signUpEditor.ts +++ b/examples/react/develop/multieditor-ts/src/core/signUpEditor.ts @@ -4,10 +4,9 @@ import { isRequired, isString, max, - Validator, } from '@agile-ts/multieditor'; -import { generateColor, generateId, isLight } from './utils'; import { globalBind } from '@agile-ts/core'; +import * as Yup from 'yup'; // // export const isValidNameValidator = new Validator() // .required() @@ -81,23 +80,25 @@ import { globalBind } from '@agile-ts/core'; // fixedProperties: ['id'], // reValidateMode: 'afterFirstSubmit', // })); -// -// // For better debugging -// globalBind('__core__', { isValidNameValidator, signUpEditor }); export const signUpEditor = createMultieditor((editor) => ({ data: { id: 'myCoolId', - name: 'jeff', + firstName: 'jeff', + lastName: 'rose', age: 10, }, onSubmit: async (preparedData) => { alert(JSON.stringify(preparedData)); }, validateMethods: { - name: editor.Validator(isRequired, isString), + firstName: editor.Validator(isRequired, isString), + lastName: Yup.string().max(15) as any, // TODO age: editor.Validator(isRequired, isNumber, max(10)), }, fixedProperties: ['id'], reValidateMode: 'afterFirstSubmit', })); + +// For better debugging +globalBind('__core__', { signUpEditor }); diff --git a/examples/react/develop/multieditor-ts/yarn.lock b/examples/react/develop/multieditor-ts/yarn.lock index 268a94d3..abdc218a 100644 --- a/examples/react/develop/multieditor-ts/yarn.lock +++ b/examples/react/develop/multieditor-ts/yarn.lock @@ -1095,6 +1095,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.10.5": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.4.tgz#fd17d16bfdf878e6dd02d19753a39fa8a8d9c84a" + integrity sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/template@^7.10.4", "@babel/template@^7.12.7", "@babel/template@^7.4.0", "@babel/template@^7.8.6": version "7.12.7" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.12.7.tgz#c817233696018e39fbb6c491d2fb684e05ed43bc" @@ -1597,6 +1604,11 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0" integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw== +"@types/lodash@^4.14.165": + version "4.14.173" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.173.tgz#9d3b674c67a26cf673756f6aca7b429f237f91ed" + integrity sha512-vv0CAYoaEjCw/mLy96GBTnRoZrSxkGE0BKzKimdR8P3OzrNYNvBgtW7p055A+E8C31vXNUhWKoFCbhq7gbyhFg== + "@types/minimatch@*": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" @@ -2264,6 +2276,11 @@ async-limiter@~1.0.0: resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== +async@0.9.x: + version "0.9.2" + resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" + integrity sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0= + async@^2.6.2: version "2.6.3" resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" @@ -2706,6 +2723,11 @@ bser@2.1.1: dependencies: node-int64 "^0.4.0" +btoa@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/btoa/-/btoa-1.2.1.tgz#01a9909f8b2c93f6bf680ba26131eb30f7fa3d73" + integrity sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g== + buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" @@ -3050,6 +3072,15 @@ cliui@^5.0.0: strip-ansi "^5.2.0" wrap-ansi "^5.1.0" +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + clone-deep@^0.2.4: version "0.2.4" resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-0.2.4.tgz#4e73dd09e9fb971cc38670c5dced9c1896481cc6" @@ -3977,7 +4008,7 @@ dotenv@8.2.0: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a" integrity sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw== -duplexer@^0.1.1: +duplexer@^0.1.1, duplexer@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== @@ -4005,6 +4036,13 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= +ejs@^3.1.5: + version "3.1.6" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.6.tgz#5bfd0a0689743bb5268b3550cceeebbc1702822a" + integrity sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw== + dependencies: + jake "^10.6.1" + electron-to-chromium@^1.3.378, electron-to-chromium@^1.3.621: version "1.3.633" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.633.tgz#16dd5aec9de03894e8d14a1db4cda8a369b9b7fe" @@ -4170,7 +4208,7 @@ escalade@^3.1.1: resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== -escape-html@~1.0.3: +escape-html@^1.0.3, escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= @@ -4682,6 +4720,13 @@ file-uri-to-path@1.0.0: resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== +filelist@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.2.tgz#80202f21462d4d1c2e214119b1807c1bc0380e5b" + integrity sha512-z7O0IS8Plc39rTCq6i6iHxk43duYOn8uFJiWSewIq0Bww1RNybVHSCjahmcC87ZqAm4OTvFzlzeGu3XAzG1ctQ== + dependencies: + minimatch "^3.0.4" + filesize@6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/filesize/-/filesize-6.0.1.tgz#f850b509909c7c86f7e450ea19006c31c2ed3d2f" @@ -4958,7 +5003,7 @@ gensync@^1.0.0-beta.1: resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== -get-caller-file@^2.0.1: +get-caller-file@^2.0.1, get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== @@ -5098,6 +5143,13 @@ gzip-size@5.1.1: duplexer "^0.1.1" pify "^4.0.1" +gzip-size@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462" + integrity sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q== + dependencies: + duplexer "^0.1.2" + handle-thing@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" @@ -6024,6 +6076,16 @@ istanbul-reports@^2.2.6: dependencies: html-escaper "^2.0.0" +jake@^10.6.1: + version "10.8.2" + resolved "https://registry.yarnpkg.com/jake/-/jake-10.8.2.tgz#ebc9de8558160a66d82d0eadc6a2e58fbc500a7b" + integrity sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A== + dependencies: + async "0.9.x" + chalk "^2.4.2" + filelist "^1.0.1" + minimatch "^3.0.4" + jest-changed-files@^24.9.0: version "24.9.0" resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-24.9.0.tgz#08d8c15eb79a7fa3fc98269bc14b451ee82f8039" @@ -6762,6 +6824,11 @@ locate-path@^5.0.0: dependencies: p-locate "^4.1.0" +lodash-es@^4.17.15: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" + integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== + lodash._reinterpolate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" @@ -7201,6 +7268,11 @@ nan@^2.12.1: resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19" integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ== +nanoclone@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/nanoclone/-/nanoclone-0.2.1.tgz#dd4090f8f1a110d26bb32c49ed2f5b9235209ed4" + integrity sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA== + nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" @@ -7534,6 +7606,14 @@ open@^7.0.2: is-docker "^2.0.0" is-wsl "^2.1.1" +open@^7.3.1: + version "7.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" + integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q== + dependencies: + is-docker "^2.0.0" + is-wsl "^2.1.1" + opn@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc" @@ -8717,6 +8797,11 @@ prop-types@^15.5.6, prop-types@^15.5.7, prop-types@^15.6.0, prop-types@^15.6.2, object-assign "^4.1.1" react-is "^16.8.1" +property-expr@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-2.0.4.tgz#37b925478e58965031bb612ec5b3260f8241e910" + integrity sha512-sFPkHQjVKheDNnPvotjQmm3KD3uk1fWKUN7CrpdbwmUx3CrG3QiM8QpTSimvig5vTXmTvjz7+TDvXOI9+4rkcg== + proxy-addr@~2.0.5: version "2.0.6" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf" @@ -9419,7 +9504,7 @@ rgba-regex@^1.0.0: resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= -rimraf@2.6.3: +rimraf@2.6.3, rimraf@~2.6.2: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== @@ -9846,6 +9931,24 @@ source-list-map@^2.0.0: resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== +source-map-explorer@^2.5.2: + version "2.5.2" + resolved "https://registry.yarnpkg.com/source-map-explorer/-/source-map-explorer-2.5.2.tgz#857cab5dd9d1d7175e9c5c2739dc9ccfb99f2dc5" + integrity sha512-gBwOyCcHPHcdLbgw6Y6kgoH1uLKL6hN3zz0xJcNI2lpnElZliIlmSYAjUVwAWnc7+HscoTyh1ScR7ITtFuEnxg== + dependencies: + btoa "^1.2.1" + chalk "^4.1.0" + convert-source-map "^1.7.0" + ejs "^3.1.5" + escape-html "^1.0.3" + glob "^7.1.6" + gzip-size "^6.0.0" + lodash "^4.17.20" + open "^7.3.1" + source-map "^0.7.3" + temp "^0.9.4" + yargs "^16.2.0" + source-map-resolve@^0.5.0, source-map-resolve@^0.5.2: version "0.5.3" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" @@ -9880,6 +9983,11 @@ source-map@^0.5.0, source-map@^0.5.6: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= +source-map@^0.7.3: + version "0.7.3" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" + integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== + spdx-correct@^3.0.0: version "3.1.1" resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" @@ -10072,6 +10180,15 @@ string-width@^4.1.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.0" +string-width@^4.2.0: + version "4.2.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5" + integrity sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.0" + string.prototype.matchall@^4.0.2: version "4.0.3" resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.3.tgz#24243399bc31b0a49d19e2b74171a15653ec996a" @@ -10267,6 +10384,14 @@ tapable@^1.0.0, tapable@^1.1.3: resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== +temp@^0.9.4: + version "0.9.4" + resolved "https://registry.yarnpkg.com/temp/-/temp-0.9.4.tgz#cd20a8580cb63635d0e4e9d4bd989d44286e7620" + integrity sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA== + dependencies: + mkdirp "^0.5.1" + rimraf "~2.6.2" + terser-webpack-plugin@2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-2.3.8.tgz#894764a19b0743f2f704e7c2a848c5283a696724" @@ -10425,6 +10550,11 @@ toidentifier@1.0.0: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== +toposort@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/toposort/-/toposort-2.0.2.tgz#ae21768175d1559d48bef35420b2f4962f09c330" + integrity sha1-riF2gXXRVZ1IvvNUILL0li8JwzA= + tough-cookie@^2.3.3, tough-cookie@^2.3.4, tough-cookie@^2.5.0, tough-cookie@~2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" @@ -11170,6 +11300,15 @@ wrap-ansi@^5.1.0: string-width "^3.0.0" strip-ansi "^5.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -11232,6 +11371,11 @@ y18n@^4.0.0: resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.1.tgz#8db2b83c31c5d75099bb890b23f3094891e247d4" integrity sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ== +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + yallist@^3.0.2: version "3.1.1" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" @@ -11255,6 +11399,11 @@ yargs-parser@^13.1.2: camelcase "^5.0.0" decamelize "^1.2.0" +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + yargs@^13.3.0, yargs@^13.3.2: version "13.3.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" @@ -11270,3 +11419,29 @@ yargs@^13.3.0, yargs@^13.3.2: which-module "^2.0.0" y18n "^4.0.0" yargs-parser "^13.1.2" + +yargs@^16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yup@^0.32.9: + version "0.32.9" + resolved "https://registry.yarnpkg.com/yup/-/yup-0.32.9.tgz#9367bec6b1b0e39211ecbca598702e106019d872" + integrity sha512-Ci1qN+i2H0XpY7syDQ0k5zKQ/DoxO0LzPg8PAR/X4Mpj6DqaeCoIYEEjDJwhArh3Fa7GWbQQVDZKeXYlSH4JMg== + dependencies: + "@babel/runtime" "^7.10.5" + "@types/lodash" "^4.14.165" + lodash "^4.17.20" + lodash-es "^4.17.15" + nanoclone "^0.2.1" + property-expr "^2.0.4" + toposort "^2.0.2" diff --git a/packages/multieditor/src/item.ts b/packages/multieditor/src/item.ts index 6af13b5c..bd30487f 100644 --- a/packages/multieditor/src/item.ts +++ b/packages/multieditor/src/item.ts @@ -1,13 +1,13 @@ import { StateRuntimeJobConfigInterface, defineConfig, - EnhancedState, + State, } from '@agile-ts/core'; import { ItemKey, Multieditor } from './multieditor'; import { Status } from './status'; import { Validator } from './validator'; -export class Item extends EnhancedState { +export class Item extends State { public editor: () => Multieditor; public isValid = false; @@ -21,30 +21,28 @@ export class Item extends EnhancedState { * Item - Item of an Editor * @param editor - Editor to which the Item belongs * @param data - Data that the Item holds - * @param key - Key/Name of Item * @param config - Config */ constructor( editor: Multieditor, data: DataType, - key: ItemKey, - config: ItemConfigInterface = {} + config: ItemConfigInterface ) { super(editor.agileInstance(), data, { - key: key, + key: config.key, }); config = defineConfig(config, { canBeEdited: true, }); this.editor = () => editor; - this.validator = editor.getValidator(key); + this.validator = editor.getValidator(config.key); this.config = config; this.status = new Status(this); // Add SideEffect that rebuilds the Status depending of the Item value this.addSideEffect('validateItem', async () => { this.isValid = await this.validator.validate( - key, + config.key, this.value, this.editor() ); @@ -79,15 +77,17 @@ export class Item extends EnhancedState { * @param config - Config */ public reset(config: StateRuntimeJobConfigInterface = {}): this { - super.reset(config); + this.set(this.initialStateValue, config); this.status.display = false; return this; } } /** + * @param key - Key/Name of Item * @param canBeEdited - If Item Value gets passed into the preparedData on Submit (if it got edited) */ export interface ItemConfigInterface { + key: ItemKey; canBeEdited?: boolean; } diff --git a/packages/multieditor/src/multieditor/multieditor.ts b/packages/multieditor/src/multieditor/multieditor.ts index ddcce0fe..da9c03f7 100644 --- a/packages/multieditor/src/multieditor/multieditor.ts +++ b/packages/multieditor/src/multieditor/multieditor.ts @@ -1,10 +1,4 @@ -import { - Agile, - ComputeValueMethod, - getAgileInstance, - LogCodeManager, - Observer, -} from '@agile-ts/core'; +import { Agile, LogCodeManager, Observer } from '@agile-ts/core'; import { defineConfig, copy, @@ -27,15 +21,16 @@ export class Multieditor< public agileInstance: () => Agile; public config: EditorConfigInterface; + public isModified = false; public isValid = false; public submitted = false; + public fixedProperties: ItemKey[] = []; public editableProperties: ItemKey[] = []; - public validateMethods: DataObject< - ValidationMethodInterface | Validator - > = {}; - public computeMethods: DataObject> = {}; + + public validators: { [key: string]: Validator } = {}; + public onSubmit: ( preparedData: DataObject, config?: OnSubmitConfigType @@ -53,20 +48,14 @@ export class Multieditor< */ constructor( config: EditorConfig, - agileInstance?: Agile + agileInstance: Agile ) { - if (!agileInstance) agileInstance = getAgileInstance(null); - if (!agileInstance) - LogCodeManager.getLogger()?.error( - 'No Global agileInstance found! Please pass an agileInstance into the MultiEditor!' - ); - this.agileInstance = () => agileInstance as any; + this.agileInstance = () => agileInstance; let _config = typeof config === 'function' ? config(this) : config; _config = defineConfig(_config, { fixedProperties: [], - editableProperties: Object.keys(_config.data), - validateMethods: {}, - computeMethods: {}, + editableProperties: Object.keys(_config.initialData), + validationSchema: {}, reValidateMode: 'onSubmit', validate: 'editable', }); @@ -74,24 +63,31 @@ export class Multieditor< this.onSubmit = _config.onSubmit as any; this.fixedProperties = _config.fixedProperties as any; this.editableProperties = _config.editableProperties as any; - this.validateMethods = _config.validateMethods as any; - this.computeMethods = _config.computeMethods as any; this.config = { reValidateMode: _config.reValidateMode as any, validate: _config.validate as any, }; - // Add Items to Data Object and validate it for the first Time - for (const key in _config.data) { - const item = new Item(this as any, _config.data[key], key, { + // Format validation methods to Validators + Object.keys(_config.validationSchema as any).map((key) => { + const validationMethod = (_config.validationSchema as any)[key]; + if (validationMethod instanceof Validator) { + if (validationMethod.key == null) validationMethod.key = key; + this.validators[key] = validationMethod as Validator; + } else + this.validators[key] = new Validator({ + key, + }).addValidationSchema(validationMethod); + }); + + // Instantiate data Items + for (const key in _config.initialData) { + const item = new Item(this as any, _config.initialData[key], { + key, canBeEdited: this.editableProperties.includes(key), }); this.data[key] = item; - item.validate(); - if (Object.prototype.hasOwnProperty.call(this.computeMethods, key)) { - const computeMethod = this.computeMethods[key]; - item.computeValue(computeMethod); - } + item.validate(); // Initial validate } } @@ -160,7 +156,7 @@ export class Multieditor< const validator = new Validator(); _validationMethods.forEach((validatorMethod) => { - validator.addValidationMethod(generateId(), validatorMethod); + validator.addValidationSchema(generateId(), validatorMethod); }); return validator; @@ -418,16 +414,8 @@ export class Multieditor< * @param key - Key/Name of Item */ public getValidator(key: ItemKey): Validator { - if (Object.prototype.hasOwnProperty.call(this.validateMethods, key)) { - const validation = this.validateMethods[key]; - if (validation instanceof Validator) { - if (!validation.key) validation.key = key; - return validation; - } else { - return new Validator({ - key: key, - }).addValidationMethod({ method: validation }); - } + if (Object.prototype.hasOwnProperty.call(this.validators, key)) { + return this.validators[key]; } return new Validator({ key: key }); } @@ -527,13 +515,12 @@ export interface CreateEditorConfigInterface< onSubmitConfig = any > { key?: string; - data: DataObject; + initialData: DataObject; fixedProperties?: string[]; editableProperties?: string[]; - validateMethods?: DataObject< - ValidationMethodInterface | Validator - >; - computeMethods?: DataObject>; + validationSchema?: { + [key: string]: ValidationMethodInterface | Validator; + }; onSubmit: ( preparedData: DataObject, config?: onSubmitConfig diff --git a/packages/multieditor/src/validator/resolvers/yup/index.ts b/packages/multieditor/src/validator/resolvers/yup/index.ts new file mode 100644 index 00000000..e69de29b diff --git a/packages/multieditor/src/validator/types/general.ts b/packages/multieditor/src/validator/schemas/general.ts similarity index 100% rename from packages/multieditor/src/validator/types/general.ts rename to packages/multieditor/src/validator/schemas/general.ts diff --git a/packages/multieditor/src/validator/types/number.ts b/packages/multieditor/src/validator/schemas/number.ts similarity index 100% rename from packages/multieditor/src/validator/types/number.ts rename to packages/multieditor/src/validator/schemas/number.ts diff --git a/packages/multieditor/src/validator/types/string.ts b/packages/multieditor/src/validator/schemas/string.ts similarity index 100% rename from packages/multieditor/src/validator/types/string.ts rename to packages/multieditor/src/validator/schemas/string.ts diff --git a/packages/multieditor/src/validator/validator.ts b/packages/multieditor/src/validator/validator.ts index 853d18ef..c574eb83 100644 --- a/packages/multieditor/src/validator/validator.ts +++ b/packages/multieditor/src/validator/validator.ts @@ -1,20 +1,27 @@ import { generateId, isFunction, LogCodeManager } from '@agile-ts/core'; import { ItemKey, Multieditor } from '../multieditor'; +import { defineConfig } from '@agile-ts/utils'; export class Validator { public _key?: ValidatorKey; public config: ValidatorConfigInterface = {}; - public validationMethods: { + + // Schemas to validate Items via this Validator + public validationSchemas: { [key: string]: ValidationMethodInterface; } = {}; /** - * @public * Validator - Easy way to validate Editor Values + * + * @public * @param config - Config */ constructor(config: ValidatorConfigInterface = {}) { - this._key = this.config.key; + config = defineConfig(config, { + key: generateId(), + }); + this._key = config.key; } /** @@ -53,7 +60,7 @@ export class Validator { if (item == null) return false; // Reverse validation methods because the first method should have the highest weight - const validationMethodKeys = Object.keys(this.validationMethods).reverse(); + const validationMethodKeys = Object.keys(this.validationSchemas).reverse(); // Track created Statuses during the Validation Time item.status.statusTracker.track(); @@ -61,7 +68,7 @@ export class Validator { // Call validation methods (-> validate Item at specified key) for (const validationMethodKey of validationMethodKeys) isValid = - (await this.validationMethods[validationMethodKey]( + (await this.validationSchemas[validationMethodKey]( key, value, editor @@ -83,14 +90,14 @@ export class Validator { * Adds Validation Method to Validator * @param method - Validation Method */ - public addValidationMethod( + public addValidationSchema( method: AddValidationMethodMethodType ): this; - public addValidationMethod( + public addValidationSchema( key: ValidationMethodKey, method: AddValidationMethodMethodType ): this; - public addValidationMethod( + public addValidationSchema( keyOrMethod: ValidationMethodKey | AddValidationMethodMethodType, method?: AddValidationMethodMethodType ): this { @@ -110,7 +117,8 @@ export class Validator { >; } - // Resolve validation method + // Resolve validation schema + // TODO add Yup support via resolvers (https://github.dev/formium/formik/tree/master/packages/formik/src, https://github.com/react-hook-form/resolvers) if (typeof validationMethodObject !== 'object') { validationMethodObject = validationMethodObject(); } @@ -122,7 +130,7 @@ export class Validator { return this; } - this.validationMethods[key] = validationMethodObject.method; + this.validationSchemas[key] = validationMethodObject.method; return this; } From 423ad379bd789418df0bdff2ac6d5fa3bc0b77a2 Mon Sep 17 00:00:00 2001 From: BennoDev Date: Wed, 22 Sep 2021 14:33:50 +0200 Subject: [PATCH 04/14] added multieditor resolver for yup --- .../multieditor-ts/src/core/signUpEditor.ts | 16 ++- packages/multieditor/package.json | 3 +- packages/multieditor/src/item.ts | 67 ++++----- .../src/multieditor/multieditor.ts | 25 +--- packages/multieditor/src/validator/index.ts | 8 +- .../src/validator/resolvers/agile/index.ts | 25 ++++ .../src/validator/resolvers/index.ts | 2 + .../src/validator/resolvers/yup/index.ts | 42 ++++++ .../{schemas => validationMethods}/general.ts | 0 .../{schemas => validationMethods}/number.ts | 0 .../{schemas => validationMethods}/string.ts | 0 .../multieditor/src/validator/validator.ts | 128 ++++++++++-------- yarn.lock | 45 ++++++ 13 files changed, 236 insertions(+), 125 deletions(-) create mode 100644 packages/multieditor/src/validator/resolvers/agile/index.ts create mode 100644 packages/multieditor/src/validator/resolvers/index.ts rename packages/multieditor/src/validator/{schemas => validationMethods}/general.ts (100%) rename packages/multieditor/src/validator/{schemas => validationMethods}/number.ts (100%) rename packages/multieditor/src/validator/{schemas => validationMethods}/string.ts (100%) diff --git a/examples/react/develop/multieditor-ts/src/core/signUpEditor.ts b/examples/react/develop/multieditor-ts/src/core/signUpEditor.ts index 616508de..17fa08a6 100644 --- a/examples/react/develop/multieditor-ts/src/core/signUpEditor.ts +++ b/examples/react/develop/multieditor-ts/src/core/signUpEditor.ts @@ -1,9 +1,11 @@ import { + agileResolver, createMultieditor, isNumber, isRequired, isString, max, + yupResolver, } from '@agile-ts/multieditor'; import { globalBind } from '@agile-ts/core'; import * as Yup from 'yup'; @@ -82,7 +84,7 @@ import * as Yup from 'yup'; // })); export const signUpEditor = createMultieditor((editor) => ({ - data: { + initialData: { id: 'myCoolId', firstName: 'jeff', lastName: 'rose', @@ -91,13 +93,15 @@ export const signUpEditor = createMultieditor((editor) => ({ onSubmit: async (preparedData) => { alert(JSON.stringify(preparedData)); }, - validateMethods: { - firstName: editor.Validator(isRequired, isString), - lastName: Yup.string().max(15) as any, // TODO - age: editor.Validator(isRequired, isNumber, max(10)), + validationSchema: { + firstName: agileResolver(isRequired, isString).append( + yupResolver(Yup.string().min(10)) + ), + lastName: yupResolver(Yup.string().max(15)), + age: agileResolver(isRequired, isNumber, max(10)), }, fixedProperties: ['id'], - reValidateMode: 'afterFirstSubmit', + reValidateMode: 'onChange', })); // For better debugging diff --git a/packages/multieditor/package.json b/packages/multieditor/package.json index b53507a7..97250d7e 100644 --- a/packages/multieditor/package.json +++ b/packages/multieditor/package.json @@ -42,7 +42,8 @@ "lint": "eslint src/**/*" }, "devDependencies": { - "@agile-ts/core": "file:../core" + "@agile-ts/core": "file:../core", + "yup": "^0.32.9" }, "peerDependencies": { "@agile-ts/core": "^0.2.4" diff --git a/packages/multieditor/src/item.ts b/packages/multieditor/src/item.ts index bd30487f..1f831feb 100644 --- a/packages/multieditor/src/item.ts +++ b/packages/multieditor/src/item.ts @@ -7,28 +7,33 @@ import { ItemKey, Multieditor } from './multieditor'; import { Status } from './status'; import { Validator } from './validator'; -export class Item extends State { - public editor: () => Multieditor; +export class Item extends State { + // Multieditor the Item belongs to + public editor: () => Multieditor; - public isValid = false; public config: ItemConfigInterface; + // Whether the Item is valid. + public isValid = false; + // Handles the validation of the Item + public validator: Validator; + // Validation Status of the Item public status: Status; - public validator: Validator; /** + * An Item represents a piece of information from the Multieditor. + * * @public - * Item - Item of an Editor - * @param editor - Editor to which the Item belongs - * @param data - Data that the Item holds - * @param config - Config + * @param editor - Multieditor to which the Item belongs. + * @param initialValue - Data that the Item holds + * @param config - Configuration object */ constructor( - editor: Multieditor, - data: DataType, + editor: Multieditor, + initialValue: ValueType, config: ItemConfigInterface ) { - super(editor.agileInstance(), data, { + super(editor.agileInstance(), initialValue, { key: config.key, }); config = defineConfig(config, { @@ -39,13 +44,10 @@ export class Item extends State { this.config = config; this.status = new Status(this); - // Add SideEffect that rebuilds the Status depending of the Item value + // Add side effect to revalidate the Item on every Item value change this.addSideEffect('validateItem', async () => { - this.isValid = await this.validator.validate( - config.key, - this.value, - this.editor() - ); + await this.validate(); + if (this.editor().canAssignStatusToItemOnChange(this)) this.status.display = true; this.editor().validate(); @@ -53,28 +55,23 @@ export class Item extends State { }); } - //========================================================================================================= - // Validate - //========================================================================================================= /** + * Revalidates the Item. + * * @public - * Validates Item and updates its 'isValid' property */ public async validate(): Promise { - const isValid = this.key - ? await this.validator.validate(this.key, this.value, this.editor()) - : false; + const isValid = await this.validator.validate(this, this.value); this.isValid = isValid; return isValid; } - //========================================================================================================= - // Reset - //========================================================================================================= /** + * Resets the Item value to its initial value. + * + * * @public - * Resets State to its initial Value - * @param config - Config + * @param config - Configuration object */ public reset(config: StateRuntimeJobConfigInterface = {}): this { this.set(this.initialStateValue, config); @@ -83,11 +80,15 @@ export class Item extends State { } } -/** - * @param key - Key/Name of Item - * @param canBeEdited - If Item Value gets passed into the preparedData on Submit (if it got edited) - */ export interface ItemConfigInterface { + /** + * Key/Name identifier of the State. + */ key: ItemKey; + /** + * @param canBeEdited - Whether the Item value can be edited + * and thus is passes into the 'preparedData' object when submitting. + * @default true + */ canBeEdited?: boolean; } diff --git a/packages/multieditor/src/multieditor/multieditor.ts b/packages/multieditor/src/multieditor/multieditor.ts index da9c03f7..59eb73fb 100644 --- a/packages/multieditor/src/multieditor/multieditor.ts +++ b/packages/multieditor/src/multieditor/multieditor.ts @@ -77,7 +77,7 @@ export class Multieditor< } else this.validators[key] = new Validator({ key, - }).addValidationSchema(validationMethod); + }).addValidationMethod(validationMethod); }); // Instantiate data Items @@ -139,29 +139,6 @@ export class Multieditor< return deps; } - //========================================================================================================= - // Validator - //========================================================================================================= - /** - * @public - * Validator - Create validation Conditions for an Item - */ - public Validator( - ...validationMethods: ( - | ValidationMethodObjectInterface - | (() => ValidationMethodObjectInterface) - )[] - ): Validator { - const _validationMethods = normalizeArray(validationMethods); - const validator = new Validator(); - - _validationMethods.forEach((validatorMethod) => { - validator.addValidationSchema(generateId(), validatorMethod); - }); - - return validator; - } - //========================================================================================================= // Set Value //========================================================================================================= diff --git a/packages/multieditor/src/validator/index.ts b/packages/multieditor/src/validator/index.ts index 1158a7ff..a88d46dc 100644 --- a/packages/multieditor/src/validator/index.ts +++ b/packages/multieditor/src/validator/index.ts @@ -1,5 +1,7 @@ export * from './validator'; -export * from './types/general'; -export * from './types/number'; -export * from './types/string'; +export * from './resolvers'; + +export * from './validationMethods/general'; +export * from './validationMethods/number'; +export * from './validationMethods/string'; diff --git a/packages/multieditor/src/validator/resolvers/agile/index.ts b/packages/multieditor/src/validator/resolvers/agile/index.ts new file mode 100644 index 00000000..17353763 --- /dev/null +++ b/packages/multieditor/src/validator/resolvers/agile/index.ts @@ -0,0 +1,25 @@ +import { generateId, normalizeArray } from '@agile-ts/utils'; +import { ValidationMethodObjectInterface, Validator } from '../../validator'; + +export function agileResolver( + ...validationMethods: ( + | ValidationMethodObjectInterface + | (() => ValidationMethodObjectInterface) + )[] +): Validator { + const _validationMethods = normalizeArray(validationMethods); + const validator = new Validator(); + + _validationMethods.forEach((validationMethod) => { + if (typeof validationMethod !== 'object') { + validationMethod = validationMethod(); + } + + validator.addValidationMethod( + `${validationMethod.name}_${generateId()}`, + validationMethod.method + ); + }); + + return validator; +} diff --git a/packages/multieditor/src/validator/resolvers/index.ts b/packages/multieditor/src/validator/resolvers/index.ts new file mode 100644 index 00000000..af44a737 --- /dev/null +++ b/packages/multieditor/src/validator/resolvers/index.ts @@ -0,0 +1,2 @@ +export * from './yup'; +export * from './agile'; diff --git a/packages/multieditor/src/validator/resolvers/yup/index.ts b/packages/multieditor/src/validator/resolvers/yup/index.ts index e69de29b..142eb521 100644 --- a/packages/multieditor/src/validator/resolvers/yup/index.ts +++ b/packages/multieditor/src/validator/resolvers/yup/index.ts @@ -0,0 +1,42 @@ +import * as Yup from 'yup'; +import { Validator } from '../../validator'; +import { generateId } from '@agile-ts/core'; + +export function yupResolver(schema: Yup.BaseSchema): Validator { + const validator = new Validator(); + validator.addValidationMethod( + `yup_${generateId()}`, + async (toValidateItemKey, value, editor) => { + let isValid = true; + try { + await schema.validate(value); + } catch (e: any) { + isValid = false; + + // Resolve Yup Error + if (e.name === 'ValidationError') { + if (e.inner != null) { + if (e.inner.length === 0) { + editor.setStatus( + toValidateItemKey, + 'error', + e.message.replace('this', toValidateItemKey) + ); + } + for (let err of e.inner) { + editor.setStatus( + toValidateItemKey, + 'error', + err.message.replace('this', toValidateItemKey) + ); + } + } + } + } + + return isValid; + } + ); + + return validator; +} diff --git a/packages/multieditor/src/validator/schemas/general.ts b/packages/multieditor/src/validator/validationMethods/general.ts similarity index 100% rename from packages/multieditor/src/validator/schemas/general.ts rename to packages/multieditor/src/validator/validationMethods/general.ts diff --git a/packages/multieditor/src/validator/schemas/number.ts b/packages/multieditor/src/validator/validationMethods/number.ts similarity index 100% rename from packages/multieditor/src/validator/schemas/number.ts rename to packages/multieditor/src/validator/validationMethods/number.ts diff --git a/packages/multieditor/src/validator/schemas/string.ts b/packages/multieditor/src/validator/validationMethods/string.ts similarity index 100% rename from packages/multieditor/src/validator/schemas/string.ts rename to packages/multieditor/src/validator/validationMethods/string.ts diff --git a/packages/multieditor/src/validator/validator.ts b/packages/multieditor/src/validator/validator.ts index c574eb83..f48d3c13 100644 --- a/packages/multieditor/src/validator/validator.ts +++ b/packages/multieditor/src/validator/validator.ts @@ -1,21 +1,22 @@ import { generateId, isFunction, LogCodeManager } from '@agile-ts/core'; +import { defineConfig, isValidObject } from '@agile-ts/utils'; import { ItemKey, Multieditor } from '../multieditor'; -import { defineConfig } from '@agile-ts/utils'; +import { Item } from '../item'; export class Validator { public _key?: ValidatorKey; public config: ValidatorConfigInterface = {}; // Schemas to validate Items via this Validator - public validationSchemas: { + public validationMethods: { [key: string]: ValidationMethodInterface; } = {}; /** - * Validator - Easy way to validate Editor Values + * Class to handle schema validations. * * @public - * @param config - Config + * @param config - Configuration object */ constructor(config: ValidatorConfigInterface = {}) { config = defineConfig(config, { @@ -25,42 +26,42 @@ export class Validator { } /** + * Updates the key/name identifier of the Validator. + * * @public - * Set Key/Name of Validator + * @param value - New key/name identifier. */ public set key(value: ValidatorKey | undefined) { this._key = value; } /** + * Returns the key/name identifier of the Validator. + * * @public - * Get Key/Name of Validator */ public get key(): ValidatorKey | undefined { return this._key; } - //========================================================================================================= - // Validate - //========================================================================================================= /** + * Validates the specified value + * and updates the status of the provided Item. + * * @public - * Validates Item Value at Key and updates its Status - * @param key - Key/Name of Item - * @param value - Value that gets validated - * @param editor - MultiEditor that holds the Item which gets validated + * @param item - Item to apply the validated value to. + * @param value - Value to be validated. */ public async validate( - key: ItemKey, - value: DataType, - editor: Multieditor + item: Item, + value: DataType ): Promise { let isValid = true; - const item = editor.getItemById(key); - if (item == null) return false; + if (item == null || item._key == null) return false; + const editor = item.editor(); // Reverse validation methods because the first method should have the highest weight - const validationMethodKeys = Object.keys(this.validationSchemas).reverse(); + const validationMethodKeys = Object.keys(this.validationMethods).reverse(); // Track created Statuses during the Validation Time item.status.statusTracker.track(); @@ -68,8 +69,8 @@ export class Validator { // Call validation methods (-> validate Item at specified key) for (const validationMethodKey of validationMethodKeys) isValid = - (await this.validationSchemas[validationMethodKey]( - key, + (await this.validationMethods[validationMethodKey]( + item._key, value, editor )) && isValid; @@ -77,60 +78,75 @@ export class Validator { // Handle tracked Statuses const trackedStatuses = item.status.statusTracker.getTrackedStatuses(); item.status.activeValues = new Set(trackedStatuses); - if (trackedStatuses.length <= 0) editor.resetStatus(key); + if (trackedStatuses.length <= 0) editor.resetStatus(item._key); return isValid; } - //========================================================================================================= - // Add Validation Method - //========================================================================================================= /** + * Assigns a new validation method to the Validator. + * * @public - * Adds Validation Method to Validator - * @param method - Validation Method + * @param method - Validation method to be added. */ - public addValidationSchema( - method: AddValidationMethodMethodType - ): this; - public addValidationSchema( + public addValidationMethod(method: ValidationMethodInterface): this; + /** + * Assigns a new validation method to the Validator. + * + * @public + * @param key - Key/Name identifier of the to add validation method. + * @param method - Validation method to be added + */ + public addValidationMethod( key: ValidationMethodKey, - method: AddValidationMethodMethodType + method: ValidationMethodInterface ): this; - public addValidationSchema( - keyOrMethod: ValidationMethodKey | AddValidationMethodMethodType, - method?: AddValidationMethodMethodType + public addValidationMethod( + keyOrMethod: ValidationMethodKey | ValidationMethodInterface, + method?: ValidationMethodInterface ): this { - const generateKey = isFunction(keyOrMethod); - let validationMethodObject: AddValidationMethodMethodType; + let _method: ValidationMethodInterface; let key: ValidationMethodKey; - if (generateKey) { + if (isFunction(keyOrMethod)) { key = generateId(); - validationMethodObject = keyOrMethod as AddValidationMethodMethodType< - DataType - >; + _method = keyOrMethod as ValidationMethodInterface; } else { key = keyOrMethod as string; - validationMethodObject = method as AddValidationMethodMethodType< - DataType - >; + _method = method as ValidationMethodInterface; } - // Resolve validation schema - // TODO add Yup support via resolvers (https://github.dev/formium/formik/tree/master/packages/formik/src, https://github.com/react-hook-form/resolvers) - if (typeof validationMethodObject !== 'object') { - validationMethodObject = validationMethodObject(); + if (!isFunction(_method)) { + // TODO error + return this; } - if (!isFunction(validationMethodObject.method)) { - LogCodeManager.getLogger()?.error( - 'A Validation Method has to be a function!' - ); + this.validationMethods[key] = _method; + + return this; + } + + /** + * Appends the specified Validator to this Validator. + * + * @public + * @param validator - Validator to be appended to this Validator. + */ + public append(validator: Validator) { + if (validator === this) { + // TODO error return this; } - this.validationSchemas[key] = validationMethodObject.method; + // Append validation methods to this Validator + const toMergeValidationMethodKeys = Object.keys( + validator.validationMethods + ); + for (const key of toMergeValidationMethodKeys) { + if (!this.validationMethods.hasOwnProperty(key)) { + this.validationMethods[key] = validator.validationMethods[key]; + } + } return this; } @@ -138,10 +154,6 @@ export class Validator { export type ValidatorKey = string | number; -export type AddValidationMethodMethodType = - | ValidationMethodObjectInterface - | (() => ValidationMethodObjectInterface); - /** * @param key - Key/Name of Validator * @param prefix - Validation Method Prefix @@ -154,7 +166,7 @@ export type ValidationMethodInterface = ( toValidateItemKey: ItemKey, value: DataType, editor: Multieditor -) => boolean; +) => Promise | boolean; export type ValidationMethodKey = string | number; diff --git a/yarn.lock b/yarn.lock index 165b8170..adc5d7cc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2449,6 +2449,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.10.5": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.4.tgz#fd17d16bfdf878e6dd02d19753a39fa8a8d9c84a" + integrity sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/template@^7.10.4", "@babel/template@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.14.5.tgz#a9bc9d8b33354ff6e55a9c60d1109200a68974f4" @@ -4467,6 +4474,11 @@ "@types/koa-compose" "*" "@types/node" "*" +"@types/lodash@^4.14.165": + version "4.14.173" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.173.tgz#9d3b674c67a26cf673756f6aca7b429f237f91ed" + integrity sha512-vv0CAYoaEjCw/mLy96GBTnRoZrSxkGE0BKzKimdR8P3OzrNYNvBgtW7p055A+E8C31vXNUhWKoFCbhq7gbyhFg== + "@types/long@^4.0.0": version "4.0.1" resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.1.tgz#459c65fa1867dafe6a8f322c4c51695663cc55e9" @@ -12637,6 +12649,11 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" +lodash-es@^4.17.15: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" + integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== + lodash._reinterpolate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" @@ -13398,6 +13415,11 @@ nan@^2.12.1: resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19" integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ== +nanoclone@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/nanoclone/-/nanoclone-0.2.1.tgz#dd4090f8f1a110d26bb32c49ed2f5b9235209ed4" + integrity sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA== + nanoid@^2.1.0: version "2.1.11" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-2.1.11.tgz#ec24b8a758d591561531b4176a01e3ab4f0f0280" @@ -15521,6 +15543,11 @@ prop-types@^15.7.2: object-assign "^4.1.1" react-is "^16.8.1" +property-expr@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-2.0.4.tgz#37b925478e58965031bb612ec5b3260f8241e910" + integrity sha512-sFPkHQjVKheDNnPvotjQmm3KD3uk1fWKUN7CrpdbwmUx3CrG3QiM8QpTSimvig5vTXmTvjz7+TDvXOI9+4rkcg== + proto-list@~1.2.1: version "1.2.4" resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" @@ -18038,6 +18065,11 @@ toidentifier@1.0.0: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== +toposort@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/toposort/-/toposort-2.0.2.tgz#ae21768175d1559d48bef35420b2f4962f09c330" + integrity sha1-riF2gXXRVZ1IvvNUILL0li8JwzA= + touch@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b" @@ -19444,6 +19476,19 @@ yocto-queue@^0.1.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== +yup@^0.32.9: + version "0.32.9" + resolved "https://registry.yarnpkg.com/yup/-/yup-0.32.9.tgz#9367bec6b1b0e39211ecbca598702e106019d872" + integrity sha512-Ci1qN+i2H0XpY7syDQ0k5zKQ/DoxO0LzPg8PAR/X4Mpj6DqaeCoIYEEjDJwhArh3Fa7GWbQQVDZKeXYlSH4JMg== + dependencies: + "@babel/runtime" "^7.10.5" + "@types/lodash" "^4.14.165" + lodash "^4.17.20" + lodash-es "^4.17.15" + nanoclone "^0.2.1" + property-expr "^2.0.4" + toposort "^2.0.2" + zen-observable-ts@^0.8.21: version "0.8.21" resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-0.8.21.tgz#85d0031fbbde1eba3cd07d3ba90da241215f421d" From e4335a47afc6e78fdcff518323c4155244913498 Mon Sep 17 00:00:00 2001 From: BennoDev Date: Wed, 22 Sep 2021 17:21:20 +0200 Subject: [PATCH 05/14] fixed typos --- .../react/develop/multieditor-ts/src/App.tsx | 68 +-- .../multieditor-ts/src/core/signUpEditor.ts | 29 +- packages/multieditor/README.md | 12 +- packages/multieditor/src/item.ts | 12 +- .../src/multieditor/multieditor.ts | 388 +++++++++--------- packages/multieditor/src/status/status.ts | 1 + .../src/validator/resolvers/agile/index.ts | 34 +- .../src/validator/resolvers/yup/index.ts | 9 + .../validator/validationMethods/general.ts | 4 +- .../src/validator/validationMethods/number.ts | 6 +- .../src/validator/validationMethods/string.ts | 4 +- .../multieditor/src/validator/validator.ts | 28 +- .../multieditor/tests/old/default.spec.ts | 6 +- 13 files changed, 340 insertions(+), 261 deletions(-) diff --git a/examples/react/develop/multieditor-ts/src/App.tsx b/examples/react/develop/multieditor-ts/src/App.tsx index 96b5658b..3ff0c2ed 100644 --- a/examples/react/develop/multieditor-ts/src/App.tsx +++ b/examples/react/develop/multieditor-ts/src/App.tsx @@ -1,9 +1,9 @@ -import React from "react"; -import "./App.css"; -import ErrorMessage from "./components/ErrorMessage"; -import { useAgile } from "@agile-ts/react"; -import { signUpEditor } from "./core/signUpEditor"; -import { generateColor, generateId } from "./core/utils"; +import React from 'react'; +import './App.css'; +import ErrorMessage from './components/ErrorMessage'; +import { useAgile } from '@agile-ts/react'; +import { signUpEditor } from './core/signUpEditor'; +import { generateColor, generateId } from './core/utils'; const App = () => { useAgile(signUpEditor.deps); @@ -13,29 +13,32 @@ const App = () => {

Sign Up

signUpEditor.setValue("firstName", e.target.value)} - value={signUpEditor.getValueById("firstName")} + onChange={(e) => + signUpEditor.setValue('firstName', e.target.value, { + background: false, + }) + } + value={signUpEditor.getItemValue('firstName')} /> - + - signUpEditor.setValue("lastName", e.target.value, { + signUpEditor.setValue('lastName', e.target.value, { background: false, }) } - value={signUpEditor.getValueById("lastName")} + value={signUpEditor.getItemValue('lastName')} /> - +
+ style={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
{ style={{ marginLeft: 50 }} onClick={(event) => { signUpEditor.setValue( - "image", + 'image', { id: generateId(), color: generateColor(), @@ -53,43 +56,41 @@ const App = () => { { background: false } ); event.preventDefault(); - }} - > + }}> Reset Image
- + - + signUpEditor.setValue("userName", e.target.value)} + onChange={(e) => signUpEditor.setValue('userName', e.target.value)} /> - + - signUpEditor.setValue("email", e.target.value)} /> - + signUpEditor.setValue('email', e.target.value)} /> + - signUpEditor.setValue("age", e.target.value)} /> - + signUpEditor.setValue('age', e.target.value)} /> +