mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-10-15 16:03:02 +00:00
* fix: pre-fill the test panel JSON args editor and align its placeholder Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: reseed the JSON args editor when the preprocessor tab is selected Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: seed schema defaults and own-property args in the JSON payload Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: follow the schema in an untouched JSON payload, ignore same-tab clicks Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: latch JSON editor ownership from Monaco, drop the late remounts The pristine check read the bound `code` value, which trails the buffer by SimpleEditor's 200ms debounce — a reseed arriving in that window overwrote text already typed. Latch ownership from Monaco's own change event instead, via a new undebounced `input` event guarded so `setCode`'s `setValue` does not read as an edit. Both `.then(() => argsRender++)` bumps are gone: the arg views now remount at the tab transition only, and follow the schema in through `initialCode` when inference resolves, so a remount can no longer land on an in-progress payload. `FlowPreviewContent.selectInput` overwrote the editor on select but not on deselect, leaving the abandoned input's payload over reverted args. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
123 lines
3.5 KiB
Svelte
123 lines
3.5 KiB
Svelte
<script lang="ts">
|
|
import SimpleEditor from '$lib/components/SimpleEditor.svelte'
|
|
import { createEventDispatcher, untrack } from 'svelte'
|
|
|
|
const dispatch = createEventDispatcher()
|
|
|
|
interface Props {
|
|
updateOnBlur?: boolean
|
|
placeholder?: string
|
|
selected?: boolean
|
|
/** Content the editor opens with, and keeps following while the buffer is untouched — so a
|
|
* payload nobody has typed into tracks the schema instead of going stale. The first edit
|
|
* hands the buffer to the user and later changes stop overwriting it. */
|
|
initialCode?: string
|
|
}
|
|
|
|
let {
|
|
updateOnBlur = true,
|
|
placeholder = 'Write a JSON payload. The input schema will be inferred.<br/><br/>Example:<br/><br/>{<br/> "foo": "12"<br/>}',
|
|
selected = false,
|
|
initialCode = ''
|
|
}: Props = $props()
|
|
|
|
let pendingJson = $state(untrack(() => initialCode))
|
|
// The last content this component wrote, kept only to skip a reseed that would replace the
|
|
// buffer with what it already holds — `setValue` resets the cursor and the undo stack.
|
|
let seededCode = untrack(() => initialCode)
|
|
// Latched from Monaco's own change event, never from `pendingJson`: that trails the buffer by
|
|
// SimpleEditor's debounce, a window in which typed text still looks like the seeded payload
|
|
// and a reseed lands on top of it.
|
|
let userEdited = false
|
|
let simpleEditor: SimpleEditor | undefined = $state(undefined)
|
|
let focusTrap: HTMLElement | undefined = $state()
|
|
|
|
$effect(() => {
|
|
const next = initialCode
|
|
untrack(() => {
|
|
if (next !== seededCode && !userEdited) {
|
|
seed(next)
|
|
}
|
|
})
|
|
})
|
|
|
|
// `SimpleEditor.setCode` cancels the change burst its own `setValue` opens, so reseeding
|
|
// never dispatches `select` — the payload reaches `args` only when the user edits it.
|
|
function seed(code: string) {
|
|
seededCode = code
|
|
userEdited = false
|
|
pendingJson = code
|
|
simpleEditor?.setCode(code)
|
|
}
|
|
|
|
function updatePayloadFromJson(jsonInput: string) {
|
|
if (jsonInput === undefined || jsonInput === null || jsonInput.trim() === '') {
|
|
dispatch('select', undefined)
|
|
return
|
|
}
|
|
try {
|
|
const parsed = JSON.parse(jsonInput)
|
|
dispatch('select', parsed)
|
|
} catch (error) {
|
|
dispatch('select', undefined)
|
|
}
|
|
}
|
|
|
|
/** Authoritative overwrite: replaces the buffer whether or not it has been typed into, and
|
|
* re-establishes it as the content to keep following. */
|
|
export function setCode(code: string) {
|
|
seed(code)
|
|
}
|
|
|
|
export function resetSelected(dispatchEvent?: boolean) {
|
|
if (dispatchEvent) {
|
|
dispatch('select', undefined)
|
|
}
|
|
}
|
|
|
|
function handleKeydown(event: KeyboardEvent) {
|
|
if (event.key === 'Escape' && selected) {
|
|
focusTrap?.focus()
|
|
resetSelected(true)
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<svelte:window onkeydown={handleKeydown} />
|
|
|
|
<!-- Add a hidden button that can receive focus -->
|
|
<button bind:this={focusTrap} class="sr-only" tabindex="-1" aria-hidden="true">Focus trap</button>
|
|
|
|
<div class="h-full rounded-md border">
|
|
<SimpleEditor
|
|
bind:this={simpleEditor}
|
|
on:input={() => (userEdited = true)}
|
|
on:focus={() => {
|
|
if (updateOnBlur) {
|
|
dispatch('focus')
|
|
updatePayloadFromJson(pendingJson)
|
|
}
|
|
}}
|
|
on:blur={async () => {
|
|
if (updateOnBlur) {
|
|
dispatch('blur')
|
|
}
|
|
}}
|
|
on:change={(e) => {
|
|
if (e.detail?.code !== undefined) {
|
|
updatePayloadFromJson(e.detail.code)
|
|
}
|
|
}}
|
|
bind:code={pendingJson}
|
|
lang="json"
|
|
class="h-full json-inputs-editor"
|
|
{placeholder}
|
|
/>
|
|
</div>
|
|
|
|
<style>
|
|
:global(.json-inputs-editor .monaco-editor .suggest-widget) {
|
|
z-index: 200000 !important;
|
|
}
|
|
</style>
|