Files
nixos-router/pkgs/router-webui/templates/dashboard.html
T
nilsandClaude Sonnet 5.5 caf2c6b26d Add DNS accounts, Let's Encrypt, password change, reboot, HTTP redirect
- router.dnsProviders: named accounts at DNS providers, used by dynamic
  DNS and certificates (ddclient and lego provider lists in
  pkgs/router-webui/providers.json). Schema 2 migrates router.ddns.
- router.acme: a Let's Encrypt certificate for the web UI via
  security.acme (DNS-01, resolver 1.1.1.1), served and reloaded by the
  web UI; Certificate page.
- Web UI: password change (web UI and root), reboot button, HTTP to HTTPS
  redirect (router.webui.httpPort), grouped menu.
- Latest kernel (linuxPackages_latest); 7.3 and 7.3.0 are the same kernel
  for the reboot hint.
- SPECS.md: wanted later (REST API, GraphQL, MCP).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AeFqV9dZrK6nipHkPfyM4F
2026-10-30 19:27:49 +01:00

84 lines
4.1 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{{define "dashboard"}}
{{$d := .Data.Dashboard}}{{$u := $d.Snap.Uplink}}{{$sys := $d.Snap.System}}
<div class="ranges" role="group" aria-label="Time range">
{{range $d.Ranges}}<a href="/?range={{.}}" data-range="{{.}}"{{if eq . $d.Range}} class="active" aria-current="true"{{end}}>{{.}}</a>{{end}}
</div>
<div class="cards">
{{if $d.Snap.Time.IsZero}}
<section class="card"><h2>Internet</h2><p class="state">Collecting…</p></section>
{{else}}
<section class="card {{if and $u.Connected (or $u.Reachable (not $u.Checked))}}up{{else if $u.Connected}}degraded{{else}}down{{end}}">
<h2>Internet</h2>
<p class="state">
{{if and $u.Connected (or $u.Reachable (not $u.Checked))}}Connected
{{else if $u.Connected}}Connected, but no answer from the internet
{{else if not $u.Exists}}{{if eq $u.Type "pppoe"}}Not connected: no PPPoE session{{else}}Not connected: {{$u.Device}} is missing{{end}}
{{else}}Not connected{{end}}
{{if not $u.Since.IsZero}}<span class="muted">for {{ago $u.Since}}</span>{{end}}
</p>
<dl>
<dt>Uplink</dt><dd>{{$u.Device}} ({{if eq $u.Type "pppoe"}}PPPoE{{else}}DHCP{{end}})</dd>
{{if $u.IPv4}}<dt>IPv4</dt><dd>{{join $u.IPv4 ", "}}</dd>{{end}}
{{if $u.IPv6}}<dt>IPv6</dt><dd>{{join $u.IPv6 ", "}}</dd>{{end}}
{{if $u.Gateway}}<dt>Gateway</dt><dd>{{$u.Gateway}}</dd>{{end}}
{{range $d.Snap.Pings}}
<dt>Ping {{.Target}}</dt><dd>{{if .OK}}{{ms .RTT}}{{else if .Address}}<span class="bad">no answer</span>{{else}}<span class="muted">no address</span>{{end}}{{if and .Address (ne .Address .Target)}} <span class="muted">{{.Address}}</span>{{end}}</dd>
{{end}}
</dl>
</section>
{{end}}
<section class="card">
<h2>System</h2>
<dl>
<dt>Uptime</dt><dd>{{age $sys.Uptime}}</dd>
{{if $sys.Kernel}}<dt>Kernel</dt><dd>{{$sys.Kernel}}{{if $sys.KernelNext}} <span class="bad">reboot to run {{$sys.KernelNext}}</span> <a href="/advanced">Reboot</a>{{end}}</dd>{{end}}
<dt>Load</dt><dd>{{$sys.Load}}</dd>
<dt>CPU</dt><dd>{{value $sys.CPU "%"}}</dd>
{{if $sys.MemTotal}}<dt>Memory</dt><dd>{{bytes $sys.MemUsed}} of {{bytes $sys.MemTotal}}</dd>{{end}}
{{if not (isNaN $sys.Temperature)}}<dt>Temperature</dt><dd>{{value $sys.Temperature "°C"}}</dd>{{end}}
{{if $sys.DiskTotal}}<dt>Disk</dt><dd>{{bytes $sys.DiskUsed}} of {{bytes $sys.DiskTotal}}</dd>{{end}}
</dl>
</section>
{{if $d.Events}}
<section class="card">
<h2>Connection log</h2>
<ul class="events">
{{range $d.Events}}<li><span class="{{if .Connected}}ok{{else}}bad{{end}}">{{if .Connected}}up{{else}}down{{end}}</span> {{.Time.Local.Format "Jan 2 15:04:05"}}{{if .Detail}} <span class="muted">{{.Detail}}</span>{{end}}</li>{{end}}
</ul>
</section>
{{end}}
</div>
<section>
<h2>DHCP clients</h2>
{{if $d.Leases}}
<div class="scroll">
<table class="leases">
<tr><th>Name</th><th>Address</th><th>MAC</th><th>LAN</th><th>Lease ends in</th></tr>
{{range $d.Leases}}<tr><td>{{or .Hostname "–"}}</td><td>{{.Address}}</td><td><code>{{.MAC}}</code></td><td>{{.LAN}}</td><td>{{until .Expires}}</td></tr>{{end}}
</table>
</div>
{{else}}<p class="muted">No active leases.</p>{{end}}
</section>
<div class="charts">
{{range $d.Charts}}
<figure class="chart">
<figcaption><strong>{{.Title}}</strong>
<span class="legend">{{range .Lines}}<span class="key {{.Class}}">{{.Label}} <b>{{.Now}}</b></span>{{end}}</span>
</figcaption>
<svg viewBox="-64 -8 690 150" role="img" aria-label="{{.Title}}">
{{range .YTicks}}<line class="grid" x1="0" x2="{{chartW}}" y1="{{.Pos}}" y2="{{.Pos}}"/><text class="lab" x="-6" y="{{.Pos}}" text-anchor="end" dominant-baseline="middle">{{.Label}}</text>{{end}}
{{range .XTicks}}<text class="lab" x="{{.Pos}}" y="138" text-anchor="middle">{{.Label}}</text>{{end}}
{{range .Lines}}<path class="line {{.Class}}" d="{{.Path}}"/>{{end}}
{{if .Empty}}<text class="lab" x="300" y="64" text-anchor="middle">no data yet</text>{{end}}
{{range .Cols}}<rect class="hover" x="{{.X}}" y="0" width="{{.W}}" height="{{chartH}}"><title>{{.Tip}}</title></rect>{{end}}
</svg>
</figure>
{{end}}
</div>
{{end}}