Speak the suite's sign-in door copy at id.oficina.works
The hub's door button reads 'Sign in' (was 'Continue'), with the shared help line, sent and signed-out copy; titles read '<Page> · Oficina'; the email says 'expires in 15 minutes'. People no longer see the hub called 'Home': 'Back to Oficina', 'Not connected to Oficina yet', and connect.English reworded to 'your Oficina account'. Reviewed by GPT-6-Astra via Codex (#79). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Squashed from chore/door-copy into main.
18 files changed,
+233
−57
connect/view.go+9 −5connect/view_test.go+31 −0go.mod+1 −1go.sum+2 −18internal/home/calma.go+15 −0internal/home/directory_catalog.go+4 −4internal/home/directory_catalog_test.go+1 −1internal/home/door_copy_test.go+135 −0internal/home/handoff_failure_test.go+2 −2internal/home/signin.go+6 −1internal/home/templates/check_your_mail.html+6 −6internal/home/templates/directory_signed_out.html+6 −5internal/home/templates/docs_chooser.html+1 −1internal/home/templates/docs_empty.html+1 −1internal/home/templates/docs_unavailable.html+1 −1internal/home/templates/handoff_failed.html+2 −2internal/home/templates/signin.html+9 −8internal/home/templates/signin_failed.html+1 −1
CI passed — run details
diff --git a/connect/view.go b/connect/view.go| index ba0eda2..c7736a2 100644 |
| --- a/connect/view.go |
| +++ b/connect/view.go |
| @@ -46,10 +46,14 @@ func Page(state, label string, translate ...func(string) string) PageData { |
| return p |
| } |
| +// English is the copy the apps render for connecting an account. It |
| +// never names the hub: the account is "your Oficina account" (Paul, |
| +// 2026-09-23), worded as Docs' approved docs.home.* strings are. The |
| +// signed-out state speaks the door's words (estilo chrome.English). |
| var English = map[string]string{ |
| - "signedout_title": "Signed out", "signedout_body": "You can sign in again with Home.", "signedout_action": "Sign in with Home", |
| - "start_title": "Connect your account to Home", "start_body": "Use Home to sign in to this account. Your content and sharing settings stay as they are.", "start_action": "Continue to Home", "cancel_action": "Back", |
| - "confirm_title": "Confirm account connection", "confirm_body": "Connect the account below to the Home account you just signed into.", "confirm_action": "Connect accounts", |
| - "unknown_title": "Home account not connected", "unknown_body": "Sign in to your existing account, then connect Home from the account menu.", "local_action": "Sign in to your existing account", |
| - "failed_title": "Could not connect accounts", "failed_body": "Return to the app and start again.", "success_title": "Accounts connected", "success_body": "You can now use Home to sign in to this account.", "documents_action": "Back to the app", "menu_action": "Connect Home account", |
| + "signedout_title": "You’re signed out", "signedout_body": "You can sign in again with your Oficina account.", "signedout_action": "Sign in", |
| + "start_title": "Connect your Oficina account", "start_body": "Use your Oficina account to sign in to this account. Your content and sharing settings stay as they are.", "start_action": "Connect", "cancel_action": "Back", |
| + "confirm_title": "Confirm account connection", "confirm_body": "Connect the account below to the Oficina account you just signed in to.", "confirm_action": "Connect accounts", |
| + "unknown_title": "Oficina account not connected", "unknown_body": "Sign in to your existing account, then connect your Oficina account from the account menu.", "local_action": "Sign in to your existing account", |
| + "failed_title": "Could not connect accounts", "failed_body": "Return to the app and start again.", "success_title": "Accounts connected", "success_body": "You can now use your Oficina account to sign in to this account.", "documents_action": "Back to the app", "menu_action": "Connect your Oficina account", |
| } |
diff --git a/connect/view_test.go b/connect/view_test.go| new file mode 100644 |
| index 0000000..b48f1ca |
| --- /dev/null |
| +++ b/connect/view_test.go |
| @@ -0,0 +1,31 @@ |
| +package connect |
| + |
| +import ( |
| + "strings" |
| + "testing" |
| +) |
| + |
| +// The apps render this copy. It never names the hub (Paul, 2026-09-23): |
| +// the account is "your Oficina account". |
| +func TestEnglishNeverNamesTheHub(t *testing.T) { |
| + for k, v := range English { |
| + if strings.Contains(v, "Home") { |
| + t.Errorf("%s = %q names Home", k, v) |
| + } |
| + } |
| + for state, want := range map[string]string{ |
| + "signedout": "You’re signed out", |
| + "start": "Connect your Oficina account", |
| + "unknown": "Oficina account not connected", |
| + } { |
| + if got := Page(state, "").Title; got != want { |
| + t.Errorf("%s title = %q, want %q", state, got, want) |
| + } |
| + } |
| + if got := Page("signedout", "").ActionLabel; got != "Sign in" { |
| + t.Errorf("signedout action = %q, want %q", got, "Sign in") |
| + } |
| + if got := English["menu_action"]; got != "Connect your Oficina account" { |
| + t.Errorf("menu_action = %q", got) |
| + } |
| +} |
diff --git a/go.mod b/go.mod| index 989def4..79ca099 100644 |
| --- a/go.mod |
| +++ b/go.mod |
| @@ -5,7 +5,7 @@ go 1.25.0 |
| toolchain go1.26.5 |
| require ( |
| - amadan.net/oficina/estilo.git v0.0.0-20260929172243-77346e82cb36 |
| + amadan.net/oficina/estilo.git v0.0.0-20261001084202-0b4d92c3dc16 |
| amadan.net/oficina/home/handoff v0.0.0-20260908102137-481d2d57f489 |
| amadan.net/oficina/home/roster v0.0.0-20260908123429-74dda570e0cf |
| amadan.net/rastrillo/rastrillo v0.26.1-0.20260908075707-29e4491631bd |
diff --git a/go.sum b/go.sum| index 8768f37..77a79ac 100644 |
| --- a/go.sum |
| +++ b/go.sum |
| @@ -1,23 +1,7 @@ |
| amadan.net/carlos/platform.git/launchctx v0.0.0-20260911135504-fb577f96f7d1 h1:RxwIRojWcVtwSdNAjtdz7y1bxHLh3GUgqT1TrXVKpyM= |
| amadan.net/carlos/platform.git/launchctx v0.0.0-20260911135504-fb577f96f7d1/go.mod h1:6fBmMWgtESLFXZURzu/HyRXM0vyLuo4+XGGdKuZ+wao= |
| -amadan.net/oficina/estilo.git v0.0.0-20260911182719-0bcb9287988d h1:3HsB96tGs+P0tGf2VzqpqA8yqYBhJ+apBh2txAoz9qI= |
| -amadan.net/oficina/estilo.git v0.0.0-20260911182719-0bcb9287988d/go.mod h1:0R45/vCUAT+kpS7S6K/ZxBdE8f7YxFN4HT3HyDJ3nPY= |
| -amadan.net/oficina/estilo.git v0.0.0-20260929065402-0f830bc12f2c h1:XE8qYLSGKYLN+SNJv+/BMx0rCnHFUJusJcQ0/JLS+IM= |
| -amadan.net/oficina/estilo.git v0.0.0-20260929065402-0f830bc12f2c/go.mod h1:4u0jNBtIdMLOsJyrScfqoEuYDJF7BBM3qM9YWbzt6aw= |
| -amadan.net/oficina/estilo.git v0.0.0-20260929065843-683ccd534ead h1:t5QdNWBWWIJonOPdyD6CuwZ64XdahP7j8U+ewlTg1e8= |
| -amadan.net/oficina/estilo.git v0.0.0-20260929065843-683ccd534ead/go.mod h1:4u0jNBtIdMLOsJyrScfqoEuYDJF7BBM3qM9YWbzt6aw= |
| -amadan.net/oficina/estilo.git v0.0.0-20260929070257-7a1a376ad2ab h1:ypKDilZG0lxfXyPrEPVPmWFHnDNDsl1NE+IndxiukkY= |
| -amadan.net/oficina/estilo.git v0.0.0-20260929070257-7a1a376ad2ab/go.mod h1:4u0jNBtIdMLOsJyrScfqoEuYDJF7BBM3qM9YWbzt6aw= |
| -amadan.net/oficina/estilo.git v0.0.0-20260929070530-5b2ce835e773 h1:9DIAhG3TaGG+LE2+8LvU73ZEhfK+oNn2y2p4kFjAAi0= |
| -amadan.net/oficina/estilo.git v0.0.0-20260929070530-5b2ce835e773/go.mod h1:4u0jNBtIdMLOsJyrScfqoEuYDJF7BBM3qM9YWbzt6aw= |
| -amadan.net/oficina/estilo.git v0.0.0-20260929082849-4d41ba2100ff h1:eGeR7E6hcL8b1z6FR1v0LkoY58lVyVLju7xvz39gJkQ= |
| -amadan.net/oficina/estilo.git v0.0.0-20260929082849-4d41ba2100ff/go.mod h1:4u0jNBtIdMLOsJyrScfqoEuYDJF7BBM3qM9YWbzt6aw= |
| -amadan.net/oficina/estilo.git v0.0.0-20260929171000-db2000f8275c h1:RPB7vypc+8AFIl+vMAxPCwFbEp2o+G3Dop+68klwn2M= |
| -amadan.net/oficina/estilo.git v0.0.0-20260929171000-db2000f8275c/go.mod h1:4u0jNBtIdMLOsJyrScfqoEuYDJF7BBM3qM9YWbzt6aw= |
| -amadan.net/oficina/estilo.git v0.0.0-20260929171256-065aca0402c2 h1:zPP+L/nK+PpXsg237Y5nAGP6RaAmoUBcp5DKY5kzNAY= |
| -amadan.net/oficina/estilo.git v0.0.0-20260929171256-065aca0402c2/go.mod h1:4u0jNBtIdMLOsJyrScfqoEuYDJF7BBM3qM9YWbzt6aw= |
| -amadan.net/oficina/estilo.git v0.0.0-20260929172243-77346e82cb36 h1:Gu1R9LtvUQjn7HsUcJxowYHgIB9SdKq8yrDQs6SWnWg= |
| -amadan.net/oficina/estilo.git v0.0.0-20260929172243-77346e82cb36/go.mod h1:4u0jNBtIdMLOsJyrScfqoEuYDJF7BBM3qM9YWbzt6aw= |
| +amadan.net/oficina/estilo.git v0.0.0-20261001084202-0b4d92c3dc16 h1:F5v3x25dEj1rJNnBm71G7shN+fM+T2actUlaGPvoeH8= |
| +amadan.net/oficina/estilo.git v0.0.0-20261001084202-0b4d92c3dc16/go.mod h1:4u0jNBtIdMLOsJyrScfqoEuYDJF7BBM3qM9YWbzt6aw= |
| 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/oficina/home/roster v0.0.0-20260908123429-74dda570e0cf h1:SRKjCUgtk42WwR7VSn+V0eLNk20mfiY8dQmzdw13Sbo= |
diff --git a/internal/home/calma.go b/internal/home/calma.go| index 631387a..92557f3 100644 |
| --- a/internal/home/calma.go |
| +++ b/internal/home/calma.go |
| @@ -4,6 +4,7 @@ import ( |
| "amadan.net/oficina/estilo.git/busy" |
| _ "embed" |
| + "amadan.net/oficina/estilo.git/chrome" |
| "amadan.net/oficina/estilo.git/sky" |
| "amadan.net/oficina/estilo.git/theme" |
| "github.com/go-chi/chi/v5" |
| @@ -25,8 +26,22 @@ var homeFuncs = map[string]any{ |
| "suiteSky": func() sky.View { return sky.For(sky.SuiteSeed) }, |
| // Onest's stylesheet, under estilo's versioned prefix. |
| "fontsCSS": func() string { return theme.FontPrefix + "fonts.css" }, |
| + // The door's words and tab titles are estilo's (chrome.English), the |
| + // one copy set every app's door speaks, so the hub's door cannot |
| + // drift from theirs. Home draws its own templates, so it reads the |
| + // strings from estilo's types rather than rendering estilo-signin. |
| + "signinDoor": func() chrome.SignIn { return chrome.SignIn{App: suiteName} }, |
| + "sentDoor": func() chrome.SignInNotice { return chrome.SignInNotice{App: suiteName}.Sent("/signin") }, |
| + "signedOutDoor": func() chrome.SignInNotice { |
| + return chrome.SignInNotice{App: suiteName}.SignedOut("/auth/start") |
| + }, |
| + "linkLifetime": func() int { return int(chrome.LinkLifetime.Minutes()) }, |
| } |
| +// suiteName is what the hub calls itself to people: the suite, never |
| +// "Home" (Paul, 2026-09-23). |
| +const suiteName = "Oficina" |
| + |
| // doorPages are the pages at the door — signing in, and everything on the |
| // way in or out. The layout draws them as one card on the sky with the |
| // Oficina mark, as Calma's sign-in does; every other page keeps the full |
diff --git a/internal/home/directory_catalog.go b/internal/home/directory_catalog.go| index b417778..0e89eb0 100644 |
| --- a/internal/home/directory_catalog.go |
| +++ b/internal/home/directory_catalog.go |
| @@ -16,11 +16,11 @@ func directoryCatalog(cfg Runtime) []catalogApp { |
| } |
| apps := []catalogApp{ |
| docs, |
| - {Name: "Sheets", Icon: "/static/brand/sheets.svg", Status: "Not connected to Home yet"}, |
| - {Name: "Slides", Icon: "/static/brand/slides.svg", Status: "Not connected to Home yet"}, |
| - {Name: "Calendar", Icon: "/static/brand/calendar.svg", Status: "Not connected to Home yet"}, |
| + {Name: "Sheets", Icon: "/static/brand/sheets.svg", Status: "Not connected to Oficina yet"}, |
| + {Name: "Slides", Icon: "/static/brand/slides.svg", Status: "Not connected to Oficina yet"}, |
| + {Name: "Calendar", Icon: "/static/brand/calendar.svg", Status: "Not connected to Oficina yet"}, |
| {Name: "Calls", Icon: "/static/brand/calls.svg", Status: "Coming soon"}, |
| - {Name: "Memoria", Icon: "/static/brand/memoria.svg", Status: "Not connected to Home yet"}, |
| + {Name: "Memoria", Icon: "/static/brand/memoria.svg", Status: "Not connected to Oficina yet"}, |
| {Name: "Mail", Icon: "/static/brand/mail.svg", Status: "Separate sign-in"}, |
| {Name: "Files", Icon: "/static/brand/files.svg", Status: "Separate sign-in"}, |
| } |
diff --git a/internal/home/directory_catalog_test.go b/internal/home/directory_catalog_test.go| index e103859..58db5be 100644 |
| --- a/internal/home/directory_catalog_test.go |
| +++ b/internal/home/directory_catalog_test.go |
| @@ -53,7 +53,7 @@ func TestDirectoryCatalogRequiresSigninAndDoesNotInventLaunchDestinations(t *tes |
| if strings.Count(body, "<a ") != 7 || strings.Count(body, `href="/help/open-source"`) != 1 || !strings.Contains(body, `href="/apps/docs"`) || !strings.Contains(body, "Choose a team") || hasOtherScript(body) { |
| t.Fatal("catalog advertised unsupported launch", body) |
| } |
| - if strings.Count(body, "Not connected to Home yet") != 0 || strings.Count(body, "Coming soon") != 0 || strings.Count(body, "Separate sign-in") != 2 { |
| + if strings.Count(body, "Not connected to Oficina yet") != 0 || strings.Count(body, "Coming soon") != 0 || strings.Count(body, "Separate sign-in") != 2 { |
| t.Fatal("catalog readiness missing", body) |
| } |
| entry := f.request("GET", docsEntryPath, "", "", cookie) |
diff --git a/internal/home/door_copy_test.go b/internal/home/door_copy_test.go| new file mode 100644 |
| index 0000000..7c5552a |
| --- /dev/null |
| +++ b/internal/home/door_copy_test.go |
| @@ -0,0 +1,135 @@ |
| +package home |
| + |
| +import ( |
| + "net/http" |
| + "net/http/httptest" |
| + "strings" |
| + "testing" |
| +) |
| + |
| +// The door's words are estilo's chrome.English, the one copy set every |
| +// app's door renders (Paul, 2026-10-01: the submit reads "Sign in", never |
| +// "Continue" or "Email me a link"). They are pinned here as literals, not |
| +// read back from chrome.English, so a change upstream shows up as a red |
| +// test on the hub rather than as silently different copy. |
| +const ( |
| + doorHelp = "We’ll email you a link that signs you in. It works once and expires in 15 minutes." |
| + doorSentBody = "If that address can sign in here, we’ve sent it a link. It works once and expires in 15 minutes." |
| +) |
| + |
| +func getCredential(t *testing.T, app *testApp, path string) string { |
| + t.Helper() |
| + req := httptest.NewRequest(http.MethodGet, path, nil) |
| + req.Host = credentialHost |
| + w := httptest.NewRecorder() |
| + app.Router().ServeHTTP(w, req) |
| + if w.Code != http.StatusOK { |
| + t.Fatalf("GET %s: %d", path, w.Code) |
| + } |
| + return w.Body.String() |
| +} |
| + |
| +func mustContain(t *testing.T, page, body string, wants ...string) { |
| + t.Helper() |
| + for _, want := range wants { |
| + if !strings.Contains(body, want) { |
| + t.Errorf("%s: missing %q", page, want) |
| + } |
| + } |
| +} |
| + |
| +func mustNotContain(t *testing.T, page, body string, nots ...string) { |
| + t.Helper() |
| + for _, not := range nots { |
| + if strings.Contains(body, not) { |
| + t.Errorf("%s: still says %q", page, not) |
| + } |
| + } |
| +} |
| + |
| +func TestDoorSpeaksTheSuiteCopy(t *testing.T) { |
| + app := newTestApp(t) |
| + |
| + form := getCredential(t, app, "/signin") |
| + mustContain(t, "/signin", form, |
| + "<title>Sign in · Oficina</title>", |
| + "<h1>Sign in</h1>", |
| + ">Email address</label>", |
| + doorHelp, |
| + `<button type="submit" rst-btn="primary">Sign in</button>`) |
| + mustNotContain(t, "/signin", form, ">Continue<", "Email me a link", "Home") |
| + |
| + sent := getCredential(t, app, "/signin/sent") |
| + mustContain(t, "/signin/sent", sent, |
| + "<title>Check your email · Oficina</title>", |
| + "<h1>Check your email</h1>", |
| + doorSentBody, |
| + `<a href="/signin">Use a different address</a>`) |
| + mustNotContain(t, "/signin/sent", sent, "fifteen", "Check your mail", "Home") |
| + |
| + failed := redeem(t, app, "not-a-token").Body.String() |
| + mustContain(t, "signin failed", failed, "Sign-in links work once and expire after 15 minutes.") |
| + mustNotContain(t, "signin failed", failed, "fifteen") |
| + |
| + f := newMountedChooser(t) |
| + out := f.request("GET", "/signed-out", "", "", nil) |
| + if out.Code != http.StatusOK { |
| + t.Fatalf("GET /signed-out: %d", out.Code) |
| + } |
| + mustContain(t, "/signed-out", out.Body.String(), |
| + "<title>Signed out · Oficina</title>", |
| + "<h1>You’re signed out</h1>", |
| + "You’ve signed out of Oficina on this device.", |
| + `rst-btn="primary">Sign in</a>`) |
| + mustNotContain(t, "/signed-out", out.Body.String(), "You are signed out", "Home") |
| +} |
| + |
| +// The hub builds its own signin.Flow, so it sets the email itself: the |
| +// suite's subject, and a body that says how long the link lasts rather |
| +// than keymaildev's default "expires shortly". |
| +func TestSigninEmailSpeaksTheSuiteCopy(t *testing.T) { |
| + app := newTestApp(t) |
| + signIn(t, app, "someone@example.com") |
| + mail, ok := app.mailer.last() |
| + if !ok { |
| + t.Fatal("no mail was sent") |
| + } |
| + if mail.Subject != "Sign in to Oficina" { |
| + t.Errorf("subject = %q", mail.Subject) |
| + } |
| + for _, want := range []string{"Here’s your link to sign in to Oficina:", Origin + linkPath + "?token=", "It works once and expires in 15 minutes."} { |
| + if !strings.Contains(mail.Body, want) { |
| + t.Errorf("body missing %q:\n%s", want, mail.Body) |
| + } |
| + } |
| + if strings.Contains(mail.Body, "shortly") || strings.Contains(mail.Body, "Home") { |
| + t.Errorf("body is not the suite's copy:\n%s", mail.Body) |
| + } |
| +} |
| + |
| +// Never name the hub to people (Paul, 2026-09-23): the suite is Oficina. |
| +func TestHubNeverCallsItselfHome(t *testing.T) { |
| + f := newMountedChooser(t) |
| + page := f.request("GET", "/", "", "", f.session(t, chooserPerson)) |
| + mustNotContain(t, "directory", page.Body.String(), "to Home") |
| + for _, app := range directoryCatalog(Runtime{}) { |
| + if strings.Contains(app.Status, "Home") { |
| + t.Errorf("%s: status %q names Home", app.Name, app.Status) |
| + } |
| + } |
| + files, err := templatesFS.ReadDir("templates") |
| + if err != nil { |
| + t.Fatal(err) |
| + } |
| + for _, e := range files { |
| + b, err := templatesFS.ReadFile("templates/" + e.Name()) |
| + if err != nil { |
| + t.Fatal(err) |
| + } |
| + for _, bad := range []string{"Back to Home", "Return to Home", "to Home"} { |
| + if strings.Contains(string(b), bad) { |
| + t.Errorf("%s says %q", e.Name(), bad) |
| + } |
| + } |
| + } |
| +} |
diff --git a/internal/home/handoff_failure_test.go b/internal/home/handoff_failure_test.go| index 092f393..254164c 100644 |
| --- a/internal/home/handoff_failure_test.go |
| +++ b/internal/home/handoff_failure_test.go |
| @@ -37,7 +37,7 @@ func TestHandoffFailuresHaveFixedPrivateDiagnostics(t *testing.T) { |
| t.Fatal(response.Code, response.Header()) |
| } |
| body := response.Body.String() |
| - if !strings.Contains(body, "Could not finish signing in") || strings.Contains(body, "fifteen minutes") || !strings.Contains(body, `href="`+directoryOrigin+`"`) || strings.Contains(body, secret) { |
| + if !strings.Contains(body, "Could not finish signing in") || strings.Contains(body, "15 minutes") || !strings.Contains(body, `href="`+directoryOrigin+`"`) || strings.Contains(body, secret) { |
| t.Fatal("wrong handoff failure page", body) |
| } |
| log := p.logs.String() |
| @@ -52,7 +52,7 @@ func TestHandoffFailuresHaveFixedPrivateDiagnostics(t *testing.T) { |
| } |
| p.logs.Reset() |
| failedLink := exchangeRequest(p.credential.App, "POST", Origin+linkPath, Origin, url.Values{"token": {secret}}) |
| - if failedLink.Code != 400 || !strings.Contains(failedLink.Body.String(), "Sign-in links work once and expire after fifteen minutes") || strings.Contains(p.logs.String(), "home handoff failed") { |
| + if failedLink.Code != 400 || !strings.Contains(failedLink.Body.String(), "Sign-in links work once and expire after 15 minutes") || strings.Contains(p.logs.String(), "home handoff failed") { |
| t.Fatal("magic-link failure changed", failedLink.Code) |
| } |
| } |
diff --git a/internal/home/signin.go b/internal/home/signin.go| index d66be07..1888483 100644 |
| --- a/internal/home/signin.go |
| +++ b/internal/home/signin.go |
| @@ -7,6 +7,7 @@ import ( |
| "strings" |
| "time" |
| + "amadan.net/oficina/estilo.git/chrome" |
| "github.com/carlosframework/rastrillo/sessions" |
| "github.com/keymaildev/signin" |
| ) |
| @@ -94,7 +95,11 @@ func newFlow(secrets Secrets, links signin.LinkStore, origin string) *signin.Flo |
| Key: secrets.SigninKey, |
| Origin: origin, |
| LinkPath: linkPath, |
| - Subject: "Sign in to Oficina", |
| + // The suite's subject and body (estilo chrome.English), so the |
| + // email says how long the link lasts rather than keymaildev's |
| + // default "expires shortly", and names Oficina, never "Home". |
| + Subject: chrome.EmailSubject(suiteName), |
| + Body: chrome.EmailBody(suiteName), |
| } |
| } |
diff --git a/internal/home/templates/check_your_mail.html b/internal/home/templates/check_your_mail.html| index 8d38667..517f714 100644 |
| --- a/internal/home/templates/check_your_mail.html |
| +++ b/internal/home/templates/check_your_mail.html |
| @@ -1,6 +1,6 @@ |
| -{{define "title"}}Check your mail · Oficina{{end}} |
| -{{define "content"}} |
| -<h1>Check your mail</h1> |
| -<p>If that address can sign in here, a link is on its way. It works once, and expires in fifteen minutes.</p> |
| -<p><a href="/signin">Use a different address</a></p> |
| -{{end}} |
| +{{define "title"}}{{sentDoor.Title}}{{end}} |
| +{{define "content"}}{{with sentDoor}} |
| +<h1>{{.Heading}}</h1> |
| +<p>{{.Body}}</p> |
| +<p><a href="{{.Link.Href}}">{{.Link.Label}}</a></p> |
| +{{end}}{{end}} |
diff --git a/internal/home/templates/directory_signed_out.html b/internal/home/templates/directory_signed_out.html| index ace69eb..19d79fe 100644 |
| --- a/internal/home/templates/directory_signed_out.html |
| +++ b/internal/home/templates/directory_signed_out.html |
| @@ -1,5 +1,6 @@ |
| -{{define "title"}}Oficina{{end}} |
| -{{define "content"}} |
| -<h1>You are signed out</h1> |
| -<a href="/auth/start" rst-btn="primary">Sign in</a> |
| -{{end}} |
| +{{define "title"}}{{signedOutDoor.Title}}{{end}} |
| +{{define "content"}}{{with signedOutDoor}} |
| +<h1>{{.Heading}}</h1> |
| +<p>{{.Body}}</p> |
| +<a href="{{.Link.Href}}" rst-btn="primary">{{.Link.Label}}</a> |
| +{{end}}{{end}} |
diff --git a/internal/home/templates/docs_chooser.html b/internal/home/templates/docs_chooser.html| index f8de751..eec274c 100644 |
| --- a/internal/home/templates/docs_chooser.html |
| +++ b/internal/home/templates/docs_chooser.html |
| @@ -7,5 +7,5 @@ |
| <button type="submit" name="team" value="{{.SQID}}" rst-btn>{{.Name}}</button> |
| {{end}} |
| </form> |
| -<p><a href="/">Back to Home</a></p> |
| +<p><a href="/">Back to Oficina</a></p> |
| {{end}} |
diff --git a/internal/home/templates/docs_empty.html b/internal/home/templates/docs_empty.html| index 483356e..d3df80d 100644 |
| --- a/internal/home/templates/docs_empty.html |
| +++ b/internal/home/templates/docs_empty.html |
| @@ -2,5 +2,5 @@ |
| {{define "content"}} |
| <h1>No teams available</h1> |
| <p>This account has no team with {{.AppName}} available.</p> |
| -<p><a href="/">Back to Home</a></p> |
| +<p><a href="/">Back to Oficina</a></p> |
| {{end}} |
diff --git a/internal/home/templates/docs_unavailable.html b/internal/home/templates/docs_unavailable.html| index 51e2bcd..f8ff90b 100644 |
| --- a/internal/home/templates/docs_unavailable.html |
| +++ b/internal/home/templates/docs_unavailable.html |
| @@ -2,5 +2,5 @@ |
| {{define "content"}} |
| <h1>Could not load your teams</h1> |
| <p>Try again in a moment.</p> |
| -<p><a href="/">Back to Home</a></p> |
| +<p><a href="/">Back to Oficina</a></p> |
| {{end}} |
diff --git a/internal/home/templates/handoff_failed.html b/internal/home/templates/handoff_failed.html| index 0017972..fa7ddcd 100644 |
| --- a/internal/home/templates/handoff_failed.html |
| +++ b/internal/home/templates/handoff_failed.html |
| @@ -1,6 +1,6 @@ |
| {{define "title"}}Could not finish signing in · Oficina{{end}} |
| {{define "content"}} |
| <h1>Could not finish signing in</h1> |
| -<p>Return to Home and open the app again.</p> |
| -<p><a href="{{.HomeURL}}">Back to Home</a></p> |
| +<p>Return to Oficina and open the app again.</p> |
| +<p><a href="{{.HomeURL}}">Back to Oficina</a></p> |
| {{end}} |
diff --git a/internal/home/templates/signin.html b/internal/home/templates/signin.html| index 94b0e20..373cdff 100644 |
| --- a/internal/home/templates/signin.html |
| +++ b/internal/home/templates/signin.html |
| @@ -1,14 +1,15 @@ |
| -{{define "title"}}Sign in · Oficina{{end}} |
| -{{define "content"}} |
| -<h1>Sign in</h1> |
| -{{if .Error}}<p role="alert" rst-callout rst-tone="negative"><span rst-callout-body>{{.Error}}</span></p>{{end}} |
| +{{define "title"}}{{signinDoor.Title}}{{end}} |
| +{{define "content"}}{{with signinDoor}} |
| +<h1>{{.Heading}}</h1> |
| +{{if $.Error}}<p role="alert" rst-callout rst-tone="negative"><span rst-callout-body>{{$.Error}}</span></p>{{end}} |
| <form method="post" action="/signin" rst-form> |
| <div rst-field> |
| - <label rst-field-label for="address">Email address</label> |
| - <input id="address" name="address" type="email" autocomplete="email" required autofocus rst-input> |
| + <label rst-field-label for="address">{{.AddressLabel}}</label> |
| + <input id="address" name="address" type="email" autocomplete="email" required autofocus rst-input aria-describedby="address-help"> |
| + <p id="address-help" rst-field-help>{{.Help}}</p> |
| </div> |
| <div rst-form-foot> |
| - <button type="submit" rst-btn="primary">Continue</button> |
| + <button type="submit" rst-btn="primary">{{.Submit}}</button> |
| </div> |
| </form> |
| -{{end}} |
| +{{end}}{{end}} |
diff --git a/internal/home/templates/signin_failed.html b/internal/home/templates/signin_failed.html| index 74929f8..d8494b5 100644 |
| --- a/internal/home/templates/signin_failed.html |
| +++ b/internal/home/templates/signin_failed.html |
| @@ -1,6 +1,6 @@ |
| {{define "title"}}That link did not work · Oficina{{end}} |
| {{define "content"}} |
| <h1>That link did not work</h1> |
| -<p>Sign-in links work once and expire after fifteen minutes. Ask for a new one.</p> |
| +<p>Sign-in links work once and expire after {{linkLifetime}} minutes. Ask for a new one.</p> |
| <p><a href="/signin">Start again</a></p> |
| {{end}} |