fix: resolve admin issue review findings and record verification

This commit is contained in:
Codex
2026-09-12 18:24:23 +02:00
parent c7e5f295e6
commit 2d1b714ebe
10 changed files with 85 additions and 46 deletions
@@ -0,0 +1,11 @@
/** Horizontal tab lists activate and focus the same item when navigating by keyboard. */
export function nextTabIndex(key: string, current: number, count: number): number | undefined {
if (count === 0) return undefined;
switch (key) {
case "ArrowRight": return (current + 1) % count;
case "ArrowLeft": return (current + count - 1) % count;
case "Home": return 0;
case "End": return count - 1;
default: return undefined;
}
}
-1
View File
@@ -806,7 +806,6 @@ export function AppShell({ canLogout }: AppShellProps) {
<div style={{ display: activeSurface === "database-management" ? "contents" : "none" }}>
<DatabaseManagementPage
key={selectedWorkspaceId}
initialWorkspaceId={selectedWorkspaceId}
canManage={canManageDatabase}
canManageSecrets={canManageWorkspaceSecrets}
onNavigationStateChange={updateDatabaseNavigationState}
@@ -90,14 +90,12 @@ function renderPage({
canManageSecrets = true,
onNavigationStateChange,
presentation = "legacy",
initialWorkspaceId,
}: {
rows?: CatalogDatabase[] | (() => CatalogDatabase[]);
canManage?: boolean;
canManageSecrets?: boolean;
onNavigationStateChange?: (state: { dirty: boolean; busy: boolean }) => void;
presentation?: "legacy" | "fleet";
initialWorkspaceId?: string;
} = {}) {
server.use(http.get("/api/catalog/databases", () => HttpResponse.json(
typeof rows === "function" ? rows() : rows,
@@ -106,7 +104,6 @@ function renderPage({
const view = render(
<QueryClientProvider client={client}>
<DatabaseManagementPage
initialWorkspaceId={initialWorkspaceId}
canManage={canManage}
canManageSecrets={canManageSecrets}
onNavigationStateChange={onNavigationStateChange}
@@ -119,7 +116,7 @@ function renderPage({
}
test("fleet entry opens the database list without workspace preparation or an automatic editor", async () => {
renderPage({ presentation: "fleet", initialWorkspaceId: "psd-clinical" });
renderPage({ presentation: "fleet" });
expect(await screen.findByRole("button", { name: "View tables for Policlinico San Donato" })).toBeVisible();
expect(screen.getByText("Research laboratory")).toBeVisible();
expect(screen.queryByRole("button", { name: "Back to list" })).not.toBeInTheDocument();
@@ -127,6 +124,18 @@ test("fleet entry opens the database list without workspace preparation or an au
expect(screen.queryByRole("link", { name: "Open workspace preprocessing" })).not.toBeInTheDocument();
});
test.each(["tables", "relationships"])("fresh entry ignores a previously persisted %s screen", async kind => {
vi.stubEnv("MODE", "production");
localStorage.setItem("thothii:database-management-screen", JSON.stringify({ kind, workspaceId: "psd-clinical" }));
try {
renderPage({ presentation: "fleet" });
expect(await screen.findByRole("button", { name: "View tables for Policlinico San Donato" })).toBeVisible();
expect(screen.queryByRole("button", { name: "Back to databases" })).not.toBeInTheDocument();
} finally {
vi.unstubAllEnvs();
}
});
function makeSyncRun(
scope: CatalogSyncRun["scope"],
tableIds: string[] = [],
+1 -23
View File
@@ -92,23 +92,7 @@ const SYNC_STARTED_MESSAGES: Record<CatalogSyncScope, string> = {
relationships: "Relationship synchronization started",
all: "Full schema synchronization started",
};
const DATABASE_SCREEN_STORAGE_KEY = "thothii:database-management-screen";
function readPersistedDatabaseScreen(): DatabaseScreen {
if (import.meta.env.MODE === "test") return { kind: "list" };
try {
const parsed = JSON.parse(window.localStorage.getItem(DATABASE_SCREEN_STORAGE_KEY) ?? "null") as { kind?: unknown; workspaceId?: unknown } | null;
if ((parsed?.kind === "tables" || parsed?.kind === "relationships") && typeof parsed.workspaceId === "string") {
return { kind: parsed.kind, workspaceId: parsed.workspaceId };
}
} catch {
// Ignore malformed persisted navigation and return to the safe list view.
}
return { kind: "list" };
}
interface Props {
initialWorkspaceId?: string;
canManage: boolean;
canManageSecrets: boolean;
onNavigationStateChange?: (state: DatabaseNavigationState) => void;
@@ -214,7 +198,7 @@ export function DatabaseManagementPage({
(run) => run.status === "running",
);
const [screen, setScreen] = useState<DatabaseScreen>(readPersistedDatabaseScreen);
const [screen, setScreen] = useState<DatabaseScreen>({ kind: "list" });
const [interactionPreferences, setInteractionPreferences] = useState(() => workspacePreferences.load());
useEffect(() => workspacePreferences.subscribe(setInteractionPreferences), []);
const selectedMetadataModel = interactionPreferences.provider && interactionPreferences.model
@@ -254,12 +238,6 @@ export function DatabaseManagementPage({
suggestions: SensitivityReviewItem[];
} | null>(null);
useEffect(() => {
if (import.meta.env.MODE === "test") return;
const persisted = screen.kind === "tables" || screen.kind === "relationships" ? screen : { kind: "list" };
window.localStorage.setItem(DATABASE_SCREEN_STORAGE_KEY, JSON.stringify(persisted));
}, [screen]);
const originRef = useRef<HTMLElement | null>(null);
const searchInputRef = useRef<HTMLInputElement>(null);
const formHeadingRef = useRef<HTMLHeadingElement>(null);
+4 -11
View File
@@ -9,6 +9,7 @@ import {
} from "../api/pi-management";
import { listModels } from "../api/models";
import { Button } from "../components/ui/button";
import { nextTabIndex } from "../components/ui/tab-navigation";
import { WorkAreaPanel } from "./WorkAreaPanel";
type Feedback = { tone: "success" | "error"; message: string } | undefined;
@@ -214,18 +215,10 @@ function PiPlatformInstructions({ hostPlatform }: { hostPlatform?: PiPlatform })
function handleTabKeyDown(event: React.KeyboardEvent<HTMLButtonElement>, platform: PiPlatform) {
const index = piPlatforms.findIndex((item) => item.id === platform);
const nextPlatform = event.key === "ArrowRight"
? piPlatforms[(index + 1) % piPlatforms.length]
: event.key === "ArrowLeft"
? piPlatforms[(index - 1 + piPlatforms.length) % piPlatforms.length]
: event.key === "Home"
? piPlatforms[0]
: event.key === "End"
? piPlatforms[piPlatforms.length - 1]
: undefined;
if (!nextPlatform) return;
const next = nextTabIndex(event.key, index, piPlatforms.length);
if (next === undefined) return;
event.preventDefault();
activateAndFocus(nextPlatform.id);
activateAndFocus(piPlatforms[next].id);
}
return (
+2 -3
View File
@@ -32,6 +32,7 @@ import {
type AuthOperationGuard,
} from "../auth/authOperation";
import { Button } from "../components/ui/button";
import { nextTabIndex } from "../components/ui/tab-navigation";
import { WorkAreaPanel } from "./WorkAreaPanel";
import { WorkspacePreparation } from "./administration/WorkspacePreparation";
@@ -556,9 +557,7 @@ export function WorkspaceManager({
tabIndex={activeArea === area ? 0 : -1}
onClick={() => setActiveArea(area)}
onKeyDown={event => {
const next = event.key === "ArrowRight" ? (index + 1) % workspaceAreas.length
: event.key === "ArrowLeft" ? (index + workspaceAreas.length - 1) % workspaceAreas.length
: event.key === "Home" ? 0 : event.key === "End" ? workspaceAreas.length - 1 : undefined;
const next = nextTabIndex(event.key, index, workspaceAreas.length);
if (next === undefined) return;
event.preventDefault();
setActiveArea(workspaceAreas[next]);