feat: Redirect root to /insight, update Insight service card details, and enable live data fetching for observability adapters.
This commit is contained in:
parent
7112aae0ad
commit
2b121a3d21
2
next-env.d.ts
vendored
2
next-env.d.ts
vendored
@ -1,6 +1,6 @@
|
||||
/// <reference types="next" />
|
||||
/// <reference types="next/image-types/global" />
|
||||
import "./.next/dev/types/routes.d.ts";
|
||||
import "./.next/types/routes.d.ts";
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
||||
|
||||
@ -58,7 +58,7 @@ export function InsightSidebarContent({
|
||||
<SidebarHeader className={`flex items-start justify-between mb-7 ${collapsed ? 'flex-col items-center gap-4' : ''}`}>
|
||||
{!collapsed && (
|
||||
<div className="space-y-2">
|
||||
<h1 className="text-lg font-semibold text-slate-100">Insight Workbench</h1>
|
||||
<h1 className="text-lg font-semibold text-slate-100">Observability Workbench</h1>
|
||||
<p className="text-sm text-slate-400">
|
||||
Navigate topology, run cross-domain queries and keep SLOs on track.
|
||||
</p>
|
||||
@ -94,8 +94,8 @@ export function InsightSidebarContent({
|
||||
<button
|
||||
onClick={() => onSelectSection(section.id)}
|
||||
className={`w-full rounded-xl transition ${collapsed
|
||||
? 'flex flex-col items-center gap-2 px-2 py-3'
|
||||
: 'flex items-center gap-3 px-3 py-2 text-left'
|
||||
? 'flex flex-col items-center gap-2 px-2 py-3'
|
||||
: 'flex items-center gap-3 px-3 py-2 text-left'
|
||||
} ${active
|
||||
? 'bg-slate-800 text-slate-100 shadow-inner shadow-slate-800/60'
|
||||
: 'text-slate-300 hover:bg-slate-800/60'
|
||||
@ -128,8 +128,8 @@ export function InsightSidebarContent({
|
||||
<button
|
||||
key={option.id}
|
||||
className={`flex flex-col rounded-xl border px-3 py-2 text-left transition ${activeMode
|
||||
? 'border-emerald-500/70 bg-emerald-500/10 text-emerald-200'
|
||||
: 'border-slate-800 bg-slate-900/70 text-slate-200 hover:border-slate-700'
|
||||
? 'border-emerald-500/70 bg-emerald-500/10 text-emerald-200'
|
||||
: 'border-slate-800 bg-slate-900/70 text-slate-200 hover:border-slate-700'
|
||||
}`}
|
||||
onClick={() => onTopologyChange(option.id)}
|
||||
type="button"
|
||||
@ -161,8 +161,8 @@ export function InsightSidebarContent({
|
||||
<button
|
||||
key={option.id}
|
||||
className={`flex items-center justify-between rounded-xl border px-3 py-2 text-left text-sm transition ${activeLanguage
|
||||
? 'border-emerald-500/70 bg-emerald-500/10 text-emerald-200'
|
||||
: 'border-slate-800 bg-slate-900/70 text-slate-200 hover:border-slate-700'
|
||||
? 'border-emerald-500/70 bg-emerald-500/10 text-emerald-200'
|
||||
: 'border-slate-800 bg-slate-900/70 text-slate-200 hover:border-slate-700'
|
||||
}`}
|
||||
onClick={() => onToggleLanguage(option.id)}
|
||||
type="button"
|
||||
|
||||
@ -20,9 +20,8 @@ const mockLogs: LogEntry[] = Array.from({ length: 25 }).map((_, idx) => ({
|
||||
}))
|
||||
|
||||
export async function fetchLogs(query: string) {
|
||||
void query
|
||||
await new Promise(resolve => setTimeout(resolve, 200))
|
||||
return mockLogs
|
||||
const adapter = createLogsAdapter()
|
||||
return adapter.queryLogs(query)
|
||||
}
|
||||
|
||||
export function createLogsAdapter(baseUrl?: string, token?: string) {
|
||||
@ -30,15 +29,10 @@ export function createLogsAdapter(baseUrl?: string, token?: string) {
|
||||
return {
|
||||
async queryLogs(query: string, params?: Record<string, string>) {
|
||||
void params
|
||||
try {
|
||||
return await client.request<LogEntry[]>(`/logs/query`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ query })
|
||||
})
|
||||
} catch (err) {
|
||||
console.warn('Logs adapter fallback to mock', err)
|
||||
return fetchLogs(query)
|
||||
}
|
||||
return await client.request<LogEntry[]>(`/logs/query`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ query })
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@ export interface ClientOptions {
|
||||
}
|
||||
|
||||
export function createOpenObserveClient(options: ClientOptions = {}) {
|
||||
const { baseUrl = '/api', token } = options
|
||||
const { baseUrl = 'https://infra.svc.plus/api', token } = options
|
||||
|
||||
async function request<T>(path: string, init?: RequestInit): Promise<T> {
|
||||
const headers = new Headers(init?.headers)
|
||||
|
||||
@ -28,10 +28,8 @@ const mockSeries: PrometheusResponse[] = [
|
||||
]
|
||||
|
||||
export async function fetchPromQL(query: string) {
|
||||
void query
|
||||
// Replace with API call when backend is ready.
|
||||
await new Promise(resolve => setTimeout(resolve, 300))
|
||||
return mockSeries
|
||||
const adapter = createPrometheusAdapter()
|
||||
return adapter.queryRange(query)
|
||||
}
|
||||
|
||||
export function createPrometheusAdapter(baseUrl?: string, token?: string) {
|
||||
@ -39,15 +37,13 @@ export function createPrometheusAdapter(baseUrl?: string, token?: string) {
|
||||
return {
|
||||
async queryRange(query: string, params?: Record<string, string>) {
|
||||
void params
|
||||
try {
|
||||
return await client.request<PrometheusResponse[]>(`/prometheus/query`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ query })
|
||||
})
|
||||
} catch (err) {
|
||||
console.warn('Prometheus adapter fallback to mock', err)
|
||||
return fetchPromQL(query)
|
||||
}
|
||||
return await client.request<PrometheusResponse[]>(`/prometheus/api/v1/query`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
body: new URLSearchParams({ query }).toString()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,9 +44,8 @@ const mockTrace: TraceSpan[] = [
|
||||
]
|
||||
|
||||
export async function fetchTraces(query: string) {
|
||||
void query
|
||||
await new Promise(resolve => setTimeout(resolve, 250))
|
||||
return mockTrace
|
||||
const adapter = createTracesAdapter()
|
||||
return adapter.queryTraces(query)
|
||||
}
|
||||
|
||||
export function createTracesAdapter(baseUrl?: string, token?: string) {
|
||||
@ -54,15 +53,10 @@ export function createTracesAdapter(baseUrl?: string, token?: string) {
|
||||
return {
|
||||
async queryTraces(query: string, params?: Record<string, string>) {
|
||||
void params
|
||||
try {
|
||||
return await client.request<TraceSpan[]>(`/traces/query`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ query })
|
||||
})
|
||||
} catch (err) {
|
||||
console.warn('Traces adapter fallback to mock', err)
|
||||
return fetchTraces(query)
|
||||
}
|
||||
return await client.request<TraceSpan[]>(`/traces/query`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ query })
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -118,40 +118,11 @@ const shortcuts = [
|
||||
},
|
||||
];
|
||||
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
export default function HomePage() {
|
||||
const { mode, isOpen, setIsOpen, setMinimized, close } = useMoltbotStore();
|
||||
const isSidebar = mode !== 'overlay' && isOpen;
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-background text-text transition-colors duration-150 flex flex-col">
|
||||
<UnifiedNavigation />
|
||||
|
||||
<div className={cn(
|
||||
"flex flex-1 relative overflow-hidden",
|
||||
mode === 'left-sidebar' && "flex-row-reverse"
|
||||
)}>
|
||||
<div className="flex-1 overflow-y-auto relative">
|
||||
<div className="relative mx-auto max-w-7xl px-6 pb-20">
|
||||
<div
|
||||
className="absolute inset-0 bg-gradient-app-from opacity-20 pointer-events-none"
|
||||
aria-hidden
|
||||
/>
|
||||
<main className="relative space-y-12 pt-10">
|
||||
<HeroSection />
|
||||
<NextStepsSection />
|
||||
<StatsSection />
|
||||
<ShortcutsSection />
|
||||
</main>
|
||||
<div className="relative">
|
||||
<Footer />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
redirect("/insight");
|
||||
return null;
|
||||
}
|
||||
|
||||
export function HeroSection() {
|
||||
|
||||
@ -246,23 +246,13 @@ export default function ServicesPage() {
|
||||
},
|
||||
{
|
||||
key: "insight",
|
||||
name: isChinese ? "Insight 工作台" : "Insight Workbench",
|
||||
name: isChinese ? "监控与观测" : "Monitoring & Observability",
|
||||
description: isChinese
|
||||
? "进入观测、告警与智能协作控制面。"
|
||||
: "Observability, alerts, and AI-assisted operations.",
|
||||
? "基础设施、数据库与应用系统的全栈可观测性工作台。"
|
||||
: "Full-stack observability workbench for infrastructure, databases, and apps.",
|
||||
href: "/insight",
|
||||
icon: Gauge,
|
||||
},
|
||||
{
|
||||
key: "infra-monitor",
|
||||
name: isChinese ? "基础设施监控" : "Infrastructure Monitoring",
|
||||
description: isChinese
|
||||
? "基于 Pigsty 4.0 (Apache-2.0) 构建的开源可观测性与监控平台。"
|
||||
: "Open-source observability based on Pigsty 4.0 (Apache-2.0).",
|
||||
href: "https://infra.svc.plus/",
|
||||
icon: Database,
|
||||
external: true,
|
||||
},
|
||||
{
|
||||
key: "ai-gateway",
|
||||
name: isChinese ? "AI 网关" : "AI Gateway",
|
||||
|
||||
Loading…
Reference in New Issue
Block a user