headplane/app/routes/machines/dialogs/new.tsx
2025-01-26 15:04:13 -05:00

95 lines
2.5 KiB
TypeScript

import { KeyIcon, ServerIcon } from '@primer/octicons-react';
import { useEffect, useState } from 'react';
import { Link, useFetcher } from 'react-router';
import Code from '~/components/Code';
import Dialog from '~/components/Dialog';
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 {
server: string;
users: User[];
}
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]);
return (
<>
<Dialog isOpen={pushDialog} onOpenChange={setPushDialog}>
<Dialog.Panel
isDisabled={!mkey || !mkey.trim().startsWith('mkey:') || !user}
>
<Dialog.Title>Register Machine Key</Dialog.Title>
<Dialog.Text className="mb-4">
The machine key is given when you run{' '}
<Code isCopyable>
tailscale up --login-server=
{data.server}
</Code>{' '}
on your device.
</Dialog.Text>
<input type="hidden" name="_method" value="register" />
<input type="hidden" name="id" value="_" />
<TextField
label="Machine Key"
placeholder="mkey:ff....."
name="mkey"
state={[mkey, setMkey]}
className="my-2 font-mono"
/>
<Select
label="Owner"
name="user"
placeholder="Select a user"
state={[user, setUser]}
>
{data.users.map((user) => (
<Select.Item key={user.id} id={user.name}>
{user.name}
</Select.Item>
))}
</Select>
</Dialog.Panel>
</Dialog>
<Menu>
<Menu.Button variant="heavy">Add Device</Menu.Button>
<Menu.Items>
<Menu.ItemButton onPress={() => setPushDialog(true)}>
<ServerIcon className="w-4 h-4 mr-2" />
Register Machine Key
</Menu.ItemButton>
<Menu.ItemButton>
<Link to="/settings/auth-keys">
<KeyIcon className="w-4 h-4 mr-2" />
Generate Pre-auth Key
</Link>
</Menu.ItemButton>
</Menu.Items>
</Menu>
</>
);
}