Prepare shared-style account connection screens and current handoff dependency
5 files changed,
+87
−6
go.mod+1 −1go.sum+2 −0internal/docs/home_render.go+44 −0internal/docs/render.go+30 −5internal/docs/views/home_link.html+10 −0
CI passed — run details
diff --git a/go.mod b/go.mod| index af27f6f..2b025da 100644 |
| --- a/go.mod |
| +++ b/go.mod |
| @@ -4,7 +4,7 @@ go 1.26.5 |
| require ( |
| amadan.net/oficina/estilo.git v0.0.0-20260908001419-672a447da335 |
| - amadan.net/oficina/home/handoff v0.0.0-20260908100301-967d29f96288 |
| + amadan.net/oficina/home/handoff v0.0.0-20260908102137-481d2d57f489 |
| github.com/carlosframework/rastrillo v0.23.0 |
| github.com/go-chi/chi/v5 v5.3.2 |
| github.com/google/uuid v1.6.0 |
diff --git a/go.sum b/go.sum| index 657556f..69457d9 100644 |
| --- a/go.sum |
| +++ b/go.sum |
| @@ -2,6 +2,8 @@ amadan.net/oficina/estilo.git v0.0.0-20260908001419-672a447da335 h1:YogZKYINrPNX |
| amadan.net/oficina/estilo.git v0.0.0-20260908001419-672a447da335/go.mod h1:0R45/vCUAT+kpS7S6K/ZxBdE8f7YxFN4HT3HyDJ3nPY= |
| amadan.net/oficina/home/handoff v0.0.0-20260908100301-967d29f96288 h1:T1GQM8pChN+4+cpx7TUF7ogCczUaCw/D98YR8nH35NA= |
| amadan.net/oficina/home/handoff v0.0.0-20260908100301-967d29f96288/go.mod h1:YISpzFJ+iMgrM0rUL032OSzsAQbP4/nozvXLCCOcn1k= |
| +amadan.net/oficina/home/handoff v0.0.0-20260908102137-481d2d57f489 h1:RPKtyry/71i06o8L+gjAaUyexbmG56kO1YPs601URAM= |
| +amadan.net/oficina/home/handoff v0.0.0-20260908102137-481d2d57f489/go.mod h1:YISpzFJ+iMgrM0rUL032OSzsAQbP4/nozvXLCCOcn1k= |
| amadan.net/rastrillo/rastrillo v0.26.1-0.20260908075707-29e4491631bd h1:jlFSt95M1ontOg+VePU+kIJpChtWqDQAbnmlxqCnbgc= |
| amadan.net/rastrillo/rastrillo v0.26.1-0.20260908075707-29e4491631bd/go.mod h1:RpyHVPD0udcSfHJroY0KZE/FUjgw6Tvfo8SJm2qeZGE= |
| github.com/carlosframework/rastrillo v0.23.0 h1:tKAAlwPt4Pg/rkqk7o6jvV12bbZ0r34oEVpuOlKfX7w= |
diff --git a/internal/docs/home_render.go b/internal/docs/home_render.go| new file mode 100644 |
| index 0000000..3577c7b |
| --- /dev/null |
| +++ b/internal/docs/home_render.go |
| @@ -0,0 +1,44 @@ |
| +package docs |
| + |
| +import ( |
| + "net/http" |
| + |
| + "github.com/carlosframework/rastrillo" |
| +) |
| + |
| +type homeLinkPage struct { |
| + Title, Body, Address, Action, ActionLabel, CancelLabel string |
| + PostAction bool |
| +} |
| + |
| +func (rd *renderer) homeLink(w http.ResponseWriter, r *http.Request, state, address string, status int) { |
| + page := homeLinkPage{Address: address} |
| + key := "docs.home." |
| + switch state { |
| + case "start": |
| + page.Action, page.PostAction = "/account/home", true |
| + page.ActionLabel = rastrillo.T(r, key+"start_action") |
| + case "confirm": |
| + page.Action, page.PostAction = "/account/home/confirm", true |
| + page.ActionLabel = rastrillo.T(r, key+"confirm_action") |
| + case "unknown": |
| + page.Action = "/signin/local" |
| + page.ActionLabel = rastrillo.T(r, key+"local_action") |
| + case "success": |
| + page.Action = "/" |
| + page.ActionLabel = rastrillo.T(r, key+"documents_action") |
| + default: |
| + state = "failed" |
| + page.Action = "/account/home" |
| + page.ActionLabel = rastrillo.T(r, key+"menu_action") |
| + } |
| + page.Title = rastrillo.T(r, key+state+"_title") |
| + page.Body = rastrillo.T(r, key+state+"_body") |
| + if state == "start" || state == "confirm" { |
| + page.CancelLabel = rastrillo.T(r, key+"cancel_action") |
| + } |
| + w.Header().Set("Cache-Control", "no-store") |
| + if err := rd.pageStatus(w, r, "home-link", page, status); err != nil { |
| + http.Error(w, rastrillo.T(r, "docs.error.generic"), http.StatusInternalServerError) |
| + } |
| +} |
diff --git a/internal/docs/render.go b/internal/docs/render.go| index 5011faa..5638a1b 100644 |
| --- a/internal/docs/render.go |
| +++ b/internal/docs/render.go |
| @@ -59,6 +59,23 @@ const ( |
| // template or a handler), resolved through rastrillo.T at render |
| // time. cmd/docs/main.go wires it in as rastrillo.Options.BaseCatalog. |
| var Catalog = rastrillo.Catalog{ |
| + "docs.home.start_title": "Connect Docs to Home", |
| + "docs.home.start_body": "Use Home to sign in to this Docs account. Your documents and sharing settings stay as they are.", |
| + "docs.home.start_action": "Continue to Home", |
| + "docs.home.cancel_action": "Back to Docs", |
| + "docs.home.confirm_title": "Confirm account connection", |
| + "docs.home.confirm_body": "Connect the Docs account below to the Home account you just signed into.", |
| + "docs.home.confirm_action": "Connect accounts", |
| + "docs.home.unknown_title": "Home account not connected", |
| + "docs.home.unknown_body": "Sign in to your existing Docs account, then connect Home from the account menu.", |
| + "docs.home.local_action": "Sign in to Docs", |
| + "docs.home.failed_title": "Could not connect accounts", |
| + "docs.home.failed_body": "Return to Docs and start again.", |
| + "docs.home.success_title": "Accounts connected", |
| + "docs.home.success_body": "You can now use Home to sign in to this Docs account.", |
| + "docs.home.documents_action": "Back to documents", |
| + "docs.home.menu_action": "Connect Home account", |
| + |
| // docs.list.* — GET /, spec §6.4. Title is the screen's noun, per |
| // page-header's own contract ("Posts", not "Home"). The four group |
| // labels are recency buckets (handlers.go's recencyBucket); a |
| @@ -454,11 +471,12 @@ const headTemplate = "views/head.html" |
| // pageTemplates maps a page name to its file under views/. |
| var pageTemplates = map[string]string{ |
| - "list": "views/list.html", |
| - "public": "views/public.html", |
| - "share": "views/share.html", |
| - "show": "views/show.html", |
| - "signin": "views/signin.html", |
| + "home-link": "views/home_link.html", |
| + "list": "views/list.html", |
| + "public": "views/public.html", |
| + "share": "views/share.html", |
| + "show": "views/show.html", |
| + "signin": "views/signin.html", |
| } |
| // renderer owns the app's parsed templates and its fingerprinted |
| @@ -540,6 +558,10 @@ func newRenderer() (*renderer, error) { |
| // page renders the named page's "layout" template — its own content |
| // wrapped in rastrillo's shell — into w. |
| func (rd *renderer) page(w http.ResponseWriter, r *http.Request, name string, data any) error { |
| + return rd.pageStatus(w, r, name, data, 0) |
| +} |
| + |
| +func (rd *renderer) pageStatus(w http.ResponseWriter, r *http.Request, name string, data any, status int) error { |
| tmpl, ok := rd.pages[name] |
| if !ok { |
| return fmt.Errorf("docs: unknown page %q", name) |
| @@ -551,6 +573,9 @@ func (rd *renderer) page(w http.ResponseWriter, r *http.Request, name string, da |
| return fmt.Errorf("docs: render page %q: %w", name, err) |
| } |
| w.Header().Set("Content-Type", "text/html; charset=utf-8") |
| + if status != 0 { |
| + w.WriteHeader(status) |
| + } |
| _, err := buf.WriteTo(w) |
| return err |
| } |
diff --git a/internal/docs/views/home_link.html b/internal/docs/views/home_link.html| new file mode 100644 |
| index 0000000..d5b1e02 |
| --- /dev/null |
| +++ b/internal/docs/views/home_link.html |
| @@ -0,0 +1,10 @@ |
| +{{define "title"}}{{.Title}}{{end}} |
| +{{define "content"}} |
| +<header rst-page-header><div rst-page-header-titles><h1>{{.Title}}</h1></div></header> |
| +<div rst-box> |
| + <div rst-box-head><p>{{.Body}}</p>{{if .Address}}<p><strong>{{.Address}}</strong></p>{{end}}</div> |
| + {{if .PostAction}}<form method="post" action="{{.Action}}"><button rst-btn="primary" type="submit">{{.ActionLabel}}</button></form> |
| + {{else}}<a rst-btn="primary" href="{{.Action}}">{{.ActionLabel}}</a>{{end}} |
| + {{if .CancelLabel}}<a href="/">{{.CancelLabel}}</a>{{end}} |
| +</div> |
| +{{end}} |