@samanhappy/mcphub 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/README.fr.md +6 -4
  2. package/README.md +24 -4
  3. package/README.zh.md +25 -4
  4. package/bin/cli.js +64 -50
  5. package/dist/betterAuth.js +21 -0
  6. package/dist/betterAuth.js.map +1 -1
  7. package/dist/cli/call-arguments.js +81 -0
  8. package/dist/cli/call-arguments.js.map +1 -0
  9. package/dist/cli/commands/call.js +75 -0
  10. package/dist/cli/commands/call.js.map +1 -0
  11. package/dist/cli/commands/config.js +132 -0
  12. package/dist/cli/commands/config.js.map +1 -0
  13. package/dist/cli/commands/discover.js +127 -0
  14. package/dist/cli/commands/discover.js.map +1 -0
  15. package/dist/cli/commands/export.js +20 -0
  16. package/dist/cli/commands/export.js.map +1 -0
  17. package/dist/cli/commands/groups.js +107 -0
  18. package/dist/cli/commands/groups.js.map +1 -0
  19. package/dist/cli/commands/install.js +173 -0
  20. package/dist/cli/commands/install.js.map +1 -0
  21. package/dist/cli/commands/keys.js +91 -0
  22. package/dist/cli/commands/keys.js.map +1 -0
  23. package/dist/cli/commands/login.js +70 -0
  24. package/dist/cli/commands/login.js.map +1 -0
  25. package/dist/cli/commands/servers.js +142 -0
  26. package/dist/cli/commands/servers.js.map +1 -0
  27. package/dist/cli/commands/tools.js +162 -0
  28. package/dist/cli/commands/tools.js.map +1 -0
  29. package/dist/cli/context.js +44 -0
  30. package/dist/cli/context.js.map +1 -0
  31. package/dist/cli/errors.js +19 -0
  32. package/dist/cli/errors.js.map +1 -0
  33. package/dist/cli/help.js +157 -0
  34. package/dist/cli/help.js.map +1 -0
  35. package/dist/cli/http.js +93 -0
  36. package/dist/cli/http.js.map +1 -0
  37. package/dist/cli/main.js +81 -0
  38. package/dist/cli/main.js.map +1 -0
  39. package/dist/cli/output.js +47 -0
  40. package/dist/cli/output.js.map +1 -0
  41. package/dist/cli/parse-args.js +103 -0
  42. package/dist/cli/parse-args.js.map +1 -0
  43. package/dist/cli/profile.js +109 -0
  44. package/dist/cli/profile.js.map +1 -0
  45. package/dist/cli/prompts.js +56 -0
  46. package/dist/cli/prompts.js.map +1 -0
  47. package/dist/controllers/oauthServerController.js +37 -1
  48. package/dist/controllers/oauthServerController.js.map +1 -1
  49. package/dist/controllers/serverController.js +3 -0
  50. package/dist/controllers/serverController.js.map +1 -1
  51. package/dist/dao/ActivityDao.js +2 -0
  52. package/dist/dao/ActivityDao.js.map +1 -1
  53. package/dist/dao/ServerDaoDbImpl.js +3 -0
  54. package/dist/dao/ServerDaoDbImpl.js.map +1 -1
  55. package/dist/db/connection.js +48 -4
  56. package/dist/db/connection.js.map +1 -1
  57. package/dist/db/entities/Activity.js +4 -0
  58. package/dist/db/entities/Activity.js.map +1 -1
  59. package/dist/db/entities/Server.js +4 -0
  60. package/dist/db/entities/Server.js.map +1 -1
  61. package/dist/db/entities/VectorEmbedding.js +2 -5
  62. package/dist/db/entities/VectorEmbedding.js.map +1 -1
  63. package/dist/db/repositories/VectorEmbeddingRepository.js +100 -34
  64. package/dist/db/repositories/VectorEmbeddingRepository.js.map +1 -1
  65. package/dist/services/activityLoggingService.js +1 -0
  66. package/dist/services/activityLoggingService.js.map +1 -1
  67. package/dist/services/betterAuthConfig.js +18 -1
  68. package/dist/services/betterAuthConfig.js.map +1 -1
  69. package/dist/services/dataService.js +10 -1
  70. package/dist/services/dataService.js.map +1 -1
  71. package/dist/services/mcpService.js +46 -12
  72. package/dist/services/mcpService.js.map +1 -1
  73. package/dist/services/vectorSearchService.js +16 -3
  74. package/dist/services/vectorSearchService.js.map +1 -1
  75. package/dist/utils/migration.js +1 -0
  76. package/dist/utils/migration.js.map +1 -1
  77. package/dist/utils/rateLimit.js +3 -3
  78. package/dist/utils/serverConfigPersistence.js +5 -0
  79. package/dist/utils/serverConfigPersistence.js.map +1 -1
  80. package/frontend/dist/assets/ActivityPage-B1B9ySGe.js +2 -0
  81. package/frontend/dist/assets/ActivityPage-B1B9ySGe.js.map +1 -0
  82. package/frontend/dist/assets/Dashboard-CYzpYZ1d.js +2 -0
  83. package/frontend/dist/assets/Dashboard-CYzpYZ1d.js.map +1 -0
  84. package/frontend/dist/assets/{EndpointCopy-C59moJ3Y.js → EndpointCopy-DVmlWW-s.js} +2 -2
  85. package/frontend/dist/assets/{EndpointCopy-C59moJ3Y.js.map → EndpointCopy-DVmlWW-s.js.map} +1 -1
  86. package/frontend/dist/assets/{GroupsPage-Bhg51kbu.js → GroupsPage-CsyoUc8S.js} +2 -2
  87. package/frontend/dist/assets/{GroupsPage-Bhg51kbu.js.map → GroupsPage-CsyoUc8S.js.map} +1 -1
  88. package/frontend/dist/assets/LoginPage-C3t8hbb2.js +2 -0
  89. package/frontend/dist/assets/LoginPage-C3t8hbb2.js.map +1 -0
  90. package/frontend/dist/assets/{LogsPage-HBGNLtyN.js → LogsPage-DOZeagVs.js} +2 -2
  91. package/frontend/dist/assets/{LogsPage-HBGNLtyN.js.map → LogsPage-DOZeagVs.js.map} +1 -1
  92. package/frontend/dist/assets/{MarketPage-C5ATZ4WS.js → MarketPage-kMEHUGfJ.js} +2 -2
  93. package/frontend/dist/assets/{MarketPage-C5ATZ4WS.js.map → MarketPage-kMEHUGfJ.js.map} +1 -1
  94. package/frontend/dist/assets/{PromptsPage-DUge8OO4.js → PromptsPage-D7JYoTav.js} +2 -2
  95. package/frontend/dist/assets/{PromptsPage-DUge8OO4.js.map → PromptsPage-D7JYoTav.js.map} +1 -1
  96. package/frontend/dist/assets/{ResourcesPage-5J3JYGVC.js → ResourcesPage-BlwePI9a.js} +2 -2
  97. package/frontend/dist/assets/{ResourcesPage-5J3JYGVC.js.map → ResourcesPage-BlwePI9a.js.map} +1 -1
  98. package/frontend/dist/assets/ServersPage-DrkPpCgK.js +37 -0
  99. package/frontend/dist/assets/ServersPage-DrkPpCgK.js.map +1 -0
  100. package/frontend/dist/assets/{SettingsPage-BeLZKC1d.js → SettingsPage-BWigWLml.js} +2 -2
  101. package/frontend/dist/assets/{SettingsPage-BeLZKC1d.js.map → SettingsPage-BWigWLml.js.map} +1 -1
  102. package/frontend/dist/assets/{StatusDot-DR803YdX.js → StatusDot-BDBIaafQ.js} +2 -2
  103. package/frontend/dist/assets/{StatusDot-DR803YdX.js.map → StatusDot-BDBIaafQ.js.map} +1 -1
  104. package/frontend/dist/assets/{ToggleGroup-DE8t8Ni4.js → ToggleGroup-OOcsllhw.js} +2 -2
  105. package/frontend/dist/assets/{ToggleGroup-DE8t8Ni4.js.map → ToggleGroup-OOcsllhw.js.map} +1 -1
  106. package/frontend/dist/assets/{UsersPage-CMscqAmn.js → UsersPage-DL8E7KtW.js} +2 -2
  107. package/frontend/dist/assets/{UsersPage-CMscqAmn.js.map → UsersPage-DL8E7KtW.js.map} +1 -1
  108. package/frontend/dist/assets/index-C7wNc_3N.js +3 -0
  109. package/frontend/dist/assets/index-C7wNc_3N.js.map +1 -0
  110. package/frontend/dist/assets/index-D0OIBhmN.css +1 -0
  111. package/frontend/dist/assets/{resourceService-BFMkDDIh.js → resourceService-B-U4FKGB.js} +2 -2
  112. package/frontend/dist/assets/{resourceService-BFMkDDIh.js.map → resourceService-B-U4FKGB.js.map} +1 -1
  113. package/frontend/dist/assets/{useServerData-BnLmpLAC.js → useServerData-DYoDryJj.js} +2 -2
  114. package/frontend/dist/assets/{useServerData-BnLmpLAC.js.map → useServerData-DYoDryJj.js.map} +1 -1
  115. package/frontend/dist/assets/useSettingsData-6utb1Z46.js +2 -0
  116. package/frontend/dist/assets/{useSettingsData-Cqi9d7Ug.js.map → useSettingsData-6utb1Z46.js.map} +1 -1
  117. package/frontend/dist/assets/{variableDetection-BigiltQM.js → variableDetection-DsYuiOB_.js} +3 -3
  118. package/frontend/dist/assets/variableDetection-DsYuiOB_.js.map +1 -0
  119. package/frontend/dist/index.html +2 -2
  120. package/package.json +2 -1
  121. package/frontend/dist/assets/ActivityPage-VwilVMvp.js +0 -2
  122. package/frontend/dist/assets/ActivityPage-VwilVMvp.js.map +0 -1
  123. package/frontend/dist/assets/Dashboard-DuBJTbbA.js +0 -2
  124. package/frontend/dist/assets/Dashboard-DuBJTbbA.js.map +0 -1
  125. package/frontend/dist/assets/LoginPage-C8RkMoJN.js +0 -2
  126. package/frontend/dist/assets/LoginPage-C8RkMoJN.js.map +0 -1
  127. package/frontend/dist/assets/ServersPage-DtnlfwJF.js +0 -37
  128. package/frontend/dist/assets/ServersPage-DtnlfwJF.js.map +0 -1
  129. package/frontend/dist/assets/index-B9cW2F0H.js +0 -3
  130. package/frontend/dist/assets/index-B9cW2F0H.js.map +0 -1
  131. package/frontend/dist/assets/index-Crcbkt8x.css +0 -1
  132. package/frontend/dist/assets/useSettingsData-Cqi9d7Ug.js +0 -2
  133. package/frontend/dist/assets/variableDetection-BigiltQM.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"variableDetection-DsYuiOB_.js","sources":["../../src/utils/serverFormPayload.ts","../../src/components/ServerForm.tsx","../../src/utils/variableDetection.ts"],"sourcesContent":["import type { EnvVar, ServerConfig, ServerFormData } from '../types';\n\ntype ServerType = NonNullable<ServerConfig['type']>;\n\ninterface BuildServerPayloadInput {\n formData: ServerFormData;\n serverType: ServerType;\n envVars: EnvVar[];\n headerVars: EnvVar[];\n}\n\nconst buildKeyValueRecord = (vars: EnvVar[]): Record<string, string> => {\n const record: Record<string, string> = {};\n\n vars.forEach(({ key, value }) => {\n const trimmedKey = key.trim();\n if (trimmedKey) {\n record[trimmedKey] = value;\n }\n });\n\n return record;\n};\n\nconst parseCommaSeparatedList = (value?: string): string[] => {\n if (!value) {\n return [];\n }\n\n return value\n .split(',')\n .map((item) => item.trim())\n .filter((item) => item.length > 0);\n};\n\nconst buildOptions = (options?: ServerFormData['options']) => {\n const nextOptions: NonNullable<ServerFormData['options']> = {};\n\n if (options?.timeout && options.timeout !== 60000) {\n nextOptions.timeout = options.timeout;\n }\n\n if (typeof options?.resetTimeoutOnProgress === 'boolean') {\n nextOptions.resetTimeoutOnProgress = options.resetTimeoutOnProgress;\n }\n\n if (options?.maxTotalTimeout) {\n nextOptions.maxTotalTimeout = options.maxTotalTimeout;\n }\n\n return nextOptions;\n};\n\nconst buildOAuthConfig = (\n oauth?: ServerFormData['oauth'],\n): Partial<NonNullable<ServerConfig['oauth']>> => {\n if (!oauth) {\n return {};\n }\n\n const nextOAuth: Partial<NonNullable<ServerConfig['oauth']>> = {};\n const clientId = oauth.clientId?.trim();\n const clientSecret = oauth.clientSecret?.trim();\n const scopes = oauth.scopes?.trim();\n const accessToken = oauth.accessToken?.trim();\n const refreshToken = oauth.refreshToken?.trim();\n const authorizationEndpoint = oauth.authorizationEndpoint?.trim();\n const tokenEndpoint = oauth.tokenEndpoint?.trim();\n const resource = oauth.resource?.trim();\n\n if (clientId) nextOAuth.clientId = clientId;\n if (clientSecret) nextOAuth.clientSecret = clientSecret;\n if (scopes) {\n const parsedScopes = scopes\n .split(/[\\s,]+/)\n .map((scope) => scope.trim())\n .filter((scope) => scope.length > 0);\n\n if (parsedScopes.length > 0) {\n nextOAuth.scopes = parsedScopes;\n }\n }\n if (accessToken) nextOAuth.accessToken = accessToken;\n if (refreshToken) nextOAuth.refreshToken = refreshToken;\n if (authorizationEndpoint) nextOAuth.authorizationEndpoint = authorizationEndpoint;\n if (tokenEndpoint) nextOAuth.tokenEndpoint = tokenEndpoint;\n if (resource) nextOAuth.resource = resource;\n\n return nextOAuth;\n};\n\nconst buildOpenApiConfig = (formData: ServerFormData): NonNullable<ServerConfig['openapi']> => {\n const openapi: NonNullable<ServerConfig['openapi']> = {\n version: formData.openapi?.version || '3.1.0',\n passthroughHeaders: parseCommaSeparatedList(formData.openapi?.passthroughHeaders),\n };\n\n if (formData.openapi?.inputMode === 'url') {\n openapi.url = formData.openapi?.url || '';\n } else if (formData.openapi?.inputMode === 'schema' && formData.openapi?.schema) {\n try {\n openapi.schema = JSON.parse(formData.openapi.schema);\n } catch {\n throw new Error('Invalid JSON schema format');\n }\n }\n\n if (formData.openapi?.securityType && formData.openapi.securityType !== 'none') {\n openapi.security = {\n type: formData.openapi.securityType,\n ...(formData.openapi.securityType === 'apiKey' && {\n apiKey: {\n name: formData.openapi.apiKeyName || '',\n in: formData.openapi.apiKeyIn || 'header',\n value: formData.openapi.apiKeyValue || '',\n },\n }),\n ...(formData.openapi.securityType === 'http' && {\n http: {\n scheme: formData.openapi.httpScheme || 'bearer',\n credentials: formData.openapi.httpCredentials || '',\n },\n }),\n ...(formData.openapi.securityType === 'oauth2' && {\n oauth2: {\n token: formData.openapi.oauth2Token || '',\n },\n }),\n ...(formData.openapi.securityType === 'openIdConnect' && {\n openIdConnect: {\n url: formData.openapi.openIdConnectUrl || '',\n token: formData.openapi.openIdConnectToken || '',\n },\n }),\n };\n }\n\n return openapi;\n};\n\nexport const buildServerPayload = ({\n formData,\n serverType,\n envVars,\n headerVars,\n}: BuildServerPayloadInput) => {\n const env = buildKeyValueRecord(envVars);\n const headers = buildKeyValueRecord(headerVars);\n const options = buildOptions(formData.options);\n const description = formData.description?.trim() || '';\n\n const config: Partial<ServerConfig> = {\n type: serverType,\n description,\n options,\n visibility: formData.visibility ?? 'private',\n };\n\n if (serverType === 'openapi') {\n config.headers = headers;\n config.openapi = buildOpenApiConfig(formData);\n } else if (serverType === 'sse' || serverType === 'streamable-http') {\n config.url = formData.url.trim();\n config.env = env;\n config.headers = headers;\n config.passthroughHeaders = parseCommaSeparatedList(formData.passthroughHeaders);\n config.oauth = buildOAuthConfig(formData.oauth);\n config.enableKeepAlive = formData.keepAlive?.enabled || false;\n config.keepAliveInterval = formData.keepAlive?.enabled\n ? formData.keepAlive.interval || 60000\n : undefined;\n } else {\n config.command = formData.command.trim();\n config.args = formData.args;\n config.env = env;\n }\n\n return {\n name: formData.name.trim(),\n config,\n };\n};","import { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { X } from 'lucide-react';\nimport { Server, EnvVar, ServerFormData } from '@/types';\nimport { buildServerPayload } from '../utils/serverFormPayload';\n\ninterface ServerFormProps {\n onSubmit: (payload: any) => void;\n onCancel: () => void;\n initialData?: Server | null;\n modalTitle: string;\n formError?: string | null;\n}\n\nconst ServerForm = ({\n onSubmit,\n onCancel,\n initialData = null,\n modalTitle,\n formError = null,\n}: ServerFormProps) => {\n const { t } = useTranslation();\n\n // Determine the initial server type from the initialData\n const getInitialServerType = () => {\n if (!initialData || !initialData.config) return 'stdio';\n\n if (initialData.config.type) {\n return initialData.config.type; // Use explicit type if available\n } else if (initialData.config.url) {\n return 'sse'; // Fallback to SSE if URL exists\n } else {\n return 'stdio'; // Default to stdio\n }\n };\n\n const getInitialServerEnvVars = (data: Server | null): EnvVar[] => {\n if (!data || !data.config || !data.config.env) return [];\n\n return Object.entries(data.config.env).map(([key, value]) => ({\n key,\n value,\n description: '', // You can set a default description if needed\n }));\n };\n\n const getInitialOAuthConfig = (data: Server | null): ServerFormData['oauth'] => {\n const oauth = data?.config?.oauth;\n return {\n clientId: oauth?.clientId || '',\n clientSecret: oauth?.clientSecret || '',\n scopes: oauth?.scopes ? oauth.scopes.join(' ') : '',\n accessToken: oauth?.accessToken || '',\n refreshToken: oauth?.refreshToken || '',\n authorizationEndpoint: oauth?.authorizationEndpoint || '',\n tokenEndpoint: oauth?.tokenEndpoint || '',\n resource: oauth?.resource || '',\n };\n };\n\n const [serverType, setServerType] = useState<'stdio' | 'sse' | 'streamable-http' | 'openapi'>(\n getInitialServerType(),\n );\n\n const [formData, setFormData] = useState<ServerFormData>({\n name: (initialData && initialData.name) || '',\n description: (initialData && initialData.config && initialData.config.description) || '',\n url: (initialData && initialData.config && initialData.config.url) || '',\n command: (initialData && initialData.config && initialData.config.command) || '',\n arguments:\n initialData && initialData.config && initialData.config.args\n ? Array.isArray(initialData.config.args)\n ? initialData.config.args.join(' ')\n : String(initialData.config.args)\n : '',\n args: (initialData && initialData.config && initialData.config.args) || [],\n type: getInitialServerType(), // Initialize the type field\n env: getInitialServerEnvVars(initialData),\n headers: [],\n passthroughHeaders:\n initialData?.config?.passthroughHeaders?.join(', ') || '',\n visibility: (initialData?.config?.visibility ?? 'private') as\n | 'private'\n | 'group'\n | 'public',\n options: {\n timeout:\n (initialData &&\n initialData.config &&\n initialData.config.options &&\n initialData.config.options.timeout) ||\n 60000,\n resetTimeoutOnProgress:\n initialData?.config?.options?.resetTimeoutOnProgress ?? true,\n maxTotalTimeout:\n (initialData &&\n initialData.config &&\n initialData.config.options &&\n initialData.config.options.maxTotalTimeout) ||\n undefined,\n },\n oauth: getInitialOAuthConfig(initialData),\n // KeepAlive configuration initialization\n keepAlive: {\n enabled: initialData?.config?.enableKeepAlive || false,\n interval: initialData?.config?.keepAliveInterval || 60000,\n },\n // OpenAPI configuration initialization\n openapi:\n initialData && initialData.config && initialData.config.openapi\n ? {\n url: initialData.config.openapi.url || '',\n schema: initialData.config.openapi.schema\n ? JSON.stringify(initialData.config.openapi.schema, null, 2)\n : '',\n inputMode: initialData.config.openapi.url\n ? 'url'\n : initialData.config.openapi.schema\n ? 'schema'\n : 'url',\n version: initialData.config.openapi.version || '3.1.0',\n securityType: initialData.config.openapi.security?.type || 'none',\n // API Key initialization\n apiKeyName: initialData.config.openapi.security?.apiKey?.name || '',\n apiKeyIn: initialData.config.openapi.security?.apiKey?.in || 'header',\n apiKeyValue: initialData.config.openapi.security?.apiKey?.value || '',\n // HTTP auth initialization\n httpScheme: initialData.config.openapi.security?.http?.scheme || 'bearer',\n httpCredentials: initialData.config.openapi.security?.http?.credentials || '',\n // OAuth2 initialization\n oauth2Token: initialData.config.openapi.security?.oauth2?.token || '',\n // OpenID Connect initialization\n openIdConnectUrl: initialData.config.openapi.security?.openIdConnect?.url || '',\n openIdConnectToken: initialData.config.openapi.security?.openIdConnect?.token || '',\n // Passthrough headers initialization\n passthroughHeaders: initialData.config.openapi.passthroughHeaders\n ? initialData.config.openapi.passthroughHeaders.join(', ')\n : '',\n }\n : {\n inputMode: 'url',\n url: '',\n schema: '',\n version: '3.1.0',\n securityType: 'none',\n passthroughHeaders: '',\n },\n });\n\n const [envVars, setEnvVars] = useState<EnvVar[]>(\n initialData && initialData.config && initialData.config.env\n ? Object.entries(initialData.config.env).map(([key, value]) => ({ key, value }))\n : [],\n );\n\n const [headerVars, setHeaderVars] = useState<EnvVar[]>(\n initialData && initialData.config && initialData.config.headers\n ? Object.entries(initialData.config.headers).map(([key, value]) => ({ key, value }))\n : [],\n );\n\n const [isRequestOptionsExpanded, setIsRequestOptionsExpanded] = useState<boolean>(false);\n const [isOAuthSectionExpanded, setIsOAuthSectionExpanded] = useState<boolean>(false);\n const [isKeepAliveSectionExpanded, setIsKeepAliveSectionExpanded] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n const isEdit = !!initialData;\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const { name, value } = e.target;\n setFormData({ ...formData, [name]: value });\n };\n\n // Transform space-separated arguments string into array\n const handleArgsChange = (value: string) => {\n const args = value.split(' ').filter((arg) => arg.trim() !== '');\n setFormData({ ...formData, arguments: value, args });\n };\n\n const updateServerType = (type: 'stdio' | 'sse' | 'streamable-http' | 'openapi') => {\n setServerType(type);\n setFormData((prev) => ({ ...prev, type }));\n };\n\n const handleEnvVarChange = (index: number, field: 'key' | 'value', value: string) => {\n const newEnvVars = [...envVars];\n newEnvVars[index][field] = value;\n setEnvVars(newEnvVars);\n };\n\n const addEnvVar = () => {\n setEnvVars([...envVars, { key: '', value: '' }]);\n };\n\n const removeEnvVar = (index: number) => {\n const newEnvVars = [...envVars];\n newEnvVars.splice(index, 1);\n setEnvVars(newEnvVars);\n };\n\n const handleHeaderVarChange = (index: number, field: 'key' | 'value', value: string) => {\n const newHeaderVars = [...headerVars];\n newHeaderVars[index][field] = value;\n setHeaderVars(newHeaderVars);\n };\n\n const addHeaderVar = () => {\n setHeaderVars([...headerVars, { key: '', value: '' }]);\n };\n\n const removeHeaderVar = (index: number) => {\n const newHeaderVars = [...headerVars];\n newHeaderVars.splice(index, 1);\n setHeaderVars(newHeaderVars);\n };\n\n const handleOAuthChange = <K extends keyof NonNullable<ServerFormData['oauth']>>(\n field: K,\n value: string,\n ) => {\n setFormData((prev) => ({\n ...prev,\n oauth: {\n ...(prev.oauth || {}),\n [field]: value,\n },\n }));\n };\n\n // Handle options changes\n const handleOptionsChange = (\n field: 'timeout' | 'resetTimeoutOnProgress' | 'maxTotalTimeout',\n value: number | boolean | undefined,\n ) => {\n setFormData((prev) => ({\n ...prev,\n options: {\n ...prev.options,\n [field]: value,\n },\n }));\n };\n\n // Submit handler for server configuration\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n setError(null);\n\n try {\n const payload = buildServerPayload({\n formData,\n serverType,\n envVars,\n headerVars,\n });\n\n onSubmit(payload);\n } catch (err) {\n setError(`Error: ${err instanceof Error ? err.message : String(err)}`);\n }\n };\n\n return (\n <div className=\"hub-card p-6 w-full max-w-3xl max-h-screen overflow-y-auto\">\n <div className=\"flex justify-between items-center mb-5\">\n <h2 className=\"text-lg font-semibold text-[var(--hub-ink)]\">{modalTitle}</h2>\n <button\n onClick={onCancel}\n className=\"hub-icon-btn\"\n aria-label=\"Close\"\n >\n <X size={16} />\n </button>\n </div>\n\n {(error || formError) && (\n <div className=\"bg-red-50 text-red-700 p-3 rounded mb-4\">{formError || error}</div>\n )}\n\n <form onSubmit={handleSubmit}>\n <div className=\"mb-4\">\n <label className=\"block text-sm font-medium mb-1.5 text-[var(--hub-ink-2)]\" htmlFor=\"name\">\n {t('server.name')}\n </label>\n <input\n type=\"text\"\n name=\"name\"\n id=\"name\"\n value={formData.name}\n onChange={handleInputChange}\n className=\"w-full py-2 px-3 form-input\"\n placeholder=\"e.g.: time-mcp\"\n required\n />\n </div>\n\n <div className=\"mb-4\">\n <label className=\"block text-sm font-medium mb-1.5 text-[var(--hub-ink-2)]\" htmlFor=\"description\">\n {t('server.description')}\n </label>\n <input\n type=\"text\"\n name=\"description\"\n id=\"description\"\n value={formData.description || ''}\n onChange={handleInputChange}\n className=\"w-full py-2 px-3 form-input\"\n placeholder={t('server.descriptionPlaceholder')}\n />\n </div>\n\n <div className=\"mb-4\">\n <label className=\"block text-sm font-medium mb-1.5 text-[var(--hub-ink-2)]\" htmlFor=\"visibility\">\n {t('server.visibility', 'Visibility')}\n </label>\n <select\n id=\"visibility\"\n name=\"visibility\"\n value={formData.visibility || 'private'}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n visibility: e.target.value as 'private' | 'group' | 'public',\n }))\n }\n className=\"w-full py-2 px-3 form-input\"\n >\n <option value=\"private\">\n {t('server.visibilityPrivate', 'Private — only the owner and admins')}\n </option>\n {formData.visibility === 'group' && (\n // 'group' is a reserved enum value; the filter doesn't yet honour it.\n // Surface it as a disabled option so a server pre-set to 'group' (e.g.\n // via direct DB update or a future user→group migration) renders\n // intelligibly rather than silently falling back to 'private' in the UI.\n <option value=\"group\" disabled>\n {t('server.visibilityGroup', 'Group (reserved — not yet implemented)')}\n </option>\n )}\n <option value=\"public\">\n {t('server.visibilityPublic', 'Public — every authenticated user')}\n </option>\n </select>\n <p className=\"text-xs text-gray-500 mt-1\">\n {t(\n 'server.visibilityDescription',\n \"Controls which non-admin users see this server in tools/list. Admins always see all servers regardless of this setting.\",\n )}\n </p>\n </div>\n\n <div className=\"mb-4\">\n <label className=\"block text-sm font-medium mb-1.5 text-[var(--hub-ink-2)]\">{t('server.type')}</label>\n <div className=\"flex space-x-4\">\n <div>\n <input\n type=\"radio\"\n id=\"command\"\n name=\"serverType\"\n value=\"command\"\n checked={serverType === 'stdio'}\n onChange={() => updateServerType('stdio')}\n className=\"mr-1\"\n />\n <label htmlFor=\"command\" className=\"text-[var(--hub-ink)]\">{t('server.typeStdio')}</label>\n </div>\n <div>\n <input\n type=\"radio\"\n id=\"url\"\n name=\"serverType\"\n value=\"url\"\n checked={serverType === 'sse'}\n onChange={() => updateServerType('sse')}\n className=\"mr-1\"\n />\n <label htmlFor=\"url\" className=\"text-[var(--hub-ink)]\">{t('server.typeSse')}</label>\n </div>\n <div>\n <input\n type=\"radio\"\n id=\"streamable-http\"\n name=\"serverType\"\n value=\"streamable-http\"\n checked={serverType === 'streamable-http'}\n onChange={() => updateServerType('streamable-http')}\n className=\"mr-1\"\n />\n <label htmlFor=\"streamable-http\" className=\"text-[var(--hub-ink)]\">{t('server.typeStreamableHttp')}</label>\n </div>\n <div>\n <input\n type=\"radio\"\n id=\"openapi\"\n name=\"serverType\"\n value=\"openapi\"\n checked={serverType === 'openapi'}\n onChange={() => updateServerType('openapi')}\n className=\"mr-1\"\n />\n <label htmlFor=\"openapi\" className=\"text-[var(--hub-ink)]\">{t('server.typeOpenapi')}</label>\n </div>\n </div>\n </div>\n\n {serverType === 'openapi' ? (\n <>\n {/* Input Mode Selection */}\n <div className=\"mb-4\">\n <label className=\"block text-sm font-medium mb-1.5 text-[var(--hub-ink-2)]\">\n {t('server.openapi.inputMode')}\n </label>\n <div className=\"flex space-x-4\">\n <div>\n <input\n type=\"radio\"\n id=\"input-mode-url\"\n name=\"inputMode\"\n value=\"url\"\n checked={formData.openapi?.inputMode === 'url'}\n onChange={() =>\n setFormData((prev) => ({\n ...prev,\n openapi: { ...prev.openapi!, inputMode: 'url' },\n }))\n }\n className=\"mr-1\"\n />\n <label htmlFor=\"input-mode-url\">{t('server.openapi.inputModeUrl')}</label>\n </div>\n <div>\n <input\n type=\"radio\"\n id=\"input-mode-schema\"\n name=\"inputMode\"\n value=\"schema\"\n checked={formData.openapi?.inputMode === 'schema'}\n onChange={() =>\n setFormData((prev) => ({\n ...prev,\n openapi: { ...prev.openapi!, inputMode: 'schema' },\n }))\n }\n className=\"mr-1\"\n />\n <label htmlFor=\"input-mode-schema\">{t('server.openapi.inputModeSchema')}</label>\n </div>\n </div>\n </div>\n\n {/* URL Input */}\n {formData.openapi?.inputMode === 'url' && (\n <div className=\"mb-4\">\n <label className=\"block text-sm font-medium mb-1.5 text-[var(--hub-ink-2)]\" htmlFor=\"openapi-url\">\n {t('server.openapi.specUrl')}\n </label>\n <input\n type=\"url\"\n name=\"openapi-url\"\n id=\"openapi-url\"\n value={formData.openapi?.url || ''}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n openapi: { ...prev.openapi!, url: e.target.value },\n }))\n }\n className=\"w-full py-2 px-3 form-input\"\n placeholder=\"e.g.: https://api.example.com/openapi.json\"\n required={serverType === 'openapi' && formData.openapi?.inputMode === 'url'}\n />\n </div>\n )}\n\n {/* Schema Input */}\n {formData.openapi?.inputMode === 'schema' && (\n <div className=\"mb-4\">\n <label\n className=\"block text-sm font-medium mb-1.5 text-[var(--hub-ink-2)]\"\n htmlFor=\"openapi-schema\"\n >\n {t('server.openapi.schema')}\n </label>\n <textarea\n name=\"openapi-schema\"\n id=\"openapi-schema\"\n rows={10}\n value={formData.openapi?.schema || ''}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n openapi: { ...prev.openapi!, schema: e.target.value },\n }))\n }\n className=\"w-full py-2 px-3 form-input font-mono text-sm\"\n placeholder={`{\n \"openapi\": \"3.1.0\",\n \"info\": {\n \"title\": \"API\",\n \"version\": \"1.0.0\"\n },\n \"servers\": [\n {\n \"url\": \"https://api.example.com\"\n }\n ],\n \"paths\": {\n ...\n }\n}`}\n required={serverType === 'openapi' && formData.openapi?.inputMode === 'schema'}\n />\n <p className=\"text-xs text-[var(--hub-ink-3)] mt-1\">{t('server.openapi.schemaHelp')}</p>\n </div>\n )}\n\n {/* Security Configuration */}\n <div className=\"mb-4\">\n <label className=\"block text-sm font-medium mb-1.5 text-[var(--hub-ink-2)]\">\n {t('server.openapi.security')}\n </label>\n <select\n value={formData.openapi?.securityType || 'none'}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n openapi: {\n ...prev.openapi,\n securityType: e.target.value as any,\n url: prev.openapi?.url || '',\n },\n }))\n }\n className=\"w-full py-2 px-3 form-input\"\n >\n <option value=\"none\">{t('server.openapi.securityNone')}</option>\n <option value=\"apiKey\">{t('server.openapi.securityApiKey')}</option>\n <option value=\"http\">{t('server.openapi.securityHttp')}</option>\n <option value=\"oauth2\">{t('server.openapi.securityOAuth2')}</option>\n <option value=\"openIdConnect\">{t('server.openapi.securityOpenIdConnect')}</option>\n </select>\n </div>\n\n {/* API Key Configuration */}\n {formData.openapi?.securityType === 'apiKey' && (\n <div className=\"mb-4 p-4 border border-gray-200 dark:border-gray-700 rounded bg-gray-50 dark:bg-gray-800\">\n <h4 className=\"text-sm font-medium mb-3 text-[var(--hub-ink-2)]\">\n {t('server.openapi.apiKeyConfig')}\n </h4>\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-3\">\n <div>\n <label className=\"block text-xs text-[var(--hub-ink-2)] mb-1\">\n {t('server.openapi.apiKeyName')}\n </label>\n <input\n type=\"text\"\n value={formData.openapi?.apiKeyName || ''}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n openapi: {\n ...prev.openapi,\n apiKeyName: e.target.value,\n url: prev.openapi?.url || '',\n },\n }))\n }\n className=\"w-full border rounded px-2 py-1 text-sm form-input focus:outline-none\"\n placeholder=\"Authorization\"\n />\n </div>\n <div>\n <label className=\"block text-xs text-[var(--hub-ink-2)] mb-1\">\n {t('server.openapi.apiKeyIn')}\n </label>\n <select\n value={formData.openapi?.apiKeyIn || 'header'}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n openapi: {\n ...prev.openapi,\n apiKeyIn: e.target.value as any,\n url: prev.openapi?.url || '',\n },\n }))\n }\n className=\"w-full border rounded px-2 py-1 text-sm focus:outline-none form-input\"\n >\n <option value=\"header\">{t('server.openapi.apiKeyInHeader')}</option>\n <option value=\"query\">{t('server.openapi.apiKeyInQuery')}</option>\n <option value=\"cookie\">{t('server.openapi.apiKeyInCookie')}</option>\n </select>\n </div>\n <div>\n <label className=\"block text-xs text-gray-600 mb-1\">\n {t('server.openapi.apiKeyValue')}\n </label>\n <input\n type=\"password\"\n value={formData.openapi?.apiKeyValue || ''}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n openapi: {\n ...prev.openapi,\n apiKeyValue: e.target.value,\n url: prev.openapi?.url || '',\n },\n }))\n }\n className=\"w-full border rounded px-2 py-1 text-sm focus:outline-none form-input\"\n placeholder=\"your-api-key\"\n />\n </div>\n </div>\n </div>\n )}\n\n {/* HTTP Authentication Configuration */}\n {formData.openapi?.securityType === 'http' && (\n <div className=\"mb-4 p-4 border border-gray-200 dark:border-gray-700 rounded bg-gray-50 dark:bg-gray-800\">\n <h4 className=\"text-sm font-medium mb-3 text-gray-700 dark:text-gray-300\">\n {t('server.openapi.httpAuthConfig')}\n </h4>\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-3\">\n <div>\n <label className=\"block text-xs text-gray-600 mb-1\">\n {t('server.openapi.httpScheme')}\n </label>\n <select\n value={formData.openapi?.httpScheme || 'bearer'}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n openapi: {\n ...prev.openapi,\n httpScheme: e.target.value as any,\n url: prev.openapi?.url || '',\n },\n }))\n }\n className=\"w-full border rounded px-2 py-1 text-sm focus:outline-none form-input\"\n >\n <option value=\"basic\">{t('server.openapi.httpSchemeBasic')}</option>\n <option value=\"bearer\">{t('server.openapi.httpSchemeBearer')}</option>\n <option value=\"digest\">{t('server.openapi.httpSchemeDigest')}</option>\n </select>\n </div>\n <div>\n <label className=\"block text-xs text-gray-600 mb-1\">\n {t('server.openapi.httpCredentials')}\n </label>\n <input\n type=\"password\"\n value={formData.openapi?.httpCredentials || ''}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n openapi: {\n ...prev.openapi,\n httpCredentials: e.target.value,\n url: prev.openapi?.url || '',\n },\n }))\n }\n className=\"w-full border rounded px-2 py-1 text-sm focus:outline-none form-input\"\n placeholder={\n formData.openapi?.httpScheme === 'basic'\n ? 'base64-encoded-credentials'\n : 'bearer-token'\n }\n />\n </div>\n </div>\n </div>\n )}\n\n {/* OAuth2 Configuration */}\n {formData.openapi?.securityType === 'oauth2' && (\n <div className=\"mb-4 p-4 border border-gray-200 dark:border-gray-700 rounded bg-gray-50 dark:bg-gray-800\">\n <h4 className=\"text-sm font-medium mb-3 text-gray-700 dark:text-gray-300\">\n {t('server.openapi.oauth2Config')}\n </h4>\n <div className=\"grid grid-cols-1 gap-3\">\n <div>\n <label className=\"block text-xs text-gray-600 mb-1\">\n {t('server.openapi.oauth2Token')}\n </label>\n <input\n type=\"password\"\n value={formData.openapi?.oauth2Token || ''}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n openapi: {\n ...prev.openapi,\n oauth2Token: e.target.value,\n url: prev.openapi?.url || '',\n },\n }))\n }\n className=\"w-full border rounded px-2 py-1 text-sm focus:outline-none form-input\"\n placeholder=\"access-token\"\n />\n </div>\n </div>\n </div>\n )}\n\n {/* OpenID Connect Configuration */}\n {formData.openapi?.securityType === 'openIdConnect' && (\n <div className=\"mb-4 p-4 border border-gray-200 dark:border-gray-700 rounded bg-gray-50 dark:bg-gray-800\">\n <h4 className=\"text-sm font-medium mb-3 text-gray-700 dark:text-gray-300\">\n {t('server.openapi.openIdConnectConfig')}\n </h4>\n <div className=\"grid grid-cols-1 gap-3\">\n <div>\n <label className=\"block text-xs text-gray-600 mb-1\">\n {t('server.openapi.openIdConnectUrl')}\n </label>\n <input\n type=\"url\"\n value={formData.openapi?.openIdConnectUrl || ''}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n openapi: {\n ...prev.openapi,\n openIdConnectUrl: e.target.value,\n url: prev.openapi?.url || '',\n },\n }))\n }\n className=\"w-full border rounded px-2 py-1 text-sm focus:outline-none form-input\"\n placeholder=\"https://example.com/.well-known/openid_configuration\"\n />\n </div>\n <div>\n <label className=\"block text-xs text-gray-600 mb-1\">\n {t('server.openapi.openIdConnectToken')}\n </label>\n <input\n type=\"password\"\n value={formData.openapi?.openIdConnectToken || ''}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n openapi: {\n ...prev.openapi,\n openIdConnectToken: e.target.value,\n url: prev.openapi?.url || '',\n },\n }))\n }\n className=\"w-full border rounded px-2 py-1 text-sm focus:outline-none form-input\"\n placeholder=\"id-token\"\n />\n </div>\n </div>\n </div>\n )}\n\n {/* Passthrough Headers Configuration */}\n <div className=\"mb-4\">\n <label className=\"block text-sm font-medium mb-1.5 text-gray-700 dark:text-gray-300\">\n {t('server.openapi.passthroughHeaders')}\n </label>\n <input\n type=\"text\"\n value={formData.openapi?.passthroughHeaders || ''}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n openapi: {\n ...prev.openapi,\n passthroughHeaders: e.target.value,\n url: prev.openapi?.url || '',\n },\n }))\n }\n className=\"w-full py-2 px-3 form-input\"\n placeholder=\"Authorization, X-API-Key, X-Custom-Header\"\n />\n <p className=\"text-xs text-gray-500 mt-1\">\n {t('server.openapi.passthroughHeadersHelp')}\n </p>\n </div>\n\n <div className=\"mb-4\">\n <div className=\"flex justify-between items-center mb-2\">\n <label className=\"block text-sm font-medium text-gray-700 dark:text-gray-300\">\n {t('server.headers')}\n </label>\n <button\n type=\"button\"\n onClick={addHeaderVar}\n className=\"bg-gray-200 hover:bg-gray-300 text-gray-700 font-medium py-1 px-2 rounded text-sm flex items-center justify-center min-w-[30px] min-h-[30px] btn-primary\"\n >\n +\n </button>\n </div>\n {headerVars.map((headerVar, index) => (\n <div key={index} className=\"flex items-center mb-2\">\n <div className=\"flex items-center space-x-2 flex-grow\">\n <input\n type=\"text\"\n value={headerVar.key}\n onChange={(e) => handleHeaderVarChange(index, 'key', e.target.value)}\n className=\"w-1/2 py-2 px-3 form-input\"\n placeholder=\"Authorization\"\n />\n <span className=\"flex items-center\">:</span>\n <input\n type=\"text\"\n value={headerVar.value}\n onChange={(e) => handleHeaderVarChange(index, 'value', e.target.value)}\n className=\"w-1/2 py-2 px-3 form-input\"\n placeholder=\"Bearer token...\"\n />\n </div>\n <button\n type=\"button\"\n onClick={() => removeHeaderVar(index)}\n className=\"bg-gray-200 hover:bg-gray-300 text-gray-700 font-medium py-1 px-2 rounded text-sm flex items-center justify-center min-w-[30px] min-h-[30px] ml-2 btn-danger\"\n >\n -\n </button>\n </div>\n ))}\n </div>\n </>\n ) : serverType === 'sse' || serverType === 'streamable-http' ? (\n <>\n <div className=\"mb-4\">\n <label className=\"block text-sm font-medium mb-1.5 text-gray-700 dark:text-gray-300\" htmlFor=\"url\">\n {t('server.url')}\n </label>\n <input\n type=\"url\"\n name=\"url\"\n id=\"url\"\n value={formData.url}\n onChange={handleInputChange}\n className=\"w-full py-2 px-3 form-input\"\n placeholder={\n serverType === 'streamable-http'\n ? 'e.g.: http://localhost:3000/mcp'\n : 'e.g.: http://localhost:3000/sse'\n }\n required={serverType === 'sse' || serverType === 'streamable-http'}\n />\n </div>\n\n <div className=\"mb-4\">\n <div className=\"flex justify-between items-center mb-2\">\n <label className=\"block text-sm font-medium text-gray-700 dark:text-gray-300\">\n {t('server.headers')}\n </label>\n <button\n type=\"button\"\n onClick={addHeaderVar}\n className=\"bg-gray-200 hover:bg-gray-300 text-gray-700 font-medium py-1 px-2 rounded text-sm flex items-center justify-center min-w-[30px] min-h-[30px] btn-primary\"\n >\n +\n </button>\n </div>\n {headerVars.map((headerVar, index) => (\n <div key={index} className=\"flex items-center mb-2\">\n <div className=\"flex items-center space-x-2 flex-grow\">\n <input\n type=\"text\"\n value={headerVar.key}\n onChange={(e) => handleHeaderVarChange(index, 'key', e.target.value)}\n className=\"w-1/2 py-2 px-3 form-input\"\n placeholder=\"Authorization\"\n />\n <span className=\"flex items-center\">:</span>\n <input\n type=\"text\"\n value={headerVar.value}\n onChange={(e) => handleHeaderVarChange(index, 'value', e.target.value)}\n className=\"w-1/2 py-2 px-3 form-input\"\n placeholder=\"Bearer token...\"\n />\n </div>\n <button\n type=\"button\"\n onClick={() => removeHeaderVar(index)}\n className=\"bg-gray-200 hover:bg-gray-300 text-gray-700 font-medium py-1 px-2 rounded text-sm flex items-center justify-center min-w-[30px] min-h-[30px] ml-2 btn-danger\"\n >\n -\n </button>\n </div>\n ))}\n </div>\n\n <div className=\"mb-4\">\n <label className=\"block text-sm font-medium mb-1.5 text-gray-700 dark:text-gray-300\">\n {t('server.openapi.passthroughHeaders')}\n </label>\n <input\n type=\"text\"\n value={formData.passthroughHeaders || ''}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n passthroughHeaders: e.target.value,\n }))\n }\n className=\"w-full py-2 px-3 form-input\"\n placeholder=\"Authorization, X-Custom-User-Id\"\n />\n <p className=\"text-xs text-gray-500 mt-1\">\n {t('server.openapi.passthroughHeadersHelp')}\n </p>\n </div>\n\n <div className=\"mb-4\">\n <div className=\"flex justify-between items-center mb-2\">\n <label className=\"block text-sm font-medium text-gray-700 dark:text-gray-300\">\n {t('server.envVars')}\n </label>\n <button\n type=\"button\"\n onClick={addEnvVar}\n className=\"bg-gray-200 hover:bg-gray-300 text-gray-700 font-medium py-1 px-2 rounded text-sm flex items-center justify-center min-w-[30px] min-h-[30px] btn-primary\"\n >\n +\n </button>\n </div>\n {envVars.map((envVar, index) => (\n <div key={index} className=\"flex items-center mb-2\">\n <div className=\"flex items-center space-x-2 flex-grow\">\n <input\n type=\"text\"\n value={envVar.key}\n onChange={(e) => handleEnvVarChange(index, 'key', e.target.value)}\n className=\"w-1/2 py-2 px-3 form-input\"\n placeholder={t('server.key')}\n />\n <span className=\"flex items-center\">:</span>\n <input\n type=\"text\"\n value={envVar.value}\n onChange={(e) => handleEnvVarChange(index, 'value', e.target.value)}\n className=\"w-1/2 py-2 px-3 form-input\"\n placeholder={t('server.value')}\n />\n </div>\n <button\n type=\"button\"\n onClick={() => removeEnvVar(index)}\n className=\"bg-gray-200 hover:bg-gray-300 text-gray-700 font-medium py-1 px-2 rounded text-sm flex items-center justify-center min-w-[30px] min-h-[30px] ml-2 btn-danger\"\n >\n -\n </button>\n </div>\n ))}\n </div>\n\n <div className=\"mb-4\">\n <div\n className=\"flex items-center justify-between cursor-pointer bg-gray-50 dark:bg-gray-800 hover:bg-gray-100 p-3 rounded border border-gray-200 dark:border-gray-700\"\n onClick={() => setIsOAuthSectionExpanded(!isOAuthSectionExpanded)}\n >\n <label className=\"text-sm font-medium text-gray-700 dark:text-gray-300\">\n {t('server.oauth.sectionTitle')}\n </label>\n <span className=\"text-gray-500 text-sm\">{isOAuthSectionExpanded ? '▼' : '▶'}</span>\n </div>\n\n {isOAuthSectionExpanded && (\n <div className=\"border border-gray-200 dark:border-gray-700 rounded-b p-4 bg-gray-50 dark:bg-gray-800 border-t-0\">\n <p className=\"text-xs text-gray-500 mb-3\">\n {t('server.oauth.sectionDescription')}\n </p>\n <div className=\"grid grid-cols-1 gap-3 md:grid-cols-2\">\n <div>\n <label className=\"block text-xs text-gray-600 mb-1\">\n {t('server.oauth.clientId')}\n </label>\n <input\n type=\"text\"\n value={formData.oauth?.clientId || ''}\n onChange={(e) => handleOAuthChange('clientId', e.target.value)}\n className=\"w-full py-2 px-3 form-input\"\n placeholder=\"client id\"\n autoComplete=\"off\"\n />\n </div>\n <div>\n <label className=\"block text-xs text-gray-600 mb-1\">\n {t('server.oauth.clientSecret')}\n </label>\n <input\n type=\"password\"\n value={formData.oauth?.clientSecret || ''}\n onChange={(e) => handleOAuthChange('clientSecret', e.target.value)}\n className=\"w-full py-2 px-3 form-input\"\n placeholder=\"client secret\"\n autoComplete=\"off\"\n />\n </div>\n {/* \n <div>\n <label className=\"block text-xs text-gray-600 mb-1\">\n {t('server.oauth.authorizationEndpoint')}\n </label>\n <input\n type=\"url\"\n value={formData.oauth?.authorizationEndpoint || ''}\n onChange={(e) => handleOAuthChange('authorizationEndpoint', e.target.value)}\n className=\"w-full py-2 px-3 form-input\"\n placeholder=\"https://auth.example.com/authorize\"\n />\n </div>\n <div>\n <label className=\"block text-xs text-gray-600 mb-1\">\n {t('server.oauth.tokenEndpoint')}\n </label>\n <input\n type=\"url\"\n value={formData.oauth?.tokenEndpoint || ''}\n onChange={(e) => handleOAuthChange('tokenEndpoint', e.target.value)}\n className=\"w-full py-2 px-3 form-input\"\n placeholder=\"https://auth.example.com/token\"\n />\n </div>\n <div>\n <label className=\"block text-xs text-gray-600 mb-1\">\n {t('server.oauth.scopes')}\n </label>\n <input\n type=\"text\"\n value={formData.oauth?.scopes || ''}\n onChange={(e) => handleOAuthChange('scopes', e.target.value)}\n className=\"w-full py-2 px-3 form-input\"\n placeholder={t('server.oauth.scopesPlaceholder')}\n autoComplete=\"off\"\n />\n </div>\n <div>\n <label className=\"block text-xs text-gray-600 mb-1\">\n {t('server.oauth.resource')}\n </label>\n <input\n type=\"text\"\n value={formData.oauth?.resource || ''}\n onChange={(e) => handleOAuthChange('resource', e.target.value)}\n className=\"w-full py-2 px-3 form-input\"\n placeholder=\"https://mcp.example.com/mcp\"\n autoComplete=\"off\"\n />\n </div>\n <div>\n <label className=\"block text-xs text-gray-600 mb-1\">\n {t('server.oauth.accessToken')}\n </label>\n <input\n type=\"password\"\n value={formData.oauth?.accessToken || ''}\n onChange={(e) => handleOAuthChange('accessToken', e.target.value)}\n className=\"w-full py-2 px-3 form-input\"\n placeholder=\"access-token\"\n autoComplete=\"off\"\n />\n </div>\n <div>\n <label className=\"block text-xs text-gray-600 mb-1\">\n {t('server.oauth.refreshToken')}\n </label>\n <input\n type=\"password\"\n value={formData.oauth?.refreshToken || ''}\n onChange={(e) => handleOAuthChange('refreshToken', e.target.value)}\n className=\"w-full py-2 px-3 form-input\"\n placeholder=\"refresh-token\"\n autoComplete=\"off\"\n />\n </div>\n */}\n </div>\n </div>\n )}\n </div>\n </>\n ) : (\n <>\n <div className=\"mb-4\">\n <label className=\"block text-sm font-medium mb-1.5 text-gray-700 dark:text-gray-300\" htmlFor=\"command\">\n {t('server.command')}\n </label>\n <input\n type=\"text\"\n name=\"command\"\n id=\"command\"\n value={formData.command}\n onChange={handleInputChange}\n className=\"w-full py-2 px-3 form-input\"\n placeholder=\"e.g.: npx\"\n required={serverType === 'stdio'}\n />\n </div>\n <div className=\"mb-4\">\n <label className=\"block text-sm font-medium mb-1.5 text-gray-700 dark:text-gray-300\" htmlFor=\"arguments\">\n {t('server.arguments')}\n </label>\n <input\n type=\"text\"\n name=\"arguments\"\n id=\"arguments\"\n value={formData.arguments}\n onChange={(e) => handleArgsChange(e.target.value)}\n className=\"w-full py-2 px-3 form-input\"\n placeholder=\"e.g.: -y time-mcp\"\n required={serverType === 'stdio'}\n />\n </div>\n\n <div className=\"mb-4\">\n <div className=\"flex justify-between items-center mb-2\">\n <label className=\"block text-sm font-medium text-gray-700 dark:text-gray-300\">\n {t('server.envVars')}\n </label>\n <button\n type=\"button\"\n onClick={addEnvVar}\n className=\"bg-gray-200 hover:bg-gray-300 text-gray-700 font-medium py-1 px-2 rounded text-sm flex items-center justify-center min-w-[30px] min-h-[30px] btn-primary\"\n >\n +\n </button>\n </div>\n {envVars.map((envVar, index) => (\n <div key={index} className=\"flex items-center mb-2\">\n <div className=\"flex items-center space-x-2 flex-grow\">\n <input\n type=\"text\"\n value={envVar.key}\n onChange={(e) => handleEnvVarChange(index, 'key', e.target.value)}\n className=\"w-1/2 py-2 px-3 form-input\"\n placeholder={t('server.key')}\n />\n <span className=\"flex items-center\">:</span>\n <input\n type=\"text\"\n value={envVar.value}\n onChange={(e) => handleEnvVarChange(index, 'value', e.target.value)}\n className=\"w-1/2 py-2 px-3 form-input\"\n placeholder={t('server.value')}\n />\n </div>\n <button\n type=\"button\"\n onClick={() => removeEnvVar(index)}\n className=\"bg-gray-200 hover:bg-gray-300 text-gray-700 font-medium py-1 px-2 rounded text-sm flex items-center justify-center min-w-[30px] min-h-[30px] ml-2 btn-danger\"\n >\n -\n </button>\n </div>\n ))}\n </div>\n </>\n )}\n\n {/* Request Options Configuration */}\n {serverType !== 'openapi' && (\n <div className=\"mb-4\">\n <div\n className=\"flex items-center justify-between cursor-pointer bg-gray-50 dark:bg-gray-800 hover:bg-gray-100 p-3 rounded border border-gray-200 dark:border-gray-700\"\n onClick={() => setIsRequestOptionsExpanded(!isRequestOptionsExpanded)}\n >\n <label className=\"text-sm font-medium text-gray-700 dark:text-gray-300\">\n {t('server.requestOptions')}\n </label>\n <span className=\"text-gray-500 text-sm\">{isRequestOptionsExpanded ? '▼' : '▶'}</span>\n </div>\n\n {isRequestOptionsExpanded && (\n <div className=\"border border-gray-200 dark:border-gray-700 rounded-b p-4 bg-gray-50 dark:bg-gray-800 border-t-0\">\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div>\n <label\n className=\"block text-gray-600 text-sm font-medium mb-1\"\n htmlFor=\"timeout\"\n >\n {t('server.timeout')}\n </label>\n <input\n type=\"number\"\n id=\"timeout\"\n value={formData.options?.timeout || 60000}\n onChange={(e) =>\n handleOptionsChange('timeout', parseInt(e.target.value) || 60000)\n }\n className=\"w-full py-2 px-3 form-input\"\n placeholder=\"30000\"\n min=\"1000\"\n max=\"300000\"\n />\n <p className=\"text-xs text-gray-500 mt-1\">{t('server.timeoutDescription')}</p>\n </div>\n\n <div>\n <label\n className=\"block text-gray-600 text-sm font-medium mb-1\"\n htmlFor=\"maxTotalTimeout\"\n >\n {t('server.maxTotalTimeout')}\n </label>\n <input\n type=\"number\"\n id=\"maxTotalTimeout\"\n value={formData.options?.maxTotalTimeout || ''}\n onChange={(e) =>\n handleOptionsChange(\n 'maxTotalTimeout',\n e.target.value ? parseInt(e.target.value) : undefined,\n )\n }\n className=\"w-full py-2 px-3 form-input\"\n placeholder=\"Optional\"\n min=\"1000\"\n />\n <p className=\"text-xs text-gray-500 mt-1\">\n {t('server.maxTotalTimeoutDescription')}\n </p>\n </div>\n </div>\n\n <div className=\"mt-3\">\n <label className=\"flex items-center\">\n <input\n type=\"checkbox\"\n checked={formData.options?.resetTimeoutOnProgress ?? true}\n onChange={(e) =>\n handleOptionsChange('resetTimeoutOnProgress', e.target.checked)\n }\n className=\"mr-2\"\n />\n <span className=\"text-gray-600 text-sm\">\n {t('server.resetTimeoutOnProgress')}\n </span>\n </label>\n <p className=\"text-xs text-gray-500 mt-1 ml-6\">\n {t('server.resetTimeoutOnProgressDescription')}\n </p>\n </div>\n </div>\n )}\n </div>\n )}\n\n {/* KeepAlive Configuration - only for SSE/Streamable HTTP */}\n {(serverType === 'sse' || serverType === 'streamable-http') && (\n <div className=\"mb-4\">\n <div\n className=\"flex items-center justify-between cursor-pointer bg-gray-50 dark:bg-gray-800 hover:bg-gray-100 p-3 rounded border border-gray-200 dark:border-gray-700\"\n onClick={() => setIsKeepAliveSectionExpanded(!isKeepAliveSectionExpanded)}\n >\n <label className=\"text-sm font-medium text-gray-700 dark:text-gray-300\">\n {t('server.keepAlive', 'Keep-Alive')}\n </label>\n <span className=\"text-gray-500 text-sm\">\n {isKeepAliveSectionExpanded ? '▼' : '▶'}\n </span>\n </div>\n\n {isKeepAliveSectionExpanded && (\n <div className=\"border border-gray-200 dark:border-gray-700 rounded-b p-4 bg-gray-50 dark:bg-gray-800 border-t-0\">\n <div className=\"flex items-center mb-3\">\n <input\n type=\"checkbox\"\n id=\"enableKeepAlive\"\n checked={formData.keepAlive?.enabled || false}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n keepAlive: {\n ...prev.keepAlive,\n enabled: e.target.checked,\n },\n }))\n }\n className=\"mr-2\"\n />\n <label htmlFor=\"enableKeepAlive\" className=\"text-gray-600 text-sm\">\n {t('server.enableKeepAlive', 'Enable Keep-Alive')}\n </label>\n </div>\n <p className=\"text-xs text-gray-500 mb-3\">\n {t(\n 'server.keepAliveDescription',\n 'Send periodic ping requests to maintain the connection. Useful for long-running connections that may timeout.',\n )}\n </p>\n <div>\n <label\n className=\"block text-gray-600 text-sm font-medium mb-1\"\n htmlFor=\"keepAliveInterval\"\n >\n {t('server.keepAliveInterval', 'Interval (ms)')}\n </label>\n <input\n type=\"number\"\n id=\"keepAliveInterval\"\n value={formData.keepAlive?.interval || 60000}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n keepAlive: {\n ...prev.keepAlive,\n interval: parseInt(e.target.value) || 60000,\n },\n }))\n }\n className=\"w-full py-2 px-3 form-input\"\n placeholder=\"60000\"\n min=\"5000\"\n max=\"300000\"\n />\n <p className=\"text-xs text-gray-500 mt-1\">\n {t(\n 'server.keepAliveIntervalDescription',\n 'Time between keep-alive pings in milliseconds (default: 60000ms = 1 minute)',\n )}\n </p>\n </div>\n </div>\n )}\n </div>\n )}\n\n <div className=\"flex justify-end mt-6\">\n <button\n type=\"button\"\n onClick={onCancel}\n className=\"hub-btn mr-2\"\n >\n {t('server.cancel')}\n </button>\n <button\n type=\"submit\"\n className=\"hub-btn primary\"\n >\n {isEdit ? t('server.save') : t('server.add')}\n </button>\n </div>\n </form>\n </div>\n );\n};\n\nexport default ServerForm;\n","// Utility function to detect ${} variables in server configurations\nexport const detectVariables = (payload: any): string[] => {\n const variables = new Set<string>();\n const variableRegex = /\\$\\{([^}]+)\\}/g;\n\n const checkString = (str: string) => {\n let match;\n while ((match = variableRegex.exec(str)) !== null) {\n variables.add(match[1]);\n }\n };\n\n const checkObject = (obj: any, path: string = '') => {\n if (typeof obj === 'string') {\n checkString(obj);\n } else if (Array.isArray(obj)) {\n obj.forEach((item, index) => checkObject(item, `${path}[${index}]`));\n } else if (obj && typeof obj === 'object') {\n Object.entries(obj).forEach(([key, value]) => {\n checkObject(value, path ? `${path}.${key}` : key);\n });\n }\n };\n\n checkObject(payload);\n return Array.from(variables);\n};\n"],"names":["buildKeyValueRecord","vars","record","key","value","trimmedKey","parseCommaSeparatedList","item","buildOptions","options","nextOptions","buildOAuthConfig","oauth","nextOAuth","clientId","_a","clientSecret","_b","scopes","_c","accessToken","_d","refreshToken","_e","authorizationEndpoint","_f","tokenEndpoint","_g","resource","_h","parsedScopes","scope","buildOpenApiConfig","formData","openapi","buildServerPayload","serverType","envVars","headerVars","env","headers","description","config","ServerForm","onSubmit","onCancel","initialData","modalTitle","formError","t","useTranslation","getInitialServerType","getInitialServerEnvVars","data","getInitialOAuthConfig","setServerType","useState","setFormData","_j","_i","_l","_k","_n","_m","_p","_o","_r","_q","_t","_s","_v","_u","_x","_w","setEnvVars","setHeaderVars","isRequestOptionsExpanded","setIsRequestOptionsExpanded","isOAuthSectionExpanded","setIsOAuthSectionExpanded","isKeepAliveSectionExpanded","setIsKeepAliveSectionExpanded","error","setError","isEdit","handleInputChange","e","name","handleArgsChange","args","arg","updateServerType","type","prev","handleEnvVarChange","index","field","newEnvVars","addEnvVar","removeEnvVar","handleHeaderVarChange","newHeaderVars","addHeaderVar","removeHeaderVar","handleOAuthChange","handleOptionsChange","handleSubmit","payload","err","jsxs","jsx","X","Fragment","_y","_z","_A","_B","_C","_D","_E","_F","_G","_H","_I","_J","_K","_L","_M","_N","_O","_P","_Q","_R","_S","_T","_U","headerVar","envVar","_V","_W","_X","_Y","_Z","__","_$","detectVariables","variables","variableRegex","checkString","str","match","checkObject","obj","path"],"mappings":"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"}
@@ -9,11 +9,11 @@
9
9
  <link rel="preconnect" href="https://fonts.googleapis.com">
10
10
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
11
11
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
12
- <script type="module" crossorigin src="./assets/index-B9cW2F0H.js"></script>
12
+ <script type="module" crossorigin src="./assets/index-C7wNc_3N.js"></script>
13
13
  <link rel="modulepreload" crossorigin href="./assets/framework-vendor-BUhDPOUZ.js">
14
14
  <link rel="modulepreload" crossorigin href="./assets/i18n-vendor-Kbr87Ofu.js">
15
15
  <link rel="modulepreload" crossorigin href="./assets/icons-vendor-CKgJB3SC.js">
16
- <link rel="stylesheet" crossorigin href="./assets/index-Crcbkt8x.css">
16
+ <link rel="stylesheet" crossorigin href="./assets/index-D0OIBhmN.css">
17
17
  </head>
18
18
 
19
19
  <body class="bg-gray-100">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@samanhappy/mcphub",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "A hub server for mcp servers",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -124,6 +124,7 @@
124
124
  "build": "pnpm backend:build && pnpm frontend:build",
125
125
  "backend:build": "tsc",
126
126
  "start": "node dist/index.js",
127
+ "cli": "tsx src/cli/main.ts",
127
128
  "backend:dev": "tsx watch src/index.ts",
128
129
  "backend:debug": "tsx watch src/index.ts --inspect",
129
130
  "lint": "eslint .",
@@ -1,2 +0,0 @@
1
- import{r as l,j as e}from"./framework-vendor-BUhDPOUZ.js";import{r as Y,s as Z,t as ee,v as te,w as ae}from"./index-B9cW2F0H.js";import{P as se}from"./Pagination-BFi-X7qY.js";import{u as le}from"./i18n-vendor-Kbr87Ofu.js";import"./icons-vendor-CKgJB3SC.js";const T=["success","error"],re=a=>T.includes(a),xe=()=>{const{t:a}=le(),[m,B]=l.useState([]),[n,V]=l.useState(null),[r,$]=l.useState(null),[i,I]=l.useState(null),[o,d]=l.useState(1),[b,J]=l.useState(10),[j,M]=l.useState(!0),[z,f]=l.useState(null),[c,G]=l.useState(null),[H,A]=l.useState(!1),[F,R]=l.useState({}),[v,N]=l.useState(""),[p,w]=l.useState(""),[x,k]=l.useState(""),[g,S]=l.useState(""),[y,C]=l.useState(""),L=l.useCallback(async()=>{M(!0),f(null);try{const t={...F},[s,u,h]=await Promise.all([Y(o,b,t),Z(t),ee()]);s!=null&&s.success&&Array.isArray(s.data)&&(B(s.data),s.pagination&&I(s.pagination)),u!=null&&u.success&&u.data&&V(u.data),h!=null&&h.success&&h.data&&$(h.data)}catch(t){console.error("Error fetching activity data:",t),f(a("activity.fetchError"))}finally{M(!1)}},[o,b,F,a]);l.useEffect(()=>{L()},[L]),l.useEffect(()=>{if(!i)return;const t=Math.max(1,i.totalPages||1);o>t&&d(t)},[i,o]);const K=async t=>{try{const s=await ae(t.id);s!=null&&s.success&&s.data&&(G(s.data),A(!0))}catch(s){console.error("Error fetching activity details:",s)}},W=async()=>{var t;if(window.confirm(a("activity.confirmCleanup")))try{const s=await te(30);s!=null&&s.success&&(alert(a("activity.cleanupSuccess",{count:((t=s.data)==null?void 0:t.deletedCount)||0})),L())}catch(s){console.error("Error cleaning up activities:",s),alert(a("activity.cleanupError"))}},O=()=>{const t={};v&&(t.server=v),p&&(t.tool=p),x&&re(x)&&(t.status=x),g&&(t.group=g),y&&(t.keyName=y),R(t),d(1)},U=()=>{N(""),w(""),k(""),S(""),C(""),R({}),d(1)},P=t=>t<1e3?`${t}ms`:t<6e4?`${(t/1e3).toFixed(2)}s`:`${(t/6e4).toFixed(2)}m`,D=t=>new Date(t).toLocaleString(),E=t=>{if(!t)return null;try{return JSON.parse(t)}catch{return t}},_=()=>n?e.jsx("div",{className:"grid grid-cols-2 md:grid-cols-4 gap-3 mb-4",children:[{label:a("activity.totalCalls"),value:n.totalCalls,tone:"default"},{label:a("activity.successCount"),value:n.successCount,tone:"ok"},{label:a("activity.errorCount"),value:n.errorCount,tone:"err"},{label:a("activity.avgDuration"),value:P(n.avgDuration),tone:"default"}].map(t=>e.jsxs("div",{className:"hub-card",style:{padding:"12px 14px"},children:[e.jsx("div",{className:"text-[12px]",style:{color:"var(--hub-ink-3)"},children:t.label}),e.jsx("div",{className:"hub-num",style:{fontSize:22,fontWeight:500,lineHeight:1.1,marginTop:6,letterSpacing:"-0.02em",color:t.tone==="ok"?"oklch(0.4 0.13 145)":t.tone==="err"?"oklch(0.45 0.18 25)":"var(--hub-ink)"},children:t.value})]},t.label))}):null,q=()=>e.jsx("div",{className:"hub-card px-4 py-3 mb-4",children:e.jsxs("div",{className:"flex flex-wrap gap-3 items-end",children:[e.jsxs("div",{className:"flex-1 min-w-[140px]",children:[e.jsx("label",{className:"sr-only",htmlFor:"activity-server",children:a("activity.server")}),e.jsxs("div",{className:"relative",children:[e.jsx("input",{id:"activity-server",type:"text",value:v,onChange:t=>N(t.target.value),placeholder:a("activity.searchServer"),className:"hub-input pr-9",list:"server-options"}),v&&e.jsx("button",{onClick:()=>N(""),className:"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300","aria-label":a("common.clear"),type:"button",children:e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",clipRule:"evenodd"})})})]}),(r==null?void 0:r.servers)&&e.jsx("datalist",{id:"server-options",children:r.servers.map(t=>e.jsx("option",{value:t},t))})]}),e.jsxs("div",{className:"flex-1 min-w-[140px]",children:[e.jsx("label",{className:"sr-only",htmlFor:"activity-tool",children:a("activity.tool")}),e.jsxs("div",{className:"relative",children:[e.jsx("input",{id:"activity-tool",type:"text",value:p,onChange:t=>w(t.target.value),placeholder:a("activity.searchTool"),className:"hub-input pr-9",list:"tool-options"}),p&&e.jsx("button",{onClick:()=>w(""),className:"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300","aria-label":a("common.clear"),type:"button",children:e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",clipRule:"evenodd"})})})]}),(r==null?void 0:r.tools)&&e.jsx("datalist",{id:"tool-options",children:r.tools.map(t=>e.jsx("option",{value:t},t))})]}),e.jsxs("div",{className:"flex-1 min-w-[140px]",children:[e.jsx("label",{className:"sr-only",htmlFor:"activity-status",children:a("activity.status")}),e.jsxs("div",{className:"relative",children:[e.jsx("input",{id:"activity-status",type:"text",value:x,onChange:t=>k(t.target.value.toLowerCase()),placeholder:a("activity.searchStatus"),className:"hub-input pr-9",list:"activity-status-options"}),x&&e.jsx("button",{onClick:()=>k(""),className:"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300","aria-label":a("common.clear"),type:"button",children:e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",clipRule:"evenodd"})})})]}),e.jsx("datalist",{id:"activity-status-options",children:T.map(t=>e.jsx("option",{value:t},t))})]}),e.jsxs("div",{className:"flex-1 min-w-[140px]",children:[e.jsx("label",{className:"sr-only",htmlFor:"activity-group",children:a("activity.group")}),e.jsxs("div",{className:"relative",children:[e.jsx("input",{id:"activity-group",type:"text",value:g,onChange:t=>S(t.target.value),placeholder:a("activity.searchGroup"),className:"hub-input pr-9",list:"group-options"}),g&&e.jsx("button",{onClick:()=>S(""),className:"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300","aria-label":a("common.clear"),type:"button",children:e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",clipRule:"evenodd"})})})]}),(r==null?void 0:r.groups)&&e.jsx("datalist",{id:"group-options",children:r.groups.map(t=>e.jsx("option",{value:t},t))})]}),e.jsxs("div",{className:"flex-1 min-w-[140px]",children:[e.jsx("label",{className:"sr-only",htmlFor:"activity-keyname",children:a("activity.keyName")}),e.jsxs("div",{className:"relative",children:[e.jsx("input",{id:"activity-keyname",type:"text",value:y,onChange:t=>C(t.target.value),placeholder:a("activity.searchKeyName"),className:"hub-input pr-9",list:"keyname-options"}),y&&e.jsx("button",{onClick:()=>C(""),className:"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300","aria-label":a("common.clear"),type:"button",children:e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",clipRule:"evenodd"})})})]}),(r==null?void 0:r.keyNames)&&e.jsx("datalist",{id:"keyname-options",children:r.keyNames.map(t=>e.jsx("option",{value:t},t))})]}),e.jsxs("div",{className:"flex-shrink-0 flex items-center gap-2",children:[e.jsxs("button",{onClick:O,className:"hub-btn primary whitespace-nowrap",children:[e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-3.5 w-3.5",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z",clipRule:"evenodd"})}),a("common.search")]}),e.jsx("button",{onClick:U,className:"hub-btn whitespace-nowrap",children:a("common.clear")})]})]})}),Q=()=>m.length===0?e.jsx("div",{className:"hub-card p-10 text-center",style:{color:"var(--hub-ink-3)"},children:a("activity.noData")}):e.jsx("div",{className:"hub-card overflow-hidden",children:e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"min-w-full",children:[e.jsx("thead",{style:{background:"var(--hub-bg-2)"},children:e.jsx("tr",{children:[a("activity.timestamp"),a("activity.server"),a("activity.tool"),a("activity.duration"),a("activity.status"),a("activity.group"),a("activity.key"),a("common.actions")].map(t=>e.jsx("th",{className:"hub-mono",style:{padding:"9px 14px",textAlign:"left",fontSize:11,color:"var(--hub-ink-3)",textTransform:"uppercase",letterSpacing:"0.08em",fontWeight:500},children:t},t))})}),e.jsx("tbody",{children:m.map(t=>e.jsxs("tr",{className:"transition-colors hover:bg-[var(--hub-surface-hover)]",style:{borderTop:"1px solid var(--hub-line-2)"},children:[e.jsx("td",{className:"hub-mono whitespace-nowrap",style:{padding:"10px 14px",fontSize:12,color:"var(--hub-ink-2)"},children:D(t.timestamp)}),e.jsx("td",{style:{padding:"10px 14px"},children:e.jsx("span",{className:"hub-tag",children:t.server})}),e.jsx("td",{style:{padding:"10px 14px"},children:e.jsx("span",{className:"hub-tag accent",children:t.tool})}),e.jsx("td",{className:"hub-mono hub-num whitespace-nowrap",style:{padding:"10px 14px",fontSize:12,color:"var(--hub-ink-2)"},children:P(t.duration)}),e.jsx("td",{style:{padding:"10px 14px"},className:"whitespace-nowrap",children:e.jsxs("span",{className:`hub-status ${t.status==="success"?"ok":"err"}`,children:[e.jsx("span",{className:"hub-dot"}),t.status==="success"?a("activity.statusSuccess"):a("activity.statusError")]})}),e.jsx("td",{style:{padding:"10px 14px",fontSize:12,color:"var(--hub-ink-3)"},children:t.group||"—"}),e.jsx("td",{style:{padding:"10px 14px",fontSize:12,color:"var(--hub-ink-3)"},children:t.keyName||"—"}),e.jsx("td",{style:{padding:"10px 14px"},children:e.jsx("button",{onClick:()=>K(t),className:"hub-btn ghost sm",style:{color:"var(--hub-accent)"},children:a("common.view")})})]},t.id))})]})})}),X=()=>{if(!H||!c)return null;const t=E(c.input),s=E(c.output);return e.jsx("div",{className:"fixed inset-0 bg-black/50 flex items-center justify-center z-50",children:e.jsxs("div",{className:"hub-card max-w-4xl w-full mx-4 max-h-[90vh] overflow-hidden",style:{boxShadow:"0 8px 24px rgba(0,0,0,0.12)"},children:[e.jsxs("div",{className:"flex items-center justify-between px-5 py-3",style:{borderBottom:"1px solid var(--hub-line-2)"},children:[e.jsx("h3",{className:"hub-card-title",children:a("activity.details")}),e.jsx("button",{onClick:()=>A(!1),className:"hub-icon-btn sm","aria-label":"close",children:e.jsx("svg",{className:"h-3.5 w-3.5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})})})]}),e.jsxs("div",{className:"px-6 py-4 overflow-y-auto max-h-[calc(90vh-120px)]",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-4 mb-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.timestamp")}),e.jsx("p",{className:"text-gray-900 dark:text-white",children:D(c.timestamp)})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.duration")}),e.jsx("p",{className:"text-gray-900 dark:text-white",children:P(c.duration)})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.server")}),e.jsx("p",{className:"text-gray-900 dark:text-white font-mono",children:c.server})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.tool")}),e.jsx("p",{className:"text-gray-900 dark:text-white font-mono",children:c.tool})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.status")}),e.jsx("span",{className:`px-2 py-1 rounded text-xs font-medium ${c.status==="success"?"bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200":"bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200"}`,children:c.status==="success"?a("activity.statusSuccess"):a("activity.statusError")})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.group")}),e.jsx("p",{className:"text-gray-900 dark:text-white",children:c.group||"-"})]}),c.keyName&&e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.key")}),e.jsx("p",{className:"text-gray-900 dark:text-white",children:c.keyName})]})]}),c.errorMessage&&e.jsxs("div",{className:"mb-4",children:[e.jsx("label",{className:"block text-sm font-medium text-red-500 mb-1",children:a("activity.errorMessage")}),e.jsx("div",{className:"bg-red-50 dark:bg-red-900/20 rounded p-3 text-sm text-red-800 dark:text-red-200",children:c.errorMessage})]}),t&&e.jsxs("div",{className:"mb-4",children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400 mb-1",children:a("activity.input")}),e.jsx("pre",{className:"bg-gray-100 dark:bg-gray-700 rounded p-3 text-sm overflow-x-auto max-h-64",children:typeof t=="string"?t:JSON.stringify(t,null,2)})]}),s&&e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400 mb-1",children:a("activity.output")}),e.jsx("pre",{className:"bg-gray-100 dark:bg-gray-700 rounded p-3 text-sm overflow-x-auto max-h-64",children:typeof s=="string"?s:JSON.stringify(s,null,2)})]})]})]})})};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:a("activity.title")}),e.jsxs("p",{className:"hub-sub",children:[e.jsx("span",{className:"hub-num",children:(i==null?void 0:i.total)??m.length})," entries"]})]}),e.jsxs("button",{onClick:W,className:"hub-btn danger",children:[e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-3.5 w-3.5",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M9 2a1 1 0 00-.894.553L7.382 4H4a1 1 0 000 2v10a2 2 0 002 2h8a2 2 0 002-2V6a1 1 0 100-2h-3.382l-.724-1.447A1 1 0 0011 2H9zM7 8a1 1 0 012 0v6a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v6a1 1 0 102 0V8a1 1 0 00-1-1z",clipRule:"evenodd"})}),a("activity.cleanup")]})]}),z&&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.jsx("span",{className:"truncate text-[13px]",children:z}),e.jsx("button",{className:"hub-icon-btn sm",onClick:()=>f(null),"aria-label":"close",children:e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-3 w-3",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",clipRule:"evenodd"})})})]}),j&&m.length===0?e.jsx("div",{className:"hub-card p-10 text-center",style:{color:"var(--hub-ink-3)"},children:a("app.loading")}):e.jsxs(e.Fragment,{children:[_(),q(),Q(),e.jsxs("div",{className:"flex items-center mt-6",children:[e.jsx("div",{className:"flex-[2] text-sm text-gray-500 dark:text-gray-400",children:i&&a("common.showing",{start:(i.page-1)*i.limit+1,end:Math.min(i.page*i.limit,i.total),total:i.total})}),e.jsx("div",{className:"flex-[4] flex justify-center",children:i&&i.totalPages>1&&e.jsx(se,{currentPage:o,totalPages:i.totalPages,onPageChange:d,disabled:j})}),e.jsxs("div",{className:"flex-[2] flex items-center justify-end space-x-2",children:[e.jsxs("label",{htmlFor:"perPage",className:"text-sm text-gray-500 dark:text-gray-400",children:[a("common.itemsPerPage"),":"]}),e.jsxs("select",{id:"perPage",value:b,onChange:t=>{J(Number(t.target.value)),d(1)},disabled:j,className:"border border-gray-300 dark:border-gray-600 rounded p-1 text-sm dark:bg-gray-700 dark:text-white outline-none disabled:opacity-50 disabled:cursor-not-allowed",children:[e.jsx("option",{value:10,children:"10"}),e.jsx("option",{value:20,children:"20"}),e.jsx("option",{value:50,children:"50"}),e.jsx("option",{value:100,children:"100"})]})]})]})]}),X()]})};export{xe as default};
2
- //# sourceMappingURL=ActivityPage-VwilVMvp.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ActivityPage-VwilVMvp.js","sources":["../../src/pages/ActivityPage.tsx"],"sourcesContent":["import React, { useState, useEffect, useCallback } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport {\n Activity,\n ActivityStats,\n ActivityFilter,\n ActivityFilterOptions,\n ActivityStatus,\n} from '@/types';\nimport {\n getActivities,\n getActivityById,\n getActivityStats,\n getActivityFilterOptions,\n deleteOldActivities,\n} from '@/services/activityService';\nimport Pagination from '@/components/ui/Pagination';\n\n// Pagination info type\ninterface PaginationInfo {\n page: number;\n limit: number;\n total: number;\n totalPages: number;\n hasNextPage: boolean;\n hasPrevPage: boolean;\n}\n\nconst STATUS_OPTIONS: ActivityStatus[] = ['success', 'error'];\n\nconst isValidStatus = (value: string): value is ActivityStatus =>\n STATUS_OPTIONS.includes(value as ActivityStatus);\n\nconst ActivityPage: React.FC = () => {\n const { t } = useTranslation();\n\n // State\n const [activities, setActivities] = useState<Activity[]>([]);\n const [stats, setStats] = useState<ActivityStats | null>(null);\n const [filterOptions, setFilterOptions] = useState<ActivityFilterOptions | null>(null);\n const [pagination, setPagination] = useState<PaginationInfo | null>(null);\n const [currentPage, setCurrentPage] = useState(1);\n const [itemsPerPage, setItemsPerPage] = useState(10);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [selectedActivity, setSelectedActivity] = useState<Activity | null>(null);\n const [showDetailModal, setShowDetailModal] = useState(false);\n\n // Filter state\n const [appliedFilters, setAppliedFilters] = useState<ActivityFilter>({});\n const [searchServer, setSearchServer] = useState('');\n const [searchTool, setSearchTool] = useState('');\n const [searchStatus, setSearchStatus] = useState<string>('');\n const [searchGroup, setSearchGroup] = useState('');\n const [searchKeyName, setSearchKeyName] = useState('');\n\n // Fetch data\n const fetchData = useCallback(async () => {\n setIsLoading(true);\n setError(null);\n\n try {\n // Use appliedFilters directly for fetching\n const currentFilter = { ...appliedFilters };\n\n // Fetch activities, stats, and filter options in parallel\n const [activitiesRes, statsRes, optionsRes] = await Promise.all([\n getActivities(currentPage, itemsPerPage, currentFilter),\n getActivityStats(currentFilter),\n getActivityFilterOptions(),\n ]);\n\n if (activitiesRes?.success && Array.isArray(activitiesRes.data)) {\n setActivities(activitiesRes.data);\n if (activitiesRes.pagination) {\n setPagination(activitiesRes.pagination);\n }\n }\n\n if (statsRes?.success && statsRes.data) {\n setStats(statsRes.data);\n }\n\n if (optionsRes?.success && optionsRes.data) {\n setFilterOptions(optionsRes.data);\n }\n } catch (err) {\n console.error('Error fetching activity data:', err);\n setError(t('activity.fetchError'));\n } finally {\n setIsLoading(false);\n }\n }, [currentPage, itemsPerPage, appliedFilters, t]);\n\n useEffect(() => {\n fetchData();\n }, [fetchData]);\n\n useEffect(() => {\n if (!pagination) {\n return;\n }\n\n const totalPages = Math.max(1, pagination.totalPages || 1);\n if (currentPage > totalPages) {\n setCurrentPage(totalPages);\n }\n }, [pagination, currentPage]);\n\n // Handle view activity details\n const handleViewDetails = async (activity: Activity) => {\n try {\n const response = await getActivityById(activity.id);\n if (response?.success && response.data) {\n setSelectedActivity(response.data);\n setShowDetailModal(true);\n }\n } catch (err) {\n console.error('Error fetching activity details:', err);\n }\n };\n\n // Handle cleanup old activities\n const handleCleanup = async () => {\n if (!window.confirm(t('activity.confirmCleanup'))) {\n return;\n }\n\n try {\n const response = await deleteOldActivities(30);\n if (response?.success) {\n alert(t('activity.cleanupSuccess', { count: response.data?.deletedCount || 0 }));\n fetchData();\n }\n } catch (err) {\n console.error('Error cleaning up activities:', err);\n alert(t('activity.cleanupError'));\n }\n };\n\n // Handle search\n const handleSearch = () => {\n const filters: ActivityFilter = {};\n if (searchServer) filters.server = searchServer;\n if (searchTool) filters.tool = searchTool;\n if (searchStatus && isValidStatus(searchStatus)) {\n filters.status = searchStatus;\n }\n if (searchGroup) filters.group = searchGroup;\n if (searchKeyName) filters.keyName = searchKeyName;\n\n setAppliedFilters(filters);\n setCurrentPage(1);\n };\n\n // Handle clear filters\n const handleClearFilters = () => {\n setSearchServer('');\n setSearchTool('');\n setSearchStatus('');\n setSearchGroup('');\n setSearchKeyName('');\n setAppliedFilters({});\n setCurrentPage(1);\n };\n\n // Format duration\n const formatDuration = (ms: number): string => {\n if (ms < 1000) return `${ms}ms`;\n if (ms < 60000) return `${(ms / 1000).toFixed(2)}s`;\n return `${(ms / 60000).toFixed(2)}m`;\n };\n\n // Format timestamp\n const formatTimestamp = (timestamp: string): string => {\n return new Date(timestamp).toLocaleString();\n };\n\n // Parse JSON safely\n const safeParseJSON = (str: string | undefined): any => {\n if (!str) return null;\n try {\n return JSON.parse(str);\n } catch {\n return str;\n }\n };\n\n // Render stats cards\n const renderStats = () => {\n if (!stats) return null;\n\n return (\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-3 mb-4\">\n {[\n { label: t('activity.totalCalls'), value: stats.totalCalls, tone: 'default' as const },\n { label: t('activity.successCount'), value: stats.successCount, tone: 'ok' as const },\n { label: t('activity.errorCount'), value: stats.errorCount, tone: 'err' as const },\n {\n label: t('activity.avgDuration'),\n value: formatDuration(stats.avgDuration),\n tone: 'default' as const,\n },\n ].map((s) => (\n <div key={s.label} className=\"hub-card\" style={{ padding: '12px 14px' }}>\n <div className=\"text-[12px]\" style={{ color: 'var(--hub-ink-3)' }}>\n {s.label}\n </div>\n <div\n className=\"hub-num\"\n style={{\n fontSize: 22,\n fontWeight: 500,\n lineHeight: 1.1,\n marginTop: 6,\n letterSpacing: '-0.02em',\n color:\n s.tone === 'ok'\n ? 'oklch(0.4 0.13 145)'\n : s.tone === 'err'\n ? 'oklch(0.45 0.18 25)'\n : 'var(--hub-ink)',\n }}\n >\n {s.value}\n </div>\n </div>\n ))}\n </div>\n );\n };\n\n // Render filters\n const renderFilters = () => {\n return (\n <div className=\"hub-card px-4 py-3 mb-4\">\n <div className=\"flex flex-wrap gap-3 items-end\">\n <div className=\"flex-1 min-w-[140px]\">\n <label className=\"sr-only\" htmlFor=\"activity-server\">\n {t('activity.server')}\n </label>\n <div className=\"relative\">\n <input\n id=\"activity-server\"\n type=\"text\"\n value={searchServer}\n onChange={(e) => setSearchServer(e.target.value)}\n placeholder={t('activity.searchServer')}\n className=\"hub-input pr-9\"\n list=\"server-options\"\n />\n {searchServer && (\n <button\n onClick={() => setSearchServer('')}\n className=\"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300\"\n aria-label={t('common.clear')}\n type=\"button\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-4 w-4\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n )}\n </div>\n {filterOptions?.servers && (\n <datalist id=\"server-options\">\n {filterOptions.servers.map((s) => (\n <option key={s} value={s} />\n ))}\n </datalist>\n )}\n </div>\n <div className=\"flex-1 min-w-[140px]\">\n <label className=\"sr-only\" htmlFor=\"activity-tool\">\n {t('activity.tool')}\n </label>\n <div className=\"relative\">\n <input\n id=\"activity-tool\"\n type=\"text\"\n value={searchTool}\n onChange={(e) => setSearchTool(e.target.value)}\n placeholder={t('activity.searchTool')}\n className=\"hub-input pr-9\"\n list=\"tool-options\"\n />\n {searchTool && (\n <button\n onClick={() => setSearchTool('')}\n className=\"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300\"\n aria-label={t('common.clear')}\n type=\"button\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-4 w-4\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n )}\n </div>\n {filterOptions?.tools && (\n <datalist id=\"tool-options\">\n {filterOptions.tools.map((t) => (\n <option key={t} value={t} />\n ))}\n </datalist>\n )}\n </div>\n <div className=\"flex-1 min-w-[140px]\">\n <label className=\"sr-only\" htmlFor=\"activity-status\">\n {t('activity.status')}\n </label>\n <div className=\"relative\">\n <input\n id=\"activity-status\"\n type=\"text\"\n value={searchStatus}\n onChange={(e) => setSearchStatus(e.target.value.toLowerCase())}\n placeholder={t('activity.searchStatus')}\n className=\"hub-input pr-9\"\n list=\"activity-status-options\"\n />\n {searchStatus && (\n <button\n onClick={() => setSearchStatus('')}\n className=\"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300\"\n aria-label={t('common.clear')}\n type=\"button\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-4 w-4\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n )}\n </div>\n <datalist id=\"activity-status-options\">\n {STATUS_OPTIONS.map((status) => (\n <option key={status} value={status} />\n ))}\n </datalist>\n </div>\n <div className=\"flex-1 min-w-[140px]\">\n <label className=\"sr-only\" htmlFor=\"activity-group\">\n {t('activity.group')}\n </label>\n <div className=\"relative\">\n <input\n id=\"activity-group\"\n type=\"text\"\n value={searchGroup}\n onChange={(e) => setSearchGroup(e.target.value)}\n placeholder={t('activity.searchGroup')}\n className=\"hub-input pr-9\"\n list=\"group-options\"\n />\n {searchGroup && (\n <button\n onClick={() => setSearchGroup('')}\n className=\"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300\"\n aria-label={t('common.clear')}\n type=\"button\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-4 w-4\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n )}\n </div>\n {filterOptions?.groups && (\n <datalist id=\"group-options\">\n {filterOptions.groups.map((g) => (\n <option key={g} value={g} />\n ))}\n </datalist>\n )}\n </div>\n <div className=\"flex-1 min-w-[140px]\">\n <label className=\"sr-only\" htmlFor=\"activity-keyname\">\n {t('activity.keyName')}\n </label>\n <div className=\"relative\">\n <input\n id=\"activity-keyname\"\n type=\"text\"\n value={searchKeyName}\n onChange={(e) => setSearchKeyName(e.target.value)}\n placeholder={t('activity.searchKeyName')}\n className=\"hub-input pr-9\"\n list=\"keyname-options\"\n />\n {searchKeyName && (\n <button\n onClick={() => setSearchKeyName('')}\n className=\"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300\"\n aria-label={t('common.clear')}\n type=\"button\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-4 w-4\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n )}\n </div>\n {filterOptions?.keyNames && (\n <datalist id=\"keyname-options\">\n {filterOptions.keyNames.map((k) => (\n <option key={k} value={k} />\n ))}\n </datalist>\n )}\n </div>\n <div className=\"flex-shrink-0 flex items-center gap-2\">\n <button onClick={handleSearch} className=\"hub-btn primary whitespace-nowrap\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-3.5 w-3.5\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z\"\n clipRule=\"evenodd\"\n />\n </svg>\n {t('common.search')}\n </button>\n <button onClick={handleClearFilters} className=\"hub-btn whitespace-nowrap\">\n {t('common.clear')}\n </button>\n </div>\n </div>\n </div>\n );\n };\n\n // Render activity table\n const renderActivityTable = () => {\n if (activities.length === 0) {\n return (\n <div className=\"hub-card p-10 text-center\" style={{ color: 'var(--hub-ink-3)' }}>\n {t('activity.noData')}\n </div>\n );\n }\n\n return (\n <div className=\"hub-card overflow-hidden\">\n <div className=\"overflow-x-auto\">\n <table className=\"min-w-full\">\n <thead style={{ background: 'var(--hub-bg-2)' }}>\n <tr>\n {[\n t('activity.timestamp'),\n t('activity.server'),\n t('activity.tool'),\n t('activity.duration'),\n t('activity.status'),\n t('activity.group'),\n t('activity.key'),\n t('common.actions'),\n ].map((label) => (\n <th\n key={label}\n className=\"hub-mono\"\n style={{\n padding: '9px 14px',\n textAlign: 'left',\n fontSize: 11,\n color: 'var(--hub-ink-3)',\n textTransform: 'uppercase',\n letterSpacing: '0.08em',\n fontWeight: 500,\n }}\n >\n {label}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {activities.map((activity) => (\n <tr\n key={activity.id}\n className=\"transition-colors hover:bg-[var(--hub-surface-hover)]\"\n style={{ borderTop: '1px solid var(--hub-line-2)' }}\n >\n <td\n className=\"hub-mono whitespace-nowrap\"\n style={{ padding: '10px 14px', fontSize: 12, color: 'var(--hub-ink-2)' }}\n >\n {formatTimestamp(activity.timestamp)}\n </td>\n <td style={{ padding: '10px 14px' }}>\n <span className=\"hub-tag\">{activity.server}</span>\n </td>\n <td style={{ padding: '10px 14px' }}>\n <span className=\"hub-tag accent\">{activity.tool}</span>\n </td>\n <td\n className=\"hub-mono hub-num whitespace-nowrap\"\n style={{ padding: '10px 14px', fontSize: 12, color: 'var(--hub-ink-2)' }}\n >\n {formatDuration(activity.duration)}\n </td>\n <td style={{ padding: '10px 14px' }} className=\"whitespace-nowrap\">\n <span\n className={`hub-status ${activity.status === 'success' ? 'ok' : 'err'}`}\n >\n <span className=\"hub-dot\" />\n {activity.status === 'success'\n ? t('activity.statusSuccess')\n : t('activity.statusError')}\n </span>\n </td>\n <td\n style={{ padding: '10px 14px', fontSize: 12, color: 'var(--hub-ink-3)' }}\n >\n {activity.group || '—'}\n </td>\n <td\n style={{ padding: '10px 14px', fontSize: 12, color: 'var(--hub-ink-3)' }}\n >\n {activity.keyName || '—'}\n </td>\n <td style={{ padding: '10px 14px' }}>\n <button\n onClick={() => handleViewDetails(activity)}\n className=\"hub-btn ghost sm\"\n style={{ color: 'var(--hub-accent)' }}\n >\n {t('common.view')}\n </button>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </div>\n );\n };\n\n // Render detail modal\n const renderDetailModal = () => {\n if (!showDetailModal || !selectedActivity) return null;\n\n const inputData = safeParseJSON(selectedActivity.input);\n const outputData = safeParseJSON(selectedActivity.output);\n\n return (\n <div className=\"fixed inset-0 bg-black/50 flex items-center justify-center z-50\">\n <div\n className=\"hub-card max-w-4xl w-full mx-4 max-h-[90vh] overflow-hidden\"\n style={{ boxShadow: '0 8px 24px rgba(0,0,0,0.12)' }}\n >\n <div\n className=\"flex items-center justify-between px-5 py-3\"\n style={{ borderBottom: '1px solid var(--hub-line-2)' }}\n >\n <h3 className=\"hub-card-title\">{t('activity.details')}</h3>\n <button\n onClick={() => setShowDetailModal(false)}\n className=\"hub-icon-btn sm\"\n aria-label=\"close\"\n >\n <svg className=\"h-3.5 w-3.5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </button>\n </div>\n <div className=\"px-6 py-4 overflow-y-auto max-h-[calc(90vh-120px)]\">\n <div className=\"grid grid-cols-2 gap-4 mb-4\">\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.timestamp')}\n </label>\n <p className=\"text-gray-900 dark:text-white\">\n {formatTimestamp(selectedActivity.timestamp)}\n </p>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.duration')}\n </label>\n <p className=\"text-gray-900 dark:text-white\">\n {formatDuration(selectedActivity.duration)}\n </p>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.server')}\n </label>\n <p className=\"text-gray-900 dark:text-white font-mono\">{selectedActivity.server}</p>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.tool')}\n </label>\n <p className=\"text-gray-900 dark:text-white font-mono\">{selectedActivity.tool}</p>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.status')}\n </label>\n <span\n className={`px-2 py-1 rounded text-xs font-medium ${\n selectedActivity.status === 'success'\n ? 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200'\n : 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200'\n }`}\n >\n {selectedActivity.status === 'success'\n ? t('activity.statusSuccess')\n : t('activity.statusError')}\n </span>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.group')}\n </label>\n <p className=\"text-gray-900 dark:text-white\">{selectedActivity.group || '-'}</p>\n </div>\n {selectedActivity.keyName && (\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.key')}\n </label>\n <p className=\"text-gray-900 dark:text-white\">{selectedActivity.keyName}</p>\n </div>\n )}\n </div>\n\n {selectedActivity.errorMessage && (\n <div className=\"mb-4\">\n <label className=\"block text-sm font-medium text-red-500 mb-1\">\n {t('activity.errorMessage')}\n </label>\n <div className=\"bg-red-50 dark:bg-red-900/20 rounded p-3 text-sm text-red-800 dark:text-red-200\">\n {selectedActivity.errorMessage}\n </div>\n </div>\n )}\n\n {inputData && (\n <div className=\"mb-4\">\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400 mb-1\">\n {t('activity.input')}\n </label>\n <pre className=\"bg-gray-100 dark:bg-gray-700 rounded p-3 text-sm overflow-x-auto max-h-64\">\n {typeof inputData === 'string' ? inputData : JSON.stringify(inputData, null, 2)}\n </pre>\n </div>\n )}\n\n {outputData && (\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400 mb-1\">\n {t('activity.output')}\n </label>\n <pre className=\"bg-gray-100 dark:bg-gray-700 rounded p-3 text-sm overflow-x-auto max-h-64\">\n {typeof outputData === 'string'\n ? outputData\n : JSON.stringify(outputData, null, 2)}\n </pre>\n </div>\n )}\n </div>\n </div>\n </div>\n );\n };\n\n return (\n <div>\n <div className=\"flex items-end justify-between gap-4 mb-6\">\n <div>\n <h1 className=\"hub-h1\">{t('activity.title')}</h1>\n <p className=\"hub-sub\">\n <span className=\"hub-num\">{pagination?.total ?? activities.length}</span> entries\n </p>\n </div>\n <button onClick={handleCleanup} className=\"hub-btn danger\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-3.5 w-3.5\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M9 2a1 1 0 00-.894.553L7.382 4H4a1 1 0 000 2v10a2 2 0 002 2h8a2 2 0 002-2V6a1 1 0 100-2h-3.382l-.724-1.447A1 1 0 0011 2H9zM7 8a1 1 0 012 0v6a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v6a1 1 0 102 0V8a1 1 0 00-1-1z\"\n clipRule=\"evenodd\"\n />\n </svg>\n {t('activity.cleanup')}\n </button>\n </div>\n\n {error && (\n <div\n className=\"hub-card flex items-center justify-between gap-3 mb-4\"\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 <span className=\"truncate text-[13px]\">{error}</span>\n <button className=\"hub-icon-btn sm\" onClick={() => setError(null)} aria-label=\"close\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-3 w-3\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n </div>\n )}\n\n {isLoading && activities.length === 0 ? (\n <div className=\"hub-card p-10 text-center\" style={{ color: 'var(--hub-ink-3)' }}>\n {t('app.loading')}\n </div>\n ) : (\n <>\n {renderStats()}\n {renderFilters()}\n {renderActivityTable()}\n\n {/* Pagination */}\n <div className=\"flex items-center mt-6\">\n <div className=\"flex-[2] text-sm text-gray-500 dark:text-gray-400\">\n {pagination &&\n t('common.showing', {\n start: (pagination.page - 1) * pagination.limit + 1,\n end: Math.min(pagination.page * pagination.limit, pagination.total),\n total: pagination.total,\n })}\n </div>\n <div className=\"flex-[4] flex justify-center\">\n {pagination && pagination.totalPages > 1 && (\n <Pagination\n currentPage={currentPage}\n totalPages={pagination.totalPages}\n onPageChange={setCurrentPage}\n disabled={isLoading}\n />\n )}\n </div>\n <div className=\"flex-[2] flex items-center justify-end space-x-2\">\n <label htmlFor=\"perPage\" className=\"text-sm text-gray-500 dark:text-gray-400\">\n {t('common.itemsPerPage')}:\n </label>\n <select\n id=\"perPage\"\n value={itemsPerPage}\n onChange={(e) => {\n setItemsPerPage(Number(e.target.value));\n setCurrentPage(1);\n }}\n disabled={isLoading}\n className=\"border border-gray-300 dark:border-gray-600 rounded p-1 text-sm dark:bg-gray-700 dark:text-white outline-none disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n <option value={10}>10</option>\n <option value={20}>20</option>\n <option value={50}>50</option>\n <option value={100}>100</option>\n </select>\n </div>\n </div>\n </>\n )}\n\n {renderDetailModal()}\n </div>\n );\n};\n\nexport default ActivityPage;\n"],"names":["STATUS_OPTIONS","isValidStatus","value","ActivityPage","t","useTranslation","activities","setActivities","useState","stats","setStats","filterOptions","setFilterOptions","pagination","setPagination","currentPage","setCurrentPage","itemsPerPage","setItemsPerPage","isLoading","setIsLoading","error","setError","selectedActivity","setSelectedActivity","showDetailModal","setShowDetailModal","appliedFilters","setAppliedFilters","searchServer","setSearchServer","searchTool","setSearchTool","searchStatus","setSearchStatus","searchGroup","setSearchGroup","searchKeyName","setSearchKeyName","fetchData","useCallback","currentFilter","activitiesRes","statsRes","optionsRes","getActivities","getActivityStats","getActivityFilterOptions","err","useEffect","totalPages","handleViewDetails","activity","response","getActivityById","handleCleanup","deleteOldActivities","_a","handleSearch","filters","handleClearFilters","formatDuration","ms","formatTimestamp","timestamp","safeParseJSON","str","renderStats","jsx","s","jsxs","renderFilters","e","status","g","k","renderActivityTable","label","renderDetailModal","inputData","outputData","Fragment","Pagination"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- import{b as z,R as m,r as k,j as e}from"./framework-vendor-BUhDPOUZ.js";import{u as E}from"./useServerData-BnLmpLAC.js";import{d as $}from"./index-B9cW2F0H.js";import{u as D}from"./useSettingsData-Cqi9d7Ug.js";import{E as h}from"./EndpointCopy-C59moJ3Y.js";import{S as L}from"./StatusDot-DR803YdX.js";import{u as T}from"./i18n-vendor-Kbr87Ofu.js";import{R as M,P,j as S,k as A}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})]})},U=(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,F=()=>{var j;const{t:s}=T(),l=z(),{allServers:a,error:t,setError:y,isLoading:p,triggerRefresh:C}=E({refreshOnMount:!0}),{groups:b}=$(),{installConfig:u}=D(),[w,x]=m.useState(!1),v=m.useRef(!1);m.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=k.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]),R=k.useMemo(()=>a.slice(0,6),[a]),d=((j=u==null?void 0:u.baseUrl)==null?void 0:j.replace(/\/+$/,""))||"",g=!w;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:()=>C(),children:[e.jsx(M,{size:13})," ",s("common.refresh")]}),e.jsxs("button",{className:"hub-btn primary",onClick:()=>l("/servers"),children:[e.jsx(P,{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(S,{size:14,className:"flex-shrink-0"}),e.jsx("span",{className:"truncate text-[13px]",children:t})]}),e.jsx("button",{className:"hub-icon-btn sm",onClick:()=>y(null),"aria-label":s("app.closeButton"),children:"✕"})]}),g?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&&!g&&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(A,{size:12})]})]}),e.jsxs("div",{className:"hub-row head hub-mono",style:{gridTemplateColumns:"1.3fr 110px 70px 90px 80px 80px 80px"},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")})]}),R.map(r=>{var i,o,f,N;return e.jsxs("div",{className:"hub-row hover cursor-pointer",style:{gridTemplateColumns:"1.3fr 110px 70px 90px 80px 80px 80px"},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(S,{size:13,className:"text-[var(--hub-err)] flex-shrink-0"})]}),e.jsx("div",{children:e.jsx(L,{status:r.status,enabled:r.enabled})}),e.jsx("div",{children:(i=r.config)!=null&&i.type?e.jsx("span",{className:"hub-tag",children:U(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:((f=r.prompts)==null?void 0:f.length)||0}),e.jsx("div",{className:"hub-num hub-mono",style:{fontSize:12.5,color:"var(--hub-ink-2)"},children:((N=r.resources)==null?void 0:N.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{F as default};
2
- //# sourceMappingURL=Dashboard-DuBJTbbA.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Dashboard-DuBJTbbA.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\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: '1.3fr 110px 70px 90px 80px 80px 80px' }}\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: '1.3fr 110px 70px 90px 80px 80px 80px' }}\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>\n <ServerStatusDot status={s.status} enabled={s.enabled} />\n </div>\n <div>\n {s.config?.type ? (\n <span className=\"hub-tag\">{transportLabel(t, s.config.type)}</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","showSkeleton","RefreshCw","Plus","AlertCircle","_","ChevronRight","ServerStatusDot","_b","_c","_d","EndpointCopy","g"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- import{b as E,j as e,r as n,u as q}from"./framework-vendor-BUhDPOUZ.js";import{u as O,g as H,G as T,T as K,L as _,a as V,c as J,b as Q}from"./index-B9cW2F0H.js";import{u as A}from"./i18n-vendor-Kbr87Ofu.js";import{B as X,j as B}from"./icons-vendor-CKgJB3SC.js";const Y=({isOpen:s,onClose:i})=>{const{t:o}=A(),u=E();if(!s)return null;const f=()=>{i(),u("/settings"),setTimeout(()=>{const l=document.querySelector('[data-section="password"]');if(l){l.scrollIntoView({behavior:"smooth",block:"start"});const h=l.querySelector('[role="button"]');h&&!l.querySelector(".mt-4")&&h.click()}},100)},g=l=>{l.target===l.currentTarget&&i()},d=l=>{l.key==="Escape"&&i()};return e.jsx("div",{className:"fixed inset-0 bg-black/50 z-[100] flex items-center justify-center p-4",onClick:g,onKeyDown:d,tabIndex:-1,children:e.jsx("div",{className:"bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full transform transition-all duration-200 ease-out",role:"dialog","aria-modal":"true","aria-labelledby":"password-warning-title","aria-describedby":"password-warning-message",children:e.jsxs("div",{className:"p-6",children:[e.jsxs("div",{className:"flex items-start space-x-3",children:[e.jsx("div",{className:"flex-shrink-0",children:e.jsx("svg",{className:"w-6 h-6 text-yellow-600 dark:text-yellow-400",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z"})})}),e.jsxs("div",{className:"flex-1",children:[e.jsx("h3",{id:"password-warning-title",className:"text-lg font-medium text-gray-900 dark:text-white mb-2",children:o("auth.defaultPasswordWarning")}),e.jsx("p",{id:"password-warning-message",className:"text-gray-600 dark:text-gray-300 leading-relaxed",children:o("auth.defaultPasswordMessage")})]})]}),e.jsxs("div",{className:"flex justify-end space-x-3 mt-6",children:[e.jsx("button",{onClick:i,className:"hub-btn",children:o("common.cancel")}),e.jsx("button",{onClick:f,className:"hub-btn primary",autoFocus:!0,children:o("auth.goToSettings")})]})]})})})},Z=s=>{if(!s)return null;try{const i=typeof window<"u"?window.location.origin:"http://localhost",o=new URL(s,i);return o.origin!==i?null:`${o.pathname}${o.search}${o.hash}`||"/"}catch{return s.startsWith("/")&&!s.startsWith("//")?s:null}},re=()=>{const{t:s}=A(),[i,o]=n.useState(""),[u,f]=n.useState(""),[g,d]=n.useState(null),[l,h]=n.useState(!1),[m,j]=n.useState(null),[v,w]=n.useState(null),[$,D]=n.useState(void 0),[b,y]=n.useState({google:!1,github:!1}),[I,k]=n.useState(!1),{login:F,auth:p}=O(),N=q(),S=E(),c=n.useMemo(()=>{const a=new URLSearchParams(N.search);return Z(a.get("returnUrl"))},[N.search]),C=n.useCallback(a=>{if(!a)return!1;const t=a.toLowerCase();return t.includes("failed to fetch")||t.includes("networkerror")||t.includes("network error")||t.includes("connection refused")||t.includes("unable to connect")||t.includes("fetch error")||t.includes("econnrefused")||t.includes("http 500")||t.includes("internal server error")||t.includes("proxy error")},[]),L=n.useCallback(()=>{if(!c)return"/";if(!c.startsWith("/oauth/authorize"))return c;const a=H();if(!a)return c;try{const t=window.location.origin,r=new URL(c,t);return r.searchParams.set("token",a),`${r.pathname}${r.search}${r.hash}`}catch{const t=c.includes("?")?"&":"?";return`${c}${t}token=${encodeURIComponent(a)}`}},[c]),x=n.useCallback(()=>{c?window.location.assign(L()):S("/")},[L,S,c]);n.useEffect(()=>{!p.loading&&p.isAuthenticated&&x()},[p.isAuthenticated,p.loading,x]),n.useEffect(()=>{(async()=>{var U,z,R,W;const r=(await V()).betterAuth;if(!(r!=null&&r.enabled)){y({google:!1,github:!1});return}D(r.basePath),y({google:((z=(U=r.providers)==null?void 0:U.google)==null?void 0:z.enabled)===!0,github:((W=(R=r.providers)==null?void 0:R.github)==null?void 0:W.enabled)===!0})})()},[]);const G=async a=>{a.preventDefault(),d(null),w(null),h(!0);try{if(!i||!u){d(s("auth.emptyFields")),h(!1);return}const t=await F(i,u);if(t.success)t.isUsingDefaultPassword?k(!0):x();else{const r=t.message;d(C(r)?s("auth.serverUnavailable"):s("auth.loginFailed"))}}catch(t){const r=t instanceof Error?t.message:void 0;d(C(r)?s("auth.serverUnavailable"):s("auth.loginError"))}finally{h(!1)}},P=async a=>{w(null),j(a);try{await J($).signIn.social({provider:a,callbackURL:c||"/",errorCallbackURL:`${Q()}/login`})}catch(t){console.error("Social login error:",t),w(s("auth.socialLoginFailed")),j(null)}},M=()=>{k(!1),x()};return e.jsxs("div",{className:"relative min-h-screen w-full overflow-hidden",style:{background:"var(--hub-bg)",color:"var(--hub-ink)"},children:[e.jsxs("div",{className:"absolute top-3 right-4 z-20 flex items-center gap-1",children:[e.jsx("a",{href:"https://github.com/samanhappy/mcphub",target:"_blank",rel:"noopener noreferrer",className:"hub-icon-btn","aria-label":"GitHub Repository",children:e.jsx(T,{className:"h-4 w-4"})}),e.jsx("a",{href:"https://docs.mcphub.app",target:"_blank",rel:"noopener noreferrer",className:"hub-icon-btn","aria-label":"Documentation",children:e.jsx(X,{className:"h-4 w-4"})}),e.jsx(K,{}),e.jsx(_,{})]}),e.jsx("div",{className:"pointer-events-none absolute inset-0 -z-10",children:e.jsxs("svg",{className:"h-full w-full",style:{opacity:.5},xmlns:"http://www.w3.org/2000/svg",children:[e.jsx("defs",{children:e.jsx("pattern",{id:"grid",width:"32",height:"32",patternUnits:"userSpaceOnUse",children:e.jsx("path",{d:"M 32 0 L 0 0 0 32",fill:"none",stroke:"var(--hub-line-2)",strokeWidth:"0.5"})})}),e.jsx("rect",{width:"100%",height:"100%",fill:"url(#grid)"})]})}),e.jsx("div",{className:"relative mx-auto flex min-h-screen w-full max-w-md items-center justify-center px-6",children:e.jsxs("div",{className:"w-full space-y-8",children:[e.jsxs("div",{className:"flex flex-col items-center gap-3",children:[e.jsxs("div",{className:"relative grid place-items-center",style:{width:44,height:44,borderRadius:10,background:"var(--hub-ink)",color:"white"},children:[e.jsx("span",{className:"hub-mono font-semibold",style:{fontSize:18},children:"M"}),e.jsx("span",{className:"absolute",style:{right:-2,bottom:-2,width:8,height:8,borderRadius:50,background:"var(--hub-ok)",boxShadow:"0 0 0 3px var(--hub-bg)"}})]}),e.jsxs("div",{className:"text-center",children:[e.jsx("h1",{style:{fontSize:20,fontWeight:600,letterSpacing:"-0.02em",color:"var(--hub-ink)"},children:s("app.title")}),e.jsx("p",{className:"hub-sub",style:{marginTop:4},children:s("auth.slogan")})]})]}),e.jsxs("div",{className:"hub-card",style:{padding:"22px 22px 20px",boxShadow:"0 1px 2px rgba(0,0,0,0.02)"},children:[e.jsxs("form",{className:"space-y-3",onSubmit:G,children:[e.jsxs("div",{children:[e.jsx("label",{htmlFor:"username",className:"hub-sect block",style:{marginBottom:6},children:s("auth.username")}),e.jsx("input",{id:"username",name:"username",type:"text",autoComplete:"username",required:!0,className:"hub-input",placeholder:s("auth.username"),value:i,onChange:a=>o(a.target.value)})]}),e.jsxs("div",{children:[e.jsx("label",{htmlFor:"password",className:"hub-sect block",style:{marginBottom:6},children:s("auth.password")}),e.jsx("input",{id:"password",name:"password",type:"password",autoComplete:"current-password",required:!0,className:"hub-input",placeholder:s("auth.password"),value:u,onChange:a=>f(a.target.value)})]}),g&&e.jsxs("div",{className:"flex items-center gap-2",style:{padding:"8px 10px",borderRadius:7,border:"1px solid oklch(0.85 0.1 25)",background:"oklch(0.97 0.03 25)",color:"oklch(0.4 0.18 25)",fontSize:12.5},children:[e.jsx(B,{size:13,className:"flex-shrink-0"}),e.jsx("span",{children:g})]}),e.jsx("button",{type:"submit",disabled:l,className:"hub-btn primary w-full justify-center",style:{height:34},children:s(l?"auth.loggingIn":"auth.login")})]}),(b.google||b.github)&&e.jsxs("div",{className:"mt-5 space-y-3",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"h-px flex-1",style:{background:"var(--hub-line)"}}),e.jsx("span",{className:"hub-sect",style:{textTransform:"uppercase",letterSpacing:"0.08em"},children:s("auth.orContinue")}),e.jsx("div",{className:"h-px flex-1",style:{background:"var(--hub-line)"}})]}),v&&e.jsxs("div",{className:"flex items-center gap-2",style:{padding:"8px 10px",borderRadius:7,border:"1px solid oklch(0.85 0.1 25)",background:"oklch(0.97 0.03 25)",color:"oklch(0.4 0.18 25)",fontSize:12.5},children:[e.jsx(B,{size:13,className:"flex-shrink-0"}),e.jsx("span",{children:v})]}),e.jsxs("div",{className:"space-y-2",children:[b.google&&e.jsx("button",{type:"button",onClick:()=>P("google"),disabled:m!==null,className:"hub-btn w-full justify-center",style:{height:34},children:s(m==="google"?"auth.loggingIn":"auth.loginWithGoogle")}),b.github&&e.jsxs("button",{type:"button",onClick:()=>P("github"),disabled:m!==null,className:"hub-btn w-full justify-center",style:{height:34,background:"var(--hub-ink)",color:"var(--hub-bg)",borderColor:"var(--hub-ink)"},children:[e.jsx(T,{className:"h-3.5 w-3.5"}),s(m==="github"?"auth.loggingIn":"auth.loginWithGithub")]})]})]})]}),e.jsxs("p",{className:"text-center hub-mono",style:{fontSize:11,color:"var(--hub-ink-3)"},children:["v","1.0.0"]})]})}),e.jsx(Y,{isOpen:I,onClose:M})]})};export{re as default};
2
- //# sourceMappingURL=LoginPage-C8RkMoJN.js.map