@hotmeshio/long-tail 0.7.5 → 0.8.0
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.
- package/build/api/workflows/config.d.ts +7 -1
- package/build/api/workflows/config.js +7 -1
- package/build/api/workflows/discovery.js +1 -4
- package/build/lib/db/schemas/020_workflow_certified.sql +34 -0
- package/build/modules/ltconfig.d.ts +3 -2
- package/build/modules/ltconfig.js +4 -4
- package/build/routes/workflows/config.js +1 -0
- package/build/services/config/cache.js +1 -0
- package/build/services/config/read.js +2 -0
- package/build/services/config/sql.d.ts +2 -2
- package/build/services/config/sql.js +6 -5
- package/build/services/config/write.js +13 -0
- package/build/services/escalation/bulk.d.ts +3 -1
- package/build/services/escalation/bulk.js +3 -1
- package/build/services/escalation/crud.d.ts +4 -3
- package/build/services/escalation/crud.js +4 -3
- package/build/start/workers.js +1 -0
- package/build/system/mcp-servers/admin/schemas.d.ts +3 -0
- package/build/system/mcp-servers/admin/schemas.js +3 -1
- package/build/system/mcp-servers/admin/workflow-config.js +1 -0
- package/build/types/config.d.ts +16 -0
- package/build/types/startup.d.ts +11 -1
- package/dashboard/dist/assets/{AdminDashboard-Bgomc_jH.js → AdminDashboard-9JLg41f-.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-Bgomc_jH.js.map → AdminDashboard-9JLg41f-.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-C6gDgz21.js → AgentConfigPage-D5P1hcOc.js} +2 -2
- package/dashboard/dist/assets/{AgentConfigPage-C6gDgz21.js.map → AgentConfigPage-D5P1hcOc.js.map} +1 -1
- package/dashboard/dist/assets/{AgentDetailPage-0rrH5FmV.js → AgentDetailPage-DrijeAV8.js} +2 -2
- package/dashboard/dist/assets/{AgentDetailPage-0rrH5FmV.js.map → AgentDetailPage-DrijeAV8.js.map} +1 -1
- package/dashboard/dist/assets/{AgentsPage-DkIU2zed.js → AgentsPage-BW5d0JOt.js} +2 -2
- package/dashboard/dist/assets/{AgentsPage-DkIU2zed.js.map → AgentsPage-BW5d0JOt.js.map} +1 -1
- package/dashboard/dist/assets/{AvailableEscalationsPage-C9DAtNGp.js → AvailableEscalationsPage-CoZ4Lufr.js} +2 -2
- package/dashboard/dist/assets/{AvailableEscalationsPage-C9DAtNGp.js.map → AvailableEscalationsPage-CoZ4Lufr.js.map} +1 -1
- package/dashboard/dist/assets/{BotPicker-MnI3OyE7.js → BotPicker-xGUCxJo-.js} +2 -2
- package/dashboard/dist/assets/{BotPicker-MnI3OyE7.js.map → BotPicker-xGUCxJo-.js.map} +1 -1
- package/dashboard/dist/assets/{CapabilitiesPage-Cv_AD_5i.js → CapabilitiesPage-ChaRJiyg.js} +2 -2
- package/dashboard/dist/assets/{CapabilitiesPage-Cv_AD_5i.js.map → CapabilitiesPage-ChaRJiyg.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-Ne-Q3QFM.js → CollapsibleSection-CXMPecjj.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-Ne-Q3QFM.js.map → CollapsibleSection-CXMPecjj.js.map} +1 -1
- package/dashboard/dist/assets/{CredentialsPage-B3Mfwl22.js → CredentialsPage-BbdfZh1D.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-B3Mfwl22.js.map → CredentialsPage-BbdfZh1D.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-CtjUBRPo.js → CronLabel-CJUL50eO.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-CtjUBRPo.js.map → CronLabel-CJUL50eO.js.map} +1 -1
- package/dashboard/dist/assets/{CustomDurationPicker-Cp1fgzPX.js → CustomDurationPicker-id6Tq64R.js} +2 -2
- package/dashboard/dist/assets/{CustomDurationPicker-Cp1fgzPX.js.map → CustomDurationPicker-id6Tq64R.js.map} +1 -1
- package/dashboard/dist/assets/{ElapsedCell-Gr5UlUbn.js → ElapsedCell-B8TrnyT5.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-Gr5UlUbn.js.map → ElapsedCell-B8TrnyT5.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationSchemaPage-C5tuV6SJ.js → EscalationSchemaPage-C6UuZgCD.js} +2 -2
- package/dashboard/dist/assets/{EscalationSchemaPage-C5tuV6SJ.js.map → EscalationSchemaPage-C6UuZgCD.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationsOverview-BIZVnSBF.js → EscalationsOverview-CjLyujJ3.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-BIZVnSBF.js.map → EscalationsOverview-CjLyujJ3.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-90aUfsNr.js → EventTable-D_rNmyGG.js} +2 -2
- package/dashboard/dist/assets/{EventTable-90aUfsNr.js.map → EventTable-D_rNmyGG.js.map} +1 -1
- package/dashboard/dist/assets/{GraphInvokePage-Io5ZucT8.js → GraphInvokePage-BMyrTnI6.js} +2 -2
- package/dashboard/dist/assets/{GraphInvokePage-Io5ZucT8.js.map → GraphInvokePage-BMyrTnI6.js.map} +1 -1
- package/dashboard/dist/assets/{HomePage-Cu0vUzTF.js → HomePage-MBv6pwk4.js} +2 -2
- package/dashboard/dist/assets/{HomePage-Cu0vUzTF.js.map → HomePage-MBv6pwk4.js.map} +1 -1
- package/dashboard/dist/assets/{ListToolbar-CdmIvEIF.js → ListToolbar--FkPpYDY.js} +2 -2
- package/dashboard/dist/assets/{ListToolbar-CdmIvEIF.js.map → ListToolbar--FkPpYDY.js.map} +1 -1
- package/dashboard/dist/assets/{McpOverview-C-Ypezuv.js → McpOverview-CtAFXv-T.js} +2 -2
- package/dashboard/dist/assets/{McpOverview-C-Ypezuv.js.map → McpOverview-CtAFXv-T.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryDetailPage-DdontKcj.js → McpQueryDetailPage-5Jzz2q2g.js} +2 -2
- package/dashboard/dist/assets/{McpQueryDetailPage-DdontKcj.js.map → McpQueryDetailPage-5Jzz2q2g.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryPage-D-1TaOGG.js → McpQueryPage-DveeRF5I.js} +2 -2
- package/dashboard/dist/assets/{McpQueryPage-D-1TaOGG.js.map → McpQueryPage-DveeRF5I.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunDetailPage-B1sCxKLD.js → McpRunDetailPage-BYIxBcA7.js} +2 -2
- package/dashboard/dist/assets/{McpRunDetailPage-B1sCxKLD.js.map → McpRunDetailPage-BYIxBcA7.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunsPage-eWJ7cDa3.js → McpRunsPage-Cgke6ask.js} +2 -2
- package/dashboard/dist/assets/{McpRunsPage-eWJ7cDa3.js.map → McpRunsPage-Cgke6ask.js.map} +1 -1
- package/dashboard/dist/assets/OperationsPage-D2i7xrAI.js +2 -0
- package/dashboard/dist/assets/OperationsPage-D2i7xrAI.js.map +1 -0
- package/dashboard/dist/assets/{OperatorDashboard-YP6kP-f_.js → OperatorDashboard-DMQwodfo.js} +2 -2
- package/dashboard/dist/assets/{OperatorDashboard-YP6kP-f_.js.map → OperatorDashboard-DMQwodfo.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessDetailPage-C_BXQvBs.js → ProcessDetailPage-Dodrk5-z.js} +2 -2
- package/dashboard/dist/assets/{ProcessDetailPage-C_BXQvBs.js.map → ProcessDetailPage-Dodrk5-z.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessesListPage-BNhFwTLl.js → ProcessesListPage-BVtkWVLY.js} +2 -2
- package/dashboard/dist/assets/{ProcessesListPage-BNhFwTLl.js.map → ProcessesListPage-BVtkWVLY.js.map} +1 -1
- package/dashboard/dist/assets/{RoleDetailPage-8GLNjj9I.js → RoleDetailPage-8NldZI49.js} +2 -2
- package/dashboard/dist/assets/{RoleDetailPage-8GLNjj9I.js.map → RoleDetailPage-8NldZI49.js.map} +1 -1
- package/dashboard/dist/assets/{RolesPage-B59tE2lZ.js → RolesPage-BJBjtFNY.js} +2 -2
- package/dashboard/dist/assets/{RolesPage-B59tE2lZ.js.map → RolesPage-BJBjtFNY.js.map} +1 -1
- package/dashboard/dist/assets/{RunAsSelector-CokM3Ifp.js → RunAsSelector-Cc1i017Z.js} +2 -2
- package/dashboard/dist/assets/{RunAsSelector-CokM3Ifp.js.map → RunAsSelector-Cc1i017Z.js.map} +1 -1
- package/dashboard/dist/assets/{StickyPagination-_H2j2CAH.js → StickyPagination-GQKFFTjL.js} +2 -2
- package/dashboard/dist/assets/{StickyPagination-_H2j2CAH.js.map → StickyPagination-GQKFFTjL.js.map} +1 -1
- package/dashboard/dist/assets/{StreamMessageDetail-sSfHDYIa.js → StreamMessageDetail-BYzfjWe_.js} +2 -2
- package/dashboard/dist/assets/{StreamMessageDetail-sSfHDYIa.js.map → StreamMessageDetail-BYzfjWe_.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-LZWtfBK3.js → SwimlaneTimeline-DLVmRrd-.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-LZWtfBK3.js.map → SwimlaneTimeline-DLVmRrd-.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-CHBV2V6R.js → TaskDetailPage-HzQpzp6D.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-CHBV2V6R.js.map → TaskDetailPage-HzQpzp6D.js.map} +1 -1
- package/dashboard/dist/assets/{TasksListPage-B71FxvrY.js → TasksListPage-DpqevgTz.js} +2 -2
- package/dashboard/dist/assets/{TasksListPage-B71FxvrY.js.map → TasksListPage-DpqevgTz.js.map} +1 -1
- package/dashboard/dist/assets/{TimeAgo-JgT0U_sd.js → TimeAgo-CftB8aJE.js} +2 -2
- package/dashboard/dist/assets/{TimeAgo-JgT0U_sd.js.map → TimeAgo-CftB8aJE.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-gEreK8Nn.js → TimestampCell-BSKj1jqT.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-gEreK8Nn.js.map → TimestampCell-BSKj1jqT.js.map} +1 -1
- package/dashboard/dist/assets/{ToolTestPanel-ChfHw9Aq.js → ToolTestPanel-DVQICZUQ.js} +2 -2
- package/dashboard/dist/assets/{ToolTestPanel-ChfHw9Aq.js.map → ToolTestPanel-DVQICZUQ.js.map} +1 -1
- package/dashboard/dist/assets/{TopicDetailPage-DigI0HGt.js → TopicDetailPage-B2LAQDEg.js} +2 -2
- package/dashboard/dist/assets/{TopicDetailPage-DigI0HGt.js.map → TopicDetailPage-B2LAQDEg.js.map} +1 -1
- package/dashboard/dist/assets/{TopicsPage-BHjlFpPN.js → TopicsPage-SwPAnN2C.js} +2 -2
- package/dashboard/dist/assets/{TopicsPage-BHjlFpPN.js.map → TopicsPage-SwPAnN2C.js.map} +1 -1
- package/dashboard/dist/assets/{UserName-uncbaKYf.js → UserName-Ce9gvlT5.js} +2 -2
- package/dashboard/dist/assets/{UserName-uncbaKYf.js.map → UserName-Ce9gvlT5.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowExecutionPage-DwzLKTkt.js → WorkflowExecutionPage-BI9NzeaH.js} +2 -2
- package/dashboard/dist/assets/{WorkflowExecutionPage-DwzLKTkt.js.map → WorkflowExecutionPage-BI9NzeaH.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowPill-BegV-iRF.js → WorkflowPill-BuNkWUVM.js} +2 -2
- package/dashboard/dist/assets/WorkflowPill-BuNkWUVM.js.map +1 -0
- package/dashboard/dist/assets/{WorkflowsDashboard-rpnGhGnl.js → WorkflowsDashboard-CvWSgQdE.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsDashboard-rpnGhGnl.js.map → WorkflowsDashboard-CvWSgQdE.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsOverview-ihhW8DiS.js → WorkflowsOverview-CjBWlwlH.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-ihhW8DiS.js.map → WorkflowsOverview-CjBWlwlH.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-C61-8y-E.js → YamlWorkflowDetailPage-Ds5o1UK9.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-C61-8y-E.js.map → YamlWorkflowDetailPage-Ds5o1UK9.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowsPage-CMpgsLEo.js → YamlWorkflowsPage-ChwvZS4Z.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowsPage-CMpgsLEo.js.map → YamlWorkflowsPage-ChwvZS4Z.js.map} +1 -1
- package/dashboard/dist/assets/{agents-27sErp5R.js → agents-A1U43853.js} +2 -2
- package/dashboard/dist/assets/{agents-27sErp5R.js.map → agents-A1U43853.js.map} +1 -1
- package/dashboard/dist/assets/{bots-CPHuAvjW.js → bots-CyzN6Uxi.js} +2 -2
- package/dashboard/dist/assets/{bots-CPHuAvjW.js.map → bots-CyzN6Uxi.js.map} +1 -1
- package/dashboard/dist/assets/{capabilities-BBTPqF-V.js → capabilities-BE1X5FVI.js} +2 -2
- package/dashboard/dist/assets/{capabilities-BBTPqF-V.js.map → capabilities-BE1X5FVI.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-C9j2mwX8.js → controlplane-BrwK_MT8.js} +2 -2
- package/dashboard/dist/assets/{controlplane-C9j2mwX8.js.map → controlplane-BrwK_MT8.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-CyJ_wz-f.js → escalation-DDdt7UdU.js} +2 -2
- package/dashboard/dist/assets/{escalation-CyJ_wz-f.js.map → escalation-DDdt7UdU.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-columns-DU4Jyxxo.js → escalation-columns-D_zFY1zF.js} +2 -2
- package/dashboard/dist/assets/{escalation-columns-DU4Jyxxo.js.map → escalation-columns-D_zFY1zF.js.map} +1 -1
- package/dashboard/dist/assets/{index-BVHXREYZ.js → index-6MALVAEY.js} +2 -2
- package/dashboard/dist/assets/{index-BVHXREYZ.js.map → index-6MALVAEY.js.map} +1 -1
- package/dashboard/dist/assets/{index-CCHGKErT.js → index-BNWKksZ6.js} +2 -2
- package/dashboard/dist/assets/{index-CCHGKErT.js.map → index-BNWKksZ6.js.map} +1 -1
- package/dashboard/dist/assets/{index-D9pi0fs6.js → index-BtrNxebh.js} +2 -2
- package/dashboard/dist/assets/{index-D9pi0fs6.js.map → index-BtrNxebh.js.map} +1 -1
- package/dashboard/dist/assets/{index-Dzqt3g-K.js → index-C-rJQ-vB.js} +2 -2
- package/dashboard/dist/assets/{index-Dzqt3g-K.js.map → index-C-rJQ-vB.js.map} +1 -1
- package/dashboard/dist/assets/{index-BiLZJ43R.js → index-CGUBekEU.js} +2 -2
- package/dashboard/dist/assets/{index-BiLZJ43R.js.map → index-CGUBekEU.js.map} +1 -1
- package/dashboard/dist/assets/{index-BoZydcaW.js → index-CKXSKsVZ.js} +3 -3
- package/dashboard/dist/assets/{index-BoZydcaW.js.map → index-CKXSKsVZ.js.map} +1 -1
- package/dashboard/dist/assets/{index-CjXzZ19T.js → index-D2dDPGNk.js} +2 -2
- package/dashboard/dist/assets/{index-CjXzZ19T.js.map → index-D2dDPGNk.js.map} +1 -1
- package/dashboard/dist/assets/{index-CNprOGuS.js → index-D4U--3Xo.js} +2 -2
- package/dashboard/dist/assets/{index-CNprOGuS.js.map → index-D4U--3Xo.js.map} +1 -1
- package/dashboard/dist/assets/{index-BBQggGcf.js → index-D4gAsCGh.js} +2 -2
- package/dashboard/dist/assets/{index-BBQggGcf.js.map → index-D4gAsCGh.js.map} +1 -1
- package/dashboard/dist/assets/{index-DoivEaUZ.js → index-DEXouwBQ.js} +2 -2
- package/dashboard/dist/assets/{index-DoivEaUZ.js.map → index-DEXouwBQ.js.map} +1 -1
- package/dashboard/dist/assets/{index-CgeFUhUr.js → index-NnGsWGNS.js} +2 -2
- package/dashboard/dist/assets/{index-CgeFUhUr.js.map → index-NnGsWGNS.js.map} +1 -1
- package/dashboard/dist/assets/index-U27KBbTV.js +9 -0
- package/dashboard/dist/assets/index-U27KBbTV.js.map +1 -0
- package/dashboard/dist/assets/index-fwHQSJCp.js +6 -0
- package/dashboard/dist/assets/index-fwHQSJCp.js.map +1 -0
- package/dashboard/dist/assets/{knowledge-BErJA3Je.js → knowledge-B3ZIRTeu.js} +2 -2
- package/dashboard/dist/assets/{knowledge-BErJA3Je.js.map → knowledge-B3ZIRTeu.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-Cx9L42EN.js → mcp-BJjWiHdc.js} +2 -2
- package/dashboard/dist/assets/{mcp-Cx9L42EN.js.map → mcp-BJjWiHdc.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-Cf6kcBoW.js → mcp-query-ksjBztwq.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-Cf6kcBoW.js.map → mcp-query-ksjBztwq.js.map} +1 -1
- package/dashboard/dist/assets/{pipelines-CFctrv71.js → pipelines-DT1astmP.js} +2 -2
- package/dashboard/dist/assets/{pipelines-CFctrv71.js.map → pipelines-DT1astmP.js.map} +1 -1
- package/dashboard/dist/assets/{roles-CCXZtqDr.js → roles-UboiQxXT.js} +2 -2
- package/dashboard/dist/assets/{roles-CCXZtqDr.js.map → roles-UboiQxXT.js.map} +1 -1
- package/dashboard/dist/assets/{tasks-BPNj8ZWL.js → tasks-aL0K8WW3.js} +2 -2
- package/dashboard/dist/assets/{tasks-BPNj8ZWL.js.map → tasks-aL0K8WW3.js.map} +1 -1
- package/dashboard/dist/assets/{topics-CR4UBuSV.js → topics-CZO06VJl.js} +2 -2
- package/dashboard/dist/assets/{topics-CR4UBuSV.js.map → topics-CZO06VJl.js.map} +1 -1
- package/dashboard/dist/assets/{useEventHooks-BgdnN8Rj.js → useEventHooks-DlWkui_n.js} +2 -2
- package/dashboard/dist/assets/{useEventHooks-BgdnN8Rj.js.map → useEventHooks-DlWkui_n.js.map} +1 -1
- package/dashboard/dist/assets/{useNamespace-BDsKfT0f.js → useNamespace-BBzCmCIN.js} +2 -2
- package/dashboard/dist/assets/{useNamespace-BDsKfT0f.js.map → useNamespace-BBzCmCIN.js.map} +1 -1
- package/dashboard/dist/assets/{useYamlActivityEvents-CWZwHIlR.js → useYamlActivityEvents-ZS6wRSSc.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-CWZwHIlR.js.map → useYamlActivityEvents-ZS6wRSSc.js.map} +1 -1
- package/dashboard/dist/assets/{users-BqmKVXR1.js → users-Dzh04pRB.js} +2 -2
- package/dashboard/dist/assets/{users-BqmKVXR1.js.map → users-Dzh04pRB.js.map} +1 -1
- package/dashboard/dist/assets/{workflows-Dps45zjk.js → workflows-BTkHs6VT.js} +2 -2
- package/dashboard/dist/assets/workflows-BTkHs6VT.js.map +1 -0
- package/dashboard/dist/assets/{yaml-workflows-DhlTkbvY.js → yaml-workflows-Df8u3lgx.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-DhlTkbvY.js.map → yaml-workflows-Df8u3lgx.js.map} +1 -1
- package/dashboard/dist/index.html +1 -1
- package/docs/api/http/escalations.md +3 -3
- package/docs/api/http/workflows.md +2 -1
- package/docs/api/mcp/admin.md +13 -7
- package/docs/api/sdk/escalations.md +3 -1
- package/docs/api/sdk/workflows.md +3 -2
- package/docs/architecture.md +2 -2
- package/docs/dashboard.md +6 -5
- package/docs/iam.md +3 -3
- package/docs/workflows.md +7 -5
- package/package.json +2 -2
- package/dashboard/dist/assets/OperationsPage-C5phWL0O.js +0 -2
- package/dashboard/dist/assets/OperationsPage-C5phWL0O.js.map +0 -1
- package/dashboard/dist/assets/WorkflowPill-BegV-iRF.js.map +0 -1
- package/dashboard/dist/assets/index-BHS-ubrT.js +0 -6
- package/dashboard/dist/assets/index-BHS-ubrT.js.map +0 -1
- package/dashboard/dist/assets/index-ChniBGqD.js +0 -9
- package/dashboard/dist/assets/index-ChniBGqD.js.map +0 -1
- package/dashboard/dist/assets/workflows-Dps45zjk.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TopicsPage-BHjlFpPN.js","sources":["../../src/pages/topics/TopicsPage.tsx"],"sourcesContent":["import { useState, useMemo } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport {\n Search, LayoutGrid, Radio,\n CheckSquare, GitBranch, AlertTriangle, Zap,\n BookOpen, Bot, AppWindow, Flag,\n} from 'lucide-react';\nimport { useTopics, type TopicCatalogEntry } from '../../api/topics';\nimport { PageHeader } from '../../components/common/layout/PageHeader';\nimport type { LucideIcon } from 'lucide-react';\n\n// ── Category meta ──────────────────────────────────────────────────────────────\n\nconst CATEGORY_META: Record<string, { icon: LucideIcon; color: string }> = {\n task: { icon: CheckSquare, color: 'text-blue-400' },\n workflow: { icon: GitBranch, color: 'text-accent' },\n escalation: { icon: AlertTriangle, color: 'text-amber-400' },\n activity: { icon: Zap, color: 'text-cyan-400' },\n knowledge: { icon: BookOpen, color: 'text-violet-400' },\n agent: { icon: Bot, color: 'text-emerald-400' },\n app: { icon: AppWindow, color: 'text-rose-400' },\n milestone: { icon: Flag, color: 'text-violet-400' },\n};\n\nconst CATEGORY_COLORS: Record<string, string> = {\n task: 'bg-blue-400/15 text-blue-400',\n workflow: 'bg-accent/15 text-accent',\n escalation: 'bg-amber-400/15 text-amber-400',\n activity: 'bg-cyan-400/15 text-cyan-400',\n knowledge: 'bg-violet-400/15 text-violet-400',\n agent: 'bg-emerald-400/15 text-emerald-400',\n app: 'bg-rose-400/15 text-rose-400',\n milestone: 'bg-violet-400/15 text-violet-400',\n};\n\n// ── Page ──────────────────────────────────────────────────────────────────────\n\nexport function TopicsPage() {\n const navigate = useNavigate();\n const [search, setSearch] = useState('');\n const [activeCategory, setActiveCategory] = useState<string | null>(null);\n\n const { data, isLoading } = useTopics({ limit: 500 });\n const allTopics: TopicCatalogEntry[] = data?.topics ?? [];\n\n const categories = useMemo(() => {\n const seen = new Set<string>();\n for (const t of allTopics) seen.add(t.category);\n return Array.from(seen).sort();\n }, [allTopics]);\n\n const grouped = useMemo(() => {\n const q = search.toLowerCase().trim();\n const cats = activeCategory ? [activeCategory] : categories;\n return cats\n .map((cat) => ({\n name: cat,\n topics: allTopics.filter(\n (t) =>\n t.category === cat &&\n (!q || t.topic.toLowerCase().includes(q) || t.description?.toLowerCase().includes(q)),\n ),\n }))\n .filter((g) => g.topics.length > 0);\n }, [allTopics, categories, search, activeCategory]);\n\n return (\n <div>\n <PageHeader title=\"Event Topics\" docsHash=\"#docs:topics.md\" />\n\n {/* Sticky filter bar: category icons + search */}\n {!isLoading && categories.length > 0 && (\n <div className=\"sticky top-0 z-20 bg-surface pt-3 pb-3\">\n <div className=\"bg-[#F7F7F7] rounded-lg px-5 pt-3 pb-3 flex items-center gap-5\">\n <button\n onClick={() => setActiveCategory(null)}\n className={`flex flex-col items-center gap-1 transition-colors ${\n activeCategory === null ? 'text-accent' : 'text-text-quaternary hover:text-text-secondary'\n }`}\n >\n <LayoutGrid className=\"w-3 h-3\" strokeWidth={1.5} />\n <span className=\"text-[9px] font-medium\">All</span>\n </button>\n {categories.map((cat) => {\n const meta = CATEGORY_META[cat] ?? { icon: Radio, color: 'text-text-tertiary' };\n const Icon = meta.icon;\n const isActive = activeCategory === cat;\n return (\n <button\n key={cat}\n onClick={() => setActiveCategory(isActive ? null : cat)}\n className={`flex flex-col items-center gap-1 transition-colors ${\n isActive ? meta.color : 'text-text-quaternary hover:text-text-secondary'\n }`}\n >\n <Icon className=\"w-3 h-3\" strokeWidth={1.5} />\n <span className=\"text-[9px] font-medium capitalize\">{cat}</span>\n </button>\n );\n })}\n <span className=\"flex-1\" />\n <div className=\"relative\">\n <Search className=\"absolute left-0 top-1/2 -translate-y-1/2 w-3 h-3 text-text-quaternary\" />\n <input\n type=\"text\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n placeholder={`Search ${allTopics.length} topics…`}\n className=\"pl-5 py-1 text-sm bg-transparent border-b border-surface-border/60 text-text-primary placeholder:text-text-quaternary focus:outline-none focus:border-accent/50 transition-colors w-48\"\n />\n </div>\n </div>\n </div>\n )}\n\n {/* Topic list */}\n {isLoading ? (\n <div className=\"animate-pulse space-y-8 mt-4\">\n {[1, 2, 3].map((i) => (\n <div key={i}>\n <div className=\"h-4 bg-surface-sunken rounded w-28 mb-4\" />\n <div className=\"space-y-3\">\n {[1, 2, 3, 4].map((j) => (\n <div key={j} className=\"space-y-1.5\">\n <div className=\"h-3 bg-surface-sunken rounded w-64\" />\n <div className=\"h-3 bg-surface-sunken rounded w-full\" />\n </div>\n ))}\n </div>\n </div>\n ))}\n </div>\n ) : grouped.length === 0 ? (\n <p className=\"text-sm text-text-tertiary mt-8\">\n {search || activeCategory ? 'No topics match your filter.' : 'No topics registered yet.'}\n </p>\n ) : (\n <div className=\"space-y-10\">\n {grouped.map(({ name, topics }) => {\n const meta = CATEGORY_META[name] ?? { icon: Radio, color: 'text-text-tertiary' };\n const Icon = meta.icon;\n return (\n <div key={name}>\n <div className=\"sticky top-[78px] z-10 bg-surface flex items-center gap-2 py-2 mb-2 border-b border-surface-border\">\n <Icon className={`w-3 h-3 ${meta.color}`} strokeWidth={1.5} />\n <h2 className=\"section-h2 capitalize\">{name}</h2>\n <span className=\"text-xs text-text-quaternary\">{topics.length}</span>\n </div>\n <div className=\"divide-y divide-surface-border/30\">\n {topics.map((topic) => (\n <TopicRow\n key={topic.topic}\n topic={topic}\n onClick={() => navigate(`/topics/${encodeURIComponent(topic.topic)}`)}\n />\n ))}\n </div>\n </div>\n );\n })}\n </div>\n )}\n </div>\n );\n}\n\n// ── Topic row ──────────────────────────────────────────────────────────────────\n\nfunction TopicRow({ topic, onClick }: { topic: TopicCatalogEntry; onClick: () => void }) {\n const pillCls = CATEGORY_COLORS[topic.category] ?? 'bg-zinc-400/15 text-zinc-400';\n return (\n <div\n role=\"button\"\n tabIndex={0}\n onClick={onClick}\n onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') onClick(); }}\n className=\"group py-3 px-3 -mx-3 rounded-md cursor-pointer transition-colors text-left\"\n >\n <div className=\"flex items-center gap-3 mb-0.5\">\n <Radio className=\"w-3 h-3 shrink-0 text-text-quaternary group-hover:text-text-tertiary transition-colors\" strokeWidth={1.5} />\n <span className=\"text-xs font-mono text-text-primary truncate\">{topic.topic}</span>\n <span className={`ml-1 inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium shrink-0 ${pillCls}`}>\n {topic.category}\n </span>\n {(topic.subscriber_count ?? 0) > 0 && (\n <span className=\"inline-flex items-center justify-center min-w-[18px] px-1 py-0.5 rounded-full text-[10px] font-medium bg-accent/15 text-accent shrink-0\">\n {topic.subscriber_count}\n </span>\n )}\n <span className=\"ml-auto text-[10px] font-mono text-text-quaternary shrink-0\">{topic.source}</span>\n </div>\n {topic.description && (\n <p className=\"pl-6 text-[11px] text-text-tertiary group-hover:text-text-secondary leading-relaxed line-clamp-1 transition-colors\">\n {topic.description}\n </p>\n )}\n </div>\n );\n}\n"],"names":["CATEGORY_META","CheckSquare","GitBranch","AlertTriangle","Zap","BookOpen","Bot","AppWindow","Flag","CATEGORY_COLORS","TopicsPage","navigate","useNavigate","search","setSearch","useState","activeCategory","setActiveCategory","data","isLoading","useTopics","allTopics","categories","useMemo","seen","t","grouped","q","cat","_a","g","jsx","PageHeader","jsxs","LayoutGrid","meta","Radio","Icon","isActive","Search","e","i","j","name","topics","topic","TopicRow","onClick","pillCls"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TopicsPage-SwPAnN2C.js","sources":["../../src/pages/topics/TopicsPage.tsx"],"sourcesContent":["import { useState, useMemo } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport {\n Search, LayoutGrid, Radio,\n CheckSquare, GitBranch, AlertTriangle, Zap,\n BookOpen, Bot, AppWindow, Flag,\n} from 'lucide-react';\nimport { useTopics, type TopicCatalogEntry } from '../../api/topics';\nimport { PageHeader } from '../../components/common/layout/PageHeader';\nimport type { LucideIcon } from 'lucide-react';\n\n// ── Category meta ──────────────────────────────────────────────────────────────\n\nconst CATEGORY_META: Record<string, { icon: LucideIcon; color: string }> = {\n task: { icon: CheckSquare, color: 'text-blue-400' },\n workflow: { icon: GitBranch, color: 'text-accent' },\n escalation: { icon: AlertTriangle, color: 'text-amber-400' },\n activity: { icon: Zap, color: 'text-cyan-400' },\n knowledge: { icon: BookOpen, color: 'text-violet-400' },\n agent: { icon: Bot, color: 'text-emerald-400' },\n app: { icon: AppWindow, color: 'text-rose-400' },\n milestone: { icon: Flag, color: 'text-violet-400' },\n};\n\nconst CATEGORY_COLORS: Record<string, string> = {\n task: 'bg-blue-400/15 text-blue-400',\n workflow: 'bg-accent/15 text-accent',\n escalation: 'bg-amber-400/15 text-amber-400',\n activity: 'bg-cyan-400/15 text-cyan-400',\n knowledge: 'bg-violet-400/15 text-violet-400',\n agent: 'bg-emerald-400/15 text-emerald-400',\n app: 'bg-rose-400/15 text-rose-400',\n milestone: 'bg-violet-400/15 text-violet-400',\n};\n\n// ── Page ──────────────────────────────────────────────────────────────────────\n\nexport function TopicsPage() {\n const navigate = useNavigate();\n const [search, setSearch] = useState('');\n const [activeCategory, setActiveCategory] = useState<string | null>(null);\n\n const { data, isLoading } = useTopics({ limit: 500 });\n const allTopics: TopicCatalogEntry[] = data?.topics ?? [];\n\n const categories = useMemo(() => {\n const seen = new Set<string>();\n for (const t of allTopics) seen.add(t.category);\n return Array.from(seen).sort();\n }, [allTopics]);\n\n const grouped = useMemo(() => {\n const q = search.toLowerCase().trim();\n const cats = activeCategory ? [activeCategory] : categories;\n return cats\n .map((cat) => ({\n name: cat,\n topics: allTopics.filter(\n (t) =>\n t.category === cat &&\n (!q || t.topic.toLowerCase().includes(q) || t.description?.toLowerCase().includes(q)),\n ),\n }))\n .filter((g) => g.topics.length > 0);\n }, [allTopics, categories, search, activeCategory]);\n\n return (\n <div>\n <PageHeader title=\"Event Topics\" docsHash=\"#docs:topics.md\" />\n\n {/* Sticky filter bar: category icons + search */}\n {!isLoading && categories.length > 0 && (\n <div className=\"sticky top-0 z-20 bg-surface pt-3 pb-3\">\n <div className=\"bg-[#F7F7F7] rounded-lg px-5 pt-3 pb-3 flex items-center gap-5\">\n <button\n onClick={() => setActiveCategory(null)}\n className={`flex flex-col items-center gap-1 transition-colors ${\n activeCategory === null ? 'text-accent' : 'text-text-quaternary hover:text-text-secondary'\n }`}\n >\n <LayoutGrid className=\"w-3 h-3\" strokeWidth={1.5} />\n <span className=\"text-[9px] font-medium\">All</span>\n </button>\n {categories.map((cat) => {\n const meta = CATEGORY_META[cat] ?? { icon: Radio, color: 'text-text-tertiary' };\n const Icon = meta.icon;\n const isActive = activeCategory === cat;\n return (\n <button\n key={cat}\n onClick={() => setActiveCategory(isActive ? null : cat)}\n className={`flex flex-col items-center gap-1 transition-colors ${\n isActive ? meta.color : 'text-text-quaternary hover:text-text-secondary'\n }`}\n >\n <Icon className=\"w-3 h-3\" strokeWidth={1.5} />\n <span className=\"text-[9px] font-medium capitalize\">{cat}</span>\n </button>\n );\n })}\n <span className=\"flex-1\" />\n <div className=\"relative\">\n <Search className=\"absolute left-0 top-1/2 -translate-y-1/2 w-3 h-3 text-text-quaternary\" />\n <input\n type=\"text\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n placeholder={`Search ${allTopics.length} topics…`}\n className=\"pl-5 py-1 text-sm bg-transparent border-b border-surface-border/60 text-text-primary placeholder:text-text-quaternary focus:outline-none focus:border-accent/50 transition-colors w-48\"\n />\n </div>\n </div>\n </div>\n )}\n\n {/* Topic list */}\n {isLoading ? (\n <div className=\"animate-pulse space-y-8 mt-4\">\n {[1, 2, 3].map((i) => (\n <div key={i}>\n <div className=\"h-4 bg-surface-sunken rounded w-28 mb-4\" />\n <div className=\"space-y-3\">\n {[1, 2, 3, 4].map((j) => (\n <div key={j} className=\"space-y-1.5\">\n <div className=\"h-3 bg-surface-sunken rounded w-64\" />\n <div className=\"h-3 bg-surface-sunken rounded w-full\" />\n </div>\n ))}\n </div>\n </div>\n ))}\n </div>\n ) : grouped.length === 0 ? (\n <p className=\"text-sm text-text-tertiary mt-8\">\n {search || activeCategory ? 'No topics match your filter.' : 'No topics registered yet.'}\n </p>\n ) : (\n <div className=\"space-y-10\">\n {grouped.map(({ name, topics }) => {\n const meta = CATEGORY_META[name] ?? { icon: Radio, color: 'text-text-tertiary' };\n const Icon = meta.icon;\n return (\n <div key={name}>\n <div className=\"sticky top-[78px] z-10 bg-surface flex items-center gap-2 py-2 mb-2 border-b border-surface-border\">\n <Icon className={`w-3 h-3 ${meta.color}`} strokeWidth={1.5} />\n <h2 className=\"section-h2 capitalize\">{name}</h2>\n <span className=\"text-xs text-text-quaternary\">{topics.length}</span>\n </div>\n <div className=\"divide-y divide-surface-border/30\">\n {topics.map((topic) => (\n <TopicRow\n key={topic.topic}\n topic={topic}\n onClick={() => navigate(`/topics/${encodeURIComponent(topic.topic)}`)}\n />\n ))}\n </div>\n </div>\n );\n })}\n </div>\n )}\n </div>\n );\n}\n\n// ── Topic row ──────────────────────────────────────────────────────────────────\n\nfunction TopicRow({ topic, onClick }: { topic: TopicCatalogEntry; onClick: () => void }) {\n const pillCls = CATEGORY_COLORS[topic.category] ?? 'bg-zinc-400/15 text-zinc-400';\n return (\n <div\n role=\"button\"\n tabIndex={0}\n onClick={onClick}\n onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') onClick(); }}\n className=\"group py-3 px-3 -mx-3 rounded-md cursor-pointer transition-colors text-left\"\n >\n <div className=\"flex items-center gap-3 mb-0.5\">\n <Radio className=\"w-3 h-3 shrink-0 text-text-quaternary group-hover:text-text-tertiary transition-colors\" strokeWidth={1.5} />\n <span className=\"text-xs font-mono text-text-primary truncate\">{topic.topic}</span>\n <span className={`ml-1 inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium shrink-0 ${pillCls}`}>\n {topic.category}\n </span>\n {(topic.subscriber_count ?? 0) > 0 && (\n <span className=\"inline-flex items-center justify-center min-w-[18px] px-1 py-0.5 rounded-full text-[10px] font-medium bg-accent/15 text-accent shrink-0\">\n {topic.subscriber_count}\n </span>\n )}\n <span className=\"ml-auto text-[10px] font-mono text-text-quaternary shrink-0\">{topic.source}</span>\n </div>\n {topic.description && (\n <p className=\"pl-6 text-[11px] text-text-tertiary group-hover:text-text-secondary leading-relaxed line-clamp-1 transition-colors\">\n {topic.description}\n </p>\n )}\n </div>\n );\n}\n"],"names":["CATEGORY_META","CheckSquare","GitBranch","AlertTriangle","Zap","BookOpen","Bot","AppWindow","Flag","CATEGORY_COLORS","TopicsPage","navigate","useNavigate","search","setSearch","useState","activeCategory","setActiveCategory","data","isLoading","useTopics","allTopics","categories","useMemo","seen","t","grouped","q","cat","_a","g","jsx","PageHeader","jsxs","LayoutGrid","meta","Radio","Icon","isActive","Search","e","i","j","name","topics","topic","TopicRow","onClick","pillCls"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{j as r}from"./vendor-query-B2UbickB.js";import{a as t}from"./users-
|
|
2
|
-
//# sourceMappingURL=UserName-
|
|
1
|
+
import{j as r}from"./vendor-query-B2UbickB.js";import{a as t}from"./users-Dzh04pRB.js";function m({userId:a,fallback:s}){const{data:e}=t(a);return e?r.jsx(r.Fragment,{children:e.display_name||e.email||e.external_id}):r.jsx(r.Fragment,{children:s??`${a.slice(0,8)}…`})}export{m as U};
|
|
2
|
+
//# sourceMappingURL=UserName-Ce9gvlT5.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserName-
|
|
1
|
+
{"version":3,"file":"UserName-Ce9gvlT5.js","sources":["../../src/components/common/display/UserName.tsx"],"sourcesContent":["import { useUser } from '../../../api/users';\n\n/**\n * Resolves a user ID to their display name (or email, or truncated ID as fallback).\n * Renders inline — suitable for use inside <span>, <p>, etc.\n */\nexport function UserName({ userId, fallback }: { userId: string; fallback?: string }) {\n const { data: resolved } = useUser(userId);\n\n if (resolved) {\n return <>{resolved.display_name || resolved.email || resolved.external_id}</>;\n }\n\n // Still loading or no record — show fallback or truncated ID\n return <>{fallback ?? `${userId.slice(0, 8)}…`}</>;\n}\n"],"names":["UserName","userId","fallback","resolved","useUser","jsx","Fragment"],"mappings":"uFAMO,SAASA,EAAS,CAAE,OAAAC,EAAQ,SAAAC,GAAmD,CACpF,KAAM,CAAE,KAAMC,GAAaC,EAAQH,CAAM,EAEzC,OAAIE,oBACQ,SAAAA,EAAS,cAAgBA,EAAS,OAASA,EAAS,YAAY,EAIrEE,EAAAA,IAAAC,EAAAA,SAAA,CAAG,YAAY,GAAGL,EAAO,MAAM,EAAG,CAAC,CAAC,GAAA,CAAI,CACjD"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{j as e,a as b}from"./vendor-query-B2UbickB.js";import{a as W,f as P}from"./workflows-
|
|
2
|
-
//# sourceMappingURL=WorkflowExecutionPage-
|
|
1
|
+
import{j as e,a as b}from"./vendor-query-B2UbickB.js";import{a as W,f as P}from"./workflows-BTkHs6VT.js";import{h as R}from"./useEventHooks-DlWkui_n.js";import{u as S}from"./useCollapsedSections-BU5HULGs.js";import{b as L,e as A}from"./tasks-aL0K8WW3.js";import{b as y,D as U,J as N,e as M}from"./index-CKXSKsVZ.js";import{P as V}from"./PageHeader-CFta2VaS.js";import{C as k}from"./CollapsibleSection-CXMPecjj.js";import{L as D}from"./ListToolbar--FkPpYDY.js";import{S as _}from"./StatusBadge-D9MeQHrh.js";import{C as K}from"./CopyableId-blg-gZvT.js";import{L as u,e as Q,c as z}from"./vendor-react-CXumBFUA.js";import{S as B}from"./SwimlaneTimeline-DLVmRrd-.js";import{E as H}from"./EventTable-D_rNmyGG.js";import"./vendor-icons-BaQqUm-e.js";import"./StreamMessageDetail-BYzfjWe_.js";import"./FilterBar-BQ2JGg8U.js";function m({label:t,value:a,mono:s,truncate:r,children:n}){return e.jsxs("div",{children:[e.jsx("p",{className:"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-1",children:t}),n||e.jsx("p",{className:`text-xs text-text-primary ${s?"font-mono":""} ${r?"truncate":""}`,title:r?a:void 0,children:a})]})}function J(t){const a=t.lastIndexOf("-");return a<=0?{taskQueue:t,workflowType:t}:{taskQueue:t.substring(0,a),workflowType:t.substring(a+1)}}function O({execution:t,task:a,escalations:s}){const r=t.parent_workflow_id,l=a&&a.workflow_id===t.workflow_id?a.parent_workflow_id:null,d=r||l||null,c=d&&d!==t.workflow_id?d:null,{taskQueue:o,workflowType:p}=J(t.workflow_type);return e.jsxs("div",{className:"bg-surface-sunken/50 rounded-md px-6 py-5 mb-6",children:[e.jsxs("div",{className:"grid grid-cols-2 sm:grid-cols-4 gap-y-4 gap-x-8",children:[e.jsx(K,{label:"Workflow Type",value:p,href:`/workflows/executions?entity=${encodeURIComponent(p)}`}),e.jsx(m,{label:"Task Queue",value:o,mono:!0}),e.jsx(m,{label:"Start Time",children:t.start_time?e.jsx(y,{date:t.start_time,format:"datetime",className:"text-text-primary"}):e.jsx("span",{className:"text-xs text-text-tertiary",children:"--"})}),e.jsx(m,{label:"End Time",children:t.close_time?e.jsx(y,{date:t.close_time,format:"datetime",className:"text-text-primary"}):e.jsx("span",{className:"text-xs text-text-tertiary",children:"--"})}),e.jsx(m,{label:"Duration",children:e.jsx(U,{ms:t.duration_ms,className:"font-mono text-text-primary"})}),e.jsx(m,{label:"History Size",value:`${t.summary.total_events} events`}),e.jsx(m,{label:"Activities",value:`${t.summary.activities.completed} / ${t.summary.activities.total}`}),e.jsx(m,{label:"Workflow ID",value:t.workflow_id,mono:!0,truncate:!0})]}),(c||s&&s.length>0)&&e.jsxs("div",{className:"mt-5 pt-4 border-t border-surface-border/50 space-y-3",children:[c&&e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary shrink-0",children:"Parent"}),e.jsx(u,{to:`/workflows/executions/${c}`,className:"text-xs font-mono text-accent hover:underline truncate",title:c,children:c})]}),!1,s&&s.length>0&&e.jsxs("div",{className:"flex items-start gap-2",children:[e.jsx("span",{className:"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary shrink-0 mt-0.5",children:s.length===1?"Escalation":"Escalations"}),e.jsx("div",{className:"flex flex-wrap gap-x-4 gap-y-1",children:s.map(f=>e.jsxs(u,{to:`/escalations/detail/${f.id}`,className:"inline-flex items-center gap-1.5 text-xs font-mono text-accent hover:underline",children:[e.jsx("span",{children:f.type}),e.jsx(_,{status:f.status})]},f.id))})]})]})]})}function F(t){var r;const a=t.events.find(n=>n.event_type==="workflow_execution_started"),s=(r=a==null?void 0:a.attributes)==null?void 0:r.input;return s&&typeof s=="object"?s:null}function q({execution:t}){const a=F(t),s=t.result,r=(s==null?void 0:s.data)??s??null;return!a&&!r?null:e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4 mb-6",children:[a!==null&&e.jsx("div",{children:e.jsx(N,{data:a,label:"Input Envelope"})}),r!==null&&e.jsx("div",{children:e.jsx(N,{data:r,label:"Result"})})]})}function Z({isRunning:t,hasToolCalls:a,workflowId:s,onAction:r}){const[n,l]=b.useState(!1),d=b.useRef(null);return b.useEffect(()=>{if(!n)return;const c=o=>{d.current&&!d.current.contains(o.target)&&l(!1)};return document.addEventListener("mousedown",c),()=>document.removeEventListener("mousedown",c)},[n]),e.jsxs("div",{className:"relative",ref:d,children:[e.jsx("button",{onClick:()=>l(!n),className:"btn-primary text-xs",children:"Actions"}),n&&e.jsxs("div",{className:"absolute right-0 mt-1 w-44 bg-surface-raised border border-surface-border rounded-md shadow-lg z-10",children:[e.jsx("button",{onClick:()=>{r("restart"),l(!1)},className:"block w-full text-left px-4 py-2 text-xs text-text-secondary hover:bg-surface-hover",children:"Restart Workflow"}),t&&e.jsx("button",{onClick:()=>{r("terminate"),l(!1)},className:"block w-full text-left px-4 py-2 text-xs text-status-error hover:bg-surface-hover",children:"Terminate"}),a&&e.jsx(u,{to:`/mcp/queries/${s}?step=3`,className:"block w-full text-left px-4 py-2 text-xs text-accent hover:bg-surface-hover",onClick:()=>l(!1),children:"Compile into Pipeline"}),e.jsx(u,{to:`/mcp/executions/${encodeURIComponent(s)}?namespace=durable`,className:"block w-full text-left px-4 py-2 text-xs text-text-secondary hover:bg-surface-hover",onClick:()=>l(!1),children:"View Pipeline Execution"}),e.jsx(u,{to:`/admin/streams?source=worker&jid=${encodeURIComponent(s)}`,className:"block w-full text-left px-4 py-2 text-xs text-text-secondary hover:bg-surface-hover",onClick:()=>l(!1),children:"Worker Messages"}),e.jsx(u,{to:`/admin/streams?source=engine&jid=${encodeURIComponent(s)}`,className:"block w-full text-left px-4 py-2 text-xs text-text-secondary hover:bg-surface-hover",onClick:()=>l(!1),children:"Engine Messages"})]})]})}function pe(){const{workflowId:t}=Q();R(t);const a="Workflow Execution",{data:s,isLoading:r,error:n,refetch:l,isFetching:d}=W(t),{data:c}=L(t),{data:o}=A(t),{data:p}=M(t),f=z(),h=P(),{isCollapsed:j,toggle:w}=S("workflow-execution"),C=x=>{var i;if(x==="terminate")confirm("Are you sure you want to terminate this workflow?")&&h.mutate(t);else if(x==="restart"&&s){const I=s.workflow_id.replace(/-[A-Za-z0-9_-]{20,}$/,""),v=s.events.find($=>$.event_type==="workflow_execution_started"),g=(i=v==null?void 0:v.attributes)==null?void 0:i.input;g&&sessionStorage.setItem("lt:invoke:prefill",JSON.stringify(g)),f(`/workflows/start?type=${encodeURIComponent(I)}&mode=now`)}};if(r)return e.jsxs("div",{className:"animate-pulse space-y-4",children:[e.jsx("div",{className:"h-8 bg-surface-sunken rounded w-64"}),e.jsx("div",{className:"h-60 bg-surface-sunken rounded"})]});if(n||!s){const x=(n==null?void 0:n.message)??"",i=x.includes("expired")||x.includes("no longer available");return e.jsxs("div",{children:[e.jsx(u,{to:"/workflows/executions",className:"text-xs text-text-tertiary hover:text-text-primary",children:"← Workflows"}),e.jsxs("div",{className:"mt-4 text-center py-8",children:[e.jsx("p",{className:"text-sm text-text-primary mb-1",children:i?"Execution data is no longer available":n?"Unable to load execution":"Execution not found"}),e.jsx("p",{className:"text-xs text-text-tertiary",children:i?"This workflow's underlying job has expired. The task record is preserved, but the execution timeline has been cleaned up.":x||"The workflow could not be resolved."})]})]})}const E=s.status!=="completed"&&s.status!=="failed",T=s.status==="completed"&&s.events.some(x=>{if(x.event_type!=="activity_task_completed")return!1;const i=x.attributes.activity_type;return i==="callDbTool"||i==="callVisionTool"||i==="callMcpTool"||(i==null?void 0:i.startsWith("mcp_"))});return e.jsxs("div",{children:[e.jsx(V,{title:a,actions:e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(D,{onRefresh:()=>l(),isFetching:d,apiPath:`/workflow-states/${t}/execution`}),e.jsx(_,{status:s.status}),e.jsx(Z,{isRunning:E,hasToolCalls:T,workflowId:t,onAction:C})]})}),e.jsx(O,{execution:s,task:c,childTasks:o==null?void 0:o.tasks,escalations:p==null?void 0:p.escalations}),h.error&&e.jsx("div",{className:"py-3 mb-6",children:e.jsxs("p",{className:"text-xs text-status-error",children:["Terminate failed: ",h.error.message]})}),e.jsxs("div",{className:"space-y-6",children:[e.jsx(k,{title:"Details",sectionKey:"details",isCollapsed:j("details"),onToggle:w,contentClassName:"mt-4 ml-9",children:e.jsx(q,{execution:s})}),e.jsx(k,{title:"Execution Timeline",sectionKey:"timeline",isCollapsed:j("timeline"),onToggle:w,contentClassName:"mt-4 ml-9",children:e.jsx(B,{events:s.events,childTasks:o==null?void 0:o.tasks,jid:t,appId:"durable"})}),e.jsx(k,{title:"Events",sectionKey:"events",isCollapsed:j("events"),onToggle:w,contentClassName:"mt-4 ml-9",children:e.jsx(H,{events:s.events,childTasks:o==null?void 0:o.tasks,jid:t,appId:"durable"})})]})]})}export{pe as WorkflowExecutionPage};
|
|
2
|
+
//# sourceMappingURL=WorkflowExecutionPage-BI9NzeaH.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkflowExecutionPage-DwzLKTkt.js","sources":["../../src/pages/workflows/workflow-execution/ExecutionHeader.tsx","../../src/pages/workflows/workflow-execution/ExecutionInputResult.tsx","../../src/pages/workflows/WorkflowExecutionPage.tsx"],"sourcesContent":["import { Link } from 'react-router-dom';\nimport { StatusBadge } from '../../../components/common/display/StatusBadge';\nimport { CopyableId } from '../../../components/common/display/CopyableId';\nimport type { WorkflowExecution, LTTaskRecord, LTEscalationRecord } from '../../../api/types';\nimport { DateValue } from '../../../components/common/display/DateValue';\nimport { DurationValue } from '../../../components/common/display/DurationValue';\n\nfunction MetadataField({\n label,\n value,\n mono,\n truncate,\n children,\n}: {\n label: string;\n value?: string;\n mono?: boolean;\n truncate?: boolean;\n children?: React.ReactNode;\n}) {\n return (\n <div>\n <p className=\"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-1\">\n {label}\n </p>\n {children || (\n <p\n className={`text-xs text-text-primary ${mono ? 'font-mono' : ''} ${truncate ? 'truncate' : ''}`}\n title={truncate ? value : undefined}\n >\n {value}\n </p>\n )}\n </div>\n );\n}\n\n/**\n * Split a HotMesh compound entity key (taskQueue-workflowName) on the last '-'.\n * Workflow names are camelCase, so the last segment is always the workflow type.\n */\nfunction splitEntityKey(compound: string): { taskQueue: string; workflowType: string } {\n const lastDash = compound.lastIndexOf('-');\n if (lastDash <= 0) return { taskQueue: compound, workflowType: compound };\n return {\n taskQueue: compound.substring(0, lastDash),\n workflowType: compound.substring(lastDash + 1),\n };\n}\n\ninterface ExecutionHeaderProps {\n execution: WorkflowExecution;\n task?: LTTaskRecord | null;\n childTasks?: LTTaskRecord[];\n escalations?: LTEscalationRecord[];\n}\n\nexport function ExecutionHeader({ execution, task, escalations }: ExecutionHeaderProps) {\n // Determine parent relationship — prefer execution-level pj (from HotMesh\n // raw state), fall back to lt_tasks record. When the SDK adds\n // parent_workflow_id natively, it flows through automatically.\n const executionParent = (execution as any).parent_workflow_id as string | undefined;\n const isLeaf = task && task.workflow_id === execution.workflow_id;\n const taskParent = isLeaf ? task.parent_workflow_id : null;\n const rawParent = executionParent || taskParent || null;\n // Filter self-references — cron-invoked workflows store themselves as parent\n const parentWorkflowId = rawParent && rawParent !== execution.workflow_id ? rawParent : null;\n\n // Split compound HotMesh keys into separate task queue / workflow type\n const { taskQueue, workflowType } = splitEntityKey(execution.workflow_type);\n\n return (\n <div className=\"bg-surface-sunken/50 rounded-md px-6 py-5 mb-6\">\n\n <div className=\"grid grid-cols-2 sm:grid-cols-4 gap-y-4 gap-x-8\">\n <CopyableId label=\"Workflow Type\" value={workflowType} href={`/workflows/executions?entity=${encodeURIComponent(workflowType)}`} />\n <MetadataField label=\"Task Queue\" value={taskQueue} mono />\n <MetadataField label=\"Start Time\">\n {execution.start_time\n ? <DateValue date={execution.start_time} format=\"datetime\" className=\"text-text-primary\" />\n : <span className=\"text-xs text-text-tertiary\">--</span>}\n </MetadataField>\n <MetadataField label=\"End Time\">\n {execution.close_time\n ? <DateValue date={execution.close_time} format=\"datetime\" className=\"text-text-primary\" />\n : <span className=\"text-xs text-text-tertiary\">--</span>}\n </MetadataField>\n <MetadataField label=\"Duration\">\n <DurationValue ms={execution.duration_ms} className=\"font-mono text-text-primary\" />\n </MetadataField>\n <MetadataField\n label=\"History Size\"\n value={`${execution.summary.total_events} events`}\n />\n <MetadataField\n label=\"Activities\"\n value={`${execution.summary.activities.completed} / ${execution.summary.activities.total}`}\n />\n <MetadataField\n label=\"Workflow ID\"\n value={execution.workflow_id}\n mono\n truncate\n />\n </div>\n\n {/* Related links */}\n {(parentWorkflowId || (escalations && escalations.length > 0)) && (\n <div className=\"mt-5 pt-4 border-t border-surface-border/50 space-y-3\">\n {/* Parent navigation */}\n {parentWorkflowId && (\n <div className=\"flex items-center gap-2\">\n <span className=\"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary shrink-0\">\n Parent\n </span>\n <Link\n to={`/workflows/executions/${parentWorkflowId}`}\n className=\"text-xs font-mono text-accent hover:underline truncate\"\n title={parentWorkflowId}\n >\n {parentWorkflowId}\n </Link>\n </div>\n )}\n\n {/* Process link — deep-links to process list filtered by this workflow */}\n {false && (\n <div className=\"flex items-center gap-2\">\n <span className=\"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary shrink-0\">\n Process\n </span>\n <Link\n to={`/processes/all?search=${encodeURIComponent(execution.workflow_id)}`}\n className=\"text-xs font-mono text-accent hover:underline truncate\"\n >\n Find in Processes\n </Link>\n </div>\n )}\n\n {/* Escalation links */}\n {escalations && escalations.length > 0 && (\n <div className=\"flex items-start gap-2\">\n <span className=\"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary shrink-0 mt-0.5\">\n {escalations.length === 1 ? 'Escalation' : 'Escalations'}\n </span>\n <div className=\"flex flex-wrap gap-x-4 gap-y-1\">\n {escalations.map((esc) => (\n <Link\n key={esc.id}\n to={`/escalations/detail/${esc.id}`}\n className=\"inline-flex items-center gap-1.5 text-xs font-mono text-accent hover:underline\"\n >\n <span>{esc.type}</span>\n <StatusBadge status={esc.status} />\n </Link>\n ))}\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n );\n}\n","import { JsonViewer } from '../../../components/common/data/JsonViewer';\nimport type { WorkflowExecution } from '../../../api/types';\n\ninterface ExecutionInputResultProps {\n execution: WorkflowExecution;\n}\n\n/**\n * Extract the workflow input envelope from the workflow_execution_started event.\n * HotMesh 0.13.0+ includes the actual trigger arguments (the envelope passed\n * to startWorkflow) in the start event's `input` attribute.\n */\nfunction extractInput(execution: WorkflowExecution): Record<string, unknown> | null {\n const startEvent = execution.events.find(\n (e) => e.event_type === 'workflow_execution_started',\n );\n const input = (startEvent?.attributes as any)?.input;\n return input && typeof input === 'object' ? input : null;\n}\n\nexport function ExecutionInputResult({ execution }: ExecutionInputResultProps) {\n const input = extractInput(execution);\n\n // Result: unwrap the workflow return — the `data` field is what LT users care about\n const rawResult = execution.result as Record<string, unknown> | null | undefined;\n const result = rawResult?.data ?? rawResult ?? null;\n\n if (!input && !result) return null;\n\n return (\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4 mb-6\">\n {input !== null && (\n <div>\n <JsonViewer data={input} label=\"Input Envelope\" />\n </div>\n )}\n {result !== null && (\n <div>\n <JsonViewer data={result} label=\"Result\" />\n </div>\n )}\n </div>\n );\n}\n","import { useState, useRef, useEffect } from 'react';\nimport { useParams, useNavigate, Link } from 'react-router-dom';\nimport { useWorkflowExecution, useTerminateWorkflow } from '../../api/workflows';\nimport { useWorkflowDetailEvents } from '../../hooks/useEventHooks';\nimport { useCollapsedSections } from '../../hooks/useCollapsedSections';\nimport { useTaskByWorkflowId, useChildTasks } from '../../api/tasks';\nimport { useEscalationsByWorkflowId } from '../../api/escalations';\n\nimport { PageHeader } from '../../components/common/layout/PageHeader';\nimport { CollapsibleSection } from '../../components/common/layout/CollapsibleSection';\nimport { ListToolbar } from '../../components/common/data/ListToolbar';\nimport { StatusBadge } from '../../components/common/display/StatusBadge';\n\nimport { ExecutionHeader } from './workflow-execution/ExecutionHeader';\nimport { ExecutionInputResult } from './workflow-execution/ExecutionInputResult';\nimport { SwimlaneTimeline } from './workflow-execution/SwimlaneTimeline';\nimport { EventTable } from './workflow-execution/EventTable';\n\nfunction ActionsDropdown({ isRunning, hasToolCalls, workflowId, onAction }: {\n isRunning: boolean;\n hasToolCalls: boolean;\n workflowId: string;\n onAction: (action: 'restart' | 'terminate') => void;\n}) {\n const [open, setOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!open) return;\n const handler = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false);\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, [open]);\n\n return (\n <div className=\"relative\" ref={ref}>\n <button onClick={() => setOpen(!open)} className=\"btn-primary text-xs\">\n Actions\n </button>\n {open && (\n <div className=\"absolute right-0 mt-1 w-44 bg-surface-raised border border-surface-border rounded-md shadow-lg z-10\">\n <button\n onClick={() => { onAction('restart'); setOpen(false); }}\n className=\"block w-full text-left px-4 py-2 text-xs text-text-secondary hover:bg-surface-hover\"\n >\n Restart Workflow\n </button>\n {isRunning && (\n <button\n onClick={() => { onAction('terminate'); setOpen(false); }}\n className=\"block w-full text-left px-4 py-2 text-xs text-status-error hover:bg-surface-hover\"\n >\n Terminate\n </button>\n )}\n {hasToolCalls && (\n <Link\n to={`/mcp/queries/${workflowId}?step=3`}\n className=\"block w-full text-left px-4 py-2 text-xs text-accent hover:bg-surface-hover\"\n onClick={() => setOpen(false)}\n >\n Compile into Pipeline\n </Link>\n )}\n <Link\n to={`/mcp/executions/${encodeURIComponent(workflowId)}?namespace=durable`}\n className=\"block w-full text-left px-4 py-2 text-xs text-text-secondary hover:bg-surface-hover\"\n onClick={() => setOpen(false)}\n >\n View Pipeline Execution\n </Link>\n <Link\n to={`/admin/streams?source=worker&jid=${encodeURIComponent(workflowId)}`}\n className=\"block w-full text-left px-4 py-2 text-xs text-text-secondary hover:bg-surface-hover\"\n onClick={() => setOpen(false)}\n >\n Worker Messages\n </Link>\n <Link\n to={`/admin/streams?source=engine&jid=${encodeURIComponent(workflowId)}`}\n className=\"block w-full text-left px-4 py-2 text-xs text-text-secondary hover:bg-surface-hover\"\n onClick={() => setOpen(false)}\n >\n Engine Messages\n </Link>\n </div>\n )}\n </div>\n );\n}\n\nexport function WorkflowExecutionPage() {\n const { workflowId } = useParams<{ workflowId: string }>();\n useWorkflowDetailEvents(workflowId);\n\n const executionTitle = 'Workflow Execution';\n const { data: execution, isLoading, error, refetch, isFetching } = useWorkflowExecution(workflowId!);\n const { data: task } = useTaskByWorkflowId(workflowId!);\n const { data: childTasksData } = useChildTasks(workflowId!);\n const { data: escalationsData } = useEscalationsByWorkflowId(workflowId);\n const navigate = useNavigate();\n const terminateMutation = useTerminateWorkflow();\n const { isCollapsed, toggle } = useCollapsedSections('workflow-execution');\n\n const handleAction = (action: 'restart' | 'terminate') => {\n if (action === 'terminate') {\n if (confirm('Are you sure you want to terminate this workflow?')) {\n terminateMutation.mutate(workflowId!);\n }\n } else if (action === 'restart' && execution) {\n // Extract entity from workflow_id (format: {entity}-{guid})\n const entity = execution.workflow_id.replace(/-[A-Za-z0-9_-]{20,}$/, '');\n // Extract original input from the started event\n const startEvent = execution.events.find((e) => e.event_type === 'workflow_execution_started');\n const input = (startEvent?.attributes as any)?.input;\n if (input) {\n sessionStorage.setItem('lt:invoke:prefill', JSON.stringify(input));\n }\n navigate(`/workflows/start?type=${encodeURIComponent(entity)}&mode=now`);\n }\n };\n\n if (isLoading) {\n return (\n <div className=\"animate-pulse space-y-4\">\n <div className=\"h-8 bg-surface-sunken rounded w-64\" />\n <div className=\"h-60 bg-surface-sunken rounded\" />\n </div>\n );\n }\n\n if (error || !execution) {\n const msg = (error as Error)?.message ?? '';\n const isExpired = msg.includes('expired') || msg.includes('no longer available');\n\n return (\n <div>\n <Link to=\"/workflows/executions\" className=\"text-xs text-text-tertiary hover:text-text-primary\">\n ← Workflows\n </Link>\n <div className=\"mt-4 text-center py-8\">\n <p className=\"text-sm text-text-primary mb-1\">\n {isExpired\n ? 'Execution data is no longer available'\n : error\n ? 'Unable to load execution'\n : 'Execution not found'}\n </p>\n <p className=\"text-xs text-text-tertiary\">\n {isExpired\n ? \"This workflow's underlying job has expired. The task record is preserved, but the execution timeline has been cleaned up.\"\n : msg || 'The workflow could not be resolved.'}\n </p>\n </div>\n </div>\n );\n }\n\n const isRunning = execution.status !== 'completed' && execution.status !== 'failed';\n const hasToolCalls = execution.status === 'completed' && execution.events.some(\n (e) => {\n if (e.event_type !== 'activity_task_completed') return false;\n const actType = (e.attributes as any).activity_type;\n return actType === 'callDbTool' || actType === 'callVisionTool' || actType === 'callMcpTool' || actType?.startsWith('mcp_');\n },\n );\n\n return (\n <div>\n <PageHeader\n title={executionTitle}\n actions={\n <div className=\"flex items-center gap-3\">\n <ListToolbar\n onRefresh={() => refetch()}\n isFetching={isFetching}\n apiPath={`/workflow-states/${workflowId}/execution`}\n />\n <StatusBadge status={execution.status} />\n <ActionsDropdown\n isRunning={isRunning}\n hasToolCalls={hasToolCalls}\n workflowId={workflowId!}\n onAction={handleAction}\n />\n </div>\n }\n />\n\n <ExecutionHeader\n execution={execution}\n task={task}\n childTasks={childTasksData?.tasks}\n escalations={escalationsData?.escalations}\n />\n\n {terminateMutation.error && (\n <div className=\"py-3 mb-6\">\n <p className=\"text-xs text-status-error\">\n Terminate failed: {terminateMutation.error.message}\n </p>\n </div>\n )}\n\n\n <div className=\"space-y-6\">\n <CollapsibleSection title=\"Details\" sectionKey=\"details\" isCollapsed={isCollapsed('details')} onToggle={toggle} contentClassName=\"mt-4 ml-9\">\n <ExecutionInputResult execution={execution} />\n </CollapsibleSection>\n\n <CollapsibleSection title=\"Execution Timeline\" sectionKey=\"timeline\" isCollapsed={isCollapsed('timeline')} onToggle={toggle} contentClassName=\"mt-4 ml-9\">\n <SwimlaneTimeline\n events={execution.events}\n childTasks={childTasksData?.tasks}\n jid={workflowId}\n appId=\"durable\"\n />\n </CollapsibleSection>\n\n <CollapsibleSection title=\"Events\" sectionKey=\"events\" isCollapsed={isCollapsed('events')} onToggle={toggle} contentClassName=\"mt-4 ml-9\">\n <EventTable\n events={execution.events}\n childTasks={childTasksData?.tasks}\n jid={workflowId}\n appId=\"durable\"\n />\n </CollapsibleSection>\n </div>\n </div>\n );\n}\n"],"names":["MetadataField","label","value","mono","truncate","children","jsx","splitEntityKey","compound","lastDash","ExecutionHeader","execution","task","escalations","executionParent","taskParent","rawParent","parentWorkflowId","taskQueue","workflowType","jsxs","CopyableId","DateValue","DurationValue","Link","esc","StatusBadge","extractInput","startEvent","e","input","_a","ExecutionInputResult","rawResult","result","JsonViewer","ActionsDropdown","isRunning","hasToolCalls","workflowId","onAction","open","setOpen","useState","ref","useRef","useEffect","handler","WorkflowExecutionPage","useParams","useWorkflowDetailEvents","executionTitle","isLoading","error","refetch","isFetching","useWorkflowExecution","useTaskByWorkflowId","childTasksData","useChildTasks","escalationsData","useEscalationsByWorkflowId","navigate","useNavigate","terminateMutation","useTerminateWorkflow","isCollapsed","toggle","useCollapsedSections","handleAction","action","entity","msg","isExpired","actType","PageHeader","ListToolbar","CollapsibleSection","SwimlaneTimeline","EventTable"],"mappings":"izBAOA,SAASA,EAAc,CACrB,MAAAC,EACA,MAAAC,EACA,KAAAC,EACA,SAAAC,EACA,SAAAC,CACF,EAMG,CACD,cACG,MAAA,CACC,SAAA,CAAAC,EAAAA,IAAC,IAAA,CAAE,UAAU,8EACV,SAAAL,EACH,EACCI,GACCC,EAAAA,IAAC,IAAA,CACC,UAAW,6BAA6BH,EAAO,YAAc,EAAE,IAAIC,EAAW,WAAa,EAAE,GAC7F,MAAOA,EAAWF,EAAQ,OAEzB,SAAAA,CAAA,CAAA,CACH,EAEJ,CAEJ,CAMA,SAASK,EAAeC,EAA+D,CACrF,MAAMC,EAAWD,EAAS,YAAY,GAAG,EACzC,OAAIC,GAAY,EAAU,CAAE,UAAWD,EAAU,aAAcA,CAAA,EACxD,CACL,UAAWA,EAAS,UAAU,EAAGC,CAAQ,EACzC,aAAcD,EAAS,UAAUC,EAAW,CAAC,CAAA,CAEjD,CASO,SAASC,EAAgB,CAAE,UAAAC,EAAW,KAAAC,EAAM,YAAAC,GAAqC,CAItF,MAAMC,EAAmBH,EAAkB,mBAErCI,EADSH,GAAQA,EAAK,cAAgBD,EAAU,YAC1BC,EAAK,mBAAqB,KAChDI,EAAYF,GAAmBC,GAAc,KAE7CE,EAAmBD,GAAaA,IAAcL,EAAU,YAAcK,EAAY,KAGlF,CAAE,UAAAE,EAAW,aAAAC,CAAA,EAAiBZ,EAAeI,EAAU,aAAa,EAE1E,OACES,EAAAA,KAAC,MAAA,CAAI,UAAU,iDAEb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,kDACb,SAAA,CAAAd,EAAAA,IAACe,EAAA,CAAW,MAAM,gBAAgB,MAAOF,EAAc,KAAM,gCAAgC,mBAAmBA,CAAY,CAAC,EAAA,CAAI,QAChInB,EAAA,CAAc,MAAM,aAAa,MAAOkB,EAAW,KAAI,GAAC,EACzDZ,EAAAA,IAACN,GAAc,MAAM,aAClB,WAAU,WACPM,EAAAA,IAACgB,GAAU,KAAMX,EAAU,WAAY,OAAO,WAAW,UAAU,mBAAA,CAAoB,QACtF,OAAA,CAAK,UAAU,6BAA6B,SAAA,IAAA,CAAE,CAAA,CACrD,EACAL,EAAAA,IAACN,GAAc,MAAM,WAClB,WAAU,WACPM,EAAAA,IAACgB,GAAU,KAAMX,EAAU,WAAY,OAAO,WAAW,UAAU,mBAAA,CAAoB,QACtF,OAAA,CAAK,UAAU,6BAA6B,SAAA,IAAA,CAAE,CAAA,CACrD,EACAL,EAAAA,IAACN,EAAA,CAAc,MAAM,WACnB,SAAAM,EAAAA,IAACiB,EAAA,CAAc,GAAIZ,EAAU,YAAa,UAAU,6BAAA,CAA8B,CAAA,CACpF,EACAL,EAAAA,IAACN,EAAA,CACC,MAAM,eACN,MAAO,GAAGW,EAAU,QAAQ,YAAY,SAAA,CAAA,EAE1CL,EAAAA,IAACN,EAAA,CACC,MAAM,aACN,MAAO,GAAGW,EAAU,QAAQ,WAAW,SAAS,MAAMA,EAAU,QAAQ,WAAW,KAAK,EAAA,CAAA,EAE1FL,EAAAA,IAACN,EAAA,CACC,MAAM,cACN,MAAOW,EAAU,YACjB,KAAI,GACJ,SAAQ,EAAA,CAAA,CACV,EACF,GAGEM,GAAqBJ,GAAeA,EAAY,OAAS,IAC3DO,EAAAA,KAAC,MAAA,CAAI,UAAU,wDAEV,SAAA,CAAAH,GACCG,EAAAA,KAAC,MAAA,CAAI,UAAU,0BACb,SAAA,CAAAd,EAAAA,IAAC,OAAA,CAAK,UAAU,kFAAkF,SAAA,SAElG,EACAA,EAAAA,IAACkB,EAAA,CACC,GAAI,yBAAyBP,CAAgB,GAC7C,UAAU,yDACV,MAAOA,EAEN,SAAAA,CAAA,CAAA,CACH,EACF,EAID,GAeAJ,GAAeA,EAAY,OAAS,GACnCO,EAAAA,KAAC,MAAA,CAAI,UAAU,yBACb,SAAA,CAAAd,EAAAA,IAAC,QAAK,UAAU,yFACb,WAAY,SAAW,EAAI,aAAe,aAAA,CAC7C,QACC,MAAA,CAAI,UAAU,iCACZ,SAAAO,EAAY,IAAKY,GAChBL,EAAAA,KAACI,EAAA,CAEC,GAAI,uBAAuBC,EAAI,EAAE,GACjC,UAAU,iFAEV,SAAA,CAAAnB,EAAAA,IAAC,OAAA,CAAM,WAAI,IAAA,CAAK,EAChBA,EAAAA,IAACoB,EAAA,CAAY,OAAQD,EAAI,MAAA,CAAQ,CAAA,CAAA,EAL5BA,EAAI,EAAA,CAOZ,CAAA,CACH,CAAA,CAAA,CACF,CAAA,CAAA,CAEN,CAAA,EAEF,CAEJ,CCxJA,SAASE,EAAahB,EAA8D,OAClF,MAAMiB,EAAajB,EAAU,OAAO,KACjCkB,GAAMA,EAAE,aAAe,4BAAA,EAEpBC,GAASC,EAAAH,GAAA,YAAAA,EAAY,aAAZ,YAAAG,EAAgC,MAC/C,OAAOD,GAAS,OAAOA,GAAU,SAAWA,EAAQ,IACtD,CAEO,SAASE,EAAqB,CAAE,UAAArB,GAAwC,CAC7E,MAAMmB,EAAQH,EAAahB,CAAS,EAG9BsB,EAAYtB,EAAU,OACtBuB,GAASD,GAAA,YAAAA,EAAW,OAAQA,GAAa,KAE/C,MAAI,CAACH,GAAS,CAACI,EAAe,KAG5Bd,EAAAA,KAAC,MAAA,CAAI,UAAU,6CACZ,SAAA,CAAAU,IAAU,YACR,MAAA,CACC,SAAAxB,EAAAA,IAAC6B,GAAW,KAAML,EAAO,MAAM,gBAAA,CAAiB,CAAA,CAClD,EAEDI,IAAW,MACV5B,EAAAA,IAAC,MAAA,CACC,SAAAA,EAAAA,IAAC6B,GAAW,KAAMD,EAAQ,MAAM,QAAA,CAAS,CAAA,CAC3C,CAAA,EAEJ,CAEJ,CCzBA,SAASE,EAAgB,CAAE,UAAAC,EAAW,aAAAC,EAAc,WAAAC,EAAY,SAAAC,GAK7D,CACD,KAAM,CAACC,EAAMC,CAAO,EAAIC,EAAAA,SAAS,EAAK,EAChCC,EAAMC,EAAAA,OAAuB,IAAI,EAEvCC,OAAAA,EAAAA,UAAU,IAAM,CACd,GAAI,CAACL,EAAM,OACX,MAAMM,EAAWlB,GAAkB,CAC7Be,EAAI,SAAW,CAACA,EAAI,QAAQ,SAASf,EAAE,MAAc,GAAGa,EAAQ,EAAK,CAC3E,EACA,gBAAS,iBAAiB,YAAaK,CAAO,EACvC,IAAM,SAAS,oBAAoB,YAAaA,CAAO,CAChE,EAAG,CAACN,CAAI,CAAC,EAGPrB,EAAAA,KAAC,MAAA,CAAI,UAAU,WAAW,IAAAwB,EACxB,SAAA,CAAAtC,EAAAA,IAAC,SAAA,CAAO,QAAS,IAAMoC,EAAQ,CAACD,CAAI,EAAG,UAAU,sBAAsB,SAAA,SAAA,CAEvE,EACCA,GACCrB,EAAAA,KAAC,MAAA,CAAI,UAAU,sGACb,SAAA,CAAAd,EAAAA,IAAC,SAAA,CACC,QAAS,IAAM,CAAEkC,EAAS,SAAS,EAAGE,EAAQ,EAAK,CAAG,EACtD,UAAU,sFACX,SAAA,kBAAA,CAAA,EAGAL,GACC/B,EAAAA,IAAC,SAAA,CACC,QAAS,IAAM,CAAEkC,EAAS,WAAW,EAAGE,EAAQ,EAAK,CAAG,EACxD,UAAU,oFACX,SAAA,WAAA,CAAA,EAIFJ,GACChC,EAAAA,IAACkB,EAAA,CACC,GAAI,gBAAgBe,CAAU,UAC9B,UAAU,8EACV,QAAS,IAAMG,EAAQ,EAAK,EAC7B,SAAA,uBAAA,CAAA,EAIHpC,EAAAA,IAACkB,EAAA,CACC,GAAI,mBAAmB,mBAAmBe,CAAU,CAAC,qBACrD,UAAU,sFACV,QAAS,IAAMG,EAAQ,EAAK,EAC7B,SAAA,yBAAA,CAAA,EAGDpC,EAAAA,IAACkB,EAAA,CACC,GAAI,oCAAoC,mBAAmBe,CAAU,CAAC,GACtE,UAAU,sFACV,QAAS,IAAMG,EAAQ,EAAK,EAC7B,SAAA,iBAAA,CAAA,EAGDpC,EAAAA,IAACkB,EAAA,CACC,GAAI,oCAAoC,mBAAmBe,CAAU,CAAC,GACtE,UAAU,sFACV,QAAS,IAAMG,EAAQ,EAAK,EAC7B,SAAA,iBAAA,CAAA,CAED,CAAA,CACF,CAAA,EAEJ,CAEJ,CAEO,SAASM,IAAwB,CACtC,KAAM,CAAE,WAAAT,CAAA,EAAeU,EAAA,EACvBC,EAAwBX,CAAU,EAElC,MAAMY,EAAiB,qBACjB,CAAE,KAAMxC,EAAW,UAAAyC,EAAW,MAAAC,EAAO,QAAAC,EAAS,WAAAC,CAAA,EAAeC,EAAqBjB,CAAW,EAC7F,CAAE,KAAM3B,GAAS6C,EAAoBlB,CAAW,EAChD,CAAE,KAAMmB,GAAmBC,EAAcpB,CAAW,EACpD,CAAE,KAAMqB,GAAoBC,EAA2BtB,CAAU,EACjEuB,EAAWC,EAAA,EACXC,EAAoBC,EAAA,EACpB,CAAE,YAAAC,EAAa,OAAAC,GAAWC,EAAqB,oBAAoB,EAEnEC,EAAgBC,GAAoC,OACxD,GAAIA,IAAW,YACT,QAAQ,mDAAmD,GAC7DN,EAAkB,OAAOzB,CAAW,UAE7B+B,IAAW,WAAa3D,EAAW,CAE5C,MAAM4D,EAAS5D,EAAU,YAAY,QAAQ,uBAAwB,EAAE,EAEjEiB,EAAajB,EAAU,OAAO,KAAMkB,GAAMA,EAAE,aAAe,4BAA4B,EACvFC,GAASC,EAAAH,GAAA,YAAAA,EAAY,aAAZ,YAAAG,EAAgC,MAC3CD,GACF,eAAe,QAAQ,oBAAqB,KAAK,UAAUA,CAAK,CAAC,EAEnEgC,EAAS,yBAAyB,mBAAmBS,CAAM,CAAC,WAAW,CACzE,CACF,EAEA,GAAInB,EACF,OACEhC,EAAAA,KAAC,MAAA,CAAI,UAAU,0BACb,SAAA,CAAAd,EAAAA,IAAC,MAAA,CAAI,UAAU,oCAAA,CAAqC,EACpDA,EAAAA,IAAC,MAAA,CAAI,UAAU,gCAAA,CAAiC,CAAA,EAClD,EAIJ,GAAI+C,GAAS,CAAC1C,EAAW,CACvB,MAAM6D,GAAOnB,GAAA,YAAAA,EAAiB,UAAW,GACnCoB,EAAYD,EAAI,SAAS,SAAS,GAAKA,EAAI,SAAS,qBAAqB,EAE/E,cACG,MAAA,CACC,SAAA,CAAAlE,MAACkB,EAAA,CAAK,GAAG,wBAAwB,UAAU,qDAAqD,SAAA,cAEhG,EACAJ,EAAAA,KAAC,MAAA,CAAI,UAAU,wBACb,SAAA,CAAAd,EAAAA,IAAC,KAAE,UAAU,iCACV,WACG,wCACA+C,EACE,2BACA,qBAAA,CACR,QACC,IAAA,CAAE,UAAU,6BACV,SAAAoB,EACG,4HACAD,GAAO,qCAAA,CACb,CAAA,CAAA,CACF,CAAA,EACF,CAEJ,CAEA,MAAMnC,EAAY1B,EAAU,SAAW,aAAeA,EAAU,SAAW,SACrE2B,EAAe3B,EAAU,SAAW,aAAeA,EAAU,OAAO,KACvEkB,GAAM,CACL,GAAIA,EAAE,aAAe,0BAA2B,MAAO,GACvD,MAAM6C,EAAW7C,EAAE,WAAmB,cACtC,OAAO6C,IAAY,cAAgBA,IAAY,kBAAoBA,IAAY,gBAAiBA,GAAA,YAAAA,EAAS,WAAW,QACtH,CAAA,EAGF,cACG,MAAA,CACC,SAAA,CAAApE,EAAAA,IAACqE,EAAA,CACC,MAAOxB,EACP,QACE/B,EAAAA,KAAC,MAAA,CAAI,UAAU,0BACb,SAAA,CAAAd,EAAAA,IAACsE,EAAA,CACC,UAAW,IAAMtB,EAAA,EACjB,WAAAC,EACA,QAAS,oBAAoBhB,CAAU,YAAA,CAAA,EAEzCjC,EAAAA,IAACoB,EAAA,CAAY,OAAQf,EAAU,MAAA,CAAQ,EACvCL,EAAAA,IAAC8B,EAAA,CACC,UAAAC,EACA,aAAAC,EACA,WAAAC,EACA,SAAU8B,CAAA,CAAA,CACZ,CAAA,CACF,CAAA,CAAA,EAIJ/D,EAAAA,IAACI,EAAA,CACC,UAAAC,EACA,KAAAC,EACA,WAAY8C,GAAA,YAAAA,EAAgB,MAC5B,YAAaE,GAAA,YAAAA,EAAiB,WAAA,CAAA,EAG/BI,EAAkB,OACjB1D,EAAAA,IAAC,MAAA,CAAI,UAAU,YACb,SAAAc,EAAAA,KAAC,IAAA,CAAE,UAAU,4BAA4B,SAAA,CAAA,qBACpB4C,EAAkB,MAAM,OAAA,CAAA,CAC7C,CAAA,CACF,EAIF5C,EAAAA,KAAC,MAAA,CAAI,UAAU,YACb,SAAA,CAAAd,MAACuE,GAAmB,MAAM,UAAU,WAAW,UAAU,YAAaX,EAAY,SAAS,EAAG,SAAUC,EAAQ,iBAAiB,YAC/H,SAAA7D,EAAAA,IAAC0B,EAAA,CAAqB,UAAArB,EAAsB,EAC9C,EAEAL,EAAAA,IAACuE,EAAA,CAAmB,MAAM,qBAAqB,WAAW,WAAW,YAAaX,EAAY,UAAU,EAAG,SAAUC,EAAQ,iBAAiB,YAC5I,SAAA7D,EAAAA,IAACwE,EAAA,CACC,OAAQnE,EAAU,OAClB,WAAY+C,GAAA,YAAAA,EAAgB,MAC5B,IAAKnB,EACL,MAAM,SAAA,CAAA,EAEV,EAEAjC,EAAAA,IAACuE,EAAA,CAAmB,MAAM,SAAS,WAAW,SAAS,YAAaX,EAAY,QAAQ,EAAG,SAAUC,EAAQ,iBAAiB,YAC5H,SAAA7D,EAAAA,IAACyE,EAAA,CACC,OAAQpE,EAAU,OAClB,WAAY+C,GAAA,YAAAA,EAAgB,MAC5B,IAAKnB,EACL,MAAM,SAAA,CAAA,CACR,CACF,CAAA,CAAA,CACF,CAAA,EACF,CAEJ"}
|
|
1
|
+
{"version":3,"file":"WorkflowExecutionPage-BI9NzeaH.js","sources":["../../src/pages/workflows/workflow-execution/ExecutionHeader.tsx","../../src/pages/workflows/workflow-execution/ExecutionInputResult.tsx","../../src/pages/workflows/WorkflowExecutionPage.tsx"],"sourcesContent":["import { Link } from 'react-router-dom';\nimport { StatusBadge } from '../../../components/common/display/StatusBadge';\nimport { CopyableId } from '../../../components/common/display/CopyableId';\nimport type { WorkflowExecution, LTTaskRecord, LTEscalationRecord } from '../../../api/types';\nimport { DateValue } from '../../../components/common/display/DateValue';\nimport { DurationValue } from '../../../components/common/display/DurationValue';\n\nfunction MetadataField({\n label,\n value,\n mono,\n truncate,\n children,\n}: {\n label: string;\n value?: string;\n mono?: boolean;\n truncate?: boolean;\n children?: React.ReactNode;\n}) {\n return (\n <div>\n <p className=\"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-1\">\n {label}\n </p>\n {children || (\n <p\n className={`text-xs text-text-primary ${mono ? 'font-mono' : ''} ${truncate ? 'truncate' : ''}`}\n title={truncate ? value : undefined}\n >\n {value}\n </p>\n )}\n </div>\n );\n}\n\n/**\n * Split a HotMesh compound entity key (taskQueue-workflowName) on the last '-'.\n * Workflow names are camelCase, so the last segment is always the workflow type.\n */\nfunction splitEntityKey(compound: string): { taskQueue: string; workflowType: string } {\n const lastDash = compound.lastIndexOf('-');\n if (lastDash <= 0) return { taskQueue: compound, workflowType: compound };\n return {\n taskQueue: compound.substring(0, lastDash),\n workflowType: compound.substring(lastDash + 1),\n };\n}\n\ninterface ExecutionHeaderProps {\n execution: WorkflowExecution;\n task?: LTTaskRecord | null;\n childTasks?: LTTaskRecord[];\n escalations?: LTEscalationRecord[];\n}\n\nexport function ExecutionHeader({ execution, task, escalations }: ExecutionHeaderProps) {\n // Determine parent relationship — prefer execution-level pj (from HotMesh\n // raw state), fall back to lt_tasks record. When the SDK adds\n // parent_workflow_id natively, it flows through automatically.\n const executionParent = (execution as any).parent_workflow_id as string | undefined;\n const isLeaf = task && task.workflow_id === execution.workflow_id;\n const taskParent = isLeaf ? task.parent_workflow_id : null;\n const rawParent = executionParent || taskParent || null;\n // Filter self-references — cron-invoked workflows store themselves as parent\n const parentWorkflowId = rawParent && rawParent !== execution.workflow_id ? rawParent : null;\n\n // Split compound HotMesh keys into separate task queue / workflow type\n const { taskQueue, workflowType } = splitEntityKey(execution.workflow_type);\n\n return (\n <div className=\"bg-surface-sunken/50 rounded-md px-6 py-5 mb-6\">\n\n <div className=\"grid grid-cols-2 sm:grid-cols-4 gap-y-4 gap-x-8\">\n <CopyableId label=\"Workflow Type\" value={workflowType} href={`/workflows/executions?entity=${encodeURIComponent(workflowType)}`} />\n <MetadataField label=\"Task Queue\" value={taskQueue} mono />\n <MetadataField label=\"Start Time\">\n {execution.start_time\n ? <DateValue date={execution.start_time} format=\"datetime\" className=\"text-text-primary\" />\n : <span className=\"text-xs text-text-tertiary\">--</span>}\n </MetadataField>\n <MetadataField label=\"End Time\">\n {execution.close_time\n ? <DateValue date={execution.close_time} format=\"datetime\" className=\"text-text-primary\" />\n : <span className=\"text-xs text-text-tertiary\">--</span>}\n </MetadataField>\n <MetadataField label=\"Duration\">\n <DurationValue ms={execution.duration_ms} className=\"font-mono text-text-primary\" />\n </MetadataField>\n <MetadataField\n label=\"History Size\"\n value={`${execution.summary.total_events} events`}\n />\n <MetadataField\n label=\"Activities\"\n value={`${execution.summary.activities.completed} / ${execution.summary.activities.total}`}\n />\n <MetadataField\n label=\"Workflow ID\"\n value={execution.workflow_id}\n mono\n truncate\n />\n </div>\n\n {/* Related links */}\n {(parentWorkflowId || (escalations && escalations.length > 0)) && (\n <div className=\"mt-5 pt-4 border-t border-surface-border/50 space-y-3\">\n {/* Parent navigation */}\n {parentWorkflowId && (\n <div className=\"flex items-center gap-2\">\n <span className=\"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary shrink-0\">\n Parent\n </span>\n <Link\n to={`/workflows/executions/${parentWorkflowId}`}\n className=\"text-xs font-mono text-accent hover:underline truncate\"\n title={parentWorkflowId}\n >\n {parentWorkflowId}\n </Link>\n </div>\n )}\n\n {/* Process link — deep-links to process list filtered by this workflow */}\n {false && (\n <div className=\"flex items-center gap-2\">\n <span className=\"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary shrink-0\">\n Process\n </span>\n <Link\n to={`/processes/all?search=${encodeURIComponent(execution.workflow_id)}`}\n className=\"text-xs font-mono text-accent hover:underline truncate\"\n >\n Find in Processes\n </Link>\n </div>\n )}\n\n {/* Escalation links */}\n {escalations && escalations.length > 0 && (\n <div className=\"flex items-start gap-2\">\n <span className=\"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary shrink-0 mt-0.5\">\n {escalations.length === 1 ? 'Escalation' : 'Escalations'}\n </span>\n <div className=\"flex flex-wrap gap-x-4 gap-y-1\">\n {escalations.map((esc) => (\n <Link\n key={esc.id}\n to={`/escalations/detail/${esc.id}`}\n className=\"inline-flex items-center gap-1.5 text-xs font-mono text-accent hover:underline\"\n >\n <span>{esc.type}</span>\n <StatusBadge status={esc.status} />\n </Link>\n ))}\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n );\n}\n","import { JsonViewer } from '../../../components/common/data/JsonViewer';\nimport type { WorkflowExecution } from '../../../api/types';\n\ninterface ExecutionInputResultProps {\n execution: WorkflowExecution;\n}\n\n/**\n * Extract the workflow input envelope from the workflow_execution_started event.\n * HotMesh 0.13.0+ includes the actual trigger arguments (the envelope passed\n * to startWorkflow) in the start event's `input` attribute.\n */\nfunction extractInput(execution: WorkflowExecution): Record<string, unknown> | null {\n const startEvent = execution.events.find(\n (e) => e.event_type === 'workflow_execution_started',\n );\n const input = (startEvent?.attributes as any)?.input;\n return input && typeof input === 'object' ? input : null;\n}\n\nexport function ExecutionInputResult({ execution }: ExecutionInputResultProps) {\n const input = extractInput(execution);\n\n // Result: unwrap the workflow return — the `data` field is what LT users care about\n const rawResult = execution.result as Record<string, unknown> | null | undefined;\n const result = rawResult?.data ?? rawResult ?? null;\n\n if (!input && !result) return null;\n\n return (\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4 mb-6\">\n {input !== null && (\n <div>\n <JsonViewer data={input} label=\"Input Envelope\" />\n </div>\n )}\n {result !== null && (\n <div>\n <JsonViewer data={result} label=\"Result\" />\n </div>\n )}\n </div>\n );\n}\n","import { useState, useRef, useEffect } from 'react';\nimport { useParams, useNavigate, Link } from 'react-router-dom';\nimport { useWorkflowExecution, useTerminateWorkflow } from '../../api/workflows';\nimport { useWorkflowDetailEvents } from '../../hooks/useEventHooks';\nimport { useCollapsedSections } from '../../hooks/useCollapsedSections';\nimport { useTaskByWorkflowId, useChildTasks } from '../../api/tasks';\nimport { useEscalationsByWorkflowId } from '../../api/escalations';\n\nimport { PageHeader } from '../../components/common/layout/PageHeader';\nimport { CollapsibleSection } from '../../components/common/layout/CollapsibleSection';\nimport { ListToolbar } from '../../components/common/data/ListToolbar';\nimport { StatusBadge } from '../../components/common/display/StatusBadge';\n\nimport { ExecutionHeader } from './workflow-execution/ExecutionHeader';\nimport { ExecutionInputResult } from './workflow-execution/ExecutionInputResult';\nimport { SwimlaneTimeline } from './workflow-execution/SwimlaneTimeline';\nimport { EventTable } from './workflow-execution/EventTable';\n\nfunction ActionsDropdown({ isRunning, hasToolCalls, workflowId, onAction }: {\n isRunning: boolean;\n hasToolCalls: boolean;\n workflowId: string;\n onAction: (action: 'restart' | 'terminate') => void;\n}) {\n const [open, setOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!open) return;\n const handler = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false);\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, [open]);\n\n return (\n <div className=\"relative\" ref={ref}>\n <button onClick={() => setOpen(!open)} className=\"btn-primary text-xs\">\n Actions\n </button>\n {open && (\n <div className=\"absolute right-0 mt-1 w-44 bg-surface-raised border border-surface-border rounded-md shadow-lg z-10\">\n <button\n onClick={() => { onAction('restart'); setOpen(false); }}\n className=\"block w-full text-left px-4 py-2 text-xs text-text-secondary hover:bg-surface-hover\"\n >\n Restart Workflow\n </button>\n {isRunning && (\n <button\n onClick={() => { onAction('terminate'); setOpen(false); }}\n className=\"block w-full text-left px-4 py-2 text-xs text-status-error hover:bg-surface-hover\"\n >\n Terminate\n </button>\n )}\n {hasToolCalls && (\n <Link\n to={`/mcp/queries/${workflowId}?step=3`}\n className=\"block w-full text-left px-4 py-2 text-xs text-accent hover:bg-surface-hover\"\n onClick={() => setOpen(false)}\n >\n Compile into Pipeline\n </Link>\n )}\n <Link\n to={`/mcp/executions/${encodeURIComponent(workflowId)}?namespace=durable`}\n className=\"block w-full text-left px-4 py-2 text-xs text-text-secondary hover:bg-surface-hover\"\n onClick={() => setOpen(false)}\n >\n View Pipeline Execution\n </Link>\n <Link\n to={`/admin/streams?source=worker&jid=${encodeURIComponent(workflowId)}`}\n className=\"block w-full text-left px-4 py-2 text-xs text-text-secondary hover:bg-surface-hover\"\n onClick={() => setOpen(false)}\n >\n Worker Messages\n </Link>\n <Link\n to={`/admin/streams?source=engine&jid=${encodeURIComponent(workflowId)}`}\n className=\"block w-full text-left px-4 py-2 text-xs text-text-secondary hover:bg-surface-hover\"\n onClick={() => setOpen(false)}\n >\n Engine Messages\n </Link>\n </div>\n )}\n </div>\n );\n}\n\nexport function WorkflowExecutionPage() {\n const { workflowId } = useParams<{ workflowId: string }>();\n useWorkflowDetailEvents(workflowId);\n\n const executionTitle = 'Workflow Execution';\n const { data: execution, isLoading, error, refetch, isFetching } = useWorkflowExecution(workflowId!);\n const { data: task } = useTaskByWorkflowId(workflowId!);\n const { data: childTasksData } = useChildTasks(workflowId!);\n const { data: escalationsData } = useEscalationsByWorkflowId(workflowId);\n const navigate = useNavigate();\n const terminateMutation = useTerminateWorkflow();\n const { isCollapsed, toggle } = useCollapsedSections('workflow-execution');\n\n const handleAction = (action: 'restart' | 'terminate') => {\n if (action === 'terminate') {\n if (confirm('Are you sure you want to terminate this workflow?')) {\n terminateMutation.mutate(workflowId!);\n }\n } else if (action === 'restart' && execution) {\n // Extract entity from workflow_id (format: {entity}-{guid})\n const entity = execution.workflow_id.replace(/-[A-Za-z0-9_-]{20,}$/, '');\n // Extract original input from the started event\n const startEvent = execution.events.find((e) => e.event_type === 'workflow_execution_started');\n const input = (startEvent?.attributes as any)?.input;\n if (input) {\n sessionStorage.setItem('lt:invoke:prefill', JSON.stringify(input));\n }\n navigate(`/workflows/start?type=${encodeURIComponent(entity)}&mode=now`);\n }\n };\n\n if (isLoading) {\n return (\n <div className=\"animate-pulse space-y-4\">\n <div className=\"h-8 bg-surface-sunken rounded w-64\" />\n <div className=\"h-60 bg-surface-sunken rounded\" />\n </div>\n );\n }\n\n if (error || !execution) {\n const msg = (error as Error)?.message ?? '';\n const isExpired = msg.includes('expired') || msg.includes('no longer available');\n\n return (\n <div>\n <Link to=\"/workflows/executions\" className=\"text-xs text-text-tertiary hover:text-text-primary\">\n ← Workflows\n </Link>\n <div className=\"mt-4 text-center py-8\">\n <p className=\"text-sm text-text-primary mb-1\">\n {isExpired\n ? 'Execution data is no longer available'\n : error\n ? 'Unable to load execution'\n : 'Execution not found'}\n </p>\n <p className=\"text-xs text-text-tertiary\">\n {isExpired\n ? \"This workflow's underlying job has expired. The task record is preserved, but the execution timeline has been cleaned up.\"\n : msg || 'The workflow could not be resolved.'}\n </p>\n </div>\n </div>\n );\n }\n\n const isRunning = execution.status !== 'completed' && execution.status !== 'failed';\n const hasToolCalls = execution.status === 'completed' && execution.events.some(\n (e) => {\n if (e.event_type !== 'activity_task_completed') return false;\n const actType = (e.attributes as any).activity_type;\n return actType === 'callDbTool' || actType === 'callVisionTool' || actType === 'callMcpTool' || actType?.startsWith('mcp_');\n },\n );\n\n return (\n <div>\n <PageHeader\n title={executionTitle}\n actions={\n <div className=\"flex items-center gap-3\">\n <ListToolbar\n onRefresh={() => refetch()}\n isFetching={isFetching}\n apiPath={`/workflow-states/${workflowId}/execution`}\n />\n <StatusBadge status={execution.status} />\n <ActionsDropdown\n isRunning={isRunning}\n hasToolCalls={hasToolCalls}\n workflowId={workflowId!}\n onAction={handleAction}\n />\n </div>\n }\n />\n\n <ExecutionHeader\n execution={execution}\n task={task}\n childTasks={childTasksData?.tasks}\n escalations={escalationsData?.escalations}\n />\n\n {terminateMutation.error && (\n <div className=\"py-3 mb-6\">\n <p className=\"text-xs text-status-error\">\n Terminate failed: {terminateMutation.error.message}\n </p>\n </div>\n )}\n\n\n <div className=\"space-y-6\">\n <CollapsibleSection title=\"Details\" sectionKey=\"details\" isCollapsed={isCollapsed('details')} onToggle={toggle} contentClassName=\"mt-4 ml-9\">\n <ExecutionInputResult execution={execution} />\n </CollapsibleSection>\n\n <CollapsibleSection title=\"Execution Timeline\" sectionKey=\"timeline\" isCollapsed={isCollapsed('timeline')} onToggle={toggle} contentClassName=\"mt-4 ml-9\">\n <SwimlaneTimeline\n events={execution.events}\n childTasks={childTasksData?.tasks}\n jid={workflowId}\n appId=\"durable\"\n />\n </CollapsibleSection>\n\n <CollapsibleSection title=\"Events\" sectionKey=\"events\" isCollapsed={isCollapsed('events')} onToggle={toggle} contentClassName=\"mt-4 ml-9\">\n <EventTable\n events={execution.events}\n childTasks={childTasksData?.tasks}\n jid={workflowId}\n appId=\"durable\"\n />\n </CollapsibleSection>\n </div>\n </div>\n );\n}\n"],"names":["MetadataField","label","value","mono","truncate","children","jsx","splitEntityKey","compound","lastDash","ExecutionHeader","execution","task","escalations","executionParent","taskParent","rawParent","parentWorkflowId","taskQueue","workflowType","jsxs","CopyableId","DateValue","DurationValue","Link","esc","StatusBadge","extractInput","startEvent","e","input","_a","ExecutionInputResult","rawResult","result","JsonViewer","ActionsDropdown","isRunning","hasToolCalls","workflowId","onAction","open","setOpen","useState","ref","useRef","useEffect","handler","WorkflowExecutionPage","useParams","useWorkflowDetailEvents","executionTitle","isLoading","error","refetch","isFetching","useWorkflowExecution","useTaskByWorkflowId","childTasksData","useChildTasks","escalationsData","useEscalationsByWorkflowId","navigate","useNavigate","terminateMutation","useTerminateWorkflow","isCollapsed","toggle","useCollapsedSections","handleAction","action","entity","msg","isExpired","actType","PageHeader","ListToolbar","CollapsibleSection","SwimlaneTimeline","EventTable"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{j as
|
|
2
|
-
//# sourceMappingURL=WorkflowPill-
|
|
1
|
+
import{j as n}from"./vendor-query-B2UbickB.js";import{W as r,Z as u,c as m,S as d,ad as h}from"./vendor-icons-BaQqUm-e.js";const a=[{text:"text-rose-400",bg:"bg-rose-400/[0.08]"},{text:"text-pink-400",bg:"bg-pink-400/[0.08]"},{text:"text-fuchsia-400",bg:"bg-fuchsia-400/[0.08]"},{text:"text-purple-400",bg:"bg-purple-400/[0.08]"},{text:"text-violet-400",bg:"bg-violet-400/[0.08]"},{text:"text-indigo-400",bg:"bg-indigo-400/[0.08]"},{text:"text-blue-400",bg:"bg-blue-400/[0.08]"},{text:"text-sky-400",bg:"bg-sky-400/[0.08]"},{text:"text-cyan-400",bg:"bg-cyan-400/[0.08]"},{text:"text-teal-400",bg:"bg-teal-400/[0.08]"},{text:"text-emerald-400",bg:"bg-emerald-400/[0.08]"},{text:"text-green-400",bg:"bg-green-400/[0.08]"},{text:"text-lime-400",bg:"bg-lime-400/[0.08]"},{text:"text-yellow-400",bg:"bg-yellow-400/[0.08]"},{text:"text-amber-400",bg:"bg-amber-400/[0.08]"},{text:"text-orange-400",bg:"bg-orange-400/[0.08]"},{text:"text-red-400",bg:"bg-red-400/[0.08]"},{text:"text-stone-400",bg:"bg-stone-400/[0.08]"},{text:"text-rose-300",bg:"bg-rose-300/[0.08]"},{text:"text-violet-300",bg:"bg-violet-300/[0.08]"},{text:"text-sky-300",bg:"bg-sky-300/[0.08]"},{text:"text-teal-300",bg:"bg-teal-300/[0.08]"},{text:"text-amber-300",bg:"bg-amber-300/[0.08]"},{text:"text-pink-300",bg:"bg-pink-300/[0.08]"}];function f(t){let x=0;for(let g=0;g<t.length;g++)x=(x<<5)-x+t.charCodeAt(g)|0;return Math.abs(x)}function k(t){return a[f(t)%a.length]}const y={certified:h,registered:d,pipeline:m,capability:u,durable:r},w={certified:{text:"text-status-success",bg:"bg-status-success/10"},registered:{text:"text-amber-500/70",bg:"bg-amber-200/[0.12]"}},C={xs:{bulb:"w-4 h-4",icon:"w-2 h-2",text:"text-[9px]",pad:"pr-1.5 pl-0.5",gap:"-ml-1"},sm:{bulb:"w-5 h-5",icon:"w-2.5 h-2.5",text:"text-[11px]",pad:"pr-2 pl-1",gap:"-ml-1.5"},md:{bulb:"w-6 h-6",icon:"w-3 h-3",text:"text-[13px]",pad:"pr-2.5 pl-1.5",gap:"-ml-2"}};function I({type:t,size:x="sm",certified:g,variant:i}){const l=i??(g?"certified":"durable"),c=y[l]??r,b=C[x],e=w[l],s=e?null:k(t),p=(e==null?void 0:e.text)??(s==null?void 0:s.text)??"text-accent/75",o=(e==null?void 0:e.bg)??(s==null?void 0:s.bg)??"bg-accent/[0.08]";return n.jsxs("span",{className:"inline-flex items-center",children:[n.jsx("span",{className:`${b.bulb} rounded-full ${o} inline-flex items-center justify-center shrink-0 z-[1]`,children:n.jsx(c,{className:`${b.icon} ${p}`})}),n.jsx("span",{className:`${b.gap} ${b.pad} ${o} rounded-r-full font-mono text-text-secondary`,style:{fontSize:b.text==="text-[9px]"?"9px":b.text==="text-[11px]"?"11px":"13px",lineHeight:1.4},children:t})]})}export{I as W};
|
|
2
|
+
//# sourceMappingURL=WorkflowPill-BuNkWUVM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WorkflowPill-BuNkWUVM.js","sources":["../../src/lib/type-color.ts","../../src/components/common/display/WorkflowPill.tsx"],"sourcesContent":["/**\n * Deterministic color assignment for workflow type names.\n *\n * Maps any string to a consistent color from a curated 24-color palette.\n * The same type name always produces the same color across the entire UI.\n * Uses a simple hash to distribute names evenly across the palette.\n *\n * Each entry provides:\n * text — icon and text color (Tailwind class)\n * bg — subtle background tint (Tailwind class)\n */\n\nconst PALETTE: Array<{ text: string; bg: string }> = [\n { text: 'text-rose-400', bg: 'bg-rose-400/[0.08]' },\n { text: 'text-pink-400', bg: 'bg-pink-400/[0.08]' },\n { text: 'text-fuchsia-400', bg: 'bg-fuchsia-400/[0.08]' },\n { text: 'text-purple-400', bg: 'bg-purple-400/[0.08]' },\n { text: 'text-violet-400', bg: 'bg-violet-400/[0.08]' },\n { text: 'text-indigo-400', bg: 'bg-indigo-400/[0.08]' },\n { text: 'text-blue-400', bg: 'bg-blue-400/[0.08]' },\n { text: 'text-sky-400', bg: 'bg-sky-400/[0.08]' },\n { text: 'text-cyan-400', bg: 'bg-cyan-400/[0.08]' },\n { text: 'text-teal-400', bg: 'bg-teal-400/[0.08]' },\n { text: 'text-emerald-400', bg: 'bg-emerald-400/[0.08]' },\n { text: 'text-green-400', bg: 'bg-green-400/[0.08]' },\n { text: 'text-lime-400', bg: 'bg-lime-400/[0.08]' },\n { text: 'text-yellow-400', bg: 'bg-yellow-400/[0.08]' },\n { text: 'text-amber-400', bg: 'bg-amber-400/[0.08]' },\n { text: 'text-orange-400', bg: 'bg-orange-400/[0.08]' },\n { text: 'text-red-400', bg: 'bg-red-400/[0.08]' },\n { text: 'text-stone-400', bg: 'bg-stone-400/[0.08]' },\n { text: 'text-rose-300', bg: 'bg-rose-300/[0.08]' },\n { text: 'text-violet-300', bg: 'bg-violet-300/[0.08]' },\n { text: 'text-sky-300', bg: 'bg-sky-300/[0.08]' },\n { text: 'text-teal-300', bg: 'bg-teal-300/[0.08]' },\n { text: 'text-amber-300', bg: 'bg-amber-300/[0.08]' },\n { text: 'text-pink-300', bg: 'bg-pink-300/[0.08]' },\n];\n\nfunction hash(str: string): number {\n let h = 0;\n for (let i = 0; i < str.length; i++) {\n h = ((h << 5) - h + str.charCodeAt(i)) | 0;\n }\n return Math.abs(h);\n}\n\nexport function typeColor(typeName: string): { text: string; bg: string } {\n return PALETTE[hash(typeName) % PALETTE.length];\n}\n","import { Workflow, ShieldCheck, SlidersHorizontal, Wand2, Zap } from 'lucide-react';\nimport { typeColor } from '../../../lib/type-color';\n\ntype WorkflowVariant = 'durable' | 'registered' | 'certified' | 'pipeline' | 'capability';\n\ninterface WorkflowPillProps {\n type: string;\n size?: 'xs' | 'sm' | 'md';\n /** @deprecated Use `variant` instead */\n certified?: boolean;\n variant?: WorkflowVariant;\n}\n\nconst VARIANT_ICON: Record<WorkflowVariant, typeof Workflow> = {\n certified: ShieldCheck,\n registered: SlidersHorizontal,\n pipeline: Wand2,\n capability: Zap,\n durable: Workflow,\n};\n\nconst VARIANT_FIXED_COLOR: Record<string, { text: string; bg: string }> = {\n certified: { text: 'text-status-success', bg: 'bg-status-success/10' },\n registered: { text: 'text-amber-500/70', bg: 'bg-amber-200/[0.12]' },\n};\n\nconst SIZE_CONFIG = {\n xs: { bulb: 'w-4 h-4', icon: 'w-2 h-2', text: 'text-[9px]', pad: 'pr-1.5 pl-0.5', gap: '-ml-1' },\n sm: { bulb: 'w-5 h-5', icon: 'w-2.5 h-2.5', text: 'text-[11px]', pad: 'pr-2 pl-1', gap: '-ml-1.5' },\n md: { bulb: 'w-6 h-6', icon: 'w-3 h-3', text: 'text-[13px]', pad: 'pr-2.5 pl-1.5', gap: '-ml-2' },\n} as const;\n\nexport function WorkflowPill({ type, size = 'sm', certified, variant }: WorkflowPillProps) {\n const resolved = variant ?? (certified ? 'certified' : 'durable');\n // Callers pass server-provided tier strings here — fall back to the durable\n // icon on an unrecognized value so version skew degrades instead of crashing.\n const Icon = VARIANT_ICON[resolved] ?? Workflow;\n const s = SIZE_CONFIG[size];\n\n const fixed = VARIANT_FIXED_COLOR[resolved];\n const derived = fixed ? null : typeColor(type);\n const iconColor = fixed?.text ?? derived?.text ?? 'text-accent/75';\n const bgColor = fixed?.bg ?? derived?.bg ?? 'bg-accent/[0.08]';\n\n return (\n <span className=\"inline-flex items-center\">\n {/* Bulb — circular icon container */}\n <span className={`${s.bulb} rounded-full ${bgColor} inline-flex items-center justify-center shrink-0 z-[1]`}>\n <Icon className={`${s.icon} ${iconColor}`} />\n </span>\n {/* Label — extends right, overlapping the bulb */}\n <span\n className={`${s.gap} ${s.pad} ${bgColor} rounded-r-full font-mono text-text-secondary`}\n style={{ fontSize: s.text === 'text-[9px]' ? '9px' : s.text === 'text-[11px]' ? '11px' : '13px', lineHeight: 1.4 }}\n >\n {type}\n </span>\n </span>\n );\n}\n"],"names":["PALETTE","hash","str","h","i","typeColor","typeName","VARIANT_ICON","ShieldCheck","SlidersHorizontal","Wand2","Zap","Workflow","VARIANT_FIXED_COLOR","SIZE_CONFIG","WorkflowPill","type","size","certified","variant","resolved","Icon","s","fixed","derived","iconColor","bgColor","jsxs","jsx"],"mappings":"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"}
|
package/dashboard/dist/assets/{WorkflowsDashboard-rpnGhGnl.js → WorkflowsDashboard-CvWSgQdE.js}
RENAMED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as d,j as t}from"./vendor-query-B2UbickB.js";import{E as z}from"./ElapsedCell-
|
|
2
|
-
//# sourceMappingURL=WorkflowsDashboard-
|
|
1
|
+
import{a as d,j as t}from"./vendor-query-B2UbickB.js";import{E as z}from"./ElapsedCell-B8TrnyT5.js";import{j as A,b as v}from"./index-CKXSKsVZ.js";import{u as E,d as $,b as L}from"./workflows-BTkHs6VT.js";import{u as M}from"./useNamespace-BBzCmCIN.js";import{b as I}from"./useEventHooks-DlWkui_n.js";import{u as U}from"./useFilterParams-x-Dg0Vgz.js";import{b as O}from"./api-path-u2Jf9QXS.js";import{D as B}from"./DataTable-ZWgVQg7F.js";import{W as H}from"./WorkflowPill-BuNkWUVM.js";import{P as V}from"./PageHeader-CFta2VaS.js";import{F as G,c as f,b as x}from"./FilterBar-BQ2JGg8U.js";import{S as J}from"./StickyPagination-GQKFFTjL.js";import{L as q}from"./ListToolbar--FkPpYDY.js";import{R as K,a as k}from"./RowActions-BA9L9djf.js";import{u as Q,y as X}from"./vendor-icons-BaQqUm-e.js";import{c as Y}from"./vendor-react-CXumBFUA.js";import"./controlplane-BrwK_MT8.js";import"./EmptyState-BcsfPq9T.js";const Z={running:"in_progress",completed:"completed",failed:"failed"},ee={in_progress:"bg-status-active",completed:"bg-status-success",failed:"bg-status-error"},te={running:"text-status-active",completed:"text-status-success",failed:"text-status-error"};function se(p,n,m,l,a){return[{key:"workflow_id",label:"Workflow ID",render:e=>{const o=ee[Z[e.status]??e.status]??"bg-status-pending",r=e.status==="running"?" animate-pulse":"";return t.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[t.jsx("span",{className:`w-1.5 h-1.5 shrink-0 rounded-full ${o}${r}`,title:e.status}),t.jsx("span",{className:"font-mono text-xs text-text-primary truncate",children:e.workflow_id})]})}},{key:"entity",label:"Type",render:e=>t.jsx(H,{type:e.entity,variant:a.get(e.entity)??"durable",size:"xs"}),className:"w-44 shrink-0"},{key:"created_at",label:"Created",render:e=>t.jsx(v,{date:e.created_at,format:"relative",className:"text-xs text-text-secondary whitespace-nowrap"}),className:"w-32",sortable:!0},{key:"updated_at",label:"Updated",render:e=>t.jsx(v,{date:e.updated_at,format:"relative",className:"text-xs text-text-secondary whitespace-nowrap"}),className:"w-32",sortable:!0},{key:"duration",label:"Duration",render:e=>t.jsx(z,{startDate:e.created_at,endDate:e.status==="running"?null:e.updated_at,isLive:e.status==="running"}),className:"w-28"},{key:"actions",label:"",render:e=>t.jsxs(K,{children:[t.jsx(k,{icon:Q,title:`Filter by ${e.entity}`,onClick:()=>p(e.entity)}),t.jsx("button",{onClick:o=>{o.stopPropagation(),n(e.status)},className:"opacity-0 group-hover/row:opacity-100 transition-opacity",title:`Filter by ${e.status}`,children:t.jsx("svg",{className:`w-[18px] h-[18px] ${te[e.status]??"text-text-tertiary"} hover:opacity-70`,viewBox:"0 0 24 24",fill:"currentColor",children:t.jsx("circle",{cx:"12",cy:"12",r:"6"})})}),m&&t.jsx(k,{icon:X,title:"View config",onClick:()=>l(`/workflows/registry/${encodeURIComponent(e.entity)}`)})]}),className:"w-24 text-right"}]}function ke({tier:p="all"}){I();const n=Y(),{isSuperAdmin:m}=A(),{namespace:l}=M(),{filters:a,setFilter:e,pagination:o,sort:r,setSort:j}=U({filters:{search:"",entity:"",status:"",tier:p}}),c=a.tier||"all",g=c==="certified"?"true":c==="durable"?"false":void 0,{data:b}=E(),{data:y}=$(),S=d.useMemo(()=>{const s=new Map;for(const w of y??[])s.set(w.workflow_type,w.tier??"durable");return s},[y]),_=se(s=>e("entity",s),s=>e("status",s),m,n,S),[u,C]=d.useState(a.search);d.useEffect(()=>{if(u===a.search)return;const s=setTimeout(()=>e("search",u),300);return()=>clearTimeout(s)},[u,e,a.search]);const{data:i,isLoading:N,refetch:P,isFetching:T}=L({limit:o.pageSize,offset:o.offset,entity:a.entity||void 0,search:a.search||void 0,status:a.status||void 0,sort_by:r.sort_by||"created_at",order:r.order||"desc",registered:g,namespace:l||void 0}),h=(i==null?void 0:i.total)??0,F=(i==null?void 0:i.jobs)??[],D=d.useMemo(()=>[...new Set((b??[]).map(s=>s.workflow_type))].sort(),[b]),R="Workflow Executions",W=c==="certified"?"No certified workflow executions found":c==="durable"?"No durable workflow executions found":"No workflow executions found";return t.jsxs("div",{children:[t.jsx(V,{title:R,docsHash:"#docs:dashboard.md:durable-executions"}),t.jsxs(G,{actions:t.jsx(q,{onRefresh:()=>P(),isFetching:T,apiPath:O("/workflow-states/jobs",{limit:o.pageSize,offset:o.offset,entity:a.entity||void 0,search:a.search||void 0,status:a.status||void 0,sort_by:r.sort_by||"created_at",order:r.order||"desc",registered:g,namespace:l||void 0})}),children:[t.jsx("input",{type:"text",placeholder:"Search workflow ID...",value:u,onChange:s=>C(s.target.value),className:"input text-[11px] py-1 px-2 w-56"}),t.jsx(f,{}),t.jsx(x,{label:"Type",value:a.entity,onChange:s=>e("entity",s),options:D.map(s=>({value:s,label:s}))}),t.jsx(f,{}),t.jsx(x,{label:"Status",value:a.status,onChange:s=>e("status",s),options:[{value:"running",label:"Running"},{value:"completed",label:"Completed"},{value:"failed",label:"Failed"}]}),t.jsx(f,{}),t.jsx(x,{label:"Tier",value:a.tier==="all"?"":a.tier,onChange:s=>e("tier",s||"all"),options:[{value:"certified",label:"Certified"},{value:"durable",label:"Durable"}]})]}),t.jsx(B,{columns:_,data:F,keyFn:s=>s.workflow_id,onRowClick:s=>n(`/workflows/executions/${s.workflow_id}`),isLoading:N,emptyMessage:W,sort:r,onSort:j}),t.jsx(J,{page:o.page,totalPages:o.totalPages(h),onPageChange:o.setPage,total:h,pageSize:o.pageSize,onPageSizeChange:o.setPageSize})]})}export{ke as WorkflowsDashboard};
|
|
2
|
+
//# sourceMappingURL=WorkflowsDashboard-CvWSgQdE.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkflowsDashboard-rpnGhGnl.js","sources":["../../src/pages/workflows/WorkflowsDashboard.tsx"],"sourcesContent":["import { useState, useEffect, useMemo } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { Filter, Settings } from 'lucide-react';\nimport { ElapsedCell } from '../../components/common/display/ElapsedCell';\nimport { DateValue } from '../../components/common/display/DateValue';\nimport { useJobs, useWorkflowConfigs, useDiscoveredWorkflows } from '../../api/workflows';\nimport { useAuth } from '../../hooks/useAuth';\nimport { useNamespace } from '../../hooks/useNamespace';\nimport { useWorkflowListEvents } from '../../hooks/useEventHooks';\nimport { useFilterParams } from '../../hooks/useFilterParams';\nimport { buildApiPath } from '../../lib/api-path';\nimport { DataTable, type Column } from '../../components/common/data/DataTable';\nimport { WorkflowPill } from '../../components/common/display/WorkflowPill';\nimport { PageHeader } from '../../components/common/layout/PageHeader';\nimport { FilterBar, FilterSelect, FilterDivider } from '../../components/common/data/FilterBar';\nimport { StickyPagination } from '../../components/common/data/StickyPagination';\nimport { ListToolbar } from '../../components/common/data/ListToolbar';\nimport { RowAction, RowActionGroup } from '../../components/common/layout/RowActions';\nimport type { LTJob, WorkflowTier } from '../../api/types';\n\nexport type ExecutionsTier = 'all' | 'certified' | 'durable';\n\nconst jobStatusMap: Record<string, string> = {\n running: 'in_progress',\n completed: 'completed',\n failed: 'failed',\n};\n\nconst STATUS_DOT: Record<string, string> = {\n in_progress: 'bg-status-active',\n completed: 'bg-status-success',\n failed: 'bg-status-error',\n};\n\nconst STATUS_COLORS: Record<string, string> = {\n running: 'text-status-active',\n completed: 'text-status-success',\n failed: 'text-status-error',\n};\n\nfunction buildColumns(\n onFilterEntity: (entity: string) => void,\n onFilterStatus: (status: string) => void,\n isSuperAdmin: boolean,\n navigate: (path: string) => void,\n tierMap: Map<string, WorkflowTier>,\n): Column<LTJob>[] {\n return [\n {\n key: 'workflow_id',\n label: 'Workflow ID',\n render: (row) => {\n const dotClass = STATUS_DOT[jobStatusMap[row.status] ?? row.status] ?? 'bg-status-pending';\n const pulseClass = row.status === 'running' ? ' animate-pulse' : '';\n return (\n <div className=\"flex items-center gap-2 min-w-0\">\n <span className={`w-1.5 h-1.5 shrink-0 rounded-full ${dotClass}${pulseClass}`} title={row.status} />\n <span className=\"font-mono text-xs text-text-primary truncate\">{row.workflow_id}</span>\n </div>\n );\n },\n },\n {\n key: 'entity',\n label: 'Type',\n render: (row) => <WorkflowPill type={row.entity} variant={tierMap.get(row.entity) ?? 'durable'} size=\"xs\" />,\n className: 'w-44 shrink-0',\n },\n {\n key: 'created_at',\n label: 'Created',\n render: (row) => <DateValue date={row.created_at} format=\"relative\" className=\"text-xs text-text-secondary whitespace-nowrap\" />,\n className: 'w-32',\n sortable: true,\n },\n {\n key: 'updated_at',\n label: 'Updated',\n render: (row) => <DateValue date={row.updated_at} format=\"relative\" className=\"text-xs text-text-secondary whitespace-nowrap\" />,\n className: 'w-32',\n sortable: true,\n },\n {\n key: 'duration',\n label: 'Duration',\n render: (row) => (\n <ElapsedCell\n startDate={row.created_at}\n endDate={row.status === 'running' ? null : row.updated_at}\n isLive={row.status === 'running'}\n />\n ),\n className: 'w-28',\n },\n {\n key: 'actions',\n label: '',\n render: (row) => (\n <RowActionGroup>\n <RowAction\n icon={Filter}\n title={`Filter by ${row.entity}`}\n onClick={() => onFilterEntity(row.entity)}\n />\n <button\n onClick={(e) => { e.stopPropagation(); onFilterStatus(row.status); }}\n className=\"opacity-0 group-hover/row:opacity-100 transition-opacity\"\n title={`Filter by ${row.status}`}\n >\n <svg className={`w-[18px] h-[18px] ${STATUS_COLORS[row.status] ?? 'text-text-tertiary'} hover:opacity-70`} viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <circle cx=\"12\" cy=\"12\" r=\"6\" />\n </svg>\n </button>\n {isSuperAdmin && (\n <RowAction\n icon={Settings}\n title=\"View config\"\n onClick={() => navigate(`/workflows/registry/${encodeURIComponent(row.entity)}`)}\n />\n )}\n </RowActionGroup>\n ),\n className: 'w-24 text-right',\n },\n ];\n}\n\nexport function WorkflowsDashboard({ tier: initialTier = 'all' }: { tier?: ExecutionsTier }) {\n useWorkflowListEvents();\n const navigate = useNavigate();\n const { isSuperAdmin } = useAuth();\n const { namespace } = useNamespace();\n\n const { filters, setFilter, pagination, sort, setSort } = useFilterParams({\n filters: { search: '', entity: '', status: '', tier: initialTier },\n });\n\n const activeTier = (filters.tier || 'all') as ExecutionsTier;\n\n // Map tier to server-side registered filter\n const registeredFilter = activeTier === 'certified' ? 'true'\n : activeTier === 'durable' ? 'false'\n : undefined;\n\n const { data: configs } = useWorkflowConfigs();\n const { data: discoveredData } = useDiscoveredWorkflows();\n\n const tierMap = useMemo(() => {\n const map = new Map<string, WorkflowTier>();\n for (const dw of discoveredData ?? []) {\n map.set(dw.workflow_type, dw.tier ?? 'durable');\n }\n return map;\n }, [discoveredData]);\n\n const columns = buildColumns(\n (entity) => setFilter('entity', entity),\n (status) => setFilter('status', status),\n isSuperAdmin,\n navigate,\n tierMap,\n );\n const [searchInput, setSearchInput] = useState(filters.search);\n\n useEffect(() => {\n if (searchInput === filters.search) return;\n const timer = setTimeout(() => setFilter('search', searchInput), 300);\n return () => clearTimeout(timer);\n }, [searchInput, setFilter, filters.search]);\n\n const { data: jobsData, isLoading, refetch, isFetching } = useJobs({\n limit: pagination.pageSize,\n offset: pagination.offset,\n entity: filters.entity || undefined,\n search: filters.search || undefined,\n status: filters.status || undefined,\n sort_by: sort.sort_by || 'created_at',\n order: sort.order || 'desc',\n registered: registeredFilter,\n namespace: namespace || undefined,\n });\n\n const total = jobsData?.total ?? 0;\n const jobs = jobsData?.jobs ?? [];\n\n const entities = useMemo(() => {\n return [...new Set((configs ?? []).map((c) => c.workflow_type))].sort();\n }, [configs]);\n\n const pageTitle = 'Workflow Executions';\n\n const emptyMessage = activeTier === 'certified'\n ? 'No certified workflow executions found'\n : activeTier === 'durable'\n ? 'No durable workflow executions found'\n : 'No workflow executions found';\n\n return (\n <div>\n <PageHeader title={pageTitle} docsHash=\"#docs:dashboard.md:durable-executions\" />\n\n <FilterBar actions={\n <ListToolbar\n onRefresh={() => refetch()}\n isFetching={isFetching}\n apiPath={buildApiPath('/workflow-states/jobs', {\n limit: pagination.pageSize,\n offset: pagination.offset,\n entity: filters.entity || undefined,\n search: filters.search || undefined,\n status: filters.status || undefined,\n sort_by: sort.sort_by || 'created_at',\n order: sort.order || 'desc',\n registered: registeredFilter,\n namespace: namespace || undefined,\n })}\n />\n }>\n <input\n type=\"text\"\n placeholder=\"Search workflow ID...\"\n value={searchInput}\n onChange={(e) => setSearchInput(e.target.value)}\n className=\"input text-[11px] py-1 px-2 w-56\"\n />\n <FilterDivider />\n <FilterSelect\n label=\"Type\"\n value={filters.entity}\n onChange={(v) => setFilter('entity', v)}\n options={entities.map((e) => ({ value: e, label: e }))}\n />\n <FilterDivider />\n <FilterSelect\n label=\"Status\"\n value={filters.status}\n onChange={(v) => setFilter('status', v)}\n options={[\n { value: 'running', label: 'Running' },\n { value: 'completed', label: 'Completed' },\n { value: 'failed', label: 'Failed' },\n ]}\n />\n <FilterDivider />\n <FilterSelect\n label=\"Tier\"\n value={filters.tier === 'all' ? '' : filters.tier}\n onChange={(v) => setFilter('tier', v || 'all')}\n options={[\n { value: 'certified', label: 'Certified' },\n { value: 'durable', label: 'Durable' },\n ]}\n />\n </FilterBar>\n\n <DataTable\n columns={columns}\n data={jobs}\n keyFn={(row) => row.workflow_id}\n onRowClick={(row) => navigate(`/workflows/executions/${row.workflow_id}`)}\n isLoading={isLoading}\n emptyMessage={emptyMessage}\n sort={sort}\n onSort={setSort}\n />\n\n <StickyPagination\n page={pagination.page}\n totalPages={pagination.totalPages(total)}\n onPageChange={pagination.setPage}\n total={total}\n pageSize={pagination.pageSize}\n onPageSizeChange={pagination.setPageSize}\n />\n </div>\n );\n}\n"],"names":["jobStatusMap","STATUS_DOT","STATUS_COLORS","buildColumns","onFilterEntity","onFilterStatus","isSuperAdmin","navigate","tierMap","row","dotClass","pulseClass","jsxs","jsx","WorkflowPill","DateValue","ElapsedCell","RowActionGroup","RowAction","Filter","e","Settings","WorkflowsDashboard","initialTier","useWorkflowListEvents","useNavigate","useAuth","namespace","useNamespace","filters","setFilter","pagination","sort","setSort","useFilterParams","activeTier","registeredFilter","configs","useWorkflowConfigs","discoveredData","useDiscoveredWorkflows","useMemo","map","dw","columns","entity","status","searchInput","setSearchInput","useState","useEffect","timer","jobsData","isLoading","refetch","isFetching","useJobs","total","jobs","entities","c","pageTitle","emptyMessage","PageHeader","FilterBar","ListToolbar","buildApiPath","FilterDivider","FilterSelect","v","DataTable","StickyPagination"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"WorkflowsDashboard-CvWSgQdE.js","sources":["../../src/pages/workflows/WorkflowsDashboard.tsx"],"sourcesContent":["import { useState, useEffect, useMemo } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { Filter, Settings } from 'lucide-react';\nimport { ElapsedCell } from '../../components/common/display/ElapsedCell';\nimport { DateValue } from '../../components/common/display/DateValue';\nimport { useJobs, useWorkflowConfigs, useDiscoveredWorkflows } from '../../api/workflows';\nimport { useAuth } from '../../hooks/useAuth';\nimport { useNamespace } from '../../hooks/useNamespace';\nimport { useWorkflowListEvents } from '../../hooks/useEventHooks';\nimport { useFilterParams } from '../../hooks/useFilterParams';\nimport { buildApiPath } from '../../lib/api-path';\nimport { DataTable, type Column } from '../../components/common/data/DataTable';\nimport { WorkflowPill } from '../../components/common/display/WorkflowPill';\nimport { PageHeader } from '../../components/common/layout/PageHeader';\nimport { FilterBar, FilterSelect, FilterDivider } from '../../components/common/data/FilterBar';\nimport { StickyPagination } from '../../components/common/data/StickyPagination';\nimport { ListToolbar } from '../../components/common/data/ListToolbar';\nimport { RowAction, RowActionGroup } from '../../components/common/layout/RowActions';\nimport type { LTJob, WorkflowTier } from '../../api/types';\n\nexport type ExecutionsTier = 'all' | 'certified' | 'durable';\n\nconst jobStatusMap: Record<string, string> = {\n running: 'in_progress',\n completed: 'completed',\n failed: 'failed',\n};\n\nconst STATUS_DOT: Record<string, string> = {\n in_progress: 'bg-status-active',\n completed: 'bg-status-success',\n failed: 'bg-status-error',\n};\n\nconst STATUS_COLORS: Record<string, string> = {\n running: 'text-status-active',\n completed: 'text-status-success',\n failed: 'text-status-error',\n};\n\nfunction buildColumns(\n onFilterEntity: (entity: string) => void,\n onFilterStatus: (status: string) => void,\n isSuperAdmin: boolean,\n navigate: (path: string) => void,\n tierMap: Map<string, WorkflowTier>,\n): Column<LTJob>[] {\n return [\n {\n key: 'workflow_id',\n label: 'Workflow ID',\n render: (row) => {\n const dotClass = STATUS_DOT[jobStatusMap[row.status] ?? row.status] ?? 'bg-status-pending';\n const pulseClass = row.status === 'running' ? ' animate-pulse' : '';\n return (\n <div className=\"flex items-center gap-2 min-w-0\">\n <span className={`w-1.5 h-1.5 shrink-0 rounded-full ${dotClass}${pulseClass}`} title={row.status} />\n <span className=\"font-mono text-xs text-text-primary truncate\">{row.workflow_id}</span>\n </div>\n );\n },\n },\n {\n key: 'entity',\n label: 'Type',\n render: (row) => <WorkflowPill type={row.entity} variant={tierMap.get(row.entity) ?? 'durable'} size=\"xs\" />,\n className: 'w-44 shrink-0',\n },\n {\n key: 'created_at',\n label: 'Created',\n render: (row) => <DateValue date={row.created_at} format=\"relative\" className=\"text-xs text-text-secondary whitespace-nowrap\" />,\n className: 'w-32',\n sortable: true,\n },\n {\n key: 'updated_at',\n label: 'Updated',\n render: (row) => <DateValue date={row.updated_at} format=\"relative\" className=\"text-xs text-text-secondary whitespace-nowrap\" />,\n className: 'w-32',\n sortable: true,\n },\n {\n key: 'duration',\n label: 'Duration',\n render: (row) => (\n <ElapsedCell\n startDate={row.created_at}\n endDate={row.status === 'running' ? null : row.updated_at}\n isLive={row.status === 'running'}\n />\n ),\n className: 'w-28',\n },\n {\n key: 'actions',\n label: '',\n render: (row) => (\n <RowActionGroup>\n <RowAction\n icon={Filter}\n title={`Filter by ${row.entity}`}\n onClick={() => onFilterEntity(row.entity)}\n />\n <button\n onClick={(e) => { e.stopPropagation(); onFilterStatus(row.status); }}\n className=\"opacity-0 group-hover/row:opacity-100 transition-opacity\"\n title={`Filter by ${row.status}`}\n >\n <svg className={`w-[18px] h-[18px] ${STATUS_COLORS[row.status] ?? 'text-text-tertiary'} hover:opacity-70`} viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <circle cx=\"12\" cy=\"12\" r=\"6\" />\n </svg>\n </button>\n {isSuperAdmin && (\n <RowAction\n icon={Settings}\n title=\"View config\"\n onClick={() => navigate(`/workflows/registry/${encodeURIComponent(row.entity)}`)}\n />\n )}\n </RowActionGroup>\n ),\n className: 'w-24 text-right',\n },\n ];\n}\n\nexport function WorkflowsDashboard({ tier: initialTier = 'all' }: { tier?: ExecutionsTier }) {\n useWorkflowListEvents();\n const navigate = useNavigate();\n const { isSuperAdmin } = useAuth();\n const { namespace } = useNamespace();\n\n const { filters, setFilter, pagination, sort, setSort } = useFilterParams({\n filters: { search: '', entity: '', status: '', tier: initialTier },\n });\n\n const activeTier = (filters.tier || 'all') as ExecutionsTier;\n\n // Map tier to server-side registered filter\n const registeredFilter = activeTier === 'certified' ? 'true'\n : activeTier === 'durable' ? 'false'\n : undefined;\n\n const { data: configs } = useWorkflowConfigs();\n const { data: discoveredData } = useDiscoveredWorkflows();\n\n const tierMap = useMemo(() => {\n const map = new Map<string, WorkflowTier>();\n for (const dw of discoveredData ?? []) {\n map.set(dw.workflow_type, dw.tier ?? 'durable');\n }\n return map;\n }, [discoveredData]);\n\n const columns = buildColumns(\n (entity) => setFilter('entity', entity),\n (status) => setFilter('status', status),\n isSuperAdmin,\n navigate,\n tierMap,\n );\n const [searchInput, setSearchInput] = useState(filters.search);\n\n useEffect(() => {\n if (searchInput === filters.search) return;\n const timer = setTimeout(() => setFilter('search', searchInput), 300);\n return () => clearTimeout(timer);\n }, [searchInput, setFilter, filters.search]);\n\n const { data: jobsData, isLoading, refetch, isFetching } = useJobs({\n limit: pagination.pageSize,\n offset: pagination.offset,\n entity: filters.entity || undefined,\n search: filters.search || undefined,\n status: filters.status || undefined,\n sort_by: sort.sort_by || 'created_at',\n order: sort.order || 'desc',\n registered: registeredFilter,\n namespace: namespace || undefined,\n });\n\n const total = jobsData?.total ?? 0;\n const jobs = jobsData?.jobs ?? [];\n\n const entities = useMemo(() => {\n return [...new Set((configs ?? []).map((c) => c.workflow_type))].sort();\n }, [configs]);\n\n const pageTitle = 'Workflow Executions';\n\n const emptyMessage = activeTier === 'certified'\n ? 'No certified workflow executions found'\n : activeTier === 'durable'\n ? 'No durable workflow executions found'\n : 'No workflow executions found';\n\n return (\n <div>\n <PageHeader title={pageTitle} docsHash=\"#docs:dashboard.md:durable-executions\" />\n\n <FilterBar actions={\n <ListToolbar\n onRefresh={() => refetch()}\n isFetching={isFetching}\n apiPath={buildApiPath('/workflow-states/jobs', {\n limit: pagination.pageSize,\n offset: pagination.offset,\n entity: filters.entity || undefined,\n search: filters.search || undefined,\n status: filters.status || undefined,\n sort_by: sort.sort_by || 'created_at',\n order: sort.order || 'desc',\n registered: registeredFilter,\n namespace: namespace || undefined,\n })}\n />\n }>\n <input\n type=\"text\"\n placeholder=\"Search workflow ID...\"\n value={searchInput}\n onChange={(e) => setSearchInput(e.target.value)}\n className=\"input text-[11px] py-1 px-2 w-56\"\n />\n <FilterDivider />\n <FilterSelect\n label=\"Type\"\n value={filters.entity}\n onChange={(v) => setFilter('entity', v)}\n options={entities.map((e) => ({ value: e, label: e }))}\n />\n <FilterDivider />\n <FilterSelect\n label=\"Status\"\n value={filters.status}\n onChange={(v) => setFilter('status', v)}\n options={[\n { value: 'running', label: 'Running' },\n { value: 'completed', label: 'Completed' },\n { value: 'failed', label: 'Failed' },\n ]}\n />\n <FilterDivider />\n <FilterSelect\n label=\"Tier\"\n value={filters.tier === 'all' ? '' : filters.tier}\n onChange={(v) => setFilter('tier', v || 'all')}\n options={[\n { value: 'certified', label: 'Certified' },\n { value: 'durable', label: 'Durable' },\n ]}\n />\n </FilterBar>\n\n <DataTable\n columns={columns}\n data={jobs}\n keyFn={(row) => row.workflow_id}\n onRowClick={(row) => navigate(`/workflows/executions/${row.workflow_id}`)}\n isLoading={isLoading}\n emptyMessage={emptyMessage}\n sort={sort}\n onSort={setSort}\n />\n\n <StickyPagination\n page={pagination.page}\n totalPages={pagination.totalPages(total)}\n onPageChange={pagination.setPage}\n total={total}\n pageSize={pagination.pageSize}\n onPageSizeChange={pagination.setPageSize}\n />\n </div>\n );\n}\n"],"names":["jobStatusMap","STATUS_DOT","STATUS_COLORS","buildColumns","onFilterEntity","onFilterStatus","isSuperAdmin","navigate","tierMap","row","dotClass","pulseClass","jsxs","jsx","WorkflowPill","DateValue","ElapsedCell","RowActionGroup","RowAction","Filter","e","Settings","WorkflowsDashboard","initialTier","useWorkflowListEvents","useNavigate","useAuth","namespace","useNamespace","filters","setFilter","pagination","sort","setSort","useFilterParams","activeTier","registeredFilter","configs","useWorkflowConfigs","discoveredData","useDiscoveredWorkflows","useMemo","map","dw","columns","entity","status","searchInput","setSearchInput","useState","useEffect","timer","jobsData","isLoading","refetch","isFetching","useJobs","total","jobs","entities","c","pageTitle","emptyMessage","PageHeader","FilterBar","ListToolbar","buildApiPath","FilterDivider","FilterSelect","v","DataTable","StickyPagination"],"mappings":"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"}
|
package/dashboard/dist/assets/{WorkflowsOverview-ihhW8DiS.js → WorkflowsOverview-CjBWlwlH.js}
RENAMED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as x,j as t}from"./vendor-query-B2UbickB.js";import{b as C,u as k}from"./workflows-
|
|
2
|
-
//# sourceMappingURL=WorkflowsOverview-
|
|
1
|
+
import{a as x,j as t}from"./vendor-query-B2UbickB.js";import{b as C,u as k}from"./workflows-BTkHs6VT.js";import{b as $}from"./useEventHooks-DlWkui_n.js";import{P as D}from"./PageHeader-CFta2VaS.js";import{S as h}from"./StatCard-DlgF0CJC.js";import{c as w}from"./vendor-react-CXumBFUA.js";import"./index-CKXSKsVZ.js";import"./vendor-icons-BaQqUm-e.js";const v=[{label:"1h",ms:36e5},{label:"24h",ms:864e5},{label:"7d",ms:6048e5},{label:"30d",ms:2592e6}];function T(r){return r<1e3?`${Math.round(r)}ms`:r<6e4?`${(r/1e3).toFixed(1)}s`:r<36e5?`${(r/6e4).toFixed(1)}m`:`${(r/36e5).toFixed(1)}h`}function p({value:r,colorClass:o,onClick:f}){return r===0?t.jsx("span",{className:"text-text-tertiary",children:"0"}):t.jsx("button",{onClick:f,className:`${o} hover:underline tabular-nums font-medium`,children:r})}function _(){$();const r=w(),[o,f]=x.useState("24h"),{data:c}=C({limit:500}),{data:g}=k(),b=x.useMemo(()=>{const e=v.find(i=>i.label===o);return Date.now()-e.ms},[o]),n=x.useMemo(()=>((c==null?void 0:c.jobs)??[]).filter(e=>new Date(e.created_at).getTime()>=b),[c==null?void 0:c.jobs,b]),j=x.useMemo(()=>{const e=new Map;for(const a of n){const s=e.get(a.entity)??{total:0,running:0,completed:0,failed:0,durations:[]};if(s.total++,a.status==="running"&&s.running++,a.status==="completed"){s.completed++;const m=new Date(a.updated_at).getTime()-new Date(a.created_at).getTime();m>0&&s.durations.push(m)}a.status==="failed"&&s.failed++,e.set(a.entity,s)}const i=[];for(const[a,s]of e)i.push({type:a,...s,avgDuration:s.durations.length>0?s.durations.reduce((m,N)=>m+N,0)/s.durations.length:null});return i.sort((a,s)=>s.total-a.total)},[n]),u=x.useMemo(()=>({total:n.length,running:n.filter(e=>e.status==="running").length,completed:n.filter(e=>e.status==="completed").length,failed:n.filter(e=>e.status==="failed").length}),[n]),y=(g==null?void 0:g.length)??0,l=(e,i)=>{const a=new URLSearchParams;e&&a.set("entity",e),i&&a.set("status",i);const s=a.toString();r(`/workflows/executions${s?`?${s}`:""}`)},d="pb-2 text-[10px] font-semibold uppercase tracking-widest text-text-tertiary";return t.jsxs("div",{children:[t.jsx(D,{title:"Workflows",actions:t.jsxs("span",{className:"text-xs text-text-tertiary",children:[y," certified type",y!==1?"s":""]})}),t.jsx("div",{className:"flex items-center gap-1 mb-6",children:v.map(e=>t.jsx("button",{onClick:()=>f(e.label),className:`px-3 py-1 text-xs rounded-full transition-colors ${o===e.label?"bg-accent text-text-inverse":"text-text-tertiary hover:text-text-primary hover:bg-surface-hover"}`,children:e.label},e.label))}),t.jsxs("div",{className:"grid grid-cols-4 gap-4 mb-8",children:[t.jsx(h,{label:"Total",value:u.total,onClick:()=>l()}),t.jsx(h,{label:"Running",value:u.running,colorClass:"text-status-active",onClick:()=>l(void 0,"running")}),t.jsx(h,{label:"Completed",value:u.completed,colorClass:"text-status-success",onClick:()=>l(void 0,"completed")}),t.jsx(h,{label:"Failed",value:u.failed,colorClass:"text-status-error",onClick:()=>l(void 0,"failed")})]}),j.length>0&&t.jsxs("table",{className:"w-full text-left",children:[t.jsx("thead",{children:t.jsxs("tr",{className:"border-b border-surface-border",children:[t.jsx("th",{className:d,children:"Type"}),t.jsx("th",{className:`${d} text-right w-20`,children:"Total"}),t.jsx("th",{className:`${d} text-right w-20`,children:"Running"}),t.jsx("th",{className:`${d} text-right w-24`,children:"Completed"}),t.jsx("th",{className:`${d} text-right w-20`,children:"Failed"}),t.jsx("th",{className:`${d} text-right w-28`,children:"Avg Duration"})]})}),t.jsx("tbody",{children:j.map(e=>t.jsxs("tr",{className:"border-b border-surface-border last:border-b-0",children:[t.jsx("td",{className:"py-3 text-sm font-mono text-text-primary",children:t.jsx("button",{onClick:()=>l(e.type),className:"hover:text-accent hover:underline",children:e.type})}),t.jsx("td",{className:"py-3 text-sm text-right",children:t.jsx(p,{value:e.total,colorClass:"text-text-secondary",onClick:()=>l(e.type)})}),t.jsx("td",{className:"py-3 text-sm text-right",children:t.jsx(p,{value:e.running,colorClass:"text-status-active",onClick:()=>l(e.type,"running")})}),t.jsx("td",{className:"py-3 text-sm text-right",children:t.jsx(p,{value:e.completed,colorClass:"text-status-success",onClick:()=>l(e.type,"completed")})}),t.jsx("td",{className:"py-3 text-sm text-right",children:t.jsx(p,{value:e.failed,colorClass:"text-status-error",onClick:()=>l(e.type,"failed")})}),t.jsx("td",{className:"py-3 text-sm font-mono text-text-secondary text-right",children:e.avgDuration!==null?T(e.avgDuration):"—"})]},e.type))})]}),j.length===0&&t.jsx("div",{className:"py-16 text-center",children:t.jsxs("p",{className:"text-sm text-text-tertiary",children:["No workflow activity in the last ",o]})})]})}export{_ as WorkflowsOverview};
|
|
2
|
+
//# sourceMappingURL=WorkflowsOverview-CjBWlwlH.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkflowsOverview-ihhW8DiS.js","sources":["../../src/pages/workflows/WorkflowsOverview.tsx"],"sourcesContent":["import { useState, useMemo } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { useJobs, useWorkflowConfigs } from '../../api/workflows';\nimport { useWorkflowListEvents } from '../../hooks/useEventHooks';\nimport { PageHeader } from '../../components/common/layout/PageHeader';\nimport { StatCard } from '../../components/common/data/StatCard';\n\n// ── Duration filter ──────────────────────────────────────────────────────────\n\nconst DURATIONS = [\n { label: '1h', ms: 3_600_000 },\n { label: '24h', ms: 86_400_000 },\n { label: '7d', ms: 604_800_000 },\n { label: '30d', ms: 2_592_000_000 },\n] as const;\n\ntype DurationLabel = (typeof DURATIONS)[number]['label'];\n\n// ── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction formatDuration(ms: number): string {\n if (ms < 1000) return `${Math.round(ms)}ms`;\n if (ms < 60_000) return `${(ms / 1000).toFixed(1)}s`;\n if (ms < 3_600_000) return `${(ms / 60_000).toFixed(1)}m`;\n return `${(ms / 3_600_000).toFixed(1)}h`;\n}\n\ninterface TypeStats {\n type: string;\n total: number;\n running: number;\n completed: number;\n failed: number;\n avgDuration: number | null;\n}\n\n// ── Clickable stat cell ──────────────────────────────────────────────────────\n\nfunction StatCell({\n value,\n colorClass,\n onClick,\n}: {\n value: number;\n colorClass: string;\n onClick: () => void;\n}) {\n if (value === 0) {\n return <span className=\"text-text-tertiary\">0</span>;\n }\n return (\n <button\n onClick={onClick}\n className={`${colorClass} hover:underline tabular-nums font-medium`}\n >\n {value}\n </button>\n );\n}\n\n// ── Page ─────────────────────────────────────────────────────────────────────\n\nexport function WorkflowsOverview() {\n useWorkflowListEvents();\n const navigate = useNavigate();\n const [duration, setDuration] = useState<DurationLabel>('24h');\n\n const { data: allJobs } = useJobs({ limit: 500 });\n const { data: configs } = useWorkflowConfigs();\n\n const cutoff = useMemo(() => {\n const d = DURATIONS.find((d) => d.label === duration)!;\n return Date.now() - d.ms;\n }, [duration]);\n\n const jobs = useMemo(\n () => (allJobs?.jobs ?? []).filter((j) => new Date(j.created_at).getTime() >= cutoff),\n [allJobs?.jobs, cutoff],\n );\n\n const byType = useMemo(() => {\n const map = new Map<string, { total: number; running: number; completed: number; failed: number; durations: number[] }>();\n for (const j of jobs) {\n const entry = map.get(j.entity) ?? { total: 0, running: 0, completed: 0, failed: 0, durations: [] };\n entry.total++;\n if (j.status === 'running') entry.running++;\n if (j.status === 'completed') {\n entry.completed++;\n const dur = new Date(j.updated_at).getTime() - new Date(j.created_at).getTime();\n if (dur > 0) entry.durations.push(dur);\n }\n if (j.status === 'failed') entry.failed++;\n map.set(j.entity, entry);\n }\n\n const result: TypeStats[] = [];\n for (const [type, stats] of map) {\n result.push({\n type,\n ...stats,\n avgDuration: stats.durations.length > 0\n ? stats.durations.reduce((a, b) => a + b, 0) / stats.durations.length\n : null,\n });\n }\n return result.sort((a, b) => b.total - a.total);\n }, [jobs]);\n\n // Totals\n const totals = useMemo(() => ({\n total: jobs.length,\n running: jobs.filter((j) => j.status === 'running').length,\n completed: jobs.filter((j) => j.status === 'completed').length,\n failed: jobs.filter((j) => j.status === 'failed').length,\n }), [jobs]);\n\n const registered = configs?.length ?? 0;\n\n const goToList = (entity?: string, status?: string) => {\n const params = new URLSearchParams();\n if (entity) params.set('entity', entity);\n if (status) params.set('status', status);\n const qs = params.toString();\n navigate(`/workflows/executions${qs ? `?${qs}` : ''}`);\n };\n\n const thCls = 'pb-2 text-[10px] font-semibold uppercase tracking-widest text-text-tertiary';\n\n return (\n <div>\n <PageHeader\n title=\"Workflows\"\n actions={\n <span className=\"text-xs text-text-tertiary\">\n {registered} certified type{registered !== 1 ? 's' : ''}\n </span>\n }\n />\n\n {/* Duration tabs */}\n <div className=\"flex items-center gap-1 mb-6\">\n {DURATIONS.map((d) => (\n <button\n key={d.label}\n onClick={() => setDuration(d.label)}\n className={`px-3 py-1 text-xs rounded-full transition-colors ${\n duration === d.label\n ? 'bg-accent text-text-inverse'\n : 'text-text-tertiary hover:text-text-primary hover:bg-surface-hover'\n }`}\n >\n {d.label}\n </button>\n ))}\n </div>\n\n {/* Summary cards */}\n <div className=\"grid grid-cols-4 gap-4 mb-8\">\n <StatCard label=\"Total\" value={totals.total} onClick={() => goToList()} />\n <StatCard label=\"Running\" value={totals.running} colorClass=\"text-status-active\" onClick={() => goToList(undefined, 'running')} />\n <StatCard label=\"Completed\" value={totals.completed} colorClass=\"text-status-success\" onClick={() => goToList(undefined, 'completed')} />\n <StatCard label=\"Failed\" value={totals.failed} colorClass=\"text-status-error\" onClick={() => goToList(undefined, 'failed')} />\n </div>\n\n {/* By-type table */}\n {byType.length > 0 && (\n <table className=\"w-full text-left\">\n <thead>\n <tr className=\"border-b border-surface-border\">\n <th className={thCls}>Type</th>\n <th className={`${thCls} text-right w-20`}>Total</th>\n <th className={`${thCls} text-right w-20`}>Running</th>\n <th className={`${thCls} text-right w-24`}>Completed</th>\n <th className={`${thCls} text-right w-20`}>Failed</th>\n <th className={`${thCls} text-right w-28`}>Avg Duration</th>\n </tr>\n </thead>\n <tbody>\n {byType.map((row) => (\n <tr key={row.type} className=\"border-b border-surface-border last:border-b-0\">\n <td className=\"py-3 text-sm font-mono text-text-primary\">\n <button\n onClick={() => goToList(row.type)}\n className=\"hover:text-accent hover:underline\"\n >\n {row.type}\n </button>\n </td>\n <td className=\"py-3 text-sm text-right\">\n <StatCell value={row.total} colorClass=\"text-text-secondary\" onClick={() => goToList(row.type)} />\n </td>\n <td className=\"py-3 text-sm text-right\">\n <StatCell value={row.running} colorClass=\"text-status-active\" onClick={() => goToList(row.type, 'running')} />\n </td>\n <td className=\"py-3 text-sm text-right\">\n <StatCell value={row.completed} colorClass=\"text-status-success\" onClick={() => goToList(row.type, 'completed')} />\n </td>\n <td className=\"py-3 text-sm text-right\">\n <StatCell value={row.failed} colorClass=\"text-status-error\" onClick={() => goToList(row.type, 'failed')} />\n </td>\n <td className=\"py-3 text-sm font-mono text-text-secondary text-right\">\n {row.avgDuration !== null ? formatDuration(row.avgDuration) : '—'}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n )}\n\n {byType.length === 0 && (\n <div className=\"py-16 text-center\">\n <p className=\"text-sm text-text-tertiary\">\n No workflow activity in the last {duration}\n </p>\n </div>\n )}\n </div>\n );\n}"],"names":["DURATIONS","formatDuration","ms","StatCell","value","colorClass","onClick","jsx","WorkflowsOverview","useWorkflowListEvents","navigate","useNavigate","duration","setDuration","useState","allJobs","useJobs","configs","useWorkflowConfigs","cutoff","useMemo","d","jobs","j","byType","map","entry","dur","result","type","stats","a","b","totals","registered","goToList","entity","status","params","qs","thCls","PageHeader","jsxs","StatCard","row"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"WorkflowsOverview-CjBWlwlH.js","sources":["../../src/pages/workflows/WorkflowsOverview.tsx"],"sourcesContent":["import { useState, useMemo } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { useJobs, useWorkflowConfigs } from '../../api/workflows';\nimport { useWorkflowListEvents } from '../../hooks/useEventHooks';\nimport { PageHeader } from '../../components/common/layout/PageHeader';\nimport { StatCard } from '../../components/common/data/StatCard';\n\n// ── Duration filter ──────────────────────────────────────────────────────────\n\nconst DURATIONS = [\n { label: '1h', ms: 3_600_000 },\n { label: '24h', ms: 86_400_000 },\n { label: '7d', ms: 604_800_000 },\n { label: '30d', ms: 2_592_000_000 },\n] as const;\n\ntype DurationLabel = (typeof DURATIONS)[number]['label'];\n\n// ── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction formatDuration(ms: number): string {\n if (ms < 1000) return `${Math.round(ms)}ms`;\n if (ms < 60_000) return `${(ms / 1000).toFixed(1)}s`;\n if (ms < 3_600_000) return `${(ms / 60_000).toFixed(1)}m`;\n return `${(ms / 3_600_000).toFixed(1)}h`;\n}\n\ninterface TypeStats {\n type: string;\n total: number;\n running: number;\n completed: number;\n failed: number;\n avgDuration: number | null;\n}\n\n// ── Clickable stat cell ──────────────────────────────────────────────────────\n\nfunction StatCell({\n value,\n colorClass,\n onClick,\n}: {\n value: number;\n colorClass: string;\n onClick: () => void;\n}) {\n if (value === 0) {\n return <span className=\"text-text-tertiary\">0</span>;\n }\n return (\n <button\n onClick={onClick}\n className={`${colorClass} hover:underline tabular-nums font-medium`}\n >\n {value}\n </button>\n );\n}\n\n// ── Page ─────────────────────────────────────────────────────────────────────\n\nexport function WorkflowsOverview() {\n useWorkflowListEvents();\n const navigate = useNavigate();\n const [duration, setDuration] = useState<DurationLabel>('24h');\n\n const { data: allJobs } = useJobs({ limit: 500 });\n const { data: configs } = useWorkflowConfigs();\n\n const cutoff = useMemo(() => {\n const d = DURATIONS.find((d) => d.label === duration)!;\n return Date.now() - d.ms;\n }, [duration]);\n\n const jobs = useMemo(\n () => (allJobs?.jobs ?? []).filter((j) => new Date(j.created_at).getTime() >= cutoff),\n [allJobs?.jobs, cutoff],\n );\n\n const byType = useMemo(() => {\n const map = new Map<string, { total: number; running: number; completed: number; failed: number; durations: number[] }>();\n for (const j of jobs) {\n const entry = map.get(j.entity) ?? { total: 0, running: 0, completed: 0, failed: 0, durations: [] };\n entry.total++;\n if (j.status === 'running') entry.running++;\n if (j.status === 'completed') {\n entry.completed++;\n const dur = new Date(j.updated_at).getTime() - new Date(j.created_at).getTime();\n if (dur > 0) entry.durations.push(dur);\n }\n if (j.status === 'failed') entry.failed++;\n map.set(j.entity, entry);\n }\n\n const result: TypeStats[] = [];\n for (const [type, stats] of map) {\n result.push({\n type,\n ...stats,\n avgDuration: stats.durations.length > 0\n ? stats.durations.reduce((a, b) => a + b, 0) / stats.durations.length\n : null,\n });\n }\n return result.sort((a, b) => b.total - a.total);\n }, [jobs]);\n\n // Totals\n const totals = useMemo(() => ({\n total: jobs.length,\n running: jobs.filter((j) => j.status === 'running').length,\n completed: jobs.filter((j) => j.status === 'completed').length,\n failed: jobs.filter((j) => j.status === 'failed').length,\n }), [jobs]);\n\n const registered = configs?.length ?? 0;\n\n const goToList = (entity?: string, status?: string) => {\n const params = new URLSearchParams();\n if (entity) params.set('entity', entity);\n if (status) params.set('status', status);\n const qs = params.toString();\n navigate(`/workflows/executions${qs ? `?${qs}` : ''}`);\n };\n\n const thCls = 'pb-2 text-[10px] font-semibold uppercase tracking-widest text-text-tertiary';\n\n return (\n <div>\n <PageHeader\n title=\"Workflows\"\n actions={\n <span className=\"text-xs text-text-tertiary\">\n {registered} certified type{registered !== 1 ? 's' : ''}\n </span>\n }\n />\n\n {/* Duration tabs */}\n <div className=\"flex items-center gap-1 mb-6\">\n {DURATIONS.map((d) => (\n <button\n key={d.label}\n onClick={() => setDuration(d.label)}\n className={`px-3 py-1 text-xs rounded-full transition-colors ${\n duration === d.label\n ? 'bg-accent text-text-inverse'\n : 'text-text-tertiary hover:text-text-primary hover:bg-surface-hover'\n }`}\n >\n {d.label}\n </button>\n ))}\n </div>\n\n {/* Summary cards */}\n <div className=\"grid grid-cols-4 gap-4 mb-8\">\n <StatCard label=\"Total\" value={totals.total} onClick={() => goToList()} />\n <StatCard label=\"Running\" value={totals.running} colorClass=\"text-status-active\" onClick={() => goToList(undefined, 'running')} />\n <StatCard label=\"Completed\" value={totals.completed} colorClass=\"text-status-success\" onClick={() => goToList(undefined, 'completed')} />\n <StatCard label=\"Failed\" value={totals.failed} colorClass=\"text-status-error\" onClick={() => goToList(undefined, 'failed')} />\n </div>\n\n {/* By-type table */}\n {byType.length > 0 && (\n <table className=\"w-full text-left\">\n <thead>\n <tr className=\"border-b border-surface-border\">\n <th className={thCls}>Type</th>\n <th className={`${thCls} text-right w-20`}>Total</th>\n <th className={`${thCls} text-right w-20`}>Running</th>\n <th className={`${thCls} text-right w-24`}>Completed</th>\n <th className={`${thCls} text-right w-20`}>Failed</th>\n <th className={`${thCls} text-right w-28`}>Avg Duration</th>\n </tr>\n </thead>\n <tbody>\n {byType.map((row) => (\n <tr key={row.type} className=\"border-b border-surface-border last:border-b-0\">\n <td className=\"py-3 text-sm font-mono text-text-primary\">\n <button\n onClick={() => goToList(row.type)}\n className=\"hover:text-accent hover:underline\"\n >\n {row.type}\n </button>\n </td>\n <td className=\"py-3 text-sm text-right\">\n <StatCell value={row.total} colorClass=\"text-text-secondary\" onClick={() => goToList(row.type)} />\n </td>\n <td className=\"py-3 text-sm text-right\">\n <StatCell value={row.running} colorClass=\"text-status-active\" onClick={() => goToList(row.type, 'running')} />\n </td>\n <td className=\"py-3 text-sm text-right\">\n <StatCell value={row.completed} colorClass=\"text-status-success\" onClick={() => goToList(row.type, 'completed')} />\n </td>\n <td className=\"py-3 text-sm text-right\">\n <StatCell value={row.failed} colorClass=\"text-status-error\" onClick={() => goToList(row.type, 'failed')} />\n </td>\n <td className=\"py-3 text-sm font-mono text-text-secondary text-right\">\n {row.avgDuration !== null ? formatDuration(row.avgDuration) : '—'}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n )}\n\n {byType.length === 0 && (\n <div className=\"py-16 text-center\">\n <p className=\"text-sm text-text-tertiary\">\n No workflow activity in the last {duration}\n </p>\n </div>\n )}\n </div>\n );\n}"],"names":["DURATIONS","formatDuration","ms","StatCell","value","colorClass","onClick","jsx","WorkflowsOverview","useWorkflowListEvents","navigate","useNavigate","duration","setDuration","useState","allJobs","useJobs","configs","useWorkflowConfigs","cutoff","useMemo","d","jobs","j","byType","map","entry","dur","result","type","stats","a","b","totals","registered","goToList","entity","status","params","qs","thCls","PageHeader","jsxs","StatCard","row"],"mappings":"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"}
|