forked from MapComplete/MapComplete
Merge branch 'develop'
This commit is contained in:
commit
322f2cfd80
13 changed files with 276 additions and 62 deletions
|
@ -218,6 +218,14 @@
|
|||
}
|
||||
],
|
||||
"tagRenderings": [
|
||||
{"id":"sotm-events",
|
||||
"render": {
|
||||
"special": {
|
||||
"type": "giggity",
|
||||
"giggityUrl":"https://sotm.osmz.ru/sotmeu2023.xml"
|
||||
}
|
||||
}
|
||||
},
|
||||
"images",
|
||||
"level",
|
||||
{
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -579,10 +579,80 @@
|
|||
"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
12
package-lock.json
generated
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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,
|
||||
})
|
||||
|
|
|
@ -4,39 +4,11 @@ export class ThemeMetaTagging {
|
|||
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(/</g, "<")?.replace(/>/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"
|
||||
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(/</g,'<')?.replace(/>/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'
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
|
91
src/UI/BigComponents/Giggity.svelte
Normal file
91
src/UI/BigComponents/Giggity.svelte
Normal 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}
|
|
@ -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}
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue