Skip to content

Commit

Permalink
0.9.0. (#19)
Browse files Browse the repository at this point in the history
* 0.9.0.
  • Loading branch information
b4rtaz authored Sep 20, 2023
1 parent 160adc9 commit c4940c6
Show file tree
Hide file tree
Showing 37 changed files with 301 additions and 68 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 0.9.0

* Improved validation for the `boolean` value model.
* Improved validation for the `branches` value model.
* Internal changes preparing for the upcoming pro version.

## 0.8.0

Updated the `sequential-workflow-model` dependency to the version `0.2.0`.
Expand Down
6 changes: 3 additions & 3 deletions demos/webpack-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@
"dependencies": {
"xstate": "^4.38.2",
"sequential-workflow-model": "^0.2.0",
"sequential-workflow-designer": "^0.14.1",
"sequential-workflow-designer": "^0.16.0",
"sequential-workflow-machine": "^0.4.0",
"sequential-workflow-editor-model": "^0.8.0",
"sequential-workflow-editor": "^0.8.0"
"sequential-workflow-editor-model": "^0.9.0",
"sequential-workflow-editor": "^0.9.0"
},
"devDependencies": {
"ts-loader": "^9.4.2",
Expand Down
8 changes: 4 additions & 4 deletions editor/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "sequential-workflow-editor",
"version": "0.8.0",
"version": "0.9.0",
"type": "module",
"main": "./lib/esm/index.js",
"types": "./lib/index.d.ts",
Expand Down Expand Up @@ -46,11 +46,11 @@
"prettier:fix": "prettier --write ./src ./css"
},
"dependencies": {
"sequential-workflow-editor-model": "^0.8.0",
"sequential-workflow-editor-model": "^0.9.0",
"sequential-workflow-model": "^0.2.0"
},
"peerDependencies": {
"sequential-workflow-editor-model": "^0.8.0",
"sequential-workflow-editor-model": "^0.9.0",
"sequential-workflow-model": "^0.2.0"
},
"devDependencies": {
Expand Down Expand Up @@ -79,4 +79,4 @@
"lowcode",
"flow"
]
}
}
13 changes: 11 additions & 2 deletions editor/src/components/dynamic-list-component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ export interface DynamicListComponent<TItem> extends Component {
add(item: TItem): void;
}

export interface DynamicListComponentConfiguration {
export interface DynamicListComponentConfiguration<TItem> {
emptyMessage?: string;
canDelete?: (item: TItem) => string | null;
}

export interface DynamicListItemComponent<TItem> extends Component {
Expand All @@ -22,7 +23,7 @@ export function dynamicListComponent<TItem>(
initialItems: TItem[],
itemComponentFactory: (item: TItem) => DynamicListItemComponent<TItem>,
context: ValueContext,
configuration?: DynamicListComponentConfiguration
configuration?: DynamicListComponentConfiguration<TItem>
): DynamicListComponent<TItem> {
const onChanged = new SimpleEvent<TItem[]>();
const items = [...initialItems];
Expand All @@ -38,6 +39,14 @@ export function dynamicListComponent<TItem>(
}

function onItemDeleted(index: number) {
if (configuration && configuration.canDelete) {
const error = configuration.canDelete(items[index]);
if (error) {
window.alert(error);
return;
}
}

items.splice(index, 1);
forward();
reloadList();
Expand Down
10 changes: 10 additions & 0 deletions editor/src/components/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export * from './button-component';
export * from './component';
export * from './dynamic-list-component';
export * from './input-component';
export * from './prepended-input-component';
export * from './row-component';
export * from './select-component';
export * from './textarea-component';
export * from './validation-error-component';
export * from './value-editor-container-component';
5 changes: 5 additions & 0 deletions editor/src/core/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
export * from './append-multiline-text';
export * from './filter-value-types';
export * from './filter-value-types';
export * from './html';
export * from './icons';
export * from './stacked-simple-event';
export * from './variable-name-formatter';
10 changes: 10 additions & 0 deletions editor/src/editor-extension.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { ValueEditorFactory } from './value-editors';

export interface EditorExtension {
valueEditors?: ValueEditorExtension[];
}

export interface ValueEditorExtension {
editorId: string;
factory: ValueEditorFactory;
}
2 changes: 2 additions & 0 deletions editor/src/editor-provider-configuration.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { UidGenerator } from 'sequential-workflow-editor-model';
import { DefinitionWalker } from 'sequential-workflow-model';
import { EditorExtension } from './editor-extension';

export interface EditorProviderConfiguration {
uidGenerator: UidGenerator;
definitionWalker?: DefinitionWalker;
isHeaderHidden?: boolean;
extensions?: EditorExtension[];
}
20 changes: 14 additions & 6 deletions editor/src/editor-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
Path,
StepValidatorContext
} from 'sequential-workflow-editor-model';
import { EditorServices, ValueEditorEditorFactoryResolver } from './value-editors';
import { EditorServices, ValueEditorFactoryResolver } from './value-editors';
import {
GlobalEditorContext,
RootEditorProvider,
Expand All @@ -30,19 +30,21 @@ export class EditorProvider<TDefinition extends Definition> {
const definitionWalker = configuration.definitionWalker ?? new DefinitionWalker();
const activator = ModelActivator.create(definitionModel, configuration.uidGenerator);
const validator = DefinitionValidator.create(definitionModel, definitionWalker);
return new EditorProvider(activator, validator, definitionModel, definitionWalker, configuration);
const valueEditorFactoryResolver = ValueEditorFactoryResolver.create(configuration.extensions);
return new EditorProvider(activator, validator, definitionModel, definitionWalker, valueEditorFactoryResolver, configuration);
}

private readonly services: EditorServices = {
activator: this.activator,
valueEditorFactoryResolver: ValueEditorEditorFactoryResolver.resolve
valueEditorFactoryResolver: this.valueEditorFactoryResolver
};

private constructor(
private readonly activator: ModelActivator<TDefinition>,
private readonly validator: DefinitionValidator,
private readonly definitionModel: DefinitionModel,
private readonly definitionWalker: DefinitionWalker,
private readonly valueEditorFactoryResolver: ValueEditorFactoryResolver,
private readonly configuration: EditorProviderConfiguration
) {}

Expand Down Expand Up @@ -82,11 +84,17 @@ export class EditorProvider<TDefinition extends Definition> {
const editor = Editor.create(headerData, validator, propertyModels, definitionContext, this.services, typeClassName);

editor.onValuesChanged.subscribe((paths: Path[]) => {
if (paths.some(path => path.equals(stepModel.name.value.path))) {
const isNameChanged = paths.some(path => path.equals(stepModel.name.value.path));
if (isNameChanged) {
context.notifyNameChanged();
} else {
context.notifyPropertiesChanged();
return;
}
const areBranchesChanged = paths.some(path => path.equals('branches'));
if (areBranchesChanged) {
context.notifyChildrenChanged();
return;
}
context.notifyPropertiesChanged();
});
return editor.root;
};
Expand Down
4 changes: 2 additions & 2 deletions editor/src/editor.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { DefinitionContext, Path, PropertyModel, PropertyModels } from 'sequential-workflow-editor-model';
import { PropertyEditor } from './property-editor/property-editor';
import { EditorServices, ValueEditorEditorFactoryResolver } from './value-editors';
import { EditorServices } from './value-editors';
import { EditorHeader, EditorHeaderData } from './editor-header';
import { StackedSimpleEvent } from './core/stacked-simple-event';
import { ValidationErrorComponent, validationErrorComponent } from './components/validation-error-component';
Expand Down Expand Up @@ -32,7 +32,7 @@ export class Editor {

const editors = new Map<PropertyModel, PropertyEditor>();
for (const propertyModel of propertyModels) {
if (ValueEditorEditorFactoryResolver.isHidden(propertyModel.value.id)) {
if (editorServices.valueEditorFactoryResolver.isHidden(propertyModel.value.id, propertyModel.value.editorId)) {
continue;
}

Expand Down
1 change: 1 addition & 0 deletions editor/src/external-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Definition, Step } from 'sequential-workflow-model';
export interface StepEditorContext {
notifyNameChanged(): void;
notifyPropertiesChanged(): void;
notifyChildrenChanged(): void;
}

export interface GlobalEditorContext {
Expand Down
2 changes: 2 additions & 0 deletions editor/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export * from './components';
export * from './core';
export * from './value-editors';
export * from './editor-extension';
export * from './editor-provider-configuration';
export * from './editor-provider';
2 changes: 1 addition & 1 deletion editor/src/property-editor/property-editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export class PropertyEditor implements Component {
editorServices: EditorServices
): PropertyEditor {
const valueContext = ValueContext.create(propertyModel.value, propertyModel, definitionContext);
const valueEditorFactory = editorServices.valueEditorFactoryResolver(propertyModel.value.id);
const valueEditorFactory = editorServices.valueEditorFactoryResolver.resolve(propertyModel.value.id, propertyModel.value.editorId);
const valueEditor = valueEditorFactory(valueContext, editorServices);
let hint: PropertyHintComponent | null = null;

Expand Down
2 changes: 1 addition & 1 deletion editor/src/value-editors/dynamic/dynamic-value-editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export function dynamicValueEditor(context: ValueContext<DynamicValueModel>, ser
}

const childContext = context.createChildContext(model);
editor = services.valueEditorFactoryResolver(model.id)(childContext, services);
editor = services.valueEditorFactoryResolver.resolve(model.id, model.editorId)(childContext, services);
placeholder.appendChild(editor.view);
}

Expand Down
70 changes: 45 additions & 25 deletions editor/src/value-editors/value-editor-factory-resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,35 +15,55 @@ import { nullableAnyVariableValueEditor, nullableAnyVariableValueEditorId } from
import { booleanValueEditor, booleanValueEditorId } from './boolean/boolean-value-editor';
import { generatedStringValueEditor, generatedStringValueEditorId } from './generated-string/generated-string-value-editor';
import { stringDictionaryValueEditor } from './string-dictionary/string-dictionary-value-editor';
import { EditorExtension } from '../editor-extension';

const editors: { id: string; factory: ValueEditorFactory | null }[] = [
{ id: anyVariablesValueEditorId, factory: anyVariablesValueEditor as ValueEditorFactory },
{ id: booleanValueEditorId, factory: booleanValueEditor as ValueEditorFactory },
{ id: choiceValueEditorId, factory: choiceValueEditor as ValueEditorFactory },
{ id: nullableAnyVariableValueEditorId, factory: nullableAnyVariableValueEditor as ValueEditorFactory },
{ id: dynamicValueEditorId, factory: dynamicValueEditor as ValueEditorFactory },
{ id: generatedStringValueEditorId, factory: generatedStringValueEditor as ValueEditorFactory },
{ id: nullableVariableValueEditorId, factory: nullableVariableValueEditor as ValueEditorFactory },
{ id: nullableVariableDefinitionValueEditorId, factory: nullableVariableDefinitionValueEditor as ValueEditorFactory },
{ id: stringValueEditorId, factory: stringValueEditor as ValueEditorFactory },
{ id: stringDictionaryValueModelId, factory: stringDictionaryValueEditor as ValueEditorFactory },
{ id: numberValueEditorId, factory: numberValueEditor as ValueEditorFactory },
{ id: variableDefinitionsValueEditorId, factory: variableDefinitionsValueEditor as ValueEditorFactory },
{ id: sequenceValueModelId, factory: null },
{ id: branchesValueModelId, factory: null }
];
const defaultMap: ValueEditorMap = {
[anyVariablesValueEditorId]: anyVariablesValueEditor as ValueEditorFactory,
[booleanValueEditorId]: booleanValueEditor as ValueEditorFactory,
[choiceValueEditorId]: choiceValueEditor as ValueEditorFactory,
[nullableAnyVariableValueEditorId]: nullableAnyVariableValueEditor as ValueEditorFactory,
[dynamicValueEditorId]: dynamicValueEditor as ValueEditorFactory,
[generatedStringValueEditorId]: generatedStringValueEditor as ValueEditorFactory,
[nullableVariableValueEditorId]: nullableVariableValueEditor as ValueEditorFactory,
[nullableVariableDefinitionValueEditorId]: nullableVariableDefinitionValueEditor as ValueEditorFactory,
[stringValueEditorId]: stringValueEditor as ValueEditorFactory,
[stringDictionaryValueModelId]: stringDictionaryValueEditor as ValueEditorFactory,
[numberValueEditorId]: numberValueEditor as ValueEditorFactory,
[variableDefinitionsValueEditorId]: variableDefinitionsValueEditor as ValueEditorFactory,
[sequenceValueModelId]: null,
[branchesValueModelId]: null
};

export class ValueEditorEditorFactoryResolver {
public static resolve(valueModelId: string): ValueEditorFactory {
const editor = editors.find(editor => editor.id === valueModelId);
if (!editor || !editor.factory) {
throw new Error(`Value model id: ${valueModelId} is not supported`);
type ValueEditorMap = Record<string, ValueEditorFactory | null>;

export class ValueEditorFactoryResolver {
public static create(extensions?: EditorExtension[]): ValueEditorFactoryResolver {
let map: ValueEditorMap;
if (extensions) {
map = { ...defaultMap };
extensions.forEach(extension => {
if (extension.valueEditors) {
extension.valueEditors.forEach(e => (map[e.editorId] = e.factory));
}
});
} else {
map = defaultMap;
}
return new ValueEditorFactoryResolver(map);
}

private constructor(private readonly map: ValueEditorMap) {}

public resolve(valueModelId: string, editorId: string | undefined): ValueEditorFactory {
const id = editorId ?? valueModelId;
const editor = this.map[id];
if (!editor) {
throw new Error(`Editor id ${id} is not supported`);
}
return editor.factory;
return editor;
}

public static isHidden(valueModelId: string): boolean {
const editor = editors.find(editor => editor.id === valueModelId);
return editor ? editor.factory === null : false;
public isHidden(valueModelId: string, editorId: string | undefined): boolean {
return !this.map[editorId ?? valueModelId];
}
}
3 changes: 1 addition & 2 deletions editor/src/value-editors/value-editor.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ModelActivator, ValueModel, ValueContext } from 'sequential-workflow-editor-model';
import { ValueEditorFactoryResolver } from './value-editor-factory-resolver';
import { Component } from '../components/component';

// eslint-disable-next-line @typescript-eslint/no-unused-vars
Expand All @@ -12,8 +13,6 @@ export type ValueEditorFactory<TValueModel extends ValueModel = ValueModel> = (
services: EditorServices
) => ValueEditor<TValueModel>;

export type ValueEditorFactoryResolver = (valueModelId: string) => ValueEditorFactory;

export interface EditorServices {
valueEditorFactoryResolver: ValueEditorFactoryResolver;
activator: ModelActivator;
Expand Down
2 changes: 1 addition & 1 deletion model/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "sequential-workflow-editor-model",
"version": "0.8.0",
"version": "0.9.0",
"homepage": "https://nocode-js.com/",
"author": {
"name": "NoCode JS",
Expand Down
4 changes: 2 additions & 2 deletions model/src/context/value-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ export class ValueContext<TValueModel extends ValueModel = ValueModel, TProperti
this.onValueChanged.forward(this.model.path);
}

public validate(): ValidationResult {
public readonly validate = (): ValidationResult => {
return this.model.validate(this);
}
};

public readonly getPropertyValue = <Key extends keyof TProperties>(name: Key): TProperties[Key] => {
return readPropertyValue(name, this.propertyModel, this.definitionContext.object);
Expand Down
6 changes: 3 additions & 3 deletions model/src/context/variables-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export class ParentsProvider {

if (this.step) {
const parents = this.definitionWalker.getParents(this.definition, this.step);
const count = parents.length - 1; // skips variable definitions from itself
const count = parents.length;
for (let index = 0; index < count; index++) {
const parent = parents[index];
if (typeof parent === 'string') {
Expand Down Expand Up @@ -81,10 +81,10 @@ export class ParentsProvider {
}
}

public readonly getStepTypes = (): string[] => {
public readonly getParentStepTypes = (): string[] => {
if (this.step) {
const parents = this.definitionWalker.getParents(this.definition, this.step);
return (parents.filter(p => typeof p === 'object') as Step[]).map(p => p.type);
return (parents.slice(0, parents.length - 1).filter(p => typeof p === 'object') as Step[]).map(p => p.type);
}
return [];
};
Expand Down
1 change: 1 addition & 0 deletions model/src/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export interface ValueModel<
TProperties extends Properties = Properties
> {
id: ValueModelId;
editorId?: string;
path: Path;
label: string;
configuration: TConfiguration;
Expand Down
5 changes: 4 additions & 1 deletion model/src/test-tools/value-context-stub.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { ValueContext } from '../context';
import { ValueModel } from '../model';

export function createValueContextStub<TValueModel extends ValueModel>(value: unknown, configuration: object): ValueContext<TValueModel> {
export function createValueContextStub<TValueModel extends ValueModel>(
value: unknown,
configuration: TValueModel['configuration']
): ValueContext<TValueModel> {
return {
getValue: () => value,
model: {
Expand Down
2 changes: 1 addition & 1 deletion model/src/validator/step-validator-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ export class StepValidatorContext {
* @returns The parent step types.
* @example `['loop', 'if']`
*/
public readonly getParentStepTypes = this.parentsProvider.getStepTypes;
public readonly getParentStepTypes = this.parentsProvider.getParentStepTypes;
}
Loading

0 comments on commit c4940c6

Please sign in to comment.