prefect 3.6.16.dev5__py3-none-any.whl → 3.6.16.dev6__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/_build_info.py +3 -3
- prefect/cli/__init__.py +1 -0
- prefect/cli/cloud/asset.py +135 -0
- prefect/server/ui-v2/assets/artifact-card-BnPKAfkY.js +2 -0
- prefect/server/ui-v2/assets/artifact-card-BnPKAfkY.js.map +1 -0
- prefect/server/ui-v2/assets/artifact._id-vDOuIuta.js +2 -0
- prefect/server/ui-v2/assets/artifact._id-vDOuIuta.js.map +1 -0
- prefect/server/ui-v2/assets/automation-wizard-RlOhF90R.js +2 -0
- prefect/server/ui-v2/assets/automation-wizard-RlOhF90R.js.map +1 -0
- prefect/server/ui-v2/assets/automation._id-CEHa-X0X.js +2 -0
- prefect/server/ui-v2/assets/{automation._id-CMiura1b.js.map → automation._id-CEHa-X0X.js.map} +1 -1
- prefect/server/ui-v2/assets/{automation_._id.edit-Cbfcwa-K.js → automation_._id.edit-BRWAsELa.js} +2 -2
- prefect/server/ui-v2/assets/{automation_._id.edit-Cbfcwa-K.js.map → automation_._id.edit-BRWAsELa.js.map} +1 -1
- prefect/server/ui-v2/assets/{automations-header-BxPCOE-0.js → automations-header-Dr6v5dPp.js} +2 -2
- prefect/server/ui-v2/assets/{automations-header-BxPCOE-0.js.map → automations-header-Dr6v5dPp.js.map} +1 -1
- prefect/server/ui-v2/assets/base-job-template-form-section-C8_R96gO.js +2 -0
- prefect/server/ui-v2/assets/base-job-template-form-section-C8_R96gO.js.map +1 -0
- prefect/server/ui-v2/assets/block-type-details-tAkUWqs1.js +2 -0
- prefect/server/ui-v2/assets/block-type-details-tAkUWqs1.js.map +1 -0
- prefect/server/ui-v2/assets/block-type-logo-scnMsyY5.js +2 -0
- prefect/server/ui-v2/assets/{block-type-logo-DuvU7goV.js.map → block-type-logo-scnMsyY5.js.map} +1 -1
- prefect/server/ui-v2/assets/block._id-BY42cyjR.js +2 -0
- prefect/server/ui-v2/assets/block._id-BY42cyjR.js.map +1 -0
- prefect/server/ui-v2/assets/{block_._id.edit-C4SmoQ4y.js → block_._id.edit-n2jwU5yr.js} +2 -2
- prefect/server/ui-v2/assets/{block_._id.edit-C4SmoQ4y.js.map → block_._id.edit-n2jwU5yr.js.map} +1 -1
- prefect/server/ui-v2/assets/catalog-5_GoCKpb.js +2 -0
- prefect/server/ui-v2/assets/catalog-5_GoCKpb.js.map +1 -0
- prefect/server/ui-v2/assets/catalog_._slug-sZvt0fDy.js +2 -0
- prefect/server/ui-v2/assets/catalog_._slug-sZvt0fDy.js.map +1 -0
- prefect/server/ui-v2/assets/{catalog_._slug_.create-CgKL4TS2.js → catalog_._slug_.create-rboQmoyW.js} +2 -2
- prefect/server/ui-v2/assets/{catalog_._slug_.create-CgKL4TS2.js.map → catalog_._slug_.create-rboQmoyW.js.map} +1 -1
- prefect/server/ui-v2/assets/{collapsible-DZbPzSgr.js → collapsible-Lk7MRvBH.js} +2 -2
- prefect/server/ui-v2/assets/{collapsible-DZbPzSgr.js.map → collapsible-Lk7MRvBH.js.map} +1 -1
- prefect/server/ui-v2/assets/concurrency-limit._id-D5i9zZJh.js +2 -0
- prefect/server/ui-v2/assets/concurrency-limit._id-D5i9zZJh.js.map +1 -0
- prefect/server/ui-v2/assets/create-CtsA2QIl.js +2 -0
- prefect/server/ui-v2/assets/{create-BrNwbpVu.js.map → create-CtsA2QIl.js.map} +1 -1
- prefect/server/ui-v2/assets/{create-DWgkh2HT.js → create-DJPAEZ93.js} +2 -2
- prefect/server/ui-v2/assets/create-DJPAEZ93.js.map +1 -0
- prefect/server/ui-v2/assets/{data-table-QSHqmTar.js → data-table-bk-0xKWT.js} +2 -2
- prefect/server/ui-v2/assets/{data-table-QSHqmTar.js.map → data-table-bk-0xKWT.js.map} +1 -1
- prefect/server/ui-v2/assets/{delete-confirmation-dialog-dLycVNo4.js → delete-confirmation-dialog-BZg9EOfN.js} +2 -2
- prefect/server/ui-v2/assets/{delete-confirmation-dialog-dLycVNo4.js.map → delete-confirmation-dialog-BZg9EOfN.js.map} +1 -1
- prefect/server/ui-v2/assets/{deployment-action-header-CzvBTL6H.js → deployment-action-header-DwuMPgVg.js} +2 -2
- prefect/server/ui-v2/assets/{deployment-action-header-CzvBTL6H.js.map → deployment-action-header-DwuMPgVg.js.map} +1 -1
- prefect/server/ui-v2/assets/deployment-form-BpKkzEf2.js +3 -0
- prefect/server/ui-v2/assets/deployment-form-BpKkzEf2.js.map +1 -0
- prefect/server/ui-v2/assets/{deployment-links-CGjJpxJA.js → deployment-links-B67P-6Ph.js} +2 -2
- prefect/server/ui-v2/assets/{deployment-links-CGjJpxJA.js.map → deployment-links-B67P-6Ph.js.map} +1 -1
- prefect/server/ui-v2/assets/{deployment._id-DXrb6frJ.js → deployment._id-BVOBfMVf.js} +2 -2
- prefect/server/ui-v2/assets/deployment._id-BVOBfMVf.js.map +1 -0
- prefect/server/ui-v2/assets/deployment._id-KOMC9fpE.js +2 -0
- prefect/server/ui-v2/assets/deployment._id-KOMC9fpE.js.map +1 -0
- prefect/server/ui-v2/assets/deployment_._id.duplicate-BPk2SchT.js +2 -0
- prefect/server/ui-v2/assets/deployment_._id.duplicate-BPk2SchT.js.map +1 -0
- prefect/server/ui-v2/assets/deployment_._id.edit-Dv0M_huv.js +2 -0
- prefect/server/ui-v2/assets/deployment_._id.edit-Dv0M_huv.js.map +1 -0
- prefect/server/ui-v2/assets/deployment_._id.run-DFVA4Xhx.js +2 -0
- prefect/server/ui-v2/assets/{deployment_._id.run-CnacOmhY.js.map → deployment_._id.run-DFVA4Xhx.js.map} +1 -1
- prefect/server/ui-v2/assets/{dropdown-menu-B9LKPlz7.js → dropdown-menu-fRiq5bS-.js} +2 -2
- prefect/server/ui-v2/assets/{dropdown-menu-B9LKPlz7.js.map → dropdown-menu-fRiq5bS-.js.map} +1 -1
- prefect/server/ui-v2/assets/{event-resource-display-B42RIaiX.js → event-resource-display-C1ZAey-o.js} +2 -2
- prefect/server/ui-v2/assets/{event-resource-display-B42RIaiX.js.map → event-resource-display-C1ZAey-o.js.map} +1 -1
- prefect/server/ui-v2/assets/event._eventDate._eventId-CcbtP9Ag.js +2 -0
- prefect/server/ui-v2/assets/{event._eventDate._eventId-CKTuT_8S.js.map → event._eventDate._eventId-CcbtP9Ag.js.map} +1 -1
- prefect/server/ui-v2/assets/flow-run-graph-CycKStSg.js +2 -0
- prefect/server/ui-v2/assets/flow-run-graph-CycKStSg.js.map +1 -0
- prefect/server/ui-v2/assets/{flow-run._id-BKv9Meqc.js → flow-run._id-Dn9R_Tjy.js} +2 -2
- prefect/server/ui-v2/assets/flow-run._id-Dn9R_Tjy.js.map +1 -0
- prefect/server/ui-v2/assets/{flow-run._id-ZTkjj6bM.js → flow-run._id-Dwx7ojcj.js} +2 -2
- prefect/server/ui-v2/assets/flow-run._id-Dwx7ojcj.js.map +1 -0
- prefect/server/ui-v2/assets/flow-run._id-YzRd5jrC.js +4 -0
- prefect/server/ui-v2/assets/flow-run._id-YzRd5jrC.js.map +1 -0
- prefect/server/ui-v2/assets/flow-runs-pagination-DMLZFM1m.js +2 -0
- prefect/server/ui-v2/assets/flow-runs-pagination-DMLZFM1m.js.map +1 -0
- prefect/server/ui-v2/assets/flow._id-V6-Qhkwk.js +2 -0
- prefect/server/ui-v2/assets/flow._id-V6-Qhkwk.js.map +1 -0
- prefect/server/ui-v2/assets/{form-DOdmIC3A.js → form-Cl5Hk9bq.js} +2 -2
- prefect/server/ui-v2/assets/{form-DOdmIC3A.js.map → form-Cl5Hk9bq.js.map} +1 -1
- prefect/server/ui-v2/assets/{header-DcIuN5UN.js → header-BuI436ik.js} +2 -2
- prefect/server/ui-v2/assets/{header-DcIuN5UN.js.map → header-BuI436ik.js.map} +1 -1
- prefect/server/ui-v2/assets/{header-CnBwASd-.js → header-DcAQCxQl.js} +2 -2
- prefect/server/ui-v2/assets/{header-CnBwASd-.js.map → header-DcAQCxQl.js.map} +1 -1
- prefect/server/ui-v2/assets/{header-DxE-NzAK.js → header-qlcK4NLD.js} +2 -2
- prefect/server/ui-v2/assets/{header-DxE-NzAK.js.map → header-qlcK4NLD.js.map} +1 -1
- prefect/server/ui-v2/assets/index--Z69UYXV.js +2 -0
- prefect/server/ui-v2/assets/index--Z69UYXV.js.map +1 -0
- prefect/server/ui-v2/assets/{index-D0R9_LIL.js → index-BO4Qqsm8.js} +2 -2
- prefect/server/ui-v2/assets/index-BO4Qqsm8.js.map +1 -0
- prefect/server/ui-v2/assets/index-Bg45XS_V.js +2 -0
- prefect/server/ui-v2/assets/index-Bg45XS_V.js.map +1 -0
- prefect/server/ui-v2/assets/{index-BIBIJufF.js → index-BleYpDoN.js} +2 -2
- prefect/server/ui-v2/assets/index-BleYpDoN.js.map +1 -0
- prefect/server/ui-v2/assets/{index-DyOAqIOp.js → index-C63VUjOh.js} +2 -2
- prefect/server/ui-v2/assets/{index-DyOAqIOp.js.map → index-C63VUjOh.js.map} +1 -1
- prefect/server/ui-v2/assets/{index-DfKXdmko.js → index-C6LgWyJb.js} +2 -2
- prefect/server/ui-v2/assets/index-C6LgWyJb.js.map +1 -0
- prefect/server/ui-v2/assets/index-CE-bVgqj.js +2 -0
- prefect/server/ui-v2/assets/{index-DlAHvqFx.js.map → index-CE-bVgqj.js.map} +1 -1
- prefect/server/ui-v2/assets/{index-V_xTKaEb.js → index-CPpeVt8m.js} +13 -13
- prefect/server/ui-v2/assets/index-CPpeVt8m.js.map +1 -0
- prefect/server/ui-v2/assets/index-CYaUe0Ym.js +2 -0
- prefect/server/ui-v2/assets/index-CYaUe0Ym.js.map +1 -0
- prefect/server/ui-v2/assets/{index-C5RMFRyZ.js → index-Clbms0kg.js} +2 -2
- prefect/server/ui-v2/assets/index-Clbms0kg.js.map +1 -0
- prefect/server/ui-v2/assets/index-D13YFoYA.js +2 -0
- prefect/server/ui-v2/assets/index-D13YFoYA.js.map +1 -0
- prefect/server/ui-v2/assets/{index-Cx1qEoCK.js → index-D73a_nGu.js} +2 -2
- prefect/server/ui-v2/assets/{index-Cx1qEoCK.js.map → index-D73a_nGu.js.map} +1 -1
- prefect/server/ui-v2/assets/index-DJXBzX1E.css +1 -0
- prefect/server/ui-v2/assets/{index-BO60ehN6.js → index-DPPPaOr_.js} +2 -2
- prefect/server/ui-v2/assets/index-DPPPaOr_.js.map +1 -0
- prefect/server/ui-v2/assets/{index-DP8W-xJo.js → index-DU9ShbqW.js} +2 -2
- prefect/server/ui-v2/assets/index-DU9ShbqW.js.map +1 -0
- prefect/server/ui-v2/assets/index-DdR1lzZk.js +2 -0
- prefect/server/ui-v2/assets/index-DdR1lzZk.js.map +1 -0
- prefect/server/ui-v2/assets/{index-B9ttjsyu.js → index-ELo08q04.js} +2 -2
- prefect/server/ui-v2/assets/{index-B9ttjsyu.js.map → index-ELo08q04.js.map} +1 -1
- prefect/server/ui-v2/assets/{index-BTL1xHS9.js → index-cp6PTdHp.js} +2 -2
- prefect/server/ui-v2/assets/{index-BTL1xHS9.js.map → index-cp6PTdHp.js.map} +1 -1
- prefect/server/ui-v2/assets/{index-D6G96ToY.js → index-kM_g8J0u.js} +2 -2
- prefect/server/ui-v2/assets/{index-D6G96ToY.js.map → index-kM_g8J0u.js.map} +1 -1
- prefect/server/ui-v2/assets/{index-q5Y3hlDT.js → index-mYcm9Rkr.js} +2 -2
- prefect/server/ui-v2/assets/index-mYcm9Rkr.js.map +1 -0
- prefect/server/ui-v2/assets/{index-D9cOtoSU.js → index-yavn_NBp.js} +2 -2
- prefect/server/ui-v2/assets/index-yavn_NBp.js.map +1 -0
- prefect/server/ui-v2/assets/{json-input-YKJMJCcT.js → json-input-iUzf6BvZ.js} +2 -2
- prefect/server/ui-v2/assets/{json-input-YKJMJCcT.js.map → json-input-iUzf6BvZ.js.map} +1 -1
- prefect/server/ui-v2/assets/{key-value-RPUUqQ6F.js → key-value-DI27Dv4P.js} +2 -2
- prefect/server/ui-v2/assets/{key-value-RPUUqQ6F.js.map → key-value-DI27Dv4P.js.map} +1 -1
- prefect/server/ui-v2/assets/key._key-C-nk2nld.js +2 -0
- prefect/server/ui-v2/assets/key._key-C-nk2nld.js.map +1 -0
- prefect/server/ui-v2/assets/{lazy-markdown-B9vEkJ0h.js → lazy-markdown-D_y73qoD.js} +2 -2
- prefect/server/ui-v2/assets/{lazy-markdown-B9vEkJ0h.js.map → lazy-markdown-D_y73qoD.js.map} +1 -1
- prefect/server/ui-v2/assets/{login-C3PhSGQJ.js → login-DR_xuMmg.js} +2 -2
- prefect/server/ui-v2/assets/{login-C3PhSGQJ.js.map → login-DR_xuMmg.js.map} +1 -1
- prefect/server/ui-v2/assets/{markdown-input-Dei7u1qp.js → markdown-input-hzlzpUdj.js} +2 -2
- prefect/server/ui-v2/assets/{markdown-input-Dei7u1qp.js.map → markdown-input-hzlzpUdj.js.map} +1 -1
- prefect/server/ui-v2/assets/{python-example-snippet-DvulFxgw.js → python-example-snippet-d8bTNJ0J.js} +3 -3
- prefect/server/ui-v2/assets/{python-example-snippet-DvulFxgw.js.map → python-example-snippet-d8bTNJ0J.js.map} +1 -1
- prefect/server/ui-v2/assets/{python-input-niCawr8m.js → python-input-Bxdnzvx3.js} +2 -2
- prefect/server/ui-v2/assets/{python-input-niCawr8m.js.map → python-input-Bxdnzvx3.js.map} +1 -1
- prefect/server/ui-v2/assets/{radio-group-D55TQZsk.js → radio-group-0oOEMJCS.js} +2 -2
- prefect/server/ui-v2/assets/{radio-group-D55TQZsk.js.map → radio-group-0oOEMJCS.js.map} +1 -1
- prefect/server/ui-v2/assets/{route-error-state-Cu4m0LTX.js → route-error-state-BqbnZCc-.js} +2 -2
- prefect/server/ui-v2/assets/{route-error-state-Cu4m0LTX.js.map → route-error-state-BqbnZCc-.js.map} +1 -1
- prefect/server/ui-v2/assets/{schema-form-BQAcWW5k.js → schema-form-BD-WM4S0.js} +2 -2
- prefect/server/ui-v2/assets/{schema-form-BQAcWW5k.js.map → schema-form-BD-WM4S0.js.map} +1 -1
- prefect/server/ui-v2/assets/{schema-form-input-string-format-datetime-Cb4sTJle.js → schema-form-input-string-format-datetime-Dg3zVAp5.js} +4 -4
- prefect/server/ui-v2/assets/{schema-form-input-string-format-datetime-Cb4sTJle.js.map → schema-form-input-string-format-datetime-Dg3zVAp5.js.map} +1 -1
- prefect/server/ui-v2/assets/{settings-DV4ewZ_4.js → settings-Dm6yMLix.js} +2 -2
- prefect/server/ui-v2/assets/{settings-DV4ewZ_4.js.map → settings-Dm6yMLix.js.map} +1 -1
- prefect/server/ui-v2/assets/{sort-filter-DY7vgl7C.js → sort-filter-X6JyRc0-.js} +2 -2
- prefect/server/ui-v2/assets/{sort-filter-DY7vgl7C.js.map → sort-filter-X6JyRc0-.js.map} +1 -1
- prefect/server/ui-v2/assets/{table-ChOwO4Pk.js → table-Xyel2BEw.js} +2 -2
- prefect/server/ui-v2/assets/{table-ChOwO4Pk.js.map → table-Xyel2BEw.js.map} +1 -1
- prefect/server/ui-v2/assets/{tags-input-2KSBvO_K.js → tags-input-DqZ8v99z.js} +2 -2
- prefect/server/ui-v2/assets/{tags-input-2KSBvO_K.js.map → tags-input-DqZ8v99z.js.map} +1 -1
- prefect/server/ui-v2/assets/{task-run-concurrency-limits-reset-dialog-CNrP9yPQ.js → task-run-concurrency-limits-reset-dialog-5xFWeoYy.js} +2 -2
- prefect/server/ui-v2/assets/{task-run-concurrency-limits-reset-dialog-CNrP9yPQ.js.map → task-run-concurrency-limits-reset-dialog-5xFWeoYy.js.map} +1 -1
- prefect/server/ui-v2/assets/{task-run._id-cqXH0PMU.js → task-run._id-9DcrUEGz.js} +3 -3
- prefect/server/ui-v2/assets/{task-run._id-cqXH0PMU.js.map → task-run._id-9DcrUEGz.js.map} +1 -1
- prefect/server/ui-v2/assets/{task-run._id-CQGeAiBh.js → task-run._id-DJkoLl_e.js} +2 -2
- prefect/server/ui-v2/assets/task-run._id-DJkoLl_e.js.map +1 -0
- prefect/server/ui-v2/assets/task-runs-pagination-B2fSdB1t.js +2 -0
- prefect/server/ui-v2/assets/task-runs-pagination-B2fSdB1t.js.map +1 -0
- prefect/server/ui-v2/assets/{textarea-9v5uTuxg.js → textarea-DFEOJJdc.js} +2 -2
- prefect/server/ui-v2/assets/{textarea-9v5uTuxg.js.map → textarea-DFEOJJdc.js.map} +1 -1
- prefect/server/ui-v2/assets/{timezone-select-DPtR_b06.js → timezone-select-NViFNNLz.js} +2 -2
- prefect/server/ui-v2/assets/{timezone-select-DPtR_b06.js.map → timezone-select-NViFNNLz.js.map} +1 -1
- prefect/server/ui-v2/assets/{toggle-group-CBJphTE6.js → toggle-group-EMgSOoYH.js} +2 -2
- prefect/server/ui-v2/assets/{toggle-group-CBJphTE6.js.map → toggle-group-EMgSOoYH.js.map} +1 -1
- prefect/server/ui-v2/assets/use-delete-automation-confirmation-dialog-BHgDXlwg.js +2 -0
- prefect/server/ui-v2/assets/use-delete-automation-confirmation-dialog-BHgDXlwg.js.map +1 -0
- prefect/server/ui-v2/assets/{use-delete-block-document-confirmation-dialog-BYY1b8yH.js → use-delete-block-document-confirmation-dialog-CxRkBKPg.js} +2 -2
- prefect/server/ui-v2/assets/{use-delete-block-document-confirmation-dialog-BYY1b8yH.js.map → use-delete-block-document-confirmation-dialog-CxRkBKPg.js.map} +1 -1
- prefect/server/ui-v2/assets/use-flow-runs-selected-rows-Ck8nwx2q.js +2 -0
- prefect/server/ui-v2/assets/use-flow-runs-selected-rows-Ck8nwx2q.js.map +1 -0
- prefect/server/ui-v2/assets/{use-get-artifacts-flow-task-runs-BOTU5FPq.js → use-get-artifacts-flow-task-runs-D7Djt53s.js} +2 -2
- prefect/server/ui-v2/assets/{use-get-artifacts-flow-task-runs-BOTU5FPq.js.map → use-get-artifacts-flow-task-runs-D7Djt53s.js.map} +1 -1
- prefect/server/ui-v2/assets/{use-quick-run-DzSmbSlu.js → use-quick-run-Cpy0t7dX.js} +2 -2
- prefect/server/ui-v2/assets/{use-quick-run-DzSmbSlu.js.map → use-quick-run-Cpy0t7dX.js.map} +1 -1
- prefect/server/ui-v2/assets/{use-state-favicon-UFxhmhHr.js → use-state-favicon-CMsL9s6j.js} +2 -2
- prefect/server/ui-v2/assets/{use-state-favicon-UFxhmhHr.js.map → use-state-favicon-CMsL9s6j.js.map} +1 -1
- prefect/server/ui-v2/assets/use-stepper-CZZEx5js.js +2 -0
- prefect/server/ui-v2/assets/use-stepper-CZZEx5js.js.map +1 -0
- prefect/server/ui-v2/assets/{utilities-2FfCfMAV.js → utilities-D9BfvLg5.js} +2 -2
- prefect/server/ui-v2/assets/{utilities-2FfCfMAV.js.map → utilities-D9BfvLg5.js.map} +1 -1
- prefect/server/ui-v2/assets/work-pool-filter-dsJ6xeK6.js +2 -0
- prefect/server/ui-v2/assets/work-pool-filter-dsJ6xeK6.js.map +1 -0
- prefect/server/ui-v2/assets/{work-pool-queue-toggle-zSWhEFap.js → work-pool-queue-toggle-f_-cTWxB.js} +2 -2
- prefect/server/ui-v2/assets/{work-pool-queue-toggle-zSWhEFap.js.map → work-pool-queue-toggle-f_-cTWxB.js.map} +1 -1
- prefect/server/ui-v2/assets/{work-pool._workPoolName-BwIVfCIe.js → work-pool._workPoolName-zBqgkYLT.js} +2 -2
- prefect/server/ui-v2/assets/{work-pool._workPoolName-BwIVfCIe.js.map → work-pool._workPoolName-zBqgkYLT.js.map} +1 -1
- prefect/server/ui-v2/assets/{work-pool_._workPoolName.edit-j7cjgoJp.js → work-pool_._workPoolName.edit-B-8_CnfA.js} +2 -2
- prefect/server/ui-v2/assets/{work-pool_._workPoolName.edit-j7cjgoJp.js.map → work-pool_._workPoolName.edit-B-8_CnfA.js.map} +1 -1
- prefect/server/ui-v2/assets/{work-pool_._workPoolName.queue._workQueueName-BlFjSdoB.js → work-pool_._workPoolName.queue._workQueueName-DzrY1tMq.js} +2 -2
- prefect/server/ui-v2/assets/work-pool_._workPoolName.queue._workQueueName-DzrY1tMq.js.map +1 -0
- prefect/server/ui-v2/assets/{work-queue-icon-text-vWlRNW-b.js → work-queue-icon-text-BqqQ413o.js} +2 -2
- prefect/server/ui-v2/assets/{work-queue-icon-text-vWlRNW-b.js.map → work-queue-icon-text-BqqQ413o.js.map} +1 -1
- prefect/server/ui-v2/index.html +2 -2
- prefect/task_engine.py +26 -12
- prefect/workers/base.py +18 -1
- {prefect-3.6.16.dev5.dist-info → prefect-3.6.16.dev6.dist-info}/METADATA +1 -1
- {prefect-3.6.16.dev5.dist-info → prefect-3.6.16.dev6.dist-info}/RECORD +208 -207
- prefect/server/ui-v2/assets/artifact-card-DQfjRA2u.js +0 -2
- prefect/server/ui-v2/assets/artifact-card-DQfjRA2u.js.map +0 -1
- prefect/server/ui-v2/assets/artifact._id-BBhuX3px.js +0 -2
- prefect/server/ui-v2/assets/artifact._id-BBhuX3px.js.map +0 -1
- prefect/server/ui-v2/assets/automation-wizard-DeT-tz5i.js +0 -2
- prefect/server/ui-v2/assets/automation-wizard-DeT-tz5i.js.map +0 -1
- prefect/server/ui-v2/assets/automation._id-CMiura1b.js +0 -2
- prefect/server/ui-v2/assets/base-job-template-form-section-MeO0M71Y.js +0 -2
- prefect/server/ui-v2/assets/base-job-template-form-section-MeO0M71Y.js.map +0 -1
- prefect/server/ui-v2/assets/block-type-details-Bcb9qEO8.js +0 -2
- prefect/server/ui-v2/assets/block-type-details-Bcb9qEO8.js.map +0 -1
- prefect/server/ui-v2/assets/block-type-logo-DuvU7goV.js +0 -2
- prefect/server/ui-v2/assets/block._id-DFR6zmOy.js +0 -2
- prefect/server/ui-v2/assets/block._id-DFR6zmOy.js.map +0 -1
- prefect/server/ui-v2/assets/catalog-CPzaK8QS.js +0 -2
- prefect/server/ui-v2/assets/catalog-CPzaK8QS.js.map +0 -1
- prefect/server/ui-v2/assets/catalog_._slug-60h4tERz.js +0 -2
- prefect/server/ui-v2/assets/catalog_._slug-60h4tERz.js.map +0 -1
- prefect/server/ui-v2/assets/concurrency-limit._id-BFfR6_U0.js +0 -2
- prefect/server/ui-v2/assets/concurrency-limit._id-BFfR6_U0.js.map +0 -1
- prefect/server/ui-v2/assets/create-BrNwbpVu.js +0 -2
- prefect/server/ui-v2/assets/create-DWgkh2HT.js.map +0 -1
- prefect/server/ui-v2/assets/deployment-form-B33C7F2u.js +0 -3
- prefect/server/ui-v2/assets/deployment-form-B33C7F2u.js.map +0 -1
- prefect/server/ui-v2/assets/deployment._id-5rPcPD0T.js +0 -2
- prefect/server/ui-v2/assets/deployment._id-5rPcPD0T.js.map +0 -1
- prefect/server/ui-v2/assets/deployment._id-DXrb6frJ.js.map +0 -1
- prefect/server/ui-v2/assets/deployment_._id.duplicate-D7YLydeq.js +0 -2
- prefect/server/ui-v2/assets/deployment_._id.duplicate-D7YLydeq.js.map +0 -1
- prefect/server/ui-v2/assets/deployment_._id.edit-Daq0J0Ow.js +0 -2
- prefect/server/ui-v2/assets/deployment_._id.edit-Daq0J0Ow.js.map +0 -1
- prefect/server/ui-v2/assets/deployment_._id.run-CnacOmhY.js +0 -2
- prefect/server/ui-v2/assets/event._eventDate._eventId-CKTuT_8S.js +0 -2
- prefect/server/ui-v2/assets/flow-run-graph-OrT2Osbu.js +0 -2
- prefect/server/ui-v2/assets/flow-run-graph-OrT2Osbu.js.map +0 -1
- prefect/server/ui-v2/assets/flow-run._id-BKv9Meqc.js.map +0 -1
- prefect/server/ui-v2/assets/flow-run._id-DCYAnq0D.js +0 -4
- prefect/server/ui-v2/assets/flow-run._id-DCYAnq0D.js.map +0 -1
- prefect/server/ui-v2/assets/flow-run._id-ZTkjj6bM.js.map +0 -1
- prefect/server/ui-v2/assets/flow-runs-pagination-CykMKOhv.js +0 -2
- prefect/server/ui-v2/assets/flow-runs-pagination-CykMKOhv.js.map +0 -1
- prefect/server/ui-v2/assets/flow._id-DhrxqQmD.js +0 -2
- prefect/server/ui-v2/assets/flow._id-DhrxqQmD.js.map +0 -1
- prefect/server/ui-v2/assets/index-BIBIJufF.js.map +0 -1
- prefect/server/ui-v2/assets/index-BO60ehN6.js.map +0 -1
- prefect/server/ui-v2/assets/index-BS7fbJ2s.js +0 -2
- prefect/server/ui-v2/assets/index-BS7fbJ2s.js.map +0 -1
- prefect/server/ui-v2/assets/index-C5RMFRyZ.js.map +0 -1
- prefect/server/ui-v2/assets/index-D0R9_LIL.js.map +0 -1
- prefect/server/ui-v2/assets/index-D9cOtoSU.js.map +0 -1
- prefect/server/ui-v2/assets/index-DEpWUeaO.js +0 -2
- prefect/server/ui-v2/assets/index-DEpWUeaO.js.map +0 -1
- prefect/server/ui-v2/assets/index-DP8W-xJo.js.map +0 -1
- prefect/server/ui-v2/assets/index-DfKXdmko.js.map +0 -1
- prefect/server/ui-v2/assets/index-DiVKp6rW.js +0 -2
- prefect/server/ui-v2/assets/index-DiVKp6rW.js.map +0 -1
- prefect/server/ui-v2/assets/index-DlAHvqFx.js +0 -2
- prefect/server/ui-v2/assets/index-VNFzALsC.js +0 -2
- prefect/server/ui-v2/assets/index-VNFzALsC.js.map +0 -1
- prefect/server/ui-v2/assets/index-V_xTKaEb.js.map +0 -1
- prefect/server/ui-v2/assets/index-WIq8QUNT.js +0 -2
- prefect/server/ui-v2/assets/index-WIq8QUNT.js.map +0 -1
- prefect/server/ui-v2/assets/index-m9O-nIOl.css +0 -1
- prefect/server/ui-v2/assets/index-q5Y3hlDT.js.map +0 -1
- prefect/server/ui-v2/assets/key._key-CX8FwfwL.js +0 -2
- prefect/server/ui-v2/assets/key._key-CX8FwfwL.js.map +0 -1
- prefect/server/ui-v2/assets/task-run._id-CQGeAiBh.js.map +0 -1
- prefect/server/ui-v2/assets/task-runs-pagination-CYoOghEN.js +0 -2
- prefect/server/ui-v2/assets/task-runs-pagination-CYoOghEN.js.map +0 -1
- prefect/server/ui-v2/assets/use-delete-automation-confirmation-dialog-DZplMJDW.js +0 -2
- prefect/server/ui-v2/assets/use-delete-automation-confirmation-dialog-DZplMJDW.js.map +0 -1
- prefect/server/ui-v2/assets/use-flow-runs-selected-rows-1YE-VIgM.js +0 -2
- prefect/server/ui-v2/assets/use-flow-runs-selected-rows-1YE-VIgM.js.map +0 -1
- prefect/server/ui-v2/assets/use-stepper-CnGJHRLP.js +0 -2
- prefect/server/ui-v2/assets/use-stepper-CnGJHRLP.js.map +0 -1
- prefect/server/ui-v2/assets/work-pool-filter-CGfXNujK.js +0 -2
- prefect/server/ui-v2/assets/work-pool-filter-CGfXNujK.js.map +0 -1
- prefect/server/ui-v2/assets/work-pool_._workPoolName.queue._workQueueName-BlFjSdoB.js.map +0 -1
- {prefect-3.6.16.dev5.dist-info → prefect-3.6.16.dev6.dist-info}/WHEEL +0 -0
- {prefect-3.6.16.dev5.dist-info → prefect-3.6.16.dev6.dist-info}/entry_points.txt +0 -0
- {prefect-3.6.16.dev5.dist-info → prefect-3.6.16.dev6.dist-info}/licenses/LICENSE +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"flow._id-DhrxqQmD.js","sources":["../../src/components/flows/detail/delete-flow-dialog.tsx","../../src/components/flows/detail/mini-deployment-activity.tsx","../../src/components/flows/detail/deployment-columns.tsx","../../src/components/flows/detail/flow-deployments-tab.tsx","../../src/components/flows/detail/flow-details.tsx","../../src/components/flows/detail/flow-menu.tsx","../../src/components/flows/detail/flow-page-header.tsx","../../src/components/flows/detail/flow-stats-summary/cumulative-task-runs-card.tsx","../../src/components/flows/detail/flow-stats-summary/flow-runs-history-card.tsx","../../src/components/flows/detail/flow-stats-summary/index.tsx","../../src/components/flows/detail/index.tsx","../../src/routes/flows/flow.$id.tsx?tsr-split=component"],"sourcesContent":["import { useNavigate } from \"@tanstack/react-router\";\nimport { toast } from \"sonner\";\nimport type { Flow } from \"@/api/flows\";\nimport { useDeleteFlowById } from \"@/api/flows\";\nimport { DeleteConfirmationDialog } from \"@/components/ui/delete-confirmation-dialog\";\n\ntype DeleteFlowDialogProps = {\n\tflow: Flow;\n\topen: boolean;\n\tonOpenChange: (open: boolean) => void;\n\tonDeleted?: () => void;\n};\n\nexport const DeleteFlowDialog = ({\n\tflow,\n\topen,\n\tonOpenChange,\n\tonDeleted,\n}: DeleteFlowDialogProps) => {\n\tconst navigate = useNavigate();\n\tconst { deleteFlow, isPending } = useDeleteFlowById();\n\n\tconst handleDelete = () => {\n\t\tdeleteFlow(flow.id, {\n\t\t\tonSuccess: () => {\n\t\t\t\ttoast.success(\"Flow deleted\");\n\t\t\t\tonDeleted?.();\n\t\t\t\tvoid navigate({ to: \"/flows\" });\n\t\t\t},\n\t\t\tonError: () => {\n\t\t\t\ttoast.error(\"Failed to delete flow\");\n\t\t\t},\n\t\t});\n\t};\n\n\treturn (\n\t\t<DeleteConfirmationDialog\n\t\t\tisOpen={open}\n\t\t\ttitle=\"Delete Flow\"\n\t\t\tdescription={`Are you sure you want to delete ${flow.name}? This action cannot be undone.`}\n\t\t\tisLoading={isPending}\n\t\t\tloadingText=\"Deleting...\"\n\t\t\tonConfirm={handleDelete}\n\t\t\tonClose={() => onOpenChange(false)}\n\t\t/>\n\t);\n};\n","import { useQuery } from \"@tanstack/react-query\";\nimport { subSeconds } from \"date-fns\";\nimport { secondsInWeek } from \"date-fns/constants\";\nimport { useCallback, useState } from \"react\";\nimport { buildFilterFlowRunsQuery } from \"@/api/flow-runs\";\nimport { FlowRunActivityBarChart } from \"@/components/ui/flow-run-activity-bar-graph\";\nimport useDebounce from \"@/hooks/use-debounce\";\n\nconst BAR_WIDTH = 4;\nconst BAR_GAP = 2;\n\ninterface MiniDeploymentActivityProps {\n\tdeploymentId: string;\n}\n\nexport const MiniDeploymentActivity = ({\n\tdeploymentId,\n}: MiniDeploymentActivityProps) => {\n\tconst [numberOfBars, setNumberOfBars] = useState<number>(0);\n\tconst debouncedNumberOfBars = useDebounce(numberOfBars, 150);\n\n\tconst chartRef = useCallback((node: HTMLDivElement | null) => {\n\t\tif (!node) return;\n\n\t\tconst updateBars = () => {\n\t\t\tconst chartWidth = node.getBoundingClientRect().width;\n\t\t\tsetNumberOfBars(Math.floor(chartWidth / (BAR_WIDTH + BAR_GAP)));\n\t\t};\n\n\t\tupdateBars();\n\n\t\tconst resizeObserver = new ResizeObserver(updateBars);\n\t\tresizeObserver.observe(node);\n\t\treturn () => {\n\t\t\tresizeObserver.disconnect();\n\t\t};\n\t}, []);\n\n\tconst effectiveNumberOfBars = debouncedNumberOfBars || numberOfBars;\n\n\tconst { data: flowRuns } = useQuery(\n\t\tbuildFilterFlowRunsQuery({\n\t\t\tdeployments: {\n\t\t\t\toperator: \"and_\",\n\t\t\t\tid: { any_: [deploymentId] },\n\t\t\t},\n\t\t\tlimit: Math.min(60, effectiveNumberOfBars || 60),\n\t\t\tsort: \"START_TIME_DESC\",\n\t\t\toffset: 0,\n\t\t}),\n\t);\n\n\tconst enrichedFlowRuns =\n\t\tflowRuns?.map((flowRun) => ({\n\t\t\t...flowRun,\n\t\t})) ?? [];\n\n\treturn (\n\t\t<div className=\"w-full\" ref={chartRef}>\n\t\t\t<FlowRunActivityBarChart\n\t\t\t\tenrichedFlowRuns={enrichedFlowRuns}\n\t\t\t\tstartDate={subSeconds(new Date(), secondsInWeek)}\n\t\t\t\tendDate={new Date()}\n\t\t\t\tbarWidth={BAR_WIDTH}\n\t\t\t\tnumberOfBars={effectiveNumberOfBars}\n\t\t\t\tclassName=\"h-8 w-full\"\n\t\t\t\tchartId={`deployment-${deploymentId}`}\n\t\t\t/>\n\t\t</div>\n\t);\n};\n","import type { ColumnDef } from \"@tanstack/react-table\";\nimport type { components } from \"@/api/prefect\";\nimport { Button } from \"@/components/ui/button\";\nimport { Checkbox } from \"@/components/ui/checkbox\";\nimport {\n\tDropdownMenu,\n\tDropdownMenuContent,\n\tDropdownMenuItem,\n\tDropdownMenuTrigger,\n} from \"@/components/ui/dropdown-menu\";\nimport { Icon } from \"@/components/ui/icons\";\nimport { ScheduleBadgeGroup } from \"@/components/ui/schedule-badge\";\nimport { StatusBadge } from \"@/components/ui/status-badge\";\nimport { MiniDeploymentActivity } from \"./mini-deployment-activity\";\n\ntype Deployment = components[\"schemas\"][\"DeploymentResponse\"];\n\nexport const columns: ColumnDef<Deployment>[] = [\n\t{\n\t\tid: \"select\",\n\t\theader: ({ table }) => (\n\t\t\t<Checkbox\n\t\t\t\tchecked={table.getIsAllPageRowsSelected()}\n\t\t\t\tonCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}\n\t\t\t\taria-label=\"Select all\"\n\t\t\t/>\n\t\t),\n\t\tcell: ({ row }) => (\n\t\t\t<Checkbox\n\t\t\t\tchecked={row.getIsSelected()}\n\t\t\t\tonCheckedChange={(value) => row.toggleSelected(!!value)}\n\t\t\t\taria-label=\"Select row\"\n\t\t\t/>\n\t\t),\n\t\tenableSorting: false,\n\t\tenableHiding: false,\n\t\tmaxSize: 20,\n\t\tminSize: 20,\n\t},\n\t{\n\t\taccessorKey: \"name\",\n\t\theader: \"Name\",\n\t\tcell: ({ row }) => row.original.name,\n\t},\n\t{\n\t\taccessorKey: \"status\",\n\t\theader: \"Status\",\n\t\tcell: ({ row }) => {\n\t\t\tconst status = row.original.paused\n\t\t\t\t? \"PAUSED\"\n\t\t\t\t: (row.original.status ?? \"NOT_READY\");\n\t\t\treturn <StatusBadge status={status} />;\n\t\t},\n\t},\n\t{\n\t\taccessorKey: \"tags\",\n\t\theader: \"Tags\",\n\t\tcell: ({ row }) => (\n\t\t\t<div className=\"flex flex-wrap gap-1\">\n\t\t\t\t{row.original.tags?.map((tag) => (\n\t\t\t\t\t<span\n\t\t\t\t\t\tkey={tag}\n\t\t\t\t\t\tclassName=\"bg-gray-100 text-gray-800 text-xs font-medium px-2 py-0.5 rounded\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{tag}\n\t\t\t\t\t</span>\n\t\t\t\t))}\n\t\t\t</div>\n\t\t),\n\t},\n\t{\n\t\taccessorKey: \"schedules\",\n\t\theader: \"Schedules\",\n\t\tcell: ({ row }) => {\n\t\t\tconst schedules = row.original.schedules;\n\t\t\tif (!schedules || schedules.length === 0) return null;\n\t\t\treturn <ScheduleBadgeGroup schedules={schedules} />;\n\t\t},\n\t\tsize: 150,\n\t},\n\t{\n\t\taccessorKey: \"activity\",\n\t\theader: \"Activity\",\n\t\tcell: ({ row }) => {\n\t\t\tif (!row.original.id) return null;\n\t\t\treturn <MiniDeploymentActivity deploymentId={row.original.id} />;\n\t\t},\n\t},\n\t{\n\t\tid: \"actions\",\n\t\tcell: ({ row }) => {\n\t\t\tif (!row.original.id) return null;\n\n\t\t\treturn (\n\t\t\t\t<DropdownMenu>\n\t\t\t\t\t<DropdownMenuTrigger asChild>\n\t\t\t\t\t\t<Button variant=\"ghost\" className=\"size-8 p-0\">\n\t\t\t\t\t\t\t<span className=\"sr-only\">Open menu</span>\n\t\t\t\t\t\t\t<Icon id=\"MoreHorizontal\" className=\"size-4\" />\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</DropdownMenuTrigger>\n\t\t\t\t\t<DropdownMenuContent align=\"end\">\n\t\t\t\t\t\t<DropdownMenuItem\n\t\t\t\t\t\t\tonClick={() =>\n\t\t\t\t\t\t\t\tvoid navigator.clipboard.writeText(row.original.id)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tCopy ID\n\t\t\t\t\t\t</DropdownMenuItem>\n\t\t\t\t\t</DropdownMenuContent>\n\t\t\t\t</DropdownMenu>\n\t\t\t);\n\t\t},\n\t\tminSize: 30,\n\t\tmaxSize: 30,\n\t},\n];\n","import type { OnChangeFn, PaginationState } from \"@tanstack/react-table\";\nimport {\n\tgetCoreRowModel,\n\ttype RowSelectionState,\n\tuseReactTable,\n} from \"@tanstack/react-table\";\nimport { Trash2 } from \"lucide-react\";\nimport type { ChangeEvent } from \"react\";\nimport { useCallback, useState } from \"react\";\nimport { useDeleteDeployment } from \"@/api/deployments\";\nimport type { components } from \"@/api/prefect\";\nimport { Button } from \"@/components/ui/button\";\nimport { DataTable } from \"@/components/ui/data-table\";\nimport {\n\tDialog,\n\tDialogContent,\n\tDialogDescription,\n\tDialogFooter,\n\tDialogHeader,\n\tDialogTitle,\n} from \"@/components/ui/dialog\";\nimport { FlowRunActivityBarGraphTooltipProvider } from \"@/components/ui/flow-run-activity-bar-graph\";\nimport { SearchInput } from \"@/components/ui/input\";\nimport {\n\tSelect,\n\tSelectContent,\n\tSelectItem,\n\tSelectTrigger,\n\tSelectValue,\n} from \"@/components/ui/select\";\nimport { TagsInput } from \"@/components/ui/tags-input\";\nimport { Typography } from \"@/components/ui/typography\";\nimport { columns as baseDeploymentColumns } from \"./deployment-columns\";\n\ntype DeploymentSort = components[\"schemas\"][\"DeploymentSort\"];\n\nconst SORT_OPTIONS: { label: string; value: DeploymentSort }[] = [\n\t{ label: \"Created\", value: \"CREATED_DESC\" },\n\t{ label: \"A to Z\", value: \"NAME_ASC\" },\n\t{ label: \"Z to A\", value: \"NAME_DESC\" },\n];\n\ntype FlowDeploymentsTabProps = {\n\tdeployments: components[\"schemas\"][\"DeploymentResponse\"][];\n\tdeploymentsCount: number;\n\tdeploymentsPages: number;\n\tdeploymentSearch: string | undefined;\n\tonDeploymentSearchChange: (search: string) => void;\n\tdeploymentTags: string[];\n\tonDeploymentTagsChange: (tags: string[]) => void;\n\tdeploymentSort: DeploymentSort;\n\tonDeploymentSortChange: (sort: DeploymentSort) => void;\n\tdeploymentPagination: { page: number; limit: number };\n\tonDeploymentPaginationChange: (pagination: {\n\t\tpage: number;\n\t\tlimit: number;\n\t}) => void;\n};\n\nexport const FlowDeploymentsTab = ({\n\tdeployments,\n\tdeploymentsCount,\n\tdeploymentsPages,\n\tdeploymentSearch,\n\tonDeploymentSearchChange,\n\tdeploymentTags,\n\tonDeploymentTagsChange,\n\tdeploymentSort,\n\tonDeploymentSortChange,\n\tdeploymentPagination,\n\tonDeploymentPaginationChange,\n}: FlowDeploymentsTabProps) => {\n\tconst [rowSelection, setRowSelection] = useState<RowSelectionState>({});\n\tconst [showDeleteDialog, setShowDeleteDialog] = useState(false);\n\tconst { deleteDeployment } = useDeleteDeployment();\n\n\tconst handlePaginationChange: OnChangeFn<PaginationState> = useCallback(\n\t\t(updater) => {\n\t\t\tconst currentPagination: PaginationState = {\n\t\t\t\tpageIndex: deploymentPagination.page - 1,\n\t\t\t\tpageSize: deploymentPagination.limit,\n\t\t\t};\n\t\t\tconst newPagination =\n\t\t\t\ttypeof updater === \"function\" ? updater(currentPagination) : updater;\n\t\t\tonDeploymentPaginationChange({\n\t\t\t\tpage: newPagination.pageIndex + 1,\n\t\t\t\tlimit: newPagination.pageSize,\n\t\t\t});\n\t\t\tsetRowSelection({});\n\t\t},\n\t\t[deploymentPagination, onDeploymentPaginationChange],\n\t);\n\n\tconst deploymentsTable = useReactTable({\n\t\tdata: deployments,\n\t\tcolumns: baseDeploymentColumns,\n\t\tgetCoreRowModel: getCoreRowModel(),\n\t\tmanualPagination: true,\n\t\tpageCount: deploymentsPages,\n\t\tstate: {\n\t\t\trowSelection,\n\t\t\tpagination: {\n\t\t\t\tpageIndex: deploymentPagination.page - 1,\n\t\t\t\tpageSize: deploymentPagination.limit,\n\t\t\t},\n\t\t},\n\t\tonRowSelectionChange: setRowSelection,\n\t\tonPaginationChange: handlePaginationChange,\n\t\tgetRowId: (row) => row.id,\n\t});\n\n\tconst selectedCount = Object.keys(rowSelection).length;\n\n\tconst handleDeleteSelected = useCallback(() => {\n\t\tconst selectedIds = Object.keys(rowSelection);\n\t\tfor (const id of selectedIds) {\n\t\t\tdeleteDeployment(id);\n\t\t}\n\t\tsetRowSelection({});\n\t\tsetShowDeleteDialog(false);\n\t}, [rowSelection, deleteDeployment]);\n\n\tconst handleDeploymentTagsChange: React.ChangeEventHandler<HTMLInputElement> &\n\t\t((tags: string[]) => void) = useCallback(\n\t\t(e: string[] | ChangeEvent<HTMLInputElement>) => {\n\t\t\tif (Array.isArray(e)) {\n\t\t\t\tonDeploymentTagsChange(e);\n\t\t\t}\n\t\t},\n\t\t[onDeploymentTagsChange],\n\t);\n\n\treturn (\n\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t<div className=\"grid grid-cols-12 items-center gap-2\">\n\t\t\t\t{/* Count and selection info - first column */}\n\t\t\t\t<div className=\"flex flex-col gap-1 xl:col-span-3 md:col-span-12 col-span-6 md:order-0 order-3\">\n\t\t\t\t\t{selectedCount > 0 ? (\n\t\t\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t\t\t<Typography variant=\"bodySmall\" className=\"text-muted-foreground\">\n\t\t\t\t\t\t\t\t{selectedCount} selected\n\t\t\t\t\t\t\t</Typography>\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\t\tclassName=\"h-6 w-6 text-destructive hover:text-destructive\"\n\t\t\t\t\t\t\t\tonClick={() => setShowDeleteDialog(true)}\n\t\t\t\t\t\t\t\taria-label=\"Delete selected deployments\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Trash2 className=\"h-4 w-4\" />\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<Typography variant=\"bodySmall\" className=\"text-muted-foreground\">\n\t\t\t\t\t\t\t{deploymentsCount} Deployment{deploymentsCount !== 1 ? \"s\" : \"\"}\n\t\t\t\t\t\t</Typography>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\n\t\t\t\t{/* Controls - middle columns */}\n\t\t\t\t<div className=\"xl:col-span-4 md:col-span-6 col-span-12 md:order-1 order-0\">\n\t\t\t\t\t<SearchInput\n\t\t\t\t\t\tplaceholder=\"Search deployments...\"\n\t\t\t\t\t\tvalue={deploymentSearch ?? \"\"}\n\t\t\t\t\t\tonChange={(e) => onDeploymentSearchChange(e.target.value)}\n\t\t\t\t\t\taria-label=\"Search deployments\"\n\t\t\t\t\t\tdebounceMs={300}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t\t<div className=\"xl:col-span-3 md:col-span-6 col-span-12 md:order-2 order-1\">\n\t\t\t\t\t<TagsInput\n\t\t\t\t\t\tplaceholder=\"Filter by tags\"\n\t\t\t\t\t\tvalue={deploymentTags}\n\t\t\t\t\t\tonChange={handleDeploymentTagsChange}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\n\t\t\t\t{/* Sort - last column with left border on desktop */}\n\t\t\t\t<div className=\"xl:border-l xl:border-border xl:pl-2 xl:col-span-2 md:col-span-6 col-span-6 md:order-3 order-2\">\n\t\t\t\t\t<Select\n\t\t\t\t\t\tvalue={deploymentSort}\n\t\t\t\t\t\tonValueChange={(value) =>\n\t\t\t\t\t\t\tonDeploymentSortChange(value as DeploymentSort)\n\t\t\t\t\t\t}\n\t\t\t\t\t>\n\t\t\t\t\t\t<SelectTrigger className=\"w-full\" aria-label=\"Sort deployments\">\n\t\t\t\t\t\t\t<SelectValue placeholder=\"Sort by\" />\n\t\t\t\t\t\t</SelectTrigger>\n\t\t\t\t\t\t<SelectContent>\n\t\t\t\t\t\t\t{SORT_OPTIONS.map((option) => (\n\t\t\t\t\t\t\t\t<SelectItem key={option.value} value={option.value}>\n\t\t\t\t\t\t\t\t\t{option.label}\n\t\t\t\t\t\t\t\t</SelectItem>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</SelectContent>\n\t\t\t\t\t</Select>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<FlowRunActivityBarGraphTooltipProvider>\n\t\t\t\t{/* Override table container overflow to allow chart tooltips to escape */}\n\t\t\t\t<div className=\"[&_[data-slot=table-container]]:overflow-visible\">\n\t\t\t\t\t<DataTable table={deploymentsTable} />\n\t\t\t\t</div>\n\t\t\t</FlowRunActivityBarGraphTooltipProvider>\n\n\t\t\t<Dialog open={showDeleteDialog} onOpenChange={setShowDeleteDialog}>\n\t\t\t\t<DialogContent>\n\t\t\t\t\t<DialogHeader>\n\t\t\t\t\t\t<DialogTitle>Delete Deployments</DialogTitle>\n\t\t\t\t\t\t<DialogDescription>\n\t\t\t\t\t\t\tAre you sure you want to delete {selectedCount} deployment\n\t\t\t\t\t\t\t{selectedCount !== 1 ? \"s\" : \"\"}? This action cannot be undone.\n\t\t\t\t\t\t</DialogDescription>\n\t\t\t\t\t</DialogHeader>\n\t\t\t\t\t<DialogFooter>\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\t\tonClick={() => setShowDeleteDialog(false)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tCancel\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t<Button variant=\"destructive\" onClick={handleDeleteSelected}>\n\t\t\t\t\t\t\tDelete\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</DialogFooter>\n\t\t\t\t</DialogContent>\n\t\t\t</Dialog>\n\t\t</div>\n\t);\n};\n","import type { Flow } from \"@/api/flows\";\nimport { FormattedDate } from \"@/components/ui/formatted-date\";\n\ntype FlowDetailsProps = {\n\tflow: Flow;\n};\n\nexport const FlowDetails = ({ flow }: FlowDetailsProps) => {\n\treturn (\n\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t<dl className=\"flex flex-col gap-2\">\n\t\t\t\t<dt className=\"text-muted-foreground\">Flow ID</dt>\n\t\t\t\t<dd className=\"text-sm font-medium leading-none font-mono\">\n\t\t\t\t\t{flow.id}\n\t\t\t\t</dd>\n\t\t\t</dl>\n\t\t\t<dl className=\"flex flex-col gap-2\">\n\t\t\t\t<dt className=\"text-muted-foreground\">Created</dt>\n\t\t\t\t<dd className=\"text-sm font-medium leading-none font-mono\">\n\t\t\t\t\t{flow.created ? (\n\t\t\t\t\t\t<FormattedDate date={flow.created} format=\"absolute\" />\n\t\t\t\t\t) : (\n\t\t\t\t\t\t\"N/A\"\n\t\t\t\t\t)}\n\t\t\t\t</dd>\n\t\t\t</dl>\n\t\t\t<dl className=\"flex flex-col gap-2\">\n\t\t\t\t<dt className=\"text-muted-foreground\">Updated</dt>\n\t\t\t\t<dd className=\"text-sm font-medium leading-none font-mono\">\n\t\t\t\t\t{flow.updated ? (\n\t\t\t\t\t\t<FormattedDate date={flow.updated} format=\"absolute\" />\n\t\t\t\t\t) : (\n\t\t\t\t\t\t\"N/A\"\n\t\t\t\t\t)}\n\t\t\t\t</dd>\n\t\t\t</dl>\n\t\t</div>\n\t);\n};\n","import { toast } from \"sonner\";\nimport type { Flow } from \"@/api/flows\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n\tDropdownMenu,\n\tDropdownMenuContent,\n\tDropdownMenuItem,\n\tDropdownMenuLabel,\n\tDropdownMenuTrigger,\n} from \"@/components/ui/dropdown-menu\";\nimport { Icon } from \"@/components/ui/icons\";\n\nexport type FlowMenuProps = {\n\tflow: Flow;\n\tonDelete: () => void;\n};\n\nexport const FlowMenu = ({ flow, onDelete }: FlowMenuProps) => {\n\tconst handleCopyId = () => {\n\t\tvoid navigator.clipboard.writeText(flow.id);\n\t\ttoast.success(\"ID copied\");\n\t};\n\n\treturn (\n\t\t<DropdownMenu>\n\t\t\t<DropdownMenuTrigger asChild>\n\t\t\t\t<Button variant=\"outline\" className=\"size-8 p-0\">\n\t\t\t\t\t<span className=\"sr-only\">Open menu</span>\n\t\t\t\t\t<Icon id=\"MoreVertical\" className=\"size-4\" />\n\t\t\t\t</Button>\n\t\t\t</DropdownMenuTrigger>\n\t\t\t<DropdownMenuContent align=\"end\">\n\t\t\t\t<DropdownMenuLabel>Actions</DropdownMenuLabel>\n\t\t\t\t<DropdownMenuItem onClick={handleCopyId}>Copy ID</DropdownMenuItem>\n\t\t\t\t<DropdownMenuItem variant=\"destructive\" onClick={onDelete}>\n\t\t\t\t\tDelete\n\t\t\t\t</DropdownMenuItem>\n\t\t\t</DropdownMenuContent>\n\t\t</DropdownMenu>\n\t);\n};\n","import type { Flow } from \"@/api/flows\";\nimport {\n\tBreadcrumb,\n\tBreadcrumbItem,\n\tBreadcrumbLink,\n\tBreadcrumbList,\n\tBreadcrumbPage,\n\tBreadcrumbSeparator,\n} from \"@/components/ui/breadcrumb\";\nimport { FlowMenu } from \"./flow-menu\";\n\ntype FlowPageHeaderProps = {\n\tflow: Flow;\n\tonDelete: () => void;\n};\n\nexport function FlowPageHeader({ flow, onDelete }: FlowPageHeaderProps) {\n\treturn (\n\t\t<div className=\"flex items-center justify-between\">\n\t\t\t<Breadcrumb>\n\t\t\t\t<BreadcrumbList>\n\t\t\t\t\t<BreadcrumbItem>\n\t\t\t\t\t\t<BreadcrumbLink to=\"/flows\" className=\"text-xl font-semibold\">\n\t\t\t\t\t\t\tFlows\n\t\t\t\t\t\t</BreadcrumbLink>\n\t\t\t\t\t</BreadcrumbItem>\n\t\t\t\t\t<BreadcrumbSeparator />\n\t\t\t\t\t<BreadcrumbItem className=\"text-xl font-semibold\">\n\t\t\t\t\t\t<BreadcrumbPage>{flow.name}</BreadcrumbPage>\n\t\t\t\t\t</BreadcrumbItem>\n\t\t\t\t</BreadcrumbList>\n\t\t\t</Breadcrumb>\n\t\t\t<FlowMenu flow={flow} onDelete={onDelete} />\n\t\t</div>\n\t);\n}\n","import { useSuspenseQueries } from \"@tanstack/react-query\";\nimport { useMemo } from \"react\";\nimport { Area, AreaChart } from \"recharts\";\nimport {\n\tbuildCountTaskRunsQuery,\n\tbuildTaskRunsHistoryQuery,\n\ttype HistoryResponse,\n} from \"@/api/task-runs\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"@/components/ui/card\";\nimport { type ChartConfig, ChartContainer } from \"@/components/ui/chart\";\nimport {\n\tbuildCompletedTaskRunsCountFilter,\n\tbuildFailedTaskRunsCountFilter,\n\tbuildRunningTaskRunsCountFilter,\n\tbuildTaskRunsHistoryFilterForFlow,\n\tbuildTotalTaskRunsCountFilter,\n} from \"./query-filters\";\n\nconst REFETCH_INTERVAL = 30_000;\n\ntype CumulativeTaskRunsCardProps = {\n\tflowId: string;\n};\n\ntype ChartDataPoint = {\n\ttimestamp: string;\n\tcompleted: number;\n\tfailed: number;\n};\n\nconst chartConfig = {\n\tcompleted: {\n\t\tlabel: \"Completed\",\n\t\tcolor: \"hsl(142.1 76.2% 36.3%)\",\n\t},\n\tfailed: {\n\t\tlabel: \"Failed\",\n\t\tcolor: \"hsl(0 84.2% 60.2%)\",\n\t},\n} satisfies ChartConfig;\n\nconst transformHistoryToChartData = (\n\thistory: HistoryResponse[],\n): ChartDataPoint[] => {\n\tconst chartData: ChartDataPoint[] = [];\n\tlet cumulativeCompleted = 0;\n\tlet cumulativeFailed = 0;\n\n\tfor (const item of history) {\n\t\tlet completedCount = 0;\n\t\tlet failedCount = 0;\n\n\t\tfor (const state of item.states) {\n\t\t\tif (state.state_type === \"COMPLETED\") {\n\t\t\t\tcompletedCount += state.count_runs;\n\t\t\t} else if (\n\t\t\t\tstate.state_type === \"FAILED\" ||\n\t\t\t\tstate.state_type === \"CRASHED\"\n\t\t\t) {\n\t\t\t\tfailedCount += state.count_runs;\n\t\t\t}\n\t\t}\n\n\t\tcumulativeCompleted += completedCount;\n\t\tcumulativeFailed += failedCount;\n\n\t\tchartData.push({\n\t\t\ttimestamp: item.interval_start,\n\t\t\tcompleted: cumulativeCompleted,\n\t\t\tfailed: cumulativeFailed,\n\t\t});\n\t}\n\n\treturn chartData;\n};\n\nexport function CumulativeTaskRunsCard({\n\tflowId,\n}: CumulativeTaskRunsCardProps) {\n\tconst [\n\t\t{ data: total },\n\t\t{ data: completed },\n\t\t{ data: failed },\n\t\t{ data: running },\n\t\t{ data: history },\n\t] = useSuspenseQueries({\n\t\tqueries: [\n\t\t\tbuildCountTaskRunsQuery(\n\t\t\t\tbuildTotalTaskRunsCountFilter(flowId),\n\t\t\t\tREFETCH_INTERVAL,\n\t\t\t),\n\t\t\tbuildCountTaskRunsQuery(\n\t\t\t\tbuildCompletedTaskRunsCountFilter(flowId),\n\t\t\t\tREFETCH_INTERVAL,\n\t\t\t),\n\t\t\tbuildCountTaskRunsQuery(\n\t\t\t\tbuildFailedTaskRunsCountFilter(flowId),\n\t\t\t\tREFETCH_INTERVAL,\n\t\t\t),\n\t\t\tbuildCountTaskRunsQuery(\n\t\t\t\tbuildRunningTaskRunsCountFilter(flowId),\n\t\t\t\tREFETCH_INTERVAL,\n\t\t\t),\n\t\t\tbuildTaskRunsHistoryQuery(\n\t\t\t\tbuildTaskRunsHistoryFilterForFlow(flowId),\n\t\t\t\tREFETCH_INTERVAL,\n\t\t\t),\n\t\t],\n\t});\n\n\tconst chartData = useMemo(\n\t\t() => transformHistoryToChartData(history),\n\t\t[history],\n\t);\n\n\tconst hasFailedData = chartData.some((point) => point.failed > 0);\n\n\tconst percentComparisonTotal = total - running;\n\tconst completedPercentage =\n\t\tpercentComparisonTotal > 0\n\t\t\t? ((completed / percentComparisonTotal) * 100).toFixed(0)\n\t\t\t: \"0\";\n\tconst failedPercentage =\n\t\tpercentComparisonTotal > 0\n\t\t\t? ((failed / percentComparisonTotal) * 100).toFixed(1)\n\t\t\t: \"0\";\n\n\treturn (\n\t\t<Card className=\"flex-1 relative overflow-hidden pb-20\">\n\t\t\t<CardHeader className=\"pb-2\">\n\t\t\t\t<CardTitle>Task Runs</CardTitle>\n\t\t\t</CardHeader>\n\t\t\t<CardContent>\n\t\t\t\t<div className=\"grid gap-1\">\n\t\t\t\t\t<div className=\"inline-flex items-end gap-1 text-base\">\n\t\t\t\t\t\t<span className=\"font-semibold\">{total}</span>\n\t\t\t\t\t</div>\n\t\t\t\t\t{running > 0 && (\n\t\t\t\t\t\t<div className=\"inline-flex items-end gap-1 text-sm\">\n\t\t\t\t\t\t\t<span className=\"font-semibold text-blue-600\">{running}</span>\n\t\t\t\t\t\t\t<span className=\"text-muted-foreground\">Running</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t\t<div className=\"inline-flex items-end gap-1 text-sm\">\n\t\t\t\t\t\t<span className=\"font-semibold text-green-600\">{completed}</span>\n\t\t\t\t\t\t<span className=\"text-muted-foreground\">Completed</span>\n\t\t\t\t\t\t<span className=\"text-green-600\">{completedPercentage}%</span>\n\t\t\t\t\t</div>\n\t\t\t\t\t{failed > 0 && (\n\t\t\t\t\t\t<div className=\"inline-flex items-end gap-1 text-sm\">\n\t\t\t\t\t\t\t<span className=\"font-semibold text-red-600\">{failed}</span>\n\t\t\t\t\t\t\t<span className=\"text-muted-foreground\">Failed</span>\n\t\t\t\t\t\t\t<span className=\"text-red-600\">{failedPercentage}%</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</CardContent>\n\t\t\t<div className=\"absolute bottom-4 left-0 right-0 h-16\">\n\t\t\t\t<ChartContainer config={chartConfig} className=\"h-full w-full\">\n\t\t\t\t\t<AreaChart\n\t\t\t\t\t\tdata={chartData}\n\t\t\t\t\t\tmargin={{ top: 0, right: 0, bottom: 0, left: 0 }}\n\t\t\t\t\t>\n\t\t\t\t\t\t<defs>\n\t\t\t\t\t\t\t<linearGradient\n\t\t\t\t\t\t\t\tid=\"completedGradientFlow\"\n\t\t\t\t\t\t\t\tx1=\"0\"\n\t\t\t\t\t\t\t\ty1=\"1\"\n\t\t\t\t\t\t\t\tx2=\"0\"\n\t\t\t\t\t\t\t\ty2=\"0\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<stop\n\t\t\t\t\t\t\t\t\toffset=\"0%\"\n\t\t\t\t\t\t\t\t\tstopColor=\"var(--color-completed)\"\n\t\t\t\t\t\t\t\t\tstopOpacity={0}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t<stop\n\t\t\t\t\t\t\t\t\toffset=\"100%\"\n\t\t\t\t\t\t\t\t\tstopColor=\"var(--color-completed)\"\n\t\t\t\t\t\t\t\t\tstopOpacity={0.3}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</linearGradient>\n\t\t\t\t\t\t\t<linearGradient\n\t\t\t\t\t\t\t\tid=\"failedGradientFlow\"\n\t\t\t\t\t\t\t\tx1=\"0\"\n\t\t\t\t\t\t\t\ty1=\"1\"\n\t\t\t\t\t\t\t\tx2=\"0\"\n\t\t\t\t\t\t\t\ty2=\"0\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<stop\n\t\t\t\t\t\t\t\t\toffset=\"0%\"\n\t\t\t\t\t\t\t\t\tstopColor=\"var(--color-failed)\"\n\t\t\t\t\t\t\t\t\tstopOpacity={0}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t<stop\n\t\t\t\t\t\t\t\t\toffset=\"100%\"\n\t\t\t\t\t\t\t\t\tstopColor=\"var(--color-failed)\"\n\t\t\t\t\t\t\t\t\tstopOpacity={0.3}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</linearGradient>\n\t\t\t\t\t\t</defs>\n\t\t\t\t\t\t{hasFailedData && (\n\t\t\t\t\t\t\t<Area\n\t\t\t\t\t\t\t\ttype=\"monotone\"\n\t\t\t\t\t\t\t\tdataKey=\"failed\"\n\t\t\t\t\t\t\t\tstroke=\"var(--color-failed)\"\n\t\t\t\t\t\t\t\tstrokeWidth={2}\n\t\t\t\t\t\t\t\tactiveDot={false}\n\t\t\t\t\t\t\t\tfill=\"url(#failedGradientFlow)\"\n\t\t\t\t\t\t\t\tdot={false}\n\t\t\t\t\t\t\t\tisAnimationActive={false}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t<Area\n\t\t\t\t\t\t\ttype=\"monotone\"\n\t\t\t\t\t\t\tdataKey=\"completed\"\n\t\t\t\t\t\t\tstroke=\"var(--color-completed)\"\n\t\t\t\t\t\t\tstrokeWidth={2}\n\t\t\t\t\t\t\tactiveDot={false}\n\t\t\t\t\t\t\tfill=\"url(#completedGradientFlow)\"\n\t\t\t\t\t\t\tdot={false}\n\t\t\t\t\t\t\tisAnimationActive={false}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</AreaChart>\n\t\t\t\t</ChartContainer>\n\t\t\t</div>\n\t\t</Card>\n\t);\n}\n","import { useSuspenseQueries } from \"@tanstack/react-query\";\nimport { subDays } from \"date-fns\";\nimport { useCallback, useMemo, useState } from \"react\";\nimport {\n\tbuildCountFlowRunsQuery,\n\tbuildFilterFlowRunsQuery,\n\ttype FlowRun,\n} from \"@/api/flow-runs\";\nimport type { Flow } from \"@/api/flows\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"@/components/ui/card\";\nimport {\n\tFlowRunActivityBarChart,\n\tFlowRunActivityBarGraphTooltipProvider,\n} from \"@/components/ui/flow-run-activity-bar-graph\";\nimport { Skeleton } from \"@/components/ui/skeleton\";\nimport useDebounce from \"@/hooks/use-debounce\";\nimport {\n\tbuildFlowRunsCountFilterForHistory,\n\tbuildFlowRunsHistoryFilter,\n} from \"./query-filters\";\n\nconst BAR_WIDTH = 8;\nconst BAR_GAP = 4;\nconst REFETCH_INTERVAL = 30_000;\n\ntype FlowRunsHistoryCardProps = {\n\tflowId: string;\n\tflow: Flow;\n};\n\nexport function FlowRunsHistoryCard({\n\tflowId,\n\tflow,\n}: FlowRunsHistoryCardProps) {\n\tconst [numberOfBars, setNumberOfBars] = useState<number>(0);\n\tconst debouncedNumberOfBars = useDebounce(numberOfBars, 150);\n\n\tconst chartRef = useCallback((node: HTMLDivElement | null) => {\n\t\tif (!node) return;\n\n\t\tconst updateBars = () => {\n\t\t\tconst chartWidth = node.getBoundingClientRect().width;\n\t\t\tsetNumberOfBars(Math.floor(chartWidth / (BAR_WIDTH + BAR_GAP)));\n\t\t};\n\n\t\tupdateBars();\n\t\tconst resizeObserver = new ResizeObserver(updateBars);\n\t\tresizeObserver.observe(node);\n\t\treturn () => resizeObserver.disconnect();\n\t}, []);\n\n\tconst effectiveNumberOfBars = debouncedNumberOfBars || numberOfBars;\n\t// Use a fixed limit of 60 to ensure query key stability with prefetch\n\tconst QUERY_LIMIT = 60;\n\n\tconst [{ data: flowRuns }, { data: totalCount }] = useSuspenseQueries({\n\t\tqueries: [\n\t\t\tbuildFilterFlowRunsQuery(\n\t\t\t\tbuildFlowRunsHistoryFilter(flowId, QUERY_LIMIT),\n\t\t\t\tREFETCH_INTERVAL,\n\t\t\t),\n\t\t\tbuildCountFlowRunsQuery(\n\t\t\t\tbuildFlowRunsCountFilterForHistory(flowId),\n\t\t\t\tREFETCH_INTERVAL,\n\t\t\t),\n\t\t],\n\t});\n\n\tconst enrichedFlowRuns = useMemo(\n\t\t() =>\n\t\t\tflowRuns.map((flowRun: FlowRun) => ({\n\t\t\t\t...flowRun,\n\t\t\t\tflow,\n\t\t\t})),\n\t\t[flowRuns, flow],\n\t);\n\n\tconst { startDate, endDate } = useMemo((): {\n\t\tstartDate: Date;\n\t\tendDate: Date;\n\t} => {\n\t\tconst now = new Date();\n\t\treturn {\n\t\t\tstartDate: subDays(now, 7),\n\t\t\tendDate: now,\n\t\t};\n\t}, []);\n\n\treturn (\n\t\t<Card className=\"flex-1\">\n\t\t\t<CardHeader className=\"flex flex-row items-center justify-between pb-2\">\n\t\t\t\t<CardTitle>Flow Runs</CardTitle>\n\t\t\t\t<span className=\"text-sm text-muted-foreground\">\n\t\t\t\t\t{totalCount} total\n\t\t\t\t</span>\n\t\t\t</CardHeader>\n\t\t\t<CardContent>\n\t\t\t\t<div className=\"h-24\" ref={chartRef}>\n\t\t\t\t\t{effectiveNumberOfBars === 0 ? (\n\t\t\t\t\t\t<Skeleton className=\"h-full w-full\" />\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<FlowRunActivityBarGraphTooltipProvider>\n\t\t\t\t\t\t\t<FlowRunActivityBarChart\n\t\t\t\t\t\t\t\tenrichedFlowRuns={enrichedFlowRuns}\n\t\t\t\t\t\t\t\tstartDate={startDate}\n\t\t\t\t\t\t\t\tendDate={endDate}\n\t\t\t\t\t\t\t\tnumberOfBars={effectiveNumberOfBars}\n\t\t\t\t\t\t\t\tbarWidth={BAR_WIDTH}\n\t\t\t\t\t\t\t\tclassName=\"h-full w-full\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</FlowRunActivityBarGraphTooltipProvider>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</CardContent>\n\t\t</Card>\n\t);\n}\n","import type { Flow } from \"@/api/flows\";\nimport { CumulativeTaskRunsCard } from \"./cumulative-task-runs-card\";\nimport { FlowRunsHistoryCard } from \"./flow-runs-history-card\";\n\ntype FlowStatsSummaryProps = {\n\tflowId: string;\n\tflow: Flow;\n};\n\nexport function FlowStatsSummary({ flowId, flow }: FlowStatsSummaryProps) {\n\treturn (\n\t\t<div className=\"grid gap-5 md:grid-cols-[2fr_1fr]\">\n\t\t\t<FlowRunsHistoryCard flowId={flowId} flow={flow} />\n\t\t\t<CumulativeTaskRunsCard flowId={flowId} />\n\t\t</div>\n\t);\n}\n","import { useNavigate } from \"@tanstack/react-router\";\nimport { type JSX, useCallback, useState } from \"react\";\nimport type { FlowRun } from \"@/api/flow-runs\";\nimport type { Flow } from \"@/api/flows\";\nimport type { components } from \"@/api/prefect\";\nimport type { FlowRunCardData } from \"@/components/flow-runs/flow-run-card\";\nimport {\n\tFlowRunsList,\n\tFlowRunsPagination,\n\tFlowRunsRowCount,\n\ttype PaginationState,\n\ttype SortFilters,\n\tuseFlowRunsSelectedRows,\n} from \"@/components/flow-runs/flow-runs-list\";\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 type { FlowRunState } from \"@/components/flow-runs/flow-runs-list/flow-runs-filters/state-filters.constants\";\nimport { SearchInput } from \"@/components/ui/input\";\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from \"@/components/ui/tabs\";\nimport { DeleteFlowDialog } from \"./delete-flow-dialog\";\nimport { FlowDeploymentsTab } from \"./flow-deployments-tab\";\nimport { FlowDetails } from \"./flow-details\";\nimport { FlowPageHeader } from \"./flow-page-header\";\nimport { FlowStatsSummary } from \"./flow-stats-summary\";\n\nexport default function FlowDetail({\n\tflow,\n\tflowRuns,\n\tflowRunsCount,\n\tflowRunsPages,\n\tdeployments,\n\tdeploymentsCount,\n\tdeploymentsPages,\n\ttab = \"runs\",\n\tpagination,\n\tonPaginationChange,\n\tonPrefetchPage,\n\tsort,\n\tonSortChange,\n\tflowRunSearch,\n\tonFlowRunSearchChange,\n\tselectedStates,\n\tonSelectFilter,\n\tdeploymentSearch,\n\tonDeploymentSearchChange,\n\tdeploymentTags,\n\tonDeploymentTagsChange,\n\tdeploymentSort,\n\tonDeploymentSortChange,\n\tdeploymentPagination,\n\tonDeploymentPaginationChange,\n}: {\n\tflow: Flow;\n\tflowRuns: FlowRun[];\n\tflowRunsCount: number;\n\tflowRunsPages: number;\n\tdeployments: components[\"schemas\"][\"DeploymentResponse\"][];\n\tdeploymentsCount: number;\n\tdeploymentsPages: number;\n\ttab: \"runs\" | \"deployments\" | \"details\";\n\tpagination: PaginationState;\n\tonPaginationChange: (pagination: PaginationState) => void;\n\tonPrefetchPage: (page: number) => void;\n\tsort: SortFilters;\n\tonSortChange: (sort: SortFilters) => void;\n\tflowRunSearch: string | undefined;\n\tonFlowRunSearchChange: (search: string) => void;\n\tselectedStates: Set<FlowRunState>;\n\tonSelectFilter: (states: Set<FlowRunState>) => void;\n\tdeploymentSearch: string | undefined;\n\tonDeploymentSearchChange: (search: string) => void;\n\tdeploymentTags: string[];\n\tonDeploymentTagsChange: (tags: string[]) => void;\n\tdeploymentSort: components[\"schemas\"][\"DeploymentSort\"];\n\tonDeploymentSortChange: (\n\t\tsort: components[\"schemas\"][\"DeploymentSort\"],\n\t) => void;\n\tdeploymentPagination: { page: number; limit: number };\n\tonDeploymentPaginationChange: (pagination: {\n\t\tpage: number;\n\t\tlimit: number;\n\t}) => void;\n}): JSX.Element {\n\tconst navigate = useNavigate();\n\tconst [showDeleteDialog, setShowDeleteDialog] = useState(false);\n\tconst [selectedRows, setSelectedRows, { onSelectRow, clearSet }] =\n\t\tuseFlowRunsSelectedRows();\n\n\t// Enrich paginated flow runs with flow object for the list\n\tconst enrichedFlowRuns: FlowRunCardData[] = flowRuns.map((flowRun) => ({\n\t\t...flowRun,\n\t\tflow: flow,\n\t}));\n\n\t// Handler to clear filters\n\tconst onClearFilters = useCallback(() => {\n\t\tonFlowRunSearchChange(\"\");\n\t\tonSelectFilter(new Set());\n\t\tclearSet();\n\t}, [onFlowRunSearchChange, onSelectFilter, clearSet]);\n\n\treturn (\n\t\t<>\n\t\t\t<div className=\"container mx-auto flex flex-col gap-4\">\n\t\t\t\t<FlowPageHeader\n\t\t\t\t\tflow={flow}\n\t\t\t\t\tonDelete={() => setShowDeleteDialog(true)}\n\t\t\t\t/>\n\t\t\t\t<FlowStatsSummary flowId={flow.id} flow={flow} />\n\t\t\t\t<Tabs\n\t\t\t\t\tvalue={tab}\n\t\t\t\t\tonValueChange={(value) =>\n\t\t\t\t\t\tvoid navigate({\n\t\t\t\t\t\t\tto: \".\",\n\t\t\t\t\t\t\tsearch: (prev) => ({\n\t\t\t\t\t\t\t\t...prev,\n\t\t\t\t\t\t\t\ttab: value as \"runs\" | \"deployments\" | \"details\",\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t>\n\t\t\t\t\t<TabsList>\n\t\t\t\t\t\t<TabsTrigger value=\"runs\">Runs</TabsTrigger>\n\t\t\t\t\t\t<TabsTrigger value=\"deployments\">Deployments</TabsTrigger>\n\t\t\t\t\t\t<TabsTrigger value=\"details\">Details</TabsTrigger>\n\t\t\t\t\t</TabsList>\n\t\t\t\t\t<TabsContent value=\"runs\" 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<FlowRunsRowCount\n\t\t\t\t\t\t\t\tcount={flowRunsCount}\n\t\t\t\t\t\t\t\tresults={enrichedFlowRuns}\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<SearchInput\n\t\t\t\t\t\t\t\t\tplaceholder=\"Search by run name\"\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\tclassName=\"w-64\"\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t<StateFilter\n\t\t\t\t\t\t\t\t\tselectedFilters={selectedStates}\n\t\t\t\t\t\t\t\t\tonSelectFilter={onSelectFilter}\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<FlowRunsList\n\t\t\t\t\t\t\tflowRuns={enrichedFlowRuns}\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\tonClearFilters={onClearFilters}\n\t\t\t\t\t\t/>\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</TabsContent>\n\t\t\t\t\t<TabsContent value=\"deployments\">\n\t\t\t\t\t\t<FlowDeploymentsTab\n\t\t\t\t\t\t\tdeployments={deployments}\n\t\t\t\t\t\t\tdeploymentsCount={deploymentsCount}\n\t\t\t\t\t\t\tdeploymentsPages={deploymentsPages}\n\t\t\t\t\t\t\tdeploymentSearch={deploymentSearch}\n\t\t\t\t\t\t\tonDeploymentSearchChange={onDeploymentSearchChange}\n\t\t\t\t\t\t\tdeploymentTags={deploymentTags}\n\t\t\t\t\t\t\tonDeploymentTagsChange={onDeploymentTagsChange}\n\t\t\t\t\t\t\tdeploymentSort={deploymentSort}\n\t\t\t\t\t\t\tonDeploymentSortChange={onDeploymentSortChange}\n\t\t\t\t\t\t\tdeploymentPagination={deploymentPagination}\n\t\t\t\t\t\t\tonDeploymentPaginationChange={onDeploymentPaginationChange}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</TabsContent>\n\t\t\t\t\t<TabsContent value=\"details\">\n\t\t\t\t\t\t<FlowDetails flow={flow} />\n\t\t\t\t\t</TabsContent>\n\t\t\t\t</Tabs>\n\t\t\t</div>\n\t\t\t<DeleteFlowDialog\n\t\t\t\tflow={flow}\n\t\t\t\topen={showDeleteDialog}\n\t\t\t\tonOpenChange={setShowDeleteDialog}\n\t\t\t/>\n\t\t</>\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 } from \"react\";\nimport { z } from \"zod\";\nimport { buildPaginateDeploymentsQuery } from \"@/api/deployments\";\nimport {\n\tbuildCountFlowRunsQuery,\n\tbuildFilterFlowRunsQuery,\n\tbuildPaginateFlowRunsQuery,\n\ttype FlowRunsPaginateFilter,\n} from \"@/api/flow-runs\";\nimport {\n\tbuildDeploymentsCountByFlowQuery,\n\tbuildFLowDetailsQuery,\n} from \"@/api/flows\";\nimport type { components } from \"@/api/prefect\";\nimport {\n\tbuildCountTaskRunsQuery,\n\tbuildGetFlowRunsTaskRunsCountQuery,\n\tbuildTaskRunsHistoryQuery,\n} from \"@/api/task-runs\";\nimport {\n\ttype PaginationState,\n\tSORT_FILTERS,\n\ttype SortFilters,\n} from \"@/components/flow-runs/flow-runs-list\";\nimport type { FlowRunState } from \"@/components/flow-runs/flow-runs-list/flow-runs-filters/state-filters.constants\";\nimport FlowDetail from \"@/components/flows/detail\";\nimport {\n\tbuildCompletedTaskRunsCountFilter,\n\tbuildFailedTaskRunsCountFilter,\n\tbuildFlowRunsCountFilterForHistory,\n\tbuildFlowRunsHistoryFilter,\n\tbuildRunningTaskRunsCountFilter,\n\tbuildTaskRunsHistoryFilterForFlow,\n\tbuildTotalTaskRunsCountFilter,\n} from \"@/components/flows/detail/flow-stats-summary/query-filters\";\nimport { usePageTitle } from \"@/hooks/use-page-title\";\n\n// Route for /flows/flow/$id\n\n// This file contains the route definition and loader function for the /flows/flow/$id route.\n\n// 1. searchParams defined as a zod schema for validating and typechecking the search query.\n// 2. filterFlowRunsBySearchParams function that takes a search object and returns a filter for flow runs.\n// 3. Route definition using createFileRoute function:\n// - It uses useSuspenseQueries to fetch data for the flow, flow runs, deployments, and related counts.\n// - Passes the fetched data to the FlowDetail component.\n// - Includes a loader function to prefetch data on the server side.\n\nconst searchParams = z\n\t.object({\n\t\ttab: z.enum([\"runs\", \"deployments\", \"details\"]).optional().default(\"runs\"),\n\t\t\"runs.page\": z.number().int().positive().optional().default(1),\n\t\t\"runs.limit\": z.number().int().positive().max(100).optional().default(10),\n\t\t\"runs.sort\": z.enum(SORT_FILTERS).optional().default(\"START_TIME_DESC\"),\n\t\t\"runs.flowRuns.nameLike\": z.string().optional().default(\"\"),\n\t\t\"runs.flowRuns.state.name\": z.array(z.string()).optional(),\n\t\ttype: z.enum([\"span\", \"range\"]).optional(),\n\t\tseconds: z.number().int().positive().optional(),\n\t\tstartDateTime: z.date().optional(),\n\t\tendDateTime: z.date().optional(),\n\t\t\"deployments.page\": z.number().int().positive().optional().default(1),\n\t\t\"deployments.limit\": z.number().int().positive().optional().default(10),\n\t\t\"deployments.nameLike\": z.string().optional(),\n\t\t\"deployments.tags\": z.array(z.string()).optional(),\n\t\t\"deployments.sort\": z\n\t\t\t.enum([\"CREATED_DESC\", \"UPDATED_DESC\", \"NAME_ASC\", \"NAME_DESC\"])\n\t\t\t.optional()\n\t\t\t.default(\"NAME_ASC\"),\n\t})\n\t.optional()\n\t.default({});\n\ntype SearchParams = z.infer<typeof searchParams>;\n\nconst buildPaginationBody = (\n\tsearch: SearchParams,\n\tflowId: string,\n): FlowRunsPaginateFilter => {\n\tconst flowRunSearch = search[\"runs.flowRuns.nameLike\"];\n\tconst stateFilters = search[\"runs.flowRuns.state.name\"] ?? [];\n\n\tconst hasFilters = flowRunSearch || stateFilters.length > 0;\n\tconst flowRunsFilter = hasFilters\n\t\t? {\n\t\t\t\toperator: \"and_\" as const,\n\t\t\t\t...(flowRunSearch && {\n\t\t\t\t\tname: { like_: flowRunSearch },\n\t\t\t\t}),\n\t\t\t\t...(stateFilters.length > 0 && {\n\t\t\t\t\tstate: {\n\t\t\t\t\t\toperator: \"and_\" as const,\n\t\t\t\t\t\tname: { any_: stateFilters },\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t}\n\t\t: undefined;\n\n\treturn {\n\t\tpage: search[\"runs.page\"],\n\t\tlimit: search[\"runs.limit\"],\n\t\tsort: search[\"runs.sort\"],\n\t\tflow_runs: flowRunsFilter,\n\t\tflows: { operator: \"and_\" as const, id: { any_: [flowId] } },\n\t};\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[\"runs.page\"],\n\t\t\tlimit: search[\"runs.limit\"],\n\t\t}),\n\t\t[search[\"runs.page\"], search[\"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\"runs.page\": newPagination.page,\n\t\t\t\t\t\"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 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, \"runs.sort\": sort, \"runs.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[\"runs.sort\"], onSortChange] 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\"runs.flowRuns.nameLike\": flowRunSearch,\n\t\t\t\t\t\"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[\"runs.flowRuns.nameLike\"], onFlowRunSearchChange] as const;\n};\n\nconst useStateFilter = () => {\n\tconst search = Route.useSearch();\n\tconst navigate = Route.useNavigate();\n\n\tconst selectedStates = useMemo(\n\t\t() => new Set((search[\"runs.flowRuns.state.name\"] || []) as FlowRunState[]),\n\t\t[search[\"runs.flowRuns.state.name\"]],\n\t);\n\n\tconst onSelectFilter = useCallback(\n\t\t(states: Set<FlowRunState>) => {\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\"runs.flowRuns.state.name\": Array.from(states),\n\t\t\t\t\t\"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 { selectedStates, onSelectFilter };\n};\n\nconst useDeploymentSearch = () => {\n\tconst search = Route.useSearch();\n\tconst navigate = Route.useNavigate();\n\n\tconst onDeploymentSearchChange = useCallback(\n\t\t(deploymentSearch: 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\"deployments.nameLike\": deploymentSearch || undefined,\n\t\t\t\t\t\"deployments.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[\"deployments.nameLike\"], onDeploymentSearchChange] as const;\n};\n\nconst useDeploymentTagsFilter = () => {\n\tconst search = Route.useSearch();\n\tconst navigate = Route.useNavigate();\n\n\tconst onDeploymentTagsChange = useCallback(\n\t\t(tags: 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\"deployments.tags\": tags.length > 0 ? tags : undefined,\n\t\t\t\t\t\"deployments.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[\"deployments.tags\"] ?? [], onDeploymentTagsChange] as const;\n};\n\nconst useDeploymentSort = () => {\n\tconst search = Route.useSearch();\n\tconst navigate = Route.useNavigate();\n\n\tconst onDeploymentSortChange = useCallback(\n\t\t(sort: components[\"schemas\"][\"DeploymentSort\"]) => {\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\"deployments.sort\": sort,\n\t\t\t\t\t\"deployments.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[\"deployments.sort\"], onDeploymentSortChange] as const;\n};\n\nconst useDeploymentPagination = () => {\n\tconst search = Route.useSearch();\n\tconst navigate = Route.useNavigate();\n\n\tconst deploymentPagination = useMemo(\n\t\t() => ({\n\t\t\tpage: search[\"deployments.page\"],\n\t\t\tlimit: search[\"deployments.limit\"],\n\t\t}),\n\t\t[search[\"deployments.page\"], search[\"deployments.limit\"]],\n\t);\n\n\tconst onDeploymentPaginationChange = useCallback(\n\t\t(newPagination: { page: number; limit: number }) => {\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\"deployments.page\": newPagination.page,\n\t\t\t\t\t\"deployments.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 [deploymentPagination, onDeploymentPaginationChange] as const;\n};\n\nconst FlowDetailRoute = () => {\n\tconst queryClient = useQueryClient();\n\tconst { id } = Route.useParams();\n\tconst search = Route.useSearch();\n\n\t// Navigation hooks for flow runs\n\tconst [pagination, onPaginationChange] = usePagination();\n\tconst [sort, onSortChange] = useSort();\n\tconst [flowRunSearch, onFlowRunSearchChange] = useFlowRunSearch();\n\tconst { selectedStates, onSelectFilter } = useStateFilter();\n\n\t// Navigation hooks for deployments\n\tconst [deploymentSearch, onDeploymentSearchChange] = useDeploymentSearch();\n\tconst [deploymentTags, onDeploymentTagsChange] = useDeploymentTagsFilter();\n\tconst [deploymentSort, onDeploymentSortChange] = useDeploymentSort();\n\tconst [deploymentPagination, onDeploymentPaginationChange] =\n\t\tuseDeploymentPagination();\n\n\t// Suspense queries for stable data (flow)\n\tconst [{ data: flow }] = useSuspenseQueries({\n\t\tqueries: [buildFLowDetailsQuery(id)],\n\t});\n\n\t// Use useQuery for deployments to leverage placeholderData: keepPreviousData\n\t// This prevents the page from suspending when search/filter changes\n\tconst { data: deploymentsPage } = useQuery(\n\t\tbuildPaginateDeploymentsQuery({\n\t\t\tsort: search[\"deployments.sort\"],\n\t\t\tpage: search[\"deployments.page\"],\n\t\t\tlimit: search[\"deployments.limit\"],\n\t\t\tflows: { operator: \"and_\", id: { any_: [id] } },\n\t\t\tdeployments: {\n\t\t\t\toperator: \"and_\",\n\t\t\t\tflow_or_deployment_name: { like_: search[\"deployments.nameLike\"] },\n\t\t\t\ttags: { operator: \"and_\", all_: search[\"deployments.tags\"] || [] },\n\t\t\t},\n\t\t}),\n\t);\n\n\t// Set page title based on flow name\n\tusePageTitle(flow?.name ? `Flow: ${flow.name}` : \"Flow\");\n\n\t// Use useQuery for paginated flow runsto 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, id), 30_000),\n\t);\n\n\tconst flowRuns = flowRunsPage?.results ?? [];\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\t// Prefetch handler for pagination hover\n\tconst onPrefetchPage = useCallback(\n\t\t(page: number) => {\n\t\t\tconst filter = buildPaginationBody(\n\t\t\t\t{\n\t\t\t\t\t...search,\n\t\t\t\t\t\"runs.page\": page,\n\t\t\t\t},\n\t\t\t\tid,\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, id],\n\t);\n\n\treturn (\n\t\t<FlowDetail\n\t\t\tflow={flow}\n\t\t\tflowRuns={flowRuns}\n\t\t\tflowRunsCount={flowRunsPage?.count ?? 0}\n\t\t\tflowRunsPages={flowRunsPage?.pages ?? 0}\n\t\t\tdeployments={deploymentsPage?.results ?? []}\n\t\t\tdeploymentsCount={deploymentsPage?.count ?? 0}\n\t\t\tdeploymentsPages={deploymentsPage?.pages ?? 0}\n\t\t\ttab={search.tab}\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\tflowRunSearch={flowRunSearch}\n\t\t\tonFlowRunSearchChange={onFlowRunSearchChange}\n\t\t\tselectedStates={selectedStates}\n\t\t\tonSelectFilter={onSelectFilter}\n\t\t\tdeploymentSearch={deploymentSearch}\n\t\t\tonDeploymentSearchChange={onDeploymentSearchChange}\n\t\t\tdeploymentTags={deploymentTags}\n\t\t\tonDeploymentTagsChange={onDeploymentTagsChange}\n\t\t\tdeploymentSort={deploymentSort}\n\t\t\tonDeploymentSortChange={onDeploymentSortChange}\n\t\t\tdeploymentPagination={deploymentPagination}\n\t\t\tonDeploymentPaginationChange={onDeploymentPaginationChange}\n\t\t/>\n\t);\n};\n\nexport const Route = createFileRoute(\"/flows/flow/$id\")({\n\tcomponent: FlowDetailRoute,\n\tvalidateSearch: zodValidator(searchParams),\n\tloaderDeps: ({ search }) => ({\n\t\tflowRunsDeps: search,\n\t}),\n\tloader: ({ params: { id }, context, deps }) => {\n\t\tconst REFETCH_INTERVAL = 30_000;\n\n\t\t// Prefetch flow details\n\t\tvoid context.queryClient.prefetchQuery(buildFLowDetailsQuery(id));\n\n\t\t// Prefetch paginated flow runs without blocking (uses keepPreviousData)\n\t\tvoid context.queryClient.prefetchQuery(\n\t\t\tbuildPaginateFlowRunsQuery(\n\t\t\t\tbuildPaginationBody(deps.flowRunsDeps, id),\n\t\t\t\t30_000,\n\t\t\t),\n\t\t);\n\n\t\t// Prefetch deployments with filter parameters\n\t\tvoid context.queryClient.prefetchQuery(\n\t\t\tbuildPaginateDeploymentsQuery({\n\t\t\t\tsort: deps.flowRunsDeps[\"deployments.sort\"],\n\t\t\t\tpage: deps.flowRunsDeps[\"deployments.page\"],\n\t\t\t\tlimit: deps.flowRunsDeps[\"deployments.limit\"],\n\t\t\t\tflows: { operator: \"and_\", id: { any_: [id] } },\n\t\t\t\tdeployments: {\n\t\t\t\t\toperator: \"and_\",\n\t\t\t\t\tflow_or_deployment_name: {\n\t\t\t\t\t\tlike_: deps.flowRunsDeps[\"deployments.nameLike\"],\n\t\t\t\t\t},\n\t\t\t\t\ttags: {\n\t\t\t\t\t\toperator: \"and_\",\n\t\t\t\t\t\tall_: deps.flowRunsDeps[\"deployments.tags\"] || [],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}),\n\t\t);\n\n\t\t// Prefetch deployments count\n\t\tvoid context.queryClient.prefetchQuery(\n\t\t\tbuildDeploymentsCountByFlowQuery([id]),\n\t\t);\n\n\t\t// Prefetch FlowStatsSummary queries\n\t\t// FlowRunsHistoryCard queries\n\t\tvoid context.queryClient.prefetchQuery(\n\t\t\tbuildFilterFlowRunsQuery(\n\t\t\t\tbuildFlowRunsHistoryFilter(id, 60),\n\t\t\t\tREFETCH_INTERVAL,\n\t\t\t),\n\t\t);\n\t\tvoid context.queryClient.prefetchQuery(\n\t\t\tbuildCountFlowRunsQuery(\n\t\t\t\tbuildFlowRunsCountFilterForHistory(id),\n\t\t\t\tREFETCH_INTERVAL,\n\t\t\t),\n\t\t);\n\n\t\t// CumulativeTaskRunsCard queries\n\t\tvoid context.queryClient.prefetchQuery(\n\t\t\tbuildCountTaskRunsQuery(\n\t\t\t\tbuildTotalTaskRunsCountFilter(id),\n\t\t\t\tREFETCH_INTERVAL,\n\t\t\t),\n\t\t);\n\t\tvoid context.queryClient.prefetchQuery(\n\t\t\tbuildCountTaskRunsQuery(\n\t\t\t\tbuildCompletedTaskRunsCountFilter(id),\n\t\t\t\tREFETCH_INTERVAL,\n\t\t\t),\n\t\t);\n\t\tvoid context.queryClient.prefetchQuery(\n\t\t\tbuildCountTaskRunsQuery(\n\t\t\t\tbuildFailedTaskRunsCountFilter(id),\n\t\t\t\tREFETCH_INTERVAL,\n\t\t\t),\n\t\t);\n\t\tvoid context.queryClient.prefetchQuery(\n\t\t\tbuildCountTaskRunsQuery(\n\t\t\t\tbuildRunningTaskRunsCountFilter(id),\n\t\t\t\tREFETCH_INTERVAL,\n\t\t\t),\n\t\t);\n\t\tvoid context.queryClient.prefetchQuery(\n\t\t\tbuildTaskRunsHistoryQuery(\n\t\t\t\tbuildTaskRunsHistoryFilterForFlow(id),\n\t\t\t\tREFETCH_INTERVAL,\n\t\t\t),\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(\n\t\t\t\t\tbuildPaginationBody(deps.flowRunsDeps, id),\n\t\t\t\t\t30_000,\n\t\t\t\t),\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\n\t\t// Ensure flow details are loaded (critical data)\n\t\treturn context.queryClient.ensureQueryData(buildFLowDetailsQuery(id));\n\t},\n\twrapInSuspense: true,\n});\n"],"names":["DeleteFlowDialog","flow","open","onOpenChange","onDeleted","navigate","useNavigate","deleteFlow","isPending","useDeleteFlowById","handleDelete","toast","jsx","DeleteConfirmationDialog","BAR_WIDTH","BAR_GAP","MiniDeploymentActivity","deploymentId","numberOfBars","setNumberOfBars","useState","debouncedNumberOfBars","useDebounce","chartRef","useCallback","node","updateBars","chartWidth","resizeObserver","effectiveNumberOfBars","flowRuns","useQuery","buildFilterFlowRunsQuery","enrichedFlowRuns","flowRun","FlowRunActivityBarChart","subSeconds","secondsInWeek","columns","table","Checkbox","value","row","status","StatusBadge","tag","schedules","ScheduleBadgeGroup","DropdownMenu","DropdownMenuTrigger","jsxs","Button","Icon","DropdownMenuContent","DropdownMenuItem","SORT_OPTIONS","FlowDeploymentsTab","deployments","deploymentsCount","deploymentsPages","deploymentSearch","onDeploymentSearchChange","deploymentTags","onDeploymentTagsChange","deploymentSort","onDeploymentSortChange","deploymentPagination","onDeploymentPaginationChange","rowSelection","setRowSelection","showDeleteDialog","setShowDeleteDialog","deleteDeployment","useDeleteDeployment","handlePaginationChange","updater","currentPagination","newPagination","deploymentsTable","useReactTable","baseDeploymentColumns","getCoreRowModel","selectedCount","handleDeleteSelected","selectedIds","id","handleDeploymentTagsChange","e","Typography","Trash2","SearchInput","TagsInput","Select","SelectTrigger","SelectValue","SelectContent","option","SelectItem","FlowRunActivityBarGraphTooltipProvider","DataTable","Dialog","DialogContent","DialogHeader","DialogTitle","DialogDescription","DialogFooter","FlowDetails","FormattedDate","FlowMenu","onDelete","handleCopyId","DropdownMenuLabel","FlowPageHeader","Breadcrumb","BreadcrumbList","BreadcrumbItem","BreadcrumbLink","BreadcrumbSeparator","BreadcrumbPage","REFETCH_INTERVAL","chartConfig","transformHistoryToChartData","history","chartData","cumulativeCompleted","cumulativeFailed","item","completedCount","failedCount","state","CumulativeTaskRunsCard","flowId","total","completed","failed","running","useSuspenseQueries","buildCountTaskRunsQuery","buildTotalTaskRunsCountFilter","buildCompletedTaskRunsCountFilter","buildFailedTaskRunsCountFilter","buildRunningTaskRunsCountFilter","buildTaskRunsHistoryQuery","buildTaskRunsHistoryFilterForFlow","useMemo","hasFailedData","point","percentComparisonTotal","completedPercentage","failedPercentage","Card","CardHeader","CardTitle","CardContent","ChartContainer","AreaChart","Area","FlowRunsHistoryCard","QUERY_LIMIT","totalCount","buildFlowRunsHistoryFilter","buildCountFlowRunsQuery","buildFlowRunsCountFilterForHistory","startDate","endDate","now","subDays","Skeleton","FlowStatsSummary","FlowDetail","flowRunsCount","flowRunsPages","tab","pagination","onPaginationChange","onPrefetchPage","sort","onSortChange","flowRunSearch","onFlowRunSearchChange","selectedStates","onSelectFilter","selectedRows","setSelectedRows","onSelectRow","clearSet","useFlowRunsSelectedRows","onClearFilters","Fragment","Tabs","prev","TabsList","TabsTrigger","TabsContent","FlowRunsRowCount","StateFilter","SortFilter","FlowRunsList","FlowRunsPagination","z","optional","default","number","int","positive","max","SORT_FILTERS","string","type","seconds","startDateTime","date","endDateTime","buildPaginationBody","search","stateFilters","flowRunsFilter","length","operator","name","like_","any_","undefined","page","limit","flow_runs","flows","usePagination","Route","useSearch","to","replace","useSort","useFlowRunSearch","useStateFilter","Set","states","Array","from","useDeploymentSearch","useDeploymentTagsFilter","tags","useDeploymentSort","useDeploymentPagination","FlowDetailRoute","queryClient","useQueryClient","useParams","data","queries","buildFLowDetailsQuery","deploymentsPage","buildPaginateDeploymentsQuery","flow_or_deployment_name","all_","usePageTitle","flowRunsPage","buildPaginateFlowRunsQuery","results","useEffect","flowRunIds","map","run","prefetchQuery","buildGetFlowRunsTaskRunsCountQuery","filter","ensureQueryData","count","pages"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-BIBIJufF.js","sources":["../../src/routes/automations/index.tsx?tsr-split=errorComponent"],"sourcesContent":["import type { ErrorComponentProps } from \"@tanstack/react-router\";\nimport { createFileRoute } from \"@tanstack/react-router\";\nimport { buildListAutomationsQuery } from \"@/api/automations\";\nimport { categorizeError } from \"@/api/error-utils\";\nimport { AutomationsHeader } from \"@/components/automations/automations-header\";\nimport { AutomationsPage } from \"@/components/automations/automations-page\";\nimport { RouteErrorState } from \"@/components/ui/route-error-state\";\n\nfunction AutomationsErrorComponent({ error, reset }: ErrorComponentProps) {\n\tconst serverError = categorizeError(error, \"Failed to load automations\");\n\n\t// Only handle API errors (server-error, client-error) at route level\n\t// Let network errors and unknown errors bubble up to root error component\n\tif (\n\t\tserverError.type !== \"server-error\" &&\n\t\tserverError.type !== \"client-error\"\n\t) {\n\t\tthrow error;\n\t}\n\n\treturn (\n\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t<AutomationsHeader />\n\t\t\t<RouteErrorState error={serverError} onRetry={reset} />\n\t\t</div>\n\t);\n}\n\n// nb: Currently there is no filtering or search params used on this page\nexport const Route = createFileRoute(\"/automations/\")({\n\tcomponent: AutomationsPage,\n\terrorComponent: AutomationsErrorComponent,\n\tloader: ({ context }) =>\n\t\tcontext.queryClient.ensureQueryData(buildListAutomationsQuery()),\n\twrapInSuspense: true,\n});\n"],"names":["AutomationsErrorComponent","error","reset","serverError","categorizeError","type","jsxs","jsx","AutomationsHeader","RouteErrorState"],"mappings":"oXAQA,SAASA,EAA0B,CAAEC,MAAAA,EAAOC,MAAAA,CAA2B,EAAG,CACzE,MAAMC,EAAcC,EAAgBH,EAAO,4BAA4B,EAIvE,GACCE,EAAYE,OAAS,gBACrBF,EAAYE,OAAS,eAErB,MAAMJ,EAGP,OACCK,EAAAA,KAAC,MAAA,CAAI,UAAU,sBACd,SAAA,CAAAC,EAAAA,IAACC,EAAA,EAAiB,EAClBD,EAAAA,IAACE,EAAA,CAAgB,MAAON,EAAa,QAASD,CAAAA,CAAM,CAAA,EACrD,CAEF"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-BO60ehN6.js","sources":["../../src/routes/deployments/index.tsx?tsr-split=errorComponent"],"sourcesContent":["import { useQuery, useSuspenseQueries } from \"@tanstack/react-query\";\nimport type { ErrorComponentProps } from \"@tanstack/react-router\";\nimport { createFileRoute } from \"@tanstack/react-router\";\nimport type {\n\tColumnFiltersState,\n\tPaginationState,\n} from \"@tanstack/react-table\";\nimport { zodValidator } from \"@tanstack/zod-adapter\";\nimport { useCallback, useMemo } from \"react\";\nimport { z } from \"zod\";\nimport {\n\tbuildCountDeploymentsQuery,\n\tbuildPaginateDeploymentsQuery,\n\ttype DeploymentsPaginationFilter,\n} from \"@/api/deployments\";\nimport { categorizeError } from \"@/api/error-utils\";\nimport { buildListFlowsQuery } from \"@/api/flows\";\nimport type { components } from \"@/api/prefect\";\nimport { DeploymentsDataTable } from \"@/components/deployments/data-table\";\nimport { DeploymentsEmptyState } from \"@/components/deployments/empty-state\";\nimport { DeploymentsPageHeader } from \"@/components/deployments/header\";\nimport { RouteErrorState } from \"@/components/ui/route-error-state\";\n\n/**\n * Schema for validating URL search parameters for the variables page.\n * @property {number} page - The page number to display. Must be positive. Defaults to 1.\n * @property {number} limit - The maximum number of items to return. Must be positive. Defaults to 10.\n */\nconst searchParams = z.object({\n\tpage: z.number().int().positive().optional().default(1).catch(1),\n\tlimit: z.number().int().positive().optional().default(10).catch(10),\n\tsort: z\n\t\t.enum([\"NAME_ASC\", \"NAME_DESC\", \"CREATED_DESC\", \"UPDATED_DESC\"])\n\t\t.optional()\n\t\t.default(\"NAME_ASC\")\n\t\t.catch(\"NAME_ASC\"),\n\tflowOrDeploymentName: z.string().optional().catch(\"\"),\n\ttags: z.array(z.string()).optional().catch([]),\n});\n\n/**\n * Builds pagination parameters for deployments query from search params\n *\n * @param search - Optional validated search parameters containing page and limit\n * @returns DeploymentsPaginationFilter with page, limit and sort order\n *\n * @example\n * ```ts\n * const filter = buildPaginationBody({ page: 2, limit: 25 })\n * // Returns { page: 2, limit: 25, sort: \"NAME_ASC\" }\n * ```\n */\nconst buildPaginationBody = (\n\tsearch?: z.infer<typeof searchParams>,\n): DeploymentsPaginationFilter => ({\n\tpage: search?.page ?? 1,\n\tlimit: search?.limit ?? 10,\n\tsort: search?.sort ?? \"NAME_ASC\",\n\tdeployments: {\n\t\toperator: \"and_\",\n\t\tflow_or_deployment_name: { like_: search?.flowOrDeploymentName ?? \"\" },\n\t\ttags: { operator: \"and_\", all_: search?.tags ?? [] },\n\t},\n});\n\nfunction DeploymentsErrorComponent({ error, reset }: ErrorComponentProps) {\n\tconst serverError = categorizeError(error, \"Failed to load deployments\");\n\n\t// Only handle API errors (server-error, client-error) at route level\n\t// Let network errors and unknown errors bubble up to root error component\n\tif (\n\t\tserverError.type !== \"server-error\" &&\n\t\tserverError.type !== \"client-error\"\n\t) {\n\t\tthrow error;\n\t}\n\n\treturn (\n\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t<DeploymentsPageHeader />\n\t\t\t<RouteErrorState error={serverError} onRetry={reset} />\n\t\t</div>\n\t);\n}\n\nexport const Route = createFileRoute(\"/deployments/\")({\n\tvalidateSearch: zodValidator(searchParams),\n\tcomponent: RouteComponent,\n\terrorComponent: DeploymentsErrorComponent,\n\tloaderDeps: ({ search }) => buildPaginationBody(search),\n\tloader: async ({ deps, context }) => {\n\t\t// Get full count of deployments, don't block the UI\n\t\tconst deploymentsCountResult = context.queryClient.ensureQueryData(\n\t\t\tbuildCountDeploymentsQuery(),\n\t\t);\n\n\t\t// Get paginated deployments, wait for the result to get corresponding flows\n\t\tconst deploymentsPaginateResult = await context.queryClient.ensureQueryData(\n\t\t\tbuildPaginateDeploymentsQuery(deps),\n\t\t);\n\n\t\tconst deployments = deploymentsPaginateResult?.results ?? [];\n\n\t\tconst flowIds = [\n\t\t\t...new Set(deployments.map((deployment) => deployment.flow_id)),\n\t\t];\n\n\t\t// Get flows corresponding to the deployments\n\t\tconst flowsFilterResult = context.queryClient.ensureQueryData(\n\t\t\tbuildListFlowsQuery({\n\t\t\t\tflows: {\n\t\t\t\t\toperator: \"and_\",\n\t\t\t\t\tid: {\n\t\t\t\t\t\tany_: flowIds,\n\t\t\t\t\t},\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);\n\n\t\treturn {\n\t\t\tdeploymentsCountResult,\n\t\t\tdeploymentsPaginateResult,\n\t\t\tflowsFilterResult,\n\t\t};\n\t},\n\twrapInSuspense: true,\n});\n\n/**\n * Hook to manage pagination state and navigation for deployments table\n *\n * Handles conversion between 1-based page numbers in the URL and 0-based indices used by React Table.\n * Updates the URL search parameters when pagination changes.\n *\n * @returns A tuple containing:\n * - pagination: Current pagination state with pageIndex and pageSize\n * - onPaginationChange: Callback to update pagination and navigate with new search params\n */\nconst usePagination = () => {\n\tconst search = Route.useSearch();\n\tconst navigate = Route.useNavigate();\n\n\t// React Table uses 0-based pagination, so we need to subtract 1 from the page number\n\tconst pageIndex = (search.page ?? 1) - 1;\n\tconst pageSize = search.limit ?? 10;\n\tconst pagination: PaginationState = useMemo(\n\t\t() => ({\n\t\t\tpageIndex,\n\t\t\tpageSize,\n\t\t}),\n\t\t[pageIndex, pageSize],\n\t);\n\n\tconst onPaginationChange = useCallback(\n\t\t(newPagination: PaginationState) => {\n\t\t\tvoid navigate({\n\t\t\t\tto: \".\",\n\t\t\t\tsearch: (prev) => ({\n\t\t\t\t\t...prev,\n\t\t\t\t\tpage: newPagination.pageIndex + 1,\n\t\t\t\t\tlimit: newPagination.pageSize,\n\t\t\t\t}),\n\t\t\t\treplace: true,\n\t\t\t});\n\t\t},\n\t\t[navigate],\n\t);\n\n\treturn [pagination, onPaginationChange] as const;\n};\n\n/**\n * Hook to manage sorting state and navigation for deployments table\n *\n * Handles updating the URL search parameters when sort order changes.\n * Returns the current sort value from URL and a callback to update it.\n *\n * @returns A tuple containing:\n * - sort: Current sort value from URL search params\n * - onSortingChange: Callback to update sort and navigate with new search params\n */\nconst useSort = () => {\n\tconst search = Route.useSearch();\n\tconst navigate = Route.useNavigate();\n\n\tconst onSortingChange = (sort: components[\"schemas\"][\"DeploymentSort\"]) => {\n\t\tvoid navigate({\n\t\t\tto: \".\",\n\t\t\tsearch: (prev) => ({ ...prev, sort }),\n\t\t\treplace: true,\n\t\t});\n\t};\n\n\treturn [search.sort, onSortingChange] as const;\n};\n\nconst useDeploymentsColumnFilters = () => {\n\tconst search = Route.useSearch();\n\tconst navigate = Route.useNavigate();\n\tconst columnFilters: ColumnFiltersState = useMemo(\n\t\t() => [\n\t\t\t{ id: \"flowOrDeploymentName\", value: search.flowOrDeploymentName },\n\t\t\t{ id: \"tags\", value: search.tags },\n\t\t],\n\t\t[search.flowOrDeploymentName, search.tags],\n\t);\n\n\tconst onColumnFiltersChange = useCallback(\n\t\t(newColumnFilters: ColumnFiltersState) => {\n\t\t\tvoid navigate({\n\t\t\t\tto: \".\",\n\t\t\t\tsearch: (prev) => {\n\t\t\t\t\tconst flowOrDeploymentName = newColumnFilters.find(\n\t\t\t\t\t\t(filter) => filter.id === \"flowOrDeploymentName\",\n\t\t\t\t\t)?.value as string | undefined;\n\t\t\t\t\tconst tags = newColumnFilters.find((filter) => filter.id === \"tags\")\n\t\t\t\t\t\t?.value as string[] | undefined;\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...prev,\n\t\t\t\t\t\toffset: 0,\n\t\t\t\t\t\tflowOrDeploymentName,\n\t\t\t\t\t\ttags,\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\t[navigate],\n\t);\n\n\treturn [columnFilters, onColumnFiltersChange] as const;\n};\n\nfunction RouteComponent() {\n\tconst search = Route.useSearch();\n\tconst [pagination, onPaginationChange] = usePagination();\n\tconst [sort, onSortChange] = useSort();\n\tconst [columnFilters, onColumnFiltersChange] = useDeploymentsColumnFilters();\n\n\tconst [{ data: deploymentsCount }, { data: deploymentsPage }] =\n\t\tuseSuspenseQueries({\n\t\t\tqueries: [\n\t\t\t\tbuildCountDeploymentsQuery(),\n\t\t\t\tbuildPaginateDeploymentsQuery(buildPaginationBody(search)),\n\t\t\t],\n\t\t});\n\n\tconst deployments = deploymentsPage?.results ?? [];\n\n\tconst { data: flows } = useQuery(\n\t\tbuildListFlowsQuery({\n\t\t\tflows: {\n\t\t\t\toperator: \"and_\",\n\t\t\t\tid: {\n\t\t\t\t\tany_: [\n\t\t\t\t\t\t...new Set(deployments.map((deployment) => deployment.flow_id)),\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t},\n\t\t\toffset: 0,\n\t\t\tsort: \"NAME_ASC\",\n\t\t}),\n\t);\n\n\tconst deploymentsWithFlows = deployments.map((deployment) => ({\n\t\t...deployment,\n\t\tflow: flows?.find((flow) => flow.id === deployment.flow_id),\n\t}));\n\n\treturn (\n\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t<DeploymentsPageHeader />\n\t\t\t{deploymentsCount === 0 ? (\n\t\t\t\t<DeploymentsEmptyState />\n\t\t\t) : (\n\t\t\t\t<DeploymentsDataTable\n\t\t\t\t\tdeployments={deploymentsWithFlows}\n\t\t\t\t\tcurrentDeploymentsCount={deploymentsCount}\n\t\t\t\t\tpageCount={deploymentsPage?.pages ?? 0}\n\t\t\t\t\tpagination={pagination}\n\t\t\t\t\tsort={sort}\n\t\t\t\t\tcolumnFilters={columnFilters}\n\t\t\t\t\tonPaginationChange={onPaginationChange}\n\t\t\t\t\tonSortChange={onSortChange}\n\t\t\t\t\tonColumnFiltersChange={onColumnFiltersChange}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n"],"names":["DeploymentsErrorComponent","error","reset","serverError","categorizeError","type","jsxs","jsx","DeploymentsPageHeader","RouteErrorState"],"mappings":"wWAiEA,SAASA,EAA0B,CAAEC,MAAAA,EAAOC,MAAAA,CAA2B,EAAG,CACzE,MAAMC,EAAcC,EAAgBH,EAAO,4BAA4B,EAIvE,GACCE,EAAYE,OAAS,gBACrBF,EAAYE,OAAS,eAErB,MAAMJ,EAGP,OACCK,EAAAA,KAAC,MAAA,CAAI,UAAU,sBACd,SAAA,CAAAC,EAAAA,IAACC,EAAA,EAAqB,EACtBD,EAAAA,IAACE,EAAA,CAAgB,MAAON,EAAa,QAASD,CAAAA,CAAM,CAAA,EACrD,CAEF"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{j as s,L as n,s as r}from"./vendor-tanstack-BdLtprmr.js";import{E as l,t as m,v as c,w as d,x,q as p,I as u,D as j,bv as g,ap as h,C as f,B as A,g as y,h as b,bw as D}from"./index-V_xTKaEb.js";import{D as N}from"./delete-confirmation-dialog-dLycVNo4.js";import{u as v,A as S,a as E,b as B,c as C,d as L}from"./use-delete-automation-confirmation-dialog-DZplMJDW.js";import{A as k}from"./automations-header-BxPCOE-0.js";import"./vendor-react-HBv6Kpyp.js";import"./vendor-radix-CJc458uP.js";import"./vendor-recharts-CY3PKigC.js";import"./vendor-forms-BlFSCfFw.js";import"./vendor-date-Cl1Jav-N.js";import"./work-queue-icon-text-vWlRNW-b.js";import"./index-B9ttjsyu.js";import"./dropdown-menu-B9LKPlz7.js";import"./use-delete-confirmation-dialog-CkL-rSsp.js";const I=()=>s.jsxs(l,{children:[s.jsx(m,{id:"Bot"}),s.jsx(c,{children:"Create an automation to get started"}),s.jsx(d,{children:"Automations bring reactivity to your data stack and let you configure triggers and actions based on events."}),s.jsxs(x,{children:[s.jsx(n,{to:"/automations/create",children:s.jsxs(p,{children:["Add Automation ",s.jsx(u,{id:"Plus",className:"size-4 ml-2"})]})}),s.jsx(j,{id:"automations-guide"})]})]}),T=()=>{const[e,i]=v(),{data:a}=r(g()),o=t=>i(t);return s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"flex flex-col gap-4",children:[s.jsx(k,{}),a.length===0?s.jsx(I,{}):s.jsxs("div",{className:"flex flex-col gap-4",children:[s.jsxs(h,{variant:"bodySmall",className:"text-muted-foreground",children:[a.length," ",`${a.length===1?"automation":"automations"}`]}),s.jsx("ul",{className:"flex flex-col gap-2",children:a.map(t=>s.jsx("li",{"aria-label":`automation item ${t.name}`,children:s.jsx(w,{automation:t,onDelete:()=>o(t)})},t.id))})]})]}),s.jsx(N,{...e})]})},w=({automation:e,onDelete:i})=>s.jsxs(f,{className:"p-4 pt-5 flex flex-col gap-6",children:[s.jsxs("div",{className:"flex items-center justify-between",children:[s.jsx($,{automation:e}),s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx(S,{automation:e}),s.jsx(E,{id:e.id,onDelete:i})]})]}),s.jsxs("div",{className:"flex flex-col gap-4",children:[e.description&&s.jsx(B,{automation:e}),s.jsx(C,{automation:e}),s.jsx(L,{automation:e})]})]}),$=({automation:e})=>s.jsx(A,{children:s.jsx(y,{children:s.jsx(b,{className:"text-xl",children:s.jsx(D,{to:"/automations/automation/$id",params:{id:e.id},className:"text-lg",children:e.name})})})}),W=T;export{W as component};
|
|
2
|
-
//# sourceMappingURL=index-BS7fbJ2s.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-BS7fbJ2s.js","sources":["../../src/components/automations/automations-empty-state/automations-empty-state.tsx","../../src/components/automations/automations-page.tsx","../../src/routes/automations/index.tsx?tsr-split=component"],"sourcesContent":["import { Link } from \"@tanstack/react-router\";\nimport { Button } from \"@/components/ui/button\";\nimport { DocsLink } from \"@/components/ui/docs-link\";\nimport {\n\tEmptyState,\n\tEmptyStateActions,\n\tEmptyStateDescription,\n\tEmptyStateIcon,\n\tEmptyStateTitle,\n} from \"@/components/ui/empty-state\";\nimport { Icon } from \"@/components/ui/icons\";\n\nexport const AutomationsEmptyState = () => {\n\treturn (\n\t\t<EmptyState>\n\t\t\t<EmptyStateIcon id=\"Bot\" />\n\t\t\t<EmptyStateTitle>Create an automation to get started</EmptyStateTitle>\n\t\t\t<EmptyStateDescription>\n\t\t\t\tAutomations bring reactivity to your data stack and let you configure\n\t\t\t\ttriggers and actions based on events.\n\t\t\t</EmptyStateDescription>\n\t\t\t<EmptyStateActions>\n\t\t\t\t<Link to=\"/automations/create\">\n\t\t\t\t\t<Button>\n\t\t\t\t\t\tAdd Automation <Icon id=\"Plus\" className=\"size-4 ml-2\" />\n\t\t\t\t\t</Button>\n\t\t\t\t</Link>\n\t\t\t\t<DocsLink id=\"automations-guide\" />\n\t\t\t</EmptyStateActions>\n\t\t</EmptyState>\n\t);\n};\n","import { useSuspenseQuery } from \"@tanstack/react-query\";\nimport { type Automation, buildListAutomationsQuery } from \"@/api/automations\";\nimport {\n\tBreadcrumb,\n\tBreadcrumbItem,\n\tBreadcrumbLink,\n\tBreadcrumbList,\n} from \"@/components/ui/breadcrumb\";\nimport { Card } from \"@/components/ui/card\";\nimport { DeleteConfirmationDialog } from \"@/components/ui/delete-confirmation-dialog\";\nimport { Typography } from \"../ui/typography\";\nimport {\n\tAutomationActions,\n\tAutomationDescription,\n\tAutomationTrigger,\n} from \"./automation-details\";\nimport { AutomationEnableToggle } from \"./automation-enable-toggle\";\nimport { AutomationsActionsMenu } from \"./automations-actions-menu\";\nimport { AutomationsEmptyState } from \"./automations-empty-state\";\nimport { AutomationsHeader } from \"./automations-header\";\nimport { useDeleteAutomationConfirmationDialog } from \"./use-delete-automation-confirmation-dialog\";\n\nexport const AutomationsPage = () => {\n\tconst [dialogState, confirmDelete] = useDeleteAutomationConfirmationDialog();\n\tconst { data } = useSuspenseQuery(buildListAutomationsQuery());\n\n\tconst handleDelete = (automation: Automation) => confirmDelete(automation);\n\n\treturn (\n\t\t<>\n\t\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t\t<AutomationsHeader />\n\t\t\t\t{data.length === 0 ? (\n\t\t\t\t\t<AutomationsEmptyState />\n\t\t\t\t) : (\n\t\t\t\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t\t\t\t<Typography variant=\"bodySmall\" className=\"text-muted-foreground\">\n\t\t\t\t\t\t\t{data.length}{\" \"}\n\t\t\t\t\t\t\t{`${data.length === 1 ? \"automation\" : \"automations\"}`}\n\t\t\t\t\t\t</Typography>\n\t\t\t\t\t\t<ul className=\"flex flex-col gap-2\">\n\t\t\t\t\t\t\t{data.map((automation) => (\n\t\t\t\t\t\t\t\t<li\n\t\t\t\t\t\t\t\t\tkey={automation.id}\n\t\t\t\t\t\t\t\t\taria-label={`automation item ${automation.name}`}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<AutomationCardDetails\n\t\t\t\t\t\t\t\t\t\tautomation={automation}\n\t\t\t\t\t\t\t\t\t\tonDelete={() => handleDelete(automation)}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</ul>\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t\t<DeleteConfirmationDialog {...dialogState} />\n\t\t</>\n\t);\n};\n\ntype AutomationCardDetailsProps = {\n\tautomation: Automation;\n\tonDelete: () => void;\n};\nconst AutomationCardDetails = ({\n\tautomation,\n\tonDelete,\n}: AutomationCardDetailsProps) => {\n\treturn (\n\t\t<Card className=\"p-4 pt-5 flex flex-col gap-6\">\n\t\t\t<div className=\"flex items-center justify-between\">\n\t\t\t\t<NavHeader automation={automation} />\n\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t<AutomationEnableToggle automation={automation} />\n\t\t\t\t\t<AutomationsActionsMenu id={automation.id} onDelete={onDelete} />\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t\t{automation.description && (\n\t\t\t\t\t<AutomationDescription automation={automation} />\n\t\t\t\t)}\n\t\t\t\t<AutomationTrigger automation={automation} />\n\t\t\t\t<AutomationActions automation={automation} />\n\t\t\t</div>\n\t\t</Card>\n\t);\n};\n\ntype NavHeaderProps = {\n\tautomation: Automation;\n};\n\nconst NavHeader = ({ automation }: NavHeaderProps) => {\n\treturn (\n\t\t<Breadcrumb>\n\t\t\t<BreadcrumbList>\n\t\t\t\t<BreadcrumbItem className=\"text-xl\">\n\t\t\t\t\t<BreadcrumbLink\n\t\t\t\t\t\tto=\"/automations/automation/$id\"\n\t\t\t\t\t\tparams={{ id: automation.id }}\n\t\t\t\t\t\tclassName=\"text-lg\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{automation.name}\n\t\t\t\t\t</BreadcrumbLink>\n\t\t\t\t</BreadcrumbItem>\n\t\t\t</BreadcrumbList>\n\t\t</Breadcrumb>\n\t);\n};\n","import type { ErrorComponentProps } from \"@tanstack/react-router\";\nimport { createFileRoute } from \"@tanstack/react-router\";\nimport { buildListAutomationsQuery } from \"@/api/automations\";\nimport { categorizeError } from \"@/api/error-utils\";\nimport { AutomationsHeader } from \"@/components/automations/automations-header\";\nimport { AutomationsPage } from \"@/components/automations/automations-page\";\nimport { RouteErrorState } from \"@/components/ui/route-error-state\";\n\nfunction AutomationsErrorComponent({ error, reset }: ErrorComponentProps) {\n\tconst serverError = categorizeError(error, \"Failed to load automations\");\n\n\t// Only handle API errors (server-error, client-error) at route level\n\t// Let network errors and unknown errors bubble up to root error component\n\tif (\n\t\tserverError.type !== \"server-error\" &&\n\t\tserverError.type !== \"client-error\"\n\t) {\n\t\tthrow error;\n\t}\n\n\treturn (\n\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t<AutomationsHeader />\n\t\t\t<RouteErrorState error={serverError} onRetry={reset} />\n\t\t</div>\n\t);\n}\n\n// nb: Currently there is no filtering or search params used on this page\nexport const Route = createFileRoute(\"/automations/\")({\n\tcomponent: AutomationsPage,\n\terrorComponent: AutomationsErrorComponent,\n\tloader: ({ context }) =>\n\t\tcontext.queryClient.ensureQueryData(buildListAutomationsQuery()),\n\twrapInSuspense: true,\n});\n"],"names":["AutomationsEmptyState","EmptyState","jsx","EmptyStateIcon","EmptyStateTitle","EmptyStateDescription","EmptyStateActions","Link","jsxs","Button","Icon","DocsLink","AutomationsPage","dialogState","confirmDelete","useDeleteAutomationConfirmationDialog","data","useSuspenseQuery","buildListAutomationsQuery","handleDelete","automation","Fragment","AutomationsHeader","Typography","AutomationCardDetails","DeleteConfirmationDialog","onDelete","Card","NavHeader","AutomationEnableToggle","AutomationsActionsMenu","AutomationDescription","AutomationTrigger","AutomationActions","Breadcrumb","BreadcrumbList","BreadcrumbItem","BreadcrumbLink","SplitComponent"],"mappings":"0vBAYO,MAAMA,EAAwB,WAElCC,EAAA,CACA,SAAA,CAAAC,EAAAA,IAACC,EAAA,CAAe,GAAG,KAAA,CAAM,EACzBD,EAAAA,IAACE,GAAgB,SAAA,qCAAA,CAAmC,EACpDF,EAAAA,IAACG,GAAsB,SAAA,6GAAA,CAGvB,SACCC,EAAA,CACA,SAAA,CAAAJ,MAACK,EAAA,CAAK,GAAG,sBACR,SAAAC,EAAAA,KAACC,EAAA,CAAO,SAAA,CAAA,kBACQP,EAAAA,IAACQ,EAAA,CAAK,GAAG,OAAO,UAAU,aAAA,CAAc,CAAA,CAAA,CACxD,CAAA,CACD,EACAR,EAAAA,IAACS,EAAA,CAAS,GAAG,mBAAA,CAAoB,CAAA,CAAA,CAClC,CAAA,EACD,ECPWC,EAAkB,IAAM,CACpC,KAAM,CAACC,EAAaC,CAAa,EAAIC,EAAA,EAC/B,CAAE,KAAAC,CAAA,EAASC,EAAiBC,GAA2B,EAEvDC,EAAgBC,GAA2BN,EAAcM,CAAU,EAEzE,OACCZ,EAAAA,KAAAa,WAAA,CACC,SAAA,CAAAb,EAAAA,KAAC,MAAA,CAAI,UAAU,sBACd,SAAA,CAAAN,EAAAA,IAACoB,EAAA,EAAkB,EAClBN,EAAK,SAAW,EAChBd,EAAAA,IAACF,IAAsB,EAEvBQ,EAAAA,KAAC,MAAA,CAAI,UAAU,sBACd,SAAA,CAAAA,EAAAA,KAACe,EAAA,CAAW,QAAQ,YAAY,UAAU,wBACxC,SAAA,CAAAP,EAAK,OAAQ,IACb,GAAGA,EAAK,SAAW,EAAI,aAAe,aAAa,EAAA,EACrD,QACC,KAAA,CAAG,UAAU,sBACZ,SAAAA,EAAK,IAAKI,GACVlB,EAAAA,IAAC,KAAA,CAEA,aAAY,mBAAmBkB,EAAW,IAAI,GAE9C,SAAAlB,EAAAA,IAACsB,EAAA,CACA,WAAAJ,EACA,SAAU,IAAMD,EAAaC,CAAU,CAAA,CAAA,CACxC,EANKA,EAAW,EAAA,CAQjB,CAAA,CACF,CAAA,CAAA,CACD,CAAA,EAEF,EACAlB,MAACuB,EAAA,CAA0B,GAAGZ,CAAA,CAAa,CAAA,EAC5C,CAEF,EAMMW,EAAwB,CAAC,CAC9B,WAAAJ,EACA,SAAAM,CACD,IAEElB,EAAAA,KAACmB,EAAA,CAAK,UAAU,+BACf,SAAA,CAAAnB,EAAAA,KAAC,MAAA,CAAI,UAAU,oCACd,SAAA,CAAAN,MAAC0B,GAAU,WAAAR,EAAwB,EACnCZ,EAAAA,KAAC,MAAA,CAAI,UAAU,0BACd,SAAA,CAAAN,MAAC2B,GAAuB,WAAAT,EAAwB,EAChDlB,EAAAA,IAAC4B,EAAA,CAAuB,GAAIV,EAAW,GAAI,SAAAM,CAAA,CAAoB,CAAA,CAAA,CAChE,CAAA,EACD,EACAlB,EAAAA,KAAC,MAAA,CAAI,UAAU,sBACb,SAAA,CAAAY,EAAW,aACXlB,EAAAA,IAAC6B,EAAA,CAAsB,WAAAX,CAAA,CAAwB,EAEhDlB,MAAC8B,GAAkB,WAAAZ,EAAwB,EAC3ClB,MAAC+B,GAAkB,WAAAb,CAAA,CAAwB,CAAA,CAAA,CAC5C,CAAA,EACD,EAQIQ,EAAY,CAAC,CAAE,WAAAR,WAElBc,EAAA,CACA,SAAAhC,EAAAA,IAACiC,GACA,SAAAjC,EAAAA,IAACkC,EAAA,CAAe,UAAU,UACzB,SAAAlC,EAAAA,IAACmC,EAAA,CACA,GAAG,8BACH,OAAQ,CAAE,GAAIjB,EAAW,EAAA,EACzB,UAAU,UAET,SAAAA,EAAW,IAAA,CAAA,CACb,CACD,EACD,EACD,EC/EFkB,EAvBS1B"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-C5RMFRyZ.js","sources":["../../src/components/variables/data-table/cells.tsx","../../src/components/variables/data-table/data-table.tsx","../../src/components/variables/empty-state.tsx","../../src/components/variables/variable-dialog/use-variable-dialog.ts","../../src/components/variables/variable-dialog/variable-dialog.tsx","../../src/routes/variables/index.tsx?tsr-split=component"],"sourcesContent":["import type { CellContext } from \"@tanstack/react-table\";\nimport { useRef } from \"react\";\nimport { toast } from \"sonner\";\nimport type { components } from \"@/api/prefect\";\nimport { useDeleteVariable } from \"@/api/variables\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n\tDropdownMenu,\n\tDropdownMenuContent,\n\tDropdownMenuItem,\n\tDropdownMenuLabel,\n\tDropdownMenuTrigger,\n} from \"@/components/ui/dropdown-menu\";\nimport {\n\tHoverCard,\n\tHoverCardContent,\n\tHoverCardTrigger,\n} from \"@/components/ui/hover-card\";\nimport { Icon } from \"@/components/ui/icons\";\nimport { LazyJsonInput as JsonInput } from \"@/components/ui/json-input-lazy\";\nimport { useIsOverflowing } from \"@/hooks/use-is-overflowing\";\n\ntype ActionsCellProps = CellContext<\n\tcomponents[\"schemas\"][\"Variable\"],\n\tunknown\n> & {\n\tonVariableEdit: (variable: components[\"schemas\"][\"Variable\"]) => void;\n};\n\nexport const ActionsCell = ({ row, onVariableEdit }: ActionsCellProps) => {\n\tconst id = row.original.id;\n\tconst { deleteVariable } = useDeleteVariable();\n\tif (!id) return null;\n\n\tconst onVariableDelete = () => {\n\t\tdeleteVariable(id, {\n\t\t\tonSuccess: () => {\n\t\t\t\ttoast.success(\"Variable deleted\");\n\t\t\t},\n\t\t});\n\t};\n\n\treturn (\n\t\t<div className=\"flex flex-row justify-end\">\n\t\t\t<DropdownMenu>\n\t\t\t\t<DropdownMenuTrigger asChild>\n\t\t\t\t\t<Button variant=\"outline\" className=\"size-8 p-0\">\n\t\t\t\t\t\t<span className=\"sr-only\">Open menu</span>\n\t\t\t\t\t\t<Icon id=\"MoreVertical\" className=\"size-4\" />\n\t\t\t\t\t</Button>\n\t\t\t\t</DropdownMenuTrigger>\n\t\t\t\t<DropdownMenuContent align=\"end\">\n\t\t\t\t\t<DropdownMenuLabel>Actions</DropdownMenuLabel>\n\t\t\t\t\t<DropdownMenuItem\n\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\tvoid navigator.clipboard.writeText(id);\n\t\t\t\t\t\t\ttoast.success(\"ID copied\");\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tCopy ID\n\t\t\t\t\t</DropdownMenuItem>\n\t\t\t\t\t<DropdownMenuItem\n\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\tvoid navigator.clipboard.writeText(row.original.name);\n\t\t\t\t\t\t\ttoast.success(\"Name copied\");\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tCopy Name\n\t\t\t\t\t</DropdownMenuItem>\n\t\t\t\t\t<DropdownMenuItem\n\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\tconst copyValue =\n\t\t\t\t\t\t\t\ttypeof row.original.value !== \"string\"\n\t\t\t\t\t\t\t\t\t? JSON.stringify(row.original.value)\n\t\t\t\t\t\t\t\t\t: row.original.value;\n\t\t\t\t\t\t\tif (copyValue) {\n\t\t\t\t\t\t\t\tvoid navigator.clipboard.writeText(copyValue);\n\t\t\t\t\t\t\t\ttoast.success(\"Value copied\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tCopy Value\n\t\t\t\t\t</DropdownMenuItem>\n\t\t\t\t\t<DropdownMenuItem onClick={() => onVariableEdit(row.original)}>\n\t\t\t\t\t\tEdit\n\t\t\t\t\t</DropdownMenuItem>\n\t\t\t\t\t<DropdownMenuItem onClick={onVariableDelete}>Delete</DropdownMenuItem>\n\t\t\t\t</DropdownMenuContent>\n\t\t\t</DropdownMenu>\n\t\t</div>\n\t);\n};\n\nexport const ValueCell = (\n\tprops: CellContext<components[\"schemas\"][\"Variable\"], unknown>,\n) => {\n\tconst value = props.getValue();\n\tconst codeRef = useRef<HTMLDivElement>(null);\n\tconst isOverflowing = useIsOverflowing(codeRef);\n\n\tif (!value) return null;\n\treturn (\n\t\t// Disable the hover card if the value is not overflowing\n\t\t<HoverCard open={isOverflowing ? undefined : false}>\n\t\t\t<HoverCardTrigger asChild>\n\t\t\t\t<code\n\t\t\t\t\tref={codeRef}\n\t\t\t\t\tclassName=\"px-2 py-1 font-mono text-sm text-ellipsis overflow-hidden whitespace-nowrap block\"\n\t\t\t\t>\n\t\t\t\t\t{JSON.stringify(value, null, 2)}\n\t\t\t\t</code>\n\t\t\t</HoverCardTrigger>\n\t\t\t<HoverCardContent className=\"p-0\">\n\t\t\t\t<JsonInput value={JSON.stringify(value, null, 2)} disabled />\n\t\t\t</HoverCardContent>\n\t\t</HoverCard>\n\t);\n};\n","import {\n\ttype ColumnFiltersState,\n\tcreateColumnHelper,\n\tgetCoreRowModel,\n\ttype OnChangeFn,\n\ttype PaginationState,\n\tuseReactTable,\n} from \"@tanstack/react-table\";\nimport type React from \"react\";\nimport { useCallback, useMemo } from \"react\";\nimport type { components } from \"@/api/prefect\";\nimport { DataTable } from \"@/components/ui/data-table\";\nimport { SearchInput } from \"@/components/ui/input\";\nimport {\n\tSelect,\n\tSelectContent,\n\tSelectItem,\n\tSelectTrigger,\n\tSelectValue,\n} from \"@/components/ui/select\";\nimport { TagBadgeGroup } from \"@/components/ui/tag-badge-group\";\nimport { TagsInput } from \"@/components/ui/tags-input\";\nimport { pluralize } from \"@/utils\";\nimport { ActionsCell, ValueCell } from \"./cells\";\n\nconst columnHelper = createColumnHelper<components[\"schemas\"][\"Variable\"]>();\n\nconst createColumns = (\n\tonVariableEdit: (variable: components[\"schemas\"][\"Variable\"]) => void,\n) => [\n\tcolumnHelper.accessor(\"name\", {\n\t\theader: \"Name\",\n\t}),\n\tcolumnHelper.accessor(\"value\", {\n\t\theader: \"Value\",\n\t\tcell: ValueCell,\n\t}),\n\tcolumnHelper.accessor(\"updated\", {\n\t\theader: \"Updated\",\n\t\tcell: (props) => {\n\t\t\tconst updated = props.getValue();\n\t\t\tif (!updated) return null;\n\t\t\treturn new Date(updated ?? new Date())\n\t\t\t\t.toLocaleString(undefined, {\n\t\t\t\t\tyear: \"numeric\",\n\t\t\t\t\tmonth: \"numeric\",\n\t\t\t\t\tday: \"numeric\",\n\t\t\t\t\thour: \"numeric\",\n\t\t\t\t\tminute: \"numeric\",\n\t\t\t\t\tsecond: \"numeric\",\n\t\t\t\t\thour12: true,\n\t\t\t\t})\n\t\t\t\t.replace(\",\", \"\");\n\t\t},\n\t}),\n\tcolumnHelper.accessor(\"tags\", {\n\t\theader: () => null,\n\t\tcell: (props) => {\n\t\t\tconst tags = props.getValue();\n\t\t\tif (!tags) return null;\n\t\t\treturn <TagBadgeGroup tags={tags} maxTagsDisplayed={3} />;\n\t\t},\n\t}),\n\tcolumnHelper.display({\n\t\tid: \"actions\",\n\t\tcell: (props) => <ActionsCell {...props} onVariableEdit={onVariableEdit} />,\n\t}),\n];\n\ntype VariablesDataTableProps = {\n\tvariables: components[\"schemas\"][\"Variable\"][];\n\tcurrentVariableCount: number;\n\tpagination: PaginationState;\n\tonPaginationChange: (newPagination: PaginationState) => void;\n\tcolumnFilters: ColumnFiltersState;\n\tonColumnFiltersChange: (newColumnFilters: ColumnFiltersState) => void;\n\tsorting: components[\"schemas\"][\"VariableSort\"];\n\tonSortingChange: (sortKey: components[\"schemas\"][\"VariableSort\"]) => void;\n\tonVariableEdit: (variable: components[\"schemas\"][\"Variable\"]) => void;\n};\n\nexport const VariablesDataTable = ({\n\tvariables,\n\tcurrentVariableCount,\n\tpagination,\n\tonPaginationChange,\n\tcolumnFilters,\n\tonColumnFiltersChange,\n\tsorting,\n\tonSortingChange,\n\tonVariableEdit,\n}: VariablesDataTableProps) => {\n\tconst columns = useMemo(\n\t\t() => createColumns(onVariableEdit),\n\t\t[onVariableEdit],\n\t);\n\n\tconst nameSearchValue = columnFilters.find((filter) => filter.id === \"name\")\n\t\t?.value as string;\n\tconst tagsSearchValue = columnFilters.find((filter) => filter.id === \"tags\")\n\t\t?.value as string[];\n\tconst handleNameSearchChange = useCallback(\n\t\t(value?: string) => {\n\t\t\tconst filters = columnFilters.filter((filter) => filter.id !== \"name\");\n\t\t\tonColumnFiltersChange(\n\t\t\t\tvalue ? [...filters, { id: \"name\", value }] : filters,\n\t\t\t);\n\t\t},\n\t\t[onColumnFiltersChange, columnFilters],\n\t);\n\n\tconst handleTagsSearchChange: React.ChangeEventHandler<HTMLInputElement> &\n\t\t((tags: string[]) => void) = useCallback(\n\t\t(e: string[] | React.ChangeEvent<HTMLInputElement>) => {\n\t\t\tconst tags = Array.isArray(e) ? e : e.target.value;\n\t\t\tconst filters = columnFilters.filter((filter) => filter.id !== \"tags\");\n\t\t\tonColumnFiltersChange(\n\t\t\t\ttags.length ? [...filters, { id: \"tags\", value: tags }] : filters,\n\t\t\t);\n\t\t},\n\t\t[onColumnFiltersChange, columnFilters],\n\t);\n\n\tconst handlePaginationChange: OnChangeFn<PaginationState> = useCallback(\n\t\t(updater) => {\n\t\t\tlet newPagination = pagination;\n\t\t\tif (typeof updater === \"function\") {\n\t\t\t\tnewPagination = updater(pagination);\n\t\t\t} else {\n\t\t\t\tnewPagination = updater;\n\t\t\t}\n\t\t\tonPaginationChange(newPagination);\n\t\t},\n\t\t[pagination, onPaginationChange],\n\t);\n\n\tconst table = useReactTable({\n\t\tdata: variables,\n\t\tcolumns: columns,\n\t\tstate: {\n\t\t\tpagination,\n\t\t\tcolumnFilters,\n\t\t},\n\t\tgetCoreRowModel: getCoreRowModel(),\n\t\tmanualPagination: true,\n\t\tonPaginationChange: handlePaginationChange,\n\t\trowCount: currentVariableCount,\n\t\tdefaultColumn: {\n\t\t\tmaxSize: 300,\n\t\t},\n\t});\n\n\treturn (\n\t\t<div>\n\t\t\t<div className=\"grid sm:grid-cols-2 md:grid-cols-6 lg:grid-cols-12 gap-2 pb-4 items-center\">\n\t\t\t\t<div className=\"sm:col-span-2 md:col-span-6 lg:col-span-4 order-last lg:order-first\">\n\t\t\t\t\t<p className=\"text-sm text-muted-foreground\">\n\t\t\t\t\t\t{currentVariableCount} {pluralize(currentVariableCount, \"Variable\")}\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\t\t\t\t<div className=\"sm:col-span-2 md:col-span-2 lg:col-span-3\">\n\t\t\t\t\t<SearchInput\n\t\t\t\t\t\tplaceholder=\"Search variables\"\n\t\t\t\t\t\tvalue={nameSearchValue}\n\t\t\t\t\t\tonChange={(e) => handleNameSearchChange(e.target.value)}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t\t<div className=\"xs:col-span-1 md:col-span-2 lg:col-span-3\">\n\t\t\t\t\t<TagsInput\n\t\t\t\t\t\tplaceholder=\"Filter by tags\"\n\t\t\t\t\t\tonChange={handleTagsSearchChange}\n\t\t\t\t\t\tvalue={tagsSearchValue}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t\t<div className=\"xs:col-span-1 md:col-span-2 lg:col-span-2\">\n\t\t\t\t\t<Select value={sorting} onValueChange={onSortingChange}>\n\t\t\t\t\t\t<SelectTrigger aria-label=\"Variable sort order\" className=\"w-full\">\n\t\t\t\t\t\t\t<SelectValue placeholder=\"Sort by\" />\n\t\t\t\t\t\t</SelectTrigger>\n\t\t\t\t\t\t<SelectContent>\n\t\t\t\t\t\t\t<SelectItem value=\"CREATED_DESC\">Created</SelectItem>\n\t\t\t\t\t\t\t<SelectItem value=\"UPDATED_DESC\">Updated</SelectItem>\n\t\t\t\t\t\t\t<SelectItem value=\"NAME_ASC\">A to Z</SelectItem>\n\t\t\t\t\t\t\t<SelectItem value=\"NAME_DESC\">Z to A</SelectItem>\n\t\t\t\t\t\t</SelectContent>\n\t\t\t\t\t</Select>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<DataTable table={table} />\n\t\t</div>\n\t);\n};\n","import { Button } from \"@/components/ui/button\";\nimport { DocsLink } from \"@/components/ui/docs-link\";\nimport {\n\tEmptyState,\n\tEmptyStateActions,\n\tEmptyStateDescription,\n\tEmptyStateIcon,\n\tEmptyStateTitle,\n} from \"@/components/ui/empty-state\";\nimport { Icon } from \"@/components/ui/icons\";\n\ntype VariablesEmptyStateProps = {\n\tonAddVariableClick: () => void;\n};\nexport const VariablesEmptyState = ({\n\tonAddVariableClick,\n}: VariablesEmptyStateProps) => (\n\t<EmptyState>\n\t\t<EmptyStateIcon id=\"Variable\" />\n\t\t<EmptyStateTitle>Add a variable to get started</EmptyStateTitle>\n\t\t<EmptyStateDescription>\n\t\t\tVariables store non-sensitive pieces of JSON.\n\t\t</EmptyStateDescription>\n\t\t<EmptyStateActions>\n\t\t\t<Button onClick={() => onAddVariableClick()}>\n\t\t\t\tAdd Variable <Icon id=\"Plus\" className=\"size-4 ml-2\" />\n\t\t\t</Button>\n\t\t\t<DocsLink id=\"variables-guide\" />\n\t\t</EmptyStateActions>\n\t</EmptyState>\n);\n","import { useCallback, useState } from \"react\";\nimport type { VariableDialogProps } from \"./variable-dialog\";\n\nexport const useVariableDialog = () => {\n\tconst handleVariableDialogOpenChange = useCallback((open: boolean) => {\n\t\tsetDialogState((prev) => ({\n\t\t\t...prev,\n\t\t\topen,\n\t\t}));\n\t}, []);\n\n\tconst [dialogState, setDialogState] = useState<VariableDialogProps>({\n\t\topen: false,\n\t\tonOpenChange: handleVariableDialogOpenChange,\n\t});\n\n\tconst handleVariableAddOrEdit = useCallback(\n\t\t(variableToEdit?: VariableDialogProps[\"variableToEdit\"]) => {\n\t\t\tsetDialogState((prev) => ({\n\t\t\t\t...prev,\n\t\t\t\topen: true,\n\t\t\t\tvariableToEdit,\n\t\t\t}));\n\t\t},\n\t\t[],\n\t);\n\n\treturn [dialogState, handleVariableAddOrEdit] as const;\n};\n","import { zodResolver } from \"@hookform/resolvers/zod\";\nimport { useEffect, useMemo } from \"react\";\nimport { useForm } from \"react-hook-form\";\nimport { toast } from \"sonner\";\nimport { z } from \"zod\";\nimport type { components } from \"@/api/prefect\";\nimport { useCreateVariable, useUpdateVariable } from \"@/api/variables\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n\tDialog,\n\tDialogClose,\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\";\nimport { LazyJsonInput as JsonInput } from \"@/components/ui/json-input-lazy\";\nimport { TagsInput } from \"@/components/ui/tags-input\";\n\nexport type JSONValue =\n\t| string\n\t| number\n\t| boolean\n\t| Record<string, never>\n\t| unknown[]\n\t| null;\n\nconst formSchema = z.object({\n\tname: z.string().min(2, { message: \"Name must be at least 2 characters\" }),\n\tvalue: z.string(),\n\ttags: z.string().array().optional(),\n});\n\nexport type VariableDialogProps = {\n\tonOpenChange: (open: boolean) => void;\n\topen: boolean;\n\tvariableToEdit?: components[\"schemas\"][\"Variable\"];\n};\n\nconst VARIABLE_FORM_DEFAULT_VALUES = {\n\tname: \"\",\n\tvalue: \"\",\n\ttags: [],\n};\n\nexport const VariableDialog = ({\n\tonOpenChange,\n\topen,\n\tvariableToEdit,\n}: VariableDialogProps) => {\n\tconst form = useForm({\n\t\tresolver: zodResolver(formSchema),\n\t\tdefaultValues: VARIABLE_FORM_DEFAULT_VALUES,\n\t});\n\tconst initialValues = useMemo(() => {\n\t\tif (!variableToEdit) return undefined;\n\t\treturn {\n\t\t\tname: variableToEdit.name,\n\t\t\tvalue: JSON.stringify(variableToEdit.value, null, 2),\n\t\t\ttags: variableToEdit.tags,\n\t\t};\n\t}, [variableToEdit]);\n\n\tuseEffect(() => {\n\t\t// Ensure we start with the initial values when the dialog opens\n\t\tif (open) {\n\t\t\tform.reset(initialValues ?? VARIABLE_FORM_DEFAULT_VALUES);\n\t\t}\n\t}, [initialValues, form, open]);\n\n\tconst { createVariable, isPending: isCreating } = useCreateVariable();\n\n\tconst { updateVariable, isPending: isUpdating } = useUpdateVariable();\n\n\tconst onSubmit = (values: z.infer<typeof formSchema>) => {\n\t\ttry {\n\t\t\tconst value = JSON.parse(values.value) as JSONValue;\n\t\t\tif (variableToEdit?.id) {\n\t\t\t\tupdateVariable(\n\t\t\t\t\t{\n\t\t\t\t\t\tid: variableToEdit.id,\n\t\t\t\t\t\tname: values.name,\n\t\t\t\t\t\tvalue,\n\t\t\t\t\t\ttags: values.tags,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tonSuccess: () => {\n\t\t\t\t\t\t\ttoast.success(\"Variable updated\");\n\t\t\t\t\t\t\tonOpenChange(false);\n\t\t\t\t\t\t},\n\t\t\t\t\t\tonError: (error) => {\n\t\t\t\t\t\t\tconst message =\n\t\t\t\t\t\t\t\terror.message || \"Unknown error while updating variable.\";\n\t\t\t\t\t\t\tform.setError(\"root\", {\n\t\t\t\t\t\t\t\tmessage,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tcreateVariable(\n\t\t\t\t\t{\n\t\t\t\t\t\tname: values.name,\n\t\t\t\t\t\tvalue,\n\t\t\t\t\t\ttags: values.tags,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tonSuccess: () => {\n\t\t\t\t\t\t\ttoast.success(\"Variable created\");\n\t\t\t\t\t\t\tonOpenChange(false);\n\t\t\t\t\t\t},\n\t\t\t\t\t\tonError: (error) => {\n\t\t\t\t\t\t\tconst message =\n\t\t\t\t\t\t\t\terror.message || \"Unknown error while creating variable.\";\n\t\t\t\t\t\t\tform.setError(\"root\", {\n\t\t\t\t\t\t\t\tmessage,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t} catch {\n\t\t\tform.setError(\"value\", { message: \"Value must be valid JSON\" });\n\t\t}\n\t};\n\tconst dialogTitle = variableToEdit ? \"Edit Variable\" : \"New Variable\";\n\tconst dialogDescription = variableToEdit\n\t\t? \"Edit the variable by changing the name, value, or tags.\"\n\t\t: \"Add a new variable by providing a name, value, and optional tags. Values can be any valid JSON value.\";\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>{dialogTitle}</DialogTitle>\n\t\t\t\t</DialogHeader>\n\t\t\t\t<DialogDescription>{dialogDescription}</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<FormMessage>{form.formState.errors.root?.message}</FormMessage>\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>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 autoComplete=\"off\" {...field} />\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<FormField\n\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\tname=\"value\"\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>Value</FormLabel>\n\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t<JsonInput {...field} />\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<FormField\n\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\tname=\"tags\"\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>Tags</FormLabel>\n\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t<TagsInput {...field} />\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<DialogClose asChild>\n\t\t\t\t\t\t\t\t<Button type=\"button\" variant=\"outline\">\n\t\t\t\t\t\t\t\t\tClose\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t</DialogClose>\n\t\t\t\t\t\t\t<Button type=\"submit\" loading={isCreating || isUpdating}>\n\t\t\t\t\t\t\t\t{variableToEdit ? \"Save\" : \"Create\"}\n\t\t\t\t\t\t\t</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 { useSuspenseQueries } from \"@tanstack/react-query\";\nimport type { ErrorComponentProps } from \"@tanstack/react-router\";\nimport { createFileRoute } from \"@tanstack/react-router\";\nimport type {\n\tColumnFiltersState,\n\tPaginationState,\n} from \"@tanstack/react-table\";\nimport { zodValidator } from \"@tanstack/zod-adapter\";\nimport { useCallback, useMemo } from \"react\";\nimport { z } from \"zod\";\nimport { categorizeError } from \"@/api/error-utils\";\nimport type { components } from \"@/api/prefect\";\nimport {\n\tbuildCountVariablesQuery,\n\tbuildFilterVariablesQuery,\n\ttype VariablesFilter,\n} from \"@/api/variables\";\nimport { RouteErrorState } from \"@/components/ui/route-error-state\";\nimport { VariablesDataTable } from \"@/components/variables/data-table\";\nimport { VariablesEmptyState } from \"@/components/variables/empty-state\";\nimport { VariablesPageHeader } from \"@/components/variables/header\";\nimport {\n\tuseVariableDialog,\n\tVariableDialog,\n} from \"@/components/variables/variable-dialog\";\n\n/**\n * Schema for validating URL search parameters for the variables page.\n * @property {number} offset - The number of items to skip (for pagination). Must be non-negative. Defaults to 0.\n * @property {number} limit - The maximum number of items to return. Must be positive. Defaults to 10.\n * @property {string} sort - The sort order for variables. Can be \"CREATED_DESC\", \"UPDATED_DESC\", \"NAME_ASC\", or \"NAME_DESC\". Defaults to \"CREATED_DESC\".\n * @property {string} name - Optional filter to search variables by name.\n * @property {string[]} tags - Optional array of tags to filter variables by.\n */\nconst searchParams = z.object({\n\toffset: z.number().int().nonnegative().optional().default(0).catch(0),\n\tlimit: z.number().int().positive().optional().default(10).catch(10),\n\tsort: z\n\t\t.enum([\"CREATED_DESC\", \"UPDATED_DESC\", \"NAME_ASC\", \"NAME_DESC\"])\n\t\t.optional()\n\t\t.default(\"CREATED_DESC\")\n\t\t.catch(\"CREATED_DESC\"),\n\tname: z.string().optional().catch(undefined),\n\ttags: z.array(z.string()).optional().catch(undefined),\n});\n\n/**\n * Builds a filter body for the variables API based on search parameters.\n * @param search - Optional search parameters containing offset, limit, sort, name filter, and tags filter\n * @returns An object containing pagination parameters and variable filters that can be passed to the variables API\n */\nconst buildFilterBody = (\n\tsearch?: z.infer<typeof searchParams>,\n): VariablesFilter => ({\n\toffset: search?.offset ?? 0,\n\tlimit: search?.limit ?? 10,\n\tsort: search?.sort ?? \"CREATED_DESC\",\n\tvariables: {\n\t\toperator: \"and_\" as const,\n\t\t...(search?.name && { name: { like_: search.name } }),\n\t\t...(search?.tags?.length && {\n\t\t\ttags: { operator: \"and_\" as const, all_: search.tags },\n\t\t}),\n\t},\n});\n\nfunction VariablesErrorComponent({ error, reset }: ErrorComponentProps) {\n\tconst serverError = categorizeError(error, \"Failed to load variables\");\n\n\t// Only handle API errors (server-error, client-error) at route level\n\t// Let network errors and unknown errors bubble up to root error component\n\tif (\n\t\tserverError.type !== \"server-error\" &&\n\t\tserverError.type !== \"client-error\"\n\t) {\n\t\tthrow error;\n\t}\n\n\treturn (\n\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t<VariablesPageHeader />\n\t\t\t<RouteErrorState error={serverError} onRetry={reset} />\n\t\t</div>\n\t);\n}\n\nexport const Route = createFileRoute(\"/variables/\")({\n\tvalidateSearch: zodValidator(searchParams),\n\tcomponent: RouteComponent,\n\terrorComponent: VariablesErrorComponent,\n\tloaderDeps: ({ search }) => buildFilterBody(search),\n\tloader: ({ deps, context }) => {\n\t\t// Prefetch filtered variables\n\t\tvoid context.queryClient.prefetchQuery(buildFilterVariablesQuery(deps));\n\t\t// Prefetch filtered count\n\t\tvoid context.queryClient.prefetchQuery(buildCountVariablesQuery(deps));\n\t\t// Prefetch total count (no filter)\n\t\tvoid context.queryClient.prefetchQuery(buildCountVariablesQuery());\n\t},\n\twrapInSuspense: true,\n});\n\n/**\n * Hook to manage pagination state and navigation for variables table\n *\n * Calculates current page index and size from URL search parameters and provides\n * a callback to update pagination state. Updates the URL when pagination changes.\n *\n * @returns A tuple containing:\n * - pagination: Current pagination state with pageIndex and pageSize\n * - onPaginationChange: Callback to update pagination and navigate with new search params\n */\nconst usePagination = () => {\n\tconst search = Route.useSearch();\n\tconst navigate = Route.useNavigate();\n\n\tconst pageIndex = search.offset ? Math.ceil(search.offset / search.limit) : 0;\n\tconst pageSize = search.limit ?? 10;\n\tconst pagination: PaginationState = useMemo(\n\t\t() => ({\n\t\t\tpageIndex,\n\t\t\tpageSize,\n\t\t}),\n\t\t[pageIndex, pageSize],\n\t);\n\n\tconst onPaginationChange = useCallback(\n\t\t(newPagination: PaginationState) => {\n\t\t\tvoid navigate({\n\t\t\t\tto: \".\",\n\t\t\t\tsearch: (prev) => ({\n\t\t\t\t\t...prev,\n\t\t\t\t\toffset: newPagination.pageIndex * newPagination.pageSize,\n\t\t\t\t\tlimit: newPagination.pageSize,\n\t\t\t\t}),\n\t\t\t\treplace: true,\n\t\t\t});\n\t\t},\n\t\t[navigate],\n\t);\n\n\treturn [pagination, onPaginationChange] as const;\n};\n\n/**\n * Hook to manage column filtering state and navigation for variables table\n *\n * Handles filtering by name and tags, updating the URL search parameters when filters change.\n * Resets pagination offset when filters are updated.\n *\n * @returns A tuple containing:\n * - columnFilters: Current column filter state for name and tags\n * - onColumnFiltersChange: Callback to update filters and navigate with new search params\n */\nconst useVariableColumnFilters = () => {\n\tconst search = Route.useSearch();\n\tconst navigate = Route.useNavigate();\n\tconst columnFilters: ColumnFiltersState = useMemo(\n\t\t() => [\n\t\t\t{ id: \"name\", value: search.name },\n\t\t\t{ id: \"tags\", value: search.tags },\n\t\t],\n\t\t[search.name, search.tags],\n\t);\n\n\tconst onColumnFiltersChange = useCallback(\n\t\t(newColumnFilters: ColumnFiltersState) => {\n\t\t\tvoid navigate({\n\t\t\t\tto: \".\",\n\t\t\t\tsearch: (prev) => {\n\t\t\t\t\tconst name = newColumnFilters.find((filter) => filter.id === \"name\")\n\t\t\t\t\t\t?.value as string | undefined;\n\t\t\t\t\tconst tags = newColumnFilters.find((filter) => filter.id === \"tags\")\n\t\t\t\t\t\t?.value as string[] | undefined;\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...prev,\n\t\t\t\t\t\toffset: 0,\n\t\t\t\t\t\tname,\n\t\t\t\t\t\ttags,\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\t[navigate],\n\t);\n\n\treturn [columnFilters, onColumnFiltersChange] as const;\n};\n\n/**\n * Hook to manage sorting state and navigation for variables table\n *\n * Handles updating the URL search parameters when sort key changes.\n * Uses the current sort value from search params and provides a callback\n * to update sorting.\n *\n * @returns A tuple containing:\n * - sorting: Current sort key from search params\n * - onSortingChange: Callback to update sort and navigate with new search params\n */\nconst useVariableSorting = () => {\n\tconst search = Route.useSearch();\n\tconst navigate = Route.useNavigate();\n\n\tconst onSortingChange = useCallback(\n\t\t(sortKey: components[\"schemas\"][\"VariableSort\"]) => {\n\t\t\tvoid navigate({\n\t\t\t\tto: \".\",\n\t\t\t\tsearch: (prev) => ({ ...prev, sort: sortKey }),\n\t\t\t\treplace: true,\n\t\t\t});\n\t\t},\n\t\t[navigate],\n\t);\n\n\treturn [search.sort, onSortingChange] as const;\n};\n\nfunction RouteComponent() {\n\tconst search = Route.useSearch();\n\tconst [pagination, onPaginationChange] = usePagination();\n\tconst [columnFilters, onColumnFiltersChange] = useVariableColumnFilters();\n\tconst [sorting, onSortingChange] = useVariableSorting();\n\tconst [variableDialogState, onVariableAddOrEdit] = useVariableDialog();\n\n\tconst [{ data: variables }, { data: filteredCount }, { data: totalCount }] =\n\t\tuseSuspenseQueries({\n\t\t\tqueries: [\n\t\t\t\tbuildFilterVariablesQuery(buildFilterBody(search)),\n\t\t\t\tbuildCountVariablesQuery(buildFilterBody(search)),\n\t\t\t\tbuildCountVariablesQuery(),\n\t\t\t],\n\t\t});\n\n\tconst hasVariables = (totalCount ?? 0) > 0;\n\n\treturn (\n\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t<VariablesPageHeader onAddVariableClick={onVariableAddOrEdit} />\n\t\t\t<VariableDialog {...variableDialogState} />\n\t\t\t{hasVariables ? (\n\t\t\t\t<VariablesDataTable\n\t\t\t\t\tvariables={variables ?? []}\n\t\t\t\t\tcurrentVariableCount={filteredCount ?? 0}\n\t\t\t\t\tpagination={pagination}\n\t\t\t\t\tonPaginationChange={onPaginationChange}\n\t\t\t\t\tcolumnFilters={columnFilters}\n\t\t\t\t\tonColumnFiltersChange={onColumnFiltersChange}\n\t\t\t\t\tsorting={sorting}\n\t\t\t\t\tonSortingChange={onSortingChange}\n\t\t\t\t\tonVariableEdit={onVariableAddOrEdit}\n\t\t\t\t/>\n\t\t\t) : (\n\t\t\t\t<VariablesEmptyState onAddVariableClick={onVariableAddOrEdit} />\n\t\t\t)}\n\t\t</div>\n\t);\n}\n"],"names":["ActionsCell","row","onVariableEdit","id","deleteVariable","useDeleteVariable","onVariableDelete","toast","jsx","DropdownMenu","DropdownMenuTrigger","jsxs","Button","Icon","DropdownMenuContent","DropdownMenuLabel","DropdownMenuItem","copyValue","ValueCell","props","value","codeRef","useRef","isOverflowing","useIsOverflowing","HoverCard","HoverCardTrigger","HoverCardContent","JsonInput","columnHelper","createColumnHelper","createColumns","updated","tags","TagBadgeGroup","VariablesDataTable","variables","currentVariableCount","pagination","onPaginationChange","columnFilters","onColumnFiltersChange","sorting","onSortingChange","columns","useMemo","nameSearchValue","filter","tagsSearchValue","handleNameSearchChange","useCallback","filters","handleTagsSearchChange","e","handlePaginationChange","updater","newPagination","table","useReactTable","getCoreRowModel","pluralize","SearchInput","TagsInput","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","DataTable","VariablesEmptyState","onAddVariableClick","EmptyState","EmptyStateIcon","EmptyStateTitle","EmptyStateDescription","EmptyStateActions","DocsLink","useVariableDialog","handleVariableDialogOpenChange","open","setDialogState","prev","dialogState","useState","handleVariableAddOrEdit","variableToEdit","formSchema","z.object","z.string","VARIABLE_FORM_DEFAULT_VALUES","VariableDialog","onOpenChange","form","useForm","zodResolver","initialValues","useEffect","createVariable","isCreating","useCreateVariable","updateVariable","isUpdating","useUpdateVariable","onSubmit","values","error","message","dialogTitle","dialogDescription","Dialog","DialogContent","DialogHeader","DialogTitle","DialogDescription","Form","FormMessage","FormField","field","FormItem","FormLabel","FormControl","Input","DialogFooter","DialogClose","buildFilterBody","search","offset","limit","sort","operator","name","like_","length","all_","usePagination","Route","useSearch","navigate","useNavigate","pageIndex","Math","ceil","pageSize","to","replace","useVariableColumnFilters","newColumnFilters","find","useVariableSorting","sortKey","RouteComponent","variableDialogState","onVariableAddOrEdit","data","filteredCount","totalCount","useSuspenseQueries","queries","buildFilterVariablesQuery","buildCountVariablesQuery","hasVariables","VariablesPageHeader"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-D0R9_LIL.js","sources":["../../src/components/flows/cells.tsx","../../src/components/flows/columns.tsx","../../src/components/flows/data-table.tsx","../../src/components/flows/empty-state/flows-empty-state.tsx","../../src/components/flows/flows-page-header.tsx","../../src/components/flows/flows-page.tsx","../../src/routes/flows/index.tsx?tsr-split=component"],"sourcesContent":["import { useQuery } from \"@tanstack/react-query\";\nimport { Link } from \"@tanstack/react-router\";\nimport { subWeeks } from \"date-fns\";\nimport { useMemo } from \"react\";\nimport { toast } from \"sonner\";\nimport { buildFilterFlowRunsQuery } from \"@/api/flow-runs\";\nimport {\n\tbuildDeploymentsCountByFlowQuery,\n\tbuildNextRunsByFlowQuery,\n\tuseDeleteFlowById,\n} from \"@/api/flows\";\nimport type { components } from \"@/api/prefect\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n\tDropdownMenu,\n\tDropdownMenuContent,\n\tDropdownMenuItem,\n\tDropdownMenuLabel,\n\tDropdownMenuSeparator,\n\tDropdownMenuTrigger,\n} from \"@/components/ui/dropdown-menu\";\nimport { FlowRunActivityBarChart } from \"@/components/ui/flow-run-activity-bar-graph\";\nimport { Icon } from \"@/components/ui/icons\";\nimport { StateIcon } from \"@/components/ui/state-badge\";\nimport { pluralize } from \"@/utils\";\nimport { formatDate } from \"@/utils/date\";\n\ntype Flow = components[\"schemas\"][\"Flow\"];\n\nexport const FlowName = ({ row }: { row: { original: Flow } }) => {\n\tif (!row.original.id) return null;\n\n\treturn (\n\t\t<div className=\"flex flex-col pl-4\">\n\t\t\t<Link\n\t\t\t\tto=\"/flows/flow/$id\"\n\t\t\t\tparams={{ id: row.original.id }}\n\t\t\t\tclassName=\"text-sm font-medium truncate\"\n\t\t\t\ttitle={row.original.name}\n\t\t\t>\n\t\t\t\t{row.original.name}\n\t\t\t</Link>\n\t\t\t<span className=\"text-xs text-muted-foreground\">\n\t\t\t\tCreated{\" \"}\n\t\t\t\t{row.original?.created && formatDate(row.original.created, \"dateTime\")}\n\t\t\t</span>\n\t\t</div>\n\t);\n};\n\nexport const FlowLastRun = ({ row }: { row: { original: Flow } }) => {\n\tconst flowId = row.original.id;\n\tconst { data: flowRuns } = useQuery({\n\t\t...buildFilterFlowRunsQuery({\n\t\t\tflows: { operator: \"and_\", id: { any_: [flowId ?? \"\"] } },\n\t\t\tflow_runs: {\n\t\t\t\toperator: \"and_\",\n\t\t\t\tstart_time: { is_null_: false },\n\t\t\t},\n\t\t\toffset: 0,\n\t\t\tlimit: 1,\n\t\t\tsort: \"START_TIME_DESC\",\n\t\t}),\n\t\tenabled: !!flowId,\n\t});\n\n\tconst lastRun = flowRuns?.[0];\n\tif (!flowId || !lastRun) return null;\n\n\treturn (\n\t\t<div className=\"flex items-center gap-1\">\n\t\t\t{lastRun.state_type && (\n\t\t\t\t<StateIcon\n\t\t\t\t\ttype={lastRun.state_type}\n\t\t\t\t\tname={lastRun.state_name ?? undefined}\n\t\t\t\t/>\n\t\t\t)}\n\t\t\t<Link to=\"/runs/flow-run/$id\" params={{ id: lastRun.id ?? \"\" }}>\n\t\t\t\t<span className=\"text-sm text-blue-700 hover:underline\">\n\t\t\t\t\t{lastRun.name}\n\t\t\t\t</span>\n\t\t\t</Link>\n\t\t</div>\n\t);\n};\n\nexport const FlowNextRun = ({ row }: { row: { original: Flow } }) => {\n\tconst flowId = row.original.id;\n\tconst { data: nextRunsMap } = useQuery(\n\t\tbuildNextRunsByFlowQuery(flowId ? [flowId] : [], { enabled: !!flowId }),\n\t);\n\n\tconst nextRun = flowId ? nextRunsMap?.[flowId] : null;\n\tif (!flowId || !nextRun) return null;\n\n\treturn (\n\t\t<div className=\"flex items-center gap-1\">\n\t\t\t{nextRun.state_type && (\n\t\t\t\t<StateIcon type={nextRun.state_type} name={nextRun.state_name} />\n\t\t\t)}\n\t\t\t<Link to=\"/runs/flow-run/$id\" params={{ id: nextRun.id ?? \"\" }}>\n\t\t\t\t<span className=\"text-sm text-blue-700 hover:underline\">\n\t\t\t\t\t{nextRun.name}\n\t\t\t\t</span>\n\t\t\t</Link>\n\t\t</div>\n\t);\n};\n\nexport const FlowDeploymentCount = ({ row }: { row: { original: Flow } }) => {\n\tconst flowId = row.original.id;\n\tconst { data: countsMap } = useQuery(\n\t\tbuildDeploymentsCountByFlowQuery(flowId ? [flowId] : [], {\n\t\t\tenabled: !!flowId,\n\t\t}),\n\t);\n\tif (!flowId) return null;\n\n\tconst count = countsMap?.[flowId] ?? 0;\n\n\tif (count === 0) {\n\t\treturn <span className=\"text-sm text-muted-foreground\">None</span>;\n\t}\n\n\treturn (\n\t\t<Link\n\t\t\tto=\"/flows/flow/$id\"\n\t\t\tparams={{ id: flowId }}\n\t\t\tsearch={{ tab: \"deployments\" }}\n\t\t>\n\t\t\t<span className=\"text-sm text-blue-700 hover:underline\">\n\t\t\t\t{count} {pluralize(count, \"Deployment\")}\n\t\t\t</span>\n\t\t</Link>\n\t);\n};\n\nexport const FlowActionMenu = ({ row }: { row: { original: Flow } }) => {\n\tconst id = row.original.id;\n\n\tconst { deleteFlow } = useDeleteFlowById();\n\n\tif (!id) {\n\t\treturn null;\n\t}\n\treturn (\n\t\t<div className=\"flex justify-end\">\n\t\t\t<DropdownMenu>\n\t\t\t\t<DropdownMenuTrigger asChild>\n\t\t\t\t\t<Button variant=\"ghost\" className=\"h-8 w-8 p-0\">\n\t\t\t\t\t\t<span className=\"sr-only\">Open menu</span>\n\t\t\t\t\t\t<Icon id=\"MoreVertical\" className=\"h-4 w-4\" />\n\t\t\t\t\t</Button>\n\t\t\t\t</DropdownMenuTrigger>\n\t\t\t\t<DropdownMenuContent align=\"end\">\n\t\t\t\t\t<DropdownMenuLabel>Actions</DropdownMenuLabel>\n\t\t\t\t\t<DropdownMenuItem\n\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\tvoid navigator.clipboard.writeText(id);\n\t\t\t\t\t\t\ttoast.success(\"ID copied\");\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tCopy ID\n\t\t\t\t\t</DropdownMenuItem>\n\t\t\t\t\t<DropdownMenuSeparator />\n\t\t\t\t\t<DropdownMenuItem onClick={() => deleteFlow(id)}>\n\t\t\t\t\t\tDelete\n\t\t\t\t\t</DropdownMenuItem>\n\t\t\t\t\t<DropdownMenuItem>Automate</DropdownMenuItem>\n\t\t\t\t</DropdownMenuContent>\n\t\t\t</DropdownMenu>\n\t\t</div>\n\t);\n};\n\nconst NUMBER_OF_ACTIVITY_BARS = 16;\n\nexport const FlowActivity = ({ row }: { row: { original: Flow } }) => {\n\tconst flowId = row.original.id;\n\n\tconst { startDate, endDate } = useMemo((): {\n\t\tstartDate: Date;\n\t\tendDate: Date;\n\t} => {\n\t\tconst now = new Date();\n\t\treturn {\n\t\t\tstartDate: subWeeks(now, 1),\n\t\t\tendDate: now,\n\t\t};\n\t}, []);\n\n\tconst { data: flowRuns } = useQuery({\n\t\t...buildFilterFlowRunsQuery({\n\t\t\tflows: { operator: \"and_\", id: { any_: [flowId ?? \"\"] } },\n\t\t\tflow_runs: {\n\t\t\t\toperator: \"and_\",\n\t\t\t\tstart_time: { is_null_: false },\n\t\t\t},\n\t\t\toffset: 0,\n\t\t\tlimit: NUMBER_OF_ACTIVITY_BARS,\n\t\t\tsort: \"START_TIME_DESC\",\n\t\t}),\n\t\tenabled: !!flowId,\n\t});\n\n\tif (!flowId) return null;\n\n\treturn (\n\t\t<FlowRunActivityBarChart\n\t\t\tchartId={`flow-activity-${flowId}`}\n\t\t\tenrichedFlowRuns={flowRuns ?? []}\n\t\t\tstartDate={startDate}\n\t\t\tendDate={endDate}\n\t\t\tnumberOfBars={NUMBER_OF_ACTIVITY_BARS}\n\t\t\tclassName=\"h-[24px] w-[140px]\"\n\t\t/>\n\t);\n};\n","import type { ColumnDef } from \"@tanstack/react-table\";\nimport type { components } from \"@/api/prefect\";\nimport { Checkbox } from \"@/components/ui/checkbox\";\nimport {\n\tFlowActionMenu,\n\tFlowActivity,\n\tFlowDeploymentCount,\n\tFlowLastRun,\n\tFlowName,\n\tFlowNextRun,\n} from \"./cells\";\n\ntype Flow = components[\"schemas\"][\"Flow\"];\n\nexport const columns: ColumnDef<Flow>[] = [\n\t{\n\t\tid: \"select\",\n\t\theader: ({ table }) => (\n\t\t\t<Checkbox\n\t\t\t\tchecked={table.getIsAllPageRowsSelected()}\n\t\t\t\tonCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}\n\t\t\t\taria-label=\"Select all\"\n\t\t\t/>\n\t\t),\n\t\tcell: ({ row }) => (\n\t\t\t<Checkbox\n\t\t\t\tchecked={row.getIsSelected()}\n\t\t\t\tonCheckedChange={(value) => row.toggleSelected(!!value)}\n\t\t\t\taria-label=\"Select row\"\n\t\t\t/>\n\t\t),\n\t\tenableSorting: false,\n\t\tenableHiding: false,\n\t\tmaxSize: 10,\n\t},\n\t{\n\t\taccessorKey: \"name\",\n\t\theader: () => <div className=\"pl-4\">Flow</div>,\n\t\tcell: FlowName,\n\t},\n\t{\n\t\taccessorKey: \"lastRuns\",\n\t\theader: \"Last Run\",\n\t\tcell: FlowLastRun,\n\t},\n\t{\n\t\taccessorKey: \"nextRuns\",\n\t\theader: \"Next Run\",\n\t\tcell: FlowNextRun,\n\t},\n\t{\n\t\taccessorKey: \"deployments\",\n\t\theader: \"Deployments\",\n\t\tcell: FlowDeploymentCount,\n\t},\n\t{\n\t\taccessorKey: \"activity\",\n\t\theader: \"Activity\",\n\t\tcell: FlowActivity,\n\t},\n\t{\n\t\tid: \"actions\",\n\t\tcell: FlowActionMenu,\n\t},\n];\n","import type {\n\tColumnFiltersState,\n\tOnChangeFn,\n\tPaginationState,\n} from \"@tanstack/react-table\";\nimport {\n\tgetCoreRowModel,\n\ttype RowSelectionState,\n\tuseReactTable,\n} from \"@tanstack/react-table\";\nimport type React from \"react\";\nimport { useCallback, useState } from \"react\";\nimport { type Flow, useDeleteFlowById } from \"@/api/flows\";\nimport { DataTable } from \"@/components/ui/data-table\";\nimport { Icon } from \"@/components/ui/icons\";\nimport { SearchInput } from \"@/components/ui/input\";\nimport {\n\tSelect,\n\tSelectContent,\n\tSelectItem,\n\tSelectTrigger,\n\tSelectValue,\n} from \"@/components/ui/select\";\nimport { TagsInput } from \"@/components/ui/tags-input\";\nimport { pluralize } from \"@/utils\";\nimport { columns } from \"./columns\";\n\nconst FLOW_SORT_OPTIONS = [\n\t{ label: \"A to Z\", value: \"NAME_ASC\" },\n\t{ label: \"Z to A\", value: \"NAME_DESC\" },\n\t{ label: \"Created\", value: \"CREATED_DESC\" },\n] as const;\n\ntype FlowSortValue = \"NAME_ASC\" | \"NAME_DESC\" | \"CREATED_DESC\" | \"UPDATED_DESC\";\n\nexport default function FlowsTable({\n\tflows,\n\tcount,\n\tpageCount,\n\tsort,\n\tpagination,\n\tonPaginationChange,\n\tonSortChange,\n\tcolumnFilters,\n\tonColumnFiltersChange,\n\tonPrefetchPage,\n}: {\n\tflows: Flow[];\n\tcount: number;\n\tpageCount: number;\n\tsort: FlowSortValue;\n\tpagination: PaginationState;\n\tonPaginationChange: (pagination: PaginationState) => void;\n\tonSortChange: (sort: FlowSortValue) => void;\n\tcolumnFilters: ColumnFiltersState;\n\tonColumnFiltersChange: (columnFilters: ColumnFiltersState) => void;\n\tonPrefetchPage?: (page: number) => void;\n}) {\n\tconst { deleteFlow } = useDeleteFlowById();\n\tconst [rowSelection, setRowSelection] = useState<RowSelectionState>({});\n\n\tconst nameSearchValue = (columnFilters.find((filter) => filter.id === \"name\")\n\t\t?.value ?? \"\") as string;\n\tconst tagsSearchValue = (columnFilters.find((filter) => filter.id === \"tags\")\n\t\t?.value ?? []) as string[];\n\n\tconst handleNameSearchChange = useCallback(\n\t\t(value?: string) => {\n\t\t\tconst filters = columnFilters.filter((filter) => filter.id !== \"name\");\n\t\t\tonColumnFiltersChange(\n\t\t\t\tvalue ? [...filters, { id: \"name\", value }] : filters,\n\t\t\t);\n\t\t},\n\t\t[onColumnFiltersChange, columnFilters],\n\t);\n\n\tconst handleTagsSearchChange: React.ChangeEventHandler<HTMLInputElement> &\n\t\t((tags: string[]) => void) = useCallback(\n\t\t(e: string[] | React.ChangeEvent<HTMLInputElement>) => {\n\t\t\tconst tags = Array.isArray(e) ? e : [];\n\t\t\tconst filters = columnFilters.filter((filter) => filter.id !== \"tags\");\n\t\t\tonColumnFiltersChange(\n\t\t\t\ttags.length ? [...filters, { id: \"tags\", value: tags }] : filters,\n\t\t\t);\n\t\t},\n\t\t[onColumnFiltersChange, columnFilters],\n\t);\n\n\tconst handlePaginationChange: OnChangeFn<PaginationState> = useCallback(\n\t\t(updater) => {\n\t\t\tlet newPagination = pagination;\n\t\t\tif (typeof updater === \"function\") {\n\t\t\t\tnewPagination = updater(pagination);\n\t\t\t} else {\n\t\t\t\tnewPagination = updater;\n\t\t\t}\n\t\t\tonPaginationChange(newPagination);\n\t\t},\n\t\t[pagination, onPaginationChange],\n\t);\n\n\tconst table = useReactTable({\n\t\tcolumns: columns,\n\t\tdata: flows,\n\t\tgetCoreRowModel: getCoreRowModel(),\n\t\tmanualPagination: true,\n\t\tpageCount,\n\t\tstate: {\n\t\t\trowSelection,\n\t\t\tpagination,\n\t\t},\n\t\tonRowSelectionChange: setRowSelection,\n\t\tonPaginationChange: handlePaginationChange,\n\t});\n\n\tconst handleDeleteRows = () => {\n\t\tconst selectedRows = Object.keys(rowSelection);\n\n\t\tconst idsToDelete = selectedRows.map((rowId) => flows[Number(rowId)].id);\n\n\t\tfor (const id of idsToDelete) {\n\t\t\tdeleteFlow(id);\n\t\t}\n\n\t\ttable.toggleAllRowsSelected(false);\n\t};\n\n\treturn (\n\t\t<div className=\"h-full\">\n\t\t\t<div className=\"grid sm:grid-cols-2 md:grid-cols-6 lg:grid-cols-12 gap-2 pb-4 items-center\">\n\t\t\t\t<div className=\"sm:col-span-2 md:col-span-6 lg:col-span-4 order-last lg:order-first\">\n\t\t\t\t\t{Object.keys(rowSelection).length > 0 ? (\n\t\t\t\t\t\t<p className=\"text-sm text-muted-foreground flex items-center\">\n\t\t\t\t\t\t\t{Object.keys(rowSelection).length} selected\n\t\t\t\t\t\t\t<Icon\n\t\t\t\t\t\t\t\tid=\"Trash2\"\n\t\t\t\t\t\t\t\tclassName=\"ml-2 cursor-pointer h-4 w-4 inline\"\n\t\t\t\t\t\t\t\tonClick={handleDeleteRows}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</p>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<p className=\"text-sm text-muted-foreground\">\n\t\t\t\t\t\t\t{count} {pluralize(count, \"Flow\")}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t<div className=\"sm:col-span-2 md:col-span-2 lg:col-span-3\">\n\t\t\t\t\t<SearchInput\n\t\t\t\t\t\tplaceholder=\"Flow names\"\n\t\t\t\t\t\tvalue={nameSearchValue}\n\t\t\t\t\t\tonChange={(e) => handleNameSearchChange(e.target.value)}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t\t<div className=\"xs:col-span-1 md:col-span-2 lg:col-span-3\">\n\t\t\t\t\t<TagsInput\n\t\t\t\t\t\tplaceholder=\"Filter by tags\"\n\t\t\t\t\t\tonChange={handleTagsSearchChange}\n\t\t\t\t\t\tvalue={tagsSearchValue}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t\t<div className=\"xs:col-span-1 md:col-span-2 lg:col-span-2\">\n\t\t\t\t\t<Select value={sort} onValueChange={onSortChange}>\n\t\t\t\t\t\t<SelectTrigger aria-label=\"Flow sort order\" className=\"w-full\">\n\t\t\t\t\t\t\t<SelectValue placeholder=\"Sort by\" />\n\t\t\t\t\t\t</SelectTrigger>\n\t\t\t\t\t\t<SelectContent>\n\t\t\t\t\t\t\t{FLOW_SORT_OPTIONS.map((option) => (\n\t\t\t\t\t\t\t\t<SelectItem key={option.value} value={option.value}>\n\t\t\t\t\t\t\t\t\t{option.label}\n\t\t\t\t\t\t\t\t</SelectItem>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</SelectContent>\n\t\t\t\t\t</Select>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<DataTable table={table} onPrefetchPage={onPrefetchPage} />\n\t\t</div>\n\t);\n}\n","import { DocsLink } from \"@/components/ui/docs-link\";\nimport {\n\tEmptyState,\n\tEmptyStateActions,\n\tEmptyStateDescription,\n\tEmptyStateIcon,\n\tEmptyStateTitle,\n} from \"@/components/ui/empty-state\";\n\nexport const FlowsEmptyState = () => (\n\t<EmptyState>\n\t\t<EmptyStateIcon id=\"Workflow\" />\n\t\t<EmptyStateTitle>Run a flow to get started</EmptyStateTitle>\n\t\t<EmptyStateDescription>\n\t\t\tFlows are Python functions that encapsulate workflow logic and allow users\n\t\t\tto interact with and reason about the state of their workflows.\n\t\t</EmptyStateDescription>\n\t\t<EmptyStateActions>\n\t\t\t<DocsLink id=\"flows-guide\" />\n\t\t</EmptyStateActions>\n\t</EmptyState>\n);\n","import {\n\tBreadcrumb,\n\tBreadcrumbItem,\n\tBreadcrumbList,\n} from \"@/components/ui/breadcrumb\";\n\nexport const FlowsHeader = () => {\n\treturn (\n\t\t<div className=\"flex items-center gap-2\">\n\t\t\t<Breadcrumb>\n\t\t\t\t<BreadcrumbList>\n\t\t\t\t\t<BreadcrumbItem className=\"text-xl font-semibold\">\n\t\t\t\t\t\tFlows\n\t\t\t\t\t</BreadcrumbItem>\n\t\t\t\t</BreadcrumbList>\n\t\t\t</Breadcrumb>\n\t\t</div>\n\t);\n};\n","import type {\n\tColumnFiltersState,\n\tPaginationState,\n} from \"@tanstack/react-table\";\nimport type { Flow } from \"@/api/flows\";\nimport FlowsTable from \"./data-table\";\nimport { FlowsEmptyState } from \"./empty-state\";\nimport { FlowsHeader } from \"./flows-page-header\";\n\ntype FlowSortValue = \"NAME_ASC\" | \"NAME_DESC\" | \"CREATED_DESC\" | \"UPDATED_DESC\";\n\ntype FlowsPageProps = {\n\tflows: Flow[];\n\tcount: number;\n\ttotalCount: number;\n\tpageCount: number;\n\tsort: FlowSortValue;\n\tpagination: PaginationState;\n\tonPaginationChange: (pagination: PaginationState) => void;\n\tonSortChange: (sort: FlowSortValue) => void;\n\tcolumnFilters: ColumnFiltersState;\n\tonColumnFiltersChange: (columnFilters: ColumnFiltersState) => void;\n\tonPrefetchPage?: (page: number) => void;\n};\n\nexport default function FlowsPage({\n\tflows,\n\tcount,\n\ttotalCount,\n\tpageCount,\n\tsort,\n\tpagination,\n\tonPaginationChange,\n\tonSortChange,\n\tcolumnFilters,\n\tonColumnFiltersChange,\n\tonPrefetchPage,\n}: FlowsPageProps) {\n\treturn (\n\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t<FlowsHeader />\n\t\t\t{totalCount === 0 ? (\n\t\t\t\t<FlowsEmptyState />\n\t\t\t) : (\n\t\t\t\t<FlowsTable\n\t\t\t\t\tflows={flows}\n\t\t\t\t\tcount={count}\n\t\t\t\t\tpageCount={pageCount}\n\t\t\t\t\tsort={sort}\n\t\t\t\t\tpagination={pagination}\n\t\t\t\t\tonPaginationChange={onPaginationChange}\n\t\t\t\t\tonSortChange={onSortChange}\n\t\t\t\t\tcolumnFilters={columnFilters}\n\t\t\t\t\tonColumnFiltersChange={onColumnFiltersChange}\n\t\t\t\t\tonPrefetchPage={onPrefetchPage}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import {\n\tuseQuery,\n\tuseQueryClient,\n\tuseSuspenseQuery,\n} from \"@tanstack/react-query\";\nimport type { ErrorComponentProps } from \"@tanstack/react-router\";\nimport { createFileRoute } from \"@tanstack/react-router\";\nimport type {\n\tColumnFiltersState,\n\tPaginationState,\n} from \"@tanstack/react-table\";\nimport { zodValidator } from \"@tanstack/zod-adapter\";\nimport { useCallback, useMemo } from \"react\";\nimport { z } from \"zod\";\nimport { categorizeError } from \"@/api/error-utils\";\nimport { buildFilterFlowRunsQuery } from \"@/api/flow-runs\";\nimport {\n\tbuildCountFlowsFilteredQuery,\n\tbuildDeploymentsCountByFlowQuery,\n\tbuildNextRunsByFlowQuery,\n\tbuildPaginateFlowsQuery,\n\ttype FlowsPaginateFilter,\n} from \"@/api/flows\";\nimport FlowsPage from \"@/components/flows/flows-page\";\nimport { RouteErrorState } from \"@/components/ui/route-error-state\";\n\n// Route for /flows/\n\nconst searchParams = z\n\t.object({\n\t\tname: z.string().optional(),\n\t\tpage: z.number().int().positive().optional().default(1).catch(1),\n\t\tlimit: z\n\t\t\t.number()\n\t\t\t.int()\n\t\t\t.positive()\n\t\t\t.max(100)\n\t\t\t.optional()\n\t\t\t.default(10)\n\t\t\t.catch(10),\n\t\ttags: z.array(z.string()).optional(),\n\t\tsort: z\n\t\t\t.enum([\"CREATED_DESC\", \"UPDATED_DESC\", \"NAME_ASC\", \"NAME_DESC\"])\n\t\t\t.optional()\n\t\t\t.default(\"NAME_ASC\"),\n\t})\n\t.optional()\n\t.default({});\n\ntype SearchParams = z.infer<typeof searchParams>;\n\nconst buildPaginationBody = (search?: SearchParams): FlowsPaginateFilter => {\n\tconst hasNameFilter = Boolean(search?.name);\n\tconst hasTagsFilter = Boolean(search?.tags?.length);\n\n\tif (!hasNameFilter && !hasTagsFilter) {\n\t\treturn {\n\t\t\tpage: search?.page ?? 1,\n\t\t\tlimit: search?.limit ?? 10,\n\t\t\tsort: search?.sort ?? \"NAME_ASC\",\n\t\t};\n\t}\n\n\treturn {\n\t\tpage: search?.page ?? 1,\n\t\tlimit: search?.limit ?? 10,\n\t\tsort: search?.sort ?? \"NAME_ASC\",\n\t\tflows: {\n\t\t\toperator: \"and_\",\n\t\t\t...(hasNameFilter && { name: { like_: search?.name } }),\n\t\t\t...(hasTagsFilter && {\n\t\t\t\ttags: { operator: \"and_\", all_: search?.tags },\n\t\t\t}),\n\t\t},\n\t};\n};\n\nconst NUMBER_OF_ACTIVITY_BARS = 16;\n\nfunction FlowsErrorComponent({ error, reset }: ErrorComponentProps) {\n\tconst serverError = categorizeError(error, \"Failed to load flows\");\n\n\t// Only handle API errors (server-error, client-error) at route level\n\t// Let network errors and unknown errors bubble up to root error component\n\tif (\n\t\tserverError.type !== \"server-error\" &&\n\t\tserverError.type !== \"client-error\"\n\t) {\n\t\tthrow error;\n\t}\n\n\treturn (\n\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t<div>\n\t\t\t\t<h1 className=\"text-2xl font-semibold\">Flows</h1>\n\t\t\t</div>\n\t\t\t<RouteErrorState error={serverError} onRetry={reset} />\n\t\t</div>\n\t);\n}\n\nexport const Route = createFileRoute(\"/flows/\")({\n\tvalidateSearch: zodValidator(searchParams),\n\tcomponent: FlowsRoute,\n\terrorComponent: FlowsErrorComponent,\n\tloaderDeps: ({ search }) => buildPaginationBody(search),\n\tloader: ({ deps, context }) => {\n\t\t// Prefetch current page queries without blocking the loader\n\t\tvoid context.queryClient.prefetchQuery(\n\t\t\tbuildPaginateFlowsQuery(deps, 30_000),\n\t\t);\n\t\tvoid context.queryClient.prefetchQuery(\n\t\t\tbuildCountFlowsFilteredQuery({\n\t\t\t\toffset: 0,\n\t\t\t\tsort: deps.sort,\n\t\t\t\tflows: deps.flows ?? undefined,\n\t\t\t}),\n\t\t);\n\t\t// Prefetch total count for empty state check\n\t\tvoid context.queryClient.prefetchQuery(\n\t\t\tbuildCountFlowsFilteredQuery({\n\t\t\t\toffset: 0,\n\t\t\t\tsort: \"NAME_ASC\",\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\t// Convert URL params (1-based page) to TanStack Table's PaginationState (0-based pageIndex)\n\tconst pagination: PaginationState = useMemo(\n\t\t() => ({\n\t\t\tpageIndex: (search.page ?? 1) - 1,\n\t\t\tpageSize: search.limit ?? 10,\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\t// Convert TanStack Table's 0-based pageIndex back to 1-based page for URL\n\t\t\t\t\tpage: newPagination.pageIndex + 1,\n\t\t\t\t\tlimit: newPagination.pageSize,\n\t\t\t\t}),\n\t\t\t\treplace: true,\n\t\t\t});\n\t\t},\n\t\t[navigate],\n\t);\n\n\treturn [pagination, onPaginationChange] as const;\n};\n\ntype FlowSort = \"CREATED_DESC\" | \"UPDATED_DESC\" | \"NAME_ASC\" | \"NAME_DESC\";\n\nconst useSort = () => {\n\tconst search = Route.useSearch();\n\tconst navigate = Route.useNavigate();\n\n\tconst onSortChange = useCallback(\n\t\t(sort: FlowSort) => {\n\t\t\tvoid navigate({\n\t\t\t\tto: \".\",\n\t\t\t\tsearch: (prev) => ({ ...prev, sort }),\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 useFlowsColumnFilters = () => {\n\tconst search = Route.useSearch();\n\tconst navigate = Route.useNavigate();\n\tconst columnFilters: ColumnFiltersState = useMemo(\n\t\t() => [\n\t\t\t{ id: \"name\", value: search.name },\n\t\t\t{ id: \"tags\", value: search.tags },\n\t\t],\n\t\t[search.name, search.tags],\n\t);\n\n\tconst onColumnFiltersChange = useCallback(\n\t\t(newColumnFilters: ColumnFiltersState) => {\n\t\t\tvoid navigate({\n\t\t\t\tto: \".\",\n\t\t\t\tsearch: (prev) => {\n\t\t\t\t\tconst name = newColumnFilters.find((filter) => filter.id === \"name\")\n\t\t\t\t\t\t?.value as string | undefined;\n\t\t\t\t\tconst tags = newColumnFilters.find((filter) => filter.id === \"tags\")\n\t\t\t\t\t\t?.value as string[] | undefined;\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...prev,\n\t\t\t\t\t\tpage: 1,\n\t\t\t\t\t\tname,\n\t\t\t\t\t\ttags,\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\t[navigate],\n\t);\n\n\treturn [columnFilters, onColumnFiltersChange] as const;\n};\n\nfunction FlowsRoute() {\n\tconst search = Route.useSearch();\n\tconst queryClient = useQueryClient();\n\tconst [pagination, onPaginationChange] = usePagination();\n\tconst [sort, onSortChange] = useSort();\n\tconst [columnFilters, onColumnFiltersChange] = useFlowsColumnFilters();\n\n\tconst paginationBody = buildPaginationBody(search);\n\n\t// Use useSuspenseQuery for count (stable key, won't cause suspense on search change)\n\tconst { data: count } = useSuspenseQuery(\n\t\tbuildCountFlowsFilteredQuery({\n\t\t\toffset: 0,\n\t\t\tsort: search.sort,\n\t\t\tflows: paginationBody.flows ?? undefined,\n\t\t}),\n\t);\n\n\t// Get total count of all flows (without filters) to determine if empty state should be shown\n\tconst { data: totalCount } = useSuspenseQuery(\n\t\tbuildCountFlowsFilteredQuery({\n\t\t\toffset: 0,\n\t\t\tsort: \"NAME_ASC\",\n\t\t}),\n\t);\n\n\t// Use useQuery for paginated flows to leverage placeholderData: keepPreviousData\n\t// This prevents the page from suspending when search/filter changes\n\tconst { data: flowsPage } = useQuery(\n\t\tbuildPaginateFlowsQuery(paginationBody, 30_000),\n\t);\n\n\tconst flows = flowsPage?.results ?? [];\n\n\t// Prefetch a page and its child component data when user hovers over pagination buttons\n\tconst onPrefetchPage = useCallback(\n\t\t(page: number) => {\n\t\t\tconst pageDeps = { ...paginationBody, page };\n\t\t\tvoid queryClient\n\t\t\t\t.prefetchQuery(buildPaginateFlowsQuery(pageDeps, 30_000))\n\t\t\t\t.then(() => {\n\t\t\t\t\t// Get the prefetched page data from cache\n\t\t\t\t\tconst pageData = queryClient.getQueryData<{\n\t\t\t\t\t\tresults?: Array<{ id?: string }>;\n\t\t\t\t\t}>(buildPaginateFlowsQuery(pageDeps, 30_000).queryKey);\n\n\t\t\t\t\tconst flowIds =\n\t\t\t\t\t\tpageData?.results\n\t\t\t\t\t\t\t?.map((flow) => flow.id)\n\t\t\t\t\t\t\t.filter((id): id is string => Boolean(id)) ?? [];\n\n\t\t\t\t\tif (flowIds.length === 0) return;\n\n\t\t\t\t\t// Prefetch child component queries for each flow individually\n\t\t\t\t\t// Using individual flow IDs ensures query keys match what components use\n\t\t\t\t\tfor (const flowId of flowIds) {\n\t\t\t\t\t\t// FlowNextRun query - uses single flow ID array for query key matching\n\t\t\t\t\t\tvoid queryClient.prefetchQuery(buildNextRunsByFlowQuery([flowId]));\n\n\t\t\t\t\t\t// FlowDeploymentCount query - uses single flow ID array for query key matching\n\t\t\t\t\t\tvoid queryClient.prefetchQuery(\n\t\t\t\t\t\t\tbuildDeploymentsCountByFlowQuery([flowId]),\n\t\t\t\t\t\t);\n\t\t\t\t\t\t// FlowLastRun query - last completed run\n\t\t\t\t\t\tvoid queryClient.prefetchQuery(\n\t\t\t\t\t\t\tbuildFilterFlowRunsQuery({\n\t\t\t\t\t\t\t\tflows: { operator: \"and_\", id: { any_: [flowId] } },\n\t\t\t\t\t\t\t\tflow_runs: {\n\t\t\t\t\t\t\t\t\toperator: \"and_\",\n\t\t\t\t\t\t\t\t\tstart_time: { is_null_: false },\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\toffset: 0,\n\t\t\t\t\t\t\t\tlimit: 1,\n\t\t\t\t\t\t\t\tsort: \"START_TIME_DESC\",\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\t// FlowActivity query - recent runs for activity chart\n\t\t\t\t\t\tvoid queryClient.prefetchQuery(\n\t\t\t\t\t\t\tbuildFilterFlowRunsQuery({\n\t\t\t\t\t\t\t\tflows: { operator: \"and_\", id: { any_: [flowId] } },\n\t\t\t\t\t\t\t\tflow_runs: {\n\t\t\t\t\t\t\t\t\toperator: \"and_\",\n\t\t\t\t\t\t\t\t\tstart_time: { is_null_: false },\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\toffset: 0,\n\t\t\t\t\t\t\t\tlimit: NUMBER_OF_ACTIVITY_BARS,\n\t\t\t\t\t\t\t\tsort: \"START_TIME_DESC\",\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t},\n\t\t[queryClient, paginationBody],\n\t);\n\n\treturn (\n\t\t<FlowsPage\n\t\t\tflows={flows}\n\t\t\tcount={count ?? 0}\n\t\t\ttotalCount={totalCount ?? 0}\n\t\t\tpageCount={flowsPage?.pages ?? 0}\n\t\t\tsort={sort as \"NAME_ASC\" | \"NAME_DESC\" | \"CREATED_DESC\"}\n\t\t\tpagination={pagination}\n\t\t\tonPaginationChange={onPaginationChange}\n\t\t\tonSortChange={onSortChange}\n\t\t\tcolumnFilters={columnFilters}\n\t\t\tonColumnFiltersChange={onColumnFiltersChange}\n\t\t\tonPrefetchPage={onPrefetchPage}\n\t\t/>\n\t);\n}\n"],"names":["FlowName","row","jsxs","jsx","Link","formatDate","FlowLastRun","flowId","flowRuns","useQuery","buildFilterFlowRunsQuery","lastRun","StateIcon","FlowNextRun","nextRunsMap","buildNextRunsByFlowQuery","nextRun","FlowDeploymentCount","countsMap","buildDeploymentsCountByFlowQuery","count","pluralize","FlowActionMenu","id","deleteFlow","useDeleteFlowById","DropdownMenu","DropdownMenuTrigger","Button","Icon","DropdownMenuContent","DropdownMenuLabel","DropdownMenuItem","toast","DropdownMenuSeparator","NUMBER_OF_ACTIVITY_BARS","FlowActivity","startDate","endDate","useMemo","now","subWeeks","FlowRunActivityBarChart","columns","table","Checkbox","value","FLOW_SORT_OPTIONS","FlowsTable","flows","pageCount","sort","pagination","onPaginationChange","onSortChange","columnFilters","onColumnFiltersChange","onPrefetchPage","rowSelection","setRowSelection","useState","nameSearchValue","filter","tagsSearchValue","handleNameSearchChange","useCallback","filters","handleTagsSearchChange","e","tags","handlePaginationChange","updater","newPagination","useReactTable","getCoreRowModel","handleDeleteRows","idsToDelete","rowId","SearchInput","TagsInput","Select","SelectTrigger","SelectValue","SelectContent","option","SelectItem","DataTable","FlowsEmptyState","EmptyState","EmptyStateIcon","EmptyStateTitle","EmptyStateDescription","EmptyStateActions","DocsLink","FlowsHeader","Breadcrumb","BreadcrumbList","BreadcrumbItem","FlowsPage","totalCount","z","name","string","optional","page","number","int","positive","default","catch","limit","max","buildPaginationBody","search","hasNameFilter","Boolean","hasTagsFilter","length","operator","like_","all_","usePagination","Route","useSearch","navigate","useNavigate","pageIndex","pageSize","to","prev","replace","useSort","useFlowsColumnFilters","newColumnFilters","find","FlowsRoute","queryClient","useQueryClient","paginationBody","data","useSuspenseQuery","buildCountFlowsFilteredQuery","offset","undefined","flowsPage","buildPaginateFlowsQuery","results","pageDeps","prefetchQuery","then","flowIds","getQueryData","queryKey","map","flow","any_","flow_runs","start_time","is_null_","pages"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-D9cOtoSU.js","sources":["../../src/routes/flows/index.tsx?tsr-split=errorComponent"],"sourcesContent":["import {\n\tuseQuery,\n\tuseQueryClient,\n\tuseSuspenseQuery,\n} from \"@tanstack/react-query\";\nimport type { ErrorComponentProps } from \"@tanstack/react-router\";\nimport { createFileRoute } from \"@tanstack/react-router\";\nimport type {\n\tColumnFiltersState,\n\tPaginationState,\n} from \"@tanstack/react-table\";\nimport { zodValidator } from \"@tanstack/zod-adapter\";\nimport { useCallback, useMemo } from \"react\";\nimport { z } from \"zod\";\nimport { categorizeError } from \"@/api/error-utils\";\nimport { buildFilterFlowRunsQuery } from \"@/api/flow-runs\";\nimport {\n\tbuildCountFlowsFilteredQuery,\n\tbuildDeploymentsCountByFlowQuery,\n\tbuildNextRunsByFlowQuery,\n\tbuildPaginateFlowsQuery,\n\ttype FlowsPaginateFilter,\n} from \"@/api/flows\";\nimport FlowsPage from \"@/components/flows/flows-page\";\nimport { RouteErrorState } from \"@/components/ui/route-error-state\";\n\n// Route for /flows/\n\nconst searchParams = z\n\t.object({\n\t\tname: z.string().optional(),\n\t\tpage: z.number().int().positive().optional().default(1).catch(1),\n\t\tlimit: z\n\t\t\t.number()\n\t\t\t.int()\n\t\t\t.positive()\n\t\t\t.max(100)\n\t\t\t.optional()\n\t\t\t.default(10)\n\t\t\t.catch(10),\n\t\ttags: z.array(z.string()).optional(),\n\t\tsort: z\n\t\t\t.enum([\"CREATED_DESC\", \"UPDATED_DESC\", \"NAME_ASC\", \"NAME_DESC\"])\n\t\t\t.optional()\n\t\t\t.default(\"NAME_ASC\"),\n\t})\n\t.optional()\n\t.default({});\n\ntype SearchParams = z.infer<typeof searchParams>;\n\nconst buildPaginationBody = (search?: SearchParams): FlowsPaginateFilter => {\n\tconst hasNameFilter = Boolean(search?.name);\n\tconst hasTagsFilter = Boolean(search?.tags?.length);\n\n\tif (!hasNameFilter && !hasTagsFilter) {\n\t\treturn {\n\t\t\tpage: search?.page ?? 1,\n\t\t\tlimit: search?.limit ?? 10,\n\t\t\tsort: search?.sort ?? \"NAME_ASC\",\n\t\t};\n\t}\n\n\treturn {\n\t\tpage: search?.page ?? 1,\n\t\tlimit: search?.limit ?? 10,\n\t\tsort: search?.sort ?? \"NAME_ASC\",\n\t\tflows: {\n\t\t\toperator: \"and_\",\n\t\t\t...(hasNameFilter && { name: { like_: search?.name } }),\n\t\t\t...(hasTagsFilter && {\n\t\t\t\ttags: { operator: \"and_\", all_: search?.tags },\n\t\t\t}),\n\t\t},\n\t};\n};\n\nconst NUMBER_OF_ACTIVITY_BARS = 16;\n\nfunction FlowsErrorComponent({ error, reset }: ErrorComponentProps) {\n\tconst serverError = categorizeError(error, \"Failed to load flows\");\n\n\t// Only handle API errors (server-error, client-error) at route level\n\t// Let network errors and unknown errors bubble up to root error component\n\tif (\n\t\tserverError.type !== \"server-error\" &&\n\t\tserverError.type !== \"client-error\"\n\t) {\n\t\tthrow error;\n\t}\n\n\treturn (\n\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t<div>\n\t\t\t\t<h1 className=\"text-2xl font-semibold\">Flows</h1>\n\t\t\t</div>\n\t\t\t<RouteErrorState error={serverError} onRetry={reset} />\n\t\t</div>\n\t);\n}\n\nexport const Route = createFileRoute(\"/flows/\")({\n\tvalidateSearch: zodValidator(searchParams),\n\tcomponent: FlowsRoute,\n\terrorComponent: FlowsErrorComponent,\n\tloaderDeps: ({ search }) => buildPaginationBody(search),\n\tloader: ({ deps, context }) => {\n\t\t// Prefetch current page queries without blocking the loader\n\t\tvoid context.queryClient.prefetchQuery(\n\t\t\tbuildPaginateFlowsQuery(deps, 30_000),\n\t\t);\n\t\tvoid context.queryClient.prefetchQuery(\n\t\t\tbuildCountFlowsFilteredQuery({\n\t\t\t\toffset: 0,\n\t\t\t\tsort: deps.sort,\n\t\t\t\tflows: deps.flows ?? undefined,\n\t\t\t}),\n\t\t);\n\t\t// Prefetch total count for empty state check\n\t\tvoid context.queryClient.prefetchQuery(\n\t\t\tbuildCountFlowsFilteredQuery({\n\t\t\t\toffset: 0,\n\t\t\t\tsort: \"NAME_ASC\",\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\t// Convert URL params (1-based page) to TanStack Table's PaginationState (0-based pageIndex)\n\tconst pagination: PaginationState = useMemo(\n\t\t() => ({\n\t\t\tpageIndex: (search.page ?? 1) - 1,\n\t\t\tpageSize: search.limit ?? 10,\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\t// Convert TanStack Table's 0-based pageIndex back to 1-based page for URL\n\t\t\t\t\tpage: newPagination.pageIndex + 1,\n\t\t\t\t\tlimit: newPagination.pageSize,\n\t\t\t\t}),\n\t\t\t\treplace: true,\n\t\t\t});\n\t\t},\n\t\t[navigate],\n\t);\n\n\treturn [pagination, onPaginationChange] as const;\n};\n\ntype FlowSort = \"CREATED_DESC\" | \"UPDATED_DESC\" | \"NAME_ASC\" | \"NAME_DESC\";\n\nconst useSort = () => {\n\tconst search = Route.useSearch();\n\tconst navigate = Route.useNavigate();\n\n\tconst onSortChange = useCallback(\n\t\t(sort: FlowSort) => {\n\t\t\tvoid navigate({\n\t\t\t\tto: \".\",\n\t\t\t\tsearch: (prev) => ({ ...prev, sort }),\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 useFlowsColumnFilters = () => {\n\tconst search = Route.useSearch();\n\tconst navigate = Route.useNavigate();\n\tconst columnFilters: ColumnFiltersState = useMemo(\n\t\t() => [\n\t\t\t{ id: \"name\", value: search.name },\n\t\t\t{ id: \"tags\", value: search.tags },\n\t\t],\n\t\t[search.name, search.tags],\n\t);\n\n\tconst onColumnFiltersChange = useCallback(\n\t\t(newColumnFilters: ColumnFiltersState) => {\n\t\t\tvoid navigate({\n\t\t\t\tto: \".\",\n\t\t\t\tsearch: (prev) => {\n\t\t\t\t\tconst name = newColumnFilters.find((filter) => filter.id === \"name\")\n\t\t\t\t\t\t?.value as string | undefined;\n\t\t\t\t\tconst tags = newColumnFilters.find((filter) => filter.id === \"tags\")\n\t\t\t\t\t\t?.value as string[] | undefined;\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...prev,\n\t\t\t\t\t\tpage: 1,\n\t\t\t\t\t\tname,\n\t\t\t\t\t\ttags,\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\t[navigate],\n\t);\n\n\treturn [columnFilters, onColumnFiltersChange] as const;\n};\n\nfunction FlowsRoute() {\n\tconst search = Route.useSearch();\n\tconst queryClient = useQueryClient();\n\tconst [pagination, onPaginationChange] = usePagination();\n\tconst [sort, onSortChange] = useSort();\n\tconst [columnFilters, onColumnFiltersChange] = useFlowsColumnFilters();\n\n\tconst paginationBody = buildPaginationBody(search);\n\n\t// Use useSuspenseQuery for count (stable key, won't cause suspense on search change)\n\tconst { data: count } = useSuspenseQuery(\n\t\tbuildCountFlowsFilteredQuery({\n\t\t\toffset: 0,\n\t\t\tsort: search.sort,\n\t\t\tflows: paginationBody.flows ?? undefined,\n\t\t}),\n\t);\n\n\t// Get total count of all flows (without filters) to determine if empty state should be shown\n\tconst { data: totalCount } = useSuspenseQuery(\n\t\tbuildCountFlowsFilteredQuery({\n\t\t\toffset: 0,\n\t\t\tsort: \"NAME_ASC\",\n\t\t}),\n\t);\n\n\t// Use useQuery for paginated flows to leverage placeholderData: keepPreviousData\n\t// This prevents the page from suspending when search/filter changes\n\tconst { data: flowsPage } = useQuery(\n\t\tbuildPaginateFlowsQuery(paginationBody, 30_000),\n\t);\n\n\tconst flows = flowsPage?.results ?? [];\n\n\t// Prefetch a page and its child component data when user hovers over pagination buttons\n\tconst onPrefetchPage = useCallback(\n\t\t(page: number) => {\n\t\t\tconst pageDeps = { ...paginationBody, page };\n\t\t\tvoid queryClient\n\t\t\t\t.prefetchQuery(buildPaginateFlowsQuery(pageDeps, 30_000))\n\t\t\t\t.then(() => {\n\t\t\t\t\t// Get the prefetched page data from cache\n\t\t\t\t\tconst pageData = queryClient.getQueryData<{\n\t\t\t\t\t\tresults?: Array<{ id?: string }>;\n\t\t\t\t\t}>(buildPaginateFlowsQuery(pageDeps, 30_000).queryKey);\n\n\t\t\t\t\tconst flowIds =\n\t\t\t\t\t\tpageData?.results\n\t\t\t\t\t\t\t?.map((flow) => flow.id)\n\t\t\t\t\t\t\t.filter((id): id is string => Boolean(id)) ?? [];\n\n\t\t\t\t\tif (flowIds.length === 0) return;\n\n\t\t\t\t\t// Prefetch child component queries for each flow individually\n\t\t\t\t\t// Using individual flow IDs ensures query keys match what components use\n\t\t\t\t\tfor (const flowId of flowIds) {\n\t\t\t\t\t\t// FlowNextRun query - uses single flow ID array for query key matching\n\t\t\t\t\t\tvoid queryClient.prefetchQuery(buildNextRunsByFlowQuery([flowId]));\n\n\t\t\t\t\t\t// FlowDeploymentCount query - uses single flow ID array for query key matching\n\t\t\t\t\t\tvoid queryClient.prefetchQuery(\n\t\t\t\t\t\t\tbuildDeploymentsCountByFlowQuery([flowId]),\n\t\t\t\t\t\t);\n\t\t\t\t\t\t// FlowLastRun query - last completed run\n\t\t\t\t\t\tvoid queryClient.prefetchQuery(\n\t\t\t\t\t\t\tbuildFilterFlowRunsQuery({\n\t\t\t\t\t\t\t\tflows: { operator: \"and_\", id: { any_: [flowId] } },\n\t\t\t\t\t\t\t\tflow_runs: {\n\t\t\t\t\t\t\t\t\toperator: \"and_\",\n\t\t\t\t\t\t\t\t\tstart_time: { is_null_: false },\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\toffset: 0,\n\t\t\t\t\t\t\t\tlimit: 1,\n\t\t\t\t\t\t\t\tsort: \"START_TIME_DESC\",\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\t// FlowActivity query - recent runs for activity chart\n\t\t\t\t\t\tvoid queryClient.prefetchQuery(\n\t\t\t\t\t\t\tbuildFilterFlowRunsQuery({\n\t\t\t\t\t\t\t\tflows: { operator: \"and_\", id: { any_: [flowId] } },\n\t\t\t\t\t\t\t\tflow_runs: {\n\t\t\t\t\t\t\t\t\toperator: \"and_\",\n\t\t\t\t\t\t\t\t\tstart_time: { is_null_: false },\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\toffset: 0,\n\t\t\t\t\t\t\t\tlimit: NUMBER_OF_ACTIVITY_BARS,\n\t\t\t\t\t\t\t\tsort: \"START_TIME_DESC\",\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t},\n\t\t[queryClient, paginationBody],\n\t);\n\n\treturn (\n\t\t<FlowsPage\n\t\t\tflows={flows}\n\t\t\tcount={count ?? 0}\n\t\t\ttotalCount={totalCount ?? 0}\n\t\t\tpageCount={flowsPage?.pages ?? 0}\n\t\t\tsort={sort as \"NAME_ASC\" | \"NAME_DESC\" | \"CREATED_DESC\"}\n\t\t\tpagination={pagination}\n\t\t\tonPaginationChange={onPaginationChange}\n\t\t\tonSortChange={onSortChange}\n\t\t\tcolumnFilters={columnFilters}\n\t\t\tonColumnFiltersChange={onColumnFiltersChange}\n\t\t\tonPrefetchPage={onPrefetchPage}\n\t\t/>\n\t);\n}\n"],"names":["z","name","string","optional","page","number","int","positive","default","catch","limit","max","tags","sort","FlowsErrorComponent","error","reset","serverError","categorizeError","type","jsxs","jsx","RouteErrorState"],"mappings":"kWA4BqBA,EACZ,CACPC,KAAMD,EAAEE,EAASC,SAAAA,EACjBC,KAAMJ,EAAEK,EAASC,MAAMC,SAAAA,EAAWJ,SAAAA,EAAWK,QAAQ,CAAC,EAAEC,MAAM,CAAC,EAC/DC,MAAOV,EACLK,EACAC,IAAAA,EACAC,SAAAA,EACAI,IAAI,GAAG,EACPR,SAAAA,EACAK,QAAQ,EAAE,EACVC,MAAM,EAAE,EACVG,KAAMZ,EAAQA,EAAEE,CAAQ,EAAEC,SAAAA,EAC1BU,KAAMb,EACC,CAAC,eAAgB,eAAgB,WAAY,WAAW,CAAC,EAC9DG,WACAK,QAAQ,UAAU,CACrB,CAAC,EACAL,WACAK,QAAQ,CAAA,CAAE,EAgCZ,SAASM,EAAoB,CAAEC,MAAAA,EAAOC,MAAAA,CAA2B,EAAG,CACnE,MAAMC,EAAcC,EAAgBH,EAAO,sBAAsB,EAIjE,GACCE,EAAYE,OAAS,gBACrBF,EAAYE,OAAS,eAErB,MAAMJ,EAGP,OACCK,EAAAA,KAAC,MAAA,CAAI,UAAU,sBACd,SAAA,CAAAC,EAAAA,IAAC,OACA,SAAAA,EAAAA,IAAC,KAAA,CAAG,UAAU,yBAAyB,iBAAK,CAAA,CAC7C,EACAA,EAAAA,IAACC,EAAA,CAAgB,MAAOL,EAAa,QAASD,CAAAA,CAAM,CAAA,EACrD,CAEF"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{j as e,L as h,r as m,C as v,D,B as N,s as S,t as w}from"./vendor-tanstack-BdLtprmr.js";import{ap as p,ao as f,bq as T,ag as I,ah as R,br as _,ai as z,aj as E,al as M,ak as P,am as A,an as L,q as j,I as k,U as F,E as Q,t as V,v as q,w as H,x as O,D as $,B as U,h as G,V as J,bs as K,bt as W,bu as g}from"./index-V_xTKaEb.js";import{u as C,B as X}from"./use-delete-block-document-confirmation-dialog-BYY1b8yH.js";import{D as Y}from"./data-table-QSHqmTar.js";import{D as y}from"./delete-confirmation-dialog-dLycVNo4.js";import{B as Z}from"./block-type-logo-DuvU7goV.js";import{u as ee}from"./use-page-title-ar2vyvpx.js";import"./vendor-react-HBv6Kpyp.js";import"./vendor-radix-CJc458uP.js";import"./vendor-recharts-CY3PKigC.js";import"./vendor-forms-BlFSCfFw.js";import"./vendor-date-Cl1Jav-N.js";import"./dropdown-menu-B9LKPlz7.js";import"./use-delete-confirmation-dialog-CkL-rSsp.js";import"./table-ChOwO4Pk.js";const se=({blockDocument:a})=>{const{id:o,name:s,block_type:t,block_type_name:l}=a;return e.jsxs("div",{className:"flex gap-4 items-center",children:[t&&l&&e.jsx(Z,{size:"sm",logoUrl:t.logo_url,alt:`${l} logo`}),e.jsxs("div",{className:"flex flex-col",children:[s&&e.jsx(h,{to:"/blocks/block/$id",params:{id:o},children:e.jsx(p,{className:"font-semibold",children:s})}),l&&a.block_type?.slug&&e.jsx(h,{to:"/blocks/catalog/$slug",params:{slug:a.block_type.slug},children:e.jsx(p,{variant:"bodySmall",className:"text-muted-foreground",children:l})})]})]})},b=N(),ae=({onDelete:a})=>[b.display({maxSize:10,id:"select",header:({table:o})=>{let s=!1;return o.getIsAllRowsSelected()?s=!0:o.getIsSomePageRowsSelected()&&(s="indeterminate"),e.jsx(f,{checked:s,onCheckedChange:t=>o.toggleAllPageRowsSelected(!!t),"aria-label":"Select all"})},cell:({row:o})=>e.jsx(f,{checked:o.getIsSelected(),onCheckedChange:s=>o.toggleSelected(!!s),"aria-label":"Select row"}),enableSorting:!1,enableHiding:!1}),b.display({id:"block",header:"Block",cell:({row:o})=>e.jsx(se,{blockDocument:o.original})}),b.display({id:"actions",cell:o=>{const s=o.row.original;return e.jsx("div",{className:"flex justify-end",children:e.jsx(X,{blockDocument:s,onDelete:()=>a(s)})})}})],oe=({blockDocuments:a,blockDocumentsCount:o,onPaginationChange:s,pagination:t,rowSelection:l,setRowSelection:i})=>{const[r,d]=C(),u=m.useCallback(c=>{let x=t;typeof c=="function"?x=c(t):x=c,s(x)},[t,s]),n=v({columns:ae({onDelete:d}),data:a,defaultColumn:{maxSize:300},getCoreRowModel:D(),manualPagination:!0,onPaginationChange:u,rowCount:o,getRowId:c=>c.id,onRowSelectionChange:i,state:{pagination:t,rowSelection:l}});return e.jsxs(e.Fragment,{children:[e.jsx(Y,{table:n}),e.jsx(y,{...r})]})};function te({selectedBlockTypesSlugs:a,onToggleBlockTypeSlug:o,onRemoveBlockTypeSlug:s}){return e.jsx(m.Suspense,{children:e.jsx(le,{selectedBlockTypesSlugs:a,onToggleBlockTypeSlug:o,onRemoveBlockTypeSlug:s})})}function le({selectedBlockTypesSlugs:a,onToggleBlockTypeSlug:o,onRemoveBlockTypeSlug:s}){const[t,l]=m.useState(""),i=m.useDeferredValue(t),{data:r}=S(T()),d=m.useMemo(()=>a.map(n=>r.find(c=>c.slug===n)).filter(Boolean),[r,a]),u=m.useMemo(()=>r.filter(n=>n.name.toLowerCase().includes(i.toLowerCase())),[r,i]);return e.jsxs(I,{children:[e.jsx(R,{selected:a.length>0,children:e.jsx("div",{className:"flex gap-1",children:a.length>0?d.map(n=>e.jsx(_,{tag:n.name,onRemove:()=>s(n.slug)},n.id)):"Block type"})}),e.jsxs(z,{children:[e.jsx(E,{value:t,onValueChange:l,placeholder:"Search for a block type..."}),e.jsx(M,{children:"No block type found"}),e.jsx(P,{children:e.jsx(A,{children:u.map(n=>e.jsxs(L,{selected:a.includes(n.slug),onSelect:c=>{o(c),l("")},value:n.slug,closeOnSelect:!1,children:[e.jsx("input",{type:"checkbox",checked:a.includes(n.slug),readOnly:!0,className:"mr-2 pointer-events-none"}),n.name]},n.id))})})]})]})}const ne=({count:a,rowSelection:o,setRowSelection:s})=>{const[t,l]=C(),i=m.useMemo(()=>Object.keys(o),[o]);return i.length>0?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(p,{variant:"bodySmall",className:"text-muted-foreground",children:[i.length," selected"]}),e.jsx(j,{"aria-label":"Delete rows",size:"icon",variant:"secondary",onClick:()=>{l(i,{onSuccess:()=>s({})})},children:e.jsx(k,{id:"Trash2",className:"size-4"})})]}),e.jsx(y,{...t})]}):e.jsxs(p,{variant:"bodySmall",className:"text-muted-foreground",children:[a," ",F(a,"Block")]})},ce=()=>e.jsxs(Q,{children:[e.jsx(V,{id:"Box"}),e.jsx(q,{children:"Add a block to get started"}),e.jsx(H,{children:"Blocks securely store credentials and configuration to easily manage connections to external systems."}),e.jsxs(O,{children:[e.jsx(h,{to:"/blocks/catalog",children:e.jsxs(j,{children:["Add Block ",e.jsx(k,{id:"Plus",className:"size-4 ml-2"})]})}),e.jsx($,{id:"blocks-guide"})]})]}),ie=({allCount:a,blockDocuments:o=[],onSearch:s,search:t,blockTypeSlugsFilter:l,onToggleBlockTypeSlug:i,onRemoveBlockTypeSlug:r,pagination:d,onPaginationChange:u})=>{const[n,c]=m.useState({});return e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(U,{children:e.jsx(G,{className:"text-xl font-semibold",children:"Blocks"})}),e.jsx(j,{size:"icon",className:"size-7",variant:"outline",children:e.jsx(h,{to:"/blocks/catalog",children:e.jsx(k,{id:"Plus",className:"size-4"})})})]}),a===0?e.jsx(ce,{}):e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx(ne,{rowSelection:n,setRowSelection:c,count:a}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("div",{className:"min-w-56",children:e.jsx(J,{"aria-label":"search blocks",placeholder:"Search blocks",value:t,onChange:x=>s(x.target.value)})}),e.jsx("div",{className:"min-w-64",children:e.jsx(te,{selectedBlockTypesSlugs:l,onToggleBlockTypeSlug:i,onRemoveBlockTypeSlug:r})})]})]}),e.jsx(oe,{blockDocuments:o,rowSelection:n,setRowSelection:c,blockDocumentsCount:a,pagination:d,onPaginationChange:u})]})]})};function Ne(){ee("Blocks");const[a,o]=re(),[s,t]=me(),[l,i]=de(),{data:r}=S(K()),{data:d}=w(W({sort:"NAME_ASC",include_secrets:!1,block_documents:{name:{like_:a},operator:"and_",is_anonymous:{eq_:!1}},block_types:{slug:{any_:s.length>0?s:void 0}},offset:l.pageIndex*l.pageSize,limit:l.pageSize})),u=c=>{const x=s.filter(B=>B!==c);t(x)},n=c=>{if(s.includes(c))return u(c);t([...s,c])};return e.jsx(ie,{allCount:r,blockDocuments:d,onSearch:o,search:a,blockTypeSlugsFilter:s,onRemoveBlockTypeSlug:u,onToggleBlockTypeSlug:n,pagination:l,onPaginationChange:i})}function re(){const{blockName:a}=g.useSearch(),o=g.useNavigate(),s=m.useCallback(l=>{o({to:".",search:i=>({...i,blockName:l}),replace:!0})},[o]);return[m.useMemo(()=>a??"",[a]),s]}function me(){const{blockTypes:a=[]}=g.useSearch(),o=g.useNavigate(),s=m.useCallback(t=>{o({to:".",search:l=>({...l,blockTypes:t}),replace:!0})},[o]);return[a,s]}function de(){const a=g.useSearch(),o=g.useNavigate(),s=(a.page??1)-1,t=a.limit??10,l=m.useMemo(()=>({pageIndex:s,pageSize:t}),[s,t]),i=m.useCallback(r=>{o({to:".",search:d=>({...d,page:r.pageIndex+1,limit:r.pageSize}),replace:!0})},[o]);return[l,i]}export{Ne as component};
|
|
2
|
-
//# sourceMappingURL=index-DEpWUeaO.js.map
|