From b8bca0287dd620ea144dff1280ab45909ddd441c Mon Sep 17 00:00:00 2001 From: pietervdvn Date: Mon, 18 Jul 2022 02:00:32 +0200 Subject: [PATCH] Refactor isShown into a tagsfilter --- .../Sources/FilteringFeatureSource.ts | 15 +++--- Logic/Tags/TagUtils.ts | 14 ++++++ .../Conversion/CreateNoteImportLayer.ts | 48 +++++++------------ Models/ThemeConfig/Conversion/PrepareTheme.ts | 2 +- Models/ThemeConfig/Conversion/Validation.ts | 4 ++ Models/ThemeConfig/Json/LayerConfigJson.ts | 4 +- Models/ThemeConfig/LayerConfig.ts | 6 +-- assets/layers/school/school.json | 14 ++---- assets/themes/buurtnatuur/buurtnatuur.json | 24 ++-------- assets/themes/cyclestreets/cyclestreets.json | 10 +--- assets/themes/grb_import/grb.json | 16 ++----- assets/themes/postal_codes/postal_codes.json | 20 +------- assets/themes/speelplekken/speelplekken.json | 10 +--- 13 files changed, 64 insertions(+), 123 deletions(-) diff --git a/Logic/FeatureSource/Sources/FilteringFeatureSource.ts b/Logic/FeatureSource/Sources/FilteringFeatureSource.ts index f363813a7..1fbb7fbe0 100644 --- a/Logic/FeatureSource/Sources/FilteringFeatureSource.ts +++ b/Logic/FeatureSource/Sources/FilteringFeatureSource.ts @@ -4,6 +4,8 @@ import {FeatureSourceForLayer, Tiled} from "../FeatureSource"; import {BBox} from "../../BBox"; import {ElementStorage} from "../../ElementStorage"; import {TagsFilter} from "../../Tags/TagsFilter"; +import {tag} from "@turf/turf"; +import {OsmFeature} from "../../../Models/OsmFeature"; export default class FilteringFeatureSource implements FeatureSourceForLayer, Tiled { public features: UIEventSource<{ feature: any; freshness: Date }[]> = @@ -65,21 +67,16 @@ export default class FilteringFeatureSource implements FeatureSourceForLayer, Ti private update() { const self = this; const layer = this.upstream.layer; - const features: { feature: any; freshness: Date }[] = (this.upstream.features.data ?? []); + const features: { feature: OsmFeature; freshness: Date }[] = (this.upstream.features.data ?? []); const includedFeatureIds = new Set(); const newFeatures = (features ?? []).filter((f) => { self.registerCallback(f.feature) - const isShown = layer.layerDef.isShown; + const isShown: TagsFilter = layer.layerDef.isShown; const tags = f.feature.properties; - if (isShown.IsKnown(tags)) { - const result = layer.layerDef.isShown.GetRenderValue( - f.feature.properties - ).txt; - if (result !== "yes") { - return false; - } + if (isShown !== undefined && !isShown.matchesProperties(tags) ) { + return false; } const tagsFilter = Array.from(layer.appliedFilters?.data?.values() ?? []) diff --git a/Logic/Tags/TagUtils.ts b/Logic/Tags/TagUtils.ts index c957d7206..caca5c0b7 100644 --- a/Logic/Tags/TagUtils.ts +++ b/Logic/Tags/TagUtils.ts @@ -257,6 +257,20 @@ export class TagUtils { } } + /** + * Same as `.Tag`, except that this will return undefined if the json is undefined + * @param json + * @param context + * @constructor + */ + public static TagD(json?: TagConfigJson, context: string = ""): TagsFilter | undefined { + if(json === undefined){ + return undefined + } + return TagUtils.Tag(json, context) + } + + /** * INLINE sort of the given list */ diff --git a/Models/ThemeConfig/Conversion/CreateNoteImportLayer.ts b/Models/ThemeConfig/Conversion/CreateNoteImportLayer.ts index 666bf3cf7..076c898af 100644 --- a/Models/ThemeConfig/Conversion/CreateNoteImportLayer.ts +++ b/Models/ThemeConfig/Conversion/CreateNoteImportLayer.ts @@ -16,7 +16,7 @@ export default class CreateNoteImportLayer extends Conversion r !== null && r["location"] !== undefined); const firstRender = (pointRenderings [0]) - if(firstRender === undefined){ - throw `Layer ${layerJson.id} does not have a pointRendering: `+context + if (firstRender === undefined) { + throw `Layer ${layerJson.id} does not have a pointRendering: ` + context } const title = layer.presets[0].title const importButton = {} { - const translations = trs(t.importButton,{layerId: layer.id, title: layer.presets[0].title}) + const translations = trs(t.importButton, {layerId: layer.id, title: layer.presets[0].title}) for (const key in translations) { - if(key !== "_context"){ + if (key !== "_context") { importButton[key] = "{" + translations[key] + "}" - }else{ + } else { importButton[key] = translations[key] } } @@ -68,19 +68,19 @@ export default class CreateNoteImportLayer extends Conversion(translation: TypedTranslation, subs: T) : object{ + function trs(translation: TypedTranslation, subs: T): object { return {...translation.Subs(subs).translations, "_context": translation.context} } const result: LayerConfigJson = { "id": "note_import_" + layer.id, // By disabling the name, the import-layers won't pollute the filter view "name": t.layerName.Subs({title: layer.title.render}).translations, - "description": trs(t.description , {title: layer.title.render}), + "description": trs(t.description, {title: layer.title.render}), "source": { "osmTags": { "and": [ @@ -93,7 +93,7 @@ export default class CreateNoteImportLayer extends Conversion {let lines = feat.get('comments')[0].text.split('\\n').map(l => l.trim()); lines.splice(0, feat.get('_trigger_index') + 1); lines = lines.filter(l => l != ''); return lines.join(';');})()" ], "isShown": { - "render": "no", - "mappings": [ - { - "if": "comments!~.*https://mapcomplete.osm.be.*", - "then": "no" - }, - { - "if": { - and: - ["_trigger_index~*", - {or: isShownIfAny} - ] - }, - "then": "yes" - } - ] + and: + ["_trigger_index~*", + {or: isShownIfAny} + ] }, "titleIcons": [ { @@ -165,9 +153,9 @@ export default class CreateNoteImportLayer extends Conversion { for (const layerConfig of alreadyLoaded) { try { - const layerDeps = DependencyCalculator.getLayerDependencies(new LayerConfig(layerConfig)) + const layerDeps = DependencyCalculator.getLayerDependencies(new LayerConfig(layerConfig, themeId+"(dependencies)")) dependencies.push(...layerDeps) } catch (e) { console.error(e) diff --git a/Models/ThemeConfig/Conversion/Validation.ts b/Models/ThemeConfig/Conversion/Validation.ts index bfbe094ec..22400569e 100644 --- a/Models/ThemeConfig/Conversion/Validation.ts +++ b/Models/ThemeConfig/Conversion/Validation.ts @@ -549,6 +549,10 @@ export class ValidateLayer extends DesugaringStep { if (json["hideUnderlayingFeaturesMinPercentage"] !== undefined) { errors.push(context + ": layer " + json.id + " contains an old 'hideUnderlayingFeaturesMinPercentage'") } + + if(json.isShown !== undefined && (json.isShown["render"] !== undefined || json.isShown["mappings"] !== undefined)){ + warnings.push(context + " has a tagRendering as `isShown`") + } } { // Check location of layer file diff --git a/Models/ThemeConfig/Json/LayerConfigJson.ts b/Models/ThemeConfig/Json/LayerConfigJson.ts index f9633ff97..772b9ff54 100644 --- a/Models/ThemeConfig/Json/LayerConfigJson.ts +++ b/Models/ThemeConfig/Json/LayerConfigJson.ts @@ -135,7 +135,7 @@ export interface LayerConfigJson { doNotDownload?: boolean; /** - * This tag rendering should either be 'yes' or 'no'. If 'no' is returned, then the feature will be hidden from view. + * If set, only features matching this extra tag will be shown. * This is useful to hide certain features from view. * * Important: hiding features does not work dynamically, but is only calculated when the data is first renders. @@ -143,7 +143,7 @@ export interface LayerConfigJson { * * The default value is 'yes' */ - isShown?: TagRenderingConfigJson; + isShown?: TagConfigJson; /** * Advanced option - might be set by the theme compiler diff --git a/Models/ThemeConfig/LayerConfig.ts b/Models/ThemeConfig/LayerConfig.ts index 0582c57ac..d45c2c132 100644 --- a/Models/ThemeConfig/LayerConfig.ts +++ b/Models/ThemeConfig/LayerConfig.ts @@ -39,7 +39,7 @@ export default class LayerConfig extends WithContextLoader { public readonly calculatedTags: [string, string, boolean][]; public readonly doNotDownload: boolean; public readonly passAllFeatures: boolean; - public readonly isShown: TagRenderingConfig; + public readonly isShown: TagsFilter; public minzoom: number; public minzoomVisible: number; public readonly maxzoom: number; @@ -302,7 +302,7 @@ export default class LayerConfig extends WithContextLoader { }); this.title = this.tr("title", undefined); - this.isShown = this.tr("isShown", "yes"); + this.isShown = TagUtils.TagD(json.isShown, context+".isShown") this.deletion = null; if (json.deletion === true) { @@ -478,7 +478,7 @@ export default class LayerConfig extends WithContextLoader { } AllTagRenderings(): TagRenderingConfig[] { - return Utils.NoNull([...this.tagRenderings, ...this.titleIcons, this.title, this.isShown]) + return Utils.NoNull([...this.tagRenderings, ...this.titleIcons, this.title]) } public isLeftRightSensitive(): boolean { diff --git a/assets/layers/school/school.json b/assets/layers/school/school.json index ac877be74..5d1024791 100644 --- a/assets/layers/school/school.json +++ b/assets/layers/school/school.json @@ -21,17 +21,9 @@ "_is_enclosed=feat.properties._enclosing != '[]'" ], "isShown": { - "render": "yes", - "mappings": [ - { - "if": { - "and": [ - "building~*", - "_is_enclosed=true" - ] - }, - "then": "no" - } + "or": [ + "building=", + "_is_enclosed!=true" ] }, "tagRenderings": [ diff --git a/assets/themes/buurtnatuur/buurtnatuur.json b/assets/themes/buurtnatuur/buurtnatuur.json index b9c9bba16..0527a4e39 100644 --- a/assets/themes/buurtnatuur/buurtnatuur.json +++ b/assets/themes/buurtnatuur/buurtnatuur.json @@ -34,7 +34,9 @@ "osmTags": { "or": [ "leisure=nature_reserve", - "boundary=protected_area" + { + "and": ["boundary=protected_area","protect_class!=22"] + } ] } }, @@ -149,15 +151,7 @@ "_overlapWithUpperLayers=Math.max(...feat.overlapWith('nature_reserve_buurtnatuur').map(o => o.overlap))/feat.area", "_tooMuchOverlap=Number(feat.properties._overlapWithUpperLayers) > 0.1 ? 'yes' :'no'" ], - "isShown": { - "render": "yes", - "mappings": [ - { - "if": "_tooMuchOverlap=yes", - "then": "no" - } - ] - }, + "isShown": "_tooMuchOverlap!=yes", "title": { "render": { "nl": "Park" @@ -257,15 +251,7 @@ "_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": { - "render": "yes", - "mappings": [ - { - "if": "_tooMuchOverlap=yes", - "then": "no" - } - ] - }, + "isShown": "_tooMuchOverlap!=yes", "title": { "render": { "nl": "Bos" diff --git a/assets/themes/cyclestreets/cyclestreets.json b/assets/themes/cyclestreets/cyclestreets.json index 92bdc2cea..4218b0d1f 100644 --- a/assets/themes/cyclestreets/cyclestreets.json +++ b/assets/themes/cyclestreets/cyclestreets.json @@ -73,15 +73,7 @@ ] } }, - "isShown": { - "render": "yes", - "mappings": [ - { - "if": "id!~way/.*", - "then": "no" - } - ] - }, + "isShown": "id~way/.*", "description": { "nl": "Een fietsstraat is een straat waar gemotoriseerd verkeer een fietser niet mag inhalen", "en": "A cyclestreet is a street where motorized traffic is not allowed to overtake a cyclist", diff --git a/assets/themes/grb_import/grb.json b/assets/themes/grb_import/grb.json index 9c8153a66..d0581433e 100644 --- a/assets/themes/grb_import/grb.json +++ b/assets/themes/grb_import/grb.json @@ -630,18 +630,10 @@ } } ], - "isShown": { - "render": "yes", - "mappings": [ - { - "if": { - "and": [ - "_imported_osm_object_found=true", - "_imported_osm_still_fresh=true" - ] - }, - "then": "no" - } + "isShown":{ + "or": [ + "_imported_osm_object_found!=true", + "_imported_osm_still_fresh!=true" ] }, "mapRendering": [ diff --git a/assets/themes/postal_codes/postal_codes.json b/assets/themes/postal_codes/postal_codes.json index dfbbd1722..3315e0dc4 100644 --- a/assets/themes/postal_codes/postal_codes.json +++ b/assets/themes/postal_codes/postal_codes.json @@ -117,15 +117,7 @@ "dashArray": "8 8" } ], - "isShown": { - "render": "yes", - "mappings": [ - { - "if": "_country!=be", - "then": "no" - } - ] - } + "isShown": "_country=be" }, { "id": "wrong_postal_code", @@ -196,15 +188,7 @@ ] } ], - "isShown": { - "render": "yes", - "mappings": [ - { - "if": "_country!=be", - "then": "no" - } - ] - } + "isShown": "_country=be" } ] } \ No newline at end of file diff --git a/assets/themes/speelplekken/speelplekken.json b/assets/themes/speelplekken/speelplekken.json index c4ff417d2..9b0b1825e 100644 --- a/assets/themes/speelplekken/speelplekken.json +++ b/assets/themes/speelplekken/speelplekken.json @@ -288,14 +288,6 @@ "then": "./assets/themes/speelplekken/youtube.svg" } ], - "isShown": { - "render": "yes", - "mappings": [ - { - "if": "_is_shadowed=yes", - "then": "no" - } - ] - } + "isShown":"_is_shadowed!=yes" } } \ No newline at end of file