import { FilterUi } from './ui/FilterUi.js';
import { TimeFilter } from './ui/TimeFilter.js';
import { CheckboxFilter } from './ui/CheckboxFilter.js'
import { KeyValueFilter } from './ui/KeyValueFilter.js'
import { BoundingBox } from './ui/BoundingBoxFilter.js';
import { DropdownFilter } from './ui/DropdownFilter.js'
import { RangeFilter } from './ui/RangeFilter.js'
import { EventObject } from "../../events/EventObject.js";
import { Window } from '../../ui/Window.js';
import { TextFilter } from './ui/TextFilter.js';
import { MagnituteFilter } from './ui/MagnituteFilter.js';
import "./Filters.css";
export { Filters };
/**
* A class that inititates the DateTime and Attribute Filters based on the config
* Also contains methods for the active filters
*
* @author sjaswal <shahzeib.jaswal@awi.de>
* @author rhess <robin.hess@awi.de>
*
* @memberof vef.map.filters
*/
class Filters extends EventObject {
filterClasses = {
"time": TimeFilter,
"checkbox": CheckboxFilter,
"dropdown": DropdownFilter,
"range": RangeFilter,
"keyvalue": KeyValueFilter,
"boundingbox": BoundingBox,
"text": TextFilter,
"mags": MagnituteFilter
};
constructor(cache, map) {
super({
"change": [],
"add": [],
"remove": []
});
this.cache = cache;
this.map = map;
this.filters = {};
this.cache.on("layermanager_filterlayer_change", () => this.fire("change", this))
}
/**
* Returns the Active Filters i.e. DateTime and Attribute Filters
*/
getActiveFilters() {
let activeFilters = [];
const addFilter = filter => {
const required = !!(filter?.options_?.required);
let filters = filter.getActiveFilter();
if (!Array.isArray(filters)) filters = [filters];
for (let i = 0; i < filters.length; ++i) {
if (filters[i].hasOwnProperty('values')) {
filters[i].required = required;
activeFilters.push(filters[i]);
}
}
}
for (let key in this.filters) {
if (this.filters[key] instanceof FilterUi) {
if (!this.filters[key].isActive()) continue;
addFilter(this.filters[key]);
}
}
addFilter(this.cache);
return activeFilters;
}
setMap(map) {
this.map = map;
for (let key in this.filters) {
this.filters[key].setMap(map);
}
}
/**
* Add a filter based on the json config
* @param {object} config filter config
*/
addFilter(config) {
const type = config.type.toLowerCase();
const filterClass = this.filterClasses[type];
if (filterClass) {
const id = config.id || (type + "_" + new Date().getTime().toString() + Math.floor(Math.random() * 1000000).toString());
const filter = new filterClass(null, config, this.cache, this.map);
this.filters[id] = filter;
filter.on("change", () => this.fire("change", this));
filter.on("remove", () => this.removeFilter(id));
filter.on("copy", () => {
const options = filter.getOptions();
options.type = type;
if (options.id) delete options.id;
this.addFilter(options);
});
this.fire("add", { id: id, filter: filter });
return filter;
}
}
/**
* @param {object[]} configs array of configurations
*/
addFilters(configs) {
for (let i = 0; i < configs.length; ++i) {
this.addFilter(configs[i]);
}
}
/**
* @param {string} id
*/
removeFilter(id) {
if (id in this.filters) {
this.filters[id].dispose();
delete this.filters[id];
this.fire("remove", { id: id, filter: this.filters[id] });
}
}
/**
* Helper function to create an add button to create new filters
*/
createAddButton() {
let selectionWindow = null;
const div = document.createElement("div");
div.classList.add("btn-add-filter");
div.innerHTML = '<a href="#"><i class="fas fa-plus"></i> Add Filter</a>';
div.querySelector("a").addEventListener("click", e => {
e.preventDefault();
if (!selectionWindow) selectionWindow = this.createSelectionWindow_();
selectionWindow.setOptions({ pointerEvent: e, open: true });
});
return div;
}
/**
* Helper function to create a simple filter selection window with a dropdown
* @private
*/
createSelectionWindow_() {
const content = `
<div class="filter-selection-dropdown-wrapper">
<select class="filter-selection-dropdown">
<option value="time">Time Filter</option>
<option value="range">Range Filter</option>
<option value="keyvalue">Key Value Filter</option>
<option value="checkbox">Checkbox Filter</option>
<option value="dropdown">Dropdown Filter</option>
<option value="boundingbox">Bounding Box Filter</option>
</select>
<button class="btn-add"><i class="fas fa-plus"></i></button>
</div>
`;
const options = {
width: "350px",
responsive: true,
content: content,
draggable: true,
title: "Add Filter",
open: false
};
const selectionWindow = new Window(null, options);
selectionWindow.query(".btn-add").addEventListener("click", e => {
const value = selectionWindow.query(".filter-selection-dropdown").value;
const filter = this.addFilter({ type: value });
selectionWindow.close();
if (filter) {
const style = selectionWindow.getElement().style;
filter.openSettings({ top: style.top, left: style.left });
}
});
return selectionWindow;
}
}