chore(backend): добавить поддержку ACME и управление сертификатами
This commit is contained in:
+887
-254
File diff suppressed because it is too large
Load Diff
@@ -289,8 +289,8 @@ function ProbeSourceCell({ probe, catalog }: { probe: PingProbe; catalog: Server
|
||||
|
||||
export default function DashboardPage() {
|
||||
const pathname = usePathname()
|
||||
const { mode, backendUrl } = useDataSource()
|
||||
const isLive = mode === "live"
|
||||
const { mode, backendUrl, prefsHydrated } = useDataSource()
|
||||
const isLive = prefsHydrated && mode === "live"
|
||||
const apiFetch = useMemo(() => makeApiFetch(backendUrl), [backendUrl])
|
||||
|
||||
const [liveProbes, setLiveProbes] = useState<PingProbe[] | null>(null)
|
||||
@@ -306,9 +306,10 @@ export default function DashboardPage() {
|
||||
const [internetPathError, setInternetPathError] = useState<string | null>(null)
|
||||
|
||||
const probeServerCatalog = useMemo(() => {
|
||||
if (!prefsHydrated) return []
|
||||
if (!isLive) return mockServers
|
||||
return liveServersResolved ?? []
|
||||
}, [isLive, liveServersResolved])
|
||||
}, [prefsHydrated, isLive, liveServersResolved])
|
||||
|
||||
const fetchProbes = useCallback(async (silent: boolean) => {
|
||||
if (!isLive) return
|
||||
@@ -523,13 +524,15 @@ export default function DashboardPage() {
|
||||
}, [mockDashEpoch])
|
||||
|
||||
const activeProbesTable = useMemo(() => {
|
||||
if (!prefsHydrated) return []
|
||||
if (!isLive) return mockActiveProbes
|
||||
if (liveProbes === null && probesLoading) return []
|
||||
if (liveProbes === null) return []
|
||||
return liveProbes.filter((p) => p.enabled && p.showOnDashboard === true)
|
||||
}, [isLive, liveProbes, probesLoading, mockActiveProbes])
|
||||
}, [prefsHydrated, isLive, liveProbes, probesLoading, mockActiveProbes])
|
||||
|
||||
const probesSubtitle = useMemo(() => {
|
||||
if (!prefsHydrated) return "Загрузка…"
|
||||
if (!isLive) {
|
||||
const starred = mockActiveProbes.length
|
||||
return starred > 0
|
||||
@@ -541,10 +544,13 @@ export default function DashboardPage() {
|
||||
return n > 0
|
||||
? `${n} на дашборде · последний час (API)`
|
||||
: "Нет проб на дашборде · отметьте звёздочкой на странице мониторинга"
|
||||
}, [isLive, mockActiveProbes.length, probesError, liveProbes, activeProbesTable.length])
|
||||
}, [prefsHydrated, isLive, mockActiveProbes.length, probesError, liveProbes, activeProbesTable.length])
|
||||
|
||||
/** Карточка «Состояние серверов»: в Live — `/api/servers` (тот же запрос, что и для каталога проб). */
|
||||
const serverStatusModel = useMemo(() => {
|
||||
if (!prefsHydrated) {
|
||||
return { kind: "loading" as const, subtitle: "Загрузка…" }
|
||||
}
|
||||
if (!isLive) {
|
||||
return {
|
||||
kind: "mock" as const,
|
||||
@@ -571,9 +577,12 @@ export default function DashboardPage() {
|
||||
servers,
|
||||
subtitle: `${servers.length} узлов · ${onlineN} онлайн · API`,
|
||||
}
|
||||
}, [isLive, liveServersResolved, probesLoading, probesError])
|
||||
}, [prefsHydrated, isLive, liveServersResolved, probesLoading, probesError])
|
||||
|
||||
const latencyChartBlock = useMemo(() => {
|
||||
if (!prefsHydrated) {
|
||||
return { kind: "loading" as const }
|
||||
}
|
||||
if (!isLive) {
|
||||
return {
|
||||
kind: "mock" as const,
|
||||
@@ -612,7 +621,7 @@ export default function DashboardPage() {
|
||||
subtitle:
|
||||
"Средний RTT по источникам проб · окно 1 ч · до 8 узлов · API",
|
||||
}
|
||||
}, [isLive, liveProbes, probesLoading, liveServersResolved])
|
||||
}, [prefsHydrated, isLive, liveProbes, probesLoading, liveServersResolved])
|
||||
|
||||
const dashboardKpi = useMemo(() => {
|
||||
const sparkSrv = [5, 5, 6, 6, 5, 6, 6, 6, 7, 6, 6, 6, 6, 6, 6, 6, 6]
|
||||
@@ -620,6 +629,24 @@ export default function DashboardPage() {
|
||||
const sparkBgp = [7800, 7900, 8000, 8100, 8050, 8120, 8200, 8240, 8300, 8350, 8380, 8400, 8420, 8430, 8432]
|
||||
const sparkAlt = [1, 2, 2, 3, 3, 4, 5, 4, 4, 4, 3, 3, 4, 4, 4]
|
||||
|
||||
const loadingKpi = (sparkColor: string) => ({
|
||||
value: "—",
|
||||
unit: undefined as string | undefined,
|
||||
delta: "Загрузка…",
|
||||
deltaDir: "up" as const,
|
||||
spark: undefined as number[] | undefined,
|
||||
sparkColor,
|
||||
})
|
||||
|
||||
if (!prefsHydrated) {
|
||||
return {
|
||||
servers: loadingKpi("var(--chart-line-1)"),
|
||||
filters: loadingKpi("var(--chart-line-2)"),
|
||||
bgp: loadingKpi("var(--chart-line-4)"),
|
||||
alerts: loadingKpi("var(--chart-5)"),
|
||||
}
|
||||
}
|
||||
|
||||
if (!isLive) {
|
||||
const totalSrv = mockServers.length
|
||||
const onlineSrv = mockServers.filter((s) => s.status === "online").length
|
||||
@@ -730,7 +757,7 @@ export default function DashboardPage() {
|
||||
sparkColor: "var(--chart-5)",
|
||||
},
|
||||
}
|
||||
}, [isLive, liveServersResolved, liveKpi, liveProbes, probesLoading])
|
||||
}, [prefsHydrated, isLive, liveServersResolved, liveKpi, liveProbes, probesLoading])
|
||||
|
||||
return (
|
||||
<div className="flex flex-col h-full">
|
||||
|
||||
Reference in New Issue
Block a user