@shipfox/client-workflows 14.0.1 → 16.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 (272) hide show
  1. package/.storybook/preview.css +4 -0
  2. package/.storybook/preview.tsx +7 -2
  3. package/.turbo/turbo-build.log +1 -1
  4. package/CHANGELOG.md +42 -0
  5. package/dist/components/job-detail/agent-config-failure-callout.d.ts.map +1 -0
  6. package/dist/components/{workflow-run-view → job-detail}/agent-config-failure-callout.js +2 -2
  7. package/dist/components/job-detail/agent-config-failure-callout.js.map +1 -0
  8. package/dist/components/job-detail/job-detail-header.d.ts +15 -0
  9. package/dist/components/job-detail/job-detail-header.d.ts.map +1 -0
  10. package/dist/components/job-detail/job-detail-header.js +124 -0
  11. package/dist/components/job-detail/job-detail-header.js.map +1 -0
  12. package/dist/components/job-detail/job-detail-view.d.ts +16 -0
  13. package/dist/components/job-detail/job-detail-view.d.ts.map +1 -0
  14. package/dist/components/job-detail/job-detail-view.js +420 -0
  15. package/dist/components/job-detail/job-detail-view.js.map +1 -0
  16. package/dist/components/job-detail/job-empty-states.d.ts +10 -0
  17. package/dist/components/job-detail/job-empty-states.d.ts.map +1 -0
  18. package/dist/components/job-detail/job-empty-states.js +195 -0
  19. package/dist/components/job-detail/job-empty-states.js.map +1 -0
  20. package/dist/components/job-detail/job-execution-switcher.d.ts.map +1 -0
  21. package/dist/components/job-detail/job-execution-switcher.js.map +1 -0
  22. package/dist/components/job-detail/job-execution-time-text.d.ts.map +1 -0
  23. package/dist/components/job-detail/job-execution-time-text.js.map +1 -0
  24. package/dist/components/job-detail/job-selection.d.ts +24 -0
  25. package/dist/components/job-detail/job-selection.d.ts.map +1 -0
  26. package/dist/components/job-detail/job-selection.js +66 -0
  27. package/dist/components/job-detail/job-selection.js.map +1 -0
  28. package/dist/components/job-detail/step-attempt-log-panel.d.ts +15 -0
  29. package/dist/components/job-detail/step-attempt-log-panel.d.ts.map +1 -0
  30. package/dist/components/{workflow-run-view → job-detail}/step-attempt-log-panel.js +61 -16
  31. package/dist/components/job-detail/step-attempt-log-panel.js.map +1 -0
  32. package/dist/components/job-graph/job-graph-content.js +1 -1
  33. package/dist/components/job-graph/job-graph-content.js.map +1 -1
  34. package/dist/components/step-list/step-list-model.js +2 -2
  35. package/dist/components/step-list/step-list-model.js.map +1 -1
  36. package/dist/components/step-list/step-list.d.ts +1 -0
  37. package/dist/components/step-list/step-list.d.ts.map +1 -1
  38. package/dist/components/step-list/step-list.js +29 -4
  39. package/dist/components/step-list/step-list.js.map +1 -1
  40. package/dist/components/workflow-run-duration-label.d.ts +9 -4
  41. package/dist/components/workflow-run-duration-label.d.ts.map +1 -1
  42. package/dist/components/workflow-run-duration-label.js +27 -7
  43. package/dist/components/workflow-run-duration-label.js.map +1 -1
  44. package/dist/components/workflow-run-list/workflow-run-row.d.ts.map +1 -1
  45. package/dist/components/workflow-run-list/workflow-run-row.js +6 -5
  46. package/dist/components/workflow-run-list/workflow-run-row.js.map +1 -1
  47. package/dist/components/workflow-run-summary/workflow-run-summary.d.ts.map +1 -1
  48. package/dist/components/workflow-run-summary/workflow-run-summary.js +69 -64
  49. package/dist/components/workflow-run-summary/workflow-run-summary.js.map +1 -1
  50. package/dist/components/workflow-run-tabs/index.d.ts +3 -3
  51. package/dist/components/workflow-run-tabs/index.d.ts.map +1 -1
  52. package/dist/components/workflow-run-tabs/index.js +3 -3
  53. package/dist/components/workflow-run-tabs/index.js.map +1 -1
  54. package/dist/components/workflow-run-tabs/run-annotation-count-chip.d.ts +16 -0
  55. package/dist/components/workflow-run-tabs/run-annotation-count-chip.d.ts.map +1 -0
  56. package/dist/components/workflow-run-tabs/run-annotation-count-chip.js +50 -0
  57. package/dist/components/workflow-run-tabs/run-annotation-count-chip.js.map +1 -0
  58. package/dist/components/workflow-run-tabs/run-annotation-item.d.ts +20 -0
  59. package/dist/components/workflow-run-tabs/run-annotation-item.d.ts.map +1 -0
  60. package/dist/components/workflow-run-tabs/run-annotation-item.js +102 -0
  61. package/dist/components/workflow-run-tabs/run-annotation-item.js.map +1 -0
  62. package/dist/components/workflow-run-tabs/run-annotation-list.d.ts +32 -0
  63. package/dist/components/workflow-run-tabs/run-annotation-list.d.ts.map +1 -0
  64. package/dist/components/workflow-run-tabs/run-annotation-list.js +202 -0
  65. package/dist/components/workflow-run-tabs/run-annotation-list.js.map +1 -0
  66. package/dist/components/workflow-run-tabs/run-annotation-summary-line.d.ts +1 -1
  67. package/dist/components/workflow-run-tabs/run-annotation-summary-line.d.ts.map +1 -1
  68. package/dist/components/workflow-run-tabs/run-annotation-summary-line.js +87 -22
  69. package/dist/components/workflow-run-tabs/run-annotation-summary-line.js.map +1 -1
  70. package/dist/components/workflow-run-tabs/run-annotations-empty.d.ts +3 -1
  71. package/dist/components/workflow-run-tabs/run-annotations-empty.d.ts.map +1 -1
  72. package/dist/components/workflow-run-tabs/run-annotations-empty.js +2 -2
  73. package/dist/components/workflow-run-tabs/run-annotations-empty.js.map +1 -1
  74. package/dist/components/workflow-run-tabs/severity-visuals.d.ts +20 -0
  75. package/dist/components/workflow-run-tabs/severity-visuals.d.ts.map +1 -0
  76. package/dist/components/workflow-run-tabs/severity-visuals.js +31 -0
  77. package/dist/components/workflow-run-tabs/severity-visuals.js.map +1 -0
  78. package/dist/components/workflow-run-view/index.d.ts +0 -1
  79. package/dist/components/workflow-run-view/index.d.ts.map +1 -1
  80. package/dist/components/workflow-run-view/index.js +0 -1
  81. package/dist/components/workflow-run-view/index.js.map +1 -1
  82. package/dist/components/workflow-run-view/run-workspace-nav.d.ts +20 -0
  83. package/dist/components/workflow-run-view/run-workspace-nav.d.ts.map +1 -0
  84. package/dist/components/workflow-run-view/run-workspace-nav.js +277 -0
  85. package/dist/components/workflow-run-view/run-workspace-nav.js.map +1 -0
  86. package/dist/components/workflow-run-view/workflow-run-selection.d.ts.map +1 -1
  87. package/dist/components/workflow-run-view/workflow-run-selection.js +1 -14
  88. package/dist/components/workflow-run-view/workflow-run-selection.js.map +1 -1
  89. package/dist/components/workflow-run-view/workflow-run-view.d.ts +10 -10
  90. package/dist/components/workflow-run-view/workflow-run-view.d.ts.map +1 -1
  91. package/dist/components/workflow-run-view/workflow-run-view.js +351 -239
  92. package/dist/components/workflow-run-view/workflow-run-view.js.map +1 -1
  93. package/dist/components/workflow-status/status-visuals.d.ts.map +1 -1
  94. package/dist/components/workflow-status/status-visuals.js +10 -2
  95. package/dist/components/workflow-status/status-visuals.js.map +1 -1
  96. package/dist/components/workflow-status/workflow-status-icon.d.ts +3 -1
  97. package/dist/components/workflow-status/workflow-status-icon.d.ts.map +1 -1
  98. package/dist/components/workflow-status/workflow-status-icon.js +13 -2
  99. package/dist/components/workflow-status/workflow-status-icon.js.map +1 -1
  100. package/dist/core/entities/job-execution.d.ts +9 -0
  101. package/dist/core/entities/job-execution.d.ts.map +1 -1
  102. package/dist/core/entities/job-execution.js +13 -3
  103. package/dist/core/entities/job-execution.js.map +1 -1
  104. package/dist/core/entities/job.d.ts.map +1 -1
  105. package/dist/core/entities/step-attempt.d.ts.map +1 -1
  106. package/dist/core/entities/step.d.ts +2 -0
  107. package/dist/core/entities/step.d.ts.map +1 -1
  108. package/dist/core/entities/step.js +13 -0
  109. package/dist/core/entities/step.js.map +1 -1
  110. package/dist/core/entities/workflow-run-attempt.d.ts.map +1 -1
  111. package/dist/core/entities/workflow-run.d.ts +56 -1
  112. package/dist/core/entities/workflow-run.d.ts.map +1 -1
  113. package/dist/core/entities/workflow-run.js +98 -0
  114. package/dist/core/entities/workflow-run.js.map +1 -1
  115. package/dist/core/run-annotation.d.ts +73 -0
  116. package/dist/core/run-annotation.d.ts.map +1 -0
  117. package/dist/core/run-annotation.js +125 -0
  118. package/dist/core/run-annotation.js.map +1 -0
  119. package/dist/core/workflow-run.d.ts +4 -4
  120. package/dist/core/workflow-run.d.ts.map +1 -1
  121. package/dist/core/workflow-run.js +3 -3
  122. package/dist/core/workflow-run.js.map +1 -1
  123. package/dist/feature.d.ts +20 -16
  124. package/dist/feature.d.ts.map +1 -1
  125. package/dist/feature.js +5 -0
  126. package/dist/feature.js.map +1 -1
  127. package/dist/hooks/api/run-annotation-mapper.d.ts +10 -0
  128. package/dist/hooks/api/run-annotation-mapper.d.ts.map +1 -0
  129. package/dist/hooks/api/run-annotation-mapper.js +22 -0
  130. package/dist/hooks/api/run-annotation-mapper.js.map +1 -0
  131. package/dist/hooks/api/run-annotations.d.ts +25 -0
  132. package/dist/hooks/api/run-annotations.d.ts.map +1 -0
  133. package/dist/hooks/api/run-annotations.js +78 -0
  134. package/dist/hooks/api/run-annotations.js.map +1 -0
  135. package/dist/hooks/api/workflow-runs.d.ts +5 -3
  136. package/dist/hooks/api/workflow-runs.d.ts.map +1 -1
  137. package/dist/hooks/api/workflow-runs.js +5 -4
  138. package/dist/hooks/api/workflow-runs.js.map +1 -1
  139. package/dist/index.d.ts +1 -0
  140. package/dist/index.d.ts.map +1 -1
  141. package/dist/index.js +1 -0
  142. package/dist/index.js.map +1 -1
  143. package/dist/pages/workflow-job-detail-page.d.ts +11 -0
  144. package/dist/pages/workflow-job-detail-page.d.ts.map +1 -0
  145. package/dist/pages/workflow-job-detail-page.js +66 -0
  146. package/dist/pages/workflow-job-detail-page.js.map +1 -0
  147. package/dist/pages/workflow-run-detail-page.d.ts.map +1 -1
  148. package/dist/pages/workflow-run-detail-page.js +4 -37
  149. package/dist/pages/workflow-run-detail-page.js.map +1 -1
  150. package/dist/routes/inputs.d.ts +52 -34
  151. package/dist/routes/inputs.d.ts.map +1 -1
  152. package/dist/routes/inputs.js +74 -43
  153. package/dist/routes/inputs.js.map +1 -1
  154. package/dist/routes/job-detail.d.ts +10 -0
  155. package/dist/routes/job-detail.d.ts.map +1 -0
  156. package/dist/routes/job-detail.js +27 -0
  157. package/dist/routes/job-detail.js.map +1 -0
  158. package/dist/routes/project-route.d.ts +1 -1
  159. package/dist/routes/run-detail.d.ts.map +1 -1
  160. package/dist/routes/runs.d.ts.map +1 -1
  161. package/dist/routes/workflows.d.ts.map +1 -1
  162. package/dist/tsconfig.test.tsbuildinfo +1 -1
  163. package/package.json +10 -9
  164. package/src/components/{workflow-run-view → job-detail}/agent-config-failure-callout.stories.tsx +1 -1
  165. package/src/components/{workflow-run-view → job-detail}/agent-config-failure-callout.tsx +2 -2
  166. package/src/components/job-detail/job-detail-header.test.tsx +34 -0
  167. package/src/components/job-detail/job-detail-header.tsx +136 -0
  168. package/src/components/job-detail/job-detail-view.stories.tsx +531 -0
  169. package/src/components/job-detail/job-detail-view.tsx +467 -0
  170. package/src/components/job-detail/job-empty-states.test.ts +27 -0
  171. package/src/components/job-detail/job-empty-states.tsx +248 -0
  172. package/src/components/job-detail/job-selection.test.ts +188 -0
  173. package/src/components/job-detail/job-selection.ts +96 -0
  174. package/src/components/{workflow-run-view → job-detail}/step-attempt-log-panel.test.tsx +32 -9
  175. package/src/components/{workflow-run-view → job-detail}/step-attempt-log-panel.tsx +52 -18
  176. package/src/components/job-graph/job-graph-content.tsx +1 -1
  177. package/src/components/step-list/step-list-model.test.ts +1 -1
  178. package/src/components/step-list/step-list-model.ts +2 -2
  179. package/src/components/step-list/step-list.stories.tsx +1 -1
  180. package/src/components/step-list/step-list.test.tsx +33 -0
  181. package/src/components/step-list/step-list.tsx +40 -9
  182. package/src/components/workflow-run-duration-label.tsx +50 -12
  183. package/src/components/workflow-run-list/workflow-run-row.tsx +6 -4
  184. package/src/components/workflow-run-summary/workflow-run-summary.stories.tsx +38 -0
  185. package/src/components/workflow-run-summary/workflow-run-summary.test.tsx +79 -5
  186. package/src/components/workflow-run-summary/workflow-run-summary.tsx +56 -60
  187. package/src/components/workflow-run-tabs/index.ts +3 -3
  188. package/src/components/workflow-run-tabs/run-annotation-count-chip.tsx +63 -0
  189. package/src/components/workflow-run-tabs/run-annotation-item.tsx +123 -0
  190. package/src/components/workflow-run-tabs/run-annotation-list.tsx +258 -0
  191. package/src/components/workflow-run-tabs/run-annotation-summary-line.test.tsx +77 -3
  192. package/src/components/workflow-run-tabs/run-annotation-summary-line.tsx +92 -17
  193. package/src/components/workflow-run-tabs/run-annotations-empty.tsx +6 -2
  194. package/src/components/workflow-run-tabs/run-annotations.stories.tsx +293 -0
  195. package/src/components/workflow-run-tabs/severity-visuals.ts +37 -0
  196. package/src/components/workflow-run-view/index.ts +0 -1
  197. package/src/components/workflow-run-view/run-workspace-nav.test.tsx +286 -0
  198. package/src/components/workflow-run-view/run-workspace-nav.tsx +314 -0
  199. package/src/components/workflow-run-view/workflow-run-selection.ts +1 -23
  200. package/src/components/workflow-run-view/workflow-run-view.test.tsx +237 -1085
  201. package/src/components/workflow-run-view/workflow-run-view.tsx +450 -323
  202. package/src/components/workflow-status/status-visuals.ts +5 -2
  203. package/src/components/workflow-status/workflow-status-icon.stories.tsx +1 -0
  204. package/src/components/workflow-status/workflow-status-icon.tsx +26 -1
  205. package/src/core/entities/job-execution.ts +17 -2
  206. package/src/core/entities/step.ts +26 -0
  207. package/src/core/entities/workflow-run-display.test.ts +159 -0
  208. package/src/core/entities/workflow-run.ts +139 -1
  209. package/src/core/run-annotation.test.ts +315 -0
  210. package/src/core/run-annotation.ts +238 -0
  211. package/src/core/workflow-run.ts +16 -1
  212. package/src/feature.ts +5 -0
  213. package/src/hooks/api/run-annotation-mapper.ts +30 -0
  214. package/src/hooks/api/run-annotations.ts +137 -0
  215. package/src/hooks/api/workflow-runs.ts +6 -2
  216. package/src/index.ts +1 -0
  217. package/src/page-harness-budget.test.ts +1 -0
  218. package/src/pages/workflow-job-detail-page.test.tsx +605 -0
  219. package/src/pages/workflow-job-detail-page.tsx +84 -0
  220. package/src/pages/workflow-run-detail-page.tsx +3 -43
  221. package/src/pages/workflow-run-pages.test.tsx +77 -332
  222. package/src/routes/inputs.test.ts +56 -6
  223. package/src/routes/inputs.ts +71 -19
  224. package/src/routes/job-detail.tsx +29 -0
  225. package/test/pages.tsx +25 -3
  226. package/test/render.tsx +6 -1
  227. package/tsconfig.build.tsbuildinfo +1 -1
  228. package/dist/components/workflow-run-tabs/run-jobs-list.d.ts +0 -18
  229. package/dist/components/workflow-run-tabs/run-jobs-list.d.ts.map +0 -1
  230. package/dist/components/workflow-run-tabs/run-jobs-list.js +0 -107
  231. package/dist/components/workflow-run-tabs/run-jobs-list.js.map +0 -1
  232. package/dist/components/workflow-run-tabs/run-tab-count.d.ts +0 -6
  233. package/dist/components/workflow-run-tabs/run-tab-count.d.ts.map +0 -1
  234. package/dist/components/workflow-run-tabs/run-tab-count.js +0 -27
  235. package/dist/components/workflow-run-tabs/run-tab-count.js.map +0 -1
  236. package/dist/components/workflow-run-tabs/run-tab-strip.d.ts +0 -8
  237. package/dist/components/workflow-run-tabs/run-tab-strip.d.ts.map +0 -1
  238. package/dist/components/workflow-run-tabs/run-tab-strip.js +0 -82
  239. package/dist/components/workflow-run-tabs/run-tab-strip.js.map +0 -1
  240. package/dist/components/workflow-run-view/agent-config-failure-callout.d.ts.map +0 -1
  241. package/dist/components/workflow-run-view/agent-config-failure-callout.js.map +0 -1
  242. package/dist/components/workflow-run-view/job-card.d.ts +0 -17
  243. package/dist/components/workflow-run-view/job-card.d.ts.map +0 -1
  244. package/dist/components/workflow-run-view/job-card.js +0 -496
  245. package/dist/components/workflow-run-view/job-card.js.map +0 -1
  246. package/dist/components/workflow-run-view/job-execution-switcher.d.ts.map +0 -1
  247. package/dist/components/workflow-run-view/job-execution-switcher.js.map +0 -1
  248. package/dist/components/workflow-run-view/job-execution-time-text.d.ts.map +0 -1
  249. package/dist/components/workflow-run-view/job-execution-time-text.js.map +0 -1
  250. package/dist/components/workflow-run-view/step-attempt-log-panel.d.ts +0 -9
  251. package/dist/components/workflow-run-view/step-attempt-log-panel.d.ts.map +0 -1
  252. package/dist/components/workflow-run-view/step-attempt-log-panel.js.map +0 -1
  253. package/dist/core/workflow-run-tabs.d.ts +0 -9
  254. package/dist/core/workflow-run-tabs.d.ts.map +0 -1
  255. package/dist/core/workflow-run-tabs.js +0 -3
  256. package/dist/core/workflow-run-tabs.js.map +0 -1
  257. package/src/components/workflow-run-tabs/run-jobs-list.tsx +0 -151
  258. package/src/components/workflow-run-tabs/run-tab-count.tsx +0 -28
  259. package/src/components/workflow-run-tabs/run-tab-strip.stories.tsx +0 -52
  260. package/src/components/workflow-run-tabs/run-tab-strip.test.tsx +0 -117
  261. package/src/components/workflow-run-tabs/run-tab-strip.tsx +0 -97
  262. package/src/components/workflow-run-view/job-card.stories.tsx +0 -789
  263. package/src/components/workflow-run-view/job-card.test.tsx +0 -115
  264. package/src/components/workflow-run-view/job-card.tsx +0 -614
  265. package/src/core/workflow-run-tabs.ts +0 -8
  266. /package/dist/components/{workflow-run-view → job-detail}/agent-config-failure-callout.d.ts +0 -0
  267. /package/dist/components/{workflow-run-view → job-detail}/job-execution-switcher.d.ts +0 -0
  268. /package/dist/components/{workflow-run-view → job-detail}/job-execution-switcher.js +0 -0
  269. /package/dist/components/{workflow-run-view → job-detail}/job-execution-time-text.d.ts +0 -0
  270. /package/dist/components/{workflow-run-view → job-detail}/job-execution-time-text.js +0 -0
  271. /package/src/components/{workflow-run-view → job-detail}/job-execution-switcher.tsx +0 -0
  272. /package/src/components/{workflow-run-view → job-detail}/job-execution-time-text.tsx +0 -0
@@ -0,0 +1,20 @@
1
+ import type { IconName } from '@shipfox/react-ui/icon';
2
+ import type { RunAnnotationSeverity } from '#core/run-annotation.js';
3
+ /**
4
+ * The glyph vocabulary for annotation severity, shared by every count surface.
5
+ *
6
+ * Deliberately the same marks the `Callout` uses on the cards themselves, so the glyph beside
7
+ * `1 error` in the summary is the glyph on the error card below it.
8
+ */
9
+ export declare const SEVERITY_ICON: Record<RunAnnotationSeverity, IconName>;
10
+ /**
11
+ * Severity tone lives in the glyph, never in the label.
12
+ *
13
+ * Coloring the text would make severity compete with the brand accent, which this system
14
+ * reserves for links, focus, and "you are here". Shape plus tone in a 12px mark distinguishes
15
+ * an error from a warning without either of them shouting.
16
+ */
17
+ export declare const SEVERITY_ICON_TONE: Record<RunAnnotationSeverity, string>;
18
+ /** Hairline tone for a bordered count chip, matching the glyph it sits beside. */
19
+ export declare const SEVERITY_CHIP_TONE: Record<RunAnnotationSeverity, string>;
20
+ //# sourceMappingURL=severity-visuals.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"severity-visuals.d.ts","sourceRoot":"","sources":["../../../src/components/workflow-run-tabs/severity-visuals.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,wBAAwB,CAAC;AACrD,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,yBAAyB,CAAC;AAEnE;;;;;GAKG;AACH,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,qBAAqB,EAAE,QAAQ,CAKjE,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,qBAAqB,EAAE,MAAM,CAKpE,CAAC;AAEF,kFAAkF;AAClF,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,qBAAqB,EAAE,MAAM,CAKpE,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * The glyph vocabulary for annotation severity, shared by every count surface.
3
+ *
4
+ * Deliberately the same marks the `Callout` uses on the cards themselves, so the glyph beside
5
+ * `1 error` in the summary is the glyph on the error card below it.
6
+ */ export const SEVERITY_ICON = {
7
+ error: 'closeCircleFill',
8
+ warning: 'errorWarningFill',
9
+ info: 'info',
10
+ success: 'checkboxCircleFill'
11
+ };
12
+ /**
13
+ * Severity tone lives in the glyph, never in the label.
14
+ *
15
+ * Coloring the text would make severity compete with the brand accent, which this system
16
+ * reserves for links, focus, and "you are here". Shape plus tone in a 12px mark distinguishes
17
+ * an error from a warning without either of them shouting.
18
+ */ export const SEVERITY_ICON_TONE = {
19
+ error: 'text-tag-error-icon',
20
+ warning: 'text-tag-warning-icon',
21
+ info: 'text-tag-blue-icon',
22
+ success: 'text-tag-success-icon'
23
+ };
24
+ /** Hairline tone for a bordered count chip, matching the glyph it sits beside. */ export const SEVERITY_CHIP_TONE = {
25
+ error: 'border-tag-error-border text-tag-error-icon',
26
+ warning: 'border-tag-warning-border text-tag-warning-icon',
27
+ info: 'border-tag-blue-border text-tag-blue-icon',
28
+ success: 'border-tag-success-border text-tag-success-icon'
29
+ };
30
+
31
+ //# sourceMappingURL=severity-visuals.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/workflow-run-tabs/severity-visuals.ts"],"sourcesContent":["import type {IconName} from '@shipfox/react-ui/icon';\nimport type {RunAnnotationSeverity} from '#core/run-annotation.js';\n\n/**\n * The glyph vocabulary for annotation severity, shared by every count surface.\n *\n * Deliberately the same marks the `Callout` uses on the cards themselves, so the glyph beside\n * `1 error` in the summary is the glyph on the error card below it.\n */\nexport const SEVERITY_ICON: Record<RunAnnotationSeverity, IconName> = {\n error: 'closeCircleFill',\n warning: 'errorWarningFill',\n info: 'info',\n success: 'checkboxCircleFill',\n};\n\n/**\n * Severity tone lives in the glyph, never in the label.\n *\n * Coloring the text would make severity compete with the brand accent, which this system\n * reserves for links, focus, and \"you are here\". Shape plus tone in a 12px mark distinguishes\n * an error from a warning without either of them shouting.\n */\nexport const SEVERITY_ICON_TONE: Record<RunAnnotationSeverity, string> = {\n error: 'text-tag-error-icon',\n warning: 'text-tag-warning-icon',\n info: 'text-tag-blue-icon',\n success: 'text-tag-success-icon',\n};\n\n/** Hairline tone for a bordered count chip, matching the glyph it sits beside. */\nexport const SEVERITY_CHIP_TONE: Record<RunAnnotationSeverity, string> = {\n error: 'border-tag-error-border text-tag-error-icon',\n warning: 'border-tag-warning-border text-tag-warning-icon',\n info: 'border-tag-blue-border text-tag-blue-icon',\n success: 'border-tag-success-border text-tag-success-icon',\n};\n"],"names":["SEVERITY_ICON","error","warning","info","success","SEVERITY_ICON_TONE","SEVERITY_CHIP_TONE"],"mappings":"AAGA;;;;;CAKC,GACD,OAAO,MAAMA,gBAAyD;IACpEC,OAAO;IACPC,SAAS;IACTC,MAAM;IACNC,SAAS;AACX,EAAE;AAEF;;;;;;CAMC,GACD,OAAO,MAAMC,qBAA4D;IACvEJ,OAAO;IACPC,SAAS;IACTC,MAAM;IACNC,SAAS;AACX,EAAE;AAEF,gFAAgF,GAChF,OAAO,MAAME,qBAA4D;IACvEL,OAAO;IACPC,SAAS;IACTC,MAAM;IACNC,SAAS;AACX,EAAE"}
@@ -1,3 +1,2 @@
1
- export { JobCard } from './job-card.js';
2
1
  export { WorkflowRunView } from './workflow-run-view.js';
3
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/workflow-run-view/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAC,MAAM,eAAe,CAAC;AACtC,OAAO,EAAC,eAAe,EAAC,MAAM,wBAAwB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/workflow-run-view/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,eAAe,EAAC,MAAM,wBAAwB,CAAC"}
@@ -1,4 +1,3 @@
1
- export { JobCard } from './job-card.js';
2
1
  export { WorkflowRunView } from './workflow-run-view.js';
3
2
 
4
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/workflow-run-view/index.ts"],"sourcesContent":["export {JobCard} from './job-card.js';\nexport {WorkflowRunView} from './workflow-run-view.js';\n"],"names":["JobCard","WorkflowRunView"],"mappings":"AAAA,SAAQA,OAAO,QAAO,gBAAgB;AACtC,SAAQC,eAAe,QAAO,yBAAyB"}
1
+ {"version":3,"sources":["../../../src/components/workflow-run-view/index.ts"],"sourcesContent":["export {WorkflowRunView} from './workflow-run-view.js';\n"],"names":["WorkflowRunView"],"mappings":"AAAA,SAAQA,eAAe,QAAO,yBAAyB"}
@@ -0,0 +1,20 @@
1
+ import type { RunAnnotationSummary } from '#core/run-annotation.js';
2
+ import { type WorkflowRunDetail } from '#core/workflow-run.js';
3
+ import { type WorkflowJobSearch, type WorkflowRunTab } from '#routes/inputs.js';
4
+ type RunWorkspaceSection = Exclude<WorkflowRunTab, 'jobs'>;
5
+ export interface RunWorkspaceNavProps {
6
+ workspaceSlug: string;
7
+ projectSlug: string;
8
+ run: WorkflowRunDetail;
9
+ activeSection: RunWorkspaceSection;
10
+ currentJobId?: string | undefined;
11
+ jobSearch?: WorkflowJobSearch | undefined;
12
+ annotationSummary?: RunAnnotationSummary | undefined;
13
+ }
14
+ /**
15
+ * The stable navigation model shared by run-level and job-level routes. The graph explains
16
+ * topology; this compact index makes moving between dedicated job pages predictable.
17
+ */
18
+ export declare function RunWorkspaceNav({ workspaceSlug, projectSlug, run, activeSection, currentJobId, jobSearch, annotationSummary, }: RunWorkspaceNavProps): import("react").JSX.Element;
19
+ export {};
20
+ //# sourceMappingURL=run-workspace-nav.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-workspace-nav.d.ts","sourceRoot":"","sources":["../../../src/components/workflow-run-view/run-workspace-nav.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAC,oBAAoB,EAAC,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,cAAc,EAGpB,MAAM,mBAAmB,CAAC;AAG3B,KAAK,mBAAmB,GAAG,OAAO,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;AAE3D,MAAM,WAAW,oBAAoB;IACnC,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,iBAAiB,CAAC;IACvB,aAAa,EAAE,mBAAmB,CAAC;IACnC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,SAAS,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;IAC1C,iBAAiB,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAC;CACtD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,EAC9B,aAAa,EACb,WAAW,EACX,GAAG,EACH,aAAa,EACb,YAAY,EACZ,SAAc,EACd,iBAAiB,GAClB,EAAE,oBAAoB,+BA0DtB"}
@@ -0,0 +1,277 @@
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
+ countTruncated: annotationSummary?.truncated,
214
+ onNavigate: onNavigate
215
+ })
216
+ }),
217
+ /*#__PURE__*/ _jsx("li", {
218
+ children: /*#__PURE__*/ _jsx(RunSectionLink, {
219
+ workspaceSlug: workspaceSlug,
220
+ projectSlug: projectSlug,
221
+ runId: run.id,
222
+ runAttempt: runAttempt,
223
+ section: "source",
224
+ current: !currentJobId && activeSection === 'source',
225
+ onNavigate: onNavigate
226
+ })
227
+ })
228
+ ]
229
+ })
230
+ ]
231
+ })
232
+ ]
233
+ });
234
+ }
235
+ function RunSectionLink({ workspaceSlug, projectSlug, runId, runAttempt, section, current, count, countTruncated = false, onNavigate }) {
236
+ return /*#__PURE__*/ _jsxs(Link, {
237
+ to: "/w/$workspaceSlug/p/$projectSlug/runs/$workflowRunId",
238
+ params: {
239
+ workspaceSlug,
240
+ projectSlug,
241
+ workflowRunId: runId
242
+ },
243
+ search: workflowRunSearchParams({
244
+ runAttempt,
245
+ ...section === 'summary' ? {} : {
246
+ tab: section
247
+ }
248
+ }, {
249
+ runAttempt
250
+ }),
251
+ onClick: onNavigate,
252
+ "aria-current": current ? 'page' : undefined,
253
+ "aria-label": count ? `${sectionLabel(section)}, ${countTruncated ? `${count} or more` : count}` : undefined,
254
+ 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'),
255
+ children: [
256
+ sectionLabel(section),
257
+ count ? /*#__PURE__*/ _jsxs("span", {
258
+ "aria-hidden": "true",
259
+ className: "ml-auto font-code text-xs text-foreground-neutral-muted tabular-nums",
260
+ children: [
261
+ count,
262
+ countTruncated ? '+' : ''
263
+ ]
264
+ }) : null
265
+ ]
266
+ });
267
+ }
268
+ function sectionLabel(section) {
269
+ if (section === 'annotations') return 'Annotations';
270
+ if (section === 'source') return 'Source';
271
+ return 'Summary';
272
+ }
273
+ function compareJobs(left, right) {
274
+ return left.position - right.position || left.id.localeCompare(right.id);
275
+ }
276
+
277
+ //# 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 type {RunAnnotationSummary} from '#core/run-annotation.js';\nimport {\n defaultJobExecution,\n deriveJobDisplayStatus,\n type Job,\n type WorkflowRunDetail,\n} from '#core/workflow-run.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 countTruncated={annotationSummary?.truncated}\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 countTruncated = false,\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 /** The read hit its page budget, so the count is a lower bound and renders as `N+`. */\n countTruncated?: boolean | 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 aria-label={\n count\n ? `${sectionLabel(section)}, ${countTruncated ? `${count} or more` : count}`\n : undefined\n }\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\n aria-hidden=\"true\"\n className=\"ml-auto font-code text-xs text-foreground-neutral-muted tabular-nums\"\n >\n {count}\n {countTruncated ? '+' : ''}\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","countTruncated","truncated","tab","left","right","position","localeCompare"],"mappings":";AAAA,SAAQA,WAAW,EAAEC,kBAAkB,QAAO,gCAAgC;AAC9E,SAAQC,IAAI,QAAO,yBAAyB;AAC5C,SAAQC,kBAAkB,QAAO,gCAAgC;AACjE,SAAQC,IAAI,QAAO,+BAA+B;AAClD,SAAQC,EAAE,QAAO,0BAA0B;AAC3C,SAAQC,IAAI,QAAO,yBAAyB;AAC5C,SAAQC,SAAS,EAAEC,OAAO,EAAEC,MAAM,EAAEC,QAAQ,QAAO,QAAQ;AAC3D,SAAQC,kBAAkB,QAAO,sDAAsD;AAEvF,SACEC,mBAAmB,EACnBC,sBAAsB,QAGjB,wBAAwB;AAC/B,SAGEC,uBAAuB,EACvBC,uBAAuB,QAClB,oBAAoB;AAC3B,SAAQC,oBAAoB,QAAO,2CAA2C;AAc9E;;;CAGC,GACD,OAAO,SAASC,gBAAgB,EAC9BC,aAAa,EACbC,WAAW,EACXC,GAAG,EACHC,aAAa,EACbC,YAAY,EACZC,YAAY,CAAC,CAAC,EACdC,iBAAiB,EACI;IACrB,MAAMC,OAAOjB,QAAQ,IAAM;eAAIY,IAAIK,IAAI;SAAC,CAACC,IAAI,CAACC,cAAc;QAACP,IAAIK,IAAI;KAAC;IACtE,MAAM,CAACG,YAAYC,cAAc,GAAGnB,SAAS;IAC7C,MAAMoB,aAAaL,KAAKM,IAAI,CAAC,CAACC,MAAQA,IAAIC,EAAE,KAAKX;IACjD,MAAMY,eAAeJ,YAAYK,eAAeC,aAAaf;IAE7D,qBACE,KAAClB;QAAmBkC,YAAY;QAAMC,yBAAyB;kBAC7D,cAAA,KAACC;YAAMC,WAAU;sBACf,cAAA,MAACxC;gBAAYyC,MAAMb;gBAAYc,cAAcb;;kCAC3C,KAAC5B;wBAAmB0C,OAAO;kCACzB,cAAA,MAACC;4BACCC,MAAK;4BACLL,WAAU;4BACVM,cAAW;;8CAEX,MAACC;oCAAKP,WAAU;;sDACd,KAACpC;4CAAK4C,IAAG;4CAAOC,MAAK;4CAAKT,WAAU;sDAAsC;;sDAG1E,KAACO;4CAAKP,WAAU;sDACbN;;;;8CAGL,KAAChC;oCACCgD,MAAK;oCACLD,MAAM;oCACNE,eAAY;oCACZX,WAAWnC,GACT,+DACAuB,cAAc;;;;;kCAKtB,KAACwB;wBACCZ,WAAWnC,GACT,8FACA,CAACuB,cAAc;kCAGjB,cAAA,KAACyB;4BACCnC,eAAeA;4BACfC,aAAaA;4BACbC,KAAKA;4BACLK,MAAMA;4BACNJ,eAAeA;4BACfC,cAAcA;4BACdC,WAAWA;4BACXC,mBAAmBA;4BACnBI,YAAYA;4BACZ0B,YAAY,IAAMzB,cAAc;;;;;;;AAO9C;AAEA,SAASwB,uBAAuB,EAC9BnC,aAAa,EACbC,WAAW,EACXC,GAAG,EACHK,IAAI,EACJJ,aAAa,EACbC,YAAY,EACZC,SAAS,EACTC,iBAAiB,EACjBI,UAAU,EACV0B,UAAU,EAMX;IACC,MAAMC,gBAAgB9C,OAA0B;IAChD,MAAM+C,aAAajC,UAAUiC,UAAU,IAAIpC,IAAIoC,UAAU,CAACC,OAAO;IAEjElD,UAAU;QACR,IAAI,CAACe,gBAAgBM,YAAY;QACjC2B,cAAcG,OAAO,EAAEC,eAAe;YAACC,OAAO;QAAS;IACzD,GAAG;QAACtC;QAAcM;KAAW;IAE7BrB,UAAU;QACR,IAAI,CAACe,gBAAgB,CAACM,YAAY;QAClC2B,cAAcG,OAAO,EAAEC,eAAe;YAACC,OAAO;QAAS;IACzD,GAAG;QAACtC;QAAcM;KAAW;IAE7B,qBACE,MAACiC;QAAIf,cAAW;QAAgBN,WAAU;;0BACxC,KAACsB;0BACC,cAAA,KAACC;8BACC,cAAA,KAACC;wBACC9C,eAAeA;wBACfC,aAAaA;wBACb8C,OAAO7C,IAAIa,EAAE;wBACbuB,YAAYA;wBACZU,SAAQ;wBACRR,SAAS,CAACpC,gBAAgBD,kBAAkB;wBAC5CiC,YAAYA;;;;0BAKlB,MAACY;gBAAQC,mBAAgB;gBAA6B3B,WAAU;;kCAC9D,MAACY;wBAAIZ,WAAU;;0CACb,KAACpC;gCACC4C,IAAG;gCACHf,IAAG;gCACHgB,MAAK;gCACLmB,IAAI;gCACJ5B,WAAU;0CACX;;0CAGD,KAACpC;gCAAK4C,IAAG;gCAAOC,MAAK;gCAAKT,WAAU;0CACjCf,KAAK4C,MAAM;;;;kCAGhB,KAACC;wBAAG9B,WAAU;kCACXf,KAAK8C,GAAG,CAAC,CAACvC;4BACT,MAAM0B,UAAU1B,IAAIC,EAAE,KAAKX;4BAC3B,MAAMkD,YAAY5D,oBAAoBoB;4BACtC,MAAMyC,WAAWD,WAAWE,mBAAmB1C,IAAI0C,eAAe;4BAElE,qBACE,KAACX;0CACC,cAAA,MAACzD;oCACCqE,KAAKjB,UAAUH,gBAAgBqB;oCAC/BC,IAAG;oCACHC,QAAQ;wCAAC5D;wCAAeC;wCAAa4D,eAAe3D,IAAIa,EAAE;wCAAE+C,OAAOhD,IAAIC,EAAE;oCAAA;oCACzEgD,QAAQnE,wBAAwB;wCAAC0C;oCAAU;oCAC3C0B,SAAS5B;oCACT6B,gBAAczB,UAAU,SAASkB;oCACjCpC,WAAWnC,GACT,kPACAqD,WAAW;;sDAGb,KAAC/C;4CACCyE,QAAQvE,uBAAuBmB;4CAC/BiB,MAAM;4CACNoC,SAAS;;sDAEX,KAACtC;4CAAKP,WAAU;sDACbR,IAAIG,WAAW;;sDAElB,KAACY;4CAAKP,WAAU;sDACbiC,yBAAW,KAACzD;gDAAqBsE,MAAMb;iDAAe;;;;+BAtBpDzC,IAAIC,EAAE;wBA2BnB;;;;0BAIJ,MAACiC;gBAAQC,mBAAgB;;kCACvB,KAAC/D;wBACC4C,IAAG;wBACHf,IAAG;wBACHgB,MAAK;wBACLmB,IAAI;wBACJ5B,WAAU;kCACX;;kCAGD,MAACsB;;0CACC,KAACC;0CACC,cAAA,KAACC;oCACC9C,eAAeA;oCACfC,aAAaA;oCACb8C,OAAO7C,IAAIa,EAAE;oCACbuB,YAAYA;oCACZU,SAAQ;oCACRR,SAAS,CAACpC,gBAAgBD,kBAAkB;oCAC5CkE,OAAO/D,mBAAmBgE;oCAC1BC,gBAAgBjE,mBAAmBkE;oCACnCpC,YAAYA;;;0CAGhB,KAACS;0CACC,cAAA,KAACC;oCACC9C,eAAeA;oCACfC,aAAaA;oCACb8C,OAAO7C,IAAIa,EAAE;oCACbuB,YAAYA;oCACZU,SAAQ;oCACRR,SAAS,CAACpC,gBAAgBD,kBAAkB;oCAC5CiC,YAAYA;;;;;;;;;AAO1B;AAEA,SAASU,eAAe,EACtB9C,aAAa,EACbC,WAAW,EACX8C,KAAK,EACLT,UAAU,EACVU,OAAO,EACPR,OAAO,EACP6B,KAAK,EACLE,iBAAiB,KAAK,EACtBnC,UAAU,EAYX;IACC,qBACE,MAAChD;QACCuE,IAAG;QACHC,QAAQ;YAAC5D;YAAeC;YAAa4D,eAAed;QAAK;QACzDgB,QACElE,wBACE;YAACyC;YAAY,GAAIU,YAAY,YAAY,CAAC,IAAI;gBAACyB,KAAKzB;YAAO,CAAC;QAAC,GAC7D;YAACV;QAAU;QAGf0B,SAAS5B;QACT6B,gBAAczB,UAAU,SAASkB;QACjC9B,cACEyC,QACI,GAAGnD,aAAa8B,SAAS,EAAE,EAAEuB,iBAAiB,GAAGF,MAAM,QAAQ,CAAC,GAAGA,OAAO,GAC1EX;QAENpC,WAAWnC,GACT,iRACAqD,WAAW;;YAGZtB,aAAa8B;YACbqB,sBACC,MAACxC;gBACCI,eAAY;gBACZX,WAAU;;oBAET+C;oBACAE,iBAAiB,MAAM;;iBAExB;;;AAGV;AAEA,SAASrD,aAAa8B,OAA4B;IAChD,IAAIA,YAAY,eAAe,OAAO;IACtC,IAAIA,YAAY,UAAU,OAAO;IACjC,OAAO;AACT;AAEA,SAASvC,YAAYiE,IAAS,EAAEC,KAAU;IACxC,OAAOD,KAAKE,QAAQ,GAAGD,MAAMC,QAAQ,IAAIF,KAAK3D,EAAE,CAAC8D,aAAa,CAACF,MAAM5D,EAAE;AACzE"}
@@ -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,CAwC/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,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\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
+ {"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,20 @@
1
- import type { RunAnnotationSummary } from '#core/workflow-run-tabs.js';
2
- import { type WorkflowRunSelectionInput } from '#core/workflow-run-url-state.js';
3
- import { type WorkflowRunTab } from '#routes/inputs.js';
1
+ import { type ReactNode } from 'react';
2
+ import { type WorkflowJobSearch, type WorkflowRunsSearch, type WorkflowRunTab } from '#routes/inputs.js';
4
3
  export interface WorkflowRunViewProps {
5
4
  projectId: string;
6
5
  workspaceSlug?: string | undefined;
7
6
  projectSlug?: string | undefined;
8
7
  workflowRunId?: string | undefined;
9
- selection?: WorkflowRunSelectionInput | undefined;
10
- onSelectionChange?: ((selection: WorkflowRunSelectionInput) => void) | undefined;
8
+ runAttempt?: number | undefined;
9
+ selection?: WorkflowRunsSearch | undefined;
11
10
  tab?: WorkflowRunTab | undefined;
12
- onTabChange?: ((tab: WorkflowRunTab) => void) | undefined;
13
- annotationSummary?: RunAnnotationSummary | undefined;
11
+ activeJobId?: string | undefined;
12
+ jobSearch?: WorkflowJobSearch | undefined;
13
+ jobContent?: ReactNode | undefined;
14
14
  }
15
15
  /**
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.
16
+ * The persistent run workspace. Run-level sections and dedicated job routes share the same
17
+ * header and job index, while the all-jobs Summary always opens on the dependency graph.
18
18
  */
19
- export declare function WorkflowRunView({ projectId, workspaceSlug, projectSlug, workflowRunId, selection, onSelectionChange, tab, onTabChange, annotationSummary, }: WorkflowRunViewProps): import("react").JSX.Element;
19
+ export declare function WorkflowRunView({ projectId, workspaceSlug, projectSlug, workflowRunId, runAttempt, selection, tab, activeJobId, jobSearch, jobContent, }: WorkflowRunViewProps): import("react").JSX.Element;
20
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":"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"}
1
+ {"version":3,"file":"workflow-run-view.d.ts","sourceRoot":"","sources":["../../../src/components/workflow-run-view/workflow-run-view.tsx"],"names":[],"mappings":"AAcA,OAAO,EAAC,KAAK,SAAS,EAAqB,MAAM,OAAO,CAAC;AAUzD,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,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,WAAW,EACX,SAAS,EACT,UAAU,GACX,EAAE,oBAAoB,+BA0CtB"}