prefect 3.6.15__py3-none-any.whl → 3.6.16.dev3__py3-none-any.whl

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 (259) hide show
  1. prefect/__init__.py +20 -0
  2. prefect/_build_info.py +3 -3
  3. prefect/_internal/analytics/__init__.py +80 -0
  4. prefect/_internal/analytics/_config.py +2 -0
  5. prefect/_internal/analytics/ci_detection.py +39 -0
  6. prefect/_internal/analytics/client.py +132 -0
  7. prefect/_internal/analytics/device_id.py +55 -0
  8. prefect/_internal/analytics/emit.py +90 -0
  9. prefect/_internal/analytics/enabled.py +33 -0
  10. prefect/_internal/analytics/events.py +14 -0
  11. prefect/_internal/analytics/milestones.py +177 -0
  12. prefect/_internal/analytics/notice.py +60 -0
  13. prefect/_internal/analytics/service.py +238 -0
  14. prefect/analytics/__init__.py +67 -0
  15. prefect/deployments/runner.py +20 -0
  16. prefect/flow_engine.py +16 -0
  17. prefect/flows.py +8 -0
  18. prefect/logging/formatters.py +24 -1
  19. prefect/server/ui-v2/assets/{artifact-card-BBzQR-Cj.js → artifact-card-BclosG8t.js} +2 -2
  20. prefect/server/ui-v2/assets/{artifact-card-BBzQR-Cj.js.map → artifact-card-BclosG8t.js.map} +1 -1
  21. prefect/server/ui-v2/assets/artifact._id-C0r4BJr2.js +2 -0
  22. prefect/server/ui-v2/assets/artifact._id-C0r4BJr2.js.map +1 -0
  23. prefect/server/ui-v2/assets/{automation-wizard-EYSfXlQ7.js → automation-wizard-Bmgt6nn8.js} +2 -2
  24. prefect/server/ui-v2/assets/{automation-wizard-EYSfXlQ7.js.map → automation-wizard-Bmgt6nn8.js.map} +1 -1
  25. prefect/server/ui-v2/assets/automation._id-Ccke3KJz.js +2 -0
  26. prefect/server/ui-v2/assets/{automation._id-Dn7jABys.js.map → automation._id-Ccke3KJz.js.map} +1 -1
  27. prefect/server/ui-v2/assets/{automation_._id.edit-COrqswD3.js → automation_._id.edit-BlKPUTVf.js} +2 -2
  28. prefect/server/ui-v2/assets/{automation_._id.edit-COrqswD3.js.map → automation_._id.edit-BlKPUTVf.js.map} +1 -1
  29. prefect/server/ui-v2/assets/{automations-header-DN_dmMXW.js → automations-header-Df2zw3SC.js} +2 -2
  30. prefect/server/ui-v2/assets/{automations-header-DN_dmMXW.js.map → automations-header-Df2zw3SC.js.map} +1 -1
  31. prefect/server/ui-v2/assets/{base-job-template-form-section-De2ACYbw.js → base-job-template-form-section-oZD6U-RW.js} +2 -2
  32. prefect/server/ui-v2/assets/{base-job-template-form-section-De2ACYbw.js.map → base-job-template-form-section-oZD6U-RW.js.map} +1 -1
  33. prefect/server/ui-v2/assets/{block-type-details-Cklc7TkK.js → block-type-details-CYrdaLot.js} +2 -2
  34. prefect/server/ui-v2/assets/{block-type-details-Cklc7TkK.js.map → block-type-details-CYrdaLot.js.map} +1 -1
  35. prefect/server/ui-v2/assets/block-type-logo-CyAWq7mC.js +2 -0
  36. prefect/server/ui-v2/assets/block-type-logo-CyAWq7mC.js.map +1 -0
  37. prefect/server/ui-v2/assets/{block._id-tuz1Bcj2.js → block._id-CBgHrpTP.js} +2 -2
  38. prefect/server/ui-v2/assets/{block._id-tuz1Bcj2.js.map → block._id-CBgHrpTP.js.map} +1 -1
  39. prefect/server/ui-v2/assets/{block_._id.edit-CFEYhF5R.js → block_._id.edit-CW-kdi4O.js} +2 -2
  40. prefect/server/ui-v2/assets/{block_._id.edit-CFEYhF5R.js.map → block_._id.edit-CW-kdi4O.js.map} +1 -1
  41. prefect/server/ui-v2/assets/{catalog-CCPRo7nY.js → catalog-Brh0kn1I.js} +2 -2
  42. prefect/server/ui-v2/assets/{catalog-CCPRo7nY.js.map → catalog-Brh0kn1I.js.map} +1 -1
  43. prefect/server/ui-v2/assets/catalog_._slug-MCgzguIZ.js +2 -0
  44. prefect/server/ui-v2/assets/{catalog_._slug-Bl2J2oI3.js.map → catalog_._slug-MCgzguIZ.js.map} +1 -1
  45. prefect/server/ui-v2/assets/{catalog_._slug_.create-9UD_SxDN.js → catalog_._slug_.create-DBaeHi9Q.js} +2 -2
  46. prefect/server/ui-v2/assets/{catalog_._slug_.create-9UD_SxDN.js.map → catalog_._slug_.create-DBaeHi9Q.js.map} +1 -1
  47. prefect/server/ui-v2/assets/{collapsible-BVQTBG_U.js → collapsible-B_NJS0uJ.js} +2 -2
  48. prefect/server/ui-v2/assets/{collapsible-BVQTBG_U.js.map → collapsible-B_NJS0uJ.js.map} +1 -1
  49. prefect/server/ui-v2/assets/{concurrency-limit._id-CsgRxA0a.js → concurrency-limit._id-qzNUQzQa.js} +2 -2
  50. prefect/server/ui-v2/assets/{concurrency-limit._id-CsgRxA0a.js.map → concurrency-limit._id-qzNUQzQa.js.map} +1 -1
  51. prefect/server/ui-v2/assets/create-BwXG6EIb.js +2 -0
  52. prefect/server/ui-v2/assets/{create-D--LHaji.js.map → create-BwXG6EIb.js.map} +1 -1
  53. prefect/server/ui-v2/assets/{create-BycfZHGQ.js → create-MoiIE9Ms.js} +2 -2
  54. prefect/server/ui-v2/assets/{create-BycfZHGQ.js.map → create-MoiIE9Ms.js.map} +1 -1
  55. prefect/server/ui-v2/assets/data-table-CPkppyg6.js +2 -0
  56. prefect/server/ui-v2/assets/data-table-CPkppyg6.js.map +1 -0
  57. prefect/server/ui-v2/assets/delete-confirmation-dialog-CwDK_2QS.js +2 -0
  58. prefect/server/ui-v2/assets/{delete-confirmation-dialog-DHkm2p8m.js.map → delete-confirmation-dialog-CwDK_2QS.js.map} +1 -1
  59. prefect/server/ui-v2/assets/{deployment-action-header-D5GOooPm.js → deployment-action-header-Vp9YsCJO.js} +2 -2
  60. prefect/server/ui-v2/assets/{deployment-action-header-D5GOooPm.js.map → deployment-action-header-Vp9YsCJO.js.map} +1 -1
  61. prefect/server/ui-v2/assets/{deployment-form-wfg6HeAJ.js → deployment-form-CJcg_6DJ.js} +3 -3
  62. prefect/server/ui-v2/assets/{deployment-form-wfg6HeAJ.js.map → deployment-form-CJcg_6DJ.js.map} +1 -1
  63. prefect/server/ui-v2/assets/{deployment-links-6iugOgDh.js → deployment-links-CIkJIuHh.js} +2 -2
  64. prefect/server/ui-v2/assets/{deployment-links-6iugOgDh.js.map → deployment-links-CIkJIuHh.js.map} +1 -1
  65. prefect/server/ui-v2/assets/deployment._id-C6XrGMp_.js +2 -0
  66. prefect/server/ui-v2/assets/{deployment._id-Ci9zge5n.js.map → deployment._id-C6XrGMp_.js.map} +1 -1
  67. prefect/server/ui-v2/assets/{deployment._id-whsGcHdu.js → deployment._id-CWgTYmTG.js} +2 -2
  68. prefect/server/ui-v2/assets/{deployment._id-whsGcHdu.js.map → deployment._id-CWgTYmTG.js.map} +1 -1
  69. prefect/server/ui-v2/assets/deployment_._id.duplicate-Bg0s0ZJn.js +2 -0
  70. prefect/server/ui-v2/assets/{deployment_._id.duplicate-D9ZWkh8H.js.map → deployment_._id.duplicate-Bg0s0ZJn.js.map} +1 -1
  71. prefect/server/ui-v2/assets/deployment_._id.edit-CnoB0UeG.js +2 -0
  72. prefect/server/ui-v2/assets/{deployment_._id.edit-CS7sObzC.js.map → deployment_._id.edit-CnoB0UeG.js.map} +1 -1
  73. prefect/server/ui-v2/assets/{deployment_._id.run-g7SZuDFi.js → deployment_._id.run-BqPK6rTB.js} +2 -2
  74. prefect/server/ui-v2/assets/{deployment_._id.run-g7SZuDFi.js.map → deployment_._id.run-BqPK6rTB.js.map} +1 -1
  75. prefect/server/ui-v2/assets/{dropdown-menu-0atiOSFo.js → dropdown-menu-D7Gwbd15.js} +2 -2
  76. prefect/server/ui-v2/assets/{dropdown-menu-0atiOSFo.js.map → dropdown-menu-D7Gwbd15.js.map} +1 -1
  77. prefect/server/ui-v2/assets/{event-resource-display-DHiAb1Up.js → event-resource-display-CDRgVKd4.js} +2 -2
  78. prefect/server/ui-v2/assets/{event-resource-display-DHiAb1Up.js.map → event-resource-display-CDRgVKd4.js.map} +1 -1
  79. prefect/server/ui-v2/assets/event._eventDate._eventId-C73GMDkK.js +2 -0
  80. prefect/server/ui-v2/assets/{event._eventDate._eventId-D7Twzb22.js.map → event._eventDate._eventId-C73GMDkK.js.map} +1 -1
  81. prefect/server/ui-v2/assets/{flow-run-graph-BhzuSJLm.js → flow-run-graph-ckiE3mA9.js} +2 -2
  82. prefect/server/ui-v2/assets/{flow-run-graph-BhzuSJLm.js.map → flow-run-graph-ckiE3mA9.js.map} +1 -1
  83. prefect/server/ui-v2/assets/{flow-run._id-CqpH6bvx.js → flow-run._id-BukrNCAq.js} +2 -2
  84. prefect/server/ui-v2/assets/{flow-run._id-CqpH6bvx.js.map → flow-run._id-BukrNCAq.js.map} +1 -1
  85. prefect/server/ui-v2/assets/{flow-run._id-lIIQBD7H.js → flow-run._id-CtI5VZ2M.js} +2 -2
  86. prefect/server/ui-v2/assets/{flow-run._id-lIIQBD7H.js.map → flow-run._id-CtI5VZ2M.js.map} +1 -1
  87. prefect/server/ui-v2/assets/flow-run._id-s1UJuakA.js +4 -0
  88. prefect/server/ui-v2/assets/{flow-run._id-RLy2kBh0.js.map → flow-run._id-s1UJuakA.js.map} +1 -1
  89. prefect/server/ui-v2/assets/{flow-runs-pagination-BATUweRV.js → flow-runs-pagination-SLbYtvaR.js} +2 -2
  90. prefect/server/ui-v2/assets/{flow-runs-pagination-BATUweRV.js.map → flow-runs-pagination-SLbYtvaR.js.map} +1 -1
  91. prefect/server/ui-v2/assets/flow._id-CZ5P0v4N.js +2 -0
  92. prefect/server/ui-v2/assets/{flow._id-BdQGWPKP.js.map → flow._id-CZ5P0v4N.js.map} +1 -1
  93. prefect/server/ui-v2/assets/{form-DLrbC7rV.js → form-mws4law8.js} +2 -2
  94. prefect/server/ui-v2/assets/{form-DLrbC7rV.js.map → form-mws4law8.js.map} +1 -1
  95. prefect/server/ui-v2/assets/{header-BTAWyeXv.js → header-Bes1LmY7.js} +2 -2
  96. prefect/server/ui-v2/assets/{header-BTAWyeXv.js.map → header-Bes1LmY7.js.map} +1 -1
  97. prefect/server/ui-v2/assets/{header-ChFAx5uR.js → header-Bj_zBR-a.js} +2 -2
  98. prefect/server/ui-v2/assets/{header-ChFAx5uR.js.map → header-Bj_zBR-a.js.map} +1 -1
  99. prefect/server/ui-v2/assets/{header-CyQqOj1w.js → header-CPxTHSvz.js} +2 -2
  100. prefect/server/ui-v2/assets/{header-CyQqOj1w.js.map → header-CPxTHSvz.js.map} +1 -1
  101. prefect/server/ui-v2/assets/{index-m48E4KcG.js → index-B8vo2Lrg.js} +5 -5
  102. prefect/server/ui-v2/assets/{index-m48E4KcG.js.map → index-B8vo2Lrg.js.map} +1 -1
  103. prefect/server/ui-v2/assets/{index-D5RT-SAp.js → index-BBeh-3Nh.js} +2 -2
  104. prefect/server/ui-v2/assets/{index-D5RT-SAp.js.map → index-BBeh-3Nh.js.map} +1 -1
  105. prefect/server/ui-v2/assets/index-BLnEvHia.js +2 -0
  106. prefect/server/ui-v2/assets/{index-7i4X9TeK.js.map → index-BLnEvHia.js.map} +1 -1
  107. prefect/server/ui-v2/assets/index-BpKoubXu.js +2 -0
  108. prefect/server/ui-v2/assets/index-BpKoubXu.js.map +1 -0
  109. prefect/server/ui-v2/assets/index-By6YGqR3.js +2 -0
  110. prefect/server/ui-v2/assets/index-By6YGqR3.js.map +1 -0
  111. prefect/server/ui-v2/assets/index-CEi3BlKI.js +2 -0
  112. prefect/server/ui-v2/assets/index-CEi3BlKI.js.map +1 -0
  113. prefect/server/ui-v2/assets/{index-BaWDC4da.js → index-CS-zxv7Z.js} +2 -2
  114. prefect/server/ui-v2/assets/{index-BaWDC4da.js.map → index-CS-zxv7Z.js.map} +1 -1
  115. prefect/server/ui-v2/assets/{index-kP_I5Qfd.js → index-CToHKh4q.js} +2 -2
  116. prefect/server/ui-v2/assets/{index-kP_I5Qfd.js.map → index-CToHKh4q.js.map} +1 -1
  117. prefect/server/ui-v2/assets/{index-CKGj5lSu.js → index-CUVvZndW.js} +2 -2
  118. prefect/server/ui-v2/assets/{index-CKGj5lSu.js.map → index-CUVvZndW.js.map} +1 -1
  119. prefect/server/ui-v2/assets/{index-CxUfZRkN.js → index-CYVn-I3i.js} +2 -2
  120. prefect/server/ui-v2/assets/{index-CxUfZRkN.js.map → index-CYVn-I3i.js.map} +1 -1
  121. prefect/server/ui-v2/assets/{index-CnlN-VC_.js → index-Cun0JN4t.js} +2 -2
  122. prefect/server/ui-v2/assets/{index-CnlN-VC_.js.map → index-Cun0JN4t.js.map} +1 -1
  123. prefect/server/ui-v2/assets/{index-BwCLKpNb.js → index-D6ynV6U7.js} +2 -2
  124. prefect/server/ui-v2/assets/{index-BwCLKpNb.js.map → index-D6ynV6U7.js.map} +1 -1
  125. prefect/server/ui-v2/assets/{index-CHf6xi9j.js → index-DdNUJLRW.js} +2 -2
  126. prefect/server/ui-v2/assets/{index-CHf6xi9j.js.map → index-DdNUJLRW.js.map} +1 -1
  127. prefect/server/ui-v2/assets/{index-CQnWiUE5.js → index-DlHOXQhu.js} +2 -2
  128. prefect/server/ui-v2/assets/{index-CQnWiUE5.js.map → index-DlHOXQhu.js.map} +1 -1
  129. prefect/server/ui-v2/assets/{index-Eqdr6Ff7.js → index-DyVw8YE8.js} +2 -2
  130. prefect/server/ui-v2/assets/{index-Eqdr6Ff7.js.map → index-DyVw8YE8.js.map} +1 -1
  131. prefect/server/ui-v2/assets/{index-Btb_-PDp.js → index-DzRz7D2P.js} +2 -2
  132. prefect/server/ui-v2/assets/{index-Btb_-PDp.js.map → index-DzRz7D2P.js.map} +1 -1
  133. prefect/server/ui-v2/assets/{index-DQGif3jm.js → index-DzUcVNZg.js} +2 -2
  134. prefect/server/ui-v2/assets/{index-DQGif3jm.js.map → index-DzUcVNZg.js.map} +1 -1
  135. prefect/server/ui-v2/assets/{index-DNh9ZBy4.js → index-IBvMMs6S.js} +2 -2
  136. prefect/server/ui-v2/assets/{index-DNh9ZBy4.js.map → index-IBvMMs6S.js.map} +1 -1
  137. prefect/server/ui-v2/assets/index-_kpA__te.js +2 -0
  138. prefect/server/ui-v2/assets/{index-CiSFHkhI.js.map → index-_kpA__te.js.map} +1 -1
  139. prefect/server/ui-v2/assets/index-m9O-nIOl.css +1 -0
  140. prefect/server/ui-v2/assets/{index-lyQav_XM.js → index-wOvyf10b.js} +2 -2
  141. prefect/server/ui-v2/assets/{index-lyQav_XM.js.map → index-wOvyf10b.js.map} +1 -1
  142. prefect/server/ui-v2/assets/{json-input-Ba-BeBcw.js → json-input-Ce-HlRqa.js} +2 -2
  143. prefect/server/ui-v2/assets/{json-input-Ba-BeBcw.js.map → json-input-Ce-HlRqa.js.map} +1 -1
  144. prefect/server/ui-v2/assets/{key-value-DkSKn6jE.js → key-value-XHEZOtZX.js} +2 -2
  145. prefect/server/ui-v2/assets/{key-value-DkSKn6jE.js.map → key-value-XHEZOtZX.js.map} +1 -1
  146. prefect/server/ui-v2/assets/{key._key-Cjx57ymg.js → key._key-LpsMf3zD.js} +2 -2
  147. prefect/server/ui-v2/assets/{key._key-Cjx57ymg.js.map → key._key-LpsMf3zD.js.map} +1 -1
  148. prefect/server/ui-v2/assets/{lazy-markdown-Du2Xu3Yp.js → lazy-markdown-1Hz0xzca.js} +2 -2
  149. prefect/server/ui-v2/assets/{lazy-markdown-Du2Xu3Yp.js.map → lazy-markdown-1Hz0xzca.js.map} +1 -1
  150. prefect/server/ui-v2/assets/{login-DxMF9Jvj.js → login-D5uepl9L.js} +2 -2
  151. prefect/server/ui-v2/assets/{login-DxMF9Jvj.js.map → login-D5uepl9L.js.map} +1 -1
  152. prefect/server/ui-v2/assets/{markdown-input-DPi8zyRr.js → markdown-input-CG6M9zD0.js} +2 -2
  153. prefect/server/ui-v2/assets/{markdown-input-DPi8zyRr.js.map → markdown-input-CG6M9zD0.js.map} +1 -1
  154. prefect/server/ui-v2/assets/python-example-snippet-DRHcUlCX.js +3 -0
  155. prefect/server/ui-v2/assets/{python-example-snippet-DfCFYPN_.js.map → python-example-snippet-DRHcUlCX.js.map} +1 -1
  156. prefect/server/ui-v2/assets/{python-input-mr6GD840.js → python-input-BsUS8fw1.js} +2 -2
  157. prefect/server/ui-v2/assets/{python-input-mr6GD840.js.map → python-input-BsUS8fw1.js.map} +1 -1
  158. prefect/server/ui-v2/assets/{radio-group-Co3cN0Kv.js → radio-group-BUsmwdrt.js} +2 -2
  159. prefect/server/ui-v2/assets/{radio-group-Co3cN0Kv.js.map → radio-group-BUsmwdrt.js.map} +1 -1
  160. prefect/server/ui-v2/assets/{route-error-state-DnBaNT2T.js → route-error-state-BFBpiIhD.js} +2 -2
  161. prefect/server/ui-v2/assets/{route-error-state-DnBaNT2T.js.map → route-error-state-BFBpiIhD.js.map} +1 -1
  162. prefect/server/ui-v2/assets/{schema-form-CWDHSME9.js → schema-form-BwTmkvJk.js} +2 -2
  163. prefect/server/ui-v2/assets/schema-form-BwTmkvJk.js.map +1 -0
  164. prefect/server/ui-v2/assets/{schema-form-input-string-format-datetime-BSWlW_aQ.js → schema-form-input-string-format-datetime-nrb3g-JJ.js} +4 -4
  165. prefect/server/ui-v2/assets/{schema-form-input-string-format-datetime-BSWlW_aQ.js.map → schema-form-input-string-format-datetime-nrb3g-JJ.js.map} +1 -1
  166. prefect/server/ui-v2/assets/{settings-DU5y6tJE.js → settings-CUBtK5aW.js} +2 -2
  167. prefect/server/ui-v2/assets/{settings-DU5y6tJE.js.map → settings-CUBtK5aW.js.map} +1 -1
  168. prefect/server/ui-v2/assets/{sort-filter-DpuWNkQo.js → sort-filter-Cv8zAXMp.js} +2 -2
  169. prefect/server/ui-v2/assets/{sort-filter-DpuWNkQo.js.map → sort-filter-Cv8zAXMp.js.map} +1 -1
  170. prefect/server/ui-v2/assets/{table-bBL6C0ZK.js → table-BBNGfPra.js} +2 -2
  171. prefect/server/ui-v2/assets/{table-bBL6C0ZK.js.map → table-BBNGfPra.js.map} +1 -1
  172. prefect/server/ui-v2/assets/{tags-input-BLPMVWpZ.js → tags-input-DHrnkwjQ.js} +2 -2
  173. prefect/server/ui-v2/assets/{tags-input-BLPMVWpZ.js.map → tags-input-DHrnkwjQ.js.map} +1 -1
  174. prefect/server/ui-v2/assets/task-run-concurrency-limits-reset-dialog-Z8-yFZ2_.js +2 -0
  175. prefect/server/ui-v2/assets/{task-run-concurrency-limits-reset-dialog-S69sih55.js.map → task-run-concurrency-limits-reset-dialog-Z8-yFZ2_.js.map} +1 -1
  176. prefect/server/ui-v2/assets/{task-run._id-Dl3Azs8t.js → task-run._id-BY58gqs2.js} +2 -2
  177. prefect/server/ui-v2/assets/{task-run._id-Dl3Azs8t.js.map → task-run._id-BY58gqs2.js.map} +1 -1
  178. prefect/server/ui-v2/assets/{task-run._id-B_tIDm4K.js → task-run._id-u73Jxfqw.js} +3 -3
  179. prefect/server/ui-v2/assets/{task-run._id-B_tIDm4K.js.map → task-run._id-u73Jxfqw.js.map} +1 -1
  180. prefect/server/ui-v2/assets/task-runs-pagination-DUy3147A.js +2 -0
  181. prefect/server/ui-v2/assets/{task-runs-pagination-VdR-LO4r.js.map → task-runs-pagination-DUy3147A.js.map} +1 -1
  182. prefect/server/ui-v2/assets/{textarea-B3_TtPRi.js → textarea-DUhh6-kq.js} +2 -2
  183. prefect/server/ui-v2/assets/{textarea-B3_TtPRi.js.map → textarea-DUhh6-kq.js.map} +1 -1
  184. prefect/server/ui-v2/assets/timezone-select-D4Q6VBtD.js +2 -0
  185. prefect/server/ui-v2/assets/{timezone-select-BuPYznge.js.map → timezone-select-D4Q6VBtD.js.map} +1 -1
  186. prefect/server/ui-v2/assets/{toggle-group-Cn07UIim.js → toggle-group-7WUJn2Tx.js} +2 -2
  187. prefect/server/ui-v2/assets/{toggle-group-Cn07UIim.js.map → toggle-group-7WUJn2Tx.js.map} +1 -1
  188. prefect/server/ui-v2/assets/use-delete-automation-confirmation-dialog-D4AD5Ndf.js +2 -0
  189. prefect/server/ui-v2/assets/{use-delete-automation-confirmation-dialog-DpdsLH4t.js.map → use-delete-automation-confirmation-dialog-D4AD5Ndf.js.map} +1 -1
  190. prefect/server/ui-v2/assets/{use-delete-block-document-confirmation-dialog-Cq5nGhzr.js → use-delete-block-document-confirmation-dialog-DnwWEGUY.js} +2 -2
  191. prefect/server/ui-v2/assets/{use-delete-block-document-confirmation-dialog-Cq5nGhzr.js.map → use-delete-block-document-confirmation-dialog-DnwWEGUY.js.map} +1 -1
  192. prefect/server/ui-v2/assets/{use-flow-runs-selected-rows-DmQSWBTu.js → use-flow-runs-selected-rows-C-tehPRB.js} +2 -2
  193. prefect/server/ui-v2/assets/{use-flow-runs-selected-rows-DmQSWBTu.js.map → use-flow-runs-selected-rows-C-tehPRB.js.map} +1 -1
  194. prefect/server/ui-v2/assets/{use-get-artifacts-flow-task-runs-DTwcWiqW.js → use-get-artifacts-flow-task-runs-DRWRrmrb.js} +2 -2
  195. prefect/server/ui-v2/assets/{use-get-artifacts-flow-task-runs-DTwcWiqW.js.map → use-get-artifacts-flow-task-runs-DRWRrmrb.js.map} +1 -1
  196. prefect/server/ui-v2/assets/{use-quick-run-CPempwLh.js → use-quick-run-B4Xj-YQQ.js} +2 -2
  197. prefect/server/ui-v2/assets/{use-quick-run-CPempwLh.js.map → use-quick-run-B4Xj-YQQ.js.map} +1 -1
  198. prefect/server/ui-v2/assets/use-state-favicon-au2TZdMV.js +2 -0
  199. prefect/server/ui-v2/assets/{use-state-favicon-M09DmrNy.js.map → use-state-favicon-au2TZdMV.js.map} +1 -1
  200. prefect/server/ui-v2/assets/{use-stepper-CDucnvzp.js → use-stepper-DyIb3vlq.js} +2 -2
  201. prefect/server/ui-v2/assets/{use-stepper-CDucnvzp.js.map → use-stepper-DyIb3vlq.js.map} +1 -1
  202. prefect/server/ui-v2/assets/{utilities-BRCNRcQl.js → utilities-D9Y2wo66.js} +2 -2
  203. prefect/server/ui-v2/assets/{utilities-BRCNRcQl.js.map → utilities-D9Y2wo66.js.map} +1 -1
  204. prefect/server/ui-v2/assets/vendor-recharts-BvvJP9Po.js +34 -0
  205. prefect/server/ui-v2/assets/vendor-recharts-BvvJP9Po.js.map +1 -0
  206. prefect/server/ui-v2/assets/{work-pool-filter-C2tpSS-w.js → work-pool-filter-CSOATj2D.js} +2 -2
  207. prefect/server/ui-v2/assets/{work-pool-filter-C2tpSS-w.js.map → work-pool-filter-CSOATj2D.js.map} +1 -1
  208. prefect/server/ui-v2/assets/work-pool-queue-toggle-Dh7B1zMo.js +2 -0
  209. prefect/server/ui-v2/assets/{work-pool-queue-toggle-BQ9b-Wxy.js.map → work-pool-queue-toggle-Dh7B1zMo.js.map} +1 -1
  210. prefect/server/ui-v2/assets/work-pool._workPoolName-B_NFWXKS.js +2 -0
  211. prefect/server/ui-v2/assets/{work-pool._workPoolName-C_LiL3SE.js.map → work-pool._workPoolName-B_NFWXKS.js.map} +1 -1
  212. prefect/server/ui-v2/assets/{work-pool_._workPoolName.edit-DBHlrVVx.js → work-pool_._workPoolName.edit-Cyzn8g-S.js} +2 -2
  213. prefect/server/ui-v2/assets/{work-pool_._workPoolName.edit-DBHlrVVx.js.map → work-pool_._workPoolName.edit-Cyzn8g-S.js.map} +1 -1
  214. prefect/server/ui-v2/assets/{work-pool_._workPoolName.queue._workQueueName-DkITxJOP.js → work-pool_._workPoolName.queue._workQueueName-DQzqQWPT.js} +2 -2
  215. prefect/server/ui-v2/assets/{work-pool_._workPoolName.queue._workQueueName-DkITxJOP.js.map → work-pool_._workPoolName.queue._workQueueName-DQzqQWPT.js.map} +1 -1
  216. prefect/server/ui-v2/assets/{work-queue-icon-text-D4BWBVDN.js → work-queue-icon-text-BOpcJ8YU.js} +2 -2
  217. prefect/server/ui-v2/assets/{work-queue-icon-text-D4BWBVDN.js.map → work-queue-icon-text-BOpcJ8YU.js.map} +1 -1
  218. prefect/server/ui-v2/index.html +3 -3
  219. {prefect-3.6.15.dist-info → prefect-3.6.16.dev3.dist-info}/METADATA +2 -1
  220. {prefect-3.6.15.dist-info → prefect-3.6.16.dev3.dist-info}/RECORD +223 -211
  221. prefect/server/ui-v2/assets/artifact._id-BFdf1WUA.js +0 -2
  222. prefect/server/ui-v2/assets/artifact._id-BFdf1WUA.js.map +0 -1
  223. prefect/server/ui-v2/assets/automation._id-Dn7jABys.js +0 -2
  224. prefect/server/ui-v2/assets/block-type-logo-Cbpfxded.js +0 -2
  225. prefect/server/ui-v2/assets/block-type-logo-Cbpfxded.js.map +0 -1
  226. prefect/server/ui-v2/assets/catalog_._slug-Bl2J2oI3.js +0 -2
  227. prefect/server/ui-v2/assets/create-D--LHaji.js +0 -2
  228. prefect/server/ui-v2/assets/data-table-rlbkLcrY.js +0 -2
  229. prefect/server/ui-v2/assets/data-table-rlbkLcrY.js.map +0 -1
  230. prefect/server/ui-v2/assets/delete-confirmation-dialog-DHkm2p8m.js +0 -2
  231. prefect/server/ui-v2/assets/deployment._id-Ci9zge5n.js +0 -2
  232. prefect/server/ui-v2/assets/deployment_._id.duplicate-D9ZWkh8H.js +0 -2
  233. prefect/server/ui-v2/assets/deployment_._id.edit-CS7sObzC.js +0 -2
  234. prefect/server/ui-v2/assets/event._eventDate._eventId-D7Twzb22.js +0 -2
  235. prefect/server/ui-v2/assets/flow-run._id-RLy2kBh0.js +0 -4
  236. prefect/server/ui-v2/assets/flow._id-BdQGWPKP.js +0 -2
  237. prefect/server/ui-v2/assets/index-7i4X9TeK.js +0 -2
  238. prefect/server/ui-v2/assets/index-BkiGTHwU.js +0 -2
  239. prefect/server/ui-v2/assets/index-BkiGTHwU.js.map +0 -1
  240. prefect/server/ui-v2/assets/index-COouj_0-.css +0 -1
  241. prefect/server/ui-v2/assets/index-CiSFHkhI.js +0 -2
  242. prefect/server/ui-v2/assets/index-DATPYZfT.js +0 -2
  243. prefect/server/ui-v2/assets/index-DATPYZfT.js.map +0 -1
  244. prefect/server/ui-v2/assets/index-VH4TnZ4e.js +0 -2
  245. prefect/server/ui-v2/assets/index-VH4TnZ4e.js.map +0 -1
  246. prefect/server/ui-v2/assets/python-example-snippet-DfCFYPN_.js +0 -3
  247. prefect/server/ui-v2/assets/schema-form-CWDHSME9.js.map +0 -1
  248. prefect/server/ui-v2/assets/task-run-concurrency-limits-reset-dialog-S69sih55.js +0 -2
  249. prefect/server/ui-v2/assets/task-runs-pagination-VdR-LO4r.js +0 -2
  250. prefect/server/ui-v2/assets/timezone-select-BuPYznge.js +0 -2
  251. prefect/server/ui-v2/assets/use-delete-automation-confirmation-dialog-DpdsLH4t.js +0 -2
  252. prefect/server/ui-v2/assets/use-state-favicon-M09DmrNy.js +0 -2
  253. prefect/server/ui-v2/assets/vendor-recharts-BAN776s_.js +0 -34
  254. prefect/server/ui-v2/assets/vendor-recharts-BAN776s_.js.map +0 -1
  255. prefect/server/ui-v2/assets/work-pool-queue-toggle-BQ9b-Wxy.js +0 -2
  256. prefect/server/ui-v2/assets/work-pool._workPoolName-C_LiL3SE.js +0 -2
  257. {prefect-3.6.15.dist-info → prefect-3.6.16.dev3.dist-info}/WHEEL +0 -0
  258. {prefect-3.6.15.dist-info → prefect-3.6.16.dev3.dist-info}/entry_points.txt +0 -0
  259. {prefect-3.6.15.dist-info → prefect-3.6.16.dev3.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-BpKoubXu.js","sources":["../../src/components/flow-runs/flow-runs-list/flow-runs-filters/date-range-filter.tsx","../../src/components/flow-runs/flow-runs-list/flow-runs-filters/flow-filter.tsx","../../src/components/task-runs/task-runs-list/use-delete-task-runs-dialog.ts","../../src/components/task-runs/task-runs-list/task-runs-row-count.tsx","../../src/components/task-runs/task-runs-list/use-task-runs-selected-rows.ts","../../src/components/flow-runs/flow-runs-list/flow-runs-filters/saved-filters-menu.tsx","../../src/components/flow-runs/flow-runs-scatter-plot/scatter-plot-utils.ts","../../src/components/flow-runs/flow-runs-scatter-plot/flow-runs-scatter-plot.tsx","../../src/components/runs/save-filter-dialog.tsx","../../src/components/runs/use-saved-filters.ts","../../src/components/runs/runs-page.tsx","../../src/components/runs/use-runs-saved-filters.ts","../../src/hooks/use-runs-filters.ts","../../src/routes/runs/index.tsx?tsr-split=component"],"sourcesContent":["import { useMemo } from \"react\";\nimport {\n\ttype DateRangeSelectValue,\n\tRichDateRangeSelector,\n} from \"@/components/ui/date-range-select\";\nimport {\n\ttype DateRangeUrlState,\n\tdateRangeValueToUrlState,\n\turlStateToDateRangeValue,\n} from \"./date-range-url-state\";\n\ntype DateRangeFilterProps = {\n\tvalue: DateRangeUrlState;\n\tonValueChange: (value: DateRangeUrlState) => void;\n\tclassName?: string;\n};\n\n/**\n * DateRangeFilter component for filtering flow runs by date range.\n * Wraps RichDateRangeSelector and handles URL state serialization.\n */\nexport const DateRangeFilter = ({\n\tvalue,\n\tonValueChange,\n\tclassName,\n}: DateRangeFilterProps) => {\n\tconst dateRangeValue = useMemo(\n\t\t() => urlStateToDateRangeValue(value),\n\t\t[value],\n\t);\n\n\tconst handleValueChange = (newValue: DateRangeSelectValue) => {\n\t\tonValueChange(dateRangeValueToUrlState(newValue));\n\t};\n\n\treturn (\n\t\t<RichDateRangeSelector\n\t\t\tvalue={dateRangeValue}\n\t\t\tonValueChange={handleValueChange}\n\t\t\tplaceholder=\"All time\"\n\t\t\tclearable\n\t\t\tclassName={className}\n\t\t/>\n\t);\n};\n","import { useQuery } from \"@tanstack/react-query\";\nimport { useDeferredValue, useMemo, useState } from \"react\";\nimport { buildListFlowsQuery, type Flow } from \"@/api/flows\";\nimport { Checkbox } from \"@/components/ui/checkbox\";\nimport {\n\tCombobox,\n\tComboboxCommandEmtpy,\n\tComboboxCommandGroup,\n\tComboboxCommandInput,\n\tComboboxCommandItem,\n\tComboboxCommandList,\n\tComboboxContent,\n\tComboboxTrigger,\n} from \"@/components/ui/combobox\";\nimport { Typography } from \"@/components/ui/typography\";\n\nconst MAX_FLOWS_DISPLAYED = 2;\n\ntype FlowFilterProps = {\n\tselectedFlows: Set<string>;\n\tonSelectFlows: (flows: Set<string>) => void;\n};\n\nexport const FlowFilter = ({\n\tselectedFlows,\n\tonSelectFlows,\n}: FlowFilterProps) => {\n\tconst [search, setSearch] = useState(\"\");\n\tconst deferredSearch = useDeferredValue(search);\n\n\tconst { data: flows = [] } = useQuery(\n\t\tbuildListFlowsQuery({\n\t\t\tflows: deferredSearch\n\t\t\t\t? {\n\t\t\t\t\t\toperator: \"and_\",\n\t\t\t\t\t\tname: { like_: deferredSearch },\n\t\t\t\t\t}\n\t\t\t\t: undefined,\n\t\t\tlimit: 100,\n\t\t\toffset: 0,\n\t\t\tsort: \"NAME_ASC\",\n\t\t}),\n\t);\n\n\tconst { data: selectedFlowsData = [] } = useQuery(\n\t\tbuildListFlowsQuery(\n\t\t\t{\n\t\t\t\tflows:\n\t\t\t\t\tselectedFlows.size > 0\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\toperator: \"and_\",\n\t\t\t\t\t\t\t\tid: { any_: Array.from(selectedFlows) },\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: undefined,\n\t\t\t\tlimit: selectedFlows.size || 1,\n\t\t\t\toffset: 0,\n\t\t\t\tsort: \"NAME_ASC\",\n\t\t\t},\n\t\t\t{ enabled: selectedFlows.size > 0 },\n\t\t),\n\t);\n\n\tconst handleSelectFlow = (flowId: string) => {\n\t\tconst updatedFlows = new Set(selectedFlows);\n\t\tif (selectedFlows.has(flowId)) {\n\t\t\tupdatedFlows.delete(flowId);\n\t\t} else {\n\t\t\tupdatedFlows.add(flowId);\n\t\t}\n\t\tonSelectFlows(updatedFlows);\n\t};\n\n\tconst handleClearAll = () => {\n\t\tonSelectFlows(new Set());\n\t};\n\n\tconst renderSelectedFlows = () => {\n\t\tif (selectedFlows.size === 0) {\n\t\t\treturn \"All flows\";\n\t\t}\n\n\t\tconst selectedFlowNames = selectedFlowsData\n\t\t\t.filter((flow) => selectedFlows.has(flow.id))\n\t\t\t.map((flow) => flow.name);\n\n\t\tconst visible = selectedFlowNames.slice(0, MAX_FLOWS_DISPLAYED);\n\t\tconst extraCount = selectedFlowNames.length - MAX_FLOWS_DISPLAYED;\n\n\t\treturn (\n\t\t\t<div className=\"flex flex-1 min-w-0 items-center gap-2\">\n\t\t\t\t<div className=\"flex flex-1 min-w-0 items-center gap-2 overflow-hidden\">\n\t\t\t\t\t<span className=\"truncate\">{visible.join(\", \")}</span>\n\t\t\t\t</div>\n\t\t\t\t{extraCount > 0 && (\n\t\t\t\t\t<Typography variant=\"bodySmall\" className=\"shrink-0\">\n\t\t\t\t\t\t+ {extraCount}\n\t\t\t\t\t</Typography>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t);\n\t};\n\n\tconst filteredFlows = useMemo(() => {\n\t\treturn flows.filter(\n\t\t\t(flow: Flow) =>\n\t\t\t\t!deferredSearch ||\n\t\t\t\tflow.name.toLowerCase().includes(deferredSearch.toLowerCase()),\n\t\t);\n\t}, [flows, deferredSearch]);\n\n\treturn (\n\t\t<Combobox>\n\t\t\t<ComboboxTrigger\n\t\t\t\taria-label=\"Filter by flow\"\n\t\t\t\tselected={selectedFlows.size === 0}\n\t\t\t>\n\t\t\t\t{renderSelectedFlows()}\n\t\t\t</ComboboxTrigger>\n\t\t\t<ComboboxContent>\n\t\t\t\t<ComboboxCommandInput\n\t\t\t\t\tvalue={search}\n\t\t\t\t\tonValueChange={setSearch}\n\t\t\t\t\tplaceholder=\"Search flows...\"\n\t\t\t\t/>\n\t\t\t\t<ComboboxCommandList>\n\t\t\t\t\t<ComboboxCommandEmtpy>No flows found</ComboboxCommandEmtpy>\n\t\t\t\t\t<ComboboxCommandGroup>\n\t\t\t\t\t\t<ComboboxCommandItem\n\t\t\t\t\t\t\taria-label=\"All flows\"\n\t\t\t\t\t\t\tonSelect={handleClearAll}\n\t\t\t\t\t\t\tcloseOnSelect={false}\n\t\t\t\t\t\t\tvalue=\"__all__\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Checkbox checked={selectedFlows.size === 0} />\n\t\t\t\t\t\t\tAll flows\n\t\t\t\t\t\t</ComboboxCommandItem>\n\t\t\t\t\t\t{filteredFlows.map((flow: Flow) => (\n\t\t\t\t\t\t\t<ComboboxCommandItem\n\t\t\t\t\t\t\t\tkey={flow.id}\n\t\t\t\t\t\t\t\taria-label={flow.name}\n\t\t\t\t\t\t\t\tonSelect={() => handleSelectFlow(flow.id)}\n\t\t\t\t\t\t\t\tcloseOnSelect={false}\n\t\t\t\t\t\t\t\tvalue={flow.id}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Checkbox checked={selectedFlows.has(flow.id)} />\n\t\t\t\t\t\t\t\t{flow.name}\n\t\t\t\t\t\t\t</ComboboxCommandItem>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</ComboboxCommandGroup>\n\t\t\t\t</ComboboxCommandList>\n\t\t\t</ComboboxContent>\n\t\t</Combobox>\n\t);\n};\n","import { toast } from \"sonner\";\nimport { useDeleteTaskRun } from \"@/api/task-runs\";\nimport { useDeleteConfirmationDialog } from \"@/components/ui/delete-confirmation-dialog\";\n\nexport const useDeleteTaskRunsDialog = () => {\n\tconst [dialogState, confirmDelete] = useDeleteConfirmationDialog();\n\n\tconst { mutateAsync } = useDeleteTaskRun();\n\n\tconst handleDeletes = async (\n\t\ttaskRunIds: Array<string>,\n\t\tonConfirm = () => {},\n\t) => {\n\t\ttry {\n\t\t\tconst res = await Promise.allSettled(\n\t\t\t\ttaskRunIds.map((id) => mutateAsync({ id })),\n\t\t\t);\n\t\t\tconst { numFails, numSuccess } = res.reduce(\n\t\t\t\t(accumulator, currentValue) => {\n\t\t\t\t\tif (currentValue.status === \"rejected\") {\n\t\t\t\t\t\taccumulator.numFails += 1;\n\t\t\t\t\t} else {\n\t\t\t\t\t\taccumulator.numSuccess += 1;\n\t\t\t\t\t}\n\t\t\t\t\treturn accumulator;\n\t\t\t\t},\n\t\t\t\t{ numFails: 0, numSuccess: 0 },\n\t\t\t);\n\t\t\tif (numFails > 1) {\n\t\t\t\ttoast.error(`${numFails} task runs failed to delete`);\n\t\t\t} else if (numFails === 1) {\n\t\t\t\ttoast.error(\"Task run failed to delete\");\n\t\t\t} else if (numSuccess > 1) {\n\t\t\t\ttoast.success(`${numSuccess} task runs deleted`);\n\t\t\t} else {\n\t\t\t\ttoast.success(\"Task run deleted\");\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tconsole.error(\"Unknown error while deleting task run.\", err);\n\t\t} finally {\n\t\t\tonConfirm();\n\t\t}\n\t};\n\n\tconst handleConfirmDelete = (\n\t\ttaskRunIds: Array<string>,\n\t\tonConfirm = () => {},\n\t) =>\n\t\tconfirmDelete({\n\t\t\ttitle: \"Delete Task Runs\",\n\t\t\tdescription: \"Are you sure you want to delete selected task runs?\",\n\t\t\tonConfirm: () => {\n\t\t\t\tvoid handleDeletes(taskRunIds, onConfirm);\n\t\t\t},\n\t\t});\n\n\treturn [dialogState, handleConfirmDelete] as const;\n};\n","import type { CheckedState } from \"@radix-ui/react-checkbox\";\nimport { useMemo } from \"react\";\nimport type { TaskRunResponse } from \"@/api/task-runs\";\nimport { Button } from \"@/components/ui/button\";\nimport { Checkbox } from \"@/components/ui/checkbox\";\nimport { DeleteConfirmationDialog } from \"@/components/ui/delete-confirmation-dialog\";\nimport { Icon } from \"@/components/ui/icons\";\nimport { Typography } from \"@/components/ui/typography\";\nimport { pluralize } from \"@/utils\";\nimport { useDeleteTaskRunsDialog } from \"./use-delete-task-runs-dialog\";\n\ntype CountOnlyProps = {\n\tcount: number | undefined;\n};\ntype SelectableProps = {\n\tcount: number | undefined;\n\tresults: Array<TaskRunResponse> | undefined;\n\tsetSelectedRows: (rows: Set<string>) => void;\n\tselectedRows: Set<string>;\n};\ntype TaskRunsRowCountProps = CountOnlyProps | SelectableProps;\n\nexport const TaskRunsRowCount = ({\n\tcount = 0,\n\t...props\n}: TaskRunsRowCountProps) => {\n\t// Selectable UX\n\tif (\n\t\t\"results\" in props &&\n\t\t\"setSelectedRows\" in props &&\n\t\t\"selectedRows\" in props\n\t) {\n\t\treturn <SelectedCount count={count} {...props} />;\n\t}\n\n\t// Count only UX\n\treturn (\n\t\t<Typography variant=\"bodySmall\" className=\"text-muted-foreground\">\n\t\t\t{count} {pluralize(count, \"Task run\")}\n\t\t</Typography>\n\t);\n};\n\nfunction SelectedCount({\n\tcount = 0,\n\tresults = [],\n\tsetSelectedRows,\n\tselectedRows,\n}: SelectableProps) {\n\tconst [deleteConfirmationDialogState, confirmDelete] =\n\t\tuseDeleteTaskRunsDialog();\n\n\tconst resultsIds = useMemo(() => results.map(({ id }) => id), [results]);\n\n\tconst selectedRowsList = Array.from(selectedRows);\n\n\tconst ToggleCheckbox = () => {\n\t\tconst isAllRowsSelected = resultsIds.every((id) => selectedRows.has(id));\n\t\tconst isSomeRowsSelected = resultsIds.some((id) => selectedRows.has(id));\n\t\tlet checkedState: CheckedState = false;\n\t\tif (isAllRowsSelected) {\n\t\t\tcheckedState = true;\n\t\t} else if (isSomeRowsSelected) {\n\t\t\tcheckedState = \"indeterminate\";\n\t\t}\n\t\treturn (\n\t\t\t<Checkbox\n\t\t\t\tclassName=\"block\"\n\t\t\t\tchecked={checkedState}\n\t\t\t\tonCheckedChange={(checked) => {\n\t\t\t\t\tif (checked) {\n\t\t\t\t\t\tsetSelectedRows(new Set(resultsIds));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsetSelectedRows(new Set());\n\t\t\t\t\t}\n\t\t\t\t}}\n\t\t\t\taria-label=\"Toggle all\"\n\t\t\t/>\n\t\t);\n\t};\n\n\t// If has selected rows\n\tif (selectedRows.size > 0)\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t<ToggleCheckbox />\n\t\t\t\t\t<Typography variant=\"bodySmall\" className=\"text-muted-foreground\">\n\t\t\t\t\t\t{selectedRowsList.length} selected\n\t\t\t\t\t</Typography>\n\t\t\t\t\t<Button\n\t\t\t\t\t\taria-label=\"Delete rows\"\n\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\tconfirmDelete(selectedRowsList, () => setSelectedRows(new Set()));\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<Icon id=\"Trash2\" className=\"size-4\" />\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\t\t\t\t<DeleteConfirmationDialog {...deleteConfirmationDialogState} />\n\t\t\t</>\n\t\t);\n\n\treturn (\n\t\t<div className=\"flex items-center gap-2\">\n\t\t\t{results && setSelectedRows && selectedRows && (\n\t\t\t\t<Checkbox\n\t\t\t\t\tclassName=\"block\"\n\t\t\t\t\tchecked={false}\n\t\t\t\t\tonCheckedChange={(checked) => {\n\t\t\t\t\t\tsetSelectedRows(new Set(checked ? resultsIds : undefined));\n\t\t\t\t\t}}\n\t\t\t\t\taria-label=\"Toggle all\"\n\t\t\t\t/>\n\t\t\t)}\n\t\t\t<Typography variant=\"bodySmall\" className=\"text-muted-foreground\">\n\t\t\t\t{count} {pluralize(count, \"Task run\")}\n\t\t\t</Typography>\n\t\t</div>\n\t);\n}\n","import { useState } from \"react\";\n\nexport const useTaskRunsSelectedRows = (defaultValues?: Array<string>) => {\n\tconst [selectedRows, setSelectedRows] = useState<Set<string>>(\n\t\tnew Set(defaultValues),\n\t);\n\n\tconst addRow = (id: string) =>\n\t\tsetSelectedRows((curr) => new Set(curr).add(id));\n\n\tconst removeRow = (id: string) =>\n\t\tsetSelectedRows((curr) => {\n\t\t\tconst newValue = new Set(curr);\n\t\t\tnewValue.delete(id);\n\t\t\treturn newValue;\n\t\t});\n\n\tconst onSelectRow = (id: string, checked: boolean) => {\n\t\tif (checked) {\n\t\t\taddRow(id);\n\t\t} else {\n\t\t\tremoveRow(id);\n\t\t}\n\t};\n\n\tconst clearSet = () => setSelectedRows(new Set());\n\n\tconst utils = {\n\t\taddRow,\n\t\tremoveRow,\n\t\tonSelectRow,\n\t\tclearSet,\n\t};\n\n\treturn [selectedRows, setSelectedRows, utils] as const;\n};\n","import { useState } from \"react\";\nimport { Button } from \"@/components/ui/button\";\nimport { DeleteConfirmationDialog } from \"@/components/ui/delete-confirmation-dialog/delete-confirmation-dialog\";\nimport {\n\tDropdownMenu,\n\tDropdownMenuContent,\n\tDropdownMenuItem,\n\tDropdownMenuSeparator,\n\tDropdownMenuTrigger,\n} from \"@/components/ui/dropdown-menu\";\nimport { Icon } from \"@/components/ui/icons\";\n\nexport type SavedFilter = {\n\tid: string | null;\n\tname: string;\n\tisDefault: boolean;\n};\n\nexport type SavedFiltersMenuPermissions = {\n\tcanSave: boolean;\n\tcanDelete: boolean;\n};\n\nexport type SavedFiltersMenuProps = {\n\tcurrentFilter: SavedFilter | null;\n\tsavedFilters: SavedFilter[];\n\tonSelect: (filter: SavedFilter) => void;\n\tonSave: () => void;\n\tonDelete: (id: string) => void;\n\tonSetDefault: (id: string) => void;\n\tonRemoveDefault: (id: string) => void;\n\tpermissions?: SavedFiltersMenuPermissions;\n};\n\nconst CUSTOM_FILTER_NAME = \"Custom\";\nconst UNSAVED_FILTER_NAME = \"Unsaved\";\n\nfunction isCustomOrUnsavedFilter(filter: SavedFilter | null): boolean {\n\tif (!filter) return true;\n\treturn (\n\t\tfilter.name === CUSTOM_FILTER_NAME || filter.name === UNSAVED_FILTER_NAME\n\t);\n}\n\nexport const SavedFiltersMenu = ({\n\tcurrentFilter,\n\tsavedFilters,\n\tonSelect,\n\tonSave,\n\tonDelete,\n\tonSetDefault,\n\tonRemoveDefault,\n\tpermissions = { canSave: true, canDelete: true },\n}: SavedFiltersMenuProps) => {\n\tconst [showDeleteDialog, setShowDeleteDialog] = useState(false);\n\n\tconst displayName = currentFilter?.name ?? CUSTOM_FILTER_NAME;\n\tconst isCustomUnsaved = isCustomOrUnsavedFilter(currentFilter);\n\tconst canSave = isCustomUnsaved && permissions.canSave;\n\tconst canDelete = currentFilter?.id && permissions.canDelete;\n\tconst canToggleDefault = !isCustomUnsaved;\n\n\tconst handleDelete = () => {\n\t\tif (!currentFilter?.id) return;\n\t\tonDelete(currentFilter.id);\n\t\tsetShowDeleteDialog(false);\n\t};\n\n\tconst handleToggleDefault = () => {\n\t\tif (!currentFilter?.id) return;\n\t\tif (currentFilter.isDefault) {\n\t\t\tonRemoveDefault(currentFilter.id);\n\t\t} else {\n\t\t\tonSetDefault(currentFilter.id);\n\t\t}\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<DropdownMenu>\n\t\t\t\t<DropdownMenuTrigger asChild>\n\t\t\t\t\t<Button variant=\"outline\" className=\"gap-2\">\n\t\t\t\t\t\t<Icon id=\"SlidersVertical\" className=\"size-4\" />\n\t\t\t\t\t\t<span>{displayName}</span>\n\t\t\t\t\t\t<Icon id=\"ChevronDown\" className=\"size-4\" />\n\t\t\t\t\t</Button>\n\t\t\t\t</DropdownMenuTrigger>\n\t\t\t\t<DropdownMenuContent align=\"start\" className=\"min-w-[200px]\">\n\t\t\t\t\t{savedFilters.map((filter) => (\n\t\t\t\t\t\t<DropdownMenuItem\n\t\t\t\t\t\t\tkey={filter.id ?? filter.name}\n\t\t\t\t\t\t\tonClick={() => onSelect(filter)}\n\t\t\t\t\t\t\tclassName=\"flex items-center justify-between\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<span>{filter.name}</span>\n\t\t\t\t\t\t\t{filter.isDefault && (\n\t\t\t\t\t\t\t\t<Icon id=\"CircleCheck\" className=\"size-4 text-green-500\" />\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</DropdownMenuItem>\n\t\t\t\t\t))}\n\n\t\t\t\t\t{(canSave || canDelete || canToggleDefault) && (\n\t\t\t\t\t\t<DropdownMenuSeparator />\n\t\t\t\t\t)}\n\n\t\t\t\t\t{canSave && (\n\t\t\t\t\t\t<DropdownMenuItem onClick={onSave}>\n\t\t\t\t\t\t\t<Icon id=\"Plus\" className=\"mr-2 size-4\" />\n\t\t\t\t\t\t\tSave current filters\n\t\t\t\t\t\t</DropdownMenuItem>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{canDelete && (\n\t\t\t\t\t\t<DropdownMenuItem\n\t\t\t\t\t\t\tvariant=\"destructive\"\n\t\t\t\t\t\t\tonClick={() => setShowDeleteDialog(true)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Icon id=\"Trash2\" className=\"mr-2 size-4\" />\n\t\t\t\t\t\t\tDelete\n\t\t\t\t\t\t</DropdownMenuItem>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{canToggleDefault && (\n\t\t\t\t\t\t<DropdownMenuItem onClick={handleToggleDefault}>\n\t\t\t\t\t\t\t<Icon id=\"CircleCheck\" className=\"mr-2 size-4\" />\n\t\t\t\t\t\t\t{currentFilter?.isDefault\n\t\t\t\t\t\t\t\t? \"Remove as default\"\n\t\t\t\t\t\t\t\t: \"Set as default\"}\n\t\t\t\t\t\t</DropdownMenuItem>\n\t\t\t\t\t)}\n\t\t\t\t</DropdownMenuContent>\n\t\t\t</DropdownMenu>\n\n\t\t\t<DeleteConfirmationDialog\n\t\t\t\tisOpen={showDeleteDialog}\n\t\t\t\ttitle=\"Delete saved filter\"\n\t\t\t\tdescription={`Are you sure you want to delete \"${currentFilter?.name}\"? This action cannot be undone.`}\n\t\t\t\tonConfirm={handleDelete}\n\t\t\t\tonClose={() => setShowDeleteDialog(false)}\n\t\t\t/>\n\t\t</>\n\t);\n};\n","/**\n * Utility functions for scatter plot axis formatting and tick generation.\n * These are separated from the component to avoid React Fast Refresh warnings.\n */\n\n/**\n * Formats a duration value (in seconds) to a compact string representation.\n * Examples: \"0s\", \"0.50s\", \"30s\", \"5m\", \"2h\", \"3d\", \"1y\"\n */\nexport const formatYAxisTick = (value: number): string => {\n\tif (value === 0) return \"0s\";\n\tif (value < 1) return `${value.toFixed(2)}s`;\n\n\tconst SECONDS_PER_YEAR = 31536000;\n\tconst SECONDS_PER_DAY = 86400;\n\tconst SECONDS_PER_HOUR = 3600;\n\tconst SECONDS_PER_MINUTE = 60;\n\n\tconst years = Math.floor(value / SECONDS_PER_YEAR);\n\tif (years > 0) return `${years}y`;\n\n\tconst days = Math.floor(value / SECONDS_PER_DAY);\n\tif (days > 0) return `${days}d`;\n\n\tconst hours = Math.floor(value / SECONDS_PER_HOUR);\n\tif (hours > 0) return `${hours}h`;\n\n\tconst minutes = Math.floor(value / SECONDS_PER_MINUTE);\n\tif (minutes > 0) return `${minutes}m`;\n\n\treturn `${Math.ceil(value)}s`;\n};\n\n/**\n * Standard time intervals for generating \"nice\" tick values.\n * Similar to D3's time scale tick generation.\n */\nexport const TIME_INTERVALS = [\n\t{ ms: 1000, name: \"second\" },\n\t{ ms: 5 * 1000, name: \"5seconds\" },\n\t{ ms: 15 * 1000, name: \"15seconds\" },\n\t{ ms: 30 * 1000, name: \"30seconds\" },\n\t{ ms: 60 * 1000, name: \"minute\" },\n\t{ ms: 5 * 60 * 1000, name: \"5minutes\" },\n\t{ ms: 15 * 60 * 1000, name: \"15minutes\" },\n\t{ ms: 30 * 60 * 1000, name: \"30minutes\" },\n\t{ ms: 60 * 60 * 1000, name: \"hour\" },\n\t{ ms: 3 * 60 * 60 * 1000, name: \"3hours\" },\n\t{ ms: 6 * 60 * 60 * 1000, name: \"6hours\" },\n\t{ ms: 12 * 60 * 60 * 1000, name: \"12hours\" },\n\t{ ms: 24 * 60 * 60 * 1000, name: \"day\" },\n\t{ ms: 7 * 24 * 60 * 60 * 1000, name: \"week\" },\n\t{ ms: 30 * 24 * 60 * 60 * 1000, name: \"month\" },\n];\n\n/**\n * Generates tick values aligned with \"nice\" time boundaries.\n * Similar to D3's time scale tick generation, this ensures ticks fall on\n * natural boundaries like hour marks, day boundaries, etc.\n */\nexport const generateNiceTimeTicks = (\n\tstartMs: number,\n\tendMs: number,\n\ttargetTickCount: number,\n): number[] => {\n\tconst range = endMs - startMs;\n\tif (range <= 0) return [startMs];\n\n\tconst idealInterval = range / targetTickCount;\n\tlet chosenInterval = TIME_INTERVALS[0].ms;\n\tfor (const interval of TIME_INTERVALS) {\n\t\tif (interval.ms >= idealInterval) {\n\t\t\tchosenInterval = interval.ms;\n\t\t\tbreak;\n\t\t}\n\t\tchosenInterval = interval.ms;\n\t}\n\n\tconst firstTick = Math.ceil(startMs / chosenInterval) * chosenInterval;\n\tconst ticks: number[] = [];\n\tfor (let tick = firstTick; tick <= endMs; tick += chosenInterval) {\n\t\tticks.push(tick);\n\t}\n\n\tif (ticks.length === 0) {\n\t\tticks.push(startMs);\n\t}\n\n\treturn ticks;\n};\n\n/**\n * Creates a formatter for X-axis tick labels based on time boundaries.\n * Uses V1's hierarchical approach: checks which time boundary the timestamp\n * crosses (millisecond, second, minute, hour, day, month, year) and formats accordingly.\n */\nexport const createXAxisTickFormatter = () => {\n\treturn (value: number): string => {\n\t\tconst date = new Date(value);\n\n\t\tconst second = new Date(date);\n\t\tsecond.setMilliseconds(0);\n\t\tif (second.getTime() < date.getTime()) {\n\t\t\treturn `.${date.getMilliseconds().toString().padStart(3, \"0\").slice(0, 3)}`;\n\t\t}\n\n\t\tconst minute = new Date(date);\n\t\tminute.setSeconds(0, 0);\n\t\tif (minute.getTime() < date.getTime()) {\n\t\t\treturn `:${date.getSeconds().toString().padStart(2, \"0\")}`;\n\t\t}\n\n\t\tconst hour = new Date(date);\n\t\thour.setMinutes(0, 0, 0);\n\t\tif (hour.getTime() < date.getTime()) {\n\t\t\treturn date.toLocaleTimeString(undefined, {\n\t\t\t\thour: \"numeric\",\n\t\t\t\tminute: \"2-digit\",\n\t\t\t});\n\t\t}\n\n\t\tconst day = new Date(date);\n\t\tday.setHours(0, 0, 0, 0);\n\t\tif (day.getTime() < date.getTime()) {\n\t\t\treturn date.toLocaleTimeString(undefined, {\n\t\t\t\thour: \"numeric\",\n\t\t\t\thour12: true,\n\t\t\t});\n\t\t}\n\n\t\tconst month = new Date(date);\n\t\tmonth.setDate(1);\n\t\tmonth.setHours(0, 0, 0, 0);\n\t\tif (month.getTime() < date.getTime()) {\n\t\t\treturn date.toLocaleDateString(undefined, {\n\t\t\t\tweekday: \"short\",\n\t\t\t\tday: \"numeric\",\n\t\t\t});\n\t\t}\n\n\t\tconst year = new Date(date);\n\t\tyear.setMonth(0, 1);\n\t\tyear.setHours(0, 0, 0, 0);\n\t\tif (year.getTime() < date.getTime()) {\n\t\t\treturn date.toLocaleDateString(undefined, { month: \"long\" });\n\t\t}\n\n\t\treturn date.getFullYear().toString();\n\t};\n};\n","import { useQuery } from \"@tanstack/react-query\";\nimport { Link } from \"@tanstack/react-router\";\nimport humanizeDuration from \"humanize-duration\";\nimport { Calendar, ChevronRight, Clock } from \"lucide-react\";\nimport { useMemo } from \"react\";\nimport {\n\tCartesianGrid,\n\tResponsiveContainer,\n\tScatter,\n\tScatterChart,\n\tTooltip,\n\tXAxis,\n\tYAxis,\n} from \"recharts\";\nimport {\n\tbuildGetFlowRunDetailsQuery,\n\ttype SimpleFlowRun,\n} from \"@/api/flow-runs\";\nimport { buildFLowDetailsQuery } from \"@/api/flows\";\nimport type { components } from \"@/api/prefect\";\nimport { StateBadge } from \"@/components/ui/state-badge\";\nimport { getStateColor, STATE_COLORS } from \"@/utils/state-colors\";\nimport {\n\tcreateXAxisTickFormatter,\n\tformatYAxisTick,\n\tgenerateNiceTimeTicks,\n} from \"./scatter-plot-utils\";\n\ntype FlowRunsScatterPlotProps = {\n\thistory: SimpleFlowRun[];\n\tstartDate?: Date;\n\tendDate?: Date;\n};\n\ntype ChartDataPoint = {\n\tx: number;\n\ty: number;\n\tstateType: components[\"schemas\"][\"StateType\"];\n\tid: string;\n\tduration: number;\n\tlateness: number;\n\ttimestamp: string;\n};\n\ntype CustomDotProps = {\n\tcx?: number;\n\tcy?: number;\n\tpayload?: ChartDataPoint;\n};\n\nconst CustomDot = ({ cx, cy, payload }: CustomDotProps) => {\n\tif (cx === undefined || cy === undefined || !payload) {\n\t\treturn null;\n\t}\n\n\t// Use 500 shade for fill, 600 shade for border (matching V1)\n\tconst fillColor =\n\t\tgetStateColor(payload.stateType, 500) ||\n\t\tSTATE_COLORS[payload.stateType] ||\n\t\t\"#6b7280\";\n\tconst strokeColor =\n\t\tgetStateColor(payload.stateType, 600) ||\n\t\tSTATE_COLORS[payload.stateType] ||\n\t\t\"#6b7280\";\n\n\treturn (\n\t\t<circle\n\t\t\tcx={cx}\n\t\t\tcy={cy}\n\t\t\tr={8}\n\t\t\tfill={fillColor}\n\t\t\tstroke={strokeColor}\n\t\t\tstrokeWidth={1}\n\t\t\topacity={0.5}\n\t\t\tclassName=\"hover:opacity-100 transition-opacity cursor-pointer\"\n\t\t/>\n\t);\n};\n\ntype FlowRunTooltipPayload = {\n\tpayload?: ChartDataPoint;\n};\n\ntype FlowRunTooltipProps = {\n\tactive?: boolean;\n\tpayload?: FlowRunTooltipPayload[];\n};\n\nconst FlowRunTooltip = ({ active, payload }: FlowRunTooltipProps) => {\n\tconst firstPayload = payload?.[0];\n\tconst data = firstPayload?.payload;\n\tconst flowRunId = data?.id;\n\n\t// Fetch flow run details when tooltip is active\n\tconst { data: flowRun } = useQuery({\n\t\t...buildGetFlowRunDetailsQuery(flowRunId ?? \"\"),\n\t\tenabled: active && Boolean(flowRunId),\n\t\tstaleTime: 5 * 60 * 1000, // 5 minutes to avoid refetching on mouse movement\n\t});\n\n\t// Fetch flow details when we have flow_id\n\tconst { data: flow } = useQuery({\n\t\t...buildFLowDetailsQuery(flowRun?.flow_id ?? \"\"),\n\t\tenabled: Boolean(flowRun?.flow_id),\n\t\tstaleTime: 5 * 60 * 1000,\n\t});\n\n\tif (!active || !payload || payload.length === 0 || !data) {\n\t\treturn null;\n\t}\n\n\tconst startTime = new Date(data.timestamp);\n\n\treturn (\n\t\t<div className=\"bg-background border rounded-lg p-3 shadow-lg flex flex-col gap-2 min-w-48\">\n\t\t\t{/* Flow name and flow run name breadcrumbs */}\n\t\t\t<div className=\"flex items-center gap-1 text-sm text-muted-foreground\">\n\t\t\t\t{flowRun?.flow_id && (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\tto=\"/flows/flow/$id\"\n\t\t\t\t\t\t\tparams={{ id: flowRun.flow_id }}\n\t\t\t\t\t\t\tclassName=\"font-semibold hover:underline truncate max-w-32\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{flow?.name ?? \"...\"}\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t<ChevronRight className=\"size-3 flex-shrink-0\" />\n\t\t\t\t\t</>\n\t\t\t\t)}\n\t\t\t\t<Link\n\t\t\t\t\tto=\"/runs/flow-run/$id\"\n\t\t\t\t\tparams={{ id: data.id }}\n\t\t\t\t\tclassName=\"hover:underline truncate max-w-32\"\n\t\t\t\t>\n\t\t\t\t\t{flowRun?.name ?? data.id.slice(0, 8)}\n\t\t\t\t</Link>\n\t\t\t</div>\n\t\t\t<div>\n\t\t\t\t<StateBadge type={data.stateType} />\n\t\t\t</div>\n\t\t\t<hr className=\"border-border\" />\n\t\t\t<div className=\"flex flex-col gap-1\">\n\t\t\t\t<span className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n\t\t\t\t\t<Clock className=\"size-4\" />\n\t\t\t\t\t{humanizeDuration(Math.ceil(data.duration * 1000), {\n\t\t\t\t\t\tlargest: 2,\n\t\t\t\t\t\tround: true,\n\t\t\t\t\t})}\n\t\t\t\t</span>\n\t\t\t\t<span className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n\t\t\t\t\t<Calendar className=\"size-4\" />\n\t\t\t\t\t{startTime.toLocaleString()}\n\t\t\t\t</span>\n\t\t\t</div>\n\t\t</div>\n\t);\n};\n\nexport const FlowRunsScatterPlot = ({\n\thistory,\n\tstartDate,\n\tendDate,\n}: FlowRunsScatterPlotProps) => {\n\tconst chartData = useMemo<ChartDataPoint[]>(() => {\n\t\treturn history.map((item) => ({\n\t\t\tx: new Date(item.timestamp).getTime(),\n\t\t\ty: item.duration,\n\t\t\tstateType: item.state_type,\n\t\t\tid: item.id,\n\t\t\tduration: item.duration,\n\t\t\tlateness: item.lateness,\n\t\t\ttimestamp: item.timestamp,\n\t\t}));\n\t}, [history]);\n\n\t// Compute actual numeric domain for x-axis\n\tconst xDomain = useMemo(() => {\n\t\tif (startDate && endDate) {\n\t\t\treturn [startDate.getTime(), endDate.getTime()] as [number, number];\n\t\t}\n\t\tif (chartData.length === 0) {\n\t\t\tconst now = Date.now();\n\t\t\tconst dayAgo = now - 24 * 60 * 60 * 1000;\n\t\t\treturn [dayAgo, now] as [number, number];\n\t\t}\n\t\t// Compute from data\n\t\tconst timestamps = chartData.map((d) => d.x);\n\t\tconst min = Math.min(...timestamps);\n\t\tconst max = Math.max(...timestamps);\n\t\treturn [min, max] as [number, number];\n\t}, [startDate, endDate, chartData]);\n\n\t// Create memoized X-axis formatter\n\tconst formatXAxisTick = useMemo(() => createXAxisTickFormatter(), []);\n\n\t// Generate explicit tick values for X-axis aligned with nice time boundaries\n\tconst xAxisTicks = useMemo(() => {\n\t\treturn generateNiceTimeTicks(xDomain[0], xDomain[1], 10);\n\t}, [xDomain]);\n\n\tif (history.length === 0) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<div className=\"hidden md:block w-full h-72\" data-testid=\"scatter-plot\">\n\t\t\t<ResponsiveContainer width=\"100%\" height=\"100%\">\n\t\t\t\t<ScatterChart>\n\t\t\t\t\t<CartesianGrid\n\t\t\t\t\t\thorizontal={true}\n\t\t\t\t\t\tvertical={false}\n\t\t\t\t\t\tstroke=\"#cacccf\"\n\t\t\t\t\t\tstrokeDasharray=\"\"\n\t\t\t\t\t/>\n\t\t\t\t\t<XAxis\n\t\t\t\t\t\ttype=\"number\"\n\t\t\t\t\t\tdataKey=\"x\"\n\t\t\t\t\t\tscale=\"time\"\n\t\t\t\t\t\tdomain={xDomain}\n\t\t\t\t\t\tticks={xAxisTicks}\n\t\t\t\t\t\ttickFormatter={formatXAxisTick}\n\t\t\t\t\t\ttick={{ fontSize: 12 }}\n\t\t\t\t\t\ttickLine={false}\n\t\t\t\t\t\taxisLine={{ stroke: \"#e5e7eb\" }}\n\t\t\t\t\t/>\n\t\t\t\t\t<YAxis\n\t\t\t\t\t\ttype=\"number\"\n\t\t\t\t\t\tdataKey=\"y\"\n\t\t\t\t\t\ttickFormatter={formatYAxisTick}\n\t\t\t\t\t\ttick={{ fontSize: 12 }}\n\t\t\t\t\t\ttickLine={false}\n\t\t\t\t\t\taxisLine={{ stroke: \"#e5e7eb\" }}\n\t\t\t\t\t\twidth={60}\n\t\t\t\t\t/>\n\t\t\t\t\t<Tooltip\n\t\t\t\t\t\tcontent={<FlowRunTooltip />}\n\t\t\t\t\t\tcursor={{ strokeDasharray: \"3 3\" }}\n\t\t\t\t\t\tanimationDuration={0}\n\t\t\t\t\t/>\n\t\t\t\t\t<Scatter\n\t\t\t\t\t\tdata={chartData}\n\t\t\t\t\t\tshape={<CustomDot />}\n\t\t\t\t\t\tisAnimationActive={false}\n\t\t\t\t\t/>\n\t\t\t\t</ScatterChart>\n\t\t\t</ResponsiveContainer>\n\t\t</div>\n\t);\n};\n","import { zodResolver } from \"@hookform/resolvers/zod\";\nimport { useEffect } from \"react\";\nimport { useForm } from \"react-hook-form\";\nimport { z } from \"zod\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n\tDialog,\n\tDialogContent,\n\tDialogDescription,\n\tDialogFooter,\n\tDialogHeader,\n\tDialogTitle,\n} from \"@/components/ui/dialog\";\nimport {\n\tForm,\n\tFormControl,\n\tFormField,\n\tFormItem,\n\tFormLabel,\n\tFormMessage,\n} from \"@/components/ui/form\";\nimport { Input } from \"@/components/ui/input\";\n\nconst formSchema = z.object({\n\tname: z\n\t\t.string()\n\t\t.min(1, { message: \"Name is required\" })\n\t\t.max(100, { message: \"Name must be 100 characters or less\" }),\n});\n\ntype FormValues = z.infer<typeof formSchema>;\n\nexport type SaveFilterDialogProps = {\n\topen: boolean;\n\tonOpenChange: (open: boolean) => void;\n\tonSave: (name: string) => void;\n};\n\nexport const SaveFilterDialog = ({\n\topen,\n\tonOpenChange,\n\tonSave,\n}: SaveFilterDialogProps) => {\n\tconst form = useForm<FormValues>({\n\t\tresolver: zodResolver(formSchema),\n\t\tdefaultValues: {\n\t\t\tname: \"\",\n\t\t},\n\t});\n\n\tuseEffect(() => {\n\t\tif (open) {\n\t\t\tform.reset({ name: \"\" });\n\t\t}\n\t}, [open, form]);\n\n\tconst onSubmit = (values: FormValues) => {\n\t\tonSave(values.name);\n\t\tonOpenChange(false);\n\t};\n\n\treturn (\n\t\t<Dialog open={open} onOpenChange={onOpenChange}>\n\t\t\t<DialogContent>\n\t\t\t\t<DialogHeader>\n\t\t\t\t\t<DialogTitle>Save Filter</DialogTitle>\n\t\t\t\t</DialogHeader>\n\t\t\t\t<DialogDescription>\n\t\t\t\t\tSave your current filter configuration for quick access later.\n\t\t\t\t</DialogDescription>\n\t\t\t\t<Form {...form}>\n\t\t\t\t\t<form\n\t\t\t\t\t\tonSubmit={(e) => void form.handleSubmit(onSubmit)(e)}\n\t\t\t\t\t\tclassName=\"space-y-4\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\tname=\"name\"\n\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t\t<FormLabel>Filter Name</FormLabel>\n\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\t\t\t\t\tplaceholder=\"e.g., Failed runs this week\"\n\t\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<DialogFooter>\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\t\t\tonClick={() => onOpenChange(false)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tCancel\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t<Button type=\"submit\">Save</Button>\n\t\t\t\t\t\t</DialogFooter>\n\t\t\t\t\t</form>\n\t\t\t\t</Form>\n\t\t\t</DialogContent>\n\t\t</Dialog>\n\t);\n};\n","import { useCallback, useMemo } from \"react\";\nimport type {\n\tDateRangePreset,\n\tDateRangeUrlState,\n} from \"@/components/flow-runs/flow-runs-list/flow-runs-filters/date-range-url-state\";\nimport {\n\tFLOW_RUN_STATES_WITHOUT_SCHEDULED,\n\ttype FlowRunState,\n} from \"@/components/flow-runs/flow-runs-list/flow-runs-filters/state-filters.constants\";\nimport { useLocalStorage } from \"@/hooks/use-local-storage\";\n\n/**\n * LocalStorage Key Naming Convention\n *\n * Following the Vue UI pattern (prefect-ui-library-custom-default-flow-runs-filter),\n * we use the following keys for the React UI:\n *\n * - `prefect-ui-v2-saved-filters`: Array of saved filter objects\n * - `prefect-ui-v2-default-filter-id`: ID of the filter marked as default (or null)\n *\n * This naming convention:\n * 1. Prefixes with \"prefect-ui-v2\" to namespace and avoid conflicts\n * 2. Uses kebab-case for consistency with web conventions\n * 3. Clearly describes the stored data\n */\nconst SAVED_FILTERS_STORAGE_KEY = \"prefect-ui-v2-saved-filters\";\nconst DEFAULT_FILTER_ID_STORAGE_KEY = \"prefect-ui-v2-default-filter-id\";\n\n/**\n * System filter IDs - prefixed to distinguish from user-generated IDs.\n * These filters are always available and cannot be deleted.\n */\nexport const SYSTEM_FILTER_PAST_WEEK_ID = \"system-past-week\";\nexport const SYSTEM_FILTER_HIDE_SCHEDULED_ID = \"system-hide-scheduled\";\n\n/**\n * Checks if a filter ID belongs to a system filter.\n * System filters cannot be deleted or modified.\n */\nexport function isSystemFilter(id: string | null): boolean {\n\treturn (\n\t\tid === SYSTEM_FILTER_PAST_WEEK_ID || id === SYSTEM_FILTER_HIDE_SCHEDULED_ID\n\t);\n}\n\n/**\n * System filters that are always available in the saved filters menu.\n * These match the Vue UI's systemSavedSearches from prefect-ui-library.\n *\n * - \"Past week\": Default filter applied on page load, filters to last 7 days\n * - \"Hide scheduled runs\": Filters to last 7 days and excludes scheduled-type states\n */\nexport const SYSTEM_FILTERS: SavedFilter[] = [\n\t{\n\t\tid: SYSTEM_FILTER_PAST_WEEK_ID,\n\t\tname: \"Past week\",\n\t\tfilters: { range: \"past-7-days\" },\n\t},\n\t{\n\t\tid: SYSTEM_FILTER_HIDE_SCHEDULED_ID,\n\t\tname: \"Hide scheduled runs\",\n\t\tfilters: {\n\t\t\trange: \"past-7-days\",\n\t\t\tstate: [...FLOW_RUN_STATES_WITHOUT_SCHEDULED],\n\t\t},\n\t},\n];\n\n/**\n * The default system filter to apply when no filters are active and no user default is set.\n * Matches Vue's systemDefaultSavedSearch.\n */\nexport const SYSTEM_DEFAULT_FILTER = SYSTEM_FILTERS[0];\n\n/**\n * Filter values stored in a SavedFilter.\n *\n * Design decisions:\n * - Uses arrays instead of comma-separated strings for consistency with the Vue UI\n * implementation and better data structure maintainability\n * - Uses camelCase property names (workPools) while URL parameters use kebab-case (work-pools)\n * See URL_PARAM_TO_FILTER_KEY_MAP for the transformation mapping\n * - Date range uses the same structure as DateRangeUrlState for compatibility\n *\n * Integration with useRunsFilters:\n * - useRunsFilters uses Set<string> for filter values; convert with Array.from() / new Set()\n * - useRunsFilters uses comma-separated strings in URL params; this uses arrays for storage\n */\nexport type SavedFilterValues = {\n\tstate?: FlowRunState[];\n\tflows?: string[];\n\tdeployments?: string[];\n\tworkPools?: string[];\n\ttags?: string[];\n\trange?: DateRangePreset;\n\tstart?: string;\n\tend?: string;\n};\n\n/**\n * A saved filter configuration that can be persisted to localStorage.\n *\n * The id field uses a timestamp-based UUID for uniqueness.\n * The isDefault field is computed at runtime based on DEFAULT_FILTER_ID_STORAGE_KEY,\n * not stored in the filter object itself.\n */\nexport type SavedFilter = {\n\tid: string;\n\tname: string;\n\tfilters: SavedFilterValues;\n};\n\n/**\n * Input type for creating a new saved filter (id is generated automatically).\n */\nexport type SavedFilterCreate = {\n\tname: string;\n\tfilters: SavedFilterValues;\n};\n\n/**\n * Mapping between URL parameter names (kebab-case) and SavedFilterValues property names (camelCase).\n *\n * This transformation is needed because:\n * - URL parameters use kebab-case for web conventions (e.g., \"work-pools\")\n * - TypeScript/JavaScript properties use camelCase (e.g., \"workPools\")\n *\n * When integrating with useRunsFilters, use this mapping to convert between formats:\n * - URL → SavedFilter: urlParamToFilterKey[urlParam]\n * - SavedFilter → URL: filterKeyToUrlParam[filterKey]\n */\nexport const URL_PARAM_TO_FILTER_KEY_MAP = {\n\tstate: \"state\",\n\tflows: \"flows\",\n\tdeployments: \"deployments\",\n\t\"work-pools\": \"workPools\",\n\ttags: \"tags\",\n\trange: \"range\",\n\tstart: \"start\",\n\tend: \"end\",\n} as const;\n\nexport const FILTER_KEY_TO_URL_PARAM_MAP = {\n\tstate: \"state\",\n\tflows: \"flows\",\n\tdeployments: \"deployments\",\n\tworkPools: \"work-pools\",\n\ttags: \"tags\",\n\trange: \"range\",\n\tstart: \"start\",\n\tend: \"end\",\n} as const;\n\n/**\n * Generates a unique ID for a saved filter using timestamp and random string.\n */\nfunction generateFilterId(): string {\n\treturn `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\n}\n\n/**\n * Compares two SavedFilterValues objects for equality.\n *\n * This is used to determine if the current filter state matches a saved filter.\n * Arrays are compared by sorting and checking element equality.\n * Date range fields are compared directly.\n *\n * Based on the Vue UI's isSameFilter pattern from src/utilities/savedFilters.ts\n */\nexport function areFiltersEqual(\n\tfilterA: SavedFilterValues,\n\tfilterB: SavedFilterValues,\n): boolean {\n\tconst sortedArrayEqual = (\n\t\ta: string[] | undefined,\n\t\tb: string[] | undefined,\n\t): boolean => {\n\t\tif (a === undefined && b === undefined) return true;\n\t\tif (a === undefined || b === undefined) return false;\n\t\tif (a.length !== b.length) return false;\n\t\tconst sortedA = [...a].sort();\n\t\tconst sortedB = [...b].sort();\n\t\treturn sortedA.every((val, idx) => val === sortedB[idx]);\n\t};\n\n\treturn (\n\t\tsortedArrayEqual(filterA.state, filterB.state) &&\n\t\tsortedArrayEqual(filterA.flows, filterB.flows) &&\n\t\tsortedArrayEqual(filterA.deployments, filterB.deployments) &&\n\t\tsortedArrayEqual(filterA.workPools, filterB.workPools) &&\n\t\tsortedArrayEqual(filterA.tags, filterB.tags) &&\n\t\tfilterA.range === filterB.range &&\n\t\tfilterA.start === filterB.start &&\n\t\tfilterA.end === filterB.end\n\t);\n}\n\n/**\n * Converts SavedFilterValues to DateRangeUrlState for use with existing components.\n */\nexport function filterValuesToDateRangeUrlState(\n\tfilters: SavedFilterValues,\n): DateRangeUrlState {\n\treturn {\n\t\trange: filters.range,\n\t\tstart: filters.start,\n\t\tend: filters.end,\n\t};\n}\n\n/**\n * Converts DateRangeUrlState to partial SavedFilterValues.\n */\nexport function dateRangeUrlStateToFilterValues(\n\tdateRange: DateRangeUrlState,\n): Pick<SavedFilterValues, \"range\" | \"start\" | \"end\"> {\n\treturn {\n\t\trange: dateRange.range,\n\t\tstart: dateRange.start,\n\t\tend: dateRange.end,\n\t};\n}\n\nexport type UseSavedFiltersReturn = {\n\tsavedFilters: SavedFilter[];\n\tdefaultFilterId: string | null;\n\tsaveFilter: (filter: SavedFilterCreate) => SavedFilter;\n\tdeleteFilter: (filterId: string) => void;\n\tupdateFilter: (filterId: string, updates: Partial<SavedFilterCreate>) => void;\n\tsetDefaultFilter: (filterId: string | null) => void;\n\tgetFilterById: (filterId: string) => SavedFilter | undefined;\n\tfindMatchingFilter: (filters: SavedFilterValues) => SavedFilter | undefined;\n\tisDefaultFilter: (filterId: string) => boolean;\n};\n\n/**\n * Hook for managing saved filters in localStorage.\n *\n * This hook provides CRUD operations for saved filters and manages the default filter setting.\n * It uses the existing useLocalStorage hook for persistence.\n *\n * Usage:\n * ```tsx\n * const {\n * savedFilters,\n * defaultFilterId,\n * saveFilter,\n * deleteFilter,\n * setDefaultFilter,\n * findMatchingFilter,\n * } = useSavedFilters();\n *\n * // Save current filters\n * const newFilter = saveFilter({ name: \"My Filter\", filters: currentFilters });\n *\n * // Set as default\n * setDefaultFilter(newFilter.id);\n *\n * // Check if current filters match a saved filter\n * const matchingFilter = findMatchingFilter(currentFilters);\n * ```\n *\n * Integration with useRunsFilters:\n * When integrating with the existing useRunsFilters hook, you'll need to:\n * 1. Convert Set<string> to string[] when saving: Array.from(filters.states)\n * 2. Convert string[] to Set<string> when applying: new Set(savedFilter.filters.state)\n * 3. Map URL param names using URL_PARAM_TO_FILTER_KEY_MAP / FILTER_KEY_TO_URL_PARAM_MAP\n */\nexport function useSavedFilters(): UseSavedFiltersReturn {\n\tconst [userSavedFilters, setUserSavedFilters] = useLocalStorage<\n\t\tSavedFilter[]\n\t>(SAVED_FILTERS_STORAGE_KEY, []);\n\n\tconst [defaultFilterId, setDefaultFilterId] = useLocalStorage<string | null>(\n\t\tDEFAULT_FILTER_ID_STORAGE_KEY,\n\t\tnull,\n\t);\n\n\t// Combine system filters with user-saved filters\n\t// System filters appear first, followed by user-saved filters\n\tconst savedFilters = useMemo(\n\t\t() => [...SYSTEM_FILTERS, ...userSavedFilters],\n\t\t[userSavedFilters],\n\t);\n\n\tconst saveFilter = useCallback(\n\t\t(filterCreate: SavedFilterCreate): SavedFilter => {\n\t\t\tconst newFilter: SavedFilter = {\n\t\t\t\tid: generateFilterId(),\n\t\t\t\tname: filterCreate.name,\n\t\t\t\tfilters: filterCreate.filters,\n\t\t\t};\n\t\t\tsetUserSavedFilters((prev) => [...prev, newFilter]);\n\t\t\treturn newFilter;\n\t\t},\n\t\t[setUserSavedFilters],\n\t);\n\n\tconst deleteFilter = useCallback(\n\t\t(filterId: string): void => {\n\t\t\tsetUserSavedFilters((prev) => prev.filter((f) => f.id !== filterId));\n\t\t\tsetDefaultFilterId((prev) => (prev === filterId ? null : prev));\n\t\t},\n\t\t[setUserSavedFilters, setDefaultFilterId],\n\t);\n\n\tconst updateFilter = useCallback(\n\t\t(filterId: string, updates: Partial<SavedFilterCreate>): void => {\n\t\t\tsetUserSavedFilters((prev) =>\n\t\t\t\tprev.map((f) =>\n\t\t\t\t\tf.id === filterId\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t...f,\n\t\t\t\t\t\t\t\t...(updates.name !== undefined && { name: updates.name }),\n\t\t\t\t\t\t\t\t...(updates.filters !== undefined && {\n\t\t\t\t\t\t\t\t\tfilters: updates.filters,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: f,\n\t\t\t\t),\n\t\t\t);\n\t\t},\n\t\t[setUserSavedFilters],\n\t);\n\n\tconst setDefaultFilter = useCallback(\n\t\t(filterId: string | null): void => {\n\t\t\tsetDefaultFilterId(filterId);\n\t\t},\n\t\t[setDefaultFilterId],\n\t);\n\n\tconst getFilterById = useCallback(\n\t\t(filterId: string): SavedFilter | undefined => {\n\t\t\treturn savedFilters.find((f) => f.id === filterId);\n\t\t},\n\t\t[savedFilters],\n\t);\n\n\tconst findMatchingFilter = useCallback(\n\t\t(filters: SavedFilterValues): SavedFilter | undefined => {\n\t\t\treturn savedFilters.find((f) => areFiltersEqual(f.filters, filters));\n\t\t},\n\t\t[savedFilters],\n\t);\n\n\tconst isDefaultFilter = useMemo(\n\t\t() =>\n\t\t\t(filterId: string): boolean => {\n\t\t\t\treturn defaultFilterId === filterId;\n\t\t\t},\n\t\t[defaultFilterId],\n\t);\n\n\treturn {\n\t\tsavedFilters,\n\t\tdefaultFilterId,\n\t\tsaveFilter,\n\t\tdeleteFilter,\n\t\tupdateFilter,\n\t\tsetDefaultFilter,\n\t\tgetFilterById,\n\t\tfindMatchingFilter,\n\t\tisDefaultFilter,\n\t};\n}\n","import { useQuery } from \"@tanstack/react-query\";\nimport type { ChangeEvent } from \"react\";\nimport type { FlowRun, SimpleFlowRun } from \"@/api/flow-runs\";\nimport { buildListFlowsQuery } from \"@/api/flows\";\nimport type { TaskRunResponse } from \"@/api/task-runs\";\nimport type { FlowRunCardData } from \"@/components/flow-runs/flow-run-card\";\nimport {\n\tDateRangeFilter,\n\ttype DateRangeUrlState,\n\tDeploymentFilter,\n\tFlowFilter,\n\ttype FlowRunState,\n\tFlowRunsList,\n\tFlowRunsPagination,\n\tFlowRunsRowCount,\n\ttype PaginationState,\n\ttype SortFilters,\n\tuseFlowRunsSelectedRows,\n} from \"@/components/flow-runs/flow-runs-list\";\nimport {\n\ttype SavedFilter,\n\tSavedFiltersMenu,\n} from \"@/components/flow-runs/flow-runs-list/flow-runs-filters/saved-filters-menu\";\nimport { SortFilter } from \"@/components/flow-runs/flow-runs-list/flow-runs-filters/sort-filter\";\nimport { StateFilter } from \"@/components/flow-runs/flow-runs-list/flow-runs-filters/state-filter\";\nimport { WorkPoolFilter } from \"@/components/flow-runs/flow-runs-list/flow-runs-filters/work-pool-filter\";\nimport { FlowRunsScatterPlot } from \"@/components/flow-runs/flow-runs-scatter-plot\";\nimport {\n\ttype TaskRunSortFilters,\n\tTaskRunsList,\n\tTaskRunsPagination,\n\tTaskRunsRowCount,\n\tTaskRunsSortFilter,\n\tuseTaskRunsSelectedRows,\n} from \"@/components/task-runs/task-runs-list\";\nimport {\n\tBreadcrumb,\n\tBreadcrumbItem,\n\tBreadcrumbList,\n} from \"@/components/ui/breadcrumb\";\nimport { Card, CardContent } from \"@/components/ui/card\";\nimport { DocsLink } from \"@/components/ui/docs-link\";\nimport {\n\tEmptyState,\n\tEmptyStateActions,\n\tEmptyStateDescription,\n\tEmptyStateIcon,\n\tEmptyStateTitle,\n} from \"@/components/ui/empty-state\";\nimport { SearchInput } from \"@/components/ui/input\";\nimport { Label } from \"@/components/ui/label\";\nimport { Switch } from \"@/components/ui/switch\";\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from \"@/components/ui/tabs\";\nimport { TagsInput } from \"@/components/ui/tags-input\";\nimport { SaveFilterDialog } from \"./save-filter-dialog\";\nimport { isSystemFilter } from \"./use-saved-filters\";\n\ntype RunsPageProps = {\n\ttab: \"flow-runs\" | \"task-runs\";\n\tonTabChange: (tab: string) => void;\n\tflowRunsCount: number;\n\ttaskRunsCount: number;\n\t/** Whether any flow runs exist (unfiltered) - used for empty state check */\n\thasAnyFlowRuns: boolean;\n\t/** Whether any task runs exist (unfiltered) - used for empty state check */\n\thasAnyTaskRuns: boolean;\n\t// Flow runs props\n\tflowRuns: FlowRun[];\n\tflowRunsPages: number;\n\tpagination: PaginationState;\n\tonPaginationChange: (pagination: PaginationState) => void;\n\tonPrefetchPage?: (page: number) => void;\n\tsort: SortFilters;\n\tonSortChange: (sort: SortFilters) => void;\n\thideSubflows: boolean;\n\tonHideSubflowsChange: (hideSubflows: boolean) => void;\n\tflowRunSearch: string;\n\tonFlowRunSearchChange: (search: string) => void;\n\tselectedStates: Set<FlowRunState>;\n\tonStateFilterChange: (states: Set<FlowRunState>) => void;\n\tselectedFlows: Set<string>;\n\tonFlowFilterChange: (flows: Set<string>) => void;\n\tselectedDeployments: Set<string>;\n\tonDeploymentFilterChange: (deployments: Set<string>) => void;\n\tselectedTags: Set<string>;\n\tonTagsFilterChange: (tags: Set<string>) => void;\n\tselectedWorkPools: Set<string>;\n\tonWorkPoolFilterChange: (workPools: Set<string>) => void;\n\tdateRange: DateRangeUrlState;\n\tonDateRangeChange: (dateRange: DateRangeUrlState) => void;\n\t// Scatter plot props\n\tflowRunHistory: SimpleFlowRun[];\n\tscatterPlotDateRange: { startDate?: Date; endDate?: Date };\n\t// Task runs props\n\ttaskRuns: TaskRunResponse[];\n\ttaskRunsPages: number;\n\ttaskRunsPagination: PaginationState;\n\tonTaskRunsPaginationChange: (pagination: PaginationState) => void;\n\tonTaskRunsPrefetchPage?: (page: number) => void;\n\ttaskRunsSort: TaskRunSortFilters;\n\tonTaskRunsSortChange: (sort: TaskRunSortFilters) => void;\n\ttaskRunSearch: string;\n\tonTaskRunSearchChange: (search: string) => void;\n\tonClearTaskRunFilters: () => void;\n\t// Saved filters props\n\tcurrentFilter: SavedFilter | null;\n\tsavedFilters: SavedFilter[];\n\tonSelectFilter: (filter: SavedFilter) => void;\n\tonSaveFilter: () => void;\n\tonDeleteFilter: (id: string) => void;\n\tonSetDefault: (id: string) => void;\n\tonRemoveDefault: (id: string) => void;\n\tisSaveDialogOpen: boolean;\n\tonCloseSaveDialog: () => void;\n\tonConfirmSave: (name: string) => void;\n};\n\nexport const RunsPage = ({\n\ttab,\n\tonTabChange,\n\tflowRunsCount,\n\ttaskRunsCount,\n\thasAnyFlowRuns,\n\thasAnyTaskRuns,\n\t// Flow runs props\n\tflowRuns,\n\tflowRunsPages,\n\tpagination,\n\tonPaginationChange,\n\tonPrefetchPage,\n\tsort,\n\tonSortChange,\n\thideSubflows,\n\tonHideSubflowsChange,\n\tflowRunSearch,\n\tonFlowRunSearchChange,\n\tselectedStates,\n\tonStateFilterChange,\n\tselectedFlows,\n\tonFlowFilterChange,\n\tselectedDeployments,\n\tonDeploymentFilterChange,\n\tselectedTags,\n\tonTagsFilterChange,\n\tselectedWorkPools,\n\tonWorkPoolFilterChange,\n\tdateRange,\n\tonDateRangeChange,\n\t// Scatter plot props\n\tflowRunHistory,\n\tscatterPlotDateRange,\n\t// Task runs props\n\ttaskRuns,\n\ttaskRunsPages,\n\ttaskRunsPagination,\n\tonTaskRunsPaginationChange,\n\tonTaskRunsPrefetchPage,\n\ttaskRunsSort,\n\tonTaskRunsSortChange,\n\ttaskRunSearch,\n\tonTaskRunSearchChange,\n\tonClearTaskRunFilters,\n\t// Saved filters props\n\tcurrentFilter,\n\tsavedFilters,\n\tonSelectFilter,\n\tonSaveFilter,\n\tonDeleteFilter,\n\tonSetDefault,\n\tonRemoveDefault,\n\tisSaveDialogOpen,\n\tonCloseSaveDialog,\n\tonConfirmSave,\n}: RunsPageProps) => {\n\t// Use unfiltered counts for empty state check (no runs exist at all)\n\tconst isEmpty = !hasAnyFlowRuns && !hasAnyTaskRuns;\n\n\t// Flow runs selection\n\tconst [selectedRows, setSelectedRows, { onSelectRow }] =\n\t\tuseFlowRunsSelectedRows();\n\n\t// Task runs selection\n\tconst [\n\t\ttaskRunsSelectedRows,\n\t\tsetTaskRunsSelectedRows,\n\t\t{ onSelectRow: onSelectTaskRunRow },\n\t] = useTaskRunsSelectedRows();\n\n\tconst flowIds = [...new Set(flowRuns.map((flowRun) => flowRun.flow_id))];\n\n\tconst { data: flows } = useQuery(\n\t\tbuildListFlowsQuery(\n\t\t\t{\n\t\t\t\tflows: {\n\t\t\t\t\toperator: \"and_\",\n\t\t\t\t\tid: { any_: flowIds },\n\t\t\t\t},\n\t\t\t\toffset: 0,\n\t\t\t\tsort: \"NAME_ASC\",\n\t\t\t},\n\t\t\t{ enabled: flowIds.length > 0 },\n\t\t),\n\t);\n\n\tconst flowRunsWithFlows: FlowRunCardData[] = flowRuns.map((flowRun) => ({\n\t\t...flowRun,\n\t\tflow: flows?.find((flow) => flow.id === flowRun.flow_id),\n\t}));\n\n\tif (isEmpty) {\n\t\treturn (\n\t\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t\t<RunsHeader />\n\t\t\t\t<RunsEmptyState />\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn (\n\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t<div className=\"flex items-center justify-between\">\n\t\t\t\t<RunsHeader />\n\t\t\t\t<SavedFiltersMenu\n\t\t\t\t\tcurrentFilter={currentFilter}\n\t\t\t\t\tsavedFilters={savedFilters}\n\t\t\t\t\tonSelect={onSelectFilter}\n\t\t\t\t\tonSave={onSaveFilter}\n\t\t\t\t\tonDelete={onDeleteFilter}\n\t\t\t\t\tonSetDefault={onSetDefault}\n\t\t\t\t\tonRemoveDefault={onRemoveDefault}\n\t\t\t\t\tpermissions={{\n\t\t\t\t\t\tcanSave: true,\n\t\t\t\t\t\tcanDelete: !isSystemFilter(currentFilter?.id ?? null),\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t\t<div className=\"flex flex-col gap-2\">\n\t\t\t\t<div className=\"flex flex-wrap gap-2 lg:grid lg:grid-flow-col lg:auto-cols-fr\">\n\t\t\t\t\t<div className=\"flex flex-col gap-1 w-full lg:w-auto\">\n\t\t\t\t\t\t<Label className=\"text-xs text-muted-foreground\">Date Range</Label>\n\t\t\t\t\t\t<DateRangeFilter\n\t\t\t\t\t\t\tvalue={dateRange}\n\t\t\t\t\t\t\tonValueChange={onDateRangeChange}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div className=\"flex flex-col gap-1 w-full lg:w-auto\">\n\t\t\t\t\t\t<Label className=\"text-xs text-muted-foreground\">States</Label>\n\t\t\t\t\t\t<StateFilter\n\t\t\t\t\t\t\tselectedFilters={selectedStates}\n\t\t\t\t\t\t\tonSelectFilter={onStateFilterChange}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t<div className=\"flex flex-wrap gap-2 lg:grid lg:grid-flow-col lg:auto-cols-fr\">\n\t\t\t\t\t<div className=\"flex flex-col gap-1 w-full lg:w-auto\">\n\t\t\t\t\t\t<Label className=\"text-xs text-muted-foreground\">Flows</Label>\n\t\t\t\t\t\t<FlowFilter\n\t\t\t\t\t\t\tselectedFlows={selectedFlows}\n\t\t\t\t\t\t\tonSelectFlows={onFlowFilterChange}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div className=\"flex flex-col gap-1 w-full lg:w-auto\">\n\t\t\t\t\t\t<Label className=\"text-xs text-muted-foreground\">Deployments</Label>\n\t\t\t\t\t\t<DeploymentFilter\n\t\t\t\t\t\t\tselectedDeployments={selectedDeployments}\n\t\t\t\t\t\t\tonSelectDeployments={onDeploymentFilterChange}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div className=\"flex flex-col gap-1 w-full lg:w-auto\">\n\t\t\t\t\t\t<Label className=\"text-xs text-muted-foreground\">Work Pools</Label>\n\t\t\t\t\t\t<WorkPoolFilter\n\t\t\t\t\t\t\tselectedWorkPools={selectedWorkPools}\n\t\t\t\t\t\t\tonSelectWorkPools={onWorkPoolFilterChange}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div className=\"flex flex-col gap-1 w-full lg:w-auto\">\n\t\t\t\t\t\t<Label className=\"text-xs text-muted-foreground\">Tags</Label>\n\t\t\t\t\t\t<TagsInput\n\t\t\t\t\t\t\tvalue={Array.from(selectedTags)}\n\t\t\t\t\t\t\tonChange={(e: string[] | ChangeEvent<HTMLInputElement>) => {\n\t\t\t\t\t\t\t\tconst tags = Array.isArray(e) ? e : [];\n\t\t\t\t\t\t\t\tonTagsFilterChange(new Set(tags));\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\tplaceholder=\"All tags\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<SaveFilterDialog\n\t\t\t\topen={isSaveDialogOpen}\n\t\t\t\tonOpenChange={onCloseSaveDialog}\n\t\t\t\tonSave={onConfirmSave}\n\t\t\t/>\n\t\t\t<Tabs value={tab} onValueChange={onTabChange}>\n\t\t\t\t<TabsList>\n\t\t\t\t\t<TabsTrigger value=\"flow-runs\">Flow Runs</TabsTrigger>\n\t\t\t\t\t<TabsTrigger value=\"task-runs\">Task Runs</TabsTrigger>\n\t\t\t\t</TabsList>\n\t\t\t\t<TabsContent value=\"flow-runs\">\n\t\t\t\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t\t\t\t<Card>\n\t\t\t\t\t\t\t<CardContent>\n\t\t\t\t\t\t\t\t<FlowRunsScatterPlot\n\t\t\t\t\t\t\t\t\thistory={flowRunHistory}\n\t\t\t\t\t\t\t\t\tstartDate={scatterPlotDateRange.startDate}\n\t\t\t\t\t\t\t\t\tendDate={scatterPlotDateRange.endDate}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</CardContent>\n\t\t\t\t\t\t</Card>\n\t\t\t\t\t\t<div className=\"flex items-center justify-between\">\n\t\t\t\t\t\t\t<FlowRunsRowCount\n\t\t\t\t\t\t\t\tcount={flowRunsCount}\n\t\t\t\t\t\t\t\tresults={flowRunsWithFlows}\n\t\t\t\t\t\t\t\tselectedRows={selectedRows}\n\t\t\t\t\t\t\t\tsetSelectedRows={setSelectedRows}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<div className=\"flex items-center gap-4\">\n\t\t\t\t\t\t\t\t<div className=\"flex items-center gap-2 whitespace-nowrap\">\n\t\t\t\t\t\t\t\t\t<Switch\n\t\t\t\t\t\t\t\t\t\tid=\"hide-subflows\"\n\t\t\t\t\t\t\t\t\t\tchecked={hideSubflows}\n\t\t\t\t\t\t\t\t\t\tonCheckedChange={onHideSubflowsChange}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t<Label htmlFor=\"hide-subflows\">Hide subflows</Label>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<SearchInput\n\t\t\t\t\t\t\t\t\tvalue={flowRunSearch}\n\t\t\t\t\t\t\t\t\tonChange={(e) => onFlowRunSearchChange(e.target.value)}\n\t\t\t\t\t\t\t\t\tplaceholder=\"Search by flow run name\"\n\t\t\t\t\t\t\t\t\taria-label=\"Search by flow run name\"\n\t\t\t\t\t\t\t\t\tclassName=\"w-64\"\n\t\t\t\t\t\t\t\t\tdebounceMs={1200}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t<SortFilter value={sort} onSelect={onSortChange} />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<FlowRunsPagination\n\t\t\t\t\t\t\tcount={flowRunsCount}\n\t\t\t\t\t\t\tpages={flowRunsPages}\n\t\t\t\t\t\t\tpagination={pagination}\n\t\t\t\t\t\t\tonChangePagination={onPaginationChange}\n\t\t\t\t\t\t\tonPrefetchPage={onPrefetchPage}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<FlowRunsList\n\t\t\t\t\t\t\tflowRuns={flowRunsWithFlows}\n\t\t\t\t\t\t\tselectedRows={selectedRows}\n\t\t\t\t\t\t\tonSelect={onSelectRow}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t</TabsContent>\n\t\t\t\t<TabsContent value=\"task-runs\">\n\t\t\t\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t\t\t\t<div className=\"flex items-center justify-between\">\n\t\t\t\t\t\t\t<TaskRunsRowCount\n\t\t\t\t\t\t\t\tcount={taskRunsCount}\n\t\t\t\t\t\t\t\tresults={taskRuns}\n\t\t\t\t\t\t\t\tselectedRows={taskRunsSelectedRows}\n\t\t\t\t\t\t\t\tsetSelectedRows={setTaskRunsSelectedRows}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<div className=\"flex items-center gap-4\">\n\t\t\t\t\t\t\t\t<SearchInput\n\t\t\t\t\t\t\t\t\tvalue={taskRunSearch}\n\t\t\t\t\t\t\t\t\tonChange={(e) => onTaskRunSearchChange(e.target.value)}\n\t\t\t\t\t\t\t\t\tplaceholder=\"Search by task run name\"\n\t\t\t\t\t\t\t\t\taria-label=\"Search by task run name\"\n\t\t\t\t\t\t\t\t\tclassName=\"w-64\"\n\t\t\t\t\t\t\t\t\tdebounceMs={1200}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t<TaskRunsSortFilter\n\t\t\t\t\t\t\t\t\tvalue={taskRunsSort}\n\t\t\t\t\t\t\t\t\tonSelect={onTaskRunsSortChange}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<TaskRunsPagination\n\t\t\t\t\t\t\tcount={taskRunsCount}\n\t\t\t\t\t\t\tpages={taskRunsPages}\n\t\t\t\t\t\t\tpagination={taskRunsPagination}\n\t\t\t\t\t\t\tonChangePagination={onTaskRunsPaginationChange}\n\t\t\t\t\t\t\tonPrefetchPage={onTaskRunsPrefetchPage}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<TaskRunsList\n\t\t\t\t\t\t\ttaskRuns={taskRuns}\n\t\t\t\t\t\t\tselectedRows={taskRunsSelectedRows}\n\t\t\t\t\t\t\tonSelect={onSelectTaskRunRow}\n\t\t\t\t\t\t\tonClearFilters={onClearTaskRunFilters}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t</TabsContent>\n\t\t\t</Tabs>\n\t\t</div>\n\t);\n};\n\nconst RunsHeader = () => (\n\t<div className=\"flex items-center gap-2\">\n\t\t<Breadcrumb>\n\t\t\t<BreadcrumbList>\n\t\t\t\t<BreadcrumbItem className=\"text-xl font-semibold\">Runs</BreadcrumbItem>\n\t\t\t</BreadcrumbList>\n\t\t</Breadcrumb>\n\t</div>\n);\n\nconst RunsEmptyState = () => (\n\t<EmptyState>\n\t\t<EmptyStateIcon id=\"Workflow\" />\n\t\t<EmptyStateTitle>Run a task or flow to get started</EmptyStateTitle>\n\t\t<EmptyStateDescription>\n\t\t\tRuns store the state history for each execution of a task or flow.\n\t\t</EmptyStateDescription>\n\t\t<EmptyStateActions>\n\t\t\t<DocsLink id=\"getting-started\" />\n\t\t</EmptyStateActions>\n\t</EmptyState>\n);\n","import { getRouteApi } from \"@tanstack/react-router\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { DateRangePreset } from \"@/components/flow-runs/flow-runs-list\";\nimport type { SavedFilter as SavedFiltersMenuFilter } from \"@/components/flow-runs/flow-runs-list/flow-runs-filters/saved-filters-menu\";\nimport {\n\ttype SavedFilter,\n\ttype SavedFilterValues,\n\tSYSTEM_DEFAULT_FILTER,\n\tuseSavedFilters,\n} from \"./use-saved-filters\";\n\nconst routeApi = getRouteApi(\"/runs/\");\n\n/**\n * Converts URL search params to SavedFilterValues format.\n * URL params use comma-separated strings, SavedFilterValues uses arrays.\n */\nfunction urlParamsToFilterValues(search: {\n\tstate?: string;\n\tflows?: string;\n\tdeployments?: string;\n\t\"work-pools\"?: string;\n\ttags?: string;\n\trange?: string;\n\tstart?: string;\n\tend?: string;\n}): SavedFilterValues {\n\tconst parseCommaSeparated = (value: string | undefined): string[] => {\n\t\tif (!value) return [];\n\t\treturn value.split(\",\").filter((s) => s.trim().length > 0);\n\t};\n\n\tconst stateArray = parseCommaSeparated(search.state);\n\tconst flowsArray = parseCommaSeparated(search.flows);\n\tconst deploymentsArray = parseCommaSeparated(search.deployments);\n\tconst workPoolsArray = parseCommaSeparated(search[\"work-pools\"]);\n\tconst tagsArray = parseCommaSeparated(search.tags);\n\n\treturn {\n\t\t...(stateArray.length > 0 && {\n\t\t\tstate: stateArray as SavedFilterValues[\"state\"],\n\t\t}),\n\t\t...(flowsArray.length > 0 && { flows: flowsArray }),\n\t\t...(deploymentsArray.length > 0 && { deployments: deploymentsArray }),\n\t\t...(workPoolsArray.length > 0 && { workPools: workPoolsArray }),\n\t\t...(tagsArray.length > 0 && { tags: tagsArray }),\n\t\t...(search.range && { range: search.range as SavedFilterValues[\"range\"] }),\n\t\t...(search.start && { start: search.start }),\n\t\t...(search.end && { end: search.end }),\n\t};\n}\n\n/**\n * Converts SavedFilterValues to URL search params format.\n * SavedFilterValues uses arrays, URL params use comma-separated strings.\n */\nfunction filterValuesToUrlParams(filters: SavedFilterValues): {\n\tstate: string;\n\tflows: string;\n\tdeployments: string;\n\t\"work-pools\": string;\n\ttags: string;\n\trange: DateRangePreset | undefined;\n\tstart: string | undefined;\n\tend: string | undefined;\n} {\n\treturn {\n\t\tstate: filters.state?.join(\",\") ?? \"\",\n\t\tflows: filters.flows?.join(\",\") ?? \"\",\n\t\tdeployments: filters.deployments?.join(\",\") ?? \"\",\n\t\t\"work-pools\": filters.workPools?.join(\",\") ?? \"\",\n\t\ttags: filters.tags?.join(\",\") ?? \"\",\n\t\trange: filters.range,\n\t\tstart: filters.start,\n\t\tend: filters.end,\n\t};\n}\n\n/**\n * Converts a SavedFilter from the hook to the format expected by SavedFiltersMenu.\n */\nfunction toMenuFilter(\n\tfilter: SavedFilter,\n\tdefaultFilterId: string | null,\n): SavedFiltersMenuFilter {\n\treturn {\n\t\tid: filter.id,\n\t\tname: filter.name,\n\t\tisDefault: filter.id === defaultFilterId,\n\t};\n}\n\nexport type UseRunsSavedFiltersReturn = {\n\t/** The currently active filter (matches current URL state), or null if custom/unsaved */\n\tcurrentFilter: SavedFiltersMenuFilter | null;\n\t/** All saved filters formatted for the menu */\n\tsavedFiltersForMenu: SavedFiltersMenuFilter[];\n\t/** Handler for selecting a filter from the menu */\n\tonSelectFilter: (filter: SavedFiltersMenuFilter) => void;\n\t/** Handler for saving the current filter state */\n\tonSaveFilter: () => void;\n\t/** Handler for deleting a filter */\n\tonDeleteFilter: (id: string) => void;\n\t/** Handler for setting a filter as default */\n\tonSetDefault: (id: string) => void;\n\t/** Handler for removing a filter as default */\n\tonRemoveDefault: (id: string) => void;\n\t/** Whether the save dialog is open */\n\tisSaveDialogOpen: boolean;\n\t/** Handler to close the save dialog */\n\tcloseSaveDialog: () => void;\n\t/** Handler to confirm saving with a name */\n\tconfirmSave: (name: string) => void;\n};\n\n/**\n * Hook that integrates useSavedFilters with the runs page URL state.\n *\n * This hook:\n * 1. Reads current filter state from URL params\n * 2. Finds matching saved filter (if any)\n * 3. Provides handlers for the SavedFiltersMenu component\n * 4. Manages the save dialog state\n */\nexport function useRunsSavedFilters(): UseRunsSavedFiltersReturn {\n\tconst search = routeApi.useSearch();\n\tconst navigate = routeApi.useNavigate();\n\n\tconst {\n\t\tsavedFilters,\n\t\tdefaultFilterId,\n\t\tsaveFilter,\n\t\tdeleteFilter,\n\t\tsetDefaultFilter,\n\t\tfindMatchingFilter,\n\t} = useSavedFilters();\n\n\tconst [isSaveDialogOpen, setIsSaveDialogOpen] = useState(false);\n\n\t// Convert current URL state to filter values\n\tconst currentFilterValues = useMemo(\n\t\t() => urlParamsToFilterValues(search),\n\t\t[search],\n\t);\n\n\t// Find if current URL state matches any saved filter\n\tconst matchingSavedFilter = useMemo(\n\t\t() => findMatchingFilter(currentFilterValues),\n\t\t[findMatchingFilter, currentFilterValues],\n\t);\n\n\t// Convert saved filters to menu format\n\tconst savedFiltersForMenu = useMemo(\n\t\t() => savedFilters.map((f) => toMenuFilter(f, defaultFilterId)),\n\t\t[savedFilters, defaultFilterId],\n\t);\n\n\t// Current filter for the menu (null if custom/unsaved)\n\tconst currentFilter = useMemo((): SavedFiltersMenuFilter | null => {\n\t\tif (matchingSavedFilter) {\n\t\t\treturn toMenuFilter(matchingSavedFilter, defaultFilterId);\n\t\t}\n\t\t// Check if there are any active filters\n\t\tconst hasActiveFilters =\n\t\t\tcurrentFilterValues.state?.length ||\n\t\t\tcurrentFilterValues.flows?.length ||\n\t\t\tcurrentFilterValues.deployments?.length ||\n\t\t\tcurrentFilterValues.workPools?.length ||\n\t\t\tcurrentFilterValues.tags?.length ||\n\t\t\tcurrentFilterValues.range ||\n\t\t\tcurrentFilterValues.start ||\n\t\t\tcurrentFilterValues.end;\n\n\t\tif (hasActiveFilters) {\n\t\t\t// Return \"Unsaved\" filter indicator\n\t\t\treturn {\n\t\t\t\tid: null,\n\t\t\t\tname: \"Unsaved\",\n\t\t\t\tisDefault: false,\n\t\t\t};\n\t\t}\n\n\t\t// No filters active - return \"Custom\" (default state)\n\t\treturn {\n\t\t\tid: null,\n\t\t\tname: \"Custom\",\n\t\t\tisDefault: false,\n\t\t};\n\t}, [matchingSavedFilter, defaultFilterId, currentFilterValues]);\n\n\t// Handler for selecting a filter from the menu\n\tconst onSelectFilter = useCallback(\n\t\t(filter: SavedFiltersMenuFilter) => {\n\t\t\t// Find the full saved filter to get the filter values\n\t\t\tconst savedFilter = savedFilters.find((f) => f.id === filter.id);\n\t\t\tif (!savedFilter) return;\n\n\t\t\tconst urlParams = filterValuesToUrlParams(savedFilter.filters);\n\n\t\t\tvoid navigate({\n\t\t\t\tto: \".\",\n\t\t\t\tsearch: (prev) => ({\n\t\t\t\t\t...prev,\n\t\t\t\t\t...urlParams,\n\t\t\t\t\tpage: 1, // Reset pagination when applying filter\n\t\t\t\t}),\n\t\t\t\treplace: true,\n\t\t\t});\n\t\t},\n\t\t[navigate, savedFilters],\n\t);\n\n\t// Handler for initiating save (opens dialog)\n\tconst onSaveFilter = useCallback(() => {\n\t\tsetIsSaveDialogOpen(true);\n\t}, []);\n\n\t// Handler for confirming save with a name\n\tconst confirmSave = useCallback(\n\t\t(name: string) => {\n\t\t\tsaveFilter({\n\t\t\t\tname,\n\t\t\t\tfilters: currentFilterValues,\n\t\t\t});\n\t\t\tsetIsSaveDialogOpen(false);\n\t\t},\n\t\t[saveFilter, currentFilterValues],\n\t);\n\n\t// Handler for closing the save dialog\n\tconst closeSaveDialog = useCallback(() => {\n\t\tsetIsSaveDialogOpen(false);\n\t}, []);\n\n\t// Handler for deleting a filter\n\tconst onDeleteFilter = useCallback(\n\t\t(id: string) => {\n\t\t\tdeleteFilter(id);\n\t\t},\n\t\t[deleteFilter],\n\t);\n\n\t// Handler for setting a filter as default\n\tconst onSetDefault = useCallback(\n\t\t(id: string) => {\n\t\t\tsetDefaultFilter(id);\n\t\t},\n\t\t[setDefaultFilter],\n\t);\n\n\t// Handler for removing a filter as default\n\tconst onRemoveDefault = useCallback(() => {\n\t\tsetDefaultFilter(null);\n\t}, [setDefaultFilter]);\n\n\treturn {\n\t\tcurrentFilter,\n\t\tsavedFiltersForMenu,\n\t\tonSelectFilter,\n\t\tonSaveFilter,\n\t\tonDeleteFilter,\n\t\tonSetDefault,\n\t\tonRemoveDefault,\n\t\tisSaveDialogOpen,\n\t\tcloseSaveDialog,\n\t\tconfirmSave,\n\t};\n}\n\n/**\n * Hook to apply the default filter on initial page load.\n * Should be called in the route component.\n *\n * This hook will apply a default filter when:\n * 1. The page first loads\n * 2. No filters are currently active in the URL\n *\n * Filter priority:\n * 1. User-set default filter (if one is set in localStorage)\n * 2. System default filter (\"Past week\") - always applied as baseline\n *\n * This matches the Vue UI behavior where the \"Past week\" filter is applied\n * by default on page load.\n *\n * It uses a ref guard to ensure the default filter is only applied once per mount,\n * preventing issues with React StrictMode and edge cases where navigation might\n * not change the URL.\n */\nexport function useApplyDefaultFilterOnMount(): void {\n\tconst navigate = routeApi.useNavigate();\n\tconst search = routeApi.useSearch();\n\tconst { defaultFilterId, getFilterById } = useSavedFilters();\n\n\t// Ref to track if we've already applied the default filter this mount\n\tconst didApplyRef = useRef(false);\n\n\t// Compute whether there are any active filters in the URL\n\tconst hasActiveFilters = useMemo(() => {\n\t\treturn !!(\n\t\t\tsearch.state ||\n\t\t\tsearch.flows ||\n\t\t\tsearch.deployments ||\n\t\t\tsearch[\"work-pools\"] ||\n\t\t\tsearch.tags ||\n\t\t\tsearch.range ||\n\t\t\tsearch.start ||\n\t\t\tsearch.end\n\t\t);\n\t}, [search]);\n\n\tuseEffect(() => {\n\t\t// Only apply once per mount\n\t\tif (didApplyRef.current) return;\n\n\t\t// Don't apply if filters are already active in URL\n\t\tif (hasActiveFilters) return;\n\n\t\t// Determine which filter to apply:\n\t\t// 1. User-set default filter (if set and exists)\n\t\t// 2. System default filter (\"Past week\") as baseline\n\t\tlet filterToApply: SavedFilter | undefined;\n\n\t\tif (defaultFilterId) {\n\t\t\t// User has set a default filter - use it if it exists\n\t\t\tfilterToApply = getFilterById(defaultFilterId);\n\t\t}\n\n\t\t// If no user default or it doesn't exist, use system default\n\t\tif (!filterToApply) {\n\t\t\tfilterToApply = SYSTEM_DEFAULT_FILTER;\n\t\t}\n\n\t\t// Mark as applied before navigating\n\t\tdidApplyRef.current = true;\n\n\t\tconst urlParams = filterValuesToUrlParams(filterToApply.filters);\n\n\t\tvoid navigate({\n\t\t\tto: \".\",\n\t\t\tsearch: (prev) => ({\n\t\t\t\t...prev,\n\t\t\t\t...urlParams,\n\t\t\t\tpage: 1, // Reset pagination when applying default filter\n\t\t\t}),\n\t\t\treplace: true,\n\t\t});\n\t}, [defaultFilterId, hasActiveFilters, getFilterById, navigate]);\n}\n","import { getRouteApi } from \"@tanstack/react-router\";\nimport { useCallback, useMemo } from \"react\";\nimport {\n\ttype DateRangeUrlState,\n\tFLOW_RUN_STATES,\n\ttype FlowRunState,\n} from \"@/components/flow-runs/flow-runs-list\";\n\nconst routeApi = getRouteApi(\"/runs/\");\n\nconst parseStateFilter = (stateString: string): FlowRunState[] => {\n\tif (!stateString) return [];\n\treturn stateString\n\t\t.split(\",\")\n\t\t.filter((s): s is FlowRunState =>\n\t\t\tFLOW_RUN_STATES.includes(s as FlowRunState),\n\t\t);\n};\n\nconst parseCommaSeparatedFilter = (filterString: string): string[] => {\n\tif (!filterString) return [];\n\treturn filterString.split(\",\").filter((s) => s.trim().length > 0);\n};\n\nexport type RunsFilters = {\n\tstates: Set<FlowRunState>;\n\tflows: Set<string>;\n\tdeployments: Set<string>;\n\tworkPools: Set<string>;\n\ttags: Set<string>;\n\tdateRange: DateRangeUrlState;\n\n\tonStatesChange: (states: Set<FlowRunState>) => void;\n\tonFlowsChange: (flows: Set<string>) => void;\n\tonDeploymentsChange: (deployments: Set<string>) => void;\n\tonWorkPoolsChange: (workPools: Set<string>) => void;\n\tonTagsChange: (tags: Set<string>) => void;\n\tonDateRangeChange: (range: DateRangeUrlState) => void;\n\n\tclearAllFilters: () => void;\n\thasActiveFilters: boolean;\n};\n\nexport function useRunsFilters(): RunsFilters {\n\tconst search = routeApi.useSearch();\n\tconst navigate = routeApi.useNavigate();\n\n\tconst states = useMemo(\n\t\t() => new Set<FlowRunState>(parseStateFilter(search.state ?? \"\")),\n\t\t[search.state],\n\t);\n\n\tconst flows = useMemo(\n\t\t() => new Set<string>(parseCommaSeparatedFilter(search.flows ?? \"\")),\n\t\t[search.flows],\n\t);\n\n\tconst deployments = useMemo(\n\t\t() => new Set<string>(parseCommaSeparatedFilter(search.deployments ?? \"\")),\n\t\t[search.deployments],\n\t);\n\n\tconst workPools = useMemo(\n\t\t() =>\n\t\t\tnew Set<string>(parseCommaSeparatedFilter(search[\"work-pools\"] ?? \"\")),\n\t\t[search[\"work-pools\"]],\n\t);\n\n\tconst tags = useMemo(\n\t\t() => new Set<string>(parseCommaSeparatedFilter(search.tags ?? \"\")),\n\t\t[search.tags],\n\t);\n\n\tconst dateRange: DateRangeUrlState = useMemo(\n\t\t() => ({\n\t\t\trange: search.range,\n\t\t\tstart: search.start,\n\t\t\tend: search.end,\n\t\t}),\n\t\t[search.range, search.start, search.end],\n\t);\n\n\tconst onStatesChange = useCallback(\n\t\t(newStates: Set<FlowRunState>) => {\n\t\t\tconst statesArray = Array.from(newStates);\n\t\t\tvoid navigate({\n\t\t\t\tto: \".\",\n\t\t\t\tsearch: (prev) => ({\n\t\t\t\t\t...prev,\n\t\t\t\t\tstate: statesArray.length > 0 ? statesArray.join(\",\") : \"\",\n\t\t\t\t\tpage: 1,\n\t\t\t\t}),\n\t\t\t\treplace: true,\n\t\t\t});\n\t\t},\n\t\t[navigate],\n\t);\n\n\tconst onFlowsChange = useCallback(\n\t\t(newFlows: Set<string>) => {\n\t\t\tconst flowsArray = Array.from(newFlows);\n\t\t\tvoid navigate({\n\t\t\t\tto: \".\",\n\t\t\t\tsearch: (prev) => ({\n\t\t\t\t\t...prev,\n\t\t\t\t\tflows: flowsArray.length > 0 ? flowsArray.join(\",\") : \"\",\n\t\t\t\t\tpage: 1,\n\t\t\t\t}),\n\t\t\t\treplace: true,\n\t\t\t});\n\t\t},\n\t\t[navigate],\n\t);\n\n\tconst onDeploymentsChange = useCallback(\n\t\t(newDeployments: Set<string>) => {\n\t\t\tconst deploymentsArray = Array.from(newDeployments);\n\t\t\tvoid navigate({\n\t\t\t\tto: \".\",\n\t\t\t\tsearch: (prev) => ({\n\t\t\t\t\t...prev,\n\t\t\t\t\tdeployments:\n\t\t\t\t\t\tdeploymentsArray.length > 0 ? deploymentsArray.join(\",\") : \"\",\n\t\t\t\t\tpage: 1,\n\t\t\t\t}),\n\t\t\t\treplace: true,\n\t\t\t});\n\t\t},\n\t\t[navigate],\n\t);\n\n\tconst onWorkPoolsChange = useCallback(\n\t\t(newWorkPools: Set<string>) => {\n\t\t\tconst workPoolsArray = Array.from(newWorkPools);\n\t\t\tvoid navigate({\n\t\t\t\tto: \".\",\n\t\t\t\tsearch: (prev) => ({\n\t\t\t\t\t...prev,\n\t\t\t\t\t\"work-pools\":\n\t\t\t\t\t\tworkPoolsArray.length > 0 ? workPoolsArray.join(\",\") : \"\",\n\t\t\t\t\tpage: 1,\n\t\t\t\t}),\n\t\t\t\treplace: true,\n\t\t\t});\n\t\t},\n\t\t[navigate],\n\t);\n\n\tconst onTagsChange = useCallback(\n\t\t(newTags: Set<string>) => {\n\t\t\tconst tagsArray = Array.from(newTags);\n\t\t\tvoid navigate({\n\t\t\t\tto: \".\",\n\t\t\t\tsearch: (prev) => ({\n\t\t\t\t\t...prev,\n\t\t\t\t\ttags: tagsArray.length > 0 ? tagsArray.join(\",\") : \"\",\n\t\t\t\t\tpage: 1,\n\t\t\t\t}),\n\t\t\t\treplace: true,\n\t\t\t});\n\t\t},\n\t\t[navigate],\n\t);\n\n\tconst onDateRangeChange = useCallback(\n\t\t(newDateRange: DateRangeUrlState) => {\n\t\t\tvoid navigate({\n\t\t\t\tto: \".\",\n\t\t\t\tsearch: (prev) => ({\n\t\t\t\t\t...prev,\n\t\t\t\t\trange: newDateRange.range,\n\t\t\t\t\tstart: newDateRange.start,\n\t\t\t\t\tend: newDateRange.end,\n\t\t\t\t\tpage: 1,\n\t\t\t\t}),\n\t\t\t\treplace: true,\n\t\t\t});\n\t\t},\n\t\t[navigate],\n\t);\n\n\tconst hasActiveFilters = useMemo(() => {\n\t\treturn (\n\t\t\tstates.size > 0 ||\n\t\t\tflows.size > 0 ||\n\t\t\tdeployments.size > 0 ||\n\t\t\tworkPools.size > 0 ||\n\t\t\ttags.size > 0 ||\n\t\t\tdateRange.range !== undefined ||\n\t\t\tdateRange.start !== undefined ||\n\t\t\tdateRange.end !== undefined\n\t\t);\n\t}, [states, flows, deployments, workPools, tags, dateRange]);\n\n\tconst clearAllFilters = useCallback(() => {\n\t\tvoid navigate({\n\t\t\tto: \".\",\n\t\t\tsearch: (prev) => ({\n\t\t\t\t...prev,\n\t\t\t\tstate: \"\",\n\t\t\t\tflows: \"\",\n\t\t\t\tdeployments: \"\",\n\t\t\t\t\"work-pools\": \"\",\n\t\t\t\ttags: \"\",\n\t\t\t\trange: undefined,\n\t\t\t\tstart: undefined,\n\t\t\t\tend: undefined,\n\t\t\t\tpage: 1,\n\t\t\t}),\n\t\t\treplace: true,\n\t\t});\n\t}, [navigate]);\n\n\treturn {\n\t\tstates,\n\t\tflows,\n\t\tdeployments,\n\t\tworkPools,\n\t\ttags,\n\t\tdateRange,\n\t\tonStatesChange,\n\t\tonFlowsChange,\n\t\tonDeploymentsChange,\n\t\tonWorkPoolsChange,\n\t\tonTagsChange,\n\t\tonDateRangeChange,\n\t\tclearAllFilters,\n\t\thasActiveFilters,\n\t};\n}\n","import {\n\tuseQuery,\n\tuseQueryClient,\n\tuseSuspenseQueries,\n} from \"@tanstack/react-query\";\nimport { createFileRoute } from \"@tanstack/react-router\";\nimport { zodValidator } from \"@tanstack/zod-adapter\";\nimport { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { z } from \"zod\";\nimport {\n\tbuildCountFlowRunsQuery,\n\tbuildFlowRunHistoryQuery,\n\tbuildPaginateFlowRunsQuery,\n\ttype FlowRunHistoryFilter,\n\ttype FlowRunsPaginateFilter,\n} from \"@/api/flow-runs\";\nimport {\n\tbuildCountTaskRunsQuery,\n\tbuildGetFlowRunsTaskRunsCountQuery,\n\tbuildPaginateTaskRunsQuery,\n\ttype TaskRunsPaginateFilter,\n} from \"@/api/task-runs\";\nimport {\n\tDATE_RANGE_PRESETS,\n\ttype DateRangeUrlState,\n\tFLOW_RUN_STATES,\n\ttype FlowRunState,\n\ttype PaginationState,\n\tSORT_FILTERS,\n\ttype SortFilters,\n\turlStateToDateRangeValue,\n} from \"@/components/flow-runs/flow-runs-list\";\nimport { RunsPage } from \"@/components/runs/runs-page\";\nimport {\n\tuseApplyDefaultFilterOnMount,\n\tuseRunsSavedFilters,\n} from \"@/components/runs/use-runs-saved-filters\";\nimport {\n\tTASK_RUN_SORT_FILTERS,\n\ttype TaskRunSortFilters,\n} from \"@/components/task-runs/task-runs-list\";\nimport { mapValueToRange } from \"@/components/ui/date-range-select\";\nimport { useLocalStorage } from \"@/hooks/use-local-storage\";\nimport { useRunsFilters } from \"@/hooks/use-runs-filters\";\n\nconst searchParams = z.object({\n\ttab: z.enum([\"flow-runs\", \"task-runs\"]).optional().default(\"flow-runs\"),\n\t// Flow runs pagination params\n\tpage: z.number().int().positive().optional().default(1).catch(1),\n\tlimit: z.number().int().positive().optional().catch(undefined),\n\tsort: z.enum(SORT_FILTERS).optional().default(\"START_TIME_DESC\"),\n\t\"hide-subflows\": z.boolean().optional().default(false),\n\t\"flow-run-search\": z.string().optional().default(\"\"),\n\tstate: z.string().optional().default(\"\"),\n\tflows: z.string().optional().default(\"\"),\n\tdeployments: z.string().optional().default(\"\"),\n\t\"work-pools\": z.string().optional().default(\"\"),\n\ttags: z.string().optional().default(\"\"),\n\trange: z.enum(DATE_RANGE_PRESETS).optional(),\n\tstart: z.string().optional(),\n\tend: z.string().optional(),\n\t// Task runs pagination params\n\t\"task-runs-page\": z.number().int().positive().optional().default(1).catch(1),\n\t\"task-runs-limit\": z.number().int().positive().optional().catch(undefined),\n\t\"task-runs-sort\": z\n\t\t.enum(TASK_RUN_SORT_FILTERS)\n\t\t.optional()\n\t\t.default(\"EXPECTED_START_TIME_DESC\"),\n\t\"task-run-search\": z.string().optional().default(\"\"),\n});\n\ntype SearchParams = z.infer<typeof searchParams>;\n\n// Helper to parse state string to array of FlowRunState\nconst parseStateFilter = (stateString: string): FlowRunState[] => {\n\tif (!stateString) return [];\n\treturn stateString\n\t\t.split(\",\")\n\t\t.filter((s): s is FlowRunState =>\n\t\t\tFLOW_RUN_STATES.includes(s as FlowRunState),\n\t\t);\n};\n\n// Helper to get date range from search params\nconst getDateRangeFilter = (\n\tsearch?: SearchParams,\n): { after_?: string; before_?: string } | undefined => {\n\tif (!search) return undefined;\n\n\tconst dateRangeUrlState: DateRangeUrlState = {\n\t\trange: search.range,\n\t\tstart: search.start,\n\t\tend: search.end,\n\t};\n\n\tconst dateRangeValue = urlStateToDateRangeValue(dateRangeUrlState);\n\tif (!dateRangeValue) return undefined;\n\n\tconst range = mapValueToRange(dateRangeValue);\n\tif (!range) return undefined;\n\n\treturn {\n\t\tafter_: range.startDate.toISOString(),\n\t\tbefore_: range.endDate.toISOString(),\n\t};\n};\n\n// Helper to parse flows string to array of flow IDs\nconst parseFlowsFilter = (flowsString: string): string[] => {\n\tif (!flowsString) return [];\n\treturn flowsString.split(\",\").filter((s) => s.trim().length > 0);\n};\n\n// Helper to parse deployments string to array of deployment IDs\nconst parseDeploymentsFilter = (deploymentsString: string): string[] => {\n\tif (!deploymentsString) return [];\n\treturn deploymentsString.split(\",\").filter((s) => s.trim().length > 0);\n};\n\n// Helper to parse work pools string to array of work pool names\nconst parseWorkPoolsFilter = (workPoolsString: string): string[] => {\n\tif (!workPoolsString) return [];\n\treturn workPoolsString.split(\",\").filter((s) => s.trim().length > 0);\n};\n\n// Helper to parse tags string to array of tag strings\nconst parseTagsFilter = (tagsString: string): string[] => {\n\tif (!tagsString) return [];\n\treturn tagsString.split(\",\").filter((s) => s.trim().length > 0);\n};\n\nconst buildPaginationBody = (search?: SearchParams): FlowRunsPaginateFilter => {\n\tconst hideSubflows = search?.[\"hide-subflows\"];\n\tconst flowRunSearch = search?.[\"flow-run-search\"];\n\tconst stateFilters = parseStateFilter(search?.state ?? \"\");\n\tconst flowsFilter = parseFlowsFilter(search?.flows ?? \"\");\n\tconst deploymentsFilter = parseDeploymentsFilter(search?.deployments ?? \"\");\n\tconst workPoolsFilter = parseWorkPoolsFilter(search?.[\"work-pools\"] ?? \"\");\n\tconst tagsFilter = parseTagsFilter(search?.tags ?? \"\");\n\tconst dateRangeFilter = getDateRangeFilter(search);\n\n\t// Map state names to state types for the API filter\n\tconst stateNames = stateFilters.length > 0 ? stateFilters : undefined;\n\tconst flowIds = flowsFilter.length > 0 ? flowsFilter : undefined;\n\tconst deploymentIds =\n\t\tdeploymentsFilter.length > 0 ? deploymentsFilter : undefined;\n\tconst workPoolNames =\n\t\tworkPoolsFilter.length > 0 ? workPoolsFilter : undefined;\n\n\t// Build flow_runs filter only if we have filters to apply\n\tconst hasFilters =\n\t\thideSubflows ||\n\t\tflowRunSearch ||\n\t\tstateNames ||\n\t\tflowIds ||\n\t\tdeploymentIds ||\n\t\ttagsFilter.length > 0 ||\n\t\tdateRangeFilter;\n\tconst flowRunsFilter = hasFilters\n\t\t? {\n\t\t\t\toperator: \"and_\" as const,\n\t\t\t\t...(hideSubflows && {\n\t\t\t\t\tparent_task_run_id: { operator: \"and_\" as const, is_null_: true },\n\t\t\t\t}),\n\t\t\t\t...(flowRunSearch && {\n\t\t\t\t\tname: { like_: flowRunSearch },\n\t\t\t\t}),\n\t\t\t\t...(stateNames && {\n\t\t\t\t\tstate: {\n\t\t\t\t\t\toperator: \"and_\" as const,\n\t\t\t\t\t\tname: { any_: stateNames },\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t\t...(tagsFilter.length > 0 && {\n\t\t\t\t\ttags: { operator: \"and_\" as const, any_: tagsFilter },\n\t\t\t\t}),\n\t\t\t\t...(dateRangeFilter && {\n\t\t\t\t\texpected_start_time: dateRangeFilter,\n\t\t\t\t}),\n\t\t\t}\n\t\t: undefined;\n\n\t// Build flows filter for filtering by flow_id\n\tconst flowsFilterBody = flowIds\n\t\t? { operator: \"and_\" as const, id: { any_: flowIds } }\n\t\t: undefined;\n\n\t// Build deployments filter for filtering by deployment_id\n\tconst deploymentsFilterBody = deploymentIds\n\t\t? { operator: \"and_\" as const, id: { any_: deploymentIds } }\n\t\t: undefined;\n\n\t// Build work_pools filter for filtering by work pool name\n\tconst workPoolsFilterBody = workPoolNames\n\t\t? { operator: \"and_\" as const, name: { any_: workPoolNames } }\n\t\t: undefined;\n\n\treturn {\n\t\tpage: search?.page ?? 1,\n\t\tlimit: search?.limit ?? 100,\n\t\tsort: search?.sort ?? \"START_TIME_DESC\",\n\t\tflow_runs: flowRunsFilter,\n\t\tflows: flowsFilterBody,\n\t\tdeployments: deploymentsFilterBody,\n\t\twork_pools: workPoolsFilterBody,\n\t};\n};\n\nconst buildTaskRunsPaginationBody = (\n\tsearch?: SearchParams,\n): TaskRunsPaginateFilter => {\n\tconst taskRunSearch = search?.[\"task-run-search\"];\n\tconst stateFilters = parseStateFilter(search?.state ?? \"\");\n\tconst flowsFilter = parseFlowsFilter(search?.flows ?? \"\");\n\tconst deploymentsFilter = parseDeploymentsFilter(search?.deployments ?? \"\");\n\tconst tagsFilter = parseTagsFilter(search?.tags ?? \"\");\n\tconst dateRangeFilter = getDateRangeFilter(search);\n\n\t// Build task_runs filter only if we have task-specific filters to apply\n\tconst taskRunsFilter = taskRunSearch\n\t\t? {\n\t\t\t\toperator: \"and_\" as const,\n\t\t\t\tname: { like_: taskRunSearch },\n\t\t\t}\n\t\t: undefined;\n\n\t// Build flow_runs filter from shared filters (state, tags, date range)\n\t// These filters apply to the flow runs that the task runs belong to\n\tconst stateNames = stateFilters.length > 0 ? stateFilters : undefined;\n\tconst hasFlowRunsFilters =\n\t\tstateNames || tagsFilter.length > 0 || dateRangeFilter;\n\tconst flowRunsFilter = hasFlowRunsFilters\n\t\t? {\n\t\t\t\toperator: \"and_\" as const,\n\t\t\t\t...(stateNames && {\n\t\t\t\t\tstate: {\n\t\t\t\t\t\toperator: \"and_\" as const,\n\t\t\t\t\t\tname: { any_: stateNames },\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t\t...(tagsFilter.length > 0 && {\n\t\t\t\t\ttags: { operator: \"and_\" as const, any_: tagsFilter },\n\t\t\t\t}),\n\t\t\t\t...(dateRangeFilter && {\n\t\t\t\t\texpected_start_time: dateRangeFilter,\n\t\t\t\t}),\n\t\t\t}\n\t\t: undefined;\n\n\t// Build flows filter for filtering by flow_id\n\tconst flowIds = flowsFilter.length > 0 ? flowsFilter : undefined;\n\tconst flowsFilterBody = flowIds\n\t\t? { operator: \"and_\" as const, id: { any_: flowIds } }\n\t\t: undefined;\n\n\t// Build deployments filter for filtering by deployment_id\n\tconst deploymentIds =\n\t\tdeploymentsFilter.length > 0 ? deploymentsFilter : undefined;\n\tconst deploymentsFilterBody = deploymentIds\n\t\t? { operator: \"and_\" as const, id: { any_: deploymentIds } }\n\t\t: undefined;\n\n\t// Note: work_pools filter is NOT supported by the task_runs/paginate endpoint\n\n\treturn {\n\t\tpage: search?.[\"task-runs-page\"] ?? 1,\n\t\tlimit: search?.[\"task-runs-limit\"] ?? 100,\n\t\tsort: search?.[\"task-runs-sort\"] ?? \"EXPECTED_START_TIME_DESC\",\n\t\ttask_runs: taskRunsFilter,\n\t\tflow_runs: flowRunsFilter,\n\t\tflows: flowsFilterBody,\n\t\tdeployments: deploymentsFilterBody,\n\t};\n};\n\nconst buildHistoryFilter = (search?: SearchParams): FlowRunHistoryFilter => {\n\tconst hideSubflows = search?.[\"hide-subflows\"];\n\tconst stateFilters = parseStateFilter(search?.state ?? \"\");\n\tconst flowsFilter = parseFlowsFilter(search?.flows ?? \"\");\n\tconst deploymentsFilter = parseDeploymentsFilter(search?.deployments ?? \"\");\n\tconst workPoolsFilter = parseWorkPoolsFilter(search?.[\"work-pools\"] ?? \"\");\n\tconst tagsFilter = parseTagsFilter(search?.tags ?? \"\");\n\tconst dateRangeFilter = getDateRangeFilter(search);\n\n\t// Map state names to state types for the API filter\n\tconst stateNames = stateFilters.length > 0 ? stateFilters : undefined;\n\tconst flowIds = flowsFilter.length > 0 ? flowsFilter : undefined;\n\tconst deploymentIds =\n\t\tdeploymentsFilter.length > 0 ? deploymentsFilter : undefined;\n\tconst workPoolNames =\n\t\tworkPoolsFilter.length > 0 ? workPoolsFilter : undefined;\n\n\t// Build flow_runs filter only if we have filters to apply\n\tconst hasFilters =\n\t\thideSubflows || stateNames || tagsFilter.length > 0 || dateRangeFilter;\n\tconst flowRunsFilter = hasFilters\n\t\t? {\n\t\t\t\toperator: \"and_\" as const,\n\t\t\t\t...(hideSubflows && {\n\t\t\t\t\tparent_task_run_id: { operator: \"and_\" as const, is_null_: true },\n\t\t\t\t}),\n\t\t\t\t...(stateNames && {\n\t\t\t\t\tstate: {\n\t\t\t\t\t\toperator: \"and_\" as const,\n\t\t\t\t\t\tname: { any_: stateNames },\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t\t...(tagsFilter.length > 0 && {\n\t\t\t\t\ttags: { operator: \"and_\" as const, any_: tagsFilter },\n\t\t\t\t}),\n\t\t\t\t...(dateRangeFilter && {\n\t\t\t\t\texpected_start_time: dateRangeFilter,\n\t\t\t\t}),\n\t\t\t}\n\t\t: undefined;\n\n\t// Build flows filter for filtering by flow_id\n\tconst flowsFilterBody = flowIds\n\t\t? { operator: \"and_\" as const, id: { any_: flowIds } }\n\t\t: undefined;\n\n\t// Build deployments filter for filtering by deployment_id\n\tconst deploymentsFilterBody = deploymentIds\n\t\t? { operator: \"and_\" as const, id: { any_: deploymentIds } }\n\t\t: undefined;\n\n\t// Build work_pools filter for filtering by work pool name\n\tconst workPoolsFilterBody = workPoolNames\n\t\t? { operator: \"and_\" as const, name: { any_: workPoolNames } }\n\t\t: undefined;\n\n\treturn {\n\t\tsort: \"EXPECTED_START_TIME_DESC\",\n\t\tlimit: 1000,\n\t\toffset: 0,\n\t\tflow_runs: flowRunsFilter,\n\t\tflows: flowsFilterBody,\n\t\tdeployments: deploymentsFilterBody,\n\t\twork_pools: workPoolsFilterBody,\n\t};\n};\n\nexport const Route = createFileRoute(\"/runs/\")({\n\tvalidateSearch: zodValidator(searchParams),\n\tcomponent: RouteComponent,\n\tloaderDeps: ({ search }) => ({\n\t\tflowRunsDeps: buildPaginationBody(search),\n\t\ttaskRunsDeps: buildTaskRunsPaginationBody(search),\n\t\thistoryDeps: buildHistoryFilter(search),\n\t}),\n\tloader: ({ deps, context }) => {\n\t\t// Prefetch all queries without blocking the loader\n\t\t// This allows the component to render immediately and use placeholderData\n\t\tvoid context.queryClient.prefetchQuery(buildCountFlowRunsQuery());\n\t\tvoid context.queryClient.prefetchQuery(buildCountTaskRunsQuery());\n\t\tvoid context.queryClient.prefetchQuery(\n\t\t\tbuildPaginateFlowRunsQuery(deps.flowRunsDeps, 30_000),\n\t\t);\n\t\tvoid context.queryClient.prefetchQuery(\n\t\t\tbuildPaginateTaskRunsQuery(deps.taskRunsDeps, 30_000),\n\t\t);\n\t\tvoid context.queryClient.prefetchQuery(\n\t\t\tbuildFlowRunHistoryQuery(deps.historyDeps, 30_000),\n\t\t);\n\n\t\t// Background async chain: prefetch task run counts for each flow run\n\t\t// This prevents suspense when FlowRunCard renders\n\t\tvoid (async () => {\n\t\t\tconst pageData = await context.queryClient.ensureQueryData(\n\t\t\t\tbuildPaginateFlowRunsQuery(deps.flowRunsDeps, 30_000),\n\t\t\t);\n\t\t\tconst flowRunIds = pageData?.results?.map((run) => run.id) ?? [];\n\t\t\tif (flowRunIds.length > 0) {\n\t\t\t\tvoid context.queryClient.prefetchQuery(\n\t\t\t\t\tbuildGetFlowRunsTaskRunsCountQuery(flowRunIds),\n\t\t\t\t);\n\t\t\t}\n\t\t})();\n\t},\n\twrapInSuspense: true,\n});\n\nconst usePagination = () => {\n\tconst search = Route.useSearch();\n\tconst navigate = Route.useNavigate();\n\n\tconst pagination: PaginationState = useMemo(\n\t\t() => ({\n\t\t\tpage: search.page ?? 1,\n\t\t\tlimit: search.limit ?? 100,\n\t\t}),\n\t\t[search.page, search.limit],\n\t);\n\n\tconst onPaginationChange = useCallback(\n\t\t(newPagination: PaginationState) => {\n\t\t\tvoid navigate({\n\t\t\t\tto: \".\",\n\t\t\t\tsearch: (prev) => ({\n\t\t\t\t\t...prev,\n\t\t\t\t\tpage: newPagination.page,\n\t\t\t\t\tlimit: newPagination.limit,\n\t\t\t\t}),\n\t\t\t\treplace: true,\n\t\t\t});\n\t\t},\n\t\t[navigate],\n\t);\n\n\treturn [pagination, onPaginationChange] as const;\n};\n\nconst useSort = () => {\n\tconst search = Route.useSearch();\n\tconst navigate = Route.useNavigate();\n\n\tconst onSortChange = useCallback(\n\t\t(sort: SortFilters) => {\n\t\t\tvoid navigate({\n\t\t\t\tto: \".\",\n\t\t\t\tsearch: (prev) => ({ ...prev, sort, page: 1 }),\n\t\t\t\treplace: true,\n\t\t\t});\n\t\t},\n\t\t[navigate],\n\t);\n\n\treturn [search.sort, onSortChange] as const;\n};\n\nconst useHideSubflows = () => {\n\tconst search = Route.useSearch();\n\tconst navigate = Route.useNavigate();\n\n\tconst onHideSubflowsChange = useCallback(\n\t\t(hideSubflows: boolean) => {\n\t\t\tvoid navigate({\n\t\t\t\tto: \".\",\n\t\t\t\tsearch: (prev) => ({ ...prev, \"hide-subflows\": hideSubflows, page: 1 }),\n\t\t\t\treplace: true,\n\t\t\t});\n\t\t},\n\t\t[navigate],\n\t);\n\n\treturn [search[\"hide-subflows\"], onHideSubflowsChange] as const;\n};\n\nconst useTab = () => {\n\tconst search = Route.useSearch();\n\tconst navigate = Route.useNavigate();\n\n\tconst onTabChange = useCallback(\n\t\t(tab: string) => {\n\t\t\tvoid navigate({\n\t\t\t\tto: \".\",\n\t\t\t\tsearch: (prev) => ({\n\t\t\t\t\t...prev,\n\t\t\t\t\ttab: tab as \"flow-runs\" | \"task-runs\",\n\t\t\t\t\tpage: 1,\n\t\t\t\t}),\n\t\t\t\treplace: true,\n\t\t\t});\n\t\t},\n\t\t[navigate],\n\t);\n\n\treturn [search.tab, onTabChange] as const;\n};\n\nconst useFlowRunSearch = () => {\n\tconst search = Route.useSearch();\n\tconst navigate = Route.useNavigate();\n\n\tconst onFlowRunSearchChange = useCallback(\n\t\t(flowRunSearch: string) => {\n\t\t\tvoid navigate({\n\t\t\t\tto: \".\",\n\t\t\t\tsearch: (prev) => ({\n\t\t\t\t\t...prev,\n\t\t\t\t\t\"flow-run-search\": flowRunSearch,\n\t\t\t\t\tpage: 1, // Reset pagination when search changes\n\t\t\t\t}),\n\t\t\t\treplace: true,\n\t\t\t});\n\t\t},\n\t\t[navigate],\n\t);\n\n\treturn [search[\"flow-run-search\"], onFlowRunSearchChange] as const;\n};\n\n// Task runs hooks\nconst useTaskRunsPagination = () => {\n\tconst search = Route.useSearch();\n\tconst navigate = Route.useNavigate();\n\n\tconst pagination: PaginationState = useMemo(\n\t\t() => ({\n\t\t\tpage: search[\"task-runs-page\"] ?? 1,\n\t\t\tlimit: search[\"task-runs-limit\"] ?? 100,\n\t\t}),\n\t\t[search[\"task-runs-page\"], search[\"task-runs-limit\"]],\n\t);\n\n\tconst onPaginationChange = useCallback(\n\t\t(newPagination: PaginationState) => {\n\t\t\tvoid navigate({\n\t\t\t\tto: \".\",\n\t\t\t\tsearch: (prev) => ({\n\t\t\t\t\t...prev,\n\t\t\t\t\t\"task-runs-page\": newPagination.page,\n\t\t\t\t\t\"task-runs-limit\": newPagination.limit,\n\t\t\t\t}),\n\t\t\t\treplace: true,\n\t\t\t});\n\t\t},\n\t\t[navigate],\n\t);\n\n\treturn [pagination, onPaginationChange] as const;\n};\n\nconst useTaskRunsSort = () => {\n\tconst search = Route.useSearch();\n\tconst navigate = Route.useNavigate();\n\n\tconst onSortChange = useCallback(\n\t\t(sort: TaskRunSortFilters) => {\n\t\t\tvoid navigate({\n\t\t\t\tto: \".\",\n\t\t\t\tsearch: (prev) => ({\n\t\t\t\t\t...prev,\n\t\t\t\t\t\"task-runs-sort\": sort,\n\t\t\t\t\t\"task-runs-page\": 1,\n\t\t\t\t}),\n\t\t\t\treplace: true,\n\t\t\t});\n\t\t},\n\t\t[navigate],\n\t);\n\n\treturn [search[\"task-runs-sort\"], onSortChange] as const;\n};\n\nconst useTaskRunSearch = () => {\n\tconst search = Route.useSearch();\n\tconst navigate = Route.useNavigate();\n\n\tconst onTaskRunSearchChange = useCallback(\n\t\t(taskRunSearch: string) => {\n\t\t\tvoid navigate({\n\t\t\t\tto: \".\",\n\t\t\t\tsearch: (prev) => ({\n\t\t\t\t\t...prev,\n\t\t\t\t\t\"task-run-search\": taskRunSearch,\n\t\t\t\t\t\"task-runs-page\": 1, // Reset pagination when search changes\n\t\t\t\t}),\n\t\t\t\treplace: true,\n\t\t\t});\n\t\t},\n\t\t[navigate],\n\t);\n\n\treturn [search[\"task-run-search\"], onTaskRunSearchChange] as const;\n};\n\nfunction RouteComponent() {\n\tconst queryClient = useQueryClient();\n\tconst search = Route.useSearch();\n\tconst navigate = Route.useNavigate();\n\n\t// localStorage persistence for pagination limits (separate keys for flow runs and task runs)\n\tconst [storedFlowRunsLimit, setStoredFlowRunsLimit] = useLocalStorage(\n\t\t\"workspace-flow-runs-list-limit\",\n\t\t100,\n\t);\n\tconst [storedTaskRunsLimit, setStoredTaskRunsLimit] = useLocalStorage(\n\t\t\"workspace-task-runs-list-limit\",\n\t\t100,\n\t);\n\n\t// Track if we've done the initial URL sync to avoid re-running on every render\n\tconst hasInitializedRef = useRef(false);\n\n\t// On mount - if URL limit is undefined (not explicitly set), use localStorage value\n\tuseEffect(() => {\n\t\tif (hasInitializedRef.current) return;\n\t\thasInitializedRef.current = true;\n\n\t\tconst needsFlowRunsLimit = search.limit === undefined;\n\t\tconst needsTaskRunsLimit = search[\"task-runs-limit\"] === undefined;\n\n\t\tif (needsFlowRunsLimit || needsTaskRunsLimit) {\n\t\t\tvoid navigate({\n\t\t\t\tto: \".\",\n\t\t\t\tsearch: (prev) => ({\n\t\t\t\t\t...prev,\n\t\t\t\t\t...(needsFlowRunsLimit && { limit: storedFlowRunsLimit }),\n\t\t\t\t\t...(needsTaskRunsLimit && {\n\t\t\t\t\t\t\"task-runs-limit\": storedTaskRunsLimit,\n\t\t\t\t\t}),\n\t\t\t\t}),\n\t\t\t\treplace: true,\n\t\t\t});\n\t\t}\n\t}, [\n\t\tnavigate,\n\t\tsearch.limit,\n\t\tsearch[\"task-runs-limit\"],\n\t\tstoredFlowRunsLimit,\n\t\tstoredTaskRunsLimit,\n\t]);\n\n\t// When flow runs URL limit changes (user interaction), save to localStorage\n\tuseEffect(() => {\n\t\tif (search.limit !== undefined && search.limit !== storedFlowRunsLimit) {\n\t\t\tsetStoredFlowRunsLimit(search.limit);\n\t\t}\n\t}, [search.limit, storedFlowRunsLimit, setStoredFlowRunsLimit]);\n\n\t// When task runs URL limit changes (user interaction), save to localStorage\n\tuseEffect(() => {\n\t\tif (\n\t\t\tsearch[\"task-runs-limit\"] !== undefined &&\n\t\t\tsearch[\"task-runs-limit\"] !== storedTaskRunsLimit\n\t\t) {\n\t\t\tsetStoredTaskRunsLimit(search[\"task-runs-limit\"]);\n\t\t}\n\t}, [search[\"task-runs-limit\"], storedTaskRunsLimit, setStoredTaskRunsLimit]);\n\n\t// Flow runs hooks\n\tconst [pagination, onPaginationChange] = usePagination();\n\tconst [sort, onSortChange] = useSort();\n\tconst [hideSubflows, onHideSubflowsChange] = useHideSubflows();\n\tconst [tab, onTabChange] = useTab();\n\tconst [flowRunSearch, onFlowRunSearchChange] = useFlowRunSearch();\n\t// Consolidated filter state\n\tconst {\n\t\tstates: selectedStates,\n\t\tflows: selectedFlows,\n\t\tdeployments: selectedDeployments,\n\t\tworkPools: selectedWorkPools,\n\t\ttags: selectedTags,\n\t\tdateRange,\n\t\tonStatesChange: onStateFilterChange,\n\t\tonFlowsChange: onFlowFilterChange,\n\t\tonDeploymentsChange: onDeploymentFilterChange,\n\t\tonWorkPoolsChange: onWorkPoolFilterChange,\n\t\tonTagsChange: onTagsFilterChange,\n\t\tonDateRangeChange,\n\t} = useRunsFilters();\n\t// Task runs hooks\n\tconst [taskRunsPagination, onTaskRunsPaginationChange] =\n\t\tuseTaskRunsPagination();\n\tconst [taskRunsSort, onTaskRunsSortChange] = useTaskRunsSort();\n\tconst [taskRunSearch, onTaskRunSearchChange] = useTaskRunSearch();\n\n\t// Saved filters hook\n\tconst {\n\t\tcurrentFilter,\n\t\tsavedFiltersForMenu,\n\t\tonSelectFilter,\n\t\tonSaveFilter,\n\t\tonDeleteFilter,\n\t\tonSetDefault,\n\t\tonRemoveDefault,\n\t\tisSaveDialogOpen,\n\t\tcloseSaveDialog,\n\t\tconfirmSave,\n\t} = useRunsSavedFilters();\n\n\t// Apply default filter on initial page load (if one is set and no filters are active)\n\tuseApplyDefaultFilterOnMount();\n\n\t// Use useSuspenseQueries for unfiltered count queries (stable keys, won't cause suspense on search change)\n\t// These are used to determine if the app has ANY runs at all (for empty state)\n\tconst [{ data: flowRunsCountAll }, { data: taskRunsCountAll }] =\n\t\tuseSuspenseQueries({\n\t\t\tqueries: [buildCountFlowRunsQuery(), buildCountTaskRunsQuery()],\n\t\t});\n\n\t// Use useQuery for paginated flow runs to leverage placeholderData: keepPreviousData\n\t// This prevents the page from suspending when search/filter changes\n\tconst { data: flowRunsPage } = useQuery(\n\t\tbuildPaginateFlowRunsQuery(buildPaginationBody(search), 30_000),\n\t);\n\n\t// Use useQuery for paginated task runs to leverage placeholderData: keepPreviousData\n\tconst { data: taskRunsPage } = useQuery(\n\t\tbuildPaginateTaskRunsQuery(buildTaskRunsPaginationBody(search), 30_000),\n\t);\n\n\t// Use useQuery for flow run history (scatter plot) to leverage placeholderData: keepPreviousData\n\t// This prevents the scatter plot from flickering when search/filter changes\n\tconst { data: flowRunHistory } = useQuery(\n\t\tbuildFlowRunHistoryQuery(buildHistoryFilter(search), 30_000),\n\t);\n\n\tconst flowRuns = flowRunsPage?.results ?? [];\n\tconst taskRuns = taskRunsPage?.results ?? [];\n\n\t// Extract date range from search params for the scatter plot\n\tconst scatterPlotDateRange = useMemo(() => {\n\t\tconst dateRangeFilter = getDateRangeFilter(search);\n\t\treturn {\n\t\t\tstartDate: dateRangeFilter?.after_\n\t\t\t\t? new Date(dateRangeFilter.after_)\n\t\t\t\t: undefined,\n\t\t\tendDate: dateRangeFilter?.before_\n\t\t\t\t? new Date(dateRangeFilter.before_)\n\t\t\t\t: undefined,\n\t\t};\n\t}, [search]);\n\n\t// Prefetch task run counts for the current page's flow runs\n\t// This ensures the data is ready when FlowRunCard renders\n\tuseEffect(() => {\n\t\tconst flowRunIds = flowRuns.map((run) => run.id);\n\t\tif (flowRunIds.length > 0) {\n\t\t\tvoid queryClient.prefetchQuery(\n\t\t\t\tbuildGetFlowRunsTaskRunsCountQuery(flowRunIds),\n\t\t\t);\n\t\t}\n\t}, [queryClient, flowRuns]);\n\n\tconst onPrefetchPage = useCallback(\n\t\t(page: number) => {\n\t\t\tconst filter = buildPaginationBody({\n\t\t\t\t...search,\n\t\t\t\tpage,\n\t\t\t});\n\t\t\t// Prefetch the page data, then chain prefetch of task run counts\n\t\t\tvoid (async () => {\n\t\t\t\tconst pageData = await queryClient.ensureQueryData(\n\t\t\t\t\tbuildPaginateFlowRunsQuery(filter, 30_000),\n\t\t\t\t);\n\t\t\t\tconst flowRunIds = pageData?.results?.map((run) => run.id) ?? [];\n\t\t\t\tif (flowRunIds.length > 0) {\n\t\t\t\t\tvoid queryClient.prefetchQuery(\n\t\t\t\t\t\tbuildGetFlowRunsTaskRunsCountQuery(flowRunIds),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t})();\n\t\t},\n\t\t[queryClient, search],\n\t);\n\n\tconst onTaskRunsPrefetchPage = useCallback(\n\t\t(page: number) => {\n\t\t\tconst filter = buildTaskRunsPaginationBody({\n\t\t\t\t...search,\n\t\t\t\t\"task-runs-page\": page,\n\t\t\t});\n\t\t\tvoid queryClient.prefetchQuery(\n\t\t\t\tbuildPaginateTaskRunsQuery(filter, 30_000),\n\t\t\t);\n\t\t},\n\t\t[queryClient, search],\n\t);\n\n\tconst onClearTaskRunFilters = useCallback(() => {\n\t\tonTaskRunSearchChange(\"\");\n\t}, [onTaskRunSearchChange]);\n\n\treturn (\n\t\t<RunsPage\n\t\t\ttab={tab}\n\t\t\tonTabChange={onTabChange}\n\t\t\tflowRunsCount={flowRunsPage?.count ?? 0}\n\t\t\ttaskRunsCount={taskRunsPage?.count ?? 0}\n\t\t\thasAnyFlowRuns={(flowRunsCountAll ?? 0) > 0}\n\t\t\thasAnyTaskRuns={(taskRunsCountAll ?? 0) > 0}\n\t\t\tflowRuns={flowRuns}\n\t\t\tflowRunsPages={flowRunsPage?.pages ?? 0}\n\t\t\tpagination={pagination}\n\t\t\tonPaginationChange={onPaginationChange}\n\t\t\tonPrefetchPage={onPrefetchPage}\n\t\t\tsort={sort}\n\t\t\tonSortChange={onSortChange}\n\t\t\thideSubflows={hideSubflows}\n\t\t\tonHideSubflowsChange={onHideSubflowsChange}\n\t\t\tflowRunSearch={flowRunSearch}\n\t\t\tonFlowRunSearchChange={onFlowRunSearchChange}\n\t\t\tselectedStates={selectedStates}\n\t\t\tonStateFilterChange={onStateFilterChange}\n\t\t\tselectedFlows={selectedFlows}\n\t\t\tonFlowFilterChange={onFlowFilterChange}\n\t\t\tselectedDeployments={selectedDeployments}\n\t\t\tonDeploymentFilterChange={onDeploymentFilterChange}\n\t\t\tselectedTags={selectedTags}\n\t\t\tonTagsFilterChange={onTagsFilterChange}\n\t\t\tselectedWorkPools={selectedWorkPools}\n\t\t\tonWorkPoolFilterChange={onWorkPoolFilterChange}\n\t\t\tdateRange={dateRange}\n\t\t\tonDateRangeChange={onDateRangeChange}\n\t\t\t// Scatter plot props\n\t\t\tflowRunHistory={flowRunHistory ?? []}\n\t\t\tscatterPlotDateRange={scatterPlotDateRange}\n\t\t\t// Task runs props\n\t\t\ttaskRuns={taskRuns}\n\t\t\ttaskRunsPages={taskRunsPage?.pages ?? 0}\n\t\t\ttaskRunsPagination={taskRunsPagination}\n\t\t\tonTaskRunsPaginationChange={onTaskRunsPaginationChange}\n\t\t\tonTaskRunsPrefetchPage={onTaskRunsPrefetchPage}\n\t\t\ttaskRunsSort={taskRunsSort}\n\t\t\tonTaskRunsSortChange={onTaskRunsSortChange}\n\t\t\ttaskRunSearch={taskRunSearch}\n\t\t\tonTaskRunSearchChange={onTaskRunSearchChange}\n\t\t\tonClearTaskRunFilters={onClearTaskRunFilters}\n\t\t\t// Saved filters props\n\t\t\tcurrentFilter={currentFilter}\n\t\t\tsavedFilters={savedFiltersForMenu}\n\t\t\tonSelectFilter={onSelectFilter}\n\t\t\tonSaveFilter={onSaveFilter}\n\t\t\tonDeleteFilter={onDeleteFilter}\n\t\t\tonSetDefault={onSetDefault}\n\t\t\tonRemoveDefault={onRemoveDefault}\n\t\t\tisSaveDialogOpen={isSaveDialogOpen}\n\t\t\tonCloseSaveDialog={closeSaveDialog}\n\t\t\tonConfirmSave={confirmSave}\n\t\t/>\n\t);\n}\n"],"names":["DateRangeFilter","value","onValueChange","className","dateRangeValue","useMemo","urlStateToDateRangeValue","handleValueChange","newValue","dateRangeValueToUrlState","jsx","RichDateRangeSelector","MAX_FLOWS_DISPLAYED","FlowFilter","selectedFlows","onSelectFlows","search","setSearch","useState","deferredSearch","useDeferredValue","flows","useQuery","buildListFlowsQuery","selectedFlowsData","handleSelectFlow","flowId","updatedFlows","handleClearAll","renderSelectedFlows","selectedFlowNames","flow","visible","extraCount","jsxs","Typography","filteredFlows","Combobox","ComboboxTrigger","ComboboxContent","ComboboxCommandInput","ComboboxCommandList","ComboboxCommandEmtpy","ComboboxCommandGroup","ComboboxCommandItem","Checkbox","useDeleteTaskRunsDialog","dialogState","confirmDelete","useDeleteConfirmationDialog","mutateAsync","useDeleteTaskRun","handleDeletes","taskRunIds","onConfirm","res","id","numFails","numSuccess","accumulator","currentValue","toast","err","TaskRunsRowCount","count","props","SelectedCount","pluralize","results","setSelectedRows","selectedRows","deleteConfirmationDialogState","resultsIds","selectedRowsList","ToggleCheckbox","isAllRowsSelected","isSomeRowsSelected","checkedState","checked","Fragment","Button","Icon","DeleteConfirmationDialog","useTaskRunsSelectedRows","defaultValues","addRow","curr","removeRow","CUSTOM_FILTER_NAME","UNSAVED_FILTER_NAME","isCustomOrUnsavedFilter","filter","SavedFiltersMenu","currentFilter","savedFilters","onSelect","onSave","onDelete","onSetDefault","onRemoveDefault","permissions","showDeleteDialog","setShowDeleteDialog","displayName","isCustomUnsaved","canSave","canDelete","canToggleDefault","handleDelete","handleToggleDefault","DropdownMenu","DropdownMenuTrigger","DropdownMenuContent","DropdownMenuItem","DropdownMenuSeparator","formatYAxisTick","SECONDS_PER_YEAR","SECONDS_PER_DAY","SECONDS_PER_HOUR","SECONDS_PER_MINUTE","years","days","hours","minutes","TIME_INTERVALS","generateNiceTimeTicks","startMs","endMs","targetTickCount","range","idealInterval","chosenInterval","interval","firstTick","ticks","tick","createXAxisTickFormatter","date","second","minute","hour","day","month","year","CustomDot","cx","cy","payload","fillColor","getStateColor","STATE_COLORS","strokeColor","FlowRunTooltip","active","data","flowRunId","flowRun","buildGetFlowRunDetailsQuery","buildFLowDetailsQuery","startTime","Link","ChevronRight","StateBadge","Clock","humanizeDuration","Calendar","FlowRunsScatterPlot","history","startDate","endDate","chartData","item","xDomain","now","timestamps","min","max","formatXAxisTick","xAxisTicks","ResponsiveContainer","ScatterChart","CartesianGrid","XAxis","YAxis","Tooltip","Scatter","formSchema","z.object","z.string","SaveFilterDialog","open","onOpenChange","form","useForm","zodResolver","useEffect","onSubmit","values","Dialog","DialogContent","DialogHeader","DialogTitle","DialogDescription","Form","e","FormField","field","FormItem","FormLabel","FormControl","Input","FormMessage","DialogFooter","SAVED_FILTERS_STORAGE_KEY","DEFAULT_FILTER_ID_STORAGE_KEY","SYSTEM_FILTER_PAST_WEEK_ID","SYSTEM_FILTER_HIDE_SCHEDULED_ID","isSystemFilter","SYSTEM_FILTERS","FLOW_RUN_STATES_WITHOUT_SCHEDULED","SYSTEM_DEFAULT_FILTER","generateFilterId","areFiltersEqual","filterA","filterB","sortedArrayEqual","b","sortedA","sortedB","val","idx","useSavedFilters","userSavedFilters","setUserSavedFilters","useLocalStorage","defaultFilterId","setDefaultFilterId","saveFilter","useCallback","filterCreate","newFilter","prev","deleteFilter","filterId","f","updateFilter","updates","setDefaultFilter","getFilterById","findMatchingFilter","filters","isDefaultFilter","RunsPage","tab","onTabChange","flowRunsCount","taskRunsCount","hasAnyFlowRuns","hasAnyTaskRuns","flowRuns","flowRunsPages","pagination","onPaginationChange","onPrefetchPage","sort","onSortChange","hideSubflows","onHideSubflowsChange","flowRunSearch","onFlowRunSearchChange","selectedStates","onStateFilterChange","onFlowFilterChange","selectedDeployments","onDeploymentFilterChange","selectedTags","onTagsFilterChange","selectedWorkPools","onWorkPoolFilterChange","dateRange","onDateRangeChange","flowRunHistory","scatterPlotDateRange","taskRuns","taskRunsPages","taskRunsPagination","onTaskRunsPaginationChange","onTaskRunsPrefetchPage","taskRunsSort","onTaskRunsSortChange","taskRunSearch","onTaskRunSearchChange","onClearTaskRunFilters","onSelectFilter","onSaveFilter","onDeleteFilter","isSaveDialogOpen","onCloseSaveDialog","onConfirmSave","isEmpty","onSelectRow","useFlowRunsSelectedRows","taskRunsSelectedRows","setTaskRunsSelectedRows","onSelectTaskRunRow","flowIds","flowRunsWithFlows","RunsHeader","RunsEmptyState","Label","StateFilter","DeploymentFilter","WorkPoolFilter","TagsInput","tags","Tabs","TabsList","TabsTrigger","TabsContent","Card","CardContent","FlowRunsRowCount","Switch","SearchInput","SortFilter","FlowRunsPagination","FlowRunsList","TaskRunsSortFilter","TaskRunsPagination","TaskRunsList","Breadcrumb","BreadcrumbList","BreadcrumbItem","EmptyState","EmptyStateIcon","EmptyStateTitle","EmptyStateDescription","EmptyStateActions","DocsLink","routeApi","getRouteApi","urlParamsToFilterValues","parseCommaSeparated","s","stateArray","flowsArray","deploymentsArray","workPoolsArray","tagsArray","filterValuesToUrlParams","toMenuFilter","useRunsSavedFilters","navigate","setIsSaveDialogOpen","currentFilterValues","matchingSavedFilter","savedFiltersForMenu","savedFilter","urlParams","confirmSave","name","closeSaveDialog","useApplyDefaultFilterOnMount","didApplyRef","useRef","hasActiveFilters","filterToApply","parseStateFilter","stateString","FLOW_RUN_STATES","parseCommaSeparatedFilter","filterString","useRunsFilters","states","deployments","workPools","onStatesChange","newStates","statesArray","onFlowsChange","newFlows","onDeploymentsChange","newDeployments","onWorkPoolsChange","newWorkPools","onTagsChange","newTags","newDateRange","clearAllFilters","z","optional","default","page","number","int","positive","catch","limit","undefined","SORT_FILTERS","boolean","string","state","DATE_RANGE_PRESETS","start","end","TASK_RUN_SORT_FILTERS","split","includes","getDateRangeFilter","dateRangeUrlState","mapValueToRange","after_","toISOString","before_","parseFlowsFilter","flowsString","trim","length","parseDeploymentsFilter","deploymentsString","parseWorkPoolsFilter","workPoolsString","parseTagsFilter","tagsString","buildPaginationBody","stateFilters","flowsFilter","deploymentsFilter","workPoolsFilter","tagsFilter","dateRangeFilter","stateNames","deploymentIds","workPoolNames","flowRunsFilter","operator","parent_task_run_id","is_null_","like_","any_","expected_start_time","flowsFilterBody","deploymentsFilterBody","workPoolsFilterBody","flow_runs","work_pools","buildTaskRunsPaginationBody","taskRunsFilter","task_runs","buildHistoryFilter","offset","usePagination","Route","useSearch","useNavigate","newPagination","to","replace","useSort","useHideSubflows","useTab","useFlowRunSearch","useTaskRunsPagination","useTaskRunsSort","useTaskRunSearch","RouteComponent","queryClient","useQueryClient","storedFlowRunsLimit","setStoredFlowRunsLimit","storedTaskRunsLimit","setStoredTaskRunsLimit","hasInitializedRef","current","needsFlowRunsLimit","needsTaskRunsLimit","flowRunsCountAll","taskRunsCountAll","useSuspenseQueries","queries","buildCountFlowRunsQuery","buildCountTaskRunsQuery","flowRunsPage","buildPaginateFlowRunsQuery","taskRunsPage","buildPaginateTaskRunsQuery","buildFlowRunHistoryQuery","Date","flowRunIds","map","run","prefetchQuery","buildGetFlowRunsTaskRunsCountQuery","ensureQueryData","pages"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{j as e,L as h,r as m,C as v,D,B as N,s as S,t as w}from"./vendor-tanstack-BcZfOOfy.js";import{ap as p,ao as f,bq as T,ag as I,ah as R,br as _,ai as z,aj as E,al as M,ak as P,am as A,an as L,q as j,I as k,U as F,E as Q,t as V,v as q,w as H,x as O,D as $,B as U,h as G,V as J,bs as K,bt as W,bu as g}from"./index-B8vo2Lrg.js";import{u as C,B as X}from"./use-delete-block-document-confirmation-dialog-DnwWEGUY.js";import{D as Y}from"./data-table-CPkppyg6.js";import{D as y}from"./delete-confirmation-dialog-CwDK_2QS.js";import{B as Z}from"./block-type-logo-CyAWq7mC.js";import{u as ee}from"./use-page-title-DEH55Ovu.js";import"./vendor-react-Bce9NwRC.js";import"./vendor-radix-BTiKGWfR.js";import"./vendor-recharts-BvvJP9Po.js";import"./vendor-forms-ClCIacbh.js";import"./vendor-date-wwuDAncJ.js";import"./dropdown-menu-D7Gwbd15.js";import"./use-delete-confirmation-dialog-CUdii6Lo.js";import"./table-BBNGfPra.js";const se=({blockDocument:a})=>{const{id:o,name:s,block_type:t,block_type_name:l}=a;return e.jsxs("div",{className:"flex gap-4 items-center",children:[t&&l&&e.jsx(Z,{size:"sm",logoUrl:t.logo_url,alt:`${l} logo`}),e.jsxs("div",{className:"flex flex-col",children:[s&&e.jsx(h,{to:"/blocks/block/$id",params:{id:o},children:e.jsx(p,{className:"font-semibold",children:s})}),l&&a.block_type?.slug&&e.jsx(h,{to:"/blocks/catalog/$slug",params:{slug:a.block_type.slug},children:e.jsx(p,{variant:"bodySmall",className:"text-muted-foreground",children:l})})]})]})},b=N(),ae=({onDelete:a})=>[b.display({maxSize:10,id:"select",header:({table:o})=>{let s=!1;return o.getIsAllRowsSelected()?s=!0:o.getIsSomePageRowsSelected()&&(s="indeterminate"),e.jsx(f,{checked:s,onCheckedChange:t=>o.toggleAllPageRowsSelected(!!t),"aria-label":"Select all"})},cell:({row:o})=>e.jsx(f,{checked:o.getIsSelected(),onCheckedChange:s=>o.toggleSelected(!!s),"aria-label":"Select row"}),enableSorting:!1,enableHiding:!1}),b.display({id:"block",header:"Block",cell:({row:o})=>e.jsx(se,{blockDocument:o.original})}),b.display({id:"actions",cell:o=>{const s=o.row.original;return e.jsx("div",{className:"flex justify-end",children:e.jsx(X,{blockDocument:s,onDelete:()=>a(s)})})}})],oe=({blockDocuments:a,blockDocumentsCount:o,onPaginationChange:s,pagination:t,rowSelection:l,setRowSelection:i})=>{const[r,d]=C(),u=m.useCallback(c=>{let x=t;typeof c=="function"?x=c(t):x=c,s(x)},[t,s]),n=v({columns:ae({onDelete:d}),data:a,defaultColumn:{maxSize:300},getCoreRowModel:D(),manualPagination:!0,onPaginationChange:u,rowCount:o,getRowId:c=>c.id,onRowSelectionChange:i,state:{pagination:t,rowSelection:l}});return e.jsxs(e.Fragment,{children:[e.jsx(Y,{table:n}),e.jsx(y,{...r})]})};function te({selectedBlockTypesSlugs:a,onToggleBlockTypeSlug:o,onRemoveBlockTypeSlug:s}){return e.jsx(m.Suspense,{children:e.jsx(le,{selectedBlockTypesSlugs:a,onToggleBlockTypeSlug:o,onRemoveBlockTypeSlug:s})})}function le({selectedBlockTypesSlugs:a,onToggleBlockTypeSlug:o,onRemoveBlockTypeSlug:s}){const[t,l]=m.useState(""),i=m.useDeferredValue(t),{data:r}=S(T()),d=m.useMemo(()=>a.map(n=>r.find(c=>c.slug===n)).filter(Boolean),[r,a]),u=m.useMemo(()=>r.filter(n=>n.name.toLowerCase().includes(i.toLowerCase())),[r,i]);return e.jsxs(I,{children:[e.jsx(R,{selected:a.length>0,children:e.jsx("div",{className:"flex gap-1",children:a.length>0?d.map(n=>e.jsx(_,{tag:n.name,onRemove:()=>s(n.slug)},n.id)):"Block type"})}),e.jsxs(z,{children:[e.jsx(E,{value:t,onValueChange:l,placeholder:"Search for a block type..."}),e.jsx(M,{children:"No block type found"}),e.jsx(P,{children:e.jsx(A,{children:u.map(n=>e.jsxs(L,{selected:a.includes(n.slug),onSelect:c=>{o(c),l("")},value:n.slug,closeOnSelect:!1,children:[e.jsx("input",{type:"checkbox",checked:a.includes(n.slug),readOnly:!0,className:"mr-2 pointer-events-none"}),n.name]},n.id))})})]})]})}const ne=({count:a,rowSelection:o,setRowSelection:s})=>{const[t,l]=C(),i=m.useMemo(()=>Object.keys(o),[o]);return i.length>0?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(p,{variant:"bodySmall",className:"text-muted-foreground",children:[i.length," selected"]}),e.jsx(j,{"aria-label":"Delete rows",size:"icon",variant:"secondary",onClick:()=>{l(i,{onSuccess:()=>s({})})},children:e.jsx(k,{id:"Trash2",className:"size-4"})})]}),e.jsx(y,{...t})]}):e.jsxs(p,{variant:"bodySmall",className:"text-muted-foreground",children:[a," ",F(a,"Block")]})},ce=()=>e.jsxs(Q,{children:[e.jsx(V,{id:"Box"}),e.jsx(q,{children:"Add a block to get started"}),e.jsx(H,{children:"Blocks securely store credentials and configuration to easily manage connections to external systems."}),e.jsxs(O,{children:[e.jsx(h,{to:"/blocks/catalog",children:e.jsxs(j,{children:["Add Block ",e.jsx(k,{id:"Plus",className:"size-4 ml-2"})]})}),e.jsx($,{id:"blocks-guide"})]})]}),ie=({allCount:a,blockDocuments:o=[],onSearch:s,search:t,blockTypeSlugsFilter:l,onToggleBlockTypeSlug:i,onRemoveBlockTypeSlug:r,pagination:d,onPaginationChange:u})=>{const[n,c]=m.useState({});return e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(U,{children:e.jsx(G,{className:"text-xl font-semibold",children:"Blocks"})}),e.jsx(j,{size:"icon",className:"size-7",variant:"outline",children:e.jsx(h,{to:"/blocks/catalog",children:e.jsx(k,{id:"Plus",className:"size-4"})})})]}),a===0?e.jsx(ce,{}):e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx(ne,{rowSelection:n,setRowSelection:c,count:a}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("div",{className:"min-w-56",children:e.jsx(J,{"aria-label":"search blocks",placeholder:"Search blocks",value:t,onChange:x=>s(x.target.value)})}),e.jsx("div",{className:"min-w-64",children:e.jsx(te,{selectedBlockTypesSlugs:l,onToggleBlockTypeSlug:i,onRemoveBlockTypeSlug:r})})]})]}),e.jsx(oe,{blockDocuments:o,rowSelection:n,setRowSelection:c,blockDocumentsCount:a,pagination:d,onPaginationChange:u})]})]})};function Ne(){ee("Blocks");const[a,o]=re(),[s,t]=me(),[l,i]=de(),{data:r}=S(K()),{data:d}=w(W({sort:"NAME_ASC",include_secrets:!1,block_documents:{name:{like_:a},operator:"and_",is_anonymous:{eq_:!1}},block_types:{slug:{any_:s.length>0?s:void 0}},offset:l.pageIndex*l.pageSize,limit:l.pageSize})),u=c=>{const x=s.filter(B=>B!==c);t(x)},n=c=>{if(s.includes(c))return u(c);t([...s,c])};return e.jsx(ie,{allCount:r,blockDocuments:d,onSearch:o,search:a,blockTypeSlugsFilter:s,onRemoveBlockTypeSlug:u,onToggleBlockTypeSlug:n,pagination:l,onPaginationChange:i})}function re(){const{blockName:a}=g.useSearch(),o=g.useNavigate(),s=m.useCallback(l=>{o({to:".",search:i=>({...i,blockName:l}),replace:!0})},[o]);return[m.useMemo(()=>a??"",[a]),s]}function me(){const{blockTypes:a=[]}=g.useSearch(),o=g.useNavigate(),s=m.useCallback(t=>{o({to:".",search:l=>({...l,blockTypes:t}),replace:!0})},[o]);return[a,s]}function de(){const a=g.useSearch(),o=g.useNavigate(),s=(a.page??1)-1,t=a.limit??10,l=m.useMemo(()=>({pageIndex:s,pageSize:t}),[s,t]),i=m.useCallback(r=>{o({to:".",search:d=>({...d,page:r.pageIndex+1,limit:r.pageSize}),replace:!0})},[o]);return[l,i]}export{Ne as component};
2
+ //# sourceMappingURL=index-By6YGqR3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-By6YGqR3.js","sources":["../../src/components/blocks/block-document-data-table/block-document-cell.tsx","../../src/components/blocks/block-document-data-table/block-document-data-table.tsx","../../src/components/blocks/block-types-multi-select/block-types-multi-select.tsx","../../src/components/blocks/blocks-row-count/blocks-row-count.tsx","../../src/components/blocks/empty-state/empty-state.tsx","../../src/components/blocks/blocks-page.tsx","../../src/routes/blocks/index.tsx?tsr-split=component"],"sourcesContent":["import { Link } from \"@tanstack/react-router\";\nimport type { BlockDocument } from \"@/api/block-documents\";\nimport { BlockTypeLogo } from \"@/components/block-type-logo/block-type-logo\";\nimport { Typography } from \"@/components/ui/typography\";\n\ntype BlockDocumentCellProps = {\n\tblockDocument: BlockDocument;\n};\n\nexport const BlockDocumentCell = ({\n\tblockDocument,\n}: BlockDocumentCellProps) => {\n\tconst { id, name, block_type, block_type_name } = blockDocument;\n\n\treturn (\n\t\t<div className=\"flex gap-4 items-center\">\n\t\t\t{block_type && block_type_name && (\n\t\t\t\t<BlockTypeLogo\n\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\tlogoUrl={block_type.logo_url}\n\t\t\t\t\talt={`${block_type_name} logo`}\n\t\t\t\t/>\n\t\t\t)}\n\t\t\t<div className=\"flex flex-col\">\n\t\t\t\t{name && (\n\t\t\t\t\t<Link to=\"/blocks/block/$id\" params={{ id }}>\n\t\t\t\t\t\t<Typography className=\"font-semibold\">{name}</Typography>\n\t\t\t\t\t</Link>\n\t\t\t\t)}\n\t\t\t\t{block_type_name && blockDocument.block_type?.slug && (\n\t\t\t\t\t<Link\n\t\t\t\t\t\tto=\"/blocks/catalog/$slug\"\n\t\t\t\t\t\tparams={{ slug: blockDocument.block_type.slug }}\n\t\t\t\t\t>\n\t\t\t\t\t\t<Typography variant=\"bodySmall\" className=\"text-muted-foreground\">\n\t\t\t\t\t\t\t{block_type_name}\n\t\t\t\t\t\t</Typography>\n\t\t\t\t\t</Link>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t);\n};\n","import type { CheckedState } from \"@radix-ui/react-checkbox\";\nimport {\n\tcreateColumnHelper,\n\tgetCoreRowModel,\n\ttype OnChangeFn,\n\ttype PaginationState,\n\ttype RowSelectionState,\n\tuseReactTable,\n} from \"@tanstack/react-table\";\nimport { useCallback } from \"react\";\nimport type { BlockDocument } from \"@/api/block-documents\";\nimport { BlockDocumentActionMenu } from \"@/components/blocks/block-document-action-menu\";\nimport { useDeleteBlockDocumentConfirmationDialog } from \"@/components/blocks/use-delete-block-document-confirmation-dialog\";\nimport { Checkbox } from \"@/components/ui/checkbox\";\nimport { DataTable } from \"@/components/ui/data-table\";\nimport { DeleteConfirmationDialog } from \"@/components/ui/delete-confirmation-dialog\";\nimport { BlockDocumentCell } from \"./block-document-cell\";\n\nconst columnHelper = createColumnHelper<BlockDocument>();\n\nconst createColumns = ({\n\tonDelete,\n}: {\n\tonDelete: (blockDocument: BlockDocument) => void;\n}) => [\n\tcolumnHelper.display({\n\t\tmaxSize: 10,\n\t\tid: \"select\",\n\t\theader: ({ table }) => {\n\t\t\tlet checkedState: CheckedState = false;\n\t\t\tif (table.getIsAllRowsSelected()) {\n\t\t\t\tcheckedState = true;\n\t\t\t} else if (table.getIsSomePageRowsSelected()) {\n\t\t\t\tcheckedState = \"indeterminate\";\n\t\t\t}\n\t\t\treturn (\n\t\t\t\t<Checkbox\n\t\t\t\t\tchecked={checkedState}\n\t\t\t\t\tonCheckedChange={(value) =>\n\t\t\t\t\t\ttable.toggleAllPageRowsSelected(Boolean(value))\n\t\t\t\t\t}\n\t\t\t\t\taria-label=\"Select all\"\n\t\t\t\t/>\n\t\t\t);\n\t\t},\n\t\tcell: ({ row }) => (\n\t\t\t<Checkbox\n\t\t\t\tchecked={row.getIsSelected()}\n\t\t\t\tonCheckedChange={(value) => row.toggleSelected(Boolean(value))}\n\t\t\t\taria-label=\"Select row\"\n\t\t\t/>\n\t\t),\n\t\tenableSorting: false,\n\t\tenableHiding: false,\n\t}),\n\tcolumnHelper.display({\n\t\tid: \"block\",\n\t\theader: \"Block\",\n\t\tcell: ({ row }) => <BlockDocumentCell blockDocument={row.original} />,\n\t}),\n\tcolumnHelper.display({\n\t\tid: \"actions\",\n\t\tcell: (props) => {\n\t\t\tconst cell = props.row.original;\n\t\t\treturn (\n\t\t\t\t<div className=\"flex justify-end\">\n\t\t\t\t\t<BlockDocumentActionMenu\n\t\t\t\t\t\tblockDocument={cell}\n\t\t\t\t\t\tonDelete={() => onDelete(cell)}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t);\n\t\t},\n\t}),\n];\n\nexport type BlockDocumentsDataTableProps = {\n\tblockDocumentsCount: number;\n\tblockDocuments: Array<BlockDocument>;\n\tpagination: PaginationState;\n\tonPaginationChange: (pagination: PaginationState) => void;\n\trowSelection: RowSelectionState;\n\tsetRowSelection: OnChangeFn<RowSelectionState>;\n};\nexport const BlockDocumentsDataTable = ({\n\tblockDocuments,\n\tblockDocumentsCount,\n\tonPaginationChange,\n\tpagination,\n\trowSelection,\n\tsetRowSelection,\n}: BlockDocumentsDataTableProps) => {\n\tconst [dialogState, handleConfirmDelete] =\n\t\tuseDeleteBlockDocumentConfirmationDialog();\n\n\tconst handlePaginationChange: OnChangeFn<PaginationState> = useCallback(\n\t\t(updater) => {\n\t\t\tlet newPagination = pagination;\n\t\t\tif (typeof updater === \"function\") {\n\t\t\t\tnewPagination = updater(pagination);\n\t\t\t} else {\n\t\t\t\tnewPagination = updater;\n\t\t\t}\n\t\t\tonPaginationChange(newPagination);\n\t\t},\n\t\t[pagination, onPaginationChange],\n\t);\n\n\tconst table = useReactTable({\n\t\tcolumns: createColumns({ onDelete: handleConfirmDelete }),\n\t\tdata: blockDocuments,\n\t\tdefaultColumn: { maxSize: 300 },\n\t\tgetCoreRowModel: getCoreRowModel(),\n\t\tmanualPagination: true,\n\t\tonPaginationChange: handlePaginationChange,\n\t\trowCount: blockDocumentsCount,\n\t\tgetRowId: (row) => row.id,\n\t\tonRowSelectionChange: setRowSelection,\n\t\tstate: { pagination, rowSelection },\n\t});\n\n\treturn (\n\t\t<>\n\t\t\t<DataTable table={table} />\n\t\t\t<DeleteConfirmationDialog {...dialogState} />\n\t\t</>\n\t);\n};\n","\"use client\";\n\nimport { useSuspenseQuery } from \"@tanstack/react-query\";\nimport { Suspense, useDeferredValue, useMemo, useState } from \"react\";\nimport {\n\ttype BlockType,\n\tbuildListFilterBlockTypesQuery,\n} from \"@/api/block-types\";\nimport {\n\tCombobox,\n\tComboboxCommandEmtpy,\n\tComboboxCommandGroup,\n\tComboboxCommandInput,\n\tComboboxCommandItem,\n\tComboboxCommandList,\n\tComboboxContent,\n\tComboboxTrigger,\n} from \"@/components/ui/combobox\";\nimport { TagBadge } from \"@/components/ui/tag-badge\";\n\ntype BlockTypesMultiSelectProps = {\n\tselectedBlockTypesSlugs: Array<string>;\n\tonToggleBlockTypeSlug: (blockTypeSlug: string) => void;\n\tonRemoveBlockTypeSlug: (blockTypeSlug: string) => void;\n};\n\nexport function BlockTypesMultiSelect({\n\tselectedBlockTypesSlugs,\n\tonToggleBlockTypeSlug,\n\tonRemoveBlockTypeSlug,\n}: BlockTypesMultiSelectProps) {\n\treturn (\n\t\t<Suspense>\n\t\t\t<BlockTypesMultiSelectImplementation\n\t\t\t\tselectedBlockTypesSlugs={selectedBlockTypesSlugs}\n\t\t\t\tonToggleBlockTypeSlug={onToggleBlockTypeSlug}\n\t\t\t\tonRemoveBlockTypeSlug={onRemoveBlockTypeSlug}\n\t\t\t/>\n\t\t</Suspense>\n\t);\n}\n\nfunction BlockTypesMultiSelectImplementation({\n\tselectedBlockTypesSlugs,\n\tonToggleBlockTypeSlug,\n\tonRemoveBlockTypeSlug,\n}: BlockTypesMultiSelectProps) {\n\tconst [search, setSearch] = useState(\"\");\n\n\tconst deferredSearch = useDeferredValue(search);\n\n\tconst { data: blockTypes } = useSuspenseQuery(\n\t\tbuildListFilterBlockTypesQuery(),\n\t);\n\n\tconst selectedBlockTypes = useMemo(() => {\n\t\treturn selectedBlockTypesSlugs\n\t\t\t.map((blockTypeSlug) =>\n\t\t\t\tblockTypes.find((blockType) => blockType.slug === blockTypeSlug),\n\t\t\t)\n\t\t\t.filter(Boolean) as Array<BlockType>;\n\t}, [blockTypes, selectedBlockTypesSlugs]);\n\n\tconst filteredData = useMemo(() => {\n\t\treturn blockTypes.filter((blockType) =>\n\t\t\tblockType.name.toLowerCase().includes(deferredSearch.toLowerCase()),\n\t\t);\n\t}, [blockTypes, deferredSearch]);\n\n\treturn (\n\t\t<Combobox>\n\t\t\t<ComboboxTrigger selected={selectedBlockTypesSlugs.length > 0}>\n\t\t\t\t<div className=\"flex gap-1\">\n\t\t\t\t\t{selectedBlockTypesSlugs.length > 0\n\t\t\t\t\t\t? selectedBlockTypes.map((blockType) => (\n\t\t\t\t\t\t\t\t<TagBadge\n\t\t\t\t\t\t\t\t\tkey={blockType.id}\n\t\t\t\t\t\t\t\t\ttag={blockType.name}\n\t\t\t\t\t\t\t\t\tonRemove={() => onRemoveBlockTypeSlug(blockType.slug)}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t))\n\t\t\t\t\t\t: \"Block type\"}\n\t\t\t\t</div>\n\t\t\t</ComboboxTrigger>\n\t\t\t<ComboboxContent>\n\t\t\t\t<ComboboxCommandInput\n\t\t\t\t\tvalue={search}\n\t\t\t\t\tonValueChange={setSearch}\n\t\t\t\t\tplaceholder=\"Search for a block type...\"\n\t\t\t\t/>\n\t\t\t\t<ComboboxCommandEmtpy>No block type found</ComboboxCommandEmtpy>\n\t\t\t\t<ComboboxCommandList>\n\t\t\t\t\t<ComboboxCommandGroup>\n\t\t\t\t\t\t{filteredData.map((blockType) => (\n\t\t\t\t\t\t\t<ComboboxCommandItem\n\t\t\t\t\t\t\t\tkey={blockType.id}\n\t\t\t\t\t\t\t\tselected={selectedBlockTypesSlugs.includes(blockType.slug)}\n\t\t\t\t\t\t\t\tonSelect={(value) => {\n\t\t\t\t\t\t\t\t\tonToggleBlockTypeSlug(value);\n\t\t\t\t\t\t\t\t\tsetSearch(\"\");\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\tvalue={blockType.slug}\n\t\t\t\t\t\t\t\tcloseOnSelect={false}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\t\t\tchecked={selectedBlockTypesSlugs.includes(blockType.slug)}\n\t\t\t\t\t\t\t\t\treadOnly\n\t\t\t\t\t\t\t\t\tclassName=\"mr-2 pointer-events-none\"\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t{blockType.name}\n\t\t\t\t\t\t\t</ComboboxCommandItem>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</ComboboxCommandGroup>\n\t\t\t\t</ComboboxCommandList>\n\t\t\t</ComboboxContent>\n\t\t</Combobox>\n\t);\n}\n","import type { OnChangeFn, RowSelectionState } from \"@tanstack/react-table\";\nimport { useMemo } from \"react\";\nimport { useDeleteBlockDocumentConfirmationDialog } from \"@/components/blocks/use-delete-block-document-confirmation-dialog\";\nimport { Button } from \"@/components/ui/button\";\nimport { DeleteConfirmationDialog } from \"@/components/ui/delete-confirmation-dialog\";\nimport { Icon } from \"@/components/ui/icons\";\nimport { Typography } from \"@/components/ui/typography\";\nimport { pluralize } from \"@/utils\";\n\nexport type BlocksRowCountProps = {\n\tcount: number;\n\trowSelection: RowSelectionState;\n\tsetRowSelection: OnChangeFn<RowSelectionState>;\n};\nexport const BlocksRowCount = ({\n\tcount,\n\trowSelection,\n\tsetRowSelection,\n}: BlocksRowCountProps) => {\n\tconst [deleteConfirmationDialogState, handleConfirmDelete] =\n\t\tuseDeleteBlockDocumentConfirmationDialog();\n\n\tconst selectedBlockIds = useMemo(\n\t\t() => Object.keys(rowSelection),\n\t\t[rowSelection],\n\t);\n\n\t// If has selected rows\n\tif (selectedBlockIds.length > 0)\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t<Typography variant=\"bodySmall\" className=\"text-muted-foreground\">\n\t\t\t\t\t\t{selectedBlockIds.length} selected\n\t\t\t\t\t</Typography>\n\t\t\t\t\t<Button\n\t\t\t\t\t\taria-label=\"Delete rows\"\n\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\thandleConfirmDelete(selectedBlockIds, {\n\t\t\t\t\t\t\t\tonSuccess: () => setRowSelection({}),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<Icon id=\"Trash2\" className=\"size-4\" />\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\t\t\t\t<DeleteConfirmationDialog {...deleteConfirmationDialogState} />\n\t\t\t</>\n\t\t);\n\n\treturn (\n\t\t<Typography variant=\"bodySmall\" className=\"text-muted-foreground\">\n\t\t\t{count} {pluralize(count, \"Block\")}\n\t\t</Typography>\n\t);\n};\n","import { Link } from \"@tanstack/react-router\";\nimport { Button } from \"@/components/ui/button\";\nimport { DocsLink } from \"@/components/ui/docs-link\";\nimport {\n\tEmptyState,\n\tEmptyStateActions,\n\tEmptyStateDescription,\n\tEmptyStateIcon,\n\tEmptyStateTitle,\n} from \"@/components/ui/empty-state\";\nimport { Icon } from \"@/components/ui/icons\";\n\nexport const BlocksEmptyState = () => (\n\t<EmptyState>\n\t\t<EmptyStateIcon id=\"Box\" />\n\t\t<EmptyStateTitle>Add a block to get started</EmptyStateTitle>\n\t\t<EmptyStateDescription>\n\t\t\tBlocks securely store credentials and configuration to easily manage\n\t\t\tconnections to external systems.\n\t\t</EmptyStateDescription>\n\t\t<EmptyStateActions>\n\t\t\t<Link to=\"/blocks/catalog\">\n\t\t\t\t<Button>\n\t\t\t\t\tAdd Block <Icon id=\"Plus\" className=\"size-4 ml-2\" />\n\t\t\t\t</Button>\n\t\t\t</Link>\n\t\t\t<DocsLink id=\"blocks-guide\" />\n\t\t</EmptyStateActions>\n\t</EmptyState>\n);\n","import { Link } from \"@tanstack/react-router\";\nimport type { PaginationState, RowSelectionState } from \"@tanstack/react-table\";\nimport { useState } from \"react\";\nimport type { BlockDocument } from \"@/api/block-documents\";\nimport { Breadcrumb, BreadcrumbItem } from \"@/components/ui/breadcrumb\";\nimport { Button } from \"@/components/ui/button\";\nimport { Icon } from \"@/components/ui/icons\";\nimport { SearchInput } from \"@/components/ui/input\";\nimport { BlockDocumentsDataTable } from \"./block-document-data-table\";\nimport { BlockTypesMultiSelect } from \"./block-types-multi-select\";\nimport { BlocksRowCount } from \"./blocks-row-count\";\nimport { BlocksEmptyState } from \"./empty-state\";\n\ntype BlocksPageProps = {\n\tallCount: number;\n\tblockDocuments: Array<BlockDocument> | undefined;\n\tonSearch: (value?: string) => void;\n\tsearch: string;\n\tblockTypeSlugsFilter: Array<string>;\n\tonToggleBlockTypeSlug: (blockTypeIds: string) => void;\n\tonRemoveBlockTypeSlug: (blockTypeIds: string) => void;\n\tpagination: PaginationState;\n\tonPaginationChange: (paginationState: PaginationState) => void;\n};\n\nexport const BlocksPage = ({\n\tallCount,\n\tblockDocuments = [],\n\tonSearch,\n\tsearch,\n\tblockTypeSlugsFilter,\n\tonToggleBlockTypeSlug,\n\tonRemoveBlockTypeSlug,\n\tpagination,\n\tonPaginationChange,\n}: BlocksPageProps) => {\n\tconst [rowSelection, setRowSelection] = useState<RowSelectionState>({});\n\n\treturn (\n\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t<Breadcrumb>\n\t\t\t\t\t<BreadcrumbItem className=\"text-xl font-semibold\">\n\t\t\t\t\t\tBlocks\n\t\t\t\t\t</BreadcrumbItem>\n\t\t\t\t</Breadcrumb>\n\t\t\t\t<Button size=\"icon\" className=\"size-7\" variant=\"outline\">\n\t\t\t\t\t<Link to=\"/blocks/catalog\">\n\t\t\t\t\t\t<Icon id=\"Plus\" className=\"size-4\" />\n\t\t\t\t\t</Link>\n\t\t\t\t</Button>\n\t\t\t</div>\n\t\t\t{allCount === 0 ? (\n\t\t\t\t<BlocksEmptyState />\n\t\t\t) : (\n\t\t\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t\t\t<div className=\"flex items-center justify-between\">\n\t\t\t\t\t\t<BlocksRowCount\n\t\t\t\t\t\t\trowSelection={rowSelection}\n\t\t\t\t\t\t\tsetRowSelection={setRowSelection}\n\t\t\t\t\t\t\tcount={allCount}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t\t\t<div className=\"min-w-56\">\n\t\t\t\t\t\t\t\t<SearchInput\n\t\t\t\t\t\t\t\t\taria-label=\"search blocks\"\n\t\t\t\t\t\t\t\t\tplaceholder=\"Search blocks\"\n\t\t\t\t\t\t\t\t\tvalue={search}\n\t\t\t\t\t\t\t\t\tonChange={(e) => onSearch(e.target.value)}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div className=\"min-w-64\">\n\t\t\t\t\t\t\t\t<BlockTypesMultiSelect\n\t\t\t\t\t\t\t\t\tselectedBlockTypesSlugs={blockTypeSlugsFilter}\n\t\t\t\t\t\t\t\t\tonToggleBlockTypeSlug={onToggleBlockTypeSlug}\n\t\t\t\t\t\t\t\t\tonRemoveBlockTypeSlug={onRemoveBlockTypeSlug}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<BlockDocumentsDataTable\n\t\t\t\t\t\tblockDocuments={blockDocuments}\n\t\t\t\t\t\trowSelection={rowSelection}\n\t\t\t\t\t\tsetRowSelection={setRowSelection}\n\t\t\t\t\t\tblockDocumentsCount={allCount}\n\t\t\t\t\t\tpagination={pagination}\n\t\t\t\t\t\tonPaginationChange={onPaginationChange}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n};\n","import { useQuery, useSuspenseQuery } from \"@tanstack/react-query\";\nimport { createFileRoute } from \"@tanstack/react-router\";\nimport type { PaginationState } from \"@tanstack/react-table\";\nimport { zodValidator } from \"@tanstack/zod-adapter\";\nimport { useCallback, useMemo } from \"react\";\nimport { z } from \"zod\";\nimport {\n\ttype BlockDocumentsFilter,\n\tbuildCountAllBlockDocumentsQuery,\n\tbuildCountFilterBlockDocumentsQuery,\n\tbuildListFilterBlockDocumentsQuery,\n} from \"@/api/block-documents\";\nimport { buildListFilterBlockTypesQuery } from \"@/api/block-types\";\nimport { BlocksPage } from \"@/components/blocks/blocks-page\";\nimport { usePageTitle } from \"@/hooks/use-page-title\";\n\nconst searchParams = z.object({\n\tblockName: z.string().optional(),\n\tblockTypes: z.array(z.string()).optional(),\n\tpage: z.number().int().positive().optional().default(1).catch(1),\n\tlimit: z.number().int().positive().optional().default(10).catch(10),\n});\n\nexport const Route = createFileRoute(\"/blocks/\")({\n\tvalidateSearch: zodValidator(searchParams),\n\tcomponent: RouteComponent,\n\tloaderDeps: ({ search: { blockName, blockTypes, page, limit } }) => ({\n\t\tblockName,\n\t\tblockTypes,\n\t\tpage,\n\t\tlimit,\n\t}),\n\tloader: ({ deps, context: { queryClient } }) => {\n\t\t// ----- Critical data\n\t\tconst filter: BlockDocumentsFilter = {\n\t\t\tblock_types: { slug: { any_: deps.blockTypes } },\n\t\t\tblock_documents: {\n\t\t\t\tis_anonymous: { eq_: false },\n\t\t\t\toperator: \"or_\",\n\t\t\t\tname: { like_: deps.blockName },\n\t\t\t},\n\t\t\tlimit: deps.limit,\n\t\t\toffset: deps.page,\n\t\t\tinclude_secrets: false,\n\t\t\tsort: \"NAME_ASC\",\n\t\t};\n\t\treturn Promise.all([\n\t\t\tqueryClient.ensureQueryData(buildListFilterBlockTypesQuery()),\n\t\t\t// All count query\n\t\t\tqueryClient.ensureQueryData(buildCountAllBlockDocumentsQuery()),\n\t\t\t// Filtered block document\n\t\t\tqueryClient.ensureQueryData(buildListFilterBlockDocumentsQuery(filter)),\n\t\t\t// Filtered count query\n\t\t\tqueryClient.ensureQueryData(buildCountFilterBlockDocumentsQuery(filter)),\n\t\t]);\n\t},\n\twrapInSuspense: true,\n});\n\nfunction RouteComponent() {\n\tusePageTitle(\"Blocks\");\n\tconst [search, onSearch] = useSearch();\n\tconst [blockTypeSlugs, onSetBlockTypeSlugs] = useFilterByBlockTypes();\n\tconst [pagination, onPaginationChange] = usePagination();\n\n\tconst { data: allBlockDocumentsCount } = useSuspenseQuery(\n\t\tbuildCountAllBlockDocumentsQuery(),\n\t);\n\n\tconst { data: blockDocuments } = useQuery(\n\t\tbuildListFilterBlockDocumentsQuery({\n\t\t\tsort: \"NAME_ASC\",\n\t\t\tinclude_secrets: false,\n\t\t\tblock_documents: {\n\t\t\t\tname: { like_: search },\n\t\t\t\toperator: \"and_\",\n\t\t\t\tis_anonymous: { eq_: false },\n\t\t\t},\n\t\t\tblock_types: {\n\t\t\t\tslug: {\n\t\t\t\t\tany_: blockTypeSlugs.length > 0 ? blockTypeSlugs : undefined,\n\t\t\t\t},\n\t\t\t},\n\t\t\toffset: pagination.pageIndex * pagination.pageSize,\n\t\t\tlimit: pagination.pageSize,\n\t\t}),\n\t);\n\n\tconst handleRemoveBlockType = (id: string) => {\n\t\tconst newValue = blockTypeSlugs.filter((blockId) => blockId !== id);\n\t\tonSetBlockTypeSlugs(newValue);\n\t};\n\n\tconst handleToggleBlockType = (id: string) => {\n\t\t// Remove block id if its in the list\n\t\tif (blockTypeSlugs.includes(id)) {\n\t\t\treturn handleRemoveBlockType(id);\n\t\t}\n\t\t// Else add it to the list\n\t\tonSetBlockTypeSlugs([...blockTypeSlugs, id]);\n\t};\n\n\treturn (\n\t\t<BlocksPage\n\t\t\tallCount={allBlockDocumentsCount}\n\t\t\tblockDocuments={blockDocuments}\n\t\t\tonSearch={onSearch}\n\t\t\tsearch={search}\n\t\t\tblockTypeSlugsFilter={blockTypeSlugs}\n\t\t\tonRemoveBlockTypeSlug={handleRemoveBlockType}\n\t\t\tonToggleBlockTypeSlug={handleToggleBlockType}\n\t\t\tpagination={pagination}\n\t\t\tonPaginationChange={onPaginationChange}\n\t\t/>\n\t);\n}\n\nfunction useSearch() {\n\tconst { blockName } = Route.useSearch();\n\tconst navigate = Route.useNavigate();\n\n\tconst onSearch = useCallback(\n\t\t(value?: string) => {\n\t\t\tvoid navigate({\n\t\t\t\tto: \".\",\n\t\t\t\tsearch: (prev) => ({\n\t\t\t\t\t...prev,\n\t\t\t\t\tblockName: value,\n\t\t\t\t}),\n\t\t\t\treplace: true,\n\t\t\t});\n\t\t},\n\t\t[navigate],\n\t);\n\tconst search = useMemo(() => blockName ?? \"\", [blockName]);\n\treturn [search, onSearch] as const;\n}\n\nfunction useFilterByBlockTypes() {\n\tconst { blockTypes = [] } = Route.useSearch();\n\tconst navigate = Route.useNavigate();\n\n\tconst onSetBlockTypes = useCallback(\n\t\t(value?: Array<string>) => {\n\t\t\tvoid navigate({\n\t\t\t\tto: \".\",\n\t\t\t\tsearch: (prev) => ({\n\t\t\t\t\t...prev,\n\t\t\t\t\tblockTypes: value,\n\t\t\t\t}),\n\t\t\t\treplace: true,\n\t\t\t});\n\t\t},\n\t\t[navigate],\n\t);\n\n\treturn [blockTypes, onSetBlockTypes] as const;\n}\n\nfunction usePagination() {\n\tconst search = Route.useSearch();\n\tconst navigate = Route.useNavigate();\n\n\t// React Table uses 0-based pagination, so we need to subtract 1 from the page number\n\tconst pageIndex = (search.page ?? 1) - 1;\n\tconst pageSize = search.limit ?? 10;\n\tconst pagination: PaginationState = useMemo(\n\t\t() => ({\n\t\t\tpageIndex,\n\t\t\tpageSize,\n\t\t}),\n\t\t[pageIndex, pageSize],\n\t);\n\n\tconst onPaginationChange = useCallback(\n\t\t(newPagination: PaginationState) => {\n\t\t\tvoid navigate({\n\t\t\t\tto: \".\",\n\t\t\t\tsearch: (prev) => ({\n\t\t\t\t\t...prev,\n\t\t\t\t\tpage: newPagination.pageIndex + 1,\n\t\t\t\t\tlimit: newPagination.pageSize,\n\t\t\t\t}),\n\t\t\t\treplace: true,\n\t\t\t});\n\t\t},\n\t\t[navigate],\n\t);\n\n\treturn [pagination, onPaginationChange] as const;\n}\n"],"names":["BlockDocumentCell","blockDocument","id","name","block_type","block_type_name","jsxs","jsx","BlockTypeLogo","Link","Typography","columnHelper","createColumnHelper","createColumns","onDelete","table","checkedState","Checkbox","value","row","props","cell","BlockDocumentActionMenu","BlockDocumentsDataTable","blockDocuments","blockDocumentsCount","onPaginationChange","pagination","rowSelection","setRowSelection","dialogState","handleConfirmDelete","useDeleteBlockDocumentConfirmationDialog","handlePaginationChange","useCallback","updater","newPagination","useReactTable","getCoreRowModel","Fragment","DataTable","DeleteConfirmationDialog","BlockTypesMultiSelect","selectedBlockTypesSlugs","onToggleBlockTypeSlug","onRemoveBlockTypeSlug","Suspense","BlockTypesMultiSelectImplementation","search","setSearch","useState","deferredSearch","useDeferredValue","blockTypes","useSuspenseQuery","buildListFilterBlockTypesQuery","selectedBlockTypes","useMemo","blockTypeSlug","blockType","filteredData","Combobox","ComboboxTrigger","TagBadge","ComboboxContent","ComboboxCommandInput","ComboboxCommandEmtpy","ComboboxCommandList","ComboboxCommandGroup","ComboboxCommandItem","BlocksRowCount","count","deleteConfirmationDialogState","selectedBlockIds","Button","Icon","pluralize","BlocksEmptyState","EmptyState","EmptyStateIcon","EmptyStateTitle","EmptyStateDescription","EmptyStateActions","DocsLink","BlocksPage","allCount","onSearch","blockTypeSlugsFilter","Breadcrumb","BreadcrumbItem","SearchInput","e","RouteComponent","usePageTitle","useSearch","blockTypeSlugs","onSetBlockTypeSlugs","useFilterByBlockTypes","usePagination","data","allBlockDocumentsCount","buildCountAllBlockDocumentsQuery","useQuery","buildListFilterBlockDocumentsQuery","sort","include_secrets","block_documents","like_","operator","is_anonymous","eq_","block_types","slug","any_","length","undefined","offset","pageIndex","pageSize","limit","handleRemoveBlockType","newValue","filter","blockId","handleToggleBlockType","includes","blockName","Route","navigate","useNavigate","to","prev","replace","onSetBlockTypes","page"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{j as e,L as x,r as d,t as g,s as p}from"./vendor-tanstack-BcZfOOfy.js";import{E as f,t as C,v as k,w as y,x as W,q as h,I as m,D as N,y as l,W as v,A as S,F as P,G as b,H as D,J as E,K as T,M as _,N as I,C as L,m as w,n as R,O as M,o as O,Q as A,T as z,U as $,V as F}from"./index-B8vo2Lrg.js";import{W as Q}from"./header-Bj_zBR-a.js";import{D as B,a as H,b as K,c as U,d as u}from"./dropdown-menu-D7Gwbd15.js";import{m as V}from"./vendor-date-wwuDAncJ.js";import"./vendor-react-Bce9NwRC.js";import"./vendor-radix-BTiKGWfR.js";import"./vendor-recharts-BvvJP9Po.js";import"./vendor-forms-ClCIacbh.js";const q=()=>e.jsxs(f,{children:[e.jsx(C,{id:"Cpu"}),e.jsx(k,{children:"Add a work pool to get started"}),e.jsx(y,{children:"Work pools allow you to prioritize and manage deployments and control the infrastructure they run on."}),e.jsxs(W,{children:[e.jsx(x,{to:"/work-pools/create",children:e.jsxs(h,{children:["Add Work Pool ",e.jsx(m,{id:"Plus",className:"size-4 ml-2"})]})}),e.jsx(N,{id:"work-pools-guide"})]})]}),J=({workPool:s,onDelete:n})=>{const a=r=>{navigator.clipboard.writeText(r),l.success("ID copied")};return e.jsxs(B,{children:[e.jsx(H,{asChild:!0,children:e.jsxs(h,{variant:"outline",className:"size-8 p-0",children:[e.jsx("span",{className:"sr-only",children:"Open menu"}),e.jsx(m,{id:"MoreVertical",className:"size-4"})]})}),e.jsxs(K,{align:"end",children:[e.jsx(U,{children:"Actions"}),e.jsx(u,{onClick:()=>a(s.id),children:"Copy ID"}),e.jsx(x,{to:"/work-pools/work-pool/$workPoolName/edit",params:{workPoolName:s.name},children:e.jsx(u,{children:"Edit"})}),e.jsx(u,{onClick:n,children:"Delete"})]})]})},Y=({workPoolName:s})=>e.jsx(v,{workPoolName:s}),G=({workPool:s})=>{const[n,a]=d.useState(s.status==="PAUSED"),{pauseWorkPool:r,isPending:c}=S(),{resumeWorkPool:i,isPending:t}=P(),o=d.useMemo(()=>c||t,[c,t]),j=()=>{n?i(s.name,{onSuccess:()=>{a(!1),l.success(`${s.name} resumed`)},onError:()=>{l.error(`Failed to resume ${s.name}`)}}):r(s.name,{onSuccess:()=>{a(!0),l.success(`${s.name} paused`)},onError:()=>{l.error(`Failed to pause ${s.name}`)}})};return e.jsx(b,{checked:!n,onCheckedChange:j,disabled:o,"aria-label":n?"Resume work pool":"Pause work pool"})},X={process:"Process",ecs:"ECS","azure-container-instance":"Azure Container Instance",docker:"Docker","cloud-run":"Cloud Run","cloud-run-v2":"Cloud Run v2","vertex-ai":"Vertex AI",kubernetes:"Kubernetes"},Z={process:"Cpu",ecs:"Cpu","azure-container-instance":"Cpu",docker:"Cpu","cloud-run":"Cpu","cloud-run-v2":"Cpu","vertex-ai":"Cpu",kubernetes:"Cpu"},ee=s=>X[s]??s,se=s=>Z[s]??"Cpu",te=({type:s})=>e.jsxs(D,{children:[e.jsx(m,{id:se(s)}),ee(s)]}),ae=({workPool:s})=>{const{deleteWorkPool:n}=E(),a=T({interval:1e3}),{data:r}=g(_(s.name)),c=()=>{n(s.name,{onSuccess:()=>{l.success(`${s.name} deleted`)},onError:o=>{l.error(`Failed to delete work pool: ${o instanceof Error?o.message:"Unknown error"}`)}})},i=r&&r.length>0?V(r.filter(o=>o.last_heartbeat_time).map(o=>new Date(o.last_heartbeat_time))):null,t=i?I(i,a):null;return e.jsxs(L,{className:"gap-2",children:[e.jsxs(w,{className:"flex flex-row items-center justify-between",children:[e.jsxs(R,{className:"flex items-center gap-2",children:[e.jsx(Y,{workPoolName:s.name}),s.status&&e.jsx(M,{status:s.status,showTooltip:!0})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(G,{workPool:s}),e.jsx(J,{workPool:s,onDelete:c})]})]}),e.jsxs(O,{className:"flex flex-col gap-1",children:[e.jsx("div",{className:"flex items-center gap-1",children:e.jsx(te,{type:s.type})}),e.jsxs("div",{className:"flex flex-wrap gap-x-8 gap-y-1 text-sm",children:[e.jsxs("div",{children:[e.jsx("span",{className:"font-medium text-muted-foreground",children:"Concurrency Limit"})," ",e.jsx("span",{className:"text-foreground",children:s.concurrency_limit?s.concurrency_limit:"Unlimited"})]}),t&&e.jsxs("div",{children:[e.jsx("span",{className:"font-medium text-muted-foreground",children:"Last Polled"})," ",e.jsx("span",{className:"text-foreground",children:t})]})]})]})]})};function pe(){const[s,n]=d.useState(""),{data:a=0}=p(A()),{data:r=[]}=p(z({limit:200,offset:0})),c=d.useMemo(()=>r.filter(t=>[t.name,t.description,t.type,JSON.stringify(t.base_job_template),t.id,t.default_queue_id,t.status].join(" ").toLowerCase().includes(s.toLowerCase())),[r,s]),i=t=>{n(t.target.value)};return e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsx(Q,{}),a<1?e.jsx(q,{}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"flex items-end justify-between",children:[e.jsxs("div",{className:"text-sm text-muted-foreground",children:[a," ",$(a,"work pool")]}),e.jsx("div",{className:"flex gap-2",children:e.jsx(F,{placeholder:"Search work pools...",value:s,onChange:i})})]}),e.jsx("div",{className:"flex flex-col gap-4",children:c.map(t=>e.jsx(ae,{workPool:t},t.id))})]})]})}export{pe as component};
2
+ //# sourceMappingURL=index-CEi3BlKI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-CEi3BlKI.js","sources":["../../src/components/work-pools/empty-state.tsx","../../src/components/work-pools/work-pool-card/components/work-pool-context-menu.tsx","../../src/components/work-pools/work-pool-card/components/work-pool-name.tsx","../../src/components/work-pools/work-pool-card/components/work-pool-pause-resume-toggle.tsx","../../src/components/work-pools/work-pool-card/components/work-pool-type-badge.tsx","../../src/components/work-pools/work-pool-card/work-pool-card.tsx","../../src/routes/work-pools/index.tsx?tsr-split=component"],"sourcesContent":["import { Link } from \"@tanstack/react-router\";\nimport { Button } from \"@/components/ui/button\";\nimport { DocsLink } from \"@/components/ui/docs-link\";\nimport {\n\tEmptyState,\n\tEmptyStateActions,\n\tEmptyStateDescription,\n\tEmptyStateIcon,\n\tEmptyStateTitle,\n} from \"@/components/ui/empty-state\";\nimport { Icon } from \"@/components/ui/icons\";\n\nexport const WorkPoolsEmptyState = () => (\n\t<EmptyState>\n\t\t<EmptyStateIcon id=\"Cpu\" />\n\t\t<EmptyStateTitle>Add a work pool to get started</EmptyStateTitle>\n\t\t<EmptyStateDescription>\n\t\t\tWork pools allow you to prioritize and manage deployments and control the\n\t\t\tinfrastructure they run on.\n\t\t</EmptyStateDescription>\n\t\t<EmptyStateActions>\n\t\t\t<Link to=\"/work-pools/create\">\n\t\t\t\t<Button>\n\t\t\t\t\tAdd Work Pool <Icon id=\"Plus\" className=\"size-4 ml-2\" />\n\t\t\t\t</Button>\n\t\t\t</Link>\n\t\t\t<DocsLink id=\"work-pools-guide\" />\n\t\t</EmptyStateActions>\n\t</EmptyState>\n);\n","import { Link } from \"@tanstack/react-router\";\nimport { toast } from \"sonner\";\nimport type { WorkPool } from \"@/api/work-pools\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n\tDropdownMenu,\n\tDropdownMenuContent,\n\tDropdownMenuItem,\n\tDropdownMenuLabel,\n\tDropdownMenuTrigger,\n} from \"@/components/ui/dropdown-menu\";\nimport { Icon } from \"@/components/ui/icons\";\n\nexport type WorkPoolContextMenuProps = {\n\tworkPool: WorkPool;\n\tonDelete: () => void;\n};\n\nexport const WorkPoolContextMenu = ({\n\tworkPool,\n\tonDelete,\n}: WorkPoolContextMenuProps) => {\n\tconst handleCopyId = (id: string) => {\n\t\tvoid navigator.clipboard.writeText(id);\n\t\ttoast.success(\"ID copied\");\n\t};\n\n\treturn (\n\t\t<DropdownMenu>\n\t\t\t<DropdownMenuTrigger asChild>\n\t\t\t\t<Button variant=\"outline\" className=\"size-8 p-0\">\n\t\t\t\t\t<span className=\"sr-only\">Open menu</span>\n\t\t\t\t\t<Icon id=\"MoreVertical\" className=\"size-4\" />\n\t\t\t\t</Button>\n\t\t\t</DropdownMenuTrigger>\n\t\t\t<DropdownMenuContent align=\"end\">\n\t\t\t\t<DropdownMenuLabel>Actions</DropdownMenuLabel>\n\t\t\t\t<DropdownMenuItem onClick={() => handleCopyId(workPool.id)}>\n\t\t\t\t\tCopy ID\n\t\t\t\t</DropdownMenuItem>\n\t\t\t\t<Link\n\t\t\t\t\tto=\"/work-pools/work-pool/$workPoolName/edit\"\n\t\t\t\t\tparams={{ workPoolName: workPool.name }}\n\t\t\t\t>\n\t\t\t\t\t<DropdownMenuItem>Edit</DropdownMenuItem>\n\t\t\t\t</Link>\n\t\t\t\t<DropdownMenuItem onClick={onDelete}>Delete</DropdownMenuItem>\n\t\t\t</DropdownMenuContent>\n\t\t</DropdownMenu>\n\t);\n};\n","import { WorkPoolIconText } from \"@/components/work-pools/work-pool-icon-text\";\n\ntype WorkPoolNameProps = {\n\tworkPoolName: string;\n};\n\nexport const WorkPoolName = ({ workPoolName }: WorkPoolNameProps) => {\n\treturn <WorkPoolIconText workPoolName={workPoolName} />;\n};\n","import { useMemo, useState } from \"react\";\nimport { toast } from \"sonner\";\nimport type { WorkPool } from \"@/api/work-pools\";\nimport { usePauseWorkPool, useResumeWorkPool } from \"@/api/work-pools\";\nimport { Switch } from \"@/components/ui/switch\";\nexport type WorkPoolPauseResumeToggleParams = {\n\tworkPool: WorkPool;\n};\n\nexport const WorkPoolPauseResumeToggle = ({\n\tworkPool,\n}: WorkPoolPauseResumeToggleParams) => {\n\tconst [isPaused, setIsPaused] = useState(workPool.status === \"PAUSED\");\n\n\tconst { pauseWorkPool, isPending: isPausing } = usePauseWorkPool();\n\tconst { resumeWorkPool, isPending: isResuming } = useResumeWorkPool();\n\n\tconst disabled = useMemo(() => {\n\t\treturn isPausing || isResuming;\n\t}, [isPausing, isResuming]);\n\n\tconst handleTogglePause = () => {\n\t\tif (isPaused) {\n\t\t\tresumeWorkPool(workPool.name, {\n\t\t\t\tonSuccess: () => {\n\t\t\t\t\tsetIsPaused(false);\n\t\t\t\t\ttoast.success(`${workPool.name} resumed`);\n\t\t\t\t},\n\t\t\t\tonError: () => {\n\t\t\t\t\ttoast.error(`Failed to resume ${workPool.name}`);\n\t\t\t\t},\n\t\t\t});\n\t\t} else {\n\t\t\tpauseWorkPool(workPool.name, {\n\t\t\t\tonSuccess: () => {\n\t\t\t\t\tsetIsPaused(true);\n\t\t\t\t\ttoast.success(`${workPool.name} paused`);\n\t\t\t\t},\n\t\t\t\tonError: () => {\n\t\t\t\t\ttoast.error(`Failed to pause ${workPool.name}`);\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t};\n\n\treturn (\n\t\t<Switch\n\t\t\tchecked={!isPaused}\n\t\t\tonCheckedChange={handleTogglePause}\n\t\t\tdisabled={disabled}\n\t\t\taria-label={isPaused ? \"Resume work pool\" : \"Pause work pool\"}\n\t\t/>\n\t);\n};\n","import type { WorkPool } from \"@/api/work-pools\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { Icon, type IconId } from \"@/components/ui/icons\";\n\ntype WorkPoolTypeBadgeProps = {\n\ttype: WorkPool[\"type\"];\n};\n\nconst WORK_POOL_TYPE_LABELS: Record<WorkPool[\"type\"], string> = {\n\tprocess: \"Process\",\n\tecs: \"ECS\",\n\t\"azure-container-instance\": \"Azure Container Instance\",\n\tdocker: \"Docker\",\n\t\"cloud-run\": \"Cloud Run\",\n\t\"cloud-run-v2\": \"Cloud Run v2\",\n\t\"vertex-ai\": \"Vertex AI\",\n\tkubernetes: \"Kubernetes\",\n} as const;\n\nconst WORK_POOL_TYPE_ICONS: Record<WorkPool[\"type\"], IconId> = {\n\tprocess: \"Cpu\",\n\tecs: \"Cpu\",\n\t\"azure-container-instance\": \"Cpu\",\n\tdocker: \"Cpu\",\n\t\"cloud-run\": \"Cpu\",\n\t\"cloud-run-v2\": \"Cpu\",\n\t\"vertex-ai\": \"Cpu\",\n\tkubernetes: \"Cpu\",\n} as const;\n\nconst getWorkPoolTypeLabel = (type: WorkPool[\"type\"]) => {\n\treturn WORK_POOL_TYPE_LABELS[type] ?? type;\n};\n\nconst getWorkPoolTypeIcon = (type: WorkPool[\"type\"]) => {\n\treturn WORK_POOL_TYPE_ICONS[type] ?? \"Cpu\";\n};\n\nexport const WorkPoolTypeBadge = ({ type }: WorkPoolTypeBadgeProps) => {\n\treturn (\n\t\t<Badge>\n\t\t\t<Icon id={getWorkPoolTypeIcon(type)} />\n\t\t\t{getWorkPoolTypeLabel(type)}\n\t\t</Badge>\n\t);\n};\n","import { useQuery } from \"@tanstack/react-query\";\nimport { max } from \"date-fns\";\nimport { toast } from \"sonner\";\nimport type { WorkPool } from \"@/api/work-pools\";\nimport {\n\tbuildListWorkPoolWorkersQuery,\n\tuseDeleteWorkPool,\n} from \"@/api/work-pools\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"@/components/ui/card\";\nimport { WorkPoolStatusIcon } from \"@/components/work-pools/work-pool-status-icon\";\nimport { useNow } from \"@/hooks/use-now\";\nimport { formatDateTimeRelative } from \"@/utils\";\nimport { WorkPoolContextMenu } from \"./components/work-pool-context-menu\";\nimport { WorkPoolName } from \"./components/work-pool-name\";\nimport { WorkPoolPauseResumeToggle } from \"./components/work-pool-pause-resume-toggle\";\nimport { WorkPoolTypeBadge } from \"./components/work-pool-type-badge\";\n\ntype WorkPoolCardProps = {\n\tworkPool: WorkPool;\n};\n\nexport const WorkPoolCard = ({ workPool }: WorkPoolCardProps) => {\n\tconst { deleteWorkPool } = useDeleteWorkPool();\n\tconst now = useNow({ interval: 1000 });\n\tconst { data: workers } = useQuery(\n\t\tbuildListWorkPoolWorkersQuery(workPool.name),\n\t);\n\n\tconst handleDelete = () => {\n\t\tdeleteWorkPool(workPool.name, {\n\t\t\tonSuccess: () => {\n\t\t\t\ttoast.success(`${workPool.name} deleted`);\n\t\t\t},\n\t\t\tonError: (error) => {\n\t\t\t\ttoast.error(\n\t\t\t\t\t`Failed to delete work pool: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n\t\t\t\t);\n\t\t\t},\n\t\t});\n\t};\n\n\tconst lastWorkerHeartbeat =\n\t\tworkers && workers.length > 0\n\t\t\t? max(\n\t\t\t\t\tworkers\n\t\t\t\t\t\t.filter((worker) => worker.last_heartbeat_time)\n\t\t\t\t\t\t.map((worker) => new Date(worker.last_heartbeat_time as string)),\n\t\t\t\t)\n\t\t\t: null;\n\n\tconst lastPolled = lastWorkerHeartbeat\n\t\t? formatDateTimeRelative(lastWorkerHeartbeat, now)\n\t\t: null;\n\n\treturn (\n\t\t<Card className=\"gap-2\">\n\t\t\t<CardHeader className=\"flex flex-row items-center justify-between\">\n\t\t\t\t<CardTitle className=\"flex items-center gap-2\">\n\t\t\t\t\t<WorkPoolName workPoolName={workPool.name} />\n\t\t\t\t\t{workPool.status && (\n\t\t\t\t\t\t<WorkPoolStatusIcon status={workPool.status} showTooltip />\n\t\t\t\t\t)}\n\t\t\t\t</CardTitle>\n\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t<WorkPoolPauseResumeToggle workPool={workPool} />\n\t\t\t\t\t<WorkPoolContextMenu workPool={workPool} onDelete={handleDelete} />\n\t\t\t\t</div>\n\t\t\t</CardHeader>\n\t\t\t<CardContent className=\"flex flex-col gap-1\">\n\t\t\t\t<div className=\"flex items-center gap-1\">\n\t\t\t\t\t<WorkPoolTypeBadge type={workPool.type} />\n\t\t\t\t</div>\n\t\t\t\t<div className=\"flex flex-wrap gap-x-8 gap-y-1 text-sm\">\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<span className=\"font-medium text-muted-foreground\">\n\t\t\t\t\t\t\tConcurrency Limit\n\t\t\t\t\t\t</span>{\" \"}\n\t\t\t\t\t\t<span className=\"text-foreground\">\n\t\t\t\t\t\t\t{workPool.concurrency_limit\n\t\t\t\t\t\t\t\t? workPool.concurrency_limit\n\t\t\t\t\t\t\t\t: \"Unlimited\"}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</div>\n\t\t\t\t\t{lastPolled && (\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<span className=\"font-medium text-muted-foreground\">\n\t\t\t\t\t\t\t\tLast Polled\n\t\t\t\t\t\t\t</span>{\" \"}\n\t\t\t\t\t\t\t<span className=\"text-foreground\">{lastPolled}</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</CardContent>\n\t\t</Card>\n\t);\n};\n","import { useSuspenseQuery } from \"@tanstack/react-query\";\nimport type { ErrorComponentProps } from \"@tanstack/react-router\";\nimport { createFileRoute } from \"@tanstack/react-router\";\nimport { useMemo, useState } from \"react\";\nimport { categorizeError } from \"@/api/error-utils\";\nimport {\n\tbuildCountWorkPoolsQuery,\n\tbuildFilterWorkPoolsQuery,\n} from \"@/api/work-pools\";\nimport { SearchInput } from \"@/components/ui/input\";\nimport { RouteErrorState } from \"@/components/ui/route-error-state\";\nimport { WorkPoolsEmptyState } from \"@/components/work-pools/empty-state\";\nimport { WorkPoolsPageHeader } from \"@/components/work-pools/header\";\nimport { WorkPoolCard } from \"@/components/work-pools/work-pool-card/work-pool-card\";\nimport { pluralize } from \"@/utils\";\n\nfunction WorkPoolsErrorComponent({ error, reset }: ErrorComponentProps) {\n\tconst serverError = categorizeError(error, \"Failed to load work pools\");\n\n\t// Only handle API errors (server-error, client-error) at route level\n\t// Let network errors and unknown errors bubble up to root error component\n\tif (\n\t\tserverError.type !== \"server-error\" &&\n\t\tserverError.type !== \"client-error\"\n\t) {\n\t\tthrow error;\n\t}\n\n\treturn (\n\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t<WorkPoolsPageHeader />\n\t\t\t<RouteErrorState error={serverError} onRetry={reset} />\n\t\t</div>\n\t);\n}\n\nexport const Route = createFileRoute(\"/work-pools/\")({\n\tcomponent: RouteComponent,\n\terrorComponent: WorkPoolsErrorComponent,\n\tloader: ({ context }) => {\n\t\tvoid context.queryClient.ensureQueryData(buildCountWorkPoolsQuery());\n\t\tvoid context.queryClient.ensureQueryData(\n\t\t\tbuildFilterWorkPoolsQuery({\n\t\t\t\tlimit: 200,\n\t\t\t\toffset: 0,\n\t\t\t}),\n\t\t);\n\t},\n\twrapInSuspense: true,\n});\n\nfunction RouteComponent() {\n\tconst [searchTerm, setSearchTerm] = useState(\"\");\n\n\tconst { data: workPoolCount = 0 } = useSuspenseQuery(\n\t\tbuildCountWorkPoolsQuery(),\n\t);\n\n\tconst { data: workPools = [] } = useSuspenseQuery(\n\t\tbuildFilterWorkPoolsQuery({\n\t\t\tlimit: 200,\n\t\t\toffset: 0,\n\t\t}),\n\t);\n\n\tconst filteredWorkPools = useMemo(() => {\n\t\treturn workPools.filter((workPool) =>\n\t\t\t[\n\t\t\t\tworkPool.name,\n\t\t\t\tworkPool.description,\n\t\t\t\tworkPool.type,\n\t\t\t\tJSON.stringify(workPool.base_job_template),\n\t\t\t\tworkPool.id,\n\t\t\t\tworkPool.default_queue_id,\n\t\t\t\tworkPool.status,\n\t\t\t]\n\t\t\t\t.join(\" \")\n\t\t\t\t.toLowerCase()\n\t\t\t\t.includes(searchTerm.toLowerCase()),\n\t\t);\n\t}, [workPools, searchTerm]);\n\n\tconst handleSearchChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n\t\tsetSearchTerm(event.target.value);\n\t};\n\n\treturn (\n\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t<WorkPoolsPageHeader />\n\t\t\t{workPoolCount < 1 ? (\n\t\t\t\t<WorkPoolsEmptyState />\n\t\t\t) : (\n\t\t\t\t<>\n\t\t\t\t\t<div className=\"flex items-end justify-between\">\n\t\t\t\t\t\t<div className=\"text-sm text-muted-foreground\">\n\t\t\t\t\t\t\t{workPoolCount} {pluralize(workPoolCount, \"work pool\")}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div className=\"flex gap-2\">\n\t\t\t\t\t\t\t<SearchInput\n\t\t\t\t\t\t\t\tplaceholder=\"Search work pools...\"\n\t\t\t\t\t\t\t\tvalue={searchTerm}\n\t\t\t\t\t\t\t\tonChange={handleSearchChange}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t\t\t\t{filteredWorkPools.map((workPool) => (\n\t\t\t\t\t\t\t<WorkPoolCard key={workPool.id} workPool={workPool} />\n\t\t\t\t\t\t))}\n\t\t\t\t\t</div>\n\t\t\t\t</>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n"],"names":["WorkPoolsEmptyState","jsxs","EmptyState","jsx","EmptyStateIcon","EmptyStateTitle","EmptyStateDescription","EmptyStateActions","Link","Button","Icon","DocsLink","WorkPoolContextMenu","workPool","onDelete","handleCopyId","id","toast","DropdownMenu","DropdownMenuTrigger","DropdownMenuContent","DropdownMenuLabel","DropdownMenuItem","WorkPoolName","workPoolName","WorkPoolIconText","WorkPoolPauseResumeToggle","isPaused","setIsPaused","useState","pauseWorkPool","isPausing","usePauseWorkPool","resumeWorkPool","isResuming","useResumeWorkPool","disabled","useMemo","handleTogglePause","Switch","WORK_POOL_TYPE_LABELS","WORK_POOL_TYPE_ICONS","getWorkPoolTypeLabel","type","getWorkPoolTypeIcon","WorkPoolTypeBadge","Badge","WorkPoolCard","deleteWorkPool","useDeleteWorkPool","now","useNow","workers","useQuery","buildListWorkPoolWorkersQuery","handleDelete","error","lastWorkerHeartbeat","max","worker","lastPolled","formatDateTimeRelative","Card","CardHeader","CardTitle","WorkPoolStatusIcon","CardContent","RouteComponent","searchTerm","setSearchTerm","data","workPoolCount","useSuspenseQuery","buildCountWorkPoolsQuery","workPools","buildFilterWorkPoolsQuery","limit","offset","filteredWorkPools","filter","name","description","JSON","stringify","base_job_template","default_queue_id","status","join","toLowerCase","includes","handleSearchChange","event","target","value","WorkPoolsPageHeader","Fragment","pluralize","SearchInput","map"],"mappings":"8lBAYO,MAAMA,EAAsB,IAClCC,EAAAA,KAACC,EAAA,CACA,SAAA,CAAAC,EAAAA,IAACC,EAAA,CAAe,GAAG,KAAA,CAAM,EACzBD,EAAAA,IAACE,GAAgB,SAAA,gCAAA,CAA8B,EAC/CF,EAAAA,IAACG,GAAsB,SAAA,uGAAA,CAGvB,SACCC,EAAA,CACA,SAAA,CAAAJ,MAACK,EAAA,CAAK,GAAG,qBACR,SAAAP,EAAAA,KAACQ,EAAA,CAAO,SAAA,CAAA,iBACON,EAAAA,IAACO,EAAA,CAAK,GAAG,OAAO,UAAU,aAAA,CAAc,CAAA,CAAA,CACvD,CAAA,CACD,EACAP,EAAAA,IAACQ,EAAA,CAAS,GAAG,kBAAA,CAAmB,CAAA,CAAA,CACjC,CAAA,EACD,ECVYC,EAAsB,CAAC,CACnC,SAAAC,EACA,SAAAC,CACD,IAAgC,CAC/B,MAAMC,EAAgBC,GAAe,CAC/B,UAAU,UAAU,UAAUA,CAAE,EACrCC,EAAM,QAAQ,WAAW,CAC1B,EAEA,cACEC,EAAA,CACA,SAAA,CAAAf,EAAAA,IAACgB,EAAA,CAAoB,QAAO,GAC3B,SAAAlB,EAAAA,KAACQ,GAAO,QAAQ,UAAU,UAAU,aACnC,SAAA,CAAAN,EAAAA,IAAC,OAAA,CAAK,UAAU,UAAU,SAAA,YAAS,EACnCA,EAAAA,IAACO,EAAA,CAAK,GAAG,eAAe,UAAU,QAAA,CAAS,CAAA,CAAA,CAC5C,CAAA,CACD,EACAT,EAAAA,KAACmB,EAAA,CAAoB,MAAM,MAC1B,SAAA,CAAAjB,EAAAA,IAACkB,GAAkB,SAAA,SAAA,CAAO,EAC1BlB,MAACmB,GAAiB,QAAS,IAAMP,EAAaF,EAAS,EAAE,EAAG,SAAA,UAE5D,EACAV,EAAAA,IAACK,EAAA,CACA,GAAG,2CACH,OAAQ,CAAE,aAAcK,EAAS,IAAA,EAEjC,SAAAV,EAAAA,IAACmB,GAAiB,SAAA,MAAA,CAAI,CAAA,CAAA,EAEvBnB,EAAAA,IAACmB,EAAA,CAAiB,QAASR,EAAU,SAAA,QAAA,CAAM,CAAA,CAAA,CAC5C,CAAA,EACD,CAEF,EC5CaS,EAAe,CAAC,CAAE,aAAAC,KACvBrB,MAACsB,GAAiB,aAAAD,EAA4B,ECEzCE,EAA4B,CAAC,CACzC,SAAAb,CACD,IAAuC,CACtC,KAAM,CAACc,EAAUC,CAAW,EAAIC,EAAAA,SAAShB,EAAS,SAAW,QAAQ,EAE/D,CAAE,cAAAiB,EAAe,UAAWC,CAAA,EAAcC,EAAA,EAC1C,CAAE,eAAAC,EAAgB,UAAWC,CAAA,EAAeC,EAAA,EAE5CC,EAAWC,EAAAA,QAAQ,IACjBN,GAAaG,EAClB,CAACH,EAAWG,CAAU,CAAC,EAEpBI,EAAoB,IAAM,CAC3BX,EACHM,EAAepB,EAAS,KAAM,CAC7B,UAAW,IAAM,CAChBe,EAAY,EAAK,EACjBX,EAAM,QAAQ,GAAGJ,EAAS,IAAI,UAAU,CACzC,EACA,QAAS,IAAM,CACdI,EAAM,MAAM,oBAAoBJ,EAAS,IAAI,EAAE,CAChD,CAAA,CACA,EAEDiB,EAAcjB,EAAS,KAAM,CAC5B,UAAW,IAAM,CAChBe,EAAY,EAAI,EAChBX,EAAM,QAAQ,GAAGJ,EAAS,IAAI,SAAS,CACxC,EACA,QAAS,IAAM,CACdI,EAAM,MAAM,mBAAmBJ,EAAS,IAAI,EAAE,CAC/C,CAAA,CACA,CAEH,EAEA,OACCV,EAAAA,IAACoC,EAAA,CACA,QAAS,CAACZ,EACV,gBAAiBW,EACjB,SAAAF,EACA,aAAYT,EAAW,mBAAqB,iBAAA,CAAA,CAG/C,EC7CMa,EAA0D,CAC/D,QAAS,UACT,IAAK,MACL,2BAA4B,2BAC5B,OAAQ,SACR,YAAa,YACb,eAAgB,eAChB,YAAa,YACb,WAAY,YACb,EAEMC,EAAyD,CAC9D,QAAS,MACT,IAAK,MACL,2BAA4B,MAC5B,OAAQ,MACR,YAAa,MACb,eAAgB,MAChB,YAAa,MACb,WAAY,KACb,EAEMC,GAAwBC,GACtBH,EAAsBG,CAAI,GAAKA,EAGjCC,GAAuBD,GACrBF,EAAqBE,CAAI,GAAK,MAGzBE,GAAoB,CAAC,CAAE,KAAAF,YAEjCG,EAAA,CACA,SAAA,CAAA3C,EAAAA,IAACO,EAAA,CAAK,GAAIkC,GAAoBD,CAAI,CAAA,CAAG,EACpCD,GAAqBC,CAAI,CAAA,EAC3B,ECtBWI,GAAe,CAAC,CAAE,SAAAlC,KAAkC,CAChE,KAAM,CAAE,eAAAmC,CAAA,EAAmBC,EAAA,EACrBC,EAAMC,EAAO,CAAE,SAAU,IAAM,EAC/B,CAAE,KAAMC,CAAA,EAAYC,EACzBC,EAA8BzC,EAAS,IAAI,CAAA,EAGtC0C,EAAe,IAAM,CAC1BP,EAAenC,EAAS,KAAM,CAC7B,UAAW,IAAM,CAChBI,EAAM,QAAQ,GAAGJ,EAAS,IAAI,UAAU,CACzC,EACA,QAAU2C,GAAU,CACnBvC,EAAM,MACL,+BAA+BuC,aAAiB,MAAQA,EAAM,QAAU,eAAe,EAAA,CAEzF,CAAA,CACA,CACF,EAEMC,EACLL,GAAWA,EAAQ,OAAS,EACzBM,EACAN,EACE,OAAQO,GAAWA,EAAO,mBAAmB,EAC7C,IAAKA,GAAW,IAAI,KAAKA,EAAO,mBAA6B,CAAC,CAAA,EAEhE,KAEEC,EAAaH,EAChBI,EAAuBJ,EAAqBP,CAAG,EAC/C,KAEH,OACCjD,EAAAA,KAAC6D,EAAA,CAAK,UAAU,QACf,SAAA,CAAA7D,EAAAA,KAAC8D,EAAA,CAAW,UAAU,6CACrB,SAAA,CAAA9D,EAAAA,KAAC+D,EAAA,CAAU,UAAU,0BACpB,SAAA,CAAA7D,EAAAA,IAACoB,EAAA,CAAa,aAAcV,EAAS,IAAA,CAAM,EAC1CA,EAAS,QACTV,EAAAA,IAAC8D,EAAA,CAAmB,OAAQpD,EAAS,OAAQ,YAAW,EAAA,CAAC,CAAA,EAE3D,EACAZ,EAAAA,KAAC,MAAA,CAAI,UAAU,0BACd,SAAA,CAAAE,MAACuB,GAA0B,SAAAb,EAAoB,EAC/CV,EAAAA,IAACS,EAAA,CAAoB,SAAAC,EAAoB,SAAU0C,CAAA,CAAc,CAAA,CAAA,CAClE,CAAA,EACD,EACAtD,EAAAA,KAACiE,EAAA,CAAY,UAAU,sBACtB,SAAA,CAAA/D,EAAAA,IAAC,MAAA,CAAI,UAAU,0BACd,SAAAA,EAAAA,IAAC0C,IAAkB,KAAMhC,EAAS,KAAM,CAAA,CACzC,EACAZ,EAAAA,KAAC,MAAA,CAAI,UAAU,yCACd,SAAA,CAAAA,OAAC,MAAA,CACA,SAAA,CAAAE,EAAAA,IAAC,OAAA,CAAK,UAAU,oCAAoC,SAAA,oBAEpD,EAAQ,IACRA,EAAAA,IAAC,QAAK,UAAU,kBACd,WAAS,kBACPU,EAAS,kBACT,WAAA,CACJ,CAAA,EACD,EACC+C,UACC,MAAA,CACA,SAAA,CAAAzD,EAAAA,IAAC,OAAA,CAAK,UAAU,oCAAoC,SAAA,cAEpD,EAAQ,IACRA,EAAAA,IAAC,OAAA,CAAK,UAAU,kBAAmB,SAAAyD,CAAA,CAAW,CAAA,CAAA,CAC/C,CAAA,CAAA,CAEF,CAAA,CAAA,CACD,CAAA,EACD,CAEF,EC5CA,SAASO,IAAiB,CACzB,KAAM,CAACC,EAAYC,CAAa,EAAIxC,EAAAA,SAAS,EAAE,EAEzC,CAAEyC,KAAMC,EAAgB,CAAA,EAAMC,EACnCC,GACD,EAEM,CAAEH,KAAMI,EAAY,CAAA,CAAA,EAAOF,EAChCG,EAA0B,CACzBC,MAAO,IACPC,OAAQ,CAAA,CACR,CACF,EAEMC,EAAoBzC,EAAAA,QAAQ,IAC1BqC,EAAUK,OAAQlE,GACxB,CACCA,EAASmE,KACTnE,EAASoE,YACTpE,EAAS8B,KACTuC,KAAKC,UAAUtE,EAASuE,iBAAiB,EACzCvE,EAASG,GACTH,EAASwE,iBACTxE,EAASyE,MAAM,EAEdC,KAAK,GAAG,EACRC,YAAAA,EACAC,SAASrB,EAAWoB,YAAAA,CAAa,CACpC,EACE,CAACd,EAAWN,CAAU,CAAC,EAEpBsB,EAAsBC,GAA+C,CAC1EtB,EAAcsB,EAAMC,OAAOC,KAAK,CACjC,EAEA,OACC5F,EAAAA,KAAC,MAAA,CAAI,UAAU,sBACd,SAAA,CAAAE,EAAAA,IAAC2F,EAAA,EAAmB,EACnBvB,EAAgB,EAChBpE,EAAAA,IAACH,EAAA,CAAA,GAEDC,EAAAA,KAAA8F,WAAA,CACC,SAAA,CAAA9F,EAAAA,KAAC,MAAA,CAAI,UAAU,iCACd,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,gCACbsE,SAAAA,CAAAA,EAAc,IAAEyB,EAAUzB,EAAe,WAAW,CAAA,EACtD,EACApE,EAAAA,IAAC,MAAA,CAAI,UAAU,aACd,SAAAA,EAAAA,IAAC8F,EAAA,CACA,YAAY,uBACZ,MAAO7B,EACP,SAAUsB,CAAAA,CAAmB,CAAA,CAE/B,CAAA,EACD,EACAvF,EAAAA,IAAC,MAAA,CAAI,UAAU,sBACb2E,SAAAA,EAAkBoB,IAAKrF,GACvBV,EAAAA,IAAC4C,GAAA,CAA+B,SAAAlC,CAAA,EAAbA,EAASG,EAAuB,CACnD,CAAA,CACF,CAAA,CAAA,CACD,CAAA,EAEF,CAEF"}
@@ -1,2 +1,2 @@
1
- import{j as o}from"./vendor-tanstack-BcZfOOfy.js";import{s}from"./index-m48E4KcG.js";import{R as p}from"./route-error-state-DnBaNT2T.js";import{o as n,e as l,a as m,n as e,s as a}from"./vendor-forms-ClCIacbh.js";import"./vendor-react-Bce9NwRC.js";import"./vendor-radix-BTiKGWfR.js";import"./vendor-recharts-BAN776s_.js";import"./vendor-date-wwuDAncJ.js";n({name:a().optional(),page:e().int().positive().optional().default(1).catch(1),limit:e().int().positive().max(100).optional().default(10).catch(10),tags:m(a()).optional(),sort:l(["CREATED_DESC","UPDATED_DESC","NAME_ASC","NAME_DESC"]).optional().default("NAME_ASC")}).optional().default({});function h({error:t,reset:i}){const r=s(t,"Failed to load flows");if(r.type!=="server-error"&&r.type!=="client-error")throw t;return o.jsxs("div",{className:"flex flex-col gap-4",children:[o.jsx("div",{children:o.jsx("h1",{className:"text-2xl font-semibold",children:"Flows"})}),o.jsx(p,{error:r,onRetry:i})]})}export{h as errorComponent};
2
- //# sourceMappingURL=index-BaWDC4da.js.map
1
+ import{j as o}from"./vendor-tanstack-BcZfOOfy.js";import{s}from"./index-B8vo2Lrg.js";import{R as p}from"./route-error-state-BFBpiIhD.js";import{o as n,e as l,a as m,n as e,s as a}from"./vendor-forms-ClCIacbh.js";import"./vendor-react-Bce9NwRC.js";import"./vendor-radix-BTiKGWfR.js";import"./vendor-recharts-BvvJP9Po.js";import"./vendor-date-wwuDAncJ.js";n({name:a().optional(),page:e().int().positive().optional().default(1).catch(1),limit:e().int().positive().max(100).optional().default(10).catch(10),tags:m(a()).optional(),sort:l(["CREATED_DESC","UPDATED_DESC","NAME_ASC","NAME_DESC"]).optional().default("NAME_ASC")}).optional().default({});function h({error:t,reset:i}){const r=s(t,"Failed to load flows");if(r.type!=="server-error"&&r.type!=="client-error")throw t;return o.jsxs("div",{className:"flex flex-col gap-4",children:[o.jsx("div",{children:o.jsx("h1",{className:"text-2xl font-semibold",children:"Flows"})}),o.jsx(p,{error:r,onRetry:i})]})}export{h as errorComponent};
2
+ //# sourceMappingURL=index-CS-zxv7Z.js.map