@vcmap/ui 6.2.3 → 6.2.4
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/config/dev.config.json +365 -1
- package/dist/assets/cesium.js +1 -1
- package/dist/assets/{core-f4ee6bea.js → core-b61fb7c0.js} +10577 -8847
- package/dist/assets/core-workers/panoramaImageWorker.js +1 -1
- package/dist/assets/core.js +1 -1
- package/dist/assets/ol.js +1 -1
- package/dist/assets/{ui-d3a7bd39.css → ui-f33a5ee2.css} +1 -1
- package/dist/assets/{ui-d3a7bd39.js → ui-f33a5ee2.js} +3839 -3803
- package/dist/assets/ui.js +1 -1
- package/dist/assets/vue.js +1 -1
- package/dist/assets/{vuetify-8e1623b2.js → vuetify-2fc014c4.js} +1 -1
- package/dist/assets/vuetify.js +1 -1
- package/index.d.ts +3 -1
- package/index.js +1 -1
- package/package.json +1 -1
- package/plugins/@vcmap-show-case/extent-example/src/ExtentExample.vue +28 -0
- package/plugins/@vcmap-show-case/extent-example/src/index.js +3 -14
- package/src/actions/actionHelper.d.ts +0 -1
- package/src/actions/actionHelper.js +3 -3
- package/src/components/extent/VcsExtent.vue +12 -1
- package/src/components/extent/VcsExtent.vue.d.ts +1 -0
- package/src/contentTree/contentTreeItem.js +1 -1
- package/src/contentTree/wmsGroupContentTreeItem.d.ts +52 -6
- package/src/contentTree/wmsGroupContentTreeItem.js +128 -28
- package/src/i18n/de.d.ts +1 -0
- package/src/i18n/de.js +1 -0
- package/src/i18n/en.d.ts +1 -0
- package/src/i18n/en.js +1 -0
- package/src/manager/collectionManager/CollectionManager.vue +14 -1
- package/src/search/SearchComponent.vue +9 -11
- package/src/search/SearchComponent.vue.d.ts +2 -1
- /package/dist/assets/{cesium-dcdef786.js → cesium-bc979301.js} +0 -0
- /package/dist/assets/core-workers/{panoramaImageWorker.js-a6bb36f6.js → panoramaImageWorker.js-2cf50d2d.js} +0 -0
- /package/dist/assets/{ol-f7a5160f.js → ol-28f9c83c.js} +0 -0
- /package/dist/assets/{vue-cbd2bd60.js → vue-004523e0.js} +0 -0
- /package/dist/assets/{vuetify-8e1623b2.css → vuetify-2fc014c4.css} +0 -0
package/dist/assets/ui.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from "./ui-
|
|
1
|
+
export * from "./ui-f33a5ee2.js";
|
package/dist/assets/vue.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from "./vue-
|
|
1
|
+
export * from "./vue-004523e0.js";
|
|
@@ -10,7 +10,7 @@ function loadCss(href) {
|
|
|
10
10
|
elem.onerror = reject;
|
|
11
11
|
document.head.appendChild(elem);
|
|
12
12
|
});
|
|
13
|
-
} await loadCss('./assets/vuetify-
|
|
13
|
+
} await loadCss('./assets/vuetify-2fc014c4.css');import { watch as Q, onScopeDispose as Ze, effectScope as Zl, shallowRef as K, Fragment as ie, reactive as it, computed as b, watchEffect as Fe, toRefs as Yt, capitalize as Nn, isVNode as Rc, Comment as Nc, unref as ot, warn as ja, getCurrentInstance as Hc, ref as j, provide as De, inject as ye, defineComponent as zc, camelize as Ir, h as Gt, toRaw as Be, createVNode as r, mergeProps as O, onBeforeUnmount as Qe, readonly as Ql, onDeactivated as _r, onActivated as Wc, onMounted as Ye, nextTick as we, TransitionGroup as Jl, Transition as jt, isRef as Tn, toRef as $, onBeforeMount as ra, withDirectives as $e, resolveDirective as gt, vShow as Ct, onUpdated as jc, Text as Uc, resolveDynamicComponent as Yc, markRaw as Gc, Teleport as Kc, cloneVNode as qc, createTextVNode as Tt, onUnmounted as Tr, onBeforeUpdate as Xc, withModifiers as Tl, toDisplayString as Zc, vModelText as Qc, resolveComponent as Jc, render as Ar } from "./vue-004523e0.js";
|
|
14
14
|
function rt(e, n) {
|
|
15
15
|
let t;
|
|
16
16
|
function a() {
|
package/dist/assets/vuetify.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from "./vuetify-
|
|
1
|
+
export * from "./vuetify-2fc014c4.js";
|
package/index.d.ts
CHANGED
|
@@ -279,13 +279,15 @@ export { default as VcsSplashScreen } from "./src/application/VcsSplashScreen.vu
|
|
|
279
279
|
export type * from "./src/application/VcsSplashScreen.vue.d.ts";
|
|
280
280
|
export { default as Search } from "./src/search/search.js";
|
|
281
281
|
export type * from "./src/search/search.d.ts";
|
|
282
|
+
export { searchComponentId } from "./src/search/SearchComponent.vue";
|
|
283
|
+
export type * from "./src/search/SearchComponent.vue.d.ts";
|
|
282
284
|
export { markText } from "./src/search/markText.js";
|
|
283
285
|
export type * from "./src/search/markText.d.ts";
|
|
284
286
|
export { default as ResultItemComponent } from "./src/search/ResultItem.vue";
|
|
285
287
|
export type * from "./src/search/ResultItem.vue.d.ts";
|
|
286
288
|
export { default as ResultsComponent } from "./src/search/ResultsComponent.vue";
|
|
287
289
|
export type * from "./src/search/ResultsComponent.vue.d.ts";
|
|
288
|
-
export { addLoadingOverlay, callSafeAction, createMapButtonAction, createToggleAction, createModalAction, createLinkAction, createGoToViewpointAction, createZoomToFeatureAction
|
|
290
|
+
export { addLoadingOverlay, callSafeAction, createMapButtonAction, createToggleAction, createModalAction, createLinkAction, createGoToViewpointAction, createZoomToFeatureAction } from "./src/actions/actionHelper.js";
|
|
289
291
|
export type * from "./src/actions/actionHelper.d.ts";
|
|
290
292
|
export { createDeepPickingAction, deepPickingWindowId } from "./src/actions/deepPickingAction.js";
|
|
291
293
|
export type * from "./src/actions/deepPickingAction.d.ts";
|
package/index.js
CHANGED
|
@@ -11,7 +11,6 @@ export {
|
|
|
11
11
|
createLinkAction,
|
|
12
12
|
createGoToViewpointAction,
|
|
13
13
|
createZoomToFeatureAction,
|
|
14
|
-
searchComponentId,
|
|
15
14
|
} from './src/actions/actionHelper.js';
|
|
16
15
|
export {
|
|
17
16
|
createDeepPickingAction,
|
|
@@ -377,6 +376,7 @@ export {
|
|
|
377
376
|
getLegendEntries,
|
|
378
377
|
} from './src/legend/legendHelper.js';
|
|
379
378
|
export { default as Search } from './src/search/search.js';
|
|
379
|
+
export { searchComponentId } from './src/search/SearchComponent.vue';
|
|
380
380
|
export { markText } from './src/search/markText.js';
|
|
381
381
|
export { default as ResultItemComponent } from './src/search/ResultItem.vue';
|
|
382
382
|
export { default as ResultsComponent } from './src/search/ResultsComponent.vue';
|
package/package.json
CHANGED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-container class="pa-0">
|
|
3
|
+
<VcsExtentEditor heading="Default WGS84 projection" v-model="wgs84Extent" />
|
|
4
|
+
<VcsExtentEditor
|
|
5
|
+
heading="Mercator projection example"
|
|
6
|
+
v-model="mercatorExtent"
|
|
7
|
+
/>
|
|
8
|
+
</v-container>
|
|
9
|
+
</template>
|
|
10
|
+
<script>
|
|
11
|
+
import { VcsExtentEditor } from '@vcmap/ui';
|
|
12
|
+
import { VContainer } from 'vuetify/components';
|
|
13
|
+
import { Extent, mercatorProjection, wgs84Projection } from '@vcmap/core';
|
|
14
|
+
|
|
15
|
+
export default {
|
|
16
|
+
name: 'ExtentExample',
|
|
17
|
+
components: { VcsExtentEditor, VContainer },
|
|
18
|
+
setup() {
|
|
19
|
+
const wgs84Extent = new Extent({ projection: wgs84Projection }).toJSON();
|
|
20
|
+
const mercatorExtent = new Extent({
|
|
21
|
+
projection: mercatorProjection,
|
|
22
|
+
}).toJSON();
|
|
23
|
+
|
|
24
|
+
return { wgs84Extent, mercatorExtent };
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
</script>
|
|
28
|
+
<style lang="scss" scoped></style>
|
|
@@ -1,19 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ButtonLocation,
|
|
3
|
-
createToggleAction,
|
|
4
|
-
WindowSlot,
|
|
5
|
-
VcsExtentEditor,
|
|
6
|
-
} from '@vcmap/ui';
|
|
7
|
-
import { Extent } from '@vcmap/core';
|
|
8
|
-
import { reactive } from 'vue';
|
|
1
|
+
import { ButtonLocation, createToggleAction, WindowSlot } from '@vcmap/ui';
|
|
9
2
|
import packageJSON from '../package.json';
|
|
3
|
+
import ExtentExample from './ExtentExample.vue';
|
|
10
4
|
|
|
11
5
|
/**
|
|
12
6
|
* @returns {VcsPlugin}
|
|
13
7
|
*/
|
|
14
8
|
export default async function extentExample() {
|
|
15
|
-
const modelValue = reactive(new Extent().toJSON());
|
|
16
|
-
|
|
17
9
|
return {
|
|
18
10
|
get name() {
|
|
19
11
|
return packageJSON.name;
|
|
@@ -33,15 +25,12 @@ export default async function extentExample() {
|
|
|
33
25
|
},
|
|
34
26
|
{
|
|
35
27
|
id: 'extent-example',
|
|
36
|
-
component:
|
|
28
|
+
component: ExtentExample,
|
|
37
29
|
slot: WindowSlot.DYNAMIC_LEFT,
|
|
38
30
|
state: {
|
|
39
31
|
headerTitle: 'Extent Example',
|
|
40
32
|
headerIcon: '$vcsBoundingBox',
|
|
41
33
|
},
|
|
42
|
-
props: {
|
|
43
|
-
modelValue,
|
|
44
|
-
},
|
|
45
34
|
},
|
|
46
35
|
app.windowManager,
|
|
47
36
|
packageJSON.name,
|
|
@@ -118,7 +118,6 @@ export function addLoadingOverlay(app: import("../vcsUiApp.js").default, owner:
|
|
|
118
118
|
maxWidth?: string | number | undefined;
|
|
119
119
|
persistent?: boolean | undefined;
|
|
120
120
|
} | undefined): () => void;
|
|
121
|
-
export const searchComponentId: "searchId";
|
|
122
121
|
export type ActionOptions = Omit<VcsAction, 'callback'>;
|
|
123
122
|
export type ActionCallback = (p?: PointerEvent) => (void | Promise<void>);
|
|
124
123
|
export type VcsAction = {
|
|
@@ -18,7 +18,9 @@ import {
|
|
|
18
18
|
getFittedWindowPositionOptions,
|
|
19
19
|
getTargetSize,
|
|
20
20
|
} from '../manager/window/windowHelper.js';
|
|
21
|
-
import SearchComponent
|
|
21
|
+
import SearchComponent, {
|
|
22
|
+
searchComponentId,
|
|
23
|
+
} from '../search/SearchComponent.vue';
|
|
22
24
|
import VcsLoadingOverlay from '../components/plugins/VcsLoadingOverlay.vue';
|
|
23
25
|
|
|
24
26
|
/**
|
|
@@ -215,8 +217,6 @@ export function createToggleAction(
|
|
|
215
217
|
return { action, destroy };
|
|
216
218
|
}
|
|
217
219
|
|
|
218
|
-
export const searchComponentId = 'searchId';
|
|
219
|
-
|
|
220
220
|
/**
|
|
221
221
|
* @param {import("../vcsUiApp.js").default} app
|
|
222
222
|
* @returns {{action: import("vue").UnwrapRef<VcsAction>, destroy: function():void}}
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
hide-z
|
|
19
19
|
v-model="min"
|
|
20
20
|
:disabled="disabled"
|
|
21
|
+
:extent="extent"
|
|
21
22
|
:axis-rules="[
|
|
22
23
|
[(v) => checkInput(v, max[0])],
|
|
23
24
|
[(v) => checkInput(v, max[1])],
|
|
@@ -35,6 +36,7 @@
|
|
|
35
36
|
hide-z
|
|
36
37
|
v-model="max"
|
|
37
38
|
:disabled="disabled"
|
|
39
|
+
:extent="extent"
|
|
38
40
|
:axis-rules="[
|
|
39
41
|
[(v) => checkInput(min[0], v)],
|
|
40
42
|
[(v) => checkInput(min[1], v)],
|
|
@@ -54,7 +56,7 @@
|
|
|
54
56
|
<script>
|
|
55
57
|
import { computed, toRaw } from 'vue';
|
|
56
58
|
import { VCol, VContainer, VRow } from 'vuetify/components';
|
|
57
|
-
import { Extent } from '@vcmap/core';
|
|
59
|
+
import { Extent, Projection } from '@vcmap/core';
|
|
58
60
|
import VcsLabel from '../form-inputs-controls/VcsLabel.vue';
|
|
59
61
|
import VcsTextField from '../form-inputs-controls/VcsTextField.vue';
|
|
60
62
|
import VcsCoordinate from '../form-inputs-controls/VcsCoordinate.vue';
|
|
@@ -100,6 +102,14 @@
|
|
|
100
102
|
setup(props, { emit }) {
|
|
101
103
|
const localValue = useProxiedComplexModel(props, 'modelValue', emit);
|
|
102
104
|
|
|
105
|
+
const { proj } = new Projection(localValue.value.projection);
|
|
106
|
+
const extent = proj.getExtent() || [
|
|
107
|
+
-Infinity,
|
|
108
|
+
-Infinity,
|
|
109
|
+
Infinity,
|
|
110
|
+
Infinity,
|
|
111
|
+
];
|
|
112
|
+
|
|
103
113
|
const getCoordinate = (start, end = 4) =>
|
|
104
114
|
computed({
|
|
105
115
|
get() {
|
|
@@ -121,6 +131,7 @@
|
|
|
121
131
|
min: getCoordinate(0, 2),
|
|
122
132
|
max: getCoordinate(2),
|
|
123
133
|
checkInput,
|
|
134
|
+
extent,
|
|
124
135
|
cid,
|
|
125
136
|
};
|
|
126
137
|
},
|
|
@@ -15,6 +15,7 @@ declare const _default: import("vue").DefineComponent<{
|
|
|
15
15
|
min: import("vue").WritableComputedRef<any>;
|
|
16
16
|
max: import("vue").WritableComputedRef<any>;
|
|
17
17
|
checkInput: typeof checkInput;
|
|
18
|
+
extent: import("ol/extent.js", { with: { "resolution-mode": "import" } }).Extent;
|
|
18
19
|
cid: string;
|
|
19
20
|
}, any, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, "update:modelValue"[], "update:modelValue", import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
20
21
|
modelValue: {
|
|
@@ -436,7 +436,7 @@ class ContentTreeItem {
|
|
|
436
436
|
removeAction(actionName) {
|
|
437
437
|
const index = this._getActionIndex(actionName);
|
|
438
438
|
if (index > -1) {
|
|
439
|
-
this._actions.value.
|
|
439
|
+
this._actions.value = this._actions.value.filter((_, i) => i !== index);
|
|
440
440
|
}
|
|
441
441
|
}
|
|
442
442
|
|
|
@@ -16,9 +16,31 @@ export type WMSEntry = {
|
|
|
16
16
|
name: string;
|
|
17
17
|
active: import("vue").Ref<boolean>;
|
|
18
18
|
activeStyle: import("vue").Ref<string>;
|
|
19
|
-
title
|
|
20
|
-
extent
|
|
21
|
-
styles
|
|
19
|
+
title?: string | undefined;
|
|
20
|
+
extent?: import("@vcmap/core").Extent | undefined;
|
|
21
|
+
styles?: WMSStyleEntry[] | undefined;
|
|
22
|
+
};
|
|
23
|
+
export type SerializedWMSLegend = {
|
|
24
|
+
url: string;
|
|
25
|
+
width: number;
|
|
26
|
+
height: number;
|
|
27
|
+
};
|
|
28
|
+
export type SerializedWMSStyle = {
|
|
29
|
+
name: string;
|
|
30
|
+
title?: string | undefined;
|
|
31
|
+
legend?: SerializedWMSLegend[] | undefined;
|
|
32
|
+
};
|
|
33
|
+
export type SerializedWMSLayer = {
|
|
34
|
+
name: string;
|
|
35
|
+
title?: string | undefined;
|
|
36
|
+
/**
|
|
37
|
+
* Layer extent, in WGS84 coordinates
|
|
38
|
+
*/
|
|
39
|
+
extent?: number[] | undefined;
|
|
40
|
+
styles?: SerializedWMSStyle[] | undefined;
|
|
41
|
+
};
|
|
42
|
+
export type SerializedWMSCapabilities = {
|
|
43
|
+
layers: Array<SerializedWMSLayer>;
|
|
22
44
|
};
|
|
23
45
|
/**
|
|
24
46
|
* @typedef {import('./contentTreeItem.js').ContentTreeItemOptions &
|
|
@@ -41,9 +63,33 @@ export type WMSEntry = {
|
|
|
41
63
|
* @property {string} name
|
|
42
64
|
* @property {import("vue").Ref<boolean>} active
|
|
43
65
|
* @property {import("vue").Ref<string>} activeStyle
|
|
44
|
-
* @property {string} title
|
|
45
|
-
* @property {import("@vcmap/core").Extent} extent
|
|
46
|
-
* @property {Array<WMSStyleEntry>} styles
|
|
66
|
+
* @property {string} [title]
|
|
67
|
+
* @property {import("@vcmap/core").Extent} [extent]
|
|
68
|
+
* @property {Array<WMSStyleEntry>} [styles]
|
|
69
|
+
*/
|
|
70
|
+
/**
|
|
71
|
+
* @typedef {Object} SerializedWMSLegend
|
|
72
|
+
* @property {string} url
|
|
73
|
+
* @property {number} width
|
|
74
|
+
* @property {number} height
|
|
75
|
+
*/
|
|
76
|
+
/**
|
|
77
|
+
* @typedef {Object} SerializedWMSStyle
|
|
78
|
+
* @property {string} name
|
|
79
|
+
* @property {string} [title]
|
|
80
|
+
* @property {SerializedWMSLegend[]} [legend]
|
|
81
|
+
*/
|
|
82
|
+
/**
|
|
83
|
+
* @typedef {Object} SerializedWMSLayer
|
|
84
|
+
* @property {string} name
|
|
85
|
+
* @property {string} [title]
|
|
86
|
+
* @property {number[]} [extent] Layer extent, in WGS84 coordinates
|
|
87
|
+
* @property {SerializedWMSStyle[]} [styles]
|
|
88
|
+
*/
|
|
89
|
+
/**
|
|
90
|
+
* @description The serialized form of WMS Capabilities are used in the configuration to avoid fetching the capabilities on every startup.
|
|
91
|
+
* @typedef {Object} SerializedWMSCapabilities
|
|
92
|
+
* @property {Array<SerializedWMSLayer>} layers
|
|
47
93
|
*/
|
|
48
94
|
/**
|
|
49
95
|
* A WMSGroupItem, will take over a WMSLayer and request the Capabilities of the layer to show all available
|
|
@@ -2,6 +2,7 @@ import { markVolatile } from '@vcmap/core';
|
|
|
2
2
|
import { getLogger } from '@vcsuite/logger';
|
|
3
3
|
import { ref } from 'vue';
|
|
4
4
|
import { parseBoolean } from '@vcsuite/parsers';
|
|
5
|
+
import { is } from '@vcsuite/check';
|
|
5
6
|
import deepEqual from 'fast-deep-equal';
|
|
6
7
|
import WMSCapabilities from 'ol/format/WMSCapabilities';
|
|
7
8
|
import { StateActionState } from '../actions/stateRefAction.js';
|
|
@@ -10,6 +11,90 @@ import WmsChildContentTreeItem from './wmsChildContentTreeItem.js';
|
|
|
10
11
|
import VcsObjectContentTreeItem from './vcsObjectContentTreeItem.js';
|
|
11
12
|
import { legendSymbol } from '../legend/legendHelper.js';
|
|
12
13
|
|
|
14
|
+
/**
|
|
15
|
+
*
|
|
16
|
+
* @param {string} src The OnlineRessource property of the legend
|
|
17
|
+
* @param {number} width The width of the image
|
|
18
|
+
* @param {string} title The title of the layer.
|
|
19
|
+
* @returns {import('../legend/legendHelper.js').StyleLegendItem}
|
|
20
|
+
*/
|
|
21
|
+
function parseLegend(src, width, title) {
|
|
22
|
+
if (width < 25) {
|
|
23
|
+
return {
|
|
24
|
+
type: 'StyleLegendItem',
|
|
25
|
+
colNr: 1,
|
|
26
|
+
rows: [{ type: 'IconLegendRow', title, image: { src } }],
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
return { type: 'ImageLegendItem', popoutBtn: true, src };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
*
|
|
34
|
+
* @param {SerializedWMSCapabilities} capabilities
|
|
35
|
+
* @returns {WMSEntry[]}
|
|
36
|
+
*/
|
|
37
|
+
function parseSerializedCapabilities(capabilities) {
|
|
38
|
+
if (capabilities?.layers?.length > 0) {
|
|
39
|
+
return capabilities.layers
|
|
40
|
+
.filter((layer) => {
|
|
41
|
+
if (!is(layer, { name: String })) {
|
|
42
|
+
getLogger(this.className).warn(
|
|
43
|
+
`Ignoring WMS Layer without name in layer ${this._layerName}`,
|
|
44
|
+
);
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
return true;
|
|
48
|
+
})
|
|
49
|
+
.map((layer) => {
|
|
50
|
+
const styles = layer.styles
|
|
51
|
+
?.filter((s) => {
|
|
52
|
+
if (!is(s, { name: String })) {
|
|
53
|
+
getLogger(this.className).warn(
|
|
54
|
+
`Ignoring WMS Style without name in layer ${this._layerName}`,
|
|
55
|
+
);
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
return true;
|
|
59
|
+
})
|
|
60
|
+
.map((s) => ({
|
|
61
|
+
name: s.name,
|
|
62
|
+
title: s.title,
|
|
63
|
+
legend:
|
|
64
|
+
s.legend
|
|
65
|
+
?.filter((l) => {
|
|
66
|
+
if (!is(l, { url: String, width: Number, height: Number })) {
|
|
67
|
+
getLogger(this.className).warn(
|
|
68
|
+
`Ignoring invalid WMS Legend in style ${s.name} in layer ${this._layerName}`,
|
|
69
|
+
);
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
return true;
|
|
73
|
+
})
|
|
74
|
+
.map((l) => parseLegend(l.url, l.width, s.title || '')) || [],
|
|
75
|
+
}));
|
|
76
|
+
|
|
77
|
+
const wmsEntry = {
|
|
78
|
+
name: layer.name,
|
|
79
|
+
active: ref(false),
|
|
80
|
+
activeStyle: ref(''),
|
|
81
|
+
};
|
|
82
|
+
if (layer.title) {
|
|
83
|
+
wmsEntry.title = layer.title;
|
|
84
|
+
}
|
|
85
|
+
if (layer.extent) {
|
|
86
|
+
wmsEntry.extent = layer.extent;
|
|
87
|
+
}
|
|
88
|
+
if (styles?.length > 0) {
|
|
89
|
+
wmsEntry.styles = styles;
|
|
90
|
+
}
|
|
91
|
+
return wmsEntry;
|
|
92
|
+
});
|
|
93
|
+
} else {
|
|
94
|
+
return [];
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
13
98
|
/**
|
|
14
99
|
* @param {string} rawUrl
|
|
15
100
|
* @param {Record<string, string>} parameters
|
|
@@ -49,27 +134,9 @@ async function getWMSEntries(rawUrl, parameters) {
|
|
|
49
134
|
title: style.Title,
|
|
50
135
|
legend: style.LegendURL?.filter(
|
|
51
136
|
(legend) => legend.OnlineResource,
|
|
52
|
-
).map((legend) =>
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
return {
|
|
56
|
-
type: 'StyleLegendItem',
|
|
57
|
-
colNr: 1,
|
|
58
|
-
rows: [
|
|
59
|
-
{
|
|
60
|
-
type: 'IconLegendRow',
|
|
61
|
-
title: layer.Title,
|
|
62
|
-
image: { src },
|
|
63
|
-
},
|
|
64
|
-
],
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
return {
|
|
68
|
-
type: 'ImageLegendItem',
|
|
69
|
-
src,
|
|
70
|
-
popoutBtn: true,
|
|
71
|
-
};
|
|
72
|
-
}),
|
|
137
|
+
).map((legend) =>
|
|
138
|
+
parseLegend(legend.OnlineResource, legend.size[0], layer.Title),
|
|
139
|
+
),
|
|
73
140
|
};
|
|
74
141
|
}) ?? [];
|
|
75
142
|
return {
|
|
@@ -133,9 +200,34 @@ function createWMSChildContentTreeItem(
|
|
|
133
200
|
* @property {string} name
|
|
134
201
|
* @property {import("vue").Ref<boolean>} active
|
|
135
202
|
* @property {import("vue").Ref<string>} activeStyle
|
|
136
|
-
* @property {string} title
|
|
137
|
-
* @property {import("@vcmap/core").Extent} extent
|
|
138
|
-
* @property {Array<WMSStyleEntry>} styles
|
|
203
|
+
* @property {string} [title]
|
|
204
|
+
* @property {import("@vcmap/core").Extent} [extent]
|
|
205
|
+
* @property {Array<WMSStyleEntry>} [styles]
|
|
206
|
+
*/
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* @typedef {Object} SerializedWMSLegend
|
|
210
|
+
* @property {string} url
|
|
211
|
+
* @property {number} width
|
|
212
|
+
* @property {number} height
|
|
213
|
+
*/
|
|
214
|
+
/**
|
|
215
|
+
* @typedef {Object} SerializedWMSStyle
|
|
216
|
+
* @property {string} name
|
|
217
|
+
* @property {string} [title]
|
|
218
|
+
* @property {SerializedWMSLegend[]} [legend]
|
|
219
|
+
*/
|
|
220
|
+
/**
|
|
221
|
+
* @typedef {Object} SerializedWMSLayer
|
|
222
|
+
* @property {string} name
|
|
223
|
+
* @property {string} [title]
|
|
224
|
+
* @property {number[]} [extent] Layer extent, in WGS84 coordinates
|
|
225
|
+
* @property {SerializedWMSStyle[]} [styles]
|
|
226
|
+
*/
|
|
227
|
+
/**
|
|
228
|
+
* @description The serialized form of WMS Capabilities are used in the configuration to avoid fetching the capabilities on every startup.
|
|
229
|
+
* @typedef {Object} SerializedWMSCapabilities
|
|
230
|
+
* @property {Array<SerializedWMSLayer>} layers
|
|
139
231
|
*/
|
|
140
232
|
|
|
141
233
|
/**
|
|
@@ -496,10 +588,17 @@ class WMSGroupContentTreeItem extends VcsObjectContentTreeItem {
|
|
|
496
588
|
this.clickable = !this._setWMSLayersExclusive;
|
|
497
589
|
|
|
498
590
|
try {
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
591
|
+
let availableWMSEntries = [];
|
|
592
|
+
if (this._layer.properties.capabilities) {
|
|
593
|
+
availableWMSEntries = parseSerializedCapabilities(
|
|
594
|
+
this._layer.properties.capabilities,
|
|
595
|
+
);
|
|
596
|
+
} else {
|
|
597
|
+
availableWMSEntries = await getWMSEntries(
|
|
598
|
+
this._layer.url,
|
|
599
|
+
this._layer.parameters,
|
|
600
|
+
);
|
|
601
|
+
}
|
|
503
602
|
// check if the layer still exists, it can happen that the layer was removed while fetching the capabilities.
|
|
504
603
|
if (!this._layer) {
|
|
505
604
|
return;
|
|
@@ -612,6 +711,7 @@ class WMSGroupContentTreeItem extends VcsObjectContentTreeItem {
|
|
|
612
711
|
}
|
|
613
712
|
}),
|
|
614
713
|
);
|
|
714
|
+
|
|
615
715
|
if (this._loadOnStartup) {
|
|
616
716
|
await this._loadWMSChildren();
|
|
617
717
|
}
|
package/src/i18n/de.d.ts
CHANGED
|
@@ -527,6 +527,7 @@ declare namespace messages {
|
|
|
527
527
|
export let select: string;
|
|
528
528
|
let placeholder_1: string;
|
|
529
529
|
export { placeholder_1 as placeholder };
|
|
530
|
+
export let hideWindow: string;
|
|
530
531
|
export let zoomToFeatureAction: string;
|
|
531
532
|
export let zoomToAll: string;
|
|
532
533
|
export let zoomToAllMobile: string;
|
package/src/i18n/de.js
CHANGED
|
@@ -372,6 +372,7 @@ const messages = {
|
|
|
372
372
|
tooltip: 'Suche',
|
|
373
373
|
select: 'Suchergebnis auswählen',
|
|
374
374
|
placeholder: 'Suche nach Adresse oder Ort/Sehenswürdigkeit',
|
|
375
|
+
hideWindow: 'Suche ausblenden',
|
|
375
376
|
zoomToFeatureAction: 'Auf Ergebnis zoomen',
|
|
376
377
|
zoomToAll: 'Auf alle Ergebnisse zoomen',
|
|
377
378
|
zoomToAllMobile: 'Auf alle zoomen',
|
package/src/i18n/en.d.ts
CHANGED
|
@@ -527,6 +527,7 @@ declare namespace messages {
|
|
|
527
527
|
export let select: string;
|
|
528
528
|
let placeholder_1: string;
|
|
529
529
|
export { placeholder_1 as placeholder };
|
|
530
|
+
export let hideWindow: string;
|
|
530
531
|
export let zoomToFeatureAction: string;
|
|
531
532
|
export let zoomToAllMobile: string;
|
|
532
533
|
export let zoomToAll: string;
|
package/src/i18n/en.js
CHANGED
|
@@ -372,6 +372,7 @@ const messages = {
|
|
|
372
372
|
tooltip: 'Search',
|
|
373
373
|
select: 'Select result item',
|
|
374
374
|
placeholder: 'Search for address or landmark/point of interest',
|
|
375
|
+
hideWindow: 'Hide search',
|
|
375
376
|
zoomToFeatureAction: 'Zoom to result',
|
|
376
377
|
zoomToAllMobile: 'Zoom to all',
|
|
377
378
|
zoomToAll: 'Zoom to all',
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
</template>
|
|
29
29
|
|
|
30
30
|
<script>
|
|
31
|
-
import { computed, inject, ref } from 'vue';
|
|
31
|
+
import { computed, inject, onUnmounted, ref } from 'vue';
|
|
32
32
|
import { VExpansionPanels, VContainer } from 'vuetify/components';
|
|
33
33
|
import CollectionComponentProvider from './CollectionComponentProvider.vue';
|
|
34
34
|
import CollectionComponentList from './CollectionComponentList.vue';
|
|
@@ -57,6 +57,19 @@
|
|
|
57
57
|
* @type {import("vue").Ref<string|null>}
|
|
58
58
|
*/
|
|
59
59
|
const componentView = ref(null);
|
|
60
|
+
|
|
61
|
+
const removedListener = collectionManager.removed.addEventListener(
|
|
62
|
+
(collectionComponent) => {
|
|
63
|
+
if (componentView.value === collectionComponent.id) {
|
|
64
|
+
componentView.value = null;
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
onUnmounted(() => {
|
|
70
|
+
removedListener();
|
|
71
|
+
});
|
|
72
|
+
|
|
60
73
|
/**
|
|
61
74
|
* @type {import("vue").WritableComputedRef<number[]>}
|
|
62
75
|
*/
|
|
@@ -21,11 +21,7 @@
|
|
|
21
21
|
</span>
|
|
22
22
|
<template v-if="results.length > 0">
|
|
23
23
|
<v-divider class="mt-1 base-darken-1" />
|
|
24
|
-
<ResultsComponent
|
|
25
|
-
:query="query"
|
|
26
|
-
:results="results"
|
|
27
|
-
:show-selected-only="showSelectedOnly"
|
|
28
|
-
/>
|
|
24
|
+
<ResultsComponent :query="query" :results="results" />
|
|
29
25
|
<v-divider />
|
|
30
26
|
|
|
31
27
|
<v-row no-gutters>
|
|
@@ -33,9 +29,10 @@
|
|
|
33
29
|
<div class="button-container d-flex align-center px-2 pt-2 pb-1">
|
|
34
30
|
<VcsFormButton
|
|
35
31
|
class="fixed-button"
|
|
36
|
-
|
|
32
|
+
tooltip="search.hideWindow"
|
|
33
|
+
@click="closeWindow"
|
|
37
34
|
>
|
|
38
|
-
<v-icon icon="mdi-
|
|
35
|
+
<v-icon icon="mdi-minus-box-multiple-outline" />
|
|
39
36
|
</VcsFormButton>
|
|
40
37
|
<VcsFormButton
|
|
41
38
|
@click="zoomToAll"
|
|
@@ -71,6 +68,8 @@
|
|
|
71
68
|
import VcsFormButton from '../components/buttons/VcsFormButton.vue';
|
|
72
69
|
import { useFontSize } from '../vuePlugins/vuetify.js';
|
|
73
70
|
|
|
71
|
+
export const searchComponentId = 'searchId';
|
|
72
|
+
|
|
74
73
|
/**
|
|
75
74
|
* @description Stylized search component providing an input field for search inputs.
|
|
76
75
|
* Renders a list of results using {@link ResultsComponent }
|
|
@@ -98,8 +97,6 @@
|
|
|
98
97
|
const { xs } = useDisplay();
|
|
99
98
|
let queryPreSuggestion = '';
|
|
100
99
|
|
|
101
|
-
const showSelectedOnly = ref(false);
|
|
102
|
-
|
|
103
100
|
let suggestionTimeout;
|
|
104
101
|
|
|
105
102
|
const onInput = () => {
|
|
@@ -140,7 +137,6 @@
|
|
|
140
137
|
suggesting.value = '';
|
|
141
138
|
suggestions.value = [];
|
|
142
139
|
queryPreSuggestion = '';
|
|
143
|
-
showSelectedOnly.value = false;
|
|
144
140
|
};
|
|
145
141
|
|
|
146
142
|
const search = async () => {
|
|
@@ -163,7 +159,6 @@
|
|
|
163
159
|
return fontSize.value + 11;
|
|
164
160
|
});
|
|
165
161
|
return {
|
|
166
|
-
showSelectedOnly,
|
|
167
162
|
xs,
|
|
168
163
|
query,
|
|
169
164
|
searching,
|
|
@@ -193,6 +188,9 @@
|
|
|
193
188
|
query.value = queryPreSuggestion;
|
|
194
189
|
}
|
|
195
190
|
},
|
|
191
|
+
closeWindow() {
|
|
192
|
+
app.windowManager.remove(searchComponentId);
|
|
193
|
+
},
|
|
196
194
|
};
|
|
197
195
|
},
|
|
198
196
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
export const searchComponentId: "searchId";
|
|
1
2
|
declare const _default: import("vue").DefineComponent<{}, {
|
|
2
|
-
showSelectedOnly: import("vue").Ref<boolean>;
|
|
3
3
|
xs: import("vue").Ref<boolean>;
|
|
4
4
|
query: import("vue").Ref<string>;
|
|
5
5
|
searching: import("vue").Ref<boolean>;
|
|
@@ -15,5 +15,6 @@ declare const _default: import("vue").DefineComponent<{}, {
|
|
|
15
15
|
selectedSuggestion: import("vue").Ref<number>;
|
|
16
16
|
onInput: () => void;
|
|
17
17
|
selectSuggestion(value: any): void;
|
|
18
|
+
closeWindow(): void;
|
|
18
19
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{}>>, {}, {}>;
|
|
19
20
|
export default _default;
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|