@processmaker/modeler 1.39.8 → 1.39.10
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.
- package/dist/img/proceC2.b229e6b6.svg +3 -0
- package/dist/modeler.common.js +3295 -401
- package/dist/modeler.common.js.map +1 -1
- package/dist/modeler.umd.js +3273 -379
- package/dist/modeler.umd.js.map +1 -1
- package/dist/modeler.umd.min.js +4 -4
- package/dist/modeler.umd.min.js.map +1 -1
- package/package.json +7 -6
- package/src/assets/corneaIcon.svg +3 -0
- package/src/assets/proceC2.svg +3 -0
- package/src/components/crown/crownButtons/crownColorDropdown.vue +5 -1
- package/src/components/crown/crownButtons/crownDropdowns.vue +5 -0
- package/src/components/crown/crownConfig/crownConfig.vue +5 -0
- package/src/components/iconColors.js +50 -9
- package/src/components/inspectors/InspectorPanel.vue +13 -2
- package/src/components/inspectors/PreviewPanel.vue +1 -1
- package/src/components/modeler/Modeler.vue +73 -14
- package/src/components/modeler/Selection.vue +19 -0
- package/src/components/nodes/node.js +1 -1
- package/src/components/nodes/task/shape.js +4 -0
- package/src/components/nodes/task/task.vue +2 -0
- package/src/components/railBottom/controls/SubmenuPopper/SubmenuPopper.vue +7 -3
- package/src/components/rails/explorer-rail/nodeTypesLoop/nodeTypesLoop.vue +14 -4
- package/src/components/welcome/WelcomeMessage.vue +82 -0
- package/src/mixins/clickAndDrop.js +19 -9
- package/src/mixins/customIcon.js +23 -3
- package/src/mixins/iconHelper.js +14 -0
- package/src/multiplayer/multiplayer.js +135 -22
- package/src/multiplayer/room.js +1 -2
- package/src/setup/addLoopCharacteristics.js +4 -0
- package/src/setup/globals.js +1 -1
- package/src/setup/initialLoad.js +3 -0
|
@@ -3,10 +3,11 @@ import pinIcon from '@/assets/pin-angle.svg';
|
|
|
3
3
|
import pinFillIcon from '@/assets/pin-angle-fill.svg';
|
|
4
4
|
import nodeTypesStore from '@/nodeTypesStore';
|
|
5
5
|
import clickAndDrop from '@/mixins/clickAndDrop';
|
|
6
|
+
import iconHelper from '@/mixins/iconHelper';
|
|
6
7
|
|
|
7
8
|
export default {
|
|
8
9
|
name: 'NodeTypesLoop',
|
|
9
|
-
mixins: [clickAndDrop],
|
|
10
|
+
mixins: [clickAndDrop, iconHelper],
|
|
10
11
|
data() {
|
|
11
12
|
return {
|
|
12
13
|
pinIcon,
|
|
@@ -57,13 +58,15 @@ export default {
|
|
|
57
58
|
<template v-for="object in filteredNodes">
|
|
58
59
|
<div
|
|
59
60
|
class="node-types__item"
|
|
61
|
+
:class="{'node-types__item__highlight': object.type === 'processmaker-ai-assistant'}"
|
|
60
62
|
:data-test="object.type"
|
|
61
63
|
:key="object.id"
|
|
62
64
|
@mouseover="showPin = true"
|
|
63
65
|
@mouseleave="showPin = false"
|
|
64
66
|
@click.self="onClickHandler($event, object)"
|
|
65
67
|
>
|
|
66
|
-
<
|
|
68
|
+
<i v-if="!containsSvg(object.icon)" :class="object.icon" class="fa-lg"/>
|
|
69
|
+
<img v-else class="node-types__item__icon" :src="object.icon" :alt="$t(object.label)">
|
|
67
70
|
<span>{{ $t(object.label) }}</span>
|
|
68
71
|
<img
|
|
69
72
|
v-if="nodeTypeAlreadyPinned(object, object.type)"
|
|
@@ -88,13 +91,15 @@ export default {
|
|
|
88
91
|
<template v-for="pinnedObject in pinnedObjects">
|
|
89
92
|
<div
|
|
90
93
|
class="node-types__item"
|
|
94
|
+
:class="{'node-types__item__highlight': pinnedObject.type === 'processmaker-ai-assistant'}"
|
|
91
95
|
:data-test="pinnedObject.type"
|
|
92
96
|
:key="pinnedObject.id"
|
|
93
97
|
@mouseover="showPin = true"
|
|
94
98
|
@mouseleave="showPin = false"
|
|
95
99
|
@click.stop="onClickHandler($event, pinnedObject)"
|
|
96
100
|
>
|
|
97
|
-
<
|
|
101
|
+
<i v-if="!containsSvg(pinnedObject.icon)" :class="pinnedObject.icon" class="fa-lg"/>
|
|
102
|
+
<img v-else class="node-types__item__icon" :src="pinnedObject.icon" :alt="$t(pinnedObject.label)">
|
|
98
103
|
<span>{{ $t(pinnedObject.label) }}</span>
|
|
99
104
|
<img
|
|
100
105
|
:src="pinFillIcon"
|
|
@@ -110,13 +115,15 @@ export default {
|
|
|
110
115
|
<template v-for="nodeType in unpinnedObjects">
|
|
111
116
|
<div
|
|
112
117
|
class="node-types__item"
|
|
118
|
+
:class="{'node-types__item__highlight': nodeType.type === 'processmaker-ai-assistant'}"
|
|
113
119
|
:data-test="nodeType.type"
|
|
114
120
|
:key="nodeType.id"
|
|
115
121
|
@mouseover="showPin = true"
|
|
116
122
|
@mouseleave="showPin = false"
|
|
117
123
|
@click.stop="onClickHandler($event, nodeType)"
|
|
118
124
|
>
|
|
119
|
-
<
|
|
125
|
+
<i v-if="!containsSvg(nodeType.icon)" :class="nodeType.icon" class="fa-lg"/>
|
|
126
|
+
<img v-else class="node-types__item__icon" :src="nodeType.icon" :alt="$t(nodeType.label)">
|
|
120
127
|
<span>{{ $t(nodeType.label) }}</span>
|
|
121
128
|
<img
|
|
122
129
|
:src="pinIcon"
|
|
@@ -154,6 +161,9 @@ export default {
|
|
|
154
161
|
width: 1.5rem;
|
|
155
162
|
height: 1.5rem;
|
|
156
163
|
}
|
|
164
|
+
&__highlight {
|
|
165
|
+
background-color: #FFF4D3;
|
|
166
|
+
}
|
|
157
167
|
span {
|
|
158
168
|
margin-left: 0.8rem;
|
|
159
169
|
font-size: 13px;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="message d-flex flex-column w-100 align-items-center">
|
|
3
|
+
<div class="d-flex justify-content-center align-items-center flex-column justify-content-center">
|
|
4
|
+
<div class="w-100">
|
|
5
|
+
{{
|
|
6
|
+
$t("To start, click and drop objects to build the process you like.")
|
|
7
|
+
}}
|
|
8
|
+
</div>
|
|
9
|
+
<div class="justify-content-center align-items-center w-100 text-center my-4">
|
|
10
|
+
<div class="text-align-center d-flex text-center justify-content-center align-items-center">
|
|
11
|
+
<div class="hyphen" />
|
|
12
|
+
or
|
|
13
|
+
<div class="hyphen" />
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
</div>
|
|
17
|
+
<b-button class="new-process-btn d-flex flex-row p-2 align-items-center" @click="onClick">
|
|
18
|
+
<inline-svg :src="proceC2Icon" class="mx-2 ai-icon" />
|
|
19
|
+
<div class="mr-3">{{ $t("Kick-start a new process with our generative AI") }}</div>
|
|
20
|
+
<span class="fa fa-chevron-right" />
|
|
21
|
+
</b-button>
|
|
22
|
+
</div>
|
|
23
|
+
</template>
|
|
24
|
+
<script>
|
|
25
|
+
import InlineSvg from 'vue-inline-svg';
|
|
26
|
+
|
|
27
|
+
export default {
|
|
28
|
+
name: 'WelcomeMessage',
|
|
29
|
+
components: {
|
|
30
|
+
InlineSvg,
|
|
31
|
+
},
|
|
32
|
+
data() {
|
|
33
|
+
return {
|
|
34
|
+
proceC2Icon: require('@/assets/proceC2.svg'),
|
|
35
|
+
};
|
|
36
|
+
},
|
|
37
|
+
methods: {},
|
|
38
|
+
};
|
|
39
|
+
</script>
|
|
40
|
+
<style>
|
|
41
|
+
.message {
|
|
42
|
+
color: #5f666d;
|
|
43
|
+
font-style: italic;
|
|
44
|
+
line-height: 27px;
|
|
45
|
+
word-wrap: break-word;
|
|
46
|
+
position: absolute;
|
|
47
|
+
display: flex;
|
|
48
|
+
justify-content: center;
|
|
49
|
+
align-items: center;
|
|
50
|
+
left: 0;
|
|
51
|
+
border: 0 none;
|
|
52
|
+
z-index: 1;
|
|
53
|
+
font-size: 110%;
|
|
54
|
+
font-weight: 100;
|
|
55
|
+
height: calc(100% - 130px);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.hyphen {
|
|
59
|
+
transform: rotate(0deg);
|
|
60
|
+
transform-origin: 0 0;
|
|
61
|
+
border: 1px #5f666d solid;
|
|
62
|
+
width: 30px;
|
|
63
|
+
margin: 5px 13px 0px 13px;
|
|
64
|
+
}
|
|
65
|
+
.new-process-btn {
|
|
66
|
+
color: #0872C2;
|
|
67
|
+
border-color: #0872C2;
|
|
68
|
+
background-color: #ffffff;
|
|
69
|
+
box-shadow: 0 3px 9px -3px #c2c2c2;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.new-process-btn:hover {
|
|
73
|
+
background-color: #edf7ff;
|
|
74
|
+
color: #0872C2;
|
|
75
|
+
border-color: #0872C2;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.ai-icon {
|
|
79
|
+
width: 22px;
|
|
80
|
+
height: 22px;
|
|
81
|
+
}
|
|
82
|
+
</style>
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import nodeTypesStore from '@/nodeTypesStore';
|
|
2
|
+
import iconHelper from '@/mixins/iconHelper';
|
|
2
3
|
|
|
3
4
|
export default {
|
|
5
|
+
mixins: [iconHelper],
|
|
4
6
|
data() {
|
|
5
7
|
return {
|
|
6
8
|
wasClicked: false,
|
|
@@ -68,20 +70,28 @@ export default {
|
|
|
68
70
|
nodeTypesStore.commit('setGhostNode', tempGhost);
|
|
69
71
|
},
|
|
70
72
|
createDraggingHelper(event, control) {
|
|
73
|
+
|
|
71
74
|
if (this.movedElement) {
|
|
72
75
|
document.removeEventListener('mousemove', this.setDraggingPosition);
|
|
73
76
|
document.body.removeChild(this.movedElement);
|
|
74
|
-
nodeTypesStore.commit('setGhostNode', null);
|
|
75
77
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
78
|
+
|
|
79
|
+
const isSvgIcon = this.containsSvg(control.icon);
|
|
80
|
+
const tempGhost = isSvgIcon ? document.createElement('img') : document.createElement('i');
|
|
81
|
+
|
|
82
|
+
Object.assign(tempGhost.style, this.helperStyles);
|
|
83
|
+
|
|
84
|
+
// Set the appropriate attribute or property based on the control icon type
|
|
85
|
+
if (isSvgIcon) {
|
|
86
|
+
tempGhost.src = control.icon;
|
|
87
|
+
} else {
|
|
88
|
+
tempGhost.setAttribute('class', control.icon);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
document.body.appendChild(tempGhost);
|
|
83
92
|
nodeTypesStore.commit('setGhostNode', tempGhost);
|
|
84
|
-
|
|
93
|
+
|
|
94
|
+
const sourceElement = event.target;
|
|
85
95
|
this.xOffset = event.clientX - sourceElement.getBoundingClientRect().left;
|
|
86
96
|
this.yOffset = event.clientY - sourceElement.getBoundingClientRect().top;
|
|
87
97
|
},
|
package/src/mixins/customIcon.js
CHANGED
|
@@ -6,6 +6,13 @@ export default {
|
|
|
6
6
|
iconName: '',
|
|
7
7
|
};
|
|
8
8
|
},
|
|
9
|
+
watch: {
|
|
10
|
+
shape() {
|
|
11
|
+
if (this.node.definition.get('customIcon')) {
|
|
12
|
+
this.setCustomIcon(this.node.definition.get('customIcon'));
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
},
|
|
9
16
|
|
|
10
17
|
methods: {
|
|
11
18
|
setCustomIconName(iconName) {
|
|
@@ -14,11 +21,24 @@ export default {
|
|
|
14
21
|
resetCustomIconName() {
|
|
15
22
|
this.setCustomIconName('');
|
|
16
23
|
},
|
|
17
|
-
setCustomIcon(
|
|
18
|
-
if (!this.shape){
|
|
24
|
+
setCustomIcon(icon) {
|
|
25
|
+
if (!this.shape) {
|
|
19
26
|
return;
|
|
20
27
|
}
|
|
21
|
-
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
const decodedIcon = atob(icon);
|
|
31
|
+
this.updateIcon(decodedIcon);
|
|
32
|
+
} catch (error) {
|
|
33
|
+
this.updateIcon(icon);
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
updateIcon(icon) {
|
|
37
|
+
const iconURL = this.getIconURL(icon);
|
|
38
|
+
this.shape.attr('image/xlink:href', iconURL);
|
|
39
|
+
},
|
|
40
|
+
getIconURL(icon) {
|
|
41
|
+
return coloredIcon(icon, this.node);
|
|
22
42
|
},
|
|
23
43
|
},
|
|
24
44
|
mounted() {
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
methods: {
|
|
3
|
+
containsSvg(icon) {
|
|
4
|
+
// Regular expression to match a URL pattern
|
|
5
|
+
const urlPattern = /^(https?:\/\/)?([\w-]+(\.[\w-]+)+)(\/[\w@?^=%&:/~+#-]*)*$/;
|
|
6
|
+
|
|
7
|
+
// Regular expression to check if the string contains '.svg'
|
|
8
|
+
const svgPattern = /\.svg/;
|
|
9
|
+
|
|
10
|
+
// Check if the variable is a string and either a URL or contains '.svg'
|
|
11
|
+
return typeof icon === 'string' && (urlPattern.test(icon) || svgPattern.test(icon));
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
};
|
|
@@ -1,48 +1,161 @@
|
|
|
1
|
+
import { io } from 'socket.io-client';
|
|
1
2
|
import * as Y from 'yjs';
|
|
2
|
-
import { WebsocketProvider } from 'y-websocket';
|
|
3
3
|
import { getNodeIdGenerator } from '../NodeIdGenerator';
|
|
4
4
|
import Room from './room';
|
|
5
5
|
export default class Multiplayer {
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
clientIO = null;
|
|
7
|
+
yDoc = null;
|
|
8
|
+
yArray = null;
|
|
8
9
|
modeler = null;
|
|
9
10
|
#nodeIdGenerator = null;
|
|
10
11
|
room = null;
|
|
12
|
+
deletedItem = null;
|
|
13
|
+
|
|
11
14
|
constructor(modeler) {
|
|
12
15
|
// define document
|
|
13
|
-
this.
|
|
16
|
+
this.yDoc = new Y.Doc();
|
|
17
|
+
// Create a shared array
|
|
18
|
+
this.yArray = this.yDoc.getArray('elements');
|
|
19
|
+
// Create a Modeler instance
|
|
14
20
|
this.modeler = modeler;
|
|
15
21
|
}
|
|
16
22
|
init() {
|
|
23
|
+
// Get the node id generator
|
|
17
24
|
this.#nodeIdGenerator = getNodeIdGenerator(this.modeler.definitions);
|
|
25
|
+
// Get the room name from the process id
|
|
26
|
+
this.room = new Room(`room-${window.ProcessMaker.modeler.process.id}`);
|
|
18
27
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
28
|
+
// Connect to websocket server
|
|
29
|
+
this.clientIO = io(process.env.VUE_APP_WEBSOCKET_PROVIDER, { transports: ['websocket', 'polling']});
|
|
30
|
+
|
|
31
|
+
this.clientIO.on('connect', () => {
|
|
32
|
+
// Join the room
|
|
33
|
+
this.clientIO.emit('joinRoom', this.room.getRoom());
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// Listen for updates when a new element is added
|
|
37
|
+
this.clientIO.on('createElement', async(payload) => {
|
|
38
|
+
// Create the new element in the process
|
|
39
|
+
await this.createRemoteShape(payload.changes);
|
|
40
|
+
// Add the new element to the shared array
|
|
41
|
+
Y.applyUpdate(this.yDoc, new Uint8Array(payload.updateDoc));
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// Listen for updates when an element is removed
|
|
45
|
+
this.clientIO.on('removeElement', (payload) => {
|
|
46
|
+
payload.deletedNodes.forEach(nodeId => {
|
|
47
|
+
// Get the node id
|
|
48
|
+
const node = this.getNodeById(nodeId);
|
|
49
|
+
// Remove the element from the process
|
|
50
|
+
this.removeShape(node);
|
|
35
51
|
});
|
|
52
|
+
// Remove the element from the shared array
|
|
53
|
+
Y.applyUpdate(this.yDoc, new Uint8Array(payload.updateDoc));
|
|
36
54
|
});
|
|
55
|
+
|
|
37
56
|
window.ProcessMaker.EventBus.$on('multiplayer-addNode', ( data ) => {
|
|
38
57
|
this.addNode(data);
|
|
39
58
|
});
|
|
59
|
+
|
|
60
|
+
window.ProcessMaker.EventBus.$on('multiplayer-removeNode', ( data ) => {
|
|
61
|
+
this.removeNode(data);
|
|
62
|
+
});
|
|
63
|
+
window.ProcessMaker.EventBus.$on('multiplayer-updateNodes', ( data ) => {
|
|
64
|
+
this.updateNodes(data);
|
|
65
|
+
});
|
|
40
66
|
}
|
|
41
67
|
addNode(data) {
|
|
42
|
-
|
|
43
|
-
|
|
68
|
+
// Add the new element to the process
|
|
69
|
+
this.createShape(data);
|
|
70
|
+
// Add the new element to the shared array
|
|
71
|
+
// this.yArray.push([data]);
|
|
72
|
+
const yMapNested = new Y.Map();
|
|
73
|
+
this.doTransact(yMapNested, data);
|
|
74
|
+
this.yArray.push([yMapNested]);
|
|
75
|
+
// Encode the state as an update and send it to the server
|
|
76
|
+
const stateUpdate = Y.encodeStateAsUpdate(this.yDoc);
|
|
77
|
+
// Send the update to the web socket server
|
|
78
|
+
this.clientIO.emit('createElement', stateUpdate);
|
|
44
79
|
}
|
|
45
80
|
createShape(value) {
|
|
46
81
|
this.modeler.handleDropProcedure(value, false);
|
|
82
|
+
this.#nodeIdGenerator.updateCounters();
|
|
83
|
+
}
|
|
84
|
+
createRemoteShape(changes) {
|
|
85
|
+
return new Promise(resolve => {
|
|
86
|
+
changes.map((data) => {
|
|
87
|
+
this.createShape(data);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
resolve();
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
removeNode(data) {
|
|
94
|
+
const index = this.getIndex(data.definition.id);
|
|
95
|
+
this.removeShape(data);
|
|
96
|
+
this.yArray.delete(index, 1); // delete one element
|
|
97
|
+
|
|
98
|
+
// Encode the state as an update and send it to the server
|
|
99
|
+
const stateUpdate = Y.encodeStateAsUpdate(this.yDoc);
|
|
100
|
+
// Send the update to the web socket server
|
|
101
|
+
this.clientIO.emit('removeElement', stateUpdate);
|
|
102
|
+
}
|
|
103
|
+
getIndex(id) {
|
|
104
|
+
let index = -1;
|
|
105
|
+
for (const value of this.yArray) {
|
|
106
|
+
index ++;
|
|
107
|
+
if (value.get('id') === id) {
|
|
108
|
+
break ;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return index;
|
|
112
|
+
}
|
|
113
|
+
getNodeById(nodeId) {
|
|
114
|
+
const node = this.modeler.nodes.find((element) => element.definition && element.definition.id === nodeId);
|
|
115
|
+
|
|
116
|
+
return node;
|
|
117
|
+
}
|
|
118
|
+
removeShape(node) {
|
|
119
|
+
this.modeler.removeNodeProcedure(node, true);
|
|
120
|
+
}
|
|
121
|
+
getRemovedNodes(array1, array2) {
|
|
122
|
+
return array1.filter(object1 => {
|
|
123
|
+
return !array2.some(object2 => {
|
|
124
|
+
return object1.definition.id === object2.get('id');
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
updateNodes(data) {
|
|
129
|
+
data.forEach((value) => {
|
|
130
|
+
const index = this.getIndex(value.id);
|
|
131
|
+
const nodeToUpdate = this.yarray.get(index);
|
|
132
|
+
this.doTransact(nodeToUpdate, value.properties);
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
doTransact(yMapNested, data) {
|
|
136
|
+
this.yDoc.transact(() => {
|
|
137
|
+
for (const key in data) {
|
|
138
|
+
if (Object.prototype.hasOwnProperty.call(data, key)) {
|
|
139
|
+
yMapNested.set(key, data[key]);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
updateShapes(data) {
|
|
145
|
+
const { paper } = this.modeler;
|
|
146
|
+
const element = this.getJointElement(paper.model, data.id);
|
|
147
|
+
// Update the element's position attribute
|
|
148
|
+
element.set('position', { x:data.clientX, y:data.clientY });
|
|
149
|
+
// Trigger a rendering of the element on the paper
|
|
150
|
+
paper.findViewByModel(element).update();
|
|
151
|
+
}
|
|
152
|
+
getJointElement(graph, targetValue) {
|
|
153
|
+
const cells = graph.getCells();
|
|
154
|
+
for (const cell of cells) {
|
|
155
|
+
if (cell.component.id === targetValue) {
|
|
156
|
+
return cell;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return null; // Return null if no matching element is found
|
|
47
160
|
}
|
|
48
161
|
}
|
package/src/multiplayer/room.js
CHANGED
|
@@ -16,6 +16,10 @@ export default (node) => {
|
|
|
16
16
|
return;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
if (node.implementation === 'package-ai/processmaker-ai-assistant') {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
19
23
|
// Insert the loop config inspector at the specified index
|
|
20
24
|
node.inspectorConfig[0].items.splice(node.loopInspectorIndex || 1, 0, loopCharacteristicsInspector);
|
|
21
25
|
|
package/src/setup/globals.js
CHANGED
package/src/setup/initialLoad.js
CHANGED
|
@@ -20,6 +20,9 @@ window.ProcessMaker.EventBus.$on('modeler-init', registerNodes);
|
|
|
20
20
|
window.ProcessMaker.EventBus.$on('modeler-start', ({ loadXML }) => {
|
|
21
21
|
loadXML(blank);
|
|
22
22
|
});
|
|
23
|
+
/**
|
|
24
|
+
* TODO: Remove this block when the collaborative mode will be dynamic
|
|
25
|
+
*/
|
|
23
26
|
window.ProcessMaker.EventBus.$on('multiplayer-start', (params) => {
|
|
24
27
|
const multiplayer = new Multiplayer(params.modeler);
|
|
25
28
|
multiplayer.init();
|