mirror of
https://github.com/netbirdio/netbird.git
synced 2026-05-21 08:09:55 +00:00
wip
This commit is contained in:
@@ -7,6 +7,7 @@ import { VerticalTabs } from "@/components/VerticalTabs.tsx";
|
||||
import { SettingsNavigationTriggers } from "@/modules/settings/SettingsNavigationTriggers.tsx";
|
||||
import { SettingsProvider } from "@/modules/settings/SettingsContext.tsx";
|
||||
import { SettingsGeneral } from "@/modules/settings/SettingsGeneral.tsx";
|
||||
import { SettingsAppearance } from "@/modules/settings/SettingsAppearance.tsx";
|
||||
import { SettingsNetwork } from "@/modules/settings/SettingsNetwork.tsx";
|
||||
import { SettingsSecurity } from "@/modules/settings/SettingsSecurity.tsx";
|
||||
import { SettingsSSH } from "@/modules/settings/SettingsSSH.tsx";
|
||||
@@ -14,15 +15,35 @@ import { SettingsAdvanced } from "@/modules/settings/SettingsAdvanced.tsx";
|
||||
import { SettingsTroubleshooting } from "@/modules/settings/SettingsTroubleshooting.tsx";
|
||||
import { SettingsAbout } from "@/modules/settings/SettingsAbout.tsx";
|
||||
|
||||
const LAST_TAB_KEY = "netbird:settings:lastTab";
|
||||
|
||||
const readLastTab = () => {
|
||||
try {
|
||||
return localStorage.getItem(LAST_TAB_KEY);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
export const Settings = () => {
|
||||
const location = useLocation();
|
||||
const navState = location.state as { tab?: string } | null;
|
||||
const [active, setActive] = useState(navState?.tab ?? "general");
|
||||
const [active, setActive] = useState(
|
||||
() => navState?.tab ?? readLastTab() ?? "general",
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (navState?.tab) setActive(navState.tab);
|
||||
}, [navState?.tab, location.key]);
|
||||
|
||||
useEffect(() => {
|
||||
try {
|
||||
localStorage.setItem(LAST_TAB_KEY, active);
|
||||
} catch {
|
||||
// ignore quota / unavailable storage
|
||||
}
|
||||
}, [active]);
|
||||
|
||||
return (
|
||||
<VerticalTabs value={active} onValueChange={setActive} className={"p-4"}>
|
||||
<SettingsNavigationTriggers />
|
||||
@@ -37,6 +58,9 @@ export const Settings = () => {
|
||||
<VerticalTabs.Content value={"general"}>
|
||||
<SettingsGeneral />
|
||||
</VerticalTabs.Content>
|
||||
<VerticalTabs.Content value={"appearance"}>
|
||||
<SettingsAppearance />
|
||||
</VerticalTabs.Content>
|
||||
<VerticalTabs.Content value={"network"}>
|
||||
<SettingsNetwork />
|
||||
</VerticalTabs.Content>
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
import FancyToggleSwitch from "@/components/FancyToggleSwitch";
|
||||
import { CardSelect } from "@/components/CardSelect.tsx";
|
||||
import { SectionGroup } from "@/modules/settings/SettingsSection.tsx";
|
||||
import {
|
||||
useAppearance,
|
||||
type AppearanceView,
|
||||
} from "@/modules/appearance/AppearanceContext.tsx";
|
||||
import simpleScreen from "@/assets/screens/simple.png";
|
||||
import advancedScreen from "@/assets/screens/advanced.png";
|
||||
|
||||
const ScreenPreview = ({ src, alt }: { src: string; alt: string }) => (
|
||||
<img
|
||||
src={src}
|
||||
alt={alt}
|
||||
draggable={false}
|
||||
className={"h-full w-full object-contain select-none"}
|
||||
/>
|
||||
);
|
||||
|
||||
export function SettingsAppearance() {
|
||||
const {
|
||||
view,
|
||||
setView,
|
||||
showPeersNav,
|
||||
showResourcesNav,
|
||||
showExitNodeNav,
|
||||
showProfileSelector,
|
||||
showSettingsButton,
|
||||
setField,
|
||||
} = useAppearance();
|
||||
|
||||
return (
|
||||
<>
|
||||
<SectionGroup title={"View"}>
|
||||
<CardSelect
|
||||
value={view}
|
||||
onChange={(v) => setView(v as AppearanceView)}
|
||||
>
|
||||
<CardSelect.Option
|
||||
value={"default"}
|
||||
title={"Simple"}
|
||||
description={"Streamlined view with essential controls."}
|
||||
preview={<ScreenPreview src={simpleScreen} alt={"Simple view"} />}
|
||||
/>
|
||||
<CardSelect.Option
|
||||
value={"advanced"}
|
||||
title={"Advanced"}
|
||||
description={"All details and power-user options visible."}
|
||||
preview={<ScreenPreview src={advancedScreen} alt={"Advanced view"} />}
|
||||
/>
|
||||
</CardSelect>
|
||||
</SectionGroup>
|
||||
|
||||
<SectionGroup title={"Interface"}>
|
||||
<FancyToggleSwitch
|
||||
value={showPeersNav}
|
||||
onChange={(v) => setField("showPeersNav", v)}
|
||||
label={"Peers"}
|
||||
helpText={"Show the Peers item in the side navigation."}
|
||||
/>
|
||||
<FancyToggleSwitch
|
||||
value={showResourcesNav}
|
||||
onChange={(v) => setField("showResourcesNav", v)}
|
||||
label={"Resources"}
|
||||
helpText={"Show the Resources item in the side navigation."}
|
||||
/>
|
||||
<FancyToggleSwitch
|
||||
value={showExitNodeNav}
|
||||
onChange={(v) => setField("showExitNodeNav", v)}
|
||||
label={"Exit Node"}
|
||||
helpText={"Show the active exit node in the side navigation."}
|
||||
/>
|
||||
<FancyToggleSwitch
|
||||
value={showProfileSelector}
|
||||
onChange={(v) => setField("showProfileSelector", v)}
|
||||
label={"Profile Selector"}
|
||||
helpText={"Show the profile selector in the header."}
|
||||
/>
|
||||
<FancyToggleSwitch
|
||||
value={showSettingsButton}
|
||||
onChange={(v) => setField("showSettingsButton", v)}
|
||||
label={"Settings Button"}
|
||||
helpText={"Show the settings button in the header."}
|
||||
/>
|
||||
</SectionGroup>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
ShieldIcon,
|
||||
SlidersHorizontalIcon,
|
||||
SquareTerminalIcon,
|
||||
SwatchBookIcon,
|
||||
} from "lucide-react";
|
||||
|
||||
export const SettingsNavigationTriggers = () => {
|
||||
@@ -29,6 +30,11 @@ export const SettingsNavigationTriggers = () => {
|
||||
icon={SlidersHorizontalIcon}
|
||||
title={"General"}
|
||||
/>
|
||||
<VerticalTabs.Trigger
|
||||
value={"appearance"}
|
||||
icon={SwatchBookIcon}
|
||||
title={"Appearance"}
|
||||
/>
|
||||
<VerticalTabs.Trigger
|
||||
value={"network"}
|
||||
icon={NetworkIcon}
|
||||
|
||||
Reference in New Issue
Block a user