@geogirafe/lib-geoportal
Version:
GeoGirafe is a flexible application to build online geoportals.
122 lines (121 loc) • 4.97 kB
JavaScript
import { removeUnwantedOlParams } from './utils/olutils.js';
import WfsManager from './wfs/wfsmanager.js';
/**
* A feature-to-grid data converter, to show feature's properties in grid-like system.
*/
export default class FeatureToGridDataById {
context;
options;
constructor(context, options) {
this.context = context;
this.options = {
...{
keepGeomProperty: false,
removeEmptyColumns: true
},
...options
};
}
/**
* Takes an array of OpenLayers features and converts them into a grid data object, where each feature
* is mapped by its ID as the key.
* @returns The grid data objects, by id.
*/
toGridDataById(features) {
const gridDataById = features.reduce((gridDataById, feature) => this.addFeatureToGridDataById(gridDataById, feature), {});
if (this.options.removeEmptyColumns) {
Object.values(gridDataById).forEach((gridData) => FeatureToGridDataById.removeEmptyColumns(gridData));
}
return gridDataById;
}
/**
* @returns a gridDataByID for a single converted OL feature.
* @private
*/
addFeatureToGridDataById(gridDataById, feature) {
const featureType = FeatureToGridDataById.getUserFeatureType(feature);
let notOlProperties = removeUnwantedOlParams(feature, this.options.keepGeomProperty);
if (!Object.keys(notOlProperties).length) {
// Don't keep feature without properties.
return gridDataById;
}
// Apply default prefix to links and images if necessary
notOlProperties = Object.fromEntries(Object.entries(notOlProperties).map(([key, value]) => [key, this.ensureAbsolutePath(value)]));
if (!Object.keys(gridDataById).includes(featureType)) {
gridDataById[featureType] = FeatureToGridDataById.createGridDataWithColumns(notOlProperties);
}
const gridData = gridDataById[featureType];
// Add feature and not OL properties backref
gridData.features.push(feature);
gridData.notOlProperties.push(notOlProperties);
// Add cell content.
const data = gridData.columns.map((column) => notOlProperties[column]);
gridData.data.push(data);
return gridDataById;
}
ensureAbsolutePath(attributeContent) {
if (this.context.configManager.Config.general.defaultUrlPrefix && this.isLikelyHtml(attributeContent)) {
const regex = /(href|src)="\/([^"]*)"/g;
return attributeContent.replaceAll(regex, (_match, attr, path) => {
return `${attr}="${this.context.configManager.Config.general.defaultUrlPrefix}/${path}"`;
});
}
// Not an HTML string
return attributeContent;
}
isLikelyHtml(str) {
return /<[a-z][\s\S]*>/i.test(str);
}
/**
* @returns {GridData} A new empty grid data object with columns from given properties.
* @static
*/
static createGridDataWithColumns(properties) {
return {
columns: Object.keys(properties),
notOlProperties: [],
data: [],
features: []
};
}
/**
* Removes empty columns (columns and data) from a given gridData object.
* It's expected that all features in the gridData have the same properties.
* @static
*/
static removeEmptyColumns(gridData) {
const emptyColumnIndexes = FeatureToGridDataById.findEmptyColumnIndexOf(gridData.data);
gridData.columns = gridData.columns.filter((_column, index) => !emptyColumnIndexes.includes(index));
gridData.data.forEach((_, index) => {
gridData.data[index] = gridData.data[index].filter((_val, index) => !emptyColumnIndexes.includes(index));
});
}
/**
* This method finds the indexes of empty columns in a given 2D array.
* @param data - The 2D array to search for empty columns.
* @returns An array of indexes representing the empty columns.
* @static
*/
static findEmptyColumnIndexOf(data) {
if (!data[0]) {
return [];
}
const emptyColumnIndexes = Array.from({ length: data[0].length }, (_, index) => index);
data.forEach((column) => {
const notEmptyColumnIndexes = [];
emptyColumnIndexes.forEach((emptyIndex) => {
if (column[emptyIndex]) {
notEmptyColumnIndexes.push(emptyIndex);
}
});
notEmptyColumnIndexes.forEach((indexToRemove) => {
const idx = emptyColumnIndexes.findIndex((emptyColumnIndex) => emptyColumnIndex === indexToRemove);
emptyColumnIndexes.splice(idx, 1);
});
});
return emptyColumnIndexes;
}
static getUserFeatureType(feature) {
return WfsManager.extractFeatureTypeFromId(feature);
}
}