@vcmap/ui 5.0.0-rc.21 → 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 (153) hide show
  1. package/README.md +2 -2
  2. package/app.config.json +5 -0
  3. package/build/buildHelpers.js +1 -0
  4. package/build/buildPreview.js +2 -2
  5. package/build/commonViteConfig.js +1 -0
  6. package/config/aerowest.config.json +2 -0
  7. package/config/base.config.json +1 -0
  8. package/config/codes.config.json +2 -0
  9. package/config/dev.config.json +6 -0
  10. package/config/graphFeatureInfo.config.json +3 -1
  11. package/config/projects.config.json +27 -0
  12. package/config/www.config.json +27 -14
  13. package/dist/assets/cesium.js +1 -1
  14. package/dist/assets/{core.59d4d1.js → core.9342a1.js} +7912 -5474
  15. package/dist/assets/core.js +1 -1
  16. package/dist/assets/favicon.decf54cc.svg +10 -0
  17. package/dist/assets/index.fd041928.js +1 -0
  18. package/dist/assets/{ol.c1c512.js → ol.d2cba3.js} +12406 -12152
  19. package/dist/assets/ol.js +1 -1
  20. package/dist/assets/ui.c27597.css +5 -0
  21. package/dist/assets/{ui.80175f.js → ui.c27597.js} +6508 -5169
  22. package/dist/assets/ui.js +1 -1
  23. package/dist/assets/vue.js +2 -2
  24. package/dist/assets/vuetify.2f1432.css +5 -0
  25. package/dist/assets/{vuetify.efc158.js → vuetify.2f1432.js} +1 -1
  26. package/dist/assets/vuetify.js +2 -2
  27. package/dist/index.html +6 -1
  28. package/index.html +5 -0
  29. package/index.js +7 -3
  30. package/lib/olLib.js +15 -1
  31. package/package.json +5 -4
  32. package/plugins/@vcmap/project-selector/{ContextsListComponent.vue → ModulesListComponent.vue} +10 -10
  33. package/plugins/@vcmap/project-selector/ProjectSelectorComponent.vue +16 -16
  34. package/plugins/@vcmap/project-selector/README.md +15 -21
  35. package/plugins/@vcmap/project-selector/config.json +3 -3
  36. package/plugins/@vcmap/project-selector/de.json +3 -0
  37. package/plugins/@vcmap/project-selector/en.json +3 -0
  38. package/plugins/@vcmap/project-selector/index.js +76 -101
  39. package/plugins/@vcmap/simple-graph/index.js +1 -1
  40. package/plugins/@vcmap/theme-changer/ThemeChangerComponent.vue +10 -4
  41. package/plugins/@vcmap-show-case/category-tester/Categories.vue +2 -2
  42. package/plugins/@vcmap-show-case/category-tester/Category.vue +1 -4
  43. package/plugins/@vcmap-show-case/config-editor/editor.vue +14 -14
  44. package/plugins/@vcmap-show-case/form-inputs-example/FormInputsExample.vue +92 -81
  45. package/plugins/@vcmap-show-case/form-inputs-example/index.js +8 -3
  46. package/plugins/@vcmap-show-case/form-inputs-example/validation.js +1 -1
  47. package/plugins/@vcmap-show-case/list-example/ListExample.vue +5 -2
  48. package/plugins/@vcmap-show-case/table-example/DataTableExample.vue +202 -0
  49. package/plugins/@vcmap-show-case/table-example/README.md +3 -0
  50. package/plugins/@vcmap-show-case/table-example/index.js +47 -0
  51. package/plugins/@vcmap-show-case/table-example/package.json +5 -0
  52. package/plugins/@vcmap-show-case/wizard-example/wizardExample.vue +57 -23
  53. package/plugins/package.json +2 -1
  54. package/src/actions/actionHelper.js +16 -27
  55. package/src/actions/styleSelector.vue +26 -19
  56. package/src/application/VcsApp.vue +13 -5
  57. package/src/application/VcsAttributions.vue +2 -3
  58. package/src/application/VcsAttributionsFooter.vue +10 -16
  59. package/src/application/VcsNavbar.vue +1 -2
  60. package/src/application/VcsSettings.vue +21 -8
  61. package/src/assets/favicon-128.png +0 -0
  62. package/src/assets/favicon-180.png +0 -0
  63. package/src/assets/favicon-192.png +0 -0
  64. package/src/assets/favicon-32.png +0 -0
  65. package/src/assets/favicon.svg +10 -0
  66. package/src/components/buttons/VcsButton.vue +2 -3
  67. package/src/components/form-inputs-controls/VcsCheckbox.vue +46 -26
  68. package/src/components/form-inputs-controls/VcsDatePicker.vue +111 -0
  69. package/src/components/form-inputs-controls/VcsFormSection.vue +15 -13
  70. package/src/components/form-inputs-controls/VcsLabel.vue +10 -1
  71. package/src/components/form-inputs-controls/VcsRadio.vue +38 -18
  72. package/src/components/form-inputs-controls/VcsSelect.vue +117 -59
  73. package/src/components/form-inputs-controls/VcsTextArea.vue +101 -60
  74. package/src/components/form-inputs-controls/VcsTextField.vue +182 -69
  75. package/src/components/form-inputs-controls/VcsWizard.vue +23 -15
  76. package/src/components/form-inputs-controls/VcsWizardStep.vue +18 -16
  77. package/src/components/form-inputs-controls/composables.js +26 -0
  78. package/src/components/form-output/VcsFormattedNumber.vue +1 -1
  79. package/src/components/icons/2DDistanceIcon.vue +0 -3
  80. package/src/components/icons/3DDistanceIcon.vue +0 -3
  81. package/src/components/icons/3DHeightIcon.vue +0 -3
  82. package/src/components/icons/CheckboxCheckedIcon.vue +4 -11
  83. package/src/components/icons/CheckboxIcon.vue +9 -2
  84. package/src/components/icons/CheckboxIndeterminateIcon.vue +4 -21
  85. package/src/components/icons/CommentIcon.vue +1 -5
  86. package/src/components/icons/LegendIcon.vue +10 -60
  87. package/src/components/icons/ObliqueViewIcon.vue +6 -8
  88. package/src/components/icons/SimpleCircleOutlinedIcon.vue +1 -1
  89. package/src/components/icons/SplitViewIcon.vue +0 -4
  90. package/src/components/icons/ToolsIcon.vue +2 -4
  91. package/src/components/lists/VcsActionList.vue +0 -1
  92. package/src/components/lists/VcsList.vue +30 -30
  93. package/src/components/lists/VcsTreeview.vue +2 -2
  94. package/src/components/lists/VcsTreeviewLeaf.vue +3 -9
  95. package/src/components/lists/VcsTreeviewSearchbar.vue +4 -4
  96. package/src/components/notification/VcsBadge.vue +6 -2
  97. package/src/components/notification/VcsHelp.vue +39 -0
  98. package/src/components/tables/VcsDataTable.vue +386 -0
  99. package/src/components/tables/VcsTable.vue +55 -254
  100. package/src/contentTree/contentTreeCollection.js +1 -1
  101. package/src/contentTree/layerContentTreeItem.js +3 -0
  102. package/src/downloadHelper.js +49 -0
  103. package/src/featureInfo/AddressBalloonComponent.vue +1 -1
  104. package/src/featureInfo/BalloonComponent.vue +21 -15
  105. package/src/featureInfo/abstractFeatureInfoView.js +1 -1
  106. package/src/featureInfo/featureInfo.js +27 -9
  107. package/src/featureInfo/tableFeatureInfoView.js +4 -0
  108. package/src/i18n/de.js +13 -1
  109. package/src/i18n/en.js +13 -1
  110. package/src/i18n/i18nCollection.js +22 -22
  111. package/src/init.js +90 -7
  112. package/src/legend/styleLegendItem.vue +24 -2
  113. package/src/legend/vcsLegend.vue +24 -31
  114. package/src/manager/categoryManager/CategoryComponent.vue +56 -47
  115. package/src/manager/categoryManager/CategoryManager.vue +23 -10
  116. package/src/manager/categoryManager/categoryManager.js +11 -11
  117. package/src/manager/navbarManager.js +18 -0
  118. package/src/manager/toolbox/GroupToolboxComponent.vue +2 -3
  119. package/src/manager/toolbox/SelectToolboxComponent.vue +11 -5
  120. package/src/manager/toolbox/ToolboxManager.vue +0 -7
  121. package/src/manager/window/WindowComponent.vue +10 -16
  122. package/src/manager/window/WindowComponentHeader.vue +6 -4
  123. package/src/manager/window/WindowManager.vue +14 -15
  124. package/src/manager/window/windowHelper.js +1 -1
  125. package/src/manager/window/windowManager.js +18 -7
  126. package/src/navigation/mapNavCompass.vue +1 -1
  127. package/src/navigation/mapNavigation.vue +6 -6
  128. package/src/navigation/obliqueRotation.vue +36 -13
  129. package/src/navigation/orientationToolsButton.vue +0 -1
  130. package/src/navigation/overviewMap.js +11 -20
  131. package/src/navigation/tiltSlider.vue +30 -6
  132. package/src/navigation/vcsZoomButton.vue +37 -11
  133. package/src/pluginHelper.js +20 -0
  134. package/src/search/resultsComponent.vue +0 -1
  135. package/src/search/search.js +19 -20
  136. package/src/search/searchComponent.vue +21 -7
  137. package/src/state.js +6 -6
  138. package/src/styles/_theming.scss +72 -3
  139. package/src/styles/_typography.scss +0 -5
  140. package/src/styles/main.scss +1 -0
  141. package/src/styles/shades.scss +2 -0
  142. package/src/styles/variables.scss +40 -4
  143. package/src/uiConfig.js +4 -3
  144. package/src/vcsUiApp.js +49 -40
  145. package/src/vuePlugins/i18n.js +1 -0
  146. package/src/vuePlugins/vuetify.js +59 -13
  147. package/start.js +8 -2
  148. package/dist/assets/index.a3861d4e.js +0 -1
  149. package/dist/assets/ui.80175f.css +0 -1
  150. package/dist/assets/vuetify.efc158.css +0 -5
  151. package/map.config.json +0 -44
  152. /package/dist/assets/{cesium.49585c.js → cesium.166f91.js} +0 -0
  153. /package/dist/assets/{vue.a08ab1.js → vue.5d00e9.js} +0 -0
package/src/i18n/de.js CHANGED
@@ -55,18 +55,26 @@ const messages = {
55
55
  vcsTable: {
56
56
  key: 'Name',
57
57
  value: 'Wert',
58
+ },
59
+ vcsDataTable: {
58
60
  searchbarPlaceholder: 'Name, Wert, ...',
59
61
  itemsPerPage: 'pro Seite',
60
62
  ofItems: 'von',
61
63
  nextPage: 'Nächste Seite',
62
64
  formerPage: 'Vorherige Seite',
65
+ noDataPlaceholder: 'Keine Daten verfügbar',
66
+ noResultsPlaceholder: 'Keine übereinstimmenden Einträge gefunden',
63
67
  },
64
68
  },
65
69
  settings: {
66
70
  title: 'Einstellungen',
67
71
  tooltip: 'Einstellungen',
68
- languageTitle: 'Spracheinstellungen',
69
72
  languageSelector: 'Sprache',
73
+ theme: {
74
+ title: 'Farbschema',
75
+ dark: 'Dunkel',
76
+ light: 'Hell',
77
+ },
70
78
  },
71
79
  featureInfo: {
72
80
  activateToolTitle: 'Informationstool aktivieren',
@@ -85,6 +93,7 @@ const messages = {
85
93
  select: 'Suchergebnis selektieren',
86
94
  placeholder: 'Suche nach Straße, Adresse, Ort, POI',
87
95
  zoomToFeatureAction: 'Auf Ergebnis zoomen',
96
+ zoomToAll: 'Zu allen Ergebnissen zoomen',
88
97
  },
89
98
  toolbox: {
90
99
  flight: 'Flug',
@@ -103,6 +112,9 @@ const messages = {
103
112
  information: 'Information',
104
113
  success: 'Erfolg',
105
114
  },
115
+ datePicker: {
116
+ today: 'Heute',
117
+ },
106
118
  };
107
119
 
108
120
  export default messages;
package/src/i18n/en.js CHANGED
@@ -55,18 +55,26 @@ const messages = {
55
55
  vcsTable: {
56
56
  key: 'Name',
57
57
  value: 'Value',
58
+ },
59
+ vcsDataTable: {
58
60
  searchbarPlaceholder: 'Name, Value, ...',
59
61
  itemsPerPage: 'per page',
60
62
  ofItems: 'of',
61
63
  nextPage: 'Next page',
62
64
  formerPage: 'Former page',
65
+ noDataPlaceholder: 'No data available',
66
+ noResultsPlaceholder: 'No matching records found',
63
67
  },
64
68
  },
65
69
  settings: {
66
70
  title: 'Settings',
67
71
  tooltip: 'Settings',
68
- languageTitle: 'Language settings',
69
72
  languageSelector: 'Language',
73
+ theme: {
74
+ title: 'Color theme',
75
+ dark: 'Dark',
76
+ light: 'Light',
77
+ },
70
78
  },
71
79
  featureInfo: {
72
80
  activateToolTitle: 'Activate Infotool',
@@ -85,6 +93,7 @@ const messages = {
85
93
  select: 'Select result item',
86
94
  placeholder: 'Search for Street, Address, Landmark, POI',
87
95
  zoomToFeatureAction: 'Zoom to result',
96
+ zoomToAll: 'Zoom to all',
88
97
  },
89
98
  toolbox: {
90
99
  flight: 'flight',
@@ -103,6 +112,9 @@ const messages = {
103
112
  information: 'Information',
104
113
  success: 'Success',
105
114
  },
115
+ datePicker: {
116
+ today: 'Today',
117
+ },
106
118
  };
107
119
 
108
120
  export default messages;
@@ -1,5 +1,5 @@
1
1
  // eslint-disable-next-line max-classes-per-file
2
- import { contextIdSymbol, IndexedCollection } from '@vcmap/core';
2
+ import { moduleIdSymbol, IndexedCollection } from '@vcmap/core';
3
3
  import { getLogger } from '@vcsuite/logger';
4
4
 
5
5
  /**
@@ -51,59 +51,59 @@ export function mergeDeep(...sources) {
51
51
  */
52
52
  class I18nCollection extends IndexedCollection {
53
53
  /**
54
- * @param {function():string} getDynamicContextId - function to get the current dynamic context id
54
+ * @param {function():string} getDynamicModuleId - function to get the current dynamic module id
55
55
  */
56
- constructor(getDynamicContextId) {
56
+ constructor(getDynamicModuleId) {
57
57
  super(false);
58
58
  /**
59
59
  * @type {function(): string}
60
60
  * @private
61
61
  */
62
- this._getDynamicContextId = getDynamicContextId;
62
+ this._getDynamicModuleId = getDynamicModuleId;
63
63
  }
64
64
 
65
65
  /**
66
66
  * @inheritDoc
67
67
  */
68
68
  add(item) {
69
- if (!item[contextIdSymbol]) {
70
- item[contextIdSymbol] = this._getDynamicContextId();
69
+ if (!item[moduleIdSymbol]) {
70
+ item[moduleIdSymbol] = this._getDynamicModuleId();
71
71
  }
72
72
  super.add(item);
73
73
  }
74
74
 
75
75
  /**
76
76
  * @param {Array<Object>} configArray
77
- * @param {string} contextId
77
+ * @param {string} moduleId
78
78
  * @returns {Promise<void>}
79
79
  */
80
- async parseItems(configArray, contextId) {
80
+ async parseItems(configArray, moduleId) {
81
81
  if (Array.isArray(configArray)) {
82
82
  configArray.forEach((item) => {
83
- item[contextIdSymbol] = contextId;
83
+ item[moduleIdSymbol] = moduleId;
84
84
  this.add(item);
85
85
  });
86
86
  }
87
87
  }
88
88
 
89
89
  /**
90
- * @param {string} contextId
90
+ * @param {string} moduleId
91
91
  */
92
- async removeContext(contextId) {
92
+ async removeModule(moduleId) {
93
93
  [...this]
94
- .filter(item => item[contextIdSymbol] === contextId)
94
+ .filter(item => item[moduleIdSymbol] === moduleId)
95
95
  .forEach((item) => {
96
96
  this.remove(item);
97
97
  });
98
98
  }
99
99
 
100
100
  /**
101
- * @param {string} contextId
101
+ * @param {string} moduleId
102
102
  * @returns {Array<Object>}
103
103
  */
104
- serializeContext(contextId) {
104
+ serializeModule(moduleId) {
105
105
  return [...this]
106
- .filter(item => item[contextIdSymbol] === contextId)
106
+ .filter(item => item[moduleIdSymbol] === moduleId)
107
107
  .filter(item => !item[i18nPluginSymbol])
108
108
  .map(item => JSON.parse(JSON.stringify(item)));
109
109
  }
@@ -112,12 +112,12 @@ class I18nCollection extends IndexedCollection {
112
112
  * This method adds plugin messages to the collection. It is no necessary to call this function
113
113
  * from within a plugin. Use the i18n property on your plugin.
114
114
  * @param {string} plugin Name of the plugin
115
- * @param {string} contextId
115
+ * @param {string} moduleId
116
116
  * @param {Object} messages
117
117
  */
118
- addPluginMessages(plugin, contextId, messages) {
118
+ addPluginMessages(plugin, moduleId, messages) {
119
119
  messages[i18nPluginSymbol] = plugin;
120
- messages[contextIdSymbol] = contextId;
120
+ messages[moduleIdSymbol] = moduleId;
121
121
  this.add(messages);
122
122
  }
123
123
 
@@ -125,11 +125,11 @@ class I18nCollection extends IndexedCollection {
125
125
  * This method removes plugin messages from the collection. It is no necessary to call this function
126
126
  * from within a plugin. Once your plugin is removed, the VcsUiApp will call this for you.
127
127
  * @param {string} pluginName
128
- * @param {string} contextId
128
+ * @param {string} moduleId
129
129
  */
130
- removePluginMessages(pluginName, contextId) {
130
+ removePluginMessages(pluginName, moduleId) {
131
131
  [...this]
132
- .filter(item => item[i18nPluginSymbol] === pluginName && item[contextIdSymbol] === contextId)
132
+ .filter(item => item[i18nPluginSymbol] === pluginName && item[moduleIdSymbol] === moduleId)
133
133
  .forEach((item) => {
134
134
  this.remove(item);
135
135
  });
@@ -147,7 +147,7 @@ class I18nCollection extends IndexedCollection {
147
147
  * @inheritDoc
148
148
  */
149
149
  destroy() {
150
- this._getDynamicContextId = null;
150
+ this._getDynamicModuleId = null;
151
151
  super.destroy();
152
152
  }
153
153
  }
package/src/init.js CHANGED
@@ -1,20 +1,49 @@
1
1
  import Vue from 'vue';
2
- import { check, checkMaybe } from '@vcsuite/check';
3
- import { Context } from '@vcmap/core';
2
+ import { check, checkMaybe, is } from '@vcsuite/check';
3
+ import { VcsModule } from '@vcmap/core';
4
4
  import VcsAppComponentWrapper from './application/vcsAppWrapper.vue';
5
5
  import { vuetify } from './vuePlugins/vuetify.js';
6
6
  import { createVueI18n, setupI18n } from './vuePlugins/i18n.js';
7
7
  import VcsUiApp from './vcsUiApp.js';
8
8
 
9
+ /**
10
+ * Base pattern to check VcsObjects
11
+ * @type {import("vcsuite/check").PatternFor<import("@vcmap/core").VcsObject>}
12
+ */
13
+ const VcsObjectPattern = {
14
+ type: String,
15
+ name: String,
16
+ };
17
+
18
+ /**
19
+ * Base pattern to check VcsUiAppConfig
20
+ * @type {import("vcsuite/check").PatternFor<VcsUiAppConfig>}
21
+ */
22
+ export const VcsUiAppConfigPattern = {
23
+ id: [undefined, String],
24
+ layers: [undefined, [VcsObjectPattern]],
25
+ maps: [undefined, [VcsObjectPattern]],
26
+ styles: [undefined, [VcsObjectPattern]],
27
+ viewpoints: [undefined, [VcsObjectPattern]],
28
+ startingViewpointName: [undefined, String],
29
+ startingMapName: [undefined, String],
30
+ projection: [undefined, Object],
31
+ categories: [undefined, [{ name: String, items: [Object] }]],
32
+ obliqueCollections: [undefined, [VcsObjectPattern]],
33
+ plugins: [undefined, [Object]],
34
+ contentTree: [undefined, [Object]],
35
+ uiConfig: [undefined, [Object]],
36
+ featureInfo: [undefined, [VcsObjectPattern]],
37
+ i18n: [undefined, [Object]],
38
+ };
39
+
9
40
  /**
10
41
  * creates and mounts a vcsApp
11
42
  * @param {string} mountTarget
12
- * @param {string=} configUrl optional config
13
43
  * @returns {Promise<VcsUiApp>}
14
44
  */
15
- export default async function initApp(mountTarget, configUrl) {
45
+ export default async function initApp(mountTarget) {
16
46
  check(mountTarget, String);
17
- checkMaybe(configUrl, String);
18
47
  const app = new VcsUiApp();
19
48
  const i18n = createVueI18n();
20
49
  new Vue({
@@ -28,11 +57,65 @@ export default async function initApp(mountTarget, configUrl) {
28
57
  }).$mount(mountTarget);
29
58
 
30
59
  setupI18n(app, i18n);
60
+ return app;
61
+ }
62
+
63
+ /**
64
+ * Initializes app with an optional single config
65
+ * @param {string} mountTarget
66
+ * @param {string=} configUrl optional config
67
+ * @returns {Promise<VcsUiApp>}
68
+ */
69
+ export async function initAppFromModule(mountTarget, configUrl) {
70
+ check(mountTarget, String);
71
+ checkMaybe(configUrl, String);
72
+
73
+ const app = await initApp(mountTarget);
31
74
  if (configUrl) {
32
75
  const config = await fetch(configUrl)
33
76
  .then(response => response.json());
34
- const context = new Context(config);
35
- await app.addContext(context);
77
+ const module = new VcsModule(config);
78
+ await app.addModule(module);
36
79
  }
80
+
37
81
  return app;
38
82
  }
83
+
84
+ /**
85
+ * Initializes app with a map config containing a set of config urls
86
+ * @param {string} mountTarget
87
+ * @param {string} appUrl app config containing further modules to be loaded
88
+ * @returns {Promise<VcsUiApp>}
89
+ */
90
+ export async function initAppFromAppConfig(mountTarget, appUrl) {
91
+ check(mountTarget, String);
92
+ check(appUrl, String);
93
+
94
+ const app = await initApp(mountTarget);
95
+ /**
96
+ * @type {{modules: Array<string|VcsUiAppConfig>}}
97
+ */
98
+ const appConfig = await fetch(appUrl)
99
+ .then(response => response.json());
100
+
101
+ check(appConfig.modules, [String, Object]);
102
+
103
+ const modules = await Promise.all(appConfig.modules.map(async (c) => {
104
+ if (is(c, VcsUiAppConfigPattern)) {
105
+ return new VcsModule(/** @type{import("@vcmap/core").VcsAppConfig} */ c);
106
+ } else if (is(c, String)) {
107
+ const response = await fetch(c);
108
+ if (response.ok) {
109
+ const config = await response.json();
110
+ return new VcsModule(config);
111
+ }
112
+ }
113
+ return null;
114
+ }));
115
+ // eslint-disable-next-line no-restricted-syntax
116
+ for await (const module of modules) {
117
+ if (module) {
118
+ await app.addModule(module);
119
+ }
120
+ }
121
+ }
@@ -6,7 +6,11 @@
6
6
  :key="idx"
7
7
  :class="{ 'w-full': item.colNr === 1, 'w-half': item.colNr !== 1 }"
8
8
  >
9
- <v-list-item dense>
9
+ <v-list-item
10
+ dense
11
+ class="pa-0"
12
+ :class="determineInnerPadding(idx)"
13
+ >
10
14
  <v-list-item-icon class="pr-2">
11
15
  <v-img
12
16
  v-if="row.type === StyleRowType.Icon || row.type === StyleRowType.Shape"
@@ -126,7 +130,24 @@
126
130
  required: true,
127
131
  },
128
132
  },
129
- setup() {
133
+ setup(props) {
134
+ /**
135
+ * Determines if a list item has padding right or left, so it has correct spacing to second row.
136
+ * @param {number} index The index of the list item. Starts with 0.
137
+ * @returns {string} Vuetify padding helper.
138
+ */
139
+ function determineInnerPadding(index) {
140
+ // check if there are more than two columns
141
+ if (props.item.colNr !== 1) {
142
+ // check if even number. If so, it is located in the left column and needs padding on the right.
143
+ if (index % 2 === 0) {
144
+ return 'pr-2';
145
+ } else {
146
+ return 'pl-2';
147
+ }
148
+ }
149
+ return '';
150
+ }
130
151
  return {
131
152
  StyleRowType,
132
153
  getImageSrcFromShape,
@@ -136,6 +157,7 @@
136
157
  }
137
158
  return null;
138
159
  },
160
+ determineInnerPadding,
139
161
  };
140
162
  },
141
163
  };
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <v-card
2
+ <v-sheet
3
3
  class="overflow-y-auto"
4
4
  >
5
5
  <v-expansion-panels
@@ -7,47 +7,48 @@
7
7
  multiple
8
8
  v-if="entries.length > 0"
9
9
  v-model="panels"
10
+ class="rounded-0"
10
11
  >
11
12
  <v-expansion-panel
12
13
  v-for="(entry,i) in entries"
13
14
  :key="i"
14
- class="pa-0 ma-0"
15
+ class="px-2"
15
16
  @change="entry.open = !entry.open"
16
17
  >
17
18
  <v-expansion-panel-header hide-actions>
18
- {{ $t(entry.title) }}
19
19
  <template #default="{ open }">
20
- <div class="d-flex">
21
- <v-icon :class="{ 'v-treeview-node__toggle': !open }">
22
- mdi-chevron-down
23
- </v-icon>
24
- <VcsTreeviewLeaf class="w-full" :item="entry" />
20
+ <div class="d-flex justify-space-between">
21
+ <div class="d-flex align-center">
22
+ <v-icon class="mr-1" :class="{ 'rotate': !open }">
23
+ mdi-chevron-down
24
+ </v-icon>
25
+ {{ $t(entry.title) }}
26
+ </div>
27
+ <VcsActionButtonList small :actions="entry.actions" />
25
28
  </div>
26
29
  </template>
27
30
  </v-expansion-panel-header>
28
- <v-expansion-panel-content>
31
+ <v-expansion-panel-content class="pl-6 pb-2">
29
32
  <v-list dense>
30
33
  <div v-for="(item, idx) in entry.legend" :key="idx">
31
- <div v-if="item.type === LegendType.Image" class="mx-2">
34
+ <div v-if="item.type === LegendType.Image">
32
35
  <img
33
36
  :src="$t(item.src)"
34
- max-width="287"
35
- max-height="auto"
36
- class="mx-2 legend-image"
37
+ class="legend-image"
37
38
  :title="item.tooltip"
38
39
  >
39
40
  </div>
40
- <div v-else-if="item.type === LegendType.Iframe" class="mx-2">
41
+ <div v-else-if="item.type === LegendType.Iframe">
41
42
  <iframe
42
43
  :id="`legendIframe${idx}`"
43
44
  :src="$t(item.src)"
44
45
  scrolling="no"
45
- width="287"
46
+ style="width: 100%; height: 100%;"
46
47
  frameBorder="0"
47
48
  @load="setIframeHeight(`legendIframe${idx}`)"
48
49
  />
49
50
  </div>
50
- <style-legend-item v-else :item="item" class="mx-2" />
51
+ <style-legend-item v-else :item="item" />
51
52
  </div>
52
53
  </v-list>
53
54
  </v-expansion-panel-content>
@@ -56,13 +57,12 @@
56
57
  <v-sheet v-else class="ma-2">
57
58
  {{ $t('legend.empty') }}
58
59
  </v-sheet>
59
- </v-card>
60
+ </v-sheet>
60
61
  </template>
61
62
 
62
63
  <script>
63
64
 
64
65
  import {
65
- VCard,
66
66
  VExpansionPanels,
67
67
  VExpansionPanel,
68
68
  VExpansionPanelHeader,
@@ -74,7 +74,7 @@
74
74
  import { computed } from 'vue';
75
75
  import { LegendType } from './legendHelper.js';
76
76
  import StyleLegendItem from './styleLegendItem.vue';
77
- import VcsTreeviewLeaf from '../components/lists/VcsTreeviewLeaf.vue';
77
+ import VcsActionButtonList from '../components/buttons/VcsActionButtonList.vue';
78
78
 
79
79
  /**
80
80
  * @description A component rendering configured legend information for active layers.
@@ -84,9 +84,8 @@
84
84
  export default {
85
85
  name: 'VcsLegend',
86
86
  components: {
87
- VcsTreeviewLeaf,
87
+ VcsActionButtonList,
88
88
  StyleLegendItem,
89
- VCard,
90
89
  VExpansionPanels,
91
90
  VExpansionPanel,
92
91
  VExpansionPanelHeader,
@@ -130,17 +129,11 @@
130
129
  </script>
131
130
 
132
131
  <style lang="scss" scoped>
133
- .v-list-item--dense {
134
- height: 32px;
135
- }
136
- ::v-deep {
137
- .treeview-label {
138
- max-width: 189px;
139
- }
140
- }
141
132
  .legend-image {
142
- max-width: 287px;
133
+ max-width: 100%;
143
134
  height: auto;
144
- width: auto;
135
+ }
136
+ .rotate {
137
+ transform: rotate(-90deg);
145
138
  }
146
139
  </style>
@@ -1,48 +1,54 @@
1
1
  <template>
2
- <v-container>
3
- <v-row @click="open = !open" class="px-2 py-1 cursor-pointer">
4
- <span>
5
- <v-icon v-if="open">mdi-chevron-up</v-icon>
6
- <v-icon v-else>mdi-chevron-down</v-icon>
7
- </span>
8
- <span class="flex-grow-1 flex-shrink-1">{{ $t(category.title) }}</span>
9
- <vcs-action-button-list
10
- v-if="category.actions?.length > 0"
11
- :actions="category.actions"
12
- small
13
- />
14
- </v-row>
15
- <template v-if="open">
16
- <v-row>
17
- <v-col class="pa-0">
18
- <vcs-list
19
- :items="category.items.slice(0, 10)"
20
- :selectable="category.selectable"
21
- :single-select="category.singleSelect"
22
- v-model="selection"
23
- :show-title="false"
2
+ <v-expansion-panel
3
+ class="px-2"
4
+ @change="active = !active"
5
+ >
6
+ <v-expansion-panel-header hide-actions>
7
+ <template #default="{ open }">
8
+ <div class="d-flex justify-space-between">
9
+ <div class="d-flex align-center">
10
+ <v-icon class="mr-1" :class="{ 'rotate': !open }">
11
+ mdi-chevron-down
12
+ </v-icon>
13
+ {{ $t(category.title) }}
14
+ </div>
15
+ <VcsActionButtonList
16
+ v-if="category.actions?.length > 0"
17
+ :actions="category.actions"
18
+ small
19
+ class="float-end"
24
20
  />
25
- </v-col>
26
- </v-row>
27
- <v-row v-if="category.items.length > 10">
28
- <v-col class="pa-0">
29
- <VcsButton @click="openCategoryItemWindow" class="pa-2" small>
30
- {{ $t('categoryManager.more') }}
31
- </VcsButton>
32
- </v-col>
33
- </v-row>
34
- <v-row v-else-if="category.items.length === 0">
35
- <v-col class="pa-2">
36
- {{ $t('categoryManager.empty') }}
37
- </v-col>
38
- </v-row>
39
- </template>
40
- </v-container>
21
+ </div>
22
+ </template>
23
+ </v-expansion-panel-header>
24
+ <v-expansion-panel-content class="pb-1">
25
+ <vcs-list
26
+ :items="category.items.slice(0, 10)"
27
+ :selectable="category.selectable"
28
+ :single-select="category.singleSelect"
29
+ v-model="selection"
30
+ :show-title="false"
31
+ />
32
+ <v-sheet v-if="category.items.length > 10" class="ma-2 pl-2">
33
+ <VcsButton @click="openCategoryItemWindow" small>
34
+ {{ $t('categoryManager.more') }}
35
+ </VcsButton>
36
+ </v-sheet>
37
+ <v-sheet v-else-if="category.items.length === 0" class="ma-2 pl-2">
38
+ {{ $t('categoryManager.empty') }}
39
+ </v-sheet>
40
+ </v-expansion-panel-content>
41
+ </v-expansion-panel>
41
42
  </template>
42
43
 
43
44
  <script>
44
45
  import { computed, inject, ref } from 'vue';
45
- import { VIcon, VContainer, VRow, VCol } from 'vuetify/lib';
46
+ import {
47
+ VIcon, VExpansionPanel,
48
+ VExpansionPanelHeader,
49
+ VExpansionPanelContent,
50
+ VSheet,
51
+ } from 'vuetify/lib';
46
52
  import VcsList from '../../components/lists/VcsList.vue';
47
53
  import VcsActionButtonList from '../../components/buttons/VcsActionButtonList.vue';
48
54
  import VcsButton from '../../components/buttons/VcsButton.vue';
@@ -54,11 +60,12 @@
54
60
  name: 'CategoryComponent',
55
61
  components: {
56
62
  VcsActionButtonList,
57
- VcsList,
58
- VContainer,
59
- VRow,
60
63
  VcsButton,
61
- VCol,
64
+ VcsList,
65
+ VExpansionPanel,
66
+ VExpansionPanelHeader,
67
+ VExpansionPanelContent,
68
+ VSheet,
62
69
  VIcon,
63
70
  },
64
71
  props: {
@@ -72,7 +79,7 @@
72
79
  /** @type {VcsUiApp} */
73
80
  const app = inject('vcsApp');
74
81
  const windowId = `${category.id}-category-list`;
75
- const open = ref(false);
82
+ const active = ref(false);
76
83
 
77
84
  const selection = computed({
78
85
  get() { return category.selection; },
@@ -84,7 +91,7 @@
84
91
 
85
92
  return {
86
93
  selection,
87
- open,
94
+ active,
88
95
  openCategoryItemWindow() {
89
96
  if (app.windowManager.has(windowId)) {
90
97
  setTimeout(() => {
@@ -110,6 +117,8 @@
110
117
  };
111
118
  </script>
112
119
 
113
- <style scoped>
114
-
120
+ <style lang="scss" scoped>
121
+ .rotate {
122
+ transform: rotate(-90deg);
123
+ }
115
124
  </style>