inbound-antispam-panel: Inbound log, Why as a sheet; no Deny on a Postfix reject
Follows the two design commits before it (owner's decisions quoted there). Kit: a new component, Sheet / SheetRow (components.go), partials sheet_tag and sheet (components.html), its rules in panel.css as in theme.css, and its sample on the kit page next to status_tag. It is the browser's popover: no script. Inbound log: the Why column is gone; the decision tag opens a sheet with who decided, then either the filter's verdict and its symbols one a line (a detail the journal milter wrote) or the reply (a detail the tailer read from mail.log - it starts with its code), and the subject whole. The sheet's id is the journal row's. A row Postfix itself refused no longer links to the filter lists. Tests: the page fixture and view tests for the sheet's markup and content (TestWhyRows), the link rule, three Deny and two Allow on the mockup's six rows; e2e reads "Decided by" and "Reply" from the sheet and wants no sender link on the refused row. Seen: the fixture page with a sheet open, headless Edge at 1360 px - the same as the accepted drawing. Checked on the test server, uncommitted tree: go vet ./... ok, go test ./... ok (22 packages), make e2e ok. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -27,6 +27,13 @@
|
||||
mapping of status to Bulma classes; the label defaults to the status. */}}
|
||||
{{define "tag"}}<span class="{{status_tag .Status}}">{{if .Label}}{{.Label}}{{else}}{{.Status}}{{end}}</span>{{end}}
|
||||
|
||||
{{/* sheet_tag is a status tag that opens a sheet (input: Sheet): the tag as a
|
||||
button, and the sheet it names right after it. sheet is what opens: the tag
|
||||
again, a title, the cross that closes it, and a table of name and value.
|
||||
The browser's popover does the rest - no script. */}}
|
||||
{{define "sheet_tag"}}<button type="button" class="{{status_tag .Tag.Status}}" popovertarget="{{.ID}}">{{if .Tag.Label}}{{.Tag.Label}}{{else}}{{.Tag.Status}}{{end}}</button>{{template "sheet" .}}{{end}}
|
||||
{{define "sheet"}}<div class="sp-sheet" id="{{.ID}}" popover><div class="sp-sheet-in"><div class="sp-sheet-head">{{template "tag" .Tag}}<h2>{{.Title}}</h2><button type="button" popovertarget="{{.ID}}" popovertargetaction="hide" aria-label="Close"><i class="ti ti-x"></i></button></div><div class="sp-sheet-body"><div class="table-container"><table class="table is-fullwidth"><tbody>{{range .Rows}}<tr><th>{{.Label}}</th><td{{if .Mono}} class="sp-mono sp-small"{{end}}>{{range $i, $line := .Lines}}{{if $i}}<br>{{end}}{{$line}}{{end}}</td></tr>{{end}}</tbody></table></div></div></div></div>{{end}}
|
||||
|
||||
{{/* kicker is the upper-case mono micro-label on its own (input: string).
|
||||
page_head writes its own kicker as the line above the title. */}}
|
||||
{{define "kicker"}}<span class="sp-kicker">{{.}}</span>{{end}}
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
{{/* Inbound log (mockup in-log.html): what port 25 decided about each message
|
||||
offered for an inbound domain, one row per recipient, newest first,
|
||||
filtered by domain, decision and day. It does not poll. The last cell is
|
||||
the way to correct a decision in Filter lists, and only the global role,
|
||||
who alone edits the lists, is given it. */}}
|
||||
filtered by domain, decision and day. It does not poll. The decision is a
|
||||
tag that opens a sheet with who decided and why. The last cell is the way
|
||||
to correct a decision in Filter lists, and only the global role, who alone
|
||||
edits the lists, is given it. */}}
|
||||
{{define "content"}}
|
||||
{{template "page_head" .Head}}
|
||||
|
||||
{{template "box_open" .Messages}}
|
||||
{{if .Rows}}
|
||||
<div class="table-container"><table class="table is-fullwidth is-hoverable">
|
||||
<thead><tr><th>Time, UTC</th><th>From</th><th>To</th><th>Subject</th><th>Decision</th><th>Why</th><th></th></tr></thead>
|
||||
<thead><tr><th>Time, UTC</th><th>From</th><th>To</th><th>Subject</th><th>Decision</th><th></th></tr></thead>
|
||||
<tbody>{{range .Rows}}
|
||||
<tr><td class="sp-mono sp-muted sp-nowrap sp-small">{{.Time}}</td><td>{{wbr_at .From}}{{if .Client}}<br><span class="sp-mono sp-muted sp-small">{{.Client}}</span>{{end}}</td><td>{{wbr_at .To}}</td>{{if .Subject}}<td class="sp-clip" title="{{.Subject}}">{{.Subject}}</td>{{else}}<td class="sp-clip sp-muted">—</td>{{end}}<td>{{template "tag" .Decision}}</td><td class="sp-muted sp-small">{{.Why}}</td><td class="sp-actions">{{if .Action}}<a href="{{.Action.Href}}">{{.Action.Label}}</a>{{end}}</td></tr>{{end}}
|
||||
<tr><td class="sp-mono sp-muted sp-nowrap sp-small">{{.Time}}</td><td>{{wbr_at .From}}{{if .Client}}<br><span class="sp-mono sp-muted sp-small">{{.Client}}</span>{{end}}</td><td>{{wbr_at .To}}</td>{{if .Subject}}<td class="sp-clip" title="{{.Subject}}">{{.Subject}}</td>{{else}}<td class="sp-clip sp-muted">—</td>{{end}}<td>{{template "sheet_tag" .Why}}</td><td class="sp-actions">{{if .Action}}<a href="{{.Action.Href}}">{{.Action.Label}}</a>{{end}}</td></tr>{{end}}
|
||||
</tbody>
|
||||
</table></div>
|
||||
{{template "box_foot" .Foot}}
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
<thead><tr><th>Status</th><th>Tag</th><th>Bulma classes</th></tr></thead>
|
||||
<tbody>{{range .StatusRows}}
|
||||
<tr><td>{{.Words}}</td><td>{{template "tag" .Tag}}</td><td class="sp-mono sp-small">{{status_tag .Tag.Status}}</td></tr>{{end}}
|
||||
<tr><td>a tag that opens a <code>sheet</code></td><td>{{template "sheet_tag" .Sheet}}</td><td class="sp-mono sp-small">button.tag + sp-sheet (popover)</td></tr>
|
||||
</tbody>
|
||||
</table></div>
|
||||
{{template "box_close"}}
|
||||
|
||||
Reference in New Issue
Block a user