panel-redesign: Help with seventeen topics; every box links to its own

Follows the design commit before it. Written by Sonnet, reviewed by
Opus.

  - view/help.go, templates/help.html: the mockup's topics, texts, ids
    and menu. The page shows the groups the reader's menu shows:
    Overview and Server for the global role, Outbound and Inbound by
    reach (Inbound only with the feature on), Account for everyone;
    boxes are numbered as shown.
  - Box.Help set on the boxes the mockups mark; the inbound MX box has
    its link again.
  - TestEveryHelpLinkLandsOnATopic also fails on a topic that no page
    links to, unless it is listed as menu-only (account) - and on a
    stale exception.

Known until the change that follows: the dns, dmarc and account topics
describe the three-choice report address, which the code does not have
yet; Account's DMARC box still links to #dns.

Not verified by running: three sentences rest on Postfix behaviour
(delivery is deferred when a required TLS session cannot be made; a
milter with default_action=tempfail answers 4xx; with "any recipient"
an address the upstream refuses comes back as a bounce).

Evidence
  - docs/assets/panel-redesign/evidence/help.png (1440x3600) and
    in-domain.png: headless Edge, real templates served locally with
    their fixtures - NOT from the container.
  - go test -count=1 ./internal/web/... ./cmd/panel: ok (six packages).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
mix
2026-10-10 11:58:36 +03:00
co-authored by Claude Opus 5.5
parent ef19c1448e
commit 4ab63d08ae
19 changed files with 474 additions and 136 deletions
+4 -4
View File
@@ -98,11 +98,11 @@ func NewBackup(m Meta, passwordMin int, refusal string) *Backup {
Title: "Backup",
Lead: Plain("Take the whole instance with you, or bring one domain in from another SelfPost. Both files are secrets."),
},
Full: Box{No: "01", Title: "Full backup"},
Full: Box{No: "01", Title: "Full backup", Help: topicLink(HelpBackup, "Backups, encryption and restore")},
FullAction: serverBackup,
Encrypt: true,
PasswordMin: passwordMin,
Import: Box{No: "02", Title: "Import a domain", ID: "import"},
Import: Box{No: "02", Title: "Import a domain", ID: "import", Help: topicLink(HelpBackup, "Moving a domain to another instance")},
ImportAction: serverBackup + "/import",
}
if refusal != "" {
@@ -198,7 +198,7 @@ func NewUsers(m Meta, inbound bool, flash string) *Users {
Em("global"), " is the whole server, ", Em("domain"), " is ", reach),
Actions: []Action{{Label: "Create user", Icon: "ti-user-plus", Href: serverUsers + "/new", Primary: true}},
},
List: Box{No: "01", Title: "Panel users"},
List: Box{No: "01", Title: "Panel users", Help: topicLink(HelpUsers, "Roles are a reach, not a rank")},
ShowInbound: inbound,
}
if flash != "" {
@@ -298,7 +298,7 @@ func NewUserForm(m Meta, in UserFormInput) *UserForm {
Head: Head{Crumbs: crumbs, Title: title},
CancelHref: serverUsers,
Account: Box{No: "01", Title: "Account"},
Account: Box{No: "01", Title: "Account", Help: topicLink(HelpUsers, "Roles and domain assignments")},
Username: in.Username,
Email: in.Email,
NewUser: in.ID == 0,