- 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
84 lines
4.1 KiB
HTML
84 lines
4.1 KiB
HTML
{{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}}
|