Skip to content

Commit 97dfacb

Browse files
authored
multi-conditional switch example. (#72)
1 parent 233073a commit 97dfacb

File tree

3 files changed

+342
-0
lines changed

3 files changed

+342
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ Features:
3333
* [🚄 Stress Test](https://nocode-js.github.io/sequential-workflow-designer/examples/stress-test.html)
3434
* [🚪 Editing Restrictions](https://nocode-js.github.io/sequential-workflow-designer/examples/editing-restrictions.html)
3535
* [📜 Scrollable Page](https://nocode-js.github.io/sequential-workflow-designer/examples/scrollable-page.html)
36+
* [🌵 Multi-Conditional Switch](https://nocode-js.github.io/sequential-workflow-designer/examples/multi-conditional-switch.html)
3637
* [React Demo](https://nocode-js.github.io/sequential-workflow-designer/react-app/)
3738
* [Angular Demo](https://nocode-js.github.io/sequential-workflow-designer/angular-app/)
3839

Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
/* global window, document, sequentialWorkflowDesigner */
2+
3+
function randomCondition() {
4+
const a = Math.random() > 0.5 ? 'alfa' : 'beta';
5+
const b = Math.random() > 0.5 ? '>' : '<';
6+
const c = Math.round(Math.random() * 100);
7+
return `${a} ${b} ${c}`;
8+
}
9+
10+
function createWriteStep(value) {
11+
return {
12+
id: sequentialWorkflowDesigner.Uid.next(),
13+
componentType: 'task',
14+
type: 'write',
15+
name: `Write ${value}`,
16+
properties: {}
17+
};
18+
}
19+
20+
function createIfStep(name, trueSteps, falseSteps) {
21+
return {
22+
id: sequentialWorkflowDesigner.Uid.next(),
23+
componentType: 'switch',
24+
type: 'if',
25+
name,
26+
properties: {
27+
condition: randomCondition()
28+
},
29+
branches: {
30+
true: trueSteps || [],
31+
false: falseSteps || []
32+
}
33+
};
34+
}
35+
36+
function createParallelStep(name, children) {
37+
return {
38+
id: sequentialWorkflowDesigner.Uid.next(),
39+
componentType: 'switch',
40+
type: 'parallel',
41+
name,
42+
properties: {
43+
conditions: {
44+
'Condition A': randomCondition(),
45+
'Condition B': randomCondition(),
46+
'Condition C': randomCondition()
47+
}
48+
},
49+
branches: {
50+
'Condition A': children ? [children[0]] : [],
51+
'Condition B': children ? [children[1]] : [],
52+
'Condition C': children ? [children[2]] : []
53+
}
54+
};
55+
}
56+
57+
function createButton(text, clickHandler) {
58+
const button = document.createElement('button');
59+
button.innerText = text;
60+
button.addEventListener('click', clickHandler, false);
61+
return button;
62+
}
63+
64+
function appendTitle(root, title) {
65+
const h2 = document.createElement('h2');
66+
h2.innerText = title;
67+
root.appendChild(h2);
68+
}
69+
70+
function appendPropertyTitle(root, title) {
71+
const h3 = document.createElement('h3');
72+
h3.innerText = title;
73+
root.appendChild(h3);
74+
}
75+
76+
function appendNameEditor(root, step, editorContext) {
77+
const input = document.createElement('input');
78+
input.type = 'text';
79+
input.value = step.name;
80+
input.addEventListener(
81+
'input',
82+
() => {
83+
step.name = input.value;
84+
editorContext.notifyNameChanged();
85+
},
86+
false
87+
);
88+
89+
appendPropertyTitle(root, 'Name');
90+
root.appendChild(input);
91+
}
92+
93+
function appendConditionEditor(root, value, onChange) {
94+
const input = document.createElement('input');
95+
input.type = 'text';
96+
input.value = value;
97+
input.addEventListener(
98+
'input',
99+
() => {
100+
onChange(input.value);
101+
},
102+
false
103+
);
104+
root.appendChild(input);
105+
}
106+
107+
function ifStepEditorProvider(step, editorContext) {
108+
const root = document.createElement('div');
109+
appendTitle(root, 'If step');
110+
appendNameEditor(root, step, editorContext);
111+
appendPropertyTitle(root, 'Condition');
112+
appendConditionEditor(root, step.properties.condition, value => {
113+
step.properties.condition = value;
114+
editorContext.notifyPropertiesChanged();
115+
});
116+
return root;
117+
}
118+
119+
function parallelStepEditorProvider(step, editorContext) {
120+
function deleteBranch(branch, name) {
121+
root.removeChild(branch);
122+
delete step.branches[name];
123+
editorContext.notifyChildrenChanged();
124+
}
125+
126+
function appendBranch(name) {
127+
const branch = document.createElement('div');
128+
branch.className = 'switch-branch';
129+
130+
const title = document.createElement('h4');
131+
title.innerText = name;
132+
133+
const label = document.createElement('label');
134+
label.innerText = 'Condition: ';
135+
136+
branch.appendChild(title);
137+
branch.appendChild(label);
138+
139+
appendConditionEditor(branch, step.properties.conditions[name], value => {
140+
step.properties.conditions[name] = value;
141+
editorContext.notifyPropertiesChanged();
142+
});
143+
144+
const deleteButton = createButton('Delete branch', () => {
145+
if (Object.keys(step.branches).length <= 1) {
146+
window.alert('You cannot delete the last branch.');
147+
return;
148+
}
149+
if (!window.confirm('Are you sure?')) {
150+
return;
151+
}
152+
deleteBranch(branch, name);
153+
});
154+
branch.appendChild(deleteButton);
155+
root.appendChild(branch);
156+
}
157+
158+
function addBranch(name) {
159+
step.properties.conditions[name] = randomCondition();
160+
step.branches[name] = [];
161+
editorContext.notifyChildrenChanged();
162+
appendBranch(name);
163+
}
164+
165+
const root = document.createElement('div');
166+
appendTitle(root, 'Parallel step');
167+
appendNameEditor(root, step, editorContext);
168+
169+
const addBranchButton = createButton('Add branch', () => {
170+
const branchName = window.prompt('Enter branch name');
171+
if (branchName) {
172+
addBranch(branchName);
173+
}
174+
});
175+
176+
appendPropertyTitle(root, 'Branches');
177+
root.appendChild(addBranchButton);
178+
for (const initialBranchName of Object.keys(step.branches)) {
179+
appendBranch(initialBranchName);
180+
}
181+
return root;
182+
}
183+
184+
function writeStepEditorProvider(step, editorContext) {
185+
const root = document.createElement('div');
186+
appendTitle(root, `${step.type} step`);
187+
appendNameEditor(root, step, editorContext);
188+
return root;
189+
}
190+
191+
function globalEditorProvider() {
192+
const root = document.createElement('div');
193+
appendTitle(root, `Multi-Conditional Switch`);
194+
const description = document.createElement('p');
195+
description.innerText = 'This example demonstrates how to create a multi-conditional switch step.';
196+
root.appendChild(description);
197+
return root;
198+
}
199+
200+
function stepEditorProvider(step, editorContext) {
201+
switch (step.type) {
202+
case 'if':
203+
return ifStepEditorProvider(step, editorContext);
204+
case 'parallel':
205+
return parallelStepEditorProvider(step, editorContext);
206+
case 'write':
207+
return writeStepEditorProvider(step, editorContext);
208+
}
209+
throw new Error('Unknown step type');
210+
}
211+
212+
function load() {
213+
const definition = {
214+
sequence: [
215+
createIfStep('If', [createWriteStep('header')]),
216+
createParallelStep('Parallel', [createWriteStep('null'), createWriteStep('checksum'), createWriteStep('buffer')])
217+
],
218+
properties: {}
219+
};
220+
const configuration = {
221+
toolbox: {
222+
groups: [
223+
{
224+
name: 'Steps',
225+
steps: [createWriteStep('_'), createIfStep('If'), createParallelStep('Parallel')]
226+
}
227+
]
228+
},
229+
steps: {
230+
iconUrlProvider: componentType => {
231+
return componentType === 'switch' ? './assets/icon-if.svg' : './assets/icon-task.svg';
232+
}
233+
},
234+
editors: {
235+
globalEditorProvider,
236+
stepEditorProvider
237+
},
238+
controlBar: true
239+
};
240+
const placeholder = document.getElementById('designer');
241+
sequentialWorkflowDesigner.Designer.create(placeholder, definition, configuration);
242+
}
243+
244+
window.addEventListener('load', load, false);
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="UTF-8" />
5+
<title>🌵 Multi-Conditional Switch - Sequential Workflow Designer</title>
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
7+
<link rel="icon" href="./assets/favicon.ico" />
8+
9+
<link rel="stylesheet" href="./assets/common.css" />
10+
<style>
11+
html,
12+
body {
13+
width: 100vw;
14+
height: 100vh;
15+
overflow: hidden;
16+
}
17+
body {
18+
display: flex;
19+
flex-direction: column;
20+
}
21+
.main {
22+
flex: 1;
23+
position: relative;
24+
}
25+
#designer {
26+
position: absolute;
27+
width: 100%;
28+
height: 100%;
29+
}
30+
31+
.sqd-editor {
32+
padding: 10px;
33+
}
34+
.sqd-editor h2 {
35+
margin: 10px 0 20px;
36+
padding: 0;
37+
line-height: 1.1em;
38+
}
39+
.sqd-editor p {
40+
line-height: 1.3em;
41+
}
42+
.sqd-editor button {
43+
border: 0;
44+
padding: 5px 8px;
45+
background: #222;
46+
color: #fff;
47+
cursor: pointer;
48+
border-radius: 5px;
49+
}
50+
.sqd-editor button:hover {
51+
background: #444;
52+
}
53+
.sqd-editor input[type='text'] {
54+
width: 100%;
55+
margin: 0 0 5px;
56+
box-sizing: border-box;
57+
padding: 5px;
58+
border: 1px solid #ddd;
59+
border-radius: 5px;
60+
}
61+
.sqd-editor .switch-branch {
62+
padding: 10px;
63+
border: 1px solid #ddd;
64+
margin: 10px 0;
65+
border-radius: 5px;
66+
}
67+
.sqd-editor .switch-branch h4 {
68+
margin: 0;
69+
font-size: 14px;
70+
background: #ddd;
71+
padding: 5px;
72+
border-radius: 5px;
73+
}
74+
.sqd-editor .switch-branch label {
75+
display: block;
76+
padding: 5px 0;
77+
}
78+
</style>
79+
</head>
80+
<body>
81+
<header class="title-bar">
82+
<div class="column">
83+
<h1>🌵 Multi-Conditional Switch Example</h1>
84+
</div>
85+
<div class="column text-end flex-1">
86+
<a href="https://github.com/nocode-js/sequential-workflow-designer" target="_blank">GitHub</a>
87+
</div>
88+
</header>
89+
90+
<div class="main">
91+
<div id="designer"></div>
92+
</div>
93+
94+
<script src="./assets/lib.js"></script>
95+
<script src="./assets/multi-conditional-switch.js"></script>
96+
</body>
97+
</html>

0 commit comments

Comments
 (0)