feat(frontend): add blank Global Settings page (#2218)
* feat(frontend): add blank Global Settings page Add a Global Settings page to the desktop renderer, reachable from the sidebar Settings menu when no project is selected. The project-scoped Settings entry stays when a project is active; otherwise the menu shows Global settings, which opens the new /settings route. The page body is intentionally empty for now and will be filled in incrementally. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(frontend): regenerate route tree + test Global Settings menu Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
bc84b6d2a3
commit
14030772b9
|
|
@ -0,0 +1,12 @@
|
|||
import { DashboardSubhead } from "./DashboardSubhead";
|
||||
|
||||
// App-wide settings, shown from the sidebar when no project is selected. The
|
||||
// body is intentionally empty for now; it will be filled in incrementally.
|
||||
export function GlobalSettingsForm() {
|
||||
return (
|
||||
<div className="flex h-full min-h-0 flex-col bg-background text-foreground">
|
||||
<DashboardSubhead title="Global settings" subtitle="Settings that apply across all projects" />
|
||||
<div className="min-h-0 flex-1 overflow-y-auto p-[18px]" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -135,6 +135,16 @@ describe("Sidebar", () => {
|
|||
);
|
||||
});
|
||||
|
||||
it("opens global settings from the footer menu when no project is selected", async () => {
|
||||
const user = userEvent.setup();
|
||||
renderSidebar();
|
||||
|
||||
await user.click(screen.getAllByLabelText("Settings")[0]);
|
||||
await user.click(await screen.findByRole("menuitem", { name: "Global settings" }));
|
||||
|
||||
expect(navigateMock).toHaveBeenCalledWith({ to: "/settings" });
|
||||
});
|
||||
|
||||
it("always shows action icons and reserves padding for them", () => {
|
||||
renderSidebar();
|
||||
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ function useSelection() {
|
|||
activeSessionId: params.sessionId,
|
||||
goHome: () => void navigate({ to: "/" }),
|
||||
goPrs: () => void navigate({ to: "/prs" }),
|
||||
goGlobalSettings: () => void navigate({ to: "/settings" }),
|
||||
goSettings: (projectId: string) => void navigate({ to: "/projects/$projectId/settings", params: { projectId } }),
|
||||
goProject: (projectId: string) => void navigate({ to: "/projects/$projectId", params: { projectId } }),
|
||||
goSession: (projectId: string, sessionId: string) =>
|
||||
|
|
@ -284,14 +285,17 @@ export function Sidebar({
|
|||
Search
|
||||
<DropdownMenuShortcut>⌘K</DropdownMenuShortcut>
|
||||
</DropdownMenuItem>
|
||||
{selection.activeProjectId && (
|
||||
<>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem onSelect={() => selection.goSettings(selection.activeProjectId!)}>
|
||||
<Settings aria-hidden="true" />
|
||||
Project settings
|
||||
</DropdownMenuItem>
|
||||
</>
|
||||
<DropdownMenuSeparator />
|
||||
{selection.activeProjectId ? (
|
||||
<DropdownMenuItem onSelect={() => selection.goSettings(selection.activeProjectId!)}>
|
||||
<Settings aria-hidden="true" />
|
||||
Project settings
|
||||
</DropdownMenuItem>
|
||||
) : (
|
||||
<DropdownMenuItem onSelect={selection.goGlobalSettings}>
|
||||
<Settings aria-hidden="true" />
|
||||
Global settings
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
|
|
@ -342,14 +346,17 @@ export function Sidebar({
|
|||
Search
|
||||
<DropdownMenuShortcut>⌘K</DropdownMenuShortcut>
|
||||
</DropdownMenuItem>
|
||||
{selection.activeProjectId && (
|
||||
<>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem onSelect={() => selection.goSettings(selection.activeProjectId!)}>
|
||||
<Settings aria-hidden="true" />
|
||||
Project settings
|
||||
</DropdownMenuItem>
|
||||
</>
|
||||
<DropdownMenuSeparator />
|
||||
{selection.activeProjectId ? (
|
||||
<DropdownMenuItem onSelect={() => selection.goSettings(selection.activeProjectId!)}>
|
||||
<Settings aria-hidden="true" />
|
||||
Project settings
|
||||
</DropdownMenuItem>
|
||||
) : (
|
||||
<DropdownMenuItem onSelect={selection.goGlobalSettings}>
|
||||
<Settings aria-hidden="true" />
|
||||
Global settings
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
import { Route as rootRouteImport } from "./routes/__root";
|
||||
import { Route as ShellRouteImport } from "./routes/_shell";
|
||||
import { Route as ShellIndexRouteImport } from "./routes/_shell.index";
|
||||
import { Route as ShellSettingsRouteImport } from "./routes/_shell.settings";
|
||||
import { Route as ShellPrsRouteImport } from "./routes/_shell.prs";
|
||||
import { Route as ShellSessionsSessionIdRouteImport } from "./routes/_shell.sessions.$sessionId";
|
||||
import { Route as ShellProjectsProjectIdRouteImport } from "./routes/_shell.projects.$projectId";
|
||||
|
|
@ -26,6 +27,11 @@ const ShellIndexRoute = ShellIndexRouteImport.update({
|
|||
path: "/",
|
||||
getParentRoute: () => ShellRoute,
|
||||
} as any);
|
||||
const ShellSettingsRoute = ShellSettingsRouteImport.update({
|
||||
id: "/settings",
|
||||
path: "/settings",
|
||||
getParentRoute: () => ShellRoute,
|
||||
} as any);
|
||||
const ShellPrsRoute = ShellPrsRouteImport.update({
|
||||
id: "/prs",
|
||||
path: "/prs",
|
||||
|
|
@ -55,6 +61,7 @@ const ShellProjectsProjectIdSessionsSessionIdRoute = ShellProjectsProjectIdSessi
|
|||
export interface FileRoutesByFullPath {
|
||||
"/": typeof ShellIndexRoute;
|
||||
"/prs": typeof ShellPrsRoute;
|
||||
"/settings": typeof ShellSettingsRoute;
|
||||
"/projects/$projectId": typeof ShellProjectsProjectIdRoute;
|
||||
"/sessions/$sessionId": typeof ShellSessionsSessionIdRoute;
|
||||
"/projects/$projectId/settings": typeof ShellProjectsProjectIdSettingsRoute;
|
||||
|
|
@ -62,6 +69,7 @@ export interface FileRoutesByFullPath {
|
|||
}
|
||||
export interface FileRoutesByTo {
|
||||
"/prs": typeof ShellPrsRoute;
|
||||
"/settings": typeof ShellSettingsRoute;
|
||||
"/": typeof ShellIndexRoute;
|
||||
"/projects/$projectId": typeof ShellProjectsProjectIdRoute;
|
||||
"/sessions/$sessionId": typeof ShellSessionsSessionIdRoute;
|
||||
|
|
@ -72,6 +80,7 @@ export interface FileRoutesById {
|
|||
__root__: typeof rootRouteImport;
|
||||
"/_shell": typeof ShellRouteWithChildren;
|
||||
"/_shell/prs": typeof ShellPrsRoute;
|
||||
"/_shell/settings": typeof ShellSettingsRoute;
|
||||
"/_shell/": typeof ShellIndexRoute;
|
||||
"/_shell/projects/$projectId": typeof ShellProjectsProjectIdRoute;
|
||||
"/_shell/sessions/$sessionId": typeof ShellSessionsSessionIdRoute;
|
||||
|
|
@ -83,6 +92,7 @@ export interface FileRouteTypes {
|
|||
fullPaths:
|
||||
| "/"
|
||||
| "/prs"
|
||||
| "/settings"
|
||||
| "/projects/$projectId"
|
||||
| "/sessions/$sessionId"
|
||||
| "/projects/$projectId/settings"
|
||||
|
|
@ -90,6 +100,7 @@ export interface FileRouteTypes {
|
|||
fileRoutesByTo: FileRoutesByTo;
|
||||
to:
|
||||
| "/prs"
|
||||
| "/settings"
|
||||
| "/"
|
||||
| "/projects/$projectId"
|
||||
| "/sessions/$sessionId"
|
||||
|
|
@ -99,6 +110,7 @@ export interface FileRouteTypes {
|
|||
| "__root__"
|
||||
| "/_shell"
|
||||
| "/_shell/prs"
|
||||
| "/_shell/settings"
|
||||
| "/_shell/"
|
||||
| "/_shell/projects/$projectId"
|
||||
| "/_shell/sessions/$sessionId"
|
||||
|
|
@ -126,6 +138,13 @@ declare module "@tanstack/react-router" {
|
|||
preLoaderRoute: typeof ShellIndexRouteImport;
|
||||
parentRoute: typeof ShellRoute;
|
||||
};
|
||||
"/_shell/settings": {
|
||||
id: "/_shell/settings";
|
||||
path: "/settings";
|
||||
fullPath: "/settings";
|
||||
preLoaderRoute: typeof ShellSettingsRouteImport;
|
||||
parentRoute: typeof ShellRoute;
|
||||
};
|
||||
"/_shell/prs": {
|
||||
id: "/_shell/prs";
|
||||
path: "/prs";
|
||||
|
|
@ -166,6 +185,7 @@ declare module "@tanstack/react-router" {
|
|||
|
||||
interface ShellRouteChildren {
|
||||
ShellPrsRoute: typeof ShellPrsRoute;
|
||||
ShellSettingsRoute: typeof ShellSettingsRoute;
|
||||
ShellIndexRoute: typeof ShellIndexRoute;
|
||||
ShellProjectsProjectIdRoute: typeof ShellProjectsProjectIdRoute;
|
||||
ShellSessionsSessionIdRoute: typeof ShellSessionsSessionIdRoute;
|
||||
|
|
@ -175,6 +195,7 @@ interface ShellRouteChildren {
|
|||
|
||||
const ShellRouteChildren: ShellRouteChildren = {
|
||||
ShellPrsRoute: ShellPrsRoute,
|
||||
ShellSettingsRoute: ShellSettingsRoute,
|
||||
ShellIndexRoute: ShellIndexRoute,
|
||||
ShellProjectsProjectIdRoute: ShellProjectsProjectIdRoute,
|
||||
ShellSessionsSessionIdRoute: ShellSessionsSessionIdRoute,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
import { createFileRoute } from "@tanstack/react-router";
|
||||
import { GlobalSettingsForm } from "../components/GlobalSettingsForm";
|
||||
|
||||
export const Route = createFileRoute("/_shell/settings")({
|
||||
component: GlobalSettingsForm,
|
||||
});
|
||||
Loading…
Reference in New Issue