More layout tweaks and fixes

This commit is contained in:
Pieter Vander Vennet 2024-06-18 19:40:50 +02:00
parent b678efffd1
commit 2019e6c34c
11 changed files with 161 additions and 99 deletions

View file

@ -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"
}
}
}

View file

@ -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 <a href={url}>{source}</a> using the embedded JSON-LD",
"missing": {
"intro": "OpenStreetMap has no information about the following attributes",

View file

@ -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),

View file

@ -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
}

View file

@ -748,7 +748,11 @@ export class RewriteSpecial extends DesugaringStep<TagRenderingConfigJson> {
)
}
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<TagRenderingConfigJson> {
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<TagRenderingConfigJson> {
}
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 {

View file

@ -66,7 +66,7 @@
</script>
<div>
<div class="interactive flex w-full justify-between py-1 px-2">
<div class:interactive={!readonly} class="flex w-full justify-between py-1 px-2">
<div class="flex flex-col">
<div>
{#if renderingExternal}

View file

@ -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<string[]>
public readonly missing: Store<string[]>
public readonly unknownImages: Store<string[]>
public readonly propertyKeysExternal: string[]
public readonly knownImages: Store<Set<string>>
constructor(tags: UIEventSource<OsmTags>, externalProperties: Record<string, string>) {
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
}
}

View file

@ -1,6 +1,6 @@
<script lang="ts">
import LinkableImage from "../Image/LinkableImage.svelte"
import { Store, UIEventSource } from "../../Logic/UIEventSource"
import { UIEventSource } from "../../Logic/UIEventSource"
import type { OsmTags } from "../../Models/OsmFeature"
import type { SpecialVisualizationState } from "../SpecialVisualization"
import type { Feature } from "geojson"
@ -14,10 +14,10 @@
import AttributedImage from "../Image/AttributedImage.svelte"
import Translations from "../i18n/Translations"
import Tr from "../Base/Tr.svelte"
import { ComparisonState } from "./ComparisonState"
export let externalProperties: Record<string, string>
delete externalProperties["@context"]
console.log("External properties are", externalProperties)
export let sourceUrl: string
export let tags: UIEventSource<OsmTags>
@ -27,66 +27,14 @@
export let readonly = false
export let comparisonState : ComparisonState
let missing = comparisonState.missing
let unknownImages = comparisonState.unknownImages
let knownImages = comparisonState.knownImages
let different =comparisonState.different
const t = Translations.t.external
let externalKeys: string[] = Object.keys(externalProperties).sort()
const imageKeyRegex = /image|image:[0-9]+/
let knownImages: Store<Set<string>> = tags.map(
(osmProperties) =>
new Set(
Object.keys(osmProperties)
.filter((k) => k.match(imageKeyRegex))
.map((k) => osmProperties[k])
)
)
let unknownImages: Store<string[]> = knownImages.map((images) =>
externalKeys
.filter((k) => k.match(imageKeyRegex))
.map((k) => externalProperties[k])
.filter((i) => !images.has(i))
)
let propertyKeysExternal = externalKeys.filter((k) => k.match(imageKeyRegex) === null)
let missing: Store<string[]> = 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])
let different: Store<string[]> = 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
})
)
let hasDifferencesAtStart =
different.data.length + missing.data.length + unknownImages.data.length > 0
let currentStep: "init" | "applying_all" | "all_applied" = "init"
let applyAllHovered = false
@ -102,19 +50,13 @@
}
</script>
{#if propertyKeysExternal.length === 0 && $knownImages.size + $unknownImages.length === 0}
<Tr cls="subtle" t={t.noDataLoaded} />
{:else if !hasDifferencesAtStart}
<span class="subtle text-sm">
<Tr t={t.allIncluded.Subs({ source: sourceUrl })} />
</span>
{:else if $unknownImages.length === 0 && $missing.length === 0 && $different.length === 0}
{#if $unknownImages.length === 0 && $missing.length === 0 && $different.length === 0}
<div class="thanks m-0 flex items-center gap-x-2 px-2">
<Party class="h-8 w-8 shrink-0" />
<Tr t={t.allIncluded.Subs({ source: sourceUrl })} />
</div>
{:else}
<div class="low-interaction p-1">
{#if !readonly}
<Tr t={t.loadedFrom.Subs({ url: sourceUrl, source: sourceUrl })} />
{/if}
@ -218,9 +160,8 @@
{/if}
{/if}
{#if externalProperties["_last_edit_timestamp"] !== undefined}
<span class="subtle text-sm">
External data has been last modified on {externalProperties["_last_edit_timestamp"]}
<span class="subtle text-sm flex flex-end justify-end mt-2 mr-4">
<Tr t={t.lastModified.Subs({date: new Date(externalProperties["_last_edit_timestamp"]).toLocaleString() })}/>
</span>
{/if}
</div>
{/if}

View file

@ -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<string, string> } }
@ -29,6 +30,19 @@
export let sourceUrl: Store<string>
export let collapsed: boolean
const t = Translations.t.external
let comparisonState: Store<ComparisonState | undefined> = 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)
</script>
{#if !$sourceUrl}
@ -39,8 +53,14 @@
<div class="subtle italic low-interaction p-2 px-4 rounded">
<Tr t={Translations.t.external.error} />
</div>
{:else if $externalData["success"] !== undefined}
<AccordionSingle>
{:else if $propertyKeysExternal.length === 0 && $knownImages.size + $unknownImages.length === 0}
<Tr cls="subtle" t={t.noDataLoaded} />
{:else if !$hasDifferencesAtStart}
<span class="subtle text-sm">
<Tr t={t.allIncluded.Subs({ source: $sourceUrl })} />
</span>
{:else if $comparisonState !== undefined}
<AccordionSingle expanded={!collapsed}>
<span slot="header" class="flex">
<GlobeAlt class="w-6 h-6" />
<Tr t={Translations.t.external.title} />
@ -53,6 +73,7 @@
{tags}
{readonly}
sourceUrl={$sourceUrl}
comparisonState={$comparisonState}
/>
</AccordionSingle>
{/if}

View file

@ -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

View file

@ -134,10 +134,15 @@ 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) => {
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
return true // unregister
}
}catch (e) {
console.error("Could not get '_referencing_ways'-attribute of tags due to", e)
}
})
}