diff --git a/assets/layers/questions/questions.json b/assets/layers/questions/questions.json index f620399ba..a5c455f05 100644 --- a/assets/layers/questions/questions.json +++ b/assets/layers/questions/questions.json @@ -3358,6 +3358,19 @@ "en": "Has no toilets", "nl": "Heeft geenad toiletten" } + }, + { + "if": "toilets=separate", + "then": { + "en": "The toilets are marked separately on the map", + "nl": "De toiletten zijn als alleenstaand punt op de kaart aangeduid" + } + } + ], + "requiredLayers": [ + { + "id": "toilet", + "minzoom": 18 } ] } diff --git a/langs/layers/en.json b/langs/layers/en.json index 7c3ed989e..ff876584a 100644 --- a/langs/layers/en.json +++ b/langs/layers/en.json @@ -565,6 +565,9 @@ "12": { "then": "Woodcarving" }, + "13": { + "then": "Poem" + }, "2": { "then": "Painting" }, @@ -9333,6 +9336,9 @@ }, "1": { "then": "Has no toilets" + }, + "2": { + "then": "The toilets are marked separately on the map" } }, "question": "Has {title()} toilets?" @@ -14563,4 +14569,4 @@ "render": "wind turbine" } } -} +} \ No newline at end of file diff --git a/langs/layers/nl.json b/langs/layers/nl.json index feccfe08c..0ec3b23b6 100644 --- a/langs/layers/nl.json +++ b/langs/layers/nl.json @@ -551,6 +551,9 @@ "12": { "then": "Houtsculptuur" }, + "13": { + "then": "Gedicht" + }, "2": { "then": "Schilderij" }, @@ -7954,6 +7957,9 @@ }, "1": { "then": "Heeft geenad toiletten" + }, + "2": { + "then": "De toiletten zijn als alleenstaand punt op de kaart aangeduid" } }, "question": "Heeft {title()} toiletten?" @@ -11558,4 +11564,4 @@ "render": "windturbine" } } -} +} \ No newline at end of file diff --git a/scripts/generateLayerOverview.ts b/scripts/generateLayerOverview.ts index a702c99f1..3295e65ed 100644 --- a/scripts/generateLayerOverview.ts +++ b/scripts/generateLayerOverview.ts @@ -805,9 +805,7 @@ class LayerOverviewUtils extends Script { const sourcePath = `./assets/layers/${id}/${id}.json` const targetPath = `./public/assets/generated/layers/${id}.json` - if (id === "questions") { - layerState.set(id, "clean") - } else if (LayerOverviewUtils.shouldBeUpdated(sourcePath, targetPath)) { + if (LayerOverviewUtils.shouldBeUpdated(sourcePath, targetPath)) { layerState.set(id, "changed") } else { layerState.set(id, "clean") @@ -816,10 +814,10 @@ class LayerOverviewUtils extends Script { const state = layerState.get(id) if (state !== "clean") { allClean = false - console.log(`- ${id} (${state}; ${dirtyDeps.map(dd => dd + "*").join(", ")})`) + console.log(`- ${id} (${state}; ${dirtyDeps.map(dd => dd + "*").join(", ")})`) } } - if (allClean) { + if (!allClean) { console.log("\n") } } diff --git a/src/Models/ThemeConfig/Conversion/PrepareTheme.ts b/src/Models/ThemeConfig/Conversion/PrepareTheme.ts index 8dfd15376..3418acdcb 100644 --- a/src/Models/ThemeConfig/Conversion/PrepareTheme.ts +++ b/src/Models/ThemeConfig/Conversion/PrepareTheme.ts @@ -303,7 +303,8 @@ class AddDependencyLayersToTheme extends DesugaringStep { neededLayer: string neededBy: string reason: string - context?: string + context?: string, + minzoom?: number }[] = [] do { const dependencies: { @@ -311,7 +312,8 @@ class AddDependencyLayersToTheme extends DesugaringStep { reason: string context?: string neededBy: string - checkHasSnapName: boolean + checkHasSnapName: boolean, + minzoom?: number }[] = [] for (const layerConfig of alreadyLoaded) { @@ -382,6 +384,7 @@ class AddDependencyLayersToTheme extends DesugaringStep { dep.forceLoad = true dep.passAllFeatures = true dep.description = reason + dep.minzoom = unmetDependency.minzoom ?? dep.minzoom dependenciesToAdd.unshift({ config: dep, reason, @@ -400,6 +403,7 @@ class AddDependencyLayersToTheme extends DesugaringStep { const state = this._state const allKnownLayers: Map = state.sharedLayers const knownTagRenderings: Map = state.tagRenderings + // Current layers in the theme const layers: LayerConfigJson[] = theme.layers // Layers should be expanded at this point knownTagRenderings.forEach((value, key) => { diff --git a/src/Models/ThemeConfig/DependencyCalculator.ts b/src/Models/ThemeConfig/DependencyCalculator.ts index 868a75e62..2f581d86c 100644 --- a/src/Models/ThemeConfig/DependencyCalculator.ts +++ b/src/Models/ThemeConfig/DependencyCalculator.ts @@ -5,11 +5,19 @@ import { SpecialVisualization } from "../../UI/SpecialVisualization" import SpecialVisualizations from "../../UI/SpecialVisualizations" export default class DependencyCalculator { - public static GetTagRenderingDependencies(tr: TagRenderingConfig): string[] { + public static GetTagRenderingDependencies(tr: TagRenderingConfig): { + id: string, + minzoom?: number, + neededBy: string + }[] { if (tr === undefined) { throw "Got undefined tag rendering in getTagRenderingDependencies" } - const deps: string[] = [] + const deps: { id: string, minZoom?: number, neededBy: string }[] = [] + + if (tr.requiredLayers) { + deps.push(...tr.requiredLayers.map(req => ({ ...req, neededBy: tr.id }))) + } // All translated snippets const parts: string[] = [].concat(...tr.EnumerateTranslations().map((tr) => tr.AllValues())) @@ -21,7 +29,7 @@ export default class DependencyCalculator { .map((p) => <{ func: SpecialVisualization; args: string[] }>p) .filter((o) => o?.func?.getLayerDependencies !== undefined) for (const specialViz of specialVizs) { - deps.push(...specialViz.func.getLayerDependencies(specialViz.args)) + deps.push(...specialViz.func.getLayerDependencies(specialViz.args).map(id => ({ id, neededBy: tr.id }))) } } return deps @@ -43,7 +51,8 @@ export default class DependencyCalculator { reason: string context?: string neededBy: string - checkHasSnapName: boolean + checkHasSnapName: boolean, + minzoom?: number }[] = [] for (let i = 0; layer.presets !== undefined && i < layer.presets.length; i++) { @@ -68,8 +77,9 @@ export default class DependencyCalculator { for (const tr of layer.AllTagRenderings()) { for (const dep of DependencyCalculator.GetTagRenderingDependencies(tr)) { deps.push({ - neededLayer: dep, - reason: "a tagrendering needs this layer", + neededLayer: dep.id, + reason: `tagrendering ${dep.neededBy} needs this layer`, + minzoom: dep.minzoom, context: tr.id, neededBy: layer.id, checkHasSnapName: false, @@ -91,8 +101,8 @@ export default class DependencyCalculator { let currentKey = undefined let currentLine = undefined const params: ExtraFuncParams = { - getFeatureById: (_) => undefined, - getFeaturesWithin: (layerId, _) => { + getFeatureById: () => undefined, + getFeaturesWithin: (layerId) => { if (layerId === "*") { // This is a wildcard return [] @@ -128,7 +138,9 @@ export default class DependencyCalculator { ) const result = func(obj, helpers) obj.properties[key] = JSON.stringify(result) - } catch (e) {} + } catch (e) { + // pass + } } } diff --git a/src/Models/ThemeConfig/Json/TagRenderingConfigJson.ts b/src/Models/ThemeConfig/Json/TagRenderingConfigJson.ts index e33798d9b..e045da9d5 100644 --- a/src/Models/ThemeConfig/Json/TagRenderingConfigJson.ts +++ b/src/Models/ThemeConfig/Json/TagRenderingConfigJson.ts @@ -236,4 +236,15 @@ export interface TagRenderingConfigJson { * group: hidden */ _definedIn?: [string, string] + + /** + * question: what layers should always be included in the theme if this question is set? + * + * Some items (e.g. toilets, bicycle pumps) can be added as separate node or as prefixed values. + * In this case, we'll always want to include the relevant layer, on a high zoom level + * This can be forced by setting this. + * Note: if the theme already has a layer with this ID, the value is ignored + * group: hidden + */ + requiredLayers: { id: string, minzoom?: number }[] } diff --git a/src/Models/ThemeConfig/TagRenderingConfig.ts b/src/Models/ThemeConfig/TagRenderingConfig.ts index 0f14025b4..8a755b124 100644 --- a/src/Models/ThemeConfig/TagRenderingConfig.ts +++ b/src/Models/ThemeConfig/TagRenderingConfig.ts @@ -5,10 +5,7 @@ import { TagUtils } from "../../Logic/Tags/TagUtils" import { And } from "../../Logic/Tags/And" import { Utils } from "../../Utils" import { Tag } from "../../Logic/Tags/Tag" -import { - MappingConfigJson, - QuestionableTagRenderingConfigJson, -} from "./Json/QuestionableTagRenderingConfigJson" +import { MappingConfigJson, QuestionableTagRenderingConfigJson } from "./Json/QuestionableTagRenderingConfigJson" import Validators, { ValidatorType } from "../../UI/InputElement/Validators" import { TagRenderingConfigJson } from "./Json/TagRenderingConfigJson" import { RegexTag } from "../../Logic/Tags/RegexTag" @@ -68,6 +65,8 @@ export default class TagRenderingConfig { */ public readonly _definedIn: [string, string] = undefined + public readonly requiredLayers: { id: string, minzoom?: number }[] + public readonly freeform?: { readonly key: string readonly type: ValidatorType @@ -174,6 +173,7 @@ export default class TagRenderingConfig { translationKey + ".editButtonAriaLabel" ) + this.requiredLayers = json.requiredLayers ?? [] this.condition = TagUtils.Tag(json.condition ?? { and: [] }, `${context}.condition`) this.invalidValues = json["invalidValues"] ? TagUtils.Tag(json["invalidValues"], `${context}.invalidValues`)