feat: add basic machine page
This commit is contained in:
parent
9594468bf4
commit
fdc3cdde39
32
src/lib/components/Attribute.svelte
Normal file
32
src/lib/components/Attribute.svelte
Normal file
@ -0,0 +1,32 @@
|
||||
<script lang="ts">
|
||||
import { IconCopy } from "@tabler/icons-svelte";
|
||||
import { toast } from "@zerodevx/svelte-toast";
|
||||
import clsx from "clsx";
|
||||
export let key: string;
|
||||
export let value: string;
|
||||
export let copyable = false;
|
||||
</script>
|
||||
|
||||
<dl class="flex gap-1 text-sm">
|
||||
<dt class="w-1/3 sm:w-1/4 lg:w-1/3 shrink-0 min-w-0 truncate text-gray-700">
|
||||
{key}
|
||||
</dt>
|
||||
{#if copyable}
|
||||
<button
|
||||
class="focus:outline-none flex items-center gap-x-1 truncate hover:bg-gray-100 rounded-md"
|
||||
on:click={() => {
|
||||
navigator.clipboard.writeText(value);
|
||||
toast.push("Copied " + key);
|
||||
}}
|
||||
>
|
||||
<dd class="min-w-0 truncate px-2 py-1">
|
||||
{value}
|
||||
</dd>
|
||||
<IconCopy stroke={1} size={24} class="text-gray-600 pr-2" />
|
||||
</button>
|
||||
{:else}
|
||||
<dd class="min-w-0 truncate px-2 py-1">
|
||||
{value}
|
||||
</dd>
|
||||
{/if}
|
||||
</dl>
|
||||
@ -12,7 +12,7 @@
|
||||
href={`${base}${to}`}
|
||||
class={clsx(
|
||||
"flex items-center gap-x-2 p-2 border-b-2 text-sm",
|
||||
$page.url.pathname === `${base}${to}`
|
||||
$page.url.pathname.startsWith(`${base}${to}`)
|
||||
? "border-white"
|
||||
: "border-transparent",
|
||||
)}
|
||||
|
||||
@ -17,9 +17,9 @@ export type Machine = {
|
||||
|
||||
createdAt: Date;
|
||||
registerMethod: 'REGISTER_METHOD_UNSPECIFIED'
|
||||
| 'REGISTER_METHOD_AUTH_KEY'
|
||||
| 'REGISTER_METHOD_CLI'
|
||||
| 'REGISTER_METHOD_OIDC'
|
||||
| 'REGISTER_METHOD_AUTH_KEY'
|
||||
| 'REGISTER_METHOD_CLI'
|
||||
| 'REGISTER_METHOD_OIDC'
|
||||
|
||||
forcedTags: string[];
|
||||
invalidTags: string[];
|
||||
|
||||
@ -36,10 +36,12 @@
|
||||
{#each $query.data as machine}
|
||||
<tr class="hover:bg-gray-100">
|
||||
<td class="pt-2 pb-4 pl-4">
|
||||
<h1>{machine.givenName}</h1>
|
||||
<span class="text-sm font-mono text-gray-500"
|
||||
>{machine.name}</span
|
||||
>
|
||||
<a href={`machines/${machine.id}`}>
|
||||
<h1>{machine.givenName}</h1>
|
||||
<span class="text-sm font-mono text-gray-500"
|
||||
>{machine.name}</span
|
||||
>
|
||||
</a>
|
||||
</td>
|
||||
<td class="pt-2 pb-4 font-mono text-gray-600">
|
||||
{#each machine.ipAddresses as ip, i}
|
||||
|
||||
78
src/routes/machines/[id]/+page.svelte
Normal file
78
src/routes/machines/[id]/+page.svelte
Normal file
@ -0,0 +1,78 @@
|
||||
<script lang="ts">
|
||||
import type { PageData } from "./$types";
|
||||
import { createQuery } from "@tanstack/svelte-query";
|
||||
import { pull } from "$lib/api";
|
||||
import type { Machine } from "$lib/types";
|
||||
import { IconCircleFilled, IconCopy } from "@tabler/icons-svelte";
|
||||
import Attribute from "$lib/components/Attribute.svelte";
|
||||
import clsx from "clsx";
|
||||
|
||||
export let data: PageData;
|
||||
const query = createQuery({
|
||||
queryKey: [`machines/${data.id}`],
|
||||
queryFn: async () => {
|
||||
const response = await pull<{ node: Machine }>(
|
||||
`v1/node/${data.id}`,
|
||||
);
|
||||
return response.node;
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>
|
||||
{$query.isSuccess ? `${$query.data.givenName} - Machines` : "Machines"}
|
||||
</title>
|
||||
</svelte:head>
|
||||
|
||||
{#if $query.isLoading}
|
||||
<p>Loading...</p>
|
||||
{:else if $query.isError}
|
||||
<p>Error: {$query.error.message}</p>
|
||||
{:else if $query.isSuccess}
|
||||
<div>
|
||||
<span class="flex items-baseline gap-x-4 text-sm mb-4">
|
||||
<h1 class="text-2xl font-bold">
|
||||
{$query.data.givenName}
|
||||
</h1>
|
||||
<IconCircleFilled
|
||||
stroke={1}
|
||||
size={24}
|
||||
class={clsx(
|
||||
"w-4 h-4",
|
||||
$query.data.online ? "text-green-700" : "text-gray-300",
|
||||
)}
|
||||
/>
|
||||
</span>
|
||||
<div
|
||||
class="p-4 md:p-6 border rounded-md grid grid-cols-1 lg:grid-cols-2 gap-y-2 sm:gap-x-12"
|
||||
>
|
||||
<Attribute key="Creator" value={$query.data.user.name} />
|
||||
<Attribute key="Node ID" value={$query.data.id} />
|
||||
<Attribute key="Node Name" value={$query.data.givenName} />
|
||||
<Attribute key="Hostname" value={$query.data.name} />
|
||||
<Attribute
|
||||
key="Node Key"
|
||||
value={$query.data.nodeKey}
|
||||
copyable={true}
|
||||
/>
|
||||
<Attribute
|
||||
key="Created"
|
||||
value={new Date($query.data.createdAt).toLocaleString()}
|
||||
/>
|
||||
<Attribute
|
||||
key="Last Seen"
|
||||
value={new Date($query.data.lastSeen).toLocaleString()}
|
||||
/>
|
||||
<Attribute
|
||||
key="Expiry"
|
||||
value={new Date($query.data.expiry).toLocaleString()}
|
||||
/>
|
||||
<Attribute
|
||||
key="Domain"
|
||||
value={`${$query.data.givenName}.${$query.data.user.name}.ts.net`}
|
||||
copyable={true}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
17
src/routes/machines/[id]/+page.ts
Normal file
17
src/routes/machines/[id]/+page.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { pull } from "$lib/api";
|
||||
import type { Machine } from "$lib/types";
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export async function load({ parent, params }: Parameters<PageLoad>[0]) {
|
||||
const { queryClient } = await parent();
|
||||
|
||||
await queryClient.prefetchQuery({
|
||||
queryKey: [`machines/${params.id}`],
|
||||
queryFn: async () => {
|
||||
const data = await pull<{ node: Machine }>(`v1/node/${params.id}`);
|
||||
return data.node;
|
||||
},
|
||||
});
|
||||
|
||||
return { id: params.id }
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user