@processmaker/modeler 1.39.4 → 1.39.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@processmaker/modeler",
3
- "version": "1.39.4",
3
+ "version": "1.39.6",
4
4
  "scripts": {
5
5
  "serve": "vue-cli-service serve",
6
6
  "test:unit": "vue-cli-service test:unit",
Binary file
@@ -0,0 +1,40 @@
1
+ <template>
2
+ <crown-button
3
+ v-if="node.isBpmnType(...validPreviewElements)"
4
+ :title="$t('Preview')"
5
+ role="menuitem"
6
+ id="preview-button"
7
+ aria-label="Preview"
8
+ @click="preview()"
9
+ v-b-tooltip.hover.viewport.d50="{ customClass: 'no-pointer-events' }"
10
+ >
11
+ <i class="fas fa-eye cog-container--button"/>
12
+ </crown-button>
13
+ </template>
14
+
15
+ <script>
16
+ import trashIcon from '@/assets/trash-alt-solid.svg';
17
+ import CrownButton from '@/components/crown/crownButtons/crownButton';
18
+ import validPreviewElements from '@/components/crown/crownButtons/validPreviewElements';
19
+
20
+ export default {
21
+ components: { CrownButton },
22
+ props: { graph: Object, shape: Object, node: Object },
23
+ data() {
24
+ return {
25
+ trashIcon,
26
+ validPreviewElements,
27
+ };
28
+ },
29
+ computed: {
30
+ isPoolLane() {
31
+ return this.node.type === 'processmaker-modeler-lane';
32
+ },
33
+ },
34
+ methods: {
35
+ preview() {
36
+ this.$emit('previewNode', this.node);
37
+ },
38
+ },
39
+ };
40
+ </script>
@@ -0,0 +1,11 @@
1
+ const validPreviewElements = [
2
+ 'bpmn:Task',
3
+ 'bpmn:UserTask',
4
+ 'bpmn:GlobalTask',
5
+ 'bpmn:CallActivity',
6
+ 'bpmn:ManualTask',
7
+ 'bpmn:ScriptTask',
8
+ 'bpmn:ServiceTask',
9
+ ];
10
+
11
+ export default validPreviewElements;
@@ -62,6 +62,13 @@
62
62
  v-on="$listeners"
63
63
  />
64
64
 
65
+ <preview-button
66
+ :graph="graph"
67
+ :shape="shape"
68
+ :node="node"
69
+ v-on="$listeners"
70
+ />
71
+
65
72
  <b-modal
66
73
  :no-fade="runningInCypressTest"
67
74
  id="modal-prevent-closing"
@@ -79,6 +86,7 @@
79
86
  </template>
80
87
 
81
88
  <script>
89
+ import PreviewButton from '@/components/crown/crownButtons/previewButton';
82
90
  import DeleteButton from '@/components/crown/crownButtons/deleteButton';
83
91
  import GenericFlowButton from '@/components/crown/crownButtons/genericFlowButton';
84
92
  import AssociationFlowButton from '@/components/crown/crownButtons/associationFlowButton';
@@ -97,6 +105,7 @@ import runningInCypressTest from '@/runningInCypressTest';
97
105
  export default {
98
106
  components: {
99
107
  CrownDropdowns,
108
+ PreviewButton,
100
109
  DeleteButton,
101
110
  GenericFlowButton,
102
111
  AssociationFlowButton,
@@ -0,0 +1,47 @@
1
+ <template>
2
+ <div class="no-preview">
3
+ <img :src="noPreviewImg" alt="no preview">
4
+ <h1>No Screen Asigned</h1>
5
+ <h2>This is a placeholder screen. Please, assign a screen to this task.</h2>
6
+ </div>
7
+ </template>
8
+
9
+ <script>
10
+
11
+ export default {
12
+ data() {
13
+ return {
14
+ noPreviewImg: require('@/assets/noPreviewImage.png'),
15
+ };
16
+ },
17
+ };
18
+ </script>
19
+
20
+ <style scoped>
21
+ .no-preview {
22
+ display: flex;
23
+ flex-direction: column;
24
+ justify-content: center;
25
+ align-items: center;
26
+ color: #44494E;
27
+ padding: 5px;
28
+ }
29
+
30
+ .no-preview img {
31
+ max-width: 50%;
32
+ width: auto;
33
+ padding-bottom: 150px;
34
+ }
35
+
36
+ .no-preview h1 {
37
+ text-align: center;
38
+ font-weight: bold;
39
+ font-size: xx-large;
40
+ margin-bottom: 50px;
41
+ }
42
+
43
+ .no-preview h2 {
44
+ text-align: center;
45
+ font-size: x-large;
46
+ }
47
+ </style>
@@ -0,0 +1,148 @@
1
+ <template>
2
+ <b-col
3
+ v-show="visible"
4
+ id="preview_panel"
5
+ class="pl-0 h-100 overflow-hidden preview-column"
6
+ :style="{ maxWidth: width + 'px' }"
7
+ @mousedown="onMouseDown"
8
+ @mouseup="onMouseUp"
9
+ @mousemove="onMouseMove"
10
+ data-test="preview-column"
11
+ >
12
+ <b-row class="control-bar">
13
+ <b-col cols="9">
14
+ <div>
15
+ <i v-show = "selectedPreview == 1" class="fas fa-file-alt"/>
16
+ <b v-show = "selectedPreview == 2"> {} </b>
17
+ <b-dropdown
18
+ variant="ellipsis"
19
+ no-caret
20
+ no-flip
21
+ lazy
22
+ class="dropdown-right"
23
+ style="margin-top:-10px"
24
+ v-model="selectedPreview"
25
+ >
26
+ <template #button-content>
27
+ <i class="fas fa-sort-down" />
28
+ </template>
29
+
30
+ <b-dropdown-item key="1" class="ellipsis-dropdown-item mx-auto" @click="onSelectedPreview(1)">
31
+ <div class="ellipsis-dropdown-content">
32
+ <b class="pr-1 fa-fw fas fa-file-alt" />
33
+ <span>{{ $t('Document') }}</span>
34
+ </div>
35
+ </b-dropdown-item>
36
+
37
+ <b-dropdown-item key="2" class="ellipsis-dropdown-item mx-auto" @click="onSelectedPreview(2)">
38
+ <div class="ellipsis-dropdown-content">
39
+ <b class="pr-1 fa-fw">{ }</b>
40
+ <span>{{ $t('Object') }}</span>
41
+ </div>
42
+ </b-dropdown-item>
43
+ </b-dropdown>
44
+ <span>{{ $t('Preview') }} - {{ taskTitle }}</span>
45
+ </div>
46
+ </b-col>
47
+ <b-col class="actions">
48
+ <div>
49
+ <i class="fas fa-external-link-alt"/>
50
+ <i class="fas fa-times" @click="onClose()" />
51
+ </div>
52
+ </b-col>
53
+ </b-row>
54
+
55
+ <b-row>
56
+ <div style="background-color: #0074D9; height: 20px; width: 100%">&nbsp;</div>
57
+ </b-row>
58
+
59
+ <b-row>
60
+ <div class="item-title"> {{ screenTitle }} </div>
61
+ <div class="task-title"> {{ taskTitle }} </div>
62
+ </b-row>
63
+
64
+ <no-preview-available/>
65
+ </b-col>
66
+
67
+ </template>
68
+
69
+ <script>
70
+ import store from '@/store';
71
+ import NoPreviewAvailable from '@/components/inspectors/NoPreviewAvailable';
72
+
73
+ export default {
74
+ props: ['nodeRegistry', 'visible'],
75
+ components: {NoPreviewAvailable},
76
+ data() {
77
+ return {
78
+ data: {},
79
+ selectedPreview: '1',
80
+ taskTitle: '',
81
+ screenTitle: '',
82
+ width: 400,
83
+ isDragging: false,
84
+ currentPos: 400,
85
+ };
86
+ },
87
+ watch: {
88
+ highlightedNode() {
89
+ document.activeElement.blur();
90
+ this.prepareData();
91
+ },
92
+ 'highlightedNode.definition'(current, previous) { this.handleAssignmentChanges(current, previous); },
93
+ 'highlightedNode.definition.assignmentLock'(current, previous) { this.handleAssignmentChanges(current, previous); },
94
+ 'highlightedNode.definition.allowReassignment'(current, previous) { this.handleAssignmentChanges(current, previous); },
95
+ 'highlightedNode.definition.assignedUsers'(current, previous) { this.handleAssignmentChanges(current, previous); },
96
+ 'highlightedNode.definition.assignedGroups'(current, previous) { this.handleAssignmentChanges(current, previous); },
97
+ 'highlightedNode.definition.assignmentRules'(current, previous) { this.handleAssignmentChanges(current, previous); },
98
+ },
99
+ computed: {
100
+ highlightedNode() {
101
+ return store.getters.highlightedNodes[0];
102
+ },
103
+ },
104
+ methods: {
105
+ prepareData() {
106
+ if (!this.highlightedNode) {
107
+ return {};
108
+ }
109
+
110
+ this.taskTitle = this?.highlightedNode?.definition?.name;
111
+ },
112
+
113
+ handleAssignmentChanges(currentValue, previousValue) {
114
+ if (currentValue === previousValue) {
115
+ return;
116
+ }
117
+ this.prepareData();
118
+ },
119
+
120
+ onSelectedPreview(item) {
121
+ this.selectedPreview = item;
122
+ },
123
+ previewNode(node) {
124
+ this.taskTitle = node?.name;
125
+ this.showPanel = true;
126
+ },
127
+ onClose() {
128
+ this.$emit('togglePreview', false);
129
+ },
130
+ onMouseDown(event) {
131
+ this.isDragging = true;
132
+ this.currentPos = event.x;
133
+ },
134
+ onMouseUp() {
135
+ this.isDragging = false;
136
+ },
137
+ onMouseMove(event) {
138
+ if (this.isDragging) {
139
+ const dx = this.currentPos - event.x;
140
+ this.currentPos = event.x;
141
+ this.width = parseInt(this.width) + dx;
142
+ this.$emit('previewResize', this.width);
143
+ }
144
+ },
145
+ },
146
+ };
147
+ </script>
148
+ <style lang="scss" src="./preview_panel.scss" scoped />
@@ -0,0 +1,63 @@
1
+ $inspector-column-max-width: 400px;
2
+ $inspector-column-min-width: 400px;
3
+
4
+ #preview_panel::after {
5
+ display: flex;
6
+ content: '';
7
+ left: 0;
8
+ width: 5px;
9
+ height: 100%;
10
+ cursor: ew-resize;
11
+ }
12
+
13
+ .preview-column {
14
+ max-width: $inspector-column-max-width;
15
+ resize: both;
16
+ overflow:auto;
17
+ background-color: #F5F5F5;
18
+ border-left: 8px solid #EBEEF2;
19
+ }
20
+
21
+ .paneiframe {
22
+ display:block;
23
+ width:100%;
24
+ }
25
+
26
+ .preview-column .control-bar {
27
+ background-color: white;
28
+ padding: 0 5px 0 5px;
29
+ color: #7f7f7f;
30
+ }
31
+
32
+ .preview-column .control-bar .actions {
33
+ text-align: right;
34
+ }
35
+
36
+ .preview-column .control-bar .actions div {
37
+ width: 100%;
38
+ text-align: right;
39
+ }
40
+
41
+ .preview-column .control-bar .actions div i {
42
+ width: 20px;
43
+ cursor: pointer;
44
+ }
45
+
46
+ .item-title {
47
+ margin-top: 15px;
48
+ width: 100%;
49
+ height: 30px;
50
+ font-size: larger;
51
+ text-align: center;
52
+ align-items: center;
53
+ color: #7f7f7f;
54
+ }
55
+
56
+ .task-title {
57
+ width: 100%;
58
+ height: 60px;
59
+ font-size: xx-large;
60
+ font-weight: bold;
61
+ text-align: center;
62
+ color: #6c757d;
63
+ }
@@ -2,6 +2,7 @@
2
2
  <span data-test="body-container">
3
3
  <tool-bar
4
4
  v-if="showComponent"
5
+ ref="tool-bar"
5
6
  :canvas-drag-position="canvasDragPosition"
6
7
  :cursor="cursor"
7
8
  :is-rendering="isRendering"
@@ -12,6 +13,7 @@
12
13
  :warnings="allWarnings"
13
14
  :xml-manager="xmlManager"
14
15
  :validationBar="validationBar"
16
+ :extra-actions="extraActions"
15
17
  @load-xml="loadXML"
16
18
  @toggle-panels-compressed="panelsCompressed = !panelsCompressed"
17
19
  @toggle-mini-map-open="miniMapOpen = $event"
@@ -21,6 +23,7 @@
21
23
  @close="close"
22
24
  @save-state="pushToUndoStack"
23
25
  @clearSelection="clearSelection"
26
+ @action="handleToolbarAction"
24
27
  />
25
28
  <b-row class="modeler h-100">
26
29
  <b-tooltip
@@ -47,9 +50,18 @@
47
50
  </b-col>
48
51
 
49
52
  <InspectorButton
50
- v-if="showComponent"
53
+ ref="inspector-button"
54
+ v-if="showComponent && showInspectorButton"
51
55
  :showInspector="isOpenInspector"
52
- @toggleInspector="handleToggleInspector"
56
+ @toggleInspector="[handleToggleInspector($event), setInspectorButtonPosition($event)]"
57
+ :style="{ right: inspectorButtonRight + 'px' }"
58
+ />
59
+
60
+ <PreviewPanel ref="preview-panel"
61
+ @togglePreview="[handleTogglePreview($event), setInspectorButtonPosition($event)]"
62
+ @previewResize="setInspectorButtonPosition"
63
+ :visible="isOpenPreview"
64
+ :nodeRegistry="nodeRegistry"
53
65
  />
54
66
 
55
67
  <InspectorPanel
@@ -98,6 +110,7 @@
98
110
  :is-idle="requestIdleNodes.includes(node.definition.id)"
99
111
  @add-node="addNode"
100
112
  @remove-node="removeNode"
113
+ @previewNode="[handlePreview($event), setInspectorButtonPosition($event)]"
101
114
  @set-cursor="cursor = $event"
102
115
  @set-pool-target="poolTarget = $event"
103
116
  @unset-pools="unsetPools"
@@ -156,6 +169,7 @@ import store from '@/store';
156
169
  import nodeTypesStore from '@/nodeTypesStore';
157
170
  import InspectorButton from '@/components/inspectors/inspectorButton/InspectorButton.vue';
158
171
  import InspectorPanel from '@/components/inspectors/InspectorPanel';
172
+ import PreviewPanel from '@/components/inspectors/PreviewPanel';
159
173
  import undoRedoStore from '@/undoRedoStore';
160
174
  import { Linter } from 'bpmnlint';
161
175
  import linterConfig from '../../../.bpmnlintrc';
@@ -203,6 +217,7 @@ import Selection from './Selection';
203
217
 
204
218
  export default {
205
219
  components: {
220
+ PreviewPanel,
206
221
  ToolBar,
207
222
  ExplorerRail,
208
223
  InspectorButton,
@@ -242,6 +257,7 @@ export default {
242
257
  mixins: [hotkeys, cloneSelection],
243
258
  data() {
244
259
  return {
260
+ extraActions: [],
245
261
  pasteInProgress: false,
246
262
  cloneInProgress: false,
247
263
  internalClipboard: [],
@@ -278,6 +294,7 @@ export default {
278
294
  miniMapOpen: false,
279
295
  panelsCompressed: false,
280
296
  isOpenInspector: false,
297
+ isOpenPreview: false,
281
298
  isGrabbing: false,
282
299
  isRendering: false,
283
300
  allWarnings: [],
@@ -296,6 +313,8 @@ export default {
296
313
  isSelecting: false,
297
314
  isIntoTheSelection: false,
298
315
  dragStart: null,
316
+ showInspectorButton: true,
317
+ inspectorButtonRight: 65,
299
318
  };
300
319
  },
301
320
  watch: {
@@ -354,9 +373,36 @@ export default {
354
373
  showComponent: () => store.getters.showComponent,
355
374
  },
356
375
  methods: {
376
+ handleToolbarAction(action) {
377
+ if (action.handler instanceof Function) {
378
+ action.handler(this);
379
+ }
380
+ },
357
381
  handleToggleInspector(value) {
382
+ this.showInspectorButton = !(value ?? true);
358
383
  this.isOpenInspector = value;
359
384
  },
385
+ handlePreview(node) {
386
+ this.$refs['preview-panel'].previewNode(node);
387
+ this.handleTogglePreview(true) ;
388
+ },
389
+ handleTogglePreview(value) {
390
+ this.isOpenPreview = value;
391
+ },
392
+ setInspectorButtonPosition() {
393
+ const previewWidth = this.$refs['preview-panel'].width;
394
+ if (this.isOpenInspector) {
395
+ return;
396
+ }
397
+
398
+ if (this.isOpenPreview && !this.isOpenInspector) {
399
+ this.inspectorButtonRight = 65 + previewWidth;
400
+ }
401
+
402
+ if (!this.isOpenPreview && !this.isOpenInspector) {
403
+ this.inspectorButtonRight = 65;
404
+ }
405
+ },
360
406
  isAppleOS() {
361
407
  return typeof navigator !== 'undefined' && /Mac|iPad|iPhone/.test(navigator.platform);
362
408
  },
@@ -689,6 +735,15 @@ export default {
689
735
  });
690
736
  nodeTypesStore.commit('setPmBlockNodeTypes', this.pmBlockNodes);
691
737
  },
738
+ registerMenuAction(action) {
739
+ if (!action.value || typeof action.value !== 'string') {
740
+ throw new Error('Menu action must have a action.value');
741
+ }
742
+ if (!action.content || typeof action.content !== 'string') {
743
+ throw new Error('Menu action must have a action.content');
744
+ }
745
+ this.extraActions.push(action);
746
+ },
692
747
  addMessageFlows() {
693
748
  if (this.collaboration) {
694
749
  this.collaboration
@@ -1330,6 +1385,9 @@ export default {
1330
1385
  this.registerNode(Process);
1331
1386
  /* Initialize the BpmnModdle and its extensions */
1332
1387
  window.ProcessMaker.EventBus.$emit('modeler-init', {
1388
+ $t: this.$t,
1389
+ modeler: this,
1390
+ registerMenuAction: this.registerMenuAction,
1333
1391
  registerInspectorExtension,
1334
1392
  registerBpmnExtension: this.registerBpmnExtension,
1335
1393
  registerNode: this.registerNode,
@@ -1464,6 +1522,9 @@ export default {
1464
1522
 
1465
1523
  /* Register custom nodes */
1466
1524
  window.ProcessMaker.EventBus.$emit('modeler-start', {
1525
+ $t: this.$t,
1526
+ modeler: this,
1527
+ registerMenuAction: this.registerMenuAction,
1467
1528
  loadXML: async(xml) => {
1468
1529
  await this.loadXML(xml);
1469
1530
  await undoRedoStore.dispatch('pushState', xml);
@@ -20,6 +20,7 @@ import { shapes } from 'jointjs';
20
20
  import linkConfig from '@/mixins/linkConfig';
21
21
  import get from 'lodash/get';
22
22
  import { namePosition } from './sequenceFlowConfig';
23
+ import highlightConfig from '@/mixins/highlightConfig';
23
24
  import CrownConfig from '@/components/crown/crownConfig/crownConfig';
24
25
  import SequenceFlow from '@/components/nodes/genericFlow/SequenceFlow';
25
26
 
@@ -40,7 +41,7 @@ export default {
40
41
  'planeElements',
41
42
  'isRendering',
42
43
  ],
43
- mixins: [linkConfig],
44
+ mixins: [highlightConfig, linkConfig],
44
45
  data() {
45
46
  return {
46
47
  shape: null,
@@ -56,7 +56,7 @@
56
56
  {{ $t('Close') }}
57
57
  </a>
58
58
  <EllipsisMenu
59
- :actions="ellipsisMenuActions"
59
+ :actions="combinedMenuActions"
60
60
  :divider="false"
61
61
  @navigate="onNavigate"
62
62
  @show="onShow"
@@ -129,6 +129,7 @@ export default {
129
129
  'warnings',
130
130
  'xmlManager',
131
131
  'validationBar',
132
+ 'extraActions',
132
133
  ],
133
134
  watch: {
134
135
  miniMapOpen(isOpen) {
@@ -146,6 +147,9 @@ export default {
146
147
  },
147
148
  },
148
149
  computed: {
150
+ combinedMenuActions() {
151
+ return this.extraActions ? this.ellipsisMenuActions.concat(this.extraActions) : this.ellipsisMenuActions;
152
+ },
149
153
  canUndo() {
150
154
  return undoRedoStore.getters.canUndo;
151
155
  },
@@ -237,7 +241,7 @@ export default {
237
241
  this.$emit('publishPmBlock');
238
242
  break;
239
243
  default:
240
- break;
244
+ this.$emit('action', action);
241
245
  }
242
246
  },
243
247
  onShow() {
@@ -113,7 +113,7 @@ export default {
113
113
  return this.shape.findView(this.paperManager.paper);
114
114
  },
115
115
  shapeBody() {
116
- return this.shapeView.$el.find('[joint-selector=body]');
116
+ return this.shapeView.$el.find('[joint-selector=body]') || this.shapeView.$el;
117
117
  },
118
118
  },
119
119
  methods: {