From 28e40eecbfd7d997f34172c2ed321dda88be7d65 Mon Sep 17 00:00:00 2001 From: Aarnav Tale Date: Tue, 28 Jan 2025 16:02:47 -0500 Subject: [PATCH] fix: switch to new aria components --- app/routes/auth/login.tsx | 8 +- app/routes/dns/components/rename.tsx | 24 ++---- app/routes/dns/dialogs/dns.tsx | 49 ++++++------- app/routes/dns/dialogs/nameserver.tsx | 19 ++--- app/routes/machines/components/machine.tsx | 68 ++++++++--------- app/routes/machines/components/menu.tsx | 82 ++++++++++----------- app/routes/machines/dialogs/move.tsx | 4 +- app/routes/machines/dialogs/new.tsx | 85 ++++++++++------------ app/routes/machines/dialogs/rename.tsx | 5 +- app/routes/machines/machine.tsx | 18 +---- app/routes/settings/auth-keys.tsx | 38 +++++----- app/routes/settings/components/key.tsx | 8 +- 12 files changed, 181 insertions(+), 227 deletions(-) diff --git a/app/routes/auth/login.tsx b/app/routes/auth/login.tsx index 623f6d0..fccd9b0 100644 --- a/app/routes/auth/login.tsx +++ b/app/routes/auth/login.tsx @@ -1,19 +1,17 @@ +import { useMemo } from 'react'; import { type ActionFunctionArgs, type LoaderFunctionArgs, redirect, } from 'react-router'; import { Form, useActionData, useLoaderData } from 'react-router'; -import { useMemo } from 'react'; - import Button from '~/components/Button'; import Card from '~/components/Card'; import Code from '~/components/Code'; -import TextField from '~/components/TextField'; +import Input from '~/components/Input'; import type { Key } from '~/types'; import { loadContext } from '~/utils/config/headplane'; import { pull } from '~/utils/headscale'; -import { beginAuthFlow, getRedirectUri } from '~/utils/oidc'; import { commitSession, getSession } from '~/utils/sessions.server'; export async function loader({ request }: LoaderFunctionArgs) { @@ -109,7 +107,7 @@ export default function Page() { {actionData?.error ? (

{actionData.error}

) : undefined} - -

Tailnet Name

-

+

+

Tailnet Name

+

This is the base domain name of your Tailnet. Devices are accessible at{' '} [device].{name} when Magic DNS is enabled.

{ event.target.select(); @@ -64,11 +57,10 @@ export default function Modal({ name, disabled }: Properties) { Keep in mind that changing this can lead to all sorts of unexpected behavior and may break existing devices in your tailnet. - diff --git a/app/routes/dns/dialogs/dns.tsx b/app/routes/dns/dialogs/dns.tsx index 099dbff..061ca15 100644 --- a/app/routes/dns/dialogs/dns.tsx +++ b/app/routes/dns/dialogs/dns.tsx @@ -1,10 +1,8 @@ import { useMemo, useState } from 'react'; import { useSubmit } from 'react-router'; - import Code from '~/components/Code'; import Dialog from '~/components/Dialog'; -import TextField from '~/components/TextField'; -import { cn } from '~/utils/cn'; +import Input from '~/components/Input'; interface Props { records: { name: string; type: 'A'; value: string }[]; @@ -56,28 +54,29 @@ export default function AddDNS({ records }: Props) { Enter the domain and IP address for the new DNS record. - - - {isDuplicate ? ( -

- A record with the domain name {name} and IP address{' '} - {ip} already exists. -

- ) : undefined} +
+ + + {isDuplicate ? ( +

+ A record with the domain name {name} and IP address{' '} + {ip} already exists. +

+ ) : undefined} +
); diff --git a/app/routes/dns/dialogs/nameserver.tsx b/app/routes/dns/dialogs/nameserver.tsx index c021eda..cd9ae19 100644 --- a/app/routes/dns/dialogs/nameserver.tsx +++ b/app/routes/dns/dialogs/nameserver.tsx @@ -3,8 +3,8 @@ import { useState } from 'react'; import { useSubmit } from 'react-router'; import Dialog from '~/components/Dialog'; +import Input from '~/components/Input'; import Switch from '~/components/Switch'; -import TextField from '~/components/TextField'; import Tooltip from '~/components/Tooltip'; import { cn } from '~/utils/cn'; @@ -68,16 +68,12 @@ export default function AddNameserver({ nameservers }: Props) { }} > Add nameserver - Nameserver - - Use this IPv4 or IPv6 address to resolve names. - -
@@ -118,12 +114,11 @@ export default function AddNameserver({ nameservers }: Props) { {split ? ( <> Domain - Only single-label or fully-qualified queries matching this suffix diff --git a/app/routes/machines/components/machine.tsx b/app/routes/machines/components/machine.tsx index c9bf209..f9bfbac 100644 --- a/app/routes/machines/components/machine.tsx +++ b/app/routes/machines/components/machine.tsx @@ -79,6 +79,14 @@ export default function MachineRow({ tags.unshift('Subnets'); } + const ipOptions = useMemo(() => { + if (magic) { + return [...machine.ipAddresses, `${machine.givenName}.${prefix}`]; + } + + return machine.ipAddresses; + }, [magic, machine.ipAddresses]); + return (
{machine.ipAddresses[0]} - + - - {machine.ipAddresses.map((ip) => ( - { - await navigator.clipboard.writeText(ip); - toast('Copied IP address to clipboard'); - }} - > - {ip} - - - ))} - {magic ? ( - { - const ip = `${machine.givenName}.${prefix}`; - await navigator.clipboard.writeText(ip); - toast('Copied hostname to clipboard'); - }} - > - {machine.givenName}.{prefix} - - - ) : undefined} - + { + await navigator.clipboard.writeText(key.toString()); + toast('Copied IP address to clipboard'); + }} + > + + {ipOptions.map((ip) => ( + +
+ {ip} + +
+
+ ))} +
+
diff --git a/app/routes/machines/components/menu.tsx b/app/routes/machines/components/menu.tsx index 15769b7..c6df411 100644 --- a/app/routes/machines/components/menu.tsx +++ b/app/routes/machines/components/menu.tsx @@ -1,9 +1,8 @@ -import { KebabHorizontalIcon } from '@primer/octicons-react'; -import React, { useState } from 'react'; -import MenuComponent from '~/components/Menu'; +import { Cog, Ellipsis } from 'lucide-react'; +import { useState } from 'react'; +import Menu from '~/components/Menu'; import type { Machine, Route, User } from '~/types'; import { cn } from '~/utils/cn'; - import Delete from '../dialogs/delete'; import Expire from '../dialogs/expire'; import Move from '../dialogs/move'; @@ -16,17 +15,17 @@ interface MenuProps { routes: Route[]; users: User[]; magic?: string; - buttonChild?: React.ReactNode; + isFullButton?: boolean; } type Modal = 'rename' | 'expire' | 'remove' | 'routes' | 'move' | 'tags' | null; -export default function Menu({ +export default function MachineMenu({ machine, routes, magic, users, - buttonChild, + isFullButton, }: MenuProps) { const [modal, setModal] = useState(null); @@ -97,44 +96,45 @@ export default function Menu({ /> )} - - {buttonChild ?? ( - + {isFullButton ? ( + + +

Machine Settings

+
+ ) : ( + - -
+ + )} - - setModal('rename')}> - Edit machine name - - setModal('routes')}> - Edit route settings - - setModal('tags')}> - Edit ACL tags - - setModal('move')}> - Change owner - - {expired ? undefined : ( - setModal('expire')}> - Expire - - )} - setModal('remove')} - > - Remove - - -
+ setModal(key as Modal)}> + + Edit machine name + Edit route settings + Edit ACL tags + Change owner + + + {expired ? ( + <> + ) : ( + +

Expire

+
+ )} + +

Remove

+
+
+
+ ); } diff --git a/app/routes/machines/dialogs/move.tsx b/app/routes/machines/dialogs/move.tsx index 6c28695..ab13a9b 100644 --- a/app/routes/machines/dialogs/move.tsx +++ b/app/routes/machines/dialogs/move.tsx @@ -26,9 +26,7 @@ export default function Move({ machine, users, isOpen, setIsOpen }: MoveProps) { defaultSelectedKey={machine.user.id} > {users.map((user) => ( - - {user.name} - + {user.name} ))} diff --git a/app/routes/machines/dialogs/new.tsx b/app/routes/machines/dialogs/new.tsx index 1ecd8fe..62aa289 100644 --- a/app/routes/machines/dialogs/new.tsx +++ b/app/routes/machines/dialogs/new.tsx @@ -1,14 +1,11 @@ -import { KeyIcon, ServerIcon } from '@primer/octicons-react'; -import { useEffect, useState } from 'react'; -import { Link, useFetcher } from 'react-router'; - +import { Computer, KeySquare } from 'lucide-react'; +import { useState } from 'react'; +import { useNavigate } from 'react-router'; import Code from '~/components/Code'; import Dialog from '~/components/Dialog'; +import Input from '~/components/Input'; import Menu from '~/components/Menu'; import Select from '~/components/Select'; -import Spinner from '~/components/Spinner'; -import TextField from '~/components/TextField'; -import { toast } from '~/components/Toaster'; import type { User } from '~/types'; export interface NewProps { @@ -17,32 +14,14 @@ export interface NewProps { } export default function New(data: NewProps) { - const fetcher = useFetcher<{ success?: boolean }>(); const [pushDialog, setPushDialog] = useState(false); const [mkey, setMkey] = useState(''); - const [user, setUser] = useState(''); - const [toasted, setToasted] = useState(false); - - useEffect(() => { - if (!fetcher.data || toasted) { - return; - } - - if (fetcher.data.success) { - toast('Registered new machine'); - } else { - toast('Failed to register machine due to an invalid key'); - } - - setToasted(true); - }, [fetcher.data, toasted]); + const navigate = useNavigate(); return ( <> - + Register Machine Key The machine key is given when you run{' '} @@ -54,41 +33,55 @@ export default function New(data: NewProps) { - Add Device - - setPushDialog(true)}> - - Register Machine Key - - - - - Generate Pre-auth Key - - - + { + if (key === 'register') { + setPushDialog(true); + return; + } + + if (key === 'pre-auth') { + navigate('/settings/auth-keys'); + } + }} + > + + +
+ + Register Machine Key +
+
+ +
+ + Generate Pre-auth Key +
+
+
+
); diff --git a/app/routes/machines/dialogs/rename.tsx b/app/routes/machines/dialogs/rename.tsx index e983180..c36153c 100644 --- a/app/routes/machines/dialogs/rename.tsx +++ b/app/routes/machines/dialogs/rename.tsx @@ -1,7 +1,7 @@ import { useState } from 'react'; import Code from '~/components/Code'; import Dialog from '~/components/Dialog'; -import TextField from '~/components/TextField'; +import Input from '~/components/Input'; import type { Machine } from '~/types'; interface RenameProps { @@ -29,11 +29,10 @@ export default function Rename({
- diff --git a/app/routes/machines/machine.tsx b/app/routes/machines/machine.tsx index 96d6c06..3f70ac1 100644 --- a/app/routes/machines/machine.tsx +++ b/app/routes/machines/machine.tsx @@ -138,24 +138,11 @@ export default function Page() { - - Machine Settings - - } />
@@ -196,7 +183,8 @@ export default function Page() {

diff --git a/app/routes/settings/auth-keys.tsx b/app/routes/settings/auth-keys.tsx index 8b25ecf..30fc63c 100644 --- a/app/routes/settings/auth-keys.tsx +++ b/app/routes/settings/auth-keys.tsx @@ -1,21 +1,18 @@ -import type { LoaderFunctionArgs, ActionFunctionArgs } from 'react-router'; -import { useLoaderData } from 'react-router'; -import { useLiveData } from '~/utils/useLiveData'; -import { getSession } from '~/utils/sessions.server'; -import { Link as RemixLink } from 'react-router'; -import type { PreAuthKey, User } from '~/types'; -import { pull, post } from '~/utils/headscale'; -import { loadContext } from '~/utils/config/headplane'; import { useState } from 'react'; -import { send } from '~/utils/res'; - +import type { ActionFunctionArgs, LoaderFunctionArgs } from 'react-router'; +import { useLoaderData } from 'react-router'; +import { Link as RemixLink } from 'react-router'; import Link from '~/components/Link'; -import TableList from '~/components/TableList'; import Select from '~/components/Select'; -import Switch from '~/components/Switch'; - -import AddPreAuthKey from './dialogs/new'; +import TableList from '~/components/TableList'; +import type { PreAuthKey, User } from '~/types'; +import { loadContext } from '~/utils/config/headplane'; +import { post, pull } from '~/utils/headscale'; +import { send } from '~/utils/res'; +import { getSession } from '~/utils/sessions.server'; +import { useLiveData } from '~/utils/useLiveData'; import AuthKeyRow from './components/key'; +import AddPreAuthKey from './dialogs/new'; export async function action({ request }: ActionFunctionArgs) { const session = await getSession(request.headers.get('Cookie')); @@ -156,6 +153,7 @@ export default function Page() { return true; }); + // TODO: Fix the selects return (

@@ -202,13 +200,13 @@ export default function Page() {

diff --git a/app/routes/settings/components/key.tsx b/app/routes/settings/components/key.tsx index fd30adc..e32e94d 100644 --- a/app/routes/settings/components/key.tsx +++ b/app/routes/settings/components/key.tsx @@ -1,9 +1,9 @@ -import type { PreAuthKey } from '~/types'; import { toast } from '~/components/Toaster'; +import type { PreAuthKey } from '~/types'; -import Code from '~/components/Code'; -import Button from '~/components/Button'; import Attribute from '~/components/Attribute'; +import Button from '~/components/Button'; +import Code from '~/components/Code'; import ExpireKey from '../dialogs/expire'; interface Props { @@ -31,7 +31,7 @@ export default function AuthKeyRow({ authKey, server }: Props) { tailscale up --login-server {server} --authkey {authKey.key}
- {authKey.used && !authKey.reusable || + {(authKey.used && !authKey.reusable) || new Date(authKey.expiration) < new Date() ? undefined : ( )}