UNPKG

@geogirafe/lib-geoportal

Version:

GeoGirafe is a flexible application to build online geoportals.

250 lines (249 loc) • 9.67 kB
// SPDX-License-Identifier: Apache-2.0 import GirafeHTMLElement from '../../../base/GirafeHTMLElement.js'; import { isTimeAwareLayer } from '../../../models/layers/timeawarelayer.js'; import { isSnappableLayer } from '../../../models/layers/snappablelayer.js'; import tippy from 'tippy.js'; import TimeRestrictionComponent from '../../timerestriction/component.js'; import LayerWms from '../../../models/layers/layerwms.js'; import Layer from '../../../models/layers/layer.js'; import GroupLayer from '../../../models/layers/grouplayer.js'; import LayerGroup from 'ol/layer/Group.js'; export default class TreeViewElement extends GirafeHTMLElement { dragManager; layer; dragButton; container; header; constructor(layer, name) { super(name); this.layer = layer; } connectedCallback() { super.connectedCallback(); this.dragManager = this.context.dragManager; } render() { super.render(); this.dragButton = this.shadow.getElementById('drag-button'); this.container = this.shadow.getElementById('container'); this.header = this.shadow.querySelector('header'); super.girafeTranslate(); this.initializeDrag(); if (isTimeAwareLayer(this.layer)) { this.createTimeRestrictionTooltip(this.layer); } this.subscribe(/layers\.layersList\..*\.isHighlighted/, (_oldValue, newValue, layer) => { if (newValue && layer === this.layer) { this.highlight(); } }); } highlight() { this.header.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); this.header.classList.add('highlight'); setTimeout(() => { this.header.classList.remove('highlight'); this.layer.isHighlighted = false; }, 3000); } refreshRender(layer) { if (!layer) { // For performance reason, we allow a call to refreshRender() // only with the concerned layer as parameter. // Otherwise, this method could be called too many times // and will refresh every layer many times. throw new Error('When refreshing the treeview, the parameter layer MUST BE set.'); } if (this.state.treeview.renderEnabled && layer === this.layer) { super.refreshRender(); super.girafeTranslate(); if (this.layer.isHighlighted) { this.highlight(); } } } showMetadata() { const metadataTitle = this.context.configManager.Config.infoWindow.defaultMetadataTitle ?? this.layer.name; window.gOpenWindow(metadataTitle, this.layer.metadataUrl); } initializeDrag() { if (!this.layer.isDraggable) { return; } this.dragButton.draggable = true; this.dragButton.ondragstart = (e) => this.dragStart(e); this.dragButton.ondragend = (e) => this.dragEnd(e); this.ondragenter = (e) => this.dragEnter(e); this.ondragleave = (e) => this.dragLeave(e); } dragStart(event) { this.dragManager.dragStart(this.layer); event.dataTransfer.setDragImage(this, this.offsetWidth, 0); } dragEnd(_event) { this.dragManager.dragEnd(); } dragEnter(_event) { if (this.dragManager.dragEnter(this.layer)) { this.setDragStyle(); } } dragLeave(_event) { if (this.dragManager.dragLeave(this.layer)) { this.setDragStyle(); } } setDragStyle() { if (this.dragManager.dragAfter) { this.container.classList.remove('dragBefore'); this.container.classList.add('dragAfter'); } else if (this.dragManager.dragBefore) { this.container.classList.remove('dragAfter'); this.container.classList.add('dragBefore'); } else { this.container.classList.remove('dragAfter'); this.container.classList.remove('dragBefore'); } } getButtonClass(button) { const buttonClasses = 'gg-icon-button gg-small gg-opacity tool'; const activeButtonClasses = buttonClasses + ' active'; switch (button) { case 'swipedLeft': if (this.layer.isSwipeable && !this.layer.inactive && this.layer instanceof Layer) { return this.layer.swiped === 'left' ? activeButtonClasses : buttonClasses; } return 'hidden'; case 'swipedRight': if (this.layer.isSwipeable && !this.layer.inactive && this.layer instanceof Layer) { return this.layer.swiped === 'right' ? activeButtonClasses : buttonClasses; } return 'hidden'; case 'opacity': if (this.layer.inactive) { return 'hidden'; } if (this.layer instanceof Layer) { return this.layer.opacity < 1 ? activeButtonClasses : buttonClasses; } // Allow opacity on group-layer of the 1st level only. if (this.layer instanceof GroupLayer && this.layer.isFirstLevelGroup()) { return this.layer.opacity < 1 ? activeButtonClasses : buttonClasses; } return 'hidden'; case 'filter': if (!this.layer.inactive && this.layer instanceof LayerWms && this.layer.queryable) { if (this.layer.hasFilter) { // Hide the filter icon if it's not a simple filter (advanced filter icon will be shown instead) return this.layer.filter.isSimpleFilter() ? activeButtonClasses : 'hidden'; } // No filter applied yet return buttonClasses; } return 'hidden'; case 'advanced-filter': if (!this.layer.inactive && this.layer instanceof LayerWms && this.layer.hasFilter && this.layer.filter.isAdvancedFilter()) { return activeButtonClasses; } return 'hidden'; case 'timeRestriction': if (!this.layer.inactive && isTimeAwareLayer(this.layer)) { return this.layer.hasTimeRestriction ? activeButtonClasses : buttonClasses; } return 'hidden'; case 'snappable': if (!this.layer.inactive && isSnappableLayer(this.layer)) { return this.layer.snapActive ? activeButtonClasses : buttonClasses; } return 'hidden'; case 'draggable': if (this.layer.isDraggable) { return 'gg-icon-button gg-small gg-grab gg-opacity tool'; } return 'hidden'; case 'removable': if (this.layer.isRemovable) { return 'gg-icon-button gg-small remove gg-opacity tool'; } else { return 'hidden'; } default: throw Error('Unsupported type: ' + button); } } createTimeRestrictionTooltip(layer) { const el = this.shadow.getElementById('timeRestriction'); if (!el) return; tippy(el, { trigger: 'click', arrow: true, interactive: true, theme: 'light', placement: 'bottom', appendTo: document.body, content: (_reference) => { return new TimeRestrictionComponent(layer); } }); } createOpacityTooltip() { if (!(this.layer instanceof Layer || (this.layer instanceof GroupLayer && this.layer.isFirstLevelGroup()))) { console.warn('Opacity tooltip can only be created for Layer or 1st level LayerGroup'); return; } const layer = this.layer || LayerGroup; 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 = 'gg-range'; slider.min = '0'; slider.max = '20'; slider.value = (layer.opacity * 20).toString(); slider.oninput = () => { layer.opacity = Number.parseInt(slider.value) / 20; }; return slider; } }); } removeFromParent() { TreeViewElement.removeLayerFromParent(this.layer, this.state); } static removeLayerFromParent(layer, state) { if (layer.parent) { const index = layer.parent.children.indexOf(layer); if (index >= 0) { layer.parent.children.splice(index, 1); } if (layer.parent.children.length === 0) { TreeViewElement.removeLayerFromParent(layer.parent, state); } } else { const index = state.layers.layersList.indexOf(layer); if (index >= 0) { state.layers.layersList.splice(index, 1); } } } }