prefect 3.7.3.dev2__py3-none-any.whl → 3.7.3.dev4__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/client/orchestration/__init__.py +10 -3
- prefect/runner/_workspace_resolver.py +83 -5
- prefect/server/orchestration/core_policy.py +3 -2
- prefect/server/ui-v2/assets/{artifact._id-Zo42JsyQ.js → artifact._id-CZKgXEWB.js} +2 -2
- prefect/server/ui-v2/assets/{artifact._id-Zo42JsyQ.js.map → artifact._id-CZKgXEWB.js.map} +1 -1
- prefect/server/ui-v2/assets/{artifacts-BdknReie.js → artifacts-DwYa9F9j.js} +2 -2
- prefect/server/ui-v2/assets/{artifacts-BdknReie.js.map → artifacts-DwYa9F9j.js.map} +1 -1
- prefect/server/ui-v2/assets/{automation-wizard-CqzFukp0.js → automation-wizard-Co7sJL6C.js} +2 -2
- prefect/server/ui-v2/assets/{automation-wizard-CqzFukp0.js.map → automation-wizard-Co7sJL6C.js.map} +1 -1
- prefect/server/ui-v2/assets/{automation._id-DHR9tHhZ.js → automation._id-CzAbz8OQ.js} +2 -2
- prefect/server/ui-v2/assets/{automation._id-DHR9tHhZ.js.map → automation._id-CzAbz8OQ.js.map} +1 -1
- prefect/server/ui-v2/assets/{automation_._id.edit-CUgxw4VO.js → automation_._id.edit-C7B50KC9.js} +2 -2
- prefect/server/ui-v2/assets/{automation_._id.edit-CUgxw4VO.js.map → automation_._id.edit-C7B50KC9.js.map} +1 -1
- prefect/server/ui-v2/assets/{automations-BteX3VP5.js → automations-C6FJGw7P.js} +2 -2
- prefect/server/ui-v2/assets/{automations-BteX3VP5.js.map → automations-C6FJGw7P.js.map} +1 -1
- prefect/server/ui-v2/assets/{automations-_EtuoGXy.js → automations-DKLFqR-W.js} +2 -2
- prefect/server/ui-v2/assets/{automations-_EtuoGXy.js.map → automations-DKLFqR-W.js.map} +1 -1
- prefect/server/ui-v2/assets/{automations-header-DVHcldsa.js → automations-header-BuKdnos3.js} +2 -2
- prefect/server/ui-v2/assets/{automations-header-DVHcldsa.js.map → automations-header-BuKdnos3.js.map} +1 -1
- prefect/server/ui-v2/assets/{automations-wizard-BxUMHb1N.js → automations-wizard-5YbxdG3F.js} +2 -2
- prefect/server/ui-v2/assets/{automations-wizard-BxUMHb1N.js.map → automations-wizard-5YbxdG3F.js.map} +1 -1
- prefect/server/ui-v2/assets/{base-job-template-form-section-B0YP4I3P.js → base-job-template-form-section-BRcgnkke.js} +2 -2
- prefect/server/ui-v2/assets/{base-job-template-form-section-B0YP4I3P.js.map → base-job-template-form-section-BRcgnkke.js.map} +1 -1
- prefect/server/ui-v2/assets/{block-type-details-B3Vwd-RE.js → block-type-details-C_uCdUZa.js} +2 -2
- prefect/server/ui-v2/assets/{block-type-details-B3Vwd-RE.js.map → block-type-details-C_uCdUZa.js.map} +1 -1
- prefect/server/ui-v2/assets/{block._id-B3CCPFtJ.js → block._id-MmsBO1E0.js} +2 -2
- prefect/server/ui-v2/assets/{block._id-B3CCPFtJ.js.map → block._id-MmsBO1E0.js.map} +1 -1
- prefect/server/ui-v2/assets/{block_._id.edit-DSO33Cqt.js → block_._id.edit-UsE5VhnE.js} +2 -2
- prefect/server/ui-v2/assets/{block_._id.edit-DSO33Cqt.js.map → block_._id.edit-UsE5VhnE.js.map} +1 -1
- prefect/server/ui-v2/assets/blocks-CH5PZKMD.js.map +1 -1
- prefect/server/ui-v2/assets/blocks-Y4tx1Z1C.js +2 -0
- prefect/server/ui-v2/assets/blocks-Y4tx1Z1C.js.map +1 -0
- prefect/server/ui-v2/assets/{catalog-peZ0ZDPi.js → catalog-DXAxNW-w.js} +2 -2
- prefect/server/ui-v2/assets/{catalog-peZ0ZDPi.js.map → catalog-DXAxNW-w.js.map} +1 -1
- prefect/server/ui-v2/assets/{catalog_._slug-BUsVdYgf.js → catalog_._slug-C3g_TnXA.js} +2 -2
- prefect/server/ui-v2/assets/{catalog_._slug-BUsVdYgf.js.map → catalog_._slug-C3g_TnXA.js.map} +1 -1
- prefect/server/ui-v2/assets/{catalog_._slug_.create-ByZmibJZ.js → catalog_._slug_.create-_dCqBSi1.js} +2 -2
- prefect/server/ui-v2/assets/{catalog_._slug_.create-ByZmibJZ.js.map → catalog_._slug_.create-_dCqBSi1.js.map} +1 -1
- prefect/server/ui-v2/assets/{concurrency-limit._id-VxLjP6mE.js → concurrency-limit._id-Z8kY_5iu.js} +2 -2
- prefect/server/ui-v2/assets/{concurrency-limit._id-VxLjP6mE.js.map → concurrency-limit._id-Z8kY_5iu.js.map} +1 -1
- prefect/server/ui-v2/assets/concurrency-limits-CIYS9zer.js +2 -0
- prefect/server/ui-v2/assets/{concurrency-limits-BI7aLjxZ.js.map → concurrency-limits-CIYS9zer.js.map} +1 -1
- prefect/server/ui-v2/assets/{create-CxHFH55_.js → create-CRMR6U_t.js} +2 -2
- prefect/server/ui-v2/assets/{create-CxHFH55_.js.map → create-CRMR6U_t.js.map} +1 -1
- prefect/server/ui-v2/assets/{create-DMBCpuVl.js → create-Duz7u3aJ.js} +2 -2
- prefect/server/ui-v2/assets/{create-DMBCpuVl.js.map → create-Duz7u3aJ.js.map} +1 -1
- prefect/server/ui-v2/assets/{data-table-BbGyTn8n.js → data-table-CxsVws4O.js} +2 -2
- prefect/server/ui-v2/assets/{data-table-BbGyTn8n.js.map → data-table-CxsVws4O.js.map} +1 -1
- prefect/server/ui-v2/assets/{data-table-DLh2VpHW.js → data-table-DYXgBnS9.js} +2 -2
- prefect/server/ui-v2/assets/{data-table-DLh2VpHW.js.map → data-table-DYXgBnS9.js.map} +1 -1
- prefect/server/ui-v2/assets/deployment-form-CdtzHwSg.js +3 -0
- prefect/server/ui-v2/assets/{deployment-form-CmjkGAeP.js.map → deployment-form-CdtzHwSg.js.map} +1 -1
- prefect/server/ui-v2/assets/{deployment-links-BY54Gk6i.js → deployment-links-BEzQncME.js} +2 -2
- prefect/server/ui-v2/assets/{deployment-links-BY54Gk6i.js.map → deployment-links-BEzQncME.js.map} +1 -1
- prefect/server/ui-v2/assets/{deployment._id-PXR53xU4.js → deployment._id-CGJLPiAU.js} +2 -2
- prefect/server/ui-v2/assets/{deployment._id-PXR53xU4.js.map → deployment._id-CGJLPiAU.js.map} +1 -1
- prefect/server/ui-v2/assets/{deployment_._id.duplicate-DdLQwNw9.js → deployment_._id.duplicate-C4fAvCua.js} +2 -2
- prefect/server/ui-v2/assets/{deployment_._id.duplicate-DdLQwNw9.js.map → deployment_._id.duplicate-C4fAvCua.js.map} +1 -1
- prefect/server/ui-v2/assets/{deployment_._id.edit-D5bMVvb9.js → deployment_._id.edit-DsGbk3kr.js} +2 -2
- prefect/server/ui-v2/assets/{deployment_._id.edit-D5bMVvb9.js.map → deployment_._id.edit-DsGbk3kr.js.map} +1 -1
- prefect/server/ui-v2/assets/{deployment_._id.run-DczKs3Hq.js → deployment_._id.run-DmQjQowN.js} +2 -2
- prefect/server/ui-v2/assets/{deployment_._id.run-DczKs3Hq.js.map → deployment_._id.run-DmQjQowN.js.map} +1 -1
- prefect/server/ui-v2/assets/deployments-BP5QdKL3.js +2 -0
- prefect/server/ui-v2/assets/{deployments-r9sa-J42.js.map → deployments-BP5QdKL3.js.map} +1 -1
- prefect/server/ui-v2/assets/{deployments-CgJ1ie-z.js → deployments-BX4JGvv6.js} +2 -2
- prefect/server/ui-v2/assets/{deployments-CgJ1ie-z.js.map → deployments-BX4JGvv6.js.map} +1 -1
- prefect/server/ui-v2/assets/error-boundary-GTe7hhSV.js +2 -0
- prefect/server/ui-v2/assets/error-boundary-GTe7hhSV.js.map +1 -0
- prefect/server/ui-v2/assets/{event-resource-display-2u5ia4Md.js → event-resource-display-CU5MsqQH.js} +2 -2
- prefect/server/ui-v2/assets/{event-resource-display-2u5ia4Md.js.map → event-resource-display-CU5MsqQH.js.map} +1 -1
- prefect/server/ui-v2/assets/{event._eventDate._eventId-BAp6hV6h.js → event._eventDate._eventId-4IMEuU6B.js} +2 -2
- prefect/server/ui-v2/assets/{event._eventDate._eventId-BAp6hV6h.js.map → event._eventDate._eventId-4IMEuU6B.js.map} +1 -1
- prefect/server/ui-v2/assets/{events-BknsFN6O.js → events-D1Dc3zQ-.js} +2 -2
- prefect/server/ui-v2/assets/{events-BknsFN6O.js.map → events-D1Dc3zQ-.js.map} +1 -1
- prefect/server/ui-v2/assets/{events-timeline-Rl2m78Y5.js → events-timeline-Co9wTQgm.js} +2 -2
- prefect/server/ui-v2/assets/{events-timeline-Rl2m78Y5.js.map → events-timeline-Co9wTQgm.js.map} +1 -1
- prefect/server/ui-v2/assets/{flow-run-graph-DT6ORwEA.js → flow-run-graph-DjwzUq6H.js} +2 -2
- prefect/server/ui-v2/assets/{flow-run-graph-DT6ORwEA.js.map → flow-run-graph-DjwzUq6H.js.map} +1 -1
- prefect/server/ui-v2/assets/flow-run._id-CoTv2cTD.js +4 -0
- prefect/server/ui-v2/assets/flow-run._id-CoTv2cTD.js.map +1 -0
- prefect/server/ui-v2/assets/flow-run._id-DJeNWnOU.js +2 -0
- prefect/server/ui-v2/assets/{flow-run._id-CLKdcnle.js.map → flow-run._id-DJeNWnOU.js.map} +1 -1
- prefect/server/ui-v2/assets/{flow._id-BZAOxnsl.js → flow._id-5--exJ1V.js} +2 -2
- prefect/server/ui-v2/assets/{flow._id-BZAOxnsl.js.map → flow._id-5--exJ1V.js.map} +1 -1
- prefect/server/ui-v2/assets/flow._id-BUiXEl1F.js +2 -0
- prefect/server/ui-v2/assets/{flow._id-CyI-Q-4Z.js.map → flow._id-BUiXEl1F.js.map} +1 -1
- prefect/server/ui-v2/assets/flows-CK1dzMTf.js +2 -0
- prefect/server/ui-v2/assets/{flows-CfyGye_i.js.map → flows-CK1dzMTf.js.map} +1 -1
- prefect/server/ui-v2/assets/{header-CZl2UtVY.js → header-BsgfqCC8.js} +2 -2
- prefect/server/ui-v2/assets/{header-CZl2UtVY.js.map → header-BsgfqCC8.js.map} +1 -1
- prefect/server/ui-v2/assets/header-DUaFtREk.js +2 -0
- prefect/server/ui-v2/assets/{header-CfPjWK5N.js.map → header-DUaFtREk.js.map} +1 -1
- prefect/server/ui-v2/assets/{header-B7UaCf9Y.js → header-DVeMEFGG.js} +2 -2
- prefect/server/ui-v2/assets/{header-B7UaCf9Y.js.map → header-DVeMEFGG.js.map} +1 -1
- prefect/server/ui-v2/assets/{index-BiTXO7bZ.js → index--DOPlnGf.js} +4 -4
- prefect/server/ui-v2/assets/index--DOPlnGf.js.map +1 -0
- prefect/server/ui-v2/assets/{json-input-DuU-pR4T.js → json-input-DT3KbxDZ.js} +2 -2
- prefect/server/ui-v2/assets/{json-input-DuU-pR4T.js.map → json-input-DT3KbxDZ.js.map} +1 -1
- prefect/server/ui-v2/assets/{key._key-BfIX2NO0.js → key._key-BgZBad2s.js} +2 -2
- prefect/server/ui-v2/assets/{key._key-BfIX2NO0.js.map → key._key-BgZBad2s.js.map} +1 -1
- prefect/server/ui-v2/assets/{lazy-markdown-C6e3AE83.js → lazy-markdown-CjMJs81K.js} +2 -2
- prefect/server/ui-v2/assets/{lazy-markdown-C6e3AE83.js.map → lazy-markdown-CjMJs81K.js.map} +1 -1
- prefect/server/ui-v2/assets/{login-BAVVPHlC.js → login-Cx1NrLpk.js} +2 -2
- prefect/server/ui-v2/assets/{login-BAVVPHlC.js.map → login-Cx1NrLpk.js.map} +1 -1
- prefect/server/ui-v2/assets/runs-Cr_7Tg39.js +2 -0
- prefect/server/ui-v2/assets/{runs-HrNDCquv.js.map → runs-Cr_7Tg39.js.map} +1 -1
- prefect/server/ui-v2/assets/{runs-J2wsTr98.js → runs-DUrOYS1_.js} +2 -2
- prefect/server/ui-v2/assets/{runs-J2wsTr98.js.map → runs-DUrOYS1_.js.map} +1 -1
- prefect/server/ui-v2/assets/{schedule-badge-0fzDLqK0.js → schedule-badge-Zhj77ROw.js} +2 -2
- prefect/server/ui-v2/assets/{schedule-badge-0fzDLqK0.js.map → schedule-badge-Zhj77ROw.js.map} +1 -1
- prefect/server/ui-v2/assets/schema-form-Ccp8AU3g.js +6 -0
- prefect/server/ui-v2/assets/schema-form-Ccp8AU3g.js.map +1 -0
- prefect/server/ui-v2/assets/{settings-CKEdr8bc.js → settings-CjNHvh7S.js} +2 -2
- prefect/server/ui-v2/assets/{settings-CKEdr8bc.js.map → settings-CjNHvh7S.js.map} +1 -1
- prefect/server/ui-v2/assets/{task-run-concurrency-limits-reset-dialog-CSOUIoRP.js → task-run-concurrency-limits-reset-dialog-CJnrAkAF.js} +2 -2
- prefect/server/ui-v2/assets/{task-run-concurrency-limits-reset-dialog-CSOUIoRP.js.map → task-run-concurrency-limits-reset-dialog-CJnrAkAF.js.map} +1 -1
- prefect/server/ui-v2/assets/task-run._id-Cvm_Plyh.js +3 -0
- prefect/server/ui-v2/assets/{task-run._id-BUnHohQT.js.map → task-run._id-Cvm_Plyh.js.map} +1 -1
- prefect/server/ui-v2/assets/{timezone-select-Bnsn0RhV.js → timezone-select-Cp7XxZiY.js} +2 -2
- prefect/server/ui-v2/assets/{timezone-select-Bnsn0RhV.js.map → timezone-select-Cp7XxZiY.js.map} +1 -1
- prefect/server/ui-v2/assets/{toggle-group-_iuYMe3I.js → toggle-group-DGZ0dcl7.js} +2 -2
- prefect/server/ui-v2/assets/{toggle-group-_iuYMe3I.js.map → toggle-group-DGZ0dcl7.js.map} +1 -1
- prefect/server/ui-v2/assets/{trigger-details-CTi7CDXp.js → trigger-details-BvMAAJrh.js} +2 -2
- prefect/server/ui-v2/assets/{trigger-details-CTi7CDXp.js.map → trigger-details-BvMAAJrh.js.map} +1 -1
- prefect/server/ui-v2/assets/{use-delete-automation-confirmation-dialog-Dzh4KhYd.js → use-delete-automation-confirmation-dialog-C4LY0Nzd.js} +2 -2
- prefect/server/ui-v2/assets/{use-delete-automation-confirmation-dialog-Dzh4KhYd.js.map → use-delete-automation-confirmation-dialog-C4LY0Nzd.js.map} +1 -1
- prefect/server/ui-v2/assets/{use-delete-block-document-confirmation-dialog-CMUcMn04.js → use-delete-block-document-confirmation-dialog-CkaSA4HR.js} +2 -2
- prefect/server/ui-v2/assets/{use-delete-block-document-confirmation-dialog-CMUcMn04.js.map → use-delete-block-document-confirmation-dialog-CkaSA4HR.js.map} +1 -1
- prefect/server/ui-v2/assets/{use-delete-deployment-confirmation-dialog-DCR3G6aC.js → use-delete-deployment-confirmation-dialog-cisnGao9.js} +2 -2
- prefect/server/ui-v2/assets/{use-delete-deployment-confirmation-dialog-DCR3G6aC.js.map → use-delete-deployment-confirmation-dialog-cisnGao9.js.map} +1 -1
- prefect/server/ui-v2/assets/{use-get-artifacts-flow-task-runs-CwYIhd7a.js → use-get-artifacts-flow-task-runs-BCK_2tbs.js} +2 -2
- prefect/server/ui-v2/assets/{use-get-artifacts-flow-task-runs-CwYIhd7a.js.map → use-get-artifacts-flow-task-runs-BCK_2tbs.js.map} +1 -1
- prefect/server/ui-v2/assets/{use-resource-options-TivZbz4R.js → use-resource-options-rV-5KQt6.js} +2 -2
- prefect/server/ui-v2/assets/{use-resource-options-TivZbz4R.js.map → use-resource-options-rV-5KQt6.js.map} +1 -1
- prefect/server/ui-v2/assets/variables-BabJ_hXE.js +2 -0
- prefect/server/ui-v2/assets/{variables-DohLnyOU.js.map → variables-BabJ_hXE.js.map} +1 -1
- prefect/server/ui-v2/assets/{variables--T46q5I7.js → variables-z-MiCawT.js} +2 -2
- prefect/server/ui-v2/assets/{variables--T46q5I7.js.map → variables-z-MiCawT.js.map} +1 -1
- prefect/server/ui-v2/assets/{work-pool-queue-form-BTlH9k-v.js → work-pool-queue-form-BQp2FWMa.js} +2 -2
- prefect/server/ui-v2/assets/{work-pool-queue-form-BTlH9k-v.js.map → work-pool-queue-form-BQp2FWMa.js.map} +1 -1
- prefect/server/ui-v2/assets/{work-pool-queue-toggle-DJYRbHHT.js → work-pool-queue-toggle-DJp6MSwY.js} +2 -2
- prefect/server/ui-v2/assets/{work-pool-queue-toggle-DJYRbHHT.js.map → work-pool-queue-toggle-DJp6MSwY.js.map} +1 -1
- prefect/server/ui-v2/assets/{work-pool._workPoolName-BNogexz_.js → work-pool._workPoolName-DL31uKjj.js} +2 -2
- prefect/server/ui-v2/assets/{work-pool._workPoolName-BNogexz_.js.map → work-pool._workPoolName-DL31uKjj.js.map} +1 -1
- prefect/server/ui-v2/assets/{work-pool_._workPoolName.edit-BUADYBE8.js → work-pool_._workPoolName.edit-DDMAg-Oa.js} +2 -2
- prefect/server/ui-v2/assets/{work-pool_._workPoolName.edit-BUADYBE8.js.map → work-pool_._workPoolName.edit-DDMAg-Oa.js.map} +1 -1
- prefect/server/ui-v2/assets/{work-pool_._workPoolName.queue._workQueueName-BB5g0Fdn.js → work-pool_._workPoolName.queue._workQueueName-DOowHyr0.js} +2 -2
- prefect/server/ui-v2/assets/{work-pool_._workPoolName.queue._workQueueName-BB5g0Fdn.js.map → work-pool_._workPoolName.queue._workQueueName-DOowHyr0.js.map} +1 -1
- prefect/server/ui-v2/assets/{work-pool_._workPoolName.queue.create-USf-zJSY.js → work-pool_._workPoolName.queue.create-U8kXUs3q.js} +2 -2
- prefect/server/ui-v2/assets/{work-pool_._workPoolName.queue.create-USf-zJSY.js.map → work-pool_._workPoolName.queue.create-U8kXUs3q.js.map} +1 -1
- prefect/server/ui-v2/assets/{work-pool_._workPoolName.queue_._workQueueName.edit-DQsfRuma.js → work-pool_._workPoolName.queue_._workQueueName.edit-CR2SFGIl.js} +2 -2
- prefect/server/ui-v2/assets/{work-pool_._workPoolName.queue_._workQueueName.edit-DQsfRuma.js.map → work-pool_._workPoolName.queue_._workQueueName.edit-CR2SFGIl.js.map} +1 -1
- prefect/server/ui-v2/assets/{work-pools-QaYhK2wz.js → work-pools-DP8kBaS2.js} +2 -2
- prefect/server/ui-v2/assets/{work-pools-QaYhK2wz.js.map → work-pools-DP8kBaS2.js.map} +1 -1
- prefect/server/ui-v2/assets/{work-pools-D_2J6ZNf.js → work-pools-lxhnp-i4.js} +2 -2
- prefect/server/ui-v2/assets/{work-pools-D_2J6ZNf.js.map → work-pools-lxhnp-i4.js.map} +1 -1
- prefect/server/ui-v2/assets/{work-queue-icon-text-BI7IQrcX.js → work-queue-icon-text-BMp37wo6.js} +2 -2
- prefect/server/ui-v2/assets/{work-queue-icon-text-BI7IQrcX.js.map → work-queue-icon-text-BMp37wo6.js.map} +1 -1
- prefect/server/ui-v2/assets/work-queue-select-B7h2Ezjb.js +2 -0
- prefect/server/ui-v2/assets/{work-queue-select-QOtPRzFp.js.map → work-queue-select-B7h2Ezjb.js.map} +1 -1
- prefect/server/ui-v2/index.html +1 -1
- prefect/workers/_worker_channel/_transport.py +6 -1
- {prefect-3.7.3.dev2.dist-info → prefect-3.7.3.dev4.dist-info}/METADATA +1 -1
- {prefect-3.7.3.dev2.dist-info → prefect-3.7.3.dev4.dist-info}/RECORD +168 -166
- prefect/server/ui-v2/assets/blocks-BPxghuZI.js +0 -2
- prefect/server/ui-v2/assets/blocks-BPxghuZI.js.map +0 -1
- prefect/server/ui-v2/assets/concurrency-limits-BI7aLjxZ.js +0 -2
- prefect/server/ui-v2/assets/deployment-form-CmjkGAeP.js +0 -3
- prefect/server/ui-v2/assets/deployments-r9sa-J42.js +0 -2
- prefect/server/ui-v2/assets/flow-run._id-CLKdcnle.js +0 -2
- prefect/server/ui-v2/assets/flow-run._id-n-hTsvaN.js +0 -4
- prefect/server/ui-v2/assets/flow-run._id-n-hTsvaN.js.map +0 -1
- prefect/server/ui-v2/assets/flow._id-CyI-Q-4Z.js +0 -2
- prefect/server/ui-v2/assets/flows-CfyGye_i.js +0 -2
- prefect/server/ui-v2/assets/header-CfPjWK5N.js +0 -2
- prefect/server/ui-v2/assets/index-BiTXO7bZ.js.map +0 -1
- prefect/server/ui-v2/assets/runs-HrNDCquv.js +0 -2
- prefect/server/ui-v2/assets/schema-form-DLdMdbMj.js +0 -6
- prefect/server/ui-v2/assets/schema-form-DLdMdbMj.js.map +0 -1
- prefect/server/ui-v2/assets/task-run._id-BUnHohQT.js +0 -3
- prefect/server/ui-v2/assets/variables-DohLnyOU.js +0 -2
- prefect/server/ui-v2/assets/work-queue-select-QOtPRzFp.js +0 -2
- {prefect-3.7.3.dev2.dist-info → prefect-3.7.3.dev4.dist-info}/WHEEL +0 -0
- {prefect-3.7.3.dev2.dist-info → prefect-3.7.3.dev4.dist-info}/entry_points.txt +0 -0
- {prefect-3.7.3.dev2.dist-info → prefect-3.7.3.dev4.dist-info}/licenses/LICENSE +0 -0
prefect/_build_info.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# Generated by versioningit
|
|
2
|
-
__version__ = "3.7.3.
|
|
3
|
-
__build_date__ = "2026-05-
|
|
4
|
-
__git_commit__ = "
|
|
2
|
+
__version__ = "3.7.3.dev4"
|
|
3
|
+
__build_date__ = "2026-05-27 09:18:11.572029+00:00"
|
|
4
|
+
__git_commit__ = "bbfa2910a7234f773a7a12cd4c7fcf8a4ce9708a"
|
|
5
5
|
__dirty__ = False
|
|
@@ -137,6 +137,7 @@ from prefect.settings import (
|
|
|
137
137
|
)
|
|
138
138
|
from prefect.types._datetime import now
|
|
139
139
|
|
|
140
|
+
from prefect._internal.urls import strip_auth_from_url
|
|
140
141
|
from prefect._internal.version_checking import (
|
|
141
142
|
_api_version_check_key,
|
|
142
143
|
_cache_api_version_check,
|
|
@@ -1132,7 +1133,9 @@ class PrefectClient(
|
|
|
1132
1133
|
except Exception as e:
|
|
1133
1134
|
if "Unauthorized" in str(e):
|
|
1134
1135
|
raise e
|
|
1135
|
-
raise RuntimeError(
|
|
1136
|
+
raise RuntimeError(
|
|
1137
|
+
f"Failed to reach API at {strip_auth_from_url(str(self.api_url))}"
|
|
1138
|
+
) from e
|
|
1136
1139
|
|
|
1137
1140
|
api_version = version.parse(api_version)
|
|
1138
1141
|
client_version = version.parse(self.client_version())
|
|
@@ -1190,7 +1193,9 @@ class PrefectClient(
|
|
|
1190
1193
|
f"{PREFECT_API_DATABASE_CONNECTION_URL.value()}"
|
|
1191
1194
|
)
|
|
1192
1195
|
else:
|
|
1193
|
-
self.logger.debug(
|
|
1196
|
+
self.logger.debug(
|
|
1197
|
+
f"Connecting to API at {strip_auth_from_url(str(self.api_url))}"
|
|
1198
|
+
)
|
|
1194
1199
|
|
|
1195
1200
|
# Enter the httpx client's context
|
|
1196
1201
|
await self._exit_stack.enter_async_context(self._client)
|
|
@@ -1519,7 +1524,9 @@ class SyncPrefectClient(
|
|
|
1519
1524
|
except Exception as e:
|
|
1520
1525
|
if "Unauthorized" in str(e):
|
|
1521
1526
|
raise e
|
|
1522
|
-
raise RuntimeError(
|
|
1527
|
+
raise RuntimeError(
|
|
1528
|
+
f"Failed to reach API at {strip_auth_from_url(str(self.api_url))}"
|
|
1529
|
+
) from e
|
|
1523
1530
|
|
|
1524
1531
|
api_version = version.parse(api_version)
|
|
1525
1532
|
client_version = version.parse(self.client_version())
|
|
@@ -174,6 +174,61 @@ def _workspace_destination_for_deployment_path(
|
|
|
174
174
|
return (workspace_root / relative_destination).resolve()
|
|
175
175
|
|
|
176
176
|
|
|
177
|
+
def _resolve_local_runtime_directory(
|
|
178
|
+
path: str | None, source_cwd: Path, storage_base_path: Path | None
|
|
179
|
+
) -> Path:
|
|
180
|
+
resolved_path = _resolve_local_deployment_path(path, source_cwd, storage_base_path)
|
|
181
|
+
return Path(resolved_path).resolve() if resolved_path is not None else source_cwd
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def _entrypoint_file_path(entrypoint: str, working_directory: Path) -> Path | None:
|
|
185
|
+
entrypoint = _resolve_runtime_entrypoint(entrypoint)
|
|
186
|
+
if ":" not in entrypoint:
|
|
187
|
+
return None
|
|
188
|
+
|
|
189
|
+
path, _object_name = entrypoint.rsplit(":", 1)
|
|
190
|
+
if not path.endswith(".py"):
|
|
191
|
+
return None
|
|
192
|
+
|
|
193
|
+
entrypoint_path = Path(path).expanduser()
|
|
194
|
+
if not entrypoint_path.is_absolute():
|
|
195
|
+
entrypoint_path = working_directory / entrypoint_path
|
|
196
|
+
return entrypoint_path.resolve()
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def _has_entrypoint_file(entrypoint: str, working_directory: Path) -> bool:
|
|
200
|
+
entrypoint_path = _entrypoint_file_path(entrypoint, working_directory)
|
|
201
|
+
return entrypoint_path is not None and entrypoint_path.is_file()
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
async def _ensure_entrypoint_in_workspace(
|
|
205
|
+
client: "PrefectClient",
|
|
206
|
+
deployment: "DeploymentResponse",
|
|
207
|
+
workspace_root: Path,
|
|
208
|
+
source_cwd: Path,
|
|
209
|
+
storage_base_path: Path | None,
|
|
210
|
+
) -> Path:
|
|
211
|
+
if _has_entrypoint_file(deployment.entrypoint, workspace_root):
|
|
212
|
+
return workspace_root
|
|
213
|
+
|
|
214
|
+
local_runtime_directory = _resolve_local_runtime_directory(
|
|
215
|
+
deployment.path, source_cwd, storage_base_path
|
|
216
|
+
)
|
|
217
|
+
if not deployment.storage_document_id and not _has_entrypoint_file(
|
|
218
|
+
deployment.entrypoint, local_runtime_directory
|
|
219
|
+
):
|
|
220
|
+
return workspace_root
|
|
221
|
+
|
|
222
|
+
await _pull_storage_into_workspace(
|
|
223
|
+
client,
|
|
224
|
+
deployment,
|
|
225
|
+
workspace_root,
|
|
226
|
+
source_cwd,
|
|
227
|
+
storage_base_path,
|
|
228
|
+
)
|
|
229
|
+
return workspace_root
|
|
230
|
+
|
|
231
|
+
|
|
177
232
|
@contextlib.contextmanager
|
|
178
233
|
def _redirect_stdout_to_stderr() -> Any:
|
|
179
234
|
stdout = sys.stdout
|
|
@@ -218,9 +273,12 @@ async def _pull_storage_into_workspace(
|
|
|
218
273
|
else None
|
|
219
274
|
)
|
|
220
275
|
else:
|
|
221
|
-
|
|
276
|
+
resolved_local_path = _resolve_local_deployment_path(
|
|
222
277
|
deployment.path, source_cwd, storage_base_path
|
|
223
278
|
)
|
|
279
|
+
from_path = (
|
|
280
|
+
resolved_local_path if resolved_local_path is not None else str(source_cwd)
|
|
281
|
+
)
|
|
224
282
|
storage_block = LocalFileSystem(basepath=from_path)
|
|
225
283
|
|
|
226
284
|
LOGGER.info("Downloading flow code from storage at %r", from_path)
|
|
@@ -253,11 +311,17 @@ async def prepare_workspace(
|
|
|
253
311
|
source_cwd,
|
|
254
312
|
storage_base_path,
|
|
255
313
|
)
|
|
256
|
-
|
|
257
|
-
|
|
314
|
+
local_runtime_directory = _resolve_local_runtime_directory(
|
|
315
|
+
deployment.path, source_cwd, storage_base_path
|
|
316
|
+
)
|
|
317
|
+
if not _has_entrypoint_file(
|
|
318
|
+
deployment.entrypoint, working_directory
|
|
319
|
+
) and _has_entrypoint_file(deployment.entrypoint, local_runtime_directory):
|
|
320
|
+
working_directory = local_runtime_directory
|
|
258
321
|
else:
|
|
322
|
+
working_directory = resolved_workspace_root
|
|
323
|
+
step_selected_working_directory = False
|
|
259
324
|
os.chdir(resolved_workspace_root)
|
|
260
|
-
working_directory = Path.cwd().resolve()
|
|
261
325
|
LOGGER.info("Running %s deployment pull step(s)", len(deployment.pull_steps))
|
|
262
326
|
|
|
263
327
|
def _track_step_workspace(
|
|
@@ -266,17 +330,19 @@ async def prepare_workspace(
|
|
|
266
330
|
step_start_cwd: Path | None,
|
|
267
331
|
step_end_cwd: Path | None,
|
|
268
332
|
) -> None:
|
|
269
|
-
nonlocal working_directory
|
|
333
|
+
nonlocal step_selected_working_directory, working_directory
|
|
270
334
|
|
|
271
335
|
if isinstance(step_output, dict) and step_output.get("directory"):
|
|
272
336
|
resolved_directory = _resolve_directory_output(
|
|
273
337
|
step_output, step_end_cwd
|
|
274
338
|
)
|
|
275
339
|
if resolved_directory is not None:
|
|
340
|
+
step_selected_working_directory = True
|
|
276
341
|
working_directory = resolved_directory
|
|
277
342
|
return
|
|
278
343
|
|
|
279
344
|
if step_end_cwd is not None and step_end_cwd != step_start_cwd:
|
|
345
|
+
step_selected_working_directory = True
|
|
280
346
|
working_directory = step_end_cwd
|
|
281
347
|
|
|
282
348
|
with _observe_step_completion(_track_step_workspace):
|
|
@@ -288,6 +354,18 @@ async def prepare_workspace(
|
|
|
288
354
|
logger=LOGGER,
|
|
289
355
|
)
|
|
290
356
|
|
|
357
|
+
if not step_selected_working_directory:
|
|
358
|
+
working_directory = await _ensure_entrypoint_in_workspace(
|
|
359
|
+
client,
|
|
360
|
+
deployment,
|
|
361
|
+
resolved_workspace_root,
|
|
362
|
+
source_cwd,
|
|
363
|
+
storage_base_path,
|
|
364
|
+
)
|
|
365
|
+
|
|
366
|
+
os.chdir(working_directory)
|
|
367
|
+
working_directory = Path.cwd().resolve()
|
|
368
|
+
|
|
291
369
|
project_root = _find_project_root(working_directory, resolved_workspace_root)
|
|
292
370
|
return PreparedWorkspace(
|
|
293
371
|
workspace_root=resolved_workspace_root,
|
|
@@ -1159,8 +1159,9 @@ class RetryFailedTasks(TaskRunOrchestrationRule):
|
|
|
1159
1159
|
else:
|
|
1160
1160
|
base_delay = delay or 0
|
|
1161
1161
|
|
|
1162
|
-
# guard against negative relative jitter inputs
|
|
1163
|
-
|
|
1162
|
+
# guard against negative relative jitter inputs; also guard against
|
|
1163
|
+
# base_delay == 0: clamped_poisson_interval(0, ...) divides by zero.
|
|
1164
|
+
if run_settings.retry_jitter_factor and base_delay > 0:
|
|
1164
1165
|
delay = clamped_poisson_interval(
|
|
1165
1166
|
base_delay, clamping_factor=run_settings.retry_jitter_factor
|
|
1166
1167
|
)
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime-QTnfLwEv.js";import{a as t,o as n,r,s as i}from"./vendor-codemirror-B3tGe8Gh.js";import{_ as a,a as o,g as s,i as c,j as l,o as u,r as d}from"./vendor-tanstack-4U0A7zMo.js";import{g as f,h as p,t as m,u as h}from"./button-B1qHyd9c.js";import{n as g}from"./dist-jHPxXbiJ.js";import{n as _}from"./input-B5J9cihQ.js";import{t as v}from"./tag-badge-RtUnjBoH.js";import{Dr as y,Er as b,K as x,Mr as S,Or as C,Rn as w,ar as T,cr as E,jr as D,kr as O,lr as k,m as A,sr as j,ur as M}from"./index-BiTXO7bZ.js";import{t as N}from"./key-value-CVUITXjd.js";import{n as P}from"./use-get-artifacts-flow-task-runs-CwYIhd7a.js";import{t as F}from"./lazy-markdown-C6e3AE83.js";import{t as I}from"./data-table-BbGyTn8n.js";var L=e(i(),1),R=n(),z=({artifact:e})=>(0,R.jsxs)(R.Fragment,{children:[(0,R.jsxs)(`div`,{className:`flex items-center justify-between`,children:[e.key?(0,R.jsx)(`div`,{className:`flex items-center gap-2 min-w-0`,children:(0,R.jsx)(b,{className:`min-w-0`,children:(0,R.jsxs)(O,{className:`flex-nowrap`,children:[(0,R.jsx)(y,{className:`min-w-0`,children:(0,R.jsx)(C,{to:`/artifacts/key/$key`,params:{key:e.key},className:`text-xl font-semibold truncate block`,title:e.key,children:e.key})}),(0,R.jsx)(D,{}),(0,R.jsx)(y,{className:`text-xl font-semibold min-w-0`,children:(0,R.jsx)(`span`,{className:`font-mono truncate block`,title:e.id,children:e.id})})]})})}):(0,R.jsx)(`div`,{className:`flex items-center gap-2 min-w-0`,children:(0,R.jsx)(b,{className:`min-w-0`,children:(0,R.jsxs)(O,{className:`flex-nowrap`,children:[e.flow_run&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(y,{className:`min-w-0`,children:(0,R.jsx)(C,{to:`/runs/flow-run/$id`,params:{id:e.flow_run_id??``},className:`text-xl font-semibold truncate block`,title:e.flow_run.name,children:e.flow_run.name})}),(0,R.jsx)(D,{})]}),e.task_run&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(y,{className:`min-w-0`,children:(0,R.jsx)(C,{to:`/runs/task-run/$id`,params:{id:e.task_run_id??``},className:`text-xl font-semibold truncate block`,title:e.task_run.name,children:e.task_run.name})}),(0,R.jsx)(D,{})]}),(0,R.jsx)(y,{className:`text-xl font-semibold min-w-0`,children:(0,R.jsx)(`span`,{className:`font-mono truncate block`,title:e.id,children:e.id})})]})})}),(0,R.jsx)(T,{id:`artifacts-guide`,label:`Documentation`})]}),e.description&&(0,R.jsx)(`div`,{className:`text-sm text-muted-foreground my-2`,children:(0,R.jsx)(F,{children:e.description})}),(0,R.jsx)(`hr`,{})]}),B=({artifact:e})=>{let[n,i]=(0,L.useState)(!1),a=()=>{i(e=>!e)},o=(0,L.useRef)(null),{setContainer:s}=r({container:o.current,extensions:[t.lineWrapping],value:String(e.data),indentWithTab:!1,editable:!0,basicSetup:{highlightActiveLine:!1,foldGutter:!1,highlightActiveLineGutter:!1}});(0,L.useEffect)(()=>{o.current&&s(o.current)},[s]);let c=e=>{g.success(`Copied to clipboard`),navigator.clipboard.writeText(e)};return(0,R.jsxs)(`div`,{className:`flex flex-col justify-center items-center`,children:[(0,R.jsxs)(m,{"data-testid":`show-raw-data-button`,variant:`outline`,onClick:a,className:`my-4`,children:[n?`Hide`:`Show`,` Raw Data`]}),(0,R.jsx)(`div`,{className:`rounded-md border shadow-xs focus-within:outline-hidden focus-within:ring-1 focus-within:ring-ring relative`,style:{display:n?`block`:`none`},ref:e=>{o.current=e},"data-testid":`raw-data-display`,children:(0,R.jsx)(m,{onClick:()=>c(e.data),variant:`ghost`,size:`icon`,className:`absolute top-0 right-0 z-10`,"aria-label":`copy`,children:(0,R.jsx)(f,{id:`Copy`,className:`size-2`})})})]})},ee=s(`/artifacts/artifact/$id`),V=({artifact:e,artifactContent:t,detailsContent:n})=>{let{tab:r}=ee.useSearch(),i=H(e,t,n);return(0,R.jsxs)(j,{defaultValue:`Artifact`,value:r,children:[(0,R.jsx)(k,{children:i.map(({value:e,hiddenOnDesktop:t,LinkComponent:n})=>(0,R.jsx)(n,{className:p(t&&`lg:hidden`)},e))}),i.map(({value:e,ViewComponent:t})=>(0,R.jsx)(t,{},e))]})};function H(e,t,n){return(0,L.useMemo)(()=>{let r=[];return r.push({value:`Artifact`,LinkComponent:({className:e})=>(0,R.jsx)(a,{to:`.`,search:{tab:`Artifact`},children:(0,R.jsx)(M,{value:`Artifact`,className:e,children:`Artifact`})}),ViewComponent:()=>(0,R.jsxs)(E,{value:`Artifact`,children:[t,(0,R.jsx)(B,{artifact:e})]})}),r.push({value:`Details`,hiddenOnDesktop:!0,LinkComponent:({className:e})=>(0,R.jsx)(a,{to:`.`,search:{tab:`Details`},children:(0,R.jsx)(M,{value:`Details`,className:e,children:`Details`})}),ViewComponent:()=>(0,R.jsx)(E,{value:`Details`,children:n})}),r.push({value:`Raw`,LinkComponent:({className:e})=>(0,R.jsx)(a,{to:`.`,search:{tab:`Raw`},children:(0,R.jsx)(M,{value:`Raw`,className:e,children:`Raw`})}),ViewComponent:()=>(0,R.jsx)(E,{value:`Raw`,children:(0,R.jsx)(U,{artifact:e})})}),r},[e,t,n])}function U({artifact:e}){return(0,R.jsx)(`pre`,{className:`whitespace-pre-wrap break-words rounded-md border bg-muted p-4 text-sm`,children:typeof e.data==`string`?e.data:JSON.stringify(e.data,null,2)})}var W=({url:e})=>(0,R.jsxs)(`div`,{"data-testid":e,className:`prose dark:prose-invert mt-2`,children:[(0,R.jsx)(`img`,{"data-testid":`image-${e}`,src:e,alt:`artifact-image`,className:`w-full`}),(0,R.jsxs)(`p`,{className:`text-lg`,children:[`Image URL:`,` `,(0,R.jsx)(`a`,{className:`text-link hover:text-link-hover hover:underline`,target:`_blank`,href:e,rel:`noreferrer`,children:e})]})]}),G=({markdown:e})=>(0,R.jsx)(`div`,{"data-testid":`markdown-display`,className:`mt-4 prose dark:prose-invert`,children:(0,R.jsx)(F,{children:e})}),K=({progress:e})=>(0,R.jsxs)(`p`,{"data-testid":`progress-display`,className:`text-lg`,children:[`Progress: `,e,`%`]}),q=c(),J=({tableData:e})=>{let t=(0,L.useMemo)(()=>JSON.parse(e),[e]),n=(0,L.useMemo)(()=>Object.keys(t[0]??{}),[t]),[r,i]=(0,L.useState)(``),a=(0,L.useMemo)(()=>n.map(e=>q.display({id:e,header:()=>e,cell:({row:t})=>{let n=String(t.original[e]??``);return(0,R.jsx)(`span`,{className:`truncate block`,title:n,children:n})}})),[n]),s=d({data:(0,L.useMemo)(()=>r?t.filter(e=>Object.values(e).some(e=>String(e).toLowerCase().includes(r.toLowerCase()))):t,[r,t]),columns:a,getCoreRowModel:o(),getPaginationRowModel:u(),initialState:{pagination:{pageIndex:0,pageSize:10}}});return(0,R.jsxs)(`div`,{"data-testid":`table-display`,className:`mt-4`,children:[(0,R.jsx)(`div`,{className:`flex flex-row justify-end items-center mb-2`,children:(0,R.jsx)(_,{placeholder:`Search`,value:r,onChange:e=>i(e.target.value)})}),(0,R.jsx)(I,{table:s})]})},Y=({artifact:e})=>{let t=(0,L.useMemo)(()=>e.created?h(e.created,`dateTime`):null,[e.created]);return(0,R.jsxs)(`div`,{className:`mt-4`,children:[(0,R.jsx)(`p`,{className:`text-base font-semibold`,children:`Artifact`}),(0,R.jsxs)(`div`,{className:`mt-3 flex flex-col gap-3`,children:[(0,R.jsx)(N,{label:`Key`,value:(0,R.jsx)(`span`,{className:`font-mono`,children:e.key??`None`})}),(0,R.jsx)(N,{label:`Type`,value:(0,R.jsx)(`span`,{className:`font-mono`,children:e.type??`None`})}),(0,R.jsx)(N,{label:`Created`,value:(0,R.jsx)(`span`,{children:t??`None`})})]})]})},X=e(S(),1),Z=({flowRun:e})=>{let t=(0,L.useMemo)(()=>e.start_time?h(e.start_time,`dateTime`):null,[e.start_time]),n=(0,L.useMemo)(()=>e.estimated_run_time?(0,X.default)(Math.ceil(e.estimated_run_time)*1e3):null,[e.estimated_run_time]),r=(0,L.useMemo)(()=>e.created?h(e.created,`dateTime`):null,[e.created]),i=(0,L.useMemo)(()=>e.updated?h(e.updated,`dateTime`):null,[e.updated]);return(0,R.jsxs)(`div`,{className:`mt-4`,children:[(0,R.jsx)(`p`,{className:`text-lg font-bold`,children:`Flow Run`}),(0,R.jsxs)(`div`,{className:`mt-3 flex flex-col gap-3`,children:[(0,R.jsx)(N,{label:`Start time`,value:(0,R.jsxs)(`span`,{className:`font-mono flex items-center`,children:[(0,R.jsx)(f,{id:`Calendar`,className:`inline w-4 mr-2`}),t??`None`]})}),(0,R.jsx)(N,{label:`Duration`,value:(0,R.jsxs)(`span`,{className:`font-mono flex items-center`,children:[(0,R.jsx)(f,{id:`Clock`,className:`inline w-4 mr-2`}),n??`None`]})}),(0,R.jsx)(N,{label:`Created`,value:(0,R.jsx)(`span`,{className:`font-mono`,children:r??`None`})}),(0,R.jsx)(N,{label:`Last Updated`,value:(0,R.jsx)(`span`,{className:`font-mono`,children:i??`None`})}),(0,R.jsx)(N,{label:`Tags`,value:e.tags&&e.tags.length>0?(0,R.jsx)(`div`,{className:`flex flex-wrap`,children:e.tags.map(e=>(0,R.jsx)(v,{tag:e},e))}):(0,R.jsx)(`span`,{className:`font-mono`,children:`None`})}),(0,R.jsx)(N,{label:`State Message`,value:(0,R.jsx)(`span`,{className:`font-mono`,children:e.state?.message??`None`})})]})]})},Q=({artifact:e})=>{let{flow_run:t,task_run:n}=e;return e.key||t||n?(0,R.jsxs)(`div`,{className:`flex flex-col gap-2`,children:[e.key&&(0,R.jsx)(N,{label:`Artifact`,value:(0,R.jsx)(a,{to:`/artifacts/key/$key`,params:{key:e.key},className:`text-link hover:text-link-hover hover:underline`,children:e.key})}),t&&(0,R.jsx)(N,{label:`Flow Run`,value:(0,R.jsx)(a,{to:`/runs/flow-run/$id`,params:{id:t.id},className:`text-link hover:text-link-hover hover:underline`,children:t.name})}),n&&(0,R.jsx)(N,{label:`Task Run`,value:(0,R.jsx)(a,{to:`/runs/task-run/$id`,params:{id:n.id},className:`text-link hover:text-link-hover hover:underline`,children:n.name})}),(0,R.jsx)(`hr`,{className:`mt-2 border-border`})]}):null},$=({taskRun:e})=>{let t=(0,L.useMemo)(()=>e.created?h(e.created,`dateTime`):null,[e.created]),n=(0,L.useMemo)(()=>e.updated?h(e.updated,`dateTime`):null,[e.updated]);return(0,R.jsxs)(`div`,{className:`mt-4`,children:[(0,R.jsx)(`p`,{className:`text-lg font-bold`,children:`Task Run`}),(0,R.jsxs)(`div`,{className:`mt-3 flex flex-col gap-3`,children:[(0,R.jsx)(N,{label:`Created`,value:(0,R.jsx)(`span`,{className:`font-mono`,children:t??`None`})}),(0,R.jsx)(N,{label:`Last Updated`,value:(0,R.jsx)(`span`,{className:`font-mono`,children:n??`None`})}),(0,R.jsx)(N,{label:`Tags`,value:e.tags&&e.tags.length>0?(0,R.jsx)(`div`,{className:`flex flex-wrap`,children:e.tags.map(e=>(0,R.jsx)(v,{tag:e},e))}):(0,R.jsx)(`span`,{className:`font-mono`,children:`None`})})]})]})},te=({artifact:e})=>{let{flow_run:t,task_run:n}=e;return(0,R.jsxs)(`div`,{className:`flex flex-col gap-4 pt-4`,children:[(0,R.jsx)(Q,{artifact:e}),(0,R.jsx)(Y,{artifact:e}),(t||n)&&(0,R.jsx)(`hr`,{className:`mt-4 border-border`}),t&&(0,R.jsx)(Z,{flowRun:t}),t&&n&&(0,R.jsx)(`hr`,{className:`mt-4 border-border`}),n&&(0,R.jsx)($,{taskRun:n})]})},ne=({artifact:e})=>{let t=(0,L.useMemo)(()=>{switch(e.type){case`markdown`:case`link`:return(0,R.jsx)(G,{markdown:e.data});case`image`:return(0,R.jsx)(W,{url:e.data});case`progress`:return(0,R.jsx)(K,{progress:e.data});case`table`:return(0,R.jsx)(J,{tableData:e.data});default:return(0,R.jsx)(`pre`,{children:JSON.stringify(e.data,null,2)})}},[e]),n=(0,R.jsx)(te,{artifact:e});return(0,R.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,R.jsx)(z,{artifact:e}),(0,R.jsxs)(`div`,{className:`flex flex-col lg:flex-row lg:gap-6`,children:[(0,R.jsx)(`div`,{className:`flex-1 min-w-0`,children:(0,R.jsx)(V,{artifact:e,artifactContent:t,detailsContent:n})}),(0,R.jsx)(w,{children:n})]})]})},re=function(){let{id:e}=A.useParams(),{data:t}=l(x(e));return(0,R.jsx)(ne,{artifact:P(e)??t})};export{re as component};
|
|
2
|
-
//# sourceMappingURL=artifact._id-
|
|
1
|
+
import{r as e}from"./rolldown-runtime-QTnfLwEv.js";import{a as t,o as n,r,s as i}from"./vendor-codemirror-B3tGe8Gh.js";import{_ as a,a as o,g as s,i as c,j as l,o as u,r as d}from"./vendor-tanstack-4U0A7zMo.js";import{g as f,h as p,t as m,u as h}from"./button-B1qHyd9c.js";import{n as g}from"./dist-jHPxXbiJ.js";import{n as _}from"./input-B5J9cihQ.js";import{t as v}from"./tag-badge-RtUnjBoH.js";import{Ar as y,Dr as b,Er as x,K as S,Ln as C,Or as w,Tr as T,cr as E,ir as D,jr as O,lr as k,m as A,or as j,sr as M}from"./index--DOPlnGf.js";import{t as N}from"./key-value-CVUITXjd.js";import{n as P}from"./use-get-artifacts-flow-task-runs-BCK_2tbs.js";import{t as F}from"./lazy-markdown-CjMJs81K.js";import{t as I}from"./data-table-CxsVws4O.js";var L=e(i(),1),R=n(),z=({artifact:e})=>(0,R.jsxs)(R.Fragment,{children:[(0,R.jsxs)(`div`,{className:`flex items-center justify-between`,children:[e.key?(0,R.jsx)(`div`,{className:`flex items-center gap-2 min-w-0`,children:(0,R.jsx)(T,{className:`min-w-0`,children:(0,R.jsxs)(w,{className:`flex-nowrap`,children:[(0,R.jsx)(x,{className:`min-w-0`,children:(0,R.jsx)(b,{to:`/artifacts/key/$key`,params:{key:e.key},className:`text-xl font-semibold truncate block`,title:e.key,children:e.key})}),(0,R.jsx)(y,{}),(0,R.jsx)(x,{className:`text-xl font-semibold min-w-0`,children:(0,R.jsx)(`span`,{className:`font-mono truncate block`,title:e.id,children:e.id})})]})})}):(0,R.jsx)(`div`,{className:`flex items-center gap-2 min-w-0`,children:(0,R.jsx)(T,{className:`min-w-0`,children:(0,R.jsxs)(w,{className:`flex-nowrap`,children:[e.flow_run&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(x,{className:`min-w-0`,children:(0,R.jsx)(b,{to:`/runs/flow-run/$id`,params:{id:e.flow_run_id??``},className:`text-xl font-semibold truncate block`,title:e.flow_run.name,children:e.flow_run.name})}),(0,R.jsx)(y,{})]}),e.task_run&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(x,{className:`min-w-0`,children:(0,R.jsx)(b,{to:`/runs/task-run/$id`,params:{id:e.task_run_id??``},className:`text-xl font-semibold truncate block`,title:e.task_run.name,children:e.task_run.name})}),(0,R.jsx)(y,{})]}),(0,R.jsx)(x,{className:`text-xl font-semibold min-w-0`,children:(0,R.jsx)(`span`,{className:`font-mono truncate block`,title:e.id,children:e.id})})]})})}),(0,R.jsx)(D,{id:`artifacts-guide`,label:`Documentation`})]}),e.description&&(0,R.jsx)(`div`,{className:`text-sm text-muted-foreground my-2`,children:(0,R.jsx)(F,{children:e.description})}),(0,R.jsx)(`hr`,{})]}),B=({artifact:e})=>{let[n,i]=(0,L.useState)(!1),a=()=>{i(e=>!e)},o=(0,L.useRef)(null),{setContainer:s}=r({container:o.current,extensions:[t.lineWrapping],value:String(e.data),indentWithTab:!1,editable:!0,basicSetup:{highlightActiveLine:!1,foldGutter:!1,highlightActiveLineGutter:!1}});(0,L.useEffect)(()=>{o.current&&s(o.current)},[s]);let c=e=>{g.success(`Copied to clipboard`),navigator.clipboard.writeText(e)};return(0,R.jsxs)(`div`,{className:`flex flex-col justify-center items-center`,children:[(0,R.jsxs)(m,{"data-testid":`show-raw-data-button`,variant:`outline`,onClick:a,className:`my-4`,children:[n?`Hide`:`Show`,` Raw Data`]}),(0,R.jsx)(`div`,{className:`rounded-md border shadow-xs focus-within:outline-hidden focus-within:ring-1 focus-within:ring-ring relative`,style:{display:n?`block`:`none`},ref:e=>{o.current=e},"data-testid":`raw-data-display`,children:(0,R.jsx)(m,{onClick:()=>c(e.data),variant:`ghost`,size:`icon`,className:`absolute top-0 right-0 z-10`,"aria-label":`copy`,children:(0,R.jsx)(f,{id:`Copy`,className:`size-2`})})})]})},ee=s(`/artifacts/artifact/$id`),V=({artifact:e,artifactContent:t,detailsContent:n})=>{let{tab:r}=ee.useSearch(),i=H(e,t,n);return(0,R.jsxs)(j,{defaultValue:`Artifact`,value:r,children:[(0,R.jsx)(E,{children:i.map(({value:e,hiddenOnDesktop:t,LinkComponent:n})=>(0,R.jsx)(n,{className:p(t&&`lg:hidden`)},e))}),i.map(({value:e,ViewComponent:t})=>(0,R.jsx)(t,{},e))]})};function H(e,t,n){return(0,L.useMemo)(()=>{let r=[];return r.push({value:`Artifact`,LinkComponent:({className:e})=>(0,R.jsx)(a,{to:`.`,search:{tab:`Artifact`},children:(0,R.jsx)(k,{value:`Artifact`,className:e,children:`Artifact`})}),ViewComponent:()=>(0,R.jsxs)(M,{value:`Artifact`,children:[t,(0,R.jsx)(B,{artifact:e})]})}),r.push({value:`Details`,hiddenOnDesktop:!0,LinkComponent:({className:e})=>(0,R.jsx)(a,{to:`.`,search:{tab:`Details`},children:(0,R.jsx)(k,{value:`Details`,className:e,children:`Details`})}),ViewComponent:()=>(0,R.jsx)(M,{value:`Details`,children:n})}),r.push({value:`Raw`,LinkComponent:({className:e})=>(0,R.jsx)(a,{to:`.`,search:{tab:`Raw`},children:(0,R.jsx)(k,{value:`Raw`,className:e,children:`Raw`})}),ViewComponent:()=>(0,R.jsx)(M,{value:`Raw`,children:(0,R.jsx)(U,{artifact:e})})}),r},[e,t,n])}function U({artifact:e}){return(0,R.jsx)(`pre`,{className:`whitespace-pre-wrap break-words rounded-md border bg-muted p-4 text-sm`,children:typeof e.data==`string`?e.data:JSON.stringify(e.data,null,2)})}var W=({url:e})=>(0,R.jsxs)(`div`,{"data-testid":e,className:`prose dark:prose-invert mt-2`,children:[(0,R.jsx)(`img`,{"data-testid":`image-${e}`,src:e,alt:`artifact-image`,className:`w-full`}),(0,R.jsxs)(`p`,{className:`text-lg`,children:[`Image URL:`,` `,(0,R.jsx)(`a`,{className:`text-link hover:text-link-hover hover:underline`,target:`_blank`,href:e,rel:`noreferrer`,children:e})]})]}),G=({markdown:e})=>(0,R.jsx)(`div`,{"data-testid":`markdown-display`,className:`mt-4 prose dark:prose-invert`,children:(0,R.jsx)(F,{children:e})}),K=({progress:e})=>(0,R.jsxs)(`p`,{"data-testid":`progress-display`,className:`text-lg`,children:[`Progress: `,e,`%`]}),q=c(),J=({tableData:e})=>{let t=(0,L.useMemo)(()=>JSON.parse(e),[e]),n=(0,L.useMemo)(()=>Object.keys(t[0]??{}),[t]),[r,i]=(0,L.useState)(``),a=(0,L.useMemo)(()=>n.map(e=>q.display({id:e,header:()=>e,cell:({row:t})=>{let n=String(t.original[e]??``);return(0,R.jsx)(`span`,{className:`truncate block`,title:n,children:n})}})),[n]),s=d({data:(0,L.useMemo)(()=>r?t.filter(e=>Object.values(e).some(e=>String(e).toLowerCase().includes(r.toLowerCase()))):t,[r,t]),columns:a,getCoreRowModel:o(),getPaginationRowModel:u(),initialState:{pagination:{pageIndex:0,pageSize:10}}});return(0,R.jsxs)(`div`,{"data-testid":`table-display`,className:`mt-4`,children:[(0,R.jsx)(`div`,{className:`flex flex-row justify-end items-center mb-2`,children:(0,R.jsx)(_,{placeholder:`Search`,value:r,onChange:e=>i(e.target.value)})}),(0,R.jsx)(I,{table:s})]})},Y=({artifact:e})=>{let t=(0,L.useMemo)(()=>e.created?h(e.created,`dateTime`):null,[e.created]);return(0,R.jsxs)(`div`,{className:`mt-4`,children:[(0,R.jsx)(`p`,{className:`text-base font-semibold`,children:`Artifact`}),(0,R.jsxs)(`div`,{className:`mt-3 flex flex-col gap-3`,children:[(0,R.jsx)(N,{label:`Key`,value:(0,R.jsx)(`span`,{className:`font-mono`,children:e.key??`None`})}),(0,R.jsx)(N,{label:`Type`,value:(0,R.jsx)(`span`,{className:`font-mono`,children:e.type??`None`})}),(0,R.jsx)(N,{label:`Created`,value:(0,R.jsx)(`span`,{children:t??`None`})})]})]})},X=e(O(),1),Z=({flowRun:e})=>{let t=(0,L.useMemo)(()=>e.start_time?h(e.start_time,`dateTime`):null,[e.start_time]),n=(0,L.useMemo)(()=>e.estimated_run_time?(0,X.default)(Math.ceil(e.estimated_run_time)*1e3):null,[e.estimated_run_time]),r=(0,L.useMemo)(()=>e.created?h(e.created,`dateTime`):null,[e.created]),i=(0,L.useMemo)(()=>e.updated?h(e.updated,`dateTime`):null,[e.updated]);return(0,R.jsxs)(`div`,{className:`mt-4`,children:[(0,R.jsx)(`p`,{className:`text-lg font-bold`,children:`Flow Run`}),(0,R.jsxs)(`div`,{className:`mt-3 flex flex-col gap-3`,children:[(0,R.jsx)(N,{label:`Start time`,value:(0,R.jsxs)(`span`,{className:`font-mono flex items-center`,children:[(0,R.jsx)(f,{id:`Calendar`,className:`inline w-4 mr-2`}),t??`None`]})}),(0,R.jsx)(N,{label:`Duration`,value:(0,R.jsxs)(`span`,{className:`font-mono flex items-center`,children:[(0,R.jsx)(f,{id:`Clock`,className:`inline w-4 mr-2`}),n??`None`]})}),(0,R.jsx)(N,{label:`Created`,value:(0,R.jsx)(`span`,{className:`font-mono`,children:r??`None`})}),(0,R.jsx)(N,{label:`Last Updated`,value:(0,R.jsx)(`span`,{className:`font-mono`,children:i??`None`})}),(0,R.jsx)(N,{label:`Tags`,value:e.tags&&e.tags.length>0?(0,R.jsx)(`div`,{className:`flex flex-wrap`,children:e.tags.map(e=>(0,R.jsx)(v,{tag:e},e))}):(0,R.jsx)(`span`,{className:`font-mono`,children:`None`})}),(0,R.jsx)(N,{label:`State Message`,value:(0,R.jsx)(`span`,{className:`font-mono`,children:e.state?.message??`None`})})]})]})},Q=({artifact:e})=>{let{flow_run:t,task_run:n}=e;return e.key||t||n?(0,R.jsxs)(`div`,{className:`flex flex-col gap-2`,children:[e.key&&(0,R.jsx)(N,{label:`Artifact`,value:(0,R.jsx)(a,{to:`/artifacts/key/$key`,params:{key:e.key},className:`text-link hover:text-link-hover hover:underline`,children:e.key})}),t&&(0,R.jsx)(N,{label:`Flow Run`,value:(0,R.jsx)(a,{to:`/runs/flow-run/$id`,params:{id:t.id},className:`text-link hover:text-link-hover hover:underline`,children:t.name})}),n&&(0,R.jsx)(N,{label:`Task Run`,value:(0,R.jsx)(a,{to:`/runs/task-run/$id`,params:{id:n.id},className:`text-link hover:text-link-hover hover:underline`,children:n.name})}),(0,R.jsx)(`hr`,{className:`mt-2 border-border`})]}):null},$=({taskRun:e})=>{let t=(0,L.useMemo)(()=>e.created?h(e.created,`dateTime`):null,[e.created]),n=(0,L.useMemo)(()=>e.updated?h(e.updated,`dateTime`):null,[e.updated]);return(0,R.jsxs)(`div`,{className:`mt-4`,children:[(0,R.jsx)(`p`,{className:`text-lg font-bold`,children:`Task Run`}),(0,R.jsxs)(`div`,{className:`mt-3 flex flex-col gap-3`,children:[(0,R.jsx)(N,{label:`Created`,value:(0,R.jsx)(`span`,{className:`font-mono`,children:t??`None`})}),(0,R.jsx)(N,{label:`Last Updated`,value:(0,R.jsx)(`span`,{className:`font-mono`,children:n??`None`})}),(0,R.jsx)(N,{label:`Tags`,value:e.tags&&e.tags.length>0?(0,R.jsx)(`div`,{className:`flex flex-wrap`,children:e.tags.map(e=>(0,R.jsx)(v,{tag:e},e))}):(0,R.jsx)(`span`,{className:`font-mono`,children:`None`})})]})]})},te=({artifact:e})=>{let{flow_run:t,task_run:n}=e;return(0,R.jsxs)(`div`,{className:`flex flex-col gap-4 pt-4`,children:[(0,R.jsx)(Q,{artifact:e}),(0,R.jsx)(Y,{artifact:e}),(t||n)&&(0,R.jsx)(`hr`,{className:`mt-4 border-border`}),t&&(0,R.jsx)(Z,{flowRun:t}),t&&n&&(0,R.jsx)(`hr`,{className:`mt-4 border-border`}),n&&(0,R.jsx)($,{taskRun:n})]})},ne=({artifact:e})=>{let t=(0,L.useMemo)(()=>{switch(e.type){case`markdown`:case`link`:return(0,R.jsx)(G,{markdown:e.data});case`image`:return(0,R.jsx)(W,{url:e.data});case`progress`:return(0,R.jsx)(K,{progress:e.data});case`table`:return(0,R.jsx)(J,{tableData:e.data});default:return(0,R.jsx)(`pre`,{children:JSON.stringify(e.data,null,2)})}},[e]),n=(0,R.jsx)(te,{artifact:e});return(0,R.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,R.jsx)(z,{artifact:e}),(0,R.jsxs)(`div`,{className:`flex flex-col lg:flex-row lg:gap-6`,children:[(0,R.jsx)(`div`,{className:`flex-1 min-w-0`,children:(0,R.jsx)(V,{artifact:e,artifactContent:t,detailsContent:n})}),(0,R.jsx)(C,{children:n})]})]})},re=function(){let{id:e}=A.useParams(),{data:t}=l(S(e));return(0,R.jsx)(ne,{artifact:P(e)??t})};export{re as component};
|
|
2
|
+
//# sourceMappingURL=artifact._id-CZKgXEWB.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"artifact._id-Zo42JsyQ.js","names":["useSuspenseQuery","buildGetArtifactQuery","useGetArtifactFlowTaskRuns","ArtifactDetailPage","Route","SplitComponent","RouteComponent","id","useParams","data","artifact","artifactWithMetadata","component"],"sources":["../../src/components/artifacts/artifact/artifact-detail-header.tsx","../../src/components/artifacts/artifact/artifact-raw-data-display.tsx","../../src/components/artifacts/artifact/artifact-detail-tabs.tsx","../../src/components/artifacts/artifact/detail-image.tsx","../../src/components/artifacts/artifact/detail-markdown.tsx","../../src/components/artifacts/artifact/detail-progress.tsx","../../src/components/artifacts/artifact/detail-table.tsx","../../src/components/artifacts/artifact/metadata-sidebar/artifact-section.tsx","../../src/components/artifacts/artifact/metadata-sidebar/flow-run-section.tsx","../../src/components/artifacts/artifact/metadata-sidebar/links-section.tsx","../../src/components/artifacts/artifact/metadata-sidebar/task-run-section.tsx","../../src/components/artifacts/artifact/metadata-sidebar/index.tsx","../../src/components/artifacts/artifact/artifact-detail-page.tsx","../../src/routes/artifacts/artifact.$id.tsx?tsr-split=component"],"sourcesContent":["import type { ArtifactWithFlowRunAndTaskRun } from \"@/api/artifacts\";\nimport {\n\tBreadcrumb,\n\tBreadcrumbItem,\n\tBreadcrumbLink,\n\tBreadcrumbList,\n\tBreadcrumbSeparator,\n} from \"@/components/ui/breadcrumb\";\nimport { DocsLink } from \"@/components/ui/docs-link\";\nimport { LazyMarkdown } from \"@/components/ui/lazy-markdown\";\n\nexport type ArtifactDetailHeaderProps = {\n\tartifact: ArtifactWithFlowRunAndTaskRun;\n};\n\nexport const ArtifactDetailHeader = ({\n\tartifact,\n}: ArtifactDetailHeaderProps) => {\n\tconst header = artifact.key ? (\n\t\t<div className=\"flex items-center gap-2 min-w-0\">\n\t\t\t<Breadcrumb className=\"min-w-0\">\n\t\t\t\t<BreadcrumbList className=\"flex-nowrap\">\n\t\t\t\t\t<BreadcrumbItem className=\"min-w-0\">\n\t\t\t\t\t\t<BreadcrumbLink\n\t\t\t\t\t\t\tto=\"/artifacts/key/$key\"\n\t\t\t\t\t\t\tparams={{ key: artifact.key }}\n\t\t\t\t\t\t\tclassName=\"text-xl font-semibold truncate block\"\n\t\t\t\t\t\t\ttitle={artifact.key}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{artifact.key}\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 min-w-0\">\n\t\t\t\t\t\t<span className=\"font-mono truncate block\" title={artifact.id}>\n\t\t\t\t\t\t\t{artifact.id}\n\t\t\t\t\t\t</span>\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\t\t<div className=\"flex items-center gap-2 min-w-0\">\n\t\t\t<Breadcrumb className=\"min-w-0\">\n\t\t\t\t<BreadcrumbList className=\"flex-nowrap\">\n\t\t\t\t\t{artifact.flow_run && (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<BreadcrumbItem className=\"min-w-0\">\n\t\t\t\t\t\t\t\t<BreadcrumbLink\n\t\t\t\t\t\t\t\t\tto=\"/runs/flow-run/$id\"\n\t\t\t\t\t\t\t\t\tparams={{ id: artifact.flow_run_id ?? \"\" }}\n\t\t\t\t\t\t\t\t\tclassName=\"text-xl font-semibold truncate block\"\n\t\t\t\t\t\t\t\t\ttitle={artifact.flow_run.name}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{artifact.flow_run.name}\n\t\t\t\t\t\t\t\t</BreadcrumbLink>\n\t\t\t\t\t\t\t</BreadcrumbItem>\n\t\t\t\t\t\t\t<BreadcrumbSeparator />\n\t\t\t\t\t\t</>\n\t\t\t\t\t)}\n\t\t\t\t\t{artifact.task_run && (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<BreadcrumbItem className=\"min-w-0\">\n\t\t\t\t\t\t\t\t<BreadcrumbLink\n\t\t\t\t\t\t\t\t\tto=\"/runs/task-run/$id\"\n\t\t\t\t\t\t\t\t\tparams={{ id: artifact.task_run_id ?? \"\" }}\n\t\t\t\t\t\t\t\t\tclassName=\"text-xl font-semibold truncate block\"\n\t\t\t\t\t\t\t\t\ttitle={artifact.task_run.name}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{artifact.task_run.name}\n\t\t\t\t\t\t\t\t</BreadcrumbLink>\n\t\t\t\t\t\t\t</BreadcrumbItem>\n\t\t\t\t\t\t\t<BreadcrumbSeparator />\n\t\t\t\t\t\t</>\n\t\t\t\t\t)}\n\t\t\t\t\t<BreadcrumbItem className=\"text-xl font-semibold min-w-0\">\n\t\t\t\t\t\t<span className=\"font-mono truncate block\" title={artifact.id}>\n\t\t\t\t\t\t\t{artifact.id}\n\t\t\t\t\t\t</span>\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\treturn (\n\t\t<>\n\t\t\t<div className=\"flex items-center justify-between\">\n\t\t\t\t{header}\n\t\t\t\t<DocsLink id=\"artifacts-guide\" label=\"Documentation\" />\n\t\t\t</div>\n\t\t\t{artifact.description && (\n\t\t\t\t<div className=\"text-sm text-muted-foreground my-2\">\n\t\t\t\t\t<LazyMarkdown>{artifact.description}</LazyMarkdown>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t<hr />\n\t\t</>\n\t);\n};\n","import { EditorView, useCodeMirror } from \"@uiw/react-codemirror\";\nimport { useEffect, useRef, useState } from \"react\";\nimport { toast } from \"sonner\";\nimport type { ArtifactWithFlowRunAndTaskRun } from \"@/api/artifacts\";\nimport { Button } from \"@/components/ui/button\";\nimport { Icon } from \"@/components/ui/icons\";\n\ntype ArtifactDataDisplayProps = {\n\tartifact: ArtifactWithFlowRunAndTaskRun;\n};\n\nexport const ArtifactDataDisplay = ({ artifact }: ArtifactDataDisplayProps) => {\n\tconst [showData, setShowData] = useState(false);\n\n\tconst toggleShowData = () => {\n\t\tsetShowData((val) => !val);\n\t};\n\n\tconst editor = useRef<HTMLDivElement | null>(null);\n\tconst basicSetup = {\n\t\thighlightActiveLine: false,\n\t\tfoldGutter: false,\n\t\thighlightActiveLineGutter: false,\n\t};\n\tconst { setContainer } = useCodeMirror({\n\t\tcontainer: editor.current,\n\t\textensions: [EditorView.lineWrapping],\n\t\tvalue: String(artifact.data),\n\t\tindentWithTab: false,\n\t\teditable: true,\n\t\tbasicSetup,\n\t});\n\n\tuseEffect(() => {\n\t\tif (editor.current) {\n\t\t\tsetContainer(editor.current);\n\t\t}\n\t}, [setContainer]);\n\n\tconst handleCopy = (_value: string) => {\n\t\ttoast.success(\"Copied to clipboard\");\n\t\tvoid navigator.clipboard.writeText(_value);\n\t};\n\n\treturn (\n\t\t<div className=\"flex flex-col justify-center items-center\">\n\t\t\t<Button\n\t\t\t\tdata-testid=\"show-raw-data-button\"\n\t\t\t\tvariant={\"outline\"}\n\t\t\t\tonClick={toggleShowData}\n\t\t\t\tclassName=\"my-4\"\n\t\t\t>\n\t\t\t\t{showData ? \"Hide\" : \"Show\"} Raw Data\n\t\t\t</Button>\n\n\t\t\t<div\n\t\t\t\tclassName=\"rounded-md border shadow-xs focus-within:outline-hidden focus-within:ring-1 focus-within:ring-ring relative\"\n\t\t\t\tstyle={{\n\t\t\t\t\tdisplay: showData ? \"block\" : \"none\",\n\t\t\t\t}}\n\t\t\t\tref={(node) => {\n\t\t\t\t\teditor.current = node;\n\t\t\t\t}}\n\t\t\t\tdata-testid=\"raw-data-display\"\n\t\t\t>\n\t\t\t\t<Button\n\t\t\t\t\tonClick={() => handleCopy(artifact.data as string)}\n\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\tclassName=\"absolute top-0 right-0 z-10\"\n\t\t\t\t\taria-label=\"copy\"\n\t\t\t\t>\n\t\t\t\t\t<Icon id=\"Copy\" className=\"size-2\" />\n\t\t\t\t</Button>\n\t\t\t</div>\n\t\t</div>\n\t);\n};\n","import { getRouteApi, Link } from \"@tanstack/react-router\";\nimport { type JSX, type ReactNode, useMemo } from \"react\";\nimport type { ArtifactWithFlowRunAndTaskRun } from \"@/api/artifacts\";\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from \"@/components/ui/tabs\";\nimport type { ArtifactDetailTabOptions } from \"@/routes/artifacts/artifact.$id\";\nimport { cn } from \"@/utils\";\n\nimport { ArtifactDataDisplay } from \"./artifact-raw-data-display\";\n\nconst routeApi = getRouteApi(\"/artifacts/artifact/$id\");\n\ntype TabOption = {\n\tvalue: ArtifactDetailTabOptions;\n\thiddenOnDesktop?: boolean;\n\tLinkComponent: (props: { className?: string }) => JSX.Element;\n\tViewComponent: () => JSX.Element;\n};\n\ntype ArtifactDetailTabsProps = {\n\tartifact: ArtifactWithFlowRunAndTaskRun;\n\tartifactContent: ReactNode;\n\tdetailsContent: ReactNode;\n};\n\nexport const ArtifactDetailTabs = ({\n\tartifact,\n\tartifactContent,\n\tdetailsContent,\n}: ArtifactDetailTabsProps) => {\n\tconst { tab } = routeApi.useSearch();\n\n\tconst tabOptions = useBuildTabOptions(\n\t\tartifact,\n\t\tartifactContent,\n\t\tdetailsContent,\n\t);\n\n\treturn (\n\t\t<Tabs defaultValue=\"Artifact\" value={tab}>\n\t\t\t<TabsList>\n\t\t\t\t{tabOptions.map(({ value, hiddenOnDesktop, LinkComponent }) => (\n\t\t\t\t\t<LinkComponent\n\t\t\t\t\t\tkey={value}\n\t\t\t\t\t\tclassName={cn(hiddenOnDesktop && \"lg:hidden\")}\n\t\t\t\t\t/>\n\t\t\t\t))}\n\t\t\t</TabsList>\n\t\t\t{tabOptions.map(({ value, ViewComponent }) => (\n\t\t\t\t<ViewComponent key={value} />\n\t\t\t))}\n\t\t</Tabs>\n\t);\n};\n\nfunction useBuildTabOptions(\n\tartifact: ArtifactWithFlowRunAndTaskRun,\n\tartifactContent: ReactNode,\n\tdetailsContent: ReactNode,\n): Array<TabOption> {\n\treturn useMemo(() => {\n\t\tconst tabs: Array<TabOption> = [];\n\n\t\ttabs.push({\n\t\t\tvalue: \"Artifact\",\n\t\t\tLinkComponent: ({ className }) => (\n\t\t\t\t<Link to=\".\" search={{ tab: \"Artifact\" }}>\n\t\t\t\t\t<TabsTrigger value=\"Artifact\" className={className}>\n\t\t\t\t\t\tArtifact\n\t\t\t\t\t</TabsTrigger>\n\t\t\t\t</Link>\n\t\t\t),\n\t\t\tViewComponent: () => (\n\t\t\t\t<TabsContent value=\"Artifact\">\n\t\t\t\t\t{artifactContent}\n\t\t\t\t\t<ArtifactDataDisplay artifact={artifact} />\n\t\t\t\t</TabsContent>\n\t\t\t),\n\t\t});\n\n\t\ttabs.push({\n\t\t\tvalue: \"Details\",\n\t\t\thiddenOnDesktop: true,\n\t\t\tLinkComponent: ({ className }) => (\n\t\t\t\t<Link to=\".\" search={{ tab: \"Details\" }}>\n\t\t\t\t\t<TabsTrigger value=\"Details\" className={className}>\n\t\t\t\t\t\tDetails\n\t\t\t\t\t</TabsTrigger>\n\t\t\t\t</Link>\n\t\t\t),\n\t\t\tViewComponent: () => (\n\t\t\t\t<TabsContent value=\"Details\">{detailsContent}</TabsContent>\n\t\t\t),\n\t\t});\n\n\t\ttabs.push({\n\t\t\tvalue: \"Raw\",\n\t\t\tLinkComponent: ({ className }) => (\n\t\t\t\t<Link to=\".\" search={{ tab: \"Raw\" }}>\n\t\t\t\t\t<TabsTrigger value=\"Raw\" className={className}>\n\t\t\t\t\t\tRaw\n\t\t\t\t\t</TabsTrigger>\n\t\t\t\t</Link>\n\t\t\t),\n\t\t\tViewComponent: () => (\n\t\t\t\t<TabsContent value=\"Raw\">\n\t\t\t\t\t<ArtifactRawData artifact={artifact} />\n\t\t\t\t</TabsContent>\n\t\t\t),\n\t\t});\n\n\t\treturn tabs;\n\t}, [artifact, artifactContent, detailsContent]);\n}\n\nfunction ArtifactRawData({\n\tartifact,\n}: {\n\tartifact: ArtifactWithFlowRunAndTaskRun;\n}) {\n\treturn (\n\t\t<pre className=\"whitespace-pre-wrap break-words rounded-md border bg-muted p-4 text-sm\">\n\t\t\t{typeof artifact.data === \"string\"\n\t\t\t\t? artifact.data\n\t\t\t\t: JSON.stringify(artifact.data, null, 2)}\n\t\t</pre>\n\t);\n}\n","export type DetailImageProps = {\n\turl: string;\n};\n\nexport const DetailImage = ({ url }: DetailImageProps) => {\n\treturn (\n\t\t<div data-testid={url} className=\"prose dark:prose-invert mt-2\">\n\t\t\t<img\n\t\t\t\tdata-testid={`image-${url}`}\n\t\t\t\tsrc={url}\n\t\t\t\talt=\"artifact-image\"\n\t\t\t\tclassName=\"w-full\"\n\t\t\t/>\n\n\t\t\t<p className=\"text-lg\">\n\t\t\t\tImage URL:{\" \"}\n\t\t\t\t<a\n\t\t\t\t\tclassName=\"text-link hover:text-link-hover hover:underline\"\n\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\thref={url}\n\t\t\t\t\trel=\"noreferrer\"\n\t\t\t\t>\n\t\t\t\t\t{url}\n\t\t\t\t</a>\n\t\t\t</p>\n\t\t</div>\n\t);\n};\n","import { LazyMarkdown } from \"@/components/ui/lazy-markdown\";\n\nexport type DetailMarkdownProps = {\n\tmarkdown: string;\n};\n\nexport const DetailMarkdown = ({ markdown }: DetailMarkdownProps) => {\n\treturn (\n\t\t<div\n\t\t\tdata-testid=\"markdown-display\"\n\t\t\tclassName=\"mt-4 prose dark:prose-invert\"\n\t\t>\n\t\t\t<LazyMarkdown>{markdown}</LazyMarkdown>\n\t\t</div>\n\t);\n};\n","export type DetailProgressProps = {\n\tprogress: number;\n};\n\nexport const DetailProgress = ({ progress }: DetailProgressProps) => {\n\treturn (\n\t\t<p data-testid=\"progress-display\" className=\"text-lg\">\n\t\t\tProgress: {progress}%\n\t\t</p>\n\t);\n};\n","import {\n\tcreateColumnHelper,\n\tgetCoreRowModel,\n\tgetPaginationRowModel,\n\tuseReactTable,\n} from \"@tanstack/react-table\";\nimport { useMemo, useState } from \"react\";\nimport { DataTable } from \"@/components/ui/data-table\";\nimport { SearchInput } from \"@/components/ui/input\";\n\nexport type DetailTableProps = {\n\ttableData: string;\n};\n\nconst columnHelper = createColumnHelper<Record<string, string>>();\n\nexport const DetailTable = ({ tableData }: DetailTableProps) => {\n\tconst rows = useMemo(\n\t\t() => JSON.parse(tableData) as Record<string, string>[],\n\t\t[tableData],\n\t);\n\tconst headers = useMemo(() => Object.keys(rows[0] ?? {}), [rows]);\n\tconst [input, setInput] = useState<string>(\"\");\n\n\tconst columns = useMemo(\n\t\t() =>\n\t\t\theaders.map((header) =>\n\t\t\t\tcolumnHelper.display({\n\t\t\t\t\tid: header,\n\t\t\t\t\theader: () => header,\n\t\t\t\t\tcell: ({ row }) => {\n\t\t\t\t\t\tconst value = String(row.original[header] ?? \"\");\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<span className=\"truncate block\" title={value}>\n\t\t\t\t\t\t\t\t{value}\n\t\t\t\t\t\t\t</span>\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[headers],\n\t);\n\n\tconst filteredRows = useMemo(() => {\n\t\tif (!input) return rows;\n\t\treturn rows.filter((row) =>\n\t\t\tObject.values(row).some((value) =>\n\t\t\t\tString(value).toLowerCase().includes(input.toLowerCase()),\n\t\t\t),\n\t\t);\n\t}, [input, rows]);\n\n\tconst table = useReactTable({\n\t\tdata: filteredRows,\n\t\tcolumns,\n\t\tgetCoreRowModel: getCoreRowModel(),\n\t\tgetPaginationRowModel: getPaginationRowModel(),\n\t\tinitialState: { pagination: { pageIndex: 0, pageSize: 10 } },\n\t});\n\n\treturn (\n\t\t<div data-testid=\"table-display\" className=\"mt-4\">\n\t\t\t<div className=\"flex flex-row justify-end items-center mb-2\">\n\t\t\t\t<SearchInput\n\t\t\t\t\tplaceholder=\"Search\"\n\t\t\t\t\tvalue={input}\n\t\t\t\t\tonChange={(e) => setInput(e.target.value)}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t\t<DataTable table={table} />\n\t\t</div>\n\t);\n};\n","import { useMemo } from \"react\";\nimport type { ArtifactWithFlowRunAndTaskRun } from \"@/api/artifacts\";\nimport { KeyValue } from \"@/components/ui/key-value\";\nimport { formatDate } from \"@/utils/date\";\n\ntype ArtifactSectionProps = {\n\tartifact: ArtifactWithFlowRunAndTaskRun;\n};\n\nexport const ArtifactSection = ({ artifact }: ArtifactSectionProps) => {\n\tconst createdDate = useMemo(() => {\n\t\tif (!artifact.created) return null;\n\t\treturn formatDate(artifact.created, \"dateTime\");\n\t}, [artifact.created]);\n\n\treturn (\n\t\t<div className=\"mt-4\">\n\t\t\t<p className=\"text-base font-semibold\">Artifact</p>\n\n\t\t\t<div className=\"mt-3 flex flex-col gap-3\">\n\t\t\t\t<KeyValue\n\t\t\t\t\tlabel=\"Key\"\n\t\t\t\t\tvalue={<span className=\"font-mono\">{artifact.key ?? \"None\"}</span>}\n\t\t\t\t/>\n\n\t\t\t\t<KeyValue\n\t\t\t\t\tlabel=\"Type\"\n\t\t\t\t\tvalue={<span className=\"font-mono\">{artifact.type ?? \"None\"}</span>}\n\t\t\t\t/>\n\n\t\t\t\t<KeyValue\n\t\t\t\t\tlabel=\"Created\"\n\t\t\t\t\tvalue={<span>{createdDate ?? \"None\"}</span>}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t</div>\n\t);\n};\n","import humanizeDuration from \"humanize-duration\";\nimport { useMemo } from \"react\";\nimport type { FlowRun } from \"@/api/flow-runs\";\nimport { Icon } from \"@/components/ui/icons\";\nimport { KeyValue } from \"@/components/ui/key-value\";\nimport { TagBadge } from \"@/components/ui/tag-badge\";\nimport { formatDate } from \"@/utils/date\";\n\ntype FlowRunSectionProps = {\n\tflowRun: FlowRun;\n};\n\nexport const FlowRunSection = ({ flowRun }: FlowRunSectionProps) => {\n\tconst startTime = useMemo(() => {\n\t\tif (!flowRun.start_time) return null;\n\t\treturn formatDate(flowRun.start_time, \"dateTime\");\n\t}, [flowRun.start_time]);\n\n\tconst duration = useMemo(() => {\n\t\tif (!flowRun.estimated_run_time) return null;\n\t\treturn humanizeDuration(Math.ceil(flowRun.estimated_run_time) * 1000);\n\t}, [flowRun.estimated_run_time]);\n\n\tconst createdDate = useMemo(() => {\n\t\tif (!flowRun.created) return null;\n\t\treturn formatDate(flowRun.created, \"dateTime\");\n\t}, [flowRun.created]);\n\n\tconst updatedDate = useMemo(() => {\n\t\tif (!flowRun.updated) return null;\n\t\treturn formatDate(flowRun.updated, \"dateTime\");\n\t}, [flowRun.updated]);\n\n\treturn (\n\t\t<div className=\"mt-4\">\n\t\t\t<p className=\"text-lg font-bold\">Flow Run</p>\n\n\t\t\t<div className=\"mt-3 flex flex-col gap-3\">\n\t\t\t\t<KeyValue\n\t\t\t\t\tlabel=\"Start time\"\n\t\t\t\t\tvalue={\n\t\t\t\t\t\t<span className=\"font-mono flex items-center\">\n\t\t\t\t\t\t\t<Icon id=\"Calendar\" className=\"inline w-4 mr-2\" />\n\t\t\t\t\t\t\t{startTime ?? \"None\"}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t}\n\t\t\t\t/>\n\n\t\t\t\t<KeyValue\n\t\t\t\t\tlabel=\"Duration\"\n\t\t\t\t\tvalue={\n\t\t\t\t\t\t<span className=\"font-mono flex items-center\">\n\t\t\t\t\t\t\t<Icon id=\"Clock\" className=\"inline w-4 mr-2\" />\n\t\t\t\t\t\t\t{duration ?? \"None\"}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t}\n\t\t\t\t/>\n\n\t\t\t\t<KeyValue\n\t\t\t\t\tlabel=\"Created\"\n\t\t\t\t\tvalue={<span className=\"font-mono\">{createdDate ?? \"None\"}</span>}\n\t\t\t\t/>\n\n\t\t\t\t<KeyValue\n\t\t\t\t\tlabel=\"Last Updated\"\n\t\t\t\t\tvalue={<span className=\"font-mono\">{updatedDate ?? \"None\"}</span>}\n\t\t\t\t/>\n\n\t\t\t\t<KeyValue\n\t\t\t\t\tlabel=\"Tags\"\n\t\t\t\t\tvalue={\n\t\t\t\t\t\tflowRun.tags && flowRun.tags.length > 0 ? (\n\t\t\t\t\t\t\t<div className=\"flex flex-wrap\">\n\t\t\t\t\t\t\t\t{flowRun.tags.map((tag) => (\n\t\t\t\t\t\t\t\t\t<TagBadge key={tag} tag={tag} />\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<span className=\"font-mono\">None</span>\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t/>\n\n\t\t\t\t<KeyValue\n\t\t\t\t\tlabel=\"State Message\"\n\t\t\t\t\tvalue={\n\t\t\t\t\t\t<span className=\"font-mono\">\n\t\t\t\t\t\t\t{flowRun.state?.message ?? \"None\"}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t</div>\n\t);\n};\n","import { Link } from \"@tanstack/react-router\";\nimport type { ArtifactWithFlowRunAndTaskRun } from \"@/api/artifacts\";\nimport { KeyValue } from \"@/components/ui/key-value\";\n\ntype LinksSectionProps = {\n\tartifact: ArtifactWithFlowRunAndTaskRun;\n};\n\nexport const LinksSection = ({ artifact }: LinksSectionProps) => {\n\tconst { flow_run, task_run } = artifact;\n\tconst hasLinks = artifact.key || flow_run || task_run;\n\n\tif (!hasLinks) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<div className=\"flex flex-col gap-2\">\n\t\t\t{artifact.key && (\n\t\t\t\t<KeyValue\n\t\t\t\t\tlabel=\"Artifact\"\n\t\t\t\t\tvalue={\n\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\tto=\"/artifacts/key/$key\"\n\t\t\t\t\t\t\tparams={{ key: artifact.key }}\n\t\t\t\t\t\t\tclassName=\"text-link hover:text-link-hover hover:underline\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{artifact.key}\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t{flow_run && (\n\t\t\t\t<KeyValue\n\t\t\t\t\tlabel=\"Flow Run\"\n\t\t\t\t\tvalue={\n\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\tto=\"/runs/flow-run/$id\"\n\t\t\t\t\t\t\tparams={{ id: flow_run.id }}\n\t\t\t\t\t\t\tclassName=\"text-link hover:text-link-hover hover:underline\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{flow_run.name}\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t{task_run && (\n\t\t\t\t<KeyValue\n\t\t\t\t\tlabel=\"Task Run\"\n\t\t\t\t\tvalue={\n\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\tto=\"/runs/task-run/$id\"\n\t\t\t\t\t\t\tparams={{ id: task_run.id }}\n\t\t\t\t\t\t\tclassName=\"text-link hover:text-link-hover hover:underline\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{task_run.name}\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t<hr className=\"mt-2 border-border\" />\n\t\t</div>\n\t);\n};\n","import { useMemo } from \"react\";\nimport type { TaskRun } from \"@/api/task-runs\";\nimport { KeyValue } from \"@/components/ui/key-value\";\nimport { TagBadge } from \"@/components/ui/tag-badge\";\nimport { formatDate } from \"@/utils/date\";\n\ntype TaskRunSectionProps = {\n\ttaskRun: TaskRun;\n};\n\nexport const TaskRunSection = ({ taskRun }: TaskRunSectionProps) => {\n\tconst createdDate = useMemo(() => {\n\t\tif (!taskRun.created) return null;\n\t\treturn formatDate(taskRun.created, \"dateTime\");\n\t}, [taskRun.created]);\n\n\tconst updatedDate = useMemo(() => {\n\t\tif (!taskRun.updated) return null;\n\t\treturn formatDate(taskRun.updated, \"dateTime\");\n\t}, [taskRun.updated]);\n\n\treturn (\n\t\t<div className=\"mt-4\">\n\t\t\t<p className=\"text-lg font-bold\">Task Run</p>\n\n\t\t\t<div className=\"mt-3 flex flex-col gap-3\">\n\t\t\t\t<KeyValue\n\t\t\t\t\tlabel=\"Created\"\n\t\t\t\t\tvalue={<span className=\"font-mono\">{createdDate ?? \"None\"}</span>}\n\t\t\t\t/>\n\n\t\t\t\t<KeyValue\n\t\t\t\t\tlabel=\"Last Updated\"\n\t\t\t\t\tvalue={<span className=\"font-mono\">{updatedDate ?? \"None\"}</span>}\n\t\t\t\t/>\n\n\t\t\t\t<KeyValue\n\t\t\t\t\tlabel=\"Tags\"\n\t\t\t\t\tvalue={\n\t\t\t\t\t\ttaskRun.tags && taskRun.tags.length > 0 ? (\n\t\t\t\t\t\t\t<div className=\"flex flex-wrap\">\n\t\t\t\t\t\t\t\t{taskRun.tags.map((tag) => (\n\t\t\t\t\t\t\t\t\t<TagBadge key={tag} tag={tag} />\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<span className=\"font-mono\">None</span>\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t</div>\n\t);\n};\n","import type { ArtifactWithFlowRunAndTaskRun } from \"@/api/artifacts\";\nimport { ArtifactSection } from \"./artifact-section\";\nimport { FlowRunSection } from \"./flow-run-section\";\nimport { LinksSection } from \"./links-section\";\nimport { TaskRunSection } from \"./task-run-section\";\n\nexport type MetadataSidebarProps = {\n\tartifact: ArtifactWithFlowRunAndTaskRun;\n};\n\nexport const MetadataSidebar = ({ artifact }: MetadataSidebarProps) => {\n\tconst { flow_run, task_run } = artifact;\n\n\treturn (\n\t\t<div className=\"flex flex-col gap-4 pt-4\">\n\t\t\t<LinksSection artifact={artifact} />\n\n\t\t\t<ArtifactSection artifact={artifact} />\n\n\t\t\t{(flow_run || task_run) && <hr className=\"mt-4 border-border\" />}\n\n\t\t\t{flow_run && <FlowRunSection flowRun={flow_run} />}\n\n\t\t\t{flow_run && task_run && <hr className=\"mt-4 border-border\" />}\n\n\t\t\t{task_run && <TaskRunSection taskRun={task_run} />}\n\t\t</div>\n\t);\n};\n","import { useMemo } from \"react\";\nimport type { ArtifactWithFlowRunAndTaskRun } from \"@/api/artifacts\";\nimport { LayoutWellSidebar } from \"@/components/ui/layout-well\";\nimport { ArtifactDetailHeader } from \"./artifact-detail-header\";\nimport { ArtifactDetailTabs } from \"./artifact-detail-tabs\";\nimport { DetailImage } from \"./detail-image\";\nimport { DetailMarkdown } from \"./detail-markdown\";\nimport { DetailProgress } from \"./detail-progress\";\nimport { DetailTable } from \"./detail-table\";\nimport { MetadataSidebar } from \"./metadata-sidebar\";\n\nexport type ArtifactDetailPageProps = {\n\tartifact: ArtifactWithFlowRunAndTaskRun;\n};\n\nexport const ArtifactDetailPage = ({ artifact }: ArtifactDetailPageProps) => {\n\tconst artifactContent = useMemo(() => {\n\t\tswitch (artifact.type) {\n\t\t\tcase \"markdown\":\n\t\t\tcase \"link\":\n\t\t\t\treturn <DetailMarkdown markdown={artifact.data as string} />;\n\t\t\tcase \"image\":\n\t\t\t\treturn <DetailImage url={artifact.data as string} />;\n\t\t\tcase \"progress\":\n\t\t\t\treturn <DetailProgress progress={artifact.data as number} />;\n\t\t\tcase \"table\":\n\t\t\t\treturn <DetailTable tableData={artifact.data as string} />;\n\t\t\tdefault:\n\t\t\t\treturn <pre>{JSON.stringify(artifact.data, null, 2)}</pre>;\n\t\t}\n\t}, [artifact]);\n\n\tconst sidebarContent = <MetadataSidebar artifact={artifact} />;\n\n\treturn (\n\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t<ArtifactDetailHeader artifact={artifact} />\n\t\t\t<div className=\"flex flex-col lg:flex-row lg:gap-6\">\n\t\t\t\t<div className=\"flex-1 min-w-0\">\n\t\t\t\t\t<ArtifactDetailTabs\n\t\t\t\t\t\tartifact={artifact}\n\t\t\t\t\t\tartifactContent={artifactContent}\n\t\t\t\t\t\tdetailsContent={sidebarContent}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t\t<LayoutWellSidebar>{sidebarContent}</LayoutWellSidebar>\n\t\t\t</div>\n\t\t</div>\n\t);\n};\n","import { useSuspenseQuery } from \"@tanstack/react-query\";\nimport type { ErrorComponentProps } from \"@tanstack/react-router\";\nimport { createFileRoute } from \"@tanstack/react-router\";\nimport { zodValidator } from \"@tanstack/zod-adapter\";\nimport { z } from \"zod\";\nimport { buildGetArtifactQuery } from \"@/api/artifacts\";\nimport { useGetArtifactFlowTaskRuns } from \"@/api/artifacts/use-get-artifacts-flow-task-runs/use-get-artifacts-flow-task-runs\";\nimport { categorizeError } from \"@/api/error-utils\";\nimport { ArtifactDetailPage } from \"@/components/artifacts/artifact/artifact-detail-page\";\nimport { RouteErrorState } from \"@/components/ui/route-error-state\";\n\n/**\n * Schema for validating URL search parameters for the Artifact Detail page\n * @property {\"Artifact\" | \"Details\" | \"Raw\"} tab used to designate which tab view to display\n */\nconst searchParams = z.object({\n\ttab: z.enum([\"Artifact\", \"Details\", \"Raw\"]).default(\"Artifact\"),\n});\n\nexport type ArtifactDetailTabOptions = z.infer<typeof searchParams>[\"tab\"];\n\nexport const Route = createFileRoute(\"/artifacts/artifact/$id\")({\n\tvalidateSearch: zodValidator(searchParams),\n\tcomponent: function RouteComponent() {\n\t\tconst { id } = Route.useParams();\n\n\t\tconst { data: artifact } = useSuspenseQuery(buildGetArtifactQuery(id));\n\n\t\tconst artifactWithMetadata = useGetArtifactFlowTaskRuns(id);\n\n\t\treturn <ArtifactDetailPage artifact={artifactWithMetadata ?? artifact} />;\n\t},\n\tloader: async ({ context, params }) => {\n\t\tconst { id } = params;\n\n\t\tconst artifact = await context.queryClient.ensureQueryData(\n\t\t\tbuildGetArtifactQuery(id),\n\t\t);\n\n\t\treturn { artifact };\n\t},\n\terrorComponent: function ArtifactDetailErrorComponent({\n\t\terror,\n\t\treset,\n\t}: ErrorComponentProps) {\n\t\tconst serverError = categorizeError(error, \"Failed to load artifact\");\n\t\tif (\n\t\t\tserverError.type !== \"server-error\" &&\n\t\t\tserverError.type !== \"client-error\"\n\t\t) {\n\t\t\tthrow error;\n\t\t}\n\t\treturn (\n\t\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t\t<div>\n\t\t\t\t\t<h1 className=\"text-2xl font-semibold\">Artifact</h1>\n\t\t\t\t</div>\n\t\t\t\t<RouteErrorState error={serverError} onRetry={reset} />\n\t\t\t</div>\n\t\t);\n\t},\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"artifact._id-CZKgXEWB.js","names":["useSuspenseQuery","buildGetArtifactQuery","useGetArtifactFlowTaskRuns","ArtifactDetailPage","Route","SplitComponent","RouteComponent","id","useParams","data","artifact","artifactWithMetadata","component"],"sources":["../../src/components/artifacts/artifact/artifact-detail-header.tsx","../../src/components/artifacts/artifact/artifact-raw-data-display.tsx","../../src/components/artifacts/artifact/artifact-detail-tabs.tsx","../../src/components/artifacts/artifact/detail-image.tsx","../../src/components/artifacts/artifact/detail-markdown.tsx","../../src/components/artifacts/artifact/detail-progress.tsx","../../src/components/artifacts/artifact/detail-table.tsx","../../src/components/artifacts/artifact/metadata-sidebar/artifact-section.tsx","../../src/components/artifacts/artifact/metadata-sidebar/flow-run-section.tsx","../../src/components/artifacts/artifact/metadata-sidebar/links-section.tsx","../../src/components/artifacts/artifact/metadata-sidebar/task-run-section.tsx","../../src/components/artifacts/artifact/metadata-sidebar/index.tsx","../../src/components/artifacts/artifact/artifact-detail-page.tsx","../../src/routes/artifacts/artifact.$id.tsx?tsr-split=component"],"sourcesContent":["import type { ArtifactWithFlowRunAndTaskRun } from \"@/api/artifacts\";\nimport {\n\tBreadcrumb,\n\tBreadcrumbItem,\n\tBreadcrumbLink,\n\tBreadcrumbList,\n\tBreadcrumbSeparator,\n} from \"@/components/ui/breadcrumb\";\nimport { DocsLink } from \"@/components/ui/docs-link\";\nimport { LazyMarkdown } from \"@/components/ui/lazy-markdown\";\n\nexport type ArtifactDetailHeaderProps = {\n\tartifact: ArtifactWithFlowRunAndTaskRun;\n};\n\nexport const ArtifactDetailHeader = ({\n\tartifact,\n}: ArtifactDetailHeaderProps) => {\n\tconst header = artifact.key ? (\n\t\t<div className=\"flex items-center gap-2 min-w-0\">\n\t\t\t<Breadcrumb className=\"min-w-0\">\n\t\t\t\t<BreadcrumbList className=\"flex-nowrap\">\n\t\t\t\t\t<BreadcrumbItem className=\"min-w-0\">\n\t\t\t\t\t\t<BreadcrumbLink\n\t\t\t\t\t\t\tto=\"/artifacts/key/$key\"\n\t\t\t\t\t\t\tparams={{ key: artifact.key }}\n\t\t\t\t\t\t\tclassName=\"text-xl font-semibold truncate block\"\n\t\t\t\t\t\t\ttitle={artifact.key}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{artifact.key}\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 min-w-0\">\n\t\t\t\t\t\t<span className=\"font-mono truncate block\" title={artifact.id}>\n\t\t\t\t\t\t\t{artifact.id}\n\t\t\t\t\t\t</span>\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\t\t<div className=\"flex items-center gap-2 min-w-0\">\n\t\t\t<Breadcrumb className=\"min-w-0\">\n\t\t\t\t<BreadcrumbList className=\"flex-nowrap\">\n\t\t\t\t\t{artifact.flow_run && (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<BreadcrumbItem className=\"min-w-0\">\n\t\t\t\t\t\t\t\t<BreadcrumbLink\n\t\t\t\t\t\t\t\t\tto=\"/runs/flow-run/$id\"\n\t\t\t\t\t\t\t\t\tparams={{ id: artifact.flow_run_id ?? \"\" }}\n\t\t\t\t\t\t\t\t\tclassName=\"text-xl font-semibold truncate block\"\n\t\t\t\t\t\t\t\t\ttitle={artifact.flow_run.name}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{artifact.flow_run.name}\n\t\t\t\t\t\t\t\t</BreadcrumbLink>\n\t\t\t\t\t\t\t</BreadcrumbItem>\n\t\t\t\t\t\t\t<BreadcrumbSeparator />\n\t\t\t\t\t\t</>\n\t\t\t\t\t)}\n\t\t\t\t\t{artifact.task_run && (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<BreadcrumbItem className=\"min-w-0\">\n\t\t\t\t\t\t\t\t<BreadcrumbLink\n\t\t\t\t\t\t\t\t\tto=\"/runs/task-run/$id\"\n\t\t\t\t\t\t\t\t\tparams={{ id: artifact.task_run_id ?? \"\" }}\n\t\t\t\t\t\t\t\t\tclassName=\"text-xl font-semibold truncate block\"\n\t\t\t\t\t\t\t\t\ttitle={artifact.task_run.name}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{artifact.task_run.name}\n\t\t\t\t\t\t\t\t</BreadcrumbLink>\n\t\t\t\t\t\t\t</BreadcrumbItem>\n\t\t\t\t\t\t\t<BreadcrumbSeparator />\n\t\t\t\t\t\t</>\n\t\t\t\t\t)}\n\t\t\t\t\t<BreadcrumbItem className=\"text-xl font-semibold min-w-0\">\n\t\t\t\t\t\t<span className=\"font-mono truncate block\" title={artifact.id}>\n\t\t\t\t\t\t\t{artifact.id}\n\t\t\t\t\t\t</span>\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\treturn (\n\t\t<>\n\t\t\t<div className=\"flex items-center justify-between\">\n\t\t\t\t{header}\n\t\t\t\t<DocsLink id=\"artifacts-guide\" label=\"Documentation\" />\n\t\t\t</div>\n\t\t\t{artifact.description && (\n\t\t\t\t<div className=\"text-sm text-muted-foreground my-2\">\n\t\t\t\t\t<LazyMarkdown>{artifact.description}</LazyMarkdown>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t<hr />\n\t\t</>\n\t);\n};\n","import { EditorView, useCodeMirror } from \"@uiw/react-codemirror\";\nimport { useEffect, useRef, useState } from \"react\";\nimport { toast } from \"sonner\";\nimport type { ArtifactWithFlowRunAndTaskRun } from \"@/api/artifacts\";\nimport { Button } from \"@/components/ui/button\";\nimport { Icon } from \"@/components/ui/icons\";\n\ntype ArtifactDataDisplayProps = {\n\tartifact: ArtifactWithFlowRunAndTaskRun;\n};\n\nexport const ArtifactDataDisplay = ({ artifact }: ArtifactDataDisplayProps) => {\n\tconst [showData, setShowData] = useState(false);\n\n\tconst toggleShowData = () => {\n\t\tsetShowData((val) => !val);\n\t};\n\n\tconst editor = useRef<HTMLDivElement | null>(null);\n\tconst basicSetup = {\n\t\thighlightActiveLine: false,\n\t\tfoldGutter: false,\n\t\thighlightActiveLineGutter: false,\n\t};\n\tconst { setContainer } = useCodeMirror({\n\t\tcontainer: editor.current,\n\t\textensions: [EditorView.lineWrapping],\n\t\tvalue: String(artifact.data),\n\t\tindentWithTab: false,\n\t\teditable: true,\n\t\tbasicSetup,\n\t});\n\n\tuseEffect(() => {\n\t\tif (editor.current) {\n\t\t\tsetContainer(editor.current);\n\t\t}\n\t}, [setContainer]);\n\n\tconst handleCopy = (_value: string) => {\n\t\ttoast.success(\"Copied to clipboard\");\n\t\tvoid navigator.clipboard.writeText(_value);\n\t};\n\n\treturn (\n\t\t<div className=\"flex flex-col justify-center items-center\">\n\t\t\t<Button\n\t\t\t\tdata-testid=\"show-raw-data-button\"\n\t\t\t\tvariant={\"outline\"}\n\t\t\t\tonClick={toggleShowData}\n\t\t\t\tclassName=\"my-4\"\n\t\t\t>\n\t\t\t\t{showData ? \"Hide\" : \"Show\"} Raw Data\n\t\t\t</Button>\n\n\t\t\t<div\n\t\t\t\tclassName=\"rounded-md border shadow-xs focus-within:outline-hidden focus-within:ring-1 focus-within:ring-ring relative\"\n\t\t\t\tstyle={{\n\t\t\t\t\tdisplay: showData ? \"block\" : \"none\",\n\t\t\t\t}}\n\t\t\t\tref={(node) => {\n\t\t\t\t\teditor.current = node;\n\t\t\t\t}}\n\t\t\t\tdata-testid=\"raw-data-display\"\n\t\t\t>\n\t\t\t\t<Button\n\t\t\t\t\tonClick={() => handleCopy(artifact.data as string)}\n\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\tclassName=\"absolute top-0 right-0 z-10\"\n\t\t\t\t\taria-label=\"copy\"\n\t\t\t\t>\n\t\t\t\t\t<Icon id=\"Copy\" className=\"size-2\" />\n\t\t\t\t</Button>\n\t\t\t</div>\n\t\t</div>\n\t);\n};\n","import { getRouteApi, Link } from \"@tanstack/react-router\";\nimport { type JSX, type ReactNode, useMemo } from \"react\";\nimport type { ArtifactWithFlowRunAndTaskRun } from \"@/api/artifacts\";\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from \"@/components/ui/tabs\";\nimport type { ArtifactDetailTabOptions } from \"@/routes/artifacts/artifact.$id\";\nimport { cn } from \"@/utils\";\n\nimport { ArtifactDataDisplay } from \"./artifact-raw-data-display\";\n\nconst routeApi = getRouteApi(\"/artifacts/artifact/$id\");\n\ntype TabOption = {\n\tvalue: ArtifactDetailTabOptions;\n\thiddenOnDesktop?: boolean;\n\tLinkComponent: (props: { className?: string }) => JSX.Element;\n\tViewComponent: () => JSX.Element;\n};\n\ntype ArtifactDetailTabsProps = {\n\tartifact: ArtifactWithFlowRunAndTaskRun;\n\tartifactContent: ReactNode;\n\tdetailsContent: ReactNode;\n};\n\nexport const ArtifactDetailTabs = ({\n\tartifact,\n\tartifactContent,\n\tdetailsContent,\n}: ArtifactDetailTabsProps) => {\n\tconst { tab } = routeApi.useSearch();\n\n\tconst tabOptions = useBuildTabOptions(\n\t\tartifact,\n\t\tartifactContent,\n\t\tdetailsContent,\n\t);\n\n\treturn (\n\t\t<Tabs defaultValue=\"Artifact\" value={tab}>\n\t\t\t<TabsList>\n\t\t\t\t{tabOptions.map(({ value, hiddenOnDesktop, LinkComponent }) => (\n\t\t\t\t\t<LinkComponent\n\t\t\t\t\t\tkey={value}\n\t\t\t\t\t\tclassName={cn(hiddenOnDesktop && \"lg:hidden\")}\n\t\t\t\t\t/>\n\t\t\t\t))}\n\t\t\t</TabsList>\n\t\t\t{tabOptions.map(({ value, ViewComponent }) => (\n\t\t\t\t<ViewComponent key={value} />\n\t\t\t))}\n\t\t</Tabs>\n\t);\n};\n\nfunction useBuildTabOptions(\n\tartifact: ArtifactWithFlowRunAndTaskRun,\n\tartifactContent: ReactNode,\n\tdetailsContent: ReactNode,\n): Array<TabOption> {\n\treturn useMemo(() => {\n\t\tconst tabs: Array<TabOption> = [];\n\n\t\ttabs.push({\n\t\t\tvalue: \"Artifact\",\n\t\t\tLinkComponent: ({ className }) => (\n\t\t\t\t<Link to=\".\" search={{ tab: \"Artifact\" }}>\n\t\t\t\t\t<TabsTrigger value=\"Artifact\" className={className}>\n\t\t\t\t\t\tArtifact\n\t\t\t\t\t</TabsTrigger>\n\t\t\t\t</Link>\n\t\t\t),\n\t\t\tViewComponent: () => (\n\t\t\t\t<TabsContent value=\"Artifact\">\n\t\t\t\t\t{artifactContent}\n\t\t\t\t\t<ArtifactDataDisplay artifact={artifact} />\n\t\t\t\t</TabsContent>\n\t\t\t),\n\t\t});\n\n\t\ttabs.push({\n\t\t\tvalue: \"Details\",\n\t\t\thiddenOnDesktop: true,\n\t\t\tLinkComponent: ({ className }) => (\n\t\t\t\t<Link to=\".\" search={{ tab: \"Details\" }}>\n\t\t\t\t\t<TabsTrigger value=\"Details\" className={className}>\n\t\t\t\t\t\tDetails\n\t\t\t\t\t</TabsTrigger>\n\t\t\t\t</Link>\n\t\t\t),\n\t\t\tViewComponent: () => (\n\t\t\t\t<TabsContent value=\"Details\">{detailsContent}</TabsContent>\n\t\t\t),\n\t\t});\n\n\t\ttabs.push({\n\t\t\tvalue: \"Raw\",\n\t\t\tLinkComponent: ({ className }) => (\n\t\t\t\t<Link to=\".\" search={{ tab: \"Raw\" }}>\n\t\t\t\t\t<TabsTrigger value=\"Raw\" className={className}>\n\t\t\t\t\t\tRaw\n\t\t\t\t\t</TabsTrigger>\n\t\t\t\t</Link>\n\t\t\t),\n\t\t\tViewComponent: () => (\n\t\t\t\t<TabsContent value=\"Raw\">\n\t\t\t\t\t<ArtifactRawData artifact={artifact} />\n\t\t\t\t</TabsContent>\n\t\t\t),\n\t\t});\n\n\t\treturn tabs;\n\t}, [artifact, artifactContent, detailsContent]);\n}\n\nfunction ArtifactRawData({\n\tartifact,\n}: {\n\tartifact: ArtifactWithFlowRunAndTaskRun;\n}) {\n\treturn (\n\t\t<pre className=\"whitespace-pre-wrap break-words rounded-md border bg-muted p-4 text-sm\">\n\t\t\t{typeof artifact.data === \"string\"\n\t\t\t\t? artifact.data\n\t\t\t\t: JSON.stringify(artifact.data, null, 2)}\n\t\t</pre>\n\t);\n}\n","export type DetailImageProps = {\n\turl: string;\n};\n\nexport const DetailImage = ({ url }: DetailImageProps) => {\n\treturn (\n\t\t<div data-testid={url} className=\"prose dark:prose-invert mt-2\">\n\t\t\t<img\n\t\t\t\tdata-testid={`image-${url}`}\n\t\t\t\tsrc={url}\n\t\t\t\talt=\"artifact-image\"\n\t\t\t\tclassName=\"w-full\"\n\t\t\t/>\n\n\t\t\t<p className=\"text-lg\">\n\t\t\t\tImage URL:{\" \"}\n\t\t\t\t<a\n\t\t\t\t\tclassName=\"text-link hover:text-link-hover hover:underline\"\n\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\thref={url}\n\t\t\t\t\trel=\"noreferrer\"\n\t\t\t\t>\n\t\t\t\t\t{url}\n\t\t\t\t</a>\n\t\t\t</p>\n\t\t</div>\n\t);\n};\n","import { LazyMarkdown } from \"@/components/ui/lazy-markdown\";\n\nexport type DetailMarkdownProps = {\n\tmarkdown: string;\n};\n\nexport const DetailMarkdown = ({ markdown }: DetailMarkdownProps) => {\n\treturn (\n\t\t<div\n\t\t\tdata-testid=\"markdown-display\"\n\t\t\tclassName=\"mt-4 prose dark:prose-invert\"\n\t\t>\n\t\t\t<LazyMarkdown>{markdown}</LazyMarkdown>\n\t\t</div>\n\t);\n};\n","export type DetailProgressProps = {\n\tprogress: number;\n};\n\nexport const DetailProgress = ({ progress }: DetailProgressProps) => {\n\treturn (\n\t\t<p data-testid=\"progress-display\" className=\"text-lg\">\n\t\t\tProgress: {progress}%\n\t\t</p>\n\t);\n};\n","import {\n\tcreateColumnHelper,\n\tgetCoreRowModel,\n\tgetPaginationRowModel,\n\tuseReactTable,\n} from \"@tanstack/react-table\";\nimport { useMemo, useState } from \"react\";\nimport { DataTable } from \"@/components/ui/data-table\";\nimport { SearchInput } from \"@/components/ui/input\";\n\nexport type DetailTableProps = {\n\ttableData: string;\n};\n\nconst columnHelper = createColumnHelper<Record<string, string>>();\n\nexport const DetailTable = ({ tableData }: DetailTableProps) => {\n\tconst rows = useMemo(\n\t\t() => JSON.parse(tableData) as Record<string, string>[],\n\t\t[tableData],\n\t);\n\tconst headers = useMemo(() => Object.keys(rows[0] ?? {}), [rows]);\n\tconst [input, setInput] = useState<string>(\"\");\n\n\tconst columns = useMemo(\n\t\t() =>\n\t\t\theaders.map((header) =>\n\t\t\t\tcolumnHelper.display({\n\t\t\t\t\tid: header,\n\t\t\t\t\theader: () => header,\n\t\t\t\t\tcell: ({ row }) => {\n\t\t\t\t\t\tconst value = String(row.original[header] ?? \"\");\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<span className=\"truncate block\" title={value}>\n\t\t\t\t\t\t\t\t{value}\n\t\t\t\t\t\t\t</span>\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[headers],\n\t);\n\n\tconst filteredRows = useMemo(() => {\n\t\tif (!input) return rows;\n\t\treturn rows.filter((row) =>\n\t\t\tObject.values(row).some((value) =>\n\t\t\t\tString(value).toLowerCase().includes(input.toLowerCase()),\n\t\t\t),\n\t\t);\n\t}, [input, rows]);\n\n\tconst table = useReactTable({\n\t\tdata: filteredRows,\n\t\tcolumns,\n\t\tgetCoreRowModel: getCoreRowModel(),\n\t\tgetPaginationRowModel: getPaginationRowModel(),\n\t\tinitialState: { pagination: { pageIndex: 0, pageSize: 10 } },\n\t});\n\n\treturn (\n\t\t<div data-testid=\"table-display\" className=\"mt-4\">\n\t\t\t<div className=\"flex flex-row justify-end items-center mb-2\">\n\t\t\t\t<SearchInput\n\t\t\t\t\tplaceholder=\"Search\"\n\t\t\t\t\tvalue={input}\n\t\t\t\t\tonChange={(e) => setInput(e.target.value)}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t\t<DataTable table={table} />\n\t\t</div>\n\t);\n};\n","import { useMemo } from \"react\";\nimport type { ArtifactWithFlowRunAndTaskRun } from \"@/api/artifacts\";\nimport { KeyValue } from \"@/components/ui/key-value\";\nimport { formatDate } from \"@/utils/date\";\n\ntype ArtifactSectionProps = {\n\tartifact: ArtifactWithFlowRunAndTaskRun;\n};\n\nexport const ArtifactSection = ({ artifact }: ArtifactSectionProps) => {\n\tconst createdDate = useMemo(() => {\n\t\tif (!artifact.created) return null;\n\t\treturn formatDate(artifact.created, \"dateTime\");\n\t}, [artifact.created]);\n\n\treturn (\n\t\t<div className=\"mt-4\">\n\t\t\t<p className=\"text-base font-semibold\">Artifact</p>\n\n\t\t\t<div className=\"mt-3 flex flex-col gap-3\">\n\t\t\t\t<KeyValue\n\t\t\t\t\tlabel=\"Key\"\n\t\t\t\t\tvalue={<span className=\"font-mono\">{artifact.key ?? \"None\"}</span>}\n\t\t\t\t/>\n\n\t\t\t\t<KeyValue\n\t\t\t\t\tlabel=\"Type\"\n\t\t\t\t\tvalue={<span className=\"font-mono\">{artifact.type ?? \"None\"}</span>}\n\t\t\t\t/>\n\n\t\t\t\t<KeyValue\n\t\t\t\t\tlabel=\"Created\"\n\t\t\t\t\tvalue={<span>{createdDate ?? \"None\"}</span>}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t</div>\n\t);\n};\n","import humanizeDuration from \"humanize-duration\";\nimport { useMemo } from \"react\";\nimport type { FlowRun } from \"@/api/flow-runs\";\nimport { Icon } from \"@/components/ui/icons\";\nimport { KeyValue } from \"@/components/ui/key-value\";\nimport { TagBadge } from \"@/components/ui/tag-badge\";\nimport { formatDate } from \"@/utils/date\";\n\ntype FlowRunSectionProps = {\n\tflowRun: FlowRun;\n};\n\nexport const FlowRunSection = ({ flowRun }: FlowRunSectionProps) => {\n\tconst startTime = useMemo(() => {\n\t\tif (!flowRun.start_time) return null;\n\t\treturn formatDate(flowRun.start_time, \"dateTime\");\n\t}, [flowRun.start_time]);\n\n\tconst duration = useMemo(() => {\n\t\tif (!flowRun.estimated_run_time) return null;\n\t\treturn humanizeDuration(Math.ceil(flowRun.estimated_run_time) * 1000);\n\t}, [flowRun.estimated_run_time]);\n\n\tconst createdDate = useMemo(() => {\n\t\tif (!flowRun.created) return null;\n\t\treturn formatDate(flowRun.created, \"dateTime\");\n\t}, [flowRun.created]);\n\n\tconst updatedDate = useMemo(() => {\n\t\tif (!flowRun.updated) return null;\n\t\treturn formatDate(flowRun.updated, \"dateTime\");\n\t}, [flowRun.updated]);\n\n\treturn (\n\t\t<div className=\"mt-4\">\n\t\t\t<p className=\"text-lg font-bold\">Flow Run</p>\n\n\t\t\t<div className=\"mt-3 flex flex-col gap-3\">\n\t\t\t\t<KeyValue\n\t\t\t\t\tlabel=\"Start time\"\n\t\t\t\t\tvalue={\n\t\t\t\t\t\t<span className=\"font-mono flex items-center\">\n\t\t\t\t\t\t\t<Icon id=\"Calendar\" className=\"inline w-4 mr-2\" />\n\t\t\t\t\t\t\t{startTime ?? \"None\"}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t}\n\t\t\t\t/>\n\n\t\t\t\t<KeyValue\n\t\t\t\t\tlabel=\"Duration\"\n\t\t\t\t\tvalue={\n\t\t\t\t\t\t<span className=\"font-mono flex items-center\">\n\t\t\t\t\t\t\t<Icon id=\"Clock\" className=\"inline w-4 mr-2\" />\n\t\t\t\t\t\t\t{duration ?? \"None\"}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t}\n\t\t\t\t/>\n\n\t\t\t\t<KeyValue\n\t\t\t\t\tlabel=\"Created\"\n\t\t\t\t\tvalue={<span className=\"font-mono\">{createdDate ?? \"None\"}</span>}\n\t\t\t\t/>\n\n\t\t\t\t<KeyValue\n\t\t\t\t\tlabel=\"Last Updated\"\n\t\t\t\t\tvalue={<span className=\"font-mono\">{updatedDate ?? \"None\"}</span>}\n\t\t\t\t/>\n\n\t\t\t\t<KeyValue\n\t\t\t\t\tlabel=\"Tags\"\n\t\t\t\t\tvalue={\n\t\t\t\t\t\tflowRun.tags && flowRun.tags.length > 0 ? (\n\t\t\t\t\t\t\t<div className=\"flex flex-wrap\">\n\t\t\t\t\t\t\t\t{flowRun.tags.map((tag) => (\n\t\t\t\t\t\t\t\t\t<TagBadge key={tag} tag={tag} />\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<span className=\"font-mono\">None</span>\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t/>\n\n\t\t\t\t<KeyValue\n\t\t\t\t\tlabel=\"State Message\"\n\t\t\t\t\tvalue={\n\t\t\t\t\t\t<span className=\"font-mono\">\n\t\t\t\t\t\t\t{flowRun.state?.message ?? \"None\"}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t</div>\n\t);\n};\n","import { Link } from \"@tanstack/react-router\";\nimport type { ArtifactWithFlowRunAndTaskRun } from \"@/api/artifacts\";\nimport { KeyValue } from \"@/components/ui/key-value\";\n\ntype LinksSectionProps = {\n\tartifact: ArtifactWithFlowRunAndTaskRun;\n};\n\nexport const LinksSection = ({ artifact }: LinksSectionProps) => {\n\tconst { flow_run, task_run } = artifact;\n\tconst hasLinks = artifact.key || flow_run || task_run;\n\n\tif (!hasLinks) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<div className=\"flex flex-col gap-2\">\n\t\t\t{artifact.key && (\n\t\t\t\t<KeyValue\n\t\t\t\t\tlabel=\"Artifact\"\n\t\t\t\t\tvalue={\n\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\tto=\"/artifacts/key/$key\"\n\t\t\t\t\t\t\tparams={{ key: artifact.key }}\n\t\t\t\t\t\t\tclassName=\"text-link hover:text-link-hover hover:underline\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{artifact.key}\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t{flow_run && (\n\t\t\t\t<KeyValue\n\t\t\t\t\tlabel=\"Flow Run\"\n\t\t\t\t\tvalue={\n\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\tto=\"/runs/flow-run/$id\"\n\t\t\t\t\t\t\tparams={{ id: flow_run.id }}\n\t\t\t\t\t\t\tclassName=\"text-link hover:text-link-hover hover:underline\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{flow_run.name}\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t{task_run && (\n\t\t\t\t<KeyValue\n\t\t\t\t\tlabel=\"Task Run\"\n\t\t\t\t\tvalue={\n\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\tto=\"/runs/task-run/$id\"\n\t\t\t\t\t\t\tparams={{ id: task_run.id }}\n\t\t\t\t\t\t\tclassName=\"text-link hover:text-link-hover hover:underline\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{task_run.name}\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t<hr className=\"mt-2 border-border\" />\n\t\t</div>\n\t);\n};\n","import { useMemo } from \"react\";\nimport type { TaskRun } from \"@/api/task-runs\";\nimport { KeyValue } from \"@/components/ui/key-value\";\nimport { TagBadge } from \"@/components/ui/tag-badge\";\nimport { formatDate } from \"@/utils/date\";\n\ntype TaskRunSectionProps = {\n\ttaskRun: TaskRun;\n};\n\nexport const TaskRunSection = ({ taskRun }: TaskRunSectionProps) => {\n\tconst createdDate = useMemo(() => {\n\t\tif (!taskRun.created) return null;\n\t\treturn formatDate(taskRun.created, \"dateTime\");\n\t}, [taskRun.created]);\n\n\tconst updatedDate = useMemo(() => {\n\t\tif (!taskRun.updated) return null;\n\t\treturn formatDate(taskRun.updated, \"dateTime\");\n\t}, [taskRun.updated]);\n\n\treturn (\n\t\t<div className=\"mt-4\">\n\t\t\t<p className=\"text-lg font-bold\">Task Run</p>\n\n\t\t\t<div className=\"mt-3 flex flex-col gap-3\">\n\t\t\t\t<KeyValue\n\t\t\t\t\tlabel=\"Created\"\n\t\t\t\t\tvalue={<span className=\"font-mono\">{createdDate ?? \"None\"}</span>}\n\t\t\t\t/>\n\n\t\t\t\t<KeyValue\n\t\t\t\t\tlabel=\"Last Updated\"\n\t\t\t\t\tvalue={<span className=\"font-mono\">{updatedDate ?? \"None\"}</span>}\n\t\t\t\t/>\n\n\t\t\t\t<KeyValue\n\t\t\t\t\tlabel=\"Tags\"\n\t\t\t\t\tvalue={\n\t\t\t\t\t\ttaskRun.tags && taskRun.tags.length > 0 ? (\n\t\t\t\t\t\t\t<div className=\"flex flex-wrap\">\n\t\t\t\t\t\t\t\t{taskRun.tags.map((tag) => (\n\t\t\t\t\t\t\t\t\t<TagBadge key={tag} tag={tag} />\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<span className=\"font-mono\">None</span>\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t</div>\n\t);\n};\n","import type { ArtifactWithFlowRunAndTaskRun } from \"@/api/artifacts\";\nimport { ArtifactSection } from \"./artifact-section\";\nimport { FlowRunSection } from \"./flow-run-section\";\nimport { LinksSection } from \"./links-section\";\nimport { TaskRunSection } from \"./task-run-section\";\n\nexport type MetadataSidebarProps = {\n\tartifact: ArtifactWithFlowRunAndTaskRun;\n};\n\nexport const MetadataSidebar = ({ artifact }: MetadataSidebarProps) => {\n\tconst { flow_run, task_run } = artifact;\n\n\treturn (\n\t\t<div className=\"flex flex-col gap-4 pt-4\">\n\t\t\t<LinksSection artifact={artifact} />\n\n\t\t\t<ArtifactSection artifact={artifact} />\n\n\t\t\t{(flow_run || task_run) && <hr className=\"mt-4 border-border\" />}\n\n\t\t\t{flow_run && <FlowRunSection flowRun={flow_run} />}\n\n\t\t\t{flow_run && task_run && <hr className=\"mt-4 border-border\" />}\n\n\t\t\t{task_run && <TaskRunSection taskRun={task_run} />}\n\t\t</div>\n\t);\n};\n","import { useMemo } from \"react\";\nimport type { ArtifactWithFlowRunAndTaskRun } from \"@/api/artifacts\";\nimport { LayoutWellSidebar } from \"@/components/ui/layout-well\";\nimport { ArtifactDetailHeader } from \"./artifact-detail-header\";\nimport { ArtifactDetailTabs } from \"./artifact-detail-tabs\";\nimport { DetailImage } from \"./detail-image\";\nimport { DetailMarkdown } from \"./detail-markdown\";\nimport { DetailProgress } from \"./detail-progress\";\nimport { DetailTable } from \"./detail-table\";\nimport { MetadataSidebar } from \"./metadata-sidebar\";\n\nexport type ArtifactDetailPageProps = {\n\tartifact: ArtifactWithFlowRunAndTaskRun;\n};\n\nexport const ArtifactDetailPage = ({ artifact }: ArtifactDetailPageProps) => {\n\tconst artifactContent = useMemo(() => {\n\t\tswitch (artifact.type) {\n\t\t\tcase \"markdown\":\n\t\t\tcase \"link\":\n\t\t\t\treturn <DetailMarkdown markdown={artifact.data as string} />;\n\t\t\tcase \"image\":\n\t\t\t\treturn <DetailImage url={artifact.data as string} />;\n\t\t\tcase \"progress\":\n\t\t\t\treturn <DetailProgress progress={artifact.data as number} />;\n\t\t\tcase \"table\":\n\t\t\t\treturn <DetailTable tableData={artifact.data as string} />;\n\t\t\tdefault:\n\t\t\t\treturn <pre>{JSON.stringify(artifact.data, null, 2)}</pre>;\n\t\t}\n\t}, [artifact]);\n\n\tconst sidebarContent = <MetadataSidebar artifact={artifact} />;\n\n\treturn (\n\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t<ArtifactDetailHeader artifact={artifact} />\n\t\t\t<div className=\"flex flex-col lg:flex-row lg:gap-6\">\n\t\t\t\t<div className=\"flex-1 min-w-0\">\n\t\t\t\t\t<ArtifactDetailTabs\n\t\t\t\t\t\tartifact={artifact}\n\t\t\t\t\t\tartifactContent={artifactContent}\n\t\t\t\t\t\tdetailsContent={sidebarContent}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t\t<LayoutWellSidebar>{sidebarContent}</LayoutWellSidebar>\n\t\t\t</div>\n\t\t</div>\n\t);\n};\n","import { useSuspenseQuery } from \"@tanstack/react-query\";\nimport type { ErrorComponentProps } from \"@tanstack/react-router\";\nimport { createFileRoute } from \"@tanstack/react-router\";\nimport { zodValidator } from \"@tanstack/zod-adapter\";\nimport { z } from \"zod\";\nimport { buildGetArtifactQuery } from \"@/api/artifacts\";\nimport { useGetArtifactFlowTaskRuns } from \"@/api/artifacts/use-get-artifacts-flow-task-runs/use-get-artifacts-flow-task-runs\";\nimport { categorizeError } from \"@/api/error-utils\";\nimport { ArtifactDetailPage } from \"@/components/artifacts/artifact/artifact-detail-page\";\nimport { RouteErrorState } from \"@/components/ui/route-error-state\";\n\n/**\n * Schema for validating URL search parameters for the Artifact Detail page\n * @property {\"Artifact\" | \"Details\" | \"Raw\"} tab used to designate which tab view to display\n */\nconst searchParams = z.object({\n\ttab: z.enum([\"Artifact\", \"Details\", \"Raw\"]).default(\"Artifact\"),\n});\n\nexport type ArtifactDetailTabOptions = z.infer<typeof searchParams>[\"tab\"];\n\nexport const Route = createFileRoute(\"/artifacts/artifact/$id\")({\n\tvalidateSearch: zodValidator(searchParams),\n\tcomponent: function RouteComponent() {\n\t\tconst { id } = Route.useParams();\n\n\t\tconst { data: artifact } = useSuspenseQuery(buildGetArtifactQuery(id));\n\n\t\tconst artifactWithMetadata = useGetArtifactFlowTaskRuns(id);\n\n\t\treturn <ArtifactDetailPage artifact={artifactWithMetadata ?? artifact} />;\n\t},\n\tloader: async ({ context, params }) => {\n\t\tconst { id } = params;\n\n\t\tconst artifact = await context.queryClient.ensureQueryData(\n\t\t\tbuildGetArtifactQuery(id),\n\t\t);\n\n\t\treturn { artifact };\n\t},\n\terrorComponent: function ArtifactDetailErrorComponent({\n\t\terror,\n\t\treset,\n\t}: ErrorComponentProps) {\n\t\tconst serverError = categorizeError(error, \"Failed to load artifact\");\n\t\tif (\n\t\t\tserverError.type !== \"server-error\" &&\n\t\t\tserverError.type !== \"client-error\"\n\t\t) {\n\t\t\tthrow error;\n\t\t}\n\t\treturn (\n\t\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t\t<div>\n\t\t\t\t\t<h1 className=\"text-2xl font-semibold\">Artifact</h1>\n\t\t\t\t</div>\n\t\t\t\t<RouteErrorState error={serverError} onRetry={reset} />\n\t\t\t</div>\n\t\t);\n\t},\n});\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime-QTnfLwEv.js";import{o as t,s as n}from"./vendor-codemirror-B3tGe8Gh.js";import{k as r}from"./vendor-tanstack-4U0A7zMo.js";import{g as i,o as a}from"./button-B1qHyd9c.js";import{i as o,n as s,o as c,s as l,t as u}from"./select-CPCe8juw.js";import{n as d}from"./input-B5J9cihQ.js";import{
|
|
2
|
-
//# sourceMappingURL=artifacts-
|
|
1
|
+
import{r as e}from"./rolldown-runtime-QTnfLwEv.js";import{o as t,s as n}from"./vendor-codemirror-B3tGe8Gh.js";import{k as r}from"./vendor-tanstack-4U0A7zMo.js";import{g as i,o as a}from"./button-B1qHyd9c.js";import{i as o,n as s,o as c,s as l,t as u}from"./select-CPCe8juw.js";import{n as d}from"./input-B5J9cihQ.js";import{$n as f,Er as p,G as m,Jr as h,Or as g,Tr as _,W as v,Y as y,Z as b,er as x,ir as S,nr as C,rr as w,tr as T}from"./index--DOPlnGf.js";import{t as E}from"./use-debounce-callback-D-Cp7o1a.js";import{n as D,r as O,t as k}from"./toggle-group-DGZ0dcl7.js";var A=e(n(),1),j=t(),M=[{value:`all`,label:`All Types`},{value:`markdown`,label:`Markdown`},{value:`progress`,label:`Progress`},{value:`image`,label:`Image`},{value:`table`,label:`Table`}],N=({filters:e,onFilterChange:t,totalCount:n,displayMode:r,setDisplayMode:f})=>{let p=(0,A.useCallback)(n=>{t([...e.filter(e=>e.id!==`name`),{id:`name`,label:`Name`,value:n}])},[e,t]),m=(0,A.useCallback)(n=>{t([...e.filter(e=>e.id!==`type`),{id:`type`,label:`Type`,value:n}])},[e,t]),h=(0,A.useMemo)(()=>e.find(e=>e.id===`type`)?.value,[e]),g=(0,A.useMemo)(()=>e.find(e=>e.id===`name`)?.value,[e]);return(0,j.jsxs)(`div`,{"data-testid":`artifact-filter`,className:`flex justify-between items-center`,children:[(0,j.jsx)(`div`,{children:(0,j.jsxs)(`p`,{className:`text-base text-sm text-muted-foreground`,children:[n.toLocaleString(),` `,a(n,`artifact`)]})}),(0,j.jsxs)(`div`,{className:`flex gap-4`,children:[(0,j.jsx)(d,{"data-testid":`search-input`,defaultValue:g,placeholder:`Search artifacts`,onChange:e=>p(e.target.value)}),(0,j.jsxs)(`div`,{className:`flex gap-4`,children:[(0,j.jsxs)(u,{"data-testid":`type-select`,value:h,onValueChange:m,children:[(0,j.jsx)(c,{"aria-label":`Artifact type`,children:(0,j.jsx)(l,{placeholder:`Type`})}),(0,j.jsx)(s,{children:M.map(({value:e,label:t})=>(0,j.jsx)(o,{value:e,children:t},e))})]}),(0,j.jsx)(`div`,{children:(0,j.jsxs)(k,{type:`single`,defaultValue:r,onValueChange:e=>f(e),children:[(0,j.jsx)(D,{"data-testid":`grid-layout`,value:`grid`,children:(0,j.jsx)(i,{id:`LayoutGrid`})}),(0,j.jsx)(D,{"data-testid":`list-layout`,value:`list`,children:(0,j.jsx)(i,{id:`AlignJustify`})})]})})]})]})]})},P=()=>(0,j.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,j.jsx)(`div`,{className:`flex items-center gap-2`,children:(0,j.jsx)(_,{children:(0,j.jsx)(g,{children:(0,j.jsx)(p,{className:`text-xl font-semibold`,children:`Artifacts`})})})}),(0,j.jsx)(S,{id:`artifacts-guide`,label:`Documentation`})]}),F=()=>(0,j.jsxs)(f,{children:[(0,j.jsx)(`div`,{className:`flex items-center gap-3`,children:(0,j.jsx)(C,{id:`Image`})}),(0,j.jsx)(w,{children:`Create an artifact to get started`}),(0,j.jsx)(T,{children:`Artifacts are byproducts of your runs; they can be anything from a markdown string to a table.`}),(0,j.jsx)(x,{children:(0,j.jsx)(S,{id:`artifacts-guide`})})]}),I=({filters:e,onFilterChange:t,artifactsList:n,artifactsCount:r})=>{let[i,a]=h(`artifacts-grid-style`,`grid`),o=(0,A.useMemo)(()=>i===`grid`?`grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-4`:`grid-cols-1`,[i]);return(0,j.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,j.jsx)(P,{}),(0,j.jsx)(N,{filters:e,onFilterChange:t,totalCount:r,setDisplayMode:a,displayMode:i}),n.length===0?(0,j.jsx)(F,{}):(0,j.jsx)(`div`,{className:o,children:n.map(e=>(0,j.jsx)(O,{artifact:e},e.id))})]})},L=()=>{let e=v.useSearch(),t=v.useNavigate();return{filters:(0,A.useMemo)(()=>[{id:`type`,label:`Type`,value:e.type??`all`},{id:`name`,label:`Name`,value:e.name}],[e.type,e.name]),onFilterChange:E((0,A.useCallback)(e=>{e&&t({to:`.`,search:()=>e.filter(e=>e.value).reduce((e,t)=>(t.value&&(e[t.id]=t.value),e),{}),replace:!0})},[t]),400)}},R=function(){let e=v.useSearch(),{filters:t,onFilterChange:n}=L(),[{data:i},{data:a}]=r({queries:[m(b(e)),y(b(e))]});return(0,j.jsx)(I,{filters:t,onFilterChange:n,artifactsCount:i,artifactsList:a})};export{R as component};
|
|
2
|
+
//# sourceMappingURL=artifacts-DwYa9F9j.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"artifacts-BdknReie.js","names":["useSuspenseQueries","useCallback","useMemo","buildCountLatestArtifactsQuery","buildListLatestArtifactsQuery","ArtifactsPage","useDebounceCallback","Route","useFilter","search","useSearch","navigate","useNavigate","filters","id","label","value","type","name","onFilterChange","newFilters","filterType","to","filter","reduce","prev","curr","Record","replace","SplitComponent","RouteComponent","data","artifactsCount","artifactsList","queries","buildFilterBody","component"],"sources":["../../src/components/artifacts/artifacts-filter.tsx","../../src/components/artifacts/artifacts-header.tsx","../../src/components/artifacts/empty-state.tsx","../../src/components/artifacts/artifacts-page.tsx","../../src/routes/artifacts/index.tsx?tsr-split=component"],"sourcesContent":["import { useCallback, useMemo } from \"react\";\nimport { SearchInput } from \"@/components/ui/input\";\nimport {\n\tSelect,\n\tSelectContent,\n\tSelectItem,\n\tSelectTrigger,\n\tSelectValue,\n} from \"@/components/ui/select\";\nimport { pluralize } from \"@/utils\";\nimport { Icon } from \"../ui/icons\";\nimport { ToggleGroup, ToggleGroupItem } from \"../ui/toggle-group\";\nimport type { filterType } from \"./types\";\n\ntype ArtifactsFilterProps = {\n\tfilters: filterType[];\n\tonFilterChange: (newFilters: filterType[]) => void;\n\ttotalCount: number;\n\tsetDisplayMode: (mode: string) => void;\n\tdisplayMode: string;\n};\n\nconst artifactTypeOptions = [\n\t{ value: \"all\", label: \"All Types\" },\n\t{ value: \"markdown\", label: \"Markdown\" },\n\t{ value: \"progress\", label: \"Progress\" },\n\t{ value: \"image\", label: \"Image\" },\n\t{ value: \"table\", label: \"Table\" },\n] as const;\n\nexport const ArtifactsFilterComponent = ({\n\tfilters,\n\tonFilterChange,\n\ttotalCount,\n\tdisplayMode,\n\tsetDisplayMode,\n}: ArtifactsFilterProps) => {\n\tconst changeArtifactName = useCallback(\n\t\t(value: string) => {\n\t\t\tonFilterChange([\n\t\t\t\t...filters.filter((filter) => filter.id !== \"name\"),\n\t\t\t\t{ id: \"name\", label: \"Name\", value },\n\t\t\t]);\n\t\t},\n\t\t[filters, onFilterChange],\n\t);\n\n\tconst changeArtifactType = useCallback(\n\t\t(value: string) => {\n\t\t\tonFilterChange([\n\t\t\t\t...filters.filter((filter) => filter.id !== \"type\"),\n\t\t\t\t{ id: \"type\", label: \"Type\", value },\n\t\t\t]);\n\t\t},\n\t\t[filters, onFilterChange],\n\t);\n\n\tconst typeValue = useMemo(\n\t\t() => filters.find((val) => val.id === \"type\")?.value,\n\t\t[filters],\n\t);\n\n\tconst nameValue = useMemo(\n\t\t() => filters.find((val) => val.id === \"name\")?.value,\n\t\t[filters],\n\t);\n\treturn (\n\t\t<div\n\t\t\tdata-testid=\"artifact-filter\"\n\t\t\tclassName=\"flex justify-between items-center\"\n\t\t>\n\t\t\t<div>\n\t\t\t\t<p className=\"text-base text-sm text-muted-foreground\">\n\t\t\t\t\t{totalCount.toLocaleString()} {pluralize(totalCount, \"artifact\")}\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t\t<div className=\"flex gap-4\">\n\t\t\t\t<SearchInput\n\t\t\t\t\tdata-testid=\"search-input\"\n\t\t\t\t\tdefaultValue={nameValue}\n\t\t\t\t\tplaceholder=\"Search artifacts\"\n\t\t\t\t\tonChange={(e) => changeArtifactName(e.target.value)}\n\t\t\t\t/>\n\n\t\t\t\t<div className=\"flex gap-4\">\n\t\t\t\t\t<Select\n\t\t\t\t\t\tdata-testid=\"type-select\"\n\t\t\t\t\t\tvalue={typeValue}\n\t\t\t\t\t\tonValueChange={changeArtifactType}\n\t\t\t\t\t>\n\t\t\t\t\t\t<SelectTrigger aria-label=\"Artifact type\">\n\t\t\t\t\t\t\t<SelectValue placeholder=\"Type\" />\n\t\t\t\t\t\t</SelectTrigger>\n\t\t\t\t\t\t<SelectContent>\n\t\t\t\t\t\t\t{artifactTypeOptions.map(({ value, label }) => (\n\t\t\t\t\t\t\t\t<SelectItem key={value} value={value}>\n\t\t\t\t\t\t\t\t\t{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\t<div>\n\t\t\t\t\t\t<ToggleGroup\n\t\t\t\t\t\t\ttype=\"single\"\n\t\t\t\t\t\t\tdefaultValue={displayMode}\n\t\t\t\t\t\t\tonValueChange={(value: string) => setDisplayMode(value)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<ToggleGroupItem data-testid=\"grid-layout\" value=\"grid\">\n\t\t\t\t\t\t\t\t<Icon id=\"LayoutGrid\" />\n\t\t\t\t\t\t\t</ToggleGroupItem>\n\t\t\t\t\t\t\t<ToggleGroupItem data-testid=\"list-layout\" value=\"list\">\n\t\t\t\t\t\t\t\t<Icon id=\"AlignJustify\" />\n\t\t\t\t\t\t\t</ToggleGroupItem>\n\t\t\t\t\t\t</ToggleGroup>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n};\n","import {\n\tBreadcrumb,\n\tBreadcrumbItem,\n\tBreadcrumbList,\n} from \"@/components/ui/breadcrumb\";\nimport { DocsLink } from \"@/components/ui/docs-link\";\n\nexport const ArtifactsHeader = () => {\n\treturn (\n\t\t<div className=\"flex items-center justify-between\">\n\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t<Breadcrumb>\n\t\t\t\t\t<BreadcrumbList>\n\t\t\t\t\t\t<BreadcrumbItem className=\"text-xl font-semibold\">\n\t\t\t\t\t\t\tArtifacts\n\t\t\t\t\t\t</BreadcrumbItem>\n\t\t\t\t\t</BreadcrumbList>\n\t\t\t\t</Breadcrumb>\n\t\t\t</div>\n\t\t\t<DocsLink id=\"artifacts-guide\" label=\"Documentation\" />\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 ArtifactsEmptyState = () => (\n\t<EmptyState>\n\t\t<div className=\"flex items-center gap-3\">\n\t\t\t<EmptyStateIcon id=\"Image\" />\n\t\t</div>\n\t\t<EmptyStateTitle>Create an artifact to get started</EmptyStateTitle>\n\t\t<EmptyStateDescription>\n\t\t\tArtifacts are byproducts of your runs; they can be anything from a\n\t\t\tmarkdown string to a table.\n\t\t</EmptyStateDescription>\n\t\t<EmptyStateActions>\n\t\t\t<DocsLink id=\"artifacts-guide\" />\n\t\t</EmptyStateActions>\n\t</EmptyState>\n);\n","import { useMemo } from \"react\";\nimport type { ArtifactCollection } from \"@/api/artifacts\";\nimport { useLocalStorage } from \"@/hooks/use-local-storage\";\nimport { ArtifactCard } from \"./artifact-card\";\nimport { ArtifactsFilterComponent } from \"./artifacts-filter\";\nimport { ArtifactsHeader } from \"./artifacts-header\";\nimport { ArtifactsEmptyState } from \"./empty-state\";\nimport type { filterType } from \"./types\";\n\nexport type ArtifactsPageProps = {\n\tfilters: filterType[];\n\tonFilterChange: (newFilters: filterType[]) => void;\n\tartifactsCount: number;\n\tartifactsList: ArtifactCollection[];\n};\n\nexport const ArtifactsPage = ({\n\tfilters,\n\tonFilterChange,\n\tartifactsList,\n\tartifactsCount,\n}: ArtifactsPageProps) => {\n\tconst [displayMode, setDisplayMode] = useLocalStorage<string>(\n\t\t\"artifacts-grid-style\",\n\t\t\"grid\",\n\t);\n\n\tconst gridClass = useMemo(() => {\n\t\treturn displayMode === \"grid\"\n\t\t\t? \"grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-4\"\n\t\t\t: \"grid-cols-1\";\n\t}, [displayMode]);\n\n\treturn (\n\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t<ArtifactsHeader />\n\t\t\t<ArtifactsFilterComponent\n\t\t\t\tfilters={filters}\n\t\t\t\tonFilterChange={onFilterChange}\n\t\t\t\ttotalCount={artifactsCount}\n\t\t\t\tsetDisplayMode={setDisplayMode}\n\t\t\t\tdisplayMode={displayMode}\n\t\t\t/>\n\n\t\t\t{artifactsList.length === 0 ? (\n\t\t\t\t<ArtifactsEmptyState />\n\t\t\t) : (\n\t\t\t\t<div className={gridClass}>\n\t\t\t\t\t{artifactsList.map((artifact) => (\n\t\t\t\t\t\t<ArtifactCard key={artifact.id} artifact={artifact} />\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n};\n","import { useSuspenseQueries } from \"@tanstack/react-query\";\nimport type { ErrorComponentProps } from \"@tanstack/react-router\";\nimport { createFileRoute } from \"@tanstack/react-router\";\nimport { zodValidator } from \"@tanstack/zod-adapter\";\nimport { useCallback, useMemo } from \"react\";\nimport { z } from \"zod\";\nimport {\n\ttype ArtifactCollectionsFilter,\n\tbuildCountLatestArtifactsQuery,\n\tbuildListLatestArtifactsQuery,\n} from \"@/api/artifacts\";\nimport { categorizeError } from \"@/api/error-utils\";\nimport { ArtifactsPage } from \"@/components/artifacts/artifacts-page\";\nimport type { filterType } from \"@/components/artifacts/types\";\nimport { PrefectLoading } from \"@/components/ui/loading\";\nimport { RouteErrorState } from \"@/components/ui/route-error-state\";\nimport useDebounceCallback from \"@/hooks/use-debounce-callback\";\n\n/**\n * Schema for validating URL search parameters for the artifacts 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\ttype: z.string().optional().catch(\"\"),\n\tname: z.string().optional().catch(\"\"),\n});\n\n/**\n * Builds filter parameters for artifacts query from search params\n *\n * @param search - Optional validated search parameters containing page and limit\n * @returns ArtifactsFilter with type and name\n *\n * @example\n * ```ts\n * const filter = buildFilterBody({ type: \"markdown\", name: \"my-dataset\" })\n * // Returns {\n * //\t\tartifacts: {\n * //\t\t\toperator: \"and_\",\n * //\t\t\ttype: { any_: [\"markdown\"] },\n * //\t\t\tkey: { exists_: true, like_: \"my-dataset\" }\n * //\t\t},\n * //\t\toffset: 0\n * //}\n * ```\n */\nconst buildFilterBody = (\n\tsearch?: z.infer<typeof searchParams>,\n): ArtifactCollectionsFilter => ({\n\tartifacts: {\n\t\toperator: \"and_\",\n\t\ttype: {\n\t\t\tany_: search?.type && search?.type !== \"all\" ? [search.type] : undefined,\n\t\t},\n\t\tkey: {\n\t\t\texists_: true,\n\t\t\tlike_: search?.name ?? \"\",\n\t\t},\n\t},\n\tsort: \"ID_DESC\",\n\toffset: 0,\n});\n\nexport const Route = createFileRoute(\"/artifacts/\")({\n\tvalidateSearch: zodValidator(searchParams),\n\tcomponent: function RouteComponent() {\n\t\tconst search = Route.useSearch();\n\t\tconst { filters, onFilterChange } = useFilter();\n\n\t\tconst [{ data: artifactsCount }, { data: artifactsList }] =\n\t\t\tuseSuspenseQueries({\n\t\t\t\tqueries: [\n\t\t\t\t\tbuildCountLatestArtifactsQuery(buildFilterBody(search)),\n\t\t\t\t\tbuildListLatestArtifactsQuery(buildFilterBody(search)),\n\t\t\t\t],\n\t\t\t});\n\n\t\treturn (\n\t\t\t<ArtifactsPage\n\t\t\t\tfilters={filters}\n\t\t\t\tonFilterChange={onFilterChange}\n\t\t\t\tartifactsCount={artifactsCount}\n\t\t\t\tartifactsList={artifactsList}\n\t\t\t/>\n\t\t);\n\t},\n\tloaderDeps: ({ search }) => buildFilterBody(search),\n\tloader: ({ deps, context }) => {\n\t\tvoid context.queryClient.prefetchQuery(\n\t\t\tbuildCountLatestArtifactsQuery(deps),\n\t\t);\n\t\tvoid context.queryClient.prefetchQuery(buildListLatestArtifactsQuery(deps));\n\t},\n\terrorComponent: function ArtifactsErrorComponent({\n\t\terror,\n\t\treset,\n\t}: ErrorComponentProps) {\n\t\tconst serverError = categorizeError(error, \"Failed to load artifacts\");\n\t\tif (\n\t\t\tserverError.type !== \"server-error\" &&\n\t\t\tserverError.type !== \"client-error\"\n\t\t) {\n\t\t\tthrow error;\n\t\t}\n\t\treturn (\n\t\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t\t<div>\n\t\t\t\t\t<h1 className=\"text-2xl font-semibold\">Artifacts</h1>\n\t\t\t\t</div>\n\t\t\t\t<RouteErrorState error={serverError} onRetry={reset} />\n\t\t\t</div>\n\t\t);\n\t},\n\twrapInSuspense: true,\n\tpendingComponent: PrefectLoading,\n});\n\nconst useFilter = () => {\n\tconst search = Route.useSearch();\n\tconst navigate = Route.useNavigate();\n\n\tconst filters = useMemo(\n\t\t() => [\n\t\t\t{ id: \"type\", label: \"Type\", value: search.type ?? \"all\" },\n\t\t\t{ id: \"name\", label: \"Name\", value: search.name },\n\t\t],\n\t\t[search.type, search.name],\n\t);\n\n\tconst onFilterChange = useDebounceCallback(\n\t\tuseCallback(\n\t\t\t(newFilters: filterType[]) => {\n\t\t\t\tif (!newFilters) return;\n\t\t\t\tvoid navigate({\n\t\t\t\t\tto: \".\",\n\t\t\t\t\tsearch: () =>\n\t\t\t\t\t\tnewFilters\n\t\t\t\t\t\t\t.filter((filter) => filter.value)\n\t\t\t\t\t\t\t.reduce(\n\t\t\t\t\t\t\t\t(prev, curr) => {\n\t\t\t\t\t\t\t\t\tif (!curr.value) return prev;\n\t\t\t\t\t\t\t\t\tprev[curr.id] = curr.value;\n\t\t\t\t\t\t\t\t\treturn prev;\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{} as Record<string, string>,\n\t\t\t\t\t\t\t),\n\t\t\t\t\treplace: true,\n\t\t\t\t});\n\t\t\t},\n\t\t\t[navigate],\n\t\t),\n\t\t400,\n\t);\n\n\treturn { filters, onFilterChange };\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"artifacts-DwYa9F9j.js","names":["useSuspenseQueries","useCallback","useMemo","buildCountLatestArtifactsQuery","buildListLatestArtifactsQuery","ArtifactsPage","useDebounceCallback","Route","useFilter","search","useSearch","navigate","useNavigate","filters","id","label","value","type","name","onFilterChange","newFilters","filterType","to","filter","reduce","prev","curr","Record","replace","SplitComponent","RouteComponent","data","artifactsCount","artifactsList","queries","buildFilterBody","component"],"sources":["../../src/components/artifacts/artifacts-filter.tsx","../../src/components/artifacts/artifacts-header.tsx","../../src/components/artifacts/empty-state.tsx","../../src/components/artifacts/artifacts-page.tsx","../../src/routes/artifacts/index.tsx?tsr-split=component"],"sourcesContent":["import { useCallback, useMemo } from \"react\";\nimport { SearchInput } from \"@/components/ui/input\";\nimport {\n\tSelect,\n\tSelectContent,\n\tSelectItem,\n\tSelectTrigger,\n\tSelectValue,\n} from \"@/components/ui/select\";\nimport { pluralize } from \"@/utils\";\nimport { Icon } from \"../ui/icons\";\nimport { ToggleGroup, ToggleGroupItem } from \"../ui/toggle-group\";\nimport type { filterType } from \"./types\";\n\ntype ArtifactsFilterProps = {\n\tfilters: filterType[];\n\tonFilterChange: (newFilters: filterType[]) => void;\n\ttotalCount: number;\n\tsetDisplayMode: (mode: string) => void;\n\tdisplayMode: string;\n};\n\nconst artifactTypeOptions = [\n\t{ value: \"all\", label: \"All Types\" },\n\t{ value: \"markdown\", label: \"Markdown\" },\n\t{ value: \"progress\", label: \"Progress\" },\n\t{ value: \"image\", label: \"Image\" },\n\t{ value: \"table\", label: \"Table\" },\n] as const;\n\nexport const ArtifactsFilterComponent = ({\n\tfilters,\n\tonFilterChange,\n\ttotalCount,\n\tdisplayMode,\n\tsetDisplayMode,\n}: ArtifactsFilterProps) => {\n\tconst changeArtifactName = useCallback(\n\t\t(value: string) => {\n\t\t\tonFilterChange([\n\t\t\t\t...filters.filter((filter) => filter.id !== \"name\"),\n\t\t\t\t{ id: \"name\", label: \"Name\", value },\n\t\t\t]);\n\t\t},\n\t\t[filters, onFilterChange],\n\t);\n\n\tconst changeArtifactType = useCallback(\n\t\t(value: string) => {\n\t\t\tonFilterChange([\n\t\t\t\t...filters.filter((filter) => filter.id !== \"type\"),\n\t\t\t\t{ id: \"type\", label: \"Type\", value },\n\t\t\t]);\n\t\t},\n\t\t[filters, onFilterChange],\n\t);\n\n\tconst typeValue = useMemo(\n\t\t() => filters.find((val) => val.id === \"type\")?.value,\n\t\t[filters],\n\t);\n\n\tconst nameValue = useMemo(\n\t\t() => filters.find((val) => val.id === \"name\")?.value,\n\t\t[filters],\n\t);\n\treturn (\n\t\t<div\n\t\t\tdata-testid=\"artifact-filter\"\n\t\t\tclassName=\"flex justify-between items-center\"\n\t\t>\n\t\t\t<div>\n\t\t\t\t<p className=\"text-base text-sm text-muted-foreground\">\n\t\t\t\t\t{totalCount.toLocaleString()} {pluralize(totalCount, \"artifact\")}\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t\t<div className=\"flex gap-4\">\n\t\t\t\t<SearchInput\n\t\t\t\t\tdata-testid=\"search-input\"\n\t\t\t\t\tdefaultValue={nameValue}\n\t\t\t\t\tplaceholder=\"Search artifacts\"\n\t\t\t\t\tonChange={(e) => changeArtifactName(e.target.value)}\n\t\t\t\t/>\n\n\t\t\t\t<div className=\"flex gap-4\">\n\t\t\t\t\t<Select\n\t\t\t\t\t\tdata-testid=\"type-select\"\n\t\t\t\t\t\tvalue={typeValue}\n\t\t\t\t\t\tonValueChange={changeArtifactType}\n\t\t\t\t\t>\n\t\t\t\t\t\t<SelectTrigger aria-label=\"Artifact type\">\n\t\t\t\t\t\t\t<SelectValue placeholder=\"Type\" />\n\t\t\t\t\t\t</SelectTrigger>\n\t\t\t\t\t\t<SelectContent>\n\t\t\t\t\t\t\t{artifactTypeOptions.map(({ value, label }) => (\n\t\t\t\t\t\t\t\t<SelectItem key={value} value={value}>\n\t\t\t\t\t\t\t\t\t{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\t<div>\n\t\t\t\t\t\t<ToggleGroup\n\t\t\t\t\t\t\ttype=\"single\"\n\t\t\t\t\t\t\tdefaultValue={displayMode}\n\t\t\t\t\t\t\tonValueChange={(value: string) => setDisplayMode(value)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<ToggleGroupItem data-testid=\"grid-layout\" value=\"grid\">\n\t\t\t\t\t\t\t\t<Icon id=\"LayoutGrid\" />\n\t\t\t\t\t\t\t</ToggleGroupItem>\n\t\t\t\t\t\t\t<ToggleGroupItem data-testid=\"list-layout\" value=\"list\">\n\t\t\t\t\t\t\t\t<Icon id=\"AlignJustify\" />\n\t\t\t\t\t\t\t</ToggleGroupItem>\n\t\t\t\t\t\t</ToggleGroup>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n};\n","import {\n\tBreadcrumb,\n\tBreadcrumbItem,\n\tBreadcrumbList,\n} from \"@/components/ui/breadcrumb\";\nimport { DocsLink } from \"@/components/ui/docs-link\";\n\nexport const ArtifactsHeader = () => {\n\treturn (\n\t\t<div className=\"flex items-center justify-between\">\n\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t<Breadcrumb>\n\t\t\t\t\t<BreadcrumbList>\n\t\t\t\t\t\t<BreadcrumbItem className=\"text-xl font-semibold\">\n\t\t\t\t\t\t\tArtifacts\n\t\t\t\t\t\t</BreadcrumbItem>\n\t\t\t\t\t</BreadcrumbList>\n\t\t\t\t</Breadcrumb>\n\t\t\t</div>\n\t\t\t<DocsLink id=\"artifacts-guide\" label=\"Documentation\" />\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 ArtifactsEmptyState = () => (\n\t<EmptyState>\n\t\t<div className=\"flex items-center gap-3\">\n\t\t\t<EmptyStateIcon id=\"Image\" />\n\t\t</div>\n\t\t<EmptyStateTitle>Create an artifact to get started</EmptyStateTitle>\n\t\t<EmptyStateDescription>\n\t\t\tArtifacts are byproducts of your runs; they can be anything from a\n\t\t\tmarkdown string to a table.\n\t\t</EmptyStateDescription>\n\t\t<EmptyStateActions>\n\t\t\t<DocsLink id=\"artifacts-guide\" />\n\t\t</EmptyStateActions>\n\t</EmptyState>\n);\n","import { useMemo } from \"react\";\nimport type { ArtifactCollection } from \"@/api/artifacts\";\nimport { useLocalStorage } from \"@/hooks/use-local-storage\";\nimport { ArtifactCard } from \"./artifact-card\";\nimport { ArtifactsFilterComponent } from \"./artifacts-filter\";\nimport { ArtifactsHeader } from \"./artifacts-header\";\nimport { ArtifactsEmptyState } from \"./empty-state\";\nimport type { filterType } from \"./types\";\n\nexport type ArtifactsPageProps = {\n\tfilters: filterType[];\n\tonFilterChange: (newFilters: filterType[]) => void;\n\tartifactsCount: number;\n\tartifactsList: ArtifactCollection[];\n};\n\nexport const ArtifactsPage = ({\n\tfilters,\n\tonFilterChange,\n\tartifactsList,\n\tartifactsCount,\n}: ArtifactsPageProps) => {\n\tconst [displayMode, setDisplayMode] = useLocalStorage<string>(\n\t\t\"artifacts-grid-style\",\n\t\t\"grid\",\n\t);\n\n\tconst gridClass = useMemo(() => {\n\t\treturn displayMode === \"grid\"\n\t\t\t? \"grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-4\"\n\t\t\t: \"grid-cols-1\";\n\t}, [displayMode]);\n\n\treturn (\n\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t<ArtifactsHeader />\n\t\t\t<ArtifactsFilterComponent\n\t\t\t\tfilters={filters}\n\t\t\t\tonFilterChange={onFilterChange}\n\t\t\t\ttotalCount={artifactsCount}\n\t\t\t\tsetDisplayMode={setDisplayMode}\n\t\t\t\tdisplayMode={displayMode}\n\t\t\t/>\n\n\t\t\t{artifactsList.length === 0 ? (\n\t\t\t\t<ArtifactsEmptyState />\n\t\t\t) : (\n\t\t\t\t<div className={gridClass}>\n\t\t\t\t\t{artifactsList.map((artifact) => (\n\t\t\t\t\t\t<ArtifactCard key={artifact.id} artifact={artifact} />\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n};\n","import { useSuspenseQueries } from \"@tanstack/react-query\";\nimport type { ErrorComponentProps } from \"@tanstack/react-router\";\nimport { createFileRoute } from \"@tanstack/react-router\";\nimport { zodValidator } from \"@tanstack/zod-adapter\";\nimport { useCallback, useMemo } from \"react\";\nimport { z } from \"zod\";\nimport {\n\ttype ArtifactCollectionsFilter,\n\tbuildCountLatestArtifactsQuery,\n\tbuildListLatestArtifactsQuery,\n} from \"@/api/artifacts\";\nimport { categorizeError } from \"@/api/error-utils\";\nimport { ArtifactsPage } from \"@/components/artifacts/artifacts-page\";\nimport type { filterType } from \"@/components/artifacts/types\";\nimport { PrefectLoading } from \"@/components/ui/loading\";\nimport { RouteErrorState } from \"@/components/ui/route-error-state\";\nimport useDebounceCallback from \"@/hooks/use-debounce-callback\";\n\n/**\n * Schema for validating URL search parameters for the artifacts 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\ttype: z.string().optional().catch(\"\"),\n\tname: z.string().optional().catch(\"\"),\n});\n\n/**\n * Builds filter parameters for artifacts query from search params\n *\n * @param search - Optional validated search parameters containing page and limit\n * @returns ArtifactsFilter with type and name\n *\n * @example\n * ```ts\n * const filter = buildFilterBody({ type: \"markdown\", name: \"my-dataset\" })\n * // Returns {\n * //\t\tartifacts: {\n * //\t\t\toperator: \"and_\",\n * //\t\t\ttype: { any_: [\"markdown\"] },\n * //\t\t\tkey: { exists_: true, like_: \"my-dataset\" }\n * //\t\t},\n * //\t\toffset: 0\n * //}\n * ```\n */\nconst buildFilterBody = (\n\tsearch?: z.infer<typeof searchParams>,\n): ArtifactCollectionsFilter => ({\n\tartifacts: {\n\t\toperator: \"and_\",\n\t\ttype: {\n\t\t\tany_: search?.type && search?.type !== \"all\" ? [search.type] : undefined,\n\t\t},\n\t\tkey: {\n\t\t\texists_: true,\n\t\t\tlike_: search?.name ?? \"\",\n\t\t},\n\t},\n\tsort: \"ID_DESC\",\n\toffset: 0,\n});\n\nexport const Route = createFileRoute(\"/artifacts/\")({\n\tvalidateSearch: zodValidator(searchParams),\n\tcomponent: function RouteComponent() {\n\t\tconst search = Route.useSearch();\n\t\tconst { filters, onFilterChange } = useFilter();\n\n\t\tconst [{ data: artifactsCount }, { data: artifactsList }] =\n\t\t\tuseSuspenseQueries({\n\t\t\t\tqueries: [\n\t\t\t\t\tbuildCountLatestArtifactsQuery(buildFilterBody(search)),\n\t\t\t\t\tbuildListLatestArtifactsQuery(buildFilterBody(search)),\n\t\t\t\t],\n\t\t\t});\n\n\t\treturn (\n\t\t\t<ArtifactsPage\n\t\t\t\tfilters={filters}\n\t\t\t\tonFilterChange={onFilterChange}\n\t\t\t\tartifactsCount={artifactsCount}\n\t\t\t\tartifactsList={artifactsList}\n\t\t\t/>\n\t\t);\n\t},\n\tloaderDeps: ({ search }) => buildFilterBody(search),\n\tloader: ({ deps, context }) => {\n\t\tvoid context.queryClient.prefetchQuery(\n\t\t\tbuildCountLatestArtifactsQuery(deps),\n\t\t);\n\t\tvoid context.queryClient.prefetchQuery(buildListLatestArtifactsQuery(deps));\n\t},\n\terrorComponent: function ArtifactsErrorComponent({\n\t\terror,\n\t\treset,\n\t}: ErrorComponentProps) {\n\t\tconst serverError = categorizeError(error, \"Failed to load artifacts\");\n\t\tif (\n\t\t\tserverError.type !== \"server-error\" &&\n\t\t\tserverError.type !== \"client-error\"\n\t\t) {\n\t\t\tthrow error;\n\t\t}\n\t\treturn (\n\t\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t\t<div>\n\t\t\t\t\t<h1 className=\"text-2xl font-semibold\">Artifacts</h1>\n\t\t\t\t</div>\n\t\t\t\t<RouteErrorState error={serverError} onRetry={reset} />\n\t\t\t</div>\n\t\t);\n\t},\n\twrapInSuspense: true,\n\tpendingComponent: PrefectLoading,\n});\n\nconst useFilter = () => {\n\tconst search = Route.useSearch();\n\tconst navigate = Route.useNavigate();\n\n\tconst filters = useMemo(\n\t\t() => [\n\t\t\t{ id: \"type\", label: \"Type\", value: search.type ?? \"all\" },\n\t\t\t{ id: \"name\", label: \"Name\", value: search.name },\n\t\t],\n\t\t[search.type, search.name],\n\t);\n\n\tconst onFilterChange = useDebounceCallback(\n\t\tuseCallback(\n\t\t\t(newFilters: filterType[]) => {\n\t\t\t\tif (!newFilters) return;\n\t\t\t\tvoid navigate({\n\t\t\t\t\tto: \".\",\n\t\t\t\t\tsearch: () =>\n\t\t\t\t\t\tnewFilters\n\t\t\t\t\t\t\t.filter((filter) => filter.value)\n\t\t\t\t\t\t\t.reduce(\n\t\t\t\t\t\t\t\t(prev, curr) => {\n\t\t\t\t\t\t\t\t\tif (!curr.value) return prev;\n\t\t\t\t\t\t\t\t\tprev[curr.id] = curr.value;\n\t\t\t\t\t\t\t\t\treturn prev;\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{} as Record<string, string>,\n\t\t\t\t\t\t\t),\n\t\t\t\t\treplace: true,\n\t\t\t\t});\n\t\t\t},\n\t\t\t[navigate],\n\t\t),\n\t\t400,\n\t);\n\n\treturn { filters, onFilterChange };\n};\n"],"mappings":"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"}
|