@bimdata/bcf-components 6.6.2 → 6.7.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.
- package/package.json +1 -1
- package/src/components/bcf-statistics/BcfStatistics.scss +0 -1
- package/src/components/bcf-topic-form/BcfTopicForm.scss +4 -0
- package/src/components/bcf-topic-form/BcfTopicForm.vue +12 -0
- package/src/components/bcf-topic-form/bcf-topic-documents-selector/BcfTopicDocumentsSelector.vue +1 -1
- package/src/components/bcf-topic-form/bcf-topic-groups/BcfTopicGroups.vue +148 -0
- package/src/components/bcf-topic-form/bcf-topic-groups/GroupItem.vue +70 -0
- package/src/components/user-avatar/UserAvatar.vue +32 -1
- package/src/components/user-avatar/UserAvatarList.vue +113 -0
- package/src/i18n/lang/en.json +4 -1
- package/src/i18n/lang/fr.json +4 -1
- package/src/service.js +4 -0
- package/src/components/user-avatar/UserAvatar.scss +0 -30
package/package.json
CHANGED
|
@@ -164,6 +164,11 @@
|
|
|
164
164
|
:documents="topicDocuments"
|
|
165
165
|
@selection-change="topicDocuments = $event"
|
|
166
166
|
/>
|
|
167
|
+
<BcfTopicGroups
|
|
168
|
+
:project="project"
|
|
169
|
+
:groups="topicGroups"
|
|
170
|
+
@selection-change="topicGroups = $event"
|
|
171
|
+
/>
|
|
167
172
|
</div>
|
|
168
173
|
</div>
|
|
169
174
|
|
|
@@ -210,10 +215,12 @@ import BcfTopicDocumentsSelector from "./bcf-topic-documents-selector/BcfTopicDo
|
|
|
210
215
|
import BcfTopicImages from "./bcf-topic-images/BcfTopicImages.vue";
|
|
211
216
|
import BcfTopicSnapshots from "./bcf-topic-snapshots/BcfTopicSnapshots.vue";
|
|
212
217
|
import BcfTopicSnapshotsActions from "./bcf-topic-snapshots-actions/BcfTopicSnapshotsActions.vue";
|
|
218
|
+
import BcfTopicGroups from "./bcf-topic-groups/BcfTopicGroups.vue";
|
|
213
219
|
|
|
214
220
|
export default {
|
|
215
221
|
components: {
|
|
216
222
|
BcfTopicDocumentsSelector,
|
|
223
|
+
BcfTopicGroups,
|
|
217
224
|
BcfTopicImages,
|
|
218
225
|
BcfTopicSnapshots,
|
|
219
226
|
BcfTopicSnapshotsActions,
|
|
@@ -297,6 +304,7 @@ export default {
|
|
|
297
304
|
const topicDescription = ref("");
|
|
298
305
|
const topicLabels = ref([]);
|
|
299
306
|
const topicDocuments = ref([]);
|
|
307
|
+
const topicGroups = ref([]);
|
|
300
308
|
const viewpoints = ref([]);
|
|
301
309
|
|
|
302
310
|
const viewpointsToCreate = ref([]);
|
|
@@ -326,6 +334,7 @@ export default {
|
|
|
326
334
|
topicDescription.value = "";
|
|
327
335
|
topicLabels.value = [];
|
|
328
336
|
topicDocuments.value = [];
|
|
337
|
+
topicGroups.value = [];
|
|
329
338
|
viewpoints.value = [];
|
|
330
339
|
viewpointsToCreate.value = [];
|
|
331
340
|
viewpointsToUpdate.value = [];
|
|
@@ -349,6 +358,7 @@ export default {
|
|
|
349
358
|
topicDescription.value = topic.description || "";
|
|
350
359
|
topicLabels.value = topic.labels || [];
|
|
351
360
|
topicDocuments.value = topic.documents || [];
|
|
361
|
+
topicGroups.value = topic.groups || [];
|
|
352
362
|
viewpoints.value = topic.viewpoints || [];
|
|
353
363
|
} else {
|
|
354
364
|
reset();
|
|
@@ -466,6 +476,7 @@ export default {
|
|
|
466
476
|
due_date: topicDueDate.value,
|
|
467
477
|
description: topicDescription.value,
|
|
468
478
|
labels: topicLabels.value,
|
|
479
|
+
groups: topicGroups.value,
|
|
469
480
|
bimdata_viewer_layout: viewpointsToCreate.value.length > 1 && viewerLayout ? viewerLayout : props.topic?.bimdata_viewer_layout,
|
|
470
481
|
};
|
|
471
482
|
|
|
@@ -520,6 +531,7 @@ export default {
|
|
|
520
531
|
topicDescription,
|
|
521
532
|
topicDocuments,
|
|
522
533
|
topicDueDate,
|
|
534
|
+
topicGroups,
|
|
523
535
|
topicPriority,
|
|
524
536
|
topicStage,
|
|
525
537
|
topicStatus,
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="bcf-topic-groups" @click="isOpenGroups = true">
|
|
3
|
+
<span class="label">
|
|
4
|
+
<template v-if="groups.length > 0">
|
|
5
|
+
{{ $t("BcfComponents.BcfTopicForm.groupsCount", { count: groups.length }) }}
|
|
6
|
+
</template>
|
|
7
|
+
<template v-else>
|
|
8
|
+
{{ $t("BcfComponents.BcfTopicForm.groupsLabel") }}
|
|
9
|
+
</template>
|
|
10
|
+
</span>
|
|
11
|
+
<BIMDataIconChevron size="xxs" />
|
|
12
|
+
<div class="underline"></div>
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
<div v-if="isOpenGroups" class="bcf-topic-groups__selector">
|
|
16
|
+
<BIMDataButton ghost radius @click="isOpenGroups = false">
|
|
17
|
+
<BIMDataIconArrow size="xxs" />
|
|
18
|
+
<span class="m-l-6">{{ "BcfComponents.back" }}</span>
|
|
19
|
+
</BIMDataButton>
|
|
20
|
+
<div class="body">
|
|
21
|
+
<div class="text">
|
|
22
|
+
{{ $t("BcfComponents.BcfTopicForm.groupsText") }}
|
|
23
|
+
</div>
|
|
24
|
+
<div class="list">
|
|
25
|
+
<GroupItem
|
|
26
|
+
v-for="group in projectGroups"
|
|
27
|
+
:key="group.id"
|
|
28
|
+
:group="group"
|
|
29
|
+
:selected="topicGroups.includes(group.id)"
|
|
30
|
+
@toggle="toggleGroup"
|
|
31
|
+
/>
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
<BIMDataButton
|
|
35
|
+
width="100%"
|
|
36
|
+
color="primary"
|
|
37
|
+
fill
|
|
38
|
+
radius
|
|
39
|
+
@click="isOpenGroups = false, $emit('selection-change', topicGroups)"
|
|
40
|
+
>
|
|
41
|
+
{{ $t("BcfComponents.BcfTopicForm.validate") }}
|
|
42
|
+
</BIMDataButton>
|
|
43
|
+
</div>
|
|
44
|
+
</template>
|
|
45
|
+
|
|
46
|
+
<script setup>
|
|
47
|
+
import { computed, onMounted, ref } from "vue";
|
|
48
|
+
import service from "../../../service.js";
|
|
49
|
+
import GroupItem from "./GroupItem.vue";
|
|
50
|
+
|
|
51
|
+
const props = defineProps({
|
|
52
|
+
project: {
|
|
53
|
+
type: Object,
|
|
54
|
+
required: true,
|
|
55
|
+
},
|
|
56
|
+
groups: {
|
|
57
|
+
type: Array,
|
|
58
|
+
required: true,
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
defineEmits(["selection-change"]);
|
|
63
|
+
|
|
64
|
+
const isOpenGroups = ref(false);
|
|
65
|
+
const projectGroups = ref([]);
|
|
66
|
+
const selectedGroups = ref([]);
|
|
67
|
+
|
|
68
|
+
const topicGroups = computed(
|
|
69
|
+
() => selectedGroups.value.map(group => group.id)
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
const toggleGroup = group => {
|
|
73
|
+
const index = selectedGroups.value.findIndex(g => g.id === group.id);
|
|
74
|
+
if (index !== -1) {
|
|
75
|
+
selectedGroups.value.splice(index, 1);
|
|
76
|
+
} else {
|
|
77
|
+
selectedGroups.value.push(group);
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
onMounted(async () => {
|
|
82
|
+
projectGroups.value = await service.fetchProjectGroups(props.project);
|
|
83
|
+
selectedGroups.value = projectGroups.value.filter(group => props.groups.includes(group.id));
|
|
84
|
+
});
|
|
85
|
+
</script>
|
|
86
|
+
|
|
87
|
+
<style scoped>
|
|
88
|
+
.bcf-topic-groups {
|
|
89
|
+
position: relative;
|
|
90
|
+
height: 32px;
|
|
91
|
+
display: flex;
|
|
92
|
+
justify-content: space-between;
|
|
93
|
+
align-items: center;
|
|
94
|
+
cursor: pointer;
|
|
95
|
+
|
|
96
|
+
.label {
|
|
97
|
+
font-size: 12px;
|
|
98
|
+
color: var(--color-granite-light);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.underline {
|
|
102
|
+
position: absolute;
|
|
103
|
+
bottom: 0;
|
|
104
|
+
width: 100%;
|
|
105
|
+
height: 1px;
|
|
106
|
+
display: block;
|
|
107
|
+
background: var(--color-silver);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.bcf-topic-groups__selector {
|
|
112
|
+
position: absolute;
|
|
113
|
+
z-index: 2;
|
|
114
|
+
top: 0;
|
|
115
|
+
left: 0;
|
|
116
|
+
width: 100%;
|
|
117
|
+
height: 100%;
|
|
118
|
+
padding: var(--spacing-unit);
|
|
119
|
+
background-color: var(--color-white);
|
|
120
|
+
|
|
121
|
+
display: flex;
|
|
122
|
+
flex-direction: column;
|
|
123
|
+
align-items: flex-start;
|
|
124
|
+
gap: var(--spacing-unit);
|
|
125
|
+
|
|
126
|
+
.body {
|
|
127
|
+
flex: 1;
|
|
128
|
+
overflow: hidden;
|
|
129
|
+
display: flex;
|
|
130
|
+
flex-direction: column;
|
|
131
|
+
|
|
132
|
+
.text {
|
|
133
|
+
text-align: center;
|
|
134
|
+
color: var(--color-granite);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.list {
|
|
138
|
+
margin-top: var(--spacing-unit);
|
|
139
|
+
padding: var(--spacing-unit) 0;
|
|
140
|
+
flex: 1;
|
|
141
|
+
overflow: auto;
|
|
142
|
+
display: flex;
|
|
143
|
+
flex-direction: column;
|
|
144
|
+
gap: var(--spacing-unit);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
</style>
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="group-item">
|
|
3
|
+
<BIMDataCheckbox v-model="checked" />
|
|
4
|
+
<div class="card">
|
|
5
|
+
<div class="stripe" :style="{ backgroundColor: group.color }"></div>
|
|
6
|
+
<BIMDataIconGroup />
|
|
7
|
+
<BIMDataTextbox class="name" cut-position="end" :text="group.name" />
|
|
8
|
+
<UserAvatarList :users="group.members" />
|
|
9
|
+
</div>
|
|
10
|
+
</div>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script setup>
|
|
14
|
+
import { ref, watch } from "vue";
|
|
15
|
+
import UserAvatarList from "../../user-avatar/UserAvatarList.vue";
|
|
16
|
+
|
|
17
|
+
const props = defineProps({
|
|
18
|
+
group: {
|
|
19
|
+
type: Object,
|
|
20
|
+
required: true,
|
|
21
|
+
},
|
|
22
|
+
selected: {
|
|
23
|
+
type: Boolean,
|
|
24
|
+
default: false,
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const emit = defineEmits(["toggle"]);
|
|
29
|
+
|
|
30
|
+
const checked = ref(props.selected);
|
|
31
|
+
|
|
32
|
+
watch(checked, () => emit("toggle", props.group));
|
|
33
|
+
</script>
|
|
34
|
+
|
|
35
|
+
<style scoped>
|
|
36
|
+
.group-item {
|
|
37
|
+
min-height: 50px;
|
|
38
|
+
padding-right: 6px;
|
|
39
|
+
|
|
40
|
+
display: flex;
|
|
41
|
+
justify-content: space-between;
|
|
42
|
+
align-items: center;
|
|
43
|
+
gap: var(--spacing-unit);
|
|
44
|
+
|
|
45
|
+
.card {
|
|
46
|
+
position: relative;
|
|
47
|
+
height: 100%;
|
|
48
|
+
flex: 1;
|
|
49
|
+
padding: var(--spacing-unit) calc(var(--spacing-unit) * 2);
|
|
50
|
+
box-shadow: var(--box-shadow);
|
|
51
|
+
|
|
52
|
+
display: flex;
|
|
53
|
+
align-items: center;
|
|
54
|
+
gap: var(--spacing-unit);
|
|
55
|
+
|
|
56
|
+
.stripe {
|
|
57
|
+
position: absolute;
|
|
58
|
+
top: 0;
|
|
59
|
+
left: 0;
|
|
60
|
+
height: 100%;
|
|
61
|
+
width: 6px;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.name {
|
|
65
|
+
width: 0 !important;
|
|
66
|
+
flex: 1;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
</style>
|
|
@@ -58,4 +58,35 @@ export default {
|
|
|
58
58
|
};
|
|
59
59
|
</script>
|
|
60
60
|
|
|
61
|
-
<style scoped
|
|
61
|
+
<style scoped>
|
|
62
|
+
.user-avatar {
|
|
63
|
+
min-width: 32px;
|
|
64
|
+
min-height: 32px;
|
|
65
|
+
|
|
66
|
+
display: flex;
|
|
67
|
+
justify-content: center;
|
|
68
|
+
align-items: center;
|
|
69
|
+
border-radius: 50%;
|
|
70
|
+
overflow: hidden;
|
|
71
|
+
|
|
72
|
+
img {
|
|
73
|
+
width: 100%;
|
|
74
|
+
height: 100%;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
&.user-avatar--primary {
|
|
78
|
+
background-color: var(--color-primary);
|
|
79
|
+
color: var(--color-silver-light);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
&.user-avatar--secondary {
|
|
83
|
+
background-color: var(--color-secondary);
|
|
84
|
+
color: var(--color-primary);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
&.user-avatar--silver-light {
|
|
88
|
+
background-color: var(--color-silver-light);
|
|
89
|
+
color: var(--color-primary);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
</style>
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
class="user-avatar-list"
|
|
4
|
+
:style="{
|
|
5
|
+
width: `${listWidth}px`,
|
|
6
|
+
gridTemplateColumns: `repeat(${listLength}, ${itemGap}px)`
|
|
7
|
+
}"
|
|
8
|
+
>
|
|
9
|
+
<UserAvatar
|
|
10
|
+
class="user-avatar-list__item"
|
|
11
|
+
v-for="user of displayedUsers"
|
|
12
|
+
:key="user.id"
|
|
13
|
+
:user="user"
|
|
14
|
+
:size="itemSize"
|
|
15
|
+
/>
|
|
16
|
+
<template v-if="users.length > length">
|
|
17
|
+
<div
|
|
18
|
+
class="user-avatar-list__tail-item"
|
|
19
|
+
:style="{ width: `${itemSize}px`, height: `${itemSize}px` }"
|
|
20
|
+
>
|
|
21
|
+
{{ `+ ${users.length - length + 1}` }}
|
|
22
|
+
</div>
|
|
23
|
+
</template>
|
|
24
|
+
</div>
|
|
25
|
+
</template>
|
|
26
|
+
|
|
27
|
+
<script>
|
|
28
|
+
import { computed } from "vue";
|
|
29
|
+
// Components
|
|
30
|
+
import UserAvatar from "./UserAvatar.vue";
|
|
31
|
+
|
|
32
|
+
export default {
|
|
33
|
+
components: {
|
|
34
|
+
UserAvatar
|
|
35
|
+
},
|
|
36
|
+
props: {
|
|
37
|
+
users: {
|
|
38
|
+
type: Array,
|
|
39
|
+
required: true
|
|
40
|
+
},
|
|
41
|
+
length: {
|
|
42
|
+
type: Number,
|
|
43
|
+
default: 4
|
|
44
|
+
},
|
|
45
|
+
itemSize: {
|
|
46
|
+
type: [Number, String],
|
|
47
|
+
default: 32,
|
|
48
|
+
validate: value => value >= 32
|
|
49
|
+
},
|
|
50
|
+
itemGap: {
|
|
51
|
+
type: [Number, String],
|
|
52
|
+
default: 24,
|
|
53
|
+
validate: value => value > 0
|
|
54
|
+
},
|
|
55
|
+
fixedWidth: {
|
|
56
|
+
type: Boolean,
|
|
57
|
+
default: false
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
setup(props) {
|
|
61
|
+
const displayedUsers = computed(() => {
|
|
62
|
+
const n = props.users.length;
|
|
63
|
+
const l = props.length;
|
|
64
|
+
return props.users.slice(0, n > l ? l - 1 : l);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
const listLength = computed(() => {
|
|
68
|
+
const n = props.users.length;
|
|
69
|
+
const l = props.length;
|
|
70
|
+
return props.fixedWidth || n > l ? l : n;
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
const listWidth = computed(() => {
|
|
74
|
+
const l = listLength.value;
|
|
75
|
+
const w = +props.itemSize;
|
|
76
|
+
const g = +props.itemGap;
|
|
77
|
+
return l * g + (w > g ? w - g : 0);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
// References
|
|
82
|
+
displayedUsers,
|
|
83
|
+
listLength,
|
|
84
|
+
listWidth
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
</script>
|
|
89
|
+
|
|
90
|
+
<style scoped>
|
|
91
|
+
.user-avatar-list {
|
|
92
|
+
display: grid;
|
|
93
|
+
|
|
94
|
+
.user-avatar-list__item {
|
|
95
|
+
border: 1px solid var(--color-white);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.user-avatar-list__tail-item {
|
|
99
|
+
min-width: 32px;
|
|
100
|
+
min-height: 32px;
|
|
101
|
+
|
|
102
|
+
display: flex;
|
|
103
|
+
justify-content: center;
|
|
104
|
+
align-items: center;
|
|
105
|
+
border: 1px solid var(--color-white);
|
|
106
|
+
border-radius: 50%;
|
|
107
|
+
font-weight: bold;
|
|
108
|
+
background-color: var(--color-primary);
|
|
109
|
+
color: var(--color-silver-light);
|
|
110
|
+
z-index: 1;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
</style>
|
package/src/i18n/lang/en.json
CHANGED
|
@@ -73,7 +73,10 @@
|
|
|
73
73
|
"emptySearch": "No result",
|
|
74
74
|
"documentsLabel": "Add a file",
|
|
75
75
|
"documentsCount": "Files - {count} selected files",
|
|
76
|
-
"
|
|
76
|
+
"groupsLabel": "Permissions",
|
|
77
|
+
"groupsCount": "Permissions - {count} selected groups",
|
|
78
|
+
"groupsText": "You are now setting the access rights: choose the user group(s) that will be exclusively authorized to see and interact with this topic.",
|
|
79
|
+
"validate": "Validate"
|
|
77
80
|
},
|
|
78
81
|
"BcfTopicOverview": {
|
|
79
82
|
"openViewer": "Open in viewer",
|
package/src/i18n/lang/fr.json
CHANGED
|
@@ -73,7 +73,10 @@
|
|
|
73
73
|
"emptySearch": "Pas de résultat",
|
|
74
74
|
"documentsLabel": "Documents",
|
|
75
75
|
"documentsCount": "Documents - {count} documents sélectionnés",
|
|
76
|
-
"
|
|
76
|
+
"groupsLabel": "Permissions",
|
|
77
|
+
"groupsCount": "Permissions - {count} groupes sélectionnés",
|
|
78
|
+
"groupsText": "Sélectionner les groupes utilisateur qui peuvent voir ce topic et intéragir avec.",
|
|
79
|
+
"validate": "Valider"
|
|
77
80
|
},
|
|
78
81
|
"BcfTopicOverview": {
|
|
79
82
|
"openViewer": "Ouvrir dans le viewer",
|
package/src/service.js
CHANGED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
.user-avatar {
|
|
2
|
-
min-width: 32px;
|
|
3
|
-
min-height: 32px;
|
|
4
|
-
|
|
5
|
-
display: flex;
|
|
6
|
-
justify-content: center;
|
|
7
|
-
align-items: center;
|
|
8
|
-
border-radius: 50%;
|
|
9
|
-
overflow: hidden;
|
|
10
|
-
|
|
11
|
-
img {
|
|
12
|
-
width: 100%;
|
|
13
|
-
height: 100%;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
&--primary {
|
|
17
|
-
background-color: var(--color-primary);
|
|
18
|
-
color: var(--color-silver-light);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
&--secondary {
|
|
22
|
-
background-color: var(--color-secondary);
|
|
23
|
-
color: var(--color-primary);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
&--silver-light {
|
|
27
|
-
background-color: var(--color-silver-light);
|
|
28
|
-
color: var(--color-primary);
|
|
29
|
-
}
|
|
30
|
-
}
|