@shipfox/client-workflows 12.0.2 → 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 (325) hide show
  1. package/.storybook/main.ts +16 -1
  2. package/.storybook/preview.tsx +3 -3
  3. package/.storybook/workspace-source.ts +31 -0
  4. package/.turbo/turbo-build.log +1 -1
  5. package/CHANGELOG.md +79 -0
  6. package/dist/components/job-graph/job-duration-format.d.ts +2 -2
  7. package/dist/components/job-graph/job-duration-format.d.ts.map +1 -1
  8. package/dist/components/job-graph/job-duration-format.js +4 -2
  9. package/dist/components/job-graph/job-duration-format.js.map +1 -1
  10. package/dist/components/job-graph/job-duration-label.js +1 -1
  11. package/dist/components/job-graph/job-duration-label.js.map +1 -1
  12. package/dist/components/job-graph/job-graph-content.d.ts +2 -1
  13. package/dist/components/job-graph/job-graph-content.d.ts.map +1 -1
  14. package/dist/components/job-graph/job-graph-content.js +3 -3
  15. package/dist/components/job-graph/job-graph-content.js.map +1 -1
  16. package/dist/components/job-graph/job-graph-view.d.ts +2 -1
  17. package/dist/components/job-graph/job-graph-view.d.ts.map +1 -1
  18. package/dist/components/job-graph/job-graph-view.js +2 -2
  19. package/dist/components/job-graph/job-graph-view.js.map +1 -1
  20. package/dist/components/job-graph/job-node.d.ts +1 -1
  21. package/dist/components/job-graph/job-node.d.ts.map +1 -1
  22. package/dist/components/job-graph/job-node.js +10 -9
  23. package/dist/components/job-graph/job-node.js.map +1 -1
  24. package/dist/components/job-graph/types.d.ts +2 -1
  25. package/dist/components/job-graph/types.d.ts.map +1 -1
  26. package/dist/components/job-graph/types.js.map +1 -1
  27. package/dist/components/step-list/step-list.d.ts +2 -2
  28. package/dist/components/step-list/step-list.d.ts.map +1 -1
  29. package/dist/components/step-list/step-list.js.map +1 -1
  30. package/dist/components/workflow-run-duration-label.js +1 -1
  31. package/dist/components/workflow-run-duration-label.js.map +1 -1
  32. package/dist/components/workflow-run-list/job-status-strip.d.ts +21 -0
  33. package/dist/components/workflow-run-list/job-status-strip.d.ts.map +1 -0
  34. package/dist/components/workflow-run-list/job-status-strip.js +185 -0
  35. package/dist/components/workflow-run-list/job-status-strip.js.map +1 -0
  36. package/dist/components/workflow-run-list/run-display.d.ts +27 -3
  37. package/dist/components/workflow-run-list/run-display.d.ts.map +1 -1
  38. package/dist/components/workflow-run-list/run-display.js +78 -7
  39. package/dist/components/workflow-run-list/run-display.js.map +1 -1
  40. package/dist/components/workflow-run-list/types.d.ts +23 -24
  41. package/dist/components/workflow-run-list/types.d.ts.map +1 -1
  42. package/dist/components/workflow-run-list/types.js.map +1 -1
  43. package/dist/components/workflow-run-list/workflow-run-filter-menu.d.ts +22 -0
  44. package/dist/components/workflow-run-list/workflow-run-filter-menu.d.ts.map +1 -0
  45. package/dist/components/workflow-run-list/workflow-run-filter-menu.js +68 -0
  46. package/dist/components/workflow-run-list/workflow-run-filter-menu.js.map +1 -0
  47. package/dist/components/workflow-run-list/workflow-run-filters.d.ts +18 -0
  48. package/dist/components/workflow-run-list/workflow-run-filters.d.ts.map +1 -0
  49. package/dist/components/workflow-run-list/workflow-run-filters.js +236 -0
  50. package/dist/components/workflow-run-list/workflow-run-filters.js.map +1 -0
  51. package/dist/components/workflow-run-list/workflow-run-list-content.d.ts +8 -4
  52. package/dist/components/workflow-run-list/workflow-run-list-content.d.ts.map +1 -1
  53. package/dist/components/workflow-run-list/workflow-run-list-content.js +40 -12
  54. package/dist/components/workflow-run-list/workflow-run-list-content.js.map +1 -1
  55. package/dist/components/workflow-run-list/workflow-run-list-states.d.ts +29 -2
  56. package/dist/components/workflow-run-list/workflow-run-list-states.d.ts.map +1 -1
  57. package/dist/components/workflow-run-list/workflow-run-list-states.js +103 -44
  58. package/dist/components/workflow-run-list/workflow-run-list-states.js.map +1 -1
  59. package/dist/components/workflow-run-list/workflow-run-list-view.d.ts +1 -1
  60. package/dist/components/workflow-run-list/workflow-run-list-view.d.ts.map +1 -1
  61. package/dist/components/workflow-run-list/workflow-run-list-view.js +60 -43
  62. package/dist/components/workflow-run-list/workflow-run-list-view.js.map +1 -1
  63. package/dist/components/workflow-run-list/workflow-run-list.d.ts +1 -1
  64. package/dist/components/workflow-run-list/workflow-run-list.d.ts.map +1 -1
  65. package/dist/components/workflow-run-list/workflow-run-list.js +20 -8
  66. package/dist/components/workflow-run-list/workflow-run-list.js.map +1 -1
  67. package/dist/components/workflow-run-list/workflow-run-row.d.ts +19 -9
  68. package/dist/components/workflow-run-list/workflow-run-row.d.ts.map +1 -1
  69. package/dist/components/workflow-run-list/workflow-run-row.js +179 -112
  70. package/dist/components/workflow-run-list/workflow-run-row.js.map +1 -1
  71. package/dist/components/workflow-run-number-label.d.ts +15 -0
  72. package/dist/components/workflow-run-number-label.d.ts.map +1 -0
  73. package/dist/components/workflow-run-number-label.js +41 -0
  74. package/dist/components/workflow-run-number-label.js.map +1 -0
  75. package/dist/components/workflow-run-summary/workflow-run-attempt-switcher.d.ts +3 -3
  76. package/dist/components/workflow-run-summary/workflow-run-attempt-switcher.d.ts.map +1 -1
  77. package/dist/components/workflow-run-summary/workflow-run-attempt-switcher.js +10 -9
  78. package/dist/components/workflow-run-summary/workflow-run-attempt-switcher.js.map +1 -1
  79. package/dist/components/workflow-run-summary/workflow-run-summary.d.ts +4 -9
  80. package/dist/components/workflow-run-summary/workflow-run-summary.d.ts.map +1 -1
  81. package/dist/components/workflow-run-summary/workflow-run-summary.js +107 -74
  82. package/dist/components/workflow-run-summary/workflow-run-summary.js.map +1 -1
  83. package/dist/components/workflow-run-tabs/index.d.ts +6 -0
  84. package/dist/components/workflow-run-tabs/index.d.ts.map +1 -0
  85. package/dist/components/workflow-run-tabs/index.js +7 -0
  86. package/dist/components/workflow-run-tabs/index.js.map +1 -0
  87. package/dist/components/workflow-run-tabs/run-annotation-summary-line.d.ts +11 -0
  88. package/dist/components/workflow-run-tabs/run-annotation-summary-line.d.ts.map +1 -0
  89. package/dist/components/workflow-run-tabs/run-annotation-summary-line.js +71 -0
  90. package/dist/components/workflow-run-tabs/run-annotation-summary-line.js.map +1 -0
  91. package/dist/components/workflow-run-tabs/run-annotations-empty.d.ts +2 -0
  92. package/dist/components/workflow-run-tabs/run-annotations-empty.d.ts.map +1 -0
  93. package/dist/components/workflow-run-tabs/run-annotations-empty.js +11 -0
  94. package/dist/components/workflow-run-tabs/run-annotations-empty.js.map +1 -0
  95. package/dist/components/workflow-run-tabs/run-jobs-list.d.ts +18 -0
  96. package/dist/components/workflow-run-tabs/run-jobs-list.d.ts.map +1 -0
  97. package/dist/components/workflow-run-tabs/run-jobs-list.js +107 -0
  98. package/dist/components/workflow-run-tabs/run-jobs-list.js.map +1 -0
  99. package/dist/components/workflow-run-tabs/run-tab-count.d.ts +6 -0
  100. package/dist/components/workflow-run-tabs/run-tab-count.d.ts.map +1 -0
  101. package/dist/components/workflow-run-tabs/run-tab-count.js +27 -0
  102. package/dist/components/workflow-run-tabs/run-tab-count.js.map +1 -0
  103. package/dist/components/workflow-run-tabs/run-tab-strip.d.ts +8 -0
  104. package/dist/components/workflow-run-tabs/run-tab-strip.d.ts.map +1 -0
  105. package/dist/components/workflow-run-tabs/run-tab-strip.js +82 -0
  106. package/dist/components/workflow-run-tabs/run-tab-strip.js.map +1 -0
  107. package/dist/components/workflow-run-view/agent-config-failure-callout.d.ts +2 -2
  108. package/dist/components/workflow-run-view/agent-config-failure-callout.d.ts.map +1 -1
  109. package/dist/components/workflow-run-view/agent-config-failure-callout.js +4 -4
  110. package/dist/components/workflow-run-view/agent-config-failure-callout.js.map +1 -1
  111. package/dist/components/workflow-run-view/job-card.d.ts +2 -2
  112. package/dist/components/workflow-run-view/job-card.d.ts.map +1 -1
  113. package/dist/components/workflow-run-view/job-card.js +51 -32
  114. package/dist/components/workflow-run-view/job-card.js.map +1 -1
  115. package/dist/components/workflow-run-view/job-execution-switcher.d.ts +1 -1
  116. package/dist/components/workflow-run-view/job-execution-switcher.d.ts.map +1 -1
  117. package/dist/components/workflow-run-view/job-execution-switcher.js +20 -8
  118. package/dist/components/workflow-run-view/job-execution-switcher.js.map +1 -1
  119. package/dist/components/workflow-run-view/workflow-run-selection.d.ts.map +1 -1
  120. package/dist/components/workflow-run-view/workflow-run-selection.js +40 -1
  121. package/dist/components/workflow-run-view/workflow-run-selection.js.map +1 -1
  122. package/dist/components/workflow-run-view/workflow-run-states.d.ts +1 -0
  123. package/dist/components/workflow-run-view/workflow-run-states.d.ts.map +1 -1
  124. package/dist/components/workflow-run-view/workflow-run-states.js +10 -1
  125. package/dist/components/workflow-run-view/workflow-run-states.js.map +1 -1
  126. package/dist/components/workflow-run-view/workflow-run-view.d.ts +10 -5
  127. package/dist/components/workflow-run-view/workflow-run-view.d.ts.map +1 -1
  128. package/dist/components/workflow-run-view/workflow-run-view.js +136 -85
  129. package/dist/components/workflow-run-view/workflow-run-view.js.map +1 -1
  130. package/dist/components/workflow-source-panel/index.d.ts +1 -0
  131. package/dist/components/workflow-source-panel/index.d.ts.map +1 -1
  132. package/dist/components/workflow-source-panel/index.js +1 -0
  133. package/dist/components/workflow-source-panel/index.js.map +1 -1
  134. package/dist/components/workflow-source-panel/workflow-source-content.d.ts +12 -0
  135. package/dist/components/workflow-source-panel/workflow-source-content.d.ts.map +1 -0
  136. package/dist/components/workflow-source-panel/workflow-source-content.js +53 -0
  137. package/dist/components/workflow-source-panel/workflow-source-content.js.map +1 -0
  138. package/dist/components/workflow-source-panel/workflow-source-panel.d.ts +1 -1
  139. package/dist/components/workflow-source-panel/workflow-source-panel.d.ts.map +1 -1
  140. package/dist/components/workflow-source-panel/workflow-source-panel.js +7 -54
  141. package/dist/components/workflow-source-panel/workflow-source-panel.js.map +1 -1
  142. package/dist/components/workflow-status/status-visuals.d.ts +4 -4
  143. package/dist/components/workflow-status/status-visuals.d.ts.map +1 -1
  144. package/dist/components/workflow-status/status-visuals.js +7 -0
  145. package/dist/components/workflow-status/status-visuals.js.map +1 -1
  146. package/dist/components/workflow-status/workflow-status-icon.d.ts +3 -4
  147. package/dist/components/workflow-status/workflow-status-icon.d.ts.map +1 -1
  148. package/dist/components/workflow-status/workflow-status-icon.js +6 -4
  149. package/dist/components/workflow-status/workflow-status-icon.js.map +1 -1
  150. package/dist/core/entities/job-execution.d.ts +10 -0
  151. package/dist/core/entities/job-execution.d.ts.map +1 -1
  152. package/dist/core/entities/job-execution.js +11 -0
  153. package/dist/core/entities/job-execution.js.map +1 -1
  154. package/dist/core/entities/job.d.ts +4 -2
  155. package/dist/core/entities/job.d.ts.map +1 -1
  156. package/dist/core/entities/job.js +8 -1
  157. package/dist/core/entities/job.js.map +1 -1
  158. package/dist/core/entities/step.d.ts +1 -1
  159. package/dist/core/entities/step.d.ts.map +1 -1
  160. package/dist/core/entities/step.js +2 -0
  161. package/dist/core/entities/step.js.map +1 -1
  162. package/dist/core/entities/workflow-run.d.ts +52 -4
  163. package/dist/core/entities/workflow-run.d.ts.map +1 -1
  164. package/dist/core/entities/workflow-run.js +22 -3
  165. package/dist/core/entities/workflow-run.js.map +1 -1
  166. package/dist/core/workflow-run-tabs.d.ts +9 -0
  167. package/dist/core/workflow-run-tabs.d.ts.map +1 -0
  168. package/dist/core/workflow-run-tabs.js +3 -0
  169. package/dist/core/workflow-run-tabs.js.map +1 -0
  170. package/dist/core/workflow-run.d.ts +6 -6
  171. package/dist/core/workflow-run.d.ts.map +1 -1
  172. package/dist/core/workflow-run.js +3 -3
  173. package/dist/core/workflow-run.js.map +1 -1
  174. package/dist/feature.d.ts +7 -7
  175. package/dist/feature.js +5 -5
  176. package/dist/feature.js.map +1 -1
  177. package/dist/hooks/api/workflow-run-mapper.d.ts +4 -3
  178. package/dist/hooks/api/workflow-run-mapper.d.ts.map +1 -1
  179. package/dist/hooks/api/workflow-run-mapper.js +31 -3
  180. package/dist/hooks/api/workflow-run-mapper.js.map +1 -1
  181. package/dist/hooks/api/workflow-runs.d.ts +4 -4
  182. package/dist/hooks/api/workflow-runs.d.ts.map +1 -1
  183. package/dist/hooks/api/workflow-runs.js +12 -4
  184. package/dist/hooks/api/workflow-runs.js.map +1 -1
  185. package/dist/index.d.ts +4 -3
  186. package/dist/index.d.ts.map +1 -1
  187. package/dist/index.js +3 -2
  188. package/dist/index.js.map +1 -1
  189. package/dist/pages/project-workflows-page.js +46 -1
  190. package/dist/pages/project-workflows-page.js.map +1 -1
  191. package/dist/pages/workflow-run-detail-page.d.ts +11 -0
  192. package/dist/pages/workflow-run-detail-page.d.ts.map +1 -0
  193. package/dist/pages/workflow-run-detail-page.js +52 -0
  194. package/dist/pages/workflow-run-detail-page.js.map +1 -0
  195. package/dist/pages/workflow-run-list-page.d.ts +10 -0
  196. package/dist/pages/workflow-run-list-page.d.ts.map +1 -0
  197. package/dist/pages/workflow-run-list-page.js +43 -0
  198. package/dist/pages/workflow-run-list-page.js.map +1 -0
  199. package/dist/routes/inputs.d.ts +94 -5
  200. package/dist/routes/inputs.d.ts.map +1 -1
  201. package/dist/routes/inputs.js +199 -13
  202. package/dist/routes/inputs.js.map +1 -1
  203. package/dist/routes/project-route.d.ts +6 -0
  204. package/dist/routes/project-route.d.ts.map +1 -0
  205. package/dist/routes/project-route.js +25 -0
  206. package/dist/routes/project-route.js.map +1 -0
  207. package/dist/routes/run-detail.d.ts.map +1 -1
  208. package/dist/routes/run-detail.js +12 -7
  209. package/dist/routes/run-detail.js.map +1 -1
  210. package/dist/routes/runs.d.ts.map +1 -1
  211. package/dist/routes/runs.js +11 -6
  212. package/dist/routes/runs.js.map +1 -1
  213. package/dist/routes/workflows.d.ts.map +1 -1
  214. package/dist/routes/workflows.js +6 -5
  215. package/dist/routes/workflows.js.map +1 -1
  216. package/dist/tsconfig.test.tsbuildinfo +1 -1
  217. package/package.json +9 -9
  218. package/src/components/job-graph/job-duration-format.ts +11 -2
  219. package/src/components/job-graph/job-duration-label.tsx +5 -1
  220. package/src/components/job-graph/job-graph-content.tsx +7 -4
  221. package/src/components/job-graph/job-graph-view.test.tsx +19 -8
  222. package/src/components/job-graph/job-graph-view.tsx +6 -3
  223. package/src/components/job-graph/job-graph.stories.tsx +24 -20
  224. package/src/components/job-graph/job-node.stories.tsx +11 -6
  225. package/src/components/job-graph/job-node.test.tsx +82 -12
  226. package/src/components/job-graph/job-node.tsx +22 -15
  227. package/src/components/job-graph/types.ts +5 -1
  228. package/src/components/step-list/step-list.stories.tsx +2 -3
  229. package/src/components/step-list/step-list.tsx +3 -2
  230. package/src/components/workflow-run-duration-label.tsx +1 -1
  231. package/src/components/workflow-run-list/job-status-strip.tsx +189 -0
  232. package/src/components/workflow-run-list/run-display.test.ts +169 -30
  233. package/src/components/workflow-run-list/run-display.ts +116 -9
  234. package/src/components/workflow-run-list/types.ts +21 -17
  235. package/src/components/workflow-run-list/workflow-run-filter-menu.tsx +100 -0
  236. package/src/components/workflow-run-list/workflow-run-filters.tsx +243 -0
  237. package/src/components/workflow-run-list/workflow-run-list-content.tsx +44 -16
  238. package/src/components/workflow-run-list/workflow-run-list-states.tsx +128 -27
  239. package/src/components/workflow-run-list/workflow-run-list-view.test.tsx +441 -104
  240. package/src/components/workflow-run-list/workflow-run-list-view.tsx +73 -43
  241. package/src/components/workflow-run-list/workflow-run-list.stories.tsx +140 -20
  242. package/src/components/workflow-run-list/workflow-run-list.tsx +20 -10
  243. package/src/components/workflow-run-list/workflow-run-row.tsx +173 -106
  244. package/src/components/workflow-run-number-label.test.tsx +45 -0
  245. package/src/components/workflow-run-number-label.tsx +47 -0
  246. package/src/components/workflow-run-summary/workflow-run-attempt-switcher.test.tsx +7 -8
  247. package/src/components/workflow-run-summary/workflow-run-attempt-switcher.tsx +15 -14
  248. package/src/components/workflow-run-summary/workflow-run-summary.stories.tsx +29 -38
  249. package/src/components/workflow-run-summary/workflow-run-summary.test.tsx +30 -24
  250. package/src/components/workflow-run-summary/workflow-run-summary.tsx +102 -77
  251. package/src/components/workflow-run-tabs/index.ts +5 -0
  252. package/src/components/workflow-run-tabs/run-annotation-summary-line.test.tsx +69 -0
  253. package/src/components/workflow-run-tabs/run-annotation-summary-line.tsx +97 -0
  254. package/src/components/workflow-run-tabs/run-annotations-empty.tsx +11 -0
  255. package/src/components/workflow-run-tabs/run-jobs-list.tsx +151 -0
  256. package/src/components/workflow-run-tabs/run-tab-count.tsx +28 -0
  257. package/src/components/workflow-run-tabs/run-tab-strip.stories.tsx +52 -0
  258. package/src/components/workflow-run-tabs/run-tab-strip.test.tsx +117 -0
  259. package/src/components/workflow-run-tabs/run-tab-strip.tsx +97 -0
  260. package/src/components/workflow-run-view/agent-config-failure-callout.stories.tsx +2 -3
  261. package/src/components/workflow-run-view/agent-config-failure-callout.tsx +4 -4
  262. package/src/components/workflow-run-view/job-card.stories.tsx +11 -10
  263. package/src/components/workflow-run-view/job-card.test.tsx +115 -0
  264. package/src/components/workflow-run-view/job-card.tsx +74 -35
  265. package/src/components/workflow-run-view/job-execution-switcher.tsx +31 -9
  266. package/src/components/workflow-run-view/workflow-run-selection.test.ts +48 -0
  267. package/src/components/workflow-run-view/workflow-run-selection.ts +48 -1
  268. package/src/components/workflow-run-view/workflow-run-states.tsx +12 -1
  269. package/src/components/workflow-run-view/workflow-run-view.test.tsx +152 -94
  270. package/src/components/workflow-run-view/workflow-run-view.tsx +219 -95
  271. package/src/components/workflow-source-panel/index.ts +1 -0
  272. package/src/components/workflow-source-panel/workflow-source-content.tsx +84 -0
  273. package/src/components/workflow-source-panel/workflow-source-panel.tsx +14 -81
  274. package/src/components/workflow-status/status-visuals.test.ts +9 -0
  275. package/src/components/workflow-status/status-visuals.ts +6 -4
  276. package/src/components/workflow-status/workflow-status-icon.stories.tsx +10 -2
  277. package/src/components/workflow-status/workflow-status-icon.test.tsx +18 -0
  278. package/src/components/workflow-status/workflow-status-icon.tsx +17 -24
  279. package/src/core/entities/job-execution.ts +22 -0
  280. package/src/core/entities/job-status.test.ts +104 -0
  281. package/src/core/entities/job.ts +18 -3
  282. package/src/core/entities/step.ts +4 -0
  283. package/src/core/entities/workflow-run.ts +76 -7
  284. package/src/core/workflow-run-tabs.ts +8 -0
  285. package/src/core/workflow-run.test.ts +24 -9
  286. package/src/core/workflow-run.ts +17 -2
  287. package/src/feature.ts +5 -5
  288. package/src/hooks/api/workflow-run-mapper.ts +30 -3
  289. package/src/hooks/api/workflow-runs.test.tsx +2 -0
  290. package/src/hooks/api/workflow-runs.ts +12 -7
  291. package/src/index.ts +7 -2
  292. package/src/page-harness-budget.test.ts +1 -1
  293. package/src/pages/project-workflows-page.test.tsx +59 -5
  294. package/src/pages/project-workflows-page.tsx +34 -1
  295. package/src/pages/workflow-run-detail-page.tsx +72 -0
  296. package/src/pages/workflow-run-list-page.tsx +65 -0
  297. package/src/pages/workflow-run-pages.test.tsx +823 -0
  298. package/src/routes/inputs.test.ts +240 -12
  299. package/src/routes/inputs.ts +215 -11
  300. package/src/routes/project-route.tsx +25 -0
  301. package/src/routes/run-detail.tsx +15 -8
  302. package/src/routes/runs.tsx +14 -7
  303. package/src/routes/workflows.tsx +5 -4
  304. package/src/storybook-config.test.ts +27 -0
  305. package/test/fixtures/workflow-run.ts +76 -7
  306. package/test/pages.tsx +18 -8
  307. package/test/render.tsx +8 -2
  308. package/tsconfig.build.tsbuildinfo +1 -1
  309. package/tsconfig.test.json +7 -1
  310. package/dist/components/workflow-run-list/workflow-run-list-header.d.ts +0 -10
  311. package/dist/components/workflow-run-list/workflow-run-list-header.d.ts.map +0 -1
  312. package/dist/components/workflow-run-list/workflow-run-list-header.js +0 -55
  313. package/dist/components/workflow-run-list/workflow-run-list-header.js.map +0 -1
  314. package/dist/pages/workflow-run-first-time-use.d.ts +0 -6
  315. package/dist/pages/workflow-run-first-time-use.d.ts.map +0 -1
  316. package/dist/pages/workflow-run-first-time-use.js +0 -17
  317. package/dist/pages/workflow-run-first-time-use.js.map +0 -1
  318. package/dist/pages/workflow-run-page.d.ts +0 -10
  319. package/dist/pages/workflow-run-page.d.ts.map +0 -1
  320. package/dist/pages/workflow-run-page.js +0 -90
  321. package/dist/pages/workflow-run-page.js.map +0 -1
  322. package/src/components/workflow-run-list/workflow-run-list-header.tsx +0 -53
  323. package/src/pages/workflow-run-first-time-use.tsx +0 -17
  324. package/src/pages/workflow-run-page.test.tsx +0 -519
  325. package/src/pages/workflow-run-page.tsx +0 -94
@@ -0,0 +1,107 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { EmptyState } from '@shipfox/react-ui/empty-state';
3
+ import { useTimeTick } from '@shipfox/react-ui/time-ticker';
4
+ import { cn } from '@shipfox/react-ui/utils';
5
+ import { defaultJobExecution, deriveJobDisplayStatus, deriveJobExecutionDisplayStatus } from '#core/workflow-run.js';
6
+ import { formatJobDurationAccessibleLabel } from '../job-graph/job-duration-format.js';
7
+ import { JobDurationLabel } from '../job-graph/job-duration-label.js';
8
+ import { JobCard } from '../workflow-run-view/job-card.js';
9
+ import { WorkflowStatusIcon } from '../workflow-status/workflow-status-icon.js';
10
+ export function RunJobsList({ jobs, selectedJobId, onSelectedJobChange, workspaceSlug, selectedJobExecution, selectedAttemptId, onSelectedJobExecutionChange, onSelectedAttemptChange, sourcePanelId, sourceAvailable, focusedSourceStepId, onOpenStepSource }) {
11
+ useTimeTick();
12
+ if (jobs.length === 0) {
13
+ return /*#__PURE__*/ _jsx("section", {
14
+ "aria-label": "Workflow jobs",
15
+ className: "rounded-8 border border-border-neutral-base bg-background-components-base",
16
+ children: /*#__PURE__*/ _jsx("div", {
17
+ className: "min-h-160",
18
+ children: /*#__PURE__*/ _jsx(RunJobsEmptyState, {})
19
+ })
20
+ });
21
+ }
22
+ const orderedJobs = [
23
+ ...jobs
24
+ ].sort(compareJobs);
25
+ return /*#__PURE__*/ _jsx("section", {
26
+ "aria-label": "Workflow jobs",
27
+ className: "flex min-w-0 flex-col gap-8",
28
+ children: /*#__PURE__*/ _jsx("ul", {
29
+ "aria-label": "Run jobs",
30
+ className: "m-0 flex min-w-0 list-none flex-col gap-8 p-0",
31
+ children: orderedJobs.map((job)=>{
32
+ const selected = job.id === selectedJobId;
33
+ const status = deriveJobDisplayStatus(job);
34
+ const execution = defaultJobExecution(job);
35
+ const durationLabel = formatJobDurationAccessibleLabel(job.displayDuration, execution ? deriveJobExecutionDisplayStatus(execution) : undefined);
36
+ const rowLabel = [
37
+ job.displayName,
38
+ statusLabel(status),
39
+ durationLabel,
40
+ job.carriedOver ? 'reused' : undefined
41
+ ].filter((part)=>Boolean(part)).join(', ');
42
+ return /*#__PURE__*/ _jsxs("li", {
43
+ className: "min-w-0",
44
+ children: [
45
+ /*#__PURE__*/ _jsxs("button", {
46
+ type: "button",
47
+ "aria-expanded": selected,
48
+ "aria-controls": selected ? `job-card-${job.id}` : undefined,
49
+ "aria-label": rowLabel,
50
+ onClick: ()=>onSelectedJobChange(selected ? undefined : job.id),
51
+ className: cn('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', selected && 'bg-background-components-hover hover:bg-background-components-pressed'),
52
+ children: [
53
+ selected ? /*#__PURE__*/ _jsx("span", {
54
+ "aria-hidden": "true",
55
+ className: "absolute inset-y-6 left-0 w-px rounded-full bg-border-highlights-interactive"
56
+ }) : null,
57
+ /*#__PURE__*/ _jsx(WorkflowStatusIcon, {
58
+ status: status,
59
+ size: 14,
60
+ tooltip: false
61
+ }),
62
+ /*#__PURE__*/ _jsx("span", {
63
+ className: "min-w-0 flex-1 truncate text-sm font-medium text-foreground-neutral-base",
64
+ children: job.displayName
65
+ }),
66
+ /*#__PURE__*/ _jsx(JobDurationLabel, {
67
+ duration: job.displayDuration
68
+ })
69
+ ]
70
+ }),
71
+ selected ? /*#__PURE__*/ _jsx("div", {
72
+ id: `job-card-${job.id}`,
73
+ className: "mt-8",
74
+ children: /*#__PURE__*/ _jsx(JobCard, {
75
+ workspaceSlug: workspaceSlug,
76
+ job: job,
77
+ selectedJobExecution: selectedJobExecution,
78
+ selectedAttemptId: job.carriedOver ? undefined : selectedAttemptId,
79
+ onSelectedJobExecutionChange: onSelectedJobExecutionChange,
80
+ onSelectedAttemptChange: onSelectedAttemptChange,
81
+ sourcePanelId: sourcePanelId,
82
+ sourceAvailable: sourceAvailable,
83
+ focusedSourceStepId: focusedSourceStepId,
84
+ onOpenStepSource: onOpenStepSource
85
+ })
86
+ }) : null
87
+ ]
88
+ }, job.id);
89
+ })
90
+ })
91
+ });
92
+ }
93
+ function RunJobsEmptyState() {
94
+ return /*#__PURE__*/ _jsx(EmptyState, {
95
+ icon: "componentLine",
96
+ title: "No jobs yet",
97
+ description: "This run has not materialized jobs."
98
+ });
99
+ }
100
+ function compareJobs(left, right) {
101
+ return left.position - right.position || left.displayName.localeCompare(right.displayName) || left.id.localeCompare(right.id);
102
+ }
103
+ function statusLabel(status) {
104
+ return status === 'listening' ? 'Listening' : status.charAt(0).toUpperCase() + status.slice(1);
105
+ }
106
+
107
+ //# sourceMappingURL=run-jobs-list.js.map
@@ -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":";AAAA,SAAQA,UAAU,QAAO,gCAAgC;AACzD,SAAQC,WAAW,QAAO,gCAAgC;AAC1D,SAAQC,EAAE,QAAO,0BAA0B;AAC3C,SACEC,mBAAmB,EACnBC,sBAAsB,EACtBC,+BAA+B,QAE1B,wBAAwB;AAC/B,SAAQC,gCAAgC,QAAO,sCAAsC;AACrF,SAAQC,gBAAgB,QAAO,qCAAqC;AACpE,SAAQC,OAAO,QAAO,mCAAmC;AACzD,SAAQC,kBAAkB,QAAO,6CAA6C;AAiB9E,OAAO,SAASC,YAAY,EAC1BC,IAAI,EACJC,aAAa,EACbC,mBAAmB,EACnBC,aAAa,EACbC,oBAAoB,EACpBC,iBAAiB,EACjBC,4BAA4B,EAC5BC,uBAAuB,EACvBC,aAAa,EACbC,eAAe,EACfC,mBAAmB,EACnBC,gBAAgB,EACC;IACjBrB;IAEA,IAAIU,KAAKY,MAAM,KAAK,GAAG;QACrB,qBACE,KAACC;YACCC,cAAW;YACXC,WAAU;sBAEV,cAAA,KAACC;gBAAID,WAAU;0BACb,cAAA,KAACE;;;IAIT;IAEA,MAAMC,cAAc;WAAIlB;KAAK,CAACmB,IAAI,CAACC;IAEnC,qBACE,KAACP;QAAQC,cAAW;QAAgBC,WAAU;kBAC5C,cAAA,KAACM;YAAGP,cAAW;YAAWC,WAAU;sBACjCG,YAAYI,GAAG,CAAC,CAACC;gBAChB,MAAMC,WAAWD,IAAIE,EAAE,KAAKxB;gBAC5B,MAAMyB,SAASjC,uBAAuB8B;gBACtC,MAAMI,YAAYnC,oBAAoB+B;gBACtC,MAAMK,gBAAgBjC,iCACpB4B,IAAIM,eAAe,EACnBF,YAAYjC,gCAAgCiC,aAAaG;gBAE3D,MAAMC,WAAW;oBACfR,IAAIS,WAAW;oBACfC,YAAYP;oBACZE;oBACAL,IAAIW,WAAW,GAAG,WAAWJ;iBAC9B,CACEK,MAAM,CAAC,CAACC,OAAyBC,QAAQD,OACzCE,IAAI,CAAC;gBAER,qBACE,MAACC;oBAAgBxB,WAAU;;sCACzB,MAACyB;4BACCC,MAAK;4BACLC,iBAAelB;4BACfmB,iBAAenB,WAAW,CAAC,SAAS,EAAED,IAAIE,EAAE,EAAE,GAAGK;4BACjDhB,cAAYiB;4BACZa,SAAS,IAAM1C,oBAAoBsB,WAAWM,YAAYP,IAAIE,EAAE;4BAChEV,WAAWxB,GACT,qPACAiC,YACE;;gCAGHA,yBACC,KAACqB;oCACCC,eAAY;oCACZ/B,WAAU;qCAEV;8CACJ,KAACjB;oCAAmB4B,QAAQA;oCAAQqB,MAAM;oCAAIC,SAAS;;8CACvD,KAACH;oCAAK9B,WAAU;8CACbQ,IAAIS,WAAW;;8CAElB,KAACpC;oCAAiBqD,UAAU1B,IAAIM,eAAe;;;;wBAEhDL,yBACC,KAACR;4BAAIS,IAAI,CAAC,SAAS,EAAEF,IAAIE,EAAE,EAAE;4BAAEV,WAAU;sCACvC,cAAA,KAAClB;gCACCM,eAAeA;gCACfoB,KAAKA;gCACLnB,sBAAsBA;gCACtBC,mBAAmBkB,IAAIW,WAAW,GAAGJ,YAAYzB;gCACjDC,8BAA8BA;gCAC9BC,yBAAyBA;gCACzBC,eAAeA;gCACfC,iBAAiBA;gCACjBC,qBAAqBA;gCACrBC,kBAAkBA;;6BAGpB;;mBAxCGY,IAAIE,EAAE;YA2CnB;;;AAIR;AAEA,SAASR;IACP,qBACE,KAAC5B;QACC6D,MAAK;QACLC,OAAM;QACNC,aAAY;;AAGlB;AAEA,SAAShC,YAAYiC,IAAS,EAAEC,KAAU;IACxC,OACED,KAAKE,QAAQ,GAAGD,MAAMC,QAAQ,IAC9BF,KAAKrB,WAAW,CAACwB,aAAa,CAACF,MAAMtB,WAAW,KAChDqB,KAAK5B,EAAE,CAAC+B,aAAa,CAACF,MAAM7B,EAAE;AAElC;AAEA,SAASQ,YAAYP,MAAiD;IACpE,OAAOA,WAAW,cAAc,cAAcA,OAAO+B,MAAM,CAAC,GAAGC,WAAW,KAAKhC,OAAOiC,KAAK,CAAC;AAC9F"}
@@ -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,6 +1,6 @@
1
1
  import type { AgentStepConfig, StepError } from '#core/workflow-run.js';
2
- export declare function AgentConfigFailureCallout({ workspaceId, config, error, }: {
3
- workspaceId: string;
2
+ export declare function AgentConfigFailureCallout({ workspaceSlug, config, error, }: {
3
+ workspaceSlug?: string | undefined;
4
4
  config: AgentStepConfig | null;
5
5
  error: StepError | null;
6
6
  }): import("react").JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"agent-config-failure-callout.d.ts","sourceRoot":"","sources":["../../../src/components/workflow-run-view/agent-config-failure-callout.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAC,eAAe,EAAE,SAAS,EAAC,MAAM,uBAAuB,CAAC;AAEtE,wBAAgB,yBAAyB,CAAC,EACxC,WAAW,EACX,MAAM,EACN,KAAK,GACN,EAAE;IACD,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,eAAe,GAAG,IAAI,CAAC;IAC/B,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;CACzB,+BAoBA"}
1
+ {"version":3,"file":"agent-config-failure-callout.d.ts","sourceRoot":"","sources":["../../../src/components/workflow-run-view/agent-config-failure-callout.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAC,eAAe,EAAE,SAAS,EAAC,MAAM,uBAAuB,CAAC;AAEtE,wBAAgB,yBAAyB,CAAC,EACxC,aAAa,EACb,MAAM,EACN,KAAK,GACN,EAAE;IACD,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,MAAM,EAAE,eAAe,GAAG,IAAI,CAAC;IAC/B,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;CACzB,+BAoBA"}
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Alert, AlertActions, AlertContent, AlertDescription, AlertTitle } from '@shipfox/react-ui/alert';
3
3
  import { Button } from '@shipfox/react-ui/button';
4
4
  import { Link } from '@tanstack/react-router';
5
- export function AgentConfigFailureCallout({ workspaceId, config, error }) {
5
+ export function AgentConfigFailureCallout({ workspaceSlug, config, error }) {
6
6
  const copy = agentConfigFailureCopy(config, error);
7
7
  return /*#__PURE__*/ _jsx(Alert, {
8
8
  variant: "warning",
@@ -16,16 +16,16 @@ export function AgentConfigFailureCallout({ workspaceId, config, error }) {
16
16
  /*#__PURE__*/ _jsx(AlertDescription, {
17
17
  children: copy.description
18
18
  }),
19
- copy.showProviderCta ? /*#__PURE__*/ _jsx(AlertActions, {
19
+ copy.showProviderCta && workspaceSlug ? /*#__PURE__*/ _jsx(AlertActions, {
20
20
  children: /*#__PURE__*/ _jsx(Button, {
21
21
  asChild: true,
22
22
  size: "2xs",
23
23
  variant: "secondary",
24
24
  iconRight: "chevronRight",
25
25
  children: /*#__PURE__*/ _jsx(Link, {
26
- to: "/workspaces/$wid/settings/agents",
26
+ to: "/w/$workspaceSlug/settings/agents",
27
27
  params: {
28
- wid: workspaceId
28
+ workspaceSlug
29
29
  },
30
30
  children: "Configure Agents"
31
31
  })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/workflow-run-view/agent-config-failure-callout.tsx"],"sourcesContent":["import {\n Alert,\n AlertActions,\n AlertContent,\n AlertDescription,\n AlertTitle,\n} from '@shipfox/react-ui/alert';\nimport {Button} from '@shipfox/react-ui/button';\nimport {Link} from '@tanstack/react-router';\nimport type {AgentStepConfig, StepError} from '#core/workflow-run.js';\n\nexport function AgentConfigFailureCallout({\n workspaceId,\n config,\n error,\n}: {\n workspaceId: string;\n config: AgentStepConfig | null;\n error: StepError | null;\n}) {\n const copy = agentConfigFailureCopy(config, error);\n\n return (\n <Alert variant=\"warning\" animated={false} className=\"px-10 py-8\">\n <AlertContent>\n <AlertTitle>{copy.title}</AlertTitle>\n <AlertDescription>{copy.description}</AlertDescription>\n {copy.showProviderCta ? (\n <AlertActions>\n <Button asChild size=\"2xs\" variant=\"secondary\" iconRight=\"chevronRight\">\n <Link to=\"/workspaces/$wid/settings/agents\" params={{wid: workspaceId}}>\n Configure Agents\n </Link>\n </Button>\n </AlertActions>\n ) : null}\n </AlertContent>\n </Alert>\n );\n}\n\nfunction agentConfigFailureCopy(\n config: AgentStepConfig | null,\n error: StepError | null,\n): {title: string; description: string; showProviderCta: boolean} {\n const provider = configValue(config?.provider, 'the selected provider');\n const model = configValue(config?.model, 'the selected model');\n\n switch (error?.agentConfigIssue) {\n case 'provider_not_configured':\n return {\n title: `Configure credentials for ${provider}`,\n description: `This step uses ${provider}, but no workspace credentials are configured for that model provider. Configure ${provider} in Agents, then re-run the workflow.`,\n showProviderCta: true,\n };\n case 'credentials_invalid':\n return {\n title: `Update credentials for ${provider}`,\n description: `This step uses ${provider}, but the saved credentials could not be used. Reconfigure ${provider} in Agents, then re-run the workflow.`,\n showProviderCta: true,\n };\n case 'provider_unsupported':\n return {\n title: `Choose a supported model provider`,\n description: `This step references ${provider}, which is not available to the agent runner. Update the workflow to use a supported provider, then re-run it.`,\n showProviderCta: false,\n };\n case 'model_unavailable':\n return {\n title: `Choose an available model`,\n description: `This step uses ${model} with ${provider}, but that model is not available for the provider. Update the model or provider in the workflow, then re-run it.`,\n showProviderCta: false,\n };\n case 'step_config_invalid':\n return {\n title: \"Fix this step's agent settings\",\n description:\n 'Make sure the step has a prompt, provider, model, and thinking value, then re-run the workflow.',\n showProviderCta: false,\n };\n case undefined:\n return {\n title: \"We couldn't load the agent configuration for this step\",\n description:\n 'Make sure the step has a prompt, provider, model, and thinking value. Then configure credentials for the model provider in Agents and re-run the workflow.',\n showProviderCta: true,\n };\n }\n}\n\nfunction configValue(value: string | null | undefined, fallback: string): string {\n return value ?? fallback;\n}\n"],"names":["Alert","AlertActions","AlertContent","AlertDescription","AlertTitle","Button","Link","AgentConfigFailureCallout","workspaceId","config","error","copy","agentConfigFailureCopy","variant","animated","className","title","description","showProviderCta","asChild","size","iconRight","to","params","wid","provider","configValue","model","agentConfigIssue","undefined","value","fallback"],"mappings":";AAAA,SACEA,KAAK,EACLC,YAAY,EACZC,YAAY,EACZC,gBAAgB,EAChBC,UAAU,QACL,0BAA0B;AACjC,SAAQC,MAAM,QAAO,2BAA2B;AAChD,SAAQC,IAAI,QAAO,yBAAyB;AAG5C,OAAO,SAASC,0BAA0B,EACxCC,WAAW,EACXC,MAAM,EACNC,KAAK,EAKN;IACC,MAAMC,OAAOC,uBAAuBH,QAAQC;IAE5C,qBACE,KAACV;QAAMa,SAAQ;QAAUC,UAAU;QAAOC,WAAU;kBAClD,cAAA,MAACb;;8BACC,KAACE;8BAAYO,KAAKK,KAAK;;8BACvB,KAACb;8BAAkBQ,KAAKM,WAAW;;gBAClCN,KAAKO,eAAe,iBACnB,KAACjB;8BACC,cAAA,KAACI;wBAAOc,OAAO;wBAACC,MAAK;wBAAMP,SAAQ;wBAAYQ,WAAU;kCACvD,cAAA,KAACf;4BAAKgB,IAAG;4BAAmCC,QAAQ;gCAACC,KAAKhB;4BAAW;sCAAG;;;qBAK1E;;;;AAIZ;AAEA,SAASI,uBACPH,MAA8B,EAC9BC,KAAuB;IAEvB,MAAMe,WAAWC,YAAYjB,QAAQgB,UAAU;IAC/C,MAAME,QAAQD,YAAYjB,QAAQkB,OAAO;IAEzC,OAAQjB,OAAOkB;QACb,KAAK;YACH,OAAO;gBACLZ,OAAO,CAAC,0BAA0B,EAAES,UAAU;gBAC9CR,aAAa,CAAC,eAAe,EAAEQ,SAAS,iFAAiF,EAAEA,SAAS,qCAAqC,CAAC;gBAC1KP,iBAAiB;YACnB;QACF,KAAK;YACH,OAAO;gBACLF,OAAO,CAAC,uBAAuB,EAAES,UAAU;gBAC3CR,aAAa,CAAC,eAAe,EAAEQ,SAAS,2DAA2D,EAAEA,SAAS,qCAAqC,CAAC;gBACpJP,iBAAiB;YACnB;QACF,KAAK;YACH,OAAO;gBACLF,OAAO,CAAC,iCAAiC,CAAC;gBAC1CC,aAAa,CAAC,qBAAqB,EAAEQ,SAAS,8GAA8G,CAAC;gBAC7JP,iBAAiB;YACnB;QACF,KAAK;YACH,OAAO;gBACLF,OAAO,CAAC,yBAAyB,CAAC;gBAClCC,aAAa,CAAC,eAAe,EAAEU,MAAM,MAAM,EAAEF,SAAS,iHAAiH,CAAC;gBACxKP,iBAAiB;YACnB;QACF,KAAK;YACH,OAAO;gBACLF,OAAO;gBACPC,aACE;gBACFC,iBAAiB;YACnB;QACF,KAAKW;YACH,OAAO;gBACLb,OAAO;gBACPC,aACE;gBACFC,iBAAiB;YACnB;IACJ;AACF;AAEA,SAASQ,YAAYI,KAAgC,EAAEC,QAAgB;IACrE,OAAOD,SAASC;AAClB"}
1
+ {"version":3,"sources":["../../../src/components/workflow-run-view/agent-config-failure-callout.tsx"],"sourcesContent":["import {\n Alert,\n AlertActions,\n AlertContent,\n AlertDescription,\n AlertTitle,\n} from '@shipfox/react-ui/alert';\nimport {Button} from '@shipfox/react-ui/button';\nimport {Link} from '@tanstack/react-router';\nimport type {AgentStepConfig, StepError} from '#core/workflow-run.js';\n\nexport function AgentConfigFailureCallout({\n workspaceSlug,\n config,\n error,\n}: {\n workspaceSlug?: string | undefined;\n config: AgentStepConfig | null;\n error: StepError | null;\n}) {\n const copy = agentConfigFailureCopy(config, error);\n\n return (\n <Alert variant=\"warning\" animated={false} className=\"px-10 py-8\">\n <AlertContent>\n <AlertTitle>{copy.title}</AlertTitle>\n <AlertDescription>{copy.description}</AlertDescription>\n {copy.showProviderCta && workspaceSlug ? (\n <AlertActions>\n <Button asChild size=\"2xs\" variant=\"secondary\" iconRight=\"chevronRight\">\n <Link to=\"/w/$workspaceSlug/settings/agents\" params={{workspaceSlug}}>\n Configure Agents\n </Link>\n </Button>\n </AlertActions>\n ) : null}\n </AlertContent>\n </Alert>\n );\n}\n\nfunction agentConfigFailureCopy(\n config: AgentStepConfig | null,\n error: StepError | null,\n): {title: string; description: string; showProviderCta: boolean} {\n const provider = configValue(config?.provider, 'the selected provider');\n const model = configValue(config?.model, 'the selected model');\n\n switch (error?.agentConfigIssue) {\n case 'provider_not_configured':\n return {\n title: `Configure credentials for ${provider}`,\n description: `This step uses ${provider}, but no workspace credentials are configured for that model provider. Configure ${provider} in Agents, then re-run the workflow.`,\n showProviderCta: true,\n };\n case 'credentials_invalid':\n return {\n title: `Update credentials for ${provider}`,\n description: `This step uses ${provider}, but the saved credentials could not be used. Reconfigure ${provider} in Agents, then re-run the workflow.`,\n showProviderCta: true,\n };\n case 'provider_unsupported':\n return {\n title: `Choose a supported model provider`,\n description: `This step references ${provider}, which is not available to the agent runner. Update the workflow to use a supported provider, then re-run it.`,\n showProviderCta: false,\n };\n case 'model_unavailable':\n return {\n title: `Choose an available model`,\n description: `This step uses ${model} with ${provider}, but that model is not available for the provider. Update the model or provider in the workflow, then re-run it.`,\n showProviderCta: false,\n };\n case 'step_config_invalid':\n return {\n title: \"Fix this step's agent settings\",\n description:\n 'Make sure the step has a prompt, provider, model, and thinking value, then re-run the workflow.',\n showProviderCta: false,\n };\n case undefined:\n return {\n title: \"We couldn't load the agent configuration for this step\",\n description:\n 'Make sure the step has a prompt, provider, model, and thinking value. Then configure credentials for the model provider in Agents and re-run the workflow.',\n showProviderCta: true,\n };\n }\n}\n\nfunction configValue(value: string | null | undefined, fallback: string): string {\n return value ?? fallback;\n}\n"],"names":["Alert","AlertActions","AlertContent","AlertDescription","AlertTitle","Button","Link","AgentConfigFailureCallout","workspaceSlug","config","error","copy","agentConfigFailureCopy","variant","animated","className","title","description","showProviderCta","asChild","size","iconRight","to","params","provider","configValue","model","agentConfigIssue","undefined","value","fallback"],"mappings":";AAAA,SACEA,KAAK,EACLC,YAAY,EACZC,YAAY,EACZC,gBAAgB,EAChBC,UAAU,QACL,0BAA0B;AACjC,SAAQC,MAAM,QAAO,2BAA2B;AAChD,SAAQC,IAAI,QAAO,yBAAyB;AAG5C,OAAO,SAASC,0BAA0B,EACxCC,aAAa,EACbC,MAAM,EACNC,KAAK,EAKN;IACC,MAAMC,OAAOC,uBAAuBH,QAAQC;IAE5C,qBACE,KAACV;QAAMa,SAAQ;QAAUC,UAAU;QAAOC,WAAU;kBAClD,cAAA,MAACb;;8BACC,KAACE;8BAAYO,KAAKK,KAAK;;8BACvB,KAACb;8BAAkBQ,KAAKM,WAAW;;gBAClCN,KAAKO,eAAe,IAAIV,8BACvB,KAACP;8BACC,cAAA,KAACI;wBAAOc,OAAO;wBAACC,MAAK;wBAAMP,SAAQ;wBAAYQ,WAAU;kCACvD,cAAA,KAACf;4BAAKgB,IAAG;4BAAoCC,QAAQ;gCAACf;4BAAa;sCAAG;;;qBAKxE;;;;AAIZ;AAEA,SAASI,uBACPH,MAA8B,EAC9BC,KAAuB;IAEvB,MAAMc,WAAWC,YAAYhB,QAAQe,UAAU;IAC/C,MAAME,QAAQD,YAAYhB,QAAQiB,OAAO;IAEzC,OAAQhB,OAAOiB;QACb,KAAK;YACH,OAAO;gBACLX,OAAO,CAAC,0BAA0B,EAAEQ,UAAU;gBAC9CP,aAAa,CAAC,eAAe,EAAEO,SAAS,iFAAiF,EAAEA,SAAS,qCAAqC,CAAC;gBAC1KN,iBAAiB;YACnB;QACF,KAAK;YACH,OAAO;gBACLF,OAAO,CAAC,uBAAuB,EAAEQ,UAAU;gBAC3CP,aAAa,CAAC,eAAe,EAAEO,SAAS,2DAA2D,EAAEA,SAAS,qCAAqC,CAAC;gBACpJN,iBAAiB;YACnB;QACF,KAAK;YACH,OAAO;gBACLF,OAAO,CAAC,iCAAiC,CAAC;gBAC1CC,aAAa,CAAC,qBAAqB,EAAEO,SAAS,8GAA8G,CAAC;gBAC7JN,iBAAiB;YACnB;QACF,KAAK;YACH,OAAO;gBACLF,OAAO,CAAC,yBAAyB,CAAC;gBAClCC,aAAa,CAAC,eAAe,EAAES,MAAM,MAAM,EAAEF,SAAS,iHAAiH,CAAC;gBACxKN,iBAAiB;YACnB;QACF,KAAK;YACH,OAAO;gBACLF,OAAO;gBACPC,aACE;gBACFC,iBAAiB;YACnB;QACF,KAAKU;YACH,OAAO;gBACLZ,OAAO;gBACPC,aACE;gBACFC,iBAAiB;YACnB;IACJ;AACF;AAEA,SAASO,YAAYI,KAAgC,EAAEC,QAAgB;IACrE,OAAOD,SAASC;AAClB"}
@@ -1,8 +1,8 @@
1
1
  import type { ReactNode } from 'react';
2
2
  import { type Job, type JobExecution, type StepSourceLocation } from '#core/workflow-run.js';
3
3
  import { type StepExpandedContext } from '../step-list/index.js';
4
- export declare function JobCard({ workspaceId, job, selectedJobExecution, selectedAttemptId, onSelectedJobExecutionChange, onSelectedAttemptChange, renderExpandedStep, sourcePanelId, sourceAvailable, focusedSourceStepId, onOpenStepSource, }: {
5
- workspaceId: string;
4
+ export declare function JobCard({ workspaceSlug, job, selectedJobExecution, selectedAttemptId, onSelectedJobExecutionChange, onSelectedAttemptChange, renderExpandedStep, sourcePanelId, sourceAvailable, focusedSourceStepId, onOpenStepSource, }: {
5
+ workspaceSlug?: string | undefined;
6
6
  job: Job;
7
7
  selectedJobExecution: JobExecution | undefined;
8
8
  selectedAttemptId: string | null | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"job-card.d.ts","sourceRoot":"","sources":["../../../src/components/workflow-run-view/job-card.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,OAAO,CAAC;AAGrC,OAAO,EAEL,KAAK,GAAG,EACR,KAAK,YAAY,EAKjB,KAAK,kBAAkB,EAIxB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAC,KAAK,mBAAmB,EAAoC,MAAM,uBAAuB,CAAC;AAelG,wBAAgB,OAAO,CAAC,EACtB,WAAW,EACX,GAAG,EACH,oBAAoB,EACpB,iBAAiB,EACjB,4BAA4B,EAC5B,uBAAuB,EACvB,kBAAkB,EAClB,aAAa,EACb,eAAe,EACf,mBAAmB,EACnB,gBAAgB,GACjB,EAAE;IACD,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,GAAG,CAAC;IACT,oBAAoB,EAAE,YAAY,GAAG,SAAS,CAAC;IAC/C,iBAAiB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC7C,4BAA4B,EAAE,CAAC,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IACzF,uBAAuB,EAAE,CAAC,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC/E,kBAAkB,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,mBAAmB,KAAK,SAAS,CAAC,GAAG,SAAS,CAAC;IAC/E,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,eAAe,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACtC,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAChD,gBAAgB,CAAC,EACb,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,kBAAkB,EAAE,OAAO,EAAE,iBAAiB,GAAG,IAAI,KAAK,IAAI,CAAC,GAC3F,SAAS,CAAC;CACf,+BAkIA"}
1
+ {"version":3,"file":"job-card.d.ts","sourceRoot":"","sources":["../../../src/components/workflow-run-view/job-card.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,OAAO,CAAC;AAGrC,OAAO,EAKL,KAAK,GAAG,EAER,KAAK,YAAY,EAKjB,KAAK,kBAAkB,EAIxB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAC,KAAK,mBAAmB,EAAoC,MAAM,uBAAuB,CAAC;AAiBlG,wBAAgB,OAAO,CAAC,EACtB,aAAa,EACb,GAAG,EACH,oBAAoB,EACpB,iBAAiB,EACjB,4BAA4B,EAC5B,uBAAuB,EACvB,kBAAkB,EAClB,aAAa,EACb,eAAe,EACf,mBAAmB,EACnB,gBAAgB,GACjB,EAAE;IACD,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,GAAG,EAAE,GAAG,CAAC;IACT,oBAAoB,EAAE,YAAY,GAAG,SAAS,CAAC;IAC/C,iBAAiB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC7C,4BAA4B,EAAE,CAAC,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IACzF,uBAAuB,EAAE,CAAC,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC/E,kBAAkB,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,mBAAmB,KAAK,SAAS,CAAC,GAAG,SAAS,CAAC;IAC/E,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,eAAe,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACtC,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAChD,gBAAgB,CAAC,EACb,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,kBAAkB,EAAE,OAAO,EAAE,iBAAiB,GAAG,IAAI,KAAK,IAAI,CAAC,GAC3F,SAAS,CAAC;CACf,+BAyIA"}
@@ -10,25 +10,30 @@ import { Tooltip, TooltipContent, TooltipTrigger } from '@shipfox/react-ui/toolt
10
10
  import { Text } from '@shipfox/react-ui/typography';
11
11
  import { Fragment, useId, useRef, useState } from 'react';
12
12
  import { getWorkflowStatusVisual } from '#components/workflow-status/status-visuals.js';
13
- import { AGENT_CONFIG_ISSUES, STEP_ERROR_REASONS, WORKFLOW_JOB_STATUSES, workflowRunTriggerDisplayLabel, workflowRunTriggerLabel } from '#core/workflow-run.js';
13
+ import { AGENT_CONFIG_ISSUES, defaultJobExecution, deriveJobDisplayStatus, deriveJobExecutionDisplayStatus, STEP_ERROR_REASONS, WORKFLOW_JOB_STATUSES, workflowRunTriggerDisplayLabel, workflowRunTriggerLabel } from '#core/workflow-run.js';
14
14
  import { StepList } from '../step-list/index.js';
15
15
  import { AgentConfigFailureCallout } from './agent-config-failure-callout.js';
16
16
  import { JobExecutionSwitcher } from './job-execution-switcher.js';
17
17
  import { formatJobExecutionTime, JobExecutionTimeText } from './job-execution-time-text.js';
18
18
  import { StepAttemptLogPanel } from './step-attempt-log-panel.js';
19
- const STATUS_BADGE_LABEL_WIDTH_CH = Math.max(...WORKFLOW_JOB_STATUSES.map((status)=>getWorkflowStatusVisual(status).label.length));
20
- export function JobCard({ workspaceId, job, selectedJobExecution, selectedAttemptId, onSelectedJobExecutionChange, onSelectedAttemptChange, renderExpandedStep, sourcePanelId, sourceAvailable, focusedSourceStepId, onOpenStepSource }) {
19
+ const STATUS_BADGE_LABEL_WIDTH_CH = Math.max(...[
20
+ ...WORKFLOW_JOB_STATUSES,
21
+ 'listening'
22
+ ].map((status)=>getWorkflowStatusVisual(status).label.length));
23
+ export function JobCard({ workspaceSlug, job, selectedJobExecution, selectedAttemptId, onSelectedJobExecutionChange, onSelectedAttemptChange, renderExpandedStep, sourcePanelId, sourceAvailable, focusedSourceStepId, onOpenStepSource }) {
21
24
  const titleId = useId();
22
25
  const sourceButtonRef = useRef(null);
23
26
  const [localSelectedAttempt, setLocalSelectedAttempt] = useState({
24
27
  jobExecutionId: undefined,
25
28
  attemptId: null
26
29
  });
27
- const selectedExecutionStatus = selectedJobExecution?.status ?? job.status;
30
+ const title = selectedJobExecution?.displayName ?? job.displayName;
31
+ const isNonDefaultExecutionSelected = selectedJobExecution !== undefined && selectedJobExecution.id !== defaultJobExecution(job)?.id;
32
+ const selectedExecutionStatus = isNonDefaultExecutionSelected ? deriveJobExecutionDisplayStatus(selectedJobExecution) : deriveJobDisplayStatus(job);
28
33
  const effectiveSelectedAttemptId = selectedAttemptId === undefined && localSelectedAttempt.jobExecutionId === selectedJobExecution?.id ? localSelectedAttempt.attemptId : selectedAttemptId;
29
34
  const selectedSourceAction = selectedStepSourceAction(selectedJobExecution, effectiveSelectedAttemptId);
30
35
  const defaultRenderExpandedStep = ({ step, stepId, attempt, attemptError, attemptStatus, carriedOver })=>carriedOver ? /*#__PURE__*/ _jsx(CarriedOverStepPanel, {}) : /*#__PURE__*/ _jsx(StepAttemptDetailPanel, {
31
- workspaceId: workspaceId,
36
+ workspaceSlug: workspaceSlug,
32
37
  step: step,
33
38
  stepId: stepId,
34
39
  attempt: attempt,
@@ -62,7 +67,7 @@ export function JobCard({ workspaceId, job, selectedJobExecution, selectedAttemp
62
67
  size: "sm",
63
68
  bold: true,
64
69
  className: "sr-only",
65
- children: job.displayName
70
+ children: title
66
71
  }),
67
72
  /*#__PURE__*/ _jsxs("div", {
68
73
  className: "flex min-w-0 items-center gap-8",
@@ -85,13 +90,16 @@ export function JobCard({ workspaceId, job, selectedJobExecution, selectedAttemp
85
90
  /*#__PURE__*/ _jsx(JobStatusBadge, {
86
91
  status: selectedExecutionStatus
87
92
  }),
88
- /*#__PURE__*/ _jsx(Text, {
89
- as: "h2",
90
- id: titleId,
91
- size: "sm",
92
- bold: true,
93
- className: "min-w-0 truncate text-foreground-neutral-base",
94
- children: job.displayName
93
+ /*#__PURE__*/ _jsx("div", {
94
+ className: "flex min-w-0 items-center gap-8",
95
+ children: /*#__PURE__*/ _jsx(Text, {
96
+ as: "h2",
97
+ id: titleId,
98
+ size: "sm",
99
+ bold: true,
100
+ className: "min-w-0 truncate text-foreground-neutral-base",
101
+ children: title
102
+ })
95
103
  })
96
104
  ]
97
105
  }),
@@ -200,7 +208,8 @@ function JobExecutionMetadata({ execution }) {
200
208
  }) : /*#__PURE__*/ _jsx(JobExecutionMetadataItem, {
201
209
  icon: item.icon,
202
210
  kind: item.kind,
203
- time: item.time
211
+ time: item.time,
212
+ displayStatus: deriveJobExecutionDisplayStatus(execution)
204
213
  })
205
214
  ]
206
215
  }, item.key))
@@ -258,9 +267,9 @@ function JobExecutionTriggerMetadata({ execution }) {
258
267
  ]
259
268
  });
260
269
  }
261
- function JobExecutionMetadataItem({ icon, kind, time }) {
270
+ function JobExecutionMetadataItem({ icon, kind, time, displayStatus }) {
262
271
  useTimeTick();
263
- const tooltip = `${jobExecutionTimeVerb(kind, time)} for ${formatJobExecutionTime(time)}`;
272
+ const tooltip = `${jobExecutionTimeVerb(kind, time, displayStatus)} for ${formatJobExecutionTime(time)}`;
264
273
  return /*#__PURE__*/ _jsxs(Tooltip, {
265
274
  children: [
266
275
  /*#__PURE__*/ _jsx(TooltipTrigger, {
@@ -294,9 +303,11 @@ function JobExecutionMetadataItem({ icon, kind, time }) {
294
303
  ]
295
304
  });
296
305
  }
297
- function jobExecutionTimeVerb(kind, time) {
298
- if (kind === 'queue') return time.state === 'live' ? 'Queuing' : 'Queued';
299
- return time.state === 'live' ? 'Running' : 'Ran';
306
+ function jobExecutionTimeVerb(kind, time, displayStatus) {
307
+ if (kind === 'queue') return time.state === 'live' ? 'Queueing' : 'Queued';
308
+ if (time.state !== 'live') return 'Ran';
309
+ if (displayStatus === 'running') return 'Running';
310
+ return displayStatus === 'pending' ? 'Runner assigned' : 'Execution elapsed';
300
311
  }
301
312
  function MetadataSeparator() {
302
313
  return /*#__PURE__*/ _jsx("span", {
@@ -317,13 +328,13 @@ function selectedStepSourceAction(jobExecution, selectedAttemptId) {
317
328
  }
318
329
  return null;
319
330
  }
320
- function StepAttemptDetailPanel({ workspaceId, step, stepId, attempt, attemptError, attemptStatus }) {
331
+ function StepAttemptDetailPanel({ workspaceSlug, step, stepId, attempt, attemptError, attemptStatus }) {
321
332
  const selectedAttemptError = toSelectedAttemptError(step, attemptError) ?? step.error;
322
333
  return /*#__PURE__*/ _jsxs("div", {
323
334
  className: "flex min-w-0 flex-col gap-10",
324
335
  children: [
325
336
  isAgentConfigFailure(step, selectedAttemptError) ? /*#__PURE__*/ _jsx(AgentConfigFailureCallout, {
326
- workspaceId: workspaceId,
337
+ workspaceSlug: workspaceSlug,
327
338
  config: step.agentConfig,
328
339
  error: selectedAttemptError
329
340
  }) : null,
@@ -350,7 +361,7 @@ function toSelectedAttemptError(step, error) {
350
361
  signal: typeof error.signal === 'string' ? error.signal : undefined,
351
362
  reason: resolvedReason,
352
363
  agentConfigIssue,
353
- category: step.type === 'setup' ? 'setup' : 'user'
364
+ category: step.type === 'setup' || step.type === 'checkout' ? 'setup' : 'user'
354
365
  };
355
366
  }
356
367
  function isAgentConfigFailure(step, error) {
@@ -364,32 +375,40 @@ function emptyStateForJob(job, jobExecution) {
364
375
  status: 'succeeded'
365
376
  };
366
377
  }
367
- if (jobExecution.status === 'pending') {
378
+ const displayStatus = job.mode === 'listening' ? deriveJobExecutionDisplayStatus(jobExecution) : deriveJobDisplayStatus(job);
379
+ if (jobExecution.status === 'running' && displayStatus === 'pending') {
380
+ return {
381
+ title: 'Runner preparing job',
382
+ description: 'A runner is assigned. Steps will appear here when work begins.',
383
+ status: displayStatus
384
+ };
385
+ }
386
+ if (displayStatus === 'pending') {
368
387
  return {
369
388
  title: 'Waiting for this job to start',
370
389
  description: 'Steps will appear here once the job starts.',
371
- status: jobExecution.status
390
+ status: displayStatus
372
391
  };
373
392
  }
374
- if (jobExecution.status === 'running') {
393
+ if (displayStatus === 'running') {
375
394
  return {
376
395
  title: 'Waiting for the first step',
377
- description: 'This job is running, but no steps have started yet.',
378
- status: jobExecution.status
396
+ description: 'The first running step will appear here shortly.',
397
+ status: displayStatus
379
398
  };
380
399
  }
381
- if (jobExecution.status === 'cancelled') {
400
+ if (displayStatus === 'cancelled') {
382
401
  return {
383
402
  title: 'Cancelled before start',
384
403
  description: 'This job was cancelled before any step started.',
385
- status: jobExecution.status
404
+ status: displayStatus
386
405
  };
387
406
  }
388
- if (jobExecution.status === 'succeeded' || jobExecution.status === 'failed') {
407
+ if (displayStatus === 'succeeded' || displayStatus === 'failed') {
389
408
  return {
390
409
  title: 'No steps recorded',
391
410
  description: `Execution #${jobExecution.sequence} finished without recorded steps.`,
392
- status: jobExecution.status
411
+ status: displayStatus
393
412
  };
394
413
  }
395
414
  return undefined;
@@ -406,7 +425,7 @@ function emptyStateForMissingExecution(job) {
406
425
  return {
407
426
  title: 'Waiting for trigger events',
408
427
  description: 'Matching trigger events will create job executions here.',
409
- status: 'running'
428
+ status: deriveJobDisplayStatus(job)
410
429
  };
411
430
  }
412
431
  if (job.mode === 'listening' && job.listenerStatus === 'resolved') {