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.
- prefect/__init__.py +20 -0
- prefect/_build_info.py +3 -3
- prefect/_internal/analytics/__init__.py +80 -0
- prefect/_internal/analytics/_config.py +2 -0
- prefect/_internal/analytics/ci_detection.py +39 -0
- prefect/_internal/analytics/client.py +132 -0
- prefect/_internal/analytics/device_id.py +55 -0
- prefect/_internal/analytics/emit.py +90 -0
- prefect/_internal/analytics/enabled.py +33 -0
- prefect/_internal/analytics/events.py +14 -0
- prefect/_internal/analytics/milestones.py +177 -0
- prefect/_internal/analytics/notice.py +60 -0
- prefect/_internal/analytics/service.py +238 -0
- prefect/analytics/__init__.py +67 -0
- prefect/deployments/runner.py +20 -0
- prefect/flow_engine.py +16 -0
- prefect/flows.py +8 -0
- prefect/logging/formatters.py +24 -1
- prefect/server/ui-v2/assets/{artifact-card-BBzQR-Cj.js → artifact-card-BclosG8t.js} +2 -2
- prefect/server/ui-v2/assets/{artifact-card-BBzQR-Cj.js.map → artifact-card-BclosG8t.js.map} +1 -1
- prefect/server/ui-v2/assets/artifact._id-C0r4BJr2.js +2 -0
- prefect/server/ui-v2/assets/artifact._id-C0r4BJr2.js.map +1 -0
- prefect/server/ui-v2/assets/{automation-wizard-EYSfXlQ7.js → automation-wizard-Bmgt6nn8.js} +2 -2
- prefect/server/ui-v2/assets/{automation-wizard-EYSfXlQ7.js.map → automation-wizard-Bmgt6nn8.js.map} +1 -1
- prefect/server/ui-v2/assets/automation._id-Ccke3KJz.js +2 -0
- prefect/server/ui-v2/assets/{automation._id-Dn7jABys.js.map → automation._id-Ccke3KJz.js.map} +1 -1
- prefect/server/ui-v2/assets/{automation_._id.edit-COrqswD3.js → automation_._id.edit-BlKPUTVf.js} +2 -2
- prefect/server/ui-v2/assets/{automation_._id.edit-COrqswD3.js.map → automation_._id.edit-BlKPUTVf.js.map} +1 -1
- prefect/server/ui-v2/assets/{automations-header-DN_dmMXW.js → automations-header-Df2zw3SC.js} +2 -2
- prefect/server/ui-v2/assets/{automations-header-DN_dmMXW.js.map → automations-header-Df2zw3SC.js.map} +1 -1
- prefect/server/ui-v2/assets/{base-job-template-form-section-De2ACYbw.js → base-job-template-form-section-oZD6U-RW.js} +2 -2
- prefect/server/ui-v2/assets/{base-job-template-form-section-De2ACYbw.js.map → base-job-template-form-section-oZD6U-RW.js.map} +1 -1
- prefect/server/ui-v2/assets/{block-type-details-Cklc7TkK.js → block-type-details-CYrdaLot.js} +2 -2
- prefect/server/ui-v2/assets/{block-type-details-Cklc7TkK.js.map → block-type-details-CYrdaLot.js.map} +1 -1
- prefect/server/ui-v2/assets/block-type-logo-CyAWq7mC.js +2 -0
- prefect/server/ui-v2/assets/block-type-logo-CyAWq7mC.js.map +1 -0
- prefect/server/ui-v2/assets/{block._id-tuz1Bcj2.js → block._id-CBgHrpTP.js} +2 -2
- prefect/server/ui-v2/assets/{block._id-tuz1Bcj2.js.map → block._id-CBgHrpTP.js.map} +1 -1
- prefect/server/ui-v2/assets/{block_._id.edit-CFEYhF5R.js → block_._id.edit-CW-kdi4O.js} +2 -2
- prefect/server/ui-v2/assets/{block_._id.edit-CFEYhF5R.js.map → block_._id.edit-CW-kdi4O.js.map} +1 -1
- prefect/server/ui-v2/assets/{catalog-CCPRo7nY.js → catalog-Brh0kn1I.js} +2 -2
- prefect/server/ui-v2/assets/{catalog-CCPRo7nY.js.map → catalog-Brh0kn1I.js.map} +1 -1
- prefect/server/ui-v2/assets/catalog_._slug-MCgzguIZ.js +2 -0
- prefect/server/ui-v2/assets/{catalog_._slug-Bl2J2oI3.js.map → catalog_._slug-MCgzguIZ.js.map} +1 -1
- prefect/server/ui-v2/assets/{catalog_._slug_.create-9UD_SxDN.js → catalog_._slug_.create-DBaeHi9Q.js} +2 -2
- prefect/server/ui-v2/assets/{catalog_._slug_.create-9UD_SxDN.js.map → catalog_._slug_.create-DBaeHi9Q.js.map} +1 -1
- prefect/server/ui-v2/assets/{collapsible-BVQTBG_U.js → collapsible-B_NJS0uJ.js} +2 -2
- prefect/server/ui-v2/assets/{collapsible-BVQTBG_U.js.map → collapsible-B_NJS0uJ.js.map} +1 -1
- prefect/server/ui-v2/assets/{concurrency-limit._id-CsgRxA0a.js → concurrency-limit._id-qzNUQzQa.js} +2 -2
- prefect/server/ui-v2/assets/{concurrency-limit._id-CsgRxA0a.js.map → concurrency-limit._id-qzNUQzQa.js.map} +1 -1
- prefect/server/ui-v2/assets/create-BwXG6EIb.js +2 -0
- prefect/server/ui-v2/assets/{create-D--LHaji.js.map → create-BwXG6EIb.js.map} +1 -1
- prefect/server/ui-v2/assets/{create-BycfZHGQ.js → create-MoiIE9Ms.js} +2 -2
- prefect/server/ui-v2/assets/{create-BycfZHGQ.js.map → create-MoiIE9Ms.js.map} +1 -1
- prefect/server/ui-v2/assets/data-table-CPkppyg6.js +2 -0
- prefect/server/ui-v2/assets/data-table-CPkppyg6.js.map +1 -0
- prefect/server/ui-v2/assets/delete-confirmation-dialog-CwDK_2QS.js +2 -0
- prefect/server/ui-v2/assets/{delete-confirmation-dialog-DHkm2p8m.js.map → delete-confirmation-dialog-CwDK_2QS.js.map} +1 -1
- prefect/server/ui-v2/assets/{deployment-action-header-D5GOooPm.js → deployment-action-header-Vp9YsCJO.js} +2 -2
- prefect/server/ui-v2/assets/{deployment-action-header-D5GOooPm.js.map → deployment-action-header-Vp9YsCJO.js.map} +1 -1
- prefect/server/ui-v2/assets/{deployment-form-wfg6HeAJ.js → deployment-form-CJcg_6DJ.js} +3 -3
- prefect/server/ui-v2/assets/{deployment-form-wfg6HeAJ.js.map → deployment-form-CJcg_6DJ.js.map} +1 -1
- prefect/server/ui-v2/assets/{deployment-links-6iugOgDh.js → deployment-links-CIkJIuHh.js} +2 -2
- prefect/server/ui-v2/assets/{deployment-links-6iugOgDh.js.map → deployment-links-CIkJIuHh.js.map} +1 -1
- prefect/server/ui-v2/assets/deployment._id-C6XrGMp_.js +2 -0
- prefect/server/ui-v2/assets/{deployment._id-Ci9zge5n.js.map → deployment._id-C6XrGMp_.js.map} +1 -1
- prefect/server/ui-v2/assets/{deployment._id-whsGcHdu.js → deployment._id-CWgTYmTG.js} +2 -2
- prefect/server/ui-v2/assets/{deployment._id-whsGcHdu.js.map → deployment._id-CWgTYmTG.js.map} +1 -1
- prefect/server/ui-v2/assets/deployment_._id.duplicate-Bg0s0ZJn.js +2 -0
- prefect/server/ui-v2/assets/{deployment_._id.duplicate-D9ZWkh8H.js.map → deployment_._id.duplicate-Bg0s0ZJn.js.map} +1 -1
- prefect/server/ui-v2/assets/deployment_._id.edit-CnoB0UeG.js +2 -0
- prefect/server/ui-v2/assets/{deployment_._id.edit-CS7sObzC.js.map → deployment_._id.edit-CnoB0UeG.js.map} +1 -1
- prefect/server/ui-v2/assets/{deployment_._id.run-g7SZuDFi.js → deployment_._id.run-BqPK6rTB.js} +2 -2
- prefect/server/ui-v2/assets/{deployment_._id.run-g7SZuDFi.js.map → deployment_._id.run-BqPK6rTB.js.map} +1 -1
- prefect/server/ui-v2/assets/{dropdown-menu-0atiOSFo.js → dropdown-menu-D7Gwbd15.js} +2 -2
- prefect/server/ui-v2/assets/{dropdown-menu-0atiOSFo.js.map → dropdown-menu-D7Gwbd15.js.map} +1 -1
- prefect/server/ui-v2/assets/{event-resource-display-DHiAb1Up.js → event-resource-display-CDRgVKd4.js} +2 -2
- prefect/server/ui-v2/assets/{event-resource-display-DHiAb1Up.js.map → event-resource-display-CDRgVKd4.js.map} +1 -1
- prefect/server/ui-v2/assets/event._eventDate._eventId-C73GMDkK.js +2 -0
- prefect/server/ui-v2/assets/{event._eventDate._eventId-D7Twzb22.js.map → event._eventDate._eventId-C73GMDkK.js.map} +1 -1
- prefect/server/ui-v2/assets/{flow-run-graph-BhzuSJLm.js → flow-run-graph-ckiE3mA9.js} +2 -2
- prefect/server/ui-v2/assets/{flow-run-graph-BhzuSJLm.js.map → flow-run-graph-ckiE3mA9.js.map} +1 -1
- prefect/server/ui-v2/assets/{flow-run._id-CqpH6bvx.js → flow-run._id-BukrNCAq.js} +2 -2
- prefect/server/ui-v2/assets/{flow-run._id-CqpH6bvx.js.map → flow-run._id-BukrNCAq.js.map} +1 -1
- prefect/server/ui-v2/assets/{flow-run._id-lIIQBD7H.js → flow-run._id-CtI5VZ2M.js} +2 -2
- prefect/server/ui-v2/assets/{flow-run._id-lIIQBD7H.js.map → flow-run._id-CtI5VZ2M.js.map} +1 -1
- prefect/server/ui-v2/assets/flow-run._id-s1UJuakA.js +4 -0
- prefect/server/ui-v2/assets/{flow-run._id-RLy2kBh0.js.map → flow-run._id-s1UJuakA.js.map} +1 -1
- prefect/server/ui-v2/assets/{flow-runs-pagination-BATUweRV.js → flow-runs-pagination-SLbYtvaR.js} +2 -2
- prefect/server/ui-v2/assets/{flow-runs-pagination-BATUweRV.js.map → flow-runs-pagination-SLbYtvaR.js.map} +1 -1
- prefect/server/ui-v2/assets/flow._id-CZ5P0v4N.js +2 -0
- prefect/server/ui-v2/assets/{flow._id-BdQGWPKP.js.map → flow._id-CZ5P0v4N.js.map} +1 -1
- prefect/server/ui-v2/assets/{form-DLrbC7rV.js → form-mws4law8.js} +2 -2
- prefect/server/ui-v2/assets/{form-DLrbC7rV.js.map → form-mws4law8.js.map} +1 -1
- prefect/server/ui-v2/assets/{header-BTAWyeXv.js → header-Bes1LmY7.js} +2 -2
- prefect/server/ui-v2/assets/{header-BTAWyeXv.js.map → header-Bes1LmY7.js.map} +1 -1
- prefect/server/ui-v2/assets/{header-ChFAx5uR.js → header-Bj_zBR-a.js} +2 -2
- prefect/server/ui-v2/assets/{header-ChFAx5uR.js.map → header-Bj_zBR-a.js.map} +1 -1
- prefect/server/ui-v2/assets/{header-CyQqOj1w.js → header-CPxTHSvz.js} +2 -2
- prefect/server/ui-v2/assets/{header-CyQqOj1w.js.map → header-CPxTHSvz.js.map} +1 -1
- prefect/server/ui-v2/assets/{index-m48E4KcG.js → index-B8vo2Lrg.js} +5 -5
- prefect/server/ui-v2/assets/{index-m48E4KcG.js.map → index-B8vo2Lrg.js.map} +1 -1
- prefect/server/ui-v2/assets/{index-D5RT-SAp.js → index-BBeh-3Nh.js} +2 -2
- prefect/server/ui-v2/assets/{index-D5RT-SAp.js.map → index-BBeh-3Nh.js.map} +1 -1
- prefect/server/ui-v2/assets/index-BLnEvHia.js +2 -0
- prefect/server/ui-v2/assets/{index-7i4X9TeK.js.map → index-BLnEvHia.js.map} +1 -1
- prefect/server/ui-v2/assets/index-BpKoubXu.js +2 -0
- prefect/server/ui-v2/assets/index-BpKoubXu.js.map +1 -0
- prefect/server/ui-v2/assets/index-By6YGqR3.js +2 -0
- prefect/server/ui-v2/assets/index-By6YGqR3.js.map +1 -0
- prefect/server/ui-v2/assets/index-CEi3BlKI.js +2 -0
- prefect/server/ui-v2/assets/index-CEi3BlKI.js.map +1 -0
- prefect/server/ui-v2/assets/{index-BaWDC4da.js → index-CS-zxv7Z.js} +2 -2
- prefect/server/ui-v2/assets/{index-BaWDC4da.js.map → index-CS-zxv7Z.js.map} +1 -1
- prefect/server/ui-v2/assets/{index-kP_I5Qfd.js → index-CToHKh4q.js} +2 -2
- prefect/server/ui-v2/assets/{index-kP_I5Qfd.js.map → index-CToHKh4q.js.map} +1 -1
- prefect/server/ui-v2/assets/{index-CKGj5lSu.js → index-CUVvZndW.js} +2 -2
- prefect/server/ui-v2/assets/{index-CKGj5lSu.js.map → index-CUVvZndW.js.map} +1 -1
- prefect/server/ui-v2/assets/{index-CxUfZRkN.js → index-CYVn-I3i.js} +2 -2
- prefect/server/ui-v2/assets/{index-CxUfZRkN.js.map → index-CYVn-I3i.js.map} +1 -1
- prefect/server/ui-v2/assets/{index-CnlN-VC_.js → index-Cun0JN4t.js} +2 -2
- prefect/server/ui-v2/assets/{index-CnlN-VC_.js.map → index-Cun0JN4t.js.map} +1 -1
- prefect/server/ui-v2/assets/{index-BwCLKpNb.js → index-D6ynV6U7.js} +2 -2
- prefect/server/ui-v2/assets/{index-BwCLKpNb.js.map → index-D6ynV6U7.js.map} +1 -1
- prefect/server/ui-v2/assets/{index-CHf6xi9j.js → index-DdNUJLRW.js} +2 -2
- prefect/server/ui-v2/assets/{index-CHf6xi9j.js.map → index-DdNUJLRW.js.map} +1 -1
- prefect/server/ui-v2/assets/{index-CQnWiUE5.js → index-DlHOXQhu.js} +2 -2
- prefect/server/ui-v2/assets/{index-CQnWiUE5.js.map → index-DlHOXQhu.js.map} +1 -1
- prefect/server/ui-v2/assets/{index-Eqdr6Ff7.js → index-DyVw8YE8.js} +2 -2
- prefect/server/ui-v2/assets/{index-Eqdr6Ff7.js.map → index-DyVw8YE8.js.map} +1 -1
- prefect/server/ui-v2/assets/{index-Btb_-PDp.js → index-DzRz7D2P.js} +2 -2
- prefect/server/ui-v2/assets/{index-Btb_-PDp.js.map → index-DzRz7D2P.js.map} +1 -1
- prefect/server/ui-v2/assets/{index-DQGif3jm.js → index-DzUcVNZg.js} +2 -2
- prefect/server/ui-v2/assets/{index-DQGif3jm.js.map → index-DzUcVNZg.js.map} +1 -1
- prefect/server/ui-v2/assets/{index-DNh9ZBy4.js → index-IBvMMs6S.js} +2 -2
- prefect/server/ui-v2/assets/{index-DNh9ZBy4.js.map → index-IBvMMs6S.js.map} +1 -1
- prefect/server/ui-v2/assets/index-_kpA__te.js +2 -0
- prefect/server/ui-v2/assets/{index-CiSFHkhI.js.map → index-_kpA__te.js.map} +1 -1
- prefect/server/ui-v2/assets/index-m9O-nIOl.css +1 -0
- prefect/server/ui-v2/assets/{index-lyQav_XM.js → index-wOvyf10b.js} +2 -2
- prefect/server/ui-v2/assets/{index-lyQav_XM.js.map → index-wOvyf10b.js.map} +1 -1
- prefect/server/ui-v2/assets/{json-input-Ba-BeBcw.js → json-input-Ce-HlRqa.js} +2 -2
- prefect/server/ui-v2/assets/{json-input-Ba-BeBcw.js.map → json-input-Ce-HlRqa.js.map} +1 -1
- prefect/server/ui-v2/assets/{key-value-DkSKn6jE.js → key-value-XHEZOtZX.js} +2 -2
- prefect/server/ui-v2/assets/{key-value-DkSKn6jE.js.map → key-value-XHEZOtZX.js.map} +1 -1
- prefect/server/ui-v2/assets/{key._key-Cjx57ymg.js → key._key-LpsMf3zD.js} +2 -2
- prefect/server/ui-v2/assets/{key._key-Cjx57ymg.js.map → key._key-LpsMf3zD.js.map} +1 -1
- prefect/server/ui-v2/assets/{lazy-markdown-Du2Xu3Yp.js → lazy-markdown-1Hz0xzca.js} +2 -2
- prefect/server/ui-v2/assets/{lazy-markdown-Du2Xu3Yp.js.map → lazy-markdown-1Hz0xzca.js.map} +1 -1
- prefect/server/ui-v2/assets/{login-DxMF9Jvj.js → login-D5uepl9L.js} +2 -2
- prefect/server/ui-v2/assets/{login-DxMF9Jvj.js.map → login-D5uepl9L.js.map} +1 -1
- prefect/server/ui-v2/assets/{markdown-input-DPi8zyRr.js → markdown-input-CG6M9zD0.js} +2 -2
- prefect/server/ui-v2/assets/{markdown-input-DPi8zyRr.js.map → markdown-input-CG6M9zD0.js.map} +1 -1
- prefect/server/ui-v2/assets/python-example-snippet-DRHcUlCX.js +3 -0
- prefect/server/ui-v2/assets/{python-example-snippet-DfCFYPN_.js.map → python-example-snippet-DRHcUlCX.js.map} +1 -1
- prefect/server/ui-v2/assets/{python-input-mr6GD840.js → python-input-BsUS8fw1.js} +2 -2
- prefect/server/ui-v2/assets/{python-input-mr6GD840.js.map → python-input-BsUS8fw1.js.map} +1 -1
- prefect/server/ui-v2/assets/{radio-group-Co3cN0Kv.js → radio-group-BUsmwdrt.js} +2 -2
- prefect/server/ui-v2/assets/{radio-group-Co3cN0Kv.js.map → radio-group-BUsmwdrt.js.map} +1 -1
- prefect/server/ui-v2/assets/{route-error-state-DnBaNT2T.js → route-error-state-BFBpiIhD.js} +2 -2
- prefect/server/ui-v2/assets/{route-error-state-DnBaNT2T.js.map → route-error-state-BFBpiIhD.js.map} +1 -1
- prefect/server/ui-v2/assets/{schema-form-CWDHSME9.js → schema-form-BwTmkvJk.js} +2 -2
- prefect/server/ui-v2/assets/schema-form-BwTmkvJk.js.map +1 -0
- 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
- 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
- prefect/server/ui-v2/assets/{settings-DU5y6tJE.js → settings-CUBtK5aW.js} +2 -2
- prefect/server/ui-v2/assets/{settings-DU5y6tJE.js.map → settings-CUBtK5aW.js.map} +1 -1
- prefect/server/ui-v2/assets/{sort-filter-DpuWNkQo.js → sort-filter-Cv8zAXMp.js} +2 -2
- prefect/server/ui-v2/assets/{sort-filter-DpuWNkQo.js.map → sort-filter-Cv8zAXMp.js.map} +1 -1
- prefect/server/ui-v2/assets/{table-bBL6C0ZK.js → table-BBNGfPra.js} +2 -2
- prefect/server/ui-v2/assets/{table-bBL6C0ZK.js.map → table-BBNGfPra.js.map} +1 -1
- prefect/server/ui-v2/assets/{tags-input-BLPMVWpZ.js → tags-input-DHrnkwjQ.js} +2 -2
- prefect/server/ui-v2/assets/{tags-input-BLPMVWpZ.js.map → tags-input-DHrnkwjQ.js.map} +1 -1
- prefect/server/ui-v2/assets/task-run-concurrency-limits-reset-dialog-Z8-yFZ2_.js +2 -0
- 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
- prefect/server/ui-v2/assets/{task-run._id-Dl3Azs8t.js → task-run._id-BY58gqs2.js} +2 -2
- prefect/server/ui-v2/assets/{task-run._id-Dl3Azs8t.js.map → task-run._id-BY58gqs2.js.map} +1 -1
- prefect/server/ui-v2/assets/{task-run._id-B_tIDm4K.js → task-run._id-u73Jxfqw.js} +3 -3
- prefect/server/ui-v2/assets/{task-run._id-B_tIDm4K.js.map → task-run._id-u73Jxfqw.js.map} +1 -1
- prefect/server/ui-v2/assets/task-runs-pagination-DUy3147A.js +2 -0
- prefect/server/ui-v2/assets/{task-runs-pagination-VdR-LO4r.js.map → task-runs-pagination-DUy3147A.js.map} +1 -1
- prefect/server/ui-v2/assets/{textarea-B3_TtPRi.js → textarea-DUhh6-kq.js} +2 -2
- prefect/server/ui-v2/assets/{textarea-B3_TtPRi.js.map → textarea-DUhh6-kq.js.map} +1 -1
- prefect/server/ui-v2/assets/timezone-select-D4Q6VBtD.js +2 -0
- prefect/server/ui-v2/assets/{timezone-select-BuPYznge.js.map → timezone-select-D4Q6VBtD.js.map} +1 -1
- prefect/server/ui-v2/assets/{toggle-group-Cn07UIim.js → toggle-group-7WUJn2Tx.js} +2 -2
- prefect/server/ui-v2/assets/{toggle-group-Cn07UIim.js.map → toggle-group-7WUJn2Tx.js.map} +1 -1
- prefect/server/ui-v2/assets/use-delete-automation-confirmation-dialog-D4AD5Ndf.js +2 -0
- prefect/server/ui-v2/assets/{use-delete-automation-confirmation-dialog-DpdsLH4t.js.map → use-delete-automation-confirmation-dialog-D4AD5Ndf.js.map} +1 -1
- prefect/server/ui-v2/assets/{use-delete-block-document-confirmation-dialog-Cq5nGhzr.js → use-delete-block-document-confirmation-dialog-DnwWEGUY.js} +2 -2
- 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
- prefect/server/ui-v2/assets/{use-flow-runs-selected-rows-DmQSWBTu.js → use-flow-runs-selected-rows-C-tehPRB.js} +2 -2
- prefect/server/ui-v2/assets/{use-flow-runs-selected-rows-DmQSWBTu.js.map → use-flow-runs-selected-rows-C-tehPRB.js.map} +1 -1
- prefect/server/ui-v2/assets/{use-get-artifacts-flow-task-runs-DTwcWiqW.js → use-get-artifacts-flow-task-runs-DRWRrmrb.js} +2 -2
- 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
- prefect/server/ui-v2/assets/{use-quick-run-CPempwLh.js → use-quick-run-B4Xj-YQQ.js} +2 -2
- prefect/server/ui-v2/assets/{use-quick-run-CPempwLh.js.map → use-quick-run-B4Xj-YQQ.js.map} +1 -1
- prefect/server/ui-v2/assets/use-state-favicon-au2TZdMV.js +2 -0
- prefect/server/ui-v2/assets/{use-state-favicon-M09DmrNy.js.map → use-state-favicon-au2TZdMV.js.map} +1 -1
- prefect/server/ui-v2/assets/{use-stepper-CDucnvzp.js → use-stepper-DyIb3vlq.js} +2 -2
- prefect/server/ui-v2/assets/{use-stepper-CDucnvzp.js.map → use-stepper-DyIb3vlq.js.map} +1 -1
- prefect/server/ui-v2/assets/{utilities-BRCNRcQl.js → utilities-D9Y2wo66.js} +2 -2
- prefect/server/ui-v2/assets/{utilities-BRCNRcQl.js.map → utilities-D9Y2wo66.js.map} +1 -1
- prefect/server/ui-v2/assets/vendor-recharts-BvvJP9Po.js +34 -0
- prefect/server/ui-v2/assets/vendor-recharts-BvvJP9Po.js.map +1 -0
- prefect/server/ui-v2/assets/{work-pool-filter-C2tpSS-w.js → work-pool-filter-CSOATj2D.js} +2 -2
- prefect/server/ui-v2/assets/{work-pool-filter-C2tpSS-w.js.map → work-pool-filter-CSOATj2D.js.map} +1 -1
- prefect/server/ui-v2/assets/work-pool-queue-toggle-Dh7B1zMo.js +2 -0
- prefect/server/ui-v2/assets/{work-pool-queue-toggle-BQ9b-Wxy.js.map → work-pool-queue-toggle-Dh7B1zMo.js.map} +1 -1
- prefect/server/ui-v2/assets/work-pool._workPoolName-B_NFWXKS.js +2 -0
- prefect/server/ui-v2/assets/{work-pool._workPoolName-C_LiL3SE.js.map → work-pool._workPoolName-B_NFWXKS.js.map} +1 -1
- prefect/server/ui-v2/assets/{work-pool_._workPoolName.edit-DBHlrVVx.js → work-pool_._workPoolName.edit-Cyzn8g-S.js} +2 -2
- prefect/server/ui-v2/assets/{work-pool_._workPoolName.edit-DBHlrVVx.js.map → work-pool_._workPoolName.edit-Cyzn8g-S.js.map} +1 -1
- prefect/server/ui-v2/assets/{work-pool_._workPoolName.queue._workQueueName-DkITxJOP.js → work-pool_._workPoolName.queue._workQueueName-DQzqQWPT.js} +2 -2
- prefect/server/ui-v2/assets/{work-pool_._workPoolName.queue._workQueueName-DkITxJOP.js.map → work-pool_._workPoolName.queue._workQueueName-DQzqQWPT.js.map} +1 -1
- prefect/server/ui-v2/assets/{work-queue-icon-text-D4BWBVDN.js → work-queue-icon-text-BOpcJ8YU.js} +2 -2
- prefect/server/ui-v2/assets/{work-queue-icon-text-D4BWBVDN.js.map → work-queue-icon-text-BOpcJ8YU.js.map} +1 -1
- prefect/server/ui-v2/index.html +3 -3
- {prefect-3.6.15.dist-info → prefect-3.6.16.dev3.dist-info}/METADATA +2 -1
- {prefect-3.6.15.dist-info → prefect-3.6.16.dev3.dist-info}/RECORD +223 -211
- prefect/server/ui-v2/assets/artifact._id-BFdf1WUA.js +0 -2
- prefect/server/ui-v2/assets/artifact._id-BFdf1WUA.js.map +0 -1
- prefect/server/ui-v2/assets/automation._id-Dn7jABys.js +0 -2
- prefect/server/ui-v2/assets/block-type-logo-Cbpfxded.js +0 -2
- prefect/server/ui-v2/assets/block-type-logo-Cbpfxded.js.map +0 -1
- prefect/server/ui-v2/assets/catalog_._slug-Bl2J2oI3.js +0 -2
- prefect/server/ui-v2/assets/create-D--LHaji.js +0 -2
- prefect/server/ui-v2/assets/data-table-rlbkLcrY.js +0 -2
- prefect/server/ui-v2/assets/data-table-rlbkLcrY.js.map +0 -1
- prefect/server/ui-v2/assets/delete-confirmation-dialog-DHkm2p8m.js +0 -2
- prefect/server/ui-v2/assets/deployment._id-Ci9zge5n.js +0 -2
- prefect/server/ui-v2/assets/deployment_._id.duplicate-D9ZWkh8H.js +0 -2
- prefect/server/ui-v2/assets/deployment_._id.edit-CS7sObzC.js +0 -2
- prefect/server/ui-v2/assets/event._eventDate._eventId-D7Twzb22.js +0 -2
- prefect/server/ui-v2/assets/flow-run._id-RLy2kBh0.js +0 -4
- prefect/server/ui-v2/assets/flow._id-BdQGWPKP.js +0 -2
- prefect/server/ui-v2/assets/index-7i4X9TeK.js +0 -2
- prefect/server/ui-v2/assets/index-BkiGTHwU.js +0 -2
- prefect/server/ui-v2/assets/index-BkiGTHwU.js.map +0 -1
- prefect/server/ui-v2/assets/index-COouj_0-.css +0 -1
- prefect/server/ui-v2/assets/index-CiSFHkhI.js +0 -2
- prefect/server/ui-v2/assets/index-DATPYZfT.js +0 -2
- prefect/server/ui-v2/assets/index-DATPYZfT.js.map +0 -1
- prefect/server/ui-v2/assets/index-VH4TnZ4e.js +0 -2
- prefect/server/ui-v2/assets/index-VH4TnZ4e.js.map +0 -1
- prefect/server/ui-v2/assets/python-example-snippet-DfCFYPN_.js +0 -3
- prefect/server/ui-v2/assets/schema-form-CWDHSME9.js.map +0 -1
- prefect/server/ui-v2/assets/task-run-concurrency-limits-reset-dialog-S69sih55.js +0 -2
- prefect/server/ui-v2/assets/task-runs-pagination-VdR-LO4r.js +0 -2
- prefect/server/ui-v2/assets/timezone-select-BuPYznge.js +0 -2
- prefect/server/ui-v2/assets/use-delete-automation-confirmation-dialog-DpdsLH4t.js +0 -2
- prefect/server/ui-v2/assets/use-state-favicon-M09DmrNy.js +0 -2
- prefect/server/ui-v2/assets/vendor-recharts-BAN776s_.js +0 -34
- prefect/server/ui-v2/assets/vendor-recharts-BAN776s_.js.map +0 -1
- prefect/server/ui-v2/assets/work-pool-queue-toggle-BQ9b-Wxy.js +0 -2
- prefect/server/ui-v2/assets/work-pool._workPoolName-C_LiL3SE.js +0 -2
- {prefect-3.6.15.dist-info → prefect-3.6.16.dev3.dist-info}/WHEEL +0 -0
- {prefect-3.6.15.dist-info → prefect-3.6.16.dev3.dist-info}/entry_points.txt +0 -0
- {prefect-3.6.15.dist-info → prefect-3.6.16.dev3.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{r as l,j as s,t as E,L as Me,F as $e,n as ot,E as rt}from"./vendor-tanstack-BcZfOOfy.js";import{a8 as Ye,a9 as lt,aa as it,ab as be,ac as ct,ad as ut,ae as dt,af as mt,ag as ft,ah as gt,ai as ht,aj as Ee,ak as oe,al as re,am as pt,y as ee,N as qe,q as le,I as V,an as xt,ao as wt,ap as St,aq as vt,ar as kt,as as yt,at as Ft,_ as jt,$ as Ct,a0 as Rt,a1 as bt,a2 as Tt,p as Dt,a3 as _t,au as ie,av as Nt,i as O,aw as Mt,ax as Et,ay as Ae,az as Pe,C as At,o as Pt,G as It,O as Ie,B as Lt,g as zt,h as Ot,E as Vt,t as Ht,v as Wt,w as Bt,x as Ut,D as Qt,aA as Ge,aB as j,aC as $t,aD as Yt,aE as Le,aF as ze,aG as qt,aH as Oe,aI as Gt,aJ as Xt,aK as Kt,aL as Jt}from"./index-m48E4KcG.js";import{D as Zt,W as es}from"./work-pool-filter-C2tpSS-w.js";import{S as ts}from"./sort-filter-DpuWNkQo.js";import{S as ss,F as as,a as ns}from"./flow-runs-pagination-BATUweRV.js";import{u as os,F as rs}from"./use-flow-runs-selected-rows-DmQSWBTu.js";import{D as Xe}from"./delete-confirmation-dialog-DHkm2p8m.js";import{D as ls,a as is,b as cs,d as te,e as us}from"./dropdown-menu-0atiOSFo.js";import{g as ds,S as ms}from"./state-colors-CAAf0Eg3.js";import{R as fs,S as gs,X as hs,Y as ps,T as xs,d as ws}from"./vendor-recharts-BAN776s_.js";import{c as Ss}from"./vendor-date-wwuDAncJ.js";import{T as vs,a as ks,b as ys}from"./task-runs-pagination-VdR-LO4r.js";import{u as Fs}from"./use-delete-confirmation-dialog-CUdii6Lo.js";import{T as js}from"./tags-input-BLPMVWpZ.js";import{a as Cs}from"./zod-Cuos7J7w.js";import{c as Rs,o as Ke,s as _,e as se,n as ae,b as bs}from"./vendor-forms-ClCIacbh.js";import{F as Ts,b as Ds,c as _s,d as Ns,e as Ms,a as Es}from"./form-DLrbC7rV.js";import"./vendor-react-Bce9NwRC.js";import"./vendor-radix-BTiKGWfR.js";const As=({value:e,onValueChange:t,className:n})=>{const a=l.useMemo(()=>Ye(e),[e]),o=i=>{t(it(i))};return s.jsx(lt,{value:a,onValueChange:o,placeholder:"All time",clearable:!0,className:n})},Ve=2,Ps=({selectedFlows:e,onSelectFlows:t})=>{const[n,a]=l.useState(""),o=l.useDeferredValue(n),{data:i=[]}=E(be({flows:o?{operator:"and_",name:{like_:o}}:void 0,limit:100,offset:0,sort:"NAME_ASC"})),{data:r=[]}=E(be({flows:e.size>0?{operator:"and_",id:{any_:Array.from(e)}}:void 0,limit:e.size||1,offset:0,sort:"NAME_ASC"},{enabled:e.size>0})),u=m=>{const h=new Set(e);e.has(m)?h.delete(m):h.add(m),t(h)},c=()=>{t(new Set)},d=()=>{if(e.size===0)return"All flows";const m=r.filter(S=>e.has(S.id)).map(S=>S.name),h=m.slice(0,Ve),x=m.length-Ve;return s.jsxs("div",{className:"flex flex-1 min-w-0 items-center gap-2",children:[s.jsx("div",{className:"flex flex-1 min-w-0 items-center gap-2 overflow-hidden",children:s.jsx("span",{className:"truncate",children:h.join(", ")})}),x>0&&s.jsxs(re,{variant:"bodySmall",className:"shrink-0",children:["+ ",x]})]})},f=l.useMemo(()=>i.filter(m=>!o||m.name.toLowerCase().includes(o.toLowerCase())),[i,o]);return s.jsxs(ct,{children:[s.jsx(ut,{"aria-label":"Filter by flow",selected:e.size===0,children:d()}),s.jsxs(dt,{children:[s.jsx(mt,{value:n,onValueChange:a,placeholder:"Search flows..."}),s.jsxs(ft,{children:[s.jsx(gt,{children:"No flows found"}),s.jsxs(ht,{children:[s.jsxs(Ee,{"aria-label":"All flows",onSelect:c,closeOnSelect:!1,value:"__all__",children:[s.jsx(oe,{checked:e.size===0}),"All flows"]}),f.map(m=>s.jsxs(Ee,{"aria-label":m.name,onSelect:()=>u(m.id),closeOnSelect:!1,value:m.id,children:[s.jsx(oe,{checked:e.has(m.id)}),m.name]},m.id))]})]})]})]})},Is=()=>{const[e,t]=Fs(),{mutateAsync:n}=pt(),a=async(i,r=()=>{})=>{try{const u=await Promise.allSettled(i.map(f=>n({id:f}))),{numFails:c,numSuccess:d}=u.reduce((f,m)=>(m.status==="rejected"?f.numFails+=1:f.numSuccess+=1,f),{numFails:0,numSuccess:0});c>1?ee.error(`${c} task runs failed to delete`):c===1?ee.error("Task run failed to delete"):d>1?ee.success(`${d} task runs deleted`):ee.success("Task run deleted")}catch(u){console.error("Unknown error while deleting task run.",u)}finally{r()}};return[e,(i,r=()=>{})=>t({title:"Delete Task Runs",description:"Are you sure you want to delete selected task runs?",onConfirm:()=>{a(i,r)}})]},Ls=({count:e=0,...t})=>"results"in t&&"setSelectedRows"in t&&"selectedRows"in t?s.jsx(zs,{count:e,...t}):s.jsxs(re,{variant:"bodySmall",className:"text-muted-foreground",children:[e," ",qe(e,"Task run")]});function zs({count:e=0,results:t=[],setSelectedRows:n,selectedRows:a}){const[o,i]=Is(),r=l.useMemo(()=>t.map(({id:d})=>d),[t]),u=Array.from(a),c=()=>{const d=r.every(h=>a.has(h)),f=r.some(h=>a.has(h));let m=!1;return d?m=!0:f&&(m="indeterminate"),s.jsx(oe,{className:"block",checked:m,onCheckedChange:h=>{n(h?new Set(r):new Set)},"aria-label":"Toggle all"})};return a.size>0?s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx(c,{}),s.jsxs(re,{variant:"bodySmall",className:"text-muted-foreground",children:[u.length," selected"]}),s.jsx(le,{"aria-label":"Delete rows",size:"icon",variant:"secondary",onClick:()=>{i(u,()=>n(new Set))},children:s.jsx(V,{id:"Trash2",className:"size-4"})})]}),s.jsx(Xe,{...o})]}):s.jsxs("div",{className:"flex items-center gap-2",children:[t&&n&&a&&s.jsx(oe,{className:"block",checked:!1,onCheckedChange:d=>{n(new Set(d?r:void 0))},"aria-label":"Toggle all"}),s.jsxs(re,{variant:"bodySmall",className:"text-muted-foreground",children:[e," ",qe(e,"Task run")]})]})}const Os=e=>{const[t,n]=l.useState(new Set(e)),a=c=>n(d=>new Set(d).add(c)),o=c=>n(d=>{const f=new Set(d);return f.delete(c),f});return[t,n,{addRow:a,removeRow:o,onSelectRow:(c,d)=>{d?a(c):o(c)},clearSet:()=>n(new Set)}]},Je="Custom",Vs="Unsaved";function Hs(e){return e?e.name===Je||e.name===Vs:!0}const Ws=({currentFilter:e,savedFilters:t,onSelect:n,onSave:a,onDelete:o,onSetDefault:i,onRemoveDefault:r,permissions:u={canSave:!0,canDelete:!0}})=>{const[c,d]=l.useState(!1),f=e?.name??Je,m=Hs(e),h=m&&u.canSave,x=e?.id&&u.canDelete,S=!m,y=()=>{e?.id&&(o(e.id),d(!1))},g=()=>{e?.id&&(e.isDefault?r(e.id):i(e.id))};return s.jsxs(s.Fragment,{children:[s.jsxs(ls,{children:[s.jsx(is,{asChild:!0,children:s.jsxs(le,{variant:"outline",className:"gap-2",children:[s.jsx(V,{id:"SlidersVertical",className:"size-4"}),s.jsx("span",{children:f}),s.jsx(V,{id:"ChevronDown",className:"size-4"})]})}),s.jsxs(cs,{align:"start",className:"min-w-[200px]",children:[t.map(p=>s.jsxs(te,{onClick:()=>n(p),className:"flex items-center justify-between",children:[s.jsx("span",{children:p.name}),p.isDefault&&s.jsx(V,{id:"CircleCheck",className:"size-4 text-green-500"})]},p.id??p.name)),(h||x||S)&&s.jsx(us,{}),h&&s.jsxs(te,{onClick:a,children:[s.jsx(V,{id:"Plus",className:"mr-2 size-4"}),"Save current filters"]}),x&&s.jsxs(te,{variant:"destructive",onClick:()=>d(!0),children:[s.jsx(V,{id:"Trash2",className:"mr-2 size-4"}),"Delete"]}),S&&s.jsxs(te,{onClick:g,children:[s.jsx(V,{id:"CircleCheck",className:"mr-2 size-4"}),e?.isDefault?"Remove as default":"Set as default"]})]})]}),s.jsx(Xe,{isOpen:c,title:"Delete saved filter",description:`Are you sure you want to delete "${e?.name}"? This action cannot be undone.`,onConfirm:y,onClose:()=>d(!1)})]})},Bs=({cx:e,cy:t,payload:n})=>{if(e===void 0||t===void 0||!n)return null;const a=ds(n.stateType)||ms[n.stateType]||"#6b7280";return s.jsx("circle",{cx:e,cy:t,r:6,fill:a,stroke:a,strokeWidth:1,opacity:.7,className:"hover:opacity-100 transition-opacity cursor-pointer"})},Us=({active:e,payload:t})=>{const a=t?.[0]?.payload,o=a?.id,{data:i}=E({...xt(o??""),enabled:e&&!!o,staleTime:300*1e3}),{data:r}=E({...wt(i?.flow_id??""),enabled:!!i?.flow_id,staleTime:300*1e3});if(!e||!t||t.length===0||!a)return null;const u=new Date(a.timestamp);return s.jsxs("div",{className:"bg-background border rounded-lg p-3 shadow-lg flex flex-col gap-2 min-w-48",children:[s.jsxs("div",{className:"flex items-center gap-1 text-sm text-muted-foreground",children:[i?.flow_id&&s.jsxs(s.Fragment,{children:[s.jsx(Me,{to:"/flows/flow/$id",params:{id:i.flow_id},className:"font-semibold hover:underline truncate max-w-32",children:r?.name??"..."}),s.jsx(St,{className:"size-3 flex-shrink-0"})]}),s.jsx(Me,{to:"/runs/flow-run/$id",params:{id:a.id},className:"hover:underline truncate max-w-32",children:i?.name??a.id.slice(0,8)})]}),s.jsx("div",{children:s.jsx(vt,{type:a.stateType})}),s.jsx("hr",{className:"border-border"}),s.jsxs("div",{className:"flex flex-col gap-1",children:[s.jsxs("span",{className:"flex items-center gap-2 text-sm text-muted-foreground",children:[s.jsx(yt,{className:"size-4"}),kt(Math.ceil(a.duration*1e3),{largest:2,round:!0})]}),s.jsxs("span",{className:"flex items-center gap-2 text-sm text-muted-foreground",children:[s.jsx(Ft,{className:"size-4"}),u.toLocaleString()]})]})]})},Qs=e=>t=>t===0?"0s":e<1?`${Math.round(t*1e3)}ms`:e<10?`${t.toFixed(1)}s`:e<60?`${Math.round(t)}s`:Ss(0,t*1e3,{addSuffix:!1}),$s=(e,t)=>i=>{const r=new Date(i);if(t<1e3||e<1e4){const u=r.getSeconds(),c=r.getMilliseconds();return`${r.toLocaleTimeString(void 0,{hour:"2-digit",minute:"2-digit"})}:${u.toString().padStart(2,"0")}.${Math.floor(c/100)}`}return t<6e4||e<10*6e4?r.toLocaleTimeString(void 0,{hour:"2-digit",minute:"2-digit",second:"2-digit"}):e>=864e5?r.getHours()===0&&r.getMinutes()===0&&r.getSeconds()===0&&r.getMilliseconds()===0?r.toLocaleDateString(void 0,{weekday:"short",day:"numeric"}):r.toLocaleTimeString(void 0,{hour:"2-digit",minute:"2-digit"}):r.toLocaleTimeString(void 0,{hour:"2-digit",minute:"2-digit"})},Ys=({history:e,startDate:t,endDate:n})=>{const a=l.useRef(null),[o,i]=l.useState(0);l.useEffect(()=>{const g=a.current;if(!g)return;const p=new ResizeObserver(w=>{for(const k of w)i(k.contentRect.width)});return p.observe(g),i(g.getBoundingClientRect().width),()=>p.disconnect()},[]);const r=l.useMemo(()=>e.map(g=>({x:new Date(g.timestamp).getTime(),y:g.duration,stateType:g.state_type,id:g.id,duration:g.duration,lateness:g.lateness,timestamp:g.timestamp})),[e]),{xDomain:u,xDomainMin:c,xDomainMax:d}=l.useMemo(()=>{if(t&&n)return{xDomain:[t.getTime(),n.getTime()],xDomainMin:t.getTime(),xDomainMax:n.getTime()};if(r.length===0){const k=Date.now(),b=k-1440*60*1e3;return{xDomain:[b,k],xDomainMin:b,xDomainMax:k}}const g=r.map(k=>k.x),p=Math.min(...g),w=Math.max(...g);return{xDomain:[p,w],xDomainMin:p,xDomainMax:w}},[t,n,r]),f=l.useMemo(()=>r.length===0?60:Math.max(...r.map(g=>g.y)),[r]),m=l.useMemo(()=>{if(r.length<2)return Number.POSITIVE_INFINITY;const g=r.map(w=>w.x).sort((w,k)=>w-k);let p=Number.POSITIVE_INFINITY;for(let w=1;w<g.length;w++){const k=g[w]-g[w-1];k>0&&k<p&&(p=k)}return p},[r]),h=d-c,x=l.useMemo(()=>$s(h,m),[h,m]),S=l.useMemo(()=>Qs(f),[f]),y=l.useMemo(()=>{const w=o-60,k=Math.max(2,Math.ceil(w/100)),b=1440*60*1e3,F=d-c;if(F>=b){const v=[],W=new Date(c),H=new Date(W);H.setHours(24,0,0,0),v.push(c);let P=H.getTime();for(;P<d;)v.push(P),P+=b;const B=v[v.length-1];if(d-B>F/k/2&&v.push(d),v.length<k){const M=[];for(let T=0;T<v.length-1;T++){M.push(v[T]);const I=v[T+1]-v[T],L=Math.max(1,Math.floor(I/(F/k)));if(L>1){const U=I/L;for(let z=1;z<L;z++)M.push(v[T]+U*z)}}return M.push(v[v.length-1]),M}return v}const N=[],A=(d-c)/(k-1);for(let v=0;v<k;v++)N.push(c+A*v);return N},[o,c,d]);return e.length===0?null:s.jsx("div",{ref:a,className:"hidden md:block w-full h-64","data-testid":"scatter-plot",children:s.jsx(fs,{width:"100%",height:"100%",children:s.jsxs(gs,{children:[s.jsx(hs,{type:"number",dataKey:"x",scale:"time",domain:u,ticks:y,tickFormatter:x,tick:{fontSize:12},tickLine:!1,axisLine:{stroke:"#e5e7eb"}}),s.jsx(ps,{type:"number",dataKey:"y",tickFormatter:S,tick:{fontSize:12},tickLine:!1,axisLine:{stroke:"#e5e7eb"},width:60}),s.jsx(xs,{content:s.jsx(Us,{}),cursor:{strokeDasharray:"3 3"},animationDuration:0}),s.jsx(ws,{data:r,shape:s.jsx(Bs,{}),isAnimationActive:!1})]})})})},qs=Ke({name:_().min(1,{message:"Name is required"}).max(100,{message:"Name must be 100 characters or less"})}),Gs=({open:e,onOpenChange:t,onSave:n})=>{const a=Rs({resolver:Cs(qs),defaultValues:{name:""}});l.useEffect(()=>{e&&a.reset({name:""})},[e,a]);const o=i=>{n(i.name),t(!1)};return s.jsx(jt,{open:e,onOpenChange:t,children:s.jsxs(Ct,{children:[s.jsx(Rt,{children:s.jsx(bt,{children:"Save Filter"})}),s.jsx(Tt,{children:"Save your current filter configuration for quick access later."}),s.jsx(Ts,{...a,children:s.jsxs("form",{onSubmit:i=>{a.handleSubmit(o)(i)},className:"space-y-4",children:[s.jsx(Ds,{control:a.control,name:"name",render:({field:i})=>s.jsxs(_s,{children:[s.jsx(Ns,{children:"Filter Name"}),s.jsx(Ms,{children:s.jsx(Dt,{autoComplete:"off",placeholder:"e.g., Failed runs this week",...i})}),s.jsx(Es,{})]})}),s.jsxs(_t,{children:[s.jsx(le,{type:"button",variant:"outline",onClick:()=>t(!1),children:"Cancel"}),s.jsx(le,{type:"submit",children:"Save"})]})]})})]})})},Xs="prefect-ui-v2-saved-filters",Ks="prefect-ui-v2-default-filter-id",Ze="system-past-week",et="system-hide-scheduled";function Js(e){return e===Ze||e===et}const tt=[{id:Ze,name:"Past week",filters:{range:"past-7-days"}},{id:et,name:"Hide scheduled runs",filters:{range:"past-7-days",state:[...Nt]}}],Zs=tt[0];function ea(){return`${Date.now()}-${Math.random().toString(36).substring(2,9)}`}function ta(e,t){const n=(a,o)=>{if(a===void 0&&o===void 0)return!0;if(a===void 0||o===void 0||a.length!==o.length)return!1;const i=[...a].sort(),r=[...o].sort();return i.every((u,c)=>u===r[c])};return n(e.state,t.state)&&n(e.flows,t.flows)&&n(e.deployments,t.deployments)&&n(e.workPools,t.workPools)&&n(e.tags,t.tags)&&e.range===t.range&&e.start===t.start&&e.end===t.end}function st(){const[e,t]=ie(Xs,[]),[n,a]=ie(Ks,null),o=l.useMemo(()=>[...tt,...e],[e]),i=l.useCallback(h=>{const x={id:ea(),name:h.name,filters:h.filters};return t(S=>[...S,x]),x},[t]),r=l.useCallback(h=>{t(x=>x.filter(S=>S.id!==h)),a(x=>x===h?null:x)},[t,a]),u=l.useCallback((h,x)=>{t(S=>S.map(y=>y.id===h?{...y,...x.name!==void 0&&{name:x.name},...x.filters!==void 0&&{filters:x.filters}}:y))},[t]),c=l.useCallback(h=>{a(h)},[a]),d=l.useCallback(h=>o.find(x=>x.id===h),[o]),f=l.useCallback(h=>o.find(x=>ta(x.filters,h)),[o]),m=l.useMemo(()=>h=>n===h,[n]);return{savedFilters:o,defaultFilterId:n,saveFilter:i,deleteFilter:r,updateFilter:u,setDefaultFilter:c,getFilterById:d,findMatchingFilter:f,isDefaultFilter:m}}const sa=({tab:e,onTabChange:t,flowRunsCount:n,taskRunsCount:a,hasAnyFlowRuns:o,hasAnyTaskRuns:i,flowRuns:r,flowRunsPages:u,pagination:c,onPaginationChange:d,onPrefetchPage:f,sort:m,onSortChange:h,hideSubflows:x,onHideSubflowsChange:S,flowRunSearch:y,onFlowRunSearchChange:g,selectedStates:p,onStateFilterChange:w,selectedFlows:k,onFlowFilterChange:b,selectedDeployments:F,onDeploymentFilterChange:N,selectedTags:A,onTagsFilterChange:v,selectedWorkPools:W,onWorkPoolFilterChange:H,dateRange:P,onDateRangeChange:B,flowRunHistory:M,scatterPlotDateRange:T,taskRuns:I,taskRunsPages:L,taskRunsPagination:U,onTaskRunsPaginationChange:z,onTaskRunsPrefetchPage:Q,taskRunsSort:de,onTaskRunsSortChange:me,taskRunSearch:fe,onTaskRunSearchChange:ge,onClearTaskRunFilters:he,currentFilter:X,savedFilters:pe,onSelectFilter:xe,onSaveFilter:we,onDeleteFilter:Se,onSetDefault:ve,onRemoveDefault:ke,isSaveDialogOpen:$,onCloseSaveDialog:Y,onConfirmSave:ye})=>{const q=!o&&!i,[K,Fe,{onSelectRow:je}]=os(),[J,Ce,{onSelectRow:C}]=Os(),D=[...new Set(r.map(R=>R.flow_id))],{data:Z}=E(be({flows:{operator:"and_",id:{any_:D}},offset:0,sort:"NAME_ASC"},{enabled:D.length>0})),G=r.map(R=>({...R,flow:Z?.find(Re=>Re.id===R.flow_id)}));return q?s.jsxs("div",{className:"flex flex-col gap-4",children:[s.jsx(He,{}),s.jsx(aa,{})]}):s.jsxs("div",{className:"flex flex-col gap-4",children:[s.jsxs("div",{className:"flex items-center justify-between",children:[s.jsx(He,{}),s.jsx(Ws,{currentFilter:X,savedFilters:pe,onSelect:xe,onSave:we,onDelete:Se,onSetDefault:ve,onRemoveDefault:ke,permissions:{canSave:!0,canDelete:!Js(X?.id??null)}})]}),s.jsxs("div",{className:"flex flex-col gap-2",children:[s.jsxs("div",{className:"flex flex-wrap gap-2 lg:grid lg:grid-flow-col lg:auto-cols-fr",children:[s.jsxs("div",{className:"flex flex-col gap-1 w-full lg:w-auto",children:[s.jsx(O,{className:"text-xs text-muted-foreground",children:"Date Range"}),s.jsx(As,{value:P,onValueChange:B})]}),s.jsxs("div",{className:"flex flex-col gap-1 w-full lg:w-auto",children:[s.jsx(O,{className:"text-xs text-muted-foreground",children:"States"}),s.jsx(ss,{selectedFilters:p,onSelectFilter:w})]})]}),s.jsxs("div",{className:"flex flex-wrap gap-2 lg:grid lg:grid-flow-col lg:auto-cols-fr",children:[s.jsxs("div",{className:"flex flex-col gap-1 w-full lg:w-auto",children:[s.jsx(O,{className:"text-xs text-muted-foreground",children:"Flows"}),s.jsx(Ps,{selectedFlows:k,onSelectFlows:b})]}),s.jsxs("div",{className:"flex flex-col gap-1 w-full lg:w-auto",children:[s.jsx(O,{className:"text-xs text-muted-foreground",children:"Deployments"}),s.jsx(Zt,{selectedDeployments:F,onSelectDeployments:N})]}),s.jsxs("div",{className:"flex flex-col gap-1 w-full lg:w-auto",children:[s.jsx(O,{className:"text-xs text-muted-foreground",children:"Work Pools"}),s.jsx(es,{selectedWorkPools:W,onSelectWorkPools:H})]}),s.jsxs("div",{className:"flex flex-col gap-1 w-full lg:w-auto",children:[s.jsx(O,{className:"text-xs text-muted-foreground",children:"Tags"}),s.jsx(js,{value:Array.from(A),onChange:R=>{const Re=Array.isArray(R)?R:[];v(new Set(Re))},placeholder:"All tags"})]})]})]}),s.jsx(Gs,{open:$,onOpenChange:Y,onSave:ye}),s.jsxs(Mt,{value:e,onValueChange:t,children:[s.jsxs(Et,{children:[s.jsx(Ae,{value:"flow-runs",children:"Flow Runs"}),s.jsx(Ae,{value:"task-runs",children:"Task Runs"})]}),s.jsx(Pe,{value:"flow-runs",children:s.jsxs("div",{className:"flex flex-col gap-4",children:[s.jsx(At,{children:s.jsx(Pt,{children:s.jsx(Ys,{history:M,startDate:T.startDate,endDate:T.endDate})})}),s.jsxs("div",{className:"flex items-center justify-between",children:[s.jsx(rs,{count:n,results:G,selectedRows:K,setSelectedRows:Fe}),s.jsxs("div",{className:"flex items-center gap-4",children:[s.jsxs("div",{className:"flex items-center gap-2 whitespace-nowrap",children:[s.jsx(It,{id:"hide-subflows",checked:x,onCheckedChange:S}),s.jsx(O,{htmlFor:"hide-subflows",children:"Hide subflows"})]}),s.jsx(Ie,{value:y,onChange:R=>g(R.target.value),placeholder:"Search by flow run name","aria-label":"Search by flow run name",className:"w-64",debounceMs:1200}),s.jsx(ts,{value:m,onSelect:h})]})]}),s.jsx(as,{count:n,pages:u,pagination:c,onChangePagination:d,onPrefetchPage:f}),s.jsx(ns,{flowRuns:G,selectedRows:K,onSelect:je})]})}),s.jsx(Pe,{value:"task-runs",children:s.jsxs("div",{className:"flex flex-col gap-4",children:[s.jsxs("div",{className:"flex items-center justify-between",children:[s.jsx(Ls,{count:a,results:I,selectedRows:J,setSelectedRows:Ce}),s.jsxs("div",{className:"flex items-center gap-4",children:[s.jsx(Ie,{value:fe,onChange:R=>ge(R.target.value),placeholder:"Search by task run name","aria-label":"Search by task run name",className:"w-64",debounceMs:1200}),s.jsx(vs,{value:de,onSelect:me})]})]}),s.jsx(ks,{count:a,pages:L,pagination:U,onChangePagination:z,onPrefetchPage:Q}),s.jsx(ys,{taskRuns:I,selectedRows:J,onSelect:C,onClearFilters:he})]})})]})]})},He=()=>s.jsx("div",{className:"flex items-center gap-2",children:s.jsx(Lt,{children:s.jsx(zt,{children:s.jsx(Ot,{className:"text-xl font-semibold",children:"Runs"})})})}),aa=()=>s.jsxs(Vt,{children:[s.jsx(Ht,{id:"Workflow"}),s.jsx(Wt,{children:"Run a task or flow to get started"}),s.jsx(Bt,{children:"Runs store the state history for each execution of a task or flow."}),s.jsx(Ut,{children:s.jsx(Qt,{id:"getting-started"})})]}),ce=$e("/runs/");function na(e){const t=u=>u?u.split(",").filter(c=>c.trim().length>0):[],n=t(e.state),a=t(e.flows),o=t(e.deployments),i=t(e["work-pools"]),r=t(e.tags);return{...n.length>0&&{state:n},...a.length>0&&{flows:a},...o.length>0&&{deployments:o},...i.length>0&&{workPools:i},...r.length>0&&{tags:r},...e.range&&{range:e.range},...e.start&&{start:e.start},...e.end&&{end:e.end}}}function at(e){return{state:e.state?.join(",")??"",flows:e.flows?.join(",")??"",deployments:e.deployments?.join(",")??"","work-pools":e.workPools?.join(",")??"",tags:e.tags?.join(",")??"",range:e.range,start:e.start,end:e.end}}function We(e,t){return{id:e.id,name:e.name,isDefault:e.id===t}}function oa(){const e=ce.useSearch(),t=ce.useNavigate(),{savedFilters:n,defaultFilterId:a,saveFilter:o,deleteFilter:i,setDefaultFilter:r,findMatchingFilter:u}=st(),[c,d]=l.useState(!1),f=l.useMemo(()=>na(e),[e]),m=l.useMemo(()=>u(f),[u,f]),h=l.useMemo(()=>n.map(F=>We(F,a)),[n,a]),x=l.useMemo(()=>m?We(m,a):f.state?.length||f.flows?.length||f.deployments?.length||f.workPools?.length||f.tags?.length||f.range||f.start||f.end?{id:null,name:"Unsaved",isDefault:!1}:{id:null,name:"Custom",isDefault:!1},[m,a,f]),S=l.useCallback(F=>{const N=n.find(v=>v.id===F.id);if(!N)return;const A=at(N.filters);t({to:".",search:v=>({...v,...A,page:1}),replace:!0})},[t,n]),y=l.useCallback(()=>{d(!0)},[]),g=l.useCallback(F=>{o({name:F,filters:f}),d(!1)},[o,f]),p=l.useCallback(()=>{d(!1)},[]),w=l.useCallback(F=>{i(F)},[i]),k=l.useCallback(F=>{r(F)},[r]),b=l.useCallback(()=>{r(null)},[r]);return{currentFilter:x,savedFiltersForMenu:h,onSelectFilter:S,onSaveFilter:y,onDeleteFilter:w,onSetDefault:k,onRemoveDefault:b,isSaveDialogOpen:c,closeSaveDialog:p,confirmSave:g}}function ra(){const e=ce.useNavigate(),t=ce.useSearch(),{defaultFilterId:n,getFilterById:a}=st(),o=l.useRef(!1),i=l.useMemo(()=>!!(t.state||t.flows||t.deployments||t["work-pools"]||t.tags||t.range||t.start||t.end),[t]);l.useEffect(()=>{if(o.current||i)return;let r;n&&(r=a(n)),r||(r=Zs),o.current=!0;const u=at(r.filters);e({to:".",search:c=>({...c,...u,page:1}),replace:!0})},[n,i,a,e])}const Be=$e("/runs/"),la=e=>e?e.split(",").filter(t=>Ge.includes(t)):[],ne=e=>e?e.split(",").filter(t=>t.trim().length>0):[];function ia(){const e=Be.useSearch(),t=Be.useNavigate(),n=l.useMemo(()=>new Set(la(e.state??"")),[e.state]),a=l.useMemo(()=>new Set(ne(e.flows??"")),[e.flows]),o=l.useMemo(()=>new Set(ne(e.deployments??"")),[e.deployments]),i=l.useMemo(()=>new Set(ne(e["work-pools"]??"")),[e["work-pools"]]),r=l.useMemo(()=>new Set(ne(e.tags??"")),[e.tags]),u=l.useMemo(()=>({range:e.range,start:e.start,end:e.end}),[e.range,e.start,e.end]),c=l.useCallback(g=>{const p=Array.from(g);t({to:".",search:w=>({...w,state:p.length>0?p.join(","):"",page:1}),replace:!0})},[t]),d=l.useCallback(g=>{const p=Array.from(g);t({to:".",search:w=>({...w,flows:p.length>0?p.join(","):"",page:1}),replace:!0})},[t]),f=l.useCallback(g=>{const p=Array.from(g);t({to:".",search:w=>({...w,deployments:p.length>0?p.join(","):"",page:1}),replace:!0})},[t]),m=l.useCallback(g=>{const p=Array.from(g);t({to:".",search:w=>({...w,"work-pools":p.length>0?p.join(","):"",page:1}),replace:!0})},[t]),h=l.useCallback(g=>{const p=Array.from(g);t({to:".",search:w=>({...w,tags:p.length>0?p.join(","):"",page:1}),replace:!0})},[t]),x=l.useCallback(g=>{t({to:".",search:p=>({...p,range:g.range,start:g.start,end:g.end,page:1}),replace:!0})},[t]),S=l.useMemo(()=>n.size>0||a.size>0||o.size>0||i.size>0||r.size>0||u.range!==void 0||u.start!==void 0||u.end!==void 0,[n,a,o,i,r,u]),y=l.useCallback(()=>{t({to:".",search:g=>({...g,state:"",flows:"",deployments:"","work-pools":"",tags:"",range:void 0,start:void 0,end:void 0,page:1}),replace:!0})},[t]);return{states:n,flows:a,deployments:o,workPools:i,tags:r,dateRange:u,onStatesChange:c,onFlowsChange:d,onDeploymentsChange:f,onWorkPoolsChange:m,onTagsChange:h,onDateRangeChange:x,clearAllFilters:y,hasActiveFilters:S}}Ke({tab:se(["flow-runs","task-runs"]).optional().default("flow-runs"),page:ae().int().positive().optional().default(1).catch(1),limit:ae().int().positive().optional().catch(void 0),sort:se(Jt).optional().default("START_TIME_DESC"),"hide-subflows":bs().optional().default(!1),"flow-run-search":_().optional().default(""),state:_().optional().default(""),flows:_().optional().default(""),deployments:_().optional().default(""),"work-pools":_().optional().default(""),tags:_().optional().default(""),range:se(Kt).optional(),start:_().optional(),end:_().optional(),"task-runs-page":ae().int().positive().optional().default(1).catch(1),"task-runs-limit":ae().int().positive().optional().catch(void 0),"task-runs-sort":se(Xt).optional().default("EXPECTED_START_TIME_DESC"),"task-run-search":_().optional().default("")});const Te=e=>e?e.split(",").filter(t=>Ge.includes(t)):[],ue=e=>{if(!e)return;const t={range:e.range,start:e.start,end:e.end},n=Ye(t);if(!n)return;const a=Gt(n);if(a)return{after_:a.startDate.toISOString(),before_:a.endDate.toISOString()}},De=e=>e?e.split(",").filter(t=>t.trim().length>0):[],_e=e=>e?e.split(",").filter(t=>t.trim().length>0):[],nt=e=>e?e.split(",").filter(t=>t.trim().length>0):[],Ne=e=>e?e.split(",").filter(t=>t.trim().length>0):[],Ue=e=>{const t=e?.["hide-subflows"],n=e?.["flow-run-search"],a=Te(e?.state??""),o=De(e?.flows??""),i=_e(e?.deployments??""),r=nt(e?.["work-pools"]??""),u=Ne(e?.tags??""),c=ue(e),d=a.length>0?a:void 0,f=o.length>0?o:void 0,m=i.length>0?i:void 0,h=r.length>0?r:void 0,S=t||n||d||f||m||u.length>0||c?{operator:"and_",...t&&{parent_task_run_id:{operator:"and_",is_null_:!0}},...n&&{name:{like_:n}},...d&&{state:{operator:"and_",name:{any_:d}}},...u.length>0&&{tags:{operator:"and_",any_:u}},...c&&{expected_start_time:c}}:void 0,y=f?{operator:"and_",id:{any_:f}}:void 0,g=m?{operator:"and_",id:{any_:m}}:void 0,p=h?{operator:"and_",name:{any_:h}}:void 0;return{page:e?.page??1,limit:e?.limit??100,sort:e?.sort??"START_TIME_DESC",flow_runs:S,flows:y,deployments:g,work_pools:p}},Qe=e=>{const t=e?.["task-run-search"],n=Te(e?.state??""),a=De(e?.flows??""),o=_e(e?.deployments??""),i=Ne(e?.tags??""),r=ue(e),u=t?{operator:"and_",name:{like_:t}}:void 0,c=n.length>0?n:void 0,f=c||i.length>0||r?{operator:"and_",...c&&{state:{operator:"and_",name:{any_:c}}},...i.length>0&&{tags:{operator:"and_",any_:i}},...r&&{expected_start_time:r}}:void 0,m=a.length>0?a:void 0,h=m?{operator:"and_",id:{any_:m}}:void 0,x=o.length>0?o:void 0,S=x?{operator:"and_",id:{any_:x}}:void 0;return{page:e?.["task-runs-page"]??1,limit:e?.["task-runs-limit"]??100,sort:e?.["task-runs-sort"]??"EXPECTED_START_TIME_DESC",task_runs:u,flow_runs:f,flows:h,deployments:S}},ca=e=>{const t=e?.["hide-subflows"],n=Te(e?.state??""),a=De(e?.flows??""),o=_e(e?.deployments??""),i=nt(e?.["work-pools"]??""),r=Ne(e?.tags??""),u=ue(e),c=n.length>0?n:void 0,d=a.length>0?a:void 0,f=o.length>0?o:void 0,m=i.length>0?i:void 0;return{sort:"EXPECTED_START_TIME_DESC",limit:1e3,offset:0,flow_runs:t||c||r.length>0||u?{operator:"and_",...t&&{parent_task_run_id:{operator:"and_",is_null_:!0}},...c&&{state:{operator:"and_",name:{any_:c}}},...r.length>0&&{tags:{operator:"and_",any_:r}},...u&&{expected_start_time:u}}:void 0,flows:d?{operator:"and_",id:{any_:d}}:void 0,deployments:f?{operator:"and_",id:{any_:f}}:void 0,work_pools:m?{operator:"and_",name:{any_:m}}:void 0}},ua=()=>{const e=j.useSearch(),t=j.useNavigate(),n=l.useMemo(()=>({page:e.page??1,limit:e.limit??100}),[e.page,e.limit]),a=l.useCallback(o=>{t({to:".",search:i=>({...i,page:o.page,limit:o.limit}),replace:!0})},[t]);return[n,a]},da=()=>{const e=j.useSearch(),t=j.useNavigate(),n=l.useCallback(a=>{t({to:".",search:o=>({...o,sort:a,page:1}),replace:!0})},[t]);return[e.sort,n]},ma=()=>{const e=j.useSearch(),t=j.useNavigate(),n=l.useCallback(a=>{t({to:".",search:o=>({...o,"hide-subflows":a,page:1}),replace:!0})},[t]);return[e["hide-subflows"],n]},fa=()=>{const e=j.useSearch(),t=j.useNavigate(),n=l.useCallback(a=>{t({to:".",search:o=>({...o,tab:a,page:1}),replace:!0})},[t]);return[e.tab,n]},ga=()=>{const e=j.useSearch(),t=j.useNavigate(),n=l.useCallback(a=>{t({to:".",search:o=>({...o,"flow-run-search":a,page:1}),replace:!0})},[t]);return[e["flow-run-search"],n]},ha=()=>{const e=j.useSearch(),t=j.useNavigate(),n=l.useMemo(()=>({page:e["task-runs-page"]??1,limit:e["task-runs-limit"]??100}),[e["task-runs-page"],e["task-runs-limit"]]),a=l.useCallback(o=>{t({to:".",search:i=>({...i,"task-runs-page":o.page,"task-runs-limit":o.limit}),replace:!0})},[t]);return[n,a]},pa=()=>{const e=j.useSearch(),t=j.useNavigate(),n=l.useCallback(a=>{t({to:".",search:o=>({...o,"task-runs-sort":a,"task-runs-page":1}),replace:!0})},[t]);return[e["task-runs-sort"],n]},xa=()=>{const e=j.useSearch(),t=j.useNavigate(),n=l.useCallback(a=>{t({to:".",search:o=>({...o,"task-run-search":a,"task-runs-page":1}),replace:!0})},[t]);return[e["task-run-search"],n]};function La(){const e=ot(),t=j.useSearch(),n=j.useNavigate(),[a,o]=ie("workspace-flow-runs-list-limit",100),[i,r]=ie("workspace-task-runs-list-limit",100),u=l.useRef(!1);l.useEffect(()=>{if(u.current)return;u.current=!0;const C=t.limit===void 0,D=t["task-runs-limit"]===void 0;(C||D)&&n({to:".",search:Z=>({...Z,...C&&{limit:a},...D&&{"task-runs-limit":i}}),replace:!0})},[n,t.limit,t["task-runs-limit"],a,i]),l.useEffect(()=>{t.limit!==void 0&&t.limit!==a&&o(t.limit)},[t.limit,a,o]),l.useEffect(()=>{t["task-runs-limit"]!==void 0&&t["task-runs-limit"]!==i&&r(t["task-runs-limit"])},[t["task-runs-limit"],i,r]);const[c,d]=ua(),[f,m]=da(),[h,x]=ma(),[S,y]=fa(),[g,p]=ga(),{states:w,flows:k,deployments:b,workPools:F,tags:N,dateRange:A,onStatesChange:v,onFlowsChange:W,onDeploymentsChange:H,onWorkPoolsChange:P,onTagsChange:B,onDateRangeChange:M}=ia(),[T,I]=ha(),[L,U]=pa(),[z,Q]=xa(),{currentFilter:de,savedFiltersForMenu:me,onSelectFilter:fe,onSaveFilter:ge,onDeleteFilter:he,onSetDefault:X,onRemoveDefault:pe,isSaveDialogOpen:xe,closeSaveDialog:we,confirmSave:Se}=oa();ra();const[{data:ve},{data:ke}]=rt({queries:[$t(),Yt()]}),{data:$}=E(Le(Ue(t),3e4)),{data:Y}=E(ze(Qe(t),3e4)),{data:ye}=E(qt(ca(t),3e4)),q=$?.results??[],K=Y?.results??[],Fe=l.useMemo(()=>{const C=ue(t);return{startDate:C?.after_?new Date(C.after_):void 0,endDate:C?.before_?new Date(C.before_):void 0}},[t]);l.useEffect(()=>{const C=q.map(D=>D.id);C.length>0&&e.prefetchQuery(Oe(C))},[e,q]);const je=l.useCallback(C=>{const D=Ue({...t,page:C});(async()=>{const G=(await e.ensureQueryData(Le(D,3e4)))?.results?.map(R=>R.id)??[];G.length>0&&e.prefetchQuery(Oe(G))})()},[e,t]),J=l.useCallback(C=>{const D=Qe({...t,"task-runs-page":C});e.prefetchQuery(ze(D,3e4))},[e,t]),Ce=l.useCallback(()=>{Q("")},[Q]);return s.jsx(sa,{tab:S,onTabChange:y,flowRunsCount:$?.count??0,taskRunsCount:Y?.count??0,hasAnyFlowRuns:(ve??0)>0,hasAnyTaskRuns:(ke??0)>0,flowRuns:q,flowRunsPages:$?.pages??0,pagination:c,onPaginationChange:d,onPrefetchPage:je,sort:f,onSortChange:m,hideSubflows:h,onHideSubflowsChange:x,flowRunSearch:g,onFlowRunSearchChange:p,selectedStates:w,onStateFilterChange:v,selectedFlows:k,onFlowFilterChange:W,selectedDeployments:b,onDeploymentFilterChange:H,selectedTags:N,onTagsFilterChange:B,selectedWorkPools:F,onWorkPoolFilterChange:P,dateRange:A,onDateRangeChange:M,flowRunHistory:ye??[],scatterPlotDateRange:Fe,taskRuns:K,taskRunsPages:Y?.pages??0,taskRunsPagination:T,onTaskRunsPaginationChange:I,onTaskRunsPrefetchPage:J,taskRunsSort:L,onTaskRunsSortChange:U,taskRunSearch:z,onTaskRunSearchChange:Q,onClearTaskRunFilters:Ce,currentFilter:de,savedFilters:me,onSelectFilter:fe,onSaveFilter:ge,onDeleteFilter:he,onSetDefault:X,onRemoveDefault:pe,isSaveDialogOpen:xe,onCloseSaveDialog:we,onConfirmSave:Se})}export{La as component};
|
|
2
|
-
//# sourceMappingURL=index-BkiGTHwU.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-BkiGTHwU.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/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","import { useQuery } from \"@tanstack/react-query\";\nimport { Link } from \"@tanstack/react-router\";\nimport { formatDistanceStrict } from \"date-fns\";\nimport humanizeDuration from \"humanize-duration\";\nimport { Calendar, ChevronRight, Clock } from \"lucide-react\";\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport {\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\";\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 getStateColor for dynamic color mode support\n\tconst color =\n\t\tgetStateColor(payload.stateType) ||\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={6}\n\t\t\tfill={color}\n\t\t\tstroke={color}\n\t\t\tstrokeWidth={1}\n\t\t\topacity={0.7}\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\nconst createYAxisTickFormatter = (maxDuration: number) => {\n\treturn (value: number): string => {\n\t\tif (value === 0) return \"0s\";\n\t\t// For very small durations (< 1 second), show milliseconds\n\t\tif (maxDuration < 1) {\n\t\t\treturn `${Math.round(value * 1000)}ms`;\n\t\t}\n\t\t// For small durations (< 10 seconds), show one decimal\n\t\tif (maxDuration < 10) {\n\t\t\treturn `${value.toFixed(1)}s`;\n\t\t}\n\t\t// For durations < 60 seconds, show integer seconds\n\t\tif (maxDuration < 60) {\n\t\t\treturn `${Math.round(value)}s`;\n\t\t}\n\t\t// For larger durations, use the humanized format\n\t\treturn formatDistanceStrict(0, value * 1000, { addSuffix: false });\n\t};\n};\n\nconst createXAxisTickFormatter = (rangeMs: number, minDeltaMs: number) => {\n\tconst oneMinute = 60 * 1000;\n\tconst oneHour = 60 * oneMinute;\n\tconst oneDay = 24 * oneHour;\n\n\treturn (value: number): string => {\n\t\tconst date = new Date(value);\n\n\t\t// If data points are very close (< 1 second apart) or range is very small, show with fractional seconds\n\t\tif (minDeltaMs < 1000 || rangeMs < 10_000) {\n\t\t\tconst seconds = date.getSeconds();\n\t\t\tconst ms = date.getMilliseconds();\n\t\t\tconst timeStr = date.toLocaleTimeString(undefined, {\n\t\t\t\thour: \"2-digit\",\n\t\t\t\tminute: \"2-digit\",\n\t\t\t});\n\t\t\t// Append seconds and tenths of a second\n\t\t\treturn `${timeStr}:${seconds.toString().padStart(2, \"0\")}.${Math.floor(ms / 100)}`;\n\t\t}\n\n\t\t// If data points are within a minute apart or range is small, show with seconds\n\t\tif (minDeltaMs < oneMinute || rangeMs < 10 * oneMinute) {\n\t\t\treturn date.toLocaleTimeString(undefined, {\n\t\t\t\thour: \"2-digit\",\n\t\t\t\tminute: \"2-digit\",\n\t\t\t\tsecond: \"2-digit\",\n\t\t\t});\n\t\t}\n\n\t\t// For multi-day ranges, show date on day boundaries (midnight) and time otherwise\n\t\t// This follows the Vue implementation pattern from formatLabel\n\t\tif (rangeMs >= oneDay) {\n\t\t\t// Check if this tick falls on a day boundary (midnight)\n\t\t\tconst isStartOfDay =\n\t\t\t\tdate.getHours() === 0 &&\n\t\t\t\tdate.getMinutes() === 0 &&\n\t\t\t\tdate.getSeconds() === 0 &&\n\t\t\t\tdate.getMilliseconds() === 0;\n\n\t\t\tif (isStartOfDay) {\n\t\t\t\t// Show date for day boundaries (e.g., \"Mon 15\" or \"Dec 15\")\n\t\t\t\treturn date.toLocaleDateString(undefined, {\n\t\t\t\t\tweekday: \"short\",\n\t\t\t\t\tday: \"numeric\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Show time for non-boundary ticks\n\t\t\treturn date.toLocaleTimeString(undefined, {\n\t\t\t\thour: \"2-digit\",\n\t\t\t\tminute: \"2-digit\",\n\t\t\t});\n\t\t}\n\n\t\t// If range is less than a day, show time (hours and minutes)\n\t\treturn date.toLocaleTimeString(undefined, {\n\t\t\thour: \"2-digit\",\n\t\t\tminute: \"2-digit\",\n\t\t});\n\t};\n};\n\nexport const FlowRunsScatterPlot = ({\n\thistory,\n\tstartDate,\n\tendDate,\n}: FlowRunsScatterPlotProps) => {\n\tconst containerRef = useRef<HTMLDivElement>(null);\n\tconst [containerWidth, setContainerWidth] = useState(0);\n\n\t// Track container width for dynamic tick count calculation\n\tuseEffect(() => {\n\t\tconst container = containerRef.current;\n\t\tif (!container) return;\n\n\t\tconst resizeObserver = new ResizeObserver((entries) => {\n\t\t\tfor (const entry of entries) {\n\t\t\t\tsetContainerWidth(entry.contentRect.width);\n\t\t\t}\n\t\t});\n\n\t\tresizeObserver.observe(container);\n\t\t// Set initial width\n\t\tsetContainerWidth(container.getBoundingClientRect().width);\n\n\t\treturn () => resizeObserver.disconnect();\n\t}, []);\n\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 (needed for adaptive formatting)\n\tconst { xDomain, xDomainMin, xDomainMax } = useMemo(() => {\n\t\tif (startDate && endDate) {\n\t\t\treturn {\n\t\t\t\txDomain: [startDate.getTime(), endDate.getTime()] as [number, number],\n\t\t\t\txDomainMin: startDate.getTime(),\n\t\t\t\txDomainMax: endDate.getTime(),\n\t\t\t};\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 {\n\t\t\t\txDomain: [dayAgo, now] as [number, number],\n\t\t\t\txDomainMin: dayAgo,\n\t\t\t\txDomainMax: now,\n\t\t\t};\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 {\n\t\t\txDomain: [min, max] as [number, number],\n\t\t\txDomainMin: min,\n\t\t\txDomainMax: max,\n\t\t};\n\t}, [startDate, endDate, chartData]);\n\n\t// Compute max duration for adaptive y-axis formatting\n\tconst maxDuration = useMemo(() => {\n\t\tif (chartData.length === 0) return 60;\n\t\treturn Math.max(...chartData.map((d) => d.y));\n\t}, [chartData]);\n\n\t// Compute minimum delta between data points for adaptive x-axis formatting\n\tconst minDeltaMs = useMemo(() => {\n\t\tif (chartData.length < 2) return Number.POSITIVE_INFINITY;\n\t\tconst sortedTimestamps = chartData.map((d) => d.x).sort((a, b) => a - b);\n\t\tlet minDelta = Number.POSITIVE_INFINITY;\n\t\tfor (let i = 1; i < sortedTimestamps.length; i++) {\n\t\t\tconst delta = sortedTimestamps[i] - sortedTimestamps[i - 1];\n\t\t\tif (delta > 0 && delta < minDelta) {\n\t\t\t\tminDelta = delta;\n\t\t\t}\n\t\t}\n\t\treturn minDelta;\n\t}, [chartData]);\n\n\t// Create memoized formatters based on domain\n\tconst rangeMs = xDomainMax - xDomainMin;\n\tconst formatXAxisTick = useMemo(\n\t\t() => createXAxisTickFormatter(rangeMs, minDeltaMs),\n\t\t[rangeMs, minDeltaMs],\n\t);\n\n\tconst formatYAxisTick = useMemo(\n\t\t() => createYAxisTickFormatter(maxDuration),\n\t\t[maxDuration],\n\t);\n\n\t// Calculate explicit tick values for evenly spaced x-axis ticks\n\t// Target ~100px spacing between ticks for visually even distribution\n\t// For multi-day ranges, include midnight boundaries to show day changes\n\tconst xAxisTicks = useMemo(() => {\n\t\tconst tickSpacing = 100; // pixels between ticks\n\t\tconst chartMargin = 60; // left (40) + right (20) margins from ScatterChart\n\t\tconst availableWidth = containerWidth - chartMargin;\n\t\tconst tickCount = Math.max(2, Math.ceil(availableWidth / tickSpacing));\n\n\t\tconst oneDay = 24 * 60 * 60 * 1000;\n\t\tconst rangeMs = xDomainMax - xDomainMin;\n\n\t\t// For multi-day ranges, generate ticks that include midnight boundaries\n\t\tif (rangeMs >= oneDay) {\n\t\t\tconst ticks: number[] = [];\n\n\t\t\t// Find the first midnight after xDomainMin\n\t\t\tconst startDate = new Date(xDomainMin);\n\t\t\tconst firstMidnight = new Date(startDate);\n\t\t\tfirstMidnight.setHours(24, 0, 0, 0); // Next midnight\n\n\t\t\t// Add start tick\n\t\t\tticks.push(xDomainMin);\n\n\t\t\t// Add midnight boundaries\n\t\t\tlet currentMidnight = firstMidnight.getTime();\n\t\t\twhile (currentMidnight < xDomainMax) {\n\t\t\t\tticks.push(currentMidnight);\n\t\t\t\tcurrentMidnight += oneDay;\n\t\t\t}\n\n\t\t\t// Add end tick if not too close to last tick\n\t\t\tconst lastTick = ticks[ticks.length - 1];\n\t\t\tif (xDomainMax - lastTick > rangeMs / tickCount / 2) {\n\t\t\t\tticks.push(xDomainMax);\n\t\t\t}\n\n\t\t\t// If we have too few ticks, add intermediate ticks between midnights\n\t\t\tif (ticks.length < tickCount) {\n\t\t\t\tconst newTicks: number[] = [];\n\t\t\t\tfor (let i = 0; i < ticks.length - 1; i++) {\n\t\t\t\t\tnewTicks.push(ticks[i]);\n\t\t\t\t\tconst gap = ticks[i + 1] - ticks[i];\n\t\t\t\t\tconst intermediateCount = Math.max(\n\t\t\t\t\t\t1,\n\t\t\t\t\t\tMath.floor(gap / (rangeMs / tickCount)),\n\t\t\t\t\t);\n\t\t\t\t\tif (intermediateCount > 1) {\n\t\t\t\t\t\tconst intermediateStep = gap / intermediateCount;\n\t\t\t\t\t\tfor (let j = 1; j < intermediateCount; j++) {\n\t\t\t\t\t\t\tnewTicks.push(ticks[i] + intermediateStep * j);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tnewTicks.push(ticks[ticks.length - 1]);\n\t\t\t\treturn newTicks;\n\t\t\t}\n\n\t\t\treturn ticks;\n\t\t}\n\n\t\t// For single-day ranges, generate evenly spaced ticks\n\t\tconst ticks: number[] = [];\n\t\tconst step = (xDomainMax - xDomainMin) / (tickCount - 1);\n\t\tfor (let i = 0; i < tickCount; i++) {\n\t\t\tticks.push(xDomainMin + step * i);\n\t\t}\n\t\treturn ticks;\n\t}, [containerWidth, xDomainMin, xDomainMax]);\n\n\tif (history.length === 0) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<div\n\t\t\tref={containerRef}\n\t\t\tclassName=\"hidden md:block w-full h-64\"\n\t\t\tdata-testid=\"scatter-plot\"\n\t\t>\n\t\t\t<ResponsiveContainer width=\"100%\" height=\"100%\">\n\t\t\t\t<ScatterChart>\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","CustomDot","cx","cy","payload","color","getStateColor","STATE_COLORS","FlowRunTooltip","active","data","flowRunId","flowRun","buildGetFlowRunDetailsQuery","buildFLowDetailsQuery","startTime","Link","ChevronRight","StateBadge","Clock","humanizeDuration","Calendar","createYAxisTickFormatter","maxDuration","formatDistanceStrict","createXAxisTickFormatter","rangeMs","minDeltaMs","date","seconds","ms","FlowRunsScatterPlot","history","startDate","endDate","containerRef","useRef","containerWidth","setContainerWidth","useEffect","container","resizeObserver","entries","entry","chartData","item","xDomain","xDomainMin","xDomainMax","now","dayAgo","timestamps","d","min","max","sortedTimestamps","a","b","minDelta","i","delta","formatXAxisTick","formatYAxisTick","xAxisTicks","availableWidth","tickCount","oneDay","ticks","firstMidnight","currentMidnight","lastTick","newTicks","gap","intermediateCount","intermediateStep","j","step","ResponsiveContainer","ScatterChart","XAxis","YAxis","Tooltip","Scatter","formSchema","z.object","z.string","SaveFilterDialog","open","onOpenChange","form","useForm","zodResolver","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","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","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","range","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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"}
|