@processmaker/modeler 1.39.19 → 1.39.21
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/modeler.common.js +563 -443
- package/dist/modeler.common.js.map +1 -1
- package/dist/modeler.umd.js +563 -443
- package/dist/modeler.umd.js.map +1 -1
- package/dist/modeler.umd.min.js +3 -3
- package/dist/modeler.umd.min.js.map +1 -1
- package/package.json +1 -1
- package/src/components/crown/crownButtons/crownColorDropdown.vue +14 -0
- package/src/components/modeler/Modeler.vue +53 -24
- package/src/components/modeler/Selection.vue +2 -0
- package/src/multiplayer/multiplayer.js +39 -4
package/package.json
CHANGED
|
@@ -137,6 +137,20 @@ export default {
|
|
|
137
137
|
store.commit('updateNodeProp', { node: this.node, key: 'color', value: color });
|
|
138
138
|
Vue.set(this.node.definition, 'color', color);
|
|
139
139
|
this.$emit('save-state');
|
|
140
|
+
|
|
141
|
+
const properties = {
|
|
142
|
+
id: this.node.definition.id,
|
|
143
|
+
properties: {
|
|
144
|
+
color: this.node.definition.color,
|
|
145
|
+
x: this.node.diagram.bounds.x,
|
|
146
|
+
y: this.node.diagram.bounds.y,
|
|
147
|
+
height: this.node.diagram.bounds.height,
|
|
148
|
+
width: this.node.diagram.bounds.width,
|
|
149
|
+
type: this.node.type,
|
|
150
|
+
id: this.node.definition.id,
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
window.ProcessMaker.EventBus.$emit('multiplayer-updateNodes', [properties]);
|
|
140
154
|
},
|
|
141
155
|
resetNodeColor() {
|
|
142
156
|
store.commit('updateNodeProp', { node: this.node, key: 'color', value: undefined });
|
|
@@ -952,7 +952,25 @@ export default {
|
|
|
952
952
|
},
|
|
953
953
|
async createNodeAsync(type, definition, diagram) {
|
|
954
954
|
const node = this.createNode(type, definition, diagram);
|
|
955
|
+
if (!this.isMultiplayer) {
|
|
956
|
+
store.commit('addNode', node);
|
|
957
|
+
}
|
|
958
|
+
else {
|
|
959
|
+
this.loadNodeForMultiplayer(node);
|
|
960
|
+
}
|
|
961
|
+
},
|
|
962
|
+
async loadNodeForMultiplayer(node) {
|
|
963
|
+
if (node.type === 'processmaker-modeler-lane') {
|
|
964
|
+
await this.addNode(node, node.definition.id, true);
|
|
965
|
+
this.nodeIdGenerator.updateCounters();
|
|
966
|
+
await this.$nextTick();
|
|
967
|
+
await this.paperManager.awaitScheduledUpdates();
|
|
968
|
+
window.ProcessMaker.EventBus.$emit('multiplayer-addLanes', [node]);
|
|
969
|
+
return;
|
|
970
|
+
}
|
|
971
|
+
this.multiplayerHook(node, false);
|
|
955
972
|
store.commit('addNode', node);
|
|
973
|
+
this.poolTarget = null;
|
|
956
974
|
},
|
|
957
975
|
createNode(type, definition, diagram) {
|
|
958
976
|
if (Node.isTimerType(type)) {
|
|
@@ -1112,7 +1130,7 @@ export default {
|
|
|
1112
1130
|
const view = newNodeComponent.shapeView;
|
|
1113
1131
|
await this.$refs.selector.selectElement(view);
|
|
1114
1132
|
},
|
|
1115
|
-
multiplayerHook(node, fromClient) {
|
|
1133
|
+
multiplayerHook(node, fromClient, isProcessRequested = false) {
|
|
1116
1134
|
const blackList = [
|
|
1117
1135
|
'processmaker-modeler-lane',
|
|
1118
1136
|
'processmaker-modeler-generic-flow',
|
|
@@ -1136,10 +1154,16 @@ export default {
|
|
|
1136
1154
|
type: node.type,
|
|
1137
1155
|
id: node.definition.id,
|
|
1138
1156
|
isAddingLaneAbove: true,
|
|
1157
|
+
color: node.color,
|
|
1139
1158
|
};
|
|
1140
1159
|
if (node?.pool?.component) {
|
|
1141
1160
|
defaultData['poolId'] = node.pool.component.id;
|
|
1142
1161
|
}
|
|
1162
|
+
|
|
1163
|
+
if (isProcessRequested) {
|
|
1164
|
+
return defaultData;
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1143
1167
|
window.ProcessMaker.EventBus.$emit('multiplayer-addNode', defaultData);
|
|
1144
1168
|
}
|
|
1145
1169
|
if (this.flowTypes.includes(node.type)) {
|
|
@@ -1148,17 +1172,23 @@ export default {
|
|
|
1148
1172
|
|
|
1149
1173
|
if (node.type === 'processmaker-modeler-data-input-association') {
|
|
1150
1174
|
sourceRefId = Array.isArray(node.definition.sourceRef) && node.definition.sourceRef[0]?.id;
|
|
1151
|
-
targetRefId = node.definition.targetRef?.$parent?.$parent
|
|
1175
|
+
targetRefId = node.definition.targetRef?.$parent?.$parent?.get('id');
|
|
1152
1176
|
}
|
|
1153
1177
|
|
|
1154
1178
|
if (sourceRefId && targetRefId) {
|
|
1155
|
-
|
|
1179
|
+
const flowData = {
|
|
1156
1180
|
id: node.definition.id,
|
|
1157
1181
|
type: node.type,
|
|
1158
1182
|
sourceRefId,
|
|
1159
1183
|
targetRefId,
|
|
1160
1184
|
waypoint: node.diagram.waypoint,
|
|
1161
|
-
}
|
|
1185
|
+
};
|
|
1186
|
+
|
|
1187
|
+
if (isProcessRequested) {
|
|
1188
|
+
return flowData;
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
window.ProcessMaker.EventBus.$emit('multiplayer-addFlow', flowData);
|
|
1162
1192
|
}
|
|
1163
1193
|
}
|
|
1164
1194
|
}
|
|
@@ -1281,36 +1311,34 @@ export default {
|
|
|
1281
1311
|
nodeThatWillBeReplaced: node,
|
|
1282
1312
|
};
|
|
1283
1313
|
|
|
1284
|
-
|
|
1285
|
-
// Get all node types
|
|
1286
|
-
const nodeTypes = nodeTypesStore.getters.getNodeTypes;
|
|
1287
|
-
// Get the new control
|
|
1288
|
-
const newControl = nodeTypes.flatMap(nodeType => {
|
|
1289
|
-
return nodeType.items?.filter(item => item.type === typeToReplaceWith);
|
|
1290
|
-
}).filter(Boolean);
|
|
1291
|
-
// If the new control is found, emit event to server to replace node
|
|
1292
|
-
if (newControl.length === 1) {
|
|
1293
|
-
window.ProcessMaker.EventBus.$emit('multiplayer-replaceNode', { nodeData, newControl: newControl[0].type });
|
|
1294
|
-
}
|
|
1295
|
-
} else {
|
|
1296
|
-
await this.replaceNodeProcedure(nodeData, true);
|
|
1297
|
-
}
|
|
1314
|
+
await this.replaceNodeProcedure(nodeData);
|
|
1298
1315
|
});
|
|
1299
1316
|
});
|
|
1300
1317
|
},
|
|
1301
1318
|
async replaceNodeProcedure(data, isReplaced = false) {
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
data.clientY = clientY;
|
|
1307
|
-
}
|
|
1319
|
+
// Get the clientX and clientY from the node that will be replaced
|
|
1320
|
+
const { x: clientX, y: clientY } = this.paper.localToClientPoint(data.nodeThatWillBeReplaced.diagram.bounds);
|
|
1321
|
+
data.clientX = clientX;
|
|
1322
|
+
data.clientY = clientY;
|
|
1308
1323
|
|
|
1309
1324
|
const newNode = await this.handleDrop(data);
|
|
1310
1325
|
|
|
1311
1326
|
await this.removeNode(data.nodeThatWillBeReplaced, { removeRelationships: false, isReplaced });
|
|
1312
1327
|
this.highlightNode(newNode);
|
|
1313
1328
|
this.selectNewNode(newNode);
|
|
1329
|
+
|
|
1330
|
+
if (this.isMultiplayer && !isReplaced) {
|
|
1331
|
+
// Get all node types
|
|
1332
|
+
const nodeTypes = nodeTypesStore.getters.getNodeTypes;
|
|
1333
|
+
// Get the new control
|
|
1334
|
+
const newControl = nodeTypes.flatMap(nodeType => {
|
|
1335
|
+
return nodeType.items?.filter(item => item.type === data.typeToReplaceWith);
|
|
1336
|
+
}).filter(Boolean);
|
|
1337
|
+
// If the new control is found, emit event to server to replace node
|
|
1338
|
+
if (newControl.length === 1) {
|
|
1339
|
+
window.ProcessMaker.EventBus.$emit('multiplayer-replaceNode', { data, newControl: newControl[0].type });
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1314
1342
|
},
|
|
1315
1343
|
replaceAiNode({ node, typeToReplaceWith, assetId, assetName, redirectTo }) {
|
|
1316
1344
|
this.performSingleUndoRedoTransaction(async() => {
|
|
@@ -1727,6 +1755,7 @@ export default {
|
|
|
1727
1755
|
try {
|
|
1728
1756
|
const multiplayer = new Multiplayer(this);
|
|
1729
1757
|
multiplayer.init();
|
|
1758
|
+
this.multiplayer = multiplayer;
|
|
1730
1759
|
} catch (error) {
|
|
1731
1760
|
console.warn('Could not initialize multiplayer', error);
|
|
1732
1761
|
}
|
|
@@ -604,6 +604,7 @@ export default {
|
|
|
604
604
|
y: shape.model.get('position').y,
|
|
605
605
|
height: shape.model.get('size').height,
|
|
606
606
|
width: shape.model.get('size').width,
|
|
607
|
+
color: shape.model.get('color'),
|
|
607
608
|
},
|
|
608
609
|
};
|
|
609
610
|
if (node?.pool?.component) {
|
|
@@ -624,6 +625,7 @@ export default {
|
|
|
624
625
|
y: model.get('position').y,
|
|
625
626
|
height: model.get('size').height,
|
|
626
627
|
width: model.get('size').width,
|
|
628
|
+
color: model.get('color'),
|
|
627
629
|
},
|
|
628
630
|
});
|
|
629
631
|
});
|
|
@@ -3,7 +3,7 @@ import * as Y from 'yjs';
|
|
|
3
3
|
import { getNodeIdGenerator } from '../NodeIdGenerator';
|
|
4
4
|
import { getDefaultAnchorPoint } from '@/portsUtils';
|
|
5
5
|
import Room from './room';
|
|
6
|
-
|
|
6
|
+
import store from '@/store';
|
|
7
7
|
export default class Multiplayer {
|
|
8
8
|
clientIO = null;
|
|
9
9
|
yDoc = null;
|
|
@@ -66,6 +66,26 @@ export default class Multiplayer {
|
|
|
66
66
|
this.modeler.enableMultiplayer(payload.isMultiplayer);
|
|
67
67
|
});
|
|
68
68
|
|
|
69
|
+
this.clientIO.on('requestProcess', (payload) => {
|
|
70
|
+
const { firstClient, clientId } = payload;
|
|
71
|
+
|
|
72
|
+
// Check if the current client is the first client
|
|
73
|
+
if (firstClient.id === this.clientIO.id) {
|
|
74
|
+
// Get the process definition
|
|
75
|
+
const nodes = this.modeler.nodes.map((node) => this.modeler.multiplayerHook(node, false, true));
|
|
76
|
+
|
|
77
|
+
nodes.forEach((node) => {
|
|
78
|
+
const yMapNested = new Y.Map();
|
|
79
|
+
this.doTransact(yMapNested, node);
|
|
80
|
+
this.yArray.push([yMapNested]);
|
|
81
|
+
// Encode the state as an update and send it to the server
|
|
82
|
+
const stateUpdate = Y.encodeStateAsUpdate(this.yDoc);
|
|
83
|
+
// Send the update to the web socket server
|
|
84
|
+
this.clientIO.emit('createElement', { updateDoc: stateUpdate, clientId });
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
|
|
69
89
|
// Listen for updates when a new element is added
|
|
70
90
|
this.clientIO.on('createElement', async(payload) => {
|
|
71
91
|
// Create the new element in the process
|
|
@@ -74,6 +94,16 @@ export default class Multiplayer {
|
|
|
74
94
|
Y.applyUpdate(this.yDoc, new Uint8Array(payload.updateDoc));
|
|
75
95
|
});
|
|
76
96
|
|
|
97
|
+
// Listen for updates when a new element is requested
|
|
98
|
+
this.clientIO.on('createRequestedElement', async(payload) => {
|
|
99
|
+
if (payload.clientId === this.clientIO.id) {
|
|
100
|
+
// Create the new element in the process
|
|
101
|
+
await this.createRemoteShape(payload.changes);
|
|
102
|
+
// Add the new element to the shared array
|
|
103
|
+
Y.applyUpdate(this.yDoc, new Uint8Array(payload.updateDoc));
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
|
|
77
107
|
// Listen for updates when an element is removed
|
|
78
108
|
this.clientIO.on('removeElement', (payload) => {
|
|
79
109
|
payload.deletedNodes.forEach(nodeId => {
|
|
@@ -135,7 +165,7 @@ export default class Multiplayer {
|
|
|
135
165
|
// Encode the state as an update and send it to the server
|
|
136
166
|
const stateUpdate = Y.encodeStateAsUpdate(this.yDoc);
|
|
137
167
|
// Send the update to the web socket server
|
|
138
|
-
this.clientIO.emit('createElement', stateUpdate);
|
|
168
|
+
this.clientIO.emit('createElement', { updateDoc: stateUpdate });
|
|
139
169
|
}
|
|
140
170
|
createShape(value){
|
|
141
171
|
if (this.modeler.nodeRegistry[value.type] && this.modeler.nodeRegistry[value.type].multiplayerClient) {
|
|
@@ -229,6 +259,7 @@ export default class Multiplayer {
|
|
|
229
259
|
clientY,
|
|
230
260
|
control: { type: updatedNode.type },
|
|
231
261
|
nodeThatWillBeReplaced: node,
|
|
262
|
+
color: node.color,
|
|
232
263
|
id: updatedNode.id,
|
|
233
264
|
};
|
|
234
265
|
|
|
@@ -292,6 +323,10 @@ export default class Multiplayer {
|
|
|
292
323
|
data.height,
|
|
293
324
|
);
|
|
294
325
|
element.set('position', { x: data.x, y: data.y });
|
|
326
|
+
|
|
327
|
+
const node = this.getNodeById(data.id);
|
|
328
|
+
store.commit('updateNodeProp', { node, key: 'color', value: data.color });
|
|
329
|
+
|
|
295
330
|
// Trigger a rendering of the element on the paper
|
|
296
331
|
await paper.findViewByModel(element).update();
|
|
297
332
|
// validate if the parent pool was updated
|
|
@@ -310,7 +345,7 @@ export default class Multiplayer {
|
|
|
310
345
|
// Encode the state as an update and send it to the server
|
|
311
346
|
const stateUpdate = Y.encodeStateAsUpdate(this.yDoc);
|
|
312
347
|
// Send the update to the web socket server
|
|
313
|
-
this.clientIO.emit('createElement', stateUpdate);
|
|
348
|
+
this.clientIO.emit('createElement', { updateDoc: stateUpdate });
|
|
314
349
|
this.#nodeIdGenerator.updateCounters();
|
|
315
350
|
}
|
|
316
351
|
|
|
@@ -333,7 +368,7 @@ export default class Multiplayer {
|
|
|
333
368
|
this.doTransact(yMapNested, data);
|
|
334
369
|
this.yArray.push([yMapNested]);
|
|
335
370
|
const stateUpdate = Y.encodeStateAsUpdate(this.yDoc);
|
|
336
|
-
this.clientIO.emit('createElement', stateUpdate);
|
|
371
|
+
this.clientIO.emit('createElement', { updateDoc: stateUpdate });
|
|
337
372
|
});
|
|
338
373
|
});
|
|
339
374
|
}
|