fix: runs page date picker query parameter handling

- Route query params by job status: queue-only statuses (running/suspended/waiting)
  use createdBeforeQueue/createdAfterQueue, completed-only statuses (success/failure)
  skip queue params, and no filter uses both
- Pass completedAfter (extendedMinTs) on initial load to avoid overfetching
- Skip auto-refresh syncer for manual timeframes (fixed past date ranges)
- Debounce param change effect to prevent double API calls
- Remove redundant timeframe dependency from effect (already tracked via filters)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Ruben Fiszel
2026-02-26 18:18:54 +00:00
co-authored by Claude Opus 4.6
parent eeb823b0b5
commit 0c739a7542
@@ -109,6 +109,7 @@ export function useJobsLoader(args: () => UseJobLoaderArgs) {
let intervalId: ReturnType<typeof setInterval> | undefined = $state()
let sync = true
let paramChangeTimeout: ReturnType<typeof setTimeout> | undefined
function onParamChanges() {
resetJobs()
@@ -180,11 +181,18 @@ export function useJobsLoader(args: () => UseJobLoaderArgs) {
loadingFetch = true
let scriptPathStart = folder == null || folder === '' ? undefined : `f/${folder}/`
let scriptPathExact = path == null || path === '' ? undefined : path
let isQueueOnly = success == 'running' || success == 'suspended' || success == 'waiting'
let isCompletedOnly = success == 'success' || success == 'failure'
let promise = JobService.listJobs({
workspace: currentWorkspace,
completedBefore: completedBefore ?? undefined,
completedAfter: completedAfter ?? undefined,
createdAfterQueue,
completedBefore: isQueueOnly ? undefined : (completedBefore ?? undefined),
completedAfter: isQueueOnly ? undefined : (completedAfter ?? undefined),
createdBeforeQueue: isQueueOnly ? (completedBefore ?? undefined) : undefined,
createdAfterQueue: isCompletedOnly
? undefined
: isQueueOnly
? (completedAfter ?? createdAfterQueue)
: createdAfterQueue,
schedulePath: schedulePath ?? undefined,
scriptPathExact,
createdBy: user == null || user === '' ? undefined : user,
@@ -311,16 +319,19 @@ export function useJobsLoader(args: () => UseJobLoaderArgs) {
const extendedMinTs = subtractDaysFromDateString(minTs, lookback)
if (concurrencyKey == null || concurrencyKey === '') {
return CancelablePromiseUtils.map(fetchJobs(maxTs, null, extendedMinTs), (newJobs) => {
extendedJobs = { jobs: newJobs, obscured_jobs: [] } as ExtendedJobs
return CancelablePromiseUtils.map(
fetchJobs(maxTs, extendedMinTs ?? null, extendedMinTs),
(newJobs) => {
extendedJobs = { jobs: newJobs, obscured_jobs: [] } as ExtendedJobs
// Filter on minTs here and not in the backend
// to get enough data for the concurrency graph
jobs = sortMinDate(minTs, newJobs)
externalJobs = []
computeCompletedJobs()
loading = false
})
// Filter on minTs here and not in the backend
// to get enough data for the concurrency graph
jobs = sortMinDate(minTs, newJobs)
externalJobs = []
computeCompletedJobs()
loading = false
}
)
} else {
return CancelablePromiseUtils.map(
fetchExtendedJobs(concurrencyKey, maxTs, extendedMinTs ?? null),
@@ -379,6 +390,9 @@ export function useJobsLoader(args: () => UseJobLoaderArgs) {
if (loadingFetch) {
return
}
if (timeframe?.type === 'manual') {
return
}
if (sync) {
if (syncQueuedRunsCount) {
getCount()
@@ -526,12 +540,18 @@ export function useJobsLoader(args: () => UseJobLoaderArgs) {
Object.keys(filters ?? {}).map((k) => filters?.[k as keyof RunsFilterInstance])
currentWorkspace
lookback
timeframe
perPage
showSchedules
showFutureJobs
let p = untrack(() => onParamChanges())
return () => p.cancel()
let p: CancelablePromise<void> | undefined
clearTimeout(paramChangeTimeout)
paramChangeTimeout = setTimeout(() => {
p = untrack(() => onParamChanges())
}, 0)
return () => {
clearTimeout(paramChangeTimeout)
p?.cancel()
}
})
$effect(() => {
;[autoRefresh, refreshRate]