@vcmap/ui 5.1.3 → 5.1.5

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 (65) hide show
  1. package/config/base.config.json +0 -2
  2. package/config/dev.config.json +4 -0
  3. package/config/www.config.json +0 -2
  4. package/dist/assets/cesium.js +1 -1
  5. package/dist/assets/{core.c815b8.js → core.a3bdf3.js} +2491 -2446
  6. package/dist/assets/core.js +1 -1
  7. package/dist/assets/index-dccddacb.js +1 -0
  8. package/dist/assets/ol.js +1 -1
  9. package/dist/assets/{ui.f85ce1.css → ui.f5e8c3.css} +2 -2
  10. package/dist/assets/{ui.f85ce1.js → ui.f5e8c3.js} +4461 -4276
  11. package/dist/assets/ui.js +1 -1
  12. package/dist/assets/vue.js +2 -2
  13. package/dist/assets/{vuetify.bf2ba1.js → vuetify.4aa1eb.js} +1 -1
  14. package/dist/assets/vuetify.js +2 -2
  15. package/dist/index.html +6 -2
  16. package/index.d.ts +1 -1
  17. package/index.html +5 -1
  18. package/index.js +1 -0
  19. package/package.json +2 -2
  20. package/src/actions/listActions.d.ts +59 -3
  21. package/src/actions/listActions.js +114 -2
  22. package/src/application/VcsApp.vue +20 -4
  23. package/src/application/VcsApp.vue.d.ts +8 -2
  24. package/src/application/VcsNavbar.vue +1 -1
  25. package/src/application/VcsTextPageFooter.vue +47 -30
  26. package/src/application/VcsTextPageFooter.vue.d.ts +5 -3
  27. package/src/components/form-inputs-controls/VcsTextArea.vue +11 -3
  28. package/src/components/form-inputs-controls/VcsTextArea.vue.d.ts +2 -0
  29. package/src/components/icons/+all.js +8 -0
  30. package/src/components/icons/2DPointIcon.vue +22 -0
  31. package/src/components/icons/2DPointIcon.vue.d.ts +2 -0
  32. package/src/components/icons/3DPointIcon.vue +22 -0
  33. package/src/components/icons/3DPointIcon.vue.d.ts +2 -0
  34. package/src/components/icons/AxisIcon.vue +10 -15
  35. package/src/components/icons/PointMeasurementIcon.vue +7 -17
  36. package/src/components/viewpoint/VcsViewpointComponent.vue +27 -5
  37. package/src/components/viewpoint/VcsViewpointComponent.vue.d.ts +9 -0
  38. package/src/components/viewpoint/VcsViewpointEditor.vue +10 -1
  39. package/src/components/viewpoint/VcsViewpointEditor.vue.d.ts +11 -1
  40. package/src/contentTree/LayerTree.vue +22 -3
  41. package/src/featureInfo/abstractFeatureInfoView.d.ts +8 -0
  42. package/src/featureInfo/abstractFeatureInfoView.js +20 -1
  43. package/src/i18n/de.d.ts +6 -1
  44. package/src/i18n/de.js +6 -1
  45. package/src/i18n/en.d.ts +6 -1
  46. package/src/i18n/en.js +6 -1
  47. package/src/manager/collectionManager/collectionComponentClass.d.ts +14 -4
  48. package/src/manager/collectionManager/collectionComponentClass.js +40 -22
  49. package/src/manager/collectionManager/editorCollectionComponentClass.d.ts +7 -1
  50. package/src/manager/collectionManager/editorCollectionComponentClass.js +7 -2
  51. package/src/manager/contextMenu/contextMenuManager.d.ts +11 -0
  52. package/src/manager/contextMenu/contextMenuManager.js +22 -1
  53. package/src/navigation/MapNavigation.vue +7 -4
  54. package/src/navigation/overviewMap.js +24 -19
  55. package/src/siteConfig.d.ts +5 -0
  56. package/src/siteConfig.js +93 -0
  57. package/src/uiConfig.d.ts +16 -6
  58. package/src/uiConfig.js +5 -3
  59. package/src/vcsUiApp.d.ts +1 -0
  60. package/src/vcsUiApp.js +4 -0
  61. package/dist/assets/index-0abd9815.js +0 -1
  62. /package/dist/assets/{cesium.012009.js → cesium.a6cb0f.js} +0 -0
  63. /package/dist/assets/{ol.fbe9a4.js → ol.6a61cd.js} +0 -0
  64. /package/dist/assets/{vue.65726b.js → vue.7cc217.js} +0 -0
  65. /package/dist/assets/{vuetify.bf2ba1.css → vuetify.4aa1eb.css} +0 -0
@@ -13,12 +13,16 @@ import { createListEditAction } from '../../actions/listActions.js';
13
13
  * editor: EditorWindowComponentOptions|function(T):EditorWindowComponentOptions|undefined,
14
14
  * multiEditor?: EditorWindowComponentOptions,
15
15
  * predicate?: import("./collectionManager.js").PredicateFunction<T>,
16
- * selectionBased?: boolean
16
+ * selectionBased?: boolean,
17
+ * editTitle?: string,
18
+ * bulkEditTitle?: string
17
19
  * }} EditingOptions
18
20
  * @property {EditorWindowComponentOptions|function(T)|undefined} editor
19
21
  * @property {EditorWindowComponentOptions} [multiEditor]
20
22
  * @property {import("./collectionManager.js").PredicateFunction<T>} [predicate=()=>true] - Optional predicate function for editor
21
23
  * @property {boolean} [selectionBased=true] - If true, editor windows are coupled to selection and editor windows are exclusive
24
+ * @property {string} [editTitle="list.editItem"]
25
+ * @property {string} [bulkEditTitle="list.edit"]
22
26
  * @template {Object} T
23
27
  */
24
28
 
@@ -236,7 +240,7 @@ export function makeEditorCollectionComponentClass(
236
240
  });
237
241
 
238
242
  const editItemAction = {
239
- name: 'list.editItem',
243
+ name: editingOptions.editTitle ?? 'list.editItem',
240
244
  async callback() {
241
245
  if (selectionBased) {
242
246
  closeEditorWindows();
@@ -263,6 +267,7 @@ export function makeEditorCollectionComponentClass(
263
267
  app.windowManager,
264
268
  editorCollectionComponent.owner,
265
269
  getMultiEditorWindowId(),
270
+ editingOptions.bulkEditTitle,
266
271
  );
267
272
 
268
273
  editorCollectionComponent.addActions([
@@ -38,6 +38,16 @@ declare class ContextMenuManager {
38
38
  * @private
39
39
  */
40
40
  private _listeners;
41
+ /**
42
+ * An event called when the context menu is closed
43
+ * @type {VcsEvent<void>}
44
+ */
45
+ closed: VcsEvent<void>;
46
+ /**
47
+ * @type {() => void}
48
+ * @private
49
+ */
50
+ private _closedListener;
41
51
  _ensureInteraction(): void;
42
52
  _setupListeners(): void;
43
53
  /**
@@ -68,3 +78,4 @@ declare class ContextMenuManager {
68
78
  clear(): void;
69
79
  destroy(): void;
70
80
  }
81
+ import { VcsEvent } from '@vcmap/core';
@@ -1,4 +1,4 @@
1
- import { CesiumMap, BaseOLMap } from '@vcmap/core';
1
+ import { CesiumMap, BaseOLMap, VcsEvent } from '@vcmap/core';
2
2
  import { unByKey } from 'ol/Observable.js';
3
3
  import { check } from '@vcsuite/check';
4
4
  import ContextMenuInteraction from './contextMenuInteraction.js';
@@ -81,6 +81,24 @@ class ContextMenuManager {
81
81
  * @private
82
82
  */
83
83
  this._listeners = [];
84
+
85
+ /**
86
+ * An event called when the context menu is closed
87
+ * @type {VcsEvent<void>}
88
+ */
89
+ this.closed = new VcsEvent();
90
+
91
+ /**
92
+ * @type {() => void}
93
+ * @private
94
+ */
95
+ this._closedListener = this._app.windowManager.removed.addEventListener(
96
+ (window) => {
97
+ if (window.id === contextMenuWindowId) {
98
+ this.closed.raiseEvent();
99
+ }
100
+ },
101
+ );
84
102
  }
85
103
 
86
104
  _ensureInteraction() {
@@ -208,12 +226,15 @@ class ContextMenuManager {
208
226
  }
209
227
 
210
228
  destroy() {
229
+ this.clear();
211
230
  this._interaction.destroy();
212
231
  if (this._interactionListener) {
213
232
  this._interactionListener();
214
233
  this._interactionListener = null;
215
234
  }
216
235
  this._eventHandlers = [];
236
+ this._closedListener();
237
+ this.closed.destroy();
217
238
  }
218
239
  }
219
240
 
@@ -64,7 +64,9 @@
64
64
  } else {
65
65
  listener = app.maps.mapActivated.addEventListener((map) => {
66
66
  defaultViewpoint = map.getViewpointSync();
67
- listener();
67
+ if (defaultViewpoint?.isValid()) {
68
+ listener();
69
+ }
68
70
  });
69
71
  }
70
72
 
@@ -88,9 +90,10 @@
88
90
  title: 'navigation.homeButton',
89
91
  icon: '$vcsHomePoint',
90
92
  async callback() {
91
- await app.maps.activeMap?.gotoViewpoint(
92
- getStartingViewpoint() || defaultViewpoint,
93
- );
93
+ const vp = getStartingViewpoint() || defaultViewpoint;
94
+ if (app.maps.activeMap && vp?.isValid()) {
95
+ await app.maps.activeMap.gotoViewpoint(vp);
96
+ }
94
97
  },
95
98
  });
96
99
 
@@ -11,6 +11,7 @@ import {
11
11
  Extent,
12
12
  Viewpoint,
13
13
  deserializeLayer,
14
+ maxZIndex,
14
15
  } from '@vcmap/core';
15
16
  import Point from 'ol/geom/Point.js';
16
17
  import Feature from 'ol/Feature.js';
@@ -454,23 +455,25 @@ class OverviewMap {
454
455
  * @private
455
456
  */
456
457
  _obliqueImageChange(image) {
457
- const { source } = this._obliqueImageLayer;
458
- if (this._obliqueViewDirection !== image.viewDirection) {
459
- this._obliqueViewDirection = image.viewDirection;
460
- source.changed();
461
- }
462
- const activeFeature = source.getFeatureById(image.name);
463
- if (activeFeature) {
464
- this._obliqueSelectedImageLayer.removeAllFeatures();
465
- this._obliqueSelectedImageLayer.addFeatures([activeFeature]);
466
- const extent = new Extent({
467
- coordinates: activeFeature.getGeometry().getExtent(),
468
- projection: mercatorProjection.toJSON(),
469
- });
470
-
471
- const vp = Viewpoint.createViewpointFromExtent(extent);
472
- vp.distance /= this._obliqueResolutionFactor;
473
- this._map.gotoViewpoint(vp);
458
+ if (image) {
459
+ const { source } = this._obliqueImageLayer;
460
+ if (this._obliqueViewDirection !== image.viewDirection) {
461
+ this._obliqueViewDirection = image.viewDirection;
462
+ source.changed();
463
+ }
464
+ const activeFeature = source.getFeatureById(image.name);
465
+ if (activeFeature) {
466
+ this._obliqueSelectedImageLayer.removeAllFeatures();
467
+ this._obliqueSelectedImageLayer.addFeatures([activeFeature]);
468
+ const extent = new Extent({
469
+ coordinates: activeFeature.getGeometry().getExtent(),
470
+ projection: mercatorProjection.toJSON(),
471
+ });
472
+
473
+ const vp = Viewpoint.createViewpointFromExtent(extent);
474
+ vp.distance /= this._obliqueResolutionFactor;
475
+ this._map.gotoViewpoint(vp);
476
+ }
474
477
  }
475
478
  }
476
479
 
@@ -492,7 +495,7 @@ class OverviewMap {
492
495
  this._obliqueTileLayer = new VectorLayer({
493
496
  projection: mercatorProjection.toJSON(),
494
497
  style: obliqueTileStyle,
495
- zIndex: 1,
498
+ zIndex: maxZIndex - 3,
496
499
  });
497
500
  this._obliqueTileLayer[overviewMapLayerSymbol] = true;
498
501
 
@@ -507,11 +510,13 @@ class OverviewMap {
507
510
  this._obliqueImageLayer = new VectorLayer({
508
511
  projection: mercatorProjection.toJSON(),
509
512
  style: obliqueImageStyle,
513
+ zIndex: maxZIndex - 2,
510
514
  });
511
515
  this._obliqueImageLayer[overviewMapLayerSymbol] = true;
512
516
  this._obliqueSelectedImageLayer = new VectorLayer({
513
517
  projection: mercatorProjection.toJSON(),
514
518
  style: this.obliqueSelectedStyle,
519
+ zIndex: maxZIndex - 1,
515
520
  });
516
521
  this._obliqueSelectedImageLayer[overviewMapLayerSymbol] = true;
517
522
  this._map.layerCollection.add(this._obliqueImageLayer);
@@ -539,7 +544,7 @@ class OverviewMap {
539
544
  if (!this._cameraIconLayer) {
540
545
  this._cameraIconLayer = new VectorLayer({
541
546
  projection: mercatorProjection.toJSON(),
542
- zIndex: 50,
547
+ zIndex: maxZIndex,
543
548
  });
544
549
  this._cameraIconLayer[overviewMapLayerSymbol] = true;
545
550
  this._map.layerCollection.add(this._cameraIconLayer);
@@ -0,0 +1,5 @@
1
+ /**
2
+ * @param {import("./uiConfig.js").default} uiConfig
3
+ * @returns {() => void}
4
+ */
5
+ export default function createSiteConfig(uiConfig: import("./uiConfig.js").default): () => void;
@@ -0,0 +1,93 @@
1
+ import { check } from '@vcsuite/check';
2
+
3
+ /**
4
+ * @param {string} src
5
+ */
6
+ function setFavicon(src) {
7
+ check(src, String);
8
+
9
+ const link = document.createElement('link');
10
+ link.className = 'vcs-favicon';
11
+ const oldLinks = document.getElementsByClassName('vcs-favicon');
12
+ const toRemove = [];
13
+ for (let i = 0; i < oldLinks.length; i++) {
14
+ toRemove.push(oldLinks.item(i));
15
+ }
16
+ toRemove.forEach((elem) => {
17
+ document.head.removeChild(elem);
18
+ });
19
+ link.id = 'dynamic-favicon';
20
+ link.rel = 'shortcut icon';
21
+ link.href = src;
22
+ document.head.appendChild(link);
23
+ }
24
+
25
+ /**
26
+ * @param {string} title
27
+ */
28
+ function setHeaderTitle(title) {
29
+ const titleElement = document.createElement('title');
30
+ titleElement.innerText = title;
31
+ const oldTitle = document.getElementsByTagName('title').item(0);
32
+ if (oldTitle) {
33
+ document.head.removeChild(oldTitle);
34
+ }
35
+ document.head.appendChild(titleElement);
36
+ }
37
+
38
+ const defaultFavicon = './assets/favicon.svg';
39
+
40
+ const defaultHeaderTitle = 'VC Map';
41
+
42
+ /**
43
+ * @param {import("./uiConfig.js").default} uiConfig
44
+ * @returns {() => void}
45
+ */
46
+ export default function createSiteConfig(uiConfig) {
47
+ if (typeof uiConfig.config.value.favicon === 'string') {
48
+ setFavicon(uiConfig.config.value.favicon);
49
+ }
50
+
51
+ if (typeof uiConfig.config.value.headerTitle === 'string') {
52
+ setHeaderTitle(uiConfig.config.value.headerTitle);
53
+ }
54
+
55
+ const updateFavicon = () => {
56
+ if (typeof uiConfig.config.value.favicon === 'string') {
57
+ setFavicon(uiConfig.config.value.favicon);
58
+ } else {
59
+ setFavicon(defaultFavicon);
60
+ }
61
+ };
62
+
63
+ const updateHeaderTitle = () => {
64
+ if (typeof uiConfig.config.value.headerTitle === 'string') {
65
+ setHeaderTitle(uiConfig.config.value.headerTitle);
66
+ } else {
67
+ setHeaderTitle(defaultHeaderTitle);
68
+ }
69
+ };
70
+
71
+ const listeners = [
72
+ uiConfig.added.addEventListener(({ name }) => {
73
+ if (name === 'favicon') {
74
+ updateFavicon();
75
+ } else if (name === 'headerTitle') {
76
+ updateHeaderTitle();
77
+ }
78
+ }),
79
+ uiConfig.removed.addEventListener(({ name }) => {
80
+ if (name === 'favicon') {
81
+ updateFavicon();
82
+ } else if (name === 'headerTitle') {
83
+ updateHeaderTitle();
84
+ }
85
+ }),
86
+ ];
87
+
88
+ return () => {
89
+ listeners.forEach((cb) => {
90
+ cb();
91
+ });
92
+ };
93
+ }
package/src/uiConfig.d.ts CHANGED
@@ -4,7 +4,7 @@ export type UiConfigurationItem<T> = {
4
4
  value: T;
5
5
  };
6
6
  export type TextPageType = {
7
- title: string;
7
+ title?: string | undefined;
8
8
  url?: string | URL | undefined;
9
9
  content?: string | undefined;
10
10
  };
@@ -38,13 +38,21 @@ export type UiConfigObject = {
38
38
  */
39
39
  helpBaseUrl?: string | undefined;
40
40
  /**
41
- * - an option imprint, will show a link in the footer.
41
+ * - an option imprint, will show a link in the footer. Default title is 'footer.imprint.title'.
42
42
  */
43
43
  imprint?: TextPageType | undefined;
44
44
  /**
45
- * - an option dataProtection, will show a link in the footer.
45
+ * - an option dataProtection, will show a link in the footer. Default title is 'footer.dataProtection.title'.
46
46
  */
47
47
  dataProtection?: TextPageType | undefined;
48
+ /**
49
+ * - the favicon to set
50
+ */
51
+ favicon?: string | undefined;
52
+ /**
53
+ * - the title to display in the tab of the browser
54
+ */
55
+ headerTitle?: string | undefined;
48
56
  };
49
57
  /**
50
58
  * @typedef {{
@@ -55,7 +63,7 @@ export type UiConfigObject = {
55
63
  */
56
64
  /**
57
65
  * @typedef {Object} TextPageType
58
- * @property {string} title
66
+ * @property {string} [title]
59
67
  * @property {URL|string} [url]
60
68
  * @property {string} [content]
61
69
  */
@@ -68,8 +76,10 @@ export type UiConfigObject = {
68
76
  * @property {boolean} [startingFeatureInfo] - an optional flag whether to activate feature info on startup (default active)
69
77
  * @property {string} [positionDisplayEventType] - mouse event, when position display is updated. Either 'click' (default) or 'move'.
70
78
  * @property {string} [helpBaseUrl='https://help.vc.systems/'] - an optional URL to a help landing page
71
- * @property {TextPageType} [imprint] - an option imprint, will show a link in the footer.
72
- * @property {TextPageType} [dataProtection] - an option dataProtection, will show a link in the footer.
79
+ * @property {TextPageType} [imprint] - an option imprint, will show a link in the footer. Default title is 'footer.imprint.title'.
80
+ * @property {TextPageType} [dataProtection] - an option dataProtection, will show a link in the footer. Default title is 'footer.dataProtection.title'.
81
+ * @property {string} [favicon] - the favicon to set
82
+ * @property {string} [headerTitle] - the title to display in the tab of the browser
73
83
  */
74
84
  /**
75
85
  * @extends {Collection<UiConfigurationItem<unknown>>}
package/src/uiConfig.js CHANGED
@@ -11,7 +11,7 @@ import { ref } from 'vue';
11
11
 
12
12
  /**
13
13
  * @typedef {Object} TextPageType
14
- * @property {string} title
14
+ * @property {string} [title]
15
15
  * @property {URL|string} [url]
16
16
  * @property {string} [content]
17
17
  */
@@ -25,8 +25,10 @@ import { ref } from 'vue';
25
25
  * @property {boolean} [startingFeatureInfo] - an optional flag whether to activate feature info on startup (default active)
26
26
  * @property {string} [positionDisplayEventType] - mouse event, when position display is updated. Either 'click' (default) or 'move'.
27
27
  * @property {string} [helpBaseUrl='https://help.vc.systems/'] - an optional URL to a help landing page
28
- * @property {TextPageType} [imprint] - an option imprint, will show a link in the footer.
29
- * @property {TextPageType} [dataProtection] - an option dataProtection, will show a link in the footer.
28
+ * @property {TextPageType} [imprint] - an option imprint, will show a link in the footer. Default title is 'footer.imprint.title'.
29
+ * @property {TextPageType} [dataProtection] - an option dataProtection, will show a link in the footer. Default title is 'footer.dataProtection.title'.
30
+ * @property {string} [favicon] - the favicon to set
31
+ * @property {string} [headerTitle] - the title to display in the tab of the browser
30
32
  */
31
33
 
32
34
  /**
package/src/vcsUiApp.d.ts CHANGED
@@ -188,6 +188,7 @@ declare class VcsUiApp extends VcsApp {
188
188
  * @type {import("@vcmap/core").VcsEvent<string>}
189
189
  */
190
190
  mounted: import("@vcmap/core").VcsEvent<string>;
191
+ _destroySiteConfig: () => void;
191
192
  /**
192
193
  * @type {import("@vcmap/core").OverrideCollection<VcsPlugin<Object, Object>>}
193
194
  */
package/src/vcsUiApp.js CHANGED
@@ -42,6 +42,7 @@ import Notifier from './notifier/notifier.js';
42
42
  import AbstractFeatureInfoView from './featureInfo/abstractFeatureInfoView.js';
43
43
  import { createVueI18n, setupI18n } from './vuePlugins/i18n.js';
44
44
  import { callbackClassRegistry } from './callback/vcsCallback.js';
45
+ import createSiteConfig from './siteConfig.js';
45
46
 
46
47
  /**
47
48
  * @typedef {import("@vcmap/core").VcsModuleConfig & {
@@ -330,6 +331,8 @@ class VcsUiApp extends VcsApp {
330
331
  * @type {import("@vcmap/core").VcsEvent<string>}
331
332
  */
332
333
  this.mounted = new VcsEvent();
334
+
335
+ this._destroySiteConfig = createSiteConfig(this._uiConfig);
333
336
  }
334
337
 
335
338
  /**
@@ -682,6 +685,7 @@ class VcsUiApp extends VcsApp {
682
685
  this._featureInfoClassRegistry.destroy();
683
686
  this._featureInfo.destroy();
684
687
  this._uiConfig.destroy();
688
+ this._destroySiteConfig();
685
689
  super.destroy();
686
690
  }
687
691
  }
@@ -1 +0,0 @@
1
- import{initAppFromAppConfig as p}from"./ui.f85ce1.js";p("#app","app.config.json");
File without changes
File without changes