panel: place mail queue and TLS cert side by side on Status
test / test (push) Has been cancelled

Widen the status page and wrap the short queue/certificate cards in
.split so the stack is shorter; other checks stay full width.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-11 23:24:24 +03:00
parent 3a520d9ec7
commit 6b8658602d
4 changed files with 35 additions and 19 deletions
+4
View File
@@ -1,3 +1,7 @@
{{/* Wide enough for mail queue and TLS certificate side by side (see .split
in panel.css, as on account and delivery). */}}
{{define "wide"}}wide{{end}}
{{define "content"}}
<h1>Server status</h1>
+20 -18
View File
@@ -72,25 +72,27 @@
</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="split">
<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 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>
<div class="card" id="sockets">
+4 -1
View File
@@ -263,7 +263,7 @@ func TestOnlyThePagesMadeOfDataDeclareThemselvesWide(t *testing.T) {
if err != nil {
t.Fatalf("New: %v", err)
}
wide := map[string]bool{"account": true, "deliveries": true, "delivery": true, "mail_queue": true, "system_log": true}
wide := map[string]bool{"account": true, "deliveries": true, "delivery": true, "mail_queue": true, "status": true, "system_log": true}
for name, page := range engine.Pages() {
var buf bytes.Buffer
if err := page.ExecuteTemplate(&buf, "wide", nil); err != nil {
@@ -379,6 +379,9 @@ func TestStatusPageRendersEveryCheck(t *testing.T) {
"opendkim", "FATAL", "Mail queue is empty", "mail.example.com",
"203.0.113.10 → no PTR record", `action="/reload"`,
`hx-get="/status/fragment"`, `class="st st-error"`,
// Queue and certificate sit abreast inside the polled fragment; their
// ids stay on the cards so the section index and scroll highlights hold.
`class="split"`, `id="queue"`, `id="certificate"`, `id="sockets"`,
// The machine card: the bars carry their reading in an attribute
// (the CSP rules out sizing them with a style), and the figures are
// printed beside them for anything that does not render a meter.