@shipfox/client-workflows 14.0.0 → 15.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.storybook/preview.tsx +7 -2
- package/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +35 -0
- package/dist/components/job-detail/agent-config-failure-callout.d.ts.map +1 -0
- package/dist/components/{workflow-run-view → job-detail}/agent-config-failure-callout.js +2 -2
- package/dist/components/job-detail/agent-config-failure-callout.js.map +1 -0
- package/dist/components/job-detail/job-detail-header.d.ts +8 -0
- package/dist/components/job-detail/job-detail-header.d.ts.map +1 -0
- package/dist/components/job-detail/job-detail-header.js +111 -0
- package/dist/components/job-detail/job-detail-header.js.map +1 -0
- package/dist/components/job-detail/job-detail-view.d.ts +16 -0
- package/dist/components/job-detail/job-detail-view.d.ts.map +1 -0
- package/dist/components/job-detail/job-detail-view.js +405 -0
- package/dist/components/job-detail/job-detail-view.js.map +1 -0
- package/dist/components/job-detail/job-empty-states.d.ts +10 -0
- package/dist/components/job-detail/job-empty-states.d.ts.map +1 -0
- package/dist/components/job-detail/job-empty-states.js +195 -0
- package/dist/components/job-detail/job-empty-states.js.map +1 -0
- package/dist/components/job-detail/job-execution-switcher.d.ts.map +1 -0
- package/dist/components/job-detail/job-execution-switcher.js.map +1 -0
- package/dist/components/job-detail/job-execution-time-text.d.ts.map +1 -0
- package/dist/components/job-detail/job-execution-time-text.js.map +1 -0
- package/dist/components/job-detail/job-selection.d.ts +24 -0
- package/dist/components/job-detail/job-selection.d.ts.map +1 -0
- package/dist/components/job-detail/job-selection.js +66 -0
- package/dist/components/job-detail/job-selection.js.map +1 -0
- package/dist/components/job-detail/step-attempt-log-panel.d.ts +15 -0
- package/dist/components/job-detail/step-attempt-log-panel.d.ts.map +1 -0
- package/dist/components/{workflow-run-view → job-detail}/step-attempt-log-panel.js +61 -16
- package/dist/components/job-detail/step-attempt-log-panel.js.map +1 -0
- package/dist/components/job-graph/job-graph-content.js +1 -1
- package/dist/components/job-graph/job-graph-content.js.map +1 -1
- package/dist/components/step-list/step-list-model.js +2 -2
- package/dist/components/step-list/step-list-model.js.map +1 -1
- package/dist/components/step-list/step-list.d.ts +1 -0
- package/dist/components/step-list/step-list.d.ts.map +1 -1
- package/dist/components/step-list/step-list.js +29 -4
- package/dist/components/step-list/step-list.js.map +1 -1
- package/dist/components/workflow-run-duration-label.d.ts +9 -4
- package/dist/components/workflow-run-duration-label.d.ts.map +1 -1
- package/dist/components/workflow-run-duration-label.js +27 -7
- package/dist/components/workflow-run-duration-label.js.map +1 -1
- package/dist/components/workflow-run-list/workflow-run-row.d.ts.map +1 -1
- package/dist/components/workflow-run-list/workflow-run-row.js +6 -5
- package/dist/components/workflow-run-list/workflow-run-row.js.map +1 -1
- package/dist/components/workflow-run-summary/workflow-run-summary.d.ts.map +1 -1
- package/dist/components/workflow-run-summary/workflow-run-summary.js +68 -64
- package/dist/components/workflow-run-summary/workflow-run-summary.js.map +1 -1
- package/dist/components/workflow-run-tabs/index.d.ts +0 -3
- package/dist/components/workflow-run-tabs/index.d.ts.map +1 -1
- package/dist/components/workflow-run-tabs/index.js +0 -3
- package/dist/components/workflow-run-tabs/index.js.map +1 -1
- package/dist/components/workflow-run-tabs/run-annotations-empty.d.ts +3 -1
- package/dist/components/workflow-run-tabs/run-annotations-empty.d.ts.map +1 -1
- package/dist/components/workflow-run-tabs/run-annotations-empty.js +2 -2
- package/dist/components/workflow-run-tabs/run-annotations-empty.js.map +1 -1
- package/dist/components/workflow-run-view/index.d.ts +0 -1
- package/dist/components/workflow-run-view/index.d.ts.map +1 -1
- package/dist/components/workflow-run-view/index.js +0 -1
- package/dist/components/workflow-run-view/index.js.map +1 -1
- package/dist/components/workflow-run-view/run-workspace-nav.d.ts +20 -0
- package/dist/components/workflow-run-view/run-workspace-nav.d.ts.map +1 -0
- package/dist/components/workflow-run-view/run-workspace-nav.js +271 -0
- package/dist/components/workflow-run-view/run-workspace-nav.js.map +1 -0
- package/dist/components/workflow-run-view/workflow-run-selection.d.ts.map +1 -1
- package/dist/components/workflow-run-view/workflow-run-selection.js +1 -14
- package/dist/components/workflow-run-view/workflow-run-selection.js.map +1 -1
- package/dist/components/workflow-run-view/workflow-run-view.d.ts +10 -8
- package/dist/components/workflow-run-view/workflow-run-view.d.ts.map +1 -1
- package/dist/components/workflow-run-view/workflow-run-view.js +250 -236
- package/dist/components/workflow-run-view/workflow-run-view.js.map +1 -1
- package/dist/components/workflow-status/status-visuals.d.ts.map +1 -1
- package/dist/components/workflow-status/status-visuals.js +10 -2
- package/dist/components/workflow-status/status-visuals.js.map +1 -1
- package/dist/components/workflow-status/workflow-status-icon.d.ts +3 -1
- package/dist/components/workflow-status/workflow-status-icon.d.ts.map +1 -1
- package/dist/components/workflow-status/workflow-status-icon.js +13 -2
- package/dist/components/workflow-status/workflow-status-icon.js.map +1 -1
- package/dist/core/entities/job-execution.d.ts +9 -0
- package/dist/core/entities/job-execution.d.ts.map +1 -1
- package/dist/core/entities/job-execution.js +13 -3
- package/dist/core/entities/job-execution.js.map +1 -1
- package/dist/core/entities/job.d.ts.map +1 -1
- package/dist/core/entities/step-attempt.d.ts.map +1 -1
- package/dist/core/entities/step.d.ts +2 -0
- package/dist/core/entities/step.d.ts.map +1 -1
- package/dist/core/entities/step.js +13 -0
- package/dist/core/entities/step.js.map +1 -1
- package/dist/core/entities/workflow-run-attempt.d.ts.map +1 -1
- package/dist/core/entities/workflow-run.d.ts +56 -1
- package/dist/core/entities/workflow-run.d.ts.map +1 -1
- package/dist/core/entities/workflow-run.js +98 -0
- package/dist/core/entities/workflow-run.js.map +1 -1
- package/dist/core/workflow-run.d.ts +4 -4
- package/dist/core/workflow-run.d.ts.map +1 -1
- package/dist/core/workflow-run.js +3 -3
- package/dist/core/workflow-run.js.map +1 -1
- package/dist/feature.d.ts +20 -16
- package/dist/feature.d.ts.map +1 -1
- package/dist/feature.js +5 -0
- package/dist/feature.js.map +1 -1
- package/dist/hooks/api/workflow-runs.d.ts +5 -3
- package/dist/hooks/api/workflow-runs.d.ts.map +1 -1
- package/dist/hooks/api/workflow-runs.js +5 -4
- package/dist/hooks/api/workflow-runs.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/pages/workflow-job-detail-page.d.ts +11 -0
- package/dist/pages/workflow-job-detail-page.d.ts.map +1 -0
- package/dist/pages/workflow-job-detail-page.js +66 -0
- package/dist/pages/workflow-job-detail-page.js.map +1 -0
- package/dist/pages/workflow-run-detail-page.d.ts.map +1 -1
- package/dist/pages/workflow-run-detail-page.js +4 -37
- package/dist/pages/workflow-run-detail-page.js.map +1 -1
- package/dist/routes/inputs.d.ts +47 -34
- package/dist/routes/inputs.d.ts.map +1 -1
- package/dist/routes/inputs.js +69 -37
- package/dist/routes/inputs.js.map +1 -1
- package/dist/routes/job-detail.d.ts +10 -0
- package/dist/routes/job-detail.d.ts.map +1 -0
- package/dist/routes/job-detail.js +27 -0
- package/dist/routes/job-detail.js.map +1 -0
- package/dist/routes/project-route.d.ts +1 -1
- package/dist/routes/run-detail.d.ts.map +1 -1
- package/dist/routes/runs.d.ts.map +1 -1
- package/dist/routes/workflows.d.ts.map +1 -1
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +7 -7
- package/src/components/{workflow-run-view → job-detail}/agent-config-failure-callout.stories.tsx +1 -1
- package/src/components/{workflow-run-view → job-detail}/agent-config-failure-callout.tsx +2 -2
- package/src/components/job-detail/job-detail-header.test.tsx +31 -0
- package/src/components/job-detail/job-detail-header.tsx +111 -0
- package/src/components/job-detail/job-detail-view.stories.tsx +526 -0
- package/src/components/job-detail/job-detail-view.tsx +450 -0
- package/src/components/job-detail/job-empty-states.test.ts +27 -0
- package/src/components/job-detail/job-empty-states.tsx +248 -0
- package/src/components/job-detail/job-selection.test.ts +188 -0
- package/src/components/job-detail/job-selection.ts +96 -0
- package/src/components/{workflow-run-view → job-detail}/step-attempt-log-panel.test.tsx +32 -9
- package/src/components/{workflow-run-view → job-detail}/step-attempt-log-panel.tsx +52 -18
- package/src/components/job-graph/job-graph-content.tsx +1 -1
- package/src/components/step-list/step-list-model.test.ts +1 -1
- package/src/components/step-list/step-list-model.ts +2 -2
- package/src/components/step-list/step-list.stories.tsx +1 -1
- package/src/components/step-list/step-list.test.tsx +33 -0
- package/src/components/step-list/step-list.tsx +40 -9
- package/src/components/workflow-run-duration-label.tsx +50 -12
- package/src/components/workflow-run-list/workflow-run-row.tsx +6 -4
- package/src/components/workflow-run-summary/workflow-run-summary.stories.tsx +38 -0
- package/src/components/workflow-run-summary/workflow-run-summary.test.tsx +79 -5
- package/src/components/workflow-run-summary/workflow-run-summary.tsx +56 -60
- package/src/components/workflow-run-tabs/index.ts +0 -3
- package/src/components/workflow-run-tabs/run-annotations-empty.tsx +6 -2
- package/src/components/workflow-run-view/index.ts +0 -1
- package/src/components/workflow-run-view/run-workspace-nav.test.tsx +242 -0
- package/src/components/workflow-run-view/run-workspace-nav.tsx +301 -0
- package/src/components/workflow-run-view/workflow-run-selection.ts +1 -23
- package/src/components/workflow-run-view/workflow-run-view.test.tsx +62 -1136
- package/src/components/workflow-run-view/workflow-run-view.tsx +330 -321
- package/src/components/workflow-status/status-visuals.ts +5 -2
- package/src/components/workflow-status/workflow-status-icon.stories.tsx +1 -0
- package/src/components/workflow-status/workflow-status-icon.tsx +26 -1
- package/src/core/entities/job-execution.ts +17 -2
- package/src/core/entities/step.ts +26 -0
- package/src/core/entities/workflow-run-display.test.ts +159 -0
- package/src/core/entities/workflow-run.ts +139 -1
- package/src/core/workflow-run.ts +16 -1
- package/src/feature.ts +5 -0
- package/src/hooks/api/workflow-runs.ts +6 -2
- package/src/index.ts +1 -0
- package/src/page-harness-budget.test.ts +1 -0
- package/src/pages/workflow-job-detail-page.test.tsx +539 -0
- package/src/pages/workflow-job-detail-page.tsx +84 -0
- package/src/pages/workflow-run-detail-page.tsx +3 -43
- package/src/pages/workflow-run-pages.test.tsx +77 -332
- package/src/routes/inputs.test.ts +56 -6
- package/src/routes/inputs.ts +64 -17
- package/src/routes/job-detail.tsx +29 -0
- package/test/pages.tsx +25 -3
- package/test/render.tsx +6 -1
- package/tsconfig.build.tsbuildinfo +1 -1
- package/dist/components/workflow-run-tabs/run-jobs-list.d.ts +0 -18
- package/dist/components/workflow-run-tabs/run-jobs-list.d.ts.map +0 -1
- package/dist/components/workflow-run-tabs/run-jobs-list.js +0 -107
- package/dist/components/workflow-run-tabs/run-jobs-list.js.map +0 -1
- package/dist/components/workflow-run-tabs/run-tab-count.d.ts +0 -6
- package/dist/components/workflow-run-tabs/run-tab-count.d.ts.map +0 -1
- package/dist/components/workflow-run-tabs/run-tab-count.js +0 -27
- package/dist/components/workflow-run-tabs/run-tab-count.js.map +0 -1
- package/dist/components/workflow-run-tabs/run-tab-strip.d.ts +0 -8
- package/dist/components/workflow-run-tabs/run-tab-strip.d.ts.map +0 -1
- package/dist/components/workflow-run-tabs/run-tab-strip.js +0 -82
- package/dist/components/workflow-run-tabs/run-tab-strip.js.map +0 -1
- package/dist/components/workflow-run-view/agent-config-failure-callout.d.ts.map +0 -1
- package/dist/components/workflow-run-view/agent-config-failure-callout.js.map +0 -1
- package/dist/components/workflow-run-view/job-card.d.ts +0 -17
- package/dist/components/workflow-run-view/job-card.d.ts.map +0 -1
- package/dist/components/workflow-run-view/job-card.js +0 -496
- package/dist/components/workflow-run-view/job-card.js.map +0 -1
- package/dist/components/workflow-run-view/job-execution-switcher.d.ts.map +0 -1
- package/dist/components/workflow-run-view/job-execution-switcher.js.map +0 -1
- package/dist/components/workflow-run-view/job-execution-time-text.d.ts.map +0 -1
- package/dist/components/workflow-run-view/job-execution-time-text.js.map +0 -1
- package/dist/components/workflow-run-view/step-attempt-log-panel.d.ts +0 -9
- package/dist/components/workflow-run-view/step-attempt-log-panel.d.ts.map +0 -1
- package/dist/components/workflow-run-view/step-attempt-log-panel.js.map +0 -1
- package/src/components/workflow-run-tabs/run-jobs-list.tsx +0 -151
- package/src/components/workflow-run-tabs/run-tab-count.tsx +0 -28
- package/src/components/workflow-run-tabs/run-tab-strip.stories.tsx +0 -52
- package/src/components/workflow-run-tabs/run-tab-strip.test.tsx +0 -117
- package/src/components/workflow-run-tabs/run-tab-strip.tsx +0 -97
- package/src/components/workflow-run-view/job-card.stories.tsx +0 -789
- package/src/components/workflow-run-view/job-card.test.tsx +0 -115
- package/src/components/workflow-run-view/job-card.tsx +0 -614
- /package/dist/components/{workflow-run-view → job-detail}/agent-config-failure-callout.d.ts +0 -0
- /package/dist/components/{workflow-run-view → job-detail}/job-execution-switcher.d.ts +0 -0
- /package/dist/components/{workflow-run-view → job-detail}/job-execution-switcher.js +0 -0
- /package/dist/components/{workflow-run-view → job-detail}/job-execution-time-text.d.ts +0 -0
- /package/dist/components/{workflow-run-view → job-detail}/job-execution-time-text.js +0 -0
- /package/src/components/{workflow-run-view → job-detail}/job-execution-switcher.tsx +0 -0
- /package/src/components/{workflow-run-view → job-detail}/job-execution-time-text.tsx +0 -0
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
import {Collapsible, CollapsibleTrigger} from '@shipfox/react-ui/collapsible';
|
|
2
|
+
import {Icon} from '@shipfox/react-ui/icon';
|
|
3
|
+
import {TimeTickerProvider} from '@shipfox/react-ui/time-ticker';
|
|
4
|
+
import {Text} from '@shipfox/react-ui/typography';
|
|
5
|
+
import {cn} from '@shipfox/react-ui/utils';
|
|
6
|
+
import {Link} from '@tanstack/react-router';
|
|
7
|
+
import {useEffect, useMemo, useRef, useState} from 'react';
|
|
8
|
+
import {WorkflowStatusIcon} from '#components/workflow-status/workflow-status-icon.js';
|
|
9
|
+
import {
|
|
10
|
+
defaultJobExecution,
|
|
11
|
+
deriveJobDisplayStatus,
|
|
12
|
+
type Job,
|
|
13
|
+
type WorkflowRunDetail,
|
|
14
|
+
} from '#core/workflow-run.js';
|
|
15
|
+
import type {RunAnnotationSummary} from '#core/workflow-run-tabs.js';
|
|
16
|
+
import {
|
|
17
|
+
type WorkflowJobSearch,
|
|
18
|
+
type WorkflowRunTab,
|
|
19
|
+
workflowJobSearchParams,
|
|
20
|
+
workflowRunSearchParams,
|
|
21
|
+
} from '#routes/inputs.js';
|
|
22
|
+
import {JobExecutionTimeText} from '../job-detail/job-execution-time-text.js';
|
|
23
|
+
|
|
24
|
+
type RunWorkspaceSection = Exclude<WorkflowRunTab, 'jobs'>;
|
|
25
|
+
|
|
26
|
+
export interface RunWorkspaceNavProps {
|
|
27
|
+
workspaceSlug: string;
|
|
28
|
+
projectSlug: string;
|
|
29
|
+
run: WorkflowRunDetail;
|
|
30
|
+
activeSection: RunWorkspaceSection;
|
|
31
|
+
currentJobId?: string | undefined;
|
|
32
|
+
jobSearch?: WorkflowJobSearch | undefined;
|
|
33
|
+
annotationSummary?: RunAnnotationSummary | undefined;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* The stable navigation model shared by run-level and job-level routes. The graph explains
|
|
38
|
+
* topology; this compact index makes moving between dedicated job pages predictable.
|
|
39
|
+
*/
|
|
40
|
+
export function RunWorkspaceNav({
|
|
41
|
+
workspaceSlug,
|
|
42
|
+
projectSlug,
|
|
43
|
+
run,
|
|
44
|
+
activeSection,
|
|
45
|
+
currentJobId,
|
|
46
|
+
jobSearch = {},
|
|
47
|
+
annotationSummary,
|
|
48
|
+
}: RunWorkspaceNavProps) {
|
|
49
|
+
const jobs = useMemo(() => [...run.jobs].sort(compareJobs), [run.jobs]);
|
|
50
|
+
const [mobileOpen, setMobileOpen] = useState(false);
|
|
51
|
+
const currentJob = jobs.find((job) => job.id === currentJobId);
|
|
52
|
+
const currentLabel = currentJob?.displayName ?? sectionLabel(activeSection);
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<TimeTickerProvider intervalMs={1000} reducedMotionIntervalMs={10_000}>
|
|
56
|
+
<aside className="w-full shrink-0 border-b border-border-neutral-base bg-background-neutral-background min-[768px]:w-240 min-[768px]:border-b-0 min-[768px]:border-r">
|
|
57
|
+
<Collapsible open={mobileOpen} onOpenChange={setMobileOpen}>
|
|
58
|
+
<CollapsibleTrigger asChild>
|
|
59
|
+
<button
|
|
60
|
+
type="button"
|
|
61
|
+
className="flex min-h-44 w-full items-center justify-between gap-12 px-16 text-left outline-none focus-visible:shadow-border-interactive-with-active min-[768px]:hidden"
|
|
62
|
+
aria-label="Toggle run navigation"
|
|
63
|
+
>
|
|
64
|
+
<span className="min-w-0">
|
|
65
|
+
<Text as="span" size="xs" className="block text-foreground-neutral-muted">
|
|
66
|
+
Run navigation
|
|
67
|
+
</Text>
|
|
68
|
+
<span className="block truncate font-code text-xs leading-20 text-foreground-neutral-base">
|
|
69
|
+
{currentLabel}
|
|
70
|
+
</span>
|
|
71
|
+
</span>
|
|
72
|
+
<Icon
|
|
73
|
+
name="chevronDown"
|
|
74
|
+
size={14}
|
|
75
|
+
aria-hidden="true"
|
|
76
|
+
className={cn(
|
|
77
|
+
'shrink-0 text-foreground-neutral-muted transition-transform',
|
|
78
|
+
mobileOpen && 'rotate-180',
|
|
79
|
+
)}
|
|
80
|
+
/>
|
|
81
|
+
</button>
|
|
82
|
+
</CollapsibleTrigger>
|
|
83
|
+
<div
|
|
84
|
+
className={cn(
|
|
85
|
+
'max-h-[50vh] overflow-y-auto p-8 min-[768px]:block min-[768px]:max-h-none min-[768px]:p-12',
|
|
86
|
+
!mobileOpen && 'hidden',
|
|
87
|
+
)}
|
|
88
|
+
>
|
|
89
|
+
<RunWorkspaceNavContent
|
|
90
|
+
workspaceSlug={workspaceSlug}
|
|
91
|
+
projectSlug={projectSlug}
|
|
92
|
+
run={run}
|
|
93
|
+
jobs={jobs}
|
|
94
|
+
activeSection={activeSection}
|
|
95
|
+
currentJobId={currentJobId}
|
|
96
|
+
jobSearch={jobSearch}
|
|
97
|
+
annotationSummary={annotationSummary}
|
|
98
|
+
mobileOpen={mobileOpen}
|
|
99
|
+
onNavigate={() => setMobileOpen(false)}
|
|
100
|
+
/>
|
|
101
|
+
</div>
|
|
102
|
+
</Collapsible>
|
|
103
|
+
</aside>
|
|
104
|
+
</TimeTickerProvider>
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function RunWorkspaceNavContent({
|
|
109
|
+
workspaceSlug,
|
|
110
|
+
projectSlug,
|
|
111
|
+
run,
|
|
112
|
+
jobs,
|
|
113
|
+
activeSection,
|
|
114
|
+
currentJobId,
|
|
115
|
+
jobSearch,
|
|
116
|
+
annotationSummary,
|
|
117
|
+
mobileOpen,
|
|
118
|
+
onNavigate,
|
|
119
|
+
}: RunWorkspaceNavProps & {
|
|
120
|
+
jobs: Job[];
|
|
121
|
+
jobSearch: WorkflowJobSearch;
|
|
122
|
+
mobileOpen: boolean;
|
|
123
|
+
onNavigate: () => void;
|
|
124
|
+
}) {
|
|
125
|
+
const currentRowRef = useRef<HTMLAnchorElement>(null);
|
|
126
|
+
const runAttempt = jobSearch.runAttempt ?? run.runAttempt.attempt;
|
|
127
|
+
|
|
128
|
+
useEffect(() => {
|
|
129
|
+
if (!currentJobId || mobileOpen) return;
|
|
130
|
+
currentRowRef.current?.scrollIntoView({block: 'nearest'});
|
|
131
|
+
}, [currentJobId, mobileOpen]);
|
|
132
|
+
|
|
133
|
+
useEffect(() => {
|
|
134
|
+
if (!currentJobId || !mobileOpen) return;
|
|
135
|
+
currentRowRef.current?.scrollIntoView({block: 'nearest'});
|
|
136
|
+
}, [currentJobId, mobileOpen]);
|
|
137
|
+
|
|
138
|
+
return (
|
|
139
|
+
<nav aria-label="Run workspace" className="flex min-w-0 flex-col gap-16">
|
|
140
|
+
<ul>
|
|
141
|
+
<li>
|
|
142
|
+
<RunSectionLink
|
|
143
|
+
workspaceSlug={workspaceSlug}
|
|
144
|
+
projectSlug={projectSlug}
|
|
145
|
+
runId={run.id}
|
|
146
|
+
runAttempt={runAttempt}
|
|
147
|
+
section="summary"
|
|
148
|
+
current={!currentJobId && activeSection === 'summary'}
|
|
149
|
+
onNavigate={onNavigate}
|
|
150
|
+
/>
|
|
151
|
+
</li>
|
|
152
|
+
</ul>
|
|
153
|
+
|
|
154
|
+
<section aria-labelledby="run-workspace-jobs-heading" className="min-w-0">
|
|
155
|
+
<div className="flex items-center justify-between gap-8 px-8 pb-6">
|
|
156
|
+
<Text
|
|
157
|
+
as="h2"
|
|
158
|
+
id="run-workspace-jobs-heading"
|
|
159
|
+
size="xs"
|
|
160
|
+
bold
|
|
161
|
+
className="text-foreground-neutral-muted"
|
|
162
|
+
>
|
|
163
|
+
Jobs
|
|
164
|
+
</Text>
|
|
165
|
+
<Text as="span" size="xs" className="font-code text-foreground-neutral-subtle">
|
|
166
|
+
{jobs.length}
|
|
167
|
+
</Text>
|
|
168
|
+
</div>
|
|
169
|
+
<ol className="max-h-[320px] overflow-y-auto">
|
|
170
|
+
{jobs.map((job) => {
|
|
171
|
+
const current = job.id === currentJobId;
|
|
172
|
+
const execution = defaultJobExecution(job);
|
|
173
|
+
const duration = execution?.displayDuration ?? job.displayDuration;
|
|
174
|
+
|
|
175
|
+
return (
|
|
176
|
+
<li key={job.id}>
|
|
177
|
+
<Link
|
|
178
|
+
ref={current ? currentRowRef : undefined}
|
|
179
|
+
to="/w/$workspaceSlug/p/$projectSlug/runs/$workflowRunId/jobs/$jobId"
|
|
180
|
+
params={{workspaceSlug, projectSlug, workflowRunId: run.id, jobId: job.id}}
|
|
181
|
+
search={workflowJobSearchParams({runAttempt}) as never}
|
|
182
|
+
onClick={onNavigate}
|
|
183
|
+
aria-current={current ? 'page' : undefined}
|
|
184
|
+
className={cn(
|
|
185
|
+
'flex min-h-32 min-w-0 items-center gap-8 rounded-4 px-8 text-left outline-none transition-colors hover:bg-background-neutral-hover focus-visible:shadow-border-interactive-with-active @max-[767px]:min-h-44 [@media(pointer:coarse)]:min-h-44',
|
|
186
|
+
current && 'bg-background-neutral-hover',
|
|
187
|
+
)}
|
|
188
|
+
>
|
|
189
|
+
<WorkflowStatusIcon
|
|
190
|
+
status={deriveJobDisplayStatus(job)}
|
|
191
|
+
size={12}
|
|
192
|
+
tooltip={false}
|
|
193
|
+
/>
|
|
194
|
+
<span className="min-w-0 truncate font-code text-xs leading-20 text-foreground-neutral-base">
|
|
195
|
+
{job.displayName}
|
|
196
|
+
</span>
|
|
197
|
+
<span className="ml-auto shrink-0 font-code text-xs leading-20 text-foreground-neutral-muted tabular-nums">
|
|
198
|
+
{duration ? <JobExecutionTimeText time={duration} /> : '—'}
|
|
199
|
+
</span>
|
|
200
|
+
</Link>
|
|
201
|
+
</li>
|
|
202
|
+
);
|
|
203
|
+
})}
|
|
204
|
+
</ol>
|
|
205
|
+
</section>
|
|
206
|
+
|
|
207
|
+
<section aria-labelledby="run-workspace-details-heading">
|
|
208
|
+
<Text
|
|
209
|
+
as="h2"
|
|
210
|
+
id="run-workspace-details-heading"
|
|
211
|
+
size="xs"
|
|
212
|
+
bold
|
|
213
|
+
className="px-8 pb-6 text-foreground-neutral-muted"
|
|
214
|
+
>
|
|
215
|
+
Run details
|
|
216
|
+
</Text>
|
|
217
|
+
<ul>
|
|
218
|
+
<li>
|
|
219
|
+
<RunSectionLink
|
|
220
|
+
workspaceSlug={workspaceSlug}
|
|
221
|
+
projectSlug={projectSlug}
|
|
222
|
+
runId={run.id}
|
|
223
|
+
runAttempt={runAttempt}
|
|
224
|
+
section="annotations"
|
|
225
|
+
current={!currentJobId && activeSection === 'annotations'}
|
|
226
|
+
count={annotationSummary?.total}
|
|
227
|
+
onNavigate={onNavigate}
|
|
228
|
+
/>
|
|
229
|
+
</li>
|
|
230
|
+
<li>
|
|
231
|
+
<RunSectionLink
|
|
232
|
+
workspaceSlug={workspaceSlug}
|
|
233
|
+
projectSlug={projectSlug}
|
|
234
|
+
runId={run.id}
|
|
235
|
+
runAttempt={runAttempt}
|
|
236
|
+
section="source"
|
|
237
|
+
current={!currentJobId && activeSection === 'source'}
|
|
238
|
+
onNavigate={onNavigate}
|
|
239
|
+
/>
|
|
240
|
+
</li>
|
|
241
|
+
</ul>
|
|
242
|
+
</section>
|
|
243
|
+
</nav>
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function RunSectionLink({
|
|
248
|
+
workspaceSlug,
|
|
249
|
+
projectSlug,
|
|
250
|
+
runId,
|
|
251
|
+
runAttempt,
|
|
252
|
+
section,
|
|
253
|
+
current,
|
|
254
|
+
count,
|
|
255
|
+
onNavigate,
|
|
256
|
+
}: {
|
|
257
|
+
workspaceSlug: string;
|
|
258
|
+
projectSlug: string;
|
|
259
|
+
runId: string;
|
|
260
|
+
runAttempt: number;
|
|
261
|
+
section: RunWorkspaceSection;
|
|
262
|
+
current: boolean;
|
|
263
|
+
count?: number | undefined;
|
|
264
|
+
onNavigate?: (() => void) | undefined;
|
|
265
|
+
}) {
|
|
266
|
+
return (
|
|
267
|
+
<Link
|
|
268
|
+
to="/w/$workspaceSlug/p/$projectSlug/runs/$workflowRunId"
|
|
269
|
+
params={{workspaceSlug, projectSlug, workflowRunId: runId}}
|
|
270
|
+
search={
|
|
271
|
+
workflowRunSearchParams(
|
|
272
|
+
{runAttempt, ...(section === 'summary' ? {} : {tab: section})},
|
|
273
|
+
{runAttempt},
|
|
274
|
+
) as never
|
|
275
|
+
}
|
|
276
|
+
onClick={onNavigate}
|
|
277
|
+
aria-current={current ? 'page' : undefined}
|
|
278
|
+
className={cn(
|
|
279
|
+
'flex min-h-32 items-center gap-8 rounded-4 px-8 text-xs font-medium text-foreground-neutral-base outline-none transition-colors hover:bg-background-neutral-hover focus-visible:shadow-border-interactive-with-active @max-[767px]:min-h-44 [@media(pointer:coarse)]:min-h-44',
|
|
280
|
+
current && 'bg-background-neutral-hover',
|
|
281
|
+
)}
|
|
282
|
+
>
|
|
283
|
+
{sectionLabel(section)}
|
|
284
|
+
{count ? (
|
|
285
|
+
<span className="ml-auto font-code text-xs text-foreground-neutral-muted tabular-nums">
|
|
286
|
+
{count}
|
|
287
|
+
</span>
|
|
288
|
+
) : null}
|
|
289
|
+
</Link>
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function sectionLabel(section: RunWorkspaceSection): string {
|
|
294
|
+
if (section === 'annotations') return 'Annotations';
|
|
295
|
+
if (section === 'source') return 'Source';
|
|
296
|
+
return 'Summary';
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
function compareJobs(left: Job, right: Job): number {
|
|
300
|
+
return left.position - right.position || left.id.localeCompare(right.id);
|
|
301
|
+
}
|
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
type Job,
|
|
3
3
|
type JobExecution,
|
|
4
4
|
resolveJobExecution,
|
|
5
|
+
resolveStepAttempt,
|
|
5
6
|
type Step,
|
|
6
7
|
type StepAttempt,
|
|
7
8
|
type WorkflowRunDetail,
|
|
@@ -111,26 +112,3 @@ function findStep(
|
|
|
111
112
|
|
|
112
113
|
return undefined;
|
|
113
114
|
}
|
|
114
|
-
|
|
115
|
-
function resolveStepAttempt(step: Step, attemptId: string | undefined): StepAttempt | undefined {
|
|
116
|
-
const attemptById = attemptId
|
|
117
|
-
? step.attempts.find((attempt) => attempt.id === attemptId)
|
|
118
|
-
: undefined;
|
|
119
|
-
if (attemptById) return attemptById;
|
|
120
|
-
|
|
121
|
-
const currentAttempt = step.attempts.find((attempt) => attempt.attempt === step.currentAttempt);
|
|
122
|
-
if (currentAttempt) return currentAttempt;
|
|
123
|
-
|
|
124
|
-
return step.attempts.reduce<StepAttempt | undefined>((latest, attempt) => {
|
|
125
|
-
if (!latest) return attempt;
|
|
126
|
-
return compareAttempts(attempt, latest) > 0 ? attempt : latest;
|
|
127
|
-
}, undefined);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
function compareAttempts(left: StepAttempt, right: StepAttempt): number {
|
|
131
|
-
return (
|
|
132
|
-
left.attempt - right.attempt ||
|
|
133
|
-
left.executionOrder - right.executionOrder ||
|
|
134
|
-
left.id.localeCompare(right.id)
|
|
135
|
-
);
|
|
136
|
-
}
|