@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,271 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Collapsible, CollapsibleTrigger } from '@shipfox/react-ui/collapsible';
|
|
3
|
+
import { Icon } from '@shipfox/react-ui/icon';
|
|
4
|
+
import { TimeTickerProvider } from '@shipfox/react-ui/time-ticker';
|
|
5
|
+
import { Text } from '@shipfox/react-ui/typography';
|
|
6
|
+
import { cn } from '@shipfox/react-ui/utils';
|
|
7
|
+
import { Link } from '@tanstack/react-router';
|
|
8
|
+
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
9
|
+
import { WorkflowStatusIcon } from '#components/workflow-status/workflow-status-icon.js';
|
|
10
|
+
import { defaultJobExecution, deriveJobDisplayStatus } from '#core/workflow-run.js';
|
|
11
|
+
import { workflowJobSearchParams, workflowRunSearchParams } from '#routes/inputs.js';
|
|
12
|
+
import { JobExecutionTimeText } from '../job-detail/job-execution-time-text.js';
|
|
13
|
+
/**
|
|
14
|
+
* The stable navigation model shared by run-level and job-level routes. The graph explains
|
|
15
|
+
* topology; this compact index makes moving between dedicated job pages predictable.
|
|
16
|
+
*/ export function RunWorkspaceNav({ workspaceSlug, projectSlug, run, activeSection, currentJobId, jobSearch = {}, annotationSummary }) {
|
|
17
|
+
const jobs = useMemo(()=>[
|
|
18
|
+
...run.jobs
|
|
19
|
+
].sort(compareJobs), [
|
|
20
|
+
run.jobs
|
|
21
|
+
]);
|
|
22
|
+
const [mobileOpen, setMobileOpen] = useState(false);
|
|
23
|
+
const currentJob = jobs.find((job)=>job.id === currentJobId);
|
|
24
|
+
const currentLabel = currentJob?.displayName ?? sectionLabel(activeSection);
|
|
25
|
+
return /*#__PURE__*/ _jsx(TimeTickerProvider, {
|
|
26
|
+
intervalMs: 1000,
|
|
27
|
+
reducedMotionIntervalMs: 10_000,
|
|
28
|
+
children: /*#__PURE__*/ _jsx("aside", {
|
|
29
|
+
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",
|
|
30
|
+
children: /*#__PURE__*/ _jsxs(Collapsible, {
|
|
31
|
+
open: mobileOpen,
|
|
32
|
+
onOpenChange: setMobileOpen,
|
|
33
|
+
children: [
|
|
34
|
+
/*#__PURE__*/ _jsx(CollapsibleTrigger, {
|
|
35
|
+
asChild: true,
|
|
36
|
+
children: /*#__PURE__*/ _jsxs("button", {
|
|
37
|
+
type: "button",
|
|
38
|
+
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",
|
|
39
|
+
"aria-label": "Toggle run navigation",
|
|
40
|
+
children: [
|
|
41
|
+
/*#__PURE__*/ _jsxs("span", {
|
|
42
|
+
className: "min-w-0",
|
|
43
|
+
children: [
|
|
44
|
+
/*#__PURE__*/ _jsx(Text, {
|
|
45
|
+
as: "span",
|
|
46
|
+
size: "xs",
|
|
47
|
+
className: "block text-foreground-neutral-muted",
|
|
48
|
+
children: "Run navigation"
|
|
49
|
+
}),
|
|
50
|
+
/*#__PURE__*/ _jsx("span", {
|
|
51
|
+
className: "block truncate font-code text-xs leading-20 text-foreground-neutral-base",
|
|
52
|
+
children: currentLabel
|
|
53
|
+
})
|
|
54
|
+
]
|
|
55
|
+
}),
|
|
56
|
+
/*#__PURE__*/ _jsx(Icon, {
|
|
57
|
+
name: "chevronDown",
|
|
58
|
+
size: 14,
|
|
59
|
+
"aria-hidden": "true",
|
|
60
|
+
className: cn('shrink-0 text-foreground-neutral-muted transition-transform', mobileOpen && 'rotate-180')
|
|
61
|
+
})
|
|
62
|
+
]
|
|
63
|
+
})
|
|
64
|
+
}),
|
|
65
|
+
/*#__PURE__*/ _jsx("div", {
|
|
66
|
+
className: cn('max-h-[50vh] overflow-y-auto p-8 min-[768px]:block min-[768px]:max-h-none min-[768px]:p-12', !mobileOpen && 'hidden'),
|
|
67
|
+
children: /*#__PURE__*/ _jsx(RunWorkspaceNavContent, {
|
|
68
|
+
workspaceSlug: workspaceSlug,
|
|
69
|
+
projectSlug: projectSlug,
|
|
70
|
+
run: run,
|
|
71
|
+
jobs: jobs,
|
|
72
|
+
activeSection: activeSection,
|
|
73
|
+
currentJobId: currentJobId,
|
|
74
|
+
jobSearch: jobSearch,
|
|
75
|
+
annotationSummary: annotationSummary,
|
|
76
|
+
mobileOpen: mobileOpen,
|
|
77
|
+
onNavigate: ()=>setMobileOpen(false)
|
|
78
|
+
})
|
|
79
|
+
})
|
|
80
|
+
]
|
|
81
|
+
})
|
|
82
|
+
})
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
function RunWorkspaceNavContent({ workspaceSlug, projectSlug, run, jobs, activeSection, currentJobId, jobSearch, annotationSummary, mobileOpen, onNavigate }) {
|
|
86
|
+
const currentRowRef = useRef(null);
|
|
87
|
+
const runAttempt = jobSearch.runAttempt ?? run.runAttempt.attempt;
|
|
88
|
+
useEffect(()=>{
|
|
89
|
+
if (!currentJobId || mobileOpen) return;
|
|
90
|
+
currentRowRef.current?.scrollIntoView({
|
|
91
|
+
block: 'nearest'
|
|
92
|
+
});
|
|
93
|
+
}, [
|
|
94
|
+
currentJobId,
|
|
95
|
+
mobileOpen
|
|
96
|
+
]);
|
|
97
|
+
useEffect(()=>{
|
|
98
|
+
if (!currentJobId || !mobileOpen) return;
|
|
99
|
+
currentRowRef.current?.scrollIntoView({
|
|
100
|
+
block: 'nearest'
|
|
101
|
+
});
|
|
102
|
+
}, [
|
|
103
|
+
currentJobId,
|
|
104
|
+
mobileOpen
|
|
105
|
+
]);
|
|
106
|
+
return /*#__PURE__*/ _jsxs("nav", {
|
|
107
|
+
"aria-label": "Run workspace",
|
|
108
|
+
className: "flex min-w-0 flex-col gap-16",
|
|
109
|
+
children: [
|
|
110
|
+
/*#__PURE__*/ _jsx("ul", {
|
|
111
|
+
children: /*#__PURE__*/ _jsx("li", {
|
|
112
|
+
children: /*#__PURE__*/ _jsx(RunSectionLink, {
|
|
113
|
+
workspaceSlug: workspaceSlug,
|
|
114
|
+
projectSlug: projectSlug,
|
|
115
|
+
runId: run.id,
|
|
116
|
+
runAttempt: runAttempt,
|
|
117
|
+
section: "summary",
|
|
118
|
+
current: !currentJobId && activeSection === 'summary',
|
|
119
|
+
onNavigate: onNavigate
|
|
120
|
+
})
|
|
121
|
+
})
|
|
122
|
+
}),
|
|
123
|
+
/*#__PURE__*/ _jsxs("section", {
|
|
124
|
+
"aria-labelledby": "run-workspace-jobs-heading",
|
|
125
|
+
className: "min-w-0",
|
|
126
|
+
children: [
|
|
127
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
128
|
+
className: "flex items-center justify-between gap-8 px-8 pb-6",
|
|
129
|
+
children: [
|
|
130
|
+
/*#__PURE__*/ _jsx(Text, {
|
|
131
|
+
as: "h2",
|
|
132
|
+
id: "run-workspace-jobs-heading",
|
|
133
|
+
size: "xs",
|
|
134
|
+
bold: true,
|
|
135
|
+
className: "text-foreground-neutral-muted",
|
|
136
|
+
children: "Jobs"
|
|
137
|
+
}),
|
|
138
|
+
/*#__PURE__*/ _jsx(Text, {
|
|
139
|
+
as: "span",
|
|
140
|
+
size: "xs",
|
|
141
|
+
className: "font-code text-foreground-neutral-subtle",
|
|
142
|
+
children: jobs.length
|
|
143
|
+
})
|
|
144
|
+
]
|
|
145
|
+
}),
|
|
146
|
+
/*#__PURE__*/ _jsx("ol", {
|
|
147
|
+
className: "max-h-[320px] overflow-y-auto",
|
|
148
|
+
children: jobs.map((job)=>{
|
|
149
|
+
const current = job.id === currentJobId;
|
|
150
|
+
const execution = defaultJobExecution(job);
|
|
151
|
+
const duration = execution?.displayDuration ?? job.displayDuration;
|
|
152
|
+
return /*#__PURE__*/ _jsx("li", {
|
|
153
|
+
children: /*#__PURE__*/ _jsxs(Link, {
|
|
154
|
+
ref: current ? currentRowRef : undefined,
|
|
155
|
+
to: "/w/$workspaceSlug/p/$projectSlug/runs/$workflowRunId/jobs/$jobId",
|
|
156
|
+
params: {
|
|
157
|
+
workspaceSlug,
|
|
158
|
+
projectSlug,
|
|
159
|
+
workflowRunId: run.id,
|
|
160
|
+
jobId: job.id
|
|
161
|
+
},
|
|
162
|
+
search: workflowJobSearchParams({
|
|
163
|
+
runAttempt
|
|
164
|
+
}),
|
|
165
|
+
onClick: onNavigate,
|
|
166
|
+
"aria-current": current ? 'page' : undefined,
|
|
167
|
+
className: cn('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', current && 'bg-background-neutral-hover'),
|
|
168
|
+
children: [
|
|
169
|
+
/*#__PURE__*/ _jsx(WorkflowStatusIcon, {
|
|
170
|
+
status: deriveJobDisplayStatus(job),
|
|
171
|
+
size: 12,
|
|
172
|
+
tooltip: false
|
|
173
|
+
}),
|
|
174
|
+
/*#__PURE__*/ _jsx("span", {
|
|
175
|
+
className: "min-w-0 truncate font-code text-xs leading-20 text-foreground-neutral-base",
|
|
176
|
+
children: job.displayName
|
|
177
|
+
}),
|
|
178
|
+
/*#__PURE__*/ _jsx("span", {
|
|
179
|
+
className: "ml-auto shrink-0 font-code text-xs leading-20 text-foreground-neutral-muted tabular-nums",
|
|
180
|
+
children: duration ? /*#__PURE__*/ _jsx(JobExecutionTimeText, {
|
|
181
|
+
time: duration
|
|
182
|
+
}) : '—'
|
|
183
|
+
})
|
|
184
|
+
]
|
|
185
|
+
})
|
|
186
|
+
}, job.id);
|
|
187
|
+
})
|
|
188
|
+
})
|
|
189
|
+
]
|
|
190
|
+
}),
|
|
191
|
+
/*#__PURE__*/ _jsxs("section", {
|
|
192
|
+
"aria-labelledby": "run-workspace-details-heading",
|
|
193
|
+
children: [
|
|
194
|
+
/*#__PURE__*/ _jsx(Text, {
|
|
195
|
+
as: "h2",
|
|
196
|
+
id: "run-workspace-details-heading",
|
|
197
|
+
size: "xs",
|
|
198
|
+
bold: true,
|
|
199
|
+
className: "px-8 pb-6 text-foreground-neutral-muted",
|
|
200
|
+
children: "Run details"
|
|
201
|
+
}),
|
|
202
|
+
/*#__PURE__*/ _jsxs("ul", {
|
|
203
|
+
children: [
|
|
204
|
+
/*#__PURE__*/ _jsx("li", {
|
|
205
|
+
children: /*#__PURE__*/ _jsx(RunSectionLink, {
|
|
206
|
+
workspaceSlug: workspaceSlug,
|
|
207
|
+
projectSlug: projectSlug,
|
|
208
|
+
runId: run.id,
|
|
209
|
+
runAttempt: runAttempt,
|
|
210
|
+
section: "annotations",
|
|
211
|
+
current: !currentJobId && activeSection === 'annotations',
|
|
212
|
+
count: annotationSummary?.total,
|
|
213
|
+
onNavigate: onNavigate
|
|
214
|
+
})
|
|
215
|
+
}),
|
|
216
|
+
/*#__PURE__*/ _jsx("li", {
|
|
217
|
+
children: /*#__PURE__*/ _jsx(RunSectionLink, {
|
|
218
|
+
workspaceSlug: workspaceSlug,
|
|
219
|
+
projectSlug: projectSlug,
|
|
220
|
+
runId: run.id,
|
|
221
|
+
runAttempt: runAttempt,
|
|
222
|
+
section: "source",
|
|
223
|
+
current: !currentJobId && activeSection === 'source',
|
|
224
|
+
onNavigate: onNavigate
|
|
225
|
+
})
|
|
226
|
+
})
|
|
227
|
+
]
|
|
228
|
+
})
|
|
229
|
+
]
|
|
230
|
+
})
|
|
231
|
+
]
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
function RunSectionLink({ workspaceSlug, projectSlug, runId, runAttempt, section, current, count, onNavigate }) {
|
|
235
|
+
return /*#__PURE__*/ _jsxs(Link, {
|
|
236
|
+
to: "/w/$workspaceSlug/p/$projectSlug/runs/$workflowRunId",
|
|
237
|
+
params: {
|
|
238
|
+
workspaceSlug,
|
|
239
|
+
projectSlug,
|
|
240
|
+
workflowRunId: runId
|
|
241
|
+
},
|
|
242
|
+
search: workflowRunSearchParams({
|
|
243
|
+
runAttempt,
|
|
244
|
+
...section === 'summary' ? {} : {
|
|
245
|
+
tab: section
|
|
246
|
+
}
|
|
247
|
+
}, {
|
|
248
|
+
runAttempt
|
|
249
|
+
}),
|
|
250
|
+
onClick: onNavigate,
|
|
251
|
+
"aria-current": current ? 'page' : undefined,
|
|
252
|
+
className: cn('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', current && 'bg-background-neutral-hover'),
|
|
253
|
+
children: [
|
|
254
|
+
sectionLabel(section),
|
|
255
|
+
count ? /*#__PURE__*/ _jsx("span", {
|
|
256
|
+
className: "ml-auto font-code text-xs text-foreground-neutral-muted tabular-nums",
|
|
257
|
+
children: count
|
|
258
|
+
}) : null
|
|
259
|
+
]
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
function sectionLabel(section) {
|
|
263
|
+
if (section === 'annotations') return 'Annotations';
|
|
264
|
+
if (section === 'source') return 'Source';
|
|
265
|
+
return 'Summary';
|
|
266
|
+
}
|
|
267
|
+
function compareJobs(left, right) {
|
|
268
|
+
return left.position - right.position || left.id.localeCompare(right.id);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
//# sourceMappingURL=run-workspace-nav.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/workflow-run-view/run-workspace-nav.tsx"],"sourcesContent":["import {Collapsible, CollapsibleTrigger} from '@shipfox/react-ui/collapsible';\nimport {Icon} from '@shipfox/react-ui/icon';\nimport {TimeTickerProvider} from '@shipfox/react-ui/time-ticker';\nimport {Text} from '@shipfox/react-ui/typography';\nimport {cn} from '@shipfox/react-ui/utils';\nimport {Link} from '@tanstack/react-router';\nimport {useEffect, useMemo, useRef, useState} from 'react';\nimport {WorkflowStatusIcon} from '#components/workflow-status/workflow-status-icon.js';\nimport {\n defaultJobExecution,\n deriveJobDisplayStatus,\n type Job,\n type WorkflowRunDetail,\n} from '#core/workflow-run.js';\nimport type {RunAnnotationSummary} from '#core/workflow-run-tabs.js';\nimport {\n type WorkflowJobSearch,\n type WorkflowRunTab,\n workflowJobSearchParams,\n workflowRunSearchParams,\n} from '#routes/inputs.js';\nimport {JobExecutionTimeText} from '../job-detail/job-execution-time-text.js';\n\ntype RunWorkspaceSection = Exclude<WorkflowRunTab, 'jobs'>;\n\nexport interface RunWorkspaceNavProps {\n workspaceSlug: string;\n projectSlug: string;\n run: WorkflowRunDetail;\n activeSection: RunWorkspaceSection;\n currentJobId?: string | undefined;\n jobSearch?: WorkflowJobSearch | undefined;\n annotationSummary?: RunAnnotationSummary | undefined;\n}\n\n/**\n * The stable navigation model shared by run-level and job-level routes. The graph explains\n * topology; this compact index makes moving between dedicated job pages predictable.\n */\nexport function RunWorkspaceNav({\n workspaceSlug,\n projectSlug,\n run,\n activeSection,\n currentJobId,\n jobSearch = {},\n annotationSummary,\n}: RunWorkspaceNavProps) {\n const jobs = useMemo(() => [...run.jobs].sort(compareJobs), [run.jobs]);\n const [mobileOpen, setMobileOpen] = useState(false);\n const currentJob = jobs.find((job) => job.id === currentJobId);\n const currentLabel = currentJob?.displayName ?? sectionLabel(activeSection);\n\n return (\n <TimeTickerProvider intervalMs={1000} reducedMotionIntervalMs={10_000}>\n <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\">\n <Collapsible open={mobileOpen} onOpenChange={setMobileOpen}>\n <CollapsibleTrigger asChild>\n <button\n type=\"button\"\n 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\"\n aria-label=\"Toggle run navigation\"\n >\n <span className=\"min-w-0\">\n <Text as=\"span\" size=\"xs\" className=\"block text-foreground-neutral-muted\">\n Run navigation\n </Text>\n <span className=\"block truncate font-code text-xs leading-20 text-foreground-neutral-base\">\n {currentLabel}\n </span>\n </span>\n <Icon\n name=\"chevronDown\"\n size={14}\n aria-hidden=\"true\"\n className={cn(\n 'shrink-0 text-foreground-neutral-muted transition-transform',\n mobileOpen && 'rotate-180',\n )}\n />\n </button>\n </CollapsibleTrigger>\n <div\n className={cn(\n 'max-h-[50vh] overflow-y-auto p-8 min-[768px]:block min-[768px]:max-h-none min-[768px]:p-12',\n !mobileOpen && 'hidden',\n )}\n >\n <RunWorkspaceNavContent\n workspaceSlug={workspaceSlug}\n projectSlug={projectSlug}\n run={run}\n jobs={jobs}\n activeSection={activeSection}\n currentJobId={currentJobId}\n jobSearch={jobSearch}\n annotationSummary={annotationSummary}\n mobileOpen={mobileOpen}\n onNavigate={() => setMobileOpen(false)}\n />\n </div>\n </Collapsible>\n </aside>\n </TimeTickerProvider>\n );\n}\n\nfunction RunWorkspaceNavContent({\n workspaceSlug,\n projectSlug,\n run,\n jobs,\n activeSection,\n currentJobId,\n jobSearch,\n annotationSummary,\n mobileOpen,\n onNavigate,\n}: RunWorkspaceNavProps & {\n jobs: Job[];\n jobSearch: WorkflowJobSearch;\n mobileOpen: boolean;\n onNavigate: () => void;\n}) {\n const currentRowRef = useRef<HTMLAnchorElement>(null);\n const runAttempt = jobSearch.runAttempt ?? run.runAttempt.attempt;\n\n useEffect(() => {\n if (!currentJobId || mobileOpen) return;\n currentRowRef.current?.scrollIntoView({block: 'nearest'});\n }, [currentJobId, mobileOpen]);\n\n useEffect(() => {\n if (!currentJobId || !mobileOpen) return;\n currentRowRef.current?.scrollIntoView({block: 'nearest'});\n }, [currentJobId, mobileOpen]);\n\n return (\n <nav aria-label=\"Run workspace\" className=\"flex min-w-0 flex-col gap-16\">\n <ul>\n <li>\n <RunSectionLink\n workspaceSlug={workspaceSlug}\n projectSlug={projectSlug}\n runId={run.id}\n runAttempt={runAttempt}\n section=\"summary\"\n current={!currentJobId && activeSection === 'summary'}\n onNavigate={onNavigate}\n />\n </li>\n </ul>\n\n <section aria-labelledby=\"run-workspace-jobs-heading\" className=\"min-w-0\">\n <div className=\"flex items-center justify-between gap-8 px-8 pb-6\">\n <Text\n as=\"h2\"\n id=\"run-workspace-jobs-heading\"\n size=\"xs\"\n bold\n className=\"text-foreground-neutral-muted\"\n >\n Jobs\n </Text>\n <Text as=\"span\" size=\"xs\" className=\"font-code text-foreground-neutral-subtle\">\n {jobs.length}\n </Text>\n </div>\n <ol className=\"max-h-[320px] overflow-y-auto\">\n {jobs.map((job) => {\n const current = job.id === currentJobId;\n const execution = defaultJobExecution(job);\n const duration = execution?.displayDuration ?? job.displayDuration;\n\n return (\n <li key={job.id}>\n <Link\n ref={current ? currentRowRef : undefined}\n to=\"/w/$workspaceSlug/p/$projectSlug/runs/$workflowRunId/jobs/$jobId\"\n params={{workspaceSlug, projectSlug, workflowRunId: run.id, jobId: job.id}}\n search={workflowJobSearchParams({runAttempt}) as never}\n onClick={onNavigate}\n aria-current={current ? 'page' : undefined}\n className={cn(\n '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',\n current && 'bg-background-neutral-hover',\n )}\n >\n <WorkflowStatusIcon\n status={deriveJobDisplayStatus(job)}\n size={12}\n tooltip={false}\n />\n <span className=\"min-w-0 truncate font-code text-xs leading-20 text-foreground-neutral-base\">\n {job.displayName}\n </span>\n <span className=\"ml-auto shrink-0 font-code text-xs leading-20 text-foreground-neutral-muted tabular-nums\">\n {duration ? <JobExecutionTimeText time={duration} /> : '—'}\n </span>\n </Link>\n </li>\n );\n })}\n </ol>\n </section>\n\n <section aria-labelledby=\"run-workspace-details-heading\">\n <Text\n as=\"h2\"\n id=\"run-workspace-details-heading\"\n size=\"xs\"\n bold\n className=\"px-8 pb-6 text-foreground-neutral-muted\"\n >\n Run details\n </Text>\n <ul>\n <li>\n <RunSectionLink\n workspaceSlug={workspaceSlug}\n projectSlug={projectSlug}\n runId={run.id}\n runAttempt={runAttempt}\n section=\"annotations\"\n current={!currentJobId && activeSection === 'annotations'}\n count={annotationSummary?.total}\n onNavigate={onNavigate}\n />\n </li>\n <li>\n <RunSectionLink\n workspaceSlug={workspaceSlug}\n projectSlug={projectSlug}\n runId={run.id}\n runAttempt={runAttempt}\n section=\"source\"\n current={!currentJobId && activeSection === 'source'}\n onNavigate={onNavigate}\n />\n </li>\n </ul>\n </section>\n </nav>\n );\n}\n\nfunction RunSectionLink({\n workspaceSlug,\n projectSlug,\n runId,\n runAttempt,\n section,\n current,\n count,\n onNavigate,\n}: {\n workspaceSlug: string;\n projectSlug: string;\n runId: string;\n runAttempt: number;\n section: RunWorkspaceSection;\n current: boolean;\n count?: number | undefined;\n onNavigate?: (() => void) | undefined;\n}) {\n return (\n <Link\n to=\"/w/$workspaceSlug/p/$projectSlug/runs/$workflowRunId\"\n params={{workspaceSlug, projectSlug, workflowRunId: runId}}\n search={\n workflowRunSearchParams(\n {runAttempt, ...(section === 'summary' ? {} : {tab: section})},\n {runAttempt},\n ) as never\n }\n onClick={onNavigate}\n aria-current={current ? 'page' : undefined}\n className={cn(\n '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',\n current && 'bg-background-neutral-hover',\n )}\n >\n {sectionLabel(section)}\n {count ? (\n <span className=\"ml-auto font-code text-xs text-foreground-neutral-muted tabular-nums\">\n {count}\n </span>\n ) : null}\n </Link>\n );\n}\n\nfunction sectionLabel(section: RunWorkspaceSection): string {\n if (section === 'annotations') return 'Annotations';\n if (section === 'source') return 'Source';\n return 'Summary';\n}\n\nfunction compareJobs(left: Job, right: Job): number {\n return left.position - right.position || left.id.localeCompare(right.id);\n}\n"],"names":["Collapsible","CollapsibleTrigger","Icon","TimeTickerProvider","Text","cn","Link","useEffect","useMemo","useRef","useState","WorkflowStatusIcon","defaultJobExecution","deriveJobDisplayStatus","workflowJobSearchParams","workflowRunSearchParams","JobExecutionTimeText","RunWorkspaceNav","workspaceSlug","projectSlug","run","activeSection","currentJobId","jobSearch","annotationSummary","jobs","sort","compareJobs","mobileOpen","setMobileOpen","currentJob","find","job","id","currentLabel","displayName","sectionLabel","intervalMs","reducedMotionIntervalMs","aside","className","open","onOpenChange","asChild","button","type","aria-label","span","as","size","name","aria-hidden","div","RunWorkspaceNavContent","onNavigate","currentRowRef","runAttempt","attempt","current","scrollIntoView","block","nav","ul","li","RunSectionLink","runId","section","aria-labelledby","bold","length","ol","map","execution","duration","displayDuration","ref","undefined","to","params","workflowRunId","jobId","search","onClick","aria-current","status","tooltip","time","count","total","tab","left","right","position","localeCompare"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflow-run-selection.d.ts","sourceRoot":"","sources":["../../../src/components/workflow-run-view/workflow-run-selection.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,GAAG,EACR,KAAK,YAAY,
|
|
1
|
+
{"version":3,"file":"workflow-run-selection.d.ts","sourceRoot":"","sources":["../../../src/components/workflow-run-view/workflow-run-selection.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,GAAG,EACR,KAAK,YAAY,EAGjB,KAAK,IAAI,EACT,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACvB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAC,yBAAyB,EAAC,MAAM,iCAAiC,CAAC;AAE/E,MAAM,WAAW,4BAA4B;IAC3C,GAAG,EAAE,GAAG,GAAG,SAAS,CAAC;IACrB,YAAY,EAAE,YAAY,GAAG,SAAS,CAAC;IACvC,IAAI,EAAE,IAAI,GAAG,SAAS,CAAC;IACvB,OAAO,EAAE,WAAW,GAAG,SAAS,CAAC;IACjC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED,wBAAgB,2BAA2B,CAAC,EAC1C,GAAG,EACH,SAAS,GACV,EAAE;IACD,GAAG,EAAE,iBAAiB,CAAC;IACvB,SAAS,EAAE,yBAAyB,CAAC;CACtC,GAAG,4BAA4B,CAwC/B"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { resolveJobExecution } from '#core/workflow-run.js';
|
|
1
|
+
import { resolveJobExecution, resolveStepAttempt } from '#core/workflow-run.js';
|
|
2
2
|
export function resolveWorkflowRunSelection({ run, selection }) {
|
|
3
3
|
const jobById = new Map(run.jobs.map((job)=>[
|
|
4
4
|
job.id,
|
|
@@ -78,18 +78,5 @@ function findStep(run, stepId) {
|
|
|
78
78
|
}
|
|
79
79
|
return undefined;
|
|
80
80
|
}
|
|
81
|
-
function resolveStepAttempt(step, attemptId) {
|
|
82
|
-
const attemptById = attemptId ? step.attempts.find((attempt)=>attempt.id === attemptId) : undefined;
|
|
83
|
-
if (attemptById) return attemptById;
|
|
84
|
-
const currentAttempt = step.attempts.find((attempt)=>attempt.attempt === step.currentAttempt);
|
|
85
|
-
if (currentAttempt) return currentAttempt;
|
|
86
|
-
return step.attempts.reduce((latest, attempt)=>{
|
|
87
|
-
if (!latest) return attempt;
|
|
88
|
-
return compareAttempts(attempt, latest) > 0 ? attempt : latest;
|
|
89
|
-
}, undefined);
|
|
90
|
-
}
|
|
91
|
-
function compareAttempts(left, right) {
|
|
92
|
-
return left.attempt - right.attempt || left.executionOrder - right.executionOrder || left.id.localeCompare(right.id);
|
|
93
|
-
}
|
|
94
81
|
|
|
95
82
|
//# sourceMappingURL=workflow-run-selection.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/workflow-run-view/workflow-run-selection.ts"],"sourcesContent":["import {\n type Job,\n type JobExecution,\n resolveJobExecution,\n type Step,\n type StepAttempt,\n type WorkflowRunDetail,\n} from '#core/workflow-run.js';\nimport type {WorkflowRunSelectionInput} from '#core/workflow-run-url-state.js';\n\nexport interface ResolvedWorkflowRunSelection {\n job: Job | undefined;\n jobExecution: JobExecution | undefined;\n step: Step | undefined;\n attempt: StepAttempt | undefined;\n selectedAttemptId: string | null;\n}\n\nexport function resolveWorkflowRunSelection({\n run,\n selection,\n}: {\n run: WorkflowRunDetail;\n selection: WorkflowRunSelectionInput;\n}): ResolvedWorkflowRunSelection {\n const jobById = new Map(run.jobs.map((job) => [job.id, job]));\n const stepMatch = findStep(run, selection.stepId);\n const jobExecutionMatch = findJobExecution(run, selection.jobExecutionId);\n const stepAttemptMatch = findStepAttempt(run, selection.stepAttemptId);\n\n if (stepMatch) {\n const attempt = resolveStepAttempt(stepMatch.step, selection.stepAttemptId);\n return {\n job: stepMatch.job,\n jobExecution: stepMatch.jobExecution,\n step: stepMatch.step,\n attempt,\n selectedAttemptId: attempt?.id ?? null,\n };\n }\n\n if (stepAttemptMatch) {\n return {\n job: stepAttemptMatch.job,\n jobExecution: stepAttemptMatch.jobExecution,\n step: stepAttemptMatch.step,\n attempt: stepAttemptMatch.attempt,\n selectedAttemptId: stepAttemptMatch.attempt.id,\n };\n }\n\n const job =\n (selection.jobId ? jobById.get(selection.jobId) : undefined) ??\n jobExecutionMatch?.job ??\n run.jobs.at(0);\n const jobExecution = job ? resolveJobExecution(job, selection.jobExecutionId) : undefined;\n\n return {\n job,\n jobExecution,\n step: undefined,\n attempt: undefined,\n selectedAttemptId: null,\n };\n}\n\nfunction findJobExecution(\n run: WorkflowRunDetail,\n jobExecutionId: string | undefined,\n): {job: Job; jobExecution: JobExecution} | undefined {\n if (!jobExecutionId) return undefined;\n\n for (const job of run.jobs) {\n const jobExecution = job.jobExecutions.find((candidate) => candidate.id === jobExecutionId);\n if (jobExecution) return {job, jobExecution};\n }\n\n return undefined;\n}\n\nfunction findStepAttempt(\n run: WorkflowRunDetail,\n stepAttemptId: string | undefined,\n): {job: Job; jobExecution: JobExecution; step: Step; attempt: StepAttempt} | undefined {\n if (!stepAttemptId) return undefined;\n\n for (const job of run.jobs) {\n for (const jobExecution of job.jobExecutions) {\n for (const step of jobExecution.steps) {\n const attempt = step.attempts.find((candidate) => candidate.id === stepAttemptId);\n if (attempt) return {job, jobExecution, step, attempt};\n }\n }\n }\n\n return undefined;\n}\n\nfunction findStep(\n run: WorkflowRunDetail,\n stepId: string | undefined,\n): {job: Job; jobExecution: JobExecution; step: Step} | undefined {\n if (!stepId) return undefined;\n\n for (const job of run.jobs) {\n for (const jobExecution of job.jobExecutions) {\n const step = jobExecution.steps.find((candidate) => candidate.id === stepId);\n if (step) return {job, jobExecution, step};\n }\n }\n\n return undefined;\n}\n
|
|
1
|
+
{"version":3,"sources":["../../../src/components/workflow-run-view/workflow-run-selection.ts"],"sourcesContent":["import {\n type Job,\n type JobExecution,\n resolveJobExecution,\n resolveStepAttempt,\n type Step,\n type StepAttempt,\n type WorkflowRunDetail,\n} from '#core/workflow-run.js';\nimport type {WorkflowRunSelectionInput} from '#core/workflow-run-url-state.js';\n\nexport interface ResolvedWorkflowRunSelection {\n job: Job | undefined;\n jobExecution: JobExecution | undefined;\n step: Step | undefined;\n attempt: StepAttempt | undefined;\n selectedAttemptId: string | null;\n}\n\nexport function resolveWorkflowRunSelection({\n run,\n selection,\n}: {\n run: WorkflowRunDetail;\n selection: WorkflowRunSelectionInput;\n}): ResolvedWorkflowRunSelection {\n const jobById = new Map(run.jobs.map((job) => [job.id, job]));\n const stepMatch = findStep(run, selection.stepId);\n const jobExecutionMatch = findJobExecution(run, selection.jobExecutionId);\n const stepAttemptMatch = findStepAttempt(run, selection.stepAttemptId);\n\n if (stepMatch) {\n const attempt = resolveStepAttempt(stepMatch.step, selection.stepAttemptId);\n return {\n job: stepMatch.job,\n jobExecution: stepMatch.jobExecution,\n step: stepMatch.step,\n attempt,\n selectedAttemptId: attempt?.id ?? null,\n };\n }\n\n if (stepAttemptMatch) {\n return {\n job: stepAttemptMatch.job,\n jobExecution: stepAttemptMatch.jobExecution,\n step: stepAttemptMatch.step,\n attempt: stepAttemptMatch.attempt,\n selectedAttemptId: stepAttemptMatch.attempt.id,\n };\n }\n\n const job =\n (selection.jobId ? jobById.get(selection.jobId) : undefined) ??\n jobExecutionMatch?.job ??\n run.jobs.at(0);\n const jobExecution = job ? resolveJobExecution(job, selection.jobExecutionId) : undefined;\n\n return {\n job,\n jobExecution,\n step: undefined,\n attempt: undefined,\n selectedAttemptId: null,\n };\n}\n\nfunction findJobExecution(\n run: WorkflowRunDetail,\n jobExecutionId: string | undefined,\n): {job: Job; jobExecution: JobExecution} | undefined {\n if (!jobExecutionId) return undefined;\n\n for (const job of run.jobs) {\n const jobExecution = job.jobExecutions.find((candidate) => candidate.id === jobExecutionId);\n if (jobExecution) return {job, jobExecution};\n }\n\n return undefined;\n}\n\nfunction findStepAttempt(\n run: WorkflowRunDetail,\n stepAttemptId: string | undefined,\n): {job: Job; jobExecution: JobExecution; step: Step; attempt: StepAttempt} | undefined {\n if (!stepAttemptId) return undefined;\n\n for (const job of run.jobs) {\n for (const jobExecution of job.jobExecutions) {\n for (const step of jobExecution.steps) {\n const attempt = step.attempts.find((candidate) => candidate.id === stepAttemptId);\n if (attempt) return {job, jobExecution, step, attempt};\n }\n }\n }\n\n return undefined;\n}\n\nfunction findStep(\n run: WorkflowRunDetail,\n stepId: string | undefined,\n): {job: Job; jobExecution: JobExecution; step: Step} | undefined {\n if (!stepId) return undefined;\n\n for (const job of run.jobs) {\n for (const jobExecution of job.jobExecutions) {\n const step = jobExecution.steps.find((candidate) => candidate.id === stepId);\n if (step) return {job, jobExecution, step};\n }\n }\n\n return undefined;\n}\n"],"names":["resolveJobExecution","resolveStepAttempt","resolveWorkflowRunSelection","run","selection","jobById","Map","jobs","map","job","id","stepMatch","findStep","stepId","jobExecutionMatch","findJobExecution","jobExecutionId","stepAttemptMatch","findStepAttempt","stepAttemptId","attempt","step","jobExecution","selectedAttemptId","jobId","get","undefined","at","jobExecutions","find","candidate","steps","attempts"],"mappings":"AAAA,SAGEA,mBAAmB,EACnBC,kBAAkB,QAIb,wBAAwB;AAW/B,OAAO,SAASC,4BAA4B,EAC1CC,GAAG,EACHC,SAAS,EAIV;IACC,MAAMC,UAAU,IAAIC,IAAIH,IAAII,IAAI,CAACC,GAAG,CAAC,CAACC,MAAQ;YAACA,IAAIC,EAAE;YAAED;SAAI;IAC3D,MAAME,YAAYC,SAAST,KAAKC,UAAUS,MAAM;IAChD,MAAMC,oBAAoBC,iBAAiBZ,KAAKC,UAAUY,cAAc;IACxE,MAAMC,mBAAmBC,gBAAgBf,KAAKC,UAAUe,aAAa;IAErE,IAAIR,WAAW;QACb,MAAMS,UAAUnB,mBAAmBU,UAAUU,IAAI,EAAEjB,UAAUe,aAAa;QAC1E,OAAO;YACLV,KAAKE,UAAUF,GAAG;YAClBa,cAAcX,UAAUW,YAAY;YACpCD,MAAMV,UAAUU,IAAI;YACpBD;YACAG,mBAAmBH,SAASV,MAAM;QACpC;IACF;IAEA,IAAIO,kBAAkB;QACpB,OAAO;YACLR,KAAKQ,iBAAiBR,GAAG;YACzBa,cAAcL,iBAAiBK,YAAY;YAC3CD,MAAMJ,iBAAiBI,IAAI;YAC3BD,SAASH,iBAAiBG,OAAO;YACjCG,mBAAmBN,iBAAiBG,OAAO,CAACV,EAAE;QAChD;IACF;IAEA,MAAMD,MACJ,AAACL,CAAAA,UAAUoB,KAAK,GAAGnB,QAAQoB,GAAG,CAACrB,UAAUoB,KAAK,IAAIE,SAAQ,KAC1DZ,mBAAmBL,OACnBN,IAAII,IAAI,CAACoB,EAAE,CAAC;IACd,MAAML,eAAeb,MAAMT,oBAAoBS,KAAKL,UAAUY,cAAc,IAAIU;IAEhF,OAAO;QACLjB;QACAa;QACAD,MAAMK;QACNN,SAASM;QACTH,mBAAmB;IACrB;AACF;AAEA,SAASR,iBACPZ,GAAsB,EACtBa,cAAkC;IAElC,IAAI,CAACA,gBAAgB,OAAOU;IAE5B,KAAK,MAAMjB,OAAON,IAAII,IAAI,CAAE;QAC1B,MAAMe,eAAeb,IAAImB,aAAa,CAACC,IAAI,CAAC,CAACC,YAAcA,UAAUpB,EAAE,KAAKM;QAC5E,IAAIM,cAAc,OAAO;YAACb;YAAKa;QAAY;IAC7C;IAEA,OAAOI;AACT;AAEA,SAASR,gBACPf,GAAsB,EACtBgB,aAAiC;IAEjC,IAAI,CAACA,eAAe,OAAOO;IAE3B,KAAK,MAAMjB,OAAON,IAAII,IAAI,CAAE;QAC1B,KAAK,MAAMe,gBAAgBb,IAAImB,aAAa,CAAE;YAC5C,KAAK,MAAMP,QAAQC,aAAaS,KAAK,CAAE;gBACrC,MAAMX,UAAUC,KAAKW,QAAQ,CAACH,IAAI,CAAC,CAACC,YAAcA,UAAUpB,EAAE,KAAKS;gBACnE,IAAIC,SAAS,OAAO;oBAACX;oBAAKa;oBAAcD;oBAAMD;gBAAO;YACvD;QACF;IACF;IAEA,OAAOM;AACT;AAEA,SAASd,SACPT,GAAsB,EACtBU,MAA0B;IAE1B,IAAI,CAACA,QAAQ,OAAOa;IAEpB,KAAK,MAAMjB,OAAON,IAAII,IAAI,CAAE;QAC1B,KAAK,MAAMe,gBAAgBb,IAAImB,aAAa,CAAE;YAC5C,MAAMP,OAAOC,aAAaS,KAAK,CAACF,IAAI,CAAC,CAACC,YAAcA,UAAUpB,EAAE,KAAKG;YACrE,IAAIQ,MAAM,OAAO;gBAACZ;gBAAKa;gBAAcD;YAAI;QAC3C;IACF;IAEA,OAAOK;AACT"}
|
|
@@ -1,20 +1,22 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
1
2
|
import type { RunAnnotationSummary } from '#core/workflow-run-tabs.js';
|
|
2
|
-
import { type
|
|
3
|
-
import { type WorkflowRunTab } from '#routes/inputs.js';
|
|
3
|
+
import { type WorkflowJobSearch, type WorkflowRunsSearch, type WorkflowRunTab } from '#routes/inputs.js';
|
|
4
4
|
export interface WorkflowRunViewProps {
|
|
5
5
|
projectId: string;
|
|
6
6
|
workspaceSlug?: string | undefined;
|
|
7
7
|
projectSlug?: string | undefined;
|
|
8
8
|
workflowRunId?: string | undefined;
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
runAttempt?: number | undefined;
|
|
10
|
+
selection?: WorkflowRunsSearch | undefined;
|
|
11
11
|
tab?: WorkflowRunTab | undefined;
|
|
12
|
-
onTabChange?: ((tab: WorkflowRunTab) => void) | undefined;
|
|
13
12
|
annotationSummary?: RunAnnotationSummary | undefined;
|
|
13
|
+
activeJobId?: string | undefined;
|
|
14
|
+
jobSearch?: WorkflowJobSearch | undefined;
|
|
15
|
+
jobContent?: ReactNode | undefined;
|
|
14
16
|
}
|
|
15
17
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
+
* The persistent run workspace. Run-level sections and dedicated job routes share the same
|
|
19
|
+
* header and job index, while the all-jobs Summary always opens on the dependency graph.
|
|
18
20
|
*/
|
|
19
|
-
export declare function WorkflowRunView({ projectId, workspaceSlug, projectSlug, workflowRunId,
|
|
21
|
+
export declare function WorkflowRunView({ projectId, workspaceSlug, projectSlug, workflowRunId, runAttempt, selection, tab, annotationSummary, activeJobId, jobSearch, jobContent, }: WorkflowRunViewProps): import("react").JSX.Element;
|
|
20
22
|
//# sourceMappingURL=workflow-run-view.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflow-run-view.d.ts","sourceRoot":"","sources":["../../../src/components/workflow-run-view/workflow-run-view.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"workflow-run-view.d.ts","sourceRoot":"","sources":["../../../src/components/workflow-run-view/workflow-run-view.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAC,KAAK,SAAS,EAAY,MAAM,OAAO,CAAC;AAEhD,OAAO,KAAK,EAAC,oBAAoB,EAAC,MAAM,4BAA4B,CAAC;AAOrE,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EAGpB,MAAM,mBAAmB,CAAC;AAiB3B,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,SAAS,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC;IAC3C,GAAG,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IACjC,iBAAiB,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAC;IACrD,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,SAAS,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;IAC1C,UAAU,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;CACpC;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,EAC9B,SAAS,EACT,aAAa,EACb,WAAW,EACX,aAAa,EACb,UAAU,EACV,SAAS,EACT,GAAG,EACH,iBAAiB,EACjB,WAAW,EACX,SAAS,EACT,UAAU,GACX,EAAE,oBAAoB,+BA0BtB"}
|