@processmaker/modeler 1.39.17 → 1.39.18
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 +1255 -1007
- package/dist/modeler.common.js.map +1 -1
- package/dist/modeler.umd.js +1255 -1007
- 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 +1 -1
- package/src/components/crown/utils.js +10 -9
- package/src/components/modeler/Modeler.vue +76 -25
- package/src/components/modeler/Selection.vue +40 -13
- package/src/components/nodes/genericFlow/genericFlow.vue +0 -11
- package/src/components/nodes/messageFlow/index.js +16 -0
- package/src/components/nodes/pool/pool.vue +40 -10
- package/src/components/nodes/poolLane/index.js +36 -0
- package/src/components/nodes/sequenceFlow/index.js +15 -0
- package/src/components/topRail/multiplayerViewUsers/MultiplayerViewUsers.vue +1 -1
- package/src/mixins/linkConfig.js +0 -14
- package/src/mixins/poolLaneCrownConfig.js +0 -2
- package/src/multiplayer/multiplayer.js +93 -81
- package/src/nodeTypesStore.js +3 -3
- package/src/setup/globals.js +6 -0
|
@@ -2,27 +2,6 @@ import { io } from 'socket.io-client';
|
|
|
2
2
|
import * as Y from 'yjs';
|
|
3
3
|
import { getNodeIdGenerator } from '../NodeIdGenerator';
|
|
4
4
|
import Room from './room';
|
|
5
|
-
import MessageFlow from '@/components/nodes/genericFlow/MessageFlow';
|
|
6
|
-
import SequenceFlow from '@/components/nodes/genericFlow/SequenceFlow';
|
|
7
|
-
import DataOutputAssociation from '@/components/nodes/genericFlow/DataOutputAssociation';
|
|
8
|
-
const BpmnFlows = [
|
|
9
|
-
{
|
|
10
|
-
type: 'processmaker-modeler-text-annotation',
|
|
11
|
-
factory: DataOutputAssociation,
|
|
12
|
-
},
|
|
13
|
-
{
|
|
14
|
-
type: 'processmaker-modeler-sequence-flow',
|
|
15
|
-
factory: SequenceFlow,
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
type: 'processmaker-modeler-message-flow',
|
|
19
|
-
factory: MessageFlow,
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
type: 'processmaker-modeler-data-input-association',
|
|
23
|
-
factory: DataOutputAssociation,
|
|
24
|
-
},
|
|
25
|
-
];
|
|
26
5
|
export default class Multiplayer {
|
|
27
6
|
clientIO = null;
|
|
28
7
|
yDoc = null;
|
|
@@ -44,7 +23,8 @@ export default class Multiplayer {
|
|
|
44
23
|
// Get the node id generator
|
|
45
24
|
this.#nodeIdGenerator = getNodeIdGenerator(this.modeler.definitions);
|
|
46
25
|
// Get the room name from the process id
|
|
47
|
-
|
|
26
|
+
const processId = window.ProcessMaker.modeler.process.uuid ?? window.ProcessMaker.modeler.process.id;
|
|
27
|
+
this.room = new Room(`room-${processId}`);
|
|
48
28
|
|
|
49
29
|
// Connect to websocket server
|
|
50
30
|
this.clientIO = io(window.ProcessMaker.multiplayer.host, { transports: ['websocket', 'polling']});
|
|
@@ -53,8 +33,8 @@ export default class Multiplayer {
|
|
|
53
33
|
// Join the room
|
|
54
34
|
this.clientIO.emit('joinRoom', {
|
|
55
35
|
roomName: this.room.getRoom(),
|
|
56
|
-
clientName: window.ProcessMaker.user
|
|
57
|
-
clientAvatar: window.ProcessMaker.user
|
|
36
|
+
clientName: window.ProcessMaker.user?.fullName,
|
|
37
|
+
clientAvatar: window.ProcessMaker.user?.avatar,
|
|
58
38
|
});
|
|
59
39
|
});
|
|
60
40
|
|
|
@@ -140,12 +120,13 @@ export default class Multiplayer {
|
|
|
140
120
|
window.ProcessMaker.EventBus.$on('multiplayer-addFlow', ( data ) => {
|
|
141
121
|
this.addFlow(data);
|
|
142
122
|
});
|
|
123
|
+
|
|
124
|
+
window.ProcessMaker.EventBus.$on('multiplayer-addLanes', ( lanes ) => {
|
|
125
|
+
this.addLaneNodes(lanes);
|
|
126
|
+
});
|
|
143
127
|
}
|
|
144
128
|
addNode(data) {
|
|
145
|
-
// Add the new element to the process
|
|
146
|
-
this.createShape(data);
|
|
147
129
|
// Add the new element to the shared array
|
|
148
|
-
// this.yArray.push([data]);
|
|
149
130
|
const yMapNested = new Y.Map();
|
|
150
131
|
this.doTransact(yMapNested, data);
|
|
151
132
|
this.yArray.push([yMapNested]);
|
|
@@ -154,47 +135,45 @@ export default class Multiplayer {
|
|
|
154
135
|
// Send the update to the web socket server
|
|
155
136
|
this.clientIO.emit('createElement', stateUpdate);
|
|
156
137
|
}
|
|
157
|
-
createShape(value)
|
|
158
|
-
this.modeler.
|
|
138
|
+
createShape(value){
|
|
139
|
+
if (this.modeler.nodeRegistry[value.type] && this.modeler.nodeRegistry[value.type].multiplayerClient) {
|
|
140
|
+
this.modeler.nodeRegistry[value.type].multiplayerClient(this.modeler, value);
|
|
141
|
+
} else {
|
|
142
|
+
this.modeler.addRemoteNode(value);
|
|
143
|
+
}
|
|
159
144
|
this.#nodeIdGenerator.updateCounters();
|
|
145
|
+
|
|
160
146
|
}
|
|
161
147
|
createRemoteShape(changes) {
|
|
162
|
-
const flows = [
|
|
163
|
-
'processmaker-modeler-sequence-flow',
|
|
164
|
-
'processmaker-modeler-text-annotation',
|
|
165
|
-
'processmaker-modeler-message-flow',
|
|
166
|
-
'processmaker-modeler-data-input-association',
|
|
167
|
-
];
|
|
168
148
|
return new Promise(resolve => {
|
|
169
149
|
changes.map((data) => {
|
|
170
|
-
|
|
171
|
-
this.createFlow(data);
|
|
172
|
-
} else {
|
|
173
|
-
this.createShape(data);
|
|
174
|
-
}
|
|
150
|
+
this.createShape(data);
|
|
175
151
|
});
|
|
176
152
|
resolve();
|
|
177
153
|
});
|
|
178
154
|
}
|
|
179
155
|
removeNode(data) {
|
|
180
156
|
const index = this.getIndex(data.definition.id);
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
157
|
+
if (index >= 0) {
|
|
158
|
+
this.removeShape(data);
|
|
159
|
+
this.yArray.delete(index, 1); // delete one element
|
|
160
|
+
// Encode the state as an update and send it to the server
|
|
161
|
+
const stateUpdate = Y.encodeStateAsUpdate(this.yDoc);
|
|
162
|
+
// Send the update to the web socket server
|
|
163
|
+
this.clientIO.emit('removeElement', stateUpdate);
|
|
164
|
+
}
|
|
188
165
|
}
|
|
189
166
|
getIndex(id) {
|
|
190
167
|
let index = -1;
|
|
168
|
+
let found = false;
|
|
191
169
|
for (const value of this.yArray) {
|
|
192
170
|
index ++;
|
|
193
171
|
if (value.get('id') === id) {
|
|
172
|
+
found = true;
|
|
194
173
|
break ;
|
|
195
174
|
}
|
|
196
175
|
}
|
|
197
|
-
return index;
|
|
176
|
+
return found ? index : -1;
|
|
198
177
|
}
|
|
199
178
|
getNodeById(nodeId) {
|
|
200
179
|
const node = this.modeler.nodes.find((element) => element.definition && element.definition.id === nodeId);
|
|
@@ -215,7 +194,8 @@ export default class Multiplayer {
|
|
|
215
194
|
data.forEach((value) => {
|
|
216
195
|
const index = this.getIndex(value.id);
|
|
217
196
|
const nodeToUpdate = this.yArray.get(index);
|
|
218
|
-
|
|
197
|
+
const updateData = value.poolId ? { ...value.properties, ...{ poolId: value.poolId } } : value.properties;
|
|
198
|
+
this.doTransact(nodeToUpdate, updateData);
|
|
219
199
|
});
|
|
220
200
|
}
|
|
221
201
|
replaceNode(nodeData, newControl) {
|
|
@@ -224,13 +204,11 @@ export default class Multiplayer {
|
|
|
224
204
|
const nodeToUpdate = this.yArray.get(index);
|
|
225
205
|
// Update the node id in the nodeData
|
|
226
206
|
nodeData.id = `node_${this.#nodeIdGenerator.getDefinitionNumber()}`;
|
|
227
|
-
// Replace the node in the process
|
|
228
|
-
this.modeler.replaceNodeProcedure(nodeData, true);
|
|
229
207
|
// Update the node id generator
|
|
230
208
|
this.#nodeIdGenerator.updateCounters();
|
|
231
209
|
// Update the node in the shared array
|
|
232
210
|
this.yDoc.transact(() => {
|
|
233
|
-
nodeToUpdate.set('
|
|
211
|
+
nodeToUpdate.set('type', newControl);
|
|
234
212
|
nodeToUpdate.set('id', nodeData.id);
|
|
235
213
|
});
|
|
236
214
|
|
|
@@ -240,13 +218,14 @@ export default class Multiplayer {
|
|
|
240
218
|
this.clientIO.emit('updateElement', { updateDoc: stateUpdate, isReplaced: true });
|
|
241
219
|
}
|
|
242
220
|
replaceShape(updatedNode) {
|
|
221
|
+
const { x: clientX, y: clientY } = this.modeler.paper.localToClientPoint(updatedNode);
|
|
243
222
|
// Get the node to update
|
|
244
223
|
const node = this.getNodeById(updatedNode.oldNodeId);
|
|
245
224
|
// Update the node id in the nodeData
|
|
246
225
|
const nodeData = {
|
|
247
|
-
clientX
|
|
248
|
-
clientY
|
|
249
|
-
control: { type: updatedNode.
|
|
226
|
+
clientX,
|
|
227
|
+
clientY,
|
|
228
|
+
control: { type: updatedNode.type },
|
|
250
229
|
nodeThatWillBeReplaced: node,
|
|
251
230
|
id: updatedNode.id,
|
|
252
231
|
};
|
|
@@ -269,23 +248,27 @@ export default class Multiplayer {
|
|
|
269
248
|
// Send the update to the web socket server
|
|
270
249
|
this.clientIO.emit('updateElement', { updateDoc: stateUpdate, isReplaced: false });
|
|
271
250
|
}
|
|
272
|
-
updateShapes(data) {
|
|
251
|
+
async updateShapes(data) {
|
|
273
252
|
const { paper } = this.modeler;
|
|
274
|
-
const element = this.
|
|
253
|
+
const element = this.modeler.getElementByNodeId(data.id);
|
|
254
|
+
const newPool = this.modeler.getElementByNodeId(data.poolId);
|
|
275
255
|
// Update the element's position attribute
|
|
276
|
-
element.
|
|
256
|
+
element.resize(
|
|
257
|
+
/* Add labelWidth to ensure elements don't overlap with the pool label */
|
|
258
|
+
data.width,
|
|
259
|
+
data.height,
|
|
260
|
+
);
|
|
261
|
+
element.set('position', { x: data.x, y: data.y });
|
|
277
262
|
// Trigger a rendering of the element on the paper
|
|
278
|
-
paper.findViewByModel(element).update();
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
return cell;
|
|
285
|
-
}
|
|
263
|
+
await paper.findViewByModel(element).update();
|
|
264
|
+
// validate if the parent pool was updated
|
|
265
|
+
await element.component.$nextTick();
|
|
266
|
+
await this.modeler.paperManager.awaitScheduledUpdates();
|
|
267
|
+
if (newPool && element.component.node.pool && element.component.node.pool.component.id !== data.poolId) {
|
|
268
|
+
element.component.node.pool.component.moveElementRemote(element, newPool);
|
|
286
269
|
}
|
|
287
|
-
return null; // Return null if no matching element is found
|
|
288
270
|
}
|
|
271
|
+
|
|
289
272
|
addFlow(data) {
|
|
290
273
|
const yMapNested = new Y.Map();
|
|
291
274
|
this.doTransact(yMapNested, data);
|
|
@@ -296,20 +279,49 @@ export default class Multiplayer {
|
|
|
296
279
|
this.clientIO.emit('createElement', stateUpdate);
|
|
297
280
|
this.#nodeIdGenerator.updateCounters();
|
|
298
281
|
}
|
|
299
|
-
createFlow(data){
|
|
300
|
-
const { paper } = this.modeler;
|
|
301
|
-
const sourceElem = this.getJointElement(paper.model, data.sourceRefId);
|
|
302
|
-
const targetElem = this.getJointElement(paper.model, data.targetRefId);
|
|
303
|
-
if (sourceElem && targetElem) {
|
|
304
|
-
const bpmnFlow = BpmnFlows.find(FlowClass => {
|
|
305
|
-
return FlowClass.type === data.type;
|
|
306
|
-
});
|
|
307
|
-
const flow = new bpmnFlow.factory(this.modeler.nodeRegistry, this.modeler.moddle, this.modeler.paper);
|
|
308
|
-
const actualFlow = flow.makeFlowNode(sourceElem, targetElem, data.waypoint);
|
|
309
|
-
// add Nodes
|
|
310
|
-
this.modeler.addNode(actualFlow, data.id);
|
|
311
|
-
this.#nodeIdGenerator.updateCounters();
|
|
312
|
-
}
|
|
313
282
|
|
|
283
|
+
addLaneNodes(lanes) {
|
|
284
|
+
const pool = this.getPool(lanes);
|
|
285
|
+
window.ProcessMaker.EventBus.$emit('multiplayer-updateNodes', [{
|
|
286
|
+
id: pool.component.node.definition.id,
|
|
287
|
+
properties: {
|
|
288
|
+
x: pool.component.node.diagram.bounds.x,
|
|
289
|
+
y: pool.component.node.diagram.bounds.y,
|
|
290
|
+
height: pool.component.node.diagram.bounds.height,
|
|
291
|
+
width: pool.component.node.diagram.bounds.width,
|
|
292
|
+
isAddingLaneAbove: pool.isAddingLaneAbove,
|
|
293
|
+
},
|
|
294
|
+
}]);
|
|
295
|
+
this.yDoc.transact(() => {
|
|
296
|
+
lanes.forEach((lane) => {
|
|
297
|
+
const yMapNested = new Y.Map();
|
|
298
|
+
const data = this.prepareLaneData(lane);
|
|
299
|
+
this.doTransact(yMapNested, data);
|
|
300
|
+
this.yArray.push([yMapNested]);
|
|
301
|
+
const stateUpdate = Y.encodeStateAsUpdate(this.yDoc);
|
|
302
|
+
this.clientIO.emit('createElement', stateUpdate);
|
|
303
|
+
});
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
prepareLaneData(lane) {
|
|
307
|
+
const data = {
|
|
308
|
+
type: lane.type,
|
|
309
|
+
id: lane.definition.id,
|
|
310
|
+
name: lane.definition.name,
|
|
311
|
+
x: lane.diagram.bounds.x,
|
|
312
|
+
y: lane.diagram.bounds.y,
|
|
313
|
+
width: lane.diagram.bounds.width,
|
|
314
|
+
height: lane.diagram.bounds.height,
|
|
315
|
+
poolId: lane.pool.component.node.definition.id,
|
|
316
|
+
laneSetId: lane.pool.component.laneSet.id,
|
|
317
|
+
};
|
|
318
|
+
return data;
|
|
314
319
|
}
|
|
320
|
+
getPool(lanes) {
|
|
321
|
+
if (lanes && lanes.length > 0) {
|
|
322
|
+
return lanes[0].pool;
|
|
323
|
+
}
|
|
324
|
+
return false;
|
|
325
|
+
}
|
|
326
|
+
|
|
315
327
|
}
|
package/src/nodeTypesStore.js
CHANGED
|
@@ -114,7 +114,7 @@ export default new Vuex.Store({
|
|
|
114
114
|
},
|
|
115
115
|
actions: {
|
|
116
116
|
getUserPinnedObjects({ commit }) {
|
|
117
|
-
if (
|
|
117
|
+
if (window.ProcessMaker?.user?.id === 'standalone') {
|
|
118
118
|
// For standalone version of Modeler
|
|
119
119
|
const pinnedNodes = localStorage.pinnedNodes ? JSON.parse(localStorage.pinnedNodes) : [] ;
|
|
120
120
|
pinnedNodes.forEach(node => {
|
|
@@ -137,7 +137,7 @@ export default new Vuex.Store({
|
|
|
137
137
|
addUserPinnedObject({ commit, state }, pinnedNode) {
|
|
138
138
|
commit('setPinnedNodes', pinnedNode);
|
|
139
139
|
const pinnedNodes = state.pinnedNodeTypes;
|
|
140
|
-
if (
|
|
140
|
+
if (window.ProcessMaker?.user?.id === 'standalone') {
|
|
141
141
|
// For standalone version of Modeler
|
|
142
142
|
localStorage.pinnedNodes = JSON.stringify(pinnedNodes);
|
|
143
143
|
return;
|
|
@@ -152,7 +152,7 @@ export default new Vuex.Store({
|
|
|
152
152
|
removeUserPinnedObject({ commit, state }, nodeToUnpin) {
|
|
153
153
|
commit('setUnpinNode', nodeToUnpin);
|
|
154
154
|
const pinnedNodes = state.pinnedNodeTypes;
|
|
155
|
-
if (
|
|
155
|
+
if (window.ProcessMaker?.user?.id === 'standalone') {
|
|
156
156
|
// For standalone version of Modeler
|
|
157
157
|
localStorage.pinnedNodes = JSON.stringify(pinnedNodes);
|
|
158
158
|
return;
|
package/src/setup/globals.js
CHANGED
|
@@ -4,6 +4,7 @@ import MockAdapter from 'axios-mock-adapter';
|
|
|
4
4
|
import mockProcesses from './mockProcesses.json';
|
|
5
5
|
import mockSignals from './mockSignals.json';
|
|
6
6
|
import mockProcessSvg from './mockProcessSvg';
|
|
7
|
+
import { faker } from '@faker-js/faker';
|
|
7
8
|
|
|
8
9
|
axios.defaults.baseURL = 'https://bpm4.local.processmaker.com/api/1.0/';
|
|
9
10
|
axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
|
|
@@ -57,5 +58,10 @@ window.ProcessMaker = {
|
|
|
57
58
|
id: 1,
|
|
58
59
|
},
|
|
59
60
|
},
|
|
61
|
+
user: {
|
|
62
|
+
id: 'standalone',
|
|
63
|
+
fullName: faker.person.fullName(),
|
|
64
|
+
avatar: null,
|
|
65
|
+
},
|
|
60
66
|
|
|
61
67
|
};
|