feat(web): add dedicated /terminal page route
All checks were successful
ci/woodpecker/push/web Pipeline was successful
All checks were successful
ci/woodpecker/push/web Pipeline was successful
Creates /terminal page with full-screen terminal panel. Updates sidebar link from #terminal anchor to proper /terminal route. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
63
apps/web/src/app/(authenticated)/terminal/page.tsx
Normal file
63
apps/web/src/app/(authenticated)/terminal/page.tsx
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Terminal page — dedicated full-screen terminal route at /terminal.
|
||||||
|
*
|
||||||
|
* Renders the TerminalPanel component filling the available content area.
|
||||||
|
* The panel is always open on this page; there is no close action since
|
||||||
|
* the user navigates away using the sidebar instead.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { useState, useEffect } from "react";
|
||||||
|
import type { ReactElement } from "react";
|
||||||
|
import { TerminalPanel } from "@/components/terminal";
|
||||||
|
import { getAccessToken } from "@/lib/auth-client";
|
||||||
|
|
||||||
|
export default function TerminalPage(): ReactElement {
|
||||||
|
const [token, setToken] = useState<string>("");
|
||||||
|
|
||||||
|
// Resolve the access token once on mount. The WebSocket connection inside
|
||||||
|
// TerminalPanel uses this token for authentication.
|
||||||
|
useEffect((): void => {
|
||||||
|
getAccessToken()
|
||||||
|
.then((t) => {
|
||||||
|
setToken(t ?? "");
|
||||||
|
})
|
||||||
|
.catch((err: unknown) => {
|
||||||
|
console.error("[TerminalPage] Failed to retrieve access token:", err);
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{/* Override TerminalPanel inline height so it fills the page */}
|
||||||
|
<style>{`
|
||||||
|
.terminal-page-panel {
|
||||||
|
height: 100% !important;
|
||||||
|
border-top: none !important;
|
||||||
|
flex: 1 !important;
|
||||||
|
}
|
||||||
|
`}</style>
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
height: "100%",
|
||||||
|
overflow: "hidden",
|
||||||
|
}}
|
||||||
|
aria-label="Terminal"
|
||||||
|
>
|
||||||
|
<TerminalPanel
|
||||||
|
open={true}
|
||||||
|
onClose={(): void => {
|
||||||
|
/* No-op: on the dedicated terminal page the panel is always open.
|
||||||
|
Users navigate away using the sidebar rather than closing the panel. */
|
||||||
|
}}
|
||||||
|
token={token}
|
||||||
|
className="terminal-page-panel"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -254,7 +254,7 @@ const NAV_GROUPS: NavGroup[] = [
|
|||||||
badge: { label: "live", pulse: true },
|
badge: { label: "live", pulse: true },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href: "#terminal",
|
href: "/terminal",
|
||||||
label: "Terminal",
|
label: "Terminal",
|
||||||
icon: <IconTerminal />,
|
icon: <IconTerminal />,
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user