headplane/app/routes/machines/dialogs/routes.tsx

115 lines
3.3 KiB
TypeScript
Raw Normal View History

2025-02-04 17:21:03 -05:00
import { GlobeLock, RouteOff } from 'lucide-react';
2024-12-31 10:30:14 +05:30
import { useFetcher } from 'react-router';
import Dialog from '~/components/Dialog';
import Link from '~/components/Link';
import Switch from '~/components/Switch';
2025-02-04 17:21:03 -05:00
import TableList from '~/components/TableList';
2025-04-18 14:40:56 -04:00
import { PopulatedNode } from '~/utils/node-info';
2024-05-01 02:47:45 -04:00
interface RoutesProps {
2025-04-18 14:40:56 -04:00
node: PopulatedNode;
isOpen: boolean;
setIsOpen: (isOpen: boolean) => void;
2024-05-01 02:47:45 -04:00
}
// TODO: Support deleting routes
2025-04-18 14:40:56 -04:00
export default function Routes({ node, isOpen, setIsOpen }: RoutesProps) {
2024-12-31 10:30:14 +05:30
const fetcher = useFetcher();
2025-04-18 14:40:56 -04:00
const subnets = [
...node.customRouting.subnetApprovedRoutes,
...node.customRouting.subnetWaitingRoutes,
];
2024-05-01 02:47:45 -04:00
return (
<Dialog isOpen={isOpen} onOpenChange={setIsOpen}>
<Dialog.Panel variant="unactionable">
2025-04-18 14:40:56 -04:00
<Dialog.Title>Edit route settings of {node.givenName}</Dialog.Title>
<Dialog.Text className="font-bold">Subnet routes</Dialog.Text>
<Dialog.Text>
Connect to devices you can&apos;t install Tailscale on by advertising
IP ranges as subnet routes.{' '}
<Link
to="https://tailscale.com/kb/1019/subnets"
name="Tailscale Subnets Documentation"
>
Learn More
</Link>
</Dialog.Text>
2025-02-04 17:21:03 -05:00
<TableList className="mt-4">
2025-04-18 14:40:56 -04:00
{subnets.length === 0 ? (
2025-02-04 17:21:03 -05:00
<TableList.Item className="flex flex-col items-center gap-2.5 py-4 opacity-70">
<RouteOff />
<p className="font-semibold">
No routes are advertised by this machine
</p>
</TableList.Item>
) : undefined}
2025-04-18 14:40:56 -04:00
{subnets.map((route) => (
2025-02-04 17:21:03 -05:00
<TableList.Item key={route.id}>
<p>{route.prefix}</p>
<Switch
defaultSelected={route.enabled}
label="Enabled"
onChange={(checked) => {
const form = new FormData();
form.set('action_id', 'update_routes');
2025-04-18 14:40:56 -04:00
form.set('node_id', node.id);
form.set('routes', [route.id].join(','));
form.set('enabled', String(checked));
fetcher.submit(form, {
method: 'POST',
});
}}
/>
2025-02-04 17:21:03 -05:00
</TableList.Item>
))}
2025-02-04 17:21:03 -05:00
</TableList>
<Dialog.Text className="font-bold mt-8">Exit nodes</Dialog.Text>
<Dialog.Text>
Allow your network to route internet traffic through this machine.{' '}
<Link
to="https://tailscale.com/kb/1103/exit-nodes"
name="Tailscale Exit-node Documentation"
>
Learn More
</Link>
</Dialog.Text>
2025-02-04 17:21:03 -05:00
<TableList className="mt-4">
2025-04-18 14:40:56 -04:00
{node.customRouting.exitRoutes.length === 0 ? (
2025-02-04 17:21:03 -05:00
<TableList.Item className="flex flex-col items-center gap-2.5 py-4 opacity-70">
<GlobeLock />
<p className="font-semibold">This machine is not an exit node</p>
</TableList.Item>
) : (
2025-02-04 17:21:03 -05:00
<TableList.Item>
<p>Use as exit node</p>
<Switch
2025-04-18 14:40:56 -04:00
defaultSelected={node.customRouting.exitApproved}
label="Enabled"
onChange={(checked) => {
const form = new FormData();
form.set('action_id', 'update_routes');
2025-04-18 14:40:56 -04:00
form.set('node_id', node.id);
form.set(
'routes',
node.customRouting.exitRoutes
.map((route) => route.id)
.join(','),
);
form.set('enabled', String(checked));
fetcher.submit(form, {
method: 'POST',
});
}}
/>
2025-02-04 17:21:03 -05:00
</TableList.Item>
)}
2025-02-04 17:21:03 -05:00
</TableList>
2024-05-01 02:47:45 -04:00
</Dialog.Panel>
</Dialog>
2024-12-31 10:30:14 +05:30
);
2024-05-01 02:47:45 -04:00
}