@shipfox/client-workflows 13.0.0 → 14.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.
Files changed (133) hide show
  1. package/.storybook/main.ts +16 -1
  2. package/.storybook/workspace-source.ts +31 -0
  3. package/.turbo/turbo-build.log +1 -1
  4. package/CHANGELOG.md +23 -0
  5. package/dist/components/job-graph/job-duration-label.js +1 -1
  6. package/dist/components/job-graph/job-duration-label.js.map +1 -1
  7. package/dist/components/job-graph/job-graph-content.d.ts +2 -1
  8. package/dist/components/job-graph/job-graph-content.d.ts.map +1 -1
  9. package/dist/components/job-graph/job-graph-content.js +3 -3
  10. package/dist/components/job-graph/job-graph-content.js.map +1 -1
  11. package/dist/components/job-graph/job-graph-view.d.ts +2 -1
  12. package/dist/components/job-graph/job-graph-view.d.ts.map +1 -1
  13. package/dist/components/job-graph/job-graph-view.js +2 -2
  14. package/dist/components/job-graph/job-graph-view.js.map +1 -1
  15. package/dist/components/job-graph/job-node.js +5 -5
  16. package/dist/components/job-graph/job-node.js.map +1 -1
  17. package/dist/components/job-graph/types.d.ts +2 -1
  18. package/dist/components/job-graph/types.d.ts.map +1 -1
  19. package/dist/components/job-graph/types.js.map +1 -1
  20. package/dist/components/workflow-run-duration-label.js +1 -1
  21. package/dist/components/workflow-run-duration-label.js.map +1 -1
  22. package/dist/components/workflow-run-number-label.js +1 -1
  23. package/dist/components/workflow-run-number-label.js.map +1 -1
  24. package/dist/components/workflow-run-summary/workflow-run-attempt-switcher.js +2 -2
  25. package/dist/components/workflow-run-summary/workflow-run-attempt-switcher.js.map +1 -1
  26. package/dist/components/workflow-run-summary/workflow-run-summary.d.ts +2 -7
  27. package/dist/components/workflow-run-summary/workflow-run-summary.d.ts.map +1 -1
  28. package/dist/components/workflow-run-summary/workflow-run-summary.js +92 -68
  29. package/dist/components/workflow-run-summary/workflow-run-summary.js.map +1 -1
  30. package/dist/components/workflow-run-tabs/index.d.ts +6 -0
  31. package/dist/components/workflow-run-tabs/index.d.ts.map +1 -0
  32. package/dist/components/workflow-run-tabs/index.js +7 -0
  33. package/dist/components/workflow-run-tabs/index.js.map +1 -0
  34. package/dist/components/workflow-run-tabs/run-annotation-summary-line.d.ts +11 -0
  35. package/dist/components/workflow-run-tabs/run-annotation-summary-line.d.ts.map +1 -0
  36. package/dist/components/workflow-run-tabs/run-annotation-summary-line.js +71 -0
  37. package/dist/components/workflow-run-tabs/run-annotation-summary-line.js.map +1 -0
  38. package/dist/components/workflow-run-tabs/run-annotations-empty.d.ts +2 -0
  39. package/dist/components/workflow-run-tabs/run-annotations-empty.d.ts.map +1 -0
  40. package/dist/components/workflow-run-tabs/run-annotations-empty.js +11 -0
  41. package/dist/components/workflow-run-tabs/run-annotations-empty.js.map +1 -0
  42. package/dist/components/workflow-run-tabs/run-jobs-list.d.ts +18 -0
  43. package/dist/components/workflow-run-tabs/run-jobs-list.d.ts.map +1 -0
  44. package/dist/components/workflow-run-tabs/run-jobs-list.js +107 -0
  45. package/dist/components/workflow-run-tabs/run-jobs-list.js.map +1 -0
  46. package/dist/components/workflow-run-tabs/run-tab-count.d.ts +6 -0
  47. package/dist/components/workflow-run-tabs/run-tab-count.d.ts.map +1 -0
  48. package/dist/components/workflow-run-tabs/run-tab-count.js +27 -0
  49. package/dist/components/workflow-run-tabs/run-tab-count.js.map +1 -0
  50. package/dist/components/workflow-run-tabs/run-tab-strip.d.ts +8 -0
  51. package/dist/components/workflow-run-tabs/run-tab-strip.d.ts.map +1 -0
  52. package/dist/components/workflow-run-tabs/run-tab-strip.js +82 -0
  53. package/dist/components/workflow-run-tabs/run-tab-strip.js.map +1 -0
  54. package/dist/components/workflow-run-view/workflow-run-selection.d.ts.map +1 -1
  55. package/dist/components/workflow-run-view/workflow-run-selection.js +40 -1
  56. package/dist/components/workflow-run-view/workflow-run-selection.js.map +1 -1
  57. package/dist/components/workflow-run-view/workflow-run-states.d.ts +1 -0
  58. package/dist/components/workflow-run-view/workflow-run-states.d.ts.map +1 -1
  59. package/dist/components/workflow-run-view/workflow-run-states.js +10 -1
  60. package/dist/components/workflow-run-view/workflow-run-states.js.map +1 -1
  61. package/dist/components/workflow-run-view/workflow-run-view.d.ts +8 -4
  62. package/dist/components/workflow-run-view/workflow-run-view.d.ts.map +1 -1
  63. package/dist/components/workflow-run-view/workflow-run-view.js +125 -78
  64. package/dist/components/workflow-run-view/workflow-run-view.js.map +1 -1
  65. package/dist/components/workflow-source-panel/index.d.ts +1 -0
  66. package/dist/components/workflow-source-panel/index.d.ts.map +1 -1
  67. package/dist/components/workflow-source-panel/index.js +1 -0
  68. package/dist/components/workflow-source-panel/index.js.map +1 -1
  69. package/dist/components/workflow-source-panel/workflow-source-content.d.ts +12 -0
  70. package/dist/components/workflow-source-panel/workflow-source-content.d.ts.map +1 -0
  71. package/dist/components/workflow-source-panel/workflow-source-content.js +53 -0
  72. package/dist/components/workflow-source-panel/workflow-source-content.js.map +1 -0
  73. package/dist/components/workflow-source-panel/workflow-source-panel.d.ts +1 -1
  74. package/dist/components/workflow-source-panel/workflow-source-panel.d.ts.map +1 -1
  75. package/dist/components/workflow-source-panel/workflow-source-panel.js +7 -54
  76. package/dist/components/workflow-source-panel/workflow-source-panel.js.map +1 -1
  77. package/dist/core/entities/step.d.ts +1 -1
  78. package/dist/core/entities/step.d.ts.map +1 -1
  79. package/dist/core/entities/step.js +2 -0
  80. package/dist/core/entities/step.js.map +1 -1
  81. package/dist/core/workflow-run-tabs.d.ts +9 -0
  82. package/dist/core/workflow-run-tabs.d.ts.map +1 -0
  83. package/dist/core/workflow-run-tabs.js +3 -0
  84. package/dist/core/workflow-run-tabs.js.map +1 -0
  85. package/dist/pages/workflow-run-detail-page.d.ts.map +1 -1
  86. package/dist/pages/workflow-run-detail-page.js +28 -6
  87. package/dist/pages/workflow-run-detail-page.js.map +1 -1
  88. package/dist/routes/inputs.d.ts +33 -0
  89. package/dist/routes/inputs.d.ts.map +1 -1
  90. package/dist/routes/inputs.js +49 -0
  91. package/dist/routes/inputs.js.map +1 -1
  92. package/dist/tsconfig.test.tsbuildinfo +1 -1
  93. package/package.json +9 -9
  94. package/src/components/job-graph/job-duration-label.tsx +5 -1
  95. package/src/components/job-graph/job-graph-content.tsx +7 -4
  96. package/src/components/job-graph/job-graph-view.tsx +6 -3
  97. package/src/components/job-graph/job-graph.stories.tsx +1 -1
  98. package/src/components/job-graph/job-node.stories.tsx +1 -1
  99. package/src/components/job-graph/job-node.test.tsx +27 -2
  100. package/src/components/job-graph/job-node.tsx +6 -6
  101. package/src/components/job-graph/types.ts +5 -1
  102. package/src/components/workflow-run-duration-label.tsx +1 -1
  103. package/src/components/workflow-run-number-label.tsx +1 -1
  104. package/src/components/workflow-run-summary/workflow-run-attempt-switcher.tsx +2 -2
  105. package/src/components/workflow-run-summary/workflow-run-summary.stories.tsx +23 -30
  106. package/src/components/workflow-run-summary/workflow-run-summary.test.tsx +3 -22
  107. package/src/components/workflow-run-summary/workflow-run-summary.tsx +84 -69
  108. package/src/components/workflow-run-tabs/index.ts +5 -0
  109. package/src/components/workflow-run-tabs/run-annotation-summary-line.test.tsx +69 -0
  110. package/src/components/workflow-run-tabs/run-annotation-summary-line.tsx +97 -0
  111. package/src/components/workflow-run-tabs/run-annotations-empty.tsx +11 -0
  112. package/src/components/workflow-run-tabs/run-jobs-list.tsx +151 -0
  113. package/src/components/workflow-run-tabs/run-tab-count.tsx +28 -0
  114. package/src/components/workflow-run-tabs/run-tab-strip.stories.tsx +52 -0
  115. package/src/components/workflow-run-tabs/run-tab-strip.test.tsx +117 -0
  116. package/src/components/workflow-run-tabs/run-tab-strip.tsx +97 -0
  117. package/src/components/workflow-run-view/workflow-run-selection.test.ts +48 -0
  118. package/src/components/workflow-run-view/workflow-run-selection.ts +48 -1
  119. package/src/components/workflow-run-view/workflow-run-states.tsx +12 -1
  120. package/src/components/workflow-run-view/workflow-run-view.test.tsx +64 -64
  121. package/src/components/workflow-run-view/workflow-run-view.tsx +199 -85
  122. package/src/components/workflow-source-panel/index.ts +1 -0
  123. package/src/components/workflow-source-panel/workflow-source-content.tsx +84 -0
  124. package/src/components/workflow-source-panel/workflow-source-panel.tsx +14 -81
  125. package/src/core/entities/step.ts +4 -0
  126. package/src/core/workflow-run-tabs.ts +8 -0
  127. package/src/pages/workflow-run-detail-page.tsx +31 -4
  128. package/src/pages/workflow-run-pages.test.tsx +185 -45
  129. package/src/routes/inputs.test.ts +47 -0
  130. package/src/routes/inputs.ts +45 -0
  131. package/src/storybook-config.test.ts +27 -0
  132. package/tsconfig.build.tsbuildinfo +1 -1
  133. package/tsconfig.test.json +7 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/workflow-run-tabs/run-jobs-list.tsx"],"sourcesContent":["import {EmptyState} from '@shipfox/react-ui/empty-state';\nimport {useTimeTick} from '@shipfox/react-ui/time-ticker';\nimport {cn} from '@shipfox/react-ui/utils';\nimport {\n defaultJobExecution,\n deriveJobDisplayStatus,\n deriveJobExecutionDisplayStatus,\n type Job,\n} from '#core/workflow-run.js';\nimport {formatJobDurationAccessibleLabel} from '../job-graph/job-duration-format.js';\nimport {JobDurationLabel} from '../job-graph/job-duration-label.js';\nimport {JobCard} from '../workflow-run-view/job-card.js';\nimport {WorkflowStatusIcon} from '../workflow-status/workflow-status-icon.js';\n\nexport interface RunJobsListProps {\n jobs: Job[];\n selectedJobId?: string | undefined;\n onSelectedJobChange: (jobId: string | undefined) => void;\n workspaceSlug?: string | undefined;\n selectedJobExecution: ReturnType<typeof defaultJobExecution>;\n selectedAttemptId: string | null | undefined;\n onSelectedJobExecutionChange: ((jobExecutionId: string | undefined) => void) | undefined;\n onSelectedAttemptChange: ((attemptId: string | undefined) => void) | undefined;\n sourcePanelId?: string | undefined;\n sourceAvailable?: boolean | undefined;\n focusedSourceStepId?: string | null | undefined;\n onOpenStepSource?: Parameters<typeof JobCard>[0]['onOpenStepSource'];\n}\n\nexport function RunJobsList({\n jobs,\n selectedJobId,\n onSelectedJobChange,\n workspaceSlug,\n selectedJobExecution,\n selectedAttemptId,\n onSelectedJobExecutionChange,\n onSelectedAttemptChange,\n sourcePanelId,\n sourceAvailable,\n focusedSourceStepId,\n onOpenStepSource,\n}: RunJobsListProps) {\n useTimeTick();\n\n if (jobs.length === 0) {\n return (\n <section\n aria-label=\"Workflow jobs\"\n className=\"rounded-8 border border-border-neutral-base bg-background-components-base\"\n >\n <div className=\"min-h-160\">\n <RunJobsEmptyState />\n </div>\n </section>\n );\n }\n\n const orderedJobs = [...jobs].sort(compareJobs);\n\n return (\n <section aria-label=\"Workflow jobs\" className=\"flex min-w-0 flex-col gap-8\">\n <ul aria-label=\"Run jobs\" className=\"m-0 flex min-w-0 list-none flex-col gap-8 p-0\">\n {orderedJobs.map((job) => {\n const selected = job.id === selectedJobId;\n const status = deriveJobDisplayStatus(job);\n const execution = defaultJobExecution(job);\n const durationLabel = formatJobDurationAccessibleLabel(\n job.displayDuration,\n execution ? deriveJobExecutionDisplayStatus(execution) : undefined,\n );\n const rowLabel = [\n job.displayName,\n statusLabel(status),\n durationLabel,\n job.carriedOver ? 'reused' : undefined,\n ]\n .filter((part): part is string => Boolean(part))\n .join(', ');\n\n return (\n <li key={job.id} className=\"min-w-0\">\n <button\n type=\"button\"\n aria-expanded={selected}\n aria-controls={selected ? `job-card-${job.id}` : undefined}\n aria-label={rowLabel}\n onClick={() => onSelectedJobChange(selected ? undefined : job.id)}\n className={cn(\n 'relative flex min-h-44 w-full min-w-0 items-center gap-8 rounded-8 bg-background-neutral-base px-12 text-left shadow-button-neutral outline-none transition-colors hover:bg-background-components-hover focus-visible:shadow-button-neutral-focus',\n selected &&\n 'bg-background-components-hover hover:bg-background-components-pressed',\n )}\n >\n {selected ? (\n <span\n aria-hidden=\"true\"\n className=\"absolute inset-y-6 left-0 w-px rounded-full bg-border-highlights-interactive\"\n />\n ) : null}\n <WorkflowStatusIcon status={status} size={14} tooltip={false} />\n <span className=\"min-w-0 flex-1 truncate text-sm font-medium text-foreground-neutral-base\">\n {job.displayName}\n </span>\n <JobDurationLabel duration={job.displayDuration} />\n </button>\n {selected ? (\n <div id={`job-card-${job.id}`} className=\"mt-8\">\n <JobCard\n workspaceSlug={workspaceSlug}\n job={job}\n selectedJobExecution={selectedJobExecution}\n selectedAttemptId={job.carriedOver ? undefined : selectedAttemptId}\n onSelectedJobExecutionChange={onSelectedJobExecutionChange}\n onSelectedAttemptChange={onSelectedAttemptChange}\n sourcePanelId={sourcePanelId}\n sourceAvailable={sourceAvailable}\n focusedSourceStepId={focusedSourceStepId}\n onOpenStepSource={onOpenStepSource}\n />\n </div>\n ) : null}\n </li>\n );\n })}\n </ul>\n </section>\n );\n}\n\nfunction RunJobsEmptyState() {\n return (\n <EmptyState\n icon=\"componentLine\"\n title=\"No jobs yet\"\n description=\"This run has not materialized jobs.\"\n />\n );\n}\n\nfunction compareJobs(left: Job, right: Job): number {\n return (\n left.position - right.position ||\n left.displayName.localeCompare(right.displayName) ||\n left.id.localeCompare(right.id)\n );\n}\n\nfunction statusLabel(status: ReturnType<typeof deriveJobDisplayStatus>): string {\n return status === 'listening' ? 'Listening' : status.charAt(0).toUpperCase() + status.slice(1);\n}\n"],"names":["EmptyState","useTimeTick","cn","defaultJobExecution","deriveJobDisplayStatus","deriveJobExecutionDisplayStatus","formatJobDurationAccessibleLabel","JobDurationLabel","JobCard","WorkflowStatusIcon","RunJobsList","jobs","selectedJobId","onSelectedJobChange","workspaceSlug","selectedJobExecution","selectedAttemptId","onSelectedJobExecutionChange","onSelectedAttemptChange","sourcePanelId","sourceAvailable","focusedSourceStepId","onOpenStepSource","length","section","aria-label","className","div","RunJobsEmptyState","orderedJobs","sort","compareJobs","ul","map","job","selected","id","status","execution","durationLabel","displayDuration","undefined","rowLabel","displayName","statusLabel","carriedOver","filter","part","Boolean","join","li","button","type","aria-expanded","aria-controls","onClick","span","aria-hidden","size","tooltip","duration","icon","title","description","left","right","position","localeCompare","charAt","toUpperCase","slice"],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export declare function RunTabCount({ count, alertCount, alertLabel, }: {
2
+ count: number | undefined;
3
+ alertCount?: number | undefined;
4
+ alertLabel: string;
5
+ }): import("react").JSX.Element | null;
6
+ //# sourceMappingURL=run-tab-count.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-tab-count.d.ts","sourceRoot":"","sources":["../../../src/components/workflow-run-tabs/run-tab-count.tsx"],"names":[],"mappings":"AAEA,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,UAAc,EACd,UAAU,GACX,EAAE;IACD,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,UAAU,EAAE,MAAM,CAAC;CACpB,sCAiBA"}
@@ -0,0 +1,27 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Badge } from '@shipfox/react-ui/badge';
3
+ export function RunTabCount({ count, alertCount = 0, alertLabel }) {
4
+ if (count === undefined && alertCount <= 0) return null;
5
+ return /*#__PURE__*/ _jsxs(_Fragment, {
6
+ children: [
7
+ count === undefined ? null : /*#__PURE__*/ _jsx(Badge, {
8
+ size: "2xs",
9
+ variant: "neutral",
10
+ "aria-hidden": "true",
11
+ children: count
12
+ }),
13
+ alertCount > 0 ? /*#__PURE__*/ _jsxs(Badge, {
14
+ size: "2xs",
15
+ variant: "error",
16
+ "aria-hidden": "true",
17
+ children: [
18
+ alertCount,
19
+ " ",
20
+ alertLabel
21
+ ]
22
+ }) : null
23
+ ]
24
+ });
25
+ }
26
+
27
+ //# sourceMappingURL=run-tab-count.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/workflow-run-tabs/run-tab-count.tsx"],"sourcesContent":["import {Badge} from '@shipfox/react-ui/badge';\n\nexport function RunTabCount({\n count,\n alertCount = 0,\n alertLabel,\n}: {\n count: number | undefined;\n alertCount?: number | undefined;\n alertLabel: string;\n}) {\n if (count === undefined && alertCount <= 0) return null;\n\n return (\n <>\n {count === undefined ? null : (\n <Badge size=\"2xs\" variant=\"neutral\" aria-hidden=\"true\">\n {count}\n </Badge>\n )}\n {alertCount > 0 ? (\n <Badge size=\"2xs\" variant=\"error\" aria-hidden=\"true\">\n {alertCount} {alertLabel}\n </Badge>\n ) : null}\n </>\n );\n}\n"],"names":["Badge","RunTabCount","count","alertCount","alertLabel","undefined","size","variant","aria-hidden"],"mappings":";AAAA,SAAQA,KAAK,QAAO,0BAA0B;AAE9C,OAAO,SAASC,YAAY,EAC1BC,KAAK,EACLC,aAAa,CAAC,EACdC,UAAU,EAKX;IACC,IAAIF,UAAUG,aAAaF,cAAc,GAAG,OAAO;IAEnD,qBACE;;YACGD,UAAUG,YAAY,qBACrB,KAACL;gBAAMM,MAAK;gBAAMC,SAAQ;gBAAUC,eAAY;0BAC7CN;;YAGJC,aAAa,kBACZ,MAACH;gBAAMM,MAAK;gBAAMC,SAAQ;gBAAQC,eAAY;;oBAC3CL;oBAAW;oBAAEC;;iBAEd;;;AAGV"}
@@ -0,0 +1,8 @@
1
+ import type { RunAnnotationSummary } from '#core/workflow-run-tabs.js';
2
+ export interface RunTabStripProps {
3
+ jobCount?: number | undefined;
4
+ jobsFailed?: number | undefined;
5
+ annotationSummary?: RunAnnotationSummary | undefined;
6
+ }
7
+ export declare function RunTabStrip({ jobCount, jobsFailed, annotationSummary }: RunTabStripProps): import("react").JSX.Element;
8
+ //# sourceMappingURL=run-tab-strip.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-tab-strip.d.ts","sourceRoot":"","sources":["../../../src/components/workflow-run-tabs/run-tab-strip.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,oBAAoB,EAAC,MAAM,4BAA4B,CAAC;AAGrE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,iBAAiB,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAC;CACtD;AAED,wBAAgB,WAAW,CAAC,EAAC,QAAQ,EAAE,UAAc,EAAE,iBAAiB,EAAC,EAAE,gBAAgB,+BA6D1F"}
@@ -0,0 +1,82 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { TabsList, TabsTrigger } from '@shipfox/react-ui/tabs';
3
+ import { RunTabCount } from './run-tab-count.js';
4
+ export function RunTabStrip({ jobCount, jobsFailed = 0, annotationSummary }) {
5
+ const annotationCount = annotationSummary?.total;
6
+ const annotationErrors = annotationSummary?.error ?? 0;
7
+ return /*#__PURE__*/ _jsx("div", {
8
+ className: "min-w-0 overflow-x-auto border-b border-border-neutral-base bg-background-neutral-background [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
9
+ children: /*#__PURE__*/ _jsxs(TabsList, {
10
+ "aria-label": "Run sections",
11
+ className: "h-40 min-h-40 w-max min-w-full gap-16 px-16 [@media(pointer:coarse)]:h-44 [@media(pointer:coarse)]:min-h-44",
12
+ children: [
13
+ /*#__PURE__*/ _jsx(TabsTrigger, {
14
+ value: "summary",
15
+ className: "h-40 min-h-40 py-0 text-xs data-[state=inactive]:text-foreground-neutral-subtle data-[state=inactive]:hover:text-foreground-neutral-base [@media(pointer:coarse)]:h-44 [@media(pointer:coarse)]:min-h-44",
16
+ children: "Summary"
17
+ }),
18
+ /*#__PURE__*/ _jsxs(TabsTrigger, {
19
+ value: "jobs",
20
+ "aria-label": runTabAccessibleName({
21
+ label: 'Jobs',
22
+ total: jobCount,
23
+ totalSingular: 'job',
24
+ totalPlural: 'jobs',
25
+ alertCount: jobsFailed,
26
+ alertSingular: 'failed',
27
+ alertPlural: 'failed'
28
+ }),
29
+ className: "h-40 min-h-40 gap-6 py-0 text-xs data-[state=inactive]:text-foreground-neutral-subtle data-[state=inactive]:hover:text-foreground-neutral-base [@media(pointer:coarse)]:h-44 [@media(pointer:coarse)]:min-h-44",
30
+ children: [
31
+ /*#__PURE__*/ _jsx("span", {
32
+ children: "Jobs"
33
+ }),
34
+ /*#__PURE__*/ _jsx(RunTabCount, {
35
+ count: jobCount,
36
+ alertCount: jobsFailed,
37
+ alertLabel: "failed"
38
+ })
39
+ ]
40
+ }),
41
+ /*#__PURE__*/ _jsxs(TabsTrigger, {
42
+ value: "annotations",
43
+ "aria-label": runTabAccessibleName({
44
+ label: 'Annotations',
45
+ total: annotationCount,
46
+ totalSingular: 'annotation',
47
+ totalPlural: 'annotations',
48
+ alertCount: annotationErrors,
49
+ alertSingular: 'error',
50
+ alertPlural: 'errors'
51
+ }),
52
+ className: "h-40 min-h-40 gap-6 py-0 text-xs data-[state=inactive]:text-foreground-neutral-subtle data-[state=inactive]:hover:text-foreground-neutral-base [@media(pointer:coarse)]:h-44 [@media(pointer:coarse)]:min-h-44",
53
+ children: [
54
+ /*#__PURE__*/ _jsx("span", {
55
+ children: "Annotations"
56
+ }),
57
+ /*#__PURE__*/ _jsx(RunTabCount, {
58
+ count: annotationCount,
59
+ alertCount: annotationErrors,
60
+ alertLabel: annotationErrors === 1 ? 'error' : 'errors'
61
+ })
62
+ ]
63
+ }),
64
+ /*#__PURE__*/ _jsx(TabsTrigger, {
65
+ value: "source",
66
+ className: "h-40 min-h-40 py-0 text-xs data-[state=inactive]:text-foreground-neutral-subtle data-[state=inactive]:hover:text-foreground-neutral-base [@media(pointer:coarse)]:h-44 [@media(pointer:coarse)]:min-h-44",
67
+ children: "Source"
68
+ })
69
+ ]
70
+ })
71
+ });
72
+ }
73
+ function runTabAccessibleName({ label, total, totalSingular, totalPlural, alertCount, alertSingular, alertPlural }) {
74
+ const parts = [
75
+ label
76
+ ];
77
+ if (total !== undefined) parts.push(`${total} ${total === 1 ? totalSingular : totalPlural}`);
78
+ if (alertCount > 0) parts.push(`${alertCount} ${alertCount === 1 ? alertSingular : alertPlural}`);
79
+ return parts.join(', ');
80
+ }
81
+
82
+ //# sourceMappingURL=run-tab-strip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/workflow-run-tabs/run-tab-strip.tsx"],"sourcesContent":["import {TabsList, TabsTrigger} from '@shipfox/react-ui/tabs';\nimport type {RunAnnotationSummary} from '#core/workflow-run-tabs.js';\nimport {RunTabCount} from './run-tab-count.js';\n\nexport interface RunTabStripProps {\n jobCount?: number | undefined;\n jobsFailed?: number | undefined;\n annotationSummary?: RunAnnotationSummary | undefined;\n}\n\nexport function RunTabStrip({jobCount, jobsFailed = 0, annotationSummary}: RunTabStripProps) {\n const annotationCount = annotationSummary?.total;\n const annotationErrors = annotationSummary?.error ?? 0;\n\n return (\n <div className=\"min-w-0 overflow-x-auto border-b border-border-neutral-base bg-background-neutral-background [scrollbar-width:none] [&::-webkit-scrollbar]:hidden\">\n <TabsList\n aria-label=\"Run sections\"\n className=\"h-40 min-h-40 w-max min-w-full gap-16 px-16 [@media(pointer:coarse)]:h-44 [@media(pointer:coarse)]:min-h-44\"\n >\n <TabsTrigger\n value=\"summary\"\n className=\"h-40 min-h-40 py-0 text-xs data-[state=inactive]:text-foreground-neutral-subtle data-[state=inactive]:hover:text-foreground-neutral-base [@media(pointer:coarse)]:h-44 [@media(pointer:coarse)]:min-h-44\"\n >\n Summary\n </TabsTrigger>\n <TabsTrigger\n value=\"jobs\"\n aria-label={runTabAccessibleName({\n label: 'Jobs',\n total: jobCount,\n totalSingular: 'job',\n totalPlural: 'jobs',\n alertCount: jobsFailed,\n alertSingular: 'failed',\n alertPlural: 'failed',\n })}\n className=\"h-40 min-h-40 gap-6 py-0 text-xs data-[state=inactive]:text-foreground-neutral-subtle data-[state=inactive]:hover:text-foreground-neutral-base [@media(pointer:coarse)]:h-44 [@media(pointer:coarse)]:min-h-44\"\n >\n <span>Jobs</span>\n <RunTabCount count={jobCount} alertCount={jobsFailed} alertLabel=\"failed\" />\n </TabsTrigger>\n <TabsTrigger\n value=\"annotations\"\n aria-label={runTabAccessibleName({\n label: 'Annotations',\n total: annotationCount,\n totalSingular: 'annotation',\n totalPlural: 'annotations',\n alertCount: annotationErrors,\n alertSingular: 'error',\n alertPlural: 'errors',\n })}\n className=\"h-40 min-h-40 gap-6 py-0 text-xs data-[state=inactive]:text-foreground-neutral-subtle data-[state=inactive]:hover:text-foreground-neutral-base [@media(pointer:coarse)]:h-44 [@media(pointer:coarse)]:min-h-44\"\n >\n <span>Annotations</span>\n <RunTabCount\n count={annotationCount}\n alertCount={annotationErrors}\n alertLabel={annotationErrors === 1 ? 'error' : 'errors'}\n />\n </TabsTrigger>\n <TabsTrigger\n value=\"source\"\n className=\"h-40 min-h-40 py-0 text-xs data-[state=inactive]:text-foreground-neutral-subtle data-[state=inactive]:hover:text-foreground-neutral-base [@media(pointer:coarse)]:h-44 [@media(pointer:coarse)]:min-h-44\"\n >\n Source\n </TabsTrigger>\n </TabsList>\n </div>\n );\n}\n\nfunction runTabAccessibleName({\n label,\n total,\n totalSingular,\n totalPlural,\n alertCount,\n alertSingular,\n alertPlural,\n}: {\n label: string;\n total: number | undefined;\n totalSingular: string;\n totalPlural: string;\n alertCount: number;\n alertSingular: string;\n alertPlural: string;\n}): string {\n const parts = [label];\n\n if (total !== undefined) parts.push(`${total} ${total === 1 ? totalSingular : totalPlural}`);\n if (alertCount > 0) parts.push(`${alertCount} ${alertCount === 1 ? alertSingular : alertPlural}`);\n\n return parts.join(', ');\n}\n"],"names":["TabsList","TabsTrigger","RunTabCount","RunTabStrip","jobCount","jobsFailed","annotationSummary","annotationCount","total","annotationErrors","error","div","className","aria-label","value","runTabAccessibleName","label","totalSingular","totalPlural","alertCount","alertSingular","alertPlural","span","count","alertLabel","parts","undefined","push","join"],"mappings":";AAAA,SAAQA,QAAQ,EAAEC,WAAW,QAAO,yBAAyB;AAE7D,SAAQC,WAAW,QAAO,qBAAqB;AAQ/C,OAAO,SAASC,YAAY,EAACC,QAAQ,EAAEC,aAAa,CAAC,EAAEC,iBAAiB,EAAmB;IACzF,MAAMC,kBAAkBD,mBAAmBE;IAC3C,MAAMC,mBAAmBH,mBAAmBI,SAAS;IAErD,qBACE,KAACC;QAAIC,WAAU;kBACb,cAAA,MAACZ;YACCa,cAAW;YACXD,WAAU;;8BAEV,KAACX;oBACCa,OAAM;oBACNF,WAAU;8BACX;;8BAGD,MAACX;oBACCa,OAAM;oBACND,cAAYE,qBAAqB;wBAC/BC,OAAO;wBACPR,OAAOJ;wBACPa,eAAe;wBACfC,aAAa;wBACbC,YAAYd;wBACZe,eAAe;wBACfC,aAAa;oBACf;oBACAT,WAAU;;sCAEV,KAACU;sCAAK;;sCACN,KAACpB;4BAAYqB,OAAOnB;4BAAUe,YAAYd;4BAAYmB,YAAW;;;;8BAEnE,MAACvB;oBACCa,OAAM;oBACND,cAAYE,qBAAqB;wBAC/BC,OAAO;wBACPR,OAAOD;wBACPU,eAAe;wBACfC,aAAa;wBACbC,YAAYV;wBACZW,eAAe;wBACfC,aAAa;oBACf;oBACAT,WAAU;;sCAEV,KAACU;sCAAK;;sCACN,KAACpB;4BACCqB,OAAOhB;4BACPY,YAAYV;4BACZe,YAAYf,qBAAqB,IAAI,UAAU;;;;8BAGnD,KAACR;oBACCa,OAAM;oBACNF,WAAU;8BACX;;;;;AAMT;AAEA,SAASG,qBAAqB,EAC5BC,KAAK,EACLR,KAAK,EACLS,aAAa,EACbC,WAAW,EACXC,UAAU,EACVC,aAAa,EACbC,WAAW,EASZ;IACC,MAAMI,QAAQ;QAACT;KAAM;IAErB,IAAIR,UAAUkB,WAAWD,MAAME,IAAI,CAAC,GAAGnB,MAAM,CAAC,EAAEA,UAAU,IAAIS,gBAAgBC,aAAa;IAC3F,IAAIC,aAAa,GAAGM,MAAME,IAAI,CAAC,GAAGR,WAAW,CAAC,EAAEA,eAAe,IAAIC,gBAAgBC,aAAa;IAEhG,OAAOI,MAAMG,IAAI,CAAC;AACpB"}
@@ -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,EAEjB,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,CAyB/B"}
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,EAEjB,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"}
@@ -5,6 +5,8 @@ export function resolveWorkflowRunSelection({ run, selection }) {
5
5
  job
6
6
  ]));
7
7
  const stepMatch = findStep(run, selection.stepId);
8
+ const jobExecutionMatch = findJobExecution(run, selection.jobExecutionId);
9
+ const stepAttemptMatch = findStepAttempt(run, selection.stepAttemptId);
8
10
  if (stepMatch) {
9
11
  const attempt = resolveStepAttempt(stepMatch.step, selection.stepAttemptId);
10
12
  return {
@@ -15,7 +17,16 @@ export function resolveWorkflowRunSelection({ run, selection }) {
15
17
  selectedAttemptId: attempt?.id ?? null
16
18
  };
17
19
  }
18
- const job = (selection.jobId ? jobById.get(selection.jobId) : undefined) ?? run.jobs.at(0);
20
+ if (stepAttemptMatch) {
21
+ return {
22
+ job: stepAttemptMatch.job,
23
+ jobExecution: stepAttemptMatch.jobExecution,
24
+ step: stepAttemptMatch.step,
25
+ attempt: stepAttemptMatch.attempt,
26
+ selectedAttemptId: stepAttemptMatch.attempt.id
27
+ };
28
+ }
29
+ const job = (selection.jobId ? jobById.get(selection.jobId) : undefined) ?? jobExecutionMatch?.job ?? run.jobs.at(0);
19
30
  const jobExecution = job ? resolveJobExecution(job, selection.jobExecutionId) : undefined;
20
31
  return {
21
32
  job,
@@ -25,6 +36,34 @@ export function resolveWorkflowRunSelection({ run, selection }) {
25
36
  selectedAttemptId: null
26
37
  };
27
38
  }
39
+ function findJobExecution(run, jobExecutionId) {
40
+ if (!jobExecutionId) return undefined;
41
+ for (const job of run.jobs){
42
+ const jobExecution = job.jobExecutions.find((candidate)=>candidate.id === jobExecutionId);
43
+ if (jobExecution) return {
44
+ job,
45
+ jobExecution
46
+ };
47
+ }
48
+ return undefined;
49
+ }
50
+ function findStepAttempt(run, stepAttemptId) {
51
+ if (!stepAttemptId) return undefined;
52
+ for (const job of run.jobs){
53
+ for (const jobExecution of job.jobExecutions){
54
+ for (const step of jobExecution.steps){
55
+ const attempt = step.attempts.find((candidate)=>candidate.id === stepAttemptId);
56
+ if (attempt) return {
57
+ job,
58
+ jobExecution,
59
+ step,
60
+ attempt
61
+ };
62
+ }
63
+ }
64
+ }
65
+ return undefined;
66
+ }
28
67
  function findStep(run, stepId) {
29
68
  if (!stepId) return undefined;
30
69
  for (const job of run.jobs){
@@ -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\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 const job = (selection.jobId ? jobById.get(selection.jobId) : undefined) ?? 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 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\nfunction resolveStepAttempt(step: Step, attemptId: string | undefined): StepAttempt | undefined {\n const attemptById = attemptId\n ? step.attempts.find((attempt) => attempt.id === attemptId)\n : undefined;\n if (attemptById) return attemptById;\n\n const currentAttempt = step.attempts.find((attempt) => attempt.attempt === step.currentAttempt);\n if (currentAttempt) return currentAttempt;\n\n return step.attempts.reduce<StepAttempt | undefined>((latest, attempt) => {\n if (!latest) return attempt;\n return compareAttempts(attempt, latest) > 0 ? attempt : latest;\n }, undefined);\n}\n\nfunction compareAttempts(left: StepAttempt, right: StepAttempt): number {\n return (\n left.attempt - right.attempt ||\n left.executionOrder - right.executionOrder ||\n left.id.localeCompare(right.id)\n );\n}\n"],"names":["resolveJobExecution","resolveWorkflowRunSelection","run","selection","jobById","Map","jobs","map","job","id","stepMatch","findStep","stepId","attempt","resolveStepAttempt","step","stepAttemptId","jobExecution","selectedAttemptId","jobId","get","undefined","at","jobExecutionId","jobExecutions","steps","find","candidate","attemptId","attemptById","attempts","currentAttempt","reduce","latest","compareAttempts","left","right","executionOrder","localeCompare"],"mappings":"AAAA,SAGEA,mBAAmB,QAId,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;IAEhD,IAAIF,WAAW;QACb,MAAMG,UAAUC,mBAAmBJ,UAAUK,IAAI,EAAEZ,UAAUa,aAAa;QAC1E,OAAO;YACLR,KAAKE,UAAUF,GAAG;YAClBS,cAAcP,UAAUO,YAAY;YACpCF,MAAML,UAAUK,IAAI;YACpBF;YACAK,mBAAmBL,SAASJ,MAAM;QACpC;IACF;IAEA,MAAMD,MAAM,AAACL,CAAAA,UAAUgB,KAAK,GAAGf,QAAQgB,GAAG,CAACjB,UAAUgB,KAAK,IAAIE,SAAQ,KAAMnB,IAAII,IAAI,CAACgB,EAAE,CAAC;IACxF,MAAML,eAAeT,MAAMR,oBAAoBQ,KAAKL,UAAUoB,cAAc,IAAIF;IAEhF,OAAO;QACLb;QACAS;QACAF,MAAMM;QACNR,SAASQ;QACTH,mBAAmB;IACrB;AACF;AAEA,SAASP,SACPT,GAAsB,EACtBU,MAA0B;IAE1B,IAAI,CAACA,QAAQ,OAAOS;IAEpB,KAAK,MAAMb,OAAON,IAAII,IAAI,CAAE;QAC1B,KAAK,MAAMW,gBAAgBT,IAAIgB,aAAa,CAAE;YAC5C,MAAMT,OAAOE,aAAaQ,KAAK,CAACC,IAAI,CAAC,CAACC,YAAcA,UAAUlB,EAAE,KAAKG;YACrE,IAAIG,MAAM,OAAO;gBAACP;gBAAKS;gBAAcF;YAAI;QAC3C;IACF;IAEA,OAAOM;AACT;AAEA,SAASP,mBAAmBC,IAAU,EAAEa,SAA6B;IACnE,MAAMC,cAAcD,YAChBb,KAAKe,QAAQ,CAACJ,IAAI,CAAC,CAACb,UAAYA,QAAQJ,EAAE,KAAKmB,aAC/CP;IACJ,IAAIQ,aAAa,OAAOA;IAExB,MAAME,iBAAiBhB,KAAKe,QAAQ,CAACJ,IAAI,CAAC,CAACb,UAAYA,QAAQA,OAAO,KAAKE,KAAKgB,cAAc;IAC9F,IAAIA,gBAAgB,OAAOA;IAE3B,OAAOhB,KAAKe,QAAQ,CAACE,MAAM,CAA0B,CAACC,QAAQpB;QAC5D,IAAI,CAACoB,QAAQ,OAAOpB;QACpB,OAAOqB,gBAAgBrB,SAASoB,UAAU,IAAIpB,UAAUoB;IAC1D,GAAGZ;AACL;AAEA,SAASa,gBAAgBC,IAAiB,EAAEC,KAAkB;IAC5D,OACED,KAAKtB,OAAO,GAAGuB,MAAMvB,OAAO,IAC5BsB,KAAKE,cAAc,GAAGD,MAAMC,cAAc,IAC1CF,KAAK1B,EAAE,CAAC6B,aAAa,CAACF,MAAM3B,EAAE;AAElC"}
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\nfunction resolveStepAttempt(step: Step, attemptId: string | undefined): StepAttempt | undefined {\n const attemptById = attemptId\n ? step.attempts.find((attempt) => attempt.id === attemptId)\n : undefined;\n if (attemptById) return attemptById;\n\n const currentAttempt = step.attempts.find((attempt) => attempt.attempt === step.currentAttempt);\n if (currentAttempt) return currentAttempt;\n\n return step.attempts.reduce<StepAttempt | undefined>((latest, attempt) => {\n if (!latest) return attempt;\n return compareAttempts(attempt, latest) > 0 ? attempt : latest;\n }, undefined);\n}\n\nfunction compareAttempts(left: StepAttempt, right: StepAttempt): number {\n return (\n left.attempt - right.attempt ||\n left.executionOrder - right.executionOrder ||\n left.id.localeCompare(right.id)\n );\n}\n"],"names":["resolveJobExecution","resolveWorkflowRunSelection","run","selection","jobById","Map","jobs","map","job","id","stepMatch","findStep","stepId","jobExecutionMatch","findJobExecution","jobExecutionId","stepAttemptMatch","findStepAttempt","stepAttemptId","attempt","resolveStepAttempt","step","jobExecution","selectedAttemptId","jobId","get","undefined","at","jobExecutions","find","candidate","steps","attempts","attemptId","attemptById","currentAttempt","reduce","latest","compareAttempts","left","right","executionOrder","localeCompare"],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import type { QueryLoadErrorQuery } from '@shipfox/client-ui';
2
2
  export declare function WorkflowRunSkeleton(): import("react").JSX.Element;
3
+ export declare function WorkflowRunContentSkeleton(): import("react").JSX.Element;
3
4
  export declare function WorkflowRunNotFound(): import("react").JSX.Element;
4
5
  /**
5
6
  * Slim non-blocking banner shown when a background refetch fails after the run already
@@ -1 +1 @@
1
- {"version":3,"file":"workflow-run-states.d.ts","sourceRoot":"","sources":["../../../src/components/workflow-run-view/workflow-run-states.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,oBAAoB,CAAC;AAO5D,wBAAgB,mBAAmB,gCAwBlC;AAED,wBAAgB,mBAAmB,gCAQlC;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,EAAC,KAAK,EAAC,EAAE;IAAC,KAAK,EAAE,mBAAmB,CAAA;CAAC,+BAqB1E"}
1
+ {"version":3,"file":"workflow-run-states.d.ts","sourceRoot":"","sources":["../../../src/components/workflow-run-view/workflow-run-states.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,oBAAoB,CAAC;AAO5D,wBAAgB,mBAAmB,gCAwBlC;AAED,wBAAgB,0BAA0B,gCASzC;AAED,wBAAgB,mBAAmB,gCAQlC;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,EAAC,KAAK,EAAC,EAAE;IAAC,KAAK,EAAE,mBAAmB,CAAA;CAAC,+BAqB1E"}
@@ -7,7 +7,7 @@ import { Text } from '@shipfox/react-ui/typography';
7
7
  export function WorkflowRunSkeleton() {
8
8
  return /*#__PURE__*/ _jsx("section", {
9
9
  "aria-label": "Loading workflow run",
10
- className: "border-b border-border-neutral-base bg-background-subtle-base px-16 py-12",
10
+ className: "bg-background-neutral-background px-16 py-12",
11
11
  children: /*#__PURE__*/ _jsxs("div", {
12
12
  className: "flex min-w-0 flex-wrap items-center gap-x-12 gap-y-8",
13
13
  children: [
@@ -48,6 +48,15 @@ export function WorkflowRunSkeleton() {
48
48
  })
49
49
  });
50
50
  }
51
+ export function WorkflowRunContentSkeleton() {
52
+ return /*#__PURE__*/ _jsx("section", {
53
+ "aria-label": "Loading workflow run content",
54
+ className: "min-h-160 rounded-8 border border-border-neutral-base bg-background-components-base p-16",
55
+ children: /*#__PURE__*/ _jsx(Skeleton, {
56
+ className: "h-160 w-full rounded-6"
57
+ })
58
+ });
59
+ }
51
60
  export function WorkflowRunNotFound() {
52
61
  return /*#__PURE__*/ _jsx(EmptyState, {
53
62
  icon: "pulseLine",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/workflow-run-view/workflow-run-states.tsx"],"sourcesContent":["import type {QueryLoadErrorQuery} from '@shipfox/client-ui';\nimport {Button} from '@shipfox/react-ui/button';\nimport {Callout} from '@shipfox/react-ui/callout';\nimport {EmptyState} from '@shipfox/react-ui/empty-state';\nimport {Skeleton} from '@shipfox/react-ui/skeleton';\nimport {Text} from '@shipfox/react-ui/typography';\n\nexport function WorkflowRunSkeleton() {\n return (\n <section\n aria-label=\"Loading workflow run\"\n className=\"border-b border-border-neutral-base bg-background-subtle-base px-16 py-12\"\n >\n <div className=\"flex min-w-0 flex-wrap items-center gap-x-12 gap-y-8\">\n <div className=\"flex min-w-0 items-center gap-8\">\n <Skeleton className=\"size-8 rounded-full\" />\n <Skeleton className=\"h-24 w-180 rounded-6\" />\n </div>\n <Skeleton className=\"h-24 w-88 rounded-6\" />\n <span\n aria-hidden=\"true\"\n className=\"hidden h-20 w-px shrink-0 bg-border-neutral-base sm:block\"\n />\n <Skeleton className=\"h-20 w-64 rounded-4\" />\n <Skeleton className=\"h-20 w-112 rounded-4\" />\n <span className=\"min-w-0 flex-1\" />\n <Skeleton className=\"h-20 w-88 rounded-4\" />\n <Skeleton className=\"h-20 w-88 rounded-4\" />\n </div>\n </section>\n );\n}\n\nexport function WorkflowRunNotFound() {\n return (\n <EmptyState\n icon=\"pulseLine\"\n title=\"Run not found\"\n description=\"This run does not exist or is no longer available.\"\n />\n );\n}\n\n/**\n * Slim non-blocking banner shown when a background refetch fails after the run already\n * loaded (active-run polling can hit a transient API error), so the loaded run stays on\n * screen with an inline retry instead of being wiped by a full error placeholder.\n */\nexport function WorkflowRunStaleError({query}: {query: QueryLoadErrorQuery}) {\n return (\n <div className=\"border-b border-border-neutral-base p-8\">\n <Callout role=\"alert\" type=\"error\">\n <div className=\"flex items-center justify-between gap-8\">\n <Text size=\"xs\">Could not refresh this run.</Text>\n <Button\n type=\"button\"\n size=\"2xs\"\n variant=\"secondary\"\n isLoading={query.isFetching}\n onClick={() => {\n void query.refetch();\n }}\n >\n Retry\n </Button>\n </div>\n </Callout>\n </div>\n );\n}\n"],"names":["Button","Callout","EmptyState","Skeleton","Text","WorkflowRunSkeleton","section","aria-label","className","div","span","aria-hidden","WorkflowRunNotFound","icon","title","description","WorkflowRunStaleError","query","role","type","size","variant","isLoading","isFetching","onClick","refetch"],"mappings":";AACA,SAAQA,MAAM,QAAO,2BAA2B;AAChD,SAAQC,OAAO,QAAO,4BAA4B;AAClD,SAAQC,UAAU,QAAO,gCAAgC;AACzD,SAAQC,QAAQ,QAAO,6BAA6B;AACpD,SAAQC,IAAI,QAAO,+BAA+B;AAElD,OAAO,SAASC;IACd,qBACE,KAACC;QACCC,cAAW;QACXC,WAAU;kBAEV,cAAA,MAACC;YAAID,WAAU;;8BACb,MAACC;oBAAID,WAAU;;sCACb,KAACL;4BAASK,WAAU;;sCACpB,KAACL;4BAASK,WAAU;;;;8BAEtB,KAACL;oBAASK,WAAU;;8BACpB,KAACE;oBACCC,eAAY;oBACZH,WAAU;;8BAEZ,KAACL;oBAASK,WAAU;;8BACpB,KAACL;oBAASK,WAAU;;8BACpB,KAACE;oBAAKF,WAAU;;8BAChB,KAACL;oBAASK,WAAU;;8BACpB,KAACL;oBAASK,WAAU;;;;;AAI5B;AAEA,OAAO,SAASI;IACd,qBACE,KAACV;QACCW,MAAK;QACLC,OAAM;QACNC,aAAY;;AAGlB;AAEA;;;;CAIC,GACD,OAAO,SAASC,sBAAsB,EAACC,KAAK,EAA+B;IACzE,qBACE,KAACR;QAAID,WAAU;kBACb,cAAA,KAACP;YAAQiB,MAAK;YAAQC,MAAK;sBACzB,cAAA,MAACV;gBAAID,WAAU;;kCACb,KAACJ;wBAAKgB,MAAK;kCAAK;;kCAChB,KAACpB;wBACCmB,MAAK;wBACLC,MAAK;wBACLC,SAAQ;wBACRC,WAAWL,MAAMM,UAAU;wBAC3BC,SAAS;4BACP,KAAKP,MAAMQ,OAAO;wBACpB;kCACD;;;;;;AAOX"}
1
+ {"version":3,"sources":["../../../src/components/workflow-run-view/workflow-run-states.tsx"],"sourcesContent":["import type {QueryLoadErrorQuery} from '@shipfox/client-ui';\nimport {Button} from '@shipfox/react-ui/button';\nimport {Callout} from '@shipfox/react-ui/callout';\nimport {EmptyState} from '@shipfox/react-ui/empty-state';\nimport {Skeleton} from '@shipfox/react-ui/skeleton';\nimport {Text} from '@shipfox/react-ui/typography';\n\nexport function WorkflowRunSkeleton() {\n return (\n <section\n aria-label=\"Loading workflow run\"\n className=\"bg-background-neutral-background px-16 py-12\"\n >\n <div className=\"flex min-w-0 flex-wrap items-center gap-x-12 gap-y-8\">\n <div className=\"flex min-w-0 items-center gap-8\">\n <Skeleton className=\"size-8 rounded-full\" />\n <Skeleton className=\"h-24 w-180 rounded-6\" />\n </div>\n <Skeleton className=\"h-24 w-88 rounded-6\" />\n <span\n aria-hidden=\"true\"\n className=\"hidden h-20 w-px shrink-0 bg-border-neutral-base sm:block\"\n />\n <Skeleton className=\"h-20 w-64 rounded-4\" />\n <Skeleton className=\"h-20 w-112 rounded-4\" />\n <span className=\"min-w-0 flex-1\" />\n <Skeleton className=\"h-20 w-88 rounded-4\" />\n <Skeleton className=\"h-20 w-88 rounded-4\" />\n </div>\n </section>\n );\n}\n\nexport function WorkflowRunContentSkeleton() {\n return (\n <section\n aria-label=\"Loading workflow run content\"\n className=\"min-h-160 rounded-8 border border-border-neutral-base bg-background-components-base p-16\"\n >\n <Skeleton className=\"h-160 w-full rounded-6\" />\n </section>\n );\n}\n\nexport function WorkflowRunNotFound() {\n return (\n <EmptyState\n icon=\"pulseLine\"\n title=\"Run not found\"\n description=\"This run does not exist or is no longer available.\"\n />\n );\n}\n\n/**\n * Slim non-blocking banner shown when a background refetch fails after the run already\n * loaded (active-run polling can hit a transient API error), so the loaded run stays on\n * screen with an inline retry instead of being wiped by a full error placeholder.\n */\nexport function WorkflowRunStaleError({query}: {query: QueryLoadErrorQuery}) {\n return (\n <div className=\"border-b border-border-neutral-base p-8\">\n <Callout role=\"alert\" type=\"error\">\n <div className=\"flex items-center justify-between gap-8\">\n <Text size=\"xs\">Could not refresh this run.</Text>\n <Button\n type=\"button\"\n size=\"2xs\"\n variant=\"secondary\"\n isLoading={query.isFetching}\n onClick={() => {\n void query.refetch();\n }}\n >\n Retry\n </Button>\n </div>\n </Callout>\n </div>\n );\n}\n"],"names":["Button","Callout","EmptyState","Skeleton","Text","WorkflowRunSkeleton","section","aria-label","className","div","span","aria-hidden","WorkflowRunContentSkeleton","WorkflowRunNotFound","icon","title","description","WorkflowRunStaleError","query","role","type","size","variant","isLoading","isFetching","onClick","refetch"],"mappings":";AACA,SAAQA,MAAM,QAAO,2BAA2B;AAChD,SAAQC,OAAO,QAAO,4BAA4B;AAClD,SAAQC,UAAU,QAAO,gCAAgC;AACzD,SAAQC,QAAQ,QAAO,6BAA6B;AACpD,SAAQC,IAAI,QAAO,+BAA+B;AAElD,OAAO,SAASC;IACd,qBACE,KAACC;QACCC,cAAW;QACXC,WAAU;kBAEV,cAAA,MAACC;YAAID,WAAU;;8BACb,MAACC;oBAAID,WAAU;;sCACb,KAACL;4BAASK,WAAU;;sCACpB,KAACL;4BAASK,WAAU;;;;8BAEtB,KAACL;oBAASK,WAAU;;8BACpB,KAACE;oBACCC,eAAY;oBACZH,WAAU;;8BAEZ,KAACL;oBAASK,WAAU;;8BACpB,KAACL;oBAASK,WAAU;;8BACpB,KAACE;oBAAKF,WAAU;;8BAChB,KAACL;oBAASK,WAAU;;8BACpB,KAACL;oBAASK,WAAU;;;;;AAI5B;AAEA,OAAO,SAASI;IACd,qBACE,KAACN;QACCC,cAAW;QACXC,WAAU;kBAEV,cAAA,KAACL;YAASK,WAAU;;;AAG1B;AAEA,OAAO,SAASK;IACd,qBACE,KAACX;QACCY,MAAK;QACLC,OAAM;QACNC,aAAY;;AAGlB;AAEA;;;;CAIC,GACD,OAAO,SAASC,sBAAsB,EAACC,KAAK,EAA+B;IACzE,qBACE,KAACT;QAAID,WAAU;kBACb,cAAA,KAACP;YAAQkB,MAAK;YAAQC,MAAK;sBACzB,cAAA,MAACX;gBAAID,WAAU;;kCACb,KAACJ;wBAAKiB,MAAK;kCAAK;;kCAChB,KAACrB;wBACCoB,MAAK;wBACLC,MAAK;wBACLC,SAAQ;wBACRC,WAAWL,MAAMM,UAAU;wBAC3BC,SAAS;4BACP,KAAKP,MAAMQ,OAAO;wBACpB;kCACD;;;;;;AAOX"}
@@ -1,4 +1,6 @@
1
+ import type { RunAnnotationSummary } from '#core/workflow-run-tabs.js';
1
2
  import { type WorkflowRunSelectionInput } from '#core/workflow-run-url-state.js';
3
+ import { type WorkflowRunTab } from '#routes/inputs.js';
2
4
  export interface WorkflowRunViewProps {
3
5
  projectId: string;
4
6
  workspaceSlug?: string | undefined;
@@ -6,11 +8,13 @@ export interface WorkflowRunViewProps {
6
8
  workflowRunId?: string | undefined;
7
9
  selection?: WorkflowRunSelectionInput | undefined;
8
10
  onSelectionChange?: ((selection: WorkflowRunSelectionInput) => void) | undefined;
11
+ tab?: WorkflowRunTab | undefined;
12
+ onTabChange?: ((tab: WorkflowRunTab) => void) | undefined;
13
+ annotationSummary?: RunAnnotationSummary | undefined;
9
14
  }
10
15
  /**
11
- * Renders the run for `workflowRunId`, or a skeleton while `workflowRunId` is still unknown (the page is
12
- * resolving which run to show) or the run is loading, so the page never branches on the
13
- * loading state itself.
16
+ * Renders the run for `workflowRunId`, keeping the local tab strip mounted while the run
17
+ * request is pending so polling never inserts navigation under the user's cursor.
14
18
  */
15
- export declare function WorkflowRunView({ projectId, workspaceSlug, projectSlug, workflowRunId, selection, onSelectionChange, }: WorkflowRunViewProps): import("react").JSX.Element;
19
+ export declare function WorkflowRunView({ projectId, workspaceSlug, projectSlug, workflowRunId, selection, onSelectionChange, tab, onTabChange, annotationSummary, }: WorkflowRunViewProps): import("react").JSX.Element;
16
20
  //# 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":"AAYA,OAAO,EACL,KAAK,yBAAyB,EAE/B,MAAM,iCAAiC,CAAC;AAsBzC,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,SAAS,CAAC,EAAE,yBAAyB,GAAG,SAAS,CAAC;IAClD,iBAAiB,CAAC,EAAE,CAAC,CAAC,SAAS,EAAE,yBAAyB,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CAClF;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,EAC9B,SAAS,EACT,aAAa,EACb,WAAW,EACX,aAAa,EACb,SAAS,EACT,iBAAiB,GAClB,EAAE,oBAAoB,+BAkBtB"}
1
+ {"version":3,"file":"workflow-run-view.d.ts","sourceRoot":"","sources":["../../../src/components/workflow-run-view/workflow-run-view.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAC,oBAAoB,EAAC,MAAM,4BAA4B,CAAC;AACrE,OAAO,EACL,KAAK,yBAAyB,EAE/B,MAAM,iCAAiC,CAAC;AAMzC,OAAO,EAAoB,KAAK,cAAc,EAAC,MAAM,mBAAmB,CAAC;AAwBzE,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,SAAS,CAAC,EAAE,yBAAyB,GAAG,SAAS,CAAC;IAClD,iBAAiB,CAAC,EAAE,CAAC,CAAC,SAAS,EAAE,yBAAyB,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IACjF,GAAG,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IACjC,WAAW,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,cAAc,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC1D,iBAAiB,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAC;CACtD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,EAC9B,SAAS,EACT,aAAa,EACb,WAAW,EACX,aAAa,EACb,SAAS,EACT,iBAAiB,EACjB,GAAG,EACH,WAAW,EACX,iBAAiB,GAClB,EAAE,oBAAoB,+BAqBtB"}