forked from MapComplete/MapComplete
First working version of the notes-layer, add filtering
This commit is contained in:
parent
ebb510da04
commit
91d2272861
19 changed files with 282 additions and 109 deletions
99
Utils.ts
99
Utils.ts
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue