claude-code-workflow 7.2.18 → 7.2.20
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/.claude/commands/workflow/analyze-with-file.md +33 -8
- package/.codex/skills/analyze-with-file/SKILL.md +55 -8
- package/ccw/dist/core/routes/agent-definitions-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/agent-definitions-routes.js +152 -6
- package/ccw/dist/core/routes/agent-definitions-routes.js.map +1 -1
- package/ccw/frontend/dist/assets/{AlertDialog-5DA_OF9w.js → AlertDialog-Cukb0xv2.js} +2 -2
- package/ccw/frontend/dist/assets/{AlertDialog-5DA_OF9w.js.map → AlertDialog-Cukb0xv2.js.map} +1 -1
- package/ccw/frontend/dist/assets/{AnalysisPage-MoK5luZM.js → AnalysisPage-Ddmv0J4x.js} +2 -2
- package/ccw/frontend/dist/assets/{AnalysisPage-MoK5luZM.js.map → AnalysisPage-Ddmv0J4x.js.map} +1 -1
- package/ccw/frontend/dist/assets/{ApiSettingsPage-OreSF7CY.js → ApiSettingsPage-DMkrTZDX.js} +2 -2
- package/ccw/frontend/dist/assets/{ApiSettingsPage-OreSF7CY.js.map → ApiSettingsPage-DMkrTZDX.js.map} +1 -1
- package/ccw/frontend/dist/assets/{CliModeToggle-B_Vu8NDb.js → CliModeToggle-DXenjpbe.js} +2 -2
- package/ccw/frontend/dist/assets/{CliModeToggle-B_Vu8NDb.js.map → CliModeToggle-DXenjpbe.js.map} +1 -1
- package/ccw/frontend/dist/assets/{CliSessionSharePage-Bb3DrLGF.js → CliSessionSharePage-B-ZIMqmX.js} +2 -2
- package/ccw/frontend/dist/assets/{CliSessionSharePage-Bb3DrLGF.js.map → CliSessionSharePage-B-ZIMqmX.js.map} +1 -1
- package/ccw/frontend/dist/assets/{CliViewerPage-BS4zrFVp.js → CliViewerPage-9YxGyLxh.js} +2 -2
- package/ccw/frontend/dist/assets/{CliViewerPage-BS4zrFVp.js.map → CliViewerPage-9YxGyLxh.js.map} +1 -1
- package/ccw/frontend/dist/assets/{CodexLensPage-BWSIk06e.js → CodexLensPage-B_uv5wdn.js} +2 -2
- package/ccw/frontend/dist/assets/{CodexLensPage-BWSIk06e.js.map → CodexLensPage-B_uv5wdn.js.map} +1 -1
- package/ccw/frontend/dist/assets/{Collapsible-Cw1zJkjU.js → Collapsible-C2qk3yV0.js} +2 -2
- package/ccw/frontend/dist/assets/{Collapsible-Cw1zJkjU.js.map → Collapsible-C2qk3yV0.js.map} +1 -1
- package/ccw/frontend/dist/assets/{CommandsManagerPage-a240GHzx.js → CommandsManagerPage-DBtaWxLB.js} +2 -2
- package/ccw/frontend/dist/assets/{CommandsManagerPage-a240GHzx.js.map → CommandsManagerPage-DBtaWxLB.js.map} +1 -1
- package/ccw/frontend/dist/assets/{DeepWikiPage-CZ4pN-5G.js → DeepWikiPage-d9K4_TgG.js} +2 -2
- package/ccw/frontend/dist/assets/{DeepWikiPage-CZ4pN-5G.js.map → DeepWikiPage-d9K4_TgG.js.map} +1 -1
- package/ccw/frontend/dist/assets/{EndpointsPage-Ct66AIze.js → EndpointsPage-DhW6hYrI.js} +2 -2
- package/ccw/frontend/dist/assets/{EndpointsPage-Ct66AIze.js.map → EndpointsPage-DhW6hYrI.js.map} +1 -1
- package/ccw/frontend/dist/assets/{ExplorerPage-DAZkXx2Q.js → ExplorerPage-DYYpCvtB.js} +2 -2
- package/ccw/frontend/dist/assets/{ExplorerPage-DAZkXx2Q.js.map → ExplorerPage-DYYpCvtB.js.map} +1 -1
- package/ccw/frontend/dist/assets/{FixSessionPage-cDE32BH8.js → FixSessionPage-CSmiT5SE.js} +2 -2
- package/ccw/frontend/dist/assets/{FixSessionPage-cDE32BH8.js.map → FixSessionPage-CSmiT5SE.js.map} +1 -1
- package/ccw/frontend/dist/assets/{FloatingFileBrowser-tgDOT5P0.js → FloatingFileBrowser-DvMsXLdP.js} +2 -2
- package/ccw/frontend/dist/assets/{FloatingFileBrowser-tgDOT5P0.js.map → FloatingFileBrowser-DvMsXLdP.js.map} +1 -1
- package/ccw/frontend/dist/assets/{FloatingPanel-Diyvdyo1.js → FloatingPanel-sqezhSI8.js} +2 -2
- package/ccw/frontend/dist/assets/{FloatingPanel-Diyvdyo1.js.map → FloatingPanel-sqezhSI8.js.map} +1 -1
- package/ccw/frontend/dist/assets/{GraphExplorerPage-CPwRsfd2.js → GraphExplorerPage-DS8ghMFM.js} +2 -2
- package/ccw/frontend/dist/assets/{GraphExplorerPage-CPwRsfd2.js.map → GraphExplorerPage-DS8ghMFM.js.map} +1 -1
- package/ccw/frontend/dist/assets/{HistoryPage-D2F7j-xY.js → HistoryPage-B-x1RyHu.js} +2 -2
- package/ccw/frontend/dist/assets/{HistoryPage-D2F7j-xY.js.map → HistoryPage-B-x1RyHu.js.map} +1 -1
- package/ccw/frontend/dist/assets/{HookManagerPage-Cq_CqegO.js → HookManagerPage-BbxpDb68.js} +2 -2
- package/ccw/frontend/dist/assets/{HookManagerPage-Cq_CqegO.js.map → HookManagerPage-BbxpDb68.js.map} +1 -1
- package/ccw/frontend/dist/assets/{InstallationsPage-DeBLZFZg.js → InstallationsPage-3bShz_Ai.js} +2 -2
- package/ccw/frontend/dist/assets/{InstallationsPage-DeBLZFZg.js.map → InstallationsPage-3bShz_Ai.js.map} +1 -1
- package/ccw/frontend/dist/assets/{IssueHubPage-DqytkqBW.js → IssueHubPage-BQY_Hh3e.js} +2 -2
- package/ccw/frontend/dist/assets/{IssueHubPage-DqytkqBW.js.map → IssueHubPage-BQY_Hh3e.js.map} +1 -1
- package/ccw/frontend/dist/assets/{LiteTasksPage-BOknokuo.js → LiteTasksPage-vD_8fQcR.js} +17 -22
- package/ccw/frontend/dist/assets/LiteTasksPage-vD_8fQcR.js.map +1 -0
- package/ccw/frontend/dist/assets/{McpManagerPage-DPF421ki.js → McpManagerPage-CI5ZzB8A.js} +2 -2
- package/ccw/frontend/dist/assets/{McpManagerPage-DPF421ki.js.map → McpManagerPage-CI5ZzB8A.js.map} +1 -1
- package/ccw/frontend/dist/assets/{MemoryPage-CK-QH9cl.js → MemoryPage-CNuj2eNg.js} +2 -2
- package/ccw/frontend/dist/assets/{MemoryPage-CK-QH9cl.js.map → MemoryPage-CNuj2eNg.js.map} +1 -1
- package/ccw/frontend/dist/assets/{NotFoundPage-Bk_u5rzz.js → NotFoundPage-BrnAXkb1.js} +2 -2
- package/ccw/frontend/dist/assets/{NotFoundPage-Bk_u5rzz.js.map → NotFoundPage-BrnAXkb1.js.map} +1 -1
- package/ccw/frontend/dist/assets/{OrchestratorPage-B9ND5ptW.js → OrchestratorPage-CH81PGt4.js} +2 -2
- package/ccw/frontend/dist/assets/{OrchestratorPage-B9ND5ptW.js.map → OrchestratorPage-CH81PGt4.js.map} +1 -1
- package/ccw/frontend/dist/assets/{ProjectOverviewPage-0DUpa-rl.js → ProjectOverviewPage-dwiEXl2O.js} +2 -2
- package/ccw/frontend/dist/assets/{ProjectOverviewPage-0DUpa-rl.js.map → ProjectOverviewPage-dwiEXl2O.js.map} +1 -1
- package/ccw/frontend/dist/assets/{PromptHistoryPage-B--0N_wr.js → PromptHistoryPage-CabgLjJU.js} +2 -2
- package/ccw/frontend/dist/assets/{PromptHistoryPage-B--0N_wr.js.map → PromptHistoryPage-CabgLjJU.js.map} +1 -1
- package/ccw/frontend/dist/assets/{ReviewSessionPage-DJtY0kQl.js → ReviewSessionPage-DAMrNFn8.js} +2 -2
- package/ccw/frontend/dist/assets/{ReviewSessionPage-DJtY0kQl.js.map → ReviewSessionPage-DAMrNFn8.js.map} +1 -1
- package/ccw/frontend/dist/assets/{RulesManagerPage-yW19Un_V.js → RulesManagerPage-4jzmxPn0.js} +2 -2
- package/ccw/frontend/dist/assets/{RulesManagerPage-yW19Un_V.js.map → RulesManagerPage-4jzmxPn0.js.map} +1 -1
- package/ccw/frontend/dist/assets/{SessionDetailPage-tr8g0Hc1.js → SessionDetailPage-C5Btktmp.js} +2 -2
- package/ccw/frontend/dist/assets/{SessionDetailPage-tr8g0Hc1.js.map → SessionDetailPage-C5Btktmp.js.map} +1 -1
- package/ccw/frontend/dist/assets/{SessionsPage-CxDytLfb.js → SessionsPage-CQIB4E8m.js} +2 -2
- package/ccw/frontend/dist/assets/{SessionsPage-CxDytLfb.js.map → SessionsPage-CQIB4E8m.js.map} +1 -1
- package/ccw/frontend/dist/assets/SettingsPage-Yi9UAfm7.js +150 -0
- package/ccw/frontend/dist/assets/SettingsPage-Yi9UAfm7.js.map +1 -0
- package/ccw/frontend/dist/assets/{SkillsManagerPage-C0MOJy-C.js → SkillsManagerPage-BqfvYSkT.js} +2 -2
- package/ccw/frontend/dist/assets/{SkillsManagerPage-C0MOJy-C.js.map → SkillsManagerPage-BqfvYSkT.js.map} +1 -1
- package/ccw/frontend/dist/assets/{SpecsSettingsPage-D9Y6-U-n.js → SpecsSettingsPage-BdVPM5R6.js} +4 -4
- package/ccw/frontend/dist/assets/{SpecsSettingsPage-D9Y6-U-n.js.map → SpecsSettingsPage-BdVPM5R6.js.map} +1 -1
- package/ccw/frontend/dist/assets/{Switch-BEfkMCxZ.js → Switch-BG929kV0.js} +2 -2
- package/ccw/frontend/dist/assets/{Switch-BEfkMCxZ.js.map → Switch-BG929kV0.js.map} +1 -1
- package/ccw/frontend/dist/assets/{TabsNavigation-Dit0DM3m.js → TabsNavigation-Bol1y09b.js} +2 -2
- package/ccw/frontend/dist/assets/{TabsNavigation-Dit0DM3m.js.map → TabsNavigation-Bol1y09b.js.map} +1 -1
- package/ccw/frontend/dist/assets/{TaskDrawer-XN-D_bDk.js → TaskDrawer-Dwutrn8_.js} +2 -2
- package/ccw/frontend/dist/assets/{TaskDrawer-XN-D_bDk.js.map → TaskDrawer-Dwutrn8_.js.map} +1 -1
- package/ccw/frontend/dist/assets/{TeamPage-BOwkjrDi.js → TeamPage-CpCSwpxD.js} +2 -2
- package/ccw/frontend/dist/assets/{TeamPage-BOwkjrDi.js.map → TeamPage-CpCSwpxD.js.map} +1 -1
- package/ccw/frontend/dist/assets/{TerminalDashboardPage-X8RymrSN.js → TerminalDashboardPage-DODKjOeK.js} +2 -2
- package/ccw/frontend/dist/assets/{TerminalDashboardPage-X8RymrSN.js.map → TerminalDashboardPage-DODKjOeK.js.map} +1 -1
- package/ccw/frontend/dist/assets/{archive-BMXBzq8R.js → archive-CQw634kD.js} +2 -2
- package/ccw/frontend/dist/assets/{archive-BMXBzq8R.js.map → archive-CQw634kD.js.map} +1 -1
- package/ccw/frontend/dist/assets/{archive-restore-DHvAhQBT.js → archive-restore-B-_EG6wE.js} +2 -2
- package/ccw/frontend/dist/assets/{archive-restore-DHvAhQBT.js.map → archive-restore-B-_EG6wE.js.map} +1 -1
- package/ccw/frontend/dist/assets/{arrow-right-CBObFEN0.js → arrow-right-CcQtxBrU.js} +2 -2
- package/ccw/frontend/dist/assets/{arrow-right-CBObFEN0.js.map → arrow-right-CcQtxBrU.js.map} +1 -1
- package/ccw/frontend/dist/assets/{bookmark-plus-D-2SQ5pV.js → bookmark-plus-Cl-BbcpR.js} +2 -2
- package/ccw/frontend/dist/assets/{bookmark-plus-D-2SQ5pV.js.map → bookmark-plus-Cl-BbcpR.js.map} +1 -1
- package/ccw/frontend/dist/assets/{bot-DS7saQkk.js → bot-CLSNSkW_.js} +2 -2
- package/ccw/frontend/dist/assets/{bot-DS7saQkk.js.map → bot-CLSNSkW_.js.map} +1 -1
- package/ccw/frontend/dist/assets/{braces-D0pAnktp.js → braces-DWwkaDS6.js} +2 -2
- package/ccw/frontend/dist/assets/{braces-D0pAnktp.js.map → braces-DWwkaDS6.js.map} +1 -1
- package/ccw/frontend/dist/assets/{circle-stop-FWSboNE6.js → circle-stop-DiS7e6ma.js} +2 -2
- package/ccw/frontend/dist/assets/{circle-stop-FWSboNE6.js.map → circle-stop-DiS7e6ma.js.map} +1 -1
- package/ccw/frontend/dist/assets/{cpu-BNM2uIpY.js → cpu-CuvHUVXO.js} +2 -2
- package/ccw/frontend/dist/assets/{cpu-BNM2uIpY.js.map → cpu-CuvHUVXO.js.map} +1 -1
- package/ccw/frontend/dist/assets/{ellipsis-vertical-GwdnnWQj.js → ellipsis-vertical-BoVlINSw.js} +2 -2
- package/ccw/frontend/dist/assets/{ellipsis-vertical-GwdnnWQj.js.map → ellipsis-vertical-BoVlINSw.js.map} +1 -1
- package/ccw/frontend/dist/assets/{eye-kV2pWXQ5.js → eye-BEMOdcAN.js} +2 -2
- package/ccw/frontend/dist/assets/{eye-kV2pWXQ5.js.map → eye-BEMOdcAN.js.map} +1 -1
- package/ccw/frontend/dist/assets/{eye-off-6o-KYsBM.js → eye-off-C5HS4Ytm.js} +2 -2
- package/ccw/frontend/dist/assets/{eye-off-6o-KYsBM.js.map → eye-off-C5HS4Ytm.js.map} +1 -1
- package/ccw/frontend/dist/assets/{file-json-Q4_Blhd8.js → file-json-DQ9XLq0B.js} +2 -2
- package/ccw/frontend/dist/assets/{file-json-Q4_Blhd8.js.map → file-json-DQ9XLq0B.js.map} +1 -1
- package/ccw/frontend/dist/assets/{file-text-DSroEAMu.js → file-text-TGs_qCbw.js} +2 -2
- package/ccw/frontend/dist/assets/{file-text-DSroEAMu.js.map → file-text-TGs_qCbw.js.map} +1 -1
- package/ccw/frontend/dist/assets/{filter-A5I9Xz7E.js → filter-CIuCqnDB.js} +2 -2
- package/ccw/frontend/dist/assets/{filter-A5I9Xz7E.js.map → filter-CIuCqnDB.js.map} +1 -1
- package/ccw/frontend/dist/assets/{folder-DNNgXVVH.js → folder-BkivHBwn.js} +2 -2
- package/ccw/frontend/dist/assets/{folder-DNNgXVVH.js.map → folder-BkivHBwn.js.map} +1 -1
- package/ccw/frontend/dist/assets/{gauge-PfGM68A8.js → gauge-CtM68fVY.js} +2 -2
- package/ccw/frontend/dist/assets/{gauge-PfGM68A8.js.map → gauge-CtM68fVY.js.map} +1 -1
- package/ccw/frontend/dist/assets/{globe-C3X8YQrU.js → globe-DpnrINqP.js} +2 -2
- package/ccw/frontend/dist/assets/{globe-C3X8YQrU.js.map → globe-DpnrINqP.js.map} +1 -1
- package/ccw/frontend/dist/assets/{grid-3x3-DpyJO-oF.js → grid-3x3-SjX0a5JH.js} +2 -2
- package/ccw/frontend/dist/assets/{grid-3x3-DpyJO-oF.js.map → grid-3x3-SjX0a5JH.js.map} +1 -1
- package/ccw/frontend/dist/assets/{hard-drive-C2PQHoNg.js → hard-drive-ByAmnoEg.js} +2 -2
- package/ccw/frontend/dist/assets/{hard-drive-C2PQHoNg.js.map → hard-drive-ByAmnoEg.js.map} +1 -1
- package/ccw/frontend/dist/assets/{hash-DX8VaW1j.js → hash-DbLc3VOZ.js} +2 -2
- package/ccw/frontend/dist/assets/{hash-DX8VaW1j.js.map → hash-DbLc3VOZ.js.map} +1 -1
- package/ccw/frontend/dist/assets/{history-BXaQEkhy.js → history-Botz5Z5d.js} +2 -2
- package/ccw/frontend/dist/assets/{history-BXaQEkhy.js.map → history-Botz5Z5d.js.map} +1 -1
- package/ccw/frontend/dist/assets/{index-BiN-BRcE.js → index-BGvyf4-9.js} +2 -2
- package/ccw/frontend/dist/assets/{index-BiN-BRcE.js.map → index-BGvyf4-9.js.map} +1 -1
- package/ccw/frontend/dist/assets/index-BoqylFO4.css +39 -0
- package/ccw/frontend/dist/assets/{index-B8K8MdMl.js → index-DP_mTJI8.js} +3 -3
- package/ccw/frontend/dist/assets/{index-B8K8MdMl.js.map → index-DP_mTJI8.js.map} +1 -1
- package/ccw/frontend/dist/assets/{index-Dpe_7YH0.js → index-MkgdhX7a.js} +2 -2
- package/ccw/frontend/dist/assets/{index-Dpe_7YH0.js.map → index-MkgdhX7a.js.map} +1 -1
- package/ccw/frontend/dist/assets/{index-4zmlzlPo.js → index-ni-tG9rm.js} +2 -2
- package/ccw/frontend/dist/assets/{index-4zmlzlPo.js.map → index-ni-tG9rm.js.map} +1 -1
- package/ccw/frontend/dist/assets/{layout-grid-CUqTukRt.js → layout-grid-11E4bGJz.js} +2 -2
- package/ccw/frontend/dist/assets/{layout-grid-CUqTukRt.js.map → layout-grid-11E4bGJz.js.map} +1 -1
- package/ccw/frontend/dist/assets/{lightbulb-h90ex0mh.js → lightbulb-8KrKY82b.js} +2 -2
- package/ccw/frontend/dist/assets/{lightbulb-h90ex0mh.js.map → lightbulb-8KrKY82b.js.map} +1 -1
- package/ccw/frontend/dist/assets/{link-2-1-DjXqTg.js → link-2-BUn6RILb.js} +2 -2
- package/ccw/frontend/dist/assets/{link-2-1-DjXqTg.js.map → link-2-BUn6RILb.js.map} +1 -1
- package/ccw/frontend/dist/assets/{link-DbyJpuls.js → link-CmP254Ai.js} +2 -2
- package/ccw/frontend/dist/assets/{link-DbyJpuls.js.map → link-CmP254Ai.js.map} +1 -1
- package/ccw/frontend/dist/assets/{list-CU0leArg.js → list-BAwzl4a2.js} +2 -2
- package/ccw/frontend/dist/assets/{list-CU0leArg.js.map → list-BAwzl4a2.js.map} +1 -1
- package/ccw/frontend/dist/assets/{map-pin-DheJ6EJB.js → map-pin-gi342rqk.js} +2 -2
- package/ccw/frontend/dist/assets/{map-pin-DheJ6EJB.js.map → map-pin-gi342rqk.js.map} +1 -1
- package/ccw/frontend/dist/assets/{messages-square-Bmo5DCr1.js → messages-square-C1Lh8q8b.js} +2 -2
- package/ccw/frontend/dist/assets/{messages-square-Bmo5DCr1.js.map → messages-square-C1Lh8q8b.js.map} +1 -1
- package/ccw/frontend/dist/assets/{minimize-2-h1gktUQ6.js → minimize-2-OgWNLKdq.js} +2 -2
- package/ccw/frontend/dist/assets/{minimize-2-h1gktUQ6.js.map → minimize-2-OgWNLKdq.js.map} +1 -1
- package/ccw/frontend/dist/assets/{package-CmuCX6Z_.js → package-Djsvs5qp.js} +2 -2
- package/ccw/frontend/dist/assets/{package-CmuCX6Z_.js.map → package-Djsvs5qp.js.map} +1 -1
- package/ccw/frontend/dist/assets/{plug-Jz5HaKIu.js → plug-DvSZP2cp.js} +2 -2
- package/ccw/frontend/dist/assets/{plug-Jz5HaKIu.js.map → plug-DvSZP2cp.js.map} +1 -1
- package/ccw/frontend/dist/assets/{power-CpN5I4BU.js → power-BY7vTLmU.js} +2 -2
- package/ccw/frontend/dist/assets/{power-CpN5I4BU.js.map → power-BY7vTLmU.js.map} +1 -1
- package/ccw/frontend/dist/assets/{save-B3iyK-h8.js → save-DXfqv84T.js} +2 -2
- package/ccw/frontend/dist/assets/{save-B3iyK-h8.js.map → save-DXfqv84T.js.map} +1 -1
- package/ccw/frontend/dist/assets/{send-CYO-YU9A.js → send-E2o2LZSX.js} +2 -2
- package/ccw/frontend/dist/assets/{send-CYO-YU9A.js.map → send-E2o2LZSX.js.map} +1 -1
- package/ccw/frontend/dist/assets/settings-2-ChD1LFHH.js +7 -0
- package/ccw/frontend/dist/assets/settings-2-ChD1LFHH.js.map +1 -0
- package/ccw/frontend/dist/assets/{square-check-big-1h37S4wz.js → square-check-big-CBymuqmD.js} +2 -2
- package/ccw/frontend/dist/assets/{square-check-big-1h37S4wz.js.map → square-check-big-CBymuqmD.js.map} +1 -1
- package/ccw/frontend/dist/assets/{square-pen-BS0-oO7y.js → square-pen-BfaiJgOX.js} +2 -2
- package/ccw/frontend/dist/assets/{square-pen-BS0-oO7y.js.map → square-pen-BfaiJgOX.js.map} +1 -1
- package/ccw/frontend/dist/assets/{star-Dal-o3Lo.js → star-DHMWqZ09.js} +2 -2
- package/ccw/frontend/dist/assets/{star-Dal-o3Lo.js.map → star-DHMWqZ09.js.map} +1 -1
- package/ccw/frontend/dist/assets/{style-wEWj0pe8.js → style-wvcOEAiM.js} +2 -2
- package/ccw/frontend/dist/assets/{style-wEWj0pe8.js.map → style-wvcOEAiM.js.map} +1 -1
- package/ccw/frontend/dist/assets/{target-BB9AJiC7.js → target-B8AMmf_N.js} +2 -2
- package/ccw/frontend/dist/assets/{target-BB9AJiC7.js.map → target-B8AMmf_N.js.map} +1 -1
- package/ccw/frontend/dist/assets/{test-tube-DDnQZrAm.js → test-tube-BpDeTJi1.js} +2 -2
- package/ccw/frontend/dist/assets/{test-tube-DDnQZrAm.js.map → test-tube-BpDeTJi1.js.map} +1 -1
- package/ccw/frontend/dist/assets/{upload-DshzYJC_.js → upload-pflkdIDG.js} +2 -2
- package/ccw/frontend/dist/assets/{upload-DshzYJC_.js.map → upload-pflkdIDG.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useApiSettings-DkV-yWup.js → useApiSettings-BPx4DyKT.js} +2 -2
- package/ccw/frontend/dist/assets/{useApiSettings-DkV-yWup.js.map → useApiSettings-BPx4DyKT.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useCli-CnwgIkqD.js → useCli-D1jfH3XA.js} +2 -2
- package/ccw/frontend/dist/assets/{useCli-CnwgIkqD.js.map → useCli-D1jfH3XA.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useCommands-S0sc5bfK.js → useCommands-DhR71vpa.js} +2 -2
- package/ccw/frontend/dist/assets/{useCommands-S0sc5bfK.js.map → useCommands-DhR71vpa.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useDebounce-HxG5rpQo.js → useDebounce-a6Yyer3m.js} +2 -2
- package/ccw/frontend/dist/assets/{useDebounce-HxG5rpQo.js.map → useDebounce-a6Yyer3m.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useFileExplorer-CTg0zndf.js → useFileExplorer-B8W2JTj2.js} +2 -2
- package/ccw/frontend/dist/assets/{useFileExplorer-CTg0zndf.js.map → useFileExplorer-B8W2JTj2.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useLocale-C2BlVToA.js → useLocale-aMHdQIL_.js} +2 -2
- package/ccw/frontend/dist/assets/{useLocale-C2BlVToA.js.map → useLocale-aMHdQIL_.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useSkills-8IWJgwQU.js → useSkills-BHpc2LtN.js} +3 -3
- package/ccw/frontend/dist/assets/{useSkills-8IWJgwQU.js.map → useSkills-BHpc2LtN.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useSystemSettings-BAtCCf8T.js → useSystemSettings-BFD0SvEF.js} +2 -2
- package/ccw/frontend/dist/assets/{useSystemSettings-BAtCCf8T.js.map → useSystemSettings-BFD0SvEF.js.map} +1 -1
- package/ccw/frontend/dist/assets/{wand-sparkles-CI1Tfudg.js → wand-sparkles-dYtI2IKM.js} +2 -2
- package/ccw/frontend/dist/assets/{wand-sparkles-CI1Tfudg.js.map → wand-sparkles-dYtI2IKM.js.map} +1 -1
- package/ccw/frontend/dist/index.html +2 -2
- package/package.json +1 -1
- package/ccw/frontend/dist/assets/LiteTasksPage-BOknokuo.js.map +0 -1
- package/ccw/frontend/dist/assets/SettingsPage-DJltvfrs.js +0 -144
- package/ccw/frontend/dist/assets/SettingsPage-DJltvfrs.js.map +0 -1
- package/ccw/frontend/dist/assets/index-D6YeIKg_.css +0 -39
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{u as R,al as A,r as l,j as e,x as ne,y as le,z as re,A as oe,bu as D,I,aq as B,ar as K,as as U,at as V,au as N,bO as de,G as ce,e as E,R as me,c as P,a7 as xe,C as b,Z as $,aR as H,b as pe,ae as ue,B as z,T as he,cy as ge,ap as fe}from"./index-B8K8MdMl.js";import{u as je,a as ve,b as Ne,c as Ee,d as ye}from"./useCli-CnwgIkqD.js";import{S as be}from"./Switch-BEfkMCxZ.js";import{P as M}from"./plug-Jz5HaKIu.js";import{P as Q,a as we}from"./power-CpN5I4BU.js";import{S as Ce}from"./square-pen-BS0-oO7y.js";import"./useLocale-C2BlVToA.js";import"./errorSanitizer-IY9pf5g4.js";function Se(s){try{return JSON.stringify(s??{},null,2)}catch{return"{}"}}function ke(s){const a=s.trim();if(!a)return{ok:!0,value:{}};try{const r=JSON.parse(a);return!r||typeof r!="object"||Array.isArray(r)?{ok:!1,errorKey:"validation.configMustBeObject"}:{ok:!0,value:r}}catch{return{ok:!1,errorKey:"validation.invalidJson"}}}function Fe({mode:s,endpoint:a,open:r,onClose:p,onSave:w}){const{formatMessage:i}=R(),{error:m}=A(),h=s==="edit",[u,g]=l.useState(""),[o,y]=l.useState("custom"),[C,f]=l.useState(!0),[S,k]=l.useState("{}"),[n,j]=l.useState({}),[F,J]=l.useState(!1),L=l.useMemo(()=>h?i({id:"cliEndpoints.dialog.editTitle"},{id:(a==null?void 0:a.id)??""}):i({id:"cliEndpoints.dialog.createTitle"}),[i,h,a==null?void 0:a.id]);l.useEffect(()=>{r&&(h&&a?(g(a.name),y(a.type),f(a.enabled),k(Se(a.config))):(g(""),y("custom"),f(!0),k("{}")),j({}),J(!1))},[r,h,a]);const T=async()=>{const d={};u.trim()||(d.name="validation.nameRequired"),o||(d.type="validation.typeRequired");const x=ke(S);if(x.ok||(d.configJson=x.errorKey),Object.keys(d).length>0){j(d);return}J(!0);try{await w({name:u.trim(),type:o,enabled:C,config:x.value}),p()}catch(O){m(i({id:"cliEndpoints.messages.saveFailed"})),console.error("Failed to save CLI endpoint:",O)}finally{J(!1)}};return e.jsx(ne,{open:r,onOpenChange:p,children:e.jsxs(le,{className:"sm:max-w-[720px]",children:[e.jsx(re,{children:e.jsx(oe,{children:L})}),e.jsxs("div",{className:"space-y-4 py-4",children:[h&&a&&e.jsxs("div",{className:"space-y-2",children:[e.jsx(D,{htmlFor:"cli-endpoint-id",children:i({id:"cliEndpoints.id"})}),e.jsx(I,{id:"cli-endpoint-id",value:a.id,disabled:!0,className:"font-mono"})]}),e.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsxs(D,{htmlFor:"cli-endpoint-name",children:[i({id:"cliEndpoints.form.name"})," *"]}),e.jsx(I,{id:"cli-endpoint-name",value:u,onChange:d=>{g(d.target.value),n.name&&j(x=>({...x,name:void 0}))},placeholder:i({id:"cliEndpoints.form.namePlaceholder"}),error:!!n.name}),n.name&&e.jsx("p",{className:"text-xs text-destructive",children:i({id:`cliEndpoints.${n.name}`})})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsxs(D,{htmlFor:"cli-endpoint-type",children:[i({id:"cliEndpoints.form.type"})," *"]}),e.jsxs(B,{value:o,onValueChange:d=>{y(d),n.type&&j(x=>({...x,type:void 0}))},children:[e.jsx(K,{id:"cli-endpoint-type",className:n.type?"border-destructive":void 0,children:e.jsx(U,{})}),e.jsxs(V,{children:[e.jsx(N,{value:"litellm",children:i({id:"cliEndpoints.type.litellm"})}),e.jsx(N,{value:"custom",children:i({id:"cliEndpoints.type.custom"})}),e.jsx(N,{value:"wrapper",children:i({id:"cliEndpoints.type.wrapper"})})]})]}),n.type&&e.jsx("p",{className:"text-xs text-destructive",children:i({id:`cliEndpoints.${n.type}`})})]})]}),e.jsxs("div",{className:"flex items-center justify-between rounded-md border border-border p-3",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-medium text-foreground",children:i({id:"cliEndpoints.form.enabled"})}),e.jsx("p",{className:"text-xs text-muted-foreground",children:i({id:"cliEndpoints.form.enabledHint"})})]}),e.jsx(be,{checked:C,onCheckedChange:f})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(D,{htmlFor:"cli-endpoint-config",children:i({id:"cliEndpoints.form.configJson"})}),e.jsx(de,{id:"cli-endpoint-config",value:S,onChange:d=>{k(d.target.value),n.configJson&&j(x=>({...x,configJson:void 0}))},placeholder:i({id:"cliEndpoints.form.configJsonPlaceholder"}),className:n.configJson?"font-mono border-destructive":"font-mono",rows:10}),n.configJson&&e.jsx("p",{className:"text-xs text-destructive",children:i({id:`cliEndpoints.${n.configJson}`})})]})]}),e.jsxs(ce,{children:[e.jsx(E,{variant:"outline",onClick:p,disabled:F,children:i({id:"common.actions.cancel"})}),e.jsx(E,{onClick:T,disabled:F,children:i(F?{id:"common.actions.saving"}:{id:"common.actions.save"})})]})]})})}function Je({endpoint:s,isExpanded:a,onToggleExpand:r,onToggle:p,onEdit:w,onDelete:i}){const{formatMessage:m}=R(),u={litellm:{icon:$,color:"text-blue-600",label:"cliEndpoints.type.litellm"},custom:{icon:H,color:"text-purple-600",label:"cliEndpoints.type.custom"},wrapper:{icon:ue,color:"text-orange-600",label:"cliEndpoints.type.wrapper"}}[s.type],g=u.icon;return e.jsxs(b,{className:P("overflow-hidden",!s.enabled&&"opacity-60"),children:[e.jsx("div",{className:"p-4 cursor-pointer hover:bg-muted/50 transition-colors",onClick:r,children:e.jsxs("div",{className:"flex items-start justify-between gap-2",children:[e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx("div",{className:P("p-2 rounded-lg",s.enabled?"bg-primary/10":"bg-muted"),children:e.jsx(g,{className:P("w-5 h-5",s.enabled?u.color:"text-muted-foreground")})}),e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-sm font-medium text-foreground",children:s.name}),e.jsx(z,{variant:"outline",className:"text-xs",children:m({id:u.label})}),s.enabled&&e.jsx(z,{variant:"outline",className:"text-xs text-green-600",children:m({id:"cliEndpoints.status.enabled"})})]}),e.jsxs("p",{className:"text-sm text-muted-foreground mt-1",children:[m({id:"cliEndpoints.id"}),": ",s.id]})]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(E,{variant:"ghost",size:"sm",className:"h-8 w-8 p-0","aria-label":m({id:"cliEndpoints.actions.toggle"}),onClick:o=>{o.stopPropagation(),p(s.id,!s.enabled)},children:s.enabled?e.jsx(Q,{className:"w-4 h-4 text-green-600"}):e.jsx(we,{className:"w-4 h-4"})}),e.jsx(E,{variant:"ghost",size:"sm",className:"h-8 w-8 p-0","aria-label":m({id:"cliEndpoints.actions.edit"}),onClick:o=>{o.stopPropagation(),w(s)},children:e.jsx(Ce,{className:"w-4 h-4"})}),e.jsx(E,{variant:"ghost",size:"sm",className:"h-8 w-8 p-0","aria-label":m({id:"cliEndpoints.actions.delete"}),onClick:o=>{o.stopPropagation(),i(s.id)},children:e.jsx(he,{className:"w-4 h-4 text-destructive"})}),a?e.jsx(ge,{className:"w-5 h-5 text-muted-foreground"}):e.jsx(fe,{className:"w-5 h-5 text-muted-foreground"})]})]})}),a&&e.jsx("div",{className:"border-t border-border p-4 space-y-3 bg-muted/30",children:e.jsxs("div",{children:[e.jsx("p",{className:"text-xs text-muted-foreground mb-2",children:m({id:"cliEndpoints.config"})}),e.jsx("div",{className:"bg-background p-3 rounded-md font-mono text-sm overflow-x-auto",children:e.jsx("pre",{children:JSON.stringify(s.config,null,2)})})]})})]})}function qe(){const{formatMessage:s}=R(),{success:a,error:r}=A(),[p,w]=l.useState(""),[i,m]=l.useState("all"),[h,u]=l.useState(new Set),[g,o]=l.useState(!1),[y,C]=l.useState("create"),[f,S]=l.useState(void 0),{endpoints:k,litellmEndpoints:n,customEndpoints:j,totalCount:F,enabledCount:J,isLoading:L,isFetching:T,refetch:d}=je(),{toggleEndpoint:x}=ve(),{createEndpoint:O,isCreating:Z}=Ne(),{updateEndpoint:G,isUpdating:W}=Ee(),{deleteEndpoint:X,isDeleting:Y}=ye(),_=t=>{u(c=>{const v=new Set(c);return v.has(t)?v.delete(t):v.add(t),v})},ee=(t,c)=>{x(t,c)},se=()=>{C("create"),S(void 0),o(!0)},te=t=>{C("edit"),S(t),o(!0)},ie=async t=>{if(confirm(s({id:"cliEndpoints.deleteConfirm"},{id:t})))try{await X(t),a(s({id:"cliEndpoints.messages.deleted"}))}catch(c){console.error("Failed to delete CLI endpoint:",c),r(s({id:"cliEndpoints.messages.deleteFailed"}))}},ae=async t=>{try{if(y==="edit"&&f){await G(f.id,t),a(s({id:"cliEndpoints.messages.updated"}));return}await O(t),a(s({id:"cliEndpoints.messages.created"}))}catch(c){throw console.error("Failed to save CLI endpoint:",c),r(s({id:"cliEndpoints.messages.saveFailed"})),c}},q=(()=>{let t=k;if(i!=="all"&&(t=t.filter(c=>c.type===i)),p){const c=p.toLowerCase();t=t.filter(v=>v.name.toLowerCase().includes(c)||v.id.toLowerCase().includes(c))}return t})();return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4",children:[e.jsxs("div",{children:[e.jsxs("h1",{className:"text-2xl font-bold text-foreground flex items-center gap-2",children:[e.jsx(M,{className:"w-6 h-6 text-primary"}),s({id:"cliEndpoints.title"})]}),e.jsx("p",{className:"text-muted-foreground mt-1",children:s({id:"cliEndpoints.description"})})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs(E,{variant:"outline",onClick:()=>d(),disabled:T,children:[e.jsx(me,{className:P("w-4 h-4 mr-2",T&&"animate-spin")}),s({id:"common.actions.refresh"})]}),e.jsxs(E,{onClick:se,disabled:Z||W||Y,children:[e.jsx(xe,{className:"w-4 h-4 mr-2"}),s({id:"cliEndpoints.actions.add"})]})]})]}),e.jsxs("div",{className:"grid grid-cols-2 md:grid-cols-4 gap-4",children:[e.jsxs(b,{className:"p-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(M,{className:"w-5 h-5 text-primary"}),e.jsx("span",{className:"text-2xl font-bold",children:F})]}),e.jsx("p",{className:"text-sm text-muted-foreground mt-1",children:s({id:"cliEndpoints.stats.total"})})]}),e.jsxs(b,{className:"p-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(Q,{className:"w-5 h-5 text-green-600"}),e.jsx("span",{className:"text-2xl font-bold",children:J})]}),e.jsx("p",{className:"text-sm text-muted-foreground mt-1",children:s({id:"cliEndpoints.stats.enabled"})})]}),e.jsxs(b,{className:"p-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx($,{className:"w-5 h-5 text-blue-600"}),e.jsx("span",{className:"text-2xl font-bold",children:n.length})]}),e.jsx("p",{className:"text-sm text-muted-foreground mt-1",children:s({id:"cliEndpoints.type.litellm"})})]}),e.jsxs(b,{className:"p-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(H,{className:"w-5 h-5 text-purple-600"}),e.jsx("span",{className:"text-2xl font-bold",children:j.length})]}),e.jsx("p",{className:"text-sm text-muted-foreground mt-1",children:s({id:"cliEndpoints.type.custom"})})]})]}),e.jsxs("div",{className:"flex flex-col sm:flex-row gap-3",children:[e.jsxs("div",{className:"relative flex-1",children:[e.jsx(pe,{className:"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground"}),e.jsx(I,{placeholder:s({id:"cliEndpoints.filters.searchPlaceholder"}),value:p,onChange:t=>w(t.target.value),className:"pl-9"})]}),e.jsxs(B,{value:i,onValueChange:t=>m(t),children:[e.jsx(K,{className:"w-[180px]",children:e.jsx(U,{placeholder:s({id:"cliEndpoints.filters.type"})})}),e.jsxs(V,{children:[e.jsx(N,{value:"all",children:s({id:"cliEndpoints.filters.allTypes"})}),e.jsx(N,{value:"litellm",children:s({id:"cliEndpoints.type.litellm"})}),e.jsx(N,{value:"custom",children:s({id:"cliEndpoints.type.custom"})}),e.jsx(N,{value:"wrapper",children:s({id:"cliEndpoints.type.wrapper"})})]})]})]}),L?e.jsx("div",{className:"space-y-3",children:[1,2,3,4].map(t=>e.jsx("div",{className:"h-24 bg-muted animate-pulse rounded-lg"},t))}):q.length===0?e.jsxs(b,{className:"p-8 text-center",children:[e.jsx(M,{className:"w-12 h-12 mx-auto text-muted-foreground/50"}),e.jsx("h3",{className:"mt-4 text-lg font-medium text-foreground",children:s({id:"cliEndpoints.emptyState.title"})}),e.jsx("p",{className:"mt-2 text-muted-foreground",children:s({id:"cliEndpoints.emptyState.message"})})]}):e.jsx("div",{className:"space-y-3",children:q.map(t=>e.jsx(Je,{endpoint:t,isExpanded:h.has(t.id),onToggleExpand:()=>_(t.id),onToggle:ee,onEdit:te,onDelete:ie},t.id))}),e.jsx(Fe,{mode:y,endpoint:f,open:g,onClose:()=>o(!1),onSave:ae})]})}export{qe as EndpointsPage,qe as default};
|
|
2
|
-
//# sourceMappingURL=EndpointsPage-
|
|
1
|
+
import{u as R,al as A,r as l,j as e,x as ne,y as le,z as re,A as oe,bu as D,I,aq as B,ar as K,as as U,at as V,au as N,bO as de,G as ce,e as E,R as me,c as P,a7 as xe,C as b,Z as $,aR as H,b as pe,ae as ue,B as z,T as he,cy as ge,ap as fe}from"./index-DP_mTJI8.js";import{u as je,a as ve,b as Ne,c as Ee,d as ye}from"./useCli-D1jfH3XA.js";import{S as be}from"./Switch-BG929kV0.js";import{P as M}from"./plug-DvSZP2cp.js";import{P as Q,a as we}from"./power-BY7vTLmU.js";import{S as Ce}from"./square-pen-BfaiJgOX.js";import"./useLocale-aMHdQIL_.js";import"./errorSanitizer-IY9pf5g4.js";function Se(s){try{return JSON.stringify(s??{},null,2)}catch{return"{}"}}function ke(s){const a=s.trim();if(!a)return{ok:!0,value:{}};try{const r=JSON.parse(a);return!r||typeof r!="object"||Array.isArray(r)?{ok:!1,errorKey:"validation.configMustBeObject"}:{ok:!0,value:r}}catch{return{ok:!1,errorKey:"validation.invalidJson"}}}function Fe({mode:s,endpoint:a,open:r,onClose:p,onSave:w}){const{formatMessage:i}=R(),{error:m}=A(),h=s==="edit",[u,g]=l.useState(""),[o,y]=l.useState("custom"),[C,f]=l.useState(!0),[S,k]=l.useState("{}"),[n,j]=l.useState({}),[F,J]=l.useState(!1),L=l.useMemo(()=>h?i({id:"cliEndpoints.dialog.editTitle"},{id:(a==null?void 0:a.id)??""}):i({id:"cliEndpoints.dialog.createTitle"}),[i,h,a==null?void 0:a.id]);l.useEffect(()=>{r&&(h&&a?(g(a.name),y(a.type),f(a.enabled),k(Se(a.config))):(g(""),y("custom"),f(!0),k("{}")),j({}),J(!1))},[r,h,a]);const T=async()=>{const d={};u.trim()||(d.name="validation.nameRequired"),o||(d.type="validation.typeRequired");const x=ke(S);if(x.ok||(d.configJson=x.errorKey),Object.keys(d).length>0){j(d);return}J(!0);try{await w({name:u.trim(),type:o,enabled:C,config:x.value}),p()}catch(O){m(i({id:"cliEndpoints.messages.saveFailed"})),console.error("Failed to save CLI endpoint:",O)}finally{J(!1)}};return e.jsx(ne,{open:r,onOpenChange:p,children:e.jsxs(le,{className:"sm:max-w-[720px]",children:[e.jsx(re,{children:e.jsx(oe,{children:L})}),e.jsxs("div",{className:"space-y-4 py-4",children:[h&&a&&e.jsxs("div",{className:"space-y-2",children:[e.jsx(D,{htmlFor:"cli-endpoint-id",children:i({id:"cliEndpoints.id"})}),e.jsx(I,{id:"cli-endpoint-id",value:a.id,disabled:!0,className:"font-mono"})]}),e.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsxs(D,{htmlFor:"cli-endpoint-name",children:[i({id:"cliEndpoints.form.name"})," *"]}),e.jsx(I,{id:"cli-endpoint-name",value:u,onChange:d=>{g(d.target.value),n.name&&j(x=>({...x,name:void 0}))},placeholder:i({id:"cliEndpoints.form.namePlaceholder"}),error:!!n.name}),n.name&&e.jsx("p",{className:"text-xs text-destructive",children:i({id:`cliEndpoints.${n.name}`})})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsxs(D,{htmlFor:"cli-endpoint-type",children:[i({id:"cliEndpoints.form.type"})," *"]}),e.jsxs(B,{value:o,onValueChange:d=>{y(d),n.type&&j(x=>({...x,type:void 0}))},children:[e.jsx(K,{id:"cli-endpoint-type",className:n.type?"border-destructive":void 0,children:e.jsx(U,{})}),e.jsxs(V,{children:[e.jsx(N,{value:"litellm",children:i({id:"cliEndpoints.type.litellm"})}),e.jsx(N,{value:"custom",children:i({id:"cliEndpoints.type.custom"})}),e.jsx(N,{value:"wrapper",children:i({id:"cliEndpoints.type.wrapper"})})]})]}),n.type&&e.jsx("p",{className:"text-xs text-destructive",children:i({id:`cliEndpoints.${n.type}`})})]})]}),e.jsxs("div",{className:"flex items-center justify-between rounded-md border border-border p-3",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-medium text-foreground",children:i({id:"cliEndpoints.form.enabled"})}),e.jsx("p",{className:"text-xs text-muted-foreground",children:i({id:"cliEndpoints.form.enabledHint"})})]}),e.jsx(be,{checked:C,onCheckedChange:f})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(D,{htmlFor:"cli-endpoint-config",children:i({id:"cliEndpoints.form.configJson"})}),e.jsx(de,{id:"cli-endpoint-config",value:S,onChange:d=>{k(d.target.value),n.configJson&&j(x=>({...x,configJson:void 0}))},placeholder:i({id:"cliEndpoints.form.configJsonPlaceholder"}),className:n.configJson?"font-mono border-destructive":"font-mono",rows:10}),n.configJson&&e.jsx("p",{className:"text-xs text-destructive",children:i({id:`cliEndpoints.${n.configJson}`})})]})]}),e.jsxs(ce,{children:[e.jsx(E,{variant:"outline",onClick:p,disabled:F,children:i({id:"common.actions.cancel"})}),e.jsx(E,{onClick:T,disabled:F,children:i(F?{id:"common.actions.saving"}:{id:"common.actions.save"})})]})]})})}function Je({endpoint:s,isExpanded:a,onToggleExpand:r,onToggle:p,onEdit:w,onDelete:i}){const{formatMessage:m}=R(),u={litellm:{icon:$,color:"text-blue-600",label:"cliEndpoints.type.litellm"},custom:{icon:H,color:"text-purple-600",label:"cliEndpoints.type.custom"},wrapper:{icon:ue,color:"text-orange-600",label:"cliEndpoints.type.wrapper"}}[s.type],g=u.icon;return e.jsxs(b,{className:P("overflow-hidden",!s.enabled&&"opacity-60"),children:[e.jsx("div",{className:"p-4 cursor-pointer hover:bg-muted/50 transition-colors",onClick:r,children:e.jsxs("div",{className:"flex items-start justify-between gap-2",children:[e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx("div",{className:P("p-2 rounded-lg",s.enabled?"bg-primary/10":"bg-muted"),children:e.jsx(g,{className:P("w-5 h-5",s.enabled?u.color:"text-muted-foreground")})}),e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-sm font-medium text-foreground",children:s.name}),e.jsx(z,{variant:"outline",className:"text-xs",children:m({id:u.label})}),s.enabled&&e.jsx(z,{variant:"outline",className:"text-xs text-green-600",children:m({id:"cliEndpoints.status.enabled"})})]}),e.jsxs("p",{className:"text-sm text-muted-foreground mt-1",children:[m({id:"cliEndpoints.id"}),": ",s.id]})]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(E,{variant:"ghost",size:"sm",className:"h-8 w-8 p-0","aria-label":m({id:"cliEndpoints.actions.toggle"}),onClick:o=>{o.stopPropagation(),p(s.id,!s.enabled)},children:s.enabled?e.jsx(Q,{className:"w-4 h-4 text-green-600"}):e.jsx(we,{className:"w-4 h-4"})}),e.jsx(E,{variant:"ghost",size:"sm",className:"h-8 w-8 p-0","aria-label":m({id:"cliEndpoints.actions.edit"}),onClick:o=>{o.stopPropagation(),w(s)},children:e.jsx(Ce,{className:"w-4 h-4"})}),e.jsx(E,{variant:"ghost",size:"sm",className:"h-8 w-8 p-0","aria-label":m({id:"cliEndpoints.actions.delete"}),onClick:o=>{o.stopPropagation(),i(s.id)},children:e.jsx(he,{className:"w-4 h-4 text-destructive"})}),a?e.jsx(ge,{className:"w-5 h-5 text-muted-foreground"}):e.jsx(fe,{className:"w-5 h-5 text-muted-foreground"})]})]})}),a&&e.jsx("div",{className:"border-t border-border p-4 space-y-3 bg-muted/30",children:e.jsxs("div",{children:[e.jsx("p",{className:"text-xs text-muted-foreground mb-2",children:m({id:"cliEndpoints.config"})}),e.jsx("div",{className:"bg-background p-3 rounded-md font-mono text-sm overflow-x-auto",children:e.jsx("pre",{children:JSON.stringify(s.config,null,2)})})]})})]})}function qe(){const{formatMessage:s}=R(),{success:a,error:r}=A(),[p,w]=l.useState(""),[i,m]=l.useState("all"),[h,u]=l.useState(new Set),[g,o]=l.useState(!1),[y,C]=l.useState("create"),[f,S]=l.useState(void 0),{endpoints:k,litellmEndpoints:n,customEndpoints:j,totalCount:F,enabledCount:J,isLoading:L,isFetching:T,refetch:d}=je(),{toggleEndpoint:x}=ve(),{createEndpoint:O,isCreating:Z}=Ne(),{updateEndpoint:G,isUpdating:W}=Ee(),{deleteEndpoint:X,isDeleting:Y}=ye(),_=t=>{u(c=>{const v=new Set(c);return v.has(t)?v.delete(t):v.add(t),v})},ee=(t,c)=>{x(t,c)},se=()=>{C("create"),S(void 0),o(!0)},te=t=>{C("edit"),S(t),o(!0)},ie=async t=>{if(confirm(s({id:"cliEndpoints.deleteConfirm"},{id:t})))try{await X(t),a(s({id:"cliEndpoints.messages.deleted"}))}catch(c){console.error("Failed to delete CLI endpoint:",c),r(s({id:"cliEndpoints.messages.deleteFailed"}))}},ae=async t=>{try{if(y==="edit"&&f){await G(f.id,t),a(s({id:"cliEndpoints.messages.updated"}));return}await O(t),a(s({id:"cliEndpoints.messages.created"}))}catch(c){throw console.error("Failed to save CLI endpoint:",c),r(s({id:"cliEndpoints.messages.saveFailed"})),c}},q=(()=>{let t=k;if(i!=="all"&&(t=t.filter(c=>c.type===i)),p){const c=p.toLowerCase();t=t.filter(v=>v.name.toLowerCase().includes(c)||v.id.toLowerCase().includes(c))}return t})();return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4",children:[e.jsxs("div",{children:[e.jsxs("h1",{className:"text-2xl font-bold text-foreground flex items-center gap-2",children:[e.jsx(M,{className:"w-6 h-6 text-primary"}),s({id:"cliEndpoints.title"})]}),e.jsx("p",{className:"text-muted-foreground mt-1",children:s({id:"cliEndpoints.description"})})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs(E,{variant:"outline",onClick:()=>d(),disabled:T,children:[e.jsx(me,{className:P("w-4 h-4 mr-2",T&&"animate-spin")}),s({id:"common.actions.refresh"})]}),e.jsxs(E,{onClick:se,disabled:Z||W||Y,children:[e.jsx(xe,{className:"w-4 h-4 mr-2"}),s({id:"cliEndpoints.actions.add"})]})]})]}),e.jsxs("div",{className:"grid grid-cols-2 md:grid-cols-4 gap-4",children:[e.jsxs(b,{className:"p-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(M,{className:"w-5 h-5 text-primary"}),e.jsx("span",{className:"text-2xl font-bold",children:F})]}),e.jsx("p",{className:"text-sm text-muted-foreground mt-1",children:s({id:"cliEndpoints.stats.total"})})]}),e.jsxs(b,{className:"p-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(Q,{className:"w-5 h-5 text-green-600"}),e.jsx("span",{className:"text-2xl font-bold",children:J})]}),e.jsx("p",{className:"text-sm text-muted-foreground mt-1",children:s({id:"cliEndpoints.stats.enabled"})})]}),e.jsxs(b,{className:"p-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx($,{className:"w-5 h-5 text-blue-600"}),e.jsx("span",{className:"text-2xl font-bold",children:n.length})]}),e.jsx("p",{className:"text-sm text-muted-foreground mt-1",children:s({id:"cliEndpoints.type.litellm"})})]}),e.jsxs(b,{className:"p-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(H,{className:"w-5 h-5 text-purple-600"}),e.jsx("span",{className:"text-2xl font-bold",children:j.length})]}),e.jsx("p",{className:"text-sm text-muted-foreground mt-1",children:s({id:"cliEndpoints.type.custom"})})]})]}),e.jsxs("div",{className:"flex flex-col sm:flex-row gap-3",children:[e.jsxs("div",{className:"relative flex-1",children:[e.jsx(pe,{className:"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground"}),e.jsx(I,{placeholder:s({id:"cliEndpoints.filters.searchPlaceholder"}),value:p,onChange:t=>w(t.target.value),className:"pl-9"})]}),e.jsxs(B,{value:i,onValueChange:t=>m(t),children:[e.jsx(K,{className:"w-[180px]",children:e.jsx(U,{placeholder:s({id:"cliEndpoints.filters.type"})})}),e.jsxs(V,{children:[e.jsx(N,{value:"all",children:s({id:"cliEndpoints.filters.allTypes"})}),e.jsx(N,{value:"litellm",children:s({id:"cliEndpoints.type.litellm"})}),e.jsx(N,{value:"custom",children:s({id:"cliEndpoints.type.custom"})}),e.jsx(N,{value:"wrapper",children:s({id:"cliEndpoints.type.wrapper"})})]})]})]}),L?e.jsx("div",{className:"space-y-3",children:[1,2,3,4].map(t=>e.jsx("div",{className:"h-24 bg-muted animate-pulse rounded-lg"},t))}):q.length===0?e.jsxs(b,{className:"p-8 text-center",children:[e.jsx(M,{className:"w-12 h-12 mx-auto text-muted-foreground/50"}),e.jsx("h3",{className:"mt-4 text-lg font-medium text-foreground",children:s({id:"cliEndpoints.emptyState.title"})}),e.jsx("p",{className:"mt-2 text-muted-foreground",children:s({id:"cliEndpoints.emptyState.message"})})]}):e.jsx("div",{className:"space-y-3",children:q.map(t=>e.jsx(Je,{endpoint:t,isExpanded:h.has(t.id),onToggleExpand:()=>_(t.id),onToggle:ee,onEdit:te,onDelete:ie},t.id))}),e.jsx(Fe,{mode:y,endpoint:f,open:g,onClose:()=>o(!1),onSave:ae})]})}export{qe as EndpointsPage,qe as default};
|
|
2
|
+
//# sourceMappingURL=EndpointsPage-DhW6hYrI.js.map
|
package/ccw/frontend/dist/assets/{EndpointsPage-Ct66AIze.js.map → EndpointsPage-DhW6hYrI.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EndpointsPage-Ct66AIze.js","sources":["../../src/components/cli-endpoints/CliEndpointFormDialog.tsx","../../src/pages/EndpointsPage.tsx"],"sourcesContent":["// ========================================\n// CLI Endpoint Form Dialog\n// ========================================\n// Dialog for creating and editing CLI endpoints\n\nimport { useEffect, useMemo, useState } from 'react';\nimport { useIntl } from 'react-intl';\nimport {\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogFooter,\n} from '@/components/ui/Dialog';\nimport { Input } from '@/components/ui/Input';\nimport { Textarea } from '@/components/ui/Textarea';\nimport { Button } from '@/components/ui/Button';\nimport { Label } from '@/components/ui/Label';\nimport { Switch } from '@/components/ui/Switch';\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/components/ui/Select';\nimport { useNotifications } from '@/hooks/useNotifications';\nimport type { CliEndpoint } from '@/lib/api';\n\nexport type CliEndpointFormMode = 'create' | 'edit';\n\nexport interface CliEndpointSavePayload {\n name: string;\n type: CliEndpoint['type'];\n enabled: boolean;\n config: Record<string, unknown>;\n}\n\nexport interface CliEndpointFormDialogProps {\n mode: CliEndpointFormMode;\n endpoint?: CliEndpoint;\n open: boolean;\n onClose: () => void;\n onSave: (payload: CliEndpointSavePayload) => Promise<void>;\n}\n\ninterface FormErrors {\n name?: string;\n type?: string;\n configJson?: string;\n}\n\nfunction safeStringifyConfig(config: unknown): string {\n try {\n return JSON.stringify(config ?? {}, null, 2);\n } catch {\n return '{}';\n }\n}\n\nfunction parseConfigJson(\n configJson: string\n): { ok: true; value: Record<string, unknown> } | { ok: false; errorKey: string } {\n const trimmed = configJson.trim();\n if (!trimmed) {\n return { ok: true, value: {} };\n }\n\n try {\n const parsed = JSON.parse(trimmed) as unknown;\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n return { ok: false, errorKey: 'validation.configMustBeObject' };\n }\n return { ok: true, value: parsed as Record<string, unknown> };\n } catch {\n return { ok: false, errorKey: 'validation.invalidJson' };\n }\n}\n\nexport function CliEndpointFormDialog({\n mode,\n endpoint,\n open,\n onClose,\n onSave,\n}: CliEndpointFormDialogProps) {\n const { formatMessage } = useIntl();\n const { error: showError } = useNotifications();\n const isEditing = mode === 'edit';\n\n const [name, setName] = useState('');\n const [type, setType] = useState<CliEndpoint['type']>('custom');\n const [enabled, setEnabled] = useState(true);\n const [configJson, setConfigJson] = useState('{}');\n const [errors, setErrors] = useState<FormErrors>({});\n const [isSubmitting, setIsSubmitting] = useState(false);\n\n const dialogTitle = useMemo(() => {\n return isEditing\n ? formatMessage({ id: 'cliEndpoints.dialog.editTitle' }, { id: endpoint?.id ?? '' })\n : formatMessage({ id: 'cliEndpoints.dialog.createTitle' });\n }, [formatMessage, isEditing, endpoint?.id]);\n\n useEffect(() => {\n if (!open) return;\n\n if (isEditing && endpoint) {\n setName(endpoint.name);\n setType(endpoint.type);\n setEnabled(endpoint.enabled);\n setConfigJson(safeStringifyConfig(endpoint.config));\n } else {\n setName('');\n setType('custom');\n setEnabled(true);\n setConfigJson('{}');\n }\n setErrors({});\n setIsSubmitting(false);\n }, [open, isEditing, endpoint]);\n\n const handleSubmit = async () => {\n const nextErrors: FormErrors = {};\n\n if (!name.trim()) {\n nextErrors.name = 'validation.nameRequired';\n }\n if (!type) {\n nextErrors.type = 'validation.typeRequired';\n }\n\n const parsedConfig = parseConfigJson(configJson);\n if (!parsedConfig.ok) {\n nextErrors.configJson = parsedConfig.errorKey;\n }\n\n if (Object.keys(nextErrors).length > 0) {\n setErrors(nextErrors);\n return;\n }\n\n setIsSubmitting(true);\n try {\n await onSave({\n name: name.trim(),\n type,\n enabled,\n config: (parsedConfig as { ok: true; value: Record<string, unknown> }).value,\n });\n onClose();\n } catch (err) {\n showError(formatMessage({ id: 'cliEndpoints.messages.saveFailed' }));\n console.error('Failed to save CLI endpoint:', err);\n } finally {\n setIsSubmitting(false);\n }\n };\n\n return (\n <Dialog open={open} onOpenChange={onClose}>\n <DialogContent className=\"sm:max-w-[720px]\">\n <DialogHeader>\n <DialogTitle>{dialogTitle}</DialogTitle>\n </DialogHeader>\n\n <div className=\"space-y-4 py-4\">\n {isEditing && endpoint && (\n <div className=\"space-y-2\">\n <Label htmlFor=\"cli-endpoint-id\">{formatMessage({ id: 'cliEndpoints.id' })}</Label>\n <Input\n id=\"cli-endpoint-id\"\n value={endpoint.id}\n disabled\n className=\"font-mono\"\n />\n </div>\n )}\n\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-4\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"cli-endpoint-name\">\n {formatMessage({ id: 'cliEndpoints.form.name' })} *\n </Label>\n <Input\n id=\"cli-endpoint-name\"\n value={name}\n onChange={(e) => {\n setName(e.target.value);\n if (errors.name) setErrors((prev) => ({ ...prev, name: undefined }));\n }}\n placeholder={formatMessage({ id: 'cliEndpoints.form.namePlaceholder' })}\n error={!!errors.name}\n />\n {errors.name && (\n <p className=\"text-xs text-destructive\">\n {formatMessage({ id: `cliEndpoints.${errors.name}` })}\n </p>\n )}\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"cli-endpoint-type\">\n {formatMessage({ id: 'cliEndpoints.form.type' })} *\n </Label>\n <Select\n value={type}\n onValueChange={(v) => {\n setType(v as CliEndpoint['type']);\n if (errors.type) setErrors((prev) => ({ ...prev, type: undefined }));\n }}\n >\n <SelectTrigger id=\"cli-endpoint-type\" className={errors.type ? 'border-destructive' : undefined}>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"litellm\">{formatMessage({ id: 'cliEndpoints.type.litellm' })}</SelectItem>\n <SelectItem value=\"custom\">{formatMessage({ id: 'cliEndpoints.type.custom' })}</SelectItem>\n <SelectItem value=\"wrapper\">{formatMessage({ id: 'cliEndpoints.type.wrapper' })}</SelectItem>\n </SelectContent>\n </Select>\n {errors.type && (\n <p className=\"text-xs text-destructive\">\n {formatMessage({ id: `cliEndpoints.${errors.type}` })}\n </p>\n )}\n </div>\n </div>\n\n <div className=\"flex items-center justify-between rounded-md border border-border p-3\">\n <div>\n <p className=\"text-sm font-medium text-foreground\">{formatMessage({ id: 'cliEndpoints.form.enabled' })}</p>\n <p className=\"text-xs text-muted-foreground\">{formatMessage({ id: 'cliEndpoints.form.enabledHint' })}</p>\n </div>\n <Switch checked={enabled} onCheckedChange={setEnabled} />\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"cli-endpoint-config\">{formatMessage({ id: 'cliEndpoints.form.configJson' })}</Label>\n <Textarea\n id=\"cli-endpoint-config\"\n value={configJson}\n onChange={(e) => {\n setConfigJson(e.target.value);\n if (errors.configJson) setErrors((prev) => ({ ...prev, configJson: undefined }));\n }}\n placeholder={formatMessage({ id: 'cliEndpoints.form.configJsonPlaceholder' })}\n className={errors.configJson ? 'font-mono border-destructive' : 'font-mono'}\n rows={10}\n />\n {errors.configJson && (\n <p className=\"text-xs text-destructive\">\n {formatMessage({ id: `cliEndpoints.${errors.configJson}` })}\n </p>\n )}\n </div>\n </div>\n\n <DialogFooter>\n <Button variant=\"outline\" onClick={onClose} disabled={isSubmitting}>\n {formatMessage({ id: 'common.actions.cancel' })}\n </Button>\n <Button onClick={handleSubmit} disabled={isSubmitting}>\n {isSubmitting\n ? formatMessage({ id: 'common.actions.saving' })\n : formatMessage({ id: 'common.actions.save' })}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n}\n\nexport default CliEndpointFormDialog;\n","// ========================================\n// CLI Endpoints Page\n// ========================================\n// Manage LiteLLM endpoints, custom CLI endpoints, and CLI wrapper endpoints\n\nimport { useState } from 'react';\nimport { useIntl } from 'react-intl';\nimport {\n Plug,\n Plus,\n Search,\n RefreshCw,\n Power,\n PowerOff,\n Edit,\n Trash2,\n ChevronDown,\n ChevronUp,\n Zap,\n Code,\n Layers,\n} from 'lucide-react';\nimport { Card } from '@/components/ui/Card';\nimport { Button } from '@/components/ui/Button';\nimport { Input } from '@/components/ui/Input';\nimport { Badge } from '@/components/ui/Badge';\nimport { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from '@/components/ui/Select';\nimport { useCliEndpoints, useCreateCliEndpoint, useDeleteCliEndpoint, useToggleCliEndpoint, useUpdateCliEndpoint } from '@/hooks';\nimport { useNotifications } from '@/hooks/useNotifications';\nimport type { CliEndpoint } from '@/lib/api';\nimport { cn } from '@/lib/utils';\nimport { CliEndpointFormDialog, type CliEndpointFormMode, type CliEndpointSavePayload } from '@/components/cli-endpoints/CliEndpointFormDialog';\n\n// ========== Endpoint Card Component ==========\n\ninterface EndpointCardProps {\n endpoint: CliEndpoint;\n isExpanded: boolean;\n onToggleExpand: () => void;\n onToggle: (endpointId: string, enabled: boolean) => void;\n onEdit: (endpoint: CliEndpoint) => void;\n onDelete: (endpointId: string) => void | Promise<void>;\n}\n\nfunction EndpointCard({ endpoint, isExpanded, onToggleExpand, onToggle, onEdit, onDelete }: EndpointCardProps) {\n const { formatMessage } = useIntl();\n\n const typeConfig = {\n litellm: { icon: Zap, color: 'text-blue-600', label: 'cliEndpoints.type.litellm' },\n custom: { icon: Code, color: 'text-purple-600', label: 'cliEndpoints.type.custom' },\n wrapper: { icon: Layers, color: 'text-orange-600', label: 'cliEndpoints.type.wrapper' },\n };\n\n const config = typeConfig[endpoint.type];\n const Icon = config.icon;\n\n return (\n <Card className={cn('overflow-hidden', !endpoint.enabled && 'opacity-60')}>\n {/* Header */}\n <div\n className=\"p-4 cursor-pointer hover:bg-muted/50 transition-colors\"\n onClick={onToggleExpand}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"flex items-start gap-3\">\n <div className={cn(\n 'p-2 rounded-lg',\n endpoint.enabled ? 'bg-primary/10' : 'bg-muted'\n )}>\n <Icon className={cn(\n 'w-5 h-5',\n endpoint.enabled ? config.color : 'text-muted-foreground'\n )} />\n </div>\n <div>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm font-medium text-foreground\">\n {endpoint.name}\n </span>\n <Badge variant=\"outline\" className=\"text-xs\">\n {formatMessage({ id: config.label })}\n </Badge>\n {endpoint.enabled && (\n <Badge variant=\"outline\" className=\"text-xs text-green-600\">\n {formatMessage({ id: 'cliEndpoints.status.enabled' })}\n </Badge>\n )}\n </div>\n <p className=\"text-sm text-muted-foreground mt-1\">\n {formatMessage({ id: 'cliEndpoints.id' })}: {endpoint.id}\n </p>\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-8 w-8 p-0\"\n aria-label={formatMessage({ id: 'cliEndpoints.actions.toggle' })}\n onClick={(e) => {\n e.stopPropagation();\n onToggle(endpoint.id, !endpoint.enabled);\n }}\n >\n {endpoint.enabled ? <Power className=\"w-4 h-4 text-green-600\" /> : <PowerOff className=\"w-4 h-4\" />}\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-8 w-8 p-0\"\n aria-label={formatMessage({ id: 'cliEndpoints.actions.edit' })}\n onClick={(e) => {\n e.stopPropagation();\n onEdit(endpoint);\n }}\n >\n <Edit className=\"w-4 h-4\" />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-8 w-8 p-0\"\n aria-label={formatMessage({ id: 'cliEndpoints.actions.delete' })}\n onClick={(e) => {\n e.stopPropagation();\n onDelete(endpoint.id);\n }}\n >\n <Trash2 className=\"w-4 h-4 text-destructive\" />\n </Button>\n {isExpanded ? (\n <ChevronUp className=\"w-5 h-5 text-muted-foreground\" />\n ) : (\n <ChevronDown className=\"w-5 h-5 text-muted-foreground\" />\n )}\n </div>\n </div>\n </div>\n\n {/* Expanded Content */}\n {isExpanded && (\n <div className=\"border-t border-border p-4 space-y-3 bg-muted/30\">\n {/* Config display */}\n <div>\n <p className=\"text-xs text-muted-foreground mb-2\">{formatMessage({ id: 'cliEndpoints.config' })}</p>\n <div className=\"bg-background p-3 rounded-md font-mono text-sm overflow-x-auto\">\n <pre>{JSON.stringify(endpoint.config, null, 2)}</pre>\n </div>\n </div>\n </div>\n )}\n </Card>\n );\n}\n\n// ========== Main Page Component ==========\n\nexport function EndpointsPage() {\n const { formatMessage } = useIntl();\n const { success, error: showError } = useNotifications();\n const [searchQuery, setSearchQuery] = useState('');\n const [typeFilter, setTypeFilter] = useState<'all' | 'litellm' | 'custom' | 'wrapper'>('all');\n const [expandedEndpoints, setExpandedEndpoints] = useState<Set<string>>(new Set());\n const [dialogOpen, setDialogOpen] = useState(false);\n const [dialogMode, setDialogMode] = useState<CliEndpointFormMode>('create');\n const [editingEndpoint, setEditingEndpoint] = useState<CliEndpoint | undefined>(undefined);\n\n const {\n endpoints,\n litellmEndpoints,\n customEndpoints,\n totalCount,\n enabledCount,\n isLoading,\n isFetching,\n refetch,\n } = useCliEndpoints();\n\n const { toggleEndpoint } = useToggleCliEndpoint();\n const { createEndpoint, isCreating } = useCreateCliEndpoint();\n const { updateEndpoint, isUpdating } = useUpdateCliEndpoint();\n const { deleteEndpoint, isDeleting } = useDeleteCliEndpoint();\n\n const toggleExpand = (endpointId: string) => {\n setExpandedEndpoints((prev) => {\n const next = new Set(prev);\n if (next.has(endpointId)) {\n next.delete(endpointId);\n } else {\n next.add(endpointId);\n }\n return next;\n });\n };\n\n const handleToggle = (endpointId: string, enabled: boolean) => {\n toggleEndpoint(endpointId, enabled);\n };\n\n const handleAdd = () => {\n setDialogMode('create');\n setEditingEndpoint(undefined);\n setDialogOpen(true);\n };\n\n const handleEdit = (endpoint: CliEndpoint) => {\n setDialogMode('edit');\n setEditingEndpoint(endpoint);\n setDialogOpen(true);\n };\n\n const handleDelete = async (endpointId: string) => {\n if (!confirm(formatMessage({ id: 'cliEndpoints.deleteConfirm' }, { id: endpointId }))) return;\n\n try {\n await deleteEndpoint(endpointId);\n success(formatMessage({ id: 'cliEndpoints.messages.deleted' }));\n } catch (err) {\n console.error('Failed to delete CLI endpoint:', err);\n showError(formatMessage({ id: 'cliEndpoints.messages.deleteFailed' }));\n }\n };\n\n const handleDialogSave = async (payload: CliEndpointSavePayload) => {\n try {\n if (dialogMode === 'edit' && editingEndpoint) {\n await updateEndpoint(editingEndpoint.id, payload);\n success(formatMessage({ id: 'cliEndpoints.messages.updated' }));\n return;\n }\n\n await createEndpoint(payload);\n success(formatMessage({ id: 'cliEndpoints.messages.created' }));\n } catch (err) {\n console.error('Failed to save CLI endpoint:', err);\n showError(formatMessage({ id: 'cliEndpoints.messages.saveFailed' }));\n throw err;\n }\n };\n\n // Filter endpoints by search query and type\n const filteredEndpoints = (() => {\n let filtered = endpoints;\n\n if (typeFilter !== 'all') {\n filtered = filtered.filter((e) => e.type === typeFilter);\n }\n\n if (searchQuery) {\n const searchLower = searchQuery.toLowerCase();\n filtered = filtered.filter((e) =>\n e.name.toLowerCase().includes(searchLower) ||\n e.id.toLowerCase().includes(searchLower)\n );\n }\n\n return filtered;\n })();\n\n return (\n <div className=\"space-y-6\">\n {/* Page Header */}\n <div className=\"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4\">\n <div>\n <h1 className=\"text-2xl font-bold text-foreground flex items-center gap-2\">\n <Plug className=\"w-6 h-6 text-primary\" />\n {formatMessage({ id: 'cliEndpoints.title' })}\n </h1>\n <p className=\"text-muted-foreground mt-1\">\n {formatMessage({ id: 'cliEndpoints.description' })}\n </p>\n </div>\n <div className=\"flex gap-2\">\n <Button variant=\"outline\" onClick={() => refetch()} disabled={isFetching}>\n <RefreshCw className={cn('w-4 h-4 mr-2', isFetching && 'animate-spin')} />\n {formatMessage({ id: 'common.actions.refresh' })}\n </Button>\n <Button onClick={handleAdd} disabled={isCreating || isUpdating || isDeleting}>\n <Plus className=\"w-4 h-4 mr-2\" />\n {formatMessage({ id: 'cliEndpoints.actions.add' })}\n </Button>\n </div>\n </div>\n\n {/* Stats Cards */}\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-4\">\n <Card className=\"p-4\">\n <div className=\"flex items-center gap-2\">\n <Plug className=\"w-5 h-5 text-primary\" />\n <span className=\"text-2xl font-bold\">{totalCount}</span>\n </div>\n <p className=\"text-sm text-muted-foreground mt-1\">{formatMessage({ id: 'cliEndpoints.stats.total' })}</p>\n </Card>\n <Card className=\"p-4\">\n <div className=\"flex items-center gap-2\">\n <Power className=\"w-5 h-5 text-green-600\" />\n <span className=\"text-2xl font-bold\">{enabledCount}</span>\n </div>\n <p className=\"text-sm text-muted-foreground mt-1\">{formatMessage({ id: 'cliEndpoints.stats.enabled' })}</p>\n </Card>\n <Card className=\"p-4\">\n <div className=\"flex items-center gap-2\">\n <Zap className=\"w-5 h-5 text-blue-600\" />\n <span className=\"text-2xl font-bold\">{litellmEndpoints.length}</span>\n </div>\n <p className=\"text-sm text-muted-foreground mt-1\">{formatMessage({ id: 'cliEndpoints.type.litellm' })}</p>\n </Card>\n <Card className=\"p-4\">\n <div className=\"flex items-center gap-2\">\n <Code className=\"w-5 h-5 text-purple-600\" />\n <span className=\"text-2xl font-bold\">{customEndpoints.length}</span>\n </div>\n <p className=\"text-sm text-muted-foreground mt-1\">{formatMessage({ id: 'cliEndpoints.type.custom' })}</p>\n </Card>\n </div>\n\n {/* Filters and Search */}\n <div className=\"flex flex-col sm:flex-row gap-3\">\n <div className=\"relative flex-1\">\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground\" />\n <Input\n placeholder={formatMessage({ id: 'cliEndpoints.filters.searchPlaceholder' })}\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n className=\"pl-9\"\n />\n </div>\n <Select value={typeFilter} onValueChange={(v: typeof typeFilter) => setTypeFilter(v)}>\n <SelectTrigger className=\"w-[180px]\">\n <SelectValue placeholder={formatMessage({ id: 'cliEndpoints.filters.type' })} />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"all\">{formatMessage({ id: 'cliEndpoints.filters.allTypes' })}</SelectItem>\n <SelectItem value=\"litellm\">{formatMessage({ id: 'cliEndpoints.type.litellm' })}</SelectItem>\n <SelectItem value=\"custom\">{formatMessage({ id: 'cliEndpoints.type.custom' })}</SelectItem>\n <SelectItem value=\"wrapper\">{formatMessage({ id: 'cliEndpoints.type.wrapper' })}</SelectItem>\n </SelectContent>\n </Select>\n </div>\n\n {/* Endpoints List */}\n {isLoading ? (\n <div className=\"space-y-3\">\n {[1, 2, 3, 4].map((i) => (\n <div key={i} className=\"h-24 bg-muted animate-pulse rounded-lg\" />\n ))}\n </div>\n ) : filteredEndpoints.length === 0 ? (\n <Card className=\"p-8 text-center\">\n <Plug className=\"w-12 h-12 mx-auto text-muted-foreground/50\" />\n <h3 className=\"mt-4 text-lg font-medium text-foreground\">{formatMessage({ id: 'cliEndpoints.emptyState.title' })}</h3>\n <p className=\"mt-2 text-muted-foreground\">\n {formatMessage({ id: 'cliEndpoints.emptyState.message' })}\n </p>\n </Card>\n ) : (\n <div className=\"space-y-3\">\n {filteredEndpoints.map((endpoint) => (\n <EndpointCard\n key={endpoint.id}\n endpoint={endpoint}\n isExpanded={expandedEndpoints.has(endpoint.id)}\n onToggleExpand={() => toggleExpand(endpoint.id)}\n onToggle={handleToggle}\n onEdit={handleEdit}\n onDelete={handleDelete}\n />\n ))}\n </div>\n )}\n\n <CliEndpointFormDialog\n mode={dialogMode}\n endpoint={editingEndpoint}\n open={dialogOpen}\n onClose={() => setDialogOpen(false)}\n onSave={handleDialogSave}\n />\n </div>\n );\n}\n\nexport default EndpointsPage;\n"],"names":["safeStringifyConfig","config","parseConfigJson","configJson","trimmed","parsed","CliEndpointFormDialog","mode","endpoint","open","onClose","onSave","formatMessage","useIntl","showError","useNotifications","isEditing","name","setName","useState","type","setType","enabled","setEnabled","setConfigJson","errors","setErrors","isSubmitting","setIsSubmitting","dialogTitle","useMemo","useEffect","handleSubmit","nextErrors","parsedConfig","err","jsx","Dialog","jsxs","DialogContent","DialogHeader","DialogTitle","Label","Input","e","prev","Select","v","SelectTrigger","SelectValue","SelectContent","SelectItem","Switch","Textarea","DialogFooter","Button","EndpointCard","isExpanded","onToggleExpand","onToggle","onEdit","onDelete","Zap","Code","Layers","Icon","Card","cn","Badge","Power","PowerOff","Edit","Trash2","ChevronUp","ChevronDown","EndpointsPage","success","searchQuery","setSearchQuery","typeFilter","setTypeFilter","expandedEndpoints","setExpandedEndpoints","dialogOpen","setDialogOpen","dialogMode","setDialogMode","editingEndpoint","setEditingEndpoint","endpoints","litellmEndpoints","customEndpoints","totalCount","enabledCount","isLoading","isFetching","refetch","useCliEndpoints","toggleEndpoint","useToggleCliEndpoint","createEndpoint","isCreating","useCreateCliEndpoint","updateEndpoint","isUpdating","useUpdateCliEndpoint","deleteEndpoint","isDeleting","useDeleteCliEndpoint","toggleExpand","endpointId","next","handleToggle","handleAdd","handleEdit","handleDelete","handleDialogSave","payload","filteredEndpoints","filtered","searchLower","Plug","RefreshCw","Plus","Search","i"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"EndpointsPage-DhW6hYrI.js","sources":["../../src/components/cli-endpoints/CliEndpointFormDialog.tsx","../../src/pages/EndpointsPage.tsx"],"sourcesContent":["// ========================================\n// CLI Endpoint Form Dialog\n// ========================================\n// Dialog for creating and editing CLI endpoints\n\nimport { useEffect, useMemo, useState } from 'react';\nimport { useIntl } from 'react-intl';\nimport {\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogFooter,\n} from '@/components/ui/Dialog';\nimport { Input } from '@/components/ui/Input';\nimport { Textarea } from '@/components/ui/Textarea';\nimport { Button } from '@/components/ui/Button';\nimport { Label } from '@/components/ui/Label';\nimport { Switch } from '@/components/ui/Switch';\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/components/ui/Select';\nimport { useNotifications } from '@/hooks/useNotifications';\nimport type { CliEndpoint } from '@/lib/api';\n\nexport type CliEndpointFormMode = 'create' | 'edit';\n\nexport interface CliEndpointSavePayload {\n name: string;\n type: CliEndpoint['type'];\n enabled: boolean;\n config: Record<string, unknown>;\n}\n\nexport interface CliEndpointFormDialogProps {\n mode: CliEndpointFormMode;\n endpoint?: CliEndpoint;\n open: boolean;\n onClose: () => void;\n onSave: (payload: CliEndpointSavePayload) => Promise<void>;\n}\n\ninterface FormErrors {\n name?: string;\n type?: string;\n configJson?: string;\n}\n\nfunction safeStringifyConfig(config: unknown): string {\n try {\n return JSON.stringify(config ?? {}, null, 2);\n } catch {\n return '{}';\n }\n}\n\nfunction parseConfigJson(\n configJson: string\n): { ok: true; value: Record<string, unknown> } | { ok: false; errorKey: string } {\n const trimmed = configJson.trim();\n if (!trimmed) {\n return { ok: true, value: {} };\n }\n\n try {\n const parsed = JSON.parse(trimmed) as unknown;\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n return { ok: false, errorKey: 'validation.configMustBeObject' };\n }\n return { ok: true, value: parsed as Record<string, unknown> };\n } catch {\n return { ok: false, errorKey: 'validation.invalidJson' };\n }\n}\n\nexport function CliEndpointFormDialog({\n mode,\n endpoint,\n open,\n onClose,\n onSave,\n}: CliEndpointFormDialogProps) {\n const { formatMessage } = useIntl();\n const { error: showError } = useNotifications();\n const isEditing = mode === 'edit';\n\n const [name, setName] = useState('');\n const [type, setType] = useState<CliEndpoint['type']>('custom');\n const [enabled, setEnabled] = useState(true);\n const [configJson, setConfigJson] = useState('{}');\n const [errors, setErrors] = useState<FormErrors>({});\n const [isSubmitting, setIsSubmitting] = useState(false);\n\n const dialogTitle = useMemo(() => {\n return isEditing\n ? formatMessage({ id: 'cliEndpoints.dialog.editTitle' }, { id: endpoint?.id ?? '' })\n : formatMessage({ id: 'cliEndpoints.dialog.createTitle' });\n }, [formatMessage, isEditing, endpoint?.id]);\n\n useEffect(() => {\n if (!open) return;\n\n if (isEditing && endpoint) {\n setName(endpoint.name);\n setType(endpoint.type);\n setEnabled(endpoint.enabled);\n setConfigJson(safeStringifyConfig(endpoint.config));\n } else {\n setName('');\n setType('custom');\n setEnabled(true);\n setConfigJson('{}');\n }\n setErrors({});\n setIsSubmitting(false);\n }, [open, isEditing, endpoint]);\n\n const handleSubmit = async () => {\n const nextErrors: FormErrors = {};\n\n if (!name.trim()) {\n nextErrors.name = 'validation.nameRequired';\n }\n if (!type) {\n nextErrors.type = 'validation.typeRequired';\n }\n\n const parsedConfig = parseConfigJson(configJson);\n if (!parsedConfig.ok) {\n nextErrors.configJson = parsedConfig.errorKey;\n }\n\n if (Object.keys(nextErrors).length > 0) {\n setErrors(nextErrors);\n return;\n }\n\n setIsSubmitting(true);\n try {\n await onSave({\n name: name.trim(),\n type,\n enabled,\n config: (parsedConfig as { ok: true; value: Record<string, unknown> }).value,\n });\n onClose();\n } catch (err) {\n showError(formatMessage({ id: 'cliEndpoints.messages.saveFailed' }));\n console.error('Failed to save CLI endpoint:', err);\n } finally {\n setIsSubmitting(false);\n }\n };\n\n return (\n <Dialog open={open} onOpenChange={onClose}>\n <DialogContent className=\"sm:max-w-[720px]\">\n <DialogHeader>\n <DialogTitle>{dialogTitle}</DialogTitle>\n </DialogHeader>\n\n <div className=\"space-y-4 py-4\">\n {isEditing && endpoint && (\n <div className=\"space-y-2\">\n <Label htmlFor=\"cli-endpoint-id\">{formatMessage({ id: 'cliEndpoints.id' })}</Label>\n <Input\n id=\"cli-endpoint-id\"\n value={endpoint.id}\n disabled\n className=\"font-mono\"\n />\n </div>\n )}\n\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-4\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"cli-endpoint-name\">\n {formatMessage({ id: 'cliEndpoints.form.name' })} *\n </Label>\n <Input\n id=\"cli-endpoint-name\"\n value={name}\n onChange={(e) => {\n setName(e.target.value);\n if (errors.name) setErrors((prev) => ({ ...prev, name: undefined }));\n }}\n placeholder={formatMessage({ id: 'cliEndpoints.form.namePlaceholder' })}\n error={!!errors.name}\n />\n {errors.name && (\n <p className=\"text-xs text-destructive\">\n {formatMessage({ id: `cliEndpoints.${errors.name}` })}\n </p>\n )}\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"cli-endpoint-type\">\n {formatMessage({ id: 'cliEndpoints.form.type' })} *\n </Label>\n <Select\n value={type}\n onValueChange={(v) => {\n setType(v as CliEndpoint['type']);\n if (errors.type) setErrors((prev) => ({ ...prev, type: undefined }));\n }}\n >\n <SelectTrigger id=\"cli-endpoint-type\" className={errors.type ? 'border-destructive' : undefined}>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"litellm\">{formatMessage({ id: 'cliEndpoints.type.litellm' })}</SelectItem>\n <SelectItem value=\"custom\">{formatMessage({ id: 'cliEndpoints.type.custom' })}</SelectItem>\n <SelectItem value=\"wrapper\">{formatMessage({ id: 'cliEndpoints.type.wrapper' })}</SelectItem>\n </SelectContent>\n </Select>\n {errors.type && (\n <p className=\"text-xs text-destructive\">\n {formatMessage({ id: `cliEndpoints.${errors.type}` })}\n </p>\n )}\n </div>\n </div>\n\n <div className=\"flex items-center justify-between rounded-md border border-border p-3\">\n <div>\n <p className=\"text-sm font-medium text-foreground\">{formatMessage({ id: 'cliEndpoints.form.enabled' })}</p>\n <p className=\"text-xs text-muted-foreground\">{formatMessage({ id: 'cliEndpoints.form.enabledHint' })}</p>\n </div>\n <Switch checked={enabled} onCheckedChange={setEnabled} />\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"cli-endpoint-config\">{formatMessage({ id: 'cliEndpoints.form.configJson' })}</Label>\n <Textarea\n id=\"cli-endpoint-config\"\n value={configJson}\n onChange={(e) => {\n setConfigJson(e.target.value);\n if (errors.configJson) setErrors((prev) => ({ ...prev, configJson: undefined }));\n }}\n placeholder={formatMessage({ id: 'cliEndpoints.form.configJsonPlaceholder' })}\n className={errors.configJson ? 'font-mono border-destructive' : 'font-mono'}\n rows={10}\n />\n {errors.configJson && (\n <p className=\"text-xs text-destructive\">\n {formatMessage({ id: `cliEndpoints.${errors.configJson}` })}\n </p>\n )}\n </div>\n </div>\n\n <DialogFooter>\n <Button variant=\"outline\" onClick={onClose} disabled={isSubmitting}>\n {formatMessage({ id: 'common.actions.cancel' })}\n </Button>\n <Button onClick={handleSubmit} disabled={isSubmitting}>\n {isSubmitting\n ? formatMessage({ id: 'common.actions.saving' })\n : formatMessage({ id: 'common.actions.save' })}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n}\n\nexport default CliEndpointFormDialog;\n","// ========================================\n// CLI Endpoints Page\n// ========================================\n// Manage LiteLLM endpoints, custom CLI endpoints, and CLI wrapper endpoints\n\nimport { useState } from 'react';\nimport { useIntl } from 'react-intl';\nimport {\n Plug,\n Plus,\n Search,\n RefreshCw,\n Power,\n PowerOff,\n Edit,\n Trash2,\n ChevronDown,\n ChevronUp,\n Zap,\n Code,\n Layers,\n} from 'lucide-react';\nimport { Card } from '@/components/ui/Card';\nimport { Button } from '@/components/ui/Button';\nimport { Input } from '@/components/ui/Input';\nimport { Badge } from '@/components/ui/Badge';\nimport { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from '@/components/ui/Select';\nimport { useCliEndpoints, useCreateCliEndpoint, useDeleteCliEndpoint, useToggleCliEndpoint, useUpdateCliEndpoint } from '@/hooks';\nimport { useNotifications } from '@/hooks/useNotifications';\nimport type { CliEndpoint } from '@/lib/api';\nimport { cn } from '@/lib/utils';\nimport { CliEndpointFormDialog, type CliEndpointFormMode, type CliEndpointSavePayload } from '@/components/cli-endpoints/CliEndpointFormDialog';\n\n// ========== Endpoint Card Component ==========\n\ninterface EndpointCardProps {\n endpoint: CliEndpoint;\n isExpanded: boolean;\n onToggleExpand: () => void;\n onToggle: (endpointId: string, enabled: boolean) => void;\n onEdit: (endpoint: CliEndpoint) => void;\n onDelete: (endpointId: string) => void | Promise<void>;\n}\n\nfunction EndpointCard({ endpoint, isExpanded, onToggleExpand, onToggle, onEdit, onDelete }: EndpointCardProps) {\n const { formatMessage } = useIntl();\n\n const typeConfig = {\n litellm: { icon: Zap, color: 'text-blue-600', label: 'cliEndpoints.type.litellm' },\n custom: { icon: Code, color: 'text-purple-600', label: 'cliEndpoints.type.custom' },\n wrapper: { icon: Layers, color: 'text-orange-600', label: 'cliEndpoints.type.wrapper' },\n };\n\n const config = typeConfig[endpoint.type];\n const Icon = config.icon;\n\n return (\n <Card className={cn('overflow-hidden', !endpoint.enabled && 'opacity-60')}>\n {/* Header */}\n <div\n className=\"p-4 cursor-pointer hover:bg-muted/50 transition-colors\"\n onClick={onToggleExpand}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"flex items-start gap-3\">\n <div className={cn(\n 'p-2 rounded-lg',\n endpoint.enabled ? 'bg-primary/10' : 'bg-muted'\n )}>\n <Icon className={cn(\n 'w-5 h-5',\n endpoint.enabled ? config.color : 'text-muted-foreground'\n )} />\n </div>\n <div>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm font-medium text-foreground\">\n {endpoint.name}\n </span>\n <Badge variant=\"outline\" className=\"text-xs\">\n {formatMessage({ id: config.label })}\n </Badge>\n {endpoint.enabled && (\n <Badge variant=\"outline\" className=\"text-xs text-green-600\">\n {formatMessage({ id: 'cliEndpoints.status.enabled' })}\n </Badge>\n )}\n </div>\n <p className=\"text-sm text-muted-foreground mt-1\">\n {formatMessage({ id: 'cliEndpoints.id' })}: {endpoint.id}\n </p>\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-8 w-8 p-0\"\n aria-label={formatMessage({ id: 'cliEndpoints.actions.toggle' })}\n onClick={(e) => {\n e.stopPropagation();\n onToggle(endpoint.id, !endpoint.enabled);\n }}\n >\n {endpoint.enabled ? <Power className=\"w-4 h-4 text-green-600\" /> : <PowerOff className=\"w-4 h-4\" />}\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-8 w-8 p-0\"\n aria-label={formatMessage({ id: 'cliEndpoints.actions.edit' })}\n onClick={(e) => {\n e.stopPropagation();\n onEdit(endpoint);\n }}\n >\n <Edit className=\"w-4 h-4\" />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-8 w-8 p-0\"\n aria-label={formatMessage({ id: 'cliEndpoints.actions.delete' })}\n onClick={(e) => {\n e.stopPropagation();\n onDelete(endpoint.id);\n }}\n >\n <Trash2 className=\"w-4 h-4 text-destructive\" />\n </Button>\n {isExpanded ? (\n <ChevronUp className=\"w-5 h-5 text-muted-foreground\" />\n ) : (\n <ChevronDown className=\"w-5 h-5 text-muted-foreground\" />\n )}\n </div>\n </div>\n </div>\n\n {/* Expanded Content */}\n {isExpanded && (\n <div className=\"border-t border-border p-4 space-y-3 bg-muted/30\">\n {/* Config display */}\n <div>\n <p className=\"text-xs text-muted-foreground mb-2\">{formatMessage({ id: 'cliEndpoints.config' })}</p>\n <div className=\"bg-background p-3 rounded-md font-mono text-sm overflow-x-auto\">\n <pre>{JSON.stringify(endpoint.config, null, 2)}</pre>\n </div>\n </div>\n </div>\n )}\n </Card>\n );\n}\n\n// ========== Main Page Component ==========\n\nexport function EndpointsPage() {\n const { formatMessage } = useIntl();\n const { success, error: showError } = useNotifications();\n const [searchQuery, setSearchQuery] = useState('');\n const [typeFilter, setTypeFilter] = useState<'all' | 'litellm' | 'custom' | 'wrapper'>('all');\n const [expandedEndpoints, setExpandedEndpoints] = useState<Set<string>>(new Set());\n const [dialogOpen, setDialogOpen] = useState(false);\n const [dialogMode, setDialogMode] = useState<CliEndpointFormMode>('create');\n const [editingEndpoint, setEditingEndpoint] = useState<CliEndpoint | undefined>(undefined);\n\n const {\n endpoints,\n litellmEndpoints,\n customEndpoints,\n totalCount,\n enabledCount,\n isLoading,\n isFetching,\n refetch,\n } = useCliEndpoints();\n\n const { toggleEndpoint } = useToggleCliEndpoint();\n const { createEndpoint, isCreating } = useCreateCliEndpoint();\n const { updateEndpoint, isUpdating } = useUpdateCliEndpoint();\n const { deleteEndpoint, isDeleting } = useDeleteCliEndpoint();\n\n const toggleExpand = (endpointId: string) => {\n setExpandedEndpoints((prev) => {\n const next = new Set(prev);\n if (next.has(endpointId)) {\n next.delete(endpointId);\n } else {\n next.add(endpointId);\n }\n return next;\n });\n };\n\n const handleToggle = (endpointId: string, enabled: boolean) => {\n toggleEndpoint(endpointId, enabled);\n };\n\n const handleAdd = () => {\n setDialogMode('create');\n setEditingEndpoint(undefined);\n setDialogOpen(true);\n };\n\n const handleEdit = (endpoint: CliEndpoint) => {\n setDialogMode('edit');\n setEditingEndpoint(endpoint);\n setDialogOpen(true);\n };\n\n const handleDelete = async (endpointId: string) => {\n if (!confirm(formatMessage({ id: 'cliEndpoints.deleteConfirm' }, { id: endpointId }))) return;\n\n try {\n await deleteEndpoint(endpointId);\n success(formatMessage({ id: 'cliEndpoints.messages.deleted' }));\n } catch (err) {\n console.error('Failed to delete CLI endpoint:', err);\n showError(formatMessage({ id: 'cliEndpoints.messages.deleteFailed' }));\n }\n };\n\n const handleDialogSave = async (payload: CliEndpointSavePayload) => {\n try {\n if (dialogMode === 'edit' && editingEndpoint) {\n await updateEndpoint(editingEndpoint.id, payload);\n success(formatMessage({ id: 'cliEndpoints.messages.updated' }));\n return;\n }\n\n await createEndpoint(payload);\n success(formatMessage({ id: 'cliEndpoints.messages.created' }));\n } catch (err) {\n console.error('Failed to save CLI endpoint:', err);\n showError(formatMessage({ id: 'cliEndpoints.messages.saveFailed' }));\n throw err;\n }\n };\n\n // Filter endpoints by search query and type\n const filteredEndpoints = (() => {\n let filtered = endpoints;\n\n if (typeFilter !== 'all') {\n filtered = filtered.filter((e) => e.type === typeFilter);\n }\n\n if (searchQuery) {\n const searchLower = searchQuery.toLowerCase();\n filtered = filtered.filter((e) =>\n e.name.toLowerCase().includes(searchLower) ||\n e.id.toLowerCase().includes(searchLower)\n );\n }\n\n return filtered;\n })();\n\n return (\n <div className=\"space-y-6\">\n {/* Page Header */}\n <div className=\"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4\">\n <div>\n <h1 className=\"text-2xl font-bold text-foreground flex items-center gap-2\">\n <Plug className=\"w-6 h-6 text-primary\" />\n {formatMessage({ id: 'cliEndpoints.title' })}\n </h1>\n <p className=\"text-muted-foreground mt-1\">\n {formatMessage({ id: 'cliEndpoints.description' })}\n </p>\n </div>\n <div className=\"flex gap-2\">\n <Button variant=\"outline\" onClick={() => refetch()} disabled={isFetching}>\n <RefreshCw className={cn('w-4 h-4 mr-2', isFetching && 'animate-spin')} />\n {formatMessage({ id: 'common.actions.refresh' })}\n </Button>\n <Button onClick={handleAdd} disabled={isCreating || isUpdating || isDeleting}>\n <Plus className=\"w-4 h-4 mr-2\" />\n {formatMessage({ id: 'cliEndpoints.actions.add' })}\n </Button>\n </div>\n </div>\n\n {/* Stats Cards */}\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-4\">\n <Card className=\"p-4\">\n <div className=\"flex items-center gap-2\">\n <Plug className=\"w-5 h-5 text-primary\" />\n <span className=\"text-2xl font-bold\">{totalCount}</span>\n </div>\n <p className=\"text-sm text-muted-foreground mt-1\">{formatMessage({ id: 'cliEndpoints.stats.total' })}</p>\n </Card>\n <Card className=\"p-4\">\n <div className=\"flex items-center gap-2\">\n <Power className=\"w-5 h-5 text-green-600\" />\n <span className=\"text-2xl font-bold\">{enabledCount}</span>\n </div>\n <p className=\"text-sm text-muted-foreground mt-1\">{formatMessage({ id: 'cliEndpoints.stats.enabled' })}</p>\n </Card>\n <Card className=\"p-4\">\n <div className=\"flex items-center gap-2\">\n <Zap className=\"w-5 h-5 text-blue-600\" />\n <span className=\"text-2xl font-bold\">{litellmEndpoints.length}</span>\n </div>\n <p className=\"text-sm text-muted-foreground mt-1\">{formatMessage({ id: 'cliEndpoints.type.litellm' })}</p>\n </Card>\n <Card className=\"p-4\">\n <div className=\"flex items-center gap-2\">\n <Code className=\"w-5 h-5 text-purple-600\" />\n <span className=\"text-2xl font-bold\">{customEndpoints.length}</span>\n </div>\n <p className=\"text-sm text-muted-foreground mt-1\">{formatMessage({ id: 'cliEndpoints.type.custom' })}</p>\n </Card>\n </div>\n\n {/* Filters and Search */}\n <div className=\"flex flex-col sm:flex-row gap-3\">\n <div className=\"relative flex-1\">\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground\" />\n <Input\n placeholder={formatMessage({ id: 'cliEndpoints.filters.searchPlaceholder' })}\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n className=\"pl-9\"\n />\n </div>\n <Select value={typeFilter} onValueChange={(v: typeof typeFilter) => setTypeFilter(v)}>\n <SelectTrigger className=\"w-[180px]\">\n <SelectValue placeholder={formatMessage({ id: 'cliEndpoints.filters.type' })} />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"all\">{formatMessage({ id: 'cliEndpoints.filters.allTypes' })}</SelectItem>\n <SelectItem value=\"litellm\">{formatMessage({ id: 'cliEndpoints.type.litellm' })}</SelectItem>\n <SelectItem value=\"custom\">{formatMessage({ id: 'cliEndpoints.type.custom' })}</SelectItem>\n <SelectItem value=\"wrapper\">{formatMessage({ id: 'cliEndpoints.type.wrapper' })}</SelectItem>\n </SelectContent>\n </Select>\n </div>\n\n {/* Endpoints List */}\n {isLoading ? (\n <div className=\"space-y-3\">\n {[1, 2, 3, 4].map((i) => (\n <div key={i} className=\"h-24 bg-muted animate-pulse rounded-lg\" />\n ))}\n </div>\n ) : filteredEndpoints.length === 0 ? (\n <Card className=\"p-8 text-center\">\n <Plug className=\"w-12 h-12 mx-auto text-muted-foreground/50\" />\n <h3 className=\"mt-4 text-lg font-medium text-foreground\">{formatMessage({ id: 'cliEndpoints.emptyState.title' })}</h3>\n <p className=\"mt-2 text-muted-foreground\">\n {formatMessage({ id: 'cliEndpoints.emptyState.message' })}\n </p>\n </Card>\n ) : (\n <div className=\"space-y-3\">\n {filteredEndpoints.map((endpoint) => (\n <EndpointCard\n key={endpoint.id}\n endpoint={endpoint}\n isExpanded={expandedEndpoints.has(endpoint.id)}\n onToggleExpand={() => toggleExpand(endpoint.id)}\n onToggle={handleToggle}\n onEdit={handleEdit}\n onDelete={handleDelete}\n />\n ))}\n </div>\n )}\n\n <CliEndpointFormDialog\n mode={dialogMode}\n endpoint={editingEndpoint}\n open={dialogOpen}\n onClose={() => setDialogOpen(false)}\n onSave={handleDialogSave}\n />\n </div>\n );\n}\n\nexport default EndpointsPage;\n"],"names":["safeStringifyConfig","config","parseConfigJson","configJson","trimmed","parsed","CliEndpointFormDialog","mode","endpoint","open","onClose","onSave","formatMessage","useIntl","showError","useNotifications","isEditing","name","setName","useState","type","setType","enabled","setEnabled","setConfigJson","errors","setErrors","isSubmitting","setIsSubmitting","dialogTitle","useMemo","useEffect","handleSubmit","nextErrors","parsedConfig","err","jsx","Dialog","jsxs","DialogContent","DialogHeader","DialogTitle","Label","Input","e","prev","Select","v","SelectTrigger","SelectValue","SelectContent","SelectItem","Switch","Textarea","DialogFooter","Button","EndpointCard","isExpanded","onToggleExpand","onToggle","onEdit","onDelete","Zap","Code","Layers","Icon","Card","cn","Badge","Power","PowerOff","Edit","Trash2","ChevronUp","ChevronDown","EndpointsPage","success","searchQuery","setSearchQuery","typeFilter","setTypeFilter","expandedEndpoints","setExpandedEndpoints","dialogOpen","setDialogOpen","dialogMode","setDialogMode","editingEndpoint","setEditingEndpoint","endpoints","litellmEndpoints","customEndpoints","totalCount","enabledCount","isLoading","isFetching","refetch","useCliEndpoints","toggleEndpoint","useToggleCliEndpoint","createEndpoint","isCreating","useCreateCliEndpoint","updateEndpoint","isUpdating","useUpdateCliEndpoint","deleteEndpoint","isDeleting","useDeleteCliEndpoint","toggleExpand","endpointId","next","handleToggle","handleAdd","handleEdit","handleDelete","handleDialogSave","payload","filteredEndpoints","filtered","searchLower","Plug","RefreshCw","Plus","Search","i"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{u as $,j as e,D as v,d as C,e as u,ap as I,f as y,v as R,h as k,g as o,c as a,b as Y,I as Z,X as ee,R as se,ao as A,r as D,m as re,N as te}from"./index-
|
|
2
|
-
//# sourceMappingURL=ExplorerPage-
|
|
1
|
+
import{u as $,j as e,D as v,d as C,e as u,ap as I,f as y,v as R,h as k,g as o,c as a,b as Y,I as Z,X as ee,R as se,ao as A,r as D,m as re,N as te}from"./index-DP_mTJI8.js";import{u as le,a as ae,T as oe,F as ne}from"./useFileExplorer-B8W2JTj2.js";import{L as H}from"./list-BAwzl4a2.js";import{G as O}from"./grid-3x3-SjX0a5JH.js";import"./folder-BkivHBwn.js";function _(l){if(l.name)return l.name;const n=l.path.split(/[/\\]/);return n[n.length-1]||l.path}function ie({searchQuery:l,onSearchChange:n,onSearchClear:E,onRefresh:M,rootDirectories:x,selectedRoot:j,onRootChange:g,isLoadingRoots:f=!1,viewMode:t,onViewModeChange:N,sortOrder:i,onSortOrderChange:S,showHiddenFiles:m,onToggleShowHidden:z,onExpandAll:h,onCollapseAll:b,className:L}){const{formatMessage:s}=$(),w=x.find(r=>r.path===j),d=r=>{S(r)},p=r=>{N(r)};return e.jsxs("div",{className:a("flex items-center gap-2 px-4 py-2 border-b border-border bg-muted/30",L),children:[e.jsxs(v,{children:[e.jsx(C,{asChild:!0,children:e.jsxs(u,{variant:"outline",size:"sm",className:"gap-2 max-w-[200px]",children:[e.jsx("span",{className:"truncate",children:w?_(w):s({id:"explorer.toolbar.selectRoot"})}),e.jsx(I,{className:"h-4 w-4 flex-shrink-0"})]})}),e.jsxs(y,{align:"start",className:"w-56",children:[e.jsx(R,{children:s({id:"explorer.toolbar.rootDirectory"})}),e.jsx(k,{}),x.map(r=>e.jsxs(o,{onClick:()=>g(r.path),className:a("flex items-center gap-2 cursor-pointer",j===r.path&&"bg-accent"),children:[e.jsx("span",{className:"flex-1 truncate",children:_(r)}),r.isWorkspace&&e.jsx("span",{className:"text-xs text-primary",children:"WS"}),r.isGitRoot&&e.jsx("span",{className:"text-xs text-success",children:"GIT"})]},r.path)),x.length===0&&!f&&e.jsx("div",{className:"px-2 py-4 text-sm text-muted-foreground text-center",children:s({id:"explorer.toolbar.noRoots"})})]})]}),e.jsxs("div",{className:"flex-1 max-w-sm relative",children:[e.jsx(Y,{className:"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground"}),e.jsx(Z,{placeholder:s({id:"explorer.toolbar.searchPlaceholder"}),value:l,onChange:r=>n(r.target.value),className:"pl-9 pr-9 h-8"}),l&&e.jsx("button",{onClick:E,className:"absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground","aria-label":s({id:"common.actions.clear"}),children:e.jsx(ee,{className:"h-4 w-4"})})]}),e.jsx(u,{variant:"outline",size:"sm",onClick:M,title:s({id:"common.actions.refresh"}),className:"h-8 w-8 p-0",children:e.jsx(se,{className:"h-4 w-4"})}),e.jsxs(v,{children:[e.jsx(C,{asChild:!0,children:e.jsx(u,{variant:"outline",size:"sm",title:s({id:"explorer.toolbar.viewMode"}),className:"h-8 w-8 p-0",children:t==="tree"?e.jsx(A,{className:"h-4 w-4"}):t==="list"?e.jsx(H,{className:"h-4 w-4"}):e.jsx(O,{className:"h-4 w-4"})})}),e.jsxs(y,{align:"end",children:[e.jsx(R,{children:s({id:"explorer.toolbar.viewMode"})}),e.jsx(k,{}),e.jsxs(o,{onClick:()=>p("tree"),className:a("cursor-pointer",t==="tree"&&"bg-accent"),children:[e.jsx(A,{className:"h-4 w-4 mr-2"}),s({id:"explorer.viewMode.tree"})]}),e.jsxs(o,{onClick:()=>p("list"),className:a("cursor-pointer",t==="list"&&"bg-accent"),children:[e.jsx(H,{className:"h-4 w-4 mr-2"}),s({id:"explorer.viewMode.list"})]}),e.jsxs(o,{onClick:()=>p("compact"),className:a("cursor-pointer",t==="compact"&&"bg-accent"),children:[e.jsx(O,{className:"h-4 w-4 mr-2"}),s({id:"explorer.viewMode.compact"})]})]})]}),e.jsxs(v,{children:[e.jsx(C,{asChild:!0,children:e.jsxs(u,{variant:"outline",size:"sm",title:s({id:"explorer.toolbar.sortBy"}),className:"h-8",children:[s({id:`explorer.sortOrder.${i}`}),e.jsx(I,{className:"h-4 w-4 ml-1"})]})}),e.jsxs(y,{align:"end",children:[e.jsx(R,{children:s({id:"explorer.toolbar.sortBy"})}),e.jsx(k,{}),e.jsx(o,{onClick:()=>d("name"),className:a("cursor-pointer",i==="name"&&"bg-accent"),children:s({id:"explorer.sortOrder.name"})}),e.jsx(o,{onClick:()=>d("size"),className:a("cursor-pointer",i==="size"&&"bg-accent"),children:s({id:"explorer.sortOrder.size"})}),e.jsx(o,{onClick:()=>d("modified"),className:a("cursor-pointer",i==="modified"&&"bg-accent"),children:s({id:"explorer.sortOrder.modified"})}),e.jsx(o,{onClick:()=>d("type"),className:a("cursor-pointer",i==="type"&&"bg-accent"),children:s({id:"explorer.sortOrder.type"})})]})]}),e.jsxs(v,{children:[e.jsx(C,{asChild:!0,children:e.jsx(u,{variant:"outline",size:"sm",title:s({id:"explorer.toolbar.moreOptions"}),className:"h-8 w-8 p-0",children:e.jsx(I,{className:"h-4 w-4"})})}),e.jsxs(y,{align:"end",children:[e.jsx(R,{children:s({id:"explorer.toolbar.options"})}),e.jsx(k,{}),e.jsxs(o,{onClick:z,className:a("cursor-pointer justify-between",m&&"bg-accent"),children:[e.jsx("span",{children:s({id:"explorer.toolbar.showHidden"})}),m&&e.jsx("span",{className:"text-primary",children:"✓"})]}),h&&e.jsx(o,{onClick:h,className:"cursor-pointer",children:s({id:"explorer.toolbar.expandAll"})}),b&&e.jsx(o,{onClick:b,className:"cursor-pointer",children:s({id:"explorer.toolbar.collapseAll"})})]})]})]})}const ce=300,G=200,V=600;function ue(){const{formatMessage:l}=$(),[n,E]=D.useState("/"),[M,x]=D.useState(ce),[j,g]=D.useState(!1),f=D.useRef(null),{state:t,rootNodes:N,isLoading:i,isFetching:S,error:m,refetch:z,setSelectedFile:h,toggleExpanded:b,expandAll:L,collapseAll:s,setViewMode:w,setSortOrder:d,toggleShowHidden:p,setFilter:r,rootDirectories:B,isLoadingRoots:X}=le({rootPath:n,maxDepth:5,enabled:!0}),{content:U,isLoading:q,error:T}=ae(t.selectedFile,{enabled:!!t.selectedFile}),J=c=>{c.type==="file"&&h(c.path)},K=c=>{E(c),h(null)},Q=c=>{c.preventDefault(),g(!0),document.addEventListener("mousemove",W),document.addEventListener("mouseup",P)},W=c=>{if(!f.current)return;const F=c.clientX;F>=G&&F<=V&&x(F)},P=()=>{g(!1),document.removeEventListener("mousemove",W),document.removeEventListener("mouseup",P)};return e.jsxs("div",{className:"flex flex-col h-full",children:[e.jsxs("div",{className:"px-6 py-4 border-b border-border",children:[e.jsx("h1",{className:"text-2xl font-semibold text-foreground",children:l({id:"explorer.title"})}),e.jsx("p",{className:"text-sm text-muted-foreground mt-1",children:l({id:"explorer.description"})})]}),m&&e.jsxs("div",{className:"mx-6 mt-4 flex items-center gap-2 p-4 rounded-lg bg-destructive/10 border border-destructive/30 text-destructive",children:[e.jsx(re,{className:"h-5 w-5 flex-shrink-0"}),e.jsxs("div",{className:"flex-1",children:[e.jsx("p",{className:"text-sm font-medium",children:l({id:"explorer.errors.loadFailed"})}),e.jsx("p",{className:"text-xs mt-0.5",children:m.message})]})]}),e.jsx(ie,{searchQuery:t.filter,onSearchChange:r,onSearchClear:()=>r(""),onRefresh:z,rootDirectories:B||[],selectedRoot:n,onRootChange:K,isLoadingRoots:X,viewMode:t.viewMode,onViewModeChange:w,sortOrder:t.sortOrder,onSortOrderChange:d,showHiddenFiles:t.showHiddenFiles,onToggleShowHidden:p,onExpandAll:L,onCollapseAll:s}),e.jsxs("div",{className:"flex-1 min-h-0 flex overflow-hidden",children:[e.jsxs("div",{ref:f,className:"h-full flex flex-col bg-background border-r border-border",style:{width:`${M}px`,minWidth:`${G}px`,maxWidth:`${V}px`},children:[i&&e.jsxs("div",{className:"flex items-center justify-center py-8",children:[e.jsx(te,{className:"h-6 w-6 animate-spin text-muted-foreground"}),e.jsx("span",{className:"ml-2 text-sm text-muted-foreground",children:l({id:"explorer.tree.loading"})})]}),e.jsx("div",{className:a("flex-1 overflow-auto custom-scrollbar",i&&"opacity-50"),children:e.jsx(oe,{nodes:N,expandedPaths:t.expandedPaths,selectedPath:t.selectedFile,onNodeClick:J,onToggle:b,showIcons:!0,showSizes:!1})}),e.jsxs("div",{className:"px-4 py-2 border-t border-border text-xs text-muted-foreground flex items-center justify-between",children:[e.jsx("span",{children:l({id:"explorer.tree.stats"},{files:N.length,loading:S})}),n!=="/"&&e.jsx("span",{className:"truncate ml-2",title:n,children:n})]})]}),e.jsx("div",{className:a("w-1 bg-border cursor-col-resize hover:bg-primary/50 transition-colors flex-shrink-0",j&&"bg-primary"),onMouseDown:Q}),e.jsx("div",{className:"flex-1 min-w-0 h-full flex flex-col bg-background",children:e.jsx(ne,{fileContent:U,isLoading:q,error:T==null?void 0:T.message,showLineNumbers:!0,maxSize:1024*1024})})]})]})}export{ue as ExplorerPage,ue as default};
|
|
2
|
+
//# sourceMappingURL=ExplorerPage-DYYpCvtB.js.map
|
package/ccw/frontend/dist/assets/{ExplorerPage-DAZkXx2Q.js.map → ExplorerPage-DYYpCvtB.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExplorerPage-DAZkXx2Q.js","sources":["../../src/components/shared/ExplorerToolbar.tsx","../../src/pages/ExplorerPage.tsx"],"sourcesContent":["// ========================================\n// ExplorerToolbar Component\n// ========================================\n// Toolbar component for File Explorer with search and controls\n\nimport { Search, X, ChevronDown, RefreshCw, List, Grid, ChevronRight, ChevronDown as ChevronDownIcon } from 'lucide-react';\nimport { useIntl } from 'react-intl';\nimport { cn } from '@/lib/utils';\nimport { Button } from '@/components/ui/Button';\nimport { Input } from '@/components/ui/Input';\nimport {\n DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuLabel,\n} from '@/components/ui/Dropdown';\nimport type { RootDirectory } from '@/lib/api';\nimport type { ExplorerViewMode, ExplorerSortOrder } from '@/types/file-explorer';\n\nexport interface ExplorerToolbarProps {\n /** Current search query */\n searchQuery: string;\n /** Callback when search query changes */\n onSearchChange: (query: string) => void;\n /** Callback when search is cleared */\n onSearchClear: () => void;\n /** Callback when refresh is requested */\n onRefresh: () => void;\n /** Available root directories */\n rootDirectories: RootDirectory[];\n /** Currently selected root directory */\n selectedRoot: string;\n /** Callback when root directory changes */\n onRootChange: (path: string) => void;\n /** Loading state for root directories */\n isLoadingRoots?: boolean;\n /** Current view mode */\n viewMode: ExplorerViewMode;\n /** Callback when view mode changes */\n onViewModeChange: (mode: ExplorerViewMode) => void;\n /** Current sort order */\n sortOrder: ExplorerSortOrder;\n /** Callback when sort order changes */\n onSortOrderChange: (order: ExplorerSortOrder) => void;\n /** Whether to show hidden files */\n showHiddenFiles: boolean;\n /** Callback when show hidden files toggles */\n onToggleShowHidden: () => void;\n /** Callback to expand all directories */\n onExpandAll?: () => void;\n /** Callback to collapse all directories */\n onCollapseAll?: () => void;\n /** Custom class name */\n className?: string;\n}\n\n/**\n * Get root directory display name\n */\nfunction getRootDisplayName(root: RootDirectory): string {\n if (root.name) return root.name;\n const parts = root.path.split(/[/\\\\]/);\n return parts[parts.length - 1] || root.path;\n}\n\n/**\n * ExplorerToolbar component\n *\n * @example\n * ```tsx\n * <ExplorerToolbar\n * searchQuery={filter}\n * onSearchChange={setFilter}\n * onSearchClear={() => setFilter('')}\n * onRefresh={refetch}\n * rootDirectories={rootDirectories}\n * selectedRoot={rootPath}\n * onRootChange={(path) => setRootPath(path)}\n * viewMode={viewMode}\n * onViewModeChange={setViewMode}\n * sortOrder={sortOrder}\n * onSortOrderChange={setSortOrder}\n * showHiddenFiles={showHiddenFiles}\n * onToggleShowHidden={toggleShowHidden}\n * />\n * ```\n */\nexport function ExplorerToolbar({\n searchQuery,\n onSearchChange,\n onSearchClear,\n onRefresh,\n rootDirectories,\n selectedRoot,\n onRootChange,\n isLoadingRoots = false,\n viewMode,\n onViewModeChange,\n sortOrder,\n onSortOrderChange,\n showHiddenFiles,\n onToggleShowHidden,\n onExpandAll,\n onCollapseAll,\n className,\n}: ExplorerToolbarProps) {\n const { formatMessage } = useIntl();\n\n const selectedRootDir = rootDirectories.find((r) => r.path === selectedRoot);\n\n // Handle sort order change\n const handleSortOrderChange = (order: ExplorerSortOrder) => {\n onSortOrderChange(order);\n };\n\n // Handle view mode change\n const handleViewModeChange = (mode: ExplorerViewMode) => {\n onViewModeChange(mode);\n };\n\n return (\n <div className={cn('flex items-center gap-2 px-4 py-2 border-b border-border bg-muted/30', className)}>\n {/* Root directory selector */}\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"outline\" size=\"sm\" className=\"gap-2 max-w-[200px]\">\n <span className=\"truncate\">\n {selectedRootDir\n ? getRootDisplayName(selectedRootDir)\n : formatMessage({ id: 'explorer.toolbar.selectRoot' })\n }\n </span>\n <ChevronDown className=\"h-4 w-4 flex-shrink-0\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"w-56\">\n <DropdownMenuLabel>\n {formatMessage({ id: 'explorer.toolbar.rootDirectory' })}\n </DropdownMenuLabel>\n <DropdownMenuSeparator />\n {rootDirectories.map((root) => (\n <DropdownMenuItem\n key={root.path}\n onClick={() => onRootChange(root.path)}\n className={cn(\n 'flex items-center gap-2 cursor-pointer',\n selectedRoot === root.path && 'bg-accent'\n )}\n >\n <span className=\"flex-1 truncate\">{getRootDisplayName(root)}</span>\n {root.isWorkspace && (\n <span className=\"text-xs text-primary\">WS</span>\n )}\n {root.isGitRoot && (\n <span className=\"text-xs text-success\">GIT</span>\n )}\n </DropdownMenuItem>\n ))}\n {rootDirectories.length === 0 && !isLoadingRoots && (\n <div className=\"px-2 py-4 text-sm text-muted-foreground text-center\">\n {formatMessage({ id: 'explorer.toolbar.noRoots' })}\n </div>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n\n {/* Search input */}\n <div className=\"flex-1 max-w-sm relative\">\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground\" />\n <Input\n placeholder={formatMessage({ id: 'explorer.toolbar.searchPlaceholder' })}\n value={searchQuery}\n onChange={(e) => onSearchChange(e.target.value)}\n className=\"pl-9 pr-9 h-8\"\n />\n {searchQuery && (\n <button\n onClick={onSearchClear}\n className=\"absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground\"\n aria-label={formatMessage({ id: 'common.actions.clear' })}\n >\n <X className=\"h-4 w-4\" />\n </button>\n )}\n </div>\n\n {/* Refresh button */}\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={onRefresh}\n title={formatMessage({ id: 'common.actions.refresh' })}\n className=\"h-8 w-8 p-0\"\n >\n <RefreshCw className=\"h-4 w-4\" />\n </Button>\n\n {/* View mode dropdown */}\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"outline\"\n size=\"sm\"\n title={formatMessage({ id: 'explorer.toolbar.viewMode' })}\n className=\"h-8 w-8 p-0\"\n >\n {viewMode === 'tree' ? (\n <ChevronRight className=\"h-4 w-4\" />\n ) : viewMode === 'list' ? (\n <List className=\"h-4 w-4\" />\n ) : (\n <Grid className=\"h-4 w-4\" />\n )}\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuLabel>\n {formatMessage({ id: 'explorer.toolbar.viewMode' })}\n </DropdownMenuLabel>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n onClick={() => handleViewModeChange('tree')}\n className={cn('cursor-pointer', viewMode === 'tree' && 'bg-accent')}\n >\n <ChevronRight className=\"h-4 w-4 mr-2\" />\n {formatMessage({ id: 'explorer.viewMode.tree' })}\n </DropdownMenuItem>\n <DropdownMenuItem\n onClick={() => handleViewModeChange('list')}\n className={cn('cursor-pointer', viewMode === 'list' && 'bg-accent')}\n >\n <List className=\"h-4 w-4 mr-2\" />\n {formatMessage({ id: 'explorer.viewMode.list' })}\n </DropdownMenuItem>\n <DropdownMenuItem\n onClick={() => handleViewModeChange('compact')}\n className={cn('cursor-pointer', viewMode === 'compact' && 'bg-accent')}\n >\n <Grid className=\"h-4 w-4 mr-2\" />\n {formatMessage({ id: 'explorer.viewMode.compact' })}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n\n {/* Sort order dropdown */}\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"outline\"\n size=\"sm\"\n title={formatMessage({ id: 'explorer.toolbar.sortBy' })}\n className=\"h-8\"\n >\n {formatMessage({ id: `explorer.sortOrder.${sortOrder}` })}\n <ChevronDown className=\"h-4 w-4 ml-1\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuLabel>\n {formatMessage({ id: 'explorer.toolbar.sortBy' })}\n </DropdownMenuLabel>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n onClick={() => handleSortOrderChange('name')}\n className={cn('cursor-pointer', sortOrder === 'name' && 'bg-accent')}\n >\n {formatMessage({ id: 'explorer.sortOrder.name' })}\n </DropdownMenuItem>\n <DropdownMenuItem\n onClick={() => handleSortOrderChange('size')}\n className={cn('cursor-pointer', sortOrder === 'size' && 'bg-accent')}\n >\n {formatMessage({ id: 'explorer.sortOrder.size' })}\n </DropdownMenuItem>\n <DropdownMenuItem\n onClick={() => handleSortOrderChange('modified')}\n className={cn('cursor-pointer', sortOrder === 'modified' && 'bg-accent')}\n >\n {formatMessage({ id: 'explorer.sortOrder.modified' })}\n </DropdownMenuItem>\n <DropdownMenuItem\n onClick={() => handleSortOrderChange('type')}\n className={cn('cursor-pointer', sortOrder === 'type' && 'bg-accent')}\n >\n {formatMessage({ id: 'explorer.sortOrder.type' })}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n\n {/* More options dropdown */}\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"outline\"\n size=\"sm\"\n title={formatMessage({ id: 'explorer.toolbar.moreOptions' })}\n className=\"h-8 w-8 p-0\"\n >\n <ChevronDownIcon className=\"h-4 w-4\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuLabel>\n {formatMessage({ id: 'explorer.toolbar.options' })}\n </DropdownMenuLabel>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n onClick={onToggleShowHidden}\n className={cn('cursor-pointer justify-between', showHiddenFiles && 'bg-accent')}\n >\n <span>{formatMessage({ id: 'explorer.toolbar.showHidden' })}</span>\n {showHiddenFiles && <span className=\"text-primary\">✓</span>}\n </DropdownMenuItem>\n {onExpandAll && (\n <DropdownMenuItem\n onClick={onExpandAll}\n className=\"cursor-pointer\"\n >\n {formatMessage({ id: 'explorer.toolbar.expandAll' })}\n </DropdownMenuItem>\n )}\n {onCollapseAll && (\n <DropdownMenuItem\n onClick={onCollapseAll}\n className=\"cursor-pointer\"\n >\n {formatMessage({ id: 'explorer.toolbar.collapseAll' })}\n </DropdownMenuItem>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n );\n}\n\nexport default ExplorerToolbar;\n","// ========================================\n// ExplorerPage Component\n// ========================================\n// File Explorer page with tree view and file preview\n\nimport * as React from 'react';\nimport { useIntl } from 'react-intl';\nimport { useFileExplorer, useFileContent } from '@/hooks/useFileExplorer';\nimport { TreeView } from '@/components/shared/TreeView';\nimport { FilePreview } from '@/components/shared/FilePreview';\nimport { ExplorerToolbar } from '@/components/shared/ExplorerToolbar';\nimport { AlertCircle, Loader2 } from 'lucide-react';\nimport { cn } from '@/lib/utils';\nimport type { FileSystemNode } from '@/types/file-explorer';\n\nconst DEFAULT_TREE_WIDTH = 300;\nconst MIN_TREE_WIDTH = 200;\nconst MAX_TREE_WIDTH = 600;\n\n/**\n * ExplorerPage component - File Explorer with split pane layout\n */\nexport function ExplorerPage() {\n const { formatMessage } = useIntl();\n\n // Root path state\n const [rootPath, setRootPath] = React.useState('/');\n\n // Tree width state for resizable split pane\n const [treeWidth, setTreeWidth] = React.useState(DEFAULT_TREE_WIDTH);\n const [isResizing, setIsResizing] = React.useState(false);\n const treePanelRef = React.useRef<HTMLDivElement>(null);\n\n // File explorer hook\n const {\n state,\n rootNodes,\n isLoading,\n isFetching,\n error,\n refetch,\n setSelectedFile,\n toggleExpanded,\n expandAll,\n collapseAll,\n setViewMode,\n setSortOrder,\n toggleShowHidden,\n setFilter,\n rootDirectories,\n isLoadingRoots,\n } = useFileExplorer({\n rootPath,\n maxDepth: 5,\n enabled: true,\n });\n\n // File content hook\n const { content: fileContent, isLoading: isContentLoading, error: contentError } = useFileContent(\n state.selectedFile,\n { enabled: !!state.selectedFile }\n );\n\n // Handle node click\n const handleNodeClick = (node: FileSystemNode) => {\n if (node.type === 'file') {\n setSelectedFile(node.path);\n }\n };\n\n // Handle root directory change\n const handleRootChange = (path: string) => {\n setRootPath(path);\n setSelectedFile(null);\n };\n\n // Handle resize start\n const handleResizeStart = (e: React.MouseEvent) => {\n e.preventDefault();\n setIsResizing(true);\n document.addEventListener('mousemove', handleResize);\n document.addEventListener('mouseup', handleResizeEnd);\n };\n\n // Handle resize move\n const handleResize = (e: MouseEvent) => {\n if (!treePanelRef.current) return;\n const newWidth = e.clientX;\n if (newWidth >= MIN_TREE_WIDTH && newWidth <= MAX_TREE_WIDTH) {\n setTreeWidth(newWidth);\n }\n };\n\n // Handle resize end\n const handleResizeEnd = () => {\n setIsResizing(false);\n document.removeEventListener('mousemove', handleResize);\n document.removeEventListener('mouseup', handleResizeEnd);\n };\n\n return (\n <div className=\"flex flex-col h-full\">\n {/* Page header */}\n <div className=\"px-6 py-4 border-b border-border\">\n <h1 className=\"text-2xl font-semibold text-foreground\">\n {formatMessage({ id: 'explorer.title' })}\n </h1>\n <p className=\"text-sm text-muted-foreground mt-1\">\n {formatMessage({ id: 'explorer.description' })}\n </p>\n </div>\n\n {/* Error alert */}\n {error && (\n <div className=\"mx-6 mt-4 flex items-center gap-2 p-4 rounded-lg bg-destructive/10 border border-destructive/30 text-destructive\">\n <AlertCircle className=\"h-5 w-5 flex-shrink-0\" />\n <div className=\"flex-1\">\n <p className=\"text-sm font-medium\">\n {formatMessage({ id: 'explorer.errors.loadFailed' })}\n </p>\n <p className=\"text-xs mt-0.5\">{error.message}</p>\n </div>\n </div>\n )}\n\n {/* Toolbar */}\n <ExplorerToolbar\n searchQuery={state.filter}\n onSearchChange={setFilter}\n onSearchClear={() => setFilter('')}\n onRefresh={refetch}\n rootDirectories={rootDirectories || []}\n selectedRoot={rootPath}\n onRootChange={handleRootChange}\n isLoadingRoots={isLoadingRoots}\n viewMode={state.viewMode}\n onViewModeChange={setViewMode}\n sortOrder={state.sortOrder}\n onSortOrderChange={setSortOrder}\n showHiddenFiles={state.showHiddenFiles}\n onToggleShowHidden={toggleShowHidden}\n onExpandAll={expandAll}\n onCollapseAll={collapseAll}\n />\n\n {/* Main content - Split pane */}\n <div className=\"flex-1 min-h-0 flex overflow-hidden\">\n {/* Tree view panel */}\n <div\n ref={treePanelRef}\n className=\"h-full flex flex-col bg-background border-r border-border\"\n style={{ width: `${treeWidth}px`, minWidth: `${MIN_TREE_WIDTH}px`, maxWidth: `${MAX_TREE_WIDTH}px` }}\n >\n {/* Loading indicator */}\n {isLoading && (\n <div className=\"flex items-center justify-center py-8\">\n <Loader2 className=\"h-6 w-6 animate-spin text-muted-foreground\" />\n <span className=\"ml-2 text-sm text-muted-foreground\">\n {formatMessage({ id: 'explorer.tree.loading' })}\n </span>\n </div>\n )}\n\n {/* Tree view */}\n <div className={cn('flex-1 overflow-auto custom-scrollbar', isLoading && 'opacity-50')}>\n <TreeView\n nodes={rootNodes}\n expandedPaths={state.expandedPaths}\n selectedPath={state.selectedFile}\n onNodeClick={handleNodeClick}\n onToggle={toggleExpanded}\n showIcons\n showSizes={false}\n />\n </div>\n\n {/* Tree footer */}\n <div className=\"px-4 py-2 border-t border-border text-xs text-muted-foreground flex items-center justify-between\">\n <span>\n {formatMessage(\n { id: 'explorer.tree.stats' },\n {\n files: rootNodes.length,\n loading: isFetching\n }\n )}\n </span>\n {rootPath !== '/' && (\n <span className=\"truncate ml-2\" title={rootPath}>\n {rootPath}\n </span>\n )}\n </div>\n </div>\n\n {/* Resizable handle */}\n <div\n className={cn(\n 'w-1 bg-border cursor-col-resize hover:bg-primary/50 transition-colors flex-shrink-0',\n isResizing && 'bg-primary'\n )}\n onMouseDown={handleResizeStart}\n />\n\n {/* File preview panel */}\n <div className=\"flex-1 min-w-0 h-full flex flex-col bg-background\">\n <FilePreview\n fileContent={fileContent}\n isLoading={isContentLoading}\n error={contentError?.message}\n showLineNumbers\n maxSize={1024 * 1024} // 1MB\n />\n </div>\n </div>\n </div>\n );\n}\n\nexport default ExplorerPage;\n"],"names":["getRootDisplayName","root","parts","ExplorerToolbar","searchQuery","onSearchChange","onSearchClear","onRefresh","rootDirectories","selectedRoot","onRootChange","isLoadingRoots","viewMode","onViewModeChange","sortOrder","onSortOrderChange","showHiddenFiles","onToggleShowHidden","onExpandAll","onCollapseAll","className","formatMessage","useIntl","selectedRootDir","handleSortOrderChange","order","handleViewModeChange","mode","cn","jsxs","DropdownMenu","jsx","DropdownMenuTrigger","Button","ChevronDown","DropdownMenuContent","DropdownMenuLabel","DropdownMenuSeparator","DropdownMenuItem","Search","Input","e","X","RefreshCw","ChevronRight","List","Grid","ChevronDownIcon","DEFAULT_TREE_WIDTH","MIN_TREE_WIDTH","MAX_TREE_WIDTH","ExplorerPage","rootPath","setRootPath","React.useState","treeWidth","setTreeWidth","isResizing","setIsResizing","treePanelRef","React.useRef","state","rootNodes","isLoading","isFetching","error","refetch","setSelectedFile","toggleExpanded","expandAll","collapseAll","setViewMode","setSortOrder","toggleShowHidden","setFilter","useFileExplorer","fileContent","isContentLoading","contentError","useFileContent","handleNodeClick","node","handleRootChange","path","handleResizeStart","handleResize","handleResizeEnd","newWidth","AlertCircle","Loader2","TreeView","FilePreview"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ExplorerPage-DYYpCvtB.js","sources":["../../src/components/shared/ExplorerToolbar.tsx","../../src/pages/ExplorerPage.tsx"],"sourcesContent":["// ========================================\n// ExplorerToolbar Component\n// ========================================\n// Toolbar component for File Explorer with search and controls\n\nimport { Search, X, ChevronDown, RefreshCw, List, Grid, ChevronRight, ChevronDown as ChevronDownIcon } from 'lucide-react';\nimport { useIntl } from 'react-intl';\nimport { cn } from '@/lib/utils';\nimport { Button } from '@/components/ui/Button';\nimport { Input } from '@/components/ui/Input';\nimport {\n DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuLabel,\n} from '@/components/ui/Dropdown';\nimport type { RootDirectory } from '@/lib/api';\nimport type { ExplorerViewMode, ExplorerSortOrder } from '@/types/file-explorer';\n\nexport interface ExplorerToolbarProps {\n /** Current search query */\n searchQuery: string;\n /** Callback when search query changes */\n onSearchChange: (query: string) => void;\n /** Callback when search is cleared */\n onSearchClear: () => void;\n /** Callback when refresh is requested */\n onRefresh: () => void;\n /** Available root directories */\n rootDirectories: RootDirectory[];\n /** Currently selected root directory */\n selectedRoot: string;\n /** Callback when root directory changes */\n onRootChange: (path: string) => void;\n /** Loading state for root directories */\n isLoadingRoots?: boolean;\n /** Current view mode */\n viewMode: ExplorerViewMode;\n /** Callback when view mode changes */\n onViewModeChange: (mode: ExplorerViewMode) => void;\n /** Current sort order */\n sortOrder: ExplorerSortOrder;\n /** Callback when sort order changes */\n onSortOrderChange: (order: ExplorerSortOrder) => void;\n /** Whether to show hidden files */\n showHiddenFiles: boolean;\n /** Callback when show hidden files toggles */\n onToggleShowHidden: () => void;\n /** Callback to expand all directories */\n onExpandAll?: () => void;\n /** Callback to collapse all directories */\n onCollapseAll?: () => void;\n /** Custom class name */\n className?: string;\n}\n\n/**\n * Get root directory display name\n */\nfunction getRootDisplayName(root: RootDirectory): string {\n if (root.name) return root.name;\n const parts = root.path.split(/[/\\\\]/);\n return parts[parts.length - 1] || root.path;\n}\n\n/**\n * ExplorerToolbar component\n *\n * @example\n * ```tsx\n * <ExplorerToolbar\n * searchQuery={filter}\n * onSearchChange={setFilter}\n * onSearchClear={() => setFilter('')}\n * onRefresh={refetch}\n * rootDirectories={rootDirectories}\n * selectedRoot={rootPath}\n * onRootChange={(path) => setRootPath(path)}\n * viewMode={viewMode}\n * onViewModeChange={setViewMode}\n * sortOrder={sortOrder}\n * onSortOrderChange={setSortOrder}\n * showHiddenFiles={showHiddenFiles}\n * onToggleShowHidden={toggleShowHidden}\n * />\n * ```\n */\nexport function ExplorerToolbar({\n searchQuery,\n onSearchChange,\n onSearchClear,\n onRefresh,\n rootDirectories,\n selectedRoot,\n onRootChange,\n isLoadingRoots = false,\n viewMode,\n onViewModeChange,\n sortOrder,\n onSortOrderChange,\n showHiddenFiles,\n onToggleShowHidden,\n onExpandAll,\n onCollapseAll,\n className,\n}: ExplorerToolbarProps) {\n const { formatMessage } = useIntl();\n\n const selectedRootDir = rootDirectories.find((r) => r.path === selectedRoot);\n\n // Handle sort order change\n const handleSortOrderChange = (order: ExplorerSortOrder) => {\n onSortOrderChange(order);\n };\n\n // Handle view mode change\n const handleViewModeChange = (mode: ExplorerViewMode) => {\n onViewModeChange(mode);\n };\n\n return (\n <div className={cn('flex items-center gap-2 px-4 py-2 border-b border-border bg-muted/30', className)}>\n {/* Root directory selector */}\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"outline\" size=\"sm\" className=\"gap-2 max-w-[200px]\">\n <span className=\"truncate\">\n {selectedRootDir\n ? getRootDisplayName(selectedRootDir)\n : formatMessage({ id: 'explorer.toolbar.selectRoot' })\n }\n </span>\n <ChevronDown className=\"h-4 w-4 flex-shrink-0\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"w-56\">\n <DropdownMenuLabel>\n {formatMessage({ id: 'explorer.toolbar.rootDirectory' })}\n </DropdownMenuLabel>\n <DropdownMenuSeparator />\n {rootDirectories.map((root) => (\n <DropdownMenuItem\n key={root.path}\n onClick={() => onRootChange(root.path)}\n className={cn(\n 'flex items-center gap-2 cursor-pointer',\n selectedRoot === root.path && 'bg-accent'\n )}\n >\n <span className=\"flex-1 truncate\">{getRootDisplayName(root)}</span>\n {root.isWorkspace && (\n <span className=\"text-xs text-primary\">WS</span>\n )}\n {root.isGitRoot && (\n <span className=\"text-xs text-success\">GIT</span>\n )}\n </DropdownMenuItem>\n ))}\n {rootDirectories.length === 0 && !isLoadingRoots && (\n <div className=\"px-2 py-4 text-sm text-muted-foreground text-center\">\n {formatMessage({ id: 'explorer.toolbar.noRoots' })}\n </div>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n\n {/* Search input */}\n <div className=\"flex-1 max-w-sm relative\">\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground\" />\n <Input\n placeholder={formatMessage({ id: 'explorer.toolbar.searchPlaceholder' })}\n value={searchQuery}\n onChange={(e) => onSearchChange(e.target.value)}\n className=\"pl-9 pr-9 h-8\"\n />\n {searchQuery && (\n <button\n onClick={onSearchClear}\n className=\"absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground\"\n aria-label={formatMessage({ id: 'common.actions.clear' })}\n >\n <X className=\"h-4 w-4\" />\n </button>\n )}\n </div>\n\n {/* Refresh button */}\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={onRefresh}\n title={formatMessage({ id: 'common.actions.refresh' })}\n className=\"h-8 w-8 p-0\"\n >\n <RefreshCw className=\"h-4 w-4\" />\n </Button>\n\n {/* View mode dropdown */}\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"outline\"\n size=\"sm\"\n title={formatMessage({ id: 'explorer.toolbar.viewMode' })}\n className=\"h-8 w-8 p-0\"\n >\n {viewMode === 'tree' ? (\n <ChevronRight className=\"h-4 w-4\" />\n ) : viewMode === 'list' ? (\n <List className=\"h-4 w-4\" />\n ) : (\n <Grid className=\"h-4 w-4\" />\n )}\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuLabel>\n {formatMessage({ id: 'explorer.toolbar.viewMode' })}\n </DropdownMenuLabel>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n onClick={() => handleViewModeChange('tree')}\n className={cn('cursor-pointer', viewMode === 'tree' && 'bg-accent')}\n >\n <ChevronRight className=\"h-4 w-4 mr-2\" />\n {formatMessage({ id: 'explorer.viewMode.tree' })}\n </DropdownMenuItem>\n <DropdownMenuItem\n onClick={() => handleViewModeChange('list')}\n className={cn('cursor-pointer', viewMode === 'list' && 'bg-accent')}\n >\n <List className=\"h-4 w-4 mr-2\" />\n {formatMessage({ id: 'explorer.viewMode.list' })}\n </DropdownMenuItem>\n <DropdownMenuItem\n onClick={() => handleViewModeChange('compact')}\n className={cn('cursor-pointer', viewMode === 'compact' && 'bg-accent')}\n >\n <Grid className=\"h-4 w-4 mr-2\" />\n {formatMessage({ id: 'explorer.viewMode.compact' })}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n\n {/* Sort order dropdown */}\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"outline\"\n size=\"sm\"\n title={formatMessage({ id: 'explorer.toolbar.sortBy' })}\n className=\"h-8\"\n >\n {formatMessage({ id: `explorer.sortOrder.${sortOrder}` })}\n <ChevronDown className=\"h-4 w-4 ml-1\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuLabel>\n {formatMessage({ id: 'explorer.toolbar.sortBy' })}\n </DropdownMenuLabel>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n onClick={() => handleSortOrderChange('name')}\n className={cn('cursor-pointer', sortOrder === 'name' && 'bg-accent')}\n >\n {formatMessage({ id: 'explorer.sortOrder.name' })}\n </DropdownMenuItem>\n <DropdownMenuItem\n onClick={() => handleSortOrderChange('size')}\n className={cn('cursor-pointer', sortOrder === 'size' && 'bg-accent')}\n >\n {formatMessage({ id: 'explorer.sortOrder.size' })}\n </DropdownMenuItem>\n <DropdownMenuItem\n onClick={() => handleSortOrderChange('modified')}\n className={cn('cursor-pointer', sortOrder === 'modified' && 'bg-accent')}\n >\n {formatMessage({ id: 'explorer.sortOrder.modified' })}\n </DropdownMenuItem>\n <DropdownMenuItem\n onClick={() => handleSortOrderChange('type')}\n className={cn('cursor-pointer', sortOrder === 'type' && 'bg-accent')}\n >\n {formatMessage({ id: 'explorer.sortOrder.type' })}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n\n {/* More options dropdown */}\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"outline\"\n size=\"sm\"\n title={formatMessage({ id: 'explorer.toolbar.moreOptions' })}\n className=\"h-8 w-8 p-0\"\n >\n <ChevronDownIcon className=\"h-4 w-4\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuLabel>\n {formatMessage({ id: 'explorer.toolbar.options' })}\n </DropdownMenuLabel>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n onClick={onToggleShowHidden}\n className={cn('cursor-pointer justify-between', showHiddenFiles && 'bg-accent')}\n >\n <span>{formatMessage({ id: 'explorer.toolbar.showHidden' })}</span>\n {showHiddenFiles && <span className=\"text-primary\">✓</span>}\n </DropdownMenuItem>\n {onExpandAll && (\n <DropdownMenuItem\n onClick={onExpandAll}\n className=\"cursor-pointer\"\n >\n {formatMessage({ id: 'explorer.toolbar.expandAll' })}\n </DropdownMenuItem>\n )}\n {onCollapseAll && (\n <DropdownMenuItem\n onClick={onCollapseAll}\n className=\"cursor-pointer\"\n >\n {formatMessage({ id: 'explorer.toolbar.collapseAll' })}\n </DropdownMenuItem>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n );\n}\n\nexport default ExplorerToolbar;\n","// ========================================\n// ExplorerPage Component\n// ========================================\n// File Explorer page with tree view and file preview\n\nimport * as React from 'react';\nimport { useIntl } from 'react-intl';\nimport { useFileExplorer, useFileContent } from '@/hooks/useFileExplorer';\nimport { TreeView } from '@/components/shared/TreeView';\nimport { FilePreview } from '@/components/shared/FilePreview';\nimport { ExplorerToolbar } from '@/components/shared/ExplorerToolbar';\nimport { AlertCircle, Loader2 } from 'lucide-react';\nimport { cn } from '@/lib/utils';\nimport type { FileSystemNode } from '@/types/file-explorer';\n\nconst DEFAULT_TREE_WIDTH = 300;\nconst MIN_TREE_WIDTH = 200;\nconst MAX_TREE_WIDTH = 600;\n\n/**\n * ExplorerPage component - File Explorer with split pane layout\n */\nexport function ExplorerPage() {\n const { formatMessage } = useIntl();\n\n // Root path state\n const [rootPath, setRootPath] = React.useState('/');\n\n // Tree width state for resizable split pane\n const [treeWidth, setTreeWidth] = React.useState(DEFAULT_TREE_WIDTH);\n const [isResizing, setIsResizing] = React.useState(false);\n const treePanelRef = React.useRef<HTMLDivElement>(null);\n\n // File explorer hook\n const {\n state,\n rootNodes,\n isLoading,\n isFetching,\n error,\n refetch,\n setSelectedFile,\n toggleExpanded,\n expandAll,\n collapseAll,\n setViewMode,\n setSortOrder,\n toggleShowHidden,\n setFilter,\n rootDirectories,\n isLoadingRoots,\n } = useFileExplorer({\n rootPath,\n maxDepth: 5,\n enabled: true,\n });\n\n // File content hook\n const { content: fileContent, isLoading: isContentLoading, error: contentError } = useFileContent(\n state.selectedFile,\n { enabled: !!state.selectedFile }\n );\n\n // Handle node click\n const handleNodeClick = (node: FileSystemNode) => {\n if (node.type === 'file') {\n setSelectedFile(node.path);\n }\n };\n\n // Handle root directory change\n const handleRootChange = (path: string) => {\n setRootPath(path);\n setSelectedFile(null);\n };\n\n // Handle resize start\n const handleResizeStart = (e: React.MouseEvent) => {\n e.preventDefault();\n setIsResizing(true);\n document.addEventListener('mousemove', handleResize);\n document.addEventListener('mouseup', handleResizeEnd);\n };\n\n // Handle resize move\n const handleResize = (e: MouseEvent) => {\n if (!treePanelRef.current) return;\n const newWidth = e.clientX;\n if (newWidth >= MIN_TREE_WIDTH && newWidth <= MAX_TREE_WIDTH) {\n setTreeWidth(newWidth);\n }\n };\n\n // Handle resize end\n const handleResizeEnd = () => {\n setIsResizing(false);\n document.removeEventListener('mousemove', handleResize);\n document.removeEventListener('mouseup', handleResizeEnd);\n };\n\n return (\n <div className=\"flex flex-col h-full\">\n {/* Page header */}\n <div className=\"px-6 py-4 border-b border-border\">\n <h1 className=\"text-2xl font-semibold text-foreground\">\n {formatMessage({ id: 'explorer.title' })}\n </h1>\n <p className=\"text-sm text-muted-foreground mt-1\">\n {formatMessage({ id: 'explorer.description' })}\n </p>\n </div>\n\n {/* Error alert */}\n {error && (\n <div className=\"mx-6 mt-4 flex items-center gap-2 p-4 rounded-lg bg-destructive/10 border border-destructive/30 text-destructive\">\n <AlertCircle className=\"h-5 w-5 flex-shrink-0\" />\n <div className=\"flex-1\">\n <p className=\"text-sm font-medium\">\n {formatMessage({ id: 'explorer.errors.loadFailed' })}\n </p>\n <p className=\"text-xs mt-0.5\">{error.message}</p>\n </div>\n </div>\n )}\n\n {/* Toolbar */}\n <ExplorerToolbar\n searchQuery={state.filter}\n onSearchChange={setFilter}\n onSearchClear={() => setFilter('')}\n onRefresh={refetch}\n rootDirectories={rootDirectories || []}\n selectedRoot={rootPath}\n onRootChange={handleRootChange}\n isLoadingRoots={isLoadingRoots}\n viewMode={state.viewMode}\n onViewModeChange={setViewMode}\n sortOrder={state.sortOrder}\n onSortOrderChange={setSortOrder}\n showHiddenFiles={state.showHiddenFiles}\n onToggleShowHidden={toggleShowHidden}\n onExpandAll={expandAll}\n onCollapseAll={collapseAll}\n />\n\n {/* Main content - Split pane */}\n <div className=\"flex-1 min-h-0 flex overflow-hidden\">\n {/* Tree view panel */}\n <div\n ref={treePanelRef}\n className=\"h-full flex flex-col bg-background border-r border-border\"\n style={{ width: `${treeWidth}px`, minWidth: `${MIN_TREE_WIDTH}px`, maxWidth: `${MAX_TREE_WIDTH}px` }}\n >\n {/* Loading indicator */}\n {isLoading && (\n <div className=\"flex items-center justify-center py-8\">\n <Loader2 className=\"h-6 w-6 animate-spin text-muted-foreground\" />\n <span className=\"ml-2 text-sm text-muted-foreground\">\n {formatMessage({ id: 'explorer.tree.loading' })}\n </span>\n </div>\n )}\n\n {/* Tree view */}\n <div className={cn('flex-1 overflow-auto custom-scrollbar', isLoading && 'opacity-50')}>\n <TreeView\n nodes={rootNodes}\n expandedPaths={state.expandedPaths}\n selectedPath={state.selectedFile}\n onNodeClick={handleNodeClick}\n onToggle={toggleExpanded}\n showIcons\n showSizes={false}\n />\n </div>\n\n {/* Tree footer */}\n <div className=\"px-4 py-2 border-t border-border text-xs text-muted-foreground flex items-center justify-between\">\n <span>\n {formatMessage(\n { id: 'explorer.tree.stats' },\n {\n files: rootNodes.length,\n loading: isFetching\n }\n )}\n </span>\n {rootPath !== '/' && (\n <span className=\"truncate ml-2\" title={rootPath}>\n {rootPath}\n </span>\n )}\n </div>\n </div>\n\n {/* Resizable handle */}\n <div\n className={cn(\n 'w-1 bg-border cursor-col-resize hover:bg-primary/50 transition-colors flex-shrink-0',\n isResizing && 'bg-primary'\n )}\n onMouseDown={handleResizeStart}\n />\n\n {/* File preview panel */}\n <div className=\"flex-1 min-w-0 h-full flex flex-col bg-background\">\n <FilePreview\n fileContent={fileContent}\n isLoading={isContentLoading}\n error={contentError?.message}\n showLineNumbers\n maxSize={1024 * 1024} // 1MB\n />\n </div>\n </div>\n </div>\n );\n}\n\nexport default ExplorerPage;\n"],"names":["getRootDisplayName","root","parts","ExplorerToolbar","searchQuery","onSearchChange","onSearchClear","onRefresh","rootDirectories","selectedRoot","onRootChange","isLoadingRoots","viewMode","onViewModeChange","sortOrder","onSortOrderChange","showHiddenFiles","onToggleShowHidden","onExpandAll","onCollapseAll","className","formatMessage","useIntl","selectedRootDir","handleSortOrderChange","order","handleViewModeChange","mode","cn","jsxs","DropdownMenu","jsx","DropdownMenuTrigger","Button","ChevronDown","DropdownMenuContent","DropdownMenuLabel","DropdownMenuSeparator","DropdownMenuItem","Search","Input","e","X","RefreshCw","ChevronRight","List","Grid","ChevronDownIcon","DEFAULT_TREE_WIDTH","MIN_TREE_WIDTH","MAX_TREE_WIDTH","ExplorerPage","rootPath","setRootPath","React.useState","treeWidth","setTreeWidth","isResizing","setIsResizing","treePanelRef","React.useRef","state","rootNodes","isLoading","isFetching","error","refetch","setSelectedFile","toggleExpanded","expandAll","collapseAll","setViewMode","setSortOrder","toggleShowHidden","setFilter","useFileExplorer","fileContent","isContentLoading","contentError","useFileContent","handleNodeClick","node","handleRootChange","path","handleResizeStart","handleResize","handleResizeEnd","newWidth","AlertCircle","Loader2","TreeView","FilePreview"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{H as A,n as I,u as $,p as D,r as c,j as e,e as o,J as x,K as w,W as u,B as f,C as h,a as g,F as p,M as E,N as W,l as H}from"./index-
|
|
2
|
-
//# sourceMappingURL=FixSessionPage-
|
|
1
|
+
import{H as A,n as I,u as $,p as D,r as c,j as e,e as o,J as x,K as w,W as u,B as f,C as h,a as g,F as p,M as E,N as W,l as H}from"./index-DP_mTJI8.js";function K(){const{sessionId:j}=A(),C=I(),{formatMessage:t}=$(),{filteredSessions:N,isLoading:_,error:b,refetch:k}=D({filter:{location:"all"}}),[l,F]=c.useState("all"),i=c.useMemo(()=>N.find(s=>s.session_id===j),[N,j]),n=c.useMemo(()=>i!=null&&i.tasks?i.tasks:[],[i==null?void 0:i.tasks]),d=c.useMemo(()=>{const s=n.length,r=n.filter(a=>a.status==="completed"&&a.result==="fixed").length,m=n.filter(a=>a.status==="completed"&&a.result==="failed").length,L=n.filter(a=>a.status==="pending").length,P=n.filter(a=>a.status==="in_progress").length,S=r+m,z=s>0?Math.round(S/s*100):0;return{total:s,fixed:r,failed:m,pending:L,inProgress:P,completed:S,percentComplete:z}},[n]),v=c.useMemo(()=>l==="all"?n:l==="fixed"?n.filter(s=>s.status==="completed"&&s.result==="fixed"):l==="failed"?n.filter(s=>s.status==="completed"&&s.result==="failed"):n.filter(s=>s.status===l),[n,l]),B=s=>{if(s.status==="completed"){if(s.result==="fixed")return{variant:"success",label:t({id:"fixSession.status.fixed"}),icon:E};if(s.result==="failed")return{variant:"destructive",label:t({id:"fixSession.status.failed"}),icon:w}}return s.status==="in_progress"?{variant:"warning",label:t({id:"fixSession.status.inProgress"}),icon:W}:{variant:"secondary",label:t({id:"fixSession.status.pending"}),icon:H}},y=()=>{C("/sessions")},M=s=>{F(s)};return _?e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsxs(o,{variant:"ghost",size:"sm",disabled:!0,children:[e.jsx(x,{className:"h-4 w-4 mr-2"}),t({id:"common.actions.back"})]}),e.jsx("div",{className:"h-8 w-48 rounded bg-muted animate-pulse"})]}),e.jsx("div",{className:"grid grid-cols-4 gap-4",children:Array.from({length:4}).map((s,r)=>e.jsx("div",{className:"h-24 rounded-lg bg-muted animate-pulse"},r))})]}):b?e.jsxs("div",{className:"flex items-center gap-2 p-4 rounded-lg bg-destructive/10 border border-destructive/30 text-destructive",children:[e.jsx(w,{className:"h-5 w-5 flex-shrink-0"}),e.jsxs("div",{className:"flex-1",children:[e.jsx("p",{className:"text-sm font-medium",children:t({id:"common.errors.loadFailed"})}),e.jsx("p",{className:"text-xs mt-0.5",children:b.message})]}),e.jsx(o,{variant:"outline",size:"sm",onClick:()=>k(),children:t({id:"common.actions.retry"})})]}):i?e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsxs(o,{variant:"ghost",size:"sm",onClick:y,children:[e.jsx(x,{className:"h-4 w-4 mr-2"}),t({id:"common.actions.back"})]}),e.jsxs("div",{className:"flex-1",children:[e.jsx("h1",{className:"text-2xl font-semibold text-foreground",children:i.session_id}),i.title&&e.jsx("p",{className:"text-sm text-muted-foreground mt-0.5",children:i.title})]}),e.jsxs(f,{variant:"warning",children:[e.jsx(u,{className:"h-3 w-3 mr-1"}),"Fix"]})]}),e.jsx(h,{children:e.jsxs(g,{className:"p-6",children:[e.jsxs("div",{className:"flex items-center justify-between mb-4",children:[e.jsxs("h3",{className:"text-lg font-semibold flex items-center gap-2",children:[e.jsx(u,{className:"h-5 w-5"}),t({id:"fixSession.progress.title"})]}),e.jsx(f,{variant:"secondary",children:i.phase||t({id:"fixSession.phase.execution"})})]}),e.jsx("div",{className:"mb-2",children:e.jsx("div",{className:"h-2 w-full rounded-full bg-muted overflow-hidden",children:e.jsx("div",{className:"h-full bg-primary transition-all duration-300",style:{width:`${d.percentComplete}%`}})})}),e.jsxs("div",{className:"text-sm text-muted-foreground mb-6",children:[e.jsx("strong",{children:d.completed}),"/",d.total," ",t({id:"common.tasks"})," (",d.percentComplete,"%)"]}),e.jsxs("div",{className:"grid grid-cols-4 gap-4",children:[e.jsxs("div",{className:"text-center p-4 bg-background rounded-lg border",children:[e.jsx("div",{className:"text-2xl font-semibold text-foreground",children:d.total}),e.jsx("div",{className:"text-sm text-muted-foreground",children:t({id:"fixSession.stats.total"})})]}),e.jsxs("div",{className:"text-center p-4 bg-background rounded-lg border border-success/30 bg-success/5",children:[e.jsx("div",{className:"text-2xl font-semibold text-success",children:d.fixed}),e.jsx("div",{className:"text-sm text-muted-foreground",children:t({id:"fixSession.stats.fixed"})})]}),e.jsxs("div",{className:"text-center p-4 bg-background rounded-lg border border-destructive/30 bg-destructive/5",children:[e.jsx("div",{className:"text-2xl font-semibold text-destructive",children:d.failed}),e.jsx("div",{className:"text-sm text-muted-foreground",children:t({id:"fixSession.stats.failed"})})]}),e.jsxs("div",{className:"text-center p-4 bg-background rounded-lg border",children:[e.jsx("div",{className:"text-2xl font-semibold text-foreground",children:d.pending}),e.jsx("div",{className:"text-sm text-muted-foreground",children:t({id:"fixSession.stats.pending"})})]})]})]})}),e.jsx(h,{children:e.jsxs(g,{className:"p-6",children:[e.jsxs("div",{className:"flex items-center justify-between mb-4",children:[e.jsxs("h3",{className:"text-lg font-semibold flex items-center gap-2",children:[e.jsx(p,{className:"h-5 w-5"}),t({id:"fixSession.tasks.title"})]}),e.jsx("div",{className:"flex gap-1",children:[{key:"all",label:t({id:"fixSession.filter.all"})},{key:"pending",label:t({id:"fixSession.filter.pending"})},{key:"in_progress",label:t({id:"fixSession.filter.inProgress"})},{key:"fixed",label:t({id:"fixSession.filter.fixed"})},{key:"failed",label:t({id:"fixSession.filter.failed"})}].map(s=>e.jsx(o,{variant:l===s.key?"default":"outline",size:"sm",onClick:()=>M(s.key),children:s.label},s.key))})]}),v.length===0?e.jsxs("div",{className:"flex flex-col items-center justify-center py-12 text-center",children:[e.jsx(p,{className:"h-12 w-12 text-muted-foreground mb-4"}),e.jsx("h3",{className:"text-lg font-medium text-foreground mb-2",children:t({id:"fixSession.empty.title"})}),e.jsx("p",{className:"text-sm text-muted-foreground",children:t({id:"fixSession.empty.message"})})]}):e.jsx("div",{className:"grid gap-3",children:v.map(s=>{const r=B(s),m=r.icon;return e.jsx(h,{className:`hover:shadow-sm transition-shadow ${s.status==="completed"&&s.result==="failed"?"border-destructive/30 bg-destructive/5":""}`,children:e.jsx(g,{className:"p-4",children:e.jsxs("div",{className:"flex items-start justify-between gap-3",children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-1",children:[e.jsx("span",{className:"inline-flex items-center px-2 py-0.5 rounded text-xs font-mono font-semibold bg-primary/10 text-primary border border-primary/20",children:s.task_id||s.id||"N/A"}),e.jsxs(f,{variant:r.variant,className:"gap-1",children:[e.jsx(m,{className:"h-3 w-3"}),r.label]})]}),e.jsx("h4",{className:"font-medium text-foreground text-sm",children:s.title||t({id:"fixSession.task.untitled"})}),s.finding_title&&e.jsx("p",{className:"text-sm text-muted-foreground mt-1",children:s.finding_title}),s.file&&e.jsxs("div",{className:"flex items-center gap-1 mt-2 text-xs text-muted-foreground",children:[e.jsx(p,{className:"h-3 w-3"}),s.file,s.line&&`:${s.line}`]})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-1 text-xs",children:[s.dimension&&e.jsx("span",{className:"px-2 py-0.5 bg-muted rounded text-muted-foreground",children:s.dimension}),s.attempts&&s.attempts>1&&e.jsx("span",{className:"px-2 py-0.5 bg-muted rounded text-muted-foreground",children:t({id:"fixSession.task.attempts"},{count:s.attempts})}),s.commit_hash&&e.jsx("span",{className:"px-2 py-0.5 bg-primary-light text-primary rounded font-mono",children:s.commit_hash.substring(0,7)})]})]})})},s.task_id||s.id)})})]})}),e.jsxs("div",{className:"flex flex-wrap gap-4 text-sm text-muted-foreground p-4 bg-background rounded-lg border",children:[e.jsxs("div",{children:[e.jsxs("span",{className:"font-medium",children:[t({id:"fixSession.info.created"}),":"]})," ",new Date(i.created_at).toLocaleString()]}),i.updated_at&&e.jsxs("div",{children:[e.jsxs("span",{className:"font-medium",children:[t({id:"fixSession.info.updated"}),":"]})," ",new Date(i.updated_at).toLocaleString()]}),i.description&&e.jsxs("div",{className:"w-full",children:[e.jsxs("span",{className:"font-medium",children:[t({id:"fixSession.info.description"}),":"]})," ",i.description]})]})]}):e.jsxs("div",{className:"flex flex-col items-center justify-center py-16 px-4",children:[e.jsx(u,{className:"h-12 w-12 text-muted-foreground mb-4"}),e.jsx("h3",{className:"text-lg font-medium text-foreground mb-2",children:t({id:"fixSession.notFound.title"})}),e.jsx("p",{className:"text-sm text-muted-foreground mb-4",children:t({id:"fixSession.notFound.message"})}),e.jsxs(o,{onClick:y,children:[e.jsx(x,{className:"h-4 w-4 mr-2"}),t({id:"common.actions.back"})]})]})}export{K as FixSessionPage,K as default};
|
|
2
|
+
//# sourceMappingURL=FixSessionPage-CSmiT5SE.js.map
|