diff --git a/CHANGELOG.md b/CHANGELOG.md index 186cc57..8156b0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.9.3 + +Added `hasVariable` and `hasVariables` methods to the `PropertyValidatorContext` class. + ## 0.9.2 This version fixes a bug in the `ValueEditorFactoryResolver` class. Now, when an editor is not found, the resolver throws an error. diff --git a/demos/webpack-app/package.json b/demos/webpack-app/package.json index 4556dc9..e2f72a0 100644 --- a/demos/webpack-app/package.json +++ b/demos/webpack-app/package.json @@ -16,10 +16,10 @@ "dependencies": { "xstate": "^4.38.2", "sequential-workflow-model": "^0.2.0", - "sequential-workflow-designer": "^0.16.0", + "sequential-workflow-designer": "^0.16.1", "sequential-workflow-machine": "^0.4.0", - "sequential-workflow-editor-model": "^0.9.2", - "sequential-workflow-editor": "^0.9.2" + "sequential-workflow-editor-model": "^0.9.3", + "sequential-workflow-editor": "^0.9.3" }, "devDependencies": { "ts-loader": "^9.4.2", diff --git a/demos/webpack-app/src/playground/machine/activities/set-string-value-activity.ts b/demos/webpack-app/src/playground/machine/activities/set-string-value-activity.ts index 902e792..8be4ac6 100644 --- a/demos/webpack-app/src/playground/machine/activities/set-string-value-activity.ts +++ b/demos/webpack-app/src/playground/machine/activities/set-string-value-activity.ts @@ -1,6 +1,7 @@ import { createAtomActivity } from 'sequential-workflow-machine'; import { GlobalState } from '../global-state'; import { SetStringValueStep } from '../../model/set-string-value-step-model'; +import { TextVariableParser } from '../../utilities/text-variable-parser'; export const setStringValueActivity = createAtomActivity('setStringValue', { init: () => ({}), @@ -9,7 +10,12 @@ export const setStringValueActivity = createAtomActivity { + return String($variables.read(variableName)); + }); + $variables.set(step.properties.variable.name, value); } }); diff --git a/demos/webpack-app/src/playground/model/set-string-value-step-model.ts b/demos/webpack-app/src/playground/model/set-string-value-step-model.ts index eff7fb3..6d16bd1 100644 --- a/demos/webpack-app/src/playground/model/set-string-value-step-model.ts +++ b/demos/webpack-app/src/playground/model/set-string-value-step-model.ts @@ -8,6 +8,7 @@ import { createStringValueModel } from 'sequential-workflow-editor-model'; import { Step } from 'sequential-workflow-model'; +import { TextVariableParser } from '../utilities/text-variable-parser'; export interface SetStringValueStep extends Step { type: 'setStringValue'; @@ -43,5 +44,18 @@ export const setStringValueStepModel = createStepModel('setS ] }) ) - .label('Value'); + .label('Value') + .validator({ + validate(context) { + const value = context.getValue(); + if (value.modelId === 'string') { + const variables = TextVariableParser.parse(value.value as string); + const notFoundIndex = context.hasVariables(variables).findIndex(v => !v); + if (notFoundIndex >= 0) { + return `Variable $${variables[notFoundIndex]} is not defined`; + } + } + return null; + } + }); }); diff --git a/demos/webpack-app/src/playground/utilities/text-variable-parser.ts b/demos/webpack-app/src/playground/utilities/text-variable-parser.ts new file mode 100644 index 0000000..83c3473 --- /dev/null +++ b/demos/webpack-app/src/playground/utilities/text-variable-parser.ts @@ -0,0 +1,14 @@ +const regexp = /\$[A-Za-z][a-zA-Z_0-9-]*/g; + +export class TextVariableParser { + public static parse(text: string): string[] { + return (text.match(regexp) || []).map(v => v.substring(1)); + } + + public static replace(text: string, valueProvider: (variableName: string) => string): string { + return text.replace(regexp, v => { + const variableName = v.substring(1); + return valueProvider(variableName); + }); + } +} diff --git a/editor/package.json b/editor/package.json index 274400c..88debe8 100644 --- a/editor/package.json +++ b/editor/package.json @@ -1,6 +1,6 @@ { "name": "sequential-workflow-editor", - "version": "0.9.2", + "version": "0.9.3", "type": "module", "main": "./lib/esm/index.js", "types": "./lib/index.d.ts", @@ -46,11 +46,11 @@ "prettier:fix": "prettier --write ./src ./css" }, "dependencies": { - "sequential-workflow-editor-model": "^0.9.2", + "sequential-workflow-editor-model": "^0.9.3", "sequential-workflow-model": "^0.2.0" }, "peerDependencies": { - "sequential-workflow-editor-model": "^0.9.2", + "sequential-workflow-editor-model": "^0.9.3", "sequential-workflow-model": "^0.2.0" }, "devDependencies": { diff --git a/editor/src/property-editor/property-editor.ts b/editor/src/property-editor/property-editor.ts index 696312a..9f345f6 100644 --- a/editor/src/property-editor/property-editor.ts +++ b/editor/src/property-editor/property-editor.ts @@ -69,7 +69,11 @@ export class PropertyEditor implements Component { view.appendChild(validationError.view); } - return new PropertyEditor(view, valueContext.onValueChanged, valueEditor, validationError); + const editor = new PropertyEditor(view, valueContext.onValueChanged, valueEditor, validationError); + if (propertyModel.validator) { + valueContext.onValueChanged.subscribe(editor.onValueChangedHandler); + } + return editor; } public constructor( @@ -83,8 +87,16 @@ export class PropertyEditor implements Component { if (this.valueEditor.reloadDependencies) { this.valueEditor.reloadDependencies(); } + this.revalidate(); + } + + private revalidate() { if (this.validationError) { this.validationError.validate(); } } + + private readonly onValueChangedHandler = () => { + this.revalidate(); + }; } diff --git a/model/package.json b/model/package.json index b540b6b..8d0a6dc 100644 --- a/model/package.json +++ b/model/package.json @@ -1,6 +1,6 @@ { "name": "sequential-workflow-editor-model", - "version": "0.9.2", + "version": "0.9.3", "homepage": "https://nocode-js.com/", "author": { "name": "NoCode JS", diff --git a/model/src/validator/property-validator-context.ts b/model/src/validator/property-validator-context.ts index 73cc641..8bca002 100644 --- a/model/src/validator/property-validator-context.ts +++ b/model/src/validator/property-validator-context.ts @@ -20,6 +20,16 @@ export class PropertyValidatorContext(name: Key): TProperties[Key] { return readPropertyValue(name, this.model, this.definitionContext.object); } + + public hasVariable(name: string): boolean { + return this.hasVariables([name])[0]; + } + + public hasVariables(names: string[]): boolean[] { + const variables = this.definitionContext.parentsProvider.getVariables(); + const variableNames = new Set(variables.map(v => v.name)); + return names.map(name => variableNames.has(name)); + } } /** diff --git a/yarn.lock b/yarn.lock index 7eead8c..8ad06bb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5163,10 +5163,10 @@ semver@^7.3.4, semver@^7.3.7, semver@^7.3.8: dependencies: lru-cache "^6.0.0" -sequential-workflow-designer@^0.16.0: - version "0.16.0" - resolved "https://registry.yarnpkg.com/sequential-workflow-designer/-/sequential-workflow-designer-0.16.0.tgz#9771cdb00063e6da395df3d9bc5a280460cf087c" - integrity sha512-9xWdA3C7dQ/z2O61BNA+8QORFR5WGWT4vX7mTAk5HwTE4YcJ+GI4XTjx+5bE8k2E+PL/QmuvbY8rQBFoV9wXvw== +sequential-workflow-designer@^0.16.1: + version "0.16.1" + resolved "https://registry.yarnpkg.com/sequential-workflow-designer/-/sequential-workflow-designer-0.16.1.tgz#9c70627dab95022f53702d86c4fecbc50cd99a90" + integrity sha512-YGp6FD9GJmVFWr+d3ztENE72pp5Glvi6CCEVyZtmlghDY8tA+2C0RcHDYAvUeZg4ZIJyN8Y9Dlkzc/5LnJsEdA== dependencies: sequential-workflow-model "^0.2.0"