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
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
{{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}}
|
||||
Reference in New Issue
Block a user