diff --git a/PROJECTS/advanced/monitor-the-situation-dashboard/frontend/src/pages/panels/DShieldPanel.tsx b/PROJECTS/advanced/monitor-the-situation-dashboard/frontend/src/pages/panels/DShieldPanel.tsx index 708c5b44..30964cec 100644 --- a/PROJECTS/advanced/monitor-the-situation-dashboard/frontend/src/pages/panels/DShieldPanel.tsx +++ b/PROJECTS/advanced/monitor-the-situation-dashboard/frontend/src/pages/panels/DShieldPanel.tsx @@ -11,24 +11,29 @@ const THOUSAND = 1_000 const MILLION = 1_000_000 interface DShieldPort { - port: number + rank: number + targetport: number records: number + targets: number + sources: number } interface DShieldSource { - ip: string - country?: string - records: number + rank: number + source: string + reports: number + targets: number } interface DShieldDailySummary { + date: string records: number sources: number targets: number } interface DShieldData { - topports?: DShieldPort[] + topports?: Record | DShieldPort[] topips?: DShieldSource[] dailysummary?: DShieldDailySummary[] } @@ -36,7 +41,18 @@ interface DShieldData { export function DShieldPanel(): React.ReactElement { const { data } = useSnapshot() const ds = (data?.scan_firehose as DShieldData | undefined) ?? {} - const summary = ds.dailysummary?.[0] + + const ports = toArray(ds.topports) + .slice() + .sort((a, b) => a.rank - b.rank) + .slice(0, PORT_ROW_LIMIT) + + const sources = (ds.topips ?? []) + .slice() + .sort((a, b) => a.rank - b.rank) + .slice(0, SOURCE_ROW_LIMIT) + + const summary = pickLatestSummary(ds.dailysummary) return ( Port - Hits / 24h + Hits + Src - {(ds.topports ?? []).slice(0, PORT_ROW_LIMIT).map((p) => ( - - {p.port} - {p.records.toLocaleString()} + {ports.map((p) => ( + + {p.targetport} + {fmtN(p.records)} + {fmtN(p.sources)} ))} @@ -67,16 +85,16 @@ export function DShieldPanel(): React.ReactElement { Source IP - CC - Hits + Reports + Tgt - {(ds.topips ?? []).slice(0, SOURCE_ROW_LIMIT).map((s) => ( - - {s.ip} - {s.country ?? '—'} - {s.records.toLocaleString()} + {sources.map((s) => ( + + {s.source} + {fmtN(s.reports)} + {fmtN(s.targets)} ))} @@ -86,7 +104,7 @@ export function DShieldPanel(): React.ReactElement { {summary && (

{fmtN(summary.records)} records · {fmtN(summary.sources)} sources ·{' '} - {fmtN(summary.targets)} targets — last 24h + {fmtN(summary.targets)} targets — {summary.date}

)}
@@ -95,6 +113,21 @@ export function DShieldPanel(): React.ReactElement { DShieldPanel.displayName = 'DShieldPanel' +function toArray(v: Record | T[] | undefined): T[] { + if (!v) return [] + if (Array.isArray(v)) return v + return Object.values(v) +} + +function pickLatestSummary( + list: DShieldDailySummary[] | undefined +): DShieldDailySummary | undefined { + if (!list || list.length === 0) return undefined + return list.reduce((latest, entry) => + entry.date > latest.date ? entry : latest + ) +} + function fmtN(n: number): string { if (n >= MILLION) return `${(n / MILLION).toFixed(1)}M` if (n >= THOUSAND) return `${(n / THOUSAND).toFixed(1)}k`