@vcmap/ui 5.0.0-rc.28 → 5.0.0-rc.30
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/base.config.json +22 -0
- package/config/dev.config.json +4 -0
- package/dist/assets/cesium/Workers/cesiumWorkerBootstrapper.js +1 -1
- package/dist/assets/cesium/Workers/package.js +1 -1
- package/dist/assets/cesium/Workers/transferTypedArrayTest.js +1 -1
- package/dist/assets/{cesium.973919.js → cesium.eaf7cc.js} +149552 -149560
- package/dist/assets/cesium.js +1 -1
- package/dist/assets/{core.7a2173.js → core.b16511.js} +4077 -3965
- package/dist/assets/core.js +1 -1
- package/dist/assets/index-c115e3a1.js +1 -0
- package/dist/assets/{ol.f6e2e4.js → ol.4bbf0f.js} +11405 -11126
- package/dist/assets/ol.js +1 -1
- package/dist/assets/{ui.bd7a9a.css → ui.ab815e.css} +2 -2
- package/dist/assets/{ui.bd7a9a.js → ui.ab815e.js} +4232 -3512
- package/dist/assets/ui.js +1 -1
- package/dist/assets/vue.js +2 -2
- package/dist/assets/{vuetify.95f6c3.js → vuetify.ea3fa8.js} +1 -1
- package/dist/assets/vuetify.js +2 -2
- package/dist/index.html +1 -1
- package/index.js +7 -0
- package/lib/olLib.js +6 -0
- package/package.json +3 -3
- package/plugins/@vcmap/search-nominatim/SearchNominatimEditor.vue +90 -0
- package/plugins/@vcmap/search-nominatim/index.js +37 -0
- package/plugins/@vcmap-show-case/form-inputs-example/FormInputsExample.vue +37 -1
- package/plugins/@vcmap-show-case/form-inputs-example/index.js +3 -0
- package/plugins/@vcmap-show-case/form-inputs-example/validation.js +11 -0
- package/plugins/@vcmap-show-case/style-input-example/styleExample.vue +0 -1
- package/plugins/@vcmap-show-case/vector-properties-example/index.js +40 -0
- package/plugins/@vcmap-show-case/vector-properties-example/package.json +5 -0
- package/plugins/@vcmap-show-case/vector-properties-example/vectorPropertiesExample.vue +109 -0
- package/plugins/@vcmap-show-case/window-tester/WindowExample.vue +27 -9
- package/plugins/@vcmap-show-case/window-tester/index.js +13 -1
- package/plugins/@vcmap-show-case/window-tester/windowExampleToggleChild.vue +11 -10
- package/src/actions/actionHelper.js +7 -3
- package/src/application/VcsApp.vue +31 -0
- package/src/components/form-inputs-controls/VcsChipArrayInput.vue +282 -0
- package/src/components/form-inputs-controls/VcsTextField.vue +12 -5
- package/src/components/icons/+all.js +3 -3
- package/src/components/lists/VcsTreeviewLeaf.vue +1 -1
- package/src/components/lists/VcsTreeviewSearchbar.vue +9 -4
- package/src/components/plugins/AbstractConfigEditor.vue +84 -0
- package/src/components/style/VcsImageSelector.vue +6 -5
- package/src/components/style/VcsTextSelector.vue +1 -1
- package/src/components/tables/VcsDataTable.vue +100 -13
- package/src/components/vector-properties/VcsVectorPropertiesComponent.vue +737 -0
- package/src/components/vector-properties/composables.js +93 -0
- package/src/contentTree/contentTreeCollection.js +3 -0
- package/src/featureInfo/abstractFeatureInfoView.js +3 -1
- package/src/featureInfo/balloonFeatureInfoView.js +3 -2
- package/src/featureInfo/featureInfo.js +1 -0
- package/src/i18n/de.js +44 -9
- package/src/i18n/en.js +42 -7
- package/src/manager/collectionManager/collectionComponent.js +1 -1
- package/src/manager/window/WindowComponent.vue +4 -1
- package/src/manager/window/WindowComponentHeader.vue +25 -13
- package/src/manager/window/windowManager.js +6 -2
- package/src/navigation/overviewMap.js +1 -1
- package/src/pluginHelper.js +57 -17
- package/src/uiConfig.js +1 -0
- package/src/vcsUiApp.js +45 -34
- package/dist/assets/index-1b09f88d.js +0 -1
- /package/dist/assets/{vue.d4be99.js → vue.67e80f.js} +0 -0
- /package/dist/assets/{vuetify.95f6c3.css → vuetify.ea3fa8.css} +0 -0
- /package/src/components/icons/{PolygonIcon.vue → PointIcon.vue} +0 -0
@@ -19,6 +19,16 @@
|
|
19
19
|
const app = inject('vcsApp');
|
20
20
|
const parentId = attrs['window-state'].id;
|
21
21
|
const childId = `dynamicChild-${parentId}`;
|
22
|
+
const childComponent = {
|
23
|
+
id: childId,
|
24
|
+
parentId,
|
25
|
+
state: {
|
26
|
+
headerTitle: 'Example dynamicChild',
|
27
|
+
headerIcon: 'mdi-human-child',
|
28
|
+
},
|
29
|
+
component: WindowExampleContent,
|
30
|
+
slot: WindowSlot.DYNAMIC_CHILD,
|
31
|
+
};
|
22
32
|
|
23
33
|
return {
|
24
34
|
toggle(e) {
|
@@ -26,16 +36,7 @@
|
|
26
36
|
app.windowManager.remove(childId);
|
27
37
|
} else {
|
28
38
|
e.stopPropagation();
|
29
|
-
app.windowManager.add(
|
30
|
-
{
|
31
|
-
id: childId,
|
32
|
-
parentId,
|
33
|
-
headerTitle: 'Example dynamicChild',
|
34
|
-
component: WindowExampleContent,
|
35
|
-
slot: WindowSlot.DYNAMIC_CHILD,
|
36
|
-
},
|
37
|
-
owner,
|
38
|
-
);
|
39
|
+
app.windowManager.add(childComponent, owner);
|
39
40
|
}
|
40
41
|
},
|
41
42
|
};
|
@@ -284,7 +284,7 @@ export function createModalAction(actionOptions, modalComponent, app, owner) {
|
|
284
284
|
/**
|
285
285
|
* Creates an action which opens a given link in a new tab
|
286
286
|
* @param {ActionOptions} actionOptions
|
287
|
-
* @param {string} url
|
287
|
+
* @param {string|function():string} url
|
288
288
|
* @returns {VcsAction}
|
289
289
|
*/
|
290
290
|
export function createLinkAction(actionOptions, url) {
|
@@ -293,13 +293,17 @@ export function createLinkAction(actionOptions, url) {
|
|
293
293
|
icon: [undefined, String],
|
294
294
|
title: [undefined, String],
|
295
295
|
});
|
296
|
-
check(url, String);
|
296
|
+
check(url, [String, Function]);
|
297
297
|
|
298
298
|
return {
|
299
299
|
...actionOptions,
|
300
300
|
callback() {
|
301
301
|
const link = document.createElement('a');
|
302
|
-
|
302
|
+
if (typeof url === 'string') {
|
303
|
+
link.href = url;
|
304
|
+
} else {
|
305
|
+
link.href = url();
|
306
|
+
}
|
303
307
|
link.target = '_blank';
|
304
308
|
link.click();
|
305
309
|
},
|
@@ -94,6 +94,7 @@
|
|
94
94
|
import VcsMap from './VcsMap.vue';
|
95
95
|
import VcsNavbar from './VcsNavbar.vue';
|
96
96
|
import {
|
97
|
+
createLinkAction,
|
97
98
|
createMapButtonAction,
|
98
99
|
createToggleAction,
|
99
100
|
} from '../actions/actionHelper.js';
|
@@ -226,6 +227,9 @@
|
|
226
227
|
state: {
|
227
228
|
headerTitle: 'legend.title',
|
228
229
|
headerIcon: '$vcsLegend',
|
230
|
+
infoUrl: app.getHelpUrlCallback(
|
231
|
+
'/components/contentspace.html#id_legend',
|
232
|
+
),
|
229
233
|
},
|
230
234
|
slot: WindowSlot.DYNAMIC_RIGHT,
|
231
235
|
props: { entries },
|
@@ -324,6 +328,29 @@
|
|
324
328
|
};
|
325
329
|
}
|
326
330
|
|
331
|
+
/**
|
332
|
+
* This helper function will add a help action button referencing VC Map help page to the apps NavbarManager MENU location.
|
333
|
+
* @param {VcsUiApp} app
|
334
|
+
*/
|
335
|
+
export function setupHelpButton(app) {
|
336
|
+
const helpAction = createLinkAction(
|
337
|
+
{
|
338
|
+
name: 'help.title',
|
339
|
+
title: 'help.tooltip',
|
340
|
+
icon: '$vcsHelp',
|
341
|
+
},
|
342
|
+
app.getHelpUrlCallback(),
|
343
|
+
);
|
344
|
+
app.navbarManager.add(
|
345
|
+
{
|
346
|
+
id: 'helpButton',
|
347
|
+
action: helpAction,
|
348
|
+
},
|
349
|
+
vcsAppSymbol,
|
350
|
+
ButtonLocation.MENU,
|
351
|
+
);
|
352
|
+
}
|
353
|
+
|
327
354
|
/**
|
328
355
|
* This helper function will add a category manager button to the navbar. The category Manager
|
329
356
|
* will only be shown if there is at least one category under management in the categoryManager.
|
@@ -343,6 +370,9 @@
|
|
343
370
|
state: {
|
344
371
|
headerTitle: 'categoryManager.title',
|
345
372
|
headerIcon: '$vcsComponents',
|
373
|
+
infoUrl: app.getHelpUrlCallback(
|
374
|
+
'/components/contentspace.html#id_myWorkspace',
|
375
|
+
),
|
346
376
|
},
|
347
377
|
component: CollectionManager,
|
348
378
|
provides: {
|
@@ -517,6 +547,7 @@
|
|
517
547
|
const mapNavbarListener = setupMapNavbar(app);
|
518
548
|
const legendDestroy = setupLegendWindow(app);
|
519
549
|
const settingsDestroy = setupSettingsWindow(app);
|
550
|
+
setupHelpButton(app);
|
520
551
|
const destroyComponentsWindow = setupCategoryManagerWindow(app);
|
521
552
|
const destroyThemingListener = setupUiConfigTheming(
|
522
553
|
app,
|
@@ -0,0 +1,282 @@
|
|
1
|
+
<template>
|
2
|
+
<div id="vcs-chip-array-input" class="d-flex d-inline-block align-center">
|
3
|
+
<v-btn
|
4
|
+
v-if="hasScrollbar"
|
5
|
+
:dense="isDense"
|
6
|
+
x-small
|
7
|
+
icon
|
8
|
+
:ripple="false"
|
9
|
+
elevation="0"
|
10
|
+
@click="vcsChipArrayInput.scrollLeft -= scrollDx"
|
11
|
+
>
|
12
|
+
<v-icon>mdi-chevron-left</v-icon>
|
13
|
+
</v-btn>
|
14
|
+
<div
|
15
|
+
id="vcs-chip-array-input"
|
16
|
+
ref="vcsChipArrayInput"
|
17
|
+
class="d-flex d-inline-block"
|
18
|
+
:class="{
|
19
|
+
'overflow-x-auto': !column,
|
20
|
+
'hide-scrollbar': !column,
|
21
|
+
row: column,
|
22
|
+
'ma-1': !hasScrollbar,
|
23
|
+
}"
|
24
|
+
>
|
25
|
+
<div v-for="(item, index) in value" :key="index" class="py-1 pr-1">
|
26
|
+
<v-chip
|
27
|
+
v-if="selected !== index"
|
28
|
+
v-bind="{ ...$attrs }"
|
29
|
+
:small="isDense"
|
30
|
+
:disabled="disabled"
|
31
|
+
:close="deletableChips"
|
32
|
+
@click="select(index)"
|
33
|
+
@click:close="remove(index)"
|
34
|
+
class="pa-2"
|
35
|
+
>
|
36
|
+
<span class="text-truncate d-inline-block">{{ item }}</span>
|
37
|
+
</v-chip>
|
38
|
+
<VcsTextField
|
39
|
+
v-else
|
40
|
+
hide-details
|
41
|
+
:dense="isDense"
|
42
|
+
rounded
|
43
|
+
filled
|
44
|
+
autofocus
|
45
|
+
no-padding
|
46
|
+
:height="24"
|
47
|
+
v-bind="{ ...$attrs }"
|
48
|
+
v-model="editValue"
|
49
|
+
@keydown.esc="selected = -1"
|
50
|
+
@blur="selected = -1"
|
51
|
+
@keydown.enter="submitChange"
|
52
|
+
@click:append="submitChange"
|
53
|
+
@update:error="(err) => (isEditValid = !err)"
|
54
|
+
append-icon="mdi-check"
|
55
|
+
:style="{ width: `${inputWidth}px` }"
|
56
|
+
/>
|
57
|
+
</div>
|
58
|
+
<div class="py-1">
|
59
|
+
<v-chip
|
60
|
+
v-if="adding === false"
|
61
|
+
v-bind="{ ...$attrs }"
|
62
|
+
:small="isDense"
|
63
|
+
:disabled="disabled"
|
64
|
+
@click="adding = true"
|
65
|
+
class="pa-2"
|
66
|
+
>
|
67
|
+
<v-icon>$vcsPlus</v-icon>
|
68
|
+
</v-chip>
|
69
|
+
<VcsTextField
|
70
|
+
v-else
|
71
|
+
hide-details
|
72
|
+
:dense="isDense"
|
73
|
+
rounded
|
74
|
+
filled
|
75
|
+
autofocus
|
76
|
+
no-padding
|
77
|
+
:height="24"
|
78
|
+
class="vcs-inside-chip"
|
79
|
+
v-model="newValue"
|
80
|
+
v-bind="{ ...$attrs }"
|
81
|
+
@keydown.enter="add(newValue)"
|
82
|
+
@keydown.esc="cancel"
|
83
|
+
@blur="cancel"
|
84
|
+
@click:append="add(newValue)"
|
85
|
+
@update:error="(err) => (isNewValid = !err)"
|
86
|
+
append-icon="mdi-check"
|
87
|
+
:style="{ width: `${inputWidth}px` }"
|
88
|
+
/>
|
89
|
+
</div>
|
90
|
+
</div>
|
91
|
+
<v-btn
|
92
|
+
v-if="hasScrollbar"
|
93
|
+
:dense="isDense"
|
94
|
+
x-small
|
95
|
+
icon
|
96
|
+
:ripple="false"
|
97
|
+
elevation="0"
|
98
|
+
@click="vcsChipArrayInput.scrollLeft += scrollDx"
|
99
|
+
>
|
100
|
+
<v-icon>mdi-chevron-right</v-icon>
|
101
|
+
</v-btn>
|
102
|
+
</div>
|
103
|
+
</template>
|
104
|
+
|
105
|
+
<style lang="scss" scoped>
|
106
|
+
.hide-scrollbar {
|
107
|
+
-ms-overflow-style: none; /* IE and Edge */
|
108
|
+
scrollbar-width: none; /* Firefox */
|
109
|
+
}
|
110
|
+
.hide-scrollbar::-webkit-scrollbar {
|
111
|
+
display: none;
|
112
|
+
}
|
113
|
+
.v-chip {
|
114
|
+
display: flex;
|
115
|
+
max-width: 260px;
|
116
|
+
padding: 0 8px;
|
117
|
+
.v-chip__content {
|
118
|
+
display: flex;
|
119
|
+
}
|
120
|
+
}
|
121
|
+
.vcs-inside-chip {
|
122
|
+
::v-deep {
|
123
|
+
.v-input__slot {
|
124
|
+
.v-input__append-inner {
|
125
|
+
margin-top: 5px;
|
126
|
+
}
|
127
|
+
}
|
128
|
+
.v-text-field--filled > .v-input__control > .v-input__slot,
|
129
|
+
.v-text-field--outlined > .v-input__control > .v-input__slot {
|
130
|
+
min-height: unset;
|
131
|
+
}
|
132
|
+
}
|
133
|
+
}
|
134
|
+
</style>
|
135
|
+
|
136
|
+
<script>
|
137
|
+
import { computed, nextTick, onMounted, ref } from 'vue';
|
138
|
+
import { VBtn, VChip, VIcon } from 'vuetify/lib';
|
139
|
+
import VcsTextField from './VcsTextField.vue';
|
140
|
+
|
141
|
+
/**
|
142
|
+
* @description Renders elements of an array as chips with an input field to edit or add new elements.
|
143
|
+
* Provides two height options depending on "dense" property
|
144
|
+
* Provides VcsTooltip to show error messages on focus
|
145
|
+
* When clicking esc key, previous input is restored.
|
146
|
+
* @vue-prop {('bottom' | 'left' | 'top' | 'right')} [tooltipPosition='right'] - Position of the error tooltip.
|
147
|
+
* @vue-prop {string} [type] - The input type (string or number)
|
148
|
+
* @vue-prop {boolean} [disabled] - Disables adding or removing new elements
|
149
|
+
* @vue-prop {boolean} [column] - Remove horizontal pagination and wrap items as needed
|
150
|
+
* @vue-prop {boolean} [scrollDx=20] - scroll amount in px
|
151
|
+
* @vue-prop {boolean} [deletableChips=true] - Adds a delete button to elements to remove them from array
|
152
|
+
* @vue-prop {number} [inputWidth=50] - Width of the text fields in px.
|
153
|
+
*/
|
154
|
+
export default {
|
155
|
+
name: 'VcsChipArrayInput',
|
156
|
+
components: {
|
157
|
+
VBtn,
|
158
|
+
VcsTextField,
|
159
|
+
VChip,
|
160
|
+
VIcon,
|
161
|
+
},
|
162
|
+
props: {
|
163
|
+
value: {
|
164
|
+
type: Array,
|
165
|
+
required: true,
|
166
|
+
},
|
167
|
+
tooltipPosition: {
|
168
|
+
type: String,
|
169
|
+
default: 'right',
|
170
|
+
},
|
171
|
+
deletableChips: {
|
172
|
+
type: Boolean,
|
173
|
+
default: true,
|
174
|
+
},
|
175
|
+
inputWidth: {
|
176
|
+
type: Number,
|
177
|
+
default: 50,
|
178
|
+
},
|
179
|
+
disabled: {
|
180
|
+
type: Boolean,
|
181
|
+
default: false,
|
182
|
+
},
|
183
|
+
column: {
|
184
|
+
type: Boolean,
|
185
|
+
default: false,
|
186
|
+
},
|
187
|
+
scrollDx: {
|
188
|
+
type: Number,
|
189
|
+
default: 20,
|
190
|
+
},
|
191
|
+
},
|
192
|
+
setup(props, { attrs, emit }) {
|
193
|
+
const selected = ref(-1);
|
194
|
+
const adding = ref(false);
|
195
|
+
const isEditValid = ref(true);
|
196
|
+
const editValue = ref(undefined);
|
197
|
+
const isNewValid = ref(true);
|
198
|
+
const newValue = ref(undefined);
|
199
|
+
const vcsChipArrayInput = ref();
|
200
|
+
const hasScrollbar = ref();
|
201
|
+
const isDense = computed(() => attrs.dense !== false);
|
202
|
+
|
203
|
+
function emitValue(value) {
|
204
|
+
if (attrs.type === 'number') {
|
205
|
+
emit(
|
206
|
+
'input',
|
207
|
+
value.map((v) => parseFloat(v)),
|
208
|
+
);
|
209
|
+
} else {
|
210
|
+
emit('input', value);
|
211
|
+
}
|
212
|
+
}
|
213
|
+
|
214
|
+
function updateHasScrollbar() {
|
215
|
+
if (!props.column) {
|
216
|
+
hasScrollbar.value =
|
217
|
+
vcsChipArrayInput.value.scrollWidth -
|
218
|
+
vcsChipArrayInput.value.clientWidth >
|
219
|
+
36; // size of the scroll buttons
|
220
|
+
}
|
221
|
+
}
|
222
|
+
|
223
|
+
onMounted(() => updateHasScrollbar());
|
224
|
+
|
225
|
+
function remove(index) {
|
226
|
+
emitValue(props.value.toSpliced(index, 1));
|
227
|
+
updateHasScrollbar();
|
228
|
+
}
|
229
|
+
|
230
|
+
function select(index) {
|
231
|
+
if (!props.disabled) {
|
232
|
+
selected.value = index;
|
233
|
+
editValue.value = props.value[index];
|
234
|
+
}
|
235
|
+
}
|
236
|
+
|
237
|
+
function submitChange() {
|
238
|
+
if (isEditValid.value) {
|
239
|
+
emitValue(props.value.toSpliced(selected.value, 1, editValue.value));
|
240
|
+
selected.value = -1;
|
241
|
+
}
|
242
|
+
}
|
243
|
+
|
244
|
+
function cancel() {
|
245
|
+
newValue.value = undefined;
|
246
|
+
adding.value = false;
|
247
|
+
}
|
248
|
+
|
249
|
+
async function add(value) {
|
250
|
+
if (isNewValid.value) {
|
251
|
+
if (value) {
|
252
|
+
emitValue([...props.value, value]);
|
253
|
+
await nextTick();
|
254
|
+
updateHasScrollbar();
|
255
|
+
await nextTick();
|
256
|
+
vcsChipArrayInput.value.scrollLeft =
|
257
|
+
vcsChipArrayInput.value.scrollWidth;
|
258
|
+
}
|
259
|
+
newValue.value = undefined;
|
260
|
+
adding.value = true;
|
261
|
+
}
|
262
|
+
}
|
263
|
+
|
264
|
+
return {
|
265
|
+
selected,
|
266
|
+
adding,
|
267
|
+
editValue,
|
268
|
+
isEditValid,
|
269
|
+
newValue,
|
270
|
+
isNewValid,
|
271
|
+
isDense,
|
272
|
+
vcsChipArrayInput,
|
273
|
+
hasScrollbar,
|
274
|
+
remove,
|
275
|
+
select,
|
276
|
+
submitChange,
|
277
|
+
add,
|
278
|
+
cancel,
|
279
|
+
};
|
280
|
+
},
|
281
|
+
};
|
282
|
+
</script>
|
@@ -25,8 +25,9 @@
|
|
25
25
|
v-on="{ ...$listeners, ...on }"
|
26
26
|
:height="isDense ? 24 : 32"
|
27
27
|
:rules="rules"
|
28
|
-
class="
|
28
|
+
class="primary--placeholder align-center"
|
29
29
|
:class="{
|
30
|
+
'py-1': !noPadding,
|
30
31
|
'remove-outline': !isOutlined,
|
31
32
|
'outline--current': focus,
|
32
33
|
'outline--error': !!errorMessage,
|
@@ -134,7 +135,7 @@
|
|
134
135
|
.v-icon {
|
135
136
|
font-size: 16px;
|
136
137
|
}
|
137
|
-
fieldset {
|
138
|
+
.v-text-field--rounded fieldset {
|
138
139
|
border-radius: 2px;
|
139
140
|
border-color: var(--v-base-base);
|
140
141
|
}
|
@@ -160,6 +161,7 @@
|
|
160
161
|
* @vue-prop {('bottom' | 'left' | 'top' | 'right')} [tooltipPosition='right'] - Position of the error tooltip.
|
161
162
|
* @vue-prop {string} unit - Unit for number input fields. Is displayed behind the number.
|
162
163
|
* @vue-prop {boolean} showSpinButtons - If true, spin buttons are displayed in number input fields. Overrides Vuetify hide-spin-buttons.
|
164
|
+
* @vue-prop {boolean} noPadding - Padding is required for usage within rows. For standalone usage this prop removes class py-1.
|
163
165
|
* @vue-computed {boolean} isClearable - Whether textfield is isClearable. Makes sure icon is only shown on focus, hover or error.
|
164
166
|
* @vue-computed {boolean} isDense - Whether size of textfield is dense.
|
165
167
|
* @vue-computed {boolean} isOutlined - Textfield is outlined on either hover, focus or error, if not disabled.
|
@@ -186,6 +188,10 @@
|
|
186
188
|
type: Boolean,
|
187
189
|
default: false,
|
188
190
|
},
|
191
|
+
noPadding: {
|
192
|
+
type: Boolean,
|
193
|
+
default: false,
|
194
|
+
},
|
189
195
|
},
|
190
196
|
setup(props, { attrs, emit }) {
|
191
197
|
const hover = ref(false);
|
@@ -223,7 +229,7 @@
|
|
223
229
|
get() {
|
224
230
|
if (
|
225
231
|
attrs.type === 'number' &&
|
226
|
-
attrs.value &&
|
232
|
+
Number.isFinite(attrs.value) &&
|
227
233
|
props.unit &&
|
228
234
|
!focus.value &&
|
229
235
|
!hover.value
|
@@ -233,8 +239,9 @@
|
|
233
239
|
return attrs.value ?? '';
|
234
240
|
}
|
235
241
|
},
|
236
|
-
set(
|
237
|
-
emit
|
242
|
+
set() {
|
243
|
+
// emit is not needed, the vuetify component already emits an @input event. (forwarded listeners)
|
244
|
+
// emit('input', event);
|
238
245
|
},
|
239
246
|
});
|
240
247
|
const type = computed(() => {
|
@@ -63,7 +63,7 @@ import PlayCircleIcon from './PlayCircleIcon.vue';
|
|
63
63
|
import PlusIcon from './PlusIcon.vue';
|
64
64
|
import PoiIcon from './PoiIcon.vue';
|
65
65
|
import PointSelectIcon from './PointSelectIcon.vue';
|
66
|
-
import
|
66
|
+
import PointIcon from './PointIcon.vue';
|
67
67
|
import QueryIcon from './QueryIcon.vue';
|
68
68
|
import PresentationModeIcon from './PresentationModeIcon.vue';
|
69
69
|
import RectangleIcon from './RectangleIcon.vue';
|
@@ -328,8 +328,8 @@ const IconMap = {
|
|
328
328
|
pointSelect: {
|
329
329
|
component: PointSelectIcon,
|
330
330
|
},
|
331
|
-
|
332
|
-
component:
|
331
|
+
point: {
|
332
|
+
component: PointIcon,
|
333
333
|
},
|
334
334
|
query: {
|
335
335
|
component: QueryIcon,
|
@@ -6,7 +6,7 @@
|
|
6
6
|
<v-icon class="search-icon my-0 ml-1" size="12"> $vcsSearch </v-icon>
|
7
7
|
</slot>
|
8
8
|
|
9
|
-
<slot>
|
9
|
+
<slot v-bind="{ ...$props, on: $listeners }">
|
10
10
|
<v-text-field
|
11
11
|
solo
|
12
12
|
dense
|
@@ -19,7 +19,7 @@
|
|
19
19
|
/>
|
20
20
|
</slot>
|
21
21
|
|
22
|
-
<slot name="append">
|
22
|
+
<slot name="append" :has-filter="hasFilter">
|
23
23
|
<v-icon v-if="hasFilter" class="ml-2" size="16">$vcsFilter</v-icon>
|
24
24
|
</slot>
|
25
25
|
</div>
|
@@ -111,9 +111,14 @@
|
|
111
111
|
import { VIcon, VTextField } from 'vuetify/lib';
|
112
112
|
|
113
113
|
/**
|
114
|
-
* @description
|
115
|
-
* @vue-prop {number} height - Height of the component.
|
114
|
+
* @description stylized searchbar used in VcsTreeview, VcsDataTable and VcsList
|
116
115
|
* @vue-prop {string} [placeholder='search.title'] - Placeholder will be displayed in the search field, and will be translated.
|
116
|
+
* @vue-prop {string[]} [customClasses] - CSS classes to customize style
|
117
|
+
* @vue-prop {string} [value] - The search value
|
118
|
+
* @vue-prop {boolean} [hasFilter=false] - Appends a filter icon
|
119
|
+
* @vue-data {slot} [prepend] - prepend slot overwriting search icon
|
120
|
+
* @vue-data {slot} [default] - default slot overwriting search input text field. binds all props
|
121
|
+
* @vue-data {slot} [append] - append slot overwriting filter icon. binds hasFilter prop
|
117
122
|
*/
|
118
123
|
export default {
|
119
124
|
name: 'VcsTreeviewSearchbar',
|
@@ -0,0 +1,84 @@
|
|
1
|
+
<template>
|
2
|
+
<v-container class="pa-0">
|
3
|
+
<v-form v-model="isValid" @submit.prevent="submit">
|
4
|
+
<slot />
|
5
|
+
<div class="d-flex gap-2 px-2 pt-2 pb-1">
|
6
|
+
<div class="d-flex gap-2 w-full justify-start">
|
7
|
+
<VcsFormButton v-if="showReset" icon="$vcsReturn" @click="reset" />
|
8
|
+
</div>
|
9
|
+
<div class="d-flex gap-2 w-full justify-end">
|
10
|
+
<VcsFormButton type="submit" variant="filled" :disabled="!isValid">
|
11
|
+
{{ $t('appConfigurator.apply') }}
|
12
|
+
</VcsFormButton>
|
13
|
+
<VcsFormButton @click.stop="cancel">
|
14
|
+
{{ $t('appConfigurator.cancel') }}
|
15
|
+
</VcsFormButton>
|
16
|
+
<VcsActionButtonList :actions="actions" button="VcsFormButton" />
|
17
|
+
</div>
|
18
|
+
</div>
|
19
|
+
</v-form>
|
20
|
+
</v-container>
|
21
|
+
</template>
|
22
|
+
|
23
|
+
<script>
|
24
|
+
import { VContainer, VForm } from 'vuetify/lib';
|
25
|
+
import { ref, inject } from 'vue';
|
26
|
+
import VcsFormButton from '../buttons/VcsFormButton.vue';
|
27
|
+
import VcsActionButtonList from '../buttons/VcsActionButtonList.vue';
|
28
|
+
|
29
|
+
/**
|
30
|
+
* @description Basic wrapper for all config editor components using {@link https://vuetifyjs.com/en/api/v-form/ |vuetify form}.
|
31
|
+
* Providing a footer with submit, cancel and optionally reset button.
|
32
|
+
* @vue-prop {boolean} [showReset=false] - Flag to show a reset button in the footer. You need to handle @reset in a child component.
|
33
|
+
* @vue-prop {Array<VcsAction>} [actions] - Optional actions rendered as ActionButtonList in the footer.
|
34
|
+
* @vue-event {Event} submit - Event fired on clicking the submit button.
|
35
|
+
* @vue-event {Event} cancel - Event fired on clicking the cancel button.
|
36
|
+
* @vue-event {Event} reset - Event fired on clicking the reset button.
|
37
|
+
*/
|
38
|
+
export default {
|
39
|
+
name: 'AbstractConfigEditor',
|
40
|
+
components: {
|
41
|
+
VContainer,
|
42
|
+
VForm,
|
43
|
+
VcsFormButton,
|
44
|
+
VcsActionButtonList,
|
45
|
+
},
|
46
|
+
props: {
|
47
|
+
showReset: {
|
48
|
+
type: Boolean,
|
49
|
+
default: false,
|
50
|
+
},
|
51
|
+
actions: {
|
52
|
+
type: Array,
|
53
|
+
default: () => [],
|
54
|
+
},
|
55
|
+
},
|
56
|
+
setup(props, { attrs, emit }) {
|
57
|
+
const app = inject('vcsApp');
|
58
|
+
|
59
|
+
const close = () => {
|
60
|
+
if (app.windowManager.has(attrs['window-state'].id)) {
|
61
|
+
app.windowManager.remove(attrs['window-state'].id);
|
62
|
+
}
|
63
|
+
};
|
64
|
+
|
65
|
+
return {
|
66
|
+
isValid: ref(true),
|
67
|
+
submit(e) {
|
68
|
+
close();
|
69
|
+
emit('submit', e);
|
70
|
+
},
|
71
|
+
cancel(e) {
|
72
|
+
close();
|
73
|
+
attrs.setConfig();
|
74
|
+
emit('cancel', e);
|
75
|
+
},
|
76
|
+
reset(e) {
|
77
|
+
emit('reset', e);
|
78
|
+
},
|
79
|
+
};
|
80
|
+
},
|
81
|
+
};
|
82
|
+
</script>
|
83
|
+
|
84
|
+
<style scoped></style>
|
@@ -74,14 +74,15 @@
|
|
74
74
|
:min="input.range?.[0] || 0"
|
75
75
|
:max="input.range?.[1] || undefined"
|
76
76
|
:rules="[
|
77
|
-
(v) =>
|
77
|
+
(v) =>
|
78
|
+
!input.isRequired || !!v || 'components.validation.required',
|
78
79
|
(v) =>
|
79
80
|
!input.range ||
|
80
81
|
(!input.isRequired && !v) ||
|
81
82
|
between(v, input.range) ||
|
82
|
-
`${$t(
|
83
|
-
'
|
84
|
-
)}`,
|
83
|
+
`${$t(
|
84
|
+
'components.validation.allowedRange',
|
85
|
+
)}: ${input.range.join(' - ')}`,
|
85
86
|
]"
|
86
87
|
:show-spin-buttons="true"
|
87
88
|
/>
|
@@ -458,7 +459,7 @@
|
|
458
459
|
if (Array.isArray(props.value?.scale)) {
|
459
460
|
return props.value.scale[index];
|
460
461
|
} else {
|
461
|
-
return props.value
|
462
|
+
return props.value?.scale;
|
462
463
|
}
|
463
464
|
},
|
464
465
|
set(value) {
|