fix: expand enum type narrowing to forms

This commit is contained in:
Ruben Fiszel
2023-11-25 11:03:14 +01:00
parent ea888f5f78
commit 2b5a47db2e
4 changed files with 131 additions and 69 deletions
+16 -1
View File
@@ -28,6 +28,11 @@ export interface SchemaProperty {
contentEncoding?: 'base64'
enum?: string[]
}
min?: number
max?: number
currency?: string
currencyLocale?: string
multiselect?: boolean
customErrorMessage?: string
properties?: { [name: string]: SchemaProperty }
required?: string[]
@@ -38,6 +43,11 @@ export interface ModalSchemaProperty {
description: string
name: string
required: boolean
min?: number
max?: number
currency?: string
currencyLocale?: string
multiselect?: boolean
format?: string
pattern?: string
enum_?: string[]
@@ -60,7 +70,12 @@ export function modalToSchema(schema: ModalSchemaProperty): SchemaProperty {
format: schema.format,
customErrorMessage: schema.customErrorMessage,
properties: schema.schema?.properties,
required: schema.schema?.required
required: schema.schema?.required,
min: schema.min,
max: schema.max,
currency: schema.currency,
currencyLocale: schema.currencyLocale,
multiselect: schema.multiselect
}
}
export type Schema = {
@@ -16,6 +16,7 @@
import LightweightObjectResourceInput from './LightweightObjectResourceInput.svelte'
import DateTimeInput from './DateTimeInput.svelte'
import CurrencyInput from './apps/components/inputs/currency/CurrencyInput.svelte'
import Multiselect from 'svelte-multiselect'
export let css: ComponentCustomCSS<'schemaformcomponent'> | undefined = undefined
export let label: string = ''
@@ -37,6 +38,7 @@
type?: 'string' | 'number' | 'bytes' | 'object'
contentEncoding?: 'base64'
enum?: string[]
multiselect?: string[]
}
| undefined = undefined
export let displayHeader = true
@@ -226,73 +228,91 @@
{/if}
{:else if inputCat == 'list'}
<div class="w-full">
<div class="w-full">
{#if Array.isArray(value)}
{#each value ?? [] as v, i}
<div class="flex flex-row max-w-md mt-1 w-full">
{#if itemsType?.type == 'number'}
<input type="number" bind:value={v} />
{:else if itemsType?.type == 'string' && itemsType?.contentEncoding == 'base64'}
<input
type="file"
class="my-6"
on:change={(x) => fileChanged(x, (val) => (value[i] = val))}
multiple={false}
/>
{:else if Array.isArray(itemsType?.enum)}
<select
on:focus={(e) => {
dispatch('focus')
{#if Array.isArray(itemsType?.multiselect)}
<div class="items-start">
<Multiselect
bind:selected={value}
options={itemsType?.multiselect ?? []}
selectedOptionsDraggable={true}
/>
</div>
{:else if extra.multiselect}
<div class="items-start">
<Multiselect
bind:selected={value}
options={itemsType?.enum ?? []}
selectedOptionsDraggable={true}
/>
</div>
{:else}
<div class="w-full">
{#if Array.isArray(value)}
{#each value ?? [] as v, i}
<div class="flex flex-row max-w-md mt-1 w-full">
{#if itemsType?.type == 'number'}
<input type="number" bind:value={v} />
{:else if itemsType?.type == 'string' && itemsType?.contentEncoding == 'base64'}
<input
type="file"
class="my-6"
on:change={(x) => fileChanged(x, (val) => (value[i] = val))}
multiple={false}
/>
{:else if Array.isArray(itemsType?.enum)}
<select
on:focus={(e) => {
dispatch('focus')
}}
class="px-6"
bind:value={v}
>
{#each itemsType?.enum ?? [] as e}
<option>{e}</option>
{/each}
</select>
{:else}
<input type="text" bind:value={v} />
{/if}
<button
transition:fade|local={{ duration: 100 }}
class="rounded-full p-1 bg-surface-secondary duration-200 hover:bg-surface-hover ml-2"
aria-label="Clear"
on:click={() => {
value = value.filter((el) => el != v)
if (value.length == 0) {
value = undefined
}
}}
class="px-6"
bind:value={v}
>
{#each itemsType?.enum ?? [] as e}
<option>{e}</option>
{/each}
</select>
{:else}
<input type="text" bind:value={v} />
{/if}
<button
transition:fade|local={{ duration: 100 }}
class="rounded-full p-1 bg-surface-secondary duration-200 hover:bg-surface-hover ml-2"
aria-label="Clear"
on:click={() => {
value = value.filter((el) => el != v)
if (value.length == 0) {
value = undefined
}
}}
>
<X size={14} />
</button>
</div>
{/each}
{:else}
List is not an array
{/if}
</div>
<div class="flex my-2">
<Button
variant="border"
color="light"
size="sm"
btnClasses="mt-1"
on:click={() => {
if (value == undefined || !Array.isArray(value)) {
value = []
}
value = value.concat('')
}}
startIcon={{ icon: Plus }}
>
Add
</Button>
</div>
<span class="ml-2">
{(value ?? []).length} item{(value ?? []).length != 1 ? 's' : ''}
</span>
<X size={14} />
</button>
</div>
{/each}
{:else}
List is not an array
{/if}
</div>
<div class="flex my-2">
<Button
variant="border"
color="light"
size="sm"
btnClasses="mt-1"
on:click={() => {
if (value == undefined || !Array.isArray(value)) {
value = []
}
value = value.concat('')
}}
startIcon={{ icon: Plus }}
>
Add
</Button>
</div>
<span class="ml-2">
{(value ?? []).length} item{(value ?? []).length != 1 ? 's' : ''}
</span>
{/if}
</div>
{:else if inputCat == 'resource-object'}
<LightweightObjectResourceInput {format} bind:value />
@@ -57,9 +57,7 @@
}
</script>
<div
class={twMerge('w-full flex flex-col overflow-auto px-0.5 pb-2', largeGap ? 'gap-8' : 'gap-2')}
>
<div class={twMerge('w-full flex flex-col px-0.5 pb-2', largeGap ? 'gap-8' : 'gap-2')}>
{#each Object.keys(schema.properties ?? {}) as argName (argName)}
{#if typeof args == 'object' && schema?.properties[argName] && args}
<LightweightArgInput
@@ -22,6 +22,11 @@
contentEncoding: schema.contentEncoding,
format: schema.format,
enum_: schema.enum,
min: schema.min,
max: schema.max,
currency: schema.currency,
currencyLocale: schema.currencyLocale,
multiselect: schema.multiselect,
required,
schema:
schema.type == 'object'
@@ -55,6 +60,8 @@
import Drawer from './common/drawer/Drawer.svelte'
import ArrayTypeNarrowing from './ArrayTypeNarrowing.svelte'
import LightweightSchemaForm from './LightweightSchemaForm.svelte'
import NumberTypeNarrowing from './NumberTypeNarrowing.svelte'
import Label from './Label.svelte'
export let error = ''
export let editing = false
@@ -93,6 +100,11 @@
property.selectedType = DEFAULT_PROPERTY.selectedType
property.format = undefined
property.schema = undefined
property.min = undefined
property.max = undefined
property.currency = undefined
property.currencyLocale = undefined
property.multiselect = undefined
drawer.closeDrawer()
}
@@ -157,6 +169,11 @@
property.enum_ = undefined
property.pattern = undefined
property.default = undefined
property.min = undefined
property.max = undefined
property.currency = undefined
property.currencyLocale = undefined
property.multiselect = undefined
if (argType == 'array') {
property.items = { type: 'string' }
} else {
@@ -193,6 +210,7 @@
itemsType={property.items}
contentEncoding={property.contentEncoding}
format={property.format}
extra={property}
/>
<Toggle
options={{ right: 'Required' }}
@@ -222,6 +240,17 @@
/>
{:else if property.selectedType == 'array'}
<ArrayTypeNarrowing bind:itemsType={property.items} />
<div class="mt-4" />
<Label label="Display using multiselect">
<Toggle bind:checked={property.multiselect} />
</Label>
{:else if property.selectedType == 'number' || property.selectedType == 'integer'}
<NumberTypeNarrowing
bind:min={property.min}
bind:max={property.max}
bind:currency={property.currency}
bind:currencyLocale={property.currencyLocale}
/>
{:else if property.selectedType == 'object'}
<Tabs selected="custom-object">
<Tab value="custom-object">Custom Object</Tab>