@hotmeshio/long-tail 0.16.0 → 0.16.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/shared/form-validation/field-validator.d.ts +12 -0
- package/build/shared/form-validation/field-validator.js +31 -3
- package/build/shared/form-validation/x-lt-options.d.ts +7 -2
- package/build/shared/form-validation/x-lt-options.js +32 -10
- package/dashboard/dist/assets/{AdminDashboard-BVgjY4zN.js → AdminDashboard-BrOvvDHF.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-BVgjY4zN.js.map → AdminDashboard-BrOvvDHF.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-ChL59YL5.js → AgentConfigPage-CtVq8J0L.js} +2 -2
- package/dashboard/dist/assets/{AgentConfigPage-ChL59YL5.js.map → AgentConfigPage-CtVq8J0L.js.map} +1 -1
- package/dashboard/dist/assets/{AgentDetailPage-IJfgCOIF.js → AgentDetailPage-DTfTQDug.js} +2 -2
- package/dashboard/dist/assets/{AgentDetailPage-IJfgCOIF.js.map → AgentDetailPage-DTfTQDug.js.map} +1 -1
- package/dashboard/dist/assets/{AgentsPage-C7PnPXz_.js → AgentsPage-vCTc3Qvj.js} +2 -2
- package/dashboard/dist/assets/{AgentsPage-C7PnPXz_.js.map → AgentsPage-vCTc3Qvj.js.map} +1 -1
- package/dashboard/dist/assets/{AvailableEscalationsPage-C5f2rqHa.js → AvailableEscalationsPage-DJODShd7.js} +2 -2
- package/dashboard/dist/assets/{AvailableEscalationsPage-C5f2rqHa.js.map → AvailableEscalationsPage-DJODShd7.js.map} +1 -1
- package/dashboard/dist/assets/{BotPicker-CBf6bHLV.js → BotPicker-GU44inXA.js} +2 -2
- package/dashboard/dist/assets/{BotPicker-CBf6bHLV.js.map → BotPicker-GU44inXA.js.map} +1 -1
- package/dashboard/dist/assets/{BulkAssignModal-CkxoPByA.js → BulkAssignModal-ChqzG6FY.js} +2 -2
- package/dashboard/dist/assets/{BulkAssignModal-CkxoPByA.js.map → BulkAssignModal-ChqzG6FY.js.map} +1 -1
- package/dashboard/dist/assets/{CapabilitiesPage-D7USh3F0.js → CapabilitiesPage-Y2hycdPY.js} +2 -2
- package/dashboard/dist/assets/{CapabilitiesPage-D7USh3F0.js.map → CapabilitiesPage-Y2hycdPY.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-DfPpAIxa.js → CollapsibleSection-CmCwt_Rs.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-DfPpAIxa.js.map → CollapsibleSection-CmCwt_Rs.js.map} +1 -1
- package/dashboard/dist/assets/{CountdownTimer-DVL7WIcE.js → CountdownTimer-Bx2XXJOd.js} +2 -2
- package/dashboard/dist/assets/{CountdownTimer-DVL7WIcE.js.map → CountdownTimer-Bx2XXJOd.js.map} +1 -1
- package/dashboard/dist/assets/{CredentialsPage-BHZ5SKIu.js → CredentialsPage-CoX_PNBe.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-BHZ5SKIu.js.map → CredentialsPage-CoX_PNBe.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-wE8Hms6c.js → CronLabel-CVYKRipP.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-wE8Hms6c.js.map → CronLabel-CVYKRipP.js.map} +1 -1
- package/dashboard/dist/assets/{ElapsedCell-B4VxKHpw.js → ElapsedCell-jRURiCRW.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-B4VxKHpw.js.map → ElapsedCell-jRURiCRW.js.map} +1 -1
- package/dashboard/dist/assets/{EntityTimelinePanel-CFbQDHOj.js → EntityTimelinePanel-G6nzvgpl.js} +2 -2
- package/dashboard/dist/assets/{EntityTimelinePanel-CFbQDHOj.js.map → EntityTimelinePanel-G6nzvgpl.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationListSchemaPage-YTgexl4f.js → EscalationListSchemaPage-D-rVTQ1m.js} +2 -2
- package/dashboard/dist/assets/{EscalationListSchemaPage-YTgexl4f.js.map → EscalationListSchemaPage-D-rVTQ1m.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationSchemaPage-Sjk05eHP.js → EscalationSchemaPage-CV0R_xY9.js} +2 -2
- package/dashboard/dist/assets/{EscalationSchemaPage-Sjk05eHP.js.map → EscalationSchemaPage-CV0R_xY9.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationsOverview-gHWPjUpZ.js → EscalationsOverview-DMdx15CQ.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-gHWPjUpZ.js.map → EscalationsOverview-DMdx15CQ.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-C9lHQ57t.js → EventTable-CIvsdt-q.js} +2 -2
- package/dashboard/dist/assets/{EventTable-C9lHQ57t.js.map → EventTable-CIvsdt-q.js.map} +1 -1
- package/dashboard/dist/assets/{FilterBar-BY--ANxv.js → FilterBar-DWYGkVRH.js} +2 -2
- package/dashboard/dist/assets/{FilterBar-BY--ANxv.js.map → FilterBar-DWYGkVRH.js.map} +1 -1
- package/dashboard/dist/assets/{GraphInvokePage-B-Oo5s-W.js → GraphInvokePage-BGHlXh4r.js} +2 -2
- package/dashboard/dist/assets/{GraphInvokePage-B-Oo5s-W.js.map → GraphInvokePage-BGHlXh4r.js.map} +1 -1
- package/dashboard/dist/assets/{HomePage-BrcjKOaJ.js → HomePage-BHOnp8SK.js} +2 -2
- package/dashboard/dist/assets/{HomePage-BrcjKOaJ.js.map → HomePage-BHOnp8SK.js.map} +1 -1
- package/dashboard/dist/assets/{ListToolbar-D5TQ4X_M.js → ListToolbar-iOgn_db5.js} +2 -2
- package/dashboard/dist/assets/{ListToolbar-D5TQ4X_M.js.map → ListToolbar-iOgn_db5.js.map} +1 -1
- package/dashboard/dist/assets/{McpOverview-jlukVWQ7.js → McpOverview-Be9sMKCA.js} +2 -2
- package/dashboard/dist/assets/{McpOverview-jlukVWQ7.js.map → McpOverview-Be9sMKCA.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryDetailPage-BWKbvJSd.js → McpQueryDetailPage-BIgpmGJN.js} +2 -2
- package/dashboard/dist/assets/{McpQueryDetailPage-BWKbvJSd.js.map → McpQueryDetailPage-BIgpmGJN.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryPage-BH2Pon4M.js → McpQueryPage-Okcxw_Um.js} +2 -2
- package/dashboard/dist/assets/{McpQueryPage-BH2Pon4M.js.map → McpQueryPage-Okcxw_Um.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunDetailPage-kUnq2QSO.js → McpRunDetailPage-DT8kOfih.js} +2 -2
- package/dashboard/dist/assets/{McpRunDetailPage-kUnq2QSO.js.map → McpRunDetailPage-DT8kOfih.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunsPage-BTucgt64.js → McpRunsPage-BXhoP77D.js} +2 -2
- package/dashboard/dist/assets/{McpRunsPage-BTucgt64.js.map → McpRunsPage-BXhoP77D.js.map} +1 -1
- package/dashboard/dist/assets/{OperationsPage-Cp8WL-ld.js → OperationsPage-rVhC8JPv.js} +2 -2
- package/dashboard/dist/assets/{OperationsPage-Cp8WL-ld.js.map → OperationsPage-rVhC8JPv.js.map} +1 -1
- package/dashboard/dist/assets/{OperatorDashboard-wHyeLWzX.js → OperatorDashboard-CIt061hu.js} +2 -2
- package/dashboard/dist/assets/{OperatorDashboard-wHyeLWzX.js.map → OperatorDashboard-CIt061hu.js.map} +1 -1
- package/dashboard/dist/assets/{PersonaDetailPage-BXlTqLDK.js → PersonaDetailPage-r46uNF4E.js} +2 -2
- package/dashboard/dist/assets/{PersonaDetailPage-BXlTqLDK.js.map → PersonaDetailPage-r46uNF4E.js.map} +1 -1
- package/dashboard/dist/assets/{PersonasPage-DlmdJ3Dm.js → PersonasPage-CayYv9-j.js} +2 -2
- package/dashboard/dist/assets/{PersonasPage-DlmdJ3Dm.js.map → PersonasPage-CayYv9-j.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessDetailPage-D88ocvmT.js → ProcessDetailPage-dn7lkM4c.js} +2 -2
- package/dashboard/dist/assets/{ProcessDetailPage-D88ocvmT.js.map → ProcessDetailPage-dn7lkM4c.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessesListPage-DpXm-KtK.js → ProcessesListPage-DOp5J6Be.js} +2 -2
- package/dashboard/dist/assets/{ProcessesListPage-DpXm-KtK.js.map → ProcessesListPage-DOp5J6Be.js.map} +1 -1
- package/dashboard/dist/assets/{RoleDetailPage-DE2Rj2QE.js → RoleDetailPage-DOlNoiAK.js} +2 -2
- package/dashboard/dist/assets/{RoleDetailPage-DE2Rj2QE.js.map → RoleDetailPage-DOlNoiAK.js.map} +1 -1
- package/dashboard/dist/assets/{RolesPage-CZSvJlsz.js → RolesPage-DPppT6Zl.js} +2 -2
- package/dashboard/dist/assets/{RolesPage-CZSvJlsz.js.map → RolesPage-DPppT6Zl.js.map} +1 -1
- package/dashboard/dist/assets/{RunAsSelector-BawZcqAk.js → RunAsSelector-BgntKfSA.js} +2 -2
- package/dashboard/dist/assets/{RunAsSelector-BawZcqAk.js.map → RunAsSelector-BgntKfSA.js.map} +1 -1
- package/dashboard/dist/assets/{ScanCodesPage-DSlpA9kK.js → ScanCodesPage-DPm1lG79.js} +2 -2
- package/dashboard/dist/assets/{ScanCodesPage-DSlpA9kK.js.map → ScanCodesPage-DPm1lG79.js.map} +1 -1
- package/dashboard/dist/assets/{ScanSchemeDetailPage-BK4hisGD.js → ScanSchemeDetailPage-CuoG89q1.js} +2 -2
- package/dashboard/dist/assets/{ScanSchemeDetailPage-BK4hisGD.js.map → ScanSchemeDetailPage-CuoG89q1.js.map} +1 -1
- package/dashboard/dist/assets/{ScanStationPage-D3QjajFD.js → ScanStationPage-2SLXqqs0.js} +2 -2
- package/dashboard/dist/assets/{ScanStationPage-D3QjajFD.js.map → ScanStationPage-2SLXqqs0.js.map} +1 -1
- package/dashboard/dist/assets/{StickyPagination-BfZwU2NR.js → StickyPagination-Bc_Mzu_R.js} +2 -2
- package/dashboard/dist/assets/{StickyPagination-BfZwU2NR.js.map → StickyPagination-Bc_Mzu_R.js.map} +1 -1
- package/dashboard/dist/assets/{StreamMessageDetail-C7zIHX5D.js → StreamMessageDetail-S1cnLGkf.js} +2 -2
- package/dashboard/dist/assets/{StreamMessageDetail-C7zIHX5D.js.map → StreamMessageDetail-S1cnLGkf.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-DNSo8AT8.js → SwimlaneTimeline-BUu2sPmY.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-DNSo8AT8.js.map → SwimlaneTimeline-BUu2sPmY.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-BOJ8pwh3.js → TaskDetailPage-BMfNNtbN.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-BOJ8pwh3.js.map → TaskDetailPage-BMfNNtbN.js.map} +1 -1
- package/dashboard/dist/assets/{TasksListPage-C4CYqZf8.js → TasksListPage-BmNnopOU.js} +2 -2
- package/dashboard/dist/assets/{TasksListPage-C4CYqZf8.js.map → TasksListPage-BmNnopOU.js.map} +1 -1
- package/dashboard/dist/assets/{TimeAgo-JRPi9IEd.js → TimeAgo-Dip7gQQx.js} +2 -2
- package/dashboard/dist/assets/{TimeAgo-JRPi9IEd.js.map → TimeAgo-Dip7gQQx.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-BVYyU-nl.js → TimestampCell-DRAYnIrx.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-BVYyU-nl.js.map → TimestampCell-DRAYnIrx.js.map} +1 -1
- package/dashboard/dist/assets/{ToolTestPanel-IGrd44Au.js → ToolTestPanel-CQVYC3Ba.js} +2 -2
- package/dashboard/dist/assets/{ToolTestPanel-IGrd44Au.js.map → ToolTestPanel-CQVYC3Ba.js.map} +1 -1
- package/dashboard/dist/assets/{TopicDetailPage-DhianNey.js → TopicDetailPage-Bmtwuksg.js} +2 -2
- package/dashboard/dist/assets/{TopicDetailPage-DhianNey.js.map → TopicDetailPage-Bmtwuksg.js.map} +1 -1
- package/dashboard/dist/assets/{TopicsPage-Glhqz_Nv.js → TopicsPage-DIgF7-mJ.js} +2 -2
- package/dashboard/dist/assets/{TopicsPage-Glhqz_Nv.js.map → TopicsPage-DIgF7-mJ.js.map} +1 -1
- package/dashboard/dist/assets/{UserName-CD9OqhNI.js → UserName-DNKFz7X9.js} +2 -2
- package/dashboard/dist/assets/{UserName-CD9OqhNI.js.map → UserName-DNKFz7X9.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowExecutionPage-8Q2438Ry.js → WorkflowExecutionPage-DraIBNpl.js} +2 -2
- package/dashboard/dist/assets/{WorkflowExecutionPage-8Q2438Ry.js.map → WorkflowExecutionPage-DraIBNpl.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsDashboard-CkAoYT86.js → WorkflowsDashboard-BH7kmFjM.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsDashboard-CkAoYT86.js.map → WorkflowsDashboard-BH7kmFjM.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsOverview-Zh_EidMp.js → WorkflowsOverview-C98pCjQX.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-Zh_EidMp.js.map → WorkflowsOverview-C98pCjQX.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-BKJbFT8C.js → YamlWorkflowDetailPage-BWQjXenZ.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-BKJbFT8C.js.map → YamlWorkflowDetailPage-BWQjXenZ.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowsPage-DK1z6iFt.js → YamlWorkflowsPage-BGTI_sdP.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowsPage-DK1z6iFt.js.map → YamlWorkflowsPage-BGTI_sdP.js.map} +1 -1
- package/dashboard/dist/assets/{agents-BEASyYpg.js → agents-DfMrlw54.js} +2 -2
- package/dashboard/dist/assets/{agents-BEASyYpg.js.map → agents-DfMrlw54.js.map} +1 -1
- package/dashboard/dist/assets/{bots-CaXqSHat.js → bots-B9zS0z7D.js} +2 -2
- package/dashboard/dist/assets/{bots-CaXqSHat.js.map → bots-B9zS0z7D.js.map} +1 -1
- package/dashboard/dist/assets/{capabilities-Cijq-qev.js → capabilities-DkLM1xgH.js} +2 -2
- package/dashboard/dist/assets/{capabilities-Cijq-qev.js.map → capabilities-DkLM1xgH.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-HGuRC7AW.js → controlplane-SJK1yvbm.js} +2 -2
- package/dashboard/dist/assets/{controlplane-HGuRC7AW.js.map → controlplane-SJK1yvbm.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-columns-BLVz8XCP.js → escalation-columns-BvAylNM1.js} +2 -2
- package/dashboard/dist/assets/{escalation-columns-BLVz8XCP.js.map → escalation-columns-BvAylNM1.js.map} +1 -1
- package/dashboard/dist/assets/{index-CEIp6WWg.js → index-CLxuBb17.js} +2 -2
- package/dashboard/dist/assets/{index-CEIp6WWg.js.map → index-CLxuBb17.js.map} +1 -1
- package/dashboard/dist/assets/{index-ClY0ihQ5.js → index-CXe2d5kg.js} +2 -2
- package/dashboard/dist/assets/{index-ClY0ihQ5.js.map → index-CXe2d5kg.js.map} +1 -1
- package/dashboard/dist/assets/{index-IkgBE7e_.js → index-ClVNU3G3.js} +2 -2
- package/dashboard/dist/assets/{index-IkgBE7e_.js.map → index-ClVNU3G3.js.map} +1 -1
- package/dashboard/dist/assets/{index-D2OU2MJb.js → index-Cw-V0VhS.js} +2 -2
- package/dashboard/dist/assets/{index-D2OU2MJb.js.map → index-Cw-V0VhS.js.map} +1 -1
- package/dashboard/dist/assets/{index-Xi3LO4Ye.js → index-D2IRxjSf.js} +2 -2
- package/dashboard/dist/assets/{index-Xi3LO4Ye.js.map → index-D2IRxjSf.js.map} +1 -1
- package/dashboard/dist/assets/{index-t1JXcmBG.js → index-DKXOIcO3.js} +2 -2
- package/dashboard/dist/assets/{index-t1JXcmBG.js.map → index-DKXOIcO3.js.map} +1 -1
- package/dashboard/dist/assets/{index-YMd3ZiPd.js → index-DSfY8oDp.js} +2 -2
- package/dashboard/dist/assets/{index-YMd3ZiPd.js.map → index-DSfY8oDp.js.map} +1 -1
- package/dashboard/dist/assets/index-DTZxHZJO.js +3 -0
- package/dashboard/dist/assets/index-DTZxHZJO.js.map +1 -0
- package/dashboard/dist/assets/{index-tCDjx1kF.js → index-DamcWcqG.js} +2 -2
- package/dashboard/dist/assets/{index-tCDjx1kF.js.map → index-DamcWcqG.js.map} +1 -1
- package/dashboard/dist/assets/{index-Cg0vCZng.js → index-DazfFRUx.js} +2 -2
- package/dashboard/dist/assets/{index-Cg0vCZng.js.map → index-DazfFRUx.js.map} +1 -1
- package/dashboard/dist/assets/{index-BJDAXUzO.js → index-DvmyIGeZ.js} +2 -2
- package/dashboard/dist/assets/{index-BJDAXUzO.js.map → index-DvmyIGeZ.js.map} +1 -1
- package/dashboard/dist/assets/{index-CLQ0HBHR.js → index-PjiXOVdw.js} +2 -2
- package/dashboard/dist/assets/{index-CLQ0HBHR.js.map → index-PjiXOVdw.js.map} +1 -1
- package/dashboard/dist/assets/{index-CgXVDPW-.js → index-zrTQcPjB.js} +3 -3
- package/dashboard/dist/assets/{index-CgXVDPW-.js.map → index-zrTQcPjB.js.map} +1 -1
- package/dashboard/dist/assets/{knowledge-DpaUJtVW.js → knowledge-BNp6MH-4.js} +2 -2
- package/dashboard/dist/assets/{knowledge-DpaUJtVW.js.map → knowledge-BNp6MH-4.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-BkkLq6OE.js → mcp-Bb1k5rv-.js} +2 -2
- package/dashboard/dist/assets/{mcp-BkkLq6OE.js.map → mcp-Bb1k5rv-.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-DeXu3La5.js → mcp-query-QVakMQnS.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-DeXu3La5.js.map → mcp-query-QVakMQnS.js.map} +1 -1
- package/dashboard/dist/assets/{personas-BRbKVVko.js → personas-DV2JUjVj.js} +2 -2
- package/dashboard/dist/assets/{personas-BRbKVVko.js.map → personas-DV2JUjVj.js.map} +1 -1
- package/dashboard/dist/assets/{pipelines-B7xo92sK.js → pipelines-BkVB7Q0p.js} +2 -2
- package/dashboard/dist/assets/{pipelines-B7xo92sK.js.map → pipelines-BkVB7Q0p.js.map} +1 -1
- package/dashboard/dist/assets/{tasks-BGyqM1Ho.js → tasks-DvYWcASM.js} +2 -2
- package/dashboard/dist/assets/{tasks-BGyqM1Ho.js.map → tasks-DvYWcASM.js.map} +1 -1
- package/dashboard/dist/assets/{topics-I81rKc75.js → topics-B9zXFuVG.js} +2 -2
- package/dashboard/dist/assets/{topics-I81rKc75.js.map → topics-B9zXFuVG.js.map} +1 -1
- package/dashboard/dist/assets/{useEventHooks-CjV3uNxt.js → useEventHooks-JDpifqGZ.js} +2 -2
- package/dashboard/dist/assets/{useEventHooks-CjV3uNxt.js.map → useEventHooks-JDpifqGZ.js.map} +1 -1
- package/dashboard/dist/assets/{useNamespace-B-HMdRka.js → useNamespace-Bqr-LdWx.js} +2 -2
- package/dashboard/dist/assets/{useNamespace-B-HMdRka.js.map → useNamespace-Bqr-LdWx.js.map} +1 -1
- package/dashboard/dist/assets/{useYamlActivityEvents-CNsAlsgz.js → useYamlActivityEvents-n3naCEbw.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-CNsAlsgz.js.map → useYamlActivityEvents-n3naCEbw.js.map} +1 -1
- package/dashboard/dist/assets/{users-DiTqBepm.js → users-BNXLRVTS.js} +2 -2
- package/dashboard/dist/assets/{users-DiTqBepm.js.map → users-BNXLRVTS.js.map} +1 -1
- package/dashboard/dist/assets/{workflows-TA0p_3B8.js → workflows-D8uMBPvQ.js} +2 -2
- package/dashboard/dist/assets/{workflows-TA0p_3B8.js.map → workflows-D8uMBPvQ.js.map} +1 -1
- package/dashboard/dist/assets/{yaml-workflows-DN9-DBnQ.js → yaml-workflows-DVDOQM3Y.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-DN9-DBnQ.js.map → yaml-workflows-DVDOQM3Y.js.map} +1 -1
- package/dashboard/dist/index.html +1 -1
- package/docs/hitl/lookups.md +13 -0
- package/docs/hitl/x-lt-validation.md +2 -1
- package/docs/hitl/x-lt-widget.md +8 -1
- package/docs/hitl-guide.md +2 -1
- package/package.json +1 -1
- package/dashboard/dist/assets/index-CK_ohh6Q.js +0 -3
- package/dashboard/dist/assets/index-CK_ohh6Q.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-Cg0vCZng.js","sources":["../../src/api/maintenance.ts","../../src/pages/admin/maintenance/controls.tsx","../../src/pages/admin/maintenance/PruneSection.tsx","../../src/pages/admin/maintenance/ScheduleSection.tsx","../../src/pages/admin/maintenance/MaintenancePage.tsx"],"sourcesContent":["import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';\nimport { apiFetch } from './client';\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport interface MaintenanceRule {\n target: 'streams' | 'jobs';\n action: 'delete' | 'prune';\n olderThan: string;\n hasEntity?: boolean;\n pruned?: boolean;\n}\n\nexport interface MaintenanceConfig {\n schedule: string;\n rules: MaintenanceRule[];\n}\n\nexport interface PruneOptions {\n expire?: string;\n jobs?: boolean;\n streams?: boolean;\n engineStreams?: boolean;\n engineStreamsExpire?: string;\n workerStreams?: boolean;\n workerStreamsExpire?: string;\n attributes?: boolean;\n entities?: string[];\n pruneTransient?: boolean;\n keepHmark?: boolean;\n}\n\nexport interface PruneResult {\n jobs?: number;\n streams?: number;\n engineStreams?: number;\n workerStreams?: number;\n attributes?: number;\n transient?: number;\n marked?: number;\n}\n\n// ── Maintenance config ────────────────────────────────────────────────────────\n\nexport function useMaintenanceConfig() {\n return useQuery<{ config: MaintenanceConfig; active: boolean }>({\n queryKey: ['maintenance'],\n queryFn: () => apiFetch('/config/maintenance'),\n });\n}\n\nexport function useUpdateMaintenanceConfig() {\n const queryClient = useQueryClient();\n return useMutation<\n { config: MaintenanceConfig; restarted: boolean },\n Error,\n MaintenanceConfig\n >({\n mutationFn: (config) =>\n apiFetch('/config/maintenance', {\n method: 'PUT',\n body: JSON.stringify(config),\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['maintenance'] });\n },\n });\n}\n\n// ── DBA operations ────────────────────────────────────────────────────────────\n\nexport function usePrune() {\n return useMutation<PruneResult, Error, PruneOptions>({\n mutationFn: (options) =>\n apiFetch('/dba/prune', {\n method: 'POST',\n body: JSON.stringify(options),\n }),\n });\n}\n\nexport function useDeploy() {\n return useMutation<{ ok: boolean }, Error, void>({\n mutationFn: () =>\n apiFetch('/dba/deploy', { method: 'POST' }),\n });\n}\n","import { Info, ShieldCheck, ShieldAlert, ShieldOff } from 'lucide-react';\nimport { RETENTION_PERIOD_OPTIONS } from '../../../lib/constants';\n\n// ── Retention row (checkbox + label + select) ───────────────────────────────\n\nexport function RetentionRow({ checked, onToggle, label, hint, safety, value, onChange }: {\n checked: boolean;\n onToggle: (v: boolean) => void;\n label: string;\n hint: string;\n safety: 'safe' | 'moderate' | 'destructive';\n value: string;\n onChange: (v: string) => void;\n}) {\n const SafetyIcon = safety === 'safe' ? ShieldCheck : safety === 'moderate' ? ShieldAlert : ShieldOff;\n const safetyColor = safety === 'safe' ? 'text-status-success' : safety === 'moderate' ? 'text-status-warning' : 'text-status-error';\n const safetyLabel = safety === 'safe' ? 'Safe' : safety === 'moderate' ? 'Careful' : 'Permanent';\n\n return (\n <div className=\"flex items-center gap-4\">\n <label className=\"flex items-center gap-2.5 cursor-pointer w-80 shrink-0\">\n <input\n type=\"checkbox\"\n checked={checked}\n onChange={(e) => onToggle(e.target.checked)}\n className=\"w-4 h-4 rounded border-border accent-accent shrink-0\"\n />\n <div className=\"flex-1\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-xs text-text-primary\">{label}</span>\n <span className={`flex items-center gap-0.5 text-2xs ${safetyColor}`}>\n <SafetyIcon className=\"w-3 h-3\" strokeWidth={1.5} />\n {safetyLabel}\n </span>\n </div>\n <p className=\"text-2xs text-text-tertiary\">{hint}</p>\n </div>\n </label>\n <select\n value={value}\n onChange={(e) => onChange(e.target.value)}\n disabled={!checked}\n className={`select text-xs w-36 transition-opacity ${!checked ? 'opacity-40 cursor-not-allowed' : ''}`}\n >\n {RETENTION_PERIOD_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>{opt.label}</option>\n ))}\n </select>\n </div>\n );\n}\n\n// ── Cleanup checkbox ────────────────────────────────────────────────────────\n\nexport function CleanupCheck({ checked, onChange, label, description, safety }: {\n checked: boolean;\n onChange: (v: boolean) => void;\n label: string;\n description: string;\n safety: 'safe' | 'moderate' | 'destructive';\n}) {\n const SafetyIcon = safety === 'safe' ? ShieldCheck : safety === 'moderate' ? ShieldAlert : ShieldOff;\n const safetyColor = safety === 'safe' ? 'text-status-success' : safety === 'moderate' ? 'text-status-warning' : 'text-status-error';\n const safetyLabel = safety === 'safe' ? 'Safe' : safety === 'moderate' ? 'Careful' : 'Permanent';\n\n return (\n <label className=\"flex items-start gap-2.5 cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={checked}\n onChange={(e) => onChange(e.target.checked)}\n className=\"w-4 h-4 mt-0.5 rounded border-border accent-accent shrink-0\"\n />\n <div>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-xs text-text-primary\">{label}</span>\n <span className={`flex items-center gap-0.5 text-2xs ${safetyColor}`}>\n <SafetyIcon className=\"w-3 h-3\" strokeWidth={1.5} />\n {safetyLabel}\n </span>\n </div>\n <p className=\"text-2xs text-text-tertiary\">{description}</p>\n </div>\n </label>\n );\n}\n\n// ── Cleanup callout ─────────────────────────────────────────────────────────\n\nexport function CleanupCallout() {\n return (\n <div className=\"flex items-start gap-2 mt-2 px-3 py-2 rounded bg-surface-sunken\">\n <Info className=\"w-3.5 h-3.5 text-text-tertiary shrink-0 mt-0.5\" />\n <p className=\"text-2xs text-text-tertiary leading-relaxed\">\n Stripping preserves workflow results and timeline data needed for the execution detail view.\n Transient jobs are internal bookkeeping that accumulates over time.\n </p>\n </div>\n );\n}\n\n// ── Prune fields state shape (shared between both panels) ───────────────────\n\nexport interface PruneFields {\n pruneJobs: boolean;\n expire: string;\n engineStreams: boolean;\n engineStreamsExpire: string;\n workerStreams: boolean;\n workerStreamsExpire: string;\n stripAttributes: boolean;\n pruneTransient: boolean;\n}\n\nexport const DEFAULT_PRUNE_FIELDS: PruneFields = {\n pruneJobs: true,\n expire: '30 days',\n engineStreams: true,\n engineStreamsExpire: '1 day',\n workerStreams: true,\n workerStreamsExpire: '90 days',\n stripAttributes: false,\n pruneTransient: false,\n};\n\nexport function hasSelection(f: PruneFields): boolean {\n return f.pruneJobs || f.engineStreams || f.workerStreams || f.stripAttributes || f.pruneTransient;\n}\n\n// ── Prune fields editor (reused by both Prune Now and Schedule) ─────────────\n\nexport function PruneFieldsEditor({ fields, onChange }: {\n fields: PruneFields;\n onChange: (f: PruneFields) => void;\n}) {\n const set = <K extends keyof PruneFields>(key: K, value: PruneFields[K]) =>\n onChange({ ...fields, [key]: value });\n\n return (\n <div className=\"space-y-8\">\n {/* Stream messages — always safe to prune */}\n <div>\n <p className=\"text-2xs font-semibold uppercase tracking-widest text-text-tertiary mb-1\">\n Stream Messages\n </p>\n <p className=\"text-2xs text-text-tertiary mb-4\">\n Processed routing messages. Already consumed — safe to remove after a short retention window.\n </p>\n <div className=\"space-y-3\">\n <RetentionRow\n checked={fields.engineStreams} onToggle={(v) => set('engineStreams', v)}\n label=\"Engine messages\" hint=\"Internal orchestration signals\"\n safety=\"safe\"\n value={fields.engineStreamsExpire} onChange={(v) => set('engineStreamsExpire', v)}\n />\n <RetentionRow\n checked={fields.workerStreams} onToggle={(v) => set('workerStreams', v)}\n label=\"Worker messages\" hint=\"Activity dispatch and response payloads\"\n safety=\"safe\"\n value={fields.workerStreamsExpire} onChange={(v) => set('workerStreamsExpire', v)}\n />\n </div>\n </div>\n\n {/* Workflow data — mutually exclusive: reduce OR delete */}\n <div>\n <p className=\"text-2xs font-semibold uppercase tracking-widest text-text-tertiary mb-1\">\n Completed Workflows\n </p>\n <p className=\"text-2xs text-text-tertiary mb-4\">\n Choose how to handle completed workflow records. Reducing strips step-level detail\n but keeps the workflow and its results. Deleting removes the record entirely.\n </p>\n <div className=\"space-y-3\">\n <label className=\"flex items-start gap-2.5 cursor-pointer\">\n <input\n type=\"radio\"\n name=\"workflow-cleanup\"\n checked={!fields.stripAttributes && !fields.pruneJobs}\n onChange={() => onChange({ ...fields, stripAttributes: false, pruneJobs: false })}\n className=\"w-4 h-4 mt-0.5 accent-accent shrink-0\"\n />\n <div>\n <span className=\"text-xs text-text-primary\">Keep as-is</span>\n <p className=\"text-2xs text-text-tertiary\">No changes to completed workflow records.</p>\n </div>\n </label>\n\n <div className=\"flex items-start gap-2.5\">\n <label className=\"flex items-start gap-2.5 cursor-pointer w-80 shrink-0\">\n <input\n type=\"radio\"\n name=\"workflow-cleanup\"\n checked={fields.stripAttributes && !fields.pruneJobs}\n onChange={() => onChange({ ...fields, stripAttributes: true, pruneJobs: false })}\n className=\"w-4 h-4 mt-0.5 accent-accent shrink-0\"\n />\n <div>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-xs text-text-primary\">Reduce completed workflows</span>\n <span className=\"flex items-center gap-0.5 text-2xs text-status-warning\">\n <ShieldAlert className=\"w-3 h-3\" strokeWidth={1.5} />\n Careful\n </span>\n </div>\n <p className=\"text-2xs text-text-tertiary\">\n Strips step-level execution detail (activity inputs/outputs, internal state).\n Workflow results and timeline are preserved.\n </p>\n </div>\n </label>\n <select\n value={fields.expire}\n onChange={(e) => set('expire', e.target.value)}\n disabled={!fields.stripAttributes || fields.pruneJobs}\n className={`select text-xs w-36 transition-opacity mt-0.5 ${!fields.stripAttributes || fields.pruneJobs ? 'opacity-40 cursor-not-allowed' : ''}`}\n >\n {RETENTION_PERIOD_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>{opt.label}</option>\n ))}\n </select>\n </div>\n\n <div className=\"flex items-start gap-2.5\">\n <label className=\"flex items-start gap-2.5 cursor-pointer w-80 shrink-0\">\n <input\n type=\"radio\"\n name=\"workflow-cleanup\"\n checked={fields.pruneJobs}\n onChange={() => onChange({ ...fields, pruneJobs: true, stripAttributes: false })}\n className=\"w-4 h-4 mt-0.5 accent-accent shrink-0\"\n />\n <div>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-xs text-text-primary\">Delete completed workflows</span>\n <span className=\"flex items-center gap-0.5 text-2xs text-status-error\">\n <ShieldOff className=\"w-3 h-3\" strokeWidth={1.5} />\n Permanent\n </span>\n </div>\n <p className=\"text-2xs text-text-tertiary\">\n Permanently removes workflow records. Results, timeline, and all\n execution data are deleted and cannot be recovered.\n </p>\n </div>\n </label>\n <select\n value={fields.expire}\n onChange={(e) => set('expire', e.target.value)}\n disabled={!fields.pruneJobs}\n className={`select text-xs w-36 transition-opacity mt-0.5 ${!fields.pruneJobs ? 'opacity-40 cursor-not-allowed' : ''}`}\n >\n {RETENTION_PERIOD_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>{opt.label}</option>\n ))}\n </select>\n </div>\n </div>\n <CleanupCallout />\n </div>\n </div>\n );\n}\n","import { useState } from 'react';\nimport { usePrune, type PruneResult } from '../../../api/maintenance';\nimport { Modal } from '../../../components/common/modal/Modal';\nimport { PruneFieldsEditor, DEFAULT_PRUNE_FIELDS, hasSelection, type PruneFields } from './controls';\n\nfunction ResultCard({ label, value }: { label: string; value: number }) {\n return (\n <div>\n <p className=\"text-lg font-light text-text-primary\">{value.toLocaleString()}</p>\n <p className=\"text-2xs text-text-tertiary\">{label}</p>\n </div>\n );\n}\n\nexport function PruneSection() {\n const prune = usePrune();\n const [fields, setFields] = useState<PruneFields>(DEFAULT_PRUNE_FIELDS);\n const [result, setResult] = useState<PruneResult | null>(null);\n const [showConfirm, setShowConfirm] = useState(false);\n\n const handlePrune = () => {\n setResult(null);\n prune.mutate(\n {\n expire: fields.expire,\n jobs: fields.pruneJobs,\n engineStreams: fields.engineStreams,\n engineStreamsExpire: fields.engineStreamsExpire,\n workerStreams: fields.workerStreams,\n workerStreamsExpire: fields.workerStreamsExpire,\n attributes: fields.stripAttributes,\n pruneTransient: fields.pruneTransient,\n },\n {\n onSuccess: (data) => {\n setResult(data);\n setShowConfirm(false);\n },\n },\n );\n };\n\n return (\n <div className=\"space-y-8\">\n <PruneFieldsEditor fields={fields} onChange={setFields} />\n\n {/* Action bar */}\n <div className=\"flex items-center justify-between pt-2 border-t border-surface-border\">\n <p className=\"text-2xs text-text-tertiary\">\n {!hasSelection(fields)\n ? 'Select at least one operation to enable pruning.'\n : 'This action permanently deletes data and cannot be undone.'}\n </p>\n <button\n onClick={() => setShowConfirm(true)}\n disabled={!hasSelection(fields) || prune.isPending}\n className=\"bg-status-error text-text-inverse px-4 py-1.5 rounded-md text-xs hover:opacity-90 transition-opacity disabled:opacity-40 shrink-0\"\n >\n {prune.isPending ? 'Pruning...' : 'Prune Now'}\n </button>\n </div>\n\n {/* Results */}\n {result && (\n <div className=\"bg-surface-sunken rounded-md px-4 py-3\">\n <p className=\"text-2xs font-semibold uppercase tracking-widest text-text-tertiary mb-2\">\n Results\n </p>\n <div className=\"flex flex-wrap gap-6\">\n {result.jobs != null && result.jobs > 0 && <ResultCard label=\"Jobs deleted\" value={result.jobs} />}\n {result.engineStreams != null && result.engineStreams > 0 && <ResultCard label=\"Engine streams\" value={result.engineStreams} />}\n {result.workerStreams != null && result.workerStreams > 0 && <ResultCard label=\"Worker streams\" value={result.workerStreams} />}\n {result.streams != null && result.engineStreams == null && result.streams > 0 && <ResultCard label=\"Streams\" value={result.streams} />}\n {result.attributes != null && result.attributes > 0 && <ResultCard label=\"Artifacts stripped\" value={result.attributes} />}\n {result.transient != null && result.transient > 0 && <ResultCard label=\"Transient deleted\" value={result.transient} />}\n {result.marked != null && result.marked > 0 && <ResultCard label=\"Marked pruned\" value={result.marked} />}\n {Object.values(result).every((v) => !v || v === 0) && (\n <p className=\"text-xs text-text-tertiary\">Nothing to prune within the selected retention windows.</p>\n )}\n </div>\n </div>\n )}\n\n {prune.error && (\n <p className=\"text-xs text-status-error\">{(prune.error as Error).message}</p>\n )}\n\n {/* Confirm modal */}\n <Modal open={showConfirm} onClose={() => setShowConfirm(false)} title=\"Confirm Prune\">\n <div className=\"space-y-4\">\n <p className=\"text-sm text-text-secondary\">\n This will permanently delete data. This action cannot be undone.\n </p>\n <ul className=\"text-xs text-text-secondary space-y-1 list-disc list-inside\">\n {fields.pruneJobs && <li>Delete jobs older than {fields.expire}</li>}\n {fields.engineStreams && <li>Delete engine streams older than {fields.engineStreamsExpire}</li>}\n {fields.workerStreams && <li>Delete worker streams older than {fields.workerStreamsExpire}</li>}\n {fields.stripAttributes && <li>Strip execution artifacts from completed jobs</li>}\n {fields.pruneTransient && <li>Delete transient (entity-less) jobs</li>}\n </ul>\n <div className=\"flex justify-end gap-3 pt-2\">\n <button onClick={() => setShowConfirm(false)} className=\"btn-secondary text-xs\">Cancel</button>\n <button\n onClick={handlePrune}\n className=\"bg-status-error text-text-inverse px-3 py-1.5 rounded-md text-xs hover:opacity-90 transition-opacity\"\n disabled={prune.isPending}\n >\n {prune.isPending ? 'Pruning...' : 'Confirm Prune'}\n </button>\n </div>\n </div>\n </Modal>\n </div>\n );\n}\n","import { useState, useEffect, useCallback } from 'react';\nimport { Info } from 'lucide-react';\nimport {\n useMaintenanceConfig,\n useUpdateMaintenanceConfig,\n type MaintenanceConfig,\n} from '../../../api/maintenance';\nimport { CRON_PRESETS } from '../../../lib/constants';\nimport { PruneFieldsEditor, DEFAULT_PRUNE_FIELDS, type PruneFields } from './controls';\n\n// ── Helpers ─────────────────────────────────────────────────────────────────\n\n/** Convert a MaintenanceConfig (rules array) into PruneFields for the editor. */\nfunction configToFields(config: MaintenanceConfig | undefined): PruneFields {\n if (!config?.rules?.length) return DEFAULT_PRUNE_FIELDS;\n const r = config.rules;\n const streamDelete = r.find((x) => x.target === 'streams' && x.action === 'delete');\n const jobDeleteTransient = r.find((x) => x.target === 'jobs' && x.action === 'delete' && x.hasEntity === false);\n const jobPrune = r.find((x) => x.target === 'jobs' && x.action === 'prune' && x.hasEntity === true);\n const jobDeletePruned = r.find((x) => x.target === 'jobs' && x.action === 'delete' && x.pruned === true);\n return {\n pruneJobs: !!jobDeletePruned,\n expire: jobDeletePruned?.olderThan ?? '180 days',\n engineStreams: !!streamDelete,\n engineStreamsExpire: streamDelete?.olderThan ?? '1 day',\n workerStreams: !!streamDelete,\n workerStreamsExpire: streamDelete?.olderThan ?? '90 days',\n stripAttributes: !!jobPrune,\n pruneTransient: !!jobDeleteTransient,\n };\n}\n\n/** Convert PruneFields back to a MaintenanceConfig rules array. */\nfunction fieldsToRules(f: PruneFields): MaintenanceConfig['rules'] {\n const rules: MaintenanceConfig['rules'] = [];\n if (f.engineStreams) {\n rules.push({ target: 'streams', action: 'delete', olderThan: f.engineStreamsExpire });\n }\n if (f.workerStreams && f.workerStreamsExpire !== f.engineStreamsExpire) {\n rules.push({ target: 'streams', action: 'delete', olderThan: f.workerStreamsExpire });\n }\n if (f.pruneTransient) {\n rules.push({ target: 'jobs', action: 'delete', olderThan: f.expire, hasEntity: false });\n }\n if (f.stripAttributes) {\n rules.push({ target: 'jobs', action: 'prune', olderThan: f.expire, hasEntity: true });\n }\n if (f.pruneJobs) {\n rules.push({ target: 'jobs', action: 'delete', olderThan: f.expire, pruned: true });\n }\n return rules;\n}\n\nfunction describeCron(expr: string): string {\n return CRON_PRESETS.find((p) => p.value === expr)?.label ?? '';\n}\n\n// ── Main ────────────────────────────────────────────────────────────────────\n\nexport function ScheduleSection() {\n const { data, isLoading } = useMaintenanceConfig();\n const updateConfig = useUpdateMaintenanceConfig();\n\n const [schedule, setSchedule] = useState('');\n const [fields, setFields] = useState<PruneFields>(DEFAULT_PRUNE_FIELDS);\n const [savedSnapshot, setSavedSnapshot] = useState('');\n\n // Sync from server config when loaded\n const syncFromServer = useCallback(() => {\n if (!data?.config) return;\n setSchedule(data.config.schedule);\n setFields(configToFields(data.config));\n setSavedSnapshot(JSON.stringify({ schedule: data.config.schedule, fields: configToFields(data.config) }));\n }, [data]);\n\n useEffect(() => { syncFromServer(); }, [syncFromServer]);\n\n const currentSnapshot = JSON.stringify({ schedule, fields });\n const isDirty = savedSnapshot !== '' && currentSnapshot !== savedSnapshot;\n const active = data?.active ?? false;\n\n const handleSave = () => {\n const rules = fieldsToRules(fields);\n updateConfig.mutate(\n { schedule, rules },\n {\n onSuccess: () => {\n setSavedSnapshot(JSON.stringify({ schedule, fields }));\n },\n },\n );\n };\n\n const handleRevert = () => {\n syncFromServer();\n };\n\n if (isLoading) {\n return <div className=\"animate-pulse h-40 bg-surface-sunken rounded\" />;\n }\n\n return (\n <div className=\"space-y-8\">\n {/* Cron schedule + status */}\n <div className=\"grid grid-cols-1 @split:grid-cols-[1fr_auto] gap-10\">\n <div>\n <p className=\"text-2xs font-semibold uppercase tracking-widest text-text-tertiary mb-4\">\n Schedule\n </p>\n <div className=\"flex items-end gap-4\">\n <div>\n <label className=\"block text-2xs text-text-tertiary mb-1\">Cron Expression</label>\n <input\n type=\"text\"\n value={schedule}\n onChange={(e) => setSchedule(e.target.value)}\n placeholder=\"0 2 * * *\"\n className=\"input text-xs font-mono w-48\"\n />\n </div>\n <div>\n <div className=\"flex items-center gap-1.5 h-8\">\n <span className={`w-2.5 h-2.5 rounded-full dot-ring ${active ? 'bg-status-success' : 'bg-text-tertiary'}`} />\n <span className={`text-xs ${active ? 'text-status-success' : 'text-text-tertiary'}`}>\n {active ? 'Active' : 'Inactive'}\n </span>\n </div>\n </div>\n {describeCron(schedule) && (\n <p className=\"text-xs text-text-tertiary h-8 flex items-center\">{describeCron(schedule)}</p>\n )}\n </div>\n\n {/* Preset pills */}\n <div className=\"flex flex-wrap gap-1.5 mt-3\">\n {CRON_PRESETS.map((preset) => (\n <button\n key={preset.value}\n type=\"button\"\n onClick={() => setSchedule(preset.value)}\n className={`px-2.5 py-1 text-2xs rounded-full transition-colors ${\n schedule === preset.value\n ? 'bg-accent/10 text-accent font-medium'\n : 'bg-surface-sunken text-text-tertiary hover:text-text-secondary'\n }`}\n >\n {preset.label}\n </button>\n ))}\n </div>\n </div>\n\n <div className=\"lg:w-72\">\n <p className=\"text-2xs font-semibold uppercase tracking-widest text-text-tertiary mb-4\">\n How It Works\n </p>\n <div className=\"flex items-start gap-2 px-3 py-2 rounded bg-surface-sunken\">\n <Info className=\"w-3.5 h-3.5 text-text-tertiary shrink-0 mt-0.5\" />\n <p className=\"text-2xs text-text-tertiary leading-relaxed\">\n Rules execute sequentially on each cron cycle. Engine streams can be pruned aggressively\n since they only contain internal routing data. Worker streams should be retained longer\n to preserve execution playback and input enrichment.\n </p>\n </div>\n </div>\n </div>\n\n {/* Same prune fields as Prune Now */}\n <PruneFieldsEditor fields={fields} onChange={setFields} />\n\n {/* Action bar */}\n <div className=\"flex items-center justify-between pt-2 border-t border-surface-border\">\n <div className=\"flex items-center gap-3\">\n {isDirty && (\n <button\n onClick={handleRevert}\n className=\"text-2xs text-text-tertiary hover:text-text-primary transition-colors\"\n >\n Revert changes\n </button>\n )}\n {updateConfig.error && (\n <p className=\"text-xs text-status-error\">{(updateConfig.error as Error).message}</p>\n )}\n </div>\n <button\n onClick={handleSave}\n disabled={!isDirty || !schedule.trim() || updateConfig.isPending}\n className=\"btn-primary text-xs disabled:opacity-40 shrink-0\"\n >\n {updateConfig.isPending ? 'Saving...' : 'Save Schedule'}\n </button>\n </div>\n </div>\n );\n}\n","import { useState } from 'react';\nimport { Trash2, Clock, Info } from 'lucide-react';\nimport { PageHeader } from '../../../components/common/layout/PageHeader';\nimport { PruneSection } from './PruneSection';\nimport { ScheduleSection } from './ScheduleSection';\n\ntype Mode = 'prune' | 'schedule';\n\nfunction ModeToggle({ mode, onChange }: { mode: Mode; onChange: (m: Mode) => void }) {\n const btn = (m: Mode, icon: React.ReactNode, label: string) => (\n <button\n onClick={() => onChange(m)}\n className={`flex items-center gap-1.5 px-3 py-1.5 text-xs rounded-md transition-colors ${\n mode === m\n ? 'bg-accent/10 text-accent font-medium'\n : 'text-text-tertiary hover:text-text-secondary hover:bg-surface-hover'\n }`}\n >\n {icon}\n {label}\n </button>\n );\n\n return (\n <div className=\"flex gap-1 p-0.5 bg-surface-sunken rounded-lg w-fit\">\n {btn('prune', <Trash2 className=\"w-3.5 h-3.5\" />, 'Prune Now')}\n {btn('schedule', <Clock className=\"w-3.5 h-3.5\" />, 'Schedule')}\n </div>\n );\n}\n\nexport function MaintenancePage() {\n const [mode, setMode] = useState<Mode>('schedule');\n\n return (\n <div>\n <PageHeader\n title=\"DB Maintenance\"\n docsHash=\"#docs:dashboard.md:db-maintenance\"\n actions={<ModeToggle mode={mode} onChange={setMode} />}\n />\n\n <div className=\"flex items-start gap-2 px-4 py-3 mb-8 rounded-md bg-accent/5 border border-accent/10\">\n <Info className=\"w-4 h-4 text-accent shrink-0 mt-0.5\" />\n <p className=\"text-xs text-text-secondary leading-relaxed\">\n Workflow data grows as jobs complete. Operations are ordered safest-first: stream messages are\n always safe to prune, workflow reduction preserves results, and deletion is permanent.\n </p>\n </div>\n\n {mode === 'prune' ? <PruneSection /> : <ScheduleSection />}\n </div>\n );\n}\n"],"names":["useMaintenanceConfig","useQuery","apiFetch","useUpdateMaintenanceConfig","queryClient","useQueryClient","useMutation","config","usePrune","options","RetentionRow","checked","onToggle","label","hint","safety","value","onChange","SafetyIcon","ShieldCheck","ShieldAlert","ShieldOff","safetyColor","safetyLabel","jsxs","jsx","e","RETENTION_PERIOD_OPTIONS","opt","CleanupCallout","Info","DEFAULT_PRUNE_FIELDS","hasSelection","f","PruneFieldsEditor","fields","set","key","v","ResultCard","PruneSection","prune","setFields","useState","result","setResult","showConfirm","setShowConfirm","handlePrune","data","Modal","configToFields","_a","streamDelete","x","jobDeleteTransient","jobPrune","jobDeletePruned","fieldsToRules","rules","describeCron","expr","CRON_PRESETS","p","ScheduleSection","isLoading","updateConfig","schedule","setSchedule","savedSnapshot","setSavedSnapshot","syncFromServer","useCallback","useEffect","currentSnapshot","isDirty","active","handleSave","handleRevert","preset","ModeToggle","mode","btn","m","icon","Trash2","Clock","MaintenancePage","setMode","PageHeader"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index-DazfFRUx.js","sources":["../../src/api/maintenance.ts","../../src/pages/admin/maintenance/controls.tsx","../../src/pages/admin/maintenance/PruneSection.tsx","../../src/pages/admin/maintenance/ScheduleSection.tsx","../../src/pages/admin/maintenance/MaintenancePage.tsx"],"sourcesContent":["import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';\nimport { apiFetch } from './client';\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport interface MaintenanceRule {\n target: 'streams' | 'jobs';\n action: 'delete' | 'prune';\n olderThan: string;\n hasEntity?: boolean;\n pruned?: boolean;\n}\n\nexport interface MaintenanceConfig {\n schedule: string;\n rules: MaintenanceRule[];\n}\n\nexport interface PruneOptions {\n expire?: string;\n jobs?: boolean;\n streams?: boolean;\n engineStreams?: boolean;\n engineStreamsExpire?: string;\n workerStreams?: boolean;\n workerStreamsExpire?: string;\n attributes?: boolean;\n entities?: string[];\n pruneTransient?: boolean;\n keepHmark?: boolean;\n}\n\nexport interface PruneResult {\n jobs?: number;\n streams?: number;\n engineStreams?: number;\n workerStreams?: number;\n attributes?: number;\n transient?: number;\n marked?: number;\n}\n\n// ── Maintenance config ────────────────────────────────────────────────────────\n\nexport function useMaintenanceConfig() {\n return useQuery<{ config: MaintenanceConfig; active: boolean }>({\n queryKey: ['maintenance'],\n queryFn: () => apiFetch('/config/maintenance'),\n });\n}\n\nexport function useUpdateMaintenanceConfig() {\n const queryClient = useQueryClient();\n return useMutation<\n { config: MaintenanceConfig; restarted: boolean },\n Error,\n MaintenanceConfig\n >({\n mutationFn: (config) =>\n apiFetch('/config/maintenance', {\n method: 'PUT',\n body: JSON.stringify(config),\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['maintenance'] });\n },\n });\n}\n\n// ── DBA operations ────────────────────────────────────────────────────────────\n\nexport function usePrune() {\n return useMutation<PruneResult, Error, PruneOptions>({\n mutationFn: (options) =>\n apiFetch('/dba/prune', {\n method: 'POST',\n body: JSON.stringify(options),\n }),\n });\n}\n\nexport function useDeploy() {\n return useMutation<{ ok: boolean }, Error, void>({\n mutationFn: () =>\n apiFetch('/dba/deploy', { method: 'POST' }),\n });\n}\n","import { Info, ShieldCheck, ShieldAlert, ShieldOff } from 'lucide-react';\nimport { RETENTION_PERIOD_OPTIONS } from '../../../lib/constants';\n\n// ── Retention row (checkbox + label + select) ───────────────────────────────\n\nexport function RetentionRow({ checked, onToggle, label, hint, safety, value, onChange }: {\n checked: boolean;\n onToggle: (v: boolean) => void;\n label: string;\n hint: string;\n safety: 'safe' | 'moderate' | 'destructive';\n value: string;\n onChange: (v: string) => void;\n}) {\n const SafetyIcon = safety === 'safe' ? ShieldCheck : safety === 'moderate' ? ShieldAlert : ShieldOff;\n const safetyColor = safety === 'safe' ? 'text-status-success' : safety === 'moderate' ? 'text-status-warning' : 'text-status-error';\n const safetyLabel = safety === 'safe' ? 'Safe' : safety === 'moderate' ? 'Careful' : 'Permanent';\n\n return (\n <div className=\"flex items-center gap-4\">\n <label className=\"flex items-center gap-2.5 cursor-pointer w-80 shrink-0\">\n <input\n type=\"checkbox\"\n checked={checked}\n onChange={(e) => onToggle(e.target.checked)}\n className=\"w-4 h-4 rounded border-border accent-accent shrink-0\"\n />\n <div className=\"flex-1\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-xs text-text-primary\">{label}</span>\n <span className={`flex items-center gap-0.5 text-2xs ${safetyColor}`}>\n <SafetyIcon className=\"w-3 h-3\" strokeWidth={1.5} />\n {safetyLabel}\n </span>\n </div>\n <p className=\"text-2xs text-text-tertiary\">{hint}</p>\n </div>\n </label>\n <select\n value={value}\n onChange={(e) => onChange(e.target.value)}\n disabled={!checked}\n className={`select text-xs w-36 transition-opacity ${!checked ? 'opacity-40 cursor-not-allowed' : ''}`}\n >\n {RETENTION_PERIOD_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>{opt.label}</option>\n ))}\n </select>\n </div>\n );\n}\n\n// ── Cleanup checkbox ────────────────────────────────────────────────────────\n\nexport function CleanupCheck({ checked, onChange, label, description, safety }: {\n checked: boolean;\n onChange: (v: boolean) => void;\n label: string;\n description: string;\n safety: 'safe' | 'moderate' | 'destructive';\n}) {\n const SafetyIcon = safety === 'safe' ? ShieldCheck : safety === 'moderate' ? ShieldAlert : ShieldOff;\n const safetyColor = safety === 'safe' ? 'text-status-success' : safety === 'moderate' ? 'text-status-warning' : 'text-status-error';\n const safetyLabel = safety === 'safe' ? 'Safe' : safety === 'moderate' ? 'Careful' : 'Permanent';\n\n return (\n <label className=\"flex items-start gap-2.5 cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={checked}\n onChange={(e) => onChange(e.target.checked)}\n className=\"w-4 h-4 mt-0.5 rounded border-border accent-accent shrink-0\"\n />\n <div>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-xs text-text-primary\">{label}</span>\n <span className={`flex items-center gap-0.5 text-2xs ${safetyColor}`}>\n <SafetyIcon className=\"w-3 h-3\" strokeWidth={1.5} />\n {safetyLabel}\n </span>\n </div>\n <p className=\"text-2xs text-text-tertiary\">{description}</p>\n </div>\n </label>\n );\n}\n\n// ── Cleanup callout ─────────────────────────────────────────────────────────\n\nexport function CleanupCallout() {\n return (\n <div className=\"flex items-start gap-2 mt-2 px-3 py-2 rounded bg-surface-sunken\">\n <Info className=\"w-3.5 h-3.5 text-text-tertiary shrink-0 mt-0.5\" />\n <p className=\"text-2xs text-text-tertiary leading-relaxed\">\n Stripping preserves workflow results and timeline data needed for the execution detail view.\n Transient jobs are internal bookkeeping that accumulates over time.\n </p>\n </div>\n );\n}\n\n// ── Prune fields state shape (shared between both panels) ───────────────────\n\nexport interface PruneFields {\n pruneJobs: boolean;\n expire: string;\n engineStreams: boolean;\n engineStreamsExpire: string;\n workerStreams: boolean;\n workerStreamsExpire: string;\n stripAttributes: boolean;\n pruneTransient: boolean;\n}\n\nexport const DEFAULT_PRUNE_FIELDS: PruneFields = {\n pruneJobs: true,\n expire: '30 days',\n engineStreams: true,\n engineStreamsExpire: '1 day',\n workerStreams: true,\n workerStreamsExpire: '90 days',\n stripAttributes: false,\n pruneTransient: false,\n};\n\nexport function hasSelection(f: PruneFields): boolean {\n return f.pruneJobs || f.engineStreams || f.workerStreams || f.stripAttributes || f.pruneTransient;\n}\n\n// ── Prune fields editor (reused by both Prune Now and Schedule) ─────────────\n\nexport function PruneFieldsEditor({ fields, onChange }: {\n fields: PruneFields;\n onChange: (f: PruneFields) => void;\n}) {\n const set = <K extends keyof PruneFields>(key: K, value: PruneFields[K]) =>\n onChange({ ...fields, [key]: value });\n\n return (\n <div className=\"space-y-8\">\n {/* Stream messages — always safe to prune */}\n <div>\n <p className=\"text-2xs font-semibold uppercase tracking-widest text-text-tertiary mb-1\">\n Stream Messages\n </p>\n <p className=\"text-2xs text-text-tertiary mb-4\">\n Processed routing messages. Already consumed — safe to remove after a short retention window.\n </p>\n <div className=\"space-y-3\">\n <RetentionRow\n checked={fields.engineStreams} onToggle={(v) => set('engineStreams', v)}\n label=\"Engine messages\" hint=\"Internal orchestration signals\"\n safety=\"safe\"\n value={fields.engineStreamsExpire} onChange={(v) => set('engineStreamsExpire', v)}\n />\n <RetentionRow\n checked={fields.workerStreams} onToggle={(v) => set('workerStreams', v)}\n label=\"Worker messages\" hint=\"Activity dispatch and response payloads\"\n safety=\"safe\"\n value={fields.workerStreamsExpire} onChange={(v) => set('workerStreamsExpire', v)}\n />\n </div>\n </div>\n\n {/* Workflow data — mutually exclusive: reduce OR delete */}\n <div>\n <p className=\"text-2xs font-semibold uppercase tracking-widest text-text-tertiary mb-1\">\n Completed Workflows\n </p>\n <p className=\"text-2xs text-text-tertiary mb-4\">\n Choose how to handle completed workflow records. Reducing strips step-level detail\n but keeps the workflow and its results. Deleting removes the record entirely.\n </p>\n <div className=\"space-y-3\">\n <label className=\"flex items-start gap-2.5 cursor-pointer\">\n <input\n type=\"radio\"\n name=\"workflow-cleanup\"\n checked={!fields.stripAttributes && !fields.pruneJobs}\n onChange={() => onChange({ ...fields, stripAttributes: false, pruneJobs: false })}\n className=\"w-4 h-4 mt-0.5 accent-accent shrink-0\"\n />\n <div>\n <span className=\"text-xs text-text-primary\">Keep as-is</span>\n <p className=\"text-2xs text-text-tertiary\">No changes to completed workflow records.</p>\n </div>\n </label>\n\n <div className=\"flex items-start gap-2.5\">\n <label className=\"flex items-start gap-2.5 cursor-pointer w-80 shrink-0\">\n <input\n type=\"radio\"\n name=\"workflow-cleanup\"\n checked={fields.stripAttributes && !fields.pruneJobs}\n onChange={() => onChange({ ...fields, stripAttributes: true, pruneJobs: false })}\n className=\"w-4 h-4 mt-0.5 accent-accent shrink-0\"\n />\n <div>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-xs text-text-primary\">Reduce completed workflows</span>\n <span className=\"flex items-center gap-0.5 text-2xs text-status-warning\">\n <ShieldAlert className=\"w-3 h-3\" strokeWidth={1.5} />\n Careful\n </span>\n </div>\n <p className=\"text-2xs text-text-tertiary\">\n Strips step-level execution detail (activity inputs/outputs, internal state).\n Workflow results and timeline are preserved.\n </p>\n </div>\n </label>\n <select\n value={fields.expire}\n onChange={(e) => set('expire', e.target.value)}\n disabled={!fields.stripAttributes || fields.pruneJobs}\n className={`select text-xs w-36 transition-opacity mt-0.5 ${!fields.stripAttributes || fields.pruneJobs ? 'opacity-40 cursor-not-allowed' : ''}`}\n >\n {RETENTION_PERIOD_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>{opt.label}</option>\n ))}\n </select>\n </div>\n\n <div className=\"flex items-start gap-2.5\">\n <label className=\"flex items-start gap-2.5 cursor-pointer w-80 shrink-0\">\n <input\n type=\"radio\"\n name=\"workflow-cleanup\"\n checked={fields.pruneJobs}\n onChange={() => onChange({ ...fields, pruneJobs: true, stripAttributes: false })}\n className=\"w-4 h-4 mt-0.5 accent-accent shrink-0\"\n />\n <div>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-xs text-text-primary\">Delete completed workflows</span>\n <span className=\"flex items-center gap-0.5 text-2xs text-status-error\">\n <ShieldOff className=\"w-3 h-3\" strokeWidth={1.5} />\n Permanent\n </span>\n </div>\n <p className=\"text-2xs text-text-tertiary\">\n Permanently removes workflow records. Results, timeline, and all\n execution data are deleted and cannot be recovered.\n </p>\n </div>\n </label>\n <select\n value={fields.expire}\n onChange={(e) => set('expire', e.target.value)}\n disabled={!fields.pruneJobs}\n className={`select text-xs w-36 transition-opacity mt-0.5 ${!fields.pruneJobs ? 'opacity-40 cursor-not-allowed' : ''}`}\n >\n {RETENTION_PERIOD_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>{opt.label}</option>\n ))}\n </select>\n </div>\n </div>\n <CleanupCallout />\n </div>\n </div>\n );\n}\n","import { useState } from 'react';\nimport { usePrune, type PruneResult } from '../../../api/maintenance';\nimport { Modal } from '../../../components/common/modal/Modal';\nimport { PruneFieldsEditor, DEFAULT_PRUNE_FIELDS, hasSelection, type PruneFields } from './controls';\n\nfunction ResultCard({ label, value }: { label: string; value: number }) {\n return (\n <div>\n <p className=\"text-lg font-light text-text-primary\">{value.toLocaleString()}</p>\n <p className=\"text-2xs text-text-tertiary\">{label}</p>\n </div>\n );\n}\n\nexport function PruneSection() {\n const prune = usePrune();\n const [fields, setFields] = useState<PruneFields>(DEFAULT_PRUNE_FIELDS);\n const [result, setResult] = useState<PruneResult | null>(null);\n const [showConfirm, setShowConfirm] = useState(false);\n\n const handlePrune = () => {\n setResult(null);\n prune.mutate(\n {\n expire: fields.expire,\n jobs: fields.pruneJobs,\n engineStreams: fields.engineStreams,\n engineStreamsExpire: fields.engineStreamsExpire,\n workerStreams: fields.workerStreams,\n workerStreamsExpire: fields.workerStreamsExpire,\n attributes: fields.stripAttributes,\n pruneTransient: fields.pruneTransient,\n },\n {\n onSuccess: (data) => {\n setResult(data);\n setShowConfirm(false);\n },\n },\n );\n };\n\n return (\n <div className=\"space-y-8\">\n <PruneFieldsEditor fields={fields} onChange={setFields} />\n\n {/* Action bar */}\n <div className=\"flex items-center justify-between pt-2 border-t border-surface-border\">\n <p className=\"text-2xs text-text-tertiary\">\n {!hasSelection(fields)\n ? 'Select at least one operation to enable pruning.'\n : 'This action permanently deletes data and cannot be undone.'}\n </p>\n <button\n onClick={() => setShowConfirm(true)}\n disabled={!hasSelection(fields) || prune.isPending}\n className=\"bg-status-error text-text-inverse px-4 py-1.5 rounded-md text-xs hover:opacity-90 transition-opacity disabled:opacity-40 shrink-0\"\n >\n {prune.isPending ? 'Pruning...' : 'Prune Now'}\n </button>\n </div>\n\n {/* Results */}\n {result && (\n <div className=\"bg-surface-sunken rounded-md px-4 py-3\">\n <p className=\"text-2xs font-semibold uppercase tracking-widest text-text-tertiary mb-2\">\n Results\n </p>\n <div className=\"flex flex-wrap gap-6\">\n {result.jobs != null && result.jobs > 0 && <ResultCard label=\"Jobs deleted\" value={result.jobs} />}\n {result.engineStreams != null && result.engineStreams > 0 && <ResultCard label=\"Engine streams\" value={result.engineStreams} />}\n {result.workerStreams != null && result.workerStreams > 0 && <ResultCard label=\"Worker streams\" value={result.workerStreams} />}\n {result.streams != null && result.engineStreams == null && result.streams > 0 && <ResultCard label=\"Streams\" value={result.streams} />}\n {result.attributes != null && result.attributes > 0 && <ResultCard label=\"Artifacts stripped\" value={result.attributes} />}\n {result.transient != null && result.transient > 0 && <ResultCard label=\"Transient deleted\" value={result.transient} />}\n {result.marked != null && result.marked > 0 && <ResultCard label=\"Marked pruned\" value={result.marked} />}\n {Object.values(result).every((v) => !v || v === 0) && (\n <p className=\"text-xs text-text-tertiary\">Nothing to prune within the selected retention windows.</p>\n )}\n </div>\n </div>\n )}\n\n {prune.error && (\n <p className=\"text-xs text-status-error\">{(prune.error as Error).message}</p>\n )}\n\n {/* Confirm modal */}\n <Modal open={showConfirm} onClose={() => setShowConfirm(false)} title=\"Confirm Prune\">\n <div className=\"space-y-4\">\n <p className=\"text-sm text-text-secondary\">\n This will permanently delete data. This action cannot be undone.\n </p>\n <ul className=\"text-xs text-text-secondary space-y-1 list-disc list-inside\">\n {fields.pruneJobs && <li>Delete jobs older than {fields.expire}</li>}\n {fields.engineStreams && <li>Delete engine streams older than {fields.engineStreamsExpire}</li>}\n {fields.workerStreams && <li>Delete worker streams older than {fields.workerStreamsExpire}</li>}\n {fields.stripAttributes && <li>Strip execution artifacts from completed jobs</li>}\n {fields.pruneTransient && <li>Delete transient (entity-less) jobs</li>}\n </ul>\n <div className=\"flex justify-end gap-3 pt-2\">\n <button onClick={() => setShowConfirm(false)} className=\"btn-secondary text-xs\">Cancel</button>\n <button\n onClick={handlePrune}\n className=\"bg-status-error text-text-inverse px-3 py-1.5 rounded-md text-xs hover:opacity-90 transition-opacity\"\n disabled={prune.isPending}\n >\n {prune.isPending ? 'Pruning...' : 'Confirm Prune'}\n </button>\n </div>\n </div>\n </Modal>\n </div>\n );\n}\n","import { useState, useEffect, useCallback } from 'react';\nimport { Info } from 'lucide-react';\nimport {\n useMaintenanceConfig,\n useUpdateMaintenanceConfig,\n type MaintenanceConfig,\n} from '../../../api/maintenance';\nimport { CRON_PRESETS } from '../../../lib/constants';\nimport { PruneFieldsEditor, DEFAULT_PRUNE_FIELDS, type PruneFields } from './controls';\n\n// ── Helpers ─────────────────────────────────────────────────────────────────\n\n/** Convert a MaintenanceConfig (rules array) into PruneFields for the editor. */\nfunction configToFields(config: MaintenanceConfig | undefined): PruneFields {\n if (!config?.rules?.length) return DEFAULT_PRUNE_FIELDS;\n const r = config.rules;\n const streamDelete = r.find((x) => x.target === 'streams' && x.action === 'delete');\n const jobDeleteTransient = r.find((x) => x.target === 'jobs' && x.action === 'delete' && x.hasEntity === false);\n const jobPrune = r.find((x) => x.target === 'jobs' && x.action === 'prune' && x.hasEntity === true);\n const jobDeletePruned = r.find((x) => x.target === 'jobs' && x.action === 'delete' && x.pruned === true);\n return {\n pruneJobs: !!jobDeletePruned,\n expire: jobDeletePruned?.olderThan ?? '180 days',\n engineStreams: !!streamDelete,\n engineStreamsExpire: streamDelete?.olderThan ?? '1 day',\n workerStreams: !!streamDelete,\n workerStreamsExpire: streamDelete?.olderThan ?? '90 days',\n stripAttributes: !!jobPrune,\n pruneTransient: !!jobDeleteTransient,\n };\n}\n\n/** Convert PruneFields back to a MaintenanceConfig rules array. */\nfunction fieldsToRules(f: PruneFields): MaintenanceConfig['rules'] {\n const rules: MaintenanceConfig['rules'] = [];\n if (f.engineStreams) {\n rules.push({ target: 'streams', action: 'delete', olderThan: f.engineStreamsExpire });\n }\n if (f.workerStreams && f.workerStreamsExpire !== f.engineStreamsExpire) {\n rules.push({ target: 'streams', action: 'delete', olderThan: f.workerStreamsExpire });\n }\n if (f.pruneTransient) {\n rules.push({ target: 'jobs', action: 'delete', olderThan: f.expire, hasEntity: false });\n }\n if (f.stripAttributes) {\n rules.push({ target: 'jobs', action: 'prune', olderThan: f.expire, hasEntity: true });\n }\n if (f.pruneJobs) {\n rules.push({ target: 'jobs', action: 'delete', olderThan: f.expire, pruned: true });\n }\n return rules;\n}\n\nfunction describeCron(expr: string): string {\n return CRON_PRESETS.find((p) => p.value === expr)?.label ?? '';\n}\n\n// ── Main ────────────────────────────────────────────────────────────────────\n\nexport function ScheduleSection() {\n const { data, isLoading } = useMaintenanceConfig();\n const updateConfig = useUpdateMaintenanceConfig();\n\n const [schedule, setSchedule] = useState('');\n const [fields, setFields] = useState<PruneFields>(DEFAULT_PRUNE_FIELDS);\n const [savedSnapshot, setSavedSnapshot] = useState('');\n\n // Sync from server config when loaded\n const syncFromServer = useCallback(() => {\n if (!data?.config) return;\n setSchedule(data.config.schedule);\n setFields(configToFields(data.config));\n setSavedSnapshot(JSON.stringify({ schedule: data.config.schedule, fields: configToFields(data.config) }));\n }, [data]);\n\n useEffect(() => { syncFromServer(); }, [syncFromServer]);\n\n const currentSnapshot = JSON.stringify({ schedule, fields });\n const isDirty = savedSnapshot !== '' && currentSnapshot !== savedSnapshot;\n const active = data?.active ?? false;\n\n const handleSave = () => {\n const rules = fieldsToRules(fields);\n updateConfig.mutate(\n { schedule, rules },\n {\n onSuccess: () => {\n setSavedSnapshot(JSON.stringify({ schedule, fields }));\n },\n },\n );\n };\n\n const handleRevert = () => {\n syncFromServer();\n };\n\n if (isLoading) {\n return <div className=\"animate-pulse h-40 bg-surface-sunken rounded\" />;\n }\n\n return (\n <div className=\"space-y-8\">\n {/* Cron schedule + status */}\n <div className=\"grid grid-cols-1 @split:grid-cols-[1fr_auto] gap-10\">\n <div>\n <p className=\"text-2xs font-semibold uppercase tracking-widest text-text-tertiary mb-4\">\n Schedule\n </p>\n <div className=\"flex items-end gap-4\">\n <div>\n <label className=\"block text-2xs text-text-tertiary mb-1\">Cron Expression</label>\n <input\n type=\"text\"\n value={schedule}\n onChange={(e) => setSchedule(e.target.value)}\n placeholder=\"0 2 * * *\"\n className=\"input text-xs font-mono w-48\"\n />\n </div>\n <div>\n <div className=\"flex items-center gap-1.5 h-8\">\n <span className={`w-2.5 h-2.5 rounded-full dot-ring ${active ? 'bg-status-success' : 'bg-text-tertiary'}`} />\n <span className={`text-xs ${active ? 'text-status-success' : 'text-text-tertiary'}`}>\n {active ? 'Active' : 'Inactive'}\n </span>\n </div>\n </div>\n {describeCron(schedule) && (\n <p className=\"text-xs text-text-tertiary h-8 flex items-center\">{describeCron(schedule)}</p>\n )}\n </div>\n\n {/* Preset pills */}\n <div className=\"flex flex-wrap gap-1.5 mt-3\">\n {CRON_PRESETS.map((preset) => (\n <button\n key={preset.value}\n type=\"button\"\n onClick={() => setSchedule(preset.value)}\n className={`px-2.5 py-1 text-2xs rounded-full transition-colors ${\n schedule === preset.value\n ? 'bg-accent/10 text-accent font-medium'\n : 'bg-surface-sunken text-text-tertiary hover:text-text-secondary'\n }`}\n >\n {preset.label}\n </button>\n ))}\n </div>\n </div>\n\n <div className=\"lg:w-72\">\n <p className=\"text-2xs font-semibold uppercase tracking-widest text-text-tertiary mb-4\">\n How It Works\n </p>\n <div className=\"flex items-start gap-2 px-3 py-2 rounded bg-surface-sunken\">\n <Info className=\"w-3.5 h-3.5 text-text-tertiary shrink-0 mt-0.5\" />\n <p className=\"text-2xs text-text-tertiary leading-relaxed\">\n Rules execute sequentially on each cron cycle. Engine streams can be pruned aggressively\n since they only contain internal routing data. Worker streams should be retained longer\n to preserve execution playback and input enrichment.\n </p>\n </div>\n </div>\n </div>\n\n {/* Same prune fields as Prune Now */}\n <PruneFieldsEditor fields={fields} onChange={setFields} />\n\n {/* Action bar */}\n <div className=\"flex items-center justify-between pt-2 border-t border-surface-border\">\n <div className=\"flex items-center gap-3\">\n {isDirty && (\n <button\n onClick={handleRevert}\n className=\"text-2xs text-text-tertiary hover:text-text-primary transition-colors\"\n >\n Revert changes\n </button>\n )}\n {updateConfig.error && (\n <p className=\"text-xs text-status-error\">{(updateConfig.error as Error).message}</p>\n )}\n </div>\n <button\n onClick={handleSave}\n disabled={!isDirty || !schedule.trim() || updateConfig.isPending}\n className=\"btn-primary text-xs disabled:opacity-40 shrink-0\"\n >\n {updateConfig.isPending ? 'Saving...' : 'Save Schedule'}\n </button>\n </div>\n </div>\n );\n}\n","import { useState } from 'react';\nimport { Trash2, Clock, Info } from 'lucide-react';\nimport { PageHeader } from '../../../components/common/layout/PageHeader';\nimport { PruneSection } from './PruneSection';\nimport { ScheduleSection } from './ScheduleSection';\n\ntype Mode = 'prune' | 'schedule';\n\nfunction ModeToggle({ mode, onChange }: { mode: Mode; onChange: (m: Mode) => void }) {\n const btn = (m: Mode, icon: React.ReactNode, label: string) => (\n <button\n onClick={() => onChange(m)}\n className={`flex items-center gap-1.5 px-3 py-1.5 text-xs rounded-md transition-colors ${\n mode === m\n ? 'bg-accent/10 text-accent font-medium'\n : 'text-text-tertiary hover:text-text-secondary hover:bg-surface-hover'\n }`}\n >\n {icon}\n {label}\n </button>\n );\n\n return (\n <div className=\"flex gap-1 p-0.5 bg-surface-sunken rounded-lg w-fit\">\n {btn('prune', <Trash2 className=\"w-3.5 h-3.5\" />, 'Prune Now')}\n {btn('schedule', <Clock className=\"w-3.5 h-3.5\" />, 'Schedule')}\n </div>\n );\n}\n\nexport function MaintenancePage() {\n const [mode, setMode] = useState<Mode>('schedule');\n\n return (\n <div>\n <PageHeader\n title=\"DB Maintenance\"\n docsHash=\"#docs:dashboard.md:db-maintenance\"\n actions={<ModeToggle mode={mode} onChange={setMode} />}\n />\n\n <div className=\"flex items-start gap-2 px-4 py-3 mb-8 rounded-md bg-accent/5 border border-accent/10\">\n <Info className=\"w-4 h-4 text-accent shrink-0 mt-0.5\" />\n <p className=\"text-xs text-text-secondary leading-relaxed\">\n Workflow data grows as jobs complete. Operations are ordered safest-first: stream messages are\n always safe to prune, workflow reduction preserves results, and deletion is permanent.\n </p>\n </div>\n\n {mode === 'prune' ? <PruneSection /> : <ScheduleSection />}\n </div>\n );\n}\n"],"names":["useMaintenanceConfig","useQuery","apiFetch","useUpdateMaintenanceConfig","queryClient","useQueryClient","useMutation","config","usePrune","options","RetentionRow","checked","onToggle","label","hint","safety","value","onChange","SafetyIcon","ShieldCheck","ShieldAlert","ShieldOff","safetyColor","safetyLabel","jsxs","jsx","e","RETENTION_PERIOD_OPTIONS","opt","CleanupCallout","Info","DEFAULT_PRUNE_FIELDS","hasSelection","f","PruneFieldsEditor","fields","set","key","v","ResultCard","PruneSection","prune","setFields","useState","result","setResult","showConfirm","setShowConfirm","handlePrune","data","Modal","configToFields","_a","streamDelete","x","jobDeleteTransient","jobPrune","jobDeletePruned","fieldsToRules","rules","describeCron","expr","CRON_PRESETS","p","ScheduleSection","isLoading","updateConfig","schedule","setSchedule","savedSnapshot","setSavedSnapshot","syncFromServer","useCallback","useEffect","currentSnapshot","isDirty","active","handleSave","handleRevert","preset","ModeToggle","mode","btn","m","icon","Trash2","Clock","MaintenancePage","setMode","PageHeader"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as o,j as e}from"./vendor-query-RUZdMvN6.js";import{P as Ne}from"./PageHeader-CFVw67M6.js";import{F as ve,a as we}from"./FilterBar-BY--ANxv.js";import{L as ke}from"./ListToolbar-D5TQ4X_M.js";import{S as Se}from"./StickyPagination-BfZwU2NR.js";import{E as oe}from"./EmptyState-lpUFYfun.js";import{D as Ce}from"./DropZone-Pv-v5RAs.js";import{T as H}from"./TimeAgo-JRPi9IEd.js";import{u as Pe,a as De,b as pe,c as Ee,d as Fe,e as Ae,f as Ke,g as fe,h as Oe}from"./knowledge-DpaUJtVW.js";import{T as Je}from"./TagInput-BLwxTNsI.js";import{at as Te,T as Le,X as Ve,f as ce,n as le,c as de,p as xe,b8 as me}from"./vendor-icons-h-jlRSb9.js";import{f as ge,b as Re}from"./vendor-react-CdqEC2zv.js";import"./index-CgXVDPW-.js";function _e(a){return a==null?"":typeof a=="string"?a:JSON.stringify(a,null,2)}function ue(a){const n=a.trim();if(!n)return{value:"",looksLikeJson:!1,parsedOk:!1};const l=n.startsWith("{")||n.startsWith("[");try{return{value:JSON.parse(n),looksLikeJson:l,parsedOk:!0}}catch{return{value:n,looksLikeJson:l,parsedOk:!1}}}function he(a){if(typeof a=="string"){const n=a.trim();return!(n.startsWith("{")&&n.endsWith("}")||n.startsWith("[")&&n.endsWith("]"))}return typeof a=="number"||typeof a=="boolean"||a===null}function q({value:a,onChange:n,onKeyDown:l,placeholder:r,mono:m}){const u=o.useRef(null);return o.useEffect(()=>{u.current&&(u.current.style.height="auto",u.current.style.height=`${u.current.scrollHeight}px`,u.current.focus())},[a]),e.jsx("textarea",{ref:u,value:a,onChange:N=>n(N.target.value),onKeyDown:l,placeholder:r,rows:1,className:`w-full bg-transparent text-xs text-text-primary resize-none outline-none p-0 ${m?"font-mono":""}`,style:{minHeight:"1.5em"}})}function We({domain:a,entryKey:n,onDeleted:l}){var re,ne,ie;const{data:r,isLoading:m,refetch:u}=Pe(a,n),N=De(),h=pe(),F=Ee(),k=Fe(),[S,A]=o.useState(!1),[p,f]=o.useState(null),[C,g]=o.useState(""),[j,D]=o.useState(""),[P,i]=o.useState(""),[E,K]=o.useState(null),[_,T]=o.useState(null),[O,v]=o.useState(!1),[G,I]=ge(),B=((re=Ae(a,n,!!r&&r.found!==!1).data)==null?void 0:re.versions)??[],L=G.get("version"),V=L&&/^[0-9]+$/.test(L)?parseInt(L,10):null,J=V!=null&&r&&V!==r.current_version?V:null,s=J!=null,d=Ke(a,n,J),w=o.useCallback((t,x)=>{I(y=>{const b=new URLSearchParams(y);return t===x?b.delete("version"):b.set("version",String(t)),b},{replace:!0})},[I]),c=s?(ne=d.data)==null?void 0:ne.data:r==null?void 0:r.data,z=c?Object.entries(c):[],je=o.useMemo(()=>{const t=j.trim().toLowerCase();return t?z.filter(([x])=>x.toLowerCase().includes(t)):z},[z,j]),Y=o.useCallback((t,x)=>x==="field"?t:_e(c==null?void 0:c[t]),[c]),Z=p?C!==Y(p.field,p.column):!1;function X(t,x){s||(f({field:t,column:x}),g(Y(t,x)),K(null))}function M(){f(null),g("")}function ee(){T("Invalid JSON — saved as text"),setTimeout(()=>T(null),4e3)}async function Q(){if(!p||!c)return;const{field:t,column:x}=p;if(x==="value"){const{value:y,looksLikeJson:b,parsedOk:W}=ue(C);b&&!W&&ee(),await F.mutateAsync({domain:a,key:n,path:t,value:y})}else{const y=C.trim();if(!y||y===t){M();return}const b=c[t];await k.mutateAsync({domain:a,key:n,path:t}),await F.mutateAsync({domain:a,key:n,path:y,value:b})}f(null),g(""),u()}async function ye(t){await k.mutateAsync({domain:a,key:n,path:t}),K(null),f(null),u()}async function be(t){await h.mutateAsync({domain:a,key:n,data:c||{},tags:t,replace:!0}),u()}async function te(){const t=j.trim();if(!t)return;const{value:x,looksLikeJson:y,parsedOk:b}=ue(P);y&&!b&&ee();const W={...c,[t]:x||""};await h.mutateAsync({domain:a,key:n,data:W}),D(""),i(""),u()}function se(t){t.key==="Escape"?M():t.key==="Enter"&&(t.metaKey||t.ctrlKey)&&(t.preventDefault(),Q())}function ae(t){t.key==="Escape"?(D(""),i("")):t.key==="Enter"&&(t.metaKey||t.ctrlKey)&&(t.preventDefault(),te())}return m?e.jsxs("div",{className:"animate-pulse space-y-3 mt-4",children:[e.jsx("div",{className:"h-4 bg-surface-sunken rounded w-1/3"}),e.jsx("div",{className:"h-48 bg-surface-sunken rounded"})]}):!r||r.found===!1?e.jsx("p",{className:"text-sm text-text-tertiary mt-4",children:"Entry not found."}):e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-4",children:[e.jsx("div",{className:"flex items-center gap-4 min-h-[28px]",children:O?e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(Je,{tags:r.tags||[],onChange:t=>{be(t)},placeholder:"Add tag...",compact:!0}),e.jsx("button",{onClick:()=>v(!1),className:"text-2xs text-text-tertiary hover:text-text-secondary shrink-0",children:"Done"})]}):e.jsx("div",{className:"flex items-center gap-1 cursor-text group",onClick:()=>v(!0),title:"Click to edit tags",children:r.tags&&r.tags.length>0?r.tags.map(t=>e.jsx("span",{className:"inline-flex items-center px-2 py-0.5 rounded-full text-2xs font-medium bg-accent/10 text-accent",children:t},t)):e.jsx("span",{className:"text-2xs text-text-tertiary/40 italic group-hover:text-text-tertiary",children:"add tags..."})})}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("span",{className:"inline-flex items-center gap-1.5",children:[e.jsx(Te,{className:"w-3 h-3 text-accent/75 shrink-0",strokeWidth:1.5}),e.jsx("select",{value:String(J??r.current_version),onChange:t=>w(parseInt(t.target.value,10),r.current_version),title:"Version history","aria-label":"Version history",className:"select text-2xs py-1",children:(B.length>0?B:[{version:r.current_version,is_current:!0}]).map(t=>e.jsxs("option",{value:String(t.version),children:["v",t.version,t.is_current?" · current":""]},t.version))})]}),e.jsx("span",{className:"text-2xs text-text-tertiary",children:e.jsx(H,{date:r.updated_at})}),S?e.jsxs("span",{className:"flex items-center gap-2 text-2xs",children:[e.jsx("span",{className:"text-status-error",children:"Delete entry?"}),e.jsx("button",{onClick:async()=>{try{await N.mutateAsync({domain:a,key:n}),l()}catch{}},className:"font-medium text-status-error hover:text-status-error/80",disabled:N.isPending,children:N.isPending?"Deleting...":"Yes"}),e.jsx("button",{onClick:()=>A(!1),className:"text-text-tertiary hover:text-text-secondary",children:"No"})]}):e.jsx("button",{onClick:()=>A(!0),className:"text-text-tertiary/50 hover:text-status-error transition-colors",title:"Delete entry",children:e.jsx(Le,{className:"w-3.5 h-3.5"})})]})]}),s&&e.jsxs("div",{className:"flex items-center gap-2 mb-2 px-1 text-2xs",children:[e.jsxs("span",{className:"text-text-secondary",children:["Viewing ",e.jsxs("span",{className:"font-mono font-medium",children:["v",J]})," — an immutable edition",((ie=d.data)==null?void 0:ie.created_at)&&e.jsxs(e.Fragment,{children:[" from ",e.jsx(H,{date:d.data.created_at})]})]}),e.jsx("button",{onClick:()=>w(r.current_version,r.current_version),className:"font-medium text-accent hover:text-accent-hover",children:"Back to current"})]}),_&&e.jsxs("div",{className:"flex items-center justify-end gap-2 mb-2 px-1",children:[e.jsx("span",{className:"inline-block w-2.5 h-2.5 rounded-full dot-ring bg-status-warning animate-pulse"}),e.jsx("span",{className:"text-xs text-status-warning",children:_})]}),e.jsxs("table",{className:"w-full border-collapse",children:[e.jsxs("thead",{className:"sticky top-0 z-10 bg-surface",children:[e.jsxs("tr",{className:"text-left text-2xs uppercase tracking-wider text-text-tertiary border-b border-surface-border",children:[e.jsx("th",{className:"px-3 py-2 font-medium w-[200px] border-r border-surface-border",children:"Field"}),e.jsx("th",{className:"px-3 py-2 font-medium",children:"Value"})]}),!s&&e.jsxs("tr",{className:"border-b border-surface-border bg-surface",children:[e.jsx("td",{className:"px-3 py-2 align-top border-r border-surface-border",children:e.jsx("input",{value:j,onChange:t=>D(t.target.value),onKeyDown:ae,placeholder:z.length?"add or filter...":"new field",className:"w-full bg-transparent text-xs text-text-primary placeholder:text-text-tertiary/40 placeholder:italic outline-none p-0"})}),e.jsxs("td",{className:"px-3 py-2 align-top",children:[e.jsx(q,{value:P,onChange:i,onKeyDown:ae,placeholder:"value"}),j.trim()&&e.jsxs("div",{className:"flex gap-2 mt-1.5",children:[e.jsx("button",{onClick:te,className:"text-2xs font-medium text-accent hover:text-accent-hover",disabled:h.isPending,children:h.isPending?"Saving...":"Save"}),e.jsx("button",{onClick:()=>{D(""),i("")},className:"text-2xs text-text-tertiary hover:text-text-secondary",children:"Cancel"})]})]})]})]}),e.jsx("tbody",{children:je.map(([t,x])=>{const y=(p==null?void 0:p.field)===t&&p.column==="field",b=(p==null?void 0:p.field)===t&&p.column==="value",W=y||b,R=E===t;return e.jsxs("tr",{className:`border-b border-surface-border ${R?"bg-status-error/10":W?"":"hover:bg-surface-hover/30"}`,children:[e.jsx("td",{className:`px-3 py-2 align-top border-r cursor-text ${R?"bg-transparent border-r-transparent":y?"border-r-surface-border bg-accent/5 border-l-2 border-l-accent":"border-r-surface-border"}`,onClick:()=>!y&&!R&&X(t,"field"),children:y?e.jsxs("div",{children:[e.jsx(q,{value:C,onChange:g,onKeyDown:se,placeholder:"field name"}),Z&&e.jsxs("div",{className:"flex gap-2 mt-1.5",children:[e.jsx("button",{onClick:Q,className:"text-2xs font-medium text-accent hover:text-accent-hover",disabled:h.isPending,children:h.isPending?"Saving...":"Save"}),e.jsx("button",{onClick:M,className:"text-2xs text-text-tertiary hover:text-text-secondary",children:"Cancel"})]})]}):e.jsx("span",{className:"text-xs font-medium text-text-secondary break-all",children:t})}),e.jsx("td",{className:`px-3 py-2 align-top cursor-text ${R?"bg-transparent":b?"bg-accent/5 border-l-2 border-l-accent":""}`,onClick:()=>!b&&!R&&X(t,"value"),children:R?e.jsxs("span",{className:"flex items-center justify-end gap-2 text-2xs",children:[e.jsxs("span",{className:"text-status-error",children:["Remove ",e.jsx("span",{className:"font-medium",children:t}),"?"]}),e.jsx("button",{onClick:$=>{$.stopPropagation(),ye(t)},className:"font-medium text-status-error hover:text-status-error/80",disabled:h.isPending,children:h.isPending?"...":"Yes"}),e.jsx("button",{onClick:$=>{$.stopPropagation(),K(null)},className:"text-text-tertiary hover:text-text-secondary",children:"No"})]}):b?e.jsxs("div",{children:[e.jsx(q,{value:C,onChange:g,onKeyDown:se,placeholder:"value (string or JSON)",mono:!he(x)}),e.jsxs("div",{className:"flex gap-2 mt-1.5",children:[Z&&e.jsx("button",{onClick:Q,className:"text-2xs font-medium text-accent hover:text-accent-hover",disabled:h.isPending,children:h.isPending?"Saving...":"Save"}),e.jsx("button",{onClick:M,className:"text-2xs text-text-tertiary hover:text-text-secondary",children:"Cancel"}),e.jsx("button",{onClick:$=>{$.stopPropagation(),K(t)},className:"text-2xs text-status-error/50 hover:text-status-error ml-auto",children:"Remove"})]})]}):he(x)?e.jsx("p",{className:"text-xs text-text-primary break-words whitespace-pre-wrap",children:String(x)}):e.jsx("pre",{className:"text-xs text-text-primary font-mono whitespace-pre-wrap break-words",children:typeof x=="string"?x:JSON.stringify(x,null,2)})})]},t)})})]})]})}function $e({open:a,onClose:n,onCreated:l,prefillData:r,prefillDomain:m}){const{data:u}=fe(),N=pe(),[h,F]=o.useState(m||""),[k,S]=o.useState(""),[A,p]=o.useState(r?JSON.stringify(r,null,2):"{}"),[f,C]=o.useState(""),[g,j]=o.useState(""),D=((u==null?void 0:u.domains)??[]).map(i=>i.domain);if(o.useEffect(()=>{a&&(p(r?JSON.stringify(r,null,2):"{}"),F(m||""),S(""),C(""),j(""))},[a,r,m]),!a)return null;const P=async()=>{if(j(""),!h.trim()){j("Domain is required");return}if(!k.trim()){j("Key is required");return}let i;try{if(i=JSON.parse(A),typeof i!="object"||Array.isArray(i))throw new Error}catch{j("Data must be a valid JSON object");return}try{await N.mutateAsync({domain:h.trim(),key:k.trim(),data:i,tags:f?f.split(",").map(E=>E.trim()).filter(Boolean):[]}),l==null||l(h.trim(),k.trim()),n()}catch(E){j(E.message)}};return Re.createPortal(e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"fixed inset-0 z-40 bg-black/30",onClick:n}),e.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center p-6 overflow-y-auto",children:e.jsxs("div",{className:"bg-surface-raised border border-surface-border rounded-lg shadow-lg w-full max-w-md max-h-[85vh] flex flex-col",children:[e.jsxs("div",{className:"flex items-center justify-between px-5 py-4 border-b border-surface-border",children:[e.jsx("h3",{className:"text-sm font-medium text-text-primary",children:"New Knowledge Entry"}),e.jsx("button",{onClick:n,className:"text-text-tertiary hover:text-text-primary",children:e.jsx(Ve,{className:"w-4 h-4"})})]}),e.jsxs("div",{className:"px-5 py-4 space-y-4 overflow-y-auto flex-1 min-h-0",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-2xs font-semibold uppercase tracking-widest text-text-tertiary mb-1",children:"Domain"}),e.jsx("input",{type:"text",list:"domain-list",value:h,onChange:i=>F(i.target.value),placeholder:"e.g., screenshots, config, emails",className:"input text-xs w-full"}),e.jsx("datalist",{id:"domain-list",children:D.map(i=>e.jsx("option",{value:i},i))})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-2xs font-semibold uppercase tracking-widest text-text-tertiary mb-1",children:"Key"}),e.jsx("input",{type:"text",value:k,onChange:i=>S(i.target.value),placeholder:"e.g., homepage, user-profile, report-2026",className:"input text-xs w-full"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-2xs font-semibold uppercase tracking-widest text-text-tertiary mb-1",children:"Data (JSON)"}),e.jsx("textarea",{value:A,onChange:i=>p(i.target.value),rows:8,className:"input-json w-full max-h-[30vh]"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-2xs font-semibold uppercase tracking-widest text-text-tertiary mb-1",children:"Tags (comma-separated)"}),e.jsx("input",{type:"text",value:f,onChange:i=>C(i.target.value),placeholder:"e.g., important, review, 401k",className:"input text-xs w-full"})]}),g&&e.jsx("p",{className:"text-xs text-status-error",children:g})]}),e.jsxs("div",{className:"flex justify-end gap-2 px-5 py-3 border-t border-surface-border",children:[e.jsx("button",{onClick:n,className:"btn-ghost text-xs",children:"Cancel"}),e.jsx("button",{onClick:P,disabled:N.isPending,className:"btn-primary text-xs",children:N.isPending?"Creating...":"Create Entry"})]})]})})]}),document.body)}const Ie=50;function st(){var L,V,J;const[a,n]=ge(),l=a.get("domain")||"",r=a.get("key")||"",[m,u]=o.useState(""),[N,h]=o.useState(""),[F,k]=o.useState(1),[S,A]=o.useState(Ie),[p,f]=o.useState(!1),[C,g]=o.useState(),j=o.useCallback(s=>{console.debug("[Knowledge] drop received:",s.map(c=>({name:c.name,type:c.type,size:c.size})));const d=s.find(c=>c.name.endsWith(".json")||c.type==="application/json");if(!d){console.warn("[Knowledge] no JSON file found in dropped files");return}console.debug("[Knowledge] reading:",d.name);const w=new FileReader;w.onload=()=>{try{const c=JSON.parse(w.result);typeof c=="object"&&!Array.isArray(c)?(console.debug("[Knowledge] parsed object with keys:",Object.keys(c)),g(c),f(!0)):console.warn("[Knowledge] JSON is not a plain object, got:",Array.isArray(c)?"array":typeof c)}catch(c){console.warn("[Knowledge] JSON parse failed:",c)}},w.readAsText(d)},[]);o.useEffect(()=>{const s=setTimeout(()=>{h(m),k(1)},300);return()=>clearTimeout(s)},[m]);const D=(F-1)*S,P=fe(),i=Oe(l,{search:N||void 0,limit:S,offset:D}),E=((L=P.data)==null?void 0:L.domains)??[],K=((V=i.data)==null?void 0:V.entries)??[],_=((J=i.data)==null?void 0:J.total)??0,T=o.useMemo(()=>{if(!m)return E;const s=m.toLowerCase();return E.filter(d=>d.domain.toLowerCase().includes(s))},[E,m]);function O(s,d){u(""),h(""),k(1);const w={};s&&(w.domain=s),d&&(w.key=d),n(w)}const v=r?"entry":l?"entries":"domains",G=v==="entries"?i.isLoading:v==="domains"?P.isLoading:!1,I=Math.ceil((v==="entries"?_:T.length)/S),U=l?`/knowledge/entries?domain=${encodeURIComponent(l)}&limit=${S}&offset=${D}${N?`&search=${encodeURIComponent(N)}`:""}`:void 0;return e.jsxs(Ce,{onDrop:j,label:"Drop a JSON file to create an entry",accept:".json,application/json",children:[e.jsxs("div",{children:[e.jsx(Ne,{title:"Knowledge Base",docsHash:"#docs:dashboard.md:knowledge",actions:e.jsxs("button",{onClick:()=>{g(void 0),f(!0)},className:"btn-primary text-xs inline-flex items-center gap-1.5",children:[e.jsx(ce,{className:"w-3.5 h-3.5"}),"New Entry"]})}),e.jsxs("nav",{className:"flex items-center gap-1 text-sm mb-6 min-h-[28px]",children:[e.jsxs("button",{onClick:()=>O(""),className:`flex items-center gap-1.5 px-1.5 py-0.5 rounded transition-colors ${v==="domains"?"text-text-primary font-medium":"text-text-secondary hover:text-text-primary hover:bg-surface-hover"}`,children:[e.jsx(le,{className:"w-4 h-4 text-accent/75",strokeWidth:1.5}),e.jsx("span",{children:"All Domains"})]}),l&&e.jsxs(e.Fragment,{children:[e.jsx(de,{className:"w-3.5 h-3.5 text-text-tertiary"}),e.jsxs("button",{onClick:()=>O(l),className:`flex items-center gap-1.5 px-1.5 py-0.5 rounded transition-colors ${v==="entries"?"text-text-primary font-medium":"text-text-secondary hover:text-text-primary hover:bg-surface-hover"}`,children:[e.jsx(xe,{className:"w-3.5 h-3.5 text-accent/60",strokeWidth:1.5}),l]})]}),r&&e.jsxs(e.Fragment,{children:[e.jsx(de,{className:"w-3.5 h-3.5 text-text-tertiary"}),e.jsxs("span",{className:"flex items-center gap-1.5 px-1.5 py-0.5 text-text-primary font-medium",children:[e.jsx(me,{className:"w-3.5 h-3.5 text-accent/60",strokeWidth:1.5}),r]})]})]}),v==="entry"?e.jsx(We,{domain:l,entryKey:r,onDeleted:()=>O(l)}):e.jsxs(e.Fragment,{children:[e.jsx(ve,{actions:e.jsx(ke,{onRefresh:()=>v==="entries"?i.refetch():P.refetch(),isFetching:v==="entries"?i.isFetching:P.isFetching,apiPath:v==="entries"?U:"/knowledge/domains"}),children:e.jsx(we,{label:"Search",value:m,onChange:u,placeholder:l?"Filter by key or tag...":"Filter by domain..."})}),G?e.jsx("div",{className:"animate-pulse space-y-2 mt-4",children:Array.from({length:6}).map((s,d)=>e.jsx("div",{className:"h-10 bg-surface-sunken rounded"},d))}):v==="domains"?T.length===0?e.jsx("div",{className:"cursor-pointer",onClick:()=>{g(void 0),f(!0)},children:e.jsx(oe,{icon:le,title:m?"No matching domains":"Knowledge Base Empty",description:m?void 0:"Create your first entry or drop a JSON file"})}):e.jsxs("table",{className:"w-full mt-2",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"text-left text-2xs uppercase tracking-wider text-text-tertiary",children:[e.jsx("th",{className:"pb-2 pl-2 font-medium",children:"Domain"}),e.jsx("th",{className:"pb-2 font-medium w-24 text-right",children:"Entries"}),e.jsx("th",{className:"pb-2 pr-2 font-medium w-40 text-right",children:"Latest"})]})}),e.jsx("tbody",{children:T.map(s=>e.jsxs("tr",{onClick:()=>O(s.domain),className:"row-hover cursor-pointer group",children:[e.jsx("td",{className:"py-2 pl-2",children:e.jsxs("span",{className:"flex items-center gap-2.5",children:[e.jsx(xe,{className:"w-4 h-4 text-accent/75 shrink-0",strokeWidth:1.5}),e.jsx("span",{className:"text-sm text-text-primary group-hover:text-accent transition-colors",children:s.domain})]})}),e.jsx("td",{className:"py-2 text-right text-xs text-text-secondary tabular-nums",children:s.count}),e.jsx("td",{className:"py-2 pr-2 text-right text-xs text-text-secondary",children:e.jsx(H,{date:s.latest})})]},s.domain))})]}):K.length===0?e.jsx("div",{className:"cursor-pointer",onClick:()=>{g(void 0),f(!0)},children:e.jsx(oe,{icon:ce,title:m?"No matching entries":"No entries in this domain",description:m?void 0:"Add an entry or drop a JSON file"})}):e.jsxs(e.Fragment,{children:[e.jsxs("table",{className:"w-full mt-2",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"text-left text-2xs uppercase tracking-wider text-text-tertiary",children:[e.jsx("th",{className:"pb-2 pl-2 font-medium w-[200px]",children:"Key"}),e.jsx("th",{className:"pb-2 font-medium",children:"Tags"}),e.jsx("th",{className:"pb-2 font-medium w-16 text-right",children:"Fields"}),e.jsx("th",{className:"pb-2 font-medium w-20 text-right",children:"Version"}),e.jsx("th",{className:"pb-2 pr-2 font-medium w-32 text-right",children:"Updated"})]})}),e.jsx("tbody",{children:K.map(s=>{var d;return e.jsxs("tr",{onClick:()=>O(l,s.key),className:"row-hover cursor-pointer group",children:[e.jsx("td",{className:"py-2 pl-2 w-[200px]",children:e.jsxs("span",{className:"flex items-center gap-2.5",children:[e.jsx(me,{className:"w-4 h-4 text-accent/75 shrink-0",strokeWidth:1.5}),e.jsx("span",{className:"text-sm text-text-primary group-hover:text-accent transition-colors truncate max-w-[160px]",title:s.key,children:s.key})]})}),e.jsx("td",{className:"py-2",children:e.jsxs("div",{className:"flex flex-wrap gap-1",children:[(d=s.tags)==null?void 0:d.slice(0,5).map(w=>e.jsx("span",{className:"inline-flex items-center px-1.5 py-0 rounded-full text-2xs font-medium bg-accent/10 text-accent",children:w},w)),s.tags&&s.tags.length>5&&e.jsxs("span",{className:"text-2xs text-text-tertiary",children:["+",s.tags.length-5]})]})}),e.jsx("td",{className:"py-2 text-right text-xs text-text-secondary tabular-nums",children:s.data?Object.keys(s.data).length:0}),e.jsxs("td",{className:"py-2 text-right text-xs text-text-secondary font-mono tabular-nums",children:["v",s.current_version]}),e.jsx("td",{className:"py-2 pr-2 text-right text-xs text-text-secondary",children:e.jsx(H,{date:s.updated_at})})]},s.key)})})]}),e.jsx(Se,{page:F,totalPages:I,onPageChange:k,total:_,pageSize:S,onPageSizeChange:A})]})]})]}),e.jsx($e,{open:p,onClose:()=>{f(!1),g(void 0)},onCreated:(s,d)=>{n({domain:s,key:d}),P.refetch()},prefillData:C,prefillDomain:l||void 0})]})}export{st as KnowledgePage};
|
|
2
|
-
//# sourceMappingURL=index-
|
|
1
|
+
import{a as o,j as e}from"./vendor-query-RUZdMvN6.js";import{P as Ne}from"./PageHeader-CFVw67M6.js";import{F as ve,a as we}from"./FilterBar-DWYGkVRH.js";import{L as ke}from"./ListToolbar-iOgn_db5.js";import{S as Se}from"./StickyPagination-Bc_Mzu_R.js";import{E as oe}from"./EmptyState-lpUFYfun.js";import{D as Ce}from"./DropZone-Pv-v5RAs.js";import{T as H}from"./TimeAgo-Dip7gQQx.js";import{u as Pe,a as De,b as pe,c as Ee,d as Fe,e as Ae,f as Ke,g as fe,h as Oe}from"./knowledge-BNp6MH-4.js";import{T as Je}from"./TagInput-BLwxTNsI.js";import{at as Te,T as Le,X as Ve,f as ce,n as le,c as de,p as xe,b8 as me}from"./vendor-icons-h-jlRSb9.js";import{f as ge,b as Re}from"./vendor-react-CdqEC2zv.js";import"./index-zrTQcPjB.js";function _e(a){return a==null?"":typeof a=="string"?a:JSON.stringify(a,null,2)}function ue(a){const n=a.trim();if(!n)return{value:"",looksLikeJson:!1,parsedOk:!1};const l=n.startsWith("{")||n.startsWith("[");try{return{value:JSON.parse(n),looksLikeJson:l,parsedOk:!0}}catch{return{value:n,looksLikeJson:l,parsedOk:!1}}}function he(a){if(typeof a=="string"){const n=a.trim();return!(n.startsWith("{")&&n.endsWith("}")||n.startsWith("[")&&n.endsWith("]"))}return typeof a=="number"||typeof a=="boolean"||a===null}function q({value:a,onChange:n,onKeyDown:l,placeholder:r,mono:m}){const u=o.useRef(null);return o.useEffect(()=>{u.current&&(u.current.style.height="auto",u.current.style.height=`${u.current.scrollHeight}px`,u.current.focus())},[a]),e.jsx("textarea",{ref:u,value:a,onChange:N=>n(N.target.value),onKeyDown:l,placeholder:r,rows:1,className:`w-full bg-transparent text-xs text-text-primary resize-none outline-none p-0 ${m?"font-mono":""}`,style:{minHeight:"1.5em"}})}function We({domain:a,entryKey:n,onDeleted:l}){var re,ne,ie;const{data:r,isLoading:m,refetch:u}=Pe(a,n),N=De(),h=pe(),F=Ee(),k=Fe(),[S,A]=o.useState(!1),[p,f]=o.useState(null),[C,g]=o.useState(""),[j,D]=o.useState(""),[P,i]=o.useState(""),[E,K]=o.useState(null),[_,T]=o.useState(null),[O,v]=o.useState(!1),[G,I]=ge(),B=((re=Ae(a,n,!!r&&r.found!==!1).data)==null?void 0:re.versions)??[],L=G.get("version"),V=L&&/^[0-9]+$/.test(L)?parseInt(L,10):null,J=V!=null&&r&&V!==r.current_version?V:null,s=J!=null,d=Ke(a,n,J),w=o.useCallback((t,x)=>{I(y=>{const b=new URLSearchParams(y);return t===x?b.delete("version"):b.set("version",String(t)),b},{replace:!0})},[I]),c=s?(ne=d.data)==null?void 0:ne.data:r==null?void 0:r.data,z=c?Object.entries(c):[],je=o.useMemo(()=>{const t=j.trim().toLowerCase();return t?z.filter(([x])=>x.toLowerCase().includes(t)):z},[z,j]),Y=o.useCallback((t,x)=>x==="field"?t:_e(c==null?void 0:c[t]),[c]),Z=p?C!==Y(p.field,p.column):!1;function X(t,x){s||(f({field:t,column:x}),g(Y(t,x)),K(null))}function M(){f(null),g("")}function ee(){T("Invalid JSON — saved as text"),setTimeout(()=>T(null),4e3)}async function Q(){if(!p||!c)return;const{field:t,column:x}=p;if(x==="value"){const{value:y,looksLikeJson:b,parsedOk:W}=ue(C);b&&!W&&ee(),await F.mutateAsync({domain:a,key:n,path:t,value:y})}else{const y=C.trim();if(!y||y===t){M();return}const b=c[t];await k.mutateAsync({domain:a,key:n,path:t}),await F.mutateAsync({domain:a,key:n,path:y,value:b})}f(null),g(""),u()}async function ye(t){await k.mutateAsync({domain:a,key:n,path:t}),K(null),f(null),u()}async function be(t){await h.mutateAsync({domain:a,key:n,data:c||{},tags:t,replace:!0}),u()}async function te(){const t=j.trim();if(!t)return;const{value:x,looksLikeJson:y,parsedOk:b}=ue(P);y&&!b&&ee();const W={...c,[t]:x||""};await h.mutateAsync({domain:a,key:n,data:W}),D(""),i(""),u()}function se(t){t.key==="Escape"?M():t.key==="Enter"&&(t.metaKey||t.ctrlKey)&&(t.preventDefault(),Q())}function ae(t){t.key==="Escape"?(D(""),i("")):t.key==="Enter"&&(t.metaKey||t.ctrlKey)&&(t.preventDefault(),te())}return m?e.jsxs("div",{className:"animate-pulse space-y-3 mt-4",children:[e.jsx("div",{className:"h-4 bg-surface-sunken rounded w-1/3"}),e.jsx("div",{className:"h-48 bg-surface-sunken rounded"})]}):!r||r.found===!1?e.jsx("p",{className:"text-sm text-text-tertiary mt-4",children:"Entry not found."}):e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-4",children:[e.jsx("div",{className:"flex items-center gap-4 min-h-[28px]",children:O?e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(Je,{tags:r.tags||[],onChange:t=>{be(t)},placeholder:"Add tag...",compact:!0}),e.jsx("button",{onClick:()=>v(!1),className:"text-2xs text-text-tertiary hover:text-text-secondary shrink-0",children:"Done"})]}):e.jsx("div",{className:"flex items-center gap-1 cursor-text group",onClick:()=>v(!0),title:"Click to edit tags",children:r.tags&&r.tags.length>0?r.tags.map(t=>e.jsx("span",{className:"inline-flex items-center px-2 py-0.5 rounded-full text-2xs font-medium bg-accent/10 text-accent",children:t},t)):e.jsx("span",{className:"text-2xs text-text-tertiary/40 italic group-hover:text-text-tertiary",children:"add tags..."})})}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("span",{className:"inline-flex items-center gap-1.5",children:[e.jsx(Te,{className:"w-3 h-3 text-accent/75 shrink-0",strokeWidth:1.5}),e.jsx("select",{value:String(J??r.current_version),onChange:t=>w(parseInt(t.target.value,10),r.current_version),title:"Version history","aria-label":"Version history",className:"select text-2xs py-1",children:(B.length>0?B:[{version:r.current_version,is_current:!0}]).map(t=>e.jsxs("option",{value:String(t.version),children:["v",t.version,t.is_current?" · current":""]},t.version))})]}),e.jsx("span",{className:"text-2xs text-text-tertiary",children:e.jsx(H,{date:r.updated_at})}),S?e.jsxs("span",{className:"flex items-center gap-2 text-2xs",children:[e.jsx("span",{className:"text-status-error",children:"Delete entry?"}),e.jsx("button",{onClick:async()=>{try{await N.mutateAsync({domain:a,key:n}),l()}catch{}},className:"font-medium text-status-error hover:text-status-error/80",disabled:N.isPending,children:N.isPending?"Deleting...":"Yes"}),e.jsx("button",{onClick:()=>A(!1),className:"text-text-tertiary hover:text-text-secondary",children:"No"})]}):e.jsx("button",{onClick:()=>A(!0),className:"text-text-tertiary/50 hover:text-status-error transition-colors",title:"Delete entry",children:e.jsx(Le,{className:"w-3.5 h-3.5"})})]})]}),s&&e.jsxs("div",{className:"flex items-center gap-2 mb-2 px-1 text-2xs",children:[e.jsxs("span",{className:"text-text-secondary",children:["Viewing ",e.jsxs("span",{className:"font-mono font-medium",children:["v",J]})," — an immutable edition",((ie=d.data)==null?void 0:ie.created_at)&&e.jsxs(e.Fragment,{children:[" from ",e.jsx(H,{date:d.data.created_at})]})]}),e.jsx("button",{onClick:()=>w(r.current_version,r.current_version),className:"font-medium text-accent hover:text-accent-hover",children:"Back to current"})]}),_&&e.jsxs("div",{className:"flex items-center justify-end gap-2 mb-2 px-1",children:[e.jsx("span",{className:"inline-block w-2.5 h-2.5 rounded-full dot-ring bg-status-warning animate-pulse"}),e.jsx("span",{className:"text-xs text-status-warning",children:_})]}),e.jsxs("table",{className:"w-full border-collapse",children:[e.jsxs("thead",{className:"sticky top-0 z-10 bg-surface",children:[e.jsxs("tr",{className:"text-left text-2xs uppercase tracking-wider text-text-tertiary border-b border-surface-border",children:[e.jsx("th",{className:"px-3 py-2 font-medium w-[200px] border-r border-surface-border",children:"Field"}),e.jsx("th",{className:"px-3 py-2 font-medium",children:"Value"})]}),!s&&e.jsxs("tr",{className:"border-b border-surface-border bg-surface",children:[e.jsx("td",{className:"px-3 py-2 align-top border-r border-surface-border",children:e.jsx("input",{value:j,onChange:t=>D(t.target.value),onKeyDown:ae,placeholder:z.length?"add or filter...":"new field",className:"w-full bg-transparent text-xs text-text-primary placeholder:text-text-tertiary/40 placeholder:italic outline-none p-0"})}),e.jsxs("td",{className:"px-3 py-2 align-top",children:[e.jsx(q,{value:P,onChange:i,onKeyDown:ae,placeholder:"value"}),j.trim()&&e.jsxs("div",{className:"flex gap-2 mt-1.5",children:[e.jsx("button",{onClick:te,className:"text-2xs font-medium text-accent hover:text-accent-hover",disabled:h.isPending,children:h.isPending?"Saving...":"Save"}),e.jsx("button",{onClick:()=>{D(""),i("")},className:"text-2xs text-text-tertiary hover:text-text-secondary",children:"Cancel"})]})]})]})]}),e.jsx("tbody",{children:je.map(([t,x])=>{const y=(p==null?void 0:p.field)===t&&p.column==="field",b=(p==null?void 0:p.field)===t&&p.column==="value",W=y||b,R=E===t;return e.jsxs("tr",{className:`border-b border-surface-border ${R?"bg-status-error/10":W?"":"hover:bg-surface-hover/30"}`,children:[e.jsx("td",{className:`px-3 py-2 align-top border-r cursor-text ${R?"bg-transparent border-r-transparent":y?"border-r-surface-border bg-accent/5 border-l-2 border-l-accent":"border-r-surface-border"}`,onClick:()=>!y&&!R&&X(t,"field"),children:y?e.jsxs("div",{children:[e.jsx(q,{value:C,onChange:g,onKeyDown:se,placeholder:"field name"}),Z&&e.jsxs("div",{className:"flex gap-2 mt-1.5",children:[e.jsx("button",{onClick:Q,className:"text-2xs font-medium text-accent hover:text-accent-hover",disabled:h.isPending,children:h.isPending?"Saving...":"Save"}),e.jsx("button",{onClick:M,className:"text-2xs text-text-tertiary hover:text-text-secondary",children:"Cancel"})]})]}):e.jsx("span",{className:"text-xs font-medium text-text-secondary break-all",children:t})}),e.jsx("td",{className:`px-3 py-2 align-top cursor-text ${R?"bg-transparent":b?"bg-accent/5 border-l-2 border-l-accent":""}`,onClick:()=>!b&&!R&&X(t,"value"),children:R?e.jsxs("span",{className:"flex items-center justify-end gap-2 text-2xs",children:[e.jsxs("span",{className:"text-status-error",children:["Remove ",e.jsx("span",{className:"font-medium",children:t}),"?"]}),e.jsx("button",{onClick:$=>{$.stopPropagation(),ye(t)},className:"font-medium text-status-error hover:text-status-error/80",disabled:h.isPending,children:h.isPending?"...":"Yes"}),e.jsx("button",{onClick:$=>{$.stopPropagation(),K(null)},className:"text-text-tertiary hover:text-text-secondary",children:"No"})]}):b?e.jsxs("div",{children:[e.jsx(q,{value:C,onChange:g,onKeyDown:se,placeholder:"value (string or JSON)",mono:!he(x)}),e.jsxs("div",{className:"flex gap-2 mt-1.5",children:[Z&&e.jsx("button",{onClick:Q,className:"text-2xs font-medium text-accent hover:text-accent-hover",disabled:h.isPending,children:h.isPending?"Saving...":"Save"}),e.jsx("button",{onClick:M,className:"text-2xs text-text-tertiary hover:text-text-secondary",children:"Cancel"}),e.jsx("button",{onClick:$=>{$.stopPropagation(),K(t)},className:"text-2xs text-status-error/50 hover:text-status-error ml-auto",children:"Remove"})]})]}):he(x)?e.jsx("p",{className:"text-xs text-text-primary break-words whitespace-pre-wrap",children:String(x)}):e.jsx("pre",{className:"text-xs text-text-primary font-mono whitespace-pre-wrap break-words",children:typeof x=="string"?x:JSON.stringify(x,null,2)})})]},t)})})]})]})}function $e({open:a,onClose:n,onCreated:l,prefillData:r,prefillDomain:m}){const{data:u}=fe(),N=pe(),[h,F]=o.useState(m||""),[k,S]=o.useState(""),[A,p]=o.useState(r?JSON.stringify(r,null,2):"{}"),[f,C]=o.useState(""),[g,j]=o.useState(""),D=((u==null?void 0:u.domains)??[]).map(i=>i.domain);if(o.useEffect(()=>{a&&(p(r?JSON.stringify(r,null,2):"{}"),F(m||""),S(""),C(""),j(""))},[a,r,m]),!a)return null;const P=async()=>{if(j(""),!h.trim()){j("Domain is required");return}if(!k.trim()){j("Key is required");return}let i;try{if(i=JSON.parse(A),typeof i!="object"||Array.isArray(i))throw new Error}catch{j("Data must be a valid JSON object");return}try{await N.mutateAsync({domain:h.trim(),key:k.trim(),data:i,tags:f?f.split(",").map(E=>E.trim()).filter(Boolean):[]}),l==null||l(h.trim(),k.trim()),n()}catch(E){j(E.message)}};return Re.createPortal(e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"fixed inset-0 z-40 bg-black/30",onClick:n}),e.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center p-6 overflow-y-auto",children:e.jsxs("div",{className:"bg-surface-raised border border-surface-border rounded-lg shadow-lg w-full max-w-md max-h-[85vh] flex flex-col",children:[e.jsxs("div",{className:"flex items-center justify-between px-5 py-4 border-b border-surface-border",children:[e.jsx("h3",{className:"text-sm font-medium text-text-primary",children:"New Knowledge Entry"}),e.jsx("button",{onClick:n,className:"text-text-tertiary hover:text-text-primary",children:e.jsx(Ve,{className:"w-4 h-4"})})]}),e.jsxs("div",{className:"px-5 py-4 space-y-4 overflow-y-auto flex-1 min-h-0",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-2xs font-semibold uppercase tracking-widest text-text-tertiary mb-1",children:"Domain"}),e.jsx("input",{type:"text",list:"domain-list",value:h,onChange:i=>F(i.target.value),placeholder:"e.g., screenshots, config, emails",className:"input text-xs w-full"}),e.jsx("datalist",{id:"domain-list",children:D.map(i=>e.jsx("option",{value:i},i))})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-2xs font-semibold uppercase tracking-widest text-text-tertiary mb-1",children:"Key"}),e.jsx("input",{type:"text",value:k,onChange:i=>S(i.target.value),placeholder:"e.g., homepage, user-profile, report-2026",className:"input text-xs w-full"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-2xs font-semibold uppercase tracking-widest text-text-tertiary mb-1",children:"Data (JSON)"}),e.jsx("textarea",{value:A,onChange:i=>p(i.target.value),rows:8,className:"input-json w-full max-h-[30vh]"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-2xs font-semibold uppercase tracking-widest text-text-tertiary mb-1",children:"Tags (comma-separated)"}),e.jsx("input",{type:"text",value:f,onChange:i=>C(i.target.value),placeholder:"e.g., important, review, 401k",className:"input text-xs w-full"})]}),g&&e.jsx("p",{className:"text-xs text-status-error",children:g})]}),e.jsxs("div",{className:"flex justify-end gap-2 px-5 py-3 border-t border-surface-border",children:[e.jsx("button",{onClick:n,className:"btn-ghost text-xs",children:"Cancel"}),e.jsx("button",{onClick:P,disabled:N.isPending,className:"btn-primary text-xs",children:N.isPending?"Creating...":"Create Entry"})]})]})})]}),document.body)}const Ie=50;function st(){var L,V,J;const[a,n]=ge(),l=a.get("domain")||"",r=a.get("key")||"",[m,u]=o.useState(""),[N,h]=o.useState(""),[F,k]=o.useState(1),[S,A]=o.useState(Ie),[p,f]=o.useState(!1),[C,g]=o.useState(),j=o.useCallback(s=>{console.debug("[Knowledge] drop received:",s.map(c=>({name:c.name,type:c.type,size:c.size})));const d=s.find(c=>c.name.endsWith(".json")||c.type==="application/json");if(!d){console.warn("[Knowledge] no JSON file found in dropped files");return}console.debug("[Knowledge] reading:",d.name);const w=new FileReader;w.onload=()=>{try{const c=JSON.parse(w.result);typeof c=="object"&&!Array.isArray(c)?(console.debug("[Knowledge] parsed object with keys:",Object.keys(c)),g(c),f(!0)):console.warn("[Knowledge] JSON is not a plain object, got:",Array.isArray(c)?"array":typeof c)}catch(c){console.warn("[Knowledge] JSON parse failed:",c)}},w.readAsText(d)},[]);o.useEffect(()=>{const s=setTimeout(()=>{h(m),k(1)},300);return()=>clearTimeout(s)},[m]);const D=(F-1)*S,P=fe(),i=Oe(l,{search:N||void 0,limit:S,offset:D}),E=((L=P.data)==null?void 0:L.domains)??[],K=((V=i.data)==null?void 0:V.entries)??[],_=((J=i.data)==null?void 0:J.total)??0,T=o.useMemo(()=>{if(!m)return E;const s=m.toLowerCase();return E.filter(d=>d.domain.toLowerCase().includes(s))},[E,m]);function O(s,d){u(""),h(""),k(1);const w={};s&&(w.domain=s),d&&(w.key=d),n(w)}const v=r?"entry":l?"entries":"domains",G=v==="entries"?i.isLoading:v==="domains"?P.isLoading:!1,I=Math.ceil((v==="entries"?_:T.length)/S),U=l?`/knowledge/entries?domain=${encodeURIComponent(l)}&limit=${S}&offset=${D}${N?`&search=${encodeURIComponent(N)}`:""}`:void 0;return e.jsxs(Ce,{onDrop:j,label:"Drop a JSON file to create an entry",accept:".json,application/json",children:[e.jsxs("div",{children:[e.jsx(Ne,{title:"Knowledge Base",docsHash:"#docs:dashboard.md:knowledge",actions:e.jsxs("button",{onClick:()=>{g(void 0),f(!0)},className:"btn-primary text-xs inline-flex items-center gap-1.5",children:[e.jsx(ce,{className:"w-3.5 h-3.5"}),"New Entry"]})}),e.jsxs("nav",{className:"flex items-center gap-1 text-sm mb-6 min-h-[28px]",children:[e.jsxs("button",{onClick:()=>O(""),className:`flex items-center gap-1.5 px-1.5 py-0.5 rounded transition-colors ${v==="domains"?"text-text-primary font-medium":"text-text-secondary hover:text-text-primary hover:bg-surface-hover"}`,children:[e.jsx(le,{className:"w-4 h-4 text-accent/75",strokeWidth:1.5}),e.jsx("span",{children:"All Domains"})]}),l&&e.jsxs(e.Fragment,{children:[e.jsx(de,{className:"w-3.5 h-3.5 text-text-tertiary"}),e.jsxs("button",{onClick:()=>O(l),className:`flex items-center gap-1.5 px-1.5 py-0.5 rounded transition-colors ${v==="entries"?"text-text-primary font-medium":"text-text-secondary hover:text-text-primary hover:bg-surface-hover"}`,children:[e.jsx(xe,{className:"w-3.5 h-3.5 text-accent/60",strokeWidth:1.5}),l]})]}),r&&e.jsxs(e.Fragment,{children:[e.jsx(de,{className:"w-3.5 h-3.5 text-text-tertiary"}),e.jsxs("span",{className:"flex items-center gap-1.5 px-1.5 py-0.5 text-text-primary font-medium",children:[e.jsx(me,{className:"w-3.5 h-3.5 text-accent/60",strokeWidth:1.5}),r]})]})]}),v==="entry"?e.jsx(We,{domain:l,entryKey:r,onDeleted:()=>O(l)}):e.jsxs(e.Fragment,{children:[e.jsx(ve,{actions:e.jsx(ke,{onRefresh:()=>v==="entries"?i.refetch():P.refetch(),isFetching:v==="entries"?i.isFetching:P.isFetching,apiPath:v==="entries"?U:"/knowledge/domains"}),children:e.jsx(we,{label:"Search",value:m,onChange:u,placeholder:l?"Filter by key or tag...":"Filter by domain..."})}),G?e.jsx("div",{className:"animate-pulse space-y-2 mt-4",children:Array.from({length:6}).map((s,d)=>e.jsx("div",{className:"h-10 bg-surface-sunken rounded"},d))}):v==="domains"?T.length===0?e.jsx("div",{className:"cursor-pointer",onClick:()=>{g(void 0),f(!0)},children:e.jsx(oe,{icon:le,title:m?"No matching domains":"Knowledge Base Empty",description:m?void 0:"Create your first entry or drop a JSON file"})}):e.jsxs("table",{className:"w-full mt-2",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"text-left text-2xs uppercase tracking-wider text-text-tertiary",children:[e.jsx("th",{className:"pb-2 pl-2 font-medium",children:"Domain"}),e.jsx("th",{className:"pb-2 font-medium w-24 text-right",children:"Entries"}),e.jsx("th",{className:"pb-2 pr-2 font-medium w-40 text-right",children:"Latest"})]})}),e.jsx("tbody",{children:T.map(s=>e.jsxs("tr",{onClick:()=>O(s.domain),className:"row-hover cursor-pointer group",children:[e.jsx("td",{className:"py-2 pl-2",children:e.jsxs("span",{className:"flex items-center gap-2.5",children:[e.jsx(xe,{className:"w-4 h-4 text-accent/75 shrink-0",strokeWidth:1.5}),e.jsx("span",{className:"text-sm text-text-primary group-hover:text-accent transition-colors",children:s.domain})]})}),e.jsx("td",{className:"py-2 text-right text-xs text-text-secondary tabular-nums",children:s.count}),e.jsx("td",{className:"py-2 pr-2 text-right text-xs text-text-secondary",children:e.jsx(H,{date:s.latest})})]},s.domain))})]}):K.length===0?e.jsx("div",{className:"cursor-pointer",onClick:()=>{g(void 0),f(!0)},children:e.jsx(oe,{icon:ce,title:m?"No matching entries":"No entries in this domain",description:m?void 0:"Add an entry or drop a JSON file"})}):e.jsxs(e.Fragment,{children:[e.jsxs("table",{className:"w-full mt-2",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"text-left text-2xs uppercase tracking-wider text-text-tertiary",children:[e.jsx("th",{className:"pb-2 pl-2 font-medium w-[200px]",children:"Key"}),e.jsx("th",{className:"pb-2 font-medium",children:"Tags"}),e.jsx("th",{className:"pb-2 font-medium w-16 text-right",children:"Fields"}),e.jsx("th",{className:"pb-2 font-medium w-20 text-right",children:"Version"}),e.jsx("th",{className:"pb-2 pr-2 font-medium w-32 text-right",children:"Updated"})]})}),e.jsx("tbody",{children:K.map(s=>{var d;return e.jsxs("tr",{onClick:()=>O(l,s.key),className:"row-hover cursor-pointer group",children:[e.jsx("td",{className:"py-2 pl-2 w-[200px]",children:e.jsxs("span",{className:"flex items-center gap-2.5",children:[e.jsx(me,{className:"w-4 h-4 text-accent/75 shrink-0",strokeWidth:1.5}),e.jsx("span",{className:"text-sm text-text-primary group-hover:text-accent transition-colors truncate max-w-[160px]",title:s.key,children:s.key})]})}),e.jsx("td",{className:"py-2",children:e.jsxs("div",{className:"flex flex-wrap gap-1",children:[(d=s.tags)==null?void 0:d.slice(0,5).map(w=>e.jsx("span",{className:"inline-flex items-center px-1.5 py-0 rounded-full text-2xs font-medium bg-accent/10 text-accent",children:w},w)),s.tags&&s.tags.length>5&&e.jsxs("span",{className:"text-2xs text-text-tertiary",children:["+",s.tags.length-5]})]})}),e.jsx("td",{className:"py-2 text-right text-xs text-text-secondary tabular-nums",children:s.data?Object.keys(s.data).length:0}),e.jsxs("td",{className:"py-2 text-right text-xs text-text-secondary font-mono tabular-nums",children:["v",s.current_version]}),e.jsx("td",{className:"py-2 pr-2 text-right text-xs text-text-secondary",children:e.jsx(H,{date:s.updated_at})})]},s.key)})})]}),e.jsx(Se,{page:F,totalPages:I,onPageChange:k,total:_,pageSize:S,onPageSizeChange:A})]})]})]}),e.jsx($e,{open:p,onClose:()=>{f(!1),g(void 0)},onCreated:(s,d)=>{n({domain:s,key:d}),P.refetch()},prefillData:C,prefillDomain:l||void 0})]})}export{st as KnowledgePage};
|
|
2
|
+
//# sourceMappingURL=index-DvmyIGeZ.js.map
|