@geogirafe/lib-geoportal 1.1.0-dev.2468094514 → 1.1.0-dev.2507911619

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.
package/README.md CHANGED
@@ -243,6 +243,15 @@ For major changes, please open an issue first to discuss what you would like to
243
243
  Contribution guidelines are available here: [CONTRIBUTING.md](CONTRIBUTING.md).
244
244
  **Please read them before contributing.**
245
245
 
246
+ # Supporting
247
+
248
+ There are many ways to support GeoGirafe.
249
+
250
+ - You can use the following tag on your project to help promote GeoGirafe:
251
+ [![GeoGirafe](https://geogirafe.org/wp-content/uploads/geogirafe-badge.svg)](https://geogirafe.org)
252
+ - If you are interested in providing financial assistance, please reach out to us at contact@geogirafe.org.
253
+ - If you have another idea how to support the project, we invite you to join us on the dedicaced discord server: https://discord.gg/kdrXjaqBbH.
254
+
246
255
  # License
247
256
 
248
257
  Apache License, Version 2.0
@@ -55,6 +55,7 @@
55
55
  "Copy ShortUrl": "Kurz-URL kopieren",
56
56
  "Copy to Clipboard": "In die Zwischenablage kopieren",
57
57
  "Copy value": "Wert kopieren",
58
+ "copy-cell-content": "Zelleninhalt kopieren",
58
59
  "Create custom theme": "Thema erstellen",
59
60
  "cross-section-settings": "Querschnitt",
60
61
  "CSV export": "CSV-Export",
@@ -155,6 +156,7 @@
155
156
  "fr": "Französisch",
156
157
  "Freehand line": "Freihandlinie",
157
158
  "Freehand polygon": "Freihandpolygon",
159
+ "freeze-column": "Spalte fixieren",
158
160
  "Generate and copy code": "Code generieren und kopieren",
159
161
  "Generate and copy link": "Link generieren und kopieren",
160
162
  "Generate CSV": "CSV generieren",
@@ -440,6 +442,7 @@
440
442
  "Toggle all legends": "Alle Legenden umschalten",
441
443
  "Toggle legend": "Legende umschalten",
442
444
  "Tools": "Werkzeuge",
445
+ "unfreeze-column": "Spaltenfixierung aufheben",
443
446
  "Unselect all filtered layers": "Alle Layers im Filter abwählen",
444
447
  "Unsupported file format": "Nicht unterstütztes Dateiformat",
445
448
  "URL (auto_WMTS)": "URL",
@@ -55,6 +55,7 @@
55
55
  "Copy ShortUrl": "Copy ShortUrl",
56
56
  "Copy to Clipboard": "Copy to Clipboard",
57
57
  "Copy value": "Copier value",
58
+ "copy-cell-content": "Copy cell content",
58
59
  "Create custom theme": "Create custom theme",
59
60
  "cross-section-settings": "Cross-section",
60
61
  "CSV export": "CSV export",
@@ -156,6 +157,7 @@
156
157
  "fr": "French",
157
158
  "Freehand line": "Freehand line",
158
159
  "Freehand polygon": "Freehand polygon",
160
+ "freeze-column": "Freeze column",
159
161
  "Generate and copy code": "Generate and copy code",
160
162
  "Generate and copy link": "Generate and copy link",
161
163
  "Generate CSV": "Generate CSV",
@@ -442,6 +444,7 @@
442
444
  "Toggle all legends": "Toggle all legends",
443
445
  "Toggle legend": "Toggle legend",
444
446
  "Tools": "Tools",
447
+ "unfreeze-column": "Unfreeze column",
445
448
  "Unselect all filtered layers": "Unselect all filtered layers",
446
449
  "Unsupported file format": "Unsupported file format",
447
450
  "URL (auto_WMTS)": "URL",
@@ -55,6 +55,7 @@
55
55
  "Copy ShortUrl": "Copier le lien court",
56
56
  "Copy to Clipboard": "Copier dans le presse-papiers",
57
57
  "Copy value": "Copier la valeur",
58
+ "copy-cell-content": "Copier le contenu de la cellule",
58
59
  "Create custom theme": "Créer un thème personnalisé",
59
60
  "cross-section-settings": "Coupe transversale",
60
61
  "CSV export": "Export CSV",
@@ -155,6 +156,7 @@
155
156
  "fr": "Français",
156
157
  "Freehand line": "Ligne à main levée",
157
158
  "Freehand polygon": "Polygone à main levée",
159
+ "freeze-column": "Figer la colonne",
158
160
  "Generate and copy code": "Générer et copier le code",
159
161
  "Generate and copy link": "Générer et copier le lien",
160
162
  "Generate CSV": "Générer CSV",
@@ -440,6 +442,7 @@
440
442
  "Toggle all legends": "Afficher / Masquer toutes les légendes",
441
443
  "Toggle legend": "Afficher / Masquer la légende",
442
444
  "Tools": "Outis",
445
+ "unfreeze-column": "Libérer la colonne",
443
446
  "Unselect all filtered layers": "Déselectionner toutes les couches filtrées",
444
447
  "Unsupported file format": "Format de fichier non supporté",
445
448
  "URL (auto_WMTS)": "URL",
@@ -55,6 +55,7 @@
55
55
  "Copy ShortUrl": "Copia ShortUrl",
56
56
  "Copy to Clipboard": "Copia negli appunti",
57
57
  "Copy value": "Copia il valore",
58
+ "copy-cell-content": "Copia contenuto cella",
58
59
  "Create custom theme": "Crea un tema personalizzato",
59
60
  "cross-section-settings": "Sezione trasversale",
60
61
  "CSV export": "Esporta CSV",
@@ -155,6 +156,7 @@
155
156
  "fr": "Francese",
156
157
  "Freehand line": "Linea a mano libera",
157
158
  "Freehand polygon": "Poligono a mano libera",
159
+ "freeze-column": "Blocca colonna",
158
160
  "Generate and copy code": "Genera e copia il codice",
159
161
  "Generate and copy link": "Genera e copia il link",
160
162
  "Generate CSV": "Genera CSV",
@@ -440,6 +442,7 @@
440
442
  "Toggle all legends": "Attiva / Disattiva tutte le legende",
441
443
  "Toggle legend": "Attiva / Disattiva legenda",
442
444
  "Tools": "Strumenti",
445
+ "unfreeze-column": "Sblocca colonna",
443
446
  "Unselect all filtered layers": "Deselezionare tutti i layers filtrati",
444
447
  "Unsupported file format": "Formato di file non supportato",
445
448
  "URL (auto_WMTS)": "URL",
@@ -20,7 +20,7 @@ class SelectionGridComponent extends GirafeResizableElement {
20
20
  </style><style>
21
21
  .tabulator{text-align:left;background-color:#888;border:1px solid #999;font-size:14px;position:relative;overflow:hidden;-webkit-transform:translateZ(0);-moz-transform:translateZ(0);-ms-transform:translateZ(0);-o-transform:translateZ(0);transform:translateZ(0)}.tabulator[tabulator-layout=fitDataFill] .tabulator-tableholder .tabulator-table{min-width:100%}.tabulator[tabulator-layout=fitDataTable]{display:inline-block}.tabulator.tabulator-block-select,.tabulator.tabulator-ranges .tabulator-cell:not(.tabulator-editing){user-select:none}.tabulator .tabulator-header{box-sizing:border-box;color:#555;-webkit-user-select:none;-moz-user-select:none;-khtml-user-select:none;-o-user-select:none;white-space:nowrap;background-color:#e6e6e6;border-bottom:1px solid #999;outline:none;width:100%;font-weight:700;position:relative;overflow:hidden}.tabulator .tabulator-header.tabulator-header-hidden{display:none}.tabulator .tabulator-header .tabulator-header-contents{position:relative;overflow:hidden}.tabulator .tabulator-header .tabulator-header-contents .tabulator-headers{display:inline-block}.tabulator .tabulator-header .tabulator-col{box-sizing:border-box;text-align:left;vertical-align:bottom;background:#e6e6e6;border-right:1px solid #aaa;flex-direction:column;justify-content:flex-start;display:inline-flex;position:relative;overflow:hidden}.tabulator .tabulator-header .tabulator-col.tabulator-moving{pointer-events:none;background:#cdcdcd;border:1px solid #999;position:absolute}.tabulator .tabulator-header .tabulator-col.tabulator-range-highlight{color:#000;background-color:#d6d6d6}.tabulator .tabulator-header .tabulator-col.tabulator-range-selected{color:#fff;background-color:#3876ca}.tabulator .tabulator-header .tabulator-col .tabulator-col-content{box-sizing:border-box;padding:4px;position:relative}.tabulator .tabulator-header .tabulator-col .tabulator-col-content .tabulator-header-popup-button{padding:0 8px}.tabulator .tabulator-header .tabulator-col .tabulator-col-content .tabulator-header-popup-button:hover{cursor:pointer;opacity:.6}.tabulator .tabulator-header .tabulator-col .tabulator-col-content .tabulator-col-title-holder{position:relative}.tabulator .tabulator-header .tabulator-col .tabulator-col-content .tabulator-col-title{box-sizing:border-box;text-overflow:ellipsis;vertical-align:bottom;white-space:nowrap;width:100%;overflow:hidden}.tabulator .tabulator-header .tabulator-col .tabulator-col-content .tabulator-col-title.tabulator-col-title-wrap{text-overflow:clip;white-space:normal}.tabulator .tabulator-header .tabulator-col .tabulator-col-content .tabulator-col-title .tabulator-title-editor{box-sizing:border-box;background:#fff;border:1px solid #999;width:100%;padding:1px}.tabulator .tabulator-header .tabulator-col .tabulator-col-content .tabulator-col-title .tabulator-header-popup-button+.tabulator-title-editor{width:calc(100% - 22px)}.tabulator .tabulator-header .tabulator-col .tabulator-col-content .tabulator-col-sorter{align-items:center;display:flex;position:absolute;top:0;bottom:0;right:4px}.tabulator .tabulator-header .tabulator-col .tabulator-col-content .tabulator-col-sorter .tabulator-arrow{border-bottom:6px solid #bbb;border-left:6px solid #0000;border-right:6px solid #0000;width:0;height:0}.tabulator .tabulator-header .tabulator-col.tabulator-col-group .tabulator-col-group-cols{border-top:1px solid #aaa;margin-right:-1px;display:flex;position:relative;overflow:hidden}.tabulator .tabulator-header .tabulator-col .tabulator-header-filter{box-sizing:border-box;text-align:center;width:100%;margin-top:2px;position:relative}.tabulator .tabulator-header .tabulator-col .tabulator-header-filter textarea{height:auto!important}.tabulator .tabulator-header .tabulator-col .tabulator-header-filter svg{margin-top:3px}.tabulator .tabulator-header .tabulator-col .tabulator-header-filter input::-ms-clear{width:0;height:0}.tabulator .tabulator-header .tabulator-col.tabulator-sortable .tabulator-col-title{padding-right:25px}@media (hover:hover) and (pointer:fine){.tabulator .tabulator-header .tabulator-col.tabulator-sortable.tabulator-col-sorter-element:hover{cursor:pointer;background-color:#cdcdcd}}.tabulator .tabulator-header .tabulator-col.tabulator-sortable[aria-sort=none] .tabulator-col-content .tabulator-col-sorter{color:#bbb}@media (hover:hover) and (pointer:fine){.tabulator .tabulator-header .tabulator-col.tabulator-sortable[aria-sort=none] .tabulator-col-content .tabulator-col-sorter.tabulator-col-sorter-element .tabulator-arrow:hover{cursor:pointer;border-bottom:6px solid #555}}.tabulator .tabulator-header .tabulator-col.tabulator-sortable[aria-sort=none] .tabulator-col-content .tabulator-col-sorter .tabulator-arrow{border-top:none;border-bottom:6px solid #bbb}.tabulator .tabulator-header .tabulator-col.tabulator-sortable[aria-sort=ascending] .tabulator-col-content .tabulator-col-sorter{color:#666}@media (hover:hover) and (pointer:fine){.tabulator .tabulator-header .tabulator-col.tabulator-sortable[aria-sort=ascending] .tabulator-col-content .tabulator-col-sorter.tabulator-col-sorter-element .tabulator-arrow:hover{cursor:pointer;border-bottom:6px solid #555}}.tabulator .tabulator-header .tabulator-col.tabulator-sortable[aria-sort=ascending] .tabulator-col-content .tabulator-col-sorter .tabulator-arrow{border-top:none;border-bottom:6px solid #666}.tabulator .tabulator-header .tabulator-col.tabulator-sortable[aria-sort=descending] .tabulator-col-content .tabulator-col-sorter{color:#666}@media (hover:hover) and (pointer:fine){.tabulator .tabulator-header .tabulator-col.tabulator-sortable[aria-sort=descending] .tabulator-col-content .tabulator-col-sorter.tabulator-col-sorter-element .tabulator-arrow:hover{cursor:pointer;border-top:6px solid #555}}.tabulator .tabulator-header .tabulator-col.tabulator-sortable[aria-sort=descending] .tabulator-col-content .tabulator-col-sorter .tabulator-arrow{color:#666;border-top:6px solid #666;border-bottom:none}.tabulator .tabulator-header .tabulator-col.tabulator-col-vertical .tabulator-col-content .tabulator-col-title{text-orientation:mixed;writing-mode:vertical-rl;justify-content:center;align-items:center;display:flex}.tabulator .tabulator-header .tabulator-col.tabulator-col-vertical.tabulator-col-vertical-flip .tabulator-col-title{transform:rotate(180deg)}.tabulator .tabulator-header .tabulator-col.tabulator-col-vertical.tabulator-sortable .tabulator-col-title{padding-top:20px;padding-right:0}.tabulator .tabulator-header .tabulator-col.tabulator-col-vertical.tabulator-sortable.tabulator-col-vertical-flip .tabulator-col-title{padding-bottom:20px;padding-right:0}.tabulator .tabulator-header .tabulator-col.tabulator-col-vertical.tabulator-sortable .tabulator-col-sorter{justify-content:center;inset:4px 0 auto}.tabulator .tabulator-header .tabulator-frozen{z-index:11;position:sticky;left:0}.tabulator .tabulator-header .tabulator-frozen.tabulator-frozen-left{border-right:2px solid #aaa}.tabulator .tabulator-header .tabulator-frozen.tabulator-frozen-right{border-left:2px solid #aaa}.tabulator .tabulator-header .tabulator-calcs-holder{box-sizing:border-box;border-top:1px solid #aaa;border-bottom:1px solid #aaa;display:inline-block;background:#f3f3f3!important}.tabulator .tabulator-header .tabulator-calcs-holder .tabulator-row{background:#f3f3f3!important}.tabulator .tabulator-header .tabulator-calcs-holder .tabulator-row .tabulator-col-resize-handle{display:none}.tabulator .tabulator-header .tabulator-frozen-rows-holder{padding-top:1em;display:inline-block}.tabulator .tabulator-header .tabulator-frozen-rows-holder:empty{display:none}.tabulator .tabulator-tableholder{-webkit-overflow-scrolling:touch;white-space:nowrap;width:100%;position:relative;overflow:auto}.tabulator .tabulator-tableholder:focus{outline:none}.tabulator .tabulator-tableholder .tabulator-placeholder{box-sizing:border-box;justify-content:center;align-items:center;width:100%;min-width:100%;display:flex}.tabulator .tabulator-tableholder .tabulator-placeholder[tabulator-render-mode=virtual]{min-height:100%}.tabulator .tabulator-tableholder .tabulator-placeholder .tabulator-placeholder-contents{color:#ccc;text-align:center;white-space:normal;padding:10px;font-size:20px;font-weight:700;display:inline-block}.tabulator .tabulator-tableholder .tabulator-table{color:#333;white-space:nowrap;background-color:#fff;display:inline-block;position:relative;overflow:visible}.tabulator .tabulator-tableholder .tabulator-table .tabulator-row.tabulator-calcs{font-weight:700;background:#e2e2e2!important}.tabulator .tabulator-tableholder .tabulator-table .tabulator-row.tabulator-calcs.tabulator-calcs-top{border-bottom:2px solid #aaa}.tabulator .tabulator-tableholder .tabulator-table .tabulator-row.tabulator-calcs.tabulator-calcs-bottom{border-top:2px solid #aaa}.tabulator .tabulator-tableholder .tabulator-range-overlay{pointer-events:none;z-index:10;position:absolute;inset:0}.tabulator .tabulator-tableholder .tabulator-range-overlay .tabulator-range{box-sizing:border-box;border:1px solid #2975dd;position:absolute}.tabulator .tabulator-tableholder .tabulator-range-overlay .tabulator-range.tabulator-range-active:after{content:"";background-color:#2975dd;border-radius:999px;width:6px;height:6px;position:absolute;bottom:-3px;right:-3px}.tabulator .tabulator-tableholder .tabulator-range-overlay .tabulator-range-cell-active{box-sizing:border-box;border:2px solid #2975dd;position:absolute}.tabulator .tabulator-footer{color:#555;-webkit-user-select:none;-moz-user-select:none;user-select:none;-khtml-user-select:none;-o-user-select:none;white-space:nowrap;background-color:#e6e6e6;border-top:1px solid #999;font-weight:700}.tabulator .tabulator-footer .tabulator-footer-contents{flex-direction:row;justify-content:space-between;align-items:center;padding:5px 10px;display:flex}.tabulator .tabulator-footer .tabulator-footer-contents:empty{display:none}.tabulator .tabulator-footer .tabulator-spreadsheet-tabs{margin-top:-5px;overflow-x:auto}.tabulator .tabulator-footer .tabulator-spreadsheet-tabs .tabulator-spreadsheet-tab{border:1px solid #999;border-top:none;border-bottom-right-radius:5px;border-bottom-left-radius:5px;padding:5px;font-size:.9em;display:inline-block}.tabulator .tabulator-footer .tabulator-spreadsheet-tabs .tabulator-spreadsheet-tab:hover{cursor:pointer;opacity:.7}.tabulator .tabulator-footer .tabulator-spreadsheet-tabs .tabulator-spreadsheet-tab.tabulator-spreadsheet-tab-active{background:#fff}.tabulator .tabulator-footer .tabulator-calcs-holder{box-sizing:border-box;text-align:left;border-top:1px solid #aaa;border-bottom:1px solid #aaa;width:100%;overflow:hidden;background:#f3f3f3!important}.tabulator .tabulator-footer .tabulator-calcs-holder .tabulator-row{display:inline-block;background:#f3f3f3!important}.tabulator .tabulator-footer .tabulator-calcs-holder .tabulator-row .tabulator-col-resize-handle{display:none}.tabulator .tabulator-footer .tabulator-calcs-holder:only-child{border-bottom:none;margin-bottom:-5px}.tabulator .tabulator-footer>*+.tabulator-page-counter{margin-left:10px}.tabulator .tabulator-footer .tabulator-page-counter{font-weight:400}.tabulator .tabulator-footer .tabulator-paginator{color:#555;font-family:inherit;font-size:inherit;font-weight:inherit;text-align:right;flex:1}.tabulator .tabulator-footer .tabulator-page-size{border:1px solid #aaa;border-radius:3px;margin:0 5px;padding:2px 5px;display:inline-block}.tabulator .tabulator-footer .tabulator-pages{margin:0 7px}.tabulator .tabulator-footer .tabulator-page{background:#fff3;border:1px solid #aaa;border-radius:3px;margin:0 2px;padding:2px 5px;display:inline-block}.tabulator .tabulator-footer .tabulator-page.active{color:#d00}.tabulator .tabulator-footer .tabulator-page:disabled{opacity:.5}@media (hover:hover) and (pointer:fine){.tabulator .tabulator-footer .tabulator-page:not(disabled):hover{color:#fff;cursor:pointer;background:#0003}}.tabulator .tabulator-col-resize-handle{vertical-align:middle;z-index:11;width:6px;margin-left:-3px;margin-right:-3px;display:inline-block;position:relative}@media (hover:hover) and (pointer:fine){.tabulator .tabulator-col-resize-handle:hover{cursor:ew-resize}}.tabulator .tabulator-col-resize-handle:last-of-type{width:3px;margin-right:0}.tabulator .tabulator-col-resize-guide{opacity:.5;background-color:#999;width:4px;height:100%;margin-left:-.5px;position:absolute;top:0}.tabulator .tabulator-row-resize-guide{opacity:.5;background-color:#999;width:100%;height:4px;margin-top:-.5px;position:absolute;left:0}.tabulator .tabulator-alert{text-align:center;z-index:100;background:#0006;align-items:center;width:100%;height:100%;display:flex;position:absolute;top:0;left:0}.tabulator .tabulator-alert .tabulator-alert-msg{background:#fff;border-radius:10px;margin:0 auto;padding:10px 20px;font-size:16px;font-weight:700;display:inline-block}.tabulator .tabulator-alert .tabulator-alert-msg.tabulator-alert-state-msg{color:#000;border:4px solid #333}.tabulator .tabulator-alert .tabulator-alert-msg.tabulator-alert-state-error{color:#590000;border:4px solid #d00}.tabulator-row{box-sizing:border-box;background-color:#fff;min-height:22px;position:relative}.tabulator-row.tabulator-row-even{background-color:#efefef}@media (hover:hover) and (pointer:fine){.tabulator-row.tabulator-selectable:hover{cursor:pointer;background-color:#bbb}}.tabulator-row.tabulator-selected{background-color:#9abcea}@media (hover:hover) and (pointer:fine){.tabulator-row.tabulator-selected:hover{cursor:pointer;background-color:#769bcc}}.tabulator-row.tabulator-row-moving{background:#fff;border:1px solid #000}.tabulator-row.tabulator-moving{pointer-events:none;z-index:15;border-top:1px solid #aaa;border-bottom:1px solid #aaa;position:absolute}.tabulator-row.tabulator-range-highlight .tabulator-cell.tabulator-range-row-header{color:#000;background-color:#d6d6d6}.tabulator-row.tabulator-range-highlight.tabulator-range-selected .tabulator-cell.tabulator-range-row-header,.tabulator-row.tabulator-range-selected .tabulator-cell.tabulator-range-row-header{color:#fff;background-color:#3876ca}.tabulator-row .tabulator-row-resize-handle{height:5px;position:absolute;bottom:0;left:0;right:0}.tabulator-row .tabulator-row-resize-handle.prev{top:0;bottom:auto}@media (hover:hover) and (pointer:fine){.tabulator-row .tabulator-row-resize-handle:hover{cursor:ns-resize}}.tabulator-row .tabulator-responsive-collapse{box-sizing:border-box;border-top:1px solid #aaa;border-bottom:1px solid #aaa;padding:5px}.tabulator-row .tabulator-responsive-collapse:empty{display:none}.tabulator-row .tabulator-responsive-collapse table{font-size:14px}.tabulator-row .tabulator-responsive-collapse table tr td{position:relative}.tabulator-row .tabulator-responsive-collapse table tr td:first-of-type{padding-right:10px}.tabulator-row .tabulator-cell{box-sizing:border-box;text-overflow:ellipsis;vertical-align:middle;white-space:nowrap;border-right:1px solid #aaa;outline:none;padding:4px;display:inline-block;position:relative;overflow:hidden}.tabulator-row .tabulator-cell.tabulator-row-header{background:#e6e6e6;border-bottom:1px solid #aaa;border-right:1px solid #999}.tabulator-row .tabulator-cell.tabulator-frozen{background-color:inherit;z-index:11;display:inline-block;position:sticky;left:0}.tabulator-row .tabulator-cell.tabulator-frozen.tabulator-frozen-left{border-right:2px solid #aaa}.tabulator-row .tabulator-cell.tabulator-frozen.tabulator-frozen-right{border-left:2px solid #aaa}.tabulator-row .tabulator-cell.tabulator-editing{border:1px solid #1d68cd;outline:none;padding:0}.tabulator-row .tabulator-cell.tabulator-editing input,.tabulator-row .tabulator-cell.tabulator-editing select{background:0 0;border:1px;outline:none}.tabulator-row .tabulator-cell.tabulator-validation-fail{border:1px solid #d00}.tabulator-row .tabulator-cell.tabulator-validation-fail input,.tabulator-row .tabulator-cell.tabulator-validation-fail select{color:#d00;background:0 0;border:1px}.tabulator-row .tabulator-cell.tabulator-row-handle{-webkit-user-select:none;-moz-user-select:none;-khtml-user-select:none;-o-user-select:none;justify-content:center;align-items:center;display:inline-flex}.tabulator-row .tabulator-cell.tabulator-row-handle .tabulator-row-handle-box{width:80%}.tabulator-row .tabulator-cell.tabulator-row-handle .tabulator-row-handle-box .tabulator-row-handle-bar{background:#666;width:100%;height:3px;margin-top:2px}.tabulator-row .tabulator-cell.tabulator-range-selected:not(.tabulator-range-only-cell-selected):not(.tabulator-range-row-header){background-color:#9abcea}.tabulator-row .tabulator-cell .tabulator-data-tree-branch-empty{width:7px;display:inline-block}.tabulator-row .tabulator-cell .tabulator-data-tree-branch{vertical-align:middle;border-bottom:2px solid #aaa;border-left:2px solid #aaa;border-bottom-left-radius:1px;width:7px;height:9px;margin-top:-9px;margin-right:5px;display:inline-block}.tabulator-row .tabulator-cell .tabulator-data-tree-control{vertical-align:middle;background:#0000001a;border:1px solid #333;border-radius:2px;justify-content:center;align-items:center;width:11px;height:11px;margin-right:5px;display:inline-flex;overflow:hidden}@media (hover:hover) and (pointer:fine){.tabulator-row .tabulator-cell .tabulator-data-tree-control:hover{cursor:pointer;background:#0003}}.tabulator-row .tabulator-cell .tabulator-data-tree-control .tabulator-data-tree-control-collapse{background:0 0;width:1px;height:7px;display:inline-block;position:relative}.tabulator-row .tabulator-cell .tabulator-data-tree-control .tabulator-data-tree-control-collapse:after{content:"";background:#333;width:7px;height:1px;position:absolute;top:3px;left:-3px}.tabulator-row .tabulator-cell .tabulator-data-tree-control .tabulator-data-tree-control-expand{background:#333;width:1px;height:7px;display:inline-block;position:relative}.tabulator-row .tabulator-cell .tabulator-data-tree-control .tabulator-data-tree-control-expand:after{content:"";background:#333;width:7px;height:1px;position:absolute;top:3px;left:-3px}.tabulator-row .tabulator-cell .tabulator-responsive-collapse-toggle{color:#fff;-webkit-user-select:none;-moz-user-select:none;-khtml-user-select:none;-o-user-select:none;background:#666;border-radius:20px;justify-content:center;align-items:center;width:15px;height:15px;font-size:1.1em;font-weight:700;display:inline-flex}@media (hover:hover) and (pointer:fine){.tabulator-row .tabulator-cell .tabulator-responsive-collapse-toggle:hover{cursor:pointer;opacity:.7}}.tabulator-row .tabulator-cell .tabulator-responsive-collapse-toggle.open .tabulator-responsive-collapse-toggle-close{display:initial}.tabulator-row .tabulator-cell .tabulator-responsive-collapse-toggle.open .tabulator-responsive-collapse-toggle-open{display:none}.tabulator-row .tabulator-cell .tabulator-responsive-collapse-toggle svg{stroke:#fff}.tabulator-row .tabulator-cell .tabulator-responsive-collapse-toggle .tabulator-responsive-collapse-toggle-close{display:none}.tabulator-row .tabulator-cell .tabulator-traffic-light{border-radius:14px;width:14px;height:14px;display:inline-block}.tabulator-row.tabulator-group{box-sizing:border-box;background:#ccc;border-top:1px solid #999;border-bottom:1px solid #999;border-right:1px solid #aaa;min-width:100%;padding:5px 5px 5px 10px;font-weight:700}@media (hover:hover) and (pointer:fine){.tabulator-row.tabulator-group:hover{cursor:pointer;background-color:#0000001a}}.tabulator-row.tabulator-group.tabulator-group-visible .tabulator-arrow{border:6px solid #0000;border-top-color:#666;border-bottom:0;margin-right:10px}.tabulator-row.tabulator-group.tabulator-group-level-1{padding-left:30px}.tabulator-row.tabulator-group.tabulator-group-level-2{padding-left:50px}.tabulator-row.tabulator-group.tabulator-group-level-3{padding-left:70px}.tabulator-row.tabulator-group.tabulator-group-level-4{padding-left:90px}.tabulator-row.tabulator-group.tabulator-group-level-5{padding-left:110px}.tabulator-row.tabulator-group .tabulator-group-toggle{display:inline-block}.tabulator-row.tabulator-group .tabulator-arrow{vertical-align:middle;border:6px solid #0000;border-left-color:#666;border-right:0;width:0;height:0;margin-right:16px;display:inline-block}.tabulator-row.tabulator-group span{color:#d00;margin-left:10px}.tabulator-toggle{box-sizing:border-box;background:#dcdcdc;border:1px solid #ccc;flex-direction:row;display:flex}.tabulator-toggle.tabulator-toggle-on{background:#1c6cc2}.tabulator-toggle .tabulator-toggle-switch{box-sizing:border-box;background:#fff;border:1px solid #ccc}.tabulator-popup-container{-webkit-overflow-scrolling:touch;box-sizing:border-box;z-index:10000;background:#fff;border:1px solid #aaa;font-size:14px;display:inline-block;position:absolute;overflow-y:auto;box-shadow:0 0 5px #0003}.tabulator-popup{border-radius:3px;padding:5px}.tabulator-tooltip{box-shadow:none;pointer-events:none;border-radius:2px;max-width:min(500px,100%);padding:3px 5px;font-size:12px}.tabulator-menu .tabulator-menu-item{box-sizing:border-box;user-select:none;padding:5px 10px;position:relative}.tabulator-menu .tabulator-menu-item.tabulator-menu-item-disabled{opacity:.5}@media (hover:hover) and (pointer:fine){.tabulator-menu .tabulator-menu-item:not(.tabulator-menu-item-disabled):hover{cursor:pointer;background:#efefef}}.tabulator-menu .tabulator-menu-item.tabulator-menu-item-submenu{padding-right:25px}.tabulator-menu .tabulator-menu-item.tabulator-menu-item-submenu:after{content:"";vertical-align:top;border:1px solid #aaa;border-width:1px 1px 0 0;width:7px;height:7px;display:inline-block;position:absolute;top:calc(5px + .4em);right:10px;transform:rotate(45deg)}.tabulator-menu .tabulator-menu-separator{border-top:1px solid #aaa}.tabulator-edit-list{-webkit-overflow-scrolling:touch;max-height:200px;font-size:14px;overflow-y:auto}.tabulator-edit-list .tabulator-edit-list-item{color:#333;outline:none;padding:4px}.tabulator-edit-list .tabulator-edit-list-item.active{color:#fff;background:#1d68cd}.tabulator-edit-list .tabulator-edit-list-item.active.focused{outline:1px solid #ffffff80}.tabulator-edit-list .tabulator-edit-list-item.focused{outline:1px solid #1d68cd}@media (hover:hover) and (pointer:fine){.tabulator-edit-list .tabulator-edit-list-item:hover{color:#fff;cursor:pointer;background:#1d68cd}}.tabulator-edit-list .tabulator-edit-list-placeholder{color:#333;text-align:center;padding:4px}.tabulator-edit-list .tabulator-edit-list-group{color:#333;border-bottom:1px solid #aaa;padding:6px 4px 4px;font-weight:700}.tabulator-edit-list .tabulator-edit-list-group.tabulator-edit-list-group-level-2,.tabulator-edit-list .tabulator-edit-list-item.tabulator-edit-list-group-level-2{padding-left:12px}.tabulator-edit-list .tabulator-edit-list-group.tabulator-edit-list-group-level-3,.tabulator-edit-list .tabulator-edit-list-item.tabulator-edit-list-group-level-3{padding-left:20px}.tabulator-edit-list .tabulator-edit-list-group.tabulator-edit-list-group-level-4,.tabulator-edit-list .tabulator-edit-list-item.tabulator-edit-list-group-level-4{padding-left:28px}.tabulator-edit-list .tabulator-edit-list-group.tabulator-edit-list-group-level-5,.tabulator-edit-list .tabulator-edit-list-item.tabulator-edit-list-group-level-5{padding-left:36px}.tabulator.tabulator-ltr{direction:ltr}.tabulator.tabulator-rtl{text-align:initial;direction:rtl}.tabulator.tabulator-rtl .tabulator-header .tabulator-col{border-left:1px solid #aaa;border-right:initial;text-align:initial}.tabulator.tabulator-rtl .tabulator-header .tabulator-col.tabulator-col-group .tabulator-col-group-cols{margin-left:-1px;margin-right:0}.tabulator.tabulator-rtl .tabulator-header .tabulator-col.tabulator-sortable .tabulator-col-title{padding-left:25px;padding-right:0}.tabulator.tabulator-rtl .tabulator-header .tabulator-col .tabulator-col-content .tabulator-col-sorter{left:8px;right:auto}.tabulator.tabulator-rtl .tabulator-tableholder .tabulator-range-overlay .tabulator-range.tabulator-range-active:after{content:"";background-color:#2975dd;border-radius:999px;width:6px;height:6px;position:absolute;bottom:-3px;left:-3px;right:auto}.tabulator.tabulator-rtl .tabulator-row .tabulator-cell{border-left:1px solid #aaa;border-right:initial}.tabulator.tabulator-rtl .tabulator-row .tabulator-cell .tabulator-data-tree-branch{border-left:initial;border-right:2px solid #aaa;border-bottom-right-radius:1px;border-bottom-left-radius:0;margin-left:5px;margin-right:0}.tabulator.tabulator-rtl .tabulator-row .tabulator-cell .tabulator-data-tree-control{margin-left:5px;margin-right:0}.tabulator.tabulator-rtl .tabulator-row .tabulator-cell.tabulator-frozen.tabulator-frozen-left{border-left:2px solid #aaa}.tabulator.tabulator-rtl .tabulator-row .tabulator-cell.tabulator-frozen.tabulator-frozen-right{border-right:2px solid #aaa}.tabulator.tabulator-rtl .tabulator-row .tabulator-col-resize-handle:last-of-type{width:3px;margin-left:0;margin-right:-3px}.tabulator.tabulator-rtl .tabulator-footer .tabulator-calcs-holder{text-align:initial}.tabulator-print-fullscreen{z-index:10000;position:absolute;inset:0}body.tabulator-print-fullscreen-hide>:not(.tabulator-print-fullscreen){display:none!important}.tabulator-print-table{border-collapse:collapse}.tabulator-print-table .tabulator-data-tree-branch{vertical-align:middle;border-bottom:2px solid #aaa;border-left:2px solid #aaa;border-bottom-left-radius:1px;width:7px;height:9px;margin-top:-9px;margin-right:5px;display:inline-block}.tabulator-print-table .tabulator-print-table-group{box-sizing:border-box;background:#ccc;border-top:1px solid #999;border-bottom:1px solid #999;border-right:1px solid #aaa;min-width:100%;padding:5px 5px 5px 10px;font-weight:700}@media (hover:hover) and (pointer:fine){.tabulator-print-table .tabulator-print-table-group:hover{cursor:pointer;background-color:#0000001a}}.tabulator-print-table .tabulator-print-table-group.tabulator-group-visible .tabulator-arrow{border:6px solid #0000;border-top-color:#666;border-bottom:0;margin-right:10px}.tabulator-print-table .tabulator-print-table-group.tabulator-group-level-1 td{padding-left:30px!important}.tabulator-print-table .tabulator-print-table-group.tabulator-group-level-2 td{padding-left:50px!important}.tabulator-print-table .tabulator-print-table-group.tabulator-group-level-3 td{padding-left:70px!important}.tabulator-print-table .tabulator-print-table-group.tabulator-group-level-4 td{padding-left:90px!important}.tabulator-print-table .tabulator-print-table-group.tabulator-group-level-5 td{padding-left:110px!important}.tabulator-print-table .tabulator-print-table-group .tabulator-group-toggle{display:inline-block}.tabulator-print-table .tabulator-print-table-group .tabulator-arrow{vertical-align:middle;border:6px solid #0000;border-left-color:#666;border-right:0;width:0;height:0;margin-right:16px;display:inline-block}.tabulator-print-table .tabulator-print-table-group span{color:#d00;margin-left:10px}.tabulator-print-table .tabulator-data-tree-control{vertical-align:middle;background:#0000001a;border:1px solid #333;border-radius:2px;justify-content:center;align-items:center;width:11px;height:11px;margin-right:5px;display:inline-flex;overflow:hidden}@media (hover:hover) and (pointer:fine){.tabulator-print-table .tabulator-data-tree-control:hover{cursor:pointer;background:#0003}}.tabulator-print-table .tabulator-data-tree-control .tabulator-data-tree-control-collapse{background:0 0;width:1px;height:7px;display:inline-block;position:relative}.tabulator-print-table .tabulator-data-tree-control .tabulator-data-tree-control-collapse:after{content:"";background:#333;width:7px;height:1px;position:absolute;top:3px;left:-3px}.tabulator-print-table .tabulator-data-tree-control .tabulator-data-tree-control-expand{background:#333;width:1px;height:7px;display:inline-block;position:relative}.tabulator-print-table .tabulator-data-tree-control .tabulator-data-tree-control-expand:after{content:"";background:#333;width:7px;height:1px;position:absolute;top:3px;left:-3px}
22
22
  </style><style>
23
- :host,#panel{background:var(--bkg-color);height:16rem;min-height:10rem}#panel{inset:0;overflow:hidden}#gutter{background:var(--bkg-color);cursor:row-resize;width:100%;height:.4rem;position:absolute;top:0;left:0}#gutter:hover{background:var(--bkg-color-grad1)}#gutter:after{content:" ";background:var(--bkg-color-grad1);border-radius:1rem;width:4rem;height:.4rem;display:block;position:relative;left:calc(50% - 2rem)}#close{color:#777;background-color:var(--bkg-color);cursor:pointer;border:none;width:1rem;height:1rem;margin:.5rem;padding:0;line-height:1rem;position:absolute;top:6px;right:0}#close i:before{content:"uf00d"}#close:hover{color:#000;border-color:#000}#content{background:var(--bkg-color);flex-direction:column;margin:0 .5rem .5rem;padding:0;display:flex;position:absolute;inset:.5rem 0 0;overflow:hidden}#header{flex:0;justify-content:space-between;display:flex}.selection-panel{margin-right:.5rem;display:flex;& .gg-icon-button[disabled]{pointer-events:none;opacity:.5}& .gg-icon-button[disabled]:hover{background-color:#0000}& .label{align-self:center;padding-left:1rem}}.gg-tabs{margin:0}#grid{flex:1;overflow:hidden}.geo-type{margin-right:.5rem}::-webkit-scrollbar{width:8px}::-webkit-scrollbar-thumb{background:#999}.tiny-margin{margin:.1rem}.tabulator-col[aria-sort=none] .tabulator-col-sorter i{color:#999}.tabulator-col[aria-sort=asc] .tabulator-col-sorter i{color:red}.tabulator-col[aria-sort=desc] .tabulator-col-sorter i{color:red;transform:scaleY(-1)}#tabulator{background-color:var(--bkg-color)}#tabulator .tabulator-header .tabulator-col-content{background-color:var(--bkg-color);color:var(--text-color)}#tabulator .tabulator-header .tabulator-col,#tabulator .tabulator-header .tabulator-col-row-handle{white-space:normal}#tabulator .tabulator-tableholder .tabulator-table .tabulator-row{background-color:var(--bkg-color);color:var(--text-color)}#tabulator .tabulator-tableholder .tabulator-table .tabulator-row:nth-child(2n){background-color:var(--bkg-color-grad1)}#tabulator .tabulator-tableholder .tabulator-table .tabulator-row.tabulator-selected{background-color:#9abcea}.tabulator-cell img{float:left;height:1.5rem;margin-right:.5rem}.tabulator-cell span{align-items:center;line-height:1.5rem;display:inline-flex;position:relative}.tabulator-cell span sup{position:absolute;top:-.3rem;right:-.5rem}@media (hover:hover) and (pointer:fine){#tabulator .tabulator-tableholder .tabulator-table .tabulator-row:hover{cursor:pointer;background-color:var(--bkg-color-grad2)}}img.sort-icon{width:1rem;height:1rem;&.default{opacity:.5}&:hover{opacity:1}}
23
+ :host,#panel{background:var(--bkg-color);height:16rem;min-height:10rem}#panel{inset:0;overflow:hidden}#gutter{background:var(--bkg-color);cursor:row-resize;width:100%;height:.4rem;position:absolute;top:0;left:0}#gutter:hover{background:var(--bkg-color-grad1)}#gutter:after{content:" ";background:var(--bkg-color-grad1);border-radius:1rem;width:4rem;height:.4rem;display:block;position:relative;left:calc(50% - 2rem)}#close{color:#777;background-color:var(--bkg-color);cursor:pointer;border:none;width:1rem;height:1rem;margin:.5rem;padding:0;line-height:1rem;position:absolute;top:6px;right:0}#close i:before{content:"uf00d"}#close:hover{color:#000;border-color:#000}#content{background:var(--bkg-color);flex-direction:column;margin:0 .5rem .5rem;padding:0;display:flex;position:absolute;inset:.5rem 0 0;overflow:hidden}#header{flex:0;justify-content:space-between;display:flex}.selection-panel{margin-right:.5rem;display:flex;& .gg-icon-button[disabled]{pointer-events:none;opacity:.5}& .gg-icon-button[disabled]:hover{background-color:#0000}& .label{align-self:center;padding-left:1rem}}.gg-tabs{margin:0}#grid{flex:1;overflow:hidden}.geo-type{margin-right:.5rem}::-webkit-scrollbar{width:8px}::-webkit-scrollbar-thumb{background:#999}.tiny-margin{margin:.1rem}.tabulator-col[aria-sort=none] .tabulator-col-sorter i{color:#999}.tabulator-col[aria-sort=asc] .tabulator-col-sorter i{color:red}.tabulator-col[aria-sort=desc] .tabulator-col-sorter i{color:red;transform:scaleY(-1)}#tabulator{background-color:var(--bkg-color)}#tabulator .tabulator-header .tabulator-col-content{background-color:var(--bkg-color);color:var(--text-color)}#tabulator .tabulator-header .tabulator-col,#tabulator .tabulator-header .tabulator-col-row-handle{white-space:normal}#tabulator .tabulator-tableholder .tabulator-table .tabulator-row{background-color:var(--bkg-color);color:var(--text-color)}#tabulator .tabulator-tableholder .tabulator-table .tabulator-row:nth-child(2n){background-color:var(--bkg-color-grad1)}#tabulator .tabulator-tableholder .tabulator-table .tabulator-row.tabulator-selected{background-color:#9abcea}.tabulator{font-size:inherit!important}.tabulator-cell{text-wrap:pretty!important;height:fit-content!important}.tabulator-cell a{width:inherit;height:inherit}.tabulator-cell img{width:inherit;height:inherit;object-fit:scale-down;float:left;max-height:3rem;margin-right:.5rem}.tabulator-cell span{align-items:center;line-height:1.5rem;display:inline-flex;position:relative}.tabulator-cell span sup{position:absolute;top:-.3rem;right:-.5rem}@media (hover:hover) and (pointer:fine){#tabulator .tabulator-tableholder .tabulator-table .tabulator-row:hover{cursor:pointer;background-color:var(--bkg-color-grad2)}}img.sort-icon{width:1rem;height:1rem;&.default{opacity:.5}&:hover{opacity:1}}
24
24
  </style>
25
25
  <div id="panel"><div id="content"><div id="header"><div class="gg-tabs">${this.getTabHeaders().map((th) => uHtml ` <button id="${th.id}" i18n="${th.text}" class="${th.active ? 'gg-tab active' : 'gg-tab'}" .active="${th.active}" onclick="${() => this.displayGrid(th.id, true)}"></button> `)}</div><div class="selection-panel"><span class="label" i18n="Selection"></span> <button class="gg-icon-button gg-medium" onclick="${() => this.selectAll()}" tip="Select all"><img alt="select all icon" src="icons/select-all-on.svg"></button> <button class="gg-icon-button gg-medium" onclick="${() => this.selectNone()}" tip="Select none"><img alt="select none icon" src="icons/select-all-off.svg"></button> <button class="gg-icon-button gg-medium" onclick="${() => this.invertSelection()}" tip="Invert selection"><img alt="invert selection icon" src="icons/select-invert.svg"></button><girafe-get-directions></girafe-get-directions><button class="${this.resultsSelected ? 'gg-icon-button gg-medium' : 'gg-icon-button gg-medium disabled'}" ?disabled="${!this.resultsSelected}" onclick="${() => this.zoomToSelection()}" tip="Zoom to"><img alt="zoom to selection icon" src="icons/zoom-to-selection.svg"></button> <button class="${this.resultsSelected ? 'gg-icon-button gg-medium' : 'gg-icon-button gg-medium disabled'}" ?disabled="${!this.resultsSelected}" onclick="${() => this.generateCSV()}" tip="Generate CSV"><img alt="download csv icon" src="icons/arrow-download.svg"></button> <button class="gg-icon-button gg-medium" onclick="${() => this.closePanel()}" tip="Clear results and close Panel"><img alt="close-icon" src="icons/close.svg"></button></div></div><div id="tabulator"></div></div><div id="gutter"></div></div>`;
26
26
  };
@@ -1,6 +1,6 @@
1
1
  import type OlFeature from 'ol/Feature.js';
2
2
  import { GridDataById } from '../../../tools/featuretogriddatabyid.js';
3
- import { ColumnDefinition, RowComponent } from 'tabulator-tables';
3
+ import { ColumnComponent, ColumnDefinition, RowComponent } from 'tabulator-tables';
4
4
  import IGirafeContext from '../../../tools/context/icontext.js';
5
5
  /**
6
6
  * Represents the header text and state of a tab.
@@ -34,6 +34,11 @@ export default class SelectionTabulatorManager {
34
34
  private data;
35
35
  private readonly context;
36
36
  private readonly columnAliasHelper;
37
+ private readonly minimalColumnWidth;
38
+ private readonly columnPositionsBeforeFreezing;
39
+ private popupLastImageSrc;
40
+ private popupLastInstance;
41
+ private get tableColumns();
37
42
  constructor(context: IGirafeContext);
38
43
  /**
39
44
  * Set the HTML element to be used by the grid.
@@ -62,6 +67,7 @@ export default class SelectionTabulatorManager {
62
67
  */
63
68
  private gridDataToGridTab;
64
69
  columnsToGridColumns(idTable: string, columns: string[]): ColumnDefinition[];
70
+ getLookupColumnForFreezing(): [ColumnComponent, boolean];
65
71
  filterEmptyColumnsOnData(data: GridDataById): GridDataById;
66
72
  /**
67
73
  * @returns A newly created grid column object.
@@ -3,6 +3,8 @@ import { TabulatorFull as Tabulator } from 'tabulator-tables';
3
3
  import { getUid } from 'ol/util.js';
4
4
  import ColumnAliasHelper from '../../../tools/utils/aliases.js';
5
5
  import { linkify } from '../../../tools/utils/utils.js';
6
+ import { noop } from '../../../tools/utils/async.js';
7
+ import tippy from 'tippy.js';
6
8
  const geometryColumns = new Set(['geom', 'the_geom', 'geometry']);
7
9
  export default class SelectionTabulatorManager {
8
10
  featureToGridData;
@@ -13,10 +15,17 @@ export default class SelectionTabulatorManager {
13
15
  data = {};
14
16
  context;
15
17
  columnAliasHelper;
18
+ minimalColumnWidth = 64;
19
+ columnPositionsBeforeFreezing = {};
20
+ popupLastImageSrc;
21
+ popupLastInstance;
22
+ get tableColumns() {
23
+ return this.table?.getColumns(false) ?? [];
24
+ }
16
25
  constructor(context) {
17
26
  this.context = context;
18
27
  this.columnAliasHelper = new ColumnAliasHelper(context.stateManager);
19
- this.featureToGridData = new FeatureToGridDataById({ keepGeomProperty: true });
28
+ this.featureToGridData = new FeatureToGridDataById(this.context, { keepGeomProperty: true });
20
29
  }
21
30
  /**
22
31
  * Set the HTML element to be used by the grid.
@@ -56,9 +65,11 @@ export default class SelectionTabulatorManager {
56
65
  data: this.data[id].notOlProperties,
57
66
  columns: this.columnsToGridColumns(id, this.data[id].columns),
58
67
  selectableRows: true,
59
- layout: 'fitColumns',
68
+ layout: 'fitDataStretch',
69
+ movableColumns: true,
60
70
  locale: true,
61
71
  maxHeight: '750',
72
+ resizableRows: true,
62
73
  headerSortElement: function (_, dir) {
63
74
  switch (dir) {
64
75
  case 'asc':
@@ -68,7 +79,8 @@ export default class SelectionTabulatorManager {
68
79
  default:
69
80
  return '<img alt="sort-icon" src="icons/sort.svg" class="sort-icon default" />';
70
81
  }
71
- }
82
+ },
83
+ popupContainer: this.element
72
84
  });
73
85
  this.table?.on('rowSelectionChanged', (selection) => {
74
86
  // True if at least one row is selected.
@@ -137,11 +149,74 @@ export default class SelectionTabulatorManager {
137
149
  columnDefinition.push({
138
150
  title: this.context.i18nManager.getTranslation(columnAlias),
139
151
  field: column,
140
- formatter: 'html'
152
+ formatter: 'html',
153
+ headerTooltip: true,
154
+ minWidth: this.minimalColumnWidth,
155
+ headerMenu: (_e, _c) => [
156
+ {
157
+ label: (column) => this.context.i18nManager.getTranslation(column.getDefinition().frozen ? 'unfreeze-column' : 'freeze-column'),
158
+ action: (_e, column) => {
159
+ const columnDefinition = column.getDefinition();
160
+ const freezeOrNot = !columnDefinition.frozen;
161
+ const [toColumn, after] = this.getLookupColumnForFreezing();
162
+ if (freezeOrNot) {
163
+ this.columnPositionsBeforeFreezing[column.getField()] = this.tableColumns.findIndex((colComp) => colComp.getField() === column.getField());
164
+ this.table?.moveColumn(column, toColumn, after);
165
+ }
166
+ else {
167
+ const colPos = this.columnPositionsBeforeFreezing[column.getField()];
168
+ if (colPos) {
169
+ const previousColumn = this.tableColumns.at(colPos);
170
+ if (previousColumn) {
171
+ this.table?.moveColumn(column, previousColumn, true);
172
+ }
173
+ }
174
+ }
175
+ column
176
+ .updateDefinition({
177
+ ...columnDefinition,
178
+ frozen: !columnDefinition.frozen
179
+ })
180
+ .then(noop);
181
+ }
182
+ }
183
+ ],
184
+ contextMenu: [
185
+ {
186
+ label: this.context.i18nManager.getTranslation('copy-cell-content'),
187
+ action: (_e, cell) => {
188
+ navigator.clipboard?.writeText(cell.getElement().textContent);
189
+ }
190
+ }
191
+ ],
192
+ cellMouseEnter: (_e, cell) => {
193
+ const imageElement = cell.getElement().querySelector('img');
194
+ if (imageElement && this.popupLastImageSrc !== imageElement.src) {
195
+ if (this.popupLastInstance) {
196
+ this.popupLastInstance.destroy();
197
+ }
198
+ this.popupLastImageSrc = imageElement.src;
199
+ this.popupLastInstance = tippy(imageElement, {
200
+ arrow: true,
201
+ theme: 'image-popup',
202
+ content: (_ref) => {
203
+ const popupImageElement = document.createElement('img');
204
+ popupImageElement.src = imageElement.src;
205
+ return popupImageElement;
206
+ }
207
+ });
208
+ this.popupLastInstance.show();
209
+ }
210
+ }
141
211
  });
142
212
  }
143
213
  return columnDefinition;
144
214
  }
215
+ getLookupColumnForFreezing() {
216
+ const firstFrozenColumnDefinition = this.tableColumns.find((colComp) => colComp.getDefinition().frozen);
217
+ const firstColumnDefinition = this.tableColumns[0];
218
+ return firstFrozenColumnDefinition ? [firstFrozenColumnDefinition, true] : [firstColumnDefinition, false];
219
+ }
145
220
  filterEmptyColumnsOnData(data) {
146
221
  for (const [_, entry] of Object.entries(data)) {
147
222
  const columns = entry.columns;
@@ -26,7 +26,7 @@ declare class SelectionWindowComponent extends GirafeDraggableElement {
26
26
  private isVisibleComponentSetup;
27
27
  private readonly debounceOnFeaturesSelected;
28
28
  private resizeWindow;
29
- private readonly featureToGridData;
29
+ private featureToGridData;
30
30
  private windowFeatures;
31
31
  private windowLayers;
32
32
  visible: boolean;
@@ -33,7 +33,7 @@ table{border-collapse:collapse;table-layout:auto;width:100%}td.feature-id{text-a
33
33
  isVisibleComponentSetup = false;
34
34
  debounceOnFeaturesSelected = debounce(this.onFeaturesSelected.bind(this), 200);
35
35
  resizeWindow = null;
36
- featureToGridData = new FeatureToGridDataById({ removeEmptyColumns: false });
36
+ featureToGridData;
37
37
  windowFeatures = [];
38
38
  windowLayers = [];
39
39
  visible = false;
@@ -52,6 +52,7 @@ table{border-collapse:collapse;table-layout:auto;width:100%}td.feature-id{text-a
52
52
  super.connectedCallback();
53
53
  this.csvManager = new CsvManager(this.context);
54
54
  this.columnAliasHelper = new ColumnAliasHelper(this.context.stateManager);
55
+ this.featureToGridData = new FeatureToGridDataById(this.context, { removeEmptyColumns: false });
55
56
  this.render();
56
57
  this.registerVisibilityEvents();
57
58
  }
@@ -96,6 +96,8 @@ header{border-top:1px solid #ddd;align-items:center;height:2rem;display:flex}.to
96
96
  }
97
97
  createOpacityTooltip() {
98
98
  const el = this.shadow.getElementById('opacity');
99
+ if (!el)
100
+ return;
99
101
  tippy(el, {
100
102
  trigger: 'click',
101
103
  arrow: true,
@@ -116,6 +118,8 @@ header{border-top:1px solid #ddd;align-items:center;height:2rem;display:flex}.to
116
118
  }
117
119
  createFilterTooltip() {
118
120
  const el = this.shadow.getElementById('filter');
121
+ if (!el)
122
+ return;
119
123
  tippy(el, {
120
124
  trigger: 'click',
121
125
  arrow: true,
package/decs.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
- declare module 'tippy.js';
2
+ // declare module 'tippy.js';
3
3
  declare module 'olcs';
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.1.0-dev.2468094514",
8
+ "version": "1.1.0-dev.2507911619",
9
9
  "type": "module",
10
10
  "engines": {
11
11
  "node": ">=20.19.0"
package/styles/index.css CHANGED
@@ -223,3 +223,18 @@ girafe-prototype-banner {
223
223
  font-size: 1.2rem;
224
224
  font-weight: bold;
225
225
  }
226
+
227
+ /* For showing a Popup of an Image found in Selection */
228
+ div.tippy-box[data-theme=image-popup] {
229
+ border: var(--app-standard-border) !important;
230
+ div.tippy-content {
231
+ background-color: var(--bkg-color) !important;
232
+ img {
233
+ max-height: 20rem;
234
+ max-width: 20rem;
235
+ }
236
+ }
237
+ div.tippy-arrow {
238
+ color: var(--bkg-color) !important;
239
+ }
240
+ }
@@ -1 +1 @@
1
- {"version":"1.1.0-dev.2468094514", "build":"2468094514", "date":"21/04/2026"}
1
+ {"version":"1.1.0-dev.2507911619", "build":"2507911619", "date":"07/05/2026"}
@@ -58,7 +58,15 @@ export default defineConfig(({ command, mode }) => {
58
58
  key: readFileSync(`${certsDirectory}/app.localhost.key.pem`),
59
59
  cert: readFileSync(`${certsDirectory}/app.localhost.cert.pem`)
60
60
  }
61
- : false
61
+ : false,
62
+ // To be able to see Images locally and resolve clickable Links correctly
63
+ proxy: {
64
+ '^/file_proxy/.*': {
65
+ target: "https://map.geo.bs.ch/file_proxy/",
66
+ changeOrigin: true,
67
+ rewrite: (path) => path.replace(/^\/file_proxy/, '')
68
+ }
69
+ }
62
70
  },
63
71
  build: {
64
72
  outDir: 'dist/app',
@@ -127,7 +135,7 @@ export default defineConfig(({ command, mode }) => {
127
135
  { src: 'node_modules/ol/ol.css', dest: 'lib/ol/' },
128
136
  { src: 'node_modules/tabulator-tables/dist/css/tabulator.min.css', dest: 'lib/tabulator-tables/' },
129
137
  { src: 'node_modules/tippy.js/dist/*.css', dest: 'lib/tippy.js/' },
130
- { src: 'node_modules/vanilla-picker/dist/*.css', dest: 'lib/vanilla-picker/' }
138
+ { src: 'node_modules/vanilla-picker/dist/*.css', dest: 'lib/vanilla-picker/' },
131
139
  ]
132
140
  }),
133
141
  InlineTemplatesPlugin(),
@@ -1,6 +1,7 @@
1
1
  declare class GirafeConfig {
2
2
  general: {
3
3
  locale: string;
4
+ defaultUrlPrefix: string;
4
5
  logLevel: 'debug' | 'info' | 'warn' | 'error';
5
6
  };
6
7
  languages: {
@@ -163,9 +164,6 @@ declare class GirafeConfig {
163
164
  quote: string;
164
165
  separator: string;
165
166
  };
166
- metadata: {
167
- metadataUrlPrefix: string;
168
- };
169
167
  infoWindow: {
170
168
  defaultWindowWidth: string;
171
169
  defaultWindowHeight: string;
@@ -263,7 +261,6 @@ declare class GirafeConfig {
263
261
  private initConfigLidar;
264
262
  private initConfigNews;
265
263
  private initConfigCsv;
266
- private initConfigMetadata;
267
264
  private initConfigInfoWindow;
268
265
  private initConfigContact;
269
266
  private initConfigOffline;
@@ -20,7 +20,6 @@ class GirafeConfig {
20
20
  contextmenu;
21
21
  crs;
22
22
  csv;
23
- metadata;
24
23
  infoWindow;
25
24
  offline;
26
25
  query;
@@ -56,7 +55,6 @@ class GirafeConfig {
56
55
  this.news = this.initConfigNews(config);
57
56
  this.lidar = this.initConfigLidar(config);
58
57
  this.csv = this.initConfigCsv(config);
59
- this.metadata = this.initConfigMetadata(config);
60
58
  this.infoWindow = this.initConfigInfoWindow(config);
61
59
  this.offline = this.initConfigOffline(config);
62
60
  this.query = this.initConfigQuery(config);
@@ -255,15 +253,6 @@ class GirafeConfig {
255
253
  ...config.csv
256
254
  };
257
255
  }
258
- initConfigMetadata(config) {
259
- const defaultConfig = {
260
- metadataUrlPrefix: ''
261
- };
262
- return {
263
- ...defaultConfig,
264
- ...config.metadata
265
- };
266
- }
267
256
  initConfigInfoWindow(config) {
268
257
  const defaultConfig = {
269
258
  defaultWindowWidth: '960px',
@@ -315,6 +304,7 @@ class GirafeConfig {
315
304
  initConfigGeneral(config) {
316
305
  return {
317
306
  locale: config.general.locale ?? GirafeConfig.DEFAULT_LOCALE,
307
+ defaultUrlPrefix: config.general.defaultUrlPrefix ?? '',
318
308
  // NOTE REG: Small hack specific to Vite: When running in debug mode, we force the logLevel to debug.
319
309
  // Otherwise we will always have to manually activate it.
320
310
  logLevel: import.meta?.env?.DEV ? 'debug' : (config.general.logLevel ?? 'warn')
@@ -42,8 +42,13 @@ ${stack}
42
42
  }
43
43
  listenToAllErrors() {
44
44
  // Listen to all uncatched errors
45
- window.onerror = async (_message, file, line, col, error) => {
46
- const title = error?.message ?? `Unknown error in ${file} at line ${line} and column ${col}.`;
45
+ window.onerror = async (message, file, line, col, error) => {
46
+ if (message === 'ResizeObserver loop completed with undelivered notifications.') {
47
+ // Seems to be an Issue on Tabulator Tables: https://github.com/olifolkerd/tabulator/issues?q=ResizeObserver%20loop%20completed%20with%20undelivered%20notifications
48
+ console.debug(`Ignored Error: ${message}`);
49
+ return false;
50
+ }
51
+ const title = error?.message ?? message ?? `Unknown error in ${file} at line ${line} and column ${col}.`;
47
52
  const stack = await this.getStackTrace(error);
48
53
  this.pushErrorMessageWithStack(title, stack);
49
54
  return false;
@@ -1,4 +1,5 @@
1
1
  import type OlFeature from 'ol/Feature.js';
2
+ import IGirafeContext from './context/icontext.js';
2
3
  /**
3
4
  * Represents a grid data organized by unique ids.
4
5
  */
@@ -30,8 +31,9 @@ export interface FeatureToGridDataOptions {
30
31
  * A feature-to-grid data converter, to show feature's properties in grid-like system.
31
32
  */
32
33
  export default class FeatureToGridDataById {
34
+ private readonly context;
33
35
  options: FeatureToGridDataOptions;
34
- constructor(options: FeatureToGridDataOptions);
36
+ constructor(context: IGirafeContext, options: FeatureToGridDataOptions);
35
37
  /**
36
38
  * Takes an array of OpenLayers features and converts them into a grid data object, where each feature
37
39
  * is mapped by its ID as the key.
@@ -43,6 +45,8 @@ export default class FeatureToGridDataById {
43
45
  * @private
44
46
  */
45
47
  private addFeatureToGridDataById;
48
+ private ensureAbsolutePath;
49
+ private isLikelyHtml;
46
50
  /**
47
51
  * @returns {GridData} A new empty grid data object with columns from given properties.
48
52
  * @static
@@ -4,8 +4,10 @@ import WfsManager from './wfs/wfsmanager.js';
4
4
  * A feature-to-grid data converter, to show feature's properties in grid-like system.
5
5
  */
6
6
  export default class FeatureToGridDataById {
7
+ context;
7
8
  options;
8
- constructor(options) {
9
+ constructor(context, options) {
10
+ this.context = context;
9
11
  this.options = {
10
12
  ...{
11
13
  keepGeomProperty: false,
@@ -32,11 +34,13 @@ export default class FeatureToGridDataById {
32
34
  */
33
35
  addFeatureToGridDataById(gridDataById, feature) {
34
36
  const featureType = FeatureToGridDataById.getUserFeatureType(feature);
35
- const notOlProperties = removeUnwantedOlParams(feature, this.options.keepGeomProperty);
37
+ let notOlProperties = removeUnwantedOlParams(feature, this.options.keepGeomProperty);
36
38
  if (!Object.keys(notOlProperties).length) {
37
39
  // Don't keep feature without properties.
38
40
  return gridDataById;
39
41
  }
42
+ // Apply default prefix to links and images if necessary
43
+ notOlProperties = Object.fromEntries(Object.entries(notOlProperties).map(([key, value]) => [key, this.ensureAbsolutePath(value)]));
40
44
  if (!Object.keys(gridDataById).includes(featureType)) {
41
45
  gridDataById[featureType] = FeatureToGridDataById.createGridDataWithColumns(notOlProperties);
42
46
  }
@@ -49,6 +53,19 @@ export default class FeatureToGridDataById {
49
53
  gridData.data.push(data);
50
54
  return gridDataById;
51
55
  }
56
+ ensureAbsolutePath(attributeContent) {
57
+ if (this.context.configManager.Config.general.defaultUrlPrefix && this.isLikelyHtml(attributeContent)) {
58
+ const regex = /(href|src)="\/([^"]*)"/g;
59
+ return attributeContent.replaceAll(regex, (_match, attr, path) => {
60
+ return `${attr}="${this.context.configManager.Config.general.defaultUrlPrefix}/${path}"`;
61
+ });
62
+ }
63
+ // Not an HTML string
64
+ return attributeContent;
65
+ }
66
+ isLikelyHtml(str) {
67
+ return /<[a-z][\s\S]*>/i.test(str);
68
+ }
52
69
  /**
53
70
  * @returns {GridData} A new empty grid data object with columns from given properties.
54
71
  * @static
package/tools/main.d.ts CHANGED
@@ -111,7 +111,7 @@ export { unByKeyAll, getOlayerByName, removeUnwantedOlParams, polygonFromCircle,
111
111
  export { getPropertyByPath, setPropertyByPath, createObjectFromPath, deletePropertyByPath, mergeObjects } from './utils/pathUtils.js';
112
112
  export { generateQrCode } from './utils/qrcode.js';
113
113
  export { default as ServiceWorkerHelper } from './utils/swhelper.js';
114
- export { systemIsInDarkMode, isSafari, isFirefox, getValidIndex, minMax, hexToRgbaArray, rgbStrToRgbaArray, colorToRgbaArray, isValidEmail, applyOpacityToLayers, applyFeaturesToSelection, linkify } from './utils/utils.js';
114
+ export { systemIsInDarkMode, isSafari, isFirefox, getValidIndex, minMax, hexToRgbaArray, rgbStrToRgbaArray, colorToRgbaArray, isValidEmail, applyOpacityToLayers, applyFeaturesToSelection, linkify, applyDefaultPrefixToUrl } from './utils/utils.js';
115
115
  export { default as VendorSpecificOgcServerManager } from './vendorspecificogcservermanager.js';
116
116
  export type { WfsClientOptions, WfsClientOptionalOptions, QueryableLayerWms, GetFeatureOptionsPartial } from './wfs/wfsclient.js';
117
117
  export { default as WfsClient, WfsClientMapServer, WfsClientQgis, WfsClientGeorama, WfsClientDefault, WfsClientGeoServer } from './wfs/wfsclient.js';
package/tools/main.js CHANGED
@@ -86,7 +86,7 @@ export { unByKeyAll, getOlayerByName, removeUnwantedOlParams, polygonFromCircle,
86
86
  export { getPropertyByPath, setPropertyByPath, createObjectFromPath, deletePropertyByPath, mergeObjects } from './utils/pathUtils.js';
87
87
  export { generateQrCode } from './utils/qrcode.js';
88
88
  export { default as ServiceWorkerHelper } from './utils/swhelper.js';
89
- export { systemIsInDarkMode, isSafari, isFirefox, getValidIndex, minMax, hexToRgbaArray, rgbStrToRgbaArray, colorToRgbaArray, isValidEmail, applyOpacityToLayers, applyFeaturesToSelection, linkify } from './utils/utils.js';
89
+ export { systemIsInDarkMode, isSafari, isFirefox, getValidIndex, minMax, hexToRgbaArray, rgbStrToRgbaArray, colorToRgbaArray, isValidEmail, applyOpacityToLayers, applyFeaturesToSelection, linkify, applyDefaultPrefixToUrl } from './utils/utils.js';
90
90
  export { default as VendorSpecificOgcServerManager } from './vendorspecificogcservermanager.js';
91
91
  export { default as WfsClient, WfsClientMapServer, WfsClientQgis, WfsClientGeorama, WfsClientDefault, WfsClientGeoServer } from './wfs/wfsclient.js';
92
92
  export { default as WfsFilter, wfsOperatorsStrList, isWfsOperator, mapAttributeTypeToFilterOperators } from './wfs/wfsfilter.js';
@@ -2,6 +2,7 @@ export declare const MockConfig: {
2
2
  general: {
3
3
  locale: string;
4
4
  logLevel: string;
5
+ defaultUrlPrefix: string;
5
6
  };
6
7
  languages: {
7
8
  translations: {
@@ -2,7 +2,8 @@
2
2
  export const MockConfig = {
3
3
  general: {
4
4
  locale: 'en-US',
5
- logLevel: 'debug'
5
+ logLevel: 'debug',
6
+ defaultUrlPrefix: 'https://map.geo.bs.ch'
6
7
  },
7
8
  languages: {
8
9
  translations: {
@@ -26,7 +26,6 @@ declare class ThemesManager extends GirafeSingleton {
26
26
  private applyOpacityToBasemaps;
27
27
  private applyOpacityToBasemap;
28
28
  private prepareThemes;
29
- private calculateMetadataUrl;
30
29
  /**
31
30
  * Will create layer and child layers if elem passed is a group of layers
32
31
  * @param elem either a layer or a group of layers
@@ -16,6 +16,7 @@ import BasemapSwisstopoVectorTiles from '../../models/basemaps/basemapswisstopov
16
16
  import BasemapOsm from '../../models/basemaps/basemaposm.js';
17
17
  import { DEFAULT_OPACITY, OPACITY_FOR_DEFAULT_BASEMAP } from './themes-config.js';
18
18
  import Layer from '../../models/layers/layer.js';
19
+ import { applyDefaultPrefixToUrl } from '../utils/utils.js';
19
20
  class ThemesManager extends GirafeSingleton {
20
21
  anonymousUserInfo = { u: 'anonymous' };
21
22
  get state() {
@@ -246,15 +247,6 @@ class ThemesManager extends GirafeSingleton {
246
247
  });
247
248
  return { themes, themesFunctionalities };
248
249
  }
249
- calculateMetadataUrl(metadataUrl) {
250
- if (!metadataUrl) {
251
- return undefined;
252
- }
253
- if (!metadataUrl.startsWith('http') && this.context.configManager.Config.metadata.metadataUrlPrefix) {
254
- return this.context.configManager.Config.metadata.metadataUrlPrefix + metadataUrl;
255
- }
256
- return metadataUrl;
257
- }
258
250
  /**
259
251
  * Will create layer and child layers if elem passed is a group of layers
260
252
  * @param elem either a layer or a group of layers
@@ -312,7 +304,7 @@ class ThemesManager extends GirafeSingleton {
312
304
  time: elem.time
313
305
  };
314
306
  if (options.metadataUrl) {
315
- options.metadataUrl = this.calculateMetadataUrl(options.metadataUrl);
307
+ options.metadataUrl = applyDefaultPrefixToUrl(this.context, options.metadataUrl);
316
308
  }
317
309
  const group = new GroupLayer(elem.id, elem.name, order.value, options);
318
310
  // Append children
@@ -336,7 +328,7 @@ class ThemesManager extends GirafeSingleton {
336
328
  const ogcServer = this.state.ogcServers[ogcServerName];
337
329
  const options = elem;
338
330
  if (options.metadata?.metadataUrl) {
339
- options.metadata.metadataUrl = this.calculateMetadataUrl(options.metadata.metadataUrl);
331
+ options.metadata.metadataUrl = applyDefaultPrefixToUrl(this.context, options.metadata.metadataUrl);
340
332
  }
341
333
  const wmsLayer = new LayerWms(elem.id, elem.name, order.value, ogcServer, elem);
342
334
  // For WMFS queries, the layers attribute will be used. It can be different from the name.
@@ -356,7 +348,7 @@ class ThemesManager extends GirafeSingleton {
356
348
  const ogcServer = elem.metadata?.ogcServer ? this.state.ogcServers[elem.metadata?.ogcServer] : undefined;
357
349
  const options = elem;
358
350
  if (options.metadata?.metadataUrl) {
359
- options.metadata.metadataUrl = this.calculateMetadataUrl(options.metadata.metadataUrl);
351
+ options.metadata.metadataUrl = applyDefaultPrefixToUrl(this.context, options.metadata.metadataUrl);
360
352
  }
361
353
  return new LayerWmts(elem.id, elem.name, order.value, elem.url, elem.layer, options, ogcServer);
362
354
  }
@@ -376,7 +368,7 @@ class ThemesManager extends GirafeSingleton {
376
368
  layerName: elem.metadata.layerName
377
369
  };
378
370
  if (options.metadata?.metadataUrl) {
379
- options.metadata.metadataUrl = this.calculateMetadataUrl(options.metadata.metadataUrl);
371
+ options.metadata.metadataUrl = applyDefaultPrefixToUrl(this.context, options.metadata.metadataUrl);
380
372
  }
381
373
  return new LayerVectorTiles(elem.id, elem.name, order.value, elem.style, options);
382
374
  }
@@ -161,18 +161,26 @@ export const getRadiusDataForCircle = (circle, defaultStyle, stroke) => {
161
161
  };
162
162
  };
163
163
  export const getLengthAsMetricText = (length) => {
164
- if (length) {
165
- const formatedLength = length > 100 ? (length / 1000).toFixed(2) + ' km' : length.toFixed(2) + ' m';
166
- return formatedLength;
164
+ if (length === undefined) {
165
+ return '';
167
166
  }
168
- return '';
167
+ if (length <= 500) {
168
+ return `${length.toFixed(2)} m`;
169
+ }
170
+ const lengthInKilometers = length / 1000;
171
+ if (length <= 2000) {
172
+ return `${lengthInKilometers.toFixed(3)} km`;
173
+ }
174
+ return `${lengthInKilometers.toFixed(2)} km`;
169
175
  };
170
176
  export const getAreaAsMetricText = (area) => {
171
- if (area) {
172
- const formatedArea = area > 10000 ? (area / 1000000).toFixed(2) + ' km²' : area.toFixed(2) + ' m²';
173
- return formatedArea;
177
+ if (area === undefined) {
178
+ return '';
174
179
  }
175
- return '';
180
+ if (area <= 10000) {
181
+ return `${area.toFixed(2)} m²`;
182
+ }
183
+ return `${(area / 1000000).toFixed(2)} km²`;
176
184
  };
177
185
  export const getAzimuthAsText = (azimuth) => {
178
186
  if (azimuth) {
@@ -2,6 +2,7 @@ import BaseLayer from '../../models/layers/baselayer.js';
2
2
  import Feature from 'ol/Feature.js';
3
3
  import { Geometry } from 'ol/geom.js';
4
4
  import State from '../state/state.js';
5
+ import IGirafeContext from '../context/icontext.js';
5
6
  /**
6
7
  * Checks if the system prefers dark mode.
7
8
  * Falls back safely if matchMedia is not supported.
@@ -68,3 +69,11 @@ export declare const applyOpacityToLayers: (opacity: number, layers: BaseLayer[]
68
69
  */
69
70
  export declare const applyFeaturesToSelection: (features: Feature<Geometry>[], state: State) => void;
70
71
  export declare const linkify: (str: string) => string;
72
+ /**
73
+ * Apply default prefix to a relative URL
74
+ * Is usefull on the demo website for metadata or some images urls
75
+ * @param context
76
+ * @param metadataUrl
77
+ * @returns
78
+ */
79
+ export declare function applyDefaultPrefixToUrl(context: IGirafeContext, metadataUrl?: string): string | undefined;
@@ -183,3 +183,19 @@ export const linkify = (str) => {
183
183
  }
184
184
  return str;
185
185
  };
186
+ /**
187
+ * Apply default prefix to a relative URL
188
+ * Is usefull on the demo website for metadata or some images urls
189
+ * @param context
190
+ * @param metadataUrl
191
+ * @returns
192
+ */
193
+ export function applyDefaultPrefixToUrl(context, metadataUrl) {
194
+ if (!metadataUrl) {
195
+ return undefined;
196
+ }
197
+ if (!metadataUrl.startsWith('http') && context.configManager.Config.general.defaultUrlPrefix) {
198
+ return `${context.configManager.Config.general.defaultUrlPrefix}${metadataUrl}`;
199
+ }
200
+ return metadataUrl;
201
+ }