From f1819e59b97d0e5459d520fced8383317d504dce Mon Sep 17 00:00:00 2001 From: Henry Dollman Date: Sun, 14 Jul 2024 23:39:51 -0400 Subject: [PATCH] updates --- main.go | 4 +- site/bun.lockb | Bin 138541 -> 141686 bytes site/package.json | 91 +++++----- site/src/components/add-server.tsx | 17 +- site/src/components/charts/cpu-chart.tsx | 2 +- site/src/components/charts/radial.tsx | 93 +++++++++++ site/src/components/command-palette.tsx | 1 - site/src/components/example-chart.tsx | 53 ------ site/src/components/loader.tsx | 0 site/src/components/logo.tsx | 4 +- site/src/components/routes/server.tsx | 55 ++++-- .../components/server-table/systems-table.tsx | 56 +++++-- site/src/components/ui/select.tsx | 158 ++++++++++++++++++ site/src/components/ui/separator.tsx | 29 ++++ site/src/components/ui/switch.tsx | 27 +++ site/src/main.tsx | 2 +- site/src/types.d.ts | 47 ++++-- 17 files changed, 488 insertions(+), 151 deletions(-) create mode 100644 site/src/components/charts/radial.tsx delete mode 100644 site/src/components/example-chart.tsx delete mode 100644 site/src/components/loader.tsx create mode 100644 site/src/components/ui/select.tsx create mode 100644 site/src/components/ui/separator.tsx create mode 100644 site/src/components/ui/switch.tsx diff --git a/main.go b/main.go index c5c8e87..4e99ab9 100644 --- a/main.go +++ b/main.go @@ -390,8 +390,8 @@ func handleStatusAlerts(newStatus string, oldRecord *models.Record) error { // send alert sendAlert(EmailData{ to: user.Get("email").(string), - subj: fmt.Sprintf("Server %s is %s %v", systemName, alertStatus, emoji), - body: fmt.Sprintf("Server %s is %s %v", systemName, alertStatus, emoji), + subj: fmt.Sprintf("Connection to %s is %s %v", systemName, alertStatus, emoji), + body: fmt.Sprintf("Connection to %s is %s %v\n\n- Qoma", systemName, alertStatus, emoji), }) } return nil diff --git a/site/bun.lockb b/site/bun.lockb index eb6ce562af69ad33eeb98f61b859a6395433da5c..1f21930ef45038ef0e7b2758e768eba75444c9d2 100755 GIT binary patch delta 22419 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 QL1$0om>PS7&cpJ50q05p{{R30 delta 20833 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 diff --git a/site/package.json b/site/package.json index 16b5a3a..0874a10 100644 --- a/site/package.json +++ b/site/package.json @@ -1,46 +1,49 @@ { - "name": "site", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build": "vite build", - "preview": "vite preview" - }, - "dependencies": { - "@nanostores/react": "^0.7.2", - "@nanostores/router": "^0.15.0", - "@radix-ui/react-alert-dialog": "^1.1.1", - "@radix-ui/react-dialog": "^1.1.1", - "@radix-ui/react-dropdown-menu": "^2.1.1", - "@radix-ui/react-label": "^2.1.0", - "@radix-ui/react-slot": "^1.1.0", - "@radix-ui/react-toast": "^1.2.1", - "@radix-ui/react-tooltip": "^1.1.2", - "@tanstack/react-table": "^8.19.2", - "@vitejs/plugin-react": "^4.3.1", - "class-variance-authority": "^0.7.0", - "clsx": "^2.1.1", - "cmdk": "^1.0.0", - "lucide-react": "^0.407.0", - "nanostores": "^0.10.3", - "pocketbase": "^0.21.3", - "react": "^18.3.1", - "react-dom": "^18.3.1", - "recharts": "^2.13.0-alpha.1", - "tailwind-merge": "^2.4.0", - "tailwindcss-animate": "^1.0.7", - "valibot": "^0.36.0" - }, - "devDependencies": { - "@types/bun": "^1.1.6", - "@types/react": "^18.3.3", - "@types/react-dom": "^18.3.0", - "autoprefixer": "^10.4.19", - "postcss": "^8.4.39", - "tailwindcss": "^3.4.4", - "typescript": "^5.5.3", - "vite": "^5.3.3" - } + "name": "site", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "@nanostores/react": "^0.7.2", + "@nanostores/router": "^0.15.0", + "@radix-ui/react-alert-dialog": "^1.1.1", + "@radix-ui/react-dialog": "^1.1.1", + "@radix-ui/react-dropdown-menu": "^2.1.1", + "@radix-ui/react-label": "^2.1.0", + "@radix-ui/react-select": "^2.1.1", + "@radix-ui/react-separator": "^1.1.0", + "@radix-ui/react-slot": "^1.1.0", + "@radix-ui/react-switch": "^1.1.0", + "@radix-ui/react-toast": "^1.2.1", + "@radix-ui/react-tooltip": "^1.1.2", + "@tanstack/react-table": "^8.19.2", + "@vitejs/plugin-react": "^4.3.1", + "class-variance-authority": "^0.7.0", + "clsx": "^2.1.1", + "cmdk": "^1.0.0", + "lucide-react": "^0.407.0", + "nanostores": "^0.10.3", + "pocketbase": "^0.21.3", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "recharts": "^2.13.0-alpha.1", + "tailwind-merge": "^2.4.0", + "tailwindcss-animate": "^1.0.7", + "valibot": "^0.36.0" + }, + "devDependencies": { + "@types/bun": "^1.1.6", + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", + "autoprefixer": "^10.4.19", + "postcss": "^8.4.39", + "tailwindcss": "^3.4.4", + "typescript": "^5.5.3", + "vite": "^5.3.3" + } } diff --git a/site/src/components/add-server.tsx b/site/src/components/add-server.tsx index bf4dbb7..e233e6e 100644 --- a/site/src/components/add-server.tsx +++ b/site/src/components/add-server.tsx @@ -52,15 +52,18 @@ export function AddServerButton() { e.preventDefault() const formData = new FormData(e.target as HTMLFormElement) const data = Object.fromEntries(formData) as Record - data.status = 'down' - data.stats = { - c: 0, - d: 0, - dp: 0, - du: 0, + data.status = 'pending' + data.info = { + cpu: 0, m: 0, - mp: 0, mu: 0, + mp: 0, + mb: 0, + d: 0, + du: 0, + dp: 0, + dr: 0, + dw: 0, } as SystemStats try { setOpen(false) diff --git a/site/src/components/charts/cpu-chart.tsx b/site/src/components/charts/cpu-chart.tsx index 7319a25..6ee3ac3 100644 --- a/site/src/components/charts/cpu-chart.tsx +++ b/site/src/components/charts/cpu-chart.tsx @@ -51,7 +51,7 @@ export default function CpuChart({ chartData }: { chartData: { time: string; cpu /> + + Radial Chart - Stacked + January - June 2024 + + + + + } /> + + + + + + + + +
+ Trending up by 5.2% this month +
+
+ Showing total visitors for the last 6 months +
+
+ + ) +} diff --git a/site/src/components/command-palette.tsx b/site/src/components/command-palette.tsx index b756609..925c993 100644 --- a/site/src/components/command-palette.tsx +++ b/site/src/components/command-palette.tsx @@ -97,7 +97,6 @@ export default function CommandPalette() { Admin { window.location.href = '/_/#/settings/backups' }} diff --git a/site/src/components/example-chart.tsx b/site/src/components/example-chart.tsx deleted file mode 100644 index 5fbb4a6..0000000 --- a/site/src/components/example-chart.tsx +++ /dev/null @@ -1,53 +0,0 @@ -'use client' - -import { Bar, BarChart, CartesianGrid, XAxis } from 'recharts' - -import { - ChartConfig, - ChartContainer, - ChartLegend, - ChartLegendContent, - ChartTooltip, - ChartTooltipContent, -} from '@/components/ui/chart' - -const chartData = [ - { month: 'January', desktop: 186, mobile: 80 }, - { month: 'February', desktop: 305, mobile: 200 }, - { month: 'March', desktop: 237, mobile: 120 }, - { month: 'April', desktop: 73, mobile: 190 }, - { month: 'May', desktop: 209, mobile: 130 }, - { month: 'June', desktop: 214, mobile: 140 }, -] - -const chartConfig = { - desktop: { - label: 'Desktop', - color: '#2563eb', - }, - mobile: { - label: 'Mobile', - color: '#60a5fa', - }, -} satisfies ChartConfig - -export function Component() { - return ( - - - - value.slice(0, 3)} - /> - } /> - } /> - - - - - ) -} diff --git a/site/src/components/loader.tsx b/site/src/components/loader.tsx deleted file mode 100644 index e69de29..0000000 diff --git a/site/src/components/logo.tsx b/site/src/components/logo.tsx index a0bc5fe..b9ea42e 100644 --- a/site/src/components/logo.tsx +++ b/site/src/components/logo.tsx @@ -1,8 +1,8 @@ export function Logo({ className }: { className?: string }) { return ( // audiowide - - + + ) } diff --git a/site/src/components/routes/server.tsx b/site/src/components/routes/server.tsx index 7345bcd..097e941 100644 --- a/site/src/components/routes/server.tsx +++ b/site/src/components/routes/server.tsx @@ -9,7 +9,16 @@ import Spinner from '../spinner' // import DiskChart from '../charts/disk-chart' // import ContainerCpuChart from '../charts/container-cpu-chart' // import ContainerMemChart from '../charts/container-mem-chart' -import { CpuIcon, MemoryStickIcon } from 'lucide-react' +import { CpuIcon, MemoryStickIcon, ServerIcon } from 'lucide-react' +import { RadialChart } from '../charts/radial' +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/select' +import { Separator } from '@/components/ui/separator' const CpuChart = lazy(() => import('../charts/cpu-chart')) const ContainerCpuChart = lazy(() => import('../charts/container-cpu-chart')) @@ -87,7 +96,7 @@ export default function ServerDetail({ name }: { name: string }) { const memData = [] as { time: string; mem: number; memUsed: number; memCache: number }[] const diskData = [] as { time: string; disk: number; diskUsed: number }[] for (let { created, stats } of serverStats) { - cpuData.push({ time: created, cpu: stats.c }) + cpuData.push({ time: created, cpu: stats.cpu }) // maxCpu = Math.max(maxCpu, stats.c) memData.push({ time: created, mem: stats.m, memUsed: stats.mu, memCache: stats.mb }) diskData.push({ time: created, disk: stats.d, diskUsed: stats.du }) @@ -135,18 +144,32 @@ export default function ServerDetail({ name }: { name: string }) { containerCpuData.push(cpuData) containerMemData.push(memData) } + // console.log('containerMemData', containerMemData) setContainerCpuChartData(containerCpuData.reverse()) setContainerMemChartData(containerMemData.reverse()) }, [containers]) return ( <> -
-
-

{name}

-
- +
+ + {name} + + +

{server.status}

+

Uptime {(server.info?.u / 86400).toLocaleString()} days

+

+ {server.info?.m} ({server.info?.c} cores / {server.info?.t} threads) +

+
+
+ + + + + + Total CPU Usage @@ -162,8 +185,8 @@ export default function ServerDetail({ name }: { name: string }) { {containerCpuChartData.length > 0 && ( - - + + Docker CPU Usage @@ -177,8 +200,8 @@ export default function ServerDetail({ name }: { name: string }) { )} - - + + Total Memory Usage Precise utilization at the recorded time @@ -189,8 +212,8 @@ export default function ServerDetail({ name }: { name: string }) { {containerMemChartData.length > 0 && ( - - + + Docker Memory Usage @@ -199,13 +222,13 @@ export default function ServerDetail({ name }: { name: string }) { }> - {server?.stats?.m && } + )} - - + + Disk Usage Precise usage at the recorded time diff --git a/site/src/components/server-table/systems-table.tsx b/site/src/components/server-table/systems-table.tsx index 7bd04de..d8f3e62 100644 --- a/site/src/components/server-table/systems-table.tsx +++ b/site/src/components/server-table/systems-table.tsx @@ -57,7 +57,7 @@ import { Trash2Icon, BellIcon, } from 'lucide-react' -import { useMemo, useState } from 'react' +import { useEffect, useMemo, useState } from 'react' import { $servers, pb, navigate } from '@/lib/stores' import { useStore } from '@nanostores/react' import { AddServerButton } from '../add-server' @@ -70,6 +70,8 @@ import { DialogTitle, DialogHeader, } from '@/components/ui/dialog' +import { Switch } from '@/components/ui/switch' +import { Separator } from '../ui/separator' function CellFormatter(info: CellContext) { const val = info.getValue() as number @@ -105,10 +107,13 @@ function sortableHeader(column: Column, name: string, Ico export default function SystemsTable() { const data = useStore($servers) - // const [deleteServer, setDeleteServer] = useState({} as SystemRecord) const [sorting, setSorting] = useState([]) const [columnFilters, setColumnFilters] = useState([]) + // useEffect(() => { + // console.log('servers', data) + // }, [data]) + const columns: ColumnDef[] = useMemo(() => { return [ { @@ -124,7 +129,8 @@ export default function SystemsTable() { className={cn('w-2 h-2 left-0 rounded-full', { 'bg-green-500': status === 'up', 'bg-red-500': status === 'down', - 'bg-yellow-500': status === 'paused', + 'bg-primary/40': status === 'paused', + 'bg-yellow-500': status === 'pending', })} style={{ marginBottom: '-1px' }} > @@ -143,17 +149,17 @@ export default function SystemsTable() { header: ({ column }) => sortableHeader(column, 'Server', Server), }, { - accessorKey: 'stats.c', + accessorKey: 'info.cpu', cell: CellFormatter, header: ({ column }) => sortableHeader(column, 'CPU', Cpu), }, { - accessorKey: 'stats.mp', + accessorKey: 'info.mp', cell: CellFormatter, header: ({ column }) => sortableHeader(column, 'Memory', MemoryStick), }, { - accessorKey: 'stats.dp', + accessorKey: 'info.dp', cell: CellFormatter, header: ({ column }) => sortableHeader(column, 'Disk', HardDrive), }, @@ -167,18 +173,44 @@ export default function SystemsTable() {
- - Notifications + Alerts for {name} + {isAdmin() && ( + + Please{' '} + + configure an SMTP server + {' '} + to ensure alerts are delivered. + + )} - The agent must be running on the server to connect. Copy the{' '} - docker-compose.yml for the - agent below. +
+
+ +

+ Triggers when system status switches between up and down. +

+
+ +
@@ -202,7 +234,7 @@ export default function SystemsTable() { { pb.collection('systems').update(id, { - status: status === 'paused' ? 'up' : 'paused', + status: status === 'paused' ? 'pending' : 'paused', }) }} > diff --git a/site/src/components/ui/select.tsx b/site/src/components/ui/select.tsx new file mode 100644 index 0000000..fe56d4d --- /dev/null +++ b/site/src/components/ui/select.tsx @@ -0,0 +1,158 @@ +import * as React from "react" +import * as SelectPrimitive from "@radix-ui/react-select" +import { Check, ChevronDown, ChevronUp } from "lucide-react" + +import { cn } from "@/lib/utils" + +const Select = SelectPrimitive.Root + +const SelectGroup = SelectPrimitive.Group + +const SelectValue = SelectPrimitive.Value + +const SelectTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + span]:line-clamp-1", + className + )} + {...props} + > + {children} + + + + +)) +SelectTrigger.displayName = SelectPrimitive.Trigger.displayName + +const SelectScrollUpButton = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)) +SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName + +const SelectScrollDownButton = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)) +SelectScrollDownButton.displayName = + SelectPrimitive.ScrollDownButton.displayName + +const SelectContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, position = "popper", ...props }, ref) => ( + + + + + {children} + + + + +)) +SelectContent.displayName = SelectPrimitive.Content.displayName + +const SelectLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +SelectLabel.displayName = SelectPrimitive.Label.displayName + +const SelectItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + + {children} + +)) +SelectItem.displayName = SelectPrimitive.Item.displayName + +const SelectSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +SelectSeparator.displayName = SelectPrimitive.Separator.displayName + +export { + Select, + SelectGroup, + SelectValue, + SelectTrigger, + SelectContent, + SelectLabel, + SelectItem, + SelectSeparator, + SelectScrollUpButton, + SelectScrollDownButton, +} diff --git a/site/src/components/ui/separator.tsx b/site/src/components/ui/separator.tsx new file mode 100644 index 0000000..6d7f122 --- /dev/null +++ b/site/src/components/ui/separator.tsx @@ -0,0 +1,29 @@ +import * as React from "react" +import * as SeparatorPrimitive from "@radix-ui/react-separator" + +import { cn } from "@/lib/utils" + +const Separator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>( + ( + { className, orientation = "horizontal", decorative = true, ...props }, + ref + ) => ( + + ) +) +Separator.displayName = SeparatorPrimitive.Root.displayName + +export { Separator } diff --git a/site/src/components/ui/switch.tsx b/site/src/components/ui/switch.tsx new file mode 100644 index 0000000..aa58baa --- /dev/null +++ b/site/src/components/ui/switch.tsx @@ -0,0 +1,27 @@ +import * as React from "react" +import * as SwitchPrimitives from "@radix-ui/react-switch" + +import { cn } from "@/lib/utils" + +const Switch = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)) +Switch.displayName = SwitchPrimitives.Root.displayName + +export { Switch } diff --git a/site/src/main.tsx b/site/src/main.tsx index 112ceb7..50678d8 100644 --- a/site/src/main.tsx +++ b/site/src/main.tsx @@ -124,7 +124,7 @@ const Layout = () => { { e.preventDefault() navigate('/') diff --git a/site/src/types.d.ts b/site/src/types.d.ts index fab340d..65c5d4d 100644 --- a/site/src/types.d.ts +++ b/site/src/types.d.ts @@ -3,28 +3,51 @@ import { RecordModel } from 'pocketbase' export interface SystemRecord extends RecordModel { name: string host: string - status: 'up' | 'down' | 'paused' + status: 'up' | 'down' | 'paused' | 'pending' port: string - stats: SystemStats + info: SystemInfo +} + +export interface SystemInfo { + /** cpu percent */ + cpu: number + /** cpu threads */ + t: number + /** cpu cores */ + c: number + /** cpu model */ + m: string + /** operating system */ + o?: string + /** uptime */ + u: number + /** memory percent */ + mp: number + /** disk percent */ + dp: number } export interface SystemStats { /** cpu percent */ - c: number - /** disk size (gb) */ - d: number - /** disk percent */ - dp: number - /** disk used (gb) */ - du: number + cpu: number /** total memory (gb) */ m: number + /** memory used (gb) */ + mu: number /** memory percent */ mp: number /** memory buffer + cache (gb) */ mb: number - /** memory used (gb) */ - mu: number + /** disk size (gb) */ + d: number + /** disk used (gb) */ + du: number + /** disk percent */ + dp: number + /** disk read (mb) */ + dr: number + /** disk write (mb) */ + dw: number } export interface ContainerStatsRecord extends RecordModel { @@ -43,5 +66,5 @@ interface ContainerStats { export interface SystemStatsRecord extends RecordModel { system: string - stats: SystemStats + info: SystemStats }