forked from MapComplete/MapComplete
Studio: first working version for basic layer properties
This commit is contained in:
parent
5a49677d5a
commit
f18a2b9184
41 changed files with 4446 additions and 852 deletions
|
|
@ -10,7 +10,8 @@
|
|||
import TagRenderingConfig from "../../Models/ThemeConfig/TagRenderingConfig";
|
||||
import {onDestroy} from "svelte";
|
||||
import SchemaBasedInput from "./SchemaBasedInput.svelte";
|
||||
|
||||
import type {JsonSchemaType} from "./jsonSchema";
|
||||
import nmd from "nano-markdown"
|
||||
/**
|
||||
* If 'types' is defined: allow the user to pick one of the types to input.
|
||||
*/
|
||||
|
|
@ -18,45 +19,116 @@
|
|||
export let state: EditLayerState
|
||||
export let path: (string | number)[] = []
|
||||
export let schema: ConfigMeta
|
||||
let value = new UIEventSource<string>(undefined)
|
||||
const defaultOption = schema.hints.typesdefault ? Number(schema.hints.typesdefault) : undefined
|
||||
|
||||
const hasBooleanOption = (<JsonSchemaType[]>schema.type)?.findIndex(t => t["type"] === "boolean")
|
||||
const types = schema.hints.types.split(";")
|
||||
if (hasBooleanOption >= 0) {
|
||||
console.log(path.join("."), ": types are", types, ", boolean index is", hasBooleanOption)
|
||||
types.splice(hasBooleanOption)
|
||||
}
|
||||
|
||||
const configJson: QuestionableTagRenderingConfigJson = {
|
||||
id: "TYPE_OF:" + path.join("_"),
|
||||
question: "Which subcategory is needed?",
|
||||
questionHint: schema.description,
|
||||
mappings: schema.hints.types.split(";").map(opt => opt.trim()).filter(opt => opt.length > 0).map((opt, i) => ({
|
||||
questionHint: nmd(schema.description),
|
||||
mappings: types.map(opt => opt.trim()).filter(opt => opt.length > 0).map((opt, i) => ({
|
||||
if: "value=" + i,
|
||||
then: opt
|
||||
addExtraTags: ["direct="],
|
||||
then: opt + (i === defaultOption ? " (Default)" : "")
|
||||
}))
|
||||
}
|
||||
const config = new TagRenderingConfig(configJson, "config based on " + schema.path.join("."))
|
||||
let tags = new UIEventSource<Record<string, string>>({})
|
||||
|
||||
let chosenOption: number = undefined
|
||||
if (hasBooleanOption >= 0) {
|
||||
configJson.mappings.unshift(
|
||||
{
|
||||
if: "direct=true",
|
||||
then: "Yes " + (schema.hints.iftrue ?? ""),
|
||||
addExtraTags: ["value="]
|
||||
},
|
||||
{
|
||||
if: "direct=false",
|
||||
then: "No " + (schema.hints.iffalse ?? ""),
|
||||
addExtraTags: ["value="]
|
||||
}
|
||||
)
|
||||
}
|
||||
const config = new TagRenderingConfig(configJson, "config based on " + schema.path.join("."))
|
||||
|
||||
|
||||
const existingValue = state.getCurrentValueFor(path)
|
||||
console.log("Setting direct: ", hasBooleanOption, path.join("."), existingValue)
|
||||
if (hasBooleanOption >= 0 && (existingValue === true || existingValue === false)) {
|
||||
tags.setData({direct: "" + existingValue})
|
||||
} else if (existingValue) {
|
||||
// We found an existing value. Let's figure out what type it matches and select that one
|
||||
// We run over all possibilities and check what is required
|
||||
const possibleTypes = []
|
||||
outer: for (let i = 0; i < (<[]>schema.type).length; i++) {
|
||||
const type = schema.type[i];
|
||||
if (type.required) {
|
||||
for (const requiredAttribute of type.required) {
|
||||
if (existingValue[requiredAttribute] === undefined) {
|
||||
console.log(path.join("."), " does not have required field", requiredAttribute, " so it cannot be type ", type)
|
||||
// The 'existingValue' does _not_ have this required attribute, so it cannot be of this type
|
||||
continue outer
|
||||
}
|
||||
}
|
||||
possibleTypes.push(i)
|
||||
} else {
|
||||
possibleTypes.push(i)
|
||||
}
|
||||
}
|
||||
|
||||
if (possibleTypes.length > 0) {
|
||||
tags.setData({value: "" + possibleTypes[0]})
|
||||
}
|
||||
} else if (defaultOption !== undefined) {
|
||||
tags.setData({value: "" + defaultOption})
|
||||
}
|
||||
|
||||
if (hasBooleanOption >= 0) {
|
||||
|
||||
const directValue = tags.mapD(tags => {
|
||||
if(tags["value"]){
|
||||
return undefined
|
||||
}
|
||||
return tags["direct"] === "true";
|
||||
})
|
||||
onDestroy(state.register(path, directValue, true))
|
||||
}
|
||||
|
||||
let chosenOption: number = defaultOption
|
||||
let subSchemas: ConfigMeta[] = []
|
||||
onDestroy(tags.addCallback(tags => {
|
||||
chosenOption = Number(tags["value"])
|
||||
onDestroy(tags.addCallbackAndRun(tags => {
|
||||
chosenOption = tags["value"] ? Number(tags["value"]) : defaultOption
|
||||
const type = schema.type[chosenOption]
|
||||
const cleanPath = <string[]> path.filter(p => typeof p === "string")
|
||||
if (!type) {
|
||||
return
|
||||
}
|
||||
if (!type.properties) {
|
||||
return
|
||||
}
|
||||
const cleanPath = <string[]>path.filter(p => typeof p === "string")
|
||||
for (const crumble of Object.keys(type.properties)) {
|
||||
console.log("Searching entries for", [...cleanPath, crumble])
|
||||
subSchemas.push(...(state.getSchema([...cleanPath, crumble])))
|
||||
}
|
||||
}))
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<TagRenderingEditable {config} showQuestionIfUnknown={true} {state} {tags}/>
|
||||
</div>
|
||||
|
||||
{#if chosenOption !== undefined}
|
||||
<div class="pl-2 border-2 border-dashed border-gray-300 flex flex-col gap-y-2">
|
||||
{#each subSchemas as subschema}
|
||||
{JSON.stringify(subschema)}
|
||||
<SchemaBasedInput {state} schema={subschema} path={[...path]}></SchemaBasedInput>
|
||||
{/each}
|
||||
<div class="p-2 border-2 border-dashed border-gray-300 flex flex-col gap-y-2">
|
||||
<div>
|
||||
<TagRenderingEditable selectedElement={undefined} {config} showQuestionIfUnknown={true} {state} {tags}/>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if chosenOption !== undefined}
|
||||
{#each subSchemas as subschema}
|
||||
<SchemaBasedInput {state} schema={subschema}
|
||||
path={[...path, (subschema?.path?.at(-1) ?? "???")]}></SchemaBasedInput>
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue