UNPKG

@geogirafe/lib-geoportal

Version:

GeoGirafe is a flexible application to build online geoportals.

238 lines (237 loc) 24.7 kB
import { html as uHtml } from 'uhtml'; // SPDX-License-Identifier: Apache-2.0 import tippy from 'tippy.js'; import LayerWms from '../../../models/layers/layerwms.js'; import LayerLocalFile from '../../../models/layers/layerlocalfile.js'; import QueryBuilderComponent from '../../querybuilder/component.js'; import LayerWmts from '../../../models/layers/layerwmts.js'; import TreeViewElement from '../tools/treeviewelement.js'; import { isSnappableLayer } from '../../../models/layers/snappablelayer.js'; import WmsLegendHelper from '../../../tools/wms/wmslegendhelper.js'; class TreeViewItemComponent extends TreeViewElement { templateUrl = null; styleUrls = null; template = () => { return uHtml `<style> header{border-top:1px solid #ddd;align-items:center;height:2rem;display:flex}.tool{display:none!important}header:hover .tool{display:flex!important}.tool.active{order:100;opacity:1!important;display:flex!important}.label-container{flex-grow:1;align-items:center;display:flex;overflow:auto}.label-out-resolution span{font-style:italic}.resolution-tool{margin-left:.5rem}.legend{display:flex}.legend img{background:var(--svg-legend-bkg);height:fit-content;filter:var(--svg-map-filter)}.legend-icon{background:var(--svg-legend-bkg);max-height:1.5rem;filter:var(--svg-map-filter);margin-left:.5rem}.children{flex-basis:100%;order:10;padding-left:1.3rem}.dragAfter{border-bottom:1rem dashed #ccc}.dragBefore{border-top:1rem dashed #ccc}.gg-checkbox{width:1.2rem}.gg-caret,.gg-spacer{text-align:center;width:1.5rem;padding:0}.gg-caret{transform:scale(1.3)}.gg-caret.gg-rotate90{transform:scale(1.3)rotate(90deg)}.gg-small.gg-lock{min-width:1rem}.gg-opacity.gg-lock:hover{opacity:.5!important}.gg-tree-label{text-align:left;white-space:nowrap;text-overflow:ellipsis;padding-left:0;overflow:hidden}.gg-grab:hover{cursor:grab}.gg-selected{opacity:1}.legend-file{color:var(--text-color);font-style:italic;display:flex}@keyframes headerFade{0%{background-color:var(--highlight-color)}to{background-color:#0000}}.highlight{animation:3s ease-in-out forwards headerFade} </style><style> .hidden{display:none!important}.gg-rotate90{transform:rotate(90deg)}.gg-rotate180{transform:rotate(180deg)}.gg-rotate270{transform:rotate(270deg)}img{filter:var(--svg-filter)}img.legend-image{filter:var(--svg-map-filter);background:var(--svg-legend-bkg)}div{scrollbar-width:thin}a,a:visited{color:var(--link-color)}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes spin-wait{0%{transform:rotate(0)}7%{transform:rotate(360deg)}to{transform:rotate(360deg)}}.gg-spin{animation-name:spin;animation-duration:2s;animation-timing-function:linear;animation-iteration-count:infinite}.gg-spin-wait{animation-name:spin-wait;animation-duration:10s;animation-timing-function:linear;animation-iteration-count:infinite}::-webkit-scrollbar{width:5px}::-webkit-scrollbar-thumb{background:#999}button,input,select,textarea{font:inherit}.gg-button,.gg-select,.gg-input,.gg-textarea{background-color:var(--bkg-color);color:var(--text-color);border:var(--app-standard-border);box-sizing:border-box;cursor:pointer;border-radius:3px;outline:0;margin:0;padding:0 0 0 .5rem;display:inline-block}.gg-label{background-color:var(--bkg-color);color:var(--text-color);border:none;align-items:center;margin:0;padding:0;display:flex}.gg-button,.gg-select,.gg-input,.gg-label{min-height:calc(var(--app-standard-height) / 1.5)}.gg-textarea{max-height:initial;resize:vertical;height:6rem;padding:.5rem;line-height:1.3rem}.gg-input{cursor:text}.gg-checkbox{accent-color:var(--text-color);width:1.2rem}.gg-range{accent-color:var(--text-color)}.gg-button{padding:0 .5rem}.gg-button.active{border:solid 1px var(--text-color-grad1);background-color:var(--bkg-color-grad2)}.gg-button:disabled{background-color:var(--bkg-color-grad1);color:var(--text-color-grad2);cursor:not-allowed;border:none}.gg-button:disabled img{filter:opacity(.6)}.gg-input:disabled,.gg-select:disabled,.gg-textarea:disabled{background-color:var(--bkg-color-grad1);color:var(--text-color-grad2);cursor:not-allowed}.gg-button>img{vertical-align:middle}.gg-icon-button{color:var(--text-color);cursor:pointer;background-color:#0000;border:none;flex-direction:column;justify-content:center;align-items:center;padding:0;display:flex}.gg-icon{justify-content:center;align-items:center;display:flex}.gg-big,.gg-big-withtext{min-width:var(--app-standard-height);min-height:var(--app-standard-height);max-height:var(--app-standard-height)}.gg-big img,.gg-big-withtext img{width:calc(var(--app-standard-height) - 1.5rem);margin:0}.gg-big-withtext span{font-variant:small-caps;padding:0 1rem;font-size:.9rem}.gg-medium,.gg-medium-withtext{min-width:calc(var(--app-standard-height) / 1.2);min-height:calc(var(--app-standard-height) / 1.2);max-height:calc(var(--app-standard-height) / 1.2);flex-direction:row}.gg-medium img{width:calc(var(--app-standard-height) / 2.4);margin:0}.gg-medium-withtext img{width:calc(var(--app-standard-height) / 2.4);margin-left:.5rem}.gg-medium-withtext span{padding:0 1rem 0 .5rem;font-size:.9rem}.gg-small,.gg-small-withtext{min-width:calc(var(--app-standard-height) / 2);min-height:calc(var(--app-standard-height) / 2);max-height:calc(var(--app-standard-height) / 2);flex-direction:row}.gg-small img{width:calc(var(--app-standard-height) / 3);margin:0}.gg-small-withtext img{width:calc(var(--app-standard-height) / 3);margin-left:.5rem}.gg-small-withtext span{padding:0 .5rem 0 .3rem;font-size:.9rem}.gg-button:hover:not(:disabled),.gg-select:hover:not(:disabled),.gg-input:hover:not(:disabled),.gg-textarea:hover:not(:disabled),.gg-icon-button:hover:not(:disabled){background-color:var(--bkg-color-grad1)}.gg-opacity{opacity:.5}.gg-opacity:hover{opacity:1;background-color:#0000}.gg-tabs{cursor:pointer;grid-auto-flow:column;padding-bottom:1rem;font-size:1rem;display:grid}.gg-tab{border:none;border-bottom:var(--app-standard-border);cursor:pointer;color:var(--text-color);background:0 0;padding:.5rem}.gg-tab.active{border-bottom:solid 1px var(--text-color)}.girafe-button-big,.girafe-button-large,.girafe-button-small,.girafe-button-tiny{color:var(--text-color);background-color:#0000;border:none;flex-direction:column;display:flex}.girafe-button-big:hover,.girafe-button-large:hover,.girafe-button-small:hover,.girafe-button-tiny:hover{background-color:var(--bkg-color-grad1);cursor:pointer}.girafe-button-big.dark,.girafe-button-large.dark,.girafe-button-small.dark,.girafe-button-tiny.dark{background-color:var(--bkg-color);filter:invert()}.girafe-button-big{width:var(--app-standard-height);height:var(--app-standard-height);align-items:center;padding:1rem}.girafe-button-big img{overflow:hidden}.girafe-button-large{flex-direction:row}.girafe-button-large img{height:2rem;margin:.3rem}.girafe-button-large span{height:2rem;margin:.3rem;line-height:2rem}.girafe-button-small{min-width:calc(var(--app-standard-height) / 2);height:calc(var(--app-standard-height) / 2);align-items:center;padding:.5rem}.girafe-button-small img{overflow:hidden}.girafe-button-small span{text-align:left;text-overflow:ellipsis;width:100%;overflow:hidden}.girafe-button-tiny{align-items:center;width:1rem;height:1rem;padding:0}.girafe-button-tiny img{overflow:hidden}.girafe-onboarding-theme{background-color:var(--bkg-color)!important;color:var(--text-color)!important}.girafe-onboarding-theme button{background-color:var(--bkg-color)!important;color:var(--text-color)!important;text-shadow:none!important}.girafe-onboarding-theme button.driver-popover-close-btn{z-index:10000}.tippy-box{background-color:var(--bkg-color)!important;border:var(--app-standard-border)!important}.tippy-content{color:var(--text-color)!important}.tippy-arrow{color:var(--bkg-color)!important}.tippy-box[data-theme~=error]{background-color:var(--error-color);white-space:pre-line}div.tippy-box[data-theme=image-popup]{border:var(--app-standard-border)!important;& div.tippy-content{background-color:var(--bkg-color)!important;& img{max-width:20rem;max-height:20rem}}& div.tippy-arrow{color:var(--bkg-color)!important}} </style> <style>${this.customStyle}</style> <link rel="stylesheet" href="lib/tippy.js/tippy.css"><link rel="stylesheet" href="lib/tippy.js/backdrop.css"><link rel="stylesheet" href="lib/tippy.js/border.css"><link rel="stylesheet" href="lib/tippy.js/svg-arrow.css"><div id="container"><header><div class="gg-spacer gg-small"><img class="${this.layer.restricted ? (this.layer.active ? 'gg-small gg-lock gg-selected' : 'gg-small gg-lock gg-opacity') : 'hidden'}" alt="Protected layer" src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8bWFzayBpZD0ibWFzazBfMzdfNDUxNyIgc3R5bGU9Im1hc2stdHlwZTphbHBoYSIgbWFza1VuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeD0iMCIgeT0iMCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0Ij4KICA8cmVjdCB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9IiNEOUQ5RDkiLz4KICA8L21hc2s+CiAgPGcgbWFzaz0idXJsKCNtYXNrMF8zN180NTE3KSI+CiAgPHBhdGggZD0iTTYgMjJDNS40NSAyMiA0Ljk3OTE3IDIxLjgwNDIgNC41ODc1IDIxLjQxMjVDNC4xOTU4MyAyMS4wMjA4IDQgMjAuNTUgNCAyMFYxMEM0IDkuNDUgNC4xOTU4MyA4Ljk3OTE3IDQuNTg3NSA4LjU4NzVDNC45NzkxNyA4LjE5NTgzIDUuNDUgOCA2IDhIN1Y2QzcgNC42MTY2NyA3LjQ4NzUgMy40Mzc1IDguNDYyNSAyLjQ2MjVDOS40Mzc1IDEuNDg3NSAxMC42MTY3IDEgMTIgMUMxMy4zODMzIDEgMTQuNTYyNSAxLjQ4NzUgMTUuNTM3NSAyLjQ2MjVDMTYuNTEyNSAzLjQzNzUgMTcgNC42MTY2NyAxNyA2VjhIMThDMTguNTUgOCAxOS4wMjA4IDguMTk1ODMgMTkuNDEyNSA4LjU4NzVDMTkuODA0MiA4Ljk3OTE3IDIwIDkuNDUgMjAgMTBWMjBDMjAgMjAuNTUgMTkuODA0MiAyMS4wMjA4IDE5LjQxMjUgMjEuNDEyNUMxOS4wMjA4IDIxLjgwNDIgMTguNTUgMjIgMTggMjJINlpNNiAyMEgxOFYxMEg2VjIwWk0xMiAxN0MxMi41NSAxNyAxMy4wMjA4IDE2LjgwNDIgMTMuNDEyNSAxNi40MTI1QzEzLjgwNDIgMTYuMDIwOCAxNCAxNS41NSAxNCAxNUMxNCAxNC40NSAxMy44MDQyIDEzLjk3OTIgMTMuNDEyNSAxMy41ODc1QzEzLjAyMDggMTMuMTk1OCAxMi41NSAxMyAxMiAxM0MxMS40NSAxMyAxMC45NzkyIDEzLjE5NTggMTAuNTg3NSAxMy41ODc1QzEwLjE5NTggMTMuOTc5MiAxMCAxNC40NSAxMCAxNUMxMCAxNS41NSAxMC4xOTU4IDE2LjAyMDggMTAuNTg3NSAxNi40MTI1QzEwLjk3OTIgMTYuODA0MiAxMS40NSAxNyAxMiAxN1pNOSA4SDE1VjZDMTUgNS4xNjY2NyAxNC43MDgzIDQuNDU4MzMgMTQuMTI1IDMuODc1QzEzLjU0MTcgMy4yOTE2NyAxMi44MzMzIDMgMTIgM0MxMS4xNjY3IDMgMTAuNDU4MyAzLjI5MTY3IDkuODc1IDMuODc1QzkuMjkxNjcgNC40NTgzMyA5IDUuMTY2NjcgOSA2VjhaIiBmaWxsPSIjMUMxQjFGIi8+CiAgPC9nPgo8L3N2Zz4KICA="></div><button class="${this.layer.active ? 'gg-icon-button gg-small gg-selected' : 'gg-icon-button gg-small gg-opacity'}" tip="Activate / Deactivate" onclick="${() => this.toggle()}"><img class="${this.layer.active ? 'gg-checkbox' : 'hidden'}" alt="Expand/Collapse button" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NDggNTEyIj48IS0tIUZvbnQgQXdlc29tZSBGcmVlIDYuNi4wIGJ5IEBmb250YXdlc29tZSAtIGh0dHBzOi8vZm9udGF3ZXNvbWUuY29tIExpY2Vuc2UgLSBodHRwczovL2ZvbnRhd2Vzb21lLmNvbS9saWNlbnNlL2ZyZWUgQ29weXJpZ2h0IDIwMjQgRm9udGljb25zLCBJbmMuLS0+PHBhdGggZD0iTTY0IDMyQzI4LjcgMzIgMCA2MC43IDAgOTZMMCA0MTZjMCAzNS4zIDI4LjcgNjQgNjQgNjRsMzIwIDBjMzUuMyAwIDY0LTI4LjcgNjQtNjRsMC0zMjBjMC0zNS4zLTI4LjctNjQtNjQtNjRMNjQgMzJ6TTMzNyAyMDlMMjA5IDMzN2MtOS40IDkuNC0yNC42IDkuNC0zMy45IDBsLTY0LTY0Yy05LjQtOS40LTkuNC0yNC42IDAtMzMuOXMyNC42LTkuNCAzMy45IDBsNDcgNDdMMzAzIDE3NWM5LjQtOS40IDI0LjYtOS40IDMzLjkgMHM5LjQgMjQuNiAwIDMzLjl6Ii8+PC9zdmc+"> <img class="${!this.layer.active ? 'gg-checkbox' : 'hidden'}" alt="Expand/Collapse button" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NDggNTEyIj48IS0tIUZvbnQgQXdlc29tZSBGcmVlIDYuNi4wIGJ5IEBmb250YXdlc29tZSAtIGh0dHBzOi8vZm9udGF3ZXNvbWUuY29tIExpY2Vuc2UgLSBodHRwczovL2ZvbnRhd2Vzb21lLmNvbS9saWNlbnNlL2ZyZWUgQ29weXJpZ2h0IDIwMjQgRm9udGljb25zLCBJbmMuLS0+PHBhdGggZD0iTTM4NCA4MGM4LjggMCAxNiA3LjIgMTYgMTZsMCAzMjBjMCA4LjgtNy4yIDE2LTE2IDE2TDY0IDQzMmMtOC44IDAtMTYtNy4yLTE2LTE2TDQ4IDk2YzAtOC44IDcuMi0xNiAxNi0xNmwzMjAgMHpNNjQgMzJDMjguNyAzMiAwIDYwLjcgMCA5NkwwIDQxNmMwIDM1LjMgMjguNyA2NCA2NCA2NGwzMjAgMGMzNS4zIDAgNjQtMjguNyA2NC02NGwwLTMyMGMwLTM1LjMtMjguNy02NC02NC02NEw2NCAzMnoiLz48L3N2Zz4="></button><div class="${this.layer.hasError ? 'gg-icon gg-small gg-opacity' : 'hidden'}" tip="${this.layer.errorMessage ? this.layer.errorMessage : 'Error on layer'}"><img alt="Error on layer" src="icons/error.svg"></div><div class="${this.isVisibleInCurrentResolution() ? 'label-container' : 'label-container label-out-resolution'}"><button class="${this.layer.active ? 'gg-icon-button gg-small gg-selected' : 'gg-icon-button gg-small gg-opacity'}" onclick="${() => this.toggle()}"><span i18n="${this.layer.name}" class="gg-tree-label">${this.layer.name}</span></button> <button class="${this.layer.active && this.layer instanceof LayerWms && !this.isVisibleInCurrentResolution() ? 'gg-icon-button gg-small resolution-tool' : 'hidden'}" tip="Zoom to visible resolution" onclick="${() => this.zoomToVisibleResolution()}"><img alt="Zoom to visible resolution" src="icons/zoom.svg"></button> <img class="${this.layer.active && this.iconUrl ? 'legend-icon' : 'hidden'}" alt="${'Icon for ' + this.layer.name}" src="${this.iconUrl}" loading="lazy" crossorigin="${this.getCrossOrigin(this.iconUrl)}"></div><button class="${this.layer.active && this.layer instanceof LayerLocalFile ? 'gg-icon-button gg-small gg-opacity tool' : 'hidden'}" tip="Zoom to full extent" onclick="${() => this.zoomToFullExtent()}"><img alt="Zoom to full extent" src="icons/zoom.svg"></button> <button class="${this.getButtonClass('swipedLeft')}" tip="Swipe layer to the left" onclick="${() => this.layer.swiped = (this.layer.swiped === 'left') ? 'no' : 'left'}"><img alt="Swipe layer to the left" src="icons/swipe-left.svg"></button> <button class="${this.getButtonClass('swipedRight')}" tip="Swipe layer to the right" onclick="${() => this.layer.swiped = (this.layer.swiped === 'right') ? 'no' : 'right'}"><img alt="Swipe layer to the right" src="icons/swipe-right.svg"></button> <button id="opacity" class="${this.getButtonClass('opacity')}" tip="Control opacity"><img alt="Control opacity" src="icons/opacity.svg"></button> <button id="filter" class="${this.getButtonClass('filter')}" tip="Filter layer"><img alt="Filter layer" src="icons/filter.svg"></button> <button id="advanced-filter" class="${this.getButtonClass('advanced-filter')}" tip="Open advanced filter tool" onclick="${() => this.state.interface.advancedFilterPanelVisible = !this.state.interface.advancedFilterPanelVisible}"><img alt="Advanced filter" src="icons/advanced-filter.svg"></button> <button id="timeRestriction" class="${this.getButtonClass('timeRestriction')}" tip="Define time restriction on layer"><img alt="Define time restriction on layer" src="icons/clock.svg"></button> <button class="${this.getButtonClass('snappable')}" onclick="${() => this.toggleSnap()}" tip="Snap to layer features"><img alt="Enable snapping" src="icons/snapping.svg"></button> <button class="${this.hasLegend ? (this.layer.isLegendExpanded ? 'gg-icon-button gg-small tool' : 'gg-icon-button gg-small gg-opacity tool') : 'hidden'}" tip="Toggle legend" onclick="${() => this.toggleLegend()}"><img alt="Toggle legend" src="icons/legend.svg" loading="lazy"></button> <button class="${this.layer.hasMetadata ? 'metadata gg-icon-button gg-small gg-opacity tool' : 'hidden'}" onclick="${() => this.showMetadata()}"><img alt="Metadata" src="icons/info.svg"></button> <button id="drag-button" class="${this.getButtonClass('draggable')}" tip="Move"><img alt="Move layer" src="icons/drag.svg"></button> <button class="${this.getButtonClass('removable')}" tip="Remove layer" onclick="${() => this.deleteLayer()}"><img alt="Remove layer" src="icons/trash.svg"></button></header>${Object.keys(this.legendUrls).map((l) => uHtml `<div class="${this.isLegendExpanded ? 'legend' : 'hidden'}"><div class="gg-spacer gg-small"></div><img alt="${'Legend for ' + l}" src="${this.legendUrls[l]}" loading="lazy" crossorigin="${this.getCrossOrigin(this.legendUrls[l])}"></div>`)}<div class="${this.layer instanceof LayerLocalFile && this.isLegendExpanded ? 'legend-file' : 'legend-file hidden'}"><div class="gg-spacer gg-small"></div><div class="gg-spacer gg-small"></div><div><span i18n="File from">File from</span> <span>${this.layer.lastModifiedDate}</span> <span>[</span> <span>${this.layer._features?.length}</span> <span i18n="features">features</span> <span>]</span></div></div></div> ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`; }; iconUrl = null; legendUrls = {}; wmsLegendHelper; layer; get hasLegend() { return this.context.layerManager.isLayerWithLegend(this.layer) && this.layer.legend; } get isLegendExpanded() { if (this.context.layerManager.isLayerWithLegend(this.layer)) { return this.layer.isLegendExpanded; } return false; } toggleLegend() { if (this.context.layerManager.isLayerWithLegend(this.layer)) { this.layer.isLegendExpanded = !this.layer.isLegendExpanded; } } toggleSnap() { if (isSnappableLayer(this.layer)) { this.layer.snapActive = !this.layer.snapActive; } } constructor(layer) { super(layer, 'treeviewitem'); this.layer = layer; } render() { // If we come from a html element, the layer was not defined in the constructor // And we have to set the layer using the id passed to the layerid attribute const layerId = this.getAttribute('layerid'); if (layerId) { this.layer = this.context.layerManager.getTreeItem(layerId); if (this.layer instanceof LayerWms) { // Manage Legend icons for WMS this.setWmsLegend(); } if (this.layer instanceof LayerWmts) { this.setWmtsLegend(); } } super.render(); this.createOpacityTooltip(); this.createFilterTooltip(); } setWmsLegend() { if (!(this.layer instanceof LayerWms)) { // nothing to do if it's not a WMS return; } this.iconUrl = this.wmsLegendHelper.getIconUrl(this.layer); if (this.isVisibleInCurrentResolution()) { this.legendUrls = this.wmsLegendHelper.getLegendUrls(this.layer); } else { this.legendUrls = {}; } } setWmtsLegend() { if (!(this.layer instanceof LayerWmts)) { // nothing to do if it's not a WMS return; } if (this.layer.legend) { if (this.layer.legendImage) { this.legendUrls[this.layer.name] = this.layer.legendImage; } else { this.layer.hasError = true; this.layer.errorMessage = `The WMTS Layer ${this.layer.name} has no legendImage.`; } } } getCrossOrigin(url) { if (!url) { return 'anonymous'; } const hostname = new URL(url).hostname; return this.state.oauth.audience.includes(hostname) ? 'use-credentials' : 'anonymous'; } createOpacityTooltip() { const el = this.shadow.getElementById('opacity'); if (!el) { return; } tippy(el, { trigger: 'click', arrow: true, interactive: true, theme: 'light', placement: 'right', content: (_reference) => { const slider = document.createElement('input'); slider.type = 'range'; slider.className = 'slider'; slider.min = '0'; slider.max = '20'; slider.value = (this.layer.opacity * 20).toString(); slider.oninput = () => (this.layer.opacity = Number.parseInt(slider.value) / 20); return slider; } }); } createFilterTooltip() { const el = this.shadow.getElementById('filter'); if (!el) { return; } tippy(el, { trigger: 'click', arrow: true, interactive: true, theme: 'light', placement: 'right', appendTo: document.body, content: (_reference) => { const filterbox = new QueryBuilderComponent(this.layer, this.context); return filterbox; } }); } registerEvents() { this.subscribe(/layers\..*\.isLegendExpanded/, (_oldValue, _newValue, layer) => { this.refreshLegendsAndStyle(); this.refreshRender(layer); }); this.subscribe(/layers\.layersList\..*\.activeState/, (_oldValue, _newValue, layer) => { this.refreshLegendsAndStyle(); this.refreshRender(layer); }); this.subscribe(/layers\.layersList\..*\.hasError/, (_oldValue, _newValue, layer) => this.refreshRender(layer)); this.subscribe(/layers\.layersList\..*\.errorMessage/, (_oldValue, _newValue, layer) => this.refreshRender(layer)); this.subscribe(/layers\.layersList\..*\.filter/, (_oldValue, _newValue, layer) => this.refreshRender(layer)); this.subscribe(/layers\.layersList\..*\.snapActive/, (_oldValue, _newValue, layer) => this.refreshRender(layer)); this.subscribe(/layers\.layersList\..*\.timeRestriction/, (_old, _new, layer) => { if (layer === this.layer || layer === this.layer.parent) this.refreshRender(this.layer); }); this.subscribe(/layers\.layersList\..*\.opacity/, (_oldValue, _newValue, layer) => this.refreshRender(layer)); this.subscribe(/layers\.layersList\..*\.swiped/, (_oldValue, _newValue, layer) => this.refreshRender(layer)); this.subscribe('treeview.advanced', () => this.refreshRender(this.layer)); this.subscribe('position', () => this.refreshLegendsAndStyle()); } refreshLegendsAndStyle() { if (!this.layer.parent.isExpanded) { // Not visible, nothing to refresh return; } let refresh = false; if (this.layer instanceof LayerWms && this.layer.legend && this.layer.isLegendExpanded) { this.setWmsLegend(); refresh = true; } if ((this.layer instanceof LayerWms || this.layer instanceof LayerWmts) && this.layer.hasRestrictedResolution()) { // Restricted resolution, maybe the layername should be written italic refresh = true; } if (refresh) { super.refreshRender(); } } toggle(state) { this.context.layerManager.toggleLayer(this.layer, state); } zoomToVisibleResolution() { if (!(this.layer instanceof LayerWms)) { throw new Error(`${this.layer.name} is not a WMS layer, this method should not be called here.`); } if (this.layer.maxResolution) { if (this.context.configManager.Config.map.constrainScales) { // We have to find the right resolution const allowedResolutions = this.context.mapManager.getMap().getView().getResolutions(); const maxResolution = this.layer.maxResolution; const newResolution = allowedResolutions.find((r) => r < maxResolution); this.state.position.resolution = newResolution; } else { // We can just zoom to the correct resolution. // But because of rounding errors (for example 1.59 becomes 1.589999999999998), // we zoom a bit more than just the max resolution (5% more) const resolution = this.layer.maxResolution * 0.95; this.state.position.resolution = resolution; } } } isVisibleInCurrentResolution() { if (!(this.layer instanceof LayerWms) && !(this.layer instanceof LayerWmts)) { // Always true for not WMS/WMTS layers return true; } const currentResolution = this.state.position.resolution; if (currentResolution) { return this.layer.isVisibleAtResolution(currentResolution); } return false; } zoomToFullExtent() { if (!(this.layer instanceof LayerLocalFile)) { throw new Error(`${this.layer.name} is not a LocalFile layer, this method should not be called here.`); } this.context.mapManager.zoomToExtent(this.layer.extent); } deleteLayer() { this.context.layerManager.toggleLayer(this.layer, 'off'); this.removeFromParent(); } connectedCallback() { super.connectedCallback(); this.wmsLegendHelper = new WmsLegendHelper(this.context); this.render(); this.registerEvents(); } } export default TreeViewItemComponent;