Add names to feature sources, fix that old, cached geometries get changed when a newer version is loaded

This commit is contained in:
pietervdvn 2021-04-23 12:55:38 +02:00
parent 6234d26bac
commit 141d4db028
14 changed files with 60 additions and 43 deletions

View file

@ -11,6 +11,8 @@ import {TagsFilter} from "../Tags/TagsFilter";
export default class UpdateFromOverpass implements FeatureSource {
public readonly name = "UpdateFromOverpass"
/**
* The last loaded features of the geojson
*/
@ -86,7 +88,7 @@ export default class UpdateFromOverpass implements FeatureSource {
if (layer.doNotDownload) {
continue;
}
if(layer.source.geojsonSource !== undefined){
if (layer.source.geojsonSource !== undefined) {
// Not our responsibility to download this layer!
continue;
}
@ -128,8 +130,8 @@ export default class UpdateFromOverpass implements FeatureSource {
console.log("Still running a query, not updating");
return;
}
if(this.timeout.data > 0){
if (this.timeout.data > 0) {
console.log("Still in timeout - not updating")
return;
}

View file

@ -13,7 +13,7 @@ export default class UpdateTagsFromOsmAPI {
"_last_edit:timestamp",
"_version_number"],
"Information about the last edit of this object. \n\nIMPORTANT: this data is _only_ loaded when the popup is added. This means it should _not_ be used to render icons!",
(feature: any, index: number, freshness: Date) => {/*Do nothing - this is only added for documentation reasons*/
() => {/*Do nothing - this is only added for documentation reasons*/
}
)
@ -28,7 +28,7 @@ export default class UpdateTagsFromOsmAPI {
}
OsmObject.DownloadObject(id, (element: OsmObject, meta: OsmObjectMeta) => {
console.log("Updating element from OSM-API: ", element)
console.debug("Updating tags from the OSM-API: ", element)
const tags = element.tags;

View file

@ -11,12 +11,10 @@ import LayerConfig from "../../Customizations/JSON/LayerConfig";
export default class FeatureDuplicatorPerLayer implements FeatureSource {
public readonly features: UIEventSource<{ feature: any; freshness: Date }[]>;
public static GetMatchingLayerId(){
}
public readonly name;
constructor(layers: UIEventSource<{ layerDef: LayerConfig }[]>, upstream: FeatureSource) {
this.name = "FeatureDuplicator of "+upstream.name;
this.features = upstream.features.map(features => {
const newFeatures: { feature: any, freshness: Date }[] = [];
if(features === undefined){

View file

@ -18,6 +18,8 @@ export default class FeaturePipeline implements FeatureSource {
public features: UIEventSource<{ feature: any; freshness: Date }[]>;
public readonly name = "FeaturePipeline"
constructor(flayers: UIEventSource<{ isDisplayed: UIEventSource<boolean>, layerDef: LayerConfig }[]>,
updater: FeatureSource,
layout: UIEventSource<LayoutConfig>,

View file

@ -2,4 +2,8 @@ import {UIEventSource} from "../UIEventSource";
export default interface FeatureSource {
features: UIEventSource<{feature: any, freshness: Date}[]>;
/**
* Mainly used for debuging
*/
name: string;
}

View file

@ -3,13 +3,15 @@ import {UIEventSource} from "../UIEventSource";
export default class FeatureSourceMerger implements FeatureSource {
public features: UIEventSource<{ feature: any; freshness: Date }[]> = new UIEventSource<{feature: any; freshness: Date}[]>([]);
public features: UIEventSource<{ feature: any; freshness: Date }[]> = new UIEventSource<{ feature: any; freshness: Date }[]>([]);
public readonly name;
private readonly _sources: FeatureSource[];
constructor(sources: FeatureSource[]) {
this._sources = sources;
this.name = "SourceMerger of (" + sources.map(s => s.name).join(", ") + ")"
const self = this;
for (let i = 0; i < sources.length; i++){
for (let i = 0; i < sources.length; i++) {
let source = sources[i];
source.features.addCallback(() => {
self.Update();
@ -21,17 +23,17 @@ export default class FeatureSourceMerger implements FeatureSource {
private Update() {
let all = {}; // Mapping 'id' -> {feature, freshness}
for (const source of this._sources) {
if(source?.features?.data === undefined){
if (source?.features?.data === undefined) {
continue;
}
for (const f of source.features.data) {
const id = f.feature.properties.id+f.feature.geometry.type+f.feature._matching_layer_id;
const id = f.feature.properties.id;
const oldV = all[id];
if(oldV === undefined){
if (oldV === undefined) {
all[id] = f;
}else{
if(oldV.freshness < f.freshness){
all[id]=f;
} else {
if (oldV.freshness < f.freshness) {
all[id] = f;
}
}
}

View file

@ -5,7 +5,7 @@ import Loc from "../../Models/Loc";
export default class FilteringFeatureSource implements FeatureSource {
public features: UIEventSource<{ feature: any; freshness: Date }[]> = new UIEventSource<{ feature: any; freshness: Date }[]>([]);
public readonly name = "FilteringFeatureSource"
constructor(layers: UIEventSource<{
isDisplayed: UIEventSource<boolean>,
layerDef: LayerConfig
@ -23,7 +23,6 @@ export default class FilteringFeatureSource implements FeatureSource {
layerDict[layer.layerDef.id] = layer;
}
console.log("Updating the filtering layer, input ", upstream.features.data.length, "features")
const features: { feature: any, freshness: Date }[] = upstream.features.data;
@ -65,8 +64,6 @@ export default class FilteringFeatureSource implements FeatureSource {
return false;
});
console.log("Updating the filtering layer, output ", newFeatures.length, "features")
self.features.setData(newFeatures);
}

View file

@ -14,12 +14,10 @@ import LayerConfig from "../../Customizations/JSON/LayerConfig";
*/
export default class GeoJsonSource implements FeatureSource {
features: UIEventSource<{ feature: any; freshness: Date }[]>;
public readonly features: UIEventSource<{ feature: any; freshness: Date }[]>;
public readonly name;
private readonly onFail: ((errorMsg: any, url: string) => void) = undefined;
private readonly layerId: string;
private readonly seenids: Set<string> = new Set<string>()
constructor(locationControl: UIEventSource<Loc>,
@ -27,6 +25,7 @@ export default class GeoJsonSource implements FeatureSource {
onFail?: ((errorMsg: any) => void)) {
this.layerId = flayer.layerDef.id;
let url = flayer.layerDef.source.geojsonSource;
this.name = "GeoJsonSource of " + url;
const zoomLevel = flayer.layerDef.source.geojsonZoomLevel;
this.features = new UIEventSource<{ feature: any; freshness: Date }[]>([])
@ -110,8 +109,6 @@ export default class GeoJsonSource implements FeatureSource {
flayersPerSource.get(url).push(flayer)
}
console.log("SOURCES", flayersPerSource)
const sources: GeoJsonSource[] = []
flayersPerSource.forEach((flayers, key) => {
@ -153,13 +150,11 @@ export default class GeoJsonSource implements FeatureSource {
const self = this;
$.getJSON(url, function (json, status) {
if (status !== "success") {
console.log("Fetching geojson failed failed")
self.onFail(status, url);
return;
}
if (json.elements === [] && json.remarks.indexOf("runtime error") > 0) {
console.log("Timeout or other runtime error");
self.onFail("Runtime error (timeout)", url)
return;
}
@ -179,19 +174,19 @@ export default class GeoJsonSource implements FeatureSource {
}
self.seenids.add(feature.properties.id)
let freshness : Date = time;
if(feature["_timestamp"] !== undefined){
let freshness: Date = time;
if (feature["_timestamp"] !== undefined) {
freshness = new Date(feature["_timestamp"])
}
newFeatures.push({feature: feature, freshness: freshness})
}
console.log("Downloaded "+newFeatures.length+" new features and "+skipped+" already seen features from "+ url);
if(newFeatures.length == 0){
console.debug("Downloaded " + newFeatures.length + " new features and " + skipped + " already seen features from " + url);
if (newFeatures.length == 0) {
return;
}
eventSource.setData(eventSource.data.concat(newFeatures))
}).fail(msg => self.onFail(msg, url))

View file

@ -11,6 +11,8 @@ export default class LocalStorageSaver implements FeatureSource {
public static readonly storageKey: string = "cached-features";
public readonly features: UIEventSource<{ feature: any; freshness: Date }[]>;
public readonly name = "LocalStorageSaver";
constructor(source: FeatureSource, layout: UIEventSource<LayoutConfig>) {
this.features = source.features;

View file

@ -5,6 +5,7 @@ import LayoutConfig from "../../Customizations/JSON/LayoutConfig";
export default class LocalStorageSource implements FeatureSource {
public features: UIEventSource<{ feature: any; freshness: Date }[]>;
public readonly name = "LocalStorageSource";
constructor(layout: UIEventSource<LayoutConfig>) {
this.features = new UIEventSource<{ feature: any; freshness: Date }[]>([])
@ -17,8 +18,15 @@ export default class LocalStorageSource implements FeatureSource {
if (fromStorage == null) {
return;
}
const loaded = JSON.parse(fromStorage);
this.features.setData(loaded);
const loaded : { feature: any; freshness: Date | string }[]=
JSON.parse(fromStorage);
const parsed : { feature: any; freshness: Date }[]= loaded.map(ff => ({
feature: ff.feature,
freshness : typeof ff.freshness == "string" ? new Date(ff.freshness) : ff.freshness
}))
this.features.setData(parsed);
console.log("Loaded ", loaded.length, " features from localstorage as cache")
} catch (e) {
console.log("Could not load features from localStorage:", e)

View file

@ -6,10 +6,13 @@ import MetaTagging from "../MetaTagging";
import ExtractRelations from "../Osm/ExtractRelations";
export default class MetaTaggingFeatureSource implements FeatureSource {
features: UIEventSource<{ feature: any; freshness: Date }[]> = new UIEventSource<{feature: any; freshness: Date}[]>(undefined);
public readonly features: UIEventSource<{ feature: any; freshness: Date }[]> = new UIEventSource<{feature: any; freshness: Date}[]>(undefined);
public readonly name;
constructor(source: FeatureSource) {
const self = this;
this.name = "MetaTagging of "+source.name
source.features.addCallbackAndRun((featuresFreshness: { feature: any, freshness: Date }[]) => {
if (featuresFreshness === undefined) {
return;

View file

@ -3,10 +3,11 @@ import {UIEventSource} from "../UIEventSource";
import State from "../../State";
export default class RegisteringFeatureSource implements FeatureSource {
features: UIEventSource<{ feature: any; freshness: Date }[]>;
public readonly features: UIEventSource<{ feature: any; freshness: Date }[]>;
public readonly name;
constructor(source: FeatureSource) {
this.features = source.features;
this.name = "RegisteringSource of "+source.name;
this.features.addCallbackAndRun(features => {
for (const feature of features ?? []) {
if (!State.state.allElements.has(feature.feature.properties.id)) {

View file

@ -5,10 +5,13 @@ import FeatureSource from "./FeatureSource";
import {UIEventSource} from "../UIEventSource";
export default class RememberingSource implements FeatureSource {
features: UIEventSource<{ feature: any, freshness: Date }[]>;
public readonly features: UIEventSource<{ feature: any, freshness: Date }[]>;
public readonly name;
constructor(source: FeatureSource) {
const self = this;
this.name = "RememberingSource of "+source.name;
const empty = [];
this.features = source.features.map(features => {
const oldFeatures = self.features?.data ?? empty;

View file

@ -51,7 +51,7 @@ export default class WayHandlingApplyingFeatureSource implements FeatureSource {
// Create the copy
const centerPoint = GeoOperations.centerpoint(feat);
centerPoint._matching_layer_id = feat._matching_layer_id;
centerPoint["_matching_layer_id"] = feat._matching_layer_id;
newFeatures.push({feature: centerPoint, freshness: f.freshness});
if(layer.wayHandling === LayerConfig.WAYHANDLING_CENTER_AND_WAY){