@@ -156,7 +168,7 @@
diff --git a/frontend/src/lib/components/FlowPreviewContent.svelte b/frontend/src/lib/components/FlowPreviewContent.svelte
index 75d960ba18..638b63877f 100644
--- a/frontend/src/lib/components/FlowPreviewContent.svelte
+++ b/frontend/src/lib/components/FlowPreviewContent.svelte
@@ -13,7 +13,7 @@
import { AlertTriangle, ArrowRight, CornerDownLeft, Play, RefreshCw, X } from 'lucide-svelte'
import { emptyString, sendUserToast } from '$lib/utils'
import { dfs } from './flows/dfs'
- import { sliceModules } from './flows/flowStateUtils'
+ import { sliceModules } from './flows/flowStateUtils.svelte'
import InputSelectedBadge from './schema/InputSelectedBadge.svelte'
import Toggle from './Toggle.svelte'
import JsonInputs from './JsonInputs.svelte'
@@ -53,7 +53,7 @@
export function test() {
renderCount++
- runPreview($previewArgs, undefined)
+ runPreview(previewArgs.val, undefined)
}
const {
@@ -75,9 +75,9 @@
function extractFlow(previewMode: 'upTo' | 'whole'): OpenFlow {
if (previewMode === 'whole') {
- return $flowStore
+ return flowStore.val
} else {
- const flow: Flow = JSON.parse(JSON.stringify($flowStore))
+ const flow: Flow = JSON.parse(JSON.stringify(flowStore.val))
const idOrders = dfs(flow.value.modules, (x) => x.id)
let upToIndex = idOrders.indexOf($selectedId)
@@ -97,13 +97,13 @@
initial = false
}
try {
- lastPreviewFlow = JSON.stringify($flowStore)
+ lastPreviewFlow = JSON.stringify(flowStore.val)
jobProgressReset()
const newFlow = extractFlow(previewMode)
jobId = await runFlowPreview(args, newFlow, $pathStore, restartedFrom)
isRunning = true
if (inputSelected) {
- savedArgs = $previewArgs
+ savedArgs = previewArgs.val
inputSelected = undefined
}
} catch (e) {
@@ -120,7 +120,7 @@
case 'Enter':
if (event.ctrlKey || event.metaKey) {
event.preventDefault()
- runPreview($previewArgs, undefined)
+ runPreview(previewArgs.val, undefined)
}
break
@@ -156,20 +156,20 @@
}
}
- let savedArgs = $previewArgs
+ let savedArgs = previewArgs.val
let inputSelected: 'captures' | 'history' | 'saved' | undefined = undefined
async function selectInput(input, type?: 'captures' | 'history' | 'saved' | undefined) {
if (!input) {
- $previewArgs = savedArgs
+ previewArgs.val = savedArgs
inputSelected = undefined
setTimeout(() => {
preventEscape = false
}, 100)
} else {
- $previewArgs = input
+ previewArgs.val = input
inputSelected = type
preventEscape = true
- jsonEditor?.setCode(JSON.stringify($previewArgs ?? {}, null, '\t'))
+ jsonEditor?.setCode(JSON.stringify(previewArgs.val ?? {}, null, '\t'))
}
}
@@ -185,7 +185,7 @@
async function loadIndividualStepsStates() {
// console.log('loadIndividualStepsStates')
- dfs($flowStore.value.modules, async (module) => {
+ dfs(flowStore.val.value.modules, async (module) => {
// console.log('module', $flowStateStore[module.id], module.id)
const prev = $flowStateStore[module.id]?.previewResult
if (prev && prev != NEVER_TESTED_THIS_FAR) {
@@ -283,7 +283,7 @@
variant="border"
title={`Re-start this flow from step ${selectedJobStep} (included).`}
on:click={() => {
- runPreview($previewArgs, {
+ runPreview(previewArgs.val, {
flow_job_id: jobId,
step_id: selectedJobStep,
branch_or_iteration_n: 0
@@ -308,7 +308,7 @@
color="blue"
startIcon={{ icon: RefreshCw }}
on:click={() => {
- runPreview($previewArgs, {
+ runPreview(previewArgs.val, {
flow_job_id: jobId,
step_id: selectedJobStep,
branch_or_iteration_n: 0
@@ -354,7 +354,7 @@
btnClasses="!p-1 !w-[34px] !ml-1"
aria-label="Restart flow"
on:click|once={() => {
- runPreview($previewArgs, {
+ runPreview(previewArgs.val, {
flow_job_id: jobId,
step_id: selectedJobStep,
branch_or_iteration_n: branchOrIterationN
@@ -375,7 +375,7 @@
color="dark"
size="sm"
btnClasses="w-full max-w-lg"
- on:click={() => runPreview($previewArgs, undefined)}
+ on:click={() => runPreview(previewArgs.val, undefined)}
id="flow-editor-test-flow-drawer"
shortCut={{ Icon: CornerDownLeft }}
>
@@ -385,7 +385,7 @@
{/if}
- {#if lastPreviewFlow && JSON.stringify($flowStore) != lastPreviewFlow}
+ {#if lastPreviewFlow && JSON.stringify(flowStore.val) != lastPreviewFlow}
{
selectInput(e.detail.payload, e.detail?.type)
@@ -433,7 +433,7 @@
}}
lightMode
on:change={(e) => {
- jsonEditor?.setCode(JSON.stringify($previewArgs ?? {}, null, '\t'))
+ jsonEditor?.setCode(JSON.stringify(previewArgs.val ?? {}, null, '\t'))
refresh()
}}
/>
@@ -445,7 +445,7 @@
bind:this={jsonEditor}
on:select={(e) => {
if (e.detail) {
- $previewArgs = e.detail
+ previewArgs.val = e.detail
}
}}
updateOnBlur={false}
@@ -458,10 +458,10 @@
{
- savedArgs = $previewArgs
+ savedArgs = previewArgs.val
}}
bind:isValid
/>
diff --git a/frontend/src/lib/components/FlowStatusViewerInner.svelte b/frontend/src/lib/components/FlowStatusViewerInner.svelte
index 8a2a630268..a4a6d9edcd 100644
--- a/frontend/src/lib/components/FlowStatusViewerInner.svelte
+++ b/frontend/src/lib/components/FlowStatusViewerInner.svelte
@@ -29,7 +29,7 @@
import Alert from './common/alert/Alert.svelte'
import FlowGraphViewerStep from './FlowGraphViewerStep.svelte'
import FlowGraphV2 from './graph/FlowGraphV2.svelte'
- import { buildPrefix } from './graph/graphBuilder'
+ import { buildPrefix } from './graph/graphBuilder.svelte'
const dispatch = createEventDispatcher()
@@ -1253,31 +1253,29 @@
success={jobId != undefined && isSuccess(job?.['success'])}
flowModuleStates={$localModuleStates}
bind:expandedSubflows
- on:select={(e) => {
+ onSelect={(e) => {
+ console.log('onSelect', e)
if (rightColumnSelect != 'node_definition') {
rightColumnSelect = 'node_status'
}
- if (typeof e.detail == 'string') {
- if (e.detail == 'Input') {
+ if (typeof e == 'string') {
+ if (e == 'Input') {
selectedNode = 'start'
stepDetail = undefined
- } else if (e.detail == 'Result') {
+ } else if (e == 'Result') {
selectedNode = 'end'
stepDetail = 'end'
} else {
- const mod = dfs(job?.raw_flow?.modules ?? [], (m) => m).find(
- (m) => m?.id === e?.detail
- )
+ const mod = dfs(job?.raw_flow?.modules ?? [], (m) => m).find((m) => m?.id === e)
stepDetail = mod
- selectedNode = e?.detail
+ selectedNode = e
}
} else {
- stepDetail = e.detail
- selectedNode = e.detail.id
+ stepDetail = e
+ selectedNode = e.id
}
}}
- on:selectedIteration={async (e) => {
- let detail = e.detail
+ onSelectedIteration={async (detail) => {
if (detail.manuallySet) {
let rootJobId = detail.id
await tick()
diff --git a/frontend/src/lib/components/FlowViewer.svelte b/frontend/src/lib/components/FlowViewer.svelte
index 49ad0bc54b..4f2ab8a456 100644
--- a/frontend/src/lib/components/FlowViewer.svelte
+++ b/frontend/src/lib/components/FlowViewer.svelte
@@ -8,20 +8,30 @@
import FlowViewerInner from './FlowViewerInner.svelte'
import FlowInputViewer from './FlowInputViewer.svelte'
- export let flow: {
- summary: string
- description?: string
- value: FlowValue
- schema?: any
+ interface Props {
+ flow: {
+ summary: string
+ description?: string
+ value: FlowValue
+ schema?: any
+ }
+ initialOpen?: number | undefined
+ noSide?: boolean
+ noGraph?: boolean
+ tab?: 'ui' | 'raw' | 'schema'
+ noSummary?: boolean
+ noGraphDownload?: boolean
}
- export let initialOpen: number | undefined = undefined
- export let noSide = false
- export let noGraph: boolean = false
-
- export let tab: 'ui' | 'raw' | 'schema' = noGraph ? 'schema' : 'ui'
- export let noSummary = false
- export let noGraphDownload = false
+ let {
+ flow,
+ initialOpen = undefined,
+ noSide = false,
+ noGraph = false,
+ tab = $bindable(noGraph ? 'schema' : 'ui'),
+ noSummary = false,
+ noGraphDownload = false
+ }: Props = $props()
let open: { [id: number]: boolean } = {}
if (initialOpen) {
@@ -38,7 +48,7 @@
Raw
Input Schema
-
+ {#snippet content()}
{#if !noSummary}
@@ -65,5 +75,5 @@
-
+ {/snippet}
diff --git a/frontend/src/lib/components/FlowViewerInner.svelte b/frontend/src/lib/components/FlowViewerInner.svelte
index e4bec76006..0e300c8410 100644
--- a/frontend/src/lib/components/FlowViewerInner.svelte
+++ b/frontend/src/lib/components/FlowViewerInner.svelte
@@ -11,16 +11,20 @@
import HighlightTheme from './HighlightTheme.svelte'
import { filteredContentForExport } from './flows/utils'
- export let flow: {
- summary: string
- description?: string
- value: FlowValue
- schema?: any
+ interface Props {
+ flow: {
+ summary: string
+ description?: string
+ value: FlowValue
+ schema?: any
+ }
}
- $: flowFiltered = filteredContentForExport(flow)
+ let { flow }: Props = $props()
- let rawType: 'json' | 'yaml' = 'yaml'
+ let flowFiltered = $derived(filteredContentForExport(flow))
+
+ let rawType: 'json' | 'yaml' = $state('yaml')
function trimStringToLines(inputString: string, maxLines: number = 100): string {
const lines = inputString?.split('\n') ?? []
@@ -29,7 +33,7 @@
return linesToKeep.join('\n')
}
- let code: string = ''
+ let code: string = $state('')
function computeCode() {
const str =
@@ -44,11 +48,13 @@
code = str
}
- let shouldDisplayLoadMore = false
+ let shouldDisplayLoadMore = $state(false)
- $: flowFiltered && rawType && computeCode()
+ $effect(() => {
+ flowFiltered && rawType && computeCode()
+ })
- let maxLines = 100
+ let maxLines = $state(100)
@@ -62,7 +68,7 @@
>
YAML
JSON
-
+ {#snippet content()}
{/if}
-
+ {/snippet}
diff --git a/frontend/src/lib/components/FolderEditor.svelte b/frontend/src/lib/components/FolderEditor.svelte
index 22229d8f8e..c12aecf9c7 100644
--- a/frontend/src/lib/components/FolderEditor.svelte
+++ b/frontend/src/lib/components/FolderEditor.svelte
@@ -184,13 +184,11 @@
- (ownerItem = '')}
- let:item
- >
-
-
+ (ownerItem = '')}>
+ {#snippet children({ item })}
+
+
+ {/snippet}
@@ -278,7 +276,6 @@
{
const role = e.detail
// const wasInFolder = (folder?.owners ?? []).includes(folder)
@@ -315,28 +312,30 @@
loadFolder()
}}
>
-
+ {#snippet children({ item })}
+
-
+
-
+
+ {/snippet}
{:else}
diff --git a/frontend/src/lib/components/GroupEditor.svelte b/frontend/src/lib/components/GroupEditor.svelte
index fbe03bd9f0..1f66cabfec 100644
--- a/frontend/src/lib/components/GroupEditor.svelte
+++ b/frontend/src/lib/components/GroupEditor.svelte
@@ -150,7 +150,6 @@
{
const role = e.detail
// const wasInGroup = (group?.members ?? []).includes(group)
@@ -211,31 +210,33 @@
loadGroup()
}}
>
-
-
- {#if role === 'manager'}
+ {#snippet children({ item })}
- {/if}
+
+ {#if role === 'manager'}
+
+ {/if}
+ {/snippet}
{:else}
diff --git a/frontend/src/lib/components/HistoricInputs.svelte b/frontend/src/lib/components/HistoricInputs.svelte
index 1acd9a9e28..ac79c0479b 100644
--- a/frontend/src/lib/components/HistoricInputs.svelte
+++ b/frontend/src/lib/components/HistoricInputs.svelte
@@ -8,21 +8,34 @@
import HistoricList from './HistoricList.svelte'
import { Loader2 } from 'lucide-svelte'
- export let runnableId: string | undefined = undefined
- export let runnableType: RunnableType | undefined = undefined
- export let loading: boolean = false
- export let selected: string | undefined = undefined
- export let showAuthor = false
- export let placement: 'bottom-start' | 'top-start' | 'bottom-end' | 'top-end' = 'top-end'
- export let limitPayloadSize = false
- export let searchArgs: Record | undefined = undefined
+ interface Props {
+ runnableId?: string | undefined
+ runnableType?: RunnableType | undefined
+ loading?: boolean
+ selected?: string | undefined
+ showAuthor?: boolean
+ placement?: 'bottom-start' | 'top-start' | 'bottom-end' | 'top-end'
+ limitPayloadSize?: boolean
+ searchArgs?: Record | undefined
+ }
- let historicList: HistoricList | undefined = undefined
+ let {
+ runnableId = undefined,
+ runnableType = undefined,
+ loading = $bindable(false),
+ selected = $bindable(undefined),
+ showAuthor = false,
+ placement = 'top-end',
+ limitPayloadSize = false,
+ searchArgs = undefined
+ }: Props = $props()
+
+ let historicList: HistoricList | undefined = $state(undefined)
const dispatch = createEventDispatcher()
- let jobs: Job[] = []
+ let jobs: Job[] = $state([])
let hasMoreCurrentRuns = false
- let page = 1
+ let page = $state(1)
async function handleSelected(data: any) {
if (selected === data.id) {
@@ -34,7 +47,10 @@
const fullPayload = await data.getFullPayload?.()
dispatch('select', { args: fullPayload, jobId: data.id })
} else {
- dispatch('select', { args: structuredClone(data.payloadData), jobId: data.id })
+ dispatch('select', {
+ args: structuredClone($state.snapshot(data.payloadData)),
+ jobId: data.id
+ })
}
}
@@ -77,11 +93,11 @@
} else if (runnableType === 'ScriptHash') {
return 'script,preview'
}
- return 'all'
+ return ''
}
-
+
{#if runnableId}
import { InputService, type RunnableType } from '$lib/gen'
import { workspaceStore } from '$lib/stores'
- import { onDestroy } from 'svelte'
+ import { onDestroy, untrack } from 'svelte'
import InfiniteList from './InfiniteList.svelte'
import JobSchemaPicker from './schema/JobSchemaPicker.svelte'
- export let runnableId: string | undefined
- export let runnableType: RunnableType | undefined
- export let selected: string | undefined = undefined
- export let showAuthor = false
- export let placement: 'bottom-start' | 'top-start' | 'bottom-end' | 'top-end' = 'bottom-start'
- export let limitPayloadSize = false
- export let searchArgs: Record | undefined = undefined
+ interface Props {
+ runnableId: string | undefined
+ runnableType: RunnableType | undefined
+ selected?: string | undefined
+ showAuthor?: boolean
+ placement?: 'bottom-start' | 'top-start' | 'bottom-end' | 'top-end'
+ limitPayloadSize?: boolean
+ searchArgs?: Record | undefined
+ }
- let infiniteList: InfiniteList | undefined = undefined
+ let {
+ runnableId,
+ runnableType,
+ selected = undefined,
+ showAuthor = false,
+ placement = 'bottom-start',
+ limitPayloadSize = false,
+ searchArgs = undefined
+ }: Props = $props()
+
+ let infiniteList: InfiniteList | undefined = $state(undefined)
let loadInputsPageFn: ((page: number, perPage: number) => Promise) | undefined = undefined
- let viewerOpen = false
+ let viewerOpen = $state(false)
let openStates: Record = {} // Track open state for each item
export async function refresh(clearCurrentRuns: boolean = false) {
@@ -101,18 +113,20 @@
viewerOpen = Object.values(openStates).some((state) => state)
}
- $: $workspaceStore && runnableId && runnableType && infiniteList && initLoadInputs()
+ $effect(() => {
+ $workspaceStore && runnableId && runnableType && infiniteList && untrack(() => initLoadInputs())
+ })
-
+ {#snippet columns()}
-
-
+ {/snippet}
+ {#snippet children({ item, hover })}
-
-
+ {/snippet}
+ {#snippet empty()}
{runnableId ? 'No previous inputs' : 'Save draft to see previous runs'}
-
+ {/snippet}
diff --git a/frontend/src/lib/components/IconedResourceType.svelte b/frontend/src/lib/components/IconedResourceType.svelte
index 5daea14d17..7375c64cd7 100644
--- a/frontend/src/lib/components/IconedResourceType.svelte
+++ b/frontend/src/lib/components/IconedResourceType.svelte
@@ -1,18 +1,35 @@
@@ -20,12 +37,13 @@
{name}
{/if}
{#if iconComponent}
+ {@const SvelteComponent = iconComponent}
-
+
{:else if formatExtension}
-
+
{:else}
@@ -34,4 +52,3 @@
{name}
{/if}
-
diff --git a/frontend/src/lib/components/InfiniteList.svelte b/frontend/src/lib/components/InfiniteList.svelte
index 6457d5ea60..b4afaf41ba 100644
--- a/frontend/src/lib/components/InfiniteList.svelte
+++ b/frontend/src/lib/components/InfiniteList.svelte
@@ -6,26 +6,48 @@
const dispatch = createEventDispatcher()
- export let loading = false
- export let items: any[] | undefined = undefined
- export let selectedItemId: any | undefined = undefined
- export let isEmpty: boolean = true
- export let length: number = 0
- export let rounded: boolean = true
- export let noBorder: boolean = false
- export let extraRowClasses: { bgSelected: string; bgHover: string; class: string } = {
- bgSelected: '',
- bgHover: '',
- class: ''
+ interface Props {
+ loading?: boolean
+ items?: any[] | undefined
+ selectedItemId?: any | undefined
+ isEmpty?: boolean
+ length?: number
+ rounded?: boolean
+ noBorder?: boolean
+ extraRowClasses?: { bgSelected: string; bgHover: string; class: string }
+ neverShowLoader?: boolean
+ columns?: import('svelte').Snippet
+ extra_row?: import('svelte').Snippet<[any]>
+ children?: import('svelte').Snippet<[any]>
+ empty?: import('svelte').Snippet<[any]>
}
- export let neverShowLoader = false
+
+ let {
+ loading = $bindable(false),
+ items = $bindable(undefined),
+ selectedItemId = $bindable(undefined),
+ isEmpty = $bindable(true),
+ length = $bindable(0),
+ rounded = true,
+ noBorder = false,
+ extraRowClasses = {
+ bgSelected: '',
+ bgHover: '',
+ class: ''
+ },
+ neverShowLoader = false,
+ columns,
+ extra_row,
+ children,
+ empty
+ }: Props = $props()
const perPage = 20
- let hasMore = false
+ let hasMore = $state(false)
let page = 1
let hasAlreadyFailed = false
- let hovered: any | undefined = undefined
+ let hovered: any | undefined = $state(undefined)
let initLoad = false
let loadInputs: ((page: number, perPage: number) => Promise) | undefined = undefined
let deleteItemFn: ((id: any) => Promise) | undefined = undefined
@@ -39,7 +61,7 @@
page = 1
}
- let loadingMore = false
+ let loadingMore = $state(false)
export async function loadData(loadOption: 'refresh' | 'forceRefresh' | 'loadMore' = 'loadMore') {
// console.log('loadData', loadOption, length, items?.length)
@@ -146,7 +168,7 @@
{noBorder}
{neverShowLoader}
>
-
+ {@render columns?.()}
(hovered = e.detail ? 'extraRow' : undefined)}
>
-
+ {@render extra_row?.({ hover: hovered === 'extraRow' })}
{#each items ?? [] as item, index}
{@const hover = item.id === hovered}
@@ -171,16 +193,16 @@
)}
on:hover={(e) => (hovered = e.detail ? item.id : undefined)}
>
-
+ {@render children?.({ item, hover })}
{/each}
-
+ {#snippet emptyMessage()}
{#if (!items || items?.length === 0) && (!loading || neverShowLoader)}
-
+ {@render empty?.({ items })}
{/if}
-
+ {/snippet}