mirror of
https://github.com/netbirdio/netbird.git
synced 2026-05-12 03:39:55 +00:00
add setting
This commit is contained in:
69
client/ui-wails/frontend/settings.md
Normal file
69
client/ui-wails/frontend/settings.md
Normal file
@@ -0,0 +1,69 @@
|
||||
1. General
|
||||
|
||||
The "old tray" toggles + notifications. This is what 90% of users come to Settings for.
|
||||
|
||||
- Connect on startup — disableAutoConnect (inverted)
|
||||
- Allow SSH — serverSshAllowed (master switch; the SSH tab is the detail)
|
||||
- Quantum-resistance — rosenpassEnabled
|
||||
- Nested when on: Permissive mode — rosenpassPermissive
|
||||
- Lazy connections — lazyConnectionEnabled
|
||||
- Block inbound — blockInbound
|
||||
- Show notifications — disableNotifications (inverted)
|
||||
|
||||
▎ Note: blockInbound is technically a firewall behavior, but Stage 1 explicitly groups it with the tray-replacement toggles. Keep it here.
|
||||
|
||||
2. Connection
|
||||
|
||||
Identity + how the wire is established. The "what server am I talking to and how" tab.
|
||||
|
||||
- Management URL — managementUrl
|
||||
- Pre-shared key — preSharedKey (password input, toggle reveal)
|
||||
- Advanced (collapsed by default)
|
||||
- Admin URL — adminUrl
|
||||
- Interface name — interfaceName
|
||||
- WireGuard port — wireguardPort
|
||||
- MTU — mtu
|
||||
|
||||
3. Network
|
||||
|
||||
Routing / DNS / LAN behavior — i.e. what the daemon does to the host network.
|
||||
|
||||
- Network monitor — networkMonitor
|
||||
- Disable DNS — disableDns
|
||||
- Disable client routes — disableClientRoutes
|
||||
- Disable server routes — disableServerRoutes
|
||||
- Block LAN access — blockLanAccess
|
||||
|
||||
4. SSH
|
||||
|
||||
Detailed SSH server config. Greyed out with an inline notice ("Enable Allow SSH in General to configure") when serverSshAllowed is off.
|
||||
|
||||
- SSH root login — enableSshRoot
|
||||
- SFTP — enableSshSftp
|
||||
- Local port forwarding — enableSshLocalPortForwarding
|
||||
- Remote port forwarding — enableSshRemotePortForwarding
|
||||
- Advanced (collapsed)
|
||||
- Disable SSH auth — disableSshAuth
|
||||
- JWT cache TTL — sshJwtCacheTtl
|
||||
|
||||
5. Diagnostics
|
||||
|
||||
Everything you reach for when something is wrong. Mixes config (log level) with actions (bundle creation) deliberately — they're used together.
|
||||
|
||||
- Log level — Debug / Info / Warn / Error (dropdown)
|
||||
- Log file path — read-only, with Copy + Reveal in Finder/Explorer buttons (configFile / logFile from daemon)
|
||||
- Config file path — same pattern
|
||||
- Debug bundle (own section)
|
||||
- Anonymize toggle
|
||||
- Include system info toggle
|
||||
- Upload on create toggle → reveals URL field when on
|
||||
- Create Bundle button → progress indicator → resulting path or upload URL displayed below
|
||||
|
||||
6. About
|
||||
|
||||
Version + update flow + identity reference.
|
||||
|
||||
- App version, daemon version
|
||||
- Check for Updates button → drives the auto-update flow (15-min timeout, success/error states)
|
||||
- Local peer info quick-reference (FQDN, IP) — same data the connection-state view shows
|
||||
- Links: docs, GitHub repo, license
|
||||
@@ -1,8 +1,7 @@
|
||||
export default function PlaceholderHeader() {
|
||||
return (
|
||||
<div
|
||||
className="h-[36px] shrink-0 cursor-default"
|
||||
style={{ "--wails-draggable": "drag" } as React.CSSProperties}
|
||||
className="h-[36px] shrink-0 cursor-default wails-draggable"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ export const ProfileSelector = ({ email = "" }: Props) => {
|
||||
<button
|
||||
type="button"
|
||||
className={
|
||||
"h-11 rounded-md text-nb-gray-300 flex items-center gap-1 text-xs hover:bg-nb-gray-930 data-[state=open]:bg-nb-gray-930 px-2 -mx-2 outline-none cursor-default transition-colors duration-150"
|
||||
"h-11 rounded-md text-nb-gray-300 flex items-center gap-1 text-xs hover:bg-nb-gray-930 data-[state=open]:bg-nb-gray-930 px-2 -mx-1 outline-none cursor-default transition-colors duration-150"
|
||||
}
|
||||
>
|
||||
<div
|
||||
|
||||
@@ -19,3 +19,11 @@ body,
|
||||
body {
|
||||
@apply bg-nb-gray font-sans text-nb-gray-200 antialiased;
|
||||
}
|
||||
|
||||
.wails-draggable {
|
||||
--wails-draggable: drag;
|
||||
}
|
||||
|
||||
.wails-no-draggable {
|
||||
--wails-draggable: no-drag;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,25 @@
|
||||
import { ProfileSelector } from "@/components/ProfileSelector.tsx";
|
||||
import { IconButton } from "@/components/IconButton.tsx";
|
||||
import { SettingsIcon } from "lucide-react";
|
||||
import { cn } from "@/lib/cn";
|
||||
|
||||
export const Header = () => {
|
||||
type Props = {
|
||||
settingsActive?: boolean;
|
||||
onSettingsClick?: () => void;
|
||||
};
|
||||
|
||||
export const Header = ({ settingsActive = false, onSettingsClick }: Props) => {
|
||||
return (
|
||||
<div className={"w-full justify-between flex mb-12"}>
|
||||
<ProfileSelector />
|
||||
<IconButton icon={SettingsIcon} />
|
||||
<ProfileSelector email={"eduard@netbird.io"} />
|
||||
<IconButton
|
||||
icon={SettingsIcon}
|
||||
onClick={onSettingsClick}
|
||||
className={cn(
|
||||
settingsActive &&
|
||||
"bg-nb-gray-930 text-nb-gray-200 hover:text-nb-gray-200",
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
32
client/ui-wails/frontend/src/layouts/MainLeftSide.tsx
Normal file
32
client/ui-wails/frontend/src/layouts/MainLeftSide.tsx
Normal file
@@ -0,0 +1,32 @@
|
||||
import { ConnectionStatus } from "@/layouts/ConnectionStatus.tsx";
|
||||
import { Header } from "@/layouts/Header.tsx";
|
||||
import { Navigation } from "@/layouts/Navigation.tsx";
|
||||
|
||||
export type MainModule = "peers" | "settings";
|
||||
|
||||
type Props = {
|
||||
active: MainModule;
|
||||
onChange: (module: MainModule) => void;
|
||||
};
|
||||
|
||||
export const MainLeftSide = ({ active, onChange }: Props) => {
|
||||
return (
|
||||
<div
|
||||
className={"flex flex-col max-w-xs w-full shrink-0 items-center"}
|
||||
>
|
||||
<Header
|
||||
settingsActive={active === "settings"}
|
||||
onSettingsClick={() =>
|
||||
onChange(active === "settings" ? "peers" : "settings")
|
||||
}
|
||||
/>
|
||||
<ConnectionStatus />
|
||||
<Navigation
|
||||
peersActive={active === "peers"}
|
||||
onPeersClick={() => {
|
||||
if (active !== "peers") onChange("peers");
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
15
client/ui-wails/frontend/src/layouts/MainRightSide.tsx
Normal file
15
client/ui-wails/frontend/src/layouts/MainRightSide.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import { ReactNode } from "react";
|
||||
|
||||
type Props = {
|
||||
children: ReactNode;
|
||||
};
|
||||
|
||||
export const MainRightSide = ({ children }: Props) => {
|
||||
return (
|
||||
<div
|
||||
className={"wails-no-draggable flex-1 min-h-0 min-w-0 flex flex-col bg-nb-gray-935 rounded-xl rounded-br-2xl border border-nb-gray-900"}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -5,14 +5,20 @@ import {
|
||||
SquareArrowUpRight,
|
||||
} from "lucide-react";
|
||||
|
||||
export const Navigation = () => {
|
||||
type Props = {
|
||||
peersActive?: boolean;
|
||||
onPeersClick?: () => void;
|
||||
};
|
||||
|
||||
export const Navigation = ({ peersActive = false, onPeersClick }: Props) => {
|
||||
return (
|
||||
<nav className={"w-full flex flex-col gap-1 mt-8"}>
|
||||
<NavItem
|
||||
icon={MonitorSmartphoneIcon}
|
||||
title={"Peers"}
|
||||
description={"13 of 16 Online"}
|
||||
active
|
||||
active={peersActive}
|
||||
onClick={onPeersClick}
|
||||
/>
|
||||
<NavItem
|
||||
icon={Layers3Icon}
|
||||
|
||||
@@ -8,7 +8,7 @@ import { PeersList } from "./PeersList";
|
||||
|
||||
const isOnline = (status: string) => status === "connected";
|
||||
|
||||
export const PeersModule = () => {
|
||||
export const Peers = () => {
|
||||
const [search, setSearch] = useState("");
|
||||
const [statusFilter, setStatusFilter] = useState<StatusFilter>("all");
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
export const Settings = () => {
|
||||
return (
|
||||
<div className={"flex flex-col w-full h-full min-h-0 pt-4 px-4"}>
|
||||
<h2 className={"text-sm font-medium text-nb-gray-200"}>Settings</h2>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1,23 +1,22 @@
|
||||
import { ConnectionStatus } from "@/layouts/ConnectionStatus.tsx";
|
||||
import { Header } from "@/layouts/Header.tsx";
|
||||
import { Navigation } from "@/layouts/Navigation.tsx";
|
||||
import { PeersModule } from "@/modules/peers/PeersModule.tsx";
|
||||
import { useState } from "react";
|
||||
import { MainLeftSide, MainModule } from "@/layouts/MainLeftSide.tsx";
|
||||
import { MainRightSide } from "@/layouts/MainRightSide.tsx";
|
||||
import { Peers } from "@/modules/peers/Peers.tsx";
|
||||
import { Settings } from "@/modules/settings/Settings.tsx";
|
||||
|
||||
type Props = {
|
||||
|
||||
};
|
||||
export const Main = ({}: Props) => {
|
||||
return (
|
||||
<div className={"flex h-full p-4 gap-4 min-h-0"}>
|
||||
<div className={"flex flex-col max-w-xs w-full shrink-0 items-center"}>
|
||||
<Header />
|
||||
<ConnectionStatus />
|
||||
<Navigation />
|
||||
</div>
|
||||
const [active, setActive] = useState<MainModule>("peers");
|
||||
|
||||
<div className={"flex-1 min-h-0 min-w-0 flex flex-col bg-nb-gray-935 rounded-xl border border-nb-gray-900"}>
|
||||
<PeersModule />
|
||||
</div>
|
||||
return (
|
||||
<div className={"wails-draggable flex h-full p-4 gap-4 min-h-0"}>
|
||||
<MainLeftSide active={active} onChange={setActive} />
|
||||
|
||||
<MainRightSide>
|
||||
{active === "peers" ? <Peers /> : <Settings />}
|
||||
</MainRightSide>
|
||||
</div>
|
||||
|
||||
);
|
||||
|
||||
@@ -103,9 +103,9 @@ func main() {
|
||||
window := app.Window.NewWithOptions(application.WebviewWindowOptions{
|
||||
Title: "NetBird",
|
||||
Width: 880,
|
||||
Height: 620,
|
||||
Height: 520,
|
||||
MinWidth: 880,
|
||||
MinHeight: 620,
|
||||
MinHeight: 520,
|
||||
Hidden: false,
|
||||
BackgroundColour: application.NewRGB(24, 26, 29),
|
||||
URL: "/",
|
||||
|
||||
Reference in New Issue
Block a user