Skip to content

Commit 6d9829d

Browse files
authored
0.18.4. (#117)
1 parent 957b90d commit 6d9829d

24 files changed

+157
-85
lines changed

CHANGELOG.md

+11-6
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
1-
## 0.18.3
1+
## 0.18.4
22

3-
Added a feature to the sequential-workflow-designer-react package that enables re-rendering the canvas when you pass a new instance of the wrapped definition. The instance of the definition must remain the same. This enables easy manipulation of the definition from outside the designer in your React application.
3+
This version removes the features introduced in the previous release. We noticed that the proposed solution did not update the undo stack. As a result, we removed that feature in this version. Instead, we added a new method to the Designer class called `replaceDefinition`, which allows for the replacement of the entire definition and updates the undo stack.
44

5-
```tsx
6-
function action() {
5+
```ts
6+
function appendStep() {
77
const newStep: Step = { /* ... */ };
88

9-
definition.value.sequence.push(newStep);
10-
setDefinition({ ...definition });
9+
const newDefinition = ObjectCloner.deepClone(designer.getDefinition());
10+
newDefinition.sequence.push(newStep);
11+
await designer.replaceDefinition(newDefinition);
1112
}
1213
```
1314

15+
## 0.18.3
16+
17+
Edited: changes are reverted in the 0.18.4 version.
18+
1419
## 0.18.2
1520

1621
This version corrects a bug in the `moveViewportToStep` method that caused the viewport to move to the incorrect position.

README.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,10 @@ Add the below code to your head section in HTML document.
9696
```html
9797
<head>
9898
...
99-
<link href="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.18.3/css/designer.css" rel="stylesheet">
100-
<link href="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.18.3/css/designer-light.css" rel="stylesheet">
101-
<link href="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.18.3/css/designer-dark.css" rel="stylesheet">
102-
<script src="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.18.3/dist/index.umd.js"></script>
99+
<link href="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.18.4/css/designer.css" rel="stylesheet">
100+
<link href="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.18.4/css/designer-light.css" rel="stylesheet">
101+
<link href="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.18.4/css/designer-dark.css" rel="stylesheet">
102+
<script src="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.18.4/dist/index.umd.js"></script>
103103
```
104104

105105
Call the designer by:

angular/designer/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "sequential-workflow-designer-angular",
33
"description": "Angular wrapper for Sequential Workflow Designer component.",
4-
"version": "0.18.3",
4+
"version": "0.18.4",
55
"author": {
66
"name": "NoCode JS",
77
"url": "https://nocode-js.com/"
@@ -15,7 +15,7 @@
1515
"peerDependencies": {
1616
"@angular/common": "12 - 16",
1717
"@angular/core": "12 - 16",
18-
"sequential-workflow-designer": "^0.18.3"
18+
"sequential-workflow-designer": "^0.18.4"
1919
},
2020
"dependencies": {
2121
"tslib": "^2.3.0"

demos/angular-app/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626
"@angular/platform-browser-dynamic": "^15.2.9",
2727
"@angular/router": "^15.2.9",
2828
"rxjs": "~7.8.0",
29-
"sequential-workflow-designer": "^0.18.3",
30-
"sequential-workflow-designer-angular": "^0.18.3",
29+
"sequential-workflow-designer": "^0.18.4",
30+
"sequential-workflow-designer-angular": "^0.18.4",
3131
"tslib": "^2.3.0",
3232
"zone.js": "~0.13.0"
3333
},

demos/angular-app/yarn.lock

+8-8
Original file line numberDiff line numberDiff line change
@@ -5956,17 +5956,17 @@ send@0.18.0:
59565956
range-parser "~1.2.1"
59575957
statuses "2.0.1"
59585958

5959-
sequential-workflow-designer-angular@^0.18.3:
5960-
version "0.18.3"
5961-
resolved "https://registry.yarnpkg.com/sequential-workflow-designer-angular/-/sequential-workflow-designer-angular-0.18.3.tgz#4bfb9943c987ac6b609c657a34d48701d10484f0"
5962-
integrity sha512-mJGok8qR0xDffn+tNBS3O8wCK9xgu8n/xiIVCurwqcPJ46jvHiQdjnJfS4Ea8bj5MGC1uRQvle9zO8puNlRzbw==
5959+
sequential-workflow-designer-angular@^0.18.4:
5960+
version "0.18.4"
5961+
resolved "https://registry.yarnpkg.com/sequential-workflow-designer-angular/-/sequential-workflow-designer-angular-0.18.4.tgz#552062a04c84e294e940858a2c99b843b0ac4705"
5962+
integrity sha512-K4ZxmbNGQhvJqYqC4ZszHYswViDKTHTKbc3YmqtVpGA5asVJ0fbhNEsfZyRzvI3N7F5/BAQtWvPRA1FKjvOXxg==
59635963
dependencies:
59645964
tslib "^2.3.0"
59655965

5966-
sequential-workflow-designer@^0.18.3:
5967-
version "0.18.3"
5968-
resolved "https://registry.yarnpkg.com/sequential-workflow-designer/-/sequential-workflow-designer-0.18.3.tgz#3c2165550160216fb40e2eb945c654d5ae5d505c"
5969-
integrity sha512-IchagYDpIYNvIVv4HleKn+x+ZfItVDxoQqQbBF1Ms7vEZdd0CwfvB17NBZLfz02LTGyGE/GGGPc8IEvqkajvMQ==
5966+
sequential-workflow-designer@^0.18.4:
5967+
version "0.18.4"
5968+
resolved "https://registry.yarnpkg.com/sequential-workflow-designer/-/sequential-workflow-designer-0.18.4.tgz#da4d3924fab044391c2d0c26244ca164a8b2d659"
5969+
integrity sha512-JdLXiAjsqovJOHJEDXrk+FXcm/GHsoaNAAiaCNx3LqXHimpRMaH+Cy9DdL6L6KNsrLsWQcxWay+B6pokNTUFeg==
59705970
dependencies:
59715971
sequential-workflow-model "^0.2.0"
59725972

demos/react-app/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
"dependencies": {
77
"react": "^18.2.0",
88
"react-dom": "^18.2.0",
9-
"sequential-workflow-designer": "^0.18.3",
10-
"sequential-workflow-designer-react": "^0.18.3"
9+
"sequential-workflow-designer": "^0.18.4",
10+
"sequential-workflow-designer-react": "^0.18.4"
1111
},
1212
"devDependencies": {
1313
"@types/jest": "^29.2.5",

demos/react-app/src/playground/Playground.tsx

+5-4
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,13 @@ export function Playground() {
8686
}
8787
}
8888

89-
function appendStepClicked() {
89+
async function appendStepClicked() {
9090
const newStep = createTaskStep();
9191

92-
// We need to keep the same reference to the definition, but the wrapped definition must be a new instance.
93-
definition.value.sequence.push(newStep);
94-
setDefinition({ ...definition });
92+
const newDefinition = ObjectCloner.deepClone(definition.value);
93+
newDefinition.sequence.push(newStep);
94+
// We need to wait for the controller to finish the operation before we can select the new step
95+
await controller.replaceDefinition(newDefinition);
9596

9697
setSelectedStepId(newStep.id);
9798
setMoveViewportToStep(newStep.id);

demos/svelte-app/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
"eslint": "eslint ./src --ext .ts"
1717
},
1818
"dependencies": {
19-
"sequential-workflow-designer": "^0.18.3",
20-
"sequential-workflow-designer-svelte": "^0.18.3"
19+
"sequential-workflow-designer": "^0.18.4",
20+
"sequential-workflow-designer-svelte": "^0.18.4"
2121
},
2222
"devDependencies": {
2323
"@sveltejs/adapter-static": "^2.0.3",

designer/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "sequential-workflow-designer",
33
"description": "Customizable no-code component for building flow-based programming applications.",
4-
"version": "0.18.3",
4+
"version": "0.18.4",
55
"type": "module",
66
"main": "./lib/esm/index.js",
77
"types": "./lib/index.d.ts",

designer/src/api/control-bar-api.ts

+21-9
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,40 @@
1+
import { SimpleEvent } from '../core';
12
import { DefinitionModifier } from '../definition-modifier';
23
import { DesignerState } from '../designer-state';
34
import { HistoryController } from '../history-controller';
45
import { ViewportApi } from './viewport-api';
56

67
export class ControlBarApi {
7-
public constructor(
8+
public static create(
9+
state: DesignerState,
10+
historyController: HistoryController | undefined,
11+
definitionModifier: DefinitionModifier,
12+
viewportApi: ViewportApi
13+
): ControlBarApi {
14+
const api = new ControlBarApi(state, historyController, definitionModifier, viewportApi);
15+
state.onIsReadonlyChanged.subscribe(api.onStateChanged.forward);
16+
state.onSelectedStepIdChanged.subscribe(api.onStateChanged.forward);
17+
state.onIsDragDisabledChanged.subscribe(api.onStateChanged.forward);
18+
if (api.isUndoRedoSupported()) {
19+
state.onDefinitionChanged.subscribe(api.onStateChanged.forward);
20+
}
21+
return api;
22+
}
23+
24+
private constructor(
825
private readonly state: DesignerState,
926
private readonly historyController: HistoryController | undefined,
1027
private readonly definitionModifier: DefinitionModifier,
1128
private readonly viewportApi: ViewportApi
1229
) {}
1330

31+
public readonly onStateChanged = new SimpleEvent<unknown>();
32+
1433
/**
1534
* @deprecated Don't use this method
1635
*/
1736
public subscribe(handler: () => void) {
18-
// TODO: this should be refactored
19-
20-
this.state.onIsReadonlyChanged.subscribe(handler);
21-
this.state.onSelectedStepIdChanged.subscribe(handler);
22-
this.state.onIsDragDisabledChanged.subscribe(handler);
23-
if (this.isUndoRedoSupported()) {
24-
this.state.onDefinitionChanged.subscribe(handler);
25-
}
37+
this.onStateChanged.subscribe(handler);
2638
}
2739

2840
public resetViewport() {

designer/src/api/designer-api.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export class DesignerApi {
1515
const toolboxDataProvider = new ToolboxDataProvider(context.componentContext.iconProvider, context.configuration.toolbox);
1616

1717
return new DesignerApi(
18-
new ControlBarApi(context.state, context.historyController, context.definitionModifier, viewport),
18+
ControlBarApi.create(context.state, context.historyController, context.definitionModifier, viewport),
1919
new ToolboxApi(context.state, context, context.behaviorController, toolboxDataProvider, context.configuration.uidGenerator),
2020
new EditorApi(context.state, context.definitionWalker, context.definitionModifier),
2121
workspace,

designer/src/api/path-bar-api.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ import { DesignerState } from '../designer-state';
55
export class PathBarApi {
66
public constructor(private readonly state: DesignerState, private readonly definitionWalker: DefinitionWalker) {}
77

8+
public readonly onStateChanged = race(0, this.state.onFolderPathChanged, this.state.onDefinitionChanged);
9+
810
/**
911
* @deprecated Don't use this method
1012
*/
1113
public subscribe(handler: () => void) {
12-
// TODO: this should be refactored
13-
14-
race(0, this.state.onFolderPathChanged, this.state.onDefinitionChanged).subscribe(handler);
14+
this.onStateChanged.subscribe(handler);
1515
}
1616

1717
public setFolderPath(path: string[]) {

designer/src/control-bar/control-bar.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export class ControlBar implements UiComponent {
1414
view.bindZoomOutButtonClick(() => bar.onZoomOutButtonClicked());
1515
view.bindDisableDragButtonClick(() => bar.onMoveButtonClicked());
1616
view.bindDeleteButtonClick(() => bar.onDeleteButtonClicked());
17-
api.controlBar.subscribe(() => bar.refreshButtons());
17+
api.controlBar.onStateChanged.subscribe(() => bar.refreshButtons());
1818

1919
if (isUndoRedoSupported) {
2020
view.bindUndoButtonClick(() => bar.onUndoButtonClicked());

designer/src/core/simple-event.spec.ts

+17
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,21 @@ describe('SimpleEvent', () => {
2121
expect(counter).toEqual(1);
2222
expect(e.count()).toEqual(0);
2323
});
24+
25+
it('first() works as expected', done => {
26+
const e = new SimpleEvent<number>();
27+
let lastValue: number | undefined;
28+
29+
e.first().then(v => (lastValue = v));
30+
31+
e.forward(1);
32+
e.forward(2);
33+
e.forward(3);
34+
e.forward(4);
35+
36+
setTimeout(() => {
37+
expect(lastValue).toEqual(1);
38+
done();
39+
}, 10);
40+
});
2441
});

designer/src/core/simple-event.ts

+12-2
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,25 @@ export class SimpleEvent<T> {
1414
}
1515
}
1616

17-
public forward(value: T) {
17+
public readonly forward = (value: T) => {
1818
if (this.listeners.length > 0) {
1919
this.listeners.forEach(listener => listener(value));
2020
}
21-
}
21+
};
2222

2323
public count(): number {
2424
return this.listeners.length;
2525
}
26+
27+
public first(): Promise<T> {
28+
return new Promise(resolve => {
29+
const handler = (value: T) => {
30+
this.unsubscribe(handler);
31+
resolve(value);
32+
};
33+
this.subscribe(handler);
34+
});
35+
}
2636
}
2737

2838
export type SimpleEventListener<T> = (value: T) => void;

designer/src/designer.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { Workspace } from './workspace/workspace';
1010
describe('Designer', () => {
1111
it('create() creates designer', () => {
1212
const workspaceSpy = spyOn(Workspace, 'create').and.returnValues({
13-
onReady: new SimpleEvent<void>()
13+
onRendered: new SimpleEvent<void>()
1414
} as Workspace);
1515
const toolboxSpy = spyOn(Toolbox, 'create');
1616
const controlBarSpy = spyOn(ControlBar, 'create');

designer/src/designer.ts

+25-14
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export class Designer<TDefinition extends Definition = Definition> {
5353
designerContext.historyController,
5454
designerApi
5555
);
56-
view.workspace.onReady.subscribe(() => designer.onReady.forward());
56+
view.workspace.onRendered.first().then(designer.onReady.forward);
5757

5858
race(0, designerContext.state.onDefinitionChanged, designerContext.state.onSelectedStepIdChanged).subscribe(
5959
([definition, selectedStepId]) => {
@@ -66,15 +66,9 @@ export class Designer<TDefinition extends Definition = Definition> {
6666
}
6767
);
6868

69-
designerContext.state.onViewportChanged.subscribe(viewPort => {
70-
designer.onViewportChanged.forward(viewPort);
71-
});
72-
designerContext.state.onIsToolboxCollapsedChanged.subscribe(isCollapsed => {
73-
designer.onIsToolboxCollapsedChanged.forward(isCollapsed);
74-
});
75-
designerContext.state.onIsEditorCollapsedChanged.subscribe(isCollapsed => {
76-
designer.onIsEditorCollapsedChanged.forward(isCollapsed);
77-
});
69+
designerContext.state.onViewportChanged.subscribe(designer.onViewportChanged.forward);
70+
designerContext.state.onIsToolboxCollapsedChanged.subscribe(designer.onIsToolboxCollapsedChanged.forward);
71+
designerContext.state.onIsEditorCollapsedChanged.subscribe(designer.onIsEditorCollapsedChanged.forward);
7872
return designer;
7973
}
8074

@@ -240,10 +234,20 @@ export class Designer<TDefinition extends Definition = Definition> {
240234
* @description Dump the undo stack.
241235
*/
242236
public dumpUndoStack(): UndoStack {
243-
if (!this.historyController) {
244-
throw new Error('Undo feature is not activated');
245-
}
246-
return this.historyController.dump();
237+
return this.getHistoryController().dump();
238+
}
239+
240+
/**
241+
* Replaces the current definition with a new one and adds the previous definition to the undo stack.
242+
* @param definition A new definition.
243+
*/
244+
public async replaceDefinition(definition: TDefinition) {
245+
this.getHistoryController().replaceDefinition(definition);
246+
247+
await Promise.all([
248+
this.view.workspace.onRendered.first(), // This should be fired first
249+
this.onDefinitionChanged.first()
250+
]);
247251
}
248252

249253
/**
@@ -267,4 +271,11 @@ export class Designer<TDefinition extends Definition = Definition> {
267271
public destroy() {
268272
this.view.destroy();
269273
}
274+
275+
private getHistoryController(): HistoryController {
276+
if (!this.historyController) {
277+
throw new Error('Undo feature is not activated');
278+
}
279+
return this.historyController;
280+
}
270281
}

0 commit comments

Comments
 (0)