@bimdata/bcf-components 6.0.0-rc.8 → 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
package/README.md CHANGED
@@ -42,9 +42,3 @@ const app = createApp()
42
42
  It is also possible to provide your own translations for i18n by removing
43
43
  `i18nPlugin` from plugin config and adding translation keys from
44
44
  [`src/i18n/lang/fr.js`](./src/i18n/lang/fr.json) to the translation files of your app.
45
-
46
- ## Build
47
-
48
- ```bash
49
- npm run build
50
- ```
package/package.json CHANGED
@@ -1,36 +1,31 @@
1
1
  {
2
2
  "name": "@bimdata/bcf-components",
3
- "version": "6.0.0-rc.8",
3
+ "version": "6.0.0",
4
4
  "files": [
5
- "dist",
5
+ "src",
6
6
  "vue3-plugin.js"
7
7
  ],
8
- "main": "./dist/bcf-components.mjs",
9
- "module": "./dist/bcf-components.mjs",
8
+ "main": "./src/index.js",
9
+ "module": "./src/index.js",
10
10
  "scripts": {
11
- "build": "vite build --config build.config.js",
12
- "prepublishOnly": "npm run build",
13
11
  "release": "semantic-release"
14
12
  },
13
+ "dependencies": {
14
+ "async": "^3.2.4"
15
+ },
15
16
  "peerDependencies": {
17
+ "@bimdata/design-system": "*",
18
+ "@bimdata/components": "*",
16
19
  "vue": "^3.0"
17
20
  },
18
21
  "devDependencies": {
19
- "@bimdata/components": "^1.0.6",
20
- "@bimdata/design-system": "2.0.0-rc.36",
21
- "@bimdata/vite-plugin-libcss": "0.0.1",
22
22
  "@semantic-release/changelog": "^6.0.3",
23
- "@semantic-release/commit-analyzer": "^9.0.2",
23
+ "@semantic-release/commit-analyzer": "^11.0.0",
24
24
  "@semantic-release/git": "^10.0.1",
25
- "@semantic-release/github": "^8.0.7",
26
- "@semantic-release/npm": "^10.0.3",
27
- "@semantic-release/release-notes-generator": "^11.0.1",
28
- "@vitejs/plugin-vue": "^4.2.1",
29
- "async": "^3.2.4",
30
- "conventional-changelog-eslint": "^3.0.9",
31
- "sass": "^1.62.1",
32
- "semantic-release": "^21.0.2",
33
- "vite": "^4.3.5",
34
- "vite-plugin-static-copy": "^0.16.0"
25
+ "@semantic-release/github": "^9.2.1",
26
+ "@semantic-release/npm": "^11.0.0",
27
+ "@semantic-release/release-notes-generator": "^12.0.0",
28
+ "conventional-changelog-eslint": "^5.0.0",
29
+ "semantic-release": "^22.0.5"
35
30
  }
36
31
  }
@@ -0,0 +1,67 @@
1
+ .bcf-filters {
2
+ &__btn-toggle {
3
+ flex: 1;
4
+ &:enabled {
5
+ color: var(--color-primary);
6
+ }
7
+
8
+ &:disabled {
9
+ background-color: var(--color-white);
10
+ color: var(--color-silver-dark);
11
+ }
12
+ }
13
+
14
+ &__container {
15
+ position: absolute;
16
+ z-index: 1;
17
+ top: calc(32px + 12px);
18
+ left: 0;
19
+ width: 100%;
20
+ min-width: 252px;
21
+ max-width: 296px;
22
+ padding: var(--spacing-unit);
23
+ box-shadow: var(--box-shadow);
24
+ background-color: var(--color-white);
25
+
26
+ display: flex;
27
+ flex-direction: column;
28
+ gap: calc(var(--spacing-unit) * 2);
29
+
30
+ &__header {
31
+ display: flex;
32
+ justify-content: space-between;
33
+ align-items: center;
34
+
35
+ &__title {
36
+ font-size: 1.1rem;
37
+ font-weight: bold;
38
+ }
39
+ }
40
+
41
+ :deep(.bimdata-select.active) {
42
+ z-index: 3;
43
+ }
44
+
45
+ &__date {
46
+ & > .flex {
47
+ gap: calc(var(--spacing-unit) / 2);
48
+ }
49
+
50
+ :deep(.bimdata-datepicker.error) {
51
+ input {
52
+ border-bottom: 1px solid var(--color-high);
53
+ }
54
+ }
55
+
56
+ p {
57
+ margin: calc(var(--spacing-unit) / 2) 0 0;
58
+ font-size: 11px;
59
+ }
60
+ }
61
+
62
+ &__actions {
63
+ display: flex;
64
+ justify-content: center;
65
+ }
66
+ }
67
+ }
@@ -0,0 +1,228 @@
1
+ <template>
2
+ <div class="bcf-filters" v-click-away="close">
3
+ <BIMDataButton
4
+ class="bcf-filters__btn-toggle"
5
+ :disabled="topics.length === 0"
6
+ width="120px"
7
+ fill
8
+ square
9
+ icon
10
+ @click="toggle"
11
+ >
12
+ <BIMDataIconFilterList size="xxs" fill color="default" margin="0 6px 0 0" />
13
+ <span>
14
+ {{ $t("BcfComponents.BcfFilters.filtersButton") }}
15
+ </span>
16
+ </BIMDataButton>
17
+
18
+ <transition name="slide-fade-up">
19
+ <div class="bcf-filters__container" v-show="isOpen">
20
+ <div class="bcf-filters__container__header">
21
+ <div class="bcf-filters__container__header__title">
22
+ {{ $t("BcfComponents.BcfFilters.filtersTitle") }}
23
+ </div>
24
+ <BIMDataButton color="primary" ghost rounded icon @click="close">
25
+ <BIMDataIconClose size="xxs" fill color="primary" />
26
+ </BIMDataButton>
27
+ </div>
28
+
29
+ <BIMDataSelect
30
+ width="100%"
31
+ :multi="true"
32
+ :label="$t('BcfComponents.BcfFilters.priorityLabel')"
33
+ :nullLabel="$t('BcfComponents.BcfFilters.undefined')"
34
+ :options="priorityOptions"
35
+ v-model="filters.priorities"
36
+ />
37
+
38
+ <BIMDataSelect
39
+ width="100%"
40
+ :multi="true"
41
+ :label="$t('BcfComponents.BcfFilters.statusLabel')"
42
+ :nullLabel="$t('BcfComponents.BcfFilters.undefined')"
43
+ :options="statusOptions"
44
+ v-model="filters.statuses"
45
+ />
46
+
47
+ <div class="bcf-filters__container__date">
48
+ <BIMDataDatePicker
49
+ v-model="filters.startDate"
50
+ :value="filters.startDate"
51
+ @to-date-change="filters.endDate = $event"
52
+ :toDate="filters.endDate"
53
+ :clearButton="true"
54
+ width="100%"
55
+ :placeholder="$t('BcfComponents.BcfFilters.datePlaceholder')"
56
+ :isDateRange="true"
57
+ :autoCloseRange="true"
58
+ >
59
+ </BIMDataDatePicker>
60
+ </div>
61
+
62
+ <BIMDataSelect
63
+ width="100%"
64
+ :multi="true"
65
+ :label="$t('BcfComponents.BcfFilters.assignedToLabel')"
66
+ :nullLabel="$t('BcfComponents.BcfFilters.undefined')"
67
+ :options="userOptions"
68
+ v-model="filters.users"
69
+ />
70
+
71
+ <BIMDataSelect
72
+ width="100%"
73
+ :multi="true"
74
+ :label="$t('BcfComponents.BcfFilters.creatorsLabel')"
75
+ :nullLabel="$t('BcfComponents.BcfFilters.undefined')"
76
+ :options="creatorOptions"
77
+ v-model="filters.creators"
78
+ />
79
+
80
+ <BIMDataSelect
81
+ width="100%"
82
+ :multi="true"
83
+ :label="$t('BcfComponents.BcfFilters.tagsLabel')"
84
+ :nullLabel="$t('BcfComponents.BcfFilters.undefined')"
85
+ :options="labelOptions"
86
+ v-model="filters.labels"
87
+ >
88
+ <template #empty>
89
+ <div class="p-x-12 p-t-12 p-b-6">
90
+ <BIMDataText fontSize="13px">
91
+ {{ $t("BcfComponents.BcfFilters.undefined") }}
92
+ </BIMDataText>
93
+ </div>
94
+ </template>
95
+ </BIMDataSelect>
96
+
97
+ <div class="bcf-filters__container__actions">
98
+ <BIMDataButton class="m-r-12" color="primary" ghost radius @click="resetFilters">
99
+ {{ $t("BcfComponents.BcfFilters.resetButton") }}
100
+ </BIMDataButton>
101
+ <BIMDataButton color="primary" fill radius @click="submitFilters">
102
+ <BIMDataIconSearch size="xxs" margin="0 6px 0 0" />
103
+ <span>
104
+ {{ $t("BcfComponents.BcfFilters.searchButton") }}
105
+ </span>
106
+ </BIMDataButton>
107
+ </div>
108
+ </div>
109
+ </transition>
110
+ </div>
111
+ </template>
112
+
113
+ <script>
114
+ import { computed, ref, toRaw, watch } from "vue";
115
+ import { useBcfFilter } from "../../composables/filter.js";
116
+ // Components
117
+ import BIMDataButton from "@bimdata/design-system/src/BIMDataComponents/BIMDataButton/BIMDataButton.vue";
118
+ import {
119
+ BIMDataIconClose,
120
+ BIMDataIconFilterList,
121
+ BIMDataIconSearch,
122
+ } from "@bimdata/design-system/src/BIMDataComponents/BIMDataIcon/BIMDataIconStandalone/index.js";
123
+ import BIMDataInput from "@bimdata/design-system/src/BIMDataComponents/BIMDataInput/BIMDataInput.vue";
124
+ import BIMDataSelect from "@bimdata/design-system/src/BIMDataComponents/BIMDataSelect/BIMDataSelect.vue";
125
+ import BIMDataText from "@bimdata/design-system/src/BIMDataComponents/BIMDataText/BIMDataText.vue";
126
+
127
+ function getSelectOptions(list) {
128
+ return Array.from(new Set(list)).sort((a, b) =>
129
+ a.localeCompare(b, undefined, { sensitivity: "base" })
130
+ );
131
+ }
132
+
133
+ export default {
134
+ components: {
135
+ BIMDataButton,
136
+ BIMDataIconClose,
137
+ BIMDataIconFilterList,
138
+ BIMDataIconSearch,
139
+ BIMDataInput,
140
+ BIMDataSelect,
141
+ BIMDataText
142
+ },
143
+ props: {
144
+ topics: {
145
+ type: Array,
146
+ required: true,
147
+ },
148
+ initFilters: {
149
+ type: Object,
150
+ },
151
+ },
152
+ emits: ["submit"],
153
+ setup(props, { emit }) {
154
+ const isOpen = ref(false);
155
+ const close = () => (isOpen.value = false);
156
+ const toggle = () => (isOpen.value = !isOpen.value);
157
+
158
+ const { filters, filteredTopics, reset, apply } = useBcfFilter(computed(() => props.topics));
159
+
160
+ watch(
161
+ () => props.initFilters,
162
+ () => {
163
+ if (props.initFilters) {
164
+ apply(props.initFilters);
165
+ } else {
166
+ filters;
167
+ }
168
+ },
169
+ { deep: true }
170
+ );
171
+
172
+ const priorityOptions = computed(() =>
173
+ getSelectOptions(props.topics.map((topic) => topic.priority))
174
+ );
175
+
176
+ const statusOptions = computed(() =>
177
+ getSelectOptions(props.topics.map((topic) => topic.topic_status))
178
+ );
179
+
180
+ const userOptions = computed(() =>
181
+ getSelectOptions(props.topics.map((topic) => topic.assigned_to))
182
+ );
183
+
184
+ const creatorOptions = computed(() =>
185
+ getSelectOptions(props.topics.map((topic) => topic.creation_author))
186
+ );
187
+
188
+ const labelOptions = computed(() =>
189
+ getSelectOptions(props.topics.flatMap((topic) => topic.labels))
190
+ );
191
+
192
+ const submitFilters = () => {
193
+ filters.endDate?.setHours(23, 59, 59);
194
+ emit("submit", {
195
+ filters: toRaw(filters),
196
+ topics: filteredTopics.value,
197
+ });
198
+ isOpen.value = false;
199
+ };
200
+
201
+ const resetFilters = () => {
202
+ reset();
203
+ emit("submit", {
204
+ filters: toRaw(filters),
205
+ topics: filteredTopics.value,
206
+ });
207
+ };
208
+
209
+ return {
210
+ // References
211
+ creatorOptions,
212
+ filters,
213
+ isOpen,
214
+ labelOptions,
215
+ priorityOptions,
216
+ statusOptions,
217
+ userOptions,
218
+ // Methods
219
+ close,
220
+ resetFilters,
221
+ submitFilters,
222
+ toggle,
223
+ };
224
+ },
225
+ };
226
+ </script>
227
+
228
+ <style scoped lang="scss" src="./BcfFilters.scss"></style>
@@ -0,0 +1,28 @@
1
+ .bcf-settings {
2
+ height: 100%;
3
+
4
+ &__header {
5
+ padding: 0 calc(var(--spacing-unit) / 2);
6
+ display: flex;
7
+ align-items: center;
8
+ gap: calc(var(--spacing-unit) / 3);
9
+
10
+ &__title {
11
+ flex-grow: 1;
12
+ font-size: 1rem;
13
+ font-weight: bold;
14
+ }
15
+ }
16
+
17
+ &__content {
18
+ height: calc(100% - 32px);
19
+ padding: 0 calc(var(--spacing-unit) * 0.5);
20
+ overflow: auto;
21
+
22
+ &__text {
23
+ padding: calc(var(--spacing-unit) * 2) calc(var(--spacing-unit) * 4);
24
+ text-align: center;
25
+ color: var(--color-granite);
26
+ }
27
+ }
28
+ }
@@ -0,0 +1,117 @@
1
+ <template>
2
+ <div class="bcf-settings">
3
+ <div class="bcf-settings__header">
4
+ <BIMDataButton
5
+ v-if="uiConfig.backButton"
6
+ color="granite"
7
+ ghost
8
+ rounded
9
+ icon
10
+ @click="$emit('back')"
11
+ >
12
+ <BIMDataIconArrow size="xxs" />
13
+ </BIMDataButton>
14
+ <span class="bcf-settings__header__title">
15
+ {{ $t("BcfComponents.BcfSettings.title") }}
16
+ </span>
17
+ <BIMDataButton
18
+ v-if="uiConfig.closeButton"
19
+ color="granite"
20
+ ghost
21
+ rounded
22
+ icon
23
+ @click="$emit('close')"
24
+ >
25
+ <BIMDataIconClose size="xxs" />
26
+ </BIMDataButton>
27
+ </div>
28
+
29
+ <div class="bcf-settings__content">
30
+ <div class="bcf-settings__content__text">
31
+ {{ $t("BcfComponents.BcfSettings.text") }}
32
+ </div>
33
+ <SettingCard
34
+ v-for="t in EXTENSION_TYPES"
35
+ :detailedExtensions="detailedExtensions"
36
+ :extensionType="t"
37
+ @create-extension="createExtension"
38
+ @update-extension="updateExtension"
39
+ @delete-extension="deleteExtension"
40
+ />
41
+ </div>
42
+ </div>
43
+ </template>
44
+
45
+ <script>
46
+ import { EXTENSION_TYPES } from "../../config.js";
47
+ import { useService } from "../../service.js";
48
+ // Components
49
+ import BIMDataButton from "@bimdata/design-system/src/BIMDataComponents/BIMDataButton/BIMDataButton.vue";
50
+
51
+ import {
52
+ BIMDataIconArrow,
53
+ BIMDataIconClose,
54
+ } from "@bimdata/design-system/src/BIMDataComponents/BIMDataIcon/BIMDataIconStandalone/index.js";
55
+ import SettingCard from "./setting-card/SettingCard.vue";
56
+
57
+ export default {
58
+ components: {
59
+ BIMDataButton,
60
+ BIMDataIconArrow,
61
+ BIMDataIconClose,
62
+ SettingCard,
63
+ },
64
+ props: {
65
+ uiConfig: {
66
+ type: Object,
67
+ default: () => ({
68
+ backButton: false,
69
+ closeButton: false,
70
+ }),
71
+ },
72
+ project: {
73
+ type: Object,
74
+ required: true,
75
+ },
76
+ detailedExtensions: {
77
+ type: Object,
78
+ required: true,
79
+ },
80
+ },
81
+ emits: ["back", "close", "extension-created", "extension-updated", "extension-deleted"],
82
+ setup(props, { emit }) {
83
+ const service = useService();
84
+
85
+ const createExtension = async (event) => {
86
+ const ext = await service.createExtension(props.project, event.extensionType, event.data);
87
+ emit("extension-created", ext);
88
+ };
89
+
90
+ const updateExtension = async (event) => {
91
+ const ext = await service.updateExtension(
92
+ props.project,
93
+ event.extensionType,
94
+ event.extension,
95
+ event.data
96
+ );
97
+ emit("extension-updated", ext);
98
+ };
99
+
100
+ const deleteExtension = async (event) => {
101
+ await service.deleteExtension(props.project, event.extensionType, event.extension);
102
+ emit("extension-deleted", event.extension);
103
+ };
104
+
105
+ return {
106
+ // References
107
+ EXTENSION_TYPES,
108
+ // Methods
109
+ createExtension,
110
+ updateExtension,
111
+ deleteExtension,
112
+ };
113
+ },
114
+ };
115
+ </script>
116
+
117
+ <style scoped lang="scss" src="./BcfSettings.scss"></style>
@@ -0,0 +1,59 @@
1
+ .setting-card {
2
+ margin: var(--spacing-unit) 0;
3
+ padding: var(--spacing-unit);
4
+ box-shadow: var(--box-shadow);
5
+ background: var(--color-white);
6
+
7
+ &__header {
8
+ display: flex;
9
+ justify-content: space-between;
10
+ align-items: center;
11
+ cursor: pointer;
12
+
13
+ &__text {
14
+ font-weight: bold;
15
+ }
16
+
17
+ &__icons {
18
+ display: flex;
19
+ align-items: center;
20
+ gap: calc(var(--spacing-unit) * 2);
21
+
22
+ .count {
23
+ min-width: 21px;
24
+ height: 21px;
25
+ padding: 0 4px;
26
+
27
+ display: flex;
28
+ justify-content: center;
29
+ align-items: center;
30
+
31
+ border-radius: 11px;
32
+ font-size: 11px;
33
+ font-weight: 700;
34
+ background-color: var(--color-primary);
35
+ color: var(--color-white);
36
+ }
37
+ }
38
+
39
+ }
40
+
41
+ &__subheader {
42
+ display: flex;
43
+ justify-content: space-between;
44
+ align-items: center;
45
+ margin-top: calc(var(--spacing-unit) / 2);
46
+ margin-bottom: var(--spacing-unit);
47
+ }
48
+
49
+ &__form {
50
+ margin-bottom: var(--spacing-unit);
51
+
52
+ .actions {
53
+ display: flex;
54
+ justify-content: flex-end;
55
+ align-items: center;
56
+ gap: calc(var(--spacing-unit) / 2);
57
+ }
58
+ }
59
+ }
@@ -0,0 +1,140 @@
1
+ <template>
2
+ <div class="setting-card">
3
+ <div class="setting-card__header" @click="toggle">
4
+ <div class="setting-card__header__text">
5
+ {{ $t(`BcfComponents.SettingCard.title.${extensionType}`) }}
6
+ </div>
7
+ <div class="setting-card__header__icons">
8
+ <div v-if="availableExtensions" class="count">
9
+ {{ availableExtensions.length }}
10
+ </div>
11
+ <BIMDataIconChevron size="xxs" :rotate="isOpen ? 90 : 0" />
12
+ </div>
13
+ </div>
14
+ <div v-show="isOpen">
15
+ <div class="setting-card__subheader">
16
+ {{ $t(`BcfComponents.SettingCard.text.${extensionType}`) }}
17
+ <BIMDataButton fill radius @click="toggleForm">
18
+ <BIMDataIconPlus margin="0 6px 0 0" size="xxxs" fill />
19
+ <span>
20
+ {{ $t("BcfComponents.SettingCard.addButton") }}
21
+ </span>
22
+ </BIMDataButton>
23
+ </div>
24
+
25
+ <transition name="slide-fade-up">
26
+ <div v-show="isOpenForm" class="setting-card__form">
27
+ <BIMDataInput
28
+ ref="input"
29
+ :placeholder="$t(`BcfComponents.SettingCard.input.${extensionType}`)"
30
+ v-model="name"
31
+ @keyup.enter.stop="addExtension"
32
+ />
33
+
34
+ <div class="actions">
35
+ <BIMDataButton ghost radius @click="closeForm">
36
+ {{ $t("BcfComponents.SettingCard.cancelButton") }}
37
+ </BIMDataButton>
38
+ <BIMDataButton color="primary" fill radius @click="addExtension">
39
+ {{ $t("BcfComponents.SettingCard.validateButton") }}
40
+ </BIMDataButton>
41
+ </div>
42
+ </div>
43
+ </transition>
44
+
45
+ <ul class="setting-card__content bimdata-list">
46
+ <SettingCardItem
47
+ v-for="extension in availableExtensions"
48
+ :key="extension.id"
49
+ :extensionType="extensionType"
50
+ :extension="extension"
51
+ @update-extension="$emit('update-extension', $event)"
52
+ @delete-extension="$emit('delete-extension', $event)"
53
+ />
54
+ </ul>
55
+ </div>
56
+ </div>
57
+ </template>
58
+
59
+ <script>
60
+ import { computed, ref } from "vue";
61
+ import { getAvailableExtensions } from "../../../utils/extensions.js";
62
+ // Compopnents
63
+ import BIMDataButton from "@bimdata/design-system/src/BIMDataComponents/BIMDataButton/BIMDataButton.vue";
64
+ import {
65
+ BIMDataIconChevron,
66
+ BIMDataIconPlus,
67
+ } from "@bimdata/design-system/src/BIMDataComponents/BIMDataIcon/BIMDataIconStandalone/index.js";
68
+ import BIMDataInput from "@bimdata/design-system/src/BIMDataComponents/BIMDataInput/BIMDataInput.vue";
69
+ import SettingCardItem from "./SettingCardItem.vue";
70
+
71
+ export default {
72
+ components: {
73
+ BIMDataButton,
74
+ BIMDataIconChevron,
75
+ BIMDataIconPlus,
76
+ BIMDataInput,
77
+ SettingCardItem,
78
+ },
79
+ props: {
80
+ detailedExtensions: {
81
+ type: Object,
82
+ required: true,
83
+ },
84
+ extensionType: {
85
+ type: String,
86
+ required: true,
87
+ },
88
+ },
89
+ emits: ["create-extension", "update-extension", "delete-extension"],
90
+ setup(props, { emit }) {
91
+ const availableExtensions = computed(() =>
92
+ getAvailableExtensions(props.extensionType, props.detailedExtensions)
93
+ );
94
+
95
+ const input = ref(null);
96
+ const name = ref("");
97
+
98
+ const isOpen = ref(false);
99
+ const close = () => (isOpen.value = false);
100
+ const toggle = () => (isOpen.value = !isOpen.value);
101
+
102
+ const isOpenForm = ref(false);
103
+ const closeForm = () => {
104
+ name.value = "";
105
+ isOpenForm.value = false;
106
+ };
107
+ const toggleForm = () => {
108
+ isOpenForm.value = !isOpenForm.value;
109
+ if (isOpenForm.value) {
110
+ setTimeout(() => input.value.focus(), 50);
111
+ }
112
+ };
113
+
114
+ const addExtension = async () => {
115
+ emit("create-extension", {
116
+ extensionType: props.extensionType,
117
+ data: { value: name.value },
118
+ });
119
+ closeForm();
120
+ };
121
+
122
+ return {
123
+ // References
124
+ availableExtensions,
125
+ input,
126
+ isOpen,
127
+ isOpenForm,
128
+ name,
129
+ // Methods
130
+ addExtension,
131
+ close,
132
+ closeForm,
133
+ toggle,
134
+ toggleForm,
135
+ };
136
+ },
137
+ };
138
+ </script>
139
+
140
+ <style scoped lang="scss" src="./SettingCard.scss"></style>