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": [
{"id":"sotm-events",
"render": {
"special": {
"type": "giggity",
"giggityUrl":"https://sotm.osmz.ru/sotmeu2023.xml"
}
}
},
"images",
"level",
{

View file

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

View file

@ -579,11 +579,81 @@
"enableImproveAccuracy": true,
"enableRelocation": false
},
"pointRendering": [],
"lineRendering": [
{}
]
"pointRendering": [
{
"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
}
}

12
package-lock.json generated
View file

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

View file

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

View file

@ -26,7 +26,12 @@ export class LastClickFeatureSource implements WritableFeatureSource {
for (let i = 0; i < (layer.presets ?? []).length; i++) {
const preset = layer.presets[i]
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,
includeBadges: false,
})

View file

@ -1,42 +1,14 @@
import { Utils } from "../../Utils"
/** This code is autogenerated - do not edit. Edit ./assets/layers/usersettings/usersettings.json instead */
export class ThemeMetaTagging {
public static readonly themeName = "usersettings"
public static readonly themeName = "usersettings"
public metaTaggging_for_usersettings(feat: { properties: Record<string, string> }) {
Utils.AddLazyProperty(feat.properties, "_mastodon_candidate_md", () =>
feat.properties._description
.match(/\[[^\]]*\]\((.*(mastodon|en.osm.town).*)\).*/)
?.at(1)
)
Utils.AddLazyProperty(
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"
}
}
public metaTaggging_for_usersettings(feat: {properties: Record<string, string>}) {
Utils.AddLazyProperty(feat.properties, '_mastodon_candidate_md', () => feat.properties._description.match(/\[[^\]]*\]\((.*(mastodon|en.osm.town).*)\).*/)?.at(1) )
Utils.AddLazyProperty(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 (!Constants.priviliged_layers.find((x) => x == json.id)) {
context.err(
@ -1377,6 +1386,7 @@ export class ValidateLayer extends Conversion<
context.err("Could not parse layer due to:" + e)
return undefined
}
for (let i = 0; i < (layerConfig.calculatedTags ?? []).length; i++) {
const [_, code, __] = layerConfig.calculatedTags[i]
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
})
)
let knownTagRenderings = layer.tagRenderings
.filter(config => (config.condition?.matchesProperties($tags) ?? true) && (config.metacondition?.matchesProperties({ ...$tags, ..._metatags } ?? true)
&& config.IsKnown($tags)))
</script>
{#if $tags._deleted === "yes"}
@ -29,9 +34,7 @@
</button>
{:else}
<div class="flex h-full flex-col gap-y-2 overflow-y-auto p-1 px-2">
{#each layer.tagRenderings as config (config.id)}
{#if (config.condition?.matchesProperties($tags) ?? true) && config.metacondition?.matchesProperties({ ...$tags, ..._metatags } ?? true)}
{#if config.IsKnown($tags)}
{#each knownTagRenderings as config (config.id)}
<TagRenderingEditable
{tags}
{config}
@ -39,9 +42,8 @@
{selectedElement}
{layer}
{highlightedRendering}
clss={knownTagRenderings.length === 1 ? "h-full" : "tr-length-"+knownTagRenderings.length}
/>
{/if}
{/if}
{/each}
</div>
{/if}

View file

@ -21,7 +21,7 @@
export let editingEnabled: Store<boolean> | undefined = state?.featureSwitchUserbadge
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
*/
@ -71,7 +71,7 @@
}
</script>
<div bind:this={htmlElem}>
<div bind:this={htmlElem} class={clss}>
{#if config.question && (!editingEnabled || $editingEnabled)}
{#if editMode}
<TagRenderingQuestion {config} {tags} {selectedElement} {state} {layer}>
@ -106,7 +106,7 @@
</div>
{/if}
{: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} />
</div>
{/if}

View file

@ -76,6 +76,8 @@ import StarsBarIcon from "./Reviews/StarsBarIcon.svelte"
import ReviewForm from "./Reviews/ReviewForm.svelte"
import Questionbox from "./Popup/TagRendering/Questionbox.svelte"
import { TagUtils } from "../Logic/Tags/TagUtils"
import Giggity from "./BigComponents/Giggity.svelte"
import ThemeViewState from "../Models/ThemeViewState"
class NearbyImageVis implements SpecialVisualization {
// 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"
funcName = "nearby_images"
needsUrls = NearbyImagesSearch.apiUrls
constr(
state: SpecialVisualizationState,
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))

View file

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