@hotmeshio/long-tail 0.8.4 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/api/escalations/index.d.ts +1 -1
- package/build/api/escalations/index.js +2 -1
- package/build/api/escalations/resolve.d.ts +28 -0
- package/build/api/escalations/resolve.js +98 -0
- package/build/api/roles.d.ts +21 -0
- package/build/api/roles.js +50 -0
- package/build/lib/db/index.js +12 -1
- package/build/lib/db/migrate.js +27 -0
- package/build/lib/db/schemas/021_role_list_schema.sql +27 -0
- package/build/modules/defaults.d.ts +2 -0
- package/build/modules/defaults.js +3 -1
- package/build/routes/escalations/resolve.js +18 -0
- package/build/routes/roles.js +20 -0
- package/build/sdk/index.d.ts +8 -0
- package/build/sdk/index.js +1 -0
- package/build/services/escalation/crud.d.ts +36 -0
- package/build/services/escalation/crud.js +53 -0
- package/build/services/maintenance/index.js +22 -0
- package/build/services/role/index.d.ts +13 -1
- package/build/services/role/index.js +27 -0
- package/build/services/role/sql.d.ts +14 -2
- package/build/services/role/sql.js +51 -3
- package/build/services/role/types.d.ts +27 -0
- package/build/types/maintenance.d.ts +6 -1
- package/dashboard/dist/assets/{AdminDashboard-B-JptT54.js → AdminDashboard-5bWcBxyS.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-B-JptT54.js.map → AdminDashboard-5bWcBxyS.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-B1Jc6iJk.js → AgentConfigPage-CVg_tFbf.js} +6 -6
- package/dashboard/dist/assets/{AgentConfigPage-B1Jc6iJk.js.map → AgentConfigPage-CVg_tFbf.js.map} +1 -1
- package/dashboard/dist/assets/{AgentDetailPage-CWpclCOY.js → AgentDetailPage-CLlkIoRQ.js} +4 -4
- package/dashboard/dist/assets/{AgentDetailPage-CWpclCOY.js.map → AgentDetailPage-CLlkIoRQ.js.map} +1 -1
- package/dashboard/dist/assets/{AgentsPage-DyAf5GA2.js → AgentsPage-CjruF_ek.js} +2 -2
- package/dashboard/dist/assets/{AgentsPage-DyAf5GA2.js.map → AgentsPage-CjruF_ek.js.map} +1 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-h6awiuVk.js +2 -0
- package/dashboard/dist/assets/AvailableEscalationsPage-h6awiuVk.js.map +1 -0
- package/dashboard/dist/assets/{BotPicker-B1RdaNuY.js → BotPicker-CGEFHHDE.js} +2 -2
- package/dashboard/dist/assets/{BotPicker-B1RdaNuY.js.map → BotPicker-CGEFHHDE.js.map} +1 -1
- package/dashboard/dist/assets/{CapabilitiesPage-CxHDnyjX.js → CapabilitiesPage-BI1tNYun.js} +2 -2
- package/dashboard/dist/assets/{CapabilitiesPage-CxHDnyjX.js.map → CapabilitiesPage-BI1tNYun.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-Ds0e8cCO.js → CollapsibleSection-B9f52Z2K.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-Ds0e8cCO.js.map → CollapsibleSection-B9f52Z2K.js.map} +1 -1
- package/dashboard/dist/assets/{CopyableId-blg-gZvT.js → CopyableId-uot2mE_g.js} +2 -2
- package/dashboard/dist/assets/{CopyableId-blg-gZvT.js.map → CopyableId-uot2mE_g.js.map} +1 -1
- package/dashboard/dist/assets/CountdownTimer-C71erQ67.js +2 -0
- package/dashboard/dist/assets/CountdownTimer-C71erQ67.js.map +1 -0
- package/dashboard/dist/assets/{CredentialsPage-D8UVO-3A.js → CredentialsPage-smk5H_mP.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-D8UVO-3A.js.map → CredentialsPage-smk5H_mP.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-ZesYXxCH.js → CronLabel-CCJLmkIq.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-ZesYXxCH.js.map → CronLabel-CCJLmkIq.js.map} +1 -1
- package/dashboard/dist/assets/CustomDurationPicker-DQ28g5GB.js +2 -0
- package/dashboard/dist/assets/CustomDurationPicker-DQ28g5GB.js.map +1 -0
- package/dashboard/dist/assets/DataTable-Byn3oyT9.js +2 -0
- package/dashboard/dist/assets/DataTable-Byn3oyT9.js.map +1 -0
- package/dashboard/dist/assets/{DropZone-SgiK1WOl.js → DropZone-C_Mc4UrO.js} +2 -2
- package/dashboard/dist/assets/{DropZone-SgiK1WOl.js.map → DropZone-C_Mc4UrO.js.map} +1 -1
- package/dashboard/dist/assets/{ElapsedCell-CO8S6vdb.js → ElapsedCell-Cw1uvJKx.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-CO8S6vdb.js.map → ElapsedCell-Cw1uvJKx.js.map} +1 -1
- package/dashboard/dist/assets/EscalationListSchemaPage-3v2tiCnq.js +20 -0
- package/dashboard/dist/assets/EscalationListSchemaPage-3v2tiCnq.js.map +1 -0
- package/dashboard/dist/assets/EscalationSchemaPage-DIq2pMED.js +9 -0
- package/dashboard/dist/assets/EscalationSchemaPage-DIq2pMED.js.map +1 -0
- package/dashboard/dist/assets/{EscalationsOverview-DMpRvVql.js → EscalationsOverview-BqOZ1v8w.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-DMpRvVql.js.map → EscalationsOverview-BqOZ1v8w.js.map} +1 -1
- package/dashboard/dist/assets/EventTable-CyfHfOWj.js +2 -0
- package/dashboard/dist/assets/EventTable-CyfHfOWj.js.map +1 -0
- package/dashboard/dist/assets/{FilterBar-B4Mk2PvT.js → FilterBar-DDIn8TOs.js} +2 -2
- package/dashboard/dist/assets/{FilterBar-B4Mk2PvT.js.map → FilterBar-DDIn8TOs.js.map} +1 -1
- package/dashboard/dist/assets/{GraphInvokePage-CTuul-av.js → GraphInvokePage-DbNUaWhH.js} +2 -2
- package/dashboard/dist/assets/{GraphInvokePage-CTuul-av.js.map → GraphInvokePage-DbNUaWhH.js.map} +1 -1
- package/dashboard/dist/assets/{HomePage-BKFpOaHX.js → HomePage-Cj9sLt4Z.js} +2 -2
- package/dashboard/dist/assets/{HomePage-BKFpOaHX.js.map → HomePage-Cj9sLt4Z.js.map} +1 -1
- package/dashboard/dist/assets/{ListToolbar-Dz2_neVF.js → ListToolbar-D7PoQOZC.js} +2 -2
- package/dashboard/dist/assets/{ListToolbar-Dz2_neVF.js.map → ListToolbar-D7PoQOZC.js.map} +1 -1
- package/dashboard/dist/assets/{McpOverview-Do-vaEqV.js → McpOverview-D9g1iJyn.js} +2 -2
- package/dashboard/dist/assets/{McpOverview-Do-vaEqV.js.map → McpOverview-D9g1iJyn.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryDetailPage-HwDGNSbN.js → McpQueryDetailPage-DwS1pXdT.js} +2 -2
- package/dashboard/dist/assets/{McpQueryDetailPage-HwDGNSbN.js.map → McpQueryDetailPage-DwS1pXdT.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryPage-DxMUpQ7R.js → McpQueryPage-DZQ1z6-H.js} +2 -2
- package/dashboard/dist/assets/{McpQueryPage-DxMUpQ7R.js.map → McpQueryPage-DZQ1z6-H.js.map} +1 -1
- package/dashboard/dist/assets/McpRunDetailPage-Bx6w39lr.js +2 -0
- package/dashboard/dist/assets/{McpRunDetailPage-BzzZIXIk.js.map → McpRunDetailPage-Bx6w39lr.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunsPage-D3J42d2i.js → McpRunsPage-C-oS_tTh.js} +2 -2
- package/dashboard/dist/assets/{McpRunsPage-D3J42d2i.js.map → McpRunsPage-C-oS_tTh.js.map} +1 -1
- package/dashboard/dist/assets/{NamespacePill-SErKwgkb.js → NamespacePill-DhgC3EUO.js} +2 -2
- package/dashboard/dist/assets/{NamespacePill-SErKwgkb.js.map → NamespacePill-DhgC3EUO.js.map} +1 -1
- package/dashboard/dist/assets/OperationsPage-CQzX6jM1.js +2 -0
- package/dashboard/dist/assets/OperationsPage-CQzX6jM1.js.map +1 -0
- package/dashboard/dist/assets/OperatorDashboard-Cqf87ojd.js +2 -0
- package/dashboard/dist/assets/{OperatorDashboard-BqJn8wEZ.js.map → OperatorDashboard-Cqf87ojd.js.map} +1 -1
- package/dashboard/dist/assets/PageHeader-sGNTmSXX.js +2 -0
- package/dashboard/dist/assets/PageHeader-sGNTmSXX.js.map +1 -0
- package/dashboard/dist/assets/{PageHeaderWithStats-W3akV6nB.js → PageHeaderWithStats-87STTAJX.js} +2 -2
- package/dashboard/dist/assets/{PageHeaderWithStats-W3akV6nB.js.map → PageHeaderWithStats-87STTAJX.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessDetailPage-C8sT2xuE.js → ProcessDetailPage-CplnDXkz.js} +2 -2
- package/dashboard/dist/assets/{ProcessDetailPage-C8sT2xuE.js.map → ProcessDetailPage-CplnDXkz.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessesListPage-eA8buUgd.js → ProcessesListPage-DFOJC27f.js} +2 -2
- package/dashboard/dist/assets/{ProcessesListPage-eA8buUgd.js.map → ProcessesListPage-DFOJC27f.js.map} +1 -1
- package/dashboard/dist/assets/RoleDetailPage-VrWOaPlg.js +8 -0
- package/dashboard/dist/assets/RoleDetailPage-VrWOaPlg.js.map +1 -0
- package/dashboard/dist/assets/{RolePill-DHWixsQR.js → RolePill-C91qbDOW.js} +2 -2
- package/dashboard/dist/assets/{RolePill-DHWixsQR.js.map → RolePill-C91qbDOW.js.map} +1 -1
- package/dashboard/dist/assets/{RolesPage-BQNQxsMY.js → RolesPage-DdI1rVAP.js} +2 -2
- package/dashboard/dist/assets/{RolesPage-BQNQxsMY.js.map → RolesPage-DdI1rVAP.js.map} +1 -1
- package/dashboard/dist/assets/{RunAsSelector-mhusrlYE.js → RunAsSelector-C6EozzKV.js} +2 -2
- package/dashboard/dist/assets/{RunAsSelector-mhusrlYE.js.map → RunAsSelector-C6EozzKV.js.map} +1 -1
- package/dashboard/dist/assets/SlidePanel-BpWveV1T.js +2 -0
- package/dashboard/dist/assets/SlidePanel-BpWveV1T.js.map +1 -0
- package/dashboard/dist/assets/{StatusBadge-DZ9137bI.js → StatusBadge-CEQMRmSQ.js} +2 -2
- package/dashboard/dist/assets/StatusBadge-CEQMRmSQ.js.map +1 -0
- package/dashboard/dist/assets/{StickyPagination-CqT9Q1I6.js → StickyPagination-BEgkYJ0-.js} +2 -2
- package/dashboard/dist/assets/{StickyPagination-CqT9Q1I6.js.map → StickyPagination-BEgkYJ0-.js.map} +1 -1
- package/dashboard/dist/assets/{StreamMessageDetail-jOJaoupp.js → StreamMessageDetail-DWVPtzj7.js} +2 -2
- package/dashboard/dist/assets/{StreamMessageDetail-jOJaoupp.js.map → StreamMessageDetail-DWVPtzj7.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-BrfmWgAj.js → SwimlaneTimeline-4NrDJNYc.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-BrfmWgAj.js.map → SwimlaneTimeline-4NrDJNYc.js.map} +1 -1
- package/dashboard/dist/assets/{TagInput-CGGC3DTR.js → TagInput-Csm36_pS.js} +2 -2
- package/dashboard/dist/assets/{TagInput-CGGC3DTR.js.map → TagInput-Csm36_pS.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-Cus_JHIC.js → TaskDetailPage-BvdaAUtF.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-Cus_JHIC.js.map → TaskDetailPage-BvdaAUtF.js.map} +1 -1
- package/dashboard/dist/assets/{TaskQueuePill-D6omQJNY.js → TaskQueuePill-5XdNaqwM.js} +2 -2
- package/dashboard/dist/assets/{TaskQueuePill-D6omQJNY.js.map → TaskQueuePill-5XdNaqwM.js.map} +1 -1
- package/dashboard/dist/assets/{TasksListPage-B7GK8AoX.js → TasksListPage-BxA161LH.js} +2 -2
- package/dashboard/dist/assets/{TasksListPage-B7GK8AoX.js.map → TasksListPage-BxA161LH.js.map} +1 -1
- package/dashboard/dist/assets/{TimeAgo-C606LzT3.js → TimeAgo-ChwJ4fjZ.js} +2 -2
- package/dashboard/dist/assets/{TimeAgo-C606LzT3.js.map → TimeAgo-ChwJ4fjZ.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-hfh6zvH-.js → TimestampCell-C7KzmvyC.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-hfh6zvH-.js.map → TimestampCell-C7KzmvyC.js.map} +1 -1
- package/dashboard/dist/assets/{ToolPill-BW0iRwZu.js → ToolPill-CAwj7EPw.js} +2 -2
- package/dashboard/dist/assets/{ToolPill-BW0iRwZu.js.map → ToolPill-CAwj7EPw.js.map} +1 -1
- package/dashboard/dist/assets/{ToolTestPanel-CsPsyvQq.js → ToolTestPanel-ISkuXtkT.js} +2 -2
- package/dashboard/dist/assets/{ToolTestPanel-CsPsyvQq.js.map → ToolTestPanel-ISkuXtkT.js.map} +1 -1
- package/dashboard/dist/assets/{TopicDetailPage-Diz6r7zr.js → TopicDetailPage-D8uZ8Wbs.js} +3 -3
- package/dashboard/dist/assets/{TopicDetailPage-Diz6r7zr.js.map → TopicDetailPage-D8uZ8Wbs.js.map} +1 -1
- package/dashboard/dist/assets/TopicsPage-rj88vA_1.js +2 -0
- package/dashboard/dist/assets/{TopicsPage-B6fn7fFh.js.map → TopicsPage-rj88vA_1.js.map} +1 -1
- package/dashboard/dist/assets/{UserName-Cc-5QH5q.js → UserName-D03Lh6Aj.js} +2 -2
- package/dashboard/dist/assets/{UserName-Cc-5QH5q.js.map → UserName-D03Lh6Aj.js.map} +1 -1
- package/dashboard/dist/assets/WorkflowExecutionPage-LD9WzPee.js +2 -0
- package/dashboard/dist/assets/WorkflowExecutionPage-LD9WzPee.js.map +1 -0
- package/dashboard/dist/assets/{WorkflowPill-BtNBSplz.js → WorkflowPill-fodIWnT3.js} +2 -2
- package/dashboard/dist/assets/{WorkflowPill-BtNBSplz.js.map → WorkflowPill-fodIWnT3.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsDashboard-CHCM6hUa.js → WorkflowsDashboard-DH0jitAb.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsDashboard-CHCM6hUa.js.map → WorkflowsDashboard-DH0jitAb.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsOverview-WeOvl8-_.js → WorkflowsOverview-D6BVaH9e.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-WeOvl8-_.js.map → WorkflowsOverview-D6BVaH9e.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-6GfhVDpv.js → YamlWorkflowDetailPage-D_CfNEqW.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-6GfhVDpv.js.map → YamlWorkflowDetailPage-D_CfNEqW.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowsPage-DqcY3ocP.js → YamlWorkflowsPage-BMJgtcAq.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowsPage-DqcY3ocP.js.map → YamlWorkflowsPage-BMJgtcAq.js.map} +1 -1
- package/dashboard/dist/assets/{agents-DlzvjNxE.js → agents-Ci0tZDO3.js} +2 -2
- package/dashboard/dist/assets/{agents-DlzvjNxE.js.map → agents-Ci0tZDO3.js.map} +1 -1
- package/dashboard/dist/assets/{bots-CWMN-KUI.js → bots-DZyt1oO4.js} +2 -2
- package/dashboard/dist/assets/{bots-CWMN-KUI.js.map → bots-DZyt1oO4.js.map} +1 -1
- package/dashboard/dist/assets/{capabilities-_WSZ7cxO.js → capabilities-DzVKeWyC.js} +2 -2
- package/dashboard/dist/assets/{capabilities-_WSZ7cxO.js.map → capabilities-DzVKeWyC.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-_k9nWZy3.js → controlplane-CQzrn-rD.js} +2 -2
- package/dashboard/dist/assets/{controlplane-_k9nWZy3.js.map → controlplane-CQzrn-rD.js.map} +1 -1
- package/dashboard/dist/assets/escalation-columns-s29Q4mrF.js +2 -0
- package/dashboard/dist/assets/{escalation-columns-Dyrf6Tdp.js.map → escalation-columns-s29Q4mrF.js.map} +1 -1
- package/dashboard/dist/assets/{index-kKufOPLo.js → index-3SrgIA7w.js} +2 -2
- package/dashboard/dist/assets/{index-kKufOPLo.js.map → index-3SrgIA7w.js.map} +1 -1
- package/dashboard/dist/assets/{index-Dd4Si1Rl.js → index-B2dB90aC.js} +2 -2
- package/dashboard/dist/assets/{index-Dd4Si1Rl.js.map → index-B2dB90aC.js.map} +1 -1
- package/dashboard/dist/assets/index-BSOcWfeR.js +5 -0
- package/dashboard/dist/assets/index-BSOcWfeR.js.map +1 -0
- package/dashboard/dist/assets/{index-uUYXmvFf.js → index-BWy4UvaT.js} +2 -2
- package/dashboard/dist/assets/{index-uUYXmvFf.js.map → index-BWy4UvaT.js.map} +1 -1
- package/dashboard/dist/assets/{index-C3h0qGzG.js → index-BqKxJ2fB.js} +2 -2
- package/dashboard/dist/assets/{index-C3h0qGzG.js.map → index-BqKxJ2fB.js.map} +1 -1
- package/dashboard/dist/assets/{index-DwWP-Z_c.js → index-C9moIiIq.js} +5 -5
- package/dashboard/dist/assets/{index-DwWP-Z_c.js.map → index-C9moIiIq.js.map} +1 -1
- package/dashboard/dist/assets/{index-Dc-Ye2wk.js → index-CcKXMU-s.js} +2 -2
- package/dashboard/dist/assets/{index-Dc-Ye2wk.js.map → index-CcKXMU-s.js.map} +1 -1
- package/dashboard/dist/assets/index-DIPe82gq.css +1 -0
- package/dashboard/dist/assets/{index-D8GcHxNJ.js → index-DOHGHMP7.js} +2 -2
- package/dashboard/dist/assets/{index-D8GcHxNJ.js.map → index-DOHGHMP7.js.map} +1 -1
- package/dashboard/dist/assets/{index-C5Yc3TT7.js → index-DTn4XzYN.js} +2 -2
- package/dashboard/dist/assets/{index-C5Yc3TT7.js.map → index-DTn4XzYN.js.map} +1 -1
- package/dashboard/dist/assets/index-Dv8mzG9B.js +2 -0
- package/dashboard/dist/assets/index-Dv8mzG9B.js.map +1 -0
- package/dashboard/dist/assets/{index-Ex5tEte8.js → index-LwodswlU.js} +2 -2
- package/dashboard/dist/assets/{index-Ex5tEte8.js.map → index-LwodswlU.js.map} +1 -1
- package/dashboard/dist/assets/{index-C7VXLKJs.js → index-kPipMHZx.js} +2 -2
- package/dashboard/dist/assets/{index-C7VXLKJs.js.map → index-kPipMHZx.js.map} +1 -1
- package/dashboard/dist/assets/{index-BiApvBEz.js → index-sdc9ecdW.js} +2 -2
- package/dashboard/dist/assets/{index-BiApvBEz.js.map → index-sdc9ecdW.js.map} +1 -1
- package/dashboard/dist/assets/{knowledge-fYoEF4Lx.js → knowledge-fi5z5YLq.js} +2 -2
- package/dashboard/dist/assets/{knowledge-fYoEF4Lx.js.map → knowledge-fi5z5YLq.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-1lzlgtS8.js → mcp-CH8Tj9Pw.js} +2 -2
- package/dashboard/dist/assets/{mcp-1lzlgtS8.js.map → mcp-CH8Tj9Pw.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-nlrAz7m_.js → mcp-query-6alwNh7K.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-nlrAz7m_.js.map → mcp-query-6alwNh7K.js.map} +1 -1
- package/dashboard/dist/assets/{pipelines-Ihi7EKXi.js → pipelines-Dqh9PLUw.js} +2 -2
- package/dashboard/dist/assets/{pipelines-Ihi7EKXi.js.map → pipelines-Dqh9PLUw.js.map} +1 -1
- package/dashboard/dist/assets/roles-dJKBZUBh.js +2 -0
- package/dashboard/dist/assets/roles-dJKBZUBh.js.map +1 -0
- package/dashboard/dist/assets/{tasks-Crk9Y3C4.js → tasks-BYz490un.js} +2 -2
- package/dashboard/dist/assets/{tasks-Crk9Y3C4.js.map → tasks-BYz490un.js.map} +1 -1
- package/dashboard/dist/assets/{topics-CtfcCyw9.js → topics-Dt975EWi.js} +2 -2
- package/dashboard/dist/assets/{topics-CtfcCyw9.js.map → topics-Dt975EWi.js.map} +1 -1
- package/dashboard/dist/assets/{useEventHooks-Dn_vN2xE.js → useEventHooks-ZT6RV2Gj.js} +2 -2
- package/dashboard/dist/assets/{useEventHooks-Dn_vN2xE.js.map → useEventHooks-ZT6RV2Gj.js.map} +1 -1
- package/dashboard/dist/assets/{useNamespace-Cfs3vKWk.js → useNamespace-B_G1iE9i.js} +2 -2
- package/dashboard/dist/assets/{useNamespace-Cfs3vKWk.js.map → useNamespace-B_G1iE9i.js.map} +1 -1
- package/dashboard/dist/assets/{useYamlActivityEvents-ymobxH47.js → useYamlActivityEvents-DGkvIadL.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-ymobxH47.js.map → useYamlActivityEvents-DGkvIadL.js.map} +1 -1
- package/dashboard/dist/assets/{users-DngGIiC_.js → users-C2jopvM1.js} +2 -2
- package/dashboard/dist/assets/{users-DngGIiC_.js.map → users-C2jopvM1.js.map} +1 -1
- package/dashboard/dist/assets/{vendor-icons-DOIDKgo6.js → vendor-icons-BXhWQC7l.js} +161 -121
- package/dashboard/dist/assets/vendor-icons-BXhWQC7l.js.map +1 -0
- package/dashboard/dist/assets/{workflows-DuUspMAl.js → workflows-By8Wgvig.js} +2 -2
- package/dashboard/dist/assets/{workflows-DuUspMAl.js.map → workflows-By8Wgvig.js.map} +1 -1
- package/dashboard/dist/assets/{yaml-workflows-DXQCiOsP.js → yaml-workflows-Cq_vp41d.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-DXQCiOsP.js.map → yaml-workflows-Cq_vp41d.js.map} +1 -1
- package/dashboard/dist/index.html +3 -3
- package/docs/api/http/escalations.md +20 -0
- package/docs/api/sdk/escalations.md +37 -2
- package/docs/dashboard.md +16 -3
- package/docs/data.md +1 -1
- package/docs/hitl-guide.md +240 -21
- package/docs/maintenance.md +6 -3
- package/docs/oauth-and-delegation.md +1 -1
- package/package.json +3 -3
- package/dashboard/dist/assets/AvailableEscalationsPage-DDwAgklw.js +0 -2
- package/dashboard/dist/assets/AvailableEscalationsPage-DDwAgklw.js.map +0 -1
- package/dashboard/dist/assets/CustomDurationPicker-OKlwH5a_.js +0 -2
- package/dashboard/dist/assets/CustomDurationPicker-OKlwH5a_.js.map +0 -1
- package/dashboard/dist/assets/DataTable-ZWgVQg7F.js +0 -2
- package/dashboard/dist/assets/DataTable-ZWgVQg7F.js.map +0 -1
- package/dashboard/dist/assets/EscalationSchemaPage-Br5sD8-N.js +0 -9
- package/dashboard/dist/assets/EscalationSchemaPage-Br5sD8-N.js.map +0 -1
- package/dashboard/dist/assets/EventTable-BARJeiS2.js +0 -2
- package/dashboard/dist/assets/EventTable-BARJeiS2.js.map +0 -1
- package/dashboard/dist/assets/McpRunDetailPage-BzzZIXIk.js +0 -2
- package/dashboard/dist/assets/OperationsPage-BaM-QDhy.js +0 -2
- package/dashboard/dist/assets/OperationsPage-BaM-QDhy.js.map +0 -1
- package/dashboard/dist/assets/OperatorDashboard-BqJn8wEZ.js +0 -2
- package/dashboard/dist/assets/PageHeader-DJo7yMUR.js +0 -2
- package/dashboard/dist/assets/PageHeader-DJo7yMUR.js.map +0 -1
- package/dashboard/dist/assets/RoleDetailPage-aR-ror5v.js +0 -11
- package/dashboard/dist/assets/RoleDetailPage-aR-ror5v.js.map +0 -1
- package/dashboard/dist/assets/StatusBadge-DZ9137bI.js.map +0 -1
- package/dashboard/dist/assets/TopicsPage-B6fn7fFh.js +0 -2
- package/dashboard/dist/assets/WorkflowExecutionPage-BFq7UdhA.js +0 -2
- package/dashboard/dist/assets/WorkflowExecutionPage-BFq7UdhA.js.map +0 -1
- package/dashboard/dist/assets/escalation-CK8ElYzD.js +0 -2
- package/dashboard/dist/assets/escalation-CK8ElYzD.js.map +0 -1
- package/dashboard/dist/assets/escalation-columns-Dyrf6Tdp.js +0 -2
- package/dashboard/dist/assets/index-BdqKh0UK.css +0 -1
- package/dashboard/dist/assets/index-OV1JoB_P.js +0 -6
- package/dashboard/dist/assets/index-OV1JoB_P.js.map +0 -1
- package/dashboard/dist/assets/index-ZBj6Xgim.js +0 -2
- package/dashboard/dist/assets/index-ZBj6Xgim.js.map +0 -1
- package/dashboard/dist/assets/roles-D4Wn7kE9.js +0 -2
- package/dashboard/dist/assets/roles-D4Wn7kE9.js.map +0 -1
- package/dashboard/dist/assets/useCollapsedSections-BU5HULGs.js +0 -2
- package/dashboard/dist/assets/useCollapsedSections-BU5HULGs.js.map +0 -1
- package/dashboard/dist/assets/vendor-icons-DOIDKgo6.js.map +0 -1
package/dashboard/dist/assets/{CredentialsPage-D8UVO-3A.js.map → CredentialsPage-smk5H_mP.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CredentialsPage-D8UVO-3A.js","sources":["../../src/pages/settings/CredentialsPage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { Unplug, Trash2, Plus, ChevronDown } from 'lucide-react';\nimport { useOAuthConnections, useDisconnectOAuth } from '../../api/oauth';\nimport { getToken } from '../../api/client';\nimport { PageHeader } from '../../components/common/layout/PageHeader';\nimport { OAuthIcon } from '../../components/common/OAuthIcon';\nimport { TimeAgo } from '../../components/common/display/TimeAgo';\nimport { ConfirmDeleteModal } from '../../components/common/modal/ConfirmDeleteModal';\nimport { LT_BASE } from '../../lib/base-path';\n\ninterface ConnectionToRevoke {\n provider: string;\n label: string;\n}\n\nconst PROVIDERS: Record<string, { name: string; helpText: string; placeholder: string; oauth?: boolean }> = {\n anthropic: {\n name: 'Anthropic',\n helpText: 'Run \"claude setup-token\" for an OAuth token, or use an API key from console.anthropic.com.',\n placeholder: 'sk-ant-oat01-... or sk-ant-api03-...',\n },\n openai: {\n name: 'OpenAI',\n helpText: 'Create an API key at platform.openai.com/api-keys.',\n placeholder: 'sk-...',\n },\n google: {\n name: 'Google',\n helpText: 'Connect your Google account for Gmail, Calendar, and Drive access.',\n placeholder: '',\n oauth: true,\n },\n};\n\nexport function CredentialsPage() {\n const { data, isLoading } = useOAuthConnections();\n const disconnect = useDisconnectOAuth();\n const [confirmRevoke, setConfirmRevoke] = useState<ConnectionToRevoke | null>(null);\n const [addOpen, setAddOpen] = useState(false);\n const [selectedProvider, setSelectedProvider] = useState('anthropic');\n\n const connections = data?.connections ?? [];\n\n const handleRevoke = () => {\n if (!confirmRevoke) return;\n disconnect.mutate(\n { provider: confirmRevoke.provider, label: confirmRevoke.label },\n { onSuccess: () => setConfirmRevoke(null) },\n );\n };\n\n const connectUrl = (provider: string) =>\n `${LT_BASE}/api/auth/oauth/connect/${provider}?token=${encodeURIComponent(getToken() || '')}&returnTo=/credentials`;\n\n return (\n <div>\n <PageHeader\n title=\"Credentials\"\n docsHash=\"#docs:dashboard.md:credentials\"\n actions={\n <button\n onClick={() => setAddOpen((o) => !o)}\n className=\"btn-primary text-xs inline-flex items-center gap-1.5\"\n >\n <Plus className=\"w-3.5 h-3.5\" />\n Add Credential\n </button>\n }\n />\n\n <p className=\"text-sm text-text-secondary mb-6\">\n Manage credentials used by tools when invoked on your behalf.\n Each credential is encrypted at rest and resolved automatically during tool execution.\n </p>\n\n {/* Add credential dropdown */}\n {addOpen && (\n <div className=\"mb-6 pb-5 border-b border-surface-border/60 space-y-3\">\n <div className=\"flex items-center gap-3\">\n <label className=\"text-xs text-text-secondary font-medium\">Provider</label>\n <div className=\"relative\">\n <select\n value={selectedProvider}\n onChange={(e) => setSelectedProvider(e.target.value)}\n className=\"input text-xs pr-7 appearance-none\"\n >\n {Object.entries(PROVIDERS).map(([key, p]) => (\n <option key={key} value={key}>{p.name}</option>\n ))}\n </select>\n <ChevronDown className=\"absolute right-2 top-1/2 -translate-y-1/2 w-3 h-3 text-text-tertiary pointer-events-none\" />\n </div>\n </div>\n <p className=\"text-xs text-text-tertiary\">\n {PROVIDERS[selectedProvider]?.helpText}\n </p>\n <a\n href={connectUrl(selectedProvider)}\n className=\"btn-primary text-xs inline-flex items-center gap-1.5\"\n >\n <OAuthIcon provider={selectedProvider} className=\"w-3.5 h-3.5\" />\n Connect {PROVIDERS[selectedProvider]?.name}\n </a>\n </div>\n )}\n\n {/* Credentials table */}\n {isLoading ? (\n <div className=\"animate-pulse space-y-3\">\n {[1, 2].map((i) => (\n <div key={i} className=\"h-16 bg-surface-sunken rounded\" />\n ))}\n </div>\n ) : connections.length === 0 ? (\n <div className=\"text-center py-16 text-text-tertiary\">\n <Unplug className=\"w-10 h-10 mx-auto mb-3 opacity-40\" />\n <p className=\"text-sm\">No credentials registered.</p>\n <p className=\"text-xs mt-1\">Add a credential to enable tool authentication.</p>\n </div>\n ) : (\n <div className=\"divide-y divide-surface-border/30\">\n {connections.map((conn) => (\n <div\n key={`${conn.provider}-${conn.label}`}\n className=\"group/row flex items-center gap-4 px-3 py-2.5 -mx-3\"\n >\n <OAuthIcon provider={conn.provider} className=\"w-6 h-6 shrink-0\" />\n\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm text-text-primary font-medium capitalize\">\n {conn.provider}\n </span>\n {conn.label !== 'default' && (\n <span className=\"text-[10px] px-1.5 py-0.5 bg-surface-sunken rounded text-text-tertiary\">\n {conn.label}\n </span>\n )}\n {conn.credential_type && (\n <span className=\"text-[10px] px-1.5 py-0.5 bg-accent-faint rounded text-accent\">\n {conn.credential_type}\n </span>\n )}\n </div>\n <div className=\"flex items-center gap-3 mt-0.5\">\n {conn.email && (\n <span className=\"text-xs text-text-tertiary\">{conn.email}</span>\n )}\n {conn.expires_at && (\n <span className=\"text-xs text-text-tertiary\">\n Expires <TimeAgo date={conn.expires_at} />\n </span>\n )}\n </div>\n </div>\n\n <button\n onClick={() => setConfirmRevoke({ provider: conn.provider, label: conn.label })}\n className=\"opacity-0 group-hover/row:opacity-100 transition-opacity text-text-tertiary hover:text-status-error\"\n title=\"Revoke credential\"\n >\n <Trash2 className=\"w-4 h-4\" />\n </button>\n </div>\n ))}\n </div>\n )}\n\n <ConfirmDeleteModal\n open={!!confirmRevoke}\n onClose={() => setConfirmRevoke(null)}\n onConfirm={handleRevoke}\n title=\"Revoke Credential\"\n description={\n <>\n Revoke the{' '}\n <span className=\"font-medium text-text-primary capitalize\">\n {confirmRevoke?.provider}\n </span>\n {confirmRevoke?.label !== 'default' && (\n <> ({confirmRevoke?.label})</>\n )}{' '}\n credential? Tools will no longer be able to use this credential.\n </>\n }\n isPending={disconnect.isPending}\n error={disconnect.error as Error | null}\n />\n </div>\n );\n}\n"],"names":["PROVIDERS","CredentialsPage","data","isLoading","useOAuthConnections","disconnect","useDisconnectOAuth","confirmRevoke","setConfirmRevoke","useState","addOpen","setAddOpen","selectedProvider","setSelectedProvider","connections","handleRevoke","connectUrl","provider","LT_BASE","getToken","jsx","PageHeader","jsxs","o","Plus","e","key","p","ChevronDown","_a","OAuthIcon","_b","i","Unplug","conn","TimeAgo","Trash2","ConfirmDeleteModal","Fragment"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CredentialsPage-smk5H_mP.js","sources":["../../src/pages/settings/CredentialsPage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { Unplug, Trash2, Plus, ChevronDown } from 'lucide-react';\nimport { useOAuthConnections, useDisconnectOAuth } from '../../api/oauth';\nimport { getToken } from '../../api/client';\nimport { PageHeader } from '../../components/common/layout/PageHeader';\nimport { OAuthIcon } from '../../components/common/OAuthIcon';\nimport { TimeAgo } from '../../components/common/display/TimeAgo';\nimport { ConfirmDeleteModal } from '../../components/common/modal/ConfirmDeleteModal';\nimport { LT_BASE } from '../../lib/base-path';\n\ninterface ConnectionToRevoke {\n provider: string;\n label: string;\n}\n\nconst PROVIDERS: Record<string, { name: string; helpText: string; placeholder: string; oauth?: boolean }> = {\n anthropic: {\n name: 'Anthropic',\n helpText: 'Run \"claude setup-token\" for an OAuth token, or use an API key from console.anthropic.com.',\n placeholder: 'sk-ant-oat01-... or sk-ant-api03-...',\n },\n openai: {\n name: 'OpenAI',\n helpText: 'Create an API key at platform.openai.com/api-keys.',\n placeholder: 'sk-...',\n },\n google: {\n name: 'Google',\n helpText: 'Connect your Google account for Gmail, Calendar, and Drive access.',\n placeholder: '',\n oauth: true,\n },\n};\n\nexport function CredentialsPage() {\n const { data, isLoading } = useOAuthConnections();\n const disconnect = useDisconnectOAuth();\n const [confirmRevoke, setConfirmRevoke] = useState<ConnectionToRevoke | null>(null);\n const [addOpen, setAddOpen] = useState(false);\n const [selectedProvider, setSelectedProvider] = useState('anthropic');\n\n const connections = data?.connections ?? [];\n\n const handleRevoke = () => {\n if (!confirmRevoke) return;\n disconnect.mutate(\n { provider: confirmRevoke.provider, label: confirmRevoke.label },\n { onSuccess: () => setConfirmRevoke(null) },\n );\n };\n\n const connectUrl = (provider: string) =>\n `${LT_BASE}/api/auth/oauth/connect/${provider}?token=${encodeURIComponent(getToken() || '')}&returnTo=/credentials`;\n\n return (\n <div>\n <PageHeader\n title=\"Credentials\"\n docsHash=\"#docs:dashboard.md:credentials\"\n actions={\n <button\n onClick={() => setAddOpen((o) => !o)}\n className=\"btn-primary text-xs inline-flex items-center gap-1.5\"\n >\n <Plus className=\"w-3.5 h-3.5\" />\n Add Credential\n </button>\n }\n />\n\n <p className=\"text-sm text-text-secondary mb-6\">\n Manage credentials used by tools when invoked on your behalf.\n Each credential is encrypted at rest and resolved automatically during tool execution.\n </p>\n\n {/* Add credential dropdown */}\n {addOpen && (\n <div className=\"mb-6 pb-5 border-b border-surface-border/60 space-y-3\">\n <div className=\"flex items-center gap-3\">\n <label className=\"text-xs text-text-secondary font-medium\">Provider</label>\n <div className=\"relative\">\n <select\n value={selectedProvider}\n onChange={(e) => setSelectedProvider(e.target.value)}\n className=\"input text-xs pr-7 appearance-none\"\n >\n {Object.entries(PROVIDERS).map(([key, p]) => (\n <option key={key} value={key}>{p.name}</option>\n ))}\n </select>\n <ChevronDown className=\"absolute right-2 top-1/2 -translate-y-1/2 w-3 h-3 text-text-tertiary pointer-events-none\" />\n </div>\n </div>\n <p className=\"text-xs text-text-tertiary\">\n {PROVIDERS[selectedProvider]?.helpText}\n </p>\n <a\n href={connectUrl(selectedProvider)}\n className=\"btn-primary text-xs inline-flex items-center gap-1.5\"\n >\n <OAuthIcon provider={selectedProvider} className=\"w-3.5 h-3.5\" />\n Connect {PROVIDERS[selectedProvider]?.name}\n </a>\n </div>\n )}\n\n {/* Credentials table */}\n {isLoading ? (\n <div className=\"animate-pulse space-y-3\">\n {[1, 2].map((i) => (\n <div key={i} className=\"h-16 bg-surface-sunken rounded\" />\n ))}\n </div>\n ) : connections.length === 0 ? (\n <div className=\"text-center py-16 text-text-tertiary\">\n <Unplug className=\"w-10 h-10 mx-auto mb-3 opacity-40\" />\n <p className=\"text-sm\">No credentials registered.</p>\n <p className=\"text-xs mt-1\">Add a credential to enable tool authentication.</p>\n </div>\n ) : (\n <div className=\"divide-y divide-surface-border/30\">\n {connections.map((conn) => (\n <div\n key={`${conn.provider}-${conn.label}`}\n className=\"group/row flex items-center gap-4 px-3 py-2.5 -mx-3\"\n >\n <OAuthIcon provider={conn.provider} className=\"w-6 h-6 shrink-0\" />\n\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm text-text-primary font-medium capitalize\">\n {conn.provider}\n </span>\n {conn.label !== 'default' && (\n <span className=\"text-[10px] px-1.5 py-0.5 bg-surface-sunken rounded text-text-tertiary\">\n {conn.label}\n </span>\n )}\n {conn.credential_type && (\n <span className=\"text-[10px] px-1.5 py-0.5 bg-accent-faint rounded text-accent\">\n {conn.credential_type}\n </span>\n )}\n </div>\n <div className=\"flex items-center gap-3 mt-0.5\">\n {conn.email && (\n <span className=\"text-xs text-text-tertiary\">{conn.email}</span>\n )}\n {conn.expires_at && (\n <span className=\"text-xs text-text-tertiary\">\n Expires <TimeAgo date={conn.expires_at} />\n </span>\n )}\n </div>\n </div>\n\n <button\n onClick={() => setConfirmRevoke({ provider: conn.provider, label: conn.label })}\n className=\"opacity-0 group-hover/row:opacity-100 transition-opacity text-text-tertiary hover:text-status-error\"\n title=\"Revoke credential\"\n >\n <Trash2 className=\"w-4 h-4\" />\n </button>\n </div>\n ))}\n </div>\n )}\n\n <ConfirmDeleteModal\n open={!!confirmRevoke}\n onClose={() => setConfirmRevoke(null)}\n onConfirm={handleRevoke}\n title=\"Revoke Credential\"\n description={\n <>\n Revoke the{' '}\n <span className=\"font-medium text-text-primary capitalize\">\n {confirmRevoke?.provider}\n </span>\n {confirmRevoke?.label !== 'default' && (\n <> ({confirmRevoke?.label})</>\n )}{' '}\n credential? Tools will no longer be able to use this credential.\n </>\n }\n isPending={disconnect.isPending}\n error={disconnect.error as Error | null}\n />\n </div>\n );\n}\n"],"names":["PROVIDERS","CredentialsPage","data","isLoading","useOAuthConnections","disconnect","useDisconnectOAuth","confirmRevoke","setConfirmRevoke","useState","addOpen","setAddOpen","selectedProvider","setSelectedProvider","connections","handleRevoke","connectUrl","provider","LT_BASE","getToken","jsx","PageHeader","jsxs","o","Plus","e","key","p","ChevronDown","_a","OAuthIcon","_b","i","Unplug","conn","TimeAgo","Trash2","ConfirmDeleteModal","Fragment"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{u as c,b as r,c as o,j as n}from"./vendor-query-B2UbickB.js";import{d as i}from"./index-
|
|
2
|
-
//# sourceMappingURL=CronLabel-
|
|
1
|
+
import{u as c,b as r,c as o,j as n}from"./vendor-query-B2UbickB.js";import{d as i}from"./index-C9moIiIq.js";import{R as l,a9 as p}from"./vendor-icons-BXhWQC7l.js";function g(e){return c({queryKey:["agent-subscriptions",e],queryFn:()=>i(`/agents/${e}/subscriptions`),enabled:!!e})}function b(){const e=r();return o({mutationFn:({agentId:t,...s})=>i(`/agents/${t}/subscriptions`,{method:"POST",body:JSON.stringify(s)}),onSuccess:(t,s)=>{e.invalidateQueries({queryKey:["agent-subscriptions",s.agentId]}),e.invalidateQueries({queryKey:["agents"]})}})}function f(){const e=r();return o({mutationFn:({agentId:t,subId:s,...a})=>i(`/agents/${t}/subscriptions/${s}`,{method:"PUT",body:JSON.stringify(a)}),onSuccess:(t,s)=>{e.invalidateQueries({queryKey:["agent-subscriptions",s.agentId]})}})}function h(){const e=r();return o({mutationFn:({agentId:t,subId:s})=>i(`/agents/${t}/subscriptions/${s}`,{method:"DELETE"}),onSuccess:(t,s)=>{e.invalidateQueries({queryKey:["agent-subscriptions",s.agentId]}),e.invalidateQueries({queryKey:["agents"]})}})}const y={task:"text-status-active",workflow:"text-accent",escalation:"text-status-warning",activity:"text-status-active",knowledge:"text-accent",agent:"text-status-success",app:"text-status-error",milestone:"text-accent"};function q({topic:e}){const t=e.split("."),s=t[0]==="system"?t[1]:t[0],a=y[s]??"text-text-quaternary",u=t[0]==="system"?`${t[1]}.${t[t.length-1]}`:t.slice(-2).join(".");return n.jsxs("span",{className:"inline-flex items-center gap-1 text-[11px] font-mono text-text-secondary",children:[n.jsx(l,{className:`w-2.5 h-2.5 shrink-0 ${a}`,strokeWidth:1.5}),u]})}function C({cron:e}){return n.jsxs("span",{className:"inline-flex items-center gap-1 text-[11px] font-mono text-text-secondary",children:[n.jsx(p,{className:"w-2.5 h-2.5 shrink-0 text-text-quaternary",strokeWidth:1.5}),e]})}export{C,q as E,b as a,f as b,h as c,g as u};
|
|
2
|
+
//# sourceMappingURL=CronLabel-CCJLmkIq.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CronLabel-
|
|
1
|
+
{"version":3,"file":"CronLabel-CCJLmkIq.js","sources":["../../src/api/agent-subscriptions.ts","../../src/components/common/display/EventTopicPill.tsx","../../src/components/common/display/CronLabel.tsx"],"sourcesContent":["import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';\nimport { apiFetch } from './client';\n\nexport interface AgentSubscription {\n id: string;\n agent_id: string;\n topic: string;\n filter?: Record<string, any>;\n reaction_type: 'durable' | 'pipeline' | 'mcp_query' | 'capability';\n workflow_type?: string;\n pipeline_id?: string;\n mcp_prompt?: string;\n server_id?: string;\n tool_name?: string;\n input_mapping: Record<string, any>;\n execute_as?: string;\n enabled: boolean;\n created_at: string;\n updated_at: string;\n}\n\ninterface SubscriptionListResponse {\n subscriptions: AgentSubscription[];\n}\n\nexport function useAgentSubscriptions(agentId: string | null) {\n return useQuery<SubscriptionListResponse>({\n queryKey: ['agent-subscriptions', agentId],\n queryFn: () => apiFetch(`/agents/${agentId}/subscriptions`),\n enabled: !!agentId,\n });\n}\n\nexport function useCreateSubscription() {\n const queryClient = useQueryClient();\n return useMutation<AgentSubscription, Error, { agentId: string } & Partial<AgentSubscription>>({\n mutationFn: ({ agentId, ...body }) =>\n apiFetch(`/agents/${agentId}/subscriptions`, {\n method: 'POST',\n body: JSON.stringify(body),\n }),\n onSuccess: (_, vars) => {\n queryClient.invalidateQueries({ queryKey: ['agent-subscriptions', vars.agentId] });\n queryClient.invalidateQueries({ queryKey: ['agents'] });\n },\n });\n}\n\nexport function useUpdateSubscription() {\n const queryClient = useQueryClient();\n return useMutation<AgentSubscription, Error, { agentId: string; subId: string } & Partial<AgentSubscription>>({\n mutationFn: ({ agentId, subId, ...body }) =>\n apiFetch(`/agents/${agentId}/subscriptions/${subId}`, {\n method: 'PUT',\n body: JSON.stringify(body),\n }),\n onSuccess: (_, vars) => {\n queryClient.invalidateQueries({ queryKey: ['agent-subscriptions', vars.agentId] });\n },\n });\n}\n\nexport function useDeleteSubscription() {\n const queryClient = useQueryClient();\n return useMutation<{ deleted: boolean }, Error, { agentId: string; subId: string }>({\n mutationFn: ({ agentId, subId }) =>\n apiFetch(`/agents/${agentId}/subscriptions/${subId}`, { method: 'DELETE' }),\n onSuccess: (_, vars) => {\n queryClient.invalidateQueries({ queryKey: ['agent-subscriptions', vars.agentId] });\n queryClient.invalidateQueries({ queryKey: ['agents'] });\n },\n });\n}\n","import { Radio } from 'lucide-react';\n\n/**\n * Universal event topic display — Radio icon + monotype text.\n * Used everywhere an event subscription topic is rendered.\n * No border, no background — matches CronLabel's simplicity.\n */\n\nconst CATEGORY_COLORS: Record<string, string> = {\n task: 'text-status-active',\n workflow: 'text-accent',\n escalation: 'text-status-warning',\n activity: 'text-status-active',\n knowledge: 'text-accent',\n agent: 'text-status-success',\n app: 'text-status-error',\n milestone: 'text-accent',\n};\n\ninterface EventTopicPillProps {\n topic: string;\n}\n\nexport function EventTopicPill({ topic }: EventTopicPillProps) {\n const parts = topic.split('.');\n const category = parts[0] === 'system' ? parts[1] : parts[0];\n const iconColor = CATEGORY_COLORS[category] ?? 'text-text-quaternary';\n // Show category.action for system events (e.g., workflow.completed)\n const shortTopic = parts[0] === 'system'\n ? `${parts[1]}.${parts[parts.length - 1]}`\n : parts.slice(-2).join('.');\n\n return (\n <span className=\"inline-flex items-center gap-1 text-[11px] font-mono text-text-secondary\">\n <Radio className={`w-2.5 h-2.5 shrink-0 ${iconColor}`} strokeWidth={1.5} />\n {shortTopic}\n </span>\n );\n}\n","import { Clock } from 'lucide-react';\n\ninterface CronLabelProps {\n cron: string;\n}\n\n/**\n * Universal cron expression display — Clock icon + monotype text.\n * Used everywhere a cron schedule is rendered.\n */\nexport function CronLabel({ cron }: CronLabelProps) {\n return (\n <span className=\"inline-flex items-center gap-1 text-[11px] font-mono text-text-secondary\">\n <Clock className=\"w-2.5 h-2.5 shrink-0 text-text-quaternary\" strokeWidth={1.5} />\n {cron}\n </span>\n );\n}\n"],"names":["useAgentSubscriptions","agentId","useQuery","apiFetch","useCreateSubscription","queryClient","useQueryClient","useMutation","body","_","vars","useUpdateSubscription","subId","useDeleteSubscription","CATEGORY_COLORS","EventTopicPill","topic","parts","category","iconColor","shortTopic","jsxs","jsx","Radio","CronLabel","cron","Clock"],"mappings":"mKAyBO,SAASA,EAAsBC,EAAwB,CAC5D,OAAOC,EAAmC,CACxC,SAAU,CAAC,sBAAuBD,CAAO,EACzC,QAAS,IAAME,EAAS,WAAWF,CAAO,gBAAgB,EAC1D,QAAS,CAAC,CAACA,CAAA,CACZ,CACH,CAEO,SAASG,GAAwB,CACtC,MAAMC,EAAcC,EAAA,EACpB,OAAOC,EAAwF,CAC7F,WAAY,CAAC,CAAE,QAAAN,EAAS,GAAGO,KACzBL,EAAS,WAAWF,CAAO,iBAAkB,CAC3C,OAAQ,OACR,KAAM,KAAK,UAAUO,CAAI,CAAA,CAC1B,EACH,UAAW,CAACC,EAAGC,IAAS,CACtBL,EAAY,kBAAkB,CAAE,SAAU,CAAC,sBAAuBK,EAAK,OAAO,EAAG,EACjFL,EAAY,kBAAkB,CAAE,SAAU,CAAC,QAAQ,EAAG,CACxD,CAAA,CACD,CACH,CAEO,SAASM,GAAwB,CACtC,MAAMN,EAAcC,EAAA,EACpB,OAAOC,EAAuG,CAC5G,WAAY,CAAC,CAAE,QAAAN,EAAS,MAAAW,EAAO,GAAGJ,CAAA,IAChCL,EAAS,WAAWF,CAAO,kBAAkBW,CAAK,GAAI,CACpD,OAAQ,MACR,KAAM,KAAK,UAAUJ,CAAI,CAAA,CAC1B,EACH,UAAW,CAACC,EAAGC,IAAS,CACtBL,EAAY,kBAAkB,CAAE,SAAU,CAAC,sBAAuBK,EAAK,OAAO,EAAG,CACnF,CAAA,CACD,CACH,CAEO,SAASG,GAAwB,CACtC,MAAMR,EAAcC,EAAA,EACpB,OAAOC,EAA6E,CAClF,WAAY,CAAC,CAAE,QAAAN,EAAS,MAAAW,KACtBT,EAAS,WAAWF,CAAO,kBAAkBW,CAAK,GAAI,CAAE,OAAQ,SAAU,EAC5E,UAAW,CAACH,EAAGC,IAAS,CACtBL,EAAY,kBAAkB,CAAE,SAAU,CAAC,sBAAuBK,EAAK,OAAO,EAAG,EACjFL,EAAY,kBAAkB,CAAE,SAAU,CAAC,QAAQ,EAAG,CACxD,CAAA,CACD,CACH,CChEA,MAAMS,EAA0C,CAC9C,KAAY,qBACZ,SAAY,cACZ,WAAY,sBACZ,SAAY,qBACZ,UAAY,cACZ,MAAY,sBACZ,IAAY,oBACZ,UAAY,aACd,EAMO,SAASC,EAAe,CAAE,MAAAC,GAA8B,CAC7D,MAAMC,EAAQD,EAAM,MAAM,GAAG,EACvBE,EAAWD,EAAM,CAAC,IAAM,SAAWA,EAAM,CAAC,EAAIA,EAAM,CAAC,EACrDE,EAAYL,EAAgBI,CAAQ,GAAK,uBAEzCE,EAAaH,EAAM,CAAC,IAAM,SAC5B,GAAGA,EAAM,CAAC,CAAC,IAAIA,EAAMA,EAAM,OAAS,CAAC,CAAC,GACtCA,EAAM,MAAM,EAAE,EAAE,KAAK,GAAG,EAE5B,OACEI,EAAAA,KAAC,OAAA,CAAK,UAAU,2EACd,SAAA,CAAAC,MAACC,GAAM,UAAW,wBAAwBJ,CAAS,GAAI,YAAa,IAAK,EACxEC,CAAA,EACH,CAEJ,CC5BO,SAASI,EAAU,CAAE,KAAAC,GAAwB,CAClD,OACEJ,EAAAA,KAAC,OAAA,CAAK,UAAU,2EACd,SAAA,CAAAC,EAAAA,IAACI,EAAA,CAAM,UAAU,4CAA4C,YAAa,IAAK,EAC9ED,CAAA,EACH,CAEJ"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{j as l,a as f}from"./vendor-query-B2UbickB.js";import{M as b}from"./Modal-CSrxpXeM.js";import{u as g}from"./index-C9moIiIq.js";import{D as w,f as v}from"./constants-BHkpVaqx.js";function D({open:t,onClose:n,onConfirm:i,selectedCount:e,isPending:s,error:o}){const r=e&&e>1?`Cancel ${e} escalations`:"Cancel escalation";return l.jsx(b,{open:t,onClose:n,title:r,children:l.jsxs("div",{className:"space-y-4",children:[l.jsx("p",{className:"text-sm text-text-secondary",children:e&&e>1?`This will permanently cancel ${e} escalations. Any waiting workflows will be unblocked and receive a cancellation signal.`:"This will permanently cancel this escalation. Any waiting workflow will be unblocked and receive a cancellation signal."}),l.jsx("p",{className:"text-xs text-text-tertiary",children:"This action cannot be undone."}),o&&l.jsx("p",{className:"text-xs text-status-error",children:o.message}),l.jsxs("div",{className:"flex justify-end gap-3 pt-2",children:[l.jsx("button",{onClick:n,disabled:s,className:"btn-secondary text-xs",children:"Keep"}),l.jsx("button",{onClick:i,disabled:s,className:"bg-status-error text-white px-3 py-1.5 rounded-md text-xs hover:opacity-90 transition-opacity disabled:opacity-50",children:s?"Cancelling...":"Yes, Cancel"})]})]})})}const j=new Set(["__proto__","constructor","prototype"]);function m(t){const n=[];for(const i of t.split(".")){const e=i.match(/^([^[\]]*)((?:\[\d+\])*)$/);if(!e)throw new Error(`invalid x-lt-bind path segment: "${i}"`);const[,s,o]=e;if(s){if(j.has(s))throw new Error(`x-lt-bind path may not target "${s}"`);n.push({key:s})}for(const r of o.match(/\d+/g)??[])n.push({index:Number(r)})}if(n.length===0)throw new Error(`empty x-lt-bind path: "${t}"`);return n}function k(t,n,i){const e=m(n);let s=t;for(let r=0;r<e.length-1;r++){const u=e[r],d=e[r+1],c="key"in u?u.key:u.index,a="index"in d;(s[c]==null||typeof s[c]!="object")&&(s[c]=a?[]:{}),s=s[c]}const o=e[e.length-1];s["key"in o?o.key:o.index]=i}function y(t,n){let i=t;for(const e of m(n)){if(i==null||typeof i!="object")return;i=i["key"in e?e.key:e.index]}return i}function h(t,n){const i=n==null?void 0:n["x-lt-bind"];return typeof i=="string"&&i.length>0?i:t}function I(t,n){const i=n==null?void 0:n.properties;if(!i)return{...t};const e={};for(const[s,o]of Object.entries(i))s in t&&k(e,h(s,o),t[s]);return e}function S(t,n){const i=n==null?void 0:n.properties;if(!i)return t?{...t}:{};const e={};for(const[s,o]of Object.entries(i)){const r=y(t,h(s,o));r!==void 0&&(e[s]=r)}return e}const N=["escalation","metadata","envelope","payload","resolver"],T=/\{\{\s*([^{}]+?)\s*\}\}/g,p="—";function x(t){if(t==null)return p;if(typeof t=="string")return t;if(typeof t=="number"||typeof t=="boolean")return String(t);try{return JSON.stringify(t)}catch{return p}}function E(t,n){return t.replace(T,(i,e)=>{const s=e.indexOf("."),o=s===-1?e:e.slice(0,s);if(!N.includes(o))return p;const r=n[o];if(s===-1)return x(r);try{return x(y(r,e.slice(s+1)))}catch{return p}})}function _(t){const n=t==null?void 0:t["x-lt-help"];if(typeof n=="string"&&n.trim().length>0)return n;const i=t==null?void 0:t["x-lt-context"];return typeof i=="string"&&i.trim().length>0?i:null}function F(t,n){const i=_(t);return i?E(i,n):null}function H({isTerminal:t,status:n,claimed:i,claimedByMe:e}){return t?n==="cancelled"?"This escalation was cancelled. The record is shown for reference.":"This escalation has been resolved. The submitted form is shown for reference.":e?"You have claimed this escalation. Fill out the form and submit to resolve it.":i?"Another user has claimed this escalation. It unlocks if their claim expires or is released.":"Claim this escalation to enable the form."}function K(){const{data:t}=g();return f.useMemo(()=>{var i;return(((i=t==null?void 0:t.escalation)==null?void 0:i.claimDurations)??w).map(e=>({value:String(e),label:v(e)}))},[t])}const $=[{value:1,label:"minutes"},{value:60,label:"hours"}];function L({onChange:t,compact:n,autoFocus:i,"data-testid":e="custom-duration-input"}){const[s,o]=f.useState(""),[r,u]=f.useState(1);f.useEffect(()=>{const a=parseInt(s);t(a>0?a*r:0)},[s,r,t]);const d=n?"text-xs":"text-sm",c=n?"w-16":"w-20";return l.jsxs("div",{className:"flex items-center gap-2","data-testid":e,children:[l.jsx("input",{type:"number",min:1,max:r===60?24:1440,value:s,onChange:a=>o(a.target.value),placeholder:r===60?"hrs":"min",className:`input ${d} ${c} text-center`,autoFocus:i,"data-testid":`${e}-quantity`}),l.jsx("select",{value:r,onChange:a=>u(parseInt(a.target.value)),className:`select ${d} py-1`,"data-testid":`${e}-unit`,children:$.map(a=>l.jsx("option",{value:a.value,children:a.label},a.value))})]})}export{L as C,D as a,F as b,S as c,H as d,E as i,I as m,K as u};
|
|
2
|
+
//# sourceMappingURL=CustomDurationPicker-DQ28g5GB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CustomDurationPicker-DQ28g5GB.js","sources":["../../src/components/common/modal/ConfirmCancelModal.tsx","../../src/lib/x-lt-bind.ts","../../src/lib/x-lt-help.ts","../../src/hooks/useClaimDurations.ts","../../src/components/common/form/CustomDurationPicker.tsx"],"sourcesContent":["import { Modal } from './Modal';\n\ninterface ConfirmCancelModalProps {\n open: boolean;\n onClose: () => void;\n onConfirm: () => void;\n selectedCount?: number;\n isPending?: boolean;\n error?: Error | null;\n}\n\nexport function ConfirmCancelModal({\n open,\n onClose,\n onConfirm,\n selectedCount,\n isPending,\n error,\n}: ConfirmCancelModalProps) {\n const title = selectedCount && selectedCount > 1\n ? `Cancel ${selectedCount} escalations`\n : 'Cancel escalation';\n\n return (\n <Modal open={open} onClose={onClose} title={title}>\n <div className=\"space-y-4\">\n <p className=\"text-sm text-text-secondary\">\n {selectedCount && selectedCount > 1\n ? `This will permanently cancel ${selectedCount} escalations. Any waiting workflows will be unblocked and receive a cancellation signal.`\n : 'This will permanently cancel this escalation. Any waiting workflow will be unblocked and receive a cancellation signal.'}\n </p>\n <p className=\"text-xs text-text-tertiary\">This action cannot be undone.</p>\n {error && <p className=\"text-xs text-status-error\">{error.message}</p>}\n <div className=\"flex justify-end gap-3 pt-2\">\n <button onClick={onClose} disabled={isPending} className=\"btn-secondary text-xs\">\n Keep\n </button>\n <button\n onClick={onConfirm}\n disabled={isPending}\n className=\"bg-status-error text-white px-3 py-1.5 rounded-md text-xs hover:opacity-90 transition-opacity disabled:opacity-50\"\n >\n {isPending ? 'Cancelling...' : 'Yes, Cancel'}\n </button>\n </div>\n </div>\n </Modal>\n );\n}\n","/**\n * x-lt-bind — maps the escalation FORM (flat field values the user edits) to and\n * from the PAYLOAD (the nested JSON the workflow consumes). A form_schema property\n * may declare `x-lt-bind: \"a.b[0].c\"`, the path its value occupies in the payload;\n * a property with no bind sits at its own name at the root (1:1). This is a\n * front-end port of the server's resolver-mapping (the dashboard build cannot\n * import backend service code) — keep the two in sync.\n *\n * mapPayloadToForm — payload → flat form values, to PREFILL/display the form\n * mapFormToPayload — flat form values → payload, the shape submitted/stored\n */\n\ntype PathSeg = { key: string } | { index: number };\n\nconst BLOCKED_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\n\n/** Parse a bind path — dot keys with optional `[n]` indices. Rejects pollution keys. */\nexport function parsePath(path: string): PathSeg[] {\n const segs: PathSeg[] = [];\n for (const raw of path.split('.')) {\n const m = raw.match(/^([^[\\]]*)((?:\\[\\d+\\])*)$/);\n if (!m) throw new Error(`invalid x-lt-bind path segment: \"${raw}\"`);\n const [, name, brackets] = m;\n if (name) {\n if (BLOCKED_KEYS.has(name)) throw new Error(`x-lt-bind path may not target \"${name}\"`);\n segs.push({ key: name });\n }\n for (const b of brackets.match(/\\d+/g) ?? []) segs.push({ index: Number(b) });\n }\n if (segs.length === 0) throw new Error(`empty x-lt-bind path: \"${path}\"`);\n return segs;\n}\n\n/** Set `value` at `path` inside `root`, creating intermediate objects/arrays. */\nexport function setDeep(root: Record<string, any>, path: string, value: unknown): void {\n const segs = parsePath(path);\n let node: any = root;\n for (let i = 0; i < segs.length - 1; i++) {\n const seg = segs[i];\n const next = segs[i + 1];\n const childKey = 'key' in seg ? seg.key : seg.index;\n const wantArray = 'index' in next;\n if (node[childKey] == null || typeof node[childKey] !== 'object') {\n node[childKey] = wantArray ? [] : {};\n }\n node = node[childKey];\n }\n const last = segs[segs.length - 1];\n node['key' in last ? last.key : last.index] = value;\n}\n\n/** Read the value at `path` inside `root` (undefined if any segment is missing). */\nexport function getDeep(root: unknown, path: string): unknown {\n let node: any = root;\n for (const seg of parsePath(path)) {\n if (node == null || typeof node !== 'object') return undefined;\n node = node['key' in seg ? seg.key : seg.index];\n }\n return node;\n}\n\n/** The bind path for a form property (its `x-lt-bind`, or the property name). */\nexport function bindPathFor(propName: string, propDef: Record<string, any> | undefined): string {\n const bind = propDef?.['x-lt-bind'];\n return typeof bind === 'string' && bind.length > 0 ? bind : propName;\n}\n\n/**\n * Assemble the payload from the form's flat values. A field absent from\n * `formValues` is omitted (so clearing/deleting a field drops it from the\n * payload). Unknown keys not declared in the schema are dropped. With no schema\n * properties, values pass through unchanged.\n */\nexport function mapFormToPayload(\n formValues: Record<string, any>,\n formSchema: Record<string, any> | null | undefined,\n): Record<string, any> {\n const props = formSchema?.properties as Record<string, any> | undefined;\n if (!props) return { ...formValues };\n const payload: Record<string, any> = {};\n for (const [name, def] of Object.entries(props)) {\n if (!(name in formValues)) continue;\n setDeep(payload, bindPathFor(name, def as Record<string, any>), formValues[name]);\n }\n return payload;\n}\n\n/**\n * Reverse of {@link mapFormToPayload}: pull each form field's value out of the\n * payload via its bind path, to prefill/display the form. A field whose bound\n * path is missing from the payload is omitted (the caller falls back to the\n * schema default).\n */\nexport function mapPayloadToForm(\n payload: Record<string, any> | null | undefined,\n formSchema: Record<string, any> | null | undefined,\n): Record<string, any> {\n const props = formSchema?.properties as Record<string, any> | undefined;\n if (!props) return payload ? { ...payload } : {};\n const form: Record<string, any> = {};\n for (const [name, def] of Object.entries(props)) {\n const v = getDeep(payload, bindPathFor(name, def as Record<string, any>));\n if (v !== undefined) form[name] = v;\n }\n return form;\n}\n","/**\n * x-lt-help — the form's guidance content, rendered in the side panel beside\n * the resolve form. A form_schema may declare schema-level `x-lt-help`: a\n * markdown string whose `{{domain.path}}` tokens interpolate values from the\n * escalation surface, so help text can reference the live record:\n *\n * {{escalation.role}} — any column on the escalation row\n * {{metadata.schema_version}} — the row's metadata dict\n * {{envelope.formDefaults.customer.name}} — the workflow-sent input envelope\n * {{payload.category}} — the escalation context payload\n * {{resolver.notes}} — the submitted resolver payload\n *\n * Paths reuse the x-lt-bind syntax (`a.b[0].c`). A missing value renders as an\n * em dash. `x-lt-context` is accepted as the plain-text fallback source when\n * `x-lt-help` is absent.\n */\nimport { getDeep } from './x-lt-bind';\n\n/** The token domains a help template may reference. */\nexport const HELP_DOMAINS = ['escalation', 'metadata', 'envelope', 'payload', 'resolver'] as const;\nexport type HelpDomain = (typeof HELP_DOMAINS)[number];\n\nexport type HelpTokenContext = Partial<Record<HelpDomain, Record<string, unknown> | null>>;\n\nconst TOKEN_PATTERN = /\\{\\{\\s*([^{}]+?)\\s*\\}\\}/g;\nconst MISSING_VALUE = '—';\n\nfunction formatTokenValue(value: unknown): string {\n if (value === undefined || value === null) return MISSING_VALUE;\n if (typeof value === 'string') return value;\n if (typeof value === 'number' || typeof value === 'boolean') return String(value);\n try {\n return JSON.stringify(value);\n } catch {\n return MISSING_VALUE;\n }\n}\n\n/** Replace every `{{domain.path}}` token with its value from the context. */\nexport function interpolateHelp(template: string, ctx: HelpTokenContext): string {\n return template.replace(TOKEN_PATTERN, (_match, rawPath: string) => {\n const dot = rawPath.indexOf('.');\n const domain = (dot === -1 ? rawPath : rawPath.slice(0, dot)) as HelpDomain;\n if (!HELP_DOMAINS.includes(domain)) return MISSING_VALUE;\n const root = ctx[domain];\n if (dot === -1) return formatTokenValue(root);\n try {\n return formatTokenValue(getDeep(root, rawPath.slice(dot + 1)));\n } catch {\n return MISSING_VALUE;\n }\n });\n}\n\n/** The schema's help source: `x-lt-help` first, `x-lt-context` as fallback. */\nexport function resolveHelpSource(schema: Record<string, unknown> | null | undefined): string | null {\n const help = schema?.['x-lt-help'];\n if (typeof help === 'string' && help.trim().length > 0) return help;\n const context = schema?.['x-lt-context'];\n if (typeof context === 'string' && context.trim().length > 0) return context;\n return null;\n}\n\n/** The schema's help content, interpolated. Null when the schema declares none. */\nexport function buildHelpMarkdown(\n schema: Record<string, unknown> | null | undefined,\n ctx: HelpTokenContext,\n): string | null {\n const source = resolveHelpSource(schema);\n return source ? interpolateHelp(source, ctx) : null;\n}\n\nexport interface HelpStateHint {\n isTerminal: boolean;\n status?: string;\n claimed: boolean;\n claimedByMe: boolean;\n}\n\n/**\n * State-aware guidance shown when the schema carries no help content — the\n * panel always tells the user what this page expects of them right now.\n */\nexport function defaultHelpMarkdown({ isTerminal, status, claimed, claimedByMe }: HelpStateHint): string {\n if (isTerminal) {\n return status === 'cancelled'\n ? 'This escalation was cancelled. The record is shown for reference.'\n : 'This escalation has been resolved. The submitted form is shown for reference.';\n }\n if (claimedByMe) return 'You have claimed this escalation. Fill out the form and submit to resolve it.';\n if (claimed) return 'Another user has claimed this escalation. It unlocks if their claim expires or is released.';\n return 'Claim this escalation to enable the form.';\n}\n","import { useMemo } from 'react';\nimport { useSettings } from '../api/settings';\nimport { DEFAULT_CLAIM_DURATIONS, formatClaimDuration } from '../lib/constants';\n\nexport interface ClaimDurationOption {\n value: string;\n label: string;\n}\n\n/**\n * Returns claim duration presets from server settings (with fallback).\n * Options are formatted for use in selects and tab rows.\n */\nexport function useClaimDurations(): ClaimDurationOption[] {\n const { data: settings } = useSettings();\n\n return useMemo(() => {\n const minutes = settings?.escalation?.claimDurations ?? DEFAULT_CLAIM_DURATIONS;\n return minutes.map((m) => ({\n value: String(m),\n label: formatClaimDuration(m),\n }));\n }, [settings]);\n}\n","import { useState, useEffect } from 'react';\n\nconst UNITS = [\n { value: 1, label: 'minutes' },\n { value: 60, label: 'hours' },\n] as const;\n\ninterface CustomDurationPickerProps {\n /** Called with the computed duration in minutes whenever quantity or unit changes */\n onChange: (minutes: number) => void;\n /** Compact variant for inline use (e.g. action bars) */\n compact?: boolean;\n /** Auto-focus the quantity input */\n autoFocus?: boolean;\n 'data-testid'?: string;\n}\n\nexport function CustomDurationPicker({\n onChange,\n compact,\n autoFocus,\n 'data-testid': testId = 'custom-duration-input',\n}: CustomDurationPickerProps) {\n const [quantity, setQuantity] = useState('');\n const [multiplier, setMultiplier] = useState(1);\n\n useEffect(() => {\n const q = parseInt(quantity);\n onChange(q > 0 ? q * multiplier : 0);\n }, [quantity, multiplier, onChange]);\n\n const textSize = compact ? 'text-xs' : 'text-sm';\n const inputWidth = compact ? 'w-16' : 'w-20';\n\n return (\n <div className=\"flex items-center gap-2\" data-testid={testId}>\n <input\n type=\"number\"\n min={1}\n max={multiplier === 60 ? 24 : 1440}\n value={quantity}\n onChange={(e) => setQuantity(e.target.value)}\n placeholder={multiplier === 60 ? 'hrs' : 'min'}\n className={`input ${textSize} ${inputWidth} text-center`}\n autoFocus={autoFocus}\n data-testid={`${testId}-quantity`}\n />\n <select\n value={multiplier}\n onChange={(e) => setMultiplier(parseInt(e.target.value))}\n className={`select ${textSize} py-1`}\n data-testid={`${testId}-unit`}\n >\n {UNITS.map((u) => (\n <option key={u.value} value={u.value}>{u.label}</option>\n ))}\n </select>\n </div>\n );\n}\n"],"names":["ConfirmCancelModal","open","onClose","onConfirm","selectedCount","isPending","error","title","jsx","Modal","jsxs","BLOCKED_KEYS","parsePath","path","segs","raw","m","name","brackets","b","setDeep","root","value","node","i","seg","next","childKey","wantArray","last","getDeep","bindPathFor","propName","propDef","bind","mapFormToPayload","formValues","formSchema","props","payload","def","mapPayloadToForm","form","v","HELP_DOMAINS","TOKEN_PATTERN","MISSING_VALUE","formatTokenValue","interpolateHelp","template","ctx","_match","rawPath","dot","domain","resolveHelpSource","schema","help","context","buildHelpMarkdown","source","defaultHelpMarkdown","isTerminal","status","claimed","claimedByMe","useClaimDurations","settings","useSettings","useMemo","_a","DEFAULT_CLAIM_DURATIONS","formatClaimDuration","UNITS","CustomDurationPicker","onChange","compact","autoFocus","testId","quantity","setQuantity","useState","multiplier","setMultiplier","useEffect","q","textSize","inputWidth","e","u"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{j as e}from"./vendor-query-B2UbickB.js";import{E as f}from"./EmptyState-BcsfPq9T.js";function j({active:s,direction:a}){return e.jsx("svg",{className:`w-3 h-3 shrink-0 transition-all duration-150 ${s?"text-accent opacity-100":"opacity-0 group-hover/sorthead:opacity-40 text-text-tertiary"} ${s&&a==="asc"?"rotate-180":""}`,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2.5,children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M19 9l-7 7-7-7"})})}function k({columns:s,data:a,keyFn:c,onRowClick:o,activeRowKey:d,rowClassName:x,isLoading:h,emptyMessage:p="No records found",sort:n,onSort:u,inline:m,layout:b="auto"}){return h?e.jsx("div",{className:"animate-pulse space-y-0",children:Array.from({length:5}).map((t,r)=>e.jsx("div",{className:"h-14 border-b last:border-b-0 px-6 flex items-center",children:e.jsx("div",{className:"h-3 bg-surface-sunken rounded w-full"})},r))}):a.length?e.jsxs("table",{className:`w-full ${b==="fixed"?"table-fixed":""}`,children:[e.jsx("thead",{children:e.jsx("tr",{className:"border-b",children:s.map(t=>{const r=t.sortable&&u,i=(n==null?void 0:n.sort_by)===t.key;return e.jsx("th",{onClick:r?()=>u(t.key):void 0,className:`${m?"":"sticky top-[60px] z-10 "}bg-surface px-6 py-3 text-left text-[10px] font-semibold uppercase tracking-widest text-text-tertiary whitespace-nowrap ${t.className??""} ${r?"cursor-pointer select-none group/sorthead hover:text-text-secondary transition-colors":""}`,children:e.jsxs("span",{className:"inline-flex items-center gap-1",children:[t.label,r&&e.jsx(j,{active:i,direction:i?n.order:"desc"})]})},t.key)})})}),e.jsx("tbody",{children:a.map((t,r)=>{const i=d!=null&&c(t)===d;return e.jsx("tr",{onClick:o?()=>o(t):void 0,className:`group/row border-b last:border-b-0 transition-colors duration-100 ${o?"cursor-pointer row-hover":""} ${i?"border-l-2 border-l-accent":""} ${x?x(t):""}`,children:s.map(l=>e.jsx("td",{className:`px-6 py-2.5 text-sm ${l.className??""}`,children:l.render(t,r)},l.key))},c(t))})})]}):p?e.jsx(f,{title:p}):null}export{k as D};
|
|
2
|
+
//# sourceMappingURL=DataTable-Byn3oyT9.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DataTable-Byn3oyT9.js","sources":["../../src/components/common/data/DataTable.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { EmptyState } from '../display/EmptyState';\nimport type { SortState } from '../../../hooks/useFilterParams';\n\nexport interface Column<T> {\n key: string;\n label: string | ReactNode;\n render: (row: T, index: number) => ReactNode;\n className?: string;\n /** If true, this column header is clickable and triggers onSort. */\n sortable?: boolean;\n}\n\ninterface DataTableProps<T> {\n columns: Column<T>[];\n data: T[];\n keyFn: (row: T) => string;\n onRowClick?: (row: T) => void;\n /** Highlight the row whose keyFn matches this value. */\n activeRowKey?: string | null;\n /** Optional per-row class name for custom styling (e.g., engine vs worker tint). */\n rowClassName?: (row: T) => string;\n isLoading?: boolean;\n emptyMessage?: string;\n /** Current sort state — pass to show active sort indicator. */\n sort?: SortState;\n /** Called when a sortable column header is clicked. */\n onSort?: (column: string) => void;\n /** Disable the sticky header (useful when nested inside collapsible sections). */\n inline?: boolean;\n /**\n * `fixed` locks the table to its container width: columns with width\n * classes keep them, the rest share the remainder, and long content\n * truncates instead of widening the table. Use beside a slide panel where\n * the table must shrink as the panel expands.\n */\n layout?: 'auto' | 'fixed';\n}\n\nfunction SortIcon({ active, direction }: { active: boolean; direction: 'asc' | 'desc' }) {\n return (\n <svg\n className={`w-3 h-3 shrink-0 transition-all duration-150 ${\n active ? 'text-accent opacity-100' : 'opacity-0 group-hover/sorthead:opacity-40 text-text-tertiary'\n } ${active && direction === 'asc' ? 'rotate-180' : ''}`}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2.5}\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M19 9l-7 7-7-7\" />\n </svg>\n );\n}\n\nexport function DataTable<T>({\n columns,\n data,\n keyFn,\n onRowClick,\n activeRowKey,\n rowClassName,\n isLoading,\n emptyMessage = 'No records found',\n sort,\n onSort,\n inline,\n layout = 'auto',\n}: DataTableProps<T>) {\n if (isLoading) {\n return (\n <div className=\"animate-pulse space-y-0\">\n {Array.from({ length: 5 }).map((_, i) => (\n <div key={i} className=\"h-14 border-b last:border-b-0 px-6 flex items-center\">\n <div className=\"h-3 bg-surface-sunken rounded w-full\" />\n </div>\n ))}\n </div>\n );\n }\n\n if (!data.length) {\n return emptyMessage ? <EmptyState title={emptyMessage} /> : null;\n }\n\n return (\n <table className={`w-full ${layout === 'fixed' ? 'table-fixed' : ''}`}>\n <thead>\n <tr className=\"border-b\">\n {columns.map((col) => {\n const isSortable = col.sortable && onSort;\n const isActive = sort?.sort_by === col.key;\n\n return (\n <th\n key={col.key}\n onClick={isSortable ? () => onSort(col.key) : undefined}\n className={`${inline ? '' : 'sticky top-[60px] z-10 '}bg-surface px-6 py-3 text-left text-[10px] font-semibold uppercase tracking-widest text-text-tertiary whitespace-nowrap ${col.className ?? ''} ${\n isSortable ? 'cursor-pointer select-none group/sorthead hover:text-text-secondary transition-colors' : ''\n }`}\n >\n <span className=\"inline-flex items-center gap-1\">\n {col.label}\n {isSortable && (\n <SortIcon active={isActive} direction={isActive ? sort.order : 'desc'} />\n )}\n </span>\n </th>\n );\n })}\n </tr>\n </thead>\n <tbody>\n {data.map((row, index) => {\n const isActive = activeRowKey != null && keyFn(row) === activeRowKey;\n return (\n <tr\n key={keyFn(row)}\n onClick={onRowClick ? () => onRowClick(row) : undefined}\n className={`group/row border-b last:border-b-0 transition-colors duration-100 ${\n onRowClick ? 'cursor-pointer row-hover' : ''\n } ${isActive ? 'border-l-2 border-l-accent' : ''} ${rowClassName ? rowClassName(row) : ''}`}\n >\n {columns.map((col) => (\n <td\n key={col.key}\n className={`px-6 py-2.5 text-sm ${col.className ?? ''}`}\n >\n {col.render(row, index)}\n </td>\n ))}\n </tr>\n );\n })}\n </tbody>\n </table>\n );\n}\n"],"names":["SortIcon","active","direction","jsx","DataTable","columns","data","keyFn","onRowClick","activeRowKey","rowClassName","isLoading","emptyMessage","sort","onSort","inline","layout","_","i","jsxs","col","isSortable","isActive","row","index","EmptyState"],"mappings":"4FAuCA,SAASA,EAAS,CAAE,OAAAC,EAAQ,UAAAC,GAA6D,CACvF,OACEC,EAAAA,IAAC,MAAA,CACC,UAAW,gDACTF,EAAS,0BAA4B,8DACvC,IAAIA,GAAUC,IAAc,MAAQ,aAAe,EAAE,GACrD,QAAQ,YACR,KAAK,OACL,OAAO,eACP,YAAa,IAEb,eAAC,OAAA,CAAK,cAAc,QAAQ,eAAe,QAAQ,EAAE,gBAAA,CAAiB,CAAA,CAAA,CAG5E,CAEO,SAASE,EAAa,CAC3B,QAAAC,EACA,KAAAC,EACA,MAAAC,EACA,WAAAC,EACA,aAAAC,EACA,aAAAC,EACA,UAAAC,EACA,aAAAC,EAAe,mBACf,KAAAC,EACA,OAAAC,EACA,OAAAC,EACA,OAAAC,EAAS,MACX,EAAsB,CACpB,OAAIL,EAEAR,EAAAA,IAAC,MAAA,CAAI,UAAU,0BACZ,SAAA,MAAM,KAAK,CAAE,OAAQ,CAAA,CAAG,EAAE,IAAI,CAACc,EAAGC,IACjCf,EAAAA,IAAC,MAAA,CAAY,UAAU,uDACrB,SAAAA,EAAAA,IAAC,MAAA,CAAI,UAAU,sCAAA,CAAuC,CAAA,EAD9Ce,CAEV,CACD,CAAA,CACH,EAICZ,EAAK,OAKRa,OAAC,SAAM,UAAW,UAAUH,IAAW,QAAU,cAAgB,EAAE,GACjE,SAAA,CAAAb,EAAAA,IAAC,QAAA,CACC,eAAC,KAAA,CAAG,UAAU,WACX,SAAAE,EAAQ,IAAKe,GAAQ,CACpB,MAAMC,EAAaD,EAAI,UAAYN,EAC7BQ,GAAWT,GAAA,YAAAA,EAAM,WAAYO,EAAI,IAEvC,OACEjB,EAAAA,IAAC,KAAA,CAEC,QAASkB,EAAa,IAAMP,EAAOM,EAAI,GAAG,EAAI,OAC9C,UAAW,GAAGL,EAAS,GAAK,yBAAyB,2HAA2HK,EAAI,WAAa,EAAE,IACjMC,EAAa,wFAA0F,EACzG,GAEA,SAAAF,EAAAA,KAAC,OAAA,CAAK,UAAU,iCACb,SAAA,CAAAC,EAAI,MACJC,SACErB,EAAA,CAAS,OAAQsB,EAAU,UAAWA,EAAWT,EAAK,MAAQ,MAAA,CAAQ,CAAA,CAAA,CAE3E,CAAA,EAXKO,EAAI,GAAA,CAcf,CAAC,EACH,EACF,QACC,QAAA,CACE,SAAAd,EAAK,IAAI,CAACiB,EAAKC,IAAU,CACxB,MAAMF,EAAWb,GAAgB,MAAQF,EAAMgB,CAAG,IAAMd,EACxD,OACAN,EAAAA,IAAC,KAAA,CAEC,QAASK,EAAa,IAAMA,EAAWe,CAAG,EAAI,OAC9C,UAAW,qEACTf,EAAa,2BAA6B,EAC5C,IAAIc,EAAW,6BAA+B,EAAE,IAAIZ,EAAeA,EAAaa,CAAG,EAAI,EAAE,GAExF,SAAAlB,EAAQ,IAAKe,GACZjB,EAAAA,IAAC,KAAA,CAEC,UAAW,uBAAuBiB,EAAI,WAAa,EAAE,GAEpD,SAAAA,EAAI,OAAOG,EAAKC,CAAK,CAAA,EAHjBJ,EAAI,GAAA,CAKZ,CAAA,EAbIb,EAAMgB,CAAG,CAAA,CAgBlB,CAAC,CAAA,CACH,CAAA,EACF,EArDOX,EAAeT,EAAAA,IAACsB,EAAA,CAAW,MAAOb,EAAc,EAAK,IAuDhE"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as n,j as l}from"./vendor-query-B2UbickB.js";import{
|
|
2
|
-
//# sourceMappingURL=DropZone-
|
|
1
|
+
import{a as n,j as l}from"./vendor-query-B2UbickB.js";import{aS as D}from"./vendor-icons-BXhWQC7l.js";function v(r,c){const p=c.split(",").map(e=>e.trim());for(const e of p)if(e.startsWith(".")&&r.name.toLowerCase().endsWith(e.toLowerCase())||e===r.type||e.endsWith("/*")&&r.type.startsWith(e.slice(0,-1)))return!0;return!1}function j({onDrop:r,children:c,label:p="Drop files here",accept:e,disabled:i}){const[u,f]=n.useState(!1),s=n.useRef(0),d=n.useCallback(t=>{t.preventDefault(),t.stopPropagation(),s.current++,i||f(!0)},[i]),g=n.useCallback(t=>{t.preventDefault(),t.stopPropagation(),s.current--,s.current<=0&&(s.current=0,f(!1))},[]),x=n.useCallback(t=>{t.preventDefault(),t.stopPropagation()},[]),h=n.useCallback(t=>{if(t.preventDefault(),t.stopPropagation(),s.current=0,f(!1),i)return;const o=Array.from(t.dataTransfer.files);if(console.debug("[DropZone] dropped files:",o.map(a=>({name:a.name,type:a.type,size:a.size}))),e){const a=o.filter(m=>v(m,e));console.debug("[DropZone] after accept filter:",a.length,"of",o.length),a.length?r(a):console.warn("[DropZone] no files matched accept pattern:",e)}else o.length&&r(o)},[r,e,i]);return l.jsxs("div",{className:"relative",onDragEnter:d,onDragLeave:g,onDragOver:x,onDrop:h,children:[c,u&&l.jsx("div",{className:"fixed inset-0 z-50 flex flex-col items-center justify-center transition-opacity pointer-events-none",style:{background:"rgba(var(--color-surface-rgb, 255 255 255) / 0.85)"},children:l.jsxs("div",{className:"flex flex-col items-center gap-2 px-6 py-5 rounded-xl border border-dashed border-text-quaternary/40",children:[l.jsx(D,{className:"w-8 h-8 text-text-tertiary"}),l.jsx("p",{className:"text-xs text-text-secondary",children:p})]})})]})}export{j as D};
|
|
2
|
+
//# sourceMappingURL=DropZone-C_Mc4UrO.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DropZone-
|
|
1
|
+
{"version":3,"file":"DropZone-C_Mc4UrO.js","sources":["../../src/components/common/DropZone.tsx"],"sourcesContent":["import { useState, useCallback, useRef, type DragEvent, type ReactNode } from 'react';\nimport { UploadCloud } from 'lucide-react';\n\ninterface DropZoneProps {\n onDrop: (files: File[]) => void;\n children: ReactNode;\n label?: string;\n accept?: string;\n disabled?: boolean;\n}\n\nfunction matchesAccept(file: File, accept: string): boolean {\n const patterns = accept.split(',').map(s => s.trim());\n for (const pattern of patterns) {\n if (pattern.startsWith('.') && file.name.toLowerCase().endsWith(pattern.toLowerCase())) return true;\n if (pattern === file.type) return true;\n if (pattern.endsWith('/*') && file.type.startsWith(pattern.slice(0, -1))) return true;\n }\n return false;\n}\n\nexport function DropZone({ onDrop, children, label = 'Drop files here', accept, disabled }: DropZoneProps) {\n const [dragOver, setDragOver] = useState(false);\n const dragCounter = useRef(0);\n\n const handleDragEnter = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n dragCounter.current++;\n if (!disabled) setDragOver(true);\n }, [disabled]);\n\n const handleDragLeave = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n dragCounter.current--;\n if (dragCounter.current <= 0) {\n dragCounter.current = 0;\n setDragOver(false);\n }\n }, []);\n\n const handleDragOver = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n }, []);\n\n const handleDrop = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n dragCounter.current = 0;\n setDragOver(false);\n if (disabled) return;\n\n const files = Array.from(e.dataTransfer.files);\n console.debug('[DropZone] dropped files:', files.map(f => ({ name: f.name, type: f.type, size: f.size })));\n\n if (accept) {\n const filtered = files.filter(f => matchesAccept(f, accept));\n console.debug('[DropZone] after accept filter:', filtered.length, 'of', files.length);\n if (filtered.length) onDrop(filtered);\n else console.warn('[DropZone] no files matched accept pattern:', accept);\n } else {\n if (files.length) onDrop(files);\n }\n }, [onDrop, accept, disabled]);\n\n return (\n <div\n className=\"relative\"\n onDragEnter={handleDragEnter}\n onDragLeave={handleDragLeave}\n onDragOver={handleDragOver}\n onDrop={handleDrop}\n >\n {children}\n {dragOver && (\n <div className=\"fixed inset-0 z-50 flex flex-col items-center justify-center transition-opacity pointer-events-none\"\n style={{ background: 'rgba(var(--color-surface-rgb, 255 255 255) / 0.85)' }}\n >\n <div className=\"flex flex-col items-center gap-2 px-6 py-5 rounded-xl border border-dashed border-text-quaternary/40\">\n <UploadCloud className=\"w-8 h-8 text-text-tertiary\" />\n <p className=\"text-xs text-text-secondary\">{label}</p>\n </div>\n </div>\n )}\n </div>\n );\n}\n"],"names":["matchesAccept","file","accept","patterns","s","pattern","DropZone","onDrop","children","label","disabled","dragOver","setDragOver","useState","dragCounter","useRef","handleDragEnter","useCallback","e","handleDragLeave","handleDragOver","handleDrop","files","f","filtered","jsxs","jsx","UploadCloud"],"mappings":"sGAWA,SAASA,EAAcC,EAAYC,EAAyB,CAC1D,MAAMC,EAAWD,EAAO,MAAM,GAAG,EAAE,IAAIE,GAAKA,EAAE,MAAM,EACpD,UAAWC,KAAWF,EAGpB,GAFIE,EAAQ,WAAW,GAAG,GAAKJ,EAAK,KAAK,YAAA,EAAc,SAASI,EAAQ,YAAA,CAAa,GACjFA,IAAYJ,EAAK,MACjBI,EAAQ,SAAS,IAAI,GAAKJ,EAAK,KAAK,WAAWI,EAAQ,MAAM,EAAG,EAAE,CAAC,EAAG,MAAO,GAEnF,MAAO,EACT,CAEO,SAASC,EAAS,CAAE,OAAAC,EAAQ,SAAAC,EAAU,MAAAC,EAAQ,kBAAmB,OAAAP,EAAQ,SAAAQ,GAA2B,CACzG,KAAM,CAACC,EAAUC,CAAW,EAAIC,EAAAA,SAAS,EAAK,EACxCC,EAAcC,EAAAA,OAAO,CAAC,EAEtBC,EAAkBC,cAAaC,GAAiB,CACpDA,EAAE,eAAA,EACFA,EAAE,gBAAA,EACFJ,EAAY,UACPJ,GAAUE,EAAY,EAAI,CACjC,EAAG,CAACF,CAAQ,CAAC,EAEPS,EAAkBF,cAAaC,GAAiB,CACpDA,EAAE,eAAA,EACFA,EAAE,gBAAA,EACFJ,EAAY,UACRA,EAAY,SAAW,IACzBA,EAAY,QAAU,EACtBF,EAAY,EAAK,EAErB,EAAG,CAAA,CAAE,EAECQ,EAAiBH,cAAaC,GAAiB,CACnDA,EAAE,eAAA,EACFA,EAAE,gBAAA,CACJ,EAAG,CAAA,CAAE,EAECG,EAAaJ,cAAaC,GAAiB,CAK/C,GAJAA,EAAE,eAAA,EACFA,EAAE,gBAAA,EACFJ,EAAY,QAAU,EACtBF,EAAY,EAAK,EACbF,EAAU,OAEd,MAAMY,EAAQ,MAAM,KAAKJ,EAAE,aAAa,KAAK,EAG7C,GAFA,QAAQ,MAAM,4BAA6BI,EAAM,IAAIC,IAAM,CAAE,KAAMA,EAAE,KAAM,KAAMA,EAAE,KAAM,KAAMA,EAAE,IAAA,EAAO,CAAC,EAErGrB,EAAQ,CACV,MAAMsB,EAAWF,EAAM,UAAYtB,EAAcuB,EAAGrB,CAAM,CAAC,EAC3D,QAAQ,MAAM,kCAAmCsB,EAAS,OAAQ,KAAMF,EAAM,MAAM,EAChFE,EAAS,OAAQjB,EAAOiB,CAAQ,EAC/B,QAAQ,KAAK,8CAA+CtB,CAAM,CACzE,MACMoB,EAAM,QAAQf,EAAOe,CAAK,CAElC,EAAG,CAACf,EAAQL,EAAQQ,CAAQ,CAAC,EAE7B,OACEe,EAAAA,KAAC,MAAA,CACC,UAAU,WACV,YAAaT,EACb,YAAaG,EACb,WAAYC,EACZ,OAAQC,EAEP,SAAA,CAAAb,EACAG,GACCe,EAAAA,IAAC,MAAA,CAAI,UAAU,sGACb,MAAO,CAAE,WAAY,oDAAA,EAErB,SAAAD,EAAAA,KAAC,MAAA,CAAI,UAAU,uGACb,SAAA,CAAAC,EAAAA,IAACC,EAAA,CAAY,UAAU,4BAAA,CAA6B,EACpDD,EAAAA,IAAC,IAAA,CAAE,UAAU,8BAA+B,SAAAjB,CAAA,CAAM,CAAA,CAAA,CACpD,CAAA,CAAA,CACF,CAAA,CAAA,CAIR"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as s,j as n}from"./vendor-query-B2UbickB.js";import{z as p,H as f}from"./index-
|
|
2
|
-
//# sourceMappingURL=ElapsedCell-
|
|
1
|
+
import{a as s,j as n}from"./vendor-query-B2UbickB.js";import{z as p,H as f}from"./index-C9moIiIq.js";function D({startDate:r,endDate:o,isLive:e}){const[l,c]=s.useState(Date.now);s.useEffect(()=>{if(!e)return;const u=setInterval(()=>c(Date.now()),1e3);return()=>clearInterval(u)},[e]);const i=new Date(r).getTime(),m=o?new Date(o).getTime():l,t=Math.max(0,m-i),a=p(t),x=s.useMemo(()=>[{label:"ms",value:String(t)},{label:"sec",value:`${(t/1e3).toFixed(3)}s`},{label:"text",value:a}],[t,a]);return n.jsx(f,{options:x,children:n.jsx("span",{className:`text-xs ${e?"text-status-active":"text-text-tertiary"}`,children:a})})}export{D as E};
|
|
2
|
+
//# sourceMappingURL=ElapsedCell-Cw1uvJKx.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ElapsedCell-
|
|
1
|
+
{"version":3,"file":"ElapsedCell-Cw1uvJKx.js","sources":["../../src/components/common/display/ElapsedCell.tsx"],"sourcesContent":["import { useState, useEffect, useMemo } from 'react';\nimport { formatDurationCompact } from '../../../lib/format';\nimport { DateTooltip } from './DateTooltip';\n\ninterface ElapsedCellProps {\n startDate: string;\n endDate?: string | null;\n isLive?: boolean;\n}\n\n/**\n * Elapsed duration cell for data tables.\n * Shows compact duration with hover tooltip. Ticks every second when live.\n */\nexport function ElapsedCell({ startDate, endDate, isLive }: ElapsedCellProps) {\n const [now, setNow] = useState(Date.now);\n\n useEffect(() => {\n if (!isLive) return;\n const id = setInterval(() => setNow(Date.now()), 1000);\n return () => clearInterval(id);\n }, [isLive]);\n\n const start = new Date(startDate).getTime();\n const end = endDate ? new Date(endDate).getTime() : now;\n const ms = Math.max(0, end - start);\n\n const display = formatDurationCompact(ms);\n\n const options = useMemo(() => [\n { label: 'ms', value: String(ms) },\n { label: 'sec', value: `${(ms / 1000).toFixed(3)}s` },\n { label: 'text', value: display },\n ], [ms, display]);\n\n return (\n <DateTooltip options={options}>\n <span className={`text-xs ${isLive ? 'text-status-active' : 'text-text-tertiary'}`}>\n {display}\n </span>\n </DateTooltip>\n );\n}\n"],"names":["ElapsedCell","startDate","endDate","isLive","now","setNow","useState","useEffect","id","start","end","ms","display","formatDurationCompact","options","useMemo","jsx","DateTooltip"],"mappings":"qGAcO,SAASA,EAAY,CAAE,UAAAC,EAAW,QAAAC,EAAS,OAAAC,GAA4B,CAC5E,KAAM,CAACC,EAAKC,CAAM,EAAIC,EAAAA,SAAS,KAAK,GAAG,EAEvCC,EAAAA,UAAU,IAAM,CACd,GAAI,CAACJ,EAAQ,OACb,MAAMK,EAAK,YAAY,IAAMH,EAAO,KAAK,IAAA,CAAK,EAAG,GAAI,EACrD,MAAO,IAAM,cAAcG,CAAE,CAC/B,EAAG,CAACL,CAAM,CAAC,EAEX,MAAMM,EAAQ,IAAI,KAAKR,CAAS,EAAE,QAAA,EAC5BS,EAAMR,EAAU,IAAI,KAAKA,CAAO,EAAE,UAAYE,EAC9CO,EAAK,KAAK,IAAI,EAAGD,EAAMD,CAAK,EAE5BG,EAAUC,EAAsBF,CAAE,EAElCG,EAAUC,EAAAA,QAAQ,IAAM,CAC5B,CAAE,MAAO,KAAM,MAAO,OAAOJ,CAAE,CAAA,EAC/B,CAAE,MAAO,MAAO,MAAO,IAAIA,EAAK,KAAM,QAAQ,CAAC,CAAC,GAAA,EAChD,CAAE,MAAO,OAAQ,MAAOC,CAAA,CAAQ,EAC/B,CAACD,EAAIC,CAAO,CAAC,EAEhB,OACEI,EAAAA,IAACC,EAAA,CAAY,QAAAH,EACX,SAAAE,EAAAA,IAAC,OAAA,CAAK,UAAW,WAAWb,EAAS,qBAAuB,oBAAoB,GAC7E,SAAAS,CAAA,CACH,EACF,CAEJ"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import{a as l,j as e}from"./vendor-query-B2UbickB.js";import{d as w,f as S,l as _,a as L}from"./roles-dJKBZUBh.js";import{J as E}from"./index-C9moIiIq.js";import{a6 as v,B as C,V as O,ap as R}from"./vendor-icons-BXhWQC7l.js";import{e as V}from"./vendor-react-CXumBFUA.js";const q=`{
|
|
2
|
+
"x-lt-layout": "active-history",
|
|
3
|
+
"x-lt-help": "# {{escalation.type}}\\nThe live item plus its history.",
|
|
4
|
+
"x-lt-active": {
|
|
5
|
+
"title": "{{metadata.title}}",
|
|
6
|
+
"subtitle": "Updated {{escalation.updated_at}}",
|
|
7
|
+
"body": "{{payload.document_markdown}}",
|
|
8
|
+
"fields": [
|
|
9
|
+
{ "label": "Owner", "value": "{{metadata.owner}}" }
|
|
10
|
+
]
|
|
11
|
+
},
|
|
12
|
+
"x-lt-history": {
|
|
13
|
+
"row": {
|
|
14
|
+
"title": "{{metadata.title}} rev {{metadata.revision}}",
|
|
15
|
+
"subtitle": "{{escalation.status}} · {{escalation.resolved_at}}"
|
|
16
|
+
},
|
|
17
|
+
"limit": 25
|
|
18
|
+
}
|
|
19
|
+
}`;function j(i){const s=i.trim();if(!s)return{ok:!0,value:null};try{const r=JSON.parse(s);return typeof r!="object"||Array.isArray(r)||r===null?{ok:!1}:{ok:!0,value:r}}catch{return{ok:!1}}}function F(){const{role:i}=V(),{data:s,isLoading:r}=w(),n=S(),t=((s==null?void 0:s.roles)??[]).find(a=>a.role===i),[o,c]=l.useState(""),[h,u]=l.useState(""),[y,d]=l.useState(!1),[N,x]=l.useState(!1),[p,m]=l.useState(!1),f=l.useRef(null);l.useEffect(()=>{!t||f.current===t.role||(f.current=t.role,c(t.list_schema?JSON.stringify(t.list_schema,null,2):""),u(""),d(!1),m(!1))},[t]);const g=a=>{c(a),d(!0),x(!1),m(!j(a).ok)},b=()=>{const a=j(o);if(!a.ok||!t){m(!a.ok);return}n.mutate({role:t.role,list_schema:a.value??null,change_summary:h.trim()||void 0},{onSuccess:()=>{d(!1),x(!0),u(""),window.setTimeout(()=>x(!1),2500)}})},k=a=>{c(a?JSON.stringify(a,null,2):""),d(!0),x(!1),m(!1)};return r?e.jsxs("div",{className:"animate-pulse space-y-4",children:[e.jsx("div",{className:"h-8 bg-surface-sunken rounded w-64"}),e.jsx("div",{className:"h-96 bg-surface-sunken rounded"})]}):t?e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-start justify-between mb-10",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center gap-3 mb-1",children:[e.jsx(v,{className:"w-5 h-5 text-accent",strokeWidth:1.5}),e.jsx("h1",{className:"text-lg font-medium text-text-primary",children:"Escalations List Schema"}),e.jsx("button",{onClick:()=>{window.location.hash="#docs:dashboard.md:escalations-list-schema"},className:"text-text-quaternary hover:text-accent transition-colors",title:"Open docs for this page",children:e.jsx(C,{className:"w-4 h-4",strokeWidth:1.5})}),e.jsx("span",{className:"font-mono text-sm text-text-tertiary",children:t.role}),t.current_list_schema_version!=null&&e.jsxs("span",{className:"text-[10px] font-mono text-text-quaternary",children:["v",t.current_list_schema_version," in use"]})]}),e.jsx("button",{onClick:()=>{window.location.hash="#docs:hitl-guide.md:escalations-list-schema"},className:"text-[11px] text-accent hover:underline pl-8",children:"List authoring reference — layout modes, the active card, history, and token binding →"})]}),e.jsxs("div",{className:"flex items-center gap-2 shrink-0",children:[N&&e.jsxs("span",{className:"flex items-center gap-1 text-xs text-status-success animate-page-enter",children:[e.jsx(O,{className:"w-3 h-3"})," Saved"]}),n.error&&e.jsx("span",{className:"text-xs text-status-error max-w-[220px] truncate",children:n.error.message}),e.jsx("button",{onClick:b,disabled:!y||p||n.isPending,className:"px-3 py-1.5 text-xs rounded-md bg-accent text-text-inverse hover:bg-accent-hover transition-colors disabled:opacity-40 disabled:cursor-not-allowed",children:n.isPending?"Saving…":"Save Version"})]})]}),e.jsxs("div",{className:"grid grid-cols-3 gap-16 items-start",children:[e.jsxs("div",{className:"col-span-2 space-y-6",children:[e.jsx("textarea",{value:o,onChange:a=>g(a.target.value),rows:28,spellCheck:!1,className:"input text-xs font-mono w-full resize-y leading-relaxed",placeholder:q}),p&&e.jsx("p",{className:"text-[10px] text-status-error -mt-4",children:"Invalid JSON"}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-1.5",children:"Change Summary"}),e.jsx("input",{type:"text",value:h,onChange:a=>u(a.target.value),placeholder:"e.g., Added the history column",className:"input text-sm w-full"}),e.jsx("p",{className:"text-[10px] text-text-quaternary mt-1.5",children:"Recorded on the version this save creates. Versions independently of the resolve form schema."})]})]}),e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center gap-2 mb-3 pb-2 border-b border-surface-border",children:[e.jsx(R,{className:"w-4 h-4 text-text-quaternary",strokeWidth:1.5}),e.jsx("h2",{className:"section-h2",children:"Versions"})]}),e.jsx(J,{role:t.role,onLoad:k})]})]})]}):e.jsxs("div",{className:"flex flex-col items-center justify-center py-20 text-center",children:[e.jsx(v,{className:"w-12 h-12 text-text-quaternary mb-4",strokeWidth:1}),e.jsx("h2",{className:"text-lg font-medium text-text-primary mb-2",children:"Role not found"})]})}function J({role:i,onLoad:s}){const{data:r}=_(i),n=(r==null?void 0:r.versions)??[];return n.length===0?e.jsx("p",{className:"text-[11px] text-text-tertiary leading-relaxed",children:"Versions appear here after the first save. Each list-schema change adds one; earlier versions stay viewable and loadable as an editing base."}):e.jsx("div",{className:"divide-y divide-surface-border/40",children:n.map(t=>e.jsx(P,{role:i,summary:t,onLoad:s},t.version))})}function P({role:i,summary:s,onLoad:r}){const[n,t]=l.useState(!1),o=L(i,s.version,n);return e.jsxs("div",{className:"py-2",children:[e.jsxs("button",{onClick:()=>t(c=>!c),className:"w-full text-left group",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("span",{className:"text-xs font-mono text-text-secondary",children:["v",s.version]}),s.is_current&&e.jsx("span",{className:"text-[9px] font-bold uppercase tracking-wider text-accent",children:"current"}),e.jsx("span",{className:"flex-1"}),e.jsx("span",{className:"text-[10px] text-text-quaternary shrink-0",children:new Date(s.created_at).toLocaleDateString()})]}),s.change_summary&&e.jsx("p",{className:"mt-0.5 text-[10px] text-text-tertiary truncate",children:s.change_summary})]}),n&&e.jsx("div",{className:"mt-2 space-y-2",children:o.data?e.jsxs(e.Fragment,{children:[o.data.list_schema?e.jsx(E,{data:o.data.list_schema,defaultCollapsed:!0}):e.jsx("p",{className:"text-[10px] text-text-quaternary",children:"This version carries no list schema."}),e.jsx("button",{onClick:()=>r(o.data.list_schema??null),className:"text-[10px] text-accent hover:underline",children:"Load into editor"})]}):e.jsx("p",{className:"text-[10px] text-text-quaternary",children:"Loading…"})})]})}export{F as EscalationListSchemaPage};
|
|
20
|
+
//# sourceMappingURL=EscalationListSchemaPage-3v2tiCnq.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EscalationListSchemaPage-3v2tiCnq.js","sources":["../../src/pages/admin/roles/EscalationListSchemaPage.tsx"],"sourcesContent":["import { useState, useEffect, useRef } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { LayoutList, Check, History, BookOpen } from 'lucide-react';\nimport {\n useRoleDetails,\n useRoleListSchema,\n useRoleListSchemaVersions,\n useUpdateRole,\n type RoleListSchemaVersionSummary,\n} from '../../../api/roles';\nimport { JsonViewer } from '../../../components/common/data/JsonViewer';\n\n/**\n * The escalation LIST schema, on its own page (/admin/roles/:role/list-schema).\n * This is the rich view a role's list page renders when scoped to just this\n * role — the list-page analog of the resolve form schema. Versioned\n * INDEPENDENTLY of the form schema: saving here writes ONLY list_schema and\n * advances only current_list_schema_version, leaving the form version alone.\n */\n\nconst PLACEHOLDER = `{\n \"x-lt-layout\": \"active-history\",\n \"x-lt-help\": \"# {{escalation.type}}\\\\nThe live item plus its history.\",\n \"x-lt-active\": {\n \"title\": \"{{metadata.title}}\",\n \"subtitle\": \"Updated {{escalation.updated_at}}\",\n \"body\": \"{{payload.document_markdown}}\",\n \"fields\": [\n { \"label\": \"Owner\", \"value\": \"{{metadata.owner}}\" }\n ]\n },\n \"x-lt-history\": {\n \"row\": {\n \"title\": \"{{metadata.title}} rev {{metadata.revision}}\",\n \"subtitle\": \"{{escalation.status}} · {{escalation.resolved_at}}\"\n },\n \"limit\": 25\n }\n}`;\n\nfunction safeParseObject(text: string): { ok: boolean; value?: Record<string, unknown> | null } {\n const trimmed = text.trim();\n if (!trimmed) return { ok: true, value: null };\n try {\n const parsed = JSON.parse(trimmed);\n if (typeof parsed !== 'object' || Array.isArray(parsed) || parsed === null) return { ok: false };\n return { ok: true, value: parsed };\n } catch {\n return { ok: false };\n }\n}\n\nexport function EscalationListSchemaPage() {\n const { role: roleKey } = useParams<{ role: string }>();\n const { data, isLoading } = useRoleDetails();\n const updateRole = useUpdateRole();\n\n const role = (data?.roles ?? []).find((r) => r.role === roleKey);\n\n const [text, setText] = useState('');\n const [summary, setSummary] = useState('');\n const [dirty, setDirty] = useState(false);\n const [savedOk, setSavedOk] = useState(false);\n const [jsonError, setJsonError] = useState(false);\n\n // Seed once per role — refetches must not clobber in-progress edits.\n const seededFor = useRef<string | null>(null);\n useEffect(() => {\n if (!role || seededFor.current === role.role) return;\n seededFor.current = role.role;\n setText(role.list_schema ? JSON.stringify(role.list_schema, null, 2) : '');\n setSummary('');\n setDirty(false);\n setJsonError(false);\n }, [role]);\n\n const handleEdit = (value: string) => {\n setText(value);\n setDirty(true);\n setSavedOk(false);\n setJsonError(!safeParseObject(value).ok);\n };\n\n const handleSave = () => {\n const parsed = safeParseObject(text);\n if (!parsed.ok || !role) { setJsonError(!parsed.ok); return; }\n updateRole.mutate(\n { role: role.role, list_schema: parsed.value ?? null, change_summary: summary.trim() || undefined },\n {\n onSuccess: () => {\n setDirty(false);\n setSavedOk(true);\n setSummary('');\n window.setTimeout(() => setSavedOk(false), 2500);\n },\n },\n );\n };\n\n const loadIntoEditor = (schema: Record<string, unknown> | null) => {\n setText(schema ? JSON.stringify(schema, null, 2) : '');\n setDirty(true);\n setSavedOk(false);\n setJsonError(false);\n };\n\n if (isLoading) {\n return (\n <div className=\"animate-pulse space-y-4\">\n <div className=\"h-8 bg-surface-sunken rounded w-64\" />\n <div className=\"h-96 bg-surface-sunken rounded\" />\n </div>\n );\n }\n\n if (!role) {\n return (\n <div className=\"flex flex-col items-center justify-center py-20 text-center\">\n <LayoutList className=\"w-12 h-12 text-text-quaternary mb-4\" strokeWidth={1} />\n <h2 className=\"text-lg font-medium text-text-primary mb-2\">Role not found</h2>\n </div>\n );\n }\n\n return (\n <div>\n {/* ── Header ── */}\n <div className=\"flex items-start justify-between mb-10\">\n <div>\n <div className=\"flex items-center gap-3 mb-1\">\n <LayoutList className=\"w-5 h-5 text-accent\" strokeWidth={1.5} />\n <h1 className=\"text-lg font-medium text-text-primary\">Escalations List Schema</h1>\n <button\n onClick={() => { window.location.hash = '#docs:dashboard.md:escalations-list-schema'; }}\n className=\"text-text-quaternary hover:text-accent transition-colors\"\n title=\"Open docs for this page\"\n >\n <BookOpen className=\"w-4 h-4\" strokeWidth={1.5} />\n </button>\n <span className=\"font-mono text-sm text-text-tertiary\">{role.role}</span>\n {role.current_list_schema_version != null && (\n <span className=\"text-[10px] font-mono text-text-quaternary\">\n v{role.current_list_schema_version} in use\n </span>\n )}\n </div>\n <button\n onClick={() => { window.location.hash = '#docs:hitl-guide.md:escalations-list-schema'; }}\n className=\"text-[11px] text-accent hover:underline pl-8\"\n >\n List authoring reference — layout modes, the active card, history, and token binding →\n </button>\n </div>\n\n <div className=\"flex items-center gap-2 shrink-0\">\n {savedOk && (\n <span className=\"flex items-center gap-1 text-xs text-status-success animate-page-enter\">\n <Check className=\"w-3 h-3\" /> Saved\n </span>\n )}\n {updateRole.error && (\n <span className=\"text-xs text-status-error max-w-[220px] truncate\">\n {(updateRole.error as Error).message}\n </span>\n )}\n <button\n onClick={handleSave}\n disabled={!dirty || jsonError || updateRole.isPending}\n className=\"px-3 py-1.5 text-xs rounded-md bg-accent text-text-inverse hover:bg-accent-hover transition-colors disabled:opacity-40 disabled:cursor-not-allowed\"\n >\n {updateRole.isPending ? 'Saving…' : 'Save Version'}\n </button>\n </div>\n </div>\n\n {/* ── Editor + version rail ── */}\n <div className=\"grid grid-cols-3 gap-16 items-start\">\n <div className=\"col-span-2 space-y-6\">\n <textarea\n value={text}\n onChange={(e) => handleEdit(e.target.value)}\n rows={28}\n spellCheck={false}\n className=\"input text-xs font-mono w-full resize-y leading-relaxed\"\n placeholder={PLACEHOLDER}\n />\n {jsonError && <p className=\"text-[10px] text-status-error -mt-4\">Invalid JSON</p>}\n\n <div>\n <label className=\"block text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-1.5\">\n Change Summary\n </label>\n <input\n type=\"text\"\n value={summary}\n onChange={(e) => setSummary(e.target.value)}\n placeholder=\"e.g., Added the history column\"\n className=\"input text-sm w-full\"\n />\n <p className=\"text-[10px] text-text-quaternary mt-1.5\">\n Recorded on the version this save creates. Versions independently of the resolve form schema.\n </p>\n </div>\n </div>\n\n {/* Version history — view any snapshot, load one as the editing base */}\n <div>\n <div className=\"flex items-center gap-2 mb-3 pb-2 border-b border-surface-border\">\n <History className=\"w-4 h-4 text-text-quaternary\" strokeWidth={1.5} />\n <h2 className=\"section-h2\">Versions</h2>\n </div>\n <VersionRail role={role.role} onLoad={loadIntoEditor} />\n </div>\n </div>\n </div>\n );\n}\n\nfunction VersionRail({\n role,\n onLoad,\n}: {\n role: string;\n onLoad: (schema: Record<string, unknown> | null) => void;\n}) {\n const { data } = useRoleListSchemaVersions(role);\n const versions = data?.versions ?? [];\n\n if (versions.length === 0) {\n return (\n <p className=\"text-[11px] text-text-tertiary leading-relaxed\">\n Versions appear here after the first save. Each list-schema change adds one;\n earlier versions stay viewable and loadable as an editing base.\n </p>\n );\n }\n\n return (\n <div className=\"divide-y divide-surface-border/40\">\n {versions.map((v) => (\n <VersionEntry key={v.version} role={role} summary={v} onLoad={onLoad} />\n ))}\n </div>\n );\n}\n\nfunction VersionEntry({\n role,\n summary,\n onLoad,\n}: {\n role: string;\n summary: RoleListSchemaVersionSummary;\n onLoad: (schema: Record<string, unknown> | null) => void;\n}) {\n const [open, setOpen] = useState(false);\n const snapshot = useRoleListSchema(role, summary.version, open);\n\n return (\n <div className=\"py-2\">\n <button onClick={() => setOpen((o) => !o)} className=\"w-full text-left group\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-xs font-mono text-text-secondary\">v{summary.version}</span>\n {summary.is_current && (\n <span className=\"text-[9px] font-bold uppercase tracking-wider text-accent\">current</span>\n )}\n <span className=\"flex-1\" />\n <span className=\"text-[10px] text-text-quaternary shrink-0\">\n {new Date(summary.created_at).toLocaleDateString()}\n </span>\n </div>\n {summary.change_summary && (\n <p className=\"mt-0.5 text-[10px] text-text-tertiary truncate\">{summary.change_summary}</p>\n )}\n </button>\n {open && (\n <div className=\"mt-2 space-y-2\">\n {snapshot.data ? (\n <>\n {snapshot.data.list_schema\n ? <JsonViewer data={snapshot.data.list_schema} defaultCollapsed />\n : <p className=\"text-[10px] text-text-quaternary\">This version carries no list schema.</p>}\n <button\n onClick={() => onLoad((snapshot.data!.list_schema ?? null) as Record<string, unknown> | null)}\n className=\"text-[10px] text-accent hover:underline\"\n >\n Load into editor\n </button>\n </>\n ) : (\n <p className=\"text-[10px] text-text-quaternary\">Loading…</p>\n )}\n </div>\n )}\n </div>\n );\n}\n"],"names":["PLACEHOLDER","safeParseObject","text","trimmed","parsed","EscalationListSchemaPage","roleKey","useParams","data","isLoading","useRoleDetails","updateRole","useUpdateRole","role","r","setText","useState","summary","setSummary","dirty","setDirty","savedOk","setSavedOk","jsonError","setJsonError","seededFor","useRef","useEffect","handleEdit","value","handleSave","loadIntoEditor","schema","jsxs","jsx","LayoutList","BookOpen","Check","e","History","VersionRail","onLoad","useRoleListSchemaVersions","versions","v","VersionEntry","open","setOpen","snapshot","useRoleListSchema","o","Fragment","JsonViewer"],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import{a as l,j as e}from"./vendor-query-B2UbickB.js";import{d as w,f as S,j as _,k as E}from"./roles-dJKBZUBh.js";import{J as C}from"./index-C9moIiIq.js";import{g as j,B as O,V as R,ap as q}from"./vendor-icons-BXhWQC7l.js";import{e as V}from"./vendor-react-CXumBFUA.js";const J=`{
|
|
2
|
+
"type": "object",
|
|
3
|
+
"properties": {
|
|
4
|
+
"approved": { "type": "boolean", "title": "Approve?" },
|
|
5
|
+
"notes": { "type": "string", "title": "Notes" }
|
|
6
|
+
},
|
|
7
|
+
"required": ["approved"]
|
|
8
|
+
}`;function v(o){const t=o.trim();if(!t)return{ok:!0,value:null};try{const r=JSON.parse(t);return typeof r!="object"||Array.isArray(r)||r===null?{ok:!1}:{ok:!0,value:r}}catch{return{ok:!1}}}function T(){const{role:o}=V(),{data:t,isLoading:r}=w(),n=S(),s=((t==null?void 0:t.roles)??[]).find(a=>a.role===o),[c,i]=l.useState(""),[h,u]=l.useState(""),[g,d]=l.useState(!1),[N,x]=l.useState(!1),[p,m]=l.useState(!1),f=l.useRef(null);l.useEffect(()=>{!s||f.current===s.role||(f.current=s.role,i(s.form_schema?JSON.stringify(s.form_schema,null,2):""),u(""),d(!1),m(!1))},[s]);const y=a=>{i(a),d(!0),x(!1),m(!v(a).ok)},b=()=>{const a=v(c);if(!a.ok||!s){m(!a.ok);return}n.mutate({role:s.role,form_schema:a.value??null,change_summary:h.trim()||void 0},{onSuccess:()=>{d(!1),x(!0),u(""),window.setTimeout(()=>x(!1),2500)}})},k=a=>{i(a?JSON.stringify(a,null,2):""),d(!0),x(!1),m(!1)};return r?e.jsxs("div",{className:"animate-pulse space-y-4",children:[e.jsx("div",{className:"h-8 bg-surface-sunken rounded w-64"}),e.jsx("div",{className:"h-96 bg-surface-sunken rounded"})]}):s?e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-start justify-between mb-10",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center gap-3 mb-1",children:[e.jsx(j,{className:"w-5 h-5 text-accent",strokeWidth:1.5}),e.jsx("h1",{className:"text-lg font-medium text-text-primary",children:"Escalation Schema"}),e.jsx("button",{onClick:()=>{window.location.hash="#docs:dashboard.md:escalation-schema"},className:"text-text-quaternary hover:text-accent transition-colors",title:"Open docs for this page",children:e.jsx(O,{className:"w-4 h-4",strokeWidth:1.5})}),e.jsx("span",{className:"font-mono text-sm text-text-tertiary",children:s.role}),s.current_schema_version!=null&&e.jsxs("span",{className:"text-[10px] font-mono text-text-quaternary",children:["v",s.current_schema_version," in use"]})]}),e.jsx("button",{onClick:()=>{window.location.hash="#docs:hitl-guide.md:json-schema-form-authoring"},className:"text-[11px] text-accent hover:underline pl-8",children:"Form authoring reference — field types, widgets, and every x-lt-* keyword →"})]}),e.jsxs("div",{className:"flex items-center gap-2 shrink-0",children:[N&&e.jsxs("span",{className:"flex items-center gap-1 text-xs text-status-success animate-page-enter",children:[e.jsx(R,{className:"w-3 h-3"})," Saved"]}),n.error&&e.jsx("span",{className:"text-xs text-status-error max-w-[220px] truncate",children:n.error.message}),e.jsx("button",{onClick:b,disabled:!g||p||n.isPending,className:"px-3 py-1.5 text-xs rounded-md bg-accent text-text-inverse hover:bg-accent-hover transition-colors disabled:opacity-40 disabled:cursor-not-allowed",children:n.isPending?"Saving…":"Save Version"})]})]}),e.jsxs("div",{className:"grid grid-cols-3 gap-16 items-start",children:[e.jsxs("div",{className:"col-span-2 space-y-6",children:[e.jsx("textarea",{value:c,onChange:a=>y(a.target.value),rows:28,spellCheck:!1,className:"input text-xs font-mono w-full resize-y leading-relaxed",placeholder:J}),p&&e.jsx("p",{className:"text-[10px] text-status-error -mt-4",children:"Invalid JSON"}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-1.5",children:"Change Summary"}),e.jsx("input",{type:"text",value:h,onChange:a=>u(a.target.value),placeholder:"e.g., Added lotNumber field for shoe orders",className:"input text-sm w-full"}),e.jsx("p",{className:"text-[10px] text-text-quaternary mt-1.5",children:"Recorded on the version this save creates."})]})]}),e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center gap-2 mb-3 pb-2 border-b border-surface-border",children:[e.jsx(q,{className:"w-4 h-4 text-text-quaternary",strokeWidth:1.5}),e.jsx("h2",{className:"section-h2",children:"Versions"})]}),e.jsx(L,{role:s.role,onLoad:k})]})]})]}):e.jsxs("div",{className:"flex flex-col items-center justify-center py-20 text-center",children:[e.jsx(j,{className:"w-12 h-12 text-text-quaternary mb-4",strokeWidth:1}),e.jsx("h2",{className:"text-lg font-medium text-text-primary mb-2",children:"Role not found"})]})}function L({role:o,onLoad:t}){const{data:r}=_(o),n=(r==null?void 0:r.versions)??[];return n.length===0?e.jsx("p",{className:"text-[11px] text-text-tertiary leading-relaxed",children:"Versions appear here after the first save. Each schema change adds one; earlier versions stay viewable and loadable as an editing base."}):e.jsx("div",{className:"divide-y divide-surface-border/40",children:n.map(s=>e.jsx(P,{role:o,summary:s,onLoad:t},s.version))})}function P({role:o,summary:t,onLoad:r}){const[n,s]=l.useState(!1),c=E(o,t.version,n);return e.jsxs("div",{className:"py-2",children:[e.jsxs("button",{onClick:()=>s(i=>!i),className:"w-full text-left group",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("span",{className:"text-xs font-mono text-text-secondary",children:["v",t.version]}),t.is_current&&e.jsx("span",{className:"text-[9px] font-bold uppercase tracking-wider text-accent",children:"current"}),e.jsx("span",{className:"flex-1"}),e.jsx("span",{className:"text-[10px] text-text-quaternary shrink-0",children:new Date(t.created_at).toLocaleDateString()})]}),t.change_summary&&e.jsx("p",{className:"mt-0.5 text-[10px] text-text-tertiary truncate",children:t.change_summary})]}),n&&e.jsx("div",{className:"mt-2 space-y-2",children:c.data?e.jsxs(e.Fragment,{children:[c.data.form_schema?e.jsx(C,{data:c.data.form_schema,defaultCollapsed:!0}):e.jsx("p",{className:"text-[10px] text-text-quaternary",children:"This version carries no form schema."}),e.jsx("button",{onClick:()=>r(c.data.form_schema??null),className:"text-[10px] text-accent hover:underline",children:"Load into editor"})]}):e.jsx("p",{className:"text-[10px] text-text-quaternary",children:"Loading…"})})]})}export{T as EscalationSchemaPage};
|
|
9
|
+
//# sourceMappingURL=EscalationSchemaPage-DIq2pMED.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EscalationSchemaPage-DIq2pMED.js","sources":["../../src/pages/admin/roles/EscalationSchemaPage.tsx"],"sourcesContent":["import { useState, useEffect, useRef } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { Braces, Check, History, BookOpen } from 'lucide-react';\nimport {\n useRoleDetails,\n useRoleSchema,\n useRoleSchemaVersions,\n useUpdateRole,\n type RoleSchemaVersionSummary,\n} from '../../../api/roles';\nimport { JsonViewer } from '../../../components/common/data/JsonViewer';\n\n/**\n * The escalation form schema, on its own page (/admin/roles/:role/schema).\n * This is the form a person completes to resolve the role's escalations —\n * versioned, pinnable by workflows (conditionLT schemaVersion), and worth a\n * full editing surface. Saving here writes ONLY the schema: one PATCH with\n * form_schema (+ optional change summary); every actual change appends the\n * next immutable version.\n */\n\nconst PLACEHOLDER = `{\n \"type\": \"object\",\n \"properties\": {\n \"approved\": { \"type\": \"boolean\", \"title\": \"Approve?\" },\n \"notes\": { \"type\": \"string\", \"title\": \"Notes\" }\n },\n \"required\": [\"approved\"]\n}`;\n\nfunction safeParseObject(text: string): { ok: boolean; value?: Record<string, unknown> | null } {\n const trimmed = text.trim();\n if (!trimmed) return { ok: true, value: null };\n try {\n const parsed = JSON.parse(trimmed);\n if (typeof parsed !== 'object' || Array.isArray(parsed) || parsed === null) return { ok: false };\n return { ok: true, value: parsed };\n } catch {\n return { ok: false };\n }\n}\n\nexport function EscalationSchemaPage() {\n const { role: roleKey } = useParams<{ role: string }>();\n const { data, isLoading } = useRoleDetails();\n const updateRole = useUpdateRole();\n\n const role = (data?.roles ?? []).find((r) => r.role === roleKey);\n\n const [text, setText] = useState('');\n const [summary, setSummary] = useState('');\n const [dirty, setDirty] = useState(false);\n const [savedOk, setSavedOk] = useState(false);\n const [jsonError, setJsonError] = useState(false);\n\n // Seed the editor from the live schema exactly once per role — refetches\n // (cache invalidations, saves) must not clobber in-progress edits.\n const seededFor = useRef<string | null>(null);\n useEffect(() => {\n if (!role || seededFor.current === role.role) return;\n seededFor.current = role.role;\n setText(role.form_schema ? JSON.stringify(role.form_schema, null, 2) : '');\n setSummary('');\n setDirty(false);\n setJsonError(false);\n }, [role]);\n\n const handleEdit = (value: string) => {\n setText(value);\n setDirty(true);\n setSavedOk(false);\n setJsonError(!safeParseObject(value).ok);\n };\n\n const handleSave = () => {\n const parsed = safeParseObject(text);\n if (!parsed.ok || !role) { setJsonError(!parsed.ok); return; }\n // Saving just the schema — nothing else rides this PATCH.\n updateRole.mutate(\n { role: role.role, form_schema: parsed.value ?? null, change_summary: summary.trim() || undefined },\n {\n onSuccess: () => {\n setDirty(false);\n setSavedOk(true);\n setSummary('');\n window.setTimeout(() => setSavedOk(false), 2500);\n },\n },\n );\n };\n\n const loadIntoEditor = (schema: Record<string, unknown> | null) => {\n setText(schema ? JSON.stringify(schema, null, 2) : '');\n setDirty(true);\n setSavedOk(false);\n setJsonError(false);\n };\n\n if (isLoading) {\n return (\n <div className=\"animate-pulse space-y-4\">\n <div className=\"h-8 bg-surface-sunken rounded w-64\" />\n <div className=\"h-96 bg-surface-sunken rounded\" />\n </div>\n );\n }\n\n if (!role) {\n return (\n <div className=\"flex flex-col items-center justify-center py-20 text-center\">\n <Braces className=\"w-12 h-12 text-text-quaternary mb-4\" strokeWidth={1} />\n <h2 className=\"text-lg font-medium text-text-primary mb-2\">Role not found</h2>\n </div>\n );\n }\n\n return (\n <div>\n {/* ── Header ── */}\n <div className=\"flex items-start justify-between mb-10\">\n <div>\n <div className=\"flex items-center gap-3 mb-1\">\n <Braces className=\"w-5 h-5 text-accent\" strokeWidth={1.5} />\n <h1 className=\"text-lg font-medium text-text-primary\">Escalation Schema</h1>\n <button\n onClick={() => { window.location.hash = '#docs:dashboard.md:escalation-schema'; }}\n className=\"text-text-quaternary hover:text-accent transition-colors\"\n title=\"Open docs for this page\"\n >\n <BookOpen className=\"w-4 h-4\" strokeWidth={1.5} />\n </button>\n <span className=\"font-mono text-sm text-text-tertiary\">{role.role}</span>\n {role.current_schema_version != null && (\n <span className=\"text-[10px] font-mono text-text-quaternary\">\n v{role.current_schema_version} in use\n </span>\n )}\n </div>\n <button\n onClick={() => { window.location.hash = '#docs:hitl-guide.md:json-schema-form-authoring'; }}\n className=\"text-[11px] text-accent hover:underline pl-8\"\n >\n Form authoring reference — field types, widgets, and every x-lt-* keyword →\n </button>\n </div>\n\n <div className=\"flex items-center gap-2 shrink-0\">\n {savedOk && (\n <span className=\"flex items-center gap-1 text-xs text-status-success animate-page-enter\">\n <Check className=\"w-3 h-3\" /> Saved\n </span>\n )}\n {updateRole.error && (\n <span className=\"text-xs text-status-error max-w-[220px] truncate\">\n {(updateRole.error as Error).message}\n </span>\n )}\n <button\n onClick={handleSave}\n disabled={!dirty || jsonError || updateRole.isPending}\n className=\"px-3 py-1.5 text-xs rounded-md bg-accent text-text-inverse hover:bg-accent-hover transition-colors disabled:opacity-40 disabled:cursor-not-allowed\"\n >\n {updateRole.isPending ? 'Saving…' : 'Save Version'}\n </button>\n </div>\n </div>\n\n {/* ── Editor + version rail ── */}\n <div className=\"grid grid-cols-3 gap-16 items-start\">\n <div className=\"col-span-2 space-y-6\">\n <textarea\n value={text}\n onChange={(e) => handleEdit(e.target.value)}\n rows={28}\n spellCheck={false}\n className=\"input text-xs font-mono w-full resize-y leading-relaxed\"\n placeholder={PLACEHOLDER}\n />\n {jsonError && <p className=\"text-[10px] text-status-error -mt-4\">Invalid JSON</p>}\n\n <div>\n <label className=\"block text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-1.5\">\n Change Summary\n </label>\n <input\n type=\"text\"\n value={summary}\n onChange={(e) => setSummary(e.target.value)}\n placeholder=\"e.g., Added lotNumber field for shoe orders\"\n className=\"input text-sm w-full\"\n />\n <p className=\"text-[10px] text-text-quaternary mt-1.5\">\n Recorded on the version this save creates.\n </p>\n </div>\n </div>\n\n {/* Version history — view any snapshot, load one as the editing base */}\n <div>\n <div className=\"flex items-center gap-2 mb-3 pb-2 border-b border-surface-border\">\n <History className=\"w-4 h-4 text-text-quaternary\" strokeWidth={1.5} />\n <h2 className=\"section-h2\">Versions</h2>\n </div>\n <VersionRail role={role.role} onLoad={loadIntoEditor} />\n </div>\n </div>\n </div>\n );\n}\n\nfunction VersionRail({\n role,\n onLoad,\n}: {\n role: string;\n onLoad: (schema: Record<string, unknown> | null) => void;\n}) {\n const { data } = useRoleSchemaVersions(role);\n const versions = data?.versions ?? [];\n\n if (versions.length === 0) {\n return (\n <p className=\"text-[11px] text-text-tertiary leading-relaxed\">\n Versions appear here after the first save. Each schema change adds one;\n earlier versions stay viewable and loadable as an editing base.\n </p>\n );\n }\n\n return (\n <div className=\"divide-y divide-surface-border/40\">\n {versions.map((v) => (\n <VersionEntry key={v.version} role={role} summary={v} onLoad={onLoad} />\n ))}\n </div>\n );\n}\n\nfunction VersionEntry({\n role,\n summary,\n onLoad,\n}: {\n role: string;\n summary: RoleSchemaVersionSummary;\n onLoad: (schema: Record<string, unknown> | null) => void;\n}) {\n const [open, setOpen] = useState(false);\n // Snapshot fetch is lazy — only when the entry is expanded.\n const snapshot = useRoleSchema(role, summary.version, open);\n\n return (\n <div className=\"py-2\">\n <button onClick={() => setOpen((o) => !o)} className=\"w-full text-left group\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-xs font-mono text-text-secondary\">v{summary.version}</span>\n {summary.is_current && (\n <span className=\"text-[9px] font-bold uppercase tracking-wider text-accent\">current</span>\n )}\n <span className=\"flex-1\" />\n <span className=\"text-[10px] text-text-quaternary shrink-0\">\n {new Date(summary.created_at).toLocaleDateString()}\n </span>\n </div>\n {summary.change_summary && (\n <p className=\"mt-0.5 text-[10px] text-text-tertiary truncate\">{summary.change_summary}</p>\n )}\n </button>\n {open && (\n <div className=\"mt-2 space-y-2\">\n {snapshot.data ? (\n <>\n {snapshot.data.form_schema\n ? <JsonViewer data={snapshot.data.form_schema} defaultCollapsed />\n : <p className=\"text-[10px] text-text-quaternary\">This version carries no form schema.</p>}\n <button\n onClick={() => onLoad((snapshot.data!.form_schema ?? null) as Record<string, unknown> | null)}\n className=\"text-[10px] text-accent hover:underline\"\n >\n Load into editor\n </button>\n </>\n ) : (\n <p className=\"text-[10px] text-text-quaternary\">Loading…</p>\n )}\n </div>\n )}\n </div>\n );\n}\n"],"names":["PLACEHOLDER","safeParseObject","text","trimmed","parsed","EscalationSchemaPage","roleKey","useParams","data","isLoading","useRoleDetails","updateRole","useUpdateRole","role","r","setText","useState","summary","setSummary","dirty","setDirty","savedOk","setSavedOk","jsonError","setJsonError","seededFor","useRef","useEffect","handleEdit","value","handleSave","loadIntoEditor","schema","jsxs","jsx","Braces","BookOpen","Check","e","History","VersionRail","onLoad","useRoleSchemaVersions","versions","v","VersionEntry","open","setOpen","snapshot","useRoleSchema","o","Fragment","JsonViewer"],"mappings":"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"}
|
package/dashboard/dist/assets/{EscalationsOverview-DMpRvVql.js → EscalationsOverview-BqOZ1v8w.js}
RENAMED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as m,j as e}from"./vendor-query-B2UbickB.js";import{i as u}from"./index-
|
|
2
|
-
//# sourceMappingURL=EscalationsOverview-
|
|
1
|
+
import{a as m,j as e}from"./vendor-query-B2UbickB.js";import{i as u}from"./index-C9moIiIq.js";import{e as p}from"./useEventHooks-ZT6RV2Gj.js";import{P as b}from"./PageHeader-sGNTmSXX.js";import{S as n}from"./StatCard-DrdlUeQz.js";import{c as j}from"./vendor-react-CXumBFUA.js";import"./vendor-icons-BXhWQC7l.js";const v=[{label:"1h",value:"1h"},{label:"24h",value:"24h"},{label:"7d",value:"7d"},{label:"30d",value:"30d"}];function c({value:i,colorClass:r,onClick:o}){return i===0?e.jsx("span",{className:"text-text-tertiary",children:"0"}):e.jsx("button",{onClick:o,className:`${r} hover:underline tabular-nums font-medium`,children:i})}function $(){var d,x;p();const i=j(),[r,o]=m.useState("24h"),{data:s}=u(r),l=t=>{const h=new URLSearchParams(t).toString();i(`/escalations/available${h?`?${h}`:""}`)},a="pb-2 text-[10px] font-semibold uppercase tracking-widest text-text-tertiary";return e.jsxs("div",{children:[e.jsx(b,{title:"Escalations",docsHash:"#docs:dashboard.md:escalations-overview"}),e.jsx("div",{className:"flex items-center gap-1 mb-6",children:v.map(t=>e.jsx("button",{onClick:()=>o(t.value),className:`px-3 py-1 text-xs rounded-full transition-colors ${r===t.value?"bg-accent text-text-inverse":"text-text-tertiary hover:text-text-primary hover:bg-surface-hover"}`,children:t.label},t.value))}),e.jsxs("div",{className:"grid grid-cols-4 gap-4 mb-8",children:[e.jsx(n,{label:"Open",value:(s==null?void 0:s.pending)??"—",colorClass:"text-status-pending",onClick:()=>l()}),e.jsx(n,{label:"Claimed",value:(s==null?void 0:s.claimed)??"—",colorClass:"text-status-active",onClick:()=>l()}),e.jsx(n,{label:"Created",value:(s==null?void 0:s.created)??"—",onClick:()=>l()}),e.jsx(n,{label:"Resolved",value:(s==null?void 0:s.resolved)??"—",colorClass:"text-status-success",onClick:()=>l()})]}),(((d=s==null?void 0:s.by_role)==null?void 0:d.length)??0)>0&&e.jsx("div",{className:"mb-8",children:e.jsxs("table",{className:"w-full text-left",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b border-surface-border",children:[e.jsx("th",{className:a,children:"Role"}),e.jsx("th",{className:`${a} text-right w-24`,children:"Pending"}),e.jsx("th",{className:`${a} text-right w-24`,children:"Claimed"})]})}),e.jsx("tbody",{children:s.by_role.map(t=>e.jsxs("tr",{className:"border-b border-surface-border last:border-b-0",children:[e.jsx("td",{className:"py-3 text-sm font-mono text-text-primary",children:e.jsx("button",{onClick:()=>l({role:t.role}),className:"hover:text-accent hover:underline",children:t.role})}),e.jsx("td",{className:"py-3 text-sm text-right",children:e.jsx(c,{value:t.pending,colorClass:"text-status-pending",onClick:()=>l({role:t.role})})}),e.jsx("td",{className:"py-3 text-sm text-right",children:e.jsx(c,{value:t.claimed,colorClass:"text-status-active",onClick:()=>l({role:t.role})})})]},t.role))})]})}),(((x=s==null?void 0:s.by_type)==null?void 0:x.length)??0)>0&&e.jsx("div",{children:e.jsxs("table",{className:"w-full text-left",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b border-surface-border",children:[e.jsx("th",{className:a,children:"Type"}),e.jsx("th",{className:`${a} text-right w-24`,children:"Pending"}),e.jsx("th",{className:`${a} text-right w-24`,children:"Claimed"}),e.jsx("th",{className:`${a} text-right w-24`,children:"Resolved"})]})}),e.jsx("tbody",{children:s.by_type.map(t=>e.jsxs("tr",{className:"border-b border-surface-border last:border-b-0",children:[e.jsx("td",{className:"py-3 text-sm font-mono text-text-primary",children:e.jsx("button",{onClick:()=>l({type:t.type}),className:"hover:text-accent hover:underline",children:t.type})}),e.jsx("td",{className:"py-3 text-sm text-right",children:e.jsx(c,{value:t.pending,colorClass:"text-status-pending",onClick:()=>l({type:t.type})})}),e.jsx("td",{className:"py-3 text-sm text-right",children:e.jsx(c,{value:t.claimed,colorClass:"text-status-active",onClick:()=>l({type:t.type})})}),e.jsx("td",{className:"py-3 text-sm text-right",children:e.jsx(c,{value:t.resolved,colorClass:"text-status-success",onClick:()=>l({type:t.type})})})]},t.type))})]})}),s&&s.by_role.length===0&&s.by_type.length===0&&e.jsx("div",{className:"py-16 text-center",children:e.jsxs("p",{className:"text-sm text-text-tertiary",children:["No escalation activity in the last ",r]})})]})}export{$ as EscalationsOverview};
|
|
2
|
+
//# sourceMappingURL=EscalationsOverview-BqOZ1v8w.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EscalationsOverview-DMpRvVql.js","sources":["../../src/pages/operator/EscalationsOverview.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { useEscalationStats } from '../../api/escalations';\nimport { useEscalationStatsEvents } from '../../hooks/useEventHooks';\nimport { PageHeader } from '../../components/common/layout/PageHeader';\nimport { StatCard } from '../../components/common/data/StatCard';\n\n// ── Duration filter ──────────────────────────────────────────────────────────\n\nconst DURATIONS = [\n { label: '1h', value: '1h' },\n { label: '24h', value: '24h' },\n { label: '7d', value: '7d' },\n { label: '30d', value: '30d' },\n] as const;\n\ntype DurationValue = (typeof DURATIONS)[number]['value'];\n\n// ── Clickable stat cell ──────────────────────────────────────────────────────\n\nfunction StatCell({\n value,\n colorClass,\n onClick,\n}: {\n value: number;\n colorClass: string;\n onClick: () => void;\n}) {\n if (value === 0) {\n return <span className=\"text-text-tertiary\">0</span>;\n }\n return (\n <button\n onClick={onClick}\n className={`${colorClass} hover:underline tabular-nums font-medium`}\n >\n {value}\n </button>\n );\n}\n\n// ── Page ─────────────────────────────────────────────────────────────────────\n\nexport function EscalationsOverview() {\n useEscalationStatsEvents();\n const navigate = useNavigate();\n const [duration, setDuration] = useState<DurationValue>('24h');\n\n const { data: stats } = useEscalationStats(duration);\n\n const goToList = (params?: Record<string, string>) => {\n const qs = new URLSearchParams(params).toString();\n navigate(`/escalations/available${qs ? `?${qs}` : ''}`);\n };\n\n const thCls = 'pb-2 text-[10px] font-semibold uppercase tracking-widest text-text-tertiary';\n\n return (\n <div>\n <PageHeader title=\"Escalations\" docsHash=\"#docs:dashboard.md:escalations-overview\" />\n\n {/* Duration tabs */}\n <div className=\"flex items-center gap-1 mb-6\">\n {DURATIONS.map((d) => (\n <button\n key={d.value}\n onClick={() => setDuration(d.value)}\n className={`px-3 py-1 text-xs rounded-full transition-colors ${\n duration === d.value\n ? 'bg-accent text-text-inverse'\n : 'text-text-tertiary hover:text-text-primary hover:bg-surface-hover'\n }`}\n >\n {d.label}\n </button>\n ))}\n </div>\n\n {/* Summary cards */}\n <div className=\"grid grid-cols-4 gap-4 mb-8\">\n <StatCard label=\"Open\" value={stats?.pending ?? '—'} colorClass=\"text-status-pending\" onClick={() => goToList()} />\n <StatCard label=\"Claimed\" value={stats?.claimed ?? '—'} colorClass=\"text-status-active\" onClick={() => goToList()} />\n <StatCard label=\"Created\" value={stats?.created ?? '—'} onClick={() => goToList()} />\n <StatCard label=\"Resolved\" value={stats?.resolved ?? '—'} colorClass=\"text-status-success\" onClick={() => goToList()} />\n </div>\n\n {/* By-role table */}\n {(stats?.by_role?.length ?? 0) > 0 && (\n <div className=\"mb-8\">\n <table className=\"w-full text-left\">\n <thead>\n <tr className=\"border-b border-surface-border\">\n <th className={thCls}>Role</th>\n <th className={`${thCls} text-right w-24`}>Pending</th>\n <th className={`${thCls} text-right w-24`}>Claimed</th>\n </tr>\n </thead>\n <tbody>\n {stats!.by_role.map((row) => (\n <tr key={row.role} className=\"border-b border-surface-border last:border-b-0\">\n <td className=\"py-3 text-sm font-mono text-text-primary\">\n <button\n onClick={() => goToList({ role: row.role })}\n className=\"hover:text-accent hover:underline\"\n >\n {row.role}\n </button>\n </td>\n <td className=\"py-3 text-sm text-right\">\n <StatCell\n value={row.pending}\n colorClass=\"text-status-pending\"\n onClick={() => goToList({ role: row.role })}\n />\n </td>\n <td className=\"py-3 text-sm text-right\">\n <StatCell\n value={row.claimed}\n colorClass=\"text-status-active\"\n onClick={() => goToList({ role: row.role })}\n />\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n\n {/* By-type table */}\n {(stats?.by_type?.length ?? 0) > 0 && (\n <div>\n <table className=\"w-full text-left\">\n <thead>\n <tr className=\"border-b border-surface-border\">\n <th className={thCls}>Type</th>\n <th className={`${thCls} text-right w-24`}>Pending</th>\n <th className={`${thCls} text-right w-24`}>Claimed</th>\n <th className={`${thCls} text-right w-24`}>Resolved</th>\n </tr>\n </thead>\n <tbody>\n {stats!.by_type.map((row) => (\n <tr key={row.type} className=\"border-b border-surface-border last:border-b-0\">\n <td className=\"py-3 text-sm font-mono text-text-primary\">\n <button\n onClick={() => goToList({ type: row.type })}\n className=\"hover:text-accent hover:underline\"\n >\n {row.type}\n </button>\n </td>\n <td className=\"py-3 text-sm text-right\">\n <StatCell\n value={row.pending}\n colorClass=\"text-status-pending\"\n onClick={() => goToList({ type: row.type })}\n />\n </td>\n <td className=\"py-3 text-sm text-right\">\n <StatCell\n value={row.claimed}\n colorClass=\"text-status-active\"\n onClick={() => goToList({ type: row.type })}\n />\n </td>\n <td className=\"py-3 text-sm text-right\">\n <StatCell\n value={row.resolved}\n colorClass=\"text-status-success\"\n onClick={() => goToList({ type: row.type })}\n />\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n\n {/* Empty state */}\n {stats && stats.by_role.length === 0 && stats.by_type.length === 0 && (\n <div className=\"py-16 text-center\">\n <p className=\"text-sm text-text-tertiary\">\n No escalation activity in the last {duration}\n </p>\n </div>\n )}\n </div>\n );\n}\n"],"names":["DURATIONS","StatCell","value","colorClass","onClick","jsx","EscalationsOverview","useEscalationStatsEvents","navigate","useNavigate","duration","setDuration","useState","stats","useEscalationStats","goToList","params","qs","thCls","PageHeader","d","jsxs","StatCard","_a","row","_b"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"EscalationsOverview-BqOZ1v8w.js","sources":["../../src/pages/operator/EscalationsOverview.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { useEscalationStats } from '../../api/escalations';\nimport { useEscalationStatsEvents } from '../../hooks/useEventHooks';\nimport { PageHeader } from '../../components/common/layout/PageHeader';\nimport { StatCard } from '../../components/common/data/StatCard';\n\n// ── Duration filter ──────────────────────────────────────────────────────────\n\nconst DURATIONS = [\n { label: '1h', value: '1h' },\n { label: '24h', value: '24h' },\n { label: '7d', value: '7d' },\n { label: '30d', value: '30d' },\n] as const;\n\ntype DurationValue = (typeof DURATIONS)[number]['value'];\n\n// ── Clickable stat cell ──────────────────────────────────────────────────────\n\nfunction StatCell({\n value,\n colorClass,\n onClick,\n}: {\n value: number;\n colorClass: string;\n onClick: () => void;\n}) {\n if (value === 0) {\n return <span className=\"text-text-tertiary\">0</span>;\n }\n return (\n <button\n onClick={onClick}\n className={`${colorClass} hover:underline tabular-nums font-medium`}\n >\n {value}\n </button>\n );\n}\n\n// ── Page ─────────────────────────────────────────────────────────────────────\n\nexport function EscalationsOverview() {\n useEscalationStatsEvents();\n const navigate = useNavigate();\n const [duration, setDuration] = useState<DurationValue>('24h');\n\n const { data: stats } = useEscalationStats(duration);\n\n const goToList = (params?: Record<string, string>) => {\n const qs = new URLSearchParams(params).toString();\n navigate(`/escalations/available${qs ? `?${qs}` : ''}`);\n };\n\n const thCls = 'pb-2 text-[10px] font-semibold uppercase tracking-widest text-text-tertiary';\n\n return (\n <div>\n <PageHeader title=\"Escalations\" docsHash=\"#docs:dashboard.md:escalations-overview\" />\n\n {/* Duration tabs */}\n <div className=\"flex items-center gap-1 mb-6\">\n {DURATIONS.map((d) => (\n <button\n key={d.value}\n onClick={() => setDuration(d.value)}\n className={`px-3 py-1 text-xs rounded-full transition-colors ${\n duration === d.value\n ? 'bg-accent text-text-inverse'\n : 'text-text-tertiary hover:text-text-primary hover:bg-surface-hover'\n }`}\n >\n {d.label}\n </button>\n ))}\n </div>\n\n {/* Summary cards */}\n <div className=\"grid grid-cols-4 gap-4 mb-8\">\n <StatCard label=\"Open\" value={stats?.pending ?? '—'} colorClass=\"text-status-pending\" onClick={() => goToList()} />\n <StatCard label=\"Claimed\" value={stats?.claimed ?? '—'} colorClass=\"text-status-active\" onClick={() => goToList()} />\n <StatCard label=\"Created\" value={stats?.created ?? '—'} onClick={() => goToList()} />\n <StatCard label=\"Resolved\" value={stats?.resolved ?? '—'} colorClass=\"text-status-success\" onClick={() => goToList()} />\n </div>\n\n {/* By-role table */}\n {(stats?.by_role?.length ?? 0) > 0 && (\n <div className=\"mb-8\">\n <table className=\"w-full text-left\">\n <thead>\n <tr className=\"border-b border-surface-border\">\n <th className={thCls}>Role</th>\n <th className={`${thCls} text-right w-24`}>Pending</th>\n <th className={`${thCls} text-right w-24`}>Claimed</th>\n </tr>\n </thead>\n <tbody>\n {stats!.by_role.map((row) => (\n <tr key={row.role} className=\"border-b border-surface-border last:border-b-0\">\n <td className=\"py-3 text-sm font-mono text-text-primary\">\n <button\n onClick={() => goToList({ role: row.role })}\n className=\"hover:text-accent hover:underline\"\n >\n {row.role}\n </button>\n </td>\n <td className=\"py-3 text-sm text-right\">\n <StatCell\n value={row.pending}\n colorClass=\"text-status-pending\"\n onClick={() => goToList({ role: row.role })}\n />\n </td>\n <td className=\"py-3 text-sm text-right\">\n <StatCell\n value={row.claimed}\n colorClass=\"text-status-active\"\n onClick={() => goToList({ role: row.role })}\n />\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n\n {/* By-type table */}\n {(stats?.by_type?.length ?? 0) > 0 && (\n <div>\n <table className=\"w-full text-left\">\n <thead>\n <tr className=\"border-b border-surface-border\">\n <th className={thCls}>Type</th>\n <th className={`${thCls} text-right w-24`}>Pending</th>\n <th className={`${thCls} text-right w-24`}>Claimed</th>\n <th className={`${thCls} text-right w-24`}>Resolved</th>\n </tr>\n </thead>\n <tbody>\n {stats!.by_type.map((row) => (\n <tr key={row.type} className=\"border-b border-surface-border last:border-b-0\">\n <td className=\"py-3 text-sm font-mono text-text-primary\">\n <button\n onClick={() => goToList({ type: row.type })}\n className=\"hover:text-accent hover:underline\"\n >\n {row.type}\n </button>\n </td>\n <td className=\"py-3 text-sm text-right\">\n <StatCell\n value={row.pending}\n colorClass=\"text-status-pending\"\n onClick={() => goToList({ type: row.type })}\n />\n </td>\n <td className=\"py-3 text-sm text-right\">\n <StatCell\n value={row.claimed}\n colorClass=\"text-status-active\"\n onClick={() => goToList({ type: row.type })}\n />\n </td>\n <td className=\"py-3 text-sm text-right\">\n <StatCell\n value={row.resolved}\n colorClass=\"text-status-success\"\n onClick={() => goToList({ type: row.type })}\n />\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n\n {/* Empty state */}\n {stats && stats.by_role.length === 0 && stats.by_type.length === 0 && (\n <div className=\"py-16 text-center\">\n <p className=\"text-sm text-text-tertiary\">\n No escalation activity in the last {duration}\n </p>\n </div>\n )}\n </div>\n );\n}\n"],"names":["DURATIONS","StatCell","value","colorClass","onClick","jsx","EscalationsOverview","useEscalationStatsEvents","navigate","useNavigate","duration","setDuration","useState","stats","useEscalationStats","goToList","params","qs","thCls","PageHeader","d","jsxs","StatCard","_a","row","_b"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{a as u,j as t}from"./vendor-query-B2UbickB.js";import{F as O,b as y}from"./FilterBar-DDIn8TOs.js";import{f as D,C as P}from"./index-C9moIiIq.js";import{E as A}from"./SwimlaneTimeline-4NrDJNYc.js";const S="lt-collapsed-sections";function L(s){try{const r=localStorage.getItem(`${S}:${s}`);return r?new Set(JSON.parse(r)):new Set}catch{return new Set}}function h(s,r){localStorage.setItem(`${S}:${s}`,JSON.stringify([...r]))}function q(s){const[r,d]=u.useState(()=>L(s)),f=u.useCallback(i=>r.has(i),[r]),x=u.useCallback(i=>{d(c=>{const a=new Set(c);return a.has(i)?a.delete(i):a.add(i),h(s,a),a})},[s]),m=u.useCallback(i=>{d(c=>{if(c.has(i))return c;const a=new Set(c);return a.add(i),h(s,a),a})},[s]),p=u.useCallback(i=>{d(c=>{if(!c.has(i))return c;const a=new Set(c);return a.delete(i),h(s,a),a})},[s]);return{isCollapsed:f,toggle:x,collapse:m,expand:p}}const R=new Set(["activity_task_scheduled","timer_started","child_workflow_execution_started","signal_wait_started"]),Y=new Set(["activity_task_completed","activity_task_failed","timer_fired","child_workflow_execution_completed","child_workflow_execution_failed","workflow_execution_signaled"]);function I(s){const r=new Set;for(const d of s)Y.has(d.event_type)&&d.attributes.timeline_key&&r.add(d.attributes.timeline_key);return r}function z({events:s,childTasks:r,jid:d,appId:f}){const[x,m]=u.useState(""),[p,i]=u.useState(""),[c,a]=u.useState("asc"),[b,_]=u.useState(new Set),j=[...new Set(s.map(e=>e.category))].sort(),v=[...new Set(s.map(e=>e.event_type))].sort(),k=I(s),N=e=>{if(e.duration_ms!==null||!R.has(e.event_type))return!1;const n=e.attributes.timeline_key;return!(n&&k.has(n))};let l=s;x&&(l=l.filter(e=>e.category===x)),p&&(l=l.filter(e=>e.event_type===p)),l=[...l].sort((e,n)=>c==="asc"?e.event_id-n.event_id:n.event_id-e.event_id);const C=e=>{switch(e){case"activity":return"bg-status-active";case"signal":return"bg-status-success";case"timer":return"bg-status-warning";case"child_workflow":return"bg-accent";default:return"bg-text-tertiary"}},E=e=>{const n=e.event_type;if(e.attributes.activity_type)return`${n} — ${e.attributes.activity_type}`;if(e.attributes.signal_name)return`${n} — ${e.attributes.signal_name}`;if(e.attributes.child_workflow_id){const o=e.attributes.child_workflow_id,F=o.length>24?`${o.slice(0,24)}...`:o;return`${n} — ${F}`}return n},$=e=>{if(!(r!=null&&r.length))return;const n=e.attributes.activity_type;if(n)return r.find(o=>o.workflow_type===n)},g=e=>{_(n=>{const o=new Set(n);return o.has(e)?o.delete(e):o.add(e),o})},w=l.length>0&&l.every(e=>b.has(e.event_id)),T=()=>{_(w?new Set:new Set(l.map(e=>e.event_id)))};return t.jsxs("div",{children:[t.jsxs("div",{className:"px-6 py-4 border-b border-surface-border flex items-center justify-between flex-wrap gap-3",children:[t.jsxs("div",{className:"flex items-center gap-4",children:[t.jsxs("p",{className:"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary",children:["Events (",l.length,")"]}),l.length>0&&t.jsx("button",{onClick:T,className:"text-[10px] text-accent hover:underline",children:w?"Collapse all":"Expand all"})]}),t.jsxs(O,{children:[t.jsx(y,{label:"Category",value:x,onChange:m,options:j.map(e=>({value:e,label:e}))}),t.jsx(y,{label:"Type",value:p,onChange:i,options:v.map(e=>({value:e,label:e}))}),t.jsx("button",{onClick:()=>a(e=>e==="asc"?"desc":"asc"),className:"btn-ghost text-xs",children:c==="asc"?"Oldest first":"Newest first"})]})]}),t.jsx("div",{children:l.length===0?t.jsx("div",{className:"px-6 py-8 text-center",children:t.jsx("p",{className:"text-sm text-text-tertiary",children:"No events match the current filters"})}):l.map(e=>{const n=b.has(e.event_id),o=N(e);return t.jsxs("div",{className:"border-b border-surface-border last:border-b-0",children:[t.jsxs("div",{className:"px-6 py-3 flex items-center gap-4 cursor-pointer hover:bg-surface-hover transition-colors duration-200",onClick:()=>g(e.event_id),children:[t.jsx("span",{className:`text-[10px] text-text-tertiary transition-transform duration-300 ${n?"rotate-90":""}`,children:"▶"}),t.jsx("span",{className:"text-xs font-mono text-text-tertiary w-8 shrink-0",children:e.event_id}),t.jsx("span",{className:`w-2 h-2 rounded-full dot-ring shrink-0 ${C(e.category)}`}),t.jsx("span",{className:"text-sm text-text-primary flex-1 truncate",children:E(e)}),t.jsx("span",{className:"text-xs font-mono text-text-tertiary shrink-0",children:o?t.jsxs("span",{className:"inline-flex items-center gap-1 text-status-warning",children:[t.jsx("span",{className:"w-1.5 h-1.5 rounded-full dot-ring bg-status-warning animate-pulse"}),"Pending"]}):e.duration_ms!==null?D(e.duration_ms):"--"}),t.jsx("time",{className:"text-[10px] font-mono text-text-tertiary shrink-0",children:new Date(e.event_time).toLocaleTimeString()})]}),t.jsx(P,{open:n&&!!e.attributes,children:t.jsx("div",{className:"px-6 pb-4 pl-16",children:t.jsx(A,{event:e,childTask:$(e),pending:o,jid:d,appId:f,onClose:()=>g(e.event_id)})})})]},e.event_id)})})]})}export{z as E,q as u};
|
|
2
|
+
//# sourceMappingURL=EventTable-CyfHfOWj.js.map
|