Files
Termix/src/ui/features/tunnel/TunnelViewer.tsx
T
2026-05-13 01:29:43 -05:00

65 lines
2.0 KiB
TypeScript

import React from "react";
import { TunnelObject } from "./TunnelObject.tsx";
import { useTranslation } from "react-i18next";
import type { SSHHost, TunnelStatus } from "@/types/index";
interface SSHTunnelViewerProps {
hosts: SSHHost[];
tunnelStatuses: Record<string, TunnelStatus>;
tunnelActions: Record<string, boolean>;
onTunnelAction: (
action: "connect" | "disconnect" | "cancel",
host: SSHHost,
tunnelIndex: number,
) => Promise<unknown>;
}
export function TunnelViewer({
hosts = [],
tunnelStatuses = {},
tunnelActions = {},
onTunnelAction,
}: SSHTunnelViewerProps): React.ReactElement {
const { t } = useTranslation();
const activeHost: SSHHost | undefined =
Array.isArray(hosts) && hosts.length > 0 ? hosts[0] : undefined;
if (
!activeHost ||
!activeHost.tunnelConnections ||
activeHost.tunnelConnections.length === 0
) {
return (
<div className="w-full h-full flex flex-col items-center justify-center text-center p-3">
<h3 className="text-lg font-semibold text-foreground mb-2">
{t("tunnels.noSshTunnels")}
</h3>
<p className="text-muted-foreground max-w-md">
{t("tunnels.createFirstTunnelMessage")}
</p>
</div>
);
}
return (
<div className="w-full h-full flex flex-col overflow-hidden p-3 min-h-0">
<div className="min-h-0 flex-1 overflow-auto thin-scrollbar pr-1">
<div className="grid grid-cols-[repeat(auto-fit,minmax(320px,1fr))] gap-3 auto-rows-min content-start w-full">
{activeHost.tunnelConnections.map((t, idx) => (
<TunnelObject
key={`tunnel-${activeHost.id}-${idx}-${t.endpointHost}-${t.sourcePort}-${t.endpointPort}`}
host={activeHost}
tunnelIndex={idx}
tunnelStatuses={tunnelStatuses}
tunnelActions={tunnelActions}
onTunnelAction={onTunnelAction}
compact
bare
/>
))}
</div>
</div>
</div>
);
}