@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.
Files changed (91) hide show
  1. package/README.md +2 -2
  2. package/app.config.json +5 -0
  3. package/build/buildPreview.js +2 -2
  4. package/config/aerowest.config.json +2 -0
  5. package/config/base.config.json +1 -0
  6. package/config/codes.config.json +2 -0
  7. package/config/dev.config.json +6 -0
  8. package/config/graphFeatureInfo.config.json +3 -1
  9. package/config/projects.config.json +27 -0
  10. package/config/www.config.json +2 -0
  11. package/dist/assets/cesium.js +1 -1
  12. package/dist/assets/{core.a66593.js → core.9342a1.js} +7804 -5352
  13. package/dist/assets/core.js +1 -1
  14. package/dist/assets/index.fd041928.js +1 -0
  15. package/dist/assets/ol.js +1 -1
  16. package/dist/assets/ui.c27597.css +5 -0
  17. package/dist/assets/{ui.d760e4.js → ui.c27597.js} +5055 -4694
  18. package/dist/assets/ui.js +1 -1
  19. package/dist/assets/vue.js +2 -2
  20. package/dist/assets/{vuetify.427322.js → vuetify.2f1432.js} +1 -1
  21. package/dist/assets/vuetify.js +2 -2
  22. package/dist/index.html +1 -1
  23. package/index.js +5 -2
  24. package/package.json +3 -3
  25. package/plugins/@vcmap/project-selector/{ContextsListComponent.vue → ModulesListComponent.vue} +10 -10
  26. package/plugins/@vcmap/project-selector/ProjectSelectorComponent.vue +15 -15
  27. package/plugins/@vcmap/project-selector/README.md +15 -21
  28. package/plugins/@vcmap/project-selector/config.json +3 -3
  29. package/plugins/@vcmap/project-selector/de.json +3 -0
  30. package/plugins/@vcmap/project-selector/en.json +3 -0
  31. package/plugins/@vcmap/project-selector/index.js +76 -101
  32. package/plugins/@vcmap/simple-graph/index.js +1 -1
  33. package/plugins/@vcmap-show-case/category-tester/Categories.vue +2 -2
  34. package/plugins/@vcmap-show-case/category-tester/Category.vue +1 -4
  35. package/plugins/@vcmap-show-case/config-editor/editor.vue +14 -14
  36. package/plugins/@vcmap-show-case/form-inputs-example/FormInputsExample.vue +18 -1
  37. package/plugins/@vcmap-show-case/form-inputs-example/index.js +1 -0
  38. package/plugins/@vcmap-show-case/table-example/DataTableExample.vue +202 -0
  39. package/plugins/@vcmap-show-case/table-example/README.md +3 -0
  40. package/plugins/@vcmap-show-case/table-example/index.js +47 -0
  41. package/plugins/@vcmap-show-case/table-example/package.json +5 -0
  42. package/src/actions/actionHelper.js +16 -27
  43. package/src/actions/styleSelector.vue +26 -19
  44. package/src/components/form-inputs-controls/VcsDatePicker.vue +111 -0
  45. package/src/components/form-inputs-controls/VcsTextField.vue +18 -7
  46. package/src/components/form-inputs-controls/VcsWizard.vue +3 -1
  47. package/src/components/icons/CheckboxCheckedIcon.vue +1 -1
  48. package/src/components/icons/LegendIcon.vue +10 -60
  49. package/src/components/lists/VcsList.vue +25 -6
  50. package/src/components/tables/VcsDataTable.vue +386 -0
  51. package/src/components/tables/VcsTable.vue +33 -278
  52. package/src/contentTree/contentTreeCollection.js +1 -1
  53. package/src/contentTree/layerContentTreeItem.js +3 -0
  54. package/src/downloadHelper.js +49 -0
  55. package/src/featureInfo/BalloonComponent.vue +9 -8
  56. package/src/featureInfo/abstractFeatureInfoView.js +1 -1
  57. package/src/featureInfo/featureInfo.js +3 -3
  58. package/src/i18n/de.js +8 -0
  59. package/src/i18n/en.js +8 -0
  60. package/src/i18n/i18nCollection.js +22 -22
  61. package/src/init.js +90 -7
  62. package/src/manager/categoryManager/CategoryComponent.vue +56 -47
  63. package/src/manager/categoryManager/CategoryManager.vue +23 -10
  64. package/src/manager/categoryManager/categoryManager.js +11 -11
  65. package/src/manager/navbarManager.js +18 -0
  66. package/src/manager/window/WindowComponent.vue +10 -15
  67. package/src/manager/window/WindowComponentHeader.vue +4 -2
  68. package/src/manager/window/WindowManager.vue +14 -15
  69. package/src/manager/window/windowHelper.js +1 -1
  70. package/src/manager/window/windowManager.js +18 -7
  71. package/src/navigation/mapNavCompass.vue +1 -1
  72. package/src/navigation/mapNavigation.vue +6 -6
  73. package/src/navigation/obliqueRotation.vue +36 -13
  74. package/src/navigation/orientationToolsButton.vue +0 -1
  75. package/src/navigation/overviewMap.js +5 -5
  76. package/src/navigation/vcsZoomButton.vue +37 -11
  77. package/src/pluginHelper.js +20 -0
  78. package/src/search/search.js +12 -3
  79. package/src/search/searchComponent.vue +15 -0
  80. package/src/state.js +6 -6
  81. package/src/uiConfig.js +3 -3
  82. package/src/vcsUiApp.js +44 -40
  83. package/src/vuePlugins/i18n.js +1 -0
  84. package/start.js +8 -2
  85. package/dist/assets/index.8b833ead.js +0 -1
  86. package/dist/assets/ui.d760e4.css +0 -5
  87. package/map.config.json +0 -44
  88. /package/dist/assets/{cesium.88cffd.js → cesium.166f91.js} +0 -0
  89. /package/dist/assets/{ol.d4539f.js → ol.d2cba3.js} +0 -0
  90. /package/dist/assets/{vue.db5102.js → vue.5d00e9.js} +0 -0
  91. /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="focus = true;"
21
- @blur="focus = false;"
22
- @input="value => $emit('input', value)"
23
- @keydown.esc="handleEsc"
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 handleEsc() {
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
- handleEsc,
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.5);
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="25.523" viewBox="0 0 24 25.523">
4
- <rect id="size" width="24" height="24" transform="translate(0 1.523)" fill="none" />
5
- <g id="Group_1711" data-name="Group 1711" transform="translate(-712 -904)">
6
- <rect
7
- id="size-2"
8
- data-name="size"
9
- width="24"
10
- height="24"
11
- transform="translate(712 904.521)"
12
- fill="none"
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>