@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
@@ -19,19 +19,19 @@
|
|
19
19
|
>
|
20
20
|
<!-- eslint-disable-next-line -->
|
21
21
|
<template #item.key="{ item }">
|
22
|
-
<td class="vcs-table">
|
22
|
+
<td class="vcs-table px-2 overflow-max-width" :title="$t(item.key)">
|
23
23
|
{{ $t(item.key) }}
|
24
24
|
</td>
|
25
25
|
</template>
|
26
26
|
<!-- eslint-disable-next-line -->
|
27
27
|
<template #item.value="{ item }">
|
28
|
-
<td class="vcs-table">
|
28
|
+
<td class="vcs-table px-2 overflow-max-width" :title="$t(item.value)">
|
29
29
|
{{ $t(item.value) }}
|
30
30
|
</td>
|
31
31
|
</template>
|
32
32
|
<template #footer>
|
33
33
|
<v-divider />
|
34
|
-
<v-container class="pa-2" v-if="items.length > itemsPerPageRef">
|
34
|
+
<v-container class="pa-2 vcs-pagination-bar accent" v-if="items.length > itemsPerPageRef">
|
35
35
|
<v-row
|
36
36
|
dense
|
37
37
|
no-gutters
|
@@ -55,20 +55,23 @@
|
|
55
55
|
v-for="(number, index) in itemsPerPageArray"
|
56
56
|
:key="index"
|
57
57
|
@click="updateItemsPerPage(number)"
|
58
|
+
style="min-height: auto; height: 24px; text-align: right;"
|
58
59
|
>
|
59
60
|
<v-list-item-title>{{ number }}</v-list-item-title>
|
60
61
|
</v-list-item>
|
61
62
|
</v-list>
|
62
63
|
</v-menu>
|
63
|
-
<span class="
|
64
|
-
<span class="
|
64
|
+
<span class="mx-2">{{ $t('components.vcsTable.itemsPerPage') }}</span>
|
65
|
+
<span class="mx-2">
|
66
|
+
{{ itemsFrom }} - {{ itemsTo }} {{ $t('components.vcsTable.ofItems') }} {{ numberOfItems }}
|
67
|
+
</span>
|
65
68
|
<VcsButton
|
66
69
|
small
|
67
70
|
icon="mdi-chevron-left"
|
68
71
|
@click="formerPage"
|
69
72
|
tooltip="components.vcsTable.formerPage"
|
70
73
|
:disabled="page < 2"
|
71
|
-
class="
|
74
|
+
class="ml-1"
|
72
75
|
/>
|
73
76
|
<VcsButton
|
74
77
|
small
|
@@ -76,7 +79,7 @@
|
|
76
79
|
@click="nextPage"
|
77
80
|
tooltip="components.vcsTable.nextPage"
|
78
81
|
:disabled="page > numberOfPages - 1"
|
79
|
-
class="
|
82
|
+
class="ml-1"
|
80
83
|
/>
|
81
84
|
</v-row>
|
82
85
|
</v-container>
|
@@ -86,6 +89,18 @@
|
|
86
89
|
</template>
|
87
90
|
<script>
|
88
91
|
import { getCurrentInstance, ref, computed } from 'vue';
|
92
|
+
import {
|
93
|
+
VCard,
|
94
|
+
VDivider,
|
95
|
+
VContainer,
|
96
|
+
VDataTable,
|
97
|
+
VList,
|
98
|
+
VListItem,
|
99
|
+
VListItemTitle,
|
100
|
+
VMenu,
|
101
|
+
VIcon,
|
102
|
+
VRow,
|
103
|
+
} from 'vuetify/lib';
|
89
104
|
import VcsTreeviewSearchbar from '../lists/VcsTreeviewSearchbar.vue';
|
90
105
|
import VcsButton from '../buttons/VcsButton.vue';
|
91
106
|
|
@@ -116,17 +131,35 @@
|
|
116
131
|
}
|
117
132
|
|
118
133
|
/**
|
119
|
-
* @description A table view for feature attributes using {@link https://vuetifyjs.com/en/api/v-data-table/#props
|
134
|
+
* @description A table view for feature attributes using {@link https://vuetifyjs.com/en/api/v-data-table/#props v-data-table }
|
120
135
|
* @vue-prop {string} featureId - feature's id
|
121
136
|
* @vue-prop {Object} attributes - feature's attributes
|
122
137
|
* @vue-prop {Array<{text: string, value: string}>} [headers] - optional array defining column names
|
123
138
|
* @vue-prop {boolean} [showSearchbar=true] - whether to show searchbar
|
124
139
|
* @vue-prop {string} [searchbarPlaceholder='Search'] - placeholder for searchbar
|
125
|
-
* @vue-computed {Array<
|
140
|
+
* @vue-computed {Array<TableItem>} items - from attributes derived table items
|
141
|
+
* @vue-computed {Array<TableItem>} filteredItems - array of items with search filter applied on. If search string is empty, same as items array.
|
142
|
+
* @vue-computed {number} numberOfItems - number of filtered items (depending on search).
|
143
|
+
* @vue-computed {number} numberOfPages - number of pages depending on number of items, search and itemsPerPage.
|
144
|
+
* @vue-computed {number} itemsFrom - index of first item shown on current page.
|
145
|
+
* @vue-computed {number} itemsTo - index of last item shown on current page.
|
126
146
|
*/
|
127
147
|
export default {
|
128
148
|
name: 'VcsTable',
|
129
|
-
components: {
|
149
|
+
components: {
|
150
|
+
VcsButton,
|
151
|
+
VcsTreeviewSearchbar,
|
152
|
+
VCard,
|
153
|
+
VDataTable,
|
154
|
+
VContainer,
|
155
|
+
VDivider,
|
156
|
+
VRow,
|
157
|
+
VMenu,
|
158
|
+
VIcon,
|
159
|
+
VList,
|
160
|
+
VListItem,
|
161
|
+
VListItemTitle,
|
162
|
+
},
|
130
163
|
props: {
|
131
164
|
featureId: {
|
132
165
|
type: String,
|
@@ -162,7 +195,13 @@
|
|
162
195
|
},
|
163
196
|
setup(props) {
|
164
197
|
const vm = getCurrentInstance().proxy;
|
165
|
-
|
198
|
+
/**
|
199
|
+
* @type {Ref<UnwrapRef<string>>}
|
200
|
+
*/
|
201
|
+
const search = ref('');
|
202
|
+
/**
|
203
|
+
* @type {ComputedRef<Array<TableItem>>}
|
204
|
+
*/
|
166
205
|
const items = computed(() => {
|
167
206
|
return attributesToItems({
|
168
207
|
featureId: props.featureId,
|
@@ -170,6 +209,33 @@
|
|
170
209
|
});
|
171
210
|
});
|
172
211
|
|
212
|
+
/**
|
213
|
+
* @param {any} value
|
214
|
+
* @param {string|undefined} filter
|
215
|
+
* @param {TableItem} item
|
216
|
+
* @returns {boolean}
|
217
|
+
*/
|
218
|
+
const handleFilter = (value, filter, item) => {
|
219
|
+
if (filter) {
|
220
|
+
const q = filter.toLocaleLowerCase();
|
221
|
+
return [item.key, item.value].some((i) => {
|
222
|
+
const content = i.toString();
|
223
|
+
const translated = vm.$t(content);
|
224
|
+
return translated.toLowerCase().includes(q) || content.toLowerCase().includes(q);
|
225
|
+
});
|
226
|
+
}
|
227
|
+
return true;
|
228
|
+
};
|
229
|
+
|
230
|
+
/**
|
231
|
+
* @type {ComputedRef<TableItem[]>}
|
232
|
+
*/
|
233
|
+
const filteredItems = computed(() => items.value.filter(item => handleFilter(item.value, search.value, item)));
|
234
|
+
const numberOfItems = computed(() => filteredItems.value.length);
|
235
|
+
|
236
|
+
/**
|
237
|
+
* @type {ComputedRef<Array<{text: string, value: string}>>}
|
238
|
+
*/
|
173
239
|
const translatedHeaders = computed(() => {
|
174
240
|
return props.headers.map((hd) => {
|
175
241
|
hd.text = vm.$t(hd.text);
|
@@ -177,42 +243,33 @@
|
|
177
243
|
});
|
178
244
|
});
|
179
245
|
|
246
|
+
/**
|
247
|
+
* @type {Ref<UnwrapRef<number>>}
|
248
|
+
*/
|
180
249
|
const itemsPerPageRef = ref(props.itemsPerPage);
|
181
250
|
const numberOfPages = computed(() => {
|
182
|
-
return Math.ceil(
|
251
|
+
return Math.ceil(numberOfItems.value / itemsPerPageRef.value);
|
183
252
|
});
|
184
|
-
|
253
|
+
/**
|
254
|
+
* @type {Ref<UnwrapRef<number>>}
|
255
|
+
*/
|
185
256
|
const page = ref(1);
|
186
257
|
const itemsFrom = computed(() => ((page.value - 1) * itemsPerPageRef.value) + 1);
|
187
258
|
const itemsTo = computed(() => {
|
188
259
|
const last = page.value * itemsPerPageRef.value;
|
189
|
-
return last <
|
260
|
+
return last < numberOfItems.value ? last : numberOfItems.value;
|
190
261
|
});
|
191
262
|
|
192
|
-
/**
|
193
|
-
* @param {any} value
|
194
|
-
* @param {string} search
|
195
|
-
* @param {TableItem} item
|
196
|
-
* @returns {boolean}
|
197
|
-
*/
|
198
|
-
// eslint-disable-next-line default-param-last
|
199
|
-
const handleFilter = (value, search = '', item) => {
|
200
|
-
const q = search.toLocaleLowerCase();
|
201
|
-
return [item.key, item.value].some((i) => {
|
202
|
-
const content = i.toString();
|
203
|
-
const translated = vm.$t(content);
|
204
|
-
return translated.toLowerCase().includes(q) || content.toLowerCase().includes(q);
|
205
|
-
});
|
206
|
-
};
|
207
|
-
|
208
263
|
return {
|
209
|
-
search
|
264
|
+
search,
|
210
265
|
page,
|
211
266
|
items,
|
267
|
+
filteredItems,
|
212
268
|
itemsPerPageRef,
|
213
269
|
itemsFrom,
|
214
270
|
itemsTo,
|
215
271
|
numberOfPages,
|
272
|
+
numberOfItems,
|
216
273
|
nextPage() {
|
217
274
|
if (page.value + 1 <= numberOfPages.value) {
|
218
275
|
page.value += 1;
|
@@ -233,13 +290,47 @@
|
|
233
290
|
};
|
234
291
|
</script>
|
235
292
|
|
236
|
-
<style lang="scss"
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
293
|
+
<style lang="scss" scoped>
|
294
|
+
::v-deep{
|
295
|
+
.vcs-table {
|
296
|
+
td {
|
297
|
+
overflow: hidden;
|
298
|
+
text-overflow: ellipsis;
|
299
|
+
white-space: nowrap;
|
300
|
+
&.overflow-max-width{
|
301
|
+
max-width: 160px;
|
302
|
+
}
|
303
|
+
&.v-data-table__mobile-row{
|
304
|
+
justify-content: left;
|
305
|
+
height: 27px;
|
306
|
+
min-height: auto;
|
307
|
+
}
|
308
|
+
}
|
309
|
+
th.sortable{
|
310
|
+
padding: 0 8px;
|
311
|
+
span{
|
312
|
+
vertical-align: middle;
|
313
|
+
padding: 0 4px 0 0;
|
314
|
+
}
|
315
|
+
}
|
316
|
+
}
|
317
|
+
.v-data-table__mobile-row__cell{
|
318
|
+
td.vcs-table.overflow-max-width{
|
319
|
+
max-width: 260px;
|
320
|
+
}
|
321
|
+
}
|
322
|
+
.v-btn.vcs-button--small{
|
323
|
+
height: 100% !important;
|
324
|
+
display: block;
|
325
|
+
}
|
326
|
+
}
|
327
|
+
.vcs-pagination-bar{
|
328
|
+
.vcs-button-wrap{
|
329
|
+
height: 25px;
|
330
|
+
border: 1px solid lightgrey;
|
331
|
+
padding: 0 4px;
|
332
|
+
background-color: var(--v-basic-base);
|
333
|
+
border-radius: 4px;
|
243
334
|
}
|
244
335
|
}
|
245
336
|
</style>
|
@@ -7,30 +7,30 @@ import { createStateRefAction, StateActionState } from '../actions/stateRefActio
|
|
7
7
|
|
8
8
|
/**
|
9
9
|
* @typedef {Object} ContentTreeItemOptions
|
10
|
-
* @property {string} name
|
10
|
+
* @property {string} name - name of the item defining the structure within the tree using dot notation.
|
11
11
|
* @property {string} [title] - may be unset, if set from object properties later on. required otherwise
|
12
12
|
* @property {string} [tooltip] - may be unset or set from object properties later on.
|
13
|
-
* @property {string|HTMLCanvasElement|HTMLImageElement|undefined} icon - an icon URL or element to display
|
14
|
-
* @property {number} [weight]
|
15
|
-
* @property {string} [infoUrl]
|
16
|
-
* @property {boolean} [initOpen=false]
|
13
|
+
* @property {string|HTMLCanvasElement|HTMLImageElement|undefined} icon - an icon URL or element to display.
|
14
|
+
* @property {number} [weight] - optional weighting of the item. higher weights come first.
|
15
|
+
* @property {string} [infoUrl] - optional info url providing link with additional information.
|
16
|
+
* @property {boolean} [initOpen=false] - groups being initially open or not.
|
17
17
|
*/
|
18
18
|
|
19
19
|
/**
|
20
20
|
* A readonly rendering interface of a ContentTreeItem.
|
21
21
|
* @typedef {Object} TreeViewItem
|
22
22
|
* @property {string} name
|
23
|
-
* @property {boolean} visible
|
24
|
-
* @property {boolean} clickable
|
25
|
-
* @property {boolean} disabled
|
26
|
-
* @property {StateActionState} state
|
27
|
-
* @property {string} title
|
23
|
+
* @property {boolean} visible - Whether to display this item or not.
|
24
|
+
* @property {boolean} clickable - Whether this item reacts to click events, e.g. with visual feedback
|
25
|
+
* @property {boolean} disabled - Whether this item should be displayed as disabled.
|
26
|
+
* @property {StateActionState} state - The state of this item. NONE if this item cannot have a state.
|
27
|
+
* @property {string} title - The title to be displayed
|
28
28
|
* @property {string} [tooltip]
|
29
|
-
* @property {string|HTMLCanvasElement|HTMLImageElement|undefined} icon
|
29
|
+
* @property {string|HTMLCanvasElement|HTMLImageElement|undefined} [icon] - An optional icon to display with this item. Can be an URL or HTMLElement.
|
30
30
|
* @property {Array<VcsAction>} actions
|
31
31
|
* @property {Array<TreeViewItem>} children
|
32
32
|
* @property {Array<TreeViewItem>} visibleChildren - computed property
|
33
|
-
* @property {function():Promise<void>} clicked
|
33
|
+
* @property {function(PointerEvent):Promise<void>} clicked - A callback called once the item is clicked.
|
34
34
|
*/
|
35
35
|
|
36
36
|
/**
|
@@ -376,7 +376,7 @@ class ContentTreeItem {
|
|
376
376
|
* GoToExtent: 8
|
377
377
|
* The default weight is set to always push new actions past these.
|
378
378
|
* @param {VcsAction} action
|
379
|
-
* @param {number} [weight=
|
379
|
+
* @param {number} [weight=11]
|
380
380
|
*/
|
381
381
|
addAction(action, weight = 11) {
|
382
382
|
check(action.name, String);
|
@@ -6,7 +6,7 @@ import ContentTreeItem, { contentTreeClassRegistry } from './contentTreeItem.js'
|
|
6
6
|
export const subTreeSymbol = Symbol('SubTree');
|
7
7
|
|
8
8
|
/**
|
9
|
-
* A
|
9
|
+
* A subtree item. Subtrees are rendered in their own (not the main content tree).
|
10
10
|
* They will receive their own toggle button in the nav bar.
|
11
11
|
* Only toplevel items can be content tree items (with a name which does not have a .)
|
12
12
|
* @class
|
@@ -9,7 +9,7 @@ import ContentTreeItem, { contentTreeClassRegistry } from './contentTreeItem.js'
|
|
9
9
|
|
10
10
|
/**
|
11
11
|
* An abstract class for VcsObject based items.
|
12
|
-
* It
|
12
|
+
* It handles the overriding/setting of its own values based on
|
13
13
|
* the VcsObjects properties bag.
|
14
14
|
* @class
|
15
15
|
* @template {VcsObjectContentTreeItemProperties} T
|
@@ -31,6 +31,14 @@
|
|
31
31
|
</template>
|
32
32
|
<script>
|
33
33
|
|
34
|
+
import {
|
35
|
+
VIcon,
|
36
|
+
VListItem,
|
37
|
+
VListItemAvatar,
|
38
|
+
VListItemContent,
|
39
|
+
VListItemSubtitle,
|
40
|
+
VListItemTitle,
|
41
|
+
} from 'vuetify/lib';
|
34
42
|
import BalloonComponent from './BalloonComponent.vue';
|
35
43
|
|
36
44
|
/**
|
@@ -38,7 +46,15 @@
|
|
38
46
|
*/
|
39
47
|
export default {
|
40
48
|
name: 'AddressBalloonComponent',
|
41
|
-
components: {
|
49
|
+
components: {
|
50
|
+
BalloonComponent,
|
51
|
+
VListItem,
|
52
|
+
VListItemAvatar,
|
53
|
+
VIcon,
|
54
|
+
VListItemContent,
|
55
|
+
VListItemTitle,
|
56
|
+
VListItemSubtitle,
|
57
|
+
},
|
42
58
|
};
|
43
59
|
</script>
|
44
60
|
|
@@ -1,40 +1,43 @@
|
|
1
1
|
<template>
|
2
2
|
<v-card
|
3
|
-
class="mx-auto"
|
3
|
+
class="mx-auto mb-1 elevation-0"
|
4
4
|
max-width="400"
|
5
5
|
v-if="position"
|
6
6
|
>
|
7
7
|
<slot name="balloon-header" :attrs="{...$props, ...$attrs}">
|
8
|
-
<v-list-item
|
8
|
+
<v-list-item class="px-2 pr-1 align-start">
|
9
9
|
<v-list-item-avatar
|
10
10
|
tile
|
11
|
-
size="
|
11
|
+
size="20"
|
12
|
+
class="mr-2 align-self-start"
|
12
13
|
>
|
13
14
|
<v-icon color="primary">
|
14
15
|
$vcsInfo
|
15
16
|
</v-icon>
|
16
17
|
</v-list-item-avatar>
|
17
|
-
<v-list-item-content>
|
18
|
-
<v-list-item-title class="text-
|
19
|
-
{{
|
18
|
+
<v-list-item-content class="py-2 pr-1 align-self-start">
|
19
|
+
<v-list-item-title class="text-h6">
|
20
|
+
{{ $t(balloonTitle) }}
|
20
21
|
</v-list-item-title>
|
21
|
-
<v-list-item-subtitle
|
22
|
+
<v-list-item-subtitle v-if="balloonSubtitle">
|
23
|
+
{{ $t(balloonSubtitle) }}
|
24
|
+
</v-list-item-subtitle>
|
22
25
|
</v-list-item-content>
|
23
26
|
<VcsButton
|
24
27
|
@click.stop="close"
|
25
28
|
small
|
26
29
|
icon="mdi-close-thick"
|
27
|
-
|
30
|
+
tooltip="components.close"
|
28
31
|
/>
|
29
32
|
</v-list-item>
|
30
33
|
</slot>
|
31
34
|
|
32
35
|
<v-divider />
|
33
36
|
|
34
|
-
<v-card class="overflow-y-auto" max-height="250">
|
37
|
+
<v-card class="overflow-y-auto py-2 elevation-0" max-height="250">
|
35
38
|
<slot :attrs="{...$props, ...$attrs}">
|
36
39
|
<v-list v-for="(value, name, index) in attributes" :key="`attribute-${index}`">
|
37
|
-
<v-list-item>
|
40
|
+
<v-list-item class="px-2">
|
38
41
|
<v-list-item-content>
|
39
42
|
<v-list-item-title>
|
40
43
|
{{ name }}
|
@@ -50,6 +53,16 @@
|
|
50
53
|
<script>
|
51
54
|
|
52
55
|
import { inject, onMounted, onUnmounted, watch } from 'vue';
|
56
|
+
import {
|
57
|
+
VCard, VDivider,
|
58
|
+
VIcon,
|
59
|
+
VList,
|
60
|
+
VListItem,
|
61
|
+
VListItemAvatar,
|
62
|
+
VListItemContent,
|
63
|
+
VListItemSubtitle,
|
64
|
+
VListItemTitle,
|
65
|
+
} from 'vuetify/lib';
|
53
66
|
import { setupBalloonPositionListener } from './balloonHelper.js';
|
54
67
|
import VcsButton from '../components/buttons/VcsButton.vue';
|
55
68
|
|
@@ -57,8 +70,8 @@
|
|
57
70
|
* @description A balloon viewing feature attributes. Size dynamic dependent on number of attributes.
|
58
71
|
* Scrollable, if more than 6 attributes are provided.
|
59
72
|
* @vue-prop {string} featureId - feature's id
|
60
|
-
* @vue-prop {string}
|
61
|
-
* @vue-prop {string}
|
73
|
+
* @vue-prop {string} balloonTitle - balloon title
|
74
|
+
* @vue-prop {string} balloonSubtitle - balloon subtitle
|
62
75
|
* @vue-prop {Object} attributes - feature's attributes
|
63
76
|
* @vue-prop {Array<import("ol/coordinate").Coordinate>} position - clicked position balloon is rendered at
|
64
77
|
* @vue-data {slot} [#balloon-header] - slot to override balloon header, $props and $attrs are passed to `attrs`
|
@@ -66,17 +79,28 @@
|
|
66
79
|
*/
|
67
80
|
export default {
|
68
81
|
name: 'BalloonComponent',
|
69
|
-
components: {
|
82
|
+
components: {
|
83
|
+
VcsButton,
|
84
|
+
VCard,
|
85
|
+
VList,
|
86
|
+
VListItem,
|
87
|
+
VListItemAvatar,
|
88
|
+
VIcon,
|
89
|
+
VListItemContent,
|
90
|
+
VListItemTitle,
|
91
|
+
VListItemSubtitle,
|
92
|
+
VDivider,
|
93
|
+
},
|
70
94
|
props: {
|
71
95
|
featureId: {
|
72
96
|
type: String,
|
73
97
|
required: true,
|
74
98
|
},
|
75
|
-
|
99
|
+
balloonTitle: {
|
76
100
|
type: String,
|
77
101
|
required: true,
|
78
102
|
},
|
79
|
-
|
103
|
+
balloonSubtitle: {
|
80
104
|
type: String,
|
81
105
|
required: true,
|
82
106
|
},
|
@@ -125,16 +149,28 @@
|
|
125
149
|
};
|
126
150
|
</script>
|
127
151
|
|
128
|
-
<style>
|
129
|
-
.balloon:
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
152
|
+
<style lang="scss">
|
153
|
+
.balloon hr:first-child {
|
154
|
+
display: none;
|
155
|
+
}
|
156
|
+
.balloon:after {
|
157
|
+
content: "";
|
158
|
+
position: absolute;
|
159
|
+
bottom: -20px;
|
160
|
+
left: 40px;
|
161
|
+
border-width: 20px 20px 0;
|
162
|
+
border-style: solid;
|
163
|
+
display: block;
|
164
|
+
width: 0;
|
165
|
+
}
|
166
|
+
.v-sheet.theme--light.balloon:after{
|
167
|
+
border-color: #FFFFFF transparent;
|
168
|
+
}
|
169
|
+
.v-sheet.theme--dark.balloon:after{
|
170
|
+
border-color: #1E1E1E transparent;
|
171
|
+
}
|
172
|
+
.balloon .v-list-item .v-list-item__title,
|
173
|
+
.balloon .v-list-item .v-list-item__subtitle {
|
174
|
+
line-height: 18px;
|
175
|
+
}
|
140
176
|
</style>
|
@@ -26,14 +26,14 @@ export function extractNestedKey(key, attrs, defaultValue = null) {
|
|
26
26
|
|
27
27
|
/**
|
28
28
|
* @typedef {FeatureInfoViewOptions} BalloonFeatureInfoViewOptions
|
29
|
-
* @property {string} [
|
30
|
-
* @property {string} [
|
29
|
+
* @property {string} [balloonTitle] - optional title to overwrite default (layerName). Can be attribute key (nested key using '.'), i18n key or text
|
30
|
+
* @property {string} [balloonSubtitle] - optional window title to overwrite default (featureId). Can be attribute key (nested key using '.'), i18n key or text
|
31
31
|
*/
|
32
32
|
|
33
33
|
/**
|
34
34
|
* @typedef {FeatureInfoProps} BalloonFeatureInfoViewProps
|
35
|
-
* @property {string}
|
36
|
-
* @property {string}
|
35
|
+
* @property {string} balloonTitle
|
36
|
+
* @property {string} balloonSubtitle
|
37
37
|
* @property {import("ol/coordinate").Coordinate} position
|
38
38
|
*/
|
39
39
|
|
@@ -87,12 +87,12 @@ class BalloonFeatureInfoView extends AbstractFeatureInfoView {
|
|
87
87
|
/**
|
88
88
|
* @type {string}
|
89
89
|
*/
|
90
|
-
this.
|
90
|
+
this.balloonTitle = options.balloonTitle;
|
91
91
|
|
92
92
|
/**
|
93
93
|
* @type {string}
|
94
94
|
*/
|
95
|
-
this.
|
95
|
+
this.balloonSubtitle = options.balloonSubtitle;
|
96
96
|
}
|
97
97
|
|
98
98
|
/**
|
@@ -105,11 +105,11 @@ class BalloonFeatureInfoView extends AbstractFeatureInfoView {
|
|
105
105
|
return {
|
106
106
|
...properties,
|
107
107
|
position: featureInfo.position ?? getPositionFromFeature(featureInfo.feature),
|
108
|
-
|
109
|
-
extractNestedKey(this.
|
108
|
+
balloonTitle: this.balloonTitle != null ?
|
109
|
+
extractNestedKey(this.balloonTitle, properties.attributes, this.balloonTitle) :
|
110
110
|
properties.layerProperties.title,
|
111
|
-
|
112
|
-
extractNestedKey(this.
|
111
|
+
balloonSubtitle: this.balloonSubtitle != null ?
|
112
|
+
extractNestedKey(this.balloonSubtitle, properties.attributes, this.balloonSubtitle) :
|
113
113
|
properties.featureId,
|
114
114
|
};
|
115
115
|
}
|
@@ -138,11 +138,11 @@ class BalloonFeatureInfoView extends AbstractFeatureInfoView {
|
|
138
138
|
*/
|
139
139
|
toJSON() {
|
140
140
|
const config = super.toJSON();
|
141
|
-
if (this.
|
142
|
-
config.
|
141
|
+
if (this.balloonTitle) {
|
142
|
+
config.balloonTitle = this.balloonTitle;
|
143
143
|
}
|
144
|
-
if (this.
|
145
|
-
config.
|
144
|
+
if (this.balloonSubtitle) {
|
145
|
+
config.balloonSubtitle = this.balloonSubtitle;
|
146
146
|
}
|
147
147
|
return config;
|
148
148
|
}
|
@@ -99,6 +99,10 @@ export async function setupBalloonPositionListener(vcsApp, windowId, clickedPosi
|
|
99
99
|
|
100
100
|
const map = app.maps.activeMap;
|
101
101
|
if (map instanceof CesiumMap) {
|
102
|
+
if (!position[2]) {
|
103
|
+
const [position3D] = await map.getHeightFromTerrain([position]);
|
104
|
+
position[2] = position3D[2];
|
105
|
+
}
|
102
106
|
const wgs84Position = Projection.mercatorToWgs84(position);
|
103
107
|
const cartesian = Cartographic.toCartesian(Cartographic.fromDegrees(...wgs84Position));
|
104
108
|
listeners.push(map.getScene().postRender.addEventListener((scene) => {
|