164 lines
4.4 KiB
TypeScript
164 lines
4.4 KiB
TypeScript
import Stack from "@/twui/components/layout/Stack";
|
|
import { RefObject, useContext, useEffect, useRef, useState } from "react";
|
|
import { AppContext } from "@/src/pages/_app";
|
|
import {
|
|
NormalizedServerObject,
|
|
ParsedDeploymentServiceConfig,
|
|
ServerTerminalTargets,
|
|
TtydInfoObject,
|
|
WebSocketDataType,
|
|
} from "@/src/types";
|
|
import useWebSocketEventHandler from "@/twui/components/hooks/useWebSocketEventHandler";
|
|
import _ from "lodash";
|
|
import Loading from "@/twui/components/elements/Loading";
|
|
import Center from "@/twui/components/layout/Center";
|
|
import TtydIframe from "@/src/components/general/ttyd-iframe";
|
|
import useIntersectionObserver from "@/twui/components/hooks/useIntersectionObserver";
|
|
import useStatus from "@/twui/components/hooks/useStatus";
|
|
|
|
type Props = {
|
|
service: ParsedDeploymentServiceConfig;
|
|
server: NormalizedServerObject;
|
|
target: (typeof ServerTerminalTargets)[number]["name"];
|
|
log_cmd?: string;
|
|
portRef?: RefObject<number | undefined>;
|
|
};
|
|
|
|
export default function ServiceClusterServerViews({
|
|
service,
|
|
server,
|
|
target,
|
|
log_cmd,
|
|
portRef,
|
|
}: Props) {
|
|
const { pageProps, ws } = useContext(AppContext);
|
|
|
|
const viewRef = useRef<HTMLDivElement>(undefined);
|
|
|
|
const { data } = useWebSocketEventHandler<WebSocketDataType>();
|
|
const { isIntersecting } = useIntersectionObserver({ elementRef: viewRef });
|
|
|
|
const [ttyd, setTtyd] = useState<TtydInfoObject>();
|
|
|
|
const { refresh, setRefresh } = useStatus();
|
|
|
|
const WsReqSentRef = useRef(false);
|
|
|
|
function sendKillPort() {
|
|
if (ttyd?.port) {
|
|
ws.sendData({
|
|
event: "client:kill-port",
|
|
server,
|
|
service: _.omit(service, ["servers"]),
|
|
port: ttyd.port,
|
|
});
|
|
}
|
|
}
|
|
|
|
useEffect(() => {
|
|
if (!ws?.socket || WsReqSentRef.current) {
|
|
return;
|
|
}
|
|
|
|
if (target == "logs") {
|
|
ws.sendData({
|
|
event: "client:service-server-logs",
|
|
server,
|
|
service: _.omit(service, ["servers"]),
|
|
cmd: log_cmd,
|
|
});
|
|
} else {
|
|
ws.sendData({
|
|
event: "client:service-server-shell",
|
|
server,
|
|
service: _.omit(service, ["servers"]),
|
|
});
|
|
}
|
|
|
|
WsReqSentRef.current = true;
|
|
|
|
return function () {
|
|
sendKillPort();
|
|
};
|
|
}, [ws, refresh]);
|
|
|
|
useEffect(() => {
|
|
console.log("log_cmd", log_cmd);
|
|
|
|
if (WsReqSentRef.current) {
|
|
sendKillPort();
|
|
|
|
setTtyd(undefined);
|
|
WsReqSentRef.current = false;
|
|
setRefresh((prev) => prev + 1);
|
|
}
|
|
}, [target, log_cmd]);
|
|
|
|
useEffect(() => {
|
|
if (ttyd) return;
|
|
|
|
if (
|
|
data?.event == "server:service-server-logs" &&
|
|
data?.ttyd &&
|
|
data.server?.private_ip == server.private_ip
|
|
) {
|
|
setTimeout(() => {
|
|
setTtyd(data.ttyd);
|
|
}, 2000);
|
|
}
|
|
|
|
if (
|
|
data?.event == "server:service-server-shell" &&
|
|
data?.ttyd &&
|
|
data.server?.private_ip == server.private_ip
|
|
) {
|
|
setTimeout(() => {
|
|
setTtyd(data.ttyd);
|
|
}, 2000);
|
|
}
|
|
|
|
if (portRef && data?.ttyd?.port) {
|
|
portRef.current = data.ttyd.port;
|
|
}
|
|
}, [data]);
|
|
|
|
useEffect(() => {
|
|
if (!ttyd?.port) return;
|
|
|
|
if (!isIntersecting) {
|
|
sendKillPort();
|
|
}
|
|
}, [isIntersecting]);
|
|
|
|
// const dev_logs_url = ttydLogs?.port
|
|
// ? `http://localhost:${ttydLogs.port}`
|
|
// : undefined;
|
|
|
|
const title = (
|
|
<>
|
|
<code>{server.private_ip}</code> {target}
|
|
</>
|
|
);
|
|
|
|
return (
|
|
<Stack className="gap-0 w-full" componentRef={viewRef as any}>
|
|
{isIntersecting && ttyd?.url && ttyd.port ? (
|
|
<Stack className="gap-0">
|
|
<TtydIframe
|
|
url={ttyd?.url}
|
|
title={title}
|
|
wrapperProps={{
|
|
className: "border-none",
|
|
}}
|
|
/>
|
|
</Stack>
|
|
) : (
|
|
<Center className="p-10 h-[460px]">
|
|
<Loading />
|
|
</Center>
|
|
)}
|
|
<hr />
|
|
</Stack>
|
|
);
|
|
}
|