@processmaker/modeler 1.28.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 +502 -374
- package/dist/modeler.common.js.map +1 -1
- package/dist/modeler.umd.js +502 -374
- 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/components/crown/crownButtons/{duplicateButton.vue → cloneButton.vue} +10 -9
- package/src/components/crown/crownConfig/crownConfig.vue +3 -3
- package/src/components/crown/crownMultiselect/crownMultiselect.vue +20 -7
- package/src/components/inspectors/DocumentationFormTextArea.vue +6 -2
- package/src/components/modeler/Modeler.vue +50 -29
- package/src/components/modeler/Selection.vue +36 -4
- package/src/components/nodes/node.js +10 -2
- 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 +14 -6
- package/src/store.js +3 -0
- package/src/undoRedoStore.js +4 -19
package/package.json
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<crown-button
|
|
3
3
|
v-if="node.isBpmnType(...validCopyElements)"
|
|
4
|
-
:title="$t('
|
|
4
|
+
:title="$t('Clone Element')"
|
|
5
5
|
v-b-tooltip.hover.viewport.d50="{ customClass: 'no-pointer-events' }"
|
|
6
|
-
aria-label="
|
|
7
|
-
data-test="
|
|
6
|
+
aria-label="Clone Element"
|
|
7
|
+
data-test="clone-button"
|
|
8
8
|
role="menuitem"
|
|
9
|
-
@click="
|
|
9
|
+
@click="cloneElement"
|
|
10
10
|
>
|
|
11
11
|
<img
|
|
12
|
-
:src="
|
|
12
|
+
:src="cloneIcon"
|
|
13
13
|
aria-hidden="true"
|
|
14
|
+
alt="Clone element icon"
|
|
14
15
|
>
|
|
15
16
|
</crown-button>
|
|
16
17
|
|
|
@@ -18,7 +19,7 @@
|
|
|
18
19
|
|
|
19
20
|
<script>
|
|
20
21
|
import CrownButton from '@/components/crown/crownButtons/crownButton';
|
|
21
|
-
import
|
|
22
|
+
import cloneIcon from '@/assets/copy-regular.svg';
|
|
22
23
|
import validCopyElements from '@/components/crown/crownButtons/validCopyElements';
|
|
23
24
|
|
|
24
25
|
export default {
|
|
@@ -27,13 +28,13 @@ export default {
|
|
|
27
28
|
data() {
|
|
28
29
|
return {
|
|
29
30
|
copyCount: 0,
|
|
30
|
-
|
|
31
|
+
cloneIcon,
|
|
31
32
|
validCopyElements,
|
|
32
33
|
};
|
|
33
34
|
},
|
|
34
35
|
methods: {
|
|
35
|
-
|
|
36
|
-
this.$emit('
|
|
36
|
+
cloneElement() {
|
|
37
|
+
this.$emit('clone-element', this.node, ++this.copyCount);
|
|
37
38
|
},
|
|
38
39
|
},
|
|
39
40
|
};
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
v-on="$listeners"
|
|
51
51
|
/>
|
|
52
52
|
|
|
53
|
-
<
|
|
53
|
+
<clone-button
|
|
54
54
|
:node="node"
|
|
55
55
|
v-on="$listeners"
|
|
56
56
|
/>
|
|
@@ -84,7 +84,7 @@ import GenericFlowButton from '@/components/crown/crownButtons/genericFlowButton
|
|
|
84
84
|
import AssociationFlowButton from '@/components/crown/crownButtons/associationFlowButton';
|
|
85
85
|
import DataAssociationFlowButton from '@/components/crown/crownButtons/dataAssociationFlowButton';
|
|
86
86
|
import CopyButton from '@/components/crown/crownButtons/copyButton.vue';
|
|
87
|
-
import
|
|
87
|
+
import CloneButton from '@/components/crown/crownButtons/cloneButton.vue';
|
|
88
88
|
import CrownDropdowns from '@/components/crown/crownButtons/crownDropdowns';
|
|
89
89
|
import DefaultFlow from '@/components/crown/crownButtons/defaultFlowButton.vue';
|
|
90
90
|
import poolLaneCrownConfig from '@/mixins/poolLaneCrownConfig';
|
|
@@ -101,7 +101,7 @@ export default {
|
|
|
101
101
|
GenericFlowButton,
|
|
102
102
|
AssociationFlowButton,
|
|
103
103
|
CopyButton,
|
|
104
|
-
|
|
104
|
+
CloneButton,
|
|
105
105
|
DefaultFlow,
|
|
106
106
|
DataAssociationFlowButton,
|
|
107
107
|
},
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
<slot />
|
|
9
9
|
|
|
10
10
|
<button
|
|
11
|
-
v-for="button in
|
|
11
|
+
v-for="button in availableButtons"
|
|
12
12
|
:key="button.label"
|
|
13
13
|
:aria-label="button.label"
|
|
14
14
|
class="btn"
|
|
@@ -30,6 +30,7 @@ import runningInCypressTest from '@/runningInCypressTest';
|
|
|
30
30
|
export default {
|
|
31
31
|
props: {
|
|
32
32
|
paper: Object,
|
|
33
|
+
hasPools: Boolean,
|
|
33
34
|
},
|
|
34
35
|
data() {
|
|
35
36
|
return {
|
|
@@ -42,18 +43,18 @@ export default {
|
|
|
42
43
|
nodeToReplace: null,
|
|
43
44
|
buttons: [
|
|
44
45
|
{
|
|
45
|
-
label: 'Copy
|
|
46
|
+
label: 'Copy Selection',
|
|
46
47
|
icon: 'clipboard',
|
|
47
48
|
testId: 'copy-button',
|
|
48
49
|
role: 'menuitem',
|
|
49
50
|
action: this.copySelection,
|
|
50
51
|
},
|
|
51
52
|
{
|
|
52
|
-
label: '
|
|
53
|
+
label: 'Clone Selection',
|
|
53
54
|
icon: 'copy',
|
|
54
|
-
testId: '
|
|
55
|
+
testId: 'clone-button',
|
|
55
56
|
role: 'menuitem',
|
|
56
|
-
action: this.
|
|
57
|
+
action: this.cloneSelection,
|
|
57
58
|
},
|
|
58
59
|
{
|
|
59
60
|
label: 'Delete Element',
|
|
@@ -75,13 +76,25 @@ export default {
|
|
|
75
76
|
return countSelected > 1;
|
|
76
77
|
},
|
|
77
78
|
highlightedShapes: () => store.getters.highlightedShapes,
|
|
79
|
+
availableButtons() {
|
|
80
|
+
const hasPoolsSelected = this.hasPools;
|
|
81
|
+
return this.buttons.filter(button => {
|
|
82
|
+
if (button.testId === 'copy-button') {
|
|
83
|
+
return !hasPoolsSelected;
|
|
84
|
+
}
|
|
85
|
+
if (button.testId === 'clone-button') {
|
|
86
|
+
return !hasPoolsSelected;
|
|
87
|
+
}
|
|
88
|
+
return true;
|
|
89
|
+
});
|
|
90
|
+
},
|
|
78
91
|
},
|
|
79
92
|
methods: {
|
|
80
93
|
copySelection() {
|
|
81
94
|
this.$emit('copy-selection');
|
|
82
95
|
},
|
|
83
|
-
|
|
84
|
-
this.$emit('
|
|
96
|
+
cloneSelection() {
|
|
97
|
+
this.$emit('clone-selection');
|
|
85
98
|
},
|
|
86
99
|
deleteElement() {
|
|
87
100
|
this.$emit('remove-nodes');
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
data-test="documentation-text-area"
|
|
13
13
|
id="documentation-editor"
|
|
14
14
|
@input="$emit('input', $event)"
|
|
15
|
+
@blur="onBlur"
|
|
15
16
|
/>
|
|
16
17
|
|
|
17
18
|
<b-modal
|
|
@@ -34,6 +35,7 @@
|
|
|
34
35
|
data-test="documentation-modal-text-area"
|
|
35
36
|
id="documentation-editor-modal"
|
|
36
37
|
@input="$emit('input', $event)"
|
|
38
|
+
@blur="onBlur"
|
|
37
39
|
/>
|
|
38
40
|
</b-modal>
|
|
39
41
|
</div>
|
|
@@ -63,8 +65,10 @@ export default {
|
|
|
63
65
|
},
|
|
64
66
|
},
|
|
65
67
|
methods: {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
+
onBlur() {
|
|
69
|
+
// Update the undoStack when the Editor loses focus to trigger the autosave.
|
|
70
|
+
const child = this.$root.$children.find((c) => c.$refs.modeler);
|
|
71
|
+
child.$refs.modeler.pushToUndoStack();
|
|
68
72
|
},
|
|
69
73
|
},
|
|
70
74
|
};
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
@toggle-panels-compressed="panelsCompressed = !panelsCompressed"
|
|
12
12
|
@toggle-mini-map-open="miniMapOpen = $event"
|
|
13
13
|
@saveBpmn="saveBpmn"
|
|
14
|
+
@publishTemplate="publishTemplate"
|
|
14
15
|
@close="close"
|
|
15
16
|
@save-state="pushToUndoStack"
|
|
16
17
|
@clearSelection="clearSelection"
|
|
@@ -63,7 +64,7 @@
|
|
|
63
64
|
:parent-height="parentHeight"
|
|
64
65
|
:canvas-drag-position="canvasDragPosition"
|
|
65
66
|
:compressed="panelsCompressed && noElementsSelected"
|
|
66
|
-
@shape-resize="shapeResize"
|
|
67
|
+
@shape-resize="shapeResize(false)"
|
|
67
68
|
/>
|
|
68
69
|
|
|
69
70
|
<component
|
|
@@ -105,8 +106,8 @@
|
|
|
105
106
|
@copy-element="copyElement"
|
|
106
107
|
@copy-selection="copyElement"
|
|
107
108
|
@paste-element="pasteElements"
|
|
108
|
-
@
|
|
109
|
-
@
|
|
109
|
+
@clone-element="cloneElement"
|
|
110
|
+
@clone-selection="cloneSelection"
|
|
110
111
|
@default-flow="toggleDefaultFlow"
|
|
111
112
|
@shape-resize="shapeResize"
|
|
112
113
|
/>
|
|
@@ -116,7 +117,7 @@
|
|
|
116
117
|
:graph="graph"
|
|
117
118
|
:paperManager="paperManager"
|
|
118
119
|
:useModelGeometry="false"
|
|
119
|
-
@
|
|
120
|
+
@clone-selection="cloneSelection"
|
|
120
121
|
@remove-nodes="removeNodes"
|
|
121
122
|
:processNode="processNode"
|
|
122
123
|
@save-state="pushToUndoStack"
|
|
@@ -196,6 +197,7 @@ export default {
|
|
|
196
197
|
data() {
|
|
197
198
|
return {
|
|
198
199
|
pasteInProgress: false,
|
|
200
|
+
cloneInProgress: false,
|
|
199
201
|
internalClipboard: [],
|
|
200
202
|
tooltipTarget: null,
|
|
201
203
|
|
|
@@ -306,10 +308,10 @@ export default {
|
|
|
306
308
|
isAppleOS() {
|
|
307
309
|
return typeof navigator !== 'undefined' && /Mac|iPad|iPhone/.test(navigator.platform);
|
|
308
310
|
},
|
|
309
|
-
async shapeResize() {
|
|
311
|
+
async shapeResize(clearIfEmpty=true) {
|
|
310
312
|
await this.$nextTick();
|
|
311
313
|
await this.paperManager.awaitScheduledUpdates();
|
|
312
|
-
this.$refs.selector.updateSelectionBox(true);
|
|
314
|
+
this.$refs.selector.updateSelectionBox(true, clearIfEmpty);
|
|
313
315
|
},
|
|
314
316
|
toggleDefaultFlow(flow) {
|
|
315
317
|
const source = flow.definition.sourceRef;
|
|
@@ -318,7 +320,7 @@ export default {
|
|
|
318
320
|
}
|
|
319
321
|
source.set('default', flow);
|
|
320
322
|
},
|
|
321
|
-
|
|
323
|
+
cloneElement(node, copyCount) {
|
|
322
324
|
const clonedNode = node.clone(this.nodeRegistry, this.moddle, this.$t);
|
|
323
325
|
const yOffset = (node.diagram.bounds.height + 30) * copyCount;
|
|
324
326
|
|
|
@@ -335,11 +337,14 @@ export default {
|
|
|
335
337
|
processId,
|
|
336
338
|
];
|
|
337
339
|
if (this.highlightedNodes.length === 1 && flows.includes(this.highlightedNodes[0].type)) return;
|
|
338
|
-
store.commit('setCopiedElements', this.
|
|
340
|
+
store.commit('setCopiedElements', this.cloneNodesSelection());
|
|
339
341
|
this.$bvToast.toast(this.$t('Object(s) have been copied'), { noCloseButton:true, variant: 'success', solid: true, toaster: 'b-toaster-top-center' });
|
|
340
342
|
},
|
|
343
|
+
publishTemplate() {
|
|
344
|
+
this.$emit('publishTemplate');
|
|
345
|
+
},
|
|
341
346
|
async pasteElements() {
|
|
342
|
-
if (this.copiedElements && !this.pasteInProgress) {
|
|
347
|
+
if (this.copiedElements.length > 0 && !this.pasteInProgress) {
|
|
343
348
|
this.pasteInProgress = true;
|
|
344
349
|
try {
|
|
345
350
|
await this.addClonedNodes(this.copiedElements);
|
|
@@ -347,24 +352,31 @@ export default {
|
|
|
347
352
|
await this.paperManager.awaitScheduledUpdates();
|
|
348
353
|
await this.$refs.selector.selectElements(this.findViewElementsFromNodes(this.copiedElements), true);
|
|
349
354
|
await this.$nextTick();
|
|
350
|
-
await store.commit('setCopiedElements', this.
|
|
355
|
+
await store.commit('setCopiedElements', this.cloneNodesSelection());
|
|
351
356
|
this.scrollToSelection();
|
|
352
357
|
} finally {
|
|
353
358
|
this.pasteInProgress = false;
|
|
359
|
+
await this.pushToUndoStack();
|
|
354
360
|
}
|
|
355
361
|
}
|
|
356
362
|
},
|
|
357
|
-
async
|
|
358
|
-
const clonedNodes = this.
|
|
363
|
+
async cloneSelection() {
|
|
364
|
+
const clonedNodes = this.cloneNodesSelection();
|
|
359
365
|
if (clonedNodes && clonedNodes.length === 0) {
|
|
360
366
|
return;
|
|
361
367
|
}
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
+
try {
|
|
369
|
+
this.cloneInProgress = true;
|
|
370
|
+
this.$refs.selector.clearSelection();
|
|
371
|
+
await this.addClonedNodes(clonedNodes);
|
|
372
|
+
await this.$nextTick();
|
|
373
|
+
await this.paperManager.awaitScheduledUpdates();
|
|
374
|
+
await this.$refs.selector.selectElements(this.findViewElementsFromNodes(clonedNodes));
|
|
375
|
+
this.scrollToSelection();
|
|
376
|
+
} finally {
|
|
377
|
+
this.cloneInProgress = false;
|
|
378
|
+
await this.pushToUndoStack();
|
|
379
|
+
}
|
|
368
380
|
},
|
|
369
381
|
scrollToSelection() {
|
|
370
382
|
const containerRect = this.$refs['paper-container'].getBoundingClientRect();
|
|
@@ -440,9 +452,12 @@ export default {
|
|
|
440
452
|
}
|
|
441
453
|
},
|
|
442
454
|
async pushToUndoStack() {
|
|
455
|
+
if (this.pasteInProgress || this.cloneInProgress) {
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
443
458
|
try {
|
|
444
459
|
const xml = await this.getXmlFromDiagram();
|
|
445
|
-
undoRedoStore.dispatch('pushState', xml);
|
|
460
|
+
await undoRedoStore.dispatch('pushState', xml);
|
|
446
461
|
window.ProcessMaker.EventBus.$emit('modeler-change');
|
|
447
462
|
} catch (invalidXml) {
|
|
448
463
|
// eslint-disable-next-line no-console
|
|
@@ -793,12 +808,20 @@ export default {
|
|
|
793
808
|
this.isRendering = false;
|
|
794
809
|
this.$emit('parsed');
|
|
795
810
|
},
|
|
796
|
-
async loadXML(xml =
|
|
811
|
+
async loadXML(xml = null) {
|
|
812
|
+
let emitChangeEvent = false;
|
|
813
|
+
if (xml === null) {
|
|
814
|
+
xml = this.currentXML;
|
|
815
|
+
emitChangeEvent = true;
|
|
816
|
+
}
|
|
797
817
|
this.definitions = await this.xmlManager.getDefinitionsFromXml(xml);
|
|
798
818
|
this.xmlManager.definitions = this.definitions;
|
|
799
819
|
this.nodeIdGenerator = getNodeIdGenerator(this.definitions);
|
|
800
820
|
store.commit('clearNodes');
|
|
801
|
-
this.renderPaper();
|
|
821
|
+
await this.renderPaper();
|
|
822
|
+
if (emitChangeEvent) {
|
|
823
|
+
window.ProcessMaker.EventBus.$emit('modeler-change');
|
|
824
|
+
}
|
|
802
825
|
},
|
|
803
826
|
getBoundaryEvents(process) {
|
|
804
827
|
return process.get('flowElements').filter(({ $type }) => $type === 'bpmn:BoundaryEvent');
|
|
@@ -934,8 +957,6 @@ export default {
|
|
|
934
957
|
store.commit('addNode', node);
|
|
935
958
|
this.poolTarget = null;
|
|
936
959
|
});
|
|
937
|
-
|
|
938
|
-
await this.pushToUndoStack();
|
|
939
960
|
},
|
|
940
961
|
async removeNode(node, { removeRelationships = true } = {}) {
|
|
941
962
|
if (!node) {
|
|
@@ -958,10 +979,10 @@ export default {
|
|
|
958
979
|
store.commit('highlightNode', this.processNode);
|
|
959
980
|
this.$refs.selector.clearSelection();
|
|
960
981
|
await this.$nextTick();
|
|
961
|
-
this.pushToUndoStack();
|
|
982
|
+
await this.pushToUndoStack();
|
|
962
983
|
},
|
|
963
984
|
async removeNodes() {
|
|
964
|
-
this.performSingleUndoRedoTransaction(async() => {
|
|
985
|
+
await this.performSingleUndoRedoTransaction(async() => {
|
|
965
986
|
await this.paperManager.performAtomicAction(async() => {
|
|
966
987
|
const waitPromises = [];
|
|
967
988
|
this.highlightedNodes.forEach((node) =>
|
|
@@ -1004,7 +1025,7 @@ export default {
|
|
|
1004
1025
|
undoRedoStore.commit('disableSavingState');
|
|
1005
1026
|
await cb();
|
|
1006
1027
|
undoRedoStore.commit('enableSavingState');
|
|
1007
|
-
this.pushToUndoStack();
|
|
1028
|
+
await this.pushToUndoStack();
|
|
1008
1029
|
},
|
|
1009
1030
|
removeNodesFromLane(node) {
|
|
1010
1031
|
const containingLane = node.pool && node.pool.component.laneSet &&
|
|
@@ -1283,9 +1304,9 @@ export default {
|
|
|
1283
1304
|
|
|
1284
1305
|
/* Register custom nodes */
|
|
1285
1306
|
window.ProcessMaker.EventBus.$emit('modeler-start', {
|
|
1286
|
-
loadXML: xml => {
|
|
1287
|
-
this.loadXML(xml);
|
|
1288
|
-
undoRedoStore.dispatch('pushState', xml);
|
|
1307
|
+
loadXML: async(xml) => {
|
|
1308
|
+
await this.loadXML(xml);
|
|
1309
|
+
await undoRedoStore.dispatch('pushState', xml);
|
|
1289
1310
|
},
|
|
1290
1311
|
addWarnings: warnings => this.$emit('warnings', warnings),
|
|
1291
1312
|
addBreadcrumbs: breadcrumbs => this.breadcrumbData.push(breadcrumbs),
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
:plane-elements="$parent.planeElements"
|
|
17
17
|
:is-rendering="$parent.isRendering"
|
|
18
18
|
:dropdown-data="[]"
|
|
19
|
+
:has-pools="hasPoolsOrLanesSelected"
|
|
19
20
|
v-on="$listeners"
|
|
20
21
|
/>
|
|
21
22
|
</div>
|
|
@@ -28,6 +29,11 @@ import CrownMultiselect from '@/components/crown/crownMultiselect/crownMultisele
|
|
|
28
29
|
import { id as poolId } from '@/components/nodes/pool/config';
|
|
29
30
|
import { id as laneId } from '@/components/nodes/poolLane/config';
|
|
30
31
|
import { id as genericFlowId } from '@/components/nodes/genericFlow/config';
|
|
32
|
+
import { id as sequenceFlowId } from '@/components/nodes/sequenceFlow';
|
|
33
|
+
import { id as associationId } from '@/components/nodes/association';
|
|
34
|
+
import { id as messageFlowId } from '@/components/nodes/messageFlow/config';
|
|
35
|
+
import { id as dataOutputAssociationFlowId } from '@/components/nodes/dataOutputAssociation/config';
|
|
36
|
+
import { id as dataInputAssociationFlowId } from '@/components/nodes/dataInputAssociation/config';
|
|
31
37
|
import { labelWidth, poolPadding } from '../nodes/pool/poolSizes';
|
|
32
38
|
|
|
33
39
|
export default {
|
|
@@ -79,6 +85,14 @@ export default {
|
|
|
79
85
|
this.paperManager.paper.on('scale:changed ', this.updateSelectionBox);
|
|
80
86
|
this.paperManager.paper.on('translate:changed ', this.translateChanged);
|
|
81
87
|
},
|
|
88
|
+
computed: {
|
|
89
|
+
hasPoolsOrLanesSelected() {
|
|
90
|
+
return this.selected.some((view) => {
|
|
91
|
+
return view.model.component.node.type === poolId ||
|
|
92
|
+
view.model.component.node.type === laneId;
|
|
93
|
+
});
|
|
94
|
+
},
|
|
95
|
+
},
|
|
82
96
|
watch: {
|
|
83
97
|
// whenever selected changes
|
|
84
98
|
selected(newSelected) {
|
|
@@ -312,7 +326,7 @@ export default {
|
|
|
312
326
|
/**
|
|
313
327
|
* Update the selection Box
|
|
314
328
|
*/
|
|
315
|
-
updateSelectionBox(force=false) {
|
|
329
|
+
updateSelectionBox(force=false, clearIfEmpty=true) {
|
|
316
330
|
if (force || this.isSelecting && this.style) {
|
|
317
331
|
if (this.selected.length > 0) {
|
|
318
332
|
const box = this.getSelectionVertex(this.selected, false, true);
|
|
@@ -324,7 +338,7 @@ export default {
|
|
|
324
338
|
// Set the dimensions of the element
|
|
325
339
|
this.style.width = `${box.maxX - box.minX}px`;
|
|
326
340
|
this.style.height = `${box.maxY - box.minY}px`;
|
|
327
|
-
} else {
|
|
341
|
+
} else if (clearIfEmpty) {
|
|
328
342
|
this.clearSelection();
|
|
329
343
|
}
|
|
330
344
|
}
|
|
@@ -333,6 +347,13 @@ export default {
|
|
|
333
347
|
* Filter the selected elements
|
|
334
348
|
*/
|
|
335
349
|
filterSelected() {
|
|
350
|
+
const flowTypes = [
|
|
351
|
+
sequenceFlowId,
|
|
352
|
+
dataOutputAssociationFlowId,
|
|
353
|
+
dataInputAssociationFlowId,
|
|
354
|
+
associationId,
|
|
355
|
+
messageFlowId,
|
|
356
|
+
];
|
|
336
357
|
// Get the selected pools IDs
|
|
337
358
|
const selectedPoolsIds = this.selected
|
|
338
359
|
.filter(shape => shape.model.component)
|
|
@@ -343,6 +364,13 @@ export default {
|
|
|
343
364
|
if (shape.model.component && shape.model.component.node.pool) {
|
|
344
365
|
return shape.model.component.node.pool && !selectedPoolsIds.includes(shape.model.component.node.pool.component.node.id);
|
|
345
366
|
}
|
|
367
|
+
// remove from selection the selected flows that belongs to a selected pools
|
|
368
|
+
if (shape.model.component && flowTypes.includes(shape.model.component.node.type)) {
|
|
369
|
+
const parent = shape.model.getParentCell();
|
|
370
|
+
if (parent.component && parent.component.node.pool) {
|
|
371
|
+
return !selectedPoolsIds.includes(parent.component.node.pool.component.node.id);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
346
374
|
return true;
|
|
347
375
|
});
|
|
348
376
|
},
|
|
@@ -615,7 +643,7 @@ export default {
|
|
|
615
643
|
/**
|
|
616
644
|
* Rollback drag an element outside it's pool parent
|
|
617
645
|
*/
|
|
618
|
-
rollbackSelection(){
|
|
646
|
+
async rollbackSelection(){
|
|
619
647
|
const deltaX = this.initialPosition.left - this.left;
|
|
620
648
|
const deltaY = this.initialPosition.top - this.top;
|
|
621
649
|
this.style.left = `${this.initialPosition.left}px`;
|
|
@@ -624,14 +652,18 @@ export default {
|
|
|
624
652
|
const shapesToNotTranslate = [
|
|
625
653
|
'PoolLane',
|
|
626
654
|
'standard.Link',
|
|
655
|
+
'processmaker.components.nodes.boundaryEvent.Shape',
|
|
627
656
|
];
|
|
628
657
|
this.selected.filter(shape => !shapesToNotTranslate.includes(shape.model.get('type')))
|
|
629
658
|
.forEach(shape => {
|
|
630
659
|
shape.model.translate(deltaX/scale.sx, deltaY/scale.sy);
|
|
631
660
|
});
|
|
632
661
|
this.isOutOfThePool = false;
|
|
633
|
-
store.commit('allowSavingElementPosition');
|
|
662
|
+
await store.commit('allowSavingElementPosition');
|
|
634
663
|
this.paperManager.setStateValid();
|
|
664
|
+
await this.$nextTick();
|
|
665
|
+
await this.paperManager.awaitScheduledUpdates();
|
|
666
|
+
this.updateSelectionBox(true);
|
|
635
667
|
},
|
|
636
668
|
/**
|
|
637
669
|
* Expand and fit the pool container
|
|
@@ -187,9 +187,17 @@ export default class Node {
|
|
|
187
187
|
clonedFlow.id = null;
|
|
188
188
|
clonedFlow.pool = this.pool;
|
|
189
189
|
clonedFlow.cloneOf = this.id;
|
|
190
|
-
clonedFlow.diagram
|
|
190
|
+
clonedFlow.diagram = moddle.create('bpmndi:BPMNEdge', {
|
|
191
|
+
waypoint: [],
|
|
192
|
+
});
|
|
191
193
|
|
|
192
|
-
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
|
+
});
|
|
193
201
|
|
|
194
202
|
Object.keys(this.definition).filter(key => !Node.flowDefinitionPropertiesToNotCopy.includes(key)).forEach(key => {
|
|
195
203
|
const definition = this.definition.get(key);
|
|
@@ -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" />
|
|
@@ -9,8 +9,8 @@ import { getOrFindDataInput, findIOSpecificationOwner } from '../components/crow
|
|
|
9
9
|
|
|
10
10
|
export default {
|
|
11
11
|
methods: {
|
|
12
|
-
|
|
13
|
-
let clonedNodes = [], clonedFlows = [], clonedDataInputAssociations = [], clonedDataOutputAssociations = [];
|
|
12
|
+
cloneNodesSelection() {
|
|
13
|
+
let clonedNodes = [], clonedFlows = [], clonedBoundaryEvents = [], clonedDataInputAssociations = [], clonedDataOutputAssociations = [];
|
|
14
14
|
const nodes = this.highlightedNodes;
|
|
15
15
|
const selector = this.$refs.selector.$el;
|
|
16
16
|
const flowNodeTypes = [
|
|
@@ -42,12 +42,18 @@ export default {
|
|
|
42
42
|
clonedDataOutputAssociations.push(clonedFlow);
|
|
43
43
|
clonedNodes.push(clonedFlow);
|
|
44
44
|
} else {
|
|
45
|
+
// Validate boundary events and collect in clonedBoundaryEvents array
|
|
45
46
|
const clonedElement = this.cloneElementAndCalculateOffset(node);
|
|
46
|
-
|
|
47
|
+
if (node.definition && node.definition.$type !== 'bpmn:BoundaryEvent') {
|
|
48
|
+
clonedNodes.push(clonedElement);
|
|
49
|
+
} else {
|
|
50
|
+
clonedBoundaryEvents.push(clonedElement);
|
|
51
|
+
}
|
|
47
52
|
}
|
|
48
53
|
});
|
|
49
54
|
}
|
|
50
|
-
|
|
55
|
+
// Sets the clonedBoundaryEvents at the end of the array
|
|
56
|
+
clonedNodes = [...clonedNodes, ...clonedBoundaryEvents];
|
|
51
57
|
this.connectClonedFlows(clonedFlows, clonedNodes);
|
|
52
58
|
this.connectClonedDataInputAssociations(clonedDataInputAssociations, clonedNodes);
|
|
53
59
|
this.connectClonedDataOutputAssociations(clonedDataOutputAssociations, clonedNodes);
|
|
@@ -106,9 +112,11 @@ export default {
|
|
|
106
112
|
targetClone.definition.set('incoming', [clonedFlow.definition]);
|
|
107
113
|
}
|
|
108
114
|
|
|
115
|
+
const { height: selectorHeight } = this.$refs.selector.$el.getBoundingClientRect();
|
|
116
|
+
const { sy } = this.paper.scale();
|
|
117
|
+
const yOffset = selectorHeight / sy;
|
|
109
118
|
clonedFlow.diagram.waypoint.forEach(point => {
|
|
110
|
-
|
|
111
|
-
point.y += selectorHeight;
|
|
119
|
+
point.y += yOffset;
|
|
112
120
|
});
|
|
113
121
|
});
|
|
114
122
|
},
|