Merge branch 'develop'

This commit is contained in:
Pieter Vander Vennet 2023-11-12 13:49:45 +01:00
commit 322f2cfd80
13 changed files with 276 additions and 62 deletions

View file

@ -218,6 +218,14 @@
} }
], ],
"tagRenderings": [ "tagRenderings": [
{"id":"sotm-events",
"render": {
"special": {
"type": "giggity",
"giggityUrl":"https://sotm.osmz.ru/sotmeu2023.xml"
}
}
},
"images", "images",
"level", "level",
{ {

View file

@ -688,6 +688,7 @@
"mappings": [ "mappings": [
{ {
"if": "mapcomplete-show_debug=yes", "if": "mapcomplete-show_debug=yes",
"icon": "./assets/svg/debug.svg",
"then": { "then": {
"en": "Show debug info", "en": "Show debug info",
"de": "Debug-Informationen anzeigen", "de": "Debug-Informationen anzeigen",
@ -720,6 +721,11 @@
} }
] ]
}, },
{
"id":"debug-gps",
"condition": "mapcomplete-show_debug=yes",
"render": "{gps_all_tags()}"
},
{ {
"id": "debug", "id": "debug",
"condition": "mapcomplete-show_debug=yes", "condition": "mapcomplete-show_debug=yes",

View file

@ -579,10 +579,80 @@
"enableImproveAccuracy": true, "enableImproveAccuracy": true,
"enableRelocation": false "enableRelocation": false
}, },
"pointRendering": [], "pointRendering": [
"lineRendering": [ {
{} "marker": [
{
"icon": "circle",
"color": "white"
},
{
"icon": {
"render": "./assets/themes/facadegardens/geveltuin.svg",
"mappings": [
{
"if": {
"and": [
"direct_sunlight=yes"
] ]
},
"then": "./assets/themes/facadegardens/zon.svg"
},
{
"if": {
"and": [
"direct_sunlight=partial"
]
},
"then": "./assets/themes/facadegardens/halfzon.svg"
},
{
"if": {
"and": [
"direct_sunlight=no"
]
},
"then": "./assets/themes/facadegardens/schaduw.svg"
}
]
}
}
],
"iconBadges": [
{
"if": "plant~.*vine.*",
"then": "circle:white;./assets/themes/facadegardens/klimplant.svg"
},
{
"if": "plant~.*groundcover.*",
"then": "circle:white;./assets/themes/facadegardens/bodembedekker.svg"
},
{
"if": "edible=true",
"then": "circle:white;./assets/themes/facadegardens/eetbaar.svg"
},
{
"if": "rain_barel=yes",
"then": "circle:white;./assets/themes/facadegardens/gevelton.svg"
},
{
"if": "plant~.*shrub.*",
"then": "circle:white;./assets/themes/facadegardens/struik.svg"
},
{
"if": "plant~.*flower.*",
"then": "circle:white;./assets/themes/facadegardens/bloei.svg"
}
],
"iconSize": "50,50",
"location": [
"point",
"centroid"
],
"anchor": "center"
}
],
"lineRendering": []
} }
], ],
"widenFactor": 1.5 "widenFactor": 1.5

12
package-lock.json generated
View file

@ -4684,9 +4684,9 @@
"integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg=="
}, },
"node_modules/axios": { "node_modules/axios": {
"version": "1.2.3", "version": "1.6.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.2.3.tgz", "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.1.tgz",
"integrity": "sha512-pdDkMYJeuXLZ6Xj/Q5J3Phpe+jbGdsSzlQaFVkMQzRUL05+6+tetX8TV3p4HrU4kzuO9bt+io/yGQxuyxA/xcw==", "integrity": "sha512-vfBmhDpKafglh0EldBEbVuoe7DyAavGSLWhuSm5ZSEKQnHhBf0xAAwybbNH1IkrJNGnS/VG4I5yxig1pCEXE4g==",
"dependencies": { "dependencies": {
"follow-redirects": "^1.15.0", "follow-redirects": "^1.15.0",
"form-data": "^4.0.0", "form-data": "^4.0.0",
@ -16846,9 +16846,9 @@
"integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg=="
}, },
"axios": { "axios": {
"version": "1.2.3", "version": "1.6.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.2.3.tgz", "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.1.tgz",
"integrity": "sha512-pdDkMYJeuXLZ6Xj/Q5J3Phpe+jbGdsSzlQaFVkMQzRUL05+6+tetX8TV3p4HrU4kzuO9bt+io/yGQxuyxA/xcw==", "integrity": "sha512-vfBmhDpKafglh0EldBEbVuoe7DyAavGSLWhuSm5ZSEKQnHhBf0xAAwybbNH1IkrJNGnS/VG4I5yxig1pCEXE4g==",
"requires": { "requires": {
"follow-redirects": "^1.15.0", "follow-redirects": "^1.15.0",
"form-data": "^4.0.0", "form-data": "^4.0.0",

View file

@ -173,6 +173,8 @@ export default class GeoLocationHandler {
properties[k] = location[k] properties[k] = location[k]
} }
} }
console.log(location)
properties["_all"] = JSON.stringify(location)
const feature = <Feature>{ const feature = <Feature>{
type: "Feature", type: "Feature",

View file

@ -26,7 +26,12 @@ export class LastClickFeatureSource implements WritableFeatureSource {
for (let i = 0; i < (layer.presets ?? []).length; i++) { for (let i = 0; i < (layer.presets ?? []).length; i++) {
const preset = layer.presets[i] const preset = layer.presets[i]
const tags = new ImmutableStore(TagUtils.KVtoProperties(preset.tags)) const tags = new ImmutableStore(TagUtils.KVtoProperties(preset.tags))
const { html } = layer.mapRendering[0].RenderIcon(tags, { const rendering = layer.mapRendering[0]
if (!rendering) {
console.error("NO rendering for preset", layer.id)
continue
}
const { html } = rendering.RenderIcon(tags, {
noSize: true, noSize: true,
includeBadges: false, includeBadges: false,
}) })

View file

@ -3,40 +3,12 @@ import { Utils } from "../../Utils"
export class ThemeMetaTagging { export class ThemeMetaTagging {
public static readonly themeName = "usersettings" public static readonly themeName = "usersettings"
public metaTaggging_for_usersettings(feat: { properties: Record<string, string> }) { public metaTaggging_for_usersettings(feat: {properties: Record<string, string>}) {
Utils.AddLazyProperty(feat.properties, "_mastodon_candidate_md", () => Utils.AddLazyProperty(feat.properties, '_mastodon_candidate_md', () => feat.properties._description.match(/\[[^\]]*\]\((.*(mastodon|en.osm.town).*)\).*/)?.at(1) )
feat.properties._description Utils.AddLazyProperty(feat.properties, '_d', () => feat.properties._description?.replace(/&lt;/g,'<')?.replace(/&gt;/g,'>') ?? '' )
.match(/\[[^\]]*\]\((.*(mastodon|en.osm.town).*)\).*/) Utils.AddLazyProperty(feat.properties, '_mastodon_candidate_a', () => (feat => {const e = document.createElement('div');e.innerHTML = feat.properties._d;return Array.from(e.getElementsByTagName("a")).filter(a => a.href.match(/mastodon|en.osm.town/) !== null)[0]?.href }) (feat) )
?.at(1) Utils.AddLazyProperty(feat.properties, '_mastodon_link', () => (feat => {const e = document.createElement('div');e.innerHTML = feat.properties._d;return Array.from(e.getElementsByTagName("a")).filter(a => a.getAttribute("rel")?.indexOf('me') >= 0)[0]?.href})(feat) )
) Utils.AddLazyProperty(feat.properties, '_mastodon_candidate', () => feat.properties._mastodon_candidate_md ?? feat.properties._mastodon_candidate_a )
Utils.AddLazyProperty( feat.properties['__current_backgroun'] = 'initial_value'
feat.properties,
"_d",
() => feat.properties._description?.replace(/&lt;/g, "<")?.replace(/&gt;/g, ">") ?? ""
)
Utils.AddLazyProperty(feat.properties, "_mastodon_candidate_a", () =>
((feat) => {
const e = document.createElement("div")
e.innerHTML = feat.properties._d
return Array.from(e.getElementsByTagName("a")).filter(
(a) => a.href.match(/mastodon|en.osm.town/) !== null
)[0]?.href
})(feat)
)
Utils.AddLazyProperty(feat.properties, "_mastodon_link", () =>
((feat) => {
const e = document.createElement("div")
e.innerHTML = feat.properties._d
return Array.from(e.getElementsByTagName("a")).filter(
(a) => a.getAttribute("rel")?.indexOf("me") >= 0
)[0]?.href
})(feat)
)
Utils.AddLazyProperty(
feat.properties,
"_mastodon_candidate",
() => feat.properties._mastodon_candidate_md ?? feat.properties._mastodon_candidate_a
)
feat.properties["__current_backgroun"] = "initial_value"
} }
} }

View file

@ -1062,6 +1062,15 @@ export class PrevalidateLayer extends DesugaringStep<LayerConfigJson> {
) )
} }
if (!(json.pointRendering?.length > 0)) {
context.enter("pointRendering").err("There are no pointRenderings at all")
}
if (json.presets?.length > 0) {
if (!(json.pointRendering?.length > 0)) {
context.enter("presets").warn("A preset is defined, but there is no pointRendering")
}
}
if (json.source === "special") { if (json.source === "special") {
if (!Constants.priviliged_layers.find((x) => x == json.id)) { if (!Constants.priviliged_layers.find((x) => x == json.id)) {
context.err( context.err(
@ -1377,6 +1386,7 @@ export class ValidateLayer extends Conversion<
context.err("Could not parse layer due to:" + e) context.err("Could not parse layer due to:" + e)
return undefined return undefined
} }
for (let i = 0; i < (layerConfig.calculatedTags ?? []).length; i++) { for (let i = 0; i < (layerConfig.calculatedTags ?? []).length; i++) {
const [_, code, __] = layerConfig.calculatedTags[i] const [_, code, __] = layerConfig.calculatedTags[i]
try { try {

View file

@ -0,0 +1,91 @@
<script lang="ts">
import { Store, UIEventSource } from "../../Logic/UIEventSource";
import type { SpecialVisualizationState } from "../SpecialVisualization";
import { Utils } from "../../Utils";
import Loading from "../../assets/svg/Loading.svelte";
export let tags: Store<Record<string, string>>;
export let giggityUrl: string;
export let state: SpecialVisualizationState;
let name = $tags["name"];
let events: UIEventSource<{
date: Date,
start: string,
duration: string,
room: string,
slug: string,
url: string,
title: string,
track: string,
type: string,
language: string,
abstract: string,
description: string,
persons: string,
} []> = new UIEventSource(undefined);
async function loadXml() {
if (!name) {
console.log("Not fetching giggity events as name is", name, tags);
return;
}
const xmlStr = await Utils.downloadAdvanced(giggityUrl);
console.log("Raw xml", xmlStr);
const parser = new DOMParser();
let doc = parser.parseFromString(xmlStr.content, "application/xml");
let days = Array.from(doc.documentElement.getElementsByTagName("day"));
let today = new Date().toISOString().split("T")[0];
const eventsToday = days.find(day => day.getAttribute("date") === today);
console.log("Events today", eventsToday);
const childs = ["date", "start", "duration", "room", "slug", "url", "title", "track", "type", "language", "abstract", "description", "persons"];
const now = new Date().toISOString().split("T")[1].substring(0, 5)
let eventsList = [];
for (const eventXml of Array.from(eventsToday.getElementsByTagName("event"))) {
const event: Record<string, string> = {};
for (const child of childs) {
const v = Array.from(eventXml.getElementsByTagName(child)).map(xml => xml.textContent).join("; ");
event[child] = v;
}
if(!name.startsWith(event.room)){
continue
}
if(now > event.start){
continue
}
eventsList.push(event);
}
events.setData(eventsList);
}
loadXml();
</script>
{#if $events === undefined}
<Loading class="h-4">Loading giggity events from {giggityUrl}</Loading>
{:else if $events.length === 0}
<i>No upcoming events in this room</i>
{:else}
<div>
<h2>Upcoming events</h2>
{#each $events as event}
<div class="flex flex-col m-2 border border-gray-200 border-dotted">
{#if event.url}
<h3><a href={event.url} target="_blank">{event.title}</a></h3>
{:else }
<h3>{event.title}</h3>
{/if}
<div><b>{event.start}</b></div>
<i>By {event.persons}</i>
<div>
{event.abstract}
</div>
{event.url}
</div>
{/each}
</div>
{/if}

View file

@ -20,6 +20,11 @@
_metatags = tags _metatags = tags
}) })
) )
let knownTagRenderings = layer.tagRenderings
.filter(config => (config.condition?.matchesProperties($tags) ?? true) && (config.metacondition?.matchesProperties({ ...$tags, ..._metatags } ?? true)
&& config.IsKnown($tags)))
</script> </script>
{#if $tags._deleted === "yes"} {#if $tags._deleted === "yes"}
@ -29,9 +34,7 @@
</button> </button>
{:else} {:else}
<div class="flex h-full flex-col gap-y-2 overflow-y-auto p-1 px-2"> <div class="flex h-full flex-col gap-y-2 overflow-y-auto p-1 px-2">
{#each layer.tagRenderings as config (config.id)} {#each knownTagRenderings as config (config.id)}
{#if (config.condition?.matchesProperties($tags) ?? true) && config.metacondition?.matchesProperties({ ...$tags, ..._metatags } ?? true)}
{#if config.IsKnown($tags)}
<TagRenderingEditable <TagRenderingEditable
{tags} {tags}
{config} {config}
@ -39,9 +42,8 @@
{selectedElement} {selectedElement}
{layer} {layer}
{highlightedRendering} {highlightedRendering}
clss={knownTagRenderings.length === 1 ? "h-full" : "tr-length-"+knownTagRenderings.length}
/> />
{/if}
{/if}
{/each} {/each}
</div> </div>
{/if} {/if}

View file

@ -21,7 +21,7 @@
export let editingEnabled: Store<boolean> | undefined = state?.featureSwitchUserbadge export let editingEnabled: Store<boolean> | undefined = state?.featureSwitchUserbadge
export let highlightedRendering: UIEventSource<string> = undefined export let highlightedRendering: UIEventSource<string> = undefined
export let showQuestionIfUnknown: boolean = false export let clss
/** /**
* Indicates if this tagRendering currently shows the attribute or asks the question to _change_ the property * Indicates if this tagRendering currently shows the attribute or asks the question to _change_ the property
*/ */
@ -71,7 +71,7 @@
} }
</script> </script>
<div bind:this={htmlElem}> <div bind:this={htmlElem} class={clss}>
{#if config.question && (!editingEnabled || $editingEnabled)} {#if config.question && (!editingEnabled || $editingEnabled)}
{#if editMode} {#if editMode}
<TagRenderingQuestion {config} {tags} {selectedElement} {state} {layer}> <TagRenderingQuestion {config} {tags} {selectedElement} {state} {layer}>
@ -106,7 +106,7 @@
</div> </div>
{/if} {/if}
{:else} {:else}
<div class="w-full overflow-hidden p-2"> <div class="w-full h-full overflow-hidden p-2">
<TagRenderingAnswer {config} {tags} {selectedElement} {state} {layer} /> <TagRenderingAnswer {config} {tags} {selectedElement} {state} {layer} />
</div> </div>
{/if} {/if}

View file

@ -76,6 +76,8 @@ import StarsBarIcon from "./Reviews/StarsBarIcon.svelte"
import ReviewForm from "./Reviews/ReviewForm.svelte" import ReviewForm from "./Reviews/ReviewForm.svelte"
import Questionbox from "./Popup/TagRendering/Questionbox.svelte" import Questionbox from "./Popup/TagRendering/Questionbox.svelte"
import { TagUtils } from "../Logic/Tags/TagUtils" import { TagUtils } from "../Logic/Tags/TagUtils"
import Giggity from "./BigComponents/Giggity.svelte"
import ThemeViewState from "../Models/ThemeViewState"
class NearbyImageVis implements SpecialVisualization { class NearbyImageVis implements SpecialVisualization {
// Class must be in SpecialVisualisations due to weird cyclical import that breaks the tests // Class must be in SpecialVisualisations due to weird cyclical import that breaks the tests
@ -90,6 +92,7 @@ class NearbyImageVis implements SpecialVisualization {
"A component showing nearby images loaded from various online services such as Mapillary. In edit mode and when used on a feature, the user can select an image to add to the feature" "A component showing nearby images loaded from various online services such as Mapillary. In edit mode and when used on a feature, the user can select an image to add to the feature"
funcName = "nearby_images" funcName = "nearby_images"
needsUrls = NearbyImagesSearch.apiUrls needsUrls = NearbyImagesSearch.apiUrls
constr( constr(
state: SpecialVisualizationState, state: SpecialVisualizationState,
tags: UIEventSource<Record<string, string>>, tags: UIEventSource<Record<string, string>>,
@ -1447,6 +1450,51 @@ export default class SpecialVisualizations {
) )
}, },
}, },
{
funcName: "giggity",
args: [
{
name: "giggityUrl",
required: true,
doc: "The URL of the giggity-XML",
},
],
docs: "Shows events that are happening based on a Giggity URL",
needsUrls: ["*"],
constr(
state: SpecialVisualizationState,
tagSource: UIEventSource<Record<string, string>>,
argument: string[],
feature: Feature,
layer: LayerConfig
): BaseUIElement {
const giggityUrl = argument[0]
return new SvelteUIElement(Giggity, { tags: tagSource, state, giggityUrl })
},
},
{
funcName: "gps_all_tags",
needsUrls: [],
docs: "Shows the current tags of the GPS-representing object, used for debugging",
args: [],
constr(
state: SpecialVisualizationState,
_: UIEventSource<Record<string, string>>,
argument: string[],
feature: Feature,
layer: LayerConfig
): BaseUIElement {
const tags = (<ThemeViewState>(
state
)).geolocation.currentUserLocation.features.map(
(features) => features[0].properties
)
return new SvelteUIElement(AllTagsPanel, {
state,
tags,
})
},
},
] ]
specialVisualizations.push(new AutoApplyButton(specialVisualizations)) specialVisualizations.push(new AutoApplyButton(specialVisualizations))

View file

@ -64,7 +64,7 @@
} }
} }
newPath.push(...toAdd) newPath.push(...toAdd)
console.log({ newPath }) console.log("Fused path ", path.join("."), "+", i,"+", subpartPath.join("."),"into",newPath.join("."))
return newPath return newPath
} }
@ -115,7 +115,7 @@
<!-- We need an array of values, so we use the typehint of the _parent_ element as field --> <!-- We need an array of values, so we use the typehint of the _parent_ element as field -->
{#each $currentValue as value, i} {#each $currentValue as value, i}
<div class="flex w-full"> <div class="flex w-full">
<SchemaBasedField {state} {schema} path={[...path, i]} /> <SchemaBasedField {state} {schema} path={fusePath(i, [])} />
<button <button
class="h-fit w-fit rounded-full border border-black p-1" class="h-fit w-fit rounded-full border border-black p-1"
on:click={() => { on:click={() => {
@ -143,7 +143,7 @@
{/if} {/if}
<div class="border border-black"> <div class="border border-black">
{#if isTagRenderingBlock} {#if isTagRenderingBlock}
<QuestionPreview {state} path={[...path, i]} {schema}> <QuestionPreview {state} path={fusePath(i, [])} {schema}>
<button <button
on:click={() => { on:click={() => {
del(i) del(i)
@ -191,7 +191,7 @@
<SchemaBasedMultiType {state} path={fusePath(i, [])} schema={schemaForMultitype()} /> <SchemaBasedMultiType {state} path={fusePath(i, [])} schema={schemaForMultitype()} />
{:else} {:else}
{#each subparts as subpart} {#each subparts as subpart}
<SchemaBasedInput {state} path={fusePath(i, subpart.path)} schema={subpart} /> <SchemaBasedInput {state} path={fusePath(i, [subpart.path.at(-1)])} schema={subpart} />
{/each} {/each}
{/if} {/if}
</div> </div>