@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.
- package/dist/modeler.common.js +1519 -822
- package/dist/modeler.common.js.map +1 -1
- package/dist/modeler.umd.js +1519 -822
- package/dist/modeler.umd.js.map +1 -1
- package/dist/modeler.umd.min.js +3 -3
- package/dist/modeler.umd.min.js.map +1 -1
- package/package.json +1 -1
- package/src/NodeIdGenerator.js +55 -22
- package/src/NodeInspector.js +2 -2
- package/src/components/crown/crownButtons/{duplicateButton.vue → cloneButton.vue} +10 -9
- package/src/components/crown/crownConfig/crownConfig.vue +3 -4
- package/src/components/crown/crownMultiselect/crownMultiselect.vue +20 -7
- package/src/components/crown/utils.js +12 -1
- package/src/components/hotkeys/copyPaste.js +7 -4
- package/src/components/hotkeys/main.js +6 -1
- package/src/components/inspectors/DocumentationFormTextArea.vue +6 -2
- package/src/components/inspectors/LoopCharacteristics.vue +5 -2
- package/src/components/inspectors/process.js +5 -1
- package/src/components/modeler/Modeler.vue +92 -99
- package/src/components/modeler/Selection.vue +40 -29
- package/src/components/nodes/association/index.js +3 -0
- package/src/components/nodes/dataInputAssociation/dataInputAssociation.vue +36 -26
- package/src/components/nodes/genericFlow/DataOutputAssociation.js +54 -2
- package/src/components/nodes/genericFlow/genericFlow.vue +0 -17
- package/src/components/nodes/node.js +81 -8
- package/src/components/nodes/pool/poolEventHandlers.js +0 -9
- package/src/components/toolbar/ToolBar.vue +21 -9
- package/src/components/toolbar/toolbar.scss +2 -1
- package/src/mixins/cloneSelection.js +153 -0
- package/src/mixins/linkConfig.js +4 -1
- package/src/store.js +7 -11
- 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.
|
|
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
|
|
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.
|
|
126
|
-
clonedFlow.diagram
|
|
189
|
+
clonedFlow.cloneOf = this.id;
|
|
190
|
+
clonedFlow.diagram = moddle.create('bpmndi:BPMNEdge', {
|
|
191
|
+
waypoint: [],
|
|
192
|
+
});
|
|
127
193
|
|
|
128
|
-
this.diagram.waypoint.forEach(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
|
|
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
|
|
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
|
|
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
|
|
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" />
|
|
@@ -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
|
+
};
|
package/src/mixins/linkConfig.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
152
|
-
|
|
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: {
|
package/src/undoRedoStore.js
CHANGED
|
@@ -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 },
|
|
104
|
-
commit('isDraft',
|
|
88
|
+
setVersionIndicator({ commit }, value) {
|
|
89
|
+
commit('isDraft', value);
|
|
105
90
|
},
|
|
106
|
-
setLoadingState({ commit },
|
|
107
|
-
commit('isLoading',
|
|
91
|
+
setLoadingState({ commit }, value) {
|
|
92
|
+
commit('isLoading', value);
|
|
108
93
|
},
|
|
109
94
|
},
|
|
110
95
|
});
|