diff --git a/src/app/(dashboard)/dashboard/endpoint/ApiEndpointsTab.tsx b/src/app/(dashboard)/dashboard/endpoint/ApiEndpointsTab.tsx new file mode 100644 index 0000000000..3442d05d87 --- /dev/null +++ b/src/app/(dashboard)/dashboard/endpoint/ApiEndpointsTab.tsx @@ -0,0 +1,46 @@ +"use client"; + +import { Card } from "@/shared/components"; +import { useTranslations } from "next-intl"; + +export default function ApiEndpointsTab() { + const t = useTranslations("endpoints"); + + return ( +
+ +
+ code +
+

{t("apiEndpointsTitle")}

+

{t("apiEndpointsDescription")}

+
+ construction + {t("comingSoon")} +
+
+ + +

{t("plannedFeatures")}

+ +
+
+ ); +} diff --git a/src/app/(dashboard)/dashboard/endpoint/page.tsx b/src/app/(dashboard)/dashboard/endpoint/page.tsx index 96a3e31e01..01cb7f76a4 100644 --- a/src/app/(dashboard)/dashboard/endpoint/page.tsx +++ b/src/app/(dashboard)/dashboard/endpoint/page.tsx @@ -1,7 +1,141 @@ +"use client"; + +import { useState, useEffect, useCallback } from "react"; +import { SegmentedControl } from "@/shared/components"; import { getMachineId } from "@/shared/utils/machine"; import EndpointPageClient from "./EndpointPageClient"; +import McpDashboardPage from "../mcp/page"; +import A2ADashboardPage from "../a2a/page"; +import ApiEndpointsTab from "./ApiEndpointsTab"; +import { useTranslations } from "next-intl"; -export default async function EndpointPage() { - const machineId = await getMachineId(); - return ; +type ServiceStatus = { + online: boolean; + loading: boolean; +}; + +function ServiceToggle({ + label, + status, + onRefresh, +}: { + label: string; + status: ServiceStatus; + onRefresh: () => void; +}) { + return ( +
+ +
+ ); +} + +export default function EndpointPage() { + const [activeTab, setActiveTab] = useState("endpoint-proxy"); + const t = useTranslations("endpoints"); + + const [mcpStatus, setMcpStatus] = useState({ online: false, loading: true }); + const [a2aStatus, setA2aStatus] = useState({ online: false, loading: true }); + + const refreshMcpStatus = useCallback(async () => { + setMcpStatus((prev) => ({ ...prev, loading: true })); + try { + const res = await fetch("/api/mcp/status"); + if (res.ok) { + const data = await res.json(); + setMcpStatus({ online: !!data.online, loading: false }); + } else { + setMcpStatus({ online: false, loading: false }); + } + } catch { + setMcpStatus({ online: false, loading: false }); + } + }, []); + + const refreshA2aStatus = useCallback(async () => { + setA2aStatus((prev) => ({ ...prev, loading: true })); + try { + const res = await fetch("/api/a2a/status"); + if (res.ok) { + const data = await res.json(); + setA2aStatus({ online: data.status === "ok", loading: false }); + } else { + setA2aStatus({ online: false, loading: false }); + } + } catch { + setA2aStatus({ online: false, loading: false }); + } + }, []); + + useEffect(() => { + const load = () => { + void refreshMcpStatus(); + void refreshA2aStatus(); + }; + load(); + const interval = setInterval(load, 30000); + return () => clearInterval(interval); + }, [refreshMcpStatus, refreshA2aStatus]); + + return ( +
+
+ + + {activeTab === "mcp" && ( + + )} + {activeTab === "a2a" && ( + + )} +
+ + {activeTab === "endpoint-proxy" && } + {activeTab === "mcp" && } + {activeTab === "a2a" && } + {activeTab === "api-endpoints" && } +
+ ); } diff --git a/src/i18n/messages/en.json b/src/i18n/messages/en.json index 289345a7c0..413cda0f9b 100644 --- a/src/i18n/messages/en.json +++ b/src/i18n/messages/en.json @@ -74,9 +74,7 @@ "translator": "Translator", "docs": "Docs", "issues": "Issues", - "endpoint": "Endpoint", - "mcp": "MCP", - "a2a": "A2A", + "endpoints": "Endpoints", "apiManager": "API Manager", "logs": "Logs", "auditLog": "Audit Log", @@ -128,12 +126,8 @@ "cliToolsDescription": "Configure CLI tools", "home": "Home", "homeDescription": "Welcome to OmniRoute", - "endpoint": "Endpoint", - "endpointDescription": "API endpoint configuration", - "mcp": "MCP Management", - "mcpDescription": "Monitor MCP server process, tools, and operational controls", - "a2a": "A2A Management", - "a2aDescription": "Monitor Agent2Agent status, tasks, and streaming activity", + "endpoint": "Endpoints", + "endpointDescription": "Manage proxy endpoints, MCP, A2A, and API endpoints", "settings": "Settings", "settingsDescription": "Manage your preferences", "openaiCompatible": "OpenAI Compatible", @@ -821,6 +815,18 @@ "a2aQuickStartStep2": "Send JSON-RPC requests to `POST /a2a` using `message/send` or `message/stream`.", "a2aQuickStartStep3": "Track and control tasks using `tasks/get` and `tasks/cancel`." }, + "endpoints": { + "tabProxy": "Endpoint Proxy", + "tabApiEndpoints": "API Endpoints", + "apiEndpointsTitle": "API Endpoints", + "apiEndpointsDescription": "Backend API endpoints that can be consumed by other applications and services. This section will list all available REST APIs with documentation and testing capabilities.", + "comingSoon": "Coming Soon", + "plannedFeatures": "Planned Features", + "featureRestApi": "REST API endpoint catalog with interactive documentation", + "featureWebhooks": "Webhook configuration and event subscriptions", + "featureSwagger": "OpenAPI / Swagger spec auto-generation", + "featureAuth": "API key and OAuth scope management per endpoint" + }, "mcpDashboard": { "loading": "Loading MCP dashboard...", "activate": "activate", diff --git a/src/i18n/messages/pt.json b/src/i18n/messages/pt.json index f7eb5ad244..e111ffe8df 100644 --- a/src/i18n/messages/pt.json +++ b/src/i18n/messages/pt.json @@ -74,9 +74,7 @@ "translator": "Tradutor", "docs": "Documentos", "issues": "Problemas", - "endpoint": "Ponto final", - "mcp": "MCP", - "a2a": "A2A", + "endpoints": "Endpoints", "apiManager": "Gerenciador de APIs", "logs": "Registros", "auditLog": "Registro de auditoria", @@ -128,12 +126,8 @@ "cliToolsDescription": "Configurar ferramentas CLI", "home": "Página inicial", "homeDescription": "Bem-vindo ao OmniRoute", - "endpoint": "Ponto final", - "endpointDescription": "Configuração de endpoint de API", - "mcp": "MCP Management", - "mcpDescription": "Monitor MCP server process, tools, and operational controls", - "a2a": "A2A Management", - "a2aDescription": "Monitor Agent2Agent status, tasks, and streaming activity", + "endpoint": "Endpoints", + "endpointDescription": "Gerenciar endpoints proxy, MCP, A2A e endpoints de API", "settings": "Configurações", "settingsDescription": "Gerencie suas preferências", "openaiCompatible": "Compatível com OpenAI", @@ -821,6 +815,18 @@ "a2aQuickStartStep2": "Send JSON-RPC requests to `POST /a2a` using `message/send` or `message/stream`.", "a2aQuickStartStep3": "Track and control tasks using `tasks/get` and `tasks/cancel`." }, + "endpoints": { + "tabProxy": "Endpoint Proxy", + "tabApiEndpoints": "Endpoints de API", + "apiEndpointsTitle": "Endpoints de API", + "apiEndpointsDescription": "Endpoints de API backend que podem ser consumidos por outras aplicações e serviços. Esta seção listará todas as APIs REST disponíveis com documentação e testes.", + "comingSoon": "Em Breve", + "plannedFeatures": "Funcionalidades Planejadas", + "featureRestApi": "Catálogo de endpoints REST API com documentação interativa", + "featureWebhooks": "Configuração de webhooks e assinaturas de eventos", + "featureSwagger": "Geração automática de specs OpenAPI / Swagger", + "featureAuth": "Gestão de chaves API e escopos OAuth por endpoint" + }, "mcpDashboard": { "loading": "Loading MCP dashboard...", "activate": "activate", diff --git a/src/shared/components/Sidebar.tsx b/src/shared/components/Sidebar.tsx index 501d61d2b7..eb2f0b9399 100644 --- a/src/shared/components/Sidebar.tsx +++ b/src/shared/components/Sidebar.tsx @@ -14,9 +14,7 @@ import { useTranslations } from "next-intl"; // Nav items use i18n keys resolved inside the component const navItemDefs = [ { href: "/dashboard", i18nKey: "home", icon: "home", exact: true }, - { href: "/dashboard/endpoint", i18nKey: "endpoint", icon: "api" }, - { href: "/dashboard/mcp", i18nKey: "mcp", icon: "hub" }, - { href: "/dashboard/a2a", i18nKey: "a2a", icon: "group_work" }, + { href: "/dashboard/endpoint", i18nKey: "endpoints", icon: "api" }, { href: "/dashboard/api-manager", i18nKey: "apiManager", icon: "vpn_key" }, { href: "/dashboard/providers", i18nKey: "providers", icon: "dns" }, { href: "/dashboard/combos", i18nKey: "combos", icon: "layers" },