prefect 3.7.3.dev3__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.
Files changed (186) hide show
  1. prefect/_build_info.py +3 -3
  2. prefect/client/orchestration/__init__.py +10 -3
  3. prefect/runner/_workspace_resolver.py +83 -5
  4. prefect/server/orchestration/core_policy.py +3 -2
  5. prefect/server/ui-v2/assets/{artifact._id-Zo42JsyQ.js → artifact._id-CZKgXEWB.js} +2 -2
  6. prefect/server/ui-v2/assets/{artifact._id-Zo42JsyQ.js.map → artifact._id-CZKgXEWB.js.map} +1 -1
  7. prefect/server/ui-v2/assets/{artifacts-BdknReie.js → artifacts-DwYa9F9j.js} +2 -2
  8. prefect/server/ui-v2/assets/{artifacts-BdknReie.js.map → artifacts-DwYa9F9j.js.map} +1 -1
  9. prefect/server/ui-v2/assets/{automation-wizard-CqzFukp0.js → automation-wizard-Co7sJL6C.js} +2 -2
  10. prefect/server/ui-v2/assets/{automation-wizard-CqzFukp0.js.map → automation-wizard-Co7sJL6C.js.map} +1 -1
  11. prefect/server/ui-v2/assets/{automation._id-DHR9tHhZ.js → automation._id-CzAbz8OQ.js} +2 -2
  12. prefect/server/ui-v2/assets/{automation._id-DHR9tHhZ.js.map → automation._id-CzAbz8OQ.js.map} +1 -1
  13. prefect/server/ui-v2/assets/{automation_._id.edit-CUgxw4VO.js → automation_._id.edit-C7B50KC9.js} +2 -2
  14. prefect/server/ui-v2/assets/{automation_._id.edit-CUgxw4VO.js.map → automation_._id.edit-C7B50KC9.js.map} +1 -1
  15. prefect/server/ui-v2/assets/{automations-BteX3VP5.js → automations-C6FJGw7P.js} +2 -2
  16. prefect/server/ui-v2/assets/{automations-BteX3VP5.js.map → automations-C6FJGw7P.js.map} +1 -1
  17. prefect/server/ui-v2/assets/{automations-_EtuoGXy.js → automations-DKLFqR-W.js} +2 -2
  18. prefect/server/ui-v2/assets/{automations-_EtuoGXy.js.map → automations-DKLFqR-W.js.map} +1 -1
  19. prefect/server/ui-v2/assets/{automations-header-DVHcldsa.js → automations-header-BuKdnos3.js} +2 -2
  20. prefect/server/ui-v2/assets/{automations-header-DVHcldsa.js.map → automations-header-BuKdnos3.js.map} +1 -1
  21. prefect/server/ui-v2/assets/{automations-wizard-BxUMHb1N.js → automations-wizard-5YbxdG3F.js} +2 -2
  22. prefect/server/ui-v2/assets/{automations-wizard-BxUMHb1N.js.map → automations-wizard-5YbxdG3F.js.map} +1 -1
  23. prefect/server/ui-v2/assets/{base-job-template-form-section-B0YP4I3P.js → base-job-template-form-section-BRcgnkke.js} +2 -2
  24. prefect/server/ui-v2/assets/{base-job-template-form-section-B0YP4I3P.js.map → base-job-template-form-section-BRcgnkke.js.map} +1 -1
  25. prefect/server/ui-v2/assets/{block-type-details-B3Vwd-RE.js → block-type-details-C_uCdUZa.js} +2 -2
  26. prefect/server/ui-v2/assets/{block-type-details-B3Vwd-RE.js.map → block-type-details-C_uCdUZa.js.map} +1 -1
  27. prefect/server/ui-v2/assets/{block._id-B3CCPFtJ.js → block._id-MmsBO1E0.js} +2 -2
  28. prefect/server/ui-v2/assets/{block._id-B3CCPFtJ.js.map → block._id-MmsBO1E0.js.map} +1 -1
  29. prefect/server/ui-v2/assets/{block_._id.edit-DSO33Cqt.js → block_._id.edit-UsE5VhnE.js} +2 -2
  30. prefect/server/ui-v2/assets/{block_._id.edit-DSO33Cqt.js.map → block_._id.edit-UsE5VhnE.js.map} +1 -1
  31. prefect/server/ui-v2/assets/blocks-CH5PZKMD.js.map +1 -1
  32. prefect/server/ui-v2/assets/blocks-Y4tx1Z1C.js +2 -0
  33. prefect/server/ui-v2/assets/blocks-Y4tx1Z1C.js.map +1 -0
  34. prefect/server/ui-v2/assets/{catalog-peZ0ZDPi.js → catalog-DXAxNW-w.js} +2 -2
  35. prefect/server/ui-v2/assets/{catalog-peZ0ZDPi.js.map → catalog-DXAxNW-w.js.map} +1 -1
  36. prefect/server/ui-v2/assets/{catalog_._slug-BUsVdYgf.js → catalog_._slug-C3g_TnXA.js} +2 -2
  37. prefect/server/ui-v2/assets/{catalog_._slug-BUsVdYgf.js.map → catalog_._slug-C3g_TnXA.js.map} +1 -1
  38. prefect/server/ui-v2/assets/{catalog_._slug_.create-ByZmibJZ.js → catalog_._slug_.create-_dCqBSi1.js} +2 -2
  39. prefect/server/ui-v2/assets/{catalog_._slug_.create-ByZmibJZ.js.map → catalog_._slug_.create-_dCqBSi1.js.map} +1 -1
  40. prefect/server/ui-v2/assets/{concurrency-limit._id-VxLjP6mE.js → concurrency-limit._id-Z8kY_5iu.js} +2 -2
  41. prefect/server/ui-v2/assets/{concurrency-limit._id-VxLjP6mE.js.map → concurrency-limit._id-Z8kY_5iu.js.map} +1 -1
  42. prefect/server/ui-v2/assets/concurrency-limits-CIYS9zer.js +2 -0
  43. prefect/server/ui-v2/assets/{concurrency-limits-BI7aLjxZ.js.map → concurrency-limits-CIYS9zer.js.map} +1 -1
  44. prefect/server/ui-v2/assets/{create-CxHFH55_.js → create-CRMR6U_t.js} +2 -2
  45. prefect/server/ui-v2/assets/{create-CxHFH55_.js.map → create-CRMR6U_t.js.map} +1 -1
  46. prefect/server/ui-v2/assets/{create-DMBCpuVl.js → create-Duz7u3aJ.js} +2 -2
  47. prefect/server/ui-v2/assets/{create-DMBCpuVl.js.map → create-Duz7u3aJ.js.map} +1 -1
  48. prefect/server/ui-v2/assets/{data-table-BbGyTn8n.js → data-table-CxsVws4O.js} +2 -2
  49. prefect/server/ui-v2/assets/{data-table-BbGyTn8n.js.map → data-table-CxsVws4O.js.map} +1 -1
  50. prefect/server/ui-v2/assets/{data-table-DLh2VpHW.js → data-table-DYXgBnS9.js} +2 -2
  51. prefect/server/ui-v2/assets/{data-table-DLh2VpHW.js.map → data-table-DYXgBnS9.js.map} +1 -1
  52. prefect/server/ui-v2/assets/deployment-form-CdtzHwSg.js +3 -0
  53. prefect/server/ui-v2/assets/{deployment-form-CmjkGAeP.js.map → deployment-form-CdtzHwSg.js.map} +1 -1
  54. prefect/server/ui-v2/assets/{deployment-links-BY54Gk6i.js → deployment-links-BEzQncME.js} +2 -2
  55. prefect/server/ui-v2/assets/{deployment-links-BY54Gk6i.js.map → deployment-links-BEzQncME.js.map} +1 -1
  56. prefect/server/ui-v2/assets/{deployment._id-PXR53xU4.js → deployment._id-CGJLPiAU.js} +2 -2
  57. prefect/server/ui-v2/assets/{deployment._id-PXR53xU4.js.map → deployment._id-CGJLPiAU.js.map} +1 -1
  58. prefect/server/ui-v2/assets/{deployment_._id.duplicate-DdLQwNw9.js → deployment_._id.duplicate-C4fAvCua.js} +2 -2
  59. prefect/server/ui-v2/assets/{deployment_._id.duplicate-DdLQwNw9.js.map → deployment_._id.duplicate-C4fAvCua.js.map} +1 -1
  60. prefect/server/ui-v2/assets/{deployment_._id.edit-D5bMVvb9.js → deployment_._id.edit-DsGbk3kr.js} +2 -2
  61. prefect/server/ui-v2/assets/{deployment_._id.edit-D5bMVvb9.js.map → deployment_._id.edit-DsGbk3kr.js.map} +1 -1
  62. prefect/server/ui-v2/assets/{deployment_._id.run-DczKs3Hq.js → deployment_._id.run-DmQjQowN.js} +2 -2
  63. prefect/server/ui-v2/assets/{deployment_._id.run-DczKs3Hq.js.map → deployment_._id.run-DmQjQowN.js.map} +1 -1
  64. prefect/server/ui-v2/assets/deployments-BP5QdKL3.js +2 -0
  65. prefect/server/ui-v2/assets/{deployments-r9sa-J42.js.map → deployments-BP5QdKL3.js.map} +1 -1
  66. prefect/server/ui-v2/assets/{deployments-CgJ1ie-z.js → deployments-BX4JGvv6.js} +2 -2
  67. prefect/server/ui-v2/assets/{deployments-CgJ1ie-z.js.map → deployments-BX4JGvv6.js.map} +1 -1
  68. prefect/server/ui-v2/assets/error-boundary-GTe7hhSV.js +2 -0
  69. prefect/server/ui-v2/assets/error-boundary-GTe7hhSV.js.map +1 -0
  70. prefect/server/ui-v2/assets/{event-resource-display-2u5ia4Md.js → event-resource-display-CU5MsqQH.js} +2 -2
  71. prefect/server/ui-v2/assets/{event-resource-display-2u5ia4Md.js.map → event-resource-display-CU5MsqQH.js.map} +1 -1
  72. prefect/server/ui-v2/assets/{event._eventDate._eventId-BAp6hV6h.js → event._eventDate._eventId-4IMEuU6B.js} +2 -2
  73. prefect/server/ui-v2/assets/{event._eventDate._eventId-BAp6hV6h.js.map → event._eventDate._eventId-4IMEuU6B.js.map} +1 -1
  74. prefect/server/ui-v2/assets/{events-BknsFN6O.js → events-D1Dc3zQ-.js} +2 -2
  75. prefect/server/ui-v2/assets/{events-BknsFN6O.js.map → events-D1Dc3zQ-.js.map} +1 -1
  76. prefect/server/ui-v2/assets/{events-timeline-Rl2m78Y5.js → events-timeline-Co9wTQgm.js} +2 -2
  77. prefect/server/ui-v2/assets/{events-timeline-Rl2m78Y5.js.map → events-timeline-Co9wTQgm.js.map} +1 -1
  78. prefect/server/ui-v2/assets/{flow-run-graph-DT6ORwEA.js → flow-run-graph-DjwzUq6H.js} +2 -2
  79. prefect/server/ui-v2/assets/{flow-run-graph-DT6ORwEA.js.map → flow-run-graph-DjwzUq6H.js.map} +1 -1
  80. prefect/server/ui-v2/assets/flow-run._id-CoTv2cTD.js +4 -0
  81. prefect/server/ui-v2/assets/flow-run._id-CoTv2cTD.js.map +1 -0
  82. prefect/server/ui-v2/assets/flow-run._id-DJeNWnOU.js +2 -0
  83. prefect/server/ui-v2/assets/{flow-run._id-CLKdcnle.js.map → flow-run._id-DJeNWnOU.js.map} +1 -1
  84. prefect/server/ui-v2/assets/{flow._id-BZAOxnsl.js → flow._id-5--exJ1V.js} +2 -2
  85. prefect/server/ui-v2/assets/{flow._id-BZAOxnsl.js.map → flow._id-5--exJ1V.js.map} +1 -1
  86. prefect/server/ui-v2/assets/flow._id-BUiXEl1F.js +2 -0
  87. prefect/server/ui-v2/assets/{flow._id-CyI-Q-4Z.js.map → flow._id-BUiXEl1F.js.map} +1 -1
  88. prefect/server/ui-v2/assets/flows-CK1dzMTf.js +2 -0
  89. prefect/server/ui-v2/assets/{flows-CfyGye_i.js.map → flows-CK1dzMTf.js.map} +1 -1
  90. prefect/server/ui-v2/assets/{header-CZl2UtVY.js → header-BsgfqCC8.js} +2 -2
  91. prefect/server/ui-v2/assets/{header-CZl2UtVY.js.map → header-BsgfqCC8.js.map} +1 -1
  92. prefect/server/ui-v2/assets/header-DUaFtREk.js +2 -0
  93. prefect/server/ui-v2/assets/{header-CfPjWK5N.js.map → header-DUaFtREk.js.map} +1 -1
  94. prefect/server/ui-v2/assets/{header-B7UaCf9Y.js → header-DVeMEFGG.js} +2 -2
  95. prefect/server/ui-v2/assets/{header-B7UaCf9Y.js.map → header-DVeMEFGG.js.map} +1 -1
  96. prefect/server/ui-v2/assets/{index-BiTXO7bZ.js → index--DOPlnGf.js} +4 -4
  97. prefect/server/ui-v2/assets/index--DOPlnGf.js.map +1 -0
  98. prefect/server/ui-v2/assets/{json-input-DuU-pR4T.js → json-input-DT3KbxDZ.js} +2 -2
  99. prefect/server/ui-v2/assets/{json-input-DuU-pR4T.js.map → json-input-DT3KbxDZ.js.map} +1 -1
  100. prefect/server/ui-v2/assets/{key._key-BfIX2NO0.js → key._key-BgZBad2s.js} +2 -2
  101. prefect/server/ui-v2/assets/{key._key-BfIX2NO0.js.map → key._key-BgZBad2s.js.map} +1 -1
  102. prefect/server/ui-v2/assets/{lazy-markdown-C6e3AE83.js → lazy-markdown-CjMJs81K.js} +2 -2
  103. prefect/server/ui-v2/assets/{lazy-markdown-C6e3AE83.js.map → lazy-markdown-CjMJs81K.js.map} +1 -1
  104. prefect/server/ui-v2/assets/{login-BAVVPHlC.js → login-Cx1NrLpk.js} +2 -2
  105. prefect/server/ui-v2/assets/{login-BAVVPHlC.js.map → login-Cx1NrLpk.js.map} +1 -1
  106. prefect/server/ui-v2/assets/runs-Cr_7Tg39.js +2 -0
  107. prefect/server/ui-v2/assets/{runs-HrNDCquv.js.map → runs-Cr_7Tg39.js.map} +1 -1
  108. prefect/server/ui-v2/assets/{runs-J2wsTr98.js → runs-DUrOYS1_.js} +2 -2
  109. prefect/server/ui-v2/assets/{runs-J2wsTr98.js.map → runs-DUrOYS1_.js.map} +1 -1
  110. prefect/server/ui-v2/assets/{schedule-badge-0fzDLqK0.js → schedule-badge-Zhj77ROw.js} +2 -2
  111. prefect/server/ui-v2/assets/{schedule-badge-0fzDLqK0.js.map → schedule-badge-Zhj77ROw.js.map} +1 -1
  112. prefect/server/ui-v2/assets/schema-form-Ccp8AU3g.js +6 -0
  113. prefect/server/ui-v2/assets/schema-form-Ccp8AU3g.js.map +1 -0
  114. prefect/server/ui-v2/assets/{settings-CKEdr8bc.js → settings-CjNHvh7S.js} +2 -2
  115. prefect/server/ui-v2/assets/{settings-CKEdr8bc.js.map → settings-CjNHvh7S.js.map} +1 -1
  116. prefect/server/ui-v2/assets/{task-run-concurrency-limits-reset-dialog-CSOUIoRP.js → task-run-concurrency-limits-reset-dialog-CJnrAkAF.js} +2 -2
  117. 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
  118. prefect/server/ui-v2/assets/task-run._id-Cvm_Plyh.js +3 -0
  119. prefect/server/ui-v2/assets/{task-run._id-BUnHohQT.js.map → task-run._id-Cvm_Plyh.js.map} +1 -1
  120. prefect/server/ui-v2/assets/{timezone-select-Bnsn0RhV.js → timezone-select-Cp7XxZiY.js} +2 -2
  121. prefect/server/ui-v2/assets/{timezone-select-Bnsn0RhV.js.map → timezone-select-Cp7XxZiY.js.map} +1 -1
  122. prefect/server/ui-v2/assets/{toggle-group-_iuYMe3I.js → toggle-group-DGZ0dcl7.js} +2 -2
  123. prefect/server/ui-v2/assets/{toggle-group-_iuYMe3I.js.map → toggle-group-DGZ0dcl7.js.map} +1 -1
  124. prefect/server/ui-v2/assets/{trigger-details-CTi7CDXp.js → trigger-details-BvMAAJrh.js} +2 -2
  125. prefect/server/ui-v2/assets/{trigger-details-CTi7CDXp.js.map → trigger-details-BvMAAJrh.js.map} +1 -1
  126. prefect/server/ui-v2/assets/{use-delete-automation-confirmation-dialog-Dzh4KhYd.js → use-delete-automation-confirmation-dialog-C4LY0Nzd.js} +2 -2
  127. prefect/server/ui-v2/assets/{use-delete-automation-confirmation-dialog-Dzh4KhYd.js.map → use-delete-automation-confirmation-dialog-C4LY0Nzd.js.map} +1 -1
  128. prefect/server/ui-v2/assets/{use-delete-block-document-confirmation-dialog-CMUcMn04.js → use-delete-block-document-confirmation-dialog-CkaSA4HR.js} +2 -2
  129. 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
  130. prefect/server/ui-v2/assets/{use-delete-deployment-confirmation-dialog-DCR3G6aC.js → use-delete-deployment-confirmation-dialog-cisnGao9.js} +2 -2
  131. prefect/server/ui-v2/assets/{use-delete-deployment-confirmation-dialog-DCR3G6aC.js.map → use-delete-deployment-confirmation-dialog-cisnGao9.js.map} +1 -1
  132. prefect/server/ui-v2/assets/{use-get-artifacts-flow-task-runs-CwYIhd7a.js → use-get-artifacts-flow-task-runs-BCK_2tbs.js} +2 -2
  133. 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
  134. prefect/server/ui-v2/assets/{use-resource-options-TivZbz4R.js → use-resource-options-rV-5KQt6.js} +2 -2
  135. prefect/server/ui-v2/assets/{use-resource-options-TivZbz4R.js.map → use-resource-options-rV-5KQt6.js.map} +1 -1
  136. prefect/server/ui-v2/assets/variables-BabJ_hXE.js +2 -0
  137. prefect/server/ui-v2/assets/{variables-DohLnyOU.js.map → variables-BabJ_hXE.js.map} +1 -1
  138. prefect/server/ui-v2/assets/{variables--T46q5I7.js → variables-z-MiCawT.js} +2 -2
  139. prefect/server/ui-v2/assets/{variables--T46q5I7.js.map → variables-z-MiCawT.js.map} +1 -1
  140. prefect/server/ui-v2/assets/{work-pool-queue-form-BTlH9k-v.js → work-pool-queue-form-BQp2FWMa.js} +2 -2
  141. prefect/server/ui-v2/assets/{work-pool-queue-form-BTlH9k-v.js.map → work-pool-queue-form-BQp2FWMa.js.map} +1 -1
  142. prefect/server/ui-v2/assets/{work-pool-queue-toggle-DJYRbHHT.js → work-pool-queue-toggle-DJp6MSwY.js} +2 -2
  143. prefect/server/ui-v2/assets/{work-pool-queue-toggle-DJYRbHHT.js.map → work-pool-queue-toggle-DJp6MSwY.js.map} +1 -1
  144. prefect/server/ui-v2/assets/{work-pool._workPoolName-BNogexz_.js → work-pool._workPoolName-DL31uKjj.js} +2 -2
  145. prefect/server/ui-v2/assets/{work-pool._workPoolName-BNogexz_.js.map → work-pool._workPoolName-DL31uKjj.js.map} +1 -1
  146. prefect/server/ui-v2/assets/{work-pool_._workPoolName.edit-BUADYBE8.js → work-pool_._workPoolName.edit-DDMAg-Oa.js} +2 -2
  147. prefect/server/ui-v2/assets/{work-pool_._workPoolName.edit-BUADYBE8.js.map → work-pool_._workPoolName.edit-DDMAg-Oa.js.map} +1 -1
  148. prefect/server/ui-v2/assets/{work-pool_._workPoolName.queue._workQueueName-BB5g0Fdn.js → work-pool_._workPoolName.queue._workQueueName-DOowHyr0.js} +2 -2
  149. prefect/server/ui-v2/assets/{work-pool_._workPoolName.queue._workQueueName-BB5g0Fdn.js.map → work-pool_._workPoolName.queue._workQueueName-DOowHyr0.js.map} +1 -1
  150. prefect/server/ui-v2/assets/{work-pool_._workPoolName.queue.create-USf-zJSY.js → work-pool_._workPoolName.queue.create-U8kXUs3q.js} +2 -2
  151. prefect/server/ui-v2/assets/{work-pool_._workPoolName.queue.create-USf-zJSY.js.map → work-pool_._workPoolName.queue.create-U8kXUs3q.js.map} +1 -1
  152. prefect/server/ui-v2/assets/{work-pool_._workPoolName.queue_._workQueueName.edit-DQsfRuma.js → work-pool_._workPoolName.queue_._workQueueName.edit-CR2SFGIl.js} +2 -2
  153. 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
  154. prefect/server/ui-v2/assets/{work-pools-QaYhK2wz.js → work-pools-DP8kBaS2.js} +2 -2
  155. prefect/server/ui-v2/assets/{work-pools-QaYhK2wz.js.map → work-pools-DP8kBaS2.js.map} +1 -1
  156. prefect/server/ui-v2/assets/{work-pools-D_2J6ZNf.js → work-pools-lxhnp-i4.js} +2 -2
  157. prefect/server/ui-v2/assets/{work-pools-D_2J6ZNf.js.map → work-pools-lxhnp-i4.js.map} +1 -1
  158. prefect/server/ui-v2/assets/{work-queue-icon-text-BI7IQrcX.js → work-queue-icon-text-BMp37wo6.js} +2 -2
  159. prefect/server/ui-v2/assets/{work-queue-icon-text-BI7IQrcX.js.map → work-queue-icon-text-BMp37wo6.js.map} +1 -1
  160. prefect/server/ui-v2/assets/work-queue-select-B7h2Ezjb.js +2 -0
  161. prefect/server/ui-v2/assets/{work-queue-select-QOtPRzFp.js.map → work-queue-select-B7h2Ezjb.js.map} +1 -1
  162. prefect/server/ui-v2/index.html +1 -1
  163. prefect/workers/_worker_channel/_transport.py +6 -1
  164. {prefect-3.7.3.dev3.dist-info → prefect-3.7.3.dev4.dist-info}/METADATA +1 -1
  165. {prefect-3.7.3.dev3.dist-info → prefect-3.7.3.dev4.dist-info}/RECORD +168 -166
  166. prefect/server/ui-v2/assets/blocks-BPxghuZI.js +0 -2
  167. prefect/server/ui-v2/assets/blocks-BPxghuZI.js.map +0 -1
  168. prefect/server/ui-v2/assets/concurrency-limits-BI7aLjxZ.js +0 -2
  169. prefect/server/ui-v2/assets/deployment-form-CmjkGAeP.js +0 -3
  170. prefect/server/ui-v2/assets/deployments-r9sa-J42.js +0 -2
  171. prefect/server/ui-v2/assets/flow-run._id-CLKdcnle.js +0 -2
  172. prefect/server/ui-v2/assets/flow-run._id-n-hTsvaN.js +0 -4
  173. prefect/server/ui-v2/assets/flow-run._id-n-hTsvaN.js.map +0 -1
  174. prefect/server/ui-v2/assets/flow._id-CyI-Q-4Z.js +0 -2
  175. prefect/server/ui-v2/assets/flows-CfyGye_i.js +0 -2
  176. prefect/server/ui-v2/assets/header-CfPjWK5N.js +0 -2
  177. prefect/server/ui-v2/assets/index-BiTXO7bZ.js.map +0 -1
  178. prefect/server/ui-v2/assets/runs-HrNDCquv.js +0 -2
  179. prefect/server/ui-v2/assets/schema-form-DLdMdbMj.js +0 -6
  180. prefect/server/ui-v2/assets/schema-form-DLdMdbMj.js.map +0 -1
  181. prefect/server/ui-v2/assets/task-run._id-BUnHohQT.js +0 -3
  182. prefect/server/ui-v2/assets/variables-DohLnyOU.js +0 -2
  183. prefect/server/ui-v2/assets/work-queue-select-QOtPRzFp.js +0 -2
  184. {prefect-3.7.3.dev3.dist-info → prefect-3.7.3.dev4.dist-info}/WHEEL +0 -0
  185. {prefect-3.7.3.dev3.dist-info → prefect-3.7.3.dev4.dist-info}/entry_points.txt +0 -0
  186. {prefect-3.7.3.dev3.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.dev3"
3
- __build_date__ = "2026-05-26 09:20:51.606541+00:00"
4
- __git_commit__ = "822447055dd0600580c832572eb9bdf8adca2cb9"
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(f"Failed to reach API at {self.api_url}") from e
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(f"Connecting to API at {self.api_url}")
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(f"Failed to reach API at {self.api_url}") from e
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
- from_path = _resolve_local_deployment_path(
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
- os.chdir(working_directory)
257
- working_directory = Path.cwd().resolve()
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
- if run_settings.retry_jitter_factor:
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-Zo42JsyQ.js.map
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{Dr as f,Er as p,G as m,W as h,Y as g,Yr as _,Z as v,ar as y,er as b,ir as x,kr as S,nr as C,rr as w,tr as T}from"./index-BiTXO7bZ.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-_iuYMe3I.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)(p,{children:(0,j.jsx)(S,{children:(0,j.jsx)(f,{className:`text-xl font-semibold`,children:`Artifacts`})})})}),(0,j.jsx)(y,{id:`artifacts-guide`,label:`Documentation`})]}),F=()=>(0,j.jsxs)(b,{children:[(0,j.jsx)(`div`,{className:`flex items-center gap-3`,children:(0,j.jsx)(w,{id:`Image`})}),(0,j.jsx)(x,{children:`Create an artifact to get started`}),(0,j.jsx)(C,{children:`Artifacts are byproducts of your runs; they can be anything from a markdown string to a table.`}),(0,j.jsx)(T,{children:(0,j.jsx)(y,{id:`artifacts-guide`})})]}),I=({filters:e,onFilterChange:t,artifactsList:n,artifactsCount:r})=>{let[i,a]=_(`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=h.useSearch(),t=h.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=h.useSearch(),{filters:t,onFilterChange:n}=L(),[{data:i},{data:a}]=r({queries:[m(v(e)),g(v(e))]});return(0,j.jsx)(I,{filters:t,onFilterChange:n,artifactsCount:i,artifactsList:a})};export{R as component};
2
- //# sourceMappingURL=artifacts-BdknReie.js.map
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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"}