Update hosts form

This commit is contained in:
2026-09-20 13:48:35 +01:00
parent a9ebd8fb75
commit 3c1d2b61f6
20 changed files with 308 additions and 66 deletions
@@ -86,13 +86,13 @@ export default function EditHostFormSection() {
</P>
</Stack>
<HostWgIpField
{/* <HostWgIpField
value={wgIP}
onChange={setWgIP}
onStatus={setIpStatus}
current_value={host?.wg_ip_address || ""}
autoFocus
/>
/> */}
{status?.error && status.msg ? (
<Tag
@@ -139,4 +139,4 @@ export default function EditHostFormSection() {
/>
</>
);
}
}
@@ -24,6 +24,9 @@ export default async function submitAddHostForm({
wg_ip_address: form.wg_ip_address || "",
public_ip_address: form.public_ip_address || "",
interface: form.interface || "",
name: form.name || "",
short_description: form.short_description || "",
listen_port: form.listen_port != null ? Number(form.listen_port) : null,
},
},
);
@@ -0,0 +1,26 @@
import Stack from "@/src/components/twui/layout/Stack";
import useFormInit from "@/src/hooks/use-form-init";
import type { BUN_SQLITE_WGUI_HOSTS } from "@/db/types/db";
import Textarea from "@/src/components/twui/form/Textarea";
type Props = ReturnType<typeof useFormInit<BUN_SQLITE_WGUI_HOSTS>>;
export default function AddHostFormDescription({ form, setForm }: Props) {
return (
<Stack className="w-full gap-2">
<Textarea
name="short_description"
label="Short Description"
showLabel
placeholder="e.g. Main server at home"
defaultValue={form.short_description || ""}
changeHandler={(v) => {
setForm((prev) => ({
...prev,
short_description: v,
}));
}}
/>
</Stack>
);
}
@@ -0,0 +1,70 @@
import { useState } from "react";
import Input from "@/src/components/twui/form/Input";
import Button from "@/src/components/twui/layout/Button";
import Stack from "@/src/components/twui/layout/Stack";
import Row from "@/src/components/twui/layout/Row";
import useFormInit from "@/src/hooks/use-form-init";
import { AppData } from "@/src/data/app-data";
import fetchApi from "@/src/components/twui/utils/fetch/fetchApi";
import type { ApiReqParams } from "@/src/types";
import type { APIResponseObject } from "@moduletrace/bunext/types";
import type { BUN_SQLITE_WGUI_HOSTS } from "@/db/types/db";
type Props = ReturnType<typeof useFormInit<BUN_SQLITE_WGUI_HOSTS>>;
export default function AddHostFormListenPort({ form, setForm }: Props) {
const [busy, setBusy] = useState(false);
async function handleGrabNext() {
setBusy(true);
try {
const res = await fetchApi<ApiReqParams, APIResponseObject>(
"/api/admin/next-listen-port",
{ method: "GET" },
);
if (res.success && res.numberRes) {
setForm((prev) => ({
...prev,
listen_port: Number(res.numberRes),
}));
}
} catch {
} finally {
setBusy(false);
}
}
return (
<Stack className="w-full gap-2">
<Row className="w-full items-stretch gap-3 md:flex-nowrap">
<Input
name="listen_port"
label="Listen Port"
showLabel
placeholder={String(AppData["DefaultWGListenPort"])}
value={
form.listen_port != null ? String(form.listen_port) : ""
}
numberText
rawNumber
changeHandler={(v) => {
setForm((prev) => ({
...prev,
listen_port: Number(v) || undefined,
}));
}}
/>
<Button
title="Grab Next Port"
size="small"
variant="outlined"
disabled={busy}
loading={busy}
onClick={handleGrabNext}
>
{busy ? "Fetching…" : "Grab Next"}
</Button>
</Row>
</Stack>
);
}
@@ -0,0 +1,26 @@
import Input from "@/src/components/twui/form/Input";
import Stack from "@/src/components/twui/layout/Stack";
import useFormInit from "@/src/hooks/use-form-init";
import type { BUN_SQLITE_WGUI_HOSTS } from "@/db/types/db";
type Props = ReturnType<typeof useFormInit<BUN_SQLITE_WGUI_HOSTS>>;
export default function AddHostFormName({ form, setForm }: Props) {
return (
<Stack className="w-full gap-2">
<Input
name="name"
label="Host Name"
showLabel
placeholder="e.g. my-server"
defaultValue={form.name || ""}
changeHandler={(v) => {
setForm((prev) => ({
...prev,
name: v,
}));
}}
/>
</Stack>
);
}
@@ -12,6 +12,9 @@ import AddHostFormSubnet from "./add-host-form-subnet";
import AddHostFormWgIpAddress from "./add-host-form-wg-ip-address";
import AddHostFormPublicIP from "./add-host-form-public-ip";
import AddHostFormInterface from "./add-host-form-interface";
import AddHostFormName from "./add-host-form-name";
import AddHostFormDescription from "./add-host-form-description";
import AddHostFormListenPort from "./add-host-form-listen-port";
import LoadingRectangleBlock from "@/src/components/twui/layout/LoadingRectangleBlock";
import type { HostWgIpFieldStatus } from "@/src/components/general/host-wg-ip-field";
@@ -19,17 +22,21 @@ export default function AddHostForm() {
const init = useFormInit<BUN_SQLITE_WGUI_HOSTS>({
default: {
wg_ip_address: AppData["DefaultPrivateIP"],
name: "Main",
},
title: "Add Host",
title: "new_host",
async before_ready_function(params) {
if (!params.form.interface) {
params.setForm((prev) => ({
...prev,
interface:
params.app_context.pageProps?.network_interfaces?.[0] ||
undefined,
}));
}
params.setForm((prev) => ({
...prev,
interface:
params.form.interface ||
params.app_context.pageProps?.network_interfaces?.[0] ||
undefined,
listen_port:
params.form.listen_port ||
params.app_context.pageProps?.next_listen_port ||
undefined,
}));
},
});
@@ -49,7 +56,10 @@ export default function AddHostForm() {
{init.ready ? (
<Stack className="w-full gap-6 items-stretch">
{/* <AddHostFormSubnet /> */}
<AddHostFormName {...init} />
<AddHostFormDescription {...init} />
<AddHostFormInterface {...init} />
<AddHostFormListenPort {...init} />
<AddHostFormPublicIP {...init} />
<AddHostFormWgIpAddress
{...init}
@@ -1,10 +1,9 @@
import AdminCard from "@/src/components/general/admin-card";
import AddHostForm from "../(partials)/add-host-form/add-host-form";
export default function AddHostFormSection() {
return (
<AdminCard className="w-full p-5 flex flex-col gap-4">
<>
<AddHostForm />
</AdminCard>
</>
);
}
}
@@ -1,13 +1,16 @@
import getNextAvailableListenPort from "@/src/functions/backend/setup/get-next-available-listen-port";
import grabHostNetworkInterfaces from "@/src/functions/backend/setup/grab-host-network-interfaces";
import type { PagePropsType } from "@/src/types";
import type { BunextPageServerFn } from "@moduletrace/bunext/types";
const server: BunextPageServerFn<PagePropsType> = async ({ req }) => {
const network_interfaces = await grabHostNetworkInterfaces();
const next_listen_port = await getNextAvailableListenPort();
return {
props: {
network_interfaces,
next_listen_port,
},
};
};
+20 -12
View File
@@ -51,6 +51,14 @@ export default function AdminHostPage() {
description="WireGuard server configuration and interface details"
buttons={
<>
<Button
title="View Hosts"
variant="outlined"
href="/admin/hosts"
color="gray"
>
View Hosts
</Button>
<Button
title="Add New Host"
variant="outlined"
@@ -107,18 +115,18 @@ export default function AdminHostPage() {
{other_hosts[0] ? (
<Stack className="w-full gap-4 items-stretch">
{other_hosts.map((host) => (
<OtherHostCard
key={host.id}
host={host}
client_count={
clients?.filter(
(client) =>
(client.host_id || 0) ==
(host.id || 0),
).length || 0
}
/>
))}
<OtherHostCard
key={host.id}
host={host}
client_count={
clients?.filter(
(client) =>
(client.host_id || 0) ==
(host.id || 0),
).length || 0
}
/>
))}
</Stack>
) : (
<EmptyContent title="No other hosts found" />