diff --git a/app/routes/_data.dns._index/magic.tsx b/app/routes/_data.dns._index/magic.tsx index d4eabac..317893e 100644 --- a/app/routes/_data.dns._index/magic.tsx +++ b/app/routes/_data.dns._index/magic.tsx @@ -1,6 +1,7 @@ import { useFetcher } from '@remix-run/react' import Button from '~/components/Button' +// TODO: Remove useModal and replace with Dialog import useModal from '~/components/Modal' import Spinner from '~/components/Spinner' diff --git a/app/routes/_data.dns._index/rename.tsx b/app/routes/_data.dns._index/rename.tsx index b4e0ee3..c29792e 100644 --- a/app/routes/_data.dns._index/rename.tsx +++ b/app/routes/_data.dns._index/rename.tsx @@ -1,6 +1,5 @@ /* eslint-disable @typescript-eslint/naming-convention */ /* eslint-disable unicorn/no-keyword-prefix */ -import { Dialog } from '@headlessui/react' import { useFetcher } from '@remix-run/react' import { useState } from 'react' diff --git a/app/routes/_data.machines._index/route.tsx b/app/routes/_data.machines._index/route.tsx index 4862455..767ba8f 100644 --- a/app/routes/_data.machines._index/route.tsx +++ b/app/routes/_data.machines._index/route.tsx @@ -1,17 +1,13 @@ - -/* eslint-disable @typescript-eslint/no-non-null-assertion */ - import { InformationCircleIcon } from '@heroicons/react/24/outline' import { type ActionFunctionArgs, json, type LoaderFunctionArgs } from '@remix-run/node' import { useFetcher, useLoaderData } from '@remix-run/react' -import clsx from 'clsx' import { Button, Tooltip, TooltipTrigger } from 'react-aria-components' import Code from '~/components/Code' -import useModal from '~/components/Modal' import { type Machine } from '~/types' +import { cn } from '~/utils/cn' import { getConfig, getContext } from '~/utils/config' -import { del, pull } from '~/utils/headscale' +import { del, post, pull } from '~/utils/headscale' import { getSession } from '~/utils/sessions' import { useLiveData } from '~/utils/useLiveData' @@ -20,6 +16,7 @@ import MachineRow from './machine' export async function loader({ request }: LoaderFunctionArgs) { const session = await getSession(request.headers.get('Cookie')) + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const data = await pull<{ nodes: Machine[] }>('v1/node', session.get('hsApiKey')!) const context = await getContext() @@ -38,13 +35,6 @@ export async function loader({ request }: LoaderFunctionArgs) { } export async function action({ request }: ActionFunctionArgs) { - const data = await request.json() as { id?: string } - if (!data.id) { - return json({ message: 'No ID provided' }, { - status: 400 - }) - } - const session = await getSession(request.headers.get('Cookie')) if (!session.has('hsApiKey')) { return json({ message: 'Unauthorized' }, { @@ -52,8 +42,43 @@ export async function action({ request }: ActionFunctionArgs) { }) } - await del(`v1/node/${data.id}`, session.get('hsApiKey')!) - return json({ message: 'Machine removed' }) + const data = await request.formData() + if (!data.has('_method') || !data.has('id')) { + return json({ message: 'No method or ID provided' }, { + status: 400 + }) + } + + const id = String(data.get('id')) + const method = String(data.get('_method')) + + switch (method) { + case 'delete': { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + await del(`v1/node/${id}`, session.get('hsApiKey')!) + return json({ message: 'Machine removed' }) + } + + case 'rename': { + if (!data.has('name')) { + return json({ message: 'No name provided' }, { + status: 400 + }) + } + + const name = String(data.get('name')) + + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + await post(`v1/node/${id}/rename/${name}`, session.get('hsApiKey')!) + return json({ message: 'Machine renamed' }) + } + + default: { + return json({ message: 'Invalid method' }, { + status: 400 + }) + } + } } export default function Page() { @@ -61,11 +86,8 @@ export default function Page() { const data = useLoaderData() const fetcher = useFetcher() - const { Modal, open } = useModal() - return ( <> - {Modal}

Machines

@@ -79,7 +101,7 @@ export default function Page() { - Last Seen - ))} diff --git a/app/routes/_data.tsx b/app/routes/_data.tsx index f94ae14..9f6fb6c 100644 --- a/app/routes/_data.tsx +++ b/app/routes/_data.tsx @@ -2,8 +2,8 @@ import { Cog8ToothIcon, CpuChipIcon, GlobeAltIcon, LockClosedIcon, ServerStackIc import { type LoaderFunctionArgs, redirect } from '@remix-run/node' import { Form, Outlet, useLoaderData, useRouteError } from '@remix-run/react' -import Dropdown from '~/components/Dropdown' import { ErrorPopup } from '~/components/Error' +import Menu from '~/components/Menu' import TabLink from '~/components/TabLink' import { getContext } from '~/utils/config' import { HeadscaleError, pull } from '~/utils/headscale' @@ -62,21 +62,24 @@ export default function Layout() { Headscale - } - > - -

{data.user?.name}

-

{data.user?.email}

-
- -
- - -
-
+ + + + + + +

{data.user?.name}

+

{data.user?.email}

+
+ +
+ + +
+
+