@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@processmaker/modeler",
3
- "version": "1.39.17",
3
+ "version": "1.39.18",
4
4
  "scripts": {
5
5
  "serve": "vue-cli-service serve --mode development",
6
6
  "test:unit": "vue-cli-service test:unit",
@@ -62,15 +62,16 @@ export function removeNodeAssociations(node, modeler) {
62
62
 
63
63
  export function removeBoundaryEvents(graph, node, removeNode) {
64
64
  const nodeShape = graph.getCells().find(el => el.component && el.component.node === node);
65
-
66
- nodeShape.getEmbeddedCells({ deep: true })
67
- .filter(cell => {
68
- return cell.component && cell.component.node.isBpmnType('bpmn:BoundaryEvent');
69
- })
70
- .forEach(boundaryEventShape => {
71
- graph.getConnectedLinks(boundaryEventShape).forEach(shape => removeNode(shape.component.node));
72
- removeNode(boundaryEventShape.component.node);
73
- });
65
+ if (nodeShape) {
66
+ nodeShape.getEmbeddedCells({ deep: true })
67
+ .filter(cell => {
68
+ return cell.component && cell.component.node.isBpmnType('bpmn:BoundaryEvent');
69
+ })
70
+ .forEach(boundaryEventShape => {
71
+ graph.getConnectedLinks(boundaryEventShape).forEach(shape => removeNode(shape.component.node));
72
+ removeNode(boundaryEventShape.component.node);
73
+ });
74
+ }
74
75
  }
75
76
 
76
77
  export function removeOutgoingAndIncomingRefsToFlow(node){
@@ -529,6 +529,10 @@ export default {
529
529
  return this.paper.findViewByModel(shape);
530
530
  });
531
531
  },
532
+ getElementByNodeId(id) {
533
+ const cells = this.paper.model.getCells();
534
+ return cells.find((cell) => cell.component && cell.component.id === id);
535
+ },
532
536
  async close() {
533
537
  this.$emit('close');
534
538
  },
@@ -1035,21 +1039,22 @@ export default {
1035
1039
  control,
1036
1040
  });
1037
1041
  },
1038
- handleDrop(data) {
1039
- const { clientX, clientY, control } = data;
1040
- if (this.isMultiplayer) {
1041
- window.ProcessMaker.EventBus.$emit('multiplayer-addNode', {
1042
- clientX,
1043
- clientY,
1044
- control,
1045
- id: `node_${this.nodeIdGenerator.getDefinitionNumber()}`,
1046
- });
1047
- } else {
1048
- this.handleDropProcedure(data);
1042
+ async addRemoteNode(data){
1043
+ const definition = this.nodeRegistry[data.type].definition(this.moddle, this.$t);
1044
+ const diagram = this.nodeRegistry[data.type].diagram(this.moddle);
1045
+ diagram.bounds.x = data.x;
1046
+ diagram.bounds.y = data.y;
1047
+ const newNode = this.createNode(data.type, definition, diagram);
1048
+ await this.addNode(newNode, data.id, true);
1049
+ await this.$nextTick();
1050
+ await this.paperManager.awaitScheduledUpdates();
1051
+ if (this.autoValidate) {
1052
+ this.validateBpmnDiagram();
1049
1053
  }
1050
1054
  },
1051
- async handleDropProcedure(data, selected=true) {
1052
- const { clientX, clientY, control, nodeThatWillBeReplaced, id } = data;
1055
+
1056
+ async handleDrop(data) {
1057
+ const { clientX, clientY, control, nodeThatWillBeReplaced } = data;
1053
1058
  this.validateDropTarget({ clientX, clientY, control });
1054
1059
  if (!this.allowDrop) {
1055
1060
  return;
@@ -1068,11 +1073,10 @@ export default {
1068
1073
  if (newNode.isBpmnType('bpmn:BoundaryEvent')) {
1069
1074
  this.setShapeCenterUnderCursor(diagram);
1070
1075
  }
1071
- if (selected) {
1072
- this.highlightNode(newNode);
1073
- }
1074
1076
 
1075
- await this.addNode(newNode, id, selected);
1077
+ this.highlightNode(newNode);
1078
+
1079
+ await this.addNode(newNode);
1076
1080
  if (!nodeThatWillBeReplaced) {
1077
1081
  return;
1078
1082
  }
@@ -1101,7 +1105,50 @@ export default {
1101
1105
  const view = newNodeComponent.shapeView;
1102
1106
  await this.$refs.selector.selectElement(view);
1103
1107
  },
1104
- async addNode(node, id = null, selected = true) {
1108
+ multiplayerHook(node, fromClient) {
1109
+ const blackList = [
1110
+ 'processmaker-modeler-lane',
1111
+ 'processmaker-modeler-generic-flow',
1112
+ 'processmaker-modeler-sequence-flow',
1113
+ 'processmaker-modeler-association',
1114
+ 'processmaker-modeler-data-input-association',
1115
+ 'processmaker-modeler-data-input-association',
1116
+ ];
1117
+ const flowTypes = [
1118
+ 'processmaker-modeler-sequence-flow',
1119
+ 'processmaker-modeler-message-flow',
1120
+ ];
1121
+ if (!this.isMultiplayer) {
1122
+ return;
1123
+ }
1124
+ if (!fromClient) {
1125
+ if (!blackList.includes(node.type) && !flowTypes.includes(node.type)) {
1126
+ const defaultData = {
1127
+ x: node.diagram.bounds.x,
1128
+ y: node.diagram.bounds.y,
1129
+ height: node.diagram.bounds.height,
1130
+ width: node.diagram.bounds.width,
1131
+ type: node.type,
1132
+ id: node.definition.id,
1133
+ isAddingLaneAbove: true,
1134
+ };
1135
+ if (node?.pool?.component) {
1136
+ defaultData['poolId'] = node.pool.component.id;
1137
+ }
1138
+ window.ProcessMaker.EventBus.$emit('multiplayer-addNode', defaultData);
1139
+ }
1140
+ if (flowTypes.includes(node.type)) {
1141
+ window.ProcessMaker.EventBus.$emit('multiplayer-addFlow', {
1142
+ id: node.definition.id,
1143
+ type: node.type,
1144
+ sourceRefId: node.definition.sourceRef.id,
1145
+ targetRefId: node.definition.targetRef.id,
1146
+ waypoint: node.diagram.waypoint,
1147
+ });
1148
+ }
1149
+ }
1150
+ },
1151
+ async addNode(node, id = null, fromClient = false) {
1105
1152
  if (!node.pool) {
1106
1153
  node.pool = this.poolTarget;
1107
1154
  }
@@ -1111,6 +1158,9 @@ export default {
1111
1158
  node.setIds(this.nodeIdGenerator, id);
1112
1159
 
1113
1160
  this.planeElements.push(node.diagram);
1161
+ // add multiplayer logic as a hook
1162
+ this.multiplayerHook(node, fromClient);
1163
+
1114
1164
  store.commit('addNode', node);
1115
1165
  this.poolTarget = null;
1116
1166
 
@@ -1126,7 +1176,7 @@ export default {
1126
1176
  ].includes(node.type)) {
1127
1177
  return;
1128
1178
  }
1129
- if (selected) {
1179
+ if (!fromClient) {
1130
1180
  // Select the node after it has been added to the store (does not apply to flows)
1131
1181
  this.selectNewNode(node);
1132
1182
  }
@@ -1148,6 +1198,7 @@ export default {
1148
1198
  addNodeToProcess(node, targetProcess);
1149
1199
 
1150
1200
  this.planeElements.push(node.diagram);
1201
+ this.multiplayerHook(node, false);
1151
1202
  store.commit('addNode', node);
1152
1203
  this.poolTarget = null;
1153
1204
  });
@@ -1207,10 +1258,10 @@ export default {
1207
1258
  replaceNode({ node, typeToReplaceWith }) {
1208
1259
  this.performSingleUndoRedoTransaction(async() => {
1209
1260
  await this.paperManager.performAtomicAction(async() => {
1210
- const { x: clientX, y: clientY } = this.paper.localToClientPoint(node.diagram.bounds);
1261
+ const { x, y } = node.diagram.bounds;
1211
1262
 
1212
1263
  const nodeData = {
1213
- clientX, clientY,
1264
+ x, y,
1214
1265
  control: { type: typeToReplaceWith },
1215
1266
  nodeThatWillBeReplaced: node,
1216
1267
  };
@@ -1224,10 +1275,10 @@ export default {
1224
1275
  }).filter(Boolean);
1225
1276
  // If the new control is found, emit event to server to replace node
1226
1277
  if (newControl.length === 1) {
1227
- window.ProcessMaker.EventBus.$emit('multiplayer-replaceNode', { nodeData, newControl: newControl[0] });
1278
+ window.ProcessMaker.EventBus.$emit('multiplayer-replaceNode', { nodeData, newControl: newControl[0].type });
1228
1279
  }
1229
1280
  } else {
1230
- await this.replaceNodeProcedure(nodeData);
1281
+ await this.replaceNodeProcedure(nodeData, true);
1231
1282
  }
1232
1283
  });
1233
1284
  });
@@ -1240,7 +1291,7 @@ export default {
1240
1291
  data.clientY = clientY;
1241
1292
  }
1242
1293
 
1243
- const newNode = await this.handleDropProcedure(data);
1294
+ const newNode = await this.handleDrop(data);
1244
1295
 
1245
1296
  await this.removeNode(data.nodeThatWillBeReplaced, { removeRelationships: false, isReplaced });
1246
1297
  this.highlightNode(newNode);
@@ -1250,7 +1301,7 @@ export default {
1250
1301
  this.performSingleUndoRedoTransaction(async() => {
1251
1302
  await this.paperManager.performAtomicAction(async() => {
1252
1303
  const { x: clientX, y: clientY } = this.paper.localToClientPoint(node.diagram.bounds);
1253
- const newNode = await this.handleDropProcedure({
1304
+ const newNode = await this.handleDrop({
1254
1305
  clientX, clientY,
1255
1306
  control: { type: typeToReplaceWith },
1256
1307
  nodeThatWillBeReplaced: node,
@@ -578,28 +578,55 @@ export default {
578
578
  this.overPoolStopDrag();
579
579
  this.updateSelectionBox();
580
580
  if (this.isMultiplayer) {
581
- window.ProcessMaker.EventBus.$emit('multiplayer-updateNodes', this.getProperties());
581
+ window.ProcessMaker.EventBus.$emit('multiplayer-updateNodes', this.getProperties(this.selected));
582
582
  }
583
-
584
-
585
583
  },
586
- getProperties() {
587
- const changed = [];
584
+
585
+ getProperties(shapes) {
586
+ let changed = [];
588
587
  const shapesToNotTranslate = [
589
588
  'PoolLane',
590
589
  'standard.Link',
591
590
  'processmaker.components.nodes.boundaryEvent.Shape',
592
591
  ];
593
- this.selected.filter(shape => !shapesToNotTranslate.includes(shape.model.get('type')))
592
+
593
+ shapes.filter(shape => !shapesToNotTranslate.includes(shape.model.get('type')))
594
594
  .forEach(shape => {
595
- changed.push({
596
- id: shape.model.component.node.definition.id,
597
- properties: {
598
- clientX: shape.model.get('position').x,
599
- clientY: shape.model.get('position').y,
600
- },
601
- });
595
+ if (shape.model.get('type') === 'processmaker.modeler.bpmn.pool') {
596
+ const children = shape.model.component.getElementsUnderArea(shape.model, this.graph);
597
+ changed = [...changed, ...this.getContainerProperties(children, changed)];
598
+ } else {
599
+ const { node } = shape.model.component;
600
+ const defaultData = {
601
+ id: node.definition.id,
602
+ properties: {
603
+ x: shape.model.get('position').x,
604
+ y: shape.model.get('position').y,
605
+ height: shape.model.get('size').height,
606
+ width: shape.model.get('size').width,
607
+ },
608
+ };
609
+ if (node?.pool?.component) {
610
+ defaultData['poolId'] = node.pool.component.id;
611
+ }
612
+ changed.push(defaultData);
613
+ }
614
+ });
615
+ return changed;
616
+ },
617
+ getContainerProperties(children) {
618
+ const changed = [];
619
+ children.forEach(model => {
620
+ changed.push({
621
+ id: model.component.node.definition.id,
622
+ properties: {
623
+ x: model.get('position').x,
624
+ y: model.get('position').y,
625
+ height: model.get('size').height,
626
+ width: model.get('size').width,
627
+ },
602
628
  });
629
+ });
603
630
  return changed;
604
631
  },
605
632
  /**
@@ -109,17 +109,6 @@ export default {
109
109
  const flow = new bpmnFlow.factory(this.nodeRegistry, this.moddle, this.paper);
110
110
  const genericLink = this.shape.findView(this.paper);
111
111
  const waypoint = [genericLink.sourceAnchor.toJSON(), genericLink.targetAnchor.toJSON()];
112
- // Multiplayer hook
113
- if (this.$parent.isMultiplayer) {
114
- window.ProcessMaker.EventBus.$emit('multiplayer-addFlow', {
115
- type: bpmnFlow.type,
116
- id: `node_${this.$parent.nodeIdGenerator.getDefinitionNumber()}`,
117
- sourceRefId: this.sourceNode.definition.id,
118
- targetRefId: this.targetNode.definition.id,
119
- waypoint,
120
- });
121
- }
122
-
123
112
  this.$emit('replace-generic-flow', {
124
113
  actualFlow: flow.makeFlowNode(this.sourceShape, this.target, waypoint),
125
114
  genericFlow: this.node,
@@ -2,6 +2,9 @@ import component from './messageFlow.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 MessageFlow from '@/components/nodes/genericFlow/MessageFlow';
7
+
5
8
  import { id } from '@/components/nodes/messageFlow/config';
6
9
 
7
10
  export default {
@@ -42,4 +45,17 @@ export default {
42
45
  ],
43
46
  },
44
47
  ],
48
+ async multiplayerClient(modeler, data) {
49
+ const { paper } = modeler;
50
+ const sourceElem = modeler.getElementByNodeId( data.sourceRefId);
51
+ const targetElem = modeler.getElementByNodeId( data.targetRefId);
52
+ if (sourceElem && targetElem) {
53
+ const flow = new MessageFlow(modeler.nodeRegistry, modeler.moddle, paper);
54
+ const actualFlow = flow.makeFlowNode(sourceElem, targetElem, data.waypoint);
55
+ // add Nodes
56
+ modeler.addNode(actualFlow, data.id, true);
57
+ const nodeIdereator = getNodeIdGenerator(modeler.definitions);
58
+ nodeIdereator.updateCounters();
59
+ }
60
+ },
45
61
  };
@@ -133,6 +133,31 @@ export default {
133
133
  pull(this.containingProcess.get('flowElements'), elementDefinition);
134
134
  toPool.component.containingProcess.get('flowElements').push(elementDefinition);
135
135
  },
136
+ moveElementRemote(element, toPool) {
137
+ const elementDefinition = element.component.node.definition;
138
+
139
+ if (this.laneSet) {
140
+ /* Remove references to the element from the current Lane */
141
+ const containingLane = this.laneSet.get('lanes').find(lane => {
142
+ return lane.get('flowNodeRef').includes(elementDefinition);
143
+ });
144
+
145
+ pull(containingLane.get('flowNodeRef'), elementDefinition);
146
+ }
147
+
148
+ /* Remove references to the element from the current process */
149
+ pull(this.containingProcess.get('flowElements'), elementDefinition);
150
+
151
+ element.component.node.pool = toPool;
152
+
153
+ this.shape.unembed(element);
154
+ toPool.component.shape.embed(element);
155
+ if (element.component.node.type !== laneId && toPool.component.laneSet) {
156
+ toPool.component.updateLaneChildren();
157
+ }
158
+ this.$emit('set-shape-stacking', element.component.shape);
159
+ },
160
+
136
161
  moveElement(element, toPool) {
137
162
  const elementDefinition = element.component.node.definition;
138
163
 
@@ -155,7 +180,7 @@ export default {
155
180
  this.shape.unembed(element);
156
181
  toPool.component.addToPool(element);
157
182
  },
158
- async addLane() {
183
+ async addLane(emitMultiplayer = true) {
159
184
  /* A Lane element must be contained in a LaneSet element.
160
185
  * Get the current laneSet element or create a new one. */
161
186
 
@@ -177,35 +202,40 @@ export default {
177
202
 
178
203
  lanes.push(this.pushNewLane());
179
204
 
180
- await Promise.all(lanes);
205
+ await Promise.all(lanes)
206
+ .then((val) => {
207
+ if (emitMultiplayer && this.$parent.isMultiplayer) {
208
+ window.ProcessMaker.EventBus.$emit('multiplayer-addLanes', val);
209
+ }
210
+ });
181
211
  this.$emit('set-shape-stacking', this.shape);
182
212
  this.graph.getLinks().forEach(link => {
183
213
  this.$emit('set-shape-stacking', link);
184
214
  });
185
215
  this.$emit('save-state');
186
216
  },
187
- createLaneSet() {
217
+ createLaneSet(id) {
188
218
  const laneSet = this.moddle.create('bpmn:LaneSet');
189
219
  this.laneSet = laneSet;
190
220
  const generator = this.nodeIdGenerator;
191
- const [laneSetId] = generator.generate();
221
+ const [laneSetId] = id ?? generator.generate();
192
222
  this.laneSet.set('id', laneSetId);
193
223
  this.containingProcess.get('laneSets').push(laneSet);
194
224
  },
195
- pushNewLane(definition = Lane.definition(this.moddle, this.$t)) {
225
+ async pushNewLane(definition = Lane.definition(this.moddle, this.$t)) {
196
226
  definition.set('color', this.node.definition.get('color'));
197
227
  this.$emit('set-pool-target', this.shape);
198
228
 
199
229
  const diagram = Lane.diagram(this.moddle);
200
230
  diagram.bounds.width = this.shape.getBBox().width;
201
-
202
- this.$emit('add-node', new Node(
231
+ const node = new Node(
203
232
  Lane.id,
204
233
  definition,
205
234
  diagram,
206
- ));
207
-
208
- return this.$nextTick();
235
+ );
236
+ this.$emit('add-node', node);
237
+ await this.$nextTick();
238
+ return node;
209
239
  },
210
240
  addToPool(element) {
211
241
  if (element.component.node.isBpmnType('bpmn:BoundaryEvent')) {
@@ -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
  },
@@ -239,20 +239,6 @@ export default {
239
239
  if (this.updateDefinitionLinks) {
240
240
  this.updateDefinitionLinks();
241
241
  }
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
- }
254
- }
255
-
256
242
  this.$emit('save-state');
257
243
  });
258
244
 
@@ -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