diff --git a/frontend/src/lib/components/RunsPage.svelte b/frontend/src/lib/components/RunsPage.svelte
index 97f2723943..ff32cbdbd7 100644
--- a/frontend/src/lib/components/RunsPage.svelte
+++ b/frontend/src/lib/components/RunsPage.svelte
@@ -51,10 +51,11 @@
import BatchLoadProgress from '$lib/components/BatchLoadProgress.svelte'
import { pluralize, MAX_RESOLUTION_BATCH, MAX_RESOLUTION_NOTE_LEN } from '$lib/utils'
import type { BatchReRunOptions } from '$lib/components/runs/BatchReRunOptionsPane.svelte'
- import { untrack } from 'svelte'
+ import { untrack, type Snippet } from 'svelte'
import { page } from '$app/state'
import Select from '$lib/components/select/Select.svelte'
import AnimatedPane from '$lib/components/splitPanes/AnimatedPane.svelte'
+ import PagedContent from '$lib/components/common/modal/PagedContent.svelte'
import { StaleWhileLoading, useLocalStorageValue } from '$lib/svelte5Utils.svelte'
import {
Calendar,
@@ -63,8 +64,9 @@
CirclePlay,
Clock,
Hourglass,
- Loader2,
- TriangleAlertIcon
+ TriangleAlertIcon,
+ ArrowLeft,
+ Loader2
} from 'lucide-svelte'
import DropdownV2 from './DropdownV2.svelte'
import TimeframeSelect, {
@@ -208,6 +210,7 @@
function reset() {
_timeframe.val = { ...runsTimeframes[0] }
selectedIds = []
+ openedRunId = undefined
delete filters.val.schedule_path
selectedWorkspace = undefined
jobsLoader?.loadJobs(true)
@@ -498,6 +501,9 @@
})
selectedIds = []
+ // Opened from the table's "Run again", the options are done; left open, the next selection
+ // of one run would show them again. The re-run selection mode keeps them for its next batch.
+ if (!manualSelectionMode) batchRerunOptionsIsOpen = false
jobsLoader?.loadJobs(true, true)
}
@@ -581,6 +587,27 @@
)
let manualSelectionMode: undefined | 'cancel' | 'rerun' | 'resolve' = $state()
+
+ // Below 1024px (Tailwind `lg`) the side pane leaves the table too little room, so what it would
+ // show becomes a page pushed over the list. Selection modes keep the split: their rows are
+ // picked in the list while the pane holds the action.
+ const pagedLayout = $derived(innerWidth < 1024 && !manualSelectionMode)
+ // Set only by a plain row click, a chart point or the arrow keys, never by a modifier click:
+ // a Ctrl/Cmd/Shift-click starting a multi-selection selects one run first, and opening it would
+ // hide the list before the second click.
+ let openedRunId: string | undefined = $state()
+ const runPageOpen = $derived(
+ // A confirmed re-run clears the selection but leaves the options flag set.
+ (batchRerunOptionsIsOpen && selectedIds.length > 0) ||
+ (selectedIds.length === 1 && selectedIds[0] === openedRunId)
+ )
+
+ // Clears the selection too: a re-run selection of one job would otherwise land on that job.
+ function backToList() {
+ batchRerunOptionsIsOpen = false
+ selectedIds = []
+ openedRunId = undefined
+ }
let resolutionNote = $state('')
@@ -929,6 +956,7 @@
_timeframe.val = buildManualTimeframe(zoom.min.toISOString(), zoom.max.toISOString())
}}
onPointClicked={(ids) => {
+ openedRunId = ids.length === 1 ? ids[0] : undefined
runsTable?.scrollToRun(ids)
}}
/>
@@ -946,256 +974,331 @@