diff --git a/InitUiElements.ts b/InitUiElements.ts index 0f1143eba..cdc00c41d 100644 --- a/InitUiElements.ts +++ b/InitUiElements.ts @@ -56,7 +56,6 @@ export class InitUiElements { console.log("Using layout: ", layoutToUse.id, "LayoutFromBase64 is ", layoutFromBase64); - State.state = new State(layoutToUse); // This 'leaks' the global state via the window object, useful for debugging @@ -212,7 +211,7 @@ export class InitUiElements { } - static LoadLayoutFromHash(userLayoutParam: UIEventSource): [LayoutConfig, string]{ + static LoadLayoutFromHash(userLayoutParam: UIEventSource): [LayoutConfig, string] { try { let hash = location.hash.substr(1); const layoutFromBase64 = userLayoutParam.data; @@ -284,7 +283,7 @@ export class InitUiElements { }) State.state.selectedElement.addCallbackAndRunD(_ => { - isOpened.setData(false); + isOpened.setData(false); }) isOpened.setData(Hash.hash.data === undefined || Hash.hash.data === "" || Hash.hash.data == "welcome") } @@ -333,8 +332,8 @@ export class InitUiElements { }); State.state.selectedElement.addCallbackAndRunD(_ => { - layerControlButton.isEnabled.setData(false); - copyrightButton.isEnabled.setData(false); + layerControlButton.isEnabled.setData(false); + copyrightButton.isEnabled.setData(false); }) } @@ -345,11 +344,11 @@ export class InitUiElements { State.state.backgroundLayer = State.state.backgroundLayerId .map((selectedId: string) => { - if(selectedId === undefined){ + if (selectedId === undefined) { return AvailableBaseLayers.osmCarto } - - + + const available = State.state.availableBackgroundLayers.data; for (const layer of available) { if (layer.id === selectedId) { @@ -358,7 +357,7 @@ export class InitUiElements { } return AvailableBaseLayers.osmCarto; }, [State.state.availableBackgroundLayers], layer => layer.id); - + new LayerResetter( State.state.backgroundLayer, State.state.locationControl, State.state.availableBackgroundLayers, State.state.layoutToUse.map((layout: LayoutConfig) => layout.defaultBackgroundId)); diff --git a/Logic/Tags/Or.ts b/Logic/Tags/Or.ts index 12c456aa8..254e193e9 100644 --- a/Logic/Tags/Or.ts +++ b/Logic/Tags/Or.ts @@ -8,7 +8,7 @@ export class Or extends TagsFilter { super(); this.or = or; } - + matchesProperties(properties: any): boolean { for (const tagsFilter of this.or) { if (tagsFilter.matchesProperties(properties)) { @@ -23,9 +23,7 @@ export class Or extends TagsFilter { const choices = []; for (const tagsFilter of this.or) { const subChoices = tagsFilter.asOverpass(); - for (const subChoice of subChoices) { - choices.push(subChoice) - } + choices.push(...subChoices) } return choices; } diff --git a/Logic/Tags/RegexTag.ts b/Logic/Tags/RegexTag.ts index cf12798f7..68ca88d08 100644 --- a/Logic/Tags/RegexTag.ts +++ b/Logic/Tags/RegexTag.ts @@ -34,9 +34,9 @@ export class RegexTag extends TagsFilter { asOverpass(): string[] { if (typeof this.key === "string") { - return [`['${this.key}'${this.invert ? "!" : ""}~'${RegexTag.source(this.value)}']`]; + return [`["${this.key}"${this.invert ? "!" : ""}~"${RegexTag.source(this.value)}"]`]; } - return [`[~'${this.key.source}'${this.invert ? "!" : ""}~'${RegexTag.source(this.value)}']`]; + return [`[~"${this.key.source}"${this.invert ? "!" : ""}~"${RegexTag.source(this.value)}"]`]; } isUsableAsAnswer(): boolean { diff --git a/assets/layers/nature_reserve/nature_reserve.json b/assets/layers/nature_reserve/nature_reserve.json index 11bd7c027..af74d6954 100644 --- a/assets/layers/nature_reserve/nature_reserve.json +++ b/assets/layers/nature_reserve/nature_reserve.json @@ -10,7 +10,12 @@ { "or": [ "leisure=nature_reserve", - "boundary=protected_area" + { + "and": [ + "protect_class!=98", + "boundary=protected_area" + ] + } ] } ] diff --git a/assets/themes/buurtnatuur/buurtnatuur.json b/assets/themes/buurtnatuur/buurtnatuur.json index a6e6cc9e4..9c82e4d44 100644 --- a/assets/themes/buurtnatuur/buurtnatuur.json +++ b/assets/themes/buurtnatuur/buurtnatuur.json @@ -29,7 +29,7 @@ "socialImage": "./assets/themes/buurtnatuur/social_image.jpg", "layers": [ { - "id": "nature_reserve", + "id": "nature_reserve_buurtnatuur", "name": { "nl": "Natuurgebied" }, @@ -141,7 +141,7 @@ } }, "calculatedTags": [ - "_overlapWithUpperLayers=Math.max(...feat.overlapWith('nature_reserve').map(o => o.overlap))/feat.area", + "_overlapWithUpperLayers=Math.max(...feat.overlapWith('nature_reserve_buurtnatuur').map(o => o.overlap))/feat.area", "_tooMuchOverlap=Number(feat.properties._overlapWithUpperLayers) > 0.1 ? 'yes' :'no'" ], "isShown": { @@ -240,7 +240,7 @@ } }, "calculatedTags": [ - "_overlapWithUpperLayers=Math.max(...feat.overlapWith('parks','nature_reserve').map(o => o.overlap))/feat.area", + "_overlapWithUpperLayers=Math.max(...feat.overlapWith('parks','nature_reserve_buurtnatuur').map(o => o.overlap))/feat.area", "_tooMuchOverlap=Number(feat.properties._overlapWithUpperLayers) > 0.1 ? 'yes' : 'no'" ], "isShown": { diff --git a/scripts/generateLayerOverview.ts b/scripts/generateLayerOverview.ts index f10af68b0..785c858b3 100644 --- a/scripts/generateLayerOverview.ts +++ b/scripts/generateLayerOverview.ts @@ -140,6 +140,7 @@ class LayerOverviewUtils { const layerFiles = lt.layers; const themeFiles = lt.themes; + console.log(" ---------- VALIDATING ---------") const licensePaths = [] for (const i in licenses) { @@ -151,6 +152,9 @@ class LayerOverviewUtils { const knownLayerIds = new Map(); for (const layerFile of layerFiles) { + if (knownLayerIds.has(layerFile.parsed.id)) { + throw "Duplicate identifier: " + layerFile.parsed.id + " in file " + layerFile.path + } layerErrorCount.push(...this.validateLayer(layerFile.parsed, layerFile.path, knownPaths)) knownLayerIds.set(layerFile.parsed.id, new LayerConfig(layerFile.parsed, AllKnownLayers.sharedUnits)) } @@ -170,21 +174,21 @@ class LayerOverviewUtils { missingTranslations.push(...this.validateTranslationCompletenessOfObject(layerConfig, themeFile.language, "Layer " + layer)) } - } else { + } else if (layer.builtin !== undefined) { let names = layer.builtin; - if (names !== undefined) { - if (typeof names === "string") { - names = [names] + if (typeof names === "string") { + names = [names] + } + names.forEach(name => { + if (!knownLayerIds.has(name)) { + themeErrorCount.push("Unknown layer id: " + name + "(which uses inheritance)") } - names.forEach(name => { - if (!knownLayerIds.has(name)) { - themeErrorCount.push("Unknown layer id: " + name + "(which uses inheritance)") - } - return - }) - } else { - // layer.builtin contains layer overrides - we can skip those - layerErrorCount.push(...this.validateLayer(layer, undefined, knownPaths, themeFile.id)) + return + }) + } else { + layerErrorCount.push(...this.validateLayer(layer, undefined, knownPaths, themeFile.id)) + if (knownLayerIds.has(layer.id)) { + throw `The theme ${themeFile.id} defines a layer with id ${layer.id}, which is the same as an already existing layer` } } } diff --git a/test/Tag.spec.ts b/test/Tag.spec.ts index 4c32dc2e7..25d95446b 100644 --- a/test/Tag.spec.ts +++ b/test/Tag.spec.ts @@ -4,20 +4,17 @@ import T from "./TestHelper"; import {FromJSON} from "../Customizations/JSON/FromJSON"; import Locale from "../UI/i18n/Locale"; import Translations from "../UI/i18n/Translations"; -import {UIEventSource} from "../Logic/UIEventSource"; import TagRenderingConfig from "../Customizations/JSON/TagRenderingConfig"; -import EditableTagRendering from "../UI/Popup/EditableTagRendering"; import {Translation} from "../UI/i18n/Translation"; import {OH, OpeningHour} from "../UI/OpeningHours/OpeningHours"; -import PublicHolidayInput from "../UI/OpeningHours/PublicHolidayInput"; -import {SubstitutedTranslation} from "../UI/SubstitutedTranslation"; import {Tag} from "../Logic/Tags/Tag"; import {And} from "../Logic/Tags/And"; +import {Overpass} from "../Logic/Osm/Overpass"; Utils.runningFromConsole = true; -export default class TagSpec extends T{ - +export default class TagSpec extends T { + constructor() { super("Tags", [ ["Tag replacement works in translation", () => { @@ -88,11 +85,11 @@ export default class TagSpec extends T{ equal(assign.matchesProperties({"survey:date": "2021-03-29"}), false); equal(assign.matchesProperties({"_date:now": "2021-03-29"}), false); equal(assign.matchesProperties({"some_key": "2021-03-29"}), false); - + const notEmptyList = FromJSON.Tag("xyz!~\\[\\]") - equal(notEmptyList.matchesProperties({"xyz":undefined}), true); - equal(notEmptyList.matchesProperties({"xyz":"[]"}), false); - equal(notEmptyList.matchesProperties({"xyz":"[\"abc\"]"}), true); + equal(notEmptyList.matchesProperties({"xyz": undefined}), true); + equal(notEmptyList.matchesProperties({"xyz": "[]"}), false); + equal(notEmptyList.matchesProperties({"xyz": "[\"abc\"]"}), true); })], @@ -161,6 +158,38 @@ export default class TagSpec extends T{ equal(false, t.matchesProperties({"key": "somevalue"})) } ], + [ + "Test not with overpass", + () => { + const t = { + and: [ + "boundary=protected_area", + "protect_class!=98" + ] + } + const filter = FromJSON.Tag(t) + const overpass = filter.asOverpass(); + console.log(overpass) + equal(overpass[0], "[\"boundary\"=\"protected_area\"][\"protect_class\"!~\"^98$\"]") + + const or = { + or: [ + "leisure=nature_reserve", + t + ] + } + const overpassOr = FromJSON.Tag(or).asOverpass() + equal(2, overpassOr.length) + equal(overpassOr[1], "[\"boundary\"=\"protected_area\"][\"protect_class\"!~\"^98$\"]") + + const orInOr = {or:[ + "amenity=drinking_water", + or + ]} + const overpassOrInor = FromJSON.Tag(orInOr).asOverpass() + equal(3, overpassOrInor.length) + } + ], [ "Tagrendering test", () => { @@ -358,27 +387,27 @@ export default class TagSpec extends T{ ]); equal(rules, "Tu 10:00-12:00; Su 13:00-17:00"); }], - ["JOIN OH with end hours", () =>{ + ["JOIN OH with end hours", () => { const rules = OH.ToString( OH.MergeTimes([ - { - weekday: 1, - endHour: 23, - endMinutes: 30, - startHour: 23, - startMinutes: 0 - }, { - weekday: 1, - endHour: 24, - endMinutes: 0, - startHour: 23, - startMinutes: 30 - }, + { + weekday: 1, + endHour: 23, + endMinutes: 30, + startHour: 23, + startMinutes: 0 + }, { + weekday: 1, + endHour: 24, + endMinutes: 0, + startHour: 23, + startMinutes: 30 + }, - ])); + ])); equal(rules, "Tu 23:00-00:00"); - }], ["JOIN OH with overflowed hours", () =>{ + }], ["JOIN OH with overflowed hours", () => { const rules = OH.ToString( OH.MergeTimes([ @@ -464,10 +493,10 @@ export default class TagSpec extends T{ ] }; - const tagRendering = new TagRenderingConfig(config, null, "test"); + const tagRendering = new TagRenderingConfig(config, null, "test"); equal(true, tagRendering.IsKnown({bottle: "yes"})) equal(false, tagRendering.IsKnown({})) }]]); } - + }