fix(frontend): make resource a separate top-level type in schema editor for clarity
This commit is contained in:
@@ -220,15 +220,12 @@
|
||||
|
||||
function computeSelected(property: any) {
|
||||
if (!opened) return ''
|
||||
return property.type !== 'object'
|
||||
? property.type
|
||||
: property.format === 'resource-s3_object'
|
||||
? 'S3'
|
||||
: property.format?.startsWith('dynselect-')
|
||||
? 'dynselect'
|
||||
: property.oneOf && property.oneOf.length >= 2
|
||||
? 'oneOf'
|
||||
: 'object'
|
||||
if (property.type !== 'object') return property.type
|
||||
if (property.format === 'resource-s3_object') return 'S3'
|
||||
if (property.format?.startsWith('dynselect-')) return 'dynselect'
|
||||
if (property.oneOf && property.oneOf.length >= 2) return 'oneOf'
|
||||
if (property.format?.startsWith('resource-')) return 'resource'
|
||||
return 'object'
|
||||
}
|
||||
|
||||
export function openField(key: string) {
|
||||
@@ -359,10 +356,11 @@
|
||||
['Number', 'number'],
|
||||
['Integer', 'integer'],
|
||||
['Object', 'object'],
|
||||
['Resource', 'resource'],
|
||||
['OneOf', 'oneOf'],
|
||||
['Array', 'array'],
|
||||
['Boolean', 'boolean'],
|
||||
['S3 Object', 'S3']
|
||||
['S3', 'S3']
|
||||
]
|
||||
if (showDynSelectOpt) {
|
||||
typeOptions.push(['DynSelect', 'dynselect'])
|
||||
@@ -680,6 +678,7 @@
|
||||
bind:selected={
|
||||
() => computeSelected(schema.properties[opened ?? '']),
|
||||
(v) => {
|
||||
const isResource = v == 'resource'
|
||||
const isS3 = v == 'S3'
|
||||
const isOneOf = v == 'oneOf'
|
||||
const isDynSelect = v == 'dynselect'
|
||||
@@ -700,13 +699,18 @@
|
||||
nullable: undefined,
|
||||
required: undefined
|
||||
}
|
||||
|
||||
if (isS3) {
|
||||
schema.properties[argName] = {
|
||||
...emptyProperty,
|
||||
type: 'object',
|
||||
format: 'resource-s3_object'
|
||||
}
|
||||
} else if (isResource) {
|
||||
schema.properties[argName] = {
|
||||
...emptyProperty,
|
||||
type: 'object',
|
||||
format: 'resource-'
|
||||
}
|
||||
} else if (isDynSelect) {
|
||||
const functionName = argName.replace(/\s+/g, '_')
|
||||
schema.properties[argName] = {
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import ResourceTypePicker from './ResourceTypePicker.svelte'
|
||||
|
||||
export let format: string | undefined
|
||||
|
||||
let resource: string | undefined = format?.startsWith('resource-')
|
||||
? format.substring('resource-'.length)
|
||||
: undefined
|
||||
const dispatch = createEventDispatcher()
|
||||
</script>
|
||||
|
||||
<ResourceTypePicker
|
||||
on:click={(e) => {
|
||||
resource = e.detail
|
||||
format = resource != undefined ? `resource-${resource}` : undefined
|
||||
dispatch('change', format)
|
||||
}}
|
||||
value={resource}
|
||||
nonePickable={true}
|
||||
/>
|
||||
22
frontend/src/lib/components/ResourceNarrowing.svelte
Normal file
22
frontend/src/lib/components/ResourceNarrowing.svelte
Normal file
@@ -0,0 +1,22 @@
|
||||
<script lang="ts">
|
||||
import ResourceTypePicker from './ResourceTypePicker.svelte'
|
||||
|
||||
interface Props {
|
||||
format: string | undefined
|
||||
}
|
||||
|
||||
let { format = $bindable() }: Props = $props()
|
||||
|
||||
let resource: string | undefined = $state(
|
||||
format?.startsWith('resource-') ? format.substring('resource-'.length) : undefined
|
||||
)
|
||||
</script>
|
||||
|
||||
<ResourceTypePicker
|
||||
on:click={(e) => {
|
||||
resource = e.detail
|
||||
format = `resource-${resource ?? ''}`
|
||||
}}
|
||||
value={resource}
|
||||
nonePickable={true}
|
||||
/>
|
||||
@@ -5,8 +5,6 @@
|
||||
import { workspaceStore } from '$lib/stores'
|
||||
import IconedResourceType from './IconedResourceType.svelte'
|
||||
import { Button, ClearableInput } from './common'
|
||||
import Popover from './meltComponents/Popover.svelte'
|
||||
import { offset, flip, shift } from 'svelte-floating-ui/dom'
|
||||
import Label from './Label.svelte'
|
||||
import Tooltip from './Tooltip.svelte'
|
||||
import Badge from './common/badge/Badge.svelte'
|
||||
@@ -46,84 +44,61 @@
|
||||
)
|
||||
</script>
|
||||
|
||||
<Label label="Resource type" class="w-full col-span-2">
|
||||
<Label label="Resource type" class="w-full mb-4">
|
||||
{#snippet header()}
|
||||
<Tooltip light small>Select a resource type to narrow down the object type.</Tooltip>
|
||||
{/snippet}
|
||||
|
||||
{#snippet action()}
|
||||
<div class="flex flex-row gap-1">
|
||||
<Button
|
||||
size="xs"
|
||||
color="light"
|
||||
on:click={() => onClick(undefined)}
|
||||
disabled={notPickable || value === undefined}
|
||||
>
|
||||
Clear
|
||||
</Button>
|
||||
<Popover
|
||||
floatingConfig={{
|
||||
strategy: 'fixed',
|
||||
placement: 'left-end',
|
||||
middleware: [offset(8), flip(), shift()]
|
||||
}}
|
||||
contentClasses="flex flex-col gap-2 h-full p-4 max-h-[40vh] w-[500px]"
|
||||
>
|
||||
{#snippet trigger()}
|
||||
<Button nonCaptureEvent size="xs" color="dark">Select resource type</Button>
|
||||
{/snippet}
|
||||
{#snippet content({ close })}
|
||||
<ClearableInput bind:value={search} placeholder="Search resource..." />
|
||||
|
||||
<div class="overflow-y-scroll h-full">
|
||||
<div
|
||||
class="grid sm:grid-cols-2 md:grid-cols-3 gap-x-2 gap-y-1 items-center overflow-x-hidden"
|
||||
>
|
||||
{#if nonePickable && search === ''}
|
||||
{@const isPicked = value === undefined}
|
||||
<Button
|
||||
size="sm"
|
||||
variant="border"
|
||||
color={isPicked ? 'blue' : 'dark'}
|
||||
btnClasses={isPicked ? '!border-2' : 'm-[1px]'}
|
||||
disabled={notPickable}
|
||||
on:click={() => {
|
||||
onClick(undefined)
|
||||
close()
|
||||
}}
|
||||
>
|
||||
None
|
||||
</Button>
|
||||
{/if}
|
||||
{#each filteredResources as r}
|
||||
{@const isPicked = value === r}
|
||||
<Button
|
||||
size="sm"
|
||||
variant="border"
|
||||
color={isPicked ? 'blue' : 'light'}
|
||||
btnClasses={isPicked ? '!border-2' : 'm-[1px]'}
|
||||
disabled={notPickable}
|
||||
on:click={() => {
|
||||
onClick(r)
|
||||
close()
|
||||
}}
|
||||
>
|
||||
<IconedResourceType name={r} after={true} width="20px" height="20px" />
|
||||
</Button>
|
||||
{/each}
|
||||
|
||||
{#if filteredResources.length === 0 && search !== ''}
|
||||
<div class="text-tertiary text-sm">No resources found</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/snippet}
|
||||
</Popover>
|
||||
<div class="flex flex-row items-center w-full justify-between">
|
||||
<Badge color={!value ? 'gray' : 'blue'}>
|
||||
{value ?? 'None'}
|
||||
</Badge>
|
||||
</div>
|
||||
{/snippet}
|
||||
<div class="flex flex-row items-center w-full justify-between">
|
||||
<Badge color={!value ? 'gray' : 'blue'}>
|
||||
{value ?? 'None'}
|
||||
</Badge>
|
||||
|
||||
<div class="mt-2">
|
||||
<ClearableInput bind:value={search} placeholder="Search resource..." />
|
||||
|
||||
<div class="overflow-y-scroll max-h-[330px] h-full mt-1">
|
||||
<div
|
||||
class="grid sm:grid-cols-2 md:grid-cols-3 gap-x-2 gap-y-1 items-center overflow-x-hidden"
|
||||
>
|
||||
{#if nonePickable && search === ''}
|
||||
{@const isPicked = value === undefined}
|
||||
<Button
|
||||
size="sm"
|
||||
variant="border"
|
||||
color={isPicked ? 'blue' : 'light'}
|
||||
btnClasses={isPicked ? '!border-2' : 'm-[1px]'}
|
||||
disabled={notPickable}
|
||||
on:click={() => {
|
||||
onClick(undefined)
|
||||
close()
|
||||
}}
|
||||
>
|
||||
None
|
||||
</Button>
|
||||
{/if}
|
||||
{#each filteredResources as r}
|
||||
{@const isPicked = value === r}
|
||||
<Button
|
||||
size="sm"
|
||||
variant="border"
|
||||
color={isPicked ? 'blue' : 'light'}
|
||||
btnClasses={isPicked ? '!border-2' : 'm-[1px]'}
|
||||
disabled={notPickable}
|
||||
on:click={() => {
|
||||
onClick(r)
|
||||
close()
|
||||
}}
|
||||
>
|
||||
<IconedResourceType name={r} after={true} width="20px" height="20px" />
|
||||
</Button>
|
||||
{/each}
|
||||
|
||||
{#if filteredResources.length === 0 && search !== ''}
|
||||
<div class="text-tertiary text-sm">No resources found</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Label>
|
||||
|
||||
@@ -2,14 +2,24 @@
|
||||
import type { TabsContext } from '$lib/components/apps/editor/settingsPanel/inputEditor/tabs.svelte'
|
||||
import { getContext } from 'svelte'
|
||||
|
||||
export let value: string
|
||||
export let alwaysMounted: boolean = false
|
||||
export let style = ''
|
||||
interface Props {
|
||||
value: string
|
||||
alwaysMounted?: boolean
|
||||
style?: string
|
||||
values?: string[] | undefined
|
||||
class?: string
|
||||
children?: import('svelte').Snippet
|
||||
}
|
||||
|
||||
export let values: string[] | undefined = undefined
|
||||
let {
|
||||
value,
|
||||
alwaysMounted = false,
|
||||
style = '',
|
||||
values = undefined,
|
||||
class: clazz = '',
|
||||
children
|
||||
}: Props = $props()
|
||||
|
||||
let clazz: string = ''
|
||||
export { clazz as class }
|
||||
const { selected } = getContext<TabsContext>('Tabs')
|
||||
</script>
|
||||
|
||||
@@ -18,6 +28,6 @@
|
||||
class={`${clazz} ${value === $selected || values?.includes($selected) ? 'visible' : 'hidden'}`}
|
||||
{style}
|
||||
>
|
||||
<slot />
|
||||
{@render children?.()}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -82,7 +82,18 @@
|
||||
const rnd = generateRandomString()
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col items-end mb-2 w-full">
|
||||
<div class="flex flex-wrap justify-between mb-2 w-full items-center gap-y-2">
|
||||
<AddProperty
|
||||
on:change={() => {
|
||||
if (jsonView) {
|
||||
schemaString = JSON.stringify(schema, null, '\t')
|
||||
editor?.setCode(schemaString)
|
||||
}
|
||||
}}
|
||||
bind:schema
|
||||
bind:this={addPropertyComponent}
|
||||
/>
|
||||
|
||||
<Toggle
|
||||
bind:checked={jsonView}
|
||||
label="JSON View"
|
||||
@@ -100,17 +111,6 @@
|
||||
/>
|
||||
</div>
|
||||
|
||||
<AddProperty
|
||||
on:change={() => {
|
||||
if (jsonView) {
|
||||
schemaString = JSON.stringify(schema, null, '\t')
|
||||
editor?.setCode(schemaString)
|
||||
}
|
||||
}}
|
||||
bind:schema
|
||||
bind:this={addPropertyComponent}
|
||||
/>
|
||||
|
||||
{#if !jsonView}
|
||||
{#key rnd}
|
||||
<div
|
||||
|
||||
@@ -7,9 +7,7 @@
|
||||
import type VariableEditor from '../VariableEditor.svelte'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import ArgInput from '../ArgInput.svelte'
|
||||
import ObjectTypeNarrowing from '../ObjectTypeNarrowing.svelte'
|
||||
import Tabs from '../common/tabs/Tabs.svelte'
|
||||
import { Tab, TabContent } from '../common'
|
||||
import ResourceNarrowing from '../ResourceNarrowing.svelte'
|
||||
import EditableSchemaDrawer from './EditableSchemaDrawer.svelte'
|
||||
import type { SchemaProperty } from '$lib/common'
|
||||
import ToggleButtonGroup from '../common/toggleButton-v2/ToggleButtonGroup.svelte'
|
||||
@@ -18,7 +16,6 @@
|
||||
import { Pen, Plus, Trash2 } from 'lucide-svelte'
|
||||
import Popover from '$lib/components/meltComponents/Popover.svelte'
|
||||
import ResourcePicker from '../ResourcePicker.svelte'
|
||||
import Tooltip from '../Tooltip.svelte'
|
||||
|
||||
interface Props {
|
||||
format?: string | undefined
|
||||
@@ -141,222 +138,215 @@
|
||||
)
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="flex flex-col gap-2 mt-2">
|
||||
{#if type === 'object' && oneOf && oneOf.length >= 2}
|
||||
<div class="flex flex-row gap-1 items-center justify-start">
|
||||
<ToggleButtonGroup
|
||||
bind:selected={oneOfSelected}
|
||||
class="h-auto w-auto"
|
||||
tabListClass="flex-wrap"
|
||||
>
|
||||
{#snippet children({ item })}
|
||||
{#each oneOf ?? [] as obj}
|
||||
<ToggleButton value={obj.title ?? ''} label={obj.title} {item} />
|
||||
{/each}
|
||||
{/snippet}
|
||||
</ToggleButtonGroup>
|
||||
<Label label="OneOf properties">
|
||||
<div class="flex flex-row gap-1 items-center justify-start pt-2">
|
||||
<ToggleButtonGroup
|
||||
bind:selected={oneOfSelected}
|
||||
class="h-auto w-auto"
|
||||
tabListClass="flex-wrap"
|
||||
>
|
||||
{#snippet children({ item })}
|
||||
{#each oneOf ?? [] as obj}
|
||||
<ToggleButton value={obj.title ?? ''} label={obj.title} {item} />
|
||||
{/each}
|
||||
{/snippet}
|
||||
</ToggleButtonGroup>
|
||||
|
||||
<Popover placement="bottom-end" closeButton>
|
||||
{#snippet trigger()}
|
||||
<Button size="xs2" color="light" nonCaptureEvent startIcon={{ icon: Plus }} />
|
||||
{/snippet}
|
||||
{#snippet content({ close })}
|
||||
<Label label="Label" class="p-2 flex flex-col gap-2">
|
||||
<input
|
||||
type="text"
|
||||
class="w-full !bg-surface"
|
||||
onkeydown={(event) => {
|
||||
if (event.key === 'Enter') {
|
||||
<Popover placement="bottom-end" closeButton>
|
||||
{#snippet trigger()}
|
||||
<Button size="xs2" color="light" nonCaptureEvent startIcon={{ icon: Plus }} />
|
||||
{/snippet}
|
||||
{#snippet content({ close })}
|
||||
<Label label="Label" class="p-2 flex flex-col gap-2">
|
||||
<input
|
||||
type="text"
|
||||
class="w-full !bg-surface"
|
||||
onkeydown={(event) => {
|
||||
if (event.key === 'Enter') {
|
||||
createVariant(variantName)
|
||||
close()
|
||||
}
|
||||
}}
|
||||
bind:value={variantName}
|
||||
/>
|
||||
<Button
|
||||
variant="border"
|
||||
color="light"
|
||||
size="xs"
|
||||
on:click={() => {
|
||||
createVariant(variantName)
|
||||
close()
|
||||
}}
|
||||
disabled={variantName.length === 0}
|
||||
>
|
||||
Add
|
||||
</Button>
|
||||
</Label>
|
||||
{/snippet}
|
||||
</Popover>
|
||||
</div>
|
||||
<div class="flex flex-row gap-2 items-center ml-1 mt-4 mb-2">
|
||||
<span class="font-semibold text-sm">{oneOfSelected}</span>
|
||||
|
||||
<Popover
|
||||
floatingConfig={{ strategy: 'absolute', placement: 'bottom-end' }}
|
||||
containerClasses="border rounded-lg shadow-lg p-4 bg-surface"
|
||||
closeButton
|
||||
>
|
||||
{#snippet trigger()}
|
||||
<Button
|
||||
size="xs2"
|
||||
color="light"
|
||||
startIcon={{ icon: Pen }}
|
||||
propagateEvent
|
||||
iconOnly={false}
|
||||
on:click={() => {
|
||||
if (oneOfSelected) {
|
||||
variantName = oneOfSelected
|
||||
}
|
||||
}}
|
||||
bind:value={variantName}
|
||||
/>
|
||||
<Button
|
||||
variant="border"
|
||||
color="light"
|
||||
size="xs"
|
||||
on:click={() => {
|
||||
createVariant(variantName)
|
||||
close()
|
||||
}}
|
||||
disabled={variantName.length === 0}
|
||||
>
|
||||
Add
|
||||
</Button>
|
||||
</Label>
|
||||
{/snippet}
|
||||
</Popover>
|
||||
</div>
|
||||
<div class="flex flex-row gap-2 items-center">
|
||||
<span class="font-semibold text-sm">{oneOfSelected}</span>
|
||||
|
||||
<Popover
|
||||
floatingConfig={{ strategy: 'absolute', placement: 'bottom-end' }}
|
||||
containerClasses="border rounded-lg shadow-lg p-4 bg-surface"
|
||||
closeButton
|
||||
>
|
||||
{#snippet trigger()}
|
||||
<Button
|
||||
size="xs2"
|
||||
color="light"
|
||||
startIcon={{ icon: Pen }}
|
||||
propagateEvent
|
||||
iconOnly={false}
|
||||
on:click={() => {
|
||||
if (oneOfSelected) {
|
||||
variantName = oneOfSelected
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{/snippet}
|
||||
{#snippet content({ close })}
|
||||
<Label label="Label" class="p-2 flex flex-col gap-2">
|
||||
<input
|
||||
type="text"
|
||||
class="w-full !bg-surface"
|
||||
onkeydown={(event) => {
|
||||
if (event.key === 'Enter') {
|
||||
{/snippet}
|
||||
{#snippet content({ close })}
|
||||
<Label label="Label" class="p-2 flex flex-col gap-2">
|
||||
<input
|
||||
type="text"
|
||||
class="w-full !bg-surface"
|
||||
onkeydown={(event) => {
|
||||
if (event.key === 'Enter') {
|
||||
if (oneOfSelected) {
|
||||
renameVariant(variantName, oneOfSelected)
|
||||
close()
|
||||
}
|
||||
}
|
||||
}}
|
||||
bind:value={variantName}
|
||||
/>
|
||||
<Button
|
||||
variant="border"
|
||||
color="light"
|
||||
size="xs"
|
||||
on:click={() => {
|
||||
if (oneOfSelected) {
|
||||
renameVariant(variantName, oneOfSelected)
|
||||
close()
|
||||
}
|
||||
}
|
||||
}}
|
||||
bind:value={variantName}
|
||||
/>
|
||||
<Button
|
||||
variant="border"
|
||||
color="light"
|
||||
size="xs"
|
||||
on:click={() => {
|
||||
if (oneOfSelected) {
|
||||
renameVariant(variantName, oneOfSelected)
|
||||
close()
|
||||
}
|
||||
}}
|
||||
disabled={variantName.length === 0}
|
||||
>
|
||||
Rename
|
||||
</Button>
|
||||
</Label>
|
||||
{/snippet}
|
||||
</Popover>
|
||||
<Button
|
||||
size="xs2"
|
||||
color="red"
|
||||
startIcon={{ icon: Trash2 }}
|
||||
iconOnly
|
||||
disabled={(oneOf?.length ?? 0) <= 2}
|
||||
on:click={() => {
|
||||
if (oneOf && oneOfSelected) {
|
||||
const idx = oneOf.findIndex((obj) => obj.title === oneOfSelected)
|
||||
oneOf = oneOf.filter((_, i) => i !== idx)
|
||||
oneOfSelected = oneOf[0].title
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{#if oneOfSelected && oneOf}
|
||||
{@const idx = oneOf.findIndex((obj) => obj.title === oneOfSelected)}
|
||||
<EditableSchemaDrawer
|
||||
onClose={() => {
|
||||
onDrawerClose?.()
|
||||
}}
|
||||
bind:schema={oneOf[idx]}
|
||||
hiddenArgs={[
|
||||
oneOf?.find((o) => Object.keys(o.properties ?? {}).includes('kind')) ? 'kind' : 'label'
|
||||
]}
|
||||
/>
|
||||
{/if}
|
||||
{:else if type === 'object' && format !== 'resource-s3_object' && !isDynSelect}
|
||||
<Tabs
|
||||
bind:selected={initialObjectSelected}
|
||||
on:selected={(e) => {
|
||||
if (e.detail === 'json-schema') {
|
||||
format = 'json-schema'
|
||||
} else {
|
||||
format = ''
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Tab value="resource">Resource</Tab>
|
||||
<Tab value="custom-object">Custom Object</Tab>
|
||||
<Tab value="json-schema">
|
||||
JSON Schema
|
||||
<Tooltip>
|
||||
This displays a JSON schema editor, useful when a JSON schema input is expected.
|
||||
</Tooltip>
|
||||
</Tab>
|
||||
{#snippet content()}
|
||||
<div class="pt-2">
|
||||
<TabContent value="custom-object">
|
||||
<ToggleButtonGroup
|
||||
bind:selected={customObjectSelected}
|
||||
class="mb-2"
|
||||
on:selected={(e) => {
|
||||
if (e.detail === 'editor') {
|
||||
format = undefined
|
||||
} else {
|
||||
properties = undefined
|
||||
order = undefined
|
||||
requiredProperty = undefined
|
||||
}
|
||||
}}
|
||||
>
|
||||
{#snippet children({ item })}
|
||||
<ToggleButton value="editor" label="Editor" {item} />
|
||||
<ToggleButton
|
||||
value="json-schema-resource"
|
||||
label="JSON Schema Resource"
|
||||
{item}
|
||||
tooltip="Select a JSON schema resource to specify the object's properties"
|
||||
showTooltipIcon
|
||||
/>
|
||||
{/snippet}
|
||||
</ToggleButtonGroup>
|
||||
{#if customObjectSelected === 'editor'}
|
||||
<EditableSchemaDrawer
|
||||
bind:schema={
|
||||
() => {
|
||||
return {
|
||||
properties: properties,
|
||||
order: order,
|
||||
required: requiredProperty
|
||||
}
|
||||
},
|
||||
(v) => {
|
||||
properties = v.properties
|
||||
order = v.order
|
||||
requiredProperty = v.required
|
||||
}
|
||||
}
|
||||
/>
|
||||
{:else if customObjectSelected === 'json-schema-resource'}
|
||||
<ResourcePicker
|
||||
resourceType="json_schema"
|
||||
bind:value={
|
||||
() => {
|
||||
if (format?.startsWith('jsonschema-')) {
|
||||
return format.substring('jsonschema-'.length)
|
||||
}
|
||||
return undefined
|
||||
},
|
||||
(v) => {
|
||||
format = 'jsonschema-' + v
|
||||
}
|
||||
}
|
||||
/>
|
||||
{/if}
|
||||
</TabContent>
|
||||
|
||||
<TabContent value="resource">
|
||||
<ObjectTypeNarrowing bind:format />
|
||||
</TabContent>
|
||||
}}
|
||||
disabled={variantName.length === 0}
|
||||
>
|
||||
Rename
|
||||
</Button>
|
||||
</Label>
|
||||
{/snippet}
|
||||
</Popover>
|
||||
<Button
|
||||
size="xs2"
|
||||
color="red"
|
||||
startIcon={{ icon: Trash2 }}
|
||||
iconOnly
|
||||
disabled={(oneOf?.length ?? 0) <= 2}
|
||||
on:click={() => {
|
||||
if (oneOf && oneOfSelected) {
|
||||
const idx = oneOf.findIndex((obj) => obj.title === oneOfSelected)
|
||||
oneOf = oneOf.filter((_, i) => i !== idx)
|
||||
oneOfSelected = oneOf[0].title
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{#if oneOfSelected && oneOf}
|
||||
{@const idx = oneOf.findIndex((obj) => obj.title === oneOfSelected)}
|
||||
<div class="ml-1">
|
||||
<EditableSchemaDrawer
|
||||
onClose={() => {
|
||||
onDrawerClose?.()
|
||||
}}
|
||||
bind:schema={oneOf[idx]}
|
||||
hiddenArgs={[
|
||||
oneOf?.find((o) => Object.keys(o.properties ?? {}).includes('kind'))
|
||||
? 'kind'
|
||||
: 'label'
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
{/snippet}
|
||||
</Tabs>
|
||||
{/if}
|
||||
</Label>
|
||||
<div class="py-2"></div>
|
||||
{:else if type === 'object' && format?.startsWith('resource-') && format !== 'resource-s3_object' && !isDynSelect}
|
||||
<ResourceNarrowing bind:format />
|
||||
{:else if type === 'object' && !format?.startsWith('resource-') && !isDynSelect}
|
||||
<div class="py-2">
|
||||
<Label label="Object properties">
|
||||
<ToggleButtonGroup
|
||||
bind:selected={customObjectSelected}
|
||||
class="my-2"
|
||||
on:selected={(e) => {
|
||||
if (e.detail === 'editor') {
|
||||
format = undefined
|
||||
} else {
|
||||
properties = undefined
|
||||
order = undefined
|
||||
requiredProperty = undefined
|
||||
}
|
||||
}}
|
||||
>
|
||||
{#snippet children({ item })}
|
||||
<ToggleButton value="editor" label="Custom" {item} />
|
||||
<ToggleButton
|
||||
value="json-schema-resource"
|
||||
label="Template"
|
||||
{item}
|
||||
tooltip="Select a JSON schema resource to specify the object's properties"
|
||||
showTooltipIcon
|
||||
/>
|
||||
{/snippet}
|
||||
</ToggleButtonGroup>
|
||||
{#if customObjectSelected === 'editor'}
|
||||
<EditableSchemaDrawer
|
||||
bind:schema={
|
||||
() => {
|
||||
return {
|
||||
properties: properties,
|
||||
order: order,
|
||||
required: requiredProperty
|
||||
}
|
||||
},
|
||||
(v) => {
|
||||
properties = v.properties
|
||||
order = v.order
|
||||
requiredProperty = v.required
|
||||
}
|
||||
}
|
||||
/>
|
||||
{:else if customObjectSelected === 'json-schema-resource'}
|
||||
{#if format == undefined}
|
||||
<div class="text-xs text-tertiary my-1">
|
||||
Select a <code>json_schema</code> resource as a reusable JSON schema template
|
||||
</div>
|
||||
{/if}
|
||||
<ResourcePicker
|
||||
resourceType="json_schema"
|
||||
bind:value={
|
||||
() => {
|
||||
if (format?.startsWith('jsonschema-')) {
|
||||
return format.substring('jsonschema-'.length)
|
||||
}
|
||||
return undefined
|
||||
},
|
||||
(v) => {
|
||||
if (v) {
|
||||
format = 'jsonschema-' + v
|
||||
} else {
|
||||
format = undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
/>
|
||||
{/if}
|
||||
</Label>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if !(type === 'object' && oneOf && oneOf.length >= 2) && !(type == 'object' && initialObjectSelected == 'custom-object') && !isDynSelect}
|
||||
|
||||
@@ -217,7 +217,7 @@
|
||||
bind:itemsType
|
||||
canEditResourceType={isFlowInput || isAppInput}
|
||||
/>
|
||||
{:else if type == 'string' || ['number', 'integer', 'object'].includes(type ?? '')}
|
||||
{:else if type == 'string' || ['number', 'integer'].includes(type ?? '')}
|
||||
<div>
|
||||
<Label label="Field settings">
|
||||
<div>
|
||||
@@ -244,44 +244,42 @@
|
||||
bind:currency={extra['currency']}
|
||||
bind:currencyLocale={extra['currencyLocale']}
|
||||
/>
|
||||
{:else if type == 'object' && oneOf && oneOf.length >= 2 && !isFlowInput && !isAppInput}
|
||||
<ToggleButtonGroup bind:selected={oneOfSelected} class="mb-2">
|
||||
{#snippet children({ item })}
|
||||
{#each oneOf as obj}
|
||||
<ToggleButton value={obj.title ?? ''} label={obj.title} {item} />
|
||||
{/each}
|
||||
{/snippet}
|
||||
</ToggleButtonGroup>
|
||||
{#if oneOfSelected && oneOfSchemas}
|
||||
{@const idx = oneOf.findIndex((obj) => obj.title === oneOfSelected)}
|
||||
<div class="border">
|
||||
<EditableSchemaForm
|
||||
on:change
|
||||
noPreview
|
||||
bind:schema={oneOfSchemas[idx]}
|
||||
uiOnly
|
||||
jsonEnabled={false}
|
||||
editTab="inputEditor"
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
{:else if type == 'object' && !format?.startsWith('resource-') && !isFlowInput && !isAppInput}
|
||||
<div class="border">
|
||||
<EditableSchemaForm
|
||||
on:change
|
||||
noPreview
|
||||
bind:schema
|
||||
uiOnly
|
||||
jsonEnabled={false}
|
||||
editTab="inputEditor"
|
||||
/>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="text-tertiary text-xs">No settings available for this field type</div>
|
||||
{/if}
|
||||
</div>
|
||||
</Label>
|
||||
</div>
|
||||
{:else if type == 'object' && oneOf && oneOf.length >= 2 && !isFlowInput && !isAppInput}
|
||||
<ToggleButtonGroup bind:selected={oneOfSelected} class="mb-2">
|
||||
{#snippet children({ item })}
|
||||
{#each oneOf as obj}
|
||||
<ToggleButton value={obj.title ?? ''} label={obj.title} {item} />
|
||||
{/each}
|
||||
{/snippet}
|
||||
</ToggleButtonGroup>
|
||||
{#if oneOfSelected && oneOfSchemas}
|
||||
{@const idx = oneOf.findIndex((obj) => obj.title === oneOfSelected)}
|
||||
<div class="border">
|
||||
<EditableSchemaForm
|
||||
on:change
|
||||
noPreview
|
||||
bind:schema={oneOfSchemas[idx]}
|
||||
uiOnly
|
||||
jsonEnabled={false}
|
||||
editTab="inputEditor"
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
{:else if type == 'object' && !format?.startsWith('resource-') && !isFlowInput && !isAppInput}
|
||||
<div class="border">
|
||||
<EditableSchemaForm
|
||||
on:change
|
||||
noPreview
|
||||
bind:schema
|
||||
uiOnly
|
||||
jsonEnabled={false}
|
||||
editTab="inputEditor"
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{@render children?.()}
|
||||
|
||||
Reference in New Issue
Block a user