From d73e923b73aa0ed38f8b688423df79b95b91298a Mon Sep 17 00:00:00 2001 From: Sonia Appasamy Date: Mon, 6 Nov 2023 19:01:16 -0500 Subject: [PATCH] client/web: add device details view Initial addition of device details view on the frontend. A little more backend piping work to come to fill all of the detail fields, for now using placeholders. Updates tailscale/corp#14335 Signed-off-by: Sonia Appasamy --- client/web/src/components/app.tsx | 108 +++++++++++++----- .../components/views/device-details-view.tsx | 107 +++++++++++++++++ .../views/management-client-view.tsx | 40 +++---- client/web/src/index.css | 19 +++ client/web/src/ui/profile-pic.tsx | 20 +++- 5 files changed, 242 insertions(+), 52 deletions(-) create mode 100644 client/web/src/components/views/device-details-view.tsx diff --git a/client/web/src/components/app.tsx b/client/web/src/components/app.tsx index de3f0cd0f..29869d17a 100644 --- a/client/web/src/components/app.tsx +++ b/client/web/src/components/app.tsx @@ -1,31 +1,57 @@ import cx from "classnames" -import React from "react" +import React, { useEffect } from "react" import LegacyClientView from "src/components/views/legacy-client-view" import LoginClientView from "src/components/views/login-client-view" import ManagementClientView from "src/components/views/management-client-view" import ReadonlyClientView from "src/components/views/readonly-client-view" import useAuth, { AuthResponse, SessionsCallbacks } from "src/hooks/auth" -import useNodeData from "src/hooks/node-data" -import { Route, Switch } from "wouter" +import useNodeData, { NodeData, NodeUpdate } from "src/hooks/node-data" +import { ReactComponent as TailscaleIcon } from "src/icons/tailscale-icon.svg" +import ProfilePic from "src/ui/profile-pic" +import { Link, Route, Switch, useLocation } from "wouter" +import DeviceDetailsView from "./views/device-details-view" export default function App() { const { data: auth, loading: loadingAuth, sessions } = useAuth() + const { data, refreshData, updateNode } = useNodeData() + useEffect(() => { + refreshData() + }, [auth, refreshData]) return ( -
- {loadingAuth ? ( +
+ {loadingAuth || !data ? (
Loading...
// TODO(sonia): add a loading view ) : ( - - - - - {/* TODO */}Device details - {/* TODO */}Subnet router - {/* TODO */}Tailscale SSH server - {/* TODO */}Share local content - Page not found - + <> + {/* TODO(sonia): get rid of the conditions here once full/readonly + * views live on same components */} + {data.DebugMode === "full" && auth?.ok &&
} + + + + + {data.DebugMode !== "" && ( + <> + + + + {/* TODO */}Subnet router + {/* TODO */}Tailscale SSH server + {/* TODO */}Share local content + + )} + +

Page not found

+
+
+ )}
) @@ -33,18 +59,20 @@ export default function App() { function HomeView({ auth, + data, sessions, + refreshData, + updateNode, }: { auth?: AuthResponse + data: NodeData sessions: SessionsCallbacks + refreshData: () => Promise + updateNode: (update: NodeUpdate) => void }) { - const { data, refreshData, updateNode } = useNodeData() - return ( <> - {!data ? ( -
Loading...
// TODO(sonia): add a loading view - ) : data?.Status === "NeedsLogin" || data?.Status === "NoState" ? ( + {data?.Status === "NeedsLogin" || data?.Status === "NoState" ? ( // Client not on a tailnet, render login. )} - {data &&