@geogirafe/lib-geoportal 1.2.0-dev.2845014898 → 1.2.0-dev.2847659248

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.
@@ -120,6 +120,7 @@ export default class Map2dComponent extends GirafeHTMLElement {
120
120
  onChangeOrder: () => void;
121
121
  private reorderLayers;
122
122
  private onChangeLayerOpacity;
123
+ private setOpacityRecursively;
123
124
  private onChangeBasemapOpacity;
124
125
  /**
125
126
  * Change filter configuration on layer (only LayerWMS are affected)
@@ -660,10 +660,25 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
660
660
  else if (layerInfos instanceof LayerOsm) {
661
661
  this.osmManager.changeOpacity(layerInfos);
662
662
  }
663
+ else if (layerInfos instanceof GroupLayer) {
664
+ this.context.stateManager.batchChanges(() => {
665
+ this.setOpacityRecursively(layerInfos.opacity, layerInfos);
666
+ });
667
+ }
663
668
  else {
664
669
  console.warn(`Changing opacity for layer ${layerInfos.name} of type ${typeof layerInfos} not supported`);
665
670
  }
666
671
  }
672
+ setOpacityRecursively(opacity, layer) {
673
+ if (layer instanceof Layer) {
674
+ layer.opacity = opacity;
675
+ }
676
+ else if (layer instanceof GroupLayer) {
677
+ for (const childLayer of layer.children) {
678
+ this.setOpacityRecursively(opacity, childLayer);
679
+ }
680
+ }
681
+ }
667
682
  onChangeBasemapOpacity(basemap) {
668
683
  applyOpacityToLayers(basemap.opacity, basemap.layersList, (layer) => this.onChangeLayerOpacity(layer));
669
684
  }
@@ -10,6 +10,7 @@ export default abstract class TreeViewElement extends GirafeHTMLElement {
10
10
  constructor(layer: BaseLayer, name: string);
11
11
  protected connectedCallback(): void;
12
12
  render(): void;
13
+ protected isSameLayerObject(layer: BaseLayer): boolean;
13
14
  private highlight;
14
15
  refreshRender(): void;
15
16
  refreshRender(layer?: BaseLayer): void;
@@ -22,6 +23,7 @@ export default abstract class TreeViewElement extends GirafeHTMLElement {
22
23
  private setDragStyle;
23
24
  getButtonClass(button: string): string;
24
25
  protected createTimeRestrictionTooltip(layer: TimeAwareLayer): void;
26
+ protected createOpacityTooltip(): void;
25
27
  protected removeFromParent(): void;
26
28
  private static removeLayerFromParent;
27
29
  }
@@ -6,6 +6,8 @@ import tippy from 'tippy.js';
6
6
  import TimeRestrictionComponent from '../../timerestriction/component.js';
7
7
  import LayerWms from '../../../models/layers/layerwms.js';
8
8
  import Layer from '../../../models/layers/layer.js';
9
+ import Grouplayer from '../../../models/layers/grouplayer.js';
10
+ import LayerGroup from 'ol/layer/Group.js';
9
11
  export default class TreeViewElement extends GirafeHTMLElement {
10
12
  dragManager;
11
13
  layer;
@@ -31,11 +33,16 @@ export default class TreeViewElement extends GirafeHTMLElement {
31
33
  this.createTimeRestrictionTooltip(this.layer);
32
34
  }
33
35
  this.subscribe(/layers\.layersList\..*\.isHighlighted/, (_oldValue, newValue, layer) => {
34
- if (newValue && layer === this.layer) {
36
+ if (!this.isSameLayerObject(layer))
37
+ return;
38
+ if (newValue) {
35
39
  this.highlight();
36
40
  }
37
41
  });
38
42
  }
43
+ isSameLayerObject(layer) {
44
+ return layer === this.layer;
45
+ }
39
46
  highlight() {
40
47
  this.header.scrollIntoView({
41
48
  behavior: 'smooth',
@@ -117,7 +124,14 @@ export default class TreeViewElement extends GirafeHTMLElement {
117
124
  }
118
125
  return 'hidden';
119
126
  case 'opacity':
120
- if (!this.layer.inactive && this.layer instanceof Layer) {
127
+ if (this.layer.inactive) {
128
+ return 'hidden';
129
+ }
130
+ if (this.layer instanceof Layer) {
131
+ return this.layer.opacity < 1 ? activeButtonClasses : buttonClasses;
132
+ }
133
+ // Allow opacity on group-layer of the 1st level only.
134
+ if (this.layer instanceof Grouplayer && this.layer.isFirstLevelGroup()) {
121
135
  return this.layer.opacity < 1 ? activeButtonClasses : buttonClasses;
122
136
  }
123
137
  return 'hidden';
@@ -181,6 +195,36 @@ export default class TreeViewElement extends GirafeHTMLElement {
181
195
  }
182
196
  });
183
197
  }
198
+ createOpacityTooltip() {
199
+ if (!(this.layer instanceof Layer || (this.layer instanceof Grouplayer && this.layer.isFirstLevelGroup()))) {
200
+ console.warn('Opacity tooltip can only be created for Layer or 1st level LayerGroup');
201
+ return;
202
+ }
203
+ const layer = this.layer || LayerGroup;
204
+ const el = this.shadow.getElementById('opacity');
205
+ if (!el) {
206
+ return;
207
+ }
208
+ tippy(el, {
209
+ trigger: 'click',
210
+ arrow: true,
211
+ interactive: true,
212
+ theme: 'light',
213
+ placement: 'right',
214
+ content: (_reference) => {
215
+ const slider = document.createElement('input');
216
+ slider.type = 'range';
217
+ slider.className = 'gg-range';
218
+ slider.min = '0';
219
+ slider.max = '20';
220
+ slider.value = (layer.opacity * 20).toString();
221
+ slider.oninput = () => {
222
+ layer.opacity = Number.parseInt(slider.value) / 20;
223
+ };
224
+ return slider;
225
+ }
226
+ });
227
+ }
184
228
  removeFromParent() {
185
229
  TreeViewElement.removeLayerFromParent(this.layer, this.state);
186
230
  }
@@ -13,7 +13,7 @@ header{border-top:1px solid #ddd;align-items:center;height:2rem;display:flex}.to
13
13
  .hidden{display:none!important}.gg-rotate90{transform:rotate(90deg)}.gg-rotate180{transform:rotate(180deg)}.gg-rotate270{transform:rotate(270deg)}img{filter:var(--svg-filter)}img.legend-image{filter:var(--svg-map-filter);background:var(--svg-legend-bkg)}div{scrollbar-width:thin}a,a:visited{color:var(--link-color)}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes spin-wait{0%{transform:rotate(0)}7%{transform:rotate(360deg)}to{transform:rotate(360deg)}}.gg-spin{animation-name:spin;animation-duration:2s;animation-timing-function:linear;animation-iteration-count:infinite}.gg-spin-wait{animation-name:spin-wait;animation-duration:10s;animation-timing-function:linear;animation-iteration-count:infinite}::-webkit-scrollbar{width:5px}::-webkit-scrollbar-thumb{background:#999}button,input,select,textarea{font:inherit}.gg-button,.gg-select,.gg-input,.gg-textarea{background-color:var(--bkg-color);color:var(--text-color);border:var(--app-standard-border);box-sizing:border-box;cursor:pointer;border-radius:3px;outline:0;margin:0;padding:0 0 0 .5rem;display:inline-block}.gg-label{background-color:var(--bkg-color);color:var(--text-color);border:none;align-items:center;margin:0;padding:0;display:flex}.gg-button,.gg-select,.gg-input,.gg-label{min-height:calc(var(--app-standard-height) / 1.5)}.gg-textarea{max-height:initial;resize:vertical;height:6rem;padding:.5rem;line-height:1.3rem}.gg-input{cursor:text}.gg-checkbox{accent-color:var(--text-color);cursor:pointer;width:1.2rem}.gg-range{accent-color:var(--text-color)}.gg-button{padding:0 .5rem}.gg-button.active{border:solid 1px var(--text-color-grad1);background-color:var(--bkg-color-grad2)}.gg-button:disabled{background-color:var(--bkg-color-grad1);color:var(--text-color-grad2);cursor:not-allowed;border:none}.gg-button:disabled img{filter:opacity(.6)}.gg-input:disabled,.gg-select:disabled,.gg-textarea:disabled{background-color:var(--bkg-color-grad1);color:var(--text-color-grad2);cursor:not-allowed}.gg-button>img{vertical-align:middle}.gg-icon-button{color:var(--text-color);cursor:pointer;background-color:#0000;border:none;flex-direction:column;justify-content:center;align-items:center;padding:0;display:flex}.gg-icon{justify-content:center;align-items:center;display:flex}.gg-big,.gg-big-withtext{min-width:var(--app-standard-height);min-height:var(--app-standard-height);max-height:var(--app-standard-height)}.gg-big img,.gg-big-withtext img{width:calc(var(--app-standard-height) - 1.5rem);margin:0}.gg-big-withtext span{font-variant:small-caps;padding:0 1rem;font-size:.9rem}.gg-medium,.gg-medium-withtext{min-width:calc(var(--app-standard-height) / 1.2);min-height:calc(var(--app-standard-height) / 1.2);max-height:calc(var(--app-standard-height) / 1.2);flex-direction:row}.gg-medium img{width:calc(var(--app-standard-height) / 2.4);margin:0}.gg-medium-withtext img{width:calc(var(--app-standard-height) / 2.4);margin-left:.5rem}.gg-medium-withtext span{padding:0 1rem 0 .5rem;font-size:.9rem}.gg-small,.gg-small-withtext{min-width:calc(var(--app-standard-height) / 2);min-height:calc(var(--app-standard-height) / 2);max-height:calc(var(--app-standard-height) / 2);flex-direction:row}.gg-small img{width:calc(var(--app-standard-height) / 3);margin:0}.gg-small-withtext img{width:calc(var(--app-standard-height) / 3);margin-left:.5rem}.gg-small-withtext span{padding:0 .5rem 0 .3rem;font-size:.9rem}.gg-button:hover:not(:disabled),.gg-select:hover:not(:disabled),.gg-input:hover:not(:disabled),.gg-textarea:hover:not(:disabled),.gg-icon-button:hover:not(:disabled){background-color:var(--bkg-color-grad1)}.gg-opacity{opacity:.5}.gg-opacity:hover{opacity:1;background-color:#0000}.gg-tabs{cursor:pointer;grid-auto-flow:column;padding-bottom:1rem;font-size:1rem;display:grid}.gg-tab{border:none;border-bottom:var(--app-standard-border);cursor:pointer;color:var(--text-color);background:0 0;padding:.5rem}.gg-tab.active{border-bottom:solid 1px var(--text-color)}.girafe-button-big,.girafe-button-large,.girafe-button-small,.girafe-button-tiny{color:var(--text-color);background-color:#0000;border:none;flex-direction:column;display:flex}.girafe-button-big:hover,.girafe-button-large:hover,.girafe-button-small:hover,.girafe-button-tiny:hover{background-color:var(--bkg-color-grad1);cursor:pointer}.girafe-button-big.dark,.girafe-button-large.dark,.girafe-button-small.dark,.girafe-button-tiny.dark{background-color:var(--bkg-color);filter:invert()}.girafe-button-big{width:var(--app-standard-height);height:var(--app-standard-height);align-items:center;padding:1rem}.girafe-button-big img{overflow:hidden}.girafe-button-large{flex-direction:row}.girafe-button-large img{height:2rem;margin:.3rem}.girafe-button-large span{height:2rem;margin:.3rem;line-height:2rem}.girafe-button-small{min-width:calc(var(--app-standard-height) / 2);height:calc(var(--app-standard-height) / 2);align-items:center;padding:.5rem}.girafe-button-small img{overflow:hidden}.girafe-button-small span{text-align:left;text-overflow:ellipsis;width:100%;overflow:hidden}.girafe-button-tiny{align-items:center;width:1rem;height:1rem;padding:0}.girafe-button-tiny img{overflow:hidden}.girafe-onboarding-theme{background-color:var(--bkg-color)!important;color:var(--text-color)!important}.girafe-onboarding-theme button{background-color:var(--bkg-color)!important;color:var(--text-color)!important;text-shadow:none!important}.girafe-onboarding-theme button.driver-popover-close-btn{z-index:10000}.tippy-box{background-color:var(--bkg-color)!important;border:var(--app-standard-border)!important}.tippy-content{color:var(--text-color)!important}.tippy-arrow{color:var(--bkg-color)!important}.tippy-box[data-theme~=error]{background-color:var(--error-color);white-space:pre-line}div.tippy-box[data-theme=image-popup]{border:var(--app-standard-border)!important;& div.tippy-content{background-color:var(--bkg-color)!important;& img{max-width:20rem;max-height:20rem}}& div.tippy-arrow{color:var(--bkg-color)!important}}
14
14
  </style>
15
15
  <style>${this.customStyle}</style>
16
- <link rel="stylesheet" href="lib/tippy.js/tippy.css"><link rel="stylesheet" href="lib/tippy.js/backdrop.css"><link rel="stylesheet" href="lib/tippy.js/border.css"><link rel="stylesheet" href="lib/tippy.js/svg-arrow.css"><div id="container"><header><button class="gg-icon-button gg-small gg-opacity" tip="Expand / Collapse" onclick="${() => this.layer.isExpanded = !this.layer.isExpanded}"><img class="${this.layer.isExpanded ? 'gg-rotate90 gg-caret' : 'gg-caret'}" alt="Expand/Collapse button" src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8bWFzayBpZD0ibWFzazBfMTM2XzY5NTIiIHN0eWxlPSJtYXNrLXR5cGU6YWxwaGEiIG1hc2tVbml0cz0idXNlclNwYWNlT25Vc2UiIHg9IjAiIHk9IjAiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCI+CiAgPHJlY3Qgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiBmaWxsPSIjRDlEOUQ5Ii8+CiAgPC9tYXNrPgogIDxnIG1hc2s9InVybCgjbWFzazBfMTM2XzY5NTIpIj4KICA8cGF0aCBkPSJNMTAuNSAxNi4zQzEwLjM2NjcgMTYuMyAxMC4yNSAxNi4yNTQyIDEwLjE1IDE2LjE2MjVDMTAuMDUgMTYuMDcwOCAxMCAxNS45NSAxMCAxNS44VjguMjAwMDFDMTAgOC4wNTAwMSAxMC4wNSA3LjkyOTE4IDEwLjE1IDcuODM3NTFDMTAuMjUgNy43NDU4NSAxMC4zNjY3IDcuNzAwMDEgMTAuNSA3LjcwMDAxQzEwLjUzMzMgNy43MDAwMSAxMC42NSA3Ljc1MDAxIDEwLjg1IDcuODUwMDFMMTQuNDc1IDExLjQ3NUMxNC41NTgzIDExLjU1ODMgMTQuNjE2NyAxMS42NDE3IDE0LjY1IDExLjcyNUMxNC42ODMzIDExLjgwODMgMTQuNyAxMS45IDE0LjcgMTJDMTQuNyAxMi4xIDE0LjY4MzMgMTIuMTkxNyAxNC42NSAxMi4yNzVDMTQuNjE2NyAxMi4zNTgzIDE0LjU1ODMgMTIuNDQxNyAxNC40NzUgMTIuNTI1TDEwLjg1IDE2LjE1QzEwLjggMTYuMiAxMC43NDU4IDE2LjIzNzUgMTAuNjg3NSAxNi4yNjI1QzEwLjYyOTIgMTYuMjg3NSAxMC41NjY3IDE2LjMgMTAuNSAxNi4zWiIgZmlsbD0iIzFDMUIxRiIvPgogIDwvZz4KPC9zdmc+CiAg"></button> <button class="${this.layer.activeState === 'on' ? 'gg-icon-button gg-small gg-selected' : 'gg-icon-button gg-small gg-opacity'}" tip="Activate / Deactivate" onclick="${() => this.toggle()}"><img class="${this.layer.activeState === 'on' ? 'gg-checkbox' : 'hidden'}" alt="Expand/Collapse button" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NDggNTEyIj48IS0tIUZvbnQgQXdlc29tZSBGcmVlIDYuNi4wIGJ5IEBmb250YXdlc29tZSAtIGh0dHBzOi8vZm9udGF3ZXNvbWUuY29tIExpY2Vuc2UgLSBodHRwczovL2ZvbnRhd2Vzb21lLmNvbS9saWNlbnNlL2ZyZWUgQ29weXJpZ2h0IDIwMjQgRm9udGljb25zLCBJbmMuLS0+PHBhdGggZD0iTTY0IDMyQzI4LjcgMzIgMCA2MC43IDAgOTZMMCA0MTZjMCAzNS4zIDI4LjcgNjQgNjQgNjRsMzIwIDBjMzUuMyAwIDY0LTI4LjcgNjQtNjRsMC0zMjBjMC0zNS4zLTI4LjctNjQtNjQtNjRMNjQgMzJ6TTMzNyAyMDlMMjA5IDMzN2MtOS40IDkuNC0yNC42IDkuNC0zMy45IDBsLTY0LTY0Yy05LjQtOS40LTkuNC0yNC42IDAtMzMuOXMyNC42LTkuNCAzMy45IDBsNDcgNDdMMzAzIDE3NWM5LjQtOS40IDI0LjYtOS40IDMzLjkgMHM5LjQgMjQuNiAwIDMzLjl6Ii8+PC9zdmc+"> <img class="${this.layer.activeState === 'semi' ? 'gg-checkbox' : 'hidden'}" alt="Expand/Collapse button" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NDggNTEyIj48IS0tIUZvbnQgQXdlc29tZSBGcmVlIDYuNi4wIGJ5IEBmb250YXdlc29tZSAtIGh0dHBzOi8vZm9udGF3ZXNvbWUuY29tIExpY2Vuc2UgLSBodHRwczovL2ZvbnRhd2Vzb21lLmNvbS9saWNlbnNlL2ZyZWUgQ29weXJpZ2h0IDIwMjQgRm9udGljb25zLCBJbmMuLS0+PHBhdGggZD0iTTY0IDgwYy04LjggMC0xNiA3LjItMTYgMTZsMCAzMjBjMCA4LjggNy4yIDE2IDE2IDE2bDMyMCAwYzguOCAwIDE2LTcuMiAxNi0xNmwwLTMyMGMwLTguOC03LjItMTYtMTYtMTZMNjQgODB6TTAgOTZDMCA2MC43IDI4LjcgMzIgNjQgMzJsMzIwIDBjMzUuMyAwIDY0IDI4LjcgNjQgNjRsMCAzMjBjMCAzNS4zLTI4LjcgNjQtNjQgNjRMNjQgNDgwYy0zNS4zIDAtNjQtMjguNy02NC02NEwwIDk2ek0zMzcgMjA5TDIwOSAzMzdjLTkuNCA5LjQtMjQuNiA5LjQtMzMuOSAwbC02NC02NGMtOS40LTkuNC05LjQtMjQuNiAwLTMzLjlzMjQuNi05LjQgMzMuOSAwbDQ3IDQ3TDMwMyAxNzVjOS40LTkuNCAyNC42LTkuNCAzMy45IDBzOS40IDI0LjYgMCAzMy45eiIvPjwvc3ZnPg=="> <img class="${this.layer.activeState === 'off' ? 'gg-checkbox' : 'hidden'}" alt="Expand/Collapse button" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NDggNTEyIj48IS0tIUZvbnQgQXdlc29tZSBGcmVlIDYuNi4wIGJ5IEBmb250YXdlc29tZSAtIGh0dHBzOi8vZm9udGF3ZXNvbWUuY29tIExpY2Vuc2UgLSBodHRwczovL2ZvbnRhd2Vzb21lLmNvbS9saWNlbnNlL2ZyZWUgQ29weXJpZ2h0IDIwMjQgRm9udGljb25zLCBJbmMuLS0+PHBhdGggZD0iTTM4NCA4MGM4LjggMCAxNiA3LjIgMTYgMTZsMCAzMjBjMCA4LjgtNy4yIDE2LTE2IDE2TDY0IDQzMmMtOC44IDAtMTYtNy4yLTE2LTE2TDQ4IDk2YzAtOC44IDcuMi0xNiAxNi0xNmwzMjAgMHpNNjQgMzJDMjguNyAzMiAwIDYwLjcgMCA5NkwwIDQxNmMwIDM1LjMgMjguNyA2NCA2NCA2NGwzMjAgMGMzNS4zIDAgNjQtMjguNyA2NC02NGwwLTMyMGMwLTM1LjMtMjguNy02NC02NC02NEw2NCAzMnoiLz48L3N2Zz4="></button> <button class="${this.layer.hasError ? 'gg-icon-button gg-small gg-opacity' : 'hidden'}" tip="Error on layer"><img alt="Error on layer" src="icons/error.svg"></button><div class="label-container"><button class="${this.layer.activeState === 'on' ? 'gg-icon-button gg-small gg-selected' : 'gg-icon-button gg-small gg-opacity'}" onclick="${() => this.toggle()}"><span i18n="${this.layer.name}" class="gg-tree-label">${this.layer.name}</span></button></div><div><button id="timeRestriction" class="${this.getButtonClass('timeRestriction')}" tip="Define time restriction on group"><img alt="Define time restriction on group" src="icons/clock.svg"></button></div><button class="${this.layer.hasMetadata ? 'metadata gg-icon-button gg-small gg-opacity tool' : 'hidden'}" tip="Show metadata" onclick="${() => this.showMetadata()}"><img alt="Remove theme" src="icons/info.svg"></button> <button id="drag-button" class="${this.getButtonClass('draggable')}" tip="Move"><img alt="Move layer" src="icons/drag.svg"></button> <button class="${this.getButtonClass('removable')}" tip="Remove group" onclick="${() => this.deleteGroup()}"><img alt="Remove group" src="icons/trash.svg"></button></header><div class="${(this.layer.isExpanded && this.layer.isVisible ? 'children' : 'hidden')}">${this.sortedChildren().filter(layer => layer.isVisible).map(layer => (layer instanceof GroupLayer) ? uHtmlFor(layer, layer.treeItemId) `<girafe-tree-view-group groupid="${layer.treeItemId}"></girafe-tree-view-group>` : uHtmlFor(layer, layer.treeItemId) `<girafe-tree-view-item layerid="${layer.treeItemId}"></girafe-tree-view-item>`)}</div></div>
16
+ <link rel="stylesheet" href="lib/tippy.js/tippy.css"><link rel="stylesheet" href="lib/tippy.js/backdrop.css"><link rel="stylesheet" href="lib/tippy.js/border.css"><link rel="stylesheet" href="lib/tippy.js/svg-arrow.css"><div id="container"><header><button class="gg-icon-button gg-small gg-opacity" tip="Expand / Collapse" onclick="${() => this.layer.isExpanded = !this.layer.isExpanded}"><img class="${this.layer.isExpanded ? 'gg-rotate90 gg-caret' : 'gg-caret'}" alt="Expand/Collapse button" src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8bWFzayBpZD0ibWFzazBfMTM2XzY5NTIiIHN0eWxlPSJtYXNrLXR5cGU6YWxwaGEiIG1hc2tVbml0cz0idXNlclNwYWNlT25Vc2UiIHg9IjAiIHk9IjAiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCI+CiAgPHJlY3Qgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiBmaWxsPSIjRDlEOUQ5Ii8+CiAgPC9tYXNrPgogIDxnIG1hc2s9InVybCgjbWFzazBfMTM2XzY5NTIpIj4KICA8cGF0aCBkPSJNMTAuNSAxNi4zQzEwLjM2NjcgMTYuMyAxMC4yNSAxNi4yNTQyIDEwLjE1IDE2LjE2MjVDMTAuMDUgMTYuMDcwOCAxMCAxNS45NSAxMCAxNS44VjguMjAwMDFDMTAgOC4wNTAwMSAxMC4wNSA3LjkyOTE4IDEwLjE1IDcuODM3NTFDMTAuMjUgNy43NDU4NSAxMC4zNjY3IDcuNzAwMDEgMTAuNSA3LjcwMDAxQzEwLjUzMzMgNy43MDAwMSAxMC42NSA3Ljc1MDAxIDEwLjg1IDcuODUwMDFMMTQuNDc1IDExLjQ3NUMxNC41NTgzIDExLjU1ODMgMTQuNjE2NyAxMS42NDE3IDE0LjY1IDExLjcyNUMxNC42ODMzIDExLjgwODMgMTQuNyAxMS45IDE0LjcgMTJDMTQuNyAxMi4xIDE0LjY4MzMgMTIuMTkxNyAxNC42NSAxMi4yNzVDMTQuNjE2NyAxMi4zNTgzIDE0LjU1ODMgMTIuNDQxNyAxNC40NzUgMTIuNTI1TDEwLjg1IDE2LjE1QzEwLjggMTYuMiAxMC43NDU4IDE2LjIzNzUgMTAuNjg3NSAxNi4yNjI1QzEwLjYyOTIgMTYuMjg3NSAxMC41NjY3IDE2LjMgMTAuNSAxNi4zWiIgZmlsbD0iIzFDMUIxRiIvPgogIDwvZz4KPC9zdmc+CiAg"></button> <button class="${this.layer.activeState === 'on' ? 'gg-icon-button gg-small gg-selected' : 'gg-icon-button gg-small gg-opacity'}" tip="Activate / Deactivate" onclick="${() => this.toggle()}"><img class="${this.layer.activeState === 'on' ? 'gg-checkbox' : 'hidden'}" alt="Expand/Collapse button" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NDggNTEyIj48IS0tIUZvbnQgQXdlc29tZSBGcmVlIDYuNi4wIGJ5IEBmb250YXdlc29tZSAtIGh0dHBzOi8vZm9udGF3ZXNvbWUuY29tIExpY2Vuc2UgLSBodHRwczovL2ZvbnRhd2Vzb21lLmNvbS9saWNlbnNlL2ZyZWUgQ29weXJpZ2h0IDIwMjQgRm9udGljb25zLCBJbmMuLS0+PHBhdGggZD0iTTY0IDMyQzI4LjcgMzIgMCA2MC43IDAgOTZMMCA0MTZjMCAzNS4zIDI4LjcgNjQgNjQgNjRsMzIwIDBjMzUuMyAwIDY0LTI4LjcgNjQtNjRsMC0zMjBjMC0zNS4zLTI4LjctNjQtNjQtNjRMNjQgMzJ6TTMzNyAyMDlMMjA5IDMzN2MtOS40IDkuNC0yNC42IDkuNC0zMy45IDBsLTY0LTY0Yy05LjQtOS40LTkuNC0yNC42IDAtMzMuOXMyNC42LTkuNCAzMy45IDBsNDcgNDdMMzAzIDE3NWM5LjQtOS40IDI0LjYtOS40IDMzLjkgMHM5LjQgMjQuNiAwIDMzLjl6Ii8+PC9zdmc+"> <img class="${this.layer.activeState === 'semi' ? 'gg-checkbox' : 'hidden'}" alt="Expand/Collapse button" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NDggNTEyIj48IS0tIUZvbnQgQXdlc29tZSBGcmVlIDYuNi4wIGJ5IEBmb250YXdlc29tZSAtIGh0dHBzOi8vZm9udGF3ZXNvbWUuY29tIExpY2Vuc2UgLSBodHRwczovL2ZvbnRhd2Vzb21lLmNvbS9saWNlbnNlL2ZyZWUgQ29weXJpZ2h0IDIwMjQgRm9udGljb25zLCBJbmMuLS0+PHBhdGggZD0iTTY0IDgwYy04LjggMC0xNiA3LjItMTYgMTZsMCAzMjBjMCA4LjggNy4yIDE2IDE2IDE2bDMyMCAwYzguOCAwIDE2LTcuMiAxNi0xNmwwLTMyMGMwLTguOC03LjItMTYtMTYtMTZMNjQgODB6TTAgOTZDMCA2MC43IDI4LjcgMzIgNjQgMzJsMzIwIDBjMzUuMyAwIDY0IDI4LjcgNjQgNjRsMCAzMjBjMCAzNS4zLTI4LjcgNjQtNjQgNjRMNjQgNDgwYy0zNS4zIDAtNjQtMjguNy02NC02NEwwIDk2ek0zMzcgMjA5TDIwOSAzMzdjLTkuNCA5LjQtMjQuNiA5LjQtMzMuOSAwbC02NC02NGMtOS40LTkuNC05LjQtMjQuNiAwLTMzLjlzMjQuNi05LjQgMzMuOSAwbDQ3IDQ3TDMwMyAxNzVjOS40LTkuNCAyNC42LTkuNCAzMy45IDBzOS40IDI0LjYgMCAzMy45eiIvPjwvc3ZnPg=="> <img class="${this.layer.activeState === 'off' ? 'gg-checkbox' : 'hidden'}" alt="Expand/Collapse button" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NDggNTEyIj48IS0tIUZvbnQgQXdlc29tZSBGcmVlIDYuNi4wIGJ5IEBmb250YXdlc29tZSAtIGh0dHBzOi8vZm9udGF3ZXNvbWUuY29tIExpY2Vuc2UgLSBodHRwczovL2ZvbnRhd2Vzb21lLmNvbS9saWNlbnNlL2ZyZWUgQ29weXJpZ2h0IDIwMjQgRm9udGljb25zLCBJbmMuLS0+PHBhdGggZD0iTTM4NCA4MGM4LjggMCAxNiA3LjIgMTYgMTZsMCAzMjBjMCA4LjgtNy4yIDE2LTE2IDE2TDY0IDQzMmMtOC44IDAtMTYtNy4yLTE2LTE2TDQ4IDk2YzAtOC44IDcuMi0xNiAxNi0xNmwzMjAgMHpNNjQgMzJDMjguNyAzMiAwIDYwLjcgMCA5NkwwIDQxNmMwIDM1LjMgMjguNyA2NCA2NCA2NGwzMjAgMGMzNS4zIDAgNjQtMjguNyA2NC02NGwwLTMyMGMwLTM1LjMtMjguNy02NC02NC02NEw2NCAzMnoiLz48L3N2Zz4="></button> <button class="${this.layer.hasError ? 'gg-icon-button gg-small gg-opacity' : 'hidden'}" tip="Error on layer"><img alt="Error on layer" src="icons/error.svg"></button><div class="label-container"><button class="${this.layer.activeState === 'on' ? 'gg-icon-button gg-small gg-selected' : 'gg-icon-button gg-small gg-opacity'}" onclick="${() => this.toggle()}"><span i18n="${this.layer.name}" class="gg-tree-label">${this.layer.name}</span></button></div><button id="opacity" class="${this.getButtonClass('opacity')}" tip="Control opacity"><img alt="Control opacity" src="icons/opacity.svg"></button><div><button id="timeRestriction" class="${this.getButtonClass('timeRestriction')}" tip="Define time restriction on group"><img alt="Define time restriction on group" src="icons/clock.svg"></button></div><button class="${this.layer.hasMetadata ? 'metadata gg-icon-button gg-small gg-opacity tool' : 'hidden'}" tip="Show metadata" onclick="${() => this.showMetadata()}"><img alt="Remove theme" src="icons/info.svg"></button> <button id="drag-button" class="${this.getButtonClass('draggable')}" tip="Move"><img alt="Move layer" src="icons/drag.svg"></button> <button class="${this.getButtonClass('removable')}" tip="Remove group" onclick="${() => this.deleteGroup()}"><img alt="Remove group" src="icons/trash.svg"></button></header><div class="${(this.layer.isExpanded && this.layer.isVisible ? 'children' : 'hidden')}">${this.sortedChildren().filter(layer => layer.isVisible).map(layer => (layer instanceof GroupLayer) ? uHtmlFor(layer, layer.treeItemId) `<girafe-tree-view-group groupid="${layer.treeItemId}"></girafe-tree-view-group>` : uHtmlFor(layer, layer.treeItemId) `<girafe-tree-view-item layerid="${layer.treeItemId}"></girafe-tree-view-item>`)}</div></div>
17
17
  ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
18
18
  };
19
19
  layer;
@@ -31,16 +31,36 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
31
31
  super.render();
32
32
  }
33
33
  registerEvents() {
34
- this.subscribe(/layers\.layersList\..*\.isExpanded/, (_oldValue, _newValue, group) => this.refreshRender(group));
35
- this.subscribe(/layers\.layersList\..*\.activeState/, (_oldValue, _newValue, group) => this.refreshRender(group));
36
- this.subscribe(/layers\.layersList\..*\.children/, (_oldValue, _newValue, group) => this.refreshRender(group));
34
+ this.subscribe(/layers\.layersList\..*\.isExpanded/, (_oldValue, _newValue, group) => {
35
+ if (!this.isSameLayerObject(group))
36
+ return;
37
+ this.refreshRender(group);
38
+ });
39
+ this.subscribe(/layers\.layersList\..*\.activeState/, (_oldValue, _newValue, group) => {
40
+ if (!this.isSameLayerObject(group))
41
+ return;
42
+ this.refreshRender(group);
43
+ });
44
+ this.subscribe(/layers\.layersList\..*\.children/, (_oldValue, _newValue, group) => {
45
+ if (!this.isSameLayerObject(group))
46
+ return;
47
+ this.refreshRender(group);
48
+ });
37
49
  this.subscribe(/layers\.layersList\..*\.order/, (_oldValue, _newValue, layer) => {
50
+ // Don't check for same object here to affect all moved items.
38
51
  this.refreshRender(layer);
39
52
  this.refreshRender(layer.parent);
40
53
  });
41
54
  this.subscribe(/layers\.layersList\..*\.timeRestriction/, (_old, _new, layer) => {
55
+ if (!this.isSameLayerObject(layer))
56
+ return;
42
57
  this.refreshRender(layer);
43
58
  });
59
+ this.subscribe(/layers\.layersList\..*\.opacity/, (_oldValue, _newValue, group) => {
60
+ if (!this.isSameLayerObject(group))
61
+ return;
62
+ this.refreshRender(group);
63
+ });
44
64
  this.subscribe('treeview.renderEnabled', () => {
45
65
  this.refreshRender();
46
66
  });
@@ -48,6 +68,7 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
48
68
  connectedCallback() {
49
69
  super.connectedCallback();
50
70
  this.render();
71
+ this.createOpacityTooltip();
51
72
  super.girafeTranslate();
52
73
  this.registerEvents();
53
74
  }
@@ -18,7 +18,6 @@ declare class TreeViewItemComponent extends TreeViewElement {
18
18
  private setWmsLegend;
19
19
  setWmtsLegend(): void;
20
20
  getCrossOrigin(url: string | null): "anonymous" | "use-credentials";
21
- createOpacityTooltip(): void;
22
21
  createFilterTooltip(): void;
23
22
  registerEvents(): void;
24
23
  refreshLegendsAndStyle(): void;
@@ -29,5 +28,11 @@ declare class TreeViewItemComponent extends TreeViewElement {
29
28
  convertToDrawing(): void;
30
29
  deleteLayer(): void;
31
30
  protected connectedCallback(): void;
31
+ /**
32
+ * Update the opacity slider value by changing the instance of the tippy tooltip.
33
+ * This is needed when the opacity of the layer group changes.
34
+ * @private
35
+ */
36
+ private updateOpacitySlider;
32
37
  }
33
38
  export default TreeViewItemComponent;
@@ -1,3 +1,9 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
1
7
  import { html as uHtml } from 'uhtml';
2
8
  // SPDX-License-Identifier: Apache-2.0
3
9
  import tippy from 'tippy.js';
@@ -9,6 +15,7 @@ import TreeViewElement from '../tools/treeviewelement.js';
9
15
  import { isSnappableLayer } from '../../../models/layers/snappablelayer.js';
10
16
  import WmsLegendHelper from '../../../tools/wms/wmslegendhelper.js';
11
17
  import LayerDrawing from '../../../models/layers/layerdrawing.js';
18
+ import { UsedInTemplateOnly } from '../../../decorators.js';
12
19
  class TreeViewItemComponent extends TreeViewElement {
13
20
  templateUrl = null;
14
21
  styleUrls = null;
@@ -50,7 +57,7 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
50
57
  this.layer = layer;
51
58
  }
52
59
  render() {
53
- // If we come from a html element, the layer was not defined in the constructor
60
+ // If we come from an HTML element, the layer was not defined in the constructor
54
61
  // And we have to set the layer using the id passed to the layerid attribute
55
62
  const layerId = this.getAttribute('layerid');
56
63
  if (layerId) {
@@ -102,29 +109,6 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
102
109
  const hostname = new URL(url).hostname;
103
110
  return this.state.oauth.audience.includes(hostname) ? 'use-credentials' : 'anonymous';
104
111
  }
105
- createOpacityTooltip() {
106
- const el = this.shadow.getElementById('opacity');
107
- if (!el) {
108
- return;
109
- }
110
- tippy(el, {
111
- trigger: 'click',
112
- arrow: true,
113
- interactive: true,
114
- theme: 'light',
115
- placement: 'right',
116
- content: (_reference) => {
117
- const slider = document.createElement('input');
118
- slider.type = 'range';
119
- slider.className = 'gg-range';
120
- slider.min = '0';
121
- slider.max = '20';
122
- slider.value = (this.layer.opacity * 20).toString();
123
- slider.oninput = () => (this.layer.opacity = Number.parseInt(slider.value) / 20);
124
- return slider;
125
- }
126
- });
127
- }
128
112
  createFilterTooltip() {
129
113
  const el = this.shadow.getElementById('filter');
130
114
  if (!el) {
@@ -145,23 +129,53 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
145
129
  }
146
130
  registerEvents() {
147
131
  this.subscribe(/layers\..*\.isLegendExpanded/, (_oldValue, _newValue, layer) => {
132
+ if (!this.isSameLayerObject(layer))
133
+ return;
148
134
  this.refreshLegendsAndStyle();
149
135
  this.refreshRender(layer);
150
136
  });
151
137
  this.subscribe(/layers\.layersList\..*\.activeState/, (_oldValue, _newValue, layer) => {
138
+ if (!this.isSameLayerObject(layer))
139
+ return;
152
140
  this.refreshLegendsAndStyle();
153
141
  this.refreshRender(layer);
154
142
  });
155
- this.subscribe(/layers\.layersList\..*\.hasError/, (_oldValue, _newValue, layer) => this.refreshRender(layer));
156
- this.subscribe(/layers\.layersList\..*\.errorMessage/, (_oldValue, _newValue, layer) => this.refreshRender(layer));
157
- this.subscribe(/layers\.layersList\..*\.filter/, (_oldValue, _newValue, layer) => this.refreshRender(layer));
158
- this.subscribe(/layers\.layersList\..*\.snapActive/, (_oldValue, _newValue, layer) => this.refreshRender(layer));
143
+ this.subscribe(/layers\.layersList\..*\.hasError/, (_oldValue, _newValue, layer) => {
144
+ if (!this.isSameLayerObject(layer))
145
+ return;
146
+ this.refreshRender(layer);
147
+ });
148
+ this.subscribe(/layers\.layersList\..*\.errorMessage/, (_oldValue, _newValue, layer) => {
149
+ if (!this.isSameLayerObject(layer))
150
+ return;
151
+ this.refreshRender(layer);
152
+ });
153
+ this.subscribe(/layers\.layersList\..*\.filter/, (_oldValue, _newValue, layer) => {
154
+ if (!this.isSameLayerObject(layer))
155
+ return;
156
+ this.refreshRender(layer);
157
+ });
158
+ this.subscribe(/layers\.layersList\..*\.snapActive/, (_oldValue, _newValue, layer) => {
159
+ if (!this.isSameLayerObject(layer))
160
+ return;
161
+ this.refreshRender(layer);
162
+ });
159
163
  this.subscribe(/layers\.layersList\..*\.timeRestriction/, (_old, _new, layer) => {
160
- if (layer === this.layer || layer === this.layer.parent)
164
+ if (this.isSameLayerObject(layer) || layer === this.layer.parent) {
161
165
  this.refreshRender(this.layer);
166
+ }
167
+ });
168
+ this.subscribe(/layers\.layersList\..*\.opacity/, (_oldValue, _newValue, layer) => {
169
+ if (!this.isSameLayerObject(layer))
170
+ return;
171
+ this.refreshRender(layer);
172
+ this.updateOpacitySlider();
173
+ });
174
+ this.subscribe(/layers\.layersList\..*\.swiped/, (_oldValue, _newValue, layer) => {
175
+ if (!this.isSameLayerObject(layer))
176
+ return;
177
+ this.refreshRender(layer);
162
178
  });
163
- this.subscribe(/layers\.layersList\..*\.opacity/, (_oldValue, _newValue, layer) => this.refreshRender(layer));
164
- this.subscribe(/layers\.layersList\..*\.swiped/, (_oldValue, _newValue, layer) => this.refreshRender(layer));
165
179
  this.subscribe('treeview.advanced', () => this.refreshRender(this.layer));
166
180
  this.subscribe('position', () => this.refreshLegendsAndStyle());
167
181
  }
@@ -247,5 +261,23 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
247
261
  this.render();
248
262
  this.registerEvents();
249
263
  }
264
+ /**
265
+ * Update the opacity slider value by changing the instance of the tippy tooltip.
266
+ * This is needed when the opacity of the layer group changes.
267
+ * @private
268
+ */
269
+ updateOpacitySlider() {
270
+ const el = this.shadow.getElementById('opacity');
271
+ if (!el) {
272
+ return;
273
+ }
274
+ el._tippy.props.content.value = (this.layer.opacity * 20).toString();
275
+ }
250
276
  }
277
+ __decorate([
278
+ UsedInTemplateOnly()
279
+ ], TreeViewItemComponent.prototype, "hasLegend", null);
280
+ __decorate([
281
+ UsedInTemplateOnly()
282
+ ], TreeViewItemComponent.prototype, "getCrossOrigin", null);
251
283
  export default TreeViewItemComponent;
@@ -1,9 +1,6 @@
1
1
  import { htmlFor as uHtmlFor } from 'uhtml/keyed';
2
2
  import { html as uHtml } from 'uhtml';
3
3
  import TreeViewGroupElement from '../tools/treeviewgroupelement.js';
4
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
5
- // @ts-ignore This import is not used in the typescript file but needed in the HTML Template
6
- // Cannot use <ts-expect-error> here because after the build-lib, the error disappear
7
4
  import GroupLayer from '../../../models/layers/grouplayer.js';
8
5
  class TreeViewThemeComponent extends TreeViewGroupElement {
9
6
  templateUrl = null;
@@ -35,14 +32,29 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
35
32
  super.render();
36
33
  }
37
34
  registerEvents() {
38
- this.subscribe(/layers\.layersList\..*\.isExpanded/, (_oldValue, _newValue, theme) => this.refreshRender(theme));
39
- this.subscribe(/layers\.layersList\..*\.activeState/, (_oldValue, _newValue, theme) => this.refreshRender(theme));
35
+ this.subscribe(/layers\.layersList\..*\.isExpanded/, (_oldValue, _newValue, theme) => {
36
+ if (!this.isSameLayerObject(theme))
37
+ return;
38
+ this.refreshRender(theme);
39
+ });
40
+ this.subscribe(/layers\.layersList\..*\.activeState/, (_oldValue, _newValue, theme) => {
41
+ if (!this.isSameLayerObject(theme))
42
+ return;
43
+ this.refreshRender(theme);
44
+ });
40
45
  this.subscribe(/layers\.layersList\..*\.children/, (_oldValue, _newValue, group) => {
46
+ if (!this.isSameLayerObject(group))
47
+ return;
41
48
  this.refreshRender(group);
42
49
  this.refreshRender(group.parent);
43
50
  });
44
- this.subscribe(/layers\.layersList\..*\.filter/, (_oldValue, _newValue, layer) => this.refreshRender(layer));
51
+ this.subscribe(/layers\.layersList\..*\.filter/, (_oldValue, _newValue, theme) => {
52
+ if (!this.isSameLayerObject(theme))
53
+ return;
54
+ this.refreshRender(theme);
55
+ });
45
56
  this.subscribe(/layers\.layersList\..*\.order/, (_oldValue, _newValue, layer) => {
57
+ // Don't check for same object here to affect all moved items.
46
58
  this.refreshRender(layer);
47
59
  this.refreshRender(layer.parent);
48
60
  });
@@ -16,6 +16,7 @@ declare class GroupLayer extends BaseLayer implements ILayerWithTime {
16
16
  isExpanded: boolean;
17
17
  _isMixed?: boolean;
18
18
  activeState: 'on' | 'off' | 'semi';
19
+ opacity: number;
19
20
  timeOptions?: ITimeOptions;
20
21
  timeAttribute?: string;
21
22
  timeRestriction?: string;
@@ -27,6 +28,7 @@ declare class GroupLayer extends BaseLayer implements ILayerWithTime {
27
28
  get semiActive(): boolean;
28
29
  get hasTimeRestriction(): boolean;
29
30
  get hasGrandChildren(): boolean;
31
+ isFirstLevelGroup(): boolean;
30
32
  setDefaultTimeRestriction(): void;
31
33
  /**
32
34
  * Checks if all the children are LayerWms with the same ogcServer, opacity
@@ -3,20 +3,21 @@ import BaseLayer from './baselayer.js';
3
3
  import LayerTimeFormatter from '../../tools/time/layertimeformatter.js';
4
4
  import LayerWms from './layerwms.js';
5
5
  /*
6
- * This class is a used in the state of the application, which will be accessed behind a javascript proxy.
6
+ * This class is used in the state of the application, which will be accessed behind a JavaScript proxy.
7
7
  * This means that each modification made to its properties must come from outside,
8
- * because they have to be made through the proxy, so that the modification can be listen.
9
- * Therefore, this class must not contain any method which is updating a value directly
10
- * For example, any method doing <this.xxx = value> is forbidden here, because the modification be known from the proxy
8
+ * because they have to be made through the proxy, so that the modification can be listened to.
9
+ * Therefore, this class must not contain any method updating a value directly
10
+ * For example, any method doing <this.xxx = value> is forbidden here, because the modification is known from the proxy
11
11
  */
12
12
  class GroupLayer extends BaseLayer {
13
13
  isExclusiveGroup;
14
14
  isExpanded;
15
15
  _isMixed;
16
16
  activeState = 'off';
17
+ opacity = 1; // Only used on first level groups.
17
18
  timeOptions;
18
19
  timeAttribute;
19
- timeRestriction;
20
+ timeRestriction; // Only used on first level groups.
20
21
  children = [];
21
22
  constructor(id, name, order, options) {
22
23
  super(id, name, order, options);
@@ -41,6 +42,7 @@ class GroupLayer extends BaseLayer {
41
42
  const clonedObject = new GroupLayer(this.id, this.name, this.order, options);
42
43
  clonedObject.activeState = this.activeState;
43
44
  clonedObject.timeRestriction = this.timeRestriction;
45
+ clonedObject.opacity = this.opacity;
44
46
  // Clone children
45
47
  for (const child of this.children) {
46
48
  try {
@@ -74,6 +76,9 @@ class GroupLayer extends BaseLayer {
74
76
  }
75
77
  return false;
76
78
  }
79
+ isFirstLevelGroup() {
80
+ return !(this.parent instanceof GroupLayer);
81
+ }
77
82
  setDefaultTimeRestriction() {
78
83
  if (this.timeOptions) {
79
84
  const timeFormatter = new LayerTimeFormatter(this.timeOptions);
@@ -1,11 +1,11 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
2
  import BaseLayer from './baselayer.js';
3
3
  /*
4
- * This class is a used in the state of the application, which will be accessed behind a javascript proxy.
4
+ * This class is used in the state of the application, which will be accessed behind a JavaScript proxy.
5
5
  * This means that each modification made to its properties must come from outside,
6
- * because they have to be made through the proxy, so that the modification can be listen.
7
- * Therefore, this class must not contain any method which is updating a value directly
8
- * For example, any method doing <this.xxx = value> is forbidden here, because the modification be known from the proxy
6
+ * because they have to be made through the proxy, so that the modification can be listened to.
7
+ * Therefore, this class must not contain any method updating a value directly
8
+ * For example, any method doing <this.xxx = value> is forbidden here, because the modification is known from the proxy
9
9
  */
10
10
  class Layer extends BaseLayer {
11
11
  activeState = 'off';
@@ -11,7 +11,7 @@ import { BrainIgnore } from '../../tools/state/brain/decorators.js';
11
11
  * This class is used in the state of the application, which will be accessed behind a JavaScript proxy.
12
12
  * This means that each modification made to its properties must come from outside,
13
13
  * because they have to be made through the proxy, so that the modification can be listened to.
14
- * Therefore, this class must not contain any method which is updating a value directly.
14
+ * Therefore, this class must not contain any method updating a value directly.
15
15
  * For example, any method doing <this.xxx = value> is forbidden here because the modification must be known from the proxy
16
16
  */
17
17
  class LayerWms extends Layer {
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "name": "GeoGirafe PSC",
6
6
  "url": "https://doc.geogirafe.org"
7
7
  },
8
- "version": "1.2.0-dev.2845014898",
8
+ "version": "1.2.0-dev.2847659248",
9
9
  "type": "module",
10
10
  "engines": {
11
11
  "node": ">=20.19.0"
@@ -1 +1 @@
1
- {"version":"1.2.0-dev.2845014898", "build":"2845014898", "date":"13/09/2026"}
1
+ {"version":"1.2.0-dev.2847659248", "build":"2847659248", "date":"14/09/2026"}
@@ -177,8 +177,11 @@ export default class WmsClient {
177
177
  this.manageLayerOptions(layerWms);
178
178
  }
179
179
  manageLayerOptions(layerWms) {
180
+ if (layerWms.activeState === 'off') {
181
+ return;
182
+ }
180
183
  if (!this.layerExists(layerWms)) {
181
- throw new Error('Cannot change filter for this layer: it does not exist');
184
+ throw new Error(`Cannot change filter for layer ${layerWms.name}: it does not exist`);
182
185
  }
183
186
  const isBasemapLayer = layerWms.treeItemId in this.basemapLayers;
184
187
  const isLayerIndependent = layerWms.treeItemId in this.independentLayers;