diff --git a/frontend/src/lib/components/runs/RunBadges.svelte b/frontend/src/lib/components/runs/RunBadges.svelte
index 6340821860..872f227ad2 100644
--- a/frontend/src/lib/components/runs/RunBadges.svelte
+++ b/frontend/src/lib/components/runs/RunBadges.svelte
@@ -29,11 +29,20 @@
onFilterByConcurrencyKey,
large = false
}: Props = $props()
+
+ // Open links to another workspace in a new tab so we don't switch the active
+ // workspace of the current tab.
+ let isForeignWorkspace = $derived(
+ job.workspace_id != undefined && job.workspace_id !== $workspaceStore
+ )
{#if job.script_hash && showScriptHash && job.job_kind !== 'aiagent'}
{#if job.job_kind == 'script'}
- {truncateHash(job.script_hash)}
import { base } from '$lib/base'
+ import { workspaceStore } from '$lib/stores'
import { goto } from '$lib/navigation'
import type { Job } from '$lib/gen'
import {
@@ -55,6 +56,12 @@
let isExternal = $derived(job && job.id === '-')
+ // Open links to another workspace in a new tab so we don't switch the active
+ // workspace of the current tab.
+ let isForeignWorkspace = $derived(
+ job?.workspace_id != undefined && job.workspace_id !== $workspaceStore
+ )
+
let labelWidth = $state(0)
let isJobRecent = $state(true)
@@ -156,19 +163,27 @@
{/if}
- {#snippet text()}
-
- {#if job && job.job_kind}
- {getJobKindDisplayLabel(job.job_kind, job.script_path)}
- {/if}
- {#if job && job.is_flow_step && job.parent_job}
+ {#snippet text()}
+
+ {#if job && job.job_kind}
+ {getJobKindDisplayLabel(job.job_kind, job.script_path)}
+ {/if}
+ {#if job && job.is_flow_step && job.parent_job}
Step of flow
-
+
{truncateRev(job.parent_job, 10)}
{:else if job && job.parent_job}
Parent
-
+
{truncateRev(job.parent_job, 10)}
{/if}
diff --git a/frontend/src/lib/components/runs/RunsTable.svelte b/frontend/src/lib/components/runs/RunsTable.svelte
index 891f2732b3..c4b26ebb39 100644
--- a/frontend/src/lib/components/runs/RunsTable.svelte
+++ b/frontend/src/lib/components/runs/RunsTable.svelte
@@ -20,6 +20,7 @@
import DropdownMenu, { type Props as DropdownMenuProps } from '../DropdownMenu.svelte'
import { clickOutside, isJobCancelable, isJobReRunnable } from '$lib/utils'
import { goto } from '$lib/navigation'
+ import { base } from '$lib/base'
import BarsStaggered from '../icons/BarsStaggered.svelte'
interface Props {
@@ -266,24 +267,35 @@
// one, so target the job's own workspace (not the active one).
const jobWorkspace =
(job?.type === 'job' ? job.job.workspace_id : undefined) ?? $workspaceStore
+ // When the job lives in a different workspace, open in a new tab so we
+ // don't switch the active workspace of the current tab.
+ const isForeignWorkspace = jobWorkspace != undefined && jobWorkspace !== $workspaceStore
+ const navigateTo = (path: string) => {
+ if (isForeignWorkspace) {
+ window.open(`${base}${path}`, '_blank')
+ } else {
+ goto(path)
+ }
+ }
actions.push({
label: 'Show run details',
icon: ExternalLinkIcon,
- onClick: () => goto(`/run/${selectedIds[0]}?workspace=${jobWorkspace}`)
+ onClick: () => navigateTo(`/run/${selectedIds[0]}?workspace=${jobWorkspace}`)
})
if (job?.type === 'job') {
if (job.job.job_kind === 'script') {
actions.push({
label: 'Go to script page',
icon: Code2Icon,
- onClick: () => goto(`/scripts/get/${job.job.script_hash}?workspace=${jobWorkspace}`)
+ onClick: () =>
+ navigateTo(`/scripts/get/${job.job.script_hash}?workspace=${jobWorkspace}`)
})
}
if (job.job.job_kind === 'flow') {
actions.push({
label: 'Go to flow page',
icon: BarsStaggered,
- onClick: () => goto(`/flows/get/${job.job.script_path}?workspace=${jobWorkspace}`)
+ onClick: () => navigateTo(`/flows/get/${job.job.script_path}?workspace=${jobWorkspace}`)
})
}
}