@vcmap/ui 5.0.0-rc.22 → 5.0.0-rc.23
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 +2 -2
- package/app.config.json +5 -0
- package/build/buildPreview.js +2 -2
- package/config/aerowest.config.json +2 -0
- package/config/base.config.json +1 -0
- package/config/codes.config.json +2 -0
- package/config/dev.config.json +6 -0
- package/config/graphFeatureInfo.config.json +3 -1
- package/config/projects.config.json +27 -0
- package/config/www.config.json +2 -0
- package/dist/assets/cesium.js +1 -1
- package/dist/assets/{core.a66593.js → core.9342a1.js} +7804 -5352
- package/dist/assets/core.js +1 -1
- package/dist/assets/index.fd041928.js +1 -0
- package/dist/assets/ol.js +1 -1
- package/dist/assets/ui.c27597.css +5 -0
- package/dist/assets/{ui.d760e4.js → ui.c27597.js} +5055 -4694
- package/dist/assets/ui.js +1 -1
- package/dist/assets/vue.js +2 -2
- package/dist/assets/{vuetify.427322.js → vuetify.2f1432.js} +1 -1
- package/dist/assets/vuetify.js +2 -2
- package/dist/index.html +1 -1
- package/index.js +5 -2
- package/package.json +3 -3
- package/plugins/@vcmap/project-selector/{ContextsListComponent.vue → ModulesListComponent.vue} +10 -10
- package/plugins/@vcmap/project-selector/ProjectSelectorComponent.vue +15 -15
- package/plugins/@vcmap/project-selector/README.md +15 -21
- package/plugins/@vcmap/project-selector/config.json +3 -3
- package/plugins/@vcmap/project-selector/de.json +3 -0
- package/plugins/@vcmap/project-selector/en.json +3 -0
- package/plugins/@vcmap/project-selector/index.js +76 -101
- package/plugins/@vcmap/simple-graph/index.js +1 -1
- package/plugins/@vcmap-show-case/category-tester/Categories.vue +2 -2
- package/plugins/@vcmap-show-case/category-tester/Category.vue +1 -4
- package/plugins/@vcmap-show-case/config-editor/editor.vue +14 -14
- package/plugins/@vcmap-show-case/form-inputs-example/FormInputsExample.vue +18 -1
- package/plugins/@vcmap-show-case/form-inputs-example/index.js +1 -0
- package/plugins/@vcmap-show-case/table-example/DataTableExample.vue +202 -0
- package/plugins/@vcmap-show-case/table-example/README.md +3 -0
- package/plugins/@vcmap-show-case/table-example/index.js +47 -0
- package/plugins/@vcmap-show-case/table-example/package.json +5 -0
- package/src/actions/actionHelper.js +16 -27
- package/src/actions/styleSelector.vue +26 -19
- package/src/components/form-inputs-controls/VcsDatePicker.vue +111 -0
- package/src/components/form-inputs-controls/VcsTextField.vue +18 -7
- package/src/components/form-inputs-controls/VcsWizard.vue +3 -1
- package/src/components/icons/CheckboxCheckedIcon.vue +1 -1
- package/src/components/icons/LegendIcon.vue +10 -60
- package/src/components/lists/VcsList.vue +25 -6
- package/src/components/tables/VcsDataTable.vue +386 -0
- package/src/components/tables/VcsTable.vue +33 -278
- package/src/contentTree/contentTreeCollection.js +1 -1
- package/src/contentTree/layerContentTreeItem.js +3 -0
- package/src/downloadHelper.js +49 -0
- package/src/featureInfo/BalloonComponent.vue +9 -8
- package/src/featureInfo/abstractFeatureInfoView.js +1 -1
- package/src/featureInfo/featureInfo.js +3 -3
- package/src/i18n/de.js +8 -0
- package/src/i18n/en.js +8 -0
- package/src/i18n/i18nCollection.js +22 -22
- package/src/init.js +90 -7
- package/src/manager/categoryManager/CategoryComponent.vue +56 -47
- package/src/manager/categoryManager/CategoryManager.vue +23 -10
- package/src/manager/categoryManager/categoryManager.js +11 -11
- package/src/manager/navbarManager.js +18 -0
- package/src/manager/window/WindowComponent.vue +10 -15
- package/src/manager/window/WindowComponentHeader.vue +4 -2
- package/src/manager/window/WindowManager.vue +14 -15
- package/src/manager/window/windowHelper.js +1 -1
- package/src/manager/window/windowManager.js +18 -7
- package/src/navigation/mapNavCompass.vue +1 -1
- package/src/navigation/mapNavigation.vue +6 -6
- package/src/navigation/obliqueRotation.vue +36 -13
- package/src/navigation/orientationToolsButton.vue +0 -1
- package/src/navigation/overviewMap.js +5 -5
- package/src/navigation/vcsZoomButton.vue +37 -11
- package/src/pluginHelper.js +20 -0
- package/src/search/search.js +12 -3
- package/src/search/searchComponent.vue +15 -0
- package/src/state.js +6 -6
- package/src/uiConfig.js +3 -3
- package/src/vcsUiApp.js +44 -40
- package/src/vuePlugins/i18n.js +1 -0
- package/start.js +8 -2
- package/dist/assets/index.8b833ead.js +0 -1
- package/dist/assets/ui.d760e4.css +0 -5
- package/map.config.json +0 -44
- /package/dist/assets/{cesium.88cffd.js → cesium.166f91.js} +0 -0
- /package/dist/assets/{ol.d4539f.js → ol.d2cba3.js} +0 -0
- /package/dist/assets/{vue.db5102.js → vue.5d00e9.js} +0 -0
- /package/dist/assets/{vuetify.427322.css → vuetify.2f1432.css} +0 -0
@@ -17,11 +17,10 @@
|
|
17
17
|
:hide-spin-buttons="!showSpinButtons"
|
18
18
|
:dense="isDense"
|
19
19
|
:clearable="isClearable"
|
20
|
-
@focus="
|
21
|
-
@blur="
|
22
|
-
@
|
23
|
-
@keydown
|
24
|
-
@keydown="event => $emit('keydown', event)"
|
20
|
+
@focus="onFocus"
|
21
|
+
@blur="onBlur"
|
22
|
+
@keydown.esc="onEscape"
|
23
|
+
@keydown="$emit('keydown', $event)"
|
25
24
|
:value="visibleValue"
|
26
25
|
:type="type"
|
27
26
|
outlined
|
@@ -220,9 +219,19 @@
|
|
220
219
|
}
|
221
220
|
});
|
222
221
|
|
223
|
-
function
|
222
|
+
function onEscape(event) {
|
224
223
|
textFieldRef.value.blur();
|
225
224
|
emit('input', textFieldRef.value.initialValue);
|
225
|
+
emit('keydown', event);
|
226
|
+
}
|
227
|
+
|
228
|
+
function onBlur(event) {
|
229
|
+
focus.value = false;
|
230
|
+
emit('blur', event);
|
231
|
+
}
|
232
|
+
function onFocus(event) {
|
233
|
+
focus.value = true;
|
234
|
+
emit('focus', event);
|
226
235
|
}
|
227
236
|
|
228
237
|
return {
|
@@ -234,9 +243,11 @@
|
|
234
243
|
isOutlined,
|
235
244
|
visibleValue,
|
236
245
|
type,
|
237
|
-
|
246
|
+
onEscape,
|
238
247
|
textFieldRef,
|
239
248
|
errorMessage,
|
249
|
+
onBlur,
|
250
|
+
onFocus,
|
240
251
|
};
|
241
252
|
},
|
242
253
|
};
|
@@ -3,6 +3,7 @@
|
|
3
3
|
vertical
|
4
4
|
:value="value"
|
5
5
|
@change="newValue => $emit('input', newValue)"
|
6
|
+
class="rounded-0"
|
6
7
|
>
|
7
8
|
<slot />
|
8
9
|
</v-stepper>
|
@@ -61,13 +62,14 @@
|
|
61
62
|
}
|
62
63
|
}
|
63
64
|
&.theme--dark {
|
65
|
+
background: map-get($shades, 'black');
|
64
66
|
::v-deep{
|
65
67
|
.v-stepper__step {
|
66
68
|
.v-stepper__label {
|
67
69
|
color: map-get($shades, 'white');
|
68
70
|
}
|
69
71
|
&--active {
|
70
|
-
background-color: rgba(255, 255, 255, 0.
|
72
|
+
background-color: rgba(255, 255, 255, 0.17);
|
71
73
|
.v-stepper__label {
|
72
74
|
color: var(--v-primary-base);
|
73
75
|
}
|
@@ -3,7 +3,7 @@
|
|
3
3
|
<template>
|
4
4
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
5
5
|
<g id="icon-checkbox-check">
|
6
|
-
<path fill="currentColor" d="m13,2H3c-.55,0-1,.45-1,1v10c0,.55.45,1,1,1h10c.55,0,1-.45,1-1V3c0-.55-.45-1-1-1Zm-.67,3.67l-4.23,5.88h0s-.01.03-.02.03c-.27.34-.77.39-1.1.12l-3.02-2.48c-.33-.28-.38-.77-.12-1.11,0,0,.01-.01.02-.02.27-.34.76-.4,1.09-.13l2.38,1.95,3.74-5.21s0-.01.01-.02c.26-.34.74-.41,1.09-.15h0c.35.27.43.78.17,1.14Z"/>
|
6
|
+
<path fill="currentColor" d="m13,2H3c-.55,0-1,.45-1,1v10c0,.55.45,1,1,1h10c.55,0,1-.45,1-1V3c0-.55-.45-1-1-1Zm-.67,3.67l-4.23,5.88h0s-.01.03-.02.03c-.27.34-.77.39-1.1.12l-3.02-2.48c-.33-.28-.38-.77-.12-1.11,0,0,.01-.01.02-.02.27-.34.76-.4,1.09-.13l2.38,1.95,3.74-5.21s0-.01.01-.02c.26-.34.74-.41,1.09-.15h0c.35.27.43.78.17,1.14Z" />
|
7
7
|
</g>
|
8
8
|
</svg>
|
9
9
|
</template>
|
@@ -1,65 +1,15 @@
|
|
1
1
|
<!-- eslint-disable max-len -->
|
2
2
|
<template>
|
3
|
-
<svg id="icon_24_legend" xmlns="http://www.w3.org/2000/svg" width="24" height="
|
4
|
-
<
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
/>
|
14
|
-
<rect
|
15
|
-
id="Rectangle_747"
|
16
|
-
data-name="Rectangle 747"
|
17
|
-
width="6.677"
|
18
|
-
height="6.677"
|
19
|
-
rx="2"
|
20
|
-
transform="translate(713 921.323)"
|
21
|
-
fill="currentColor"
|
22
|
-
/>
|
23
|
-
<path id="Polygon_8" data-name="Polygon 8" d="M3.474,0,6.947,5.955H0Z" transform="translate(713 904)" fill="currentColor" />
|
24
|
-
<circle
|
25
|
-
id="Ellipse_88"
|
26
|
-
data-name="Ellipse 88"
|
27
|
-
cx="3.338"
|
28
|
-
cy="3.338"
|
29
|
-
r="3.338"
|
30
|
-
transform="translate(713 912.677)"
|
31
|
-
fill="currentColor"
|
32
|
-
/>
|
33
|
-
<line
|
34
|
-
id="Line_297"
|
35
|
-
data-name="Line 297"
|
36
|
-
x2="9"
|
37
|
-
transform="translate(724 907.978)"
|
38
|
-
fill="none"
|
39
|
-
stroke="currentColor"
|
40
|
-
stroke-linecap="round"
|
41
|
-
stroke-width="3"
|
42
|
-
/>
|
43
|
-
<line
|
44
|
-
id="Line_298"
|
45
|
-
data-name="Line 298"
|
46
|
-
x2="9"
|
47
|
-
transform="translate(724 916.016)"
|
48
|
-
fill="none"
|
49
|
-
stroke="currentColor"
|
50
|
-
stroke-linecap="round"
|
51
|
-
stroke-width="3"
|
52
|
-
/>
|
53
|
-
<line
|
54
|
-
id="Line_299"
|
55
|
-
data-name="Line 299"
|
56
|
-
x2="9"
|
57
|
-
transform="translate(724 924.053)"
|
58
|
-
fill="none"
|
59
|
-
stroke="currentColor"
|
60
|
-
stroke-linecap="round"
|
61
|
-
stroke-width="3"
|
62
|
-
/>
|
3
|
+
<svg id="icon_24_legend" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
4
|
+
<g transform="translate(-438 -549)">
|
5
|
+
<g fill="currentColor">
|
6
|
+
<path d="M446.8,562.318a2.87,2.87,0,0,0-4.052,0l-1.766,1.765a2.87,2.87,0,0,0,0,4.053l1.766,1.765a2.868,2.868,0,0,0,4.052,0l1.766-1.765a2.87,2.87,0,0,0,0-4.053Zm.352,4.4-1.766,1.765a.865.865,0,0,1-1.224,0l-1.766-1.765a.869.869,0,0,1,0-1.225l1.766-1.765a.867.867,0,0,1,1.224,0l1.765,1.765A.868.868,0,0,1,447.155,566.722Z" />
|
7
|
+
<path d="M445.642,551.372a1,1,0,0,0-1.728,0l-4.156,7.124a1,1,0,0,0,.864,1.5h8.311a1,1,0,0,0,.863-1.5ZM442.363,558l2.415-4.14,2.414,4.14Z" />
|
8
|
+
<path d="M459,563h-7a1,1,0,0,0,0,2h7a1,1,0,0,0,0-2Z" />
|
9
|
+
<path d="M459,567h-7a1,1,0,0,0,0,2h7a1,1,0,0,0,0-2Z" />
|
10
|
+
<path d="M452,554h7a1,1,0,0,0,0-2h-7a1,1,0,0,0,0,2Z" />
|
11
|
+
<path d="M459,556h-7a1,1,0,0,0,0,2h7a1,1,0,0,0,0-2Z" />
|
12
|
+
</g>
|
63
13
|
</g>
|
64
14
|
</svg>
|
65
15
|
</template>
|
@@ -17,12 +17,19 @@
|
|
17
17
|
<v-list-item-action
|
18
18
|
v-if="selectable"
|
19
19
|
>
|
20
|
+
<v-spacer v-if="singleSelect" />
|
20
21
|
<v-icon
|
21
|
-
v-if="selected.length === renderingItems.length"
|
22
|
+
v-else-if="selected.length === renderingItems.length"
|
22
23
|
@click="clear"
|
23
24
|
>
|
24
25
|
mdi-check-circle-outline
|
25
26
|
</v-icon>
|
27
|
+
<v-icon
|
28
|
+
v-else-if="selected.length > 0 && selected.length < renderingItems.length"
|
29
|
+
@click="selectAll()"
|
30
|
+
>
|
31
|
+
mdi-minus-circle-outline
|
32
|
+
</v-icon>
|
26
33
|
<v-icon
|
27
34
|
v-else
|
28
35
|
@click="selectAll()"
|
@@ -52,7 +59,6 @@
|
|
52
59
|
:block-overflow="true"
|
53
60
|
:overflow-count="actionButtonListOverflowCount"
|
54
61
|
small
|
55
|
-
right
|
56
62
|
/>
|
57
63
|
</v-list-item-content>
|
58
64
|
</v-list-item>
|
@@ -64,6 +70,7 @@
|
|
64
70
|
@mousedown.shift="$event.preventDefault()"
|
65
71
|
@mouseover="hovering = index"
|
66
72
|
@mouseout="hovering = null"
|
73
|
+
:class="{ 'v-list-item__lighten_even': lightenEven, 'v-list-item__lighten_odd': !lightenEven }"
|
67
74
|
>
|
68
75
|
<v-list-item-action
|
69
76
|
v-if="selectable"
|
@@ -112,7 +119,6 @@
|
|
112
119
|
:block-overflow="true"
|
113
120
|
:overflow-count="actionButtonListOverflowCount"
|
114
121
|
small
|
115
|
-
right
|
116
122
|
/>
|
117
123
|
</v-list-item-content>
|
118
124
|
</v-list-item>
|
@@ -129,6 +135,7 @@
|
|
129
135
|
VListItemAction,
|
130
136
|
VIcon,
|
131
137
|
VListItemTitle,
|
138
|
+
VSpacer,
|
132
139
|
} from 'vuetify/lib';
|
133
140
|
import VcsActionButtonList from '../buttons/VcsActionButtonList.vue';
|
134
141
|
import VcsTooltip from '../notification/VcsTooltip.vue';
|
@@ -182,6 +189,7 @@
|
|
182
189
|
VListItemAction,
|
183
190
|
VIcon,
|
184
191
|
VListItemTitle,
|
192
|
+
VSpacer,
|
185
193
|
},
|
186
194
|
props: {
|
187
195
|
/** @type {Array<VcsListItem>} */
|
@@ -246,6 +254,9 @@
|
|
246
254
|
/** @type {import("vue").Ref<string>} */
|
247
255
|
const query = ref('');
|
248
256
|
const hovering = ref(null);
|
257
|
+
const lightenEven = computed(() => {
|
258
|
+
return !(!props.searchable && !props.showTitle);
|
259
|
+
});
|
249
260
|
let firstSelected = null;
|
250
261
|
|
251
262
|
watch(props, () => {
|
@@ -281,6 +292,7 @@
|
|
281
292
|
return {
|
282
293
|
query,
|
283
294
|
hovering,
|
295
|
+
lightenEven,
|
284
296
|
/**
|
285
297
|
* @type {import("vue").ComputedRef<Array<VcsListItem>>}
|
286
298
|
*/
|
@@ -419,6 +431,16 @@
|
|
419
431
|
<style lang="scss" scoped>
|
420
432
|
::v-deep {
|
421
433
|
.v-list {
|
434
|
+
.v-list-item__lighten_even {
|
435
|
+
&:nth-child(even) {
|
436
|
+
background-color: var(--v-base-lighten4);
|
437
|
+
}
|
438
|
+
}
|
439
|
+
.v-list-item__lighten_odd {
|
440
|
+
&:nth-child(odd) {
|
441
|
+
background-color: var(--v-base-lighten4);
|
442
|
+
}
|
443
|
+
}
|
422
444
|
.v-list-item {
|
423
445
|
padding: 4px 8px 4px 16px;
|
424
446
|
&:after{
|
@@ -429,9 +451,6 @@
|
|
429
451
|
font-weight: 700;
|
430
452
|
}
|
431
453
|
}
|
432
|
-
&:nth-child(even) {
|
433
|
-
background-color: var(--v-base-lighten4);
|
434
|
-
}
|
435
454
|
.v-list-item__action {
|
436
455
|
.v-icon {
|
437
456
|
font-size: 16px;
|
@@ -0,0 +1,386 @@
|
|
1
|
+
<template>
|
2
|
+
<v-card>
|
3
|
+
<VcsTreeviewSearchbar
|
4
|
+
v-if="showSearchbar"
|
5
|
+
:placeholder="$t(searchbarPlaceholder)"
|
6
|
+
v-model="search"
|
7
|
+
/>
|
8
|
+
<v-data-table
|
9
|
+
dense
|
10
|
+
:headers="translatedHeaders"
|
11
|
+
:items="items"
|
12
|
+
:item-key="itemKey"
|
13
|
+
:items-per-page.sync="itemsPerPageRef"
|
14
|
+
:page.sync="page"
|
15
|
+
:search="search"
|
16
|
+
:custom-filter="handleFilter"
|
17
|
+
:no-data-text="$attrs.noDataText ?? $t('components.vcsDataTable.noDataPlaceholder')"
|
18
|
+
:no-results-text="$attrs.noResultsText ?? $t('components.vcsDataTable.noResultsPlaceholder')"
|
19
|
+
:single-select="singleSelect"
|
20
|
+
hide-default-footer
|
21
|
+
v-bind="$attrs"
|
22
|
+
v-on="$listeners"
|
23
|
+
class="vcs-table rounded-0"
|
24
|
+
>
|
25
|
+
<template v-for="(_, slot) of $scopedSlots" #[slot]="scope">
|
26
|
+
<slot :name="slot" v-bind="scope" />
|
27
|
+
</template>
|
28
|
+
<!-- eslint-disable-next-line -->
|
29
|
+
<template v-slot:header.data-table-select="{ props, on }">
|
30
|
+
<div v-if="on">
|
31
|
+
<v-icon
|
32
|
+
v-if="value.length === totalNumber"
|
33
|
+
@click="on.input(false)"
|
34
|
+
class="vcs-select-icon"
|
35
|
+
>
|
36
|
+
mdi-check-circle-outline
|
37
|
+
</v-icon>
|
38
|
+
<v-icon
|
39
|
+
v-else-if="props.indeterminate"
|
40
|
+
@click="on.input(true)"
|
41
|
+
class="vcs-select-icon"
|
42
|
+
>
|
43
|
+
mdi-minus-circle-outline
|
44
|
+
</v-icon>
|
45
|
+
<v-icon
|
46
|
+
v-else
|
47
|
+
@click="on.input(true)"
|
48
|
+
class="vcs-select-icon"
|
49
|
+
>
|
50
|
+
mdi-circle-outline
|
51
|
+
</v-icon>
|
52
|
+
</div>
|
53
|
+
</template>
|
54
|
+
<!-- eslint-disable-next-line -->
|
55
|
+
<template v-slot:item.data-table-select="{ isSelected, select, index }">
|
56
|
+
<div
|
57
|
+
@mouseover="hovering = index"
|
58
|
+
@mouseout="hovering = null"
|
59
|
+
>
|
60
|
+
<v-icon
|
61
|
+
v-if="isSelected"
|
62
|
+
@click="select(!isSelected)"
|
63
|
+
class="vcs-select-icon"
|
64
|
+
>
|
65
|
+
mdi-check-circle-outline
|
66
|
+
</v-icon>
|
67
|
+
<v-icon
|
68
|
+
v-else-if="hovering === index || (!singleSelect && value.length > 0)"
|
69
|
+
@click="select(!isSelected)"
|
70
|
+
class="vcs-select-icon"
|
71
|
+
>
|
72
|
+
mdi-circle-outline
|
73
|
+
</v-icon>
|
74
|
+
<v-icon
|
75
|
+
v-else
|
76
|
+
@click="select(!isSelected)"
|
77
|
+
class="vcs-select-icon"
|
78
|
+
>
|
79
|
+
mdi-circle-small
|
80
|
+
</v-icon>
|
81
|
+
</div>
|
82
|
+
</template>
|
83
|
+
<template #footer v-if="items.length > itemsPerPageRef">
|
84
|
+
<v-divider />
|
85
|
+
<v-container class="pa-2 vcs-pagination-bar">
|
86
|
+
<v-row
|
87
|
+
dense
|
88
|
+
no-gutters
|
89
|
+
justify="center"
|
90
|
+
>
|
91
|
+
<v-menu offset-y dense>
|
92
|
+
<template #activator="{ on, attrs }">
|
93
|
+
<VcsButton
|
94
|
+
small
|
95
|
+
color="primary"
|
96
|
+
v-bind="attrs"
|
97
|
+
v-on="on"
|
98
|
+
>
|
99
|
+
{{ itemsPerPageRef }}
|
100
|
+
<v-icon>mdi-chevron-down</v-icon>
|
101
|
+
</VcsButton>
|
102
|
+
</template>
|
103
|
+
<v-list>
|
104
|
+
<v-list-item
|
105
|
+
v-for="(number, index) in itemsPerPageArray"
|
106
|
+
:key="index"
|
107
|
+
@click="updateItemsPerPage(number)"
|
108
|
+
style="min-height: auto; height: 24px; text-align: right;"
|
109
|
+
>
|
110
|
+
<v-list-item-title>{{ number }}</v-list-item-title>
|
111
|
+
</v-list-item>
|
112
|
+
</v-list>
|
113
|
+
</v-menu>
|
114
|
+
<span class="mx-2">{{ $t('components.vcsDataTable.itemsPerPage') }}</span>
|
115
|
+
<span class="mx-2">
|
116
|
+
{{ itemsFrom }} - {{ itemsTo }} {{ $t('components.vcsDataTable.ofItems') }} {{ numberOfItems }}
|
117
|
+
</span>
|
118
|
+
<VcsButton
|
119
|
+
small
|
120
|
+
icon="mdi-chevron-left"
|
121
|
+
@click="formerPage"
|
122
|
+
tooltip="components.vcsDataTable.formerPage"
|
123
|
+
:disabled="page < 2"
|
124
|
+
class="ml-1"
|
125
|
+
/>
|
126
|
+
<VcsButton
|
127
|
+
small
|
128
|
+
icon="mdi-chevron-right"
|
129
|
+
@click="nextPage"
|
130
|
+
tooltip="components.vcsDataTable.nextPage"
|
131
|
+
:disabled="page > numberOfPages - 1"
|
132
|
+
class="ml-1"
|
133
|
+
/>
|
134
|
+
</v-row>
|
135
|
+
</v-container>
|
136
|
+
</template>
|
137
|
+
</v-data-table>
|
138
|
+
</v-card>
|
139
|
+
</template>
|
140
|
+
<script>
|
141
|
+
import { getCurrentInstance, ref, computed } from 'vue';
|
142
|
+
import {
|
143
|
+
VCard,
|
144
|
+
VDivider,
|
145
|
+
VContainer,
|
146
|
+
VDataTable,
|
147
|
+
VList,
|
148
|
+
VListItem,
|
149
|
+
VListItemTitle,
|
150
|
+
VMenu,
|
151
|
+
VIcon,
|
152
|
+
VRow,
|
153
|
+
} from 'vuetify/lib';
|
154
|
+
import VcsTreeviewSearchbar from '../lists/VcsTreeviewSearchbar.vue';
|
155
|
+
import VcsButton from '../buttons/VcsButton.vue';
|
156
|
+
|
157
|
+
/**
|
158
|
+
* @description A wrapper around {@link https://vuetifyjs.com/en/api/v-data-table/#props v-data-table } with custom pagination
|
159
|
+
* @vue-prop {Array<Object>} items - array of items, where each item must provide a unique key
|
160
|
+
* @vue-prop {string} itemKey - the key property, which is unique on all items.
|
161
|
+
* @vue-prop {Array<{text: string, value: string}>} [headers] - optional array defining column names. Text will be translated
|
162
|
+
* @vue-prop {boolean} [showSearchbar=true] - whether to show searchbar
|
163
|
+
* @vue-prop {string} [searchbarPlaceholder] - placeholder for searchbar
|
164
|
+
* @vue-prop {boolean} [singleSelect=false]
|
165
|
+
* @vue-computed {Array<TableItem>} filteredItems - array of items with search filter applied on. If search string is empty, same as items array.
|
166
|
+
* @vue-computed {Array<import("vuetify").DataTableHeader>} translatedHeaders - array of translated header items.
|
167
|
+
* @vue-computed {number} numberOfItems - number of filtered items (depending on search).
|
168
|
+
* @vue-computed {number} numberOfPages - number of pages depending on number of items, search and itemsPerPage.
|
169
|
+
* @vue-computed {number} itemsFrom - index of first item shown on current page.
|
170
|
+
* @vue-computed {number} itemsTo - index of last item shown on current page.
|
171
|
+
*/
|
172
|
+
export default {
|
173
|
+
name: 'VcsDataTable',
|
174
|
+
components: {
|
175
|
+
VcsButton,
|
176
|
+
VcsTreeviewSearchbar,
|
177
|
+
VCard,
|
178
|
+
VDataTable,
|
179
|
+
VContainer,
|
180
|
+
VDivider,
|
181
|
+
VRow,
|
182
|
+
VMenu,
|
183
|
+
VIcon,
|
184
|
+
VList,
|
185
|
+
VListItem,
|
186
|
+
VListItemTitle,
|
187
|
+
},
|
188
|
+
props: {
|
189
|
+
headers: {
|
190
|
+
type: Array,
|
191
|
+
default: () => [],
|
192
|
+
},
|
193
|
+
items: {
|
194
|
+
type: Array,
|
195
|
+
default: () => [],
|
196
|
+
},
|
197
|
+
itemKey: {
|
198
|
+
type: String,
|
199
|
+
required: true,
|
200
|
+
},
|
201
|
+
itemsPerPage: {
|
202
|
+
type: Number,
|
203
|
+
default: 10,
|
204
|
+
},
|
205
|
+
itemsPerPageArray: {
|
206
|
+
type: Array,
|
207
|
+
default: () => [5, 10, 15],
|
208
|
+
},
|
209
|
+
showSearchbar: {
|
210
|
+
type: Boolean,
|
211
|
+
default: true,
|
212
|
+
},
|
213
|
+
searchbarPlaceholder: {
|
214
|
+
type: String,
|
215
|
+
default: 'components.vcsDataTable.searchbarPlaceholder',
|
216
|
+
},
|
217
|
+
singleSelect: {
|
218
|
+
type: Boolean,
|
219
|
+
default: false,
|
220
|
+
},
|
221
|
+
value: {
|
222
|
+
type: Array,
|
223
|
+
default: () => [],
|
224
|
+
},
|
225
|
+
},
|
226
|
+
setup(props) {
|
227
|
+
const vm = getCurrentInstance().proxy;
|
228
|
+
const hovering = ref(null);
|
229
|
+
/**
|
230
|
+
* @type {Ref<UnwrapRef<string>>}
|
231
|
+
*/
|
232
|
+
const search = ref('');
|
233
|
+
|
234
|
+
/**
|
235
|
+
* @param {any} value
|
236
|
+
* @param {string|undefined} filter
|
237
|
+
* @param {TableItem} item
|
238
|
+
* @returns {boolean}
|
239
|
+
*/
|
240
|
+
const handleFilter = (value, filter, item) => {
|
241
|
+
if (filter) {
|
242
|
+
const q = filter.toLocaleLowerCase();
|
243
|
+
return Object.values(item).some((i) => {
|
244
|
+
const content = i.toString();
|
245
|
+
const translated = vm.$t(content);
|
246
|
+
return translated.toLowerCase().includes(q) || content.toLowerCase().includes(q);
|
247
|
+
});
|
248
|
+
}
|
249
|
+
return true;
|
250
|
+
};
|
251
|
+
|
252
|
+
/**
|
253
|
+
* @type {ComputedRef<Array<Object>>}
|
254
|
+
*/
|
255
|
+
const filteredItems = computed(() => props.items
|
256
|
+
.filter(item => handleFilter(item.value, search.value, item)));
|
257
|
+
const numberOfItems = computed(() => filteredItems.value.length);
|
258
|
+
const totalNumber = computed(() => props.items.length);
|
259
|
+
|
260
|
+
/**
|
261
|
+
* @type {ComputedRef<Array<Object>>}
|
262
|
+
*/
|
263
|
+
const translatedHeaders = computed(() => {
|
264
|
+
return props.headers.map((hd) => {
|
265
|
+
hd.text = vm.$t(hd.text);
|
266
|
+
return hd;
|
267
|
+
});
|
268
|
+
});
|
269
|
+
|
270
|
+
/**
|
271
|
+
* @type {Ref<UnwrapRef<number>>}
|
272
|
+
*/
|
273
|
+
const itemsPerPageRef = ref(props.itemsPerPage);
|
274
|
+
const numberOfPages = computed(() => {
|
275
|
+
return Math.ceil(numberOfItems.value / itemsPerPageRef.value);
|
276
|
+
});
|
277
|
+
/**
|
278
|
+
* @type {Ref<UnwrapRef<number>>}
|
279
|
+
*/
|
280
|
+
const page = ref(1);
|
281
|
+
const itemsFrom = computed(() => ((page.value - 1) * itemsPerPageRef.value) + 1);
|
282
|
+
const itemsTo = computed(() => {
|
283
|
+
const last = page.value * itemsPerPageRef.value;
|
284
|
+
return last < numberOfItems.value ? last : numberOfItems.value;
|
285
|
+
});
|
286
|
+
|
287
|
+
return {
|
288
|
+
hovering,
|
289
|
+
search,
|
290
|
+
page,
|
291
|
+
filteredItems,
|
292
|
+
itemsPerPageRef,
|
293
|
+
itemsFrom,
|
294
|
+
itemsTo,
|
295
|
+
numberOfPages,
|
296
|
+
numberOfItems,
|
297
|
+
totalNumber,
|
298
|
+
nextPage() {
|
299
|
+
if (page.value + 1 <= numberOfPages.value) {
|
300
|
+
page.value += 1;
|
301
|
+
}
|
302
|
+
},
|
303
|
+
formerPage() {
|
304
|
+
if (page.value - 1 >= 1) {
|
305
|
+
page.value -= 1;
|
306
|
+
}
|
307
|
+
},
|
308
|
+
updateItemsPerPage(number) {
|
309
|
+
itemsPerPageRef.value = number;
|
310
|
+
},
|
311
|
+
handleFilter,
|
312
|
+
translatedHeaders,
|
313
|
+
};
|
314
|
+
},
|
315
|
+
};
|
316
|
+
</script>
|
317
|
+
|
318
|
+
<style lang="scss" scoped>
|
319
|
+
@import '../../styles/shades.scss';
|
320
|
+
|
321
|
+
.vcs-select-icon {
|
322
|
+
&.v-icon {
|
323
|
+
font-size: 16px;
|
324
|
+
.v-icon__component {
|
325
|
+
width: 16px;
|
326
|
+
height: 16px;
|
327
|
+
}
|
328
|
+
}
|
329
|
+
}
|
330
|
+
|
331
|
+
::v-deep {
|
332
|
+
.vcs-table {
|
333
|
+
tbody tr {
|
334
|
+
&:hover {
|
335
|
+
background-color: transparent !important;
|
336
|
+
}
|
337
|
+
&:nth-child(odd) {
|
338
|
+
background-color: var(--v-base-lighten4) !important;
|
339
|
+
}
|
340
|
+
}
|
341
|
+
td {
|
342
|
+
font-size: 14px !important;
|
343
|
+
&.v-data-table__mobile-row {
|
344
|
+
justify-content: left;
|
345
|
+
height: 27px;
|
346
|
+
min-height: auto;
|
347
|
+
}
|
348
|
+
}
|
349
|
+
th.sortable {
|
350
|
+
padding: 0 8px;
|
351
|
+
overflow: hidden;
|
352
|
+
white-space: nowrap;
|
353
|
+
span {
|
354
|
+
vertical-align: middle;
|
355
|
+
padding: 0 4px 0 0;
|
356
|
+
}
|
357
|
+
}
|
358
|
+
&.theme--light {
|
359
|
+
thead tr th {
|
360
|
+
color: map-get($shades, 'black') !important;
|
361
|
+
}
|
362
|
+
}
|
363
|
+
&.theme--dark {
|
364
|
+
thead tr th {
|
365
|
+
color: map-get($shades, 'white') !important;
|
366
|
+
}
|
367
|
+
}
|
368
|
+
}
|
369
|
+
.v-btn.vcs-button--small {
|
370
|
+
height: 100% !important;
|
371
|
+
display: block;
|
372
|
+
}
|
373
|
+
}
|
374
|
+
|
375
|
+
.vcs-pagination-bar {
|
376
|
+
.vcs-button-wrap {
|
377
|
+
height: 25px;
|
378
|
+
border: 1px solid;
|
379
|
+
padding: 0 4px;
|
380
|
+
border-radius: 4px;
|
381
|
+
&:hover {
|
382
|
+
border: 1px solid var(--v-primary-base);
|
383
|
+
}
|
384
|
+
}
|
385
|
+
}
|
386
|
+
</style>
|