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

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.
@@ -4,6 +4,7 @@ import ColumnAliasHelper from '../../tools/utils/aliases.js';
4
4
  import IGirafePanel from '../../tools/state/igirafepanel.js';
5
5
  import LayerFilterElement from './layerfilterelement.js';
6
6
  import FilterConditionElement from './filterconditionelement.js';
7
+ import { LayerId } from '../../models/layerdefinitions.js';
7
8
  declare class AdvancedFilterComponent extends GirafeHTMLElement implements IGirafePanel {
8
9
  protected templateUrl: string | null;
9
10
  protected styleUrls: string[] | null;
@@ -16,7 +17,7 @@ declare class AdvancedFilterComponent extends GirafeHTMLElement implements IGira
16
17
  layers: LayerWms[];
17
18
  layerFilterElements: LayerFilterElement[];
18
19
  columnAliasHelper: ColumnAliasHelper;
19
- layerIsRefreshing: Map<number, boolean>;
20
+ layerIsRefreshing: Map<LayerId, boolean>;
20
21
  private csvDownloader;
21
22
  constructor();
22
23
  render(): void;
@@ -185,8 +185,9 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
185
185
  filterElement.addCondition();
186
186
  this.render();
187
187
  }
188
- const layerId = Number(e.target.value);
189
- const layer = this.layers.find((l) => l.id === layerId);
188
+ const layerId = e.target.value;
189
+ // Loose equality == is on purpose. layer.id can be of type number or string, but .value always returns a string
190
+ const layer = this.layers.find((l) => l.id == layerId);
190
191
  if (filterElement.hasAppliedConditions()) {
191
192
  // If the filter has already been applied to the layer, a new filter is created and the old one is deleted
192
193
  const newFilter = new LayerFilterElement(this.context, this.columnAliasHelper, this.layerFilterElements.length);
@@ -13,9 +13,9 @@ declare class ThemeComponent extends GirafeHTMLElement {
13
13
  activeThemeType: ThemeType;
14
14
  clickOutsideContainer: HTMLElement | null;
15
15
  get customThemes(): CustomTheme[];
16
- get allThemes(): Record<number, ThemeLayer>;
16
+ get allThemes(): Record<import("../../models/layerdefinitions.js").LayerId, ThemeLayer>;
17
17
  get favoriteThemes(): (ThemeLayer | CustomTheme)[];
18
- get activeThemes(): Record<number, ThemeLayer> | (ThemeLayer | CustomTheme)[];
18
+ get activeThemes(): Record<import("../../models/layerdefinitions.js").LayerId, ThemeLayer> | (ThemeLayer | CustomTheme)[];
19
19
  constructor();
20
20
  registerEvents(): void;
21
21
  render(): void;
@@ -28,8 +28,9 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
28
28
  this.refreshTheme();
29
29
  }
30
30
  refreshTheme() {
31
- const themeId = Number(this.getAttribute('themeid'));
32
- const theme = this.state.layers.layersList.find((layer) => layer.id === themeId);
31
+ const themeId = this.getAttribute('themeid');
32
+ // Loose equality == is on purpose. layer.id can be of type number or string, but getAttribute() always returns a string
33
+ const theme = this.state.layers.layersList.find((layer) => layer.id == themeId);
33
34
  if (theme) {
34
35
  this.theme = this.context.layerManager.getTreeItem(theme.treeItemId);
35
36
  }
@@ -26,7 +26,7 @@ header{border-top:1px solid #ddd;align-items:center;height:2rem;display:flex}.to
26
26
  .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}}
27
27
  </style>
28
28
  <style>${this.customStyle}</style>
29
- <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><div class="gg-spacer gg-small"><img class="${this.layer.restricted ? (this.layer.active ? 'gg-small gg-lock gg-selected' : 'gg-small gg-lock gg-opacity') : 'hidden'}" alt="Protected layer" src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8bWFzayBpZD0ibWFzazBfMzdfNDUxNyIgc3R5bGU9Im1hc2stdHlwZTphbHBoYSIgbWFza1VuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeD0iMCIgeT0iMCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0Ij4KICA8cmVjdCB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9IiNEOUQ5RDkiLz4KICA8L21hc2s+CiAgPGcgbWFzaz0idXJsKCNtYXNrMF8zN180NTE3KSI+CiAgPHBhdGggZD0iTTYgMjJDNS40NSAyMiA0Ljk3OTE3IDIxLjgwNDIgNC41ODc1IDIxLjQxMjVDNC4xOTU4MyAyMS4wMjA4IDQgMjAuNTUgNCAyMFYxMEM0IDkuNDUgNC4xOTU4MyA4Ljk3OTE3IDQuNTg3NSA4LjU4NzVDNC45NzkxNyA4LjE5NTgzIDUuNDUgOCA2IDhIN1Y2QzcgNC42MTY2NyA3LjQ4NzUgMy40Mzc1IDguNDYyNSAyLjQ2MjVDOS40Mzc1IDEuNDg3NSAxMC42MTY3IDEgMTIgMUMxMy4zODMzIDEgMTQuNTYyNSAxLjQ4NzUgMTUuNTM3NSAyLjQ2MjVDMTYuNTEyNSAzLjQzNzUgMTcgNC42MTY2NyAxNyA2VjhIMThDMTguNTUgOCAxOS4wMjA4IDguMTk1ODMgMTkuNDEyNSA4LjU4NzVDMTkuODA0MiA4Ljk3OTE3IDIwIDkuNDUgMjAgMTBWMjBDMjAgMjAuNTUgMTkuODA0MiAyMS4wMjA4IDE5LjQxMjUgMjEuNDEyNUMxOS4wMjA4IDIxLjgwNDIgMTguNTUgMjIgMTggMjJINlpNNiAyMEgxOFYxMEg2VjIwWk0xMiAxN0MxMi41NSAxNyAxMy4wMjA4IDE2LjgwNDIgMTMuNDEyNSAxNi40MTI1QzEzLjgwNDIgMTYuMDIwOCAxNCAxNS41NSAxNCAxNUMxNCAxNC40NSAxMy44MDQyIDEzLjk3OTIgMTMuNDEyNSAxMy41ODc1QzEzLjAyMDggMTMuMTk1OCAxMi41NSAxMyAxMiAxM0MxMS40NSAxMyAxMC45NzkyIDEzLjE5NTggMTAuNTg3NSAxMy41ODc1QzEwLjE5NTggMTMuOTc5MiAxMCAxNC40NSAxMCAxNUMxMCAxNS41NSAxMC4xOTU4IDE2LjAyMDggMTAuNTg3NSAxNi40MTI1QzEwLjk3OTIgMTYuODA0MiAxMS40NSAxNyAxMiAxN1pNOSA4SDE1VjZDMTUgNS4xNjY2NyAxNC43MDgzIDQuNDU4MzMgMTQuMTI1IDMuODc1QzEzLjU0MTcgMy4yOTE2NyAxMi44MzMzIDMgMTIgM0MxMS4xNjY3IDMgMTAuNDU4MyAzLjI5MTY3IDkuODc1IDMuODc1QzkuMjkxNjcgNC40NTgzMyA5IDUuMTY2NjcgOSA2VjhaIiBmaWxsPSIjMUMxQjFGIi8+CiAgPC9nPgo8L3N2Zz4KICA="></div><button class="${this.layer.active ? 'gg-icon-button gg-small gg-selected' : 'gg-icon-button gg-small gg-opacity'}" tip="Activate / Deactivate" onclick="${() => this.toggle()}"><img class="${this.layer.active ? 'gg-checkbox' : 'hidden'}" alt="Expand/Collapse button" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NDggNTEyIj48IS0tIUZvbnQgQXdlc29tZSBGcmVlIDYuNi4wIGJ5IEBmb250YXdlc29tZSAtIGh0dHBzOi8vZm9udGF3ZXNvbWUuY29tIExpY2Vuc2UgLSBodHRwczovL2ZvbnRhd2Vzb21lLmNvbS9saWNlbnNlL2ZyZWUgQ29weXJpZ2h0IDIwMjQgRm9udGljb25zLCBJbmMuLS0+PHBhdGggZD0iTTY0IDMyQzI4LjcgMzIgMCA2MC43IDAgOTZMMCA0MTZjMCAzNS4zIDI4LjcgNjQgNjQgNjRsMzIwIDBjMzUuMyAwIDY0LTI4LjcgNjQtNjRsMC0zMjBjMC0zNS4zLTI4LjctNjQtNjQtNjRMNjQgMzJ6TTMzNyAyMDlMMjA5IDMzN2MtOS40IDkuNC0yNC42IDkuNC0zMy45IDBsLTY0LTY0Yy05LjQtOS40LTkuNC0yNC42IDAtMzMuOXMyNC42LTkuNCAzMy45IDBsNDcgNDdMMzAzIDE3NWM5LjQtOS40IDI0LjYtOS40IDMzLjkgMHM5LjQgMjQuNiAwIDMzLjl6Ii8+PC9zdmc+"> <img class="${!this.layer.active ? 'gg-checkbox' : 'hidden'}" alt="Expand/Collapse button" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NDggNTEyIj48IS0tIUZvbnQgQXdlc29tZSBGcmVlIDYuNi4wIGJ5IEBmb250YXdlc29tZSAtIGh0dHBzOi8vZm9udGF3ZXNvbWUuY29tIExpY2Vuc2UgLSBodHRwczovL2ZvbnRhd2Vzb21lLmNvbS9saWNlbnNlL2ZyZWUgQ29weXJpZ2h0IDIwMjQgRm9udGljb25zLCBJbmMuLS0+PHBhdGggZD0iTTM4NCA4MGM4LjggMCAxNiA3LjIgMTYgMTZsMCAzMjBjMCA4LjgtNy4yIDE2LTE2IDE2TDY0IDQzMmMtOC44IDAtMTYtNy4yLTE2LTE2TDQ4IDk2YzAtOC44IDcuMi0xNiAxNi0xNmwzMjAgMHpNNjQgMzJDMjguNyAzMiAwIDYwLjcgMCA5NkwwIDQxNmMwIDM1LjMgMjguNyA2NCA2NCA2NGwzMjAgMGMzNS4zIDAgNjQtMjguNyA2NC02NGwwLTMyMGMwLTM1LjMtMjguNy02NC02NC02NEw2NCAzMnoiLz48L3N2Zz4="></button><div class="${this.layer.hasError ? 'gg-icon gg-small gg-opacity' : 'hidden'}" tip="${this.layer.errorMessage ? this.layer.errorMessage : 'Error on layer'}"><img alt="Error on layer" src="icons/error.svg"></div><div class="${this.isVisibleInCurrentResolution() ? 'label-container' : 'label-container label-out-resolution'}"><button class="${this.layer.active ? '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> <button class="${this.layer.active && this.layer instanceof LayerWms && !this.isVisibleInCurrentResolution() ? 'gg-icon-button gg-small resolution-tool' : 'hidden'}" tip="Zoom to visible resolution" onclick="${() => this.zoomToVisibleResolution()}"><img alt="Zoom to visible resolution" src="icons/zoom.svg"></button> <img class="${this.layer.active && this.iconUrl ? 'legend-icon' : 'hidden'}" alt="${'Icon for ' + this.layer.name}" src="${this.iconUrl}" loading="lazy" crossorigin="${this.getCrossOrigin(this.iconUrl)}"></div><button class="${this.layer.active && this.layer instanceof LayerLocalFile ? 'gg-icon-button gg-small gg-opacity tool' : 'hidden'}" tip="Zoom to full extent" onclick="${() => this.zoomToFullExtent()}"><img alt="Zoom to full extent" src="icons/zoom.svg"></button> <button class="${this.layer.active && this.layer instanceof LayerLocalFile ? 'gg-icon-button gg-small gg-opacity tool' : 'hidden'}" tip="Convert to drawing" onclick="${() => this.convertToDrawing()}"><img alt="draw-icon" src="icons/draw.svg"></button> <button class="${this.getButtonClass('swipedLeft')}" tip="Swipe layer to the left" onclick="${() => this.layer.swiped = (this.layer.swiped === 'left') ? 'no' : 'left'}"><img alt="Swipe layer to the left" src="icons/swipe-left.svg"></button> <button class="${this.getButtonClass('swipedRight')}" tip="Swipe layer to the right" onclick="${() => this.layer.swiped = (this.layer.swiped === 'right') ? 'no' : 'right'}"><img alt="Swipe layer to the right" src="icons/swipe-right.svg"></button> <button id="opacity" class="${this.getButtonClass('opacity')}" tip="Control opacity"><img alt="Control opacity" src="icons/opacity.svg"></button> <button id="filter" class="${this.getButtonClass('filter')}" tip="Filter layer"><img alt="Filter layer" src="icons/filter.svg"></button> <button id="advanced-filter" class="${this.getButtonClass('advanced-filter')}" tip="Open advanced filter tool" onclick="${() => this.state.interface.advancedFilterPanelVisible = !this.state.interface.advancedFilterPanelVisible}"><img alt="Advanced filter" src="icons/advanced-filter.svg"></button> <button id="timeRestriction" class="${this.getButtonClass('timeRestriction')}" tip="Define time restriction on layer"><img alt="Define time restriction on layer" src="icons/clock.svg"></button> <button class="${this.getButtonClass('snappable')}" onclick="${() => this.toggleSnap()}" tip="Snap to layer features"><img alt="Enable snapping" src="icons/snapping.svg"></button> <button class="${this.hasLegend ? (this.layer.isLegendExpanded ? 'gg-icon-button gg-small tool' : 'gg-icon-button gg-small gg-opacity tool') : 'hidden'}" tip="Toggle legend" onclick="${() => this.toggleLegend()}"><img alt="Toggle legend" src="icons/legend.svg" loading="lazy"></button> <button class="${this.layer.hasMetadata ? 'metadata gg-icon-button gg-small gg-opacity tool' : 'hidden'}" onclick="${() => this.showMetadata()}"><img alt="Metadata" 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 layer" onclick="${() => this.deleteLayer()}"><img alt="Remove layer" src="icons/trash.svg"></button></header>${Object.keys(this.legendUrls).map((l) => uHtml `<div class="${this.isLegendExpanded ? 'legend' : 'hidden'}"><div class="gg-spacer gg-small"></div><img alt="${'Legend for ' + l}" src="${this.legendUrls[l]}" loading="lazy" crossorigin="${this.getCrossOrigin(this.legendUrls[l])}"></div>`)}<div class="${this.layer instanceof LayerLocalFile && this.isLegendExpanded ? 'legend-file' : 'legend-file hidden'}"><div class="gg-spacer gg-small"></div><div class="gg-spacer gg-small"></div><div><span i18n="File from">File from</span> <span>${this.layer.lastModifiedDate}</span> <span>[</span> <span>${this.layer._features?.length}</span> <span i18n="features">features</span> <span>]</span></div></div></div>
29
+ <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><div class="gg-spacer gg-small"><img class="${this.layer.restricted ? (this.layer.active ? 'gg-small gg-lock gg-selected' : 'gg-small gg-lock gg-opacity') : 'hidden'}" alt="Protected layer" src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8bWFzayBpZD0ibWFzazBfMzdfNDUxNyIgc3R5bGU9Im1hc2stdHlwZTphbHBoYSIgbWFza1VuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeD0iMCIgeT0iMCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0Ij4KICA8cmVjdCB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9IiNEOUQ5RDkiLz4KICA8L21hc2s+CiAgPGcgbWFzaz0idXJsKCNtYXNrMF8zN180NTE3KSI+CiAgPHBhdGggZD0iTTYgMjJDNS40NSAyMiA0Ljk3OTE3IDIxLjgwNDIgNC41ODc1IDIxLjQxMjVDNC4xOTU4MyAyMS4wMjA4IDQgMjAuNTUgNCAyMFYxMEM0IDkuNDUgNC4xOTU4MyA4Ljk3OTE3IDQuNTg3NSA4LjU4NzVDNC45NzkxNyA4LjE5NTgzIDUuNDUgOCA2IDhIN1Y2QzcgNC42MTY2NyA3LjQ4NzUgMy40Mzc1IDguNDYyNSAyLjQ2MjVDOS40Mzc1IDEuNDg3NSAxMC42MTY3IDEgMTIgMUMxMy4zODMzIDEgMTQuNTYyNSAxLjQ4NzUgMTUuNTM3NSAyLjQ2MjVDMTYuNTEyNSAzLjQzNzUgMTcgNC42MTY2NyAxNyA2VjhIMThDMTguNTUgOCAxOS4wMjA4IDguMTk1ODMgMTkuNDEyNSA4LjU4NzVDMTkuODA0MiA4Ljk3OTE3IDIwIDkuNDUgMjAgMTBWMjBDMjAgMjAuNTUgMTkuODA0MiAyMS4wMjA4IDE5LjQxMjUgMjEuNDEyNUMxOS4wMjA4IDIxLjgwNDIgMTguNTUgMjIgMTggMjJINlpNNiAyMEgxOFYxMEg2VjIwWk0xMiAxN0MxMi41NSAxNyAxMy4wMjA4IDE2LjgwNDIgMTMuNDEyNSAxNi40MTI1QzEzLjgwNDIgMTYuMDIwOCAxNCAxNS41NSAxNCAxNUMxNCAxNC40NSAxMy44MDQyIDEzLjk3OTIgMTMuNDEyNSAxMy41ODc1QzEzLjAyMDggMTMuMTk1OCAxMi41NSAxMyAxMiAxM0MxMS40NSAxMyAxMC45NzkyIDEzLjE5NTggMTAuNTg3NSAxMy41ODc1QzEwLjE5NTggMTMuOTc5MiAxMCAxNC40NSAxMCAxNUMxMCAxNS41NSAxMC4xOTU4IDE2LjAyMDggMTAuNTg3NSAxNi40MTI1QzEwLjk3OTIgMTYuODA0MiAxMS40NSAxNyAxMiAxN1pNOSA4SDE1VjZDMTUgNS4xNjY2NyAxNC43MDgzIDQuNDU4MzMgMTQuMTI1IDMuODc1QzEzLjU0MTcgMy4yOTE2NyAxMi44MzMzIDMgMTIgM0MxMS4xNjY3IDMgMTAuNDU4MyAzLjI5MTY3IDkuODc1IDMuODc1QzkuMjkxNjcgNC40NTgzMyA5IDUuMTY2NjcgOSA2VjhaIiBmaWxsPSIjMUMxQjFGIi8+CiAgPC9nPgo8L3N2Zz4KICA="></div><button class="${this.layer.active ? 'gg-icon-button gg-small gg-selected' : 'gg-icon-button gg-small gg-opacity'}" tip="Activate / Deactivate" onclick="${() => this.toggle()}"><img class="${this.layer.active ? 'gg-checkbox' : 'hidden'}" alt="Expand/Collapse button" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NDggNTEyIj48IS0tIUZvbnQgQXdlc29tZSBGcmVlIDYuNi4wIGJ5IEBmb250YXdlc29tZSAtIGh0dHBzOi8vZm9udGF3ZXNvbWUuY29tIExpY2Vuc2UgLSBodHRwczovL2ZvbnRhd2Vzb21lLmNvbS9saWNlbnNlL2ZyZWUgQ29weXJpZ2h0IDIwMjQgRm9udGljb25zLCBJbmMuLS0+PHBhdGggZD0iTTY0IDMyQzI4LjcgMzIgMCA2MC43IDAgOTZMMCA0MTZjMCAzNS4zIDI4LjcgNjQgNjQgNjRsMzIwIDBjMzUuMyAwIDY0LTI4LjcgNjQtNjRsMC0zMjBjMC0zNS4zLTI4LjctNjQtNjQtNjRMNjQgMzJ6TTMzNyAyMDlMMjA5IDMzN2MtOS40IDkuNC0yNC42IDkuNC0zMy45IDBsLTY0LTY0Yy05LjQtOS40LTkuNC0yNC42IDAtMzMuOXMyNC42LTkuNCAzMy45IDBsNDcgNDdMMzAzIDE3NWM5LjQtOS40IDI0LjYtOS40IDMzLjkgMHM5LjQgMjQuNiAwIDMzLjl6Ii8+PC9zdmc+"> <img class="${!this.layer.active ? 'gg-checkbox' : 'hidden'}" alt="Expand/Collapse button" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NDggNTEyIj48IS0tIUZvbnQgQXdlc29tZSBGcmVlIDYuNi4wIGJ5IEBmb250YXdlc29tZSAtIGh0dHBzOi8vZm9udGF3ZXNvbWUuY29tIExpY2Vuc2UgLSBodHRwczovL2ZvbnRhd2Vzb21lLmNvbS9saWNlbnNlL2ZyZWUgQ29weXJpZ2h0IDIwMjQgRm9udGljb25zLCBJbmMuLS0+PHBhdGggZD0iTTM4NCA4MGM4LjggMCAxNiA3LjIgMTYgMTZsMCAzMjBjMCA4LjgtNy4yIDE2LTE2IDE2TDY0IDQzMmMtOC44IDAtMTYtNy4yLTE2LTE2TDQ4IDk2YzAtOC44IDcuMi0xNiAxNi0xNmwzMjAgMHpNNjQgMzJDMjguNyAzMiAwIDYwLjcgMCA5NkwwIDQxNmMwIDM1LjMgMjguNyA2NCA2NCA2NGwzMjAgMGMzNS4zIDAgNjQtMjguNyA2NC02NGwwLTMyMGMwLTM1LjMtMjguNy02NC02NC02NEw2NCAzMnoiLz48L3N2Zz4="></button><div class="${this.layer.hasError ? 'gg-icon gg-small gg-opacity' : 'hidden'}" tip="${this.layer.errorMessage ? this.layer.errorMessage : 'Error on layer'}"><img alt="Error on layer" src="icons/error.svg"></div><div class="${this.isVisibleInCurrentResolution() ? 'label-container' : 'label-container label-out-resolution'}"><button class="${this.layer.active ? '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> <button class="${this.layer.active && this.layer instanceof LayerWms && !this.isVisibleInCurrentResolution() ? 'gg-icon-button gg-small resolution-tool' : 'hidden'}" tip="Zoom to visible resolution" onclick="${() => this.zoomToVisibleResolution()}"><img alt="Zoom to visible resolution" src="icons/zoom.svg"></button> <img class="${this.layer.active && this.iconUrl ? 'legend-icon' : 'hidden'}" alt="${'Icon for ' + this.layer.name}" src="${this.iconUrl}" loading="lazy" crossorigin="${this.getCrossOrigin(this.iconUrl)}"></div><button class="${this.layer.active && this.layer instanceof LayerLocalFile ? 'gg-icon-button gg-small gg-opacity tool' : 'hidden'}" tip="Zoom to full extent" onclick="${() => this.zoomToFullExtent()}"><img alt="Zoom to full extent" src="icons/zoom.svg"></button> <button class="${this.layer.active && this.layer instanceof LayerLocalFile ? 'gg-icon-button gg-small gg-opacity tool' : 'hidden'}" tip="Convert to drawing" onclick="${() => this.convertToDrawing()}"><img alt="draw-icon" src="icons/draw.svg"></button> <button class="${this.getButtonClass('swipedLeft')}" tip="Swipe layer to the left" onclick="${() => this.layer.swiped = (this.layer.swiped === 'left') ? 'no' : 'left'}"><img alt="Swipe layer to the left" src="icons/swipe-left.svg"></button> <button class="${this.getButtonClass('swipedRight')}" tip="Swipe layer to the right" onclick="${() => this.layer.swiped = (this.layer.swiped === 'right') ? 'no' : 'right'}"><img alt="Swipe layer to the right" src="icons/swipe-right.svg"></button> <button id="opacity" class="${this.getButtonClass('opacity')}" tip="Control opacity"><img alt="Control opacity" src="icons/opacity.svg"></button> <button id="filter" class="${this.getButtonClass('filter')}" tip="Filter layer"><img alt="Filter layer" src="icons/filter.svg"></button> <button id="advanced-filter" class="${this.getButtonClass('advanced-filter')}" tip="Open advanced filter tool" onclick="${() => this.state.interface.advancedFilterPanelVisible = !this.state.interface.advancedFilterPanelVisible}"><img alt="Advanced filter" src="icons/advanced-filter.svg"></button> <button id="timeRestriction" class="${this.getButtonClass('timeRestriction')}" tip="Define time restriction on layer"><img alt="Define time restriction on layer" src="icons/clock.svg"></button> <button class="${this.getButtonClass('snappable')}" onclick="${() => this.toggleSnap()}" tip="Snap to layer features"><img alt="Enable snapping" src="icons/snapping.svg"></button> <button class="${this.hasLegend ? (this.layer.isLegendExpanded ? 'gg-icon-button gg-small tool' : 'gg-icon-button gg-small gg-opacity tool') : 'hidden'}" tip="Toggle legend" onclick="${() => this.toggleLegend()}"><img alt="Toggle legend" src="icons/legend.svg" loading="lazy"></button> <button class="${this.layer.hasMetadata ? 'metadata gg-icon-button gg-small gg-opacity tool' : 'hidden'}" tip="Show metadata" onclick="${() => this.showMetadata()}"><img alt="Metadata" 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 layer" onclick="${() => this.deleteLayer()}"><img alt="Remove layer" src="icons/trash.svg"></button></header>${Object.keys(this.legendUrls).map((l) => uHtml `<div class="${this.isLegendExpanded ? 'legend' : 'hidden'}"><div class="gg-spacer gg-small"></div><img alt="${'Legend for ' + l}" src="${this.legendUrls[l]}" loading="lazy" crossorigin="${this.getCrossOrigin(this.legendUrls[l])}"></div>`)}<div class="${this.layer instanceof LayerLocalFile && this.isLegendExpanded ? 'legend-file' : 'legend-file hidden'}"><div class="gg-spacer gg-small"></div><div class="gg-spacer gg-small"></div><div><span i18n="File from">File from</span> <span>${this.layer.lastModifiedDate}</span> <span>[</span> <span>${this.layer._features?.length}</span> <span i18n="features">features</span> <span>]</span></div></div></div>
30
30
  ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
31
31
  };
32
32
  iconUrl = null;
@@ -47,10 +47,7 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
47
47
  }
48
48
  }),
49
49
  logLevel: new UserPreference('general.logLevel', null, 'system', 'select'),
50
- theme: new UserPreference('themes.defaultTheme', 'theme', 'map', 'select', (themeName) => {
51
- const themeId = Object.keys(this.state.themes._allThemes).find((themeKey) => this.state.themes._allThemes[Number(themeKey)].name === themeName);
52
- return this.state.themes._allThemes[Number(themeId)];
53
- }),
50
+ theme: new UserPreference('themes.defaultTheme', 'theme', 'map', 'select', (themeName) => Object.values(this.state.themes._allThemes).find((theme) => theme.name === themeName)),
54
51
  basemap: new UserPreference('basemaps.defaultBasemap', 'activeBasemaps', 'map', 'select', (bsName) => {
55
52
  const newDefaultBasemap = Object.values(this.state.basemaps).find((basemap) => basemap.name === bsName);
56
53
  if (newDefaultBasemap?.opacity == 0) {
@@ -151,9 +148,8 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
151
148
  }
152
149
  this.refreshThemeOptions();
153
150
  if (this.preferences.basemap) {
154
- this.preferences.basemap.options = Object.keys(this.state.basemaps).map((key) => {
155
- const baseMapName = this.state.basemaps[Number(key)].name;
156
- return { label: baseMapName, value: baseMapName };
151
+ this.preferences.basemap.options = Object.values(this.state.basemaps).map((basemap) => {
152
+ return { label: basemap.name, value: basemap.name };
157
153
  });
158
154
  }
159
155
  if (this.preferences.selectionComponent) {
@@ -198,9 +194,8 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
198
194
  return;
199
195
  }
200
196
  let defaultThemes = [{ label: '-', value: '' }];
201
- Object.keys(this.state.themes._allThemes).forEach((key) => {
202
- const themeName = this.state.themes._allThemes[Number(key)].name;
203
- defaultThemes.push({ label: themeName, value: themeName });
197
+ Object.values(this.state.themes._allThemes).forEach((theme) => {
198
+ defaultThemes.push({ label: theme.name, value: theme.name });
204
199
  });
205
200
  defaultThemes = defaultThemes.sort((a, b) => a.label.toUpperCase().localeCompare(b.label.toUpperCase()));
206
201
  const customThemes = this.context.customThemesManager.customThemes.map((ct) => {
@@ -1,12 +1,12 @@
1
- import { GMFBackgroundLayer } from '../gmf.js';
2
1
  import BaseLayer from '../layers/baselayer.js';
2
+ import { BasemapDefinition, LayerId } from '../layerdefinitions.js';
3
3
  declare class Basemap {
4
- id: number;
4
+ id: LayerId;
5
5
  name: string;
6
6
  thumbnail: string;
7
7
  opacity: number;
8
8
  layersList: BaseLayer[];
9
- constructor(elem: GMFBackgroundLayer, opacity?: number);
9
+ constructor(elem: BasemapDefinition, opacity?: number);
10
10
  get projection(): string | undefined;
11
11
  get opacityDisabled(): boolean;
12
12
  }
@@ -1,6 +1,7 @@
1
1
  import ThemeLayer from './layers/themelayer.js';
2
+ import { LayerId } from './layerdefinitions.js';
2
3
  export default class CustomTheme {
3
- id: number;
4
+ id: LayerId;
4
5
  layers: ThemeLayer[];
5
6
  name: string;
6
7
  icon: string;
@@ -0,0 +1,10 @@
1
+ import { GMFTreeItem, GMFTheme } from './gmf.js';
2
+ /**
3
+ * These are the interfaces for a Georama backend that differ from GMF
4
+ */
5
+ export interface GeoramaTreeItem extends Omit<GMFTreeItem, 'id'> {
6
+ id: string;
7
+ }
8
+ export interface GeoramaTheme extends Omit<GMFTheme, 'id'> {
9
+ id: string;
10
+ }
@@ -0,0 +1 @@
1
+ export {};
package/models/gmf.d.ts CHANGED
@@ -75,7 +75,6 @@ export interface GMFTheme {
75
75
  export interface GMFGroup extends GMFTreeItem {
76
76
  children: GMFTreeItem[];
77
77
  }
78
- export type GMFBackgroundLayer = GMFTreeItem;
79
78
  export type GMFServerOgcType = 'mapserver' | 'qgisserver' | 'georama' | 'geoserver' | 'arcgis' | 'other';
80
79
  export interface GMFServerOgc {
81
80
  url: string;
@@ -0,0 +1,13 @@
1
+ import { GMFTheme, GMFTreeItem } from './gmf.js';
2
+ import { GeoramaTheme, GeoramaTreeItem } from './georama.js';
3
+ /**
4
+ * Unified interfaces for layer definitions from different backends.
5
+ */
6
+ export type LayerId = number | string;
7
+ export interface TreeItemDefinition extends Omit<GMFTreeItem, 'id'>, Omit<GeoramaTreeItem, 'id'> {
8
+ id: LayerId;
9
+ }
10
+ export interface ThemeDefinition extends Omit<GMFTheme, 'id'>, Omit<GeoramaTheme, 'id'> {
11
+ id: LayerId;
12
+ }
13
+ export type BasemapDefinition = TreeItemDefinition;
@@ -0,0 +1 @@
1
+ export {};
@@ -1,12 +1,13 @@
1
1
  import GroupLayer from './grouplayer.js';
2
2
  import ThemeLayer from './themelayer.js';
3
+ import { LayerId } from '../layerdefinitions.js';
3
4
  type BaseLayerOptions = {
4
5
  isDefaultChecked?: boolean;
5
6
  disclaimer?: string;
6
7
  metadataUrl?: string;
7
8
  };
8
9
  declare abstract class BaseLayer {
9
- id: number;
10
+ id: LayerId;
10
11
  treeItemId: string;
11
12
  name: string;
12
13
  order: number;
@@ -27,6 +28,6 @@ declare abstract class BaseLayer {
27
28
  abstract get inactive(): boolean;
28
29
  abstract clone(): BaseLayer;
29
30
  parent?: ThemeLayer | GroupLayer;
30
- constructor(id: number, name: string, order: number, options?: BaseLayerOptions);
31
+ constructor(id: LayerId, name: string, order: number, options?: BaseLayerOptions);
31
32
  }
32
33
  export default BaseLayer;
@@ -1,4 +1,5 @@
1
1
  import BaseLayer from './baselayer.js';
2
+ import { LayerId } from '../layerdefinitions.js';
2
3
  import ILayerWithTime from './ilayerwithtime.js';
3
4
  import ITimeOptions from '../../tools/time/itimeoptions.js';
4
5
  export type GroupLayerOptions = {
@@ -21,7 +22,7 @@ declare class GroupLayer extends BaseLayer implements ILayerWithTime {
21
22
  timeAttribute?: string;
22
23
  timeRestriction?: string;
23
24
  children: BaseLayer[];
24
- constructor(id: number, name: string, order: number, options?: GroupLayerOptions);
25
+ constructor(id: LayerId, name: string, order: number, options?: GroupLayerOptions);
25
26
  clone(): GroupLayer;
26
27
  get active(): boolean;
27
28
  get inactive(): boolean;
@@ -1,6 +1,7 @@
1
1
  import BaseLayer from './baselayer.js';
2
2
  import GroupLayer from './grouplayer.js';
3
3
  import ThemeLayer from './themelayer.js';
4
+ import { LayerId } from '../layerdefinitions.js';
4
5
  type LayerOptions = {
5
6
  isDefaultChecked?: boolean;
6
7
  disclaimer?: string;
@@ -15,7 +16,7 @@ declare abstract class Layer extends BaseLayer {
15
16
  swiped: 'left' | 'right' | 'no';
16
17
  isLegendExpanded: boolean;
17
18
  parent: ThemeLayer | GroupLayer;
18
- constructor(id: number, name: string, order: number, options?: LayerOptions);
19
+ constructor(id: LayerId, name: string, order: number, options?: LayerOptions);
19
20
  get isTransparent(): boolean;
20
21
  get hasValidOpacity(): boolean;
21
22
  get active(): boolean;
@@ -1,4 +1,4 @@
1
- import { GMFTreeItem } from '../gmf.js';
1
+ import { LayerId, TreeItemDefinition } from '../layerdefinitions.js';
2
2
  import Layer from './layer.js';
3
3
  type LayerCogTilesOptions = {
4
4
  isDefaultChecked?: boolean;
@@ -9,9 +9,9 @@ type LayerCogTilesOptions = {
9
9
  };
10
10
  declare class LayerCog extends Layer {
11
11
  source: string;
12
- constructor(id: number, name: string, order: number, source: string, options?: GMFTreeItem | LayerCogTilesOptions);
12
+ constructor(id: LayerId, name: string, order: number, source: string, options?: TreeItemDefinition | LayerCogTilesOptions);
13
13
  clone(): LayerCog;
14
- private static isGMFTreeItem;
15
- private static getOptionsFromGMFTreeItem;
14
+ private static isTreeItemDefinition;
15
+ private static getOptionsFromDefinition;
16
16
  }
17
17
  export default LayerCog;
@@ -10,7 +10,7 @@ class LayerCog extends Layer {
10
10
  source;
11
11
  constructor(id, name, order, source, options) {
12
12
  let opts = options ?? {};
13
- opts = LayerCog.isGMFTreeItem(opts) ? LayerCog.getOptionsFromGMFTreeItem(opts) : opts;
13
+ opts = LayerCog.isTreeItemDefinition(opts) ? LayerCog.getOptionsFromDefinition(opts) : opts;
14
14
  super(id, name, order, opts);
15
15
  this.source = source;
16
16
  }
@@ -26,10 +26,10 @@ class LayerCog extends Layer {
26
26
  clonedObject.activeState = this.activeState;
27
27
  return clonedObject;
28
28
  }
29
- static isGMFTreeItem(options) {
29
+ static isTreeItemDefinition(options) {
30
30
  return 'id' in options;
31
31
  }
32
- static getOptionsFromGMFTreeItem(options) {
32
+ static getOptionsFromDefinition(options) {
33
33
  return {
34
34
  isDefaultChecked: options.metadata?.isChecked,
35
35
  metadataUrl: options.metadata?.metadataUrl,
@@ -3,6 +3,7 @@ import Layer from './layer.js';
3
3
  import Geometry from 'ol/geom/Geometry.js';
4
4
  import { Extent } from 'ol/extent.js';
5
5
  import ILayerWithLegend from './ilayerwithlegend.js';
6
+ import { LayerId } from '../layerdefinitions.js';
6
7
  declare class LayerLocalFile extends Layer implements ILayerWithLegend {
7
8
  _features: Feature<Geometry>[];
8
9
  lastModifiedDate: string;
@@ -12,7 +13,7 @@ declare class LayerLocalFile extends Layer implements ILayerWithLegend {
12
13
  extent: Extent;
13
14
  private readonly file;
14
15
  private readonly locale;
15
- constructor(id: number, order: number, file: File, features: Feature<Geometry>[], extent: Extent, locale: string, options?: {
16
+ constructor(id: LayerId, order: number, file: File, features: Feature<Geometry>[], extent: Extent, locale: string, options?: {
16
17
  isDefaultChecked?: boolean;
17
18
  });
18
19
  clone(): LayerLocalFile;
@@ -1,4 +1,5 @@
1
1
  import Layer from './layer.js';
2
+ import { LayerId } from '../layerdefinitions.js';
2
3
  type LayerVectorTilesOptions = {
3
4
  projection?: string;
4
5
  layerName?: string;
@@ -12,7 +13,7 @@ declare class LayerVectorTiles extends Layer {
12
13
  style: string;
13
14
  layerName?: string;
14
15
  projection?: string;
15
- constructor(id: number, name: string, order: number, style: string, options?: LayerVectorTilesOptions);
16
+ constructor(id: LayerId, name: string, order: number, style: string, options?: LayerVectorTilesOptions);
16
17
  clone(): LayerVectorTiles;
17
18
  }
18
19
  export default LayerVectorTiles;
@@ -1,5 +1,5 @@
1
1
  import WfsFilter from '../../tools/wfs/wfsfilter.js';
2
- import { GMFTreeItem } from '../gmf.js';
2
+ import { LayerId, TreeItemDefinition } from '../layerdefinitions.js';
3
3
  import ServerOgc from '../serverogc.js';
4
4
  import ILayerWithFilter from './ilayerwithfilter.js';
5
5
  import ILayerWithLegend from './ilayerwithlegend.js';
@@ -70,7 +70,7 @@ declare class LayerWms extends Layer implements ILayerWithLegend, ILayerWithFilt
70
70
  timeAttribute?: string;
71
71
  enumeratedAttributes?: string[];
72
72
  editable?: string;
73
- constructor(id: number, name: string, order: number, ogcServer: ServerOgc, options?: GMFTreeItem | LayerWmsOptions);
73
+ constructor(id: LayerId, name: string, order: number, ogcServer: ServerOgc, options?: TreeItemDefinition | LayerWmsOptions);
74
74
  clone(): LayerWms;
75
75
  static isResolutionRangeRestricted(minResolution: number | undefined, maxResolution: number | undefined): boolean | 0 | undefined;
76
76
  hasRestrictedResolution(): boolean | 0 | undefined;
@@ -82,8 +82,8 @@ declare class LayerWms extends Layer implements ILayerWithLegend, ILayerWithFilt
82
82
  get serverUniqueQueryId(): string;
83
83
  get wfsQueryable(): boolean;
84
84
  get wmsQueryableOnly(): boolean;
85
- private static isGMFTreeItem;
86
- private static getOptionsFromGMFTreeItem;
85
+ private static isTreeItemDefinition;
86
+ private static getOptionsFromDefinition;
87
87
  private static getDefaultWmsInfoFormat;
88
88
  }
89
89
  export default LayerWms;
@@ -44,7 +44,7 @@ class LayerWms extends Layer {
44
44
  editable;
45
45
  constructor(id, name, order, ogcServer, options) {
46
46
  let opts = options ?? {};
47
- opts = LayerWms.isGMFTreeItem(opts) ? LayerWms.getOptionsFromGMFTreeItem(opts) : opts;
47
+ opts = LayerWms.isTreeItemDefinition(opts) ? LayerWms.getOptionsFromDefinition(opts) : opts;
48
48
  super(id, name, order, opts);
49
49
  this.ogcServer = ogcServer;
50
50
  this.minResolution = opts?.minResolution;
@@ -152,10 +152,10 @@ class LayerWms extends Layer {
152
152
  get wmsQueryableOnly() {
153
153
  return this.queryable && !this.ogcServer.wfsSupport;
154
154
  }
155
- static isGMFTreeItem(options) {
155
+ static isTreeItemDefinition(options) {
156
156
  return 'id' in options;
157
157
  }
158
- static getOptionsFromGMFTreeItem(options) {
158
+ static getOptionsFromDefinition(options) {
159
159
  const opts = {
160
160
  isDefaultChecked: options.metadata?.isChecked,
161
161
  metadataUrl: options.metadata?.metadataUrl,
@@ -1,4 +1,4 @@
1
- import { GMFTreeItem } from '../gmf.js';
1
+ import { LayerId, TreeItemDefinition } from '../layerdefinitions.js';
2
2
  import ServerOgc from '../serverogc.js';
3
3
  import ILayerWithLegend from './ilayerwithlegend.js';
4
4
  import Layer from './layer.js';
@@ -48,12 +48,12 @@ declare class LayerWmts extends Layer implements ILayerWithLegend {
48
48
  hiDPILegendImages?: Record<string, string>;
49
49
  /** Linked ol layer, starting with an underscore to not be part of the proxy. **/
50
50
  _olayer?: TileLayer<WMTS>;
51
- constructor(id: number, name: string, order: number, url: string, layer: string, options?: GMFTreeItem | LayerWmtsOptions, ogcServer?: ServerOgc);
51
+ constructor(id: LayerId, name: string, order: number, url: string, layer: string, options?: TreeItemDefinition | LayerWmtsOptions, ogcServer?: ServerOgc);
52
52
  clone(): LayerWmts;
53
53
  get layerUniqueId(): string;
54
54
  hasRestrictedResolution(): boolean | 0 | undefined;
55
55
  isVisibleAtResolution(resolution: number): boolean;
56
- private static isGMFTreeItem;
57
- private static getOptionsFromGMFTreeItem;
56
+ private static isTreeItemDefinition;
57
+ private static getOptionsFromDefinition;
58
58
  }
59
59
  export default LayerWmts;
@@ -39,7 +39,7 @@ class LayerWmts extends Layer {
39
39
  _olayer;
40
40
  constructor(id, name, order, url, layer, options, ogcServer) {
41
41
  let opts = options ?? {};
42
- opts = LayerWmts.isGMFTreeItem(opts) ? LayerWmts.getOptionsFromGMFTreeItem(opts) : opts;
42
+ opts = LayerWmts.isTreeItemDefinition(opts) ? LayerWmts.getOptionsFromDefinition(opts) : opts;
43
43
  super(id, name, order, opts);
44
44
  this.url = url;
45
45
  this.layer = layer;
@@ -102,10 +102,10 @@ class LayerWmts extends Layer {
102
102
  }
103
103
  return resolution >= (this.minResolution ?? -1) && resolution <= (this.maxResolution ?? Infinity);
104
104
  }
105
- static isGMFTreeItem(options) {
105
+ static isTreeItemDefinition(options) {
106
106
  return 'id' in options;
107
107
  }
108
- static getOptionsFromGMFTreeItem(options) {
108
+ static getOptionsFromDefinition(options) {
109
109
  return {
110
110
  isDefaultChecked: options.metadata?.isChecked,
111
111
  metadataUrl: options.metadata?.metadataUrl,
@@ -1,4 +1,4 @@
1
- import { GMFTreeItem } from '../gmf.js';
1
+ import { LayerId, TreeItemDefinition } from '../layerdefinitions.js';
2
2
  import Layer from './layer.js';
3
3
  type LayerXYZTilesOptions = {
4
4
  isDefaultChecked?: boolean;
@@ -9,9 +9,9 @@ type LayerXYZTilesOptions = {
9
9
  };
10
10
  declare class LayerXYZ extends Layer {
11
11
  source: string;
12
- constructor(id: number, name: string, order: number, source: string, options?: GMFTreeItem | LayerXYZTilesOptions);
12
+ constructor(id: LayerId, name: string, order: number, source: string, options?: TreeItemDefinition | LayerXYZTilesOptions);
13
13
  clone(): LayerXYZ;
14
- private static isGMFTreeItem;
15
- private static getOptionsFromGMFTreeItem;
14
+ private static isTreeItemDefinition;
15
+ private static getOptionsFromDefinition;
16
16
  }
17
17
  export default LayerXYZ;
@@ -10,7 +10,7 @@ class LayerXYZ extends Layer {
10
10
  source;
11
11
  constructor(id, name, order, source, options) {
12
12
  let opts = options ?? {};
13
- opts = LayerXYZ.isGMFTreeItem(opts) ? LayerXYZ.getOptionsFromGMFTreeItem(opts) : opts;
13
+ opts = LayerXYZ.isTreeItemDefinition(opts) ? LayerXYZ.getOptionsFromDefinition(opts) : opts;
14
14
  super(id, name, order, opts);
15
15
  this.source = source;
16
16
  }
@@ -26,10 +26,10 @@ class LayerXYZ extends Layer {
26
26
  clonedObject.activeState = this.activeState;
27
27
  return clonedObject;
28
28
  }
29
- static isGMFTreeItem(options) {
29
+ static isTreeItemDefinition(options) {
30
30
  return 'id' in options;
31
31
  }
32
- static getOptionsFromGMFTreeItem(options) {
32
+ static getOptionsFromDefinition(options) {
33
33
  return {
34
34
  isDefaultChecked: options.metadata?.isChecked,
35
35
  metadataUrl: options.metadata?.metadataUrl,
@@ -1,5 +1,6 @@
1
1
  import BaseLayer from './baselayer.js';
2
2
  import { Coordinate } from 'ol/coordinate.js';
3
+ import { LayerId } from '../layerdefinitions.js';
3
4
  export type ThemeLayerOptions = {
4
5
  isDefaultChecked?: boolean;
5
6
  disclaimer?: string;
@@ -15,7 +16,7 @@ declare class ThemeLayer extends BaseLayer {
15
16
  location?: Coordinate;
16
17
  zoom?: number;
17
18
  children: BaseLayer[];
18
- constructor(id: number, name: string, order: number, icon?: string, options?: ThemeLayerOptions);
19
+ constructor(id: LayerId, name: string, order: number, icon?: string, options?: ThemeLayerOptions);
19
20
  clone(): ThemeLayer;
20
21
  get active(): boolean;
21
22
  get inactive(): boolean;
package/models/main.d.ts CHANGED
@@ -5,7 +5,9 @@ export { default as BasemapSwisstopoVectorTiles } from './basemaps/basemapswisst
5
5
  export { default as CustomTheme } from './customtheme.js';
6
6
  export type { FilterOperator, AttributeTypeGroup, LogicalFilterOperator } from './filter.js';
7
7
  export { filterOperatorValues, filterOperators, isFilterOperator, isValuelessFilterOperator, isTwoSidedFilterOperator, isListFilterOperator, operatorsByAttributeTypeGroup, logicalFilterOperators, isLogicalFilterOperator } from './filter.js';
8
- export type { GMFMetadata, GMFChildLayer, GMFTreeItem, GMFThemeFunctionality, GMFThemeFunctionalities, GMFTheme, GMFGroup, GMFBackgroundLayer, GMFServerOgcType, GMFServerOgc, GMFServerOgcAttributes, GMFServerOgcObjectAttributes, GMFServerOgcColumnAttributes } from './gmf.js';
8
+ export type { GeoramaTreeItem, GeoramaTheme } from './georama.js';
9
+ export type { GMFMetadata, GMFChildLayer, GMFTreeItem, GMFThemeFunctionality, GMFThemeFunctionalities, GMFTheme, GMFGroup, GMFServerOgcType, GMFServerOgc, GMFServerOgcAttributes, GMFServerOgcObjectAttributes, GMFServerOgcColumnAttributes } from './gmf.js';
10
+ export type { LayerId, TreeItemDefinition, ThemeDefinition, BasemapDefinition } from './layerdefinitions.js';
9
11
  export { default as BaseLayer } from './layers/baselayer.js';
10
12
  export type { GroupLayerOptions } from './layers/grouplayer.js';
11
13
  export { default as GroupLayer } from './layers/grouplayer.js';
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.2847659248",
8
+ "version": "1.2.0-dev.2853894139",
9
9
  "type": "module",
10
10
  "engines": {
11
11
  "node": ">=20.19.0"
@@ -1 +1 @@
1
- {"version":"1.2.0-dev.2847659248", "build":"2847659248", "date":"14/09/2026"}
1
+ {"version":"1.2.0-dev.2853894139", "build":"2853894139", "date":"16/09/2026"}
@@ -1,5 +1,6 @@
1
1
  import { FilterOperator, LogicalFilterOperator } from '../../../models/filter.js';
2
2
  import { GMFServerOgcType } from '../../../models/gmf.js';
3
+ import { LayerId } from '../../../models/layerdefinitions.js';
3
4
  export type SharedFilterCondition = {
4
5
  property: string;
5
6
  propertyType?: string;
@@ -14,7 +15,7 @@ export type SharedFilter = {
14
15
  };
15
16
  export type SharedLayer = SharedInternalTheme | SharedInternalGroup | SharedInternalLayer | SharedExternalTheme | SharedExternalLayer;
16
17
  export type SharedInternalTheme = {
17
- id: number;
18
+ id: LayerId;
18
19
  order: number;
19
20
  checked: number;
20
21
  isExpanded: number;
@@ -25,7 +26,7 @@ export type SharedInternalTheme = {
25
26
  * And should forcefully be added to the layer tree because the user just didn't know this layer when he has created this shared state
26
27
  * Or if it was explicitly removed from the user, and then we won't have to display it again
27
28
  */
28
- excludedChildrenIds: number[];
29
+ excludedChildrenIds: Array<LayerId>;
29
30
  /**
30
31
  * When configuring the share with "preferNames=true", the name of the layer will be used to generate the sahred state
31
32
  * instead of the ID. But in this case, we also have to share the type os the layer, because tha layer name can be
@@ -38,7 +39,7 @@ export type SharedInternalTheme = {
38
39
  excludedChildrenNames: string[];
39
40
  };
40
41
  export type SharedInternalGroup = {
41
- id: number;
42
+ id: LayerId;
42
43
  order: number;
43
44
  checked: number;
44
45
  isExpanded: number;
@@ -50,7 +51,7 @@ export type SharedInternalGroup = {
50
51
  excludedChildrenNames: string[];
51
52
  };
52
53
  export type SharedInternalLayer = {
53
- id: number;
54
+ id: LayerId;
54
55
  order: number;
55
56
  checked: number;
56
57
  isExpanded: number;
@@ -87,7 +88,7 @@ export type SharedExternalLayer = {
87
88
  swiped?: 'left' | 'right' | 'no';
88
89
  };
89
90
  export type SharedBasemap = {
90
- id: number;
91
+ id: LayerId;
91
92
  name: string;
92
93
  opacity: number;
93
94
  };
@@ -13,9 +13,10 @@ import ObjectSelection from './objectselection.js';
13
13
  import type Theme from '../../models/theme.js';
14
14
  import GraphicalInterface from './graphicalInterface.js';
15
15
  import { GMFThemeFunctionalities, GMFThemeFunctionality } from '../../models/gmf.js';
16
+ import { LayerId } from '../../models/layerdefinitions.js';
16
17
  export type ThemesConfig = {
17
- _allThemes: Record<number, ThemeLayer>;
18
- _allFunctionalities: Record<number, GMFThemeFunctionalities>;
18
+ _allThemes: Record<LayerId, ThemeLayer>;
19
+ _allFunctionalities: Record<LayerId, GMFThemeFunctionalities>;
19
20
  isLoaded: boolean;
20
21
  lastSelectedTheme: ThemeLayer | CustomTheme | null;
21
22
  };
@@ -101,7 +102,7 @@ export default class State {
101
102
  */
102
103
  themes: ThemesConfig;
103
104
  functionalities: Record<string, GMFThemeFunctionality>;
104
- basemaps: Record<number, Basemap>;
105
+ basemaps: Record<LayerId, Basemap>;
105
106
  ogcServers: Record<string, ServerOgc>;
106
107
  activeBasemaps: Basemap[];
107
108
  projection: string;
@@ -1,5 +1,6 @@
1
1
  import GirafeSingleton from '../../base/GirafeSingleton.js';
2
2
  import BaseLayer from '../../models/layers/baselayer.js';
3
+ import { LayerId } from '../../models/layerdefinitions.js';
3
4
  import GroupLayer from '../../models/layers/grouplayer.js';
4
5
  import Layer from '../../models/layers/layer.js';
5
6
  import ThemeLayer from '../../models/layers/themelayer.js';
@@ -10,8 +11,8 @@ export type LayerTreeChanges = {
10
11
  export default class ThemesHelper extends GirafeSingleton {
11
12
  initializeSingleton(): void;
12
13
  private get state();
13
- findBaseLayerById(layerId: number): BaseLayer;
14
- findBaseLayerRecursiveById(layers: BaseLayer[], layerId: number): BaseLayer | null;
14
+ findBaseLayerById(layerId: LayerId): BaseLayer;
15
+ findBaseLayerRecursiveById(layers: BaseLayer[], layerId: LayerId): BaseLayer | null;
15
16
  findThemeByName(themename: string): ThemeLayer | null;
16
17
  findGroupByName(groupname: string): GroupLayer | null;
17
18
  findLayerByName(layername: string): Layer | null;
@@ -246,7 +246,7 @@ class ThemesManager extends GirafeSingleton {
246
246
  theme.children.push(layer);
247
247
  }
248
248
  }
249
- themes[index] = theme;
249
+ themes[themeJson.id] = theme;
250
250
  }
251
251
  return { themes, themesFunctionalities };
252
252
  }