Files
windmill/frontend/src/lib/components/BatchLoadProgress.svelte
T
Ruben Fiszel 2bf9cfcd59 fix: search slow runs filters by time windows instead of timing out (#11549)
* fix: search slow runs filters by time windows instead of timing out

* fix: cancel a pending runs page when its listing is reset

* fix: keep runs scan windows disjoint at microsecond precision

* fix: race the single runs request against the window scan

* fix: list the cursor window when a runs scan starts at the oldest job

* fix: show the runs history scan as an info alert

* fix: show runs scan progress as a bar and keep the session button on the searchbar row

* fix: stop a runs scan whose windows are no faster when narrower

* fix: right-align the runs searchbar row when the header wraps

* fix: keep the runs scan stop button inside a narrow list pane
2026-10-06 08:57:54 +00:00

71 lines
2.0 KiB
Svelte

<script lang="ts">
import Button from './common/button/Button.svelte'
import TextInput from './text_input/TextInput.svelte'
interface Props {
loaded: number
total: number
itemsLabel: string
/** Replaces the default "Loading … of …" text, for progress that is not a count of items. */
label?: string
batchSize?: number | null
/** Largest batch the caller can fetch in one request, when that is below the page size. */
batchSizeCap?: number
onBatchSizeChange?: (batchSize: number) => void
onStop: () => void
}
let {
loaded,
total,
itemsLabel,
label,
batchSize = null,
batchSizeCap,
onBatchSizeChange,
onStop
}: Props = $props()
let percent = $derived(total > 0 ? Math.round((Math.min(loaded, total) / total) * 100) : 0)
// A batch as large as the whole page is not a batch: it would end the streaming this row exists
// to drive, taking the row itself away mid-edit.
let maxBatchSize = $derived(Math.max(1, Math.min(total - 1, batchSizeCap ?? total - 1)))
</script>
<div class="flex items-center gap-3 text-xs text-secondary">
{#if label}
<!-- A custom label has no bounded length: it gives way before the bar and Stop do. -->
<span class="min-w-0 truncate" title={label}>{label}</span>
{:else}
<span class="whitespace-nowrap shrink-0">Loading {itemsLabel}: {loaded} of {total}...</span>
{/if}
<div class="flex-1 min-w-8 bg-surface-hover rounded-full h-1.5">
<div
class="bg-blue-500 h-1.5 rounded-full transition-all duration-300"
style="width: {percent}%"
></div>
</div>
{#if batchSize != null}
<span class="whitespace-nowrap shrink-0">Batch size:</span>
<TextInput
size="xs"
class="!w-14 shrink-0 text-center"
value={batchSize}
inputProps={{
type: 'number',
min: 1,
max: maxBatchSize,
onchange: (e) => {
const v = parseInt(e.currentTarget.value)
if (v >= 1 && v <= maxBatchSize) {
onBatchSizeChange?.(v)
} else {
e.currentTarget.value = String(batchSize)
}
}
}}
/>
{/if}
<Button size="xs" destructive onClick={onStop}>Stop</Button>
</div>