headplane/app/routes/dns/dialogs/nameserver.tsx

157 lines
4.2 KiB
TypeScript
Raw Normal View History

2024-12-31 10:30:14 +05:30
import { RepoForkedIcon } from '@primer/octicons-react';
import { Form, useSubmit } from 'react-router';
import { useState } from 'react';
2024-05-21 17:21:14 -04:00
2024-12-31 10:30:14 +05:30
import Dialog from '~/components/Dialog';
import Switch from '~/components/Switch';
import TextField from '~/components/TextField';
import Tooltip from '~/components/Tooltip';
import { cn } from '~/utils/cn';
2024-05-21 17:21:14 -04:00
interface Props {
2024-12-31 10:30:14 +05:30
nameservers: Record<string, string[]>;
2024-05-21 17:21:14 -04:00
}
export default function AddNameserver({ nameservers }: Props) {
2024-12-31 10:30:14 +05:30
const submit = useSubmit();
const [split, setSplit] = useState(false);
const [ns, setNs] = useState('');
const [domain, setDomain] = useState('');
2024-05-21 17:21:14 -04:00
return (
<Dialog>
2024-12-31 10:30:14 +05:30
<Dialog.Button>Add nameserver</Dialog.Button>
2024-05-21 17:21:14 -04:00
<Dialog.Panel>
2024-12-31 10:30:14 +05:30
{(close) => (
2024-05-21 17:21:14 -04:00
<>
2024-12-31 10:30:14 +05:30
<Dialog.Title>Add nameserver</Dialog.Title>
<Dialog.Text className="font-semibold">Nameserver</Dialog.Text>
2024-05-21 17:21:14 -04:00
<Dialog.Text className="text-sm">
Use this IPv4 or IPv6 address to resolve names.
</Dialog.Text>
<Form
method="POST"
onSubmit={(event) => {
2024-12-31 10:30:14 +05:30
event.preventDefault();
if (!ns) return;
2024-05-21 17:21:14 -04:00
if (split) {
2024-12-31 10:30:14 +05:30
const splitNs: Record<string, string[]> = {};
2024-05-21 17:21:14 -04:00
for (const [key, value] of Object.entries(nameservers)) {
2024-12-31 10:30:14 +05:30
if (key === 'global') continue;
splitNs[key] = value;
2024-05-21 17:21:14 -04:00
}
if (Object.keys(splitNs).includes(domain)) {
2024-12-31 10:30:14 +05:30
splitNs[domain].push(ns);
2024-05-21 17:21:14 -04:00
} else {
2024-12-31 10:30:14 +05:30
splitNs[domain] = [ns];
2024-05-21 17:21:14 -04:00
}
2024-12-31 10:30:14 +05:30
submit(
{
'dns.nameservers.split': splitNs,
},
{
method: 'PATCH',
encType: 'application/json',
},
);
2024-05-21 17:21:14 -04:00
} else {
2024-12-31 10:30:14 +05:30
const globalNs = nameservers.global;
globalNs.push(ns);
2024-05-21 17:21:14 -04:00
2024-12-31 10:30:14 +05:30
submit(
{
'dns.nameservers.global': globalNs,
},
{
method: 'PATCH',
encType: 'application/json',
},
);
2024-05-21 17:21:14 -04:00
}
2024-12-31 10:30:14 +05:30
setNs('');
setDomain('');
setSplit(false);
close();
2024-05-21 17:21:14 -04:00
}}
>
<TextField
label="DNS Server"
placeholder="1.2.3.4"
name="ns"
state={[ns, setNs]}
className="mt-2 mb-8"
/>
<div className="flex items-center justify-between">
<div className="block">
<div className="inline-flex items-center gap-2">
<Dialog.Text className="font-semibold">
Restrict to domain
</Dialog.Text>
<Tooltip>
2024-12-31 10:30:14 +05:30
<Tooltip.Button
className={cn(
'text-xs rounded-md px-1.5 py-0.5',
'bg-ui-200 dark:bg-ui-800',
'text-ui-600 dark:text-ui-300',
)}
2024-05-21 17:21:14 -04:00
>
<RepoForkedIcon className="w-4 h-4 mr-0.5" />
Split DNS
</Tooltip.Button>
<Tooltip.Body>
2024-12-31 10:30:14 +05:30
Only clients that support split DNS (Tailscale v1.8 or
later for most platforms) will use this nameserver.
Older clients will ignore it.
2024-05-21 17:21:14 -04:00
</Tooltip.Body>
</Tooltip>
</div>
<Dialog.Text className="text-sm">
This nameserver will only be used for some domains.
</Dialog.Text>
</div>
<Switch
label="Split DNS"
defaultSelected={split}
2024-12-31 10:30:14 +05:30
onChange={() => {
setSplit(!split);
}}
2024-05-21 17:21:14 -04:00
/>
</div>
2024-12-31 10:30:14 +05:30
{split ? (
<>
<Dialog.Text className="font-semibold mt-8">
Domain
</Dialog.Text>
<TextField
label="Domain"
placeholder="example.com"
name="domain"
state={[domain, setDomain]}
className="my-2"
/>
<Dialog.Text className="text-sm">
Only single-label or fully-qualified queries matching this
suffix should use the nameserver.
</Dialog.Text>
</>
) : undefined}
2024-05-21 17:21:14 -04:00
<div className="mt-6 flex justify-end gap-2 mt-6">
2024-12-31 10:30:14 +05:30
<Dialog.Action variant="cancel" onPress={close}>
2024-05-21 17:21:14 -04:00
Cancel
</Dialog.Action>
2024-12-31 10:30:14 +05:30
<Dialog.Action variant="confirm" onPress={close}>
2024-05-21 17:21:14 -04:00
Add
</Dialog.Action>
</div>
</Form>
</>
)}
</Dialog.Panel>
</Dialog>
2024-12-31 10:30:14 +05:30
);
2024-05-21 17:21:14 -04:00
}