@processmaker/modeler 1.39.6 → 1.39.7
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/img/cursor.86e6f3e3.svg +3 -0
- package/dist/modeler.common.js +444 -32
- package/dist/modeler.common.js.map +1 -1
- package/dist/modeler.umd.js +444 -32
- package/dist/modeler.umd.js.map +1 -1
- package/dist/modeler.umd.min.js +4 -4
- package/dist/modeler.umd.min.js.map +1 -1
- package/package.json +1 -1
- package/src/components/modeler/Modeler.vue +14 -2
- package/src/components/multiplayer/remoteCursor/RemoteCursor.vue +67 -0
- package/src/components/multiplayer/remoteCursor/cursor.svg +3 -0
- package/src/components/toolbar/ToolBar.vue +2 -0
- package/src/components/topRail/TopRail.vue +7 -1
- package/src/components/topRail/multiplayerViewUsers/MultiplayerViewUsers.vue +22 -0
- package/src/components/topRail/multiplayerViewUsers/avatar/Avatar.vue +137 -0
- package/src/components/topRail/multiplayerViewUsers/avatar/avatar.scss +6 -0
package/package.json
CHANGED
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
@close="close"
|
|
24
24
|
@save-state="pushToUndoStack"
|
|
25
25
|
@clearSelection="clearSelection"
|
|
26
|
+
:players="players"
|
|
26
27
|
@action="handleToolbarAction"
|
|
27
28
|
/>
|
|
28
29
|
<b-row class="modeler h-100">
|
|
@@ -153,6 +154,15 @@
|
|
|
153
154
|
@save-state="pushToUndoStack"
|
|
154
155
|
/>
|
|
155
156
|
</b-row>
|
|
157
|
+
|
|
158
|
+
<RemoteCursor
|
|
159
|
+
v-for="player in players"
|
|
160
|
+
:cursor-color="player.color"
|
|
161
|
+
:username="player.name"
|
|
162
|
+
:key="player.id"
|
|
163
|
+
:top="player.top"
|
|
164
|
+
:left="player.left"
|
|
165
|
+
/>
|
|
156
166
|
</span>
|
|
157
167
|
</template>
|
|
158
168
|
|
|
@@ -213,7 +223,7 @@ import RailBottom from '@/components/railBottom/RailBottom.vue';
|
|
|
213
223
|
import ProcessmakerModelerGenericFlow from '@/components/nodes/genericFlow/genericFlow';
|
|
214
224
|
|
|
215
225
|
import Selection from './Selection';
|
|
216
|
-
|
|
226
|
+
import RemoteCursor from '@/components/multiplayer/remoteCursor/RemoteCursor.vue';
|
|
217
227
|
|
|
218
228
|
export default {
|
|
219
229
|
components: {
|
|
@@ -225,6 +235,7 @@ export default {
|
|
|
225
235
|
ProcessmakerModelerGenericFlow,
|
|
226
236
|
Selection,
|
|
227
237
|
RailBottom,
|
|
238
|
+
RemoteCursor,
|
|
228
239
|
},
|
|
229
240
|
props: {
|
|
230
241
|
owner: Object,
|
|
@@ -313,6 +324,7 @@ export default {
|
|
|
313
324
|
isSelecting: false,
|
|
314
325
|
isIntoTheSelection: false,
|
|
315
326
|
dragStart: null,
|
|
327
|
+
players: [],
|
|
316
328
|
showInspectorButton: true,
|
|
317
329
|
inspectorButtonRight: 65,
|
|
318
330
|
};
|
|
@@ -907,7 +919,7 @@ export default {
|
|
|
907
919
|
|
|
908
920
|
const config = definition.config ? JSON.parse(definition.config) : {};
|
|
909
921
|
const type = config?.processKey || parser(definition, this.moddle);
|
|
910
|
-
|
|
922
|
+
|
|
911
923
|
const unnamedElements = ['bpmn:TextAnnotation', 'bpmn:Association', 'bpmn:DataOutputAssociation', 'bpmn:DataInputAssociation'];
|
|
912
924
|
const requireName = unnamedElements.indexOf(bpmnType) === -1;
|
|
913
925
|
if (requireName && !definition.get('name')) {
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="remote-cursor" :style="{ left: left + 'px', top: top + 'px' }">
|
|
3
|
+
<inline-svg :src="cursorIcon" :fill="cursorColor" />
|
|
4
|
+
|
|
5
|
+
<div class="remote-username">
|
|
6
|
+
{{ username }}
|
|
7
|
+
</div>
|
|
8
|
+
</div>
|
|
9
|
+
</template>
|
|
10
|
+
|
|
11
|
+
<script>
|
|
12
|
+
import InlineSvg from 'vue-inline-svg';
|
|
13
|
+
|
|
14
|
+
export default {
|
|
15
|
+
components: {
|
|
16
|
+
InlineSvg,
|
|
17
|
+
},
|
|
18
|
+
props: {
|
|
19
|
+
cursorColor: {
|
|
20
|
+
type: String,
|
|
21
|
+
default: '#000000',
|
|
22
|
+
},
|
|
23
|
+
username: {
|
|
24
|
+
type: String,
|
|
25
|
+
},
|
|
26
|
+
top: {
|
|
27
|
+
type: Number,
|
|
28
|
+
},
|
|
29
|
+
left: {
|
|
30
|
+
type: Number,
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
data() {
|
|
34
|
+
return {
|
|
35
|
+
cursorIcon: require('@/components/multiplayer/remoteCursor/cursor.svg'),
|
|
36
|
+
};
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<style scoped lang="scss">
|
|
42
|
+
.remote {
|
|
43
|
+
&-cursor {
|
|
44
|
+
position: absolute;
|
|
45
|
+
display: flex;
|
|
46
|
+
width: auto;
|
|
47
|
+
height: 34px;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
&-username {
|
|
51
|
+
display: flex;
|
|
52
|
+
justify-content: center;
|
|
53
|
+
align-items: center;
|
|
54
|
+
margin-top: 12px;
|
|
55
|
+
padding: 4px 10px;
|
|
56
|
+
gap: 10px;
|
|
57
|
+
border-radius: 4px;
|
|
58
|
+
background-color: #212529;
|
|
59
|
+
|
|
60
|
+
color: #FFFFFF;
|
|
61
|
+
font-size: 12px;
|
|
62
|
+
font-style: normal;
|
|
63
|
+
font-weight: 400;
|
|
64
|
+
line-height: normal;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
</style>
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
<TopRail
|
|
9
9
|
:validation-errors="validationErrors"
|
|
10
10
|
:warnings="warnings"
|
|
11
|
+
:players="players"
|
|
11
12
|
>
|
|
12
13
|
<component
|
|
13
14
|
:is="component.button"
|
|
@@ -129,6 +130,7 @@ export default {
|
|
|
129
130
|
'warnings',
|
|
130
131
|
'xmlManager',
|
|
131
132
|
'validationBar',
|
|
133
|
+
'players',
|
|
132
134
|
'extraActions',
|
|
133
135
|
],
|
|
134
136
|
watch: {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="top-rail-container">
|
|
3
|
+
<MultiplayerViewUsers :players="players"/>
|
|
3
4
|
<ValidateIssue
|
|
4
5
|
v-show="isOpenIssue"
|
|
5
6
|
:number-of-errors="numberOfErrors"
|
|
@@ -20,12 +21,13 @@
|
|
|
20
21
|
<script>
|
|
21
22
|
import store from '@/store';
|
|
22
23
|
import { ValidateButton, ValidateIssue, ValidatePanel } from '@/components/topRail/validateControl';
|
|
23
|
-
|
|
24
|
+
import MultiplayerViewUsers from '@/components/topRail/multiplayerViewUsers/MultiplayerViewUsers';
|
|
24
25
|
export default {
|
|
25
26
|
components: {
|
|
26
27
|
ValidateButton,
|
|
27
28
|
ValidateIssue,
|
|
28
29
|
ValidatePanel,
|
|
30
|
+
MultiplayerViewUsers,
|
|
29
31
|
},
|
|
30
32
|
props: {
|
|
31
33
|
validationErrors: {
|
|
@@ -36,6 +38,10 @@ export default {
|
|
|
36
38
|
type: Array,
|
|
37
39
|
required: true,
|
|
38
40
|
},
|
|
41
|
+
players: {
|
|
42
|
+
type: Array,
|
|
43
|
+
required: false,
|
|
44
|
+
},
|
|
39
45
|
},
|
|
40
46
|
data() {
|
|
41
47
|
return {
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<b-avatar-group class="container">
|
|
3
|
+
<template v-for="item in players" >
|
|
4
|
+
<Avatar :badgeBackgroundColor="item.color" :imgSrc= "item.imgSrc" :userName="item.name" :key="item.key"/>
|
|
5
|
+
</template>
|
|
6
|
+
</b-avatar-group>
|
|
7
|
+
</template>
|
|
8
|
+
|
|
9
|
+
<script>
|
|
10
|
+
import Avatar from '@/components/topRail/multiplayerViewUsers/avatar/Avatar';
|
|
11
|
+
export default {
|
|
12
|
+
components:{
|
|
13
|
+
Avatar,
|
|
14
|
+
},
|
|
15
|
+
props: {
|
|
16
|
+
players: {
|
|
17
|
+
type: Array,
|
|
18
|
+
required: true,
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
</script>
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<span
|
|
3
|
+
class="b-avatar rounded-circle"
|
|
4
|
+
:style="{'backgroundColor': generateColorHsl(userName, saturationRange, lightnessRange)}"
|
|
5
|
+
>
|
|
6
|
+
<span v-if="imgSrc" class="b-avatar-img">
|
|
7
|
+
<img :src="imgSrc" :alt=userName>
|
|
8
|
+
</span>
|
|
9
|
+
<span v-else class="b-avatar-text avatar-initials">
|
|
10
|
+
<span>
|
|
11
|
+
{{ this.getInitials(userName) }}
|
|
12
|
+
</span>
|
|
13
|
+
|
|
14
|
+
</span>
|
|
15
|
+
<span class="b-avatar-badge badge-danger"
|
|
16
|
+
:style="{bottom: '0px', right: '0px', backgroundColor: badgeBackgroundColor}"
|
|
17
|
+
/>
|
|
18
|
+
</span>
|
|
19
|
+
</template>
|
|
20
|
+
|
|
21
|
+
<script>
|
|
22
|
+
|
|
23
|
+
export default {
|
|
24
|
+
props: {
|
|
25
|
+
badgeBackgroundColor: {
|
|
26
|
+
type: String,
|
|
27
|
+
required: false,
|
|
28
|
+
},
|
|
29
|
+
imgSrc: {
|
|
30
|
+
type: String,
|
|
31
|
+
required: false,
|
|
32
|
+
},
|
|
33
|
+
userName: {
|
|
34
|
+
type: String,
|
|
35
|
+
required: false,
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
data() {
|
|
39
|
+
return {
|
|
40
|
+
saturation: 50,
|
|
41
|
+
lightness: 50,
|
|
42
|
+
range: 10,
|
|
43
|
+
};
|
|
44
|
+
},
|
|
45
|
+
computed: {
|
|
46
|
+
saturationRange() {
|
|
47
|
+
return this.getRange(this.saturation, this.range);
|
|
48
|
+
},
|
|
49
|
+
lightnessRange() {
|
|
50
|
+
return this.getRange(this.lightness, this.range);
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
methods: {
|
|
54
|
+
/**
|
|
55
|
+
* Get the initials from a given name.
|
|
56
|
+
*
|
|
57
|
+
* @param {string} name - The full name from which to extract initials.
|
|
58
|
+
* @returns {string} The initials of the first and last names.
|
|
59
|
+
*/
|
|
60
|
+
getInitials(name = '') {
|
|
61
|
+
const nameArray = name.split(' ');
|
|
62
|
+
const firstNameIn = nameArray[0].charAt(0).toUpperCase();
|
|
63
|
+
const lastNameIn = nameArray[nameArray.length - 1].charAt(0).toUpperCase();
|
|
64
|
+
return `${firstNameIn}${lastNameIn}`;
|
|
65
|
+
},
|
|
66
|
+
/**
|
|
67
|
+
* Calculates a hash value for a given string.
|
|
68
|
+
*
|
|
69
|
+
* @param {string} str - The input string for which the hash needs to be calculated.
|
|
70
|
+
* @returns {number} The calculated hash value for the input string.
|
|
71
|
+
*/
|
|
72
|
+
getHashOfString(str){
|
|
73
|
+
let hash = 0;
|
|
74
|
+
for (let i = 0; i < str.length; i++) {
|
|
75
|
+
hash = str.charCodeAt(i) + ((hash << 5) - hash);
|
|
76
|
+
}
|
|
77
|
+
hash = Math.abs(hash);
|
|
78
|
+
return hash;
|
|
79
|
+
},
|
|
80
|
+
/**
|
|
81
|
+
* Calculates a range around a given value.
|
|
82
|
+
*
|
|
83
|
+
* @param {number} value - The central value.
|
|
84
|
+
* @param {number} range - The range value.
|
|
85
|
+
* @returns {number[]} An array containing the lower and upper bounds of the range.
|
|
86
|
+
*/
|
|
87
|
+
getRange(value, range) {
|
|
88
|
+
return [Math.max(0, value-range), Math.min(value + range, 100)];
|
|
89
|
+
},
|
|
90
|
+
/**
|
|
91
|
+
* Get the hash number to within our range
|
|
92
|
+
*
|
|
93
|
+
* @param {Number} hash
|
|
94
|
+
* @param {Number} min
|
|
95
|
+
* @param {Number} max
|
|
96
|
+
* @returns {Number}
|
|
97
|
+
*/
|
|
98
|
+
normalizeHash(hash, min, max){
|
|
99
|
+
return Math.floor((hash % (max - min)) + min);
|
|
100
|
+
},
|
|
101
|
+
/**
|
|
102
|
+
*Generate Unique Color, create a string using our h,s,l values.
|
|
103
|
+
* @param {String} name
|
|
104
|
+
* @param {Array} saturationRange
|
|
105
|
+
* @param {Array} lightnessRange
|
|
106
|
+
* @returns {Number}
|
|
107
|
+
*/
|
|
108
|
+
generateHSL(name, saturationRange, lightnessRange) {
|
|
109
|
+
const hash = this.getHashOfString(name);
|
|
110
|
+
const h = this.normalizeHash(hash, 0, 360);
|
|
111
|
+
const s = this.normalizeHash(hash, saturationRange[0], saturationRange[1]);
|
|
112
|
+
const l = this.normalizeHash(hash, lightnessRange[0], lightnessRange[1]);
|
|
113
|
+
return [h, s, l];
|
|
114
|
+
},
|
|
115
|
+
/**
|
|
116
|
+
* Convert HSL array to string
|
|
117
|
+
* @param {Array} hsl
|
|
118
|
+
* @returns {String}
|
|
119
|
+
*/
|
|
120
|
+
HSLtoString(hsl) {
|
|
121
|
+
return `hsl(${hsl[0]}, ${hsl[1]}%, ${hsl[2]}%)`;
|
|
122
|
+
},
|
|
123
|
+
/**
|
|
124
|
+
* Generate a unique hsl value.
|
|
125
|
+
* @param {String} name
|
|
126
|
+
* @param {Array} saturationRange
|
|
127
|
+
* @param {Array} lightnessRange
|
|
128
|
+
* @returns {String}
|
|
129
|
+
*/
|
|
130
|
+
generateColorHsl(id, saturationRange, lightnessRange) {
|
|
131
|
+
return this.HSLtoString(this.generateHSL(id, saturationRange, lightnessRange));
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
</script>
|
|
137
|
+
<style scoped lang="scss" src="./avatar.scss"></style>
|