@vcmap/ui 5.0.0-rc.15 → 5.0.0-rc.17
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/buildHelpers.js +7 -1
- package/config/base.config.json +7 -45
- package/config/dev.config.json +5 -1
- package/config/www.config.json +14 -13
- package/dist/assets/{cesium.2e288a.js → cesium.41de56.js} +0 -0
- package/dist/assets/cesium.js +1 -1
- package/dist/assets/{core.8014d3.js → core.af84e3.js} +6077 -4544
- package/dist/assets/core.js +1 -1
- package/dist/assets/{index.3f74fa92.js → index.5b773cad.js} +1 -1
- package/dist/assets/{ol.31c3a5.js → ol.5c7490.js} +0 -0
- package/dist/assets/ol.js +1 -1
- package/dist/assets/ui.dffe32.css +1 -0
- package/dist/assets/{ui.36f84f.js → ui.dffe32.js} +7243 -6234
- package/dist/assets/ui.js +1 -1
- package/dist/assets/{vue.a39c10.js → vue.25da17.js} +0 -0
- package/dist/assets/vue.js +2 -2
- package/dist/assets/{vuetify.378637.css → vuetify.e4ece7.css} +1 -1
- package/dist/assets/{vuetify.378637.js → vuetify.e4ece7.js} +5 -2
- package/dist/assets/vuetify.js +2 -2
- package/dist/index.html +1 -1
- package/index.html +77 -0
- package/index.js +18 -3
- package/package.json +4 -2
- package/plugins/@vcmap/create-link/fallbackCreateLink.vue +4 -1
- package/plugins/@vcmap/create-link/index.js +4 -1
- package/plugins/@vcmap/pluginExample/exampleActions.js +45 -0
- package/plugins/@vcmap/pluginExample/index.js +26 -2
- package/plugins/@vcmap/pluginExample/pluginExampleComponent.vue +77 -42
- package/plugins/@vcmap/search-nominatim/nominatim.js +1 -1
- package/plugins/@vcmap/theme-changer/ThemeChangerComponent.vue +4 -2
- package/plugins/categoryTest/Categories.vue +27 -13
- package/plugins/categoryTest/Category.vue +7 -1
- package/plugins/categoryTest/index.js +1 -1
- package/plugins/notifier/index.js +31 -0
- package/plugins/notifier/notifierTester.vue +88 -0
- package/plugins/package.json +1 -1
- package/plugins/test/allIconsComponent.vue +5 -5
- package/plugins/test/emptyComponent.vue +1 -1
- package/plugins/test/index.js +27 -3
- package/plugins/test/myCustomHeader.vue +9 -1
- package/plugins/test/testList.vue +290 -0
- package/plugins/test/vcsContent.vue +1 -1
- package/plugins/test/windowManagerExample.vue +12 -7
- package/plugins/wizardExample/index.js +41 -0
- package/plugins/wizardExample/wizardExample.vue +77 -0
- package/src/actions/actionHelper.js +10 -9
- package/src/application/VcsApp.vue +43 -34
- package/src/components/form-inputs-controls/VcsCheckbox.vue +1 -0
- package/src/components/form-inputs-controls/VcsFormSection.vue +23 -15
- package/src/components/form-inputs-controls/VcsSelect.vue +33 -1
- package/src/components/form-inputs-controls/VcsTextField.vue +11 -3
- package/src/components/form-inputs-controls/VcsWizard.vue +133 -0
- package/src/components/imageElementInjector.vue +22 -0
- package/src/components/lists/VcsList.vue +468 -0
- package/src/components/lists/VcsTreeview.vue +1 -2
- package/src/components/lists/VcsTreeviewLeaf.vue +18 -50
- package/src/components/lists/VcsTreeviewSearchbar.vue +1 -23
- package/src/components/tables/VcsTable.vue +13 -1
- package/src/contentTree/LayerTree.vue +1 -1
- package/src/contentTree/contentTreeCollection.js +9 -0
- package/src/contentTree/contentTreeItem.js +13 -13
- package/src/contentTree/layerContentTreeItem.js +1 -1
- package/src/contentTree/subContentTreeItem.js +1 -1
- package/src/contentTree/vcsObjectContentTreeItem.js +1 -1
- package/src/featureInfo/BalloonComponent.vue +13 -8
- package/src/featureInfo/balloonFeatureInfoView.js +16 -22
- package/src/featureInfo/balloonHelper.js +26 -5
- package/src/featureInfo/featureInfo.js +14 -2
- package/src/featureInfo/featureInfoInteraction.js +1 -1
- package/src/i18n/de.js +13 -1
- package/src/i18n/en.js +13 -1
- package/src/icons/+all.js +4 -0
- package/src/icons/WandIcon.vue +63 -0
- package/src/manager/categoryManager/CategoryComponent.vue +115 -0
- package/src/manager/categoryManager/CategoryComponentList.vue +57 -0
- package/src/manager/categoryManager/CategoryManager.vue +35 -0
- package/src/manager/categoryManager/categoryManager.js +251 -165
- package/src/manager/contextMenu/contextMenuManager.js +8 -2
- package/src/manager/window/WindowComponent.vue +51 -70
- package/src/manager/window/WindowComponentHeader.vue +81 -13
- package/src/manager/window/WindowManager.vue +54 -30
- package/src/manager/window/windowHelper.js +341 -0
- package/src/manager/window/windowManager.js +173 -151
- package/src/navigation/overviewMap.js +10 -9
- package/src/notifier/notifier.js +120 -0
- package/src/notifier/notifierComponent.vue +84 -0
- package/src/styles/variables.scss +19 -3
- package/src/vcsUiApp.js +26 -2
- package/src/vuePlugins/vuetify.js +2 -0
- package/dist/assets/ui.36f84f.css +0 -1
- package/src/manager/categoryManager/ComponentsManager.vue +0 -30
@@ -51,6 +51,9 @@
|
|
51
51
|
component: EmptyComponent,
|
52
52
|
headerComponent: MyCustomHeader,
|
53
53
|
slot: WindowSlot.DYNAMIC_RIGHT,
|
54
|
+
props: {
|
55
|
+
sample: 'A window property',
|
56
|
+
},
|
54
57
|
},
|
55
58
|
{
|
56
59
|
id: 'dynamicRight2',
|
@@ -85,7 +88,7 @@
|
|
85
88
|
{
|
86
89
|
id: 'position1',
|
87
90
|
state: {
|
88
|
-
headerTitle: 'Example position1',
|
91
|
+
headerTitle: 'Example position1 relative',
|
89
92
|
},
|
90
93
|
component: VcsContent,
|
91
94
|
position: {
|
@@ -98,15 +101,17 @@
|
|
98
101
|
{
|
99
102
|
id: 'position2',
|
100
103
|
state: {
|
101
|
-
hideHeader:
|
102
|
-
headerTitle: 'Example position2',
|
104
|
+
hideHeader: false,
|
105
|
+
headerTitle: 'Example position2 absolute',
|
103
106
|
},
|
104
107
|
component: EmptyComponent,
|
105
108
|
position: {
|
106
|
-
left: '
|
107
|
-
|
108
|
-
|
109
|
-
|
109
|
+
left: '200px',
|
110
|
+
top: '300px',
|
111
|
+
minHeight: '250px',
|
112
|
+
maxHeight: '500px',
|
113
|
+
minWidth: '400px',
|
114
|
+
maxWidth: '1000px',
|
110
115
|
},
|
111
116
|
},
|
112
117
|
];
|
@@ -0,0 +1,41 @@
|
|
1
|
+
import { createToggleAction, ButtonLocation, WindowSlot } from '@vcmap/ui';
|
2
|
+
import WizardExample from './wizardExample.vue';
|
3
|
+
|
4
|
+
export default async () => {
|
5
|
+
return {
|
6
|
+
name: 'wizardExample',
|
7
|
+
onVcsAppMounted(app) {
|
8
|
+
const { action, destroy } = createToggleAction(
|
9
|
+
{
|
10
|
+
name: 'wizardExample',
|
11
|
+
icon: '$vcsLegend',
|
12
|
+
title: 'VCS Wizard Example',
|
13
|
+
},
|
14
|
+
{
|
15
|
+
id: 'wizard-example',
|
16
|
+
component: WizardExample,
|
17
|
+
slot: WindowSlot.DYNAMIC_LEFT,
|
18
|
+
state: {
|
19
|
+
headerTitle: 'VCS Wizard',
|
20
|
+
headerIcon: '$vcsWand',
|
21
|
+
styles: { width: '350px', height: 'auto' },
|
22
|
+
},
|
23
|
+
},
|
24
|
+
app.windowManager,
|
25
|
+
'wizardExample',
|
26
|
+
);
|
27
|
+
app.navbarManager.add(
|
28
|
+
{ id: 'wizard-example', action },
|
29
|
+
'wizardExample',
|
30
|
+
ButtonLocation.TOOL,
|
31
|
+
);
|
32
|
+
this._destroyAction = destroy;
|
33
|
+
},
|
34
|
+
destroy() {
|
35
|
+
if (this._destroyAction) {
|
36
|
+
this._destroyAction();
|
37
|
+
this._destroyAction = null;
|
38
|
+
}
|
39
|
+
},
|
40
|
+
};
|
41
|
+
};
|
@@ -0,0 +1,77 @@
|
|
1
|
+
<template>
|
2
|
+
<VcsWizard
|
3
|
+
v-model="step"
|
4
|
+
>
|
5
|
+
<v-stepper-step
|
6
|
+
step="1"
|
7
|
+
editable
|
8
|
+
:complete="step > 1"
|
9
|
+
>
|
10
|
+
This is the first step
|
11
|
+
</v-stepper-step>
|
12
|
+
<v-stepper-content
|
13
|
+
step="1"
|
14
|
+
>
|
15
|
+
<v-sheet>
|
16
|
+
This is the content of the first step.
|
17
|
+
</v-sheet>
|
18
|
+
<VcsButton
|
19
|
+
@click="increaseStep()"
|
20
|
+
class="my-2"
|
21
|
+
>
|
22
|
+
Next
|
23
|
+
</VcsButton>
|
24
|
+
</v-stepper-content>
|
25
|
+
<v-stepper-step
|
26
|
+
:rules="[() => false]"
|
27
|
+
step="2"
|
28
|
+
editable
|
29
|
+
>
|
30
|
+
This is the second step
|
31
|
+
</v-stepper-step>
|
32
|
+
<v-stepper-content
|
33
|
+
step="2"
|
34
|
+
>
|
35
|
+
<VcsSelect
|
36
|
+
:items="['this', 'is', 'a', 'test']"
|
37
|
+
label="Select"
|
38
|
+
class="my-2"
|
39
|
+
/>
|
40
|
+
<VcsButton
|
41
|
+
@click="decreaseStep()"
|
42
|
+
>
|
43
|
+
Back
|
44
|
+
</VcsButton>
|
45
|
+
</v-stepper-content>
|
46
|
+
</VcsWizard>
|
47
|
+
</template>
|
48
|
+
|
49
|
+
<script>
|
50
|
+
import { VcsWizard, VcsButton, VcsSelect } from '@vcmap/ui';
|
51
|
+
import { VStepperStep, VStepperContent, VSheet } from 'vuetify/lib';
|
52
|
+
import { ref } from 'vue';
|
53
|
+
|
54
|
+
export default {
|
55
|
+
name: 'WizardExample',
|
56
|
+
components: {
|
57
|
+
VcsWizard,
|
58
|
+
VStepperStep,
|
59
|
+
VStepperContent,
|
60
|
+
VSheet,
|
61
|
+
VcsButton,
|
62
|
+
VcsSelect,
|
63
|
+
},
|
64
|
+
setup() {
|
65
|
+
const step = ref(1);
|
66
|
+
return {
|
67
|
+
step,
|
68
|
+
increaseStep() { step.value += 1; },
|
69
|
+
decreaseStep() { step.value -= 1; },
|
70
|
+
};
|
71
|
+
},
|
72
|
+
};
|
73
|
+
</script>
|
74
|
+
|
75
|
+
<style scoped>
|
76
|
+
|
77
|
+
</style>
|
@@ -4,7 +4,8 @@ import { Collection, Extent, MapCollection, mercatorProjection, Viewpoint } from
|
|
4
4
|
import { Feature } from 'ol';
|
5
5
|
import { reactive, ref } from 'vue';
|
6
6
|
import { vcsAppSymbol } from '../pluginHelper.js';
|
7
|
-
import {
|
7
|
+
import { WindowSlot } from '../manager/window/windowManager.js';
|
8
|
+
import { getWindowPositionOptions } from '../manager/window/windowHelper.js';
|
8
9
|
import SearchComponent from '../search/searchComponent.vue';
|
9
10
|
|
10
11
|
/**
|
@@ -189,11 +190,11 @@ export function createOverviewMapAction(overviewMap, windowComponent, windowMana
|
|
189
190
|
* at the clicked position (the actions position) by default, unless the window component already has a position set.
|
190
191
|
* @param {ActionOptions} actionOptions
|
191
192
|
* @param {WindowComponentOptions} modalComponent
|
192
|
-
* @param {
|
193
|
+
* @param {VcsUiApp} app
|
193
194
|
* @param {string|symbol} owner
|
194
195
|
* @returns {{action: VcsAction, destroy: Function}}
|
195
196
|
*/
|
196
|
-
export function createModalAction(actionOptions, modalComponent,
|
197
|
+
export function createModalAction(actionOptions, modalComponent, app, owner) {
|
197
198
|
check(actionOptions, {
|
198
199
|
name: String,
|
199
200
|
icon: [undefined, String],
|
@@ -216,7 +217,7 @@ export function createModalAction(actionOptions, modalComponent, windowManager,
|
|
216
217
|
left: 0,
|
217
218
|
right: 0,
|
218
219
|
});
|
219
|
-
elem.onclick = () => { windowManager.remove(id); };
|
220
|
+
elem.onclick = () => { app.windowManager.remove(id); };
|
220
221
|
document.body.appendChild(elem);
|
221
222
|
}
|
222
223
|
};
|
@@ -235,20 +236,20 @@ export function createModalAction(actionOptions, modalComponent, windowManager,
|
|
235
236
|
if (!this.active) {
|
236
237
|
this.active = true;
|
237
238
|
const { left, top, width } = event.currentTarget.getBoundingClientRect();
|
238
|
-
const position = getWindowPositionOptions(left + width, top);
|
239
|
+
const position = getWindowPositionOptions(left + width, top, app.maps.target);
|
239
240
|
const state = { ...modalComponent?.state, hideHeader: true };
|
240
|
-
windowManager.add({ position, ...modalComponent, id, state }, owner);
|
241
|
-
addModal(windowManager.componentIds.length - 2);
|
241
|
+
app.windowManager.add({ position, ...modalComponent, id, state }, owner);
|
242
|
+
addModal(app.windowManager.componentIds.length - 2);
|
242
243
|
} else {
|
243
244
|
this.active = false;
|
244
|
-
windowManager.remove(id);
|
245
|
+
app.windowManager.remove(id);
|
245
246
|
}
|
246
247
|
return null;
|
247
248
|
},
|
248
249
|
};
|
249
250
|
|
250
251
|
const listeners = [
|
251
|
-
windowManager.removed.addEventListener(({ id: windowId }) => {
|
252
|
+
app.windowManager.removed.addEventListener(({ id: windowId }) => {
|
252
253
|
if (windowId === id) {
|
253
254
|
action.active = false;
|
254
255
|
removeModal();
|
@@ -20,6 +20,7 @@
|
|
20
20
|
<MapNavigation />
|
21
21
|
<ToolboxManagerComponent />
|
22
22
|
<WindowManagerComponent />
|
23
|
+
<NotifierComponent />
|
23
24
|
</v-container>
|
24
25
|
<v-footer absolute v-if="$vuetify.breakpoint.smAndUp" min-height="22px">
|
25
26
|
<VcsAttributionsFooter :entries="attributionEntries" :attribution-action="attributionAction" />
|
@@ -73,6 +74,7 @@
|
|
73
74
|
} from 'vue';
|
74
75
|
import { getVcsAppById } from '@vcmap/core';
|
75
76
|
import { VContainer, VFooter } from 'vuetify/lib';
|
77
|
+
import { getLogger } from '@vcsuite/logger';
|
76
78
|
import WindowManagerComponent from '../manager/window/WindowManager.vue';
|
77
79
|
import ToolboxManagerComponent from '../manager/toolbox/ToolboxManager.vue';
|
78
80
|
import { ButtonLocation } from '../manager/navbarManager.js';
|
@@ -83,7 +85,7 @@
|
|
83
85
|
import MapNavigation from '../navigation/mapNavigation.vue';
|
84
86
|
import VcsSettings from './VcsSettings.vue';
|
85
87
|
import { WindowSlot } from '../manager/window/windowManager.js';
|
86
|
-
import
|
88
|
+
import CategoryManager from '../manager/categoryManager/CategoryManager.vue';
|
87
89
|
import { defaultPrimaryColor } from '../vuePlugins/vuetify.js';
|
88
90
|
import VcsLegend from '../legend/vcsLegend.vue';
|
89
91
|
import { getLegendEntries } from '../legend/legendHelper.js';
|
@@ -91,6 +93,7 @@
|
|
91
93
|
import VcsButton from '../components/buttons/VcsButton.vue';
|
92
94
|
import VcsAttributions from './VcsAttributions.vue';
|
93
95
|
import { getAttributions } from './attributionsHelper.js';
|
96
|
+
import NotifierComponent from '../notifier/notifierComponent.vue';
|
94
97
|
|
95
98
|
/**
|
96
99
|
* You should call this function in the component providing the vcsUiApp to your
|
@@ -101,17 +104,23 @@
|
|
101
104
|
* @returns {function():void}
|
102
105
|
*/
|
103
106
|
export function setupPluginMountedListeners(app) {
|
104
|
-
|
107
|
+
/**
|
108
|
+
* wrapped execution of onVcsAppMounted hook
|
109
|
+
* @param {VcsPlugin} plugin
|
110
|
+
*/
|
111
|
+
function onVcsAppMounted(plugin) {
|
105
112
|
if (plugin.onVcsAppMounted) {
|
106
|
-
|
113
|
+
try {
|
114
|
+
plugin.onVcsAppMounted(app);
|
115
|
+
} catch (e) {
|
116
|
+
getLogger('VcsUiApp').error(`Error in plugin ${plugin.name} onVcsAppMounted hook`, e);
|
117
|
+
}
|
107
118
|
}
|
108
|
-
}
|
119
|
+
}
|
109
120
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
}
|
114
|
-
});
|
121
|
+
[...app.plugins].forEach(onVcsAppMounted);
|
122
|
+
|
123
|
+
return app.plugins.added.addEventListener(onVcsAppMounted);
|
115
124
|
}
|
116
125
|
|
117
126
|
/**
|
@@ -267,56 +276,54 @@
|
|
267
276
|
}
|
268
277
|
|
269
278
|
/**
|
270
|
-
* This helper function will add a
|
279
|
+
* This helper function will add a category manager button to the navbar. The category Manager
|
271
280
|
* will only be shown if there is at least one category under management in the categoryManager.
|
272
281
|
* @param {VcsUiApp} app
|
273
282
|
* @returns {function():void}
|
274
283
|
*/
|
275
|
-
export function
|
276
|
-
const
|
284
|
+
export function setupCategoryManagerWindow(app) {
|
285
|
+
const id = 'category-manager';
|
286
|
+
const { action: categoryManagerAction, destroy } = createToggleAction(
|
277
287
|
{
|
278
|
-
name:
|
288
|
+
name: id,
|
279
289
|
icon: '$vcsComponents',
|
280
|
-
title: '
|
290
|
+
title: 'categoryManager.tooltip',
|
281
291
|
},
|
282
292
|
{
|
283
|
-
id
|
293
|
+
id,
|
284
294
|
state: {
|
285
|
-
headerTitle: '
|
295
|
+
headerTitle: 'categoryManager.title',
|
286
296
|
headerIcon: '$vcsComponents',
|
287
297
|
},
|
288
|
-
component:
|
298
|
+
component: CategoryManager,
|
289
299
|
slot: WindowSlot.STATIC,
|
290
300
|
},
|
291
301
|
app.windowManager,
|
292
302
|
vcsAppSymbol,
|
293
303
|
);
|
294
304
|
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
{ id: 'component-manager', action: componentsManagerAction },
|
299
|
-
vcsAppSymbol,
|
300
|
-
ButtonLocation.CONTENT,
|
301
|
-
);
|
302
|
-
}
|
303
|
-
watch(app.categoryManager.items.value, () => {
|
304
|
-
if (app.categoryManager.items.value.length > 0) {
|
305
|
-
if (!app.navbarManager.has('component-manager')) {
|
305
|
+
const setupCategories = () => {
|
306
|
+
if (app.categoryManager.componentIds.length > 0) {
|
307
|
+
if (!app.navbarManager.has(id)) {
|
306
308
|
app.navbarManager.add(
|
307
|
-
{ id
|
309
|
+
{ id, action: categoryManagerAction },
|
308
310
|
vcsAppSymbol,
|
309
311
|
ButtonLocation.CONTENT,
|
310
312
|
);
|
311
313
|
}
|
312
314
|
} else {
|
313
|
-
app.windowManager.remove(
|
314
|
-
app.navbarManager.remove(
|
315
|
+
app.windowManager.remove(id);
|
316
|
+
app.navbarManager.remove(id);
|
315
317
|
}
|
316
|
-
}
|
318
|
+
};
|
319
|
+
const addedListener = app.categoryManager.added.addEventListener(setupCategories);
|
320
|
+
const removedListener = app.categoryManager.removed.addEventListener(setupCategories);
|
321
|
+
setupCategories();
|
317
322
|
|
318
323
|
return () => {
|
319
|
-
|
324
|
+
destroy();
|
325
|
+
addedListener();
|
326
|
+
removedListener();
|
320
327
|
};
|
321
328
|
}
|
322
329
|
|
@@ -405,6 +412,7 @@
|
|
405
412
|
ToolboxManagerComponent,
|
406
413
|
VContainer,
|
407
414
|
VFooter,
|
415
|
+
NotifierComponent,
|
408
416
|
},
|
409
417
|
props: {
|
410
418
|
appId: {
|
@@ -422,7 +430,7 @@
|
|
422
430
|
const mapNavbarListener = setupMapNavbar(app);
|
423
431
|
const legendDestroy = setupLegendWindow(app);
|
424
432
|
const settingsDestroy = setupSettingsWindow(app);
|
425
|
-
const destroyComponentsWindow =
|
433
|
+
const destroyComponentsWindow = setupCategoryManagerWindow(app);
|
426
434
|
const destroyThemingListener = setupUiConfigTheming(app, getCurrentInstance().proxy.$vuetify);
|
427
435
|
const { attributionEntries, attributionAction, destroyAttributions } = setupAttributions(app);
|
428
436
|
|
@@ -430,6 +438,7 @@
|
|
430
438
|
onMounted(() => {
|
431
439
|
pluginMountedListener = setupPluginMountedListeners(app);
|
432
440
|
app.maps.setTarget(mapId);
|
441
|
+
app.mounted.raiseEvent(mapId);
|
433
442
|
});
|
434
443
|
|
435
444
|
onUnmounted(() => {
|
@@ -1,11 +1,12 @@
|
|
1
1
|
<template>
|
2
2
|
<section class="vcs-form-section">
|
3
|
-
<slot name="
|
3
|
+
<slot name="header" :heading="heading" :actions="actions">
|
4
4
|
<article class="pa-2 accent">
|
5
5
|
<div class="form-section-header d-flex justify-space-between align-center">
|
6
|
-
<strong class="caption">{{ $t(
|
6
|
+
<strong class="caption">{{ $t(heading) }}</strong>
|
7
7
|
<VcsActionButtonList
|
8
8
|
:actions="actions"
|
9
|
+
:overflow-count="actionButtonListOverflowCount"
|
9
10
|
small
|
10
11
|
/>
|
11
12
|
</div>
|
@@ -30,20 +31,21 @@
|
|
30
31
|
|
31
32
|
|
32
33
|
<script>
|
33
|
-
import { computed,
|
34
|
+
import { computed, reactive } from 'vue';
|
34
35
|
import { VAlert } from 'vuetify/lib';
|
35
36
|
import VcsActionButtonList from '../buttons/VcsActionButtonList.vue';
|
36
37
|
|
37
38
|
/**
|
38
39
|
* @description
|
39
40
|
* Stylized form section with action buttons
|
40
|
-
* @vue-data {slot} [#
|
41
|
+
* @vue-data {slot} [#header] - slot to override form section header
|
41
42
|
* @vue-data {slot} [#default] - slot with the section content
|
42
43
|
* @vue-data {slot} [#help] - Slot to specify html based help. Gets precedence over helpText prop.
|
43
|
-
* @vue-prop {string}
|
44
|
-
* @vue-prop {Array<VcsAction>}
|
44
|
+
* @vue-prop {string} heading - Title of the section to be displayed, will be translated.
|
45
|
+
* @vue-prop {Array<VcsAction>} headerActions - Icons to be displayed on the right side
|
46
|
+
* @vue-prop {number} [actionButtonListOverflowCount] - overflow count to use for action lists in the title and items
|
45
47
|
* @vue-prop {string} [helpText] - Optional help text. Must be plain string. Use 'help' slot for html based help texts. Help slot has precedence over helpText prop.
|
46
|
-
* @vue-computed {Array<VcsAction>} actions - Returns
|
48
|
+
* @vue-computed {Array<VcsAction>} actions - Returns header actions extended by a help action, if help prop is passed or help slot is used.
|
47
49
|
*/
|
48
50
|
export default {
|
49
51
|
name: 'VcsFormSection',
|
@@ -52,35 +54,41 @@
|
|
52
54
|
VAlert,
|
53
55
|
},
|
54
56
|
props: {
|
55
|
-
|
57
|
+
heading: {
|
56
58
|
type: String,
|
57
59
|
default: undefined,
|
58
60
|
},
|
59
|
-
|
61
|
+
headerActions: {
|
60
62
|
type: Array,
|
61
63
|
default: () => ([]),
|
62
64
|
},
|
65
|
+
actionButtonListOverflowCount: {
|
66
|
+
type: Number,
|
67
|
+
required: false,
|
68
|
+
default: undefined,
|
69
|
+
},
|
63
70
|
helpText: {
|
64
71
|
type: String,
|
65
72
|
default: undefined,
|
66
73
|
},
|
67
74
|
},
|
68
75
|
setup(props, { slots }) {
|
69
|
-
const
|
70
|
-
const helpAction = {
|
76
|
+
const helpAction = reactive({
|
71
77
|
name: 'help',
|
72
78
|
title: 'components.vcsFormSection.help',
|
79
|
+
active: false,
|
73
80
|
icon: 'mdi-help-circle',
|
74
|
-
callback
|
75
|
-
};
|
81
|
+
callback() { this.active = !this.active; },
|
82
|
+
});
|
83
|
+
const showHelp = computed(() => helpAction.active);
|
76
84
|
/**
|
77
85
|
* @type {ComputedRef<VcsAction>}
|
78
86
|
*/
|
79
87
|
const actions = computed(() => {
|
80
88
|
if (props.helpText || (slots.help && slots.help().length > 0)) {
|
81
|
-
return [helpAction, ...props.
|
89
|
+
return [helpAction, ...props.headerActions];
|
82
90
|
}
|
83
|
-
return props.
|
91
|
+
return props.headerActions;
|
84
92
|
});
|
85
93
|
|
86
94
|
return {
|
@@ -17,11 +17,21 @@
|
|
17
17
|
:outlined="isOutlined"
|
18
18
|
:dense="isDense"
|
19
19
|
:height="isDense ? 24 : 32"
|
20
|
+
:item-text="item => $t(getText(item))"
|
20
21
|
:class="$attrs.color === 'primary' ? 'primary--select' : ''"
|
21
22
|
v-bind="{...$attrs, ...attrs}"
|
22
23
|
v-on="{...$listeners, ...on}"
|
23
24
|
@update:error="setError"
|
24
|
-
|
25
|
+
>
|
26
|
+
<template #selection="{ item, index }">
|
27
|
+
<span v-if="index === 0" class="text-truncate">
|
28
|
+
{{ $t(getText(item)) }}
|
29
|
+
</span>
|
30
|
+
<span v-if="index === 1" class="text-no-wrap grey--text text-caption">
|
31
|
+
(+{{ $attrs.value.length - 1 }})
|
32
|
+
</span>
|
33
|
+
</template>
|
34
|
+
</v-select>
|
25
35
|
</span>
|
26
36
|
</template>
|
27
37
|
</VcsTooltip>
|
@@ -46,6 +56,15 @@
|
|
46
56
|
}
|
47
57
|
}
|
48
58
|
}
|
59
|
+
.v-select{
|
60
|
+
&.v-select--is-multi{
|
61
|
+
::v-deep {
|
62
|
+
.v-select__selections{
|
63
|
+
flex-wrap: nowrap;
|
64
|
+
}
|
65
|
+
}
|
66
|
+
}
|
67
|
+
}
|
49
68
|
</style>
|
50
69
|
<script>
|
51
70
|
|
@@ -55,11 +74,13 @@
|
|
55
74
|
|
56
75
|
/**
|
57
76
|
* @description Stylized wrapper around {@link https://vuetifyjs.com/en/api/v-select/ |vuetify select}.
|
77
|
+
* Translates the items text if it is an i18n string.
|
58
78
|
* Provides two height options depending on "dense" property:
|
59
79
|
* - if dense is set true (default), height is 24 px
|
60
80
|
* - if dense is set false, height is 32 px
|
61
81
|
* Provides VcsTooltip to show error messages
|
62
82
|
* @vue-prop {('bottom' | 'left' | 'top' | 'right')} [tooltipPosition='right'] - Position of the error tooltip.
|
83
|
+
* @vue-prop {Function} itemText - A function that is applied to each item and should return the item's text value.
|
63
84
|
* @vue-computed {boolean} isDense - Whether size of select is dense.
|
64
85
|
* @vue-computed {boolean} isOutlined - Select is outlined on either hover, focus or error, if not disabled.
|
65
86
|
*/
|
@@ -74,6 +95,10 @@
|
|
74
95
|
type: String,
|
75
96
|
default: 'right',
|
76
97
|
},
|
98
|
+
itemText: {
|
99
|
+
type: Function,
|
100
|
+
default: undefined,
|
101
|
+
},
|
77
102
|
},
|
78
103
|
data() {
|
79
104
|
return {
|
@@ -95,6 +120,13 @@
|
|
95
120
|
const rules = [...this.$attrs.rules].concat(this.$attrs.errorMessages);
|
96
121
|
this.errorMessage = validate(rules, this.$attrs.value).join('\n');
|
97
122
|
},
|
123
|
+
getText(item) {
|
124
|
+
if (this.itemText) {
|
125
|
+
return this.itemText(item);
|
126
|
+
} else {
|
127
|
+
return item?.text ?? item;
|
128
|
+
}
|
129
|
+
},
|
98
130
|
},
|
99
131
|
};
|
100
132
|
</script>
|
@@ -11,7 +11,8 @@
|
|
11
11
|
:max-width="200"
|
12
12
|
>
|
13
13
|
<template #activator="{ attrs }">
|
14
|
-
<
|
14
|
+
<component
|
15
|
+
:is="inputComponent"
|
15
16
|
ref="textFieldRef"
|
16
17
|
hide-details
|
17
18
|
:dense="isDense"
|
@@ -23,7 +24,7 @@
|
|
23
24
|
v-bind="{...$attrs, ...attrs}"
|
24
25
|
v-on="{...$listeners}"
|
25
26
|
:height="isDense ? 24 : 32"
|
26
|
-
class="ma-0 pb-1 pt-1 primary--placeholder"
|
27
|
+
class="ma-0 pb-1 pt-1 primary--placeholder align-center"
|
27
28
|
:class="$attrs.color === 'primary' ? 'primary--textfield' : ''"
|
28
29
|
/>
|
29
30
|
</template>
|
@@ -51,7 +52,7 @@
|
|
51
52
|
</style>
|
52
53
|
|
53
54
|
<script>
|
54
|
-
import { VTextField } from 'vuetify/lib';
|
55
|
+
import { VTextField, VFileInput } from 'vuetify/lib';
|
55
56
|
import VcsTooltip from '../notification/VcsTooltip.vue';
|
56
57
|
|
57
58
|
/**
|
@@ -74,6 +75,7 @@
|
|
74
75
|
components: {
|
75
76
|
VcsTooltip,
|
76
77
|
VTextField,
|
78
|
+
VFileInput,
|
77
79
|
},
|
78
80
|
props: {
|
79
81
|
tooltipPosition: {
|
@@ -92,6 +94,12 @@
|
|
92
94
|
};
|
93
95
|
},
|
94
96
|
computed: {
|
97
|
+
inputComponent() {
|
98
|
+
if (this.$attrs.type === 'file') {
|
99
|
+
return 'VFileInput';
|
100
|
+
}
|
101
|
+
return 'VTextField';
|
102
|
+
},
|
95
103
|
isClearable() {
|
96
104
|
return (this.$attrs.clearable !== undefined && this.$attrs.clearable !== false) &&
|
97
105
|
(this.hover || this.focus || this.isError);
|