First working version of the notes-layer, add filtering

This commit is contained in:
Pieter Vander Vennet 2022-01-07 17:31:39 +01:00
parent ebb510da04
commit 91d2272861
19 changed files with 282 additions and 109 deletions

View file

@ -45,34 +45,31 @@ There are also some technicalities in your theme to keep in mind:
The import button can be tested in an unofficial theme by adding \`test=true\` or \`backend=osm-test\` as [URL-paramter](URL_Parameters.md).
The import button will show up then. If in testmode, you can read the changeset-XML directly in the web console.
In the case that MapComplete is pointed to the testing grounds, the edit will be made on https://master.apis.dev.openstreetmap.org`
private static knownKeys = ["addExtraTags", "and", "calculatedTags", "changesetmessage", "clustering", "color", "condition", "customCss", "dashArray", "defaultBackgroundId", "description", "descriptionTail", "doNotDownload", "enableAddNewPoints", "enableBackgroundLayerSelection", "enableGeolocation", "enableLayers", "enableMoreQuests", "enableSearch", "enableShareScreen", "enableUserBadge", "freeform", "hideFromOverview", "hideInAnswer", "icon", "iconOverlays", "iconSize", "id", "if", "ifnot", "isShown", "key", "language", "layers", "lockLocation", "maintainer", "mappings", "maxzoom", "maxZoom", "minNeededElements", "minzoom", "multiAnswer", "name", "or", "osmTags", "passAllFeatures", "presets", "question", "render", "roaming", "roamingRenderings", "rotation", "shortDescription", "socialImage", "source", "startLat", "startLon", "startZoom", "tagRenderings", "tags", "then", "title", "titleIcons", "type", "version", "wayHandling", "widenFactor", "width"]
private static extraKeys = ["nl", "en", "fr", "de", "pt", "es", "name", "phone", "email", "amenity", "leisure", "highway", "building", "yes", "no", "true", "false"]
private static injectedDownloads = {}
private static _download_cache = new Map<string, { promise: Promise<any>, timestamp: number }>()
/**
* Parses the arguments for special visualisations
*/
public static ParseVisArgs(specs: { name: string, defaultValue?: string }[], args: string[]): any {
const parsed = {};
if(args.length> specs.length){
throw "To much arguments for special visualization: got "+args.join(",")+" but expected only "+args.length+" arguments"
if (args.length > specs.length) {
throw "To much arguments for special visualization: got " + args.join(",") + " but expected only " + args.length + " arguments"
}
for (let i = 0; i < specs.length; i++){
for (let i = 0; i < specs.length; i++) {
const spec = specs[i];
let arg = args[i]?.trim();
if(arg === undefined || arg === ""){
if (arg === undefined || arg === "") {
arg = spec.defaultValue
}
parsed[spec.name] = arg
parsed[spec.name] = arg
}
return parsed;
}
private static knownKeys = ["addExtraTags", "and", "calculatedTags", "changesetmessage", "clustering", "color", "condition", "customCss", "dashArray", "defaultBackgroundId", "description", "descriptionTail", "doNotDownload", "enableAddNewPoints", "enableBackgroundLayerSelection", "enableGeolocation", "enableLayers", "enableMoreQuests", "enableSearch", "enableShareScreen", "enableUserBadge", "freeform", "hideFromOverview", "hideInAnswer", "icon", "iconOverlays", "iconSize", "id", "if", "ifnot", "isShown", "key", "language", "layers", "lockLocation", "maintainer", "mappings", "maxzoom", "maxZoom", "minNeededElements", "minzoom", "multiAnswer", "name", "or", "osmTags", "passAllFeatures", "presets", "question", "render", "roaming", "roamingRenderings", "rotation", "shortDescription", "socialImage", "source", "startLat", "startLon", "startZoom", "tagRenderings", "tags", "then", "title", "titleIcons", "type", "version", "wayHandling", "widenFactor", "width"]
private static extraKeys = ["nl", "en", "fr", "de", "pt", "es", "name", "phone", "email", "amenity", "leisure", "highway", "building", "yes", "no", "true", "false"]
private static injectedDownloads = {}
private static _download_cache = new Map<string, { promise: Promise<any>, timestamp: number }>()
static EncodeXmlValue(str) {
if (typeof str !== "string") {
str = "" + str
@ -198,14 +195,14 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
const newArr = [];
const seen = new Set<string>();
for (const string of arr) {
if(seen.has(string)){
if (seen.has(string)) {
newArr.push(string)
}
seen.add(string)
}
return newArr;
}
public static Identical<T>(t1: T[], t2: T[], eq?: (t: T, t0: T) => boolean): boolean {
if (t1.length !== t2.length) {
return false
@ -238,6 +235,13 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
return [a.substr(0, index), a.substr(index + sep.length)];
}
/**
* Given a piece of text, will replace any key occuring in 'tags' by the corresponding value
* @param txt
* @param tags
* @param useLang
* @constructor
*/
public static SubstituteKeys(txt: string | undefined, tags: any, useLang?: string): string | undefined {
if (txt === undefined) {
return undefined
@ -249,7 +253,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
while (match) {
const key = match[1]
let v = tags[key]
if(v !== undefined ){
if (v !== undefined) {
if (v["toISOString"] != undefined) {
// This is a date, probably the timestamp of the object
@ -257,18 +261,18 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
const date: Date = el;
v = date.toISOString()
}
if(useLang !== undefined && v?.translations !== undefined){
if (useLang !== undefined && v?.translations !== undefined) {
v = v.translations[useLang] ?? v.translations["*"] ?? (v.textFor !== undefined ? v.textFor(useLang) : v);
}
if(v.InnerConstructElement !== undefined){
console.warn("SubstituteKeys received a BaseUIElement to substitute in - this is probably a bug and will be downcast to a string\nThe key is", key,"\nThe value is", v)
v = ( <HTMLElement> v.InnerConstructElement())?.innerText
if (v.InnerConstructElement !== undefined) {
console.warn("SubstituteKeys received a BaseUIElement to substitute in - this is probably a bug and will be downcast to a string\nThe key is", key, "\nThe value is", v)
v = (<HTMLElement>v.InnerConstructElement())?.innerText
}
if(typeof v !== "string"){
v = ""+v
if (typeof v !== "string") {
v = "" + v
}
v = v.replace(/\n/g, "<br/>")
}
@ -321,7 +325,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
}
const sourceV = source[key];
if(target === null){
if (target === null) {
return source
}
const targetV = target[key]
@ -342,6 +346,27 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
return target;
}
static WalkJson(json: any, f: (v: number | string | boolean | undefined) => any) {
if(json === undefined){
return f(undefined)
}
const jtp = typeof json
if (jtp === "boolean" || jtp === "string" || jtp === "number"){
return f(json)
}
if (json.map !== undefined) {
return json.map(sub => {
return Utils.WalkJson(sub, f);
})
}
const cp = {...json}
for (const key in json) {
cp[key] = Utils.WalkJson(json[key], f)
}
return cp
}
static getOrSetDefault<K, V>(dict: Map<K, V>, k: K, v: () => V) {
let found = dict.get(k);
if (found !== undefined) {
@ -592,6 +617,18 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
return "https://osmcha.org/?filters=" + encodeURIComponent("{" + osmcha_link + "}")
}
/**
* Deepclone an object by serializing and deserializing it
* @param x
* @constructor
*/
static Clone<T>(x: T): T {
if (x === undefined) {
return undefined;
}
return JSON.parse(JSON.stringify(x));
}
private static colorDiff(c0: { r: number, g: number, b: number }, c1: { r: number, g: number, b: number }) {
return Math.abs(c0.r - c1.r) + Math.abs(c0.g - c1.g) + Math.abs(c0.b - c1.b);
}
@ -618,17 +655,5 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
b: parseInt(hex.substr(5, 2), 16),
}
}
/**
* Deepclone an object by serializing and deserializing it
* @param x
* @constructor
*/
static Clone<T>(x: T): T {
if(x === undefined){
return undefined;
}
return JSON.parse(JSON.stringify(x));
}
}