forked from MapComplete/MapComplete
176 lines
5.6 KiB
Svelte
176 lines
5.6 KiB
Svelte
<script lang="ts">
|
|
|
|
import { UIEventSource } from "../../Logic/UIEventSource";
|
|
import type { ConfigMeta } from "./configMeta";
|
|
import TagRenderingEditable from "../Popup/TagRendering/TagRenderingEditable.svelte";
|
|
import TagRenderingConfig from "../../Models/ThemeConfig/TagRenderingConfig";
|
|
import nmd from "nano-markdown";
|
|
import type {
|
|
QuestionableTagRenderingConfigJson
|
|
} from "../../Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson";
|
|
import EditLayerState from "./EditLayerState";
|
|
import { onDestroy } from "svelte";
|
|
import type { JsonSchemaType } from "./jsonSchema";
|
|
import { ConfigMetaUtils } from "./configMeta.ts";
|
|
import ShowConversionMessage from "./ShowConversionMessage.svelte";
|
|
|
|
export let state: EditLayerState;
|
|
export let path: (string | number)[] = [];
|
|
export let schema: ConfigMeta;
|
|
export let startInEditModeIfUnset: boolean = schema.hints && !schema.hints.ifunset;
|
|
let value = new UIEventSource<string | any>(undefined);
|
|
|
|
const isTranslation = schema.hints?.typehint === "translation" || schema.hints?.typehint === "rendered" || ConfigMetaUtils.isTranslation(schema);
|
|
let type = schema.hints.typehint ?? "string";
|
|
|
|
let rendervalue = (schema.hints.inline ?? schema.path.join(".")) + (isTranslation ? " <b>{translated(value)}</b>" : " <b>{value}</b>");
|
|
|
|
if (schema.type === "boolean") {
|
|
rendervalue = undefined;
|
|
}
|
|
if (schema.hints.typehint === "tag" || schema.hints.typehint === "simple_tag") {
|
|
rendervalue = "{tags()}";
|
|
}
|
|
|
|
let helperArgs = schema.hints.typehelper?.split(",");
|
|
let inline = schema.hints.inline !== undefined;
|
|
if (isTranslation) {
|
|
type = "translation";
|
|
if (schema.hints.inline) {
|
|
const inlineValue = schema.hints.inline;
|
|
rendervalue = inlineValue;
|
|
inline = false;
|
|
helperArgs = [inlineValue.substring(0, inlineValue.indexOf("{")), inlineValue.substring(inlineValue.indexOf("}") + 1)];
|
|
}
|
|
}
|
|
if (type.endsWith("[]")) {
|
|
type = type.substring(0, type.length - 2);
|
|
}
|
|
|
|
const configJson: QuestionableTagRenderingConfigJson = {
|
|
id: path.join("_"),
|
|
render: rendervalue,
|
|
question: schema.hints.question,
|
|
questionHint: nmd(schema.description),
|
|
freeform: schema.type === "boolean" ? undefined : {
|
|
key: "value",
|
|
type,
|
|
inline,
|
|
helperArgs
|
|
}
|
|
};
|
|
|
|
if (schema.hints.default) {
|
|
configJson.mappings = [{
|
|
if: "value=", // We leave this blank
|
|
then: path.at(-1) + " is not set. The default value <b>" + schema.hints.default + "</b> will be used. " + (schema.hints.ifunset ?? "")
|
|
}];
|
|
} else if (!schema.required) {
|
|
configJson.mappings = [{
|
|
if: "value=",
|
|
then: path.at(-1) + " is not set. " + (schema.hints.ifunset ?? "")
|
|
}];
|
|
}
|
|
|
|
function mightBeBoolean(type: undefined | JsonSchemaType): boolean {
|
|
if (type === undefined) {
|
|
return false;
|
|
}
|
|
if (type["type"]) {
|
|
type = type["type"];
|
|
}
|
|
if (type === "boolean") {
|
|
return true;
|
|
}
|
|
if (!Array.isArray(type)) {
|
|
return false;
|
|
}
|
|
|
|
return type.some(t => mightBeBoolean(t));
|
|
}
|
|
|
|
if (mightBeBoolean(schema.type)) {
|
|
configJson.mappings = configJson.mappings ?? [];
|
|
configJson.mappings.push(
|
|
{
|
|
if: "value=true",
|
|
then: schema.hints?.iftrue ?? "Yes"
|
|
},
|
|
{
|
|
if: "value=false",
|
|
then: schema.hints?.iffalse ?? "No"
|
|
}
|
|
);
|
|
}
|
|
|
|
if (schema.hints.suggestions) {
|
|
if (!configJson.mappings) {
|
|
configJson.mappings = [];
|
|
}
|
|
configJson.mappings.push(...schema.hints.suggestions);
|
|
}
|
|
let config: TagRenderingConfig;
|
|
let err: string = undefined;
|
|
let messages = state.messagesFor(path);
|
|
try {
|
|
config = new TagRenderingConfig(configJson, "config based on " + schema.path.join("."));
|
|
} catch (e) {
|
|
console.error(e, config);
|
|
err = path.join(".") + " " + e;
|
|
}
|
|
let startValue = state.getCurrentValueFor(path);
|
|
let startInEditMode = !startValue && startInEditModeIfUnset;
|
|
const tags = new UIEventSource<Record<string, string>>({ value: startValue });
|
|
try {
|
|
onDestroy(state.register(path, tags.map(tgs => {
|
|
const v = tgs["value"];
|
|
if (typeof v !== "string") {
|
|
return { ...v };
|
|
}
|
|
if (schema.type === "boolan") {
|
|
return v === "true" || v === "yes" || v === "1";
|
|
}
|
|
if (mightBeBoolean(schema.type)) {
|
|
if (v === "true" || v === "yes" || v === "1") {
|
|
return true;
|
|
}
|
|
if (v === "false" || v === "no" || v === "0") {
|
|
return false;
|
|
}
|
|
}
|
|
if (schema.type === "number") {
|
|
if (v === "") {
|
|
return undefined;
|
|
}
|
|
return Number(v);
|
|
}
|
|
if (isTranslation && typeof v === "string") {
|
|
if (v === "") {
|
|
return {};
|
|
}
|
|
return JSON.parse(v);
|
|
}
|
|
return v;
|
|
}), isTranslation));
|
|
} catch (e) {
|
|
console.error("Could not register", path, "due to", e);
|
|
}
|
|
</script>
|
|
|
|
{#if err !== undefined}
|
|
<span class="alert">{err}</span>
|
|
{:else}
|
|
<div class="w-full flex flex-col">
|
|
<TagRenderingEditable editMode={startInEditMode} {config} selectedElement={undefined} showQuestionIfUnknown={true}
|
|
{state} {tags} />
|
|
{#if $messages.length > 0}
|
|
{#each $messages as message}
|
|
<ShowConversionMessage {message} />
|
|
{/each}
|
|
{/if}
|
|
{#if window.location.hostname === "127.0.0.1"}
|
|
<span class="subtle" on:click={() => console.log(schema)}>SchemaBasedField <b>{path.join(".")}</b> <span class="cursor-pointer"
|
|
on:click={() => console.log(schema)}>{schema.hints.typehint}</span> Group: {schema.hints.group}</span>
|
|
{/if}
|
|
</div>
|
|
{/if}
|