@processmaker/modeler 1.24.4 → 1.26.0

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.
@@ -11,7 +11,9 @@
11
11
  @toggle-panels-compressed="panelsCompressed = !panelsCompressed"
12
12
  @toggle-mini-map-open="miniMapOpen = $event"
13
13
  @saveBpmn="saveBpmn"
14
+ @close="close"
14
15
  @save-state="pushToUndoStack"
16
+ @clearSelection="clearSelection"
15
17
  />
16
18
  <b-row class="modeler h-100">
17
19
  <b-tooltip
@@ -50,6 +52,7 @@
50
52
 
51
53
  <InspectorPanel
52
54
  ref="inspector-panel"
55
+ v-show="!(highlightedNodes.length > 1)"
53
56
  :style="{ height: parentHeight }"
54
57
  :nodeRegistry="nodeRegistry"
55
58
  :moddle="moddle"
@@ -60,12 +63,14 @@
60
63
  :parent-height="parentHeight"
61
64
  :canvas-drag-position="canvasDragPosition"
62
65
  :compressed="panelsCompressed && noElementsSelected"
66
+ @shape-resize="shapeResize"
63
67
  />
64
68
 
65
69
  <component
66
70
  v-for="node in nodes"
67
71
  :is="node.type"
68
72
  :key="node._modelerId"
73
+ ref="nodeComponent"
69
74
  :graph="graph"
70
75
  :paper="paper"
71
76
  :node="node"
@@ -89,8 +94,8 @@
89
94
  @remove-node="removeNode"
90
95
  @set-cursor="cursor = $event"
91
96
  @set-pool-target="poolTarget = $event"
92
- @click="highlightNode(node, $event)"
93
97
  @unset-pools="unsetPools"
98
+ @clearSelection="clearSelection"
94
99
  @set-pools="setPools"
95
100
  @save-state="pushToUndoStack"
96
101
  @set-shape-stacking="setShapeStacking"
@@ -99,6 +104,17 @@
99
104
  @replace-generic-flow="replaceGenericFlow"
100
105
  @copy-element="copyElement"
101
106
  @default-flow="toggleDefaultFlow"
107
+ @shape-resize="shapeResize"
108
+ />
109
+ <selection
110
+ v-if="paper"
111
+ ref="selector"
112
+ :graph="graph"
113
+ :paperManager="paperManager"
114
+ :useModelGeometry="false"
115
+ @remove-nodes="removeNodes"
116
+ :processNode="processNode"
117
+ @save-state="pushToUndoStack"
102
118
  />
103
119
  </b-row>
104
120
  </span>
@@ -138,8 +154,7 @@ import ensureShapeIsNotCovered from '@/components/shapeStackUtils';
138
154
  import ToolBar from '@/components/toolbar/ToolBar';
139
155
  import Node from '@/components/nodes/node';
140
156
  import { addNodeToProcess } from '@/components/nodeManager';
141
- import moveShapeByKeypress from '@/components/modeler/moveWithArrowKeys';
142
- import setUpSelectionBox from '@/components/modeler/setUpSelectionBox';
157
+ import hotkeys from '@/components/hotkeys/main';
143
158
  import TimerEventNode from '@/components/nodes/timerEventNode';
144
159
  import focusNameInputAndHighlightLabel from '@/components/modeler/focusNameInputAndHighlightLabel';
145
160
  import XMLManager from '@/components/modeler/XMLManager';
@@ -150,6 +165,8 @@ import addLoopCharacteristics from '@/setup/addLoopCharacteristics';
150
165
 
151
166
  import ProcessmakerModelerGenericFlow from '@/components/nodes/genericFlow/genericFlow';
152
167
 
168
+ import Selection from './Selection';
169
+
153
170
  export default {
154
171
  components: {
155
172
  ToolBar,
@@ -157,6 +174,7 @@ export default {
157
174
  InspectorPanel,
158
175
  MiniPaper,
159
176
  ProcessmakerModelerGenericFlow,
177
+ Selection,
160
178
  },
161
179
  props: {
162
180
  owner: Object,
@@ -167,6 +185,7 @@ export default {
167
185
  },
168
186
  },
169
187
  },
188
+ mixins: [hotkeys],
170
189
  data() {
171
190
  return {
172
191
  tooltipTarget: null,
@@ -209,6 +228,15 @@ export default {
209
228
  activeNode: null,
210
229
  xmlManager: null,
211
230
  previouslyStackedShape: null,
231
+ keyMod: this.isAppleOS() ? 'Command' : 'Control',
232
+ canvasScale: 1,
233
+ initialScale: 1,
234
+ minimumScale: 0.2,
235
+ scaleStep: 0.1,
236
+ isDragging: false,
237
+ isSelecting: false,
238
+ isIntoTheSelection: false,
239
+ dragStart: null,
212
240
  };
213
241
  },
214
242
  watch: {
@@ -237,6 +265,10 @@ export default {
237
265
  autoValidate() {
238
266
  this.validateIfAutoValidateIsOn();
239
267
  },
268
+ canvasScale(canvasScale) {
269
+ this.paperManager.scale = canvasScale;
270
+ },
271
+
240
272
  },
241
273
  computed: {
242
274
  noElementsSelected() {
@@ -261,6 +293,14 @@ export default {
261
293
  },
262
294
  },
263
295
  methods: {
296
+ isAppleOS() {
297
+ return typeof navigator !== 'undefined' && /Mac|iPad|iPhone/.test(navigator.platform);
298
+ },
299
+ async shapeResize() {
300
+ await this.$nextTick();
301
+ await this.paperManager.awaitScheduledUpdates();
302
+ this.$refs.selector.updateSelectionBox(true);
303
+ },
264
304
  toggleDefaultFlow(flow) {
265
305
  const source = flow.definition.sourceRef;
266
306
  if (source.default && source.default.id === flow.id) {
@@ -275,6 +315,9 @@ export default {
275
315
  clonedNode.diagram.bounds.y += yOffset;
276
316
  this.addNode(clonedNode);
277
317
  },
318
+ async close() {
319
+ this.$emit('close');
320
+ },
278
321
  async saveBpmn() {
279
322
  const svg = document.querySelector('.mini-paper svg');
280
323
  const css = 'text { font-family: sans-serif; }';
@@ -330,7 +373,6 @@ export default {
330
373
  try {
331
374
  const xml = await this.getXmlFromDiagram();
332
375
  undoRedoStore.dispatch('pushState', xml);
333
-
334
376
  window.ProcessMaker.EventBus.$emit('modeler-change');
335
377
  } catch (invalidXml) {
336
378
  // eslint-disable-next-line no-console
@@ -403,7 +445,7 @@ export default {
403
445
  let isSameHighlightedNode = _.isEqual(node.id, this.highlightedNode.id);
404
446
 
405
447
  if (!isSameHighlightedNode) {
406
- store.commit('highlightNode', node);
448
+ store.commit('highlightNode', node);
407
449
  }
408
450
 
409
451
  return;
@@ -746,7 +788,6 @@ export default {
746
788
 
747
789
  this.highlightNode(newNode);
748
790
  await this.addNode(newNode);
749
-
750
791
  if (!nodeThatWillBeReplaced) {
751
792
  return;
752
793
  }
@@ -767,7 +808,14 @@ export default {
767
808
  diagram.bounds.x -= (diagram.bounds.width / 2);
768
809
  diagram.bounds.y -= (diagram.bounds.height / 2);
769
810
  },
770
- addNode(node) {
811
+ async selectNewNode(node) {
812
+ await this.$nextTick();
813
+ await this.paperManager.awaitScheduledUpdates();
814
+ const newNodeComponent = this.$refs.nodeComponent.find(component => component.node === node);
815
+ const view = newNodeComponent.shapeView;
816
+ await this.$refs.selector.selectElement(view);
817
+ },
818
+ async addNode(node) {
771
819
  if (!node.pool) {
772
820
  node.pool = this.poolTarget;
773
821
  }
@@ -793,6 +841,9 @@ export default {
793
841
  return;
794
842
  }
795
843
 
844
+ // Select the node after it has been added to the store (does not apply to flows)
845
+ this.selectNewNode(node);
846
+
796
847
  return new Promise(resolve => {
797
848
  setTimeout(() => {
798
849
  this.pushToUndoStack();
@@ -814,9 +865,22 @@ export default {
814
865
  this.removeNodesFromPool(node);
815
866
  store.commit('removeNode', node);
816
867
  store.commit('highlightNode', this.processNode);
868
+ this.$refs.selector.clearSelection();
817
869
  await this.$nextTick();
818
870
  this.pushToUndoStack();
819
871
  },
872
+ async removeNodes() {
873
+ this.performSingleUndoRedoTransaction(async() => {
874
+ await this.paperManager.performAtomicAction(async() => {
875
+ const waitPromises = [];
876
+ this.highlightedNodes.forEach((node) =>
877
+ waitPromises.push(this.removeNode(node, { removeRelationships: true }))
878
+ );
879
+ await Promise.all(waitPromises);
880
+ store.commit('highlightNode');
881
+ });
882
+ });
883
+ },
820
884
  replaceNode({ node, typeToReplaceWith }) {
821
885
  this.performSingleUndoRedoTransaction(async() => {
822
886
  await this.paperManager.performAtomicAction(async() => {
@@ -829,6 +893,7 @@ export default {
829
893
 
830
894
  await this.removeNode(node, { removeRelationships: false });
831
895
  this.highlightNode(newNode);
896
+ this.selectNewNode(newNode);
832
897
  });
833
898
  });
834
899
  },
@@ -898,18 +963,6 @@ export default {
898
963
 
899
964
  this.paperManager.setPaperDimensions(clientWidth, clientHeight);
900
965
  },
901
- keydownListener(event) {
902
- const focusIsOutsideDiagram = !event.target.toString().toLowerCase().includes('body');
903
- if (focusIsOutsideDiagram) {
904
- return;
905
- }
906
-
907
- moveShapeByKeypress(
908
- event.key,
909
- store.getters.highlightedShapes,
910
- this.pushToUndoStack,
911
- );
912
- },
913
966
  validateDropTarget({ clientX, clientY, control }) {
914
967
  const { allowDrop, poolTarget } = getValidationProperties(clientX, clientY, control, this.paperManager.paper, this.graph, this.collaboration, this.$refs['paper-container']);
915
968
  this.allowDrop = allowDrop;
@@ -926,6 +979,106 @@ export default {
926
979
  this.previouslyStackedShape = shape;
927
980
  this.paperManager.performAtomicAction(() => ensureShapeIsNotCovered(shape, this.graph));
928
981
  },
982
+ showSavedNotification() {
983
+ undoRedoStore.dispatch('saved');
984
+ },
985
+ enableVersions() {
986
+ undoRedoStore.dispatch('enableVersions');
987
+ },
988
+ setVersionIndicator(isDraft) {
989
+ undoRedoStore.dispatch('setVersionIndicator', isDraft);
990
+ },
991
+ setLoadingState(isLoading) {
992
+ undoRedoStore.dispatch('setLoadingState', isLoading);
993
+ },
994
+ clearSelection(){
995
+ this.$refs.selector.clearSelection();
996
+ },
997
+ isPointInSelection(event) {
998
+ const selector = this.$refs.selector.$el;
999
+ if (typeof selector.getBoundingClientRect === 'function') {
1000
+ // check if mouse was clicked inside the selector
1001
+ const { x: sx, y: sy, width:swidth, height: sheight } = selector.getBoundingClientRect();
1002
+ if (event.clientX >= sx && event.clientX <= sx + swidth && event.clientY >= sy && event.clientY <= sy + sheight) {
1003
+ return true;
1004
+ }
1005
+ }
1006
+ return false;
1007
+ },
1008
+ async pointerDowInShape(event, element) {
1009
+ const { clientX: x, clientY: y } = event;
1010
+ const shapeView = this.paper.findViewByModel(element);
1011
+ this.isDragging = false;
1012
+ this.isSelecting = false;
1013
+ this.isIntoTheSelection = false;
1014
+ this.dragStart = { x, y };
1015
+ // Verify if is in the selection box
1016
+ if (this.isPointInSelection(event)) {
1017
+ this.isIntoTheSelection = true;
1018
+ } else {
1019
+ if (!event.shiftKey) {
1020
+ await this.$refs.selector.selectElement(shapeView);
1021
+ await this.$nextTick();
1022
+ }
1023
+ }
1024
+ this.$refs.selector.startDrag({
1025
+ clientX: event.clientX,
1026
+ clientY: event.clientY,
1027
+ });
1028
+ },
1029
+ pointerDownHandler(event) {
1030
+ const { clientX: x, clientY: y } = event;
1031
+ this.isDragging = false;
1032
+ this.isSelecting = false;
1033
+ this.isIntoTheSelection = false;
1034
+ this.dragStart = { x, y };
1035
+ // Verify if is in the selection box
1036
+ if (this.isPointInSelection(event)) {
1037
+ this.isIntoTheSelection = true;
1038
+ this.$refs.selector.startDrag({
1039
+ clientX: event.clientX,
1040
+ clientY: event.clientY,
1041
+ });
1042
+ } else {
1043
+ this.isSelecting = true;
1044
+ this.$refs.selector.startSelection(event);
1045
+ }
1046
+ },
1047
+ pointerMoveHandler(event) {
1048
+ const { clientX: x, clientY: y } = event;
1049
+ if (this.dragStart && (Math.abs(x - this.dragStart.x) > 5 || Math.abs(y - this.dragStart.y) > 5)) {
1050
+ this.isDragging = true;
1051
+ this.dragStart = null;
1052
+ } else {
1053
+ if (this.isSelecting) {
1054
+ this.$refs.selector.updateSelection(event);
1055
+ } else {
1056
+ if (this.isDragging) {
1057
+ this.$refs.selector.drag(event);
1058
+ }
1059
+ }
1060
+ }
1061
+ },
1062
+ pointerUpHandler(event, cellView) {
1063
+ if (!this.isDragging && this.dragStart) {
1064
+ // is clicked over the shape
1065
+ if (cellView) {
1066
+ this.$refs.selector.stopDrag(event);
1067
+ this.$refs.selector.selectElement(cellView, event.shiftKey);
1068
+ } else {
1069
+ this.clearSelection();
1070
+ }
1071
+ } else {
1072
+ if (this.isSelecting) {
1073
+ this.$refs.selector.endSelection(this.paperManager.paper);
1074
+ } else {
1075
+ this.$refs.selector.stopDrag(event);
1076
+ }
1077
+ }
1078
+ this.isDragging = false;
1079
+ this.dragStart = null;
1080
+ this.isSelecting = false;
1081
+ },
929
1082
  },
930
1083
  created() {
931
1084
  if (runningInCypressTest()) {
@@ -959,13 +1112,12 @@ export default {
959
1112
  this.$emit('set-xml-manager', this.xmlManager);
960
1113
  },
961
1114
  mounted() {
962
- document.addEventListener('keydown', this.keydownListener);
963
-
964
1115
  this.graph = new dia.Graph();
965
1116
  store.commit('setGraph', this.graph);
966
1117
  this.graph.set('interactiveFunc', cellView => {
1118
+ const isPoolEdge = cellView.model.get('type') === 'standard.EmbeddedImage';
967
1119
  return {
968
- elementMove: cellView.model.get('elementMove'),
1120
+ elementMove: isPoolEdge,
969
1121
  labelMove: false,
970
1122
  };
971
1123
  });
@@ -980,31 +1132,29 @@ export default {
980
1132
 
981
1133
  store.commit('setPaper', this.paperManager.paper);
982
1134
 
983
- this.paperManager.addEventHandler('blank:pointerclick', () => {
984
- store.commit('highlightNode', this.processNode);
985
- }, this);
986
-
987
1135
  this.paperManager.addEventHandler('element:pointerclick', this.blurFocusedScreenBuilderElement, this);
988
1136
 
989
1137
  this.paperManager.addEventHandler('blank:pointerdown', (event, x, y) => {
1138
+ if (this.isGrabbing) return;
990
1139
  const scale = this.paperManager.scale;
991
1140
  this.canvasDragPosition = { x: x * scale.sx, y: y * scale.sy };
992
- this.isGrabbing = true;
1141
+ this.isOverShape = false;
1142
+ this.pointerDownHandler(event);
993
1143
  }, this);
994
- this.paperManager.addEventHandler('cell:pointerup blank:pointerup', () => {
1144
+ this.paperManager.addEventHandler('blank:pointerup', (event) => {
995
1145
  this.canvasDragPosition = null;
996
- this.isGrabbing = false;
997
1146
  this.activeNode = null;
1147
+ this.pointerUpHandler(event);
1148
+ }, this);
1149
+ this.paperManager.addEventHandler('cell:pointerup', (cellView, event) => {
1150
+ this.canvasDragPosition = null;
1151
+ this.activeNode = null;
1152
+ this.pointerUpHandler(event, cellView);
998
1153
  }, this);
999
1154
 
1000
1155
  this.$el.addEventListener('mousemove', event => {
1001
- if (this.canvasDragPosition) {
1002
- this.paperManager.translate(
1003
- event.offsetX - this.canvasDragPosition.x,
1004
- event.offsetY - this.canvasDragPosition.y,
1005
- );
1006
- }
1007
- }, this);
1156
+ this.pointerMoveHandler(event);
1157
+ });
1008
1158
 
1009
1159
  this.paperManager.addEventHandler('cell:pointerclick', (cellView, evt, x, y) => {
1010
1160
  const clickHandler = cellView.model.get('onClick');
@@ -1021,23 +1171,16 @@ export default {
1021
1171
  shape.component.$emit('click', event);
1022
1172
  });
1023
1173
 
1024
- this.paperManager.addEventHandler('cell:pointerdown', ({ model: shape }) => {
1174
+ this.paperManager.addEventHandler('cell:pointerdown', ({ model: shape }, event) => {
1025
1175
  if (!this.isBpmnNode(shape)) {
1026
1176
  return;
1027
1177
  }
1028
-
1029
1178
  this.setShapeStacking(shape);
1030
1179
  this.activeNode = shape.component.node;
1180
+ this.isOverShape = true;
1181
+ this.pointerDowInShape(event, shape);
1031
1182
  });
1032
1183
 
1033
- let cursor;
1034
- const setCursor = () => {
1035
- cursor = this.cursor;
1036
- this.cursor = 'crosshair';
1037
- };
1038
- const resetCursor = () => this.cursor = cursor;
1039
- setUpSelectionBox(setCursor, resetCursor, this.paperManager, this.graph);
1040
-
1041
1184
  /* Register custom nodes */
1042
1185
  window.ProcessMaker.EventBus.$emit('modeler-start', {
1043
1186
  loadXML: xml => {