@vcmap/ui 5.1.8 → 5.2.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.
- package/build/buildTypes.js +9 -0
- package/config/base.config.json +33 -2
- package/config/dev.config.json +22 -2
- package/dist/assets/cesium.js +1 -1
- package/dist/assets/{core.45041e.js → core.627882.js} +4160 -4041
- package/dist/assets/core.js +1 -1
- package/dist/assets/index-76acacac.js +1 -0
- package/dist/assets/ol.js +1 -1
- package/dist/assets/{ui.74ba2a.css → ui.895896.css} +2 -2
- package/dist/assets/{ui.74ba2a.js → ui.895896.js} +8628 -7657
- package/dist/assets/ui.js +1 -1
- package/dist/assets/vue.js +2 -2
- package/dist/assets/{vuetify.72ace9.js → vuetify.1621f3.js} +1 -1
- package/dist/assets/vuetify.js +2 -2
- package/dist/index.html +1 -1
- package/index.d.ts +16 -0
- package/index.js +23 -0
- package/package.json +2 -2
- package/plugins/@vcmap-show-case/collection-manager-example/src/CollectionManagerExample.vue +110 -37
- package/plugins/@vcmap-show-case/collection-manager-example/src/index.js +4 -0
- package/plugins/@vcmap-show-case/form-inputs-example/src/FormInputsExample.vue +10 -3
- package/plugins/@vcmap-show-case/panel-tester/README.md +3 -0
- package/plugins/@vcmap-show-case/panel-tester/package.json +5 -0
- package/plugins/@vcmap-show-case/panel-tester/src/IframePanelExample.vue +15 -0
- package/plugins/@vcmap-show-case/panel-tester/src/ImgPanelExample.vue +19 -0
- package/plugins/@vcmap-show-case/panel-tester/src/PanelExample.vue +128 -0
- package/plugins/@vcmap-show-case/panel-tester/src/TextPanelExample.vue +34 -0
- package/plugins/@vcmap-show-case/panel-tester/src/index.js +63 -0
- package/src/actions/actionHelper.js +1 -1
- package/src/actions/flightActions.d.ts +38 -2
- package/src/actions/flightActions.js +257 -6
- package/src/application/VcsApp.vue +4 -104
- package/src/application/VcsApp.vue.d.ts +0 -6
- package/src/application/VcsContainer.vue +105 -0
- package/src/application/VcsContainer.vue.d.ts +14 -0
- package/src/application/VcsMainMap.vue +68 -0
- package/src/application/VcsMainMap.vue.d.ts +9 -0
- package/src/application/markdownHelper.d.ts +7 -0
- package/src/application/markdownHelper.js +57 -1
- package/src/components/form-inputs-controls/VcsRadioGrid.vue +27 -42
- package/src/contentTree/LayerTree.vue +40 -14
- package/src/downloadHelper.d.ts +0 -2
- package/src/downloadHelper.js +2 -4
- package/src/featureInfo/BalloonComponent.vue +31 -3
- package/src/featureInfo/BalloonComponent.vue.d.ts +1 -0
- package/src/featureInfo/MarkdownBalloonComponent.vue +24 -0
- package/src/featureInfo/MarkdownBalloonComponent.vue.d.ts +12 -0
- package/src/featureInfo/abstractFeatureInfoView.js +54 -22
- package/src/featureInfo/addressBalloonFeatureInfoView.d.ts +2 -2
- package/src/featureInfo/addressBalloonFeatureInfoView.js +1 -1
- package/src/featureInfo/balloonFeatureInfoView.js +1 -1
- package/src/featureInfo/balloonHelper.js +16 -9
- package/src/featureInfo/featureInfo.js +10 -0
- package/src/featureInfo/markdownBalloonFeatureInfoView.d.ts +47 -0
- package/src/featureInfo/markdownBalloonFeatureInfoView.js +81 -0
- package/src/featureInfo/markdownFeatureInfoView.d.ts +47 -0
- package/src/featureInfo/markdownFeatureInfoView.js +95 -0
- package/src/i18n/de.d.ts +8 -3
- package/src/i18n/de.js +3 -0
- package/src/i18n/en.d.ts +32 -26
- package/src/i18n/en.js +4 -1
- package/src/manager/collectionManager/CollectionComponent.vue +12 -49
- package/src/manager/collectionManager/CollectionComponent.vue.d.ts +5 -9
- package/src/manager/collectionManager/CollectionComponentContent.vue +102 -0
- package/src/manager/collectionManager/CollectionComponentContent.vue.d.ts +17 -0
- package/src/manager/collectionManager/CollectionComponentList.vue +10 -2
- package/src/manager/collectionManager/CollectionComponentList.vue.d.ts +9 -0
- package/src/manager/collectionManager/CollectionComponentStandalone.vue +91 -0
- package/src/manager/collectionManager/CollectionComponentStandalone.vue.d.ts +9 -0
- package/src/manager/collectionManager/collectionManager.d.ts +2 -2
- package/src/manager/collectionManager/collectionManager.js +21 -19
- package/src/manager/panel/PanelComponent.vue +110 -0
- package/src/manager/panel/PanelComponent.vue.d.ts +19 -0
- package/src/manager/panel/PanelManagerComponent.vue +224 -0
- package/src/manager/panel/PanelManagerComponent.vue.d.ts +36 -0
- package/src/manager/panel/panelHelper.d.ts +83 -0
- package/src/manager/panel/panelHelper.js +272 -0
- package/src/manager/panel/panelManager.d.ts +338 -0
- package/src/manager/panel/panelManager.js +381 -0
- package/src/manager/window/WindowManager.vue +14 -0
- package/src/manager/window/windowHelper.js +1 -1
- package/src/search/ResultItem.vue +1 -1
- package/src/search/search.d.ts +2 -2
- package/src/search/search.js +2 -2
- package/src/vcsUiApp.d.ts +14 -0
- package/src/vcsUiApp.js +18 -0
- package/dist/assets/index-3cd5a3f3.js +0 -1
- /package/dist/assets/{cesium.035e3a.js → cesium.9e39f4.js} +0 -0
- /package/dist/assets/{ol.eb3bee.js → ol.fe8c0e.js} +0 -0
- /package/dist/assets/{vue.17a8fa.js → vue.4b3319.js} +0 -0
- /package/dist/assets/{vuetify.72ace9.css → vuetify.1621f3.css} +0 -0
@@ -0,0 +1,105 @@
|
|
1
|
+
<template>
|
2
|
+
<v-container
|
3
|
+
class="vcs-container pa-0"
|
4
|
+
:class="{ 'vcs-container-xs': $vuetify.breakpoint.xs }"
|
5
|
+
fluid
|
6
|
+
absolute
|
7
|
+
>
|
8
|
+
<template v-if="$vuetify.breakpoint.xs">
|
9
|
+
<img
|
10
|
+
v-if="mobileLogo"
|
11
|
+
:src="mobileLogo"
|
12
|
+
alt="Logo"
|
13
|
+
draggable="false"
|
14
|
+
class="mobile-logo"
|
15
|
+
/>
|
16
|
+
</template>
|
17
|
+
<VcsButton
|
18
|
+
v-if="!$vuetify.breakpoint.smAndUp && $vuetify.breakpoint.mobile"
|
19
|
+
:key="attributionAction.name"
|
20
|
+
:tooltip="attributionAction.title"
|
21
|
+
:icon="attributionAction.icon"
|
22
|
+
:active="attributionAction.active"
|
23
|
+
@click.stop="attributionAction.callback($event)"
|
24
|
+
class="z-index-1 mobile-attribution-btn"
|
25
|
+
/>
|
26
|
+
<PanelManagerComponent />
|
27
|
+
<ToolboxManagerComponent />
|
28
|
+
<WindowManagerComponent />
|
29
|
+
<NotifierComponent />
|
30
|
+
</v-container>
|
31
|
+
</template>
|
32
|
+
|
33
|
+
<style scoped lang="scss">
|
34
|
+
.vcs-container {
|
35
|
+
position: absolute;
|
36
|
+
top: 48px;
|
37
|
+
left: 0;
|
38
|
+
right: 0;
|
39
|
+
bottom: 22px;
|
40
|
+
}
|
41
|
+
|
42
|
+
.vcs-container-xs {
|
43
|
+
top: 0;
|
44
|
+
bottom: 56px;
|
45
|
+
}
|
46
|
+
|
47
|
+
.mobile-logo {
|
48
|
+
max-height: 40px;
|
49
|
+
max-width: 70px;
|
50
|
+
position: absolute;
|
51
|
+
top: 1rem;
|
52
|
+
left: 1rem;
|
53
|
+
z-index: 1;
|
54
|
+
}
|
55
|
+
|
56
|
+
.mobile-attribution-btn {
|
57
|
+
position: fixed;
|
58
|
+
right: 2px;
|
59
|
+
bottom: 36px;
|
60
|
+
}
|
61
|
+
</style>
|
62
|
+
|
63
|
+
<script>
|
64
|
+
import { computed, inject } from 'vue';
|
65
|
+
import { VContainer } from 'vuetify/lib';
|
66
|
+
import PanelManagerComponent from '../manager/panel/PanelManagerComponent.vue';
|
67
|
+
import WindowManagerComponent from '../manager/window/WindowManager.vue';
|
68
|
+
import ToolboxManagerComponent from '../manager/toolbox/ToolboxManager.vue';
|
69
|
+
import VcsButton from '../components/buttons/VcsButton.vue';
|
70
|
+
import NotifierComponent from '../notifier/NotifierComponent.vue';
|
71
|
+
import VcsDefaultLogoMobile from '../logo-mobile.svg';
|
72
|
+
|
73
|
+
/**
|
74
|
+
* @description The main container with map canvas
|
75
|
+
* @vue-prop {VcsAction} attributionAction
|
76
|
+
*/
|
77
|
+
export default {
|
78
|
+
components: {
|
79
|
+
VcsButton,
|
80
|
+
PanelManagerComponent,
|
81
|
+
WindowManagerComponent,
|
82
|
+
ToolboxManagerComponent,
|
83
|
+
VContainer,
|
84
|
+
NotifierComponent,
|
85
|
+
},
|
86
|
+
props: {
|
87
|
+
attributionAction: {
|
88
|
+
type: Object,
|
89
|
+
required: true,
|
90
|
+
},
|
91
|
+
},
|
92
|
+
setup() {
|
93
|
+
const app = inject('vcsApp');
|
94
|
+
|
95
|
+
return {
|
96
|
+
mobileLogo: computed(
|
97
|
+
() =>
|
98
|
+
app.uiConfig.config.value.mobileLogo ??
|
99
|
+
app.uiConfig.config.value.logo ??
|
100
|
+
VcsDefaultLogoMobile,
|
101
|
+
),
|
102
|
+
};
|
103
|
+
},
|
104
|
+
};
|
105
|
+
</script>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
declare const _default: import("vue").DefineComponent<{
|
2
|
+
attributionAction: {
|
3
|
+
type: ObjectConstructor;
|
4
|
+
required: true;
|
5
|
+
};
|
6
|
+
}, {
|
7
|
+
mobileLogo: import("vue").ComputedRef<any>;
|
8
|
+
}, {}, {}, {}, import("vue/types/v3-component-options.js").ComponentOptionsMixin, import("vue/types/v3-component-options.js").ComponentOptionsMixin, {}, string, Readonly<import("vue").ExtractPropTypes<{
|
9
|
+
attributionAction: {
|
10
|
+
type: ObjectConstructor;
|
11
|
+
required: true;
|
12
|
+
};
|
13
|
+
}>>, {}>;
|
14
|
+
export default _default;
|
@@ -0,0 +1,68 @@
|
|
1
|
+
<template>
|
2
|
+
<div>
|
3
|
+
<VcsMap :map-id="mapId" />
|
4
|
+
<MapNavigation v-if="showMapNavigation" />
|
5
|
+
</div>
|
6
|
+
</template>
|
7
|
+
|
8
|
+
<style lang="scss" scoped></style>
|
9
|
+
|
10
|
+
<script>
|
11
|
+
import { inject, onMounted, onUnmounted, ref } from 'vue';
|
12
|
+
import { v4 as uuid } from 'uuid';
|
13
|
+
import MapNavigation from '../navigation/MapNavigation.vue';
|
14
|
+
import VcsMap from './VcsMap.vue';
|
15
|
+
|
16
|
+
export function setupMapNavigation(app) {
|
17
|
+
const showMapNavigation = ref(app.maps.size < 1);
|
18
|
+
|
19
|
+
const listeners = [
|
20
|
+
app.maps.added.addEventListener(() => {
|
21
|
+
showMapNavigation.value = true;
|
22
|
+
}),
|
23
|
+
app.maps.removed.addEventListener(() => {
|
24
|
+
if (app.maps.size < 1) {
|
25
|
+
showMapNavigation.value = false;
|
26
|
+
}
|
27
|
+
}),
|
28
|
+
];
|
29
|
+
|
30
|
+
return {
|
31
|
+
showMapNavigation,
|
32
|
+
destroy: () => {
|
33
|
+
listeners.forEach((cb) => cb());
|
34
|
+
},
|
35
|
+
};
|
36
|
+
}
|
37
|
+
|
38
|
+
/**
|
39
|
+
* @description Wrapper component for a VcsMap providing the map element.
|
40
|
+
* @vue-prop {string} mapId - The id of the map, which is rendered in the map element's canvas
|
41
|
+
*/
|
42
|
+
export default {
|
43
|
+
name: 'VcsMainMap',
|
44
|
+
components: { MapNavigation, VcsMap },
|
45
|
+
setup() {
|
46
|
+
const app = inject('vcsApp');
|
47
|
+
const id = uuid();
|
48
|
+
const mapId = `mapCollection-${id}`;
|
49
|
+
|
50
|
+
const { showMapNavigation, destroy: destroyMapNavigationListener } =
|
51
|
+
setupMapNavigation(app);
|
52
|
+
|
53
|
+
onMounted(() => {
|
54
|
+
app.maps.setTarget(mapId);
|
55
|
+
app.mounted.raiseEvent(mapId);
|
56
|
+
});
|
57
|
+
|
58
|
+
onUnmounted(() => {
|
59
|
+
destroyMapNavigationListener();
|
60
|
+
});
|
61
|
+
|
62
|
+
return {
|
63
|
+
mapId,
|
64
|
+
showMapNavigation,
|
65
|
+
};
|
66
|
+
},
|
67
|
+
};
|
68
|
+
</script>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
export function setupMapNavigation(app: any): {
|
2
|
+
showMapNavigation: import("vue").Ref<boolean>;
|
3
|
+
destroy: () => void;
|
4
|
+
};
|
5
|
+
declare const _default: import("vue").DefineComponent<{}, {
|
6
|
+
mapId: string;
|
7
|
+
showMapNavigation: import("vue").Ref<boolean>;
|
8
|
+
}, {}, {}, {}, import("vue/types/v3-component-options.js").ComponentOptionsMixin, import("vue/types/v3-component-options.js").ComponentOptionsMixin, {}, string, Readonly<import("vue").ExtractPropTypes<{}>>, {}>;
|
9
|
+
export default _default;
|
@@ -3,3 +3,10 @@
|
|
3
3
|
* @returns {string}
|
4
4
|
*/
|
5
5
|
export function parseAndSanitizeMarkdown(content: string): string;
|
6
|
+
/**
|
7
|
+
* Replaces template strings by provided attributes, e.g. {{myAttribute}}
|
8
|
+
* @param {string|string[]} template
|
9
|
+
* @param {Record<string, unknown>} attributes
|
10
|
+
* @returns {string}
|
11
|
+
*/
|
12
|
+
export function replaceAttributes(template: string | string[], attributes: Record<string, unknown>): string;
|
@@ -5,7 +5,63 @@ import DOMPurify from 'dompurify';
|
|
5
5
|
* @param {string} content
|
6
6
|
* @returns {string}
|
7
7
|
*/
|
8
|
-
// eslint-disable-next-line import/prefer-default-export
|
9
8
|
export function parseAndSanitizeMarkdown(content) {
|
10
9
|
return DOMPurify.sanitize(marked(content));
|
11
10
|
}
|
11
|
+
|
12
|
+
/**
|
13
|
+
* @param {Record<string, unknown>} parent
|
14
|
+
* @param {(string|number)[]} keys
|
15
|
+
* @returns {undefined|T}
|
16
|
+
* @template {*} T
|
17
|
+
*/
|
18
|
+
function findRecursive(parent, keys) {
|
19
|
+
if (keys.length === 1) {
|
20
|
+
return parent[keys[0]];
|
21
|
+
} else {
|
22
|
+
const nextKey = keys.shift();
|
23
|
+
const nextParent = parent[nextKey];
|
24
|
+
if (nextParent) {
|
25
|
+
return findRecursive(nextParent, keys);
|
26
|
+
}
|
27
|
+
}
|
28
|
+
return undefined;
|
29
|
+
}
|
30
|
+
|
31
|
+
/**
|
32
|
+
* Replaces template strings by provided attributes, e.g. {{myAttribute}}
|
33
|
+
* @param {string|string[]} template
|
34
|
+
* @param {Record<string, unknown>} attributes
|
35
|
+
* @returns {string}
|
36
|
+
*/
|
37
|
+
export function replaceAttributes(template, attributes) {
|
38
|
+
const templateString = Array.isArray(template)
|
39
|
+
? template.join('\n')
|
40
|
+
: template;
|
41
|
+
return templateString.replace(/\{\{([^}]+)}}/g, (p, value) => {
|
42
|
+
const keys = value.trim().split('.');
|
43
|
+
|
44
|
+
for (let i = 0; i < keys.length; i++) {
|
45
|
+
let key = keys[i];
|
46
|
+
if (typeof key === 'string') {
|
47
|
+
const indices = [];
|
48
|
+
let arrayIndex = /\[["']?([^\]]+)["']?]$/.exec(key);
|
49
|
+
while (arrayIndex != null) {
|
50
|
+
let bracketKey = arrayIndex[1];
|
51
|
+
if (/^\d+$/.test(bracketKey)) {
|
52
|
+
bracketKey = Number(bracketKey);
|
53
|
+
}
|
54
|
+
indices.push(bracketKey);
|
55
|
+
key = key.substring(0, arrayIndex.index);
|
56
|
+
arrayIndex = /\[["']?([^\]]+)["']?]$/.exec(key);
|
57
|
+
}
|
58
|
+
|
59
|
+
if (indices.length > 0) {
|
60
|
+
keys.splice(i, 1, key, ...indices);
|
61
|
+
}
|
62
|
+
}
|
63
|
+
}
|
64
|
+
|
65
|
+
return findRecursive(attributes, keys) ?? '';
|
66
|
+
});
|
67
|
+
}
|
@@ -16,42 +16,22 @@
|
|
16
16
|
v-bind="{ ...$attrs, ...attrs }"
|
17
17
|
v-on="{ ...$listeners, ...on }"
|
18
18
|
>
|
19
|
-
<
|
20
|
-
<v-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
<v-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
:alt="item[itemValue]"
|
36
|
-
class="image"
|
37
|
-
/>
|
38
|
-
</slot>
|
39
|
-
</div>
|
40
|
-
</v-col>
|
41
|
-
</v-row>
|
42
|
-
<v-row no-gutters>
|
43
|
-
<v-col>
|
44
|
-
<v-radio
|
45
|
-
:value="item[itemValue]"
|
46
|
-
:ripple="false"
|
47
|
-
class="ma-0"
|
48
|
-
:class="isDense ? 'vcs-radio-dense' : 'vcs-radio'"
|
49
|
-
:dense="isDense"
|
50
|
-
/>
|
51
|
-
</v-col>
|
52
|
-
</v-row>
|
53
|
-
</v-col>
|
54
|
-
</v-row>
|
19
|
+
<div class="d-flex gap-1 px-2 pt-2 pb-1 justify-center">
|
20
|
+
<div v-for="(item, idx) in items" :key="idx">
|
21
|
+
<div class="pt-1 pb-0" :class="$attrs.disabled ? 'disabled' : ''">
|
22
|
+
<slot name="label" :value="item[itemValue]" :src="item.src">
|
23
|
+
<img :src="item.src" :alt="item[itemValue]" class="image" />
|
24
|
+
</slot>
|
25
|
+
</div>
|
26
|
+
<v-radio
|
27
|
+
:value="item[itemValue]"
|
28
|
+
:ripple="false"
|
29
|
+
class="ma-0 justify-center"
|
30
|
+
:class="isDense ? 'vcs-radio-dense' : 'vcs-radio'"
|
31
|
+
:dense="isDense"
|
32
|
+
/>
|
33
|
+
</div>
|
34
|
+
</div>
|
55
35
|
</v-radio-group>
|
56
36
|
</v-container>
|
57
37
|
</template>
|
@@ -60,12 +40,22 @@
|
|
60
40
|
|
61
41
|
<script>
|
62
42
|
import { computed, ref } from 'vue';
|
63
|
-
import { VContainer,
|
43
|
+
import { VContainer, VRadioGroup, VRadio } from 'vuetify/lib';
|
64
44
|
import VcsTooltip from '../notification/VcsTooltip.vue';
|
65
45
|
import { useErrorSync } from './composables.js';
|
66
46
|
|
67
47
|
/**
|
68
48
|
* @description Stylized wrapper around {@link https://vuetifyjs.com/en/api/v-radio-group/ |vuetify radio group} which places icons or raster src files above the radio buttons as labels and arranges them in a grid.
|
49
|
+
* Use figure and figcaption for labeled radio icons:
|
50
|
+
* @example
|
51
|
+
* <VcsRadioGrid v-model="model" items="items" >
|
52
|
+
* <template #label="{ src, value }">
|
53
|
+
* <figure>
|
54
|
+
* <v-icon size="24" class="d-flex justify-center">{{src}}</v-icon>
|
55
|
+
* <figcaption class="d-flex justify-center">{{ value }}</figcaption>
|
56
|
+
* </figure>
|
57
|
+
* </template>
|
58
|
+
* </VcsRadioGrid>
|
69
59
|
* @vue-prop {{value: string, src: string}[]} items - The items to be displayed in the grid. The src is the path to the raster image.
|
70
60
|
* @vue-prop {('bottom' | 'left' | 'top' | 'right')} [tooltipPosition='right'] - Position of the error tooltip.
|
71
61
|
* @vue-prop {string} itemValue - The key of the provided item objects that contains the value.
|
@@ -75,8 +65,6 @@
|
|
75
65
|
name: 'VcsRadioGrid',
|
76
66
|
components: {
|
77
67
|
VContainer,
|
78
|
-
VRow,
|
79
|
-
VCol,
|
80
68
|
VRadioGroup,
|
81
69
|
VRadio,
|
82
70
|
VcsTooltip,
|
@@ -166,9 +154,6 @@
|
|
166
154
|
height: auto;
|
167
155
|
width: auto;
|
168
156
|
}
|
169
|
-
.label-wrapper {
|
170
|
-
width: 24px;
|
171
|
-
}
|
172
157
|
.disabled {
|
173
158
|
opacity: 0.3;
|
174
159
|
}
|
@@ -19,6 +19,7 @@
|
|
19
19
|
import { VSheet } from 'vuetify/lib';
|
20
20
|
import VcsTreeview from '../components/lists/VcsTreeview.vue';
|
21
21
|
|
22
|
+
const openStateMapSymbol = Symbol('openStateMap');
|
22
23
|
/**
|
23
24
|
* @description
|
24
25
|
* Implements Treeview and shows content tree
|
@@ -35,23 +36,48 @@
|
|
35
36
|
setup(props) {
|
36
37
|
const app = inject('vcsApp');
|
37
38
|
const open = app.contentTree.getTreeOpenStateRef(props.windowState.id);
|
38
|
-
|
39
|
-
const initOpen = app.contentTree
|
40
|
-
.getChildrenForSubTree(props.windowState.id)
|
41
|
-
.filter((i) => i.initOpen)
|
42
|
-
.map((i) => i.name);
|
43
|
-
|
44
39
|
const tree = app.contentTree.getComputedVisibleTree(props.windowState.id);
|
45
40
|
|
41
|
+
function getWithVisibleChildren(item) {
|
42
|
+
return [
|
43
|
+
item.name,
|
44
|
+
...item.visibleChildren.map((c) => getWithVisibleChildren(c)).flat(),
|
45
|
+
];
|
46
|
+
}
|
47
|
+
|
48
|
+
if (!app.contentTree[openStateMapSymbol]) {
|
49
|
+
app.contentTree[openStateMapSymbol] = new Map();
|
50
|
+
}
|
51
|
+
/**
|
52
|
+
* @type {Map<string, string[]>}
|
53
|
+
*/
|
54
|
+
const openStateMap = app.contentTree[openStateMapSymbol];
|
46
55
|
// watch for new visible children, which should start init open
|
47
|
-
watch(
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
56
|
+
watch(
|
57
|
+
tree,
|
58
|
+
(value, oldValue) => {
|
59
|
+
if (openStateMap.has(app.maps.activeMap?.name)) {
|
60
|
+
open.value = openStateMap.get(app.maps.activeMap?.name);
|
61
|
+
} else {
|
62
|
+
const items = [...app.contentTree]
|
63
|
+
.filter((i) => i.initOpen && i.getTreeViewItem().visible)
|
64
|
+
.map(({ name }) => name);
|
65
|
+
const oldValues = oldValue
|
66
|
+
? oldValue.map(getWithVisibleChildren).flat()
|
67
|
+
: [];
|
68
|
+
const changed = items.filter(
|
69
|
+
(name) => !oldValues.includes(name) && !open.value.includes(name),
|
70
|
+
);
|
71
|
+
open.value.push(...changed);
|
72
|
+
}
|
73
|
+
},
|
74
|
+
{ immediate: true },
|
75
|
+
);
|
76
|
+
|
77
|
+
watch(open, () => {
|
78
|
+
if (app.maps.activeMap) {
|
79
|
+
openStateMap.set(app.maps.activeMap.name, [...open.value]);
|
80
|
+
}
|
55
81
|
});
|
56
82
|
|
57
83
|
return {
|
package/src/downloadHelper.d.ts
CHANGED
package/src/downloadHelper.js
CHANGED
@@ -1,17 +1,15 @@
|
|
1
|
-
import {
|
1
|
+
import { isSameOrigin } from '@vcmap/core';
|
2
2
|
|
3
3
|
/**
|
4
4
|
* Download a blob
|
5
5
|
* @param {string} uri
|
6
6
|
* @param {string} fileName
|
7
|
-
* @api
|
8
|
-
* @export
|
9
7
|
*/
|
10
8
|
export function downloadURI(uri, fileName) {
|
11
9
|
const link = document.createElement('a');
|
12
10
|
link.download = fileName;
|
13
11
|
link.href = uri;
|
14
|
-
if (!
|
12
|
+
if (!isSameOrigin(uri)) {
|
15
13
|
link.target = '_blank';
|
16
14
|
}
|
17
15
|
link.click();
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<template>
|
2
|
-
<v-card class="mx-auto elevation-0"
|
2
|
+
<v-card class="mx-auto elevation-0" v-if="position">
|
3
3
|
<slot name="balloon-header" :attrs="{ ...$props, ...$attrs }">
|
4
4
|
<v-list-item class="px-2 align-center">
|
5
5
|
<v-list-item-avatar tile size="16" class="mr-2">
|
@@ -28,7 +28,7 @@
|
|
28
28
|
|
29
29
|
<v-card
|
30
30
|
class="overflow-y-auto py-2 elevation-0"
|
31
|
-
max-height="
|
31
|
+
:max-height="maxHeight"
|
32
32
|
color="transparent"
|
33
33
|
>
|
34
34
|
<slot :attrs="{ ...$props, ...$attrs }">
|
@@ -56,7 +56,7 @@
|
|
56
56
|
</v-card>
|
57
57
|
</template>
|
58
58
|
<script>
|
59
|
-
import { inject, onMounted, onUnmounted, watch } from 'vue';
|
59
|
+
import { inject, onMounted, onUnmounted, ref, watch } from 'vue';
|
60
60
|
import {
|
61
61
|
VCard,
|
62
62
|
VDivider,
|
@@ -68,6 +68,10 @@
|
|
68
68
|
VListItemSubtitle,
|
69
69
|
VListItemTitle,
|
70
70
|
} from 'vuetify/lib';
|
71
|
+
import {
|
72
|
+
getTargetSize,
|
73
|
+
posToNumber,
|
74
|
+
} from '../manager/window/windowHelper.js';
|
71
75
|
import { setupBalloonPositionListener } from './balloonHelper.js';
|
72
76
|
import VcsButton from '../components/buttons/VcsButton.vue';
|
73
77
|
import { getTag, getTagOptions } from '../components/tables/VcsTable.vue';
|
@@ -127,6 +131,28 @@
|
|
127
131
|
setup(props, { attrs }) {
|
128
132
|
const app = inject('vcsApp');
|
129
133
|
const windowId = attrs['window-state'].id;
|
134
|
+
function getMaxHeight() {
|
135
|
+
if (app.windowManager.get(windowId)?.position?.maxHeight) {
|
136
|
+
return (
|
137
|
+
posToNumber(
|
138
|
+
app.windowManager.get(windowId).position.maxHeight,
|
139
|
+
'maxHeight',
|
140
|
+
getTargetSize(app.maps.target),
|
141
|
+
) - 49 // 44px header offset with padding 5px
|
142
|
+
);
|
143
|
+
}
|
144
|
+
if (app.windowManager.get(windowId)?.position?.height) {
|
145
|
+
return (
|
146
|
+
posToNumber(
|
147
|
+
app.windowManager.get(windowId).position.height,
|
148
|
+
'height',
|
149
|
+
getTargetSize(app.maps.target),
|
150
|
+
) - 49 // 44px header offset with padding 5px
|
151
|
+
);
|
152
|
+
}
|
153
|
+
return 250;
|
154
|
+
}
|
155
|
+
const maxHeight = ref(getMaxHeight());
|
130
156
|
|
131
157
|
let balloonPositionListener = null;
|
132
158
|
const destroyListener = () => {
|
@@ -152,6 +178,7 @@
|
|
152
178
|
windowId,
|
153
179
|
props.position,
|
154
180
|
);
|
181
|
+
maxHeight.value = getMaxHeight();
|
155
182
|
},
|
156
183
|
);
|
157
184
|
|
@@ -168,6 +195,7 @@
|
|
168
195
|
close,
|
169
196
|
getTag,
|
170
197
|
getTagOptions,
|
198
|
+
maxHeight,
|
171
199
|
};
|
172
200
|
},
|
173
201
|
};
|
@@ -27,6 +27,7 @@ declare const _default: import("vue").DefineComponent<{
|
|
27
27
|
close: () => void;
|
28
28
|
getTag: typeof getTag;
|
29
29
|
getTagOptions: typeof getTagOptions;
|
30
|
+
maxHeight: import("vue").Ref<number>;
|
30
31
|
}, {}, {}, {}, import("vue/types/v3-component-options.js").ComponentOptionsMixin, import("vue/types/v3-component-options.js").ComponentOptionsMixin, {}, string, Readonly<import("vue").ExtractPropTypes<{
|
31
32
|
featureId: {
|
32
33
|
type: StringConstructor;
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<template>
|
2
|
+
<BalloonComponent v-bind="{ ...$attrs }">
|
3
|
+
<div class="pa-2" v-html="html" />
|
4
|
+
</BalloonComponent>
|
5
|
+
</template>
|
6
|
+
<script>
|
7
|
+
import BalloonComponent from './BalloonComponent.vue';
|
8
|
+
|
9
|
+
/**
|
10
|
+
* @description A balloon showing markdown content
|
11
|
+
*/
|
12
|
+
export default {
|
13
|
+
name: 'MarkdownBalloonComponent',
|
14
|
+
props: {
|
15
|
+
html: {
|
16
|
+
type: String,
|
17
|
+
required: true,
|
18
|
+
},
|
19
|
+
},
|
20
|
+
components: {
|
21
|
+
BalloonComponent,
|
22
|
+
},
|
23
|
+
};
|
24
|
+
</script>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
declare const _default: import("vue").DefineComponent<{
|
2
|
+
html: {
|
3
|
+
type: StringConstructor;
|
4
|
+
required: true;
|
5
|
+
};
|
6
|
+
}, {}, {}, {}, {}, import("vue/types/v3-component-options.js").ComponentOptionsMixin, import("vue/types/v3-component-options.js").ComponentOptionsMixin, {}, string, Readonly<import("vue").ExtractPropTypes<{
|
7
|
+
html: {
|
8
|
+
type: StringConstructor;
|
9
|
+
required: true;
|
10
|
+
};
|
11
|
+
}>>, {}>;
|
12
|
+
export default _default;
|