@processmaker/modeler 1.27.0 → 1.29.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.
Files changed (32) hide show
  1. package/dist/modeler.common.js +1519 -822
  2. package/dist/modeler.common.js.map +1 -1
  3. package/dist/modeler.umd.js +1519 -822
  4. package/dist/modeler.umd.js.map +1 -1
  5. package/dist/modeler.umd.min.js +3 -3
  6. package/dist/modeler.umd.min.js.map +1 -1
  7. package/package.json +1 -1
  8. package/src/NodeIdGenerator.js +55 -22
  9. package/src/NodeInspector.js +2 -2
  10. package/src/components/crown/crownButtons/{duplicateButton.vue → cloneButton.vue} +10 -9
  11. package/src/components/crown/crownConfig/crownConfig.vue +3 -4
  12. package/src/components/crown/crownMultiselect/crownMultiselect.vue +20 -7
  13. package/src/components/crown/utils.js +12 -1
  14. package/src/components/hotkeys/copyPaste.js +7 -4
  15. package/src/components/hotkeys/main.js +6 -1
  16. package/src/components/inspectors/DocumentationFormTextArea.vue +6 -2
  17. package/src/components/inspectors/LoopCharacteristics.vue +5 -2
  18. package/src/components/inspectors/process.js +5 -1
  19. package/src/components/modeler/Modeler.vue +92 -99
  20. package/src/components/modeler/Selection.vue +40 -29
  21. package/src/components/nodes/association/index.js +3 -0
  22. package/src/components/nodes/dataInputAssociation/dataInputAssociation.vue +36 -26
  23. package/src/components/nodes/genericFlow/DataOutputAssociation.js +54 -2
  24. package/src/components/nodes/genericFlow/genericFlow.vue +0 -17
  25. package/src/components/nodes/node.js +81 -8
  26. package/src/components/nodes/pool/poolEventHandlers.js +0 -9
  27. package/src/components/toolbar/ToolBar.vue +21 -9
  28. package/src/components/toolbar/toolbar.scss +2 -1
  29. package/src/mixins/cloneSelection.js +153 -0
  30. package/src/mixins/linkConfig.js +4 -1
  31. package/src/store.js +7 -11
  32. package/src/undoRedoStore.js +4 -19
@@ -86,23 +86,6 @@ export default {
86
86
  },
87
87
  },
88
88
  watch: {
89
- 'node.definition': {
90
- handler() {
91
- const newNameLabel = this.shapeName;
92
-
93
- if (newNameLabel !== this.nameLabel) {
94
- this.nameLabel = newNameLabel;
95
- }
96
- this.setDefaultMarker(this.isDefaultFlow());
97
- },
98
- deep: true,
99
- },
100
- 'node.definition.sourceRef': {
101
- handler() {
102
- this.setDefaultMarker(this.isDefaultFlow());
103
- },
104
- deep: true,
105
- },
106
89
  },
107
90
  methods: {
108
91
  completeLink() {
@@ -10,7 +10,7 @@ import cloneDeep from 'lodash/cloneDeep';
10
10
 
11
11
  export default class Node {
12
12
  static diagramPropertiesToCopy = ['x', 'y', 'width', 'height'];
13
- static definitionPropertiesToNotCopy = ['$type', 'id'];
13
+ static definitionPropertiesToNotCopy = ['$type', 'id', 'dataOutputAssociations'];
14
14
  static flowDefinitionPropertiesToNotCopy = ['$type', 'id', 'sourceRef', 'targetRef'];
15
15
  static eventDefinitionPropertiesToNotCopy = ['errorRef', 'messageRef'];
16
16
 
@@ -81,6 +81,70 @@ export default class Node {
81
81
  this.diagram.id = diagramId;
82
82
  this.diagram.bpmnElement = this.definition;
83
83
  }
84
+ if (this.definition.loopCharacteristics && this.definition.loopCharacteristics.$type === 'bpmn:StandardLoopCharacteristics') {
85
+ this.definition.loopCharacteristics.set('id', nodeIdGenerator.generate()[0]);
86
+ if (this.definition.loopCharacteristics.loopCondition) {
87
+ this.definition.loopCharacteristics.get('loopCondition').set('id', nodeIdGenerator.generate()[0]);
88
+ }
89
+ }
90
+ let dataInputRef, dataOutputRef;
91
+ if (this.definition.ioSpecification) {
92
+ this.definition.ioSpecification.set('id', nodeIdGenerator.generate()[0]);
93
+ const taskId = this.definition.id;
94
+ if (this.definition.ioSpecification.get('dataInputs')) {
95
+ this.definition.ioSpecification.get('dataInputs').forEach(dataInput => {
96
+ const id = dataInput.get('id');
97
+ if (id.substring(0, this.cloneOf.length) === this.cloneOf) {
98
+ dataInput.set('id', id.replace(this.cloneOf + '_', taskId + '_'));
99
+ dataInputRef = dataInput;
100
+ } else {
101
+ dataInput.set('id', nodeIdGenerator.generate()[0]);
102
+ }
103
+ });
104
+ }
105
+ if (this.definition.ioSpecification.get('dataOutputs')) {
106
+ this.definition.ioSpecification.get('dataOutputs').forEach(dataOutput => {
107
+ const id = dataOutput.get('id');
108
+ if (id.substring(0, this.cloneOf.length) === this.cloneOf) {
109
+ dataOutput.set('id', id.replace(this.cloneOf + '_', taskId + '_'));
110
+ dataOutputRef = dataOutput;
111
+ } else {
112
+ dataOutput.set('id', nodeIdGenerator.generate()[0]);
113
+ }
114
+ });
115
+ }
116
+ if (this.definition.ioSpecification.get('inputSets')) {
117
+ this.definition.ioSpecification.get('inputSets').forEach(inputSet => {
118
+ inputSet.set('id', nodeIdGenerator.generate()[0]);
119
+ });
120
+ }
121
+ if (this.definition.ioSpecification.get('outputSets')) {
122
+ this.definition.ioSpecification.get('outputSets').forEach(outputSet => {
123
+ outputSet.set('id', nodeIdGenerator.generate()[0]);
124
+ });
125
+ }
126
+ }
127
+ if (this.definition.loopCharacteristics && this.definition.loopCharacteristics.$type === 'bpmn:MultiInstanceLoopCharacteristics') {
128
+ this.definition.loopCharacteristics.set('id', nodeIdGenerator.generate()[0]);
129
+ if (this.definition.loopCharacteristics.loopCardinality) {
130
+ this.definition.loopCharacteristics.get('loopCardinality').set('id', nodeIdGenerator.generate()[0]);
131
+ }
132
+ if (this.definition.loopCharacteristics.loopDataInputRef && dataInputRef) {
133
+ this.definition.loopCharacteristics.set('loopDataInputRef', dataInputRef);
134
+ }
135
+ if (this.definition.loopCharacteristics.loopDataOutputRef && dataOutputRef) {
136
+ this.definition.loopCharacteristics.set('loopDataOutputRef', dataOutputRef);
137
+ }
138
+ if (this.definition.loopCharacteristics.inputDataItem) {
139
+ this.definition.loopCharacteristics.get('inputDataItem').set('id', nodeIdGenerator.generate()[0]);
140
+ }
141
+ if (this.definition.loopCharacteristics.outputDataItem) {
142
+ this.definition.loopCharacteristics.get('outputDataItem').set('id', nodeIdGenerator.generate()[0]);
143
+ }
144
+ if (this.definition.loopCharacteristics.completionCondition) {
145
+ this.definition.loopCharacteristics.get('completionCondition').set('id', nodeIdGenerator.generate()[0]);
146
+ }
147
+ }
84
148
  }
85
149
 
86
150
  clone(nodeRegistry, moddle, $t) {
@@ -90,7 +154,7 @@ export default class Node {
90
154
 
91
155
  clonedNode.id = null;
92
156
  clonedNode.pool = this.pool;
93
- clonedNode.definition.cloneOf = this.id;
157
+ clonedNode.cloneOf = this.id;
94
158
 
95
159
  Node.diagramPropertiesToCopy.forEach(prop => clonedNode.diagram.bounds[prop] = this.diagram.bounds[prop]);
96
160
  Object.keys(this.definition).filter(key => !Node.definitionPropertiesToNotCopy.includes(key)).forEach(key => {
@@ -99,7 +163,7 @@ export default class Node {
99
163
  if (key === 'eventDefinitions') {
100
164
  for (var i in clonedDefinition) {
101
165
  if (definition[i].signalRef && !clonedDefinition[i].signalRef) {
102
- clonedDefinition[i].signalRef = { ...definition[i].signalRef };
166
+ clonedDefinition[i].set('signalRef', { ...definition[i].signalRef });
103
167
  }
104
168
  }
105
169
  }
@@ -122,10 +186,18 @@ export default class Node {
122
186
 
123
187
  clonedFlow.id = null;
124
188
  clonedFlow.pool = this.pool;
125
- clonedFlow.definition.cloneOf = this.id;
126
- clonedFlow.diagram.waypoint = [];
189
+ clonedFlow.cloneOf = this.id;
190
+ clonedFlow.diagram = moddle.create('bpmndi:BPMNEdge', {
191
+ waypoint: [],
192
+ });
127
193
 
128
- this.diagram.waypoint.forEach(point => clonedFlow.diagram.waypoint.push(point));
194
+ this.diagram.waypoint.forEach(point => {
195
+ const waypoint = moddle.create('dc:Point', {
196
+ x: point.x,
197
+ y: point.y,
198
+ });
199
+ clonedFlow.diagram.waypoint.push(waypoint);
200
+ });
129
201
 
130
202
  Object.keys(this.definition).filter(key => !Node.flowDefinitionPropertiesToNotCopy.includes(key)).forEach(key => {
131
203
  const definition = this.definition.get(key);
@@ -133,12 +205,13 @@ export default class Node {
133
205
  if (key === 'eventDefinitions') {
134
206
  for (var i in clonedDefinition) {
135
207
  if (definition[i].signalRef && !clonedDefinition[i].signalRef) {
136
- clonedDefinition[i].signalRef = { ...definition[i].signalRef };
208
+ clonedDefinition[i].set('signalRef', { ...definition[i].signalRef });
137
209
  }
138
210
  }
139
211
  }
140
212
  clonedFlow.definition.set(key, clonedDefinition);
141
- clonedFlow.definition.sourceRef = clonedFlow.definition.targetRef = null;
213
+ clonedFlow.definition.set('sourceRef', null);
214
+ clonedFlow.definition.set('targetRef', null);
142
215
  });
143
216
 
144
217
  Node.eventDefinitionPropertiesToNotCopy.forEach(
@@ -46,14 +46,6 @@ export default class PoolEventHandlers {
46
46
  return;
47
47
  }
48
48
 
49
- if (this.previousValidPosition) {
50
- this.draggingElement.position(this.previousValidPosition.x, this.previousValidPosition.y, { deep: true });
51
- store.commit('updateNodeBounds', {
52
- node: this.draggingElement.component.node,
53
- bounds: this.previousValidPosition,
54
- });
55
- }
56
-
57
49
  if (this.invalidPool) {
58
50
  this.invalidPool.attr('body/fill', poolColor);
59
51
  this.invalidPool = null;
@@ -64,7 +56,6 @@ export default class PoolEventHandlers {
64
56
  this.component.moveElement(this.draggingElement, this.newPool);
65
57
  this.newPool = null;
66
58
  } else {
67
- this.component.expandToFitElement(this.draggingElement, this.shape);
68
59
  this.component.laneSet && this.component.updateLaneChildren();
69
60
  }
70
61
 
@@ -101,7 +101,7 @@
101
101
  </span>
102
102
  </div>
103
103
  <a
104
- class="btn btn-sm btn-primary autosave-btn text-uppercase mx-2"
104
+ class="btn btn-sm btn-primary btn-autosave text-uppercase mx-2"
105
105
  data-test="publish-btn"
106
106
  :title="$t('Publish')"
107
107
  @click="$emit('saveBpmn')"
@@ -109,7 +109,7 @@
109
109
  {{ $t('Publish') }}
110
110
  </a>
111
111
  <a
112
- class="btn btn-sm btn-link toolbar-item autosave-btn text-black text-uppercase"
112
+ class="btn btn-sm btn-link toolbar-item btn-autosave text-black text-uppercase"
113
113
  data-test="close-btn"
114
114
  :title="$t('Close')"
115
115
  @click="$emit('close')"
@@ -183,9 +183,6 @@ export default {
183
183
  canRedo() {
184
184
  return undoRedoStore.getters.canRedo;
185
185
  },
186
- saved() {
187
- return undoRedoStore.getters.saved;
188
- },
189
186
  versionStatus() {
190
187
  const status = undoRedoStore.getters.isDraft ? 'Draft' : 'Published';
191
188
  return this.$t(status);
@@ -227,6 +224,11 @@ export default {
227
224
  content: this.$t('Discard Draft'),
228
225
  icon: '',
229
226
  },
227
+ {
228
+ value: 'save-template',
229
+ content: this.$t('Save as Template'),
230
+ icon: '',
231
+ },
230
232
  ],
231
233
  };
232
234
  },
@@ -238,8 +240,7 @@ export default {
238
240
  }
239
241
  undoRedoStore
240
242
  .dispatch('undo')
241
- .then(() => this.$emit('load-xml'))
242
- .then(() => window.ProcessMaker.EventBus.$emit('modeler-change'));
243
+ .then(() => this.$emit('load-xml'));
243
244
  },
244
245
  redo() {
245
246
  this.$emit('clearSelection');
@@ -248,14 +249,16 @@ export default {
248
249
  }
249
250
  undoRedoStore
250
251
  .dispatch('redo')
251
- .then(() => this.$emit('load-xml'))
252
- .then(() => window.ProcessMaker.EventBus.$emit('modeler-change'));
252
+ .then(() => this.$emit('load-xml'));
253
253
  },
254
254
  onNavigate(action) {
255
255
  switch (action.value) {
256
256
  case 'discard-draft':
257
257
  window.ProcessMaker.EventBus.$emit('open-versions-discard-modal');
258
258
  break;
259
+ case 'save-template':
260
+ this.$emit('publishTemplate');
261
+ break;
259
262
  default:
260
263
  break;
261
264
  }
@@ -273,6 +276,15 @@ export default {
273
276
  }
274
277
  },
275
278
  },
279
+ mounted() {
280
+ if (this.$root.$children[0].process.is_template) {
281
+ const indexOfActions = this.ellipsisMenuActions.findIndex(object => {
282
+ return object.value === 'save-template';
283
+ });
284
+
285
+ this.ellipsisMenuActions.splice(indexOfActions, 1);
286
+ }
287
+ },
276
288
  };
277
289
  </script>
278
290
  <style lang="scss" src="./toolbar.scss" />
@@ -28,10 +28,11 @@ $toolbar-background-color: #fff;
28
28
  cursor: default !important;
29
29
  }
30
30
 
31
- .autosave-btn {
31
+ .btn-autosave {
32
32
  display: flex;
33
33
  justify-content: center;
34
34
  align-items: center;
35
+ border-radius: 4px !important;
35
36
  }
36
37
 
37
38
  .btn-ellipsis {
@@ -0,0 +1,153 @@
1
+ import { id as laneId } from '../components/nodes/poolLane/config';
2
+ import { id as sequenceFlowId } from '../components/nodes/sequenceFlow';
3
+ import { id as associationId } from '../components/nodes/association';
4
+ import { id as messageFlowId } from '../components/nodes/messageFlow/config';
5
+ import { id as dataOutputAssociationFlowId } from '../components/nodes/dataOutputAssociation/config';
6
+ import { id as dataInputAssociationFlowId } from '../components/nodes/dataInputAssociation/config';
7
+ import { id as genericFlowId } from '../components/nodes/genericFlow/config';
8
+ import { getOrFindDataInput, findIOSpecificationOwner } from '../components/crown/utils';
9
+
10
+ export default {
11
+ methods: {
12
+ cloneNodesSelection() {
13
+ let clonedNodes = [], clonedFlows = [], clonedBoundaryEvents = [], clonedDataInputAssociations = [], clonedDataOutputAssociations = [];
14
+ const nodes = this.highlightedNodes;
15
+ const selector = this.$refs.selector.$el;
16
+ const flowNodeTypes = [
17
+ sequenceFlowId,
18
+ laneId,
19
+ associationId,
20
+ messageFlowId,
21
+ genericFlowId,
22
+ ];
23
+ const dataInputAssociationNodeTypes = [
24
+ dataInputAssociationFlowId,
25
+ ];
26
+ const dataOutputAssociationNodeTypes = [
27
+ dataOutputAssociationFlowId,
28
+ ];
29
+
30
+ if (typeof selector.getBoundingClientRect === 'function') {
31
+ nodes.forEach(node => {
32
+ if (flowNodeTypes.includes(node.type)) {
33
+ const clonedFlow = this.cloneFlowAndSetNewId(node);
34
+ clonedFlows.push(clonedFlow);
35
+ clonedNodes.push(clonedFlow);
36
+ } else if (dataInputAssociationNodeTypes.includes(node.type)) {
37
+ const clonedFlow = this.cloneFlowAndSetNewId(node);
38
+ clonedDataInputAssociations.push(clonedFlow);
39
+ clonedNodes.push(clonedFlow);
40
+ } else if (dataOutputAssociationNodeTypes.includes(node.type)) {
41
+ const clonedFlow = this.cloneFlowAndSetNewId(node);
42
+ clonedDataOutputAssociations.push(clonedFlow);
43
+ clonedNodes.push(clonedFlow);
44
+ } else {
45
+ // Validate boundary events and collect in clonedBoundaryEvents array
46
+ const clonedElement = this.cloneElementAndCalculateOffset(node);
47
+ if (node.definition && node.definition.$type !== 'bpmn:BoundaryEvent') {
48
+ clonedNodes.push(clonedElement);
49
+ } else {
50
+ clonedBoundaryEvents.push(clonedElement);
51
+ }
52
+ }
53
+ });
54
+ }
55
+ // Sets the clonedBoundaryEvents at the end of the array
56
+ clonedNodes = [...clonedNodes, ...clonedBoundaryEvents];
57
+ this.connectClonedFlows(clonedFlows, clonedNodes);
58
+ this.connectClonedDataInputAssociations(clonedDataInputAssociations, clonedNodes);
59
+ this.connectClonedDataOutputAssociations(clonedDataOutputAssociations, clonedNodes);
60
+
61
+ return clonedNodes;
62
+ },
63
+ // Returns the Flow Element (Task| DataStore| DataObject) that is the target of the association
64
+ getDataInputOutputAssociationTargetRef(association) {
65
+ if (association.targetRef.$type === 'bpmn:DataInput') {
66
+ const ioSpec = association.targetRef.$parent;
67
+ return findIOSpecificationOwner(ioSpec, this);
68
+ }
69
+ if (association.targetRef.$type === 'bpmn:DataInputAssociation') {
70
+ const ioSpec = association.targetRef.$parent;
71
+ return findIOSpecificationOwner(ioSpec, this);
72
+ }
73
+ return association.targetRef;
74
+ },
75
+ cloneFlowAndSetNewId(node) {
76
+ const clonedFlow = node.cloneFlow(this.nodeRegistry, this.moddle, this.$t);
77
+ clonedFlow.setIds(this.nodeIdGenerator);
78
+ return clonedFlow;
79
+ },
80
+ cloneElementAndCalculateOffset(node) {
81
+ const clonedElement = node.clone(this.nodeRegistry, this.moddle, this.$t);
82
+ const { height: selectorHeight } = this.$refs.selector.$el.getBoundingClientRect();
83
+ const { sy } = this.paper.scale();
84
+ const yOffset = selectorHeight / sy;
85
+ clonedElement.diagram.bounds.y += yOffset;
86
+ clonedElement.setIds(this.nodeIdGenerator);
87
+ return clonedElement;
88
+ },
89
+ connectClonedFlows(clonedFlows, clonedNodes) {
90
+ clonedFlows.forEach(clonedFlow => {
91
+ const originalFlow = this.nodes.find(node => node.definition.id === clonedFlow.cloneOf);
92
+ const src = originalFlow.definition.sourceRef;
93
+ const target = originalFlow.definition.targetRef;
94
+ const srcClone = clonedNodes.find(node => node.cloneOf === src.id);
95
+ const targetClone = clonedNodes.find(node => node.cloneOf === target.id);
96
+ if (!srcClone || !targetClone) {
97
+ clonedNodes.splice(clonedNodes.indexOf(clonedFlow), 1);
98
+ return;
99
+ }
100
+ clonedFlow.definition.set('sourceRef', srcClone.definition);
101
+ clonedFlow.definition.set('targetRef', targetClone.definition);
102
+
103
+ if (srcClone.definition.outgoing) {
104
+ srcClone.definition.outgoing.push(clonedFlow.definition);
105
+ } else {
106
+ srcClone.definition.set('outgoing', [clonedFlow.definition]);
107
+ }
108
+
109
+ if (targetClone.definition.incoming) {
110
+ targetClone.definition.incoming.push(clonedFlow.definition);
111
+ } else {
112
+ targetClone.definition.set('incoming', [clonedFlow.definition]);
113
+ }
114
+
115
+ const { height: selectorHeight } = this.$refs.selector.$el.getBoundingClientRect();
116
+ const { sy } = this.paper.scale();
117
+ const yOffset = selectorHeight / sy;
118
+ clonedFlow.diagram.waypoint.forEach(point => {
119
+ point.y += yOffset;
120
+ });
121
+ });
122
+ },
123
+ connectClonedDataInputAssociations(clonedDataInputAssociations, clonedNodes) {
124
+ clonedDataInputAssociations.forEach(clonedAssociation => {
125
+ const originalAssociation = this.nodes.find(node => node.definition.id === clonedAssociation.cloneOf);
126
+ const src = originalAssociation.definition.sourceRef[0];
127
+ const srcClone = clonedNodes.find(node => node.cloneOf === src.id);
128
+ const originalTargetElement = this.getDataInputOutputAssociationTargetRef(originalAssociation.definition);
129
+ const clonedElement = clonedNodes.find(node => node.cloneOf === originalTargetElement.id);
130
+ const clonedDataInput = getOrFindDataInput(this.moddle, clonedElement, srcClone.definition);
131
+
132
+ clonedAssociation.definition.set('sourceRef', [srcClone.definition]);
133
+ clonedAssociation.definition.set('targetRef', clonedDataInput);
134
+ clonedElement.definition.set('dataInputAssociations', [clonedAssociation.definition]);
135
+ });
136
+ },
137
+ connectClonedDataOutputAssociations(clonedDataOutputAssociations, clonedNodes) {
138
+ clonedDataOutputAssociations.forEach(clonedAssociation => {
139
+ const originalAssociation = this.nodes.find(node => node.definition.id === clonedAssociation.cloneOf);
140
+ const src = originalAssociation.definition.sourceRef || originalAssociation.definition.$parent;
141
+ const target = originalAssociation.definition.targetRef;
142
+ const srcClone = clonedNodes.find(node => node.cloneOf === src.id);
143
+ const targetClone = clonedNodes.find(node => node.cloneOf === target.id);
144
+
145
+ clonedAssociation.definition.set('targetRef', targetClone.definition);
146
+ clonedAssociation.definition.set('sourceRef', srcClone.definition);
147
+
148
+ const existingOutputAssociations = srcClone.definition.get('dataOutputAssociations') || [];
149
+ srcClone.definition.set('dataOutputAssociations', [...existingOutputAssociations, clonedAssociation.definition]);
150
+ });
151
+ },
152
+ },
153
+ };
@@ -78,7 +78,7 @@ export default {
78
78
  });
79
79
  },
80
80
  setEndpoint(shape, endpoint, connectionOffset) {
81
- if (isPoint(shape)) {
81
+ if (shape && isPoint(shape)) {
82
82
  return this.shape[endpoint](shape, {
83
83
  anchor: {
84
84
  name: 'modelCenter',
@@ -253,6 +253,9 @@ export default {
253
253
  ? this.getTargetRef()
254
254
  : this.node.definition.get('targetRef');
255
255
 
256
+ // if flow doesn't have a targetRef such as incomplete node, return
257
+ if (!targetRef) return;
258
+
256
259
  if (targetRef.id) {
257
260
  const targetShape = this.graph.getElements().find(element => {
258
261
  return element.component && element.component.node.definition === targetRef;
package/src/store.js CHANGED
@@ -36,8 +36,7 @@ export default new Vuex.Store({
36
36
  globalProcesses: [],
37
37
  allowSavingElementPosition: true,
38
38
  copiedElements: [],
39
- clientX: null,
40
- clientY: null,
39
+ clientLeftPaper: false,
41
40
  },
42
41
  getters: {
43
42
  nodes: state => state.nodes,
@@ -56,8 +55,7 @@ export default new Vuex.Store({
56
55
  globalProcessEvents: (state, getters) => flatten(getters.globalProcesses.map(process => process.events)),
57
56
  allowSavingElementPosition: state => state.allowSavingElementPosition,
58
57
  copiedElements: state => state.copiedElements,
59
- clientX: state => state.clientX,
60
- clientY: state => state.clientY,
58
+ clientLeftPaper: state => state.clientLeftPaper,
61
59
  },
62
60
  mutations: {
63
61
  preventSavingElementPosition(state) {
@@ -73,6 +71,9 @@ export default new Vuex.Store({
73
71
  state.rootElements = rootElements;
74
72
  },
75
73
  updateNodeBounds(state, { node, bounds }) {
74
+ if (!bounds) {
75
+ return;
76
+ }
76
77
  Object.entries(bounds).forEach(([key, val]) => {
77
78
  if (key === '$type') {
78
79
  return;
@@ -148,13 +149,8 @@ export default new Vuex.Store({
148
149
  setCopiedElements(state, elements) {
149
150
  state.copiedElements = elements;
150
151
  },
151
- setClientMousePosition(state, position) {
152
- const { clientX, clientY } = position;
153
- state = { clientX, clientY };
154
- },
155
- clientLeftPaper(state) {
156
- state.clientX = null;
157
- state.clientY = null;
152
+ setClientLeftPaper(state, status) {
153
+ state.clientLeftPaper = status;
158
154
  },
159
155
  },
160
156
  actions: {
@@ -8,7 +8,6 @@ export default new Vuex.Store({
8
8
  stack: [],
9
9
  position: null,
10
10
  disabled: false,
11
- saved: false,
12
11
  isVersionsInstalled: false,
13
12
  isDraft: false,
14
13
  isLoading: false,
@@ -23,9 +22,6 @@ export default new Vuex.Store({
23
22
  currentState(state) {
24
23
  return state.stack[state.position];
25
24
  },
26
- saved(state) {
27
- return state.saved;
28
- },
29
25
  isVersionsInstalled(state) {
30
26
  return state.isVersionsInstalled;
31
27
  },
@@ -53,9 +49,6 @@ export default new Vuex.Store({
53
49
  enableSavingState(state) {
54
50
  state.disabled = false;
55
51
  },
56
- savedState(state, payload) {
57
- state.saved = payload;
58
- },
59
52
  isVersionsInstalled(state, payload) {
60
53
  state.isVersionsInstalled = payload;
61
54
  },
@@ -89,22 +82,14 @@ export default new Vuex.Store({
89
82
 
90
83
  commit('setPosition', state.position + 1);
91
84
  },
92
- saved({ commit }) {
93
- commit('savedState', true);
94
-
95
- // Automatically remove the notification after 2 seconds.
96
- setTimeout(() => {
97
- commit('savedState', false);
98
- }, 2000);
99
- },
100
85
  enableVersions({ commit }) {
101
86
  commit('isVersionsInstalled', true);
102
87
  },
103
- setVersionIndicator({ commit }, newState) {
104
- commit('isDraft', newState);
88
+ setVersionIndicator({ commit }, value) {
89
+ commit('isDraft', value);
105
90
  },
106
- setLoadingState({ commit }, newState) {
107
- commit('isLoading', newState);
91
+ setLoadingState({ commit }, value) {
92
+ commit('isLoading', value);
108
93
  },
109
94
  },
110
95
  });