@vcmap/ui 6.3.0-rc.1 → 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 (57) hide show
  1. package/config/base.config.json +6 -3
  2. package/config/cluster.config.json +2 -1
  3. package/config/dev.config.json +377 -1
  4. package/dist/assets/cesium.js +1 -1
  5. package/dist/assets/{core-b7d98022.js → core-c23fc5f1.js} +10565 -8835
  6. package/dist/assets/core-workers/panoramaImageWorker.js +1 -1
  7. package/dist/assets/core.js +1 -1
  8. package/dist/assets/ol.js +1 -1
  9. package/dist/assets/ui-e61976d4.css +1 -0
  10. package/dist/assets/{ui-94adeedc.js → ui-e61976d4.js} +6650 -6544
  11. package/dist/assets/ui.js +1 -1
  12. package/dist/assets/vue.js +1 -1
  13. package/dist/assets/{vuetify-2f71239e.js → vuetify-de6f6eb0.js} +1 -1
  14. package/dist/assets/vuetify.js +1 -1
  15. package/index.d.ts +3 -1
  16. package/index.js +1 -1
  17. package/package.json +1 -1
  18. package/plugins/@vcmap-show-case/panel-tester/src/TextPanelExample.vue +1 -1
  19. package/plugins/package.json +4 -3
  20. package/src/actions/actionHelper.d.ts +0 -1
  21. package/src/actions/actionHelper.js +3 -3
  22. package/src/application/VcsApp.vue +12 -1
  23. package/src/application/VcsApp.vue.d.ts +32 -0
  24. package/src/application/VcsAttributions.vue +9 -0
  25. package/src/application/VcsAttributionsFooter.vue.d.ts +1 -0
  26. package/src/application/VcsContainer.vue.d.ts +31 -0
  27. package/src/application/VcsMobileMenuList.vue +16 -1
  28. package/src/application/VcsObliqueFooter.vue +19 -6
  29. package/src/application/VcsObliqueFooter.vue.d.ts +1 -0
  30. package/src/application/VcsPanoramaFooter.vue +26 -6
  31. package/src/application/VcsTextPageFooter.vue +4 -0
  32. package/src/application/attributionsHelper.d.ts +7 -1
  33. package/src/application/attributionsHelper.js +7 -2
  34. package/src/application/uiConfigHelper.d.ts +6 -0
  35. package/src/application/uiConfigHelper.js +28 -0
  36. package/src/contentTree/wmsGroupContentTreeItem.d.ts +52 -6
  37. package/src/contentTree/wmsGroupContentTreeItem.js +127 -28
  38. package/src/featureInfo/balloonHelper.js +8 -2
  39. package/src/i18n/de.d.ts +1 -0
  40. package/src/i18n/de.js +1 -0
  41. package/src/i18n/en.d.ts +1 -0
  42. package/src/i18n/en.js +1 -0
  43. package/src/manager/panel/PanelComponent.vue +48 -27
  44. package/src/manager/panel/PanelComponent.vue.d.ts +0 -1
  45. package/src/manager/panel/PanelManagerComponent.vue +42 -19
  46. package/src/manager/panel/PanelManagerComponent.vue.d.ts +4 -3
  47. package/src/search/SearchComponent.vue +9 -11
  48. package/src/search/SearchComponent.vue.d.ts +2 -1
  49. package/src/search/search.js +2 -0
  50. package/src/uiConfig.d.ts +46 -0
  51. package/src/uiConfig.js +3 -0
  52. package/dist/assets/ui-94adeedc.css +0 -1
  53. /package/dist/assets/{cesium-4fcc8a17.js → cesium-8369e63b.js} +0 -0
  54. /package/dist/assets/core-workers/{panoramaImageWorker.js-fc0f2458.js → panoramaImageWorker.js-f9c706f1.js} +0 -0
  55. /package/dist/assets/{ol-8c487975.js → ol-9f59d99f.js} +0 -0
  56. /package/dist/assets/{vue-225a7b37.js → vue-f6136dc6.js} +0 -0
  57. /package/dist/assets/{vuetify-2f71239e.css → vuetify-de6f6eb0.css} +0 -0
package/dist/assets/ui.js CHANGED
@@ -1 +1 @@
1
- export * from "./ui-94adeedc.js";
1
+ export * from "./ui-e61976d4.js";
@@ -1 +1 @@
1
- export * from "./vue-225a7b37.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-2f71239e.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-225a7b37.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-2f71239e.js";
1
+ export * from "./vuetify-de6f6eb0.js";
package/index.d.ts CHANGED
@@ -279,13 +279,15 @@ export { default as VcsSplashScreen } from "./src/application/VcsSplashScreen.vu
279
279
  export type * from "./src/application/VcsSplashScreen.vue.d.ts";
280
280
  export { default as Search } from "./src/search/search.js";
281
281
  export type * from "./src/search/search.d.ts";
282
+ export { searchComponentId } from "./src/search/SearchComponent.vue";
283
+ export type * from "./src/search/SearchComponent.vue.d.ts";
282
284
  export { markText } from "./src/search/markText.js";
283
285
  export type * from "./src/search/markText.d.ts";
284
286
  export { default as ResultItemComponent } from "./src/search/ResultItem.vue";
285
287
  export type * from "./src/search/ResultItem.vue.d.ts";
286
288
  export { default as ResultsComponent } from "./src/search/ResultsComponent.vue";
287
289
  export type * from "./src/search/ResultsComponent.vue.d.ts";
288
- export { addLoadingOverlay, callSafeAction, createMapButtonAction, createToggleAction, createModalAction, createLinkAction, createGoToViewpointAction, createZoomToFeatureAction, searchComponentId } from "./src/actions/actionHelper.js";
290
+ export { addLoadingOverlay, callSafeAction, createMapButtonAction, createToggleAction, createModalAction, createLinkAction, createGoToViewpointAction, createZoomToFeatureAction } from "./src/actions/actionHelper.js";
289
291
  export type * from "./src/actions/actionHelper.d.ts";
290
292
  export { createDeepPickingAction, deepPickingWindowId } from "./src/actions/deepPickingAction.js";
291
293
  export type * from "./src/actions/deepPickingAction.d.ts";
package/index.js CHANGED
@@ -11,7 +11,6 @@ export {
11
11
  createLinkAction,
12
12
  createGoToViewpointAction,
13
13
  createZoomToFeatureAction,
14
- searchComponentId,
15
14
  } from './src/actions/actionHelper.js';
16
15
  export {
17
16
  createDeepPickingAction,
@@ -377,6 +376,7 @@ export {
377
376
  getLegendEntries,
378
377
  } from './src/legend/legendHelper.js';
379
378
  export { default as Search } from './src/search/search.js';
379
+ export { searchComponentId } from './src/search/SearchComponent.vue';
380
380
  export { markText } from './src/search/markText.js';
381
381
  export { default as ResultItemComponent } from './src/search/ResultItem.vue';
382
382
  export { default as ResultsComponent } from './src/search/ResultsComponent.vue';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vcmap/ui",
3
- "version": "6.3.0-rc.1",
3
+ "version": "6.3.0-rc.2",
4
4
  "author": "Virtual City Systems",
5
5
  "license": "MIT",
6
6
  "scripts": {
@@ -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
@@ -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",
@@ -31,7 +31,8 @@
31
31
  "@vcmap/cesium-inspector": "^2.0.0",
32
32
  "@vcmap/event-control": "^1.0.1",
33
33
  "@vcmap/dynamic-layer": "^1.0.0",
34
- "@vcmap/geofence": "^1.0.2"
34
+ "@vcmap/geofence": "^1.0.2",
35
+ "@vcmap/panorama": "^1.0.0"
35
36
  },
36
37
  "optionalDependencies": {
37
38
  "@vcmap/planning": "^7.0.0"
@@ -118,7 +118,6 @@ export function addLoadingOverlay(app: import("../vcsUiApp.js").default, owner:
118
118
  maxWidth?: string | number | undefined;
119
119
  persistent?: boolean | undefined;
120
120
  } | undefined): () => void;
121
- export const searchComponentId: "searchId";
122
121
  export type ActionOptions = Omit<VcsAction, 'callback'>;
123
122
  export type ActionCallback = (p?: PointerEvent) => (void | Promise<void>);
124
123
  export type VcsAction = {
@@ -18,7 +18,9 @@ import {
18
18
  getFittedWindowPositionOptions,
19
19
  getTargetSize,
20
20
  } from '../manager/window/windowHelper.js';
21
- import SearchComponent from '../search/SearchComponent.vue';
21
+ import SearchComponent, {
22
+ searchComponentId,
23
+ } from '../search/SearchComponent.vue';
22
24
  import VcsLoadingOverlay from '../components/plugins/VcsLoadingOverlay.vue';
23
25
 
24
26
  /**
@@ -215,8 +217,6 @@ export function createToggleAction(
215
217
  return { action, destroy };
216
218
  }
217
219
 
218
- export const searchComponentId = 'searchId';
219
-
220
220
  /**
221
221
  * @param {import("../vcsUiApp.js").default} app
222
222
  * @returns {{action: import("vue").UnwrapRef<VcsAction>, destroy: function():void}}
@@ -28,6 +28,12 @@
28
28
  :text-page="dataProtection"
29
29
  :window-id="'dataProtectionWindow'"
30
30
  />
31
+ <VcsTextPageFooter
32
+ v-for="(info, idx) in footerInformation"
33
+ :key="idx"
34
+ :text-page="info"
35
+ :window-id="'footerInfoWindow_' + idx"
36
+ />
31
37
  <v-spacer />
32
38
  <VcsAttributionsFooter
33
39
  :entries="attributionEntries"
@@ -89,7 +95,11 @@
89
95
  import VcsAttributions from './VcsAttributions.vue';
90
96
  import { getAttributions } from './attributionsHelper.js';
91
97
  import VcsPositionDisplay from './VcsPositionDisplay.vue';
92
- import { getDataProtection, getImprint } from './uiConfigHelper.js';
98
+ import {
99
+ getDataProtection,
100
+ getImprint,
101
+ getFooterInformation,
102
+ } from './uiConfigHelper.js';
93
103
  import VcsPanoramaFooter from './VcsPanoramaFooter.vue';
94
104
 
95
105
  /**
@@ -888,6 +898,7 @@
888
898
  footerHeight,
889
899
  imprint: getImprint(app.uiConfig.config),
890
900
  dataProtection: getDataProtection(app.uiConfig.config),
901
+ footerInformation: getFooterInformation(app.uiConfig.config),
891
902
  showSplashScreen,
892
903
  splashScreen,
893
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;
@@ -1,10 +1,21 @@
1
1
  <script setup>
2
- import { ref, inject, onUnmounted } from 'vue';
2
+ import { ref, inject, onUnmounted, computed } from 'vue';
3
3
  import { PanoramaMap } from '@vcmap/core';
4
4
 
5
+ /** @type {import('../vcsUiApp').default} */
5
6
  const app = inject('vcsApp');
6
7
  const name = ref();
7
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
+ );
8
19
 
9
20
  let imageChangedListener = () => {};
10
21
  const setImage = (image) => {
@@ -42,11 +53,20 @@
42
53
  </script>
43
54
 
44
55
  <template>
45
- <span
46
- v-if="name && time"
47
- class="d-flex align-center overflow-hidden vcs-panorama-footer"
48
- >{{ time }} - {{ name }}
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>
49
59
  </span>
50
60
  </template>
51
61
 
52
- <style scoped lang="scss"></style>
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>
@@ -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
  /**
@@ -6,6 +6,7 @@ import { ObliqueMap } from '@vcmap/core';
6
6
  * @property {string} provider - name of the data provider
7
7
  * @property {number} [year] - year of dataset
8
8
  * @property {string} url - link to data provider
9
+ * @property {string} [icon] - provider logo
9
10
  */
10
11
 
11
12
  /**
@@ -18,12 +19,12 @@ import { ObliqueMap } from '@vcmap/core';
18
19
  /**
19
20
  * merges attribution entries of same providers
20
21
  * @param {Array<AttributionEntry>} entries
21
- * @returns {Array<{provider: string, years: string, url: string}>}
22
+ * @returns {Array<{provider: string, years: string, url: string, icon?:string}>}
22
23
  */
23
24
  export function mergeAttributions(entries) {
24
25
  const providers = {};
25
26
  entries.forEach(({ attributions }) => {
26
- attributions.forEach(({ provider, year, url }) => {
27
+ attributions.forEach(({ provider, year, url, icon }) => {
27
28
  const providerObject = providers[provider];
28
29
  if (providerObject) {
29
30
  if (year) {
@@ -36,12 +37,16 @@ export function mergeAttributions(entries) {
36
37
  const set = new Set([...providerObject.years, Number(year)]);
37
38
  providerObject.years = [...set].sort((a, b) => a - b);
38
39
  }
40
+ if (icon && !providerObject.icon) {
41
+ providerObject.icon = icon;
42
+ }
39
43
  }
40
44
  }
41
45
  } else {
42
46
  providers[provider] = {
43
47
  years: year ? [Number(year)] : [],
44
48
  url,
49
+ ...(icon && { icon }),
45
50
  };
46
51
  }
47
52
  });
@@ -10,6 +10,12 @@ export function getDataProtection(uiConfig: import("../uiConfig.js").UiConfigObj
10
10
  * @returns {import('vue').ComputedRef<import('../uiConfig.js').TextPageType|undefined>}
11
11
  */
12
12
  export function getImprint(uiConfig: import("../uiConfig.js").UiConfigObject): import('vue').ComputedRef<import('../uiConfig.js').TextPageType | undefined>;
13
+ /**
14
+ * Creates a computed property for additional footer information configuration.
15
+ * @param {import("../uiConfig.js").UiConfigObject} uiConfig - The UI configuration object from the app.
16
+ * @returns {import('vue').ComputedRef<import('../uiConfig.js').TextPageType[]|undefined>}
17
+ */
18
+ export function getFooterInformation(uiConfig: import("../uiConfig.js").UiConfigObject): import('vue').ComputedRef<import('../uiConfig.js').TextPageType[] | undefined>;
13
19
  /**
14
20
  * Creates a computed property for mobile logo.
15
21
  * @param {import("../vcsUiApp.js").default} app - The VcsUiApp.
@@ -1,3 +1,4 @@
1
+ import { getLogger } from '@vcsuite/logger';
1
2
  import { computed } from 'vue';
2
3
 
3
4
  /**
@@ -35,6 +36,33 @@ export function getImprint(uiConfig) {
35
36
  return undefined;
36
37
  });
37
38
  }
39
+ /**
40
+ * Creates a computed property for additional footer information configuration.
41
+ * @param {import("../uiConfig.js").UiConfigObject} uiConfig - The UI configuration object from the app.
42
+ * @returns {import('vue').ComputedRef<import('../uiConfig.js').TextPageType[]|undefined>}
43
+ */
44
+ export function getFooterInformation(uiConfig) {
45
+ return computed(() => {
46
+ if (uiConfig?.footerInformation) {
47
+ return uiConfig.footerInformation
48
+ .filter((info) => {
49
+ if (!info.title && !info.url) {
50
+ getLogger('uiConfigHelper').warn(
51
+ 'Footer information item skipped, missing title or url',
52
+ info,
53
+ );
54
+ return false;
55
+ }
56
+ return true;
57
+ })
58
+ .map((info) => ({
59
+ title: info.title || new URL(info.url, window.location.href).hostname,
60
+ ...info,
61
+ }));
62
+ }
63
+ return undefined;
64
+ });
65
+ }
38
66
 
39
67
  /**
40
68
  * Creates a computed property for mobile logo.