Individual SSH Tunnel control

This commit is contained in:
LukeGus
2025-07-27 16:04:32 -05:00
parent 32945adcd9
commit 634e625eef
6 changed files with 491 additions and 354 deletions

View File

@@ -5,6 +5,15 @@ import { Separator } from "@/components/ui/separator.tsx";
import { Input } from "@/components/ui/input.tsx";
import { Search } from "lucide-react";
interface TunnelConnection {
sourcePort: number;
endpointPort: number;
endpointHost: string;
maxRetries: number;
retryInterval: number;
autoStart: boolean;
}
interface SSHHost {
id: number;
name: string;
@@ -19,33 +28,33 @@ interface SSHHost {
enableTunnel: boolean;
enableConfigEditor: boolean;
defaultPath: string;
tunnelConnections: any[];
tunnelConnections: TunnelConnection[];
createdAt: string;
updatedAt: string;
}
interface HostStatus {
connectionState?: string;
statusReason?: string;
statusErrorType?: string;
statusRetryCount?: number;
statusMaxRetries?: number;
statusNextRetryIn?: number;
statusRetryExhausted?: boolean;
interface TunnelStatus {
status: string;
reason?: string;
errorType?: string;
retryCount?: number;
maxRetries?: number;
nextRetryIn?: number;
retryExhausted?: boolean;
}
interface SSHTunnelViewerProps {
hosts: SSHHost[];
hostStatuses?: Record<number, HostStatus>;
onConnect?: (hostId: number) => void;
onDisconnect?: (hostId: number) => void;
tunnelStatuses: Record<string, TunnelStatus>;
tunnelActions: Record<string, boolean>;
onTunnelAction: (action: 'connect' | 'disconnect' | 'cancel', host: SSHHost, tunnelIndex: number) => Promise<void>;
}
export function SSHTunnelViewer({
hosts = [],
hostStatuses = {},
onConnect,
onDisconnect
tunnelStatuses = {},
tunnelActions = {},
onTunnelAction
}: SSHTunnelViewerProps): React.ReactElement {
const [searchQuery, setSearchQuery] = React.useState("");
const [debouncedSearch, setDebouncedSearch] = React.useState("");
@@ -56,14 +65,6 @@ export function SSHTunnelViewer({
return () => clearTimeout(handler);
}, [searchQuery]);
const handleConnect = (hostId: number) => {
onConnect?.(hostId);
};
const handleDisconnect = (hostId: number) => {
onDisconnect?.(hostId);
};
// Filter hosts by search query
const filteredHosts = React.useMemo(() => {
if (!debouncedSearch.trim()) return hosts;
@@ -169,15 +170,9 @@ export function SSHTunnelViewer({
<div key={host.id} className="w-full">
<SSHTunnelObject
host={host}
connectionState={hostStatuses[host.id]?.connectionState as any}
statusReason={hostStatuses[host.id]?.statusReason}
statusErrorType={hostStatuses[host.id]?.statusErrorType}
statusRetryCount={hostStatuses[host.id]?.statusRetryCount}
statusMaxRetries={hostStatuses[host.id]?.statusMaxRetries}
statusNextRetryIn={hostStatuses[host.id]?.statusNextRetryIn}
statusRetryExhausted={hostStatuses[host.id]?.statusRetryExhausted}
onConnect={() => handleConnect(host.id)}
onDisconnect={() => handleDisconnect(host.id)}
tunnelStatuses={tunnelStatuses}
tunnelActions={tunnelActions}
onTunnelAction={onTunnelAction}
/>
</div>
))}