@vcmap/ui 5.0.0-rc.10 → 5.0.0-rc.11
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/README.md +11 -4
- package/build/build.js +0 -3
- package/build/buildHelpers.js +0 -1
- package/build/buildPreview.js +7 -0
- package/config/aerowest.config.json +13 -3
- package/config/base.config.json +89 -64
- package/config/codes.config.json +397 -0
- package/config/dev.config.json +169 -0
- package/config/graphFeatureInfo.config.json +100 -0
- package/config/www.config.json +1232 -0
- package/dist/assets/{cesium.eb5667.js → cesium.e67536.js} +0 -0
- package/dist/assets/cesium.js +1 -1
- package/dist/assets/core.ebf665.js +4 -0
- package/dist/assets/core.js +1 -1
- package/dist/assets/{index.4ccd4433.js → index.9b213929.js} +1 -1
- package/dist/assets/{ol.ef03b1.js → ol.8bbd50.js} +0 -0
- package/dist/assets/ol.js +1 -1
- package/dist/assets/ui.fdfe0d.css +1 -0
- package/dist/assets/ui.fdfe0d.js +68 -0
- package/dist/assets/ui.js +1 -1
- package/dist/assets/vue.0bb7c6.js +9 -0
- package/dist/assets/vue.js +2 -1
- package/dist/assets/{vuetify.401a29.css → vuetify.53300f.css} +1 -1
- package/dist/assets/{vuetify.401a29.js → vuetify.53300f.js} +71 -71
- package/dist/assets/vuetify.js +2 -2
- package/dist/index.html +1 -1
- package/index.js +36 -5
- package/lib/vue.js +1 -0
- package/map.config.json +15 -6
- package/package.json +6 -7
- package/plugins/@vcmap/create-link/fallbackCreateLink.vue +71 -0
- package/plugins/@vcmap/create-link/index.js +83 -0
- package/plugins/@vcmap/create-link/package.json +6 -0
- package/plugins/@vcmap/pluginExample/index.js +1 -1
- package/plugins/@vcmap/pluginExample/pluginExampleComponent.vue +20 -3
- package/plugins/@vcmap/project-selector/ProjectSelectorComponent.vue +1 -1
- package/plugins/@vcmap/project-selector/index.js +1 -1
- package/plugins/@vcmap/project-selector/package.json +1 -2
- package/plugins/@vcmap/theme-changer/ThemeChangerComponent.vue +1 -1
- package/plugins/@vcmap/theme-changer/index.js +1 -1
- package/plugins/@vcmap/theme-changer/package.json +1 -2
- package/plugins/categoryTest/Categories.vue +89 -1
- package/plugins/categoryTest/Category.vue +1 -1
- package/plugins/simple-graph/README.md +51 -0
- package/plugins/simple-graph/SimpleGraphComponent.vue +70 -0
- package/plugins/simple-graph/index.js +17 -0
- package/plugins/simple-graph/package.json +11 -0
- package/plugins/simple-graph/simpleGraphView.js +76 -0
- package/plugins/test/editor.vue +1 -1
- package/plugins/test/index.js +63 -2
- package/plugins/test/windowManagerExample.vue +1 -1
- package/src/actions/stateRefAction.js +2 -2
- package/src/actions/styleSelector.vue +1 -1
- package/src/application/Navbar.vue +13 -2
- package/src/application/VcsApp.vue +201 -92
- package/src/application/VcsMap.vue +1 -1
- package/src/application/VcsSettings.vue +1 -1
- package/src/application/vcsAppWrapper.vue +1 -0
- package/src/components/form-inputs-controls/VcsCheckbox.vue +13 -0
- package/src/components/form-inputs-controls/VcsColorPicker.vue +1 -1
- package/src/components/form-inputs-controls/VcsRadio.vue +123 -0
- package/src/components/form-output/VcsFormattedNumber.vue +1 -1
- package/src/components/lists/VcsActionList.vue +13 -4
- package/src/components/lists/VcsTreeview.vue +4 -4
- package/src/components/lists/VcsTreeviewLeaf.vue +9 -2
- package/src/components/lists/VcsTreeviewSearchbar.vue +1 -2
- package/src/components/tables/VcsTable.vue +245 -0
- package/src/contentTree/LayerTree.vue +1 -1
- package/src/contentTree/contentTreeCollection.js +4 -4
- package/src/contentTree/contentTreeItem.js +9 -9
- package/src/contentTree/groupContentTreeItem.js +1 -1
- package/src/contentTree/layerContentTreeItem.js +15 -1
- package/src/contentTree/layerGroupContentTreeItem.js +21 -1
- package/src/contentTree/nodeContentTreeItem.js +1 -1
- package/src/featureInfo/AddressBalloonComponent.vue +47 -0
- package/src/featureInfo/BalloonComponent.vue +138 -0
- package/src/featureInfo/abstractFeatureInfoView.js +313 -0
- package/src/featureInfo/addressBalloonFeatureInfoView.js +118 -0
- package/src/featureInfo/balloonFeatureInfoView.js +151 -0
- package/src/featureInfo/balloonHelper.js +132 -0
- package/src/featureInfo/featureInfo.js +455 -0
- package/src/featureInfo/featureInfoInteraction.js +42 -0
- package/src/featureInfo/iframeFeatureInfoView.js +95 -0
- package/src/featureInfo/tableFeatureInfoView.js +106 -0
- package/src/i18n/de.js +16 -0
- package/src/i18n/en.js +16 -0
- package/src/i18n/i18nCollection.js +17 -0
- package/src/manager/buttonManager.js +5 -5
- package/src/manager/categoryManager/ComponentsManager.vue +30 -0
- package/src/manager/categoryManager/categoryManager.js +500 -0
- package/src/manager/contextMenu/contextMenuComponent.vue +43 -0
- package/src/manager/contextMenu/contextMenuInteraction.js +42 -0
- package/src/manager/contextMenu/contextMenuManager.js +197 -0
- package/src/manager/navbarManager.js +8 -8
- package/src/manager/toolbox/ToolboxManager.vue +2 -2
- package/src/manager/toolbox/toolboxManager.js +7 -3
- package/src/manager/window/WindowComponent.vue +1 -1
- package/src/manager/window/WindowManager.vue +5 -3
- package/src/manager/window/windowManager.js +118 -14
- package/src/navigation/mapNavigation.vue +3 -5
- package/src/navigation/overviewMap.js +28 -5
- package/src/navigation/vcsCompass.vue +1 -1
- package/src/setup.js +0 -2
- package/src/state.js +256 -0
- package/src/styles/_theming.scss +0 -5
- package/src/uiConfig.js +79 -0
- package/src/vcsUiApp.js +210 -20
- package/src/vuePlugins/vuetify.js +14 -4
- package/config/berlin.config.json +0 -510
- package/dist/assets/core.216494.js +0 -4
- package/dist/assets/ui.99a1a7.css +0 -1
- package/dist/assets/ui.99a1a7.js +0 -70
- package/dist/assets/vue-composition-api.c5aca1.js +0 -14
- package/dist/assets/vue-composition-api.js +0 -2
- package/dist/assets/vue.762edd.js +0 -9
- package/lib/vue-composition-api.js +0 -2
@@ -2,7 +2,10 @@
|
|
2
2
|
<v-container class="fill-height pa-0" absolute fluid>
|
3
3
|
<Navbar />
|
4
4
|
<v-container class="vcs-main pa-0" :class="{ 'vcs-main-xs': $vuetify.breakpoint.xs }" fluid absolute>
|
5
|
-
<
|
5
|
+
<template v-if="$vuetify.breakpoint.smAndDown">
|
6
|
+
<img v-if="mobileLogo" :src="mobileLogo" alt="Logo" class="mobile-logo">
|
7
|
+
<div v-else class="company-logo-mobile mobile-logo" />
|
8
|
+
</template>
|
6
9
|
<VcsMap :map-id="mapId" />
|
7
10
|
<MapNavigation />
|
8
11
|
<ToolboxManagerComponent />
|
@@ -31,15 +34,27 @@
|
|
31
34
|
bottom: 56px;
|
32
35
|
}
|
33
36
|
|
37
|
+
.mobile-logo {
|
38
|
+
max-height: 40px;
|
39
|
+
max-width: 70px;
|
40
|
+
position: absolute;
|
41
|
+
top: 1rem;
|
42
|
+
left: 1rem;
|
43
|
+
z-index: 1;
|
44
|
+
}
|
45
|
+
|
34
46
|
</style>
|
35
47
|
|
36
48
|
<script>
|
37
49
|
import { v4 as uuid } from 'uuid';
|
38
50
|
import {
|
51
|
+
computed,
|
52
|
+
getCurrentInstance,
|
39
53
|
onMounted,
|
40
54
|
onUnmounted,
|
41
55
|
provide,
|
42
|
-
|
56
|
+
watch,
|
57
|
+
} from 'vue';
|
43
58
|
import { getVcsAppById } from '@vcmap/core';
|
44
59
|
import WindowManagerComponent from '../manager/window/WindowManager.vue';
|
45
60
|
import ToolboxManagerComponent from '../manager/toolbox/ToolboxManager.vue';
|
@@ -50,8 +65,178 @@
|
|
50
65
|
import { createMapButtonAction, createToggleAction } from '../actions/actionHelper.js';
|
51
66
|
import MapNavigation from '../navigation/mapNavigation.vue';
|
52
67
|
import VcsSettings from './VcsSettings.vue';
|
53
|
-
import { WindowSlot } from '../manager/window/windowManager';
|
68
|
+
import { WindowSlot } from '../manager/window/windowManager.js';
|
69
|
+
import ComponentsManager from '../manager/categoryManager/ComponentsManager.vue';
|
70
|
+
import { defaultPrimaryColor } from '../vuePlugins/vuetify.js';
|
71
|
+
|
72
|
+
/**
|
73
|
+
* You should call this function in the component providing the vcsUiApp to your
|
74
|
+
* application in the components mounted hook. This will call VcsAppMounted on all plugins in the app
|
75
|
+
* and add a listener to call. Returns a destroy hook to stop listening to the added event. If you use the VcsApp
|
76
|
+
* component, do not call this function, since the component will do this for you.
|
77
|
+
* @param {VcsUiApp} app
|
78
|
+
* @returns {function():void}
|
79
|
+
*/
|
80
|
+
export function setupPluginMountedListeners(app) {
|
81
|
+
[...app.plugins].forEach((plugin) => {
|
82
|
+
if (plugin.onVcsAppMounted) {
|
83
|
+
plugin.onVcsAppMounted(app);
|
84
|
+
}
|
85
|
+
});
|
86
|
+
|
87
|
+
return app.plugins.added.addEventListener((plugin) => {
|
88
|
+
if (plugin.onVcsAppMounted) {
|
89
|
+
plugin.onVcsAppMounted(app);
|
90
|
+
}
|
91
|
+
});
|
92
|
+
}
|
93
|
+
|
94
|
+
/**
|
95
|
+
* This helper function will add a map action button based on the default icons
|
96
|
+
* to the apps NavbarManager. Furthermore, all maps on the app are synced for adding and removing.
|
97
|
+
* @param {VcsUiApp} app
|
98
|
+
* @returns {function():void}
|
99
|
+
*/
|
100
|
+
export function setupMapNavbar(app) {
|
101
|
+
const iconMap = {
|
102
|
+
OpenlayersMap: '$vcs2d',
|
103
|
+
CesiumMap: '$vcs3d',
|
104
|
+
ObliqueMap: '$vcsObliqueView',
|
105
|
+
};
|
106
|
+
|
107
|
+
const mapButtonActionDestroy = {};
|
108
|
+
const setupMap = ({ className, name }) => {
|
109
|
+
if (mapButtonActionDestroy[name]) {
|
110
|
+
mapButtonActionDestroy[name]();
|
111
|
+
}
|
112
|
+
const { action, destroy } = createMapButtonAction(
|
113
|
+
{
|
114
|
+
name,
|
115
|
+
icon: iconMap[className],
|
116
|
+
title: `navbar.maps.${className}`,
|
117
|
+
},
|
118
|
+
name,
|
119
|
+
app.maps,
|
120
|
+
);
|
121
|
+
app.navbarManager.add(
|
122
|
+
{
|
123
|
+
id: `mapButton-${name}`,
|
124
|
+
action,
|
125
|
+
},
|
126
|
+
vcsAppSymbol,
|
127
|
+
ButtonLocation.MAP,
|
128
|
+
);
|
129
|
+
mapButtonActionDestroy[name] = () => {
|
130
|
+
app.navbarManager.remove(`mapButton-${name}`);
|
131
|
+
destroy();
|
132
|
+
};
|
133
|
+
};
|
134
|
+
[...app.maps].forEach(setupMap);
|
135
|
+
const mapAddedListener = app.maps.added.addEventListener(setupMap);
|
136
|
+
|
137
|
+
const mapRemovedListener = app.maps.removed.addEventListener(({ name }) => {
|
138
|
+
if (mapButtonActionDestroy[name]) {
|
139
|
+
mapButtonActionDestroy[name]();
|
140
|
+
delete mapButtonActionDestroy[name];
|
141
|
+
}
|
142
|
+
});
|
143
|
+
|
144
|
+
return () => {
|
145
|
+
mapAddedListener();
|
146
|
+
mapRemovedListener();
|
147
|
+
Object.values(mapButtonActionDestroy).forEach(cb => cb());
|
148
|
+
};
|
149
|
+
}
|
150
|
+
|
151
|
+
/**
|
152
|
+
* This helper function will add a Components manager button to the navbar. The Components Manager
|
153
|
+
* will only be shown if there is at least one category under management in the categoryManager.
|
154
|
+
* @param {VcsUiApp} app
|
155
|
+
* @returns {function():void}
|
156
|
+
*/
|
157
|
+
export function setupComponentsWindow(app) {
|
158
|
+
const { action: componentsManagerAction, destroy: destroyComponentsManagerAction } = createToggleAction(
|
159
|
+
{
|
160
|
+
name: 'components-manager',
|
161
|
+
icon: '$vcsComponents',
|
162
|
+
title: 'components.tooltip',
|
163
|
+
},
|
164
|
+
{
|
165
|
+
id: 'component-manager',
|
166
|
+
state: {
|
167
|
+
headerTitle: 'components.title',
|
168
|
+
headerIcon: '$vcsComponents',
|
169
|
+
},
|
170
|
+
component: ComponentsManager,
|
171
|
+
slot: WindowSlot.STATIC,
|
172
|
+
},
|
173
|
+
app.windowManager,
|
174
|
+
vcsAppSymbol,
|
175
|
+
);
|
176
|
+
|
177
|
+
// only show Components Window if we have at least one managed Category
|
178
|
+
if (app.categoryManager.items.value.length > 0) {
|
179
|
+
app.navbarManager.add(
|
180
|
+
{ id: 'component-manager', action: componentsManagerAction },
|
181
|
+
vcsAppSymbol,
|
182
|
+
ButtonLocation.CONTENT,
|
183
|
+
);
|
184
|
+
}
|
185
|
+
watch(app.categoryManager.items, () => {
|
186
|
+
if (app.categoryManager.items.value.length > 0) {
|
187
|
+
if (!app.navbarManager.has('component-manager')) {
|
188
|
+
app.navbarManager.add(
|
189
|
+
{ id: 'component-manager', action: componentsManagerAction },
|
190
|
+
vcsAppSymbol,
|
191
|
+
ButtonLocation.CONTENT,
|
192
|
+
);
|
193
|
+
}
|
194
|
+
} else {
|
195
|
+
app.windowManager.remove('component-manager');
|
196
|
+
app.navbarManager.remove('component-manager');
|
197
|
+
}
|
198
|
+
});
|
199
|
+
|
200
|
+
return () => {
|
201
|
+
destroyComponentsManagerAction();
|
202
|
+
};
|
203
|
+
}
|
54
204
|
|
205
|
+
/**
|
206
|
+
* This helper sets up a listener to sync the theming relevant keys from the {@see UiConfigObject}
|
207
|
+
* with a given vuetify instance. Use this helper, if you do not use the VcsApp component and wish to evaluate
|
208
|
+
* the theming keys. Returns a function to stop syncing.
|
209
|
+
* @param {VcsUiApp} app
|
210
|
+
* @param {import("vuetify").Framework} vuetify
|
211
|
+
* @returns {function():void} - call to stop syncing
|
212
|
+
*/
|
213
|
+
export function setupUiConfigTheming(app, vuetify) {
|
214
|
+
const listeners = [
|
215
|
+
app.uiConfig.added.addEventListener((item) => {
|
216
|
+
if (item.name === 'primaryColor') {
|
217
|
+
vuetify.theme.themes.dark.primary = item.value;
|
218
|
+
vuetify.theme.themes.light.primary = item.value;
|
219
|
+
}
|
220
|
+
}),
|
221
|
+
app.uiConfig.removed.addEventListener((item) => {
|
222
|
+
if (item.name === 'primaryColor') {
|
223
|
+
vuetify.theme.themes.dark.primary = defaultPrimaryColor;
|
224
|
+
vuetify.theme.themes.light.primary = defaultPrimaryColor;
|
225
|
+
}
|
226
|
+
}),
|
227
|
+
];
|
228
|
+
|
229
|
+
return () => {
|
230
|
+
listeners.forEach((cb) => { cb(); });
|
231
|
+
listeners.splice(0);
|
232
|
+
};
|
233
|
+
}
|
234
|
+
|
235
|
+
/**
|
236
|
+
* The base component to setup the entire application. To embed the VcsApp, use this component.
|
237
|
+
* @vue-prop {string} appId - the id of the app to inject. this will setup listeners on the app to call vcsAppMounted on plugins
|
238
|
+
* @vue-provide
|
239
|
+
*/
|
55
240
|
export default {
|
56
241
|
components: {
|
57
242
|
MapNavigation,
|
@@ -65,62 +250,15 @@
|
|
65
250
|
type: String,
|
66
251
|
required: true,
|
67
252
|
},
|
68
|
-
app: {
|
69
|
-
type: Boolean,
|
70
|
-
default: true,
|
71
|
-
},
|
72
253
|
},
|
73
254
|
setup(props) {
|
74
255
|
const id = uuid();
|
75
256
|
const mapId = `mapCollection-${id}`;
|
257
|
+
/** @type {VcsUiApp} */
|
76
258
|
const app = getVcsAppById(props.appId);
|
77
259
|
provide('vcsApp', app);
|
78
260
|
|
79
|
-
const
|
80
|
-
OpenlayersMap: '$vcs2d',
|
81
|
-
CesiumMap: '$vcs3d',
|
82
|
-
ObliqueMap: '$vcsObliqueView',
|
83
|
-
};
|
84
|
-
|
85
|
-
const mapButtonActionDestroy = {};
|
86
|
-
|
87
|
-
const setupMap = ({ className, name }) => {
|
88
|
-
if (mapButtonActionDestroy[name]) {
|
89
|
-
mapButtonActionDestroy[name]();
|
90
|
-
}
|
91
|
-
const { action, destroy } = createMapButtonAction(
|
92
|
-
{
|
93
|
-
name,
|
94
|
-
icon: iconMap[className],
|
95
|
-
title: `navbar.maps.${className}`,
|
96
|
-
},
|
97
|
-
name,
|
98
|
-
app.maps,
|
99
|
-
);
|
100
|
-
app.navbarManager.add(
|
101
|
-
{
|
102
|
-
id: `mapButton-${name}`,
|
103
|
-
action,
|
104
|
-
},
|
105
|
-
vcsAppSymbol,
|
106
|
-
ButtonLocation.MAP,
|
107
|
-
);
|
108
|
-
mapButtonActionDestroy[name] = () => {
|
109
|
-
app.navbarManager.remove(`mapButton-${name}`);
|
110
|
-
destroy();
|
111
|
-
};
|
112
|
-
};
|
113
|
-
|
114
|
-
[...app.maps].forEach(setupMap);
|
115
|
-
const mapAddedDestroy = app.maps.added.addEventListener(setupMap);
|
116
|
-
|
117
|
-
const mapRemovedDestroy = app.maps.removed.addEventListener(({ name }) => {
|
118
|
-
if (mapButtonActionDestroy[name]) {
|
119
|
-
mapButtonActionDestroy[name]();
|
120
|
-
delete mapButtonActionDestroy[name];
|
121
|
-
}
|
122
|
-
});
|
123
|
-
|
261
|
+
const mapNavbarListener = setupMapNavbar(app);
|
124
262
|
const { action: settingsAction, destroy: settingsDestroy } = createToggleAction(
|
125
263
|
{
|
126
264
|
name: 'settings.title',
|
@@ -145,57 +283,28 @@
|
|
145
283
|
ButtonLocation.MENU,
|
146
284
|
);
|
147
285
|
|
148
|
-
|
149
|
-
const
|
150
|
-
app.windowManager.removeOwner(plugin.name);
|
151
|
-
app.navbarManager.removeOwner(plugin.name);
|
152
|
-
app.toolboxManager.removeOwner(plugin.name);
|
153
|
-
});
|
286
|
+
const destroyComponentsWindow = setupComponentsWindow(app);
|
287
|
+
const destroyThemingListener = setupUiConfigTheming(app, getCurrentInstance().proxy.$vuetify);
|
154
288
|
|
289
|
+
let pluginMountedListener;
|
155
290
|
onMounted(() => {
|
156
|
-
|
157
|
-
app.windowManager.removeOwner(plugin.name);
|
158
|
-
app.navbarManager.removeOwner(plugin.name);
|
159
|
-
app.toolboxManager.removeOwner(plugin.name);
|
160
|
-
if (plugin.onVcsAppMounted) {
|
161
|
-
plugin.onVcsAppMounted(app);
|
162
|
-
}
|
163
|
-
});
|
164
|
-
[...app.plugins].forEach((plugin) => {
|
165
|
-
if (plugin.onVcsAppMounted) {
|
166
|
-
plugin.onVcsAppMounted(app);
|
167
|
-
}
|
168
|
-
});
|
291
|
+
pluginMountedListener = setupPluginMountedListeners(app);
|
169
292
|
app.maps.setTarget(mapId);
|
170
293
|
});
|
171
294
|
|
172
295
|
onUnmounted(() => {
|
173
|
-
if (
|
174
|
-
|
175
|
-
}
|
176
|
-
if (mapRemovedDestroy) {
|
177
|
-
mapRemovedDestroy();
|
178
|
-
}
|
179
|
-
if (pluginAdded) {
|
180
|
-
pluginAdded();
|
181
|
-
}
|
182
|
-
if (pluginRemoved) {
|
183
|
-
pluginRemoved();
|
184
|
-
}
|
185
|
-
Object.values(mapButtonActionDestroy).forEach(cb => cb());
|
186
|
-
|
187
|
-
if (settingsDestroy) {
|
188
|
-
settingsDestroy();
|
296
|
+
if (pluginMountedListener) {
|
297
|
+
pluginMountedListener();
|
189
298
|
}
|
299
|
+
mapNavbarListener();
|
300
|
+
settingsDestroy();
|
301
|
+
destroyComponentsWindow();
|
302
|
+
destroyThemingListener();
|
190
303
|
});
|
191
304
|
|
192
305
|
return {
|
193
306
|
mapId,
|
194
|
-
|
195
|
-
},
|
196
|
-
provide() {
|
197
|
-
return {
|
198
|
-
language: window.navigator.language.split('-')[0],
|
307
|
+
mobileLogo: computed(() => app.uiConfig.config.value.mobileLogo ?? app.uiConfig.config.value.logo),
|
199
308
|
};
|
200
309
|
},
|
201
310
|
};
|
@@ -33,7 +33,7 @@
|
|
33
33
|
<script>
|
34
34
|
import {
|
35
35
|
ref, inject, onUnmounted, getCurrentInstance, computed,
|
36
|
-
} from '
|
36
|
+
} from 'vue';
|
37
37
|
import VcsLabel from '../components/form-inputs-controls/VcsLabel.vue';
|
38
38
|
import VcsSelect from '../components/form-inputs-controls/VcsSelect.vue';
|
39
39
|
|
@@ -11,6 +11,7 @@
|
|
11
11
|
* This component wraps the {@see VcsApp} component in a
|
12
12
|
* v-app tag to ensure vuetify functionality. If you provide your own vuetify app,
|
13
13
|
* do NOT use this wrapper, but use {@see VcsApp} directly, since you may only use v-app once.
|
14
|
+
* @vue-prop {string} appId - the app to wrap. will be passed to the VcsApp component
|
14
15
|
*/
|
15
16
|
export default {
|
16
17
|
name: 'VcsAppWrapper',
|
@@ -9,6 +9,7 @@
|
|
9
9
|
<v-checkbox
|
10
10
|
on-icon="$vcsCheckboxChecked"
|
11
11
|
off-icon="$vcsCheckbox"
|
12
|
+
class="vcs-checkbox"
|
12
13
|
hide-details
|
13
14
|
indeterminate-icon="$vcsCheckboxIndeterminate"
|
14
15
|
:dense="$attrs.dense!==false"
|
@@ -28,6 +29,18 @@
|
|
28
29
|
</VcsTooltip>
|
29
30
|
</template>
|
30
31
|
<style lang="scss" scoped>
|
32
|
+
.vcs-checkbox {
|
33
|
+
::v-deep {
|
34
|
+
label.v-label,
|
35
|
+
.v-icon.v-icon{
|
36
|
+
color: inherit;
|
37
|
+
}
|
38
|
+
.v-input--selection-controls__input {
|
39
|
+
margin: 0;
|
40
|
+
padding: 0;
|
41
|
+
}
|
42
|
+
}
|
43
|
+
}
|
31
44
|
.v-input--selection-controls {
|
32
45
|
margin: 0;
|
33
46
|
padding: 0;
|
@@ -0,0 +1,123 @@
|
|
1
|
+
<template>
|
2
|
+
<VcsTooltip
|
3
|
+
:tooltip-position="tooltipPosition"
|
4
|
+
:tooltip="errorMessage"
|
5
|
+
color="error"
|
6
|
+
>
|
7
|
+
<template #activator="{ on, attrs }">
|
8
|
+
<span v-on="on">
|
9
|
+
<v-radio-group
|
10
|
+
hide-details
|
11
|
+
class="w-full vcs-radio-group"
|
12
|
+
:dense="$attrs.dense!==false"
|
13
|
+
:ripple="false"
|
14
|
+
v-bind="{...$attrs, ...attrs}"
|
15
|
+
v-on="{...$listeners, ...on}"
|
16
|
+
@update:error="setError"
|
17
|
+
>
|
18
|
+
<v-radio
|
19
|
+
v-for="(item, idx) in items"
|
20
|
+
:id="`radio-${idx}`"
|
21
|
+
:key="`radio-${idx}`"
|
22
|
+
:ripple="false"
|
23
|
+
:color="item.color ?? 'secondary'"
|
24
|
+
:value="item.value ?? item"
|
25
|
+
:disabled="item.disabled ?? false"
|
26
|
+
:class="$attrs.dense!==false ? 'vcs-radio-dense' : 'vcs-radio'"
|
27
|
+
>
|
28
|
+
<template #label>
|
29
|
+
<VcsLabel :html-for="`radio-${idx}`" :dense="!!$attrs.dense">
|
30
|
+
{{ $t(item.label ?? item) }}
|
31
|
+
</VcsLabel>
|
32
|
+
</template>
|
33
|
+
</v-radio>
|
34
|
+
</v-radio-group>
|
35
|
+
</span>
|
36
|
+
</template>
|
37
|
+
</VcsTooltip>
|
38
|
+
</template>
|
39
|
+
<style lang="scss" scoped>
|
40
|
+
@import "../../styles/vcsFont";
|
41
|
+
.v-input--radio-group--column .v-radio:not(:last-child):not(:only-child) {
|
42
|
+
margin-bottom: 0;
|
43
|
+
}
|
44
|
+
.v-input{
|
45
|
+
&.vcs-radio-group{
|
46
|
+
::v-deep {
|
47
|
+
margin-top: 0;
|
48
|
+
padding-top: 0;
|
49
|
+
label.v-label,
|
50
|
+
.v-icon.v-icon{
|
51
|
+
font-size: $base-font-size;
|
52
|
+
color: inherit;
|
53
|
+
}
|
54
|
+
.v-radio:not(:last-child):not(:only-child){
|
55
|
+
margin-bottom: 0;
|
56
|
+
}
|
57
|
+
.v-input--selection-controls__input{
|
58
|
+
margin: 0;
|
59
|
+
}
|
60
|
+
}
|
61
|
+
}
|
62
|
+
}
|
63
|
+
.vcs-radio {
|
64
|
+
height: 40px;
|
65
|
+
align-items: center;
|
66
|
+
}
|
67
|
+
.vcs-radio-dense {
|
68
|
+
height: 32px;
|
69
|
+
align-items: center;
|
70
|
+
}
|
71
|
+
</style>
|
72
|
+
<script>
|
73
|
+
import VcsTooltip from '../notification/VcsTooltip.vue';
|
74
|
+
import VcsLabel from './VcsLabel.vue';
|
75
|
+
import validate from '../notification/validation.js';
|
76
|
+
|
77
|
+
/**
|
78
|
+
* @typedef {Object} VcsRadioItem
|
79
|
+
* @property {string} label
|
80
|
+
* @property {string} [color='secondary']
|
81
|
+
* @property {any} value
|
82
|
+
* @property {boolean} [disabled=false]
|
83
|
+
*/
|
84
|
+
|
85
|
+
/**
|
86
|
+
* @description Stylized wrapper around {@link https://vuetifyjs.com/en/api/v-radio-group/ |vuetify v-radio-group} using
|
87
|
+
* {@link https://vuetifyjs.com/en/api/v-radio/ |vuetify v-radio}.
|
88
|
+
* Provides two height options depending on "dense" property:
|
89
|
+
* - if dense is set true (default), height is 24 px
|
90
|
+
* - if dense is set false, height is 32 px
|
91
|
+
* Provides VcsTooltip to show error messages
|
92
|
+
* @vue-prop {('bottom' | 'left' | 'top' | 'right')} [tooltipPosition='right'] - Position of the error tooltip.
|
93
|
+
* @vue-prop {Array<string|VcsRadioItem>} items - A list of options. If strings are provided, the string is used as label and value.
|
94
|
+
*/
|
95
|
+
export default {
|
96
|
+
name: 'VcsRadio',
|
97
|
+
components: { VcsTooltip, VcsLabel },
|
98
|
+
props: {
|
99
|
+
tooltipPosition: {
|
100
|
+
type: String,
|
101
|
+
default: 'right',
|
102
|
+
},
|
103
|
+
items: {
|
104
|
+
type: Array,
|
105
|
+
required: true,
|
106
|
+
},
|
107
|
+
},
|
108
|
+
data() {
|
109
|
+
return {
|
110
|
+
errorMessage: '',
|
111
|
+
};
|
112
|
+
},
|
113
|
+
methods: {
|
114
|
+
setError() {
|
115
|
+
const rules = [...this.$attrs.rules].concat(this.$attrs.errorMessages);
|
116
|
+
this.errorMessage = validate(rules, this.$attrs.value).join('\n');
|
117
|
+
},
|
118
|
+
},
|
119
|
+
model: {
|
120
|
+
event: 'change',
|
121
|
+
},
|
122
|
+
};
|
123
|
+
</script>
|
@@ -52,19 +52,28 @@
|
|
52
52
|
*/
|
53
53
|
|
54
54
|
/**
|
55
|
-
* @param {
|
55
|
+
* @param {VcsAction} action
|
56
56
|
* @returns {boolean}
|
57
57
|
*/
|
58
|
-
export function
|
59
|
-
return
|
58
|
+
export function validateAction(action) {
|
59
|
+
return is(action, {
|
60
60
|
name: String,
|
61
61
|
title: [undefined, String],
|
62
62
|
icon: [undefined, String],
|
63
63
|
callback: Function,
|
64
64
|
active: [undefined, Boolean],
|
65
|
-
})
|
65
|
+
});
|
66
|
+
}
|
67
|
+
|
68
|
+
/**
|
69
|
+
* @param {Array<VcsAction>} actions
|
70
|
+
* @returns {boolean}
|
71
|
+
*/
|
72
|
+
export function validateActions(actions) {
|
73
|
+
return actions.every(validateAction);
|
66
74
|
}
|
67
75
|
|
76
|
+
|
68
77
|
/**
|
69
78
|
* @description
|
70
79
|
* A component rendering a list of actions with overflow mechanic using
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<template>
|
2
2
|
<div class="d-contents">
|
3
3
|
<VcsTreeviewSearchbar
|
4
|
-
v-if="
|
4
|
+
v-if="showSearchbar"
|
5
5
|
:placeholder="searchbarPlaceholder"
|
6
6
|
v-model="search"
|
7
7
|
/>
|
@@ -55,7 +55,7 @@
|
|
55
55
|
</style>
|
56
56
|
|
57
57
|
<script>
|
58
|
-
import { getCurrentInstance, ref } from '
|
58
|
+
import { getCurrentInstance, ref } from 'vue';
|
59
59
|
import VcsTreeviewLeaf from './VcsTreeviewLeaf.vue';
|
60
60
|
import VcsTreeviewSearchbar from './VcsTreeviewSearchbar.vue';
|
61
61
|
|
@@ -63,14 +63,14 @@
|
|
63
63
|
* @description extends API of https://vuetifyjs.com/en/api/v-treeview/
|
64
64
|
* Can render dynamic components as leaf items.
|
65
65
|
* In order to display an item needs to be registered and added to `availableComponents`.
|
66
|
-
* @vue-prop {boolean} [
|
66
|
+
* @vue-prop {boolean} [showSearchbar=false] - Whether there is a searchbar for this treeview
|
67
67
|
* @vue-prop {string} [searchbarPlaceholder] - Placeholder text for the searchbar, will be translated
|
68
68
|
*/
|
69
69
|
export default {
|
70
70
|
name: 'VcsTreeview',
|
71
71
|
components: { VcsTreeviewSearchbar, VcsTreeviewLeaf },
|
72
72
|
props: {
|
73
|
-
|
73
|
+
showSearchbar: {
|
74
74
|
type: Boolean,
|
75
75
|
default: false,
|
76
76
|
},
|
@@ -13,7 +13,7 @@
|
|
13
13
|
<span ref="imgContainer" />
|
14
14
|
</span>
|
15
15
|
|
16
|
-
<div class="position-relative col-8 pa-0 d-flex align-center">
|
16
|
+
<div class="position-relative col-8 pa-0 d-flex align-center treeview-label" :title="$t(item.title)">
|
17
17
|
<span>{{ $t(item.title) }}</span>
|
18
18
|
</div>
|
19
19
|
<VcsActionButtonList
|
@@ -27,6 +27,13 @@
|
|
27
27
|
/>
|
28
28
|
</div>
|
29
29
|
</template>
|
30
|
+
<style lang="css" scoped>
|
31
|
+
.treeview-label span{
|
32
|
+
white-space: nowrap;
|
33
|
+
overflow: hidden;
|
34
|
+
text-overflow: ellipsis;
|
35
|
+
}
|
36
|
+
</style>
|
30
37
|
|
31
38
|
<script>
|
32
39
|
import
|
@@ -34,7 +41,7 @@
|
|
34
41
|
computed,
|
35
42
|
onMounted,
|
36
43
|
ref,
|
37
|
-
} from '
|
44
|
+
} from 'vue';
|
38
45
|
|
39
46
|
import VcsActionButtonList from '../buttons/VcsActionButtonList.vue';
|
40
47
|
|
@@ -104,7 +104,7 @@
|
|
104
104
|
|
105
105
|
|
106
106
|
<script>
|
107
|
-
import { onMounted, onUnmounted } from '
|
107
|
+
import { onMounted, onUnmounted } from 'vue';
|
108
108
|
|
109
109
|
import { Subject } from 'rxjs';
|
110
110
|
import { debounceTime } from 'rxjs/operators';
|
@@ -147,7 +147,6 @@
|
|
147
147
|
onUnmounted(() => sub.unsubscribe());
|
148
148
|
|
149
149
|
return {
|
150
|
-
sub,
|
151
150
|
handleInput: (val) => {
|
152
151
|
sub.next(val);
|
153
152
|
},
|