Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions docs/decisions.md
Original file line number Diff line number Diff line change
Expand Up @@ -6094,6 +6094,33 @@ The same day the Admin dropped the status line "Připojeno, pokračuju…" ("Con
continuing…"): once the address answers, the page reloads into the Environment at
once, with nothing shown in between. `tests/shell-offline-guide.test.ts` keeps it out.

**Addendum 2026-10-12: one command under a moving sketch of the person's own system.**
Anna simplified the page on 2026-10-11 (#327), and the Organization Admin asked on
2026-10-12 to ship it to every Environment. It supersedes the page described in point 1
(the switch between four systems, the three numbered steps, "try again") and the button
of the addendum of 2026-10-09:
- **One command** as the heading, "Zapněte Tailscale a vyberte síť" ("Turn on Tailscale
and choose the network"; on a phone "Otevřete Tailscale…"), and the tailnet under it,
exactly as the Tailscale client lists it.
- **A moving sketch of the detected system** above it. The cursor clicks the Tailscale
icon, turns it on, opens the account's submenu and chooses the tailnet: in the menu
bar on macOS; in the tray by the clock on Windows, with Connect; through the app's
account button on a phone. The system is detected, so no switch between systems is
drawn. `prefers-reduced-motion` shows the finished state.
- **One small line** for when it fails: on Windows first "right-click the icon; it may
hide under ^ by the clock", then the documentation's detailed guide or the way back
to the Dashboard, now a link in that line beside the rail's logo.
- **No retry button**: the page retries by itself, as before, and reloads at once.
- The Environment and its Organization move from the lead to the tab's title
("Zapněte Tailscale · Pracovní Environment v Organizaci …").
- The Czech copy addresses the person formally (vykání), per the brand rule of
2026-10-11 that the rest of the Launchpad follows.

The worker, its cache, the registration, the update contract and `OfflineGuideInput`
are unchanged; the page's bytes change, so every installed worker takes the new page
with its next update check. Tests: `tests/shell-offline-guide.test.ts`,
`tests/launchpad-offline-guide.test.ts` and `scripts/smoke-offline-guide.ts`.

## F42 — Integrace: one catalog for the Environment, one path per app, Executor's API behind the Launchpad

**Decided by Matěj 2026-10-09 (root decision 0162, addendum of 2026-10-09; root
Expand Down
4 changes: 2 additions & 2 deletions scripts/smoke-offline-guide.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ async function main(): Promise<void> {
const shown = await text(page);
check(
"a navigation that does not resolve shows the guide",
shown.includes("Zapni Tailscale") &&
shown.includes("Zapněte Tailscale") &&
shown.includes("headscale.example.lazurio.io"),
);
check(
Expand Down Expand Up @@ -260,7 +260,7 @@ async function main(): Promise<void> {
let guided = false;
try {
await page.goto(`${origin}/`);
guided = (await text(page)).includes("Zapni Tailscale");
guided = (await text(page)).includes("Zapněte Tailscale");
} catch {
guided = false;
}
Expand Down
14 changes: 7 additions & 7 deletions src/shell/offline-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,22 +63,22 @@ type Copy = {

const copy: Record<"cs" | "en", Copy> = {
cs: {
title: "Zapni Tailscale",
title: "Zapněte Tailscale",
place: (environment, organization) =>
organization
? `${environment} Environment v Organizaci ${organization}`
: `${environment} Environment`,
desktop: "Zapni Tailscale a vyber síť",
phone: "Otevři Tailscale a vyber síť",
desktop: "Zapněte Tailscale a vyberte síť",
phone: "Otevřete Tailscale a vyberte síť",
windows:
"Na ikonu Tailscale klikni pravým tlačítkem. Nevidíš ji? Je schovaná pod šipkou ^ vedle hodin. ",
"Na ikonu Tailscale klikněte pravým tlačítkem. Nevidíte ji? Je schovaná pod šipkou ^ vedle hodin. ",
failed: "Nepovedlo se? Pomůže",
docs: "podrobný návod",
or: ", nebo se vrať do",
or: ", nebo se vraťte do",
dashboard: "Dashboardu",
home: "Dashboard",
you: "Ty",
account: "Tvůj účet",
you: "Vy",
account: "Váš účet",
otherTailnet: "jiná síť",
},
en: {
Expand Down
4 changes: 2 additions & 2 deletions tests/launchpad-offline-guide.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ posixTest(
const html = await page.text();
expect(html).toContain("headscale.example.lazurio.io");
expect(html).toContain(offlineDocsUrl("cs"));
expect(html).toContain("Zapni Tailscale");
expect(html).toContain("Zapněte Tailscale");
// The way back without the tailnet: the rail's logo and the link
// lead to the Dashboard the shell's rail names.
expect(html).toContain(
Expand All @@ -114,7 +114,7 @@ posixTest(
expect(html).toContain(
'<a class="back" href="https://dashboard.lazurio.ai/home">',
);
expect(html).toContain("nebo se vrať do");
expect(html).toContain("nebo se vraťte do");

const worker = await fetch(`${base}${OFFLINE_WORKER_PATH}`, {
headers: valid,
Expand Down
14 changes: 7 additions & 7 deletions tests/shell-offline-guide.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ test("the guide page names the Environment and its Organization in the tab's tit
expect(
renderOfflineGuide({ ...input, locale: "cs", environment: "Pracovní" }),
).toContain(
"<title>Zapni Tailscale · Pracovní Environment v Organizaci Example</title>",
"<title>Zapněte Tailscale · Pracovní Environment v Organizaci Example</title>",
);
expect(
renderOfflineGuide({ ...input, locale: "en", environment: "Work" }),
Expand All @@ -261,7 +261,7 @@ test("the guide page names the Environment and its Organization in the tab's tit
locale: "cs",
environment: "Osobní",
}),
).toContain("<title>Zapni Tailscale · Osobní Environment</title>");
).toContain("<title>Zapněte Tailscale · Osobní Environment</title>");
});

test("the guide page says one thing to do, with the tailnet, and one small line for when it fails", () => {
Expand All @@ -276,17 +276,17 @@ test("the guide page says one thing to do, with the tailnet, and one small line
// The command of a computer and of a phone; the script shows the one of
// the person's system.
expect(page).toContain(
'<span data-show="macos windows">Zapni Tailscale a vyber síť</span>',
'<span data-show="macos windows">Zapněte Tailscale a vyberte síť</span>',
);
expect(page).toContain(
'<span data-show="ios android" hidden>Otevři Tailscale a vyber síť</span>',
'<span data-show="ios android" hidden>Otevřete Tailscale a vyberte síť</span>',
);
expect(page).toContain(
'<code class="net">headscale.example.lazurio.io</code>',
);
// Windows alone: the icon is right-clicked and may hide by the clock.
expect(page).toContain(
'<span data-show="windows" hidden>Na ikonu Tailscale klikni pravým tlačítkem.',
'<span data-show="windows" hidden>Na ikonu Tailscale klikněte pravým tlačítkem.',
);
expect(page).toContain("Nepovedlo se? Pomůže");
// The system is detected and the page retries by itself: no switch between
Expand Down Expand Up @@ -320,7 +320,7 @@ test("the guide page leads back to the Dashboard without the tailnet: the rail's
`<nav class="rail" aria-label="Lazurio"><a class="home" ${href}`,
);
expect(page).toContain(`<a class="back" ${href}>Dashboardu</a>`);
expect(page).toContain("nebo se vrať do");
expect(page).toContain("nebo se vraťte do");
expect(
renderOfflineGuide({
...input,
Expand All @@ -341,6 +341,6 @@ test("the guide page leads back to the Dashboard without the tailnet: the rail's
'<nav class="rail" aria-label="Lazurio"><span class="home">',
);
expect(without).not.toContain('class="back"');
expect(without).not.toContain("nebo se vrať do");
expect(without).not.toContain("nebo se vraťte do");
}
});
Loading