mirror of
https://github.com/andwati/dokploy.git
synced 2026-11-15 00:15:17 +00:00
fix: docker terminal dropdown not showing containers for application of type "docker-compose"
This commit is contained in:
@@ -195,6 +195,7 @@ export const ComposeActions = ({ composeId }: Props) => {
|
|||||||
<DockerTerminalModal
|
<DockerTerminalModal
|
||||||
appName={data?.appName || ""}
|
appName={data?.appName || ""}
|
||||||
serverId={data?.serverId || ""}
|
serverId={data?.serverId || ""}
|
||||||
|
appType={data?.composeType || "docker-compose"}
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
import { Terminal } from "@xterm/xterm";
|
import { Terminal } from "@xterm/xterm";
|
||||||
import React, { useEffect, useRef } from "react";
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
import { FitAddon } from "xterm-addon-fit";
|
import { FitAddon } from "xterm-addon-fit";
|
||||||
import "@xterm/xterm/css/xterm.css";
|
import "@xterm/xterm/css/xterm.css";
|
||||||
import { AttachAddon } from "@xterm/addon-attach";
|
import { AttachAddon } from "@xterm/addon-attach";
|
||||||
import { useTheme } from "next-themes";
|
import { useTheme } from "next-themes";
|
||||||
|
import { Label } from "@/components/ui/label";
|
||||||
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
id: string;
|
id: string;
|
||||||
containerId: string;
|
containerId?: string;
|
||||||
serverId?: string;
|
serverId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,6 +20,7 @@ export const DockerTerminal: React.FC<Props> = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const termRef = useRef(null);
|
const termRef = useRef(null);
|
||||||
const [activeWay, setActiveWay] = React.useState<string | undefined>("bash");
|
const [activeWay, setActiveWay] = React.useState<string | undefined>("bash");
|
||||||
|
const [isConnected, setIsConnected] = useState(false);
|
||||||
const { resolvedTheme } = useTheme();
|
const { resolvedTheme } = useTheme();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const container = document.getElementById(id);
|
const container = document.getElementById(id);
|
||||||
@@ -36,31 +38,48 @@ export const DockerTerminal: React.FC<Props> = ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
const addonFit = new FitAddon();
|
const addonFit = new FitAddon();
|
||||||
|
|
||||||
const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
|
|
||||||
|
|
||||||
const wsUrl = `${protocol}//${window.location.host}/docker-container-terminal?containerId=${containerId}&activeWay=${activeWay}${serverId ? `&serverId=${serverId}` : ""}`;
|
|
||||||
|
|
||||||
const ws = new WebSocket(wsUrl);
|
|
||||||
|
|
||||||
const addonAttach = new AttachAddon(ws);
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
term.open(termRef.current);
|
term.open(termRef.current);
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
term.loadAddon(addonFit);
|
term.loadAddon(addonFit);
|
||||||
term.loadAddon(addonAttach);
|
|
||||||
addonFit.fit();
|
addonFit.fit();
|
||||||
return () => {
|
|
||||||
ws.readyState === WebSocket.OPEN && ws.close();
|
// only connect if containerId is provided
|
||||||
};
|
if (
|
||||||
|
containerId &&
|
||||||
|
containerId !== "" &&
|
||||||
|
containerId !== "select-a-container"
|
||||||
|
) {
|
||||||
|
const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
|
||||||
|
|
||||||
|
const wsUrl = `${protocol}//${window.location.host}/docker-container-terminal?containerId=${containerId}&activeWay=${activeWay}${serverId ? `&serverId=${serverId}` : ""}`;
|
||||||
|
|
||||||
|
const ws = new WebSocket(wsUrl);
|
||||||
|
|
||||||
|
const addonAttach = new AttachAddon(ws);
|
||||||
|
|
||||||
|
term.loadAddon(addonAttach);
|
||||||
|
|
||||||
|
ws.onopen = () => {
|
||||||
|
setIsConnected(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
ws.onclose = () => {
|
||||||
|
setIsConnected(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
ws.readyState === WebSocket.OPEN && ws.close();
|
||||||
|
};
|
||||||
|
}
|
||||||
}, [containerId, activeWay, id]);
|
}, [containerId, activeWay, id]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2 mt-4">
|
||||||
<span>
|
<Label>
|
||||||
Select way to connect to <b>{containerId}</b>
|
Select shell to connect to <b>{isConnected ? containerId : "..."}</b>
|
||||||
</span>
|
</Label>
|
||||||
<Tabs value={activeWay} onValueChange={setActiveWay}>
|
<Tabs value={activeWay} onValueChange={setActiveWay}>
|
||||||
<TabsList>
|
<TabsList>
|
||||||
<TabsTrigger value="bash">Bash</TabsTrigger>
|
<TabsTrigger value="bash">Bash</TabsTrigger>
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import {
|
|||||||
DialogTitle,
|
DialogTitle,
|
||||||
DialogTrigger,
|
DialogTrigger,
|
||||||
} from "@/components/ui/dialog";
|
} from "@/components/ui/dialog";
|
||||||
import { Label } from "@/components/ui/label";
|
|
||||||
import {
|
import {
|
||||||
Select,
|
Select,
|
||||||
SelectContent,
|
SelectContent,
|
||||||
@@ -40,23 +39,36 @@ interface Props {
|
|||||||
appName: string;
|
appName: string;
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
serverId?: string;
|
serverId?: string;
|
||||||
|
appType?: "stack" | "docker-compose";
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DockerTerminalModal = ({ children, appName, serverId }: Props) => {
|
export const DockerTerminalModal = ({
|
||||||
|
children,
|
||||||
|
appName,
|
||||||
|
serverId,
|
||||||
|
appType,
|
||||||
|
}: Props) => {
|
||||||
const { data, isLoading } = api.docker.getContainersByAppNameMatch.useQuery(
|
const { data, isLoading } = api.docker.getContainersByAppNameMatch.useQuery(
|
||||||
{
|
{
|
||||||
appName,
|
appName,
|
||||||
serverId,
|
appType,
|
||||||
|
...(serverId ? { serverId } : {}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
enabled: !!appName,
|
enabled: !!appName,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
const [containerId, setContainerId] = useState<string | undefined>();
|
const [containerId, setContainerId] = useState<string | undefined>();
|
||||||
const [mainDialogOpen, setMainDialogOpen] = useState(false);
|
const [mainDialogOpen, setMainDialogOpen] = useState(false);
|
||||||
const [confirmDialogOpen, setConfirmDialogOpen] = useState(false);
|
const [confirmDialogOpen, setConfirmDialogOpen] = useState(false);
|
||||||
|
|
||||||
const handleMainDialogOpenChange = (open: boolean) => {
|
const handleMainDialogOpenChange = (open: boolean) => {
|
||||||
|
if (!open && !containerId) {
|
||||||
|
setMainDialogOpen(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!open) {
|
if (!open) {
|
||||||
setConfirmDialogOpen(true);
|
setConfirmDialogOpen(true);
|
||||||
} else {
|
} else {
|
||||||
@@ -83,7 +95,7 @@ export const DockerTerminalModal = ({ children, appName, serverId }: Props) => {
|
|||||||
<Dialog open={mainDialogOpen} onOpenChange={handleMainDialogOpenChange}>
|
<Dialog open={mainDialogOpen} onOpenChange={handleMainDialogOpenChange}>
|
||||||
<DialogTrigger asChild>{children}</DialogTrigger>
|
<DialogTrigger asChild>{children}</DialogTrigger>
|
||||||
<DialogContent
|
<DialogContent
|
||||||
className="max-h-[85vh] sm:max-w-7xl"
|
className="max-h-[85vh] sm:max-w-7xl"
|
||||||
onEscapeKeyDown={(event) => event.preventDefault()}
|
onEscapeKeyDown={(event) => event.preventDefault()}
|
||||||
>
|
>
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
@@ -92,7 +104,6 @@ export const DockerTerminalModal = ({ children, appName, serverId }: Props) => {
|
|||||||
Easy way to access to docker container
|
Easy way to access to docker container
|
||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<Label>Select a container to view logs</Label>
|
|
||||||
<Select onValueChange={setContainerId} value={containerId}>
|
<Select onValueChange={setContainerId} value={containerId}>
|
||||||
<SelectTrigger>
|
<SelectTrigger>
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
@@ -121,11 +132,7 @@ export const DockerTerminalModal = ({ children, appName, serverId }: Props) => {
|
|||||||
</SelectGroup>
|
</SelectGroup>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
<Terminal
|
<Terminal serverId={serverId} id="terminal" containerId={containerId} />
|
||||||
serverId={serverId || ""}
|
|
||||||
id="terminal"
|
|
||||||
containerId={containerId || "select-a-container"}
|
|
||||||
/>
|
|
||||||
<Dialog open={confirmDialogOpen} onOpenChange={setConfirmDialogOpen}>
|
<Dialog open={confirmDialogOpen} onOpenChange={setConfirmDialogOpen}>
|
||||||
<DialogContent onEscapeKeyDown={(event) => event.preventDefault()}>
|
<DialogContent onEscapeKeyDown={(event) => event.preventDefault()}>
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
|
|||||||
Reference in New Issue
Block a user