Files
aiops/frontend/src/components/monitor/dashboard/GrafanaDashboard.tsx
T

79 lines
3.4 KiB
TypeScript

// 监控大屏 — 标签页切换 Agent / Zabbix / Prometheus // Logan.Li
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Monitor, Server, Activity, Maximize2, Minimize2 } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { PageShell } from '@/components/layout/PageShell';
import { promDatasourceApi, zabbixDatasourceApi } from '@/api';
import { ZabbixDashboard } from './ZabbixDashboard';
import { PrometheusDashboard } from './PrometheusDashboard';
import i18n from '@/i18n';
import type { TabId } from './grafana-dashboard/types';
import { AgentTab } from './grafana-dashboard/AgentTab';
import { ExternalDatasourceTab } from './grafana-dashboard/ExternalDatasourceTab';
import { normalizeDatasourceList } from './grafana-dashboard/datasource-toolbar';
// ═══════════ Tab 配置 ═══════════
const getTabs = (): { id: TabId; label: string; icon: React.ReactNode }[] => [
{ id: 'agent', label: i18n.t('monitor.dashboard.tab.agent'), icon: <Server className="w-3.5 h-3.5" /> },
{ id: 'zabbix', label: 'Zabbix', icon: <Activity className="w-3.5 h-3.5" /> },
{ id: 'prometheus', label: 'Prometheus', icon: <Activity className="w-3.5 h-3.5" /> },
];
// ═══════════ Zabbix Tab(薄包装) ═══════════
const ZabbixTab: React.FC = () => (
<ExternalDatasourceTab
fetcher={async () => normalizeDatasourceList(await zabbixDatasourceApi.list())}
loadingLabel={i18n.t('monitor.dashboard.zabbix.loading')}
emptyTitle={i18n.t('monitor.dashboard.zabbix.emptyTitle')}
>
{(ds) => <ZabbixDashboard key={String(ds.id)} dsUrl={ds.url} dsUsername={ds.username} dsPassword={ds.password} />}
</ExternalDatasourceTab>
);
// ═══════════ Prometheus Tab(薄包装) ═══════════
const PrometheusTab: React.FC = () => (
<ExternalDatasourceTab
fetcher={async () => normalizeDatasourceList(await promDatasourceApi.list())}
loadingLabel={i18n.t('monitor.dashboard.prometheus.loading')}
emptyTitle={i18n.t('monitor.dashboard.prometheus.emptyTitle')}
>
{(ds) => <PrometheusDashboard key={String(ds.id)} dsUrl={ds.url} />}
</ExternalDatasourceTab>
);
// ═══════════ 主组件 ═══════════
const GrafanaDashboard: React.FC = () => {
useTranslation();
const [tab, setTab] = useState<TabId>('agent');
const [fullscreen, setFullscreen] = useState(false);
const tabs = getTabs();
const pageTabs = tabs.map((item) => ({ id: item.id, label: item.label }));
return (
<PageShell
variant="workspace"
title={i18n.t('monitor.dashboard.title')}
subtitle={i18n.t('monitor.dashboard.subtitle')}
icon={<Monitor className="h-5 w-5" />}
tabs={pageTabs}
activeTab={tab}
onTabChange={(id) => setTab(id as TabId)}
className={fullscreen ? 'fixed inset-0 z-50 bg-background p-4 overflow-auto' : undefined}
contentClassName="min-h-[50vh]"
actions={
<Button variant="ghost" size="sm" className="h-7 w-7 p-0" onClick={() => setFullscreen(!fullscreen)}>
{fullscreen ? <Minimize2 className="w-3.5 h-3.5" /> : <Maximize2 className="w-3.5 h-3.5" />}
</Button>
}
>
{tab === 'agent' && <AgentTab />}
{tab === 'zabbix' && <ZabbixTab />}
{tab === 'prometheus' && <PrometheusTab />}
</PageShell>
);
};
export default GrafanaDashboard;