5d3000a48f
The navigation was a bar across the top that did not fit on one row — six page entries and the session block against the panel's width — and had to be split into two, costing the top of every page. It is now a column down the left edge: one left edge to scan, the current entry marked down its leading edge, sticky so it stays in view, and room under the entries for the current page's own sections. Below the width the two columns need it lies back down into the same wrapping rows as before; six entries need no drawer. The section index is for the two pages long enough to need one — the domain page (nine cards) and the status page (eight). Each card carries an id and the page's template defines the list by overriding an empty "sections" block in the layout, so a page that defines nothing renders no index. panel.js marks the section in view, looking targets up by id on each pass so the status page swapping its cards out every five seconds cannot leave it measuring boxes that have left the document; the links themselves are plain fragment links and need no script. Verified against the real pages rendered by a local panel at 1300px, 924px and 481px wide.
113 lines
4.4 KiB
HTML
113 lines
4.4 KiB
HTML
{{define "status_body"}}
|
|
<div id="status-body" hx-get="/status/fragment" hx-trigger="every 5s" hx-swap="outerHTML">
|
|
<div class="card" id="overall">
|
|
<h2>Overall <span class="st st-{{.OverallStatus}}">{{.OverallStatus}}</span></h2>
|
|
<p class="muted">{{.OverallHeading}}</p>
|
|
</div>
|
|
|
|
<div class="card" id="processes">
|
|
<h2>Processes <span class="st st-{{.ProcessStatus}}">{{.ProcessStatus}}</span></h2>
|
|
{{if .ProcessError}}
|
|
<p class="error">Could not ask supervisord for the process list.</p>
|
|
{{else}}
|
|
<table>
|
|
<thead><tr><th>Program</th><th>State</th><th>Detail</th></tr></thead>
|
|
<tbody>
|
|
{{range .Processes}}
|
|
<tr>
|
|
<td>{{.Name}}</td>
|
|
<td><span class="st st-{{.Status}}">{{.State}}</span></td>
|
|
<td class="muted">{{.Detail}}</td>
|
|
</tr>
|
|
{{end}}
|
|
</tbody>
|
|
</table>
|
|
{{end}}
|
|
</div>
|
|
|
|
<div class="card" id="machine">
|
|
<h2>Machine <span class="st st-{{.Machine.Status}}">{{.Machine.Status}}</span></h2>
|
|
<p class="muted">Processor, memory and network of the machine this container
|
|
runs on, read from the kernel's counters. CPU and throughput are rates, so
|
|
they describe{{if .Machine.WindowText}} the {{.Machine.WindowText}}{{end}}
|
|
since the previous refresh rather than this instant.</p>
|
|
<table>
|
|
<thead><tr><th class="metric">Resource</th><th>Usage</th><th>Detail</th></tr></thead>
|
|
<tbody>
|
|
<tr>
|
|
<td class="metric">CPU</td>
|
|
<td class="metric">
|
|
{{if .Machine.CPU.Measured}}
|
|
<meter value="{{.Machine.CPU.Percent}}" min="0" max="100" low="70" high="90" optimum="10">{{.Machine.CPU.BusyText}}</meter>
|
|
{{.Machine.CPU.BusyText}}
|
|
{{else}}<span class="muted">—</span>{{end}}
|
|
</td>
|
|
<td class="muted">{{.Machine.CPU.Detail}}</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="metric">Memory</td>
|
|
<td class="metric">
|
|
{{if .Machine.Memory.Measured}}
|
|
<meter value="{{.Machine.Memory.Percent}}" min="0" max="100" low="70" high="90" optimum="10">{{.Machine.Memory.PctText}}</meter>
|
|
{{.Machine.Memory.PctText}}
|
|
{{else}}<span class="muted">—</span>{{end}}
|
|
</td>
|
|
<td class="muted">{{.Machine.Memory.Detail}}</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="metric">Network</td>
|
|
<td class="metric">
|
|
{{if .Machine.Network.Measured}}
|
|
↓ {{.Machine.Network.InRateText}}<br>↑ {{.Machine.Network.OutRateText}}
|
|
{{else}}<span class="muted">—</span>{{end}}
|
|
</td>
|
|
<td class="muted">
|
|
{{range .Machine.Network.Interfaces}}
|
|
<div>{{.Name}}: {{.InText}} in, {{.OutText}} out{{if .Measured}} (↓ {{.InRateText}} ↑ {{.OutRateText}}){{end}}</div>
|
|
{{end}}
|
|
{{if .Machine.Network.Detail}}<div>{{.Machine.Network.Detail}}</div>{{end}}
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div class="card" id="queue">
|
|
<h2>Mail queue <span class="st st-{{.QueueStatus}}">{{.QueueStatus}}</span></h2>
|
|
{{if .QueueError}}
|
|
<p class="error">{{.QueueError}}</p>
|
|
{{else}}
|
|
<p>{{if .QueueSummary}}{{.QueueSummary}}{{else}}Mail queue is empty.{{end}}</p>
|
|
<a class="btn" href="/mail-queue">Full queue</a>
|
|
{{end}}
|
|
</div>
|
|
|
|
<div class="card" id="certificate">
|
|
<h2>TLS certificate <span class="st st-{{.Cert.Status}}">{{.Cert.Status}}</span></h2>
|
|
<p class="muted">The certificate Postfix serves on port 465{{if .Cert.Subject}} ({{.Cert.Subject}}){{end}}.
|
|
It is supplied by the reverse proxy through a read-only mount; SelfPost only reads it.</p>
|
|
{{if not .Cert.NotAfter.IsZero}}
|
|
<label>Expires</label>
|
|
<span class="code">{{.Cert.NotAfter.UTC.Format "2006-01-02 15:04 UTC"}}</span>
|
|
{{end}}
|
|
<p class="{{if eq .Cert.Status "ok"}}muted{{else}}error{{end}}">{{.Cert.Detail}}</p>
|
|
</div>
|
|
|
|
<div class="card" id="sockets">
|
|
<h2>Milter sockets <span class="st st-{{.SocketStatus}}">{{.SocketStatus}}</span></h2>
|
|
<table>
|
|
<thead><tr><th>Milter</th><th>Socket</th><th>State</th></tr></thead>
|
|
<tbody>
|
|
{{range .Sockets}}
|
|
<tr>
|
|
<td>{{.Name}}</td>
|
|
<td class="muted">{{.Path}}</td>
|
|
<td><span class="st st-{{.Status}}">{{.Status}}</span> {{.Detail}}</td>
|
|
</tr>
|
|
{{end}}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
{{end}}
|