@processmaker/modeler 1.33.0 → 1.35.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 (41) hide show
  1. package/cypress.json +1 -1
  2. package/dist/modeler.common.js +846 -2162
  3. package/dist/modeler.common.js.map +1 -1
  4. package/dist/modeler.umd.js +846 -2162
  5. package/dist/modeler.umd.js.map +1 -1
  6. package/dist/modeler.umd.min.js +4 -4
  7. package/dist/modeler.umd.min.js.map +1 -1
  8. package/package.json +1 -1
  9. package/src/.DS_Store +0 -0
  10. package/src/ModelerApp.vue +0 -13
  11. package/src/components/crown/crownButtons/icons/faAlignBottom.js +3 -3
  12. package/src/components/crown/crownButtons/icons/faAlignLeft.js +3 -3
  13. package/src/components/crown/crownButtons/icons/faAlignRight.js +3 -3
  14. package/src/components/crown/crownButtons/icons/faAlignTop.js +3 -3
  15. package/src/components/crown/crownButtons/icons/faCenterHorizontally.js +3 -3
  16. package/src/components/crown/crownButtons/icons/faCenterVertically.js +3 -3
  17. package/src/components/crown/crownButtons/icons/faDistributeHorizontally.js +3 -3
  18. package/src/components/crown/crownButtons/icons/faDistributeVertically.js +3 -3
  19. package/src/components/crown/crownMultiselect/crownMultiselect.vue +3 -3
  20. package/src/components/highlightColors.js +8 -0
  21. package/src/components/inspectors/inspectorButton/inspectorButton.scss +1 -0
  22. package/src/components/modeler/Modeler.vue +46 -3
  23. package/src/components/nodes/index.js +0 -1
  24. package/src/components/railBottom/RailBottom.vue +9 -0
  25. package/src/components/railBottom/controls/Controls.vue +14 -2
  26. package/src/components/railBottom/controls/SubmenuPopper/SubmenuPopper.vue +6 -4
  27. package/src/components/railBottom/controls/controls.scss +2 -0
  28. package/src/components/railBottom/miniPaperControl/miniPaperControl.scss +1 -0
  29. package/src/components/railBottom/railBottom.scss +2 -0
  30. package/src/components/railBottom/zoomControl/ZoomControl.vue +1 -3
  31. package/src/components/rails/explorer-rail/explorer.vue +3 -3
  32. package/src/components/rails/explorer-rail/filterNodeTypes/filterNodeTypes.vue +3 -0
  33. package/src/components/rails/explorer-rail/pmBlocksLoop/pmBlocksLoop.vue +19 -9
  34. package/src/components/toolbar/ToolBar.vue +21 -5
  35. package/src/components/toolbar/toolbar.scss +23 -0
  36. package/src/components/topRail/validateControl/validateButton/ValidateButton.vue +2 -0
  37. package/src/mixins/highlightConfig.js +15 -12
  38. package/src/mixins/linkConfig.js +15 -8
  39. package/src/nodeTypesStore.js +2 -0
  40. package/src/store.js +1 -0
  41. package/src/components/modeler/ModelerReadonly.vue +0 -1042
@@ -1,1042 +0,0 @@
1
- <template>
2
- <span data-test="body-container">
3
- <div class="modeler h-100">
4
- <controls
5
- v-if="showControls"
6
- class="controls h-100 rounded-0 border-top-0 border-bottom-0 border-left-0"
7
- :nodeTypes="nodeTypes"
8
- :compressed="panelsCompressed"
9
- :parent-height="parentHeight"
10
- :allowDrop="allowDrop"
11
- :canvas-drag-position="canvasDragPosition"
12
- @drag="validateDropTarget"
13
- @handleDrop="handleDrop"
14
- />
15
- <b-col
16
- ref="paper-container"
17
- class="paper-container h-100 pr-4"
18
- :class="[cursor, { 'grabbing-cursor' : isGrabbing }]"
19
- :style="{ width: parentWidth, height: parentHeight }"
20
- >
21
-
22
- <div ref="paper" data-test="paper" class="main-paper" />
23
- </b-col>
24
-
25
- <component
26
- ref="nodeComponent"
27
- v-for="node in nodes"
28
- :is="node.type"
29
- :key="node._modelerId"
30
- :graph="graph"
31
- :paper="paper"
32
- :node="node"
33
- :id="node.id"
34
- :border-outline="borderOutline(node.id)"
35
- :collaboration="collaboration"
36
- :process-node="processNode"
37
- :processes="processes"
38
- :plane-elements="planeElements"
39
- :moddle="moddle"
40
- :nodeRegistry="nodeRegistry"
41
- :root-elements="definitions.get('rootElements')"
42
- :paperManager="paperManager"
43
- :auto-validate="autoValidate"
44
- :node-id-generator="nodeIdGenerator"
45
- :highlighted="highlightedNodes.includes(node)"
46
- :is-active="node === activeNode"
47
- :is-rendering="isRendering"
48
- :is-completed="requestCompletedNodes.includes(node.definition.id)"
49
- :is-in-progress="requestInProgressNodes.includes(node.definition.id)"
50
- :is-idle="requestIdleNodes.includes(node.definition.id)"
51
- @add-node="addNode"
52
- @set-cursor="cursor = $event"
53
- @set-pool-target="poolTarget = $event"
54
- @unset-pools="unsetPools"
55
- @clearSelection="clearSelection"
56
- @set-pools="setPools"
57
- @set-shape-stacking="setShapeStacking"
58
- @default-flow="toggleDefaultFlow"
59
- />
60
-
61
- <div class="rail-container">
62
- <div class="rail-left">
63
- <ZoomControl
64
- :paper-manager="paperManager"
65
- />
66
- </div>
67
- </div>
68
-
69
- <Selection
70
- v-if="paper"
71
- ref="selector"
72
- :graph="graph"
73
- :paperManager="paperManager"
74
- :useModelGeometry="false"
75
- :processNode="processNode"
76
- />
77
- </div>
78
- </span>
79
- </template>
80
-
81
- <script>
82
- import Vue from 'vue';
83
- import _ from 'lodash';
84
- import { dia } from 'jointjs';
85
- import boundaryEventConfig from '../nodes/boundaryEvent';
86
- import BpmnModdle from 'bpmn-moddle';
87
- import controls from '../controls/controls';
88
- import pull from 'lodash/pull';
89
- import remove from 'lodash/remove';
90
- import store from '@/store';
91
- import nodeTypesStore from '@/nodeTypesStore';
92
- import undoRedoStore from '@/undoRedoStore';
93
- import { Linter } from 'bpmnlint';
94
- import linterConfig from '../../../.bpmnlintrc';
95
- import { getNodeIdGenerator } from '../../NodeIdGenerator';
96
- import Process from '../inspectors/process';
97
- import runningInCypressTest from '@/runningInCypressTest';
98
- import getValidationProperties from '@/targetValidationUtils';
99
- import { id as laneId } from '@/components/nodes/poolLane/config';
100
- import { id as sequenceFlowId } from '../nodes/sequenceFlow';
101
- import { id as associationId } from '../nodes/association';
102
- import { id as messageFlowId } from '../nodes/messageFlow/config';
103
- import { id as dataOutputAssociationFlowId } from '../nodes/dataOutputAssociation/config';
104
- import { id as dataInputAssociationFlowId } from '../nodes/dataInputAssociation/config';
105
- import { id as genericFlowId } from '@/components/nodes/genericFlow/config';
106
-
107
- import PaperManager from '../paperManager';
108
- import registerInspectorExtension from '@/components/InspectorExtensionManager';
109
-
110
- import ensureShapeIsNotCovered from '@/components/shapeStackUtils';
111
- import Node from '@/components/nodes/node';
112
- import { addNodeToProcess } from '@/components/nodeManager';
113
- import TimerEventNode from '@/components/nodes/timerEventNode';
114
- import focusNameInputAndHighlightLabel from '@/components/modeler/focusNameInputAndHighlightLabel';
115
- import XMLManager from '@/components/modeler/XMLManager';
116
- import { NodeMigrator } from '@/components/modeler/NodeMigrator';
117
- import addLoopCharacteristics from '@/setup/addLoopCharacteristics';
118
- import Selection from './Selection';
119
- import ZoomControl from '@/components/railBottom/zoomControl/ZoomControl.vue';
120
-
121
- export default {
122
- components: {
123
- controls,
124
- Selection,
125
- ZoomControl,
126
- },
127
- props: {
128
- owner: Object,
129
- decorations: {
130
- type: Object,
131
- default() {
132
- return {};
133
- },
134
- },
135
- readOnly: {
136
- type: Boolean,
137
- default: true,
138
- },
139
- requestIdleNodes: {
140
- type: Array,
141
- default: () => [],
142
- },
143
- requestCompletedNodes: {
144
- type: Array,
145
- default: () => [],
146
- },
147
- requestInProgressNodes: {
148
- type: Array,
149
- default: () => [],
150
- },
151
- },
152
- data() {
153
- return {
154
- pasteInProgress: false,
155
- cloneInProgress: false,
156
- internalClipboard: [],
157
-
158
- /* Custom parsers for handling certain bpmn node types */
159
- parsers: {},
160
-
161
- // What bpmn moddle extensions should we register
162
- extensions: [],
163
- // Our node types, keyed by the id
164
- nodeRegistry: {},
165
-
166
- // Our jointjs data graph model
167
- graph: null,
168
- paper: null,
169
- paperManager: null,
170
-
171
- definitions: null,
172
- nodeIdGenerator: null,
173
- planeElements: null,
174
- canvasDragPosition: null,
175
- processNode: null,
176
- collaboration: null,
177
- moddle: null,
178
- allowDrop: true,
179
- poolTarget: null,
180
- processes: [],
181
- cursor: null,
182
- parentHeight: null,
183
- parentWidth: null,
184
- linter: null,
185
- validationErrors: {},
186
- miniMapOpen: false,
187
- panelsCompressed: false,
188
- isGrabbing: false,
189
- isRendering: false,
190
- allWarnings: [],
191
- nodeTypes: [],
192
- pmBlockNodes: [],
193
- activeNode: null,
194
- xmlManager: null,
195
- previouslyStackedShape: null,
196
- canvasScale: 1,
197
- initialScale: 1,
198
- minimumScale: 0.2,
199
- scaleStep: 0.1,
200
- isDragging: false,
201
- isSelecting: false,
202
- isIntoTheSelection: false,
203
- dragStart: null,
204
- };
205
- },
206
- watch: {
207
- isRendering() {
208
- const loadingMessage = 'Loading process, please be patient.';
209
-
210
- if (this.isRendering) {
211
- window.ProcessMaker.alert(loadingMessage, 'warning');
212
- document.body.style.cursor = 'wait !important';
213
- this.cursor = 'wait';
214
- return;
215
- }
216
-
217
- window.ProcessMaker.navbar.alerts = window.ProcessMaker.navbar.alerts.filter(alert => {
218
- return alert.alertText !== loadingMessage;
219
- });
220
- document.body.style.cursor = 'auto';
221
- this.cursor = null;
222
- },
223
- currentXML() {
224
- this.validateIfAutoValidateIsOn();
225
- },
226
- definitions() {
227
- this.validateIfAutoValidateIsOn();
228
- },
229
- autoValidate() {
230
- this.validateIfAutoValidateIsOn();
231
- },
232
- canvasScale(canvasScale) {
233
- this.paperManager.scale = canvasScale;
234
- },
235
- },
236
- computed: {
237
- showControls() {
238
- return !this.readOnly;
239
- },
240
- autoValidate: () => store.getters.autoValidate,
241
- nodes: () => store.getters.nodes,
242
- currentXML() {
243
- return undoRedoStore.getters.currentState;
244
- },
245
- /* connectors expect a highlightedNode property */
246
- highlightedNode: () => store.getters.highlightedNodes[0],
247
- highlightedNodes: () => store.getters.highlightedNodes,
248
- },
249
- methods: {
250
- toggleDefaultFlow(flow) {
251
- const source = flow.definition.sourceRef;
252
- if (source.default && source.default.id === flow.id) {
253
- flow = null;
254
- }
255
- source.set('default', flow);
256
- },
257
- borderOutline(nodeId) {
258
- return this.decorations.borderOutline && this.decorations.borderOutline[nodeId];
259
- },
260
- cleanPlaneElements() {
261
- remove(this.planeElements, diagram => !diagram.bpmnElement);
262
- },
263
- validateIfAutoValidateIsOn() {
264
- if (this.autoValidate) {
265
- this.validateBpmnDiagram();
266
- }
267
- },
268
- translateConfig(inspectorConfig) {
269
- if (inspectorConfig.config) {
270
- const config = inspectorConfig.config;
271
-
272
- config.label = this.$t(config.label);
273
- config.helper = this.$t(config.helper);
274
- }
275
-
276
- if (inspectorConfig.items) {
277
- inspectorConfig.items.forEach(this.translateConfig);
278
- }
279
- },
280
- getXmlFromDiagram() {
281
- return new Promise((resolve, reject) => {
282
- this.toXML((error, xml) => {
283
- if (error) {
284
- reject(error);
285
- } else {
286
- resolve(xml);
287
- }
288
- });
289
- });
290
- },
291
- async validateBpmnDiagram() {
292
- if (!store.getters.globalProcesses || store.getters.globalProcesses.length === 0) {
293
- await store.dispatch('fetchGlobalProcesses');
294
- }
295
- this.validationErrors = await this.linter.lint(this.definitions);
296
- this.$emit('validate', this.validationErrors);
297
- },
298
- setPools(poolDefinition) {
299
- if (!this.collaboration) {
300
- this.collaboration = this.moddle.create('bpmn:Collaboration');
301
- this.definitions.get('rootElements').push(this.collaboration);
302
- this.collaboration.set('id', 'collaboration_0');
303
- this.plane.set('bpmnElement', this.collaboration);
304
- }
305
-
306
- if (poolDefinition.get('processRef')) {
307
- if (!this.collaboration.get('participants').includes(poolDefinition)) {
308
- this.collaboration.get('participants').push(poolDefinition);
309
- }
310
-
311
- return;
312
- }
313
-
314
- let process;
315
- if (this.collaboration.get('participants').length === 0) {
316
- process = this.processNode.definition;
317
- } else {
318
- process = this.moddle.create('bpmn:Process');
319
- this.processes.push(process);
320
- process.set('id', `process_${this.processes.length}`);
321
-
322
- this.definitions.get('rootElements').push(process);
323
- }
324
-
325
- poolDefinition.set('processRef', process);
326
- this.collaboration.get('participants').push(poolDefinition);
327
- },
328
- unsetPools() {
329
- pull(this.definitions.get('rootElements'), this.collaboration);
330
- this.plane.set('bpmnElement', this.processNode.definition);
331
- this.collaboration = null;
332
- },
333
- highlightNode(node, event) {
334
- if (!node || !this.highlightedNode) {
335
- return;
336
- }
337
-
338
- if (event && event.shiftKey) {
339
- store.commit('addToHighlightedNodes', [node]);
340
- return;
341
- }
342
-
343
- let isSameHighlightedNode = _.isEqual(node.id, this.highlightedNode.id);
344
-
345
- if (!isSameHighlightedNode) {
346
- store.commit('highlightNode', node);
347
- }
348
-
349
- return;
350
- },
351
- blurFocusedScreenBuilderElement() {
352
- const elementsToBlur = ['INPUT', 'SELECT'];
353
- if (elementsToBlur.includes(document.activeElement && document.activeElement.tagName)) {
354
- document.activeElement.blur();
355
- }
356
- },
357
- registerStatusBar(component) {
358
- this.owner.validationBar.push(component);
359
- },
360
- /**
361
- * Register a mixin into a node component.
362
- * Used during "modeler-before-init"
363
- *
364
- */
365
- registerComponentMixin(component, mixin) {
366
- if (!component.mixins) {
367
- component.mixins = [];
368
- }
369
- component.mixins.push(mixin);
370
- },
371
- /**
372
- * Register a BPMN Moddle extension in order to support extensions to the bpmn xml format.
373
- * This is used to support new attributes and elements that would be needed for specific
374
- * bpmn execution environments.
375
- */
376
- registerBpmnExtension(namespace, extension) {
377
- this.extensions[namespace] = extension;
378
- },
379
- registerNode(nodeType, customParser) {
380
- const defaultParser = () => nodeType.id;
381
- const implementationParser = definition => {
382
- if (definition.get('implementation') === nodeType.implementation) {
383
- return nodeType.id;
384
- }
385
- return undefined;
386
- };
387
-
388
- this.translateConfig(nodeType.inspectorConfig[0]);
389
- addLoopCharacteristics(nodeType);
390
- this.nodeRegistry[nodeType.id] = nodeType;
391
-
392
- Vue.component(nodeType.id, nodeType.component);
393
- this.nodeTypes.push(nodeType);
394
-
395
- const types = Array.isArray(nodeType.bpmnType)
396
- ? nodeType.bpmnType
397
- : [nodeType.bpmnType];
398
-
399
- types.forEach(bpmnType => {
400
- if (!this.parsers[bpmnType]) {
401
- this.parsers[bpmnType] = { custom: [], implementation: [], default: []};
402
- }
403
-
404
- if (customParser) {
405
- this.parsers[bpmnType].custom.push(customParser);
406
- return;
407
- }
408
-
409
- if (nodeType.implementation) {
410
- this.parsers[bpmnType].implementation.push(implementationParser);
411
- return;
412
- }
413
-
414
- this.parsers[bpmnType].default.push(defaultParser);
415
- });
416
- },
417
- registerPmBlock(pmBlockNode, customParser) {
418
- const defaultParser = () => pmBlockNode.id;
419
-
420
- this.translateConfig(pmBlockNode.inspectorConfig[0]);
421
- addLoopCharacteristics(pmBlockNode);
422
- this.nodeRegistry[pmBlockNode.id] = pmBlockNode;
423
-
424
- Vue.component(pmBlockNode.id, pmBlockNode.component);
425
- this.pmBlockNodes.push(pmBlockNode);
426
-
427
- const types = Array.isArray(pmBlockNode.bpmnType)
428
- ? pmBlockNode.bpmnType
429
- : [pmBlockNode.bpmnType];
430
-
431
- types.forEach(bpmnType => {
432
- if (customParser) {
433
- this.parsers[bpmnType].custom.push(customParser);
434
- return;
435
- }
436
- this.parsers[bpmnType].default.push(defaultParser);
437
- });
438
- nodeTypesStore.commit('setPmBlockNodeTypes', this.pmBlockNodes);
439
- },
440
- addMessageFlows() {
441
- if (this.collaboration) {
442
- this.collaboration
443
- .get('messageFlows')
444
- .filter(this.hasSourceAndTarget)
445
- .forEach(this.setNode);
446
- }
447
- },
448
- loadAssociations(flowElements, artifacts) {
449
- artifacts
450
- .filter(definition => definition.$type === 'bpmn:Association' && this.hasSourceAndTarget(definition))
451
- .forEach(definition => this.setNode(definition, flowElements, artifacts));
452
- },
453
- loadDataAssociations(flowElements) {
454
- const tasksThatHaveDataOutputAssociations = flowElements.filter(task => task.get('dataOutputAssociations') &&
455
- task.get('dataOutputAssociations').length > 0);
456
-
457
- tasksThatHaveDataOutputAssociations.forEach(task => {
458
- task.get('dataOutputAssociations').forEach(dataAssociationLink => {
459
- this.setNode(dataAssociationLink, flowElements);
460
- });
461
- });
462
-
463
- const tasksThatHaveDataInputAssociations = flowElements.filter(task => task.get('dataInputAssociations') &&
464
- task.get('dataInputAssociations').length > 0);
465
-
466
- tasksThatHaveDataInputAssociations.forEach(task => {
467
- task.get('dataInputAssociations').forEach(dataAssociationLink => {
468
- this.setNode(dataAssociationLink, flowElements);
469
- });
470
- });
471
- },
472
- loadArtifacts(flowElements, artifacts) {
473
- artifacts
474
- .filter(definition => definition.$type !== 'bpmn:Association')
475
- .forEach(definition => this.setNode(definition, flowElements, artifacts));
476
- },
477
- loadSequenceFlows(flowElements, artifacts) {
478
- flowElements
479
- .filter(definition => definition.$type === 'bpmn:SequenceFlow' && this.hasSourceAndTarget(definition))
480
- .forEach(definition => this.setNode(definition, flowElements, artifacts));
481
- },
482
- loadFlowElements(flowElements, artifacts) {
483
- flowElements
484
- .filter(definition => definition.$type !== 'bpmn:SequenceFlow')
485
- .forEach(definition => this.setNode(definition, flowElements, artifacts));
486
- },
487
- addLanes(process) {
488
- if (process.get('laneSets')[0]) {
489
- process.laneSets[0].lanes.forEach(this.setNode);
490
- }
491
- },
492
- addPools() {
493
- if (!this.collaboration) {
494
- return;
495
- }
496
- this.collaboration.get('participants').forEach(this.setNode);
497
- },
498
- setUpDiagram() {
499
- this.processes.forEach(process => {
500
- this.ensureCancelActivityIsAddedToBoundaryEvents(process);
501
-
502
- this.addLanes(process);
503
-
504
- const flowElements = process.get('flowElements');
505
- const artifacts = process.get('artifacts');
506
-
507
- this.loadFlowElements(flowElements, artifacts);
508
- this.loadSequenceFlows(flowElements, artifacts);
509
- this.loadArtifacts(flowElements, artifacts);
510
- this.loadAssociations(flowElements, artifacts);
511
- this.loadDataAssociations(flowElements);
512
- });
513
-
514
- store.commit('setRootElements', this.definitions.rootElements);
515
-
516
- this.addMessageFlows();
517
-
518
- store.commit('highlightNode', this.processNode);
519
- },
520
- getCollaboration() {
521
- return this.definitions.rootElements.find(({ $type }) => $type === 'bpmn:Collaboration');
522
- },
523
- getProcesses() {
524
- return this.definitions.rootElements.filter(({ $type }) => $type === 'bpmn:Process');
525
- },
526
- getPlane() {
527
- return this.definitions.diagrams[0].plane;
528
- },
529
- getPlaneElements() {
530
- return this.plane.get('planeElement');
531
- },
532
- parse() {
533
- this.collaboration = this.getCollaboration();
534
- this.processes = this.getProcesses();
535
- this.plane = this.getPlane();
536
- this.planeElements = this.getPlaneElements();
537
-
538
- this.cleanPlaneElements();
539
-
540
- this.processNode = new Node(
541
- 'processmaker-modeler-process',
542
- this.processes[0],
543
- this.planeElements.find(diagram => diagram.bpmnElement.id === this.processes[0].id),
544
- );
545
- },
546
- removeUnsupportedElementAttributes(definition) {
547
- const unsupportedElements = ['extensionElements'];
548
-
549
- unsupportedElements.filter(name => definition.get(name))
550
- .forEach(name => definition.set(name, undefined));
551
- },
552
- getCustomParser(definition) {
553
- const parsers = this.parsers[(definition.$type)];
554
-
555
- if (!parsers) {
556
- return;
557
- }
558
-
559
- const customParser = parsers.custom.find(parser => parser(definition, this.moddle));
560
- const implementationParser = parsers.implementation.find(parser => parser(definition, this.moddle));
561
- const defaultParser = parsers.default.find(parser => parser(definition, this.moddle));
562
-
563
- return customParser || implementationParser || defaultParser;
564
- },
565
- handleUnsupportedElement(bpmnType, flowElements, definition, artifacts, diagram) {
566
- pull(flowElements, definition);
567
- pull(artifacts, definition);
568
- pull(this.planeElements, diagram);
569
- if (this.collaboration) {
570
- pull(this.collaboration.get('messageFlows'), definition);
571
- }
572
-
573
- const incomingFlows = definition.get('incoming');
574
- if (incomingFlows) {
575
- pull(flowElements, incomingFlows);
576
- }
577
-
578
- const outgoingFlows = definition.get('outgoing');
579
- if (outgoingFlows) {
580
- pull(flowElements, outgoingFlows);
581
- }
582
- },
583
- setNode(definition, flowElements, artifacts) {
584
- const diagram = this.planeElements.find(diagram => diagram.bpmnElement.id === definition.id);
585
- const bpmnType = definition.$type;
586
- const parser = this.getCustomParser(definition);
587
-
588
- if (!parser) {
589
- this.handleUnsupportedElement(bpmnType, flowElements, definition, artifacts, diagram);
590
- return;
591
- }
592
-
593
- this.removeUnsupportedElementAttributes(definition);
594
- const type = parser(definition, this.moddle);
595
-
596
- const unnamedElements = ['bpmn:TextAnnotation', 'bpmn:Association', 'bpmn:DataOutputAssociation', 'bpmn:DataInputAssociation'];
597
- const requireName = unnamedElements.indexOf(bpmnType) === -1;
598
- if (requireName && !definition.get('name')) {
599
- definition.set('name', '');
600
- }
601
-
602
- const node = this.createNode(type, definition, diagram);
603
-
604
- store.commit('addNode', node);
605
- },
606
- createNode(type, definition, diagram) {
607
- if (Node.isTimerType(type)) {
608
- return new TimerEventNode(type, definition, diagram);
609
- }
610
- // Remove undefined or null properties
611
- Object.keys(definition).forEach(key => {
612
- if (definition[key] === undefined || definition[key] === null) {
613
- delete definition[key];
614
- }
615
- });
616
- return new Node(type, definition, diagram);
617
- },
618
- hasSourceAndTarget(definition) {
619
- const hasSource = definition.sourceRef && this.parsers[definition.sourceRef.$type];
620
- const hasTarget = definition.targetRef && this.parsers[definition.targetRef.$type];
621
-
622
- return hasSource && hasTarget;
623
- },
624
- async waitForCursorToChange() {
625
- const cursorWaitTime = 300;
626
- await this.$nextTick();
627
- return new Promise(resolve => setTimeout(resolve, cursorWaitTime));
628
- },
629
- async renderPaper() {
630
- this.isRendering = true;
631
- await this.paperManager.performAtomicAction(async() => {
632
- await this.waitForCursorToChange();
633
- this.parse();
634
- this.addPools();
635
- this.setUpDiagram();
636
- });
637
- await this.paperManager.awaitScheduledUpdates();
638
- this.isRendering = false;
639
- this.$emit('parsed');
640
- },
641
- async loadXML(xml = null) {
642
- let emitChangeEvent = false;
643
- if (xml === null) {
644
- xml = this.currentXML;
645
- emitChangeEvent = true;
646
- }
647
- this.definitions = await this.xmlManager.getDefinitionsFromXml(xml);
648
- this.xmlManager.definitions = this.definitions;
649
- this.nodeIdGenerator = getNodeIdGenerator(this.definitions);
650
- store.commit('clearNodes');
651
- await this.renderPaper();
652
- if (emitChangeEvent) {
653
- window.ProcessMaker.EventBus.$emit('modeler-change');
654
- }
655
- },
656
- getBoundaryEvents(process) {
657
- return process.get('flowElements').filter(({ $type }) => $type === 'bpmn:BoundaryEvent');
658
- },
659
- createBoundaryEvent(definition) {
660
- const boundaryEvent = boundaryEventConfig.definition(this.moddle, this.$t);
661
- boundaryEvent.set('id', definition.get('id'));
662
- boundaryEvent.set('name', definition.get('name'));
663
- boundaryEvent.set('eventDefinitions', definition.get('eventDefinitions'));
664
- boundaryEvent.set('cancelActivity', definition.get('cancelActivity'));
665
- boundaryEvent.set('attachedToRef', definition.get('attachedToRef'));
666
- boundaryEvent.set('color', definition.get('color'));
667
- boundaryEvent.$parent = definition.$parent;
668
- if (definition.get('outgoing').length > 0) {
669
- boundaryEvent.set('outgoing', definition.get('outgoing'));
670
- }
671
- return boundaryEvent;
672
- },
673
- ensureCancelActivityIsAddedToBoundaryEvents(process) {
674
- this.getBoundaryEvents(process).forEach(definition => {
675
- const boundaryEvent = this.createBoundaryEvent(definition);
676
- definition.get('outgoing').forEach(outgoing => outgoing.set('sourceRef', boundaryEvent));
677
- this.replaceDefinition(definition, boundaryEvent, process);
678
- });
679
- },
680
- replaceDefinition(definition, boundaryEvent, process) {
681
- const definitionIndex = process.get('flowElements').indexOf(definition);
682
- process.flowElements[definitionIndex] = boundaryEvent;
683
- const boundaryEventDiagram = this.planeElements.find((diagram) => {
684
- return diagram.bpmnElement === definition;
685
- });
686
- boundaryEventDiagram.bpmnElement = boundaryEvent;
687
- },
688
- toXML(cb) {
689
- this.moddle.toXML(this.definitions, { format: true }, cb);
690
- },
691
- async handleDrop({ clientX, clientY, control, nodeThatWillBeReplaced }) {
692
- this.validateDropTarget({ clientX, clientY, control });
693
-
694
- if (!this.allowDrop) {
695
- return;
696
- }
697
-
698
- const definition = this.nodeRegistry[control.type].definition(this.moddle, this.$t);
699
-
700
- const diagram = this.nodeRegistry[control.type].diagram(this.moddle);
701
-
702
- const { x, y } = this.paperManager.clientToGridPoint(clientX, clientY);
703
- diagram.bounds.x = x;
704
- diagram.bounds.y = y;
705
-
706
- const newNode = this.createNode(control.type, definition, diagram);
707
-
708
- if (newNode.isBpmnType('bpmn:BoundaryEvent')) {
709
- this.setShapeCenterUnderCursor(diagram);
710
- }
711
-
712
- this.highlightNode(newNode);
713
- await this.addNode(newNode);
714
- if (!nodeThatWillBeReplaced) {
715
- return;
716
- }
717
-
718
- const nodeMigrator = new NodeMigrator(
719
- nodeThatWillBeReplaced,
720
- definition,
721
- this.graph,
722
- newNode,
723
- this.processes,
724
- this.collaboration,
725
- );
726
- nodeMigrator.migrate();
727
-
728
- return newNode;
729
- },
730
- setShapeCenterUnderCursor(diagram) {
731
- diagram.bounds.x -= (diagram.bounds.width / 2);
732
- diagram.bounds.y -= (diagram.bounds.height / 2);
733
- },
734
- async selectNewNode(node) {
735
- await this.$nextTick();
736
- await this.paperManager.awaitScheduledUpdates();
737
- const newNodeComponent = this.$refs.nodeComponent.find(component => component.node === node);
738
- const view = newNodeComponent.shapeView;
739
- await this.$refs.selector.selectElement(view);
740
- },
741
- async addNode(node) {
742
- if (!node.pool) {
743
- node.pool = this.poolTarget;
744
- }
745
-
746
- const targetProcess = node.getTargetProcess(this.processes, this.processNode);
747
- addNodeToProcess(node, targetProcess);
748
- node.setIds(this.nodeIdGenerator);
749
-
750
- this.planeElements.push(node.diagram);
751
- store.commit('addNode', node);
752
- this.poolTarget = null;
753
-
754
- // add processmaker-modeler-generic-flow
755
- if ([
756
- sequenceFlowId,
757
- laneId,
758
- associationId,
759
- messageFlowId,
760
- dataOutputAssociationFlowId,
761
- dataInputAssociationFlowId,
762
- genericFlowId,
763
- ].includes(node.type)) {
764
- return;
765
- }
766
-
767
- // Select the node after it has been added to the store (does not apply to flows)
768
- this.selectNewNode(node);
769
- },
770
- async addClonedNodes(nodes) {
771
- nodes.forEach(node => {
772
- if (!node.pool) {
773
- node.pool = this.poolTarget;
774
- }
775
-
776
- const targetProcess = node.getTargetProcess(this.processes, this.processNode);
777
- addNodeToProcess(node, targetProcess);
778
-
779
- this.planeElements.push(node.diagram);
780
- store.commit('addNode', node);
781
- this.poolTarget = null;
782
- });
783
- },
784
- handleResize() {
785
- const { clientWidth, clientHeight } = this.$el.parentElement;
786
- this.parentWidth = clientWidth + 'px';
787
- this.parentHeight = clientHeight + 'px';
788
-
789
- this.paperManager.setPaperDimensions(clientWidth, clientHeight);
790
- },
791
- validateDropTarget({ clientX, clientY, control }) {
792
- const { allowDrop, poolTarget } = getValidationProperties(clientX, clientY, control, this.paperManager.paper, this.graph, this.collaboration, this.$refs['paper-container']);
793
- this.allowDrop = allowDrop;
794
- this.poolTarget = poolTarget;
795
- },
796
- isBpmnNode(shape) {
797
- return shape.component != null;
798
- },
799
- setShapeStacking(shape) {
800
- if (this.isRendering || (!shape.component.node.isType('processmaker-modeler-pool') && shape === this.previouslyStackedShape)) {
801
- return;
802
- }
803
-
804
- this.previouslyStackedShape = shape;
805
- this.paperManager.performAtomicAction(() => ensureShapeIsNotCovered(shape, this.graph));
806
- },
807
- clearSelection(){
808
- this.$refs.selector.clearSelection();
809
- },
810
- isPointInSelection(event) {
811
- const selector = this.$refs.selector.$el;
812
- if (typeof selector.getBoundingClientRect === 'function') {
813
- // check if mouse was clicked inside the selector
814
- const { x: sx, y: sy, width:swidth, height: sheight } = selector.getBoundingClientRect();
815
- if (event.clientX >= sx && event.clientX <= sx + swidth && event.clientY >= sy && event.clientY <= sy + sheight) {
816
- return true;
817
- }
818
- }
819
- return false;
820
- },
821
- async pointerDownInShape(event, element) {
822
- const { clientX: x, clientY: y } = event;
823
- const shapeView = this.paper.findViewByModel(element);
824
- this.isDragging = false;
825
- this.isSelecting = false;
826
- this.isIntoTheSelection = false;
827
- this.dragStart = { x, y };
828
- // Verify if is in the selection box
829
- if (this.isPointInSelection(event)) {
830
- this.isIntoTheSelection = true;
831
- } else {
832
- if (!event.shiftKey) {
833
- await this.$refs.selector.selectElement(shapeView);
834
- await this.$nextTick();
835
- }
836
- }
837
- this.$refs.selector.startDrag({
838
- clientX: event.clientX,
839
- clientY: event.clientY,
840
- });
841
- },
842
- pointerUpHandler(event, cellView) {
843
- // is clicked over the shape
844
- if (cellView) {
845
- this.$refs.selector.selectElement(cellView);
846
- } else {
847
- this.clearSelection();
848
- }
849
-
850
- this.isDragging = false;
851
- this.dragStart = null;
852
- this.isSelecting = false;
853
- },
854
- },
855
- created() {
856
- if (runningInCypressTest()) {
857
- /* Add reference to store on window; this is used in testing to verify rendered nodes */
858
- window.store = store;
859
- }
860
-
861
- this.$t = this.$t.bind(this);
862
- /**
863
- * Before Initialize the BpmnModdle and its extensions.
864
- * In this stage the node components were not yet registered,
865
- * so they could be extended.
866
- */
867
- window.ProcessMaker.EventBus.$emit('modeler-before-init', {
868
- registerComponentMixin: this.registerComponentMixin,
869
- });
870
-
871
- this.registerNode(Process);
872
- /* Initialize the BpmnModdle and its extensions */
873
- window.ProcessMaker.EventBus.$emit('modeler-init', {
874
- registerInspectorExtension,
875
- registerBpmnExtension: this.registerBpmnExtension,
876
- registerNode: this.registerNode,
877
- registerStatusBar: this.registerStatusBar,
878
- registerPmBlock: this.registerPmBlock,
879
- });
880
-
881
- this.moddle = new BpmnModdle(this.extensions);
882
- this.linter = new Linter(linterConfig);
883
- this.xmlManager = new XMLManager(this.moddle);
884
- this.$emit('set-xml-manager', this.xmlManager);
885
- },
886
- mounted() {
887
- store.commit('setReadOnly', this.readOnly);
888
-
889
- this.graph = new dia.Graph();
890
- store.commit('setGraph', this.graph);
891
- this.graph.set('interactiveFunc', cellView => {
892
- const isPoolEdge = cellView.model.get('type') === 'standard.EmbeddedImage';
893
- return {
894
- elementMove: isPoolEdge,
895
- labelMove: false,
896
- };
897
- });
898
-
899
- this.paperManager = PaperManager.factory(this.$refs.paper, this.graph.get('interactiveFunc'), this.graph);
900
- this.paper = this.paperManager.paper;
901
-
902
- this.paperManager.addEventHandler('cell:pointerdblclick', focusNameInputAndHighlightLabel);
903
-
904
- this.handleResize();
905
- window.addEventListener('resize', this.handleResize);
906
-
907
- store.commit('setPaper', this.paperManager.paper);
908
-
909
- this.paperManager.addEventHandler('element:pointerclick', this.blurFocusedScreenBuilderElement, this);
910
-
911
- this.paperManager.addEventHandler('blank:pointerdown', (event, x, y) => {
912
- const scale = this.paperManager.scale;
913
- this.canvasDragPosition = { x: x * scale.sx, y: y * scale.sy };
914
- this.isGrabbing = true;
915
- }, this);
916
-
917
- this.paperManager.addEventHandler('cell:mouseover element:mouseover', ({ model: shape }) => {
918
- if (this.isBpmnNode(shape) && shape.attr('body/cursor') !== 'default' && !this.isGrabbing) {
919
- shape.attr('body/cursor', 'move');
920
- }
921
- // If the user is panning the Paper while hovering an element, ignore the default move cursor
922
- if (this.isGrabbing && this.isBpmnNode(shape)) {
923
- shape.attr('body/cursor', 'grabbing');
924
- }
925
- });
926
- this.paperManager.addEventHandler('blank:pointerup', (event) => {
927
- this.canvasDragPosition = null;
928
- this.isGrabbing = false;
929
- this.activeNode = null;
930
- this.pointerUpHandler(event);
931
- }, this);
932
-
933
- this.paperManager.addEventHandler('cell:pointerup', (cellView, event) => {
934
- this.canvasDragPosition = null;
935
- this.activeNode = null;
936
- this.pointerUpHandler(event, cellView);
937
- }, this);
938
-
939
- this.$el.addEventListener('mousemove', event => {
940
- if (this.canvasDragPosition) {
941
- this.paperManager.translate(
942
- event.offsetX - this.canvasDragPosition.x,
943
- event.offsetY - this.canvasDragPosition.y,
944
- );
945
- }
946
- }, this);
947
-
948
- this.$el.addEventListener('mouseenter', () => {
949
- store.commit('setClientLeftPaper', false);
950
- });
951
-
952
- this.$el.addEventListener('mouseleave', () => {
953
- this.paperManager.removeEventHandler('blank:pointermove');
954
- store.commit('setClientLeftPaper', true);
955
- });
956
-
957
- this.paperManager.addEventHandler('cell:pointerclick', (cellView, evt, x, y) => {
958
- const clickHandler = cellView.model.get('onClick');
959
- if (clickHandler) {
960
- clickHandler(cellView, evt, x, y);
961
- }
962
- });
963
-
964
- this.paperManager.addEventHandler('cell:pointerclick', ({ model: shape }, event) => {
965
- if (!this.isBpmnNode(shape)) {
966
- return;
967
- }
968
-
969
- // ignore click event if the user is grabbing the paper.
970
- if (this.isGrabbing) {
971
- return;
972
- }
973
-
974
- shape.component.$emit('click', event);
975
- this.$emit('click', {
976
- event,
977
- node: this.highlightedNode.definition,
978
- });
979
- });
980
-
981
- this.paperManager.addEventHandler('cell:pointerdown', ({ model: shape }, event) => {
982
- if (!this.isBpmnNode(shape)) {
983
- return;
984
- }
985
- // If the user is pressing Space (grabbing) and clicking on a Cell, return
986
- if (this.isGrabbing) {
987
- return;
988
- }
989
- this.setShapeStacking(shape);
990
- this.activeNode = shape.component.node;
991
- this.isOverShape = true;
992
- this.pointerDownInShape(event, shape);
993
- });
994
- // If the user is grabbing the paper while he clicked in a cell, move the paper and not the cell
995
- this.paperManager.addEventHandler('cell:pointermove', (_, event, x, y) => {
996
- if (this.isGrabbing) {
997
- if (!this.canvasDragPosition) {
998
- const scale = this.paperManager.scale;
999
- this.canvasDragPosition = { x: x * scale.sx, y: y * scale.sy };
1000
- }
1001
- if (this.canvasDragPosition && !this.clientLeftPaper) {
1002
- this.paperManager.translate(
1003
- event.offsetX - this.canvasDragPosition.x,
1004
- event.offsetY - this.canvasDragPosition.y
1005
- );
1006
- }
1007
- }
1008
- });
1009
-
1010
- /* Register custom nodes */
1011
- window.ProcessMaker.EventBus.$emit('modeler-start', {
1012
- loadXML: async(xml) => {
1013
- await this.loadXML(xml);
1014
- },
1015
- });
1016
- },
1017
- };
1018
- </script>
1019
- <style lang="scss" src="./modeler.scss" />
1020
- <style lang="scss">
1021
- svg {
1022
- overflow: visible !important;
1023
- }
1024
-
1025
- .rail {
1026
- &-container {
1027
- position: relative;
1028
- bottom: 60px;
1029
- display: inline-block;
1030
- height: 48px;
1031
- max-height: 48px;
1032
- z-index: 2;
1033
- }
1034
-
1035
- &-left {
1036
- position: absolute;
1037
- display: inline;
1038
- width: auto;
1039
- padding: 0 12px;
1040
- }
1041
- }
1042
- </style>