UNPKG

@geogirafe/lib-geoportal

Version:

GeoGirafe is a flexible application to build online geoportals.

209 lines (208 loc) 8.6 kB
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; // SPDX-License-Identifier: Apache-2.0 import LayerWms from '../../models/layers/layerwms.js'; import { filterOperators, logicalFilterOperators } from '../../models/filter.js'; import { v4 as uuidv4 } from 'uuid'; import WfsFilterCondition from '../../tools/wfs/wfsfiltercondition.js'; import WfsFilter from '../../tools/wfs/wfsfilter.js'; import { typeGroupFromAttributeType as xmlTypeGroupByAttributeType } from '../../models/xmlTypes.js'; import { UsedInTemplateOnly } from '../../decorators.js'; import FilterConditionElement from './filterconditionelement.js'; /** * Represents the state of a filter element in the AdvancedFilterComponent. This class provides functionality * to store and manage filter conditions, operators, and attributes. */ class LayerFilterElement { id; layer; attributes; conditions; inverted = false; attributeChoices = new Map(); attributeTitles = new Map(); context; columnAliasHelper; position; constructor(context, columnAliasHelper, position) { this.context = context; this.columnAliasHelper = columnAliasHelper; this.id = uuidv4(); this.position = position; this.attributes = []; this.conditions = []; } /** * Sets the filter element with all conditions from a given layer with an existing filter. */ async setFromLayer(layer) { await this.setLayer(layer); if (!layer.filter) { return; } this.conditions = []; this.setConditionsFromLayerRecursively(layer.filter); } setConditionsFromLayerRecursively(filterObject) { if (filterObject.logicalOperator === 'not') { this.inverted = true; } filterObject.conditions.forEach((nestedFilterCondition) => { if (nestedFilterCondition instanceof WfsFilter) { this.setConditionsFromLayerRecursively(nestedFilterCondition); } else { this.addCondition(); const cond = this.conditions.at(-1); this.setAttributeInCondition(cond, nestedFilterCondition.property); cond.setOperator(nestedFilterCondition.operator); cond.value = nestedFilterCondition.value; cond.value2 = nestedFilterCondition.value2; cond.logicalOperator = filterObject.logicalOperator; cond.filterConditionInstance = nestedFilterCondition; cond.applied = true; } }); } get title() { const title = `${this.i18n('Filter')} ${this.position + 1}`; if (this.layer) { return `${title} (${this.i18n(this.layer.name)})`; } else { return title; } } get availableLogicalOperators() { // Filter out 'not' logical operator, as it is only available as a dedicated button to negate the whole chained expression return [...logicalFilterOperators].filter((op) => op.operator !== 'not'); } async setLayer(layer) { this.attributes = []; this.attributeChoices = new Map(); this.attributeTitles = new Map(); this.inverted = false; this.removeConditions(); if (layer) { this.layer = layer; this.attributes = await this.context.wfsManager.commonAttributesByLayer(layer, true); const queryLayer = layer.queryLayers?.split(',')[0] ?? ''; for (const attribute of this.attributes) { this.attributeTitles.set(attribute.name, this.columnAliasHelper.getColumnAlias(queryLayer, attribute.name)); } this.attributeChoices = await this.context.wfsManager.getAttributeChoices(layer); } // Add an empty condition this.addCondition(); } removeConditions() { for (const condition of this.conditions) { this.removeCondition(condition); } } addCondition() { this.conditions.push(new FilterConditionElement(this.context)); } removeCondition(condition) { const idx = this.conditions.indexOf(condition); if (idx !== -1) { condition.remove(); this.conditions.splice(idx, 1); } if (this.conditions.length > 0) { // Remove the logical operator from the first condition in the list this.conditions[0].logicalOperator = undefined; } } hasAppliedConditions() { return this.conditions.some((condition) => condition.applied); } hasNoneAppliedConditions() { return this.conditions.some((condition) => !condition.applied); } removeNonAppliedConditions() { for (const condition of this.conditions) { if (!condition.applied) { this.removeCondition(condition); } } } setAttributeInCondition(condition, attributeName) { const attribute = this.attributes.find((attr) => attr.name === attributeName); if (!attribute) { return; } const attributeDisplayName = this.getAttributeDisplayName(attribute); const attributeInputType = this.getInputTypeByAttributeType(attribute); let availableOperators = this.getOperatorsByAttributeType(attribute?.type); let choices = []; if (this.isEnumeratedAttribute(attributeName)) { availableOperators = filterOperators.filter((op) => ['in', 'nin', 'nul', 'nnul'].includes(op.operator)); choices = this.attributeChoices.get(attributeName) ?? []; } condition.setAttribute(attribute, attributeDisplayName, attributeInputType, availableOperators, choices); } isEnumeratedAttribute(attributeName) { return this.attributeChoices.has(attributeName) && this.attributeChoices.get(attributeName)?.length; } getOperatorsByAttributeType(attributeType) { if (!attributeType) { return []; } return WfsFilterCondition.supportedOperatorsByAttributeType(attributeType); } applyFilter() { let nestedFilter = undefined; if (!this.layer) { return nestedFilter; } for (const condition of this.conditions) { if (!condition.applied) { continue; } if (nestedFilter) { condition.logicalOperator = condition.logicalOperator ?? this.availableLogicalOperators[0].operator; nestedFilter = new WfsFilter([nestedFilter, condition.filterConditionInstance], condition.logicalOperator); } else { nestedFilter = new WfsFilter([condition.filterConditionInstance]); } } if (nestedFilter && this.inverted) { nestedFilter = new WfsFilter([nestedFilter], 'not'); } return nestedFilter; } toggleInverted() { this.inverted = !this.inverted; } i18n(key) { return this.context.i18nManager.getTranslation(key); } isLogicalOperatorSelectorVisible(condition) { // Show a logical operator for all conditions but the first return this.conditions.indexOf(condition) > 0; // NOSONAR: This check does exactly what it should do } getInputTypeByAttributeType(attr) { if (!attr?.type) { return 'string'; } if (this.layer instanceof LayerWms) { return xmlTypeGroupByAttributeType(attr.type) || 'string'; } return 'string'; } getAttributeDisplayName(attribute) { const attributeName = this.attributeTitles.get(attribute.name) ?? attribute.name; const attrType = this.isEnumeratedAttribute(attribute.name) ? 'list' : attribute.type; return `${this.i18n(attributeName)} [${this.i18n('datatype-' + attrType)}]`; } } __decorate([ UsedInTemplateOnly() ], LayerFilterElement.prototype, "isLogicalOperatorSelectorVisible", null); export default LayerFilterElement;