Update routes

This commit is contained in:
2026-10-21 13:34:25 +01:00
parent 42feb73264
commit 2cc876b062
4 changed files with 125 additions and 11 deletions
@@ -1,4 +1,7 @@
import type { BUN_SQLITE_WGUI_CLIENT_ROUTES } from "@/db/types/db"; import type {
BUN_SQLITE_WGUI_CLIENT_ROUTES,
BUN_SQLITE_WGUI_HOSTS,
} from "@/db/types/db";
import type { ClientRouteView } from "@/src/functions/backend/acme/decorate-client-route"; import type { ClientRouteView } from "@/src/functions/backend/acme/decorate-client-route";
import type { ClientRouteFormObject } from "./types"; import type { ClientRouteFormObject } from "./types";
import Form from "@/src/components/twui/form/Form"; import Form from "@/src/components/twui/form/Form";
@@ -12,22 +15,31 @@ import FormSection from "../form-section";
import FormActions from "../form-actions"; import FormActions from "../form-actions";
import InlineAlert from "../inline-alert"; import InlineAlert from "../inline-alert";
import submitClientRouteForm from "./submit-client-route-form"; import submitClientRouteForm from "./submit-client-route-form";
import { useContext } from "react"; import { useContext, useRef, useState } from "react";
import { AppContext } from "@/src/pages/__root"; import { AppContext } from "@/src/pages/__root";
import { useAdminCrudGet } from "@/src/hooks/use-admin-crud-get";
import Select from "../../twui/form/Select";
import adminCrudHandler from "@/src/functions/frontend/admin-crud-handler";
import EmptyContent from "../../twui/elements/EmptyContent";
import twuiNumberfy from "../../twui/utils/numberfy";
type Props = { type Props = {
host_id: number; host_id?: number;
existing_route?: ClientRouteView; existing_route?: ClientRouteView;
cancel_href: string;
}; };
export default function ClientRouteForm({ export default function ClientRouteForm({
host_id, host_id: passed_host_id,
existing_route, existing_route,
cancel_href,
}: Props) { }: Props) {
const { confirm } = useConfirm(); const { confirm } = useConfirm();
const { user } = useContext(AppContext); const { user, pageProps } = useContext(AppContext);
const [host_id, set_host_id] = useState(
passed_host_id || pageProps?.host?.id || pageProps?.hosts?.[0]?.id,
);
const is_host_id_present = typeof host_id == "number";
const init = useFormInit<ClientRouteFormObject>({ const init = useFormInit<ClientRouteFormObject>({
existing: existing_route, existing: existing_route,
@@ -53,18 +65,33 @@ export default function ClientRouteForm({
return <LoadingBlock className="h-[420px]" />; return <LoadingBlock className="h-[420px]" />;
} }
if (!pageProps?.hosts?.[0]) {
return (
<EmptyContent title="No hosts added. Please Add a host to continue" />
);
}
const cancel_href = is_host_id_present
? `/admin/hosts/${host_id}/routes`
: `/admin/routes`;
return ( return (
<Panel> <Panel>
<Form <Form
className="w-full gap-0" className="w-full gap-0"
onSubmit={() => onSubmit={() => {
if (typeof host_id !== "number") {
window.alert(`Host ID is required!`);
return;
}
submitClientRouteForm({ submitClientRouteForm({
init, init,
host_id, host_id,
cancel_href,
confirm, confirm,
}) cancel_href,
} });
}}
> >
{status?.error ? ( {status?.error ? (
<InlineAlert <InlineAlert
@@ -74,6 +101,20 @@ export default function ClientRouteForm({
/> />
) : null} ) : null}
<FormSection title="Host" description="The host for this route">
<Select
options={
pageProps.hosts.map((h) => ({
value: String(h.id),
default: h.id == host_id,
title: h.name,
})) || []
}
changeHandler={(value) => {
set_host_id(twuiNumberfy(value));
}}
/>
</FormSection>
<FormSection <FormSection
title="Route" title="Route"
description="The public hostname and path Caddy matches." description="The public hostname and path Caddy matches."
@@ -0,0 +1,41 @@
import type { BUN_SQLITE_WGUI_HOSTS } from "@/db/types/db";
import { AppData } from "@/src/data/app-data";
import type { PagePropsType, TableType } from "@/src/types";
import BunSQLite from "@moduletrace/bun-sqlite";
import type { BunextPageServerFn } from "@moduletrace/bunext/types";
const server: BunextPageServerFn<PagePropsType> = async (ctx) => {
const props = ctx.props as PagePropsType;
if (!props.main_host?.name) {
return {
redirect: {
destination: `/admin/hosts/add`,
permanent: false,
},
};
}
const hosts_res = await BunSQLite.select<BUN_SQLITE_WGUI_HOSTS, TableType>({
table: "hosts",
});
const hosts = hosts_res.payload || [];
const requested_id = Number(ctx.url.searchParams.get("host_id"));
const host =
hosts.find((h) => Number(h.id) === requested_id) ||
hosts.find((h) => Number(h.id) === AppData["WireguardMainHostID"]) ||
hosts[0] ||
null;
return {
props: {
hosts,
host,
},
};
};
export default server;
+25
View File
@@ -0,0 +1,25 @@
import type { BunextPageModuleMeta } from "@moduletrace/bunext/types";
import PageHeader from "@/src/components/general/page-header";
import PageBody from "@/src/components/general/page-body";
import { SiteData } from "@/src/data/site-data";
import ClientRouteForm from "@/src/components/general/client-route-form";
export default function AddClientPage() {
return (
<>
<PageHeader
title="Add Route"
description="Add a Client Route"
back={{ href: "/admin/routes", title: "Routes" }}
/>
<PageBody>
<ClientRouteForm />
</PageBody>
</>
);
}
export const meta: BunextPageModuleMeta = {
title: `Add client route | ${SiteData["SiteName"]}`,
description: `Add a Caddy route config to a Wireguard host`,
};
+7
View File
@@ -3,6 +3,7 @@ import PageHeader from "@/src/components/general/page-header";
import PageBody from "@/src/components/general/page-body"; import PageBody from "@/src/components/general/page-body";
import ClientRoutesPanel from "@/src/components/general/client-routes-panel"; import ClientRoutesPanel from "@/src/components/general/client-routes-panel";
import { SiteData } from "@/src/data/site-data"; import { SiteData } from "@/src/data/site-data";
import { Plus } from "lucide-react";
export default function RoutesPage() { export default function RoutesPage() {
return ( return (
@@ -10,6 +11,12 @@ export default function RoutesPage() {
<PageHeader <PageHeader
title="Routes" title="Routes"
description="HTTPS services exposed to WireGuard clients, with their host and certificate status." description="HTTPS services exposed to WireGuard clients, with their host and certificate status."
primary_action={{
key: "add-client-route",
title: "Add Route",
href: "/admin/routes/add",
icon: <Plus size={14} />,
}}
/> />
<PageBody> <PageBody>
<ClientRoutesPanel <ClientRoutesPanel