@vcmap/ui 6.2.0-rc.2 → 6.2.0-rc.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/build/postInstall.js +32 -0
- package/config/dev.config.json +12 -0
- package/dist/assets/cesium.js +1 -1
- package/dist/assets/{core-6b5c0363.js → core-640eba41.js} +6965 -6565
- package/dist/assets/core-workers/panoramaImageWorker.js +1 -1
- package/dist/assets/core.js +1 -1
- package/dist/assets/{ol-f58f403b.js → ol-2b44b2a9.js} +1 -1
- package/dist/assets/ol.js +1 -1
- package/dist/assets/ui-8896bb2c.css +1 -0
- package/dist/assets/{ui-aadb7707.js → ui-8896bb2c.js} +9668 -9247
- package/dist/assets/ui.js +1 -1
- package/dist/assets/vue.js +1 -1
- package/dist/assets/{vuetify-533fb61b.js → vuetify-45cc2bff.js} +1 -1
- package/dist/assets/vuetify.js +1 -1
- package/index.d.ts +8 -6
- package/index.js +5 -7
- package/package.json +3 -2
- package/plugins/package.json +8 -7
- package/src/actions/actionHelper.d.ts +16 -11
- package/src/actions/actionHelper.js +50 -61
- package/src/actions/flightActions.d.ts +10 -0
- package/src/actions/flightActions.js +103 -13
- package/src/application/VcsApp.vue +1 -1
- package/src/application/VcsMainMap.vue +40 -2
- package/src/application/VcsMainMap.vue.d.ts +4 -0
- package/src/application/VcsMap.vue +0 -9
- package/src/components/flight/VcsFlightAnchorsComponent.vue +1 -0
- package/src/components/flight/VcsFlightPlayer.vue +31 -17
- package/src/components/flight/VcsFlightPlayer.vue.d.ts +1 -0
- package/src/components/plugins/VcsLoadingOverlay.vue +138 -0
- package/src/components/plugins/VcsLoadingOverlay.vue.d.ts +2 -0
- package/src/components/plugins/{AbstractWorkspaceItemCreator.vue → VcsWorkspaceWrapper.vue} +3 -3
- package/src/components/vector-properties/VcsFeatureEditingWindow.vue +20 -1
- package/src/components/vector-properties/VcsFeatureEditingWindow.vue.d.ts +11 -0
- package/src/components/vector-properties/VcsFeatureInputEditor.vue +166 -0
- package/src/components/vector-properties/VcsFeatureInputEditor.vue.d.ts +17 -0
- package/src/contentTree/contentTreeCollection.d.ts +5 -0
- package/src/contentTree/contentTreeCollection.js +11 -3
- package/src/contentTree/contentTreeItem.d.ts +2 -2
- package/src/contentTree/wmsGroupContentTreeItem.js +10 -3
- package/src/featureInfo/iframeFeatureInfoView.d.ts +16 -3
- package/src/featureInfo/iframeFeatureInfoView.js +19 -2
- package/src/featureInfo/iframeWmsFeatureInfoView.d.ts +3 -1
- package/src/featureInfo/iframeWmsFeatureInfoView.js +1 -1
- package/src/i18n/de.d.ts +21 -7
- package/src/i18n/de.js +11 -0
- package/src/i18n/en.d.ts +21 -7
- package/src/i18n/en.js +11 -0
- package/src/navigation/MapNavigation.vue +22 -27
- package/src/navigation/MapNavigation.vue.d.ts +2 -34
- package/src/navigation/overviewMap.d.ts +23 -13
- package/src/navigation/overviewMap.js +73 -72
- package/dist/assets/ui-aadb7707.css +0 -1
- /package/dist/assets/{cesium-8dd00805.js → cesium-8502542e.js} +0 -0
- /package/dist/assets/core-workers/{panoramaImageWorker.js-0ce7d2f3.js → panoramaImageWorker.js-70e7fc33.js} +0 -0
- /package/dist/assets/{vue-d7691a29.js → vue-461b4f1b.js} +0 -0
- /package/dist/assets/{vuetify-533fb61b.css → vuetify-45cc2bff.css} +0 -0
- /package/src/components/plugins/{AbstractWorkspaceItemCreator.vue.d.ts → VcsWorkspaceWrapper.vue.d.ts} +0 -0
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<v-container class="py-0 px-1 vcs-flight-player">
|
|
3
|
-
<
|
|
3
|
+
<v-row no-gutters class="d-flex align-center">
|
|
4
|
+
<VcsLabel html-for="player">{{ $t('flight.player') }}</VcsLabel>
|
|
5
|
+
<v-row class="d-flex justify-end px-1 gc-2" no-gutters>
|
|
6
|
+
<VcsActionButtonList
|
|
7
|
+
overflow-icon="$vcsShare"
|
|
8
|
+
:actions="recordingActions"
|
|
9
|
+
:disabled="!isCurrentPlayer || disabled"
|
|
10
|
+
/>
|
|
11
|
+
</v-row>
|
|
12
|
+
</v-row>
|
|
4
13
|
<VcsSlider
|
|
5
14
|
v-if="clock"
|
|
6
15
|
type="number"
|
|
@@ -32,22 +41,22 @@
|
|
|
32
41
|
</div>
|
|
33
42
|
</v-container>
|
|
34
43
|
</template>
|
|
44
|
+
|
|
35
45
|
<script>
|
|
36
46
|
import { inject, onMounted, onUnmounted, ref } from 'vue';
|
|
37
|
-
import { VContainer } from 'vuetify/components';
|
|
47
|
+
import { VContainer, VRow } from 'vuetify/components';
|
|
38
48
|
import VcsSlider from '../form-inputs-controls/VcsSlider.vue';
|
|
39
49
|
import VcsLabel from '../form-inputs-controls/VcsLabel.vue';
|
|
40
50
|
import VcsButton from '../buttons/VcsButton.vue';
|
|
41
|
-
import
|
|
51
|
+
import VcsActionButtonList from '../buttons/VcsActionButtonList.vue';
|
|
52
|
+
import {
|
|
53
|
+
createFlightMovieActions,
|
|
54
|
+
createFlightPlayerActions,
|
|
55
|
+
} from '../../actions/flightActions.js';
|
|
42
56
|
import { getProvidedFlightInstance } from './composables.js';
|
|
43
57
|
|
|
44
58
|
function getDefaultClock() {
|
|
45
|
-
return {
|
|
46
|
-
startTime: 0,
|
|
47
|
-
endTime: 0,
|
|
48
|
-
currentTime: 0,
|
|
49
|
-
times: [],
|
|
50
|
-
};
|
|
59
|
+
return { startTime: 0, endTime: 0, currentTime: 0, times: [] };
|
|
51
60
|
}
|
|
52
61
|
|
|
53
62
|
/**
|
|
@@ -70,18 +79,18 @@
|
|
|
70
79
|
export default {
|
|
71
80
|
name: 'VcsFlightPlayer',
|
|
72
81
|
components: {
|
|
73
|
-
VcsLabel,
|
|
74
|
-
VcsButton,
|
|
75
82
|
VContainer,
|
|
83
|
+
VRow,
|
|
84
|
+
VcsActionButtonList,
|
|
85
|
+
VcsButton,
|
|
86
|
+
VcsLabel,
|
|
76
87
|
VcsSlider,
|
|
77
88
|
},
|
|
78
|
-
props: {
|
|
79
|
-
disabled: {
|
|
80
|
-
type: Boolean,
|
|
81
|
-
default: false,
|
|
82
|
-
},
|
|
83
|
-
},
|
|
89
|
+
props: { disabled: { type: Boolean, default: false } },
|
|
84
90
|
setup() {
|
|
91
|
+
/**
|
|
92
|
+
* @type {import("../../vcsUiApp.js").default}
|
|
93
|
+
*/
|
|
85
94
|
const app = inject('vcsApp');
|
|
86
95
|
const flightInstance = getProvidedFlightInstance();
|
|
87
96
|
const clock = ref(getDefaultClock());
|
|
@@ -113,6 +122,9 @@
|
|
|
113
122
|
}
|
|
114
123
|
}
|
|
115
124
|
|
|
125
|
+
const { actions: recordingActions, destroy: destroyRecordingActions } =
|
|
126
|
+
createFlightMovieActions(app, flightInstance);
|
|
127
|
+
|
|
116
128
|
onMounted(async () => {
|
|
117
129
|
flightInstancePlayer =
|
|
118
130
|
await app.flights.setPlayerForFlight(flightInstance);
|
|
@@ -129,12 +141,14 @@
|
|
|
129
141
|
onUnmounted(() => {
|
|
130
142
|
destroy();
|
|
131
143
|
playerChangedListener();
|
|
144
|
+
destroyRecordingActions();
|
|
132
145
|
});
|
|
133
146
|
|
|
134
147
|
return {
|
|
135
148
|
clock,
|
|
136
149
|
actions,
|
|
137
150
|
isCurrentPlayer,
|
|
151
|
+
recordingActions,
|
|
138
152
|
clockTime(seconds) {
|
|
139
153
|
const mins = Math.floor(seconds / 60);
|
|
140
154
|
const secs = Math.floor(seconds % 60);
|
|
@@ -12,6 +12,7 @@ declare const _default: import("vue").DefineComponent<{
|
|
|
12
12
|
}>;
|
|
13
13
|
actions: import("../../actions/actionHelper.js", { with: { "resolution-mode": "import" } }).VcsAction[];
|
|
14
14
|
isCurrentPlayer: import("vue").Ref<boolean>;
|
|
15
|
+
recordingActions: import("../../actions/actionHelper.js", { with: { "resolution-mode": "import" } }).VcsAction[];
|
|
15
16
|
clockTime(seconds: any): string;
|
|
16
17
|
setTime(seconds: any): void;
|
|
17
18
|
}, any, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-dialog
|
|
3
|
+
v-model="show"
|
|
4
|
+
class="vcs-loading-overlay"
|
|
5
|
+
:max-width="maxWidth"
|
|
6
|
+
:persistent="persistent"
|
|
7
|
+
>
|
|
8
|
+
<v-card class="pa-1">
|
|
9
|
+
<v-card-title v-if="title" class="title loading">
|
|
10
|
+
{{ $t(title) }}
|
|
11
|
+
</v-card-title>
|
|
12
|
+
<v-card-text v-if="text" class="px-4">
|
|
13
|
+
{{ $t(text) }}
|
|
14
|
+
</v-card-text>
|
|
15
|
+
<div class="d-flex justify-end px-4" v-if="hasProgress">
|
|
16
|
+
{{ localProgress }}%
|
|
17
|
+
</div>
|
|
18
|
+
<div class="px-4 pb-1 pt-2">
|
|
19
|
+
<v-progress-linear
|
|
20
|
+
:model-value="localProgress"
|
|
21
|
+
:indeterminate="!hasProgress"
|
|
22
|
+
rounded
|
|
23
|
+
/>
|
|
24
|
+
</div>
|
|
25
|
+
<template #actions v-if="cancellable">
|
|
26
|
+
<div class="pa-2">
|
|
27
|
+
<VcsFormButton @click="show = false">
|
|
28
|
+
{{ $t('components.cancel') }}
|
|
29
|
+
</VcsFormButton>
|
|
30
|
+
</div>
|
|
31
|
+
</template>
|
|
32
|
+
</v-card>
|
|
33
|
+
</v-dialog>
|
|
34
|
+
</template>
|
|
35
|
+
|
|
36
|
+
<script>
|
|
37
|
+
import {
|
|
38
|
+
VDialog,
|
|
39
|
+
VCard,
|
|
40
|
+
VCardText,
|
|
41
|
+
VProgressLinear,
|
|
42
|
+
VCardTitle,
|
|
43
|
+
} from 'vuetify/components';
|
|
44
|
+
import { computed, ref, watch } from 'vue';
|
|
45
|
+
import VcsFormButton from '../buttons/VcsFormButton.vue';
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @description Basic overlay to display a progress bar on a VCard, with optional text and cancel button.
|
|
49
|
+
* @vue-prop {import("vue").Ref<number>|undefined} [progress] - The current progress value, between 0 and 1.
|
|
50
|
+
* @vue-prop {string} [title] - The title of the overlay. Will be translated.
|
|
51
|
+
* @vue-prop {string} [text=''] - Optional text to display in the overlay. Will be translated.
|
|
52
|
+
* @vue-prop {boolean} [cancellable=true] - Whether the overlay can be cancelled by the user.
|
|
53
|
+
* @vue-prop {string|number} [maxWidth='500'] - Optional max-width for the dialog.
|
|
54
|
+
* @vue-prop {boolean} [persistent=true] - Whether the dialog should be persistent (not dismissible by clicking outside).
|
|
55
|
+
*/
|
|
56
|
+
export default {
|
|
57
|
+
name: 'VcsLoadingOverlay',
|
|
58
|
+
components: {
|
|
59
|
+
VDialog,
|
|
60
|
+
VCard,
|
|
61
|
+
VCardTitle,
|
|
62
|
+
VCardText,
|
|
63
|
+
VProgressLinear,
|
|
64
|
+
VcsFormButton,
|
|
65
|
+
},
|
|
66
|
+
props: {
|
|
67
|
+
progress: {
|
|
68
|
+
type: [Object, Number, undefined],
|
|
69
|
+
default: undefined,
|
|
70
|
+
},
|
|
71
|
+
title: {
|
|
72
|
+
type: String,
|
|
73
|
+
default: '',
|
|
74
|
+
},
|
|
75
|
+
text: {
|
|
76
|
+
type: String,
|
|
77
|
+
default: '',
|
|
78
|
+
},
|
|
79
|
+
cancellable: {
|
|
80
|
+
type: Boolean,
|
|
81
|
+
default: true,
|
|
82
|
+
},
|
|
83
|
+
maxWidth: {
|
|
84
|
+
type: [String, Number],
|
|
85
|
+
default: '500px',
|
|
86
|
+
},
|
|
87
|
+
persistent: {
|
|
88
|
+
type: Boolean,
|
|
89
|
+
default: true,
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
emits: ['cancel'],
|
|
93
|
+
setup(props, { emit }) {
|
|
94
|
+
const show = ref(true);
|
|
95
|
+
watch(show, () => {
|
|
96
|
+
if (!show.value) {
|
|
97
|
+
emit('cancel');
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
return {
|
|
101
|
+
show,
|
|
102
|
+
hasProgress: props.progress !== undefined,
|
|
103
|
+
localProgress: computed(() => {
|
|
104
|
+
if (props.progress && props.progress.value !== undefined) {
|
|
105
|
+
return Math.round(props.progress.value * 100);
|
|
106
|
+
}
|
|
107
|
+
return 0;
|
|
108
|
+
}),
|
|
109
|
+
};
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
</script>
|
|
113
|
+
|
|
114
|
+
<style scoped lang="scss">
|
|
115
|
+
.title {
|
|
116
|
+
font-size: calc(var(--v-vcs-font-size) * 1.2);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.loading:after {
|
|
120
|
+
content: ' .';
|
|
121
|
+
animation: dots 2s steps(4, end) infinite;
|
|
122
|
+
}
|
|
123
|
+
@keyframes dots {
|
|
124
|
+
0%,
|
|
125
|
+
100% {
|
|
126
|
+
content: '';
|
|
127
|
+
}
|
|
128
|
+
25% {
|
|
129
|
+
content: '.';
|
|
130
|
+
}
|
|
131
|
+
50% {
|
|
132
|
+
content: '..';
|
|
133
|
+
}
|
|
134
|
+
75% {
|
|
135
|
+
content: '...';
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
</style>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<v-container class="pa-0
|
|
2
|
+
<v-container class="pa-0 vcs-workspace-wrapper">
|
|
3
3
|
<slot />
|
|
4
4
|
<div v-if="showFooter">
|
|
5
5
|
<v-divider class="mt-3" />
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
* @vue-prop {boolean} [disableAdd=false] - Flag to render add button disabled.
|
|
43
43
|
* @vue-prop {boolean} [tooltipAdd='components.addToMyWorkspace'] - Option to change the add button tooltip.
|
|
44
44
|
* @vue-prop {boolean} [disableNew=false] - Flag to render new button disabled.
|
|
45
|
-
* @vue-prop {boolean} [tooltipNew''] - Option to change the add a tooltip to the new button.
|
|
45
|
+
* @vue-prop {boolean} [tooltipNew=''] - Option to change the add a tooltip to the new button.
|
|
46
46
|
* @vue-prop {Array<VcsAction>} [actions] - Optional actions rendered as ActionButtonList in the footer.
|
|
47
47
|
* @vue-prop {string} [newButtonTitle='components.new'] - Option to change the new button title, e.g. to 'components.apply'.
|
|
48
48
|
* @vue-event {Event} addClicked - Event fired on clicking the reset button.
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
* @vue-slot secondaryButton An optionnal named slot to add a secondary button to the footer, rendered filled on the left of the new button.
|
|
51
51
|
*/
|
|
52
52
|
export default {
|
|
53
|
-
name: '
|
|
53
|
+
name: 'VcsWorkspaceWrapper',
|
|
54
54
|
components: {
|
|
55
55
|
VContainer,
|
|
56
56
|
VDivider,
|
|
@@ -13,7 +13,12 @@
|
|
|
13
13
|
:feature-properties="featureProperties"
|
|
14
14
|
:allow-z-input="is3D"
|
|
15
15
|
/>
|
|
16
|
-
<div v-else class="
|
|
16
|
+
<div v-else-if="showInputs" class="py-1">
|
|
17
|
+
<VcsFeatureInputEditor
|
|
18
|
+
:is3-d="is3D && featureProperties.altitudeMode === 'absolute'"
|
|
19
|
+
/>
|
|
20
|
+
</div>
|
|
21
|
+
<div v-else class="py-1">
|
|
17
22
|
{{ $t('components.editor.modifyInfo') }}
|
|
18
23
|
</div>
|
|
19
24
|
</div>
|
|
@@ -67,6 +72,7 @@
|
|
|
67
72
|
} from './VcsVectorPropertiesComponent.vue';
|
|
68
73
|
import VcsFormSection from '../section/VcsFormSection.vue';
|
|
69
74
|
import VcsSnapTo from './VcsSnapTo.vue';
|
|
75
|
+
import VcsFeatureInputEditor from './VcsFeatureInputEditor.vue';
|
|
70
76
|
|
|
71
77
|
/**
|
|
72
78
|
* @typedef {Object} EditorManager
|
|
@@ -150,6 +156,7 @@
|
|
|
150
156
|
VSheet,
|
|
151
157
|
VcsFormSection,
|
|
152
158
|
VcsVectorPropertiesComponent,
|
|
159
|
+
VcsFeatureInputEditor,
|
|
153
160
|
VcsFeatureStyleComponent,
|
|
154
161
|
},
|
|
155
162
|
props: {
|
|
@@ -186,6 +193,10 @@
|
|
|
186
193
|
type: Boolean,
|
|
187
194
|
default: true,
|
|
188
195
|
},
|
|
196
|
+
showInputEditor: {
|
|
197
|
+
type: Boolean,
|
|
198
|
+
default: false,
|
|
199
|
+
},
|
|
189
200
|
},
|
|
190
201
|
setup(props) {
|
|
191
202
|
const vcsApp = inject('vcsApp');
|
|
@@ -463,8 +474,16 @@
|
|
|
463
474
|
availableVectorProperties,
|
|
464
475
|
is3D,
|
|
465
476
|
is2DFeature,
|
|
477
|
+
isGeometryEditing,
|
|
466
478
|
updateFeatureProperties,
|
|
467
479
|
defaultVectorProperties: VectorProperties.getDefaultOptions(),
|
|
480
|
+
showInputs: computed(
|
|
481
|
+
() =>
|
|
482
|
+
!currentTransformationMode.value &&
|
|
483
|
+
props.showInputEditor &&
|
|
484
|
+
features.value.length === 1 &&
|
|
485
|
+
features.value[0]?.getGeometry()?.getType() === 'Point',
|
|
486
|
+
),
|
|
468
487
|
};
|
|
469
488
|
},
|
|
470
489
|
};
|
|
@@ -42,6 +42,10 @@ declare const _default: import("vue").DefineComponent<{
|
|
|
42
42
|
type: BooleanConstructor;
|
|
43
43
|
default: boolean;
|
|
44
44
|
};
|
|
45
|
+
showInputEditor: {
|
|
46
|
+
type: BooleanConstructor;
|
|
47
|
+
default: boolean;
|
|
48
|
+
};
|
|
45
49
|
}, {
|
|
46
50
|
featureProperties: import("vue").ShallowRef<any>;
|
|
47
51
|
session: import("vue").ShallowRef<import("@vcmap/core", { with: { "resolution-mode": "import" } }).SelectFeaturesSession | import("@vcmap/core", { with: { "resolution-mode": "import" } }).CreateFeatureSession<GeometryType> | undefined>;
|
|
@@ -53,8 +57,10 @@ declare const _default: import("vue").DefineComponent<{
|
|
|
53
57
|
availableVectorProperties: import("vue").ShallowRef<never[]>;
|
|
54
58
|
is3D: import("vue").Ref<boolean>;
|
|
55
59
|
is2DFeature: import("vue").ComputedRef<boolean>;
|
|
60
|
+
isGeometryEditing: import("vue").ComputedRef<boolean>;
|
|
56
61
|
updateFeatureProperties: (update: import("@vcmap/core").VectorPropertiesOptions) => void;
|
|
57
62
|
defaultVectorProperties: import("@vcmap/core", { with: { "resolution-mode": "import" } }).VectorPropertiesOptions;
|
|
63
|
+
showInputs: import("vue").ComputedRef<boolean>;
|
|
58
64
|
}, any, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
59
65
|
allowedVectorProperties: {
|
|
60
66
|
type: ArrayConstructor;
|
|
@@ -84,6 +90,10 @@ declare const _default: import("vue").DefineComponent<{
|
|
|
84
90
|
type: BooleanConstructor;
|
|
85
91
|
default: boolean;
|
|
86
92
|
};
|
|
93
|
+
showInputEditor: {
|
|
94
|
+
type: BooleanConstructor;
|
|
95
|
+
default: boolean;
|
|
96
|
+
};
|
|
87
97
|
}>>, {
|
|
88
98
|
altitudeModes: unknown[];
|
|
89
99
|
allowedVectorProperties: unknown[];
|
|
@@ -92,6 +102,7 @@ declare const _default: import("vue").DefineComponent<{
|
|
|
92
102
|
showResetVectorProperties: boolean;
|
|
93
103
|
showStyle: boolean;
|
|
94
104
|
showSnapping: boolean;
|
|
105
|
+
showInputEditor: boolean;
|
|
95
106
|
}, {}>;
|
|
96
107
|
export default _default;
|
|
97
108
|
export type EditorManager = {
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="vcs-point-input-editor">
|
|
3
|
+
<v-row no-gutters>
|
|
4
|
+
<v-col>
|
|
5
|
+
<VcsLabel html-for="posX">
|
|
6
|
+
{{ $t('components.editor.position.x') }}
|
|
7
|
+
</VcsLabel>
|
|
8
|
+
</v-col>
|
|
9
|
+
<v-col>
|
|
10
|
+
<VcsTextField
|
|
11
|
+
id="posX"
|
|
12
|
+
type="number"
|
|
13
|
+
v-model.number="coordinates[0]"
|
|
14
|
+
@update:model-value="isEdited = true"
|
|
15
|
+
/>
|
|
16
|
+
</v-col>
|
|
17
|
+
</v-row>
|
|
18
|
+
<v-row no-gutters>
|
|
19
|
+
<v-col>
|
|
20
|
+
<VcsLabel html-for="posY">
|
|
21
|
+
{{ $t('components.editor.position.y') }}
|
|
22
|
+
</VcsLabel>
|
|
23
|
+
</v-col>
|
|
24
|
+
<v-col>
|
|
25
|
+
<VcsTextField
|
|
26
|
+
id="posY"
|
|
27
|
+
type="number"
|
|
28
|
+
v-model.number="coordinates[1]"
|
|
29
|
+
@update:model-value="isEdited = true"
|
|
30
|
+
/>
|
|
31
|
+
</v-col>
|
|
32
|
+
</v-row>
|
|
33
|
+
<v-row no-gutters v-if="is3D">
|
|
34
|
+
<v-col>
|
|
35
|
+
<VcsLabel html-for="posZ">
|
|
36
|
+
{{ $t('components.editor.position.z') }}
|
|
37
|
+
</VcsLabel>
|
|
38
|
+
</v-col>
|
|
39
|
+
<v-col>
|
|
40
|
+
<VcsTextField
|
|
41
|
+
id="posZ"
|
|
42
|
+
type="number"
|
|
43
|
+
v-model.number="coordinates[2]"
|
|
44
|
+
@update:model-value="isEdited = true"
|
|
45
|
+
/>
|
|
46
|
+
</v-col>
|
|
47
|
+
</v-row>
|
|
48
|
+
<v-row no-gutters v-if="isEdited" class="d-flex justify-end gc-1">
|
|
49
|
+
<VcsToolButton @click="cancel">
|
|
50
|
+
{{ $t('components.cancel') }}
|
|
51
|
+
</VcsToolButton>
|
|
52
|
+
<VcsToolButton @click="apply">
|
|
53
|
+
{{ $t('components.apply') }}
|
|
54
|
+
</VcsToolButton>
|
|
55
|
+
</v-row>
|
|
56
|
+
</div>
|
|
57
|
+
</template>
|
|
58
|
+
|
|
59
|
+
<script>
|
|
60
|
+
import { VCol, VRow } from 'vuetify/components';
|
|
61
|
+
import { inject, onUnmounted, ref } from 'vue';
|
|
62
|
+
import {
|
|
63
|
+
getDefaultProjection,
|
|
64
|
+
mercatorProjection,
|
|
65
|
+
Projection,
|
|
66
|
+
} from '@vcmap/core';
|
|
67
|
+
import { getLogger } from '@vcsuite/logger';
|
|
68
|
+
import VcsLabel from '../form-inputs-controls/VcsLabel.vue';
|
|
69
|
+
import VcsTextField from '../form-inputs-controls/VcsTextField.vue';
|
|
70
|
+
import VcsToolButton from '../buttons/VcsToolButton.vue';
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* @description Component to edit the position of a feature in a vector layer. Currently
|
|
74
|
+
* only supports point features, which need to be the currently selected feature in the manager.
|
|
75
|
+
* @vue-prop {boolean} is3D - Whether the feature is in 3D.
|
|
76
|
+
*/
|
|
77
|
+
export default {
|
|
78
|
+
name: 'VcsFeatureEditingWindow',
|
|
79
|
+
components: {
|
|
80
|
+
VCol,
|
|
81
|
+
VRow,
|
|
82
|
+
VcsLabel,
|
|
83
|
+
VcsTextField,
|
|
84
|
+
VcsToolButton,
|
|
85
|
+
},
|
|
86
|
+
props: {
|
|
87
|
+
is3D: {
|
|
88
|
+
type: Boolean,
|
|
89
|
+
required: true,
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
setup() {
|
|
93
|
+
const { currentFeatures: features } = inject('manager');
|
|
94
|
+
|
|
95
|
+
if (
|
|
96
|
+
features.value.length !== 1 ||
|
|
97
|
+
features.value[0]?.getGeometry()?.getType() !== 'Point'
|
|
98
|
+
) {
|
|
99
|
+
getLogger('VcsFeatureEditingWindow').error(
|
|
100
|
+
'This component only supports editing a single point feature.',
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const isEdited = ref(false);
|
|
105
|
+
/** @type {import("ol").Feature} */
|
|
106
|
+
const feature = features.value[0];
|
|
107
|
+
const defaultProjection = getDefaultProjection();
|
|
108
|
+
const decimalPlaces = defaultProjection.epsg.includes('4326') ? 6 : 2;
|
|
109
|
+
|
|
110
|
+
function transform(coordinates) {
|
|
111
|
+
return mercatorProjection
|
|
112
|
+
.transformTo(defaultProjection, coordinates)
|
|
113
|
+
.map((c, i) => +c.toFixed(i === 2 ? 2 : decimalPlaces));
|
|
114
|
+
}
|
|
115
|
+
const coordinates = ref(
|
|
116
|
+
transform(feature.getGeometry().getFlatCoordinates()),
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
function updateFromFeature() {
|
|
120
|
+
coordinates.value = transform(
|
|
121
|
+
feature.getGeometry().getFlatCoordinates(),
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
feature.on('change', updateFromFeature);
|
|
125
|
+
onUnmounted(() => {
|
|
126
|
+
feature.un('change', updateFromFeature);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
function updateFromInput() {
|
|
130
|
+
let updatedCoordinates;
|
|
131
|
+
try {
|
|
132
|
+
updatedCoordinates = Projection.transform(
|
|
133
|
+
mercatorProjection,
|
|
134
|
+
defaultProjection,
|
|
135
|
+
coordinates.value,
|
|
136
|
+
);
|
|
137
|
+
feature.getGeometry().setCoordinates(updatedCoordinates);
|
|
138
|
+
} catch (error) {
|
|
139
|
+
getLogger('VcsFeatureEditingWindow').error(
|
|
140
|
+
'Invalid coordinates input',
|
|
141
|
+
error,
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return {
|
|
147
|
+
isEdited,
|
|
148
|
+
coordinates,
|
|
149
|
+
apply: () => {
|
|
150
|
+
updateFromInput();
|
|
151
|
+
isEdited.value = false;
|
|
152
|
+
},
|
|
153
|
+
cancel: () => {
|
|
154
|
+
updateFromFeature();
|
|
155
|
+
isEdited.value = false;
|
|
156
|
+
},
|
|
157
|
+
};
|
|
158
|
+
},
|
|
159
|
+
};
|
|
160
|
+
</script>
|
|
161
|
+
|
|
162
|
+
<style scoped>
|
|
163
|
+
:deep(.v-btn__content):hover {
|
|
164
|
+
color: rgb(var(--v-theme-primary));
|
|
165
|
+
}
|
|
166
|
+
</style>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
declare const _default: import("vue").DefineComponent<{
|
|
2
|
+
is3D: {
|
|
3
|
+
type: BooleanConstructor;
|
|
4
|
+
required: true;
|
|
5
|
+
};
|
|
6
|
+
}, {
|
|
7
|
+
isEdited: import("vue").Ref<boolean>;
|
|
8
|
+
coordinates: import("vue").Ref<number[]>;
|
|
9
|
+
apply: () => void;
|
|
10
|
+
cancel: () => void;
|
|
11
|
+
}, any, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
12
|
+
is3D: {
|
|
13
|
+
type: BooleanConstructor;
|
|
14
|
+
required: true;
|
|
15
|
+
};
|
|
16
|
+
}>>, {}, {}>;
|
|
17
|
+
export default _default;
|
|
@@ -23,6 +23,11 @@ declare class ContentTreeCollection extends IndexedCollection<ContentTreeItem> {
|
|
|
23
23
|
* @param {import("@src/vcsUiApp.js").default} app
|
|
24
24
|
*/
|
|
25
25
|
constructor(app: import("@src/vcsUiApp.js").default);
|
|
26
|
+
/**
|
|
27
|
+
* @type {string|undefined}
|
|
28
|
+
* @private
|
|
29
|
+
*/
|
|
30
|
+
private _removedListenerTimeoutId;
|
|
26
31
|
/**
|
|
27
32
|
* @type {import("@src/vcsUiApp.js").default}
|
|
28
33
|
* @private
|
|
@@ -31,6 +31,11 @@ export const defaultContentTreeComponentId = 'Content';
|
|
|
31
31
|
* @extends {IndexedCollection<ContentTreeItem>}
|
|
32
32
|
*/
|
|
33
33
|
class ContentTreeCollection extends IndexedCollection {
|
|
34
|
+
/**
|
|
35
|
+
* @type {string|undefined}
|
|
36
|
+
* @private
|
|
37
|
+
*/
|
|
38
|
+
_removedListenerTimeoutId;
|
|
34
39
|
/**
|
|
35
40
|
* @param {import("@src/vcsUiApp.js").default} app
|
|
36
41
|
*/
|
|
@@ -75,13 +80,13 @@ class ContentTreeCollection extends IndexedCollection {
|
|
|
75
80
|
'contentTreeActiveOnStartup',
|
|
76
81
|
);
|
|
77
82
|
if (
|
|
78
|
-
contentTreeActiveOnStartup?.value &&
|
|
83
|
+
contentTreeActiveOnStartup?.value != null &&
|
|
79
84
|
contentTreeActiveOnStartup[moduleIdSymbol] !== this._app.dynamicModuleId
|
|
80
85
|
) {
|
|
81
86
|
const action = this._app.navbarManager.get(
|
|
82
87
|
defaultContentTreeComponentId,
|
|
83
88
|
)?.action;
|
|
84
|
-
if (action &&
|
|
89
|
+
if (action && action.active !== contentTreeActiveOnStartup.value) {
|
|
85
90
|
action.callback();
|
|
86
91
|
}
|
|
87
92
|
}
|
|
@@ -107,7 +112,10 @@ class ContentTreeCollection extends IndexedCollection {
|
|
|
107
112
|
}
|
|
108
113
|
}),
|
|
109
114
|
this.removed.addEventListener((child) => {
|
|
110
|
-
|
|
115
|
+
clearTimeout(this._removedListenerTimeoutId);
|
|
116
|
+
this._removedListenerTimeoutId = setTimeout(() => {
|
|
117
|
+
recreateTree();
|
|
118
|
+
}, 0);
|
|
111
119
|
if (this._weightListeners.has(child.name)) {
|
|
112
120
|
this._weightListeners.get(child.name)();
|
|
113
121
|
this._weightListeners.delete(child.name);
|
|
@@ -272,11 +272,11 @@ declare class ContentTreeItem {
|
|
|
272
272
|
/**
|
|
273
273
|
* @param {(string|HTMLCanvasElement|HTMLImageElement)=} icon
|
|
274
274
|
*/
|
|
275
|
-
set icon(icon: string |
|
|
275
|
+
set icon(icon: string | HTMLCanvasElement | HTMLImageElement | undefined);
|
|
276
276
|
/**
|
|
277
277
|
* @type {string|HTMLCanvasElement|HTMLImageElement|undefined}
|
|
278
278
|
*/
|
|
279
|
-
get icon(): string |
|
|
279
|
+
get icon(): string | HTMLCanvasElement | HTMLImageElement | undefined;
|
|
280
280
|
/**
|
|
281
281
|
* @param {number} weight
|
|
282
282
|
*/
|
|
@@ -522,6 +522,10 @@ class WMSGroupContentTreeItem extends VcsObjectContentTreeItem {
|
|
|
522
522
|
this._layer.url,
|
|
523
523
|
this._layer.parameters,
|
|
524
524
|
);
|
|
525
|
+
// check if the layer still exists, it can happen that the layer was removed while fetching the capabilities.
|
|
526
|
+
if (!this._layer) {
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
525
529
|
this._availableWMSEntries = availableWMSEntries.filter((wmsEntry) => {
|
|
526
530
|
return this._allowedWMSLayers
|
|
527
531
|
? this._allowedWMSLayers.includes(wmsEntry.name)
|
|
@@ -558,9 +562,12 @@ class WMSGroupContentTreeItem extends VcsObjectContentTreeItem {
|
|
|
558
562
|
this._setState();
|
|
559
563
|
this._setLegend();
|
|
560
564
|
} catch (e) {
|
|
561
|
-
|
|
562
|
-
this.
|
|
563
|
-
|
|
565
|
+
// if the layer is not there it has been removed while fetching the capabilities.
|
|
566
|
+
if (this._layer) {
|
|
567
|
+
this._layer.deactivate();
|
|
568
|
+
this.visible = false;
|
|
569
|
+
this._invalid = true;
|
|
570
|
+
}
|
|
564
571
|
getLogger(this.className).error(
|
|
565
572
|
`An error occured while fetching the ${this._layerName} capabilities:`,
|
|
566
573
|
e,
|