settings-save-row: the Settings form is the left column
test / test (push) Waiting to run

The owner chose Variant 2 on 2026-10-16 ("форма в левой колонке, кнопка
под своими полями"); the mockup is f95c553. Server › Settings: the form
wraps only the left column - Log retention, Notifications and Save
settings under them - and the right column, outside the form, holds
Notification mail and the read-only Sending rate limits. The boxes are
renumbered column by column (Notifications 02, Notification mail 03,
Sending rate limits 04). The fields, their names and the POST are
unchanged.

Tests: the page's outline matches the mockup's (TestPanelOutlinesMatchMockups);
go vet + go test (26 packages) and make e2e on the test server for this
tree.

CHANGELOG [Unreleased]; roadmap row done, its section quotes the choice.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
mix
2026-10-16 13:04:06 +03:00
co-authored by Claude Opus 5.5
parent f95c5530c7
commit 82a53e111c
4 changed files with 42 additions and 26 deletions
+6
View File
@@ -15,6 +15,12 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); version
stays open as before, with *In DNS now* where it differs. A `<details>`
block, no script; *Re-check DNS* draws the page again, so a record that
has just turned right comes back folded.
- **Server › Settings: *Save settings* sits under the fields it saves**
(settings-save-row): the form is the left column - Log retention,
Notifications, the button - and the right column holds what is not a
field, Notification mail and the read-only Sending rate limits. Before,
the button stood under both columns, after a long gap whenever the
records of the server's own name were open.
## [2.8.0] - 2026-10-16
+10 -1
View File
@@ -39,7 +39,7 @@ in `git log` and [CHANGELOG.md](../CHANGELOG.md).
| password-reset | Password reset by e-mail | agreed (2026-10-13) | — | — |
| local-time | The panel shows time, and counts its days, in a time zone other than UTC | agreed (2026-10-13; design questions open) | — | — |
| notification-mail-recheck | The Notification mail records on Server › Settings can be checked again from where they are shown | agreed (2026-10-15) | — | — |
| settings-save-row | Server › Settings: the Save button no longer stands alone under a long right column | agreed (2026-10-15) | — | — |
| settings-save-row | Server › Settings: the Save button no longer stands alone under a long right column | done 2026-10-16, unreleased | — | — |
| dns-record-collapse | A DNS record that is right is shown folded: its name and its tag, the values on request | done 2026-10-16, unreleased | — | — |
| go-milter-upstream | Prepare an issue and a PR for go-milter: its header map outlives a message and is unbounded | prepared 2026-10-16, the owner posts | — | [third_party/go-milter/PATCHES.md](../third_party/go-milter/PATCHES.md) |
| own-mta-builds | Analysis: build Postfix and OpenDKIM ourselves, patched, instead of Debian's packages | analysed 2026-10-15: no own builds; three rows proposed instead | — | [own-mta-builds-2026-10-15.md](own-mta-builds-2026-10-15.md) |
@@ -887,6 +887,15 @@ form's columns, or the button nearer its fields. Decide with the mockup,
after dns-record-collapse, on a page whose records are missing as well as
on one whose records are right.
**Done (2026-10-16):** shown both layouts in both states, the owner chose
"Вариант 2: форма в левой колонке, кнопка под своими полями." Folding alone
closed the gap only while the records are right. The form is now the left
column - 01 Log retention, 02 Notifications, *Save settings* - and the
right column, outside it, holds 03 Notification mail and 04 Sending rate
limits. It also leaves room for
[notification-mail-recheck](#notification-mail-recheck): a *Re-check DNS*
form in the Notification mail box is no longer a form inside a form.
## go-milter-upstream
**Problem (owner, 2026-10-16):** the panel builds go-milter v0.4.1 patched
+3 -3
View File
@@ -95,15 +95,15 @@ func NewSettings(m Meta, retention, level1 string) *Settings {
},
Retention: Box{No: "01", Title: "Log retention", Help: topicLink(HelpSettings, "How long rows are kept")},
RetentionDays: retention,
RateLimits: Box{No: "02", Title: "Sending rate limits", ID: "rate-limits", End: Plain("Read-only"), Help: topicLink(HelpLimits, "Levels 1 and 2")},
RateLimits: Box{No: "04", Title: "Sending rate limits", ID: "rate-limits", End: Plain("Read-only"), Help: topicLink(HelpLimits, "Levels 1 and 2")},
RateFacts: []Fact{
{Label: "Level 1 · per client IP", Value: Plain(level1), Big: true,
Note: Rich("Set in ", Code(".env"), "; restart to change. Nothing below may exceed it.")},
{Label: "Level 2 · domain, application",
Value: Rich("Set on each ", Link("/outbound/domains", "domain"), " and on each application of a domain.")},
},
Notifications: Box{No: "03", Title: "Notifications", ID: "notifications", Help: topicLink(HelpNotifications, "What is sent and when")},
Mail: Box{No: "04", Title: "Notification mail", ID: "notification-mail", End: Plain("DNS records of the server's own name"),
Notifications: Box{No: "02", Title: "Notifications", ID: "notifications", Help: topicLink(HelpNotifications, "What is sent and when")},
Mail: Box{No: "03", Title: "Notification mail", ID: "notification-mail", End: Plain("DNS records of the server's own name"),
Help: topicLink(HelpNotifications, "What the panel sends and what makes it arrive")},
}
}
+23 -22
View File
@@ -1,15 +1,16 @@
{{/* Server > Settings (mockup settings.html): what holds for the whole instance.
One form, one Save button; the rate limits are read-only facts, and the
records of the server's own name are the ones notifications are signed and
authorised with. A user's own name, e-mail, password and DMARC address are on
Account (account.html). */}}
One form, in the left column, with its Save button under its fields; the
right column holds what is not a field - the records of the server's own
name, the ones notifications are signed and authorised with, and the
read-only rate limits. A user's own name, e-mail, password and DMARC
address are on Account (account.html). */}}
{{define "content"}}
{{template "page_head" .Head}}
{{if .Flash}}{{template "flash" .Flash}}{{end}}
<form class="sp-form" method="post" action="/server/settings">
<div class="columns">
<div class="column is-6">
<div class="columns">
<div class="column is-6">
<form class="sp-form" method="post" action="/server/settings">
{{template "box_open" .Retention}}
{{template "body_open"}}
<div class="field"><label class="label" for="send_log_retention_days">Keep outbound log rows, days</label>
@@ -22,26 +23,26 @@
{{template "body_close"}}
{{template "box_close"}}
{{template "box_open" .RateLimits}}
{{template "body_open"}}
{{template "facts" .RateFacts}}
{{template "body_close"}}
{{template "box_close"}}
</div>
<div class="column is-6">
{{template "box_open" .Notifications}}
{{template "body_open"}}
<div class="field"><label class="checkbox"><input type="checkbox" name="notify"{{if .Notify}} checked{{end}}> Send notification e-mails</label>
<p class="help">{{template "inline" .NotifyNote}}</p></div>
{{template "body_close"}}
{{template "box_close"}}
{{template "box_open" .Mail}}
{{range .MailRecords}}{{template "dns_record" .}}
{{end}}{{template "box_close"}}
</div>
<div class="buttons"><button type="submit" class="button is-primary">Save settings</button></div>
</form>
</div>
<div class="buttons"><button type="submit" class="button is-primary">Save settings</button></div>
</form>
<div class="column is-6">
{{template "box_open" .Mail}}
{{range .MailRecords}}{{template "dns_record" .}}
{{end}}{{template "box_close"}}
{{template "box_open" .RateLimits}}
{{template "body_open"}}
{{template "facts" .RateFacts}}
{{template "body_close"}}
{{template "box_close"}}
</div>
</div>
{{end}}