@geogirafe/lib-geoportal
Version:
GeoGirafe is a flexible application to build online geoportals.
227 lines (226 loc) • 7.97 kB
JavaScript
// 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;
}
}