@vcmap/ui 5.0.0-rc.27 → 5.0.0-rc.29
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/bundle.js +2 -1
- package/config/base.config.json +22 -0
- package/config/www.config.json +1 -1
- 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.82fdbe.js → cesium.16590b.js} +29788 -29589
- package/dist/assets/cesium.js +1 -1
- package/dist/assets/{core.df069a.js → core.74da2a.js} +4330 -4231
- package/dist/assets/core.js +1 -1
- package/dist/assets/index-cb070eff.js +1 -0
- package/dist/assets/{ol.90a5d0.js → ol.50a512.js} +11405 -11126
- package/dist/assets/ol.js +1 -1
- package/dist/assets/{ui.3ed7ff.css → ui.d3054c.css} +2 -2
- package/dist/assets/{ui.3ed7ff.js → ui.d3054c.js} +2811 -2711
- package/dist/assets/ui.js +1 -1
- package/dist/assets/vue.js +2 -2
- package/dist/assets/{vuetify.614278.js → vuetify.946bd8.js} +1 -1
- package/dist/assets/vuetify.js +2 -2
- package/dist/index.html +1 -1
- package/index.js +1 -0
- package/lib/olLib.js +6 -0
- package/package.json +4 -4
- 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/VcsTextField.vue +3 -2
- 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/tables/VcsDataTable.vue +100 -13
- package/src/contentTree/contentTreeCollection.js +22 -11
- 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 +4 -0
- package/src/i18n/en.js +4 -0
- package/src/manager/collectionManager/CollectionComponent.vue +6 -1
- package/src/manager/collectionManager/collectionComponent.js +6 -0
- 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/uiConfig.js +1 -0
- package/src/vcsUiApp.js +29 -8
- package/dist/assets/index-1cff371d.js +0 -1
- /package/dist/assets/{vue.537ff3.js → vue.30740e.js} +0 -0
- /package/dist/assets/{vuetify.614278.css → vuetify.946bd8.css} +0 -0
- /package/src/components/icons/{PolygonIcon.vue → PointIcon.vue} +0 -0
package/dist/assets/ui.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
export * from "./ui.
|
1
|
+
export * from "./ui.d3054c.js";
|
package/dist/assets/vue.js
CHANGED
@@ -13,7 +13,7 @@ function loadCss(href) {
|
|
13
13
|
elem.onerror = reject;
|
14
14
|
document.head.appendChild(elem);
|
15
15
|
});
|
16
|
-
} await loadCss('./assets/vuetify.
|
16
|
+
} await loadCss('./assets/vuetify.946bd8.css');import v from "./vue.30740e.js";
|
17
17
|
const Ne = v.extend().extend({
|
18
18
|
name: "themeable",
|
19
19
|
provide() {
|
package/dist/assets/vuetify.js
CHANGED
package/dist/index.html
CHANGED
@@ -29,7 +29,7 @@
|
|
29
29
|
/>
|
30
30
|
<link rel="icon" type="image/svg+xml" href="./assets/favicon.d5ec97.svg" />
|
31
31
|
|
32
|
-
<script type="module" crossorigin src="./assets/index-
|
32
|
+
<script type="module" crossorigin src="./assets/index-cb070eff.js"></script>
|
33
33
|
</head>
|
34
34
|
<body style="height: 100vh">
|
35
35
|
<noscript>
|
package/index.js
CHANGED
@@ -139,6 +139,7 @@ export { default as VcsCompass } from './src/navigation/vcsCompass.vue';
|
|
139
139
|
export { default as VcsZoomButton } from './src/navigation/vcsZoomButton.vue';
|
140
140
|
|
141
141
|
export { createVueI18n, setupI18n } from './src/vuePlugins/i18n.js';
|
142
|
+
export { i18nPluginSymbol } from './src/i18n/i18nCollection.js';
|
142
143
|
export {
|
143
144
|
createVuetify,
|
144
145
|
vuetify,
|
package/lib/olLib.js
CHANGED
@@ -50,6 +50,7 @@ export {default as ol$ViewHint} from 'ol/ViewHint';
|
|
50
50
|
export {default as ol$ViewProperty} from 'ol/ViewProperty';
|
51
51
|
export {binarySearch as ol$array$binarySearch} from 'ol/array';
|
52
52
|
export {ascending as ol$array$ascending} from 'ol/array';
|
53
|
+
export {descending as ol$array$descending} from 'ol/array';
|
53
54
|
export {linearFindNearest as ol$array$linearFindNearest} from 'ol/array';
|
54
55
|
export {reverseSubArray as ol$array$reverseSubArray} from 'ol/array';
|
55
56
|
export {extend as ol$array$extend} from 'ol/array';
|
@@ -124,6 +125,8 @@ export {preventDefault as ol$events$Event$preventDefault} from 'ol/events/Event'
|
|
124
125
|
export {default as ol$events$Event} from 'ol/events/Event';
|
125
126
|
export {default as ol$events$EventType} from 'ol/events/EventType';
|
126
127
|
export {default as ol$events$Key} from 'ol/events/Key';
|
128
|
+
export {SnapEventType as ol$events$SnapEvent$SnapEventType} from 'ol/events/SnapEvent';
|
129
|
+
export {SnapEvent as ol$events$SnapEvent$SnapEvent} from 'ol/events/SnapEvent';
|
127
130
|
export {default as ol$events$Target} from 'ol/events/Target';
|
128
131
|
export {all as ol$events$condition$all} from 'ol/events/condition';
|
129
132
|
export {altKeyOnly as ol$events$condition$altKeyOnly} from 'ol/events/condition';
|
@@ -139,6 +142,7 @@ export {singleClick as ol$events$condition$singleClick} from 'ol/events/conditio
|
|
139
142
|
export {doubleClick as ol$events$condition$doubleClick} from 'ol/events/condition';
|
140
143
|
export {noModifierKeys as ol$events$condition$noModifierKeys} from 'ol/events/condition';
|
141
144
|
export {platformModifierKeyOnly as ol$events$condition$platformModifierKeyOnly} from 'ol/events/condition';
|
145
|
+
export {platformModifierKey as ol$events$condition$platformModifierKey} from 'ol/events/condition';
|
142
146
|
export {shiftKeyOnly as ol$events$condition$shiftKeyOnly} from 'ol/events/condition';
|
143
147
|
export {targetNotEditable as ol$events$condition$targetNotEditable} from 'ol/events/condition';
|
144
148
|
export {mouseOnly as ol$events$condition$mouseOnly} from 'ol/events/condition';
|
@@ -507,6 +511,7 @@ export {register as ol$proj$proj4$register} from 'ol/proj/proj4';
|
|
507
511
|
export {setEPSGLookup as ol$proj$proj4$setEPSGLookup} from 'ol/proj/proj4';
|
508
512
|
export {getEPSGLookup as ol$proj$proj4$getEPSGLookup} from 'ol/proj/proj4';
|
509
513
|
export {fromEPSGCode as ol$proj$proj4$fromEPSGCode} from 'ol/proj/proj4';
|
514
|
+
export {epsgLookupMapTiler as ol$proj$proj4$epsgLookupMapTiler} from 'ol/proj/proj4';
|
510
515
|
export {clear as ol$proj$projections$clear} from 'ol/proj/projections';
|
511
516
|
export {get as ol$proj$projections$get} from 'ol/proj/projections';
|
512
517
|
export {add as ol$proj$projections$add} from 'ol/proj/projections';
|
@@ -751,6 +756,7 @@ export {expressionToGlsl as ol$style$expressions$expressionToGlsl} from 'ol/styl
|
|
751
756
|
export {uniformNameForVariable as ol$style$expressions$uniformNameForVariable} from 'ol/style/expressions';
|
752
757
|
export {PALETTE_TEXTURE_ARRAY as ol$style$expressions$PALETTE_TEXTURE_ARRAY} from 'ol/style/expressions';
|
753
758
|
export {toStyle as ol$style$flat$toStyle} from 'ol/style/flat';
|
759
|
+
export {createDefaultStyle as ol$style$flat$createDefaultStyle} from 'ol/style/flat';
|
754
760
|
export {SymbolType as ol$style$literal$SymbolType} from 'ol/style/literal';
|
755
761
|
export {createOrUpdate as ol$tilecoord$createOrUpdate} from 'ol/tilecoord';
|
756
762
|
export {getKeyZXY as ol$tilecoord$getKeyZXY} from 'ol/tilecoord';
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@vcmap/ui",
|
3
|
-
"version": "5.0.0-rc.
|
3
|
+
"version": "5.0.0-rc.29",
|
4
4
|
"author": "Virtual City Systems",
|
5
5
|
"license": "MIT",
|
6
6
|
"scripts": {
|
@@ -44,9 +44,9 @@
|
|
44
44
|
"vue-i18n": "^8.24.1"
|
45
45
|
},
|
46
46
|
"peerDependencies": {
|
47
|
-
"@vcmap-cesium/engine": "~2.4.
|
48
|
-
"@vcmap/core": "^5.0.0-rc.
|
49
|
-
"ol": "~7.
|
47
|
+
"@vcmap-cesium/engine": "~2.4.3",
|
48
|
+
"@vcmap/core": "^5.0.0-rc.37",
|
49
|
+
"ol": "~7.5.1",
|
50
50
|
"vue": "~2.7.3",
|
51
51
|
"vuetify": "~2.6.7"
|
52
52
|
},
|
@@ -35,14 +35,16 @@
|
|
35
35
|
const exampleWindows = [
|
36
36
|
{
|
37
37
|
id: 'dynamicLeft',
|
38
|
-
|
38
|
+
state: {
|
39
|
+
headerTitle: ['windowTester.title', '-', 'Example dynamicLeft'],
|
40
|
+
},
|
39
41
|
component: WindowExampleToggleChild,
|
40
42
|
slot: WindowSlot.DYNAMIC_LEFT,
|
41
43
|
},
|
42
44
|
{
|
43
45
|
id: 'dynamicLeft2',
|
44
46
|
state: {
|
45
|
-
headerTitle: 'Example dynamicLeft2',
|
47
|
+
headerTitle: ['windowTester.title', '-', 'Example dynamicLeft2'],
|
46
48
|
},
|
47
49
|
component: WindowExampleToggleChild,
|
48
50
|
slot: WindowSlot.DYNAMIC_LEFT,
|
@@ -50,7 +52,11 @@
|
|
50
52
|
{
|
51
53
|
id: 'dynamicLeft2 large',
|
52
54
|
state: {
|
53
|
-
headerTitle:
|
55
|
+
headerTitle: [
|
56
|
+
'windowTester.title',
|
57
|
+
'-',
|
58
|
+
'Example dynamicLeft2 with 1000px width',
|
59
|
+
],
|
54
60
|
},
|
55
61
|
component: WindowExampleToggleChild,
|
56
62
|
slot: WindowSlot.DYNAMIC_LEFT,
|
@@ -61,7 +67,7 @@
|
|
61
67
|
{
|
62
68
|
id: 'dynamicRight',
|
63
69
|
state: {
|
64
|
-
headerTitle: 'Example dynamicRight',
|
70
|
+
headerTitle: ['windowTester.title', '-', 'Example dynamicRight'],
|
65
71
|
},
|
66
72
|
component: WindowExampleContent,
|
67
73
|
headerComponent: MyCustomHeader,
|
@@ -73,7 +79,7 @@
|
|
73
79
|
{
|
74
80
|
id: 'dynamicRight2',
|
75
81
|
state: {
|
76
|
-
headerTitle: 'Example dynamicRight2',
|
82
|
+
headerTitle: ['windowTester.title', '-', 'Example dynamicRight2'],
|
77
83
|
},
|
78
84
|
component: WindowExampleContent,
|
79
85
|
slot: WindowSlot.DYNAMIC_RIGHT,
|
@@ -81,7 +87,7 @@
|
|
81
87
|
{
|
82
88
|
id: 'static',
|
83
89
|
state: {
|
84
|
-
headerTitle: 'Example static',
|
90
|
+
headerTitle: ['windowTester.title', '-', 'Example static'],
|
85
91
|
styles: { 'background-color': 'red' },
|
86
92
|
},
|
87
93
|
component: WindowExampleToggleChild,
|
@@ -90,7 +96,11 @@
|
|
90
96
|
{
|
91
97
|
id: 'static2',
|
92
98
|
state: {
|
93
|
-
headerTitle:
|
99
|
+
headerTitle: [
|
100
|
+
'windowTester.title',
|
101
|
+
'-',
|
102
|
+
'Example static2 With TestClass',
|
103
|
+
],
|
94
104
|
classes: {
|
95
105
|
vcsTest: computed(() => {
|
96
106
|
return showTestClass.value;
|
@@ -103,7 +113,11 @@
|
|
103
113
|
{
|
104
114
|
id: 'position1',
|
105
115
|
state: {
|
106
|
-
headerTitle:
|
116
|
+
headerTitle: [
|
117
|
+
'windowTester.title',
|
118
|
+
'-',
|
119
|
+
'Example position1 relative',
|
120
|
+
],
|
107
121
|
},
|
108
122
|
component: WindowExampleToggleChild,
|
109
123
|
position: {
|
@@ -117,7 +131,11 @@
|
|
117
131
|
id: 'position2',
|
118
132
|
state: {
|
119
133
|
hideHeader: false,
|
120
|
-
headerTitle:
|
134
|
+
headerTitle: [
|
135
|
+
'windowTester.title',
|
136
|
+
'-',
|
137
|
+
'Example position2 absolute',
|
138
|
+
],
|
121
139
|
},
|
122
140
|
component: WindowExampleToggleChild,
|
123
141
|
position: {
|
@@ -25,7 +25,7 @@ export default async function windowTester() {
|
|
25
25
|
{
|
26
26
|
id: 'window-tester',
|
27
27
|
state: {
|
28
|
-
headerTitle: '
|
28
|
+
headerTitle: 'windowTester.title',
|
29
29
|
},
|
30
30
|
component: windowExample,
|
31
31
|
position: {
|
@@ -58,6 +58,18 @@ export default async function windowTester() {
|
|
58
58
|
);
|
59
59
|
this._destroyAction = [destroy, destroyToolboxData];
|
60
60
|
},
|
61
|
+
i18n: {
|
62
|
+
de: {
|
63
|
+
windowTester: {
|
64
|
+
title: 'Fenster Tester',
|
65
|
+
},
|
66
|
+
},
|
67
|
+
en: {
|
68
|
+
windowTester: {
|
69
|
+
title: 'Window Tester',
|
70
|
+
},
|
71
|
+
},
|
72
|
+
},
|
61
73
|
destroy() {
|
62
74
|
if (this._destroyActions) {
|
63
75
|
this._destroyActions.forEach((cb) => cb());
|
@@ -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,
|
@@ -233,8 +233,9 @@
|
|
233
233
|
return attrs.value ?? '';
|
234
234
|
}
|
235
235
|
},
|
236
|
-
set(
|
237
|
-
emit
|
236
|
+
set() {
|
237
|
+
// emit is not needed, the vuetify component already emits an @input event. (forwarded listeners)
|
238
|
+
// emit('input', event);
|
238
239
|
},
|
239
240
|
});
|
240
241
|
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',
|
@@ -4,7 +4,18 @@
|
|
4
4
|
v-if="showSearchbar"
|
5
5
|
:placeholder="$t(searchbarPlaceholder)"
|
6
6
|
v-model="search"
|
7
|
-
|
7
|
+
@input="handleSearch"
|
8
|
+
>
|
9
|
+
<template #prepend="scope">
|
10
|
+
<slot name="prepend" v-bind="scope" />
|
11
|
+
</template>
|
12
|
+
<template #default="scope">
|
13
|
+
<slot v-bind="scope" />
|
14
|
+
</template>
|
15
|
+
<template #append="scope">
|
16
|
+
<slot name="append" v-bind="scope" />
|
17
|
+
</template>
|
18
|
+
</VcsTreeviewSearchbar>
|
8
19
|
<v-data-table
|
9
20
|
dense
|
10
21
|
:headers="translatedHeaders"
|
@@ -22,14 +33,20 @@
|
|
22
33
|
$t('components.vcsDataTable.noResultsPlaceholder')
|
23
34
|
"
|
24
35
|
:single-select="singleSelect"
|
36
|
+
:server-items-length="serverItemsLength"
|
25
37
|
hide-default-footer
|
26
38
|
v-bind="$attrs"
|
27
39
|
v-on="$listeners"
|
28
40
|
class="vcs-table rounded-0"
|
41
|
+
@update:options="(o) => $emit('update:items', { ...o, search })"
|
29
42
|
>
|
30
43
|
<!-- eslint-disable-next-line -->
|
31
44
|
<template v-for="(_, slot) of $scopedSlots" #[slot]="scope">
|
32
|
-
<slot
|
45
|
+
<slot
|
46
|
+
v-if="!['prepend', 'default', 'append'].includes(slot)"
|
47
|
+
:name="slot"
|
48
|
+
v-bind="scope"
|
49
|
+
/>
|
33
50
|
</template>
|
34
51
|
<!-- eslint-disable-next-line -->
|
35
52
|
<template v-slot:header.data-table-select="{ props, on }">
|
@@ -54,10 +71,11 @@
|
|
54
71
|
</div>
|
55
72
|
</template>
|
56
73
|
<!-- eslint-disable-next-line -->
|
57
|
-
<template
|
74
|
+
<template #item.data-table-select="{ isSelected, select, item, index }">
|
58
75
|
<div @mouseover="hovering = index" @mouseout="hovering = null">
|
59
76
|
<v-icon
|
60
77
|
v-if="isSelected"
|
78
|
+
:disabled="item.disabled"
|
61
79
|
@click="select(!isSelected)"
|
62
80
|
class="vcs-select-icon"
|
63
81
|
>
|
@@ -67,17 +85,23 @@
|
|
67
85
|
v-else-if="
|
68
86
|
hovering === index || (!singleSelect && value.length > 0)
|
69
87
|
"
|
88
|
+
:disabled="item.disabled"
|
70
89
|
@click="select(!isSelected)"
|
71
90
|
class="vcs-select-icon"
|
72
91
|
>
|
73
92
|
mdi-circle-outline
|
74
93
|
</v-icon>
|
75
|
-
<v-icon
|
94
|
+
<v-icon
|
95
|
+
v-else
|
96
|
+
:disabled="item.disabled"
|
97
|
+
@click="select(!isSelected)"
|
98
|
+
class="vcs-select-icon"
|
99
|
+
>
|
76
100
|
mdi-circle-small
|
77
101
|
</v-icon>
|
78
102
|
</div>
|
79
103
|
</template>
|
80
|
-
<template #footer v-if="
|
104
|
+
<template #footer v-if="showFooter">
|
81
105
|
<v-divider />
|
82
106
|
<v-container class="pa-2 vcs-pagination-bar">
|
83
107
|
<v-row dense no-gutters justify="center" class="align-center">
|
@@ -143,14 +167,31 @@
|
|
143
167
|
import VcsTreeviewSearchbar from '../lists/VcsTreeviewSearchbar.vue';
|
144
168
|
import VcsButton from '../buttons/VcsButton.vue';
|
145
169
|
|
170
|
+
/**
|
171
|
+
* @typedef {Object} UpdateItemsEvent
|
172
|
+
* @property {number} page
|
173
|
+
* @property {number} itemsPerPage
|
174
|
+
* @property {string[]} sortBy
|
175
|
+
* @property {boolean[]} sortDesc
|
176
|
+
* @property {string[]} groupBy
|
177
|
+
* @property {boolean[]} groupDesc
|
178
|
+
* @property {boolean} multiSort
|
179
|
+
* @property {boolean} mustSort
|
180
|
+
* @property {string} search
|
181
|
+
*/
|
182
|
+
|
146
183
|
/**
|
147
184
|
* @description A wrapper around {@link https://vuetifyjs.com/en/api/v-data-table/#props v-data-table } with custom pagination
|
185
|
+
* Passes all slots to v-data-table and 'prepend', 'default' and 'append' slots to VcsSearchbar
|
148
186
|
* @vue-prop {Array<Object>} items - array of items, where each item must provide a unique key
|
149
187
|
* @vue-prop {string} itemKey - the key property, which is unique on all items.
|
188
|
+
* @vue-prop {number} serverItemsLength - number of total items on a backend. Used for server-side pagination.
|
189
|
+
* @vue-prop {number} serverPagesLength - number of total pages on a backend. Used for server-side pagination.
|
150
190
|
* @vue-prop {Array<{text: string, value: string}>} [headers] - optional array defining column names. Text will be translated
|
151
191
|
* @vue-prop {boolean} [showSearchbar=true] - whether to show searchbar
|
152
192
|
* @vue-prop {string} [searchbarPlaceholder] - placeholder for searchbar
|
153
193
|
* @vue-prop {boolean} [singleSelect=false]
|
194
|
+
* @vue-event {UpdateItemsEvent} update:items - Emits when one of the options properties is updated or on search input. Can be used to update items via API call to a server.
|
154
195
|
* @vue-computed {Array<TableItem>} filteredItems - array of items with search filter applied on. If search string is empty, same as items array.
|
155
196
|
* @vue-computed {Array<import("vuetify").DataTableHeader>} translatedHeaders - array of translated header items.
|
156
197
|
* @vue-computed {number} numberOfItems - number of filtered items (depending on search).
|
@@ -187,6 +228,14 @@
|
|
187
228
|
type: String,
|
188
229
|
required: true,
|
189
230
|
},
|
231
|
+
serverItemsLength: {
|
232
|
+
type: Number,
|
233
|
+
default: -1,
|
234
|
+
},
|
235
|
+
serverPagesLength: {
|
236
|
+
type: Number,
|
237
|
+
default: -1,
|
238
|
+
},
|
190
239
|
itemsPerPage: {
|
191
240
|
type: Number,
|
192
241
|
default: 10,
|
@@ -212,7 +261,7 @@
|
|
212
261
|
default: () => [],
|
213
262
|
},
|
214
263
|
},
|
215
|
-
setup(props) {
|
264
|
+
setup(props, { attrs, emit }) {
|
216
265
|
const vm = getCurrentInstance().proxy;
|
217
266
|
const hovering = ref(null);
|
218
267
|
/**
|
@@ -230,12 +279,15 @@
|
|
230
279
|
if (filter) {
|
231
280
|
const q = filter.toLocaleLowerCase();
|
232
281
|
return Object.values(item).some((i) => {
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
282
|
+
if (i) {
|
283
|
+
const content = i.toString();
|
284
|
+
const translated = vm.$t(content);
|
285
|
+
return (
|
286
|
+
translated.toLowerCase().includes(q) ||
|
287
|
+
content.toLowerCase().includes(q)
|
288
|
+
);
|
289
|
+
}
|
290
|
+
return false;
|
239
291
|
});
|
240
292
|
}
|
241
293
|
return true;
|
@@ -249,7 +301,12 @@
|
|
249
301
|
handleFilter(item.value, search.value, item),
|
250
302
|
),
|
251
303
|
);
|
252
|
-
const numberOfItems = computed(() =>
|
304
|
+
const numberOfItems = computed(() => {
|
305
|
+
if (props.serverItemsLength > -1) {
|
306
|
+
return props.serverItemsLength;
|
307
|
+
}
|
308
|
+
return filteredItems.value.length;
|
309
|
+
});
|
253
310
|
const totalNumber = computed(() => props.items.length);
|
254
311
|
|
255
312
|
/**
|
@@ -267,6 +324,9 @@
|
|
267
324
|
*/
|
268
325
|
const itemsPerPageRef = ref(props.itemsPerPage);
|
269
326
|
const numberOfPages = computed(() => {
|
327
|
+
if (props.serverPagesLength > -1) {
|
328
|
+
return props.serverPagesLength;
|
329
|
+
}
|
270
330
|
return Math.ceil(numberOfItems.value / itemsPerPageRef.value);
|
271
331
|
});
|
272
332
|
/**
|
@@ -281,6 +341,31 @@
|
|
281
341
|
return last < numberOfItems.value ? last : numberOfItems.value;
|
282
342
|
});
|
283
343
|
|
344
|
+
const handleSearch = () => {
|
345
|
+
page.value = 1;
|
346
|
+
const { sortBy, sortDesc, groupBy, groupDesc, multiSort, mustSort } =
|
347
|
+
attrs;
|
348
|
+
// attrs of v-data-table cannot be accessed outside this component but are necessary for server-side pagination and search
|
349
|
+
// hence all relevant variables are emitted
|
350
|
+
emit('update:items', {
|
351
|
+
page: page.value,
|
352
|
+
itemsPerPage: itemsPerPageRef.value,
|
353
|
+
sortBy,
|
354
|
+
sortDesc,
|
355
|
+
groupBy,
|
356
|
+
groupDesc,
|
357
|
+
multiSort,
|
358
|
+
mustSort,
|
359
|
+
search: search.value,
|
360
|
+
});
|
361
|
+
};
|
362
|
+
|
363
|
+
const showFooter = computed(
|
364
|
+
() =>
|
365
|
+
props.items.length > itemsPerPageRef.value ||
|
366
|
+
props.serverItemsLength > itemsPerPageRef.value,
|
367
|
+
);
|
368
|
+
|
284
369
|
return {
|
285
370
|
hovering,
|
286
371
|
search,
|
@@ -306,7 +391,9 @@
|
|
306
391
|
itemsPerPageRef.value = number;
|
307
392
|
},
|
308
393
|
handleFilter,
|
394
|
+
handleSearch,
|
309
395
|
translatedHeaders,
|
396
|
+
showFooter,
|
310
397
|
};
|
311
398
|
},
|
312
399
|
};
|