@processmaker/modeler 1.39.9 → 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 +653 -283
- package/dist/modeler.common.js.map +1 -1
- package/dist/modeler.umd.js +666 -288
- 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 +4 -4
- 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 +61 -10
- 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 +76 -54
- package/src/setup/addLoopCharacteristics.js +4 -0
- package/src/setup/initialLoad.js +3 -0
|
@@ -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,66 +1,62 @@
|
|
|
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;
|
|
11
12
|
deletedItem = null;
|
|
13
|
+
|
|
12
14
|
constructor(modeler) {
|
|
13
15
|
// define document
|
|
14
|
-
this.
|
|
16
|
+
this.yDoc = new Y.Doc();
|
|
17
|
+
// Create a shared array
|
|
18
|
+
this.yArray = this.yDoc.getArray('elements');
|
|
19
|
+
// Create a Modeler instance
|
|
15
20
|
this.modeler = modeler;
|
|
16
21
|
}
|
|
17
22
|
init() {
|
|
23
|
+
// Get the node id generator
|
|
18
24
|
this.#nodeIdGenerator = getNodeIdGenerator(this.modeler.definitions);
|
|
19
|
-
|
|
25
|
+
// Get the room name from the process id
|
|
20
26
|
this.room = new Room(`room-${window.ProcessMaker.modeler.process.id}`);
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
27
|
+
|
|
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());
|
|
24
34
|
});
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
this.createShape(value.toJSON());
|
|
33
|
-
this.#nodeIdGenerator.updateCounters();
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
});
|
|
37
|
-
// remove nodes observer
|
|
38
|
-
if (event.changes.deleted && event.changes.deleted.size > 0) {
|
|
39
|
-
this.removeShape();
|
|
40
|
-
}
|
|
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));
|
|
41
42
|
});
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
newProperties[key] = ymapNested.get(key);
|
|
51
|
-
} else if (change.action === 'delete') {
|
|
52
|
-
// TODO delete propertiees
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
if (Object.keys(newProperties).length > 0 ) {
|
|
56
|
-
newProperties['id'] = ymapNested.get('id');
|
|
57
|
-
this.updateShapes(newProperties);
|
|
58
|
-
}
|
|
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);
|
|
59
51
|
});
|
|
52
|
+
// Remove the element from the shared array
|
|
53
|
+
Y.applyUpdate(this.yDoc, new Uint8Array(payload.updateDoc));
|
|
60
54
|
});
|
|
55
|
+
|
|
61
56
|
window.ProcessMaker.EventBus.$on('multiplayer-addNode', ( data ) => {
|
|
62
57
|
this.addNode(data);
|
|
63
58
|
});
|
|
59
|
+
|
|
64
60
|
window.ProcessMaker.EventBus.$on('multiplayer-removeNode', ( data ) => {
|
|
65
61
|
this.removeNode(data);
|
|
66
62
|
});
|
|
@@ -69,20 +65,44 @@ export default class Multiplayer {
|
|
|
69
65
|
});
|
|
70
66
|
}
|
|
71
67
|
addNode(data) {
|
|
72
|
-
|
|
73
|
-
this.
|
|
74
|
-
|
|
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);
|
|
75
79
|
}
|
|
76
80
|
createShape(value) {
|
|
77
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
|
+
});
|
|
78
92
|
}
|
|
79
93
|
removeNode(data) {
|
|
80
94
|
const index = this.getIndex(data.definition.id);
|
|
81
|
-
this.
|
|
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);
|
|
82
102
|
}
|
|
83
103
|
getIndex(id) {
|
|
84
104
|
let index = -1;
|
|
85
|
-
for (const value of this.
|
|
105
|
+
for (const value of this.yArray) {
|
|
86
106
|
index ++;
|
|
87
107
|
if (value.get('id') === id) {
|
|
88
108
|
break ;
|
|
@@ -90,11 +110,13 @@ export default class Multiplayer {
|
|
|
90
110
|
}
|
|
91
111
|
return index;
|
|
92
112
|
}
|
|
93
|
-
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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);
|
|
98
120
|
}
|
|
99
121
|
getRemovedNodes(array1, array2) {
|
|
100
122
|
return array1.filter(object1 => {
|
|
@@ -110,11 +132,11 @@ export default class Multiplayer {
|
|
|
110
132
|
this.doTransact(nodeToUpdate, value.properties);
|
|
111
133
|
});
|
|
112
134
|
}
|
|
113
|
-
doTransact(
|
|
114
|
-
this.
|
|
135
|
+
doTransact(yMapNested, data) {
|
|
136
|
+
this.yDoc.transact(() => {
|
|
115
137
|
for (const key in data) {
|
|
116
138
|
if (Object.prototype.hasOwnProperty.call(data, key)) {
|
|
117
|
-
|
|
139
|
+
yMapNested.set(key, data[key]);
|
|
118
140
|
}
|
|
119
141
|
}
|
|
120
142
|
});
|
|
@@ -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/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();
|