mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-22 16:02:24 +00:00
fix: expand enum type narrowing to forms
This commit is contained in:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user