@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
@@ -3,16 +3,16 @@
3
3
  :class="{ 'win-container-mobile' : $vuetify.breakpoint.xs }"
4
4
  >
5
5
  <WindowComponent
6
- v-for="(id, zIndex) in componentIds"
6
+ v-for="id in componentIds"
7
7
  :key="id"
8
8
  :window-state="getState(id)"
9
9
  :slot-window="getSlot(id)"
10
- :z-index="zIndex"
10
+ :z-index="getComponent(id).zIndex"
11
11
  @moved="move(id, $event)"
12
- @click="clicked(id)"
13
- :style="getStyles(id, zIndex).value"
12
+ @mousedown="bringWindowToTop(id)"
13
+ :style="getStyles(id).value"
14
14
  :class="getState(id).classes"
15
- :is-on-top="isOnTop(zIndex)"
15
+ :is-on-top="isOnTop(id)"
16
16
  >
17
17
  <component
18
18
  :is="getComponent(id)"
@@ -23,7 +23,7 @@
23
23
  <component
24
24
  :is="getHeaderComponent(id)"
25
25
  :window-state="getState(id)"
26
- :is-on-top="isOnTop(zIndex)"
26
+ :is-on-top="isOnTop(id)"
27
27
  :slot-window="getSlot(id)"
28
28
  v-bind="getProps(id)"
29
29
  @close="close(id)"
@@ -84,23 +84,22 @@
84
84
  return windowManager.get(id)?.props ?? {};
85
85
  };
86
86
  /**
87
- * @param {number} zIndex
87
+ * @param {string} id
88
88
  * @returns {boolean}
89
89
  */
90
- const isOnTop = (zIndex) => {
91
- return zIndex === componentIds.length - 1;
90
+ const isOnTop = (id) => {
91
+ return windowManager.get(id)?.zIndex.value === componentIds.length - 1;
92
92
  };
93
93
  /**
94
94
  * @param {string} id
95
- * @param {number} zIndex
96
95
  * @returns {import("vue").ComputedRef<Object>}
97
96
  */
98
- const getStyles = (id, zIndex) => computed(() => {
97
+ const getStyles = id => computed(() => {
99
98
  const windowComponent = windowManager.get(id);
100
99
  const state = windowComponent?.state;
101
100
  const position = applyPositionOnTarget(windowComponent?.position, targetSize.value);
102
101
  return {
103
- zIndex,
102
+ zIndex: windowComponent.zIndex.value,
104
103
  ...position,
105
104
  ...(state.styles || {}),
106
105
  };
@@ -108,8 +107,8 @@
108
107
  /**
109
108
  * @param {string} id
110
109
  */
111
- const clicked = (id) => {
112
- if (windowManager.has(id)) {
110
+ const bringWindowToTop = (id) => {
111
+ if (windowManager.has(id) && !isOnTop(id)) {
113
112
  windowManager.bringWindowToTop(id);
114
113
  }
115
114
  };
@@ -143,7 +142,7 @@
143
142
  getSlot: id => windowManager.get(id).slot,
144
143
  close: (id) => { windowManager.remove(id); },
145
144
  pin: (id) => { windowManager.pinWindow(id); },
146
- clicked,
145
+ bringWindowToTop,
147
146
  move,
148
147
  };
149
148
  },
@@ -304,7 +304,7 @@ export function clipToTargetSize(windowPositionOptions, targetSize) {
304
304
  clippedPosition.height = windowPositionOptions.height;
305
305
  }
306
306
  clippedPosition.maxWidth = targetWidth;
307
- clippedPosition.maxHeight = targetHeight;
307
+ clippedPosition.maxHeight = targetHeight - 4; // 2px space plus 2px due to margin bottom
308
308
  if (windowPositionOptions.maxWidth !== undefined) {
309
309
  clippedPosition.maxWidth = Math.min(windowPositionOptions.maxWidth, targetWidth);
310
310
  }
@@ -1,4 +1,4 @@
1
- import { reactive, ref } from 'vue';
1
+ import { computed, reactive, ref } from 'vue';
2
2
  import { VcsEvent } from '@vcmap/core';
3
3
  import { v4 as uuidv4 } from 'uuid';
4
4
  import { parseEnumValue } from '@vcsuite/parsers';
@@ -137,6 +137,7 @@ export function isSlotPosition(windowPosition) {
137
137
  * @property {WindowSlot} initialSlot
138
138
  * @property {Object} props
139
139
  * @property {Object} provides
140
+ * @property {import("vue").ComputedGetter<number>} zIndex
140
141
  */
141
142
 
142
143
  /**
@@ -238,6 +239,11 @@ class WindowManager {
238
239
  * @type {Array<string>}
239
240
  */
240
241
  this.componentIds = [];
242
+ /**
243
+ * reactive ordered array of ids, defining the zIndex of a component
244
+ * @type {import("vue").Ref<Array<string>>}
245
+ */
246
+ this._zIndices = ref([]);
241
247
 
242
248
  /**
243
249
  * @type {Map<string, WindowComponent>}
@@ -277,8 +283,8 @@ class WindowManager {
277
283
  const windowComponent = this._windowComponents.get(id);
278
284
  if (windowComponent) {
279
285
  this._cachePosition(windowComponent);
280
- const index = this.componentIds.indexOf(id);
281
- this.componentIds.splice(index, 1);
286
+ this.componentIds.splice(this.componentIds.indexOf(id), 1);
287
+ this._zIndices.value.splice(this._zIndices.value.indexOf(id), 1);
282
288
  this._windowComponents.delete(id);
283
289
  this._handleSlotsChanged(windowComponent.slot.value);
284
290
  this.removed.raiseEvent(windowComponent);
@@ -453,6 +459,7 @@ class WindowManager {
453
459
 
454
460
  const position = reactive(windowPosition);
455
461
  const initialPosition = { ...windowPositionOptions };
462
+ const zIndex = computed(() => this._zIndices.value.indexOf(id));
456
463
  /**
457
464
  * @type {WindowComponent}
458
465
  */
@@ -487,6 +494,9 @@ class WindowManager {
487
494
  get provides() {
488
495
  return provides;
489
496
  },
497
+ get zIndex() {
498
+ return zIndex;
499
+ },
490
500
  };
491
501
  const cached = this._assignCachedPosition(windowComponent);
492
502
  if (!cached) {
@@ -494,6 +504,7 @@ class WindowManager {
494
504
  }
495
505
  this._windowComponents.set(id, windowComponent);
496
506
  this.componentIds.push(id);
507
+ this._zIndices.value.push(id);
497
508
  this._handleSlotsChanged(slot);
498
509
  this.added.raiseEvent(windowComponent);
499
510
  return windowComponent;
@@ -505,10 +516,10 @@ class WindowManager {
505
516
  */
506
517
  bringWindowToTop(id) {
507
518
  if (this.has(id)) {
508
- const index = this.componentIds.indexOf(id);
509
- if (index >= 0 && index !== this.componentIds.length - 1) {
510
- this.componentIds.push(id);
511
- this.componentIds.splice(index, 1);
519
+ const index = this._zIndices.value.indexOf(id);
520
+ if (index >= 0 && index !== this._zIndices.value.length - 1) {
521
+ this._zIndices.value.push(id);
522
+ this._zIndices.value.splice(index, 1);
512
523
  }
513
524
  }
514
525
  }
@@ -162,6 +162,6 @@
162
162
  }
163
163
 
164
164
  svg path:hover {
165
- fill: var(--v-base-lighten5) !important;
165
+ fill: var(--v-primary-lighten1) !important;
166
166
  }
167
167
  </style>
@@ -58,7 +58,7 @@
58
58
  import OrientationToolsButton from './orientationToolsButton.vue';
59
59
 
60
60
  /**
61
- * Creates a go-to viewpoint action from a startingViewpointName defined in a context
61
+ * Creates a go-to viewpoint action from a startingViewpointName defined in a module
62
62
  * @param {VcsUiApp} app
63
63
  * @returns {{action: import("vue").Reactive<{}>, destroy: function():void}}
64
64
  */
@@ -66,13 +66,13 @@
66
66
  const initialAction = { icon: undefined, title: undefined, active: undefined, callback: undefined };
67
67
  const action = reactive({ ...initialAction });
68
68
  /**
69
- * Gets the starting viewpoint of the last added context, where a startingViewpointName was defined
69
+ * Gets the starting viewpoint of the last added module, where a startingViewpointName was defined
70
70
  * and sets it on the home button action.
71
71
  */
72
72
  const updateStartingViewpoint = () => {
73
73
  let viewpoint = null;
74
- for (let idx = app.contexts.length - 1; idx >= 0; idx--) {
75
- const { startingViewpointName } = app.contexts[idx].config;
74
+ for (let idx = app.modules.length - 1; idx >= 0; idx--) {
75
+ const { startingViewpointName } = app.modules[idx].config;
76
76
  if (startingViewpointName && app.viewpoints.hasKey(startingViewpointName)) {
77
77
  viewpoint = app.viewpoints.getByKey(startingViewpointName);
78
78
  break;
@@ -95,8 +95,8 @@
95
95
  };
96
96
 
97
97
  const listener = [
98
- app.contextAdded.addEventListener(updateStartingViewpoint),
99
- app.contextRemoved.addEventListener(updateStartingViewpoint),
98
+ app.moduleAdded.addEventListener(updateStartingViewpoint),
99
+ app.moduleRemoved.addEventListener(updateStartingViewpoint),
100
100
  ];
101
101
 
102
102
  const destroy = () => { listener.forEach(cb => cb()); };
@@ -1,15 +1,19 @@
1
1
  <template>
2
- <div class="d-inline-flex">
3
- <OrientationToolsButton
4
- @click="input(-90)"
5
- icon="$vcsRotateLeft"
6
- tooltip="navigation.obliqueLeftTooltip"
7
- />
8
- <OrientationToolsButton
9
- @click="input(90)"
10
- icon="$vcsRotateRight"
11
- tooltip="navigation.obliqueRightTooltip"
12
- />
2
+ <div class="d-inline-flex rounded vcs-oblique-orientation">
3
+ <div class="d-inline-flex rounded inner">
4
+ <OrientationToolsButton
5
+ @click="input(-90)"
6
+ icon="$vcsRotateLeft"
7
+ tooltip="navigation.obliqueLeftTooltip"
8
+ elevation="0"
9
+ />
10
+ <OrientationToolsButton
11
+ @click="input(90)"
12
+ icon="$vcsRotateRight"
13
+ tooltip="navigation.obliqueRightTooltip"
14
+ elevation="0"
15
+ />
16
+ </div>
13
17
  </div>
14
18
  </template>
15
19
 
@@ -43,6 +47,25 @@
43
47
  };
44
48
  </script>
45
49
 
46
- <style scoped>
47
-
50
+ <style lang="scss" scoped>
51
+ .vcs-oblique-orientation {
52
+ box-shadow: rgba(0, 0, 0, 0.15) 0 2px 2px 0;
53
+ .inner{
54
+ box-shadow: rgba(0, 0, 0, 0.25) 0 -2px 2px 0 inset;
55
+ }
56
+ ::v-deep {
57
+ .btn-orientation-tools{
58
+ &:first-child{
59
+ box-shadow: rgba(0, 0, 0, 0.25) 2px 2px 1px -2px,
60
+ rgba(0, 0, 0, 0.02) -3px 2px 2px 0,
61
+ rgba(0, 0, 0, 0.12) 0 1px 1px 0 !important;
62
+ }
63
+ &:last-child{
64
+ box-shadow: rgba(0, 0, 0, 0.02) 1px 4px 1px -2px,
65
+ rgba(0, 0, 0, 0.02) 1px 2px 1px 0,
66
+ rgba(0, 0, 0, 0.1) 1px 1px 1px 0 !important;
67
+ }
68
+ }
69
+ }
70
+ }
48
71
  </style>
@@ -5,7 +5,6 @@
5
5
  >
6
6
  <template #activator="{ on, attrs }">
7
7
  <v-card
8
- elevation="0"
9
8
  class="h-8 w-8 d-flex align-center justify-center text-center btn-orientation-tools"
10
9
  v-bind="{ ...$attrs, ...attrs }"
11
10
  v-on="{ ...$listeners, ...on }"
@@ -52,8 +52,7 @@ export function getWindowComponentOptions() {
52
52
  */
53
53
  function getCameraIcon(color) {
54
54
  return {
55
- src: `data:image/svg+xml,%3C?xml version='1.0' encoding='UTF-8'?%3E%3Csvg id='cam' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 81.06 49.47'%3E%3Cdefs%3E%3ClinearGradient id='1' x1='40.53' y1='48.97' x2='40.53' y2='.25' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='0' stop-color='${encodeURIComponent(color)}'/%3E%3Cstop offset='.46' stop-color='${encodeURIComponent(color)}' stop-opacity='.60'/%3E%3Cstop offset='.65' stop-color='${encodeURIComponent(color)}' stop-opacity='.40'/%3E%3Cstop offset='.83' stop-color='${encodeURIComponent(color)}' stop-opacity='.20'/%3E%3Cstop offset='.89' stop-color='${encodeURIComponent(color)}' stop-opacity='.15'/%3E%3Cstop offset='1' stop-color='transparent' stop-opacity='0'/%3E%3C/linearGradient%3E%3ClinearGradient id='2' x1='40.53' y1='49.37' x2='40.53' y2='0' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.24' stop-color='${encodeURIComponent(color)}'/%3E%3Cstop offset='.38' stop-color='${encodeURIComponent(color)}' stop-opacity='.93'/%3E%3Cstop offset='.57' stop-color='${encodeURIComponent(color)}' stop-opacity='.70'/%3E%3Cstop offset='.78' stop-color='${encodeURIComponent(color)}' stop-opacity='.38'/%3E%3Cstop offset='1' stop-color='transparent' stop-opacity='0'/%3E%3C/linearGradient%3E%3C/defs%3E%3Cpolygon points='40.53 48.97 80.53 .25 .53 .25 40.53 48.97' fill='url(%231)' stroke='url(%232)' stroke-miterlimit='10' stroke-width='.5px'/%3E%3Ccircle cx='40.53' cy='42.97' r='6' fill='${encodeURIComponent(color)}' stroke='%23fff' stroke-miterlimit='10'/%3E%3C/svg%3E`,
56
- scale: 0.5,
55
+ src: `data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Asvg%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22121.58616%22%20height%3D%2274.204994%22%20viewBox%3D%220%200%2032.169671%2019.633405%22%20version%3D%221.1%22%20id%3D%22svg216%22%3E%3Cdefs%20id%3D%22defs213%22%3E%3ClinearGradient%20id%3D%221-0%22%20x1%3D%2240.529999%22%20y1%3D%2248.970001%22%20x2%3D%2240.529999%22%20y2%3D%220.25%22%20gradientUnits%3D%22userSpaceOnUse%22%3E%3Cstop%20offset%3D%220%22%20stop-color%3D%22${encodeURIComponent(color)}%22%20id%3D%22stop399%22%2F%3E%3Cstop%20offset%3D%22.46%22%20stop-color%3D%22${encodeURIComponent(color)}%22%20stop-opacity%3D%22.60%22%20id%3D%22stop401%22%2F%3E%3Cstop%20offset%3D%22.65%22%20stop-color%3D%22${encodeURIComponent(color)}%22%20stop-opacity%3D%22.40%22%20id%3D%22stop403%22%2F%3E%3Cstop%20offset%3D%22.83%22%20stop-color%3D%22${encodeURIComponent(color)}%22%20stop-opacity%3D%22.20%22%20id%3D%22stop405%22%2F%3E%3Cstop%20offset%3D%22.89%22%20stop-color%3D%22${encodeURIComponent(color)}%22%20stop-opacity%3D%22.15%22%20id%3D%22stop407%22%2F%3E%3Cstop%20offset%3D%221%22%20stop-color%3D%22transparent%22%20stop-opacity%3D%220%22%20id%3D%22stop409%22%2F%3E%3C%2FlinearGradient%3E%3ClinearGradient%20id%3D%222-9%22%20x1%3D%2240.529999%22%20y1%3D%2249.369999%22%20x2%3D%2240.529999%22%20y2%3D%220%22%20gradientUnits%3D%22userSpaceOnUse%22%3E%3Cstop%20offset%3D%22.24%22%20stop-color%3D%22${encodeURIComponent(color)}%22%20id%3D%22stop412%22%2F%3E%3Cstop%20offset%3D%22.38%22%20stop-color%3D%22${encodeURIComponent(color)}%22%20stop-opacity%3D%22.93%22%20id%3D%22stop414%22%2F%3E%3Cstop%20offset%3D%22.57%22%20stop-color%3D%22${encodeURIComponent(color)}%22%20stop-opacity%3D%22.70%22%20id%3D%22stop416%22%2F%3E%3Cstop%20offset%3D%22.78%22%20stop-color%3D%22${encodeURIComponent(color)}%22%20stop-opacity%3D%22.38%22%20id%3D%22stop418%22%2F%3E%3Cstop%20offset%3D%221%22%20stop-color%3D%22transparent%22%20stop-opacity%3D%220%22%20id%3D%22stop420%22%2F%3E%3C%2FlinearGradient%3E%3C%2Fdefs%3E%3Cg%20id%3D%22layer1%22%20transform%3D%22translate(5.3616118%2C3.2722342)%22%3E%3Cpolygon%20points%3D%220.53%2C0.25%2040.53%2C48.97%2080.53%2C0.25%20%22%20fill%3D%22url(%231)%22%20stroke%3D%22url(%232)%22%20stroke-miterlimit%3D%2210%22%20stroke-width%3D%220.5px%22%20id%3D%22polygon425%22%20style%3D%22fill%3Aurl(%231-0)%3Bstroke%3Aurl(%232-9)%22%20transform%3D%22matrix(0.396875%2C0%2C0%2C0.396875%2C-5.3621201%2C-3.2722342)%22%2F%3E%3Ccircle%20cx%3D%2210.723224%22%20cy%3D%2213.781484%22%20r%3D%222.3812499%22%20fill%3D%22${encodeURIComponent(color)}%22%20stroke%3D%22%23ffffff%22%20stroke-miterlimit%3D%2210%22%20id%3D%22circle427%22%20style%3D%22stroke-width%3A0.396874%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E`,
57
56
  color,
58
57
  };
59
58
  }
@@ -304,7 +303,7 @@ class OverviewMap {
304
303
  this._setupMapInteraction();
305
304
  }
306
305
  await this._map.activate();
307
- this.map.setTarget('overview-map-container');
306
+ this._map.setTarget('overview-map-container');
308
307
  this._map.target?.firstChild?.classList?.add('overviewMapElement');
309
308
  if (!this._active) {
310
309
  this._mapActivatedListener = this._app.maps.mapActivated.addEventListener(() => {
@@ -540,8 +539,9 @@ class OverviewMap {
540
539
  return;
541
540
  }
542
541
  let cameraFeature = this._cameraIconLayer.getFeatureById('cameraFeature');
542
+ const coords = Projection.wgs84ToMercator(position);
543
543
  if (!cameraFeature) {
544
- const cameraGeometry = new Point([position[0], position[1]]);
544
+ const cameraGeometry = new Point(coords);
545
545
  cameraFeature = new Feature({
546
546
  geometry: cameraGeometry,
547
547
  });
@@ -549,7 +549,7 @@ class OverviewMap {
549
549
  cameraFeature.setStyle(this.cameraIconStyle.style);
550
550
  this._cameraIconLayer.addFeatures([cameraFeature]);
551
551
  }
552
- cameraFeature.getGeometry().setCoordinates(Projection.wgs84ToMercator(position));
552
+ cameraFeature.getGeometry().setCoordinates(coords);
553
553
 
554
554
  const rotationDegrees = viewpoint.heading;
555
555
  const rotationRadians = CesiumMath.toRadians(rotationDegrees);
@@ -1,15 +1,19 @@
1
1
  <template>
2
- <div>
3
- <OrientationToolsButton
4
- @click="$emit('zoom-in')"
5
- icon="$vcsPlus"
6
- tooltip="navigation.zoomInTooltip"
7
- />
8
- <OrientationToolsButton
9
- @click="$emit('zoom-out')"
10
- icon="$vcsMinus"
11
- tooltip="navigation.zoomOutTooltip"
12
- />
2
+ <div class="rounded vcs-navigation-zoom">
3
+ <div class="rounded inner">
4
+ <OrientationToolsButton
5
+ @click="$emit('zoom-in')"
6
+ icon="$vcsPlus"
7
+ tooltip="navigation.zoomInTooltip"
8
+ elevation="0"
9
+ />
10
+ <OrientationToolsButton
11
+ @click="$emit('zoom-out')"
12
+ icon="$vcsMinus"
13
+ tooltip="navigation.zoomOutTooltip"
14
+ elevation="0"
15
+ />
16
+ </div>
13
17
  </div>
14
18
  </template>
15
19
 
@@ -25,3 +29,25 @@
25
29
  components: { OrientationToolsButton },
26
30
  };
27
31
  </script>
32
+ <style lang="scss" scoped>
33
+ .vcs-navigation-zoom {
34
+ box-shadow: rgba(0, 0, 0, 0.1) 0 2px 2px 0;
35
+ .inner{
36
+ box-shadow: rgba(0, 0, 0, 0.25) 0 0 10px 0 inset;
37
+ }
38
+ ::v-deep {
39
+ .btn-orientation-tools{
40
+ &:first-child{
41
+ box-shadow: rgba(0, 0, 0, 0.25) -2px 2px 1px -2px,
42
+ rgba(0, 0, 0, 0.08) 1px 0 0 0,
43
+ rgba(0, 0, 0, 0.05) -1px 1px 1px 1px !important;
44
+ }
45
+ &:last-child{
46
+ box-shadow: rgba(0, 0, 0, 0.25) -2px 3px 1px -2px,
47
+ rgba(0, 0, 0, 0.08) 1px 4px 2px 0,
48
+ rgba(0, 0, 0, 0.05) -1px 1px 1px 1px !important;
49
+ }
50
+ }
51
+ }
52
+ }
53
+ </style>
@@ -115,12 +115,32 @@ export async function loadPlugin(name, config) {
115
115
  return null;
116
116
  }
117
117
 
118
+ /**
119
+ * @param {string} base
120
+ * @param {string} pluginBase
121
+ * @returns {string}
122
+ */
123
+ export function getPluginEntry(base, pluginBase) {
124
+ const baseUrl = new URL(base);
125
+ const pluginBaseUrl = new URL(pluginBase);
126
+ if (baseUrl.origin !== pluginBaseUrl.origin) {
127
+ return pluginBase;
128
+ }
129
+ const baseSubs = baseUrl.pathname.split('/');
130
+ const pluginSubs = pluginBaseUrl.pathname.split('/');
131
+ return pluginSubs
132
+ .filter((sub, idx) => sub !== baseSubs[idx])
133
+ .join('/');
134
+ }
135
+
118
136
  /**
119
137
  * @param {VcsPlugin} plugin
120
138
  * @returns {Object}
121
139
  */
122
140
  export function serializePlugin(plugin) {
123
141
  const serializedPlugin = plugin.toJSON ? plugin.toJSON() : {};
142
+ serializedPlugin.name = plugin.name;
143
+ serializedPlugin.entry = getPluginEntry(window.location.href, plugin[pluginBaseUrlSymbol]);
124
144
  serializedPlugin[pluginFactorySymbol] = plugin[pluginFactorySymbol];
125
145
  serializedPlugin[pluginBaseUrlSymbol] = plugin[pluginBaseUrlSymbol];
126
146
  return serializedPlugin;
@@ -242,9 +242,6 @@ class Search extends IndexedCollection {
242
242
  });
243
243
  if (this._currentResults.value.length > 0) {
244
244
  await this._resultLayer.activate();
245
- const extent = this._resultLayer.getZoomToExtent();
246
- const viewpoint = Viewpoint.createViewpointFromExtent(extent);
247
- await this._app.maps.activeMap.gotoViewpoint(viewpoint);
248
245
  this.resultsChanged.raiseEvent(this._currentResults.value.slice(0));
249
246
  }
250
247
  }
@@ -286,6 +283,18 @@ class Search extends IndexedCollection {
286
283
  [...this._array].forEach(impl => impl.abort?.());
287
284
  }
288
285
 
286
+ /**
287
+ * Zooms to the extent of all available result features
288
+ * @returns {Promise<void>}
289
+ */
290
+ async zoomToAll() {
291
+ if (this._resultLayer.getFeatures().length > 0) {
292
+ const extent = this._resultLayer.getZoomToExtent();
293
+ const viewpoint = Viewpoint.createViewpointFromExtent(extent);
294
+ await this._app.maps.activeMap.gotoViewpoint(viewpoint);
295
+ }
296
+ }
297
+
289
298
  /**
290
299
  * Clears the results and aborts running request
291
300
  */
@@ -20,6 +20,14 @@
20
20
  </span>
21
21
  <v-divider class="mt-1" v-if="!!results.length" />
22
22
  <ResultsComponent :query="query" :results="results" />
23
+ <v-divider v-if="!!results.length" />
24
+ <VcsButton
25
+ v-if="!!results.length"
26
+ class="d-flex pt-1 px-1 justify-end"
27
+ @click="zoomToAll"
28
+ >
29
+ {{ $t('search.zoomToAll') }}
30
+ </VcsButton>
23
31
  </v-sheet>
24
32
  </template>
25
33
 
@@ -33,9 +41,11 @@
33
41
  import { VSheet, VDivider, VIcon } from 'vuetify/lib';
34
42
  import VcsTextField from '../components/form-inputs-controls/VcsTextField.vue';
35
43
  import ResultsComponent from './resultsComponent.vue';
44
+ import VcsButton from '../components/buttons/VcsButton.vue';
36
45
 
37
46
  export default {
38
47
  components: {
48
+ VcsButton,
39
49
  ResultsComponent,
40
50
  VcsTextField,
41
51
  VSheet,
@@ -72,6 +82,10 @@
72
82
  searching.value = false;
73
83
  };
74
84
 
85
+ const zoomToAll = () => {
86
+ app.search.zoomToAll();
87
+ };
88
+
75
89
  onUnmounted(() => {
76
90
  clear();
77
91
  });
@@ -83,6 +97,7 @@
83
97
  reset,
84
98
  clear,
85
99
  search,
100
+ zoomToAll,
86
101
  };
87
102
  },
88
103
  };
package/src/state.js CHANGED
@@ -39,7 +39,7 @@ import { Viewpoint } from '@vcmap/core';
39
39
  * @typedef {Object} AppState
40
40
  * @property {import("@vcmap/core").ViewpointOptions} [activeViewpoint]
41
41
  * @property {string} [activeMap]
42
- * @property {Array<string>} contextIds
42
+ * @property {Array<string>} moduleIds
43
43
  * @property {Array<LayerState>} layers
44
44
  * @property {Array<PluginState>} plugins
45
45
  * @property {string} [activeObliqueCollection]
@@ -48,7 +48,7 @@ import { Viewpoint } from '@vcmap/core';
48
48
  /**
49
49
  * The URL state of the app is an array. To null parameters, pass in 0 instead.
50
50
  * The first entry is the viewpoint state, the second the active map name
51
- * The third is an array of contexts to apply the state to
51
+ * The third is an array of modules to apply the state to
52
52
  * the fourth is an array of layer states
53
53
  * the fifth is an array of plugin states
54
54
  * the sixth is the currently active oblique collection or 0 if not applicable
@@ -65,7 +65,7 @@ const MAX_URL_LENGTH = 2048;
65
65
  */
66
66
  export function createEmptyState() {
67
67
  return {
68
- contextIds: [],
68
+ moduleIds: [],
69
69
  layers: [],
70
70
  plugins: [],
71
71
  };
@@ -143,7 +143,7 @@ function parseUrlAppState(urlState) {
143
143
  state.activeMap = urlState[1];
144
144
  }
145
145
  if (Array.isArray(urlState[2])) {
146
- state.contextIds = urlState[2].slice();
146
+ state.moduleIds = urlState[2].slice();
147
147
  }
148
148
  if (Array.isArray(urlState[3])) {
149
149
  urlState[3].forEach((urlLayerState) => {
@@ -190,7 +190,7 @@ function writeUrlAppState(state, maxLength) {
190
190
  urlState[1] = state.activeMap;
191
191
  }
192
192
 
193
- urlState[2] = state.contextIds.slice();
193
+ urlState[2] = state.moduleIds.slice();
194
194
  urlState[3] = [];
195
195
  urlState[4] = [];
196
196
 
@@ -247,7 +247,7 @@ export function setStateToUrl(state, url) {
247
247
  activeObliqueCollection: [String, undefined],
248
248
  layers: Array,
249
249
  plugins: Array,
250
- contextIds: [String],
250
+ moduleIds: [String],
251
251
  });
252
252
  check(url, URL);
253
253
 
package/src/uiConfig.js CHANGED
@@ -23,12 +23,12 @@ import { ref } from 'vue';
23
23
  */
24
24
  class UiConfig extends Collection {
25
25
  /**
26
- * @param {function():string} getDynamicContextId
26
+ * @param {function():string} getDynamicModuleId
27
27
  */
28
- constructor(getDynamicContextId) {
28
+ constructor(getDynamicModuleId) {
29
29
  super();
30
30
 
31
- makeOverrideCollection(this, getDynamicContextId);
31
+ makeOverrideCollection(this, getDynamicModuleId);
32
32
  /**
33
33
  * This object just acts as a go between for reactivity until we have vue3
34
34
  * @todo vue3 cleanup