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
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,11 @@ export function DashboardMobileNav({
Profile
<DropdownMenuShortcut keys={["G", "P"]} />
</DropdownMenuItem>
<DropdownMenuItem>
Settings
<DropdownMenuShortcut keys={["G", "S"]} />
<DropdownMenuItem asChild>
<Link to="/settings">
Settings
<DropdownMenuShortcut keys={["G", "S"]} />
</Link>
</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator />
Expand Down
8 changes: 5 additions & 3 deletions apps/dashboard/src/components/layouts/dashboard-topbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -230,9 +230,11 @@ export function DashboardTopbar({
Profile
<DropdownMenuShortcut keys={["G", "P"]} />
</DropdownMenuItem>
<DropdownMenuItem>
Settings
<DropdownMenuShortcut keys={["G", "S"]} />
<DropdownMenuItem asChild>
<Link to="/settings">
Settings
<DropdownMenuShortcut keys={["G", "S"]} />
</Link>
</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator />
Expand Down
10 changes: 10 additions & 0 deletions apps/dashboard/src/lib/command-palette/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
GitPullRequestIcon,
IssuesIcon,
ReviewsIcon,
SettingsIcon,
} from "@diffkit/icons";
import type { CommandItem } from "./types";

Expand Down Expand Up @@ -71,4 +72,13 @@ registerCommands([
shortcut: ["G", "R"],
action: { type: "navigate", to: "/reviews" },
},
{
id: "nav:settings",
label: "Go to Settings",
group: "Pages",
icon: SettingsIcon,
keywords: ["settings", "preferences", "config"],
shortcut: ["G", "S"],
action: { type: "navigate", to: "/settings" },
},
]);
71 changes: 71 additions & 0 deletions apps/dashboard/src/routeTree.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@ import { Route as RobotsDottxtRouteImport } from './routes/robots[.]txt'
import { Route as LoginRouteImport } from './routes/login'
import { Route as ProtectedRouteImport } from './routes/_protected'
import { Route as ProtectedIndexRouteImport } from './routes/_protected/index'
import { Route as ProtectedSettingsRouteImport } from './routes/_protected/settings'
import { Route as ProtectedReviewsRouteImport } from './routes/_protected/reviews'
import { Route as ProtectedPullsRouteImport } from './routes/_protected/pulls'
import { Route as ProtectedIssuesRouteImport } from './routes/_protected/issues'
import { Route as ProtectedSettingsIndexRouteImport } from './routes/_protected/settings/index'
import { Route as ApiWebhooksGithubRouteImport } from './routes/api/webhooks/github'
import { Route as ApiAuthSplatRouteImport } from './routes/api/auth/$'
import { Route as ProtectedSettingsShortcutsRouteImport } from './routes/_protected/settings/shortcuts'
import { Route as ApiGithubAppCallbackRouteImport } from './routes/api/github/app/callback'
import { Route as ApiGithubAppAuthorizeRouteImport } from './routes/api/github/app/authorize'
import { Route as ProtectedOwnerRepoReviewPullIdRouteImport } from './routes/_protected/$owner/$repo/review.$pullId'
Expand Down Expand Up @@ -55,6 +58,11 @@ const ProtectedIndexRoute = ProtectedIndexRouteImport.update({
path: '/',
getParentRoute: () => ProtectedRoute,
} as any)
const ProtectedSettingsRoute = ProtectedSettingsRouteImport.update({
id: '/settings',
path: '/settings',
getParentRoute: () => ProtectedRoute,
} as any)
const ProtectedReviewsRoute = ProtectedReviewsRouteImport.update({
id: '/reviews',
path: '/reviews',
Expand All @@ -70,6 +78,11 @@ const ProtectedIssuesRoute = ProtectedIssuesRouteImport.update({
path: '/issues',
getParentRoute: () => ProtectedRoute,
} as any)
const ProtectedSettingsIndexRoute = ProtectedSettingsIndexRouteImport.update({
id: '/',
path: '/',
getParentRoute: () => ProtectedSettingsRoute,
} as any)
const ApiWebhooksGithubRoute = ApiWebhooksGithubRouteImport.update({
id: '/api/webhooks/github',
path: '/api/webhooks/github',
Expand All @@ -80,6 +93,12 @@ const ApiAuthSplatRoute = ApiAuthSplatRouteImport.update({
path: '/api/auth/$',
getParentRoute: () => rootRouteImport,
} as any)
const ProtectedSettingsShortcutsRoute =
ProtectedSettingsShortcutsRouteImport.update({
id: '/shortcuts',
path: '/shortcuts',
getParentRoute: () => ProtectedSettingsRoute,
} as any)
const ApiGithubAppCallbackRoute = ApiGithubAppCallbackRouteImport.update({
id: '/api/github/app/callback',
path: '/api/github/app/callback',
Expand Down Expand Up @@ -118,8 +137,11 @@ export interface FileRoutesByFullPath {
'/issues': typeof ProtectedIssuesRoute
'/pulls': typeof ProtectedPullsRoute
'/reviews': typeof ProtectedReviewsRoute
'/settings': typeof ProtectedSettingsRouteWithChildren
'/settings/shortcuts': typeof ProtectedSettingsShortcutsRoute
'/api/auth/$': typeof ApiAuthSplatRoute
'/api/webhooks/github': typeof ApiWebhooksGithubRoute
'/settings/': typeof ProtectedSettingsIndexRoute
'/api/github/app/authorize': typeof ApiGithubAppAuthorizeRoute
'/api/github/app/callback': typeof ApiGithubAppCallbackRoute
'/$owner/$repo/issues/$issueId': typeof ProtectedOwnerRepoIssuesIssueIdRoute
Expand All @@ -135,8 +157,10 @@ export interface FileRoutesByTo {
'/pulls': typeof ProtectedPullsRoute
'/reviews': typeof ProtectedReviewsRoute
'/': typeof ProtectedIndexRoute
'/settings/shortcuts': typeof ProtectedSettingsShortcutsRoute
'/api/auth/$': typeof ApiAuthSplatRoute
'/api/webhooks/github': typeof ApiWebhooksGithubRoute
'/settings': typeof ProtectedSettingsIndexRoute
'/api/github/app/authorize': typeof ApiGithubAppAuthorizeRoute
'/api/github/app/callback': typeof ApiGithubAppCallbackRoute
'/$owner/$repo/issues/$issueId': typeof ProtectedOwnerRepoIssuesIssueIdRoute
Expand All @@ -153,9 +177,12 @@ export interface FileRoutesById {
'/_protected/issues': typeof ProtectedIssuesRoute
'/_protected/pulls': typeof ProtectedPullsRoute
'/_protected/reviews': typeof ProtectedReviewsRoute
'/_protected/settings': typeof ProtectedSettingsRouteWithChildren
'/_protected/': typeof ProtectedIndexRoute
'/_protected/settings/shortcuts': typeof ProtectedSettingsShortcutsRoute
'/api/auth/$': typeof ApiAuthSplatRoute
'/api/webhooks/github': typeof ApiWebhooksGithubRoute
'/_protected/settings/': typeof ProtectedSettingsIndexRoute
'/api/github/app/authorize': typeof ApiGithubAppAuthorizeRoute
'/api/github/app/callback': typeof ApiGithubAppCallbackRoute
'/_protected/$owner/$repo/issues/$issueId': typeof ProtectedOwnerRepoIssuesIssueIdRoute
Expand All @@ -173,8 +200,11 @@ export interface FileRouteTypes {
| '/issues'
| '/pulls'
| '/reviews'
| '/settings'
| '/settings/shortcuts'
| '/api/auth/$'
| '/api/webhooks/github'
| '/settings/'
| '/api/github/app/authorize'
| '/api/github/app/callback'
| '/$owner/$repo/issues/$issueId'
Expand All @@ -190,8 +220,10 @@ export interface FileRouteTypes {
| '/pulls'
| '/reviews'
| '/'
| '/settings/shortcuts'
| '/api/auth/$'
| '/api/webhooks/github'
| '/settings'
| '/api/github/app/authorize'
| '/api/github/app/callback'
| '/$owner/$repo/issues/$issueId'
Expand All @@ -207,9 +239,12 @@ export interface FileRouteTypes {
| '/_protected/issues'
| '/_protected/pulls'
| '/_protected/reviews'
| '/_protected/settings'
| '/_protected/'
| '/_protected/settings/shortcuts'
| '/api/auth/$'
| '/api/webhooks/github'
| '/_protected/settings/'
| '/api/github/app/authorize'
| '/api/github/app/callback'
| '/_protected/$owner/$repo/issues/$issueId'
Expand Down Expand Up @@ -273,6 +308,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof ProtectedIndexRouteImport
parentRoute: typeof ProtectedRoute
}
'/_protected/settings': {
id: '/_protected/settings'
path: '/settings'
fullPath: '/settings'
preLoaderRoute: typeof ProtectedSettingsRouteImport
parentRoute: typeof ProtectedRoute
}
'/_protected/reviews': {
id: '/_protected/reviews'
path: '/reviews'
Expand All @@ -294,6 +336,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof ProtectedIssuesRouteImport
parentRoute: typeof ProtectedRoute
}
'/_protected/settings/': {
id: '/_protected/settings/'
path: '/'
fullPath: '/settings/'
preLoaderRoute: typeof ProtectedSettingsIndexRouteImport
parentRoute: typeof ProtectedSettingsRoute
}
'/api/webhooks/github': {
id: '/api/webhooks/github'
path: '/api/webhooks/github'
Expand All @@ -308,6 +357,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof ApiAuthSplatRouteImport
parentRoute: typeof rootRouteImport
}
'/_protected/settings/shortcuts': {
id: '/_protected/settings/shortcuts'
path: '/shortcuts'
fullPath: '/settings/shortcuts'
preLoaderRoute: typeof ProtectedSettingsShortcutsRouteImport
parentRoute: typeof ProtectedSettingsRoute
}
'/api/github/app/callback': {
id: '/api/github/app/callback'
path: '/api/github/app/callback'
Expand Down Expand Up @@ -346,10 +402,24 @@ declare module '@tanstack/react-router' {
}
}

interface ProtectedSettingsRouteChildren {
ProtectedSettingsShortcutsRoute: typeof ProtectedSettingsShortcutsRoute
ProtectedSettingsIndexRoute: typeof ProtectedSettingsIndexRoute
}

const ProtectedSettingsRouteChildren: ProtectedSettingsRouteChildren = {
ProtectedSettingsShortcutsRoute: ProtectedSettingsShortcutsRoute,
ProtectedSettingsIndexRoute: ProtectedSettingsIndexRoute,
}

const ProtectedSettingsRouteWithChildren =
ProtectedSettingsRoute._addFileChildren(ProtectedSettingsRouteChildren)

interface ProtectedRouteChildren {
ProtectedIssuesRoute: typeof ProtectedIssuesRoute
ProtectedPullsRoute: typeof ProtectedPullsRoute
ProtectedReviewsRoute: typeof ProtectedReviewsRoute
ProtectedSettingsRoute: typeof ProtectedSettingsRouteWithChildren
ProtectedIndexRoute: typeof ProtectedIndexRoute
ProtectedOwnerRepoIssuesIssueIdRoute: typeof ProtectedOwnerRepoIssuesIssueIdRoute
ProtectedOwnerRepoPullPullIdRoute: typeof ProtectedOwnerRepoPullPullIdRoute
Expand All @@ -360,6 +430,7 @@ const ProtectedRouteChildren: ProtectedRouteChildren = {
ProtectedIssuesRoute: ProtectedIssuesRoute,
ProtectedPullsRoute: ProtectedPullsRoute,
ProtectedReviewsRoute: ProtectedReviewsRoute,
ProtectedSettingsRoute: ProtectedSettingsRouteWithChildren,
ProtectedIndexRoute: ProtectedIndexRoute,
ProtectedOwnerRepoIssuesIssueIdRoute: ProtectedOwnerRepoIssuesIssueIdRoute,
ProtectedOwnerRepoPullPullIdRoute: ProtectedOwnerRepoPullPullIdRoute,
Expand Down
77 changes: 77 additions & 0 deletions apps/dashboard/src/routes/_protected/settings.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { ChevronRightIcon } from "@diffkit/icons";
import { cn } from "@diffkit/ui/lib/utils";
import {
createFileRoute,
Link,
Outlet,
useMatches,
} from "@tanstack/react-router";
import { buildSeo, formatPageTitle, PRIVATE_ROUTE_HEADERS } from "#/lib/seo";

const settingsNav = [
{ to: "/settings", label: "General" },
{ to: "/settings/shortcuts", label: "Shortcuts" },
] as const;

export const Route = createFileRoute("/_protected/settings")({
headers: () => PRIVATE_ROUTE_HEADERS,
head: ({ match }) =>
buildSeo({
path: match.pathname,
title: formatPageTitle("Settings"),
description: "Configure your DiffKit preferences.",
robots: "noindex",
}),
component: SettingsLayout,
});

function SettingsLayout() {
const matches = useMatches();
const currentPath = matches[matches.length - 1]?.pathname ?? "/settings";

return (
<div className="h-full overflow-auto py-10">
<div className="mx-auto grid max-w-3xl gap-10 px-3 md:px-6 lg:grid-cols-[12rem_minmax(0,1fr)]">
<aside className="flex h-fit flex-col gap-5 lg:sticky lg:top-0">
<h1 className="text-lg font-semibold tracking-tight">Settings</h1>
<nav className="-mx-3 flex flex-col gap-0.5" aria-label="Settings">
{settingsNav.map((item) => {
const normalizedPath =
currentPath.replace(/\/+$/, "") || "/settings";
const isActive =
normalizedPath === item.to ||
(item.to !== "/settings" && normalizedPath.startsWith(item.to));
return (
<Link
key={item.to}
to={item.to}
activeOptions={{ exact: item.to === "/settings" }}
className={cn(
"flex items-center justify-between rounded-lg px-3 py-2 text-sm transition-colors",
isActive
? "bg-surface-1 font-medium text-foreground"
: "text-muted-foreground hover:bg-surface-1 hover:text-foreground",
)}
>
{item.label}
<ChevronRightIcon
size={14}
strokeWidth={2}
className={cn(
"transition-opacity",
isActive ? "opacity-100" : "opacity-0",
)}
/>
</Link>
);
})}
</nav>
</aside>

<div className="flex flex-col gap-8">
<Outlet />
</div>
</div>
</div>
);
}
Loading
Loading