diff --git a/assets/themes/velopark/velopark.json b/assets/themes/velopark/velopark.json index 11d5c0cab..733e839a4 100644 --- a/assets/themes/velopark/velopark.json +++ b/assets/themes/velopark/velopark.json @@ -99,7 +99,8 @@ "key": "ref:velopark", "useProxy": "no", "host": "https://data.velopark.be", - "mode": "readonly" + "mode": "readonly", + "collapsed": "no" } } }, @@ -485,7 +486,7 @@ "path": "./assets/themes/velopark/velopark.svg", "class": "medium" }, - "classes": "flex w-full ", + "classes": "flex flex-col m-2", "render": { "special": { "type": "link", @@ -511,7 +512,8 @@ "type": "linked_data_from_website", "key": "ref:velopark", "useProxy": "no", - "host": "https://data.velopark.be" + "host": "https://data.velopark.be", + "collapsed": "no" } } } diff --git a/langs/en.json b/langs/en.json index a50539f44..155daeedb 100644 --- a/langs/en.json +++ b/langs/en.json @@ -59,6 +59,7 @@ "currentInOsmIs": "At the moment, OpenStreetMap has the following value recorded:", "done": "Done", "error": "Could not load linked data from the website", + "lastModified": "External data has been last modified on {date}", "loadedFrom": "The following data is loaded from {source} using the embedded JSON-LD", "missing": { "intro": "OpenStreetMap has no information about the following attributes", diff --git a/scripts/generateLayerOverview.ts b/scripts/generateLayerOverview.ts index b8a271631..109129264 100644 --- a/scripts/generateLayerOverview.ts +++ b/scripts/generateLayerOverview.ts @@ -515,7 +515,6 @@ class LayerOverviewUtils extends Script { // At the same time, an index of available layers is built. console.log("------------- VALIDATING THE BUILTIN QUESTIONS ---------------") const sharedTagRenderings = this.getSharedTagRenderings(doesImageExist) - console.log("Shared questions are:", Array.from(sharedTagRenderings.keys()).join(", ")) console.log(" ---------- VALIDATING BUILTIN LAYERS ---------") const state: DesugaringContext = { tagRenderings: LayerOverviewUtils.asDict(sharedTagRenderings), diff --git a/src/Logic/MetaTagging.ts b/src/Logic/MetaTagging.ts index 22a48ac21..1b6796d27 100644 --- a/src/Logic/MetaTagging.ts +++ b/src/Logic/MetaTagging.ts @@ -419,7 +419,7 @@ export default class MetaTagging { "Static MetataggingObject for theme is not set; using `new Function` (aka `eval`) to get calculated tags. This might trip up the CSP" ) - const calculatedTags: [string, string, boolean][] = layer.calculatedTags + const calculatedTags: [string, string, boolean][] = layer?.calculatedTags ?? [] if (calculatedTags === undefined || calculatedTags.length === 0) { return undefined } diff --git a/src/Models/ThemeConfig/Conversion/PrepareLayer.ts b/src/Models/ThemeConfig/Conversion/PrepareLayer.ts index 956950f68..5898a9b69 100644 --- a/src/Models/ThemeConfig/Conversion/PrepareLayer.ts +++ b/src/Models/ThemeConfig/Conversion/PrepareLayer.ts @@ -748,7 +748,11 @@ export class RewriteSpecial extends DesugaringStep { ) } - private static escapeStr(v: string): string { + private static escapeStr(v: string, context: ConversionContext): string { + if(typeof v !== "string"){ + context.err("Detected a non-string value where one expected a string: "+v) + return RewriteSpecial.escapeStr(""+v, context) + } return v .replace(/,/g, "&COMMA") .replace(/\{/g, "&LBRACE") @@ -930,7 +934,7 @@ export class RewriteSpecial extends DesugaringStep { if (foundLanguages.size === 0) { const args = argNamesList - .map((nm) => RewriteSpecial.escapeStr(special[nm] ?? "")) + .map((nm) => RewriteSpecial.escapeStr(special[nm] ?? "", context)) .join(",") return { "*": `{${type}(${args})${clss}}` @@ -949,7 +953,7 @@ export class RewriteSpecial extends DesugaringStep { } if (typeof v === "string") { - args.push(RewriteSpecial.escapeStr(v)) + args.push(RewriteSpecial.escapeStr(v, context)) } else if (typeof v === "object") { args.push(JSON.stringify(v)) } else { diff --git a/src/UI/Comparison/ComparisonAction.svelte b/src/UI/Comparison/ComparisonAction.svelte index 4800291b8..d5f5208a8 100644 --- a/src/UI/Comparison/ComparisonAction.svelte +++ b/src/UI/Comparison/ComparisonAction.svelte @@ -66,7 +66,7 @@
-
+
{#if renderingExternal} diff --git a/src/UI/Comparison/ComparisonState.ts b/src/UI/Comparison/ComparisonState.ts new file mode 100644 index 000000000..dd0743374 --- /dev/null +++ b/src/UI/Comparison/ComparisonState.ts @@ -0,0 +1,80 @@ +import { Store, UIEventSource } from "../../Logic/UIEventSource" +import { OsmTags } from "../../Models/OsmFeature" +import { SpecialVisualizationState } from "../SpecialVisualization" + +export class ComparisonState { + public readonly hasDifferencesAtStart: boolean + public readonly different: Store + public readonly missing: Store + public readonly unknownImages: Store + public readonly propertyKeysExternal: string[] + public readonly knownImages: Store> + + constructor(tags: UIEventSource, externalProperties: Record) { + + externalProperties = { ...externalProperties } + delete externalProperties["@context"] + + let externalKeys: string[] = Object.keys(externalProperties).sort() + + const imageKeyRegex = /image|image:[0-9]+/ + + this.knownImages = tags.map( + (osmProperties) => + new Set( + Object.keys(osmProperties) + .filter((k) => k.match(imageKeyRegex)) + .map((k) => osmProperties[k]) + ) + ) + + this.unknownImages = this.knownImages.map((images) => + externalKeys + .filter((k) => k.match(imageKeyRegex)) + .map((k) => externalProperties[k]) + .filter((i) => !images.has(i)) + ) + + this.propertyKeysExternal = externalKeys.filter((k) => k.match(imageKeyRegex) === null) + let propertyKeysExternal = this.propertyKeysExternal + this.missing = tags.map((osmProperties) => + propertyKeysExternal.filter((k) => { + if (k.startsWith("_")) { + return false + } + return osmProperties[k] === undefined && typeof externalProperties[k] === "string" + }) + ) + // let same = propertyKeysExternal.filter((key) => osmProperties[key] === externalProperties[key]) + this.different = tags.map((osmProperties) => + propertyKeysExternal.filter((key) => { + if (key.startsWith("_")) { + return false + } + if (osmProperties[key] === undefined) { + return false + } + if (typeof externalProperties[key] !== "string") { + return false + } + if (osmProperties[key] === externalProperties[key]) { + return false + } + + if (key === "website") { + const osmCanon = new URL(osmProperties[key]).toString() + const externalCanon = new URL(externalProperties[key]).toString() + if (osmCanon === externalCanon) { + return false + } + } + + return true + }) + ) + + this.hasDifferencesAtStart = + this. different.data.length + this.missing.data.length + this.unknownImages.data.length > 0 + + } +} diff --git a/src/UI/Comparison/ComparisonTable.svelte b/src/UI/Comparison/ComparisonTable.svelte index f742db602..1aa70517b 100644 --- a/src/UI/Comparison/ComparisonTable.svelte +++ b/src/UI/Comparison/ComparisonTable.svelte @@ -1,6 +1,6 @@ -{#if propertyKeysExternal.length === 0 && $knownImages.size + $unknownImages.length === 0} - -{:else if !hasDifferencesAtStart} - - - -{:else if $unknownImages.length === 0 && $missing.length === 0 && $different.length === 0} + +{#if $unknownImages.length === 0 && $missing.length === 0 && $different.length === 0}
{:else} -
{#if !readonly} {/if} @@ -218,9 +160,8 @@ {/if} {/if} {#if externalProperties["_last_edit_timestamp"] !== undefined} - - External data has been last modified on {externalProperties["_last_edit_timestamp"]} + + {/if} -
{/if} diff --git a/src/UI/Comparison/ComparisonTool.svelte b/src/UI/Comparison/ComparisonTool.svelte index d083b98e1..f72a295ca 100644 --- a/src/UI/Comparison/ComparisonTool.svelte +++ b/src/UI/Comparison/ComparisonTool.svelte @@ -14,6 +14,7 @@ import Tr from "../Base/Tr.svelte" import AccordionSingle from "../Flowbite/AccordionSingle.svelte" import GlobeAlt from "@babeard/svelte-heroicons/mini/GlobeAlt" + import { ComparisonState } from "./ComparisonState" export let externalData: Store< | { success: { content: Record } } @@ -28,7 +29,20 @@ export let readonly = false export let sourceUrl: Store - export let collapsed : boolean + export let collapsed: boolean + const t = Translations.t.external + + let comparisonState: Store = externalData.mapD(external => { + if (external["success"]) { + return new ComparisonState(tags, external["success"]) + } + return undefined + }) + let unknownImages = comparisonState.bindD(ct => ct.unknownImages) + let knownImages = comparisonState.bindD(ct => ct.knownImages) + let propertyKeysExternal = comparisonState.mapD(ct => ct.propertyKeysExternal) + let hasDifferencesAtStart = comparisonState.mapD(ct => ct.hasDifferencesAtStart) + {#if !$sourceUrl} @@ -39,20 +53,27 @@
-{:else if $externalData["success"] !== undefined} - +{:else if $propertyKeysExternal.length === 0 && $knownImages.size + $unknownImages.length === 0} + +{:else if !$hasDifferencesAtStart} + + + +{:else if $comparisonState !== undefined} + - - + + - + {/if} diff --git a/src/UI/Map/RasterLayerHandler.ts b/src/UI/Map/RasterLayerHandler.ts index a1cffc7b7..933a130cd 100644 --- a/src/UI/Map/RasterLayerHandler.ts +++ b/src/UI/Map/RasterLayerHandler.ts @@ -97,6 +97,15 @@ class SingleBackgroundHandler { } } + private tryEnableSafe(): boolean{ + try { + return this.tryEnable() + }catch (e) { + console.log("Error: could not enable due to error", e) + return false + } + } + /** * Returns 'false' if should be attempted again * @private diff --git a/src/UI/Popup/MoveWizardState.ts b/src/UI/Popup/MoveWizardState.ts index cdb9255e8..d3e0a669a 100644 --- a/src/UI/Popup/MoveWizardState.ts +++ b/src/UI/Popup/MoveWizardState.ts @@ -134,11 +134,16 @@ export class MoveWizardState { // This is a new point. Check if it was snapped to an existing way due to the '_referencing_ways'-tag const store = this._state.featureProperties.getStore(id) store?.addCallbackAndRunD((tags) => { - if (tags._referencing_ways !== undefined && tags._referencing_ways !== "[]") { - console.log("Got referencing ways according to the tags") - this.moveDisallowedReason.setData(t.partOfAWay) - return true - } + try{ + + if (tags._referencing_ways !== undefined && tags._referencing_ways !== "[]") { + console.log("Got referencing ways according to the tags") + this.moveDisallowedReason.setData(t.partOfAWay) + return true // unregister + } + }catch (e) { + console.error("Could not get '_referencing_ways'-attribute of tags due to", e) + } }) } }