Add names to feature sources, fix that old, cached geometries get changed when a newer version is loaded
This commit is contained in:
parent
6234d26bac
commit
141d4db028
14 changed files with 60 additions and 43 deletions
|
@ -11,6 +11,8 @@ import {TagsFilter} from "../Tags/TagsFilter";
|
||||||
|
|
||||||
export default class UpdateFromOverpass implements FeatureSource {
|
export default class UpdateFromOverpass implements FeatureSource {
|
||||||
|
|
||||||
|
public readonly name = "UpdateFromOverpass"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The last loaded features of the geojson
|
* The last loaded features of the geojson
|
||||||
*/
|
*/
|
||||||
|
@ -86,7 +88,7 @@ export default class UpdateFromOverpass implements FeatureSource {
|
||||||
if (layer.doNotDownload) {
|
if (layer.doNotDownload) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(layer.source.geojsonSource !== undefined){
|
if (layer.source.geojsonSource !== undefined) {
|
||||||
// Not our responsibility to download this layer!
|
// Not our responsibility to download this layer!
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -129,7 +131,7 @@ export default class UpdateFromOverpass implements FeatureSource {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.timeout.data > 0){
|
if (this.timeout.data > 0) {
|
||||||
console.log("Still in timeout - not updating")
|
console.log("Still in timeout - not updating")
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ export default class UpdateTagsFromOsmAPI {
|
||||||
"_last_edit:timestamp",
|
"_last_edit:timestamp",
|
||||||
"_version_number"],
|
"_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!",
|
"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) => {
|
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;
|
const tags = element.tags;
|
||||||
|
|
|
@ -11,12 +11,10 @@ import LayerConfig from "../../Customizations/JSON/LayerConfig";
|
||||||
export default class FeatureDuplicatorPerLayer implements FeatureSource {
|
export default class FeatureDuplicatorPerLayer implements FeatureSource {
|
||||||
public readonly features: UIEventSource<{ feature: any; freshness: Date }[]>;
|
public readonly features: UIEventSource<{ feature: any; freshness: Date }[]>;
|
||||||
|
|
||||||
|
public readonly name;
|
||||||
public static GetMatchingLayerId(){
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(layers: UIEventSource<{ layerDef: LayerConfig }[]>, upstream: FeatureSource) {
|
constructor(layers: UIEventSource<{ layerDef: LayerConfig }[]>, upstream: FeatureSource) {
|
||||||
|
this.name = "FeatureDuplicator of "+upstream.name;
|
||||||
this.features = upstream.features.map(features => {
|
this.features = upstream.features.map(features => {
|
||||||
const newFeatures: { feature: any, freshness: Date }[] = [];
|
const newFeatures: { feature: any, freshness: Date }[] = [];
|
||||||
if(features === undefined){
|
if(features === undefined){
|
||||||
|
|
|
@ -18,6 +18,8 @@ export default class FeaturePipeline implements FeatureSource {
|
||||||
|
|
||||||
public features: UIEventSource<{ feature: any; freshness: Date }[]>;
|
public features: UIEventSource<{ feature: any; freshness: Date }[]>;
|
||||||
|
|
||||||
|
public readonly name = "FeaturePipeline"
|
||||||
|
|
||||||
constructor(flayers: UIEventSource<{ isDisplayed: UIEventSource<boolean>, layerDef: LayerConfig }[]>,
|
constructor(flayers: UIEventSource<{ isDisplayed: UIEventSource<boolean>, layerDef: LayerConfig }[]>,
|
||||||
updater: FeatureSource,
|
updater: FeatureSource,
|
||||||
layout: UIEventSource<LayoutConfig>,
|
layout: UIEventSource<LayoutConfig>,
|
||||||
|
|
|
@ -2,4 +2,8 @@ import {UIEventSource} from "../UIEventSource";
|
||||||
|
|
||||||
export default interface FeatureSource {
|
export default interface FeatureSource {
|
||||||
features: UIEventSource<{feature: any, freshness: Date}[]>;
|
features: UIEventSource<{feature: any, freshness: Date}[]>;
|
||||||
|
/**
|
||||||
|
* Mainly used for debuging
|
||||||
|
*/
|
||||||
|
name: string;
|
||||||
}
|
}
|
|
@ -3,13 +3,15 @@ import {UIEventSource} from "../UIEventSource";
|
||||||
|
|
||||||
export default class FeatureSourceMerger implements FeatureSource {
|
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[];
|
private readonly _sources: FeatureSource[];
|
||||||
|
|
||||||
constructor(sources: FeatureSource[]) {
|
constructor(sources: FeatureSource[]) {
|
||||||
this._sources = sources;
|
this._sources = sources;
|
||||||
|
this.name = "SourceMerger of (" + sources.map(s => s.name).join(", ") + ")"
|
||||||
const self = this;
|
const self = this;
|
||||||
for (let i = 0; i < sources.length; i++){
|
for (let i = 0; i < sources.length; i++) {
|
||||||
let source = sources[i];
|
let source = sources[i];
|
||||||
source.features.addCallback(() => {
|
source.features.addCallback(() => {
|
||||||
self.Update();
|
self.Update();
|
||||||
|
@ -21,17 +23,17 @@ export default class FeatureSourceMerger implements FeatureSource {
|
||||||
private Update() {
|
private Update() {
|
||||||
let all = {}; // Mapping 'id' -> {feature, freshness}
|
let all = {}; // Mapping 'id' -> {feature, freshness}
|
||||||
for (const source of this._sources) {
|
for (const source of this._sources) {
|
||||||
if(source?.features?.data === undefined){
|
if (source?.features?.data === undefined) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (const f of source.features.data) {
|
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];
|
const oldV = all[id];
|
||||||
if(oldV === undefined){
|
if (oldV === undefined) {
|
||||||
all[id] = f;
|
all[id] = f;
|
||||||
}else{
|
} else {
|
||||||
if(oldV.freshness < f.freshness){
|
if (oldV.freshness < f.freshness) {
|
||||||
all[id]=f;
|
all[id] = f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import Loc from "../../Models/Loc";
|
||||||
|
|
||||||
export default class FilteringFeatureSource implements FeatureSource {
|
export default class FilteringFeatureSource 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 = "FilteringFeatureSource"
|
||||||
constructor(layers: UIEventSource<{
|
constructor(layers: UIEventSource<{
|
||||||
isDisplayed: UIEventSource<boolean>,
|
isDisplayed: UIEventSource<boolean>,
|
||||||
layerDef: LayerConfig
|
layerDef: LayerConfig
|
||||||
|
@ -23,7 +23,6 @@ export default class FilteringFeatureSource implements FeatureSource {
|
||||||
layerDict[layer.layerDef.id] = layer;
|
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;
|
const features: { feature: any, freshness: Date }[] = upstream.features.data;
|
||||||
|
|
||||||
|
|
||||||
|
@ -65,8 +64,6 @@ export default class FilteringFeatureSource implements FeatureSource {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
});
|
});
|
||||||
console.log("Updating the filtering layer, output ", newFeatures.length, "features")
|
|
||||||
|
|
||||||
self.features.setData(newFeatures);
|
self.features.setData(newFeatures);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,12 +14,10 @@ import LayerConfig from "../../Customizations/JSON/LayerConfig";
|
||||||
*/
|
*/
|
||||||
export default class GeoJsonSource implements FeatureSource {
|
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 onFail: ((errorMsg: any, url: string) => void) = undefined;
|
||||||
|
|
||||||
private readonly layerId: string;
|
private readonly layerId: string;
|
||||||
|
|
||||||
private readonly seenids: Set<string> = new Set<string>()
|
private readonly seenids: Set<string> = new Set<string>()
|
||||||
|
|
||||||
constructor(locationControl: UIEventSource<Loc>,
|
constructor(locationControl: UIEventSource<Loc>,
|
||||||
|
@ -27,6 +25,7 @@ export default class GeoJsonSource implements FeatureSource {
|
||||||
onFail?: ((errorMsg: any) => void)) {
|
onFail?: ((errorMsg: any) => void)) {
|
||||||
this.layerId = flayer.layerDef.id;
|
this.layerId = flayer.layerDef.id;
|
||||||
let url = flayer.layerDef.source.geojsonSource;
|
let url = flayer.layerDef.source.geojsonSource;
|
||||||
|
this.name = "GeoJsonSource of " + url;
|
||||||
const zoomLevel = flayer.layerDef.source.geojsonZoomLevel;
|
const zoomLevel = flayer.layerDef.source.geojsonZoomLevel;
|
||||||
|
|
||||||
this.features = new UIEventSource<{ feature: any; freshness: Date }[]>([])
|
this.features = new UIEventSource<{ feature: any; freshness: Date }[]>([])
|
||||||
|
@ -110,8 +109,6 @@ export default class GeoJsonSource implements FeatureSource {
|
||||||
flayersPerSource.get(url).push(flayer)
|
flayersPerSource.get(url).push(flayer)
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("SOURCES", flayersPerSource)
|
|
||||||
|
|
||||||
const sources: GeoJsonSource[] = []
|
const sources: GeoJsonSource[] = []
|
||||||
|
|
||||||
flayersPerSource.forEach((flayers, key) => {
|
flayersPerSource.forEach((flayers, key) => {
|
||||||
|
@ -153,13 +150,11 @@ export default class GeoJsonSource implements FeatureSource {
|
||||||
const self = this;
|
const self = this;
|
||||||
$.getJSON(url, function (json, status) {
|
$.getJSON(url, function (json, status) {
|
||||||
if (status !== "success") {
|
if (status !== "success") {
|
||||||
console.log("Fetching geojson failed failed")
|
|
||||||
self.onFail(status, url);
|
self.onFail(status, url);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (json.elements === [] && json.remarks.indexOf("runtime error") > 0) {
|
if (json.elements === [] && json.remarks.indexOf("runtime error") > 0) {
|
||||||
console.log("Timeout or other runtime error");
|
|
||||||
self.onFail("Runtime error (timeout)", url)
|
self.onFail("Runtime error (timeout)", url)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -179,16 +174,16 @@ export default class GeoJsonSource implements FeatureSource {
|
||||||
}
|
}
|
||||||
self.seenids.add(feature.properties.id)
|
self.seenids.add(feature.properties.id)
|
||||||
|
|
||||||
let freshness : Date = time;
|
let freshness: Date = time;
|
||||||
if(feature["_timestamp"] !== undefined){
|
if (feature["_timestamp"] !== undefined) {
|
||||||
freshness = new Date(feature["_timestamp"])
|
freshness = new Date(feature["_timestamp"])
|
||||||
}
|
}
|
||||||
|
|
||||||
newFeatures.push({feature: feature, freshness: freshness})
|
newFeatures.push({feature: feature, freshness: freshness})
|
||||||
}
|
}
|
||||||
console.log("Downloaded "+newFeatures.length+" new features and "+skipped+" already seen features from "+ url);
|
console.debug("Downloaded " + newFeatures.length + " new features and " + skipped + " already seen features from " + url);
|
||||||
|
|
||||||
if(newFeatures.length == 0){
|
if (newFeatures.length == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,8 @@ export default class LocalStorageSaver implements FeatureSource {
|
||||||
public static readonly storageKey: string = "cached-features";
|
public static readonly storageKey: string = "cached-features";
|
||||||
public readonly features: UIEventSource<{ feature: any; freshness: Date }[]>;
|
public readonly features: UIEventSource<{ feature: any; freshness: Date }[]>;
|
||||||
|
|
||||||
|
public readonly name = "LocalStorageSaver";
|
||||||
|
|
||||||
constructor(source: FeatureSource, layout: UIEventSource<LayoutConfig>) {
|
constructor(source: FeatureSource, layout: UIEventSource<LayoutConfig>) {
|
||||||
this.features = source.features;
|
this.features = source.features;
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import LayoutConfig from "../../Customizations/JSON/LayoutConfig";
|
||||||
|
|
||||||
export default class LocalStorageSource implements FeatureSource {
|
export default class LocalStorageSource implements FeatureSource {
|
||||||
public features: UIEventSource<{ feature: any; freshness: Date }[]>;
|
public features: UIEventSource<{ feature: any; freshness: Date }[]>;
|
||||||
|
public readonly name = "LocalStorageSource";
|
||||||
|
|
||||||
constructor(layout: UIEventSource<LayoutConfig>) {
|
constructor(layout: UIEventSource<LayoutConfig>) {
|
||||||
this.features = new UIEventSource<{ feature: any; freshness: Date }[]>([])
|
this.features = new UIEventSource<{ feature: any; freshness: Date }[]>([])
|
||||||
|
@ -17,8 +18,15 @@ export default class LocalStorageSource implements FeatureSource {
|
||||||
if (fromStorage == null) {
|
if (fromStorage == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const loaded = JSON.parse(fromStorage);
|
const loaded : { feature: any; freshness: Date | string }[]=
|
||||||
this.features.setData(loaded);
|
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")
|
console.log("Loaded ", loaded.length, " features from localstorage as cache")
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("Could not load features from localStorage:", e)
|
console.log("Could not load features from localStorage:", e)
|
||||||
|
|
|
@ -6,10 +6,13 @@ import MetaTagging from "../MetaTagging";
|
||||||
import ExtractRelations from "../Osm/ExtractRelations";
|
import ExtractRelations from "../Osm/ExtractRelations";
|
||||||
|
|
||||||
export default class MetaTaggingFeatureSource implements FeatureSource {
|
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) {
|
constructor(source: FeatureSource) {
|
||||||
const self = this;
|
const self = this;
|
||||||
|
this.name = "MetaTagging of "+source.name
|
||||||
source.features.addCallbackAndRun((featuresFreshness: { feature: any, freshness: Date }[]) => {
|
source.features.addCallbackAndRun((featuresFreshness: { feature: any, freshness: Date }[]) => {
|
||||||
if (featuresFreshness === undefined) {
|
if (featuresFreshness === undefined) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -3,10 +3,11 @@ import {UIEventSource} from "../UIEventSource";
|
||||||
import State from "../../State";
|
import State from "../../State";
|
||||||
|
|
||||||
export default class RegisteringFeatureSource implements FeatureSource {
|
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) {
|
constructor(source: FeatureSource) {
|
||||||
this.features = source.features;
|
this.features = source.features;
|
||||||
|
this.name = "RegisteringSource of "+source.name;
|
||||||
this.features.addCallbackAndRun(features => {
|
this.features.addCallbackAndRun(features => {
|
||||||
for (const feature of features ?? []) {
|
for (const feature of features ?? []) {
|
||||||
if (!State.state.allElements.has(feature.feature.properties.id)) {
|
if (!State.state.allElements.has(feature.feature.properties.id)) {
|
||||||
|
|
|
@ -5,10 +5,13 @@ import FeatureSource from "./FeatureSource";
|
||||||
import {UIEventSource} from "../UIEventSource";
|
import {UIEventSource} from "../UIEventSource";
|
||||||
|
|
||||||
export default class RememberingSource implements FeatureSource {
|
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) {
|
constructor(source: FeatureSource) {
|
||||||
const self = this;
|
const self = this;
|
||||||
|
this.name = "RememberingSource of "+source.name;
|
||||||
const empty = [];
|
const empty = [];
|
||||||
this.features = source.features.map(features => {
|
this.features = source.features.map(features => {
|
||||||
const oldFeatures = self.features?.data ?? empty;
|
const oldFeatures = self.features?.data ?? empty;
|
||||||
|
|
|
@ -51,7 +51,7 @@ export default class WayHandlingApplyingFeatureSource implements FeatureSource {
|
||||||
|
|
||||||
// Create the copy
|
// Create the copy
|
||||||
const centerPoint = GeoOperations.centerpoint(feat);
|
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});
|
newFeatures.push({feature: centerPoint, freshness: f.freshness});
|
||||||
|
|
||||||
if(layer.wayHandling === LayerConfig.WAYHANDLING_CENTER_AND_WAY){
|
if(layer.wayHandling === LayerConfig.WAYHANDLING_CENTER_AND_WAY){
|
||||||
|
|
Loading…
Reference in a new issue