Skip to content

Commit 27207af

Browse files
committed
WiP: input autocompletion
1 parent 631c5ec commit 27207af

32 files changed

+918
-486
lines changed

demo/App.jsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import {
99
deploy,
1010
startInstance,
1111
getInstance,
12-
saveFile
1312
} from '../test/mock';
1413

1514
import diagram from './diagram.xml';
@@ -22,6 +21,8 @@ function App() {
2221
const [ modeler, setModeler ] = useState(null);
2322
const [ tab, setTab ] = useState('test');
2423

24+
const [ config, setConfig ] = useState();
25+
2526
useEffect(() => {
2627
if (modelerRef.current) {
2728
setModeler(new BpmnModeler({
@@ -48,10 +49,11 @@ function App() {
4849

4950
const props = {
5051
injector,
51-
saveFile,
5252
deploy,
5353
startInstance,
54-
getInstance
54+
getInstance,
55+
config,
56+
saveConfig: setConfig,
5557
};
5658

5759
return (

demo/diagram.xml

Lines changed: 68 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,94 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:zeebe="http://camunda.org/schema/zeebe/1.0" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_1rrr52f" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.35.0" modeler:executionPlatform="Camunda Cloud" modeler:executionPlatformVersion="8.8.0">
2+
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:zeebe="http://camunda.org/schema/zeebe/1.0" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_1rrr52f" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.37.0" modeler:executionPlatform="Camunda Cloud" modeler:executionPlatformVersion="8.8.0">
33
<bpmn:process id="Process_1kuphyf" isExecutable="true">
4-
<bpmn:startEvent id="StartEvent_1">
5-
<bpmn:outgoing>Flow_1xr5ql2</bpmn:outgoing>
6-
</bpmn:startEvent>
7-
<bpmn:task id="Task_1" name="Task_1">
4+
<bpmn:scriptTask id="Task_Script" name="Create UID">
85
<bpmn:extensionElements>
96
<zeebe:properties>
10-
<zeebe:property name="camundaModeler:exampleOutputJson" value="{&#10; &#34;response&#34;: { &#10; &#34;body&#34;: {&#10; &#34;var_1&#34;: 123,&#10; &#34;var_2&#34;: true&#10; } &#10; }&#10;}" />
7+
<zeebe:property name="camundaModeler:exampleOutputJson" value="{&#10; &#34;uid&#34;: &#34;123_John&#34;&#10;}" />
118
</zeebe:properties>
9+
<zeebe:script expression="=uid = string(id) + &#34;_&#34; + name" resultVariable="script_result" />
10+
<zeebe:ioMapping>
11+
<zeebe:input source="=user_id" target="id" />
12+
<zeebe:input source="=user_name" target="name" />
13+
<zeebe:input source="=2" target="priority" />
14+
<zeebe:output source="=uid" target="uid" />
15+
</zeebe:ioMapping>
1216
</bpmn:extensionElements>
13-
<bpmn:incoming>Flow_1xr5ql2</bpmn:incoming>
14-
<bpmn:outgoing>Flow_1c72h11</bpmn:outgoing>
15-
</bpmn:task>
16-
<bpmn:sequenceFlow id="Flow_1xr5ql2" sourceRef="StartEvent_1" targetRef="Task_1" />
17-
<bpmn:task id="Task_2" name="Task_2">
17+
<bpmn:incoming>Flow_1c72h11</bpmn:incoming>
18+
<bpmn:outgoing>Flow_05wf0jz</bpmn:outgoing>
19+
</bpmn:scriptTask>
20+
<bpmn:sequenceFlow id="Flow_05wf0jz" sourceRef="Task_Script" targetRef="Task_Sql" />
21+
<bpmn:sequenceFlow id="Flow_1c72h11" sourceRef="Task_Api" targetRef="Task_Script" />
22+
<bpmn:sequenceFlow id="Flow_1xr5ql2" sourceRef="StartEvent_1" targetRef="Task_Api" />
23+
<bpmn:serviceTask id="Task_Api" name="Get user from API">
1824
<bpmn:extensionElements>
1925
<zeebe:properties>
20-
<zeebe:property name="camundaModeler:exampleOutputJson" value="{&#10; &#34;response&#34;: { &#10; &#34;body&#34;: {&#10; &#34;var_3&#34;: 356,&#10; &#34;var_4&#34;: &#34;foo&#34;&#10; } &#10; }&#10;}" />
26+
<zeebe:property name="camundaModeler:exampleOutputJson" value="{&#10; &#34;response&#34;: { &#10; &#34;body&#34;: {&#10; &#34;id&#34;: 123,&#10; &#34;name&#34;: &#34;Joe&#34;&#10; } &#10; }&#10;}" />
2127
</zeebe:properties>
28+
<zeebe:ioMapping>
29+
<zeebe:input source="=secret_key" target="api_key" />
30+
<zeebe:input source="=&#34;http://users.com/get&#34;" target="url" />
31+
<zeebe:output source="=response.body.id" target="user_id" />
32+
<zeebe:output source="=response.body.name" target="user_name" />
33+
</zeebe:ioMapping>
34+
<zeebe:taskDefinition type="get-users" retries="" />
2235
</bpmn:extensionElements>
23-
<bpmn:incoming>Flow_1c72h11</bpmn:incoming>
24-
</bpmn:task>
25-
<bpmn:sequenceFlow id="Flow_1c72h11" sourceRef="Task_1" targetRef="Task_2" />
36+
<bpmn:incoming>Flow_1xr5ql2</bpmn:incoming>
37+
<bpmn:outgoing>Flow_1c72h11</bpmn:outgoing>
38+
</bpmn:serviceTask>
39+
<bpmn:serviceTask id="Task_Sql" name="Save to database" zeebe:modelerTemplate="io.camunda.connectors.Jdbc.v1" zeebe:modelerTemplateVersion="2" zeebe:modelerTemplateIcon="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1MTMiIGhlaWdodD0iNTEyIiBmaWxsPSJub25lIiB2aWV3Qm94PSIwIDAgNTEzIDUxMiI+CiAgPGcgY2xpcC1wYXRoPSJ1cmwoI2EpIj4KICAgIDxwYXRoIGZpbGw9IiMwMDAiIGQ9Ik00MjIuMDY5IDQxNi45OTVWMjUzLjA0NGgtMjQuNzU2VjQ0NC4zMmg5OS4wMjR2LTI3LjMyNWgtNzQuMjY4Wm0tNzQuMjY4LTE2My45NTFoLTQ5LjUxMmMtNi41NjUgMC0xMi44NjIgMi44NzktMTcuNTA1IDguMDA0LTQuNjQzIDUuMTI0LTcuMjUxIDEyLjA3NC03LjI1MSAxOS4zMjJ2MTM2LjYyNWMwIDcuMjQ3IDIuNjA4IDE0LjE5NyA3LjI1MSAxOS4zMjEgNC42NDMgNS4xMjUgMTAuOTQgOC4wMDQgMTcuNTA1IDguMDA0aDEyLjM3OHYyNy4zMjVjMCA3LjI0NyAyLjYwOCAxNC4xOTcgNy4yNTEgMTkuMzIxIDQuNjQzIDUuMTI1IDEwLjk0IDguMDA0IDE3LjUwNSA4LjAwNGgyNC43NTZ2LTI3LjMyNWgtMjQuNzU2VjQ0NC4zMmgxMi4zNzhjNi41NjYgMCAxMi44NjMtMi44NzkgMTcuNTA1LTguMDA0IDQuNjQzLTUuMTI0IDcuMjUxLTEyLjA3NCA3LjI1MS0xOS4zMjFWMjgwLjM3YzAtNy4yNDgtMi42MDgtMTQuMTk4LTcuMjUxLTE5LjMyMi00LjY0Mi01LjEyNS0xMC45MzktOC4wMDQtMTcuNTA1LTguMDA0Wm0tNDkuNTEyIDE2My45NTFWMjgwLjM3aDQ5LjUxMnYxMzYuNjI1aC00OS41MTJabS03NC4yNjggMjcuMzI1aC03NC4yNjh2LTI3LjMyNWg3NC4yNjh2LTU0LjY1aC00OS41MTJjLTYuNTY2IDAtMTIuODYyLTIuODc5LTE3LjUwNS04LjAwNC00LjY0My01LjEyNC03LjI1MS0xMi4wNzQtNy4yNTEtMTkuMzIxdi01NC42NWMwLTcuMjQ4IDIuNjA4LTE0LjE5OCA3LjI1MS0xOS4zMjIgNC42NDMtNS4xMjUgMTAuOTM5LTguMDA0IDE3LjUwNS04LjAwNGg3NC4yNjh2MjcuMzI2aC03NC4yNjh2NTQuNjVoNDkuNTEyYzYuNTY2IDAgMTIuODYzIDIuODc4IDE3LjUwNSA4LjAwMyA0LjY0MyA1LjEyNCA3LjI1MSAxMi4wNzUgNy4yNTEgMTkuMzIydjU0LjY1YzAgNy4yNDctMi42MDggMTQuMTk3LTcuMjUxIDE5LjMyMS00LjY0MiA1LjEyNS0xMC45MzkgOC4wMDQtMTcuNTA1IDguMDA0WiIvPgogICAgPHBhdGggZmlsbD0iI0M2MjlDRCIgZD0iTTE2MC42OTUgMTMuMDMyYy02My4wNjYgMC0xMzAuOTQzIDE2LjQ1LTEzMC45NDMgNTIuNTU3djIzNi41MDZjMCAyMi4wNyAyNS40MDMgMzYuNzYyIDU5LjUyIDQ0Ljg3di0yNi44ODJjLTIzLjczNi02LjIxLTM1LjA2LTE1LjAxOS0zNS43MTItMTcuOTg4di00Ni45MzhjMTcuNzggOS44NDIgMTcuNzMzIDkuMTg1IDQ1LjQyNCAxMi4wMDl2LTI2LjI0N2MtNDYuMTYyLTQuOTU5LTQzLjk2NS0xMS44OTktNDUuNDI0LTE3LjY2MXYtNDYuOTM3YzI1LjMzIDE0LjAyNSA2Ny4xNjkgMjAuNjU5IDEwNy4xMzUgMjAuNjU5IDYzLjA2NiAwIDEzMC45NDMtMTYuNDUxIDEzMC45NDMtNTIuNTU3di03OC44NGMtLjAwOS0zNi4xMDctNjcuODgxLTUyLjU1LTEzMC45NDMtNTIuNTVaTTUzLjU0MiA2NS43ODdjMS44MTMtNy4yOTUgMzcuNTE0LTI2LjQ3NyAxMDcuMTUzLTI2LjQ3NyA2OS4wMTQgMCAxMDQuNjk0IDE4Ljg0MyAxMDcuMDk3IDI2LjI3OS0yLjQwMyA3LjQzNS0zOC4wODMgMjYuMjc4LTEwNy4wOTcgMjYuMjc4LTY5LjYzOSAwLTEwNS4zMzktMTkuMTgzLTEwNy4xNTMtMjYuMDhabTIxNC4yODggNzguNDdjLTEuOTEyIDcuMzItMzcuNjAxIDI2LjQ0Ni0xMDcuMTM1IDI2LjQ0Ni02OS42MzkgMC0xMDUuMzM5LTE5LjE4NC0xMDcuMTM1LTI2LjI3OVY5Ny40ODdjMjUuMzMgMTQuMDI1IDY3LjE2OSAyMC42NTkgMTA3LjEzNSAyMC42NTkgMzkuOTY2IDAgODEuODA1LTYuNjM0IDEwNy4xMzUtMjAuNjU5djQ2Ljc3WiIvPgogIDwvZz4KICA8ZGVmcz4KICAgIDxjbGlwUGF0aCBpZD0iYSI+CiAgICAgIDxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0yOS43NTQgNmg0NTIuOTkxdjUwMEgyOS43NTR6Ii8+CiAgICA8L2NsaXBQYXRoPgogIDwvZGVmcz4KPC9zdmc+Cg==">
40+
<bpmn:extensionElements>
41+
<zeebe:taskDefinition type="io.camunda:connector-jdbc:1" retries="3" />
42+
<zeebe:ioMapping>
43+
<zeebe:input source="MYSQL" target="database" />
44+
<zeebe:input source="uri" target="connection.authType" />
45+
<zeebe:input source="=secret_sql_uri" target="connection.uri" />
46+
<zeebe:input source="=false" target="data.returnResults" />
47+
<zeebe:input source="INSERT INTO users (uid, name, id) VALUES (:uid, :id, :name);" target="data.query" />
48+
<zeebe:input source="={&#10; id: user_id,&#10; name: user_name,&#10; uid: uid&#10;}" target="data.variables" />
49+
</zeebe:ioMapping>
50+
<zeebe:taskHeaders>
51+
<zeebe:header key="elementTemplateVersion" value="2" />
52+
<zeebe:header key="elementTemplateId" value="io.camunda.connectors.Jdbc.v1" />
53+
<zeebe:header key="resultVariable" value="sql_success" />
54+
<zeebe:header key="resultExpression" value="=true" />
55+
<zeebe:header key="retryBackoff" value="PT0S" />
56+
</zeebe:taskHeaders>
57+
</bpmn:extensionElements>
58+
<bpmn:incoming>Flow_05wf0jz</bpmn:incoming>
59+
</bpmn:serviceTask>
60+
<bpmn:startEvent id="StartEvent_1">
61+
<bpmn:outgoing>Flow_1xr5ql2</bpmn:outgoing>
62+
</bpmn:startEvent>
2663
</bpmn:process>
2764
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
2865
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1kuphyf">
29-
<bpmndi:BPMNShape id="StartEvent_1_di" bpmnElement="StartEvent_1">
30-
<dc:Bounds x="182" y="102" width="36" height="36" />
66+
<bpmndi:BPMNShape id="Activity_1vrphkd_di" bpmnElement="Task_Script">
67+
<dc:Bounds x="430" y="80" width="100" height="80" />
68+
<bpmndi:BPMNLabel />
3169
</bpmndi:BPMNShape>
32-
<bpmndi:BPMNShape id="Task_1_di" bpmnElement="Task_1">
70+
<bpmndi:BPMNShape id="Activity_1r05u1a_di" bpmnElement="Task_Api">
3371
<dc:Bounds x="270" y="80" width="100" height="80" />
3472
<bpmndi:BPMNLabel />
3573
</bpmndi:BPMNShape>
36-
<bpmndi:BPMNShape id="Activity_008py6b_di" bpmnElement="Task_2">
37-
<dc:Bounds x="430" y="80" width="100" height="80" />
74+
<bpmndi:BPMNShape id="StartEvent_1_di" bpmnElement="StartEvent_1">
75+
<dc:Bounds x="182" y="102" width="36" height="36" />
76+
</bpmndi:BPMNShape>
77+
<bpmndi:BPMNShape id="Activity_0kjjmuk_di" bpmnElement="Task_Sql">
78+
<dc:Bounds x="590" y="80" width="100" height="80" />
3879
<bpmndi:BPMNLabel />
3980
</bpmndi:BPMNShape>
81+
<bpmndi:BPMNEdge id="Flow_1c72h11_di" bpmnElement="Flow_1c72h11">
82+
<di:waypoint x="370" y="120" />
83+
<di:waypoint x="430" y="120" />
84+
</bpmndi:BPMNEdge>
4085
<bpmndi:BPMNEdge id="Flow_1xr5ql2_di" bpmnElement="Flow_1xr5ql2">
4186
<di:waypoint x="218" y="120" />
4287
<di:waypoint x="270" y="120" />
4388
</bpmndi:BPMNEdge>
44-
<bpmndi:BPMNEdge id="Flow_1c72h11_di" bpmnElement="Flow_1c72h11">
45-
<di:waypoint x="370" y="120" />
46-
<di:waypoint x="430" y="120" />
89+
<bpmndi:BPMNEdge id="Flow_05wf0jz_di" bpmnElement="Flow_05wf0jz">
90+
<di:waypoint x="530" y="120" />
91+
<di:waypoint x="590" y="120" />
4792
</bpmndi:BPMNEdge>
4893
</bpmndi:BPMNPlane>
4994
</bpmndi:BPMNDiagram>
File renamed without changes.

lib/components/CodeEditor/index.jsx

Lines changed: 0 additions & 88 deletions
This file was deleted.

lib/components/CodeEditor/style.scss

Lines changed: 0 additions & 24 deletions
This file was deleted.

lib/components/Input/Input.jsx

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import React, { useState } from 'react';
2+
3+
import { Link } from '@carbon/react';
4+
import { Launch } from '@carbon/icons-react';
5+
6+
import InputEditor from './InputEditor';
7+
8+
import RunButton from './RunButton';
9+
10+
// import './Input.scss';
11+
12+
export default function Input({
13+
element,
14+
input,
15+
setInput,
16+
variables,
17+
onRunTask,
18+
}) {
19+
20+
const [ error, setError ] = useState(false);
21+
22+
const elementName = element.name || element.id;
23+
24+
return (
25+
<div className="section">
26+
<div className="section__header">
27+
<div className="section__header--title">
28+
<div className="section__header--title-with-icon">
29+
<p>Test {elementName}</p>
30+
<Link
31+
href="https://docs.camunda.io/docs/components/concepts/variables"
32+
renderIcon={ () => <Launch size="14" /> } />
33+
</div>
34+
<p className="cds--label">
35+
{'Run the selected task with the provided input variables.'}
36+
</p>
37+
</div>
38+
<div className="section__header--buttons">
39+
<RunButton
40+
onClick={ () => onRunTask(input) }
41+
error={ error }
42+
/>
43+
</div>
44+
</div>
45+
<div className="section__content">
46+
<InputEditor
47+
value={ input }
48+
onChange={ setInput }
49+
onErrorChange={ setError }
50+
variables={ variables }
51+
/>
52+
</div>
53+
</div>
54+
);
55+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import React, { useEffect, useRef, useMemo } from 'react';
2+
3+
import { basicSetup } from 'codemirror';
4+
import { EditorState } from '@codemirror/state';
5+
import { EditorView, placeholder } from '@codemirror/view';
6+
import { linter } from '@codemirror/lint';
7+
import { json } from '@codemirror/lang-json';
8+
9+
import {
10+
autoCompletionExtension,
11+
startCompletionExtension,
12+
jsonLinter } from '../../utils/codemirror';
13+
14+
export default function InputEditor({
15+
value,
16+
onChange,
17+
onErrorChange,
18+
variables = []
19+
}) {
20+
21+
const editorRef = useRef(null);
22+
const viewRef = useRef(null);
23+
24+
const completion = useMemo(() =>
25+
variables.map(({ name, detail, info }) => ({
26+
label: name,
27+
type: 'variable',
28+
info: info,
29+
detail: detail ? `[${detail}]` : undefined,
30+
})), [ variables ]);
31+
32+
useEffect(() => {
33+
if (!editorRef.current) return;
34+
35+
const startState = EditorState.create({
36+
doc: value,
37+
extensions: [
38+
basicSetup,
39+
json(),
40+
autoCompletionExtension(completion),
41+
startCompletionExtension(completion),
42+
linter(jsonLinter(onErrorChange)()),
43+
placeholder('Provide process variables in JSON format'),
44+
EditorView.updateListener.of((update) => {
45+
if (update.docChanged) {
46+
const newText = update.state.doc.toString();
47+
onChange(newText);
48+
}
49+
}),
50+
],
51+
});
52+
53+
const view = new EditorView({
54+
state: startState,
55+
parent: editorRef.current,
56+
});
57+
58+
viewRef.current = view;
59+
60+
return () => {
61+
view.destroy();
62+
};
63+
}, [ completion ]);
64+
65+
return <div ref={ editorRef } className="input-editor" />;
66+
}

0 commit comments

Comments
 (0)