Skip to content

Commit

Permalink
Add filters
Browse files Browse the repository at this point in the history
  • Loading branch information
pietervdvn committed Jan 8, 2022
1 parent 965faca commit 42a6b37
Show file tree
Hide file tree
Showing 13 changed files with 287 additions and 219 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ missing_translations.txt
Svg.ts
data/
Folder.DotSettings.user
index_*.ts
61 changes: 35 additions & 26 deletions Logic/State/MapState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export default class MapState extends UserRelatedState {
* The location as delivered by the GPS
*/
public currentUserLocation: FeatureSourceForLayer & Tiled;

/**
* All previously visited points
*/
Expand Down Expand Up @@ -82,7 +82,7 @@ export default class MapState extends UserRelatedState {
public overlayToggles: { config: TilesourceConfig, isDisplayed: UIEventSource<boolean> }[]


constructor(layoutToUse: LayoutConfig, options?: {attemptLogin: true | boolean}) {
constructor(layoutToUse: LayoutConfig, options?: { attemptLogin: true | boolean }) {
super(layoutToUse, options);

this.availableBackgroundLayers = AvailableBaseLayers.AvailableLayersAt(this.locationControl);
Expand All @@ -97,7 +97,7 @@ export default class MapState extends UserRelatedState {
const self = this
this.backgroundLayer = new UIEventSource<BaseLayer>(defaultLayer)
this.backgroundLayer.addCallbackAndRunD(layer => self.backgroundLayerId.setData(layer.id))

const attr = new Attribution(
this.locationControl,
this.osmConnection.userDetails,
Expand Down Expand Up @@ -176,35 +176,35 @@ export default class MapState extends UserRelatedState {
})
}
}
private initCurrentView(){

private initCurrentView() {
let currentViewLayer: FilteredLayer = this.filteredLayers.data.filter(l => l.layerDef.id === "current_view")[0]

if(currentViewLayer === undefined){
if (currentViewLayer === undefined) {
// This layer is not needed by the theme and thus unloaded
return;
}


let i = 0
const self = this;
const features : UIEventSource<{ feature: any, freshness: Date }[]>= this.currentBounds.map(bounds => {
if(bounds === undefined){
const features: UIEventSource<{ feature: any, freshness: Date }[]> = this.currentBounds.map(bounds => {
if (bounds === undefined) {
return []
}
i++
const feature = {
freshness: new Date(),
feature: {
type: "Feature",
properties:{
id:"current_view-"+i,
"current_view":"yes",
"zoom": ""+self.locationControl.data.zoom
properties: {
id: "current_view-" + i,
"current_view": "yes",
"zoom": "" + self.locationControl.data.zoom
},
geometry:{
type:"Polygon",
coordinates:[[
geometry: {
type: "Polygon",
coordinates: [[
[bounds.maxLon, bounds.maxLat],
[bounds.minLon, bounds.maxLat],
[bounds.minLon, bounds.minLat],
Expand All @@ -216,13 +216,16 @@ export default class MapState extends UserRelatedState {
}
return [feature]
})
this.currentView = new SimpleFeatureSource(currentViewLayer,0,features)

this.currentView = new SimpleFeatureSource(currentViewLayer, 0, features)
}

private initGpsLocation() {
// Initialize the gps layer data. This is emtpy for now, the actual writing happens in the Geolocationhandler
let gpsLayerDef: FilteredLayer = this.filteredLayers.data.filter(l => l.layerDef.id === "gps_location")[0]
if(gpsLayerDef === undefined){
return
}
this.currentUserLocation = new SimpleFeatureSource(gpsLayerDef, Tiles.tile_index(0, 0, 0));
}

Expand All @@ -235,7 +238,7 @@ export default class MapState extends UserRelatedState {
features.ping()
const self = this;
let i = 0
this.currentUserLocation.features.addCallbackAndRunD(([location]) => {
this.currentUserLocation?.features?.addCallbackAndRunD(([location]) => {
if (location === undefined) {
return;
}
Expand Down Expand Up @@ -266,7 +269,9 @@ export default class MapState extends UserRelatedState {


let gpsLayerDef: FilteredLayer = this.filteredLayers.data.filter(l => l.layerDef.id === "gps_location_history")[0]
this.historicalUserLocations = new SimpleFeatureSource(gpsLayerDef, Tiles.tile_index(0, 0, 0), features);
if(gpsLayerDef !== undefined){
this.historicalUserLocations = new SimpleFeatureSource(gpsLayerDef, Tiles.tile_index(0, 0, 0), features);
}


const asLine = features.map(allPoints => {
Expand Down Expand Up @@ -294,7 +299,9 @@ export default class MapState extends UserRelatedState {
}]
})
let gpsLineLayerDef: FilteredLayer = this.filteredLayers.data.filter(l => l.layerDef.id === "gps_track")[0]
this.historicalUserLocationsTrack = new SimpleFeatureSource(gpsLineLayerDef, Tiles.tile_index(0, 0, 0), asLine);
if(gpsLineLayerDef !== undefined){
this.historicalUserLocationsTrack = new SimpleFeatureSource(gpsLineLayerDef, Tiles.tile_index(0, 0, 0), asLine);
}
}

private initHomeLocation() {
Expand Down Expand Up @@ -331,7 +338,9 @@ export default class MapState extends UserRelatedState {
})

const flayer = this.filteredLayers.data.filter(l => l.layerDef.id === "home_location")[0]
this.homeLocation = new SimpleFeatureSource(flayer, Tiles.tile_index(0, 0, 0), feature)
if (flayer !== undefined) {
this.homeLocation = new SimpleFeatureSource(flayer, Tiles.tile_index(0, 0, 0), feature)
}

}

Expand All @@ -349,19 +358,19 @@ export default class MapState extends UserRelatedState {
} else {
isDisplayed = QueryParameters.GetBooleanQueryParameter(
"layer-" + layer.id,
""+layer.shownByDefault,
"" + layer.shownByDefault,
"Wether or not layer " + layer.id + " is shown"
)
}
const flayer : FilteredLayer = {
const flayer: FilteredLayer = {
isDisplayed: isDisplayed,
layerDef: layer,
appliedFilters: new UIEventSource<Map<string, FilterState>>(new Map<string, FilterState>())
appliedFilters: new UIEventSource<Map<string, FilterState>>(new Map<string, FilterState>())
};
layer.filters.forEach(filterConfig => {
const stateSrc = filterConfig.initState()
stateSrc .addCallbackAndRun(state => flayer.appliedFilters.data.set(filterConfig.id, state))

stateSrc.addCallbackAndRun(state => flayer.appliedFilters.data.set(filterConfig.id, state))
flayer.appliedFilters.map(dict => dict.get(filterConfig.id))
.addCallback(state => stateSrc.setData(state))
})
Expand Down
25 changes: 16 additions & 9 deletions Logic/Tags/TagUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,6 @@ export class TagUtils {

/***
* Creates a hash {key --> [values : string | Regex ]}, with all the values present in the tagsfilter
*
* @param tagsFilters
* @constructor
*/
static SplitKeys(tagsFilters: TagsFilter[], allowRegex = false) {
const keyValues = {} // Map string -> string[]
Expand Down Expand Up @@ -189,16 +186,26 @@ export class TagUtils {
if (tag.indexOf(operator) >= 0) {
const split = Utils.SplitFirst(tag, operator);

const val = Number(split[1].trim())
let val = Number(split[1].trim())
if (isNaN(val)) {
throw `Error: not a valid value for a comparison: ${split[1]}, make sure it is a number and nothing more (at ${context})`
val = new Date(split[1].trim()).getTime()
}

const f = (value: string | undefined) => {
const b = Number(value?.replace(/[^\d.]/g, ''))
if (isNaN(b)) {
console.log("Comparing ",value,operator,val)
if(value === undefined){
return false;
}
let b = Number(value?.trim() )
if (isNaN(b)) {
if(value.endsWith(" UTC")) {
value = value.replace(" UTC", "+00")
}
b = new Date(value).getTime()
if(isNaN(b)){
return false
}
}
return comparator(b, val)
}
return new ComparingTag(split[0], f, operator + val)
Expand Down Expand Up @@ -259,8 +266,8 @@ export class TagUtils {
}
if (tag.indexOf("~") >= 0) {
const split = Utils.SplitFirst(tag, "~");
if(split[1] === "") {
throw "Detected a regextag with an empty regex; this is not allowed. Use '"+split[0]+"='instead (at "+context+")"
if (split[1] === "") {
throw "Detected a regextag with an empty regex; this is not allowed. Use '" + split[0] + "='instead (at " + context + ")"
}
if (split[1] === "*") {
split[1] = "..*"
Expand Down
13 changes: 5 additions & 8 deletions Models/ThemeConfig/FilterConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,11 @@ export default class FilterConfig {
`${ctx}.question`
);
let osmTags = undefined;
if (option.osmTags !== undefined) {
if ((option.fields?.length ?? 0) == 0 && option.osmTags !== undefined) {
osmTags = TagUtils.Tag(
option.osmTags,
`${ctx}.osmTags`
);

}
if (question === undefined) {
throw `Invalid filter: no question given at ${ctx}`
Expand All @@ -67,10 +66,6 @@ export default class FilterConfig {
}
})

if (fields.length > 0) {
// erase the tags, they aren't needed
osmTags = undefined
}

return {question: question, osmTags: osmTags, fields, originalTagsSpec: option.osmTags};
});
Expand All @@ -92,6 +87,7 @@ export default class FilterConfig {
}
return "" + state.state
}

const defaultValue = this.options.length > 1 ? "0" : ""
const qp = QueryParameters.GetQueryParameter("filter-" + this.id, defaultValue, "State of filter " + this.id)

Expand Down Expand Up @@ -130,13 +126,14 @@ export default class FilterConfig {
return v
}
for (const key in props) {
v = (<string>v).replace("{"+key+"}", props[key])
v = (<string>v).replace("{" + key + "}", props[key])
}
return v
}
)
const parsed = TagUtils.Tag(rewrittenTags)
return <FilterState>{
currentFilter: TagUtils.Tag(rewrittenTags),
currentFilter: parsed,
state: str
}
} catch (e) {
Expand Down
1 change: 0 additions & 1 deletion Models/ThemeConfig/LayerConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import Title from "../../UI/Base/Title";
import List from "../../UI/Base/List";
import Link from "../../UI/Base/Link";
import {Utils} from "../../Utils";
import {tag} from "@turf/turf";

export default class LayerConfig extends WithContextLoader {

Expand Down
2 changes: 1 addition & 1 deletion UI/BigComponents/FilterView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ export default class FilterView extends VariableUiElement {
}
const props = properties.data
// Replace all the field occurences in the tags...
const tagsSpec = Utils.WalkJson(filter.originalTagsSpec,
const tagsSpec = Utils.WalkJson(filter.originalTagsSpec,
v => {
if (typeof v !== "string") {
return v
Expand Down
2 changes: 1 addition & 1 deletion UI/Input/SimpleDatePicker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export default class SimpleDatePicker extends InputElement<string> {
}

IsValid(t: string): boolean {
return false;
return !isNaN(new Date(t).getTime());
}

protected InnerConstructElement(): HTMLElement {
Expand Down
3 changes: 1 addition & 2 deletions UI/Input/ValidatedTextField.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,7 @@ export default class ValidatedTextField {
"date",
"A date",
(str) => {
const time = Date.parse(str);
return !isNaN(time);
return !isNaN(new Date(str).getTime());
},
(str) => {
const d = new Date(str);
Expand Down
Loading

0 comments on commit 42a6b37

Please sign in to comment.