@vcmap/ui 5.0.0-rc.14 → 5.0.0-rc.16
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/README.md +33 -31
- package/build/build.js +9 -0
- package/build/buildHelpers.js +12 -10
- package/build/commonViteConfig.js +3 -10
- package/config/base.config.json +30 -24
- package/config/dev.config.json +13 -1
- package/config/www.config.json +104 -17
- package/dist/assets/cesium.430460.js +137226 -0
- package/dist/assets/cesium.js +1 -1
- package/dist/assets/core.5089ba.js +16024 -0
- package/dist/assets/core.js +1 -1
- package/dist/assets/index.854f8e2b.js +1 -0
- package/dist/assets/ol.9be53a.js +44279 -0
- package/dist/assets/ol.js +1 -1
- package/dist/assets/{ui.15ef6a.css → ui.49010a.css} +1 -1
- package/dist/assets/ui.49010a.js +16776 -0
- package/dist/assets/ui.js +1 -1
- package/dist/assets/vue.247c1c.js +4675 -0
- package/dist/assets/vue.js +5 -2
- package/dist/assets/{vuetify.202322.css → vuetify.735e58.css} +1 -1
- package/dist/assets/vuetify.735e58.js +21019 -0
- package/dist/assets/vuetify.js +5 -2
- package/dist/index.html +1 -1
- package/index.html +77 -0
- package/index.js +8 -1
- package/package.json +12 -10
- package/plugins/@vcmap/create-link/fallbackCreateLink.vue +4 -1
- package/plugins/@vcmap/create-link/index.js +4 -1
- package/plugins/@vcmap/pluginExample/exampleActions.js +45 -0
- package/plugins/@vcmap/pluginExample/index.js +38 -1
- package/plugins/@vcmap/pluginExample/pluginExampleComponent.vue +152 -98
- package/plugins/@vcmap/project-selector/ContextsListComponent.vue +8 -1
- package/plugins/@vcmap/project-selector/ProjectSelectorComponent.vue +27 -1
- package/plugins/@vcmap/search-nominatim/LICENSE.md +14 -0
- package/plugins/@vcmap/search-nominatim/README.md +2 -0
- package/plugins/@vcmap/search-nominatim/config.json +4 -0
- package/plugins/@vcmap/search-nominatim/index.js +26 -0
- package/plugins/@vcmap/search-nominatim/nominatim.js +170 -0
- package/plugins/@vcmap/search-nominatim/package.json +43 -0
- package/plugins/@vcmap/theme-changer/ThemeChangerComponent.vue +26 -0
- package/plugins/buttonExamples/ButtonExamples.vue +28 -1
- package/plugins/categoryTest/Categories.vue +16 -0
- package/plugins/categoryTest/Category.vue +30 -4
- package/plugins/example/mySuperComponent.vue +12 -1
- package/plugins/notifier/index.js +31 -0
- package/plugins/notifier/notifierTester.vue +88 -0
- package/plugins/package.json +2 -1
- package/plugins/simple-graph/SimpleGraphComponent.vue +5 -11
- package/plugins/test/allIconsComponent.vue +16 -0
- package/plugins/test/editor.vue +3 -0
- package/plugins/test/emptyComponent.vue +3 -0
- package/plugins/test/index.js +22 -0
- package/plugins/test/myCustomHeader.vue +9 -1
- package/plugins/test/testList.vue +287 -0
- package/plugins/test/vcsContent.vue +3 -0
- package/plugins/test/windowManagerExample.vue +3 -0
- package/plugins/wizardExample/index.js +41 -0
- package/plugins/wizardExample/wizardExample.vue +77 -0
- package/src/actions/actionHelper.js +103 -2
- package/src/actions/styleSelector.vue +9 -0
- package/src/application/VcsApp.vue +95 -17
- package/src/application/VcsAttributions.vue +63 -0
- package/src/application/VcsAttributionsFooter.vue +87 -0
- package/src/application/{Navbar.vue → VcsNavbar.vue} +35 -2
- package/src/application/VcsSettings.vue +4 -0
- package/src/application/attributionsHelper.js +150 -0
- package/src/application/vcsAppWrapper.vue +5 -1
- package/src/components/buttons/VcsActionButtonList.vue +8 -1
- package/src/components/buttons/VcsButton.vue +7 -1
- package/src/components/form-inputs-controls/VcsCheckbox.vue +7 -2
- package/src/components/form-inputs-controls/VcsColorPicker.vue +4 -0
- package/src/components/form-inputs-controls/VcsFormSection.vue +55 -9
- package/src/components/form-inputs-controls/VcsRadio.vue +7 -1
- package/src/components/form-inputs-controls/VcsSelect.vue +38 -2
- package/src/components/form-inputs-controls/VcsTextArea.vue +2 -0
- package/src/components/form-inputs-controls/VcsTextField.vue +16 -4
- package/src/components/form-inputs-controls/VcsWizard.vue +133 -0
- package/src/components/imageElementInjector.vue +22 -0
- package/src/components/lists/VcsActionList.vue +12 -1
- package/src/components/lists/VcsList.vue +466 -0
- package/src/components/lists/VcsTreeview.vue +7 -3
- package/src/components/lists/VcsTreeviewLeaf.vue +23 -51
- package/src/components/lists/VcsTreeviewSearchbar.vue +6 -23
- package/src/components/notification/VcsTooltip.vue +14 -9
- package/src/components/tables/VcsTable.vue +129 -38
- package/src/contentTree/LayerTree.vue +1 -1
- package/src/contentTree/contentTreeItem.js +13 -13
- package/src/contentTree/subContentTreeItem.js +1 -1
- package/src/contentTree/vcsObjectContentTreeItem.js +1 -1
- package/src/featureInfo/AddressBalloonComponent.vue +17 -1
- package/src/featureInfo/BalloonComponent.vue +63 -27
- package/src/featureInfo/balloonFeatureInfoView.js +14 -14
- package/src/featureInfo/balloonHelper.js +4 -0
- package/src/featureInfo/featureInfo.js +23 -2
- package/src/featureInfo/featureInfoInteraction.js +1 -1
- package/src/i18n/de.js +22 -0
- package/src/i18n/en.js +22 -0
- package/src/icons/+all.js +4 -0
- package/src/icons/WandIcon.vue +63 -0
- package/src/legend/legendHelper.js +18 -12
- package/src/legend/styleLegendItem.vue +20 -1
- package/src/legend/vcsLegend.vue +29 -3
- package/src/manager/toolbox/GroupToolboxComponent.vue +13 -1
- package/src/manager/toolbox/SelectToolboxComponent.vue +13 -1
- package/src/manager/toolbox/ToolboxManager.vue +3 -0
- package/src/manager/window/WindowComponent.vue +15 -2
- package/src/manager/window/WindowComponentHeader.vue +38 -7
- package/src/manager/window/WindowManager.vue +1 -0
- package/src/manager/window/windowManager.js +11 -1
- package/src/navigation/mapNavigation.vue +15 -36
- package/src/navigation/orientationToolsButton.vue +6 -1
- package/src/navigation/overviewMap.js +19 -47
- package/src/navigation/tiltSlider.vue +3 -0
- package/src/navigation/vcsCompass.vue +2 -0
- package/src/notifier/notifier.js +121 -0
- package/src/notifier/notifierComponent.vue +84 -0
- package/src/search/resultItem.vue +89 -0
- package/src/search/resultsComponent.vue +98 -0
- package/src/search/search.js +326 -0
- package/src/search/searchComponent.vue +90 -0
- package/src/styles/_typography.scss +3 -0
- package/src/styles/utils/_cursor.scss +4 -0
- package/src/styles/variables.scss +23 -4
- package/src/vcsUiApp.js +35 -1
- package/src/vuePlugins/vuetify.js +2 -0
- package/dist/assets/cesium.9489f8.js +0 -8699
- package/dist/assets/core.aa346a.js +0 -4
- package/dist/assets/index.3cd4fffa.js +0 -1
- package/dist/assets/ol.39651b.js +0 -439
- package/dist/assets/ui.15ef6a.js +0 -71
- package/dist/assets/vue.cbe9d8.js +0 -9
- package/dist/assets/vuetify.202322.js +0 -148
@@ -0,0 +1,466 @@
|
|
1
|
+
<template>
|
2
|
+
<div
|
3
|
+
class="d-contents"
|
4
|
+
>
|
5
|
+
<vcs-treeview-searchbar
|
6
|
+
v-if="searchable"
|
7
|
+
:placeholder="searchbarPlaceholder"
|
8
|
+
v-model="query"
|
9
|
+
/>
|
10
|
+
<v-list
|
11
|
+
dense
|
12
|
+
>
|
13
|
+
<v-list-item
|
14
|
+
v-if="showTitle"
|
15
|
+
class="font-weight-bold"
|
16
|
+
>
|
17
|
+
<v-list-item-action
|
18
|
+
v-if="selectable"
|
19
|
+
>
|
20
|
+
<v-icon
|
21
|
+
v-if="selected.length === renderingItems.length"
|
22
|
+
@click="clear"
|
23
|
+
>
|
24
|
+
mdi-check-circle-outline
|
25
|
+
</v-icon>
|
26
|
+
<v-icon
|
27
|
+
v-else
|
28
|
+
@click="selectAll()"
|
29
|
+
>
|
30
|
+
mdi-circle-outline
|
31
|
+
</v-icon>
|
32
|
+
</v-list-item-action>
|
33
|
+
|
34
|
+
<v-list-item-content
|
35
|
+
:title="$t(tooltip || title)"
|
36
|
+
>
|
37
|
+
<v-icon v-if="icon">
|
38
|
+
{{ icon }}
|
39
|
+
</v-icon>
|
40
|
+
|
41
|
+
<v-list-item-title>
|
42
|
+
{{ $t(title) }}
|
43
|
+
</v-list-item-title>
|
44
|
+
|
45
|
+
<vcs-action-button-list
|
46
|
+
v-if="actions?.length > 0"
|
47
|
+
:actions="actions"
|
48
|
+
:block-overflow="true"
|
49
|
+
:overflow-count="actionButtonListOverflowCount"
|
50
|
+
small
|
51
|
+
right
|
52
|
+
/>
|
53
|
+
</v-list-item-content>
|
54
|
+
</v-list-item>
|
55
|
+
<v-list-item
|
56
|
+
v-for="(item, index) in renderingItems"
|
57
|
+
:key="`item-${index}`"
|
58
|
+
:input-value="selected.includes(item)"
|
59
|
+
:disabled="item.disabled"
|
60
|
+
@mousedown.shift="$event.preventDefault()"
|
61
|
+
@mouseover="hovering = index"
|
62
|
+
@mouseout="hovering = null"
|
63
|
+
>
|
64
|
+
<v-list-item-action
|
65
|
+
v-if="selectable"
|
66
|
+
>
|
67
|
+
<v-icon
|
68
|
+
v-if="selected.includes(item)"
|
69
|
+
@click="remove(item)"
|
70
|
+
>
|
71
|
+
mdi-check-circle-outline
|
72
|
+
</v-icon>
|
73
|
+
<v-icon
|
74
|
+
v-else-if="hovering === index || (!singleSelect && selected.length > 0)"
|
75
|
+
@click="singleSelect ? select(item, $event) : add(item)"
|
76
|
+
>
|
77
|
+
mdi-circle-outline
|
78
|
+
</v-icon>
|
79
|
+
<v-icon
|
80
|
+
v-else
|
81
|
+
@click="select(item, $event)"
|
82
|
+
>
|
83
|
+
mdi-circle-small
|
84
|
+
</v-icon>
|
85
|
+
</v-list-item-action>
|
86
|
+
|
87
|
+
<v-list-item-content
|
88
|
+
:title="$t(item.tooltip || item.title)"
|
89
|
+
:class="[selectable ? 'cursor-pointer' : '']"
|
90
|
+
@click="select(item, $event)"
|
91
|
+
>
|
92
|
+
<v-icon v-if="item.icon">
|
93
|
+
{{ item.icon }}
|
94
|
+
</v-icon>
|
95
|
+
|
96
|
+
<v-list-item-title>
|
97
|
+
{{ $t(item.title) }}
|
98
|
+
</v-list-item-title>
|
99
|
+
|
100
|
+
<vcs-action-button-list
|
101
|
+
v-if="item.actions?.length > 0"
|
102
|
+
:actions="item.actions"
|
103
|
+
:block-overflow="true"
|
104
|
+
:overflow-count="actionButtonListOverflowCount"
|
105
|
+
small
|
106
|
+
right
|
107
|
+
/>
|
108
|
+
</v-list-item-content>
|
109
|
+
</v-list-item>
|
110
|
+
</v-list>
|
111
|
+
</div>
|
112
|
+
</template>
|
113
|
+
|
114
|
+
<script>
|
115
|
+
import { computed, getCurrentInstance, inject, ref, watch } from 'vue';
|
116
|
+
import {
|
117
|
+
VList,
|
118
|
+
VListItem,
|
119
|
+
VListItemContent,
|
120
|
+
VListItemAction,
|
121
|
+
VIcon,
|
122
|
+
VListItemTitle,
|
123
|
+
} from 'vuetify/lib';
|
124
|
+
import VcsActionButtonList from '../buttons/VcsActionButtonList.vue';
|
125
|
+
import VcsTreeviewSearchbar from './VcsTreeviewSearchbar.vue';
|
126
|
+
|
127
|
+
/**
|
128
|
+
* @typedef {Object} VcsListItem
|
129
|
+
* @property {string} name
|
130
|
+
* @property {boolean} [visible] - Whether to display this item or not.
|
131
|
+
* @property {boolean} [disabled] - Whether this item should be displayed as disabled.
|
132
|
+
* @property {string} title - The title to be displayed
|
133
|
+
* @property {string} [tooltip]
|
134
|
+
* @property {string|HTMLCanvasElement|HTMLImageElement|undefined} [icon] - An optional icon to display with this item. Can be an URL or HTMLElement.
|
135
|
+
* @property {Array<VcsAction>} [actions]
|
136
|
+
* @property {function(boolean):void} [selectionChanged] - A callback called if the selection changes with the current selection status. called before value update
|
137
|
+
*/
|
138
|
+
|
139
|
+
/**
|
140
|
+
* The VCS list is intended to render items. Items can be selectable (by default, more then one) or only a single item can
|
141
|
+
* be selected. If items are disabled they cannot selected. Items which are not visible are not rendered. This items can
|
142
|
+
* no longer be selected or deselected either. Making a selected item invisible can lead to undefined behavior
|
143
|
+
* in the selection state.
|
144
|
+
* Clicking an unselected item selects it.
|
145
|
+
* Clicking a selected item which is not part of a set or range, deselects it.
|
146
|
+
* Clicking a selected item of a list or range will deselect the other items in the range or set
|
147
|
+
* Clicking with CTRL adds or removes to a selection set.
|
148
|
+
* Clicking with SHIFT will create a selection range, starting or ending with the first item in the list
|
149
|
+
* or the last normally selected item (not the last item clicked with CTRL for instance).
|
150
|
+
* @vue-prop {Array<VcsListItem>} items
|
151
|
+
* @vue-prop {boolean} [selectable=false]
|
152
|
+
* @vue-prop {boolean} [singleSelect=false]
|
153
|
+
* @vue-prop {Array<VcsListItem>} [value=[]] - the initial items to be selected.
|
154
|
+
* @vue-prop {boolean} [searchable=false] - if this list can have its items searched. you can provide your own predicate function by providing "filterPredicate" which is of type function(VcsListItem, string):boolean
|
155
|
+
* @vue-prop {string} [searchbarPlaceholder] - placeholder to render inside the search field
|
156
|
+
* @vue-prop {boolean} [showTitle=true] - show the title component
|
157
|
+
* @vue-prop {number} [actionButtonListOverflowCount] - overflow count to use for action lists in the title and items
|
158
|
+
* @vue-prop {string} [title] - the lists title
|
159
|
+
* @vue-prop {string} [icon] - icon to prepend to the list title
|
160
|
+
* @vue-prop {string} [tooltip] - tooltip to render on the list title
|
161
|
+
* @vue-prop {Array<VcsAction>} [actions] - actions to render in the list title
|
162
|
+
*/
|
163
|
+
export default {
|
164
|
+
name: 'VcsList',
|
165
|
+
components: {
|
166
|
+
VcsTreeviewSearchbar,
|
167
|
+
VcsActionButtonList,
|
168
|
+
VList,
|
169
|
+
VListItem,
|
170
|
+
VListItemContent,
|
171
|
+
VListItemAction,
|
172
|
+
VIcon,
|
173
|
+
VListItemTitle,
|
174
|
+
},
|
175
|
+
props: {
|
176
|
+
/** @type {Array<VcsListItem>} */
|
177
|
+
items: {
|
178
|
+
type: Array,
|
179
|
+
required: true,
|
180
|
+
},
|
181
|
+
selectable: {
|
182
|
+
type: Boolean,
|
183
|
+
default: false,
|
184
|
+
},
|
185
|
+
singleSelect: {
|
186
|
+
type: Boolean,
|
187
|
+
default: false,
|
188
|
+
},
|
189
|
+
/** @type {Array<VcsListItem>} */
|
190
|
+
value: {
|
191
|
+
type: Array,
|
192
|
+
default: () => [],
|
193
|
+
},
|
194
|
+
searchable: {
|
195
|
+
type: Boolean,
|
196
|
+
default: false,
|
197
|
+
},
|
198
|
+
searchbarPlaceholder: {
|
199
|
+
type: String,
|
200
|
+
default: undefined,
|
201
|
+
},
|
202
|
+
showTitle: {
|
203
|
+
type: Boolean,
|
204
|
+
default: true,
|
205
|
+
},
|
206
|
+
actionButtonListOverflowCount: {
|
207
|
+
type: Number,
|
208
|
+
required: false,
|
209
|
+
default: undefined,
|
210
|
+
},
|
211
|
+
title: {
|
212
|
+
type: String,
|
213
|
+
required: false,
|
214
|
+
default: '',
|
215
|
+
},
|
216
|
+
icon: {
|
217
|
+
type: String,
|
218
|
+
required: false,
|
219
|
+
default: undefined,
|
220
|
+
},
|
221
|
+
tooltip: {
|
222
|
+
type: String,
|
223
|
+
required: false,
|
224
|
+
default: '',
|
225
|
+
},
|
226
|
+
actions: {
|
227
|
+
type: Array,
|
228
|
+
required: false,
|
229
|
+
default: undefined,
|
230
|
+
},
|
231
|
+
},
|
232
|
+
setup(props, { emit }) {
|
233
|
+
/** @type {import("vue").Ref<Array<VcsListItem>>} */
|
234
|
+
const selected = ref(props.value);
|
235
|
+
/** @type {import("vue").Ref<string>} */
|
236
|
+
const query = ref('');
|
237
|
+
const hovering = ref(null);
|
238
|
+
let firstSelected = null;
|
239
|
+
|
240
|
+
watch(props, () => {
|
241
|
+
if (selected.value !== props.value) {
|
242
|
+
selected.value = props.value;
|
243
|
+
}
|
244
|
+
if (props.singleSelect && selected.value.length > 1) {
|
245
|
+
selected.value
|
246
|
+
.filter((i, index) => index && i.selectionChanged)
|
247
|
+
.forEach(i => i.selectionChanged(false));
|
248
|
+
selected.value = [selected.value[0]];
|
249
|
+
emit('input', selected);
|
250
|
+
}
|
251
|
+
if (!props.selectable && selected.value.length > 0) {
|
252
|
+
selected.value
|
253
|
+
.filter(i => i.selectionChanged)
|
254
|
+
.forEach(i => i.selectionChanged(false));
|
255
|
+
selected.value = [];
|
256
|
+
emit('input', selected);
|
257
|
+
}
|
258
|
+
if (!props.searchable) {
|
259
|
+
query.value = '';
|
260
|
+
}
|
261
|
+
}, { immediate: true, deep: false });
|
262
|
+
|
263
|
+
const vm = getCurrentInstance().proxy;
|
264
|
+
/** @type {function(VcsListItem, string):boolean} */
|
265
|
+
const filterPredicate = inject('filterPredicate', (item, queryString = '') => {
|
266
|
+
const translatedTitle = vm.$t(item.title);
|
267
|
+
return translatedTitle.toLocaleLowerCase().includes(queryString.toLocaleLowerCase());
|
268
|
+
});
|
269
|
+
|
270
|
+
return {
|
271
|
+
query,
|
272
|
+
hovering,
|
273
|
+
/**
|
274
|
+
* @type {import("vue").ComputedRef<Array<VcsListItem>>}
|
275
|
+
*/
|
276
|
+
renderingItems: computed(() => {
|
277
|
+
let items = props.items.filter(i => i.visible !== false);
|
278
|
+
if (query.value) {
|
279
|
+
items = items.filter(i => filterPredicate(i, query.value));
|
280
|
+
}
|
281
|
+
return items;
|
282
|
+
}),
|
283
|
+
/** @type {import("vue").Ref<Array<VcsListItem>>} */
|
284
|
+
selected,
|
285
|
+
/**
|
286
|
+
* @param {VcsListItem} item
|
287
|
+
* @param {PointerEvent} event
|
288
|
+
*/
|
289
|
+
select(item, event) {
|
290
|
+
if (!props.selectable || item.disabled) {
|
291
|
+
return;
|
292
|
+
}
|
293
|
+
if (props.singleSelect) {
|
294
|
+
if (selected.value[0] === item) {
|
295
|
+
item.selectionChanged?.(false);
|
296
|
+
selected.value = [];
|
297
|
+
firstSelected = null;
|
298
|
+
} else {
|
299
|
+
selected.value[0]?.selectionChanged?.(false);
|
300
|
+
item.selectionChanged?.(true);
|
301
|
+
selected.value = [item];
|
302
|
+
firstSelected = item;
|
303
|
+
}
|
304
|
+
} else if (event.shiftKey) {
|
305
|
+
let firstIndex = 0;
|
306
|
+
if (firstSelected) {
|
307
|
+
firstIndex = this.renderingItems.indexOf(firstSelected);
|
308
|
+
}
|
309
|
+
const currentIndex = this.renderingItems.indexOf(item);
|
310
|
+
if (firstIndex > -1 && currentIndex > -1) {
|
311
|
+
const currentSelection = [...selected.value];
|
312
|
+
selected.value = this.renderingItems.slice(
|
313
|
+
Math.min(firstIndex, currentIndex),
|
314
|
+
Math.max(firstIndex, currentIndex) + 1,
|
315
|
+
);
|
316
|
+
currentSelection.forEach((oldItem) => {
|
317
|
+
if (oldItem.selectionChanged && !selected.value.includes(oldItem)) {
|
318
|
+
oldItem.selectionChanged(false);
|
319
|
+
}
|
320
|
+
});
|
321
|
+
selected.value.forEach((newItem) => {
|
322
|
+
if (newItem.selectionChanged && !currentSelection.includes(newItem)) {
|
323
|
+
newItem.selectionChanged(true);
|
324
|
+
}
|
325
|
+
});
|
326
|
+
} else {
|
327
|
+
selected.value
|
328
|
+
.filter(i => i !== item && i.selectionChanged)
|
329
|
+
.forEach(i => i.selectionChanged(false));
|
330
|
+
selected.value = [];
|
331
|
+
firstSelected = null;
|
332
|
+
}
|
333
|
+
} else if (selected.value.includes(item)) {
|
334
|
+
if (event.ctrlKey) {
|
335
|
+
item.selectionChanged?.(false);
|
336
|
+
selected.value = selected.value.filter(i => i !== item);
|
337
|
+
} else if (selected.value.length > 1) {
|
338
|
+
selected.value
|
339
|
+
.filter(i => i !== item && i.selectionChanged)
|
340
|
+
.forEach(i => i.selectionChanged(false));
|
341
|
+
selected.value = [item];
|
342
|
+
firstSelected = item;
|
343
|
+
} else {
|
344
|
+
item.selectionChanged?.(false);
|
345
|
+
selected.value = [];
|
346
|
+
firstSelected = null;
|
347
|
+
}
|
348
|
+
} else if (event.ctrlKey) {
|
349
|
+
item.selectionChanged?.(true);
|
350
|
+
selected.value = [...selected.value, item];
|
351
|
+
if (selected.value.length === 1) {
|
352
|
+
firstSelected = item;
|
353
|
+
}
|
354
|
+
} else {
|
355
|
+
selected.value
|
356
|
+
.filter(i => i !== item && i.selectionChanged)
|
357
|
+
.forEach(i => i.selectionChanged(false));
|
358
|
+
item.selectionChanged?.(true);
|
359
|
+
selected.value = [item];
|
360
|
+
firstSelected = item;
|
361
|
+
}
|
362
|
+
|
363
|
+
emit('input', selected.value);
|
364
|
+
},
|
365
|
+
/**
|
366
|
+
* @param {VcsListItem} item
|
367
|
+
*/
|
368
|
+
add(item) {
|
369
|
+
if (!selected.value.includes(item) && !item.disabled) {
|
370
|
+
item.selectionChanged?.(true);
|
371
|
+
selected.value = [...selected.value, item];
|
372
|
+
emit('input', selected.value);
|
373
|
+
}
|
374
|
+
},
|
375
|
+
/**
|
376
|
+
* @param {VcsListItem} item
|
377
|
+
*/
|
378
|
+
remove(item) {
|
379
|
+
if (selected.value.includes(item) && !item.disabled) {
|
380
|
+
item.selectionChanged?.(false);
|
381
|
+
selected.value = selected.value.filter(i => i !== item);
|
382
|
+
emit('input', selected.value);
|
383
|
+
}
|
384
|
+
},
|
385
|
+
clear() {
|
386
|
+
selected.value
|
387
|
+
.filter(i => i.selectionChanged)
|
388
|
+
.forEach(i => i.selectionChanged(false));
|
389
|
+
selected.value = [];
|
390
|
+
firstSelected = null;
|
391
|
+
},
|
392
|
+
selectAll() {
|
393
|
+
const currentSelection = [...selected.value];
|
394
|
+
selected.value = this.renderingItems.slice(0);
|
395
|
+
selected.value.forEach((item) => {
|
396
|
+
if (item.selectionChanged && currentSelection.includes(item)) {
|
397
|
+
item.selectionChanged(true);
|
398
|
+
}
|
399
|
+
});
|
400
|
+
},
|
401
|
+
};
|
402
|
+
},
|
403
|
+
};
|
404
|
+
</script>
|
405
|
+
|
406
|
+
<style lang="scss" scoped>
|
407
|
+
::v-deep {
|
408
|
+
.v-list{
|
409
|
+
.v-list-item {
|
410
|
+
padding: 4px 8px 4px 16px;
|
411
|
+
display: grid;
|
412
|
+
grid-template-columns: auto 1fr;
|
413
|
+
&:after{
|
414
|
+
display: none;
|
415
|
+
}
|
416
|
+
&.font-weight-bold{
|
417
|
+
.v-list-item__title{
|
418
|
+
font-weight: 700;
|
419
|
+
}
|
420
|
+
}
|
421
|
+
&.v-list-item--active{
|
422
|
+
padding: 4px 8px 3px 16px;
|
423
|
+
&.theme--light{
|
424
|
+
background-color: var(--v-primary-base);
|
425
|
+
border-bottom: 1px solid var(--v-primary-darken1);
|
426
|
+
}
|
427
|
+
}
|
428
|
+
&.v-list-item.theme--dark{
|
429
|
+
&.v-list-item--active{
|
430
|
+
background-color: var(--v-primary-darken1);
|
431
|
+
border-bottom: 1px solid var(--v-primary-darken2);
|
432
|
+
&:nth-child(even){
|
433
|
+
background-color: var(--v-primary-darken1);
|
434
|
+
}
|
435
|
+
}
|
436
|
+
&:nth-child(even){
|
437
|
+
background-color: rgba(255, 255, 255, 0.15);
|
438
|
+
}
|
439
|
+
}
|
440
|
+
&:nth-child(even) {
|
441
|
+
background-color: var(--v-accent-base);
|
442
|
+
}
|
443
|
+
.v-list-item__action {
|
444
|
+
.v-icon {
|
445
|
+
font-size: 16px;
|
446
|
+
}
|
447
|
+
}
|
448
|
+
.v-list-item__content {
|
449
|
+
flex-wrap: nowrap;
|
450
|
+
column-gap: 4px;
|
451
|
+
.v-icon,
|
452
|
+
.action-btn-wrap {
|
453
|
+
flex: 1 1 auto;
|
454
|
+
}
|
455
|
+
.v-icon{
|
456
|
+
font-size: 16px;
|
457
|
+
.v-icon__component{
|
458
|
+
width: 16px;
|
459
|
+
height: 16px;
|
460
|
+
}
|
461
|
+
}
|
462
|
+
}
|
463
|
+
}
|
464
|
+
}
|
465
|
+
}
|
466
|
+
</style>
|
@@ -13,13 +13,12 @@
|
|
13
13
|
item-key="name"
|
14
14
|
:search="search"
|
15
15
|
:filter="handleFilter"
|
16
|
-
:activatable="false"
|
17
16
|
>
|
18
17
|
<template #label="{ item }">
|
19
18
|
<VcsTreeviewLeaf
|
20
19
|
:item="item"
|
21
20
|
:class="[item.clickable ? 'cursor-pointer' : '']"
|
22
|
-
@click.native="item.clickable && item.clicked()"
|
21
|
+
@click.native="item.clickable && item.clicked($event)"
|
23
22
|
/>
|
24
23
|
</template>
|
25
24
|
</v-treeview>
|
@@ -56,6 +55,7 @@
|
|
56
55
|
|
57
56
|
<script>
|
58
57
|
import { getCurrentInstance, ref } from 'vue';
|
58
|
+
import { VTreeview } from 'vuetify/lib';
|
59
59
|
import VcsTreeviewLeaf from './VcsTreeviewLeaf.vue';
|
60
60
|
import VcsTreeviewSearchbar from './VcsTreeviewSearchbar.vue';
|
61
61
|
|
@@ -68,7 +68,11 @@
|
|
68
68
|
*/
|
69
69
|
export default {
|
70
70
|
name: 'VcsTreeview',
|
71
|
-
components: {
|
71
|
+
components: {
|
72
|
+
VcsTreeviewSearchbar,
|
73
|
+
VcsTreeviewLeaf,
|
74
|
+
VTreeview,
|
75
|
+
},
|
72
76
|
props: {
|
73
77
|
showSearchbar: {
|
74
78
|
type: Boolean,
|
@@ -3,21 +3,22 @@
|
|
3
3
|
class="d-flex flex-row align-center"
|
4
4
|
v-if="item"
|
5
5
|
>
|
6
|
-
<span v-if="item.icon" class="d-flex align-center">
|
7
|
-
<v-icon
|
8
|
-
v-if="iconType === iconTypes.string"
|
9
|
-
v-text="item.icon"
|
10
|
-
:size="16"
|
11
|
-
class="mr-1"
|
12
|
-
/>
|
13
|
-
<span ref="imgContainer" />
|
14
|
-
</span>
|
15
|
-
|
16
6
|
<div
|
17
|
-
class="position-relative col-8 pa-0 d-flex align-center treeview-
|
7
|
+
class="position-relative col-8 pa-0 d-flex align-center vcs-treeview-leaf"
|
18
8
|
:title="$t(item.tooltip || item.title)"
|
19
9
|
>
|
20
|
-
<span
|
10
|
+
<span
|
11
|
+
v-if="item.icon"
|
12
|
+
>
|
13
|
+
<v-icon
|
14
|
+
v-if="isStringIcon"
|
15
|
+
v-text="item.icon"
|
16
|
+
:size="16"
|
17
|
+
class="mr-1"
|
18
|
+
/>
|
19
|
+
<ImageElementInjector :element="item.icon" v-else />
|
20
|
+
</span>
|
21
|
+
<span class="vcs-treeview-item-title">{{ $t(item.title) }}</span>
|
21
22
|
</div>
|
22
23
|
<VcsActionButtonList
|
23
24
|
v-if="item.actions.length > 0"
|
@@ -31,7 +32,7 @@
|
|
31
32
|
</div>
|
32
33
|
</template>
|
33
34
|
<style lang="css" scoped>
|
34
|
-
.treeview-
|
35
|
+
.vcs-treeview-leaf .vcs-treeview-item-title{
|
35
36
|
white-space: nowrap;
|
36
37
|
overflow: hidden;
|
37
38
|
text-overflow: ellipsis;
|
@@ -39,21 +40,10 @@
|
|
39
40
|
</style>
|
40
41
|
|
41
42
|
<script>
|
42
|
-
import
|
43
|
-
{
|
44
|
-
computed,
|
45
|
-
onMounted,
|
46
|
-
ref,
|
47
|
-
} from 'vue';
|
48
|
-
|
43
|
+
import { computed } from 'vue';
|
44
|
+
import { VIcon } from 'vuetify/lib';
|
49
45
|
import VcsActionButtonList from '../buttons/VcsActionButtonList.vue';
|
50
|
-
|
51
|
-
|
52
|
-
const iconTypes = {
|
53
|
-
image: 'HTMLImageElement',
|
54
|
-
canvas: 'HTMLCanvasElement',
|
55
|
-
string: 'StringIcon',
|
56
|
-
};
|
46
|
+
import ImageElementInjector from '../imageElementInjector.vue';
|
57
47
|
|
58
48
|
/**
|
59
49
|
* @description
|
@@ -62,7 +52,11 @@
|
|
62
52
|
* @vue-computed {boolean} leaf - Whether the item is a leaf item or not
|
63
53
|
*/
|
64
54
|
export default {
|
65
|
-
components: {
|
55
|
+
components: {
|
56
|
+
VcsActionButtonList,
|
57
|
+
VIcon,
|
58
|
+
ImageElementInjector,
|
59
|
+
},
|
66
60
|
props: {
|
67
61
|
item: {
|
68
62
|
type: Object,
|
@@ -70,32 +64,10 @@
|
|
70
64
|
},
|
71
65
|
},
|
72
66
|
setup(props) {
|
73
|
-
const iconType = ref();
|
74
|
-
const imgContainer = ref();
|
75
|
-
|
76
67
|
const leaf = computed(() => props.item?.children?.length === 0);
|
77
68
|
|
78
|
-
onMounted(() => { // TODO make icon reactive
|
79
|
-
const { icon } = props.item;
|
80
|
-
if (icon) {
|
81
|
-
if (icon instanceof HTMLImageElement) {
|
82
|
-
imgContainer.value.appendChild(icon);
|
83
|
-
iconType.value = iconTypes.image;
|
84
|
-
}
|
85
|
-
if (icon instanceof HTMLCanvasElement) {
|
86
|
-
imgContainer.value.appendChild(icon);
|
87
|
-
iconType.value = iconTypes.canvas;
|
88
|
-
}
|
89
|
-
if (typeof icon === 'string') {
|
90
|
-
iconType.value = iconTypes.string;
|
91
|
-
}
|
92
|
-
}
|
93
|
-
});
|
94
|
-
|
95
69
|
return {
|
96
|
-
|
97
|
-
iconType,
|
98
|
-
imgContainer,
|
70
|
+
isStringIcon: computed(() => typeof props.item.icon === 'string'),
|
99
71
|
leaf,
|
100
72
|
};
|
101
73
|
},
|
@@ -17,7 +17,7 @@
|
|
17
17
|
class="searchbar outlined rounded-xl align-center d-flex justify-center white pa-1 pl-6"
|
18
18
|
:placeholder="$t(placeholder)"
|
19
19
|
:value="value"
|
20
|
-
|
20
|
+
v-on="$listeners"
|
21
21
|
clearable
|
22
22
|
/>
|
23
23
|
</slot>
|
@@ -104,11 +104,7 @@
|
|
104
104
|
|
105
105
|
|
106
106
|
<script>
|
107
|
-
import {
|
108
|
-
|
109
|
-
import { Subject } from 'rxjs';
|
110
|
-
import { debounceTime } from 'rxjs/operators';
|
111
|
-
|
107
|
+
import { VIcon, VTextField } from 'vuetify/lib';
|
112
108
|
|
113
109
|
/**
|
114
110
|
* @description Stylized wrapper around vuetify divider
|
@@ -117,6 +113,10 @@
|
|
117
113
|
*/
|
118
114
|
export default {
|
119
115
|
name: 'VcsTreeviewSearchbar',
|
116
|
+
components: {
|
117
|
+
VIcon,
|
118
|
+
VTextField,
|
119
|
+
},
|
120
120
|
props: {
|
121
121
|
placeholder: {
|
122
122
|
type: String,
|
@@ -135,22 +135,5 @@
|
|
135
135
|
default: false,
|
136
136
|
},
|
137
137
|
},
|
138
|
-
setup(props, context) {
|
139
|
-
const sub = new Subject();
|
140
|
-
onMounted(() => {
|
141
|
-
sub.pipe(debounceTime(330)).subscribe(
|
142
|
-
(value) => {
|
143
|
-
context.emit('input', value);
|
144
|
-
},
|
145
|
-
);
|
146
|
-
});
|
147
|
-
onUnmounted(() => sub.unsubscribe());
|
148
|
-
|
149
|
-
return {
|
150
|
-
handleInput: (val) => {
|
151
|
-
sub.next(val);
|
152
|
-
},
|
153
|
-
};
|
154
|
-
},
|
155
138
|
};
|
156
139
|
</script>
|
@@ -110,15 +110,17 @@
|
|
110
110
|
</style>
|
111
111
|
<script>
|
112
112
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
113
|
+
import { VTooltip } from 'vuetify/lib';
|
114
|
+
|
115
|
+
/**
|
116
|
+
* @enum {string} TooltipPositions
|
117
|
+
* @property {string} bottom
|
118
|
+
* @property {string} left
|
119
|
+
* @property {string} top
|
120
|
+
* @property {string} right
|
121
|
+
* @readonly
|
122
|
+
* @module VcsTooltip
|
123
|
+
*/
|
122
124
|
const TooltipPositions = {
|
123
125
|
bottom: 'arrow-top',
|
124
126
|
top: 'arrow-bottom',
|
@@ -134,6 +136,9 @@
|
|
134
136
|
*/
|
135
137
|
export default {
|
136
138
|
name: 'VcsTooltip',
|
139
|
+
components: {
|
140
|
+
VTooltip,
|
141
|
+
},
|
137
142
|
props: {
|
138
143
|
tooltip: {
|
139
144
|
type: String,
|