Stage 2, step 1. Written by Sonnet, reviewed by Opus.
- templates/login.html, setup.html: written from the mockups as the
content of layout_signed_out - form.sp-form, kicker, h1, Bulma fields
with icons, the full-width primary button. Actions, field names,
autocomplete and autofocus are the old ones.
- view/signin.go: typed Login and Setup (Meta carries a title only, so
Engine.Render takes the signed-out layout); auth handlers pass them
instead of maps.
- login and setup are in kitPages, have fixtures, and are off
legacy_pages.txt.
States the mockups do not draw:
- a refused sign-in / setup is the kit's flash (notification is-danger
is-light) above the fields;
- login before any administrator exists shows the old sentence in a
form.sp-form that has no action and no control: the signed-out
stylesheet sizes and centres its column through "form" alone. A
workaround, listed for the owner.
Differences from the mockups, for the owner:
- the kicker is <p><span class="sp-kicker"> (the kit's partial is a
span; a page may not write the class), the mockup has <p
class="sp-kicker">: the block sits about 3px lower;
- login's kicker is the configured host name and is absent when there
is none; setup's is the mockup's fixed text;
- the footer is the layout's legal line (full copyright holder name);
- the user name field has autofocus, so it shows its focus ring.
Evidence
- docs/assets/panel-redesign/evidence/login.png, setup.png: 1440x900,
headless Edge, from the real templates served locally with their
fixtures - NOT from the container (no Docker on this machine).
- panel/audit.js on login, login with an error, login without an
administrator, setup, setup with an error, at 1440 and 1280:
118 texts checked, problems: [] ; no page is taller than 900px.
- go test -count=1 ./internal/web/...
ok internal/web
ok internal/web/auth
ok internal/web/handlers
ok internal/web/validate
ok internal/web/view
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
54 lines
2.2 KiB
Go
54 lines
2.2 KiB
Go
package view
|
|
|
|
// The data of the two signed-out pages, sign-in and first-run setup. Neither has
|
|
// a user, so their Meta carries a Title and nothing else: Engine.Render then
|
|
// draws them with layout_signed_out, the split brand / form screen, and the
|
|
// page template supplies only the form column's content.
|
|
|
|
// Login is the data of the sign-in page (templates/login.html). Host is the
|
|
// name the panel is served as, shown above the title so the person knows which
|
|
// server is asking for a password; it is left out when the name is not known.
|
|
// SetupHint replaces the form by a pointer to the one-time setup link, for a
|
|
// panel that has no administrator yet. Error is the refusal of the last attempt
|
|
// ("Too many attempts…"); the page shows it as a flash above the fields.
|
|
type Login struct {
|
|
Meta
|
|
Host string
|
|
SetupHint bool
|
|
Error string
|
|
}
|
|
|
|
// NewLogin returns the sign-in page's data. host and formErr may be empty.
|
|
func NewLogin(host, formErr string) *Login {
|
|
return &Login{Meta: Meta{Title: "Sign in"}, Host: host, Error: formErr}
|
|
}
|
|
|
|
// NewLoginSetupHint returns the sign-in page's data for a panel with no
|
|
// administrator yet: no form, only the way to the setup link.
|
|
func NewLoginSetupHint(host string) *Login {
|
|
return &Login{Meta: Meta{Title: "Sign in"}, Host: host, SetupHint: true}
|
|
}
|
|
|
|
// Notice is the page's error as the flash partial's input; it is read only when
|
|
// Error is set.
|
|
func (l *Login) Notice() Flash { return Flash{Error: true, Text: Plain(l.Error)} }
|
|
|
|
// Setup is the data of the first-run page that creates the administrator
|
|
// (templates/setup.html), reached by the one-time link /setup/<Token>. Token is
|
|
// the path segment the form posts back to; Error is the refusal of the last
|
|
// submission, shown as a flash above the fields.
|
|
type Setup struct {
|
|
Meta
|
|
Token string
|
|
Error string
|
|
}
|
|
|
|
// NewSetup returns the setup page's data. formErr may be empty.
|
|
func NewSetup(token, formErr string) *Setup {
|
|
return &Setup{Meta: Meta{Title: "Create administrator"}, Token: token, Error: formErr}
|
|
}
|
|
|
|
// Notice is the page's error as the flash partial's input; it is read only when
|
|
// Error is set.
|
|
func (s *Setup) Notice() Flash { return Flash{Error: true, Text: Plain(s.Error)} }
|