Merge develop

This commit is contained in:
Pieter Vander Vennet 2023-12-03 04:44:59 +01:00
commit d959b6b40b
290 changed files with 37178 additions and 2200 deletions

View file

@ -10,13 +10,14 @@
export let info: { id: string; owner: number };
export let category: "layers" | "themes";
export let osmConnection: OsmConnection;
const dispatch = createEventDispatcher<{ layerSelected: string }>();
let displayName = UIEventSource.FromPromise(
osmConnection.getInformationAboutUser(info.owner)
).mapD((response) => response.display_name);
let selfId = osmConnection.userDetails.mapD((ud) => ud.uid);
function fetchIconDescription(layerId): any {
if (category === "themes") {
return AllKnownLayouts.allKnownLayouts.get(layerId).icon;
@ -24,7 +25,6 @@
return AllSharedLayers.getSharedLayersConfigs().get(layerId)?._layerIcon;
}
const dispatch = createEventDispatcher<{ layerSelected: string }>();
</script>
<NextButton clss="small" on:click={() => dispatch("layerSelected", info)}>
@ -33,12 +33,14 @@
</div>
<b class="px-1">{info.id}</b>
{#if info.owner && info.owner !== $selfId}
{#if displayName}
{#if $displayName}
(made by {$displayName}
{#if window.location.host.startsWith("127.0.0.1")}
- {info.owner}
{/if}
)
{:else }
({info.owner})
{/if}
{/if}
</NextButton>

View file

@ -9,7 +9,7 @@
import { Utils } from "../../Utils"
import type { ConversionMessage } from "../../Models/ThemeConfig/Conversion/Conversion"
import ErrorIndicatorForRegion from "./ErrorIndicatorForRegion.svelte"
import { ChevronRightIcon } from "@rgossiaux/svelte-heroicons/solid"
import { ChevronRightIcon, TrashIcon } from "@rgossiaux/svelte-heroicons/solid"
import SchemaBasedInput from "./SchemaBasedInput.svelte"
import FloatOver from "../Base/FloatOver.svelte"
import TagRenderingInput from "./TagRenderingInput.svelte"
@ -21,6 +21,7 @@
const layerSchema: ConfigMeta[] = <any>layerSchemaRaw
export let state: EditLayerState
export let backToStudio: () => void
let messages = state.messages
let hasErrors = messages.mapD(
(m: ConversionMessage[]) => m.filter((m) => m.level === "error").length
@ -72,6 +73,10 @@
})
let highlightedItem: UIEventSource<HighlightedTagRendering> = state.highlightedItem
function deleteLayer() {
state.delete()
backToStudio()
}
</script>
<div class="flex h-screen flex-col">
@ -113,6 +118,12 @@
</div>
<div class="flex flex-col" slot="content0">
<Region {state} configs={perRegion["Basic"]} />
<div class="mt-12">
<button on:click={() => deleteLayer()} class="small" >
<TrashIcon class="h-6 w-6"/> Delete this layer
</button>
</div>
</div>
<div slot="title1" class="flex">

View file

@ -107,6 +107,9 @@ export abstract class EditJsonState<T> {
return entry
}
public async delete(){
await this.server.delete(this.getId().data, this.category)
}
public getStoreFor<T>(path: ReadonlyArray<string | number>): UIEventSource<T | undefined> {
const key = path.join(".")
@ -294,16 +297,39 @@ export default class EditLayerState extends EditJsonState<LayerConfigJson> {
this.addMissingTagRenderingIds()
this.configuration.addCallbackAndRunD((layer) => {
if (layer.tagRenderings) {
function cleanArray(data: object, key: string): boolean{
if(!data){
return false
}
if (data[key]) {
// A bit of cleanup
const lBefore = layer.tagRenderings.length
const cleaned = Utils.NoNull(layer.tagRenderings)
const lBefore = data[key].length
const cleaned = Utils.NoNull(data[key])
if (cleaned.length != lBefore) {
layer.tagRenderings = cleaned
this.configuration.ping()
data[key] = cleaned
return true
}
}
return false
}
this.configuration.addCallbackAndRunD((layer) => {
let changed = cleanArray(layer, "tagRenderings") || cleanArray(layer, "pointRenderings")
for (const tr of layer.tagRenderings ?? []) {
if(typeof tr === "string"){
continue
}
const qtr = (<QuestionableTagRenderingConfigJson> tr)
if(qtr.freeform && Object.keys(qtr.freeform ).length === 0){
delete qtr.freeform
changed = true
}
}
if(changed){
this.configuration.ping()
}
})
}

View file

@ -64,7 +64,16 @@
}
}
newPath.push(...toAdd)
console.log("Fused path ", path.join("."), "+", i,"+", subpartPath.join("."),"into",newPath.join("."))
console.log(
"Fused path ",
path.join("."),
"+",
i,
"+",
subpartPath.join("."),
"into",
newPath.join(".")
)
return newPath
}

View file

@ -58,7 +58,14 @@ export default class StudioServer {
return undefined
}
}
async delete(id: string, category: "layers" | "themes") {
if (id === undefined || id === "") {
return
}
await fetch(this.urlFor(id, category), {
method: "DELETE"
})
}
async update(id: string, config: string, category: "layers" | "themes") {
if (id === undefined || id === "") {
return

View file

@ -3,104 +3,104 @@
* Little helper class to deal with choosing a builtin tagRendering or defining one yourself.
* Breaks the ideology that everything should be schema based
*/
import EditLayerState from "./EditLayerState";
import type { ConfigMeta } from "./configMeta";
import EditLayerState from "./EditLayerState"
import type { ConfigMeta } from "./configMeta"
import type {
MappingConfigJson,
QuestionableTagRenderingConfigJson
} from "../../Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson";
import TagRenderingConfig from "../../Models/ThemeConfig/TagRenderingConfig";
import TagRenderingEditable from "../Popup/TagRendering/TagRenderingEditable.svelte";
import { Store, UIEventSource } from "../../Logic/UIEventSource";
import * as questions from "../../assets/generated/layers/questions.json";
import MappingInput from "./MappingInput.svelte";
import { TrashIcon } from "@rgossiaux/svelte-heroicons/outline";
import questionableTagRenderingSchemaRaw from "../../assets/schemas/questionabletagrenderingconfigmeta.json";
import SchemaBasedField from "./SchemaBasedField.svelte";
import Region from "./Region.svelte";
import NextButton from "../Base/NextButton.svelte";
import { QuestionMarkCircleIcon } from "@rgossiaux/svelte-heroicons/solid";
import { LocalStorageSource } from "../../Logic/Web/LocalStorageSource";
import { onMount } from "svelte";
QuestionableTagRenderingConfigJson,
} from "../../Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson"
import TagRenderingConfig from "../../Models/ThemeConfig/TagRenderingConfig"
import TagRenderingEditable from "../Popup/TagRendering/TagRenderingEditable.svelte"
import { Store, UIEventSource } from "../../Logic/UIEventSource"
import * as questions from "../../assets/generated/layers/questions.json"
import MappingInput from "./MappingInput.svelte"
import { TrashIcon } from "@rgossiaux/svelte-heroicons/outline"
import questionableTagRenderingSchemaRaw from "../../assets/schemas/questionabletagrenderingconfigmeta.json"
import SchemaBasedField from "./SchemaBasedField.svelte"
import Region from "./Region.svelte"
import NextButton from "../Base/NextButton.svelte"
import { QuestionMarkCircleIcon } from "@rgossiaux/svelte-heroicons/solid"
import { LocalStorageSource } from "../../Logic/Web/LocalStorageSource"
import { onMount } from "svelte"
export let state: EditLayerState;
export let schema: ConfigMeta;
export let path: (string | number)[];
let expertMode = state.expertMode;
const store = state.getStoreFor(path);
let value = store.data;
export let state: EditLayerState
export let schema: ConfigMeta
export let path: (string | number)[]
let expertMode = state.expertMode
const store = state.getStoreFor(path)
let value = store.data
let hasSeenIntro = UIEventSource.asBoolean(
LocalStorageSource.Get("studio-seen-tagrendering-tutorial", "false")
);
)
onMount(() => {
if (!hasSeenIntro.data) {
state.showIntro.setData("tagrenderings");
hasSeenIntro.setData(true);
state.showIntro.setData("tagrenderings")
hasSeenIntro.setData(true)
}
});
})
/**
* Allows the theme builder to create 'writable' themes.
* Should only be enabled for 'tagrenderings' in the theme, if the source is OSM
*/
let allowQuestions: Store<boolean> = state.configuration.mapD(
(config) => path.at(0) === "tagRenderings" && config.source?.geoJson === undefined
);
)
let mappingsBuiltin: MappingConfigJson[] = [];
let perLabel: Record<string, MappingConfigJson> = {};
let mappingsBuiltin: MappingConfigJson[] = []
let perLabel: Record<string, MappingConfigJson> = {}
for (const tr of questions.tagRenderings) {
let description = tr["description"] ?? tr["question"] ?? "No description available";
description = description["en"] ?? description;
let description = tr["description"] ?? tr["question"] ?? "No description available"
description = description["en"] ?? description
if (tr["labels"]) {
const labels: string[] = tr["labels"];
const labels: string[] = tr["labels"]
for (const label of labels) {
let labelMapping: MappingConfigJson = perLabel[label];
let labelMapping: MappingConfigJson = perLabel[label]
if (!labelMapping) {
labelMapping = {
if: "value=" + label,
then: {
en: "Builtin collection <b>" + label + "</b>:"
}
};
perLabel[label] = labelMapping;
mappingsBuiltin.push(labelMapping);
en: "Builtin collection <b>" + label + "</b>:",
},
}
perLabel[label] = labelMapping
mappingsBuiltin.push(labelMapping)
}
labelMapping.then.en = labelMapping.then.en + "<div>" + description + "</div>";
labelMapping.then.en = labelMapping.then.en + "<div>" + description + "</div>"
}
}
mappingsBuiltin.push({
if: "value=" + tr["id"],
then: {
en: "Builtin <b>" + tr["id"] + "</b> <div class='subtle'>" + description + "</div>"
}
});
en: "Builtin <b>" + tr["id"] + "</b> <div class='subtle'>" + description + "</div>",
},
})
}
const configBuiltin = new TagRenderingConfig(<QuestionableTagRenderingConfigJson>{
question: "Which builtin element should be shown?",
mappings: mappingsBuiltin
});
mappings: mappingsBuiltin,
})
const tags = new UIEventSource({ value });
const tags = new UIEventSource({ value })
tags.addCallbackAndRunD((tgs) => {
store.setData(tgs["value"]);
});
store.setData(tgs["value"])
})
let mappings: UIEventSource<MappingConfigJson[]> = state.getStoreFor([...path, "mappings"]);
let mappings: UIEventSource<MappingConfigJson[]> = state.getStoreFor([...path, "mappings"])
const topLevelItems: Record<string, ConfigMeta> = {};
const topLevelItems: Record<string, ConfigMeta> = {}
for (const item of questionableTagRenderingSchemaRaw) {
if (item.path.length === 1) {
topLevelItems[item.path[0]] = <ConfigMeta>item;
topLevelItems[item.path[0]] = <ConfigMeta>item
}
}
function initMappings() {
if (mappings.data === undefined) {
mappings.setData([]);
mappings.setData([])
}
}
@ -113,28 +113,25 @@
"condition",
"metacondition",
"mappings",
"icon"
]);
const ignored = new Set(["labels", "description", "classes"]);
"icon",
])
const ignored = new Set(["labels", "description", "classes"])
const freeformSchemaAll = <ConfigMeta[]>(
questionableTagRenderingSchemaRaw.filter(
(schema) =>
schema.path.length == 2 &&
schema.path[0] === "freeform" &&
($allowQuestions)
(schema) => schema.path.length == 2 && schema.path[0] === "freeform" && $allowQuestions
)
);
)
let freeformSchema = $expertMode
? freeformSchemaAll
: freeformSchemaAll.filter((schema) => schema.hints?.group !== "expert");
: freeformSchemaAll.filter((schema) => schema.hints?.group !== "expert")
const missing: string[] = questionableTagRenderingSchemaRaw
.filter(
(schema) =>
schema.path.length >= 1 && !items.has(schema.path[0]) && !ignored.has(schema.path[0])
)
.map((schema) => schema.path.join("."));
console.log({ state });
.map((schema) => schema.path.join("."))
console.log({ state })
</script>
{#if typeof $store === "string"}