@processmaker/modeler 1.43.2 → 1.43.4

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.43.2",
3
+ "version": "1.43.4",
4
4
  "scripts": {
5
5
  "serve": "vue-cli-service serve --mode development",
6
6
  "test:unit": "vue-cli-service test:unit",
package/src/colorUtil.js CHANGED
@@ -44,7 +44,6 @@ export default class ColorUtil {
44
44
  * @returns {Number}
45
45
  */
46
46
  generateHSL(name) {
47
- console.log(name);
48
47
  const hash = this.getHashOfString(name);
49
48
  const h = this.normalizeHash(hash, 0, 360);
50
49
  const s = this.normalizeHash(hash, this.saturationRange[0], this.saturationRange[1]);
@@ -1,6 +1,11 @@
1
1
  <template>
2
2
  <div class="customAlert mx-auto mt-2">
3
- <b-alert show dismissible variant="warning">
3
+ <b-alert
4
+ show
5
+ dismissible
6
+ variant="warning"
7
+ @dismissed="onDismiss()"
8
+ >
4
9
  {{ $t("Generation of assets was not able to complete. Try again") }}
5
10
  </b-alert>
6
11
  </div>
@@ -11,6 +16,11 @@ export default {
11
16
  data() {
12
17
  return {};
13
18
  },
19
+ methods: {
20
+ onDismiss() {
21
+ this.$emit('onDismiss');
22
+ },
23
+ },
14
24
  };
15
25
  </script>
16
26
  <style scoped>
@@ -11,7 +11,7 @@
11
11
  <div class="p-0">
12
12
  <button
13
13
  class="h-100 px-3 cancel-btn btn btn-secondary"
14
- @click="onClose()"
14
+ @click="onStop()"
15
15
  >
16
16
  {{ $t("STOP") }}
17
17
  </button>
@@ -34,7 +34,7 @@ export default {
34
34
  };
35
35
  },
36
36
  methods: {
37
- onClose() {
37
+ onStop() {
38
38
  this.$emit('stopAssetGeneration');
39
39
  },
40
40
  },
@@ -25,6 +25,7 @@
25
25
  @clearSelection="clearSelection"
26
26
  :players="filteredPlayers"
27
27
  @action="handleToolbarAction"
28
+ @onGenerateAssets="generateAssets()"
28
29
  />
29
30
  <b-row class="modeler h-100">
30
31
  <b-tooltip
@@ -60,23 +61,25 @@
60
61
  ref="createAssetsCard"
61
62
  v-if="isAiGenerated"
62
63
  @onGenerateAssets="generateAssets()"
63
- @closeCreateAssets="onCloseCreateAssets()"
64
+ @closeCreateAssets="isAiGenerated = false"
64
65
  />
65
66
 
66
67
  <GeneratingAssetsCard
67
68
  ref="generatingAssetsCard"
68
- v-if="generatingAi"
69
+ v-if="loadingAI"
70
+ @stopAssetGeneration="onStopAssetGeneration()"
69
71
  />
70
72
 
71
73
  <AssetsCreatedCard
72
74
  ref="assetsCreatedCard"
73
75
  v-if="assetsCreated"
74
- @closeAssetsCreated="onCloseAssetsCreated()"
76
+ @closeAssetsCreated="assetsCreated = false"
75
77
  />
76
78
 
77
79
  <CreateAssetsFailCard
78
80
  ref="createAssetsFailCard"
79
- v-if="false"
81
+ v-if="assetFail"
82
+ @onDismiss="assetFail = false"
80
83
  />
81
84
 
82
85
  <InspectorButton
@@ -166,7 +169,7 @@
166
169
  />
167
170
 
168
171
  <RailBottom
169
- v-if="!generatingAi"
172
+ v-if="!loadingAI"
170
173
  :nodeTypes="nodeTypes"
171
174
  :paper-manager="paperManager"
172
175
  :graph="graph"
@@ -199,9 +202,7 @@
199
202
  </template>
200
203
 
201
204
  <script>
202
-
203
205
  import Vue from 'vue';
204
-
205
206
  import _ from 'lodash';
206
207
  import { dia } from 'jointjs';
207
208
  import boundaryEventConfig from '../nodes/boundaryEvent';
@@ -387,11 +388,12 @@ export default {
387
388
  currentCursorPosition: 0,
388
389
  previewPanelWidth: 600,
389
390
  isAiGenerated: window.ProcessMaker?.modeler?.isAiGenerated,
390
- generatingAi: false,
391
391
  assetsCreated: false,
392
- // ^ TODO: To be changed depending on microservice response
392
+ assetFail: false,
393
393
  currentNonce: null,
394
394
  promptSessionId: '',
395
+ loadingAI: false,
396
+ cancelledJobs: [],
395
397
  flowTypes: [
396
398
  'processmaker-modeler-sequence-flow',
397
399
  'processmaker-modeler-message-flow',
@@ -1731,6 +1733,47 @@ export default {
1731
1733
  this.players = this.players.map((item) => (item.id === data.id ? { ...item, ...data } : item));
1732
1734
  }
1733
1735
  },
1736
+ /**
1737
+ * Unhightligt selected Nodes
1738
+ * @param {String} clientId
1739
+ */
1740
+ unhightligtNodes(clientId) {
1741
+ const player = this.players.find(player => player.id === clientId);
1742
+
1743
+ player?.selectedNodes?.forEach((nodeId) => {
1744
+ const element = this.getElementByNodeId(nodeId);
1745
+ element.component.setHighlightColor(false, player.color);
1746
+ });
1747
+ },
1748
+ /**
1749
+ * Update the hightligted nodes
1750
+ * @param {Object} data
1751
+ */
1752
+ updateHightligtedNodes(data) {
1753
+ if (data) {
1754
+ this.unhightligtNodes(data.id);
1755
+ // highlight selected shape
1756
+ this.players = this.players.map((item) => (item.id === data.id ? { ...item, ...data } : item));
1757
+ data?.selectedNodes?.forEach((nodeId) => {
1758
+ const element = this.getElementByNodeId(nodeId);
1759
+ element.component.setHighlightColor(true, data.color);
1760
+ });
1761
+ }
1762
+ },
1763
+ isMultiplayerSelected(data) {
1764
+ let intersectionExists = false;
1765
+ if (data) {
1766
+ this.players?.some((player) => {
1767
+ if (intersectionExists) {
1768
+ return true; // This will break out of the loop
1769
+ }
1770
+ intersectionExists = player?.selectedNodes?.some(item => data.includes(item));
1771
+ return false;
1772
+ });
1773
+
1774
+ }
1775
+ return intersectionExists;
1776
+ },
1734
1777
  removePlayer(playerId) {
1735
1778
  const playerIndex = this.players.findIndex(player => player.id === playerId);
1736
1779
 
@@ -1804,7 +1847,7 @@ export default {
1804
1847
 
1805
1848
  let params = {
1806
1849
  server: window.location.host,
1807
- processId: this.processId,
1850
+ processId: window.ProcessMaker?.modeler?.process?.id,
1808
1851
  };
1809
1852
 
1810
1853
  if (this.promptSessionId && this.promptSessionId !== null && this.promptSessionId !== '') {
@@ -1819,9 +1862,8 @@ export default {
1819
1862
  this.promptSessionId = (response.data.promptSessionId);
1820
1863
  localStorage.promptSessionId = (response.data.promptSessionId);
1821
1864
  }).catch((error) => {
1822
- const errorMsg = error.response?.data?.message || error.message;
1823
-
1824
- if (error.response.status === 404) {
1865
+ const errorMsg = error.message;
1866
+ if (error === 404) {
1825
1867
  this.removePromptSessionForUser();
1826
1868
  localStorage.promptSessionId = '';
1827
1869
  this.promptSessionId = '';
@@ -1833,7 +1875,7 @@ export default {
1833
1875
  generateAssets() {
1834
1876
  this.getNonce();
1835
1877
 
1836
- // TODO: Add endpoint to get the promprSessionId
1878
+ this.fetchHistory();
1837
1879
 
1838
1880
  const params = {
1839
1881
  promptSessionId: this.promptSessionId,
@@ -1845,17 +1887,56 @@ export default {
1845
1887
 
1846
1888
  window.ProcessMaker.apiClient.post(url, params)
1847
1889
  .then(() => {
1890
+ // Response
1848
1891
  })
1849
1892
  .catch((error) => {
1850
1893
  const errorMsg = error.response?.data?.message || error.message;
1851
1894
  window.ProcessMaker.alert(errorMsg, 'danger');
1895
+ this.assetFail = true;
1852
1896
  });
1853
1897
  },
1854
- onCloseCreateAssets() {
1855
- this.isAiGenerated = false;
1898
+ subscribeToProgress() {
1899
+ const channel = `ProcessMaker.Models.User.${window.ProcessMaker?.modeler?.process?.user_id}`;
1900
+ const streamProgressEvent = '.ProcessMaker\\Package\\PackageAi\\Events\\GenerateArtifactsProgressEvent';
1901
+ window.Echo.private(channel).listen(
1902
+ streamProgressEvent,
1903
+ (response) => {
1904
+ if (response.data.promptSessionId !== this.promptSessionId) {
1905
+ return;
1906
+ }
1907
+
1908
+ if (this.cancelledJobs.some((element) => element === response.data.nonce)) {
1909
+ return;
1910
+ }
1911
+
1912
+ if (response.data) {
1913
+ if (response.data.progress.status === 'running') {
1914
+ this.loadingAI = true;
1915
+ // Blue color for nodes running
1916
+ } else if (response.data.progress.status === 'error') {
1917
+ this.loadingAI = false;
1918
+ window.ProcessMaker.alert(response.data.message, 'danger');
1919
+ // Stop and show error
1920
+ this.assetFail = true;
1921
+ } else {
1922
+ this.setPromptSessions(response.data.promptSessionId);
1923
+ // Successful generation
1924
+ this.assetsCreated = true;
1925
+ this.fetchHistory();
1926
+ setTimeout(() => {
1927
+ this.loadingAI = false;
1928
+ }, 500);
1929
+ }
1930
+ }
1931
+ },
1932
+ );
1856
1933
  },
1857
- onCloseAssetsCreated() {
1858
- this.assetsCreated = false;
1934
+ onStopAssetGeneration() {
1935
+ if (this.currentNonce) {
1936
+ this.cancelledJobs.push(this.currentNonce);
1937
+ localStorage.setItem('cancelledJobs', JSON.stringify(this.cancelledJobs));
1938
+ this.loadingAI = false;
1939
+ }
1859
1940
  },
1860
1941
  },
1861
1942
  created() {
@@ -2051,8 +2132,14 @@ export default {
2051
2132
  if (!localStorage.getItem('promptSessions') || localStorage.getItem('promptSessions') === 'null') {
2052
2133
  localStorage.setItem('promptSessions', JSON.stringify([]));
2053
2134
  }
2135
+ if (!localStorage.getItem('cancelledJobs') || localStorage.getItem('cancelledJobs') === 'null') {
2136
+ this.cancelledJobs = [];
2137
+ } else {
2138
+ this.cancelledJobs = JSON.parse(localStorage.getItem('cancelledJobs'));
2139
+ }
2054
2140
  this.promptSessionId = this.getPromptSessionForUser();
2055
2141
  this.fetchHistory();
2142
+ this.subscribeToProgress();
2056
2143
  },
2057
2144
  };
2058
2145
  </script>
@@ -112,6 +112,7 @@ export default {
112
112
  selected(newSelected) {
113
113
  this.prepareConectedLinks(newSelected);
114
114
  this.addToHighlightedNodes(newSelected);
115
+ this.highlightNodesMultiplayer (newSelected);
115
116
  },
116
117
  },
117
118
  methods: {
@@ -780,6 +781,18 @@ export default {
780
781
  store.commit('highlightNode', this.processNode);
781
782
  }
782
783
  },
784
+ highlightNodesMultiplayer(selected){
785
+ // Update selected nodes
786
+ window.ProcessMaker.EventBus.$emit('multiplayer-updateSelectedNodes', this.getSelectedNodeKeys(selected));
787
+ },
788
+ getSelectedNodeKeys(selected) {
789
+ const keys = [];
790
+ selected.forEach(shape => {
791
+ const { node } = shape.model.component;
792
+ keys.push( node.definition.id);
793
+ });
794
+ return keys;
795
+ },
783
796
  /**
784
797
  * Gets the child shape
785
798
  * @param {object} point
@@ -1,12 +1,11 @@
1
1
  import component from './boundaryTimerEvent.vue';
2
2
  import IntermediateTimer from '../../inspectors/IntermediateTimer.vue';
3
3
  import boundaryEventConfig from '../boundaryEvent';
4
- import merge from 'lodash/merge';
5
- import cloneDeep from 'lodash/cloneDeep';
6
4
  import interruptingToggleConfig from '../boundaryEvent/interruptingToggleInspector';
7
5
  import advancedAccordionConfig from '@/components/inspectors/advancedAccordionConfig';
8
6
  import documentationAccordionConfig from '@/components/inspectors/documentationAccordionConfig';
9
7
  import { defaultDurationTimerEvent } from '@/constants';
8
+ import { omit, cloneDeep, merge } from 'lodash';
10
9
 
11
10
  export const id = 'processmaker-modeler-boundary-timer-event';
12
11
 
@@ -42,7 +41,7 @@ export default merge(cloneDeep(boundaryEventConfig), {
42
41
  inspectorData(node) {
43
42
  return Object.entries(node.definition).reduce((data, [key, value]) => {
44
43
  if (key === 'eventDefinitions') {
45
- const type = Object.keys(value[0])[1];
44
+ const type = Object.keys(omit(value[0], ['id', '$type', 'get', 'set', '$instanceOf']))[0];
46
45
  const body = value[0][type].body;
47
46
  data[key] = { type, body };
48
47
  } else {
@@ -9,6 +9,7 @@
9
9
  :validation-errors="validationErrors"
10
10
  :warnings="warnings"
11
11
  :players="players"
12
+ v-on="$listeners"
12
13
  >
13
14
  <component
14
15
  :is="component.button"
@@ -7,7 +7,9 @@
7
7
  @openPanel="handleOpenPanel"
8
8
  />
9
9
 
10
- <AiGenerateButton/>
10
+ <AiGenerateButton
11
+ v-on="$listeners"
12
+ />
11
13
 
12
14
  <ValidateButton @openIssue="handleOpenIssue" />
13
15
 
@@ -117,25 +117,54 @@ export default {
117
117
  },
118
118
  },
119
119
  methods: {
120
- setShapeHighlight() {
121
- if (store.getters.isReadOnly) {
122
- this.shapeView.unhighlight(this.shapeBody, completedHighlighter);
123
- if (this.isCompleted) {
124
- this.shape.attr('body/fill', COLOR_COMPLETED_FILL);
125
- this.shapeView.highlight(this.shapeBody, completedHighlighter);
126
- }
127
- this.shapeView.unhighlight(this.shapeBody, inProgressHighlighter);
128
- if (this.isInProgress) {
129
- this.shape.attr('body/fill', COLOR_IN_PROGRESS_FILL);
130
- this.shapeView.highlight(this.shapeBody, inProgressHighlighter);
131
- }
132
- if (this.isIdle) {
133
- this.shape.attr('body/fill', COLOR_IDLE_FILL);
134
- this.shapeView.highlight(this.shapeBody, idleHighlighter);
135
- }
120
+ prepareCustomColorHighlighter(color) {
121
+ return {
122
+ highlighter: {
123
+ name: 'stroke',
124
+ options: {
125
+ attrs: {
126
+ stroke: color,
127
+ 'stroke-width': 3,
128
+ 'data-cy': 'selected',
129
+ },
130
+ },
131
+ partial: false,
132
+ type: 'default',
133
+ },
134
+ };
135
+ },
136
+ setHighlightColor(highlighted, color) {
137
+ if (!this.shapeView) {
136
138
  return;
137
139
  }
138
-
140
+ if (highlighted) {
141
+ this.shapeView.unhighlight(this.shapeBody, errorHighlighter);
142
+ this.shapeView.highlight(this.shapeBody, this.prepareCustomColorHighlighter(color));
143
+ } else {
144
+ this.shapeView.unhighlight(this.shapeBody, this.prepareCustomColorHighlighter(color));
145
+ }
146
+
147
+ },
148
+ setShapeHighlightForReadOnly() {
149
+ if (!this.shapeView) {
150
+ return;
151
+ }
152
+ this.shapeView.unhighlight(this.shapeBody, completedHighlighter);
153
+ if (this.isCompleted) {
154
+ this.shape.attr('body/fill', COLOR_COMPLETED_FILL);
155
+ this.shapeView.highlight(this.shapeBody, completedHighlighter);
156
+ }
157
+ this.shapeView.unhighlight(this.shapeBody, inProgressHighlighter);
158
+ if (this.isInProgress) {
159
+ this.shape.attr('body/fill', COLOR_IN_PROGRESS_FILL);
160
+ this.shapeView.highlight(this.shapeBody, inProgressHighlighter);
161
+ }
162
+ if (this.isIdle) {
163
+ this.shape.attr('body/fill', COLOR_IDLE_FILL);
164
+ this.shapeView.highlight(this.shapeBody, idleHighlighter);
165
+ }
166
+ },
167
+ setShapeHighlightForDefault() {
139
168
  if (!this.shapeView) {
140
169
  return;
141
170
  }
@@ -148,6 +177,19 @@ export default {
148
177
  this.shapeView.highlight(this.shapeBody, defaultHighlighter);
149
178
  }
150
179
  },
180
+ setShapeHighlight() {
181
+ if (!this.shapeView) {
182
+ return;
183
+ }
184
+ this.shapeView.unhighlight(this.shapeBody, errorHighlighter);
185
+ if (store.getters.isReadOnly) {
186
+ this.setShapeHighlightForReadOnly();
187
+ } else {
188
+ this.setShapeHighlightForDefault();
189
+ }
190
+ },
191
+
192
+
151
193
  setBorderOutline(borderOutline) {
152
194
  if (this.currentBorderOutline) {
153
195
  this.shapeView.unhighlight(this.shapeBody, this.currentBorderOutline);
@@ -82,6 +82,18 @@ export default {
82
82
  },
83
83
  },
84
84
  methods: {
85
+ setHighlightColor(highlighted, color){
86
+ if (highlighted) {
87
+ this.shape.attr({
88
+ line: { stroke: color },
89
+ '.joint-highlight-stroke': { 'display': 'none' },
90
+ });
91
+ this.shapeView.showTools();
92
+ } else {
93
+ resetShapeColor(this.shape);
94
+ this.shapeView.hideTools();
95
+ }
96
+ },
85
97
  setShapeHighlight() {
86
98
  if (this.isCompleted) {
87
99
  this.shape.attr({
@@ -67,6 +67,8 @@ export default class Multiplayer {
67
67
  });
68
68
 
69
69
  this.clientIO.on('clientLeft', (payload) => {
70
+ // Unhighlight nodes
71
+ this.modeler.unhightligtNodes(payload.clientId);
70
72
  // Remove the player from the multiplayer list
71
73
  this.modeler.removePlayer(payload.clientId);
72
74
 
@@ -80,11 +82,17 @@ export default class Multiplayer {
80
82
  this.syncLocalNodes(clientId);
81
83
  }
82
84
  });
83
-
85
+
86
+ // Listen for updates when the cursor data was updated
84
87
  this.clientIO.on('updateUserCursor', async(payload) => {
85
88
  this.updateClientCursor(payload);
86
89
  });
87
90
 
91
+ // Listen for updates when the cursor data was updated
92
+ this.clientIO.on('selectedNodesWasUpdated', async(payload) => {
93
+ this.updateHightligtedNodes(payload);
94
+ });
95
+
88
96
  // Listen for updates when a new element is added
89
97
  this.clientIO.on('createElement', async(payload) => {
90
98
  // Create the new element in the process
@@ -197,6 +205,11 @@ export default class Multiplayer {
197
205
  this.updateFlows(data);
198
206
  }
199
207
  });
208
+ window.ProcessMaker.EventBus.$on('multiplayer-updateSelectedNodes', ( data ) => {
209
+ if (this.modeler.isMultiplayer) {
210
+ this.updateSelectedNodes(data);
211
+ }
212
+ });
200
213
  window.ProcessMaker.EventBus.$on('multiplayer-updateMousePosition', ( data ) => {
201
214
  if (this.modeler.isMultiplayer) {
202
215
  this.updateMousePosition(data);
@@ -241,6 +254,31 @@ export default class Multiplayer {
241
254
  this.modeler.updateClientCursor(client);
242
255
  });
243
256
  }
257
+ /**
258
+ * Updates the selected nodes by the user
259
+ * @param {Object} data
260
+ */
261
+ updateSelectedNodes(data) {
262
+ const warningMessage = 'Another user is working on this object, wait until they finish making changes.';
263
+ if (this.modeler.isMultiplayerSelected(data)) {
264
+ window.ProcessMaker.alert(warningMessage, 'warning');
265
+ }
266
+ this.clientIO.emit('updateSelectedNodes', {
267
+ clientId: this.clientIO.id,
268
+ roomName: this.room.getRoom(),
269
+ selectedNodes: data,
270
+ });
271
+ }
272
+ /**
273
+ * Update highlighted nodes
274
+ * @param {Object} data
275
+ */
276
+ updateHightligtedNodes(payload) {
277
+ payload.clients.map(client => {
278
+ this.modeler.updateHightligtedNodes(client);
279
+ });
280
+ }
281
+
244
282
  /**
245
283
  * Sync the modeler nodes with the microservice
246
284
  * @param {String} clientId