* feat: implement SSE for job updates polling - Add /getupdate_sse/:id endpoint for real-time job updates via Server-Sent Events - SSE streams job status, logs, progress, and flow status updates - Auto-stops streaming when job completes - Frontend uses EventSource with graceful fallback to polling on errors - Reduces server load and improves real-time responsiveness - Update OpenAPI spec with new SSE endpoint definition 🤖 Generated with [Claude Code](https://claude.ai/code) Co-authored-by: Ruben Fiszel <rubenfiszel@users.noreply.github.com> * all * all * v1 * rename test job loader * iter2 * nit * all * all * improve * upgrade * try catch assets json parse * only display loader of custom component if custom component is rendered * Fix required properties (#6221) * whitelabelling nits * remove fdsfs (#6222) * add refresh on worker tag select * whitelabel nits * merge * merge * done * nit fix * all * app db * all * all --------- Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> Co-authored-by: Ruben Fiszel <rubenfiszel@users.noreply.github.com> Co-authored-by: Ruben Fiszel <ruben@windmill.dev> Co-authored-by: Tammo Ippen <tammo.ippen@posteo.de> Co-authored-by: Diego Imbert <70353967+diegoimbert@users.noreply.github.com>
90 lines
2.6 KiB
Svelte
90 lines
2.6 KiB
Svelte
<script lang="ts">
|
|
import { getContext, untrack } from 'svelte'
|
|
import type { AppEditorContext } from '../types'
|
|
import JobLoader from '$lib/components/JobLoader.svelte'
|
|
import type { Job } from '$lib/gen'
|
|
import RunnableJobPanelInner from './RunnableJobPanelInner.svelte'
|
|
|
|
interface Props {
|
|
float?: boolean
|
|
hidden?: boolean
|
|
testJob?: Job | undefined
|
|
jobToWatch?: { componentId: string; job: string } | undefined
|
|
width?: number | undefined
|
|
}
|
|
|
|
let {
|
|
float = true,
|
|
hidden = false,
|
|
testJob = $bindable(undefined),
|
|
jobToWatch = $bindable(undefined),
|
|
width = undefined
|
|
}: Props = $props()
|
|
|
|
const { runnableJobEditorPanel, selectedComponentInEditor } =
|
|
getContext<AppEditorContext>('AppEditorContext')
|
|
let testIsLoading = $state(false)
|
|
|
|
let jobLoader: JobLoader | undefined = $state()
|
|
|
|
function updateSelectedJob() {
|
|
const selectedComponent = $selectedComponentInEditor
|
|
|
|
if (selectedComponent) {
|
|
const backendJob = $runnableJobEditorPanel.jobs[selectedComponent]
|
|
if (backendJob) {
|
|
if (jobToWatch?.job == backendJob) {
|
|
return
|
|
}
|
|
if (jobToWatch?.componentId != selectedComponent) {
|
|
testJob = undefined
|
|
}
|
|
jobToWatch = { componentId: selectedComponent, job: backendJob }
|
|
jobLoader?.watchJob(backendJob)
|
|
} else {
|
|
testJob = undefined
|
|
jobToWatch = undefined
|
|
}
|
|
}
|
|
}
|
|
|
|
let logDrawerOpen = false
|
|
let resultDrawerOpen = false
|
|
$effect(() => {
|
|
;($runnableJobEditorPanel.focused || !float) &&
|
|
$selectedComponentInEditor &&
|
|
$runnableJobEditorPanel.jobs &&
|
|
untrack(() => {
|
|
updateSelectedJob()
|
|
})
|
|
})
|
|
</script>
|
|
|
|
<JobLoader bind:this={jobLoader} bind:isLoading={testIsLoading} bind:job={testJob} />
|
|
|
|
{#if ($runnableJobEditorPanel.focused && $selectedComponentInEditor) || logDrawerOpen || resultDrawerOpen || !float}
|
|
{@const frontendJob = $runnableJobEditorPanel?.frontendJobs[$selectedComponentInEditor ?? '']}
|
|
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
{#if float}
|
|
<div
|
|
class="absolute z-[100] top-0 right-0 border-t h-full"
|
|
style="width: {$runnableJobEditorPanel.width}px; transform: translateX({$runnableJobEditorPanel.width}px);"
|
|
>
|
|
<RunnableJobPanelInner {testIsLoading} {frontendJob} {testJob} />
|
|
</div>
|
|
{:else}
|
|
<div
|
|
class="flex flex-col min-w-0 grow h-full"
|
|
style={width !== undefined ? `width:${width}px;` : ''}
|
|
>
|
|
{#if $selectedComponentInEditor}
|
|
<RunnableJobPanelInner {testIsLoading} {frontendJob} {testJob} />
|
|
{:else if !hidden}
|
|
<div class="text-sm text-secondary text-center py-8 px-2 border-l h-full">
|
|
Logs and results will be displayed here
|
|
</div>
|
|
{/if}
|
|
</div>
|
|
{/if}
|
|
{/if}
|