Public: anyone can read this; the crew can change it.

Palette entries can live beside their screen: cloud, domains and owner move out of src/tui/forge.ts #7737

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

scout/forge:scout/7731-palette-entries-can-live-beside-their-sc → main 1 commit fork

  • Merged. scout/7731-palette-entries-can-live-beside-their-sc was merged into main as f37a756.

Review

Sign in to review this change.
5 files changed +57 −27
src/tui/forge.ts +4 −27
@@ -51,7 +51,6 @@ import { trustedHostsPrompt } from "./screens/trustedhosts.ts";
5151 import { flagsScreen } from "./screens/flags.ts";
5252 import { secretsScreen } from "./screens/secrets.ts";
5353 import { scorecardScreen } from "./screens/scorecard.ts";
54 import { cloudScreen } from "./screens/cloud.ts";
5554 import { crewSplitsScreen } from "./screens/crewsplits.ts";
5655 import { crewHandoverScreen } from "./screens/crewhandover.ts";
5756 import { usageScreen } from "./screens/usage.ts";
@@ -67,8 +66,7 @@ import { signInsScreen } from "./screens/signins.ts";
6766 import { limitsScreen } from "./screens/limits.ts";
6867 import { quotasScreen } from "./screens/quotas.ts";
6968 import { teamsScreen } from "./screens/teams.ts";
70 import { domainsScreen } from "./screens/domains.ts";
71 import { ownerScreen } from "./screens/owner.ts";
69 import { ENTRIES } from "./screens/entries.ts";
7270 import { capacityScreen, mayCapacity } from "./screens/capacity.ts";
7371 import { resilienceScreen } from "./screens/resilience.ts";
7472 import { forgeCeiling } from "../flow/ceiling.ts";
@@ -593,30 +591,9 @@ export function forgeCommands(session: Session): (ctx: Ctx) => Command[] {
593591 hint: "each account's budget and rest; wake one, set its budget, add or remove one",
594592 run: () => ctx.push(subscriptionsScreen(session, ctx)),
595593 });
596 // Cloud accounts, as Settings → Cloud accounts has them: a forge admin (#2199).
597 if (session.user?.isAdmin === true)
598 commands.push({
599 id: "cloud",
600 title: "Cloud accounts",
601 hint: "provider tokens, what they are used for, today's calls",
602 run: () => ctx.push(cloudScreen(session, ctx)),
603 });
604 // Each failure domain and its last drill, as Settings → Backups → Failure domains says it (#1945).
605 if (session.user?.isAdmin === true && session.user.kind !== "agent")
606 commands.push({
607 id: "domains",
608 title: "Failure domains",
609 hint: "failure domains and their last drill",
610 run: () => ctx.push(domainsScreen(session, ctx)),
611 });
612 // What needs the owner: needs, snapshot store, every failure domain (#1236).
613 if (session.user?.isAdmin === true && session.user.kind !== "agent")
614 commands.push({
615 id: "owner",
616 title: "Owner's needs",
617 hint: "what needs the owner, snapshots, failure domains",
618 run: () => ctx.push(ownerScreen(session, ctx)),
619 });
594 // Entries that live beside their screen: cloud, domains, owner.
595 for (const e of ENTRIES)
596 if (e.offered(session)) commands.push({ id: e.id, title: e.title, hint: e.hint, run: () => e.run(session, ctx) });
620597 // The forges this one sent, as /forges lists them: an admin's only.
621598 if (session.user?.isAdmin === true)
622599 commands.push({
src/tui/screens/cloud.ts +10
@@ -18,6 +18,7 @@ import { truncate } from "../term/width.ts";
1818 import type { Session } from "../session.ts";
1919 import { fill, len, split } from "../ui/layout.ts";
2020 import { ListState, drawList, later, promptScreen, type ListRow } from "./common.ts";
21 import type { PaletteEntry } from "./entries.ts";
2122
2223 const day = (at: string | null): string => (at === null ? "never" : at.slice(0, 16).replace("T", " "));
2324
@@ -210,3 +211,12 @@ export function cloudScreen(f: Session, ctx: Ctx): Screen {
210211 };
211212 return screen;
212213 }
214
215 /** Cloud accounts, as Settings → Cloud accounts has them: a forge admin (#2199). */
216 export const entry: PaletteEntry = {
217 id: "cloud",
218 title: "Cloud accounts",
219 hint: "provider tokens, what they are used for, today's calls",
220 offered: (session) => session.user?.isAdmin === true,
221 run: (session, ctx) => ctx.push(cloudScreen(session, ctx)),
222 };
src/tui/screens/domains.ts +10
@@ -14,6 +14,7 @@ import { style } from "../term/style.ts";
1414 import { truncate } from "../term/width.ts";
1515 import type { Session } from "../session.ts";
1616 import { ListState, confirmScreen, drawList, type ListRow } from "./common.ts";
17 import type { PaletteEntry } from "./entries.ts";
1718
1819 function drillLine(d: ResilienceRow): string {
1920 if (d.drill.name === null) return `Not drilled: ${d.drill.why}`;
@@ -127,3 +128,12 @@ export function domainsScreen(f: Session, ctx: Ctx): Screen {
127128 };
128129 return screen;
129130 }
131
132 /** Each failure domain and its last drill, as Settings → Backups → Failure domains says it (#1945). */
133 export const entry: PaletteEntry = {
134 id: "domains",
135 title: "Failure domains",
136 hint: "failure domains and their last drill",
137 offered: (session) => session.user?.isAdmin === true && session.user.kind !== "agent",
138 run: (session, ctx) => ctx.push(domainsScreen(session, ctx)),
139 };
src/tui/screens/entries.ts added +23
@@ -0,0 +1,23 @@
1 /**
2 * Palette entries that live beside their screen. A screen module exports an
3 * `entry`; this list names them in the order the palette offers them, and
4 * `forgeCommands` walks it at one position. Screens are imported here, and
5 * this module by `forge.ts`, never the reverse.
6 */
7
8 import type { Ctx } from "../app/app.ts";
9 import type { Session } from "../session.ts";
10 import { entry as cloud } from "./cloud.ts";
11 import { entry as domains } from "./domains.ts";
12 import { entry as owner } from "./owner.ts";
13
14 export interface PaletteEntry {
15 readonly id: string;
16 readonly title: string;
17 readonly hint: string;
18 /** Whether this session is offered the entry. */
19 offered(session: Session): boolean;
20 run(session: Session, ctx: Ctx): void;
21 }
22
23 export const ENTRIES: readonly PaletteEntry[] = [cloud, domains, owner];
src/tui/screens/owner.ts +10
@@ -13,6 +13,7 @@ import { style } from "../term/style.ts";
1313 import { truncate } from "../term/width.ts";
1414 import type { Session } from "../session.ts";
1515 import { ListState, drawList, type ListRow } from "./common.ts";
16 import type { PaletteEntry } from "./entries.ts";
1617
1718 export function ownerRows(v: OwnerView): ListRow[] {
1819 const needs: ListRow[] =
@@ -68,3 +69,12 @@ export function ownerScreen(f: Session, ctx: Ctx): Screen {
6869 };
6970 return screen;
7071 }
72
73 /** What needs the owner: needs, snapshot store, every failure domain (#1236). */
74 export const entry: PaletteEntry = {
75 id: "owner",
76 title: "Owner's needs",
77 hint: "what needs the owner, snapshots, failure domains",
78 offered: (session) => session.user?.isAdmin === true && session.user.kind !== "agent",
79 run: (session, ctx) => ctx.push(ownerScreen(session, ctx)),
80 };

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs