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}`) }) } }