Initial commit: Rampart v0.2.0
Multi-layer DDoS protection for Minecraft servers. - rampart-core: Edge node with XDP/eBPF + Rust L7 filtering - rampart-manager: REST API with JWT auth, Redis sync - rampart-cli: CLI tool for operators - velocity-plugin: Domain check, HMAC verify, server registry, load balancer - paper-plugin: Auto-registration, heartbeat, HMAC verify - dashboard: React + Vite web UI for management
This commit is contained in:
commit
cf9608ce5d
159 changed files with 15341 additions and 0 deletions
86
dashboard/src/components/Servers.tsx
Normal file
86
dashboard/src/components/Servers.tsx
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
import { useState, useEffect } from 'react'
|
||||
import { fetchServers, type Server } from '../api'
|
||||
|
||||
function Servers() {
|
||||
const [servers, setServers] = useState<Server[]>([])
|
||||
const [error, setError] = useState('')
|
||||
const [loading, setLoading] = useState(true)
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false
|
||||
|
||||
async function load() {
|
||||
try {
|
||||
const data = await fetchServers()
|
||||
if (!cancelled) {
|
||||
setServers(data)
|
||||
setError('')
|
||||
}
|
||||
} catch (err: unknown) {
|
||||
if (!cancelled) {
|
||||
setError(err instanceof Error ? err.message : 'Failed to load servers')
|
||||
}
|
||||
} finally {
|
||||
if (!cancelled) setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
load()
|
||||
const interval = setInterval(load, 10000)
|
||||
return () => {
|
||||
cancelled = true
|
||||
clearInterval(interval)
|
||||
}
|
||||
}, [])
|
||||
|
||||
if (loading) return <div className="spinner" />
|
||||
|
||||
return (
|
||||
<>
|
||||
<h1>Servers</h1>
|
||||
{error && <div className="error-msg">{error}</div>}
|
||||
<div className="table-container">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Type</th>
|
||||
<th>IP:Port</th>
|
||||
<th>Status</th>
|
||||
<th>Online/Max</th>
|
||||
<th>TPS</th>
|
||||
<th>Last Heartbeat</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{servers.length === 0 && (
|
||||
<tr>
|
||||
<td colSpan={7} style={{ textAlign: 'center', padding: '2rem', color: 'var(--text-secondary)' }}>
|
||||
No servers found
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
{servers.map((s) => (
|
||||
<tr key={s.name}>
|
||||
<td>{s.name}</td>
|
||||
<td>{s.server_type}</td>
|
||||
<td>{s.ip}:{s.port}</td>
|
||||
<td>
|
||||
<span className="status-badge">
|
||||
<span className={`status-dot ${s.status === 'online' ? 'online' : 'offline'}`} />
|
||||
{s.status}
|
||||
</span>
|
||||
</td>
|
||||
<td>{s.online_players}/{s.max_players}</td>
|
||||
<td>{s.tps.toFixed(1)}</td>
|
||||
<td>{new Date(s.last_heartbeat).toLocaleString()}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Servers
|
||||
Loading…
Add table
Add a link
Reference in a new issue