diff --git a/apps/dokploy/components/dashboard/projects/show.tsx b/apps/dokploy/components/dashboard/projects/show.tsx index 8577eee8c..fafa08ffc 100644 --- a/apps/dokploy/components/dashboard/projects/show.tsx +++ b/apps/dokploy/components/dashboard/projects/show.tsx @@ -44,7 +44,7 @@ import { DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; -import { Input } from "@/components/ui/input"; +import { FocusShortcutInput } from "@/components/shared/focus-shortcut-input"; import { Select, SelectContent, @@ -144,12 +144,13 @@ export const ShowProjects = () => { <>
- setSearchQuery(e.target.value)} className="pr-10" /> +
diff --git a/apps/dokploy/components/dashboard/search-command.tsx b/apps/dokploy/components/dashboard/search-command.tsx index 511ca00ab..42430b6d0 100644 --- a/apps/dokploy/components/dashboard/search-command.tsx +++ b/apps/dokploy/components/dashboard/search-command.tsx @@ -3,6 +3,10 @@ import { BookIcon, CircuitBoard, GlobeIcon } from "lucide-react"; import { useRouter } from "next/router"; import React from "react"; +import { + extractServices, + type Services, +} from "@/components/dashboard/settings/users/add-permissions"; import { MariadbIcon, MongodbIcon, @@ -20,13 +24,34 @@ import { CommandSeparator, } from "@/components/ui/command"; import { authClient } from "@/lib/auth-client"; -// import { -// extractServices, -// type Services, -// } from "@/pages/dashboard/project/[projectId]"; import { api } from "@/utils/api"; import { StatusTooltip } from "../shared/status-tooltip"; +// Extended Services type to include environmentId and environmentName for search navigation +type SearchServices = Services & { + environmentId: string; + environmentName: string; +}; + +const extractAllServicesFromProject = (project: any): SearchServices[] => { + const allServices: SearchServices[] = []; + + // Iterate through all environments in the project + project.environments?.forEach((environment: any) => { + const environmentServices = extractServices(environment); + const servicesWithEnvironmentId: SearchServices[] = environmentServices.map( + (service) => ({ + ...service, + environmentId: environment.environmentId, + environmentName: environment.name, + }), + ); + allServices.push(...servicesWithEnvironmentId); + }); + + return allServices; +}; + export const SearchCommand = () => { const router = useRouter(); const [open, setOpen] = React.useState(false); @@ -51,7 +76,7 @@ export const SearchCommand = () => { return (
- {/* + { - {data?.map((project) => ( - { - router.push(`/dashboard/project/${project.projectId}`); - setOpen(false); - }} - > - - {project.name} - - ))} + {data?.map((project) => { + console.log("project", project); + const productionEnvironment = project.environments.find( + (environment) => environment.name === "production", + ); + + if (!productionEnvironment) return null; + + return ( + { + router.push( + `/dashboard/project/${project.projectId}/environment/${productionEnvironment!.environmentId}`, + ); + setOpen(false); + }} + > + + {project.name} / {productionEnvironment!.name} + + ); + })} {data?.map((project) => { - const applications: Services[] = extractServices(project); + const applications: SearchServices[] = + extractAllServicesFromProject(project); return applications.map((application) => ( { )} - {project.name} / {application.name}{" "} + {project.name} / {application.environmentName} /{" "} + {application.name}{" "}
{application.id}
@@ -181,7 +219,7 @@ export const SearchCommand = () => { - */} +
); }; diff --git a/apps/dokploy/components/shared/focus-shortcut-input.tsx b/apps/dokploy/components/shared/focus-shortcut-input.tsx new file mode 100644 index 000000000..9c9215236 --- /dev/null +++ b/apps/dokploy/components/shared/focus-shortcut-input.tsx @@ -0,0 +1,36 @@ +import { useEffect, useRef } from "react"; +import { Input } from "@/components/ui/input"; + +type Props = React.ComponentPropsWithoutRef; + +export const FocusShortcutInput = (props: Props) => { + const inputRef = useRef(null); + + useEffect(() => { + const onKeyDown = (e: KeyboardEvent) => { + const isMod = e.metaKey || e.ctrlKey; + if (!isMod || e.key.toLowerCase() !== "k") return; + + const target = e.target as HTMLElement | null; + if (target) { + const tag = target.tagName; + if ( + target.isContentEditable || + tag === "INPUT" || + tag === "TEXTAREA" || + tag === "SELECT" || + target.getAttribute("role") === "textbox" + ) + return; + } + + e.preventDefault(); + inputRef.current?.focus(); + }; + + window.addEventListener("keydown", onKeyDown); + return () => window.removeEventListener("keydown", onKeyDown); + }, []); + + return ; +}; diff --git a/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId].tsx b/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId].tsx index f87ee8687..100b6f2e3 100644 --- a/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId].tsx +++ b/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId].tsx @@ -80,7 +80,6 @@ import { DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; -import { Input } from "@/components/ui/input"; import { Popover, PopoverContent, @@ -96,6 +95,7 @@ import { import { cn } from "@/lib/utils"; import { appRouter } from "@/server/api/root"; import { api } from "@/utils/api"; +import { FocusShortcutInput } from "@/components/shared/focus-shortcut-input"; export type Services = { appName: string; @@ -1197,7 +1197,7 @@ const EnvironmentPage = (
- setSearchQuery(e.target.value)}