Skip to content

Commit 59bcce7

Browse files
feat (frontend): improve capture UI (#5051)
* feat (frontend): improve capture UI * show schema diff * add accept reject form * add diff for first node input * move update schema button * change modified properties display * propagate change through nested components * allow modification of nested object in schema * reject nested changes * clean logic * clean code * clean * nit * fix first strep input * fix argument preview * clean * restore indentation for nested objects * ignore undefined field in diff computation * fix run button disabled update * nit * fix update JSON * fix deletion of nested components * dark mode * clean * replace dropdown with sidebar * only check type for compatibility * add shadow * disbale dnd on edit * auto-scroll within schema * fix nested not dnd object diff viewer * fix captures drawer * open edit tab on add new arg * change button label when schema is the same * ajust padding * fix arg update * fix oneof display * propagate change event through nested schema * handle oneOf * fix preview arg sync * handle s3 object * fix arg sync * update schema input compatibility * clean compatible * accept empty array items * clean * increase of schema args gap * fix nested schema update * allow number and int compatibility * reset args when modifying schema * open fields on add with addPropertyV2 --------- Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
1 parent fcfad69 commit 59bcce7

18 files changed

+1443
-875
lines changed

frontend/src/lib/components/ArgInput.svelte

Lines changed: 675 additions & 597 deletions
Large diffs are not rendered by default.

frontend/src/lib/components/EditableSchemaForm.svelte

Lines changed: 64 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
import PropertyEditor from './schema/PropertyEditor.svelte'
1313
import SimpleEditor from './SimpleEditor.svelte'
1414
import { createEventDispatcher } from 'svelte'
15-
1615
import ToggleButton from './common/toggleButton-v2/ToggleButton.svelte'
1716
import ToggleButtonGroup from './common/toggleButton-v2/ToggleButtonGroup.svelte'
1817
import Label from './Label.svelte'
@@ -23,6 +22,7 @@
2322
import SchemaFormDnd from './schema/SchemaFormDND.svelte'
2423
import { deepEqual } from 'fast-equals'
2524
import { tweened } from 'svelte/motion'
25+
import type { SchemaDiff } from '$lib/components/schema/schemaUtils'
2626
2727
export let schema: Schema | any
2828
export let schemaSkippedValues: string[] = []
@@ -49,6 +49,9 @@
4949
export let previewSchema: Record<string, any> | undefined = undefined
5050
export let editPanelInitialSize: number | undefined = undefined
5151
export let editPanelSize = 0
52+
export let diff: Record<string, SchemaDiff> = {}
53+
export let disableDnd: boolean = false
54+
export let shouldDispatchChanges: boolean = false
5255
5356
const dispatch = createEventDispatcher()
5457
@@ -232,6 +235,11 @@
232235
233236
let pannelButtonWidth: number = 0
234237
export let pannelExtraButtonWidth: number = 0
238+
239+
export function updateJson() {
240+
schemaString = JSON.stringify(schema, null, '\t')
241+
editor?.setCode(schemaString)
242+
}
235243
</script>
236244

237245
<div class="w-full h-full">
@@ -247,37 +255,60 @@
247255
<Splitpanes class="splitter-hidden w-full">
248256
{#if !noPreview}
249257
<Pane bind:size={inputPanelSize} minSize={20}>
250-
<div class="flex flex-col pr-2 gap-2">
258+
<div
259+
class="h-full flex flex-col gap-2 {$$slots.openEditTab && editPanelSize > 0
260+
? 'pr-[38px]'
261+
: 'pr-2'}"
262+
>
251263
{#if $$slots.addProperty}
252-
<div class="w-full justify-left pr-2">
253-
<div style={`width: calc(100% - ${pannelButtonWidth - pannelExtraButtonWidth}px);`}>
264+
<div class="w-full justify-left pr-2 grow-0">
265+
<div
266+
style={editPanelSize > 0
267+
? `width: 100%;`
268+
: `width: calc(100% - ${pannelButtonWidth - pannelExtraButtonWidth}px);`}
269+
>
254270
<slot name="addProperty" />
255271
</div>
256272
</div>
257273
{/if}
258274

259-
<SchemaFormDnd
260-
schema={previewSchema ? previewSchema : schema}
261-
{dndType}
262-
bind:args
263-
on:click={(e) => {
264-
opened = e.detail
265-
}}
266-
on:reorder={(e) => {
267-
schema.order = e.detail
268-
schema = schema
269-
dispatch('change', schema)
270-
}}
271-
on:change={() => {
272-
schema = schema
273-
dispatch('change', schema)
274-
}}
275-
{lightweightMode}
276-
prettifyHeader={isAppInput}
277-
disabled={!!previewSchema}
278-
/>
279-
280-
<slot name="runButton" />
275+
<div
276+
class="min-h-0 overflow-y-auto grow rounded-md {$$slots.runButton
277+
? 'flex flex-col gap-2'
278+
: ''}"
279+
>
280+
<SchemaFormDnd
281+
nestedClasses={'flex flex-col gap-1'}
282+
schema={previewSchema ? previewSchema : schema}
283+
{dndType}
284+
{disableDnd}
285+
bind:args
286+
on:click={(e) => {
287+
opened = e.detail
288+
}}
289+
on:reorder={(e) => {
290+
schema.order = e.detail
291+
schema = schema
292+
dispatch('change', schema)
293+
}}
294+
on:change={() => {
295+
schema = schema
296+
dispatch('change', schema)
297+
}}
298+
{lightweightMode}
299+
prettifyHeader={isAppInput}
300+
disabled={!!previewSchema}
301+
{diff}
302+
on:acceptChange
303+
on:rejectChange
304+
on:nestedChange={() => {
305+
dispatch('change', schema)
306+
}}
307+
{shouldDispatchChanges}
308+
/>
309+
310+
<slot name="runButton" />
311+
</div>
281312
</div>
282313
</Pane>
283314
{/if}
@@ -425,7 +456,6 @@
425456
{isAppInput}
426457
on:change={() => {
427458
schema = schema
428-
// console.log('schema', schema)
429459
dispatch('change', schema)
430460
}}
431461
>
@@ -440,8 +470,6 @@
440470
const isS3 = e.detail == 'S3'
441471
const isOneOf = e.detail == 'oneOf'
442472

443-
selected = e.detail
444-
445473
const emptyProperty = {
446474
contentEncoding: undefined,
447475
enum_: undefined,
@@ -508,8 +536,12 @@
508536
type: e.detail
509537
}
510538
}
511-
schema = schema
512-
dispatch('change', schema)
539+
// No better solution than this, needs future rework
540+
setTimeout(() => {
541+
schema = schema
542+
dispatch('change', schema)
543+
}, 100)
544+
dispatch('schemaChange')
513545
}}
514546
>
515547
{#each [['String', 'string'], ['Number', 'number'], ['Integer', 'integer'], ['Object', 'object'], ['OneOf', 'oneOf'], ['Array', 'array'], ['Boolean', 'boolean'], ['S3 Object', 'S3']] as x}
@@ -558,6 +590,7 @@
558590
on:schemaChange={(e) => {
559591
schema = schema
560592
dispatch('change', schema)
593+
dispatch('schemaChange')
561594
}}
562595
/>
563596
{/if}

frontend/src/lib/components/FirstStepInputs.svelte

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
error = e
2828
}
2929
}
30-
loadSchema()
30+
$: $flowStore && $flowStateStore && loadSchema()
3131
3232
function handleClick() {
3333
selected = !selected
@@ -51,6 +51,8 @@
5151
if (event.key === 'Escape' && selected) {
5252
selected = false
5353
dispatch('select', undefined)
54+
event.stopPropagation()
55+
event.preventDefault()
5456
}
5557
}
5658

frontend/src/lib/components/FlowPreviewContent.svelte

Lines changed: 46 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
let jobProgressReset: () => void
4242
4343
export function test() {
44+
renderCount++
4445
runPreview($previewArgs, undefined)
4546
}
4647
@@ -159,53 +160,53 @@
159160
on:close={captureLibraryDrawer?.toggleDrawer}
160161
>
161162
<div class="h-full flex flex-col gap-2">
162-
<CapturesInputs
163-
flowPath={$pathStore}
164-
headless={false}
165-
addButton={true}
166-
on:select={(e) => {
167-
selectedCapture = e.detail
168-
}}
169-
on:openTriggers={(e) => {
170-
dispatch('openTriggers', e.detail)
171-
captureLibraryDrawer?.closeDrawer()
172-
}}
173-
/>
163+
<div class="min-h-0 grow h-full">
164+
<CapturesInputs
165+
flowPath={$pathStore}
166+
headless={false}
167+
addButton={true}
168+
on:select={(e) => {
169+
selectedCapture = e.detail
170+
}}
171+
on:openTriggers={(e) => {
172+
dispatch('openTriggers', e.detail)
173+
captureLibraryDrawer?.closeDrawer()
174+
}}
175+
/>
176+
</div>
174177

175-
<div class="h-full overflow-hidden min-h-0 flex flex-col justify-between">
176-
<div class="w-full flex flex-col min-h-0 gap-2 px-2 py-2 grow">
177-
<div class="w-full flex flex-col">
178-
<Button
179-
color="blue"
180-
btnClasses="w-full"
181-
size="sm"
182-
spacingSize="xl"
183-
on:click={async () => {
184-
$previewArgs = JSON.parse(JSON.stringify(selectedCapture))
185-
captureLibraryDrawer?.closeDrawer()
186-
renderCount++
187-
}}
188-
disabled={!selectedCapture}
178+
<div class="w-full flex flex-col gap-2 px-2 py-2 h-[50%]">
179+
<div class="w-full flex flex-col">
180+
<Button
181+
color="blue"
182+
btnClasses="w-full"
183+
size="sm"
184+
spacingSize="xl"
185+
on:click={async () => {
186+
$previewArgs = JSON.parse(JSON.stringify(selectedCapture))
187+
captureLibraryDrawer?.closeDrawer()
188+
renderCount++
189+
}}
190+
disabled={!selectedCapture}
191+
>
192+
<ArrowLeftIcon class="w-4 h-4 mr-2" />
193+
Use input
194+
</Button>
195+
</div>
196+
<div class="w-full min-h-0 grow overflow-auto">
197+
{#if typeof selectedCapture == 'string' && selectedCapture == 'WINDMILL_TOO_BIG'}
198+
<div class="text-secondary mt-2">
199+
Payload too big to preview but can still be loaded</div
189200
>
190-
<ArrowLeftIcon class="w-4 h-4 mr-2" />
191-
Use input
192-
</Button>
193-
</div>
194-
<div class="w-full min-h-0 grow overflow-auto">
195-
{#if typeof selectedCapture == 'string' && selectedCapture == 'WINDMILL_TOO_BIG'}
196-
<div class="text-secondary mt-2">
197-
Payload too big to preview but can still be loaded</div
198-
>
199-
{:else if Object.keys(selectedCapture || {}).length > 0}
200-
<div class=" overflow-auto h-full p-2">
201-
<ObjectViewer json={selectedCapture} />
202-
</div>
203-
{:else}
204-
<div class="text-center text-tertiary">
205-
Select an Input to preview scripts arguments
206-
</div>
207-
{/if}
208-
</div>
201+
{:else if Object.keys(selectedCapture || {}).length > 0}
202+
<div class=" overflow-auto h-full p-2">
203+
<ObjectViewer json={selectedCapture} />
204+
</div>
205+
{:else}
206+
<div class="text-center text-tertiary">
207+
Select an Input to preview scripts arguments
208+
</div>
209+
{/if}
209210
</div>
210211
</div>
211212
</div>

frontend/src/lib/components/HistoricInputs.svelte

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@
102102
if (event.key === 'Escape' && selected) {
103103
selected = undefined
104104
dispatch('select', undefined)
105+
event.stopPropagation()
106+
event.preventDefault()
105107
}
106108
}
107109

frontend/src/lib/components/SavedInputsPicker.svelte

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,16 +119,22 @@
119119
function handleKeydown(event: KeyboardEvent) {
120120
if (event.key === 'Escape' && isEditing) {
121121
setEditing(null)
122+
event.stopPropagation()
123+
event.preventDefault()
122124
} else if (event.key === 'Escape' && selectedInput) {
123125
selectedInput = null
124126
selectedArgs = undefined
125127
dispatch('select', undefined)
128+
event.stopPropagation()
129+
event.preventDefault()
126130
}
127131
128132
if (event.key === 'Enter' && isEditing) {
129133
updateInput(isEditing).then(() => {
130134
setEditing(null)
131135
})
136+
event.stopPropagation()
137+
event.preventDefault()
132138
}
133139
}
134140

0 commit comments

Comments
 (0)