forked from MapComplete/MapComplete
More layout tweaks and fixes
This commit is contained in:
parent
b678efffd1
commit
2019e6c34c
11 changed files with 161 additions and 99 deletions
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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}
|
||||
|
|
80
src/UI/Comparison/ComparisonState.ts
Normal file
80
src/UI/Comparison/ComparisonState.ts
Normal 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
|
||||
|
||||
}
|
||||
}
|
|
@ -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}
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue