mirror of
https://github.com/tale/headplane.git
synced 2026-08-28 16:07:07 +00:00
chore: type fixes
This commit is contained in:
+20
-20
@@ -42,8 +42,6 @@ function TabLink({ name, to, icon }: TabLinkProps) {
|
|||||||
return (
|
return (
|
||||||
<div className="relative py-2">
|
<div className="relative py-2">
|
||||||
<NavLink
|
<NavLink
|
||||||
to={to}
|
|
||||||
prefetch="intent"
|
|
||||||
className={({ isActive }) =>
|
className={({ isActive }) =>
|
||||||
cn(
|
cn(
|
||||||
'px-3 py-2 flex items-center rounded-md text-nowrap gap-x-2.5',
|
'px-3 py-2 flex items-center rounded-md text-nowrap gap-x-2.5',
|
||||||
@@ -54,6 +52,8 @@ function TabLink({ name, to, icon }: TabLinkProps) {
|
|||||||
isActive ? 'after:visible' : 'after:invisible',
|
isActive ? 'after:visible' : 'after:invisible',
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
prefetch="intent"
|
||||||
|
to={to}
|
||||||
>
|
>
|
||||||
{icon} {name}
|
{icon} {name}
|
||||||
</NavLink>
|
</NavLink>
|
||||||
@@ -64,13 +64,13 @@ function TabLink({ name, to, icon }: TabLinkProps) {
|
|||||||
function Link({ href, text }: LinkProps) {
|
function Link({ href, text }: LinkProps) {
|
||||||
return (
|
return (
|
||||||
<a
|
<a
|
||||||
href={href}
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer"
|
|
||||||
className={cn(
|
className={cn(
|
||||||
'hidden sm:block hover:underline text-sm',
|
'hidden sm:block hover:underline text-sm',
|
||||||
'focus:outline-hidden focus:ring-3 rounded-md',
|
'focus:outline-hidden focus:ring-3 rounded-md',
|
||||||
)}
|
)}
|
||||||
|
href={href}
|
||||||
|
rel="noreferrer"
|
||||||
|
target="_blank"
|
||||||
>
|
>
|
||||||
{text}
|
{text}
|
||||||
</a>
|
</a>
|
||||||
@@ -101,20 +101,21 @@ export default function Header(data: Props) {
|
|||||||
{data.user ? (
|
{data.user ? (
|
||||||
<Menu>
|
<Menu>
|
||||||
<Menu.IconButton
|
<Menu.IconButton
|
||||||
label="User"
|
|
||||||
className={cn(data.user.picture ? 'p-0' : '')}
|
className={cn(data.user.picture ? 'p-0' : '')}
|
||||||
|
label="User"
|
||||||
>
|
>
|
||||||
{data.user.picture ? (
|
{data.user.picture ? (
|
||||||
<img
|
<img
|
||||||
src={data.user.picture}
|
alt={data.user.name}
|
||||||
alt={data.user.name || data.user.displayName}
|
|
||||||
className="w-8 h-8 rounded-full"
|
className="w-8 h-8 rounded-full"
|
||||||
|
src={data.user.picture}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<CircleUser />
|
<CircleUser />
|
||||||
)}
|
)}
|
||||||
</Menu.IconButton>
|
</Menu.IconButton>
|
||||||
<Menu.Panel
|
<Menu.Panel
|
||||||
|
disabledKeys={['profile']}
|
||||||
onAction={(key) => {
|
onAction={(key) => {
|
||||||
if (key === 'logout') {
|
if (key === 'logout') {
|
||||||
submit(
|
submit(
|
||||||
@@ -126,12 +127,11 @@ export default function Header(data: Props) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
disabledKeys={['profile']}
|
|
||||||
>
|
>
|
||||||
<Menu.Section>
|
<Menu.Section>
|
||||||
<Menu.Item key="profile" textValue="Profile">
|
<Menu.Item key="profile" textValue="Profile">
|
||||||
<div className="text-black dark:text-headplane-50">
|
<div className="text-black dark:text-headplane-50">
|
||||||
<p className="font-bold">{data.user.name || data.user.displayName}</p>
|
<p className="font-bold">{data.user.name}</p>
|
||||||
<p>{data.user.email}</p>
|
<p>{data.user.email}</p>
|
||||||
</div>
|
</div>
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
@@ -148,39 +148,39 @@ export default function Header(data: Props) {
|
|||||||
<nav className="container flex items-center gap-x-4 overflow-x-auto font-semibold">
|
<nav className="container flex items-center gap-x-4 overflow-x-auto font-semibold">
|
||||||
{data.access.machines ? (
|
{data.access.machines ? (
|
||||||
<TabLink
|
<TabLink
|
||||||
to="/machines"
|
|
||||||
name="Machines"
|
|
||||||
icon={<Server className="w-5" />}
|
icon={<Server className="w-5" />}
|
||||||
|
name="Machines"
|
||||||
|
to="/machines"
|
||||||
/>
|
/>
|
||||||
) : undefined}
|
) : undefined}
|
||||||
{data.access.users ? (
|
{data.access.users ? (
|
||||||
<TabLink
|
<TabLink
|
||||||
to="/users"
|
|
||||||
name="Users"
|
|
||||||
icon={<Users className="w-5" />}
|
icon={<Users className="w-5" />}
|
||||||
|
name="Users"
|
||||||
|
to="/users"
|
||||||
/>
|
/>
|
||||||
) : undefined}
|
) : undefined}
|
||||||
{data.access.policy ? (
|
{data.access.policy ? (
|
||||||
<TabLink
|
<TabLink
|
||||||
to="/acls"
|
|
||||||
name="Access Control"
|
|
||||||
icon={<Lock className="w-5" />}
|
icon={<Lock className="w-5" />}
|
||||||
|
name="Access Control"
|
||||||
|
to="/acls"
|
||||||
/>
|
/>
|
||||||
) : undefined}
|
) : undefined}
|
||||||
{data.configAvailable ? (
|
{data.configAvailable ? (
|
||||||
<>
|
<>
|
||||||
{data.access.dns ? (
|
{data.access.dns ? (
|
||||||
<TabLink
|
<TabLink
|
||||||
to="/dns"
|
|
||||||
name="DNS"
|
|
||||||
icon={<Globe2 className="w-5" />}
|
icon={<Globe2 className="w-5" />}
|
||||||
|
name="DNS"
|
||||||
|
to="/dns"
|
||||||
/>
|
/>
|
||||||
) : undefined}
|
) : undefined}
|
||||||
{data.access.settings ? (
|
{data.access.settings ? (
|
||||||
<TabLink
|
<TabLink
|
||||||
to="/settings"
|
|
||||||
name="Settings"
|
|
||||||
icon={<Settings className="w-5" />}
|
icon={<Settings className="w-5" />}
|
||||||
|
name="Settings"
|
||||||
|
to="/settings"
|
||||||
/>
|
/>
|
||||||
) : undefined}
|
) : undefined}
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -17,8 +17,12 @@ export default function AuthKeyRow({ authKey, user, url }: Props) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<Attribute name="Key" value={authKey.key} isCopyable />
|
<Attribute isCopyable name="Key" value={authKey.key} />
|
||||||
<Attribute name="User" value={user.name || user.displayName} isCopyable />
|
<Attribute
|
||||||
|
isCopyable
|
||||||
|
name="User"
|
||||||
|
value={user.name || user.displayName || user.email || user.id}
|
||||||
|
/>
|
||||||
<Attribute name="Reusable" value={authKey.reusable ? 'Yes' : 'No'} />
|
<Attribute name="Reusable" value={authKey.reusable ? 'Yes' : 'No'} />
|
||||||
<Attribute name="Ephemeral" value={authKey.ephemeral ? 'Yes' : 'No'} />
|
<Attribute name="Ephemeral" value={authKey.ephemeral ? 'Yes' : 'No'} />
|
||||||
<Attribute name="Used" value={authKey.used ? 'Yes' : 'No'} />
|
<Attribute name="Used" value={authKey.used ? 'Yes' : 'No'} />
|
||||||
@@ -30,13 +34,12 @@ export default function AuthKeyRow({ authKey, user, url }: Props) {
|
|||||||
<Code className="text-sm">
|
<Code className="text-sm">
|
||||||
tailscale up --login-server={url} --authkey {authKey.key}
|
tailscale up --login-server={url} --authkey {authKey.key}
|
||||||
</Code>
|
</Code>
|
||||||
<div suppressHydrationWarning className="flex gap-4 items-center">
|
<div className="flex gap-4 items-center" suppressHydrationWarning>
|
||||||
{(authKey.used && !authKey.reusable) ||
|
{(authKey.used && !authKey.reusable) ||
|
||||||
new Date(authKey.expiration) < new Date() ? undefined : (
|
new Date(authKey.expiration) < new Date() ? undefined : (
|
||||||
<ExpireAuthKey authKey={authKey} user={user} />
|
<ExpireAuthKey authKey={authKey} user={user} />
|
||||||
)}
|
)}
|
||||||
<Button
|
<Button
|
||||||
variant="light"
|
|
||||||
className="my-4"
|
className="my-4"
|
||||||
onPress={async () => {
|
onPress={async () => {
|
||||||
await navigator.clipboard.writeText(
|
await navigator.clipboard.writeText(
|
||||||
@@ -45,6 +48,7 @@ export default function AuthKeyRow({ authKey, user, url }: Props) {
|
|||||||
|
|
||||||
toast('Copied command to clipboard');
|
toast('Copied command to clipboard');
|
||||||
}}
|
}}
|
||||||
|
variant="light"
|
||||||
>
|
>
|
||||||
Copy Tailscale Command
|
Copy Tailscale Command
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
Reference in New Issue
Block a user