MapComplete/src/UI/Studio/SchemaBasedArray.svelte

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

131 lines
3.8 KiB
Svelte
Raw Normal View History

2023-06-16 02:36:11 +02:00
<script lang="ts">
import { EditJsonState } from "./EditLayerState"
2023-11-09 16:30:26 +01:00
import type { ConfigMeta } from "./configMeta"
import SchemaBasedField from "./SchemaBasedField.svelte"
import { TrashIcon } from "@babeard/svelte-heroicons/mini"
import ShowConversionMessage from "./ShowConversionMessage.svelte"
import Markdown from "../Base/Markdown.svelte"
import { Utils } from "../../Utils"
import type { QuestionableTagRenderingConfigJson } from "../../Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson"
import CollapsedTagRenderingPreview from "./CollapsedTagRenderingPreview.svelte"
import { Accordion } from "flowbite-svelte"
2023-11-09 16:30:26 +01:00
export let state: EditJsonState<any>
export let path: (string | number)[] = []
2023-11-09 16:30:26 +01:00
export let schema: ConfigMeta
schema = Utils.Clone(schema)
2023-11-09 16:30:26 +01:00
let title = schema.path.at(-1)
let singular = title
2023-08-23 11:11:53 +02:00
if (title?.endsWith("s")) {
2023-11-09 16:30:26 +01:00
singular = title.slice(0, title.length - 1)
2023-08-08 13:52:58 +02:00
}
2023-11-09 16:30:26 +01:00
let article = "a"
2023-08-23 11:11:53 +02:00
if (singular?.match(/^[aeoui]/)) {
2023-11-09 16:30:26 +01:00
article = "an"
2023-08-08 13:52:58 +02:00
}
2023-11-09 16:30:26 +01:00
const isTagRenderingBlock = path.length === 1 && path[0] === "tagRenderings"
if (isTagRenderingBlock) {
2023-11-09 16:30:26 +01:00
schema = { ...schema }
schema.description = undefined
}
const subparts: ConfigMeta[] = state
2023-11-09 16:30:26 +01:00
.getSchemaStartingWith(schema.path)
.filter((part) => part.path.length - 1 === schema.path.length)
let messages = state.messagesFor(path)
2023-11-09 16:30:26 +01:00
const currentValue = state.getStoreFor<(string | QuestionableTagRenderingConfigJson)[]>(path)
2023-11-09 16:30:26 +01:00
if (currentValue.data === undefined) {
currentValue.setData([])
}
function createItem(valueToSet?: string | QuestionableTagRenderingConfigJson) {
2023-11-09 16:30:26 +01:00
if (currentValue.data === undefined) {
currentValue.setData([])
2023-08-23 11:11:53 +02:00
}
currentValue.data.push(valueToSet)
currentValue.ping()
2023-11-09 16:30:26 +01:00
if (isTagRenderingBlock) {
state.highlightedItem.setData({ path: [...path, currentValue.data.length - 1], schema })
2023-11-05 12:05:00 +01:00
}
2023-08-08 13:52:58 +02:00
}
2023-06-20 01:32:24 +02:00
2023-08-08 13:52:58 +02:00
function fusePath(i: number, subpartPath: string[]): (string | number)[] {
2023-11-09 16:30:26 +01:00
const newPath = [...path, i]
const toAdd = [...subpartPath]
2023-08-08 13:52:58 +02:00
for (const part of path) {
if (toAdd[0] === part) {
2023-11-09 16:30:26 +01:00
toAdd.splice(0, 1)
} else {
break
2023-08-08 13:52:58 +02:00
}
}
2023-11-09 16:30:26 +01:00
newPath.push(...toAdd)
return newPath
2023-08-08 13:52:58 +02:00
}
2023-06-16 02:36:11 +02:00
2023-11-09 16:30:26 +01:00
function del(i: number) {
currentValue.data.splice(i, 1)
currentValue.ping()
}
2023-11-09 16:30:26 +01:00
2023-08-08 13:52:58 +02:00
</script>
2023-11-09 16:30:26 +01:00
<div class="pl-2">
2023-08-08 13:52:58 +02:00
<h3>{schema.path.at(-1)}</h3>
2023-08-08 13:52:58 +02:00
{#if subparts.length > 0}
2024-06-16 16:06:26 +02:00
<Markdown src={schema.description} />
2023-08-08 13:52:58 +02:00
{/if}
{#if $currentValue === undefined}
2023-11-09 16:30:26 +01:00
No array defined
{:else if $currentValue.length === 0}
2023-08-08 13:52:58 +02:00
No values are defined
{#if $messages.length > 0}
{#each $messages as message}
2023-11-09 16:30:26 +01:00
<ShowConversionMessage {message} />
{/each}
{/if}
2024-08-02 19:15:12 +02:00
{:else if subparts.length === 0}
2023-08-08 13:52:58 +02:00
<!-- We need an array of values, so we use the typehint of the _parent_ element as field -->
{#each $currentValue as value, i}
2023-08-08 13:52:58 +02:00
<div class="flex w-full">
2023-11-12 13:49:39 +01:00
<SchemaBasedField {state} {schema} path={fusePath(i, [])} />
2023-11-09 16:30:26 +01:00
<button
class="h-fit w-fit rounded-full border border-black p-1"
on:click={() => {
del(i)
}}
>
<TrashIcon class="h-4 w-4" />
2023-08-08 13:52:58 +02:00
</button>
</div>
{/each}
{:else}
<Accordion>
{#each $currentValue as value, i (value)}
<CollapsedTagRenderingPreview {state} {isTagRenderingBlock} {schema} {currentValue} {value} {i} {singular} path={fusePath(i, [])}/>
2023-08-08 13:52:58 +02:00
{/each}
</Accordion>
2023-08-08 13:52:58 +02:00
{/if}
2023-08-23 11:11:53 +02:00
<div class="flex">
<button on:click={() => createItem()}>Add {article} {singular}</button>
{#if path.length === 1 && path[0] === "tagRenderings"}
2023-11-09 16:30:26 +01:00
<button
on:click={() => {
createItem("images")
}}
>
Add a builtin tagRendering
</button>
2023-08-23 11:11:53 +02:00
{/if}
<slot name="extra-button" />
</div>
</div>