2023-06-16 02:36:11 +02:00
< script lang = "ts" >
2023-11-09 16:30:26 +01:00
import EditLayerState from "./EditLayerState"
import type { ConfigMeta } from "./configMeta"
import { UIEventSource } from "../../Logic/UIEventSource"
import SchemaBasedInput from "./SchemaBasedInput.svelte"
import SchemaBasedField from "./SchemaBasedField.svelte"
import { TrashIcon } from "@babeard/svelte-heroicons/mini"
import QuestionPreview from "./QuestionPreview.svelte"
import SchemaBasedMultiType from "./SchemaBasedMultiType.svelte"
import ShowConversionMessage from "./ShowConversionMessage.svelte"
2024-04-27 22:44:35 +02:00
import Markdown from "../Base/Markdown.svelte"
2024-06-19 00:29:19 +02:00
import AccordionSingle from "../Flowbite/AccordionSingle.svelte"
2024-06-26 11:57:18 +02:00
import Icon from "../Map/Icon.svelte"
import Tr from "../Base/Tr.svelte"
import Translations from "../i18n/Translations"
2023-11-09 16:30:26 +01:00
export let state: EditLayerState
export let schema: ConfigMeta
let title = schema.path.at(-1)
2024-06-26 11:57:18 +02:00
console.log(">>>", schema)
2023-11-09 16:30:26 +01:00
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
export let path: (string | number)[] = []
const isTagRenderingBlock = path.length === 1 & & path[0] === "tagRenderings"
2023-06-18 00:44:57 +02:00
2023-10-25 00:03:51 +02:00
if (isTagRenderingBlock) {
2023-11-09 16:30:26 +01:00
schema = { ... schema }
schema.description = undefined
2023-10-25 00:03:51 +02:00
}
2024-04-28 00:00:28 +02:00
const subparts: ConfigMeta[] = state
2023-11-09 16:30:26 +01:00
.getSchemaStartingWith(schema.path)
.filter((part) => part.path.length - 1 === schema.path.length)
2023-11-03 02:04:42 +01:00
let messages = state.messagesFor(path)
2023-11-09 16:30:26 +01:00
const currentValue: UIEventSource< any [ ] > = state.getStoreFor(path)
if (currentValue.data === undefined) {
2023-11-09 15:42:15 +01:00
currentValue.setData([])
}
2023-06-18 00:44:57 +02:00
2023-08-23 11:11:53 +02:00
function createItem(valueToSet?: any) {
2023-11-09 16:30:26 +01:00
if (currentValue.data === undefined) {
2023-11-09 15:42:15 +01:00
currentValue.setData([])
2023-08-23 11:11:53 +02:00
}
2023-11-09 15:42:15 +01: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 {
2023-11-09 15:42:15 +01:00
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-10-30 13:45:44 +01:00
function schemaForMultitype() {
2023-11-09 16:30:26 +01:00
const sch = { ... schema }
2023-10-30 13:45:44 +01:00
sch.hints.typehint = undefined
return sch
}
2023-11-09 16:30:26 +01:00
function del(i: number) {
2023-11-09 15:42:15 +01:00
currentValue.data.splice(i, 1)
currentValue.ping()
}
2023-11-09 16:30:26 +01:00
2023-11-09 15:42:15 +01:00
function swap(i: number, j: number) {
const x = currentValue.data[i]
2023-11-09 16:30:26 +01:00
currentValue.data[i] = currentValue.data[j]
2023-11-09 15:42:15 +01:00
currentValue.data[j] = x
currentValue.ping()
}
2023-11-09 16:30:26 +01:00
function moveTo(source: number, target: number) {
2023-11-09 15:42:15 +01:00
const x = currentValue.data[source]
currentValue.data.splice(source, 1)
currentValue.data.splice(target, 0, x)
currentValue.ping()
}
2024-06-26 11:57:18 +02:00
2024-07-16 23:06:26 +02:00
function genTitle(value: any, singular: string, i: number): Translation {
try {
if (schema.hints.title) {
const v = Function("value", "return " + schema.hints.title)(value)
return Translations.T(v)
}
} catch (e) {
console.log("Warning: could not translate a title for " + `${ singular } ${ i } with function ` + schema.hints.title + " and value " + JSON.stringify(value))
2024-06-26 11:57:18 +02:00
}
2024-07-16 23:06:26 +02:00
return Translations.T(`${ singular } ${ i } `)
2024-06-26 11:57:18 +02:00
}
2024-07-09 13:42:08 +02:00
let genIconF: (x: any) => { icon : string ; color : string } = < any > (
Function("value", "return " + schema.hints.icon)
)
2024-06-26 11:57:18 +02:00
console.log("Icon lambda is", schema.hints.icon, path, genIconF("test"))
function genIcon(value: any): string {
return genIconF(value)?.icon
}
function genColor(value: any): string {
if (!schema.hints.icon) {
return undefined
}
return genIconF(value)?.color
}
2023-08-08 13:52:58 +02:00
< / script >
2023-11-09 16:30:26 +01:00
2023-06-18 00:44:57 +02:00
< div class = "pl-2" >
2023-08-08 13:52:58 +02:00
< h3 > { schema . path . at ( - 1 )} </ h3 >
2023-06-18 00:44:57 +02:00
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 }
2023-11-09 15:42:15 +01:00
{ #if $currentValue === undefined }
2023-11-09 16:30:26 +01:00
No array defined
2023-11-09 15:42:15 +01:00
{ :else if $currentValue . length === 0 }
2023-08-08 13:52:58 +02:00
No values are defined
2023-11-03 02:04:42 +01:00
{ #if $messages . length > 0 }
{ #each $messages as message }
2023-11-09 16:30:26 +01:00
< ShowConversionMessage { message } />
2023-11-03 02:04:42 +01:00
{ /each }
{ /if }
2023-08-08 13:52:58 +02:00
{ :else if subparts . length === 0 }
<!-- We need an array of values, so we use the typehint of the _parent_ element as field -->
2023-11-09 15:42:15 +01:00
{ #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 }
2023-11-09 15:42:15 +01:00
{ #each $currentValue as value , i }
2024-06-26 11:57:18 +02:00
< AccordionSingle expanded = { false } >
2024-06-19 00:29:19 +02:00
< span slot = "header" >
{ #if ! isTagRenderingBlock }
< div class = "flex items-center justify-between" >
2024-06-26 11:57:18 +02:00
< h3 class = "m-0 flex" >
{ #if schema . hints . icon }
< Icon clss = "w-6 h-6" icon = { genIcon ( value )} color= { genColor ( value )} />
{ /if }
2024-07-09 13:42:08 +02:00
{ singular }
{ i }
2024-06-26 11:57:18 +02:00
{ #if schema . hints . title }
< div class = "subtle ml-2" >
2024-07-16 23:06:26 +02:00
< Tr t = { genTitle ( value , singular , i )} / >
2024-06-26 11:57:18 +02:00
< / div >
2024-07-09 13:42:08 +02:00
{ /if }
2024-06-26 11:57:18 +02:00
< / h3 >
2024-06-19 00:29:19 +02:00
< button
class="h-fit w-fit rounded-full border border-black p-1"
on:click={() => {
del(i)
}}
>
< TrashIcon class = "h-4 w-4" / >
< / button >
< / div >
2024-07-09 13:42:08 +02:00
{ :else if typeof value === "string" }
2024-06-26 11:57:18 +02:00
Builtin: < b > { value } </ b >
2024-07-09 13:42:08 +02:00
{ : else }
2024-07-16 23:06:26 +02:00
< Tr cls = "font-bold" t = { Translations . T ( value ? . question ?? value ? . render )} / >
2024-06-19 00:29:19 +02:00
{ /if }
< / span >
< div class = "normal-background p-2" >
2024-06-20 04:21:29 +02:00
{ #if isTagRenderingBlock }
< QuestionPreview { state } path = { fusePath ( i , [])} { schema } >
2023-11-09 16:30:26 +01:00
< button
on:click={() => {
2024-06-20 04:21:29 +02:00
del(i)
2023-11-09 16:30:26 +01:00
}}
>
2024-06-20 04:21:29 +02:00
< TrashIcon class = "h-4 w-4" / >
Delete this question
2023-10-25 00:03:51 +02:00
< / button >
2024-06-19 00:29:19 +02:00
2024-06-20 04:21:29 +02:00
{ #if i > 0 }
< button
on:click={() => {
moveTo(i, 0)
}}
>
Move to front
< / button >
< button
on:click={() => {
swap(i, i - 1)
}}
>
Move up
< / button >
{ /if }
{ #if i + 1 < $currentValue . length }
< button
on:click={() => {
swap(i, i + 1)
}}
>
Move down
< / button >
< button
on:click={() => {
moveTo(i, $currentValue.length - 1)
}}
>
Move to back
< / button >
{ /if }
< / QuestionPreview >
{ :else if schema . hints . types }
< SchemaBasedMultiType { state } path = { fusePath ( i , [])} schema= { schemaForMultitype ()} />
{ : else }
{ #each subparts as subpart }
< SchemaBasedInput
{ state }
path={ fusePath ( i , [ subpart . path . at ( - 1 )])}
schema={ subpart }
/>
{ /each }
{ /if }
2024-06-19 00:29:19 +02:00
< / div >
< / AccordionSingle >
2023-08-08 13:52:58 +02:00
{ /each }
{ /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 >
2023-06-18 00:44:57 +02:00
< / div >