From 3362a3d1cfae158d112e13a3b658dbfd08585fc0 Mon Sep 17 00:00:00 2001 From: Henry Dollman Date: Mon, 9 Sep 2024 20:00:09 -0400 Subject: [PATCH] progress on settings page --- beszel/site/src/components/router.tsx | 4 +- .../components/routes/settings/general.tsx | 46 +++++++++ .../src/components/routes/settings/layout.tsx | 71 ++++++++++++++ .../routes/settings/notifications.tsx | 98 +++++++++++++++++++ .../routes/settings/sidebar-nav.tsx | 40 ++++++++ beszel/site/src/main.tsx | 29 +++--- beszel/site/tailwind.config.js | 7 +- 7 files changed, 281 insertions(+), 14 deletions(-) create mode 100644 beszel/site/src/components/routes/settings/general.tsx create mode 100644 beszel/site/src/components/routes/settings/layout.tsx create mode 100644 beszel/site/src/components/routes/settings/notifications.tsx create mode 100644 beszel/site/src/components/routes/settings/sidebar-nav.tsx diff --git a/beszel/site/src/components/router.tsx b/beszel/site/src/components/router.tsx index 299710e..a77d7e9 100644 --- a/beszel/site/src/components/router.tsx +++ b/beszel/site/src/components/router.tsx @@ -4,7 +4,7 @@ export const $router = createRouter( { home: '/', server: '/system/:name', - 'forgot-password': '/forgot-password', + settings: '/settings/:name?', }, { links: false } ) @@ -16,7 +16,7 @@ export const navigate = (urlString: string) => { function onClick(e: React.MouseEvent) { e.preventDefault() - $router.open(new URL((e.target as HTMLAnchorElement).href).pathname) + $router.open(new URL((e.currentTarget as HTMLAnchorElement).href).pathname) } export const Link = (props: React.AnchorHTMLAttributes) => { diff --git a/beszel/site/src/components/routes/settings/general.tsx b/beszel/site/src/components/routes/settings/general.tsx new file mode 100644 index 0000000..71c9bfb --- /dev/null +++ b/beszel/site/src/components/routes/settings/general.tsx @@ -0,0 +1,46 @@ +import { Button } from '@/components/ui/button' +import { Label } from '@/components/ui/label' +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/select' +import { chartTimeData } from '@/lib/utils' +import { Separator } from '@/components/ui/separator' + +export default function SettingsProfilePage() { + return ( +
+ {/*
+

General

+

Set your preferred language and timezone.

+
+ */} +
+
+ + {/* */} + +

+ Sets the default time range for charts. +

+
+ + +
+
+ ) +} diff --git a/beszel/site/src/components/routes/settings/layout.tsx b/beszel/site/src/components/routes/settings/layout.tsx new file mode 100644 index 0000000..9f5b6dd --- /dev/null +++ b/beszel/site/src/components/routes/settings/layout.tsx @@ -0,0 +1,71 @@ +import { Suspense, lazy, useEffect } from 'react' +import { Separator } from '../../ui/separator' +import { SidebarNav } from './sidebar-nav.tsx' +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card.tsx' +import { useStore } from '@nanostores/react' +import { $router } from '@/components/router.tsx' +import { redirectPage } from '@nanostores/router' +import { BellIcon, SettingsIcon } from 'lucide-react' + +const General = lazy(() => import('./general.tsx')) +const Notifications = lazy(() => import('./notifications.tsx')) + +const sidebarNavItems = [ + { + title: 'General', + href: '/settings/general', + icon: SettingsIcon, + }, + { + title: 'Notifications', + href: '/settings/notifications', + icon: BellIcon, + }, +] + +export default function SettingsLayout() { + const page = useStore($router) + + useEffect(() => { + document.title = 'Settings / Beszel' + // redirect to account page if no page is specified + if (page?.path === '/settings') { + redirectPage($router, 'settings', { name: 'general' }) + } + }, []) + + return ( + + + Settings + Manage your account settings and set e-mail preferences. + + + +
+ +
+ + {/* @ts-ignore */} + + +
+
+
+
+ ) +} + +function SettingsContent({ name }: { name: string }) { + switch (name) { + case 'general': + return + // case 'display': + // return + case 'notifications': + return + } + return '' +} diff --git a/beszel/site/src/components/routes/settings/notifications.tsx b/beszel/site/src/components/routes/settings/notifications.tsx new file mode 100644 index 0000000..d340ea7 --- /dev/null +++ b/beszel/site/src/components/routes/settings/notifications.tsx @@ -0,0 +1,98 @@ +import { Button } from '@/components/ui/button' +import { Input } from '@/components/ui/input' +import { Label } from '@/components/ui/label' +import { pb } from '@/lib/stores' +import { Separator } from '@/components/ui/separator' +import { Card } from '@/components/ui/card' +// import { Switch } from '@/components/ui/switch' +import { Trash2Icon } from 'lucide-react' + +export default function SettingsNotificationsPage() { + return ( +
+ {/*
+

Notifications

+

Configure how you receive notifications.

+
+ */} +
+
+
+

Email notifications

+

+ Get notified when new alerts are created. +

+
+ + +

+ Separate multiple emails with commas. +

+
+ +
+
+

Webhook / Push notifications

+

+ Beszel uses{' '} + + Shoutrrr + {' '} + to integrate with popular notification services. +

+
+ +
+ + + + + {/* + */} +
+
+ +
+ + +
+
+ ) +} diff --git a/beszel/site/src/components/routes/settings/sidebar-nav.tsx b/beszel/site/src/components/routes/settings/sidebar-nav.tsx new file mode 100644 index 0000000..b627e9c --- /dev/null +++ b/beszel/site/src/components/routes/settings/sidebar-nav.tsx @@ -0,0 +1,40 @@ +import { cn } from '@/lib/utils' +import { buttonVariants } from '../../ui/button' +import { $router, Link } from '../../router' +import { useStore } from '@nanostores/react' +import React from 'react' + +interface SidebarNavProps extends React.HTMLAttributes { + items: { + href: string + title: string + icon?: React.FC> + }[] +} + +export function SidebarNav({ className, items, ...props }: SidebarNavProps) { + const page = useStore($router) + + return ( + + ) +} diff --git a/beszel/site/src/main.tsx b/beszel/site/src/main.tsx index f32ad68..2828171 100644 --- a/beszel/site/src/main.tsx +++ b/beszel/site/src/main.tsx @@ -1,5 +1,5 @@ import './index.css' -import React, { Suspense, lazy, useEffect } from 'react' +import { Suspense, lazy, useEffect } from 'react' import ReactDOM from 'react-dom/client' import Home from './components/routes/home.tsx' import { ThemeProvider } from './components/theme-provider.tsx' @@ -27,6 +27,7 @@ import { LogOutIcon, LogsIcon, ServerIcon, + SettingsIcon, UserIcon, UsersIcon, } from 'lucide-react' @@ -42,7 +43,7 @@ import { DropdownMenuTrigger, DropdownMenuLabel, } from './components/ui/dropdown-menu.tsx' -import { $router, Link, navigate } from './components/router.tsx' +import { $router, Link } from './components/router.tsx' import SystemDetail from './components/routes/system.tsx' import { AddSystemButton } from './components/add-system.tsx' @@ -50,6 +51,7 @@ import { AddSystemButton } from './components/add-system.tsx' const CommandPalette = lazy(() => import('./components/command-palette.tsx')) const LoginPage = lazy(() => import('./components/login/login.tsx')) const CopyToClipboardDialog = lazy(() => import('./components/copy-to-clipboard.tsx')) +const Settings = lazy(() => import('./components/routes/settings/layout.tsx')) const App = () => { const page = useStore($router) @@ -99,6 +101,12 @@ const App = () => { return } else if (page.route === 'server') { return + } else if (page.path.startsWith('/settings')) { + return ( + + + + ) } } @@ -118,20 +126,19 @@ const Layout = () => { <>
- { - e.preventDefault() - navigate('/') - }} - > +
+ + +