cpee 2.1.134 → 2.1.136
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/cockpit/compliance-view.html +12 -13
- data/cockpit/compliance.html +12 -13
- data/cockpit/css/llm.css +3 -3
- data/cockpit/css/llmmodel.css +140 -0
- data/cockpit/css/model.css +0 -1
- data/cockpit/css/ui.css +13 -7
- data/cockpit/css/wfadaptor.css +15 -10
- data/cockpit/edit.html +17 -13
- data/cockpit/graph.html +8 -8
- data/cockpit/index.html +12 -13
- data/cockpit/js/build-bpmn2.js +302 -0
- data/cockpit/js/details.js +27 -10
- data/cockpit/js/instance.js +193 -203
- data/cockpit/js/llm-ui-bubble.js +36 -0
- data/cockpit/js/llm-ui-status.js +34 -0
- data/cockpit/js/llm-ui.js +87 -0
- data/cockpit/js/llm.js +463 -118
- data/cockpit/js/parameters.js +45 -14
- data/cockpit/js/wfadaptor.js +394 -75
- data/cockpit/llm.html +17 -15
- data/cockpit/llmmodel.html +18 -17
- data/cockpit/model.html +9 -9
- data/cockpit/only_llm.html +15 -13
- data/cockpit/themes/base.js +1 -1
- data/cockpit/themes/packed/theme.js +3 -0
- data/cockpit/themes/presetlr/rngs/alternative.rng +28 -0
- data/cockpit/themes/presetlr/rngs/call.rng +249 -0
- data/cockpit/themes/presetlr/rngs/callmanipulate.rng +281 -0
- data/cockpit/themes/presetlr/rngs/choose.rng +27 -0
- data/cockpit/themes/presetlr/rngs/closed_loop.rng +62 -0
- data/cockpit/themes/presetlr/rngs/closed_loop_cancel.rng +5 -0
- data/cockpit/themes/presetlr/rngs/closed_loop_control.rng +31 -0
- data/cockpit/themes/presetlr/rngs/closed_loop_measuring.rng +12 -0
- data/cockpit/themes/presetlr/rngs/critical.rng +8 -0
- data/cockpit/themes/presetlr/rngs/escape.rng +5 -0
- data/cockpit/themes/presetlr/rngs/group.rng +3 -0
- data/cockpit/themes/presetlr/rngs/loop.rng +40 -0
- data/cockpit/themes/presetlr/rngs/manipulate.rng +76 -0
- data/cockpit/themes/presetlr/rngs/otherwise.rng +25 -0
- data/cockpit/themes/presetlr/rngs/parallel.rng +24 -0
- data/cockpit/themes/presetlr/rngs/parallel_branch.rng +5 -0
- data/cockpit/themes/presetlr/rngs/scripts.rng +23 -0
- data/cockpit/themes/presetlr/rngs/start.rng +143 -0
- data/cockpit/themes/presetlr/rngs/stop.rng +5 -0
- data/cockpit/themes/presetlr/rngs/terminate.rng +8 -0
- data/cockpit/themes/presetlr/rngs/wait_for_signal.rng +8 -0
- data/cockpit/themes/presetlr/symbols/alternative.svg +19 -0
- data/cockpit/themes/presetlr/symbols/arrow.svg +1 -0
- data/cockpit/themes/presetlr/symbols/call.svg +1 -0
- data/cockpit/themes/presetlr/symbols/call_sensor.svg +1 -0
- data/cockpit/themes/presetlr/symbols/callmanipulate.svg +1 -0
- data/cockpit/themes/presetlr/symbols/callmanipulate_sensor.svg +1 -0
- data/cockpit/themes/presetlr/symbols/callmanipulate_sensor_signal.svg +1 -0
- data/cockpit/themes/presetlr/symbols/callmanipulate_signal.svg +1 -0
- data/cockpit/themes/presetlr/symbols/choose.svg +15 -0
- data/cockpit/themes/presetlr/symbols/choose_exclusive.svg +15 -0
- data/cockpit/themes/presetlr/symbols/choose_exclusive_finish.svg +1 -0
- data/cockpit/themes/presetlr/symbols/choose_inclusive.svg +13 -0
- data/cockpit/themes/presetlr/symbols/choose_inclusive_finish.svg +1 -0
- data/cockpit/themes/presetlr/symbols/closed_loop.svg +1 -0
- data/cockpit/themes/presetlr/symbols/closed_loop_cancel.svg +1 -0
- data/cockpit/themes/presetlr/symbols/closed_loop_control.svg +1 -0
- data/cockpit/themes/presetlr/symbols/closed_loop_measuring.svg +1 -0
- data/cockpit/themes/presetlr/symbols/complex.svg +1 -0
- data/cockpit/themes/presetlr/symbols/critical.svg +1 -0
- data/cockpit/themes/presetlr/symbols/delete.svg +1 -0
- data/cockpit/themes/presetlr/symbols/end.svg +1 -0
- data/cockpit/themes/presetlr/symbols/escape.svg +1 -0
- data/cockpit/themes/presetlr/symbols/event_end.svg +1 -0
- data/cockpit/themes/presetlr/symbols/event_start.svg +1 -0
- data/cockpit/themes/presetlr/symbols/loop.svg +15 -0
- data/cockpit/themes/presetlr/symbols/loop_end.svg +15 -0
- data/cockpit/themes/presetlr/symbols/loop_end_pre.svg +15 -0
- data/cockpit/themes/presetlr/symbols/manipulate.svg +1 -0
- data/cockpit/themes/presetlr/symbols/mark.svg +1 -0
- data/cockpit/themes/presetlr/symbols/otherwise.svg +7 -0
- data/cockpit/themes/presetlr/symbols/parallel.svg +1 -0
- data/cockpit/themes/presetlr/symbols/parallel_branch.svg +7 -0
- data/cockpit/themes/presetlr/symbols/parallel_branch_event.svg +14 -0
- data/cockpit/themes/presetlr/symbols/parallel_branch_event_rev.svg +11 -0
- data/cockpit/themes/presetlr/symbols/parallel_branch_normal.svg +7 -0
- data/cockpit/themes/presetlr/symbols/parallel_eventbased_exclusive.svg +1 -0
- data/cockpit/themes/presetlr/symbols/parallel_eventbased_parallel.svg +1 -0
- data/cockpit/themes/presetlr/symbols/scripts.svg +1 -0
- data/cockpit/themes/presetlr/symbols/start.svg +1 -0
- data/cockpit/themes/presetlr/symbols/start_event.svg +1 -0
- data/cockpit/themes/presetlr/symbols/stop.svg +1 -0
- data/cockpit/themes/presetlr/symbols/terminate.svg +1 -0
- data/cockpit/themes/presetlr/symbols/wait_for_signal.svg +1 -0
- data/cockpit/themes/presetlr/theme.js +54 -0
- data/cockpit/themes/wellformed/rngs/alternative.rng +28 -0
- data/cockpit/themes/wellformed/rngs/call.rng +249 -0
- data/cockpit/themes/wellformed/rngs/callmanipulate.rng +281 -0
- data/cockpit/themes/wellformed/rngs/choose.rng +27 -0
- data/cockpit/themes/wellformed/rngs/closed_loop.rng +62 -0
- data/cockpit/themes/wellformed/rngs/closed_loop_cancel.rng +5 -0
- data/cockpit/themes/wellformed/rngs/closed_loop_control.rng +31 -0
- data/cockpit/themes/wellformed/rngs/closed_loop_measuring.rng +12 -0
- data/cockpit/themes/wellformed/rngs/critical.rng +8 -0
- data/cockpit/themes/wellformed/rngs/escape.rng +5 -0
- data/cockpit/themes/wellformed/rngs/group.rng +3 -0
- data/cockpit/themes/wellformed/rngs/loop.rng +40 -0
- data/cockpit/themes/wellformed/rngs/manipulate.rng +76 -0
- data/cockpit/themes/wellformed/rngs/otherwise.rng +25 -0
- data/cockpit/themes/wellformed/rngs/parallel.rng +24 -0
- data/cockpit/themes/wellformed/rngs/parallel_branch.rng +5 -0
- data/cockpit/themes/wellformed/rngs/scripts.rng +23 -0
- data/cockpit/themes/wellformed/rngs/start.rng +143 -0
- data/cockpit/themes/wellformed/rngs/stop.rng +5 -0
- data/cockpit/themes/wellformed/rngs/terminate.rng +8 -0
- data/cockpit/themes/wellformed/rngs/wait_for_signal.rng +8 -0
- data/cockpit/themes/wellformed/symbols/alternative.svg +1 -0
- data/cockpit/themes/wellformed/symbols/arrow.svg +1 -0
- data/cockpit/themes/wellformed/symbols/call.svg +1 -0
- data/cockpit/themes/wellformed/symbols/call_sensor.svg +1 -0
- data/cockpit/themes/wellformed/symbols/callmanipulate.svg +1 -0
- data/cockpit/themes/wellformed/symbols/callmanipulate_sensor.svg +1 -0
- data/cockpit/themes/wellformed/symbols/callmanipulate_sensor_signal.svg +1 -0
- data/cockpit/themes/wellformed/symbols/callmanipulate_signal.svg +1 -0
- data/cockpit/themes/wellformed/symbols/choose.svg +1 -0
- data/cockpit/themes/wellformed/symbols/choose_exclusive.svg +1 -0
- data/cockpit/themes/wellformed/symbols/choose_exclusive_finish.svg +1 -0
- data/cockpit/themes/wellformed/symbols/choose_inclusive.svg +1 -0
- data/cockpit/themes/wellformed/symbols/choose_inclusive_finish.svg +1 -0
- data/cockpit/themes/wellformed/symbols/closed_loop.svg +1 -0
- data/cockpit/themes/wellformed/symbols/closed_loop_cancel.svg +1 -0
- data/cockpit/themes/wellformed/symbols/closed_loop_control.svg +1 -0
- data/cockpit/themes/wellformed/symbols/closed_loop_measuring.svg +1 -0
- data/cockpit/themes/wellformed/symbols/complex.svg +1 -0
- data/cockpit/themes/wellformed/symbols/critical.svg +1 -0
- data/cockpit/themes/wellformed/symbols/delete.svg +1 -0
- data/cockpit/themes/wellformed/symbols/end.svg +1 -0
- data/cockpit/themes/wellformed/symbols/escape.svg +1 -0
- data/cockpit/themes/wellformed/symbols/event_end.svg +1 -0
- data/cockpit/themes/wellformed/symbols/event_start.svg +6 -0
- data/cockpit/themes/wellformed/symbols/loop.svg +1 -0
- data/cockpit/themes/wellformed/symbols/loop_end.svg +1 -0
- data/cockpit/themes/wellformed/symbols/manipulate.svg +1 -0
- data/cockpit/themes/wellformed/symbols/mark.svg +1 -0
- data/cockpit/themes/wellformed/symbols/otherwise.svg +1 -0
- data/cockpit/themes/wellformed/symbols/parallel.svg +1 -0
- data/cockpit/themes/wellformed/symbols/parallel_branch.svg +1 -0
- data/cockpit/themes/wellformed/symbols/parallel_branch_event.svg +1 -0
- data/cockpit/themes/wellformed/symbols/parallel_branch_event_rev.svg +11 -0
- data/cockpit/themes/wellformed/symbols/parallel_branch_normal.svg +1 -0
- data/cockpit/themes/wellformed/symbols/parallel_eventbased_exclusive.svg +1 -0
- data/cockpit/themes/wellformed/symbols/parallel_eventbased_parallel.svg +1 -0
- data/cockpit/themes/wellformed/symbols/scripts.svg +1 -0
- data/cockpit/themes/wellformed/symbols/start.svg +1 -0
- data/cockpit/themes/wellformed/symbols/start_event.svg +1 -0
- data/cockpit/themes/wellformed/symbols/stop.svg +1 -0
- data/cockpit/themes/wellformed/symbols/terminate.svg +1 -0
- data/cockpit/themes/wellformed/symbols/wait_for_signal.svg +1 -0
- data/cockpit/themes/wellformed/theme.js +32 -0
- data/cockpit/track.html +8 -8
- data/cpee.gemspec +2 -2
- data/lib/callbacks/callbacks.rng +4 -4
- data/lib/callbacks.xml +4 -4
- data/lib/cpee/constants.rb +4 -4
- data/lib/cpee/fail.rb +4 -4
- data/lib/cpee/implementation.rb +5 -4
- data/lib/cpee/implementation_callbacks.rb +4 -4
- data/lib/cpee/implementation_notifications.rb +4 -4
- data/lib/cpee/implementation_properties.rb +108 -12
- data/lib/cpee/message.rb +4 -4
- data/lib/cpee/persistence.rb +6 -4
- data/lib/cpee/redis.rb +4 -4
- data/lib/cpee/statemachine.rb +4 -4
- data/lib/cpee/value_helper.rb +4 -4
- data/lib/cpee.xml +4 -4
- data/lib/engine/executionhandler-list.rng +4 -4
- data/lib/engine/instance-info.rng +4 -4
- data/lib/engine/instances.rng +4 -4
- data/lib/engine.xml +4 -4
- data/lib/properties/t_dslx.rng +346 -0
- data/lib/properties/transformation.rng +14 -0
- data/lib/properties.xml +5 -4
- data/server/executionhandlers/eval/backend/opts.yaml +1 -1
- data/server/executionhandlers/eval/connection.rb +4 -4
- data/server/executionhandlers/eval/execution.rb +4 -4
- data/server/executionhandlers/ruby/backend/opts.yaml +1 -1
- data/server/executionhandlers/ruby/connection.rb +5 -6
- data/server/executionhandlers/ruby/controller.rb +4 -4
- data/server/executionhandlers/ruby/dsl_to_dslx.xsl +6 -2
- data/server/executionhandlers/ruby/execution.rb +4 -4
- data/server/resources/properties.empty +5 -4
- data/server/resources/properties.init +5 -4
- data/server/resources/topics.xml +4 -4
- data/server/routing/end.pid +1 -0
- data/server/routing/end.rb +4 -4
- data/server/routing/forward-events-00.pid +1 -0
- data/server/routing/forward-events.rb +4 -4
- data/server/routing/forward-votes.pid +1 -0
- data/server/routing/forward-votes.rb +4 -4
- data/server/routing/persist.pid +1 -0
- data/server/routing/persist.rb +6 -4
- data/tools/server/cpee +1 -1
- data/tools/server/resources/properties.init +4 -4
- metadata +140 -5
- data/cockpit/CPEE.xml +0 -8
- data/cockpit/Signavio.xml +0 -8
- data/cockpit/transformations.xml +0 -4
- /data/{COPYING → LICENSE} +0 -0
data/cockpit/index.html
CHANGED
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
This file is part of CPEE.
|
|
3
3
|
|
|
4
4
|
CPEE is free software: you can redistribute it and/or modify it under the terms
|
|
5
|
-
of the GNU General Public License as published by the Free Software Foundation,
|
|
5
|
+
of the GNU Lesser General Public License as published by the Free Software Foundation,
|
|
6
6
|
either version 3 of the License, or (at your option) any later version.
|
|
7
7
|
|
|
8
8
|
CPEE is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
9
9
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
10
|
-
PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
10
|
+
PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
|
11
11
|
|
|
12
|
-
You should have received a copy of the GNU General Public License along with
|
|
13
|
-
CPEE (file
|
|
12
|
+
You should have received a copy of the GNU Lesser General Public License along with
|
|
13
|
+
CPEE (file LICENSE in the main directory). If not, see
|
|
14
14
|
<http://www.gnu.org/licenses/>.
|
|
15
15
|
-->
|
|
16
16
|
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
<script type="text/javascript" src="/js_libs/jquery.svg.min.js"></script>
|
|
29
29
|
<script type="text/javascript" src="/js_libs/jquery.svgdom.min.js"></script>
|
|
30
30
|
<script type="text/javascript" src="/js_libs/vkbeautify.js"></script>
|
|
31
|
-
<script type="text/javascript" src="/js_libs/
|
|
31
|
+
<script type="text/javascript" src="/js_libs/uidash_util.js"></script>
|
|
32
32
|
<script type="text/javascript" src="/js_libs/printf.js"></script>
|
|
33
33
|
<script type="text/javascript" src="/js_libs/strftime.min.js"></script>
|
|
34
34
|
<script type="text/javascript" src="/js_libs/parsequery.js"></script>
|
|
@@ -39,11 +39,11 @@
|
|
|
39
39
|
<script type="text/javascript" src="/js_libs/relaxngui.js"></script>
|
|
40
40
|
|
|
41
41
|
<script type="text/javascript" src="/js_libs/uidash.js"></script>
|
|
42
|
-
<script type="text/javascript" src="/js_libs/
|
|
42
|
+
<script type="text/javascript" src="/js_libs/uidash_custommenu.js"></script>
|
|
43
43
|
|
|
44
|
-
<script type="text/javascript" src="/
|
|
44
|
+
<script type="text/javascript" src="js/build-bpmn2.js"></script>
|
|
45
45
|
|
|
46
|
-
<link rel="stylesheet" href="/js_libs/
|
|
46
|
+
<link rel="stylesheet" href="/js_libs/uidash_custommenu.css" type="text/css"/>
|
|
47
47
|
<link rel="stylesheet" href="/js_libs/uidash.css" type="text/css"/>
|
|
48
48
|
|
|
49
49
|
<link rel="stylesheet" href="/js_libs/relaxngui.css" type="text/css"/>
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
<link rel="stylesheet" href="/global_ui/uicpee.css" type="text/css"/>
|
|
67
67
|
<style></style>
|
|
68
68
|
</head>
|
|
69
|
-
<body data-base-port="
|
|
69
|
+
<body data-base-port="9298" data-base-engine="engine/" data-base-themes="themes/" is="x-ui-">
|
|
70
70
|
<div id='disclaimer' class='hidden'> <!--{{{-->
|
|
71
71
|
<h1>Disclaimer</h1>
|
|
72
72
|
|
|
@@ -119,7 +119,6 @@
|
|
|
119
119
|
<div class='hidden' id='relaxngworker'></div>
|
|
120
120
|
|
|
121
121
|
<div class='menu' id='templates'></div>
|
|
122
|
-
<div class='menu' id='modeltypes'></div>
|
|
123
122
|
|
|
124
123
|
<template id="label">
|
|
125
124
|
<svg width="20" height="20" xmlns="http://www.w3.org/2000/svg" style="position: absolute; top: 0; left: 0;" class="displaylabel">
|
|
@@ -168,7 +167,7 @@
|
|
|
168
167
|
<form id='fuckchrome'>
|
|
169
168
|
<input type='file' name='testsetfile' id='testsetfile'/>
|
|
170
169
|
</form>
|
|
171
|
-
<button title='a template includes various settings, subscriptions or a (partial) model' name="loadtestset">load
|
|
170
|
+
<button title='a template includes various settings, subscriptions or a (partial) model' name="loadtestset">load<br>template</button><button title='a testset includes various settings, subscriptions or a model' name="loadtestsetfile">load<br>testset</button>
|
|
172
171
|
</div>
|
|
173
172
|
<div>
|
|
174
173
|
<input type='file' name='modelfile' id='modelfile'/>
|
|
@@ -182,8 +181,8 @@
|
|
|
182
181
|
<button title='the SVG contains the graphical repesentation of the CPEE tree as you see it on the screen' name="savesvgfile">save svg<br>graph</button>
|
|
183
182
|
</div>
|
|
184
183
|
<div>
|
|
185
|
-
<a id="
|
|
186
|
-
<button title='the
|
|
184
|
+
<a id="savemodelfile" href="" download=""></a>
|
|
185
|
+
<button title='the model in the format of the current model type (e.g. CPEE, BPMN, Mermaid)' name="savemodelfile">save model</button>
|
|
187
186
|
</div>
|
|
188
187
|
</div><div class='section' id='modifiers'>
|
|
189
188
|
<template id="item">
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
/*
|
|
2
|
+
This file is part of cpee-layout.
|
|
3
|
+
|
|
4
|
+
cpee-layout is free software: you can redistribute it and/or modify it under
|
|
5
|
+
the terms of the GNU Lesser General Public License as published by the Free
|
|
6
|
+
Software Foundation, either version 3 of the License, or (at your option) any
|
|
7
|
+
later version.
|
|
8
|
+
|
|
9
|
+
cpee-layout is distributed in the hope that it will be useful, but WITHOUT
|
|
10
|
+
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
11
|
+
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
|
12
|
+
details.
|
|
13
|
+
|
|
14
|
+
You should have received a copy of the GNU Lesser General Public License
|
|
15
|
+
along with cpee-layout (file LICENSE in the main directory). If not, see
|
|
16
|
+
<http://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
The CPEE type mapping and the BPMN output follow build-bpmn.js,
|
|
19
|
+
Copyright 2026 David Kindermann (Apache-2.0).
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
//
|
|
23
|
+
// build-bpmn2.js
|
|
24
|
+
//
|
|
25
|
+
// Creates BPMN XML from wfadaptor's get_svg_metrics():
|
|
26
|
+
// bpmn2_convert(pos_matrix, con_list, lr, geometry), like david_bpmn_convert of
|
|
27
|
+
// build-bpmn.js plus the orientation and the geometry of the drawing. Rows and columns are
|
|
28
|
+
// 0-indexed.
|
|
29
|
+
//
|
|
30
|
+
// Unlike build-bpmn.js, the layout is not computed again: every symbol is
|
|
31
|
+
// placed where the metrics (and so the SVG) have it, and the flows are drawn
|
|
32
|
+
// with right angles only, entering their targets perpendicularly.
|
|
33
|
+
//
|
|
34
|
+
// 1) nodes cells → BPMN shapes, or placeholders that flows pass through
|
|
35
|
+
// 2) flows con_list, followed through placeholders from shape to shape
|
|
36
|
+
// 3) route right-angled waypoints, bending where the placeholders are
|
|
37
|
+
// 4) xml process and diagram interchange
|
|
38
|
+
//
|
|
39
|
+
|
|
40
|
+
// the svg rows (geometry.row apart) are spread to ROW here, so that tasks have
|
|
41
|
+
// the bpmn-js default height (rows are vertical in lr as well)
|
|
42
|
+
const SYM = 30; // symbol size
|
|
43
|
+
const TASK_H = 80; // task height, as bpmn-js; its icon is in the top left corner, so one line of text stays below it
|
|
44
|
+
const ROW = TASK_H + 10; // row distance, the gap stays as in the svg
|
|
45
|
+
const GAP = 10; // space between a task and the next symbol
|
|
46
|
+
const SPACE = 10; // extra space in front of every column, the svg is a bit tight for bpmn
|
|
47
|
+
const PAD = 20; // tasks are this much wider on both sides, bpmn-js puts its text close to the border
|
|
48
|
+
const BACK = 20; // flows that go around (loops) go back this far right of the target's line
|
|
49
|
+
|
|
50
|
+
// cpee types → BPMN element (kind) and event definition (def), or placeholder.
|
|
51
|
+
// Tasks, and all types not listed, get their kind from the subtype
|
|
52
|
+
const TYPE_MAP = {
|
|
53
|
+
description: { kind: "startEvent" },
|
|
54
|
+
start_event: { kind: "startEvent", def: "message" },
|
|
55
|
+
event_start: { kind: "startEvent", def: "signal" }, // the start of a signal branch
|
|
56
|
+
end: { kind: "endEvent" },
|
|
57
|
+
end_event: { kind: "endEvent", def: "message" },
|
|
58
|
+
event_end: { kind: "endEvent", def: "terminate" },
|
|
59
|
+
terminate: { kind: "endEvent", def: "terminate" },
|
|
60
|
+
call: { task: true },
|
|
61
|
+
callmanipulate: { task: true },
|
|
62
|
+
manipulate: { task: true },
|
|
63
|
+
loop_head: { kind: "exclusiveGateway" },
|
|
64
|
+
loop_tail: { kind: "exclusiveGateway" },
|
|
65
|
+
loop_finish: { kind: "exclusiveGateway" },
|
|
66
|
+
loop_tail_pre: { kind: "exclusiveGateway" }, // presetlr: pre_test loops
|
|
67
|
+
loop_finish_pre: { kind: "exclusiveGateway" },
|
|
68
|
+
parallel_start: { kind: "parallelGateway" },
|
|
69
|
+
parallel_simple: { kind: "parallelGateway" },
|
|
70
|
+
parallel_complex: { kind: "complexGateway" },
|
|
71
|
+
parallel_eventbased_parallel: { kind: "complexGateway" },
|
|
72
|
+
parallel_branch_event: { kind: "intermediateThrowEvent", def: "signal" },
|
|
73
|
+
parallel_branch_event_rev: { kind: "intermediateThrowEvent", def: "signal" },
|
|
74
|
+
parallel_branch_normal: { placeholder: "pass" },
|
|
75
|
+
choose_inclusive: { kind: "inclusiveGateway" },
|
|
76
|
+
choose_inclusive_finish: { kind: "inclusiveGateway" },
|
|
77
|
+
choose_exclusive: { kind: "exclusiveGateway" },
|
|
78
|
+
choose_exclusive_finish: { kind: "exclusiveGateway" },
|
|
79
|
+
alternative: { placeholder: "case" }, // its label names the flow
|
|
80
|
+
otherwise: { placeholder: "default" }, // its label names the flow, without one the flow is the default
|
|
81
|
+
stop: { placeholder: "pass" }
|
|
82
|
+
};
|
|
83
|
+
const TASK_SUBTYPES = { user: "userTask", service: "serviceTask", script: "scriptTask" };
|
|
84
|
+
const EVENT_SUBTYPES = {
|
|
85
|
+
timer: { kind: "intermediateCatchEvent", def: "timer" },
|
|
86
|
+
message_receive: { kind: "intermediateCatchEvent", def: "message" },
|
|
87
|
+
message_send: { kind: "intermediateThrowEvent", def: "message" }
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const fmt = (n) => Number(n).toFixed(2).replace(/\.?0+$/, "");
|
|
91
|
+
const key = (r, c) => r + "," + c;
|
|
92
|
+
function xmlEscape(s = "") {
|
|
93
|
+
return String(s).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
94
|
+
}
|
|
95
|
+
function xmlEventDef(def, id) {
|
|
96
|
+
return def ? `<${def}EventDefinition id="${id}_def"/>` : "";
|
|
97
|
+
}
|
|
98
|
+
function xmlSignavioBg(color) { // Signavio: background color per shape
|
|
99
|
+
return `<extensionElements><signavio:signavioMetaData metaKey="bgcolor" metaValue="${xmlEscape(color || "#ffffff")}"/></extensionElements>`;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// 1) nodes: kind is the BPMN element, or null for placeholders. Names are the
|
|
103
|
+
// labels only, the svg has no room for more. x is where the symbol is drawn,
|
|
104
|
+
// mid the middle of its row, labelBox where its label is, relative to the symbol
|
|
105
|
+
function buildNodes(matrix, geometry) {
|
|
106
|
+
const nodes = new Map();
|
|
107
|
+
let n = 0;
|
|
108
|
+
matrix.forEach((row, r) => (row || []).forEach((cell, c) => {
|
|
109
|
+
if (!cell) return;
|
|
110
|
+
const t = TYPE_MAP[cell.type] || { task: true };
|
|
111
|
+
const node = { r, c, x: cell.x - geometry.shift + SPACE * c, mid: r * ROW + geometry.top + TASK_H / 2, width: cell.width, fill: cell.fill, id: "n" + (++n), kind: null, label: cell.label || null };
|
|
112
|
+
const l = cell.label_box;
|
|
113
|
+
if (l) node.labelBox = { dx: l.x - (cell.x - geometry.shift), dy: l.y - (geometry.top + r * geometry.row), w: l.width, h: l.height };
|
|
114
|
+
if (!t.task) {
|
|
115
|
+
Object.assign(node, t);
|
|
116
|
+
} else { // the subtype comes from the endpoint's properties (cockpit only)
|
|
117
|
+
const sub = typeof cell.subtype === "string" ? cell.subtype : "";
|
|
118
|
+
const ev = sub.startsWith("event/") ? (EVENT_SUBTYPES[sub.split("/").slice(1).join("_")] || EVENT_SUBTYPES[sub.split("/")[1]] || { kind: "intermediateCatchEvent" }) : null;
|
|
119
|
+
if (ev) {
|
|
120
|
+
Object.assign(node, { kind: ev.kind, def: ev.def });
|
|
121
|
+
} else {
|
|
122
|
+
node.kind = sub == "marker/subprocess" ? "subProcess"
|
|
123
|
+
: sub.startsWith("task/") ? (TASK_SUBTYPES[sub.split("/")[1]] || "serviceTask")
|
|
124
|
+
: cell.type == "manipulate" ? "scriptTask" : "serviceTask";
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
nodes.set(key(r, c), node);
|
|
128
|
+
}));
|
|
129
|
+
// every column after one with a task moves by the width tasks gain
|
|
130
|
+
const taskCols = new Set([...nodes.values()].filter(isTask).map((n) => n.c));
|
|
131
|
+
for (const n of nodes.values()) n.x += 2 * PAD * [...taskCols].filter((c) => c < n.c).length;
|
|
132
|
+
return nodes;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// bounds as in the svg: tasks span their label and the row, everything else
|
|
136
|
+
// is a symbol in the middle of the row
|
|
137
|
+
function bounds(node) {
|
|
138
|
+
const x = node.x;
|
|
139
|
+
if (!node.kind) return { x: x + SYM / 2, y: node.mid, w: 0, h: 0 }; // placeholders are points
|
|
140
|
+
if (isTask(node)) return { x, y: node.mid - TASK_H / 2, w: Math.max(SYM, node.width - GAP) + 2 * PAD, h: TASK_H };
|
|
141
|
+
return { x, y: node.mid - SYM / 2, w: SYM, h: SYM };
|
|
142
|
+
}
|
|
143
|
+
const isTask = (node) => /Task$|^subProcess$/.test(node.kind);
|
|
144
|
+
|
|
145
|
+
// labels of events, gateways and placeholders are where the svg shows them,
|
|
146
|
+
// relative to their symbol. Labels the svg does not show have no bounds
|
|
147
|
+
function labelBounds(node) {
|
|
148
|
+
const l = node.labelBox;
|
|
149
|
+
return l ? { x: node.x + l.dx, y: node.mid - SYM / 2 + l.dy, w: l.w, h: l.h } : null;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// 2) flows from shape to shape, following con_list through placeholders
|
|
153
|
+
function buildFlows(nodes, conlist) {
|
|
154
|
+
const out = new Map();
|
|
155
|
+
for (const e of conlist) {
|
|
156
|
+
const f = key(e.from.row, e.from.col), t = key(e.to.row, e.to.col);
|
|
157
|
+
if (!nodes.has(f) || !nodes.has(t)) throw new Error("bpmn2_convert: con_list connects an empty cell, " + f + " -> " + t);
|
|
158
|
+
if (!out.has(f)) out.set(f, []);
|
|
159
|
+
out.get(f).push(t);
|
|
160
|
+
}
|
|
161
|
+
const flows = [];
|
|
162
|
+
const seen = new Set();
|
|
163
|
+
for (const [k, src] of nodes) {
|
|
164
|
+
if (!src.kind) continue;
|
|
165
|
+
const walk = (from, via, anchor, visited) => {
|
|
166
|
+
for (const t of out.get(from) || []) {
|
|
167
|
+
const n = nodes.get(t);
|
|
168
|
+
if (n.kind) {
|
|
169
|
+
const sig = src.id + ">" + n.id;
|
|
170
|
+
if (seen.has(sig)) continue;
|
|
171
|
+
seen.add(sig);
|
|
172
|
+
flows.push({ src, dst: n, via, anchor });
|
|
173
|
+
} else if (!visited.has(t)) {
|
|
174
|
+
visited.add(t);
|
|
175
|
+
walk(t, via.concat([n]), n.placeholder != "pass" ? n : anchor, visited);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
walk(k, [], null, new Set([k]));
|
|
180
|
+
}
|
|
181
|
+
for (const f of flows) {
|
|
182
|
+
if (!f.anchor) continue;
|
|
183
|
+
if (f.anchor.label) f.name = f.anchor.label;
|
|
184
|
+
else if (f.anchor.placeholder == "default" && f.src.kind == "exclusiveGateway") f.isDefault = true;
|
|
185
|
+
}
|
|
186
|
+
return flows;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// 3) right angles only. a is the position along the flow, c across it
|
|
190
|
+
function route(flow, lr, nodes) {
|
|
191
|
+
const P = (a, c) => lr ? { x: a, y: c } : { x: c, y: a };
|
|
192
|
+
const box = (n) => {
|
|
193
|
+
const b = bounds(n);
|
|
194
|
+
const s = { x: n.kind ? b.x + SYM / 2 : b.x, y: n.mid }; // the symbol, not the label
|
|
195
|
+
const next = n.mid + ROW / 2; // between this row and the next
|
|
196
|
+
return lr ? { n, a: s.x, c: s.y, a0: b.x, a1: b.x + b.w, c0: b.y, c1: b.y + b.h, turn: GAP / 2 }
|
|
197
|
+
: { n, a: s.y, c: s.x, a0: b.y, a1: b.y + b.h, c0: b.x, c1: b.x + b.w, turn: next - (b.y + b.h) };
|
|
198
|
+
};
|
|
199
|
+
const shapes = [...nodes.values()].filter((n) => n.kind).map(box);
|
|
200
|
+
const blocking = (c, from, to, except) => shapes.filter((b) => !except.includes(b.n) && b.c0 <= c && c <= b.c1 && b.a1 > Math.min(from, to) && b.a0 < Math.max(from, to));
|
|
201
|
+
// a leg follows its own direction (dir), forwards or backwards along the flow
|
|
202
|
+
const leg = (s, d) => {
|
|
203
|
+
const dA = d.a - s.a, dC = d.c - s.c, dir = dA < 0 ? -1 : 1, except = [s.n, d.n];
|
|
204
|
+
const out = dir > 0 ? s.a1 : s.a0, into = dir > 0 ? d.a0 : d.a1; // the sides facing each other
|
|
205
|
+
if (Math.abs(dA) < 0.5) return dC > 0 ? [P(s.a, s.c1), P(d.a, d.c0)] : [P(s.a, s.c0), P(d.a, d.c1)]; // straight across
|
|
206
|
+
if (Math.abs(dC) < 0.5 && !blocking(s.c, s.a, d.a, except).length) return [P(out, s.c), P(into, d.c)]; // straight along
|
|
207
|
+
if (dC > 0 && !blocking(d.c, s.a, d.a, except).length) return [P(s.a, s.c1), P(s.a, d.c), P(into, d.c)]; // branch out: across, then along into the target
|
|
208
|
+
if (dC < 0 && !blocking(s.c, s.a, d.a, except).length) return [P(out, s.c), P(d.a, s.c), P(d.a, d.c1)]; // join: along, then across into the target
|
|
209
|
+
// shapes in the way (e.g. the content of a loop): leave on the far side, turn,
|
|
210
|
+
// and go back parallel to the target's line, BACK beside it on the right (or
|
|
211
|
+
// beside what is in the way). Symbols are entered at 45 degrees
|
|
212
|
+
const far = dir > 0 ? s.a0 : s.a1, turn = far - dir * s.turn;
|
|
213
|
+
const inway = blocking(d.c + BACK, turn, into, except);
|
|
214
|
+
const lane = inway.length ? Math.max(...inway.map((b) => b.c1)) + BACK : d.c + BACK;
|
|
215
|
+
if (d.n.kind && !isTask(d.n)) {
|
|
216
|
+
const edge = /Gateway$/.test(d.n.kind) ? SYM / 4 : SYM / 2 / Math.SQRT2; // the border at 45 degrees: diamond or circle
|
|
217
|
+
return [P(far, s.c), P(turn, s.c), P(turn, lane), P(d.a - dir * (lane - d.c), lane), P(d.a - dir * edge, d.c + edge)];
|
|
218
|
+
}
|
|
219
|
+
const end = lane <= d.c1 ? [P(into, lane)] : [P(d.a, lane), P(d.a, d.c1)];
|
|
220
|
+
return [P(far, s.c), P(turn, s.c), P(turn, lane)].concat(end);
|
|
221
|
+
};
|
|
222
|
+
// source and target on one line, along or across the flow: straight, unless
|
|
223
|
+
// another shape is in the way (e.g. the content of a loop)
|
|
224
|
+
const s = box(flow.src), d = box(flow.dst), except = [flow.src, flow.dst];
|
|
225
|
+
const across = shapes.some((b) => !except.includes(b.n) && b.a0 <= s.a && s.a <= b.a1 && b.c1 > Math.min(s.c, d.c) && b.c0 < Math.max(s.c, d.c));
|
|
226
|
+
if (flow.src !== flow.dst) {
|
|
227
|
+
if (Math.abs(d.c - s.c) < 0.5 && !blocking(s.c, s.a, d.a, except).length) return d.a > s.a ? [P(s.a1, s.c), P(d.a0, d.c)] : [P(s.a0, s.c), P(d.a1, d.c)];
|
|
228
|
+
if (Math.abs(d.a - s.a) < 0.5 && !across) return d.c > s.c ? [P(s.a, s.c1), P(d.a, d.c0)] : [P(s.a, s.c0), P(d.a, d.c1)];
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const stops = [flow.src].concat(flow.via, [flow.dst]).map(box);
|
|
232
|
+
let pts = [];
|
|
233
|
+
for (let i = 0; i < stops.length - 1; i++) pts = pts.concat(leg(stops[i], stops[i + 1]));
|
|
234
|
+
// drop repeated points and points in the middle of a straight line
|
|
235
|
+
pts = pts.filter((p, i) => i == 0 || p.x != pts[i - 1].x || p.y != pts[i - 1].y);
|
|
236
|
+
return pts.filter((p, i) => {
|
|
237
|
+
if (i == 0 || i == pts.length - 1) return true;
|
|
238
|
+
const a = pts[i - 1], b = pts[i + 1];
|
|
239
|
+
return !((a.x == p.x && p.x == b.x) || (a.y == p.y && p.y == b.y));
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// 4) xml
|
|
244
|
+
function generateXML(nodes, flows, lr) {
|
|
245
|
+
const shapes = [...nodes.values()].filter((n) => n.kind);
|
|
246
|
+
flows.forEach((f, i) => { f.id = "e" + (i + 1); });
|
|
247
|
+
const defaults = new Map(flows.filter((f) => f.isDefault).map((f) => [f.src.id, f.id]));
|
|
248
|
+
const nameAttr = (s) => s ? ` name="${xmlEscape(s)}"` : "";
|
|
249
|
+
|
|
250
|
+
const proc = shapes.map((s) => {
|
|
251
|
+
const def = defaults.has(s.id) ? ` default="${defaults.get(s.id)}"` : "";
|
|
252
|
+
return ` <${s.kind} id="${s.id}"${nameAttr(s.label)}${def}>${xmlSignavioBg(s.fill)}${xmlEventDef(s.def, s.id)}</${s.kind}>`;
|
|
253
|
+
}).concat(flows.map((f) =>
|
|
254
|
+
` <sequenceFlow id="${f.id}" sourceRef="${f.src.id}" targetRef="${f.dst.id}"${nameAttr(f.name)}/>`
|
|
255
|
+
)).join("\n");
|
|
256
|
+
|
|
257
|
+
const xmlBounds = (b, indent) => `${indent}<omgdc:Bounds x="${fmt(b.x)}" y="${fmt(b.y)}" width="${fmt(b.w)}" height="${fmt(b.h)}"/>\n`;
|
|
258
|
+
const xmlLabel = (b) => b ? ` <bpmndi:BPMNLabel>\n${xmlBounds(b, " ")} </bpmndi:BPMNLabel>\n` : "";
|
|
259
|
+
const di = shapes.map((s) => {
|
|
260
|
+
const marker = /Gateway$/.test(s.kind) ? ' isMarkerVisible="true"' : "";
|
|
261
|
+
return ` <bpmndi:BPMNShape id="${s.id}_gui" bpmnElement="${s.id}"${marker}>\n` +
|
|
262
|
+
xmlBounds(bounds(s), " ") +
|
|
263
|
+
xmlLabel(s.label && !isTask(s) ? labelBounds(s) : null) +
|
|
264
|
+
` </bpmndi:BPMNShape>`;
|
|
265
|
+
}).concat(flows.map((f) =>
|
|
266
|
+
` <bpmndi:BPMNEdge id="${f.id}_gui" bpmnElement="${f.id}">\n` +
|
|
267
|
+
route(f, lr, nodes).map((p) => ` <omgdi:waypoint x="${fmt(p.x)}" y="${fmt(p.y)}"/>`).join("\n") + "\n" +
|
|
268
|
+
xmlLabel(f.name ? labelBounds(f.anchor) : null) +
|
|
269
|
+
` </bpmndi:BPMNEdge>`
|
|
270
|
+
)).join("\n");
|
|
271
|
+
|
|
272
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
273
|
+
<definitions
|
|
274
|
+
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
|
|
275
|
+
xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
|
|
276
|
+
xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI"
|
|
277
|
+
xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC"
|
|
278
|
+
xmlns:signavio="http://www.signavio.com"
|
|
279
|
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
280
|
+
targetNamespace="https://example.com/bpmn"
|
|
281
|
+
>
|
|
282
|
+
<process id="process1" isExecutable="false">
|
|
283
|
+
${proc}
|
|
284
|
+
</process>
|
|
285
|
+
<bpmndi:BPMNDiagram id="diagram1">
|
|
286
|
+
<bpmndi:BPMNPlane id="plane1" bpmnElement="process1">
|
|
287
|
+
${di}
|
|
288
|
+
</bpmndi:BPMNPlane>
|
|
289
|
+
</bpmndi:BPMNDiagram>
|
|
290
|
+
</definitions>`;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// returns the BPMN XML as a string
|
|
294
|
+
function bpmn2_convert(dpm, dcl, lr, geometry) {
|
|
295
|
+
if (!Array.isArray(dpm) || !Array.isArray(dcl) || typeof lr !== "boolean" || !geometry) throw new Error("bpmn2_convert: needs pos_matrix, con_list, lr and geometry of get_svg_metrics");
|
|
296
|
+
const nodes = buildNodes(dpm, geometry);
|
|
297
|
+
return generateXML(nodes, buildFlows(nodes, dcl), lr);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
if (typeof window !== "undefined") {
|
|
301
|
+
window.bpmn2_convert = bpmn2_convert;
|
|
302
|
+
}
|
data/cockpit/js/details.js
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
var details_updated = new Event("details:updated", {"bubbles":true, "cancelable":false});
|
|
2
|
+
var details_timer;
|
|
2
3
|
|
|
3
4
|
$(document).ready(function() {
|
|
4
|
-
var timer;
|
|
5
|
-
|
|
6
5
|
$(document).on('input','#dat_details input, #dat_details textarea, #dat_details [contenteditable]',function(e){
|
|
7
|
-
clearTimeout(
|
|
8
|
-
|
|
6
|
+
clearTimeout(details_timer);
|
|
7
|
+
let details = save['details'];
|
|
8
|
+
details_timer = setTimeout(() => {
|
|
9
|
+
details_timer = undefined;
|
|
10
|
+
// safety net, details_leave should have been called when details were emptied or replaced
|
|
11
|
+
if (details === save['details'] && $('#dat_details').children().length > 0) { do_main_save(); }
|
|
12
|
+
}, 5000);
|
|
9
13
|
});
|
|
10
14
|
// only for contenteditable divs
|
|
11
15
|
$(document).on('keypress','#dat_details div[contenteditable]',function(e){
|
|
@@ -15,19 +19,31 @@ $(document).ready(function() {
|
|
|
15
19
|
}
|
|
16
20
|
});
|
|
17
21
|
$(document).on('relaxngui_remove', '#dat_details', function(e){
|
|
18
|
-
|
|
22
|
+
details_leave(false);
|
|
19
23
|
do_main_save();
|
|
20
24
|
});
|
|
21
25
|
$(document).on('relaxngui_move', '#dat_details', function(e){
|
|
22
|
-
|
|
26
|
+
details_leave(false);
|
|
23
27
|
do_main_save();
|
|
24
28
|
});
|
|
25
29
|
$(document).on('relaxngui_change', '#dat_details', function(e){
|
|
26
|
-
|
|
30
|
+
details_leave(false);
|
|
27
31
|
do_main_save();
|
|
28
32
|
});
|
|
29
33
|
});
|
|
30
34
|
|
|
35
|
+
// call before details are emptied or replaced. a pending (not yet saved)
|
|
36
|
+
// change is saved when flush is true (same model stays), otherwise dropped
|
|
37
|
+
// (model is replaced, saving would overwrite the new one).
|
|
38
|
+
function details_leave(flush) { //{{{
|
|
39
|
+
let pending = details_timer != undefined;
|
|
40
|
+
clearTimeout(details_timer);
|
|
41
|
+
details_timer = undefined;
|
|
42
|
+
if (flush && pending && save['details'] && $('#dat_details').children().length > 0) {
|
|
43
|
+
do_main_save();
|
|
44
|
+
}
|
|
45
|
+
} //}}}
|
|
46
|
+
|
|
31
47
|
function do_main_save() { //{{{
|
|
32
48
|
if (save['details'].has_changed()) {
|
|
33
49
|
do_main_work(save['details_target'].svgid);
|
|
@@ -106,13 +122,14 @@ function do_main_work(svgid) { //{{{
|
|
|
106
122
|
} else {
|
|
107
123
|
$.ajax({
|
|
108
124
|
type: "PUT",
|
|
109
|
-
url: url + "/properties/
|
|
125
|
+
url: url + "/properties/dslx/",
|
|
110
126
|
contentType: 'text/xml',
|
|
111
127
|
headers: {
|
|
112
|
-
'Content-ID': '
|
|
128
|
+
'Content-ID': 'dslx',
|
|
113
129
|
'CPEE-Event-Source': myid
|
|
114
130
|
},
|
|
115
|
-
data: desc.get_description()
|
|
131
|
+
data: desc.get_description(),
|
|
132
|
+
error: report_model_failure
|
|
116
133
|
});
|
|
117
134
|
format_instance_pos();
|
|
118
135
|
|