@processmaker/modeler 1.30.2 → 1.30.3

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.30.2",
3
+ "version": "1.30.3",
4
4
  "scripts": {
5
5
  "serve": "vue-cli-service serve",
6
6
  "open-cypress": "TZ=UTC cypress open",
@@ -222,8 +222,6 @@ export default {
222
222
  if (!store.getters.allowSavingElementPosition) {
223
223
  return;
224
224
  }
225
-
226
- this.$emit('save-state');
227
225
  },
228
226
  repositionCrown() {
229
227
  const shapeView = this.shape.findView(this.paper);
@@ -1190,7 +1190,6 @@ export default {
1190
1190
  if (!this.isDragging && this.dragStart) {
1191
1191
  // is clicked over the shape
1192
1192
  if (cellView) {
1193
- this.$refs.selector.stopDrag(event);
1194
1193
  this.$refs.selector.selectElement(cellView, event.shiftKey);
1195
1194
  } else {
1196
1195
  this.clearSelection();
@@ -35,6 +35,7 @@ import { id as messageFlowId } from '@/components/nodes/messageFlow/config';
35
35
  import { id as dataOutputAssociationFlowId } from '@/components/nodes/dataOutputAssociation/config';
36
36
  import { id as dataInputAssociationFlowId } from '@/components/nodes/dataInputAssociation/config';
37
37
  import { labelWidth, poolPadding } from '../nodes/pool/poolSizes';
38
+ import { invalidNodeColor, poolColor } from '@/components/nodeColors';
38
39
 
39
40
  export default {
40
41
  name: 'Selection',
@@ -53,6 +54,7 @@ export default {
53
54
  isSelecting: false,
54
55
  isSelected: false,
55
56
  selected: [],
57
+ conectedLinks:[],
56
58
  dragging: false,
57
59
  style: {
58
60
  left: '0px',
@@ -79,6 +81,10 @@ export default {
79
81
  selectableBlackList:[
80
82
  genericFlowId,
81
83
  ],
84
+ newPool: null,
85
+ oldPool: null,
86
+ isValidSelectionLinks: true,
87
+ invalidPool: null,
82
88
  };
83
89
  },
84
90
  mounted(){
@@ -96,6 +102,7 @@ export default {
96
102
  watch: {
97
103
  // whenever selected changes
98
104
  selected(newSelected) {
105
+ this.prepareConectedLinks(newSelected);
99
106
  this.addToHighlightedNodes(newSelected);
100
107
  },
101
108
  },
@@ -145,13 +152,21 @@ export default {
145
152
  return;
146
153
  }
147
154
  // validate if there is a lane previously selected
148
- let lane = this.selected.find(view => {
149
- return this.draggableBlackList.includes(view.model.component.node.type);
155
+ let lane = this.selected.find(shape => {
156
+ return this.draggableBlackList.includes(shape.model.component.node.type);
150
157
  });
151
158
  if (lane) {
152
159
  this.selected = [view];
153
160
  return;
154
- }
161
+ }
162
+ // validate if there is a lane previously selected
163
+ let pool = this.selected.find(shape => {
164
+ return shape.model.component.node.type === poolId;
165
+ });
166
+ if (pool && view.model.component.node.type !== poolId) {
167
+ this.selected = [view];
168
+ return;
169
+ }
155
170
  // validate if the current selection is a pool
156
171
  if (view.model.component && view.model.component.node.type === poolId) {
157
172
  //validate if previous selection are all pools
@@ -162,6 +177,14 @@ export default {
162
177
  }
163
178
  return;
164
179
  }
180
+ // prevent select out of the current pool container
181
+ if (view.model.component && view.model.component.node.pool){
182
+ pool = this.getPool(this.selected);
183
+ if (pool && view.model.component.node.pool.id !== pool.model.get('id')) {
184
+ this.selected = [view];
185
+ return;
186
+ }
187
+ }
165
188
  this.selectOrUnselectShape(view);
166
189
  },
167
190
  /**
@@ -294,6 +317,73 @@ export default {
294
317
  });
295
318
  return elements;
296
319
  },
320
+ /**
321
+ * Check if a point is into the area
322
+ * @param {Object} position
323
+ * @param {Object} area
324
+ */
325
+ isPositionWithinArea(position, area) {
326
+ const { x, y, width, height } = area;
327
+ return (
328
+ position.x >= x &&
329
+ position.x <= x + width &&
330
+ position.y >= y &&
331
+ position.y <= y + height
332
+ );
333
+ },
334
+ /**
335
+ * Prepare the conectedLinks collection
336
+ * @param {Array} shapes
337
+ */
338
+ prepareConectedLinks(shapes){
339
+ const { paper } = this.paperManager;
340
+ this.conectedLinks = [];
341
+ this.isValidSelectionLinks = true;
342
+ shapes.forEach((shape) => {
343
+ let conectedLinks = this.graph.getConnectedLinks(shape.model);
344
+ // if the shape is a container
345
+ if ( shape.model.component && shape.model.component.node.type === poolId) {
346
+ const area = shape.model.getBBox();
347
+ const linksInArea = paper.model.getLinks().filter((link) => {
348
+ const sourcePosition = link.getSourcePoint();
349
+ const targetPosition = link.getTargetPoint();
350
+ return (
351
+ this.isPositionWithinArea(sourcePosition, area) ||
352
+ this.isPositionWithinArea(targetPosition, area)
353
+ );
354
+ });
355
+ if (linksInArea) {
356
+ conectedLinks = [...conectedLinks, ...linksInArea];
357
+ }
358
+ }
359
+ conectedLinks.forEach((link) => {
360
+ const linkView = paper.findViewByModel(link);
361
+ if (!this.conectedLinks.some(obj => obj.id === linkView.id)) {
362
+ this.conectedLinks.push(linkView);
363
+ this.validateSelectionLinks(linkView);
364
+ }
365
+ });
366
+ });
367
+ },
368
+ /**
369
+ * Validate if the selection is valid to drag and drop in other container
370
+ * @param {Object} linkView
371
+ */
372
+ validateSelectionLinks(linkView){
373
+ if (this.isValidSelectionLinks) {
374
+ const source = this.selected.find(shape => {
375
+ return shape.model.get('id') === linkView.model.getSourceElement().get('id');
376
+ });
377
+ const target = this.selected.find(shape => {
378
+ return shape.model.get('id') === linkView.model.getTargetElement().get('id');
379
+ });
380
+ if (source && target) {
381
+ this.isValidSelectionLinks = true;
382
+ } else {
383
+ this.isValidSelectionLinks = false;
384
+ }
385
+ }
386
+ },
297
387
  /**
298
388
  * Return the bounding box of the selected elements,
299
389
  * @param {Array} selected
@@ -474,15 +564,30 @@ export default {
474
564
  * Stop drag procedure
475
565
  * @param {Object} event
476
566
  */
477
- stopDrag() {
478
- this.overPoolStopDrag();
479
- this.$emit('save-state');
567
+ async stopDrag() {
480
568
  this.dragging = false;
481
569
  this.stopForceMove = false;
482
570
  // Readjusts the selection box, taking into consideration elements
483
571
  // that are anchored and did not move, such as boundary events.
572
+ await this.$nextTick();
573
+ await this.paperManager.awaitScheduledUpdates();
574
+ this.overPoolStopDrag();
484
575
  this.updateSelectionBox();
485
576
  },
577
+ /**
578
+ * Selector will update the waypoints of the related flows
579
+ */
580
+ updateFlowsWaypoint(){
581
+ this.conectedLinks.forEach((link)=> {
582
+ if (link.model.component && link.model.get('type') === 'standard.Link'){
583
+ const start = link.sourceAnchor;
584
+ const end = link.targetAnchor;
585
+ link.model.component.node.diagram.waypoint = [start,
586
+ ...link.model.component.shape.vertices(),
587
+ end].map(point => link.model.component.moddle.create('dc:Point', point));
588
+ }
589
+ });
590
+ },
486
591
  /**
487
592
  * Translate the Selected shapes adding some custom validations
488
593
  */
@@ -500,10 +605,12 @@ export default {
500
605
  return drafRef.model.get('id') !== shape.model.get('id');
501
606
  });
502
607
  }
503
- // allow movement only if one lane boundary event is selected;
608
+ // allow movements only if one boundary event is selected;
504
609
  if (this.selected && this.selected.length === 1 &&
505
610
  this.selected[0].model.get('type') === 'processmaker.components.nodes.boundaryEvent.Shape') {
506
611
  this.selected[0].model.translate(x, y);
612
+ // validation about boundary event movements
613
+ this.selected[0].model.component.turnInvalidTargetRed();
507
614
  return;
508
615
  }
509
616
  shapes.forEach((shape)=> shape.model.translate(x, y));
@@ -589,6 +696,21 @@ export default {
589
696
  let selectedArea = g.rect(f.x, f.y, width, height);
590
697
  return this.getElementsInSelectedArea(selectedArea, { strict: false });
591
698
  },
699
+ getPool(elements){
700
+ const { paper } = this.paperManager;
701
+ let pool = null;
702
+ if (elements && elements.length > 0) {
703
+ elements.forEach(({ model }) => {
704
+ if (pool) {
705
+ return;
706
+ }
707
+ if (model.getParentCell() && model.getParentCell().component.node.type === poolId){
708
+ pool = model.getParentCell();
709
+ }
710
+ });
711
+ }
712
+ return paper.findViewByModel(pool);
713
+ },
592
714
  /**
593
715
  * Check that they are not in a pool
594
716
  * @param {Array} elements
@@ -613,18 +735,35 @@ export default {
613
735
  if (this.isNotPoolChilds(this.selected)) {
614
736
  return;
615
737
  }
738
+ const currentPool = this.getPool(this.selected);
616
739
  const elementsUnderDivArea = this.getShapesFromPoint(event);
617
740
  const pool = elementsUnderDivArea.find(item => {
618
741
  return item.model.component && item.model.component.node.type === poolId;
619
742
  });
743
+ this.newPool = null;
744
+ this.oldPool = null;
620
745
  if (!pool) {
621
746
  this.isOutOfThePool = true;
622
747
  store.commit('preventSavingElementPosition');
623
748
  this.paperManager.setStateInvalid();
624
749
  } else {
625
- this.isOutOfThePool = false;
626
- store.commit('preventSavingElementPosition');
627
750
  this.paperManager.setStateValid();
751
+
752
+ if (this.invalidPool) {
753
+ this.invalidPool.model.component.shape.attr('body/fill', poolColor);
754
+ this.invalidPool = null;
755
+ }
756
+ if (currentPool && currentPool.model.get('id') !== pool.model.get('id')) {
757
+ this.newPool = pool;
758
+ this.oldPool = currentPool;
759
+ this.isOutOfThePool = false;
760
+ if (!this.isValidSelectionLinks){
761
+ this.isOutOfThePool = true;
762
+ this.invalidPool = pool;
763
+ pool.model.component.shape.attr('body/fill', invalidNodeColor);
764
+ store.commit('preventSavingElementPosition');
765
+ }
766
+ }
628
767
  }
629
768
  },
630
769
  /**
@@ -632,12 +771,31 @@ export default {
632
771
  */
633
772
  overPoolStopDrag(){
634
773
  if (this.isNotPoolChilds(this.selected)) {
774
+ this.updateFlowsWaypoint();
775
+ this.$emit('save-state');
635
776
  return;
636
777
  }
637
778
  if (this.isOutOfThePool) {
638
779
  this.rollbackSelection();
780
+ if (this.invalidPool) {
781
+ this.invalidPool.model.component.shape.attr('body/fill', poolColor);
782
+ this.invalidPool = null;
783
+ }
639
784
  } else {
640
- this.expandToFitElement(this.selected);
785
+ this.updateFlowsWaypoint();
786
+ if (this.newPool){
787
+ /* Remove the shape from its current pool */
788
+ this.moveElements(this.selected, this.oldPool, this.newPool);
789
+ this.newPool = null;
790
+ this.oldPool = null;
791
+ this.updateLaneChildren(this.selected);
792
+ this.$emit('save-state');
793
+ } else {
794
+ this.expandToFitElement(this.selected);
795
+ this.updateLaneChildren(this.selected);
796
+ this.$emit('save-state');
797
+ }
798
+
641
799
  }
642
800
  },
643
801
  /**
@@ -734,10 +892,38 @@ export default {
734
892
  node: pool.component.node,
735
893
  bounds: pool.getBBox(),
736
894
  });
737
- this.$emit('save-state');
738
895
  }
739
896
  }
740
897
  },
898
+ /**
899
+ * Updates the lane children when a element is moved into the pool
900
+ * @param {Array} selected
901
+ */
902
+ updateLaneChildren(selected){
903
+ if (!selected) {
904
+ return;
905
+ }
906
+ const pool = selected.find(({ model }) => {
907
+ if (model.getParentCell()) {
908
+ return model.getParentCell().component.node.type === poolId;
909
+ }
910
+ return false;
911
+ });
912
+ if (pool){
913
+ pool.model.getParentCell();
914
+ pool.model.component.laneSet && pool.component.updateLaneChildren();
915
+ }
916
+ },
917
+ moveElements(selected, oldPool, newPool){
918
+ const shapesToMove= [
919
+ 'PoolLane',
920
+ 'standard.Link',
921
+ ];
922
+ selected.filter(shape => !shapesToMove.includes(shape.model.get('type')))
923
+ .forEach(shape => {
924
+ oldPool.model.component.moveElement(shape.model, newPool.model);
925
+ });
926
+ },
741
927
  },
742
928
  };
743
929
  </script>
@@ -174,8 +174,6 @@ export default {
174
174
  this.shape.listenToOnce(this.paper, 'cell:pointerup blank:pointerup', () => {
175
175
  this.moveBoundaryEventIfOverTask();
176
176
  this.resetInvalidTarget();
177
- this.$emit('save-state');
178
-
179
177
  store.commit('allowSavingElementPosition');
180
178
  });
181
179
  },
@@ -216,9 +214,6 @@ export default {
216
214
  const task = this.getTaskUnderShape();
217
215
  this.attachBoundaryEventToTask(task);
218
216
  this.updateShapePosition(task);
219
-
220
- this.shape.on('change:position', this.turnInvalidTargetRed);
221
- this.shape.listenTo(this.paper, 'element:pointerdown', this.attachToValidTarget);
222
217
  },
223
218
  };
224
219
  </script>
@@ -6,9 +6,10 @@ import DataAssociation from '@/components/nodes/genericFlow/DataAssociation';
6
6
 
7
7
  export default class SequenceFlow extends Flow {
8
8
  static isValid({ sourceShape, targetShape, targetConfig }) {
9
+
9
10
  const targetNode = get(targetShape, 'component.node');
10
11
  const sourceNode = get(sourceShape, 'component.node');
11
-
12
+
12
13
  return Flow.hasTargetType(targetShape) &&
13
14
  Flow.targetIsNotSource(sourceNode, targetNode) &&
14
15
  SequenceFlow.targetIsNotALane(targetNode) &&
@@ -42,7 +42,6 @@ import highlightConfig from '@/mixins/highlightConfig';
42
42
  import AddLaneAboveButton from '@/components/crown/crownButtons/addLaneAboveButton';
43
43
  import AddLaneBelowButton from '@/components/crown/crownButtons/addLaneBelowButton';
44
44
  import { configurePool, elementShouldHaveFlowNodeRef } from '@/components/nodes/pool/poolUtils';
45
- import PoolEventHandlers from '@/components/nodes/pool/poolEventHandlers';
46
45
  import Node from '@/components/nodes/node';
47
46
  import { aPortEveryXPixels } from '@/portsUtils';
48
47
 
@@ -500,13 +499,6 @@ export default {
500
499
  }
501
500
  this.setPoolSize(this.shape);
502
501
  this.$emit('set-shape-stacking', this.shape);
503
-
504
- this.$nextTick(() => {
505
- const handler = new PoolEventHandlers(this.graph, this.paper, this.paperManager, this.shape, this);
506
- this.shape.listenTo(this.graph, 'change:position', (element, newPosition) => handler.onChangePosition(element, newPosition));
507
- this.shape.listenTo(this.paper, 'cell:pointerdown', (cellView) => handler.onPointerDown(cellView));
508
- this.shape.listenTo(this.paper, 'cell:pointerup', (cellView) => handler.onPointerUp(cellView));
509
- });
510
502
  },
511
503
  beforeDestroy() {
512
504
  const participants = this.collaboration.get('participants');
@@ -118,14 +118,23 @@ export default {
118
118
  const targetShape = this.shape.getTargetElement();
119
119
  resetShapeColor(targetShape);
120
120
 
121
- this.shape.listenTo(this.sourceShape, 'change:position', this.updateWaypoints);
122
- this.shape.listenTo(targetShape, 'change:position', this.updateWaypoints);
123
- this.shape.on('change:vertices change:source change:target', this.updateWaypoints);
121
+ this.shape.on('change:vertices', this.onChangeVertices);
124
122
 
125
123
  const sourceShape = this.shape.getSourceElement();
126
124
  sourceShape.embed(this.shape);
127
125
  this.$emit('set-shape-stacking', sourceShape);
128
126
  },
127
+ /**
128
+ * On Change vertices handler
129
+ * @param {Object} link
130
+ * @param {Array} vertices
131
+ * @param {Object} options
132
+ */
133
+ onChangeVertices(link, vertices, options){
134
+ if (options && options.ui) {
135
+ this.updateWaypoints();
136
+ }
137
+ },
129
138
  updateWaypoints() {
130
139
  const linkView = this.shape.findView(this.paper);
131
140
  const start = linkView.sourceAnchor;
@@ -296,7 +305,6 @@ export default {
296
305
  this.paper.el.addEventListener('mousemove', this.updateLinkTarget);
297
306
 
298
307
  this.$emit('set-cursor', 'not-allowed');
299
-
300
308
  if (this.isValidConnection) {
301
309
  this.shape.stopListening(this.paper, 'blank:pointerdown link:pointerdown element:pointerdown', this.removeLink);
302
310
  } else {