From 9a1db4948b4deb4da8d3a5eb50b234e44a6a2ebf Mon Sep 17 00:00:00 2001 From: Owen Date: Thu, 28 May 2026 21:12:55 -0700 Subject: [PATCH] Shape the ssh/vnc/rdp login ui to match auth --- src/app/auth/layout.tsx | 116 +---------------- src/app/rdp/RdpClient.tsx | 108 ++++++++-------- src/app/rdp/page.tsx | 12 +- src/app/ssh/SshClient.tsx | 233 ++++++++++++++++++---------------- src/app/ssh/page.tsx | 20 ++- src/app/vnc/VncClient.tsx | 56 ++++---- src/app/vnc/page.tsx | 12 +- src/components/AuthFooter.tsx | 117 +++++++++++++++++ 8 files changed, 364 insertions(+), 310 deletions(-) create mode 100644 src/components/AuthFooter.tsx diff --git a/src/app/auth/layout.tsx b/src/app/auth/layout.tsx index 223c4e26c..aa0c34473 100644 --- a/src/app/auth/layout.tsx +++ b/src/app/auth/layout.tsx @@ -1,13 +1,6 @@ import ThemeSwitcher from "@app/components/ThemeSwitcher"; -import { Separator } from "@app/components/ui/separator"; -import { priv } from "@app/lib/api"; -import { pullEnv } from "@app/lib/pullEnv"; -import { build } from "@server/build"; -import { GetLicenseStatusResponse } from "@server/routers/license/types"; -import { AxiosResponse } from "axios"; +import AuthFooter from "@app/components/AuthFooter"; import { Metadata } from "next"; -import { getTranslations } from "next-intl/server"; -import { cache } from "react"; export const metadata: Metadata = { title: { @@ -22,29 +15,6 @@ type AuthLayoutProps = { }; export default async function AuthLayout({ children }: AuthLayoutProps) { - const env = pullEnv(); - const t = await getTranslations(); - let hideFooter = false; - - let licenseStatus: GetLicenseStatusResponse | null = null; - if (build == "enterprise") { - const licenseStatusRes = await cache( - async () => - await priv.get>( - "/license/status" - ) - )(); - licenseStatus = licenseStatusRes.data.data; - if ( - env.branding.hideAuthLayoutFooter && - licenseStatusRes.data.data.isHostLicensed && - licenseStatusRes.data.data.isLicenseValid && - licenseStatusRes.data.data.tier !== "personal" - ) { - hideFooter = true; - } - } - return (
@@ -55,89 +25,7 @@ export default async function AuthLayout({ children }: AuthLayoutProps) {
{children}
- {!hideFooter && ( - - )} +
); } diff --git a/src/app/rdp/RdpClient.tsx b/src/app/rdp/RdpClient.tsx index 00e8ec55a..4b6911e60 100644 --- a/src/app/rdp/RdpClient.tsx +++ b/src/app/rdp/RdpClient.tsx @@ -15,6 +15,8 @@ import type { FileInfo } from "@devolutions/iron-remote-desktop-rdp/dist"; import { GetBrowserTargetResponse } from "@server/routers/resource"; +import { Card, CardContent } from "@app/components/ui/card"; +import LoginCardHeader from "@app/components/LoginCardHeader"; declare module "react" { namespace JSX { @@ -307,48 +309,51 @@ export default function RdpClient({ if (error) { return ( -
-

{error}

-
+ + + +

{error}

+
+
); } return ( -
+ <> {showLogin && ( -
-

RDP

- -
- - - update("domain", e.target.value) - } - /> - - - - update("username", e.target.value) - } - /> - - - - update("password", e.target.value) - } - /> - - {/* + + + +
+ + + update("domain", e.target.value) + } + /> + + + + update("username", e.target.value) + } + /> + + + + update("password", e.target.value) + } + /> + + {/* */} - {/* @@ -369,7 +374,7 @@ export default function RdpClient({ } /> */} - {/*
+ {/*
*/} - -
-
+ +
+ + )}
@@ -500,7 +506,7 @@ export default function RdpClient({ /> )}
-
+ ); } diff --git a/src/app/rdp/page.tsx b/src/app/rdp/page.tsx index 291a35a8c..4ccf07b3b 100644 --- a/src/app/rdp/page.tsx +++ b/src/app/rdp/page.tsx @@ -3,6 +3,7 @@ import { priv } from "@app/lib/api"; import { AxiosResponse } from "axios"; import { GetBrowserTargetResponse } from "@server/routers/resource"; import RdpClient from "./RdpClient"; +import AuthFooter from "@app/components/AuthFooter"; export const dynamic = "force-dynamic"; @@ -29,5 +30,14 @@ export default async function RdpPage() { error = "No resource found for this domain"; } - return ; + return ( +
+
+
+ +
+
+ +
+ ); } diff --git a/src/app/ssh/SshClient.tsx b/src/app/ssh/SshClient.tsx index 9472e9bee..a3eb3b85e 100644 --- a/src/app/ssh/SshClient.tsx +++ b/src/app/ssh/SshClient.tsx @@ -8,6 +8,8 @@ import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; import type { SignSshKeyResponse } from "@server/private/routers/ssh"; import { GetBrowserTargetResponse } from "@server/routers/resource"; +import { Card, CardContent } from "@app/components/ui/card"; +import LoginCardHeader from "@app/components/LoginCardHeader"; type FormState = { username: string; @@ -259,20 +261,12 @@ export default function SshClient({ setConnected(false); } - if (error) { - return ( -
-

{error}

-
- ); - } - // In push mode, show a connecting/connected state without the login form. if (signedKeyData && signedPrivateKey) { return ( -
+ <> {!connected && ( -
+

{connectError ? connectError @@ -283,7 +277,7 @@ export default function SshClient({

)} {connected && ( -
+
)} -
+ + ); + } + + if (error) { + return ( + + + +

{error}

+
+
); } return ( -
+ <> {!connected && ( -
-

SSH

- -
- - - setForm({ - ...form, - username: e.target.value - }) - } - placeholder="root" - /> - - - - setForm({ - ...form, - password: e.target.value - }) - } - placeholder={ - form.privateKey - ? "Optional with key auth" - : "" - } - /> - - - -