@hotmeshio/long-tail 0.20.0 → 0.21.1
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/README.md +4 -4
- package/build/api/escalations/accumulate.d.ts +104 -0
- package/build/api/escalations/accumulate.js +541 -0
- package/build/api/escalations/index.d.ts +1 -0
- package/build/api/escalations/index.js +11 -1
- package/build/api/roles.d.ts +4 -5
- package/build/api/roles.js +53 -4
- package/build/api/scan-codes/context.d.ts +14 -1
- package/build/api/scan-codes/context.js +30 -2
- package/build/api/scan-codes/execute.js +2 -0
- package/build/api/scan-codes/identity.js +1 -0
- package/build/api/scan-codes/verbs.d.ts +21 -0
- package/build/api/scan-codes/verbs.js +122 -3
- package/build/index.d.ts +2 -1
- package/build/index.js +63 -2
- package/build/lib/db/schemas/036_role_portals.sql +12 -0
- package/build/routes/escalations/accumulate.d.ts +7 -0
- package/build/routes/escalations/accumulate.js +158 -0
- package/build/routes/escalations/index.js +5 -0
- package/build/sdk/index.d.ts +28 -0
- package/build/sdk/index.js +9 -0
- package/build/services/escalation/accumulate.d.ts +81 -0
- package/build/services/escalation/accumulate.js +154 -0
- package/build/services/escalation/index.d.ts +1 -0
- package/build/services/escalation/index.js +1 -0
- package/build/services/mcp/playwright-server/schemas.d.ts +2 -2
- package/build/services/orchestrator/condition.d.ts +40 -3
- package/build/services/orchestrator/condition.js +42 -2
- package/build/services/role/index.js +1 -0
- package/build/services/role/seed.js +6 -1
- package/build/services/role/sql.d.ts +6 -3
- package/build/services/role/sql.js +7 -2
- package/build/services/role/types.d.ts +38 -10
- package/build/services/role/types.js +10 -1
- package/build/services/scan-code/index.d.ts +1 -1
- package/build/services/scan-code/index.js +3 -1
- package/build/services/scan-code/parse.d.ts +17 -3
- package/build/services/scan-code/parse.js +37 -4
- package/build/services/scan-code/validate.js +35 -0
- package/build/shared/form-validation/display-only-widgets.d.ts +16 -0
- package/build/shared/form-validation/display-only-widgets.js +25 -0
- package/build/shared/form-validation/index.d.ts +2 -0
- package/build/shared/form-validation/index.js +2 -0
- package/build/shared/form-validation/x-lt-bind.d.ts +2 -14
- package/build/shared/form-validation/x-lt-bind.js +12 -8
- package/build/shared/form-validation/x-lt-invoke.d.ts +38 -0
- package/build/shared/form-validation/x-lt-invoke.js +103 -0
- package/build/system/mcp-servers/admin/escalations.js +44 -0
- package/build/system/mcp-servers/admin/schemas.d.ts +195 -13
- package/build/system/mcp-servers/admin/schemas.js +40 -3
- package/build/system/mcp-servers/admin/users.js +1 -0
- package/build/system/mcp-servers/docs.js +4 -0
- package/build/system/mcp-servers/human-queue-schemas.d.ts +85 -0
- package/build/system/mcp-servers/human-queue-schemas.js +19 -1
- package/build/system/mcp-servers/human-queue.d.ts +2 -0
- package/build/system/mcp-servers/human-queue.js +77 -0
- package/build/system/seed/tool-manifests-admin.d.ts +1108 -100
- package/build/system/seed/tool-manifests-admin.js +4 -1
- package/build/system/seed/tool-manifests-escalation.d.ts +174 -0
- package/build/system/seed/tool-manifests-escalation.js +56 -0
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/types/escalation.d.ts +52 -0
- package/build/types/escalation.js +29 -1
- package/build/types/index.d.ts +4 -4
- package/build/types/index.js +4 -1
- package/build/types/scan-code.d.ts +55 -1
- package/build/types/scan-code.js +29 -2
- package/build/types/startup.d.ts +20 -0
- package/dashboard/dist/assets/{AdminDashboard-DplvDBti.js → AdminDashboard-Covdam48.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-DplvDBti.js.map → AdminDashboard-Covdam48.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-D8Bf6YxO.js → AgentConfigPage-CE1k6J5r.js} +6 -6
- package/dashboard/dist/assets/{AgentConfigPage-D8Bf6YxO.js.map → AgentConfigPage-CE1k6J5r.js.map} +1 -1
- package/dashboard/dist/assets/{AgentDetailPage-BN8g0Y2G.js → AgentDetailPage-CWJZIZP1.js} +3 -3
- package/dashboard/dist/assets/{AgentDetailPage-BN8g0Y2G.js.map → AgentDetailPage-CWJZIZP1.js.map} +1 -1
- package/dashboard/dist/assets/AgentsPage---Dg5ufF.js +2 -0
- package/dashboard/dist/assets/{AgentsPage-7JJBHku8.js.map → AgentsPage---Dg5ufF.js.map} +1 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-CpbC8oTN.js +2 -0
- package/dashboard/dist/assets/AvailableEscalationsPage-CpbC8oTN.js.map +1 -0
- package/dashboard/dist/assets/{BotPicker-CGCnIz8I.js → BotPicker-D3drO3-T.js} +2 -2
- package/dashboard/dist/assets/{BotPicker-CGCnIz8I.js.map → BotPicker-D3drO3-T.js.map} +1 -1
- package/dashboard/dist/assets/BulkAssignModal-BOAWsViq.js +2 -0
- package/dashboard/dist/assets/{BulkAssignModal-NJBcoj-f.js.map → BulkAssignModal-BOAWsViq.js.map} +1 -1
- package/dashboard/dist/assets/CapabilitiesPage-RGgD3YZO.js +2 -0
- package/dashboard/dist/assets/{CapabilitiesPage-F8dpNn9B.js.map → CapabilitiesPage-RGgD3YZO.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-BZW6VpCU.js → CollapsibleSection-DNkZn87n.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-BZW6VpCU.js.map → CollapsibleSection-DNkZn87n.js.map} +1 -1
- package/dashboard/dist/assets/{ConfirmDeleteModal-64adXLdq.js → ConfirmDeleteModal-BqzOwhPr.js} +2 -2
- package/dashboard/dist/assets/{ConfirmDeleteModal-64adXLdq.js.map → ConfirmDeleteModal-BqzOwhPr.js.map} +1 -1
- package/dashboard/dist/assets/{CountdownTimer-BxDub9d2.js → CountdownTimer-BaexQMK6.js} +2 -2
- package/dashboard/dist/assets/{CountdownTimer-BxDub9d2.js.map → CountdownTimer-BaexQMK6.js.map} +1 -1
- package/dashboard/dist/assets/{CredentialsPage-CnLzopLL.js → CredentialsPage-D7abp0aS.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-CnLzopLL.js.map → CredentialsPage-D7abp0aS.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-CAD5UYDT.js → CronLabel-DZiWmTwJ.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-CAD5UYDT.js.map → CronLabel-DZiWmTwJ.js.map} +1 -1
- package/dashboard/dist/assets/DataTable-spX1dFyb.js +2 -0
- package/dashboard/dist/assets/DataTable-spX1dFyb.js.map +1 -0
- package/dashboard/dist/assets/{DropZone-XlcY8hEH.js → DropZone-f1o-GLM8.js} +2 -2
- package/dashboard/dist/assets/{DropZone-XlcY8hEH.js.map → DropZone-f1o-GLM8.js.map} +1 -1
- package/dashboard/dist/assets/{ElapsedCell-CwO4ufd0.js → ElapsedCell-BdGO_w4v.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-CwO4ufd0.js.map → ElapsedCell-BdGO_w4v.js.map} +1 -1
- package/dashboard/dist/assets/EntityTimelinePanel-DIDcF5Yu.js +2 -0
- package/dashboard/dist/assets/{EntityTimelinePanel-CkF-oW-m.js.map → EntityTimelinePanel-DIDcF5Yu.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationListSchemaPage-h9JO_q5f.js → EscalationListSchemaPage-C28rn9XC.js} +3 -3
- package/dashboard/dist/assets/{EscalationListSchemaPage-h9JO_q5f.js.map → EscalationListSchemaPage-C28rn9XC.js.map} +1 -1
- package/dashboard/dist/assets/EscalationListView-CkBnkpDJ.js +2 -0
- package/dashboard/dist/assets/EscalationListView-CkBnkpDJ.js.map +1 -0
- package/dashboard/dist/assets/{EscalationSchemaPage-mJFL5_Se.js → EscalationSchemaPage-W5r0A1kj.js} +3 -3
- package/dashboard/dist/assets/{EscalationSchemaPage-mJFL5_Se.js.map → EscalationSchemaPage-W5r0A1kj.js.map} +1 -1
- package/dashboard/dist/assets/EscalationTimeline-DKyTz6sM.js +2 -0
- package/dashboard/dist/assets/EscalationTimeline-DKyTz6sM.js.map +1 -0
- package/dashboard/dist/assets/EscalationTitleSelect-CzKfavri.js +2 -0
- package/dashboard/dist/assets/EscalationTitleSelect-CzKfavri.js.map +1 -0
- package/dashboard/dist/assets/{EscalationsOverview-DlXUFqWJ.js → EscalationsOverview-Tdu3Yx2c.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-DlXUFqWJ.js.map → EscalationsOverview-Tdu3Yx2c.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-Ike2xchn.js → EventTable-DiIxOJwO.js} +2 -2
- package/dashboard/dist/assets/{EventTable-Ike2xchn.js.map → EventTable-DiIxOJwO.js.map} +1 -1
- package/dashboard/dist/assets/{FilterBar-DMOR-O1c.js → FilterBar-CvMBCVIo.js} +2 -2
- package/dashboard/dist/assets/{FilterBar-DMOR-O1c.js.map → FilterBar-CvMBCVIo.js.map} +1 -1
- package/dashboard/dist/assets/GraphInvokePage-DO-yyhi6.js +2 -0
- package/dashboard/dist/assets/{GraphInvokePage-CKtvWowP.js.map → GraphInvokePage-DO-yyhi6.js.map} +1 -1
- package/dashboard/dist/assets/HomePage-DSS3eHR2.js +2 -0
- package/dashboard/dist/assets/{HomePage-BQ3Q791Q.js.map → HomePage-DSS3eHR2.js.map} +1 -1
- package/dashboard/dist/assets/ListToolbar-C3-Tqqub.js +2 -0
- package/dashboard/dist/assets/{ListToolbar-DdJzj472.js.map → ListToolbar-C3-Tqqub.js.map} +1 -1
- package/dashboard/dist/assets/{McpOverview-BbtrduWn.js → McpOverview-DEJmsdVi.js} +2 -2
- package/dashboard/dist/assets/{McpOverview-BbtrduWn.js.map → McpOverview-DEJmsdVi.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryDetailPage-C1L4T-Wt.js → McpQueryDetailPage-DYJr16l7.js} +2 -2
- package/dashboard/dist/assets/{McpQueryDetailPage-C1L4T-Wt.js.map → McpQueryDetailPage-DYJr16l7.js.map} +1 -1
- package/dashboard/dist/assets/McpQueryPage-BBcG_UuU.js +2 -0
- package/dashboard/dist/assets/{McpQueryPage-CfJy7HZ7.js.map → McpQueryPage-BBcG_UuU.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunDetailPage-CA9yv7he.js → McpRunDetailPage-C6xw0kBg.js} +2 -2
- package/dashboard/dist/assets/{McpRunDetailPage-CA9yv7he.js.map → McpRunDetailPage-C6xw0kBg.js.map} +1 -1
- package/dashboard/dist/assets/McpRunsPage-CRQqrF4Q.js +2 -0
- package/dashboard/dist/assets/{McpRunsPage-D7QXjW9z.js.map → McpRunsPage-CRQqrF4Q.js.map} +1 -1
- package/dashboard/dist/assets/{NamespacePill-Bb3revqD.js → NamespacePill-DADRJOUl.js} +2 -2
- package/dashboard/dist/assets/{NamespacePill-Bb3revqD.js.map → NamespacePill-DADRJOUl.js.map} +1 -1
- package/dashboard/dist/assets/OperationsPage-Dlfwzf-0.js +3 -0
- package/dashboard/dist/assets/OperationsPage-Dlfwzf-0.js.map +1 -0
- package/dashboard/dist/assets/OperatorDashboard-DoiDGZ9R.js +2 -0
- package/dashboard/dist/assets/{OperatorDashboard-sXNDh1Ph.js.map → OperatorDashboard-DoiDGZ9R.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeader-Di5Sz3an.js → PageHeader-Csq434-v.js} +2 -2
- package/dashboard/dist/assets/{PageHeader-Di5Sz3an.js.map → PageHeader-Csq434-v.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeaderWithStats-DutKJ-h2.js → PageHeaderWithStats-CSnk1p5A.js} +2 -2
- package/dashboard/dist/assets/{PageHeaderWithStats-DutKJ-h2.js.map → PageHeaderWithStats-CSnk1p5A.js.map} +1 -1
- package/dashboard/dist/assets/{PersonaDetailPage-NeHD-Gra.js → PersonaDetailPage-BzbA4Prr.js} +2 -2
- package/dashboard/dist/assets/{PersonaDetailPage-NeHD-Gra.js.map → PersonaDetailPage-BzbA4Prr.js.map} +1 -1
- package/dashboard/dist/assets/{PersonasPage-DavKXRWX.js → PersonasPage-B36yn4hU.js} +2 -2
- package/dashboard/dist/assets/{PersonasPage-DavKXRWX.js.map → PersonasPage-B36yn4hU.js.map} +1 -1
- package/dashboard/dist/assets/PortalPage-BkD4YfDf.js +2 -0
- package/dashboard/dist/assets/PortalPage-BkD4YfDf.js.map +1 -0
- package/dashboard/dist/assets/{ProcessDetailPage-DkdKJGe6.js → ProcessDetailPage-BT0eiBWY.js} +2 -2
- package/dashboard/dist/assets/{ProcessDetailPage-DkdKJGe6.js.map → ProcessDetailPage-BT0eiBWY.js.map} +1 -1
- package/dashboard/dist/assets/ProcessesListPage-BEqeeNae.js +2 -0
- package/dashboard/dist/assets/{ProcessesListPage-CjwVKe32.js.map → ProcessesListPage-BEqeeNae.js.map} +1 -1
- package/dashboard/dist/assets/ResolverForm-BwgjIX97.js +7 -0
- package/dashboard/dist/assets/ResolverForm-BwgjIX97.js.map +1 -0
- package/dashboard/dist/assets/RoleDetailPage-BFuLNJXa.js +8 -0
- package/dashboard/dist/assets/RoleDetailPage-BFuLNJXa.js.map +1 -0
- package/dashboard/dist/assets/{RolePill-DhnVPK4q.js → RolePill-BafrASDX.js} +2 -2
- package/dashboard/dist/assets/{RolePill-DhnVPK4q.js.map → RolePill-BafrASDX.js.map} +1 -1
- package/dashboard/dist/assets/{RolesPage-OM9KM8Pg.js → RolesPage-80quJU5-.js} +2 -2
- package/dashboard/dist/assets/{RolesPage-OM9KM8Pg.js.map → RolesPage-80quJU5-.js.map} +1 -1
- package/dashboard/dist/assets/RunAsSelector-BoePhWVD.js +2 -0
- package/dashboard/dist/assets/{RunAsSelector-fFMt1bGe.js.map → RunAsSelector-BoePhWVD.js.map} +1 -1
- package/dashboard/dist/assets/{ScanCodesPage-AujH-pPQ.js → ScanCodesPage-Cu1bKEix.js} +2 -2
- package/dashboard/dist/assets/{ScanCodesPage-AujH-pPQ.js.map → ScanCodesPage-Cu1bKEix.js.map} +1 -1
- package/dashboard/dist/assets/ScanSchemeDetailPage-D9AbS6UY.js +2 -0
- package/dashboard/dist/assets/ScanSchemeDetailPage-D9AbS6UY.js.map +1 -0
- package/dashboard/dist/assets/ScanStationPage-gcZGefvT.js +2 -0
- package/dashboard/dist/assets/{ScanStationPage-C1_ppDoZ.js.map → ScanStationPage-gcZGefvT.js.map} +1 -1
- package/dashboard/dist/assets/{ScopeBadge-CXUg0FHo.js → ScopeBadge-b6MIBiYD.js} +2 -2
- package/dashboard/dist/assets/{ScopeBadge-CXUg0FHo.js.map → ScopeBadge-b6MIBiYD.js.map} +1 -1
- package/dashboard/dist/assets/{StickyPagination-B91Pk9xh.js → StickyPagination-9ITrei_d.js} +2 -2
- package/dashboard/dist/assets/{StickyPagination-B91Pk9xh.js.map → StickyPagination-9ITrei_d.js.map} +1 -1
- package/dashboard/dist/assets/{StreamMessageDetail-C7SPqaJt.js → StreamMessageDetail-BkYvEHFY.js} +2 -2
- package/dashboard/dist/assets/{StreamMessageDetail-C7SPqaJt.js.map → StreamMessageDetail-BkYvEHFY.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-BcHR8ylf.js → SwimlaneTimeline-B1rotFix.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-BcHR8ylf.js.map → SwimlaneTimeline-B1rotFix.js.map} +1 -1
- package/dashboard/dist/assets/{TagInput-BZ8vb2oW.js → TagInput-ZrIIrEUP.js} +2 -2
- package/dashboard/dist/assets/{TagInput-BZ8vb2oW.js.map → TagInput-ZrIIrEUP.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-Bqj0I_I0.js → TaskDetailPage-zhn_U_eC.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-Bqj0I_I0.js.map → TaskDetailPage-zhn_U_eC.js.map} +1 -1
- package/dashboard/dist/assets/{TaskQueuePill-Bxir8WRl.js → TaskQueuePill-DkQ1uc6y.js} +2 -2
- package/dashboard/dist/assets/{TaskQueuePill-Bxir8WRl.js.map → TaskQueuePill-DkQ1uc6y.js.map} +1 -1
- package/dashboard/dist/assets/TasksListPage-CNbNeagx.js +2 -0
- package/dashboard/dist/assets/{TasksListPage-BB1f79lL.js.map → TasksListPage-CNbNeagx.js.map} +1 -1
- package/dashboard/dist/assets/{TimeAgo-BFnODmNe.js → TimeAgo-0YVMBwls.js} +2 -2
- package/dashboard/dist/assets/{TimeAgo-BFnODmNe.js.map → TimeAgo-0YVMBwls.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-BXgLOBsr.js → TimestampCell-DB7r3np8.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-BXgLOBsr.js.map → TimestampCell-DB7r3np8.js.map} +1 -1
- package/dashboard/dist/assets/{ToolPill-FkgTXIhq.js → ToolPill-Baxm02L6.js} +2 -2
- package/dashboard/dist/assets/{ToolPill-FkgTXIhq.js.map → ToolPill-Baxm02L6.js.map} +1 -1
- package/dashboard/dist/assets/ToolTestPanel-BLfA02wv.js +2 -0
- package/dashboard/dist/assets/{ToolTestPanel-Bwe3J5lj.js.map → ToolTestPanel-BLfA02wv.js.map} +1 -1
- package/dashboard/dist/assets/{TopicDetailPage-DAF07vZ9.js → TopicDetailPage-eAqPKShq.js} +3 -3
- package/dashboard/dist/assets/{TopicDetailPage-DAF07vZ9.js.map → TopicDetailPage-eAqPKShq.js.map} +1 -1
- package/dashboard/dist/assets/TopicsPage-BNNWD-zl.js +2 -0
- package/dashboard/dist/assets/{TopicsPage-C1gxBUap.js.map → TopicsPage-BNNWD-zl.js.map} +1 -1
- package/dashboard/dist/assets/{UserName-BzXJUE6q.js → UserName-Pw46tO_k.js} +2 -2
- package/dashboard/dist/assets/{UserName-BzXJUE6q.js.map → UserName-Pw46tO_k.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowExecutionPage-SkRU5cRX.js → WorkflowExecutionPage-DvA51lT3.js} +2 -2
- package/dashboard/dist/assets/{WorkflowExecutionPage-SkRU5cRX.js.map → WorkflowExecutionPage-DvA51lT3.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowPill--AYMW7u_.js → WorkflowPill-ZepbO_ny.js} +2 -2
- package/dashboard/dist/assets/{WorkflowPill--AYMW7u_.js.map → WorkflowPill-ZepbO_ny.js.map} +1 -1
- package/dashboard/dist/assets/WorkflowsDashboard-DFDTwnhn.js +2 -0
- package/dashboard/dist/assets/{WorkflowsDashboard-CZAqRk1N.js.map → WorkflowsDashboard-DFDTwnhn.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsOverview-BoN44VTE.js → WorkflowsOverview-5i2Tcy-p.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-BoN44VTE.js.map → WorkflowsOverview-5i2Tcy-p.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-CqjhtdJf.js → YamlWorkflowDetailPage-p4VEYZS0.js} +11 -11
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-CqjhtdJf.js.map → YamlWorkflowDetailPage-p4VEYZS0.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowsPage-CwnJkzyb.js → YamlWorkflowsPage-Cq-hMVxl.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowsPage-CwnJkzyb.js.map → YamlWorkflowsPage-Cq-hMVxl.js.map} +1 -1
- package/dashboard/dist/assets/{agents-gV0Ys-sY.js → agents-EyBPJMYa.js} +2 -2
- package/dashboard/dist/assets/{agents-gV0Ys-sY.js.map → agents-EyBPJMYa.js.map} +1 -1
- package/dashboard/dist/assets/{bots-B97itB3I.js → bots-DX6jjqtF.js} +2 -2
- package/dashboard/dist/assets/{bots-B97itB3I.js.map → bots-DX6jjqtF.js.map} +1 -1
- package/dashboard/dist/assets/{capabilities-CR9xZgGd.js → capabilities-ZdLv9xBQ.js} +2 -2
- package/dashboard/dist/assets/{capabilities-CR9xZgGd.js.map → capabilities-ZdLv9xBQ.js.map} +1 -1
- package/dashboard/dist/assets/{constants-BHkpVaqx.js → constants-CeBBTzf5.js} +2 -2
- package/dashboard/dist/assets/{constants-BHkpVaqx.js.map → constants-CeBBTzf5.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-YxvP1KCa.js → controlplane-CpvZaJuw.js} +2 -2
- package/dashboard/dist/assets/{controlplane-YxvP1KCa.js.map → controlplane-CpvZaJuw.js.map} +1 -1
- package/dashboard/dist/assets/escalation-columns-Mvsze5eV.js +2 -0
- package/dashboard/dist/assets/escalation-columns-Mvsze5eV.js.map +1 -0
- package/dashboard/dist/assets/index-B_GT23TE.js +3 -0
- package/dashboard/dist/assets/index-B_GT23TE.js.map +1 -0
- package/dashboard/dist/assets/index-BbCjGO3M.js +2 -0
- package/dashboard/dist/assets/{index-CFbo9FU9.js.map → index-BbCjGO3M.js.map} +1 -1
- package/dashboard/dist/assets/{index-DMeaiKgf.js → index-Bhb89oHH.js} +2 -2
- package/dashboard/dist/assets/{index-DMeaiKgf.js.map → index-Bhb89oHH.js.map} +1 -1
- package/dashboard/dist/assets/index-CgUcYveM.js +67 -0
- package/dashboard/dist/assets/index-CgUcYveM.js.map +1 -0
- package/dashboard/dist/assets/index-Cn8uJsd7.js +2 -0
- package/dashboard/dist/assets/{index-BQpV-DTG.js.map → index-Cn8uJsd7.js.map} +1 -1
- package/dashboard/dist/assets/index-D-Xs4rAW.js +2 -0
- package/dashboard/dist/assets/{index-Bp9KBLT5.js.map → index-D-Xs4rAW.js.map} +1 -1
- package/dashboard/dist/assets/{index-DwOnWeu8.js → index-DGmzBY9D.js} +2 -2
- package/dashboard/dist/assets/{index-DwOnWeu8.js.map → index-DGmzBY9D.js.map} +1 -1
- package/dashboard/dist/assets/{index-CIpHj4di.js → index-DZhtP2Ok.js} +2 -2
- package/dashboard/dist/assets/{index-CIpHj4di.js.map → index-DZhtP2Ok.js.map} +1 -1
- package/dashboard/dist/assets/index-Dh8MJl3L.css +1 -0
- package/dashboard/dist/assets/index-DkrBFFSO.js +13 -0
- package/dashboard/dist/assets/{index-Cfvkl2J0.js.map → index-DkrBFFSO.js.map} +1 -1
- package/dashboard/dist/assets/{index-B9BBCqLI.js → index-Eo-l3Lqo.js} +2 -2
- package/dashboard/dist/assets/{index-B9BBCqLI.js.map → index-Eo-l3Lqo.js.map} +1 -1
- package/dashboard/dist/assets/index-PfSRKerc.js +2 -0
- package/dashboard/dist/assets/{index-CUZ6LYye.js.map → index-PfSRKerc.js.map} +1 -1
- package/dashboard/dist/assets/{index-ipqwPavs.js → index-oFKUFGQL.js} +2 -2
- package/dashboard/dist/assets/{index-ipqwPavs.js.map → index-oFKUFGQL.js.map} +1 -1
- package/dashboard/dist/assets/index-z5Hpeidu.js +2 -0
- package/dashboard/dist/assets/index-z5Hpeidu.js.map +1 -0
- package/dashboard/dist/assets/{knowledge-XX6cW4Ob.js → knowledge-CgloEkaf.js} +2 -2
- package/dashboard/dist/assets/{knowledge-XX6cW4Ob.js.map → knowledge-CgloEkaf.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-CH13hNH2.js → mcp-Bix7QYO7.js} +2 -2
- package/dashboard/dist/assets/{mcp-CH13hNH2.js.map → mcp-Bix7QYO7.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-Duydd3JA.js → mcp-query-o-sGX2ST.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-Duydd3JA.js.map → mcp-query-o-sGX2ST.js.map} +1 -1
- package/dashboard/dist/assets/metadata-display-COo3mMCr.js +2 -0
- package/dashboard/dist/assets/metadata-display-COo3mMCr.js.map +1 -0
- package/dashboard/dist/assets/{personas-mDk4lLQS.js → personas-30azkJ_s.js} +2 -2
- package/dashboard/dist/assets/{personas-mDk4lLQS.js.map → personas-30azkJ_s.js.map} +1 -1
- package/dashboard/dist/assets/{pipelines-B5GcgCeF.js → pipelines-Bfk2GFK7.js} +2 -2
- package/dashboard/dist/assets/{pipelines-B5GcgCeF.js.map → pipelines-Bfk2GFK7.js.map} +1 -1
- package/dashboard/dist/assets/{tasks-CItmNsRp.js → tasks-CpdopewW.js} +2 -2
- package/dashboard/dist/assets/{tasks-CItmNsRp.js.map → tasks-CpdopewW.js.map} +1 -1
- package/dashboard/dist/assets/{topics-CJYG7BX5.js → topics--bvCV9Yp.js} +2 -2
- package/dashboard/dist/assets/{topics-CJYG7BX5.js.map → topics--bvCV9Yp.js.map} +1 -1
- package/dashboard/dist/assets/useContainerWidth-DSLp1gEm.js +2 -0
- package/dashboard/dist/assets/useContainerWidth-DSLp1gEm.js.map +1 -0
- package/dashboard/dist/assets/{useDebouncedValue-BrwgXcp8.js → useDebouncedValue-Da0lPmj3.js} +2 -2
- package/dashboard/dist/assets/{useDebouncedValue-BrwgXcp8.js.map → useDebouncedValue-Da0lPmj3.js.map} +1 -1
- package/dashboard/dist/assets/{useNamespace-CHty0HAS.js → useNamespace-DD_Esl6n.js} +2 -2
- package/dashboard/dist/assets/{useNamespace-CHty0HAS.js.map → useNamespace-DD_Esl6n.js.map} +1 -1
- package/dashboard/dist/assets/{useYamlActivityEvents-CoTsia7t.js → useYamlActivityEvents-AeAhZJJk.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-CoTsia7t.js.map → useYamlActivityEvents-AeAhZJJk.js.map} +1 -1
- package/dashboard/dist/assets/{vendor-icons-DeBdvyKJ.js → vendor-icons-B7OcUM6b.js} +2 -2
- package/dashboard/dist/assets/{vendor-icons-DeBdvyKJ.js.map → vendor-icons-B7OcUM6b.js.map} +1 -1
- package/dashboard/dist/assets/{yaml-workflows-CiWwx5rM.js → yaml-workflows-BHAOOGvn.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-CiWwx5rM.js.map → yaml-workflows-BHAOOGvn.js.map} +1 -1
- package/dashboard/dist/index.html +3 -3
- package/docs/accumulator.md +113 -0
- package/docs/api/http/escalations.md +90 -0
- package/docs/api/http/roles.md +1 -0
- package/docs/api/sdk/escalations.md +92 -0
- package/docs/api/sdk/roles.md +2 -0
- package/docs/architecture.md +1 -1
- package/docs/code-owned-configuration.md +2 -1
- package/docs/dashboard.md +10 -4
- package/docs/hitl/design.md +1 -1
- package/docs/hitl/escalation.md +37 -1
- package/docs/hitl/invoke-form.md +4 -0
- package/docs/hitl/pinned-views.md +4 -0
- package/docs/hitl/portal.md +97 -0
- package/docs/hitl/resolution.md +41 -0
- package/docs/hitl/x-lt-embed.md +1 -1
- package/docs/hitl/x-lt-invoke.md +95 -0
- package/docs/hitl/x-lt-list-schema.md +3 -1
- package/docs/hitl/x-lt-widget.md +1 -0
- package/docs/hitl-guide.md +8 -1
- package/docs/scan-codes.md +33 -9
- package/docs/sdk.md +1 -1
- package/docs/workflows.md +2 -2
- package/package.json +4 -2
- package/dashboard/dist/assets/AgentsPage-7JJBHku8.js +0 -2
- package/dashboard/dist/assets/AvailableEscalationsPage-lz5qwSjg.js +0 -2
- package/dashboard/dist/assets/AvailableEscalationsPage-lz5qwSjg.js.map +0 -1
- package/dashboard/dist/assets/BulkAssignModal-NJBcoj-f.js +0 -2
- package/dashboard/dist/assets/CapabilitiesPage-F8dpNn9B.js +0 -2
- package/dashboard/dist/assets/DataTable-7C7riavf.js +0 -2
- package/dashboard/dist/assets/DataTable-7C7riavf.js.map +0 -1
- package/dashboard/dist/assets/EntityTimelinePanel-CkF-oW-m.js +0 -2
- package/dashboard/dist/assets/EscalationListView-AHW2xtlr.js +0 -2
- package/dashboard/dist/assets/EscalationListView-AHW2xtlr.js.map +0 -1
- package/dashboard/dist/assets/GraphInvokePage-CKtvWowP.js +0 -2
- package/dashboard/dist/assets/HomePage-BQ3Q791Q.js +0 -2
- package/dashboard/dist/assets/ListToolbar-DdJzj472.js +0 -2
- package/dashboard/dist/assets/McpQueryPage-CfJy7HZ7.js +0 -2
- package/dashboard/dist/assets/McpRunsPage-D7QXjW9z.js +0 -2
- package/dashboard/dist/assets/OperationsPage-aLHHAP2X.js +0 -3
- package/dashboard/dist/assets/OperationsPage-aLHHAP2X.js.map +0 -1
- package/dashboard/dist/assets/OperatorDashboard-sXNDh1Ph.js +0 -2
- package/dashboard/dist/assets/ProcessesListPage-CjwVKe32.js +0 -2
- package/dashboard/dist/assets/ResolverForm-Bk-wDkN-.js +0 -3
- package/dashboard/dist/assets/ResolverForm-Bk-wDkN-.js.map +0 -1
- package/dashboard/dist/assets/RoleDetailPage-WQt0y5l7.js +0 -8
- package/dashboard/dist/assets/RoleDetailPage-WQt0y5l7.js.map +0 -1
- package/dashboard/dist/assets/RunAsSelector-fFMt1bGe.js +0 -2
- package/dashboard/dist/assets/ScanSchemeDetailPage-eKQpmsC_.js +0 -2
- package/dashboard/dist/assets/ScanSchemeDetailPage-eKQpmsC_.js.map +0 -1
- package/dashboard/dist/assets/ScanStationPage-C1_ppDoZ.js +0 -2
- package/dashboard/dist/assets/TasksListPage-BB1f79lL.js +0 -2
- package/dashboard/dist/assets/ToolTestPanel-Bwe3J5lj.js +0 -2
- package/dashboard/dist/assets/TopicsPage-C1gxBUap.js +0 -2
- package/dashboard/dist/assets/WorkflowsDashboard-CZAqRk1N.js +0 -2
- package/dashboard/dist/assets/escalation-columns-uq-IV2aj.js +0 -2
- package/dashboard/dist/assets/escalation-columns-uq-IV2aj.js.map +0 -1
- package/dashboard/dist/assets/index-3ezfWLkE.js +0 -6
- package/dashboard/dist/assets/index-3ezfWLkE.js.map +0 -1
- package/dashboard/dist/assets/index-BQpV-DTG.js +0 -2
- package/dashboard/dist/assets/index-Bp9KBLT5.js +0 -2
- package/dashboard/dist/assets/index-Bpvfr4OW.css +0 -1
- package/dashboard/dist/assets/index-CFbo9FU9.js +0 -2
- package/dashboard/dist/assets/index-CIwlVfvV.js +0 -67
- package/dashboard/dist/assets/index-CIwlVfvV.js.map +0 -1
- package/dashboard/dist/assets/index-CUZ6LYye.js +0 -2
- package/dashboard/dist/assets/index-Cfvkl2J0.js +0 -13
- package/dashboard/dist/assets/index-SGyrXGp8.js +0 -3
- package/dashboard/dist/assets/index-SGyrXGp8.js.map +0 -1
- package/dashboard/dist/assets/invoke-context-DrVyUEfs.js +0 -2
- package/dashboard/dist/assets/invoke-context-DrVyUEfs.js.map +0 -1
- package/dashboard/dist/assets/metadata-display--TzK0REC.js +0 -2
- package/dashboard/dist/assets/metadata-display--TzK0REC.js.map +0 -1
- package/dashboard/dist/assets/resolver-payload-m9AGKZ3a.js +0 -2
- package/dashboard/dist/assets/resolver-payload-m9AGKZ3a.js.map +0 -1
- package/docs/compilation.md +0 -152
- package/docs/compiler.md +0 -311
- package/docs/contributing.md +0 -56
- package/docs/design-principles.md +0 -245
- package/docs/schema-exchange.md +0 -173
- package/docs/self-test.md +0 -106
- package/docs/story.md +0 -184
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{j as e,a as u}from"./vendor-query-DvWWuNIB.js";import{M as $,c as U,$ as B,as as I}from"./index-CgUcYveM.js";import{D as q,f as O}from"./constants-CeBBTzf5.js";import{u as R}from"./useDebouncedValue-Da0lPmj3.js";function J({open:a,onClose:i,onConfirm:r,selectedCount:s,isPending:l,error:c,actionLabel:d}){const x=!!s&&s>1,o=d||"Cancel",m=x?`${o} ${s} Items`:o==="Cancel"?"Cancel Item":o,n=x?`Are you sure you want to ${o}? This removes ${s} items from the work queue.`:`Are you sure you want to ${o}? This removes the item from the work queue.`;return e.jsx($,{open:a,onClose:i,title:m,children:e.jsxs("div",{className:"space-y-4",children:[e.jsx("p",{className:"text-sm text-text-secondary",children:n}),e.jsx("p",{className:"text-xs text-text-tertiary",children:"This action cannot be undone."}),c&&e.jsx("p",{className:"text-xs text-status-error",children:c.message}),e.jsxs("div",{className:"flex justify-end gap-3 pt-2",children:[e.jsx("button",{onClick:i,disabled:l,className:"btn-secondary text-xs",children:"Keep"}),e.jsx("button",{onClick:r,disabled:l,className:"bg-status-error text-text-inverse px-3 py-1.5 rounded-md text-xs hover:opacity-90 transition-opacity disabled:opacity-50",children:l?"Working...":`Yes, ${o}`})]})]})})}const W="x-lt-labels",z=["claim","cancel","submit","escalate","release"];function Z(a){const i=a==null?void 0:a[W];if(!i||typeof i!="object"||Array.isArray(i))return{};const r=i,s={};r.cancel===!1&&(s.cancel=!1);for(const l of z){const c=r[l];typeof c=="string"&&c.trim().length>0&&(s[l]=c.trim())}return s}function G(){const{data:a}=U();return u.useMemo(()=>{var r;return(((r=a==null?void 0:a.escalation)==null?void 0:r.claimDurations)??q).map(s=>({value:String(s),label:O(s)}))},[a])}const K=[{value:1,label:"minutes"},{value:60,label:"hours"}];function Q({onChange:a,compact:i,autoFocus:r,"data-testid":s="custom-duration-input"}){const[l,c]=u.useState(""),[d,x]=u.useState(1);u.useEffect(()=>{const n=parseInt(l);a(n>0?n*d:0)},[l,d,a]);const o=i?"text-xs":"text-sm",m=i?"w-16":"w-20";return e.jsxs("div",{className:"flex items-center gap-2","data-testid":s,children:[e.jsx("input",{type:"number",min:1,max:d===60?24:1440,value:l,onChange:n=>c(n.target.value),placeholder:d===60?"hrs":"min",className:`input ${o} ${m} text-center`,autoFocus:r,"data-testid":`${s}-quantity`}),e.jsx("select",{value:d,onChange:n=>x(parseInt(n.target.value)),className:`select ${o} py-1`,"data-testid":`${s}-unit`,children:K.map(n=>e.jsx("option",{value:n.value,children:n.label},n.value))})]})}function P({open:a,onClose:i,selectedCount:r,selectedRoles:s,onSubmit:l,isPending:c,claimedCount:d=0,result:x=null}){const{isSuperAdmin:o}=B(),m=G(),[n,f]=u.useState("user"),[p,b]=u.useState(null),[g,v]=u.useState(""),[h,N]=u.useState("30"),[L,j]=u.useState(0),[k,S]=u.useState(!1),T=u.useCallback(t=>j(t),[]),_=!o&&s.length===1?s[0]:void 0,D=R(g,250),{data:y,isLoading:C}=I({role:_,status:"active",search:D.trim()||void 0,limit:200},{enabled:a}),A=(y==null?void 0:y.users)??[],w=()=>{f("user"),b(null),v(""),N("30"),j(0),S(!1),i()},E=t=>{b(t),f("duration")},M=()=>{f("user")},F=()=>{if(!p)return;const t=h==="custom"?L:parseInt(h);!t||t<=0||l(p.id,t,k)};return e.jsx($,{open:a,onClose:w,title:"Assign Escalations",children:e.jsxs("div",{className:"space-y-4",children:[n==="user"&&e.jsxs(e.Fragment,{children:[e.jsxs("p",{className:"text-sm text-text-secondary",children:["Select a user to assign"," ",e.jsx("span",{className:"font-medium text-text-primary",children:r})," ","escalation(s) to:"]}),e.jsx("input",{type:"text",value:g,onChange:t=>v(t.target.value),placeholder:"Search by name or email...",className:"input text-xs w-full",autoFocus:!0}),e.jsxs("div",{className:"max-h-60 overflow-y-auto border border-surface-border rounded-lg divide-y divide-surface-border",children:[C&&e.jsx("p",{className:"text-xs text-text-tertiary p-3",children:"Loading users..."}),!C&&A.length===0&&e.jsx("p",{className:"text-xs text-text-tertiary p-3",children:"No users found"}),A.map(t=>e.jsxs("button",{onClick:()=>E(t),className:"w-full text-left px-3 py-2 hover:bg-surface-hover transition-colors",children:[e.jsx("p",{className:"text-xs font-medium text-text-primary",children:t.display_name||t.external_id}),t.email&&e.jsx("p",{className:"text-2xs text-text-tertiary",children:t.email})]},t.id))]}),e.jsx("div",{className:"flex justify-end pt-2",children:e.jsx("button",{onClick:w,className:"btn-secondary text-xs",children:"Cancel"})})]}),n==="duration"&&p&&e.jsxs(e.Fragment,{children:[e.jsxs("p",{className:"text-sm text-text-secondary",children:["Assign to"," ",e.jsx("span",{className:"font-medium text-text-primary",children:p.display_name||p.external_id})," ","for:"]}),e.jsxs("select",{value:h,onChange:t=>{N(t.target.value),j(0)},className:"select w-full text-sm",children:[m.map(t=>e.jsx("option",{value:t.value,children:t.label},t.value)),e.jsx("option",{value:"custom",children:"Other..."})]}),h==="custom"&&e.jsx(Q,{onChange:T,autoFocus:!0}),d>0&&e.jsxs("label",{className:"flex items-start gap-2 text-xs text-text-secondary",children:[e.jsx("input",{type:"checkbox",checked:k,onChange:t=>S(t.target.checked),className:"mt-0.5"}),e.jsxs("span",{children:["Also reassign ",e.jsx("span",{className:"font-medium text-text-primary",children:d})," ","item(s) with a live claim — the current holder loses the item. Unchecked, those are skipped."]})]}),x&&x.skipped>0&&e.jsxs("p",{className:"text-xs text-status-warning","data-testid":"assign-skip-note",children:["Assigned ",x.assigned," · skipped ",x.skipped," with live claims."]}),e.jsxs("div",{className:"flex justify-end gap-3 pt-2",children:[e.jsx("button",{onClick:M,className:"btn-secondary text-xs",children:"Back"}),e.jsx("button",{onClick:F,disabled:c,className:"btn-primary text-xs",children:c?"Assigning...":"Assign"})]})]})]})})}export{P as B,Q as C,J as a,Z as r,G as u};
|
|
2
|
+
//# sourceMappingURL=BulkAssignModal-BOAWsViq.js.map
|
package/dashboard/dist/assets/{BulkAssignModal-NJBcoj-f.js.map → BulkAssignModal-BOAWsViq.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BulkAssignModal-NJBcoj-f.js","sources":["../../src/components/common/modal/ConfirmCancelModal.tsx","../../../shared/form-validation/x-lt-labels.ts","../../src/hooks/useClaimDurations.ts","../../src/components/common/form/CustomDurationPicker.tsx","../../src/components/common/modal/BulkAssignModal.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 /** Replacement label from x-lt-labels.cancel — the challenge speaks it. */\n actionLabel?: string;\n}\n\nexport function ConfirmCancelModal({\n open,\n onClose,\n onConfirm,\n selectedCount,\n isPending,\n error,\n actionLabel,\n}: ConfirmCancelModalProps) {\n // One template for every vocabulary: the title carries the verb (the\n // pressed button's label), the body states the intent in general terms.\n const isBulk = !!selectedCount && selectedCount > 1;\n const label = actionLabel || 'Cancel';\n const title = isBulk ? `${label} ${selectedCount} Items` : label === 'Cancel' ? 'Cancel Item' : label;\n\n const body = isBulk\n ? `Are you sure you want to ${label}? This removes ${selectedCount} items from the work queue.`\n : `Are you sure you want to ${label}? This removes the item from the work queue.`;\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\">{body}</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-text-inverse px-3 py-1.5 rounded-md text-xs hover:opacity-90 transition-opacity disabled:opacity-50\"\n >\n {isPending ? 'Working...' : `Yes, ${label}`}\n </button>\n </div>\n </div>\n </Modal>\n );\n}\n","/**\n * x-lt-labels — configurable copy for the standard escalation footer. A\n * form_schema may declare, at its schema root, an object that renames the\n * footer's action controls. Each key is a standard target; its value is the\n * label to render in place of the default.\n *\n * x-lt-labels object — { claim, cancel, submit, escalate, release }\n *\n * ```jsonc\n * { \"x-lt-labels\": { \"claim\": \"Claim and Submit\", \"submit\": \"Approve\" } }\n * ```\n *\n * `cancel` additionally accepts `false` to remove the control entirely —\n * for roles where cancelling is not part of the process (\"Send to Service\"\n * flows escalate instead). The other targets are rename-only: hiding\n * claim/submit/release would strand the footer.\n *\n * Only the five known targets are read; unknown keys and non-string values\n * (except `cancel: false`) are ignored. Any target the schema omits keeps its\n * default label, so a schema overrides just the controls it cares about.\n */\n\nexport const X_LT_LABELS = 'x-lt-labels';\n\n/** The footer controls a schema may rename. */\nexport const FOOTER_LABEL_TARGETS = ['claim', 'cancel', 'submit', 'escalate', 'release'] as const;\n\nexport type FooterLabelTarget = (typeof FOOTER_LABEL_TARGETS)[number];\n\n/**\n * A partial map of target → override label. Absent targets keep their\n * default. `cancel: false` removes the cancel control from the footer.\n */\nexport type FooterLabels = Partial<Record<Exclude<FooterLabelTarget, 'cancel'>, string>> & {\n cancel?: string | false;\n};\n\n/**\n * The schema's footer label overrides, or an empty map when none are declared.\n * Reads only the known targets; a non-object `x-lt-labels`, unknown keys, and\n * blank or non-string values are dropped — except `cancel: false`, which is\n * preserved as the hide instruction.\n */\nexport function readFooterLabels(\n schema: Record<string, unknown> | null | undefined,\n): FooterLabels {\n const raw = schema?.[X_LT_LABELS];\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return {};\n const source = raw as Record<string, unknown>;\n const labels: FooterLabels = {};\n if (source.cancel === false) labels.cancel = false;\n for (const target of FOOTER_LABEL_TARGETS) {\n const value = source[target];\n if (typeof value === 'string' && value.trim().length > 0) {\n labels[target] = value.trim();\n }\n }\n return labels;\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","import { useState, useCallback } from 'react';\nimport { Modal } from './Modal';\nimport { CustomDurationPicker } from '../form/CustomDurationPicker';\nimport { useUsers } from '../../../api/users';\nimport { useAuth } from '../../../hooks/useAuth';\nimport { useClaimDurations } from '../../../hooks/useClaimDurations';\nimport { useDebouncedValue } from '../../../hooks/useDebouncedValue';\nimport type { LTUserRecord } from '../../../api/types';\n\ninterface BulkAssignModalProps {\n open: boolean;\n onClose: () => void;\n selectedCount: number;\n /** Distinct roles of the selected escalations; scopes user list for admins */\n selectedRoles: string[];\n onSubmit: (targetUserId: string, durationMinutes: number, reassign: boolean) => void;\n isPending: boolean;\n /**\n * Selected rows currently under a LIVE claim. Plain assign skips them;\n * when > 0 the duration step offers the explicit takeover.\n */\n claimedCount?: number;\n /** Assignment outcome from the last submit; skipped > 0 keeps the modal open to say so. */\n result?: { assigned: number; skipped: number } | null;\n}\n\nexport function BulkAssignModal({\n open,\n onClose,\n selectedCount,\n selectedRoles,\n onSubmit,\n isPending,\n claimedCount = 0,\n result = null,\n}: BulkAssignModalProps) {\n const { isSuperAdmin } = useAuth();\n const claimDurations = useClaimDurations();\n const [step, setStep] = useState<'user' | 'duration'>('user');\n const [selectedUser, setSelectedUser] = useState<LTUserRecord | null>(null);\n const [search, setSearch] = useState('');\n const [duration, setDuration] = useState('30');\n const [customMinutes, setCustomMinutes] = useState(0);\n const [reassign, setReassign] = useState(false);\n const onCustomChange = useCallback((m: number) => setCustomMinutes(m), []);\n\n // Admins with a single role: scope to that role. Otherwise show all active users.\n const roleFilter =\n !isSuperAdmin && selectedRoles.length === 1 ? selectedRoles[0] : undefined;\n\n // Search is resolved server-side (ILIKE on name/email/external_id) so it matches\n // every user, not just a fetched slice — no client-side filtering over a cap.\n const debouncedSearch = useDebouncedValue(search, 250);\n const { data: usersData, isLoading: usersLoading } = useUsers({\n role: roleFilter,\n status: 'active',\n search: debouncedSearch.trim() || undefined,\n limit: 200,\n }, { enabled: open });\n\n const users = usersData?.users ?? [];\n\n const handleClose = () => {\n setStep('user');\n setSelectedUser(null);\n setSearch('');\n setDuration('30');\n setCustomMinutes(0);\n setReassign(false);\n onClose();\n };\n\n const handleSelectUser = (user: LTUserRecord) => {\n setSelectedUser(user);\n setStep('duration');\n };\n\n const handleBack = () => {\n setStep('user');\n };\n\n const handleSubmit = () => {\n if (!selectedUser) return;\n const minutes = duration === 'custom' ? customMinutes : parseInt(duration);\n if (!minutes || minutes <= 0) return;\n onSubmit(selectedUser.id, minutes, reassign);\n };\n\n return (\n <Modal open={open} onClose={handleClose} title=\"Assign Escalations\">\n <div className=\"space-y-4\">\n {step === 'user' && (\n <>\n <p className=\"text-sm text-text-secondary\">\n Select a user to assign{' '}\n <span className=\"font-medium text-text-primary\">\n {selectedCount}\n </span>{' '}\n escalation(s) to:\n </p>\n\n <input\n type=\"text\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n placeholder=\"Search by name or email...\"\n className=\"input text-xs w-full\"\n autoFocus\n />\n\n <div className=\"max-h-60 overflow-y-auto border border-surface-border rounded-lg divide-y divide-surface-border\">\n {usersLoading && (\n <p className=\"text-xs text-text-tertiary p-3\">\n Loading users...\n </p>\n )}\n {!usersLoading && users.length === 0 && (\n <p className=\"text-xs text-text-tertiary p-3\">\n No users found\n </p>\n )}\n {users.map((user) => (\n <button\n key={user.id}\n onClick={() => handleSelectUser(user)}\n className=\"w-full text-left px-3 py-2 hover:bg-surface-hover transition-colors\"\n >\n <p className=\"text-xs font-medium text-text-primary\">\n {user.display_name || user.external_id}\n </p>\n {user.email && (\n <p className=\"text-2xs text-text-tertiary\">\n {user.email}\n </p>\n )}\n </button>\n ))}\n </div>\n\n <div className=\"flex justify-end pt-2\">\n <button onClick={handleClose} className=\"btn-secondary text-xs\">\n Cancel\n </button>\n </div>\n </>\n )}\n\n {step === 'duration' && selectedUser && (\n <>\n <p className=\"text-sm text-text-secondary\">\n Assign to{' '}\n <span className=\"font-medium text-text-primary\">\n {selectedUser.display_name || selectedUser.external_id}\n </span>{' '}\n for:\n </p>\n\n <select\n value={duration}\n onChange={(e) => { setDuration(e.target.value); setCustomMinutes(0); }}\n className=\"select w-full text-sm\"\n >\n {claimDurations.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n <option value=\"custom\">Other...</option>\n </select>\n {duration === 'custom' && (\n <CustomDurationPicker onChange={onCustomChange} autoFocus />\n )}\n\n {claimedCount > 0 && (\n <label className=\"flex items-start gap-2 text-xs text-text-secondary\">\n <input\n type=\"checkbox\"\n checked={reassign}\n onChange={(e) => setReassign(e.target.checked)}\n className=\"mt-0.5\"\n />\n <span>\n Also reassign <span className=\"font-medium text-text-primary\">{claimedCount}</span>{' '}\n item(s) with a live claim — the current holder loses the item.\n Unchecked, those are skipped.\n </span>\n </label>\n )}\n\n {result && result.skipped > 0 && (\n <p className=\"text-xs text-status-warning\" data-testid=\"assign-skip-note\">\n Assigned {result.assigned} · skipped {result.skipped} with live claims.\n </p>\n )}\n\n <div className=\"flex justify-end gap-3 pt-2\">\n <button onClick={handleBack} className=\"btn-secondary text-xs\">\n Back\n </button>\n <button\n onClick={handleSubmit}\n disabled={isPending}\n className=\"btn-primary text-xs\"\n >\n {isPending ? 'Assigning...' : 'Assign'}\n </button>\n </div>\n </>\n )}\n </div>\n </Modal>\n );\n}\n"],"names":["ConfirmCancelModal","open","onClose","onConfirm","selectedCount","isPending","error","actionLabel","isBulk","label","title","body","jsx","Modal","jsxs","X_LT_LABELS","FOOTER_LABEL_TARGETS","readFooterLabels","schema","raw","source","labels","target","value","useClaimDurations","settings","useSettings","useMemo","_a","DEFAULT_CLAIM_DURATIONS","m","formatClaimDuration","UNITS","CustomDurationPicker","onChange","compact","autoFocus","testId","quantity","setQuantity","useState","multiplier","setMultiplier","useEffect","q","textSize","inputWidth","e","u","BulkAssignModal","selectedRoles","onSubmit","claimedCount","result","isSuperAdmin","useAuth","claimDurations","step","setStep","selectedUser","setSelectedUser","search","setSearch","duration","setDuration","customMinutes","setCustomMinutes","reassign","setReassign","onCustomChange","useCallback","roleFilter","debouncedSearch","useDebouncedValue","usersData","usersLoading","useUsers","users","handleClose","handleSelectUser","user","handleBack","handleSubmit","minutes","Fragment","opt"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"BulkAssignModal-BOAWsViq.js","sources":["../../src/components/common/modal/ConfirmCancelModal.tsx","../../../shared/form-validation/x-lt-labels.ts","../../src/hooks/useClaimDurations.ts","../../src/components/common/form/CustomDurationPicker.tsx","../../src/components/common/modal/BulkAssignModal.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 /** Replacement label from x-lt-labels.cancel — the challenge speaks it. */\n actionLabel?: string;\n}\n\nexport function ConfirmCancelModal({\n open,\n onClose,\n onConfirm,\n selectedCount,\n isPending,\n error,\n actionLabel,\n}: ConfirmCancelModalProps) {\n // One template for every vocabulary: the title carries the verb (the\n // pressed button's label), the body states the intent in general terms.\n const isBulk = !!selectedCount && selectedCount > 1;\n const label = actionLabel || 'Cancel';\n const title = isBulk ? `${label} ${selectedCount} Items` : label === 'Cancel' ? 'Cancel Item' : label;\n\n const body = isBulk\n ? `Are you sure you want to ${label}? This removes ${selectedCount} items from the work queue.`\n : `Are you sure you want to ${label}? This removes the item from the work queue.`;\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\">{body}</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-text-inverse px-3 py-1.5 rounded-md text-xs hover:opacity-90 transition-opacity disabled:opacity-50\"\n >\n {isPending ? 'Working...' : `Yes, ${label}`}\n </button>\n </div>\n </div>\n </Modal>\n );\n}\n","/**\n * x-lt-labels — configurable copy for the standard escalation footer. A\n * form_schema may declare, at its schema root, an object that renames the\n * footer's action controls. Each key is a standard target; its value is the\n * label to render in place of the default.\n *\n * x-lt-labels object — { claim, cancel, submit, escalate, release }\n *\n * ```jsonc\n * { \"x-lt-labels\": { \"claim\": \"Claim and Submit\", \"submit\": \"Approve\" } }\n * ```\n *\n * `cancel` additionally accepts `false` to remove the control entirely —\n * for roles where cancelling is not part of the process (\"Send to Service\"\n * flows escalate instead). The other targets are rename-only: hiding\n * claim/submit/release would strand the footer.\n *\n * Only the five known targets are read; unknown keys and non-string values\n * (except `cancel: false`) are ignored. Any target the schema omits keeps its\n * default label, so a schema overrides just the controls it cares about.\n */\n\nexport const X_LT_LABELS = 'x-lt-labels';\n\n/** The footer controls a schema may rename. */\nexport const FOOTER_LABEL_TARGETS = ['claim', 'cancel', 'submit', 'escalate', 'release'] as const;\n\nexport type FooterLabelTarget = (typeof FOOTER_LABEL_TARGETS)[number];\n\n/**\n * A partial map of target → override label. Absent targets keep their\n * default. `cancel: false` removes the cancel control from the footer.\n */\nexport type FooterLabels = Partial<Record<Exclude<FooterLabelTarget, 'cancel'>, string>> & {\n cancel?: string | false;\n};\n\n/**\n * The schema's footer label overrides, or an empty map when none are declared.\n * Reads only the known targets; a non-object `x-lt-labels`, unknown keys, and\n * blank or non-string values are dropped — except `cancel: false`, which is\n * preserved as the hide instruction.\n */\nexport function readFooterLabels(\n schema: Record<string, unknown> | null | undefined,\n): FooterLabels {\n const raw = schema?.[X_LT_LABELS];\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return {};\n const source = raw as Record<string, unknown>;\n const labels: FooterLabels = {};\n if (source.cancel === false) labels.cancel = false;\n for (const target of FOOTER_LABEL_TARGETS) {\n const value = source[target];\n if (typeof value === 'string' && value.trim().length > 0) {\n labels[target] = value.trim();\n }\n }\n return labels;\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","import { useState, useCallback } from 'react';\nimport { Modal } from './Modal';\nimport { CustomDurationPicker } from '../form/CustomDurationPicker';\nimport { useUsers } from '../../../api/users';\nimport { useAuth } from '../../../hooks/useAuth';\nimport { useClaimDurations } from '../../../hooks/useClaimDurations';\nimport { useDebouncedValue } from '../../../hooks/useDebouncedValue';\nimport type { LTUserRecord } from '../../../api/types';\n\ninterface BulkAssignModalProps {\n open: boolean;\n onClose: () => void;\n selectedCount: number;\n /** Distinct roles of the selected escalations; scopes user list for admins */\n selectedRoles: string[];\n onSubmit: (targetUserId: string, durationMinutes: number, reassign: boolean) => void;\n isPending: boolean;\n /**\n * Selected rows currently under a LIVE claim. Plain assign skips them;\n * when > 0 the duration step offers the explicit takeover.\n */\n claimedCount?: number;\n /** Assignment outcome from the last submit; skipped > 0 keeps the modal open to say so. */\n result?: { assigned: number; skipped: number } | null;\n}\n\nexport function BulkAssignModal({\n open,\n onClose,\n selectedCount,\n selectedRoles,\n onSubmit,\n isPending,\n claimedCount = 0,\n result = null,\n}: BulkAssignModalProps) {\n const { isSuperAdmin } = useAuth();\n const claimDurations = useClaimDurations();\n const [step, setStep] = useState<'user' | 'duration'>('user');\n const [selectedUser, setSelectedUser] = useState<LTUserRecord | null>(null);\n const [search, setSearch] = useState('');\n const [duration, setDuration] = useState('30');\n const [customMinutes, setCustomMinutes] = useState(0);\n const [reassign, setReassign] = useState(false);\n const onCustomChange = useCallback((m: number) => setCustomMinutes(m), []);\n\n // Admins with a single role: scope to that role. Otherwise show all active users.\n const roleFilter =\n !isSuperAdmin && selectedRoles.length === 1 ? selectedRoles[0] : undefined;\n\n // Search is resolved server-side (ILIKE on name/email/external_id) so it matches\n // every user, not just a fetched slice — no client-side filtering over a cap.\n const debouncedSearch = useDebouncedValue(search, 250);\n const { data: usersData, isLoading: usersLoading } = useUsers({\n role: roleFilter,\n status: 'active',\n search: debouncedSearch.trim() || undefined,\n limit: 200,\n }, { enabled: open });\n\n const users = usersData?.users ?? [];\n\n const handleClose = () => {\n setStep('user');\n setSelectedUser(null);\n setSearch('');\n setDuration('30');\n setCustomMinutes(0);\n setReassign(false);\n onClose();\n };\n\n const handleSelectUser = (user: LTUserRecord) => {\n setSelectedUser(user);\n setStep('duration');\n };\n\n const handleBack = () => {\n setStep('user');\n };\n\n const handleSubmit = () => {\n if (!selectedUser) return;\n const minutes = duration === 'custom' ? customMinutes : parseInt(duration);\n if (!minutes || minutes <= 0) return;\n onSubmit(selectedUser.id, minutes, reassign);\n };\n\n return (\n <Modal open={open} onClose={handleClose} title=\"Assign Escalations\">\n <div className=\"space-y-4\">\n {step === 'user' && (\n <>\n <p className=\"text-sm text-text-secondary\">\n Select a user to assign{' '}\n <span className=\"font-medium text-text-primary\">\n {selectedCount}\n </span>{' '}\n escalation(s) to:\n </p>\n\n <input\n type=\"text\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n placeholder=\"Search by name or email...\"\n className=\"input text-xs w-full\"\n autoFocus\n />\n\n <div className=\"max-h-60 overflow-y-auto border border-surface-border rounded-lg divide-y divide-surface-border\">\n {usersLoading && (\n <p className=\"text-xs text-text-tertiary p-3\">\n Loading users...\n </p>\n )}\n {!usersLoading && users.length === 0 && (\n <p className=\"text-xs text-text-tertiary p-3\">\n No users found\n </p>\n )}\n {users.map((user) => (\n <button\n key={user.id}\n onClick={() => handleSelectUser(user)}\n className=\"w-full text-left px-3 py-2 hover:bg-surface-hover transition-colors\"\n >\n <p className=\"text-xs font-medium text-text-primary\">\n {user.display_name || user.external_id}\n </p>\n {user.email && (\n <p className=\"text-2xs text-text-tertiary\">\n {user.email}\n </p>\n )}\n </button>\n ))}\n </div>\n\n <div className=\"flex justify-end pt-2\">\n <button onClick={handleClose} className=\"btn-secondary text-xs\">\n Cancel\n </button>\n </div>\n </>\n )}\n\n {step === 'duration' && selectedUser && (\n <>\n <p className=\"text-sm text-text-secondary\">\n Assign to{' '}\n <span className=\"font-medium text-text-primary\">\n {selectedUser.display_name || selectedUser.external_id}\n </span>{' '}\n for:\n </p>\n\n <select\n value={duration}\n onChange={(e) => { setDuration(e.target.value); setCustomMinutes(0); }}\n className=\"select w-full text-sm\"\n >\n {claimDurations.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n <option value=\"custom\">Other...</option>\n </select>\n {duration === 'custom' && (\n <CustomDurationPicker onChange={onCustomChange} autoFocus />\n )}\n\n {claimedCount > 0 && (\n <label className=\"flex items-start gap-2 text-xs text-text-secondary\">\n <input\n type=\"checkbox\"\n checked={reassign}\n onChange={(e) => setReassign(e.target.checked)}\n className=\"mt-0.5\"\n />\n <span>\n Also reassign <span className=\"font-medium text-text-primary\">{claimedCount}</span>{' '}\n item(s) with a live claim — the current holder loses the item.\n Unchecked, those are skipped.\n </span>\n </label>\n )}\n\n {result && result.skipped > 0 && (\n <p className=\"text-xs text-status-warning\" data-testid=\"assign-skip-note\">\n Assigned {result.assigned} · skipped {result.skipped} with live claims.\n </p>\n )}\n\n <div className=\"flex justify-end gap-3 pt-2\">\n <button onClick={handleBack} className=\"btn-secondary text-xs\">\n Back\n </button>\n <button\n onClick={handleSubmit}\n disabled={isPending}\n className=\"btn-primary text-xs\"\n >\n {isPending ? 'Assigning...' : 'Assign'}\n </button>\n </div>\n </>\n )}\n </div>\n </Modal>\n );\n}\n"],"names":["ConfirmCancelModal","open","onClose","onConfirm","selectedCount","isPending","error","actionLabel","isBulk","label","title","body","jsx","Modal","jsxs","X_LT_LABELS","FOOTER_LABEL_TARGETS","readFooterLabels","schema","raw","source","labels","target","value","useClaimDurations","settings","useSettings","useMemo","_a","DEFAULT_CLAIM_DURATIONS","m","formatClaimDuration","UNITS","CustomDurationPicker","onChange","compact","autoFocus","testId","quantity","setQuantity","useState","multiplier","setMultiplier","useEffect","q","textSize","inputWidth","e","u","BulkAssignModal","selectedRoles","onSubmit","claimedCount","result","isSuperAdmin","useAuth","claimDurations","step","setStep","selectedUser","setSelectedUser","search","setSearch","duration","setDuration","customMinutes","setCustomMinutes","reassign","setReassign","onCustomChange","useCallback","roleFilter","debouncedSearch","useDebouncedValue","usersData","usersLoading","useUsers","users","handleClose","handleSelectUser","user","handleBack","handleSubmit","minutes","Fragment","opt"],"mappings":"2NAaO,SAASA,EAAmB,CACjC,KAAAC,EACA,QAAAC,EACA,UAAAC,EACA,cAAAC,EACA,UAAAC,EACA,MAAAC,EACA,YAAAC,CACF,EAA4B,CAG1B,MAAMC,EAAS,CAAC,CAACJ,GAAiBA,EAAgB,EAC5CK,EAAQF,GAAe,SACvBG,EAAQF,EAAS,GAAGC,CAAK,IAAIL,CAAa,SAAWK,IAAU,SAAW,cAAgBA,EAE1FE,EAAOH,EACT,4BAA4BC,CAAK,kBAAkBL,CAAa,8BAChE,4BAA4BK,CAAK,+CAErC,OACEG,EAAAA,IAACC,GAAM,KAAAZ,EAAY,QAAAC,EAAkB,MAAAQ,EACnC,SAAAI,EAAAA,KAAC,MAAA,CAAI,UAAU,YACb,SAAA,CAAAF,EAAAA,IAAC,IAAA,CAAE,UAAU,8BAA+B,SAAAD,EAAK,EACjDC,EAAAA,IAAC,IAAA,CAAE,UAAU,6BAA6B,SAAA,gCAA6B,EACtEN,GAASM,EAAAA,IAAC,IAAA,CAAE,UAAU,4BAA6B,WAAM,QAAQ,EAClEE,EAAAA,KAAC,MAAA,CAAI,UAAU,8BACb,SAAA,CAAAF,EAAAA,IAAC,UAAO,QAASV,EAAS,SAAUG,EAAW,UAAU,wBAAwB,SAAA,MAAA,CAEjF,EACAO,EAAAA,IAAC,SAAA,CACC,QAAST,EACT,SAAUE,EACV,UAAU,2HAET,SAAAA,EAAY,aAAe,QAAQI,CAAK,EAAA,CAAA,CAC3C,CAAA,CACF,CAAA,CAAA,CACF,CAAA,CACF,CAEJ,CC/BO,MAAMM,EAAc,cAGdC,EAAuB,CAAC,QAAS,SAAU,SAAU,WAAY,SAAS,EAkBhF,SAASC,EACdC,EACc,CACd,MAAMC,EAAMD,GAAA,YAAAA,EAASH,GACrB,GAAI,CAACI,GAAO,OAAOA,GAAQ,UAAY,MAAM,QAAQA,CAAG,EAAG,MAAO,CAAA,EAClE,MAAMC,EAASD,EACTE,EAAuB,CAAA,EACzBD,EAAO,SAAW,KAAOC,EAAO,OAAS,IAC7C,UAAWC,KAAUN,EAAsB,CACzC,MAAMO,EAAQH,EAAOE,CAAM,EACvB,OAAOC,GAAU,UAAYA,EAAM,KAAA,EAAO,OAAS,IACrDF,EAAOC,CAAM,EAAIC,EAAM,KAAA,EAE3B,CACA,OAAOF,CACT,CC7CO,SAASG,GAA2C,CACzD,KAAM,CAAE,KAAMC,CAAA,EAAaC,EAAA,EAE3B,OAAOC,EAAAA,QAAQ,IAAM,OAEnB,SADgBC,EAAAH,GAAA,YAAAA,EAAU,aAAV,YAAAG,EAAsB,iBAAkBC,GACzC,IAAKC,IAAO,CACzB,MAAO,OAAOA,CAAC,EACf,MAAOC,EAAoBD,CAAC,CAAA,EAC5B,CACJ,EAAG,CAACL,CAAQ,CAAC,CACf,CCrBA,MAAMO,EAAQ,CACZ,CAAE,MAAO,EAAG,MAAO,SAAA,EACnB,CAAE,MAAO,GAAI,MAAO,OAAA,CACtB,EAYO,SAASC,EAAqB,CACnC,SAAAC,EACA,QAAAC,EACA,UAAAC,EACA,cAAeC,EAAS,uBAC1B,EAA8B,CAC5B,KAAM,CAACC,EAAUC,CAAW,EAAIC,EAAAA,SAAS,EAAE,EACrC,CAACC,EAAYC,CAAa,EAAIF,EAAAA,SAAS,CAAC,EAE9CG,EAAAA,UAAU,IAAM,CACd,MAAMC,EAAI,SAASN,CAAQ,EAC3BJ,EAASU,EAAI,EAAIA,EAAIH,EAAa,CAAC,CACrC,EAAG,CAACH,EAAUG,EAAYP,CAAQ,CAAC,EAEnC,MAAMW,EAAWV,EAAU,UAAY,UACjCW,EAAaX,EAAU,OAAS,OAEtC,OACErB,EAAAA,KAAC,MAAA,CAAI,UAAU,0BAA0B,cAAauB,EACpD,SAAA,CAAAzB,EAAAA,IAAC,QAAA,CACC,KAAK,SACL,IAAK,EACL,IAAK6B,IAAe,GAAK,GAAK,KAC9B,MAAOH,EACP,SAAWS,GAAMR,EAAYQ,EAAE,OAAO,KAAK,EAC3C,YAAaN,IAAe,GAAK,MAAQ,MACzC,UAAW,SAASI,CAAQ,IAAIC,CAAU,eAC1C,UAAAV,EACA,cAAa,GAAGC,CAAM,WAAA,CAAA,EAExBzB,EAAAA,IAAC,SAAA,CACC,MAAO6B,EACP,SAAWM,GAAML,EAAc,SAASK,EAAE,OAAO,KAAK,CAAC,EACvD,UAAW,UAAUF,CAAQ,QAC7B,cAAa,GAAGR,CAAM,QAErB,SAAAL,EAAM,IAAKgB,GACVpC,EAAAA,IAAC,SAAA,CAAqB,MAAOoC,EAAE,MAAQ,SAAAA,EAAE,KAAA,EAA5BA,EAAE,KAAgC,CAChD,CAAA,CAAA,CACH,EACF,CAEJ,CCjCO,SAASC,EAAgB,CAC9B,KAAAhD,EACA,QAAAC,EACA,cAAAE,EACA,cAAA8C,EACA,SAAAC,EACA,UAAA9C,EACA,aAAA+C,EAAe,EACf,OAAAC,EAAS,IACX,EAAyB,CACvB,KAAM,CAAE,aAAAC,CAAA,EAAiBC,EAAA,EACnBC,EAAiBhC,EAAA,EACjB,CAACiC,EAAMC,CAAO,EAAIlB,EAAAA,SAA8B,MAAM,EACtD,CAACmB,EAAcC,CAAe,EAAIpB,EAAAA,SAA8B,IAAI,EACpE,CAACqB,EAAQC,CAAS,EAAItB,EAAAA,SAAS,EAAE,EACjC,CAACuB,EAAUC,CAAW,EAAIxB,EAAAA,SAAS,IAAI,EACvC,CAACyB,EAAeC,CAAgB,EAAI1B,EAAAA,SAAS,CAAC,EAC9C,CAAC2B,EAAUC,CAAW,EAAI5B,EAAAA,SAAS,EAAK,EACxC6B,EAAiBC,EAAAA,YAAaxC,GAAcoC,EAAiBpC,CAAC,EAAG,EAAE,EAGnEyC,EACJ,CAACjB,GAAgBJ,EAAc,SAAW,EAAIA,EAAc,CAAC,EAAI,OAI7DsB,EAAkBC,EAAkBZ,EAAQ,GAAG,EAC/C,CAAE,KAAMa,EAAW,UAAWC,CAAA,EAAiBC,EAAS,CAC5D,KAAML,EACN,OAAQ,SACR,OAAQC,EAAgB,KAAA,GAAU,OAClC,MAAO,GAAA,EACN,CAAE,QAASvE,EAAM,EAEd4E,GAAQH,GAAA,YAAAA,EAAW,QAAS,CAAA,EAE5BI,EAAc,IAAM,CACxBpB,EAAQ,MAAM,EACdE,EAAgB,IAAI,EACpBE,EAAU,EAAE,EACZE,EAAY,IAAI,EAChBE,EAAiB,CAAC,EAClBE,EAAY,EAAK,EACjBlE,EAAA,CACF,EAEM6E,EAAoBC,GAAuB,CAC/CpB,EAAgBoB,CAAI,EACpBtB,EAAQ,UAAU,CACpB,EAEMuB,EAAa,IAAM,CACvBvB,EAAQ,MAAM,CAChB,EAEMwB,EAAe,IAAM,CACzB,GAAI,CAACvB,EAAc,OACnB,MAAMwB,EAAUpB,IAAa,SAAWE,EAAgB,SAASF,CAAQ,EACrE,CAACoB,GAAWA,GAAW,GAC3BhC,EAASQ,EAAa,GAAIwB,EAAShB,CAAQ,CAC7C,EAEA,OACEvD,EAAAA,IAACC,EAAA,CAAM,KAAAZ,EAAY,QAAS6E,EAAa,MAAM,qBAC7C,SAAAhE,EAAAA,KAAC,MAAA,CAAI,UAAU,YACZ,SAAA,CAAA2C,IAAS,QACR3C,EAAAA,KAAAsE,EAAAA,SAAA,CACE,SAAA,CAAAtE,EAAAA,KAAC,IAAA,CAAE,UAAU,8BAA8B,SAAA,CAAA,0BACjB,IACxBF,EAAAA,IAAC,OAAA,CAAK,UAAU,gCACb,SAAAR,EACH,EAAQ,IAAI,mBAAA,EAEd,EAEAQ,EAAAA,IAAC,QAAA,CACC,KAAK,OACL,MAAOiD,EACP,SAAWd,GAAMe,EAAUf,EAAE,OAAO,KAAK,EACzC,YAAY,6BACZ,UAAU,uBACV,UAAS,EAAA,CAAA,EAGXjC,EAAAA,KAAC,MAAA,CAAI,UAAU,kGACZ,SAAA,CAAA6D,GACC/D,EAAAA,IAAC,IAAA,CAAE,UAAU,iCAAiC,SAAA,mBAE9C,EAED,CAAC+D,GAAgBE,EAAM,SAAW,GACjCjE,EAAAA,IAAC,IAAA,CAAE,UAAU,iCAAiC,SAAA,gBAAA,CAE9C,EAEDiE,EAAM,IAAKG,GACVlE,EAAAA,KAAC,SAAA,CAEC,QAAS,IAAMiE,EAAiBC,CAAI,EACpC,UAAU,sEAEV,SAAA,CAAApE,MAAC,KAAE,UAAU,wCACV,SAAAoE,EAAK,cAAgBA,EAAK,YAC7B,EACCA,EAAK,OACJpE,EAAAA,IAAC,KAAE,UAAU,8BACV,WAAK,KAAA,CACR,CAAA,CAAA,EAVGoE,EAAK,EAAA,CAab,CAAA,EACH,EAEApE,EAAAA,IAAC,MAAA,CAAI,UAAU,wBACb,SAAAA,EAAAA,IAAC,SAAA,CAAO,QAASkE,EAAa,UAAU,wBAAwB,SAAA,QAAA,CAEhE,CAAA,CACF,CAAA,EACF,EAGDrB,IAAS,YAAcE,GACtB7C,EAAAA,KAAAsE,EAAAA,SAAA,CACE,SAAA,CAAAtE,EAAAA,KAAC,IAAA,CAAE,UAAU,8BAA8B,SAAA,CAAA,YAC/B,UACT,OAAA,CAAK,UAAU,gCACb,SAAA6C,EAAa,cAAgBA,EAAa,YAC7C,EAAQ,IAAI,MAAA,EAEd,EAEA7C,EAAAA,KAAC,SAAA,CACC,MAAOiD,EACP,SAAWhB,GAAM,CAAEiB,EAAYjB,EAAE,OAAO,KAAK,EAAGmB,EAAiB,CAAC,CAAG,EACrE,UAAU,wBAET,SAAA,CAAAV,EAAe,IAAK6B,GACnBzE,EAAAA,IAAC,SAAA,CAAuB,MAAOyE,EAAI,MAChC,SAAAA,EAAI,KAAA,EADMA,EAAI,KAEjB,CACD,EACDzE,EAAAA,IAAC,SAAA,CAAO,MAAM,SAAS,SAAA,UAAA,CAAQ,CAAA,CAAA,CAAA,EAEhCmD,IAAa,UACZnD,EAAAA,IAACqB,GAAqB,SAAUoC,EAAgB,UAAS,GAAC,EAG3DjB,EAAe,GACdtC,OAAC,QAAA,CAAM,UAAU,qDACf,SAAA,CAAAF,EAAAA,IAAC,QAAA,CACC,KAAK,WACL,QAASuD,EACT,SAAWpB,GAAMqB,EAAYrB,EAAE,OAAO,OAAO,EAC7C,UAAU,QAAA,CAAA,SAEX,OAAA,CAAK,SAAA,CAAA,iBACUnC,EAAAA,IAAC,OAAA,CAAK,UAAU,gCAAiC,SAAAwC,EAAa,EAAQ,IAAI,8FAAA,CAAA,CAG1F,CAAA,EACF,EAGDC,GAAUA,EAAO,QAAU,UACzB,IAAA,CAAE,UAAU,8BAA8B,cAAY,mBAAmB,SAAA,CAAA,YAC9DA,EAAO,SAAS,cAAYA,EAAO,QAAQ,oBAAA,EACvD,EAGFvC,EAAAA,KAAC,MAAA,CAAI,UAAU,8BACb,SAAA,CAAAF,MAAC,SAAA,CAAO,QAASqE,EAAY,UAAU,wBAAwB,SAAA,OAE/D,EACArE,EAAAA,IAAC,SAAA,CACC,QAASsE,EACT,SAAU7E,EACV,UAAU,sBAET,WAAY,eAAiB,QAAA,CAAA,CAChC,CAAA,CACF,CAAA,CAAA,CACF,CAAA,CAAA,CAEJ,CAAA,CACF,CAEJ"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{a as i,j as e}from"./vendor-query-DvWWuNIB.js";import{u as I}from"./capabilities-ZdLv9xBQ.js";import{T as w,S}from"./ToolTestPanel-BLfA02wv.js";import{T as k}from"./ToolPill-Baxm02L6.js";import{P}from"./PageHeader-Csq434-v.js";import{F as E,b as T,a as L}from"./FilterBar-CvMBCVIo.js";import{aK as R}from"./index-CgUcYveM.js";import{L as A,x as O,bY as K,l as $,bk as q,q as D,bb as F,E as Y,a2 as B,j as M}from"./vendor-icons-B7OcUM6b.js";import"./mcp-Bix7QYO7.js";import"./RunAsSelector-BoePhWVD.js";import"./BotPicker-D3drO3-T.js";import"./bots-DX6jjqtF.js";import"./vendor-react-_9U4mKFr.js";import"./helpers-DzO-OGPe.js";const y={Communication:B,Analysis:Y,Media:F,Data:D,Automation:q,Development:$,System:K,Reference:O,Other:A},p="capability-run";function ae(){const{data:n,isLoading:c}=I(),a=R(),[l,N]=i.useState(""),[m,g]=i.useState(null),[t,x]=i.useState(null),u=(n==null?void 0:n.categories)??[],C=(n==null?void 0:n.totalTools)??0,j=i.useMemo(()=>{let s=u;if(m&&(s=s.filter(r=>r.name===m)),!l.trim())return s;const o=l.toLowerCase();return s.map(r=>({...r,tools:r.tools.filter(v=>v.name.toLowerCase().includes(o)||v.description.toLowerCase().includes(o)||v.serverName.toLowerCase().includes(o))})).filter(r=>r.tools.length>0)},[u,l,m]),f=t?`${t.serverId}:${t.tool.name}`:null,h=i.useRef(null),d=i.useRef(!1);i.useEffect(()=>{a&&f!==h.current&&(h.current=f,t?a.setPanel(e.jsx("div",{className:"h-full overflow-y-auto",children:e.jsx(w,{serverId:t.serverId,serverName:t.serverName,tool:t.tool,onClose:()=>x(null)})}),{key:p,width:420}):(d.current=!1,a.closePanel(p)))},[t,f,a]),i.useEffect(()=>{if(!(!a||!t)){if(a.open&&a.ownerKey===p){d.current=!0;return}d.current&&(d.current=!1,x(null))}},[a,t]);const b=i.useRef(a);return b.current=a,i.useEffect(()=>()=>{var s;h.current&&((s=b.current)==null||s.closePanel(p))},[]),e.jsxs("div",{children:[e.jsx(P,{title:"Capabilities"}),!c&&u.length>0&&e.jsxs(E,{children:[e.jsx(T,{label:"Category",value:m??"",onChange:s=>g(s||null),options:u.map(s=>({value:s.name,label:s.name}))}),e.jsx(L,{label:"Search",value:l,onChange:N,placeholder:`${C} capabilities…`})]}),c?e.jsx("div",{className:"animate-pulse space-y-8",children:[1,2,3].map(s=>e.jsxs("div",{children:[e.jsx("div",{className:"h-4 bg-surface-sunken rounded w-28 mb-4"}),e.jsx("div",{className:"space-y-3",children:[1,2,3].map(o=>e.jsxs("div",{className:"space-y-1.5",children:[e.jsx("div",{className:"h-4 bg-surface-sunken rounded w-36"}),e.jsx("div",{className:"h-3 bg-surface-sunken rounded w-full"})]},o))})]},s))}):j.length===0?e.jsx("p",{className:"text-sm text-text-tertiary mt-8",children:l||m?"No capabilities match your filter.":"No capabilities registered yet."}):e.jsx("div",{className:"space-y-10",children:j.map(s=>{const o=y[s.name]??y.Other;return e.jsxs("div",{children:[e.jsxs("div",{className:"sticky top-[60px] z-10 bg-surface flex items-center gap-2 py-2 mb-2 border-b border-surface-border",children:[e.jsx(o,{className:"w-3 h-3 text-accent",strokeWidth:1.5}),e.jsx("h2",{className:"section-h2",children:s.name}),e.jsx("span",{className:"text-xs text-text-quaternary",children:s.tools.length})]}),e.jsx("div",{className:"divide-y divide-surface-border/30",children:s.tools.map(r=>e.jsx(W,{tool:r,isSelected:(t==null?void 0:t.tool.name)===r.name&&(t==null?void 0:t.serverId)===r.serverId,onSelect:()=>x({serverId:r.serverId,serverName:r.serverName,tool:{name:r.name,description:r.description,inputSchema:r.inputSchema}})},`${r.serverId}-${r.name}`))})]},s.name)})})]})}function W({tool:n,isSelected:c,onSelect:a}){return e.jsxs("div",{role:"button",tabIndex:0,onClick:a,onKeyDown:l=>{(l.key==="Enter"||l.key===" ")&&a()},className:"group relative py-2 px-3 -mx-3 rounded-md cursor-pointer hover:bg-surface-hover/30 transition-colors text-left",children:[c&&e.jsx("span",{className:"absolute left-0 top-1 bottom-1 w-0.5 bg-accent rounded-full"}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(k,{name:n.name,size:"md"}),e.jsx("p",{className:"flex-1 min-w-0 truncate text-2xs text-text-tertiary group-hover:text-text-secondary transition-colors",children:n.description}),e.jsxs("div",{className:"flex items-center gap-2 shrink-0",children:[e.jsx(S,{name:n.serverName,serverId:n.serverId}),e.jsx("span",{title:"Try it",children:e.jsx(M,{className:`w-3 h-3 transition-opacity ${c?"text-accent opacity-100":"text-accent opacity-0 group-hover:opacity-100"}`,strokeWidth:1.5})})]})]})]})}export{ae as CapabilitiesPage};
|
|
2
|
+
//# sourceMappingURL=CapabilitiesPage-RGgD3YZO.js.map
|
package/dashboard/dist/assets/{CapabilitiesPage-F8dpNn9B.js.map → CapabilitiesPage-RGgD3YZO.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CapabilitiesPage-F8dpNn9B.js","sources":["../../src/pages/capabilities/CapabilitiesPage.tsx"],"sourcesContent":["import { useState, useMemo, useEffect, useRef } from 'react';\nimport {\n Play,\n MessageSquare, Eye, Database, Cog, Code2, Shield, BookOpen,\n LayoutGrid, Image,\n} from 'lucide-react';\nimport { useCapabilities, type CapabilityTool } from '../../api/capabilities';\nimport { ToolTestPanel } from '../../components/common/test/ToolTestPanel';\nimport { ToolPill } from '../../components/common/display/ToolPill';\nimport { ServerName } from '../../components/common/display/ServerName';\nimport { PageHeader } from '../../components/common/layout/PageHeader';\nimport { FilterBar, FilterSelect, FilterInput } from '../../components/common/data/FilterBar';\nimport { useShellPanelOptional } from '../../hooks/useShellPanel';\nimport type { LucideIcon } from 'lucide-react';\n\n// ── Category meta ─────────────────────────────────────────────────────────────\n\nconst CATEGORY_ICONS: Record<string, LucideIcon> = {\n Communication: MessageSquare,\n Analysis: Eye,\n Media: Image,\n Data: Database,\n Automation: Cog,\n Development: Code2,\n System: Shield,\n Reference: BookOpen,\n Other: LayoutGrid,\n};\n\n// Shell-panel ownership key — the tool run panel claims/releases this slot.\nconst CAPABILITY_PANEL_KEY = 'capability-run';\n\ninterface SelectedTool {\n serverId: string;\n serverName: string;\n tool: { name: string; description: string; inputSchema: Record<string, any> };\n}\n\n// ── Page ─────────────────────────────────────────────────────────────────────\n\nexport function CapabilitiesPage() {\n const { data, isLoading } = useCapabilities();\n const shell = useShellPanelOptional();\n const [search, setSearch] = useState('');\n const [activeCategory, setActiveCategory] = useState<string | null>(null);\n const [selected, setSelected] = useState<SelectedTool | null>(null);\n\n const categories = data?.categories ?? [];\n const totalTools = data?.totalTools ?? 0;\n\n const filtered = useMemo(() => {\n let cats = categories;\n if (activeCategory) cats = cats.filter((c) => c.name === activeCategory);\n if (!search.trim()) return cats;\n const q = search.toLowerCase();\n return cats\n .map((cat) => ({\n ...cat,\n tools: cat.tools.filter(\n (t) =>\n t.name.toLowerCase().includes(q) ||\n t.description.toLowerCase().includes(q) ||\n t.serverName.toLowerCase().includes(q),\n ),\n }))\n .filter((cat) => cat.tools.length > 0);\n }, [categories, search, activeCategory]);\n\n // ── Selection ↔ shell panel sync ────────────────────────────────────────────\n // Selecting a tool opens the run panel in the shell's right slot; an\n // external close (the panel's X, slot takeover) clears the selection. The\n // applied-key ref guards against re-setting the panel on unrelated renders.\n const selectedKey = selected ? `${selected.serverId}:${selected.tool.name}` : null;\n const appliedKey = useRef<string | null>(null);\n const panelWasOpen = useRef(false);\n useEffect(() => {\n if (!shell) return;\n if (selectedKey === appliedKey.current) return;\n appliedKey.current = selectedKey;\n if (selected) {\n shell.setPanel(\n <div className=\"h-full overflow-y-auto\">\n <ToolTestPanel\n serverId={selected.serverId}\n serverName={selected.serverName}\n tool={selected.tool}\n onClose={() => setSelected(null)}\n />\n </div>,\n { key: CAPABILITY_PANEL_KEY, width: 420 },\n );\n } else {\n panelWasOpen.current = false;\n shell.closePanel(CAPABILITY_PANEL_KEY);\n }\n }, [selected, selectedKey, shell]);\n useEffect(() => {\n if (!shell || !selected) return;\n if (shell.open && shell.ownerKey === CAPABILITY_PANEL_KEY) {\n panelWasOpen.current = true;\n return;\n }\n if (panelWasOpen.current) {\n panelWasOpen.current = false;\n setSelected(null);\n }\n }, [shell, selected]);\n // Unmount with the panel open releases the slot (keyed — never yanks\n // another claimant's panel).\n const shellRef = useRef(shell);\n shellRef.current = shell;\n useEffect(\n () => () => {\n if (appliedKey.current) shellRef.current?.closePanel(CAPABILITY_PANEL_KEY);\n },\n [],\n );\n\n return (\n <div>\n <PageHeader title=\"Capabilities\" />\n\n {/* The standard full-width sticky filter band — above the list, like\n every other master list page. */}\n {!isLoading && categories.length > 0 && (\n <FilterBar>\n <FilterSelect\n label=\"Category\"\n value={activeCategory ?? ''}\n onChange={(v) => setActiveCategory(v || null)}\n options={categories.map((c) => ({ value: c.name, label: c.name }))}\n />\n <FilterInput\n label=\"Search\"\n value={search}\n onChange={setSearch}\n placeholder={`${totalTools} capabilities…`}\n />\n </FilterBar>\n )}\n\n {/* The list IS the page — selecting a row opens the run panel in the\n shell's right panel. */}\n {isLoading ? (\n <div className=\"animate-pulse space-y-8\">\n {[1, 2, 3].map((i) => (\n <div key={i}>\n <div className=\"h-4 bg-surface-sunken rounded w-28 mb-4\" />\n <div className=\"space-y-3\">\n {[1, 2, 3].map((j) => (\n <div key={j} className=\"space-y-1.5\">\n <div className=\"h-4 bg-surface-sunken rounded w-36\" />\n <div className=\"h-3 bg-surface-sunken rounded w-full\" />\n </div>\n ))}\n </div>\n </div>\n ))}\n </div>\n ) : filtered.length === 0 ? (\n <p className=\"text-sm text-text-tertiary mt-8\">\n {search || activeCategory ? 'No capabilities match your filter.' : 'No capabilities registered yet.'}\n </p>\n ) : (\n <div className=\"space-y-10\">\n {filtered.map((category) => {\n const Icon = CATEGORY_ICONS[category.name] ?? CATEGORY_ICONS.Other;\n return (\n <div key={category.name}>\n <div className=\"sticky top-[60px] z-10 bg-surface flex items-center gap-2 py-2 mb-2 border-b border-surface-border\">\n <Icon className=\"w-3 h-3 text-accent\" strokeWidth={1.5} />\n <h2 className=\"section-h2\">{category.name}</h2>\n <span className=\"text-xs text-text-quaternary\">{category.tools.length}</span>\n </div>\n <div className=\"divide-y divide-surface-border/30\">\n {category.tools.map((tool) => (\n <ToolRow\n key={`${tool.serverId}-${tool.name}`}\n tool={tool}\n isSelected={selected?.tool.name === tool.name && selected?.serverId === tool.serverId}\n onSelect={() =>\n setSelected({\n serverId: tool.serverId,\n serverName: tool.serverName,\n tool: { name: tool.name, description: tool.description, inputSchema: tool.inputSchema },\n })\n }\n />\n ))}\n </div>\n </div>\n );\n })}\n </div>\n )}\n </div>\n );\n}\n\n// ── Tool row ─────────────────────────────────────────────────────────────────\n\nfunction ToolRow({\n tool,\n isSelected,\n onSelect,\n}: {\n tool: CapabilityTool;\n isSelected: boolean;\n onSelect: () => void;\n}) {\n return (\n <div\n role=\"button\"\n tabIndex={0}\n onClick={onSelect}\n onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') onSelect(); }}\n className=\"group relative py-2 px-3 -mx-3 rounded-md cursor-pointer hover:bg-surface-hover/30 transition-colors text-left\"\n >\n {isSelected && <span className=\"absolute left-0 top-1 bottom-1 w-0.5 bg-accent rounded-full\" />}\n <div className=\"flex items-center gap-3\">\n <ToolPill name={tool.name} size=\"md\" />\n <p className=\"flex-1 min-w-0 truncate text-2xs text-text-tertiary group-hover:text-text-secondary transition-colors\">\n {tool.description}\n </p>\n <div className=\"flex items-center gap-2 shrink-0\">\n <ServerName name={tool.serverName} serverId={tool.serverId} />\n {/* Trailing action icon — quiet until row hover, visible on the\n selected row. Selecting opens the run panel in the shell panel. */}\n <span title=\"Try it\">\n <Play\n className={`w-3 h-3 transition-opacity ${isSelected ? 'text-accent opacity-100' : 'text-accent opacity-0 group-hover:opacity-100'}`}\n strokeWidth={1.5}\n />\n </span>\n </div>\n </div>\n </div>\n );\n}\n"],"names":["CATEGORY_ICONS","MessageSquare","Eye","Image","Database","Cog","Code2","Shield","BookOpen","LayoutGrid","CAPABILITY_PANEL_KEY","CapabilitiesPage","data","isLoading","useCapabilities","shell","useShellPanelOptional","search","setSearch","useState","activeCategory","setActiveCategory","selected","setSelected","categories","totalTools","filtered","useMemo","cats","c","q","cat","t","selectedKey","appliedKey","useRef","panelWasOpen","useEffect","jsx","ToolTestPanel","shellRef","_a","PageHeader","FilterBar","FilterSelect","v","FilterInput","i","j","jsxs","category","Icon","tool","ToolRow","isSelected","onSelect","e","ToolPill","ServerName","Play"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CapabilitiesPage-RGgD3YZO.js","sources":["../../src/pages/capabilities/CapabilitiesPage.tsx"],"sourcesContent":["import { useState, useMemo, useEffect, useRef } from 'react';\nimport {\n Play,\n MessageSquare, Eye, Database, Cog, Code2, Shield, BookOpen,\n LayoutGrid, Image,\n} from 'lucide-react';\nimport { useCapabilities, type CapabilityTool } from '../../api/capabilities';\nimport { ToolTestPanel } from '../../components/common/test/ToolTestPanel';\nimport { ToolPill } from '../../components/common/display/ToolPill';\nimport { ServerName } from '../../components/common/display/ServerName';\nimport { PageHeader } from '../../components/common/layout/PageHeader';\nimport { FilterBar, FilterSelect, FilterInput } from '../../components/common/data/FilterBar';\nimport { useShellPanelOptional } from '../../hooks/useShellPanel';\nimport type { LucideIcon } from 'lucide-react';\n\n// ── Category meta ─────────────────────────────────────────────────────────────\n\nconst CATEGORY_ICONS: Record<string, LucideIcon> = {\n Communication: MessageSquare,\n Analysis: Eye,\n Media: Image,\n Data: Database,\n Automation: Cog,\n Development: Code2,\n System: Shield,\n Reference: BookOpen,\n Other: LayoutGrid,\n};\n\n// Shell-panel ownership key — the tool run panel claims/releases this slot.\nconst CAPABILITY_PANEL_KEY = 'capability-run';\n\ninterface SelectedTool {\n serverId: string;\n serverName: string;\n tool: { name: string; description: string; inputSchema: Record<string, any> };\n}\n\n// ── Page ─────────────────────────────────────────────────────────────────────\n\nexport function CapabilitiesPage() {\n const { data, isLoading } = useCapabilities();\n const shell = useShellPanelOptional();\n const [search, setSearch] = useState('');\n const [activeCategory, setActiveCategory] = useState<string | null>(null);\n const [selected, setSelected] = useState<SelectedTool | null>(null);\n\n const categories = data?.categories ?? [];\n const totalTools = data?.totalTools ?? 0;\n\n const filtered = useMemo(() => {\n let cats = categories;\n if (activeCategory) cats = cats.filter((c) => c.name === activeCategory);\n if (!search.trim()) return cats;\n const q = search.toLowerCase();\n return cats\n .map((cat) => ({\n ...cat,\n tools: cat.tools.filter(\n (t) =>\n t.name.toLowerCase().includes(q) ||\n t.description.toLowerCase().includes(q) ||\n t.serverName.toLowerCase().includes(q),\n ),\n }))\n .filter((cat) => cat.tools.length > 0);\n }, [categories, search, activeCategory]);\n\n // ── Selection ↔ shell panel sync ────────────────────────────────────────────\n // Selecting a tool opens the run panel in the shell's right slot; an\n // external close (the panel's X, slot takeover) clears the selection. The\n // applied-key ref guards against re-setting the panel on unrelated renders.\n const selectedKey = selected ? `${selected.serverId}:${selected.tool.name}` : null;\n const appliedKey = useRef<string | null>(null);\n const panelWasOpen = useRef(false);\n useEffect(() => {\n if (!shell) return;\n if (selectedKey === appliedKey.current) return;\n appliedKey.current = selectedKey;\n if (selected) {\n shell.setPanel(\n <div className=\"h-full overflow-y-auto\">\n <ToolTestPanel\n serverId={selected.serverId}\n serverName={selected.serverName}\n tool={selected.tool}\n onClose={() => setSelected(null)}\n />\n </div>,\n { key: CAPABILITY_PANEL_KEY, width: 420 },\n );\n } else {\n panelWasOpen.current = false;\n shell.closePanel(CAPABILITY_PANEL_KEY);\n }\n }, [selected, selectedKey, shell]);\n useEffect(() => {\n if (!shell || !selected) return;\n if (shell.open && shell.ownerKey === CAPABILITY_PANEL_KEY) {\n panelWasOpen.current = true;\n return;\n }\n if (panelWasOpen.current) {\n panelWasOpen.current = false;\n setSelected(null);\n }\n }, [shell, selected]);\n // Unmount with the panel open releases the slot (keyed — never yanks\n // another claimant's panel).\n const shellRef = useRef(shell);\n shellRef.current = shell;\n useEffect(\n () => () => {\n if (appliedKey.current) shellRef.current?.closePanel(CAPABILITY_PANEL_KEY);\n },\n [],\n );\n\n return (\n <div>\n <PageHeader title=\"Capabilities\" />\n\n {/* The standard full-width sticky filter band — above the list, like\n every other master list page. */}\n {!isLoading && categories.length > 0 && (\n <FilterBar>\n <FilterSelect\n label=\"Category\"\n value={activeCategory ?? ''}\n onChange={(v) => setActiveCategory(v || null)}\n options={categories.map((c) => ({ value: c.name, label: c.name }))}\n />\n <FilterInput\n label=\"Search\"\n value={search}\n onChange={setSearch}\n placeholder={`${totalTools} capabilities…`}\n />\n </FilterBar>\n )}\n\n {/* The list IS the page — selecting a row opens the run panel in the\n shell's right panel. */}\n {isLoading ? (\n <div className=\"animate-pulse space-y-8\">\n {[1, 2, 3].map((i) => (\n <div key={i}>\n <div className=\"h-4 bg-surface-sunken rounded w-28 mb-4\" />\n <div className=\"space-y-3\">\n {[1, 2, 3].map((j) => (\n <div key={j} className=\"space-y-1.5\">\n <div className=\"h-4 bg-surface-sunken rounded w-36\" />\n <div className=\"h-3 bg-surface-sunken rounded w-full\" />\n </div>\n ))}\n </div>\n </div>\n ))}\n </div>\n ) : filtered.length === 0 ? (\n <p className=\"text-sm text-text-tertiary mt-8\">\n {search || activeCategory ? 'No capabilities match your filter.' : 'No capabilities registered yet.'}\n </p>\n ) : (\n <div className=\"space-y-10\">\n {filtered.map((category) => {\n const Icon = CATEGORY_ICONS[category.name] ?? CATEGORY_ICONS.Other;\n return (\n <div key={category.name}>\n <div className=\"sticky top-[60px] z-10 bg-surface flex items-center gap-2 py-2 mb-2 border-b border-surface-border\">\n <Icon className=\"w-3 h-3 text-accent\" strokeWidth={1.5} />\n <h2 className=\"section-h2\">{category.name}</h2>\n <span className=\"text-xs text-text-quaternary\">{category.tools.length}</span>\n </div>\n <div className=\"divide-y divide-surface-border/30\">\n {category.tools.map((tool) => (\n <ToolRow\n key={`${tool.serverId}-${tool.name}`}\n tool={tool}\n isSelected={selected?.tool.name === tool.name && selected?.serverId === tool.serverId}\n onSelect={() =>\n setSelected({\n serverId: tool.serverId,\n serverName: tool.serverName,\n tool: { name: tool.name, description: tool.description, inputSchema: tool.inputSchema },\n })\n }\n />\n ))}\n </div>\n </div>\n );\n })}\n </div>\n )}\n </div>\n );\n}\n\n// ── Tool row ─────────────────────────────────────────────────────────────────\n\nfunction ToolRow({\n tool,\n isSelected,\n onSelect,\n}: {\n tool: CapabilityTool;\n isSelected: boolean;\n onSelect: () => void;\n}) {\n return (\n <div\n role=\"button\"\n tabIndex={0}\n onClick={onSelect}\n onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') onSelect(); }}\n className=\"group relative py-2 px-3 -mx-3 rounded-md cursor-pointer hover:bg-surface-hover/30 transition-colors text-left\"\n >\n {isSelected && <span className=\"absolute left-0 top-1 bottom-1 w-0.5 bg-accent rounded-full\" />}\n <div className=\"flex items-center gap-3\">\n <ToolPill name={tool.name} size=\"md\" />\n <p className=\"flex-1 min-w-0 truncate text-2xs text-text-tertiary group-hover:text-text-secondary transition-colors\">\n {tool.description}\n </p>\n <div className=\"flex items-center gap-2 shrink-0\">\n <ServerName name={tool.serverName} serverId={tool.serverId} />\n {/* Trailing action icon — quiet until row hover, visible on the\n selected row. Selecting opens the run panel in the shell panel. */}\n <span title=\"Try it\">\n <Play\n className={`w-3 h-3 transition-opacity ${isSelected ? 'text-accent opacity-100' : 'text-accent opacity-0 group-hover:opacity-100'}`}\n strokeWidth={1.5}\n />\n </span>\n </div>\n </div>\n </div>\n );\n}\n"],"names":["CATEGORY_ICONS","MessageSquare","Eye","Image","Database","Cog","Code2","Shield","BookOpen","LayoutGrid","CAPABILITY_PANEL_KEY","CapabilitiesPage","data","isLoading","useCapabilities","shell","useShellPanelOptional","search","setSearch","useState","activeCategory","setActiveCategory","selected","setSelected","categories","totalTools","filtered","useMemo","cats","c","q","cat","t","selectedKey","appliedKey","useRef","panelWasOpen","useEffect","jsx","ToolTestPanel","shellRef","_a","PageHeader","FilterBar","FilterSelect","v","FilterInput","i","j","jsxs","category","Icon","tool","ToolRow","isSelected","onSelect","e","ToolPill","ServerName","Play"],"mappings":"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"}
|
package/dashboard/dist/assets/{CollapsibleSection-BZW6VpCU.js → CollapsibleSection-DNkZn87n.js}
RENAMED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{j as t}from"./vendor-query-DvWWuNIB.js";import{C as a}from"./index-
|
|
2
|
-
//# sourceMappingURL=CollapsibleSection-
|
|
1
|
+
import{j as t}from"./vendor-query-DvWWuNIB.js";import{C as a}from"./index-CgUcYveM.js";function c({title:r,sectionKey:s,isCollapsed:e,onToggle:o,contentClassName:n,children:i}){return t.jsxs("div",{children:[t.jsxs("button",{onClick:()=>o(s),className:"flex items-center gap-3 w-full group/section",children:[t.jsx("svg",{className:`w-4 h-4 shrink-0 text-text-tertiary/40 group-hover/section:text-text-tertiary transition-all duration-200 ${e?"":"rotate-90"}`,fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,children:t.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M9 5l7 7-7 7"})}),t.jsx("span",{className:`text-xs font-semibold uppercase tracking-widest transition-colors duration-200 ${e?"text-text-tertiary":"text-text-secondary"}`,children:r}),t.jsx("span",{className:"flex-1 border-b border-surface-border"})]}),t.jsx(a,{open:!e,children:t.jsx("div",{className:n??"mt-4 ml-7",children:i})})]})}export{c as C};
|
|
2
|
+
//# sourceMappingURL=CollapsibleSection-DNkZn87n.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CollapsibleSection-
|
|
1
|
+
{"version":3,"file":"CollapsibleSection-DNkZn87n.js","sources":["../../src/components/common/layout/CollapsibleSection.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { Collapsible } from './Collapsible';\n\n/**\n * Shared collapsible section with chevron toggle and horizontal rule.\n * Used by WorkflowExecutionPage, McpRunDetailPage, and YamlWorkflowDetailPage.\n */\nexport function CollapsibleSection({\n title,\n sectionKey,\n isCollapsed,\n onToggle,\n contentClassName,\n children,\n}: {\n title: string;\n sectionKey: string;\n isCollapsed: boolean;\n onToggle: (key: string) => void;\n /** Optional class override for the content wrapper (default: \"mt-4 ml-7\") */\n contentClassName?: string;\n children: ReactNode;\n}) {\n return (\n <div>\n <button\n onClick={() => onToggle(sectionKey)}\n className=\"flex items-center gap-3 w-full group/section\"\n >\n <svg\n className={`w-4 h-4 shrink-0 text-text-tertiary/40 group-hover/section:text-text-tertiary transition-all duration-200 ${!isCollapsed ? 'rotate-90' : ''}`}\n fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M9 5l7 7-7 7\" />\n </svg>\n <span className={`text-xs font-semibold uppercase tracking-widest transition-colors duration-200 ${isCollapsed ? 'text-text-tertiary' : 'text-text-secondary'}`}>\n {title}\n </span>\n <span className=\"flex-1 border-b border-surface-border\" />\n </button>\n <Collapsible open={!isCollapsed}>\n <div className={contentClassName ?? 'mt-4 ml-7'}>{children}</div>\n </Collapsible>\n </div>\n );\n}\n"],"names":["CollapsibleSection","title","sectionKey","isCollapsed","onToggle","contentClassName","children","jsxs","jsx","Collapsible"],"mappings":"uFAOO,SAASA,EAAmB,CACjC,MAAAC,EACA,WAAAC,EACA,YAAAC,EACA,SAAAC,EACA,iBAAAC,EACA,SAAAC,CACF,EAQG,CACD,cACG,MAAA,CACC,SAAA,CAAAC,EAAAA,KAAC,SAAA,CACC,QAAS,IAAMH,EAASF,CAAU,EAClC,UAAU,+CAEV,SAAA,CAAAM,EAAAA,IAAC,MAAA,CACC,UAAW,6GAA8GL,EAA4B,GAAd,WAAgB,GACvJ,KAAK,OAAO,QAAQ,YAAY,OAAO,eAAe,YAAa,EAEnE,eAAC,OAAA,CAAK,cAAc,QAAQ,eAAe,QAAQ,EAAE,cAAA,CAAe,CAAA,CAAA,EAEtEK,EAAAA,IAAC,QAAK,UAAW,kFAAkFL,EAAc,qBAAuB,qBAAqB,GAC1J,SAAAF,CAAA,CACH,EACAO,EAAAA,IAAC,OAAA,CAAK,UAAU,uCAAA,CAAwC,CAAA,CAAA,CAAA,EAE1DA,EAAAA,IAACC,EAAA,CAAY,KAAM,CAACN,EAClB,SAAAK,EAAAA,IAAC,MAAA,CAAI,UAAWH,GAAoB,YAAc,SAAAC,CAAA,CAAS,CAAA,CAC7D,CAAA,EACF,CAEJ"}
|
package/dashboard/dist/assets/{ConfirmDeleteModal-64adXLdq.js → ConfirmDeleteModal-BqzOwhPr.js}
RENAMED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{j as e}from"./vendor-query-DvWWuNIB.js";import{M as i}from"./index-
|
|
2
|
-
//# sourceMappingURL=ConfirmDeleteModal-
|
|
1
|
+
import{j as e}from"./vendor-query-DvWWuNIB.js";import{M as i}from"./index-CgUcYveM.js";function d({open:r,onClose:t,onConfirm:x,title:n,description:c,isPending:s,error:a}){return e.jsx(i,{open:r,onClose:t,title:n,children:e.jsxs("div",{className:"space-y-4",children:[e.jsx("p",{className:"text-sm text-text-secondary",children:c}),a&&e.jsx("p",{className:"text-xs text-status-error",children:a.message}),e.jsxs("div",{className:"flex justify-end gap-3 pt-2",children:[e.jsx("button",{onClick:t,className:"btn-secondary text-xs",children:"Cancel"}),e.jsx("button",{onClick:x,className:"bg-status-error text-text-inverse px-3 py-1.5 rounded-md text-xs hover:opacity-90 transition-opacity",disabled:s,children:s?"Deleting...":"Delete"})]})]})})}export{d as C};
|
|
2
|
+
//# sourceMappingURL=ConfirmDeleteModal-BqzOwhPr.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConfirmDeleteModal-
|
|
1
|
+
{"version":3,"file":"ConfirmDeleteModal-BqzOwhPr.js","sources":["../../src/components/common/modal/ConfirmDeleteModal.tsx"],"sourcesContent":["import { Modal } from './Modal';\nimport type { ReactNode } from 'react';\n\ninterface ConfirmDeleteModalProps {\n open: boolean;\n onClose: () => void;\n onConfirm: () => void;\n title: string;\n description: ReactNode;\n isPending?: boolean;\n error?: Error | null;\n}\n\nexport function ConfirmDeleteModal({\n open,\n onClose,\n onConfirm,\n title,\n description,\n isPending,\n error,\n}: ConfirmDeleteModalProps) {\n return (\n <Modal open={open} onClose={onClose} title={title}>\n <div className=\"space-y-4\">\n <p className=\"text-sm text-text-secondary\">{description}</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} className=\"btn-secondary text-xs\">\n Cancel\n </button>\n <button\n onClick={onConfirm}\n className=\"bg-status-error text-text-inverse px-3 py-1.5 rounded-md text-xs hover:opacity-90 transition-opacity\"\n disabled={isPending}\n >\n {isPending ? 'Deleting...' : 'Delete'}\n </button>\n </div>\n </div>\n </Modal>\n );\n}\n"],"names":["ConfirmDeleteModal","open","onClose","onConfirm","title","description","isPending","error","jsx","Modal","jsxs"],"mappings":"uFAaO,SAASA,EAAmB,CACjC,KAAAC,EACA,QAAAC,EACA,UAAAC,EACA,MAAAC,EACA,YAAAC,EACA,UAAAC,EACA,MAAAC,CACF,EAA4B,CAC1B,OACEC,EAAAA,IAACC,GAAM,KAAAR,EAAY,QAAAC,EAAkB,MAAAE,EACnC,SAAAM,EAAAA,KAAC,MAAA,CAAI,UAAU,YACb,SAAA,CAAAF,EAAAA,IAAC,IAAA,CAAE,UAAU,8BAA+B,SAAAH,EAAY,EACvDE,GAASC,EAAAA,IAAC,IAAA,CAAE,UAAU,4BAA6B,WAAM,QAAQ,EAClEE,EAAAA,KAAC,MAAA,CAAI,UAAU,8BACb,SAAA,CAAAF,MAAC,SAAA,CAAO,QAASN,EAAS,UAAU,wBAAwB,SAAA,SAE5D,EACAM,EAAAA,IAAC,SAAA,CACC,QAASL,EACT,UAAU,uGACV,SAAUG,EAET,WAAY,cAAgB,QAAA,CAAA,CAC/B,CAAA,CACF,CAAA,CAAA,CACF,CAAA,CACF,CAEJ"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as r,j as n}from"./vendor-query-DvWWuNIB.js";import{
|
|
2
|
-
//# sourceMappingURL=CountdownTimer-
|
|
1
|
+
import{a as r,j as n}from"./vendor-query-DvWWuNIB.js";import{ba as c,az as m,bb as i}from"./index-CgUcYveM.js";const a=[{maxMs:0,color:"text-status-error"},{maxMs:300*1e3,color:"text-status-error"},{maxMs:900*1e3,color:"text-status-warning"},{maxMs:1/0,color:"text-text-secondary"}];function x(t){if(t<=0)return a[0].color;for(const e of a)if(t<e.maxMs)return e.color;return a[a.length-1].color}function M({until:t}){const[e,s]=r.useState(()=>new Date(t).getTime()-Date.now());r.useEffect(()=>{const o=setInterval(()=>{s(new Date(t).getTime()-Date.now())},1e3);return()=>clearInterval(o)},[t]);const l=r.useMemo(()=>{const o=new Date(t);return[{label:"ms",value:String(Math.max(0,e))},{label:"until",value:o.toISOString()},{label:"local",value:c(o,"MMM d, yyyy h:mm:ss a")}]},[t,e]);return n.jsx(m,{options:l,children:n.jsx("span",{className:`text-xs font-mono ${x(e)}`,children:i(e)})})}export{M as C};
|
|
2
|
+
//# sourceMappingURL=CountdownTimer-BaexQMK6.js.map
|
package/dashboard/dist/assets/{CountdownTimer-BxDub9d2.js.map → CountdownTimer-BaexQMK6.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CountdownTimer-
|
|
1
|
+
{"version":3,"file":"CountdownTimer-BaexQMK6.js","sources":["../../src/components/common/display/CountdownTimer.tsx"],"sourcesContent":["import { useState, useEffect, useMemo } from 'react';\nimport { format as fnsFormat } from 'date-fns';\nimport { formatRemaining } from '../../../lib/format';\nimport { DateTooltip } from './DateTooltip';\n\nconst COUNTDOWN_THRESHOLDS = [\n { maxMs: 0, color: 'text-status-error' },\n { maxMs: 5 * 60 * 1000, color: 'text-status-error' },\n { maxMs: 15 * 60 * 1000, color: 'text-status-warning' },\n { maxMs: Infinity, color: 'text-text-secondary' },\n] as const;\n\nfunction countdownColor(remainingMs: number): string {\n if (remainingMs <= 0) return COUNTDOWN_THRESHOLDS[0].color;\n for (const t of COUNTDOWN_THRESHOLDS) {\n if (remainingMs < t.maxMs) return t.color;\n }\n return COUNTDOWN_THRESHOLDS[COUNTDOWN_THRESHOLDS.length - 1].color;\n}\n\nexport function CountdownTimer({ until }: { until: string }) {\n const [remaining, setRemaining] = useState(() => new Date(until).getTime() - Date.now());\n\n useEffect(() => {\n const interval = setInterval(() => {\n setRemaining(new Date(until).getTime() - Date.now());\n }, 1000);\n return () => clearInterval(interval);\n }, [until]);\n\n const options = useMemo(() => {\n const d = new Date(until);\n return [\n { label: 'ms', value: String(Math.max(0, remaining)) },\n { label: 'until', value: d.toISOString() },\n { label: 'local', value: fnsFormat(d, 'MMM d, yyyy h:mm:ss a') },\n ];\n }, [until, remaining]);\n\n return (\n <DateTooltip options={options}>\n <span className={`text-xs font-mono ${countdownColor(remaining)}`}>\n {formatRemaining(remaining)}\n </span>\n </DateTooltip>\n );\n}\n"],"names":["COUNTDOWN_THRESHOLDS","countdownColor","remainingMs","t","CountdownTimer","until","remaining","setRemaining","useState","useEffect","interval","options","useMemo","d","fnsFormat","jsx","DateTooltip","formatRemaining"],"mappings":"+GAKA,MAAMA,EAAuB,CAC3B,CAAE,MAAO,EAAgB,MAAO,mBAAA,EAChC,CAAE,MAAO,IAAS,IAAO,MAAO,mBAAA,EAChC,CAAE,MAAO,IAAU,IAAM,MAAO,qBAAA,EAChC,CAAE,MAAO,IAAiB,MAAO,qBAAA,CACnC,EAEA,SAASC,EAAeC,EAA6B,CACnD,GAAIA,GAAe,EAAG,OAAOF,EAAqB,CAAC,EAAE,MACrD,UAAWG,KAAKH,EACd,GAAIE,EAAcC,EAAE,MAAO,OAAOA,EAAE,MAEtC,OAAOH,EAAqBA,EAAqB,OAAS,CAAC,EAAE,KAC/D,CAEO,SAASI,EAAe,CAAE,MAAAC,GAA4B,CAC3D,KAAM,CAACC,EAAWC,CAAY,EAAIC,EAAAA,SAAS,IAAM,IAAI,KAAKH,CAAK,EAAE,QAAA,EAAY,KAAK,KAAK,EAEvFI,EAAAA,UAAU,IAAM,CACd,MAAMC,EAAW,YAAY,IAAM,CACjCH,EAAa,IAAI,KAAKF,CAAK,EAAE,UAAY,KAAK,KAAK,CACrD,EAAG,GAAI,EACP,MAAO,IAAM,cAAcK,CAAQ,CACrC,EAAG,CAACL,CAAK,CAAC,EAEV,MAAMM,EAAUC,EAAAA,QAAQ,IAAM,CAC5B,MAAMC,EAAI,IAAI,KAAKR,CAAK,EACxB,MAAO,CACL,CAAE,MAAO,KAAM,MAAO,OAAO,KAAK,IAAI,EAAGC,CAAS,CAAC,CAAA,EACnD,CAAE,MAAO,QAAS,MAAOO,EAAE,aAAY,EACvC,CAAE,MAAO,QAAS,MAAOC,EAAUD,EAAG,uBAAuB,CAAA,CAAE,CAEnE,EAAG,CAACR,EAAOC,CAAS,CAAC,EAErB,OACES,EAAAA,IAACC,EAAA,CAAY,QAAAL,EACX,SAAAI,MAAC,QAAK,UAAW,qBAAqBd,EAAeK,CAAS,CAAC,GAC5D,SAAAW,EAAgBX,CAAS,EAC5B,EACF,CAEJ"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as i,j as e}from"./vendor-query-DvWWuNIB.js";import{
|
|
2
|
-
//# sourceMappingURL=CredentialsPage-
|
|
1
|
+
import{a as i,j as e}from"./vendor-query-DvWWuNIB.js";import{bx as g,by as N,bz as p,b0 as f,b1 as C}from"./index-CgUcYveM.js";import{P as k}from"./PageHeader-Csq434-v.js";import{T as A}from"./TimeAgo-0YVMBwls.js";import{C as w}from"./ConfirmDeleteModal-BqzOwhPr.js";import{g as P,C as T,bv as O,z as S}from"./vendor-icons-B7OcUM6b.js";import"./vendor-react-_9U4mKFr.js";const o={anthropic:{name:"Anthropic",helpText:'Run "claude setup-token" for an OAuth token, or use an API key from console.anthropic.com.',placeholder:"sk-ant-oat01-... or sk-ant-api03-..."},openai:{name:"OpenAI",helpText:"Create an API key at platform.openai.com/api-keys.",placeholder:"sk-..."},google:{name:"Google",helpText:"Connect your Google account for Gmail, Calendar, and Drive access.",placeholder:"",oauth:!0}};function G(){var d,x;const{data:r,isLoading:m}=g(),n=N(),[s,l]=i.useState(null),[h,u]=i.useState(!1),[a,j]=i.useState("anthropic"),c=(r==null?void 0:r.connections)??[],b=()=>{s&&n.mutate({provider:s.provider,label:s.label},{onSuccess:()=>l(null)})},v=t=>`${f}/api/auth/oauth/connect/${t}?token=${encodeURIComponent(C()||"")}&returnTo=/credentials`;return e.jsxs("div",{children:[e.jsx(k,{title:"Credentials",docsHash:"#docs:dashboard.md:credentials",actions:e.jsxs("button",{onClick:()=>u(t=>!t),className:"btn-primary text-xs inline-flex items-center gap-1.5",children:[e.jsx(P,{className:"w-3.5 h-3.5"}),"Add Credential"]})}),e.jsx("p",{className:"text-sm text-text-secondary mb-6",children:"Manage credentials used by tools when invoked on your behalf. Each credential is encrypted at rest and resolved automatically during tool execution."}),h&&e.jsxs("div",{className:"mb-6 pb-5 border-b border-surface-border/60 space-y-3",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("label",{className:"text-xs text-text-secondary font-medium",children:"Provider"}),e.jsxs("div",{className:"relative",children:[e.jsx("select",{value:a,onChange:t=>j(t.target.value),className:"input text-xs pr-7 appearance-none",children:Object.entries(o).map(([t,y])=>e.jsx("option",{value:t,children:y.name},t))}),e.jsx(T,{className:"absolute right-2 top-1/2 -translate-y-1/2 w-3 h-3 text-text-tertiary pointer-events-none"})]})]}),e.jsx("p",{className:"text-xs text-text-tertiary",children:(d=o[a])==null?void 0:d.helpText}),e.jsxs("a",{href:v(a),className:"btn-primary text-xs inline-flex items-center gap-1.5",children:[e.jsx(p,{provider:a,className:"w-3.5 h-3.5"}),"Connect ",(x=o[a])==null?void 0:x.name]})]}),m?e.jsx("div",{className:"animate-pulse space-y-3",children:[1,2].map(t=>e.jsx("div",{className:"h-16 bg-surface-sunken rounded"},t))}):c.length===0?e.jsxs("div",{className:"text-center py-16 text-text-tertiary",children:[e.jsx(O,{className:"w-10 h-10 mx-auto mb-3 opacity-40"}),e.jsx("p",{className:"text-sm",children:"No credentials registered."}),e.jsx("p",{className:"text-xs mt-1",children:"Add a credential to enable tool authentication."})]}):e.jsx("div",{className:"divide-y divide-surface-border/30",children:c.map(t=>e.jsxs("div",{className:"group/row flex items-center gap-4 px-3 py-2.5 -mx-3",children:[e.jsx(p,{provider:t.provider,className:"w-6 h-6 shrink-0"}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-sm text-text-primary font-medium capitalize",children:t.provider}),t.label!=="default"&&e.jsx("span",{className:"text-2xs px-1.5 py-0.5 bg-surface-sunken rounded text-text-tertiary",children:t.label}),t.credential_type&&e.jsx("span",{className:"text-2xs px-1.5 py-0.5 bg-accent-faint rounded text-accent",children:t.credential_type})]}),e.jsxs("div",{className:"flex items-center gap-3 mt-0.5",children:[t.email&&e.jsx("span",{className:"text-xs text-text-tertiary",children:t.email}),t.expires_at&&e.jsxs("span",{className:"text-xs text-text-tertiary",children:["Expires ",e.jsx(A,{date:t.expires_at})]})]})]}),e.jsx("button",{onClick:()=>l({provider:t.provider,label:t.label}),className:"opacity-0 group-hover/row:opacity-100 transition-opacity text-text-tertiary hover:text-status-error",title:"Revoke credential",children:e.jsx(S,{className:"w-4 h-4"})})]},`${t.provider}-${t.label}`))}),e.jsx(w,{open:!!s,onClose:()=>l(null),onConfirm:b,title:"Revoke Credential",description:e.jsxs(e.Fragment,{children:["Revoke the"," ",e.jsx("span",{className:"font-medium text-text-primary capitalize",children:s==null?void 0:s.provider}),(s==null?void 0:s.label)!=="default"&&e.jsxs(e.Fragment,{children:[" (",s==null?void 0:s.label,")"]})," ","credential? Tools will no longer be able to use this credential."]}),isPending:n.isPending,error:n.error})]})}export{G as CredentialsPage};
|
|
2
|
+
//# sourceMappingURL=CredentialsPage-D7abp0aS.js.map
|
package/dashboard/dist/assets/{CredentialsPage-CnLzopLL.js.map → CredentialsPage-D7abp0aS.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CredentialsPage-CnLzopLL.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-2xs 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-2xs 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-D7abp0aS.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-2xs 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-2xs 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-DvWWuNIB.js";import{m as i}from"./index-
|
|
2
|
-
//# sourceMappingURL=CronLabel-
|
|
1
|
+
import{u as c,b as r,c as o,j as n}from"./vendor-query-DvWWuNIB.js";import{m as i}from"./index-CgUcYveM.js";import{R as l,ax as x}from"./vendor-icons-B7OcUM6b.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-2xs 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-2xs font-mono text-text-secondary",children:[n.jsx(x,{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-DZiWmTwJ.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CronLabel-
|
|
1
|
+
{"version":3,"file":"CronLabel-DZiWmTwJ.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-2xs 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-2xs 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,wEACd,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,wEACd,SAAA,CAAAC,EAAAA,IAACI,EAAA,CAAM,UAAU,4CAA4C,YAAa,IAAK,EAC9ED,CAAA,EACH,CAEJ"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{j as e,a as M}from"./vendor-query-DvWWuNIB.js";import{E as P}from"./EmptyState-DgC_6njU.js";import{u as z}from"./useContainerWidth-DSLp1gEm.js";const $={split:"hidden @split/table:table-cell",wall:"hidden @wall/table:table-cell"};function O(i){const r=i.some(l=>l.priority!==void 0),d=[],a=[],s=[];return i.forEach((l,f)=>{const x=l.priority??(r?2:f===0?1:2);x===1?d.push(l):x===3?s.push(l):a.push(l)}),{identity:d,meta:a,dropped:s}}const W=48;function I(){if(typeof window>"u"||typeof document>"u")return 16;const i=parseFloat(getComputedStyle(document.documentElement).fontSize);return Number.isFinite(i)&&i>0?i:16}function B({active:i,direction:r}){return e.jsx("svg",{className:`w-3 h-3 shrink-0 transition-all duration-150 ${i?"text-accent opacity-100":"opacity-0 group-hover/sorthead:opacity-40 text-text-tertiary"} ${i&&r==="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 H({columns:i,sort:r,onSort:d}){const a=i.filter(s=>s.sortable);return a.length===0?null:e.jsxs("div",{className:"flex items-center gap-2 px-4 py-2 border-b",children:[e.jsx("span",{className:"text-2xs font-semibold uppercase tracking-wide text-text-tertiary",children:"Sort"}),e.jsxs("select",{className:"select text-2xs py-1",value:(r==null?void 0:r.sort_by)??"",onChange:s=>s.target.value&&d(s.target.value),children:[!(r!=null&&r.sort_by)&&e.jsx("option",{value:"",disabled:!0,children:"Choose…"}),a.map(s=>e.jsx("option",{value:s.key,children:typeof s.label=="string"?s.label:s.key},s.key))]}),(r==null?void 0:r.sort_by)&&e.jsx("button",{onClick:()=>d(r.sort_by),className:"text-2xs text-text-tertiary hover:text-accent transition-colors tabular-nums",title:"Flip sort direction",children:r.order==="asc"?"↑ asc":"↓ desc"})]})}function J({columns:i,data:r,keyFn:d,onRowClick:a,activeRowKey:s,rowClassName:l,isLoading:f,emptyMessage:x="No records found",sort:u,onSort:m,inline:_,layout:w="auto",forceCardMode:A,fold:y="auto",density:j="default"}){const[v,g]=z(),C=A??(y==="always"?!0:y==="never"?!1:g!==null&&g<W*I()),b=j==="compact",E=i.some(t=>t.priority!==void 0),N=(t,c)=>t.showFrom?$[t.showFrom]:b?(t.priority??(E?2:c===0?1:2))===1?"":$.split:"",k=j!=="default",F=b?"px-3 py-1.5":k?"px-3 py-2":"px-6 py-3",S=b?"px-3 py-1.5 text-xs":k?"px-3 py-2 text-xs":"px-6 py-2.5 text-sm";if(f)return e.jsx("div",{className:"animate-pulse space-y-0",children:Array.from({length:5}).map((t,c)=>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"})},c))});if(!r.length)return x?e.jsx(P,{title:x}):null;if(C){const{identity:t,meta:c}=O(i),o=Math.max(0,t.findIndex(n=>!/(^|\s)w-\d/.test(n.className??"")));return e.jsxs("div",{ref:v,className:"@container/table",children:[m&&e.jsx(H,{columns:i,sort:u,onSort:m}),e.jsx("div",{className:"divide-y divide-surface-border",children:r.map((n,h)=>{const D=s!=null&&d(n)===s;return e.jsxs("div",{onClick:a?()=>a(n):void 0,className:`py-3 px-4 transition-colors duration-100 ${a?"cursor-pointer row-hover":""} ${D?"border-l-2 border-l-accent":""} ${l?l(n):""}`,children:[e.jsx("div",{className:"flex items-center gap-2 min-w-0",children:t.map((p,L)=>e.jsx("div",{className:L===o?"flex-1 min-w-0":"shrink-0",children:p.render(n,h)},p.key))}),c.length>0&&e.jsx("dl",{className:"mt-2 grid grid-cols-1 @dict-inline/table:grid-cols-[max-content_1fr] gap-x-6 gap-y-1 items-baseline",children:c.map(p=>e.jsxs(M.Fragment,{children:[e.jsx("dt",{className:"text-2xs font-semibold uppercase tracking-wide text-text-tertiary",children:p.label}),e.jsx("dd",{className:"text-sm min-w-0 break-words",children:p.render(n,h)})]},p.key))})]},d(n))})})]})}return e.jsx("div",{ref:v,className:"@container/table",children:e.jsxs("table",{className:`w-full ${w==="fixed"?"table-fixed":""}`,children:[e.jsx("thead",{children:e.jsx("tr",{className:"border-b",children:i.map((t,c)=>{const o=t.sortable&&m,n=(u==null?void 0:u.sort_by)===t.key;return e.jsx("th",{onClick:o?()=>m(t.key):void 0,style:t.width?{width:t.width}:void 0,className:`${_?"":"sticky top-[var(--lt-sticky-top,60px)] z-10 "}bg-surface ${F} text-left text-2xs font-semibold uppercase tracking-widest text-text-tertiary whitespace-nowrap ${N(t,c)} ${t.className??""} ${o?"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,o&&e.jsx(B,{active:n,direction:n?u.order:"desc"})]})},t.key)})})}),e.jsx("tbody",{children:r.map((t,c)=>{const o=s!=null&&d(t)===s;return e.jsx("tr",{onClick:a?()=>a(t):void 0,className:`group/row border-b last:border-b-0 transition-colors duration-100 ${a?"cursor-pointer row-hover":""} ${o?"border-l-2 border-l-accent":""} ${l?l(t):""}`,children:i.map((n,h)=>e.jsx("td",{className:`${S} overflow-hidden ${N(n,h)} ${n.className??""}`,children:n.render(t,c)},n.key))},d(t))})})]})})}export{J as D};
|
|
2
|
+
//# sourceMappingURL=DataTable-spX1dFyb.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DataTable-spX1dFyb.js","sources":["../../src/components/common/data/DataTable.tsx"],"sourcesContent":["import { Fragment, type ReactNode } from 'react';\nimport { EmptyState } from '../display/EmptyState';\nimport { useContainerWidth } from '../../../hooks/useContainerWidth';\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 /** CSS width for the column (e.g. \"40%\", \"12rem\") — set on the header cell,\n * which sizes the whole column under `layout=\"fixed\"`. */\n width?: string;\n /** If true, this column header is clickable and triggers onSort. */\n sortable?: boolean;\n /**\n * Card-fold behavior when the container drops below the @table threshold:\n * 1 = identity — always visible, forms the card's title line;\n * 2 = folds into the card body as a label/value pair (default);\n * 3 = dropped in card mode.\n */\n priority?: 1 | 2 | 3;\n /**\n * Table-mode disclosure: the column renders only when the table's\n * container clears the named threshold. The column budget governs the\n * floor; enrichment columns return with room.\n */\n showFrom?: 'split' | 'wall';\n}\n\n/* Literal class strings so Tailwind's scanner sees the container variants. */\nconst SHOW_FROM_CLASS: Record<NonNullable<Column<unknown>['showFrom']>, string> = {\n split: 'hidden @split/table:table-cell',\n wall: 'hidden @wall/table:table-cell',\n};\n\n/**\n * Split columns by card-fold priority. When NO column declares a priority,\n * the first column is the identity and the rest fold — the sane default for\n * every list page. When any column declares one, undeclared columns fold.\n * Exported for tests.\n */\nexport function partitionColumns<T>(columns: Column<T>[]): {\n identity: Column<T>[];\n meta: Column<T>[];\n dropped: Column<T>[];\n} {\n const anyDeclared = columns.some((c) => c.priority !== undefined);\n const identity: Column<T>[] = [];\n const meta: Column<T>[] = [];\n const dropped: Column<T>[] = [];\n columns.forEach((col, i) => {\n const priority = col.priority ?? (anyDeclared ? 2 : i === 0 ? 1 : 2);\n if (priority === 1) identity.push(col);\n else if (priority === 3) dropped.push(col);\n else meta.push(col);\n });\n return { identity, meta, dropped };\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 /** Force console-card rendering regardless of measured width (tests). */\n forceCardMode?: boolean;\n /**\n * When the table folds into console cards: `auto` below the card threshold\n * (default), `never` to stay a table however narrow, `always` to fold.\n */\n fold?: 'auto' | 'never' | 'always';\n /**\n * `dense` tightens every cell (smaller type, less side padding) and keeps\n * every column. `compact` goes further and holds non-identity columns\n * back until the container clears the split threshold, so a narrow table\n * reads as a tight list of identities rather than a squeeze of every column.\n */\n density?: 'default' | 'dense' | 'compact';\n}\n\n/** The @table threshold in rem — below this the table folds into cards. */\nconst CARD_FOLD_REM = 48;\n\nfunction rootFontPx(): number {\n if (typeof window === 'undefined' || typeof document === 'undefined') return 16;\n const size = parseFloat(getComputedStyle(document.documentElement).fontSize);\n return Number.isFinite(size) && size > 0 ? size : 16;\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\n/** Compact sort control for card mode, where there is no header row. */\nfunction CardSortControl<T>({ columns, sort, onSort }: {\n columns: Column<T>[];\n sort?: SortState;\n onSort: (column: string) => void;\n}) {\n const sortable = columns.filter((c) => c.sortable);\n if (sortable.length === 0) return null;\n return (\n <div className=\"flex items-center gap-2 px-4 py-2 border-b\">\n <span className=\"text-2xs font-semibold uppercase tracking-wide text-text-tertiary\">Sort</span>\n <select\n className=\"select text-2xs py-1\"\n value={sort?.sort_by ?? ''}\n onChange={(e) => e.target.value && onSort(e.target.value)}\n >\n {!sort?.sort_by && <option value=\"\" disabled>Choose…</option>}\n {sortable.map((c) => (\n <option key={c.key} value={c.key}>{typeof c.label === 'string' ? c.label : c.key}</option>\n ))}\n </select>\n {sort?.sort_by && (\n <button\n onClick={() => onSort(sort.sort_by)}\n className=\"text-2xs text-text-tertiary hover:text-accent transition-colors tabular-nums\"\n title=\"Flip sort direction\"\n >\n {sort.order === 'asc' ? '↑ asc' : '↓ desc'}\n </button>\n )}\n </div>\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 forceCardMode,\n fold = 'auto',\n density = 'default',\n}: DataTableProps<T>) {\n const [wrapRef, width] = useContainerWidth<HTMLDivElement>();\n const cardMode = forceCardMode\n ?? (fold === 'always' ? true : fold === 'never' ? false : width !== null && width < CARD_FOLD_REM * rootFontPx());\n const compact = density === 'compact';\n const anyPriority = columns.some((c) => c.priority !== undefined);\n // In compact density a non-identity column without its own disclosure\n // threshold waits for the split width, as the enrichment columns already do.\n const discloseClass = (col: Column<T>, index: number): string => {\n if (col.showFrom) return SHOW_FROM_CLASS[col.showFrom];\n if (!compact) return '';\n const priority = col.priority ?? (anyPriority ? 2 : index === 0 ? 1 : 2);\n return priority === 1 ? '' : SHOW_FROM_CLASS.split;\n };\n const tight = density !== 'default';\n const headPad = compact ? 'px-3 py-1.5' : tight ? 'px-3 py-2' : 'px-6 py-3';\n const cellPad = compact ? 'px-3 py-1.5 text-xs' : tight ? 'px-3 py-2 text-xs' : 'px-6 py-2.5 text-sm';\n\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 if (cardMode) {\n // A table row IS a dictionary: identity columns form the title line, the\n // rest fold into dense console-style pairs. Tables never scroll\n // horizontally — they fold.\n const { identity, meta } = partitionColumns(columns);\n // The title line: glyph/width-classed identity columns (status dots,\n // checkboxes, countdowns) hold their size; the first free-width identity\n // column (the description) flexes and truncates.\n const flexAt = Math.max(0, identity.findIndex((c) => !/(^|\\s)w-\\d/.test(c.className ?? '')));\n return (\n <div ref={wrapRef} className=\"@container/table\">\n {onSort && <CardSortControl columns={columns} sort={sort} onSort={onSort} />}\n <div className=\"divide-y divide-surface-border\">\n {data.map((row, index) => {\n const isActive = activeRowKey != null && keyFn(row) === activeRowKey;\n return (\n <div\n key={keyFn(row)}\n onClick={onRowClick ? () => onRowClick(row) : undefined}\n className={`py-3 px-4 transition-colors duration-100 ${\n onRowClick ? 'cursor-pointer row-hover' : ''\n } ${isActive ? 'border-l-2 border-l-accent' : ''} ${rowClassName ? rowClassName(row) : ''}`}\n >\n <div className=\"flex items-center gap-2 min-w-0\">\n {identity.map((col, i) => (\n <div key={col.key} className={i === flexAt ? 'flex-1 min-w-0' : 'shrink-0'}>\n {col.render(row, index)}\n </div>\n ))}\n </div>\n {meta.length > 0 && (\n <dl className=\"mt-2 grid grid-cols-1 @dict-inline/table:grid-cols-[max-content_1fr] gap-x-6 gap-y-1 items-baseline\">\n {meta.map((col) => (\n <Fragment key={col.key}>\n <dt className=\"text-2xs font-semibold uppercase tracking-wide text-text-tertiary\">\n {col.label}\n </dt>\n <dd className=\"text-sm min-w-0 break-words\">{col.render(row, index)}</dd>\n </Fragment>\n ))}\n </dl>\n )}\n </div>\n );\n })}\n </div>\n </div>\n );\n }\n\n return (\n <div ref={wrapRef} className=\"@container/table\">\n <table className={`w-full ${layout === 'fixed' ? 'table-fixed' : ''}`}>\n <thead>\n <tr className=\"border-b\">\n {columns.map((col, colIndex) => {\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 style={col.width ? { width: col.width } : undefined}\n className={`${inline ? '' : 'sticky top-[var(--lt-sticky-top,60px)] z-10 '}bg-surface ${headPad} text-left text-2xs font-semibold uppercase tracking-widest text-text-tertiary whitespace-nowrap ${discloseClass(col, colIndex)} ${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, colIndex) => (\n <td\n key={col.key}\n className={`${cellPad} overflow-hidden ${discloseClass(col, colIndex)} ${col.className ?? ''}`}\n >\n {col.render(row, index)}\n </td>\n ))}\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n );\n}\n"],"names":["SHOW_FROM_CLASS","partitionColumns","columns","anyDeclared","c","identity","meta","dropped","col","i","priority","CARD_FOLD_REM","rootFontPx","size","SortIcon","active","direction","jsx","CardSortControl","sort","onSort","sortable","jsxs","e","DataTable","data","keyFn","onRowClick","activeRowKey","rowClassName","isLoading","emptyMessage","inline","layout","forceCardMode","fold","density","wrapRef","width","useContainerWidth","cardMode","compact","anyPriority","discloseClass","index","tight","headPad","cellPad","_","EmptyState","flexAt","row","isActive","Fragment","colIndex","isSortable"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as n,j as l}from"./vendor-query-DvWWuNIB.js";import{
|
|
2
|
-
//# sourceMappingURL=DropZone-
|
|
1
|
+
import{a as n,j as l}from"./vendor-query-DvWWuNIB.js";import{bT as D}from"./vendor-icons-B7OcUM6b.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-f1o-GLM8.js.map
|