@geogirafe/lib-geoportal 1.0.2141599510 → 1.0.2149179221

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/assets/i18n/de.json +2 -0
  2. package/assets/i18n/en.json +2 -0
  3. package/assets/i18n/fr.json +2 -0
  4. package/assets/i18n/it.json +2 -0
  5. package/base/GirafeHTMLElement.d.ts +1 -1
  6. package/components/map/tools/viewmanager.d.ts +1 -1
  7. package/components/map/tools/wmtsmanager.d.ts +1 -1
  8. package/components/print/tools/printMaskManager.d.ts +1 -1
  9. package/components/search/component.d.ts +0 -1
  10. package/components/search/component.js +1 -3
  11. package/components/share/component.d.ts +2 -0
  12. package/components/share/component.js +8 -4
  13. package/components/share/sharestate.d.ts +16 -0
  14. package/components/share/sharestate.js +27 -0
  15. package/components/share/sharestate.spec.d.ts +1 -0
  16. package/components/share/sharestate.spec.js +32 -0
  17. package/components/share/tools/geogirafesharemanager.d.ts +1 -1
  18. package/components/share/tools/geogirafesharemanager.js +2 -2
  19. package/components/share/tools/iurlshortener.d.ts +1 -1
  20. package/main.iframe.js +1 -1
  21. package/package.json +1 -1
  22. package/styles/iframe.css +15 -1
  23. package/templates/iframe.html +1 -0
  24. package/templates/public/about.json +1 -1
  25. package/tools/app/geogirafeapp.d.ts +2 -1
  26. package/tools/app/geogirafeapp.js +6 -1
  27. package/tools/auth/abstractconnectmanager.d.ts +1 -1
  28. package/tools/auth/gmfmanager.d.ts +1 -1
  29. package/tools/layers/layermanager.d.ts +1 -1
  30. package/tools/main.d.ts +2 -1
  31. package/tools/main.js +2 -1
  32. package/tools/ogcapi/ogcapiclient.d.ts +1 -1
  33. package/tools/ogcapi/ogcapifeaturesmanager.d.ts +1 -1
  34. package/tools/share/serializers/interfaceserializer.d.ts +1 -1
  35. package/tools/share/stateserializer.js +1 -1
  36. package/tools/state/graphicalInterface.d.ts +24 -0
  37. package/tools/state/graphicalInterface.js +25 -0
  38. package/tools/state/state.d.ts +1 -33
  39. package/tools/state/state.js +1 -26
  40. package/tools/state/swipeuppanelmode.d.ts +9 -0
  41. package/tools/state/swipeuppanelmode.js +1 -0
  42. package/tools/themes/themeshelper.d.ts +1 -1
  43. package/tools/themes/themesmanager.d.ts +1 -1
  44. package/tools/themes/userlayermanager.d.ts +1 -1
  45. package/tools/wfs/wfsclient.d.ts +1 -1
  46. package/tools/wfs/wfsmanager.d.ts +1 -1
  47. package/tools/wms/wmsclient.d.ts +1 -1
@@ -23,6 +23,7 @@
23
23
  "auto_WMTS": "WMS/WMTS",
24
24
  "Backend error": "Backend-Fehler",
25
25
  "basemap": "Hintergrundkarte",
26
+ "Basemap visible": "Hintergrundkartenauswahl sichtbar",
26
27
  "Basemaps": "Hintergrundkarten",
27
28
  "Batch creation mode": "Batch-Modus",
28
29
  "before": "vor",
@@ -324,6 +325,7 @@
324
325
  "scale": "Skalierung",
325
326
  "Scan Source": "Datenquelle laden",
326
327
  "Search": "Suche",
328
+ "Search visible": "Suche sichtbar",
327
329
  "Search...": "Suchen...",
328
330
  "search_tip": "Ort, Objekt oder Karte suchen",
329
331
  "searchFillColor": "Suchresultat Füllfarbe",
@@ -23,6 +23,7 @@
23
23
  "auto_WMTS": "WMS/WMTS",
24
24
  "Backend error": "Backend error",
25
25
  "basemap": "Basemap",
26
+ "Basemap visible": "Basemap selection visible",
26
27
  "Basemaps": "Basemaps",
27
28
  "Batch creation mode": "Batch creation mode",
28
29
  "before": "before",
@@ -325,6 +326,7 @@
325
326
  "scale": "scale",
326
327
  "Scan Source": "Connect",
327
328
  "Search": "Search",
329
+ "Search visible": "Search visible",
328
330
  "Search...": "Search...",
329
331
  "search_tip": "Search for a place, object or map",
330
332
  "searchFillColor": "Search result fill color",
@@ -23,6 +23,7 @@
23
23
  "auto_WMTS": "WMS/WMTS",
24
24
  "Backend error": "Erreur de backend",
25
25
  "basemap": "Fonds de carte",
26
+ "Basemap visible": "Sélection de la carte de base visible",
26
27
  "Basemaps": "Fonds de carte",
27
28
  "Batch creation mode": "mode batch",
28
29
  "before": "avant",
@@ -324,6 +325,7 @@
324
325
  "scale": "échelle",
325
326
  "Scan Source": "Connexion",
326
327
  "Search": "Rechercher",
328
+ "Search visible": "Recherche visible",
327
329
  "Search...": "Rechercher...",
328
330
  "search_tip": "Rechercher un lieu, un objet ou une carte",
329
331
  "searchFillColor": "Couleur de remplissage des résultats de recherche",
@@ -23,6 +23,7 @@
23
23
  "auto_WMTS": "WMS/WMTS",
24
24
  "Backend error": "Errore del backend",
25
25
  "basemap": "Mappe di base",
26
+ "Basemap visible": "Selezione mappa di base visibile",
26
27
  "Basemaps": "Mappe di base",
27
28
  "Batch creation mode": "Modalità di creazione batch",
28
29
  "before": "prima",
@@ -324,6 +325,7 @@
324
325
  "scale": "scala",
325
326
  "Scan Source": "Connessione",
326
327
  "Search": "Cerca",
328
+ "Search visible": "Ricerca visibile",
327
329
  "Search...": "Cerca...",
328
330
  "search_tip": "Cerca un luogo, un oggetto o una mappa",
329
331
  "searchFillColor": "Colore di riempimento dei risultati della ricerca",
@@ -16,7 +16,7 @@ declare class GirafeHTMLElement extends HTMLElement {
16
16
  private _context?;
17
17
  protected get context(): IGirafeContext;
18
18
  constructor(name: string, context?: IGirafeContext);
19
- get state(): import("../tools/main").GraphicalInterface;
19
+ get state(): import("../tools/main").State;
20
20
  getById<T = HTMLElement>(id: string): T;
21
21
  girafeTranslate(): void;
22
22
  userInfoChanged(): void;
@@ -4,7 +4,7 @@ import ConfigManager from '../../../tools/configuration/configmanager';
4
4
  import StateManager from '../../../tools/state/statemanager';
5
5
  declare class ViewManager {
6
6
  map: Map;
7
- get state(): import("../../../tools/main").GraphicalInterface;
7
+ get state(): import("../../../tools/main").State;
8
8
  get projection(): import("ol/proj").Projection;
9
9
  private readonly configManager;
10
10
  private readonly stateManager;
@@ -18,7 +18,7 @@ declare class WmtsManager {
18
18
  olayer: OLayer;
19
19
  layerWmts: LayerWmts;
20
20
  }>;
21
- get state(): import("../../../tools/main").GraphicalInterface;
21
+ get state(): import("../../../tools/main").State;
22
22
  constructor(map: Map, stateManager: StateManager);
23
23
  removeAllBasemapLayers(): void;
24
24
  addLayer(layer: LayerWmts): Promise<void>;
@@ -13,7 +13,7 @@ declare class PrintMaskManager {
13
13
  private possibleScales;
14
14
  scaleManuallySelected: boolean;
15
15
  constructor(map: Map, stateManager: StateManager);
16
- get state(): import("../../../tools/main").GraphicalInterface;
16
+ get state(): import("../../../tools/main").State;
17
17
  destroy(): void;
18
18
  setManuallySelectedScale(value: boolean): void;
19
19
  /**
@@ -19,7 +19,6 @@ declare class SearchComponent extends GirafeHTMLElement {
19
19
  private focusedResultIndex;
20
20
  private focusedResult;
21
21
  private selectedResult;
22
- private searchBox?;
23
22
  private searchInput?;
24
23
  paintSearchResults?: boolean;
25
24
  defaultSearchStrokeColor: string;
@@ -42,7 +42,6 @@ class SearchComponent extends GirafeHTMLElement {
42
42
  focusedResultIndex = -1;
43
43
  focusedResult = null;
44
44
  selectedResult = null;
45
- searchBox;
46
45
  searchInput;
47
46
  paintSearchResults;
48
47
  defaultSearchStrokeColor;
@@ -81,7 +80,7 @@ class SearchComponent extends GirafeHTMLElement {
81
80
  this.initColorPicker();
82
81
  }
83
82
  toggleVisibility(visible) {
84
- this.searchBox.style.display = visible ? 'flex' : 'none';
83
+ (this.shadowRoot?.host).style.display = visible ? 'flex' : 'none';
85
84
  }
86
85
  onMouseDown() {
87
86
  this.ignoreBlur = true;
@@ -100,7 +99,6 @@ class SearchComponent extends GirafeHTMLElement {
100
99
  render() {
101
100
  super.render();
102
101
  this.searchInput = this.shadowRoot?.getElementById('search');
103
- this.searchBox = this.shadowRoot?.getElementById('searchbox');
104
102
  }
105
103
  registerEvents() {
106
104
  this.subscribe('interface.searchComponentVisible', (_oldValue, newValue) => this.toggleVisibility(newValue));
@@ -1,4 +1,5 @@
1
1
  import GirafeHTMLElement from '../../base/GirafeHTMLElement';
2
+ import { ShareState } from './sharestate';
2
3
  declare class ShareComponent extends GirafeHTMLElement {
3
4
  template: () => import("uhtml").Hole;
4
5
  visible: boolean;
@@ -15,6 +16,7 @@ declare class ShareComponent extends GirafeHTMLElement {
15
16
  private simpleMaskManager?;
16
17
  private readonly eventsCallbacks;
17
18
  private iframeSize;
19
+ get shareState(): ShareState;
18
20
  get iframeWidth(): 400 | 600 | 800;
19
21
  get iframeHeight(): 300 | 600 | 450;
20
22
  constructor();
@@ -12,9 +12,9 @@ class ShareComponent extends GirafeHTMLElement {
12
12
  return uHtml `<style>
13
13
  *{font-family:Arial,sans-serif}.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}.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);width:1.2rem}.gg-range{accent-color:var(--text-color)}.gg-button{padding:0 .5rem}.gg-button.active{border:solid 1px var(--text-color-grad2);background-color:var(--text-color-grad2);color:var(--bkg-color)}.gg-button:disabled{color:gray;cursor:not-allowed;background-color:#d3d3d3;border:none}.gg-input:disabled,.gg-select:disabled,.gg-textarea:disabled{color:gray;cursor:not-allowed;background-color:#d3d3d3}.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-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,.gg-select:hover,.gg-input:hover,.gg-textarea:hover,.gg-icon-button:hover{background-color:var(--bkg-color-grad1)}.gg-opacity{opacity:.5}.gg-opacity:hover{opacity:1;background-color:#0000}.gg-tabs{cursor:pointer;border-bottom:1px solid gray;justify-content:left;align-items:end;gap:1rem;height:2rem;margin:.5rem auto 1rem;display:flex}.gg-tab{cursor:pointer;color:var(--text-color);background:0 0;border:none;padding:.5rem}.gg-tab.active{border-bottom:solid 2px var(--text-color-grad2);font-weight:600}.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}
14
14
  </style><style>
15
- #content{background:var(--bkg-color);color:var(--text-color);margin:0;padding:1rem}.group{padding-bottom:4em}.title{margin-top:0}.link{flex-direction:column;gap:.2rem;margin-top:.5rem;display:flex}.qrcode{opacity:.7;width:10rem;margin:2rem auto auto;display:block}.social{display:flex}.social button{cursor:pointer;background-color:#0000;border:none;margin:2rem auto auto}.social img{opacity:.7;width:3rem;filter:var(--svg-filter)}.social img:hover{opacity:1}input{flex-grow:1;font-size:.9rem}.error{color:var(--error-color);text-align:center;order:3;width:90%}.textarea-for-code{font-family:monospace,Arial,sans-serif;font-size:.75rem;line-height:1.1rem}.copy-success,.copy-success:hover{background-color:var(--success-color)}
15
+ #content{background:var(--bkg-color);color:var(--text-color);margin:0;padding:1rem}.group{padding-bottom:4em}.title{margin-top:0}.link{flex-direction:column;gap:.2rem;margin-top:.5rem;display:flex}.qrcode{opacity:.7;width:10rem;margin:2rem auto auto;display:block}.social{display:flex}.social button{cursor:pointer;background-color:#0000;border:none;margin:2rem auto auto}.social img{opacity:.7;width:3rem;filter:var(--svg-filter)}.social img:hover{opacity:1}input{flex-grow:1;font-size:.9rem}.error{color:var(--error-color);text-align:center;order:3;width:90%}.textarea-for-code{font-family:monospace,Arial,sans-serif;font-size:.75rem;line-height:1.1rem}.copy-success,.copy-success:hover{background-color:var(--success-color)}.checkbox-wrapper{flex-direction:row;justify-content:space-between;align-items:center;height:2rem;display:flex;& input[type=checkbox]{flex-grow:unset}}
16
16
  </style>
17
- <div id="panel"><div id="content"><div class="${!this.urlShortener ? '' : 'hidden'}"><div class="message" i18n="Error, the shortener service is not defined.">Error, the shortener service is not defined.</div></div><div id="share-map" class="${this.urlShortener ? 'group' : 'hidden'}"><h3 class="title" i18n="Share this map">Share this map</h3><div><div class="link"><input value="${this.shareLink}" class="gg-input" disabled="disabled"> <button id="btn-copy-short" class="gg-button" i18n="Generate and copy link" onclick="${() => this.generateAndCopyLink()}">Generate and copy link</button></div></div><img alt="share-qrcode" class="${(this.qrCode ? 'qrcode' : 'hidden')}" src="${this.qrCode}"><div class="${(this.success ? 'hidden' : 'qrcode error')}"><img alt="error-icon" src="icons/error.svg"> <span i18n="Error, can not fetch the shortener service. Please try again later.">Error, can not fetch the shortener service. Please try again later.</span></div><div class="social"><button onclick="${() => this.shareFacebook()}"><img alt="share-facebook" src="${this.facebookLogo}"></button> <button onclick="${() => this.shareTwitter()}"><img alt="share-twitter" src="${this.twitterLogo}"></button> <button onclick="${() => this.shareLinkedIn()}"><img alt="share-linkedin" src="${this.linkedInLogo}"></button> <button onclick="${() => this.shareMail()}"><img alt="share-mail" src="${this.mailLogo}"></button></div></div><div id="embed-map" class="${this.urlShortener ? 'group' : 'hidden'}"><h3 class="title" i18n="Embed this map">Embed this map</h3><div class="link"><select class="gg-select" id="logLevel" onchange="${(evt) => this.onSizeChanged(evt)}"><option ?selected="${this.iframeSize === ''}" i18n="Select map size..." value="">Select map size...<option ?selected="${this.iframeSize === 'small'}" i18n="Small" value="small">Small<option ?selected="${this.iframeSize === 'medium'}" i18n="Medium" value="medium">Medium<option ?selected="${this.iframeSize === 'large'}" i18n="Large" value="large">Large</select> <textarea value="${this.iframeCode}" class="gg-input gg-textarea textarea-for-code" disabled="disabled"></textarea> <button id="btn-copy-iframe" class="gg-button" i18n="Generate and copy code" ?disabled="${this.iframeSize === ''}" onclick="${() => this.generateAndCopyIframeCode()}">Generate and copy code</button></div></div></div></div>`;
17
+ <div id="panel"><div id="content"><div class="${!this.urlShortener ? '' : 'hidden'}"><div class="message" i18n="Error, the shortener service is not defined.">Error, the shortener service is not defined.</div></div><div id="share-map" class="${this.urlShortener ? 'group' : 'hidden'}"><h3 class="title" i18n="Share this map">Share this map</h3><div><div class="link"><input value="${this.shareLink}" class="gg-input" disabled="disabled"> <button id="btn-copy-short" class="gg-button" i18n="Generate and copy link" onclick="${() => this.generateAndCopyLink()}">Generate and copy link</button></div></div><img alt="share-qrcode" class="${(this.qrCode ? 'qrcode' : 'hidden')}" src="${this.qrCode}"><div class="${(this.success ? 'hidden' : 'qrcode error')}"><img alt="error-icon" src="icons/error.svg"> <span i18n="Error, can not fetch the shortener service. Please try again later.">Error, can not fetch the shortener service. Please try again later.</span></div><div class="social"><button onclick="${() => this.shareFacebook()}"><img alt="share-facebook" src="${this.facebookLogo}"></button> <button onclick="${() => this.shareTwitter()}"><img alt="share-twitter" src="${this.twitterLogo}"></button> <button onclick="${() => this.shareLinkedIn()}"><img alt="share-linkedin" src="${this.linkedInLogo}"></button> <button onclick="${() => this.shareMail()}"><img alt="share-mail" src="${this.mailLogo}"></button></div></div><div id="embed-map" class="${this.urlShortener ? 'group' : 'hidden'}"><h3 class="title" i18n="Embed this map">Embed this map</h3><div class="link"><select class="gg-select" id="logLevel" onchange="${(evt) => this.onSizeChanged(evt)}"><option ?selected="${this.iframeSize === ''}" i18n="Select map size..." value="">Select map size...<option ?selected="${this.iframeSize === 'small'}" i18n="Small" value="small">Small<option ?selected="${this.iframeSize === 'medium'}" i18n="Medium" value="medium">Medium<option ?selected="${this.iframeSize === 'large'}" i18n="Large" value="large">Large</select><div class="checkbox-wrapper"><label for="iframe-search-visible" i18n="Search visible">Search visible</label> <input type="checkbox" class="gg-checkbox" id="iframe-search-visible" value="${this.shareState.searchComponentVisible}" onchange="${(e) => this.shareState.searchComponentVisible = e.target.checked}"></div><div class="checkbox-wrapper"><label for="iframe-basemap-visible" i18n="Basemap visible">Basemap visible</label> <input type="checkbox" class="gg-checkbox" id="iframe-basemap-visible" value="${this.shareState.basemapComponentVisible}" onchange="${(e) => this.shareState.basemapComponentVisible = e.target.checked}"></div><textarea value="${this.iframeCode}" class="gg-input gg-textarea textarea-for-code" disabled="disabled"></textarea> <button id="btn-copy-iframe" class="gg-button" i18n="Generate and copy code" ?disabled="${this.iframeSize === ''}" onclick="${() => this.generateAndCopyIframeCode()}">Generate and copy code</button></div></div></div></div>`;
18
18
  };
19
19
  visible = false;
20
20
  shareLink;
@@ -30,6 +30,9 @@ class ShareComponent extends GirafeHTMLElement {
30
30
  simpleMaskManager;
31
31
  eventsCallbacks = [];
32
32
  iframeSize = '';
33
+ get shareState() {
34
+ return this.state.extendedState.share;
35
+ }
33
36
  get iframeWidth() {
34
37
  switch (this.iframeSize) {
35
38
  case 'small':
@@ -143,8 +146,9 @@ class ShareComponent extends GirafeHTMLElement {
143
146
  const baseUrl = this.context.urlManager.getRootUrl();
144
147
  const hash = this.context.shareManager.getStateToShare();
145
148
  // Get short URL for iframe
146
- const longIframeUrl = `${baseUrl}iframe.html#${hash}`;
147
- const response = await this.urlShortener.shortenUrl(longIframeUrl);
149
+ const indexDocument = `iframe.html`;
150
+ const longIframeUrl = `${baseUrl}${indexDocument}#${hash}`;
151
+ const response = await this.urlShortener.shortenUrl(longIframeUrl, indexDocument);
148
152
  this.iframeUrl = response.shorturl;
149
153
  this.iframeCode = `<iframe title="iframe GeoGirafe" width="${this.iframeWidth}" height="${this.iframeHeight}" src="${this.iframeUrl}"></iframe>`;
150
154
  }
@@ -0,0 +1,16 @@
1
+ import type { IBrainSerializable } from '../../tools/state/brain/decorators';
2
+ import type { IBrainSerializer } from '../../tools/state/brain/serialize';
3
+ import IGirafeContext from '../../tools/context/icontext';
4
+ export declare class ShareState implements IBrainSerializable {
5
+ isBrainSerializable: boolean;
6
+ searchComponentVisible: boolean;
7
+ basemapComponentVisible: boolean;
8
+ }
9
+ export declare class ShareStateSerializer implements IBrainSerializer<ShareState> {
10
+ private readonly context;
11
+ private readonly syncToInterface;
12
+ constructor(context: IGirafeContext, syncToInterface?: boolean);
13
+ private get state();
14
+ brainDeserialize(serialized: string): void;
15
+ brainSerialize(shareState: ShareState): string;
16
+ }
@@ -0,0 +1,27 @@
1
+ export class ShareState {
2
+ isBrainSerializable = true;
3
+ searchComponentVisible = false;
4
+ basemapComponentVisible = false;
5
+ }
6
+ export class ShareStateSerializer {
7
+ context;
8
+ syncToInterface;
9
+ constructor(context, syncToInterface = false) {
10
+ this.context = context;
11
+ this.syncToInterface = syncToInterface;
12
+ }
13
+ get state() {
14
+ return this.context.stateManager.state;
15
+ }
16
+ brainDeserialize(serialized) {
17
+ const deserializedShareState = JSON.parse(serialized);
18
+ this.state.extendedState.share = deserializedShareState;
19
+ if (this.syncToInterface) {
20
+ this.state.interface.searchComponentVisible = deserializedShareState.searchComponentVisible;
21
+ this.state.interface.basemapComponentVisible = deserializedShareState.basemapComponentVisible;
22
+ }
23
+ }
24
+ brainSerialize(shareState) {
25
+ return JSON.stringify(shareState);
26
+ }
27
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,32 @@
1
+ import { afterAll, beforeEach, describe, expect, it } from 'vitest';
2
+ import { ShareStateSerializer } from './sharestate';
3
+ import MockHelper from '../../tools/tests/mockhelper';
4
+ describe('ShareStateSerializer', () => {
5
+ const context = MockHelper.startMocking();
6
+ const defaultState = {
7
+ isBrainSerializable: false,
8
+ basemapComponentVisible: false,
9
+ searchComponentVisible: false
10
+ };
11
+ const serializedDefaultState = JSON.stringify(defaultState);
12
+ beforeEach(() => {
13
+ MockHelper.startMocking();
14
+ context.stateManager.state.interface.basemapComponentVisible = true;
15
+ context.stateManager.state.interface.searchComponentVisible = true;
16
+ });
17
+ afterAll(() => {
18
+ MockHelper.stopMocking(context);
19
+ });
20
+ it('deserialize and dont sync to state.interface', () => {
21
+ const serializer = new ShareStateSerializer(context);
22
+ serializer.brainDeserialize(serializedDefaultState);
23
+ expect(context.stateManager.state.interface.basemapComponentVisible).toEqual(true);
24
+ expect(context.stateManager.state.interface.searchComponentVisible).toEqual(true);
25
+ });
26
+ it('deserialize and do sync to state.interface', () => {
27
+ const serializer = new ShareStateSerializer(context, true);
28
+ serializer.brainDeserialize(serializedDefaultState);
29
+ expect(context.stateManager.state.interface.basemapComponentVisible).toEqual(false);
30
+ expect(context.stateManager.state.interface.searchComponentVisible).toEqual(false);
31
+ });
32
+ });
@@ -4,6 +4,6 @@ declare class GeoGirafeShareManager implements IUrlShortener {
4
4
  private readonly serviceUrl;
5
5
  private readonly urlManager;
6
6
  constructor(serviceUrl: string, urlManager: UrlManager);
7
- shortenUrl(longUrl: string): Promise<UrlShortenerResponse>;
7
+ shortenUrl(longUrl: string, indexDocument?: string): Promise<UrlShortenerResponse>;
8
8
  }
9
9
  export default GeoGirafeShareManager;
@@ -6,7 +6,7 @@ class GeoGirafeShareManager {
6
6
  this.serviceUrl = serviceUrl;
7
7
  this.urlManager = urlManager;
8
8
  }
9
- async shortenUrl(longUrl) {
9
+ async shortenUrl(longUrl, indexDocument) {
10
10
  const errorResponse = {
11
11
  success: false,
12
12
  shorturl: longUrl
@@ -25,7 +25,7 @@ class GeoGirafeShareManager {
25
25
  if (response_data) {
26
26
  const baseUrl = this.urlManager.getBaseUrlPath();
27
27
  const hash = response_data.short_url.split('/').pop();
28
- const shortUrl = `${baseUrl}#gg-${hash}`;
28
+ const shortUrl = `${baseUrl}${indexDocument ?? ''}#gg-${hash}`;
29
29
  const qrcode = await generateQrCode(shortUrl);
30
30
  return {
31
31
  success: true,
@@ -4,5 +4,5 @@ export type UrlShortenerResponse = {
4
4
  qrcode?: string;
5
5
  };
6
6
  export interface IUrlShortener {
7
- shortenUrl(longUrl: string): Promise<UrlShortenerResponse>;
7
+ shortenUrl(longUrl: string, indexDocument?: string): Promise<UrlShortenerResponse>;
8
8
  }
package/main.iframe.js CHANGED
@@ -3,7 +3,7 @@ import GeoGirafeApp from './tools/app/geogirafeapp';
3
3
  // Display the splash-screen
4
4
  const splash = new SplashScreen();
5
5
  splash.begin();
6
- const girafeApp = new GeoGirafeApp();
6
+ const girafeApp = new GeoGirafeApp(true);
7
7
  girafeApp.isReady().then(() => {
8
8
  // Remove the splash-screen
9
9
  splash.end();
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "name": "GeoGirafe PSC",
6
6
  "url": "https://doc.geomapfish.dev"
7
7
  },
8
- "version": "1.0.2141599510",
8
+ "version": "1.0.2149179221",
9
9
  "type": "module",
10
10
  "engines": {
11
11
  "node": ">=20.19.0"
package/styles/iframe.css CHANGED
@@ -45,5 +45,19 @@ girafe-map {
45
45
  }
46
46
 
47
47
  girafe-basemap {
48
- display: none !important;
48
+ display: block;
49
+ position: absolute;
50
+ left: 0.5rem;
51
+ bottom: 0.5rem;
52
+ }
53
+
54
+ girafe-search {
55
+ display: block;
56
+ width: 25vw;
57
+ height: 2.25rem;
58
+ position: absolute;
59
+ top: 0.5rem;
60
+ left: 50%;
61
+ transform: translate(-50%, 0);
62
+ box-shadow: 0 1px 4px #0000004d;
49
63
  }
@@ -84,6 +84,7 @@
84
84
  <div id="main">
85
85
  <girafe-map></girafe-map>
86
86
  <girafe-basemap></girafe-basemap>
87
+ <girafe-search id="search"></girafe-search>
87
88
  </div>
88
89
  </div>
89
90
  </girafe-app>
@@ -1 +1 @@
1
- {"version":"1.0.2141599510", "build":"2141599510", "date":"05/11/2025"}
1
+ {"version":"1.0.2149179221", "build":"2149179221", "date":"10/11/2025"}
@@ -2,8 +2,9 @@ export default class GeoGirafeApp {
2
2
  private readonly readyPromise;
3
3
  private resolveReady;
4
4
  private mainComponent;
5
+ private readonly isIframe;
5
6
  protected get context(): import("../context/icontext").default;
6
- constructor();
7
+ constructor(isIframe?: boolean);
7
8
  isReady(): Promise<void>;
8
9
  protected initialize(): Promise<void>;
9
10
  protected defineMainComponent(): void;
@@ -42,14 +42,17 @@ import UserPreferencesComponent from '../../components/userpreferences/component
42
42
  import VideoRecordComponent from '../../components/videorecord/component';
43
43
  import { DrawingState } from '../../components/drawing/drawingFeature';
44
44
  import DrawingSerializer from '../../components/drawing/drawingSerializer';
45
+ import { ShareState, ShareStateSerializer } from '../../components/share/sharestate';
45
46
  export default class GeoGirafeApp {
46
47
  readyPromise;
47
48
  resolveReady;
48
49
  mainComponent;
50
+ isIframe;
49
51
  get context() {
50
52
  return this.mainComponent.getContext();
51
53
  }
52
- constructor() {
54
+ constructor(isIframe = false) {
55
+ this.isIframe = isIframe;
53
56
  this.readyPromise = new Promise((resolve) => {
54
57
  this.resolveReady = resolve;
55
58
  });
@@ -84,6 +87,8 @@ export default class GeoGirafeApp {
84
87
  // TODO REG : Is this not done too late ? We need to check this, perhaps it shouol dbe done before the intialization of the share
85
88
  this.context.stateManager.state.extendedState.drawing = new DrawingState();
86
89
  this.context.stateSerializer.addSerializer(DrawingState, new DrawingSerializer(this.context));
90
+ this.context.stateManager.state.extendedState.share = new ShareState();
91
+ this.context.stateSerializer.addSerializer(ShareState, new ShareStateSerializer(this.context, this.isIframe));
87
92
  }
88
93
  defineCoreComponents() {
89
94
  customElements.define('girafe-about', AboutComponent);
@@ -3,7 +3,7 @@ export default abstract class AbstractConnectManager {
3
3
  private readonly storagePath;
4
4
  protected readonly context: IGirafeContext;
5
5
  constructor(context: IGirafeContext);
6
- protected get state(): import("../main").GraphicalInterface;
6
+ protected get state(): import("../main").State;
7
7
  abstract initialize(): Promise<void>;
8
8
  abstract login(): Promise<void>;
9
9
  abstract silentLogin(): Promise<void>;
@@ -3,7 +3,7 @@ export default class GMFManager {
3
3
  private readonly context;
4
4
  constructor(context: IGirafeContext);
5
5
  private get isOAuth();
6
- get state(): import("../main").GraphicalInterface;
6
+ get state(): import("../main").State;
7
7
  get gmfConfigForOAuth(): {
8
8
  userInfoUrl: string;
9
9
  loginUrl: string;
@@ -9,7 +9,7 @@ declare class LayerManager extends GirafeSingleton {
9
9
  #private;
10
10
  private readonly layerClones;
11
11
  private readonly layerIdToClone;
12
- get state(): import("../main").GraphicalInterface;
12
+ get state(): import("../main").State;
13
13
  initializeSingleton(): void;
14
14
  private onLayersListChanged;
15
15
  private fillLayerIdToClone;
package/tools/main.d.ts CHANGED
@@ -41,11 +41,12 @@ export { default as SessionManager } from './share/sessionmanager';
41
41
  export { default as ShareManager } from './share/sharemanager';
42
42
  export { default as StateSerializer } from './share/stateserializer';
43
43
  export { default as ComponentManager } from './state/componentManager';
44
+ export { default as GraphicalInterface } from './state/graphicalInterface';
44
45
  export { default as LayersConfig } from './state/layersConfig';
45
46
  export { default as MapManager } from './state/mapManager';
46
47
  export { default as MapPosition } from './state/mapposition';
47
48
  export { default as ObjectSelection } from './state/objectselection';
48
- export { default as GraphicalInterface } from './state/state';
49
+ export { default as State } from './state/state';
49
50
  export { default as StateToggleManager } from './state/stateToggleManager';
50
51
  export { default as StateManager } from './state/statemanager';
51
52
  export { default as UserInteractionManager } from './state/userInteractionManager';
package/tools/main.js CHANGED
@@ -41,11 +41,12 @@ export { default as SessionManager } from './share/sessionmanager';
41
41
  export { default as ShareManager } from './share/sharemanager';
42
42
  export { default as StateSerializer } from './share/stateserializer';
43
43
  export { default as ComponentManager } from './state/componentManager';
44
+ export { default as GraphicalInterface } from './state/graphicalInterface';
44
45
  export { default as LayersConfig } from './state/layersConfig';
45
46
  export { default as MapManager } from './state/mapManager';
46
47
  export { default as MapPosition } from './state/mapposition';
47
48
  export { default as ObjectSelection } from './state/objectselection';
48
- export { default as GraphicalInterface } from './state/state';
49
+ export { default as State } from './state/state';
49
50
  export { default as StateToggleManager } from './state/stateToggleManager';
50
51
  export { default as StateManager } from './state/statemanager';
51
52
  export { default as UserInteractionManager } from './state/userInteractionManager';
@@ -15,7 +15,7 @@ export default abstract class OgcApiClient<Server = ServerOgcApi> {
15
15
  private readonly stateManager;
16
16
  protected readonly options: OgcApiClientOptions;
17
17
  initialized: boolean;
18
- get state(): import("../main").GraphicalInterface;
18
+ get state(): import("../main").State;
19
19
  get url(): string;
20
20
  protected constructor(serverOgc: ServerOgc, opt: OgcApiClientOptions, stateManager: StateManager);
21
21
  getServer(): Promise<Server>;
@@ -11,7 +11,7 @@ import { OgcApiClientOptions } from './ogcapiclient';
11
11
  * Manages interaction between the GG and an OGC API Features client (OAPIF).
12
12
  */
13
13
  export default class OgcApiFeaturesManager extends VendorSpecificOgcServerManager<OgcApiFeaturesClient, OgcApiClientOptions> {
14
- get state(): import("../main").GraphicalInterface;
14
+ get state(): import("../main").State;
15
15
  getClientId(ogcServer: ServerOgc): string;
16
16
  initializeSingleton(): void;
17
17
  getSchema(layer: OapifLayer): Promise<OgcApiFeaturesSchema>;
@@ -1,6 +1,6 @@
1
1
  import IGirafeContext from '../../context/icontext';
2
2
  import { IBrainSerializer } from '../../state/brain/serialize';
3
- import { GraphicalInterface } from '../../state/state';
3
+ import GraphicalInterface from '../../state/graphicalInterface';
4
4
  export default class InterfaceSerializer implements IBrainSerializer<GraphicalInterface> {
5
5
  private readonly context;
6
6
  constructor(context: IGirafeContext);
@@ -4,11 +4,11 @@ import MapPosition from '../state/mapposition';
4
4
  import LayersConfig from '../state/layersConfig';
5
5
  import LayersConfigSerializer from './serializers/layerconfigserializer';
6
6
  import ActiveBasemapsSerializer from './serializers/activebasemapsserializer';
7
- import { GraphicalInterface } from '../state/state';
8
7
  import GirafeSingleton from '../../base/GirafeSingleton';
9
8
  import BrainSerializer from '../state/brain/serialize';
10
9
  import SelectionSerializer from './serializers/selectionserializer';
11
10
  import ObjectSelection from '../state/objectselection';
11
+ import GraphicalInterface from '../state/graphicalInterface';
12
12
  import InterfaceSerializer from './serializers/interfaceserializer';
13
13
  class StateSerializer extends GirafeSingleton {
14
14
  brainSerializer = new BrainSerializer();
@@ -0,0 +1,24 @@
1
+ import { SwipeupPanelMode } from './swipeuppanelmode';
2
+ export default class GraphicalInterface {
3
+ isMobile: boolean;
4
+ helpVisible: boolean;
5
+ drawingPanelVisible: boolean;
6
+ printPanelVisible: boolean;
7
+ extLayerPanelVisible: boolean;
8
+ crossSectionPanelVisible: boolean;
9
+ editPanelVisible: boolean;
10
+ sharePanelVisible: boolean;
11
+ selectionComponentVisible: boolean;
12
+ selectionComponent: string;
13
+ layoutPanelVisible: boolean;
14
+ aboutPanelVisible: boolean;
15
+ userPreferencesPanelVisible: boolean;
16
+ infoWindowVisible: boolean;
17
+ searchComponentVisible: boolean;
18
+ basemapComponentVisible: boolean;
19
+ darkMapMode: boolean;
20
+ darkFrontendMode: boolean;
21
+ swipeupPanelMode: SwipeupPanelMode;
22
+ contactPanelVisible: boolean;
23
+ swipeupPanelContent: 'selector' | 'features' | 'menu' | 'drawing' | 'offline' | null;
24
+ }
@@ -0,0 +1,25 @@
1
+ import { systemIsInDarkMode } from '../utils/utils';
2
+ export default class GraphicalInterface {
3
+ isMobile = false;
4
+ helpVisible = false;
5
+ drawingPanelVisible = false;
6
+ printPanelVisible = false;
7
+ extLayerPanelVisible = false;
8
+ crossSectionPanelVisible = false;
9
+ editPanelVisible = false;
10
+ sharePanelVisible = false;
11
+ selectionComponentVisible = false;
12
+ selectionComponent = '';
13
+ layoutPanelVisible = false;
14
+ aboutPanelVisible = false;
15
+ userPreferencesPanelVisible = false;
16
+ infoWindowVisible = false;
17
+ searchComponentVisible = true;
18
+ basemapComponentVisible = true;
19
+ darkMapMode = false;
20
+ // TODO: remove of adjust this when the component UserDataManager is monted on mobile UI
21
+ darkFrontendMode = systemIsInDarkMode() ?? false;
22
+ swipeupPanelMode = 'closed';
23
+ contactPanelVisible = false;
24
+ swipeupPanelContent = 'selector';
25
+ }
@@ -9,30 +9,7 @@ import type { GgUserInteractionListener } from './userInteractionManager';
9
9
  import type CustomTheme from '../../models/customtheme';
10
10
  import ObjectSelection from './objectselection';
11
11
  import type Theme from '../../models/theme';
12
- export declare class GraphicalInterface {
13
- isMobile: boolean;
14
- helpVisible: boolean;
15
- drawingPanelVisible: boolean;
16
- printPanelVisible: boolean;
17
- extLayerPanelVisible: boolean;
18
- lidarPanelVisible: boolean;
19
- crossSectionPanelVisible: boolean;
20
- editPanelVisible: boolean;
21
- sharePanelVisible: boolean;
22
- selectionComponentVisible: boolean;
23
- selectionComponent: string;
24
- layoutPanelVisible: boolean;
25
- aboutPanelVisible: boolean;
26
- userPreferencesPanelVisible: boolean;
27
- infoWindowVisible: boolean;
28
- searchComponentVisible: boolean;
29
- basemapComponentVisible: boolean;
30
- darkMapMode: boolean;
31
- darkFrontendMode: boolean;
32
- swipeupPanelMode: string;
33
- contactPanelVisible: boolean;
34
- swipeupPanelContent: 'selector' | 'features' | 'menu' | 'drawing' | 'offline' | null;
35
- }
12
+ import GraphicalInterface from './graphicalInterface';
36
13
  export type ThemesConfig = {
37
14
  _allThemes: Record<number, ThemeLayer>;
38
15
  isLoaded: boolean;
@@ -108,15 +85,6 @@ export type InfoWindow = {
108
85
  left: string | number | null;
109
86
  };
110
87
  export type ExtendedState = Record<string, object>;
111
- /**
112
- * The pannel can be:
113
- * - "closed": it is invisible, below screen
114
- * - "reduced": only a small tray is visible at the bottom of the screen
115
- * - "half": about half of the screen
116
- * - "full": the pannel is fully open, covering up to almost the top of the screen
117
- * - "manual": a state reserved for when the panel handle was used to manually adjust the panel height
118
- */
119
- export type SwipeupPanelMode = 'closed' | 'reduced' | 'half' | 'full' | 'manual';
120
88
  export default class State {
121
89
  /**
122
90
  * This class is a used as the state of the application, which will be accessed behind a javascript proxy.
@@ -7,33 +7,8 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
7
7
  import MapPosition from './mapposition';
8
8
  import { BrainSerialize } from './brain/decorators';
9
9
  import LayersConfig from './layersConfig';
10
- import { systemIsInDarkMode } from '../utils/utils';
11
10
  import ObjectSelection from './objectselection';
12
- export class GraphicalInterface {
13
- isMobile = false;
14
- helpVisible = false;
15
- drawingPanelVisible = false;
16
- printPanelVisible = false;
17
- extLayerPanelVisible = false;
18
- lidarPanelVisible = false;
19
- crossSectionPanelVisible = false;
20
- editPanelVisible = false;
21
- sharePanelVisible = false;
22
- selectionComponentVisible = false;
23
- selectionComponent = '';
24
- layoutPanelVisible = false;
25
- aboutPanelVisible = false;
26
- userPreferencesPanelVisible = false;
27
- infoWindowVisible = false;
28
- searchComponentVisible = true;
29
- basemapComponentVisible = true;
30
- darkMapMode = false;
31
- // TODO: remove of adjust this when the component UserDataManager is monted on mobile UI
32
- darkFrontendMode = systemIsInDarkMode() ?? false;
33
- swipeupPanelMode = 'closed';
34
- contactPanelVisible = false;
35
- swipeupPanelContent = 'selector';
36
- }
11
+ import GraphicalInterface from './graphicalInterface';
37
12
  export default class State {
38
13
  /**
39
14
  * This class is a used as the state of the application, which will be accessed behind a javascript proxy.
@@ -0,0 +1,9 @@
1
+ /**
2
+ * The pannel can be:
3
+ * - "closed": it is invisible, below screen
4
+ * - "reduced": only a small tray is visible at the bottom of the screen
5
+ * - "half": about half of the screen
6
+ * - "full": the pannel is fully open, covering up to almost the top of the screen
7
+ * - "manual": a state reserved for when the panel handle was used to manually adjust the panel height
8
+ */
9
+ export type SwipeupPanelMode = 'closed' | 'reduced' | 'half' | 'full' | 'manual';
@@ -0,0 +1 @@
1
+ export {};
@@ -5,7 +5,7 @@ import Layer from '../../models/layers/layer';
5
5
  import ThemeLayer from '../../models/layers/themelayer';
6
6
  export default class ThemesHelper extends GirafeSingleton {
7
7
  initializeSingleton(): void;
8
- get state(): import("../main").GraphicalInterface;
8
+ get state(): import("../main").State;
9
9
  findBaseLayerById(layerId: number): BaseLayer;
10
10
  private findBaseLayerRecurviveById;
11
11
  findThemeByName(themename: string): ThemeLayer | null;
@@ -5,7 +5,7 @@ declare class ThemesManager extends GirafeSingleton {
5
5
  anonymousUserInfo: {
6
6
  u: string;
7
7
  };
8
- get state(): import("../main").GraphicalInterface;
8
+ get state(): import("../main").State;
9
9
  initializeSingleton(): void;
10
10
  private initialize;
11
11
  private restoreState;
@@ -14,7 +14,7 @@ type UserThemeConfig = {
14
14
  export default class UserLayerManager extends GirafeSingleton {
15
15
  themeLayerItemIds: Record<string, string>;
16
16
  userThemeConfig: Record<string, UserThemeConfig>;
17
- get state(): import("../main").GraphicalInterface;
17
+ get state(): import("../main").State;
18
18
  private getThemeLayerByTreeId;
19
19
  private getUserLayerByTreeId;
20
20
  private getOrCreateThemeLayer;
@@ -19,7 +19,7 @@ export default class WfsClient<WfsXmlTypes = XmlTypes> {
19
19
  #private;
20
20
  private readonly context;
21
21
  version: string;
22
- get state(): import("../main").GraphicalInterface;
22
+ get state(): import("../main").State;
23
23
  ogcServer: ServerOgc;
24
24
  maxFeatures: number;
25
25
  featurePrefix: string;
@@ -6,7 +6,7 @@ import ServerOgc from '../../models/serverogc';
6
6
  import VendorSpecificOgcServerManager from '../vendorspecificogcservermanager';
7
7
  import Feature from 'ol/Feature';
8
8
  export default class WfsManager extends VendorSpecificOgcServerManager<WfsClient, WfsClientOptionalOptions> {
9
- get state(): import("../main").GraphicalInterface;
9
+ get state(): import("../main").State;
10
10
  getClientId(ogcServer: ServerOgc): string;
11
11
  static readonly UnknownFeatureType: string;
12
12
  initializeSingleton(): void;
@@ -13,7 +13,7 @@ export default abstract class WmsClient {
13
13
  resolutionTolerance: number;
14
14
  capabilityPromise: Promise<Record<string, unknown>> | null;
15
15
  capabilities: Record<string, unknown> | null;
16
- get state(): import("../main").GraphicalInterface;
16
+ get state(): import("../main").State;
17
17
  get audienceExcludedPaths(): string[];
18
18
  layers: LayerWms[];
19
19
  olayer?: ImageLayer<ImageWMS>;