The send log was the one place in the panel where a status was bare text, next to a delivery's own page where the same value is a badge, and a domain list where the DNS verdict is one too — so a message's outcome looked like a different kind of fact depending on which page you read it from. The level travels on the row rather than being worked out in the template: deliveryLevel is the one place that decides what a status means, the delivery page already reads it, and a second mapping written into the template or the stylesheet would have been free to drift from it. sent is ok, deferred a warning, bounced and rejected errors, and queued unknown — nothing has gone wrong, nothing has been reported yet. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+7
-1
@@ -28,7 +28,13 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); version
|
||||
whose only card is the narrow one now takes its heading and footer down to the
|
||||
card's width instead of splitting them across the wider measure, and the send
|
||||
log stops breaking `Details` and `deferred` across two lines when a row is
|
||||
tight. The three
|
||||
tight.
|
||||
- panel: the send log's **status is a badge**, in the same ok/warn/error/unknown
|
||||
colours the status page and the DNS checks use, instead of the one place in
|
||||
the panel where a status was bare text. The mapping is the one the delivery
|
||||
page already applied — `sent` is ok, `deferred` a warning, `bounced` and
|
||||
`rejected` errors, `queued` unknown because nothing has gone wrong yet.
|
||||
The three
|
||||
WOFF2 files add ~76 KB to the image and are served from the panel's own origin,
|
||||
so the Content-Security-Policy is unchanged (`default-src 'self'`).
|
||||
|
||||
|
||||
@@ -145,6 +145,17 @@ func deliveryLevel(status string) string {
|
||||
}
|
||||
}
|
||||
|
||||
// sendLogRow is a row of the send log as the table draws it: the stored row
|
||||
// plus the badge level its status maps onto. The level is carried rather than
|
||||
// derived in the template because deliveryLevel is the one place that decides
|
||||
// what a status means — the delivery page already reads it, and a second
|
||||
// mapping written in the template or the stylesheet would be free to drift
|
||||
// from it.
|
||||
type sendLogRow struct {
|
||||
store.SendLogRow
|
||||
Level string // ok / warn / error / unknown, as deliveryLevel returns
|
||||
}
|
||||
|
||||
// deliveryEvent is one step of a message's history, as the timeline on the
|
||||
// delivery page draws it. At is zero for the step that has not happened yet —
|
||||
// the delivery report a queued message is still waiting for.
|
||||
@@ -324,8 +335,10 @@ func (h *Handlers) sendLogData(r *http.Request) (map[string]any, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
view := make([]sendLogRow, len(rows))
|
||||
for i := range rows {
|
||||
rows[i].Subject = mailhdr.DecodeSubject(rows[i].Subject)
|
||||
view[i] = sendLogRow{SendLogRow: rows[i], Level: deliveryLevel(rows[i].Status)}
|
||||
}
|
||||
|
||||
domainNames := make([]string, 0, len(assigned))
|
||||
@@ -358,7 +371,7 @@ func (h *Handlers) sendLogData(r *http.Request) (map[string]any, error) {
|
||||
lastPage = int((total + sendLogPageSize - 1) / sendLogPageSize)
|
||||
}
|
||||
return map[string]any{
|
||||
"Rows": rows,
|
||||
"Rows": view,
|
||||
"FilterDomains": domainNames,
|
||||
"FilterApps": logins,
|
||||
"FilterDomain": filter.Domain,
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<td>{{.From}}</td>
|
||||
<td>{{.To}}</td>
|
||||
<td class="subject"><span title="{{.Subject}}">{{.Subject}}</span></td>
|
||||
<td class="status">{{.Status}}</td>
|
||||
<td class="status"><span class="st st-{{.Level}}">{{.Status}}</span></td>
|
||||
<td class="actions"><a href="/deliveries/{{.ID}}?domain={{$.FilterDomain}}&app={{$.FilterApp}}&p={{$.Page}}">Details</a></td>
|
||||
</tr>
|
||||
{{end}}
|
||||
|
||||
Reference in New Issue
Block a user