@geogirafe/lib-geoportal
Version:
GeoGirafe is a flexible application to build online geoportals.
81 lines (80 loc) • 3.87 kB
JavaScript
// SPDX-License-Identifier: Apache-2.0
import GirafeSingleton from '../../base/GirafeSingleton.js';
import { SelectionMode } from '../../models/selection.js';
import { applyFeaturesToSelection } from '../utils/utils.js';
/**
* Handles the feature selection, independently from the map (2D or 3D) the selection was triggered from.
* The selection is done in two steps:
* 1. `select()` asks every layer manager to add its own <code>SelectionParam</code> to the state.
* 2. The change of <code>selection.selectionParameters</code> triggers the effective query
* (WMS GetFeatureInfo and WFS GetFeature) and writes the resulting features into the state.
*/
export default class SelectionManager extends GirafeSingleton {
get state() {
return this.context.stateManager.state;
}
initializeSingleton() {
this.context.stateManager.subscribe('selection.selectionParameters', (_, newParams) => {
// The querying is asynchronous and nobody awaits it here,
// so a failing request must not end up in an unhandled rejection.
this.onSelectFeatures(newParams).catch((error) => console.error('Could not select the features.', error));
});
}
/**
* Selects all the features of the queryable layers that are inside the given extent.
* Layers selectable today are WMS, WMTS (with wms layer) and Local files.
*/
select(extent) {
// Reset current selection if SelectionMode is Replace
if (this.state.selection.selectionMode === SelectionMode.Replace) {
this.selectNone();
}
else if (this.state.selection.selectionMode === SelectionMode.Add) {
this.state.selection.selectionParameters = [];
}
// Use batch for changes to prevent multiple selection of objects
this.context.stateManager.batchChanges(() => {
this.context.wmsManager.selectFeatures(extent);
this.context.wmtsManager.selectFeatures(extent);
this.context.localFileManager.selectFeatures(extent);
});
}
selectNone() {
this.state.selection.selectedFeatures = [];
this.state.selection.selectionParameters = [];
this.state.selection.highlightedFeatures = [];
}
async onSelectFeatures(selectionParams) {
if (selectionParams.length === 0) {
return;
}
this.state.loading = true;
try {
// WMS GetFeatureInfo
const wmsPromises = selectionParams.map((param) => {
const wmsGetFeatureInfoSelectionParam = param.clone((l) => l.queryable && l.wmsQueryableOnly);
const client = this.context.wmsManager.getClient(wmsGetFeatureInfoSelectionParam.ogcServer);
return client.getFeatureInfo(wmsGetFeatureInfoSelectionParam);
});
// WFS GetFeature
const wfsPromises = selectionParams.map((param) => {
const wfsGetFeatureInfoSelectionParam = param.clone((l) => l.wfsQueryable);
const client = this.context.wfsManager.getClient(wfsGetFeatureInfoSelectionParam.ogcServer);
const features = client.getFeature(wfsGetFeatureInfoSelectionParam);
return features;
});
const wmsGmlFeatures = (await Promise.all(wmsPromises)).flat();
const wfsGmlFeatures = (await Promise.all(wfsPromises)).flat();
const gmlFeatures = [...wmsGmlFeatures, ...wfsGmlFeatures];
if (gmlFeatures.length === 0 && this.state.selection.selectedFeatures.length === 0) {
this.state.interface.selectionComponentVisible = false;
}
else {
applyFeaturesToSelection(gmlFeatures, this.state);
}
}
finally {
this.state.loading = false;
}
}
}