add visualizations, better scaling
This commit is contained in:
104
frontend/src/components/analysis/IntelligenceRiskViews.tsx
Normal file
104
frontend/src/components/analysis/IntelligenceRiskViews.tsx
Normal file
@@ -0,0 +1,104 @@
|
||||
import { Card, Drawer, Space, Tag, Typography } from 'antd';
|
||||
|
||||
import type { HostIntelligenceEvidence } from '../../types/analysis';
|
||||
import {
|
||||
endpointText,
|
||||
formatBytes,
|
||||
formatTimestamp,
|
||||
protocolColor,
|
||||
renderLabelTags,
|
||||
} from './shared.tsx';
|
||||
|
||||
const { Text } = Typography;
|
||||
|
||||
export function HostDetailDrawer({
|
||||
host,
|
||||
open,
|
||||
onClose,
|
||||
}: {
|
||||
host: HostIntelligenceEvidence | null;
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
}) {
|
||||
return (
|
||||
<Drawer title={host ? endpointText(host.ip_address, host.mac_address) : 'Host details'} placement="right" width={520} open={open} onClose={onClose}>
|
||||
{host == null ? null : (
|
||||
<Space direction="vertical" size={16} style={{ width: '100%' }}>
|
||||
<Card size="small" title="Identity">
|
||||
<Space direction="vertical" size={8} style={{ width: '100%' }}>
|
||||
<Text>IP: {host.ip_address ?? '—'}</Text>
|
||||
<Text>MAC: {host.mac_address ?? '—'}</Text>
|
||||
<Text>Interfaces: {host.interfaces.join(', ') || '—'}</Text>
|
||||
<Text>First seen: {formatTimestamp(host.first_seen)} | Last seen: {formatTimestamp(host.last_seen)}</Text>
|
||||
<div>{renderLabelTags(host.hostnames, 'geekblue')}</div>
|
||||
</Space>
|
||||
</Card>
|
||||
|
||||
<Card size="small" title="Protocol Profile">
|
||||
<Space direction="vertical" size={10} style={{ width: '100%' }}>
|
||||
{host.top_protocols.length === 0 ? (
|
||||
<Text type="secondary">No protocol profile available yet.</Text>
|
||||
) : (
|
||||
host.top_protocols.map((protocol) => {
|
||||
const maxCount = Math.max(...host.top_protocols.map((item) => item.packet_count), 1);
|
||||
const widthPct = (protocol.packet_count / maxCount) * 100;
|
||||
return (
|
||||
<div key={protocol.label}>
|
||||
<Space style={{ width: '100%', justifyContent: 'space-between' }}>
|
||||
<Tag color={protocolColor(protocol.label)}>{protocol.label}</Tag>
|
||||
<Text>{protocol.packet_count}</Text>
|
||||
</Space>
|
||||
<div style={{ height: 8, background: '#eef3f8', borderRadius: 999, overflow: 'hidden' }}>
|
||||
<div style={{ width: `${widthPct}%`, height: '100%', background: protocolColor(protocol.label) }} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})
|
||||
)}
|
||||
</Space>
|
||||
</Card>
|
||||
|
||||
<Card size="small" title="Top Peers">
|
||||
<Space direction="vertical" size={10} style={{ width: '100%' }}>
|
||||
{host.peers.length === 0 ? (
|
||||
<Text type="secondary">No peer details available yet.</Text>
|
||||
) : (
|
||||
host.peers.map((peer) => {
|
||||
const maxCount = Math.max(...host.peers.map((item) => item.packet_count), 1);
|
||||
const widthPct = (peer.packet_count / maxCount) * 100;
|
||||
return (
|
||||
<div key={`${peer.ip_address ?? 'no-ip'}|${peer.mac_address ?? 'no-mac'}`}>
|
||||
<Space direction="vertical" size={4} style={{ width: '100%' }}>
|
||||
<Text>{endpointText(peer.ip_address, peer.mac_address)}</Text>
|
||||
<Text type="secondary">{peer.packet_count} packets · {formatBytes(peer.byte_count)} · {formatTimestamp(peer.last_seen)}</Text>
|
||||
<div style={{ height: 8, background: '#eef3f8', borderRadius: 999, overflow: 'hidden' }}>
|
||||
<div style={{ width: `${widthPct}%`, height: '100%', background: '#5b8ff9' }} />
|
||||
</div>
|
||||
<div>{renderLabelTags(peer.protocols, 'purple')}</div>
|
||||
</Space>
|
||||
</div>
|
||||
);
|
||||
})
|
||||
)}
|
||||
</Space>
|
||||
</Card>
|
||||
|
||||
<Card size="small" title="Likely Services">
|
||||
<Space direction="vertical" size={10} style={{ width: '100%' }}>
|
||||
{host.services.length === 0 ? (
|
||||
<Text type="secondary">No service evidence inferred yet.</Text>
|
||||
) : (
|
||||
host.services.map((service) => (
|
||||
<div key={`${service.port ?? 'no-port'}|${service.protocol}`}>
|
||||
<Text>Port {service.port ?? '—'} · {service.protocol} · {service.packet_count} packets · {formatBytes(service.byte_count)}</Text>
|
||||
<div style={{ marginTop: 4 }}>{renderLabelTags(service.hostnames, 'geekblue')}</div>
|
||||
</div>
|
||||
))
|
||||
)}
|
||||
</Space>
|
||||
</Card>
|
||||
</Space>
|
||||
)}
|
||||
</Drawer>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user