@vcmap/ui 6.2.2 → 6.2.3

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 (40) hide show
  1. package/config/dev.config.json +1 -1
  2. package/dist/assets/cesium.js +1 -1
  3. package/dist/assets/{core-4cd2e30d.js → core-f4ee6bea.js} +2 -2
  4. package/dist/assets/core-workers/panoramaImageWorker.js +1 -1
  5. package/dist/assets/core.js +1 -1
  6. package/dist/assets/ol.js +1 -1
  7. package/dist/assets/{ui-b13e28a1.css → ui-d3a7bd39.css} +1 -1
  8. package/dist/assets/{ui-b13e28a1.js → ui-d3a7bd39.js} +6332 -6241
  9. package/dist/assets/ui.js +1 -1
  10. package/dist/assets/vue.js +1 -1
  11. package/dist/assets/{vuetify-a1930526.js → vuetify-8e1623b2.js} +1 -1
  12. package/dist/assets/vuetify.js +1 -1
  13. package/index.d.ts +2 -0
  14. package/index.js +1 -0
  15. package/package.json +1 -1
  16. package/src/application/VcsSettings.vue +4 -0
  17. package/src/components/flight/VcsFlightAnchorsComponent.vue +2 -2
  18. package/src/components/lists/VcsList.vue +10 -18
  19. package/src/components/lists/VcsTreeNode.vue +8 -3
  20. package/src/components/lists/VcsTreeNode.vue.d.ts +4 -0
  21. package/src/components/lists/VcsTreeview.vue +2 -6
  22. package/src/components/lists/VcsTreeview.vue.d.ts +0 -1
  23. package/src/components/lists/dragHelper.d.ts +9 -2
  24. package/src/components/lists/dragHelper.js +47 -21
  25. package/src/contentTree/LayerSwap.vue +15 -4
  26. package/src/contentTree/LayerSwap.vue.d.ts +4 -4
  27. package/src/contentTree/wmsGroupContentTreeItem.d.ts +22 -3
  28. package/src/contentTree/wmsGroupContentTreeItem.js +126 -64
  29. package/src/manager/collectionManager/CollectionComponentContent.vue +4 -4
  30. package/src/manager/collectionManager/CollectionComponentList.vue +2 -24
  31. package/src/manager/collectionManager/CollectionComponentList.vue.d.ts +0 -8
  32. package/src/state.d.ts +14 -0
  33. package/src/state.js +41 -0
  34. package/src/vcsUiApp.d.ts +9 -36
  35. package/src/vcsUiApp.js +45 -11
  36. /package/dist/assets/{cesium-b021f072.js → cesium-dcdef786.js} +0 -0
  37. /package/dist/assets/core-workers/{panoramaImageWorker.js-90c60e81.js → panoramaImageWorker.js-a6bb36f6.js} +0 -0
  38. /package/dist/assets/{ol-c927b883.js → ol-f7a5160f.js} +0 -0
  39. /package/dist/assets/{vue-6a295c0b.js → vue-cbd2bd60.js} +0 -0
  40. /package/dist/assets/{vuetify-a1930526.css → vuetify-8e1623b2.css} +0 -0
@@ -112,12 +112,13 @@ function createWMSChildContentTreeItem(
112
112
 
113
113
  /**
114
114
  * @typedef {import('./contentTreeItem.js').ContentTreeItemOptions &
115
- * { layerName: string, showWhenNotSupported?: boolean, setWMSLayersExclusive?:boolean, hideStyleSelector?:boolean, allowedWMSLayers?:string[]}} WMSGroupContentTreeItemOptions
116
- * @property {boolean} showWhenNotSupported - optional flag to show the item even if it is not supported by the activeMap.
115
+ * { layerName: string, loadOnStartup?: boolean, showWhenNotSupported?: boolean, setWMSLayersExclusive?:boolean, hideStyleSelector?:boolean, allowedWMSLayers?:string[]}} WMSGroupContentTreeItemOptions
117
116
  * @property {string} layerName - The name of the WMSLayer to show the children of.
117
+ * @property {boolean} [loadOnStartup=false] - optional flag to load the capabilities on startup, will be loaded on click otherwise. Leads to an inherent "initOpen" flag if not true.
118
+ * @property {boolean} [showWhenNotSupported=false] - optional flag to show the item even if it is not supported by the activeMap.
118
119
  * @property {boolean} [setWMSLayersExclusive=false] - Whether the WMSlayers are mutually exclusive.
119
120
  * @property {boolean} [hideStyleSelector=false] - Whether the layer style can be selected. Will add a StyleSelector action to compatible items if the Layer has more than one style.
120
- * @property {string[]} allowedWMSLayers - The list of layers to be shown, other available layers will not be shown.
121
+ * @property {string[]} [allowedWMSLayers] - The list of layers to be shown, other available layers will not be shown.
121
122
  */
122
123
 
123
124
  /**
@@ -154,7 +155,7 @@ class WMSGroupContentTreeItem extends VcsObjectContentTreeItem {
154
155
  * @param {import("../vcsUiApp.js").default} app
155
156
  */
156
157
  constructor(options, app) {
157
- super(options, app);
158
+ super({ initOpen: !options.loadOnStartup, ...options }, app);
158
159
 
159
160
  /**
160
161
  * @type {string}
@@ -162,6 +163,12 @@ class WMSGroupContentTreeItem extends VcsObjectContentTreeItem {
162
163
  */
163
164
  this._layerName = options.layerName;
164
165
 
166
+ /**
167
+ * @type {boolean}
168
+ * @private
169
+ */
170
+ this._loadOnStartup = parseBoolean(options.loadOnStartup, false);
171
+
165
172
  /**
166
173
  * @type {boolean}
167
174
  * @private
@@ -180,7 +187,7 @@ class WMSGroupContentTreeItem extends VcsObjectContentTreeItem {
180
187
  false,
181
188
  );
182
189
  // if WMSLayers should be handled exclusive, the item should handle like a NodeContentTreeItem.
183
- this.clickable = !this._setWMSLayersExclusive;
190
+ this.clickable = !this._setWMSLayersExclusive || !this._loadOnStartup;
184
191
 
185
192
  /**
186
193
  * @type {boolean}
@@ -188,9 +195,10 @@ class WMSGroupContentTreeItem extends VcsObjectContentTreeItem {
188
195
  */
189
196
  this._hideStyleSelector = parseBoolean(options.hideStyleSelector, false);
190
197
 
191
- this.state = this._setWMSLayersExclusive
192
- ? StateActionState.NONE
193
- : StateActionState.INACTIVE;
198
+ this.state =
199
+ this._setWMSLayersExclusive || !this._loadOnStartup
200
+ ? StateActionState.NONE
201
+ : StateActionState.INACTIVE;
194
202
 
195
203
  /**
196
204
  * @type {boolean}
@@ -238,6 +246,13 @@ class WMSGroupContentTreeItem extends VcsObjectContentTreeItem {
238
246
  */
239
247
  this._pauseStateChangedListener = false;
240
248
 
249
+ /**
250
+ * Flag to track if children have been loaded
251
+ * @type {boolean}
252
+ * @private
253
+ */
254
+ this._childrenLoaded = false;
255
+
241
256
  this._setup();
242
257
  }
243
258
 
@@ -421,6 +436,10 @@ class WMSGroupContentTreeItem extends VcsObjectContentTreeItem {
421
436
  this._listeners.splice(0);
422
437
  this._availableWMSEntries = [];
423
438
  this._legendSet = false;
439
+ this._childrenLoaded = false;
440
+
441
+ // Reset clickable state based on initial configuration
442
+ this.clickable = !this._setWMSLayersExclusive || !this._loadOnStartup;
424
443
  }
425
444
 
426
445
  /**
@@ -463,6 +482,83 @@ class WMSGroupContentTreeItem extends VcsObjectContentTreeItem {
463
482
  }
464
483
  }
465
484
 
485
+ /**
486
+ * Loads WMS entries and creates child items
487
+ * @returns {Promise<void>}
488
+ * @private
489
+ */
490
+ async _loadWMSChildren() {
491
+ if (this._childrenLoaded || !this._layer) {
492
+ return;
493
+ }
494
+
495
+ this.state = StateActionState.LOADING;
496
+ this.clickable = !this._setWMSLayersExclusive;
497
+
498
+ try {
499
+ const availableWMSEntries = await getWMSEntries(
500
+ this._layer.url,
501
+ this._layer.parameters,
502
+ );
503
+ // check if the layer still exists, it can happen that the layer was removed while fetching the capabilities.
504
+ if (!this._layer) {
505
+ return;
506
+ }
507
+ this._availableWMSEntries = availableWMSEntries.filter((wmsEntry) => {
508
+ return this._allowedWMSLayers
509
+ ? this._allowedWMSLayers.includes(wmsEntry.name)
510
+ : true;
511
+ });
512
+ const childItems = this._availableWMSEntries.map((wmsEntry) =>
513
+ createWMSChildContentTreeItem(
514
+ this._app,
515
+ wmsEntry,
516
+ this.name,
517
+ this._hideStyleSelector,
518
+ ),
519
+ );
520
+ childItems.forEach((childItem) => {
521
+ this._app.contentTree.add(childItem);
522
+ childItem.disabled = this.disabled;
523
+ this._listeners.push(
524
+ childItem.clickedEvent.addEventListener(() => {
525
+ this._handleChildClickedEvent(childItem);
526
+ }),
527
+ childItem.styleSelected.addEventListener((style) => {
528
+ this._handleStyleSelectedEvent(childItem, style);
529
+ }),
530
+ );
531
+ });
532
+ this._childItems = childItems;
533
+ // check if we do have a legend already configured, if yes we set a flag, that we do not need to set the legend.
534
+ if (this._layer.properties.legend) {
535
+ this._legendSet = true;
536
+ }
537
+ // we need to get the Initial State from the Layer, to set the correct State to the children.
538
+ this._setStateFromLayer();
539
+ // the layer State maybe incomplete or does not fit to the wmsGroupContentTreeItem, so we need to set the State to the Layer.
540
+ this._setState();
541
+ this._setLegend();
542
+ this._childrenLoaded = true;
543
+
544
+ // Update clickable state after children are loaded
545
+ if (!this._setWMSLayersExclusive) {
546
+ this.clickable = true;
547
+ }
548
+ } catch (e) {
549
+ // if the layer is not there it has been removed while fetching the capabilities.
550
+ if (this._layer) {
551
+ this._layer.deactivate();
552
+ this.visible = false;
553
+ this._invalid = true;
554
+ }
555
+ getLogger(this.className).error(
556
+ `An error occured while fetching the ${this._layerName} capabilities:`,
557
+ e,
558
+ );
559
+ }
560
+ }
561
+
466
562
  /**
467
563
  * @returns {Promise<void>}
468
564
  * @private
@@ -489,7 +585,6 @@ class WMSGroupContentTreeItem extends VcsObjectContentTreeItem {
489
585
  if (this._showWhenNotSupported) {
490
586
  this.disabled = !isSupported;
491
587
  }
492
- this.state = StateActionState.LOADING;
493
588
  this.setPropertiesFromObject(this._layer);
494
589
 
495
590
  this._listeners.push(
@@ -517,67 +612,18 @@ class WMSGroupContentTreeItem extends VcsObjectContentTreeItem {
517
612
  }
518
613
  }),
519
614
  );
520
- try {
521
- const availableWMSEntries = await getWMSEntries(
522
- this._layer.url,
523
- this._layer.parameters,
524
- );
525
- // check if the layer still exists, it can happen that the layer was removed while fetching the capabilities.
526
- if (!this._layer) {
527
- return;
528
- }
529
- this._availableWMSEntries = availableWMSEntries.filter((wmsEntry) => {
530
- return this._allowedWMSLayers
531
- ? this._allowedWMSLayers.includes(wmsEntry.name)
532
- : true;
533
- });
534
- const childItems = this._availableWMSEntries.map((wmsEntry) => {
535
- return createWMSChildContentTreeItem(
536
- this._app,
537
- wmsEntry,
538
- this.name,
539
- this._hideStyleSelector,
540
- );
541
- });
542
- childItems.forEach((childItem) => {
543
- this._app.contentTree.add(childItem);
544
- childItem.disabled = this.disabled;
545
- this._listeners.push(
546
- childItem.clickedEvent.addEventListener(() => {
547
- this._handleChildClickedEvent(childItem);
548
- }),
549
- childItem.styleSelected.addEventListener((style) => {
550
- this._handleStyleSelectedEvent(childItem, style);
551
- }),
552
- );
553
- });
554
- this._childItems = childItems;
555
- // check if we do have a legend already configured, if yes we set a flag, that we do not need to set the legend.
556
- if (this._layer.properties.legend) {
557
- this._legendSet = true;
558
- }
559
- // we need to get the Initial State from the Layer, to set the correct State to the children.
560
- this._setStateFromLayer();
561
- // the layer State maybe incomplete or does not fit to the wmsGroupContentTreeItem, so we need to set the State to the Layer.
562
- this._setState();
563
- this._setLegend();
564
- } catch (e) {
565
- // if the layer is not there it has been removed while fetching the capabilities.
566
- if (this._layer) {
567
- this._layer.deactivate();
568
- this.visible = false;
569
- this._invalid = true;
570
- }
571
- getLogger(this.className).error(
572
- `An error occured while fetching the ${this._layerName} capabilities:`,
573
- e,
574
- );
615
+ if (this._loadOnStartup) {
616
+ await this._loadWMSChildren();
575
617
  }
576
618
  }
577
619
  }
578
620
 
579
621
  async clicked() {
580
622
  await super.clicked();
623
+ if (!this._childrenLoaded) {
624
+ await this._loadWMSChildren();
625
+ return;
626
+ }
581
627
  if (this.state === StateActionState.NONE || this._setWMSLayersExclusive) {
582
628
  return;
583
629
  }
@@ -591,12 +637,28 @@ class WMSGroupContentTreeItem extends VcsObjectContentTreeItem {
591
637
  await this._setStateToLayer();
592
638
  }
593
639
 
640
+ /**
641
+ * Returns a readonly TreeViewItem used for rendering the current item.
642
+ * @returns {import('./contentTreeItem.js').TreeViewItem}
643
+ */
644
+ getTreeViewItem() {
645
+ const item = super.getTreeViewItem();
646
+ item.forceNodeDisplay = !this._loadOnStartup;
647
+ return item;
648
+ }
594
649
  /**
595
650
  * @returns {WMSGroupContentTreeItemOptions}
596
651
  */
597
652
  toJSON() {
598
653
  const config = super.toJSON();
599
654
  config.layerName = this._layerName;
655
+ const defaultInitOpen = !this._loadOnStartup;
656
+ if (this.initOpen !== defaultInitOpen) {
657
+ config.initOpen = this.initOpen;
658
+ }
659
+ if (this._loadOnStartup) {
660
+ config.loadOnStartup = this._loadOnStartup;
661
+ }
600
662
  if (this._showWhenNotSupported) {
601
663
  config.showWhenNotSupported = this._showWhenNotSupported;
602
664
  }
@@ -9,9 +9,9 @@
9
9
  :show-title="false"
10
10
  @item-moved="move"
11
11
  />
12
- <v-sheet v-if="page && pageSize && totalCount && items.length !== 0">
12
+ <v-sheet v-if="page && pageSize && totalCount > pageSize">
13
13
  <v-pagination
14
- class="px-2"
14
+ class="px-4"
15
15
  v-model="page"
16
16
  :length="Math.ceil(totalCount / pageSize)"
17
17
  density="compact"
@@ -35,7 +35,7 @@
35
35
  import { createSelectionActions } from '../../components/lists/listHelper.js';
36
36
  import VcsList from '../../components/lists/VcsList.vue';
37
37
  import VcsButton from '../../components/buttons/VcsButton.vue';
38
- import { moveItem } from './CollectionComponentList.vue';
38
+ import { moveItem } from '../../components/lists/dragHelper.js';
39
39
 
40
40
  /**
41
41
  * @description
@@ -137,7 +137,7 @@
137
137
  return actions.value;
138
138
  }),
139
139
  move(event) {
140
- moveItem(collectionComponent, event);
140
+ moveItem(collectionComponent.collection, event);
141
141
  },
142
142
  openCollectionComponentList() {
143
143
  emit('openList', collectionComponent.id);
@@ -36,34 +36,12 @@
36
36
 
37
37
  <script>
38
38
  import { computed, inject } from 'vue';
39
- import { IndexedCollection } from '@vcmap/core';
40
39
  import { VSheet } from 'vuetify/components';
41
40
  import { createSelectionActions } from '../../components/lists/listHelper.js';
42
41
  import VcsList from '../../components/lists/VcsList.vue';
43
42
  import VcsActionButtonList from '../../components/buttons/VcsActionButtonList.vue';
44
43
  import VcsButton from '../../components/buttons/VcsButton.vue';
45
-
46
- /**
47
- * Moves an item to a new position.
48
- * New position is derived from a target item in the collection.
49
- * This ensures correct movement, if rendered list is only a subset of the collection.
50
- * @param {import("./collectionComponentClass.js").default<Object>} collectionComponent
51
- * @param {import("../../components/lists/dragHelper.js").ItemMovedEvent} event
52
- */
53
- export function moveItem(
54
- collectionComponent,
55
- { item, targetItem, position },
56
- ) {
57
- const { collection } = collectionComponent;
58
- if (collection instanceof IndexedCollection) {
59
- const collectionItem = collection.getByKey(item.name);
60
- const keyProperty = collection.uniqueKey;
61
- const targetIndexCol = [...collection].findIndex(
62
- (i) => i[keyProperty] === targetItem.name,
63
- );
64
- collection.moveTo(collectionItem, targetIndexCol + position);
65
- }
66
- }
44
+ import { moveItem } from '../../components/lists/dragHelper.js';
67
45
 
68
46
  /**
69
47
  * @description
@@ -124,7 +102,7 @@
124
102
  return actions.value;
125
103
  }),
126
104
  move(event) {
127
- moveItem(collectionComponent, event);
105
+ moveItem(collectionComponent.collection, event);
128
106
  },
129
107
  closeList() {
130
108
  emit('closeList', collectionComponent.id);
@@ -1,11 +1,3 @@
1
- /**
2
- * Moves an item to a new position.
3
- * New position is derived from a target item in the collection.
4
- * This ensures correct movement, if rendered list is only a subset of the collection.
5
- * @param {import("./collectionComponentClass.js").default<Object>} collectionComponent
6
- * @param {import("../../components/lists/dragHelper.js").ItemMovedEvent} event
7
- */
8
- export function moveItem(collectionComponent: import("./collectionComponentClass.js").default<Object>, { item, targetItem, position }: import("../../components/lists/dragHelper.js").ItemMovedEvent): void;
9
1
  declare const _default: import("vue").DefineComponent<{
10
2
  showLessButton: {
11
3
  type: BooleanConstructor;
package/src/state.d.ts CHANGED
@@ -14,6 +14,20 @@ export function parseUrlProjectedViewpointState(state: UrlViewpointState, module
14
14
  * @returns {import("@vcmap/core").ViewpointOptions|null}
15
15
  */
16
16
  export function parseUrlExtentState(state: UrlExtentState, moduleId: string): import("@vcmap/core").ViewpointOptions | null;
17
+ /**
18
+ * @param {string} style
19
+ * @returns {{layers: string, styles: string}}
20
+ */
21
+ export function parseWMSStyle(style: string): {
22
+ layers: string;
23
+ styles: string;
24
+ };
25
+ /**
26
+ * @param {import("@vcmap/core").WMSLayer} layer
27
+ * @param {import("@vcmap/core").VcsModuleConfig=} moduleConfig
28
+ * @returns {string|undefined}
29
+ */
30
+ export function writeWMSStyleForLayer(layer: import("@vcmap/core").WMSLayer, moduleConfig?: import("@vcmap/core").VcsModuleConfig | undefined): string | undefined;
17
31
  /**
18
32
  * @param {(URL)=} url
19
33
  * @returns {AppState}
package/src/state.js CHANGED
@@ -203,6 +203,47 @@ export function parseUrlExtentState(state, moduleId) {
203
203
  }
204
204
  }
205
205
 
206
+ /**
207
+ * @param {string} style
208
+ * @returns {{layers: string, styles: string}}
209
+ */
210
+ export function parseWMSStyle(style) {
211
+ const [layerLengthString, parts] = style.split(';');
212
+ const layerLength = parseInt(layerLengthString, 10);
213
+ return {
214
+ layers: parts.substring(0, layerLength),
215
+ styles: parts.substring(layerLength),
216
+ };
217
+ }
218
+
219
+ /**
220
+ * @param {import("@vcmap/core").WMSLayer} layer
221
+ * @param {import("@vcmap/core").VcsModuleConfig=} moduleConfig
222
+ * @returns {string|undefined}
223
+ */
224
+ export function writeWMSStyleForLayer(layer, moduleConfig) {
225
+ const config = moduleConfig?.layers?.find((m) => m.name === layer.name) ?? {
226
+ layers: '',
227
+ parameters: {},
228
+ };
229
+ let currentLayers = layer.getLayers().join(',');
230
+ if (currentLayers === config.layers) {
231
+ currentLayers = '';
232
+ }
233
+
234
+ let currentStyle = layer.parameters.STYLES || '';
235
+ if (
236
+ currentStyle === config.parameters.STYLES ||
237
+ currentStyle === config.parameters.styles
238
+ ) {
239
+ currentStyle = '';
240
+ }
241
+ if (currentLayers || currentStyle) {
242
+ return `${currentLayers.length};${currentLayers}${currentStyle}`;
243
+ }
244
+ return undefined;
245
+ }
246
+
206
247
  /**
207
248
  * @param {UrlLayerState} state
208
249
  * @returns {LayerState}
package/src/vcsUiApp.d.ts CHANGED
@@ -256,7 +256,10 @@ declare class VcsUiApp extends VcsApp {
256
256
  defaults: import("vue").Ref<import("vuetify").DefaultsInstance>;
257
257
  display: import("vuetify").DisplayInstance;
258
258
  theme: import("vuetify").ThemeInstance & {
259
- install: (app: import("vue").App<any>) => void;
259
+ install: (app: import("vue").App<any>) => void; /**
260
+ * @type {WindowManager}
261
+ * @private
262
+ */
260
263
  };
261
264
  icons: {
262
265
  defaultSet: string;
@@ -282,33 +285,7 @@ declare class VcsUiApp extends VcsApp {
282
285
  formats?: any;
283
286
  }) => import("vuetify").DateInstance) | import("vuetify").DateInstance;
284
287
  formats?: Record<string, any> | undefined;
285
- locale: Record<string, any>; /**
286
- * Interface for VcsPlugins.
287
- * The function implementing the interface should not throw!
288
- * @typedef {{
289
- * name: string,
290
- * version: string,
291
- * mapVersion: string,
292
- * i18n?: Object<string, unknown>,
293
- * initialize?: function(import("@src/vcsUiApp.js").default, S=):void|Promise<void>,
294
- * onVcsAppMounted?: function(import("@src/vcsUiApp.js").default):void,
295
- * toJSON?: function(): C,
296
- * getDefaultOptions?: function(): C,
297
- * getState?: function(boolean=):S|Promise<S>,
298
- * getConfigEditors?: function():Array<PluginConfigEditor<object>>,
299
- * destroy?: function(): void
300
- * }} VcsPlugin
301
- * @template {Object} C - plugin config
302
- * @template {Object} S - plugin state
303
- * @property {Object<string, *>} [i18n] - the i18n messages of this plugin
304
- * @property {function(import("@src/vcsUiApp.js").default, S=)} initialize - called on plugin added. Is passed the VcsUiApp and optionally, the state for the plugin
305
- * @property {function(import("@src/vcsUiApp.js").default)} onVcsAppMounted - called on mounted of VcsApp.vue
306
- * @property {function():C} [toJSON] - should return the plugin's serialization excluding all default values
307
- * @property {function():C} [getDefaultOptions] - should return the plugin's default options
308
- * @property {function(boolean=):S|Promise<S>} [getState] - should return the plugin's state or a promise for said state. is passed a "for url" flag. If true, only the state relevant for sharing a URL should be passed and short keys shall be used
309
- * @property {Array<PluginConfigEditor>} [getConfigEditors] - should return components for configuring the plugin or custom items defined by the plugin
310
- * @api
311
- */
288
+ locale: Record<string, any>;
312
289
  };
313
290
  instance: {
314
291
  locale?: any;
@@ -323,10 +300,6 @@ declare class VcsUiApp extends VcsApp {
323
300
  endOfWeek: (date: unknown) => unknown;
324
301
  startOfMonth: (date: unknown) => unknown;
325
302
  endOfMonth: (date: unknown) => unknown;
326
- /**
327
- * @type {ContextMenuManager}
328
- * @private
329
- */
330
303
  startOfYear: (date: unknown) => unknown;
331
304
  endOfYear: (date: unknown) => unknown;
332
305
  isAfter: (date: unknown, comparing: unknown) => boolean;
@@ -348,9 +321,7 @@ declare class VcsUiApp extends VcsApp {
348
321
  getDiff: (date: unknown, comparing: unknown, unit?: string | undefined) => number;
349
322
  getWeekArray: (date: unknown, firstDayOfWeek?: string | number | undefined) => unknown[][];
350
323
  getWeekdays: (firstDayOfWeek?: string | number | undefined) => string[];
351
- getMonth: (date: unknown) => number; /**
352
- * @type {import("@vcmap/core").OverrideClassRegistry<typeof AbstractFeatureInfoView>}
353
- */
324
+ getMonth: (date: unknown) => number;
354
325
  setMonth: (date: unknown, month: number) => unknown;
355
326
  getDate: (date: unknown) => number;
356
327
  setDate: (date: unknown, day: number) => unknown;
@@ -358,7 +329,9 @@ declare class VcsUiApp extends VcsApp {
358
329
  getPreviousMonth: (date: unknown) => unknown;
359
330
  getHours: (date: unknown) => number;
360
331
  setHours: (date: unknown, hours: number) => unknown;
361
- getMinutes: (date: unknown) => number;
332
+ getMinutes: (date: unknown) => number; /**
333
+ * @returns {PanelManager}
334
+ */
362
335
  setMinutes: (date: unknown, minutes: number) => unknown;
363
336
  };
364
337
  };
package/src/vcsUiApp.js CHANGED
@@ -11,6 +11,7 @@ import {
11
11
  VcsEvent,
12
12
  Viewpoint,
13
13
  volatileModuleId,
14
+ WMSLayer,
14
15
  } from '@vcmap/core';
15
16
  import { getLogger as getLoggerByName } from '@vcsuite/logger';
16
17
  import { deserializePlugin, serializePlugin } from './pluginHelper.js';
@@ -36,7 +37,12 @@ import FeatureInfo, {
36
37
  featureInfoClassRegistry,
37
38
  } from './featureInfo/featureInfo.js';
38
39
  import UiConfig from './uiConfig.js';
39
- import { createEmptyState, getStateFromURL } from './state.js';
40
+ import {
41
+ createEmptyState,
42
+ getStateFromURL,
43
+ parseWMSStyle,
44
+ writeWMSStyleForLayer,
45
+ } from './state.js';
40
46
  import { version } from '../package.json';
41
47
  import Search from './search/search.js';
42
48
  import Notifier from './notifier/notifier.js';
@@ -557,9 +563,17 @@ class VcsUiApp extends VcsApp {
557
563
  */
558
564
  async getState(forUrl) {
559
565
  const state = createEmptyState();
560
- state.moduleIds = this.modules
561
- .filter(({ _id }) => _id !== defaultDynamicModuleId)
562
- .map(({ _id }) => _id);
566
+ const nonDynamicModules = this.modules.filter(
567
+ ({ _id }) => _id !== defaultDynamicModuleId,
568
+ );
569
+
570
+ if (nonDynamicModules.some((m) => !m.config._id)) {
571
+ getLogger().warning(
572
+ 'Some modules you are creating are missing a stable _id property. This may lead to issues while restoring application state.',
573
+ );
574
+ }
575
+
576
+ state.moduleIds = nonDynamicModules.map(({ _id }) => _id);
563
577
 
564
578
  state.activeMap = this.maps.activeMap.name;
565
579
  const viewpoint = await this.maps.activeMap.getViewpoint();
@@ -591,6 +605,12 @@ class VcsUiApp extends VcsApp {
591
605
  l.style[moduleIdSymbol] !== volatileModuleId
592
606
  ) {
593
607
  layerState.styleName = l.style.name;
608
+ } else if (l instanceof WMSLayer) {
609
+ const module = this.getModuleById(l[moduleIdSymbol]);
610
+ const styleName = writeWMSStyleForLayer(l, module?.config);
611
+ if (styleName) {
612
+ layerState.styleName = styleName;
613
+ }
594
614
  }
595
615
  return layerState;
596
616
  });
@@ -642,6 +662,11 @@ class VcsUiApp extends VcsApp {
642
662
  */
643
663
  async _parseModule(module) {
644
664
  const { config } = module;
665
+ if (!config._id) {
666
+ getLogger().warning(
667
+ 'A module is missing a stable _id property. This may lead to issues while restoring application state.',
668
+ );
669
+ }
645
670
  if (Array.isArray(config.plugins)) {
646
671
  await this._plugins.parseItems(config.plugins, module._id);
647
672
  }
@@ -667,7 +692,7 @@ class VcsUiApp extends VcsApp {
667
692
  if (layer) {
668
693
  if (layerState.active) {
669
694
  layer.activate().catch((e) => {
670
- getLogger().warn(
695
+ getLogger().warning(
671
696
  'Failed to activate cached app state. layer failed: ',
672
697
  layer.name,
673
698
  );
@@ -677,12 +702,21 @@ class VcsUiApp extends VcsApp {
677
702
  layer.deactivate();
678
703
  }
679
704
 
680
- if (
681
- layerState.styleName &&
682
- this.styles.hasKey(layerState.styleName) &&
683
- layer.setStyle
684
- ) {
685
- layer.setStyle(this.styles.getByKey(layerState.styleName));
705
+ if (layerState.styleName) {
706
+ if (this.styles.hasKey(layerState.styleName) && layer.setStyle) {
707
+ layer.setStyle(this.styles.getByKey(layerState.styleName));
708
+ } else if (layer instanceof WMSLayer) {
709
+ const { layers, styles } = parseWMSStyle(layerState.styleName);
710
+ if (styles) {
711
+ layer.parameters.STYLES = styles;
712
+ }
713
+ layer.setLayers(layers || layer.getLayers()).catch((err) => {
714
+ getLogger().warning(
715
+ `Failed to set WMS layers ${layers} on layer ${layer.name}`,
716
+ err,
717
+ );
718
+ });
719
+ }
686
720
  }
687
721
  }
688
722
  });
File without changes