Merge branch 'develop' into feature/maproulette

This commit is contained in:
Robin van der Linde 2022-07-10 19:43:48 +00:00 committed by GitHub
commit 764f9956a9
113 changed files with 8008 additions and 1160 deletions

View file

@ -3,6 +3,7 @@ import {ImmutableStore, Store, UIEventSource} from "../../UIEventSource";
import {stat} from "fs";
import FilteredLayer from "../../../Models/FilteredLayer";
import {BBox} from "../../BBox";
import {Feature} from "@turf/turf";
/**
* A simple, read only feature store.
@ -11,7 +12,7 @@ export default class StaticFeatureSource implements FeatureSource {
public readonly features: Store<{ feature: any; freshness: Date }[]>;
public readonly name: string
constructor(features: Store<{ feature: any, freshness: Date }[]>, name = "StaticFeatureSource") {
constructor(features: Store<{ feature: Feature, freshness: Date }[]>, name = "StaticFeatureSource") {
if (features === undefined) {
throw "Static feature source received undefined as source"
}
@ -19,17 +20,23 @@ export default class StaticFeatureSource implements FeatureSource {
this.features = features;
}
public static fromGeojsonAndDate(features: { feature: any, freshness: Date }[], name = "StaticFeatureSourceFromGeojsonAndDate"): StaticFeatureSource {
public static fromGeojsonAndDate(features: { feature: Feature, freshness: Date }[], name = "StaticFeatureSourceFromGeojsonAndDate"): StaticFeatureSource {
return new StaticFeatureSource(new ImmutableStore(features), name);
}
public static fromGeojson(geojson: any[], name = "StaticFeatureSourceFromGeojson"): StaticFeatureSource {
public static fromGeojson(geojson: Feature[], name = "StaticFeatureSourceFromGeojson"): StaticFeatureSource {
const now = new Date();
return StaticFeatureSource.fromGeojsonAndDate(geojson.map(feature => ({feature, freshness: now})), name);
}
static fromDateless(featureSource: Store<{ feature: any }[]>, name = "StaticFeatureSourceFromDateless") {
public static fromGeojsonStore(geojson: Store<Feature[]>, name = "StaticFeatureSourceFromGeojson"): StaticFeatureSource {
const now = new Date();
const mapped : Store<{feature: Feature, freshness: Date}[]> = geojson.map(features => features.map(feature => ({feature, freshness: now})))
return new StaticFeatureSource(mapped, name);
}
static fromDateless(featureSource: Store<{ feature: Feature }[]>, name = "StaticFeatureSourceFromDateless") {
const now = new Date();
return new StaticFeatureSource(featureSource.map(features => features.map(feature => ({
feature: feature.feature,

View file

@ -11,6 +11,7 @@ import LayoutConfig from "../../../Models/ThemeConfig/LayoutConfig";
import {Or} from "../../Tags/Or";
import {TagsFilter} from "../../Tags/TagsFilter";
import {OsmObject} from "../../Osm/OsmObject";
import {FeatureCollection} from "@turf/turf";
/**
* If a tile is needed (requested via the UIEventSource in the constructor), will download the appropriate tile and pass it via 'handleTile'
@ -136,7 +137,7 @@ export default class OsmFeatureSource {
console.log("Got tile", z, x, y, "from the osm api")
this.rawDataHandlers.forEach(handler => handler(osmJson, Tiles.tile_index(z, x, y)))
const geojson = OsmToGeoJson.default(osmJson,
const geojson = <FeatureCollection<any , {id: string}>> OsmToGeoJson.default(osmJson,
// @ts-ignore
{
flatProperties: true

View file

@ -11,7 +11,7 @@ import ChangeTagAction from "./ChangeTagAction";
import {And} from "../../Tags/And";
import {Utils} from "../../../Utils";
import {OsmConnection} from "../OsmConnection";
import {GeoJSONObject} from "@turf/turf";
import {Feature} from "@turf/turf";
import FeaturePipeline from "../../FeatureSource/FeaturePipeline";
export default class ReplaceGeometryAction extends OsmChangeAction {
@ -83,7 +83,7 @@ export default class ReplaceGeometryAction extends OsmChangeAction {
// noinspection JSUnusedGlobalSymbols
public async getPreview(): Promise<FeatureSource> {
const {closestIds, allNodesById, detachedNodes, reprojectedNodes} = await this.GetClosestIds();
const preview: GeoJSONObject[] = closestIds.map((newId, i) => {
const preview: Feature[] = closestIds.map((newId, i) => {
if (this.identicalTo[i] !== undefined) {
return undefined
}
@ -122,7 +122,7 @@ export default class ReplaceGeometryAction extends OsmChangeAction {
reprojectedNodes.forEach(({newLat, newLon, nodeId}) => {
const origNode = allNodesById.get(nodeId);
const feature = {
const feature : Feature = {
type: "Feature",
properties: {
"move": "yes",
@ -142,7 +142,7 @@ export default class ReplaceGeometryAction extends OsmChangeAction {
detachedNodes.forEach(({reason}, id) => {
const origNode = allNodesById.get(id);
const feature = {
const feature : Feature = {
type: "Feature",
properties: {
"detach": "yes",

View file

@ -35,7 +35,7 @@ export class Overpass {
this._relationTracker = relationTracker
}
public async queryGeoJson(bounds: BBox, ): Promise<[FeatureCollection, Date]> {
public async queryGeoJson(bounds: BBox): Promise<[FeatureCollection, Date]> {
const bbox = "[bbox:" + bounds.getSouth() + "," + bounds.getWest() + "," + bounds.getNorth() + "," + bounds.getEast() + "]";
const query = this.buildScript(bbox)
return this.ExecuteQuery(query);

View file

@ -314,9 +314,10 @@ export default class SimpleMetaTaggers {
lat: lat,
lon: lon,
address: {
country_code: tags._country.toLowerCase()
country_code: tags._country.toLowerCase(),
state: undefined
}
}, {tag_key: "opening_hours"});
}, <any> {tag_key: "opening_hours"});
// Recalculate!
return oh.getState() ? "yes" : "no";

View file

@ -116,12 +116,21 @@ export class TagUtils {
* Given multiple tagsfilters which can be used as answer, will take the tags with the same keys together as set.
* E.g:
*
* FlattenMultiAnswer([and: [ "x=a", "y=0;1"], and: ["x=b", "y=2"], and: ["x=", "y=3"]])
* will result in
* ["x=a;b", "y=0;1;2;3"]
*
* @param tagsFilters
* @constructor
* const tag = TagUtils.Tag({"and": [
* {
* and: [ "x=a", "y=0;1"],
* },
* {
* and: ["x=", "y=3"]
* },
* {
* and: ["x=b", "y=2"]
* }
* ]})
* TagUtils.FlattenMultiAnswer([tag]) // => TagUtils.Tag({and:["x=a;b", "y=0;1;2;3"] })
*
* TagUtils.FlattenMultiAnswer(([new Tag("x","y"), new Tag("a","b")])) // => new And([new Tag("x","y"), new Tag("a","b")])
* TagUtils.FlattenMultiAnswer(([new Tag("x","")])) // => new And([new Tag("x","")])
*/
static FlattenMultiAnswer(tagsFilters: TagsFilter[]): And {
if (tagsFilters === undefined) {
@ -131,7 +140,9 @@ export class TagUtils {
let keyValues = TagUtils.SplitKeys(tagsFilters);
const and: TagsFilter[] = []
for (const key in keyValues) {
and.push(new Tag(key, Utils.Dedup(keyValues[key]).join(";")));
const values = Utils.Dedup(keyValues[key]).filter(v => v !== "")
values.sort()
and.push(new Tag(key, values.join(";")));
}
return new And(and);
}

View file

@ -7,8 +7,12 @@ import {Utils} from "../../Utils";
*/
export class IdbLocalStorage {
private static readonly _sourceCache: Record<string, UIEventSource<any>> = {}
public static Get<T>(key: string, options?: { defaultValue?: T, whenLoaded?: (t: T | null) => void }): UIEventSource<T> {
if(IdbLocalStorage._sourceCache[key] !== undefined){
return IdbLocalStorage._sourceCache[key]
}
const src = new UIEventSource<T>(options?.defaultValue, "idb-local-storage:" + key)
if (Utils.runningFromConsole) {
return src;
@ -26,6 +30,7 @@ export class IdbLocalStorage {
options?.whenLoaded(null)
}
})
IdbLocalStorage._sourceCache[key] = src;
return src;
}