Files
windmill/frontend/src/lib/components/SavedInputsV2.svelte
T
310f37a682 feat: migrate to svelte5 + vite6 (#4813)
* runs on svelte 5

* Line component from svelte-chartjs

* Replaced all svelte-chartjs occurrences with custom wrapper

* Fix props mistake

* Fix illegal table structures

* self-closing-tags fix

* aria labels

* Fixed trivial warnings and errors

* @tanstack/svelte-table fix

* upgrade to vite 6

* svelte-kit sync before running svelte-check

* Remove on:clear which is actually on:removeAll and already handled by on:change

* fix worker tags not displaying in Autoscaling

* Try to fix svelte-kit sync not working during CI

* remove warnings

* Fix add flow page crashing

* access worldStore before assignment fix

* fix infinite recursions in App Editor

* Replaced JSON.stringify with proper deepEqual

* component mount api changed (no longer classes)

* fix ci errors

* Fix infinite loops in background runnable panel

* factored effect on deep equal logic in onObjChange

* fix "Add" not working in AgGrid Table

* Replaced legacy component.$set api

* Fix multiselect infinite value reaction

* Fix flow input fields resetting when opening their edit tab

* fix date input resetting when typing year

* Remove !p-0 affecting subgrid dotted borders

* fix missing debounceTemplate causing hundreds of updates

* Fix AgGrid action refreshes and disppearing

* resolve getItems generating random ids every rerun

* fix cannot access items before init

* fix sort lambda arguments being undefined

* Revert "Remove !p-0 affecting subgrid dotted borders"

This reverts commit c62809bb45d682a48376b071680645ed4e1c601b.

* fix input not updating in decision tree editor

* Update frontend/src/lib/components/schema/EditableSchemaWrapper.svelte

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>

* Re-added padding affecting subgrid dotted borders (#5479)

* remove !p-0 in preset components

* removed extra padding on accordion tabs subgrid

* Fix non-reactive SchemaForm

* dirty fix for the oneOf bug

* Fix warnings and update svelte-exmarkdown for svelte 5

* fix dnd not working

* don't mount component like objects

---------

Co-authored-by: Diego Imbert <diegoimbert@protonmail.com>
Co-authored-by: Diego Imbert <70353967+diegoimbert@users.noreply.github.com>
Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
2025-04-02 21:33:50 +00:00

214 lines
6.2 KiB
Svelte

<script lang="ts">
import SavedInputsPicker from '$lib/components/SavedInputsPicker.svelte'
import { createEventDispatcher, tick } from 'svelte'
import HistoricInputs from '$lib/components/HistoricInputs.svelte'
import { type RunnableType } from '$lib/gen/types.gen.js'
import { Pane, Splitpanes } from 'svelte-splitpanes'
import Section from '$lib/components/Section.svelte'
import SaveInputsButton from '$lib/components/SaveInputsButton.svelte'
import { Button } from './common'
import { ExternalLink, Search } from 'lucide-svelte'
import { Popover } from './meltComponents'
import SchemaForm from './SchemaForm.svelte'
import MultiSelect from './multiselect/MultiSelectWrapper.svelte'
const dispatch = createEventDispatcher()
export let scriptHash: string | null = null
export let scriptPath: string | null = null
export let flowPath: string | null = null
export let inputSelected: 'saved' | 'history' | undefined = undefined
export let jsonView: boolean = false
export let schema: any
// Are the current Inputs valid and able to be saved?
export let isValid: boolean
export let args: object
export function resetSelected() {
historicInputs?.resetSelected(true)
savedInputsPicker?.resetSelected(true)
}
let savedArgs: any = undefined
let runnableType: RunnableType | undefined = undefined
let savedInputsPicker: SavedInputsPicker | undefined = undefined
let historicInputs: HistoricInputs | undefined = undefined
$: runnableId = scriptHash || scriptPath || flowPath || undefined
$: runnableType = scriptHash
? 'ScriptHash'
: scriptPath
? 'ScriptPath'
: flowPath
? 'FlowPath'
: undefined
function selectArgs(selected_args: any, type: 'saved' | 'history' | undefined) {
if (selected_args) {
if (!inputSelected) {
savedArgs = args
}
inputSelected = type
dispatch('selected_args', selected_args)
} else if (savedArgs) {
inputSelected = type
dispatch('selected_args', savedArgs)
}
}
let searchArgs = {}
let appliedSearchArgs = {}
let searchArgsFields = [] as string[]
$: emptySearchArgs = Object.keys(appliedSearchArgs).length === 0
$: filteredSchema = {
properties: Object.fromEntries(
Object.entries(schema?.properties ?? {}).filter(([key]) => searchArgsFields.includes(key))
)
}
</script>
<div class="min-w-[300px] h-full flex flex-col">
<Splitpanes horizontal={true}>
<Pane class="px-4 py-2 h-full">
<Section
label="Saved Inputs"
tooltip="Shared inputs are available to anyone with access to the script"
wrapperClass="h-full"
small={true}
>
<svelte:fragment slot="action">
<SaveInputsButton
{args}
disabled={!isValid || jsonView}
{runnableId}
{runnableType}
on:update={() => {
savedInputsPicker?.refresh()
}}
/>
</svelte:fragment>
<SavedInputsPicker
bind:this={savedInputsPicker}
previewArgs={args}
{runnableId}
{runnableType}
{isValid}
on:select={(e) => {
if (e.detail) historicInputs?.resetSelected()
selectArgs(e.detail, e.detail ? 'saved' : undefined)
}}
noButton={true}
/>
</Section>
</Pane>
<Pane class="px-4 py-4 h-full">
<Section label="History" wrapperClass="h-full" small={true}>
<svelte:fragment slot="action">
<div class="flex space-x-2">
<Popover
class="w-fit"
usePointerDownOutside
closeOnOtherPopoverOpen
on:click={(e) => {
e.stopPropagation()
}}
floatingConfig={{ placement: 'top-end' }}
>
<svelte:fragment slot="trigger">
<Button
variant="contained"
size="xs2"
color={emptySearchArgs ? 'light' : 'dark'}
nonCaptureEvent
title="Search history"
iconOnly={emptySearchArgs}
endIcon={{ icon: Search }}
>
{emptySearchArgs ? '' : 'Active filters'}
</Button>
</svelte:fragment>
<svelte:fragment slot="content">
<div id="multi-select-search"></div>
<div class="p-2 overflow-auto max-h-[400px] min-h-[300px] w-[400px]">
<div class="flex items-center flex-wrap gap-x-2 justify-between">
<div class="text-sm text-secondary">Search by args</div>
<div class="flex flex-wrap gap-x-2">
{#if !emptySearchArgs}
<Button
on:click={async () => {
searchArgs = {}
appliedSearchArgs = {}
await tick()
historicInputs?.refresh(true)
}}
variant="contained"
size="xs2"
color="light">Reset filters</Button
>
{/if}
<Button
on:click={async () => {
appliedSearchArgs = structuredClone(searchArgs)
await tick()
historicInputs?.refresh(true)
}}
endIcon={{ icon: Search }}
variant="contained"
size="xs2"
color="dark">Search</Button
>
</div>
</div>
<div class="my-2">
<MultiSelect
topPlacement
target="#multi-select-search"
placeholder="arg fields to filter on"
items={Object.keys(schema?.properties ?? {})}
bind:value={searchArgsFields}
/>
</div>
{#key filteredSchema}
<SchemaForm shouldHideNoInputs schema={filteredSchema} bind:args={searchArgs} />
{/key}
{#if searchArgsFields.length === 0}
<div class="text-secondary text-sm my-8 mx-auto">No filters</div>
{/if}
</div>
</svelte:fragment>
</Popover>
<Button
size="xs2"
color="light"
btnClasses="!text-tertiary"
endIcon={{ icon: ExternalLink }}
on:click={() => {
window.open(`/runs/${runnableId}`, '_blank')
}}
>
All runs
</Button>
</div>
</svelte:fragment>
<HistoricInputs
bind:this={historicInputs}
{runnableId}
{runnableType}
on:select={(e) => {
if (e.detail) savedInputsPicker?.resetSelected()
selectArgs(e.detail?.args, e.detail ? 'history' : undefined)
}}
searchArgs={emptySearchArgs ? undefined : appliedSearchArgs}
showAuthor
placement="top-end"
/>
</Section>
</Pane>
</Splitpanes>
</div>