@hotmeshio/long-tail 0.8.5 → 0.9.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/roles.d.ts +21 -0
- package/build/api/roles.js +50 -0
- package/build/lib/db/schemas/021_role_list_schema.sql +27 -0
- package/build/routes/roles.js +20 -0
- package/build/services/role/index.d.ts +13 -1
- package/build/services/role/index.js +27 -0
- package/build/services/role/sql.d.ts +14 -2
- package/build/services/role/sql.js +51 -3
- package/build/services/role/types.d.ts +27 -0
- package/dashboard/dist/assets/{AdminDashboard-RrSvb8d-.js → AdminDashboard-5bWcBxyS.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-RrSvb8d-.js.map → AdminDashboard-5bWcBxyS.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-5RMdI0ku.js → AgentConfigPage-CVg_tFbf.js} +6 -6
- package/dashboard/dist/assets/{AgentConfigPage-5RMdI0ku.js.map → AgentConfigPage-CVg_tFbf.js.map} +1 -1
- package/dashboard/dist/assets/{AgentDetailPage-C_-sIBcr.js → AgentDetailPage-CLlkIoRQ.js} +4 -4
- package/dashboard/dist/assets/{AgentDetailPage-C_-sIBcr.js.map → AgentDetailPage-CLlkIoRQ.js.map} +1 -1
- package/dashboard/dist/assets/{AgentsPage-CxNNtSsf.js → AgentsPage-CjruF_ek.js} +2 -2
- package/dashboard/dist/assets/{AgentsPage-CxNNtSsf.js.map → AgentsPage-CjruF_ek.js.map} +1 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-h6awiuVk.js +2 -0
- package/dashboard/dist/assets/AvailableEscalationsPage-h6awiuVk.js.map +1 -0
- package/dashboard/dist/assets/{BotPicker-BQVz6bye.js → BotPicker-CGEFHHDE.js} +2 -2
- package/dashboard/dist/assets/{BotPicker-BQVz6bye.js.map → BotPicker-CGEFHHDE.js.map} +1 -1
- package/dashboard/dist/assets/{CapabilitiesPage-DlZ8SgO3.js → CapabilitiesPage-BI1tNYun.js} +2 -2
- package/dashboard/dist/assets/{CapabilitiesPage-DlZ8SgO3.js.map → CapabilitiesPage-BI1tNYun.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-lo8Qx4zb.js → CollapsibleSection-B9f52Z2K.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-lo8Qx4zb.js.map → CollapsibleSection-B9f52Z2K.js.map} +1 -1
- package/dashboard/dist/assets/{CopyableId-blg-gZvT.js → CopyableId-uot2mE_g.js} +2 -2
- package/dashboard/dist/assets/{CopyableId-blg-gZvT.js.map → CopyableId-uot2mE_g.js.map} +1 -1
- package/dashboard/dist/assets/CountdownTimer-C71erQ67.js +2 -0
- package/dashboard/dist/assets/CountdownTimer-C71erQ67.js.map +1 -0
- package/dashboard/dist/assets/{CredentialsPage-DJ9DyXsO.js → CredentialsPage-smk5H_mP.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-DJ9DyXsO.js.map → CredentialsPage-smk5H_mP.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-o0dbisw1.js → CronLabel-CCJLmkIq.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-o0dbisw1.js.map → CronLabel-CCJLmkIq.js.map} +1 -1
- package/dashboard/dist/assets/CustomDurationPicker-DQ28g5GB.js +2 -0
- package/dashboard/dist/assets/CustomDurationPicker-DQ28g5GB.js.map +1 -0
- package/dashboard/dist/assets/DataTable-Byn3oyT9.js +2 -0
- package/dashboard/dist/assets/DataTable-Byn3oyT9.js.map +1 -0
- package/dashboard/dist/assets/{DropZone-SgiK1WOl.js → DropZone-C_Mc4UrO.js} +2 -2
- package/dashboard/dist/assets/{DropZone-SgiK1WOl.js.map → DropZone-C_Mc4UrO.js.map} +1 -1
- package/dashboard/dist/assets/{ElapsedCell-N22STQcg.js → ElapsedCell-Cw1uvJKx.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-N22STQcg.js.map → ElapsedCell-Cw1uvJKx.js.map} +1 -1
- package/dashboard/dist/assets/EscalationListSchemaPage-3v2tiCnq.js +20 -0
- package/dashboard/dist/assets/EscalationListSchemaPage-3v2tiCnq.js.map +1 -0
- package/dashboard/dist/assets/{EscalationSchemaPage-Zsmewko2.js → EscalationSchemaPage-DIq2pMED.js} +2 -2
- package/dashboard/dist/assets/{EscalationSchemaPage-Zsmewko2.js.map → EscalationSchemaPage-DIq2pMED.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationsOverview-CE2p70Ct.js → EscalationsOverview-BqOZ1v8w.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-CE2p70Ct.js.map → EscalationsOverview-BqOZ1v8w.js.map} +1 -1
- package/dashboard/dist/assets/EventTable-CyfHfOWj.js +2 -0
- package/dashboard/dist/assets/EventTable-CyfHfOWj.js.map +1 -0
- package/dashboard/dist/assets/{FilterBar-B4Mk2PvT.js → FilterBar-DDIn8TOs.js} +2 -2
- package/dashboard/dist/assets/{FilterBar-B4Mk2PvT.js.map → FilterBar-DDIn8TOs.js.map} +1 -1
- package/dashboard/dist/assets/{GraphInvokePage-DywWVSdj.js → GraphInvokePage-DbNUaWhH.js} +2 -2
- package/dashboard/dist/assets/{GraphInvokePage-DywWVSdj.js.map → GraphInvokePage-DbNUaWhH.js.map} +1 -1
- package/dashboard/dist/assets/{HomePage-CxtBiULd.js → HomePage-Cj9sLt4Z.js} +2 -2
- package/dashboard/dist/assets/{HomePage-CxtBiULd.js.map → HomePage-Cj9sLt4Z.js.map} +1 -1
- package/dashboard/dist/assets/{ListToolbar-Ok2O0wmC.js → ListToolbar-D7PoQOZC.js} +2 -2
- package/dashboard/dist/assets/{ListToolbar-Ok2O0wmC.js.map → ListToolbar-D7PoQOZC.js.map} +1 -1
- package/dashboard/dist/assets/{McpOverview-CTCYZXIp.js → McpOverview-D9g1iJyn.js} +2 -2
- package/dashboard/dist/assets/{McpOverview-CTCYZXIp.js.map → McpOverview-D9g1iJyn.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryDetailPage-BOaXf0bZ.js → McpQueryDetailPage-DwS1pXdT.js} +2 -2
- package/dashboard/dist/assets/{McpQueryDetailPage-BOaXf0bZ.js.map → McpQueryDetailPage-DwS1pXdT.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryPage-BbYojoHu.js → McpQueryPage-DZQ1z6-H.js} +2 -2
- package/dashboard/dist/assets/{McpQueryPage-BbYojoHu.js.map → McpQueryPage-DZQ1z6-H.js.map} +1 -1
- package/dashboard/dist/assets/McpRunDetailPage-Bx6w39lr.js +2 -0
- package/dashboard/dist/assets/{McpRunDetailPage-CXGCVmPq.js.map → McpRunDetailPage-Bx6w39lr.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunsPage-Df1GqxUg.js → McpRunsPage-C-oS_tTh.js} +2 -2
- package/dashboard/dist/assets/{McpRunsPage-Df1GqxUg.js.map → McpRunsPage-C-oS_tTh.js.map} +1 -1
- package/dashboard/dist/assets/{NamespacePill-SErKwgkb.js → NamespacePill-DhgC3EUO.js} +2 -2
- package/dashboard/dist/assets/{NamespacePill-SErKwgkb.js.map → NamespacePill-DhgC3EUO.js.map} +1 -1
- package/dashboard/dist/assets/OperationsPage-CQzX6jM1.js +2 -0
- package/dashboard/dist/assets/OperationsPage-CQzX6jM1.js.map +1 -0
- package/dashboard/dist/assets/OperatorDashboard-Cqf87ojd.js +2 -0
- package/dashboard/dist/assets/{OperatorDashboard-DIR7XDeD.js.map → OperatorDashboard-Cqf87ojd.js.map} +1 -1
- package/dashboard/dist/assets/PageHeader-sGNTmSXX.js +2 -0
- package/dashboard/dist/assets/PageHeader-sGNTmSXX.js.map +1 -0
- package/dashboard/dist/assets/{PageHeaderWithStats-W3akV6nB.js → PageHeaderWithStats-87STTAJX.js} +2 -2
- package/dashboard/dist/assets/{PageHeaderWithStats-W3akV6nB.js.map → PageHeaderWithStats-87STTAJX.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessDetailPage-BuSi654J.js → ProcessDetailPage-CplnDXkz.js} +2 -2
- package/dashboard/dist/assets/{ProcessDetailPage-BuSi654J.js.map → ProcessDetailPage-CplnDXkz.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessesListPage-Dhik7XpW.js → ProcessesListPage-DFOJC27f.js} +2 -2
- package/dashboard/dist/assets/{ProcessesListPage-Dhik7XpW.js.map → ProcessesListPage-DFOJC27f.js.map} +1 -1
- package/dashboard/dist/assets/RoleDetailPage-VrWOaPlg.js +8 -0
- package/dashboard/dist/assets/RoleDetailPage-VrWOaPlg.js.map +1 -0
- package/dashboard/dist/assets/{RolePill-DHWixsQR.js → RolePill-C91qbDOW.js} +2 -2
- package/dashboard/dist/assets/{RolePill-DHWixsQR.js.map → RolePill-C91qbDOW.js.map} +1 -1
- package/dashboard/dist/assets/{RolesPage-BRicD5mx.js → RolesPage-DdI1rVAP.js} +2 -2
- package/dashboard/dist/assets/{RolesPage-BRicD5mx.js.map → RolesPage-DdI1rVAP.js.map} +1 -1
- package/dashboard/dist/assets/{RunAsSelector-DipyBf_T.js → RunAsSelector-C6EozzKV.js} +2 -2
- package/dashboard/dist/assets/{RunAsSelector-DipyBf_T.js.map → RunAsSelector-C6EozzKV.js.map} +1 -1
- package/dashboard/dist/assets/SlidePanel-BpWveV1T.js +2 -0
- package/dashboard/dist/assets/SlidePanel-BpWveV1T.js.map +1 -0
- package/dashboard/dist/assets/{StatusBadge-DZ9137bI.js → StatusBadge-CEQMRmSQ.js} +2 -2
- package/dashboard/dist/assets/StatusBadge-CEQMRmSQ.js.map +1 -0
- package/dashboard/dist/assets/{StickyPagination-CD4W450h.js → StickyPagination-BEgkYJ0-.js} +2 -2
- package/dashboard/dist/assets/{StickyPagination-CD4W450h.js.map → StickyPagination-BEgkYJ0-.js.map} +1 -1
- package/dashboard/dist/assets/{StreamMessageDetail-BbDdWDUY.js → StreamMessageDetail-DWVPtzj7.js} +2 -2
- package/dashboard/dist/assets/{StreamMessageDetail-BbDdWDUY.js.map → StreamMessageDetail-DWVPtzj7.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-Bktv2vi5.js → SwimlaneTimeline-4NrDJNYc.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-Bktv2vi5.js.map → SwimlaneTimeline-4NrDJNYc.js.map} +1 -1
- package/dashboard/dist/assets/{TagInput-CGGC3DTR.js → TagInput-Csm36_pS.js} +2 -2
- package/dashboard/dist/assets/{TagInput-CGGC3DTR.js.map → TagInput-Csm36_pS.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-pSU3xuG9.js → TaskDetailPage-BvdaAUtF.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-pSU3xuG9.js.map → TaskDetailPage-BvdaAUtF.js.map} +1 -1
- package/dashboard/dist/assets/{TaskQueuePill-D6omQJNY.js → TaskQueuePill-5XdNaqwM.js} +2 -2
- package/dashboard/dist/assets/{TaskQueuePill-D6omQJNY.js.map → TaskQueuePill-5XdNaqwM.js.map} +1 -1
- package/dashboard/dist/assets/{TasksListPage-M6ok-Nfd.js → TasksListPage-BxA161LH.js} +2 -2
- package/dashboard/dist/assets/{TasksListPage-M6ok-Nfd.js.map → TasksListPage-BxA161LH.js.map} +1 -1
- package/dashboard/dist/assets/{TimeAgo-DVWhRNbi.js → TimeAgo-ChwJ4fjZ.js} +2 -2
- package/dashboard/dist/assets/{TimeAgo-DVWhRNbi.js.map → TimeAgo-ChwJ4fjZ.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-rG7pmIkW.js → TimestampCell-C7KzmvyC.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-rG7pmIkW.js.map → TimestampCell-C7KzmvyC.js.map} +1 -1
- package/dashboard/dist/assets/{ToolPill-BW0iRwZu.js → ToolPill-CAwj7EPw.js} +2 -2
- package/dashboard/dist/assets/{ToolPill-BW0iRwZu.js.map → ToolPill-CAwj7EPw.js.map} +1 -1
- package/dashboard/dist/assets/{ToolTestPanel-CLcMA8OE.js → ToolTestPanel-ISkuXtkT.js} +2 -2
- package/dashboard/dist/assets/{ToolTestPanel-CLcMA8OE.js.map → ToolTestPanel-ISkuXtkT.js.map} +1 -1
- package/dashboard/dist/assets/{TopicDetailPage-C9gvoWYu.js → TopicDetailPage-D8uZ8Wbs.js} +3 -3
- package/dashboard/dist/assets/{TopicDetailPage-C9gvoWYu.js.map → TopicDetailPage-D8uZ8Wbs.js.map} +1 -1
- package/dashboard/dist/assets/TopicsPage-rj88vA_1.js +2 -0
- package/dashboard/dist/assets/{TopicsPage-CIGi3TdT.js.map → TopicsPage-rj88vA_1.js.map} +1 -1
- package/dashboard/dist/assets/{UserName-CifbOahk.js → UserName-D03Lh6Aj.js} +2 -2
- package/dashboard/dist/assets/{UserName-CifbOahk.js.map → UserName-D03Lh6Aj.js.map} +1 -1
- package/dashboard/dist/assets/WorkflowExecutionPage-LD9WzPee.js +2 -0
- package/dashboard/dist/assets/WorkflowExecutionPage-LD9WzPee.js.map +1 -0
- package/dashboard/dist/assets/{WorkflowPill-BtNBSplz.js → WorkflowPill-fodIWnT3.js} +2 -2
- package/dashboard/dist/assets/{WorkflowPill-BtNBSplz.js.map → WorkflowPill-fodIWnT3.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsDashboard-CSYrYQsO.js → WorkflowsDashboard-DH0jitAb.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsDashboard-CSYrYQsO.js.map → WorkflowsDashboard-DH0jitAb.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsOverview-CaXWYZuw.js → WorkflowsOverview-D6BVaH9e.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-CaXWYZuw.js.map → WorkflowsOverview-D6BVaH9e.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-CRBXahFJ.js → YamlWorkflowDetailPage-D_CfNEqW.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-CRBXahFJ.js.map → YamlWorkflowDetailPage-D_CfNEqW.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowsPage-D5zc8Lta.js → YamlWorkflowsPage-BMJgtcAq.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowsPage-D5zc8Lta.js.map → YamlWorkflowsPage-BMJgtcAq.js.map} +1 -1
- package/dashboard/dist/assets/{agents-D7vYXeLj.js → agents-Ci0tZDO3.js} +2 -2
- package/dashboard/dist/assets/{agents-D7vYXeLj.js.map → agents-Ci0tZDO3.js.map} +1 -1
- package/dashboard/dist/assets/{bots-CKaYN2fL.js → bots-DZyt1oO4.js} +2 -2
- package/dashboard/dist/assets/{bots-CKaYN2fL.js.map → bots-DZyt1oO4.js.map} +1 -1
- package/dashboard/dist/assets/{capabilities-BknM6oFm.js → capabilities-DzVKeWyC.js} +2 -2
- package/dashboard/dist/assets/{capabilities-BknM6oFm.js.map → capabilities-DzVKeWyC.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-BodNGCr-.js → controlplane-CQzrn-rD.js} +2 -2
- package/dashboard/dist/assets/{controlplane-BodNGCr-.js.map → controlplane-CQzrn-rD.js.map} +1 -1
- package/dashboard/dist/assets/escalation-columns-s29Q4mrF.js +2 -0
- package/dashboard/dist/assets/{escalation-columns-CcbLKRI4.js.map → escalation-columns-s29Q4mrF.js.map} +1 -1
- package/dashboard/dist/assets/{index-Gt2Rebs9.js → index-3SrgIA7w.js} +2 -2
- package/dashboard/dist/assets/{index-Gt2Rebs9.js.map → index-3SrgIA7w.js.map} +1 -1
- package/dashboard/dist/assets/{index-BH67e1Ah.js → index-B2dB90aC.js} +2 -2
- package/dashboard/dist/assets/{index-BH67e1Ah.js.map → index-B2dB90aC.js.map} +1 -1
- package/dashboard/dist/assets/index-BSOcWfeR.js +5 -0
- package/dashboard/dist/assets/index-BSOcWfeR.js.map +1 -0
- package/dashboard/dist/assets/{index-B-LQ8fsJ.js → index-BWy4UvaT.js} +2 -2
- package/dashboard/dist/assets/{index-B-LQ8fsJ.js.map → index-BWy4UvaT.js.map} +1 -1
- package/dashboard/dist/assets/{index-C3QKGY5C.js → index-BqKxJ2fB.js} +2 -2
- package/dashboard/dist/assets/{index-C3QKGY5C.js.map → index-BqKxJ2fB.js.map} +1 -1
- package/dashboard/dist/assets/{index-B_aFcGv9.js → index-C9moIiIq.js} +5 -5
- package/dashboard/dist/assets/index-C9moIiIq.js.map +1 -0
- package/dashboard/dist/assets/{index-D7NHjvA4.js → index-CcKXMU-s.js} +2 -2
- package/dashboard/dist/assets/{index-D7NHjvA4.js.map → index-CcKXMU-s.js.map} +1 -1
- package/dashboard/dist/assets/index-DIPe82gq.css +1 -0
- package/dashboard/dist/assets/{index-DHhz71yv.js → index-DOHGHMP7.js} +2 -2
- package/dashboard/dist/assets/{index-DHhz71yv.js.map → index-DOHGHMP7.js.map} +1 -1
- package/dashboard/dist/assets/{index-CdN-Z8-r.js → index-DTn4XzYN.js} +2 -2
- package/dashboard/dist/assets/{index-CdN-Z8-r.js.map → index-DTn4XzYN.js.map} +1 -1
- package/dashboard/dist/assets/index-Dv8mzG9B.js +2 -0
- package/dashboard/dist/assets/index-Dv8mzG9B.js.map +1 -0
- package/dashboard/dist/assets/{index-CV8soXIM.js → index-LwodswlU.js} +2 -2
- package/dashboard/dist/assets/{index-CV8soXIM.js.map → index-LwodswlU.js.map} +1 -1
- package/dashboard/dist/assets/{index-_gh2K9DU.js → index-kPipMHZx.js} +2 -2
- package/dashboard/dist/assets/{index-_gh2K9DU.js.map → index-kPipMHZx.js.map} +1 -1
- package/dashboard/dist/assets/{index-Bwofyfi8.js → index-sdc9ecdW.js} +2 -2
- package/dashboard/dist/assets/{index-Bwofyfi8.js.map → index-sdc9ecdW.js.map} +1 -1
- package/dashboard/dist/assets/{knowledge-CE6gjN3G.js → knowledge-fi5z5YLq.js} +2 -2
- package/dashboard/dist/assets/{knowledge-CE6gjN3G.js.map → knowledge-fi5z5YLq.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-B4F-T-7R.js → mcp-CH8Tj9Pw.js} +2 -2
- package/dashboard/dist/assets/{mcp-B4F-T-7R.js.map → mcp-CH8Tj9Pw.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-CYOarL1K.js → mcp-query-6alwNh7K.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-CYOarL1K.js.map → mcp-query-6alwNh7K.js.map} +1 -1
- package/dashboard/dist/assets/{pipelines-B4gB9qMx.js → pipelines-Dqh9PLUw.js} +2 -2
- package/dashboard/dist/assets/{pipelines-B4gB9qMx.js.map → pipelines-Dqh9PLUw.js.map} +1 -1
- package/dashboard/dist/assets/roles-dJKBZUBh.js +2 -0
- package/dashboard/dist/assets/roles-dJKBZUBh.js.map +1 -0
- package/dashboard/dist/assets/{tasks-GG8c_U9w.js → tasks-BYz490un.js} +2 -2
- package/dashboard/dist/assets/{tasks-GG8c_U9w.js.map → tasks-BYz490un.js.map} +1 -1
- package/dashboard/dist/assets/{topics-C7-6oOgA.js → topics-Dt975EWi.js} +2 -2
- package/dashboard/dist/assets/{topics-C7-6oOgA.js.map → topics-Dt975EWi.js.map} +1 -1
- package/dashboard/dist/assets/{useEventHooks-82IiMmOc.js → useEventHooks-ZT6RV2Gj.js} +2 -2
- package/dashboard/dist/assets/{useEventHooks-82IiMmOc.js.map → useEventHooks-ZT6RV2Gj.js.map} +1 -1
- package/dashboard/dist/assets/{useNamespace-DQEqD2LA.js → useNamespace-B_G1iE9i.js} +2 -2
- package/dashboard/dist/assets/{useNamespace-DQEqD2LA.js.map → useNamespace-B_G1iE9i.js.map} +1 -1
- package/dashboard/dist/assets/{useYamlActivityEvents-Bm0-ewLx.js → useYamlActivityEvents-DGkvIadL.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-Bm0-ewLx.js.map → useYamlActivityEvents-DGkvIadL.js.map} +1 -1
- package/dashboard/dist/assets/{users-DHx2ium7.js → users-C2jopvM1.js} +2 -2
- package/dashboard/dist/assets/{users-DHx2ium7.js.map → users-C2jopvM1.js.map} +1 -1
- package/dashboard/dist/assets/{vendor-icons-DOIDKgo6.js → vendor-icons-BXhWQC7l.js} +161 -121
- package/dashboard/dist/assets/vendor-icons-BXhWQC7l.js.map +1 -0
- package/dashboard/dist/assets/{workflows-qIbkeQ_5.js → workflows-By8Wgvig.js} +2 -2
- package/dashboard/dist/assets/{workflows-qIbkeQ_5.js.map → workflows-By8Wgvig.js.map} +1 -1
- package/dashboard/dist/assets/{yaml-workflows-FibyeHpo.js → yaml-workflows-Cq_vp41d.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-FibyeHpo.js.map → yaml-workflows-Cq_vp41d.js.map} +1 -1
- package/dashboard/dist/index.html +3 -3
- package/docs/dashboard.md +15 -2
- package/docs/hitl-guide.md +132 -22
- package/package.json +2 -2
- package/dashboard/dist/assets/AvailableEscalationsPage-BcbhA6NE.js +0 -2
- package/dashboard/dist/assets/AvailableEscalationsPage-BcbhA6NE.js.map +0 -1
- package/dashboard/dist/assets/CustomDurationPicker-CGiwKSVJ.js +0 -2
- package/dashboard/dist/assets/CustomDurationPicker-CGiwKSVJ.js.map +0 -1
- package/dashboard/dist/assets/DataTable-ZWgVQg7F.js +0 -2
- package/dashboard/dist/assets/DataTable-ZWgVQg7F.js.map +0 -1
- package/dashboard/dist/assets/EventTable-B3Gj7Ayg.js +0 -2
- package/dashboard/dist/assets/EventTable-B3Gj7Ayg.js.map +0 -1
- package/dashboard/dist/assets/McpRunDetailPage-CXGCVmPq.js +0 -2
- package/dashboard/dist/assets/OperationsPage-DgZYi-BC.js +0 -2
- package/dashboard/dist/assets/OperationsPage-DgZYi-BC.js.map +0 -1
- package/dashboard/dist/assets/OperatorDashboard-DIR7XDeD.js +0 -2
- package/dashboard/dist/assets/PageHeader-DJo7yMUR.js +0 -2
- package/dashboard/dist/assets/PageHeader-DJo7yMUR.js.map +0 -1
- package/dashboard/dist/assets/RoleDetailPage-BfzqQxMU.js +0 -8
- package/dashboard/dist/assets/RoleDetailPage-BfzqQxMU.js.map +0 -1
- package/dashboard/dist/assets/StatusBadge-DZ9137bI.js.map +0 -1
- package/dashboard/dist/assets/TopicsPage-CIGi3TdT.js +0 -2
- package/dashboard/dist/assets/WorkflowExecutionPage-BR0oVx_p.js +0 -2
- package/dashboard/dist/assets/WorkflowExecutionPage-BR0oVx_p.js.map +0 -1
- package/dashboard/dist/assets/escalation-CH_XK2XM.js +0 -2
- package/dashboard/dist/assets/escalation-CH_XK2XM.js.map +0 -1
- package/dashboard/dist/assets/escalation-columns-CcbLKRI4.js +0 -2
- package/dashboard/dist/assets/index--xNp5rx6.css +0 -1
- package/dashboard/dist/assets/index-B_aFcGv9.js.map +0 -1
- package/dashboard/dist/assets/index-CJpywoA8.js +0 -2
- package/dashboard/dist/assets/index-CJpywoA8.js.map +0 -1
- package/dashboard/dist/assets/index-IIq5Tkqs.js +0 -6
- package/dashboard/dist/assets/index-IIq5Tkqs.js.map +0 -1
- package/dashboard/dist/assets/roles-LZf98ePg.js +0 -2
- package/dashboard/dist/assets/roles-LZf98ePg.js.map +0 -1
- package/dashboard/dist/assets/useCollapsedSections-BU5HULGs.js +0 -2
- package/dashboard/dist/assets/useCollapsedSections-BU5HULGs.js.map +0 -1
- package/dashboard/dist/assets/vendor-icons-DOIDKgo6.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DataTable-ZWgVQg7F.js","sources":["../../src/components/common/data/DataTable.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { EmptyState } from '../display/EmptyState';\nimport type { SortState } from '../../../hooks/useFilterParams';\n\nexport interface Column<T> {\n key: string;\n label: string | ReactNode;\n render: (row: T, index: number) => ReactNode;\n className?: string;\n /** If true, this column header is clickable and triggers onSort. */\n sortable?: boolean;\n}\n\ninterface DataTableProps<T> {\n columns: Column<T>[];\n data: T[];\n keyFn: (row: T) => string;\n onRowClick?: (row: T) => void;\n /** Highlight the row whose keyFn matches this value. */\n activeRowKey?: string | null;\n /** Optional per-row class name for custom styling (e.g., engine vs worker tint). */\n rowClassName?: (row: T) => string;\n isLoading?: boolean;\n emptyMessage?: string;\n /** Current sort state — pass to show active sort indicator. */\n sort?: SortState;\n /** Called when a sortable column header is clicked. */\n onSort?: (column: string) => void;\n /** Disable the sticky header (useful when nested inside collapsible sections). */\n inline?: boolean;\n}\n\nfunction SortIcon({ active, direction }: { active: boolean; direction: 'asc' | 'desc' }) {\n return (\n <svg\n className={`w-3 h-3 shrink-0 transition-all duration-150 ${\n active ? 'text-accent opacity-100' : 'opacity-0 group-hover/sorthead:opacity-40 text-text-tertiary'\n } ${active && direction === 'asc' ? 'rotate-180' : ''}`}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2.5}\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M19 9l-7 7-7-7\" />\n </svg>\n );\n}\n\nexport function DataTable<T>({\n columns,\n data,\n keyFn,\n onRowClick,\n activeRowKey,\n rowClassName,\n isLoading,\n emptyMessage = 'No records found',\n sort,\n onSort,\n inline,\n}: DataTableProps<T>) {\n if (isLoading) {\n return (\n <div className=\"animate-pulse space-y-0\">\n {Array.from({ length: 5 }).map((_, i) => (\n <div key={i} className=\"h-14 border-b last:border-b-0 px-6 flex items-center\">\n <div className=\"h-3 bg-surface-sunken rounded w-full\" />\n </div>\n ))}\n </div>\n );\n }\n\n if (!data.length) {\n return emptyMessage ? <EmptyState title={emptyMessage} /> : null;\n }\n\n return (\n <table className=\"w-full\">\n <thead>\n <tr className=\"border-b\">\n {columns.map((col) => {\n const isSortable = col.sortable && onSort;\n const isActive = sort?.sort_by === col.key;\n\n return (\n <th\n key={col.key}\n onClick={isSortable ? () => onSort(col.key) : undefined}\n className={`${inline ? '' : 'sticky top-[60px] z-10 '}bg-surface px-6 py-3 text-left text-[10px] font-semibold uppercase tracking-widest text-text-tertiary whitespace-nowrap ${col.className ?? ''} ${\n isSortable ? 'cursor-pointer select-none group/sorthead hover:text-text-secondary transition-colors' : ''\n }`}\n >\n <span className=\"inline-flex items-center gap-1\">\n {col.label}\n {isSortable && (\n <SortIcon active={isActive} direction={isActive ? sort.order : 'desc'} />\n )}\n </span>\n </th>\n );\n })}\n </tr>\n </thead>\n <tbody>\n {data.map((row, index) => {\n const isActive = activeRowKey != null && keyFn(row) === activeRowKey;\n return (\n <tr\n key={keyFn(row)}\n onClick={onRowClick ? () => onRowClick(row) : undefined}\n className={`group/row border-b last:border-b-0 transition-colors duration-100 ${\n onRowClick ? 'cursor-pointer row-hover' : ''\n } ${isActive ? 'border-l-2 border-l-accent' : ''} ${rowClassName ? rowClassName(row) : ''}`}\n >\n {columns.map((col) => (\n <td\n key={col.key}\n className={`px-6 py-2.5 text-sm ${col.className ?? ''}`}\n >\n {col.render(row, index)}\n </td>\n ))}\n </tr>\n );\n })}\n </tbody>\n </table>\n );\n}\n"],"names":["SortIcon","active","direction","jsx","DataTable","columns","data","keyFn","onRowClick","activeRowKey","rowClassName","isLoading","emptyMessage","sort","onSort","inline","_","i","jsxs","col","isSortable","isActive","row","index","EmptyState"],"mappings":"4FAgCA,SAASA,EAAS,CAAE,OAAAC,EAAQ,UAAAC,GAA6D,CACvF,OACEC,EAAAA,IAAC,MAAA,CACC,UAAW,gDACTF,EAAS,0BAA4B,8DACvC,IAAIA,GAAUC,IAAc,MAAQ,aAAe,EAAE,GACrD,QAAQ,YACR,KAAK,OACL,OAAO,eACP,YAAa,IAEb,eAAC,OAAA,CAAK,cAAc,QAAQ,eAAe,QAAQ,EAAE,gBAAA,CAAiB,CAAA,CAAA,CAG5E,CAEO,SAASE,EAAa,CAC3B,QAAAC,EACA,KAAAC,EACA,MAAAC,EACA,WAAAC,EACA,aAAAC,EACA,aAAAC,EACA,UAAAC,EACA,aAAAC,EAAe,mBACf,KAAAC,EACA,OAAAC,EACA,OAAAC,CACF,EAAsB,CACpB,OAAIJ,EAEAR,EAAAA,IAAC,MAAA,CAAI,UAAU,0BACZ,SAAA,MAAM,KAAK,CAAE,OAAQ,CAAA,CAAG,EAAE,IAAI,CAACa,EAAGC,IACjCd,EAAAA,IAAC,MAAA,CAAY,UAAU,uDACrB,SAAAA,EAAAA,IAAC,MAAA,CAAI,UAAU,sCAAA,CAAuC,CAAA,EAD9Cc,CAEV,CACD,CAAA,CACH,EAICX,EAAK,OAKRY,EAAAA,KAAC,QAAA,CAAM,UAAU,SACf,SAAA,CAAAf,EAAAA,IAAC,QAAA,CACC,eAAC,KAAA,CAAG,UAAU,WACX,SAAAE,EAAQ,IAAKc,GAAQ,CACpB,MAAMC,EAAaD,EAAI,UAAYL,EAC7BO,GAAWR,GAAA,YAAAA,EAAM,WAAYM,EAAI,IAEvC,OACEhB,EAAAA,IAAC,KAAA,CAEC,QAASiB,EAAa,IAAMN,EAAOK,EAAI,GAAG,EAAI,OAC9C,UAAW,GAAGJ,EAAS,GAAK,yBAAyB,2HAA2HI,EAAI,WAAa,EAAE,IACjMC,EAAa,wFAA0F,EACzG,GAEA,SAAAF,EAAAA,KAAC,OAAA,CAAK,UAAU,iCACb,SAAA,CAAAC,EAAI,MACJC,SACEpB,EAAA,CAAS,OAAQqB,EAAU,UAAWA,EAAWR,EAAK,MAAQ,MAAA,CAAQ,CAAA,CAAA,CAE3E,CAAA,EAXKM,EAAI,GAAA,CAcf,CAAC,EACH,EACF,QACC,QAAA,CACE,SAAAb,EAAK,IAAI,CAACgB,EAAKC,IAAU,CACxB,MAAMF,EAAWZ,GAAgB,MAAQF,EAAMe,CAAG,IAAMb,EACxD,OACAN,EAAAA,IAAC,KAAA,CAEC,QAASK,EAAa,IAAMA,EAAWc,CAAG,EAAI,OAC9C,UAAW,qEACTd,EAAa,2BAA6B,EAC5C,IAAIa,EAAW,6BAA+B,EAAE,IAAIX,EAAeA,EAAaY,CAAG,EAAI,EAAE,GAExF,SAAAjB,EAAQ,IAAKc,GACZhB,EAAAA,IAAC,KAAA,CAEC,UAAW,uBAAuBgB,EAAI,WAAa,EAAE,GAEpD,SAAAA,EAAI,OAAOG,EAAKC,CAAK,CAAA,EAHjBJ,EAAI,GAAA,CAKZ,CAAA,EAbIZ,EAAMe,CAAG,CAAA,CAgBlB,CAAC,CAAA,CACH,CAAA,EACF,EArDOV,EAAeT,EAAAA,IAACqB,EAAA,CAAW,MAAOZ,EAAc,EAAK,IAuDhE"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{a as o,j as t}from"./vendor-query-B2UbickB.js";import{F as T,b as _}from"./FilterBar-B4Mk2PvT.js";import{f as F,C as D}from"./index-B_aFcGv9.js";import{E as P}from"./SwimlaneTimeline-Bktv2vi5.js";const O=new Set(["activity_task_scheduled","timer_started","child_workflow_execution_started","signal_wait_started"]),L=new Set(["activity_task_completed","activity_task_failed","timer_fired","child_workflow_execution_completed","child_workflow_execution_failed","workflow_execution_signaled"]);function A(i){const a=new Set;for(const l of i)L.has(l.event_type)&&l.attributes.timeline_key&&a.add(l.attributes.timeline_key);return a}function M({events:i,childTasks:a,jid:l,appId:h}){const[c,y]=o.useState(""),[d,g]=o.useState(""),[u,b]=o.useState("asc"),[p,x]=o.useState(new Set),w=[...new Set(i.map(e=>e.category))].sort(),v=[...new Set(i.map(e=>e.event_type))].sort(),j=A(i),k=e=>{if(e.duration_ms!==null||!O.has(e.event_type))return!1;const s=e.attributes.timeline_key;return!(s&&j.has(s))};let n=i;c&&(n=n.filter(e=>e.category===c)),d&&(n=n.filter(e=>e.event_type===d)),n=[...n].sort((e,s)=>u==="asc"?e.event_id-s.event_id:s.event_id-e.event_id);const N=e=>{switch(e){case"activity":return"bg-status-active";case"signal":return"bg-status-success";case"timer":return"bg-status-warning";case"child_workflow":return"bg-accent";default:return"bg-text-tertiary"}},E=e=>{const s=e.event_type;if(e.attributes.activity_type)return`${s} — ${e.attributes.activity_type}`;if(e.attributes.signal_name)return`${s} — ${e.attributes.signal_name}`;if(e.attributes.child_workflow_id){const r=e.attributes.child_workflow_id,$=r.length>24?`${r.slice(0,24)}...`:r;return`${s} — ${$}`}return s},S=e=>{if(!(a!=null&&a.length))return;const s=e.attributes.activity_type;if(s)return a.find(r=>r.workflow_type===s)},m=e=>{x(s=>{const r=new Set(s);return r.has(e)?r.delete(e):r.add(e),r})},f=n.length>0&&n.every(e=>p.has(e.event_id)),C=()=>{x(f?new Set:new Set(n.map(e=>e.event_id)))};return t.jsxs("div",{children:[t.jsxs("div",{className:"px-6 py-4 border-b border-surface-border flex items-center justify-between flex-wrap gap-3",children:[t.jsxs("div",{className:"flex items-center gap-4",children:[t.jsxs("p",{className:"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary",children:["Events (",n.length,")"]}),n.length>0&&t.jsx("button",{onClick:C,className:"text-[10px] text-accent hover:underline",children:f?"Collapse all":"Expand all"})]}),t.jsxs(T,{children:[t.jsx(_,{label:"Category",value:c,onChange:y,options:w.map(e=>({value:e,label:e}))}),t.jsx(_,{label:"Type",value:d,onChange:g,options:v.map(e=>({value:e,label:e}))}),t.jsx("button",{onClick:()=>b(e=>e==="asc"?"desc":"asc"),className:"btn-ghost text-xs",children:u==="asc"?"Oldest first":"Newest first"})]})]}),t.jsx("div",{children:n.length===0?t.jsx("div",{className:"px-6 py-8 text-center",children:t.jsx("p",{className:"text-sm text-text-tertiary",children:"No events match the current filters"})}):n.map(e=>{const s=p.has(e.event_id),r=k(e);return t.jsxs("div",{className:"border-b border-surface-border last:border-b-0",children:[t.jsxs("div",{className:"px-6 py-3 flex items-center gap-4 cursor-pointer hover:bg-surface-hover transition-colors duration-200",onClick:()=>m(e.event_id),children:[t.jsx("span",{className:`text-[10px] text-text-tertiary transition-transform duration-300 ${s?"rotate-90":""}`,children:"▶"}),t.jsx("span",{className:"text-xs font-mono text-text-tertiary w-8 shrink-0",children:e.event_id}),t.jsx("span",{className:`w-2 h-2 rounded-full dot-ring shrink-0 ${N(e.category)}`}),t.jsx("span",{className:"text-sm text-text-primary flex-1 truncate",children:E(e)}),t.jsx("span",{className:"text-xs font-mono text-text-tertiary shrink-0",children:r?t.jsxs("span",{className:"inline-flex items-center gap-1 text-status-warning",children:[t.jsx("span",{className:"w-1.5 h-1.5 rounded-full dot-ring bg-status-warning animate-pulse"}),"Pending"]}):e.duration_ms!==null?F(e.duration_ms):"--"}),t.jsx("time",{className:"text-[10px] font-mono text-text-tertiary shrink-0",children:new Date(e.event_time).toLocaleTimeString()})]}),t.jsx(D,{open:s&&!!e.attributes,children:t.jsx("div",{className:"px-6 pb-4 pl-16",children:t.jsx(P,{event:e,childTask:S(e),pending:r,jid:l,appId:h,onClose:()=>m(e.event_id)})})})]},e.event_id)})})]})}export{M as E};
|
|
2
|
-
//# sourceMappingURL=EventTable-B3Gj7Ayg.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"EventTable-B3Gj7Ayg.js","sources":["../../src/pages/workflows/workflow-execution/EventTable.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { FilterBar, FilterSelect } from '../../../components/common/data/FilterBar';\nimport { Collapsible } from '../../../components/common/layout/Collapsible';\nimport type { WorkflowExecutionEvent, LTTaskRecord } from '../../../api/types';\nimport { EventDetailPanel } from './EventDetailPanel';\nimport { formatDuration } from './utils';\n\ninterface EventTableProps {\n events: WorkflowExecutionEvent[];\n childTasks?: LTTaskRecord[];\n /** Job id (workflowId) — enables the per-activity raw-stream drill-down. */\n jid?: string;\n /** HotMesh namespace / DB schema for the raw-stream lookup (default: durable). */\n appId?: string;\n}\n\n/** Event types that represent the \"start\" phase of a paired operation */\nconst STARTED_TYPES = new Set([\n 'activity_task_scheduled',\n 'timer_started',\n 'child_workflow_execution_started',\n 'signal_wait_started',\n]);\n\n/** Completion event types that close a paired operation */\nconst COMPLETED_TYPES = new Set([\n 'activity_task_completed',\n 'activity_task_failed',\n 'timer_fired',\n 'child_workflow_execution_completed',\n 'child_workflow_execution_failed',\n 'workflow_execution_signaled',\n]);\n\n/**\n * Build a set of timeline_keys that have a matching completion event.\n * A \"scheduled\" event is only truly pending if no completion exists.\n */\nfunction buildCompletedKeys(events: WorkflowExecutionEvent[]): Set<string> {\n const keys = new Set<string>();\n for (const e of events) {\n if (COMPLETED_TYPES.has(e.event_type) && e.attributes.timeline_key) {\n keys.add(e.attributes.timeline_key);\n }\n }\n return keys;\n}\n\nexport function EventTable({ events, childTasks, jid, appId }: EventTableProps) {\n const [categoryFilter, setCategoryFilter] = useState('');\n const [typeFilter, setTypeFilter] = useState('');\n const [sortOrder, setSortOrder] = useState<'asc' | 'desc'>('asc');\n const [expandedEvents, setExpandedEvents] = useState<Set<number>>(new Set());\n\n const categories = [...new Set(events.map((e) => e.category))].sort();\n const eventTypes = [...new Set(events.map((e) => e.event_type))].sort();\n const completedKeys = buildCompletedKeys(events);\n\n /** True only when a \"started/scheduled\" event has no matching completion */\n const isPending = (evt: WorkflowExecutionEvent): boolean => {\n if (evt.duration_ms !== null) return false;\n if (!STARTED_TYPES.has(evt.event_type)) return false;\n const tlk = evt.attributes.timeline_key;\n if (tlk && completedKeys.has(tlk)) return false;\n return true;\n };\n\n let filtered = events;\n if (categoryFilter) filtered = filtered.filter((e) => e.category === categoryFilter);\n if (typeFilter) filtered = filtered.filter((e) => e.event_type === typeFilter);\n\n filtered = [...filtered].sort((a, b) =>\n sortOrder === 'asc' ? a.event_id - b.event_id : b.event_id - a.event_id,\n );\n\n const categoryDot = (category: string) => {\n switch (category) {\n case 'activity':\n return 'bg-status-active';\n case 'signal':\n return 'bg-status-success';\n case 'timer':\n return 'bg-status-warning';\n case 'child_workflow':\n return 'bg-accent';\n default:\n return 'bg-text-tertiary';\n }\n };\n\n /** Build a descriptive label for an event row */\n const eventLabel = (evt: WorkflowExecutionEvent): string => {\n const base = evt.event_type;\n if (evt.attributes.activity_type) {\n return `${base} — ${evt.attributes.activity_type}`;\n }\n if (evt.attributes.signal_name) {\n return `${base} — ${evt.attributes.signal_name}`;\n }\n if (evt.attributes.child_workflow_id) {\n const id = evt.attributes.child_workflow_id;\n const truncated = id.length > 24 ? `${id.slice(0, 24)}...` : id;\n return `${base} — ${truncated}`;\n }\n return base;\n };\n\n /** Find a matching child task for an event's activity_type */\n const findChildTask = (evt: WorkflowExecutionEvent): LTTaskRecord | undefined => {\n if (!childTasks?.length) return undefined;\n const activityType = evt.attributes.activity_type;\n if (!activityType) return undefined;\n return childTasks.find((t) => t.workflow_type === activityType);\n };\n\n const toggleEvent = (id: number) => {\n setExpandedEvents((prev) => {\n const next = new Set(prev);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n return next;\n });\n };\n\n const allExpanded = filtered.length > 0 && filtered.every((e) => expandedEvents.has(e.event_id));\n\n const toggleAll = () => {\n if (allExpanded) {\n setExpandedEvents(new Set());\n } else {\n setExpandedEvents(new Set(filtered.map((e) => e.event_id)));\n }\n };\n\n return (\n <div>\n <div className=\"px-6 py-4 border-b border-surface-border flex items-center justify-between flex-wrap gap-3\">\n <div className=\"flex items-center gap-4\">\n <p className=\"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary\">\n Events ({filtered.length})\n </p>\n {filtered.length > 0 && (\n <button onClick={toggleAll} className=\"text-[10px] text-accent hover:underline\">\n {allExpanded ? 'Collapse all' : 'Expand all'}\n </button>\n )}\n </div>\n <FilterBar>\n <FilterSelect\n label=\"Category\"\n value={categoryFilter}\n onChange={setCategoryFilter}\n options={categories.map((c) => ({ value: c, label: c }))}\n />\n <FilterSelect\n label=\"Type\"\n value={typeFilter}\n onChange={setTypeFilter}\n options={eventTypes.map((t) => ({ value: t, label: t }))}\n />\n <button\n onClick={() => setSortOrder((s) => (s === 'asc' ? 'desc' : 'asc'))}\n className=\"btn-ghost text-xs\"\n >\n {sortOrder === 'asc' ? 'Oldest first' : 'Newest first'}\n </button>\n </FilterBar>\n </div>\n\n <div>\n {filtered.length === 0 ? (\n <div className=\"px-6 py-8 text-center\">\n <p className=\"text-sm text-text-tertiary\">No events match the current filters</p>\n </div>\n ) : (\n filtered.map((evt) => {\n const isExpanded = expandedEvents.has(evt.event_id);\n const pending = isPending(evt);\n\n return (\n <div\n key={evt.event_id}\n className=\"border-b border-surface-border last:border-b-0\"\n >\n {/* Row header */}\n <div\n className=\"px-6 py-3 flex items-center gap-4 cursor-pointer hover:bg-surface-hover transition-colors duration-200\"\n onClick={() => toggleEvent(evt.event_id)}\n >\n {/* Expand chevron */}\n <span\n className={`text-[10px] text-text-tertiary transition-transform duration-300 ${isExpanded ? 'rotate-90' : ''}`}\n >\n ▶\n </span>\n\n <span className=\"text-xs font-mono text-text-tertiary w-8 shrink-0\">\n {evt.event_id}\n </span>\n <span\n className={`w-2 h-2 rounded-full dot-ring shrink-0 ${categoryDot(evt.category)}`}\n />\n <span className=\"text-sm text-text-primary flex-1 truncate\">\n {eventLabel(evt)}\n </span>\n <span className=\"text-xs font-mono text-text-tertiary shrink-0\">\n {pending ? (\n <span className=\"inline-flex items-center gap-1 text-status-warning\">\n <span className=\"w-1.5 h-1.5 rounded-full dot-ring bg-status-warning animate-pulse\" />\n Pending\n </span>\n ) : evt.duration_ms !== null ? (\n formatDuration(evt.duration_ms)\n ) : (\n '--'\n )}\n </span>\n <time className=\"text-[10px] font-mono text-text-tertiary shrink-0\">\n {new Date(evt.event_time).toLocaleTimeString()}\n </time>\n </div>\n\n {/* Inline detail panel — directly below the clicked row */}\n <Collapsible open={isExpanded && !!evt.attributes}>\n <div className=\"px-6 pb-4 pl-16\">\n <EventDetailPanel\n event={evt}\n childTask={findChildTask(evt)}\n pending={pending}\n jid={jid}\n appId={appId}\n onClose={() => toggleEvent(evt.event_id)}\n />\n </div>\n </Collapsible>\n </div>\n );\n })\n )}\n </div>\n </div>\n );\n}\n"],"names":["STARTED_TYPES","COMPLETED_TYPES","buildCompletedKeys","events","keys","e","EventTable","childTasks","jid","appId","categoryFilter","setCategoryFilter","useState","typeFilter","setTypeFilter","sortOrder","setSortOrder","expandedEvents","setExpandedEvents","categories","eventTypes","completedKeys","isPending","evt","tlk","filtered","a","b","categoryDot","category","eventLabel","base","id","truncated","findChildTask","activityType","t","toggleEvent","prev","next","allExpanded","toggleAll","jsxs","jsx","FilterBar","FilterSelect","c","s","isExpanded","pending","formatDuration","Collapsible","EventDetailPanel"],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{b as R,a as m,j as e}from"./vendor-query-B2UbickB.js";import{b as D,c as L}from"./pipelines-B4gB9qMx.js";import{u as J,c as K,D as M,b as S,J as _,N as U}from"./index-B_aFcGv9.js";import{S as $}from"./StatusBadge-DZ9137bI.js";import{P as E}from"./PageHeader-DJo7yMUR.js";import{C as A}from"./CopyableId-blg-gZvT.js";import{C as b}from"./CollapsibleSection-lo8Qx4zb.js";import{u as V}from"./useCollapsedSections-BU5HULGs.js";import{L as q}from"./ListToolbar-Ok2O0wmC.js";import{S as B}from"./SwimlaneTimeline-Bktv2vi5.js";import{E as F}from"./EventTable-B3Gj7Ayg.js";import{e as H,f as Q}from"./vendor-react-CXumBFUA.js";import"./vendor-icons-DOIDKgo6.js";import"./StreamMessageDetail-BbDdWDUY.js";import"./FilterBar-B4Mk2PvT.js";const z={running:"in_progress",completed:"completed",failed:"failed"};function O({isRunning:a,onTerminate:l}){const[s,n]=m.useState(!1),t=m.useRef(null);return m.useEffect(()=>{if(!s)return;const o=i=>{t.current&&!t.current.contains(i.target)&&n(!1)};return document.addEventListener("mousedown",o),()=>document.removeEventListener("mousedown",o)},[s]),a?e.jsxs("div",{className:"relative",ref:t,children:[e.jsx("button",{onClick:()=>n(!s),className:"btn-primary text-xs",children:"Actions"}),s&&e.jsx("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:()=>{l(),n(!1)},className:"block w-full text-left px-4 py-2 text-xs text-status-error hover:bg-surface-hover",children:"Terminate"})})]}):null}function de(){var N,w;const{jobId:a}=H(),[l]=Q(),s=l.get("namespace")||"",n=R(),{data:t,isLoading:o,error:i,refetch:v,isFetching:T}=D(a,s),C=L(),{data:u}=J(),{isCollapsed:p,toggle:f}=V("mcp-run-detail"),g=((N=u==null?void 0:u.telemetry)==null?void 0:N.traceUrl)??null,I=m.useCallback(x=>{!a||x.workflowId!==a||n.invalidateQueries({queryKey:["mcpRunExecution",a]})},[a,n]);if(K(`${U}.system.>`,I),o)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(i||!t)return e.jsxs("div",{children:[e.jsx(E,{title:"Pipeline Execution"}),e.jsxs("div",{className:"mt-4 text-center py-8",children:[e.jsx("p",{className:"text-sm text-text-primary mb-1",children:(w=i==null?void 0:i.message)!=null&&w.includes("expired")?"Execution data is no longer available":"Unable to load execution"}),e.jsx("p",{className:"text-xs text-text-tertiary",children:(i==null?void 0:i.message)??"The run could not be resolved."})]})]});const{events:j,summary:r}=t,h=j.find(x=>{var k;return x.category==="activity"&&((k=x.attributes.kind)==null?void 0:k.includes("completed"))}),P=(h==null?void 0:h.attributes.result)??null,d=t.result,y=(d==null?void 0:d.data)??d??null;return e.jsxs("div",{children:[e.jsx(E,{title:"Pipeline Execution",actions:e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(q,{onRefresh:()=>v(),isFetching:T,apiPath:`/pipelines/${a}/execution?app_id=${s}`}),e.jsx(O,{isRunning:t.status==="running",onTerminate:()=>{confirm("Interrupt this pipeline execution? This cannot be undone.")&&C.mutate({jobId:t.workflow_id,topic:t.workflow_type,appId:s},{onSuccess:()=>v()})}})]})}),e.jsxs("div",{className:"bg-surface-sunken/50 rounded-md p-5 mb-8",children:[e.jsxs("div",{className:"flex items-center gap-4 mb-4",children:[e.jsx("h2",{className:"text-sm font-mono text-text-primary truncate flex-1",children:t.workflow_id}),e.jsxs("div",{className:"flex items-center gap-4 shrink-0",children:[e.jsx(c,{label:"Tools",value:r.activities.user}),e.jsx(c,{label:"System",value:r.activities.system,muted:!0}),r.child_workflows.total>0&&e.jsx(c,{label:"Children",value:r.child_workflows.total}),r.timers>0&&e.jsx(c,{label:"Timers",value:r.timers}),r.signals>0&&e.jsx(c,{label:"Signals",value:r.signals}),e.jsx($,{status:z[t.status]??t.status})]})]}),e.jsxs("div",{className:"grid grid-cols-6 gap-x-6",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-0.5",children:"Server"}),e.jsx("p",{className:"text-xs font-mono text-text-primary truncate",children:s})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-0.5",children:"Tool"}),e.jsx("p",{className:"text-xs font-mono text-text-primary truncate",children:t.workflow_type||"—"})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-0.5",children:"Duration"}),e.jsx(M,{ms:t.duration_ms,className:"font-mono text-text-primary"})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-0.5",children:"Started"}),t.start_time?e.jsx(S,{date:t.start_time,format:"datetime",className:"font-mono text-text-primary"}):e.jsx("span",{className:"text-xs text-text-tertiary",children:"--"})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-0.5",children:"Completed"}),t.close_time?e.jsx(S,{date:t.close_time,format:"datetime",className:"font-mono text-text-primary"}):e.jsx("span",{className:"text-xs text-text-tertiary",children:"--"})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-0.5",children:"Trace"}),t.trace_id?e.jsx(A,{label:"",value:t.trace_id,href:g?g.replace("{traceId}",t.trace_id):void 0,external:!0}):e.jsx("span",{className:"text-xs text-text-tertiary",children:"—"})]})]})]}),e.jsxs("div",{className:"space-y-6",children:[e.jsx(b,{title:"Details",sectionKey:"details",isCollapsed:p("details"),onToggle:f,children:e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4 mb-6",children:[e.jsx("div",{children:e.jsx(_,{data:P??{},label:"Input"})}),y!==null&&e.jsx("div",{children:e.jsx(_,{data:y,label:"Result"})})]})}),e.jsx(b,{title:"Execution Timeline",sectionKey:"timeline",isCollapsed:p("timeline"),onToggle:f,children:e.jsx(B,{events:j,outline:!0,jid:a,appId:s||"durable"})}),e.jsx(b,{title:"Events",sectionKey:"events",isCollapsed:p("events"),onToggle:f,children:e.jsx(F,{events:j,jid:a,appId:s||"durable"})})]})]})}function c({label:a,value:l,muted:s}){return e.jsxs("div",{className:"flex items-center gap-1.5 text-xs",children:[e.jsx("span",{className:"text-text-tertiary",children:a}),e.jsx("span",{className:`font-medium tabular-nums ${s?"text-text-tertiary":"text-text-primary"}`,children:l})]})}export{de as McpRunDetailPage};
|
|
2
|
-
//# sourceMappingURL=McpRunDetailPage-CXGCVmPq.js.map
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{a as $,j as e}from"./vendor-query-B2UbickB.js";import{c as Se}from"./roles-LZf98ePg.js";import{P as ge}from"./index-B_aFcGv9.js";import{i as Me}from"./useEventHooks-82IiMmOc.js";import{P as Le}from"./PageHeader-DJo7yMUR.js";import{X as qe,ae as ce,av as Ae,ar as Oe}from"./vendor-icons-DOIDKgo6.js";import{L as Q,f as Fe,c as Ee}from"./vendor-react-CXumBFUA.js";function Te(t){return t.replace(/([a-z0-9])([A-Z])/g,"$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g,"$1 $2").split(/[-_\s]+/).filter(Boolean).map(n=>n.charAt(0).toUpperCase()+n.slice(1)).join(" ")}function le(t){var n;return((n=t.title)==null?void 0:n.trim())||Te(t.role)}const je=800,be=270,I=40,Ie=76,xe=24,We=72,oe=je-I-Ie,ve=be-xe-We,_=xe+ve,me=I+oe,j="0.5s cubic-bezier(0.4, 0, 0.2, 1)",fe=9;function De(t){return`M ${(t.x-fe).toFixed(1)} ${t.y.toFixed(1)} L ${(t.x+fe).toFixed(1)} ${t.y.toFixed(1)}`}function W(t){if(t.length===0)return"";if(t.length===1)return De(t[0]);const n=[];for(let l=0;l<t.length-1;l++){const i=t[Math.max(0,l-1)],c=t[l],p=t[l+1],a=t[Math.min(t.length-1,l+2)],d=(c.x+(p.x-i.x)/6).toFixed(1),u=(c.y+(p.y-i.y)/6).toFixed(1),o=(p.x-(a.x-c.x)/6).toFixed(1),x=(p.y-(a.y-c.y)/6).toFixed(1);l===0&&n.push(`M ${c.x.toFixed(1)} ${c.y.toFixed(1)}`),n.push(`C ${d} ${u}, ${o} ${x}, ${p.x.toFixed(1)} ${p.y.toFixed(1)}`)}return n.join(" ")}function Be(t,n){if(t.length<2||n.length<2)return"";const l=W(t),i=[...n].reverse(),c=W(i),p=c.slice(c.indexOf("C"));return`${l} L ${i[0].x.toFixed(1)} ${i[0].y.toFixed(1)} ${p} Z`}function ze(t){return t>=1e4?`${Math.round(t/1e3)}k`:t>=1e3?`${(t/1e3).toFixed(1)}k`:String(t)}function ne(t){return t.length>0?t[t.length-1]:void 0}const O="#6366f1",D="#0ea5e9",q="#1E3A8A",B="#059669",Ne="#b0e0e6",F="#5b93ad",He=13;function Ye(t,n){const l=[...t].sort((a,d)=>a.y-d.y);let i=-1/0;const c=l.map(a=>{const d=Math.max(a.y+3,i+He);return i=d,{...a,labelY:d}}),p=c.length>0?c[c.length-1].labelY-n:0;if(p>0)for(const a of c)a.labelY-=p;return c}function Ge({stations:t,selectedRole:n,onSelect:l,onUpstreamSelect:i,onPrioritySelect:c,periodHours:p}){const[a,d]=$.useState(null),u=t.length;if(u===0)return null;const o=s=>u===1?I+oe/2:I+s/(u-1)*oe,x=new Map(t.map((s,m)=>[s.role,o(m)])),f=t.map((s,m)=>{var P,V,U,Z;const g=s.target_per_hour??null,S=g!=null?g*p:null;return{idx:m,x:o(m),expected:S,actual:((P=s.metric)==null?void 0:P.resolved)??0,active:((V=s.metric)==null?void 0:V.claimed)??0,pending:((U=s.metric)==null?void 0:U.pending)??0,priorityCount:((Z=s.metric)==null?void 0:Z.priority_count)??0}}),b=f.some(s=>s.expected!=null),v=Math.max(1,...f.map(s=>s.expected??0),...f.map(s=>s.actual),...f.map(s=>s.expected!=null?s.pending:0))*1.15,C=s=>xe+ve*(1-Math.max(0,Math.min(s,v))/v),N=f.filter(s=>s.expected!=null),M=N.map(s=>({...s,y:C(s.expected)})),w=N.map(s=>({...s,y:C(s.actual)})),R=N.map(s=>({...s,y:C(s.active)})),k=N.map(s=>({...s,y:C(s.pending)})),z=W(M),H=W(w),Y=W(R),X=W(k),A=ne(w),K=ne(M),E=ne(R),J=ne(k),ee=w.length>=2&&A?`${H} L ${A.x.toFixed(1)} ${_} L ${w[0].x.toFixed(1)} ${_} Z`:"",T=N.some(s=>s.pending>0||s.active>0),te=T&&R.length>=2&&E?`${Y} L ${E.x.toFixed(1)} ${_} L ${R[0].x.toFixed(1)} ${_} Z`:"",G=T?Be(k,R):"",r=N.some(s=>s.active>0),h=N.some(s=>s.pending>s.active),L=Ye([K?{key:"target",text:"Target",color:B,y:K.y}:null,A?{key:"actual",text:"Resolved",color:q,y:A.y}:null,r&&E?{key:"active",text:"Claimed",color:O,y:E.y}:null,h&&J?{key:"queued",text:"Pending",color:D,y:J.y}:null].filter(Boolean),_+4);return e.jsxs("svg",{viewBox:`0 0 ${je} ${be}`,className:"w-full h-full",preserveAspectRatio:"xMidYMid meet",style:{display:"block"},children:[t.map(s=>{if(!s.parent_role)return null;const m=x.get(s.parent_role);if(m==null)return null;const g=o(t.findIndex(S=>S.role===s.role));return e.jsx("line",{x1:m,y1:_,x2:g,y2:_,stroke:"#e2e8f0",strokeWidth:.75},`dep-${s.role}`)}),ee&&e.jsx("path",{d:ee,fill:q,opacity:.05,style:{transition:`d ${j}`}}),te&&e.jsx("path",{d:te,fill:O,opacity:.12,style:{transition:`d ${j}`}}),G&&e.jsx("path",{d:G,fill:D,opacity:.12,style:{transition:`d ${j}`}}),z&&e.jsx("path",{d:z,fill:"none",stroke:B,strokeWidth:.5,strokeLinejoin:"round",opacity:.9,style:{transition:`d ${j}`}}),M.map(s=>e.jsxs("g",{transform:`translate(${s.x} ${s.y})`,style:{transition:`transform ${j}`},children:[e.jsx("circle",{r:2,fill:B,opacity:.8}),e.jsx("text",{y:-5,textAnchor:"middle",fontSize:6.5,fill:B,fontFamily:"ui-monospace, monospace",fontWeight:"500",opacity:.7,children:Math.round(s.expected)})]},`tval-${s.idx}`)),T&&X&&e.jsx("path",{d:X,fill:"none",stroke:D,strokeWidth:.75,strokeDasharray:"2 3",strokeLinecap:"round",opacity:.55,style:{transition:`d ${j}`}}),Y&&e.jsx("path",{d:Y,fill:"none",stroke:O,strokeWidth:.75,strokeDasharray:"2 3",strokeLinecap:"round",opacity:.5,style:{transition:`d ${j}`}}),H&&e.jsx("path",{d:H,fill:"none",stroke:q,strokeWidth:.6,strokeLinejoin:"round",strokeLinecap:"round",opacity:.65,style:{transition:`d ${j}`}}),R.map((s,m)=>{if(s.pending<=0&&s.active<=0)return null;const g=Math.max(2.5,Math.min(5,2.5+s.active/10)),S=s.pending>s.active,P=Math.min(k[m].y-4,s.y-g-4);return e.jsxs("g",{children:[s.pending>0&&e.jsx("text",{x:s.x,y:P,textAnchor:"middle",fontSize:7.5,fill:S?D:"#64748b",fontFamily:"ui-monospace, monospace",fontWeight:"600",style:{transition:`y ${j}`},children:s.pending}),e.jsxs("g",{transform:`translate(${s.x} ${s.y})`,style:{transition:`transform ${j}`},children:[e.jsx("circle",{r:g,fill:O,opacity:.85}),s.active>0&&e.jsx("text",{y:g+9,textAnchor:"middle",fontSize:7.5,fill:O,fontFamily:"ui-monospace, monospace",fontWeight:"600",children:s.active})]})]},`active-${s.idx}`)}),f.map(s=>{var he;const m=t[s.idx],g=s.x,S=s.expected!=null?C(s.actual):_,P=Math.max(2.25,Math.min(4,2.25+s.actual/160)),V=m.role===n,U=a===s.idx,Z=s.expected==null?"idle · set a target rate to plot pace":`${s.actual} resolved · target ${Math.round(s.expected)}`+(s.pending>s.active?` · ${s.pending-s.active} pending`:"")+(s.active>0?` · ${s.active} claimed`:"")+(s.priorityCount>0?` · ${s.priorityCount} priority`:""),se=Z.length*5.5+20,pe=Math.max(I+se/2+4,Math.min(me-se/2-4,g)),ue=S-P-10;return e.jsxs("g",{onClick:()=>l(m.role),onMouseEnter:()=>d(s.idx),onMouseLeave:()=>d(null),style:{cursor:"pointer"},children:[e.jsxs("g",{transform:`translate(${g} ${S})`,style:{transition:`transform ${j}`},children:[e.jsx("circle",{r:22,fill:"transparent"}),e.jsx("circle",{r:P,fill:q,opacity:.9,style:{transition:`r ${j}`}}),s.expected!=null&&e.jsx("text",{y:-P-5,textAnchor:"middle",fontSize:9.5,fill:q,fontFamily:"ui-monospace, monospace",fontWeight:"500",children:ze(s.actual)}),U&&!V&&e.jsx("circle",{r:P+3,fill:"none",stroke:q,strokeWidth:1,opacity:.4}),V&&e.jsx("circle",{r:P+4,fill:"none",stroke:"#6366f1",strokeWidth:2})]}),s.priorityCount>0&&e.jsxs("g",{transform:`translate(${g+15} ${Math.max(S-15,12)})`,onClick:ie=>{ie.stopPropagation(),c==null||c(m.role)},style:{cursor:"pointer",transition:`transform ${j}`},children:[e.jsx("title",{children:`${s.priorityCount} past the priority threshold — click to pull oldest first`}),e.jsx("circle",{r:6.5+(String(s.priorityCount).length-1)*2,fill:Ne,opacity:.9}),e.jsx("text",{y:2.5,textAnchor:"middle",fontSize:7,fill:F,fontFamily:"ui-monospace, monospace",fontWeight:"700",children:s.priorityCount})]}),(((he=m.upstream_roles)==null?void 0:he.length)??0)>0&&e.jsxs("g",{transform:`translate(${g-20} ${_})`,onClick:ie=>{ie.stopPropagation(),i==null||i(m.upstream_roles[0])},style:{cursor:"pointer"},children:[e.jsx("title",{children:`Fed by ${m.upstream_roles.join(", ")} — click to view that sequence`}),e.jsx("circle",{r:9,cy:-6,fill:"transparent"}),e.jsx("path",{d:"M -7 -14 C -3 -14 -1 -9 0 -2",fill:"none",stroke:"#94a3b8",strokeWidth:1,strokeDasharray:"2 2",strokeLinecap:"round"}),e.jsx("path",{d:"M 0 -2 L 8 -2",stroke:"#94a3b8",strokeWidth:1,strokeLinecap:"round"}),e.jsx("path",{d:"M 8 -2 l -3.5 -2 v 4 z",fill:"#94a3b8"})]}),e.jsx("text",{x:g,y:_+(s.idx%2===0?14:27),textAnchor:"middle",fontSize:9.5,fill:"#475569",fontFamily:"ui-sans-serif, sans-serif",fontWeight:"500",children:le(m)}),U&&e.jsxs("g",{children:[e.jsx("rect",{x:pe-se/2,y:ue-16,width:se,height:19,rx:3,fill:"#0f172a",opacity:.88}),e.jsx("text",{x:pe,y:ue-3,textAnchor:"middle",fontSize:8.5,fill:"white",fontFamily:"ui-monospace, monospace",children:Z})]})]},m.role)}),!b&&e.jsx("text",{x:I+oe/2,y:_+48,textAnchor:"middle",fontSize:8.5,fill:"#94a3b8",fontFamily:"ui-sans-serif, sans-serif",children:"Set target_per_hour on each role in Admin → Roles to enable the pace chart"}),L.map(s=>e.jsx("text",{x:me+6,y:s.labelY,fontSize:8,fill:s.color,fontFamily:"ui-sans-serif, sans-serif",fontWeight:s.key==="actual"?700:500,opacity:s.key==="active"?.85:1,style:{transition:`y ${j}`},children:s.text},s.key))]})}function de(t){const n=`/escalations/available?role=${encodeURIComponent(t.role)}`;if(t.priority_facet){const l=JSON.stringify([{field:`metadata.${t.priority_facet}`,direction:"asc"}]);return`${n}&orderBy=${encodeURIComponent(l)}`}return`${n}&sort_by=created_at&order=asc`}const ke=["15m","1h","24h","7d","30d"],Ve=t=>ke.includes(t);function ae(t){if(t==null)return"—";if(t<1){const n=Math.round(t*60);return n<=0?"< 1s":`${n}s`}return t<60?`${t.toFixed(0)}m`:`${(t/60).toFixed(1)}h`}function re({label:t,value:n}){return e.jsxs("div",{className:"flex items-center justify-between py-1",children:[e.jsx("span",{className:"text-[10px] text-text-tertiary uppercase tracking-wider",children:t}),e.jsx("span",{className:"text-xs font-mono font-medium text-text-primary tabular-nums",children:n})]})}function Ue({period:t,onChange:n}){return e.jsx("div",{className:"flex items-center gap-1 mb-4",children:ke.map(l=>e.jsx("button",{onClick:()=>n(l),className:`px-2 py-0.5 text-[10px] font-mono rounded transition-colors ${t===l?"bg-accent/10 text-accent font-semibold":"text-text-quaternary hover:text-text-secondary"}`,children:l},l))})}function Ze({role:t,globalPeriod:n,onClose:l}){const[i,c]=$.useState(Ve(n)?n:"24h"),{data:p}=ge(i),a=p==null?void 0:p.stations.find(x=>x.role===t.role),d=t.sla_minutes??void 0,u=t.target_per_hour??void 0,o=t.worker_count??void 0;return e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"flex items-start justify-between mb-1",children:[e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex items-baseline gap-1.5 flex-wrap",children:[e.jsx("span",{className:"text-sm font-bold text-text-primary",children:le(t)}),e.jsx("span",{className:"text-[10px] font-mono text-text-secondary",children:t.role})]}),t.description&&e.jsx("p",{className:"text-[10px] text-text-tertiary mt-0.5 line-clamp-2 leading-relaxed",children:t.description})]}),e.jsx("button",{onClick:l,className:"text-text-quaternary hover:text-text-secondary transition-colors mt-0.5 shrink-0 ml-2",children:e.jsx(qe,{className:"w-4 h-4"})})]}),e.jsxs(Q,{to:`/admin/roles/${encodeURIComponent(t.role)}`,className:"flex items-center gap-1 text-[10px] text-accent hover:underline mb-4",children:[e.jsx(ce,{className:"w-2.5 h-2.5"}),"Edit in Roles"]}),e.jsx(Ue,{period:i,onChange:c}),(u||d||o)&&e.jsxs("div",{className:"flex items-center gap-4 mb-4 text-[10px]",children:[u&&e.jsxs("div",{children:[e.jsxs("div",{className:"font-mono font-semibold text-text-primary",children:[u,"/h"]}),e.jsx("div",{className:"text-text-quaternary uppercase tracking-wider text-[8.5px]",children:"target"})]}),d&&e.jsxs("div",{children:[e.jsxs("div",{className:"font-mono font-semibold text-text-primary",children:[d,"m"]}),e.jsx("div",{className:"text-text-quaternary uppercase tracking-wider text-[8.5px]",children:"SLA"})]}),o&&e.jsxs("div",{children:[e.jsx("div",{className:"font-mono font-semibold text-text-primary",children:o}),e.jsx("div",{className:"text-text-quaternary uppercase tracking-wider text-[8.5px]",children:"workers"})]})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-x-3",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-[9px] text-text-quaternary uppercase tracking-wider mb-1.5",children:"Wait (queue)"}),e.jsx(re,{label:"P99",value:ae((a==null?void 0:a.wait.p99)??null)}),e.jsx(re,{label:"avg",value:ae((a==null?void 0:a.wait.avg)??null)})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-[9px] text-text-quaternary uppercase tracking-wider mb-1.5",children:"Work (proc.)"}),e.jsx(re,{label:"P99",value:ae((a==null?void 0:a.work.p99)??null)}),e.jsx(re,{label:"avg",value:ae((a==null?void 0:a.work.avg)??null)})]})]}),e.jsxs("div",{className:"border-t border-surface-border/40 pt-2 mt-3 space-y-1.5",children:[d&&e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-[10px] text-text-tertiary",children:"SLA target"}),e.jsxs("span",{className:"text-xs font-mono text-text-secondary",children:[d,"m"]})]}),a&&a.priority_count>0&&e.jsxs(Q,{to:de(t),className:"flex items-center justify-between group",children:[e.jsxs("span",{className:"text-[10px]",style:{color:F},children:[a.priority_count," priority — pull oldest first"]}),e.jsx(ce,{className:"w-3 h-3 transition-colors",style:{color:F}})]})]}),e.jsx("div",{className:"mt-4 border-t border-surface-border/40 pt-3",children:e.jsxs(Q,{to:`/escalations/available?role=${encodeURIComponent(t.role)}`,className:"flex items-center gap-1.5 text-[10px] text-accent hover:underline",children:["View full queue",e.jsx(ce,{className:"w-2.5 h-2.5"})]})})]})}function Qe({allMetrics:t,orderedRoles:n,period:l}){const i=t.reduce((o,x)=>o+x.pending,0),c=t.reduce((o,x)=>o+x.resolved,0),p=t.reduce((o,x)=>o+x.priority_count,0),a=new Map(t.map(o=>[o.role,o])),d=t.filter(o=>o.priority_count>0).length,u=t.filter(o=>o.pending>0).length;return e.jsxs(e.Fragment,{children:[e.jsxs("p",{className:"text-[9px] text-text-quaternary uppercase tracking-wider mb-3",children:["Pipeline · ",l]}),e.jsx("div",{className:"mb-4",children:d>0?e.jsxs("p",{className:"text-[11px]",style:{color:F},children:[d," station",d>1?"s":""," with priority items"]}):u>0?e.jsxs("p",{className:"text-[11px] text-status-warning",children:[u," station",u>1?"s":""," with backlog"]}):c>0?e.jsx("p",{className:"text-[11px] text-status-success",children:"Flowing — queue clear"}):e.jsx("p",{className:"text-[11px] text-text-quaternary",children:"Quiet — awaiting work"})}),e.jsxs("div",{className:"space-y-1.5 mb-4",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-[9px] text-text-quaternary uppercase tracking-wider",children:"Pending"}),e.jsx("span",{className:`text-xs font-mono tabular-nums ${i>0?"text-text-primary font-semibold":"text-text-quaternary"}`,children:i})]}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("span",{className:"text-[9px] text-text-quaternary uppercase tracking-wider",children:["Resolved · ",l]}),e.jsx("span",{className:"text-xs font-mono tabular-nums text-text-secondary",children:c})]}),p>0&&e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-[9px] text-text-quaternary uppercase tracking-wider",children:"Priority"}),e.jsx("span",{className:"text-xs font-mono tabular-nums font-semibold",style:{color:F},children:p})]})]}),e.jsx("div",{className:"border-t border-surface-border/40 pt-2 mb-1",children:e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-[8px] text-text-quaternary uppercase tracking-wider flex-1",children:"Station"}),e.jsx("span",{className:"text-[8px] text-text-quaternary uppercase tracking-wider w-8 text-right shrink-0",children:"pend"}),e.jsx("span",{className:"text-[8px] text-text-quaternary uppercase tracking-wider w-8 text-right shrink-0",children:"clmd"}),e.jsx("span",{className:"text-[8px] text-text-quaternary uppercase tracking-wider w-8 text-right shrink-0",children:"res"})]})}),e.jsx("div",{className:"space-y-0.5",children:n.map(o=>{const x=a.get(o.role),f=(x==null?void 0:x.pending)??0,b=(x==null?void 0:x.claimed)??0,y=(x==null?void 0:x.resolved)??0,v=(x==null?void 0:x.priority_count)??0,C=o.title||o.role,N=v>0,M=f>0;return e.jsxs("div",{className:"flex items-center gap-2 py-0.5",children:[e.jsxs("span",{className:`text-[10px] font-mono flex-1 truncate ${M?"text-text-primary":"text-text-quaternary"}`,children:[C,N&&e.jsxs("span",{className:"ml-1 text-[8px] font-semibold",style:{color:F},children:[v," PRIORITY"]})]}),e.jsx("span",{className:`text-[10px] font-mono tabular-nums w-8 text-right shrink-0 ${M?"text-text-primary font-semibold":"text-text-quaternary"}`,children:f>0?f:"—"}),e.jsx("span",{className:`text-[10px] font-mono tabular-nums w-8 text-right shrink-0 ${b>0?"text-accent":"text-text-quaternary"}`,children:b>0?b:"—"}),e.jsx("span",{className:`text-[10px] font-mono tabular-nums w-8 text-right shrink-0 ${y>0?"text-text-secondary":"text-text-quaternary"}`,children:y>0?y:"—"})]},o.role)})}),e.jsx("p",{className:"text-[9px] text-text-quaternary mt-5",children:"Select a station for queue detail."})]})}function Xe({role:t,allMetrics:n,orderedRoles:l,globalPeriod:i,onClose:c}){return e.jsx("div",{className:"w-[280px] shrink-0 px-6 py-8 flex flex-col overflow-y-auto min-h-0",children:t?e.jsx(Ze,{role:t,globalPeriod:i,onClose:c}):e.jsx(Qe,{allMetrics:n,orderedRoles:l,period:i})})}const $e=`${B}14`,we=`${D}14`,_e=`${O}14`,Re=`${q}14`,Pe="minmax(120px, 1.1fr) minmax(100px, 0.9fr) 64px 56px 56px 60px 72px 72px 104px",Ke=["15m","1h","24h","7d","30d"],Je={"15m":.25,"1h":1,"24h":24,"7d":168,"30d":720};function Ce(t){const n=t.filter(a=>a.ops_visible),l=new Map(n.map(a=>[a.role,a])),i=new Set,p=n.filter(a=>!a.parent_role||!l.has(a.parent_role)).map(a=>{const d=[],u=[{role:a,depth:0}];for(;u.length>0;){const o=u.shift();i.has(o.role.role)||(i.add(o.role.role),d.push(o),n.filter(x=>x.parent_role===o.role.role&&!i.has(x.role)).forEach(x=>u.push({role:x,depth:o.depth+1})))}return{origin:a,stations:d}});return n.filter(a=>!i.has(a.role)).forEach(a=>p.push({origin:a,stations:[{role:a,depth:0}]})),p.sort((a,d)=>d.stations.length-a.stations.length||a.origin.role.localeCompare(d.origin.role))}function ye(t){if(t==null)return"—";if(t<1){const n=Math.round(t*60);return n<=0?"< 1s":`${n}s`}return t<60?`${t.toFixed(0)}m`:`${(t/60).toFixed(1)}h`}function et(t,n){if(!n||t===0)return{pct:null,color:"bg-surface-border"};const l=t/n,i=Math.round(l*100),c=l>1?"bg-status-warning":l<.2?"bg-status-draft":"bg-status-success";return{pct:i,color:c}}function tt({role:t,metric:n,selected:l,onClick:i}){var b;const c=(n==null?void 0:n.pending)??0,p=(n==null?void 0:n.claimed)??0,a=(n==null?void 0:n.resolved)??0,d=(n==null?void 0:n.priority_count)??0,u=t.target_per_hour??null,{pct:o,color:x}=et(c,u),f=o!=null?Math.min(100,o):0;return e.jsxs(e.Fragment,{children:[e.jsxs("div",{role:"button",tabIndex:0,onClick:i,onKeyDown:y=>{y.key==="Enter"&&i()},className:`grid items-center gap-4 pr-3 cursor-pointer transition-colors ${l?"border-l-2 !border-l-accent pl-2.5":"pl-3"}`,style:{gridTemplateColumns:Pe},children:[e.jsxs("div",{className:"flex items-center gap-1.5 min-w-0 py-1.5",children:[e.jsx("span",{className:"font-bold text-text-primary truncate text-xs",children:le(t)}),(((b=t.upstream_roles)==null?void 0:b.length)??0)>0&&e.jsx("span",{title:`Fed by ${t.upstream_roles.join(", ")}`,className:"shrink-0 leading-none",children:e.jsx(Oe,{className:"w-3 h-3 text-text-quaternary"})})]}),e.jsx("span",{className:"font-mono text-[11px] text-text-tertiary truncate py-1.5",children:t.role}),e.jsx("div",{className:"self-stretch flex items-center justify-end px-1.5",style:{backgroundColor:$e},children:e.jsx("span",{className:`text-xs font-mono tabular-nums ${u!=null?"text-text-secondary":"text-text-quaternary"}`,children:u??"—"})}),e.jsx("div",{className:"self-stretch flex items-center justify-end px-1.5",style:{backgroundColor:we},children:e.jsx("span",{className:`text-xs font-mono tabular-nums ${c>0?"text-text-primary font-semibold":"text-text-quaternary"}`,children:c})}),e.jsx("div",{className:"self-stretch flex items-center justify-end px-1.5",style:{backgroundColor:_e},children:e.jsx("span",{className:`text-xs font-mono tabular-nums ${p>0?"text-accent font-semibold":"text-text-quaternary"}`,children:p})}),e.jsx("div",{className:"self-stretch flex items-center justify-end px-1.5",style:{backgroundColor:Re},children:e.jsx("span",{className:"text-xs font-mono tabular-nums text-text-quaternary",children:a})}),e.jsx("span",{className:"text-xs font-mono tabular-nums text-right py-1.5 text-text-secondary",children:ye((n==null?void 0:n.wait.p99)??null)}),e.jsx("span",{className:"text-xs font-mono tabular-nums text-right py-1.5 text-text-secondary",children:ye((n==null?void 0:n.work.p99)??null)}),e.jsxs("div",{className:"flex items-center gap-2 py-1.5",children:[e.jsx("div",{className:"w-12 h-1.5 bg-surface-sunken rounded-full overflow-hidden shrink-0",children:e.jsx("div",{className:`h-full rounded-full ${x}`,style:{width:`${f}%`}})}),e.jsx("span",{className:`text-[10px] font-mono tabular-nums ${o!=null&&o>100?"text-status-warning font-semibold":"text-text-quaternary"}`,children:o!=null?`${o}%`:"—"})]})]}),d>0&&e.jsxs("div",{className:"flex items-center gap-1.5 pb-2 pl-3.5",children:[e.jsx("span",{className:"w-2.5 h-2.5 rounded-full dot-ring shrink-0",style:{backgroundColor:Ne}}),e.jsxs(Q,{to:de(t),className:"text-[10px] hover:underline",style:{color:F},onClick:y=>y.stopPropagation(),children:[d," priority — pull oldest first →"]})]})]})}function st(){const t=[{label:"NAME"},{label:"ROLE"},{label:"TARGET/H",band:$e,hue:B},{label:"PENDING",band:we,hue:D},{label:"CLAIMED",band:_e,hue:O},{label:"RESOLVED",band:Re,hue:q},{label:"P99 WAIT"},{label:"P99 WORK"},{label:"TREND"}];return e.jsx("div",{className:"grid items-center gap-4 px-3 border-b border-surface-border mb-0.5",style:{gridTemplateColumns:Pe},children:t.map((n,l)=>n.band?e.jsx("div",{className:"self-stretch flex items-center justify-end px-1.5",style:{backgroundColor:n.band},children:e.jsx("span",{className:"text-[9px] font-semibold uppercase tracking-wider",style:{color:n.hue},children:n.label})},n.label):e.jsx("span",{className:`text-[9px] font-semibold uppercase tracking-wider text-text-quaternary py-1.5 ${l>1&&l<8?"text-right":""}`,children:n.label},n.label))})}function nt(){var G;const[t,n]=$.useState("1h"),[l,i]=$.useState(null),[c,p]=$.useState(!1);Me();const{data:a,isLoading:d,refetch:u}=Se(),{data:o,isLoading:x,refetch:f}=ge(t),b=(a==null?void 0:a.roles)??[],y=(o==null?void 0:o.stations)??[],v=$.useMemo(()=>Ce(b),[b]),[C,N]=Fe(),M=C.get("fragment"),w=v.find(r=>r.origin.role===M)??v[0]??null,R=$.useCallback(r=>{i(null),N(h=>{const L=new URLSearchParams(h);return L.set("fragment",r),L})},[N]),k=(w==null?void 0:w.stations)??[],z=$.useMemo(()=>new Set(k.map(({role:r})=>r.role)),[k]),H=$.useMemo(()=>y.filter(r=>z.has(r.role)),[y,z]),Y=$.useMemo(()=>k.map(({role:r})=>({role:r.role,title:r.title,parent_role:r.parent_role,target_per_hour:r.target_per_hour??null,upstream_roles:r.upstream_roles??[],metric:y.find(h=>h.role===r.role)})),[k,y]),X=$.useCallback(r=>{const h=v.find(L=>L.stations.some(({role:s})=>s.role===r));h&&R(h.origin.role)},[v,R]),A=Ee(),K=$.useCallback(r=>{const h=b.find(L=>L.role===r);h&&A(de(h))},[b,A]),E=((G=k.find(({role:r})=>r.role===l))==null?void 0:G.role)??null,J=d||x,ee=async()=>{p(!0),await Promise.all([u(),f()]),p(!1)},T=r=>i(h=>h===r?null:r),te=e.jsx("div",{className:"flex items-center gap-0.5",children:Ke.map(r=>e.jsx("button",{onClick:()=>n(r),className:`px-2.5 py-1 text-[10px] font-mono rounded transition-colors ${t===r?"bg-accent/10 text-accent font-semibold":"text-text-quaternary hover:text-text-secondary"}`,children:r},r))});return e.jsxs("div",{className:"flex flex-col flex-1 min-h-0",children:[e.jsx(Le,{title:"Pace Board",docsHash:"#docs:dashboard.md:pace-board",center:te,actions:e.jsx("button",{onClick:ee,disabled:c,className:"text-text-quaternary hover:text-text-secondary transition-colors disabled:opacity-40",children:e.jsx(Ae,{className:`w-3.5 h-3.5 ${c?"animate-spin":""}`})})}),J?e.jsxs("div",{className:"animate-pulse space-y-6 mt-4",children:[e.jsx("div",{className:"h-8 bg-surface-sunken rounded w-64"}),e.jsx("div",{className:"h-64 bg-surface-sunken rounded w-full"}),e.jsx("div",{className:"space-y-3",children:[1,2,3].map(r=>e.jsx("div",{className:"h-8 bg-surface-sunken rounded w-full"},r))})]}):v.length===0?e.jsxs("div",{className:"mt-8",children:[e.jsx("p",{className:"text-sm text-text-secondary mb-2",children:"Stations appear here once roles are marked visible in Operations."}),e.jsxs("p",{className:"text-xs text-text-tertiary",children:["Go to"," ",e.jsx(Q,{to:"/admin/roles",className:"text-accent hover:underline",children:"Roles"})," ","and enable ",e.jsx("strong",{children:"Visible in Operations"})," on roles that represent pipeline stations."]})]}):e.jsxs("div",{className:"flex flex-col flex-1 min-h-0",children:[v.length>1&&e.jsx("div",{className:"flex items-center gap-0.5 px-4 pt-2",children:v.map(r=>{const h=r.origin.role===(w==null?void 0:w.origin.role);return e.jsxs("button",{onClick:()=>R(r.origin.role),className:`px-2.5 py-1 text-[10px] font-mono rounded transition-colors ${h?"bg-accent/10 text-accent font-semibold":"text-text-quaternary hover:text-text-secondary"}`,children:[le(r.origin),e.jsx("span",{className:`ml-1.5 tabular-nums ${h?"text-accent/60":"text-text-quaternary/60"}`,children:r.stations.length})]},r.origin.role)})}),e.jsxs("div",{className:"flex-1 min-h-[40vh] flex items-stretch overflow-hidden",children:[e.jsx("div",{className:"flex-1 min-w-0 min-h-0 flex flex-col justify-center overflow-hidden p-4",children:e.jsx(Ge,{stations:Y,selectedRole:l,onSelect:T,onUpstreamSelect:X,onPrioritySelect:K,periodHours:Je[t]})}),e.jsx("div",{className:"w-px bg-surface-border shrink-0 self-stretch"}),e.jsx(Xe,{role:E,allMetrics:H,orderedRoles:k.map(r=>r.role),globalPeriod:t,onClose:()=>i(null)})]}),e.jsxs("div",{className:"max-h-[30vh] flex-none flex flex-col border-t border-surface-border overflow-hidden",children:[e.jsx(st,{}),e.jsx("div",{className:"flex-1 min-h-0 overflow-y-auto divide-y divide-surface-border/30",children:k.map(({role:r})=>e.jsx(tt,{role:r,metric:y.find(h=>h.role===r.role),selected:l===r.role,onClick:()=>T(r.role)},r.role))})]})]})]})}const dt=Object.freeze(Object.defineProperty({__proto__:null,OperationsPage:nt,buildFragments:Ce},Symbol.toStringTag,{value:"Module"}));export{dt as O,Ge as P,Ce as b,de as p};
|
|
2
|
-
//# sourceMappingURL=OperationsPage-DgZYi-BC.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"OperationsPage-DgZYi-BC.js","sources":["../../src/lib/role-display.ts","../../src/pages/operations/PaceChart.tsx","../../src/pages/operations/priority-link.ts","../../src/pages/operations/StationDetailPanel.tsx","../../src/pages/operations/OperationsPage.tsx"],"sourcesContent":["/**\n * Derive a human-readable name from a role id. camelCase, kebab-case, and\n * snake_case all read as spaced Title Case — printFarm, print-farm, and\n * print_farm each become \"Print Farm\". Interior capitals are preserved so\n * acronym segments keep their shape (printQA → \"Print QA\").\n */\nexport function deriveRoleTitle(role: string): string {\n return role\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2') // camelCase boundary\n .replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2') // acronym → word boundary (QAReview)\n .split(/[-_\\s]+/)\n .filter(Boolean)\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join(' ');\n}\n\n/**\n * The display name for a role: a user-set title wins; otherwise the name is\n * derived from the role id. Every role therefore has a friendly name — the\n * display name leads, and the exact role id renders as the secondary field.\n */\nexport function displayRoleTitle(r: { role: string; title?: string | null }): string {\n return r.title?.trim() || deriveRoleTitle(r.role);\n}\n","import { useState } from 'react';\nimport type { StationMetric } from '../../api/escalations';\nimport { displayRoleTitle } from '../../lib/role-display';\n\nexport interface ChartStation {\n role: string;\n title: string | null;\n target_per_hour: number | null;\n parent_role: string | null;\n /** Roles feeding this station from other sequences — drawn as a merge glyph, not a bend in the line. */\n upstream_roles?: string[];\n metric: StationMetric | undefined;\n}\n\ninterface PaceChartProps {\n stations: ChartStation[];\n selectedRole: string | null;\n onSelect: (role: string) => void;\n /** Merge-glyph click — jump to the sequence that feeds this station. */\n onUpstreamSelect?: (upstreamRole: string) => void;\n /** Priority-badge click — open the station's queue oldest-first by its age facet. */\n onPrioritySelect?: (role: string) => void;\n /** Selected window length in hours — target count = target_per_hour × this. */\n periodHours: number;\n}\n\n// ── SVG layout ────────────────────────────────────────────────────────────────\n\nconst W = 800;\nconst H = 270;\nconst ML = 40;\nconst MR = 76;\nconst MT = 24;\nconst MB = 72;\n\nconst chartW = W - ML - MR;\nconst chartH = H - MT - MB;\nconst bottom = MT + chartH;\nconst right = ML + chartW;\n\n// Smooth transition applied when the window changes and values re-scale.\nconst EASE = '0.5s cubic-bezier(0.4, 0, 0.2, 1)';\n\n// ── Path builders ─────────────────────────────────────────────────────────────\n\n// A one-point curve still needs a stroke: a short segment — slightly longer\n// than an em dash — centered through the point. It anchors the dot and its\n// end label in vertical space when a sequence has a single station (or a\n// single station carries a target).\nconst SOLO_HALF = 9;\nfunction soloSegment(p: { x: number; y: number }): string {\n return `M ${(p.x - SOLO_HALF).toFixed(1)} ${p.y.toFixed(1)} L ${(p.x + SOLO_HALF).toFixed(1)} ${p.y.toFixed(1)}`;\n}\n\n/** Catmull-Rom → cubic bezier — smooth curves for the target, actual, and active lines. */\nfunction catmullPath(pts: { x: number; y: number }[]): string {\n if (pts.length === 0) return '';\n if (pts.length === 1) return soloSegment(pts[0]);\n const segs: string[] = [];\n for (let i = 0; i < pts.length - 1; i++) {\n const p0 = pts[Math.max(0, i - 1)];\n const p1 = pts[i];\n const p2 = pts[i + 1];\n const p3 = pts[Math.min(pts.length - 1, i + 2)];\n const cp1x = (p1.x + (p2.x - p0.x) / 6).toFixed(1);\n const cp1y = (p1.y + (p2.y - p0.y) / 6).toFixed(1);\n const cp2x = (p2.x - (p3.x - p1.x) / 6).toFixed(1);\n const cp2y = (p2.y - (p3.y - p1.y) / 6).toFixed(1);\n if (i === 0) segs.push(`M ${p1.x.toFixed(1)} ${p1.y.toFixed(1)}`);\n segs.push(`C ${cp1x} ${cp1y}, ${cp2x} ${cp2y}, ${p2.x.toFixed(1)} ${p2.y.toFixed(1)}`);\n }\n return segs.join(' ');\n}\n\n/**\n * Closed region between two curves — upper spline forward, lower spline back.\n * Used for the queue-composition bands: the vertical thickness at any station\n * is the count difference between the two curves.\n */\nfunction bandPath(upper: { x: number; y: number }[], lower: { x: number; y: number }[]): string {\n if (upper.length < 2 || lower.length < 2) return '';\n const forward = catmullPath(upper);\n const rev = [...lower].reverse();\n const back = catmullPath(rev);\n // Drop the back path's leading M — the L below connects the two curves.\n const backSegs = back.slice(back.indexOf('C'));\n return `${forward} L ${rev[0].x.toFixed(1)} ${rev[0].y.toFixed(1)} ${backSegs} Z`;\n}\n\nfunction compact(n: number): string {\n return n >= 10000 ? `${Math.round(n / 1000)}k` : n >= 1000 ? `${(n / 1000).toFixed(1)}k` : String(n);\n}\n\nfunction last<T>(a: T[]): T | undefined {\n return a.length > 0 ? a[a.length - 1] : undefined;\n}\n\n// ── Colors ────────────────────────────────────────────────────────────────────\n\n// Shared queue-state palette — the chart bands and the station table columns\n// use the same hues so the two views read as one.\nexport const ACTIVE_COLOR = '#6366f1'; // claimed, being worked right now — indigo\nexport const QUEUED_COLOR = '#0ea5e9'; // pending and unclaimed, waiting in the queue — sky\nexport const RESOLVED_COLOR = '#1E3A8A'; // done — navy, matches the default theme accent\nexport const TARGET_COLOR = '#059669'; // target pace line — emerald\n\n// Priority — unclaimed items past the role's age threshold, the count the\n// floor pulls to the front of the rack. Powder blue for the badge circle;\n// the count text uses the same hue deepened enough to read at chart sizes.\nexport const PRIORITY_COLOR = '#b0e0e6';\nexport const PRIORITY_TEXT_COLOR = '#5b93ad';\n\n// ── End-label stacking — spread close labels so text doesn't collide ────────────\n\nconst MIN_GAP = 13;\nfunction spreadLabels<T extends { y: number }>(labels: T[], maxY: number): (T & { labelY: number })[] {\n const sorted = [...labels].sort((a, b) => a.y - b.y);\n let prev = -Infinity;\n const placed = sorted.map((l) => {\n const labelY = Math.max(l.y + 3, prev + MIN_GAP);\n prev = labelY;\n return { ...l, labelY };\n });\n // On a quiet window every curve sits at zero and the stack would descend\n // past the floor into the station titles — lift the whole stack back above\n // maxY instead.\n const overflow = placed.length > 0 ? placed[placed.length - 1].labelY - maxY : 0;\n if (overflow > 0) {\n for (const l of placed) l.labelY -= overflow;\n }\n return placed;\n}\n\n// ── Chart ─────────────────────────────────────────────────────────────────────\n\nexport function PaceChart({ stations, selectedRole, onSelect, onUpstreamSelect, onPrioritySelect, periodHours }: PaceChartProps) {\n const [hoveredIdx, setHoveredIdx] = useState<number | null>(null);\n\n const n = stations.length;\n if (n === 0) return null;\n\n const xOf = (i: number) => (n === 1 ? ML + chartW / 2 : ML + (i / (n - 1)) * chartW);\n const xMap = new Map(stations.map((s, i) => [s.role, xOf(i)]));\n\n // Per-station counts for the selected window:\n // - target : expected units = target_per_hour × periodHours (e.g. 22/h · 15m ≈ 5).\n // - actual : units resolved in the window (\"the number we see\").\n // - active : units in the queue being worked right now (claimed).\n const rows = stations.map((s, i) => {\n const target = s.target_per_hour ?? null;\n const expected = target != null ? target * periodHours : null;\n return {\n idx: i,\n x: xOf(i),\n expected,\n actual: s.metric?.resolved ?? 0,\n active: s.metric?.claimed ?? 0,\n pending: s.metric?.pending ?? 0,\n priorityCount: s.metric?.priority_count ?? 0,\n };\n });\n\n const hasTargets = rows.some((r) => r.expected != null);\n\n const dataMax = Math.max(\n 1,\n ...rows.map((r) => r.expected ?? 0),\n ...rows.map((r) => r.actual),\n ...rows.map((r) => (r.expected != null ? r.pending : 0)),\n );\n const maxVal = dataMax * 1.15;\n const yScale = (v: number) => MT + chartH * (1 - Math.max(0, Math.min(v, maxVal)) / maxVal);\n\n const withTarget = rows.filter((r) => r.expected != null);\n const targetPts = withTarget.map((r) => ({ ...r, y: yScale(r.expected as number) }));\n const actualPts = withTarget.map((r) => ({ ...r, y: yScale(r.actual) }));\n const activePts = withTarget.map((r) => ({ ...r, y: yScale(r.active) }));\n const pendingPts = withTarget.map((r) => ({ ...r, y: yScale(r.pending) }));\n\n const targetLinePath = catmullPath(targetPts);\n const actualSplinePath = catmullPath(actualPts);\n const activeSplinePath = catmullPath(activePts);\n const pendingSplinePath = catmullPath(pendingPts);\n\n const lastActual = last(actualPts);\n const lastTarget = last(targetPts);\n const lastActive = last(activePts);\n const lastPending = last(pendingPts);\n\n const areaPath =\n actualPts.length >= 2 && lastActual\n ? `${actualSplinePath} L ${lastActual.x.toFixed(1)} ${bottom} L ${actualPts[0].x.toFixed(1)} ${bottom} Z`\n : '';\n\n // Queue composition — pending splits into two stacked bands:\n // floor → active curve = claimed, being worked (indigo)\n // active → pending curve = waiting, unclaimed (sky)\n // When workers claim everything the instant it lands, the sky band collapses\n // to zero and the whole queue reads as indigo.\n const hasQueue = withTarget.some((r) => r.pending > 0 || r.active > 0);\n const workedBandPath =\n hasQueue && activePts.length >= 2 && lastActive\n ? `${activeSplinePath} L ${lastActive.x.toFixed(1)} ${bottom} L ${activePts[0].x.toFixed(1)} ${bottom} Z`\n : '';\n const queuedBandPath = hasQueue ? bandPath(pendingPts, activePts) : '';\n\n // Quiet lines keep their curves (flat at zero) but skip their end labels —\n // a stack of names pointing at nothing is noise.\n const showActiveLabel = withTarget.some((r) => r.active > 0);\n const showQueuedLabel = withTarget.some((r) => r.pending > r.active);\n const endLabels = spreadLabels(\n [\n lastTarget ? { key: 'target', text: 'Target', color: TARGET_COLOR, y: lastTarget.y } : null,\n lastActual ? { key: 'actual', text: 'Resolved', color: RESOLVED_COLOR, y: lastActual.y } : null,\n showActiveLabel && lastActive\n ? { key: 'active', text: 'Claimed', color: ACTIVE_COLOR, y: lastActive.y }\n : null,\n showQueuedLabel && lastPending\n ? { key: 'queued', text: 'Pending', color: QUEUED_COLOR, y: lastPending.y }\n : null,\n ].filter(Boolean) as { key: string; text: string; color: string; y: number }[],\n bottom + 4,\n );\n\n return (\n <svg viewBox={`0 0 ${W} ${H}`} className=\"w-full h-full\" preserveAspectRatio=\"xMidYMid meet\" style={{ display: 'block' }}>\n {/* Dependency connector lines (parent → child), drawn at chart floor */}\n {stations.map((s) => {\n if (!s.parent_role) return null;\n const px = xMap.get(s.parent_role);\n if (px == null) return null;\n const cx = xOf(stations.findIndex((r) => r.role === s.role));\n return <line key={`dep-${s.role}`} x1={px} y1={bottom} x2={cx} y2={bottom} stroke=\"#e2e8f0\" strokeWidth={0.75} />;\n })}\n\n {/* Area under the actual curve */}\n {areaPath && <path d={areaPath} fill={RESOLVED_COLOR} opacity={0.05} style={{ transition: `d ${EASE}` }} />}\n\n {/* Queue composition bands — the band heights split each station's\n pending total into claimed-and-worked (indigo, floor→active) and\n waiting-unclaimed (sky, active→pending). */}\n {workedBandPath && (\n <path d={workedBandPath} fill={ACTIVE_COLOR} opacity={0.12} style={{ transition: `d ${EASE}` }} />\n )}\n {queuedBandPath && (\n <path d={queuedBandPath} fill={QUEUED_COLOR} opacity={0.12} style={{ transition: `d ${EASE}` }} />\n )}\n\n {/* Target — thin emerald reference curve at the window's expected count */}\n {targetLinePath && (\n <path d={targetLinePath} fill=\"none\" stroke={TARGET_COLOR} strokeWidth={0.5} strokeLinejoin=\"round\" opacity={0.9} style={{ transition: `d ${EASE}` }} />\n )}\n\n {/* Per-station target markers — a small emerald dot on the target line\n (mirroring the Resolved line's dots) with the window's expected count\n (target_per_hour × duration) just above it */}\n {targetPts.map((tp) => (\n <g key={`tval-${tp.idx}`} transform={`translate(${tp.x} ${tp.y})`} style={{ transition: `transform ${EASE}` }}>\n <circle r={2} fill={TARGET_COLOR} opacity={0.8} />\n <text\n y={-5}\n textAnchor=\"middle\"\n fontSize={6.5}\n fill={TARGET_COLOR}\n fontFamily=\"ui-monospace, monospace\"\n fontWeight=\"500\"\n opacity={0.7}\n >\n {Math.round(tp.expected as number)}\n </text>\n </g>\n ))}\n\n {/* Pending — thin dotted sky edge along the queue total (top of the bands) */}\n {hasQueue && pendingSplinePath && (\n <path d={pendingSplinePath} fill=\"none\" stroke={QUEUED_COLOR} strokeWidth={0.75} strokeDasharray=\"2 3\" strokeLinecap=\"round\" opacity={0.55} style={{ transition: `d ${EASE}` }} />\n )}\n\n {/* Active — thin dotted indigo, how many are claimed and being worked */}\n {activeSplinePath && (\n <path d={activeSplinePath} fill=\"none\" stroke={ACTIVE_COLOR} strokeWidth={0.75} strokeDasharray=\"2 3\" strokeLinecap=\"round\" opacity={0.5} style={{ transition: `d ${EASE}` }} />\n )}\n\n {/* Actual — thin solid, primary line */}\n {actualSplinePath && (\n <path d={actualSplinePath} fill=\"none\" stroke={RESOLVED_COLOR} strokeWidth={0.6} strokeLinejoin=\"round\" strokeLinecap=\"round\" opacity={0.65} style={{ transition: `d ${EASE}` }} />\n )}\n\n {/* Queue markers — a dot on the active line per station.\n Above the dot, at the pending edge: the queue total (sky when part of\n it is still waiting, slate when everything is claimed).\n Below the dot: active (claimed, being worked right now). */}\n {activePts.map((ap, i) => {\n if (ap.pending <= 0 && ap.active <= 0) return null;\n const ar = Math.max(2.5, Math.min(5, 2.5 + ap.active / 10));\n const hasWaiting = ap.pending > ap.active;\n // Anchor the queue-total label to the pending edge so it rides the top\n // of the band; keep it clear of the dot when the two curves touch.\n const pendingLabelY = Math.min(pendingPts[i].y - 4, ap.y - ar - 4);\n return (\n <g key={`active-${ap.idx}`}>\n {ap.pending > 0 && (\n <text\n x={ap.x}\n y={pendingLabelY}\n textAnchor=\"middle\"\n fontSize={7.5}\n fill={hasWaiting ? QUEUED_COLOR : '#64748b'}\n fontFamily=\"ui-monospace, monospace\"\n fontWeight=\"600\"\n style={{ transition: `y ${EASE}` }}\n >\n {ap.pending}\n </text>\n )}\n <g transform={`translate(${ap.x} ${ap.y})`} style={{ transition: `transform ${EASE}` }}>\n <circle r={ar} fill={ACTIVE_COLOR} opacity={0.85} />\n {ap.active > 0 && (\n <text y={ar + 9} textAnchor=\"middle\" fontSize={7.5} fill={ACTIVE_COLOR} fontFamily=\"ui-monospace, monospace\" fontWeight=\"600\">\n {ap.active}\n </text>\n )}\n </g>\n </g>\n );\n })}\n\n {/* Station nodes — actual (resolved) as a dot on the actual line, styled like\n the active dot but a bit larger (actual is the most important number).\n The count sits below the dot so it stays legible as numbers grow. */}\n {rows.map((row) => {\n const s = stations[row.idx];\n const x = row.x;\n const cy = row.expected != null ? yScale(row.actual) : bottom;\n // Same small scale as the active dot — a hair larger.\n const r = Math.max(2.25, Math.min(4, 2.25 + row.actual / 160));\n const isSelected = s.role === selectedRole;\n const isHovered = hoveredIdx === row.idx;\n\n const tooltip =\n row.expected == null\n ? 'idle · set a target rate to plot pace'\n : `${row.actual} resolved · target ${Math.round(row.expected)}`\n + (row.pending > row.active ? ` · ${row.pending - row.active} pending` : '')\n + (row.active > 0 ? ` · ${row.active} claimed` : '')\n + (row.priorityCount > 0 ? ` · ${row.priorityCount} priority` : '');\n const tipW = tooltip.length * 5.5 + 20;\n const tipX = Math.max(ML + tipW / 2 + 4, Math.min(right - tipW / 2 - 4, x));\n const tipY = cy - r - 10;\n\n return (\n <g\n key={s.role}\n onClick={() => onSelect(s.role)}\n onMouseEnter={() => setHoveredIdx(row.idx)}\n onMouseLeave={() => setHoveredIdx(null)}\n style={{ cursor: 'pointer' }}\n >\n {/* Animated marker group — slides vertically as the window rescales */}\n <g transform={`translate(${x} ${cy})`} style={{ transition: `transform ${EASE}` }}>\n <circle r={22} fill=\"transparent\" />\n <circle r={r} fill={RESOLVED_COLOR} opacity={0.9} style={{ transition: `r ${EASE}` }} />\n {row.expected != null && (\n <text y={-r - 5} textAnchor=\"middle\" fontSize={9.5} fill={RESOLVED_COLOR} fontFamily=\"ui-monospace, monospace\" fontWeight=\"500\">\n {compact(row.actual)}\n </text>\n )}\n {isHovered && !isSelected && <circle r={r + 3} fill=\"none\" stroke={RESOLVED_COLOR} strokeWidth={1} opacity={0.4} />}\n {isSelected && <circle r={r + 4} fill=\"none\" stroke=\"#6366f1\" strokeWidth={2} />}\n </g>\n\n {/* Priority badge — powder blue circle carrying the count of\n unclaimed items past the role's age threshold. Clicking opens\n the station's queue oldest-first by the priority facet so the\n runner grabs the top few and moves them to the front. */}\n {row.priorityCount > 0 && (\n <g\n transform={`translate(${x + 15} ${Math.max(cy - 15, 12)})`}\n onClick={(e) => {\n e.stopPropagation();\n onPrioritySelect?.(s.role);\n }}\n style={{ cursor: 'pointer', transition: `transform ${EASE}` }}\n >\n <title>{`${row.priorityCount} past the priority threshold — click to pull oldest first`}</title>\n <circle\n r={6.5 + (String(row.priorityCount).length - 1) * 2}\n fill={PRIORITY_COLOR}\n opacity={0.9}\n />\n <text\n y={2.5}\n textAnchor=\"middle\"\n fontSize={7}\n fill={PRIORITY_TEXT_COLOR}\n fontFamily=\"ui-monospace, monospace\"\n fontWeight=\"700\"\n >\n {row.priorityCount}\n </text>\n </g>\n )}\n\n {/* Merge affordance — this station also receives input from another\n sequence. The dashed drop into the floor says \"a side-quest\n lands here\"; clicking it opens that sequence. It is a symbol,\n deliberately not a line — the upstream is NOT a descendant. */}\n {(s.upstream_roles?.length ?? 0) > 0 && (\n <g\n transform={`translate(${x - 20} ${bottom})`}\n onClick={(e) => {\n e.stopPropagation();\n onUpstreamSelect?.(s.upstream_roles![0]);\n }}\n style={{ cursor: 'pointer' }}\n >\n <title>{`Fed by ${s.upstream_roles!.join(', ')} — click to view that sequence`}</title>\n <circle r={9} cy={-6} fill=\"transparent\" />\n <path d=\"M -7 -14 C -3 -14 -1 -9 0 -2\" fill=\"none\" stroke=\"#94a3b8\" strokeWidth={1} strokeDasharray=\"2 2\" strokeLinecap=\"round\" />\n <path d=\"M 0 -2 L 8 -2\" stroke=\"#94a3b8\" strokeWidth={1} strokeLinecap=\"round\" />\n <path d=\"M 8 -2 l -3.5 -2 v 4 z\" fill=\"#94a3b8\" />\n </g>\n )}\n\n {/* Station label — the display name (user-set title, or derived\n from the role id). The exact id lives in the table below.\n Adjacent labels alternate depth from the baseline so dense\n sequences don't collide. */}\n <text\n x={x}\n y={bottom + (row.idx % 2 === 0 ? 14 : 27)}\n textAnchor=\"middle\"\n fontSize={9.5}\n fill=\"#475569\"\n fontFamily=\"ui-sans-serif, sans-serif\"\n fontWeight=\"500\"\n >\n {displayRoleTitle(s)}\n </text>\n\n {/* Tooltip */}\n {isHovered && (\n <g>\n <rect x={tipX - tipW / 2} y={tipY - 16} width={tipW} height={19} rx={3} fill=\"#0f172a\" opacity={0.88} />\n <text x={tipX} y={tipY - 3} textAnchor=\"middle\" fontSize={8.5} fill=\"white\" fontFamily=\"ui-monospace, monospace\">\n {tooltip}\n </text>\n </g>\n )}\n </g>\n );\n })}\n\n {/* No-target hint */}\n {!hasTargets && (\n <text x={ML + chartW / 2} y={bottom + 48} textAnchor=\"middle\" fontSize={8.5} fill=\"#94a3b8\" fontFamily=\"ui-sans-serif, sans-serif\">\n Set target_per_hour on each role in Admin → Roles to enable the pace chart\n </text>\n )}\n\n {/* End labels — text + count, rendered last so they sit above everything */}\n {endLabels.map((l) => (\n <text\n key={l.key}\n x={right + 6}\n y={l.labelY}\n fontSize={8}\n fill={l.color}\n fontFamily=\"ui-sans-serif, sans-serif\"\n fontWeight={l.key === 'actual' ? 700 : 500}\n opacity={l.key === 'active' ? 0.85 : 1}\n style={{ transition: `y ${EASE}` }}\n >\n {l.text}\n </text>\n ))}\n </svg>\n );\n}\n","import type { RoleDetail } from '../../api/roles';\n\n/**\n * Deep link to the available-escalations queue ordered oldest-first by the\n * role's priority age origin: the metadata facet when configured (faceted\n * orderBy, nulls last), else created_at. Mirrors the priority_count SQL so\n * the counted items sit at the top of the list the runner opens.\n */\nexport function priorityQueueLink(role: Pick<RoleDetail, 'role' | 'priority_facet'>): string {\n const base = `/escalations/available?role=${encodeURIComponent(role.role)}`;\n if (role.priority_facet) {\n const orderBy = JSON.stringify([{ field: `metadata.${role.priority_facet}`, direction: 'asc' }]);\n return `${base}&orderBy=${encodeURIComponent(orderBy)}`;\n }\n return `${base}&sort_by=created_at&order=asc`;\n}\n","import { useState } from 'react';\nimport { Link } from 'react-router-dom';\nimport { X, ExternalLink } from 'lucide-react';\nimport { useStationMetrics } from '../../api/escalations';\nimport type { StationMetric } from '../../api/escalations';\nimport type { RoleDetail } from '../../api/roles';\nimport { PRIORITY_TEXT_COLOR } from './PaceChart';\nimport { priorityQueueLink } from './priority-link';\nimport { displayRoleTitle } from '../../lib/role-display';\n\ninterface StationDetailPanelProps {\n role: RoleDetail | null;\n allMetrics: StationMetric[];\n orderedRoles: RoleDetail[];\n globalPeriod: string;\n onClose: () => void;\n}\n\n// Mirrors OperationsPage's selector — the panel reports the same windows the\n// chart can show, and opens on whichever one the chart has selected.\nconst PERIODS = ['15m', '1h', '24h', '7d', '30d'] as const;\ntype Period = (typeof PERIODS)[number];\n\nconst isPeriod = (p: string): p is Period => (PERIODS as readonly string[]).includes(p);\n\nfunction fmt(min: number | null): string {\n if (min == null) return '—';\n if (min < 1) {\n const s = Math.round(min * 60);\n return s <= 0 ? '< 1s' : `${s}s`;\n }\n if (min < 60) return `${min.toFixed(0)}m`;\n return `${(min / 60).toFixed(1)}h`;\n}\n\nfunction MetricRow({ label, value }: { label: string; value: string }) {\n return (\n <div className=\"flex items-center justify-between py-1\">\n <span className=\"text-[10px] text-text-tertiary uppercase tracking-wider\">{label}</span>\n <span className=\"text-xs font-mono font-medium text-text-primary tabular-nums\">{value}</span>\n </div>\n );\n}\n\nfunction PeriodSelector({ period, onChange }: { period: Period; onChange: (p: Period) => void }) {\n return (\n <div className=\"flex items-center gap-1 mb-4\">\n {PERIODS.map((p) => (\n <button\n key={p}\n onClick={() => onChange(p)}\n className={`px-2 py-0.5 text-[10px] font-mono rounded transition-colors ${\n period === p\n ? 'bg-accent/10 text-accent font-semibold'\n : 'text-text-quaternary hover:text-text-secondary'\n }`}\n >\n {p}\n </button>\n ))}\n </div>\n );\n}\n\nfunction RoleView({ role, globalPeriod, onClose }: { role: RoleDetail; globalPeriod: string; onClose: () => void }) {\n // Open on the chart's selected window so the panel's numbers agree with the\n // chart beside it; the local selector still lets the viewer drill around.\n const [period, setPeriod] = useState<Period>(isPeriod(globalPeriod) ? globalPeriod : '24h');\n const { data } = useStationMetrics(period);\n const metric = data?.stations.find((s) => s.role === role.role);\n const slaMinutes = role.sla_minutes ?? undefined;\n const targetPerHour = role.target_per_hour ?? undefined;\n const workerCount = role.worker_count ?? undefined;\n\n return (\n <>\n {/* Header */}\n <div className=\"flex items-start justify-between mb-1\">\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-baseline gap-1.5 flex-wrap\">\n <span className=\"text-sm font-bold text-text-primary\">{displayRoleTitle(role)}</span>\n <span className=\"text-[10px] font-mono text-text-secondary\">{role.role}</span>\n </div>\n {role.description && (\n <p className=\"text-[10px] text-text-tertiary mt-0.5 line-clamp-2 leading-relaxed\">\n {role.description}\n </p>\n )}\n </div>\n <button\n onClick={onClose}\n className=\"text-text-quaternary hover:text-text-secondary transition-colors mt-0.5 shrink-0 ml-2\"\n >\n <X className=\"w-4 h-4\" />\n </button>\n </div>\n\n <Link\n to={`/admin/roles/${encodeURIComponent(role.role)}`}\n className=\"flex items-center gap-1 text-[10px] text-accent hover:underline mb-4\"\n >\n <ExternalLink className=\"w-2.5 h-2.5\" />\n Edit in Roles\n </Link>\n\n <PeriodSelector period={period} onChange={setPeriod} />\n\n {/* Capacity settings */}\n {(targetPerHour || slaMinutes || workerCount) && (\n <div className=\"flex items-center gap-4 mb-4 text-[10px]\">\n {targetPerHour && (\n <div>\n <div className=\"font-mono font-semibold text-text-primary\">{targetPerHour}/h</div>\n <div className=\"text-text-quaternary uppercase tracking-wider text-[8.5px]\">target</div>\n </div>\n )}\n {slaMinutes && (\n <div>\n <div className=\"font-mono font-semibold text-text-primary\">{slaMinutes}m</div>\n <div className=\"text-text-quaternary uppercase tracking-wider text-[8.5px]\">SLA</div>\n </div>\n )}\n {workerCount && (\n <div>\n <div className=\"font-mono font-semibold text-text-primary\">{workerCount}</div>\n <div className=\"text-text-quaternary uppercase tracking-wider text-[8.5px]\">workers</div>\n </div>\n )}\n </div>\n )}\n\n {/* Two-column wait / work grid */}\n <div className=\"grid grid-cols-2 gap-x-3\">\n <div>\n <p className=\"text-[9px] text-text-quaternary uppercase tracking-wider mb-1.5\">Wait (queue)</p>\n <MetricRow label=\"P99\" value={fmt(metric?.wait.p99 ?? null)} />\n <MetricRow label=\"avg\" value={fmt(metric?.wait.avg ?? null)} />\n </div>\n <div>\n <p className=\"text-[9px] text-text-quaternary uppercase tracking-wider mb-1.5\">Work (proc.)</p>\n <MetricRow label=\"P99\" value={fmt(metric?.work.p99 ?? null)} />\n <MetricRow label=\"avg\" value={fmt(metric?.work.avg ?? null)} />\n </div>\n </div>\n\n {/* SLA + priority */}\n <div className=\"border-t border-surface-border/40 pt-2 mt-3 space-y-1.5\">\n {slaMinutes && (\n <div className=\"flex items-center justify-between\">\n <span className=\"text-[10px] text-text-tertiary\">SLA target</span>\n <span className=\"text-xs font-mono text-text-secondary\">{slaMinutes}m</span>\n </div>\n )}\n {metric && metric.priority_count > 0 && (\n <Link\n to={priorityQueueLink(role)}\n className=\"flex items-center justify-between group\"\n >\n <span className=\"text-[10px]\" style={{ color: PRIORITY_TEXT_COLOR }}>\n {metric.priority_count} priority — pull oldest first\n </span>\n <ExternalLink className=\"w-3 h-3 transition-colors\" style={{ color: PRIORITY_TEXT_COLOR }} />\n </Link>\n )}\n </div>\n\n {/* View queue — `role=` drives the visible filter bar on the escalations\n page (the JSON `roles=` facet param filters silently and leaves the\n bar reading \"all roles\"). */}\n <div className=\"mt-4 border-t border-surface-border/40 pt-3\">\n <Link\n to={`/escalations/available?role=${encodeURIComponent(role.role)}`}\n className=\"flex items-center gap-1.5 text-[10px] text-accent hover:underline\"\n >\n View full queue\n <ExternalLink className=\"w-2.5 h-2.5\" />\n </Link>\n </div>\n </>\n );\n}\n\nfunction OverviewPanel({\n allMetrics,\n orderedRoles,\n period,\n}: {\n allMetrics: StationMetric[];\n orderedRoles: RoleDetail[];\n period: string;\n}) {\n const totalPending = allMetrics.reduce((s, m) => s + m.pending, 0);\n const totalResolved = allMetrics.reduce((s, m) => s + m.resolved, 0);\n const totalPriority = allMetrics.reduce((s, m) => s + m.priority_count, 0);\n\n const metricByRole = new Map(allMetrics.map((m) => [m.role, m]));\n const stationsAtRisk = allMetrics.filter((m) => m.priority_count > 0).length;\n const stationsWithLoad = allMetrics.filter((m) => m.pending > 0).length;\n\n return (\n <>\n <p className=\"text-[9px] text-text-quaternary uppercase tracking-wider mb-3\">\n Pipeline · {period}\n </p>\n\n {/* Health headline */}\n <div className=\"mb-4\">\n {stationsAtRisk > 0 ? (\n <p className=\"text-[11px]\" style={{ color: PRIORITY_TEXT_COLOR }}>\n {stationsAtRisk} station{stationsAtRisk > 1 ? 's' : ''} with priority items\n </p>\n ) : stationsWithLoad > 0 ? (\n <p className=\"text-[11px] text-status-warning\">\n {stationsWithLoad} station{stationsWithLoad > 1 ? 's' : ''} with backlog\n </p>\n ) : totalResolved > 0 ? (\n <p className=\"text-[11px] text-status-success\">Flowing — queue clear</p>\n ) : (\n <p className=\"text-[11px] text-text-quaternary\">Quiet — awaiting work</p>\n )}\n </div>\n\n {/* Key counters */}\n <div className=\"space-y-1.5 mb-4\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-[9px] text-text-quaternary uppercase tracking-wider\">Pending</span>\n <span className={`text-xs font-mono tabular-nums ${totalPending > 0 ? 'text-text-primary font-semibold' : 'text-text-quaternary'}`}>\n {totalPending}\n </span>\n </div>\n <div className=\"flex items-center justify-between\">\n <span className=\"text-[9px] text-text-quaternary uppercase tracking-wider\">Resolved · {period}</span>\n <span className=\"text-xs font-mono tabular-nums text-text-secondary\">{totalResolved}</span>\n </div>\n {totalPriority > 0 && (\n <div className=\"flex items-center justify-between\">\n <span className=\"text-[9px] text-text-quaternary uppercase tracking-wider\">Priority</span>\n <span className=\"text-xs font-mono tabular-nums font-semibold\" style={{ color: PRIORITY_TEXT_COLOR }}>\n {totalPriority}\n </span>\n </div>\n )}\n </div>\n\n {/* Divider + column headers */}\n <div className=\"border-t border-surface-border/40 pt-2 mb-1\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-[8px] text-text-quaternary uppercase tracking-wider flex-1\">Station</span>\n <span className=\"text-[8px] text-text-quaternary uppercase tracking-wider w-8 text-right shrink-0\">pend</span>\n <span className=\"text-[8px] text-text-quaternary uppercase tracking-wider w-8 text-right shrink-0\">clmd</span>\n <span className=\"text-[8px] text-text-quaternary uppercase tracking-wider w-8 text-right shrink-0\">res</span>\n </div>\n </div>\n\n {/* Station list in pipeline order */}\n <div className=\"space-y-0.5\">\n {orderedRoles.map((r) => {\n const m = metricByRole.get(r.role);\n const pending = m?.pending ?? 0;\n const claimed = m?.claimed ?? 0;\n const resolved = m?.resolved ?? 0;\n const priorityCount = m?.priority_count ?? 0;\n const label = r.title || r.role;\n const hasAlert = priorityCount > 0;\n const hasLoad = pending > 0;\n\n return (\n <div key={r.role} className=\"flex items-center gap-2 py-0.5\">\n <span\n className={`text-[10px] font-mono flex-1 truncate ${\n hasLoad ? 'text-text-primary' : 'text-text-quaternary'\n }`}\n >\n {label}\n {hasAlert && (\n <span className=\"ml-1 text-[8px] font-semibold\" style={{ color: PRIORITY_TEXT_COLOR }}>\n {priorityCount} PRIORITY\n </span>\n )}\n </span>\n <span\n className={`text-[10px] font-mono tabular-nums w-8 text-right shrink-0 ${\n hasLoad ? 'text-text-primary font-semibold' : 'text-text-quaternary'\n }`}\n >\n {pending > 0 ? pending : '—'}\n </span>\n <span className={`text-[10px] font-mono tabular-nums w-8 text-right shrink-0 ${claimed > 0 ? 'text-accent' : 'text-text-quaternary'}`}>\n {claimed > 0 ? claimed : '—'}\n </span>\n <span className={`text-[10px] font-mono tabular-nums w-8 text-right shrink-0 ${resolved > 0 ? 'text-text-secondary' : 'text-text-quaternary'}`}>\n {resolved > 0 ? resolved : '—'}\n </span>\n </div>\n );\n })}\n </div>\n\n <p className=\"text-[9px] text-text-quaternary mt-5\">\n Select a station for queue detail.\n </p>\n </>\n );\n}\n\nexport function StationDetailPanel({\n role,\n allMetrics,\n orderedRoles,\n globalPeriod,\n onClose,\n}: StationDetailPanelProps) {\n return (\n <div className=\"w-[280px] shrink-0 px-6 py-8 flex flex-col overflow-y-auto min-h-0\">\n {role ? (\n <RoleView role={role} globalPeriod={globalPeriod} onClose={onClose} />\n ) : (\n <OverviewPanel allMetrics={allMetrics} orderedRoles={orderedRoles} period={globalPeriod} />\n )}\n </div>\n );\n}\n","import { useState, useMemo, useCallback } from 'react';\nimport { Link, useNavigate, useSearchParams } from 'react-router-dom';\nimport { GitMerge, RefreshCw } from 'lucide-react';\nimport { useRoleDetails, type RoleDetail } from '../../api/roles';\nimport { useStationMetrics } from '../../api/escalations';\nimport type { StationMetric } from '../../api/escalations';\nimport { useStationMetricsEvents } from '../../hooks/useEventHooks';\nimport { PageHeader } from '../../components/common/layout/PageHeader';\nimport {\n PaceChart,\n ACTIVE_COLOR,\n QUEUED_COLOR,\n RESOLVED_COLOR,\n TARGET_COLOR,\n PRIORITY_COLOR,\n PRIORITY_TEXT_COLOR,\n type ChartStation,\n} from './PaceChart';\nimport { StationDetailPanel } from './StationDetailPanel';\nimport { priorityQueueLink } from './priority-link';\nimport { displayRoleTitle } from '../../lib/role-display';\n\n// Column band tints — the same hues as the chart's queue-composition bands\n// (~8% alpha), so PENDING/ACTIVE/RESOLVED in the table visually continue the\n// sky/indigo/sage story told above.\nconst TARGET_BAND = `${TARGET_COLOR}14`;\nconst PENDING_BAND = `${QUEUED_COLOR}14`;\nconst ACTIVE_BAND = `${ACTIVE_COLOR}14`;\nconst RESOLVED_BAND = `${RESOLVED_COLOR}14`;\n\n// Station table grid — shared by the header and every row. The display name\n// leads (user-set title or derived from the id); the exact role id follows.\nconst STATION_GRID_COLS = 'minmax(120px, 1.1fr) minmax(100px, 0.9fr) 64px 56px 56px 60px 72px 72px 104px';\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nconst PERIODS = ['15m', '1h', '24h', '7d', '30d'] as const;\ntype Period = (typeof PERIODS)[number];\n\n// Window length in hours — used to express the target as a count for the\n// selected window (target_per_hour × hours), e.g. 22/h over 15m ≈ 5 expected.\nconst PERIOD_HOURS: Record<Period, number> = {\n '15m': 0.25,\n '1h': 1,\n '24h': 24,\n '7d': 168,\n '30d': 720,\n};\n\ninterface OrderedStation {\n role: RoleDetail;\n depth: number;\n}\n\n/**\n * One sequence of stations, named by its origin role. Execution is a graph;\n * each fragment is the human-readable line the user composed via parent_role.\n * Cross-fragment edges live in upstream_roles and render as a merge affordance\n * on the chart, never as a bend in the line.\n */\ninterface SequenceFragment {\n origin: RoleDetail;\n stations: OrderedStation[];\n}\n\n// ── Fragment builder — BFS per parent_role root, tracking actual depth ────────\n\nexport function buildFragments(roles: RoleDetail[]): SequenceFragment[] {\n const opsRoles = roles.filter((r) => r.ops_visible);\n const roleMap = new Map(opsRoles.map((r) => [r.role, r]));\n const visited = new Set<string>();\n\n // Roots: no parent, or parent not in ops set — each roots its own fragment.\n const roots = opsRoles.filter((r) => !r.parent_role || !roleMap.has(r.parent_role));\n\n const fragments: SequenceFragment[] = roots.map((root) => {\n const stations: OrderedStation[] = [];\n const queue: OrderedStation[] = [{ role: root, depth: 0 }];\n while (queue.length > 0) {\n const item = queue.shift()!;\n if (visited.has(item.role.role)) continue;\n visited.add(item.role.role);\n stations.push(item);\n opsRoles\n .filter((c) => c.parent_role === item.role.role && !visited.has(c.role))\n .forEach((c) => queue.push({ role: c, depth: item.depth + 1 }));\n }\n return { origin: root, stations };\n });\n\n // Unreachable (cycles / dangling) — each stands alone rather than vanishing.\n opsRoles\n .filter((r) => !visited.has(r.role))\n .forEach((r) => fragments.push({ origin: r, stations: [{ role: r, depth: 0 }] }));\n\n // Longest line first — the primary sequence leads; side-quests follow.\n return fragments.sort(\n (a, b) => b.stations.length - a.stations.length || a.origin.role.localeCompare(b.origin.role),\n );\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction fmtMin(v: number | null): string {\n if (v == null) return '—';\n if (v < 1) {\n const s = Math.round(v * 60);\n return s <= 0 ? '< 1s' : `${s}s`;\n }\n if (v < 60) return `${v.toFixed(0)}m`;\n return `${(v / 60).toFixed(1)}h`;\n}\n\nfunction loadBar(pending: number, target: number | null) {\n // No target, or nothing pending — there is no live load to trend. Show the\n // empty state rather than inventing a rate from historical throughput.\n if (!target || pending === 0) return { pct: null, color: 'bg-surface-border' };\n\n const ratio = pending / target;\n const pct = Math.round(ratio * 100);\n // Amber: backlog. Orange: some work but well under pace. Green: healthy.\n const color = ratio > 1.0 ? 'bg-status-warning' : ratio < 0.2 ? 'bg-status-draft' : 'bg-status-success';\n return { pct, color };\n}\n\n// ── Station table row ─────────────────────────────────────────────────────────\n\nfunction StationRow({\n role,\n metric,\n selected,\n onClick,\n}: {\n role: RoleDetail;\n metric: StationMetric | undefined;\n selected: boolean;\n onClick: () => void;\n}) {\n const pending = metric?.pending ?? 0;\n const claimed = metric?.claimed ?? 0;\n const resolved = metric?.resolved ?? 0;\n const priorityCount = metric?.priority_count ?? 0;\n const target = role.target_per_hour ?? null;\n const { pct, color } = loadBar(pending, target);\n const barWidth = pct != null ? Math.min(100, pct) : 0;\n\n return (\n <>\n <div\n role=\"button\"\n tabIndex={0}\n onClick={onClick}\n onKeyDown={(e) => { if (e.key === 'Enter') onClick(); }}\n className={`grid items-center gap-4 pr-3 cursor-pointer transition-colors ${\n selected ? 'border-l-2 !border-l-accent pl-2.5' : 'pl-3'\n }`}\n style={{ gridTemplateColumns: STATION_GRID_COLS }}\n >\n {/* Name — user-set title, or derived from the role id */}\n <div className=\"flex items-center gap-1.5 min-w-0 py-1.5\">\n <span className=\"font-bold text-text-primary truncate text-xs\">\n {displayRoleTitle(role)}\n </span>\n {(role.upstream_roles?.length ?? 0) > 0 && (\n <span title={`Fed by ${role.upstream_roles.join(', ')}`} className=\"shrink-0 leading-none\">\n <GitMerge className=\"w-3 h-3 text-text-quaternary\" />\n </span>\n )}\n </div>\n\n {/* Role id — the exact format */}\n <span className=\"font-mono text-[11px] text-text-tertiary truncate py-1.5\">\n {role.role}\n </span>\n\n {/* Target / hour — emerald band, same hue as the chart's target line */}\n <div\n className=\"self-stretch flex items-center justify-end px-1.5\"\n style={{ backgroundColor: TARGET_BAND }}\n >\n <span\n className={`text-xs font-mono tabular-nums ${\n target != null ? 'text-text-secondary' : 'text-text-quaternary'\n }`}\n >\n {target != null ? target : '—'}\n </span>\n </div>\n\n {/* Pending — sky band, same hue as the chart's waiting band */}\n <div\n className=\"self-stretch flex items-center justify-end px-1.5\"\n style={{ backgroundColor: PENDING_BAND }}\n >\n <span\n className={`text-xs font-mono tabular-nums ${\n pending > 0 ? 'text-text-primary font-semibold' : 'text-text-quaternary'\n }`}\n >\n {pending}\n </span>\n </div>\n\n {/* Active — indigo band, same hue as the chart's worked band */}\n <div\n className=\"self-stretch flex items-center justify-end px-1.5\"\n style={{ backgroundColor: ACTIVE_BAND }}\n >\n <span\n className={`text-xs font-mono tabular-nums ${\n claimed > 0 ? 'text-accent font-semibold' : 'text-text-quaternary'\n }`}\n >\n {claimed}\n </span>\n </div>\n\n {/* Resolved — sage band, same hue as the chart's actual curve */}\n <div\n className=\"self-stretch flex items-center justify-end px-1.5\"\n style={{ backgroundColor: RESOLVED_BAND }}\n >\n <span className=\"text-xs font-mono tabular-nums text-text-quaternary\">\n {resolved}\n </span>\n </div>\n\n {/* P99 wait */}\n <span className=\"text-xs font-mono tabular-nums text-right py-1.5 text-text-secondary\">\n {fmtMin(metric?.wait.p99 ?? null)}\n </span>\n\n {/* P99 work */}\n <span className=\"text-xs font-mono tabular-nums text-right py-1.5 text-text-secondary\">\n {fmtMin(metric?.work.p99 ?? null)}\n </span>\n\n {/* Load mini-bar */}\n <div className=\"flex items-center gap-2 py-1.5\">\n <div className=\"w-12 h-1.5 bg-surface-sunken rounded-full overflow-hidden shrink-0\">\n <div className={`h-full rounded-full ${color}`} style={{ width: `${barWidth}%` }} />\n </div>\n <span\n className={`text-[10px] font-mono tabular-nums ${\n pct != null && pct > 100\n ? 'text-status-warning font-semibold'\n : 'text-text-quaternary'\n }`}\n >\n {pct != null ? `${pct}%` : '—'}\n </span>\n </div>\n </div>\n\n {/* Priority sub-row — unclaimed items past the role's age threshold */}\n {priorityCount > 0 && (\n <div className=\"flex items-center gap-1.5 pb-2 pl-3.5\">\n <span\n className=\"w-2.5 h-2.5 rounded-full dot-ring shrink-0\"\n style={{ backgroundColor: PRIORITY_COLOR }}\n />\n <Link\n to={priorityQueueLink(role)}\n className=\"text-[10px] hover:underline\"\n style={{ color: PRIORITY_TEXT_COLOR }}\n onClick={(e) => e.stopPropagation()}\n >\n {priorityCount} priority — pull oldest first →\n </Link>\n </div>\n )}\n </>\n );\n}\n\n// ── Table header ──────────────────────────────────────────────────────────────\n\nfunction TableHead() {\n // Queue-state columns carry the chart's band hue into the table.\n const cols: { label: string; band?: string; hue?: string }[] = [\n { label: 'NAME' },\n { label: 'ROLE' },\n { label: 'TARGET/H', band: TARGET_BAND, hue: TARGET_COLOR },\n { label: 'PENDING', band: PENDING_BAND, hue: QUEUED_COLOR },\n { label: 'CLAIMED', band: ACTIVE_BAND, hue: ACTIVE_COLOR },\n { label: 'RESOLVED', band: RESOLVED_BAND, hue: RESOLVED_COLOR },\n { label: 'P99 WAIT' },\n { label: 'P99 WORK' },\n { label: 'TREND' },\n ];\n return (\n <div\n className=\"grid items-center gap-4 px-3 border-b border-surface-border mb-0.5\"\n style={{ gridTemplateColumns: STATION_GRID_COLS }}\n >\n {cols.map((col, i) =>\n col.band ? (\n <div\n key={col.label}\n className=\"self-stretch flex items-center justify-end px-1.5\"\n style={{ backgroundColor: col.band }}\n >\n <span\n className=\"text-[9px] font-semibold uppercase tracking-wider\"\n style={{ color: col.hue }}\n >\n {col.label}\n </span>\n </div>\n ) : (\n <span\n key={col.label}\n className={`text-[9px] font-semibold uppercase tracking-wider text-text-quaternary py-1.5 ${\n i > 1 && i < 8 ? 'text-right' : ''\n }`}\n >\n {col.label}\n </span>\n ),\n )}\n </div>\n );\n}\n\n\n// ── Page ──────────────────────────────────────────────────────────────────────\n\nexport function OperationsPage() {\n // 1h default: long enough to show a whole simulation shift's shape,\n // short enough that stale history doesn't drown the current run.\n const [period, setPeriod] = useState<Period>('1h');\n const [selectedRole, setSelectedRole] = useState<string | null>(null);\n const [refreshing, setRefreshing] = useState(false);\n\n // Push-driven refresh: every escalation event invalidates ['stationMetrics']\n // through the central event system (debounced, transport-agnostic). The\n // header's refresh button covers user-initiated reloads.\n useStationMetricsEvents();\n\n const { data: roleData, isLoading: rolesLoading, refetch: refetchRoles } = useRoleDetails();\n const {\n data: metricsData,\n isLoading: metricsLoading,\n refetch: refetchMetrics,\n } = useStationMetrics(period);\n\n const roles = roleData?.roles ?? [];\n const metrics = metricsData?.stations ?? [];\n\n // Sequence fragments, one per parent_role root. The active one is\n // DEEP-LINKED (?fragment=<origin role>) and each switch is a history entry,\n // so a shared link opens the same sequence and back/forward walks them.\n const fragments = useMemo((): SequenceFragment[] => buildFragments(roles), [roles]);\n const [searchParams, setSearchParams] = useSearchParams();\n const fragmentParam = searchParams.get('fragment');\n const activeFragment =\n fragments.find((f) => f.origin.role === fragmentParam) ?? fragments[0] ?? null;\n const selectFragment = useCallback(\n (origin: string) => {\n setSelectedRole(null);\n setSearchParams((prev) => {\n const p = new URLSearchParams(prev);\n p.set('fragment', origin);\n return p;\n });\n },\n [setSearchParams],\n );\n\n const ordered = activeFragment?.stations ?? [];\n const fragmentRoleSet = useMemo(\n () => new Set(ordered.map(({ role }) => role.role)),\n [ordered],\n );\n const fragmentMetrics = useMemo(\n () => metrics.filter((m) => fragmentRoleSet.has(m.role)),\n [metrics, fragmentRoleSet],\n );\n\n const chartStations = useMemo(\n (): ChartStation[] =>\n ordered.map(({ role: r }) => ({\n role: r.role,\n title: r.title,\n parent_role: r.parent_role,\n target_per_hour: r.target_per_hour ?? null,\n upstream_roles: r.upstream_roles ?? [],\n metric: metrics.find((m) => m.role === r.role),\n })),\n [ordered, metrics],\n );\n\n // Jump to the sequence that feeds this station — the merge glyph's click.\n const handleUpstreamSelect = useCallback(\n (upstreamRole: string) => {\n const target = fragments.find((f) =>\n f.stations.some(({ role }) => role.role === upstreamRole),\n );\n if (target) selectFragment(target.origin.role);\n },\n [fragments, selectFragment],\n );\n\n // Priority-badge click — open the station's queue oldest-first by its facet.\n const navigate = useNavigate();\n const handlePrioritySelect = useCallback(\n (roleName: string) => {\n const detail = roles.find((r) => r.role === roleName);\n if (detail) navigate(priorityQueueLink(detail));\n },\n [roles, navigate],\n );\n\n const selectedRoleDetail =\n ordered.find(({ role }) => role.role === selectedRole)?.role ?? null;\n\n const isLoading = rolesLoading || metricsLoading;\n\n const handleRefresh = async () => {\n setRefreshing(true);\n await Promise.all([refetchRoles(), refetchMetrics()]);\n setRefreshing(false);\n };\n\n const handleSelect = (role: string) =>\n setSelectedRole((prev) => (prev === role ? null : role));\n\n const periodSelector = (\n <div className=\"flex items-center gap-0.5\">\n {PERIODS.map((p) => (\n <button\n key={p}\n onClick={() => setPeriod(p)}\n className={`px-2.5 py-1 text-[10px] font-mono rounded transition-colors ${\n period === p\n ? 'bg-accent/10 text-accent font-semibold'\n : 'text-text-quaternary hover:text-text-secondary'\n }`}\n >\n {p}\n </button>\n ))}\n </div>\n );\n\n return (\n <div className=\"flex flex-col flex-1 min-h-0\">\n <PageHeader\n title=\"Pace Board\"\n docsHash=\"#docs:dashboard.md:pace-board\"\n center={periodSelector}\n actions={\n <button\n onClick={handleRefresh}\n disabled={refreshing}\n className=\"text-text-quaternary hover:text-text-secondary transition-colors disabled:opacity-40\"\n >\n <RefreshCw className={`w-3.5 h-3.5 ${refreshing ? 'animate-spin' : ''}`} />\n </button>\n }\n />\n\n {isLoading ? (\n <div className=\"animate-pulse space-y-6 mt-4\">\n <div className=\"h-8 bg-surface-sunken rounded w-64\" />\n <div className=\"h-64 bg-surface-sunken rounded w-full\" />\n <div className=\"space-y-3\">\n {[1, 2, 3].map((i) => (\n <div key={i} className=\"h-8 bg-surface-sunken rounded w-full\" />\n ))}\n </div>\n </div>\n ) : fragments.length === 0 ? (\n <div className=\"mt-8\">\n <p className=\"text-sm text-text-secondary mb-2\">Stations appear here once roles are marked visible in Operations.</p>\n <p className=\"text-xs text-text-tertiary\">\n Go to{' '}\n <Link to=\"/admin/roles\" className=\"text-accent hover:underline\">\n Roles\n </Link>{' '}\n and enable <strong>Visible in Operations</strong> on roles that represent pipeline\n stations.\n </p>\n </div>\n ) : (\n /* Console layout: fixed header (above) → chart row (min 40vh) → table row (max 30vh) */\n <div className=\"flex flex-col flex-1 min-h-0\">\n\n {/* Sequence picker — one tab per fragment, named by its origin role.\n Only rendered when there is more than one story to tell. */}\n {fragments.length > 1 && (\n <div className=\"flex items-center gap-0.5 px-4 pt-2\">\n {fragments.map((f) => {\n const isActive = f.origin.role === activeFragment?.origin.role;\n return (\n <button\n key={f.origin.role}\n onClick={() => selectFragment(f.origin.role)}\n className={`px-2.5 py-1 text-[10px] font-mono rounded transition-colors ${\n isActive\n ? 'bg-accent/10 text-accent font-semibold'\n : 'text-text-quaternary hover:text-text-secondary'\n }`}\n >\n {displayRoleTitle(f.origin)}\n <span className={`ml-1.5 tabular-nums ${isActive ? 'text-accent/60' : 'text-text-quaternary/60'}`}>\n {f.stations.length}\n </span>\n </button>\n );\n })}\n </div>\n )}\n\n {/* Middle row: flexible, never below 40vh — SVG fills left, sidebar fixed-width right */}\n <div className=\"flex-1 min-h-[40vh] flex items-stretch overflow-hidden\">\n {/* SVG chart — scales to fill available space */}\n <div className=\"flex-1 min-w-0 min-h-0 flex flex-col justify-center overflow-hidden p-4\">\n <PaceChart\n stations={chartStations}\n selectedRole={selectedRole}\n onSelect={handleSelect}\n onUpstreamSelect={handleUpstreamSelect}\n onPrioritySelect={handlePrioritySelect}\n periodHours={PERIOD_HOURS[period]}\n />\n </div>\n {/* Vertical divider */}\n <div className=\"w-px bg-surface-border shrink-0 self-stretch\" />\n {/* Right sidebar — fixed width, scrolls its own content */}\n <StationDetailPanel\n role={selectedRoleDetail}\n allMetrics={fragmentMetrics}\n orderedRoles={ordered.map((o) => o.role)}\n globalPeriod={period}\n onClose={() => setSelectedRole(null)}\n />\n </div>\n\n {/* Bottom row: sized to its rows up to 30vh — header sticky, rows scroll */}\n <div className=\"max-h-[30vh] flex-none flex flex-col border-t border-surface-border overflow-hidden\">\n <TableHead />\n <div className=\"flex-1 min-h-0 overflow-y-auto divide-y divide-surface-border/30\">\n {ordered.map(({ role }) => (\n <StationRow\n key={role.role}\n role={role}\n metric={metrics.find((m) => m.role === role.role)}\n selected={selectedRole === role.role}\n onClick={() => handleSelect(role.role)}\n />\n ))}\n </div>\n </div>\n\n </div>\n )}\n </div>\n );\n}\n"],"names":["deriveRoleTitle","role","w","displayRoleTitle","r","_a","W","H","ML","MR","MT","MB","chartW","chartH","bottom","right","EASE","SOLO_HALF","soloSegment","p","catmullPath","pts","segs","i","p0","p1","p2","p3","cp1x","cp1y","cp2x","cp2y","bandPath","upper","lower","forward","rev","back","backSegs","compact","n","last","a","ACTIVE_COLOR","QUEUED_COLOR","RESOLVED_COLOR","TARGET_COLOR","PRIORITY_COLOR","PRIORITY_TEXT_COLOR","MIN_GAP","spreadLabels","labels","maxY","sorted","b","prev","placed","l","labelY","overflow","PaceChart","stations","selectedRole","onSelect","onUpstreamSelect","onPrioritySelect","periodHours","hoveredIdx","setHoveredIdx","useState","xOf","xMap","rows","target","expected","_b","_c","_d","hasTargets","maxVal","yScale","v","withTarget","targetPts","actualPts","activePts","pendingPts","targetLinePath","actualSplinePath","activeSplinePath","pendingSplinePath","lastActual","lastTarget","lastActive","lastPending","areaPath","hasQueue","workedBandPath","queuedBandPath","showActiveLabel","showQueuedLabel","endLabels","px","cx","jsx","tp","ap","ar","hasWaiting","pendingLabelY","row","s","x","cy","isSelected","isHovered","tooltip","tipW","tipX","tipY","jsxs","e","priorityQueueLink","base","orderBy","PERIODS","isPeriod","fmt","min","MetricRow","label","value","PeriodSelector","period","onChange","RoleView","globalPeriod","onClose","setPeriod","data","useStationMetrics","metric","slaMinutes","targetPerHour","workerCount","Fragment","X","Link","ExternalLink","OverviewPanel","allMetrics","orderedRoles","totalPending","m","totalResolved","totalPriority","metricByRole","stationsAtRisk","stationsWithLoad","pending","claimed","resolved","priorityCount","hasAlert","hasLoad","StationDetailPanel","TARGET_BAND","PENDING_BAND","ACTIVE_BAND","RESOLVED_BAND","STATION_GRID_COLS","PERIOD_HOURS","buildFragments","roles","opsRoles","roleMap","visited","fragments","root","queue","item","c","fmtMin","loadBar","ratio","pct","color","StationRow","selected","onClick","barWidth","GitMerge","TableHead","cols","col","OperationsPage","setSelectedRole","refreshing","setRefreshing","useStationMetricsEvents","roleData","rolesLoading","refetchRoles","useRoleDetails","metricsData","metricsLoading","refetchMetrics","metrics","useMemo","searchParams","setSearchParams","useSearchParams","fragmentParam","activeFragment","f","selectFragment","useCallback","origin","ordered","fragmentRoleSet","fragmentMetrics","chartStations","handleUpstreamSelect","upstreamRole","navigate","useNavigate","handlePrioritySelect","roleName","detail","selectedRoleDetail","isLoading","handleRefresh","handleSelect","periodSelector","PageHeader","RefreshCw","isActive","o"],"mappings":"iXAMO,SAASA,GAAgBC,EAAsB,CACpD,OAAOA,EACJ,QAAQ,qBAAsB,OAAO,EACrC,QAAQ,wBAAyB,OAAO,EACxC,MAAM,SAAS,EACf,OAAO,OAAO,EACd,IAAKC,GAAMA,EAAE,OAAO,CAAC,EAAE,cAAgBA,EAAE,MAAM,CAAC,CAAC,EACjD,KAAK,GAAG,CACb,CAOO,SAASC,GAAiBC,EAAoD,OACnF,QAAOC,EAAAD,EAAE,QAAF,YAAAC,EAAS,SAAUL,GAAgBI,EAAE,IAAI,CAClD,CCKA,MAAME,GAAI,IACJC,GAAI,IACJC,EAAK,GACLC,GAAK,GACLC,GAAK,GACLC,GAAK,GAELC,GAASN,GAAIE,EAAKC,GAClBI,GAASN,GAAIG,GAAKC,GAClBG,EAASJ,GAAKG,GACdE,GAAQP,EAAKI,GAGbI,EAAO,oCAQPC,GAAY,EAClB,SAASC,GAAYC,EAAqC,CACxD,MAAO,MAAMA,EAAE,EAAIF,IAAW,QAAQ,CAAC,CAAC,IAAIE,EAAE,EAAE,QAAQ,CAAC,CAAC,OAAOA,EAAE,EAAIF,IAAW,QAAQ,CAAC,CAAC,IAAIE,EAAE,EAAE,QAAQ,CAAC,CAAC,EAChH,CAGA,SAASC,EAAYC,EAAyC,CAC5D,GAAIA,EAAI,SAAW,EAAG,MAAO,GAC7B,GAAIA,EAAI,SAAW,SAAUH,GAAYG,EAAI,CAAC,CAAC,EAC/C,MAAMC,EAAiB,CAAA,EACvB,QAASC,EAAI,EAAGA,EAAIF,EAAI,OAAS,EAAGE,IAAK,CACvC,MAAMC,EAAKH,EAAI,KAAK,IAAI,EAAGE,EAAI,CAAC,CAAC,EAC3BE,EAAKJ,EAAIE,CAAC,EACVG,EAAKL,EAAIE,EAAI,CAAC,EACdI,EAAKN,EAAI,KAAK,IAAIA,EAAI,OAAS,EAAGE,EAAI,CAAC,CAAC,EACxCK,GAAQH,EAAG,GAAKC,EAAG,EAAIF,EAAG,GAAK,GAAG,QAAQ,CAAC,EAC3CK,GAAQJ,EAAG,GAAKC,EAAG,EAAIF,EAAG,GAAK,GAAG,QAAQ,CAAC,EAC3CM,GAAQJ,EAAG,GAAKC,EAAG,EAAIF,EAAG,GAAK,GAAG,QAAQ,CAAC,EAC3CM,GAAQL,EAAG,GAAKC,EAAG,EAAIF,EAAG,GAAK,GAAG,QAAQ,CAAC,EAC7CF,IAAM,GAAGD,EAAK,KAAK,KAAKG,EAAG,EAAE,QAAQ,CAAC,CAAC,IAAIA,EAAG,EAAE,QAAQ,CAAC,CAAC,EAAE,EAChEH,EAAK,KAAK,KAAKM,CAAI,IAAIC,CAAI,KAAKC,CAAI,IAAIC,CAAI,KAAKL,EAAG,EAAE,QAAQ,CAAC,CAAC,IAAIA,EAAG,EAAE,QAAQ,CAAC,CAAC,EAAE,CACvF,CACA,OAAOJ,EAAK,KAAK,GAAG,CACtB,CAOA,SAASU,GAASC,EAAmCC,EAA2C,CAC9F,GAAID,EAAM,OAAS,GAAKC,EAAM,OAAS,EAAG,MAAO,GACjD,MAAMC,EAAUf,EAAYa,CAAK,EAC3BG,EAAM,CAAC,GAAGF,CAAK,EAAE,QAAA,EACjBG,EAAOjB,EAAYgB,CAAG,EAEtBE,EAAWD,EAAK,MAAMA,EAAK,QAAQ,GAAG,CAAC,EAC7C,MAAO,GAAGF,CAAO,MAAMC,EAAI,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC,IAAIA,EAAI,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC,IAAIE,CAAQ,IAC/E,CAEA,SAASC,GAAQC,EAAmB,CAClC,OAAOA,GAAK,IAAQ,GAAG,KAAK,MAAMA,EAAI,GAAI,CAAC,IAAMA,GAAK,IAAO,IAAIA,EAAI,KAAM,QAAQ,CAAC,CAAC,IAAM,OAAOA,CAAC,CACrG,CAEA,SAASC,GAAQC,EAAuB,CACtC,OAAOA,EAAE,OAAS,EAAIA,EAAEA,EAAE,OAAS,CAAC,EAAI,MAC1C,CAMO,MAAMC,EAAe,UACfC,EAAe,UACfC,EAAiB,UACjBC,EAAe,UAKfC,GAAiB,UACjBC,EAAsB,UAI7BC,GAAU,GAChB,SAASC,GAAsCC,EAAaC,EAA0C,CACpG,MAAMC,EAAS,CAAC,GAAGF,CAAM,EAAE,KAAK,CAAC,EAAGG,IAAM,EAAE,EAAIA,EAAE,CAAC,EACnD,IAAIC,EAAO,KACX,MAAMC,EAASH,EAAO,IAAKI,GAAM,CAC/B,MAAMC,EAAS,KAAK,IAAID,EAAE,EAAI,EAAGF,EAAON,EAAO,EAC/C,OAAAM,EAAOG,EACA,CAAE,GAAGD,EAAG,OAAAC,CAAA,CACjB,CAAC,EAIKC,EAAWH,EAAO,OAAS,EAAIA,EAAOA,EAAO,OAAS,CAAC,EAAE,OAASJ,EAAO,EAC/E,GAAIO,EAAW,EACb,UAAWF,KAAKD,EAAQC,EAAE,QAAUE,EAEtC,OAAOH,CACT,CAIO,SAASI,GAAU,CAAE,SAAAC,EAAU,aAAAC,EAAc,SAAAC,EAAU,iBAAAC,EAAkB,iBAAAC,EAAkB,YAAAC,GAA+B,CAC/H,KAAM,CAACC,EAAYC,CAAa,EAAIC,EAAAA,SAAwB,IAAI,EAE1D7B,EAAIqB,EAAS,OACnB,GAAIrB,IAAM,EAAG,OAAO,KAEpB,MAAM8B,EAAO/C,GAAeiB,IAAM,EAAIhC,EAAKI,GAAS,EAAIJ,EAAMe,GAAKiB,EAAI,GAAM5B,GACvE2D,EAAO,IAAI,IAAIV,EAAS,IAAI,CAAC,EAAGtC,IAAM,CAAC,EAAE,KAAM+C,EAAI/C,CAAC,CAAC,CAAC,CAAC,EAMvDiD,EAAOX,EAAS,IAAI,CAAC,EAAGtC,IAAM,aAClC,MAAMkD,EAAS,EAAE,iBAAmB,KAC9BC,EAAWD,GAAU,KAAOA,EAASP,EAAc,KACzD,MAAO,CACL,IAAK3C,EACL,EAAG+C,EAAI/C,CAAC,EACR,SAAAmD,EACA,SAAQrE,EAAA,EAAE,SAAF,YAAAA,EAAU,WAAY,EAC9B,SAAQsE,EAAA,EAAE,SAAF,YAAAA,EAAU,UAAW,EAC7B,UAASC,EAAA,EAAE,SAAF,YAAAA,EAAU,UAAW,EAC9B,gBAAeC,EAAA,EAAE,SAAF,YAAAA,EAAU,iBAAkB,CAAA,CAE/C,CAAC,EAEKC,EAAaN,EAAK,KAAMpE,GAAMA,EAAE,UAAY,IAAI,EAQhD2E,EANU,KAAK,IACnB,EACA,GAAGP,EAAK,IAAKpE,GAAMA,EAAE,UAAY,CAAC,EAClC,GAAGoE,EAAK,IAAKpE,GAAMA,EAAE,MAAM,EAC3B,GAAGoE,EAAK,IAAKpE,GAAOA,EAAE,UAAY,KAAOA,EAAE,QAAU,CAAE,CAAA,EAEhC,KACnB4E,EAAUC,GAAcvE,GAAKG,IAAU,EAAI,KAAK,IAAI,EAAG,KAAK,IAAIoE,EAAGF,CAAM,CAAC,EAAIA,GAE9EG,EAAaV,EAAK,OAAQpE,GAAMA,EAAE,UAAY,IAAI,EAClD+E,EAAYD,EAAW,IAAK9E,IAAO,CAAE,GAAGA,EAAG,EAAG4E,EAAO5E,EAAE,QAAkB,GAAI,EAC7EgF,EAAYF,EAAW,IAAK9E,IAAO,CAAE,GAAGA,EAAG,EAAG4E,EAAO5E,EAAE,MAAM,GAAI,EACjEiF,EAAYH,EAAW,IAAK9E,IAAO,CAAE,GAAGA,EAAG,EAAG4E,EAAO5E,EAAE,MAAM,GAAI,EACjEkF,EAAaJ,EAAW,IAAK9E,IAAO,CAAE,GAAGA,EAAG,EAAG4E,EAAO5E,EAAE,OAAO,GAAI,EAEnEmF,EAAiBnE,EAAY+D,CAAS,EACtCK,EAAmBpE,EAAYgE,CAAS,EACxCK,EAAmBrE,EAAYiE,CAAS,EACxCK,EAAoBtE,EAAYkE,CAAU,EAE1CK,EAAalD,GAAK2C,CAAS,EAC3BQ,EAAanD,GAAK0C,CAAS,EAC3BU,EAAapD,GAAK4C,CAAS,EAC3BS,EAAcrD,GAAK6C,CAAU,EAE7BS,GACJX,EAAU,QAAU,GAAKO,EACrB,GAAGH,CAAgB,MAAMG,EAAW,EAAE,QAAQ,CAAC,CAAC,IAAI7E,CAAM,MAAMsE,EAAU,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC,IAAItE,CAAM,KACnG,GAOAkF,EAAWd,EAAW,KAAM9E,GAAMA,EAAE,QAAU,GAAKA,EAAE,OAAS,CAAC,EAC/D6F,GACJD,GAAYX,EAAU,QAAU,GAAKQ,EACjC,GAAGJ,CAAgB,MAAMI,EAAW,EAAE,QAAQ,CAAC,CAAC,IAAI/E,CAAM,MAAMuE,EAAU,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC,IAAIvE,CAAM,KACnG,GACAoF,EAAiBF,EAAWhE,GAASsD,EAAYD,CAAS,EAAI,GAI9Dc,EAAkBjB,EAAW,KAAM9E,GAAMA,EAAE,OAAS,CAAC,EACrDgG,EAAkBlB,EAAW,KAAM9E,GAAMA,EAAE,QAAUA,EAAE,MAAM,EAC7DiG,EAAYnD,GAChB,CACE0C,EAAa,CAAE,IAAK,SAAU,KAAM,SAAU,MAAO9C,EAAc,EAAG8C,EAAW,CAAA,EAAM,KACvFD,EAAa,CAAE,IAAK,SAAU,KAAM,WAAY,MAAO9C,EAAgB,EAAG8C,EAAW,CAAA,EAAM,KAC3FQ,GAAmBN,EACf,CAAE,IAAK,SAAU,KAAM,UAAW,MAAOlD,EAAc,EAAGkD,EAAW,CAAA,EACrE,KACJO,GAAmBN,EACf,CAAE,IAAK,SAAU,KAAM,UAAW,MAAOlD,EAAc,EAAGkD,EAAY,CAAA,EACtE,IAAA,EACJ,OAAO,OAAO,EAChBhF,EAAS,CAAA,EAGX,cACG,MAAA,CAAI,QAAS,OAAOR,EAAC,IAAIC,EAAC,GAAI,UAAU,gBAAgB,oBAAoB,gBAAgB,MAAO,CAAE,QAAS,SAE5G,SAAA,CAAAsD,EAAS,IAAK,GAAM,CACnB,GAAI,CAAC,EAAE,YAAa,OAAO,KAC3B,MAAMyC,EAAK/B,EAAK,IAAI,EAAE,WAAW,EACjC,GAAI+B,GAAM,KAAM,OAAO,KACvB,MAAMC,EAAKjC,EAAIT,EAAS,UAAWzD,GAAMA,EAAE,OAAS,EAAE,IAAI,CAAC,EAC3D,aAAQ,OAAA,CAA2B,GAAIkG,EAAI,GAAIxF,EAAQ,GAAIyF,EAAI,GAAIzF,EAAQ,OAAO,UAAU,YAAa,KAAvF,OAAO,EAAE,IAAI,EAAgF,CACjH,CAAC,EAGAiF,IAAYS,EAAAA,IAAC,OAAA,CAAK,EAAGT,GAAU,KAAMlD,EAAgB,QAAS,IAAM,MAAO,CAAE,WAAY,KAAK7B,CAAI,IAAM,EAKxGiF,IACCO,EAAAA,IAAC,OAAA,CAAK,EAAGP,GAAgB,KAAMtD,EAAc,QAAS,IAAM,MAAO,CAAE,WAAY,KAAK3B,CAAI,IAAM,EAEjGkF,GACCM,EAAAA,IAAC,OAAA,CAAK,EAAGN,EAAgB,KAAMtD,EAAc,QAAS,IAAM,MAAO,CAAE,WAAY,KAAK5B,CAAI,IAAM,EAIjGuE,SACE,OAAA,CAAK,EAAGA,EAAgB,KAAK,OAAO,OAAQzC,EAAc,YAAa,GAAK,eAAe,QAAQ,QAAS,GAAK,MAAO,CAAE,WAAY,KAAK9B,CAAI,EAAA,EAAM,EAMvJmE,EAAU,IAAKsB,UACb,IAAA,CAAyB,UAAW,aAAaA,EAAG,CAAC,IAAIA,EAAG,CAAC,IAAK,MAAO,CAAE,WAAY,aAAazF,CAAI,IACvG,SAAA,CAAAwF,MAAC,UAAO,EAAG,EAAG,KAAM1D,EAAc,QAAS,GAAK,EAChD0D,EAAAA,IAAC,OAAA,CACC,EAAG,GACH,WAAW,SACX,SAAU,IACV,KAAM1D,EACN,WAAW,0BACX,WAAW,MACX,QAAS,GAER,SAAA,KAAK,MAAM2D,EAAG,QAAkB,CAAA,CAAA,CACnC,CAAA,EAZM,QAAQA,EAAG,GAAG,EAatB,CACD,EAGAT,GAAYN,GACXc,MAAC,OAAA,CAAK,EAAGd,EAAmB,KAAK,OAAO,OAAQ9C,EAAc,YAAa,IAAM,gBAAgB,MAAM,cAAc,QAAQ,QAAS,IAAM,MAAO,CAAE,WAAY,KAAK5B,CAAI,EAAA,CAAG,CAAG,EAIjLyE,SACE,OAAA,CAAK,EAAGA,EAAkB,KAAK,OAAO,OAAQ9C,EAAc,YAAa,IAAM,gBAAgB,MAAM,cAAc,QAAQ,QAAS,GAAK,MAAO,CAAE,WAAY,KAAK3B,CAAI,EAAA,CAAG,CAAG,EAI/KwE,SACE,OAAA,CAAK,EAAGA,EAAkB,KAAK,OAAO,OAAQ3C,EAAgB,YAAa,GAAK,eAAe,QAAQ,cAAc,QAAQ,QAAS,IAAM,MAAO,CAAE,WAAY,KAAK7B,CAAI,EAAA,CAAG,CAAG,EAOlLqE,EAAU,IAAI,CAACqB,EAAInF,IAAM,CACxB,GAAImF,EAAG,SAAW,GAAKA,EAAG,QAAU,EAAG,OAAO,KAC9C,MAAMC,EAAK,KAAK,IAAI,IAAK,KAAK,IAAI,EAAG,IAAMD,EAAG,OAAS,EAAE,CAAC,EACpDE,EAAaF,EAAG,QAAUA,EAAG,OAG7BG,EAAgB,KAAK,IAAIvB,EAAW/D,CAAC,EAAE,EAAI,EAAGmF,EAAG,EAAIC,EAAK,CAAC,EACjE,cACG,IAAA,CACE,SAAA,CAAAD,EAAG,QAAU,GACZF,EAAAA,IAAC,OAAA,CACC,EAAGE,EAAG,EACN,EAAGG,EACH,WAAW,SACX,SAAU,IACV,KAAMD,EAAahE,EAAe,UAClC,WAAW,0BACX,WAAW,MACX,MAAO,CAAE,WAAY,KAAK5B,CAAI,EAAA,EAE7B,SAAA0F,EAAG,OAAA,CAAA,SAGP,IAAA,CAAE,UAAW,aAAaA,EAAG,CAAC,IAAIA,EAAG,CAAC,IAAK,MAAO,CAAE,WAAY,aAAa1F,CAAI,IAChF,SAAA,CAAAwF,MAAC,UAAO,EAAGG,EAAI,KAAMhE,EAAc,QAAS,IAAM,EACjD+D,EAAG,OAAS,SACV,OAAA,CAAK,EAAGC,EAAK,EAAG,WAAW,SAAS,SAAU,IAAK,KAAMhE,EAAc,WAAW,0BAA0B,WAAW,MACrH,WAAG,MAAA,CACN,CAAA,CAAA,CAEJ,CAAA,CAAA,EAtBM,UAAU+D,EAAG,GAAG,EAuBxB,CAEJ,CAAC,EAKAlC,EAAK,IAAKsC,GAAQ,QACjB,MAAMC,EAAIlD,EAASiD,EAAI,GAAG,EACpBE,EAAIF,EAAI,EACRG,EAAKH,EAAI,UAAY,KAAO9B,EAAO8B,EAAI,MAAM,EAAIhG,EAEjDV,EAAI,KAAK,IAAI,KAAM,KAAK,IAAI,EAAG,KAAO0G,EAAI,OAAS,GAAG,CAAC,EACvDI,EAAaH,EAAE,OAASjD,EACxBqD,EAAYhD,IAAe2C,EAAI,IAE/BM,EACJN,EAAI,UAAY,KACZ,wCACA,GAAGA,EAAI,MAAM,sBAAsB,KAAK,MAAMA,EAAI,QAAQ,CAAC,IACxDA,EAAI,QAAUA,EAAI,OAAS,MAAMA,EAAI,QAAUA,EAAI,MAAM,WAAa,KACtEA,EAAI,OAAS,EAAI,MAAMA,EAAI,MAAM,WAAa,KAC9CA,EAAI,cAAgB,EAAI,MAAMA,EAAI,aAAa,YAAc,IAChEO,GAAOD,EAAQ,OAAS,IAAM,GAC9BE,GAAO,KAAK,IAAI9G,EAAK6G,GAAO,EAAI,EAAG,KAAK,IAAItG,GAAQsG,GAAO,EAAI,EAAGL,CAAC,CAAC,EACpEO,GAAON,EAAK7G,EAAI,GAEtB,OACEoH,EAAAA,KAAC,IAAA,CAEC,QAAS,IAAMzD,EAASgD,EAAE,IAAI,EAC9B,aAAc,IAAM3C,EAAc0C,EAAI,GAAG,EACzC,aAAc,IAAM1C,EAAc,IAAI,EACtC,MAAO,CAAE,OAAQ,SAAA,EAGjB,SAAA,CAAAoD,EAAAA,KAAC,IAAA,CAAE,UAAW,aAAaR,CAAC,IAAIC,CAAE,IAAK,MAAO,CAAE,WAAY,aAAajG,CAAI,IAC3E,SAAA,CAAAwF,EAAAA,IAAC,SAAA,CAAO,EAAG,GAAI,KAAK,cAAc,EAClCA,EAAAA,IAAC,SAAA,CAAO,EAAApG,EAAM,KAAMyC,EAAgB,QAAS,GAAK,MAAO,CAAE,WAAY,KAAK7B,CAAI,GAAG,CAAG,EACrF8F,EAAI,UAAY,MACfN,EAAAA,IAAC,QAAK,EAAG,CAACpG,EAAI,EAAG,WAAW,SAAS,SAAU,IAAK,KAAMyC,EAAgB,WAAW,0BAA0B,WAAW,MACvH,SAAAN,GAAQuE,EAAI,MAAM,CAAA,CACrB,EAEDK,GAAa,CAACD,GAAcV,EAAAA,IAAC,UAAO,EAAGpG,EAAI,EAAG,KAAK,OAAO,OAAQyC,EAAgB,YAAa,EAAG,QAAS,GAAK,EAChHqE,GAAcV,EAAAA,IAAC,SAAA,CAAO,EAAGpG,EAAI,EAAG,KAAK,OAAO,OAAO,UAAU,YAAa,CAAA,CAAG,CAAA,EAChF,EAMC0G,EAAI,cAAgB,GACnBU,EAAAA,KAAC,IAAA,CACC,UAAW,aAAaR,EAAI,EAAE,IAAI,KAAK,IAAIC,EAAK,GAAI,EAAE,CAAC,IACvD,QAAUQ,IAAM,CACdA,GAAE,gBAAA,EACFxD,GAAA,MAAAA,EAAmB8C,EAAE,KACvB,EACA,MAAO,CAAE,OAAQ,UAAW,WAAY,aAAa/F,CAAI,EAAA,EAEzD,SAAA,CAAAwF,MAAC,QAAA,CAAO,SAAA,GAAGM,EAAI,aAAa,4DAA4D,EACxFN,EAAAA,IAAC,SAAA,CACC,EAAG,KAAO,OAAOM,EAAI,aAAa,EAAE,OAAS,GAAK,EAClD,KAAM/D,GACN,QAAS,EAAA,CAAA,EAEXyD,EAAAA,IAAC,OAAA,CACC,EAAG,IACH,WAAW,SACX,SAAU,EACV,KAAMxD,EACN,WAAW,0BACX,WAAW,MAEV,SAAA8D,EAAI,aAAA,CAAA,CACP,CAAA,CAAA,KAQFzG,GAAA0G,EAAE,iBAAF,YAAA1G,GAAkB,SAAU,GAAK,GACjCmH,EAAAA,KAAC,IAAA,CACC,UAAW,aAAaR,EAAI,EAAE,IAAIlG,CAAM,IACxC,QAAU2G,IAAM,CACdA,GAAE,gBAAA,EACFzD,GAAA,MAAAA,EAAmB+C,EAAE,eAAgB,CAAC,EACxC,EACA,MAAO,CAAE,OAAQ,SAAA,EAEjB,SAAA,CAAAP,EAAAA,IAAC,SAAO,SAAA,UAAUO,EAAE,eAAgB,KAAK,IAAI,CAAC,gCAAA,CAAiC,QAC9E,SAAA,CAAO,EAAG,EAAG,GAAI,GAAI,KAAK,cAAc,EACzCP,EAAAA,IAAC,OAAA,CAAK,EAAE,+BAA+B,KAAK,OAAO,OAAO,UAAU,YAAa,EAAG,gBAAgB,MAAM,cAAc,QAAQ,EAChIA,EAAAA,IAAC,QAAK,EAAE,gBAAgB,OAAO,UAAU,YAAa,EAAG,cAAc,OAAA,CAAQ,EAC/EA,EAAAA,IAAC,OAAA,CAAK,EAAE,yBAAyB,KAAK,SAAA,CAAU,CAAA,CAAA,CAAA,EAQpDA,EAAAA,IAAC,OAAA,CACC,EAAAQ,EACA,EAAGlG,GAAUgG,EAAI,IAAM,IAAM,EAAI,GAAK,IACtC,WAAW,SACX,SAAU,IACV,KAAK,UACL,WAAW,4BACX,WAAW,MAEV,YAAiBC,CAAC,CAAA,CAAA,EAIpBI,UACE,IAAA,CACC,SAAA,CAAAX,MAAC,QAAK,EAAGc,GAAOD,GAAO,EAAG,EAAGE,GAAO,GAAI,MAAOF,GAAM,OAAQ,GAAI,GAAI,EAAG,KAAK,UAAU,QAAS,IAAM,EACtGb,EAAAA,IAAC,OAAA,CAAK,EAAGc,GAAM,EAAGC,GAAO,EAAG,WAAW,SAAS,SAAU,IAAK,KAAK,QAAQ,WAAW,0BACpF,SAAAH,CAAA,CACH,CAAA,CAAA,CACF,CAAA,CAAA,EA/FGL,EAAE,IAAA,CAmGb,CAAC,EAGA,CAACjC,GACA0B,MAAC,QAAK,EAAGhG,EAAKI,GAAS,EAAG,EAAGE,EAAS,GAAI,WAAW,SAAS,SAAU,IAAK,KAAK,UAAU,WAAW,4BAA4B,SAAA,6EAEnI,EAIDuF,EAAU,IAAK5C,GACd+C,EAAAA,IAAC,OAAA,CAEC,EAAGzF,GAAQ,EACX,EAAG0C,EAAE,OACL,SAAU,EACV,KAAMA,EAAE,MACR,WAAW,4BACX,WAAYA,EAAE,MAAQ,SAAW,IAAM,IACvC,QAASA,EAAE,MAAQ,SAAW,IAAO,EACrC,MAAO,CAAE,WAAY,KAAKzC,CAAI,EAAA,EAE7B,SAAAyC,EAAE,IAAA,EAVEA,EAAE,GAAA,CAYV,CAAA,EACH,CAEJ,CCtdO,SAASiE,GAAkBzH,EAA2D,CAC3F,MAAM0H,EAAO,+BAA+B,mBAAmB1H,EAAK,IAAI,CAAC,GACzE,GAAIA,EAAK,eAAgB,CACvB,MAAM2H,EAAU,KAAK,UAAU,CAAC,CAAE,MAAO,YAAY3H,EAAK,cAAc,GAAI,UAAW,KAAA,CAAO,CAAC,EAC/F,MAAO,GAAG0H,CAAI,YAAY,mBAAmBC,CAAO,CAAC,EACvD,CACA,MAAO,GAAGD,CAAI,+BAChB,CCKA,MAAME,GAAU,CAAC,MAAO,KAAM,MAAO,KAAM,KAAK,EAG1CC,GAAY3G,GAA4B0G,GAA8B,SAAS1G,CAAC,EAEtF,SAAS4G,GAAIC,EAA4B,CACvC,GAAIA,GAAO,KAAM,MAAO,IACxB,GAAIA,EAAM,EAAG,CACX,MAAMjB,EAAI,KAAK,MAAMiB,EAAM,EAAE,EAC7B,OAAOjB,GAAK,EAAI,OAAS,GAAGA,CAAC,GAC/B,CACA,OAAIiB,EAAM,GAAW,GAAGA,EAAI,QAAQ,CAAC,CAAC,IAC/B,IAAIA,EAAM,IAAI,QAAQ,CAAC,CAAC,GACjC,CAEA,SAASC,GAAU,CAAE,MAAAC,EAAO,MAAAC,GAA2C,CACrE,OACEX,EAAAA,KAAC,MAAA,CAAI,UAAU,yCACb,SAAA,CAAAhB,EAAAA,IAAC,OAAA,CAAK,UAAU,0DAA2D,SAAA0B,EAAM,EACjF1B,EAAAA,IAAC,OAAA,CAAK,UAAU,+DAAgE,SAAA2B,CAAA,CAAM,CAAA,EACxF,CAEJ,CAEA,SAASC,GAAe,CAAE,OAAAC,EAAQ,SAAAC,GAA+D,CAC/F,aACG,MAAA,CAAI,UAAU,+BACZ,SAAAT,GAAQ,IAAK1G,GACZqF,EAAAA,IAAC,SAAA,CAEC,QAAS,IAAM8B,EAASnH,CAAC,EACzB,UAAW,+DACTkH,IAAWlH,EACP,yCACA,gDACN,GAEC,SAAAA,CAAA,EARIA,CAAA,CAUR,EACH,CAEJ,CAEA,SAASoH,GAAS,CAAE,KAAAtI,EAAM,aAAAuI,EAAc,QAAAC,GAA4E,CAGlH,KAAM,CAACJ,EAAQK,CAAS,EAAIrE,EAAAA,SAAiByD,GAASU,CAAY,EAAIA,EAAe,KAAK,EACpF,CAAE,KAAAG,CAAA,EAASC,GAAkBP,CAAM,EACnCQ,EAASF,GAAA,YAAAA,EAAM,SAAS,KAAM5B,GAAMA,EAAE,OAAS9G,EAAK,MACpD6I,EAAa7I,EAAK,aAAe,OACjC8I,EAAgB9I,EAAK,iBAAmB,OACxC+I,EAAc/I,EAAK,cAAgB,OAEzC,OACEuH,EAAAA,KAAAyB,WAAA,CAEE,SAAA,CAAAzB,EAAAA,KAAC,MAAA,CAAI,UAAU,wCACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,iBACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,wCACb,SAAA,CAAAhB,MAAC,OAAA,CAAK,UAAU,sCAAuC,SAAArG,GAAiBF,CAAI,EAAE,EAC9EuG,EAAAA,IAAC,OAAA,CAAK,UAAU,4CAA6C,WAAK,IAAA,CAAK,CAAA,EACzE,EACCvG,EAAK,aACJuG,EAAAA,IAAC,KAAE,UAAU,qEACV,WAAK,WAAA,CACR,CAAA,EAEJ,EACAA,EAAAA,IAAC,SAAA,CACC,QAASiC,EACT,UAAU,wFAEV,SAAAjC,EAAAA,IAAC0C,GAAA,CAAE,UAAU,SAAA,CAAU,CAAA,CAAA,CACzB,EACF,EAEA1B,EAAAA,KAAC2B,EAAA,CACC,GAAI,gBAAgB,mBAAmBlJ,EAAK,IAAI,CAAC,GACjD,UAAU,uEAEV,SAAA,CAAAuG,EAAAA,IAAC4C,GAAA,CAAa,UAAU,aAAA,CAAc,EAAE,eAAA,CAAA,CAAA,EAI1C5C,EAAAA,IAAC4B,GAAA,CAAe,OAAAC,EAAgB,SAAUK,CAAA,CAAW,GAGnDK,GAAiBD,GAAcE,IAC/BxB,EAAAA,KAAC,MAAA,CAAI,UAAU,2CACZ,SAAA,CAAAuB,UACE,MAAA,CACC,SAAA,CAAAvB,EAAAA,KAAC,MAAA,CAAI,UAAU,4CAA6C,SAAA,CAAAuB,EAAc,IAAA,EAAE,EAC5EvC,EAAAA,IAAC,MAAA,CAAI,UAAU,6DAA6D,SAAA,QAAA,CAAM,CAAA,EACpF,EAEDsC,UACE,MAAA,CACC,SAAA,CAAAtB,EAAAA,KAAC,MAAA,CAAI,UAAU,4CAA6C,SAAA,CAAAsB,EAAW,GAAA,EAAC,EACxEtC,EAAAA,IAAC,MAAA,CAAI,UAAU,6DAA6D,SAAA,KAAA,CAAG,CAAA,EACjF,EAEDwC,UACE,MAAA,CACC,SAAA,CAAAxC,EAAAA,IAAC,MAAA,CAAI,UAAU,4CAA6C,SAAAwC,EAAY,EACxExC,EAAAA,IAAC,MAAA,CAAI,UAAU,6DAA6D,SAAA,SAAA,CAAO,CAAA,CAAA,CACrF,CAAA,EAEJ,EAIFgB,EAAAA,KAAC,MAAA,CAAI,UAAU,2BACb,SAAA,CAAAA,OAAC,MAAA,CACC,SAAA,CAAAhB,EAAAA,IAAC,IAAA,CAAE,UAAU,kEAAkE,SAAA,eAAY,EAC3FA,EAAAA,IAACyB,GAAA,CAAU,MAAM,MAAM,MAAOF,IAAIc,GAAA,YAAAA,EAAQ,KAAK,MAAO,IAAI,CAAA,CAAG,EAC7DrC,EAAAA,IAACyB,GAAA,CAAU,MAAM,MAAM,MAAOF,IAAIc,GAAA,YAAAA,EAAQ,KAAK,MAAO,IAAI,CAAA,CAAG,CAAA,EAC/D,SACC,MAAA,CACC,SAAA,CAAArC,EAAAA,IAAC,IAAA,CAAE,UAAU,kEAAkE,SAAA,eAAY,EAC3FA,EAAAA,IAACyB,GAAA,CAAU,MAAM,MAAM,MAAOF,IAAIc,GAAA,YAAAA,EAAQ,KAAK,MAAO,IAAI,CAAA,CAAG,EAC7DrC,EAAAA,IAACyB,GAAA,CAAU,MAAM,MAAM,MAAOF,IAAIc,GAAA,YAAAA,EAAQ,KAAK,MAAO,IAAI,CAAA,CAAG,CAAA,CAAA,CAC/D,CAAA,EACF,EAGArB,EAAAA,KAAC,MAAA,CAAI,UAAU,0DACZ,SAAA,CAAAsB,GACCtB,EAAAA,KAAC,MAAA,CAAI,UAAU,oCACb,SAAA,CAAAhB,EAAAA,IAAC,OAAA,CAAK,UAAU,iCAAiC,SAAA,aAAU,EAC3DgB,EAAAA,KAAC,OAAA,CAAK,UAAU,wCAAyC,SAAA,CAAAsB,EAAW,GAAA,CAAA,CAAC,CAAA,EACvE,EAEDD,GAAUA,EAAO,eAAiB,GACjCrB,EAAAA,KAAC2B,EAAA,CACC,GAAIzB,GAAkBzH,CAAI,EAC1B,UAAU,0CAEV,SAAA,CAAAuH,OAAC,QAAK,UAAU,cAAc,MAAO,CAAE,MAAOxE,GAC3C,SAAA,CAAA6F,EAAO,eAAe,+BAAA,EACzB,EACArC,MAAC4C,IAAa,UAAU,4BAA4B,MAAO,CAAE,MAAOpG,EAAoB,CAAG,CAAA,CAAA,CAAA,CAC7F,EAEJ,EAKAwD,EAAAA,IAAC,MAAA,CAAI,UAAU,8CACb,SAAAgB,EAAAA,KAAC2B,EAAA,CACC,GAAI,+BAA+B,mBAAmBlJ,EAAK,IAAI,CAAC,GAChE,UAAU,oEACX,SAAA,CAAA,kBAECuG,EAAAA,IAAC4C,GAAA,CAAa,UAAU,aAAA,CAAc,CAAA,CAAA,CAAA,CACxC,CACF,CAAA,EACF,CAEJ,CAEA,SAASC,GAAc,CACrB,WAAAC,EACA,aAAAC,EACA,OAAAlB,CACF,EAIG,CACD,MAAMmB,EAAgBF,EAAW,OAAO,CAACvC,EAAG0C,IAAM1C,EAAI0C,EAAE,QAAgB,CAAC,EACnEC,EAAgBJ,EAAW,OAAO,CAACvC,EAAG0C,IAAM1C,EAAI0C,EAAE,SAAgB,CAAC,EACnEE,EAAgBL,EAAW,OAAO,CAACvC,EAAG0C,IAAM1C,EAAI0C,EAAE,eAAgB,CAAC,EAEnEG,EAAkB,IAAI,IAAIN,EAAW,IAAKG,GAAM,CAACA,EAAE,KAAMA,CAAC,CAAC,CAAC,EAC5DI,EAAkBP,EAAW,OAAQG,GAAMA,EAAE,eAAiB,CAAC,EAAE,OACjEK,EAAmBR,EAAW,OAAQG,GAAMA,EAAE,QAAU,CAAC,EAAE,OAEjE,OACEjC,EAAAA,KAAAyB,WAAA,CACE,SAAA,CAAAzB,EAAAA,KAAC,IAAA,CAAE,UAAU,gEAAgE,SAAA,CAAA,cAC/Da,CAAA,EACd,EAGA7B,EAAAA,IAAC,MAAA,CAAI,UAAU,OACZ,WAAiB,EAChBgB,EAAAA,KAAC,IAAA,CAAE,UAAU,cAAc,MAAO,CAAE,MAAOxE,GACxC,SAAA,CAAA6G,EAAe,WAASA,EAAiB,EAAI,IAAM,GAAG,sBAAA,EACzD,EACEC,EAAmB,EACrBtC,EAAAA,KAAC,IAAA,CAAE,UAAU,kCACV,SAAA,CAAAsC,EAAiB,WAASA,EAAmB,EAAI,IAAM,GAAG,eAAA,EAC7D,EACEJ,EAAgB,EAClBlD,EAAAA,IAAC,KAAE,UAAU,kCAAkC,SAAA,uBAAA,CAAqB,EAEpEA,EAAAA,IAAC,IAAA,CAAE,UAAU,mCAAmC,iCAAqB,EAEzE,EAGAgB,EAAAA,KAAC,MAAA,CAAI,UAAU,mBACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,oCACb,SAAA,CAAAhB,EAAAA,IAAC,OAAA,CAAK,UAAU,2DAA2D,SAAA,UAAO,EAClFA,EAAAA,IAAC,QAAK,UAAW,kCAAkCgD,EAAe,EAAI,kCAAoC,sBAAsB,GAC7H,SAAAA,CAAA,CACH,CAAA,EACF,EACAhC,EAAAA,KAAC,MAAA,CAAI,UAAU,oCACb,SAAA,CAAAA,EAAAA,KAAC,OAAA,CAAK,UAAU,2DAA2D,SAAA,CAAA,cAAYa,CAAA,EAAO,EAC9F7B,EAAAA,IAAC,OAAA,CAAK,UAAU,qDAAsD,SAAAkD,CAAA,CAAc,CAAA,EACtF,EACCC,EAAgB,GACfnC,OAAC,MAAA,CAAI,UAAU,oCACb,SAAA,CAAAhB,EAAAA,IAAC,OAAA,CAAK,UAAU,2DAA2D,SAAA,WAAQ,EACnFA,EAAAA,IAAC,QAAK,UAAU,+CAA+C,MAAO,CAAE,MAAOxD,CAAA,EAC5E,SAAA2G,CAAA,CACH,CAAA,CAAA,CACF,CAAA,EAEJ,QAGC,MAAA,CAAI,UAAU,8CACb,SAAAnC,EAAAA,KAAC,MAAA,CAAI,UAAU,0BACb,SAAA,CAAAhB,EAAAA,IAAC,OAAA,CAAK,UAAU,kEAAkE,SAAA,UAAO,EACzFA,EAAAA,IAAC,OAAA,CAAK,UAAU,mFAAmF,SAAA,OAAI,EACvGA,EAAAA,IAAC,OAAA,CAAK,UAAU,mFAAmF,SAAA,OAAI,EACvGA,EAAAA,IAAC,OAAA,CAAK,UAAU,mFAAmF,SAAA,KAAA,CAAG,CAAA,CAAA,CACxG,CAAA,CACF,QAGC,MAAA,CAAI,UAAU,cACZ,SAAA+C,EAAa,IAAKnJ,GAAM,CACvB,MAAMqJ,EAAgBG,EAAa,IAAIxJ,EAAE,IAAI,EACvC2J,GAAgBN,GAAA,YAAAA,EAAG,UAAkB,EACrCO,GAAgBP,GAAA,YAAAA,EAAG,UAAkB,EACrCQ,GAAgBR,GAAA,YAAAA,EAAG,WAAkB,EACrCS,GAAgBT,GAAA,YAAAA,EAAG,iBAAkB,EACrCvB,EAAgB9H,EAAE,OAASA,EAAE,KAC7B+J,EAAgBD,EAAgB,EAChCE,EAAgBL,EAAU,EAEhC,OACEvC,EAAAA,KAAC,MAAA,CAAiB,UAAU,iCAC1B,SAAA,CAAAA,EAAAA,KAAC,OAAA,CACC,UAAW,yCACT4C,EAAU,oBAAsB,sBAClC,GAEC,SAAA,CAAAlC,EACAiC,UACE,OAAA,CAAK,UAAU,gCAAgC,MAAO,CAAE,MAAOnH,CAAA,EAC7D,SAAA,CAAAkH,EAAc,WAAA,CAAA,CACjB,CAAA,CAAA,CAAA,EAGJ1D,EAAAA,IAAC,OAAA,CACC,UAAW,8DACT4D,EAAU,kCAAoC,sBAChD,GAEC,SAAAL,EAAU,EAAIA,EAAU,GAAA,CAAA,EAE3BvD,EAAAA,IAAC,OAAA,CAAK,UAAW,8DAA8DwD,EAAU,EAAI,cAAgB,sBAAsB,GAChI,SAAAA,EAAU,EAAIA,EAAU,IAC3B,EACAxD,EAAAA,IAAC,OAAA,CAAK,UAAW,8DAA8DyD,EAAW,EAAI,sBAAwB,sBAAsB,GACzI,SAAAA,EAAW,EAAIA,EAAW,GAAA,CAC7B,CAAA,CAAA,EAzBQ7J,EAAE,IA0BZ,CAEJ,CAAC,CAAA,CACH,EAEAoG,EAAAA,IAAC,IAAA,CAAE,UAAU,uCAAuC,SAAA,oCAAA,CAEpD,CAAA,EACF,CAEJ,CAEO,SAAS6D,GAAmB,CACjC,KAAApK,EACA,WAAAqJ,EACA,aAAAC,EACA,aAAAf,EACA,QAAAC,CACF,EAA4B,CAC1B,aACG,MAAA,CAAI,UAAU,qEACZ,SAAAxI,QACEsI,GAAA,CAAS,KAAAtI,EAAY,aAAAuI,EAA4B,QAAAC,CAAA,CAAkB,EAEpEjC,EAAAA,IAAC6C,GAAA,CAAc,WAAAC,EAAwB,aAAAC,EAA4B,OAAQf,EAAc,EAE7F,CAEJ,CCxSA,MAAM8B,GAAc,GAAGxH,CAAY,KAC7ByH,GAAe,GAAG3H,CAAY,KAC9B4H,GAAc,GAAG7H,CAAY,KAC7B8H,GAAgB,GAAG5H,CAAc,KAIjC6H,GAAoB,gFAIpB7C,GAAU,CAAC,MAAO,KAAM,MAAO,KAAM,KAAK,EAK1C8C,GAAuC,CAC3C,MAAO,IACP,KAAM,EACN,MAAO,GACP,KAAM,IACN,MAAO,GACT,EAoBO,SAASC,GAAeC,EAAyC,CACtE,MAAMC,EAAWD,EAAM,OAAQzK,GAAMA,EAAE,WAAW,EAC5C2K,EAAU,IAAI,IAAID,EAAS,IAAK1K,GAAM,CAACA,EAAE,KAAMA,CAAC,CAAC,CAAC,EAClD4K,MAAc,IAKdC,EAFQH,EAAS,OAAQ1K,GAAM,CAACA,EAAE,aAAe,CAAC2K,EAAQ,IAAI3K,EAAE,WAAW,CAAC,EAEtC,IAAK8K,GAAS,CACxD,MAAMrH,EAA6B,CAAA,EAC7BsH,EAA0B,CAAC,CAAE,KAAMD,EAAM,MAAO,EAAG,EACzD,KAAOC,EAAM,OAAS,GAAG,CACvB,MAAMC,EAAOD,EAAM,MAAA,EACfH,EAAQ,IAAII,EAAK,KAAK,IAAI,IAC9BJ,EAAQ,IAAII,EAAK,KAAK,IAAI,EAC1BvH,EAAS,KAAKuH,CAAI,EAClBN,EACG,OAAQO,GAAMA,EAAE,cAAgBD,EAAK,KAAK,MAAQ,CAACJ,EAAQ,IAAIK,EAAE,IAAI,CAAC,EACtE,QAASA,GAAMF,EAAM,KAAK,CAAE,KAAME,EAAG,MAAOD,EAAK,MAAQ,CAAA,CAAG,CAAC,EAClE,CACA,MAAO,CAAE,OAAQF,EAAM,SAAArH,CAAA,CACzB,CAAC,EAGD,OAAAiH,EACG,OAAQ1K,GAAM,CAAC4K,EAAQ,IAAI5K,EAAE,IAAI,CAAC,EAClC,QAASA,GAAM6K,EAAU,KAAK,CAAE,OAAQ7K,EAAG,SAAU,CAAC,CAAE,KAAMA,EAAG,MAAO,CAAA,CAAG,CAAA,CAAG,CAAC,EAG3E6K,EAAU,KACf,CAAC,EAAG3H,IAAMA,EAAE,SAAS,OAAS,EAAE,SAAS,QAAU,EAAE,OAAO,KAAK,cAAcA,EAAE,OAAO,IAAI,CAAA,CAEhG,CAIA,SAASgI,GAAOrG,EAA0B,CACxC,GAAIA,GAAK,KAAM,MAAO,IACtB,GAAIA,EAAI,EAAG,CACT,MAAM8B,EAAI,KAAK,MAAM9B,EAAI,EAAE,EAC3B,OAAO8B,GAAK,EAAI,OAAS,GAAGA,CAAC,GAC/B,CACA,OAAI9B,EAAI,GAAW,GAAGA,EAAE,QAAQ,CAAC,CAAC,IAC3B,IAAIA,EAAI,IAAI,QAAQ,CAAC,CAAC,GAC/B,CAEA,SAASsG,GAAQxB,EAAiBtF,EAAuB,CAGvD,GAAI,CAACA,GAAUsF,IAAY,QAAU,CAAE,IAAK,KAAM,MAAO,mBAAA,EAEzD,MAAMyB,EAAQzB,EAAUtF,EAClBgH,EAAM,KAAK,MAAMD,EAAQ,GAAG,EAE5BE,EAAQF,EAAQ,EAAM,oBAAsBA,EAAQ,GAAM,kBAAoB,oBACpF,MAAO,CAAE,IAAAC,EAAK,MAAAC,CAAA,CAChB,CAIA,SAASC,GAAW,CAClB,KAAA1L,EACA,OAAA4I,EACA,SAAA+C,EACA,QAAAC,CACF,EAKG,OACD,MAAM9B,GAAUlB,GAAA,YAAAA,EAAQ,UAAW,EAC7BmB,GAAUnB,GAAA,YAAAA,EAAQ,UAAW,EAC7BoB,GAAWpB,GAAA,YAAAA,EAAQ,WAAY,EAC/BqB,GAAgBrB,GAAA,YAAAA,EAAQ,iBAAkB,EAC1CpE,EAASxE,EAAK,iBAAmB,KACjC,CAAE,IAAAwL,EAAK,MAAAC,CAAA,EAAUH,GAAQxB,EAAStF,CAAM,EACxCqH,EAAWL,GAAO,KAAO,KAAK,IAAI,IAAKA,CAAG,EAAI,EAEpD,OACEjE,EAAAA,KAAAyB,WAAA,CACE,SAAA,CAAAzB,EAAAA,KAAC,MAAA,CACC,KAAK,SACL,SAAU,EACV,QAAAqE,EACA,UAAYpE,GAAM,CAAMA,EAAE,MAAQ,SAASoE,EAAA,CAAW,EACtD,UAAW,iEACTD,EAAW,qCAAuC,MACpD,GACA,MAAO,CAAE,oBAAqBlB,EAAA,EAG9B,SAAA,CAAAlD,EAAAA,KAAC,MAAA,CAAI,UAAU,2CACb,SAAA,CAAAhB,MAAC,OAAA,CAAK,UAAU,+CACb,SAAArG,GAAiBF,CAAI,EACxB,KACEI,EAAAJ,EAAK,iBAAL,YAAAI,EAAqB,SAAU,GAAK,GACpCmG,MAAC,OAAA,CAAK,MAAO,UAAUvG,EAAK,eAAe,KAAK,IAAI,CAAC,GAAI,UAAU,wBACjE,SAAAuG,EAAAA,IAACuF,GAAA,CAAS,UAAU,8BAAA,CAA+B,CAAA,CACrD,CAAA,EAEJ,EAGAvF,EAAAA,IAAC,OAAA,CAAK,UAAU,2DACb,WAAK,KACR,EAGAA,EAAAA,IAAC,MAAA,CACC,UAAU,oDACV,MAAO,CAAE,gBAAiB8D,EAAA,EAE1B,SAAA9D,EAAAA,IAAC,OAAA,CACC,UAAW,kCACT/B,GAAU,KAAO,sBAAwB,sBAC3C,GAEC,SAAAA,GAA0B,GAAA,CAAA,CAC7B,CAAA,EAIF+B,EAAAA,IAAC,MAAA,CACC,UAAU,oDACV,MAAO,CAAE,gBAAiB+D,EAAA,EAE1B,SAAA/D,EAAAA,IAAC,OAAA,CACC,UAAW,kCACTuD,EAAU,EAAI,kCAAoC,sBACpD,GAEC,SAAAA,CAAA,CAAA,CACH,CAAA,EAIFvD,EAAAA,IAAC,MAAA,CACC,UAAU,oDACV,MAAO,CAAE,gBAAiBgE,EAAA,EAE1B,SAAAhE,EAAAA,IAAC,OAAA,CACC,UAAW,kCACTwD,EAAU,EAAI,4BAA8B,sBAC9C,GAEC,SAAAA,CAAA,CAAA,CACH,CAAA,EAIFxD,EAAAA,IAAC,MAAA,CACC,UAAU,oDACV,MAAO,CAAE,gBAAiBiE,EAAA,EAE1B,SAAAjE,EAAAA,IAAC,OAAA,CAAK,UAAU,sDACb,SAAAyD,CAAA,CACH,CAAA,CAAA,EAIFzD,EAAAA,IAAC,QAAK,UAAU,uEACb,aAAOqC,GAAA,YAAAA,EAAQ,KAAK,MAAO,IAAI,CAAA,CAClC,EAGArC,EAAAA,IAAC,QAAK,UAAU,uEACb,aAAOqC,GAAA,YAAAA,EAAQ,KAAK,MAAO,IAAI,CAAA,CAClC,EAGArB,EAAAA,KAAC,MAAA,CAAI,UAAU,iCACb,SAAA,CAAAhB,MAAC,OAAI,UAAU,qEACb,SAAAA,MAAC,MAAA,CAAI,UAAW,uBAAuBkF,CAAK,GAAI,MAAO,CAAE,MAAO,GAAGI,CAAQ,KAAO,EACpF,EACAtF,EAAAA,IAAC,OAAA,CACC,UAAW,sCACTiF,GAAO,MAAQA,EAAM,IACjB,oCACA,sBACN,GAEC,SAAAA,GAAO,KAAO,GAAGA,CAAG,IAAM,GAAA,CAAA,CAC7B,CAAA,CACF,CAAA,CAAA,CAAA,EAIDvB,EAAgB,GACf1C,OAAC,MAAA,CAAI,UAAU,wCACb,SAAA,CAAAhB,EAAAA,IAAC,OAAA,CACC,UAAU,6CACV,MAAO,CAAE,gBAAiBzD,EAAA,CAAe,CAAA,EAE3CyE,EAAAA,KAAC2B,EAAA,CACC,GAAIzB,GAAkBzH,CAAI,EAC1B,UAAU,8BACV,MAAO,CAAE,MAAO+C,CAAA,EAChB,QAAUyE,GAAMA,EAAE,gBAAA,EAEjB,SAAA,CAAAyC,EAAc,iCAAA,CAAA,CAAA,CACjB,CAAA,CACF,CAAA,EAEJ,CAEJ,CAIA,SAAS8B,IAAY,CAEnB,MAAMC,EAAyD,CAC7D,CAAE,MAAO,MAAA,EACT,CAAE,MAAO,MAAA,EACT,CAAE,MAAO,WAAY,KAAM3B,GAAa,IAAKxH,CAAA,EAC7C,CAAE,MAAO,UAAW,KAAMyH,GAAc,IAAK3H,CAAA,EAC7C,CAAE,MAAO,UAAW,KAAM4H,GAAa,IAAK7H,CAAA,EAC5C,CAAE,MAAO,WAAY,KAAM8H,GAAe,IAAK5H,CAAA,EAC/C,CAAE,MAAO,UAAA,EACT,CAAE,MAAO,UAAA,EACT,CAAE,MAAO,OAAA,CAAQ,EAEnB,OACE2D,EAAAA,IAAC,MAAA,CACC,UAAU,qEACV,MAAO,CAAE,oBAAqBkE,EAAA,EAE7B,SAAAuB,EAAK,IAAI,CAACC,EAAK3K,IACd2K,EAAI,KACF1F,EAAAA,IAAC,MAAA,CAEC,UAAU,oDACV,MAAO,CAAE,gBAAiB0F,EAAI,IAAA,EAE9B,SAAA1F,EAAAA,IAAC,OAAA,CACC,UAAU,oDACV,MAAO,CAAE,MAAO0F,EAAI,GAAA,EAEnB,SAAAA,EAAI,KAAA,CAAA,CACP,EATKA,EAAI,KAAA,EAYX1F,EAAAA,IAAC,OAAA,CAEC,UAAW,iFACTjF,EAAI,GAAKA,EAAI,EAAI,aAAe,EAClC,GAEC,SAAA2K,EAAI,KAAA,EALAA,EAAI,KAAA,CAMX,CAEJ,CAAA,CAGN,CAKO,SAASC,IAAiB,OAG/B,KAAM,CAAC9D,EAAQK,CAAS,EAAIrE,EAAAA,SAAiB,IAAI,EAC3C,CAACP,EAAcsI,CAAe,EAAI/H,EAAAA,SAAwB,IAAI,EAC9D,CAACgI,EAAYC,CAAa,EAAIjI,EAAAA,SAAS,EAAK,EAKlDkI,GAAA,EAEA,KAAM,CAAE,KAAMC,EAAU,UAAWC,EAAc,QAASC,CAAA,EAAiBC,GAAA,EACrE,CACJ,KAAMC,EACN,UAAWC,EACX,QAASC,CAAA,EACPlE,GAAkBP,CAAM,EAEtBwC,GAAQ2B,GAAA,YAAAA,EAAU,QAAS,CAAA,EAC3BO,GAAUH,GAAA,YAAAA,EAAa,WAAY,CAAA,EAKnC3B,EAAY+B,EAAAA,QAAQ,IAA0BpC,GAAeC,CAAK,EAAG,CAACA,CAAK,CAAC,EAC5E,CAACoC,EAAcC,CAAe,EAAIC,GAAA,EAClCC,EAAgBH,EAAa,IAAI,UAAU,EAC3CI,EACJpC,EAAU,KAAMqC,GAAMA,EAAE,OAAO,OAASF,CAAa,GAAKnC,EAAU,CAAC,GAAK,KACtEsC,EAAiBC,EAAAA,YACpBC,GAAmB,CAClBrB,EAAgB,IAAI,EACpBc,EAAiB3J,GAAS,CACxB,MAAMpC,EAAI,IAAI,gBAAgBoC,CAAI,EAClC,OAAApC,EAAE,IAAI,WAAYsM,CAAM,EACjBtM,CACT,CAAC,CACH,EACA,CAAC+L,CAAe,CAAA,EAGZQ,GAAUL,GAAA,YAAAA,EAAgB,WAAY,CAAA,EACtCM,EAAkBX,EAAAA,QACtB,IAAM,IAAI,IAAIU,EAAQ,IAAI,CAAC,CAAE,KAAAzN,CAAA,IAAWA,EAAK,IAAI,CAAC,EAClD,CAACyN,CAAO,CAAA,EAEJE,EAAkBZ,EAAAA,QACtB,IAAMD,EAAQ,OAAQtD,GAAMkE,EAAgB,IAAIlE,EAAE,IAAI,CAAC,EACvD,CAACsD,EAASY,CAAe,CAAA,EAGrBE,EAAgBb,EAAAA,QACpB,IACEU,EAAQ,IAAI,CAAC,CAAE,KAAM,MAAS,CAC5B,KAAM,EAAE,KACR,MAAO,EAAE,MACT,YAAa,EAAE,YACf,gBAAiB,EAAE,iBAAmB,KACtC,eAAgB,EAAE,gBAAkB,CAAA,EACpC,OAAQX,EAAQ,KAAMtD,GAAMA,EAAE,OAAS,EAAE,IAAI,CAAA,EAC7C,EACJ,CAACiE,EAASX,CAAO,CAAA,EAIbe,EAAuBN,EAAAA,YAC1BO,GAAyB,CACxB,MAAMtJ,EAASwG,EAAU,KAAMqC,GAC7BA,EAAE,SAAS,KAAK,CAAC,CAAE,KAAArN,CAAA,IAAWA,EAAK,OAAS8N,CAAY,CAAA,EAEtDtJ,GAAQ8I,EAAe9I,EAAO,OAAO,IAAI,CAC/C,EACA,CAACwG,EAAWsC,CAAc,CAAA,EAItBS,EAAWC,GAAA,EACXC,EAAuBV,EAAAA,YAC1BW,GAAqB,CACpB,MAAMC,EAASvD,EAAM,KAAMzK,GAAMA,EAAE,OAAS+N,CAAQ,EAChDC,GAAQJ,EAAStG,GAAkB0G,CAAM,CAAC,CAChD,EACA,CAACvD,EAAOmD,CAAQ,CAAA,EAGZK,IACJhO,EAAAqN,EAAQ,KAAK,CAAC,CAAE,KAAAzN,KAAWA,EAAK,OAAS6D,CAAY,IAArD,YAAAzD,EAAwD,OAAQ,KAE5DiO,EAAY7B,GAAgBI,EAE5B0B,GAAgB,SAAY,CAChCjC,EAAc,EAAI,EAClB,MAAM,QAAQ,IAAI,CAACI,IAAgBI,EAAA,CAAgB,CAAC,EACpDR,EAAc,EAAK,CACrB,EAEMkC,EAAgBvO,GACpBmM,EAAiB7I,GAAUA,IAAStD,EAAO,KAAOA,CAAK,EAEnDwO,SACH,MAAA,CAAI,UAAU,4BACZ,SAAA5G,GAAQ,IAAK1G,GACZqF,EAAAA,IAAC,SAAA,CAEC,QAAS,IAAMkC,EAAUvH,CAAC,EAC1B,UAAW,+DACTkH,IAAWlH,EACP,yCACA,gDACN,GAEC,SAAAA,CAAA,EARIA,CAAA,CAUR,EACH,EAGF,OACEqG,EAAAA,KAAC,MAAA,CAAI,UAAU,+BACb,SAAA,CAAAhB,EAAAA,IAACkI,GAAA,CACC,MAAM,aACN,SAAS,gCACT,OAAQD,GACR,QACEjI,EAAAA,IAAC,SAAA,CACC,QAAS+H,GACT,SAAUlC,EACV,UAAU,uFAEV,eAACsC,GAAA,CAAU,UAAW,eAAetC,EAAa,eAAiB,EAAE,EAAA,CAAI,CAAA,CAAA,CAC3E,CAAA,EAIHiC,EACC9G,EAAAA,KAAC,MAAA,CAAI,UAAU,+BACb,SAAA,CAAAhB,EAAAA,IAAC,MAAA,CAAI,UAAU,oCAAA,CAAqC,EACpDA,EAAAA,IAAC,MAAA,CAAI,UAAU,uCAAA,CAAwC,QACtD,MAAA,CAAI,UAAU,YACZ,SAAA,CAAC,EAAG,EAAG,CAAC,EAAE,IAAKjF,GACdiF,EAAAA,IAAC,MAAA,CAAY,UAAU,sCAAA,EAAbjF,CAAoD,CAC/D,CAAA,CACH,CAAA,EACF,EACE0J,EAAU,SAAW,EACvBzD,OAAC,MAAA,CAAI,UAAU,OACb,SAAA,CAAAhB,EAAAA,IAAC,IAAA,CAAE,UAAU,mCAAmC,SAAA,oEAAiE,EACjHgB,EAAAA,KAAC,IAAA,CAAE,UAAU,6BAA6B,SAAA,CAAA,QAClC,UACL2B,EAAA,CAAK,GAAG,eAAe,UAAU,8BAA8B,SAAA,QAEhE,EAAQ,IAAI,cACD3C,EAAAA,IAAC,UAAO,SAAA,uBAAA,CAAqB,EAAS,6CAAA,CAAA,CAEnD,CAAA,EACF,EAGAgB,EAAAA,KAAC,MAAA,CAAI,UAAU,+BAIZ,SAAA,CAAAyD,EAAU,OAAS,GAClBzE,EAAAA,IAAC,MAAA,CAAI,UAAU,sCACZ,SAAAyE,EAAU,IAAKqC,GAAM,CACpB,MAAMsB,EAAWtB,EAAE,OAAO,QAASD,GAAA,YAAAA,EAAgB,OAAO,MAC1D,OACE7F,EAAAA,KAAC,SAAA,CAEC,QAAS,IAAM+F,EAAeD,EAAE,OAAO,IAAI,EAC3C,UAAW,+DACTsB,EACI,yCACA,gDACN,GAEC,SAAA,CAAAzO,GAAiBmN,EAAE,MAAM,EAC1B9G,EAAAA,IAAC,OAAA,CAAK,UAAW,uBAAuBoI,EAAW,iBAAmB,yBAAyB,GAC5F,SAAAtB,EAAE,SAAS,MAAA,CACd,CAAA,CAAA,EAXKA,EAAE,OAAO,IAAA,CAcpB,CAAC,CAAA,CACH,EAIF9F,EAAAA,KAAC,MAAA,CAAI,UAAU,yDAEb,SAAA,CAAAhB,EAAAA,IAAC,MAAA,CAAI,UAAU,0EACb,SAAAA,EAAAA,IAAC5C,GAAA,CACC,SAAUiK,EACV,aAAA/J,EACA,SAAU0K,EACV,iBAAkBV,EAClB,iBAAkBI,EAClB,YAAavD,GAAatC,CAAM,CAAA,CAAA,EAEpC,EAEA7B,EAAAA,IAAC,MAAA,CAAI,UAAU,8CAAA,CAA+C,EAE9DA,EAAAA,IAAC6D,GAAA,CACC,KAAMgE,EACN,WAAYT,EACZ,aAAcF,EAAQ,IAAKmB,GAAMA,EAAE,IAAI,EACvC,aAAcxG,EACd,QAAS,IAAM+D,EAAgB,IAAI,CAAA,CAAA,CACrC,EACF,EAGA5E,EAAAA,KAAC,MAAA,CAAI,UAAU,sFACb,SAAA,CAAAhB,EAAAA,IAACwF,GAAA,EAAU,EACXxF,EAAAA,IAAC,OAAI,UAAU,mEACZ,WAAQ,IAAI,CAAC,CAAE,KAAAvG,CAAA,IACduG,EAAAA,IAACmF,GAAA,CAEC,KAAA1L,EACA,OAAQ8M,EAAQ,KAAMtD,GAAMA,EAAE,OAASxJ,EAAK,IAAI,EAChD,SAAU6D,IAAiB7D,EAAK,KAChC,QAAS,IAAMuO,EAAavO,EAAK,IAAI,CAAA,EAJhCA,EAAK,IAAA,CAMb,CAAA,CACH,CAAA,CAAA,CACF,CAAA,CAAA,CAEF,CAAA,EAEJ,CAEJ"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{j as s}from"./vendor-query-B2UbickB.js";import{j as v,w as C,r as L,t as R}from"./index-B_aFcGv9.js";import{f as F}from"./useEventHooks-82IiMmOc.js";import{u as N}from"./roles-LZf98ePg.js";import{u as T}from"./useFilterParams-x-Dg0Vgz.js";import{u as _}from"./useDebouncedValue-BA5S7V54.js";import{b as k}from"./api-path-u2Jf9QXS.js";import{D as w}from"./DataTable-ZWgVQg7F.js";import{P as z}from"./PageHeader-DJo7yMUR.js";import{S as A}from"./StickyPagination-CD4W450h.js";import{R as M,a as O}from"./RowActions-BA9L9djf.js";import{a as I,T as U,E as q}from"./escalation-columns-CcbLKRI4.js";import{L as D}from"./ListToolbar-Ok2O0wmC.js";import{a5 as $}from"./vendor-icons-DOIDKgo6.js";import{c as B}from"./vendor-react-CXumBFUA.js";import"./EmptyState-BcsfPq9T.js";import"./FilterBar-B4Mk2PvT.js";import"./PriorityBadge-B4ykBH7f.js";import"./RolePill-DHWixsQR.js";import"./WorkflowPill-BtNBSplz.js";import"./escalation-CH_XK2XM.js";function pe(){F();const d=B(),{user:i}=v(),{filters:t,setFilter:u,pagination:e,sort:n,setSort:g}=T({filters:{role:"",type:"",priority:"",search:""}}),f=_(t.search,300),x=C(),{data:l}=N(),{data:c}=L(),m={assigned_to:i==null?void 0:i.userId,status:"pending",role:t.role||void 0,type:t.type||void 0,priority:t.priority?parseInt(t.priority):void 0,search:f||void 0,sort_by:n.sort_by||"created_at",order:n.order||"desc"},{data:o,isLoading:y,error:r,refetch:h,isFetching:b}=R({...m,limit:e.pageSize,offset:e.offset}),S=(o==null?void 0:o.escalations)??[],p=(o==null?void 0:o.total)??0,E=k("/escalations",{...m,limit:e.pageSize,offset:e.offset}),P={key:"actions",label:"",render:a=>s.jsx(M,{children:s.jsx(O,{icon:$,title:"Release escalation",onClick:()=>x.mutate(a.id),colorClass:"text-text-tertiary hover:text-status-warning"})}),className:"w-16 text-right"},j=[U,...q,P];return s.jsxs("div",{children:[s.jsx(z,{title:"My Escalations"}),s.jsx(I,{filters:t,setFilter:u,roles:(l==null?void 0:l.roles)??[],types:(c==null?void 0:c.types)??[],actions:s.jsx(D,{onRefresh:()=>h(),isFetching:b,apiPath:E})}),r&&s.jsx("div",{className:"mb-4 px-4 py-3 rounded-md bg-status-error/10 border border-status-error/20 text-xs text-status-error",children:r.message==="Session expired"?"Your session has expired. Please log in again.":`Failed to load escalations: ${r.message}`}),s.jsx(w,{columns:j,data:S,keyFn:a=>a.id,onRowClick:a=>d(`/escalations/detail/${a.id}`,{state:{from:"/escalations/queue"}}),isLoading:y,emptyMessage:r?"Unable to load data":"No assigned escalations",sort:n,onSort:g}),s.jsx(A,{page:e.page,totalPages:e.totalPages(p),onPageChange:e.setPage,total:p,pageSize:e.pageSize,onPageSizeChange:e.setPageSize})]})}export{pe as OperatorDashboard};
|
|
2
|
-
//# sourceMappingURL=OperatorDashboard-DIR7XDeD.js.map
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{j as e}from"./vendor-query-B2UbickB.js";import{B as r}from"./vendor-icons-DOIDKgo6.js";function x({title:i,actions:t,center:s,docsHash:a}){return e.jsxs("div",{className:"flex items-center gap-4 mb-10",children:[e.jsxs("div",{className:"flex items-center gap-2 flex-1 min-w-0",children:[e.jsx("h1",{className:"text-3xl font-light text-text-primary",children:i}),a&&e.jsx("button",{onClick:()=>{window.location.hash=a},className:"text-text-quaternary hover:text-accent transition-colors mt-1",title:"Open docs for this page",children:e.jsx(r,{className:"w-4 h-4",strokeWidth:1.5})})]}),s,t&&e.jsx("div",{className:`flex items-center gap-3 ${s?"flex-1 justify-end":""}`,children:t})]})}export{x as P};
|
|
2
|
-
//# sourceMappingURL=PageHeader-DJo7yMUR.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"PageHeader-DJo7yMUR.js","sources":["../../src/components/common/layout/PageHeader.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { BookOpen } from 'lucide-react';\n\ninterface PageHeaderProps {\n title: string;\n actions?: ReactNode;\n /** Optional element centered between the title and the actions (e.g. a sparkline). */\n center?: ReactNode;\n /** Hash link to open the docs drawer to a specific section, e.g. \"#docs=dashboard.md#workflow-registry\" */\n docsHash?: string;\n}\n\nexport function PageHeader({ title, actions, center, docsHash }: PageHeaderProps) {\n return (\n <div className=\"flex items-center gap-4 mb-10\">\n <div className=\"flex items-center gap-2 flex-1 min-w-0\">\n <h1 className=\"text-3xl font-light text-text-primary\">{title}</h1>\n {docsHash && (\n <button\n onClick={() => { window.location.hash = docsHash; }}\n className=\"text-text-quaternary hover:text-accent transition-colors mt-1\"\n title=\"Open docs for this page\"\n >\n <BookOpen className=\"w-4 h-4\" strokeWidth={1.5} />\n </button>\n )}\n </div>\n {center}\n {actions && (\n <div className={`flex items-center gap-3 ${center ? 'flex-1 justify-end' : ''}`}>{actions}</div>\n )}\n </div>\n );\n}\n"],"names":["PageHeader","title","actions","center","docsHash","jsxs","jsx","BookOpen"],"mappings":"8FAYO,SAASA,EAAW,CAAE,MAAAC,EAAO,QAAAC,EAAS,OAAAC,EAAQ,SAAAC,GAA6B,CAChF,OACEC,EAAAA,KAAC,MAAA,CAAI,UAAU,gCACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,yCACb,SAAA,CAAAC,EAAAA,IAAC,KAAA,CAAG,UAAU,wCAAyC,SAAAL,EAAM,EAC5DG,GACCE,EAAAA,IAAC,SAAA,CACC,QAAS,IAAM,CAAE,OAAO,SAAS,KAAOF,CAAU,EAClD,UAAU,gEACV,MAAM,0BAEN,SAAAE,EAAAA,IAACC,EAAA,CAAS,UAAU,UAAU,YAAa,GAAA,CAAK,CAAA,CAAA,CAClD,EAEJ,EACCJ,EACAD,SACE,MAAA,CAAI,UAAW,2BAA2BC,EAAS,qBAAuB,EAAE,GAAK,SAAAD,CAAA,CAAQ,CAAA,EAE9F,CAEJ"}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import{a as p,j as e}from"./vendor-query-B2UbickB.js";import{c as X,e as I,f as ee,d as te,g as se,h as ae}from"./roles-LZf98ePg.js";import{J as re}from"./index-B_aFcGv9.js";import{C as ne}from"./ConfirmDeleteModal-D9_1b4MW.js";import{u as ie}from"./users-DHx2ium7.js";import{T as O,B as oe,v as M,V as le,p as ce,a as de,ar as me,N as xe,f as pe,g as B}from"./vendor-icons-DOIDKgo6.js";import{e as ue,c as he,L as fe}from"./vendor-react-CXumBFUA.js";import"./Modal-CSrxpXeM.js";function ge({value:t,onChange:d,rows:n=2,className:l="",...x}){const i=p.useRef(null);return p.useLayoutEffect(()=>{const o=i.current;o&&(o.style.height="auto",o.style.height=`${o.scrollHeight}px`)},[t]),e.jsx("textarea",{ref:i,value:t,onChange:o=>d(o.target.value),rows:n,className:`textarea-quiet ${l}`,...x})}function je({role:t}){const{data:d}=ie({role:t,limit:100}),n=(d==null?void 0:d.users)??[];return n.length===0?e.jsx("p",{className:"text-[11px] text-text-tertiary",children:"Assign users to this role to staff its queue. Members see and resolve escalations here according to their read/write scope; admins manage the role itself."}):e.jsx("div",{className:"divide-y divide-surface-border/40",children:n.map(l=>{const x=l.roles.find(i=>i.role===t);return x?e.jsxs("div",{className:"flex items-center justify-between py-1.5 gap-2",children:[e.jsx("span",{className:"text-xs text-text-secondary truncate",children:l.display_name||l.external_id}),e.jsx("span",{className:"text-[10px] text-text-quaternary font-mono shrink-0",children:ve(x)})]},l.id):null})})}function ve(t){return t.type==="superadmin"||t.type==="admin"?t.type:`member · read ${t.read_scope} · write ${t.write_scope}`}function J(t){return t==null?"":JSON.stringify(t,null,2)}function R(t){const d=t.trim();if(!d)return{ok:!0,value:void 0};try{const n=JSON.parse(d);return typeof n!="object"||Array.isArray(n)||n===null?{ok:!1}:{ok:!0,value:n}}catch{return{ok:!1}}}function L({icon:t,color:d,label:n,aside:l}){return e.jsxs("div",{className:"flex items-center justify-between mb-3 pb-2 border-b border-surface-border",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(t,{className:`w-4 h-4 ${d}`,strokeWidth:1.5}),e.jsx("h2",{className:"section-h2",children:n})]}),l]})}function v({icon:t,label:d,annotation:n,aside:l,accent:x=!1,children:i}){const o=x?"text-accent":"text-text-tertiary";return e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-5",children:[e.jsxs("div",{className:"flex items-center gap-1.5 min-w-0",children:[e.jsx(t,{className:`w-3 h-3 ${o} shrink-0`,strokeWidth:1.5}),e.jsx("span",{className:`text-[9px] font-semibold uppercase tracking-widest ${o}`,children:d}),n&&e.jsxs("span",{className:"text-[9px] text-text-quaternary truncate",children:["— ",n]})]}),l]}),e.jsx("div",{className:`border-l-2 pl-5 ${x?"border-accent/15":"border-surface-border/60"}`,children:i})]})}function U(){return e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx("span",{className:"w-1.5 h-1.5 rounded-full dot-ring bg-status-success"}),e.jsx("span",{className:"text-[9px] font-semibold uppercase tracking-widest text-status-success",children:"Live"})]})}function be({role:t,allRoles:d}){const{data:n}=te(),l=se(),x=ae(),[i,o]=p.useState(""),a=(n==null?void 0:n.chains)??[],s=p.useMemo(()=>a.filter(c=>c.source_role===t.role).map(c=>c.target_role),[a,t.role]),g=p.useMemo(()=>d.map(c=>c.role).filter(c=>c!==t.role&&c!=="superadmin"&&!s.includes(c)),[d,t.role,s]);return t.role==="superadmin"?e.jsx("p",{className:"text-[11px] text-text-tertiary",children:"Superadmins can escalate to any role implicitly."}):e.jsxs("div",{className:"space-y-3",children:[s.length===0?e.jsx("p",{className:"text-[11px] text-text-tertiary",children:"Add a target role to route hand-offs."}):e.jsx("div",{className:"flex flex-wrap gap-1.5",children:s.map(c=>e.jsxs("span",{className:"inline-flex items-center gap-1 px-2 py-0.5 text-[10px] bg-surface-sunken rounded font-mono text-text-secondary",children:[c,e.jsx("button",{onClick:()=>x.mutate({source_role:t.role,target_role:c}),className:"text-text-quaternary hover:text-status-error transition-colors leading-none ml-0.5",children:"×"})]},c))}),g.length>0&&e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("select",{value:i,onChange:c=>o(c.target.value),className:"select text-xs font-mono flex-1",children:[e.jsx("option",{value:"",children:"Add target…"}),g.map(c=>e.jsx("option",{value:c,children:c},c))]}),e.jsx("button",{onClick:()=>{i&&l.mutate({source_role:t.role,target_role:i},{onSuccess:()=>o("")})},disabled:!i||l.isPending,className:"px-2.5 py-1 text-xs rounded bg-accent text-text-inverse hover:bg-accent-hover transition-colors disabled:opacity-40 disabled:cursor-not-allowed shrink-0",children:l.isPending?"…":"Add"})]})]})}function _e({role:t,allRoles:d}){const n=I(),[l,x]=p.useState(""),i=t.upstream_roles??[],o=p.useMemo(()=>d.map(s=>s.role).filter(s=>s!==t.role&&s!=="superadmin"&&!i.includes(s)),[d,t.role,i]),a=s=>n.mutate({role:t.role,upstream_roles:s},{onSuccess:()=>x("")});return e.jsxs("div",{className:"space-y-3",children:[i.length===0?e.jsx("p",{className:"text-[11px] text-text-tertiary",children:"Add a role from another sequence that this station draws input from. Prior Step sets where this role sits in its own sequence; upstream inputs mark the side-quests that land here."}):e.jsx("div",{className:"flex flex-wrap gap-1.5",children:i.map(s=>e.jsxs("span",{className:"inline-flex items-center gap-1 px-2 py-0.5 text-[10px] bg-surface-sunken rounded font-mono text-text-secondary",children:[s,e.jsx("button",{onClick:()=>a(i.filter(g=>g!==s)),className:"text-text-quaternary hover:text-status-error transition-colors leading-none ml-0.5",children:"×"})]},s))}),o.length>0&&e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("select",{value:l,onChange:s=>x(s.target.value),className:"select text-xs font-mono flex-1",children:[e.jsx("option",{value:"",children:"Add upstream input…"}),o.map(s=>e.jsx("option",{value:s,children:s},s))]}),e.jsx("button",{onClick:()=>{l&&a([...i,l])},disabled:!l||n.isPending,className:"px-2.5 py-1 text-xs rounded bg-accent text-text-inverse hover:bg-accent-hover transition-colors disabled:opacity-40 disabled:cursor-not-allowed shrink-0",children:n.isPending?"…":"Add"})]}),n.error&&e.jsx("p",{className:"text-[10px] text-status-error",children:n.error.message})]})}function Ne(t){return{title:t.title??"",description:t.description??"",ops_visible:t.ops_visible,parent_role:t.parent_role??"",metadata_schema:J(t.metadata_schema),properties:J(t.properties)||"{}",sla_minutes:t.sla_minutes!=null?String(t.sla_minutes):"",target_per_hour:t.target_per_hour!=null?String(t.target_per_hour):"",worker_count:t.worker_count!=null?String(t.worker_count):"",priority_threshold_minutes:t.priority_threshold_minutes!=null?String(t.priority_threshold_minutes):"",priority_facet:t.priority_facet??""}}const ye=/^[a-zA-Z0-9_]+$/;function Ee(){const{role:t}=ue(),d=he(),{data:n,isLoading:l}=X(),x=I(),i=ee(),o=(n==null?void 0:n.roles)??[],a=o.find(r=>r.role===t),[s,g]=p.useState({title:"",description:"",ops_visible:!1,parent_role:"",metadata_schema:"",properties:"{}",sla_minutes:"",target_per_hour:"",worker_count:"",priority_threshold_minutes:"",priority_facet:""}),[c,S]=p.useState(!1),[W,N]=p.useState(!1),[b,C]=p.useState({}),[V,D]=p.useState(!1),[T,P]=p.useState(new Set),G=r=>P(m=>new Set([...m,r]));p.useEffect(()=>{a&&(g(Ne(a)),S(!1),N(!1),C({}),P(new Set))},[t,a==null?void 0:a.role]);const f=r=>{g(m=>({...m,...r})),S(!0),N(!1)},z=p.useMemo(()=>o.filter(r=>{if(!a||r.role===a.role)return!1;let m=r;const u=new Set;for(;m!=null&&m.parent_role;){if(m.parent_role===a.role)return!1;if(u.has(m.parent_role))break;u.add(m.parent_role),m=o.find(h=>h.role===m.parent_role)}return!0}),[o,a]),H=()=>{const r=R(s.metadata_schema),m=R(s.properties),u=s.priority_facet.trim(),h={};if(r.ok||(h.metadata_schema="Invalid JSON"),m.ok||(h.properties="Invalid JSON"),u&&!ye.test(u)&&(h.priority_facet="Letters, numbers, underscores only"),C(h),Object.keys(h).length||!a)return;const j=E=>{const _=parseFloat(E);return isNaN(_)?null:_},Q=E=>{const _=j(E);return _==null?null:Math.round(_)};x.mutate({role:a.role,title:s.title.trim()||null,description:s.description.trim()||null,ops_visible:s.ops_visible,parent_role:s.parent_role||null,metadata_schema:r.value??null,properties:m.value??{},sla_minutes:j(s.sla_minutes),target_per_hour:j(s.target_per_hour),worker_count:Q(s.worker_count),priority_threshold_minutes:j(s.priority_threshold_minutes),priority_facet:u||null},{onSuccess:()=>{S(!1),N(!0),P(new Set),window.setTimeout(()=>N(!1),2500)}})},K=()=>{a&&i.mutate(a.role,{onSuccess:()=>d("/admin/roles")})};if(l)return e.jsxs("div",{className:"animate-pulse space-y-4",children:[e.jsx("div",{className:"h-8 bg-surface-sunken rounded w-48"}),e.jsx("div",{className:"h-4 bg-surface-sunken rounded w-64"}),e.jsx("div",{className:"h-64 bg-surface-sunken rounded"})]});if(!a)return e.jsxs("div",{className:"flex flex-col items-center justify-center py-20 text-center",children:[e.jsx(O,{className:"w-12 h-12 text-text-quaternary mb-4",strokeWidth:1}),e.jsx("h2",{className:"text-lg font-medium text-text-primary mb-2",children:"Role not found"})]});const Y=a.user_count>0||a.chain_count>0||a.workflow_count>0,Z=c&&!Object.values(b).some(Boolean),y=parseFloat(s.sla_minutes),w=parseFloat(s.target_per_hour),k=parseFloat(s.worker_count),A=!isNaN(y)&&y>0,$=!isNaN(w)&&w>0,q=!isNaN(k)&&k>0,F=A&&q&&!$?`→ target ≈ ${(k/(y/60)).toFixed(1)}/h`:A&&$&&!q?`→ workers ≈ ${(w*(y/60)).toFixed(1)}`:$&&q&&!A?`→ SLA ≈ ${(k/w*60).toFixed(0)}m`:null;return e.jsxs("div",{children:[e.jsxs("div",{className:"grid grid-cols-3 gap-16 items-center mb-12",children:[e.jsxs("div",{className:"flex items-center justify-between gap-4 min-w-0",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-3 mb-1",children:[e.jsx(O,{className:"w-5 h-5 text-accent",strokeWidth:1.5}),e.jsx("h1",{className:"text-lg font-mono font-medium text-text-primary",children:a.role}),e.jsx("button",{onClick:()=>{window.location.hash="#docs:dashboard.md:role-detail"},className:"text-text-quaternary hover:text-accent transition-colors",title:"Open docs for this page",children:e.jsx(oe,{className:"w-4 h-4",strokeWidth:1.5})}),a.parent_role&&e.jsxs("span",{className:"flex items-center gap-1 text-[10px] text-text-quaternary font-mono",children:[e.jsx(M,{className:"w-3 h-3"})," ",a.parent_role]})]}),a.title&&e.jsx("p",{className:"text-sm text-text-secondary pl-8",children:a.title})]}),e.jsxs("div",{className:"flex items-center gap-2 shrink-0",title:"Show as a station on the Pace Board",children:[e.jsx("span",{className:"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary",children:"Pace Board"}),e.jsx("button",{onClick:()=>f({ops_visible:!s.ops_visible}),className:`w-9 h-5 rounded-full transition-colors relative shrink-0 ${s.ops_visible?"bg-accent":"bg-surface-border"}`,children:e.jsx("span",{className:`absolute top-[3px] left-0 w-3.5 h-3.5 rounded-full bg-white transition-transform shadow ${s.ops_visible?"translate-x-[18px]":"translate-x-[3px]"}`})})]})]}),e.jsxs("div",{className:"flex items-end justify-center gap-4 bg-surface-sunken rounded-lg px-4 py-2.5 w-full",title:"throughput = workers / (sla / 60)",children:[[{key:"sla_minutes",label:"SLA",unit:"min",placeholder:"30"},{key:"target_per_hour",label:"Target",unit:"/h",placeholder:"20"},{key:"worker_count",label:"Workers",unit:"",placeholder:"4"}].map(({key:r,label:m,unit:u,placeholder:h})=>e.jsxs("div",{children:[e.jsxs("label",{className:"block text-[9px] font-semibold uppercase tracking-widest text-text-quaternary mb-1",children:[m,u&&e.jsx("span",{className:"normal-case font-normal ml-1",children:u})]}),e.jsx("input",{type:"number",min:"0",step:"any",value:s[r],onChange:j=>f({[r]:j.target.value}),placeholder:h,className:"input text-xs w-16 font-mono"})]},r)),F&&e.jsx("span",{className:"text-[10px] text-accent font-mono whitespace-nowrap pb-2",children:F})]}),e.jsxs("div",{className:"flex items-center justify-between gap-4 min-w-0",children:[e.jsxs("div",{className:"flex items-end gap-4 bg-surface-sunken rounded-lg px-4 py-2.5 shrink-0",title:"Pending unclaimed items older than the threshold count as priority on the Pace Board. Age is measured from the metadata facet (an ISO 8601 UTC timestamp, e.g. authorized_at) or from created_at when the facet is blank; the threshold falls back to SLA when blank.",children:[e.jsxs("div",{children:[e.jsxs("label",{className:"block text-[9px] font-semibold uppercase tracking-widest text-text-quaternary mb-1",children:["Priority",e.jsx("span",{className:"normal-case font-normal ml-1",children:"min"})]}),e.jsx("input",{type:"number",min:"0",step:"any",value:s.priority_threshold_minutes,onChange:r=>f({priority_threshold_minutes:r.target.value}),placeholder:s.sla_minutes||"60",className:"input text-xs w-16 font-mono"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-[9px] font-semibold uppercase tracking-widest text-text-quaternary mb-1",children:"Facet"}),e.jsx("input",{type:"text",value:s.priority_facet,onChange:r=>f({priority_facet:r.target.value}),placeholder:"created_at",className:"input text-xs w-28 font-mono"}),b.priority_facet&&e.jsx("p",{className:"text-[9px] text-status-error mt-0.5",children:b.priority_facet})]})]}),e.jsxs("div",{className:"flex items-center gap-3 shrink-0",children:[W&&e.jsxs("span",{className:"flex items-center gap-1 text-xs text-status-success animate-page-enter",children:[e.jsx(le,{className:"w-3 h-3"})," Saved"]}),x.error&&e.jsx("span",{className:"text-xs text-status-error max-w-[180px] truncate",children:x.error.message}),e.jsx("button",{onClick:H,disabled:!Z||x.isPending,className:"px-3 py-1.5 text-xs rounded-md bg-accent text-text-inverse hover:bg-accent-hover transition-colors disabled:opacity-40 disabled:cursor-not-allowed",children:x.isPending?"Saving…":"Save"}),!Y&&e.jsxs("button",{onClick:()=>D(!0),className:"px-3 py-1.5 text-xs rounded-md text-status-error/60 hover:text-status-error hover:bg-status-error/10 transition-colors flex items-center gap-1",children:[e.jsx(ce,{className:"w-3 h-3"})," Delete"]})]})]})]}),e.jsxs("div",{className:"grid grid-cols-3 gap-16 items-start",children:[e.jsxs("div",{className:"space-y-14",children:[e.jsx(v,{icon:O,label:"Identity",annotation:"name and description",accent:!0,children:e.jsxs("div",{className:"space-y-8",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-1.5",children:"Display Name"}),e.jsx("input",{type:"text",value:s.title,onChange:r=>f({title:r.target.value}),placeholder:`e.g., ${a.role.charAt(0).toUpperCase()+a.role.slice(1)}`,className:"input text-sm w-full"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-1.5",children:"Description"}),e.jsx(ge,{value:s.description,onChange:r=>f({description:r}),placeholder:"A short description shown on role cards and in the operations view.",rows:2})]})]})}),e.jsx("div",{className:`overflow-hidden transition-all duration-300 ease-out ${s.ops_visible?"opacity-100 max-h-[900px]":"opacity-0 max-h-0 pointer-events-none"}`,"aria-hidden":!s.ops_visible,children:e.jsx(v,{icon:de,label:"Pace Board",annotation:"where this station sits on the floor",accent:!0,children:e.jsxs("div",{className:"space-y-14",children:[e.jsxs("div",{className:"space-y-5",children:[e.jsx(L,{icon:M,color:"text-text-tertiary",label:"Prior Step"}),e.jsxs("select",{value:s.parent_role,onChange:r=>f({parent_role:r.target.value}),className:"select text-sm w-full font-mono",children:[e.jsx("option",{value:"",children:"None — root process"}),z.map(r=>e.jsx("option",{value:r.role,children:r.title?`${r.role} — ${r.title}`:r.role},r.role))]}),e.jsx("p",{className:"text-[10px] text-text-tertiary leading-relaxed",children:"Places this role in one Pace Board sequence. A role with no prior step starts its own sequence."})]}),e.jsxs("div",{className:"space-y-5",children:[e.jsx(L,{icon:me,color:"text-text-tertiary",label:"Upstream Inputs",aside:e.jsx(U,{})}),e.jsx(_e,{role:a,allRoles:o})]})]})})})]}),e.jsxs("div",{className:"space-y-14",children:[e.jsx(v,{icon:xe,label:"Escalation Targets",annotation:"hand-off routing",aside:e.jsx(U,{}),children:e.jsx(be,{role:a,allRoles:o})}),e.jsx(v,{icon:pe,label:"Members",annotation:"read = what appears · write = what they can act on",children:e.jsx(je,{role:a.role})})]}),e.jsxs("div",{className:"space-y-14",children:[e.jsxs(v,{icon:B,label:"Escalation Schema",annotation:"the resolve form",accent:!0,aside:a.current_schema_version!=null?e.jsxs("span",{className:"text-[9px] font-mono text-text-quaternary",children:["v",a.current_schema_version," in use"]}):void 0,children:[e.jsxs("p",{className:"text-[10px] text-text-tertiary mb-3 leading-relaxed",children:["The form a person completes to resolve this role's escalations. Versioned — each save adds one; workflows pin any version via"," ",e.jsx("code",{className:"font-mono",children:"schemaVersion"}),"."]}),e.jsx(fe,{to:`/admin/roles/${encodeURIComponent(a.role)}/schema`,className:"text-xs text-accent hover:underline",children:a.form_schema?`Open schema editor — v${a.current_schema_version??1} in use →`:"Define the escalation form →"})]}),e.jsxs(v,{icon:B,label:"Metadata Schema",annotation:"validates metadata at creation",aside:!T.has("metadata_schema")&&a.metadata_schema?e.jsx("button",{onClick:()=>G("metadata_schema"),className:"text-[9px] text-accent hover:underline",children:"Edit"}):void 0,children:[e.jsxs("p",{className:"text-[10px] text-text-tertiary mb-3 leading-relaxed",children:["Validates ",e.jsx("code",{className:"font-mono",children:"metadata"})," at creation time. Keys appear in faceted search autocomplete."]}),!T.has("metadata_schema")&&a.metadata_schema?e.jsx(re,{data:a.metadata_schema}):e.jsxs(e.Fragment,{children:[e.jsx("textarea",{value:s.metadata_schema,onChange:r=>{const m=r.target.value;f({metadata_schema:m}),C(u=>({...u,metadata_schema:R(m).ok?void 0:"Invalid JSON"}))},rows:10,spellCheck:!1,className:"input text-xs font-mono w-full resize-y",placeholder:`{
|
|
2
|
-
"type": "object",
|
|
3
|
-
"properties": {
|
|
4
|
-
"order_id": { "type": "string" }
|
|
5
|
-
},
|
|
6
|
-
"required": ["order_id"]
|
|
7
|
-
}`}),b.metadata_schema&&e.jsx("p",{className:"text-[10px] text-status-error mt-1",children:b.metadata_schema})]})]})]})]}),e.jsx(ne,{open:V,onClose:()=>D(!1),onConfirm:K,title:"Delete Role",description:e.jsxs(e.Fragment,{children:["Delete role ",e.jsx("span",{className:"font-medium font-mono text-text-primary",children:a.role}),"? This cannot be undone."]}),isPending:i.isPending,error:i.error})]})}export{Ee as RoleDetailPage};
|
|
8
|
-
//# sourceMappingURL=RoleDetailPage-BfzqQxMU.js.map
|