Skip to content

Commit 44dc0f9

Browse files
authored
0.12.0. (#33)
1 parent 833d439 commit 44dc0f9

File tree

54 files changed

+677
-116
lines changed

Some content is hidden

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

54 files changed

+677
-116
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.12.0
2+
3+
This version introduces the localization feature. Now you can localize the editor to any language you want.
4+
15
## 0.11.3
26

37
This version improves the behavior of the `Dynamic` value editor, when the sub editor contains a control visible in the property header.

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Powerful workflow editor builder for sequential workflows. Written in TypeScript
1515
* [🛠 Playground](https://nocode-js.github.io/sequential-workflow-editor/webpack-app/public/playground.html)
1616
* [📖 Editors](https://nocode-js.github.io/sequential-workflow-editor/webpack-app/public/editors.html)
1717
* [🎯 Placement Restrictions](https://nocode-js.github.io/sequential-workflow-editor/webpack-app/public/placement-restrictions.html)
18+
* [🚩 Internationalization](https://nocode-js.github.io/sequential-workflow-editor/webpack-app/public/i18n.html)
1819
* [🚢 Vanilla JS](https://nocode-js.github.io/sequential-workflow-editor/vanilla-js-app/vanilla-js.html)
1920

2021
Pro:

demos/vanilla-js-app/vanilla-js.html

+3-3
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@
2323
}
2424
</style>
2525

26-
<link href="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.19.1/css/designer.css" rel="stylesheet" />
27-
<link href="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.19.1/css/designer-light.css" rel="stylesheet" />
28-
<script src="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.19.1/dist/index.umd.js"></script>
26+
<link href="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.21.1/css/designer.css" rel="stylesheet" />
27+
<link href="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.21.1/css/designer-light.css" rel="stylesheet" />
28+
<script src="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.21.1/dist/index.umd.js"></script>
2929

3030
<script src="./assets/lib.js"></script>
3131
<script src="./assets/vanilla-js.js"></script>

demos/webpack-app/package.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@
1616
"dependencies": {
1717
"xstate": "^4.38.2",
1818
"sequential-workflow-model": "^0.2.0",
19-
"sequential-workflow-designer": "^0.17.0",
19+
"sequential-workflow-designer": "^0.21.1",
2020
"sequential-workflow-machine": "^0.4.0",
21-
"sequential-workflow-editor-model": "^0.11.3",
22-
"sequential-workflow-editor": "^0.11.3"
21+
"sequential-workflow-editor-model": "^0.12.0",
22+
"sequential-workflow-editor": "^0.12.0"
2323
},
2424
"devDependencies": {
2525
"ts-loader": "^9.4.2",
+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
html,
2+
body {
3+
margin: 0;
4+
padding: 0;
5+
width: 100vw;
6+
height: 100vh;
7+
overflow: hidden;
8+
}
9+
body {
10+
display: flex;
11+
flex-direction: column;
12+
}
13+
body,
14+
input,
15+
h1,
16+
textarea {
17+
font: 14px/1.3em Arial, Verdana, sans-serif;
18+
}
19+
.header {
20+
width: 100%;
21+
display: flex;
22+
align-items: center;
23+
background: #203fd2;
24+
color: #fff;
25+
}
26+
.header h1 {
27+
margin: 0;
28+
padding: 0;
29+
}
30+
.header a {
31+
color: #fff;
32+
}
33+
.header .column {
34+
padding: 10px;
35+
}
36+
.header .column.flex-1 {
37+
flex: 1;
38+
}
39+
.header .text-center {
40+
text-align: center;
41+
}
42+
.header .column.text-end {
43+
text-align: right;
44+
}
45+
@media only screen and (max-width: 700px) {
46+
.header .column.hidden-mobile {
47+
display: none;
48+
}
49+
}
50+
a {
51+
color: #000;
52+
text-decoration: underline;
53+
}
54+
a:hover {
55+
text-decoration: none;
56+
}
57+
#designer {
58+
flex: 1;
59+
}

demos/webpack-app/public/i18n.html

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<title>🚩 I18n Example - Sequential Workflow Editor</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+
<script src="./builds/i18n.js" defer></script>
9+
<link rel="stylesheet" href="./assets/i18n.css" />
10+
</head>
11+
<body>
12+
<header class="header">
13+
<div class="column flex-1 hidden-mobile">
14+
<h1>🚩 I18n Example</h1>
15+
</div>
16+
<div class="column">
17+
Language:
18+
<select id="lang">
19+
<option value="pl">🇵🇱 Polish</option>
20+
<option value="en">🇬🇧 English</option>
21+
</select>
22+
</div>
23+
<div class="column flex-1 text-end">
24+
<a href="https://github.com/nocode-js/sequential-workflow-editor" target="_blank">GitHub</a>
25+
</div>
26+
</header>
27+
<div id="designer"></div>
28+
</body>
29+
</html>

demos/webpack-app/src/i18n/app.ts

+156
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
import { EditorProvider } from 'sequential-workflow-editor';
2+
import { ChownStep, I18nDefinition, definitionModel } from './definition-model';
3+
import { Designer, Uid } from 'sequential-workflow-designer';
4+
import { defaultI18n } from 'sequential-workflow-editor-model';
5+
6+
import 'sequential-workflow-designer/css/designer.css';
7+
import 'sequential-workflow-designer/css/designer-light.css';
8+
import 'sequential-workflow-editor/css/editor.css';
9+
10+
const designerDict: Record<string, Record<string, string>> = {
11+
pl: {
12+
'controlBar.resetView': 'Resetuj widok',
13+
'controlBar.zoomIn': 'Przybliż',
14+
'controlBar.zoomOut': 'Oddal',
15+
'controlBar.turnOnOffDragAndDrop': 'Włącz/wyłącz przeciąganie i upuszczanie',
16+
'controlBar.deleteSelectedStep': 'Usuń wybrany krok',
17+
'controlBar.undo': 'Cofnij',
18+
'controlBar.redo': 'Dalej',
19+
'smartEditor.toggle': 'Zwiń/rozwiń',
20+
'toolbox.title': 'Przybornik',
21+
'toolbox.search': 'Szukaj',
22+
'contextMenu.select': 'Zaznacz',
23+
'contextMenu.unselect': 'Odznacz',
24+
'contextMenu.delete': 'Usuń',
25+
'contextMenu.resetView': 'Resetuj widok',
26+
'contextMenu.duplicate': 'Duplikuj',
27+
28+
// steps
29+
'toolbox.item.chown.label': 'Uprawnienia'
30+
}
31+
};
32+
33+
const editorDict: Record<string, Record<string, string>> = {
34+
pl: {
35+
'toolbox.defaultGroupName': 'Inne',
36+
'stringDictionary.noItems': 'Brak elementów',
37+
'stringDictionary.addItem': 'Dodaj element',
38+
'stringDictionary.key': 'Klucz',
39+
'stringDictionary.value': 'Wartość',
40+
'stringDictionary.delete': 'Usuń',
41+
'stringDictionary.valueTooShort': 'Wartość musi mieć conajmniej :min znaków',
42+
'stringDictionary.duplicatedKey': 'Klucz jest zduplikowany',
43+
'stringDictionary.keyIsRequired': 'Klucz jest wymagany',
44+
45+
'number.valueMustBeNumber': 'Wartość musi być liczbą',
46+
'number.valueTooLow': 'Wartość musi być minimum :min.',
47+
'number.valueTooHigh': 'Wartość musi być maximum :max.',
48+
49+
'boolean.false': 'Fałsz',
50+
'boolean.true': 'Prawda',
51+
52+
'string.valueTooShort': 'Wartość musi mieć minimum :min znaków.',
53+
'string.valueDoesNotMatchPattern': 'Wartość nie pasuje do oczekiwanego wzorca.',
54+
55+
'dynamic.string.label': 'Tekst',
56+
'dynamic.number.label': 'Liczba',
57+
58+
// root
59+
'root.property:properties/timeout': 'Przekroczenie czasu',
60+
'root.property:properties/debug': 'Tryb debug',
61+
62+
// steps
63+
'step.chown.name': 'Uprawnienia',
64+
'step.chown.property:name': 'Nazwa',
65+
'step.chown.property:properties/stringOrNumber': 'Tekst lub liczba',
66+
'step.chown.property:properties/users': 'Użytkownik'
67+
}
68+
};
69+
70+
export class App {
71+
public static create() {
72+
const placeholder = document.getElementById('designer') as HTMLElement;
73+
const langInput = document.getElementById('lang') as HTMLInputElement;
74+
const app = new App(placeholder, langInput.value);
75+
app.reload();
76+
langInput.addEventListener('change', () => {
77+
app.setLang(langInput.value);
78+
app.reload();
79+
});
80+
return app;
81+
}
82+
83+
private designer: Designer<I18nDefinition> | null = null;
84+
private definition: I18nDefinition | null = null;
85+
86+
public constructor(private readonly placeholder: HTMLElement, private lang: string) {}
87+
88+
private readonly designerI18n = (key: string, defaultValue: string) => {
89+
const dict = designerDict[this.lang];
90+
if (dict) {
91+
const translation = dict[key];
92+
if (translation) {
93+
return translation;
94+
}
95+
}
96+
console.log(`<designer>`, key, defaultValue);
97+
return defaultValue;
98+
};
99+
100+
private readonly editorI18n = (key: string, defaultValue: string, replacements?: { [key: string]: string }) => {
101+
const dict = editorDict[this.lang];
102+
if (dict) {
103+
const translation = dict[key];
104+
if (translation) {
105+
defaultValue = translation;
106+
} else {
107+
console.log(`<editor>`, key, defaultValue);
108+
}
109+
}
110+
return defaultI18n(key, defaultValue, replacements);
111+
};
112+
113+
public setLang(lang: string) {
114+
this.lang = lang;
115+
}
116+
117+
public reload() {
118+
if (this.designer) {
119+
this.designer.destroy();
120+
}
121+
122+
const editorProvider = EditorProvider.create(definitionModel, {
123+
uidGenerator: Uid.next,
124+
i18n: this.editorI18n
125+
});
126+
127+
if (!this.definition) {
128+
this.definition = editorProvider.activateDefinition();
129+
const step = editorProvider.activateStep('chown') as ChownStep;
130+
this.definition.sequence.push(step);
131+
}
132+
133+
this.designer = Designer.create(this.placeholder, this.definition, {
134+
controlBar: true,
135+
editors: {
136+
rootEditorProvider: editorProvider.createRootEditorProvider(),
137+
stepEditorProvider: editorProvider.createStepEditorProvider()
138+
},
139+
validator: {
140+
step: editorProvider.createStepValidator(),
141+
root: editorProvider.createRootValidator()
142+
},
143+
steps: {
144+
iconUrlProvider: () => './assets/icon-task.svg'
145+
},
146+
toolbox: {
147+
groups: editorProvider.getToolboxGroups(),
148+
labelProvider: editorProvider.createStepLabelProvider()
149+
},
150+
i18n: this.designerI18n
151+
});
152+
this.designer.onDefinitionChanged.subscribe(d => (this.definition = d));
153+
}
154+
}
155+
156+
document.addEventListener('DOMContentLoaded', App.create, false);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import {
2+
Dynamic,
3+
StringDictionary,
4+
createBooleanValueModel,
5+
createDefinitionModel,
6+
createDynamicValueModel,
7+
createNumberValueModel,
8+
createStepModel,
9+
createStringDictionaryValueModel,
10+
createStringValueModel
11+
} from 'sequential-workflow-editor-model';
12+
import { Definition, Step } from 'sequential-workflow-model';
13+
14+
export interface I18nDefinition extends Definition {
15+
properties: {
16+
timeout: number;
17+
debug: boolean;
18+
};
19+
}
20+
21+
export interface ChownStep extends Step {
22+
type: 'chown';
23+
componentType: 'task';
24+
properties: {
25+
stringOrNumber: Dynamic<string | number>;
26+
users: StringDictionary;
27+
};
28+
}
29+
30+
export const definitionModel = createDefinitionModel<I18nDefinition>(model => {
31+
model.root(root => {
32+
root.property('timeout').value(
33+
createNumberValueModel({
34+
min: 100,
35+
max: 200,
36+
defaultValue: 150
37+
})
38+
);
39+
root.property('debug').value(
40+
createBooleanValueModel({
41+
defaultValue: false
42+
})
43+
);
44+
});
45+
model.steps([
46+
createStepModel<ChownStep>('chown', 'task', step => {
47+
step.property('stringOrNumber').value(
48+
createDynamicValueModel({
49+
models: [
50+
createStringValueModel({
51+
pattern: /^[a-zA-Z0-9]+$/
52+
}),
53+
createNumberValueModel({
54+
min: 1,
55+
max: 100,
56+
defaultValue: 50
57+
})
58+
]
59+
})
60+
);
61+
step.property('users').value(
62+
createStringDictionaryValueModel({
63+
valueMinLength: 1,
64+
uniqueKeys: true
65+
})
66+
);
67+
})
68+
]);
69+
});

demos/webpack-app/webpack.config.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ function bundle(name) {
2828
}
2929

3030
module.exports = [
31-
bundle('playground'),
3231
bundle('editors'),
33-
bundle('placement-restrictions')
32+
bundle('i18n'),
33+
bundle('placement-restrictions'),
34+
bundle('playground'),
3435
];

0 commit comments

Comments
 (0)