@processmaker/modeler 1.27.0 → 1.28.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 +1162 -593
- package/dist/modeler.common.js.map +1 -1
- package/dist/modeler.umd.js +1162 -593
- 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/crownConfig/crownConfig.vue +0 -1
- 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/LoopCharacteristics.vue +5 -2
- package/src/components/inspectors/process.js +5 -1
- package/src/components/modeler/Modeler.vue +51 -79
- package/src/components/modeler/Selection.vue +4 -25
- 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 +71 -6
- package/src/mixins/cloneSelection.js +145 -0
- package/src/mixins/linkConfig.js +4 -1
- package/src/store.js +4 -11
package/package.json
CHANGED
package/src/NodeIdGenerator.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
export default class NodeIdGenerator {
|
|
2
2
|
static prefix = 'node_';
|
|
3
3
|
|
|
4
|
-
#counter = 1;
|
|
5
|
-
#diagramCounter = 1;
|
|
4
|
+
static #counter = 1;
|
|
5
|
+
static #diagramCounter = 1;
|
|
6
6
|
|
|
7
7
|
constructor(definitions) {
|
|
8
8
|
this.definitions = definitions;
|
|
9
|
+
this.refreshLastIdCounter();
|
|
10
|
+
this.refreshLastDiagramIdCounter();
|
|
9
11
|
}
|
|
10
12
|
|
|
11
13
|
findById(id, root = this.definitions.rootElements, walked = []) {
|
|
@@ -17,45 +19,76 @@ export default class NodeIdGenerator {
|
|
|
17
19
|
} else if (root instanceof Object && root.$type) {
|
|
18
20
|
walked.push(root);
|
|
19
21
|
if (root.id === id) return root;
|
|
20
|
-
Object.getOwnPropertyNames(root).find(key => found = !(root[key] instanceof Function) && this.findById(id, root[key], walked));
|
|
22
|
+
Object.getOwnPropertyNames(root).find(key => found = !(root[key] instanceof Function) && (key.substring(0, 1) !== '$') && this.findById(id, root[key], walked));
|
|
21
23
|
}
|
|
22
24
|
return found;
|
|
23
25
|
}
|
|
24
26
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
matchIds(idRegex, root, walked = [], lastIdCounter = 0) {
|
|
28
|
+
if (walked.indexOf(root) > -1) return lastIdCounter;
|
|
29
|
+
if (root instanceof Array) {
|
|
30
|
+
walked.push(root);
|
|
31
|
+
root.forEach(item => lastIdCounter = this.matchIds(idRegex, item, walked, lastIdCounter));
|
|
32
|
+
} else if (root instanceof Object) {
|
|
33
|
+
walked.push(root);
|
|
34
|
+
if (root.id) {
|
|
35
|
+
const match = String(root.id).match(idRegex);
|
|
36
|
+
const idCounter = match ? parseInt(match[1]) : 0;
|
|
37
|
+
if (idCounter > lastIdCounter) {
|
|
38
|
+
lastIdCounter = idCounter;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
Object.getOwnPropertyNames(root).forEach(key => {
|
|
42
|
+
if (!(root[key] instanceof Function) && (key.substring(0, 1) !== '$')) {
|
|
43
|
+
lastIdCounter = this.matchIds(idRegex, root[key], walked, lastIdCounter);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
31
46
|
}
|
|
47
|
+
return lastIdCounter;
|
|
48
|
+
}
|
|
32
49
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
50
|
+
refreshLastIdCounter() {
|
|
51
|
+
let lastIdCounter = this.matchIds(new RegExp(`^${NodeIdGenerator.prefix}(\\d+)$`), this.definitions.rootElements);
|
|
52
|
+
NodeIdGenerator.#counter = lastIdCounter + 1;
|
|
53
|
+
}
|
|
36
54
|
|
|
55
|
+
getCounter() {
|
|
56
|
+
this.refreshLastIdCounter();
|
|
57
|
+
return NodeIdGenerator.#counter;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
refreshLastDiagramIdCounter() {
|
|
61
|
+
let lastIdCounter = this.matchIds(new RegExp(`^${NodeIdGenerator.prefix}(\\d+)_di$`), this.definitions.diagrams);
|
|
62
|
+
NodeIdGenerator.#diagramCounter = lastIdCounter + 1;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
generate() {
|
|
66
|
+
let definitionId = this.#generateDefinitionId();
|
|
67
|
+
let diagramId = this.#generateDiagramId();
|
|
37
68
|
return [definitionId, diagramId];
|
|
38
69
|
}
|
|
39
70
|
|
|
40
71
|
#generateDefinitionId = () => {
|
|
41
|
-
const id = NodeIdGenerator.prefix +
|
|
42
|
-
|
|
72
|
+
const id = NodeIdGenerator.prefix + NodeIdGenerator.#counter;
|
|
73
|
+
NodeIdGenerator.#counter++;
|
|
43
74
|
|
|
44
75
|
return id;
|
|
45
76
|
};
|
|
46
77
|
|
|
47
78
|
#generateDiagramId = () => {
|
|
48
|
-
const id = NodeIdGenerator.prefix +
|
|
49
|
-
|
|
79
|
+
const id = NodeIdGenerator.prefix + NodeIdGenerator.#diagramCounter + '_di';
|
|
80
|
+
NodeIdGenerator.#diagramCounter++;
|
|
50
81
|
|
|
51
82
|
return id;
|
|
52
83
|
};
|
|
84
|
+
}
|
|
53
85
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
};
|
|
86
|
+
// Singleton instance
|
|
87
|
+
let singleton = null;
|
|
57
88
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
89
|
+
export function getNodeIdGenerator(definitions) {
|
|
90
|
+
if (!singleton) {
|
|
91
|
+
singleton = new NodeIdGenerator(definitions);
|
|
92
|
+
}
|
|
93
|
+
return singleton;
|
|
61
94
|
}
|
package/src/NodeInspector.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { getNodeIdGenerator } from './NodeIdGenerator';
|
|
2
2
|
import omit from 'lodash/omit';
|
|
3
3
|
|
|
4
4
|
export default class NodeInspector {
|
|
@@ -6,7 +6,7 @@ export default class NodeInspector {
|
|
|
6
6
|
constructor(definitions, options = {}) {
|
|
7
7
|
this.index = window.NODE_INSPECTOR_FIRST_INDEX || new Date().getTime();
|
|
8
8
|
this.definitions = definitions;
|
|
9
|
-
this.nodeIdGenerator =
|
|
9
|
+
this.nodeIdGenerator = getNodeIdGenerator(this.definitions);
|
|
10
10
|
this.options = Object.assign({
|
|
11
11
|
prefix: this.nodeIdGenerator.generate()[0],
|
|
12
12
|
}, options);
|
|
@@ -114,6 +114,7 @@ export function getOrFindDataInput(moddle, task, sourceNode) {
|
|
|
114
114
|
inputSets: [],
|
|
115
115
|
outputSets: [],
|
|
116
116
|
});
|
|
117
|
+
task.definition.ioSpecification.$parent = task.definition;
|
|
117
118
|
}
|
|
118
119
|
// Check if dataInput exists
|
|
119
120
|
if (!task.definition.ioSpecification.dataInputs) {
|
|
@@ -126,6 +127,7 @@ export function getOrFindDataInput(moddle, task, sourceNode) {
|
|
|
126
127
|
isCollection: 'false',
|
|
127
128
|
name: sourceNode.name,
|
|
128
129
|
}));
|
|
130
|
+
task.definition.ioSpecification.dataInputs[task.definition.ioSpecification.dataInputs.length - 1].$parent = task.definition.ioSpecification;
|
|
129
131
|
task.definition.ioSpecification.set('dataInputs', task.definition.ioSpecification.dataInputs);
|
|
130
132
|
}
|
|
131
133
|
dataInput = task.definition.ioSpecification.dataInputs.find(input => input.id === dataInputId);
|
|
@@ -164,13 +166,22 @@ export function getOrFindDataInput(moddle, task, sourceNode) {
|
|
|
164
166
|
}
|
|
165
167
|
inputSet = task.definition.ioSpecification.inputSets[0];
|
|
166
168
|
// Check if dataInputRef exists
|
|
167
|
-
const dataInputRef = inputSet.dataInputRefs.find(ref => ref.id === dataInputId);
|
|
169
|
+
const dataInputRef = inputSet.get('dataInputRefs').find(ref => ref.id === dataInputId);
|
|
168
170
|
if (!dataInputRef) {
|
|
169
171
|
inputSet.dataInputRefs.push(dataInput);
|
|
170
172
|
}
|
|
171
173
|
return dataInput;
|
|
172
174
|
}
|
|
173
175
|
|
|
176
|
+
export function findIOSpecificationOwner(ioSpec, modeler) {
|
|
177
|
+
const owner = ioSpec.$parent;
|
|
178
|
+
if (!owner) {
|
|
179
|
+
return modeler.nodes.find(node => node.definition.ioSpecification === ioSpec ||
|
|
180
|
+
node.definition.ioSpecification?.id === ioSpec.id
|
|
181
|
+
)?.definition;
|
|
182
|
+
}
|
|
183
|
+
return owner;
|
|
184
|
+
}
|
|
174
185
|
|
|
175
186
|
export function removeDataInput(task, sourceNode) {
|
|
176
187
|
if (sourceNode.$type !== 'bpmn:DataObjectReference' && sourceNode.$type !== 'bpmn:DataStoreReference') {
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
export default {
|
|
2
2
|
methods: {
|
|
3
3
|
copyPasteHandler(event, options) {
|
|
4
|
-
const
|
|
5
|
-
const
|
|
4
|
+
const node = event.target.nodeName.toLowerCase();
|
|
5
|
+
const isBody = node === 'body';
|
|
6
|
+
const key = event.key.toLowerCase();
|
|
7
|
+
const isCopy = key === 'c';
|
|
8
|
+
const isPaste = key === 'v';
|
|
6
9
|
|
|
7
|
-
if (isCopy && options.mod) {
|
|
10
|
+
if (isBody && isCopy && options.mod) {
|
|
8
11
|
this.copy(event);
|
|
9
12
|
}
|
|
10
|
-
if (isPaste && options.mod) {
|
|
13
|
+
if (isBody && isPaste && options.mod) {
|
|
11
14
|
this.paste(event);
|
|
12
15
|
}
|
|
13
16
|
},
|
|
@@ -5,6 +5,11 @@ import moveShapeByKeypress from './moveWithArrowKeys';
|
|
|
5
5
|
|
|
6
6
|
export default {
|
|
7
7
|
mixins: [ZoomInOut, CopyPaste],
|
|
8
|
+
computed: {
|
|
9
|
+
clientLeftPaper() {
|
|
10
|
+
return store.getters.clientLeftPaper;
|
|
11
|
+
},
|
|
12
|
+
},
|
|
8
13
|
mounted() {
|
|
9
14
|
document.addEventListener('keydown', this.keydownListener);
|
|
10
15
|
document.addEventListener('keyup', this.keyupListener);
|
|
@@ -45,7 +50,7 @@ export default {
|
|
|
45
50
|
const scale = this.paperManager.scale;
|
|
46
51
|
this.canvasDragPosition = { x: x * scale.sx, y: y * scale.sy };
|
|
47
52
|
}
|
|
48
|
-
if (this.canvasDragPosition) {
|
|
53
|
+
if (this.canvasDragPosition && !this.clientLeftPaper) {
|
|
49
54
|
this.paperManager.translate(
|
|
50
55
|
event.offsetX - this.canvasDragPosition.x,
|
|
51
56
|
event.offsetY - this.canvasDragPosition.y
|
|
@@ -115,6 +115,9 @@ export default {
|
|
|
115
115
|
},
|
|
116
116
|
loopMaximum: 0,
|
|
117
117
|
loopCondition: null,
|
|
118
|
+
ioSpecification: {
|
|
119
|
+
dataInputs: [],
|
|
120
|
+
},
|
|
118
121
|
},
|
|
119
122
|
loopType: null,
|
|
120
123
|
multiType: null,
|
|
@@ -218,7 +221,7 @@ export default {
|
|
|
218
221
|
},
|
|
219
222
|
getLoopDataOutputRef() {
|
|
220
223
|
if (!this.local.loopCharacteristics || !this.local.loopCharacteristics.loopDataOutputRef) return null;
|
|
221
|
-
return this.local.ioSpecification
|
|
224
|
+
return this.local.ioSpecification?.dataOutputs[0].name;
|
|
222
225
|
},
|
|
223
226
|
setLoopDataOutputRef(value) {
|
|
224
227
|
if (!this.local.ioSpecification) {
|
|
@@ -252,7 +255,7 @@ export default {
|
|
|
252
255
|
},
|
|
253
256
|
getLoopDataInputRef() {
|
|
254
257
|
if (!this.local.loopCharacteristics || !this.local.loopCharacteristics.loopDataInputRef) return null;
|
|
255
|
-
return this.local.ioSpecification
|
|
258
|
+
return this.local.ioSpecification?.dataInputs[0].name;
|
|
256
259
|
},
|
|
257
260
|
setLoopDataInputRef(value) {
|
|
258
261
|
const dataDef = {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import idConfigSettings from './idConfigSettings';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
const process = {
|
|
4
4
|
id: 'processmaker-modeler-process',
|
|
5
5
|
bpmnType: 'bpmn:Process',
|
|
6
6
|
control: false,
|
|
@@ -38,3 +38,7 @@ export default {
|
|
|
38
38
|
},
|
|
39
39
|
],
|
|
40
40
|
};
|
|
41
|
+
|
|
42
|
+
export const id = process.id;
|
|
43
|
+
|
|
44
|
+
export default process;
|
|
@@ -139,12 +139,13 @@ import InspectorPanel from '@/components/inspectors/InspectorPanel';
|
|
|
139
139
|
import undoRedoStore from '@/undoRedoStore';
|
|
140
140
|
import { Linter } from 'bpmnlint';
|
|
141
141
|
import linterConfig from '../../../.bpmnlintrc';
|
|
142
|
-
import
|
|
142
|
+
import { getNodeIdGenerator } from '../../NodeIdGenerator';
|
|
143
143
|
import Process from '../inspectors/process';
|
|
144
144
|
import runningInCypressTest from '@/runningInCypressTest';
|
|
145
145
|
import getValidationProperties from '@/targetValidationUtils';
|
|
146
146
|
import MiniPaper from '@/components/miniPaper/MiniPaper';
|
|
147
147
|
import { id as laneId } from '@/components/nodes/poolLane/config';
|
|
148
|
+
import { id as processId } from '@/components/inspectors/process';
|
|
148
149
|
import { id as sequenceFlowId } from '../nodes/sequenceFlow';
|
|
149
150
|
import { id as associationId } from '../nodes/association';
|
|
150
151
|
import { id as messageFlowId } from '../nodes/messageFlow/config';
|
|
@@ -167,6 +168,7 @@ import { removeNodeFlows, removeNodeMessageFlows, removeNodeAssociations, remove
|
|
|
167
168
|
import { getInvalidNodes } from '@/components/modeler/modelerUtils';
|
|
168
169
|
import { NodeMigrator } from '@/components/modeler/NodeMigrator';
|
|
169
170
|
import addLoopCharacteristics from '@/setup/addLoopCharacteristics';
|
|
171
|
+
import cloneSelection from '../../mixins/cloneSelection';
|
|
170
172
|
|
|
171
173
|
import ProcessmakerModelerGenericFlow from '@/components/nodes/genericFlow/genericFlow';
|
|
172
174
|
|
|
@@ -190,9 +192,10 @@ export default {
|
|
|
190
192
|
},
|
|
191
193
|
},
|
|
192
194
|
},
|
|
193
|
-
mixins: [hotkeys],
|
|
195
|
+
mixins: [hotkeys, cloneSelection],
|
|
194
196
|
data() {
|
|
195
197
|
return {
|
|
198
|
+
pasteInProgress: false,
|
|
196
199
|
internalClipboard: [],
|
|
197
200
|
tooltipTarget: null,
|
|
198
201
|
|
|
@@ -329,90 +332,51 @@ export default {
|
|
|
329
332
|
dataOutputAssociationFlowId,
|
|
330
333
|
dataInputAssociationFlowId,
|
|
331
334
|
genericFlowId,
|
|
335
|
+
processId,
|
|
332
336
|
];
|
|
333
337
|
if (this.highlightedNodes.length === 1 && flows.includes(this.highlightedNodes[0].type)) return;
|
|
334
338
|
store.commit('setCopiedElements', this.cloneSelection());
|
|
335
339
|
this.$bvToast.toast(this.$t('Object(s) have been copied'), { noCloseButton:true, variant: 'success', solid: true, toaster: 'b-toaster-top-center' });
|
|
336
340
|
},
|
|
337
341
|
async pasteElements() {
|
|
338
|
-
if (this.copiedElements) {
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
+
if (this.copiedElements && !this.pasteInProgress) {
|
|
343
|
+
this.pasteInProgress = true;
|
|
344
|
+
try {
|
|
345
|
+
await this.addClonedNodes(this.copiedElements);
|
|
346
|
+
await this.$nextTick();
|
|
347
|
+
await this.paperManager.awaitScheduledUpdates();
|
|
348
|
+
await this.$refs.selector.selectElements(this.findViewElementsFromNodes(this.copiedElements), true);
|
|
349
|
+
await this.$nextTick();
|
|
350
|
+
await store.commit('setCopiedElements', this.cloneSelection());
|
|
351
|
+
this.scrollToSelection();
|
|
352
|
+
} finally {
|
|
353
|
+
this.pasteInProgress = false;
|
|
354
|
+
}
|
|
342
355
|
}
|
|
343
356
|
},
|
|
344
|
-
cloneSelection() {
|
|
345
|
-
let clonedNodes = [], clonedFlows = [], originalFlows = [];
|
|
346
|
-
const nodes = this.highlightedNodes;
|
|
347
|
-
const selector = this.$refs.selector.$el;
|
|
348
|
-
const { height: sheight } = selector.getBoundingClientRect();
|
|
349
|
-
if (typeof selector.getBoundingClientRect === 'function') {
|
|
350
|
-
// get selector height
|
|
351
|
-
nodes.forEach(node => {
|
|
352
|
-
// Add flows described in the definitions property
|
|
353
|
-
if (node.definition.incoming || node.definition.outgoing) {
|
|
354
|
-
// Since both incoming and outgoing reference the same flow, any of them is copied
|
|
355
|
-
let flowsToCopy = [...(node.definition.incoming || node.definition.outgoing)];
|
|
356
|
-
// Check if flow is already in array before pushing
|
|
357
|
-
flowsToCopy.forEach(flow => {
|
|
358
|
-
if (!originalFlows.some(el => el.id === flow.id)) {
|
|
359
|
-
originalFlows.push(flow);
|
|
360
|
-
}
|
|
361
|
-
});
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
// Check node type to clone
|
|
365
|
-
if ([
|
|
366
|
-
sequenceFlowId,
|
|
367
|
-
laneId,
|
|
368
|
-
associationId,
|
|
369
|
-
messageFlowId,
|
|
370
|
-
dataOutputAssociationFlowId,
|
|
371
|
-
dataInputAssociationFlowId,
|
|
372
|
-
genericFlowId,
|
|
373
|
-
].includes(node.type)) {
|
|
374
|
-
// Add offset for all waypoints on cloned flow
|
|
375
|
-
const clonedFlow = node.cloneFlow(this.nodeRegistry, this.moddle, this.$t);
|
|
376
|
-
clonedFlow.setIds(this.nodeIdGenerator);
|
|
377
|
-
clonedFlows.push(clonedFlow);
|
|
378
|
-
clonedNodes.push(clonedFlow);
|
|
379
|
-
} else {
|
|
380
|
-
// Clone node and calculate offset
|
|
381
|
-
const clonedNode = node.clone(this.nodeRegistry, this.moddle, this.$t);
|
|
382
|
-
const yOffset = sheight;
|
|
383
|
-
clonedNode.diagram.bounds.y += yOffset;
|
|
384
|
-
// Set cloned node id
|
|
385
|
-
clonedNode.setIds(this.nodeIdGenerator);
|
|
386
|
-
clonedNodes.push(clonedNode);
|
|
387
|
-
}
|
|
388
|
-
});
|
|
389
|
-
}
|
|
390
|
-
// Connect flows
|
|
391
|
-
clonedFlows.forEach(flow => {
|
|
392
|
-
// Look up the original flow
|
|
393
|
-
const flowClonedFrom = { definition: originalFlows.find(el => el.id === flow.definition.cloneOf) };
|
|
394
|
-
// Get the id's of the sourceRef and targetRef of original flow
|
|
395
|
-
const src = flowClonedFrom.definition.sourceRef;
|
|
396
|
-
const target = flowClonedFrom.definition.targetRef;
|
|
397
|
-
const srcClone = clonedNodes.find(node => node.definition.cloneOf === src.id);
|
|
398
|
-
const targetClone = clonedNodes.find(node => node.definition.cloneOf === target.id);
|
|
399
|
-
// Reference the elements to the flow that connects them
|
|
400
|
-
flow.definition.sourceRef = srcClone.definition;
|
|
401
|
-
flow.definition.targetRef = targetClone.definition;
|
|
402
|
-
// Reference the flow to the elements that are connected by it
|
|
403
|
-
srcClone.definition.outgoing ? srcClone.definition.outgoing.push(flow.definition) : srcClone.definition.outgoing = [flow.definition];
|
|
404
|
-
targetClone.definition.incoming ? targetClone.definition.incoming.push(flow.definition) : targetClone.definition.incoming = [flow.definition];
|
|
405
|
-
// Translate flow waypoints to where they should be
|
|
406
|
-
flow.diagram.waypoint.forEach(point => {
|
|
407
|
-
point.y += sheight;
|
|
408
|
-
});
|
|
409
|
-
});
|
|
410
|
-
return clonedNodes;
|
|
411
|
-
},
|
|
412
357
|
async duplicateSelection() {
|
|
413
358
|
const clonedNodes = this.cloneSelection();
|
|
359
|
+
if (clonedNodes && clonedNodes.length === 0) {
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
this.$refs.selector.clearSelection();
|
|
414
363
|
await this.addClonedNodes(clonedNodes);
|
|
415
|
-
this.$
|
|
364
|
+
await this.$nextTick();
|
|
365
|
+
await this.paperManager.awaitScheduledUpdates();
|
|
366
|
+
await this.$refs.selector.selectElements(this.findViewElementsFromNodes(clonedNodes));
|
|
367
|
+
this.scrollToSelection();
|
|
368
|
+
},
|
|
369
|
+
scrollToSelection() {
|
|
370
|
+
const containerRect = this.$refs['paper-container'].getBoundingClientRect();
|
|
371
|
+
const selector = this.$refs.selector;
|
|
372
|
+
const selectorRect = selector.$el.getBoundingClientRect();
|
|
373
|
+
// Scroll to the cloned elements only when they are not visible on the screen.
|
|
374
|
+
if (selectorRect.right > containerRect.right || selectorRect.bottom > containerRect.bottom || selectorRect.left < containerRect.left || selectorRect.top < containerRect.top) {
|
|
375
|
+
const currentPosition = this.paper.translate();
|
|
376
|
+
const newTy = currentPosition.ty - (selectorRect.top - containerRect.top - selectorRect.height);
|
|
377
|
+
this.paper.translate(currentPosition.tx, newTy);
|
|
378
|
+
selector.updateSelectionBox(true);
|
|
379
|
+
}
|
|
416
380
|
},
|
|
417
381
|
findViewElementsFromNodes(nodes) {
|
|
418
382
|
return nodes.map(node => {
|
|
@@ -832,7 +796,7 @@ export default {
|
|
|
832
796
|
async loadXML(xml = this.currentXML) {
|
|
833
797
|
this.definitions = await this.xmlManager.getDefinitionsFromXml(xml);
|
|
834
798
|
this.xmlManager.definitions = this.definitions;
|
|
835
|
-
this.nodeIdGenerator =
|
|
799
|
+
this.nodeIdGenerator = getNodeIdGenerator(this.definitions);
|
|
836
800
|
store.commit('clearNodes');
|
|
837
801
|
this.renderPaper();
|
|
838
802
|
},
|
|
@@ -974,7 +938,12 @@ export default {
|
|
|
974
938
|
await this.pushToUndoStack();
|
|
975
939
|
},
|
|
976
940
|
async removeNode(node, { removeRelationships = true } = {}) {
|
|
941
|
+
if (!node) {
|
|
942
|
+
// already removed
|
|
943
|
+
return;
|
|
944
|
+
}
|
|
977
945
|
if (removeRelationships) {
|
|
946
|
+
|
|
978
947
|
removeNodeFlows(node, this);
|
|
979
948
|
removeNodeMessageFlows(node, this);
|
|
980
949
|
removeNodeAssociations(node, this);
|
|
@@ -1274,14 +1243,17 @@ export default {
|
|
|
1274
1243
|
this.pointerUpHandler(event, cellView);
|
|
1275
1244
|
}, this);
|
|
1276
1245
|
|
|
1246
|
+
this.$el.addEventListener('mouseenter', () => {
|
|
1247
|
+
store.commit('setClientLeftPaper', false);
|
|
1248
|
+
});
|
|
1249
|
+
|
|
1277
1250
|
this.$el.addEventListener('mousemove', event => {
|
|
1278
|
-
const { clientX, clientY } = event;
|
|
1279
1251
|
this.pointerMoveHandler(event);
|
|
1280
|
-
store.commit('setClientMousePosition', { clientX, clientY });
|
|
1281
1252
|
});
|
|
1282
1253
|
|
|
1283
1254
|
this.$el.addEventListener('mouseleave', () => {
|
|
1284
|
-
|
|
1255
|
+
this.paperManager.removeEventHandler('blank:pointermove');
|
|
1256
|
+
store.commit('setClientLeftPaper', true);
|
|
1285
1257
|
});
|
|
1286
1258
|
|
|
1287
1259
|
this.paperManager.addEventHandler('cell:pointerclick', (cellView, evt, x, y) => {
|
|
@@ -29,13 +29,7 @@ import { id as poolId } from '@/components/nodes/pool/config';
|
|
|
29
29
|
import { id as laneId } from '@/components/nodes/poolLane/config';
|
|
30
30
|
import { id as genericFlowId } from '@/components/nodes/genericFlow/config';
|
|
31
31
|
import { labelWidth, poolPadding } from '../nodes/pool/poolSizes';
|
|
32
|
-
|
|
33
|
-
'processmaker-modeler-boundary-timer-event',
|
|
34
|
-
'processmaker-modeler-boundary-error-event',
|
|
35
|
-
'processmaker-modeler-boundary-signal-event',
|
|
36
|
-
'processmaker-modeler-boundary-conditional-event',
|
|
37
|
-
'processmaker-modeler-boundary-message-event',
|
|
38
|
-
];
|
|
32
|
+
|
|
39
33
|
export default {
|
|
40
34
|
name: 'Selection',
|
|
41
35
|
components: {
|
|
@@ -351,24 +345,6 @@ export default {
|
|
|
351
345
|
}
|
|
352
346
|
return true;
|
|
353
347
|
});
|
|
354
|
-
// A boundary event could only be selected alone
|
|
355
|
-
const firstSelectedBoundary = this.selected.find(shape => {
|
|
356
|
-
return shape.model.component &&
|
|
357
|
-
boundaryElements.includes(shape.model.component.node.type);
|
|
358
|
-
});
|
|
359
|
-
const firstSelectedElement = this.selected[0];
|
|
360
|
-
if (firstSelectedBoundary) {
|
|
361
|
-
this.selected = this.selected.filter(shape => {
|
|
362
|
-
if (firstSelectedElement === firstSelectedBoundary) {
|
|
363
|
-
// boundary event selected alone
|
|
364
|
-
return shape.model.component &&
|
|
365
|
-
shape === firstSelectedBoundary;
|
|
366
|
-
}
|
|
367
|
-
// do not allow to select a boundary event with another element
|
|
368
|
-
return shape.model.component &&
|
|
369
|
-
!boundaryElements.includes(shape.model.component.node.type);
|
|
370
|
-
});
|
|
371
|
-
}
|
|
372
348
|
},
|
|
373
349
|
/**
|
|
374
350
|
* Pan paper handler
|
|
@@ -475,6 +451,9 @@ export default {
|
|
|
475
451
|
this.$emit('save-state');
|
|
476
452
|
this.dragging = false;
|
|
477
453
|
this.stopForceMove = false;
|
|
454
|
+
// Readjusts the selection box, taking into consideration elements
|
|
455
|
+
// that are anchored and did not move, such as boundary events.
|
|
456
|
+
this.updateSelectionBox();
|
|
478
457
|
},
|
|
479
458
|
/**
|
|
480
459
|
* Translate the Selected shapes adding some custom validations
|
|
@@ -21,7 +21,7 @@ import linkConfig from '@/mixins/linkConfig';
|
|
|
21
21
|
import get from 'lodash/get';
|
|
22
22
|
import associationHead from '!!url-loader!@/assets/association-head.svg';
|
|
23
23
|
import CrownConfig from '@/components/crown/crownConfig/crownConfig';
|
|
24
|
-
import { getOrFindDataInput, removeDataInput } from '@/components/crown/utils';
|
|
24
|
+
import { getOrFindDataInput, removeDataInput, findIOSpecificationOwner } from '@/components/crown/utils';
|
|
25
25
|
import { pull } from 'lodash';
|
|
26
26
|
|
|
27
27
|
export default {
|
|
@@ -50,20 +50,38 @@ export default {
|
|
|
50
50
|
},
|
|
51
51
|
computed: {
|
|
52
52
|
isValidConnection() {
|
|
53
|
-
const targetType = get(this.target, 'component.node.type');
|
|
53
|
+
const targetType = get(this.target, 'component.node.definition.$type');
|
|
54
54
|
|
|
55
55
|
if (!targetType) {
|
|
56
56
|
return false;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
const dataStoreValidTargets = [
|
|
60
|
+
'bpmn:Task',
|
|
61
|
+
'bpmn:SubProcess',
|
|
62
|
+
'bpmn:CallActivity',
|
|
63
|
+
'bpmn:ManualTask',
|
|
64
|
+
'bpmn:ScriptTask',
|
|
65
|
+
'bpmn:ServiceTask',
|
|
66
|
+
];
|
|
67
|
+
const dataObjectValidTargets = [
|
|
68
|
+
'bpmn:Task',
|
|
69
|
+
'bpmn:SubProcess',
|
|
70
|
+
'bpmn:CallActivity',
|
|
71
|
+
'bpmn:ManualTask',
|
|
72
|
+
'bpmn:ScriptTask',
|
|
73
|
+
'bpmn:ServiceTask',
|
|
74
|
+
'bpmn:IntermediateThrowEvent',
|
|
75
|
+
'bpmn:EndEvent',
|
|
76
|
+
];
|
|
61
77
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
78
|
+
const sourceIsDataStore = this.sourceNode.definition.$type === 'bpmn:DataStoreReference';
|
|
79
|
+
const sourceIsDataObject = this.sourceNode.definition.$type === 'bpmn:DataObjectReference';
|
|
65
80
|
|
|
66
|
-
|
|
81
|
+
if (sourceIsDataStore && dataStoreValidTargets.includes(targetType)) {
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
return (sourceIsDataObject && dataObjectValidTargets.includes(targetType));
|
|
67
85
|
},
|
|
68
86
|
},
|
|
69
87
|
methods: {
|
|
@@ -71,29 +89,16 @@ export default {
|
|
|
71
89
|
if (this.node.dataAssociationProps) {
|
|
72
90
|
return this.node.dataAssociationProps.sourceShape;
|
|
73
91
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
const dataObjectDefinition = taskWithInputAssociation.component.node.definition.get('dataInputAssociations')[0].sourceRef[0];
|
|
81
|
-
|
|
82
|
-
return this.graph.getElements().find(element => {
|
|
83
|
-
return element.component && element.component.node.definition === dataObjectDefinition;
|
|
84
|
-
});
|
|
92
|
+
const source = this.node.definition.sourceRef[0];
|
|
93
|
+
// find shape
|
|
94
|
+
const shape = this.graph.getElements().find(e=>e.component.node.definition === source);
|
|
95
|
+
return shape;
|
|
85
96
|
},
|
|
86
97
|
getTargetRef() {
|
|
87
98
|
if (this.node.dataAssociationProps) {
|
|
88
99
|
return this.node.dataAssociationProps.targetCoords;
|
|
89
100
|
}
|
|
90
|
-
|
|
91
|
-
const taskWithInputAssociation = this.graph.getElements().find(element => {
|
|
92
|
-
return element.component && element.component.node.definition.get('dataInputAssociations') &&
|
|
93
|
-
element.component.node.definition.get('dataInputAssociations')[0] === this.node.definition;
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
return taskWithInputAssociation.component.node.definition;
|
|
101
|
+
return findIOSpecificationOwner(this.node.definition.targetRef.$parent, this.$parent);
|
|
97
102
|
},
|
|
98
103
|
updateRouter() {
|
|
99
104
|
this.shape.router('normal', { elementPadding: this.elementPadding });
|
|
@@ -102,6 +107,7 @@ export default {
|
|
|
102
107
|
const targetShape = this.shape.getTargetElement();
|
|
103
108
|
const dataInput = getOrFindDataInput(this.moddle, targetShape.component.node, this.sourceNode.definition);
|
|
104
109
|
this.node.definition.set('targetRef', dataInput);
|
|
110
|
+
// @todo Review why this needs to be and array. When saving the BPMN, if this is not an array the sourceRef is not stored
|
|
105
111
|
this.node.definition.set('sourceRef', [this.sourceNode.definition]);
|
|
106
112
|
targetShape.component.node.definition.set('dataInputAssociations', [this.node.definition]);
|
|
107
113
|
},
|
|
@@ -129,6 +135,10 @@ export default {
|
|
|
129
135
|
this.shape.component = this;
|
|
130
136
|
},
|
|
131
137
|
destroyed() {
|
|
138
|
+
// when a association was not completed this.targetNode will be undefined
|
|
139
|
+
if (!this.targetNode) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
132
142
|
removeDataInput(this.targetNode, this.sourceNode.definition);
|
|
133
143
|
pull(this.targetNode.definition.get('dataInputAssociations'), this.node.definition);
|
|
134
144
|
},
|