@hotmeshio/long-tail 0.17.0 → 0.17.2
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/dashboard/dist/assets/AdminDashboard-B_AVB7tk.js +2 -0
- package/dashboard/dist/assets/{AdminDashboard-Bx5G6Qb_.js.map → AdminDashboard-B_AVB7tk.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-S-YfPwCG.js → AgentConfigPage-JoZko3JB.js} +7 -7
- package/dashboard/dist/assets/{AgentConfigPage-S-YfPwCG.js.map → AgentConfigPage-JoZko3JB.js.map} +1 -1
- package/dashboard/dist/assets/{AgentDetailPage-pFVqLY4c.js → AgentDetailPage-DfpR2Fgg.js} +3 -3
- package/dashboard/dist/assets/{AgentDetailPage-pFVqLY4c.js.map → AgentDetailPage-DfpR2Fgg.js.map} +1 -1
- package/dashboard/dist/assets/AgentsPage-F2ixDk1Q.js +2 -0
- package/dashboard/dist/assets/{AgentsPage-DjAluFkM.js.map → AgentsPage-F2ixDk1Q.js.map} +1 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-D-W4OP55.js +2 -0
- package/dashboard/dist/assets/AvailableEscalationsPage-D-W4OP55.js.map +1 -0
- package/dashboard/dist/assets/{BotPicker-h2YrxQS2.js → BotPicker-B8Yal8Mm.js} +2 -2
- package/dashboard/dist/assets/{BotPicker-h2YrxQS2.js.map → BotPicker-B8Yal8Mm.js.map} +1 -1
- package/dashboard/dist/assets/BulkAssignModal-ySfoaF7f.js +2 -0
- package/dashboard/dist/assets/{BulkAssignModal-CNKZBgK5.js.map → BulkAssignModal-ySfoaF7f.js.map} +1 -1
- package/dashboard/dist/assets/CapabilitiesPage-BSJ2oFj6.js +2 -0
- package/dashboard/dist/assets/{CapabilitiesPage-DGsnIiJi.js.map → CapabilitiesPage-BSJ2oFj6.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-ptEsXSl6.js → CollapsibleSection-CcV88IUy.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-ptEsXSl6.js.map → CollapsibleSection-CcV88IUy.js.map} +1 -1
- package/dashboard/dist/assets/CountdownTimer-C-E9MXMk.js +2 -0
- package/dashboard/dist/assets/{CountdownTimer-Cvif0QtN.js.map → CountdownTimer-C-E9MXMk.js.map} +1 -1
- package/dashboard/dist/assets/{CredentialsPage-CwKUAtAR.js → CredentialsPage-DrydlZ65.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-CwKUAtAR.js.map → CredentialsPage-DrydlZ65.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-B9RbqMR-.js → CronLabel-BxQmJXos.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-B9RbqMR-.js.map → CronLabel-BxQmJXos.js.map} +1 -1
- package/dashboard/dist/assets/ElapsedCell-lszUXiyP.js +2 -0
- package/dashboard/dist/assets/{ElapsedCell-BirS3yZq.js.map → ElapsedCell-lszUXiyP.js.map} +1 -1
- package/dashboard/dist/assets/EntityTimelinePanel-CwzIV87U.js +2 -0
- package/dashboard/dist/assets/{EntityTimelinePanel-D3QNqDiL.js.map → EntityTimelinePanel-CwzIV87U.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationListSchemaPage-Bke-30FY.js → EscalationListSchemaPage-D16uUVcG.js} +3 -3
- package/dashboard/dist/assets/{EscalationListSchemaPage-Bke-30FY.js.map → EscalationListSchemaPage-D16uUVcG.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationSchemaPage-CTFE9vko.js → EscalationSchemaPage-BLM3dUEw.js} +3 -3
- package/dashboard/dist/assets/{EscalationSchemaPage-CTFE9vko.js.map → EscalationSchemaPage-BLM3dUEw.js.map} +1 -1
- package/dashboard/dist/assets/EscalationsOverview-BlFjoKlR.js +2 -0
- package/dashboard/dist/assets/{EscalationsOverview-C2FaSmXk.js.map → EscalationsOverview-BlFjoKlR.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-zFqzbEdC.js → EventTable-rTkMR8Zf.js} +2 -2
- package/dashboard/dist/assets/{EventTable-zFqzbEdC.js.map → EventTable-rTkMR8Zf.js.map} +1 -1
- package/dashboard/dist/assets/FilterBar-BeVBUdfJ.js +2 -0
- package/dashboard/dist/assets/FilterBar-BeVBUdfJ.js.map +1 -0
- package/dashboard/dist/assets/{GraphInvokePage-CA_XYI2W.js → GraphInvokePage-BV60xkVy.js} +2 -2
- package/dashboard/dist/assets/{GraphInvokePage-CA_XYI2W.js.map → GraphInvokePage-BV60xkVy.js.map} +1 -1
- package/dashboard/dist/assets/HomePage-BA0RYzFc.js +2 -0
- package/dashboard/dist/assets/HomePage-BA0RYzFc.js.map +1 -0
- package/dashboard/dist/assets/ListToolbar-4IfsUXfV.js +2 -0
- package/dashboard/dist/assets/{ListToolbar-BEogxu1f.js.map → ListToolbar-4IfsUXfV.js.map} +1 -1
- package/dashboard/dist/assets/{McpOverview-CdMR-5qh.js → McpOverview-gDegMXvF.js} +2 -2
- package/dashboard/dist/assets/{McpOverview-CdMR-5qh.js.map → McpOverview-gDegMXvF.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryDetailPage-BXo4UjJF.js → McpQueryDetailPage-CnCffPks.js} +4 -4
- package/dashboard/dist/assets/{McpQueryDetailPage-BXo4UjJF.js.map → McpQueryDetailPage-CnCffPks.js.map} +1 -1
- package/dashboard/dist/assets/McpQueryPage-CLEMtLOG.js +2 -0
- package/dashboard/dist/assets/{McpQueryPage-BvvM0Ya1.js.map → McpQueryPage-CLEMtLOG.js.map} +1 -1
- package/dashboard/dist/assets/McpRunDetailPage-tr-lrWVv.js +2 -0
- package/dashboard/dist/assets/McpRunDetailPage-tr-lrWVv.js.map +1 -0
- package/dashboard/dist/assets/McpRunsPage-nE0d_1Px.js +2 -0
- package/dashboard/dist/assets/McpRunsPage-nE0d_1Px.js.map +1 -0
- package/dashboard/dist/assets/OperationsPage-C8h1DN5Q.js +3 -0
- package/dashboard/dist/assets/OperationsPage-C8h1DN5Q.js.map +1 -0
- package/dashboard/dist/assets/OperatorDashboard-DCG8BFKE.js +2 -0
- package/dashboard/dist/assets/OperatorDashboard-DCG8BFKE.js.map +1 -0
- package/dashboard/dist/assets/{PersonaDetailPage-BHQ44UIu.js → PersonaDetailPage-BEVeJr1q.js} +2 -2
- package/dashboard/dist/assets/{PersonaDetailPage-BHQ44UIu.js.map → PersonaDetailPage-BEVeJr1q.js.map} +1 -1
- package/dashboard/dist/assets/PersonasPage-B5fj2AK6.js +2 -0
- package/dashboard/dist/assets/PersonasPage-B5fj2AK6.js.map +1 -0
- package/dashboard/dist/assets/ProcessDetailPage-CWGby6KD.js +2 -0
- package/dashboard/dist/assets/{ProcessDetailPage-CZ09xiWf.js.map → ProcessDetailPage-CWGby6KD.js.map} +1 -1
- package/dashboard/dist/assets/ProcessesListPage-nFdLMlfb.js +2 -0
- package/dashboard/dist/assets/ProcessesListPage-nFdLMlfb.js.map +1 -0
- package/dashboard/dist/assets/RoleDetailPage-OmOdRm1F.js +8 -0
- package/dashboard/dist/assets/{RoleDetailPage-CDsJKPvV.js.map → RoleDetailPage-OmOdRm1F.js.map} +1 -1
- package/dashboard/dist/assets/{RolesPage-D2cV92bL.js → RolesPage-DwprdPCA.js} +2 -2
- package/dashboard/dist/assets/{RolesPage-D2cV92bL.js.map → RolesPage-DwprdPCA.js.map} +1 -1
- package/dashboard/dist/assets/{RunAsSelector-Cvi8x8xx.js → RunAsSelector-DGw9EKSR.js} +2 -2
- package/dashboard/dist/assets/{RunAsSelector-Cvi8x8xx.js.map → RunAsSelector-DGw9EKSR.js.map} +1 -1
- package/dashboard/dist/assets/{ScanCodesPage-BWt_iRCu.js → ScanCodesPage-RPi4qZ_l.js} +2 -2
- package/dashboard/dist/assets/{ScanCodesPage-BWt_iRCu.js.map → ScanCodesPage-RPi4qZ_l.js.map} +1 -1
- package/dashboard/dist/assets/ScanSchemeDetailPage-BKc4lUjc.js +2 -0
- package/dashboard/dist/assets/{ScanSchemeDetailPage-C6mRYkxL.js.map → ScanSchemeDetailPage-BKc4lUjc.js.map} +1 -1
- package/dashboard/dist/assets/ScanStationPage-DUfxcntB.js +2 -0
- package/dashboard/dist/assets/{ScanStationPage-YQiijAKy.js.map → ScanStationPage-DUfxcntB.js.map} +1 -1
- package/dashboard/dist/assets/{StickyPagination-BsbSade1.js → StickyPagination-DXOk5z5X.js} +2 -2
- package/dashboard/dist/assets/{StickyPagination-BsbSade1.js.map → StickyPagination-DXOk5z5X.js.map} +1 -1
- package/dashboard/dist/assets/{StreamMessageDetail-jczXwuBw.js → StreamMessageDetail-BB1h2zZN.js} +2 -2
- package/dashboard/dist/assets/{StreamMessageDetail-jczXwuBw.js.map → StreamMessageDetail-BB1h2zZN.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-DSO6QXmX.js → SwimlaneTimeline-CapKokLg.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-DSO6QXmX.js.map → SwimlaneTimeline-CapKokLg.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-DWLfcAF4.js → TaskDetailPage-Dfzdp97x.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-DWLfcAF4.js.map → TaskDetailPage-Dfzdp97x.js.map} +1 -1
- package/dashboard/dist/assets/{TasksListPage-B0at3vJ3.js → TasksListPage-DxlS7PTD.js} +2 -2
- package/dashboard/dist/assets/{TasksListPage-B0at3vJ3.js.map → TasksListPage-DxlS7PTD.js.map} +1 -1
- package/dashboard/dist/assets/TimeAgo-Bv5viQ1m.js +2 -0
- package/dashboard/dist/assets/{TimeAgo-poxwErGl.js.map → TimeAgo-Bv5viQ1m.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-Be6tvFQd.js → TimestampCell-DXNBf_eb.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-Be6tvFQd.js.map → TimestampCell-DXNBf_eb.js.map} +1 -1
- package/dashboard/dist/assets/{ToolTestPanel-CYOqnqMz.js → ToolTestPanel-f32mir7Q.js} +2 -2
- package/dashboard/dist/assets/{ToolTestPanel-CYOqnqMz.js.map → ToolTestPanel-f32mir7Q.js.map} +1 -1
- package/dashboard/dist/assets/{TopicDetailPage-C82WIKaU.js → TopicDetailPage-D-N8Vsd4.js} +3 -3
- package/dashboard/dist/assets/{TopicDetailPage-C82WIKaU.js.map → TopicDetailPage-D-N8Vsd4.js.map} +1 -1
- package/dashboard/dist/assets/{TopicsPage-COH547ZD.js → TopicsPage-hqlu32wg.js} +2 -2
- package/dashboard/dist/assets/{TopicsPage-COH547ZD.js.map → TopicsPage-hqlu32wg.js.map} +1 -1
- package/dashboard/dist/assets/UserName-BhA_ItNN.js +2 -0
- package/dashboard/dist/assets/{UserName-D2SoVbe9.js.map → UserName-BhA_ItNN.js.map} +1 -1
- package/dashboard/dist/assets/WorkflowExecutionPage-BAgMKnhe.js +2 -0
- package/dashboard/dist/assets/{WorkflowExecutionPage-C82Q-TYC.js.map → WorkflowExecutionPage-BAgMKnhe.js.map} +1 -1
- package/dashboard/dist/assets/WorkflowsDashboard-B2wYT_hj.js +2 -0
- package/dashboard/dist/assets/WorkflowsDashboard-B2wYT_hj.js.map +1 -0
- package/dashboard/dist/assets/WorkflowsOverview--jC5F9lz.js +2 -0
- package/dashboard/dist/assets/{WorkflowsOverview-DdKRtWdK.js.map → WorkflowsOverview--jC5F9lz.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-D3qvyy_4.js → YamlWorkflowDetailPage-BdB5eX8s.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-D3qvyy_4.js.map → YamlWorkflowDetailPage-BdB5eX8s.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowsPage-BJsxZOBC.js → YamlWorkflowsPage-BUQQU9II.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowsPage-BJsxZOBC.js.map → YamlWorkflowsPage-BUQQU9II.js.map} +1 -1
- package/dashboard/dist/assets/{agents-OQHCkIfJ.js → agents-BF_S1J_z.js} +2 -2
- package/dashboard/dist/assets/{agents-OQHCkIfJ.js.map → agents-BF_S1J_z.js.map} +1 -1
- package/dashboard/dist/assets/{bots-e8jsNOf4.js → bots-CGlEoWAu.js} +2 -2
- package/dashboard/dist/assets/{bots-e8jsNOf4.js.map → bots-CGlEoWAu.js.map} +1 -1
- package/dashboard/dist/assets/capabilities-Pq8pG0kX.js +2 -0
- package/dashboard/dist/assets/{capabilities-CEo0AB79.js.map → capabilities-Pq8pG0kX.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-CD6ti-QB.js → controlplane-dY6a4iYT.js} +2 -2
- package/dashboard/dist/assets/{controlplane-CD6ti-QB.js.map → controlplane-dY6a4iYT.js.map} +1 -1
- package/dashboard/dist/assets/escalation-columns-CBUTda5U.js +2 -0
- package/dashboard/dist/assets/{escalation-columns-CUtDSbxl.js.map → escalation-columns-CBUTda5U.js.map} +1 -1
- package/dashboard/dist/assets/{index-Bf4IPu7I.js → index-BHfISWyn.js} +2 -2
- package/dashboard/dist/assets/{index-Bf4IPu7I.js.map → index-BHfISWyn.js.map} +1 -1
- package/dashboard/dist/assets/{index-BsP7vujM.js → index-BTksPQZe.js} +2 -2
- package/dashboard/dist/assets/{index-BsP7vujM.js.map → index-BTksPQZe.js.map} +1 -1
- package/dashboard/dist/assets/{index-B76fjEom.js → index-BWtW5puE.js} +2 -2
- package/dashboard/dist/assets/{index-B76fjEom.js.map → index-BWtW5puE.js.map} +1 -1
- package/dashboard/dist/assets/index-Bn-6MP9-.js +2 -0
- package/dashboard/dist/assets/index-Bn-6MP9-.js.map +1 -0
- package/dashboard/dist/assets/{index-C8VhbKFU.js → index-BrFGgfjR.js} +2 -2
- package/dashboard/dist/assets/index-BrFGgfjR.js.map +1 -0
- package/dashboard/dist/assets/{index-COUj4v_W.js → index-ByYeo8P7.js} +3 -3
- package/dashboard/dist/assets/{index-COUj4v_W.js.map → index-ByYeo8P7.js.map} +1 -1
- package/dashboard/dist/assets/{index-BpwkKV5f.js → index-CivQGQpu.js} +3 -3
- package/dashboard/dist/assets/{index-BpwkKV5f.js.map → index-CivQGQpu.js.map} +1 -1
- package/dashboard/dist/assets/{index-DIHr2CvI.js → index-CwQn-nhR.js} +2 -2
- package/dashboard/dist/assets/{index-DIHr2CvI.js.map → index-CwQn-nhR.js.map} +1 -1
- package/dashboard/dist/assets/index-D0bjzVum.js +2 -0
- package/dashboard/dist/assets/index-D0bjzVum.js.map +1 -0
- package/dashboard/dist/assets/{index-CTZEzzN3.js → index-D1KCPoRr.js} +2 -2
- package/dashboard/dist/assets/{index-CTZEzzN3.js.map → index-D1KCPoRr.js.map} +1 -1
- package/dashboard/dist/assets/index-D9rtK9QF.js +67 -0
- package/dashboard/dist/assets/index-D9rtK9QF.js.map +1 -0
- package/dashboard/dist/assets/{index-B0C6wSrQ.js → index-DrlZc3C0.js} +2 -2
- package/dashboard/dist/assets/{index-B0C6wSrQ.js.map → index-DrlZc3C0.js.map} +1 -1
- package/dashboard/dist/assets/index-U7HShN30.js +2 -0
- package/dashboard/dist/assets/{index-B2aiEKtM.js.map → index-U7HShN30.js.map} +1 -1
- package/dashboard/dist/assets/{knowledge-C89zT4Qe.js → knowledge-8_TilyaY.js} +2 -2
- package/dashboard/dist/assets/{knowledge-C89zT4Qe.js.map → knowledge-8_TilyaY.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-BLKHykZS.js → mcp-hY3O2HJa.js} +2 -2
- package/dashboard/dist/assets/{mcp-BLKHykZS.js.map → mcp-hY3O2HJa.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-CfiqUNDV.js → mcp-query-CA8NEf2e.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-CfiqUNDV.js.map → mcp-query-CA8NEf2e.js.map} +1 -1
- package/dashboard/dist/assets/{personas-B1HzC94M.js → personas-DrWgQ94s.js} +2 -2
- package/dashboard/dist/assets/{personas-B1HzC94M.js.map → personas-DrWgQ94s.js.map} +1 -1
- package/dashboard/dist/assets/{pipelines-C73X50ES.js → pipelines-DdgSlafC.js} +2 -2
- package/dashboard/dist/assets/{pipelines-C73X50ES.js.map → pipelines-DdgSlafC.js.map} +1 -1
- package/dashboard/dist/assets/{tasks-DHbFpQk4.js → tasks-UyjER1TA.js} +2 -2
- package/dashboard/dist/assets/{tasks-DHbFpQk4.js.map → tasks-UyjER1TA.js.map} +1 -1
- package/dashboard/dist/assets/{topics-Fu8qCUOd.js → topics-CIc5SpT_.js} +2 -2
- package/dashboard/dist/assets/{topics-Fu8qCUOd.js.map → topics-CIc5SpT_.js.map} +1 -1
- package/dashboard/dist/assets/useDebouncedValue-CmUqBRK4.js +2 -0
- package/dashboard/dist/assets/useDebouncedValue-CmUqBRK4.js.map +1 -0
- package/dashboard/dist/assets/{useNamespace-CpO5Hogb.js → useNamespace-BOZOwXTE.js} +2 -2
- package/dashboard/dist/assets/{useNamespace-CpO5Hogb.js.map → useNamespace-BOZOwXTE.js.map} +1 -1
- package/dashboard/dist/assets/{useYamlActivityEvents-BwIl6_d2.js → useYamlActivityEvents-BsTpIsba.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-BwIl6_d2.js.map → useYamlActivityEvents-BsTpIsba.js.map} +1 -1
- package/dashboard/dist/assets/{workflows-DR9OQcuq.js → workflows-BkFI3IwE.js} +2 -2
- package/dashboard/dist/assets/{workflows-DR9OQcuq.js.map → workflows-BkFI3IwE.js.map} +1 -1
- package/dashboard/dist/assets/{yaml-workflows-DjEHh9Wy.js → yaml-workflows-CeeqNi9k.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-DjEHh9Wy.js.map → yaml-workflows-CeeqNi9k.js.map} +1 -1
- package/dashboard/dist/index.html +1 -1
- package/docs/dashboard.md +18 -0
- package/package.json +1 -1
- package/dashboard/dist/assets/AdminDashboard-Bx5G6Qb_.js +0 -2
- package/dashboard/dist/assets/AgentsPage-DjAluFkM.js +0 -2
- package/dashboard/dist/assets/AvailableEscalationsPage-BHsRZk4v.js +0 -2
- package/dashboard/dist/assets/AvailableEscalationsPage-BHsRZk4v.js.map +0 -1
- package/dashboard/dist/assets/BulkAssignModal-CNKZBgK5.js +0 -2
- package/dashboard/dist/assets/CapabilitiesPage-DGsnIiJi.js +0 -2
- package/dashboard/dist/assets/CountdownTimer-Cvif0QtN.js +0 -2
- package/dashboard/dist/assets/ElapsedCell-BirS3yZq.js +0 -2
- package/dashboard/dist/assets/EntityTimelinePanel-D3QNqDiL.js +0 -2
- package/dashboard/dist/assets/EscalationsOverview-C2FaSmXk.js +0 -2
- package/dashboard/dist/assets/FilterBar-fwUqeM-5.js +0 -2
- package/dashboard/dist/assets/FilterBar-fwUqeM-5.js.map +0 -1
- package/dashboard/dist/assets/HomePage-C2HnqdFX.js +0 -2
- package/dashboard/dist/assets/HomePage-C2HnqdFX.js.map +0 -1
- package/dashboard/dist/assets/ListToolbar-BEogxu1f.js +0 -2
- package/dashboard/dist/assets/McpQueryPage-BvvM0Ya1.js +0 -2
- package/dashboard/dist/assets/McpRunDetailPage-5eaJeupC.js +0 -2
- package/dashboard/dist/assets/McpRunDetailPage-5eaJeupC.js.map +0 -1
- package/dashboard/dist/assets/McpRunsPage-B5_-3NUF.js +0 -2
- package/dashboard/dist/assets/McpRunsPage-B5_-3NUF.js.map +0 -1
- package/dashboard/dist/assets/OperationsPage-CJXTw02Z.js +0 -3
- package/dashboard/dist/assets/OperationsPage-CJXTw02Z.js.map +0 -1
- package/dashboard/dist/assets/OperatorDashboard-Dx7639os.js +0 -2
- package/dashboard/dist/assets/OperatorDashboard-Dx7639os.js.map +0 -1
- package/dashboard/dist/assets/PersonasPage-Cnmb4uox.js +0 -2
- package/dashboard/dist/assets/PersonasPage-Cnmb4uox.js.map +0 -1
- package/dashboard/dist/assets/ProcessDetailPage-CZ09xiWf.js +0 -2
- package/dashboard/dist/assets/ProcessesListPage-BT76_7bW.js +0 -2
- package/dashboard/dist/assets/ProcessesListPage-BT76_7bW.js.map +0 -1
- package/dashboard/dist/assets/RoleDetailPage-CDsJKPvV.js +0 -8
- package/dashboard/dist/assets/ScanSchemeDetailPage-C6mRYkxL.js +0 -2
- package/dashboard/dist/assets/ScanStationPage-YQiijAKy.js +0 -2
- package/dashboard/dist/assets/TimeAgo-poxwErGl.js +0 -2
- package/dashboard/dist/assets/UserName-D2SoVbe9.js +0 -2
- package/dashboard/dist/assets/WorkflowExecutionPage-C82Q-TYC.js +0 -2
- package/dashboard/dist/assets/WorkflowsDashboard-DDWwCT-v.js +0 -2
- package/dashboard/dist/assets/WorkflowsDashboard-DDWwCT-v.js.map +0 -1
- package/dashboard/dist/assets/WorkflowsOverview-DdKRtWdK.js +0 -2
- package/dashboard/dist/assets/capabilities-CEo0AB79.js +0 -2
- package/dashboard/dist/assets/escalation-columns-CUtDSbxl.js +0 -2
- package/dashboard/dist/assets/index-B2aiEKtM.js +0 -2
- package/dashboard/dist/assets/index-BYIN0l5M.js +0 -2
- package/dashboard/dist/assets/index-BYIN0l5M.js.map +0 -1
- package/dashboard/dist/assets/index-C8VhbKFU.js.map +0 -1
- package/dashboard/dist/assets/index-DSdqso-_.js +0 -67
- package/dashboard/dist/assets/index-DSdqso-_.js.map +0 -1
- package/dashboard/dist/assets/index-VsZyCFz8.js +0 -2
- package/dashboard/dist/assets/index-VsZyCFz8.js.map +0 -1
- package/dashboard/dist/assets/useDebouncedValue-C4P2jQuh.js +0 -2
- package/dashboard/dist/assets/useDebouncedValue-C4P2jQuh.js.map +0 -1
- package/dashboard/dist/assets/useEventHooks-DL3Vhz4g.js +0 -2
- package/dashboard/dist/assets/useEventHooks-DL3Vhz4g.js.map +0 -1
- package/dashboard/dist/assets/users-C0ke1Z-8.js +0 -2
- package/dashboard/dist/assets/users-C0ke1Z-8.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"OperationsPage-CJXTw02Z.js","sources":["../../src/pages/operations/StationMixBar.tsx","../../src/pages/operations/entity-pivot.ts","../../src/pages/operations/StateBands.tsx","../../src/components/common/display/CenterEllipsis.tsx","../../src/pages/operations/EntityColumns.tsx","../../src/pages/operations/EntityLensView.tsx","../../src/pages/operations/ViewMenu.tsx","../../src/pages/operations/PaceChart.tsx","../../src/pages/operations/priority-link.ts","../../src/pages/operations/StationAnalyticsSections.tsx","../../src/pages/operations/StationDetailPanel.tsx","../../src/pages/operations/OperationsPage.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport type { AggregateRow } from '../../api/escalation-analytics';\nimport { subtypeKey, subtypeLabel } from './mix-colors';\nimport { formatDurationCompact } from '../../lib/format';\n\n/**\n * Time-in-state mix for one station over the board's window — the mini-bar\n * sibling of the Load bar: each segment is a subtype's share of the station's\n * tracked time. The number beside it is the dominant share; the tooltip\n * carries the full breakdown. `—` when there is no data (empty window, or the\n * analytics gate withheld it).\n */\nexport function StationMixBar({\n groups,\n colors,\n}: {\n groups: AggregateRow[] | undefined;\n colors: Map<string, string>;\n}) {\n const segments = useMemo(() => {\n const rows = (groups ?? []).filter((g) => (g.dwellSeconds ?? 0) > 0);\n const total = rows.reduce((sum, g) => sum + (g.dwellSeconds ?? 0), 0);\n if (!total) return null;\n return rows\n .map((g) => ({\n key: subtypeKey(g.subtype),\n label: subtypeLabel(g.subtype),\n seconds: g.dwellSeconds ?? 0,\n pct: (g.dwellSeconds ?? 0) / total,\n }))\n .sort((a, b) => b.seconds - a.seconds);\n }, [groups]);\n\n if (!segments) {\n return <span className=\"text-2xs text-text-quaternary\">—</span>;\n }\n\n const tooltip = segments\n .map((s) => `${s.label} ${formatDurationCompact(s.seconds * 1000)} · ${Math.round(s.pct * 100)}%`)\n .join('\\n');\n\n return (\n <div className=\"flex items-center gap-1.5\" title={tooltip}>\n <div className=\"w-16 h-1.5 bg-surface-sunken rounded-full overflow-hidden flex shrink-0\">\n {segments.map((s) => (\n <div\n key={s.key}\n style={{ width: `${s.pct * 100}%`, backgroundColor: colors.get(s.key) }}\n />\n ))}\n </div>\n <span className=\"text-2xs font-mono text-text-quaternary tabular-nums\">\n {Math.round(segments[0].pct * 100)}%\n </span>\n </div>\n );\n}\n","import type { AggregateRow } from '../../api/escalation-analytics';\n\n// Pivot helpers for the entity lens. The RANKING query (grouped by the entity\n// facet alone) defines a page: one row per entity, ordered by total tracked\n// time — so an entity can never straddle a page boundary and its rank is its\n// whole dwell, not its largest state. The state-split and membership queries\n// then annotate exactly that page (anyOf-targeted). Pure functions.\n\nexport interface EntityRow {\n value: string;\n groups: AggregateRow[];\n total: number;\n nowState: string | null;\n}\n\n/** One ranked slice value: the column's header timeline and its dwell total. */\nexport interface SliceValue {\n value: string;\n groups: AggregateRow[];\n total: number;\n}\n\nexport function totalDwell(groups: AggregateRow[]): number {\n return groups.reduce((sum, g) => sum + (g.dwellSeconds ?? 0), 0) || 1;\n}\n\n/** The page's entity values in rank order (one ranking row per entity). */\nexport function entityValues(rankGroups: AggregateRow[], entityKey: string): string[] {\n const out: string[] = [];\n for (const g of rankGroups) {\n const value = g.facets[entityKey];\n if (value == null || (g.dwellSeconds ?? 0) <= 0) continue;\n out.push(value);\n }\n return out;\n}\n\n/**\n * Assemble per-entity band rows for one page: ranking rows fix membership,\n * order, and totals; state-split rows fill each entity's band; membership\n * rows annotate the current state.\n */\nexport function pivotEntities(\n rankGroups: AggregateRow[],\n stateGroups: AggregateRow[],\n nowGroups: AggregateRow[],\n entityKey: string,\n): EntityRow[] {\n const statesByValue = new Map<string, AggregateRow[]>();\n for (const g of stateGroups) {\n const value = g.facets[entityKey];\n if (value == null || (g.dwellSeconds ?? 0) <= 0) continue;\n const rows = statesByValue.get(value) ?? [];\n rows.push(g);\n statesByValue.set(value, rows);\n }\n const nowByValue = new Map<string, string>();\n for (const g of nowGroups) {\n const value = g.facets[entityKey];\n if (value == null || (g.count ?? 0) <= 0 || g.state == null) continue;\n // Multiple live states for one entity is a model smell; surface the first.\n if (!nowByValue.has(value)) nowByValue.set(value, g.state);\n }\n const rows: EntityRow[] = [];\n for (const g of rankGroups) {\n const value = g.facets[entityKey];\n if (value == null || (g.dwellSeconds ?? 0) <= 0) continue;\n const groups = [...(statesByValue.get(value) ?? [])]\n .sort((a, b) => (b.dwellSeconds ?? 0) - (a.dwellSeconds ?? 0));\n rows.push({\n value,\n groups,\n total: g.dwellSeconds ?? 0,\n nowState: nowByValue.get(value) ?? null,\n });\n }\n return rows;\n}\n\n/**\n * Rank a slice query's rows (grouped by state + the slice key) into per-value\n * state-split bundles — top N by total dwell. These become the lens columns,\n * each bundle the column's header timeline.\n */\nexport function rankSliceValues(\n sliceGroups: AggregateRow[],\n sliceKey: string,\n limit = 12,\n): SliceValue[] {\n const byValue = new Map<string, AggregateRow[]>();\n for (const g of sliceGroups) {\n if ((g.dwellSeconds ?? 0) <= 0) continue;\n const value = g.facets[sliceKey] ?? 'no value';\n const rows = byValue.get(value) ?? [];\n rows.push(g);\n byValue.set(value, rows);\n }\n return [...byValue.entries()]\n .map(([value, groups]) => ({\n value,\n groups: [...groups].sort((a, b) => (b.dwellSeconds ?? 0) - (a.dwellSeconds ?? 0)),\n total: totalDwell(groups),\n }))\n .sort((a, b) => b.total - a.total)\n .slice(0, limit);\n}\n","import type { AggregateRow } from '../../api/escalation-analytics';\nimport { totalDwell } from './entity-pivot';\nimport { formatDurationCompact } from '../../lib/format';\n\n/** One stacked band of state dwell. */\nexport function StateBand({\n groups,\n colors,\n height,\n className = '',\n}: {\n groups: AggregateRow[];\n colors: Map<string, string>;\n height: string;\n className?: string;\n}) {\n const total = totalDwell(groups);\n // Segments render in the GLOBAL color order (the colors map is built in\n // dwell-rank order — blue → orange → green → …), not each band's own\n // dominant-first order. A fixed sequence makes ratios comparable at a glance\n // across the system band, slice headers, and every per-entity row.\n const rank = new Map([...colors.keys()].map((k, i) => [k, i]));\n const ordered = [...groups].sort(\n (a, b) => (rank.get(a.state ?? '—') ?? Infinity) - (rank.get(b.state ?? '—') ?? Infinity),\n );\n return (\n <div className={`${height} flex rounded-full overflow-hidden bg-surface-sunken ${className}`}>\n {ordered.map((g) => (\n <div\n key={g.state ?? '—'}\n title={`${g.state ?? '—'} · ${formatDurationCompact((g.dwellSeconds ?? 0) * 1000)}`}\n style={{ width: `${((g.dwellSeconds ?? 0) / total) * 100}%`, backgroundColor: colors.get(g.state ?? '—') }}\n />\n ))}\n </div>\n );\n}\n","/**\n * Truncate a long identifier in the MIDDLE, keeping its trailing characters\n * visible. For keyed values (serial numbers, order ids) the tail digits are\n * usually what disambiguates one from the next, so a head-truncating ellipsis\n * would hide the useful part. The full value is the hover title.\n *\n * Renders as a flex span: the head truncates, the tail is pinned. Give it a\n * bounded width (the parent cell) for the ellipsis to engage.\n */\nexport function CenterEllipsis({\n text,\n tail = 6,\n className = '',\n}: {\n text: string;\n /** How many trailing characters to always keep visible. */\n tail?: number;\n className?: string;\n}) {\n // Short enough to show whole — no split (keeps the value a single text node).\n if (text.length <= tail + 1) {\n return <span className={`truncate ${className}`} title={text}>{text}</span>;\n }\n const head = text.slice(0, text.length - tail);\n const end = text.slice(text.length - tail);\n return (\n <span className={`flex items-baseline min-w-0 ${className}`} title={text}>\n <span className=\"truncate min-w-0\">{head}</span>\n <span className=\"shrink-0\">{end}</span>\n </span>\n );\n}\n","import { useMemo } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { History, ArrowRight, Clock } from 'lucide-react';\nimport { StateBand } from './StateBands';\nimport { CenterEllipsis } from '../../components/common/display/CenterEllipsis';\nimport { metadataFacetUrl } from '../../lib/facet-url';\nimport { useAggregateByFacets, type AnalyticsWindow } from '../../api/escalation-analytics';\nimport type { AggregateRow } from '../../api/escalation-analytics';\nimport type { EntityRow } from './entity-pivot';\nimport { entityValues, pivotEntities } from './entity-pivot';\nimport { formatDurationCompact } from '../../lib/format';\n\n// Compare mode shows a bounded top-K per column — a scannable snapshot, not a\n// paginated surface. Drilling into a value (focus) is where deep paging lives.\nexport const COMPARE_TOP_K = 15;\n\n// One shared column template — dot · identifier · timeline · clock — applied to\n// the header AND every row so they line up exactly, whatever the facet value's\n// length (the identifier cell center-ellipsizes to stay in its track). Time\n// values are demoted to the clock's hover title, never a column of their own.\nconst ROW_GRID = 'grid grid-cols-[0.6rem_7rem_minmax(2rem,1fr)_1rem] items-center gap-2.5';\n\n// Focus / single-list paging: a standard set of sizes.\nexport const PAGE_SIZES = [25, 50, 100] as const;\nexport const DEFAULT_PAGE_SIZE = 50;\n\n/**\n * One entity row: a filled dot in the current-state color (its label is the\n * hover title, not repeated as text), the id center-ellipsized so the trailing\n * digits stay readable, the dwell timeline that fills the cell, the tracked\n * total. Click deep-links the entity's timeline panel; ⌘/ctrl-click jumps to\n * the all-queues escalation search for this facet value.\n */\nexport function EntityRowItem({\n facetKey,\n row,\n colors,\n stateLabel,\n onOpen,\n}: {\n /** The entity's metadata facet (e.g. serialNumber) — the ⌘-click search key. */\n facetKey: string;\n row: EntityRow;\n colors: Map<string, string>;\n stateLabel: (state: string | undefined) => string;\n onOpen: (value: string) => void;\n}) {\n const navigate = useNavigate();\n const activate = (e: { metaKey: boolean; ctrlKey: boolean }) => {\n if (e.metaKey || e.ctrlKey) {\n navigate(metadataFacetUrl(facetKey, row.value));\n return;\n }\n onOpen(row.value);\n };\n return (\n <div\n role=\"button\"\n tabIndex={0}\n onClick={activate}\n onKeyDown={(e) => { if (e.key === 'Enter') activate(e); }}\n className={`${ROW_GRID} text-2xs cursor-pointer group py-0.5`}\n >\n <span\n className=\"w-2 h-2 rounded-full justify-self-center\"\n style={{ backgroundColor: row.nowState ? colors.get(row.nowState) : 'transparent' }}\n title={row.nowState ? stateLabel(row.nowState) : 'no current state'}\n />\n <CenterEllipsis\n text={row.value}\n className=\"font-mono text-text-secondary group-hover:text-accent transition-colors\"\n />\n <StateBand groups={row.groups} colors={colors} height=\"h-1.5\" className=\"min-w-[2rem]\" />\n <button\n className=\"icon-link justify-self-center\"\n title={`${formatDurationCompact(row.total * 1000)} tracked · open timeline · ⌘-click row searches every queue`}\n onClick={(e) => { e.stopPropagation(); onOpen(row.value); }}\n >\n <History className=\"w-3 h-3\" />\n </button>\n </div>\n );\n}\n\n/**\n * A presentational column: an optional header (a slice value's own timeline,\n * clickable to focus that value), the entity rows, and an optional \"more\"\n * affordance that drills into the value's full, paginated list.\n */\nfunction EntityColumnView({\n facetKey,\n sliced,\n header,\n rows,\n colors,\n stateLabel,\n onOpen,\n onTarget,\n hasMore,\n emptyText,\n}: {\n facetKey: string;\n sliced: boolean;\n header?: { value: string; groups: AggregateRow[]; total: number };\n rows: EntityRow[];\n colors: Map<string, string>;\n stateLabel: (state: string | undefined) => string;\n onOpen: (value: string) => void;\n onTarget?: (value: string) => void;\n hasMore?: boolean;\n emptyText?: string;\n}) {\n return (\n <div className={sliced ? 'w-72 shrink-0' : 'flex-1 max-w-3xl'}>\n {header && (\n <button\n type=\"button\"\n onClick={() => onTarget?.(header.value)}\n className={`${ROW_GRID} w-full text-left mb-2 group`}\n >\n {/* empty dot slot — keeps the header's identifier aligned with rows */}\n <span aria-hidden />\n <CenterEllipsis\n text={header.value}\n className=\"font-mono text-xs font-medium text-text-primary group-hover:text-accent transition-colors\"\n />\n {/* thicker band — the value's whole state timeline */}\n <StateBand groups={header.groups} colors={colors} height=\"h-2.5\" className=\"min-w-[2rem]\" />\n <span\n className=\"icon-link justify-self-center\"\n title={`${formatDurationCompact(header.total * 1000)} total in ${header.value} — the band shows the state split`}\n >\n <Clock className=\"w-3 h-3\" />\n </span>\n </button>\n )}\n {rows.length === 0 ? (\n <p className=\"text-2xs text-text-quaternary\">{emptyText ?? 'No entities on this page.'}</p>\n ) : (\n <div className=\"space-y-0.5\">\n {rows.map((row) => (\n <EntityRowItem key={row.value} facetKey={facetKey} row={row} colors={colors} stateLabel={stateLabel} onOpen={onOpen} />\n ))}\n </div>\n )}\n {hasMore && header && onTarget && (\n <button\n type=\"button\"\n onClick={() => onTarget(header.value)}\n className=\"mt-2 inline-flex items-center gap-1 text-2xs text-accent hover:text-accent-hover transition-colors\"\n >\n More <ArrowRight className=\"w-3 h-3\" />\n </button>\n )}\n </div>\n );\n}\n\n/**\n * One compare-mode column. Fetches the value's own top-K entities (dwell-ranked)\n * plus their state splits and current states — a bounded, self-contained pull,\n * cheap because a categorical facet has few values. Its header is the value's\n * whole timeline (passed from the slice aggregate); \"More\" drills into focus.\n */\nexport function SliceColumnLoader({\n entityKey,\n sliceKey,\n value,\n headerGroups,\n headerTotal,\n window,\n find,\n colors,\n stateLabel,\n onOpen,\n onTarget,\n}: {\n entityKey: string;\n sliceKey: string;\n value: string;\n headerGroups: AggregateRow[];\n headerTotal: number;\n window: AnalyticsWindow;\n find: string | null;\n colors: Map<string, string>;\n stateLabel: (state: string | undefined) => string;\n onOpen: (value: string) => void;\n onTarget: (value: string) => void;\n}) {\n // Scope by exact text match on the facet — the value came from the aggregate\n // as text, and `equals` round-trips it (a jsonb-containment anyOf would need\n // the native bool/number the text projection has already dropped).\n const scope = { entity: entityKey, equals: { [sliceKey]: value } };\n const rank = useAggregateByFacets({\n query: { ...scope, ...(find ? { prefix: { [entityKey]: find } } : {}) },\n groupBy: { facets: [entityKey] },\n measure: { kind: 'dwell', window },\n orderBy: [{ field: 'dwellSeconds', direction: 'desc' }],\n limit: COMPARE_TOP_K,\n });\n const pageValues = useMemo(\n () => entityValues(rank.data?.groups ?? [], entityKey),\n [rank.data, entityKey],\n );\n const anyOf = pageValues.map((v) => ({ [entityKey]: v }));\n const states = useAggregateByFacets(\n pageValues.length\n ? { query: { entity: entityKey, anyOf }, groupBy: { state: true, facets: [entityKey] }, measure: { kind: 'dwell', window }, limit: COMPARE_TOP_K * 4 }\n : null,\n );\n const now = useAggregateByFacets(\n pageValues.length\n ? { query: { entity: entityKey, anyOf }, groupBy: { state: true, facets: [entityKey] }, measure: { kind: 'membership' } }\n : null,\n );\n const rows = useMemo(\n () => pivotEntities(rank.data?.groups ?? [], states.data?.groups ?? [], now.data?.groups ?? [], entityKey),\n [rank.data, states.data, now.data, entityKey],\n );\n\n return (\n <EntityColumnView\n facetKey={entityKey}\n sliced\n header={{ value, groups: headerGroups, total: headerTotal }}\n rows={rows}\n colors={colors}\n stateLabel={stateLabel}\n onOpen={onOpen}\n onTarget={onTarget}\n hasMore={rank.data?.overflow ?? false}\n />\n );\n}\n\n/** A single wide column — the unsliced ranking or a focused value's paged list. */\nexport function SingleColumn({\n facetKey,\n rows,\n colors,\n stateLabel,\n onOpen,\n emptyText,\n}: {\n /** The entity's metadata facet — the ⌘-click search key on each row. */\n facetKey: string;\n rows: EntityRow[];\n colors: Map<string, string>;\n stateLabel: (state: string | undefined) => string;\n onOpen: (value: string) => void;\n emptyText?: string;\n}) {\n return (\n <EntityColumnView\n facetKey={facetKey}\n sliced={false}\n rows={rows}\n colors={colors}\n stateLabel={stateLabel}\n onOpen={onOpen}\n emptyText={emptyText}\n />\n );\n}\n","import { useEffect, useMemo, useRef, useState } from 'react';\nimport { ChevronLeft } from 'lucide-react';\nimport type { RoleDetail } from '../../api/roles';\nimport {\n useAggregateByFacets,\n useAnalyticsWindow,\n isForbidden,\n type TimelineInterval,\n} from '../../api/escalation-analytics';\nimport { useFacetKeys } from '../../api/escalations';\nimport { EntityTimelinePanel } from '../../components/escalation/EntityTimelinePanel';\nimport { useShellPanelOptional } from '../../hooks/useShellPanel';\nimport { assignLabelColors } from './mix-colors';\nimport { displayRoleTitle } from '../../lib/role-display';\nimport { formatDurationCompact } from '../../lib/format';\nimport { StateBand } from './StateBands';\nimport {\n SliceColumnLoader,\n SingleColumn,\n PAGE_SIZES,\n DEFAULT_PAGE_SIZE,\n} from './EntityColumns';\nimport { entityValues, pivotEntities, totalDwell, rankSliceValues } from './entity-pivot';\n\n// Shared shell-panel slot key — the entity timeline claims/releases this slot.\nconst TIMELINE_PANEL_KEY = 'entity-timeline';\n// The find input debounces into the URL-backed find term.\nconst FIND_DEBOUNCE_MS = 300;\n// A slice with more discrete values than this is not really categorical — cap\n// the columns and say so, rather than sprawl.\nconst SLICE_VALUE_CAP = 12;\n\n/**\n * The entity lens — the Operations page flipped station-first → entity-first.\n * One lens per entity facet the visible roles declare; roles sharing the key\n * form the entity's SYSTEM. Three intents, all URL-backed so a link (or the\n * upper-right bookmark) reproduces the exact view:\n *\n * plain — one dwell-ranked, paginated list of the whole system\n * compare — pick a categorical facet (?slice=): one column per value, each a\n * bounded top-K snapshot with its own header timeline; no paging\n * focus — target one value (?sliceValue=): that value's full paginated\n * list, where deep paging finally reads sanely\n *\n * Categorical metadata makes this efficient: the slice groups on a low-\n * cardinality key (few columns), and only the entity id — the unbounded axis —\n * is ever paged.\n */\nexport function EntityLensView({\n entityKey,\n periodHours,\n roles,\n find,\n onFindChange,\n entityValue,\n onEntityChange,\n sliceKey: sliceKeyProp = null,\n onSliceKeyChange,\n sliceValue = null,\n onSliceValueChange,\n}: {\n entityKey: string;\n periodHours: number;\n roles: RoleDetail[];\n /** Debounced find term (?find=) — a case-insensitive prefix on the entity key. */\n find: string | null;\n onFindChange: (term: string | null) => void;\n /** Deep-linked entity (?entity=) — the timeline panel follows this value. */\n entityValue: string | null;\n onEntityChange: (value: string | null) => void;\n /** The chosen categorical facet (?slice=). Null/'' = no slice (plain). */\n sliceKey?: string | null;\n onSliceKeyChange?: (key: string | null) => void;\n /** The targeted slice value (?sliceValue=). Set = focus on that one value. */\n sliceValue?: string | null;\n onSliceValueChange?: (value: string | null) => void;\n}) {\n const window = useAnalyticsWindow(periodHours);\n const shell = useShellPanelOptional();\n const sliceKey = sliceKeyProp ?? '';\n const sliced = !!sliceKey;\n const focused = sliced && !!sliceValue;\n const compare = sliced && !sliceValue;\n\n const [page, setPage] = useState(0);\n const [pageSize, setPageSize] = useState<number>(DEFAULT_PAGE_SIZE);\n\n // A page only means anything within one query shape — reset with it.\n useEffect(() => {\n setPage(0);\n }, [find, window.from, window.to, entityKey, sliceKey, sliceValue, pageSize]);\n\n // Find input: local state debounced into the URL-backed term (?find=).\n const [findInput, setFindInput] = useState(find ?? '');\n const findDebounce = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n useEffect(() => () => clearTimeout(findDebounce.current), []);\n useEffect(() => { setFindInput(find ?? ''); }, [find]);\n const handleFindInput = (value: string) => {\n setFindInput(value);\n clearTimeout(findDebounce.current);\n findDebounce.current = setTimeout(() => {\n const term = value.trim();\n onFindChange(term ? term : null);\n }, FIND_DEBOUNCE_MS);\n };\n\n const roleTitles = useMemo(() => {\n const map = new Map<string, string>();\n for (const r of roles) map.set(r.role, displayRoleTitle(r));\n return map;\n }, [roles]);\n const stateLabel = (state: string | undefined) =>\n state == null ? '—' : roleTitles.get(state) ?? state;\n\n // Counts-only (public under the board flag): the system's state bands.\n const stateDwell = useAggregateByFacets({\n query: { entity: entityKey },\n groupBy: { state: true },\n measure: { kind: 'dwell', window },\n orderBy: [{ field: 'dwellSeconds', direction: 'desc' }],\n });\n const stateNow = useAggregateByFacets({\n query: { entity: entityKey },\n groupBy: { state: true },\n measure: { kind: 'membership' },\n });\n const entityCount = useAggregateByFacets({\n query: { entity: entityKey },\n groupBy: {},\n measure: { kind: 'membership' },\n distinctBy: entityKey,\n });\n\n // Facet-grouped (strict read gate): the categorical slice — column values +\n // each value's header timeline. Runs whenever a slice is chosen.\n const slice = useAggregateByFacets(\n sliced\n ? {\n query: { entity: entityKey },\n groupBy: { state: true, facets: [sliceKey] },\n measure: { kind: 'dwell', window },\n limit: 200,\n }\n : null,\n );\n\n // The paginated ranking — plain and focus only (compare fetches per column).\n // Focus scopes to the targeted value with a single-element anyOf (equality).\n const pagedActive = !compare;\n const perEntity = useAggregateByFacets(\n pagedActive\n ? {\n query: {\n entity: entityKey,\n // Focus scopes to the targeted value by exact text match (the value\n // came from the aggregate as text; equals round-trips every scalar).\n ...(focused ? { equals: { [sliceKey]: sliceValue as string } } : {}),\n ...(find ? { prefix: { [entityKey]: find } } : {}),\n },\n groupBy: { facets: [entityKey] },\n measure: { kind: 'dwell', window },\n orderBy: [{ field: 'dwellSeconds', direction: 'desc' }],\n limit: pageSize,\n offset: page * pageSize,\n }\n : null,\n );\n const pageValues = useMemo(\n () => entityValues(perEntity?.data?.groups ?? [], entityKey),\n [perEntity?.data, entityKey],\n );\n const pageScope = pageValues.length\n ? { entity: entityKey, anyOf: pageValues.map((v) => ({ [entityKey]: v })) }\n : null;\n const perEntityStates = useAggregateByFacets(\n pageScope\n ? {\n query: pageScope,\n groupBy: { state: true, facets: [entityKey] },\n measure: { kind: 'dwell', window },\n limit: pageSize * 10,\n }\n : null,\n );\n const perEntityNow = useAggregateByFacets(\n pageScope\n ? { query: pageScope, groupBy: { state: true, facets: [entityKey] }, measure: { kind: 'membership' } }\n : null,\n );\n const entityRows = useMemo(\n () =>\n pivotEntities(\n perEntity?.data?.groups ?? [],\n perEntityStates.data?.groups ?? [],\n perEntityNow.data?.groups ?? [],\n entityKey,\n ),\n [perEntity?.data, perEntityStates.data, perEntityNow.data, entityKey],\n );\n\n // Color resolver handed to the timeline panel so its interval dots use the\n // EXACT colors of this graphic's band — same map, same state derivation. A\n // ref keeps it fresh (colors load after the panel may have opened) while the\n // identity stays stable, so the panel is set once and never re-mounted.\n const intervalColorRef = useRef<(iv: TimelineInterval) => string | undefined>(() => undefined);\n const intervalColor = useRef((iv: TimelineInterval) => intervalColorRef.current(iv)).current;\n\n // ── ?entity= ↔ timeline panel sync ──────────────────────────────────────────\n const appliedEntity = useRef<string | null>(null);\n const panelWasOpen = useRef(false);\n useEffect(() => {\n if (!shell) return;\n if (entityValue === appliedEntity.current) return;\n appliedEntity.current = entityValue;\n if (entityValue) {\n shell.setPanel(\n <EntityTimelinePanel facetKey={entityKey} value={entityValue} entity={entityKey} intervalColor={intervalColor} />,\n { key: TIMELINE_PANEL_KEY, width: 420 },\n );\n } else {\n panelWasOpen.current = false;\n shell.closePanel(TIMELINE_PANEL_KEY);\n }\n }, [entityValue, entityKey, shell]);\n useEffect(() => {\n if (!shell || !entityValue) return;\n if (shell.open && shell.ownerKey === TIMELINE_PANEL_KEY) {\n panelWasOpen.current = true;\n return;\n }\n if (panelWasOpen.current) {\n panelWasOpen.current = false;\n onEntityChange(null);\n }\n }, [shell, entityValue, onEntityChange]);\n const shellRef = useRef(shell);\n shellRef.current = shell;\n useEffect(\n () => () => {\n if (appliedEntity.current) shellRef.current?.closePanel(TIMELINE_PANEL_KEY);\n },\n [],\n );\n\n const { data: facetKeyData } = useFacetKeys();\n const sliceOptions = useMemo(\n () => ((facetKeyData?.keys as string[] | undefined) ?? []).filter((k) => k !== entityKey),\n [facetKeyData, entityKey],\n );\n\n const dwellGroups = (stateDwell.data?.groups ?? []).filter((g) => (g.dwellSeconds ?? 0) > 0);\n const colors = useMemo(\n () =>\n assignLabelColors(\n [...dwellGroups, ...(stateNow.data?.groups ?? [])].map((g) => ({\n label: g.state ?? '—',\n weight: g.dwellSeconds ?? g.count ?? 0,\n })),\n ),\n [dwellGroups, stateNow.data],\n );\n const nowByState = new Map((stateNow.data?.groups ?? []).map((g) => [g.state ?? '—', g.count ?? 0]));\n const tracked = entityCount.data?.groups[0]?.count ?? null;\n\n // Keep the panel's color resolver current. State derivation mirrors the\n // server's stateExpr: subtype-sourced roles are COALESCE(subtype, role),\n // everyone else IS their role — the same key the `colors` map is built on.\n const subtypeSourcedRoles = useMemo(\n () => new Set(roles.filter((r) => r.entity_state_source === 'subtype').map((r) => r.role)),\n [roles],\n );\n intervalColorRef.current = (iv) => {\n const state = subtypeSourcedRoles.has(iv.role) ? (iv.subtype ?? iv.role) : iv.role;\n return colors.get(state);\n };\n\n // Compare columns: the ranked slice values (bounded — a too-big facet is a smell).\n const rankedSlices = useMemo(\n () => (sliced ? rankSliceValues(slice.data?.groups ?? [], sliceKey, SLICE_VALUE_CAP) : []),\n [sliced, slice.data, sliceKey],\n );\n const distinctSliceValues = useMemo(() => {\n const set = new Set<string>();\n for (const g of slice.data?.groups ?? []) {\n if ((g.dwellSeconds ?? 0) > 0 && g.facets[sliceKey] != null) set.add(g.facets[sliceKey] as string);\n }\n return set.size;\n }, [slice.data, sliceKey]);\n\n // Focused value's own timeline (for the breadcrumb band).\n const focusedBand = useMemo(() => {\n if (!focused) return { groups: [], total: 0 };\n const groups = (slice.data?.groups ?? []).filter((g) => g.facets[sliceKey] === sliceValue);\n return { groups, total: totalDwell(groups) };\n }, [focused, slice.data, sliceKey, sliceValue]);\n\n const overflow = perEntity?.data?.overflow ?? false;\n const perEntityForbidden = isForbidden(perEntity?.error);\n const sliceForbidden = sliced && isForbidden(slice.error);\n\n return (\n <div className=\"flex-1 min-h-0 flex flex-col overflow-hidden\">\n {/* ── Top bar: the system band shares the row with the slice + find controls ── */}\n <div className=\"shrink-0 px-2 pt-4 pb-3 flex items-start gap-6 border-b border-surface-border/40\">\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-baseline justify-between gap-4 mb-2.5\">\n <p className=\"text-2xs font-semibold uppercase tracking-widest text-text-tertiary\">\n Where the time went · <span className=\"normal-case font-mono\">{entityKey}</span> system\n </p>\n {tracked != null && (\n <p className=\"text-2xs text-text-quaternary whitespace-nowrap\">\n <span className=\"text-xs font-mono font-semibold text-text-primary tabular-nums\">{tracked}</span>{' '}\n <span className=\"font-mono\">{entityKey}</span> in queue now\n </p>\n )}\n </div>\n {dwellGroups.length > 0 ? (\n <>\n <StateBand groups={dwellGroups} colors={colors} height=\"h-3\" />\n {/* Dot + label only — the proportions are the band; specifics live on hover. */}\n <div className=\"flex flex-wrap gap-x-5 gap-y-1 mt-2.5\">\n {dwellGroups.map((g) => {\n const now = nowByState.get(g.state ?? '—') ?? 0;\n const pct = Math.round(((g.dwellSeconds ?? 0) / totalDwell(dwellGroups)) * 100);\n const detail = `${formatDurationCompact((g.dwellSeconds ?? 0) * 1000)} · ${pct}%${now > 0 ? ` · ${now} now` : ''}`;\n return (\n <span key={g.state} className=\"flex items-center gap-1.5 text-2xs\" title={detail}>\n <span className=\"w-2 h-2 rounded-full shrink-0\" style={{ backgroundColor: colors.get(g.state ?? '—') }} />\n <span className=\"font-mono text-text-secondary\">{stateLabel(g.state)}</span>\n </span>\n );\n })}\n </div>\n </>\n ) : (\n <p className=\"text-2xs text-text-quaternary\">No tracked time in this window.</p>\n )}\n </div>\n\n {/* Slice + find — the band no longer runs full width. */}\n <div className=\"shrink-0 w-56 space-y-2.5\">\n <label className=\"block\">\n <span className=\"block text-2xs font-semibold uppercase tracking-widest text-text-tertiary mb-1\">Slice by</span>\n <select\n value={sliceKey}\n onChange={(e) => onSliceKeyChange?.(e.target.value || null)}\n className=\"select text-xs font-mono w-full\"\n >\n <option value=\"\">— none —</option>\n {sliceOptions.map((k) => <option key={k} value={k}>{k}</option>)}\n </select>\n </label>\n <input\n type=\"text\"\n value={findInput}\n onChange={(e) => handleFindInput(e.target.value)}\n placeholder={`Find by ${entityKey}…`}\n aria-label={`Find by ${entityKey}`}\n className=\"w-full bg-transparent border-b border-surface-border/60 focus:border-accent focus:outline-none text-xs font-mono text-text-primary placeholder:text-text-quaternary pb-0.5 transition-colors\"\n />\n </div>\n </div>\n\n {/* ── Focus breadcrumb: the targeted value's timeline + a way back to compare ── */}\n {focused && (\n <div className=\"shrink-0 px-2 pt-3 flex items-center gap-3\">\n <button\n type=\"button\"\n onClick={() => onSliceValueChange?.(null)}\n className=\"inline-flex items-center gap-1 text-2xs text-accent hover:text-accent-hover transition-colors shrink-0\"\n >\n <ChevronLeft className=\"w-3 h-3\" /> all {sliceKey}\n </button>\n <span className=\"font-mono text-xs text-text-primary shrink-0\">{sliceValue}</span>\n <StateBand groups={focusedBand.groups} colors={colors} height=\"h-2\" className=\"flex-1 max-w-md\" />\n <span className=\"font-mono tabular-nums text-2xs text-text-tertiary shrink-0\">\n {formatDurationCompact(focusedBand.total * 1000)}\n </span>\n </div>\n )}\n\n {/* ── The columns — compare (one per value) or a single wide list ── */}\n <div className=\"flex-1 min-h-0 overflow-auto px-2 py-4\">\n {compare ? (\n sliceForbidden ? (\n <p className=\"text-2xs text-text-quaternary\">Slicing requires full read access to the system's queues.</p>\n ) : rankedSlices.length === 0 ? (\n <p className=\"text-2xs text-text-quaternary\">No tracked time for this slice in the window.</p>\n ) : (\n <>\n <div className=\"flex gap-6 min-w-max\">\n {rankedSlices.map((s) => (\n <SliceColumnLoader\n key={s.value}\n entityKey={entityKey}\n sliceKey={sliceKey}\n value={s.value}\n headerGroups={s.groups}\n headerTotal={s.total}\n window={window}\n find={find}\n colors={colors}\n stateLabel={stateLabel}\n onOpen={onEntityChange}\n onTarget={(v) => onSliceValueChange?.(v)}\n />\n ))}\n </div>\n {distinctSliceValues > SLICE_VALUE_CAP && (\n <p className=\"text-2xs text-text-quaternary pt-4\">\n Showing the top {SLICE_VALUE_CAP} of {distinctSliceValues} <span className=\"font-mono\">{sliceKey}</span> values —\n a facet this wide isn't a good slice dimension.\n </p>\n )}\n </>\n )\n ) : perEntityForbidden ? (\n <p className=\"text-2xs text-text-quaternary\">\n The per-entity view requires full read access to the system's queues.\n </p>\n ) : (\n <SingleColumn\n facetKey={entityKey}\n rows={entityRows}\n colors={colors}\n stateLabel={stateLabel}\n onOpen={onEntityChange}\n emptyText={find ? `No ${entityKey} starts with “${find}” in this window.` : 'No entities tracked in this window.'}\n />\n )}\n </div>\n\n {/* ── Pager — persistent in the paginated contexts (plain + focus), not compare ── */}\n {!compare && (\n <div className=\"shrink-0 border-t border-surface-border bg-surface/95 px-2 pt-2 pb-3 flex items-center gap-3 text-2xs\">\n <button\n disabled={page === 0}\n onClick={() => setPage(page - 1)}\n className=\"text-text-tertiary hover:text-accent transition-colors disabled:opacity-40 disabled:hover:text-text-tertiary\"\n >\n Prev\n </button>\n <span className=\"font-mono tabular-nums text-text-quaternary\">page {page + 1}</span>\n <button\n disabled={!overflow}\n onClick={() => setPage(page + 1)}\n className=\"text-text-tertiary hover:text-accent transition-colors disabled:opacity-40 disabled:hover:text-text-tertiary\"\n >\n Next\n </button>\n <span className=\"ml-auto flex items-center gap-1.5 text-text-quaternary\">\n <span>per page</span>\n <select\n value={pageSize}\n onChange={(e) => setPageSize(Number(e.target.value))}\n aria-label=\"Results per page\"\n className=\"select text-2xs font-mono py-0.5\"\n >\n {PAGE_SIZES.map((n) => <option key={n} value={n}>{n}</option>)}\n </select>\n </span>\n </div>\n )}\n </div>\n );\n}\n","import { useEffect, useRef, useState } from 'react';\nimport { ChevronDown } from 'lucide-react';\nimport { useAggregateByFacets } from '../../api/escalation-analytics';\n\n/**\n * The board's view selector — the station view and every declared entity\n * system behind ONE compact menu (the sequence-menu pattern), never one\n * piece of chrome per system: a deployment declaring a dozen entity facets\n * gets a twelve-row list, not a twelve-chip strip.\n *\n * Each lens row carries its live distinct-entity count, fetched lazily only\n * while the menu is open (counts-only — the station-metrics data class, so\n * the rows render under the public board flag too).\n */\nexport function ViewMenu({ lenses, activeLens, stationCount, onSelect }: {\n lenses: string[];\n /** null = the station view. */\n activeLens: string | null;\n stationCount: number;\n onSelect: (lens: string | null) => void;\n}) {\n const [open, setOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!open) return;\n const onClick = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false);\n };\n const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') setOpen(false); };\n document.addEventListener('mousedown', onClick);\n document.addEventListener('keydown', onKey);\n return () => {\n document.removeEventListener('mousedown', onClick);\n document.removeEventListener('keydown', onKey);\n };\n }, [open]);\n\n const choose = (lens: string | null) => {\n onSelect(lens);\n setOpen(false);\n };\n\n return (\n <div\n ref={ref}\n className=\"relative\"\n title=\"View: the board station-first, or an entity system (roles sharing an entity facet) entity-first\"\n >\n <button\n type=\"button\"\n onClick={() => setOpen((v) => !v)}\n className=\"group flex items-baseline gap-1.5\"\n aria-expanded={open}\n aria-haspopup=\"listbox\"\n aria-label=\"Board view\"\n >\n <span className=\"text-2xs uppercase tracking-widest text-text-quaternary\">View</span>\n <span className=\"text-xs font-medium text-text-primary group-hover:text-accent transition-colors\">\n {activeLens ? <>by <span className=\"font-mono\">{activeLens}</span></> : 'Stations'}\n </span>\n <ChevronDown\n className={`w-3 h-3 self-center shrink-0 text-text-tertiary group-hover:text-accent transition-transform ${open ? 'rotate-180' : ''}`}\n strokeWidth={1.5}\n />\n </button>\n\n {open && (\n <div\n role=\"listbox\"\n className=\"absolute z-[100] top-full right-0 mt-1.5 min-w-[16rem] max-h-80 overflow-y-auto bg-surface-raised border border-surface-border rounded-md shadow-lg py-1\"\n >\n <ViewOption\n label=\"Stations\"\n note={`${stationCount} station${stationCount === 1 ? '' : 's'}`}\n active={activeLens === null}\n onClick={() => choose(null)}\n />\n {lenses.map((lens) => (\n <LensOption\n key={lens}\n lens={lens}\n active={activeLens === lens}\n fetchCount={open}\n onClick={() => choose(lens)}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\nfunction ViewOption({ label, note, active, onClick, mono }: {\n label: string;\n note: string | null;\n active: boolean;\n onClick: () => void;\n mono?: boolean;\n}) {\n return (\n <button\n type=\"button\"\n role=\"option\"\n aria-selected={active}\n onClick={onClick}\n className={`w-full text-left px-3 py-1.5 flex items-baseline gap-2.5 transition-colors ${\n active ? 'text-accent bg-accent/5' : 'text-text-primary hover:bg-surface-hover'\n }`}\n >\n <span className={`text-xs font-medium truncate ${mono ? 'font-mono' : ''}`}>{label}</span>\n {note && (\n <span className=\"ml-auto text-2xs font-mono text-text-quaternary tabular-nums shrink-0\">{note}</span>\n )}\n </button>\n );\n}\n\n/** One lens row — its live distinct-entity count loads only while the menu is open. */\nfunction LensOption({ lens, active, fetchCount, onClick }: {\n lens: string;\n active: boolean;\n fetchCount: boolean;\n onClick: () => void;\n}) {\n const count = useAggregateByFacets(\n {\n query: { entity: lens },\n groupBy: {},\n measure: { kind: 'membership' },\n distinctBy: lens,\n },\n { enabled: fetchCount },\n );\n const n = count.data?.groups[0]?.count;\n return (\n <ViewOption\n label={`by ${lens}`}\n mono\n note={n != null ? `${n} in queue` : null}\n active={active}\n onClick={onClick}\n />\n );\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 /** Cmd/meta+click on a resolved dot — navigate to the role's full queue. */\n onCmdClick?: (role: string) => void;\n /** Selected window length in hours — target count = target_per_hour × this. */\n periodHours: number;\n /** Use a logarithmic Y axis. Reveals shape across a wide dynamic range (7d/30d). */\n logScale?: boolean;\n /** Fill the parent container — SVG uses h-full + preserveAspectRatio meet.\n Default: auto-height (scales by width). Use when the parent has a defined height. */\n fill?: boolean;\n}\n\n// ── SVG layout ────────────────────────────────────────────────────────────────\n\nconst W = 800;\nconst H = 270;\nconst ML = 28;\nconst MR = 60;\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/** Nice round tick values for a logarithmic Y axis up to maxVal. */\nfunction logTicks(maxVal: number): number[] {\n const candidates = [1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000];\n return candidates.filter((v) => v > 0 && v < maxVal * 0.98);\n}\n\n/** Nice round tick values for a linear Y axis up to maxVal. */\nfunction linearTicks(maxVal: number): number[] {\n const raw = [0.25, 0.5, 0.75].map((f) => Math.round(f * maxVal));\n return raw.filter((v) => v > 0);\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. Each hue resolves through\n// a --lt-* theme token so registered themes (including dark) restyle the\n// chart; the navy default keeps the original sky/orange/green/slate look.\nexport const ACTIVE_COLOR = 'rgb(var(--lt-status-claimed-graphic))'; // claimed, being worked right now — orange\nexport const QUEUED_COLOR = 'rgb(var(--lt-status-queued-graphic))'; // pending and unclaimed, waiting in the queue — sky\nexport const RESOLVED_COLOR = 'rgb(var(--lt-status-success-graphic))'; // done — green\nexport const TARGET_COLOR = 'rgb(var(--lt-text-quaternary))'; // target pace line — muted gray\n\n// Priority — unclaimed items past the role's age threshold, the count the\n// floor pulls to the front of the rack.\n// Jeopardy shares one red across the product (the pill, the table sub-row,\n// this chart's badge) — the hard-limit alarm, distinct from every pace hue.\nexport const PRIORITY_COLOR = 'rgb(var(--lt-status-error))';\nexport const PRIORITY_TEXT_COLOR = 'rgb(var(--lt-status-error))';\n\n/** Translucent tint of a token-based `rgb(var(--…))` color, for band fills. */\nexport function withAlpha(color: string, alpha: number): string {\n return color.replace(/\\)$/, ` / ${alpha})`);\n}\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, onCmdClick, periodHours, logScale = false, fill = false }: 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\n const yScale = logScale\n ? (v: number) => {\n const logMax = Math.log(1 + maxVal);\n return MT + chartH * (1 - Math.log(1 + Math.max(0, v)) / logMax);\n }\n : (v: number) => MT + chartH * (1 - Math.max(0, Math.min(v, maxVal)) / maxVal);\n\n const gridTicks = logScale ? logTicks(maxVal) : linearTicks(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\n viewBox={`0 0 ${W} ${H}`}\n className={fill ? 'w-full h-full' : 'w-full'}\n preserveAspectRatio=\"xMidYMid meet\"\n style={{ display: 'block', ...(fill ? {} : { height: 'auto' }) }}\n >\n {/* Y-axis reference lines — very faint horizontal marks that communicate\n the scale. Log mode uses dashed lines at round values; linear uses\n solid hairlines at even fractions. */}\n {gridTicks.map((v) => {\n const gy = yScale(v);\n return (\n <g key={`grid-${v}`}>\n <line\n x1={ML}\n y1={gy}\n x2={right}\n y2={gy}\n className=\"stroke-surface-border\"\n strokeWidth={0.5}\n opacity={logScale ? 0.45 : 0.3}\n strokeDasharray={logScale ? '2 5' : undefined}\n style={{ transition: `y1 ${EASE}, y2 ${EASE}` }}\n />\n <text\n x={ML - 4}\n y={gy + 2.5}\n textAnchor=\"end\"\n fontSize={6}\n fontFamily=\"ui-monospace, monospace\"\n opacity={0.35}\n className=\"fill-text-quaternary\"\n >\n {compact(v)}\n </text>\n </g>\n );\n })}\n\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} className=\"stroke-surface-border\" strokeWidth={0.75} />;\n })}\n\n {/* Area under the actual curve */}\n {areaPath && <path d={areaPath} opacity={0.05} style={{ fill: RESOLVED_COLOR, 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} opacity={0.12} style={{ fill: ACTIVE_COLOR, transition: `d ${EASE}` }} />\n )}\n {queuedBandPath && (\n <path d={queuedBandPath} opacity={0.12} style={{ fill: QUEUED_COLOR, transition: `d ${EASE}` }} />\n )}\n\n {/* Target — dashed reference curve at the window's expected count */}\n {targetLinePath && (\n <path d={targetLinePath} fill=\"none\" strokeWidth={0.75} strokeDasharray=\"2 3\" strokeLinecap=\"round\" opacity={0.7} style={{ stroke: TARGET_COLOR, 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} opacity={0.8} style={{ fill: TARGET_COLOR }} />\n <text\n y={-5}\n textAnchor=\"middle\"\n fontSize={6.5}\n fontFamily=\"ui-monospace, monospace\"\n fontWeight=\"500\"\n opacity={0.7}\n style={{ fill: TARGET_COLOR }}\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\" strokeWidth={0.75} strokeDasharray=\"2 3\" strokeLinecap=\"round\" opacity={0.55} style={{ stroke: QUEUED_COLOR, 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\" strokeWidth={0.75} strokeDasharray=\"2 3\" strokeLinecap=\"round\" opacity={0.5} style={{ stroke: ACTIVE_COLOR, transition: `d ${EASE}` }} />\n )}\n\n {/* Actual — thin solid, primary line */}\n {actualSplinePath && (\n <path d={actualSplinePath} fill=\"none\" strokeWidth={0.6} strokeLinejoin=\"round\" strokeLinecap=\"round\" opacity={0.65} style={{ stroke: RESOLVED_COLOR, 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 fontFamily=\"ui-monospace, monospace\"\n fontWeight=\"600\"\n style={{ fill: hasWaiting ? QUEUED_COLOR : 'rgb(var(--lt-text-tertiary))', 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} opacity={0.85} style={{ fill: ACTIVE_COLOR }} />\n {ap.active > 0 && (\n <text y={ar + 9} textAnchor=\"middle\" fontSize={7.5} fontFamily=\"ui-monospace, monospace\" fontWeight=\"600\" style={{ fill: ACTIVE_COLOR }}>\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} in jeopardy` : '');\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={(e) => {\n if (e.metaKey || e.ctrlKey) {\n e.stopPropagation();\n onCmdClick?.(s.role);\n } else {\n onSelect(s.role);\n }\n }}\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} opacity={0.9} style={{ fill: RESOLVED_COLOR, transition: `r ${EASE}` }} />\n {row.expected != null && (\n <text y={-r - 5} textAnchor=\"middle\" fontSize={9.5} fontFamily=\"ui-monospace, monospace\" fontWeight=\"500\" style={{ fill: RESOLVED_COLOR }}>\n {compact(row.actual)}\n </text>\n )}\n {isHovered && !isSelected && <circle r={r + 3} fill=\"none\" strokeWidth={1} opacity={0.4} style={{ stroke: RESOLVED_COLOR }} />}\n {isSelected && <circle r={r + 4} fill=\"none\" className=\"stroke-accent\" strokeWidth={2} />}\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\" className=\"stroke-text-quaternary\" strokeWidth={1} strokeDasharray=\"2 2\" strokeLinecap=\"round\" />\n <path d=\"M 0 -2 L 8 -2\" className=\"stroke-text-quaternary\" strokeWidth={1} strokeLinecap=\"round\" />\n <path d=\"M 8 -2 l -3.5 -2 v 4 z\" className=\"fill-text-quaternary\" />\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 className=\"fill-text-tertiary\"\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} className=\"fill-text-primary\" opacity={0.88} />\n <text x={tipX} y={tipY - 3} textAnchor=\"middle\" fontSize={8.5} className=\"fill-surface\" 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} className=\"fill-text-quaternary\" 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 fontFamily=\"ui-sans-serif, sans-serif\"\n fontWeight={l.key === 'actual' ? 700 : 500}\n opacity={l.key === 'active' ? 0.85 : 1}\n style={{ fill: l.color, transition: `y ${EASE}` }}\n >\n {l.text}\n </text>\n ))}\n </svg>\n );\n}\n","import type { RoleDetail } from '../../api/roles';\n\n/**\n * The jeopardy deep link — the plant manager's \"focus on exactly these n items\".\n * One builder for every jeopardy pill (Pace Board chart, Home mini board, the\n * operator's Task Queue cards), producing a URL that reproduces the pill's set\n * precisely:\n *\n * - `jeopardy=1` — the server-side threshold predicate (the SAME expression\n * that produced the pill's count), so the list total equals the pill.\n * - `orderBy` on the role's age origin, ascending — oldest first. The metadata\n * facet when configured, else created_at; the sort control labels the field.\n * - `view=table` — a discrete, countable list, never the timeline.\n */\nexport function jeopardyQueueLink(role: Pick<RoleDetail, 'role' | 'priority_facet'>): string {\n const field = role.priority_facet ? `metadata.${role.priority_facet}` : 'created_at';\n const orderBy = JSON.stringify([{ field, direction: 'asc' }]);\n return `/escalations/available?role=${encodeURIComponent(role.role)}&jeopardy=1&view=table&orderBy=${encodeURIComponent(orderBy)}`;\n}\n","import { useMemo, useState } from 'react';\nimport { useSearchParams } from 'react-router-dom';\nimport { History, ChevronRight, ChevronDown, ArrowUpRight } from 'lucide-react';\nimport type { RoleDetail } from '../../api/roles';\nimport {\n useAggregateByFacets,\n useAnalyticsWindow,\n isForbidden,\n} from '../../api/escalation-analytics';\nimport { assignMixColors, subtypeKey, subtypeLabel } from './mix-colors';\nimport { formatDurationCompact } from '../../lib/format';\n\n/**\n * The station detail panel's analytics sections — the drill-down behind the\n * table's MIX bar:\n *\n * \"Where the time went\" dwell by subtype over the panel's window\n * \"In queue now\" live membership by subtype; with entity_facet, a\n * distinct-entity headline and a lazy per-entity\n * dwell list with timeline links\n *\n * Color assignment is shared across both sections so a subtype's dot means\n * the same thing in the bar and the queue list.\n */\nexport function StationAnalyticsSections({\n role,\n periodHours,\n onOpenEntity,\n}: {\n role: RoleDetail;\n periodHours: number;\n onOpenEntity: (facetKey: string, value: string) => void;\n}) {\n const window = useAnalyticsWindow(periodHours);\n const entityFacet = role.entity_facet;\n const [showEntities, setShowEntities] = useState(false);\n const [, setSearchParams] = useSearchParams();\n // The headline is the doorway to the entity lens — the board flipped\n // entity-first, where the whole system (not just this station) is the view.\n const openLens = () => {\n if (!entityFacet) return;\n setSearchParams((prev) => {\n const p = new URLSearchParams(prev);\n p.set('lens', entityFacet);\n return p;\n });\n };\n\n const dwell = useAggregateByFacets({\n query: { roles: [role.role] },\n groupBy: { columns: ['subtype'] },\n measure: { kind: 'dwell', window },\n orderBy: [{ field: 'dwellSeconds', direction: 'desc' }],\n });\n const queueNow = useAggregateByFacets({\n query: { roles: [role.role] },\n groupBy: { columns: ['subtype'] },\n measure: { kind: 'membership' },\n orderBy: [{ field: 'count', direction: 'desc' }],\n });\n const distinctEntities = useAggregateByFacets(\n entityFacet\n ? {\n query: { roles: [role.role] },\n groupBy: {},\n measure: { kind: 'membership' },\n distinctBy: entityFacet,\n }\n : null,\n );\n // Facet-grouped ⇒ always behind the strict read gate; fetched on disclosure.\n const perEntity = useAggregateByFacets(\n entityFacet && showEntities\n ? {\n query: { roles: [role.role], exists: [entityFacet] },\n groupBy: { facets: [entityFacet] },\n measure: { kind: 'dwell', window },\n orderBy: [{ field: 'dwellSeconds', direction: 'desc' }],\n limit: 8,\n }\n : null,\n );\n\n const colors = useMemo(\n () => assignMixColors([...(dwell.data?.groups ?? []), ...(queueNow.data?.groups ?? [])]),\n [dwell.data, queueNow.data],\n );\n\n if (isForbidden(dwell.error)) {\n return (\n <div className=\"border-t border-surface-border/40 pt-4 mt-5\">\n <p className=\"text-2xs text-text-quaternary\">\n Analytics require full read access to this station's queue.\n </p>\n </div>\n );\n }\n\n const dwellGroups = (dwell.data?.groups ?? []).filter((g) => (g.dwellSeconds ?? 0) > 0);\n const totalDwell = dwellGroups.reduce((sum, g) => sum + (g.dwellSeconds ?? 0), 0);\n const queueGroups = (queueNow.data?.groups ?? []).filter((g) => (g.count ?? 0) > 0);\n const entityCount = distinctEntities.data?.groups[0]?.count ?? null;\n\n return (\n <>\n {/* Where the time went — dwell mix over the panel's window */}\n <div className=\"border-t border-surface-border/40 pt-4 mt-5\">\n <p className=\"text-2xs font-semibold uppercase tracking-widest text-text-tertiary mb-2.5\">\n Where the time went\n </p>\n {totalDwell > 0 ? (\n <>\n <div className=\"h-2 flex rounded-full overflow-hidden bg-surface-sunken mb-2.5\">\n {dwellGroups.map((g) => (\n <div\n key={subtypeKey(g.subtype)}\n style={{\n width: `${((g.dwellSeconds ?? 0) / totalDwell) * 100}%`,\n backgroundColor: colors.get(subtypeKey(g.subtype)),\n }}\n />\n ))}\n </div>\n <div className=\"space-y-1\">\n {dwellGroups.map((g) => (\n <div key={subtypeKey(g.subtype)} className=\"flex items-center gap-2 text-2xs\">\n <span\n className=\"w-2 h-2 rounded-full shrink-0\"\n style={{ backgroundColor: colors.get(subtypeKey(g.subtype)) }}\n />\n <span\n className={`font-mono truncate flex-1 ${\n g.subtype ? 'text-text-secondary' : 'text-text-tertiary'\n }`}\n >\n {subtypeLabel(g.subtype)}\n </span>\n <span className=\"font-mono tabular-nums text-text-secondary shrink-0\">\n {formatDurationCompact((g.dwellSeconds ?? 0) * 1000)}\n </span>\n <span className=\"font-mono tabular-nums text-text-quaternary w-8 text-right shrink-0\">\n {Math.round(((g.dwellSeconds ?? 0) / totalDwell) * 100)}%\n </span>\n </div>\n ))}\n </div>\n {dwell.data?.overflow && (\n <p className=\"text-2xs text-text-quaternary mt-1.5\">more groups exist — narrow the window</p>\n )}\n </>\n ) : (\n <p className=\"text-2xs text-text-quaternary\">No tracked time in this window.</p>\n )}\n </div>\n\n {/* In queue now — live membership by subtype (+ entity headline) */}\n <div className=\"border-t border-surface-border/40 pt-4 mt-5\">\n <p className=\"text-2xs font-semibold uppercase tracking-widest text-text-tertiary mb-2.5\">\n In queue now\n </p>\n {entityFacet && entityCount != null && (\n <button\n onClick={openLens}\n className=\"group flex items-center gap-1 text-2xs mb-2 text-left\"\n title={`Open the ${entityFacet} lens — the whole system, entity-first`}\n >\n <span className=\"text-xs font-mono font-semibold text-text-primary tabular-nums\">\n {entityCount}\n </span>{' '}\n <span className=\"font-mono text-text-tertiary group-hover:text-accent transition-colors\">{entityFacet}</span>\n <span className=\"text-text-quaternary\"> in queue</span>\n <ArrowUpRight className=\"w-3 h-3 text-text-quaternary group-hover:text-accent transition-colors\" />\n </button>\n )}\n {queueGroups.length > 0 ? (\n <div className=\"space-y-1\">\n {queueGroups.map((g) => (\n <div key={subtypeKey(g.subtype)} className=\"flex items-center gap-2 text-2xs\">\n <span\n className=\"w-2 h-2 rounded-full shrink-0\"\n style={{ backgroundColor: colors.get(subtypeKey(g.subtype)) }}\n />\n <span\n className={`font-mono truncate flex-1 ${\n g.subtype ? 'text-text-secondary' : 'text-text-tertiary'\n }`}\n >\n {subtypeLabel(g.subtype)}\n </span>\n <span className=\"font-mono tabular-nums text-text-primary shrink-0\">{g.count}</span>\n </div>\n ))}\n </div>\n ) : (\n <p className=\"text-2xs text-text-quaternary\">Queue clear.</p>\n )}\n\n {/* By entity — facet-grouped dwell (strict gate), fetched on disclosure */}\n {entityFacet && (\n <div className=\"mt-3\">\n <button\n onClick={() => setShowEntities((v) => !v)}\n className=\"flex items-center gap-1 text-2xs text-text-tertiary hover:text-accent transition-colors\"\n >\n {showEntities ? <ChevronDown className=\"w-3 h-3\" /> : <ChevronRight className=\"w-3 h-3\" />}\n By entity\n </button>\n {showEntities && (\n isForbidden(perEntity.error) ? (\n <p className=\"text-2xs text-text-quaternary mt-1.5\">\n Requires full read access to this station's queue.\n </p>\n ) : (\n <div className=\"space-y-1 mt-1.5\">\n {(perEntity.data?.groups ?? []).map((g) => {\n const value = g.facets[entityFacet];\n if (value == null) return null;\n return (\n <div key={value} className=\"flex items-center gap-2 text-2xs\">\n <span className=\"font-mono truncate flex-1 text-text-secondary\" title={value}>\n {value}\n </span>\n <span className=\"font-mono tabular-nums text-text-secondary shrink-0\">\n {formatDurationCompact((g.dwellSeconds ?? 0) * 1000)}\n </span>\n <button\n className=\"icon-link shrink-0\"\n title=\"Open timeline\"\n onClick={() => onOpenEntity(entityFacet, value)}\n >\n <History className=\"w-3 h-3\" />\n </button>\n </div>\n );\n })}\n {perEntity.data && perEntity.data.groups.length === 0 && (\n <p className=\"text-2xs text-text-quaternary\">No entities in this window.</p>\n )}\n {perEntity.data?.overflow && (\n <p className=\"text-2xs text-text-quaternary\">top 8 by dwell</p>\n )}\n </div>\n )\n )}\n </div>\n )}\n </div>\n </>\n );\n}\n","import { useState, useCallback } 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 { jeopardyQueueLink } from './priority-link';\nimport { displayRoleTitle } from '../../lib/role-display';\nimport { StationAnalyticsSections } from './StationAnalyticsSections';\nimport { EntityTimelinePanel } from '../../components/escalation/EntityTimelinePanel';\nimport { useShellPanelOptional } from '../../hooks/useShellPanel';\nimport { assignLabelColors, subtypeLabel } from './mix-colors';\nimport type { AggregateRow } from '../../api/escalation-analytics';\nimport { formatDurationCompact } from '../../lib/format';\n\ninterface StationDetailPanelProps {\n role: RoleDetail | null;\n allMetrics: StationMetric[];\n orderedRoles: RoleDetail[];\n globalPeriod: string;\n /** The page's shared role+subtype dwell groups — the sequence bands derive\n * from them with zero extra requests. */\n mixGroups?: AggregateRow[];\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\n// Mirrors OperationsPage's window lengths — the analytics sections express the\n// panel's selected period as a trailing dwell window.\nconst PERIOD_HOURS: Record<Period, number> = {\n '15m': 0.25,\n '1h': 1,\n '24h': 24,\n '7d': 168,\n '30d': 720,\n};\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.5\">\n <span className=\"text-2xs 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-2xs font-mono rounded transition-colors ${\n period === p\n ? 'bg-accent/10 text-accent font-semibold'\n : 'icon-link'\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 // Entity timelines open in the global shell right slot, beside this panel.\n // When the role declares an entity, the timeline scopes to the entity's\n // whole SYSTEM — an order's journey walks every station, not just this one.\n const shell = useShellPanelOptional();\n const openEntityTimeline = useCallback(\n (facetKey: string, value: string) => {\n shell?.setPanel(\n role.entity_facet\n ? <EntityTimelinePanel facetKey={facetKey} value={value} entity={role.entity_facet} />\n : <EntityTimelinePanel facetKey={facetKey} value={value} role={role.role} />,\n { key: 'entity-timeline', width: 420 },\n );\n },\n [shell, role.role, role.entity_facet],\n );\n\n return (\n <>\n {/* Header */}\n <div className=\"flex items-start justify-between mb-4\">\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-2xs font-mono text-text-secondary\">{role.role}</span>\n </div>\n {role.description && (\n <p className=\"text-2xs text-text-tertiary mt-1 line-clamp-2 leading-relaxed\">\n {role.description}\n </p>\n )}\n </div>\n <button\n onClick={onClose}\n className=\"icon-link mt-0.5 shrink-0 ml-2\"\n >\n <X className=\"w-4 h-4\" />\n </button>\n </div>\n\n {/* Jeopardy leads — the one line that demands action never scrolls out of view. */}\n {metric && metric.priority_count > 0 && (\n <Link\n to={jeopardyQueueLink(role)}\n className=\"flex items-center justify-between group mb-4\"\n >\n <span className=\"text-2xs\" style={{ color: PRIORITY_TEXT_COLOR }}>\n {metric.priority_count} in jeopardy — pull oldest first\n </span>\n <ExternalLink className=\"w-3 h-3 transition-colors\" style={{ color: PRIORITY_TEXT_COLOR }} />\n </Link>\n )}\n\n <PeriodSelector period={period} onChange={setPeriod} />\n\n {/* Capacity settings */}\n {(targetPerHour || slaMinutes || workerCount) && (\n <div className=\"flex items-center gap-6 mb-6 text-2xs border-b border-surface-border/30 pb-5\">\n {targetPerHour && (\n <div>\n <div className=\"font-mono font-semibold text-text-primary text-sm\">{targetPerHour}/h</div>\n <div className=\"text-text-quaternary uppercase tracking-wider text-[8.5px] mt-0.5\">target</div>\n </div>\n )}\n {slaMinutes && (\n <div>\n <div className=\"font-mono font-semibold text-text-primary text-sm\">{slaMinutes}m</div>\n <div className=\"text-text-quaternary uppercase tracking-wider text-[8.5px] mt-0.5\">SLA</div>\n </div>\n )}\n {workerCount && (\n <div>\n <div className=\"font-mono font-semibold text-text-primary text-sm\">{workerCount}</div>\n <div className=\"text-text-quaternary uppercase tracking-wider text-[8.5px] mt-0.5\">workers</div>\n </div>\n )}\n </div>\n )}\n\n {/* Two-column wait / work grid */}\n <div className=\"grid grid-cols-2 gap-x-4 mb-2\">\n <div>\n <p className=\"text-2xs text-text-quaternary uppercase tracking-wider mb-2\">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-2xs text-text-quaternary uppercase tracking-wider mb-2\">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 */}\n {slaMinutes && (\n <div className=\"border-t border-surface-border/40 pt-4 mt-5\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-2xs text-text-tertiary\">SLA target</span>\n <span className=\"text-xs font-mono text-text-secondary\">{slaMinutes}m</span>\n </div>\n </div>\n )}\n\n {/* Time-in-state + live queue composition (the MIX bar's drill-down) */}\n <StationAnalyticsSections\n role={role}\n periodHours={PERIOD_HOURS[period]}\n onOpenEntity={openEntityTimeline}\n />\n\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-2xs 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-2xs\" style={{ color: PRIORITY_TEXT_COLOR }}>\n {stationsAtRisk} station{stationsAtRisk > 1 ? 's' : ''} with items in jeopardy\n </p>\n ) : stationsWithLoad > 0 ? (\n <p className=\"text-2xs text-status-warning\">\n {stationsWithLoad} station{stationsWithLoad > 1 ? 's' : ''} with backlog\n </p>\n ) : totalResolved > 0 ? (\n <p className=\"text-2xs text-status-success\">Flowing — queue clear</p>\n ) : (\n <p className=\"text-2xs 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-2xs 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-2xs 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-2xs 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-2xs text-text-quaternary uppercase tracking-wider flex-1\">Station</span>\n <span className=\"text-2xs text-text-quaternary uppercase tracking-wider w-8 text-right shrink-0\">pend</span>\n <span className=\"text-2xs text-text-quaternary uppercase tracking-wider w-8 text-right shrink-0\">clmd</span>\n <span className=\"text-2xs 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-2xs font-mono flex-1 truncate ${\n hasLoad ? 'text-text-primary' : 'text-text-quaternary'\n }`}\n title={label}\n >\n {label}\n </span>\n {/* Priority as a bare right-aligned number — the slot always\n renders so the count column stays aligned across rows. */}\n <span\n className=\"text-[0.625rem] leading-none font-semibold tabular-nums w-4 text-right shrink-0\"\n style={{ color: PRIORITY_TEXT_COLOR }}\n title={hasAlert ? `${priorityCount} priority — pull oldest first` : undefined}\n >\n {hasAlert ? priorityCount : ''}\n </span>\n <span\n className={`text-2xs 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-2xs font-mono tabular-nums w-8 text-right shrink-0 ${claimed > 0 ? 'text-accent font-semibold' : 'text-text-quaternary'}`}>\n {claimed > 0 ? claimed : '—'}\n </span>\n <span className={`text-2xs 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-2xs 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 mixGroups,\n onClose,\n}: StationDetailPanelProps) {\n return (\n <div className=\"w-[280px] shrink-0 px-7 py-10 flex flex-col overflow-y-auto min-h-0\">\n {role ? (\n <RoleView role={role} globalPeriod={globalPeriod} onClose={onClose} />\n ) : (\n <>\n <OverviewPanel allMetrics={allMetrics} orderedRoles={orderedRoles} period={globalPeriod} />\n <SequenceBands mixGroups={mixGroups} orderedRoles={orderedRoles} />\n </>\n )}\n </div>\n );\n}\n\n/**\n * The set-on-screen bands — where the SEQUENCE'S time went over the window,\n * cut both ways: by station (the sequential story) and by subtype (the\n * product/state story). Derived from the page's shared mix query.\n */\nfunction SequenceBands({\n mixGroups,\n orderedRoles,\n}: {\n mixGroups?: AggregateRow[];\n orderedRoles: RoleDetail[];\n}) {\n const visible = new Set(orderedRoles.map((r) => r.role));\n const rows = (mixGroups ?? []).filter((g) => g.role && visible.has(g.role) && (g.dwellSeconds ?? 0) > 0);\n if (rows.length === 0) return null;\n\n const titleFor = new Map(orderedRoles.map((r) => [r.role, r.title || r.role]));\n const byRole = sumBy(rows, (g) => g.role!);\n const bySubtype = sumBy(rows, (g) => subtypeLabel(g.subtype));\n\n return (\n <>\n <BandSection\n label=\"Time by station\"\n entries={byRole}\n display={(key) => titleFor.get(key) ?? key}\n />\n <BandSection label=\"Time by subtype\" entries={bySubtype} display={(key) => key} />\n </>\n );\n}\n\nfunction sumBy(rows: AggregateRow[], keyOf: (g: AggregateRow) => string): Array<[string, number]> {\n const totals = new Map<string, number>();\n for (const g of rows) {\n const key = keyOf(g);\n totals.set(key, (totals.get(key) ?? 0) + (g.dwellSeconds ?? 0));\n }\n return [...totals.entries()].sort(([, a], [, b]) => b - a);\n}\n\nfunction BandSection({\n label,\n entries,\n display,\n}: {\n label: string;\n entries: Array<[string, number]>;\n display: (key: string) => string;\n}) {\n const colors = assignLabelColors(entries.map(([key, weight]) => ({ label: key, weight })));\n const total = entries.reduce((sum, [, v]) => sum + v, 0) || 1;\n return (\n <div className=\"border-t border-surface-border/40 pt-4 mt-5\">\n <p className=\"text-2xs font-semibold uppercase tracking-widest text-text-tertiary mb-2.5\">{label}</p>\n <div className=\"h-2 flex rounded-full overflow-hidden bg-surface-sunken mb-2\">\n {entries.map(([key, value]) => (\n <div key={key} style={{ width: `${(value / total) * 100}%`, backgroundColor: colors.get(key) }} />\n ))}\n </div>\n <div className=\"space-y-0.5\">\n {entries.slice(0, 6).map(([key, value]) => (\n <div key={key} className=\"flex items-center gap-2 text-2xs\">\n <span className=\"w-2 h-2 rounded-full shrink-0\" style={{ backgroundColor: colors.get(key) }} />\n <span className=\"font-mono text-text-secondary truncate flex-1\">{display(key)}</span>\n <span className=\"font-mono tabular-nums text-text-tertiary shrink-0\">\n {formatDurationCompact(value * 1000)}\n </span>\n <span className=\"font-mono tabular-nums text-text-quaternary w-8 text-right shrink-0\">\n {Math.round((value / total) * 100)}%\n </span>\n </div>\n ))}\n {entries.length > 6 && (\n <p className=\"text-2xs text-text-quaternary\">+{entries.length - 6} more</p>\n )}\n </div>\n </div>\n );\n}\n","import { useState, useEffect, useMemo, useCallback, useRef } from 'react';\nimport { Link, useNavigate, useSearchParams } from 'react-router-dom';\nimport { GitMerge, RefreshCw, Eye, Settings, TriangleAlert, ChevronDown } from 'lucide-react';\nimport { useRoleDetails, useUpdateRole, type RoleDetail } from '../../api/roles';\nimport { useStationMetrics } from '../../api/escalations';\nimport type { StationMetric } from '../../api/escalations';\nimport { useStationMetricsEvents, useEscalationAnalyticsEvents } from '../../hooks/useEventHooks';\nimport { useAggregateByFacets, useAnalyticsWindow, type AggregateRow } from '../../api/escalation-analytics';\nimport { assignMixColors } from './mix-colors';\nimport { StationMixBar } from './StationMixBar';\nimport { EntityLensView } from './EntityLensView';\nimport { PageHeader } from '../../components/common/layout/PageHeader';\nimport { ViewMenu } from './ViewMenu';\nimport {\n PaceChart,\n ACTIVE_COLOR,\n QUEUED_COLOR,\n RESOLVED_COLOR,\n TARGET_COLOR,\n PRIORITY_TEXT_COLOR,\n withAlpha,\n type ChartStation,\n} from './PaceChart';\nimport { StationDetailPanel } from './StationDetailPanel';\nimport { jeopardyQueueLink } from './priority-link';\nimport { useAccess } from '../../hooks/useAccess';\nimport { displayRoleTitle } from '../../lib/role-display';\n\n// Column band tints — same hues as the chart bands. Two sets: the slate\n// configuration trio (target, SLA, workers) and the vivid status trio.\n// Status bands carry ~15% of their bright -graphic hues so they hold up on\n// light surfaces without overpowering midnight.\nconst SLA_COLOR = TARGET_COLOR;\nconst TARGET_BAND = withAlpha(TARGET_COLOR, 0.09);\nconst SLA_BAND = TARGET_BAND;\nconst WORKERS_BAND = TARGET_BAND;\nconst PENDING_BAND = withAlpha(QUEUED_COLOR, 0.15);\nconst ACTIVE_BAND = withAlpha(ACTIVE_COLOR, 0.15);\nconst RESOLVED_BAND = withAlpha(RESOLVED_COLOR, 0.15);\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// ── Editable numeric cell ─────────────────────────────────────────────────────\n\nfunction EditableNumber({ value, onSave }: { value: number | null; onSave: (n: number | null) => void }) {\n const [local, setLocal] = useState(value != null ? String(value) : '');\n const timer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n\n const commit = (val: string) => {\n const n = parseInt(val, 10);\n onSave(!val.trim() || isNaN(n) || n < 0 ? null : n);\n };\n\n return (\n <input\n type=\"number\"\n min={0}\n step={1}\n value={local}\n onChange={(e) => {\n const val = e.target.value;\n setLocal(val);\n clearTimeout(timer.current);\n timer.current = setTimeout(() => commit(val), 400);\n }}\n onBlur={(e) => { clearTimeout(timer.current); commit(e.target.value); }}\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n className=\"w-full bg-transparent text-xs font-mono tabular-nums text-right focus:outline-none\"\n />\n );\n}\n\n// ── Station table row ─────────────────────────────────────────────────────────\n\nfunction StationRow({\n role,\n metric,\n mixGroups,\n mixColors,\n selected,\n periodHours,\n onClick,\n}: {\n role: RoleDetail;\n metric: StationMetric | undefined;\n mixGroups: AggregateRow[] | undefined;\n mixColors: Map<string, string>;\n selected: boolean;\n periodHours: number;\n onClick: () => void;\n}) {\n const updateRole = useUpdateRole();\n // Config is a role-manager gesture — members can neither view nor edit roles.\n const { isBuilder, isOps } = useAccess();\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 const workers = calcWorkers(role.target_per_hour ?? null, role.sla_minutes ?? null, pending, periodHours);\n\n const saveTarget = (n: number | null) => updateRole.mutate({ role: role.role, target_per_hour: n });\n const saveSla = (n: number | null) => updateRole.mutate({ role: role.role, sla_minutes: n });\n\n return (\n <tr\n tabIndex={0}\n onClick={onClick}\n onKeyDown={(e) => { if (e.key === 'Enter') onClick(); }}\n className={`cursor-pointer border-b border-surface-border/30 last:border-b-0 transition-colors ${\n selected ? 'border-l-2 !border-l-accent' : ''\n }`}\n >\n {/* Name — user-set title, or derived from the role id */}\n <td className=\"pl-3 pr-2 py-1.5 overflow-hidden\">\n <div className=\"flex items-center gap-1.5 min-w-0\">\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 </td>\n\n {/* Role id */}\n <td className=\"hidden xl:table-cell pr-2 py-1.5 overflow-hidden\">\n <span className=\"block font-mono text-2xs text-text-tertiary truncate\">{role.role}</span>\n </td>\n\n {/* Target/h — editable */}\n <td className=\"px-2 py-1.5\" style={{ backgroundColor: TARGET_BAND }}>\n <EditableNumber value={role.target_per_hour ?? null} onSave={saveTarget} />\n </td>\n\n {/* SLA/m — editable */}\n <td className=\"px-2 py-1.5\" style={{ backgroundColor: SLA_BAND }}>\n <EditableNumber value={role.sla_minutes ?? null} onSave={saveSla} />\n </td>\n\n {/* Workers — calculated (Little's Law + backlog) */}\n <td\n className=\"px-2 py-1.5 text-right\"\n style={{ backgroundColor: WORKERS_BAND }}\n title={workers != null ? `~${workers} concurrent worker${workers === 1 ? '' : 's'} to sustain ${role.target_per_hour}/h within ${role.sla_minutes}m SLA` : undefined}\n >\n <span className={`text-xs font-mono tabular-nums ${workers != null ? '' : 'text-text-quaternary'}`}>\n {workers ?? '—'}\n </span>\n </td>\n\n {/* Pending */}\n <td className=\"px-2 py-1.5 text-right\" style={{ backgroundColor: PENDING_BAND }}>\n <Link\n to={`/escalations/available?role=${encodeURIComponent(role.role)}&status=available`}\n className={`text-xs font-mono tabular-nums hover:underline ${\n pending > 0 ? 'text-text-primary font-semibold' : 'text-text-quaternary'\n }`}\n onClick={(e) => e.stopPropagation()}\n >\n {pending}\n </Link>\n </td>\n\n {/* Claimed */}\n <td className=\"px-2 py-1.5 text-right\" style={{ backgroundColor: ACTIVE_BAND }}>\n <Link\n to={`/escalations/available?role=${encodeURIComponent(role.role)}&status=claimed`}\n className={`text-xs font-mono tabular-nums hover:underline ${\n claimed > 0 ? 'font-semibold' : 'text-text-quaternary'\n }`}\n style={claimed > 0 ? { color: ACTIVE_COLOR } : undefined}\n onClick={(e) => e.stopPropagation()}\n >\n {claimed}\n </Link>\n </td>\n\n {/* Resolved */}\n <td className=\"px-2 py-1.5 text-right\" style={{ backgroundColor: RESOLVED_BAND }}>\n <Link\n to={`/escalations/available?role=${encodeURIComponent(role.role)}&status=resolved`}\n className={`text-xs font-mono tabular-nums hover:underline ${\n resolved > 0 ? 'text-text-secondary' : 'text-text-quaternary'\n }`}\n style={resolved > 0 ? { color: RESOLVED_COLOR } : undefined}\n onClick={(e) => e.stopPropagation()}\n >\n {resolved}\n </Link>\n </td>\n\n {/* P99 wait */}\n <td className=\"hidden xl:table-cell px-2 py-1.5 text-right\">\n <span className=\"text-xs font-mono tabular-nums text-text-secondary\">\n {fmtMin(metric?.wait.p99 ?? null)}\n </span>\n </td>\n\n {/* P99 work */}\n <td className=\"hidden xl:table-cell px-2 py-1.5 text-right\">\n <span className=\"text-xs font-mono tabular-nums text-text-secondary\">\n {fmtMin(metric?.work.p99 ?? null)}\n </span>\n </td>\n\n {/* Time-in-state mix over the window */}\n <td className=\"hidden lg:table-cell px-2 py-1.5\">\n <StationMixBar groups={mixGroups} colors={mixColors} />\n </td>\n\n {/* Load mini-bar */}\n <td className=\"hidden lg:table-cell px-2 py-1.5\">\n <div className=\"flex items-center gap-2\">\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-2xs 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 </td>\n\n {/* Actions — eye always anchored first; jeopardy occupies a fixed-width\n slot after it so the eye never shifts when the alert appears. */}\n <td className=\"py-1.5\">\n <div className=\"flex items-center justify-center gap-1.5\">\n <Link\n to={`/escalations/available?role=${encodeURIComponent(role.role)}&status=all`}\n className=\"icon-link\"\n title=\"View all items in queue\"\n onClick={(e) => e.stopPropagation()}\n >\n <Eye className=\"w-3.5 h-3.5\" />\n </Link>\n {/* Fixed slot — managers get the role config; the column holds its\n shape for members, who can neither view nor edit roles. */}\n <span className=\"w-3.5 flex items-center justify-center\">\n {(isBuilder || isOps) && (\n <Link\n to={`/admin/roles/${encodeURIComponent(role.role)}?section=pace-board`}\n className=\"icon-link\"\n title=\"Configure this station\"\n onClick={(e) => e.stopPropagation()}\n >\n <Settings className=\"w-3.5 h-3.5\" />\n </Link>\n )}\n </span>\n {/* Fixed-width slot — always occupies space so the eye never shifts */}\n <span className=\"w-3.5 flex items-center justify-center\">\n {priorityCount > 0 && (\n <Link\n to={jeopardyQueueLink(role)}\n className=\"text-status-error hover:opacity-70 transition-opacity\"\n title={`${priorityCount} item${priorityCount === 1 ? '' : 's'} in jeopardy — pull oldest first`}\n onClick={(e) => e.stopPropagation()}\n >\n <TriangleAlert className=\"w-3.5 h-3.5\" strokeWidth={2} />\n </Link>\n )}\n </span>\n </div>\n </td>\n </tr>\n );\n}\n\n// ── Sequence menu ─────────────────────────────────────────────────────────────\n\ninterface SequenceAggregate {\n stations: number;\n pending: number;\n jeopardy: number;\n}\n\n/** Red jeopardy count, capped at 9+ — the same shorthand as the queue pills. */\nfunction JeopardyCount({ n }: { n: number }) {\n if (n <= 0) return null;\n return (\n <span\n className=\"inline-flex items-center gap-0.5 font-semibold tabular-nums\"\n style={{ color: PRIORITY_TEXT_COLOR }}\n title={`${n} in jeopardy`}\n >\n <TriangleAlert className=\"w-3 h-3\" strokeWidth={2.25} />\n {n > 9 ? '9+' : n}\n </span>\n );\n}\n\n/**\n * The segment selector for the 30k-foot view — compact at any segment count.\n * Collapsed, it names the ACTIVE sequence large with its aggregate story\n * (stations · pending · jeopardy) and a caret; expanded, it lists every\n * sequence with the same breakdown so trouble in an unselected segment is\n * visible from here and one click away. Metrics span every visible role, so\n * the numbers are live for all segments, not just the chosen one.\n */\nfunction SequenceMenu({ fragments, aggregates, activeOrigin, onSelect }: {\n fragments: SequenceFragment[];\n aggregates: Map<string, SequenceAggregate>;\n activeOrigin: string | null;\n onSelect: (origin: string) => void;\n}) {\n const [open, setOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!open) return;\n const onClick = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false);\n };\n const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') setOpen(false); };\n document.addEventListener('mousedown', onClick);\n document.addEventListener('keydown', onKey);\n return () => {\n document.removeEventListener('mousedown', onClick);\n document.removeEventListener('keydown', onKey);\n };\n }, [open]);\n\n const active = fragments.find((f) => f.origin.role === activeOrigin) ?? fragments[0];\n if (!active) return null;\n const agg = aggregates.get(active.origin.role);\n\n return (\n <div ref={ref} className=\"relative px-4 pt-2\">\n <button\n type=\"button\"\n onClick={() => setOpen((v) => !v)}\n className=\"group flex items-baseline gap-2.5\"\n aria-expanded={open}\n aria-haspopup=\"listbox\"\n >\n <span className=\"text-sm font-medium text-text-primary group-hover:text-accent transition-colors\">\n {displayRoleTitle(active.origin)}\n </span>\n <span className=\"text-2xs font-mono text-text-quaternary tabular-nums\">\n {agg?.stations ?? active.stations.length} station{(agg?.stations ?? active.stations.length) === 1 ? '' : 's'} · {agg?.pending ?? 0} pending\n </span>\n <JeopardyCount n={agg?.jeopardy ?? 0} />\n <ChevronDown\n className={`w-3.5 h-3.5 self-center shrink-0 text-text-tertiary group-hover:text-accent transition-transform ${open ? 'rotate-180' : ''}`}\n strokeWidth={1.5}\n />\n </button>\n\n {open && (\n <div\n role=\"listbox\"\n className=\"absolute z-[100] top-full left-4 mt-1.5 min-w-[20rem] max-h-80 overflow-y-auto bg-surface-raised border border-surface-border rounded-md shadow-lg py-1\"\n >\n {fragments.map((f) => {\n const a = aggregates.get(f.origin.role);\n const isActive = f.origin.role === active.origin.role;\n return (\n <button\n key={f.origin.role}\n type=\"button\"\n role=\"option\"\n aria-selected={isActive}\n onClick={() => { onSelect(f.origin.role); setOpen(false); }}\n className={`w-full text-left px-3 py-1.5 flex items-baseline gap-2.5 transition-colors ${\n isActive ? 'text-accent bg-accent/5' : 'text-text-primary hover:bg-surface-hover'\n }`}\n >\n <span className=\"text-xs font-medium truncate\">{displayRoleTitle(f.origin)}</span>\n <span className=\"ml-auto text-2xs font-mono text-text-quaternary tabular-nums shrink-0\">\n {a?.stations ?? f.stations.length} st · {a?.pending ?? 0} pending\n </span>\n {/* Fixed-width, left-aligned jeopardy column: every ⚠ starts at\n the same x, so the icons stack vertically whether the count\n is 1 or 9+. */}\n <span className=\"w-12 shrink-0 text-left text-2xs\">\n <JeopardyCount n={a?.jeopardy ?? 0} />\n </span>\n </button>\n );\n })}\n </div>\n )}\n </div>\n );\n}\n\n// ── Colored column specs — bands shared by header and rows ───────────────────\n// Percentage widths: under `table-fixed` the header row's widths govern every\n// column, so these scale with the window instead of forcing a minimum table\n// width. NAME (widthless) absorbs the remainder.\nconst COLORED_COLS = [\n { label: 'TARGET/H', band: TARGET_BAND, hue: TARGET_COLOR, w: 'w-[8%]' },\n { label: 'SLA/M', band: SLA_BAND, hue: SLA_COLOR, w: 'w-[7%]' },\n { label: 'WORKERS', band: WORKERS_BAND, hue: TARGET_COLOR, w: 'w-[8%]' },\n { label: 'PENDING', band: PENDING_BAND, hue: QUEUED_COLOR, w: 'w-[8%]' },\n { label: 'CLAIMED', band: ACTIVE_BAND, hue: ACTIVE_COLOR, w: 'w-[8%]' },\n { label: 'RESOLVED', band: RESOLVED_BAND, hue: RESOLVED_COLOR, w: 'w-[8%]' },\n] as const;\n\n/**\n * Little's Law staffing estimate: how many concurrent workers are needed to\n * sustain the target throughput within the SLA, accounting for any current\n * backlog that must be cleared within the selected period.\n *\n * steady-state = target_per_hour × sla_minutes / 60\n * backlog_extra = pending × sla_minutes / (60 × period_hours)\n *\n * Shorter periods with a backlog require more concurrency. The result is\n * rounded up — you can't staff 1.3 workers.\n */\nfunction calcWorkers(\n targetPerHour: number | null,\n slaMinutes: number | null,\n pending: number,\n periodHours: number,\n): number | null {\n if (!targetPerHour || !slaMinutes) return null;\n const steadyState = (targetPerHour * slaMinutes) / 60;\n const backlogExtra = pending > 0 ? (pending * slaMinutes) / (60 * periodHours) : 0;\n return Math.ceil(steadyState + backlogExtra);\n}\n\n// ── Table header ──────────────────────────────────────────────────────────────\n\n// Header cells stick inside the table's own scroll container (the bottom\n// console row). Band cells layer their tint over the opaque surface with a\n// gradient so scrolling rows never show through the sticky header.\nconst TH_BASE =\n 'sticky top-0 z-10 bg-surface border-b border-surface-border py-1.5 text-2xs font-semibold uppercase tracking-wider whitespace-nowrap';\n\nfunction TableHead() {\n return (\n <thead>\n <tr>\n <th className={`${TH_BASE} pl-3 pr-2 text-left text-text-quaternary`}>NAME</th>\n <th className={`${TH_BASE} hidden xl:table-cell w-[12%] pr-2 text-left text-text-quaternary`}>ROLE</th>\n {COLORED_COLS.map((col) => (\n <th\n key={col.label}\n className={`${TH_BASE} ${col.w} px-2 text-right`}\n style={{ color: col.hue, backgroundImage: `linear-gradient(${col.band}, ${col.band})` }}\n >\n {col.label}\n </th>\n ))}\n <th className={`${TH_BASE} hidden xl:table-cell w-[8%] px-2 text-right text-text-quaternary`}>P99 WAIT</th>\n <th className={`${TH_BASE} hidden xl:table-cell w-[8%] px-2 text-right text-text-quaternary`}>P99 WORK</th>\n <th className={`${TH_BASE} hidden lg:table-cell w-[10%] px-2 text-left text-text-quaternary`}>MIX</th>\n <th className={`${TH_BASE} hidden lg:table-cell w-[11%] px-2 text-left text-text-quaternary`}>TREND</th>\n <th className={`${TH_BASE} w-20 px-1 text-center text-text-quaternary`}>ACTIONS</th>\n </tr>\n </thead>\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 // Log default: station volumes span orders of magnitude; log keeps every\n // curve's shape visible instead of flattening the small ones.\n const [logScale, setLogScale] = useState(true);\n\n // Push-driven refresh: every escalation event invalidates ['stationMetrics']\n // (and the analytics aggregates behind the MIX bars) through the central\n // event system (debounced, transport-agnostic). The header's refresh button\n // covers user-initiated reloads.\n useStationMetricsEvents();\n useEscalationAnalyticsEvents();\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 // Per-sequence aggregates for the segment menu — computed over ALL visible\n // roles, so unselected segments report their live pending/jeopardy too.\n const fragmentAggregates = useMemo(() => {\n const metricByRole = new Map(metrics.map((m) => [m.role, m]));\n const out = new Map<string, SequenceAggregate>();\n for (const f of buildFragments(roleData?.roles ?? [])) {\n let pending = 0, jeopardy = 0;\n for (const s of f.stations) {\n const m = metricByRole.get(s.role.role);\n pending += m?.pending ?? 0;\n jeopardy += m?.priority_count ?? 0;\n }\n out.set(f.origin.role, { stations: f.stations.length, pending, jeopardy });\n }\n return out;\n }, [metrics, roleData]);\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\n // Time-in-state mix: ONE dwell aggregate serves every visible station's MIX\n // bar. The window rolls with the minute (stable keys, server-cache-aligned);\n // an analytics 403 (flag off, unprivileged) simply leaves every cell at `—`.\n const analyticsWindow = useAnalyticsWindow(PERIOD_HOURS[period]);\n const visibleRoles = useMemo(() => ordered.map(({ role }) => role.role), [ordered]);\n const { data: mixData } = useAggregateByFacets(\n visibleRoles.length\n ? {\n query: { roles: visibleRoles },\n groupBy: { columns: ['role', 'subtype'] },\n measure: { kind: 'dwell', window: analyticsWindow },\n }\n : null,\n );\n const mixByRole = useMemo(() => {\n const out = new Map<string, AggregateRow[]>();\n for (const g of mixData?.groups ?? []) {\n if (!g.role) continue;\n const rows = out.get(g.role) ?? [];\n rows.push(g);\n out.set(g.role, rows);\n }\n return out;\n }, [mixData]);\n const mixColorsByRole = useMemo(() => {\n const out = new Map<string, Map<string, string>>();\n for (const [role, rows] of mixByRole) out.set(role, assignMixColors(rows));\n return out;\n }, [mixByRole]);\n const EMPTY_COLORS = useMemo(() => new Map<string, string>(), []);\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 const navigate = useNavigate();\n\n const selectedRoleDetail =\n ordered.find(({ role }) => role.role === selectedRole)?.role ?? null;\n\n // ── Lenses: station-first (default) or entity-first, one lens per entity\n // facet the visible ops roles declare. Roles sharing a key form the\n // entity's SYSTEM; the lens shows its state mix, slices, and entities.\n const entityLenses = useMemo(() => {\n const keys = new Set<string>();\n for (const r of roles) {\n if (r.ops_visible && r.entity_facet) keys.add(r.entity_facet);\n }\n return [...keys].sort();\n }, [roles]);\n const lensParam = searchParams.get('lens');\n const activeLens = lensParam && entityLenses.includes(lensParam) ? lensParam : null;\n const selectLens = useCallback(\n (lens: string | null) => {\n setSelectedRole(null);\n setSearchParams((prev) => {\n const p = new URLSearchParams(prev);\n if (lens) p.set('lens', lens);\n else p.delete('lens');\n // Entity-scoped params belong to one lens — a switch resets them.\n p.delete('entity');\n p.delete('find');\n p.delete('slice');\n p.delete('sliceValue');\n return p;\n });\n },\n [setSearchParams],\n );\n\n // Lens deep-link companions: ?entity= (the open timeline panel) and ?find=\n // (the entity-table prefix term). Both are plain URL-encoded strings; the\n // lens view treats the params as source of truth, so back/forward replays\n // panel opens and find terms.\n const entityParam = searchParams.get('entity');\n const findParam = searchParams.get('find');\n const setEntityParam = useCallback(\n (value: string | null) => {\n setSearchParams((prev) => {\n const p = new URLSearchParams(prev);\n if (value) p.set('entity', value);\n else p.delete('entity');\n return p;\n });\n },\n [setSearchParams],\n );\n // Replace, not push — each debounced keystroke would otherwise pile up\n // history entries; the final term still restores on back/forward.\n const setFindParam = useCallback(\n (term: string | null) => {\n setSearchParams(\n (prev) => {\n const p = new URLSearchParams(prev);\n if (term) p.set('find', term);\n else p.delete('find');\n return p;\n },\n { replace: true },\n );\n },\n [setSearchParams],\n );\n\n // Slice params: ?slice= (the categorical facet) and ?sliceValue= (the focused\n // value). Both push history — they define the view, so back/forward and the\n // upper-right bookmark reproduce it. Changing the facet drops any focus.\n const sliceParam = searchParams.get('slice');\n const sliceValueParam = searchParams.get('sliceValue');\n const setSliceParam = useCallback(\n (key: string | null) => {\n setSearchParams((prev) => {\n const p = new URLSearchParams(prev);\n if (key) p.set('slice', key);\n else p.delete('slice');\n p.delete('sliceValue');\n return p;\n });\n },\n [setSearchParams],\n );\n const setSliceValueParam = useCallback(\n (value: string | null) => {\n setSearchParams((prev) => {\n const p = new URLSearchParams(prev);\n if (value) p.set('sliceValue', value);\n else p.delete('sliceValue');\n return p;\n });\n },\n [setSearchParams],\n );\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-2xs font-mono rounded transition-colors ${\n period === p\n ? 'bg-accent/10 text-accent font-semibold'\n : 'icon-link'\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=\"icon-link 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 {/* Top strip: segment selector (left) + lens selector + scale toggle (right) */}\n <div className=\"flex items-end justify-between\">\n <div className=\"flex-1\">\n {!activeLens && fragments.length > 1 && (\n <SequenceMenu\n fragments={fragments}\n aggregates={fragmentAggregates}\n activeOrigin={activeFragment?.origin.role ?? null}\n onSelect={selectFragment}\n />\n )}\n </div>\n {entityLenses.length > 0 && (\n <div className=\"px-4 pt-2 pb-0.5\">\n <ViewMenu\n lenses={entityLenses}\n activeLens={activeLens}\n stationCount={ordered.length}\n onSelect={selectLens}\n />\n </div>\n )}\n </div>\n\n {activeLens ? (\n /* ── Entity lens: the board flipped entity-first — the system's\n state band, categorical slices, and per-entity rows. ── */\n <EntityLensView\n key={activeLens}\n entityKey={activeLens}\n periodHours={PERIOD_HOURS[period]}\n roles={roles}\n find={findParam}\n onFindChange={setFindParam}\n entityValue={entityParam}\n onEntityChange={setEntityParam}\n sliceKey={sliceParam}\n onSliceKeyChange={setSliceParam}\n sliceValue={sliceValueParam}\n onSliceValueChange={setSliceValueParam}\n />\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 overflow-hidden px-2 py-4\">\n {/* Scale toggle — centered over the timeline it controls, not stranded on the far edge */}\n <div className=\"flex items-center justify-center gap-0.5 pb-2 shrink-0\">\n {(['lin', 'log'] as const).map((mode) => (\n <button\n key={mode}\n onClick={() => setLogScale(mode === 'log')}\n className={`px-2 py-0.5 text-2xs font-mono rounded transition-colors ${\n (logScale ? 'log' : 'lin') === mode\n ? 'text-accent font-semibold'\n : 'icon-link'\n }`}\n title={mode === 'lin' ? 'Linear Y axis' : 'Logarithmic Y axis — reveals shape across wide value ranges'}\n >\n {mode}\n </button>\n ))}\n </div>\n <div className=\"flex-1 min-h-0 flex flex-col justify-center overflow-hidden\">\n <PaceChart\n stations={chartStations}\n selectedRole={selectedRole}\n onSelect={handleSelect}\n onUpstreamSelect={handleUpstreamSelect}\n onCmdClick={(role) => navigate(`/escalations/available?role=${encodeURIComponent(role)}`)}\n periodHours={PERIOD_HOURS[period]}\n logScale={logScale}\n />\n </div>\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 mixGroups={mixData?.groups}\n onClose={() => setSelectedRole(null)}\n />\n </div>\n\n {/* Bottom row: one real table in one scroll container — the platform\n idiom (see DataTable). `table-fixed w-full` locks columns to the\n container width (no horizontal scroll at any breakpoint); header\n cells stick inside the scrolling region. */}\n <div className=\"max-h-[30vh] flex-none overflow-y-auto border-t border-surface-border\">\n <table className=\"w-full table-fixed\">\n <TableHead />\n <tbody>\n {ordered.map(({ role }) => (\n <StationRow\n key={role.role}\n role={role}\n metric={metrics.find((m) => m.role === role.role)}\n mixGroups={mixByRole.get(role.role)}\n mixColors={mixColorsByRole.get(role.role) ?? EMPTY_COLORS}\n selected={selectedRole === role.role}\n periodHours={PERIOD_HOURS[period]}\n onClick={() => handleSelect(role.role)}\n />\n ))}\n </tbody>\n </table>\n </div>\n </>\n )}\n\n </div>\n )}\n </div>\n );\n}\n"],"names":["StationMixBar","groups","colors","segments","useMemo","rows","g","total","sum","subtypeKey","subtypeLabel","a","b","jsx","tooltip","s","formatDurationCompact","jsxs","totalDwell","entityValues","rankGroups","entityKey","out","value","pivotEntities","stateGroups","nowGroups","statesByValue","nowByValue","rankSliceValues","sliceGroups","sliceKey","limit","byValue","StateBand","height","className","rank","k","i","ordered","CenterEllipsis","text","tail","head","end","COMPARE_TOP_K","ROW_GRID","PAGE_SIZES","DEFAULT_PAGE_SIZE","EntityRowItem","facetKey","row","stateLabel","onOpen","navigate","useNavigate","activate","e","metadataFacetUrl","History","EntityColumnView","sliced","header","onTarget","hasMore","emptyText","Clock","ArrowRight","SliceColumnLoader","headerGroups","headerTotal","window","find","scope","useAggregateByFacets","pageValues","_a","anyOf","v","states","now","_b","_c","SingleColumn","TIMELINE_PANEL_KEY","FIND_DEBOUNCE_MS","SLICE_VALUE_CAP","EntityLensView","periodHours","roles","onFindChange","entityValue","onEntityChange","sliceKeyProp","onSliceKeyChange","sliceValue","onSliceValueChange","useAnalyticsWindow","shell","useShellPanelOptional","focused","compare","page","setPage","useState","pageSize","setPageSize","useEffect","findInput","setFindInput","findDebounce","useRef","handleFindInput","term","roleTitles","map","r","displayRoleTitle","state","stateDwell","stateNow","entityCount","slice","perEntity","pageScope","perEntityStates","perEntityNow","entityRows","intervalColorRef","intervalColor","iv","appliedEntity","panelWasOpen","EntityTimelinePanel","shellRef","facetKeyData","useFacetKeys","sliceOptions","dwellGroups","assignLabelColors","nowByState","tracked","_d","subtypeSourcedRoles","rankedSlices","distinctSliceValues","set","focusedBand","overflow","_e","perEntityForbidden","isForbidden","sliceForbidden","Fragment","pct","detail","ChevronLeft","n","ViewMenu","lenses","activeLens","stationCount","onSelect","open","setOpen","ref","onClick","onKey","choose","lens","ChevronDown","ViewOption","LensOption","label","note","active","mono","fetchCount","W","H","ML","MR","MT","MB","chartW","chartH","bottom","right","EASE","SOLO_HALF","soloSegment","p","catmullPath","pts","segs","p0","p1","p2","p3","cp1x","cp1y","cp2x","cp2y","bandPath","upper","lower","forward","rev","back","backSegs","compact","last","logTicks","maxVal","linearTicks","f","ACTIVE_COLOR","QUEUED_COLOR","RESOLVED_COLOR","TARGET_COLOR","PRIORITY_TEXT_COLOR","withAlpha","color","alpha","MIN_GAP","spreadLabels","labels","maxY","sorted","prev","placed","l","labelY","PaceChart","stations","selectedRole","onUpstreamSelect","onCmdClick","logScale","fill","hoveredIdx","setHoveredIdx","xOf","xMap","target","expected","hasTargets","yScale","logMax","gridTicks","withTarget","targetPts","actualPts","activePts","pendingPts","targetLinePath","actualSplinePath","activeSplinePath","pendingSplinePath","lastActual","lastTarget","lastActive","lastPending","areaPath","hasQueue","workedBandPath","queuedBandPath","showActiveLabel","showQueuedLabel","endLabels","gy","px","cx","tp","ap","ar","hasWaiting","pendingLabelY","x","cy","isSelected","isHovered","tipW","tipX","tipY","jeopardyQueueLink","role","field","orderBy","StationAnalyticsSections","onOpenEntity","entityFacet","showEntities","setShowEntities","setSearchParams","useSearchParams","openLens","dwell","queueNow","distinctEntities","assignMixColors","queueGroups","ArrowUpRight","ChevronRight","_f","_g","PERIODS","isPeriod","PERIOD_HOURS","fmt","min","MetricRow","PeriodSelector","period","onChange","RoleView","globalPeriod","onClose","setPeriod","data","useStationMetrics","metric","slaMinutes","targetPerHour","workerCount","openEntityTimeline","useCallback","X","Link","ExternalLink","OverviewPanel","allMetrics","orderedRoles","totalPending","totalResolved","totalPriority","metricByRole","m","stationsAtRisk","stationsWithLoad","pending","claimed","resolved","priorityCount","hasAlert","hasLoad","StationDetailPanel","mixGroups","SequenceBands","visible","titleFor","byRole","sumBy","bySubtype","BandSection","key","keyOf","totals","entries","display","weight","SLA_COLOR","TARGET_BAND","SLA_BAND","WORKERS_BAND","PENDING_BAND","ACTIVE_BAND","RESOLVED_BAND","buildFragments","opsRoles","roleMap","visited","fragments","root","queue","item","c","fmtMin","loadBar","ratio","EditableNumber","onSave","local","setLocal","timer","commit","val","StationRow","mixColors","selected","updateRole","useUpdateRole","isBuilder","isOps","useAccess","barWidth","workers","calcWorkers","saveTarget","saveSla","GitMerge","Eye","Settings","TriangleAlert","JeopardyCount","SequenceMenu","aggregates","activeOrigin","agg","isActive","COLORED_COLS","steadyState","backlogExtra","TH_BASE","TableHead","col","OperationsPage","setSelectedRole","refreshing","setRefreshing","setLogScale","useStationMetricsEvents","useEscalationAnalyticsEvents","roleData","rolesLoading","refetchRoles","useRoleDetails","metricsData","metricsLoading","refetchMetrics","metrics","fragmentAggregates","jeopardy","searchParams","fragmentParam","activeFragment","selectFragment","origin","fragmentRoleSet","analyticsWindow","visibleRoles","mixData","mixByRole","mixColorsByRole","EMPTY_COLORS","fragmentMetrics","chartStations","handleUpstreamSelect","upstreamRole","selectedRoleDetail","entityLenses","keys","lensParam","selectLens","entityParam","findParam","setEntityParam","setFindParam","sliceParam","sliceValueParam","setSliceParam","setSliceValueParam","isLoading","handleRefresh","handleSelect","periodSelector","PageHeader","RefreshCw","mode","o"],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{a as f,j as e}from"./vendor-query-RUZdMvN6.js";import{L as K,V as W,H as Y,K as J,I as X,M as Z,r as ee,s as se,t as te,O as ae,T as oe}from"./index-DSdqso-_.js";import{f as ie}from"./useEventHooks-DL3Vhz4g.js";import{u as re}from"./useFilterParams-crmlBw_l.js";import{u as ne}from"./useDebouncedValue-C4P2jQuh.js";import{b as le}from"./api-path-u2Jf9QXS.js";import{i as ce}from"./task-queues-7-sHKPsN.js";import{D as me}from"./DataTable-DFPMeqyQ.js";import{S as pe}from"./StickyPagination-BsbSade1.js";import{R as ue,a as de}from"./RowActions-eYrzgQSj.js";import{E as he,a as ge,T as fe,b as xe}from"./escalation-columns-CUtDSbxl.js";import{L as be}from"./ListToolbar-BEogxu1f.js";import{E as we}from"./CountdownTimer-Cvif0QtN.js";import{B as ye,al as Pe,am as ve,P as Se,ap as je}from"./vendor-icons-h-jlRSb9.js";import{u as Ce,a as Re,f as Ee}from"./vendor-react-CdqEC2zv.js";import"./EmptyState-lpUFYfun.js";import"./EntityTimelinePanel-D3QNqDiL.js";import"./FilterBar-fwUqeM-5.js";import"./PriorityBadge-BETdj4M-.js";import"./RolePill-Di_5hfvw.js";import"./WorkflowPill-CN-952iI.js";import"./StatusBadge-BDeUwPtb.js";import"./Modal-BU7No9NH.js";function Xe(){var N;const T=Ce(),{user:i,isSuperAdmin:V,hasRoleType:z}=K(),{filters:o,setFilter:y,pagination:t,sort:x,setSort:F}=re({filters:{role:"",type:"",priority:"",search:""}});ie({role:o.role||null,verbs:["claimed","resolved"]});const O=ne(o.search,300),A=W(),{data:b}=Y(),{data:w}=J(),{data:n}=X(),P=V||z("admin"),v=f.useMemo(()=>new Set(((i==null?void 0:i.roles)??[]).map(s=>s.role)),[i]),M=f.useMemo(()=>{const s=(n==null?void 0:n.roles)??[];return(P?s:s.filter(a=>v.has(a.role)&&!ce(a.role))).map(a=>({value:a.role,label:Z(a)})).sort((a,H)=>a.label.localeCompare(H.label))},[n,P,v]),l=Re(),{data:c}=ee(),S=se(),_=f.useCallback(()=>{var a;const s=window.prompt("Pin label:");if(!(s!=null&&s.trim()))return;const g=((a=c==null?void 0:c.preferences)==null?void 0:a.pinnedViews)??[];S.mutate({pinnedViews:[...g,{id:te(),label:s.trim(),url:l.pathname+l.search,badge:!0}]})},[l.pathname,l.search,c,S]),[I,j]=Ee(),C=I.get("view"),U=f.useCallback(s=>{j(g=>{const a=new URLSearchParams(g);return s?a.set("view",s):a.delete("view"),a},{replace:!0})},[j]),m=o.role||null,p=((N=ae(m??"",void 0,!!m).data)==null?void 0:N.list_schema)??null,R=!!m&&!!p&&!!p["x-lt-layout"]&&p["x-lt-layout"]!=="table",u=R&&(C?C==="rich":!0),E={assigned_to:i==null?void 0:i.userId,status:"pending",role:o.role||void 0,type:o.type||void 0,priority:o.priority?parseInt(o.priority):void 0,search:O||void 0,sort_by:x.sort_by||"created_at",order:x.order||"desc"},{data:r,isLoading:q,error:d,refetch:B,isFetching:Q}=oe({...E,limit:t.pageSize,offset:t.offset}),k=(r==null?void 0:r.escalations)??[],h=(r==null?void 0:r.total)??0,D=le("/escalations",{...E,limit:t.pageSize,offset:t.offset}),G={key:"actions",label:"",render:s=>e.jsx(ue,{children:e.jsx(de,{icon:je,title:"Release escalation",onClick:()=>A.mutate(s.id),alwaysVisible:!0,colorClass:"text-status-warning/40 hover:text-status-warning"})}),className:"w-16 text-right"},$=[fe,...xe,G],L=s=>T(`/escalations/detail/${s.id}`,{state:{from:"/escalations/queue"}});return e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center gap-2 mb-10 min-w-0",children:[e.jsx(he,{role:o.role,options:M,onChange:s=>y("role",s),emptyLabel:"My Escalations"}),e.jsx("button",{onClick:()=>{window.location.hash="#docs:dashboard.md:all-escalations"},className:"text-text-quaternary hover:text-accent transition-colors mt-1 shrink-0",title:"Open docs for this page",children:e.jsx(ye,{className:"w-4 h-4",strokeWidth:1.5})})]}),e.jsx(ge,{filters:o,setFilter:y,roles:(b==null?void 0:b.roles)??[],types:(w==null?void 0:w.types)??[],actions:e.jsxs(e.Fragment,{children:[e.jsx(be,{onRefresh:()=>B(),isFetching:Q,apiPath:D}),R&&e.jsx("button",{onClick:()=>U(u?"table":"rich"),className:"ml-2 inline-flex h-7 w-7 items-center justify-center rounded icon-link hover:bg-surface-hover",title:u?"Table view":"Rich view",children:u?e.jsx(Pe,{className:"w-4 h-4"}):e.jsx(ve,{className:"w-4 h-4"})}),e.jsx("button",{onClick:_,className:"ml-2 inline-flex h-7 w-7 items-center justify-center rounded icon-link hover:bg-surface-hover",title:"Pin this view — save the current filters to your Pinned section","data-testid":"pin-current-view",children:e.jsx(Se,{className:"w-4 h-4"})})]})}),d&&e.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:d.message==="Session expired"?"Your session has expired. Please log in again.":`Failed to load escalations: ${d.message}`}),u?e.jsx(we,{role:m,listSchema:p,activeEscalations:k,onRowClick:L,forceViewAction:!0,total:h,page:t.page,totalPages:t.totalPages(h),pageSize:t.pageSize,onPageChange:t.setPage,onPageSizeChange:t.setPageSize}):e.jsxs(e.Fragment,{children:[e.jsx(me,{columns:$,data:k,layout:"fixed",keyFn:s=>s.id,onRowClick:L,isLoading:q,emptyMessage:d?"Unable to load data":"No assigned escalations",sort:x,onSort:F}),e.jsx(pe,{page:t.page,totalPages:t.totalPages(h),onPageChange:t.setPage,total:h,pageSize:t.pageSize,onPageSizeChange:t.setPageSize})]})]})}export{Xe as OperatorDashboard};
|
|
2
|
-
//# sourceMappingURL=OperatorDashboard-Dx7639os.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"OperatorDashboard-Dx7639os.js","sources":["../../src/pages/operator/OperatorDashboard.tsx"],"sourcesContent":["import { useCallback, useMemo } from 'react';\nimport { useNavigate, useLocation, useSearchParams } from 'react-router-dom';\nimport { LockOpen, Pin, LayoutList, Table, BookOpen } from 'lucide-react';\nimport { useAuth } from '../../hooks/useAuth';\nimport { useEscalations, useEscalationTypes, useReleaseEscalation } from '../../api/escalations';\nimport { useEscalationListEvents } from '../../hooks/useEventHooks';\nimport { useRoles, useRoleDetails, useRoleListSchema } from '../../api/roles';\nimport { useFilterParams } from '../../hooks/useFilterParams';\nimport { useDebouncedValue } from '../../hooks/useDebouncedValue';\nimport { buildApiPath } from '../../lib/api-path';\nimport { isSystemTierRole } from '../../lib/task-queues';\nimport { displayRoleTitle } from '../../lib/role-display';\nimport { DataTable, type Column } from '../../components/common/data/DataTable';\nimport { StickyPagination } from '../../components/common/data/StickyPagination';\nimport { RowAction, RowActionGroup } from '../../components/common/layout/RowActions';\nimport { ESCALATION_COLUMNS, TIME_LEFT_COLUMN, EscalationFilterBar } from './escalation-columns';\nimport { EscalationTitleSelect } from './EscalationTitleSelect';\nimport { ListToolbar } from '../../components/common/data/ListToolbar';\nimport { EscalationListView } from '../../components/escalation/EscalationListView';\nimport { usePatchPreferences, usePreferences } from '../../api/preferences';\nimport { newPinId } from '../../lib/pinned-views';\nimport type { LTEscalationRecord } from '../../api/types';\n\nexport function OperatorDashboard() {\n const navigate = useNavigate();\n const { user, isSuperAdmin, hasRoleType } = useAuth();\n const { filters, setFilter, pagination, sort, setSort } = useFilterParams({\n filters: { role: '', type: '', priority: '', search: '' },\n });\n // The personal inbox moves on claims arriving and work leaving — claimed\n // and resolved. A role filter narrows the subscription to that queue's\n // subject token; nothing else in the escalation space reaches this page.\n useEscalationListEvents({ role: filters.role || null, verbs: ['claimed', 'resolved'] });\n // Debounce so server-side search fires once the user pauses, not per keystroke.\n const debouncedSearch = useDebouncedValue(filters.search, 300);\n const release = useReleaseEscalation();\n const { data: rolesData } = useRoles();\n const { data: typesData } = useEscalationTypes();\n\n // The title doubles as the queue selector, reading as the chosen role's\n // friendly title — the same control the All Escalations page carries, over\n // the same ?role= param the filter bar mirrors.\n const { data: roleDetails } = useRoleDetails();\n const isGlobalViewer = isSuperAdmin || hasRoleType('admin');\n const memberRoleSet = useMemo(() => new Set((user?.roles ?? []).map((r) => r.role)), [user]);\n const roleOptions = useMemo(() => {\n const all = roleDetails?.roles ?? [];\n const visible = isGlobalViewer\n ? all\n : all.filter((r) => memberRoleSet.has(r.role) && !isSystemTierRole(r.role));\n return visible\n .map((r) => ({ value: r.role, label: displayRoleTitle(r) }))\n .sort((a, b) => a.label.localeCompare(b.label));\n }, [roleDetails, isGlobalViewer, memberRoleSet]);\n\n // Pin current view — the same gesture as All Escalations: every filter is\n // already deep-linked in the URL, so a pin is just the labeled URL.\n const location = useLocation();\n const { data: prefsData } = usePreferences();\n const patchPrefs = usePatchPreferences();\n const pinCurrentView = useCallback(() => {\n const label = window.prompt('Pin label:');\n if (!label?.trim()) return;\n const existing = prefsData?.preferences?.pinnedViews ?? [];\n patchPrefs.mutate({\n pinnedViews: [\n ...existing,\n { id: newPinId(), label: label.trim(), url: location.pathname + location.search, badge: true },\n ],\n });\n }, [location.pathname, location.search, prefsData, patchPrefs]);\n\n // Role-owned rich view — the same resolution the queue page runs, applied to\n // the personal inbox when one role is filtered. Deep-linked (?view=rich|table)\n // so a pinned link reproduces the presentation; absent, rich wins when the\n // role owns a non-table list_schema. Row actions render in view mode: every\n // row here is already held by the viewer, so claim gestures don't apply.\n const [searchParams, setSearchParams] = useSearchParams();\n const viewParam = searchParams.get('view');\n const setViewParam = useCallback((v: 'table' | 'rich' | null) => {\n setSearchParams((prev) => {\n const p = new URLSearchParams(prev);\n if (v) p.set('view', v); else p.delete('view');\n return p;\n }, { replace: true });\n }, [setSearchParams]);\n const singleRole = filters.role || null;\n const listSchemaQuery = useRoleListSchema(singleRole ?? '', undefined, !!singleRole);\n const listSchema = (listSchemaQuery.data?.list_schema ?? null) as Record<string, any> | null;\n const hasRichView = !!singleRole && !!listSchema\n && !!listSchema['x-lt-layout'] && listSchema['x-lt-layout'] !== 'table';\n const useRichView = hasRichView && (viewParam ? viewParam === 'rich' : true);\n\n const escalationQuery = {\n assigned_to: user?.userId,\n status: 'pending',\n role: filters.role || undefined,\n type: filters.type || undefined,\n priority: filters.priority ? parseInt(filters.priority) : undefined,\n search: debouncedSearch || undefined,\n sort_by: sort.sort_by || 'created_at',\n order: sort.order || 'desc',\n };\n\n const { data, isLoading, error: queryError, refetch, isFetching } = useEscalations({\n ...escalationQuery,\n limit: pagination.pageSize,\n offset: pagination.offset,\n });\n\n // Search is server-side (full result set) — results and total come straight\n // from the query, no client-side filtering of the current page.\n const activeClaims = data?.escalations ?? [];\n const total = data?.total ?? 0;\n\n // Copy-URL/curl path built from the SAME params the query sends.\n const apiPath = buildApiPath('/escalations', {\n ...escalationQuery,\n limit: pagination.pageSize,\n offset: pagination.offset,\n });\n\n const releaseColumn: Column<LTEscalationRecord> = {\n key: 'actions',\n label: '',\n render: (row) => (\n <RowActionGroup>\n <RowAction\n icon={LockOpen}\n title=\"Release escalation\"\n onClick={() => release.mutate(row.id)}\n alwaysVisible\n colorClass=\"text-status-warning/40 hover:text-status-warning\"\n />\n </RowActionGroup>\n ),\n className: 'w-16 text-right',\n };\n\n // Time-left first (aligns with checkbox on All Escalations), then summary + base columns + actions\n const columns: Column<LTEscalationRecord>[] = [\n TIME_LEFT_COLUMN,\n ...ESCALATION_COLUMNS,\n releaseColumn,\n ];\n\n const openDetail = (row: LTEscalationRecord) =>\n navigate(`/escalations/detail/${row.id}`, { state: { from: '/escalations/queue' } });\n\n return (\n <div>\n {/* The title IS the queue selector: it reads as the chosen role's title,\n or \"My Escalations\" — the personal inbox, narrowed the same way the\n All Escalations page narrows. */}\n <div className=\"flex items-center gap-2 mb-10 min-w-0\">\n <EscalationTitleSelect\n role={filters.role}\n options={roleOptions}\n onChange={(v) => setFilter('role', v)}\n emptyLabel=\"My Escalations\"\n />\n <button\n onClick={() => { window.location.hash = '#docs:dashboard.md:all-escalations'; }}\n className=\"text-text-quaternary hover:text-accent transition-colors mt-1 shrink-0\"\n title=\"Open docs for this page\"\n >\n <BookOpen className=\"w-4 h-4\" strokeWidth={1.5} />\n </button>\n </div>\n\n <EscalationFilterBar\n filters={filters}\n setFilter={setFilter}\n roles={rolesData?.roles ?? []}\n types={typesData?.types ?? []}\n actions={\n <>\n <ListToolbar\n onRefresh={() => refetch()}\n isFetching={isFetching}\n apiPath={apiPath}\n />\n {hasRichView && (\n <button\n onClick={() => setViewParam(useRichView ? 'table' : 'rich')}\n className=\"ml-2 inline-flex h-7 w-7 items-center justify-center rounded icon-link hover:bg-surface-hover\"\n title={useRichView ? 'Table view' : 'Rich view'}\n >\n {useRichView\n ? <Table className=\"w-4 h-4\" />\n : <LayoutList className=\"w-4 h-4\" />}\n </button>\n )}\n <button\n onClick={pinCurrentView}\n className=\"ml-2 inline-flex h-7 w-7 items-center justify-center rounded icon-link hover:bg-surface-hover\"\n title=\"Pin this view — save the current filters to your Pinned section\"\n data-testid=\"pin-current-view\"\n >\n <Pin className=\"w-4 h-4\" />\n </button>\n </>\n }\n />\n\n {queryError && (\n <div className=\"mb-4 px-4 py-3 rounded-md bg-status-error/10 border border-status-error/20 text-xs text-status-error\">\n {(queryError as Error).message === 'Session expired'\n ? 'Your session has expired. Please log in again.'\n : `Failed to load escalations: ${(queryError as Error).message}`}\n </div>\n )}\n\n {useRichView ? (\n <EscalationListView\n role={singleRole!}\n listSchema={listSchema!}\n activeEscalations={activeClaims}\n onRowClick={openDetail}\n forceViewAction\n total={total}\n page={pagination.page}\n totalPages={pagination.totalPages(total)}\n pageSize={pagination.pageSize}\n onPageChange={pagination.setPage}\n onPageSizeChange={pagination.setPageSize}\n />\n ) : (\n <>\n <DataTable\n columns={columns}\n data={activeClaims}\n layout=\"fixed\"\n keyFn={(row) => row.id}\n onRowClick={openDetail}\n isLoading={isLoading}\n emptyMessage={queryError ? 'Unable to load data' : 'No assigned escalations'}\n sort={sort}\n onSort={setSort}\n />\n\n <StickyPagination\n page={pagination.page}\n totalPages={pagination.totalPages(total)}\n onPageChange={pagination.setPage}\n total={total}\n pageSize={pagination.pageSize}\n onPageSizeChange={pagination.setPageSize}\n />\n </>\n )}\n </div>\n );\n}\n"],"names":["OperatorDashboard","navigate","useNavigate","user","isSuperAdmin","hasRoleType","useAuth","filters","setFilter","pagination","sort","setSort","useFilterParams","useEscalationListEvents","debouncedSearch","useDebouncedValue","release","useReleaseEscalation","rolesData","useRoles","typesData","useEscalationTypes","roleDetails","useRoleDetails","isGlobalViewer","memberRoleSet","useMemo","r","roleOptions","all","isSystemTierRole","displayRoleTitle","b","location","useLocation","prefsData","usePreferences","patchPrefs","usePatchPreferences","pinCurrentView","useCallback","label","existing","_a","newPinId","searchParams","setSearchParams","useSearchParams","viewParam","setViewParam","v","prev","p","singleRole","listSchema","useRoleListSchema","hasRichView","useRichView","escalationQuery","data","isLoading","queryError","refetch","isFetching","useEscalations","activeClaims","total","apiPath","buildApiPath","releaseColumn","row","jsx","RowActionGroup","RowAction","LockOpen","columns","TIME_LEFT_COLUMN","ESCALATION_COLUMNS","openDetail","jsxs","EscalationTitleSelect","BookOpen","EscalationFilterBar","Fragment","ListToolbar","Table","LayoutList","Pin","EscalationListView","DataTable","StickyPagination"],"mappings":"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"}
|