@processmaker/modeler 1.39.17 → 1.39.19

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.
Files changed (29) hide show
  1. package/dist/modeler.common.js +1717 -1211
  2. package/dist/modeler.common.js.map +1 -1
  3. package/dist/modeler.umd.js +1717 -1211
  4. package/dist/modeler.umd.js.map +1 -1
  5. package/dist/modeler.umd.min.js +4 -4
  6. package/dist/modeler.umd.min.js.map +1 -1
  7. package/package.json +1 -1
  8. package/src/components/crown/utils.js +10 -9
  9. package/src/components/modeler/Modeler.vue +94 -27
  10. package/src/components/modeler/Selection.vue +42 -15
  11. package/src/components/nodes/association/AssociationFlow.js +27 -0
  12. package/src/components/nodes/association/associationConfig.js +15 -0
  13. package/src/components/nodes/association/index.js +19 -12
  14. package/src/components/nodes/dataInputAssociation/DataInputAssociation.js +30 -0
  15. package/src/components/nodes/dataInputAssociation/index.js +17 -0
  16. package/src/components/nodes/dataOutputAssociation/index.js +15 -0
  17. package/src/components/nodes/genericFlow/DataOutputAssociation.js +1 -1
  18. package/src/components/nodes/genericFlow/genericFlow.vue +0 -10
  19. package/src/components/nodes/messageFlow/index.js +16 -0
  20. package/src/components/nodes/pool/pool.vue +40 -10
  21. package/src/components/nodes/poolLane/index.js +36 -0
  22. package/src/components/nodes/sequenceFlow/index.js +15 -0
  23. package/src/components/topRail/multiplayerViewUsers/MultiplayerViewUsers.vue +1 -1
  24. package/src/mixins/cloneSelection.js +1 -1
  25. package/src/mixins/linkConfig.js +35 -17
  26. package/src/mixins/poolLaneCrownConfig.js +0 -2
  27. package/src/multiplayer/multiplayer.js +139 -80
  28. package/src/nodeTypesStore.js +3 -3
  29. package/src/setup/globals.js +6 -0
@@ -3,6 +3,9 @@ import nameConfigSettings from '@/components/inspectors/nameConfigSettings';
3
3
  import advancedAccordionConfig from '@/components/inspectors/advancedAccordionConfig';
4
4
  import documentationAccordionConfig from '@/components/inspectors/documentationAccordionConfig';
5
5
  import { id } from '@/components/nodes/poolLane/config';
6
+ import Node from '@/components/nodes/node';
7
+ import { elementShouldHaveFlowNodeRef } from '@/components/nodes/pool/poolUtils';
8
+ import { getNodeIdGenerator } from '@/NodeIdGenerator';
6
9
 
7
10
  export default {
8
11
  id,
@@ -49,4 +52,37 @@ export default {
49
52
  ],
50
53
  },
51
54
  ],
55
+
56
+ async multiplayerClient(modeler, data) {
57
+ const pool = modeler.getElementByNodeId(data.poolId);
58
+ const definition = modeler.moddle.create('bpmn:Lane', {
59
+ name: data.name,
60
+ });
61
+ if (!pool.component.laneSet && pool.component.createLaneSet) {
62
+ pool.component.createLaneSet([data.laneSetId]);
63
+ /* If there are currently elements in the pool, add them to the first lane */
64
+ pool.component.shape.getEmbeddedCells().filter(element => elementShouldHaveFlowNodeRef(element))
65
+ .forEach(element => {
66
+ definition.get('flowNodeRef').push(element.component.node.definition);
67
+ });
68
+ const nodeIdereator = getNodeIdGenerator(modeler.definitions);
69
+ nodeIdereator.updateCounters();
70
+ }
71
+ const diagram = modeler.moddle.create('bpmndi:BPMNShape', {
72
+ bounds: modeler.moddle.create('dc:Bounds', {
73
+ height: data.height,
74
+ width: data.width,
75
+ x: data.x,
76
+ y: data.y,
77
+ }),
78
+ });
79
+ const node = new Node(
80
+ data.type,
81
+ definition,
82
+ diagram,
83
+ );
84
+ await modeler.addNode(node, data.id, true);
85
+ modeler.setShapeStacking(pool.component.shape);
86
+
87
+ },
52
88
  };
@@ -2,6 +2,8 @@ import component from './sequenceFlow.vue';
2
2
  import nameConfigSettings from '@/components/inspectors/nameConfigSettings';
3
3
  import advancedAccordionConfig from '@/components/inspectors/advancedAccordionConfig';
4
4
  import documentationAccordionConfig from '@/components/inspectors/documentationAccordionConfig';
5
+ import { getNodeIdGenerator } from '@/NodeIdGenerator';
6
+ import SequenceFlow from '@/components/nodes/genericFlow/SequenceFlow';
5
7
 
6
8
  export const id = 'processmaker-modeler-sequence-flow';
7
9
 
@@ -82,4 +84,17 @@ export default {
82
84
  ],
83
85
  },
84
86
  ],
87
+ async multiplayerClient(modeler, data) {
88
+ const { paper } = modeler;
89
+ const sourceElem = modeler.getElementByNodeId(data.sourceRefId);
90
+ const targetElem = modeler.getElementByNodeId(data.targetRefId);
91
+ if (sourceElem && targetElem) {
92
+ const flow = new SequenceFlow(modeler.nodeRegistry, modeler.moddle, paper);
93
+ const actualFlow = flow.makeFlowNode(sourceElem, targetElem, data.waypoint);
94
+ // add Nodes
95
+ modeler.addNode(actualFlow, data.id, true);
96
+ const nodeIdereator = getNodeIdGenerator(modeler.definitions);
97
+ nodeIdereator.updateCounters();
98
+ }
99
+ },
85
100
  };
@@ -23,7 +23,7 @@ export default {
23
23
  filteredPlayers() {
24
24
  const allPlayers = uniqBy(this.players, 'name');
25
25
  return allPlayers.filter(player => {
26
- return player.name.toLowerCase() !== window.ProcessMaker.user.fullName.toLowerCase();
26
+ return player.name.toLowerCase() !== window.ProcessMaker.user?.fullName.toLowerCase();
27
27
  });
28
28
  },
29
29
  },
@@ -1,6 +1,6 @@
1
1
  import { id as laneId } from '../components/nodes/poolLane/config';
2
2
  import { id as sequenceFlowId } from '../components/nodes/sequenceFlow';
3
- import { id as associationId } from '../components/nodes/association';
3
+ import { id as associationId } from '../components/nodes/association/associationConfig';
4
4
  import { id as messageFlowId } from '../components/nodes/messageFlow/config';
5
5
  import { id as dataOutputAssociationFlowId } from '../components/nodes/dataOutputAssociation/config';
6
6
  import { id as dataInputAssociationFlowId } from '../components/nodes/dataInputAssociation/config';
@@ -23,6 +23,7 @@ export default {
23
23
  props: ['highlighted', 'paper', 'paperManager', 'isCompleted', 'isIdle'],
24
24
  data() {
25
25
  return {
26
+ linkView: null,
26
27
  sourceShape: null,
27
28
  target: null,
28
29
  listeningToMouseup: false,
@@ -163,6 +164,31 @@ export default {
163
164
  this.updateWaypoints();
164
165
  await this.$nextTick();
165
166
 
167
+ if (this.$parent.isMultiplayer && this.linkView) {
168
+ // update waypoints in multiplayer mode
169
+ const nodeType = this.linkView.model.component.node.type;
170
+ const sourceRefId = this.linkView.sourceView.model.component.node.definition.id;
171
+ const targetRefId = this.linkView.targetView.model.component.node.definition.id;
172
+
173
+ const changes = [
174
+ {
175
+ id: this.linkView.model.component.node.definition.id,
176
+ properties: {
177
+ type: nodeType,
178
+ waypoint: [
179
+ this.linkView.sourceAnchor.toJSON(),
180
+ ...this.shape.vertices(),
181
+ this.linkView.targetAnchor.toJSON(),
182
+ ],
183
+ sourceRefId,
184
+ targetRefId,
185
+ },
186
+ },
187
+ ];
188
+
189
+ window.ProcessMaker.EventBus.$emit('multiplayer-updateNodes', changes);
190
+ }
191
+
166
192
  this.listeningToMouseleave = true;
167
193
  this.$emit('save-state');
168
194
  }
@@ -174,14 +200,15 @@ export default {
174
200
  * @param {Object} options
175
201
  */
176
202
  async onChangeTargets(link, vertices, options){
177
- if (options && options.ui) {
203
+ if (options?.ui) {
178
204
  await this.$nextTick();
179
205
  await this.waitForUpdateWaypoints();
206
+ this.listeningToMouseleave = false;
180
207
  await this.storeWaypoints();
181
208
  }
182
209
  },
183
210
  async onChangeVertices(link, vertices, options){
184
- if (options && options.ui) {
211
+ if (options?.ui) {
185
212
  this.updateWaypoints();
186
213
  await this.$nextTick();
187
214
  this.listeningToMouseleave = false;
@@ -189,9 +216,9 @@ export default {
189
216
  }
190
217
  },
191
218
  updateWaypoints() {
192
- const linkView = this.shape.findView(this.paper);
193
- const start = linkView.sourceAnchor;
194
- const end = linkView.targetAnchor;
219
+ this.linkView = this.shape.findView(this.paper);
220
+ const start = this.linkView.sourceAnchor;
221
+ const end = this.linkView.targetAnchor;
195
222
 
196
223
  this.node.diagram.waypoint = [start,
197
224
  ...this.shape.vertices(),
@@ -239,18 +266,9 @@ export default {
239
266
  if (this.updateDefinitionLinks) {
240
267
  this.updateDefinitionLinks();
241
268
  }
242
- if (this.shape.component.node.type === 'processmaker-modeler-data-input-association') {
243
- if (this.$parent.isMultiplayer) {
244
- const genericLink = this.shape.findView(this.paper);
245
- const waypoint = [genericLink.sourceAnchor.toJSON(), genericLink.targetAnchor.toJSON()];
246
- window.ProcessMaker.EventBus.$emit('multiplayer-addFlow', {
247
- type: this.shape.component.node.type,
248
- id: `node_${this.$parent.nodeIdGenerator.getDefinitionNumber()}`,
249
- sourceRefId: this.sourceNode.definition.id,
250
- targetRefId: this.targetNode.definition.id,
251
- waypoint,
252
- });
253
- }
269
+
270
+ if (this.linkView && ['processmaker-modeler-association', 'processmaker-modeler-data-input-association'].includes(this.shape.component.node.type)) {
271
+ this.$parent.multiplayerHook(this.shape.component.node, false);
254
272
  }
255
273
 
256
274
  this.$emit('save-state');
@@ -14,7 +14,6 @@ export default {
14
14
  ].includes(this.node.type)) {
15
15
  return;
16
16
  }
17
-
18
17
  if (this.node.pool) {
19
18
  if (!this.graph.getCell(this.node.pool)) {
20
19
  this.node.pool = this.graph.getElements().find(element => {
@@ -27,7 +26,6 @@ export default {
27
26
  if (this.isLane) {
28
27
  this.configureLaneInParentPool();
29
28
  }
30
-
31
29
  return;
32
30
  }
33
31
 
@@ -1,28 +1,9 @@
1
1
  import { io } from 'socket.io-client';
2
2
  import * as Y from 'yjs';
3
3
  import { getNodeIdGenerator } from '../NodeIdGenerator';
4
+ import { getDefaultAnchorPoint } from '@/portsUtils';
4
5
  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
- ];
6
+
26
7
  export default class Multiplayer {
27
8
  clientIO = null;
28
9
  yDoc = null;
@@ -44,7 +25,8 @@ export default class Multiplayer {
44
25
  // Get the node id generator
45
26
  this.#nodeIdGenerator = getNodeIdGenerator(this.modeler.definitions);
46
27
  // Get the room name from the process id
47
- this.room = new Room(`room-${window.ProcessMaker.modeler.process.id}`);
28
+ const processId = window.ProcessMaker.modeler.process.uuid ?? window.ProcessMaker.modeler.process.id;
29
+ this.room = new Room(`room-${processId}`);
48
30
 
49
31
  // Connect to websocket server
50
32
  this.clientIO = io(window.ProcessMaker.multiplayer.host, { transports: ['websocket', 'polling']});
@@ -53,8 +35,8 @@ export default class Multiplayer {
53
35
  // Join the room
54
36
  this.clientIO.emit('joinRoom', {
55
37
  roomName: this.room.getRoom(),
56
- clientName: window.ProcessMaker.user.fullName,
57
- clientAvatar: window.ProcessMaker.user.avatar,
38
+ clientName: window.ProcessMaker.user?.fullName,
39
+ clientAvatar: window.ProcessMaker.user?.avatar,
58
40
  });
59
41
  });
60
42
 
@@ -140,12 +122,13 @@ export default class Multiplayer {
140
122
  window.ProcessMaker.EventBus.$on('multiplayer-addFlow', ( data ) => {
141
123
  this.addFlow(data);
142
124
  });
125
+
126
+ window.ProcessMaker.EventBus.$on('multiplayer-addLanes', ( lanes ) => {
127
+ this.addLaneNodes(lanes);
128
+ });
143
129
  }
144
130
  addNode(data) {
145
- // Add the new element to the process
146
- this.createShape(data);
147
131
  // Add the new element to the shared array
148
- // this.yArray.push([data]);
149
132
  const yMapNested = new Y.Map();
150
133
  this.doTransact(yMapNested, data);
151
134
  this.yArray.push([yMapNested]);
@@ -154,47 +137,45 @@ export default class Multiplayer {
154
137
  // Send the update to the web socket server
155
138
  this.clientIO.emit('createElement', stateUpdate);
156
139
  }
157
- createShape(value) {
158
- this.modeler.handleDropProcedure(value, false);
140
+ createShape(value){
141
+ if (this.modeler.nodeRegistry[value.type] && this.modeler.nodeRegistry[value.type].multiplayerClient) {
142
+ this.modeler.nodeRegistry[value.type].multiplayerClient(this.modeler, value);
143
+ } else {
144
+ this.modeler.addRemoteNode(value);
145
+ }
159
146
  this.#nodeIdGenerator.updateCounters();
147
+
160
148
  }
161
149
  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
150
  return new Promise(resolve => {
169
151
  changes.map((data) => {
170
- if (flows.includes(data.type)) {
171
- this.createFlow(data);
172
- } else {
173
- this.createShape(data);
174
- }
152
+ this.createShape(data);
175
153
  });
176
154
  resolve();
177
155
  });
178
156
  }
179
157
  removeNode(data) {
180
158
  const index = this.getIndex(data.definition.id);
181
- this.removeShape(data);
182
- this.yArray.delete(index, 1); // delete one element
183
-
184
- // Encode the state as an update and send it to the server
185
- const stateUpdate = Y.encodeStateAsUpdate(this.yDoc);
186
- // Send the update to the web socket server
187
- this.clientIO.emit('removeElement', stateUpdate);
159
+ if (index >= 0) {
160
+ this.removeShape(data);
161
+ this.yArray.delete(index, 1); // delete one element
162
+ // Encode the state as an update and send it to the server
163
+ const stateUpdate = Y.encodeStateAsUpdate(this.yDoc);
164
+ // Send the update to the web socket server
165
+ this.clientIO.emit('removeElement', stateUpdate);
166
+ }
188
167
  }
189
168
  getIndex(id) {
190
169
  let index = -1;
170
+ let found = false;
191
171
  for (const value of this.yArray) {
192
172
  index ++;
193
173
  if (value.get('id') === id) {
174
+ found = true;
194
175
  break ;
195
176
  }
196
177
  }
197
- return index;
178
+ return found ? index : -1;
198
179
  }
199
180
  getNodeById(nodeId) {
200
181
  const node = this.modeler.nodes.find((element) => element.definition && element.definition.id === nodeId);
@@ -215,7 +196,8 @@ export default class Multiplayer {
215
196
  data.forEach((value) => {
216
197
  const index = this.getIndex(value.id);
217
198
  const nodeToUpdate = this.yArray.get(index);
218
- this.doTransact(nodeToUpdate, value.properties);
199
+ const updateData = value.poolId ? { ...value.properties, ...{ poolId: value.poolId } } : value.properties;
200
+ this.doTransact(nodeToUpdate, updateData);
219
201
  });
220
202
  }
221
203
  replaceNode(nodeData, newControl) {
@@ -224,13 +206,11 @@ export default class Multiplayer {
224
206
  const nodeToUpdate = this.yArray.get(index);
225
207
  // Update the node id in the nodeData
226
208
  nodeData.id = `node_${this.#nodeIdGenerator.getDefinitionNumber()}`;
227
- // Replace the node in the process
228
- this.modeler.replaceNodeProcedure(nodeData, true);
229
209
  // Update the node id generator
230
210
  this.#nodeIdGenerator.updateCounters();
231
211
  // Update the node in the shared array
232
212
  this.yDoc.transact(() => {
233
- nodeToUpdate.set('control', newControl);
213
+ nodeToUpdate.set('type', newControl);
234
214
  nodeToUpdate.set('id', nodeData.id);
235
215
  });
236
216
 
@@ -240,13 +220,14 @@ export default class Multiplayer {
240
220
  this.clientIO.emit('updateElement', { updateDoc: stateUpdate, isReplaced: true });
241
221
  }
242
222
  replaceShape(updatedNode) {
223
+ const { x: clientX, y: clientY } = this.modeler.paper.localToClientPoint(updatedNode);
243
224
  // Get the node to update
244
225
  const node = this.getNodeById(updatedNode.oldNodeId);
245
226
  // Update the node id in the nodeData
246
227
  const nodeData = {
247
- clientX: updatedNode.clientX,
248
- clientY: updatedNode.clientY,
249
- control: { type: updatedNode.control.type },
228
+ clientX,
229
+ clientY,
230
+ control: { type: updatedNode.type },
250
231
  nodeThatWillBeReplaced: node,
251
232
  id: updatedNode.id,
252
233
  };
@@ -269,23 +250,59 @@ export default class Multiplayer {
269
250
  // Send the update to the web socket server
270
251
  this.clientIO.emit('updateElement', { updateDoc: stateUpdate, isReplaced: false });
271
252
  }
272
- updateShapes(data) {
253
+ async updateShapes(data) {
273
254
  const { paper } = this.modeler;
274
- const element = this.getJointElement(paper.model, data.id);
275
- // Update the element's position attribute
276
- element.set('position', { x:data.clientX, y:data.clientY });
277
- // Trigger a rendering of the element on the paper
278
- paper.findViewByModel(element).update();
279
- }
280
- getJointElement(graph, targetValue) {
281
- const cells = graph.getCells();
282
- for (const cell of cells) {
283
- if (cell.component.id === targetValue) {
284
- return cell;
255
+ const element = this.modeler.getElementByNodeId(data.id);
256
+ const newPool = this.modeler.getElementByNodeId(data.poolId);
257
+
258
+ if (this.modeler.flowTypes.includes(data.type)) {
259
+ // Update the element's waypoints
260
+ // Get the source and target elements
261
+ const sourceElem = this.modeler.getElementByNodeId(data.sourceRefId);
262
+ const targetElem = this.modeler.getElementByNodeId(data.targetRefId);
263
+
264
+ const { waypoint } = data;
265
+ const startWaypoint = waypoint.shift();
266
+ const endWaypoint = waypoint.pop();
267
+
268
+ // Update the element's waypoints
269
+ const newWaypoint = waypoint.map(point => this.modeler.moddle.create('dc:Point', point));
270
+ element.set('vertices', newWaypoint);
271
+
272
+ // Update the element's source anchor
273
+ element.source(sourceElem, {
274
+ anchor: () => {
275
+ return getDefaultAnchorPoint(this.getConnectionPoint(sourceElem, startWaypoint), sourceElem.findView(paper));
276
+ },
277
+ connectionPoint: { name: 'boundary' },
278
+ });
279
+
280
+ // Update the element's target anchor
281
+ element.target(targetElem, {
282
+ anchor: () => {
283
+ return getDefaultAnchorPoint(this.getConnectionPoint(targetElem, endWaypoint), targetElem.findView(paper));
284
+ },
285
+ connectionPoint: { name: 'boundary' },
286
+ });
287
+ } else {
288
+ // Update the element's position attribute
289
+ element.resize(
290
+ /* Add labelWidth to ensure elements don't overlap with the pool label */
291
+ data.width,
292
+ data.height,
293
+ );
294
+ element.set('position', { x: data.x, y: data.y });
295
+ // Trigger a rendering of the element on the paper
296
+ await paper.findViewByModel(element).update();
297
+ // validate if the parent pool was updated
298
+ await element.component.$nextTick();
299
+ await this.modeler.paperManager.awaitScheduledUpdates();
300
+ if (newPool && element.component.node.pool && element.component.node.pool.component.id !== data.poolId) {
301
+ element.component.node.pool.component.moveElementRemote(element, newPool);
285
302
  }
286
303
  }
287
- return null; // Return null if no matching element is found
288
304
  }
305
+
289
306
  addFlow(data) {
290
307
  const yMapNested = new Y.Map();
291
308
  this.doTransact(yMapNested, data);
@@ -296,20 +313,62 @@ export default class Multiplayer {
296
313
  this.clientIO.emit('createElement', stateUpdate);
297
314
  this.#nodeIdGenerator.updateCounters();
298
315
  }
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;
316
+
317
+ addLaneNodes(lanes) {
318
+ const pool = this.getPool(lanes);
319
+ window.ProcessMaker.EventBus.$emit('multiplayer-updateNodes', [{
320
+ id: pool.component.node.definition.id,
321
+ properties: {
322
+ x: pool.component.node.diagram.bounds.x,
323
+ y: pool.component.node.diagram.bounds.y,
324
+ height: pool.component.node.diagram.bounds.height,
325
+ width: pool.component.node.diagram.bounds.width,
326
+ isAddingLaneAbove: pool.isAddingLaneAbove,
327
+ },
328
+ }]);
329
+ this.yDoc.transact(() => {
330
+ lanes.forEach((lane) => {
331
+ const yMapNested = new Y.Map();
332
+ const data = this.prepareLaneData(lane);
333
+ this.doTransact(yMapNested, data);
334
+ this.yArray.push([yMapNested]);
335
+ const stateUpdate = Y.encodeStateAsUpdate(this.yDoc);
336
+ this.clientIO.emit('createElement', stateUpdate);
306
337
  });
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();
338
+ });
339
+ }
340
+ prepareLaneData(lane) {
341
+ const data = {
342
+ type: lane.type,
343
+ id: lane.definition.id,
344
+ name: lane.definition.name,
345
+ x: lane.diagram.bounds.x,
346
+ y: lane.diagram.bounds.y,
347
+ width: lane.diagram.bounds.width,
348
+ height: lane.diagram.bounds.height,
349
+ poolId: lane.pool.component.node.definition.id,
350
+ laneSetId: lane.pool.component.laneSet.id,
351
+ };
352
+ return data;
353
+ }
354
+ getPool(lanes) {
355
+ if (lanes && lanes.length > 0) {
356
+ return lanes[0].pool;
312
357
  }
358
+ return false;
359
+ }
360
+ getConnectionPoint(element, newPosition) {
361
+ const { x: elemX, y: elemY } = element.position();
362
+ const connectionOffset = {
363
+ x: newPosition.x - elemX,
364
+ y: newPosition.y - elemY,
365
+ };
366
+
367
+ const { x, y } = element.position();
368
+ const { width, height } = element.size();
313
369
 
370
+ return connectionOffset
371
+ ? { x: x + connectionOffset.x, y: y + connectionOffset.y }
372
+ : { x: x + (width / 2), y: y + (height / 2) };
314
373
  }
315
374
  }
@@ -114,7 +114,7 @@ export default new Vuex.Store({
114
114
  },
115
115
  actions: {
116
116
  getUserPinnedObjects({ commit }) {
117
- if (!window.ProcessMaker.user) {
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 (!window.ProcessMaker.user) {
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 (!window.ProcessMaker.user) {
155
+ if (window.ProcessMaker?.user?.id === 'standalone') {
156
156
  // For standalone version of Modeler
157
157
  localStorage.pinnedNodes = JSON.stringify(pinnedNodes);
158
158
  return;
@@ -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
  };