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
104 changes: 82 additions & 22 deletions apps/dokploy/hooks/use-keyboard-nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,34 @@
import { usePathname, useRouter, useSearchParams } from "next/navigation";
import { useCallback, useEffect, useState } from "react";

const SHORTCUTS = {
const PAGES = [
"compose",
"application",
"postgres",
"redis",
"mysql",
"mariadb",
"mongodb",
] as const;
type Page = (typeof PAGES)[number];

type Shortcuts = Record<string, string>;
type ShortcutsDictionary = Record<Page, Shortcuts>;

const COMPOSE_SHORTCUTS: Shortcuts = {
g: "general",
e: "environment",
u: "domains",
d: "deployments",
b: "backups",
s: "schedules",
v: "volumeBackups",
l: "logs",
m: "monitoring",
a: "advanced",
};

const APPLICATION_SHORTCUTS: Shortcuts = {
g: "general",
e: "environment",
u: "domains",
Expand All @@ -16,29 +43,52 @@ const SHORTCUTS = {
a: "advanced",
};

const POSTGRES_SHORTCUTS: Shortcuts = {
g: "general",
e: "environment",
l: "logs",
m: "monitoring",
b: "backups",
a: "advanced",
};

const REDIS_SHORTCUTS: Shortcuts = {
g: "general",
e: "environment",
l: "logs",
m: "monitoring",
a: "advanced",
};

const SHORTCUTS: ShortcutsDictionary = {
application: APPLICATION_SHORTCUTS,
compose: COMPOSE_SHORTCUTS,
postgres: POSTGRES_SHORTCUTS,
redis: REDIS_SHORTCUTS,
mysql: POSTGRES_SHORTCUTS,
mariadb: POSTGRES_SHORTCUTS,
mongodb: POSTGRES_SHORTCUTS,
};

/**
* Use this to register keyboard shortcuts for the application page. Each
* shortcut must be prefixed with `g` (like GitHub).
* Use this to register keyboard shortcuts for different pages. Each shortcut
* must be prefixed with `g` (like GitHub).
*
* @example
* - `g g` "General",
* - `g e` "Environment",
* - `g u` "Domains",
* - `g p` "Preview Deployments",
* - `g s` "Schedules",
* - `g v` "Volume Backups",
* - `g d` "Deployments",
* - `g l` "Logs",
* - `g m` "Monitoring",
* - `g a` "Advanced"
*/
export function UseKeyboardNavForApplications() {
export function UseKeyboardNav({ forPage }: { forPage: Page }) {
const [isModPressed, setModPressed] = useState(false);
const [timer, setTimer] = useState<NodeJS.Timeout | null>(null);

const sp = useSearchParams();
const router = useRouter();
const pathname = usePathname();

const shortcuts = SHORTCUTS[forPage];

const updateSearchParam = useCallback(
(name: string, value: string) => {
const params = new URLSearchParams(sp.toString());
Expand All @@ -50,22 +100,32 @@ export function UseKeyboardNavForApplications() {
);

useEffect(() => {
const handleKeyDown = ({ key }: KeyboardEvent) => {
const handleKeyDown = ({ key, target }: KeyboardEvent) => {
const active = target as HTMLElement | null;

if (active) {
const tag = active.tagName;
if (
active.isContentEditable ||
tag === "INPUT" ||
tag === "TEXTAREA" ||
tag === "SELECT" ||
active.getAttribute("role") === "textbox"
)
return;
}

if (isModPressed) {
if (timer) clearTimeout(timer);
setModPressed(false);

if (key in SHORTCUTS) {
const tab = SHORTCUTS[key as keyof typeof SHORTCUTS];
router.push(
`${pathname}?${updateSearchParam("tab", tab.toLowerCase())}`,
);
}
} else {
if (key === "g") {
setModPressed(true);
setTimer(setTimeout(() => setModPressed(false), 5000));
if (key in shortcuts) {
const tab = shortcuts[key]!;
router.push(`${pathname}?${updateSearchParam("tab", tab)}`);
}
} else if (key === "g") {
setModPressed(true);
setTimer(setTimeout(() => setModPressed(false), 1500));
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ import {
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { UseKeyboardNavForApplications } from "@/hooks/use-keyboard-nav";
import { UseKeyboardNav } from "@/hooks/use-keyboard-nav";
import { appRouter } from "@/server/api/root";
import { api } from "@/utils/api";

Expand Down Expand Up @@ -92,7 +92,7 @@ const Service = (

return (
<div className="pb-10">
<UseKeyboardNavForApplications />
<UseKeyboardNav forPage="application" />
<BreadcrumbSidebar
list={[
{ name: "Projects", href: "/dashboard/projects" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import {
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { UseKeyboardNav } from "@/hooks/use-keyboard-nav";
import { appRouter } from "@/server/api/root";
import { api } from "@/utils/api";

Expand Down Expand Up @@ -82,6 +83,7 @@ const Service = (

return (
<div className="pb-10">
<UseKeyboardNav forPage="compose" />
<BreadcrumbSidebar
list={[
{ name: "Projects", href: "/dashboard/projects" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { UseKeyboardNav } from "@/hooks/use-keyboard-nav";
import { cn } from "@/lib/utils";
import { appRouter } from "@/server/api/root";
import { api } from "@/utils/api";
Expand Down Expand Up @@ -63,6 +64,7 @@ const Mariadb = (

return (
<div className="pb-10">
<UseKeyboardNav forPage="mariadb" />
<BreadcrumbSidebar
list={[
{ name: "Projects", href: "/dashboard/projects" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { UseKeyboardNav } from "@/hooks/use-keyboard-nav";
import { cn } from "@/lib/utils";
import { appRouter } from "@/server/api/root";
import { api } from "@/utils/api";
Expand Down Expand Up @@ -63,6 +64,7 @@ const Mongo = (

return (
<div className="pb-10">
<UseKeyboardNav forPage="mongodb" />
<BreadcrumbSidebar
list={[
{ name: "Projects", href: "/dashboard/projects" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { UseKeyboardNav } from "@/hooks/use-keyboard-nav";
import { cn } from "@/lib/utils";
import { appRouter } from "@/server/api/root";
import { api } from "@/utils/api";
Expand Down Expand Up @@ -62,6 +63,7 @@ const MySql = (

return (
<div className="pb-10">
<UseKeyboardNav forPage="mysql" />
<BreadcrumbSidebar
list={[
{ name: "Projects", href: "/dashboard/projects" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { UseKeyboardNav } from "@/hooks/use-keyboard-nav";
import { cn } from "@/lib/utils";
import { appRouter } from "@/server/api/root";
import { api } from "@/utils/api";
Expand Down Expand Up @@ -62,6 +63,7 @@ const Postgresql = (

return (
<div className="pb-10">
<UseKeyboardNav forPage="postgres" />
<BreadcrumbSidebar
list={[
{ name: "Projects", href: "/dashboard/projects" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { UseKeyboardNav } from "@/hooks/use-keyboard-nav";
import { cn } from "@/lib/utils";
import { appRouter } from "@/server/api/root";
import { api } from "@/utils/api";
Expand Down Expand Up @@ -62,6 +63,7 @@ const Redis = (

return (
<div className="pb-10">
<UseKeyboardNav forPage="redis" />
<BreadcrumbSidebar
list={[
{ name: "Projects", href: "/dashboard/projects" },
Expand Down