diff --git a/Logic/Osm/ChangesetHandler.ts b/Logic/Osm/ChangesetHandler.ts index 5b07a0faf..1861afa3a 100644 --- a/Logic/Osm/ChangesetHandler.ts +++ b/Logic/Osm/ChangesetHandler.ts @@ -50,6 +50,22 @@ export class ChangesetHandler { } + /** + * Creates a new list which contains every key at most once + */ + public static removeDuplicateMetaTags(extraMetaTags: ChangesetTag[]): ChangesetTag[]{ + const r : ChangesetTag[] = [] + const seen = new Set() + for (const extraMetaTag of extraMetaTags) { + if(seen.has(extraMetaTag.key)){ + continue + } + r.push(extraMetaTag) + seen.add(extraMetaTag.key) + } + return r + } + /** * Inplace rewrite of extraMetaTags * If the metatags contain a special motivation of the format ":node/-", this method will rewrite this negative number to the actual ID @@ -95,7 +111,7 @@ export class ChangesetHandler { } extraMetaTags = [...extraMetaTags, ...this.defaultChangesetTags()] - + extraMetaTags = ChangesetHandler.removeDuplicateMetaTags(extraMetaTags) if (this.userDetails.data.csCount == 0) { // The user became a contributor! this.userDetails.data.csCount = 1; @@ -316,6 +332,7 @@ export class ChangesetHandler { private async UpdateTags( csId: number, tags: ChangesetTag[]) { + tags = ChangesetHandler.removeDuplicateMetaTags(tags) console.trace("Updating tags of " + csId) const self = this; diff --git a/Logic/Tags/ComparingTag.ts b/Logic/Tags/ComparingTag.ts index 67ac5a9cf..20d5ffbde 100644 --- a/Logic/Tags/ComparingTag.ts +++ b/Logic/Tags/ComparingTag.ts @@ -31,6 +31,15 @@ export default class ComparingTag implements TagsFilter { return false; } + /** + * Checks if the properties match + * + * const t = new ComparingTag("key", (x => Number(x) < 42)) + * t.matchesProperties({key: 42}) // => false + * t.matchesProperties({key: 41}) // => true + * t.matchesProperties({key: 0}) // => true + * t.matchesProperties({differentKey: 42}) // => false + */ matchesProperties(properties: any): boolean { return this._predicate(properties[this._key]); } diff --git a/Logic/Tags/Tag.ts b/Logic/Tags/Tag.ts index 7189bb73c..9bc1b1eba 100644 --- a/Logic/Tags/Tag.ts +++ b/Logic/Tags/Tag.ts @@ -35,6 +35,8 @@ export class Tag extends TagsFilter { * isEmpty.matchesProperties({"key": ""}) // => true * isEmpty.matchesProperties({"other_key": ""}) // => true * isEmpty.matchesProperties({"other_key": "value"}) // => true + * isEmpty.matchesProperties({"key": undefined}) // => true + * */ matchesProperties(properties: any): boolean { const foundValue = properties[this.key] diff --git a/Models/Constants.ts b/Models/Constants.ts index d7cf889fb..6e0466d04 100644 --- a/Models/Constants.ts +++ b/Models/Constants.ts @@ -2,7 +2,7 @@ import {Utils} from "../Utils"; export default class Constants { - public static vNumber = "0.17.0-alpha-2"; + public static vNumber = "0.17.0-alpha-3"; public static ImgurApiKey = '7070e7167f0a25a' public static readonly mapillary_client_token_v4 = "MLY|4441509239301885|b40ad2d3ea105435bd40c7e76993ae85" diff --git a/UI/OpeningHours/OpeningHours.ts b/UI/OpeningHours/OpeningHours.ts index 94f42b50f..ff98cfe04 100644 --- a/UI/OpeningHours/OpeningHours.ts +++ b/UI/OpeningHours/OpeningHours.ts @@ -220,6 +220,23 @@ export class OH { } } + /** + * Converts an OH-syntax rule into an object + * + * + * const rules = OH.ParsePHRule("PH 12:00-17:00") + * rules.mode // => " " + * rules.start // => "12:00" + * rules.end // => "17:00" + * + * OH.ParseRule("PH 12:00-17:00") // => null + * OH.ParseRule("Th[-1] off") // => null + * + * const rules = OH.Parse("24/7"); + * rules.length // => 7 + * rules[0].startHour // => 0 + * OH.ToString(rules) // => "24/7" + */ public static ParseRule(rule: string): OpeningHour[] { try { if (rule.trim() == "24/7") { diff --git a/UI/i18n/Translations.ts b/UI/i18n/Translations.ts index dde9601d3..4f23c8908 100644 --- a/UI/i18n/Translations.ts +++ b/UI/i18n/Translations.ts @@ -43,6 +43,14 @@ export default class Translations { return new Translation(t, context); } + /** + * 'Wrap Translation': given an object containing translations OR a string, returns a translation object + * + * const json: any = {"en": "English", "nl": "Nederlands"}; + * const translation = Translations.WT(new Translation(json)); + * translation.textFor("en") // => "English" + * translation.textFor("nl") // => "Nederlands" + */ public static WT(s: string | Translation): Translation { if (s === undefined || s === null) { return undefined; diff --git a/Utils.ts b/Utils.ts index fe241fbb1..ee9f04497 100644 --- a/Utils.ts +++ b/Utils.ts @@ -109,7 +109,22 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be return "" + i; } - public static Round(i: number) { + /** + * Converts a number to a string with one number after the comma + * + * Utils.Round(15) // => "15.0" + * Utils.Round(1) // => "1.0" + * Utils.Round(1.5) // => "1.5" + * Utils.Round(0.5) // => "0.5" + * Utils.Round(1.6) // => "1.6" + * Utils.Round(-15) // => "-15.0" + * Utils.Round(-1) // => "-1.0" + * Utils.Round(-1.5) // => "-1.5" + * Utils.Round(-0.5) // => "-0.5" + * Utils.Round(-1.6) // => "-1.6" + * Utils.Round(-1531.63543) // =>"-1531.6" + */ + public static Round(i: number): string { if (i < 0) { return "-" + Utils.Round(-i); } diff --git a/assets/layers/charging_station/charging_station.json b/assets/layers/charging_station/charging_station.json index 6c05fa04b..9bde3a320 100644 --- a/assets/layers/charging_station/charging_station.json +++ b/assets/layers/charging_station/charging_station.json @@ -3370,18 +3370,6 @@ "nl": "Moet men betalen om dit oplaadpunt te gebruiken?" }, "mappings": [ - { - "if": { - "and": [ - "fee=no" - ] - }, - "then": { - "nl": "Gratis te gebruiken", - "en": "Free to use" - }, - "hideInAnswer": true - }, { "if": { "and": [ @@ -3410,6 +3398,18 @@ "en": "Free to use, but one has to authenticate" } }, + { + "if": { + "and": [ + "fee=no" + ] + }, + "then": { + "nl": "Gratis te gebruiken", + "en": "Free to use" + }, + "hideInAnswer": true + }, { "if": { "and": [ diff --git a/assets/layers/charging_station/charging_station.protojson b/assets/layers/charging_station/charging_station.protojson index 7c6d492ec..ad748caa2 100644 --- a/assets/layers/charging_station/charging_station.protojson +++ b/assets/layers/charging_station/charging_station.protojson @@ -224,18 +224,6 @@ "nl": "Moet men betalen om dit oplaadpunt te gebruiken?" }, "mappings": [ - { - "if": { - "and": [ - "fee=no" - ] - }, - "then": { - "nl": "Gratis te gebruiken", - "en": "Free to use" - }, - "hideInAnswer": true - }, { "if": { "and": [ @@ -264,6 +252,18 @@ "en": "Free to use, but one has to authenticate" } }, + { + "if": { + "and": [ + "fee=no" + ] + }, + "then": { + "nl": "Gratis te gebruiken", + "en": "Free to use" + }, + "hideInAnswer": true + }, { "if": { "and": [ diff --git a/assets/layers/shops/shops.json b/assets/layers/shops/shops.json index 0ded7b0bc..5df901100 100644 --- a/assets/layers/shops/shops.json +++ b/assets/layers/shops/shops.json @@ -379,6 +379,14 @@ "then": "isOpen" } ], + "label": { + "mappings": [ + { + "if": "name~*", + "then": "
{name}
" + } + ] + }, "iconSize": { "render": "40,40,center" }, @@ -396,4 +404,4 @@ } } ] -} \ No newline at end of file +} diff --git a/langs/layers/en.json b/langs/layers/en.json index 5203d3866..472d18c56 100644 --- a/langs/layers/en.json +++ b/langs/layers/en.json @@ -1797,14 +1797,14 @@ "fee": { "mappings": { "0": { - "then": "Free to use" - }, - "1": { "then": "Free to use (without authenticating)" }, - "2": { + "1": { "then": "Free to use, but one has to authenticate" }, + "2": { + "then": "Free to use" + }, "3": { "then": "Paid use, but free for customers of the hotel/pub/hospital/... who operates the charging station" }, diff --git a/langs/layers/nl.json b/langs/layers/nl.json index 46bcd6691..b71c9de87 100644 --- a/langs/layers/nl.json +++ b/langs/layers/nl.json @@ -1806,14 +1806,14 @@ "fee": { "mappings": { "0": { - "then": "Gratis te gebruiken" - }, - "1": { "then": "Gratis te gebruiken (zonder aan te melden)" }, - "2": { + "1": { "then": "Gratis te gebruiken, maar aanmelden met een applicatie is verplicht" }, + "2": { + "then": "Gratis te gebruiken" + }, "3": { "then": "Betalend te gebruiken, maar gratis voor klanten van het bijhorende hotel/café/ziekenhuis/..." }, diff --git a/testLegacy/Tag.spec.ts b/testLegacy/Tag.spec.ts index 18dbde4ce..90b526ed3 100644 --- a/testLegacy/Tag.spec.ts +++ b/testLegacy/Tag.spec.ts @@ -1,9 +1,6 @@ -import {Utils} from "../Utils"; import {equal} from "assert"; import T from "./TestHelper"; import Locale from "../UI/i18n/Locale"; -import Translations from "../UI/i18n/Translations"; -import {Translation} from "../UI/i18n/Translation"; import {OH, OpeningHour} from "../UI/OpeningHours/OpeningHours"; import {Tag} from "../Logic/Tags/Tag"; import {And} from "../Logic/Tags/And"; @@ -97,15 +94,6 @@ export default class TagSpec extends T { equal(false, t2.isEquivalent(t0)) equal(false, t2.isEquivalent(t1)) })], - ["Parse translation map", (() => { - - const json: any = {"en": "English", "nl": "Nederlands"}; - const translation = Translations.WT(new Translation(json)); - Locale.language.setData("en"); - equal(translation.txt, "English"); - Locale.language.setData("nl"); - equal(translation.txt, "Nederlands"); - })], ["Parse tag rendering", (() => { Locale.language.setData("nl"); const tr = new TagRenderingConfig({ @@ -130,13 +118,6 @@ export default class TagSpec extends T { equal(undefined, tr.GetRenderValue({"foo": "bar"})); })], - [ - "Empty match test", - () => { - const t = new Tag("key", ""); - equal(false, t.matchesProperties({"key": "somevalue"})) - } - ], [ "Test not with overpass", () => { @@ -385,42 +366,6 @@ export default class TagSpec extends T { ])); equal(rules, "Tu 23:00-00:00"); }], - ["OH 24/7", () => { - const rules = OH.Parse("24/7"); - equal(rules.length, 7); - equal(rules[0].startHour, 0); - const asStr = OH.ToString(rules); - equal(asStr, "24/7"); - }], - ["OH Th[-1] off", () => { - const rules = OH.ParseRule("Th[-1] off"); - equal(rules, null); - }], - ["OHNo parsePH 12:00-17:00", () => { - const rules = OH.ParseRule("PH 12:00-17:00"); - equal(rules, null); - }], - ["OH Parse PH 12:00-17:00", () => { - const rules = OH.ParsePHRule("PH 12:00-17:00"); - equal(rules.mode, " "); - equal(rules.start, "12:00") - equal(rules.end, "17:00") - }], - ["Round", () => { - equal(Utils.Round(15), "15.0") - equal(Utils.Round(1), "1.0") - equal(Utils.Round(1.5), "1.5") - equal(Utils.Round(0.5), "0.5") - equal(Utils.Round(1.6), "1.6") - - equal(Utils.Round(-15), "-15.0") - equal(Utils.Round(-1), "-1.0") - equal(Utils.Round(-1.5), "-1.5") - equal(Utils.Round(-0.5), "-0.5") - equal(Utils.Round(-1.6), "-1.6") - - } - ], ["Regression", () => { const config = {