Skip to content

Commit 83ea4df

Browse files
committed
feat(logs): open the workflow from the log details panel
The workflow name in a log's details panel was static text, so the only way to reach the workflow was the row's right-click context menu. Make the label a link to the workflow editor, opening in a new tab so the log list keeps its filters, scroll position, and open panel. On hover or keyboard focus the leading workflow icon morphs into SquareArrowUpRight, reusing the grid-stacked cross-fade already used by the resource header breadcrumb. Sim agent jobs and deleted workflows have no reachable workflow and stay static text. Adds a `group-hover-hover` variant so the morph is gated on a real hover-capable pointer, matching the existing `hover-hover` variant and keeping touch devices out of a half-applied hover state.
1 parent d31bdf2 commit 83ea4df

2 files changed

Lines changed: 46 additions & 9 deletions

File tree

apps/sim/app/workspace/[workspaceId]/logs/components/log-details/log-details.tsx

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,13 @@ import {
2929
ChevronUp,
3030
Clipboard,
3131
Search,
32+
SquareArrowUpRight,
3233
Workflow,
3334
Wrench,
3435
X,
3536
} from '@sim/emcn/icons'
3637
import { formatDuration } from '@sim/utils/formatting'
38+
import Link from 'next/link'
3739
import { useParams, useRouter } from 'next/navigation'
3840
import { useQueryState } from 'nuqs'
3941
import { createPortal } from 'react-dom'
@@ -59,8 +61,10 @@ import {
5961
DELETED_WORKFLOW_LABEL,
6062
formatDate,
6163
getDisplayStatus,
64+
resolveLogWorkflowId,
6265
StatusBadge,
6366
TriggerBadge,
67+
workflowEditorPath,
6468
} from '@/app/workspace/[workspaceId]/logs/utils'
6569
import { useCodeViewerFeatures } from '@/hooks/use-code-viewer'
6670
import { usePermissionConfig } from '@/hooks/use-permission-config'
@@ -317,6 +321,19 @@ export function LogDetailsContent({ log, onActiveTabChange }: LogDetailsContentP
317321
const isWorkflowExecutionLog =
318322
(log.trigger === 'manual' && !!log.duration) || !!log.executionData?.traceSpans
319323

324+
/**
325+
* The workflow this run belongs to, when it is still reachable. Null for Sim
326+
* agent jobs and deleted workflows, which render their label as static text.
327+
*/
328+
const openableWorkflowId = resolveLogWorkflowId(log)
329+
330+
const workflowLabel =
331+
log.trigger === 'mothership'
332+
? log.jobTitle || 'Untitled Job'
333+
: openableWorkflowId
334+
? log.workflow?.name || 'Unknown'
335+
: DELETED_WORKFLOW_LABEL
336+
320337
const hasCostInfo = !!(isWorkflowExecutionLog && log.cost)
321338
const showWorkflowState =
322339
isWorkflowExecutionLog &&
@@ -465,15 +482,31 @@ export function LogDetailsContent({ log, onActiveTabChange }: LogDetailsContentP
465482
<span className='font-medium text-[var(--text-tertiary)] text-caption'>
466483
{log.trigger === 'mothership' ? 'Job' : 'Workflow'}
467484
</span>
468-
<div className='flex min-w-0 items-center gap-1.5'>
469-
<Workflow className='size-[14px] flex-shrink-0 text-[var(--text-icon)]' />
470-
<span className='min-w-0 truncate font-medium text-[var(--text-secondary)] text-sm'>
471-
{log.trigger === 'mothership'
472-
? log.jobTitle || 'Untitled Job'
473-
: log.workflow?.name ||
474-
(!log.workflowId ? DELETED_WORKFLOW_LABEL : 'Unknown')}
475-
</span>
476-
</div>
485+
{openableWorkflowId ? (
486+
<Link
487+
href={workflowEditorPath(workspaceId, openableWorkflowId)}
488+
target='_blank'
489+
rel='noopener noreferrer'
490+
prefetch={false}
491+
className='-mx-1.5 -my-0.5 group flex w-fit min-w-0 max-w-[calc(100%+0.75rem)] items-center gap-1.5 rounded-[5px] px-1.5 py-0.5 transition-colors hover-hover:bg-[var(--surface-active)] focus-visible:bg-[var(--surface-active)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[color-mix(in_srgb,var(--text-muted)_30%,transparent)]'
492+
>
493+
<span className='inline-grid size-[14px] shrink-0 place-items-center'>
494+
<Workflow className='col-start-1 row-start-1 size-[14px] text-[var(--text-icon)] opacity-100 blur-0 transition-[opacity,filter,transform] duration-200 ease-in-out group-hover-hover:scale-[0.25] group-hover-hover:opacity-0 group-hover-hover:blur-[2px] group-focus-visible:scale-[0.25] group-focus-visible:opacity-0 group-focus-visible:blur-[2px] motion-reduce:transition-none' />
495+
<SquareArrowUpRight className='col-start-1 row-start-1 size-[14px] scale-[0.25] text-[var(--text-icon)] opacity-0 blur-[2px] transition-[opacity,filter,transform] duration-200 ease-in-out group-hover-hover:scale-100 group-hover-hover:opacity-100 group-hover-hover:blur-0 group-focus-visible:scale-100 group-focus-visible:opacity-100 group-focus-visible:blur-0 motion-reduce:transition-none' />
496+
</span>
497+
<span className='min-w-0 truncate font-medium text-[var(--text-secondary)] text-sm transition-colors group-hover-hover:text-[var(--text-primary)] group-focus-visible:text-[var(--text-primary)]'>
498+
{workflowLabel}
499+
</span>
500+
<span className='sr-only'>(opens in a new tab)</span>
501+
</Link>
502+
) : (
503+
<div className='flex min-w-0 items-center gap-1.5'>
504+
<Workflow className='size-[14px] flex-shrink-0 text-[var(--text-icon)]' />
505+
<span className='min-w-0 truncate font-medium text-[var(--text-secondary)] text-sm'>
506+
{workflowLabel}
507+
</span>
508+
</div>
509+
)}
477510
</div>
478511
</div>
479512

apps/sim/tailwind.config.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,10 @@ export default {
300300
require('tailwindcss/plugin')(
301301
({ addVariant }: { addVariant: (name: string, definition: string) => void }) => {
302302
addVariant('hover-hover', '@media (hover: hover) and (pointer: fine) { &:hover }')
303+
addVariant(
304+
'group-hover-hover',
305+
'@media (hover: hover) and (pointer: fine) { :merge(.group):hover & }'
306+
)
303307
}
304308
),
305309
],

0 commit comments

Comments
 (0)