mirror of
https://github.com/tale/headplane.git
synced 2026-08-31 17:28:14 +00:00
feat: integrate hostinfo into ui
This commit is contained in:
@@ -4,19 +4,21 @@ import { useMemo } from 'react';
|
||||
import Menu from '~/components/Menu';
|
||||
import StatusCircle from '~/components/StatusCircle';
|
||||
import { toast } from '~/components/Toaster';
|
||||
import type { Machine, Route, User } from '~/types';
|
||||
import type { Machine, Route, User, HostInfo } from '~/types';
|
||||
import { cn } from '~/utils/cn';
|
||||
import * as hinfo from '~/utils/host-info';
|
||||
|
||||
import MenuOptions from './menu';
|
||||
|
||||
interface Props {
|
||||
readonly machine: Machine;
|
||||
readonly routes: Route[];
|
||||
readonly users: User[];
|
||||
readonly magic?: string;
|
||||
machine: Machine;
|
||||
routes: Route[];
|
||||
users: User[];
|
||||
magic?: string;
|
||||
stats?: HostInfo;
|
||||
}
|
||||
|
||||
export default function MachineRow({ machine, routes, magic, users }: Props) {
|
||||
export default function MachineRow({ machine, routes, magic, users, stats }: Props) {
|
||||
const expired =
|
||||
machine.expiry === '0001-01-01 00:00:00' ||
|
||||
machine.expiry === '0001-01-01T00:00:00Z' ||
|
||||
@@ -151,6 +153,22 @@ export default function MachineRow({ machine, routes, magic, users }: Props) {
|
||||
</Menu>
|
||||
</div>
|
||||
</td>
|
||||
<td className="py-2">
|
||||
{stats !== undefined ? (
|
||||
<>
|
||||
<p className="font-semibold leading-snug">
|
||||
{hinfo.getTSVersion(stats)}
|
||||
</p>
|
||||
<p className="text-sm text-gray-500 dark:text-gray-300">
|
||||
{hinfo.getOSInfo(stats)}
|
||||
</p>
|
||||
</>
|
||||
) : (
|
||||
<p className="text-sm text-gray-500 dark:text-gray-300">
|
||||
Unknown
|
||||
</p>
|
||||
)}
|
||||
</td>
|
||||
<td className="py-2">
|
||||
<span
|
||||
className={cn(
|
||||
|
||||
@@ -12,12 +12,13 @@ import { pull } from '~/utils/headscale';
|
||||
import { getSession } from '~/utils/sessions.server';
|
||||
import { useLiveData } from '~/utils/useLiveData';
|
||||
import type { Machine, Route, User } from '~/types';
|
||||
import { queryAgent, initAgentSocket } from '~/utils/ws-agent';
|
||||
|
||||
import { menuAction } from './action';
|
||||
import MachineRow from './components/machine';
|
||||
import NewMachine from './dialogs/new';
|
||||
|
||||
export async function loader({ request }: LoaderFunctionArgs) {
|
||||
export async function loader({ request, context: lC }: LoaderFunctionArgs) {
|
||||
const session = await getSession(request.headers.get('Cookie'));
|
||||
const [machines, routes, users] = await Promise.all([
|
||||
pull<{ nodes: Machine[] }>('v1/node', session.get('hsApiKey')!),
|
||||
@@ -25,6 +26,9 @@ export async function loader({ request }: LoaderFunctionArgs) {
|
||||
pull<{ users: User[] }>('v1/user', session.get('hsApiKey')!),
|
||||
]);
|
||||
|
||||
initAgentSocket(lC);
|
||||
|
||||
const stats = await queryAgent(machines.nodes.map((node) => node.nodeKey));
|
||||
const context = await loadContext();
|
||||
let magic: string | undefined;
|
||||
|
||||
@@ -44,6 +48,7 @@ export async function loader({ request }: LoaderFunctionArgs) {
|
||||
routes: routes.routes,
|
||||
users: users.users,
|
||||
magic,
|
||||
stats,
|
||||
server: context.headscaleUrl,
|
||||
publicServer: context.headscalePublicUrl,
|
||||
};
|
||||
@@ -107,6 +112,7 @@ export default function Page() {
|
||||
) : undefined}
|
||||
</div>
|
||||
</th>
|
||||
<th className="pb-2">Version</th>
|
||||
<th className="pb-2">Last Seen</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -125,6 +131,7 @@ export default function Page() {
|
||||
)}
|
||||
users={data.users}
|
||||
magic={data.magic}
|
||||
stats={data.stats?.[machine.nodeKey]}
|
||||
/>
|
||||
))}
|
||||
</tbody>
|
||||
|
||||
Reference in New Issue
Block a user