Files
vibeproxy/internal/web/templates/dashboard.html
T
owenandClaude Sonnet 5 ba1f7c4c03 Initial vibeproxy implementation
Self-contained HTTP/HTTPS/TCP/UDP reverse proxy manager written in Go,
with SQLite storage, a Bootstrap 5 admin UI (Go templates, no JS
framework), and a REST API under /api/v1.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QTXFrNP1imCW7jtfL5SZrw
2026-08-17 10:28:59 -05:00

116 lines
4.2 KiB
HTML

{{define "dashboard"}}{{template "header" .}}
{{$d := .Data}}
<div class="row g-3 mb-4">
<div class="col-sm-6 col-lg-3">
<div class="card stat-card h-100"><div class="card-body">
<div class="text-secondary small">Active Proxy Hosts</div>
<div class="stat-value">{{$d.ActiveProxyHosts}}</div>
</div></div>
</div>
<div class="col-sm-6 col-lg-3">
<div class="card stat-card h-100"><div class="card-body">
<div class="text-secondary small">TCP / UDP Streams</div>
<div class="stat-value">{{$d.ActiveTCPStreams}} / {{$d.ActiveUDPStreams}}</div>
</div></div>
</div>
<div class="col-sm-6 col-lg-3">
<div class="card stat-card h-100"><div class="card-body">
<div class="text-secondary small">Requests / sec (1h avg)</div>
<div class="stat-value">{{printf "%.2f" $d.RequestsPerSecond}}</div>
</div></div>
</div>
<div class="col-sm-6 col-lg-3">
<div class="card stat-card h-100"><div class="card-body">
<div class="text-secondary small">Requests (24h)</div>
<div class="stat-value">{{$d.TotalRequestsToday}}</div>
</div></div>
</div>
</div>
<div class="row g-3">
<div class="col-lg-6">
<div class="card h-100">
<div class="card-header">Status Breakdown (24h)</div>
<div class="card-body">
{{if $d.StatusBreakdown}}
<table class="table table-sm mb-0">
<tbody>
{{range $d.StatusBreakdown}}
<tr><td class="{{statusClass .Status}}">{{.Status}}</td><td>{{.Count}}</td></tr>
{{end}}
</tbody>
</table>
{{else}}<p class="text-secondary mb-0">No requests logged yet.</p>{{end}}
</div>
</div>
</div>
<div class="col-lg-6">
<div class="card h-100">
<div class="card-header">Backend Health</div>
<div class="card-body">
{{if $d.BackendHealth}}
<table class="table table-sm mb-0">
<tbody>
{{range $d.BackendHealth}}
<tr>
<td>{{.ProxyHost}}</td><td>{{.Backend}}</td>
<td>{{if .Healthy}}<span class="badge text-bg-success">healthy</span>{{else}}<span class="badge text-bg-danger">unhealthy</span>{{end}}</td>
</tr>
{{end}}
</tbody>
</table>
{{else}}<p class="text-secondary mb-0">No backends configured.</p>{{end}}
</div>
</div>
</div>
<div class="col-lg-6">
<div class="card h-100">
<div class="card-header">Top Hosts (24h)</div>
<div class="card-body">
{{if $d.TopHosts}}
<table class="table table-sm mb-0"><tbody>
{{range $d.TopHosts}}<tr><td>{{.Host}}</td><td>{{.Count}}</td></tr>{{end}}
</tbody></table>
{{else}}<p class="text-secondary mb-0">No data yet.</p>{{end}}
</div>
</div>
</div>
<div class="col-lg-6">
<div class="card h-100">
<div class="card-header">Top Clients (24h)</div>
<div class="card-body">
{{if $d.TopClients}}
<table class="table table-sm mb-0"><tbody>
{{range $d.TopClients}}<tr><td>{{.Host}}</td><td>{{.Count}}</td></tr>{{end}}
</tbody></table>
{{else}}<p class="text-secondary mb-0">No data yet.</p>{{end}}
</div>
</div>
</div>
<div class="col-lg-6">
<div class="card h-100">
<div class="card-header">Certificates Expiring Soon (30d)</div>
<div class="card-body">
{{if $d.CertsExpiringSoon}}
<table class="table table-sm mb-0"><tbody>
{{range $d.CertsExpiringSoon}}<tr><td>{{.Name}}</td><td>{{fmtTime (deref .NotAfter)}}</td></tr>{{end}}
</tbody></table>
{{else}}<p class="text-secondary mb-0">Nothing expiring soon.</p>{{end}}
</div>
</div>
</div>
<div class="col-lg-6">
<div class="card h-100">
<div class="card-header">Recent Errors (24h)</div>
<div class="card-body">
{{if $d.RecentErrors}}
<table class="table table-sm mb-0"><tbody>
{{range $d.RecentErrors}}<tr><td>{{fmtTime .Timestamp}}</td><td class="{{statusClass .Status}}">{{.Status}}</td><td>{{.Host}}{{.Path}}</td></tr>{{end}}
</tbody></table>
{{else}}<p class="text-secondary mb-0">No recent errors.</p>{{end}}
</div>
</div>
</div>
</div>
{{template "footer" .}}{{end}}