@it-enterprise/forcebpm-ui-kit 1.0.0 → 1.0.2
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/index.js +1 -0
- package/package.json +8 -3
- package/src/FAvatar.vue +257 -0
package/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@it-enterprise/forcebpm-ui-kit",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "FBPM UI Kit",
|
|
5
5
|
"author": "it-enterprise",
|
|
6
6
|
"license": "MIT",
|
|
@@ -14,6 +14,10 @@
|
|
|
14
14
|
"./FHtmlContent": {
|
|
15
15
|
"import": "./src/FHtmlContent.vue",
|
|
16
16
|
"require": "./src/FHtmlContent.vue"
|
|
17
|
+
},
|
|
18
|
+
"./FAvatar": {
|
|
19
|
+
"import": "./src/FAvatar.vue",
|
|
20
|
+
"require": "./src/FAvatar.vue"
|
|
17
21
|
}
|
|
18
22
|
},
|
|
19
23
|
"files": [
|
|
@@ -39,8 +43,9 @@
|
|
|
39
43
|
},
|
|
40
44
|
"devDependencies": {
|
|
41
45
|
"@vitejs/plugin-vue": "^5.0.0",
|
|
42
|
-
"
|
|
43
|
-
"
|
|
46
|
+
"@vue/compiler-sfc": "^3.0.0",
|
|
47
|
+
"sass-embedded": "^1.97.2",
|
|
48
|
+
"vite": "^5.0.0"
|
|
44
49
|
},
|
|
45
50
|
"scripts": {
|
|
46
51
|
"build": "vite build",
|
package/src/FAvatar.vue
ADDED
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
// FAvatar
|
|
3
|
+
import { computed, defineEmits } from 'vue'
|
|
4
|
+
|
|
5
|
+
const props = defineProps({
|
|
6
|
+
activeUserId: {
|
|
7
|
+
type: String,
|
|
8
|
+
default: null
|
|
9
|
+
},
|
|
10
|
+
fullUser: {
|
|
11
|
+
type: Object,
|
|
12
|
+
default: null
|
|
13
|
+
},
|
|
14
|
+
group: {
|
|
15
|
+
type: Object,
|
|
16
|
+
default: null,
|
|
17
|
+
validator: value => value && 'identityId' in value && 'name' in value
|
|
18
|
+
},
|
|
19
|
+
menuProps: {
|
|
20
|
+
type: Object,
|
|
21
|
+
default: () => ({})
|
|
22
|
+
},
|
|
23
|
+
size: {
|
|
24
|
+
type: [String, Number],
|
|
25
|
+
default: 20
|
|
26
|
+
},
|
|
27
|
+
avatarClass: {
|
|
28
|
+
type: String,
|
|
29
|
+
default: ''
|
|
30
|
+
},
|
|
31
|
+
disabled: {
|
|
32
|
+
type: Boolean,
|
|
33
|
+
default: false
|
|
34
|
+
}
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
const emit = defineEmits(['clearUserPhoto'])
|
|
38
|
+
|
|
39
|
+
const getInitialsByName = name => {
|
|
40
|
+
const splitter = name.split(' ')
|
|
41
|
+
const result = splitter.reduce((sum, current) => {
|
|
42
|
+
return sum + current.substr(0, 1)
|
|
43
|
+
}, '')
|
|
44
|
+
return result.slice(0, 2)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const userPhoto = computed(() => props.fullUser?.photo)
|
|
48
|
+
|
|
49
|
+
const sizeStyle = computed(() => {
|
|
50
|
+
return {
|
|
51
|
+
height: `${props.size}px`,
|
|
52
|
+
width: `${props.size}px`,
|
|
53
|
+
minHeight: `${props.size}px`,
|
|
54
|
+
minWidth: `${props.size}px`
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
const fontStyle = computed(() => {
|
|
59
|
+
const size = Number(props.size)
|
|
60
|
+
return {
|
|
61
|
+
'font-size': `${size - size / 2}px`,
|
|
62
|
+
'line-height': `${size}px`
|
|
63
|
+
}
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
const errorHandler = () => {
|
|
67
|
+
emit('clearUserPhoto', props.fullUser.userId)
|
|
68
|
+
}
|
|
69
|
+
</script>
|
|
70
|
+
|
|
71
|
+
<template>
|
|
72
|
+
<div class="f-avatar cursor-pointer" :style="sizeStyle">
|
|
73
|
+
<!-- GROUP -->
|
|
74
|
+
<v-tooltip v-if="group" :text="group.name" location="top right" :disabled="disabled">
|
|
75
|
+
<template #activator="{ props: propsTooltip }">
|
|
76
|
+
<div v-bind="propsTooltip" :style="sizeStyle" :class="avatarClass">
|
|
77
|
+
<i class="f-icon group-star bg-secondary text-center" :style="sizeStyle">
|
|
78
|
+
<span class="text-subTitle" :style="fontStyle">
|
|
79
|
+
{{ getInitialsByName(group.name) }}
|
|
80
|
+
</span>
|
|
81
|
+
</i>
|
|
82
|
+
</div>
|
|
83
|
+
</template>
|
|
84
|
+
</v-tooltip>
|
|
85
|
+
|
|
86
|
+
<!-- USER -->
|
|
87
|
+
<v-menu
|
|
88
|
+
v-else
|
|
89
|
+
v-bind="menuProps"
|
|
90
|
+
open-on-hover
|
|
91
|
+
close-delay="100"
|
|
92
|
+
open-delay="500"
|
|
93
|
+
location="bottom right"
|
|
94
|
+
:disabled="disabled || !fullUser?.name"
|
|
95
|
+
:close-on-content-click="false"
|
|
96
|
+
>
|
|
97
|
+
<template #activator="{ props: propsMenu }">
|
|
98
|
+
<!-- User -->
|
|
99
|
+
<div v-if="fullUser" v-bind="propsMenu" class="f-avatar-user" :class="avatarClass" :style="sizeStyle">
|
|
100
|
+
<!-- Image -->
|
|
101
|
+
<v-img
|
|
102
|
+
v-if="userPhoto"
|
|
103
|
+
:src="userPhoto"
|
|
104
|
+
:width="size"
|
|
105
|
+
:height="size"
|
|
106
|
+
:min-width="size"
|
|
107
|
+
:min-height="size"
|
|
108
|
+
:class="{ 'f-avatar-me': activeUserId === fullUser.userId }"
|
|
109
|
+
class="f-avatar-img"
|
|
110
|
+
@error="errorHandler"
|
|
111
|
+
>
|
|
112
|
+
<template #placeholder>
|
|
113
|
+
<v-skeleton-loader v-if="!fullUser?.name" :height="size" :width="size" type="avatar" />
|
|
114
|
+
<span v-else class="f-avatar-initials text-subTitle d-flex align-center justify-center" :style="[sizeStyle, fontStyle]">
|
|
115
|
+
{{ getInitialsByName(fullUser.name) }}
|
|
116
|
+
</span>
|
|
117
|
+
</template>
|
|
118
|
+
</v-img>
|
|
119
|
+
|
|
120
|
+
<!-- No avatar -->
|
|
121
|
+
<template v-else>
|
|
122
|
+
<v-skeleton-loader v-if="!fullUser?.name" :height="size" :width="size" type="avatar" />
|
|
123
|
+
<span
|
|
124
|
+
v-else
|
|
125
|
+
:style="[sizeStyle, fontStyle]"
|
|
126
|
+
:class="{ 'f-avatar-me': activeUserId === fullUser.userId }"
|
|
127
|
+
class="f-avatar-initials text-subTitle d-flex align-center justify-center"
|
|
128
|
+
>
|
|
129
|
+
{{ getInitialsByName(fullUser.name) }}
|
|
130
|
+
</span>
|
|
131
|
+
</template>
|
|
132
|
+
</div>
|
|
133
|
+
</template>
|
|
134
|
+
|
|
135
|
+
<!-- User info -->
|
|
136
|
+
<div v-if="fullUser" class="d-flex flex-column align-center f-avatar-user-info">
|
|
137
|
+
<v-img cover height="120px" width="120px" :src="userPhoto" :class="{ 'f-avatar-me': activeUserId === fullUser.userId }" class="f-avatar-img">
|
|
138
|
+
<template #placeholder>
|
|
139
|
+
<FIcon icon="user-line" color="disabled-light" size="55" />
|
|
140
|
+
</template>
|
|
141
|
+
</v-img>
|
|
142
|
+
|
|
143
|
+
<div class="selectable-text mt-5">
|
|
144
|
+
<!-- Name -->
|
|
145
|
+
<div class="text-title text-center font-weight-semibold f-avatar-user-info-name" style="word-break: break-all">
|
|
146
|
+
{{ fullUser.name || 'No Name' }}
|
|
147
|
+
</div>
|
|
148
|
+
|
|
149
|
+
<v-table class="f-avatar-user-info-table mt-5">
|
|
150
|
+
<tbody>
|
|
151
|
+
<!-- Phone -->
|
|
152
|
+
<tr>
|
|
153
|
+
<td class="text-text fs-09">{{ $t('user.telephone') }}</td>
|
|
154
|
+
<td class="text-subTitle">{{ fullUser.phone || '-' }}</td>
|
|
155
|
+
</tr>
|
|
156
|
+
<!-- E-mail -->
|
|
157
|
+
<tr>
|
|
158
|
+
<td class="text-text fs-09">E-mail</td>
|
|
159
|
+
<td class="text-subTitle text-lowercase" style="word-break: break-all">
|
|
160
|
+
{{ fullUser.email || '-' }}
|
|
161
|
+
</td>
|
|
162
|
+
</tr>
|
|
163
|
+
<!-- Position -->
|
|
164
|
+
<tr>
|
|
165
|
+
<td class="text-text fs-09">{{ $t('user.position') }}</td>
|
|
166
|
+
<td class="text-subTitle">
|
|
167
|
+
{{ fullUser.positionTitle || fullUser.positionCode || '-' }}
|
|
168
|
+
</td>
|
|
169
|
+
</tr>
|
|
170
|
+
<!-- Department -->
|
|
171
|
+
<tr>
|
|
172
|
+
<td class="text-text fs-09">{{ $t('user.department') }}</td>
|
|
173
|
+
<td class="text-subTitle">
|
|
174
|
+
{{ fullUser.department || '-' }}
|
|
175
|
+
</td>
|
|
176
|
+
</tr>
|
|
177
|
+
</tbody>
|
|
178
|
+
</v-table>
|
|
179
|
+
</div>
|
|
180
|
+
</div>
|
|
181
|
+
</v-menu>
|
|
182
|
+
</div>
|
|
183
|
+
</template>
|
|
184
|
+
|
|
185
|
+
<style lang="scss" scoped>
|
|
186
|
+
.f-avatar {
|
|
187
|
+
.f-avatar-user {
|
|
188
|
+
.f-avatar-initials {
|
|
189
|
+
position: relative;
|
|
190
|
+
border-radius: 50%;
|
|
191
|
+
border: 1px solid rgb(var(--v-theme-disabled));
|
|
192
|
+
background: rgb(var(--v-theme-fields));
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.v-skeleton-loader {
|
|
196
|
+
background: transparent;
|
|
197
|
+
:deep(.v-skeleton-loader__avatar) {
|
|
198
|
+
margin: 0;
|
|
199
|
+
height: inherit;
|
|
200
|
+
width: inherit;
|
|
201
|
+
max-width: inherit;
|
|
202
|
+
min-width: inherit;
|
|
203
|
+
max-height: inherit;
|
|
204
|
+
min-height: inherit;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
:deep(.f-avatar-user-info) {
|
|
211
|
+
min-width: 250px;
|
|
212
|
+
max-width: 400px;
|
|
213
|
+
padding: 20px;
|
|
214
|
+
|
|
215
|
+
.f-avatar-user-info-table {
|
|
216
|
+
background: transparent;
|
|
217
|
+
.v-table__wrapper {
|
|
218
|
+
overflow-x: hidden;
|
|
219
|
+
|
|
220
|
+
table tbody tr {
|
|
221
|
+
&:hover {
|
|
222
|
+
background: transparent;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
td {
|
|
226
|
+
padding: 4px 0;
|
|
227
|
+
border-bottom: none;
|
|
228
|
+
height: auto;
|
|
229
|
+
line-height: 1;
|
|
230
|
+
|
|
231
|
+
&:first-child {
|
|
232
|
+
vertical-align: top;
|
|
233
|
+
padding-right: 8px;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
:deep(.f-avatar-img.v-img) {
|
|
242
|
+
border-radius: 50%;
|
|
243
|
+
border: 1px solid rgb(var(--v-theme-disabled));
|
|
244
|
+
background: rgb(var(--v-theme-line));
|
|
245
|
+
.v-img__img {
|
|
246
|
+
background: #fff;
|
|
247
|
+
}
|
|
248
|
+
.v-img__placeholder {
|
|
249
|
+
display: flex;
|
|
250
|
+
align-items: center;
|
|
251
|
+
justify-content: center;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
.f-avatar-me {
|
|
255
|
+
border: 1px solid rgb(var(--v-theme-primary)) !important;
|
|
256
|
+
}
|
|
257
|
+
</style>
|