UNPKG

@geogirafe/lib-geoportal

Version:

GeoGirafe is a flexible application to build online geoportals.

227 lines (226 loc) 7.97 kB
// SPDX-License-Identifier: Apache-2.0 import GirafeSingleton from '../../base/GirafeSingleton.js'; import DOMPurify from 'dompurify'; import MapPosition from '../state/mapposition.js'; import { get as getProjection, transform } from 'ol/proj.js'; import { isCoordinateInDegrees } from '../utils/olutils.js'; import { BASEMAP_VISIBLE_PARAMETER, SEARCH_VISIBLE_PARAMETER } from './permalinkmanager-constants.js'; import { splitTrimAndConvertToNumber } from '../utils/utils.js'; export default class PermalinkManager extends GirafeSingleton { urlParamKeys = [ 'map_x', 'map_y', 'map_zoom', 'map_crosshair', 'map_tooltip', 'map_marker', 'map_marker_size', 'map_marker_offset', 'search', 'basemap', 'themes', 'groups', 'layers', SEARCH_VISIBLE_PARAMETER, BASEMAP_VISIBLE_PARAMETER ]; urlParamKeysWithPrefix = ['wfs_']; params = {}; initializeSingleton() { this.getPermalinkParamsFromUrl(); this.removePermalinkParamsFromUrl(); this.setStateFromParams(); } get state() { return this.context.stateManager.state; } getPermalinkParamsFromUrl() { this.params = { ...this.context.urlManager.getParams(...this.urlParamKeys), ...this.context.urlManager.getParamsWithPrefix(...this.urlParamKeysWithPrefix) }; } removePermalinkParamsFromUrl() { for (const key in this.params) { this.context.urlManager.removeParams(key); } } setStateFromParams() { this.state.interface.searchComponentVisible = this.getSearchVisible() ?? true; this.state.interface.basemapComponentVisible = this.getBasemapVisible() ?? true; } hasFeatureSelectionQuery() { return this.params['wfs_layer'] !== undefined; } getFeatureSelectionQuery() { if (!this.hasFeatureSelectionQuery()) { return null; } const param_prefix = 'wfs_'; const queryLayer = this.params['wfs_layer']; const queryAttributes = []; for (const key in this.params) { if (key.startsWith(param_prefix) && key !== 'wfs_layer') { queryAttributes.push({ name: key.substring(param_prefix.length), value: DOMPurify.sanitize(this.params[key] ?? '') }); } } if (queryLayer && queryAttributes.length > 0) { return { layer: queryLayer, properties: queryAttributes }; } return null; } hasMapPosition() { // When map position and feature query are present, the feature selection query has priority. // It will move the map to display all selected features, making an additional map position unnecessary. return this.params['map_x'] && this.params['map_y'] && !this.hasFeatureSelectionQuery(); } hasToolTip() { return this.params['map_tooltip'] !== null; } hasMarker() { return this.params['map_marker'] !== null; } hasMarkerSize() { return this.params['map_marker_size'] !== null; } hasMarkerOffset() { return this.params['map_marker_offset'] !== null; } getMapPosition(targetProjection) { if (this.hasMapPosition()) { const position = new MapPosition(); this.addCenter(position, targetProjection); const defaultZoom = this.context.configManager.getDefaultConfigValue('map.startZoom'); position.zoom = Number.parseInt(this.params['map_zoom'] ?? defaultZoom); if (this.params['map_crosshair'] === 'true') { position.crosshair = position.center; } this.addTooltip(position); this.addMarker(position); if (position.isValid) { return position; } } return undefined; } addCenter(position, targetProjection) { let center = [Number.parseFloat(this.params['map_x']), Number.parseFloat(this.params['map_y'])]; // Transform position to the target projection by making an educated guess about the current CRS // of the permalink map position const defaultProjection = this.context.configManager.getDefaultConfigValue('map.srid'); const projectionInUrl = getProjection(isCoordinateInDegrees(position.center) ? 'EPSG:4326' : defaultProjection); if (projectionInUrl.getCode() !== this.state.projection) { center = transform(center, projectionInUrl, targetProjection); } position.center = center; } addTooltip(position) { if (this.hasToolTip()) { const content = DOMPurify.sanitize(this.params['map_tooltip'], this.context.configManager.Config.permalink?.sanitizeConfig); position.tooltip = { content: content, position: position.center }; } } addMarker(position) { if (this.hasMarker()) { const imageUrl = DOMPurify.sanitize(this.params['map_marker']); let size; let offset; if (this.hasMarkerSize()) { size = splitTrimAndConvertToNumber(DOMPurify.sanitize(this.params['map_marker_size'])); } if (this.hasMarkerOffset()) { offset = splitTrimAndConvertToNumber(DOMPurify.sanitize(this.params['map_marker_offset'])); } position.markers.push({ imageUrl: imageUrl, position: position.center, size: size, offset: offset }); } } hasSearch() { return this.params['search'] !== null; } getSearchTerm() { if (this.hasSearch()) { return this.params['search']; } throw new Error('No search param in the Permalink!'); } hasThemes() { return this.params['themes'] !== null; } getThemes() { if (this.hasThemes()) { return this.params['themes'].split(','); } throw new Error('No themes param in the Permalink!'); } hasBasemap() { return this.params['basemap'] !== null; } getBasemap() { if (this.hasBasemap()) { return this.params['basemap']; } throw new Error('No basemap param in the Permalink!'); } hasGroups() { return this.params['groups'] !== null; } getGroups() { if (this.hasGroups()) { return this.params['groups'].split(','); } throw new Error('No groups param in the Permalink!'); } hasLayers() { return this.params['layers'] !== null; } getLayers() { if (this.hasLayers()) { return this.params['layers'].split(','); } throw new Error('No layers param in the Permalink!'); } hasSearchVisible() { return this.params[SEARCH_VISIBLE_PARAMETER] !== null; } getSearchVisible() { if (this.hasSearchVisible()) { try { return Boolean(JSON.parse(this.params[SEARCH_VISIBLE_PARAMETER])); } catch (e) { console.warn(`Could not parse param ${SEARCH_VISIBLE_PARAMETER}: ${e}`); return undefined; } } return undefined; } hasBasemapVisible() { return this.params[BASEMAP_VISIBLE_PARAMETER] !== null; } getBasemapVisible() { if (this.hasBasemapVisible()) { try { return Boolean(JSON.parse(this.params[BASEMAP_VISIBLE_PARAMETER])); } catch (e) { console.warn(`Could not parse param ${BASEMAP_VISIBLE_PARAMETER}: ${e}`); return undefined; } } return undefined; } }