fix: suppress date and button hydration warnings
This commit is contained in:
parent
0ad578e651
commit
f2747ada94
@ -7,6 +7,7 @@ export interface AttributeProps {
|
||||
value: string;
|
||||
isCopyable?: boolean;
|
||||
link?: string;
|
||||
suppressHydrationWarning?: boolean;
|
||||
}
|
||||
|
||||
export default function Attribute({
|
||||
@ -14,6 +15,7 @@ export default function Attribute({
|
||||
value,
|
||||
link,
|
||||
isCopyable,
|
||||
suppressHydrationWarning,
|
||||
}: AttributeProps) {
|
||||
return (
|
||||
<dl className="flex items-center w-full gap-x-1">
|
||||
@ -27,6 +29,7 @@ export default function Attribute({
|
||||
)}
|
||||
</dt>
|
||||
<dd
|
||||
suppressHydrationWarning={suppressHydrationWarning}
|
||||
className={cn(
|
||||
'rounded-lg truncate w-full px-2.5 py-1 text-sm',
|
||||
'flex items-center gap-x-1',
|
||||
@ -54,7 +57,12 @@ export default function Attribute({
|
||||
}, 1000);
|
||||
}}
|
||||
>
|
||||
<p className="truncate">{value}</p>
|
||||
<p
|
||||
suppressHydrationWarning={suppressHydrationWarning}
|
||||
className="truncate"
|
||||
>
|
||||
{value}
|
||||
</p>
|
||||
<Check className="h-4.5 w-4.5 p-1 hidden data-[copied]:block" />
|
||||
<Copy className="h-4.5 w-4.5 p-1 block data-[copied]:hidden" />
|
||||
</button>
|
||||
|
||||
@ -7,13 +7,13 @@ import {
|
||||
} from 'react-router';
|
||||
import Button from '~/components/Button';
|
||||
import Card from '~/components/Card';
|
||||
import Code from '~/components/Code';
|
||||
import Footer from '~/components/Footer';
|
||||
import Header from '~/components/Header';
|
||||
import type { LoadContext } from '~/server';
|
||||
import { Capabilities } from '~/server/web/roles';
|
||||
import { User } from '~/types';
|
||||
import log from '~/utils/log';
|
||||
import toast from '~/utils/toast';
|
||||
|
||||
// This loads the bare minimum for the application to function
|
||||
// So we know that if context fails to load then well, oops?
|
||||
@ -122,7 +122,7 @@ export default function Shell() {
|
||||
<>
|
||||
<Header {...data} />
|
||||
{/* Always show the outlet if we are onboarding */}
|
||||
{(data.onboarding ? true : data.uiAccess) ? (
|
||||
{(data.onboarding ? true : !data.uiAccess) ? (
|
||||
<Outlet />
|
||||
) : (
|
||||
<Card className="mx-auto w-fit mt-24">
|
||||
@ -134,11 +134,21 @@ export default function Shell() {
|
||||
Connect to Tailscale with your devices to access this Tailnet. Use
|
||||
this command to help you get started:
|
||||
</Card.Text>
|
||||
<Button className="pointer-events-none text-md hover:bg-initial focus:ring-0">
|
||||
<Code className="pointer-events-auto bg-transparent" isCopyable>
|
||||
<Button
|
||||
className="flex text-md font-mono"
|
||||
onPress={async () => {
|
||||
await navigator.clipboard.writeText(
|
||||
`tailscale up --login-server=${data.url}`,
|
||||
);
|
||||
|
||||
toast('Copied to clipboard');
|
||||
}}
|
||||
>
|
||||
tailscale up --login-server={data.url}
|
||||
</Code>
|
||||
</Button>
|
||||
<p className="text-xs mt-1 opacity-50 text-center">
|
||||
Click this button to copy the command.
|
||||
</p>
|
||||
<p className="mt-4 text-sm opacity-50">
|
||||
Your account does not have access to the UI. Please contact your
|
||||
administrator if you believe this is a mistake.
|
||||
|
||||
@ -180,7 +180,7 @@ export default function MachineRow({
|
||||
isOnline={machine.online && !expired}
|
||||
className="w-4 h-4"
|
||||
/>
|
||||
<p>
|
||||
<p suppressHydrationWarning>
|
||||
{machine.online && !expired
|
||||
? 'Connected'
|
||||
: new Date(machine.lastSeen).toLocaleString()}
|
||||
|
||||
@ -310,14 +310,17 @@ export default function Page() {
|
||||
<Attribute name="Hostname" value={machine.name} />
|
||||
<Attribute isCopyable name="Node Key" value={machine.nodeKey} />
|
||||
<Attribute
|
||||
suppressHydrationWarning
|
||||
name="Created"
|
||||
value={new Date(machine.createdAt).toLocaleString()}
|
||||
/>
|
||||
<Attribute
|
||||
suppressHydrationWarning
|
||||
name="Last Seen"
|
||||
value={new Date(machine.lastSeen).toLocaleString()}
|
||||
/>
|
||||
<Attribute
|
||||
suppressHydrationWarning
|
||||
name="Expiry"
|
||||
value={expired ? new Date(machine.expiry).toLocaleString() : 'Never'}
|
||||
/>
|
||||
|
||||
@ -22,15 +22,19 @@ export default function AuthKeyRow({ authKey, server }: Props) {
|
||||
<Attribute name="Reusable" value={authKey.reusable ? 'Yes' : 'No'} />
|
||||
<Attribute name="Ephemeral" value={authKey.ephemeral ? 'Yes' : 'No'} />
|
||||
<Attribute name="Used" value={authKey.used ? 'Yes' : 'No'} />
|
||||
<Attribute name="Created" value={createdAt} />
|
||||
<Attribute name="Expiration" value={expiration} />
|
||||
<Attribute suppressHydrationWarning name="Created" value={createdAt} />
|
||||
<Attribute
|
||||
suppressHydrationWarning
|
||||
name="Expiration"
|
||||
value={expiration}
|
||||
/>
|
||||
<p className="mb-1 mt-4">
|
||||
To use this key, run the following command on your device:
|
||||
</p>
|
||||
<Code className="text-sm">
|
||||
tailscale up --login-server {server} --authkey {authKey.key}
|
||||
</Code>
|
||||
<div className="flex gap-4 items-center">
|
||||
<div suppressHydrationWarning className="flex gap-4 items-center">
|
||||
{(authKey.used && !authKey.reusable) ||
|
||||
new Date(authKey.expiration) < new Date() ? undefined : (
|
||||
<ExpireKey authKey={authKey} />
|
||||
|
||||
@ -42,7 +42,10 @@ export default function UserRow({ user, role }: UserRowProps) {
|
||||
<p>{mapRoleToName(role)}</p>
|
||||
</td>
|
||||
<td className="pl-0.5 py-2">
|
||||
<p className="text-sm text-headplane-600 dark:text-headplane-300">
|
||||
<p
|
||||
suppressHydrationWarning
|
||||
className="text-sm text-headplane-600 dark:text-headplane-300"
|
||||
>
|
||||
{new Date(user.createdAt).toLocaleDateString()}
|
||||
</p>
|
||||
</td>
|
||||
@ -54,7 +57,9 @@ export default function UserRow({ user, role }: UserRowProps) {
|
||||
)}
|
||||
>
|
||||
<StatusCircle isOnline={isOnline} className="w-4 h-4" />
|
||||
<p>{isOnline ? 'Connected' : new Date(lastSeen).toLocaleString()}</p>
|
||||
<p suppressHydrationWarning>
|
||||
{isOnline ? 'Connected' : new Date(lastSeen).toLocaleString()}
|
||||
</p>
|
||||
</span>
|
||||
</td>
|
||||
<td className="py-2 pr-0.5">
|
||||
|
||||
@ -12,7 +12,6 @@ import {
|
||||
} from 'react-router';
|
||||
import Button from '~/components/Button';
|
||||
import Card from '~/components/Card';
|
||||
import Code from '~/components/Code';
|
||||
import Link from '~/components/Link';
|
||||
import Options from '~/components/Options';
|
||||
import StatusCircle from '~/components/StatusCircle';
|
||||
@ -21,6 +20,7 @@ import { Machine } from '~/types';
|
||||
import cn from '~/utils/cn';
|
||||
import { useLiveData } from '~/utils/live-data';
|
||||
import log from '~/utils/log';
|
||||
import toast from '~/utils/toast';
|
||||
|
||||
export async function loader({
|
||||
request,
|
||||
@ -152,20 +152,19 @@ export default function Page() {
|
||||
}
|
||||
>
|
||||
<Button
|
||||
variant="heavy"
|
||||
className={cn(
|
||||
'my-4 px-0 w-full pointer-events-none',
|
||||
'hover:bg-initial focus:ring-0',
|
||||
)}
|
||||
>
|
||||
<Code
|
||||
isCopyable
|
||||
className="bg-transparent pointer-events-auto mx-0"
|
||||
className="flex text-md font-mono"
|
||||
onPress={async () => {
|
||||
await navigator.clipboard.writeText(
|
||||
'curl -fsSL https://tailscale.com/install.sh | sh',
|
||||
);
|
||||
|
||||
toast('Copied to clipboard');
|
||||
}}
|
||||
>
|
||||
curl -fsSL https://tailscale.com/install.sh | sh
|
||||
</Code>
|
||||
</Button>
|
||||
<p className="text-end text-sm">
|
||||
<p className="text-xs mt-1 text-headplane-600 dark:text-headplane-300 text-center">
|
||||
Click this button to copy the command.{' '}
|
||||
<Link
|
||||
name="Linux installation script"
|
||||
to="https://github.com/tailscale/tailscale/blob/main/scripts/installer.sh"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user