@samanhappy/mcphub 1.0.7 → 1.0.9

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.
Files changed (121) hide show
  1. package/dist/betterAuth.js +10 -0
  2. package/dist/betterAuth.js.map +1 -1
  3. package/dist/cli/commands/keys.js +2 -7
  4. package/dist/cli/commands/keys.js.map +1 -1
  5. package/dist/controllers/activityController.js +9 -1
  6. package/dist/controllers/activityController.js.map +1 -1
  7. package/dist/controllers/bearerKeyController.js +90 -79
  8. package/dist/controllers/bearerKeyController.js.map +1 -1
  9. package/dist/controllers/oauthServerController.js +9 -4
  10. package/dist/controllers/oauthServerController.js.map +1 -1
  11. package/dist/controllers/serverController.js +62 -4
  12. package/dist/controllers/serverController.js.map +1 -1
  13. package/dist/controllers/userController.js +6 -4
  14. package/dist/controllers/userController.js.map +1 -1
  15. package/dist/dao/ActivityDao.js +5 -0
  16. package/dist/dao/ActivityDao.js.map +1 -1
  17. package/dist/dao/BearerKeyDao.js +21 -1
  18. package/dist/dao/BearerKeyDao.js.map +1 -1
  19. package/dist/dao/BearerKeyDaoDbImpl.js +13 -0
  20. package/dist/dao/BearerKeyDaoDbImpl.js.map +1 -1
  21. package/dist/dao/UserDao.js +6 -1
  22. package/dist/dao/UserDao.js.map +1 -1
  23. package/dist/dao/UserDaoDbImpl.js +24 -36
  24. package/dist/dao/UserDaoDbImpl.js.map +1 -1
  25. package/dist/db/entities/Activity.js +5 -0
  26. package/dist/db/entities/Activity.js.map +1 -1
  27. package/dist/db/entities/BearerKey.js +8 -0
  28. package/dist/db/entities/BearerKey.js.map +1 -1
  29. package/dist/db/entities/User.js +4 -0
  30. package/dist/db/entities/User.js.map +1 -1
  31. package/dist/db/repositories/ActivityRepository.js +15 -0
  32. package/dist/db/repositories/ActivityRepository.js.map +1 -1
  33. package/dist/db/repositories/BearerKeyRepository.js +9 -0
  34. package/dist/db/repositories/BearerKeyRepository.js.map +1 -1
  35. package/dist/db/repositories/SystemConfigRepository.js +2 -1
  36. package/dist/db/repositories/SystemConfigRepository.js.map +1 -1
  37. package/dist/db/repositories/UserRepository.js +3 -0
  38. package/dist/db/repositories/UserRepository.js.map +1 -1
  39. package/dist/middlewares/auth.js +2 -2
  40. package/dist/middlewares/auth.js.map +1 -1
  41. package/dist/middlewares/userContext.js +5 -0
  42. package/dist/middlewares/userContext.js.map +1 -1
  43. package/dist/models/User.js +13 -1
  44. package/dist/models/User.js.map +1 -1
  45. package/dist/routes/index.js +7 -7
  46. package/dist/routes/index.js.map +1 -1
  47. package/dist/services/activityLoggingService.js +1 -0
  48. package/dist/services/activityLoggingService.js.map +1 -1
  49. package/dist/services/betterAuthConfig.js +2 -0
  50. package/dist/services/betterAuthConfig.js.map +1 -1
  51. package/dist/services/betterAuthSession.js +44 -6
  52. package/dist/services/betterAuthSession.js.map +1 -1
  53. package/dist/services/mcpService.js +22 -0
  54. package/dist/services/mcpService.js.map +1 -1
  55. package/dist/services/oauthServerService.js +9 -4
  56. package/dist/services/oauthServerService.js.map +1 -1
  57. package/dist/services/requestContextService.js +15 -0
  58. package/dist/services/requestContextService.js.map +1 -1
  59. package/dist/services/smartRoutingService.js +2 -0
  60. package/dist/services/smartRoutingService.js.map +1 -1
  61. package/dist/services/sseService.js +40 -3
  62. package/dist/services/sseService.js.map +1 -1
  63. package/dist/services/userService.js +15 -4
  64. package/dist/services/userService.js.map +1 -1
  65. package/dist/utils/migration.js +5 -0
  66. package/dist/utils/migration.js.map +1 -1
  67. package/frontend/dist/assets/ActivityPage-DrwHdeQ1.js +2 -0
  68. package/frontend/dist/assets/ActivityPage-DrwHdeQ1.js.map +1 -0
  69. package/frontend/dist/assets/{Dashboard-CZBclnD_.js → Dashboard-C6l7But8.js} +2 -2
  70. package/frontend/dist/assets/{Dashboard-CZBclnD_.js.map → Dashboard-C6l7But8.js.map} +1 -1
  71. package/frontend/dist/assets/{EndpointCopy-C7kzq1Rv.js → EndpointCopy-Doi0lGZI.js} +2 -2
  72. package/frontend/dist/assets/{EndpointCopy-C7kzq1Rv.js.map → EndpointCopy-Doi0lGZI.js.map} +1 -1
  73. package/frontend/dist/assets/{GroupsPage-D5J8mmwv.js → GroupsPage-Bx3Yi-md.js} +2 -2
  74. package/frontend/dist/assets/{GroupsPage-D5J8mmwv.js.map → GroupsPage-Bx3Yi-md.js.map} +1 -1
  75. package/frontend/dist/assets/LoginPage-C3p_yHJd.js +2 -0
  76. package/frontend/dist/assets/LoginPage-C3p_yHJd.js.map +1 -0
  77. package/frontend/dist/assets/{LogsPage-VhqcvLlT.js → LogsPage-Z8Iueeij.js} +2 -2
  78. package/frontend/dist/assets/{LogsPage-VhqcvLlT.js.map → LogsPage-Z8Iueeij.js.map} +1 -1
  79. package/frontend/dist/assets/{MarketPage-Cr0ZJ-12.js → MarketPage-BvEPL_eq.js} +2 -2
  80. package/frontend/dist/assets/{MarketPage-Cr0ZJ-12.js.map → MarketPage-BvEPL_eq.js.map} +1 -1
  81. package/frontend/dist/assets/{PromptsPage-BUFhppNh.js → PromptsPage-BYoNsubQ.js} +2 -2
  82. package/frontend/dist/assets/{PromptsPage-BUFhppNh.js.map → PromptsPage-BYoNsubQ.js.map} +1 -1
  83. package/frontend/dist/assets/{ResourcesPage-CLUpqvNX.js → ResourcesPage-BipHAbTQ.js} +2 -2
  84. package/frontend/dist/assets/{ResourcesPage-CLUpqvNX.js.map → ResourcesPage-BipHAbTQ.js.map} +1 -1
  85. package/frontend/dist/assets/ServersPage-Da24Dkfs.js +37 -0
  86. package/frontend/dist/assets/ServersPage-Da24Dkfs.js.map +1 -0
  87. package/frontend/dist/assets/SettingsPage-BiTd0EBn.js +12 -0
  88. package/frontend/dist/assets/SettingsPage-BiTd0EBn.js.map +1 -0
  89. package/frontend/dist/assets/StatusDot-C-kTn-AA.js +2 -0
  90. package/frontend/dist/assets/StatusDot-C-kTn-AA.js.map +1 -0
  91. package/frontend/dist/assets/{ToggleGroup-C6hpbZ4n.js → ToggleGroup-B4fP-TVG.js} +2 -2
  92. package/frontend/dist/assets/{ToggleGroup-C6hpbZ4n.js.map → ToggleGroup-B4fP-TVG.js.map} +1 -1
  93. package/frontend/dist/assets/UsersPage-MDtzW9-F.js +2 -0
  94. package/frontend/dist/assets/UsersPage-MDtzW9-F.js.map +1 -0
  95. package/frontend/dist/assets/index-aFFPxLwH.css +1 -0
  96. package/frontend/dist/assets/index-otG7s0Ro.js +3 -0
  97. package/frontend/dist/assets/index-otG7s0Ro.js.map +1 -0
  98. package/frontend/dist/assets/{resourceService-CLgvzUQW.js → resourceService-b5_G4mIW.js} +2 -2
  99. package/frontend/dist/assets/{resourceService-CLgvzUQW.js.map → resourceService-b5_G4mIW.js.map} +1 -1
  100. package/frontend/dist/assets/{useServerData-4qDtSQW3.js → useServerData-B_sSO_jj.js} +2 -2
  101. package/frontend/dist/assets/{useServerData-4qDtSQW3.js.map → useServerData-B_sSO_jj.js.map} +1 -1
  102. package/frontend/dist/assets/useSettingsData-BE6ZnRFg.js +2 -0
  103. package/frontend/dist/assets/{useSettingsData-CSmSfVuv.js.map → useSettingsData-BE6ZnRFg.js.map} +1 -1
  104. package/frontend/dist/index.html +2 -2
  105. package/package.json +1 -1
  106. package/frontend/dist/assets/ActivityPage-DDIl8rcq.js +0 -2
  107. package/frontend/dist/assets/ActivityPage-DDIl8rcq.js.map +0 -1
  108. package/frontend/dist/assets/LoginPage-BksVRHPq.js +0 -2
  109. package/frontend/dist/assets/LoginPage-BksVRHPq.js.map +0 -1
  110. package/frontend/dist/assets/ServersPage-BmDNiRbb.js +0 -37
  111. package/frontend/dist/assets/ServersPage-BmDNiRbb.js.map +0 -1
  112. package/frontend/dist/assets/SettingsPage-DdMb9-RV.js +0 -12
  113. package/frontend/dist/assets/SettingsPage-DdMb9-RV.js.map +0 -1
  114. package/frontend/dist/assets/StatusDot-DaXaKatw.js +0 -2
  115. package/frontend/dist/assets/StatusDot-DaXaKatw.js.map +0 -1
  116. package/frontend/dist/assets/UsersPage-BtYXxXM3.js +0 -2
  117. package/frontend/dist/assets/UsersPage-BtYXxXM3.js.map +0 -1
  118. package/frontend/dist/assets/index-D0OIBhmN.css +0 -1
  119. package/frontend/dist/assets/index-St_D2SAD.js +0 -3
  120. package/frontend/dist/assets/index-St_D2SAD.js.map +0 -1
  121. package/frontend/dist/assets/useSettingsData-CSmSfVuv.js +0 -2
@@ -1,2 +1,2 @@
1
- import{b as $,R as u,r as S,j as e}from"./framework-vendor-BUhDPOUZ.js";import{u as D}from"./useServerData-4qDtSQW3.js";import{d as L}from"./index-St_D2SAD.js";import{u as T}from"./useSettingsData-CSmSfVuv.js";import{E as h}from"./EndpointCopy-C7kzq1Rv.js";import{S as M}from"./StatusDot-DaXaKatw.js";import{u as P}from"./i18n-vendor-Kbr87Ofu.js";import{R as A,P as U,j as y,k as H}from"./icons-vendor-CKgJB3SC.js";const c=({label:s,value:l,tone:a="default"})=>{const t=a==="ok"?"oklch(0.4 0.13 145)":a==="warn"?"oklch(0.45 0.13 80)":a==="err"?"oklch(0.45 0.18 25)":a==="muted"?"var(--hub-ink-3)":"var(--hub-ink)";return e.jsxs("div",{className:"hub-card",style:{padding:"14px 16px"},children:[e.jsx("div",{className:"text-[12px]",style:{color:"var(--hub-ink-3)"},children:s}),e.jsx("div",{className:"hub-num",style:{fontSize:26,fontWeight:500,letterSpacing:"-0.02em",lineHeight:1.1,marginTop:8,color:t},children:l})]})},w=(s,l)=>l?l==="stdio"?s("server.typeStdio")||"stdio":l==="sse"?s("server.typeSse")||"sse":l==="streamable-http"?s("server.typeStreamableHttp")||"http":l==="openapi"?s("server.typeOpenapi")||"openapi":l:null,I=()=>{var j;const{t:s}=P(),l=$(),{allServers:a,error:t,setError:C,isLoading:p,triggerRefresh:R}=D({refreshOnMount:!0}),{groups:b}=L(),{installConfig:m}=T(),[z,x]=u.useState(!1),v=u.useRef(!1);u.useEffect(()=>{if(p){v.current=!0;return}if(v.current){x(!0);return}(a.length>0||t)&&x(!0)},[p,a.length,t]);const n=S.useMemo(()=>({total:a.length,online:a.filter(r=>r.status==="connected").length,disabled:a.filter(r=>r.enabled===!1).length,offline:a.filter(r=>r.status==="disconnected"&&r.enabled!==!1).length,connecting:a.filter(r=>(r.status==="connecting"||r.status==="oauth_required")&&r.enabled!==!1).length,tools:a.reduce((r,i)=>{var o;return r+(((o=i.tools)==null?void 0:o.length)||0)},0)}),[a]),E=S.useMemo(()=>a.slice(0,6),[a]),d=((j=m==null?void 0:m.baseUrl)==null?void 0:j.replace(/\/+$/,""))||"",g="minmax(220px,1.9fr) minmax(110px,0.95fr) minmax(120px,0.95fr) 80px 80px 90px 72px",f=!z;return e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-end justify-between gap-4 mb-6",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"hub-h1",children:s("pages.dashboard.title")}),e.jsxs("p",{className:"hub-sub",children:[s("pages.dashboard.totalServers")," · ",e.jsx("span",{className:"hub-num",children:n.total})," · ",s("pages.dashboard.onlineServers")," · ",e.jsx("span",{className:"hub-num",children:n.online})]})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs("button",{className:"hub-btn",onClick:()=>R(),children:[e.jsx(A,{size:13})," ",s("common.refresh")]}),e.jsxs("button",{className:"hub-btn primary",onClick:()=>l("/servers"),children:[e.jsx(U,{size:13})," ",s("server.add")]})]})]}),t&&e.jsxs("div",{className:"hub-card flex items-center justify-between gap-3 mb-5",style:{padding:"10px 14px",borderColor:"oklch(0.85 0.1 25)",background:"oklch(0.97 0.03 25)",color:"oklch(0.4 0.18 25)"},children:[e.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[e.jsx(y,{size:14,className:"flex-shrink-0"}),e.jsx("span",{className:"truncate text-[13px]",children:t})]}),e.jsx("button",{className:"hub-icon-btn sm",onClick:()=>C(null),"aria-label":s("app.closeButton"),children:"✕"})]}),f?e.jsx("div",{className:"grid grid-cols-2 md:grid-cols-5 gap-3 mb-6",children:Array.from({length:5}).map((r,i)=>e.jsx("div",{className:"hub-card animate-pulse",style:{padding:"14px 16px",height:78}},i))}):e.jsxs("div",{className:"grid grid-cols-2 md:grid-cols-5 gap-3 mb-6",children:[e.jsx(c,{label:s("pages.dashboard.totalServers"),value:n.total}),e.jsx(c,{label:s("pages.dashboard.onlineServers"),value:n.online,tone:"ok"}),e.jsx(c,{label:s("pages.dashboard.connectingServers"),value:n.connecting,tone:"warn"}),e.jsx(c,{label:s("pages.dashboard.offlineServers"),value:n.offline,tone:"err"}),e.jsx(c,{label:s("pages.dashboard.disabledServers"),value:n.disabled,tone:"muted"})]}),a.length>0&&!f&&e.jsxs("div",{className:"hub-card overflow-hidden mb-6",children:[e.jsxs("div",{className:"flex items-center justify-between px-4 py-3",style:{borderBottom:"1px solid var(--hub-line-2)"},children:[e.jsx("h3",{className:"hub-card-title",children:s("pages.dashboard.recentServers")}),e.jsxs("button",{className:"hub-btn ghost sm",style:{color:"var(--hub-ink-3)"},onClick:()=>l("/servers"),children:[s("common.viewAll")||"View all",e.jsx(H,{size:12})]})]}),e.jsxs("div",{className:"hub-row head hub-mono",style:{gridTemplateColumns:g},children:[e.jsx("div",{children:s("server.name")}),e.jsx("div",{children:s("server.status")}),e.jsx("div",{children:s("common.type")||"Transport"}),e.jsx("div",{children:s("server.tools")}),e.jsx("div",{children:s("server.prompts")}),e.jsx("div",{children:s("nav.resources")}),e.jsx("div",{children:s("server.enabled")})]}),E.map(r=>{var i,o,N,k;return e.jsxs("div",{className:"hub-row hover cursor-pointer",style:{gridTemplateColumns:g},onClick:()=>l("/servers"),children:[e.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[e.jsx("span",{className:"hub-mono truncate",style:{fontSize:13,color:r.enabled===!1?"var(--hub-ink-3)":"var(--hub-ink)"},children:r.name}),r.error&&e.jsx(y,{size:13,className:"text-[var(--hub-err)] flex-shrink-0"})]}),e.jsx("div",{className:"min-w-0",children:e.jsx(M,{status:r.status,enabled:r.enabled})}),e.jsx("div",{className:"min-w-0",children:(i=r.config)!=null&&i.type?e.jsx("span",{className:"hub-tag",title:w(s,r.config.type)??void 0,children:w(s,r.config.type)}):e.jsx("span",{style:{color:"var(--hub-ink-3)",fontSize:12},children:"—"})}),e.jsx("div",{className:"hub-num hub-mono",style:{fontSize:12.5},children:((o=r.tools)==null?void 0:o.length)||0}),e.jsx("div",{className:"hub-num hub-mono",style:{fontSize:12.5,color:"var(--hub-ink-2)"},children:((N=r.prompts)==null?void 0:N.length)||0}),e.jsx("div",{className:"hub-num hub-mono",style:{fontSize:12.5,color:"var(--hub-ink-2)"},children:((k=r.resources)==null?void 0:k.length)||0}),e.jsx("div",{className:"text-[12px]",style:{color:r.enabled!==!1?"var(--hub-ok)":"var(--hub-ink-3)"},children:r.enabled!==!1?"✓":"—"})]},r.name)})]}),e.jsxs("div",{className:"hub-card mb-5",style:{padding:16},children:[e.jsxs("div",{className:"flex justify-between items-start gap-3 mb-3",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"hub-card-title",children:s("pages.dashboard.endpoints")||"MCP Endpoints"}),e.jsx("p",{className:"hub-sub",style:{marginTop:2},children:s("pages.dashboard.endpointsHint")||"Use these URLs in Claude Desktop, Cursor, or any MCP client"})]}),e.jsxs("a",{className:"hub-btn ghost",href:"https://docs.mcphub.app",target:"_blank",rel:"noopener noreferrer",style:{color:"var(--hub-ink-3)"},children:[s("common.docs")||"Docs"," →"]})]}),e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-2.5",children:[e.jsx(h,{label:"ALL",url:`${d}/mcp`}),e.jsx(h,{label:"SMART",url:`${d}/mcp/$smart`}),b.slice(0,2).map(r=>e.jsx(h,{label:"GROUP",url:`${d}/mcp/${r.name}`},r.id)),b.length<2&&a[0]&&e.jsx(h,{label:"SERVER",url:`${d}/mcp/${a[0].name}`})]})]})]})};export{I as default};
2
- //# sourceMappingURL=Dashboard-CZBclnD_.js.map
1
+ import{b as $,R as u,r as S,j as e}from"./framework-vendor-BUhDPOUZ.js";import{u as D}from"./useServerData-B_sSO_jj.js";import{d as L}from"./index-otG7s0Ro.js";import{u as T}from"./useSettingsData-BE6ZnRFg.js";import{E as h}from"./EndpointCopy-Doi0lGZI.js";import{S as M}from"./StatusDot-C-kTn-AA.js";import{u as P}from"./i18n-vendor-Kbr87Ofu.js";import{R as A,P as U,j as y,k as H}from"./icons-vendor-CKgJB3SC.js";const c=({label:s,value:l,tone:a="default"})=>{const t=a==="ok"?"oklch(0.4 0.13 145)":a==="warn"?"oklch(0.45 0.13 80)":a==="err"?"oklch(0.45 0.18 25)":a==="muted"?"var(--hub-ink-3)":"var(--hub-ink)";return e.jsxs("div",{className:"hub-card",style:{padding:"14px 16px"},children:[e.jsx("div",{className:"text-[12px]",style:{color:"var(--hub-ink-3)"},children:s}),e.jsx("div",{className:"hub-num",style:{fontSize:26,fontWeight:500,letterSpacing:"-0.02em",lineHeight:1.1,marginTop:8,color:t},children:l})]})},w=(s,l)=>l?l==="stdio"?s("server.typeStdio")||"stdio":l==="sse"?s("server.typeSse")||"sse":l==="streamable-http"?s("server.typeStreamableHttp")||"http":l==="openapi"?s("server.typeOpenapi")||"openapi":l:null,I=()=>{var j;const{t:s}=P(),l=$(),{allServers:a,error:t,setError:C,isLoading:p,triggerRefresh:R}=D({refreshOnMount:!0}),{groups:b}=L(),{installConfig:m}=T(),[z,x]=u.useState(!1),v=u.useRef(!1);u.useEffect(()=>{if(p){v.current=!0;return}if(v.current){x(!0);return}(a.length>0||t)&&x(!0)},[p,a.length,t]);const n=S.useMemo(()=>({total:a.length,online:a.filter(r=>r.status==="connected").length,disabled:a.filter(r=>r.enabled===!1).length,offline:a.filter(r=>r.status==="disconnected"&&r.enabled!==!1).length,connecting:a.filter(r=>(r.status==="connecting"||r.status==="oauth_required")&&r.enabled!==!1).length,tools:a.reduce((r,i)=>{var o;return r+(((o=i.tools)==null?void 0:o.length)||0)},0)}),[a]),E=S.useMemo(()=>a.slice(0,6),[a]),d=((j=m==null?void 0:m.baseUrl)==null?void 0:j.replace(/\/+$/,""))||"",g="minmax(220px,1.9fr) minmax(110px,0.95fr) minmax(120px,0.95fr) 80px 80px 90px 72px",f=!z;return e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-end justify-between gap-4 mb-6",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"hub-h1",children:s("pages.dashboard.title")}),e.jsxs("p",{className:"hub-sub",children:[s("pages.dashboard.totalServers")," · ",e.jsx("span",{className:"hub-num",children:n.total})," · ",s("pages.dashboard.onlineServers")," · ",e.jsx("span",{className:"hub-num",children:n.online})]})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs("button",{className:"hub-btn",onClick:()=>R(),children:[e.jsx(A,{size:13})," ",s("common.refresh")]}),e.jsxs("button",{className:"hub-btn primary",onClick:()=>l("/servers"),children:[e.jsx(U,{size:13})," ",s("server.add")]})]})]}),t&&e.jsxs("div",{className:"hub-card flex items-center justify-between gap-3 mb-5",style:{padding:"10px 14px",borderColor:"oklch(0.85 0.1 25)",background:"oklch(0.97 0.03 25)",color:"oklch(0.4 0.18 25)"},children:[e.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[e.jsx(y,{size:14,className:"flex-shrink-0"}),e.jsx("span",{className:"truncate text-[13px]",children:t})]}),e.jsx("button",{className:"hub-icon-btn sm",onClick:()=>C(null),"aria-label":s("app.closeButton"),children:"✕"})]}),f?e.jsx("div",{className:"grid grid-cols-2 md:grid-cols-5 gap-3 mb-6",children:Array.from({length:5}).map((r,i)=>e.jsx("div",{className:"hub-card animate-pulse",style:{padding:"14px 16px",height:78}},i))}):e.jsxs("div",{className:"grid grid-cols-2 md:grid-cols-5 gap-3 mb-6",children:[e.jsx(c,{label:s("pages.dashboard.totalServers"),value:n.total}),e.jsx(c,{label:s("pages.dashboard.onlineServers"),value:n.online,tone:"ok"}),e.jsx(c,{label:s("pages.dashboard.connectingServers"),value:n.connecting,tone:"warn"}),e.jsx(c,{label:s("pages.dashboard.offlineServers"),value:n.offline,tone:"err"}),e.jsx(c,{label:s("pages.dashboard.disabledServers"),value:n.disabled,tone:"muted"})]}),a.length>0&&!f&&e.jsxs("div",{className:"hub-card overflow-hidden mb-6",children:[e.jsxs("div",{className:"flex items-center justify-between px-4 py-3",style:{borderBottom:"1px solid var(--hub-line-2)"},children:[e.jsx("h3",{className:"hub-card-title",children:s("pages.dashboard.recentServers")}),e.jsxs("button",{className:"hub-btn ghost sm",style:{color:"var(--hub-ink-3)"},onClick:()=>l("/servers"),children:[s("common.viewAll")||"View all",e.jsx(H,{size:12})]})]}),e.jsxs("div",{className:"hub-row head hub-mono",style:{gridTemplateColumns:g},children:[e.jsx("div",{children:s("server.name")}),e.jsx("div",{children:s("server.status")}),e.jsx("div",{children:s("common.type")||"Transport"}),e.jsx("div",{children:s("server.tools")}),e.jsx("div",{children:s("server.prompts")}),e.jsx("div",{children:s("nav.resources")}),e.jsx("div",{children:s("server.enabled")})]}),E.map(r=>{var i,o,N,k;return e.jsxs("div",{className:"hub-row hover cursor-pointer",style:{gridTemplateColumns:g},onClick:()=>l("/servers"),children:[e.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[e.jsx("span",{className:"hub-mono truncate",style:{fontSize:13,color:r.enabled===!1?"var(--hub-ink-3)":"var(--hub-ink)"},children:r.name}),r.error&&e.jsx(y,{size:13,className:"text-[var(--hub-err)] flex-shrink-0"})]}),e.jsx("div",{className:"min-w-0",children:e.jsx(M,{status:r.status,enabled:r.enabled})}),e.jsx("div",{className:"min-w-0",children:(i=r.config)!=null&&i.type?e.jsx("span",{className:"hub-tag",title:w(s,r.config.type)??void 0,children:w(s,r.config.type)}):e.jsx("span",{style:{color:"var(--hub-ink-3)",fontSize:12},children:"—"})}),e.jsx("div",{className:"hub-num hub-mono",style:{fontSize:12.5},children:((o=r.tools)==null?void 0:o.length)||0}),e.jsx("div",{className:"hub-num hub-mono",style:{fontSize:12.5,color:"var(--hub-ink-2)"},children:((N=r.prompts)==null?void 0:N.length)||0}),e.jsx("div",{className:"hub-num hub-mono",style:{fontSize:12.5,color:"var(--hub-ink-2)"},children:((k=r.resources)==null?void 0:k.length)||0}),e.jsx("div",{className:"text-[12px]",style:{color:r.enabled!==!1?"var(--hub-ok)":"var(--hub-ink-3)"},children:r.enabled!==!1?"✓":"—"})]},r.name)})]}),e.jsxs("div",{className:"hub-card mb-5",style:{padding:16},children:[e.jsxs("div",{className:"flex justify-between items-start gap-3 mb-3",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"hub-card-title",children:s("pages.dashboard.endpoints")||"MCP Endpoints"}),e.jsx("p",{className:"hub-sub",style:{marginTop:2},children:s("pages.dashboard.endpointsHint")||"Use these URLs in Claude Desktop, Cursor, or any MCP client"})]}),e.jsxs("a",{className:"hub-btn ghost",href:"https://docs.mcphub.app",target:"_blank",rel:"noopener noreferrer",style:{color:"var(--hub-ink-3)"},children:[s("common.docs")||"Docs"," →"]})]}),e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-2.5",children:[e.jsx(h,{label:"ALL",url:`${d}/mcp`}),e.jsx(h,{label:"SMART",url:`${d}/mcp/$smart`}),b.slice(0,2).map(r=>e.jsx(h,{label:"GROUP",url:`${d}/mcp/${r.name}`},r.id)),b.length<2&&a[0]&&e.jsx(h,{label:"SERVER",url:`${d}/mcp/${a[0].name}`})]})]})]})};export{I as default};
2
+ //# sourceMappingURL=Dashboard-C6l7But8.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Dashboard-CZBclnD_.js","sources":["../../src/pages/Dashboard.tsx"],"sourcesContent":["import React, { useMemo } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useNavigate } from 'react-router-dom';\nimport { RefreshCw, Plus, ChevronRight, AlertCircle } from 'lucide-react';\nimport { useServerData } from '@/hooks/useServerData';\nimport { useGroupData } from '@/hooks/useGroupData';\nimport { useSettingsData } from '@/hooks/useSettingsData';\nimport { Server } from '@/types';\nimport { EndpointCopy } from '@/components/ui/EndpointCopy';\nimport { ServerStatusDot } from '@/components/ui/StatusDot';\n\nconst Stat: React.FC<{ label: string; value: React.ReactNode; tone?: 'ok' | 'warn' | 'err' | 'muted' | 'default' }> = ({\n label,\n value,\n tone = 'default',\n}) => {\n const toneColor =\n tone === 'ok'\n ? 'oklch(0.4 0.13 145)'\n : tone === 'warn'\n ? 'oklch(0.45 0.13 80)'\n : tone === 'err'\n ? 'oklch(0.45 0.18 25)'\n : tone === 'muted'\n ? 'var(--hub-ink-3)'\n : 'var(--hub-ink)';\n return (\n <div className=\"hub-card\" style={{ padding: '14px 16px' }}>\n <div className=\"text-[12px]\" style={{ color: 'var(--hub-ink-3)' }}>\n {label}\n </div>\n <div\n className=\"hub-num\"\n style={{\n fontSize: 26,\n fontWeight: 500,\n letterSpacing: '-0.02em',\n lineHeight: 1.1,\n marginTop: 8,\n color: toneColor,\n }}\n >\n {value}\n </div>\n </div>\n );\n};\n\nconst transportLabel = (t: any, type?: string) => {\n if (!type) return null;\n if (type === 'stdio') return t('server.typeStdio') || 'stdio';\n if (type === 'sse') return t('server.typeSse') || 'sse';\n if (type === 'streamable-http') return t('server.typeStreamableHttp') || 'http';\n if (type === 'openapi') return t('server.typeOpenapi') || 'openapi';\n return type;\n};\n\nconst DashboardPage: React.FC = () => {\n const { t } = useTranslation();\n const navigate = useNavigate();\n const { allServers, error, setError, isLoading, triggerRefresh } = useServerData({\n refreshOnMount: true,\n });\n const { groups } = useGroupData();\n const { installConfig } = useSettingsData();\n\n const [hasLoaded, setHasLoaded] = React.useState(false);\n const loadingStartedRef = React.useRef(false);\n React.useEffect(() => {\n if (isLoading) {\n loadingStartedRef.current = true;\n return;\n }\n if (loadingStartedRef.current) {\n setHasLoaded(true);\n return;\n }\n if (allServers.length > 0 || error) setHasLoaded(true);\n }, [isLoading, allServers.length, error]);\n\n const stats = useMemo(\n () => ({\n total: allServers.length,\n online: allServers.filter((s: Server) => s.status === 'connected').length,\n disabled: allServers.filter((s: Server) => s.enabled === false).length,\n offline: allServers.filter(\n (s: Server) => s.status === 'disconnected' && s.enabled !== false,\n ).length,\n connecting: allServers.filter(\n (s: Server) =>\n (s.status === 'connecting' || s.status === 'oauth_required') && s.enabled !== false,\n ).length,\n tools: allServers.reduce((acc, s) => acc + (s.tools?.length || 0), 0),\n }),\n [allServers],\n );\n\n const recentServers = useMemo(() => allServers.slice(0, 6), [allServers]);\n const baseUrl = installConfig?.baseUrl?.replace(/\\/+$/, '') || '';\n const recentServerColumns =\n 'minmax(220px,1.9fr) minmax(110px,0.95fr) minmax(120px,0.95fr) 80px 80px 90px 72px';\n\n const showSkeleton = !hasLoaded;\n\n return (\n <div>\n {/* Header */}\n <div className=\"flex items-end justify-between gap-4 mb-6\">\n <div>\n <h1 className=\"hub-h1\">{t('pages.dashboard.title')}</h1>\n <p className=\"hub-sub\">\n {t('pages.dashboard.totalServers')} · <span className=\"hub-num\">{stats.total}</span>\n {' · '}\n {t('pages.dashboard.onlineServers')} · <span className=\"hub-num\">{stats.online}</span>\n </p>\n </div>\n <div className=\"flex gap-2\">\n <button className=\"hub-btn\" onClick={() => triggerRefresh()}>\n <RefreshCw size={13} /> {t('common.refresh')}\n </button>\n <button className=\"hub-btn primary\" onClick={() => navigate('/servers')}>\n <Plus size={13} /> {t('server.add')}\n </button>\n </div>\n </div>\n\n {error && (\n <div\n className=\"hub-card flex items-center justify-between gap-3 mb-5\"\n style={{\n padding: '10px 14px',\n borderColor: 'oklch(0.85 0.1 25)',\n background: 'oklch(0.97 0.03 25)',\n color: 'oklch(0.4 0.18 25)',\n }}\n >\n <div className=\"flex items-center gap-2 min-w-0\">\n <AlertCircle size={14} className=\"flex-shrink-0\" />\n <span className=\"truncate text-[13px]\">{error}</span>\n </div>\n <button\n className=\"hub-icon-btn sm\"\n onClick={() => setError(null)}\n aria-label={t('app.closeButton')}\n >\n ✕\n </button>\n </div>\n )}\n\n {/* Stat row */}\n {showSkeleton ? (\n <div className=\"grid grid-cols-2 md:grid-cols-5 gap-3 mb-6\">\n {Array.from({ length: 5 }).map((_, i) => (\n <div\n key={i}\n className=\"hub-card animate-pulse\"\n style={{ padding: '14px 16px', height: 78 }}\n />\n ))}\n </div>\n ) : (\n <div className=\"grid grid-cols-2 md:grid-cols-5 gap-3 mb-6\">\n <Stat label={t('pages.dashboard.totalServers')} value={stats.total} />\n <Stat label={t('pages.dashboard.onlineServers')} value={stats.online} tone=\"ok\" />\n <Stat label={t('pages.dashboard.connectingServers')} value={stats.connecting} tone=\"warn\" />\n <Stat label={t('pages.dashboard.offlineServers')} value={stats.offline} tone=\"err\" />\n <Stat label={t('pages.dashboard.disabledServers')} value={stats.disabled} tone=\"muted\" />\n </div>\n )}\n\n {/* Recent servers */}\n {allServers.length > 0 && !showSkeleton && (\n <div className=\"hub-card overflow-hidden mb-6\">\n <div\n className=\"flex items-center justify-between px-4 py-3\"\n style={{ borderBottom: '1px solid var(--hub-line-2)' }}\n >\n <h3 className=\"hub-card-title\">{t('pages.dashboard.recentServers')}</h3>\n <button\n className=\"hub-btn ghost sm\"\n style={{ color: 'var(--hub-ink-3)' }}\n onClick={() => navigate('/servers')}\n >\n {t('common.viewAll') || 'View all'}\n <ChevronRight size={12} />\n </button>\n </div>\n <div\n className=\"hub-row head hub-mono\"\n style={{ gridTemplateColumns: recentServerColumns }}\n >\n <div>{t('server.name')}</div>\n <div>{t('server.status')}</div>\n <div>{t('common.type') || 'Transport'}</div>\n <div>{t('server.tools')}</div>\n <div>{t('server.prompts')}</div>\n <div>{t('nav.resources')}</div>\n <div>{t('server.enabled')}</div>\n </div>\n {recentServers.map((s) => (\n <div\n key={s.name}\n className=\"hub-row hover cursor-pointer\"\n style={{ gridTemplateColumns: recentServerColumns }}\n onClick={() => navigate('/servers')}\n >\n <div className=\"flex items-center gap-2 min-w-0\">\n <span\n className=\"hub-mono truncate\"\n style={{ fontSize: 13, color: s.enabled === false ? 'var(--hub-ink-3)' : 'var(--hub-ink)' }}\n >\n {s.name}\n </span>\n {s.error && <AlertCircle size={13} className=\"text-[var(--hub-err)] flex-shrink-0\" />}\n </div>\n <div className=\"min-w-0\">\n <ServerStatusDot status={s.status} enabled={s.enabled} />\n </div>\n <div className=\"min-w-0\">\n {s.config?.type ? (\n <span className=\"hub-tag\" title={transportLabel(t, s.config.type) ?? undefined}>\n {transportLabel(t, s.config.type)}\n </span>\n ) : (\n <span style={{ color: 'var(--hub-ink-3)', fontSize: 12 }}>—</span>\n )}\n </div>\n <div className=\"hub-num hub-mono\" style={{ fontSize: 12.5 }}>\n {s.tools?.length || 0}\n </div>\n <div className=\"hub-num hub-mono\" style={{ fontSize: 12.5, color: 'var(--hub-ink-2)' }}>\n {s.prompts?.length || 0}\n </div>\n <div className=\"hub-num hub-mono\" style={{ fontSize: 12.5, color: 'var(--hub-ink-2)' }}>\n {s.resources?.length || 0}\n </div>\n <div className=\"text-[12px]\" style={{ color: s.enabled !== false ? 'var(--hub-ok)' : 'var(--hub-ink-3)' }}>\n {s.enabled !== false ? '✓' : '—'}\n </div>\n </div>\n ))}\n </div>\n )}\n\n {/* Endpoint quick-access */}\n <div className=\"hub-card mb-5\" style={{ padding: 16 }}>\n <div className=\"flex justify-between items-start gap-3 mb-3\">\n <div>\n <h3 className=\"hub-card-title\">{t('pages.dashboard.endpoints') || 'MCP Endpoints'}</h3>\n <p className=\"hub-sub\" style={{ marginTop: 2 }}>\n {t('pages.dashboard.endpointsHint') ||\n 'Use these URLs in Claude Desktop, Cursor, or any MCP client'}\n </p>\n </div>\n <a\n className=\"hub-btn ghost\"\n href=\"https://docs.mcphub.app\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{ color: 'var(--hub-ink-3)' }}\n >\n {t('common.docs') || 'Docs'} →\n </a>\n </div>\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-2.5\">\n <EndpointCopy label=\"ALL\" url={`${baseUrl}/mcp`} />\n <EndpointCopy label=\"SMART\" url={`${baseUrl}/mcp/$smart`} />\n {groups.slice(0, 2).map((g) => (\n <EndpointCopy key={g.id} label=\"GROUP\" url={`${baseUrl}/mcp/${g.name}`} />\n ))}\n {/* Pad with first server endpoint if there's space */}\n {groups.length < 2 && allServers[0] && (\n <EndpointCopy label=\"SERVER\" url={`${baseUrl}/mcp/${allServers[0].name}`} />\n )}\n </div>\n </div>\n </div>\n );\n};\n\nexport default DashboardPage;\n"],"names":["Stat","label","value","tone","toneColor","jsxs","jsx","transportLabel","t","type","DashboardPage","useTranslation","navigate","useNavigate","allServers","error","setError","isLoading","triggerRefresh","useServerData","groups","useGroupData","installConfig","useSettingsData","hasLoaded","setHasLoaded","React","loadingStartedRef","stats","useMemo","s","acc","_a","recentServers","baseUrl","recentServerColumns","showSkeleton","RefreshCw","Plus","AlertCircle","_","ChevronRight","ServerStatusDot","_b","_c","_d","EndpointCopy","g"],"mappings":"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"}
1
+ {"version":3,"file":"Dashboard-C6l7But8.js","sources":["../../src/pages/Dashboard.tsx"],"sourcesContent":["import React, { useMemo } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useNavigate } from 'react-router-dom';\nimport { RefreshCw, Plus, ChevronRight, AlertCircle } from 'lucide-react';\nimport { useServerData } from '@/hooks/useServerData';\nimport { useGroupData } from '@/hooks/useGroupData';\nimport { useSettingsData } from '@/hooks/useSettingsData';\nimport { Server } from '@/types';\nimport { EndpointCopy } from '@/components/ui/EndpointCopy';\nimport { ServerStatusDot } from '@/components/ui/StatusDot';\n\nconst Stat: React.FC<{ label: string; value: React.ReactNode; tone?: 'ok' | 'warn' | 'err' | 'muted' | 'default' }> = ({\n label,\n value,\n tone = 'default',\n}) => {\n const toneColor =\n tone === 'ok'\n ? 'oklch(0.4 0.13 145)'\n : tone === 'warn'\n ? 'oklch(0.45 0.13 80)'\n : tone === 'err'\n ? 'oklch(0.45 0.18 25)'\n : tone === 'muted'\n ? 'var(--hub-ink-3)'\n : 'var(--hub-ink)';\n return (\n <div className=\"hub-card\" style={{ padding: '14px 16px' }}>\n <div className=\"text-[12px]\" style={{ color: 'var(--hub-ink-3)' }}>\n {label}\n </div>\n <div\n className=\"hub-num\"\n style={{\n fontSize: 26,\n fontWeight: 500,\n letterSpacing: '-0.02em',\n lineHeight: 1.1,\n marginTop: 8,\n color: toneColor,\n }}\n >\n {value}\n </div>\n </div>\n );\n};\n\nconst transportLabel = (t: any, type?: string) => {\n if (!type) return null;\n if (type === 'stdio') return t('server.typeStdio') || 'stdio';\n if (type === 'sse') return t('server.typeSse') || 'sse';\n if (type === 'streamable-http') return t('server.typeStreamableHttp') || 'http';\n if (type === 'openapi') return t('server.typeOpenapi') || 'openapi';\n return type;\n};\n\nconst DashboardPage: React.FC = () => {\n const { t } = useTranslation();\n const navigate = useNavigate();\n const { allServers, error, setError, isLoading, triggerRefresh } = useServerData({\n refreshOnMount: true,\n });\n const { groups } = useGroupData();\n const { installConfig } = useSettingsData();\n\n const [hasLoaded, setHasLoaded] = React.useState(false);\n const loadingStartedRef = React.useRef(false);\n React.useEffect(() => {\n if (isLoading) {\n loadingStartedRef.current = true;\n return;\n }\n if (loadingStartedRef.current) {\n setHasLoaded(true);\n return;\n }\n if (allServers.length > 0 || error) setHasLoaded(true);\n }, [isLoading, allServers.length, error]);\n\n const stats = useMemo(\n () => ({\n total: allServers.length,\n online: allServers.filter((s: Server) => s.status === 'connected').length,\n disabled: allServers.filter((s: Server) => s.enabled === false).length,\n offline: allServers.filter(\n (s: Server) => s.status === 'disconnected' && s.enabled !== false,\n ).length,\n connecting: allServers.filter(\n (s: Server) =>\n (s.status === 'connecting' || s.status === 'oauth_required') && s.enabled !== false,\n ).length,\n tools: allServers.reduce((acc, s) => acc + (s.tools?.length || 0), 0),\n }),\n [allServers],\n );\n\n const recentServers = useMemo(() => allServers.slice(0, 6), [allServers]);\n const baseUrl = installConfig?.baseUrl?.replace(/\\/+$/, '') || '';\n const recentServerColumns =\n 'minmax(220px,1.9fr) minmax(110px,0.95fr) minmax(120px,0.95fr) 80px 80px 90px 72px';\n\n const showSkeleton = !hasLoaded;\n\n return (\n <div>\n {/* Header */}\n <div className=\"flex items-end justify-between gap-4 mb-6\">\n <div>\n <h1 className=\"hub-h1\">{t('pages.dashboard.title')}</h1>\n <p className=\"hub-sub\">\n {t('pages.dashboard.totalServers')} · <span className=\"hub-num\">{stats.total}</span>\n {' · '}\n {t('pages.dashboard.onlineServers')} · <span className=\"hub-num\">{stats.online}</span>\n </p>\n </div>\n <div className=\"flex gap-2\">\n <button className=\"hub-btn\" onClick={() => triggerRefresh()}>\n <RefreshCw size={13} /> {t('common.refresh')}\n </button>\n <button className=\"hub-btn primary\" onClick={() => navigate('/servers')}>\n <Plus size={13} /> {t('server.add')}\n </button>\n </div>\n </div>\n\n {error && (\n <div\n className=\"hub-card flex items-center justify-between gap-3 mb-5\"\n style={{\n padding: '10px 14px',\n borderColor: 'oklch(0.85 0.1 25)',\n background: 'oklch(0.97 0.03 25)',\n color: 'oklch(0.4 0.18 25)',\n }}\n >\n <div className=\"flex items-center gap-2 min-w-0\">\n <AlertCircle size={14} className=\"flex-shrink-0\" />\n <span className=\"truncate text-[13px]\">{error}</span>\n </div>\n <button\n className=\"hub-icon-btn sm\"\n onClick={() => setError(null)}\n aria-label={t('app.closeButton')}\n >\n ✕\n </button>\n </div>\n )}\n\n {/* Stat row */}\n {showSkeleton ? (\n <div className=\"grid grid-cols-2 md:grid-cols-5 gap-3 mb-6\">\n {Array.from({ length: 5 }).map((_, i) => (\n <div\n key={i}\n className=\"hub-card animate-pulse\"\n style={{ padding: '14px 16px', height: 78 }}\n />\n ))}\n </div>\n ) : (\n <div className=\"grid grid-cols-2 md:grid-cols-5 gap-3 mb-6\">\n <Stat label={t('pages.dashboard.totalServers')} value={stats.total} />\n <Stat label={t('pages.dashboard.onlineServers')} value={stats.online} tone=\"ok\" />\n <Stat label={t('pages.dashboard.connectingServers')} value={stats.connecting} tone=\"warn\" />\n <Stat label={t('pages.dashboard.offlineServers')} value={stats.offline} tone=\"err\" />\n <Stat label={t('pages.dashboard.disabledServers')} value={stats.disabled} tone=\"muted\" />\n </div>\n )}\n\n {/* Recent servers */}\n {allServers.length > 0 && !showSkeleton && (\n <div className=\"hub-card overflow-hidden mb-6\">\n <div\n className=\"flex items-center justify-between px-4 py-3\"\n style={{ borderBottom: '1px solid var(--hub-line-2)' }}\n >\n <h3 className=\"hub-card-title\">{t('pages.dashboard.recentServers')}</h3>\n <button\n className=\"hub-btn ghost sm\"\n style={{ color: 'var(--hub-ink-3)' }}\n onClick={() => navigate('/servers')}\n >\n {t('common.viewAll') || 'View all'}\n <ChevronRight size={12} />\n </button>\n </div>\n <div\n className=\"hub-row head hub-mono\"\n style={{ gridTemplateColumns: recentServerColumns }}\n >\n <div>{t('server.name')}</div>\n <div>{t('server.status')}</div>\n <div>{t('common.type') || 'Transport'}</div>\n <div>{t('server.tools')}</div>\n <div>{t('server.prompts')}</div>\n <div>{t('nav.resources')}</div>\n <div>{t('server.enabled')}</div>\n </div>\n {recentServers.map((s) => (\n <div\n key={s.name}\n className=\"hub-row hover cursor-pointer\"\n style={{ gridTemplateColumns: recentServerColumns }}\n onClick={() => navigate('/servers')}\n >\n <div className=\"flex items-center gap-2 min-w-0\">\n <span\n className=\"hub-mono truncate\"\n style={{ fontSize: 13, color: s.enabled === false ? 'var(--hub-ink-3)' : 'var(--hub-ink)' }}\n >\n {s.name}\n </span>\n {s.error && <AlertCircle size={13} className=\"text-[var(--hub-err)] flex-shrink-0\" />}\n </div>\n <div className=\"min-w-0\">\n <ServerStatusDot status={s.status} enabled={s.enabled} />\n </div>\n <div className=\"min-w-0\">\n {s.config?.type ? (\n <span className=\"hub-tag\" title={transportLabel(t, s.config.type) ?? undefined}>\n {transportLabel(t, s.config.type)}\n </span>\n ) : (\n <span style={{ color: 'var(--hub-ink-3)', fontSize: 12 }}>—</span>\n )}\n </div>\n <div className=\"hub-num hub-mono\" style={{ fontSize: 12.5 }}>\n {s.tools?.length || 0}\n </div>\n <div className=\"hub-num hub-mono\" style={{ fontSize: 12.5, color: 'var(--hub-ink-2)' }}>\n {s.prompts?.length || 0}\n </div>\n <div className=\"hub-num hub-mono\" style={{ fontSize: 12.5, color: 'var(--hub-ink-2)' }}>\n {s.resources?.length || 0}\n </div>\n <div className=\"text-[12px]\" style={{ color: s.enabled !== false ? 'var(--hub-ok)' : 'var(--hub-ink-3)' }}>\n {s.enabled !== false ? '✓' : '—'}\n </div>\n </div>\n ))}\n </div>\n )}\n\n {/* Endpoint quick-access */}\n <div className=\"hub-card mb-5\" style={{ padding: 16 }}>\n <div className=\"flex justify-between items-start gap-3 mb-3\">\n <div>\n <h3 className=\"hub-card-title\">{t('pages.dashboard.endpoints') || 'MCP Endpoints'}</h3>\n <p className=\"hub-sub\" style={{ marginTop: 2 }}>\n {t('pages.dashboard.endpointsHint') ||\n 'Use these URLs in Claude Desktop, Cursor, or any MCP client'}\n </p>\n </div>\n <a\n className=\"hub-btn ghost\"\n href=\"https://docs.mcphub.app\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{ color: 'var(--hub-ink-3)' }}\n >\n {t('common.docs') || 'Docs'} →\n </a>\n </div>\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-2.5\">\n <EndpointCopy label=\"ALL\" url={`${baseUrl}/mcp`} />\n <EndpointCopy label=\"SMART\" url={`${baseUrl}/mcp/$smart`} />\n {groups.slice(0, 2).map((g) => (\n <EndpointCopy key={g.id} label=\"GROUP\" url={`${baseUrl}/mcp/${g.name}`} />\n ))}\n {/* Pad with first server endpoint if there's space */}\n {groups.length < 2 && allServers[0] && (\n <EndpointCopy label=\"SERVER\" url={`${baseUrl}/mcp/${allServers[0].name}`} />\n )}\n </div>\n </div>\n </div>\n );\n};\n\nexport default DashboardPage;\n"],"names":["Stat","label","value","tone","toneColor","jsxs","jsx","transportLabel","t","type","DashboardPage","useTranslation","navigate","useNavigate","allServers","error","setError","isLoading","triggerRefresh","useServerData","groups","useGroupData","installConfig","useSettingsData","hasLoaded","setHasLoaded","React","loadingStartedRef","stats","useMemo","s","acc","_a","recentServers","baseUrl","recentServerColumns","showSkeleton","RefreshCw","Plus","AlertCircle","_","ChevronRight","ServerStatusDot","_b","_c","_d","EndpointCopy","g"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{r as y,j as t}from"./framework-vendor-BUhDPOUZ.js";import{i as x,m as r}from"./index-St_D2SAD.js";import{u as h}from"./i18n-vendor-Kbr87Ofu.js";import{C,o as b}from"./icons-vendor-CKgJB3SC.js";const f=async e=>{try{if(navigator.clipboard&&window.isSecureContext)return await navigator.clipboard.writeText(e),!0}catch{}try{const o=document.createElement("textarea");o.value=e,o.style.position="fixed",o.style.left="-9999px",document.body.appendChild(o),o.focus(),o.select();const s=document.execCommand("copy");return document.body.removeChild(o),s}catch{return!1}},E=({url:e,label:o,prefix:s,className:p,copyValue:d,ariaLabel:l})=>{const{t:c}=h(),{showToast:n}=x(),[a,i]=y.useState(!1),m=async u=>{if(u.stopPropagation(),!await f(d??e)){n(c("common.copyFailed")||"Copy failed","error");return}i(!0),n(c("common.copySuccess")||"Copied to clipboard","success"),setTimeout(()=>i(!1),1200)};return t.jsxs("div",{className:r("hub-endpoint",p),role:"group","aria-label":l||e,children:[o&&t.jsx("div",{className:"hub-endpoint-label",children:o}),t.jsxs("div",{className:"hub-endpoint-url",title:e,children:[s&&t.jsx("span",{style:{color:"var(--hub-ink-3)"},children:s}),e]}),t.jsx("button",{type:"button",onClick:m,className:r("hub-endpoint-copy",a?"copied":""),title:c("common.copy")||"Copy","aria-label":c("common.copy")||"Copy",children:a?t.jsx(C,{size:13}):t.jsx(b,{size:13})})]})};export{E};
2
- //# sourceMappingURL=EndpointCopy-C7kzq1Rv.js.map
1
+ import{r as y,j as t}from"./framework-vendor-BUhDPOUZ.js";import{i as x,m as r}from"./index-otG7s0Ro.js";import{u as h}from"./i18n-vendor-Kbr87Ofu.js";import{C,o as b}from"./icons-vendor-CKgJB3SC.js";const f=async e=>{try{if(navigator.clipboard&&window.isSecureContext)return await navigator.clipboard.writeText(e),!0}catch{}try{const o=document.createElement("textarea");o.value=e,o.style.position="fixed",o.style.left="-9999px",document.body.appendChild(o),o.focus(),o.select();const s=document.execCommand("copy");return document.body.removeChild(o),s}catch{return!1}},E=({url:e,label:o,prefix:s,className:p,copyValue:d,ariaLabel:l})=>{const{t:c}=h(),{showToast:n}=x(),[a,i]=y.useState(!1),m=async u=>{if(u.stopPropagation(),!await f(d??e)){n(c("common.copyFailed")||"Copy failed","error");return}i(!0),n(c("common.copySuccess")||"Copied to clipboard","success"),setTimeout(()=>i(!1),1200)};return t.jsxs("div",{className:r("hub-endpoint",p),role:"group","aria-label":l||e,children:[o&&t.jsx("div",{className:"hub-endpoint-label",children:o}),t.jsxs("div",{className:"hub-endpoint-url",title:e,children:[s&&t.jsx("span",{style:{color:"var(--hub-ink-3)"},children:s}),e]}),t.jsx("button",{type:"button",onClick:m,className:r("hub-endpoint-copy",a?"copied":""),title:c("common.copy")||"Copy","aria-label":c("common.copy")||"Copy",children:a?t.jsx(C,{size:13}):t.jsx(b,{size:13})})]})};export{E};
2
+ //# sourceMappingURL=EndpointCopy-Doi0lGZI.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"EndpointCopy-C7kzq1Rv.js","sources":["../../src/components/ui/EndpointCopy.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport { Copy, Check } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { useToast } from '@/contexts/ToastContext';\nimport { cn } from '@/utils/cn';\n\nconst copyText = async (value: string): Promise<boolean> => {\n try {\n if (navigator.clipboard && window.isSecureContext) {\n await navigator.clipboard.writeText(value);\n return true;\n }\n } catch {\n // fall through to fallback\n }\n try {\n const el = document.createElement('textarea');\n el.value = value;\n el.style.position = 'fixed';\n el.style.left = '-9999px';\n document.body.appendChild(el);\n el.focus();\n el.select();\n const ok = document.execCommand('copy');\n document.body.removeChild(el);\n return ok;\n } catch {\n return false;\n }\n};\n\ninterface EndpointCopyProps {\n url: string;\n label?: string;\n prefix?: string;\n className?: string;\n /** Optionally override the value placed on the clipboard. */\n copyValue?: string;\n ariaLabel?: string;\n}\n\nexport const EndpointCopy: React.FC<EndpointCopyProps> = ({\n url,\n label,\n prefix,\n className,\n copyValue,\n ariaLabel,\n}) => {\n const { t } = useTranslation();\n const { showToast } = useToast();\n const [copied, setCopied] = useState(false);\n\n const onCopy = async (e: React.MouseEvent) => {\n e.stopPropagation();\n const ok = await copyText(copyValue ?? url);\n if (!ok) {\n showToast(t('common.copyFailed') || 'Copy failed', 'error');\n return;\n }\n setCopied(true);\n showToast(t('common.copySuccess') || 'Copied to clipboard', 'success');\n setTimeout(() => setCopied(false), 1200);\n };\n\n return (\n <div className={cn('hub-endpoint', className)} role=\"group\" aria-label={ariaLabel || url}>\n {label && <div className=\"hub-endpoint-label\">{label}</div>}\n <div className=\"hub-endpoint-url\" title={url}>\n {prefix && <span style={{ color: 'var(--hub-ink-3)' }}>{prefix}</span>}\n {url}\n </div>\n <button\n type=\"button\"\n onClick={onCopy}\n className={cn('hub-endpoint-copy', copied ? 'copied' : '')}\n title={t('common.copy') || 'Copy'}\n aria-label={t('common.copy') || 'Copy'}\n >\n {copied ? <Check size={13} /> : <Copy size={13} />}\n </button>\n </div>\n );\n};\n\ninterface MonoCopyProps {\n text: string;\n className?: string;\n copyValue?: string;\n title?: string;\n}\n\n/** Inline monospace value with hover-to-copy icon. */\nexport const MonoCopy: React.FC<MonoCopyProps> = ({ text, className, copyValue, title }) => {\n const { t } = useTranslation();\n const { showToast } = useToast();\n const [copied, setCopied] = useState(false);\n\n const onCopy = async (e: React.MouseEvent) => {\n e.stopPropagation();\n const ok = await copyText(copyValue ?? text);\n if (!ok) {\n showToast(t('common.copyFailed') || 'Copy failed', 'error');\n return;\n }\n setCopied(true);\n showToast(t('common.copySuccess') || 'Copied to clipboard', 'success');\n setTimeout(() => setCopied(false), 1200);\n };\n\n return (\n <span\n className={cn(\n 'hub-mono inline-flex items-center gap-1.5 group cursor-pointer text-[12.5px]',\n className,\n )}\n onClick={onCopy}\n title={title || text}\n role=\"button\"\n >\n <span className=\"truncate\">{text}</span>\n {copied ? (\n <Check size={12} className=\"text-[var(--hub-ok)] flex-shrink-0\" />\n ) : (\n <Copy\n size={12}\n className=\"text-[var(--hub-ink-3)] opacity-0 group-hover:opacity-100 transition-opacity flex-shrink-0\"\n />\n )}\n </span>\n );\n};\n"],"names":["copyText","value","el","ok","EndpointCopy","url","label","prefix","className","copyValue","ariaLabel","t","useTranslation","showToast","useToast","copied","setCopied","useState","onCopy","e","jsxs","cn","jsx","Check","Copy"],"mappings":"wMAMA,MAAMA,EAAW,MAAOC,GAAoC,CAC1D,GAAI,CACF,GAAI,UAAU,WAAa,OAAO,gBAChC,aAAM,UAAU,UAAU,UAAUA,CAAK,EAClC,EAEX,MAAQ,CAER,CACA,GAAI,CACF,MAAMC,EAAK,SAAS,cAAc,UAAU,EAC5CA,EAAG,MAAQD,EACXC,EAAG,MAAM,SAAW,QACpBA,EAAG,MAAM,KAAO,UAChB,SAAS,KAAK,YAAYA,CAAE,EAC5BA,EAAG,MAAA,EACHA,EAAG,OAAA,EACH,MAAMC,EAAK,SAAS,YAAY,MAAM,EACtC,gBAAS,KAAK,YAAYD,CAAE,EACrBC,CACT,MAAQ,CACN,MAAO,EACT,CACF,EAYaC,EAA4C,CAAC,CACxD,IAAAC,EACA,MAAAC,EACA,OAAAC,EACA,UAAAC,EACA,UAAAC,EACA,UAAAC,CACF,IAAM,CACJ,KAAM,CAAE,EAAAC,CAAA,EAAMC,EAAA,EACR,CAAE,UAAAC,CAAA,EAAcC,EAAA,EAChB,CAACC,EAAQC,CAAS,EAAIC,EAAAA,SAAS,EAAK,EAEpCC,EAAS,MAAOC,GAAwB,CAG5C,GAFAA,EAAE,gBAAA,EAEE,CADO,MAAMnB,EAASS,GAAaJ,CAAG,EACjC,CACPQ,EAAUF,EAAE,mBAAmB,GAAK,cAAe,OAAO,EAC1D,MACF,CACAK,EAAU,EAAI,EACdH,EAAUF,EAAE,oBAAoB,GAAK,sBAAuB,SAAS,EACrE,WAAW,IAAMK,EAAU,EAAK,EAAG,IAAI,CACzC,EAEA,OACEI,EAAAA,KAAC,MAAA,CAAI,UAAWC,EAAG,eAAgBb,CAAS,EAAG,KAAK,QAAQ,aAAYE,GAAaL,EAClF,SAAA,CAAAC,GAASgB,EAAAA,IAAC,MAAA,CAAI,UAAU,qBAAsB,SAAAhB,EAAM,EACrDc,EAAAA,KAAC,MAAA,CAAI,UAAU,mBAAmB,MAAOf,EACtC,SAAA,CAAAE,SAAW,OAAA,CAAK,MAAO,CAAE,MAAO,kBAAA,EAAuB,SAAAA,EAAO,EAC9DF,CAAA,EACH,EACAiB,EAAAA,IAAC,SAAA,CACC,KAAK,SACL,QAASJ,EACT,UAAWG,EAAG,oBAAqBN,EAAS,SAAW,EAAE,EACzD,MAAOJ,EAAE,aAAa,GAAK,OAC3B,aAAYA,EAAE,aAAa,GAAK,OAE/B,SAAAI,QAAUQ,EAAA,CAAM,KAAM,GAAI,EAAKD,EAAAA,IAACE,EAAA,CAAK,KAAM,EAAA,CAAI,CAAA,CAAA,CAClD,EACF,CAEJ"}
1
+ {"version":3,"file":"EndpointCopy-Doi0lGZI.js","sources":["../../src/components/ui/EndpointCopy.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport { Copy, Check } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { useToast } from '@/contexts/ToastContext';\nimport { cn } from '@/utils/cn';\n\nconst copyText = async (value: string): Promise<boolean> => {\n try {\n if (navigator.clipboard && window.isSecureContext) {\n await navigator.clipboard.writeText(value);\n return true;\n }\n } catch {\n // fall through to fallback\n }\n try {\n const el = document.createElement('textarea');\n el.value = value;\n el.style.position = 'fixed';\n el.style.left = '-9999px';\n document.body.appendChild(el);\n el.focus();\n el.select();\n const ok = document.execCommand('copy');\n document.body.removeChild(el);\n return ok;\n } catch {\n return false;\n }\n};\n\ninterface EndpointCopyProps {\n url: string;\n label?: string;\n prefix?: string;\n className?: string;\n /** Optionally override the value placed on the clipboard. */\n copyValue?: string;\n ariaLabel?: string;\n}\n\nexport const EndpointCopy: React.FC<EndpointCopyProps> = ({\n url,\n label,\n prefix,\n className,\n copyValue,\n ariaLabel,\n}) => {\n const { t } = useTranslation();\n const { showToast } = useToast();\n const [copied, setCopied] = useState(false);\n\n const onCopy = async (e: React.MouseEvent) => {\n e.stopPropagation();\n const ok = await copyText(copyValue ?? url);\n if (!ok) {\n showToast(t('common.copyFailed') || 'Copy failed', 'error');\n return;\n }\n setCopied(true);\n showToast(t('common.copySuccess') || 'Copied to clipboard', 'success');\n setTimeout(() => setCopied(false), 1200);\n };\n\n return (\n <div className={cn('hub-endpoint', className)} role=\"group\" aria-label={ariaLabel || url}>\n {label && <div className=\"hub-endpoint-label\">{label}</div>}\n <div className=\"hub-endpoint-url\" title={url}>\n {prefix && <span style={{ color: 'var(--hub-ink-3)' }}>{prefix}</span>}\n {url}\n </div>\n <button\n type=\"button\"\n onClick={onCopy}\n className={cn('hub-endpoint-copy', copied ? 'copied' : '')}\n title={t('common.copy') || 'Copy'}\n aria-label={t('common.copy') || 'Copy'}\n >\n {copied ? <Check size={13} /> : <Copy size={13} />}\n </button>\n </div>\n );\n};\n\ninterface MonoCopyProps {\n text: string;\n className?: string;\n copyValue?: string;\n title?: string;\n}\n\n/** Inline monospace value with hover-to-copy icon. */\nexport const MonoCopy: React.FC<MonoCopyProps> = ({ text, className, copyValue, title }) => {\n const { t } = useTranslation();\n const { showToast } = useToast();\n const [copied, setCopied] = useState(false);\n\n const onCopy = async (e: React.MouseEvent) => {\n e.stopPropagation();\n const ok = await copyText(copyValue ?? text);\n if (!ok) {\n showToast(t('common.copyFailed') || 'Copy failed', 'error');\n return;\n }\n setCopied(true);\n showToast(t('common.copySuccess') || 'Copied to clipboard', 'success');\n setTimeout(() => setCopied(false), 1200);\n };\n\n return (\n <span\n className={cn(\n 'hub-mono inline-flex items-center gap-1.5 group cursor-pointer text-[12.5px]',\n className,\n )}\n onClick={onCopy}\n title={title || text}\n role=\"button\"\n >\n <span className=\"truncate\">{text}</span>\n {copied ? (\n <Check size={12} className=\"text-[var(--hub-ok)] flex-shrink-0\" />\n ) : (\n <Copy\n size={12}\n className=\"text-[var(--hub-ink-3)] opacity-0 group-hover:opacity-100 transition-opacity flex-shrink-0\"\n />\n )}\n </span>\n );\n};\n"],"names":["copyText","value","el","ok","EndpointCopy","url","label","prefix","className","copyValue","ariaLabel","t","useTranslation","showToast","useToast","copied","setCopied","useState","onCopy","e","jsxs","cn","jsx","Check","Copy"],"mappings":"wMAMA,MAAMA,EAAW,MAAOC,GAAoC,CAC1D,GAAI,CACF,GAAI,UAAU,WAAa,OAAO,gBAChC,aAAM,UAAU,UAAU,UAAUA,CAAK,EAClC,EAEX,MAAQ,CAER,CACA,GAAI,CACF,MAAMC,EAAK,SAAS,cAAc,UAAU,EAC5CA,EAAG,MAAQD,EACXC,EAAG,MAAM,SAAW,QACpBA,EAAG,MAAM,KAAO,UAChB,SAAS,KAAK,YAAYA,CAAE,EAC5BA,EAAG,MAAA,EACHA,EAAG,OAAA,EACH,MAAMC,EAAK,SAAS,YAAY,MAAM,EACtC,gBAAS,KAAK,YAAYD,CAAE,EACrBC,CACT,MAAQ,CACN,MAAO,EACT,CACF,EAYaC,EAA4C,CAAC,CACxD,IAAAC,EACA,MAAAC,EACA,OAAAC,EACA,UAAAC,EACA,UAAAC,EACA,UAAAC,CACF,IAAM,CACJ,KAAM,CAAE,EAAAC,CAAA,EAAMC,EAAA,EACR,CAAE,UAAAC,CAAA,EAAcC,EAAA,EAChB,CAACC,EAAQC,CAAS,EAAIC,EAAAA,SAAS,EAAK,EAEpCC,EAAS,MAAOC,GAAwB,CAG5C,GAFAA,EAAE,gBAAA,EAEE,CADO,MAAMnB,EAASS,GAAaJ,CAAG,EACjC,CACPQ,EAAUF,EAAE,mBAAmB,GAAK,cAAe,OAAO,EAC1D,MACF,CACAK,EAAU,EAAI,EACdH,EAAUF,EAAE,oBAAoB,GAAK,sBAAuB,SAAS,EACrE,WAAW,IAAMK,EAAU,EAAK,EAAG,IAAI,CACzC,EAEA,OACEI,EAAAA,KAAC,MAAA,CAAI,UAAWC,EAAG,eAAgBb,CAAS,EAAG,KAAK,QAAQ,aAAYE,GAAaL,EAClF,SAAA,CAAAC,GAASgB,EAAAA,IAAC,MAAA,CAAI,UAAU,qBAAsB,SAAAhB,EAAM,EACrDc,EAAAA,KAAC,MAAA,CAAI,UAAU,mBAAmB,MAAOf,EACtC,SAAA,CAAAE,SAAW,OAAA,CAAK,MAAO,CAAE,MAAO,kBAAA,EAAuB,SAAAA,EAAO,EAC9DF,CAAA,EACH,EACAiB,EAAAA,IAAC,SAAA,CACC,KAAK,SACL,QAASJ,EACT,UAAWG,EAAG,oBAAqBN,EAAS,SAAW,EAAE,EACzD,MAAOJ,EAAE,aAAa,GAAK,OAC3B,aAAYA,EAAE,aAAa,GAAK,OAE/B,SAAAI,QAAUQ,EAAA,CAAM,KAAM,GAAI,EAAKD,EAAAA,IAACE,EAAA,CAAK,KAAM,EAAA,CAAI,CAAA,CAAA,CAClD,EACF,CAEJ"}
@@ -1,4 +1,4 @@
1
- import{r as b,R as W,j as e}from"./framework-vendor-BUhDPOUZ.js";import{m as U,d as q,i as Q,e as M}from"./index-St_D2SAD.js";import{u as J}from"./useServerData-4qDtSQW3.js";import{u as X}from"./useSettingsData-CSmSfVuv.js";import{u as P}from"./i18n-vendor-Kbr87Ofu.js";import{W as ee,f as se,F as te,C as re,o as B,x as ae,u as le,t as ne,T as oe,s as ie,v as V,D as ce,P as _,j as de,X as me}from"./icons-vendor-CKgJB3SC.js";import{D as ue}from"./DeleteDialog-DRbWonMu.js";const pe={tools:[],prompts:[],resources:[]},H={tools:"all",prompts:"all",resources:"all"},Y=({servers:i,value:m,onChange:t,className:d})=>{const{t:u}=P(),{nameSeparator:A}=X(),[g,k]=b.useState(new Set),x=W.useMemo(()=>m.map(s=>typeof s=="string"?{name:s,...H}:{...s,tools:s.tools||"all",prompts:s.prompts||"all",resources:s.resources||"all"}),[m]),p=W.useMemo(()=>i.filter(s=>s.enabled!==!1),[i]);W.useEffect(()=>{const s=new Set(x.map(r=>r.name)),l=new Set(p.map(r=>r.name));k(r=>{const S=new Set;return r.forEach(N=>{(s.has(N)||l.has(N))&&S.add(N)}),S})},[x,p]);const v=s=>{if(x.findIndex(r=>r.name===s)>=0){const r=x.filter(S=>S.name!==s);t(r)}else{const r=[...x,{name:s,...H}];t(r)}},y=s=>{k(l=>{const r=new Set(l);return r.has(s)?r.delete(s):r.add(s),r})},w=s=>["tools","prompts","resources"].some(l=>{const r=s[l];return r==="all"||Array.isArray(r)&&r.length>0}),C=(s,l,r,S=!1)=>{const N=x.find(h=>h.name===s),z={...N?{...N}:{name:s,...pe},[l]:r};if(!w(z)){const h=x.filter(F=>F.name!==s);t(h),S||k(F=>{const I=new Set(F);return I.delete(s),I});return}if(N){t(x.map(h=>h.name===s?z:h));return}t([...x,z])},E=(s,l)=>{const r=`${s}${A}`;return l.startsWith(r)?l.slice(r.length):l},o=(s,l)=>l==="tools"?(s.tools||[]).filter(r=>r.enabled!==!1).map(r=>({key:r.name,value:E(s.name,r.name),description:r.description})):l==="prompts"?(s.prompts||[]).filter(r=>r.enabled!==!1).map(r=>({key:r.name,value:E(s.name,r.name),description:r.description})):(s.resources||[]).filter(r=>r.enabled!==!1).map(r=>({key:r.uri,value:r.uri,description:r.description})),c=(s,l,r)=>{const S=p.find(h=>h.name===s);if(!S)return;const N=o(S,l).map(h=>h.value),D=x.find(h=>h.name===s);if(!D){C(s,l,[r]);return}const z=D[l];if(z==="all"){const h=N.filter(F=>F!==r);C(s,l,h);return}if(Array.isArray(z)){if(z.includes(r)){C(s,l,z.filter(F=>F!==r));return}const h=[...z,r];C(s,l,h.length===N.length?"all":h);return}C(s,l,[r])},f=s=>{const l=x.find(r=>r.name===s);return!!(l&&w(l))},a=s=>{const l=x.find(r=>r.name===s);return l?["tools","prompts","resources"].some(r=>{const S=l[r];return Array.isArray(S)&&S.length>0}):!1},n=(s,l,r)=>{const S=x.find(D=>D.name===s);if(!S)return!1;const N=S[l];return N==="all"?!0:Array.isArray(N)?N.includes(r):!1},j=(s,l)=>{const r=x.find(D=>D.name===s.name);if(!r)return 0;const S=o(s,l),N=r[l];if(N==="all")return S.length;if(Array.isArray(N)){const D=new Set(S.map(z=>z.value));return N.filter(z=>D.has(z)).length}return 0},T=[{key:"tools",titleKey:"groups.toolSelection",countKey:"groups.toolsSelected",allKey:"groups.allTools"},{key:"prompts",titleKey:"groups.promptSelection",countKey:"groups.promptsSelected",allKey:"groups.allPrompts"},{key:"resources",titleKey:"groups.resourceSelection",countKey:"groups.resourcesSelected",allKey:"groups.allResources"}],R=s=>T.map(({key:l})=>({key:l,count:j(s,l)})).filter(l=>l.count>0);return e.jsxs("div",{className:U("space-y-4",d),children:[e.jsx("div",{className:"space-y-3",children:p.map(s=>{const l=f(s.name),r=a(s.name),S=g.has(s.name),N=x.find(h=>h.name===s.name),D=R(s),z=T.filter(({key:h})=>o(s,h).length>0);return e.jsxs("div",{className:"border border-gray-200 dark:border-gray-700 rounded-lg hover:border-gray-300 hover:bg-gray-50 dark:bg-gray-800 dark:hover:bg-gray-700 transition-colors",children:[e.jsxs("div",{className:"flex items-center justify-between p-3 cursor-pointer rounded-lg transition-colors",onClick:()=>y(s.name),children:[e.jsxs("div",{className:"flex items-center space-x-3",onClick:h=>{h.stopPropagation(),v(s.name)},children:[e.jsx("input",{type:"checkbox",checked:l||r,onChange:()=>v(s.name),className:"w-4 h-4 text-blue-600 bg-gray-100 dark:bg-gray-800 border-gray-300 rounded focus:ring-blue-500"}),e.jsx("span",{className:"font-medium text-gray-900 cursor-pointer select-none",children:s.name})]}),e.jsxs("div",{className:"flex items-center space-x-3",children:[D.map(({key:h,count:F})=>e.jsxs("span",{className:"text-sm text-green-600 flex items-center gap-1",children:[h==="tools"?e.jsx(ee,{size:14}):h==="prompts"?e.jsx(se,{size:14}):e.jsx(te,{size:14})," ",F]},h)),z.length>0&&e.jsx("button",{type:"button",className:"p-1 text-gray-400 hover:text-gray-600 transition-colors",children:e.jsx("svg",{className:U("w-5 h-5 transition-transform",S&&"rotate-180"),fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M19 9l-7 7-7-7"})})})]})]}),S&&z.length>0&&e.jsx("div",{className:"border-t border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800 p-3",children:e.jsx("div",{className:"space-y-4",children:z.map(({key:h,titleKey:F,countKey:I,allKey:L})=>{const $=o(s,h),K=j(s,h),O=(N==null?void 0:N[h])==="all"||K===$.length;return e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-3",children:[e.jsx("span",{className:"text-sm font-medium text-gray-700",children:u(F)}),e.jsxs("div",{className:"flex items-center gap-3",children:[N&&e.jsx("span",{className:"text-xs text-green-600",children:O?`(${u(L)} ${$.length}/${$.length})`:`(${u(I)} ${K}/${$.length})`}),e.jsx("button",{type:"button",onClick:()=>{C(s.name,h,O?[]:"all",!0)},className:"text-sm text-blue-600 hover:text-blue-800 transition-colors",children:u(O?"groups.selectNone":"groups.selectAll")})]})]}),e.jsx("div",{className:"grid grid-cols-1 gap-2 max-h-32 overflow-y-auto",children:$.map(G=>{const Z=n(s.name,h,G.value);return e.jsxs("label",{className:"flex items-center space-x-2 text-sm",children:[e.jsx("input",{type:"checkbox",checked:Z,onChange:()=>c(s.name,h,G.value),className:"w-3 h-3 text-blue-600 bg-gray-100 dark:bg-gray-800 border-gray-300 rounded focus:ring-blue-500"}),e.jsx("span",{className:"text-gray-700 break-all whitespace-nowrap",children:G.value}),G.description&&e.jsx("span",{className:"text-gray-400 text-xs truncate",children:G.description})]},G.key)})})]},h)})})})]},s.name)})}),p.length===0&&e.jsx("p",{className:"text-gray-500 text-sm",children:u("groups.noServerOptions")})]})},xe=({onAdd:i,onCancel:m})=>{const{t}=P(),{createGroup:d}=q(),{allServers:u}=J(),[A,g]=b.useState([]),[k,x]=b.useState(null),[p,v]=b.useState(!1),[y,w]=b.useState({name:"",description:"",servers:[]});b.useEffect(()=>{g(u.filter(o=>o.enabled!==!1))},[u]);const C=o=>{const{name:c,value:f}=o.target;w(a=>({...a,[c]:f}))},E=async o=>{o.preventDefault(),v(!0),x(null);try{if(!y.name.trim()){x(t("groups.nameRequired")),v(!1);return}const c=await d(y.name,y.description,y.servers);if(!c||!c.success){x((c==null?void 0:c.message)||t("groups.createError")),v(!1);return}i()}catch(c){x(c instanceof Error?c.message:String(c)),v(!1)}};return e.jsx("div",{className:"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4",children:e.jsxs("div",{className:"bg-white dark:bg-gray-800 rounded-lg shadow-lg max-w-3xl w-full max-h-[90vh] flex flex-col",children:[e.jsxs("div",{className:"p-6 flex-shrink-0",children:[e.jsx("h2",{className:"text-xl font-semibold text-gray-800 mb-4",children:t("groups.addNew")}),k&&e.jsx("div",{className:"mb-4 p-3 bg-red-100 text-red-700 rounded-md border border-gray-200 dark:border-gray-700",children:k})]}),e.jsxs("form",{onSubmit:E,className:"flex flex-col flex-1 min-h-0",children:[e.jsx("div",{className:"flex-1 overflow-y-auto px-6",children:e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsxs("label",{className:"block text-gray-700 text-sm font-bold mb-2",htmlFor:"name",children:[t("groups.name")," *"]}),e.jsx("input",{type:"text",id:"name",name:"name",value:y.name,onChange:C,className:"w-full border border-gray-300 rounded-md px-3 py-2 text-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent",placeholder:t("groups.namePlaceholder"),required:!0})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-gray-700 text-sm font-bold mb-2",children:t("groups.configureCapabilities")}),e.jsx(Y,{servers:A,value:y.servers,onChange:o=>w(c=>({...c,servers:o})),className:"border border-gray-200 dark:border-gray-700 rounded-lg p-4 bg-gray-50 dark:bg-gray-800"})]})]})}),e.jsxs("div",{className:"flex justify-end space-x-2 p-5 pt-3 border-t border-[var(--hub-line-2)] flex-shrink-0",children:[e.jsx("button",{type:"button",onClick:m,className:"hub-btn",disabled:p,children:t("common.cancel")}),e.jsx("button",{type:"submit",className:"hub-btn primary",disabled:p,children:t(p?"common.submitting":"common.create")})]})]})]})})},he=({group:i,onEdit:m,onCancel:t})=>{const{t:d}=P(),{updateGroup:u}=q(),{allServers:A}=J(),[g,k]=b.useState([]),[x,p]=b.useState(null),[v,y]=b.useState(!1),[w,C]=b.useState({name:i.name,description:i.description||"",servers:i.servers||[]});b.useEffect(()=>{k(A.filter(c=>c.enabled!==!1))},[A]);const E=c=>{const{name:f,value:a}=c.target;C(n=>({...n,[f]:a}))},o=async c=>{c.preventDefault(),y(!0),p(null);try{if(!w.name.trim()){p(d("groups.nameRequired")),y(!1);return}const f=await u(i.id,{name:w.name,description:w.description,servers:w.servers});if(!f||!f.success){p((f==null?void 0:f.message)||d("groups.updateError")),y(!1);return}m()}catch(f){p(f instanceof Error?f.message:String(f)),y(!1)}};return e.jsx("div",{className:"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4",children:e.jsxs("div",{className:"bg-white dark:bg-gray-800 rounded-lg shadow-lg max-w-3xl w-full max-h-[90vh] flex flex-col",children:[e.jsxs("div",{className:"p-6 flex-shrink-0",children:[e.jsx("h2",{className:"text-xl font-semibold text-gray-800 mb-4",children:d("groups.edit")}),x&&e.jsx("div",{className:"mb-4 p-3 bg-red-100 text-red-700 rounded-md border border-gray-200 dark:border-gray-700",children:x})]}),e.jsxs("form",{onSubmit:o,className:"flex flex-col flex-1 min-h-0",children:[e.jsx("div",{className:"flex-1 overflow-y-auto px-6",children:e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsxs("label",{className:"block text-gray-700 text-sm font-bold mb-2",htmlFor:"name",children:[d("groups.name")," *"]}),e.jsx("input",{type:"text",id:"name",name:"name",value:w.name,onChange:E,className:"w-full border border-gray-300 rounded-md px-3 py-2 text-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent",placeholder:d("groups.namePlaceholder"),required:!0})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-gray-700 text-sm font-bold mb-2",children:d("groups.configureCapabilities")}),e.jsx(Y,{servers:g,value:w.servers,onChange:c=>C(f=>({...f,servers:c})),className:"border border-gray-200 dark:border-gray-700 rounded-lg p-4 bg-gray-50 dark:bg-gray-800"})]})]})}),e.jsxs("div",{className:"flex justify-end space-x-2 p-5 pt-3 border-t border-[var(--hub-line-2)] flex-shrink-0",children:[e.jsx("button",{type:"button",onClick:t,className:"hub-btn",disabled:v,children:d("common.cancel")}),e.jsx("button",{type:"submit",className:"hub-btn primary",disabled:v,children:d(v?"common.submitting":"common.save")})]})]})]})})},be=i=>i.map(m=>typeof m=="string"?m:m.name),ge=(i,m)=>{const t=i.servers.find(d=>typeof d=="string"?d===m:d.name===m);return t?typeof t=="string"?{name:t,tools:"all",prompts:"all",resources:"all"}:t:{name:m,tools:"all",prompts:"all",resources:"all"}},fe=async i=>{try{if(navigator.clipboard&&window.isSecureContext)return await navigator.clipboard.writeText(i),!0}catch{}try{const m=document.createElement("textarea");m.value=i,m.style.position="fixed",m.style.left="-9999px",document.body.appendChild(m),m.focus(),m.select();const t=document.execCommand("copy");return document.body.removeChild(m),t}catch{return!1}},ye=({group:i,servers:m,onEdit:t,onDelete:d})=>{var R;const{t:u}=P(),{showToast:A}=Q(),{installConfig:g,nameSeparator:k}=X(),x=((R=g==null?void 0:g.baseUrl)==null?void 0:R.replace(/\/+$/,""))||"",[p,v]=b.useState(!1),[y,w]=b.useState(!1),[C,E]=b.useState(!1),o=b.useRef(null);b.useEffect(()=>{const s=l=>{o.current&&!o.current.contains(l.target)&&E(!1)};return document.addEventListener("mousedown",s),()=>document.removeEventListener("mousedown",s)},[]);const c=async s=>{await fe(s)?(w(!0),E(!1),A(u("common.copySuccess")||"Copied","success"),setTimeout(()=>w(!1),1500)):A(u("common.copyFailed")||"Copy failed","error")},f=`${x}/mcp/${i.name}`,a=be(i.servers),n=m.filter(s=>a.includes(s.name)),j=s=>{const l=ge(i,s.name),r=`${s.name}${k}`,S=s.tools||[],N=s.prompts||[],D=s.resources||[],z=Array.isArray(l.tools)?S.filter(I=>{if(I.enabled===!1)return!1;const L=I.name.startsWith(r)?I.name.slice(r.length):I.name;return l.tools.includes(L)}).length:S.filter(I=>I.enabled!==!1).length,h=Array.isArray(l.prompts)?N.filter(I=>{if(I.enabled===!1)return!1;const L=I.name.startsWith(r)?I.name.slice(r.length):I.name;return l.prompts.includes(L)}).length:N.filter(I=>I.enabled!==!1).length,F=Array.isArray(l.resources)?D.filter(I=>I.enabled!==!1&&l.resources.includes(I.uri)).length:D.filter(I=>I.enabled!==!1).length;return{visibleTools:z,totalTools:S.length,visiblePrompts:h,totalPrompts:N.length,visibleResources:F,totalResources:D.length}},T=n.reduce((s,l)=>s+j(l).visibleTools,0);return e.jsxs("div",{className:"hub-card overflow-visible",children:[e.jsxs("div",{className:"flex items-start gap-3 px-4 py-3",style:{borderBottom:"1px solid var(--hub-line-2)"},children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{style:{fontSize:15,fontWeight:600,letterSpacing:"-0.015em"},children:i.name}),e.jsx("span",{className:"hub-mono",style:{fontSize:11,color:"var(--hub-ink-3)",padding:"0 6px",border:"1px solid var(--hub-line)",borderRadius:4,height:18,display:"inline-flex",alignItems:"center"},title:i.id,children:i.id})]}),i.description&&e.jsx("div",{style:{fontSize:12.5,color:"var(--hub-ink-3)",marginTop:2},children:i.description})]}),e.jsxs("div",{className:"flex items-center gap-1",ref:o,children:[e.jsxs("div",{className:"relative",children:[e.jsx("button",{onClick:()=>E(s=>!s),className:"hub-icon-btn sm",title:u("common.copy"),children:y?e.jsx(re,{size:13,className:"text-[var(--hub-ok)]"}):e.jsx(B,{size:13})}),C&&e.jsxs("div",{className:"absolute top-full right-0 mt-1 z-20 hub-card",style:{minWidth:160,padding:4},children:[e.jsxs("button",{onClick:()=>c(i.id),className:"flex items-center gap-2 w-full px-2.5 py-1.5 text-[13px] rounded-md hover:bg-[var(--hub-surface-hover)] text-left",children:[e.jsx(B,{size:12})," ",u("common.copyId")]}),e.jsxs("button",{onClick:()=>c(f),className:"flex items-center gap-2 w-full px-2.5 py-1.5 text-[13px] rounded-md hover:bg-[var(--hub-surface-hover)] text-left",children:[e.jsx(ae,{size:12})," ",u("common.copyUrl")]}),e.jsxs("button",{onClick:()=>c(JSON.stringify({mcpServers:{mcphub:{url:f,headers:{Authorization:"Bearer <your-access-token>"}}}},null,2)),className:"flex items-center gap-2 w-full px-2.5 py-1.5 text-[13px] rounded-md hover:bg-[var(--hub-surface-hover)] text-left",children:[e.jsx(le,{size:12})," ",u("common.copyJson")]})]})]}),e.jsx("button",{onClick:()=>t(i),className:"hub-icon-btn sm",title:u("groups.edit"),children:e.jsx(ne,{size:13})}),e.jsx("button",{onClick:()=>v(!0),className:"hub-icon-btn sm",title:u("groups.delete"),style:{color:"var(--hub-ink-3)"},children:e.jsx(oe,{size:13})})]})]}),e.jsxs("div",{className:"grid items-center gap-3 px-4 py-3",style:{gridTemplateColumns:"1fr 80px 1fr"},children:[e.jsx("div",{className:"flex flex-col gap-1.5",children:n.length===0?e.jsx("div",{style:{fontSize:12,color:"var(--hub-ink-3)"},children:u("groups.noServers")}):n.map(s=>{const l=j(s);return e.jsxs("div",{className:"flex items-center gap-2.5 px-2.5 py-1.5 rounded-md",style:{background:"var(--hub-bg-2)",border:"1px solid var(--hub-line-2)"},children:[e.jsx("span",{className:"inline-block flex-shrink-0",style:{width:6,height:6,borderRadius:50,background:s.status==="connected"?"var(--hub-ok)":s.status==="connecting"?"var(--hub-warn)":"var(--hub-err)"}}),e.jsx("span",{className:"hub-mono truncate flex-1",style:{fontSize:12.5},children:s.name}),e.jsxs("span",{className:"hub-mono hub-num flex-shrink-0",style:{fontSize:11,color:"var(--hub-ink-3)"},children:[l.visibleTools,"/",l.totalTools," tools"]})]},s.name)})}),e.jsxs("svg",{width:"80",height:"80",viewBox:"0 0 80 80",className:"self-center",children:[n.length===0?e.jsx("path",{d:"M0,40 C30,40 50,40 80,40",stroke:"var(--hub-line)",strokeWidth:"1",fill:"none",strokeDasharray:"3 3"}):n.map((s,l)=>{const r=12+60/Math.max(n.length,1)*(l+.5);return e.jsx("path",{d:`M0,${r} C 30,${r} 50,40 80,40`,stroke:"var(--hub-line)",strokeWidth:"1",fill:"none",strokeDasharray:"3 3"},l)}),e.jsx("circle",{cx:"80",cy:"40",r:"4",fill:"var(--hub-ink)"})]}),e.jsxs("div",{className:"px-3 py-2.5 rounded-md",style:{border:"1px solid var(--hub-line)",background:"var(--hub-bg-2)"},children:[e.jsx("div",{className:"hub-sect",style:{marginBottom:4},children:"endpoint"}),e.jsxs("div",{className:"hub-mono break-all",style:{fontSize:12,color:"var(--hub-ink-2)",lineHeight:1.4},children:[e.jsx("span",{style:{color:"var(--hub-ink-3)"},children:"/mcp/"}),e.jsx("b",{style:{color:"var(--hub-ink)",fontWeight:600},children:i.name})]}),e.jsx("div",{className:"flex gap-1.5 mt-2",children:e.jsxs("button",{className:"hub-btn sm flex-1 justify-center",onClick:()=>c(f),children:[e.jsx(B,{size:11})," ",u("common.copy")]})})]})]}),e.jsxs("div",{className:"flex justify-between items-center px-4 py-2",style:{borderTop:"1px solid var(--hub-line-2)",background:"var(--hub-bg-2)",fontSize:12,color:"var(--hub-ink-3)"},children:[e.jsxs("div",{className:"hub-mono",children:[e.jsx("span",{style:{color:"var(--hub-ink-2)"},children:n.length})," ",u("nav.servers").toLowerCase()," ·"," ",e.jsx("span",{style:{color:"var(--hub-ink-2)"},children:T})," ",u("server.tools").toLowerCase()]}),e.jsxs("button",{className:"hub-btn ghost sm",style:{color:"var(--hub-ink-3)"},onClick:()=>t(i),children:[u("groups.configureTools")||u("groups.edit"),e.jsx(ie,{size:11,style:{transform:"rotate(-90deg)"}})]})]}),e.jsx(ue,{isOpen:p,onClose:()=>v(!1),onConfirm:()=>{d(i.id),v(!1)},serverName:i.name,isGroup:!0})]})},je=({onSuccess:i,onCancel:m})=>{const{t}=P(),[d,u]=b.useState(""),[A,g]=b.useState(null),[k,x]=b.useState(!1),[p,v]=b.useState(null),y=`{
1
+ import{r as b,R as W,j as e}from"./framework-vendor-BUhDPOUZ.js";import{m as U,d as q,i as Q,e as M}from"./index-otG7s0Ro.js";import{u as J}from"./useServerData-B_sSO_jj.js";import{u as X}from"./useSettingsData-BE6ZnRFg.js";import{u as P}from"./i18n-vendor-Kbr87Ofu.js";import{W as ee,f as se,F as te,C as re,o as B,x as ae,u as le,t as ne,T as oe,s as ie,v as V,D as ce,P as _,j as de,X as me}from"./icons-vendor-CKgJB3SC.js";import{D as ue}from"./DeleteDialog-DRbWonMu.js";const pe={tools:[],prompts:[],resources:[]},H={tools:"all",prompts:"all",resources:"all"},Y=({servers:i,value:m,onChange:t,className:d})=>{const{t:u}=P(),{nameSeparator:A}=X(),[g,k]=b.useState(new Set),x=W.useMemo(()=>m.map(s=>typeof s=="string"?{name:s,...H}:{...s,tools:s.tools||"all",prompts:s.prompts||"all",resources:s.resources||"all"}),[m]),p=W.useMemo(()=>i.filter(s=>s.enabled!==!1),[i]);W.useEffect(()=>{const s=new Set(x.map(r=>r.name)),l=new Set(p.map(r=>r.name));k(r=>{const S=new Set;return r.forEach(N=>{(s.has(N)||l.has(N))&&S.add(N)}),S})},[x,p]);const v=s=>{if(x.findIndex(r=>r.name===s)>=0){const r=x.filter(S=>S.name!==s);t(r)}else{const r=[...x,{name:s,...H}];t(r)}},y=s=>{k(l=>{const r=new Set(l);return r.has(s)?r.delete(s):r.add(s),r})},w=s=>["tools","prompts","resources"].some(l=>{const r=s[l];return r==="all"||Array.isArray(r)&&r.length>0}),C=(s,l,r,S=!1)=>{const N=x.find(h=>h.name===s),z={...N?{...N}:{name:s,...pe},[l]:r};if(!w(z)){const h=x.filter(F=>F.name!==s);t(h),S||k(F=>{const I=new Set(F);return I.delete(s),I});return}if(N){t(x.map(h=>h.name===s?z:h));return}t([...x,z])},E=(s,l)=>{const r=`${s}${A}`;return l.startsWith(r)?l.slice(r.length):l},o=(s,l)=>l==="tools"?(s.tools||[]).filter(r=>r.enabled!==!1).map(r=>({key:r.name,value:E(s.name,r.name),description:r.description})):l==="prompts"?(s.prompts||[]).filter(r=>r.enabled!==!1).map(r=>({key:r.name,value:E(s.name,r.name),description:r.description})):(s.resources||[]).filter(r=>r.enabled!==!1).map(r=>({key:r.uri,value:r.uri,description:r.description})),c=(s,l,r)=>{const S=p.find(h=>h.name===s);if(!S)return;const N=o(S,l).map(h=>h.value),D=x.find(h=>h.name===s);if(!D){C(s,l,[r]);return}const z=D[l];if(z==="all"){const h=N.filter(F=>F!==r);C(s,l,h);return}if(Array.isArray(z)){if(z.includes(r)){C(s,l,z.filter(F=>F!==r));return}const h=[...z,r];C(s,l,h.length===N.length?"all":h);return}C(s,l,[r])},f=s=>{const l=x.find(r=>r.name===s);return!!(l&&w(l))},a=s=>{const l=x.find(r=>r.name===s);return l?["tools","prompts","resources"].some(r=>{const S=l[r];return Array.isArray(S)&&S.length>0}):!1},n=(s,l,r)=>{const S=x.find(D=>D.name===s);if(!S)return!1;const N=S[l];return N==="all"?!0:Array.isArray(N)?N.includes(r):!1},j=(s,l)=>{const r=x.find(D=>D.name===s.name);if(!r)return 0;const S=o(s,l),N=r[l];if(N==="all")return S.length;if(Array.isArray(N)){const D=new Set(S.map(z=>z.value));return N.filter(z=>D.has(z)).length}return 0},T=[{key:"tools",titleKey:"groups.toolSelection",countKey:"groups.toolsSelected",allKey:"groups.allTools"},{key:"prompts",titleKey:"groups.promptSelection",countKey:"groups.promptsSelected",allKey:"groups.allPrompts"},{key:"resources",titleKey:"groups.resourceSelection",countKey:"groups.resourcesSelected",allKey:"groups.allResources"}],R=s=>T.map(({key:l})=>({key:l,count:j(s,l)})).filter(l=>l.count>0);return e.jsxs("div",{className:U("space-y-4",d),children:[e.jsx("div",{className:"space-y-3",children:p.map(s=>{const l=f(s.name),r=a(s.name),S=g.has(s.name),N=x.find(h=>h.name===s.name),D=R(s),z=T.filter(({key:h})=>o(s,h).length>0);return e.jsxs("div",{className:"border border-gray-200 dark:border-gray-700 rounded-lg hover:border-gray-300 hover:bg-gray-50 dark:bg-gray-800 dark:hover:bg-gray-700 transition-colors",children:[e.jsxs("div",{className:"flex items-center justify-between p-3 cursor-pointer rounded-lg transition-colors",onClick:()=>y(s.name),children:[e.jsxs("div",{className:"flex items-center space-x-3",onClick:h=>{h.stopPropagation(),v(s.name)},children:[e.jsx("input",{type:"checkbox",checked:l||r,onChange:()=>v(s.name),className:"w-4 h-4 text-blue-600 bg-gray-100 dark:bg-gray-800 border-gray-300 rounded focus:ring-blue-500"}),e.jsx("span",{className:"font-medium text-gray-900 cursor-pointer select-none",children:s.name})]}),e.jsxs("div",{className:"flex items-center space-x-3",children:[D.map(({key:h,count:F})=>e.jsxs("span",{className:"text-sm text-green-600 flex items-center gap-1",children:[h==="tools"?e.jsx(ee,{size:14}):h==="prompts"?e.jsx(se,{size:14}):e.jsx(te,{size:14})," ",F]},h)),z.length>0&&e.jsx("button",{type:"button",className:"p-1 text-gray-400 hover:text-gray-600 transition-colors",children:e.jsx("svg",{className:U("w-5 h-5 transition-transform",S&&"rotate-180"),fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M19 9l-7 7-7-7"})})})]})]}),S&&z.length>0&&e.jsx("div",{className:"border-t border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800 p-3",children:e.jsx("div",{className:"space-y-4",children:z.map(({key:h,titleKey:F,countKey:I,allKey:L})=>{const $=o(s,h),K=j(s,h),O=(N==null?void 0:N[h])==="all"||K===$.length;return e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-3",children:[e.jsx("span",{className:"text-sm font-medium text-gray-700",children:u(F)}),e.jsxs("div",{className:"flex items-center gap-3",children:[N&&e.jsx("span",{className:"text-xs text-green-600",children:O?`(${u(L)} ${$.length}/${$.length})`:`(${u(I)} ${K}/${$.length})`}),e.jsx("button",{type:"button",onClick:()=>{C(s.name,h,O?[]:"all",!0)},className:"text-sm text-blue-600 hover:text-blue-800 transition-colors",children:u(O?"groups.selectNone":"groups.selectAll")})]})]}),e.jsx("div",{className:"grid grid-cols-1 gap-2 max-h-32 overflow-y-auto",children:$.map(G=>{const Z=n(s.name,h,G.value);return e.jsxs("label",{className:"flex items-center space-x-2 text-sm",children:[e.jsx("input",{type:"checkbox",checked:Z,onChange:()=>c(s.name,h,G.value),className:"w-3 h-3 text-blue-600 bg-gray-100 dark:bg-gray-800 border-gray-300 rounded focus:ring-blue-500"}),e.jsx("span",{className:"text-gray-700 break-all whitespace-nowrap",children:G.value}),G.description&&e.jsx("span",{className:"text-gray-400 text-xs truncate",children:G.description})]},G.key)})})]},h)})})})]},s.name)})}),p.length===0&&e.jsx("p",{className:"text-gray-500 text-sm",children:u("groups.noServerOptions")})]})},xe=({onAdd:i,onCancel:m})=>{const{t}=P(),{createGroup:d}=q(),{allServers:u}=J(),[A,g]=b.useState([]),[k,x]=b.useState(null),[p,v]=b.useState(!1),[y,w]=b.useState({name:"",description:"",servers:[]});b.useEffect(()=>{g(u.filter(o=>o.enabled!==!1))},[u]);const C=o=>{const{name:c,value:f}=o.target;w(a=>({...a,[c]:f}))},E=async o=>{o.preventDefault(),v(!0),x(null);try{if(!y.name.trim()){x(t("groups.nameRequired")),v(!1);return}const c=await d(y.name,y.description,y.servers);if(!c||!c.success){x((c==null?void 0:c.message)||t("groups.createError")),v(!1);return}i()}catch(c){x(c instanceof Error?c.message:String(c)),v(!1)}};return e.jsx("div",{className:"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4",children:e.jsxs("div",{className:"bg-white dark:bg-gray-800 rounded-lg shadow-lg max-w-3xl w-full max-h-[90vh] flex flex-col",children:[e.jsxs("div",{className:"p-6 flex-shrink-0",children:[e.jsx("h2",{className:"text-xl font-semibold text-gray-800 mb-4",children:t("groups.addNew")}),k&&e.jsx("div",{className:"mb-4 p-3 bg-red-100 text-red-700 rounded-md border border-gray-200 dark:border-gray-700",children:k})]}),e.jsxs("form",{onSubmit:E,className:"flex flex-col flex-1 min-h-0",children:[e.jsx("div",{className:"flex-1 overflow-y-auto px-6",children:e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsxs("label",{className:"block text-gray-700 text-sm font-bold mb-2",htmlFor:"name",children:[t("groups.name")," *"]}),e.jsx("input",{type:"text",id:"name",name:"name",value:y.name,onChange:C,className:"w-full border border-gray-300 rounded-md px-3 py-2 text-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent",placeholder:t("groups.namePlaceholder"),required:!0})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-gray-700 text-sm font-bold mb-2",children:t("groups.configureCapabilities")}),e.jsx(Y,{servers:A,value:y.servers,onChange:o=>w(c=>({...c,servers:o})),className:"border border-gray-200 dark:border-gray-700 rounded-lg p-4 bg-gray-50 dark:bg-gray-800"})]})]})}),e.jsxs("div",{className:"flex justify-end space-x-2 p-5 pt-3 border-t border-[var(--hub-line-2)] flex-shrink-0",children:[e.jsx("button",{type:"button",onClick:m,className:"hub-btn",disabled:p,children:t("common.cancel")}),e.jsx("button",{type:"submit",className:"hub-btn primary",disabled:p,children:t(p?"common.submitting":"common.create")})]})]})]})})},he=({group:i,onEdit:m,onCancel:t})=>{const{t:d}=P(),{updateGroup:u}=q(),{allServers:A}=J(),[g,k]=b.useState([]),[x,p]=b.useState(null),[v,y]=b.useState(!1),[w,C]=b.useState({name:i.name,description:i.description||"",servers:i.servers||[]});b.useEffect(()=>{k(A.filter(c=>c.enabled!==!1))},[A]);const E=c=>{const{name:f,value:a}=c.target;C(n=>({...n,[f]:a}))},o=async c=>{c.preventDefault(),y(!0),p(null);try{if(!w.name.trim()){p(d("groups.nameRequired")),y(!1);return}const f=await u(i.id,{name:w.name,description:w.description,servers:w.servers});if(!f||!f.success){p((f==null?void 0:f.message)||d("groups.updateError")),y(!1);return}m()}catch(f){p(f instanceof Error?f.message:String(f)),y(!1)}};return e.jsx("div",{className:"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4",children:e.jsxs("div",{className:"bg-white dark:bg-gray-800 rounded-lg shadow-lg max-w-3xl w-full max-h-[90vh] flex flex-col",children:[e.jsxs("div",{className:"p-6 flex-shrink-0",children:[e.jsx("h2",{className:"text-xl font-semibold text-gray-800 mb-4",children:d("groups.edit")}),x&&e.jsx("div",{className:"mb-4 p-3 bg-red-100 text-red-700 rounded-md border border-gray-200 dark:border-gray-700",children:x})]}),e.jsxs("form",{onSubmit:o,className:"flex flex-col flex-1 min-h-0",children:[e.jsx("div",{className:"flex-1 overflow-y-auto px-6",children:e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsxs("label",{className:"block text-gray-700 text-sm font-bold mb-2",htmlFor:"name",children:[d("groups.name")," *"]}),e.jsx("input",{type:"text",id:"name",name:"name",value:w.name,onChange:E,className:"w-full border border-gray-300 rounded-md px-3 py-2 text-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent",placeholder:d("groups.namePlaceholder"),required:!0})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-gray-700 text-sm font-bold mb-2",children:d("groups.configureCapabilities")}),e.jsx(Y,{servers:g,value:w.servers,onChange:c=>C(f=>({...f,servers:c})),className:"border border-gray-200 dark:border-gray-700 rounded-lg p-4 bg-gray-50 dark:bg-gray-800"})]})]})}),e.jsxs("div",{className:"flex justify-end space-x-2 p-5 pt-3 border-t border-[var(--hub-line-2)] flex-shrink-0",children:[e.jsx("button",{type:"button",onClick:t,className:"hub-btn",disabled:v,children:d("common.cancel")}),e.jsx("button",{type:"submit",className:"hub-btn primary",disabled:v,children:d(v?"common.submitting":"common.save")})]})]})]})})},be=i=>i.map(m=>typeof m=="string"?m:m.name),ge=(i,m)=>{const t=i.servers.find(d=>typeof d=="string"?d===m:d.name===m);return t?typeof t=="string"?{name:t,tools:"all",prompts:"all",resources:"all"}:t:{name:m,tools:"all",prompts:"all",resources:"all"}},fe=async i=>{try{if(navigator.clipboard&&window.isSecureContext)return await navigator.clipboard.writeText(i),!0}catch{}try{const m=document.createElement("textarea");m.value=i,m.style.position="fixed",m.style.left="-9999px",document.body.appendChild(m),m.focus(),m.select();const t=document.execCommand("copy");return document.body.removeChild(m),t}catch{return!1}},ye=({group:i,servers:m,onEdit:t,onDelete:d})=>{var R;const{t:u}=P(),{showToast:A}=Q(),{installConfig:g,nameSeparator:k}=X(),x=((R=g==null?void 0:g.baseUrl)==null?void 0:R.replace(/\/+$/,""))||"",[p,v]=b.useState(!1),[y,w]=b.useState(!1),[C,E]=b.useState(!1),o=b.useRef(null);b.useEffect(()=>{const s=l=>{o.current&&!o.current.contains(l.target)&&E(!1)};return document.addEventListener("mousedown",s),()=>document.removeEventListener("mousedown",s)},[]);const c=async s=>{await fe(s)?(w(!0),E(!1),A(u("common.copySuccess")||"Copied","success"),setTimeout(()=>w(!1),1500)):A(u("common.copyFailed")||"Copy failed","error")},f=`${x}/mcp/${i.name}`,a=be(i.servers),n=m.filter(s=>a.includes(s.name)),j=s=>{const l=ge(i,s.name),r=`${s.name}${k}`,S=s.tools||[],N=s.prompts||[],D=s.resources||[],z=Array.isArray(l.tools)?S.filter(I=>{if(I.enabled===!1)return!1;const L=I.name.startsWith(r)?I.name.slice(r.length):I.name;return l.tools.includes(L)}).length:S.filter(I=>I.enabled!==!1).length,h=Array.isArray(l.prompts)?N.filter(I=>{if(I.enabled===!1)return!1;const L=I.name.startsWith(r)?I.name.slice(r.length):I.name;return l.prompts.includes(L)}).length:N.filter(I=>I.enabled!==!1).length,F=Array.isArray(l.resources)?D.filter(I=>I.enabled!==!1&&l.resources.includes(I.uri)).length:D.filter(I=>I.enabled!==!1).length;return{visibleTools:z,totalTools:S.length,visiblePrompts:h,totalPrompts:N.length,visibleResources:F,totalResources:D.length}},T=n.reduce((s,l)=>s+j(l).visibleTools,0);return e.jsxs("div",{className:"hub-card overflow-visible",children:[e.jsxs("div",{className:"flex items-start gap-3 px-4 py-3",style:{borderBottom:"1px solid var(--hub-line-2)"},children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{style:{fontSize:15,fontWeight:600,letterSpacing:"-0.015em"},children:i.name}),e.jsx("span",{className:"hub-mono",style:{fontSize:11,color:"var(--hub-ink-3)",padding:"0 6px",border:"1px solid var(--hub-line)",borderRadius:4,height:18,display:"inline-flex",alignItems:"center"},title:i.id,children:i.id})]}),i.description&&e.jsx("div",{style:{fontSize:12.5,color:"var(--hub-ink-3)",marginTop:2},children:i.description})]}),e.jsxs("div",{className:"flex items-center gap-1",ref:o,children:[e.jsxs("div",{className:"relative",children:[e.jsx("button",{onClick:()=>E(s=>!s),className:"hub-icon-btn sm",title:u("common.copy"),children:y?e.jsx(re,{size:13,className:"text-[var(--hub-ok)]"}):e.jsx(B,{size:13})}),C&&e.jsxs("div",{className:"absolute top-full right-0 mt-1 z-20 hub-card",style:{minWidth:160,padding:4},children:[e.jsxs("button",{onClick:()=>c(i.id),className:"flex items-center gap-2 w-full px-2.5 py-1.5 text-[13px] rounded-md hover:bg-[var(--hub-surface-hover)] text-left",children:[e.jsx(B,{size:12})," ",u("common.copyId")]}),e.jsxs("button",{onClick:()=>c(f),className:"flex items-center gap-2 w-full px-2.5 py-1.5 text-[13px] rounded-md hover:bg-[var(--hub-surface-hover)] text-left",children:[e.jsx(ae,{size:12})," ",u("common.copyUrl")]}),e.jsxs("button",{onClick:()=>c(JSON.stringify({mcpServers:{mcphub:{url:f,headers:{Authorization:"Bearer <your-access-token>"}}}},null,2)),className:"flex items-center gap-2 w-full px-2.5 py-1.5 text-[13px] rounded-md hover:bg-[var(--hub-surface-hover)] text-left",children:[e.jsx(le,{size:12})," ",u("common.copyJson")]})]})]}),e.jsx("button",{onClick:()=>t(i),className:"hub-icon-btn sm",title:u("groups.edit"),children:e.jsx(ne,{size:13})}),e.jsx("button",{onClick:()=>v(!0),className:"hub-icon-btn sm",title:u("groups.delete"),style:{color:"var(--hub-ink-3)"},children:e.jsx(oe,{size:13})})]})]}),e.jsxs("div",{className:"grid items-center gap-3 px-4 py-3",style:{gridTemplateColumns:"1fr 80px 1fr"},children:[e.jsx("div",{className:"flex flex-col gap-1.5",children:n.length===0?e.jsx("div",{style:{fontSize:12,color:"var(--hub-ink-3)"},children:u("groups.noServers")}):n.map(s=>{const l=j(s);return e.jsxs("div",{className:"flex items-center gap-2.5 px-2.5 py-1.5 rounded-md",style:{background:"var(--hub-bg-2)",border:"1px solid var(--hub-line-2)"},children:[e.jsx("span",{className:"inline-block flex-shrink-0",style:{width:6,height:6,borderRadius:50,background:s.status==="connected"?"var(--hub-ok)":s.status==="connecting"?"var(--hub-warn)":"var(--hub-err)"}}),e.jsx("span",{className:"hub-mono truncate flex-1",style:{fontSize:12.5},children:s.name}),e.jsxs("span",{className:"hub-mono hub-num flex-shrink-0",style:{fontSize:11,color:"var(--hub-ink-3)"},children:[l.visibleTools,"/",l.totalTools," tools"]})]},s.name)})}),e.jsxs("svg",{width:"80",height:"80",viewBox:"0 0 80 80",className:"self-center",children:[n.length===0?e.jsx("path",{d:"M0,40 C30,40 50,40 80,40",stroke:"var(--hub-line)",strokeWidth:"1",fill:"none",strokeDasharray:"3 3"}):n.map((s,l)=>{const r=12+60/Math.max(n.length,1)*(l+.5);return e.jsx("path",{d:`M0,${r} C 30,${r} 50,40 80,40`,stroke:"var(--hub-line)",strokeWidth:"1",fill:"none",strokeDasharray:"3 3"},l)}),e.jsx("circle",{cx:"80",cy:"40",r:"4",fill:"var(--hub-ink)"})]}),e.jsxs("div",{className:"px-3 py-2.5 rounded-md",style:{border:"1px solid var(--hub-line)",background:"var(--hub-bg-2)"},children:[e.jsx("div",{className:"hub-sect",style:{marginBottom:4},children:"endpoint"}),e.jsxs("div",{className:"hub-mono break-all",style:{fontSize:12,color:"var(--hub-ink-2)",lineHeight:1.4},children:[e.jsx("span",{style:{color:"var(--hub-ink-3)"},children:"/mcp/"}),e.jsx("b",{style:{color:"var(--hub-ink)",fontWeight:600},children:i.name})]}),e.jsx("div",{className:"flex gap-1.5 mt-2",children:e.jsxs("button",{className:"hub-btn sm flex-1 justify-center",onClick:()=>c(f),children:[e.jsx(B,{size:11})," ",u("common.copy")]})})]})]}),e.jsxs("div",{className:"flex justify-between items-center px-4 py-2",style:{borderTop:"1px solid var(--hub-line-2)",background:"var(--hub-bg-2)",fontSize:12,color:"var(--hub-ink-3)"},children:[e.jsxs("div",{className:"hub-mono",children:[e.jsx("span",{style:{color:"var(--hub-ink-2)"},children:n.length})," ",u("nav.servers").toLowerCase()," ·"," ",e.jsx("span",{style:{color:"var(--hub-ink-2)"},children:T})," ",u("server.tools").toLowerCase()]}),e.jsxs("button",{className:"hub-btn ghost sm",style:{color:"var(--hub-ink-3)"},onClick:()=>t(i),children:[u("groups.configureTools")||u("groups.edit"),e.jsx(ie,{size:11,style:{transform:"rotate(-90deg)"}})]})]}),e.jsx(ue,{isOpen:p,onClose:()=>v(!1),onConfirm:()=>{d(i.id),v(!1)},serverName:i.name,isGroup:!0})]})},je=({onSuccess:i,onCancel:m})=>{const{t}=P(),[d,u]=b.useState(""),[A,g]=b.useState(null),[k,x]=b.useState(!1),[p,v]=b.useState(null),y=`{
2
2
  "groups": [
3
3
  {
4
4
  "name": "AI Assistants",
@@ -30,4 +30,4 @@ Supports:
30
30
  - All groups will be imported in a single efficient batch operation.`,w=a=>{try{const n=JSON.parse(a.trim());if(!n.groups||!Array.isArray(n.groups))return g(t("groupImport.invalidFormat")),null;for(const j of n.groups)if(!j.name||typeof j.name!="string")return g(t("groupImport.missingName")),null;return n}catch{return g(t("groupImport.parseError")),null}},C=()=>{g(null);const a=w(d);a&&v(a.groups)},E=async()=>{if(p){x(!0),g(null);try{const a=await M("/groups/batch",{groups:p});if(a.success){const{successCount:n,failureCount:j,results:T}=a;if(j>0){const R=T.filter(s=>!s.success).map(s=>`${s.name}: ${s.message||t("groupImport.addFailed")}`);g(t("groupImport.partialSuccess",{count:n,total:p.length})+`
31
31
  `+R.join(`
32
32
  `))}n>0&&i()}else g(a.message||t("groupImport.importFailed"))}catch(a){console.error("Import error:",a),g(t("groupImport.importFailed"))}finally{x(!1)}}},o=a=>e.jsx("span",{className:"text-gray-500 ml-2",children:t(`groups.${a}`)}),c=(a,n)=>{if(!n||n==="all")return null;const j=Array.isArray(n)?n.join(", "):n;return e.jsx("span",{className:"text-gray-500 ml-2",children:t(`groups.${a}`,{items:j})})},f=a=>!a||a.length===0?e.jsx("span",{className:"text-gray-500",children:t("groups.noServers")}):e.jsx("div",{className:"space-y-1",children:a.map((n,j)=>typeof n=="string"?e.jsxs("div",{className:"text-sm",children:["• ",n]},j):e.jsxs("div",{className:"text-sm",children:["• ",n.name,n.tools&&n.tools!=="all"&&e.jsxs("span",{className:"text-gray-500 ml-2",children:["(",Array.isArray(n.tools)?n.tools.join(", "):n.tools,")"]}),n.tools==="all"&&o("previewAllTools"),c("previewPrompts",n.prompts),n.prompts==="all"&&o("previewAllPrompts"),c("previewResources",n.resources),n.resources==="all"&&o("previewAllResources")]},j))});return e.jsx("div",{className:"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4",children:e.jsxs("div",{className:"bg-white dark:bg-gray-800 shadow rounded-lg p-6 w-full max-w-4xl max-h-[90vh] overflow-y-auto",children:[e.jsxs("div",{className:"flex justify-between items-center mb-6",children:[e.jsx("h2",{className:"text-xl font-semibold text-gray-900",children:t("groupImport.title")}),e.jsx("button",{onClick:m,className:"text-gray-500 hover:text-gray-700",children:"✕"})]}),A&&e.jsx("div",{className:"mb-4 bg-red-50 border-l-4 border-red-500 p-4 rounded",children:e.jsx("p",{className:"text-red-700 whitespace-pre-wrap",children:A})}),p?e.jsxs("div",{children:[e.jsxs("div",{className:"mb-4",children:[e.jsx("h3",{className:"text-lg font-medium text-gray-900 mb-3",children:t("groupImport.previewTitle")}),e.jsx("div",{className:"space-y-3",children:p.map((a,n)=>e.jsx("div",{className:"bg-gray-50 dark:bg-gray-800 p-4 rounded-lg border border-gray-200 dark:border-gray-700",children:e.jsx("div",{className:"flex items-start justify-between",children:e.jsxs("div",{className:"flex-1",children:[e.jsx("h4",{className:"font-medium text-gray-900",children:a.name}),a.description&&e.jsx("p",{className:"text-sm text-gray-600 mt-1",children:a.description}),e.jsxs("div",{className:"mt-2 text-sm text-gray-600",children:[e.jsxs("strong",{children:[t("groups.servers"),":"]}),e.jsx("div",{className:"mt-1",children:f(a.servers)})]})]})})},n))})]}),e.jsxs("div",{className:"flex justify-end space-x-4",children:[e.jsx("button",{onClick:()=>v(null),disabled:k,className:"hub-btn",children:t("common.back")}),e.jsx("button",{onClick:E,disabled:k,className:"hub-btn primary",children:k?e.jsxs(e.Fragment,{children:[e.jsxs("svg",{className:"animate-spin h-4 w-4 mr-2",xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",children:[e.jsx("circle",{className:"opacity-25",cx:"12",cy:"12",r:"10",stroke:"currentColor",strokeWidth:"4"}),e.jsx("path",{className:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"})]}),t("groupImport.importing")]}):t("groupImport.import")})]})]}):e.jsxs("div",{children:[e.jsxs("div",{className:"mb-4",children:[e.jsx("label",{className:"block text-sm font-medium text-gray-700 mb-2",children:t("groupImport.inputLabel")}),e.jsx("textarea",{value:d,onChange:a=>u(a.target.value),className:"w-full h-96 px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 font-mono text-sm",placeholder:y}),e.jsx("p",{className:"text-xs text-gray-500 mt-2",children:t("groupImport.inputHelp")})]}),e.jsxs("div",{className:"flex justify-end space-x-4",children:[e.jsx("button",{onClick:m,className:"hub-btn",children:t("common.cancel")}),e.jsx("button",{onClick:C,disabled:!d.trim(),className:"hub-btn primary",children:t("groupImport.preview")})]})]})]})})},ve=({groups:i,onCancel:m})=>{const{t}=P(),[d,u]=b.useState(""),[A,g]=b.useState(""),[k,x]=b.useState([]),[p,v]=b.useState(!1),[y,w]=b.useState(!1),[C,E]=b.useState(null),o=a=>{x(n=>n.includes(a)?n.filter(j=>j!==a):[...n,a])},c=()=>{k.length===i.length?x([]):x(i.map(a=>a.id))},f=async()=>{if(!d.trim()){E(t("template.nameRequired"));return}w(!0),E(null);try{const a=await M("/templates/export",{name:d.trim(),description:A.trim()||void 0,groupIds:k.length>0?k:void 0,includeDisabledServers:p});if(a.success&&a.data){const n=a.data,j=new Blob([JSON.stringify(n,null,2)],{type:"application/json"}),T=URL.createObjectURL(j),R=document.createElement("a");R.href=T,R.download=`${n.name.replace(/[^a-zA-Z0-9-_]/g,"_")}.mcphub-template.json`,document.body.appendChild(R),R.click(),document.body.removeChild(R),URL.revokeObjectURL(T),m()}else E(a.message||t("template.exportFailed"))}catch(a){console.error("Export error:",a),E(t("template.exportFailed"))}finally{w(!1)}};return e.jsx("div",{className:"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4",children:e.jsxs("div",{className:"bg-white dark:bg-gray-800 shadow rounded-lg p-6 w-full max-w-3xl max-h-[90vh] overflow-y-auto",children:[e.jsxs("div",{className:"flex justify-between items-center mb-6",children:[e.jsx("h2",{className:"text-xl font-semibold text-gray-900",children:t("template.exportTitle")}),e.jsx("button",{onClick:m,className:"text-gray-500 hover:text-gray-700",children:"✕"})]}),C&&e.jsx("div",{className:"mb-4 bg-red-50 border-l-4 border-red-500 p-4 rounded",children:e.jsx("p",{className:"text-red-700",children:C})}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsxs("label",{className:"block text-sm font-medium text-gray-700 mb-1",children:[t("template.name")," *"]}),e.jsx("input",{type:"text",value:d,onChange:a=>u(a.target.value),className:"w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500",placeholder:t("template.namePlaceholder")})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-700 mb-1",children:t("template.description")}),e.jsx("input",{type:"text",value:A,onChange:a=>g(a.target.value),className:"w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500",placeholder:t("template.descriptionPlaceholder")})]}),e.jsxs("div",{children:[e.jsxs("div",{className:"flex justify-between items-center mb-2",children:[e.jsx("label",{className:"block text-sm font-medium text-gray-700",children:t("template.selectGroups")}),e.jsx("button",{onClick:c,className:"text-sm text-blue-600 hover:text-blue-800",children:k.length===i.length?t("template.deselectAll"):t("template.selectAll")})]}),e.jsx("p",{className:"text-xs text-gray-500 mb-2",children:t("template.selectGroupsHelp")}),e.jsx("div",{className:"border border-gray-200 dark:border-gray-700 rounded-md max-h-48 overflow-y-auto",children:i.map(a=>e.jsxs("label",{className:"flex items-center px-3 py-2 hover:bg-gray-50 dark:bg-gray-800 dark:hover:bg-gray-700 cursor-pointer",children:[e.jsx("input",{type:"checkbox",checked:k.includes(a.id),onChange:()=>o(a.id),className:"mr-3 h-4 w-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"}),e.jsxs("div",{children:[e.jsx("span",{className:"text-sm font-medium text-gray-900",children:a.name}),a.description&&e.jsx("span",{className:"text-xs text-gray-500 ml-2",children:a.description})]})]},a.id))})]}),e.jsxs("label",{className:"flex items-center space-x-2 cursor-pointer",children:[e.jsx("input",{type:"checkbox",checked:p,onChange:a=>v(a.target.checked),className:"h-4 w-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"}),e.jsx("span",{className:"text-sm text-gray-700",children:t("template.includeDisabled")})]})]}),e.jsx("div",{className:"mt-4 p-3 bg-blue-50 border border-blue-200 rounded-md",children:e.jsx("p",{className:"text-sm text-blue-700",children:t("template.exportNote")})}),e.jsxs("div",{className:"flex justify-end space-x-4 mt-6",children:[e.jsx("button",{onClick:m,className:"hub-btn",children:t("common.cancel")}),e.jsx("button",{onClick:f,disabled:y||!d.trim(),className:"hub-btn primary",children:t(y?"template.exporting":"template.export")})]})]})})},Ne=({onSuccess:i,onCancel:m})=>{const{t}=P(),[d,u]=b.useState(null),[A,g]=b.useState(null),[k,x]=b.useState(!1),[p,v]=b.useState(null),y=b.useRef(null),w=o=>{var a;g(null),u(null),v(null);const c=(a=o.target.files)==null?void 0:a[0];if(!c)return;const f=new FileReader;f.onload=n=>{var j;try{const T=JSON.parse((j=n.target)==null?void 0:j.result);if(!T.version||!T.name||!T.servers||!T.groups){g(t("template.invalidFormat"));return}u(T)}catch{g(t("template.parseError"))}},f.readAsText(c)},C=o=>{if(g(null),u(null),v(null),!!o.trim())try{const c=JSON.parse(o.trim());if(!c.version||!c.name||!c.servers||!c.groups){g(t("template.invalidFormat"));return}u(c)}catch{g(t("template.parseError"))}},E=async()=>{if(d){x(!0),g(null);try{const o=await M("/templates/import",d);o.data?(v(o.data),o.data.success&&i()):g(o.message||t("template.importFailed"))}catch(o){console.error("Import error:",o),g(t("template.importFailed"))}finally{x(!1)}}};return e.jsx("div",{className:"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4",children:e.jsxs("div",{className:"bg-white dark:bg-gray-800 shadow rounded-lg p-6 w-full max-w-4xl max-h-[90vh] overflow-y-auto",children:[e.jsxs("div",{className:"flex justify-between items-center mb-6",children:[e.jsx("h2",{className:"text-xl font-semibold text-gray-900",children:t("template.importTitle")}),e.jsx("button",{onClick:m,className:"text-gray-500 hover:text-gray-700",children:"✕"})]}),A&&e.jsx("div",{className:"mb-4 bg-red-50 border-l-4 border-red-500 p-4 rounded",children:e.jsx("p",{className:"text-red-700",children:A})}),p&&e.jsxs("div",{className:`mb-4 p-4 rounded border-l-4 ${p.success?"bg-green-50 border-green-500":"bg-yellow-50 border-yellow-500"}`,children:[e.jsx("p",{className:p.success?"text-green-700":"text-yellow-700",children:t("template.importResult",{serversCreated:p.serversCreated,serversSkipped:p.serversSkipped,groupsCreated:p.groupsCreated,groupsSkipped:p.groupsSkipped})}),p.requiredEnvVars.length>0&&e.jsxs("div",{className:"mt-2 p-2 bg-orange-50 border border-orange-200 rounded",children:[e.jsx("p",{className:"text-sm font-medium text-orange-800",children:t("template.envVarsNeeded")}),e.jsx("ul",{className:"mt-1 text-sm text-orange-700",children:p.requiredEnvVars.map(o=>e.jsx("li",{className:"font-mono",children:o},o))})]})]}),d?e.jsxs("div",{children:[e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"p-3 bg-gray-50 dark:bg-gray-800 rounded-md",children:[e.jsx("h3",{className:"font-medium text-gray-900",children:d.name}),d.description&&e.jsx("p",{className:"text-sm text-gray-600 mt-1",children:d.description}),e.jsxs("p",{className:"text-xs text-gray-500 mt-1",children:[t("template.version"),": ",d.version," | ",t("template.createdAt"),":"," ",new Date(d.createdAt).toLocaleDateString()]})]}),e.jsxs("div",{children:[e.jsxs("h4",{className:"text-sm font-medium text-gray-700 mb-2",children:[t("template.servers")," (",Object.keys(d.servers).length,")"]}),e.jsx("div",{className:"border border-gray-200 dark:border-gray-700 rounded-md divide-y divide-gray-200 dark:divide-gray-700 max-h-40 overflow-y-auto",children:Object.entries(d.servers).map(([o,c])=>e.jsxs("div",{className:"px-3 py-2",children:[e.jsx("span",{className:"text-sm font-medium text-gray-900",children:o}),e.jsx("span",{className:"text-xs text-gray-500 ml-2",children:c.type||"stdio"})]},o))})]}),e.jsxs("div",{children:[e.jsxs("h4",{className:"text-sm font-medium text-gray-700 mb-2",children:[t("template.groups")," (",d.groups.length,")"]}),e.jsx("div",{className:"border border-gray-200 dark:border-gray-700 rounded-md divide-y divide-gray-200 dark:divide-gray-700 max-h-40 overflow-y-auto",children:d.groups.map((o,c)=>e.jsxs("div",{className:"px-3 py-2",children:[e.jsx("span",{className:"text-sm font-medium text-gray-900",children:o.name}),o.description&&e.jsx("span",{className:"text-xs text-gray-500 ml-2",children:o.description}),e.jsxs("div",{className:"text-xs text-gray-500 mt-1",children:[o.servers.length," ",t("template.serversInGroup")]})]},c))})]}),d.requiredEnvVars.length>0&&e.jsxs("div",{className:"p-3 bg-orange-50 border border-orange-200 rounded-md",children:[e.jsx("h4",{className:"text-sm font-medium text-orange-800",children:t("template.envVarsNeeded")}),e.jsx("ul",{className:"mt-1 text-sm text-orange-700 font-mono",children:d.requiredEnvVars.map(o=>e.jsx("li",{children:o},o))})]})]}),e.jsxs("div",{className:"flex justify-end space-x-4 mt-6",children:[e.jsx("button",{onClick:()=>{u(null),v(null),y.current&&(y.current.value="")},className:"hub-btn",children:t("common.back")}),e.jsx("button",{onClick:E,disabled:k,className:"hub-btn primary",children:t(k?"template.importing":"template.import")})]})]}):e.jsxs("div",{children:[e.jsxs("div",{className:"mb-4",children:[e.jsx("div",{className:"flex items-center justify-between mb-2",children:e.jsx("label",{className:"block text-sm font-medium text-gray-700",children:t("template.uploadFile")})}),e.jsx("div",{className:"flex items-center space-x-4",children:e.jsx("input",{ref:y,type:"file",accept:".json",onChange:w,className:"block text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-semibold file:bg-blue-50 file:text-blue-700 hover:file:bg-blue-100"})})]}),e.jsxs("div",{className:"relative my-4",children:[e.jsx("div",{className:"absolute inset-0 flex items-center",children:e.jsx("div",{className:"w-full border-t border-gray-300"})}),e.jsx("div",{className:"relative flex justify-center text-sm",children:e.jsx("span",{className:"bg-white dark:bg-gray-800 px-2 text-gray-500",children:t("template.or")})})]}),e.jsxs("div",{className:"mb-4",children:[e.jsx("label",{className:"block text-sm font-medium text-gray-700 mb-2",children:t("template.pasteJson")}),e.jsx("textarea",{className:"w-full h-64 px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 font-mono text-sm",placeholder:t("template.pastePlaceholder"),onChange:o=>C(o.target.value)})]}),e.jsx("div",{className:"flex justify-end space-x-4",children:e.jsx("button",{onClick:m,className:"hub-btn",children:t("common.cancel")})})]})]})})},ze=()=>{const{t:i}=P(),{groups:m,loading:t,error:d,setError:u,deleteGroup:A,triggerRefresh:g}=q(),{allServers:k}=J({refreshOnMount:!0}),[x,p]=b.useState(null),[v,y]=b.useState(!1),[w,C]=b.useState(!1),[E,o]=b.useState(!1),[c,f]=b.useState(!1),a=async n=>{const j=await A(n);(!j||!j.success)&&u((j==null?void 0:j.message)||i("groups.deleteError"))};return e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-end justify-between gap-4 mb-6",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"hub-h1",children:i("pages.groups.title")}),e.jsxs("p",{className:"hub-sub",children:[e.jsx("span",{className:"hub-num",children:m.length})," ",i("nav.groups").toLowerCase()]})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs("button",{className:"hub-btn",onClick:()=>C(!0),children:[e.jsx(V,{size:13})," ",i("groupImport.button")]}),e.jsxs("button",{className:"hub-btn",onClick:()=>o(!0),children:[e.jsx(ce,{size:13})," ",i("template.exportButton")]}),e.jsxs("button",{className:"hub-btn",onClick:()=>f(!0),children:[e.jsx(V,{size:13})," ",i("template.importButton")]}),e.jsxs("button",{className:"hub-btn primary",onClick:()=>y(!0),children:[e.jsx(_,{size:13})," ",i("groups.add")]})]})]}),d&&e.jsxs("div",{className:"hub-card flex items-center justify-between gap-3 mb-4",style:{padding:"10px 14px",borderColor:"oklch(0.85 0.1 25)",background:"oklch(0.97 0.03 25)",color:"oklch(0.4 0.18 25)"},children:[e.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[e.jsx(de,{size:14,className:"flex-shrink-0"}),e.jsx("span",{className:"truncate text-[13px]",children:d})]}),e.jsx("button",{className:"hub-icon-btn sm",onClick:()=>u(null),children:e.jsx(me,{size:13})})]}),t?e.jsx("div",{className:"hub-card p-6 text-center",style:{color:"var(--hub-ink-3)"},children:i("app.loading")}):m.length===0?e.jsx("div",{className:"hub-card p-10 text-center",style:{color:"var(--hub-ink-3)"},children:i("groups.noGroups")}):e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-3.5",children:[m.map(n=>e.jsx(ye,{group:n,servers:k,onEdit:p,onDelete:a},n.id)),e.jsx("button",{onClick:()=>y(!0),className:"flex items-center justify-center text-[var(--hub-ink-3)] hover:text-[var(--hub-ink-2)] transition-colors",style:{border:"1px dashed var(--hub-line)",borderRadius:10,minHeight:200,background:"transparent",cursor:"pointer"},children:e.jsxs("div",{className:"text-center",children:[e.jsx("div",{className:"grid place-items-center mx-auto mb-2",style:{width:36,height:36,borderRadius:10,border:"1px solid var(--hub-line)"},children:e.jsx(_,{size:16})}),e.jsx("div",{style:{fontSize:13,fontWeight:500,color:"var(--hub-ink-2)"},children:i("groups.add")}),e.jsx("div",{style:{fontSize:12,marginTop:2},children:i("groups.addNew")})]})})]}),v&&e.jsx(xe,{onAdd:()=>{y(!1),g()},onCancel:()=>y(!1)}),w&&e.jsx(je,{onSuccess:()=>{C(!1),g()},onCancel:()=>C(!1)}),x&&e.jsx(he,{group:x,onEdit:()=>{p(null),g()},onCancel:()=>p(null)}),E&&e.jsx(ve,{groups:m,onCancel:()=>o(!1)}),c&&e.jsx(Ne,{onSuccess:()=>{f(!1),g()},onCancel:()=>f(!1)})]})};export{ze as default};
33
- //# sourceMappingURL=GroupsPage-D5J8mmwv.js.map
33
+ //# sourceMappingURL=GroupsPage-Bx3Yi-md.js.map