-
{t("nav.leitstand")}
+
{t("nav.leitstand")}
{/* An unread or unreadable board must not claim "no agents". */}
{board.loading ? null : board.error !== null && board.cards.length === 0
?
diff --git a/src/screens/leitstand/flow/FlowTab.tsx b/src/screens/leitstand/flow/FlowTab.tsx
index 4b692c9f..ffb08b93 100644
--- a/src/screens/leitstand/flow/FlowTab.tsx
+++ b/src/screens/leitstand/flow/FlowTab.tsx
@@ -65,7 +65,7 @@ function FlowNodeBody({ label, lamp, quota, proof }: { label: FlowLabel; lamp?:
);
}
-/** The Fluss tab: the flow graph of the board's agents, one lamp, one quota reading and the proof strip on every node. */
+/** The Fabrik tab: the flow graph of the board's agents, one lamp, one quota reading and the proof strip on every node. */
export function FlowTab({ cards }: { cards: readonly BoardCard[] }) {
const [reads, setReads] = useState
({ profiles: null, quotas: null, budgets: null });
useEffect(() => {
diff --git a/src/shell/mount/ShellMount.tsx b/src/shell/mount/ShellMount.tsx
index b40d1195..abc2c87f 100644
--- a/src/shell/mount/ShellMount.tsx
+++ b/src/shell/mount/ShellMount.tsx
@@ -8,7 +8,7 @@ import StartRoute from "../../screens/start/StartRoute";
import TerminalRoute from "../../screens/terminal/TerminalRoute";
import LeitstandRoute, { CLASSIC_PATH, LeitstandTabs } from "../../screens/leitstand/LeitstandRoute";
import { EinstellungenScreen } from "../../screens/einstellungen/EinstellungenScreen";
-import { SETTINGS_CLASSIC_PATH, hasLegacyPanel, hashForGoal, isNewEinstellungen, isNewLeitstand, isNewSteuerung, isStart, isTerminal } from "./routing";
+import { FABRIK_PATH, SETTINGS_CLASSIC_PATH, hasLegacyPanel, hashForGoal, isNewEinstellungen, isNewLeitstand, isNewSteuerung, isStart, isTerminal } from "./routing";
import SteuerungRoute from "./SteuerungRoute";
import "./mount.css";
@@ -40,7 +40,15 @@ export default function ShellMount({ children }: { children: (props: LegacyRoute
return () => watch.disconnect();
}, []);
useEffect(() => {
- const onHash = () => setPath(pathFromHash(window.location.hash));
+ const onHash = () => {
+ const next = pathFromHash(window.location.hash);
+ if (next === "/leitstand/fluss") {
+ // Replace the bookmark so Back does not revisit the retired tab URL.
+ window.location.replace(`#${FABRIK_PATH}`);
+ setPath(FABRIK_PATH);
+ } else setPath(next);
+ };
+ onHash();
window.addEventListener("hashchange", onHash);
return () => window.removeEventListener("hashchange", onHash);
}, []);
diff --git a/src/shell/mount/routing.test.ts b/src/shell/mount/routing.test.ts
index 02e0cab1..caec3596 100644
--- a/src/shell/mount/routing.test.ts
+++ b/src/shell/mount/routing.test.ts
@@ -24,6 +24,15 @@ describe("goal and route mapping (ia.md section 4)", () => {
}
});
+ it("keeps Fabrik and the old flow alias out of the legacy terminal viewer", () => {
+ for (const path of ["/leitstand/fabrik", "/leitstand/fabrik/", "/leitstand/fluss", "/leitstand/fluss/"]) {
+ expect(isNewLeitstand(path)).toBe(true);
+ expect(shouldMountLegacyTerminal(path)).toBe(false);
+ }
+ expect(isNewLeitstand("/leitstand/fabrik/unknown")).toBe(false);
+ expect(isNewLeitstand("/leitstand/fluss/unknown")).toBe(false);
+ });
+
it("keeps the legacy goal when entering the terminal route", () => {
for (const path of ["/leitstand/terminal", "/leitstand/terminal/"]) {
expect(goalForPath(path, "review")).toBe("review");
diff --git a/src/shell/mount/routing.ts b/src/shell/mount/routing.ts
index 21052193..73f72a37 100644
--- a/src/shell/mount/routing.ts
+++ b/src/shell/mount/routing.ts
@@ -15,13 +15,15 @@ const base = (path: string) => `/${path.split("/")[1] ?? ""}`;
export const trim = (path: string) => path.replace(/\/+$/, "");
+export const FABRIK_PATH = "/leitstand/fabrik";
+
export const TOOLS_PATH = "/leitstand/werkzeuge";
export const isTools = (path: string) => trim(path) === TOOLS_PATH;
export const isTerminal = (path: string) => trim(path.split("?")[0]) === "/leitstand/terminal";
-/** The new Leitstand owns `/leitstand` (V2-S01a), `/leitstand/betrieb` (V2-S01b) and `/leitstand/fluss` (COMP-3-3); the rest below it stays the old view. */
-export const isNewLeitstand = (path: string) => ["/leitstand", "/leitstand/betrieb", "/leitstand/fluss"].includes(trim(path));
+/** The new Leitstand owns `/leitstand` (V2-S01a), `/leitstand/betrieb` (V2-S01b) and `/leitstand/fabrik` with its old `/leitstand/fluss` alias; the rest below it stays the old view. */
+export const isNewLeitstand = (path: string) => ["/leitstand", "/leitstand/betrieb", FABRIK_PATH, "/leitstand/fluss"].includes(trim(path));
/** The new Steuerung (V2-S05a) owns `/steuerung` and its tabs: Kontingente plus two honest placeholders. */
export const isNewSteuerung = (path: string) => base(trim(path)) === "/steuerung";