@bimdata/bcf-components 6.0.0-rc.9 → 6.0.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.
Files changed (65) hide show
  1. package/README.md +0 -6
  2. package/package.json +15 -20
  3. package/src/components/bcf-filters/BcfFilters.scss +67 -0
  4. package/src/components/bcf-filters/BcfFilters.vue +228 -0
  5. package/src/components/bcf-settings/BcfSettings.scss +28 -0
  6. package/src/components/bcf-settings/BcfSettings.vue +117 -0
  7. package/src/components/bcf-settings/setting-card/SettingCard.scss +59 -0
  8. package/src/components/bcf-settings/setting-card/SettingCard.vue +140 -0
  9. package/src/components/bcf-settings/setting-card/SettingCardItem.scss +48 -0
  10. package/src/components/bcf-settings/setting-card/SettingCardItem.vue +151 -0
  11. package/src/components/bcf-statistics/BcfStatistics.scss +56 -0
  12. package/src/components/bcf-statistics/BcfStatistics.vue +112 -0
  13. package/src/components/bcf-topic-card/BcfTopicCard.scss +96 -0
  14. package/src/components/bcf-topic-card/BcfTopicCard.vue +150 -0
  15. package/src/components/bcf-topic-card/BcfTopicDefaultImage.vue +90 -0
  16. package/src/components/bcf-topic-creation-card/BcfTopicCreationCard.scss +15 -0
  17. package/src/components/bcf-topic-creation-card/BcfTopicCreationCard.vue +37 -0
  18. package/src/components/bcf-topic-creation-card/BcfTopicCreationCardImage.vue +55 -0
  19. package/src/components/bcf-topic-form/BcfTopicForm.scss +124 -0
  20. package/src/components/bcf-topic-form/BcfTopicForm.vue +541 -0
  21. package/src/components/bcf-topic-form/bcf-topic-images/BcfTopicImages.scss +88 -0
  22. package/src/components/bcf-topic-form/bcf-topic-images/BcfTopicImages.vue +101 -0
  23. package/src/components/bcf-topic-form/bcf-topic-snapshots/BcfTopicSnapshots.scss +50 -0
  24. package/src/components/bcf-topic-form/bcf-topic-snapshots/BcfTopicSnapshots.vue +71 -0
  25. package/src/components/bcf-topic-form/bcf-topic-snapshots-actions/BcfTopicSnapshotsActions.scss +9 -0
  26. package/src/components/bcf-topic-form/bcf-topic-snapshots-actions/BcfTopicSnapshotsActions.vue +69 -0
  27. package/src/components/bcf-topic-overview/BcfTopicOverview.scss +94 -0
  28. package/src/components/bcf-topic-overview/BcfTopicOverview.vue +350 -0
  29. package/src/components/bcf-topic-overview/bcf-topic-comments/BcfTopicComments.scss +39 -0
  30. package/src/components/bcf-topic-overview/bcf-topic-comments/BcfTopicComments.vue +268 -0
  31. package/src/components/bcf-topic-overview/bcf-topic-comments/topic-comment/TopicComment.scss +79 -0
  32. package/src/components/bcf-topic-overview/bcf-topic-comments/topic-comment/TopicComment.vue +357 -0
  33. package/src/components/bcf-topic-overview/bcf-topic-viewpoints/BcfTopicViewpoints.scss +73 -0
  34. package/src/components/bcf-topic-overview/bcf-topic-viewpoints/BcfTopicViewpoints.vue +84 -0
  35. package/src/components/bcf-topics-table/BcfTopicsTable.vue +148 -0
  36. package/src/components/bcf-topics-table/bcf-topic-actions-cell/BcfTopicActionsCell.vue +43 -0
  37. package/src/components/bcf-topics-table/bcf-topic-index-cell/BcfTopicIndexCell.vue +55 -0
  38. package/src/components/bcf-topics-table/bcf-topic-priority-cell/BcfTopicPriorityCell.vue +47 -0
  39. package/src/components/bcf-topics-table/bcf-topic-status-cell/BcfTopicStatusCell.vue +52 -0
  40. package/src/components/bcf-topics-table/columns.js +38 -0
  41. package/src/components/user-avatar/UserAvatar.scss +30 -0
  42. package/src/components/user-avatar/UserAvatar.vue +66 -0
  43. package/src/composables/filter.js +58 -0
  44. package/src/composables/search.js +42 -0
  45. package/src/composables/sort.js +64 -0
  46. package/src/config.js +87 -0
  47. package/{dist → src}/i18n/lang/en.json +3 -1
  48. package/{dist → src}/i18n/lang/fr.json +5 -1
  49. package/src/index.js +59 -0
  50. package/src/service.js +206 -0
  51. package/src/utils/browser.js +12 -0
  52. package/src/utils/download.js +15 -0
  53. package/src/utils/extensions.js +14 -0
  54. package/src/utils/topic.js +23 -0
  55. package/src/utils/viewer.js +21 -0
  56. package/src/utils/viewpoints.js +28 -0
  57. package/vue3-plugin.js +4 -5
  58. package/dist/bcf-components.mjs +0 -10311
  59. package/dist/style.css +0 -1
  60. /package/{dist → src}/i18n/index.js +0 -0
  61. /package/{dist → src}/i18n/lang/de.json +0 -0
  62. /package/{dist → src}/i18n/lang/es.json +0 -0
  63. /package/{dist → src}/i18n/lang/it.json +0 -0
  64. /package/{dist → src}/i18n/lang/nl.json +0 -0
  65. /package/{dist → src}/i18n/lang/no.json +0 -0
@@ -0,0 +1,350 @@
1
+ <template>
2
+ <div class="bcf-topic-overview">
3
+ <div class="bcf-topic-overview__header">
4
+ <BIMDataButton
5
+ v-if="uiConfig.backButton"
6
+ ghost rounded icon
7
+ @click="$emit('back')"
8
+ >
9
+ <BIMDataIconArrow size="xxs" fill color="granite-light" />
10
+ </BIMDataButton>
11
+ <div class="bcf-topic-overview__header__title">
12
+ <BIMDataTextbox maxWidth="250px" :text="topic.title" />
13
+ </div>
14
+ <div class="bcf-topic-overview__header__actions">
15
+ <BIMDataButton
16
+ v-if="uiConfig.editButton"
17
+ ghost rounded icon
18
+ @click="$emit('edit-topic', topic)"
19
+ >
20
+ <BIMDataIconEdit size="xxs" />
21
+ </BIMDataButton>
22
+ <BIMDataButton
23
+ v-if="uiConfig.deleteButton"
24
+ ghost rounded icon
25
+ @click="showDeleteModal = true"
26
+ >
27
+ <BIMDataIconDelete size="xxs" />
28
+ </BIMDataButton>
29
+ <BIMDataButton
30
+ v-if="uiConfig.closeButton"
31
+ ghost rounded icon
32
+ @click="$emit('close')"
33
+ >
34
+ <BIMDataIconClose size="xxs" fill color="granite-light" />
35
+ </BIMDataButton>
36
+ </div>
37
+ </div>
38
+
39
+ <div class="bcf-topic-overview__content">
40
+ <div class="bcf-topic-overview__content__head">
41
+ <div
42
+ class="bcf-topic-overview__content__head__index"
43
+ :style="{
44
+ backgroundColor: `#${priorityColor}`,
45
+ color: adjustTextColor(`#${priorityColor}`, '#FFF', '#2F374A'),
46
+ }"
47
+ >
48
+ {{ topic.index }}
49
+ </div>
50
+ <div class="bcf-topic-overview__content__head__date">
51
+ {{ $d(topic.creation_date, "short") }}
52
+ </div>
53
+ </div>
54
+
55
+ <BcfTopicViewpoints
56
+ :detailedExtensions="detailedExtensions"
57
+ :topic="topic"
58
+ @view-topic-viewpoint="$emit('view-topic-viewpoint', $event)"
59
+ />
60
+
61
+ <BIMDataButton
62
+ v-if="uiConfig.viewerMode"
63
+ width="100%"
64
+ fill
65
+ radius
66
+ :disabled="topicObjects.length === 0"
67
+ @click="$emit('view-topic-components', topic)"
68
+ >
69
+ <BIMDataIconModel3D size="xs" margin="0 6px 0 0" />
70
+ <template v-if="topicObjects.length > 0">
71
+ {{ $t("BcfComponents.BcfTopicOverview.elements", { count: topicObjects.length }) }}
72
+ </template>
73
+ <template v-else>
74
+ {{ $t("BcfComponents.BcfTopicOverview.noElements") }}
75
+ </template>
76
+ </BIMDataButton>
77
+
78
+ <BIMDataButton
79
+ v-else
80
+ width="100%"
81
+ color="primary"
82
+ fill
83
+ radius
84
+ @click="$emit('view-topic', topic)"
85
+ >
86
+ {{ $t("BcfComponents.BcfTopicOverview.openViewer") }}
87
+ </BIMDataButton>
88
+
89
+ <div class="bcf-topic-overview__content__card">
90
+ <div class="title" v-if="!uiConfig.viewerMode">
91
+ <BIMDataIconModel3D size="xs" />
92
+ <span>
93
+ {{ $t("BcfComponents.BcfTopicOverview.elements", { count: topicObjects.length }) }}
94
+ </span>
95
+ </div>
96
+ <div class="line">
97
+ <span class="label">
98
+ {{ $t("BcfComponents.BcfTopicOverview.type") }}
99
+ </span>
100
+ <span class="value">
101
+ {{
102
+ topic.topic_type
103
+ ? topic.topic_type
104
+ : $t("BcfComponents.BcfTopicOverview.noTypeSpecified")
105
+ }}
106
+ </span>
107
+ </div>
108
+ <div class="line">
109
+ <span class="label">
110
+ {{ $t("BcfComponents.BcfTopicOverview.description") }}
111
+ </span>
112
+ <span class="value" style="white-space: pre-line">
113
+ {{
114
+ topic.description
115
+ ? topic.description
116
+ : $t("BcfComponents.BcfTopicOverview.noDescriptionProvided")
117
+ }}
118
+ </span>
119
+ </div>
120
+ <div class="line">
121
+ <span class="label">
122
+ {{ $t("BcfComponents.BcfTopicOverview.assignedTo") }}
123
+ </span>
124
+ <span class="value">
125
+ {{
126
+ topic.assigned_to
127
+ ? topic.assigned_to
128
+ : $t("BcfComponents.BcfTopicOverview.notAssigned")
129
+ }}
130
+ </span>
131
+ </div>
132
+ <div class="line">
133
+ <span class="label">
134
+ {{ $t("BcfComponents.BcfTopicOverview.dueDate") }}
135
+ </span>
136
+ <span class="value">
137
+ {{
138
+ topic.due_date
139
+ ? $d(topic.due_date, "short")
140
+ : $t("BcfComponents.BcfTopicOverview.noDueDate")
141
+ }}
142
+ </span>
143
+ </div>
144
+ </div>
145
+
146
+ <div class="bcf-topic-overview__content__card">
147
+ <div class="title">
148
+ <BIMDataIconBcf />
149
+ <span>
150
+ {{ $t("BcfComponents.BcfTopicOverview.informations") }}
151
+ </span>
152
+ </div>
153
+ <div class="line">
154
+ <span class="label">
155
+ {{ $t("BcfComponents.BcfTopicOverview.status") }}
156
+ </span>
157
+ <span class="value">
158
+ {{ topic.topic_status || $t("BcfComponents.BcfTopicOverview.noStatusSpecified") }}
159
+ </span>
160
+ </div>
161
+ <div class="line">
162
+ <span class="label">
163
+ {{ $t("BcfComponents.BcfTopicOverview.stage") }}
164
+ </span>
165
+ <span class="value">
166
+ {{ topic.stage || $t("BcfComponents.BcfTopicOverview.noStageProvided") }}
167
+ </span>
168
+ </div>
169
+ <div class="line">
170
+ <span class="label">
171
+ {{ $t("BcfComponents.BcfTopicOverview.priority") }}
172
+ </span>
173
+ <span class="value" :style="{ color: `#${priorityColor}` }">
174
+ {{ topic.priority || $t("BcfComponents.BcfTopicOverview.priorityNotDefined") }}
175
+ </span>
176
+ </div>
177
+ <div class="line">
178
+ <span class="label">
179
+ {{ $t("BcfComponents.BcfTopicOverview.author") }}
180
+ </span>
181
+ <span class="value">
182
+ {{ topic.creation_author }}
183
+ </span>
184
+ </div>
185
+ <div class="line m-t-12">
186
+ <span class="label">
187
+ {{ $t("BcfComponents.BcfTopicOverview.tags") }}
188
+ </span>
189
+ <span class="value">
190
+ {{
191
+ topicLabels.length
192
+ ? topicLabels.join(", ")
193
+ : $t("BcfComponents.BcfTopicOverview.noTags")
194
+ }}
195
+ </span>
196
+ </div>
197
+ </div>
198
+
199
+ <BcfTopicComments
200
+ :uiConfig="uiConfig"
201
+ :project="project"
202
+ :topic="topic"
203
+ :currentUserEmail="currentUserEmail"
204
+ :getViewers="getViewers"
205
+ @comment-created="$emit('comment-created', $event)"
206
+ @comment-updated="$emit('comment-updated', $event)"
207
+ @comment-deleted="$emit('comment-deleted', $event)"
208
+ @view-comment-snapshot="$emit('view-comment-snapshot',$event)"
209
+ />
210
+ </div>
211
+
212
+ <BIMDataSafeZoneModal v-if="showDeleteModal" class="delete-modal">
213
+ <template #text>
214
+ {{ $t("BcfComponents.BcfTopicOverview.deleteText", { name: topic.title }) }}
215
+ </template>
216
+ <template #actions>
217
+ <BIMDataButton class="m-r-12" color="high" fill radius @click="deleteTopic">
218
+ {{ $t("BcfComponents.BcfTopicOverview.deleteBcfButton") }}
219
+ </BIMDataButton>
220
+ <BIMDataButton color="primary" outline radius @click="showDeleteModal = false">
221
+ {{ $t("BcfComponents.BcfTopicOverview.keepBcfButton") }}
222
+ </BIMDataButton>
223
+ </template>
224
+ </BIMDataSafeZoneModal>
225
+
226
+ <div v-if="loading">
227
+ <BIMDataLoading />
228
+ </div>
229
+ </div>
230
+ </template>
231
+
232
+ <script>
233
+ import { adjustTextColor } from "@bimdata/design-system/src/BIMDataComponents/BIMDataColorSelector/colors.js";
234
+ import { computed, onMounted, ref } from "vue";
235
+ import { useService } from "../../service.js";
236
+ import { getPriorityColor } from "../../utils/topic.js";
237
+ // Components
238
+ import BIMDataSafeZoneModal from "@bimdata/components/src/BIMDataSafeZoneModal/BIMDataSafeZoneModal.vue";
239
+ import BIMDataButton from "@bimdata/design-system/src/BIMDataComponents/BIMDataButton/BIMDataButton.vue";
240
+ import {BIMDataIconArrow,BIMDataIconEdit, BIMDataIconDelete, BIMDataIconClose, BIMDataIconModel3D } from "@bimdata/design-system/src/BIMDataComponents/BIMDataIcon/BIMDataIconStandalone/index.js";
241
+ import BIMDataLoading from "@bimdata/design-system/src/BIMDataComponents/BIMDataLoading/BIMDataLoading.vue";
242
+ import BIMDataTextbox from "@bimdata/design-system/src/BIMDataComponents/BIMDataTextbox/BIMDataTextbox.vue";
243
+ import BcfTopicComments from "./bcf-topic-comments/BcfTopicComments.vue";
244
+ import BcfTopicDefaultImage from "../bcf-topic-card/BcfTopicDefaultImage.vue";
245
+ import BcfTopicViewpoints from "./bcf-topic-viewpoints/BcfTopicViewpoints.vue";
246
+
247
+ export default {
248
+ components: {
249
+ BcfTopicComments,
250
+ BcfTopicDefaultImage,
251
+ BcfTopicViewpoints,
252
+ BIMDataButton,
253
+ BIMDataIconArrow,BIMDataIconEdit, BIMDataIconDelete, BIMDataIconClose, BIMDataIconModel3D,
254
+ BIMDataLoading,
255
+ BIMDataSafeZoneModal,
256
+ BIMDataTextbox,
257
+ },
258
+ props: {
259
+ uiConfig: {
260
+ type: Object,
261
+ default: () => ({
262
+ viewerMode: false,
263
+ backButton: false,
264
+ closeButton: false,
265
+ editButton: false,
266
+ deleteButton: false,
267
+ commentCreation: false,
268
+ }),
269
+ },
270
+ project: {
271
+ type: Object,
272
+ required: true,
273
+ },
274
+ detailedExtensions: {
275
+ type: Object,
276
+ required: true,
277
+ },
278
+ topic: {
279
+ type: Object,
280
+ required: true,
281
+ },
282
+ getViewers: {
283
+ type: Function,
284
+ default: () => () => ({})
285
+ },
286
+ },
287
+ emits: [
288
+ "back",
289
+ "close",
290
+ "comment-created",
291
+ "comment-deleted",
292
+ "comment-updated",
293
+ "edit-topic",
294
+ "topic-deleted",
295
+ "topic-delete-error",
296
+ "view-comment-snapshot",
297
+ "view-topic",
298
+ "view-topic-components",
299
+ "view-topic-viewpoint",
300
+ ],
301
+ setup(props, { emit }) {
302
+ const service = useService();
303
+
304
+ const loading = ref(false);
305
+ const showDeleteModal = ref(false);
306
+
307
+ const priorityColor = computed(() => getPriorityColor(props.topic, props.detailedExtensions));
308
+
309
+ const topicObjects = computed(() => props.topic.viewpoints?.[0]?.components?.selection ?? []);
310
+
311
+ const topicLabels = computed(() => Array.from(props.topic.labels ?? []).sort());
312
+
313
+ const currentUserEmail = ref("");
314
+ const loadCurrentUserEmail = async () => {
315
+ currentUserEmail.value = (await service.fetchCurrentUser()).email ?? "";
316
+ };
317
+
318
+ const deleteTopic = async () => {
319
+ try {
320
+ showDeleteModal.value = false;
321
+ loading.value = true;
322
+ await service.deleteTopic(props.project, props.topic);
323
+ emit("topic-deleted", props.topic);
324
+ } catch (error) {
325
+ console.error(error);
326
+ emit("topic-delete-error", error);
327
+ } finally {
328
+ loading.value = false;
329
+ }
330
+ };
331
+
332
+ onMounted(() => loadCurrentUserEmail())
333
+
334
+ return {
335
+ // References
336
+ currentUserEmail,
337
+ loading,
338
+ priorityColor,
339
+ showDeleteModal,
340
+ topicLabels,
341
+ topicObjects,
342
+ // Methods
343
+ adjustTextColor,
344
+ deleteTopic,
345
+ };
346
+ },
347
+ };
348
+ </script>
349
+
350
+ <style scoped lang="scss" src="./BcfTopicOverview.scss"></style>
@@ -0,0 +1,39 @@
1
+ .bcf-topic-comments {
2
+ p {
3
+ font-weight: 700;
4
+ }
5
+
6
+ &__post-comment {
7
+ &__snapshot {
8
+ height: 200px;
9
+ position: relative;
10
+ background-color: var(--color-silver-light);
11
+
12
+ img {
13
+ width: 100%;
14
+ height: 100%;
15
+ object-fit: contain;
16
+ }
17
+
18
+ .btn-delete {
19
+ position: absolute;
20
+ top: calc(50% - (32px / 2));
21
+ left: calc(50% - (32px / 2));
22
+ }
23
+ }
24
+ &__camera {
25
+ cursor: pointer;
26
+ }
27
+ }
28
+
29
+ :deep(.submenu--down li) {
30
+ padding: 0;
31
+ }
32
+ :deep(.submenu--down li > div) {
33
+ padding: calc(var(--spacing-unit) / 2);
34
+ }
35
+
36
+ :deep(.bimdata-textarea) {
37
+ width: 100%;
38
+ }
39
+ }
@@ -0,0 +1,268 @@
1
+ <template>
2
+ <div class="bcf-topic-comments">
3
+ <template v-if="uiConfig.commentCreation">
4
+ <BIMDataButton v-if="!isOpen" width="100%" color="primary" fill radius @click="isOpen = true">
5
+ {{ $t("BcfComponents.BcfTopicComments.commentButton") }}
6
+ </BIMDataButton>
7
+
8
+ <div v-else class="bcf-topic-comments__post-comment m-t-24">
9
+ <p class="color-granite m-b-24">
10
+ {{ $t("BcfComponents.BcfTopicComments.commentText") }}
11
+ </p>
12
+ <div class="bcf-comment-input m-t-24">
13
+ <BIMDataTextarea
14
+ ref="input"
15
+ width="100%"
16
+ :label="$t('BcfComponents.BcfTopicComments.commentLabel')"
17
+ v-model="text"
18
+ autofocus
19
+ resizable
20
+ />
21
+ <div class="bcf-topic-comments__post-comment__snapshot m-b-12" v-if="viewpoint">
22
+ <img v-if="viewpoint.snapshot.snapshot_data" :src="viewpoint.snapshot.snapshot_data" />
23
+ <BIMDataButton class="btn-delete" fill rounded icon @click="deleteViewpoint">
24
+ <BIMDataIconDelete size="xs" fill color="high" />
25
+ </BIMDataButton>
26
+ </div>
27
+ <div class="flex items-center justify-between">
28
+ <div class="flex items-center">
29
+ <div
30
+ class="bcf-topic-comments__post-comment__camera m-r-12"
31
+ @click="setCommentViewpoint"
32
+ v-if="!viewerSelectVisible && isViewer"
33
+ >
34
+ <BIMDataIconCamera fill color="default" />
35
+ </div>
36
+ <BIMDataDropdownList
37
+ v-if="viewerSelectVisible && isViewer"
38
+ :list="viewerSelectOptions"
39
+ elementKey="key"
40
+ @element-click="createViewpoint"
41
+ width="180px"
42
+ >
43
+ <template #header>{{ $t("BcfComponents.BcfTopicComments.takeSnapshot") }}</template>
44
+ <template #element="{ element }">
45
+ <div
46
+ style="width: 100%"
47
+ @mouseenter="highlightViewer(element.viewer)"
48
+ @mouseleave="unhighlightViewer(element.viewer)"
49
+ >
50
+ {{ `${element.id} (${element.index})` }}
51
+ </div>
52
+ </template>
53
+ </BIMDataDropdownList>
54
+ </div>
55
+ <div class="flex items-center justify-end">
56
+ <BIMDataButton color="primary" ghost radius class="m-r-6" @click="isOpen = false">
57
+ {{ $t("BcfComponents.BcfTopicComments.cancelButton") }}
58
+ </BIMDataButton>
59
+ <BIMDataButton color="primary" fill radius width="135px" @click="submitComment">
60
+ {{ $t("BcfComponents.BcfTopicComments.publishButton") }}
61
+ </BIMDataButton>
62
+ </div>
63
+ </div>
64
+ </div>
65
+ </div>
66
+ </template>
67
+ <div class="bcf-topic-comments__list m-t-18">
68
+ <p class="color-granite">
69
+ {{
70
+ (comments ? comments.length : 0) + " " + $t("BcfComponents.BcfTopicComments.commentsText")
71
+ }}
72
+ </p>
73
+ <div v-if="comments && comments.length">
74
+ <TopicComment
75
+ v-for="comment in comments"
76
+ :key="comment.guid"
77
+ :project="project"
78
+ :topic="topic"
79
+ :comment="comment"
80
+ :currentUserEmail="currentUserEmail"
81
+ :get-viewers="getViewers"
82
+ @comment-updated="onCommentUpdated"
83
+ @comment-deleted="onCommentDeleted"
84
+ @view-comment-snapshot="$emit('view-comment-snapshot', $event)"
85
+ />
86
+ </div>
87
+ </div>
88
+
89
+ <template v-if="loading">
90
+ <BIMDataLoading />
91
+ </template>
92
+ </div>
93
+ </template>
94
+
95
+ <script>
96
+ import { onMounted, inject, ref, watch, onBeforeUnmount } from "vue";
97
+ import { useService } from "../../../service.js";
98
+ import { getViewerOptions, highlightViewer, unhighlightViewer } from "../../../utils/viewer.js";
99
+
100
+ // Components
101
+ import BIMDataButton from "@bimdata/design-system/src/BIMDataComponents/BIMDataButton/BIMDataButton.vue";
102
+ import BIMDataDropdownList from "@bimdata/design-system/src/BIMDataComponents/BIMDataDropdownList/BIMDataDropdownList.vue";
103
+ import {
104
+ BIMDataIconCamera,
105
+ BIMDataIconDelete,
106
+ } from "@bimdata/design-system/src/BIMDataComponents/BIMDataIcon/BIMDataIconStandalone/index.js";
107
+ import BIMDataLoading from "@bimdata/design-system/src/BIMDataComponents/BIMDataLoading/BIMDataLoading.vue";
108
+ import BIMDataTextarea from "@bimdata/design-system/src/BIMDataComponents/BIMDataTextarea/BIMDataTextarea.vue";
109
+ import TopicComment from "./topic-comment/TopicComment.vue";
110
+
111
+ export default {
112
+ components: {
113
+ BIMDataButton,
114
+ BIMDataDropdownList,
115
+ BIMDataIconCamera,
116
+ BIMDataIconDelete,
117
+ BIMDataLoading,
118
+ BIMDataTextarea,
119
+ TopicComment,
120
+ },
121
+ props: {
122
+ project: {
123
+ type: Object,
124
+ required: true,
125
+ },
126
+ topic: {
127
+ type: Object,
128
+ required: true,
129
+ },
130
+ uiConfig: {
131
+ type: Object,
132
+ required: true,
133
+ },
134
+ currentUserEmail: {
135
+ type: String,
136
+ required: true,
137
+ },
138
+ getViewers: {
139
+ type: Function,
140
+ required: true,
141
+ },
142
+ },
143
+ emis: ["comment-created", "comment-updated", "comment-deleted", "view-comment-snapshot"],
144
+ setup(props, { emit }) {
145
+ let pluginCreatedSub, pluginDestroyedSub;
146
+
147
+ const service = useService();
148
+ const $viewer = inject("$viewer", null);
149
+
150
+ const loading = ref(false);
151
+ const isOpen = ref(false);
152
+ const input = ref(null);
153
+ const comments = ref([]);
154
+ const text = ref("");
155
+ const viewpoint = ref(null);
156
+ const viewerSelectVisible = ref(false);
157
+ const viewerSelectOptions = ref([]);
158
+
159
+ const loadComments = async () => {
160
+ comments.value = await service.fetchTopicComments(props.project, props.topic);
161
+ };
162
+
163
+ const setCommentViewpoint = async () => {
164
+ if (viewerSelectOptions.value.length === 1) {
165
+ await createViewpoint(viewerSelectOptions.value[0]);
166
+ } else if (viewerSelectOptions.value.length > 1) {
167
+ viewerSelectVisible.value = true;
168
+ }
169
+ };
170
+
171
+ const createViewpoint = async ({ viewer }) => {
172
+ unhighlightViewer(viewer);
173
+ viewerSelectVisible.value = false;
174
+ viewpoint.value = await viewer.getViewpoint();
175
+ };
176
+
177
+ const deleteViewpoint = () => {
178
+ viewpoint.value = null;
179
+ };
180
+
181
+ const submitComment = async () => {
182
+ try {
183
+ loading.value = true;
184
+ if (viewpoint.value) {
185
+ viewpoint.value = await service.createViewpoint(
186
+ props.project,
187
+ props.topic,
188
+ viewpoint.value
189
+ );
190
+ }
191
+ const comment = await service.createComment(props.project, props.topic, {
192
+ comment: text.value,
193
+ viewpoint_guid: viewpoint.value?.guid,
194
+ });
195
+ loadComments();
196
+ emit("comment-created", comment);
197
+ isOpen.value = false;
198
+ text.value = "";
199
+ } finally {
200
+ loading.value = false;
201
+ viewpoint.value = null;
202
+ }
203
+ };
204
+
205
+ const onCommentUpdated = (comment) => {
206
+ loadComments();
207
+ emit("comment-updated", comment);
208
+ };
209
+
210
+ const onCommentDeleted = (comment) => {
211
+ loadComments();
212
+ emit("comment-deleted", comment);
213
+ };
214
+
215
+ watch(
216
+ () => props.topic,
217
+ () => loadComments(),
218
+ { immediate: true }
219
+ );
220
+
221
+ watch(isOpen, () => setTimeout(() => isOpen.value && input.value.focus(), 50));
222
+
223
+ onMounted(() => {
224
+ if ($viewer) {
225
+ viewerSelectOptions.value = getViewerOptions(props.getViewers());
226
+ pluginCreatedSub = $viewer.globalContext.hub.on("plugin-created", () => {
227
+ viewerSelectOptions.value = getViewerOptions(props.getViewers());
228
+ });
229
+ pluginDestroyedSub = $viewer.globalContext.hub.on("plugin-destroyed", () => {
230
+ viewerSelectOptions.value = getViewerOptions(props.getViewers());
231
+ });
232
+ }
233
+ });
234
+
235
+ onBeforeUnmount(() => {
236
+ if ($viewer) {
237
+ $viewer.globalContext.hub.off(pluginCreatedSub);
238
+ $viewer.globalContext.hub.off(pluginDestroyedSub);
239
+ }
240
+ });
241
+
242
+ return {
243
+ // References
244
+ comments,
245
+ input,
246
+ isOpen,
247
+ loading,
248
+ text,
249
+ viewerSelectOptions,
250
+ viewerSelectVisible,
251
+ viewpoint,
252
+ isViewer: Boolean($viewer),
253
+ // Methods
254
+ createViewpoint,
255
+ deleteViewpoint,
256
+ highlightViewer,
257
+ loadComments,
258
+ onCommentDeleted,
259
+ onCommentUpdated,
260
+ setCommentViewpoint,
261
+ submitComment,
262
+ unhighlightViewer,
263
+ };
264
+ },
265
+ };
266
+ </script>
267
+
268
+ <style scoped lang="scss" src="./BcfTopicComments.scss"></style>