mirror of
https://github.com/tale/headplane.git
synced 2026-08-31 17:28:14 +00:00
fix: resolve random css issues with mobile layouts
This commit is contained in:
@@ -1,18 +1,18 @@
|
||||
import { DndContext, DragOverlay, closestCorners } from '@dnd-kit/core';
|
||||
import { closestCorners, DndContext, DragOverlay } from '@dnd-kit/core';
|
||||
import {
|
||||
restrictToParentElement,
|
||||
restrictToVerticalAxis,
|
||||
} from '@dnd-kit/modifiers';
|
||||
import {
|
||||
SortableContext,
|
||||
arrayMove,
|
||||
SortableContext,
|
||||
useSortable,
|
||||
verticalListSortingStrategy,
|
||||
} from '@dnd-kit/sortable';
|
||||
import { CSS } from '@dnd-kit/utilities';
|
||||
import { GripVertical, Lock } from 'lucide-react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { type FetcherWithComponents, Form, useFetcher } from 'react-router';
|
||||
import { Form } from 'react-router';
|
||||
import Button from '~/components/Button';
|
||||
import Input from '~/components/Input';
|
||||
import TableList from '~/components/TableList';
|
||||
@@ -37,18 +37,15 @@ export default function ManageDomains({
|
||||
}, [searchDomains]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col w-2/3">
|
||||
<div className="flex flex-col w-full sm:w-2/3">
|
||||
<h1 className="text-2xl font-medium mb-4">Search Domains</h1>
|
||||
<p className="mb-4">
|
||||
Set custom DNS search domains for your Tailnet. When using Magic DNS,
|
||||
your tailnet domain is used as the first search domain.
|
||||
</p>
|
||||
<DndContext
|
||||
modifiers={[restrictToVerticalAxis, restrictToParentElement]}
|
||||
collisionDetection={closestCorners}
|
||||
onDragStart={(event) => {
|
||||
setActiveId(event.active.id);
|
||||
}}
|
||||
modifiers={[restrictToVerticalAxis, restrictToParentElement]}
|
||||
onDragEnd={(event) => {
|
||||
setActiveId(null);
|
||||
const { active, over } = event;
|
||||
@@ -70,6 +67,9 @@ export default function ManageDomains({
|
||||
setLocalDomains(arrayMove(localDomains, oldIndex, newIndex));
|
||||
}
|
||||
}}
|
||||
onDragStart={(event) => {
|
||||
setActiveId(event.active.id);
|
||||
}}
|
||||
>
|
||||
<TableList>
|
||||
{magic ? (
|
||||
@@ -91,19 +91,19 @@ export default function ManageDomains({
|
||||
>
|
||||
{localDomains.map((sd, index) => (
|
||||
<Domain
|
||||
key={sd}
|
||||
domain={sd}
|
||||
id={index + 1}
|
||||
isDisabled={isDisabled}
|
||||
key={sd}
|
||||
/>
|
||||
))}
|
||||
<DragOverlay adjustScale>
|
||||
{activeId ? (
|
||||
<Domain
|
||||
isDragging
|
||||
domain={localDomains[(activeId as number) - 1]}
|
||||
id={(activeId as number) - 1}
|
||||
isDisabled={isDisabled}
|
||||
isDragging
|
||||
/>
|
||||
) : undefined}
|
||||
</DragOverlay>
|
||||
@@ -111,28 +111,28 @@ export default function ManageDomains({
|
||||
{isDisabled ? undefined : (
|
||||
<TableList.Item key="add-sd">
|
||||
<Form
|
||||
method="POST"
|
||||
className="flex items-center justify-between w-full"
|
||||
method="POST"
|
||||
>
|
||||
<input type="hidden" name="action_id" value="add_domain" />
|
||||
<input name="action_id" type="hidden" value="add_domain" />
|
||||
<Input
|
||||
type="text"
|
||||
className={cn(
|
||||
'border-none font-mono p-0 text-sm',
|
||||
'rounded-none focus:ring-0 w-full ml-1',
|
||||
)}
|
||||
placeholder="Search Domain"
|
||||
label="Search Domain"
|
||||
name="domain"
|
||||
labelHidden
|
||||
isRequired
|
||||
label="Search Domain"
|
||||
labelHidden
|
||||
name="domain"
|
||||
placeholder="Search Domain"
|
||||
type="text"
|
||||
/>
|
||||
<Button
|
||||
type="submit"
|
||||
className={cn(
|
||||
'px-2 py-1 rounded-md',
|
||||
'text-blue-500 dark:text-blue-400',
|
||||
)}
|
||||
type="submit"
|
||||
>
|
||||
Add
|
||||
</Button>
|
||||
@@ -164,11 +164,11 @@ function Domain({ domain, id, isDragging, isDisabled }: DomainProps) {
|
||||
|
||||
return (
|
||||
<TableList.Item
|
||||
ref={setNodeRef}
|
||||
className={cn(
|
||||
isSortableDragging ? 'opacity-50' : '',
|
||||
isDragging ? 'ring-3 bg-white dark:bg-headplane-900' : '',
|
||||
)}
|
||||
ref={setNodeRef}
|
||||
style={{
|
||||
transform: CSS.Transform.toString(transform),
|
||||
transition,
|
||||
@@ -186,15 +186,15 @@ function Domain({ domain, id, isDragging, isDisabled }: DomainProps) {
|
||||
</p>
|
||||
{isDragging ? undefined : (
|
||||
<Form method="POST">
|
||||
<input type="hidden" name="action_id" value="remove_domain" />
|
||||
<input type="hidden" name="domain" value={domain} />
|
||||
<input name="action_id" type="hidden" value="remove_domain" />
|
||||
<input name="domain" type="hidden" value={domain} />
|
||||
<Button
|
||||
type="submit"
|
||||
isDisabled={isDisabled}
|
||||
className={cn(
|
||||
'px-2 py-1 rounded-md',
|
||||
'text-red-500 dark:text-red-400',
|
||||
)}
|
||||
isDisabled={isDisabled}
|
||||
type="submit"
|
||||
>
|
||||
Remove
|
||||
</Button>
|
||||
|
||||
@@ -20,14 +20,14 @@ export default function ManageNS({
|
||||
overrideLocalDns,
|
||||
}: Props) {
|
||||
return (
|
||||
<div className="flex flex-col w-2/3">
|
||||
<div className="flex flex-col w-full sm:w-2/3">
|
||||
<h1 className="text-2xl font-medium mb-4">Nameservers</h1>
|
||||
<p>
|
||||
Set the nameservers used by devices on the Tailnet to resolve DNS
|
||||
queries.{' '}
|
||||
<Link
|
||||
to="https://tailscale.com/kb/1054/dns"
|
||||
name="Tailscale DNS Documentation"
|
||||
to="https://tailscale.com/kb/1054/dns"
|
||||
>
|
||||
Learn more
|
||||
</Link>
|
||||
@@ -35,12 +35,12 @@ export default function ManageNS({
|
||||
<div className="mt-4">
|
||||
{Object.keys(nameservers).map((key) => (
|
||||
<NameserverList
|
||||
key={key}
|
||||
isGlobal={key === 'global'}
|
||||
isDisabled={isDisabled}
|
||||
isGlobal={key === 'global'}
|
||||
key={key}
|
||||
name={key}
|
||||
nameservers={nameservers}
|
||||
overrideLocalDns={overrideLocalDns}
|
||||
name={key}
|
||||
/>
|
||||
))}
|
||||
|
||||
@@ -66,16 +66,17 @@ function NameserverList({
|
||||
name,
|
||||
}: ListProps) {
|
||||
const list = isGlobal ? nameservers.global : nameservers[name];
|
||||
const submit = useSubmit();
|
||||
|
||||
if (list.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const submit = useSubmit();
|
||||
return (
|
||||
<div className="mb-8">
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
{isGlobal ? (
|
||||
<div className="flex items-center justify-between w-full">
|
||||
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between w-full gap-2">
|
||||
<h2 className="text-md font-medium opacity-80">
|
||||
Global Nameservers
|
||||
</h2>
|
||||
@@ -87,8 +88,8 @@ function NameserverList({
|
||||
names outside the tailnet. When disabled (default), devices
|
||||
will prefer their local DNS configuration.
|
||||
<Link
|
||||
to="https://tailscale.com/kb/1054/dns#global-nameservers"
|
||||
name="Tailscale Global Nameservers Documentation"
|
||||
to="https://tailscale.com/kb/1054/dns#global-nameservers"
|
||||
>
|
||||
Learn More
|
||||
</Link>
|
||||
@@ -96,11 +97,10 @@ function NameserverList({
|
||||
</Tooltip>
|
||||
<p>Override DNS servers</p>
|
||||
<Switch
|
||||
label="Override local DNS settings"
|
||||
className="h-[15px] w-[23px] p-[2px]"
|
||||
switchClassName="h-[9px] w-[9px]"
|
||||
name="override_dns"
|
||||
className="h-[15px] w-[23px] p-0.5"
|
||||
defaultSelected={overrideLocalDns}
|
||||
label="Override local DNS settings"
|
||||
name="override_dns"
|
||||
onChange={(v) => {
|
||||
submit(
|
||||
{
|
||||
@@ -112,6 +112,7 @@ function NameserverList({
|
||||
},
|
||||
);
|
||||
}}
|
||||
switchClassName="h-[9px] w-[9px]"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -125,20 +126,20 @@ function NameserverList({
|
||||
<TableList.Item key={ns}>
|
||||
<p className="font-mono text-sm">{ns}</p>
|
||||
<Form method="POST">
|
||||
<input type="hidden" name="action_id" value="remove_ns" />
|
||||
<input type="hidden" name="ns" value={ns} />
|
||||
<input name="action_id" type="hidden" value="remove_ns" />
|
||||
<input name="ns" type="hidden" value={ns} />
|
||||
<input
|
||||
type="hidden"
|
||||
name="split_name"
|
||||
type="hidden"
|
||||
value={isGlobal ? 'global' : name}
|
||||
/>
|
||||
<Button
|
||||
isDisabled={isDisabled}
|
||||
type="submit"
|
||||
className={cn(
|
||||
'px-2 py-1 rounded-md',
|
||||
'text-red-500 dark:text-red-400',
|
||||
)}
|
||||
isDisabled={isDisabled}
|
||||
type="submit"
|
||||
>
|
||||
Remove
|
||||
</Button>
|
||||
|
||||
@@ -13,14 +13,14 @@ interface Props {
|
||||
|
||||
export default function ManageRecords({ records, isDisabled }: Props) {
|
||||
return (
|
||||
<div className="flex flex-col w-2/3">
|
||||
<div className="flex flex-col w-full sm:w-2/3">
|
||||
<h1 className="text-2xl font-medium mb-4">DNS Records</h1>
|
||||
<p>
|
||||
Headscale supports adding custom DNS records to your Tailnet. As of now,
|
||||
only <Code>A</Code> and <Code>AAAA</Code> records are supported.{' '}
|
||||
<Link
|
||||
to="https://headscale.net/stable/ref/dns"
|
||||
name="Headscale DNS Records documentation"
|
||||
to="https://headscale.net/stable/ref/dns"
|
||||
>
|
||||
Learn More
|
||||
</Link>
|
||||
@@ -32,7 +32,7 @@ export default function ManageRecords({ records, isDisabled }: Props) {
|
||||
<p className="opacity-50 mx-auto">No DNS records found</p>
|
||||
</TableList.Item>
|
||||
) : (
|
||||
records.map((record, index) => (
|
||||
records.map((record) => (
|
||||
<TableList.Item key={`${record.name}-${record.value}`}>
|
||||
<div className="flex gap-2 items-center w-full">
|
||||
<p
|
||||
@@ -43,22 +43,24 @@ export default function ManageRecords({ records, isDisabled }: Props) {
|
||||
>
|
||||
{record.type}
|
||||
</p>
|
||||
<div className="grid grid-cols-2 gap-2 w-full">
|
||||
<p className="font-mono text-sm">{record.name}</p>
|
||||
<p className="font-mono text-sm">{record.value}</p>
|
||||
<div className="flex flex-col sm:flex-row sm:gap-2 flex-1 min-w-0">
|
||||
<p className="font-mono text-sm truncate">{record.name}</p>
|
||||
<p className="font-mono text-sm truncate opacity-70 sm:opacity-100">
|
||||
{record.value}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<Form method="POST">
|
||||
<input type="hidden" name="action_id" value="remove_record" />
|
||||
<input type="hidden" name="record_name" value={record.name} />
|
||||
<input type="hidden" name="record_type" value={record.type} />
|
||||
<input name="action_id" type="hidden" value="remove_record" />
|
||||
<input name="record_name" type="hidden" value={record.name} />
|
||||
<input name="record_type" type="hidden" value={record.type} />
|
||||
<Button
|
||||
type="submit"
|
||||
isDisabled={isDisabled}
|
||||
className={cn(
|
||||
'px-2 py-1 rounded-md',
|
||||
'text-red-500 dark:text-red-400',
|
||||
)}
|
||||
isDisabled={isDisabled}
|
||||
type="submit"
|
||||
>
|
||||
Remove
|
||||
</Button>
|
||||
|
||||
@@ -9,21 +9,21 @@ interface Props {
|
||||
|
||||
export default function RenameTailnet({ name, isDisabled }: Props) {
|
||||
return (
|
||||
<div className="flex flex-col w-2/3 gap-y-4">
|
||||
<div className="flex flex-col w-full sm:w-2/3 gap-y-4">
|
||||
<h1 className="text-2xl font-medium mb-2">Tailnet Name</h1>
|
||||
<p>
|
||||
This is the base domain name of your Tailnet. Devices are accessible at{' '}
|
||||
<Code>[device].{name}</Code> when Magic DNS is enabled.
|
||||
</p>
|
||||
<Input
|
||||
isReadOnly
|
||||
labelHidden
|
||||
className="w-3/5 font-medium text-sm"
|
||||
isReadOnly
|
||||
label="Tailnet name"
|
||||
value={name}
|
||||
labelHidden
|
||||
onFocus={(event) => {
|
||||
event.target.select();
|
||||
}}
|
||||
value={name}
|
||||
/>
|
||||
<Dialog>
|
||||
<Dialog.Button isDisabled={isDisabled}>Rename Tailnet</Dialog.Button>
|
||||
@@ -33,13 +33,13 @@ export default function RenameTailnet({ name, isDisabled }: Props) {
|
||||
Keep in mind that changing this can lead to all sorts of unexpected
|
||||
behavior and may break existing devices in your tailnet.
|
||||
</Dialog.Text>
|
||||
<input type="hidden" name="action_id" value="rename_tailnet" />
|
||||
<input name="action_id" type="hidden" value="rename_tailnet" />
|
||||
<Input
|
||||
defaultValue={name}
|
||||
isRequired
|
||||
label="Tailnet name"
|
||||
placeholder="ts.net"
|
||||
defaultValue={name}
|
||||
name="new_name"
|
||||
placeholder="ts.net"
|
||||
/>
|
||||
</Dialog.Panel>
|
||||
</Dialog>
|
||||
|
||||
Reference in New Issue
Block a user