Skip to content

Commit 386f7e2

Browse files
authored
Merge pull request #18 from nocode-js/develop
0.5.2.
2 parents f23b57e + f5fe7ca commit 386f7e2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+10441
-1446
lines changed
File renamed without changes.

designer/.prettierrc .prettierrc

File renamed without changes.

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.5.2
2+
3+
This version introduces the first release of the [Sequential Workflow Designer for React](./react/) package.
4+
15
## 0.5.1
26

37
* Fixed calculation of label width in the switch step.

README.md

+7-6
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
# Sequential Workflow Designer
44

5-
[![Build Status](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2Fb4rtaz%2Fsequential-workflow-designer%2Fbadge%3Fref%3Dmain&style=flat-square)](https://actions-badge.atrox.dev/b4rtaz/sequential-workflow-designer/goto?ref=main) [![License: MIT](https://img.shields.io/github/license/mashape/apistatus.svg)](/LICENSE) [![View this project on NPM](https://img.shields.io/npm/v/sequential-workflow-designer.svg)](https://npmjs.org/package/sequential-workflow-designer)
5+
[![Build Status](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2Fb4rtaz%2Fsequential-workflow-designer%2Fbadge%3Fref%3Dmain&style=flat-square)](https://actions-badge.atrox.dev/b4rtaz/sequential-workflow-designer/goto?ref=main) [![License: MIT](https://img.shields.io/github/license/mashape/apistatus.svg?style=flat-square)](/LICENSE) [![View this project on NPM](https://img.shields.io/npm/v/sequential-workflow-designer.svg?style=flat-square)](https://npmjs.org/package/sequential-workflow-designer)
66

77
Sequential workflow designer with no dependencies for web. It's written in pure TypeScript and uses SVG for rendering. This designer is not associated with any workflow engine. It's full generic. You may create any kind application by this, from graphical programming languages to workflow designers.
88

@@ -13,7 +13,8 @@ Features:
1313
* light/dark themes,
1414
* works on modern browsers,
1515
* works on mobile,
16-
* the definition is stored as JSON.
16+
* the definition is stored as JSON,
17+
* has support for [React](./react/).
1718

1819
🤩 Don't miss [the pro version](https://github.com/nocode-js/sequential-workflow-designer-pro-demo).
1920

@@ -73,10 +74,10 @@ Add the below code to your head section in HTML document.
7374
```html
7475
<head>
7576
...
76-
<link href="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.5.1/css/designer.css" rel="stylesheet">
77-
<link href="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.5.1/css/designer-light.css" rel="stylesheet">
78-
<link href="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.5.1/css/designer-dark.css" rel="stylesheet">
79-
<script src="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.5.1/dist/index.umd.js"></script>
77+
<link href="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.5.2/css/designer.css" rel="stylesheet">
78+
<link href="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.5.2/css/designer-light.css" rel="stylesheet">
79+
<link href="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.5.2/css/designer-dark.css" rel="stylesheet">
80+
<script src="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.5.2/dist/index.umd.js"></script>
8081
```
8182

8283
Call the designer by:

demos/react-app/.gitignore

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/node_modules
2+
/.pnp
3+
.pnp.js
4+
5+
/coverage
6+
7+
/build
8+
9+
.DS_Store
10+
.env.local
11+
.env.development.local
12+
.env.test.local
13+
.env.production.local
14+
15+
npm-debug.log*
16+
yarn-debug.log*
17+
yarn-error.log*

demos/react-app/README.md

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Demo of Sequential Workflow Designer for React
2+
3+
This project contains a simple demo of using the `sequential-workflow-designer-react` package.
4+
5+
## 🚀 How to Run?
6+
7+
1. Clone this repository.
8+
2. Install dependencies: `yarn install`
9+
3. Run the project: `yarn start`

demos/react-app/package.json

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
{
2+
"name": "sequential-workflow-designer-react-app-demo",
3+
"version": "1.0.0",
4+
"private": true,
5+
"dependencies": {
6+
"react": "^18.2.0",
7+
"react-dom": "^18.2.0",
8+
"react-scripts": "5.0.1",
9+
"sequential-workflow-designer": "^0.5.2",
10+
"sequential-workflow-designer-react": "^0.5.2"
11+
},
12+
"devDependencies": {
13+
"@types/jest": "^29.2.5",
14+
"@types/node": "^16.18.11",
15+
"@types/react": "^18.0.26",
16+
"@types/react-dom": "^18.0.10",
17+
"@typescript-eslint/eslint-plugin": "^5.47.0",
18+
"@typescript-eslint/parser": "^5.47.0",
19+
"eslint": "^8.30.0",
20+
"prettier": "^2.8.2",
21+
"typescript": "^4.9.4"
22+
},
23+
"scripts": {
24+
"start": "react-scripts start",
25+
"build": "react-scripts build",
26+
"test": "react-scripts test",
27+
"test:single": "react-scripts test --watchAll=false",
28+
"eject": "react-scripts eject",
29+
"prettier": "prettier --check ./src",
30+
"prettier:fix": "prettier --write ./src",
31+
"eslint": "eslint ./src --ext .ts"
32+
},
33+
"eslintConfig": {
34+
"extends": [
35+
"react-app"
36+
]
37+
},
38+
"browserslist": {
39+
"production": [
40+
">0.2%",
41+
"not dead",
42+
"not op_mini all"
43+
],
44+
"development": [
45+
"last 1 chrome version",
46+
"last 1 firefox version",
47+
"last 1 safari version"
48+
]
49+
}
50+
}

demos/react-app/public/index.html

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1" />
6+
<title>🌸 Sequential Workflow Designer for React Demo</title>
7+
</head>
8+
<body>
9+
<noscript>You need to enable JavaScript to run this app.</noscript>
10+
<div id="root"></div>
11+
</body>
12+
</html>

demos/react-app/src/App.tsx

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import { useEffect, useState } from 'react';
2+
import { Definition, ObjectCloner, Step, StepsConfiguration, ToolboxConfiguration } from 'sequential-workflow-designer';
3+
import { SequentialWorkflowDesigner, wrapDefinition } from 'sequential-workflow-designer-react';
4+
import { GlobalEditor } from './GlobalEditor';
5+
import { StepEditor } from './StepEditor';
6+
import { createSwitchStep, createTaskStep } from './StepUtils';
7+
8+
const startDefinition: Definition = {
9+
properties: {},
10+
sequence: [createTaskStep(), createSwitchStep()]
11+
};
12+
13+
const toolboxConfiguration: ToolboxConfiguration = {
14+
groups: [{ name: 'Steps', steps: [createTaskStep(), createSwitchStep()] }]
15+
};
16+
17+
const stepsConfiguration: StepsConfiguration = {
18+
validator: (step: Step) => !!step.name
19+
};
20+
21+
export function App() {
22+
const [isVisible, setIsVisible] = useState(true);
23+
const [definition, setDefinition] = useState(() => wrapDefinition(startDefinition));
24+
const [selectedStepId, setSelectedStepId] = useState<string | null>(null);
25+
const [isReadonly, setIsReadonly] = useState(false);
26+
const definitionJson = JSON.stringify(definition.value, null, 2);
27+
28+
useEffect(() => {
29+
console.log(`definition updated, isValid=${definition.isValid}`);
30+
}, [definition]);
31+
32+
function toggleVisibilityClicked() {
33+
setIsVisible(!isVisible);
34+
}
35+
36+
function toggleSelectionClicked() {
37+
const id = definition.value.sequence[0].id;
38+
setSelectedStepId(selectedStepId ? null : id);
39+
}
40+
41+
function toggleIsReadonlyClicked() {
42+
setIsReadonly(!isReadonly);
43+
}
44+
45+
function reloadDefinitionClicked() {
46+
const newDefinition = ObjectCloner.deepClone(startDefinition);
47+
setDefinition(wrapDefinition(newDefinition));
48+
}
49+
50+
return (
51+
<>
52+
{isVisible && (
53+
<SequentialWorkflowDesigner
54+
undoStackSize={10}
55+
definition={definition}
56+
onDefinitionChange={setDefinition}
57+
selectedStepId={selectedStepId}
58+
isReadonly={isReadonly}
59+
onSelectedStepIdChanged={setSelectedStepId}
60+
toolboxConfiguration={toolboxConfiguration}
61+
stepsConfiguration={stepsConfiguration}
62+
globalEditor={<GlobalEditor />}
63+
stepEditor={<StepEditor />}
64+
/>
65+
)}
66+
67+
<ul>
68+
<li>Definition: {definitionJson.length} bytes</li>
69+
<li>Selected step: {selectedStepId}</li>
70+
<li>Is readonly: {isReadonly ? '✅ Yes' : 'No'}</li>
71+
<li>Is valid: {definition.isValid === undefined ? '?' : definition.isValid ? '✅ Yes' : '⛔ No'}</li>
72+
</ul>
73+
74+
<div>
75+
<button onClick={toggleVisibilityClicked}>Toggle visibility</button>
76+
<button onClick={reloadDefinitionClicked}>Reload definition</button>
77+
<button onClick={toggleSelectionClicked}>Toggle selection</button>
78+
<button onClick={toggleIsReadonlyClicked}>Toggle readonly</button>
79+
</div>
80+
81+
<div>
82+
<textarea value={definitionJson} readOnly={true} cols={100} rows={15} />
83+
</div>
84+
</>
85+
);
86+
}

demos/react-app/src/GlobalEditor.tsx

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { ChangeEvent } from 'react';
2+
import { useGlobalEditor } from 'sequential-workflow-designer-react';
3+
4+
export function GlobalEditor() {
5+
const { properties, setProperty } = useGlobalEditor();
6+
7+
function onAlfaChanged(e: ChangeEvent) {
8+
setProperty('alfa', (e.target as HTMLInputElement).value);
9+
}
10+
11+
return (
12+
<>
13+
<h2>Global editor</h2>
14+
15+
<h4>Alfa</h4>
16+
17+
<input type="text" value={(properties['alfa'] as string) || ''} onChange={onAlfaChanged} />
18+
</>
19+
);
20+
}

demos/react-app/src/StepEditor.tsx

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { ChangeEvent } from 'react';
2+
import { SwitchStep } from 'sequential-workflow-designer';
3+
import { useStepEditor } from 'sequential-workflow-designer-react';
4+
5+
export function StepEditor() {
6+
const { type, name, step, properties, setName, setProperty, notifyPropertiesChanged, notifyChildrenChanged } = useStepEditor();
7+
8+
function onNameChanged(e: ChangeEvent) {
9+
setName((e.target as HTMLInputElement).value);
10+
}
11+
12+
function onXChanged(e: ChangeEvent) {
13+
setProperty('x', (e.target as HTMLInputElement).value);
14+
}
15+
16+
function onYChanged(e: ChangeEvent) {
17+
properties['y'] = (e.target as HTMLInputElement).value;
18+
notifyPropertiesChanged();
19+
}
20+
21+
function toggleExtraBranch() {
22+
const switchStep = step as SwitchStep;
23+
if (switchStep.branches['extra']) {
24+
delete switchStep.branches['extra'];
25+
} else {
26+
switchStep.branches['extra'] = [];
27+
}
28+
notifyChildrenChanged();
29+
}
30+
31+
return (
32+
<>
33+
<h2>Step Editor {type}</h2>
34+
35+
<h4>Name</h4>
36+
<input type="text" value={name} onChange={onNameChanged} />
37+
38+
<h4>X Variable</h4>
39+
<input type="text" value={(properties['x'] as string) || ''} onChange={onXChanged} />
40+
41+
<h4>Y Variable</h4>
42+
<input type="text" value={(properties['y'] as string) || ''} onChange={onYChanged} />
43+
44+
{type === 'switch' && (
45+
<>
46+
<h4>Extra branch</h4>
47+
<button onClick={toggleExtraBranch}>Toggle branch</button>
48+
</>
49+
)}
50+
</>
51+
);
52+
}

demos/react-app/src/StepUtils.spec.ts

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { createSwitchStep, createTaskStep } from './StepUtils';
2+
3+
describe('StepUtils', () => {
4+
it('createTaskStep() returns different ids', () => {
5+
const a = createTaskStep();
6+
const b = createTaskStep();
7+
8+
expect(a.id).not.toBe(b.id);
9+
});
10+
11+
it('createSwitchStep() returns different ids', () => {
12+
const a = createSwitchStep();
13+
const b = createSwitchStep();
14+
15+
expect(a.id).not.toBe(b.id);
16+
});
17+
});

demos/react-app/src/StepUtils.ts

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { SwitchStep, TaskStep, Uid } from 'sequential-workflow-designer';
2+
3+
export function createTaskStep(): TaskStep {
4+
return {
5+
id: Uid.next(),
6+
componentType: 'task',
7+
type: 'task',
8+
name: 'test',
9+
properties: {}
10+
};
11+
}
12+
13+
export function createSwitchStep(): SwitchStep {
14+
return {
15+
id: Uid.next(),
16+
componentType: 'switch',
17+
type: 'switch',
18+
name: 'switch',
19+
properties: {},
20+
branches: {
21+
true: [],
22+
false: []
23+
}
24+
};
25+
}

demos/react-app/src/index.css

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
body {
2+
font: 13px/1.3em Arial, Verdana, Serif;
3+
}
4+
body {
5+
margin: 0;
6+
padding: 0;
7+
}
8+
9+
.sqd-designer-react {
10+
width: 100vw;
11+
height: 50vh;
12+
}

demos/react-app/src/index.tsx

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import React from 'react';
2+
import ReactDOM from 'react-dom/client';
3+
import { App } from './App';
4+
5+
import './index.css';
6+
7+
import 'sequential-workflow-designer/css/designer.css';
8+
import 'sequential-workflow-designer/css/designer-light.css';
9+
import 'sequential-workflow-designer/css/designer-dark.css';
10+
11+
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
12+
root.render(
13+
<React.StrictMode>
14+
<App />
15+
</React.StrictMode>
16+
);
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/// <reference types="react-scripts" />

demos/react-app/src/setupTests.ts

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import '@testing-library/jest-dom';
2+
import crypto from 'crypto';
3+
4+
Object.defineProperty(globalThis, 'crypto', {
5+
value: {
6+
getRandomValues: (buffer: Uint8Array) => crypto.randomFillSync(buffer)
7+
}
8+
});

0 commit comments

Comments
 (0)