Files
wireguard-ui/src/pages/admin/setup/(sections)/setup-actions-section.tsx
T
tbenandClaude Opus 5.5 cad1d32ae4 Redesign the frontend UI on twui
Rebuild every page on a shared set of twui-based primitives with a dense
ops-console look, WireGuard red accent and light/dark/system theming.

- Add design tokens (WireGuard red accent, zinc neutrals, theme-flipping
  semantic colours) and a no-flash theme cookie + toggle
- Add shared components: page header, panel, sub-nav, data table with
  mobile card list, stat tile, status dot, key-value list, copy button,
  inline alert, empty state, form section/actions, confirm dialog and
  toast providers
- New admin shell (sidebar, sticky header, mobile drawer) and a centered
  shell for auth and 404; strip the public template pages
- Unify adding clients at /admin/clients/add with a host picker; tabbed
  client detail (Overview / Rules / Config & QR) with config copy/download
- Re-run client setup after rule changes on the detail page so the
  firewall matches the DB
- Split Setup into status/maintenance/firewall and Settings into
  profile/password subpages
- Replace window.confirm/alert and page reloads with in-app dialogs,
  toasts and in-place list updates
- Fix nested rule form submitting the client form, prefilled signup
  passwords, hidden submit buttons, fields not updating after "next
  free" lookups, and TinyMCE white-on-white in dark mode

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-16 06:29:21 +01:00

73 lines
2.8 KiB
TypeScript

import { RotateCcw, Wrench } from "lucide-react";
import fetchApi from "@/src/components/twui/utils/fetch/fetchApi";
import Panel from "@/src/components/general/panel";
import type { ApiReqParams } from "@/src/types";
import type { APIResponseObject } from "@moduletrace/bunext/types";
import type useSystemSetupStatus from "../(hooks)/use-system-setup-status";
import SetupActionRow from "../(partials)/setup-action-row";
import SetupUpdateWgUiAction from "../(partials)/setup-update-wg-ui-action";
type Props = {
setup: ReturnType<typeof useSystemSetupStatus>;
};
const WG_TOOL_COMMANDS = [`wg`, `wg-quick`, `ip`, `curl`];
export default function SetupActionsSection({ setup }: Props) {
const setup_status = setup.setup_status;
if (!setup_status) {
return null;
}
const have_wg_tools = setup_status.tools
.filter((tool) => WG_TOOL_COMMANDS.includes(tool.command))
.every((tool) => tool.installed);
const show_restart = !setup_status.is_dev && setup_status.init_system !== "unknown";
return (
<Panel flush>
<SetupActionRow
title="WireGuard tools"
description="Installs or updates wg, wg-quick and iproute2 with your distro's package manager. Safe to re-run."
icon={<Wrench size={15} />}
button_title={have_wg_tools ? "Update tools" : "Install tools"}
on_run={async () => {
const res = await fetchApi<ApiReqParams, APIResponseObject>(
`/api/admin/setup-wireguard-tools`,
{ method: "POST" },
);
setup.refresh();
return res;
}}
/>
<SetupUpdateWgUiAction setup={setup} />
{show_restart ? (
<SetupActionRow
title="Restart service"
description={`Restarts the ${setup_status.service_name} system service. Use after manual changes.`}
icon={<RotateCcw size={15} />}
button_title="Restart"
confirm_params={{
title: "Restart wg-ui?",
message: `The ${setup_status.service_name} service restarts and this dashboard goes briefly offline.`,
confirm_label: "Restart service",
tone: "danger",
}}
on_run={async () => {
const res = await fetchApi<ApiReqParams, APIResponseObject>(
`/api/admin/restart-wg-ui-service`,
{ method: "POST" },
);
setup.refresh();
return res;
}}
/>
) : null}
</Panel>
);
}