@vcmap/ui 6.2.4 → 6.3.0-rc.2

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 (60) hide show
  1. package/config/base.config.json +6 -3
  2. package/config/cluster.config.json +2 -1
  3. package/config/dev.config.json +12 -0
  4. package/config/geofence.config.json +19 -0
  5. package/config/pano.config.json +313 -7
  6. package/config/projects.config.json +2 -1
  7. package/dist/assets/cesium.js +1 -1
  8. package/dist/assets/{core-b61fb7c0.js → core-c23fc5f1.js} +10212 -9921
  9. package/dist/assets/core-workers/panoramaImageWorker.js +1 -1
  10. package/dist/assets/core.js +1 -1
  11. package/dist/assets/ol.js +1 -1
  12. package/dist/assets/ui-e61976d4.css +1 -0
  13. package/dist/assets/{ui-f33a5ee2.js → ui-e61976d4.js} +7045 -6910
  14. package/dist/assets/ui.js +1 -1
  15. package/dist/assets/vue.js +1 -1
  16. package/dist/assets/{vuetify-2fc014c4.js → vuetify-de6f6eb0.js} +1 -1
  17. package/dist/assets/vuetify.js +1 -1
  18. package/package.json +2 -2
  19. package/plugins/@vcmap-show-case/panel-tester/src/TextPanelExample.vue +1 -1
  20. package/plugins/@vcmap-show-case/panorama-inspector/src/PanoramaDebugTools.vue +28 -3
  21. package/plugins/@vcmap-show-case/panorama-inspector/src/api.js +8 -23
  22. package/plugins/@vcmap-show-case/panorama-inspector/src/index.js +1 -1
  23. package/plugins/package.json +5 -3
  24. package/src/application/VcsApp.vue +15 -1
  25. package/src/application/VcsApp.vue.d.ts +32 -0
  26. package/src/application/VcsAttributions.vue +9 -0
  27. package/src/application/VcsAttributionsFooter.vue.d.ts +1 -0
  28. package/src/application/VcsContainer.vue.d.ts +31 -0
  29. package/src/application/VcsMobileMenuList.vue +16 -1
  30. package/src/application/VcsObliqueFooter.vue +19 -6
  31. package/src/application/VcsObliqueFooter.vue.d.ts +1 -0
  32. package/src/application/VcsPanoramaFooter.vue +72 -0
  33. package/src/application/VcsPanoramaFooter.vue.d.ts +2 -0
  34. package/src/application/VcsTextPageFooter.vue +4 -0
  35. package/src/application/attributionsHelper.d.ts +7 -1
  36. package/src/application/attributionsHelper.js +7 -2
  37. package/src/application/uiConfigHelper.d.ts +6 -0
  38. package/src/application/uiConfigHelper.js +28 -0
  39. package/src/components/vector-properties/VcsFeatureEditingWindow.vue +15 -5
  40. package/src/components/vector-properties/VcsFeatureEditingWindow.vue.d.ts +123 -1
  41. package/src/contentTree/layerContentTreeItem.d.ts +4 -0
  42. package/src/contentTree/layerContentTreeItem.js +26 -20
  43. package/src/contentTree/layerGroupContentTreeItem.d.ts +1 -0
  44. package/src/contentTree/layerGroupContentTreeItem.js +32 -26
  45. package/src/contentTree/wmsGroupContentTreeItem.d.ts +1 -0
  46. package/src/contentTree/wmsGroupContentTreeItem.js +26 -19
  47. package/src/featureInfo/balloonHelper.js +8 -2
  48. package/src/manager/panel/PanelComponent.vue +48 -27
  49. package/src/manager/panel/PanelComponent.vue.d.ts +0 -1
  50. package/src/manager/panel/PanelManagerComponent.vue +42 -19
  51. package/src/manager/panel/PanelManagerComponent.vue.d.ts +4 -3
  52. package/src/search/search.js +2 -0
  53. package/src/uiConfig.d.ts +46 -0
  54. package/src/uiConfig.js +3 -0
  55. package/dist/assets/ui-f33a5ee2.css +0 -1
  56. /package/dist/assets/{cesium-bc979301.js → cesium-8369e63b.js} +0 -0
  57. /package/dist/assets/core-workers/{panoramaImageWorker.js-2cf50d2d.js → panoramaImageWorker.js-f9c706f1.js} +0 -0
  58. /package/dist/assets/{ol-28f9c83c.js → ol-9f59d99f.js} +0 -0
  59. /package/dist/assets/{vue-004523e0.js → vue-f6136dc6.js} +0 -0
  60. /package/dist/assets/{vuetify-2fc014c4.css → vuetify-de6f6eb0.css} +0 -0
package/dist/assets/ui.js CHANGED
@@ -1 +1 @@
1
- export * from "./ui-f33a5ee2.js";
1
+ export * from "./ui-e61976d4.js";
@@ -1 +1 @@
1
- export * from "./vue-004523e0.js";
1
+ export * from "./vue-f6136dc6.js";
@@ -10,7 +10,7 @@ function loadCss(href) {
10
10
  elem.onerror = reject;
11
11
  document.head.appendChild(elem);
12
12
  });
13
- } await loadCss('./assets/vuetify-2fc014c4.css');import { watch as Q, onScopeDispose as Ze, effectScope as Zl, shallowRef as K, Fragment as ie, reactive as it, computed as b, watchEffect as Fe, toRefs as Yt, capitalize as Nn, isVNode as Rc, Comment as Nc, unref as ot, warn as ja, getCurrentInstance as Hc, ref as j, provide as De, inject as ye, defineComponent as zc, camelize as Ir, h as Gt, toRaw as Be, createVNode as r, mergeProps as O, onBeforeUnmount as Qe, readonly as Ql, onDeactivated as _r, onActivated as Wc, onMounted as Ye, nextTick as we, TransitionGroup as Jl, Transition as jt, isRef as Tn, toRef as $, onBeforeMount as ra, withDirectives as $e, resolveDirective as gt, vShow as Ct, onUpdated as jc, Text as Uc, resolveDynamicComponent as Yc, markRaw as Gc, Teleport as Kc, cloneVNode as qc, createTextVNode as Tt, onUnmounted as Tr, onBeforeUpdate as Xc, withModifiers as Tl, toDisplayString as Zc, vModelText as Qc, resolveComponent as Jc, render as Ar } from "./vue-004523e0.js";
13
+ } await loadCss('./assets/vuetify-de6f6eb0.css');import { watch as Q, onScopeDispose as Ze, effectScope as Zl, shallowRef as K, Fragment as ie, reactive as it, computed as b, watchEffect as Fe, toRefs as Yt, capitalize as Nn, isVNode as Rc, Comment as Nc, unref as ot, warn as ja, getCurrentInstance as Hc, ref as j, provide as De, inject as ye, defineComponent as zc, camelize as Ir, h as Gt, toRaw as Be, createVNode as r, mergeProps as O, onBeforeUnmount as Qe, readonly as Ql, onDeactivated as _r, onActivated as Wc, onMounted as Ye, nextTick as we, TransitionGroup as Jl, Transition as jt, isRef as Tn, toRef as $, onBeforeMount as ra, withDirectives as $e, resolveDirective as gt, vShow as Ct, onUpdated as jc, Text as Uc, resolveDynamicComponent as Yc, markRaw as Gc, Teleport as Kc, cloneVNode as qc, createTextVNode as Tt, onUnmounted as Tr, onBeforeUpdate as Xc, withModifiers as Tl, toDisplayString as Zc, vModelText as Qc, resolveComponent as Jc, render as Ar } from "./vue-f6136dc6.js";
14
14
  function rt(e, n) {
15
15
  let t;
16
16
  function a() {
@@ -1 +1 @@
1
- export * from "./vuetify-2fc014c4.js";
1
+ export * from "./vuetify-de6f6eb0.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vcmap/ui",
3
- "version": "6.2.4",
3
+ "version": "6.3.0-rc.2",
4
4
  "author": "Virtual City Systems",
5
5
  "license": "MIT",
6
6
  "scripts": {
@@ -58,7 +58,7 @@
58
58
  },
59
59
  "peerDependencies": {
60
60
  "@vcmap-cesium/engine": "^11.0.3",
61
- "@vcmap/core": "^6.2.3",
61
+ "@vcmap/core": "^6.3.0-rc.1",
62
62
  "ol": "^10.4.0",
63
63
  "vue": "~3.4.38",
64
64
  "vuetify": "~3.7.14"
@@ -3,7 +3,7 @@
3
3
  <h1>{{ $attrs['panel-state'].location }}</h1>
4
4
  <p>{{ $attrs['panel-state'].id }}</p>
5
5
  <div class="d-flex flex-column overflow-hidden w-full h-full pa-1">
6
- <p>
6
+ <p v-for="a in [...Array(5).keys()]" :key="a">
7
7
  Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy
8
8
  eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam
9
9
  voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet
@@ -17,7 +17,7 @@
17
17
  } from '@vcmap/core';
18
18
  import {
19
19
  createMapMarkerAction,
20
- createOsmGlobeAction,
20
+ createGlobeToggleAction,
21
21
  setupClickedPrimitive,
22
22
  } from './api.js';
23
23
  import { name } from '../package.json';
@@ -51,7 +51,7 @@
51
51
  }
52
52
  });
53
53
 
54
- const { action, destroy } = createOsmGlobeAction(app);
54
+ const action = createGlobeToggleAction(app);
55
55
  const { action: hideMarker, destroy: destroyMarker } =
56
56
  createMapMarkerAction(app);
57
57
 
@@ -72,6 +72,16 @@
72
72
  map.panoramaView.tilePrimitiveCollection.overlayOpacity = newOverlayOpacity;
73
73
  });
74
74
 
75
+ const contrast = ref(map.panoramaView.tilePrimitiveCollection.contrast);
76
+ watch(contrast, (newContrast) => {
77
+ map.panoramaView.tilePrimitiveCollection.contrast = newContrast;
78
+ });
79
+
80
+ const brightness = ref(map.panoramaView.tilePrimitiveCollection.brightness);
81
+ watch(brightness, (newBrightness) => {
82
+ map.panoramaView.tilePrimitiveCollection.brightness = newBrightness;
83
+ });
84
+
75
85
  const overlayNaNColor = shallowRef(
76
86
  getStringColor(
77
87
  cesiumColorToColor(
@@ -132,7 +142,6 @@
132
142
 
133
143
  onUnmounted(() => {
134
144
  clickedPrimitive.destroy();
135
- destroy();
136
145
  destroyMarker();
137
146
  map.panoramaView.tilePrimitiveCollection.opacity = 1;
138
147
  });
@@ -163,6 +172,22 @@
163
172
  <VcsCheckbox label="Show Depth" v-model="showDepth"></VcsCheckbox>
164
173
  </v-col>
165
174
  </v-row>
175
+ <v-row no-gutters>
176
+ <v-col cols="4">
177
+ <vcs-label>Brightness</vcs-label>
178
+ </v-col>
179
+ <v-col>
180
+ <vcs-slider v-model="brightness" :min="-1" :max="1" :step="0.001" />
181
+ </v-col>
182
+ </v-row>
183
+ <v-row no-gutters>
184
+ <v-col cols="4">
185
+ <vcs-label>Contrast</vcs-label>
186
+ </v-col>
187
+ <v-col>
188
+ <vcs-slider v-model="contrast" :min="0" :max="20" :step="0.01" />
189
+ </v-col>
190
+ </v-row>
166
191
  <template v-if="showDepth || showIntensity">
167
192
  <v-row no-gutters>
168
193
  <v-col cols="4">
@@ -7,9 +7,6 @@ import {
7
7
  SphereGeometry,
8
8
  Color,
9
9
  Cartesian3,
10
- Globe,
11
- ImageryLayer as CesiumImageryLayer,
12
- OpenStreetMapImageryProvider,
13
10
  } from '@vcmap-cesium/engine';
14
11
  import {
15
12
  mercatorToCartesian,
@@ -80,42 +77,30 @@ export function setupClickedPrimitive(map, clickedInteraction) {
80
77
 
81
78
  /**
82
79
  * @param {import("@vcmap/core").VcsApp} app
83
- * @returns {{ action: import("@vcmap/ui").Action, destroy: () => void }}
80
+ * @returns {import("@vcmap/ui").Action}
84
81
  */
85
- export function createOsmGlobeAction(app) {
82
+ export function createGlobeToggleAction(app) {
86
83
  /** @type {import("@vcmap/core").PanoramaMap} */
87
84
  const map = app.maps.getByType(PanoramaMap.className)[0];
85
+ const cachedLayerTypes = map.layerTypes.slice();
88
86
 
89
87
  const action = reactive({
90
- name: 'OSM Globe',
88
+ name: 'globeToggle',
91
89
  icon: 'mdi-earth',
92
- title: 'Open Street Map Globe',
90
+ title: 'Toggle additional layers',
93
91
  active: false,
94
92
  callback() {
95
93
  if (action.active) {
96
- map.getCesiumWidget().scene.globe = undefined;
94
+ map.layerTypes = cachedLayerTypes;
97
95
  action.active = false;
98
96
  } else {
99
- const { scene } = map.getCesiumWidget();
100
- scene.globe = new Globe();
101
- scene.imageryLayers.add(
102
- new CesiumImageryLayer(
103
- new OpenStreetMapImageryProvider({ maximumLevel: 18 }),
104
- ),
105
- );
97
+ map.layerTypes = [];
106
98
  action.active = true;
107
99
  }
108
100
  },
109
101
  });
110
102
 
111
- return {
112
- action,
113
- destroy: () => {
114
- if (map.initialized) {
115
- map.getCesiumWidget().scene.globe = undefined;
116
- }
117
- },
118
- };
103
+ return action;
119
104
  }
120
105
 
121
106
  /**
@@ -27,7 +27,7 @@ export default function panoramaInspector() {
27
27
  {
28
28
  id: 'panorama-inspector',
29
29
  state: {
30
- headerTitle: 'panoramaInspector.title',
30
+ headerTitle: 'Panorama Inspector',
31
31
  },
32
32
  component: PanoramaInspector,
33
33
  slot: WindowSlot.DYNAMIC_RIGHT,
@@ -9,9 +9,9 @@
9
9
  "@vcmap/swipe-tool": "^4.0.0",
10
10
  "@vcmap/export": "^2.0.0",
11
11
  "@vcmap/viewshed": "^3.0.0",
12
- "@vcmap/measurement": "^4.0.0",
12
+ "@vcmap/measurement": "^5.0.0",
13
13
  "@vcmap/multi-view": "^3.0.0",
14
- "@vcmap/draw": "^4.0.0",
14
+ "@vcmap/draw": "^5.0.0",
15
15
  "@vcmap/shadow": "^3.0.0",
16
16
  "@vcmap/search-wfs": "^2.0.0",
17
17
  "@vcmap/search-esri": "^2.0.0",
@@ -30,7 +30,9 @@
30
30
  "@vcmap/sensorthings": "^1.0.0",
31
31
  "@vcmap/cesium-inspector": "^2.0.0",
32
32
  "@vcmap/event-control": "^1.0.1",
33
- "@vcmap/dynamic-layer": "^1.0.0"
33
+ "@vcmap/dynamic-layer": "^1.0.0",
34
+ "@vcmap/geofence": "^1.0.2",
35
+ "@vcmap/panorama": "^1.0.0"
34
36
  },
35
37
  "optionalDependencies": {
36
38
  "@vcmap/planning": "^7.0.0"
@@ -17,6 +17,7 @@
17
17
  >
18
18
  <VcsPositionDisplay />
19
19
  <VcsObliqueFooter />
20
+ <vcs-panorama-footer />
20
21
  <VcsTextPageFooter
21
22
  v-if="imprint"
22
23
  :text-page="imprint"
@@ -27,6 +28,12 @@
27
28
  :text-page="dataProtection"
28
29
  :window-id="'dataProtectionWindow'"
29
30
  />
31
+ <VcsTextPageFooter
32
+ v-for="(info, idx) in footerInformation"
33
+ :key="idx"
34
+ :text-page="info"
35
+ :window-id="'footerInfoWindow_' + idx"
36
+ />
30
37
  <v-spacer />
31
38
  <VcsAttributionsFooter
32
39
  :entries="attributionEntries"
@@ -88,7 +95,12 @@
88
95
  import VcsAttributions from './VcsAttributions.vue';
89
96
  import { getAttributions } from './attributionsHelper.js';
90
97
  import VcsPositionDisplay from './VcsPositionDisplay.vue';
91
- import { getDataProtection, getImprint } from './uiConfigHelper.js';
98
+ import {
99
+ getDataProtection,
100
+ getImprint,
101
+ getFooterInformation,
102
+ } from './uiConfigHelper.js';
103
+ import VcsPanoramaFooter from './VcsPanoramaFooter.vue';
92
104
 
93
105
  /**
94
106
  * This helper checks the uiConfig and depending on the value will setup/teardown the providedSetupFunction
@@ -775,6 +787,7 @@
775
787
  */
776
788
  export default {
777
789
  components: {
790
+ VcsPanoramaFooter,
778
791
  VcsContainer,
779
792
  VcsPositionDisplay,
780
793
  VcsAttributionsFooter,
@@ -885,6 +898,7 @@
885
898
  footerHeight,
886
899
  imprint: getImprint(app.uiConfig.config),
887
900
  dataProtection: getDataProtection(app.uiConfig.config),
901
+ footerInformation: getFooterInformation(app.uiConfig.config),
888
902
  showSplashScreen,
889
903
  splashScreen,
890
904
  attributionEntries,
@@ -184,6 +184,29 @@ declare const _default: import("vue").DefineComponent<{
184
184
  } | undefined;
185
185
  readonly content?: string | undefined;
186
186
  } | undefined;
187
+ /**
188
+ * - optionnal, additional information to show in the footer as links or dialogs
189
+ */
190
+ readonly footerInformation?: readonly {
191
+ readonly title?: string | undefined;
192
+ readonly url?: string | {
193
+ readonly hash: string;
194
+ readonly host: string;
195
+ readonly hostname: string;
196
+ readonly href: string;
197
+ readonly toString: () => string;
198
+ readonly origin: string;
199
+ readonly password: string;
200
+ readonly pathname: string;
201
+ readonly port: string;
202
+ readonly protocol: string;
203
+ readonly search: string;
204
+ readonly searchParams: ReadonlyMap<string, string | null>;
205
+ readonly username: string;
206
+ readonly toJSON: () => string;
207
+ } | undefined;
208
+ readonly content?: string | undefined;
209
+ }[] | undefined;
187
210
  /**
188
211
  * - an option splashScreen, will show a splash Screen on Map Load.
189
212
  */
@@ -297,6 +320,10 @@ declare const _default: import("vue").DefineComponent<{
297
320
  * - can be used to hide the integrated Search bar
298
321
  */
299
322
  readonly hideSearch?: boolean | undefined;
323
+ /**
324
+ * - can be used to set the pitch angle of the viewpoint of features zoomed to from Search, in degrees. Defaults to -35 degrees.
325
+ */
326
+ readonly searchViewpointPitch?: number | undefined;
300
327
  /**
301
328
  * - can be used to hide the sharee button
302
329
  */
@@ -345,6 +372,10 @@ declare const _default: import("vue").DefineComponent<{
345
372
  * - can be used to hide the oblique name in the footer
346
373
  */
347
374
  readonly hideObliqueFooter?: boolean | undefined;
375
+ /**
376
+ * - can be used to hide the panorama name in the footer
377
+ */
378
+ readonly hidePanoramaFooter?: boolean | undefined;
348
379
  /**
349
380
  * - can be used to activate the overviewMap on startup
350
381
  */
@@ -411,6 +442,7 @@ declare const _default: import("vue").DefineComponent<{
411
442
  footerHeight: import("vue").ComputedRef<number>;
412
443
  imprint: import("vue").ComputedRef<import("../uiConfig.js", { with: { "resolution-mode": "import" } }).TextPageType | undefined>;
413
444
  dataProtection: import("vue").ComputedRef<import("../uiConfig.js", { with: { "resolution-mode": "import" } }).TextPageType | undefined>;
445
+ footerInformation: import("vue").ComputedRef<import("../uiConfig.js", { with: { "resolution-mode": "import" } }).TextPageType[] | undefined>;
414
446
  showSplashScreen: import("vue").Ref<boolean>;
415
447
  splashScreen: import("vue").ShallowRef<{
416
448
  title: string;
@@ -11,7 +11,11 @@
11
11
  v-for="attribution in attributions"
12
12
  :key="attribution.provider"
13
13
  :title="`${$st(attribution.provider)} ${attribution.year}`"
14
+ class="d-inline-flex align-end"
14
15
  >
16
+ <v-icon v-if="attribution.icon" class="mr-2 attribution-icon">
17
+ {{ attribution.icon }}
18
+ </v-icon>
15
19
  <a :href="attribution.url ? attribution.url : null" target="_blank">
16
20
  {{ $st(attribution.provider) }} {{ attribution.year }}
17
21
  </a>
@@ -26,6 +30,7 @@
26
30
 
27
31
  <script>
28
32
  import {
33
+ VIcon,
29
34
  VList,
30
35
  VListItem,
31
36
  VListItemTitle,
@@ -40,6 +45,7 @@
40
45
  export default {
41
46
  name: 'VcsAttributions',
42
47
  components: {
48
+ VIcon,
43
49
  VList,
44
50
  VListItem,
45
51
  VListItemTitle,
@@ -65,4 +71,7 @@
65
71
  content: '\00a9';
66
72
  }
67
73
  }
74
+ .attribution-icon {
75
+ max-width: 30px;
76
+ }
68
77
  </style>
@@ -12,6 +12,7 @@ declare const _default: import("vue").DefineComponent<{
12
12
  provider: string;
13
13
  years: string;
14
14
  url: string;
15
+ icon?: string | undefined;
15
16
  }[]>;
16
17
  }, any, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
17
18
  entries: {
@@ -96,6 +96,29 @@ declare const _default: import("vue").DefineComponent<{
96
96
  } | undefined;
97
97
  readonly content?: string | undefined;
98
98
  } | undefined;
99
+ /**
100
+ * - optionnal, additional information to show in the footer as links or dialogs
101
+ */
102
+ readonly footerInformation?: readonly {
103
+ readonly title?: string | undefined;
104
+ readonly url?: string | {
105
+ readonly hash: string;
106
+ readonly host: string;
107
+ readonly hostname: string;
108
+ readonly href: string;
109
+ readonly toString: () => string;
110
+ readonly origin: string;
111
+ readonly password: string;
112
+ readonly pathname: string;
113
+ readonly port: string;
114
+ readonly protocol: string;
115
+ readonly search: string;
116
+ readonly searchParams: ReadonlyMap<string, string | null>;
117
+ readonly username: string;
118
+ readonly toJSON: () => string;
119
+ } | undefined;
120
+ readonly content?: string | undefined;
121
+ }[] | undefined;
99
122
  /**
100
123
  * - an option splashScreen, will show a splash Screen on Map Load.
101
124
  */
@@ -209,6 +232,10 @@ declare const _default: import("vue").DefineComponent<{
209
232
  * - can be used to hide the integrated Search bar
210
233
  */
211
234
  readonly hideSearch?: boolean | undefined;
235
+ /**
236
+ * - can be used to set the pitch angle of the viewpoint of features zoomed to from Search, in degrees. Defaults to -35 degrees.
237
+ */
238
+ readonly searchViewpointPitch?: number | undefined;
212
239
  /**
213
240
  * - can be used to hide the sharee button
214
241
  */
@@ -257,6 +284,10 @@ declare const _default: import("vue").DefineComponent<{
257
284
  * - can be used to hide the oblique name in the footer
258
285
  */
259
286
  readonly hideObliqueFooter?: boolean | undefined;
287
+ /**
288
+ * - can be used to hide the panorama name in the footer
289
+ */
290
+ readonly hidePanoramaFooter?: boolean | undefined;
260
291
  /**
261
292
  * - can be used to activate the overviewMap on startup
262
293
  */
@@ -7,7 +7,11 @@
7
7
  getActionsByLocation,
8
8
  } from '../manager/navbarManager.js';
9
9
  import VcsTextPageFooter from './VcsTextPageFooter.vue';
10
- import { getDataProtection, getImprint } from './uiConfigHelper.js';
10
+ import {
11
+ getDataProtection,
12
+ getImprint,
13
+ getFooterInformation,
14
+ } from './uiConfigHelper.js';
11
15
  import { toolboxComponentId } from '../manager/toolbox/ToolboxManagerComponent.vue';
12
16
 
13
17
  const app = inject('vcsApp');
@@ -55,6 +59,7 @@
55
59
 
56
60
  const dataProtection = getDataProtection(app.uiConfig?.config);
57
61
  const imprint = getImprint(app.uiConfig?.config);
62
+ const footerInformation = getFooterInformation(app.uiConfig?.config);
58
63
  </script>
59
64
 
60
65
  <template>
@@ -88,6 +93,16 @@
88
93
  />
89
94
  </v-list-item>
90
95
  </template>
96
+ <template v-for="(info, idx) in footerInformation" :key="idx">
97
+ <v-divider></v-divider>
98
+ <v-list-item v-if="info">
99
+ <VcsTextPageFooter
100
+ class="plainStyle"
101
+ :text-page="info"
102
+ :window-id="'footerInfoWindow_' + idx"
103
+ />
104
+ </v-list-item>
105
+ </template>
91
106
  </v-list>
92
107
  </template>
93
108
 
@@ -1,10 +1,9 @@
1
1
  <template>
2
- <!-- eslint-disable vue/no-v-html -->
3
- <span
4
- v-if="content"
5
- class="d-flex align-center overflow-hidden vcs-oblique-footer"
6
- v-html="content"
7
- />
2
+ <span v-if="content" class="vcs-oblique-footer">
3
+ <!-- eslint-disable vue/no-v-html -->
4
+ <span class="overflow-hidden" v-html="content" />
5
+ <div v-if="hasLinks" class="ml-1">|</div>
6
+ </span>
8
7
  </template>
9
8
 
10
9
  <script>
@@ -85,6 +84,13 @@
85
84
  mapChangedListener();
86
85
  });
87
86
 
87
+ const hasLinks = computed(
88
+ () =>
89
+ !!app.uiConfig.config?.dataProtection ||
90
+ !!app.uiConfig.config?.imprint ||
91
+ app.uiConfig.config?.footerInformation?.length > 0,
92
+ );
93
+
88
94
  const content = computed(() => {
89
95
  if (!app.uiConfig.config.hideObliqueFooter && currentImage.value) {
90
96
  const template =
@@ -102,6 +108,7 @@
102
108
 
103
109
  return {
104
110
  content,
111
+ hasLinks,
105
112
  };
106
113
  },
107
114
  };
@@ -109,8 +116,14 @@
109
116
 
110
117
  <style lang="scss" scoped>
111
118
  .vcs-oblique-footer {
119
+ display: flex;
120
+ align-items: center;
121
+ > div {
122
+ font-size: smaller;
123
+ }
112
124
  :deep(p) {
113
125
  font-size: smaller;
126
+ display: inline;
114
127
  margin: 0;
115
128
  }
116
129
  }
@@ -1,4 +1,5 @@
1
1
  declare const _default: import("vue").DefineComponent<{}, {
2
2
  content: import("vue").ComputedRef<string | null>;
3
+ hasLinks: import("vue").ComputedRef<boolean>;
3
4
  }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{}>>, {}, {}>;
4
5
  export default _default;
@@ -0,0 +1,72 @@
1
+ <script setup>
2
+ import { ref, inject, onUnmounted, computed } from 'vue';
3
+ import { PanoramaMap } from '@vcmap/core';
4
+
5
+ /** @type {import('../vcsUiApp').default} */
6
+ const app = inject('vcsApp');
7
+ const name = ref();
8
+ const time = ref();
9
+ const hasLinks = computed(
10
+ () =>
11
+ !!app.uiConfig.config?.dataProtection ||
12
+ !!app.uiConfig.config?.imprint ||
13
+ app.uiConfig.config?.footerInformation?.length > 0,
14
+ );
15
+
16
+ const showPanoramaFooter = computed(
17
+ () => !app.uiConfig.config.hidePanoramaFooter,
18
+ );
19
+
20
+ let imageChangedListener = () => {};
21
+ const setImage = (image) => {
22
+ if (image) {
23
+ name.value = image.name;
24
+ if (image.time) {
25
+ time.value = new Intl.DateTimeFormat(app.locale, {
26
+ dateStyle: 'short',
27
+ timeStyle: 'short',
28
+ }).format(image.time);
29
+ } else {
30
+ time.value = undefined;
31
+ }
32
+ }
33
+ };
34
+ const setMap = (map) => {
35
+ imageChangedListener();
36
+ if (map instanceof PanoramaMap) {
37
+ setImage(map.currentPanoramaImage);
38
+ imageChangedListener = map.currentImageChanged.addEventListener(setImage);
39
+ } else {
40
+ name.value = undefined;
41
+ time.value = undefined;
42
+ imageChangedListener = () => {};
43
+ }
44
+ };
45
+
46
+ const mapChangedListener = app.maps.mapActivated.addEventListener(setMap);
47
+ setMap(app.maps.activeMap);
48
+
49
+ onUnmounted(() => {
50
+ imageChangedListener();
51
+ mapChangedListener();
52
+ });
53
+ </script>
54
+
55
+ <template>
56
+ <span v-if="showPanoramaFooter && name && time" class="vcs-panorama-footer">
57
+ <span class="overflow-hidden"> {{ time }} - {{ name }} </span>
58
+ <span v-if="hasLinks" class="ml-1">|</span>
59
+ </span>
60
+ </template>
61
+
62
+ <style scoped lang="scss">
63
+ .vcs-panorama-footer {
64
+ display: flex;
65
+ align-items: center;
66
+ & > span {
67
+ display: inline-flex;
68
+ font-size: smaller;
69
+ align-items: center;
70
+ }
71
+ }
72
+ </style>
@@ -0,0 +1,2 @@
1
+ declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{}>>, {}, {}>;
2
+ export default _default;
@@ -85,8 +85,12 @@
85
85
  <style lang="scss" scoped>
86
86
  .text-page-footer {
87
87
  font-size: smaller;
88
+ display: flex;
89
+ align-items: center;
88
90
  a {
89
91
  color: var(--v-text-color);
92
+ display: flex;
93
+ align-items: center;
90
94
  }
91
95
  }
92
96
  </style>
@@ -3,6 +3,7 @@
3
3
  * @property {string} provider - name of the data provider
4
4
  * @property {number} [year] - year of dataset
5
5
  * @property {string} url - link to data provider
6
+ * @property {string} [icon] - provider logo
6
7
  */
7
8
  /**
8
9
  * @typedef {Object} AttributionEntry
@@ -13,12 +14,13 @@
13
14
  /**
14
15
  * merges attribution entries of same providers
15
16
  * @param {Array<AttributionEntry>} entries
16
- * @returns {Array<{provider: string, years: string, url: string}>}
17
+ * @returns {Array<{provider: string, years: string, url: string, icon?:string}>}
17
18
  */
18
19
  export function mergeAttributions(entries: Array<AttributionEntry>): Array<{
19
20
  provider: string;
20
21
  years: string;
21
22
  url: string;
23
+ icon?: string;
22
24
  }>;
23
25
  /**
24
26
  * Gets attributions of all active maps, layers and oblique collections and returns an array of entries.
@@ -45,6 +47,10 @@ export type AttributionOptions = {
45
47
  * - link to data provider
46
48
  */
47
49
  url: string;
50
+ /**
51
+ * - provider logo
52
+ */
53
+ icon?: string | undefined;
48
54
  };
49
55
  export type AttributionEntry = {
50
56
  /**