@vcmap/ui 6.2.1 → 6.2.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 (47) hide show
  1. package/build/postInstall.js +1 -1
  2. package/dist/assets/{cesium-607748ca.js → cesium-b021f072.js} +1513 -1313
  3. package/dist/assets/cesium.js +1 -1
  4. package/dist/assets/{core-ea8a27bd.js → core-4cd2e30d.js} +1554 -1551
  5. package/dist/assets/core-workers/panoramaImageWorker.js +1 -1
  6. package/dist/assets/core.js +1 -1
  7. package/dist/assets/{ol-8fe80c53.js → ol-c927b883.js} +1 -1
  8. package/dist/assets/ol.js +1 -1
  9. package/dist/assets/ui-b13e28a1.css +1 -0
  10. package/dist/assets/{ui-ffa735dc.js → ui-b13e28a1.js} +5542 -5402
  11. package/dist/assets/ui.js +1 -1
  12. package/dist/assets/vue.js +1 -1
  13. package/dist/assets/{vuetify-def19d80.js → vuetify-a1930526.js} +1 -1
  14. package/dist/assets/vuetify.js +1 -1
  15. package/index.d.ts +1 -1
  16. package/index.js +1 -0
  17. package/package.json +4 -3
  18. package/plugins/@vcmap-show-case/category-tester/src/CollectionComponentOptions.vue +41 -2
  19. package/plugins/@vcmap-show-case/category-tester/src/index.js +2 -0
  20. package/src/application/VcsSplashScreen.vue +9 -1
  21. package/src/components/lists/VcsTreeNode.vue +2 -1
  22. package/src/components/lists/VcsTreeNode.vue.d.ts +4 -0
  23. package/src/contentTree/LayerSwap.vue +9 -0
  24. package/src/contentTree/LayerSwap.vue.d.ts +14 -0
  25. package/src/featureInfo/balloonFeatureInfoView.d.ts +15 -2
  26. package/src/featureInfo/balloonFeatureInfoView.js +8 -103
  27. package/src/featureInfo/balloonHelper.d.ts +13 -0
  28. package/src/featureInfo/balloonHelper.js +77 -0
  29. package/src/featureInfo/featureInfo.d.ts +2 -1
  30. package/src/featureInfo/featureInfo.js +11 -3
  31. package/src/featureInfo/featureInfoInteraction.js +4 -1
  32. package/src/featureInfo/iframeWmsFeatureInfoView.js +12 -2
  33. package/src/i18n/de.d.ts +3 -0
  34. package/src/i18n/de.js +3 -0
  35. package/src/i18n/en.d.ts +3 -0
  36. package/src/i18n/en.js +3 -0
  37. package/src/legend/legendHelper.js +5 -0
  38. package/src/manager/collectionManager/CollectionComponentContent.vue +67 -3
  39. package/src/manager/collectionManager/CollectionComponentContent.vue.d.ts +3 -0
  40. package/src/manager/collectionManager/collectionComponentClass.d.ts +44 -1
  41. package/src/manager/collectionManager/collectionComponentClass.js +152 -2
  42. package/src/manager/panel/PanelComponent.vue +9 -1
  43. package/src/state.js +19 -6
  44. package/dist/assets/ui-ffa735dc.css +0 -1
  45. /package/dist/assets/core-workers/{panoramaImageWorker.js-a3ad230c.js → panoramaImageWorker.js-90c60e81.js} +0 -0
  46. /package/dist/assets/{vue-09a72820.js → vue-6a295c0b.js} +0 -0
  47. /package/dist/assets/{vuetify-def19d80.css → vuetify-a1930526.css} +0 -0
package/src/i18n/de.d.ts CHANGED
@@ -458,6 +458,9 @@ declare namespace messages {
458
458
  let notValid: string;
459
459
  let required: string;
460
460
  }
461
+ export namespace layerSwap {
462
+ let deleteButton: string;
463
+ }
461
464
  }
462
465
  export namespace settings {
463
466
  let title_15: string;
package/src/i18n/de.js CHANGED
@@ -320,6 +320,9 @@ const messages = {
320
320
  notValid: 'Eingabe nicht gültig',
321
321
  required: 'Eingabe ist erforderlich',
322
322
  },
323
+ layerSwap: {
324
+ deleteButton: 'Ebene deaktivieren',
325
+ },
323
326
  },
324
327
  settings: {
325
328
  title: 'Einstellungen',
package/src/i18n/en.d.ts CHANGED
@@ -458,6 +458,9 @@ declare namespace messages {
458
458
  let notValid: string;
459
459
  let required: string;
460
460
  }
461
+ export namespace layerSwap {
462
+ let deleteButton: string;
463
+ }
461
464
  }
462
465
  export namespace settings {
463
466
  let title_15: string;
package/src/i18n/en.js CHANGED
@@ -320,6 +320,9 @@ const messages = {
320
320
  notValid: 'Input not valid',
321
321
  required: 'Input is required',
322
322
  },
323
+ layerSwap: {
324
+ deleteButton: 'Deactivate layer',
325
+ },
323
326
  },
324
327
  settings: {
325
328
  title: 'Settings',
@@ -233,6 +233,10 @@ export function getLegendEntries(app) {
233
233
  syncVectorClusterGroups([...app.layers]);
234
234
  },
235
235
  );
236
+ const destroyAddedListener = app.layers.added.addEventListener((l) => {
237
+ syncLayerLegendEntries(l);
238
+ syncVectorClusterGroups([...app.layers]);
239
+ });
236
240
  const destroyRemovedListener = app.layers.removed.addEventListener((l) => {
237
241
  removeEntryForLayer(l);
238
242
  syncVectorClusterGroups([...app.layers]);
@@ -246,6 +250,7 @@ export function getLegendEntries(app) {
246
250
  const destroy = () => {
247
251
  destroyMapListener();
248
252
  destroyChangedListener();
253
+ destroyAddedListener();
249
254
  destroyRemovedListener();
250
255
  Object.values(styleChangedListener).forEach((cb) => cb());
251
256
  };
@@ -9,7 +9,15 @@
9
9
  :show-title="false"
10
10
  @item-moved="move"
11
11
  />
12
- <v-sheet v-if="items.length > limit" class="ma-2 pl-2">
12
+ <v-sheet v-if="page && pageSize && totalCount && items.length !== 0">
13
+ <v-pagination
14
+ class="px-2"
15
+ v-model="page"
16
+ :length="Math.ceil(totalCount / pageSize)"
17
+ density="compact"
18
+ ></v-pagination>
19
+ </v-sheet>
20
+ <v-sheet v-else-if="items.length > limit" class="ma-2 pl-2">
13
21
  <VcsButton @click="openCollectionComponentList">
14
22
  {{ $t('collectionManager.more') }}
15
23
  </VcsButton>
@@ -21,8 +29,9 @@
21
29
  </template>
22
30
 
23
31
  <script>
24
- import { computed, inject } from 'vue';
25
- import { VSheet, VContainer } from 'vuetify/components';
32
+ import { computed, inject, onUnmounted, ref, watch } from 'vue';
33
+ import { VSheet, VContainer, VPagination } from 'vuetify/components';
34
+ import { getLogger } from '@vcsuite/logger';
26
35
  import { createSelectionActions } from '../../components/lists/listHelper.js';
27
36
  import VcsList from '../../components/lists/VcsList.vue';
28
37
  import VcsButton from '../../components/buttons/VcsButton.vue';
@@ -41,6 +50,7 @@
41
50
  VcsList,
42
51
  VSheet,
43
52
  VContainer,
53
+ VPagination,
44
54
  },
45
55
  emits: ['openList'],
46
56
  setup(_props, { emit }) {
@@ -57,6 +67,57 @@
57
67
 
58
68
  const actions = collectionComponent.getActions();
59
69
 
70
+ const { pagination } = collectionComponent;
71
+ const page = ref();
72
+ const pageSize = ref();
73
+ const totalCount = ref();
74
+ let destroyPaginationListeners;
75
+
76
+ async function updatePagination() {
77
+ destroyPaginationListeners?.();
78
+ if (pagination.value && !pagination.value.initialized) {
79
+ await pagination.value.initialize();
80
+ }
81
+
82
+ page.value = pagination.value?.getPage();
83
+ pageSize.value = pagination.value?.getPageSize();
84
+ totalCount.value = pagination.value?.totalCount;
85
+ const listeners = [
86
+ pagination.value?.pageChanged.addEventListener((newPage) => {
87
+ page.value = newPage;
88
+ }),
89
+ pagination.value?.pageSizeChanged.addEventListener((newPageSize) => {
90
+ pageSize.value = newPageSize;
91
+ }),
92
+ ];
93
+ destroyPaginationListeners = () => {
94
+ listeners.forEach((l) => l?.());
95
+ };
96
+ }
97
+
98
+ if (pagination.value) {
99
+ updatePagination().catch((e) => {
100
+ getLogger('CollectionComponentContent').error(
101
+ 'setting up pagination failed',
102
+ e,
103
+ );
104
+ });
105
+ }
106
+
107
+ onUnmounted(() => {
108
+ destroyPaginationListeners?.();
109
+ });
110
+
111
+ watch(pagination, async () => {
112
+ await updatePagination();
113
+ });
114
+
115
+ watch(page, async () => {
116
+ if (pagination.value && page.value !== pagination.value.getPage()) {
117
+ await pagination.value.setPage(page.value);
118
+ }
119
+ });
120
+
60
121
  return {
61
122
  title: collectionComponent.title,
62
123
  items: collectionComponent.items,
@@ -81,6 +142,9 @@
81
142
  openCollectionComponentList() {
82
143
  emit('openList', collectionComponent.id);
83
144
  },
145
+ page,
146
+ pageSize,
147
+ totalCount,
84
148
  };
85
149
  },
86
150
  };
@@ -10,6 +10,9 @@ declare const _default: import("vue").DefineComponent<{}, {
10
10
  actions: import("vue").ComputedRef<any>;
11
11
  move(event: any): void;
12
12
  openCollectionComponentList(): void;
13
+ page: import("vue").Ref<any>;
14
+ pageSize: import("vue").Ref<any>;
15
+ totalCount: import("vue").Ref<any>;
13
16
  }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, "openList"[], "openList", import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{}>> & {
14
17
  onOpenList?: ((...args: any[]) => any) | undefined;
15
18
  }, {}, {}>;
@@ -6,11 +6,43 @@
6
6
  */
7
7
  export function createSupportedMapMappingFunction<T extends Object | import("@vcmap/core").VcsObject>(supportedMaps: string[] | ((arg0: T) => string[]), mapCollection: import("@vcmap/core").MapCollection): import("./collectionManager.js").MappingFunction<T>;
8
8
  export default CollectionComponentClass;
9
+ export type Pagination<T> = {
10
+ initialize: () => Promise<void>;
11
+ initialized: boolean;
12
+ /**
13
+ * - Total number of items.
14
+ */
15
+ totalCount: number;
16
+ getPage: () => number;
17
+ setPage: (page: number) => Promise<void>;
18
+ getPageSize: () => number;
19
+ setPageSize: (pageSize: number) => Promise<void>;
20
+ getPageItems: () => T[];
21
+ pageChanged: VcsEvent<number>;
22
+ pageSizeChanged: VcsEvent<number>;
23
+ };
24
+ export type PaginationOptions<T> = {
25
+ /**
26
+ * - Async loader returning items slice and total count.
27
+ */
28
+ getItems: (startIndex: number, count: number) => Promise<{
29
+ items: T[];
30
+ total: number;
31
+ }>;
32
+ /**
33
+ * - Initial page size.
34
+ */
35
+ defaultPageSize?: number | undefined;
36
+ /**
37
+ * - Initial page which is applied on initialize.
38
+ */
39
+ initialPage?: number | undefined;
40
+ };
9
41
  export type CollectionComponentUiOptions = {
10
42
  id?: string | undefined;
11
43
  title?: string | undefined;
12
44
  /**
13
- * - only supported for IndexedCollections
45
+ * - only supported for IndexedCollections.
14
46
  */
15
47
  draggable?: boolean | undefined;
16
48
  /**
@@ -34,6 +66,7 @@ export type CollectionComponentUiOptions = {
34
66
  removeTitle?: string | undefined;
35
67
  bulkRemoveTitle?: string | undefined;
36
68
  renameTitle?: string | undefined;
69
+ pagination?: PaginationOptions<unknown> | undefined;
37
70
  };
38
71
  export type CollectionComponentClassOptions<T extends Object> = CollectionComponentUiOptions & {
39
72
  collection: import("@vcmap/core").Collection<T>;
@@ -142,6 +175,11 @@ declare class CollectionComponentClass<T extends Object | import("@vcmap/core").
142
175
  * @private
143
176
  */
144
177
  private _actionTitles;
178
+ /**
179
+ * @type {import("vue").ShallowRef<Pagination<T> | undefined>}
180
+ * @readonly
181
+ */
182
+ readonly pagination: import("vue").ShallowRef<Pagination<T> | undefined>;
145
183
  /**
146
184
  * @tyep {() => void}
147
185
  * @private
@@ -266,6 +304,10 @@ declare class CollectionComponentClass<T extends Object | import("@vcmap/core").
266
304
  * @param {string | symbol} owner
267
305
  */
268
306
  removeOwner(owner: string | symbol): void;
307
+ /**
308
+ * @param {PaginationOptions<T> | undefined} options
309
+ */
310
+ setPagination(options: PaginationOptions<T> | undefined): void;
269
311
  /**
270
312
  * resets this collection component by destroying all list items and
271
313
  * re-adding them from the collection applying current filter and mapping functions
@@ -273,3 +315,4 @@ declare class CollectionComponentClass<T extends Object | import("@vcmap/core").
273
315
  reset(): void;
274
316
  destroy(): void;
275
317
  }
318
+ import { VcsEvent } from '@vcmap/core';
@@ -1,4 +1,4 @@
1
- import { IndexedCollection, isOverrideCollection } from '@vcmap/core';
1
+ import { IndexedCollection, isOverrideCollection, VcsEvent } from '@vcmap/core';
2
2
  import { getLogger } from '@vcsuite/logger';
3
3
  import { v4 as uuidv4 } from 'uuid';
4
4
  import { computed, reactive, ref, shallowRef, watch } from 'vue';
@@ -12,11 +12,139 @@ import {
12
12
  } from '../../actions/listActions.js';
13
13
  import { sortByOwner } from '../navbarManager.js';
14
14
 
15
+ /**
16
+ * @template T
17
+ * @typedef {Object} Pagination
18
+ * @property {() => Promise<void>} initialize
19
+ * @property {boolean} initialized
20
+ * @property {number} totalCount - Total number of items.
21
+ * @property {() => number} getPage
22
+ * @property {(page: number) => Promise<void>} setPage
23
+ * @property {() => number} getPageSize
24
+ * @property {(pageSize: number) => Promise<void>} setPageSize
25
+ * @property {() => T[]} getPageItems
26
+ * @property {VcsEvent<number>} pageChanged
27
+ * @property {VcsEvent<number>} pageSizeChanged
28
+ */
29
+
30
+ /**
31
+ * @template T
32
+ * @typedef {Object} PaginationOptions
33
+ * @property {(startIndex: number, count: number) => Promise<{ items: T[], total: number }>} getItems - Async loader returning items slice and total count.
34
+ * @property {number} [defaultPageSize=10] - Initial page size.
35
+ * @property {number} [initialPage=1] - Initial page which is applied on initialize.
36
+ */
37
+
38
+ /**
39
+ * Create a simple pagination helper that loads items into the provided collection.
40
+ * The collection is cleared and refilled whenever the page (or page size) changes.
41
+ * @template {Object} T
42
+ * @param {import("@vcmap/core").Collection<T>} collection - Target collection to populate.
43
+ * @param {PaginationOptions<T>} options - Pagination options.
44
+ * @returns {Promise<Pagination<T>>}
45
+ */
46
+ function createPagination(
47
+ collection,
48
+ { getItems, defaultPageSize = 10, initialPage = 1 },
49
+ ) {
50
+ let initialized = false;
51
+ let initializePromise;
52
+ let totalCount;
53
+ let currentPage;
54
+ let currentPageSize = defaultPageSize;
55
+
56
+ const pageChanged = new VcsEvent();
57
+ const pageSizeChanged = new VcsEvent();
58
+
59
+ /**
60
+ * @param {number} page
61
+ * @param {number} [size]
62
+ * @returns {Promise<void>}
63
+ */
64
+ async function setPage(page, size) {
65
+ const pageSize = size || currentPageSize;
66
+
67
+ if (currentPage === page && currentPageSize === pageSize) {
68
+ return;
69
+ }
70
+
71
+ const prevPage = currentPage;
72
+ const prevPageSize = currentPageSize;
73
+
74
+ const result = await getItems((page - 1) * pageSize, pageSize);
75
+ // If another request finished in the meantime, ignore the result (stale)
76
+ if (currentPage !== prevPage || currentPageSize !== prevPageSize) {
77
+ return;
78
+ }
79
+ const { items, total } = result;
80
+ totalCount = total;
81
+ collection.clear();
82
+ items.forEach((i) => {
83
+ collection.add(i);
84
+ });
85
+
86
+ currentPage = page;
87
+ pageChanged.raiseEvent(currentPage);
88
+ if (pageSize && pageSize !== currentPageSize) {
89
+ currentPageSize = pageSize;
90
+ pageSizeChanged.raiseEvent(currentPageSize);
91
+ }
92
+ if (!initialized) {
93
+ initialized = true;
94
+ }
95
+ }
96
+
97
+ return {
98
+ initialize() {
99
+ if (!initializePromise) {
100
+ initializePromise = setPage(initialPage, defaultPageSize);
101
+ }
102
+ return initializePromise;
103
+ },
104
+ get initialized() {
105
+ return initialized;
106
+ },
107
+ get totalCount() {
108
+ if (!initialized) {
109
+ throw new Error(
110
+ 'No initial request send yet. Please initialize/setPage first',
111
+ );
112
+ }
113
+ return totalCount;
114
+ },
115
+ getPage() {
116
+ if (!initialized) {
117
+ throw new Error(
118
+ 'No initial request send yet. Please initialize/setPage first',
119
+ );
120
+ }
121
+ return currentPage;
122
+ },
123
+ setPage,
124
+ getPageSize() {
125
+ return currentPageSize;
126
+ },
127
+ async setPageSize(size) {
128
+ await setPage(1, size);
129
+ },
130
+ getPageItems() {
131
+ if (!initialized) {
132
+ throw new Error(
133
+ 'No initial request send yet. Please initialize/setPage first',
134
+ );
135
+ }
136
+ return [...collection];
137
+ },
138
+ pageChanged,
139
+ pageSizeChanged,
140
+ };
141
+ }
142
+
15
143
  /**
16
144
  * @typedef {Object} CollectionComponentUiOptions
17
145
  * @property {string} [id]
18
146
  * @property {string} [title]
19
- * @property {boolean} [draggable=false] - only supported for IndexedCollections
147
+ * @property {boolean} [draggable=false] - only supported for IndexedCollections.
20
148
  * @property {boolean} [renamable=false] - adds actions to rename items from list. Sets a default titleChanged callback on all list items, which can be overwritten in the mapping function, if necessary.
21
149
  * @property {boolean} [removable=false] - adds actions to remove items from list. Also adds a header action to delete selected, if selectable is set to true.
22
150
  * @property {boolean} [selectable=false]
@@ -26,6 +154,7 @@ import { sortByOwner } from '../navbarManager.js';
26
154
  * @property {string} [removeTitle="list.deleteItem"]
27
155
  * @property {string} [bulkRemoveTitle="list.delete"]
28
156
  * @property {string} [renameTitle="list.renameItem"]
157
+ * @property {PaginationOptions<unknown>} [pagination]
29
158
  */
30
159
 
31
160
  /**
@@ -205,6 +334,15 @@ class CollectionComponentClass {
205
334
  renameTitle: options.renameTitle ?? 'list.renameItem',
206
335
  };
207
336
 
337
+ /**
338
+ * @type {import("vue").ShallowRef<Pagination<T> | undefined>}
339
+ * @readonly
340
+ */
341
+ this.pagination = shallowRef();
342
+ if (options.pagination) {
343
+ this.setPagination(options.pagination);
344
+ }
345
+
208
346
  /**
209
347
  * @tyep {() => void}
210
348
  * @private
@@ -651,6 +789,18 @@ class CollectionComponentClass {
651
789
  this._actions.value = actions;
652
790
  }
653
791
 
792
+ /**
793
+ * @param {PaginationOptions<T> | undefined} options
794
+ */
795
+ setPagination(options) {
796
+ if (options) {
797
+ this.pagination.value = createPagination(this.collection, options);
798
+ } else {
799
+ this.pagination.value = undefined;
800
+ this.collection.clear();
801
+ }
802
+ }
803
+
654
804
  /**
655
805
  * resets this collection component by destroying all list items and
656
806
  * re-adding them from the collection applying current filter and mapping functions
@@ -18,7 +18,7 @@
18
18
  </template>
19
19
 
20
20
  <script>
21
- import { computed, getCurrentInstance } from 'vue';
21
+ import { computed, inject, provide, getCurrentInstance } from 'vue';
22
22
  import { PanelLocation } from './panelManager.js';
23
23
 
24
24
  export default {
@@ -31,6 +31,14 @@
31
31
  },
32
32
  emits: ['resize'],
33
33
  setup(props, { emit }) {
34
+ const app = inject('vcsApp');
35
+ const panel = app.panelManager.get(props.panelState.id);
36
+ if (panel?.provides) {
37
+ Object.entries(panel.provides).forEach(([key, value]) => {
38
+ provide(key, value);
39
+ });
40
+ }
41
+
34
42
  return {
35
43
  appIsDark: computed(() => {
36
44
  return getCurrentInstance().proxy.$vuetify.theme.dark || !1;
package/src/state.js CHANGED
@@ -324,13 +324,26 @@ function writeUrlAppState(state, maxLength) {
324
324
  */
325
325
  const urlState = new Array(7).fill(0);
326
326
  if (state.activeViewpoint) {
327
+ const { cameraPosition, groundPosition, distance, heading, pitch, roll } =
328
+ state.activeViewpoint;
329
+ function toFixed(num, digits) {
330
+ return Math.round(num * 10 ** digits) / 10 ** digits;
331
+ }
332
+ function formatCoord(coord) {
333
+ if (coord[2] === undefined) {
334
+ return [toFixed(coord[0], 6), toFixed(coord[1], 6)];
335
+ }
336
+ return [toFixed(coord[0], 6), toFixed(coord[1], 6), toFixed(coord[2], 2)];
337
+ }
338
+ const overwriteRoll =
339
+ !roll || Math.abs(roll - 360) < 1e-4 || Math.abs(roll) < 1e-4;
327
340
  urlState[0] = [
328
- state.activeViewpoint.cameraPosition?.slice() ?? 0,
329
- state.activeViewpoint.groundPosition?.slice() ?? 0,
330
- state.activeViewpoint.distance ?? 0,
331
- state.activeViewpoint.heading,
332
- state.activeViewpoint.pitch,
333
- state.activeViewpoint.roll,
341
+ cameraPosition ? formatCoord(cameraPosition) : 0,
342
+ groundPosition ? formatCoord(groundPosition) : 0,
343
+ distance ? toFixed(distance, 2) : 0,
344
+ heading ? toFixed(heading, 4) : 0,
345
+ pitch ? toFixed(pitch, 4) : -90,
346
+ overwriteRoll ? 0 : toFixed(roll, 4),
334
347
  ];
335
348
  }
336
349