@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
@@ -1,33 +1,32 @@
1
1
  import type { QueryLoadErrorQuery } from '@shipfox/client-ui';
2
2
  import type { WorkflowRunListItem } from '#core/workflow-run.js';
3
- export type WorkflowRunListStatusFilter = 'all' | 'failed' | 'running';
4
- export interface WorkflowRunListProps {
5
- workspaceId: string;
6
- projectId: string;
7
- selectedWorkflowRunId?: string | undefined;
8
- className?: string | undefined;
9
- search?: string;
10
- statusFilter?: WorkflowRunListStatusFilter;
11
- onFiltersChange?: (filters: {
12
- search?: string;
13
- status?: WorkflowRunListStatusFilter;
14
- }) => void;
15
- }
3
+ import type { WorkflowRunFilterPatch, WorkflowRunsSearch } from '#routes/inputs.js';
16
4
  export type WorkflowRunListQuery = QueryLoadErrorQuery & {
17
5
  isPending: boolean;
18
6
  };
19
- export interface WorkflowRunListViewProps {
7
+ interface WorkflowRunListCommonProps {
8
+ workspaceSlug?: string | undefined;
9
+ projectSlug?: string | undefined;
10
+ className?: string | undefined;
11
+ /**
12
+ * The parsed URL search. Pair with `onFiltersChange` to keep it in the URL; omit the
13
+ * handler and the view holds filter state itself, which is what stories and isolated tests
14
+ * mount against.
15
+ */
16
+ search?: WorkflowRunsSearch;
17
+ onFiltersChange?: (patch: WorkflowRunFilterPatch) => void;
18
+ onClearFilters?: () => void;
19
+ hasNextPage?: boolean;
20
+ isFetchingNextPage?: boolean;
21
+ isFetchNextPageError?: boolean;
22
+ onLoadMore?: () => void;
23
+ }
24
+ export interface WorkflowRunListProps extends WorkflowRunListCommonProps {
25
+ projectId: string;
26
+ }
27
+ export interface WorkflowRunListViewProps extends WorkflowRunListCommonProps {
20
28
  runs: WorkflowRunListItem[];
21
29
  query: WorkflowRunListQuery;
22
- workspaceId: string;
23
- projectId: string;
24
- selectedWorkflowRunId?: string | undefined;
25
- className?: string | undefined;
26
- search?: string;
27
- statusFilter?: WorkflowRunListStatusFilter;
28
- onFiltersChange?: (filters: {
29
- search?: string;
30
- status?: WorkflowRunListStatusFilter;
31
- }) => void;
32
30
  }
31
+ export {};
33
32
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/workflow-run-list/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,oBAAoB,CAAC;AAC5D,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,uBAAuB,CAAC;AAE/D,MAAM,MAAM,2BAA2B,GAAG,KAAK,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEvE,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,qBAAqB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,2BAA2B,CAAC;IAC3C,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,2BAA2B,CAAA;KAAC,KAAK,IAAI,CAAC;CAC9F;AAED,MAAM,MAAM,oBAAoB,GAAG,mBAAmB,GAAG;IAAC,SAAS,EAAE,OAAO,CAAA;CAAC,CAAC;AAE9E,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,mBAAmB,EAAE,CAAC;IAC5B,KAAK,EAAE,oBAAoB,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,qBAAqB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,2BAA2B,CAAC;IAC3C,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,2BAA2B,CAAA;KAAC,KAAK,IAAI,CAAC;CAC9F"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/workflow-run-list/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,oBAAoB,CAAC;AAC5D,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,uBAAuB,CAAC;AAC/D,OAAO,KAAK,EAAC,sBAAsB,EAAE,kBAAkB,EAAC,MAAM,mBAAmB,CAAC;AAElF,MAAM,MAAM,oBAAoB,GAAG,mBAAmB,GAAG;IAAC,SAAS,EAAE,OAAO,CAAA;CAAC,CAAC;AAE9E,UAAU,0BAA0B;IAClC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B;;;;OAIG;IACH,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,IAAI,CAAC;IAC1D,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,oBAAqB,SAAQ,0BAA0B;IACtE,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,wBAAyB,SAAQ,0BAA0B;IAC1E,IAAI,EAAE,mBAAmB,EAAE,CAAC;IAC5B,KAAK,EAAE,oBAAoB,CAAC;CAC7B"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/workflow-run-list/types.ts"],"sourcesContent":["import type {QueryLoadErrorQuery} from '@shipfox/client-ui';\nimport type {WorkflowRunListItem} from '#core/workflow-run.js';\n\nexport type WorkflowRunListStatusFilter = 'all' | 'failed' | 'running';\n\nexport interface WorkflowRunListProps {\n workspaceId: string;\n projectId: string;\n selectedWorkflowRunId?: string | undefined;\n className?: string | undefined;\n search?: string;\n statusFilter?: WorkflowRunListStatusFilter;\n onFiltersChange?: (filters: {search?: string; status?: WorkflowRunListStatusFilter}) => void;\n}\n\nexport type WorkflowRunListQuery = QueryLoadErrorQuery & {isPending: boolean};\n\nexport interface WorkflowRunListViewProps {\n runs: WorkflowRunListItem[];\n query: WorkflowRunListQuery;\n workspaceId: string;\n projectId: string;\n selectedWorkflowRunId?: string | undefined;\n className?: string | undefined;\n search?: string;\n statusFilter?: WorkflowRunListStatusFilter;\n onFiltersChange?: (filters: {search?: string; status?: WorkflowRunListStatusFilter}) => void;\n}\n"],"names":[],"mappings":"AAiBA,WAUC"}
1
+ {"version":3,"sources":["../../../src/components/workflow-run-list/types.ts"],"sourcesContent":["import type {QueryLoadErrorQuery} from '@shipfox/client-ui';\nimport type {WorkflowRunListItem} from '#core/workflow-run.js';\nimport type {WorkflowRunFilterPatch, WorkflowRunsSearch} from '#routes/inputs.js';\n\nexport type WorkflowRunListQuery = QueryLoadErrorQuery & {isPending: boolean};\n\ninterface WorkflowRunListCommonProps {\n workspaceSlug?: string | undefined;\n projectSlug?: string | undefined;\n className?: string | undefined;\n /**\n * The parsed URL search. Pair with `onFiltersChange` to keep it in the URL; omit the\n * handler and the view holds filter state itself, which is what stories and isolated tests\n * mount against.\n */\n search?: WorkflowRunsSearch;\n onFiltersChange?: (patch: WorkflowRunFilterPatch) => void;\n onClearFilters?: () => void;\n hasNextPage?: boolean;\n isFetchingNextPage?: boolean;\n isFetchNextPageError?: boolean;\n onLoadMore?: () => void;\n}\n\nexport interface WorkflowRunListProps extends WorkflowRunListCommonProps {\n projectId: string;\n}\n\nexport interface WorkflowRunListViewProps extends WorkflowRunListCommonProps {\n runs: WorkflowRunListItem[];\n query: WorkflowRunListQuery;\n}\n"],"names":[],"mappings":"AA4BA,WAGC"}
@@ -0,0 +1,22 @@
1
+ export interface WorkflowRunFilterOption {
2
+ value: string;
3
+ label: string;
4
+ }
5
+ export interface WorkflowRunFilterMenuProps {
6
+ label: string;
7
+ options: readonly WorkflowRunFilterOption[];
8
+ selected: readonly string[];
9
+ onChange: (next: string[]) => void;
10
+ /** Shown in place of the option list when nothing is loaded to filter by. */
11
+ emptyMessage: string;
12
+ className?: string | undefined;
13
+ }
14
+ /**
15
+ * One multi-select filter.
16
+ *
17
+ * The trigger states its own value rather than only a count, because a toolbar of five
18
+ * buttons that all read "Branch" forces the user to open each one to find out what is on.
19
+ * Checked items keep the menu open: choosing two branches should not cost two round trips.
20
+ */
21
+ export declare function WorkflowRunFilterMenu({ label, options, selected, onChange, emptyMessage, className, }: WorkflowRunFilterMenuProps): import("react").JSX.Element;
22
+ //# sourceMappingURL=workflow-run-filter-menu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflow-run-filter-menu.d.ts","sourceRoot":"","sources":["../../../src/components/workflow-run-list/workflow-run-filter-menu.tsx"],"names":[],"mappings":"AAUA,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,SAAS,uBAAuB,EAAE,CAAC;IAC5C,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACnC,6EAA6E;IAC7E,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,KAAK,EACL,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,SAAS,GACV,EAAE,0BAA0B,+BA8C5B"}
@@ -0,0 +1,68 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Button } from '@shipfox/react-ui/button';
3
+ import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuTrigger } from '@shipfox/react-ui/dropdown-menu';
4
+ import { Text } from '@shipfox/react-ui/typography';
5
+ import { cn } from '@shipfox/react-ui/utils';
6
+ /**
7
+ * One multi-select filter.
8
+ *
9
+ * The trigger states its own value rather than only a count, because a toolbar of five
10
+ * buttons that all read "Branch" forces the user to open each one to find out what is on.
11
+ * Checked items keep the menu open: choosing two branches should not cost two round trips.
12
+ */ export function WorkflowRunFilterMenu({ label, options, selected, onChange, emptyMessage, className }) {
13
+ const active = selected.length > 0;
14
+ const triggerText = triggerLabel(label, options, selected);
15
+ function toggle(value) {
16
+ onChange(selected.includes(value) ? selected.filter((entry)=>entry !== value) : [
17
+ ...selected,
18
+ value
19
+ ]);
20
+ }
21
+ return /*#__PURE__*/ _jsxs(DropdownMenu, {
22
+ children: [
23
+ /*#__PURE__*/ _jsx(DropdownMenuTrigger, {
24
+ asChild: true,
25
+ children: /*#__PURE__*/ _jsx(Button, {
26
+ type: "button",
27
+ variant: "secondary",
28
+ size: "sm",
29
+ iconRight: "arrowDownSLine",
30
+ // Mirrors the visible label so the selected value is not sighted-only; an aria-label
31
+ // replaces the button's contents as its accessible name rather than adding to them.
32
+ "aria-label": `${triggerText} filter`,
33
+ className: cn('max-w-[200px]', !active && 'text-foreground-neutral-subtle', className),
34
+ children: /*#__PURE__*/ _jsx("span", {
35
+ className: "min-w-0 truncate",
36
+ children: triggerText
37
+ })
38
+ })
39
+ }),
40
+ /*#__PURE__*/ _jsx(DropdownMenuContent, {
41
+ align: "start",
42
+ className: "max-h-[320px] w-[240px] overflow-y-auto",
43
+ children: options.length === 0 ? /*#__PURE__*/ _jsx(Text, {
44
+ as: "p",
45
+ size: "xs",
46
+ className: "px-8 py-6 text-foreground-neutral-muted",
47
+ children: emptyMessage
48
+ }) : options.map((option)=>/*#__PURE__*/ _jsx(DropdownMenuCheckboxItem, {
49
+ checked: selected.includes(option.value),
50
+ closeOnSelect: false,
51
+ onSelect: ()=>toggle(option.value),
52
+ children: option.label
53
+ }, option.value))
54
+ })
55
+ ]
56
+ });
57
+ }
58
+ function triggerLabel(label, options, selected) {
59
+ if (selected.length === 0) return label;
60
+ if (selected.length === 1) {
61
+ const [value] = selected;
62
+ const option = options.find((entry)=>entry.value === value);
63
+ return `${label}: ${option?.label ?? value}`;
64
+ }
65
+ return `${label} · ${selected.length}`;
66
+ }
67
+
68
+ //# sourceMappingURL=workflow-run-filter-menu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/workflow-run-list/workflow-run-filter-menu.tsx"],"sourcesContent":["import {Button} from '@shipfox/react-ui/button';\nimport {\n DropdownMenu,\n DropdownMenuCheckboxItem,\n DropdownMenuContent,\n DropdownMenuTrigger,\n} from '@shipfox/react-ui/dropdown-menu';\nimport {Text} from '@shipfox/react-ui/typography';\nimport {cn} from '@shipfox/react-ui/utils';\n\nexport interface WorkflowRunFilterOption {\n value: string;\n label: string;\n}\n\nexport interface WorkflowRunFilterMenuProps {\n label: string;\n options: readonly WorkflowRunFilterOption[];\n selected: readonly string[];\n onChange: (next: string[]) => void;\n /** Shown in place of the option list when nothing is loaded to filter by. */\n emptyMessage: string;\n className?: string | undefined;\n}\n\n/**\n * One multi-select filter.\n *\n * The trigger states its own value rather than only a count, because a toolbar of five\n * buttons that all read \"Branch\" forces the user to open each one to find out what is on.\n * Checked items keep the menu open: choosing two branches should not cost two round trips.\n */\nexport function WorkflowRunFilterMenu({\n label,\n options,\n selected,\n onChange,\n emptyMessage,\n className,\n}: WorkflowRunFilterMenuProps) {\n const active = selected.length > 0;\n const triggerText = triggerLabel(label, options, selected);\n\n function toggle(value: string) {\n onChange(\n selected.includes(value) ? selected.filter((entry) => entry !== value) : [...selected, value],\n );\n }\n\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"sm\"\n iconRight=\"arrowDownSLine\"\n // Mirrors the visible label so the selected value is not sighted-only; an aria-label\n // replaces the button's contents as its accessible name rather than adding to them.\n aria-label={`${triggerText} filter`}\n className={cn('max-w-[200px]', !active && 'text-foreground-neutral-subtle', className)}\n >\n <span className=\"min-w-0 truncate\">{triggerText}</span>\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"max-h-[320px] w-[240px] overflow-y-auto\">\n {options.length === 0 ? (\n <Text as=\"p\" size=\"xs\" className=\"px-8 py-6 text-foreground-neutral-muted\">\n {emptyMessage}\n </Text>\n ) : (\n options.map((option) => (\n <DropdownMenuCheckboxItem\n key={option.value}\n checked={selected.includes(option.value)}\n closeOnSelect={false}\n onSelect={() => toggle(option.value)}\n >\n {option.label}\n </DropdownMenuCheckboxItem>\n ))\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\nfunction triggerLabel(\n label: string,\n options: readonly WorkflowRunFilterOption[],\n selected: readonly string[],\n): string {\n if (selected.length === 0) return label;\n if (selected.length === 1) {\n const [value] = selected;\n const option = options.find((entry) => entry.value === value);\n return `${label}: ${option?.label ?? value}`;\n }\n return `${label} · ${selected.length}`;\n}\n"],"names":["Button","DropdownMenu","DropdownMenuCheckboxItem","DropdownMenuContent","DropdownMenuTrigger","Text","cn","WorkflowRunFilterMenu","label","options","selected","onChange","emptyMessage","className","active","length","triggerText","triggerLabel","toggle","value","includes","filter","entry","asChild","type","variant","size","iconRight","aria-label","span","align","as","map","option","checked","closeOnSelect","onSelect","find"],"mappings":";AAAA,SAAQA,MAAM,QAAO,2BAA2B;AAChD,SACEC,YAAY,EACZC,wBAAwB,EACxBC,mBAAmB,EACnBC,mBAAmB,QACd,kCAAkC;AACzC,SAAQC,IAAI,QAAO,+BAA+B;AAClD,SAAQC,EAAE,QAAO,0BAA0B;AAiB3C;;;;;;CAMC,GACD,OAAO,SAASC,sBAAsB,EACpCC,KAAK,EACLC,OAAO,EACPC,QAAQ,EACRC,QAAQ,EACRC,YAAY,EACZC,SAAS,EACkB;IAC3B,MAAMC,SAASJ,SAASK,MAAM,GAAG;IACjC,MAAMC,cAAcC,aAAaT,OAAOC,SAASC;IAEjD,SAASQ,OAAOC,KAAa;QAC3BR,SACED,SAASU,QAAQ,CAACD,SAAST,SAASW,MAAM,CAAC,CAACC,QAAUA,UAAUH,SAAS;eAAIT;YAAUS;SAAM;IAEjG;IAEA,qBACE,MAAClB;;0BACC,KAACG;gBAAoBmB,OAAO;0BAC1B,cAAA,KAACvB;oBACCwB,MAAK;oBACLC,SAAQ;oBACRC,MAAK;oBACLC,WAAU;oBACV,qFAAqF;oBACrF,oFAAoF;oBACpFC,cAAY,GAAGZ,YAAY,OAAO,CAAC;oBACnCH,WAAWP,GAAG,iBAAiB,CAACQ,UAAU,kCAAkCD;8BAE5E,cAAA,KAACgB;wBAAKhB,WAAU;kCAAoBG;;;;0BAGxC,KAACb;gBAAoB2B,OAAM;gBAAQjB,WAAU;0BAC1CJ,QAAQM,MAAM,KAAK,kBAClB,KAACV;oBAAK0B,IAAG;oBAAIL,MAAK;oBAAKb,WAAU;8BAC9BD;qBAGHH,QAAQuB,GAAG,CAAC,CAACC,uBACX,KAAC/B;wBAECgC,SAASxB,SAASU,QAAQ,CAACa,OAAOd,KAAK;wBACvCgB,eAAe;wBACfC,UAAU,IAAMlB,OAAOe,OAAOd,KAAK;kCAElCc,OAAOzB,KAAK;uBALRyB,OAAOd,KAAK;;;;AAY/B;AAEA,SAASF,aACPT,KAAa,EACbC,OAA2C,EAC3CC,QAA2B;IAE3B,IAAIA,SAASK,MAAM,KAAK,GAAG,OAAOP;IAClC,IAAIE,SAASK,MAAM,KAAK,GAAG;QACzB,MAAM,CAACI,MAAM,GAAGT;QAChB,MAAMuB,SAASxB,QAAQ4B,IAAI,CAAC,CAACf,QAAUA,MAAMH,KAAK,KAAKA;QACvD,OAAO,GAAGX,MAAM,EAAE,EAAEyB,QAAQzB,SAASW,OAAO;IAC9C;IACA,OAAO,GAAGX,MAAM,GAAG,EAAEE,SAASK,MAAM,EAAE;AACxC"}
@@ -0,0 +1,18 @@
1
+ import { type WorkflowRunFilterPatch, type WorkflowRunsSearch } from '#routes/inputs.js';
2
+ import type { WorkflowRunFacets } from './run-display.js';
3
+ export interface WorkflowRunFiltersProps {
4
+ search: WorkflowRunsSearch;
5
+ facets: WorkflowRunFacets;
6
+ onChange: (patch: WorkflowRunFilterPatch) => void;
7
+ onClear: () => void;
8
+ hasActiveFilters: boolean;
9
+ }
10
+ /**
11
+ * The run list filter row.
12
+ *
13
+ * Inline from `md` up, and behind a sheet below it, where a five-control toolbar would eat
14
+ * the viewport the list is supposed to fill. Both layouts render the same controls, so the
15
+ * narrow surface is the full filter set rather than a reduced one.
16
+ */
17
+ export declare function WorkflowRunFilters({ search, facets, onChange, onClear, hasActiveFilters, }: WorkflowRunFiltersProps): import("react").JSX.Element;
18
+ //# sourceMappingURL=workflow-run-filters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflow-run-filters.d.ts","sourceRoot":"","sources":["../../../src/components/workflow-run-list/workflow-run-filters.tsx"],"names":[],"mappings":"AAgBA,OAAO,EAEL,KAAK,sBAAsB,EAE3B,KAAK,kBAAkB,EACxB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,kBAAkB,CAAC;AAQxD,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,MAAM,EAAE,iBAAiB,CAAC;IAC1B,QAAQ,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,IAAI,CAAC;IAClD,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,MAAM,EACN,MAAM,EACN,QAAQ,EACR,OAAO,EACP,gBAAgB,GACjB,EAAE,uBAAuB,+BA8DzB"}
@@ -0,0 +1,236 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Button } from '@shipfox/react-ui/button';
3
+ import { DateRangePicker } from '@shipfox/react-ui/date-range-picker';
4
+ import { Icon } from '@shipfox/react-ui/icon';
5
+ import { Input } from '@shipfox/react-ui/input';
6
+ import { Label } from '@shipfox/react-ui/label';
7
+ import { Sheet, SheetBody, SheetContent, SheetFooter, SheetHeader, SheetTitle, SheetTrigger } from '@shipfox/react-ui/sheet';
8
+ import { useState } from 'react';
9
+ import { getWorkflowStatusVisual } from '#components/workflow-status/status-visuals.js';
10
+ import { WORKFLOW_RUN_LIST_STATUSES } from '#routes/inputs.js';
11
+ import { WorkflowRunFilterMenu } from './workflow-run-filter-menu.js';
12
+ const STATUS_OPTIONS = WORKFLOW_RUN_LIST_STATUSES.map((status)=>({
13
+ value: status,
14
+ label: getWorkflowStatusVisual(status).label
15
+ }));
16
+ /**
17
+ * The run list filter row.
18
+ *
19
+ * Inline from `md` up, and behind a sheet below it, where a five-control toolbar would eat
20
+ * the viewport the list is supposed to fill. Both layouts render the same controls, so the
21
+ * narrow surface is the full filter set rather than a reduced one.
22
+ */ export function WorkflowRunFilters({ search, facets, onChange, onClear, hasActiveFilters }) {
23
+ const [sheetOpen, setSheetOpen] = useState(false);
24
+ return /*#__PURE__*/ _jsxs("div", {
25
+ className: "flex flex-wrap items-center gap-8",
26
+ children: [
27
+ /*#__PURE__*/ _jsx(Input, {
28
+ value: search.search ?? '',
29
+ onChange: (event)=>onChange({
30
+ search: event.target.value
31
+ }),
32
+ placeholder: "Search runs by name, number, branch, or commit",
33
+ "aria-label": "Search runs",
34
+ size: "small",
35
+ className: "min-w-[240px] flex-1",
36
+ iconLeft: /*#__PURE__*/ _jsx(Icon, {
37
+ name: "searchLine",
38
+ className: "size-14 text-foreground-neutral-muted"
39
+ })
40
+ }),
41
+ /*#__PURE__*/ _jsxs("div", {
42
+ className: "hidden flex-wrap items-center gap-8 md:flex",
43
+ children: [
44
+ /*#__PURE__*/ _jsx(WorkflowRunFilterControls, {
45
+ search: search,
46
+ facets: facets,
47
+ onChange: onChange
48
+ }),
49
+ hasActiveFilters ? /*#__PURE__*/ _jsx(ClearFiltersButton, {
50
+ onClear: onClear
51
+ }) : null
52
+ ]
53
+ }),
54
+ /*#__PURE__*/ _jsxs(Sheet, {
55
+ open: sheetOpen,
56
+ onOpenChange: setSheetOpen,
57
+ children: [
58
+ /*#__PURE__*/ _jsx(SheetTrigger, {
59
+ asChild: true,
60
+ children: /*#__PURE__*/ _jsx(Button, {
61
+ type: "button",
62
+ variant: "secondary",
63
+ size: "sm",
64
+ iconLeft: "filterLine",
65
+ className: "md:hidden",
66
+ children: "Filters"
67
+ })
68
+ }),
69
+ /*#__PURE__*/ _jsxs(SheetContent, {
70
+ side: "bottom",
71
+ "aria-describedby": undefined,
72
+ children: [
73
+ /*#__PURE__*/ _jsx(SheetHeader, {
74
+ children: /*#__PURE__*/ _jsx(SheetTitle, {
75
+ children: "Filter runs"
76
+ })
77
+ }),
78
+ /*#__PURE__*/ _jsx(SheetBody, {
79
+ className: "flex flex-col gap-12",
80
+ children: /*#__PURE__*/ _jsx(WorkflowRunFilterControls, {
81
+ search: search,
82
+ facets: facets,
83
+ onChange: onChange,
84
+ stacked: true
85
+ })
86
+ }),
87
+ /*#__PURE__*/ _jsxs(SheetFooter, {
88
+ children: [
89
+ /*#__PURE__*/ _jsx(Button, {
90
+ type: "button",
91
+ variant: "secondary",
92
+ size: "sm",
93
+ disabled: !hasActiveFilters,
94
+ onClick: onClear,
95
+ children: "Clear filters"
96
+ }),
97
+ /*#__PURE__*/ _jsx(Button, {
98
+ type: "button",
99
+ variant: "primary",
100
+ size: "sm",
101
+ onClick: ()=>setSheetOpen(false),
102
+ children: "Show runs"
103
+ })
104
+ ]
105
+ })
106
+ ]
107
+ })
108
+ ]
109
+ })
110
+ ]
111
+ });
112
+ }
113
+ function WorkflowRunFilterControls({ search, facets, onChange, stacked = false }) {
114
+ const controlClassName = stacked ? 'w-full max-w-none' : undefined;
115
+ return /*#__PURE__*/ _jsxs(_Fragment, {
116
+ children: [
117
+ /*#__PURE__*/ _jsx(WorkflowRunFilterMenu, {
118
+ label: "Status",
119
+ options: STATUS_OPTIONS,
120
+ selected: search.status ?? [],
121
+ onChange: (next)=>onChange({
122
+ status: next
123
+ }),
124
+ emptyMessage: "No statuses available.",
125
+ className: controlClassName
126
+ }),
127
+ /*#__PURE__*/ _jsx(WorkflowRunFilterMenu, {
128
+ label: "Branch",
129
+ options: toOptions(facets.branch),
130
+ selected: search.branch ?? [],
131
+ onChange: (branch)=>onChange({
132
+ branch
133
+ }),
134
+ emptyMessage: "No branches in the loaded runs.",
135
+ className: controlClassName
136
+ }),
137
+ /*#__PURE__*/ _jsx(WorkflowRunFilterMenu, {
138
+ label: "Actor",
139
+ options: toOptions(facets.actor),
140
+ selected: search.actor ?? [],
141
+ onChange: (actor)=>onChange({
142
+ actor
143
+ }),
144
+ emptyMessage: "No actors in the loaded runs.",
145
+ className: controlClassName
146
+ }),
147
+ /*#__PURE__*/ _jsx(WorkflowRunFilterMenu, {
148
+ label: "Event",
149
+ options: toOptions(facets.event),
150
+ selected: search.event ?? [],
151
+ onChange: (event)=>onChange({
152
+ event
153
+ }),
154
+ emptyMessage: "No events in the loaded runs.",
155
+ className: controlClassName
156
+ }),
157
+ stacked ? /*#__PURE__*/ _jsxs("div", {
158
+ className: "flex flex-col gap-6",
159
+ children: [
160
+ /*#__PURE__*/ _jsx(Label, {
161
+ children: "Created between"
162
+ }),
163
+ /*#__PURE__*/ _jsx(RunDateRangeFilter, {
164
+ search: search,
165
+ onChange: onChange
166
+ })
167
+ ]
168
+ }) : /*#__PURE__*/ _jsx(RunDateRangeFilter, {
169
+ search: search,
170
+ onChange: onChange
171
+ })
172
+ ]
173
+ });
174
+ }
175
+ function RunDateRangeFilter({ search, onChange }) {
176
+ return /*#__PURE__*/ _jsx(DateRangePicker, {
177
+ size: "small",
178
+ "aria-label": "Filter runs by creation date",
179
+ // The shared picker renders a value only when both bounds are set, so a one-sided filter
180
+ // would otherwise read as unset. Naming the active bound keeps it visible without
181
+ // inventing the bound the user did not choose.
182
+ placeholder: partialDateLabel(search) ?? 'Any date',
183
+ dateRange: {
184
+ ...search.after ? {
185
+ start: fromCalendarDate(search.after)
186
+ } : {},
187
+ ...search.before ? {
188
+ end: fromCalendarDate(search.before)
189
+ } : {}
190
+ },
191
+ onDateRangeSelect: (range)=>onChange({
192
+ after: range?.start ? toCalendarDate(range.start) : undefined,
193
+ before: range?.end ? toCalendarDate(range.end) : undefined
194
+ }),
195
+ onClear: ()=>onChange({
196
+ after: undefined,
197
+ before: undefined
198
+ })
199
+ });
200
+ }
201
+ function ClearFiltersButton({ onClear }) {
202
+ return /*#__PURE__*/ _jsx(Button, {
203
+ type: "button",
204
+ variant: "transparentMuted",
205
+ size: "sm",
206
+ iconLeft: "closeLine",
207
+ onClick: onClear,
208
+ children: "Clear filters"
209
+ });
210
+ }
211
+ /** Describes a bound the picker cannot display on its own, or nothing when it can. */ function partialDateLabel(search) {
212
+ if (search.after && search.before) return undefined;
213
+ if (search.after) return `From ${search.after}`;
214
+ if (search.before) return `Until ${search.before}`;
215
+ return undefined;
216
+ }
217
+ function toOptions(values) {
218
+ return values.map((value)=>({
219
+ value,
220
+ label: value
221
+ }));
222
+ }
223
+ // The bounds are local calendar dates, matching how each row's date reads, so the picker and
224
+ // the URL agree with what the list shows rather than with UTC.
225
+ function toCalendarDate(date) {
226
+ const month = String(date.getMonth() + 1).padStart(2, '0');
227
+ const day = String(date.getDate()).padStart(2, '0');
228
+ return `${date.getFullYear()}-${month}-${day}`;
229
+ }
230
+ function fromCalendarDate(value) {
231
+ const [year, month, day] = value.split('-').map(Number);
232
+ const date = new Date(year, month - 1, day);
233
+ return Number.isNaN(date.getTime()) ? undefined : date;
234
+ }
235
+
236
+ //# sourceMappingURL=workflow-run-filters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/workflow-run-list/workflow-run-filters.tsx"],"sourcesContent":["import {Button} from '@shipfox/react-ui/button';\nimport {DateRangePicker} from '@shipfox/react-ui/date-range-picker';\nimport {Icon} from '@shipfox/react-ui/icon';\nimport {Input} from '@shipfox/react-ui/input';\nimport {Label} from '@shipfox/react-ui/label';\nimport {\n Sheet,\n SheetBody,\n SheetContent,\n SheetFooter,\n SheetHeader,\n SheetTitle,\n SheetTrigger,\n} from '@shipfox/react-ui/sheet';\nimport {useState} from 'react';\nimport {getWorkflowStatusVisual} from '#components/workflow-status/status-visuals.js';\nimport {\n WORKFLOW_RUN_LIST_STATUSES,\n type WorkflowRunFilterPatch,\n type WorkflowRunListStatus,\n type WorkflowRunsSearch,\n} from '#routes/inputs.js';\nimport type {WorkflowRunFacets} from './run-display.js';\nimport {WorkflowRunFilterMenu, type WorkflowRunFilterOption} from './workflow-run-filter-menu.js';\n\nconst STATUS_OPTIONS: WorkflowRunFilterOption[] = WORKFLOW_RUN_LIST_STATUSES.map((status) => ({\n value: status,\n label: getWorkflowStatusVisual(status).label,\n}));\n\nexport interface WorkflowRunFiltersProps {\n search: WorkflowRunsSearch;\n facets: WorkflowRunFacets;\n onChange: (patch: WorkflowRunFilterPatch) => void;\n onClear: () => void;\n hasActiveFilters: boolean;\n}\n\n/**\n * The run list filter row.\n *\n * Inline from `md` up, and behind a sheet below it, where a five-control toolbar would eat\n * the viewport the list is supposed to fill. Both layouts render the same controls, so the\n * narrow surface is the full filter set rather than a reduced one.\n */\nexport function WorkflowRunFilters({\n search,\n facets,\n onChange,\n onClear,\n hasActiveFilters,\n}: WorkflowRunFiltersProps) {\n const [sheetOpen, setSheetOpen] = useState(false);\n\n return (\n <div className=\"flex flex-wrap items-center gap-8\">\n <Input\n value={search.search ?? ''}\n onChange={(event) => onChange({search: event.target.value})}\n placeholder=\"Search runs by name, number, branch, or commit\"\n aria-label=\"Search runs\"\n size=\"small\"\n className=\"min-w-[240px] flex-1\"\n iconLeft={<Icon name=\"searchLine\" className=\"size-14 text-foreground-neutral-muted\" />}\n />\n\n <div className=\"hidden flex-wrap items-center gap-8 md:flex\">\n <WorkflowRunFilterControls search={search} facets={facets} onChange={onChange} />\n {hasActiveFilters ? <ClearFiltersButton onClear={onClear} /> : null}\n </div>\n\n <Sheet open={sheetOpen} onOpenChange={setSheetOpen}>\n <SheetTrigger asChild>\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"sm\"\n iconLeft=\"filterLine\"\n className=\"md:hidden\"\n >\n Filters\n </Button>\n </SheetTrigger>\n <SheetContent side=\"bottom\" aria-describedby={undefined}>\n <SheetHeader>\n <SheetTitle>Filter runs</SheetTitle>\n </SheetHeader>\n <SheetBody className=\"flex flex-col gap-12\">\n <WorkflowRunFilterControls\n search={search}\n facets={facets}\n onChange={onChange}\n stacked\n />\n </SheetBody>\n <SheetFooter>\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"sm\"\n disabled={!hasActiveFilters}\n onClick={onClear}\n >\n Clear filters\n </Button>\n <Button type=\"button\" variant=\"primary\" size=\"sm\" onClick={() => setSheetOpen(false)}>\n Show runs\n </Button>\n </SheetFooter>\n </SheetContent>\n </Sheet>\n </div>\n );\n}\n\nfunction WorkflowRunFilterControls({\n search,\n facets,\n onChange,\n stacked = false,\n}: {\n search: WorkflowRunsSearch;\n facets: WorkflowRunFacets;\n onChange: (patch: WorkflowRunFilterPatch) => void;\n stacked?: boolean;\n}) {\n const controlClassName = stacked ? 'w-full max-w-none' : undefined;\n\n return (\n <>\n <WorkflowRunFilterMenu\n label=\"Status\"\n options={STATUS_OPTIONS}\n selected={search.status ?? []}\n onChange={(next) => onChange({status: next as WorkflowRunListStatus[]})}\n emptyMessage=\"No statuses available.\"\n className={controlClassName}\n />\n <WorkflowRunFilterMenu\n label=\"Branch\"\n options={toOptions(facets.branch)}\n selected={search.branch ?? []}\n onChange={(branch) => onChange({branch})}\n emptyMessage=\"No branches in the loaded runs.\"\n className={controlClassName}\n />\n <WorkflowRunFilterMenu\n label=\"Actor\"\n options={toOptions(facets.actor)}\n selected={search.actor ?? []}\n onChange={(actor) => onChange({actor})}\n emptyMessage=\"No actors in the loaded runs.\"\n className={controlClassName}\n />\n <WorkflowRunFilterMenu\n label=\"Event\"\n options={toOptions(facets.event)}\n selected={search.event ?? []}\n onChange={(event) => onChange({event})}\n emptyMessage=\"No events in the loaded runs.\"\n className={controlClassName}\n />\n {stacked ? (\n <div className=\"flex flex-col gap-6\">\n <Label>Created between</Label>\n <RunDateRangeFilter search={search} onChange={onChange} />\n </div>\n ) : (\n <RunDateRangeFilter search={search} onChange={onChange} />\n )}\n </>\n );\n}\n\nfunction RunDateRangeFilter({\n search,\n onChange,\n}: {\n search: WorkflowRunsSearch;\n onChange: (patch: WorkflowRunFilterPatch) => void;\n}) {\n return (\n <DateRangePicker\n size=\"small\"\n aria-label=\"Filter runs by creation date\"\n // The shared picker renders a value only when both bounds are set, so a one-sided filter\n // would otherwise read as unset. Naming the active bound keeps it visible without\n // inventing the bound the user did not choose.\n placeholder={partialDateLabel(search) ?? 'Any date'}\n dateRange={{\n ...(search.after ? {start: fromCalendarDate(search.after)} : {}),\n ...(search.before ? {end: fromCalendarDate(search.before)} : {}),\n }}\n onDateRangeSelect={(range) =>\n onChange({\n after: range?.start ? toCalendarDate(range.start) : undefined,\n before: range?.end ? toCalendarDate(range.end) : undefined,\n })\n }\n onClear={() => onChange({after: undefined, before: undefined})}\n />\n );\n}\n\nfunction ClearFiltersButton({onClear}: {onClear: () => void}) {\n return (\n <Button\n type=\"button\"\n variant=\"transparentMuted\"\n size=\"sm\"\n iconLeft=\"closeLine\"\n onClick={onClear}\n >\n Clear filters\n </Button>\n );\n}\n\n/** Describes a bound the picker cannot display on its own, or nothing when it can. */\nfunction partialDateLabel(search: WorkflowRunsSearch): string | undefined {\n if (search.after && search.before) return undefined;\n if (search.after) return `From ${search.after}`;\n if (search.before) return `Until ${search.before}`;\n return undefined;\n}\n\nfunction toOptions(values: readonly string[]): WorkflowRunFilterOption[] {\n return values.map((value) => ({value, label: value}));\n}\n\n// The bounds are local calendar dates, matching how each row's date reads, so the picker and\n// the URL agree with what the list shows rather than with UTC.\nfunction toCalendarDate(date: Date): string {\n const month = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n return `${date.getFullYear()}-${month}-${day}`;\n}\n\nfunction fromCalendarDate(value: string): Date | undefined {\n const [year, month, day] = value.split('-').map(Number) as [number, number, number];\n const date = new Date(year, month - 1, day);\n return Number.isNaN(date.getTime()) ? undefined : date;\n}\n"],"names":["Button","DateRangePicker","Icon","Input","Label","Sheet","SheetBody","SheetContent","SheetFooter","SheetHeader","SheetTitle","SheetTrigger","useState","getWorkflowStatusVisual","WORKFLOW_RUN_LIST_STATUSES","WorkflowRunFilterMenu","STATUS_OPTIONS","map","status","value","label","WorkflowRunFilters","search","facets","onChange","onClear","hasActiveFilters","sheetOpen","setSheetOpen","div","className","event","target","placeholder","aria-label","size","iconLeft","name","WorkflowRunFilterControls","ClearFiltersButton","open","onOpenChange","asChild","type","variant","side","aria-describedby","undefined","stacked","disabled","onClick","controlClassName","options","selected","next","emptyMessage","toOptions","branch","actor","RunDateRangeFilter","partialDateLabel","dateRange","after","start","fromCalendarDate","before","end","onDateRangeSelect","range","toCalendarDate","values","date","month","String","getMonth","padStart","day","getDate","getFullYear","year","split","Number","Date","isNaN","getTime"],"mappings":"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"}
@@ -4,11 +4,15 @@ interface WorkflowRunListContentProps {
4
4
  query: WorkflowRunListQuery;
5
5
  totalRuns: number;
6
6
  runs: WorkflowRunListItem[];
7
- workspaceId: string;
8
- projectId: string;
9
- selectedWorkflowRunId?: string | undefined;
7
+ workspaceSlug?: string | undefined;
8
+ projectSlug?: string | undefined;
9
+ hasActiveFilters: boolean;
10
10
  onClearFilters: () => void;
11
+ hasNextPage: boolean;
12
+ isFetchingNextPage: boolean;
13
+ isFetchNextPageError: boolean;
14
+ onLoadMore?: () => void;
11
15
  }
12
- export declare function WorkflowRunListContent({ query, totalRuns, runs, workspaceId, projectId, selectedWorkflowRunId, onClearFilters, }: WorkflowRunListContentProps): import("react").JSX.Element;
16
+ export declare function WorkflowRunListContent({ query, totalRuns, runs, workspaceSlug, projectSlug, hasActiveFilters, onClearFilters, hasNextPage, isFetchingNextPage, isFetchNextPageError, onLoadMore, }: WorkflowRunListContentProps): import("react").JSX.Element;
13
17
  export {};
14
18
  //# sourceMappingURL=workflow-run-list-content.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"workflow-run-list-content.d.ts","sourceRoot":"","sources":["../../../src/components/workflow-run-list/workflow-run-list-content.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,uBAAuB,CAAC;AAC/D,OAAO,KAAK,EAAC,oBAAoB,EAAC,MAAM,YAAY,CAAC;AASrD,UAAU,2BAA2B;IACnC,KAAK,EAAE,oBAAoB,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,mBAAmB,EAAE,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,qBAAqB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,cAAc,EAAE,MAAM,IAAI,CAAC;CAC5B;AAED,wBAAgB,sBAAsB,CAAC,EACrC,KAAK,EACL,SAAS,EACT,IAAI,EACJ,WAAW,EACX,SAAS,EACT,qBAAqB,EACrB,cAAc,GACf,EAAE,2BAA2B,+BA4B7B"}
1
+ {"version":3,"file":"workflow-run-list-content.d.ts","sourceRoot":"","sources":["../../../src/components/workflow-run-list/workflow-run-list-content.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,uBAAuB,CAAC;AAC/D,OAAO,KAAK,EAAC,oBAAoB,EAAC,MAAM,YAAY,CAAC;AAUrD,UAAU,2BAA2B;IACnC,KAAK,EAAE,oBAAoB,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,mBAAmB,EAAE,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,WAAW,EAAE,OAAO,CAAC;IACrB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,oBAAoB,EAAE,OAAO,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;CACzB;AAED,wBAAgB,sBAAsB,CAAC,EACrC,KAAK,EACL,SAAS,EACT,IAAI,EACJ,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,cAAc,EACd,WAAW,EACX,kBAAkB,EAClB,oBAAoB,EACpB,UAAU,GACX,EAAE,2BAA2B,+BA+C7B"}
@@ -1,13 +1,21 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { QueryLoadError } from '@shipfox/client-ui';
3
- import { WorkflowRunListEmpty, WorkflowRunListNoMatches, WorkflowRunListSkeleton, WorkflowRunListStaleError } from './workflow-run-list-states.js';
3
+ import { WorkflowRunListEmpty, WorkflowRunListLoadMore, WorkflowRunListNoMatches, WorkflowRunListSkeleton, WorkflowRunListStaleError } from './workflow-run-list-states.js';
4
4
  import { WorkflowRunRowList } from './workflow-run-row.js';
5
- export function WorkflowRunListContent({ query, totalRuns, runs, workspaceId, projectId, selectedWorkflowRunId, onClearFilters }) {
5
+ export function WorkflowRunListContent({ query, totalRuns, runs, workspaceSlug, projectSlug, hasActiveFilters, onClearFilters, hasNextPage, isFetchingNextPage, isFetchNextPageError, onLoadMore }) {
6
6
  const { isPending, isError } = query;
7
7
  // A refetch that fails after a prior success keeps the rows on screen behind a slim
8
8
  // banner. QueryLoadError owns the inverse case (errored before anything loaded) and
9
- // self-gates to nothing here once data exists.
9
+ // self-gates to nothing here once data exists. A failed fetch never renders as an empty
10
+ // list: "nothing here" and "we could not find out" are different answers.
10
11
  const refreshFailed = isError && query.data !== undefined;
12
+ // Keyed off "we have an answer" rather than "no error", so a stale refresh still reports
13
+ // whether the filters match anything instead of leaving the list blank under the banner.
14
+ const hasLoaded = !isPending && query.data !== undefined;
15
+ // An empty result is only an empty *list* when no filter is on. With filters active it is a
16
+ // no-matches state even at zero loaded runs, so the way out is clearing them.
17
+ const showEmptyState = hasLoaded && totalRuns === 0 && !hasActiveFilters;
18
+ const showNoMatches = hasLoaded && runs.length === 0 && !showEmptyState;
11
19
  return /*#__PURE__*/ _jsxs("div", {
12
20
  className: "min-h-0 flex-1 overflow-y-auto",
13
21
  children: [
@@ -20,15 +28,35 @@ export function WorkflowRunListContent({ query, totalRuns, runs, workspaceId, pr
20
28
  !isPending && refreshFailed ? /*#__PURE__*/ _jsx(WorkflowRunListStaleError, {
21
29
  query: query
22
30
  }) : null,
23
- !isPending && !isError && totalRuns === 0 ? /*#__PURE__*/ _jsx(WorkflowRunListEmpty, {}) : null,
24
- !isPending && totalRuns > 0 && runs.length === 0 ? /*#__PURE__*/ _jsx(WorkflowRunListNoMatches, {
25
- onClear: onClearFilters
31
+ showEmptyState ? /*#__PURE__*/ _jsx(WorkflowRunListEmpty, {
32
+ workspaceSlug: workspaceSlug,
33
+ projectSlug: projectSlug
26
34
  }) : null,
27
- !isPending && runs.length > 0 ? /*#__PURE__*/ _jsx(WorkflowRunRowList, {
28
- runs: runs,
29
- workspaceId: workspaceId,
30
- projectId: projectId,
31
- selectedWorkflowRunId: selectedWorkflowRunId
35
+ showNoMatches ? /*#__PURE__*/ _jsx(WorkflowRunListNoMatches, {
36
+ onClear: onClearFilters,
37
+ hasNextPage: hasNextPage,
38
+ isFetchingNextPage: isFetchingNextPage,
39
+ isFetchNextPageError: isFetchNextPageError,
40
+ ...onLoadMore ? {
41
+ onLoadMore
42
+ } : {}
43
+ }) : null,
44
+ !isPending && runs.length > 0 ? /*#__PURE__*/ _jsxs(_Fragment, {
45
+ children: [
46
+ /*#__PURE__*/ _jsx(WorkflowRunRowList, {
47
+ runs: runs,
48
+ workspaceSlug: workspaceSlug,
49
+ projectSlug: projectSlug
50
+ }),
51
+ /*#__PURE__*/ _jsx(WorkflowRunListLoadMore, {
52
+ hasNextPage: hasNextPage,
53
+ isFetchingNextPage: isFetchingNextPage,
54
+ isFetchNextPageError: isFetchNextPageError,
55
+ ...onLoadMore ? {
56
+ onLoadMore
57
+ } : {}
58
+ })
59
+ ]
32
60
  }) : null
33
61
  ]
34
62
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/workflow-run-list/workflow-run-list-content.tsx"],"sourcesContent":["import {QueryLoadError} from '@shipfox/client-ui';\nimport type {WorkflowRunListItem} from '#core/workflow-run.js';\nimport type {WorkflowRunListQuery} from './types.js';\nimport {\n WorkflowRunListEmpty,\n WorkflowRunListNoMatches,\n WorkflowRunListSkeleton,\n WorkflowRunListStaleError,\n} from './workflow-run-list-states.js';\nimport {WorkflowRunRowList} from './workflow-run-row.js';\n\ninterface WorkflowRunListContentProps {\n query: WorkflowRunListQuery;\n totalRuns: number;\n runs: WorkflowRunListItem[];\n workspaceId: string;\n projectId: string;\n selectedWorkflowRunId?: string | undefined;\n onClearFilters: () => void;\n}\n\nexport function WorkflowRunListContent({\n query,\n totalRuns,\n runs,\n workspaceId,\n projectId,\n selectedWorkflowRunId,\n onClearFilters,\n}: WorkflowRunListContentProps) {\n const {isPending, isError} = query;\n // A refetch that fails after a prior success keeps the rows on screen behind a slim\n // banner. QueryLoadError owns the inverse case (errored before anything loaded) and\n // self-gates to nothing here once data exists.\n const refreshFailed = isError && query.data !== undefined;\n\n return (\n <div className=\"min-h-0 flex-1 overflow-y-auto\">\n {isPending ? <WorkflowRunListSkeleton /> : null}\n {!isPending ? (\n <QueryLoadError query={query} subject=\"workflow runs\" icon=\"pulseLine\" />\n ) : null}\n {!isPending && refreshFailed ? <WorkflowRunListStaleError query={query} /> : null}\n {!isPending && !isError && totalRuns === 0 ? <WorkflowRunListEmpty /> : null}\n {!isPending && totalRuns > 0 && runs.length === 0 ? (\n <WorkflowRunListNoMatches onClear={onClearFilters} />\n ) : null}\n {!isPending && runs.length > 0 ? (\n <WorkflowRunRowList\n runs={runs}\n workspaceId={workspaceId}\n projectId={projectId}\n selectedWorkflowRunId={selectedWorkflowRunId}\n />\n ) : null}\n </div>\n );\n}\n"],"names":["QueryLoadError","WorkflowRunListEmpty","WorkflowRunListNoMatches","WorkflowRunListSkeleton","WorkflowRunListStaleError","WorkflowRunRowList","WorkflowRunListContent","query","totalRuns","runs","workspaceId","projectId","selectedWorkflowRunId","onClearFilters","isPending","isError","refreshFailed","data","undefined","div","className","subject","icon","length","onClear"],"mappings":";AAAA,SAAQA,cAAc,QAAO,qBAAqB;AAGlD,SACEC,oBAAoB,EACpBC,wBAAwB,EACxBC,uBAAuB,EACvBC,yBAAyB,QACpB,gCAAgC;AACvC,SAAQC,kBAAkB,QAAO,wBAAwB;AAYzD,OAAO,SAASC,uBAAuB,EACrCC,KAAK,EACLC,SAAS,EACTC,IAAI,EACJC,WAAW,EACXC,SAAS,EACTC,qBAAqB,EACrBC,cAAc,EACc;IAC5B,MAAM,EAACC,SAAS,EAAEC,OAAO,EAAC,GAAGR;IAC7B,oFAAoF;IACpF,oFAAoF;IACpF,+CAA+C;IAC/C,MAAMS,gBAAgBD,WAAWR,MAAMU,IAAI,KAAKC;IAEhD,qBACE,MAACC;QAAIC,WAAU;;YACZN,0BAAY,KAACX,+BAA6B;YAC1C,CAACW,0BACA,KAACd;gBAAeO,OAAOA;gBAAOc,SAAQ;gBAAgBC,MAAK;iBACzD;YACH,CAACR,aAAaE,8BAAgB,KAACZ;gBAA0BG,OAAOA;iBAAY;YAC5E,CAACO,aAAa,CAACC,WAAWP,cAAc,kBAAI,KAACP,4BAA0B;YACvE,CAACa,aAAaN,YAAY,KAAKC,KAAKc,MAAM,KAAK,kBAC9C,KAACrB;gBAAyBsB,SAASX;iBACjC;YACH,CAACC,aAAaL,KAAKc,MAAM,GAAG,kBAC3B,KAAClB;gBACCI,MAAMA;gBACNC,aAAaA;gBACbC,WAAWA;gBACXC,uBAAuBA;iBAEvB;;;AAGV"}
1
+ {"version":3,"sources":["../../../src/components/workflow-run-list/workflow-run-list-content.tsx"],"sourcesContent":["import {QueryLoadError} from '@shipfox/client-ui';\nimport type {WorkflowRunListItem} from '#core/workflow-run.js';\nimport type {WorkflowRunListQuery} from './types.js';\nimport {\n WorkflowRunListEmpty,\n WorkflowRunListLoadMore,\n WorkflowRunListNoMatches,\n WorkflowRunListSkeleton,\n WorkflowRunListStaleError,\n} from './workflow-run-list-states.js';\nimport {WorkflowRunRowList} from './workflow-run-row.js';\n\ninterface WorkflowRunListContentProps {\n query: WorkflowRunListQuery;\n totalRuns: number;\n runs: WorkflowRunListItem[];\n workspaceSlug?: string | undefined;\n projectSlug?: string | undefined;\n hasActiveFilters: boolean;\n onClearFilters: () => void;\n hasNextPage: boolean;\n isFetchingNextPage: boolean;\n isFetchNextPageError: boolean;\n onLoadMore?: () => void;\n}\n\nexport function WorkflowRunListContent({\n query,\n totalRuns,\n runs,\n workspaceSlug,\n projectSlug,\n hasActiveFilters,\n onClearFilters,\n hasNextPage,\n isFetchingNextPage,\n isFetchNextPageError,\n onLoadMore,\n}: WorkflowRunListContentProps) {\n const {isPending, isError} = query;\n // A refetch that fails after a prior success keeps the rows on screen behind a slim\n // banner. QueryLoadError owns the inverse case (errored before anything loaded) and\n // self-gates to nothing here once data exists. A failed fetch never renders as an empty\n // list: \"nothing here\" and \"we could not find out\" are different answers.\n const refreshFailed = isError && query.data !== undefined;\n // Keyed off \"we have an answer\" rather than \"no error\", so a stale refresh still reports\n // whether the filters match anything instead of leaving the list blank under the banner.\n const hasLoaded = !isPending && query.data !== undefined;\n // An empty result is only an empty *list* when no filter is on. With filters active it is a\n // no-matches state even at zero loaded runs, so the way out is clearing them.\n const showEmptyState = hasLoaded && totalRuns === 0 && !hasActiveFilters;\n const showNoMatches = hasLoaded && runs.length === 0 && !showEmptyState;\n\n return (\n <div className=\"min-h-0 flex-1 overflow-y-auto\">\n {isPending ? <WorkflowRunListSkeleton /> : null}\n {!isPending ? (\n <QueryLoadError query={query} subject=\"workflow runs\" icon=\"pulseLine\" />\n ) : null}\n {!isPending && refreshFailed ? <WorkflowRunListStaleError query={query} /> : null}\n {showEmptyState ? (\n <WorkflowRunListEmpty workspaceSlug={workspaceSlug} projectSlug={projectSlug} />\n ) : null}\n {showNoMatches ? (\n <WorkflowRunListNoMatches\n onClear={onClearFilters}\n hasNextPage={hasNextPage}\n isFetchingNextPage={isFetchingNextPage}\n isFetchNextPageError={isFetchNextPageError}\n {...(onLoadMore ? {onLoadMore} : {})}\n />\n ) : null}\n {!isPending && runs.length > 0 ? (\n <>\n <WorkflowRunRowList runs={runs} workspaceSlug={workspaceSlug} projectSlug={projectSlug} />\n <WorkflowRunListLoadMore\n hasNextPage={hasNextPage}\n isFetchingNextPage={isFetchingNextPage}\n isFetchNextPageError={isFetchNextPageError}\n {...(onLoadMore ? {onLoadMore} : {})}\n />\n </>\n ) : null}\n </div>\n );\n}\n"],"names":["QueryLoadError","WorkflowRunListEmpty","WorkflowRunListLoadMore","WorkflowRunListNoMatches","WorkflowRunListSkeleton","WorkflowRunListStaleError","WorkflowRunRowList","WorkflowRunListContent","query","totalRuns","runs","workspaceSlug","projectSlug","hasActiveFilters","onClearFilters","hasNextPage","isFetchingNextPage","isFetchNextPageError","onLoadMore","isPending","isError","refreshFailed","data","undefined","hasLoaded","showEmptyState","showNoMatches","length","div","className","subject","icon","onClear"],"mappings":";AAAA,SAAQA,cAAc,QAAO,qBAAqB;AAGlD,SACEC,oBAAoB,EACpBC,uBAAuB,EACvBC,wBAAwB,EACxBC,uBAAuB,EACvBC,yBAAyB,QACpB,gCAAgC;AACvC,SAAQC,kBAAkB,QAAO,wBAAwB;AAgBzD,OAAO,SAASC,uBAAuB,EACrCC,KAAK,EACLC,SAAS,EACTC,IAAI,EACJC,aAAa,EACbC,WAAW,EACXC,gBAAgB,EAChBC,cAAc,EACdC,WAAW,EACXC,kBAAkB,EAClBC,oBAAoB,EACpBC,UAAU,EACkB;IAC5B,MAAM,EAACC,SAAS,EAAEC,OAAO,EAAC,GAAGZ;IAC7B,oFAAoF;IACpF,oFAAoF;IACpF,wFAAwF;IACxF,0EAA0E;IAC1E,MAAMa,gBAAgBD,WAAWZ,MAAMc,IAAI,KAAKC;IAChD,yFAAyF;IACzF,yFAAyF;IACzF,MAAMC,YAAY,CAACL,aAAaX,MAAMc,IAAI,KAAKC;IAC/C,4FAA4F;IAC5F,8EAA8E;IAC9E,MAAME,iBAAiBD,aAAaf,cAAc,KAAK,CAACI;IACxD,MAAMa,gBAAgBF,aAAad,KAAKiB,MAAM,KAAK,KAAK,CAACF;IAEzD,qBACE,MAACG;QAAIC,WAAU;;YACZV,0BAAY,KAACf,+BAA6B;YAC1C,CAACe,0BACA,KAACnB;gBAAeQ,OAAOA;gBAAOsB,SAAQ;gBAAgBC,MAAK;iBACzD;YACH,CAACZ,aAAaE,8BAAgB,KAAChB;gBAA0BG,OAAOA;iBAAY;YAC5EiB,+BACC,KAACxB;gBAAqBU,eAAeA;gBAAeC,aAAaA;iBAC/D;YACHc,8BACC,KAACvB;gBACC6B,SAASlB;gBACTC,aAAaA;gBACbC,oBAAoBA;gBACpBC,sBAAsBA;gBACrB,GAAIC,aAAa;oBAACA;gBAAU,IAAI,CAAC,CAAC;iBAEnC;YACH,CAACC,aAAaT,KAAKiB,MAAM,GAAG,kBAC3B;;kCACE,KAACrB;wBAAmBI,MAAMA;wBAAMC,eAAeA;wBAAeC,aAAaA;;kCAC3E,KAACV;wBACCa,aAAaA;wBACbC,oBAAoBA;wBACpBC,sBAAsBA;wBACrB,GAAIC,aAAa;4BAACA;wBAAU,IAAI,CAAC,CAAC;;;iBAGrC;;;AAGV"}