This commit is contained in:
Henry Dollman
2024-07-12 20:12:50 -04:00
parent 998fa6e03a
commit aacaf2f04f
17 changed files with 77 additions and 28 deletions

View File

@@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Home</title>
<title>Qoma</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 75.7 81.8"><path fill="#16a34a" d="M76 29v14a33 33 0 0 1-1 7 30 30 0 0 1-1 2 29 29 0 0 1-3 7 27 27 0 0 1 0 1 27 27 0 0 1-6 6 27 27 0 0 1-7 4l14 12H54L42 72H29a32 32 0 0 1-8-1 29 29 0 0 1-3-1q-6-2-10-6a28 28 0 0 1-6-10 30 30 0 0 1-2-9 35 35 0 0 1 0-2V29a32 32 0 0 1 1-8 28 28 0 0 1 1-3 28 28 0 0 1 5-9 27 27 0 0 1 1-1 28 28 0 0 1 10-6 32 32 0 0 1 0 0 30 30 0 0 1 9-2 35 35 0 0 1 2 0h17a32 32 0 0 1 9 1 28 28 0 0 1 3 1 28 28 0 0 1 9 6 27 27 0 0 1 6 9 31 31 0 0 1 0 1 30 30 0 0 1 3 9 35 35 0 0 1 0 2ZM63 43V29a20 20 0 0 0 0-4 17 17 0 0 0-1-3 15 15 0 0 0-3-4 14 14 0 0 0-1-1 15 15 0 0 0-4-3 17 17 0 0 0-1 0 17 17 0 0 0-5-1 21 21 0 0 0-2 0H29a20 20 0 0 0-4 0 17 17 0 0 0-2 1l-6 3a15 15 0 0 0-3 5 17 17 0 0 0 0 0 17 17 0 0 0-1 5 22 22 0 0 0 0 2v14a20 20 0 0 0 0 4 17 17 0 0 0 1 2 15 15 0 0 0 3 5 14 14 0 0 0 0 1 15 15 0 0 0 5 3 17 17 0 0 0 1 0 17 17 0 0 0 4 1 21 21 0 0 0 2 0h17a20 20 0 0 0 4 0 17 17 0 0 0 3-1l5-3a15 15 0 0 0 4-5 17 17 0 0 0 0-1 17 17 0 0 0 1-4 22 22 0 0 0 0-2Z"/></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 75.7 81.8"><path fill="#dc2626" d="M76 29v14a33 33 0 0 1-1 7 30 30 0 0 1-1 2 29 29 0 0 1-3 7 27 27 0 0 1 0 1 27 27 0 0 1-6 6 27 27 0 0 1-7 4l14 12H54L42 72H29a32 32 0 0 1-8-1 29 29 0 0 1-3-1q-6-2-10-6a28 28 0 0 1-6-10 30 30 0 0 1-2-9 35 35 0 0 1 0-2V29a32 32 0 0 1 1-8 28 28 0 0 1 1-3 28 28 0 0 1 5-9 27 27 0 0 1 1-1 28 28 0 0 1 10-6 32 32 0 0 1 0 0 30 30 0 0 1 9-2 35 35 0 0 1 2 0h17a32 32 0 0 1 9 1 28 28 0 0 1 3 1 28 28 0 0 1 9 6 27 27 0 0 1 6 9 31 31 0 0 1 0 1 30 30 0 0 1 3 9 35 35 0 0 1 0 2ZM63 43V29a20 20 0 0 0 0-4 17 17 0 0 0-1-3 15 15 0 0 0-3-4 14 14 0 0 0-1-1 15 15 0 0 0-4-3 17 17 0 0 0-1 0 17 17 0 0 0-5-1 21 21 0 0 0-2 0H29a20 20 0 0 0-4 0 17 17 0 0 0-2 1l-6 3a15 15 0 0 0-3 5 17 17 0 0 0 0 0 17 17 0 0 0-1 5 22 22 0 0 0 0 2v14a20 20 0 0 0 0 4 17 17 0 0 0 1 2 15 15 0 0 0 3 5 14 14 0 0 0 0 1 15 15 0 0 0 5 3 17 17 0 0 0 1 0 17 17 0 0 0 4 1 21 21 0 0 0 2 0h17a20 20 0 0 0 4 0 17 17 0 0 0 3-1l5-3a15 15 0 0 0 4-5 17 17 0 0 0 0-1 17 17 0 0 0 1-4 22 22 0 0 0 0-2Z"/></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 54.7 70" fill="#2D954F"><path d="M0 54.7V0h10.2v54.7a4.8 4.8 0 0 0 1.2 3.2 6.4 6.4 0 0 0 .3.4 5.6 5.6 0 0 0 1.5 1 4.7 4.7 0 0 0 2.1.5h29.3V0h10.1v59.8H44.6V70H15.3a16.7 16.7 0 0 1-4.8-.7 15.3 15.3 0 0 1-1.3-.5q-2.9-1.1-4.9-3.1a14 14 0 0 1-2.8-4 16.5 16.5 0 0 1-.4-.9 16 16 0 0 1-1-5.4 18.6 18.6 0 0 1-.1-.7Z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 75.7 81.8"><path fill="#888" d="M76 29v14a33 33 0 0 1-1 7 30 30 0 0 1-1 2 29 29 0 0 1-3 7 27 27 0 0 1 0 1 27 27 0 0 1-6 6 27 27 0 0 1-7 4l14 12H54L42 72H29a32 32 0 0 1-8-1 29 29 0 0 1-3-1q-6-2-10-6a28 28 0 0 1-6-10 30 30 0 0 1-2-9 35 35 0 0 1 0-2V29a32 32 0 0 1 1-8 28 28 0 0 1 1-3 28 28 0 0 1 5-9 27 27 0 0 1 1-1 28 28 0 0 1 10-6 32 32 0 0 1 0 0 30 30 0 0 1 9-2 35 35 0 0 1 2 0h17a32 32 0 0 1 9 1 28 28 0 0 1 3 1 28 28 0 0 1 9 6 27 27 0 0 1 6 9 31 31 0 0 1 0 1 30 30 0 0 1 3 9 35 35 0 0 1 0 2ZM63 43V29a20 20 0 0 0 0-4 17 17 0 0 0-1-3 15 15 0 0 0-3-4 14 14 0 0 0-1-1 15 15 0 0 0-4-3 17 17 0 0 0-1 0 17 17 0 0 0-5-1 21 21 0 0 0-2 0H29a20 20 0 0 0-4 0 17 17 0 0 0-2 1l-6 3a15 15 0 0 0-3 5 17 17 0 0 0 0 0 17 17 0 0 0-1 5 22 22 0 0 0 0 2v14a20 20 0 0 0 0 4 17 17 0 0 0 1 2 15 15 0 0 0 3 5 14 14 0 0 0 0 1 15 15 0 0 0 5 3 17 17 0 0 0 1 0 17 17 0 0 0 4 1 21 21 0 0 0 2 0h17a20 20 0 0 0 4 0 17 17 0 0 0 3-1l5-3a15 15 0 0 0 4-5 17 17 0 0 0 0-1 17 17 0 0 0 1-4 22 22 0 0 0 0-2Z"/></svg>

Before

Width:  |  Height:  |  Size: 369 B

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 421.6 140.2"><path fill-rule="evenodd" stroke="#000" stroke-linecap="round" stroke-width=".9" d="M0 109.4V0h20.4v109.4a9.6 9.6 0 0 0 2.4 6.4 12.8 12.8 0 0 0 .7.7q3.1 3.1 7.1 3.1h58.6V0h20.2v119.6H89.2V140H30.6a33.4 33.4 0 0 1-9.6-1.3 30.7 30.7 0 0 1-2.7-1 30 30 0 0 1-7-4 26.8 26.8 0 0 1-2.7-2.3 28.1 28.1 0 0 1-5.5-8 33 33 0 0 1-.8-1.7 32.2 32.2 0 0 1-2.3-11 37.1 37.1 0 0 1 0-1.3ZM307 0h20.4v73.8l58.4-30.6q2 0 3-.8t1.5-2q.5-1.2.6-2.5l.1-2.3V17.8l20.4-10.2v28a29.5 29.5 0 0 1-3.8 14.4 34.6 34.6 0 0 1-.1.2 26 26 0 0 1-11 10.5 31.6 31.6 0 0 1-.5.3l-17.8 10.2 43.4 68.8h-23l-38.2-58.6-28 12.8q-2 2-3.5 3.8a7 7 0 0 0-1 1.5 5.3 5.3 0 0 0-.5 2.3V140H307V0ZM127.6 109.4v-89h20.2V0H214q5.8 0 11.3 2.3 5.5 2.3 9.8 6.3a30 30 0 0 1 6.5 9 34.4 34.4 0 0 1 .4.7 29.3 29.3 0 0 1 2.6 12.2 33.4 33.4 0 0 1 0 .1v12.6a23.3 23.3 0 0 1-1.2 7.4 26.1 26.1 0 0 1-.1.2q-1.3 3.8-3.4 7.1-2.1 3.3-4.9 6.1a48.8 48.8 0 0 1-3.3 3 39.5 39.5 0 0 1-2.3 1.8l2.4 2.4q7.6 4 12.7 11a28 28 0 0 1 3.7 6.7 22.5 22.5 0 0 1 1.4 7.9v12.6a29.4 29.4 0 0 1-2.4 11.8 28.6 28.6 0 0 1-.2.5 30.7 30.7 0 0 1-5.3 8 28.7 28.7 0 0 1-1.6 1.7q-4.3 4-9.7 6.3-5.4 2.3-11.2 2.3h-63.6q-5.8 0-10.9-2.3-5.1-2.3-8.9-6.3a28 28 0 0 1-5-7.3 33.7 33.7 0 0 1-1-2.4 33.3 33.3 0 0 1-2.2-10.6 38.6 38.6 0 0 1 0-1.7Zm20.2-89V112q0 6 5 7.3a11.8 11.8 0 0 0 2.8.3h63.6a9.2 9.2 0 0 0 5.3-1.7 13 13 0 0 0 1.7-1.4 11.2 11.2 0 0 0 2.1-2.7 9 9 0 0 0 1.1-4.4V96.8q0-2-1.6-3.9a11 11 0 0 0 0 0 57.9 57.9 0 0 0-2.2-2.4 70.3 70.3 0 0 0-1.4-1.5l-17.8-7.6-43.2 23v-23l56-30.4q1.6 0 3-2.3a12.4 12.4 0 0 0 .4-.6 18.3 18.3 0 0 0 .8-1.6q.7-1.8.8-3.1a5.2 5.2 0 0 0 0-.2V30.6a9.6 9.6 0 0 0-2.4-6.4 12.8 12.8 0 0 0-.7-.7q-3.1-3.1-7.1-3.1h-66.2ZM266.4 0H287v140.2h-20.6V0Z" font-size="12" vector-effect="non-scaling-stroke"/></svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -27,8 +27,8 @@ export function AddServerButton() {
function copyDockerCompose(port: string) {
copyToClipboard(`services:
agent:
image: 'henrygd/quoma-agent'
container_name: 'quoma-agent'
image: 'henrygd/qoma-agent'
container_name: 'qoma-agent'
restart: unless-stopped
ports:
- '${port}:45876'

View File

@@ -63,7 +63,7 @@ export default function ({ chartData }: { chartData: Record<string, number | str
>
<CartesianGrid vertical={false} />
<YAxis
domain={[0, (max: number) => Math.ceil(max)]}
domain={[0, (max: number) => Math.max(Math.ceil(max), 0.4)]}
// tickCount={5}
tickLine={false}
axisLine={false}

View File

@@ -15,7 +15,7 @@ import Spinner from '../spinner'
const chartConfig = {
diskUsed: {
label: 'Disk Use',
label: 'Disk Usage',
color: 'hsl(var(--chart-3))',
},
} satisfies ChartConfig

View File

@@ -10,22 +10,29 @@ import { formatShortDate, formatShortTime } from '@/lib/utils'
import { useMemo } from 'react'
import Spinner from '../spinner'
const chartConfig = {
memUsed: {
label: 'Memory Use',
color: 'hsl(var(--chart-2))',
},
} satisfies ChartConfig
export default function ({
chartData,
}: {
chartData: { time: string; mem: number; memUsed: number }[]
chartData: { time: string; mem: number; memUsed: number; memCache: number }[]
}) {
const totalMem = useMemo(() => {
return Math.ceil(chartData[0]?.mem)
}, [chartData])
const chartConfig = useMemo(
() => ({
memCache: {
label: 'Cache / Buffers',
color: 'hsl(var(--chart-2))',
},
memUsed: {
label: 'Used',
color: 'hsl(var(--chart-2))',
},
}),
[]
) satisfies ChartConfig
if (!chartData.length) {
return <Spinner />
}
@@ -61,7 +68,13 @@ export default function ({
<ChartTooltip
cursor={false}
content={
<ChartTooltipContent unit="GiB" labelFormatter={formatShortDate} indicator="line" />
<ChartTooltipContent
unit="GiB"
// @ts-ignore
itemSorter={(a, b) => a.name.localeCompare(b.name)}
labelFormatter={formatShortDate}
indicator="line"
/>
}
/>
<Area
@@ -70,6 +83,16 @@ export default function ({
fill="var(--color-memUsed)"
fillOpacity={0.4}
stroke="var(--color-memUsed)"
stackId="a"
/>
<Area
dataKey="memCache"
type="monotone"
fill="var(--color-memCache)"
fillOpacity={0.2}
strokeOpacity={0.3}
stroke="var(--color-memCache)"
stackId="a"
/>
</AreaChart>
</ChartContainer>

View File

@@ -1,8 +1,8 @@
export function Logo({ className }: { className?: string }) {
return (
// audiowide
<svg viewBox="0 0 370 82" className={className} fill="currentColor">
<path d="M271.8 36v35H259V36a7.5 7.5 0 0 0-.1-1.5q-.2-.8-.6-1.4a3.9 3.9 0 0 0-.6-.9q-1.1-1-3.1-1.3a9.2 9.2 0 0 0-.8 0h-16.5V71h-12.7V24.5a6.3 6.3 0 0 1 .4-2.2 6 6 0 0 1 0-.3q.5-1.1 1.4-2 .9-.8 2-1.3a6.4 6.4 0 0 1 2.6-.5H254a17.2 17.2 0 0 1 3 .3 22.8 22.8 0 0 1 2.6.6q3 1 5.8 3v-3.9h17.2a17.7 17.7 0 0 1 2.5.2 21.3 21.3 0 0 1 1.3.2 19.5 19.5 0 0 1 3.8 1.3 21.5 21.5 0 0 1 .2 0q2 .9 3.7 2.3a15 15 0 0 1 3.2 3.3 16.3 16.3 0 0 1 1.6 3 19.7 19.7 0 0 1 .6 1.6q.8 2.6.8 5.9v35h-12.7V36a8 8 0 0 0 0-1.5q-.3-1.4-1.2-2.3-1.2-1.3-3.8-1.3H271q.7 2.4.7 5Zm94.7-.3v17.8a17.3 17.3 0 0 1-.3 3 23.1 23.1 0 0 1-.6 2.7 17 17 0 0 1-3 5.7 15.9 15.9 0 0 1-3.7 3.3 19.6 19.6 0 0 1-1.7 1Q354 71 349.6 71a25.4 25.4 0 0 1-.6 0h-22.9a17.3 17.3 0 0 1-3-.3 23.1 23.1 0 0 1-2.7-.6 17 17 0 0 1-5.6-3 15.9 15.9 0 0 1-3.3-3.7 19.6 19.6 0 0 1-1.1-1.8q-1.7-3.1-1.8-7.5a25.4 25.4 0 0 1 0-.6 17.3 17.3 0 0 1 .3-3 23.4 23.4 0 0 1 .7-2.7q.9-3 3-5.7a15.9 15.9 0 0 1 3.6-3.3 19.6 19.6 0 0 1 1.8-1q3.1-1.7 7.6-1.8a25.4 25.4 0 0 1 .5 0h23V48h-23a6.8 6.8 0 0 0-1.6.2 4.6 4.6 0 0 0-2.4 1.4 5.5 5.5 0 0 0-1.4 3.3 7.3 7.3 0 0 0 0 .6 6 6 0 0 0 .2 1.7 4.4 4.4 0 0 0 1.4 2.2 5.8 5.8 0 0 0 4 1.4H349a6.9 6.9 0 0 0 1.7-.2 4.6 4.6 0 0 0 2.3-1.4 5.4 5.4 0 0 0 1.4-3.2 7.2 7.2 0 0 0 0-.7V35.7a6.5 6.5 0 0 0-.2-1.7 4.8 4.8 0 0 0-1.3-2.3q-1.5-1.4-3.9-1.4h-27.9v-12h28a17.3 17.3 0 0 1 3 .2 23.1 23.1 0 0 1 2.6.6 17 17 0 0 1 5.7 3 15.9 15.9 0 0 1 3.3 3.7 19.6 19.6 0 0 1 1 1.8q1.7 3.1 1.8 7.5a25.4 25.4 0 0 1 0 .6Zm-222-17.5v46.4a6.7 6.7 0 0 1-.2 2 6.1 6.1 0 0 1-.3.5 6.2 6.2 0 0 1-1.3 2q-.9 1-2 1.4a6.2 6.2 0 0 1-2.4.5h-28.8a23.3 23.3 0 0 1-3-.2 29 29 0 0 1-2-.3 23.6 23.6 0 0 1-5.2-1.8 27 27 0 0 1-4.7-2.8 30 30 0 0 1-.3-.2q-2.5-1.8-4.3-4.4a21.5 21.5 0 0 1-2.1-4 26.1 26.1 0 0 1-.8-2 22.4 22.4 0 0 1-.9-4.2 29.5 29.5 0 0 1-.2-3.6V18.2h12.7v29.3A12.5 12.5 0 0 0 99 50a10 10 0 0 0 .6 2 10.5 10.5 0 0 0 2 3 10 10 0 0 0 .3.4q1.5 1.4 3.4 2.1 2 .8 4.3.8h22.2v-40h12.7ZM75.7 29.3v13.4a32.8 32.8 0 0 1-.8 7.1 29.5 29.5 0 0 1-.5 2 29 29 0 0 1-3.1 7 26.9 26.9 0 0 1-.6 1 27 27 0 0 1-5.7 6 27 27 0 0 1-7.4 4.2l14.8 11.8H54L41.8 72H29.3a32.1 32.1 0 0 1-8.2-1 28.7 28.7 0 0 1-3.5-1.2q-5.3-2.2-9.3-6a28.2 28.2 0 0 1-6-9.4A29.6 29.6 0 0 1 0 45.2a35.1 35.1 0 0 1-.1-2.5V29.3A31.8 31.8 0 0 1 1 21a28.5 28.5 0 0 1 1.2-3.4 28.1 28.1 0 0 1 5.2-8.3 26.7 26.7 0 0 1 1-1 28 28 0 0 1 9.1-6 31.8 31.8 0 0 1 .1-.1A29.9 29.9 0 0 1 27.4.1a35 35 0 0 1 1.9-.1h17.2a31.6 31.6 0 0 1 8.2 1 28.2 28.2 0 0 1 3.4 1.2 28.1 28.1 0 0 1 9.3 6 27.5 27.5 0 0 1 6 9 31.3 31.3 0 0 1 0 .4 30.1 30.1 0 0 1 2.2 9.6 35.4 35.4 0 0 1 0 2.1ZM213.9 36v17.2a22.2 22.2 0 0 1-.2 3 17 17 0 0 1-.7 2.9 18.6 18.6 0 0 1-1.1 2.8 15.3 15.3 0 0 1-1 1.7 15 15 0 0 1-3.2 3.4 18.5 18.5 0 0 1-3.8 2.3 19.5 19.5 0 0 1-4 1.3 20.8 20.8 0 0 1-2.3.3 17 17 0 0 1-1.6.1h-22.9q-2.6 0-5.7-1-3.1-.9-5.8-3a16.3 16.3 0 0 1-3.4-3.7 20 20 0 0 1-1-1.8 14.7 14.7 0 0 1-1.4-3.8q-.3-1.7-.4-3.6a26.1 26.1 0 0 1 0-1V36q0-4.4 1.4-7.6a13.2 13.2 0 0 1 .4-.7 18.6 18.6 0 0 1 2.3-3.5 15.6 15.6 0 0 1 2.1-2q2.7-2.1 5.8-3a24.2 24.2 0 0 1 2.8-.7q1.5-.3 3-.3H196a22.7 22.7 0 0 1 3.8.3q2.1.4 3.9 1.2a13.5 13.5 0 0 1 .6.3 18 18 0 0 1 3.5 2.2 15 15 0 0 1 2 2.2q2.2 2.7 3.1 5.8a23.3 23.3 0 0 1 .7 3 17.3 17.3 0 0 1 .3 2.8Zm-151 6.7V29.3a20.4 20.4 0 0 0-.3-4 16.6 16.6 0 0 0-.8-2.8 15.4 15.4 0 0 0-2.5-4.2 14.3 14.3 0 0 0-.9-1 15 15 0 0 0-4.8-3.2 17.2 17.2 0 0 0-.4-.2 17.5 17.5 0 0 0-4.9-1.1 21 21 0 0 0-1.8-.1H29.3a20 20 0 0 0-4 .4 16.6 16.6 0 0 0-2.8.8q-3 1.2-5.2 3.4a14.8 14.8 0 0 0-3.3 5 17 17 0 0 0-.1.2 17.3 17.3 0 0 0-1 4.4 21.6 21.6 0 0 0-.2 2.4v13.4a20.4 20.4 0 0 0 .4 4 16.6 16.6 0 0 0 .8 2.8 15 15 0 0 0 2.7 4.5 14.3 14.3 0 0 0 .7.7 15.2 15.2 0 0 0 5 3.3 17.5 17.5 0 0 0 .2 0 17.4 17.4 0 0 0 4.7 1.2 21.3 21.3 0 0 0 2.1 0h17a20 20 0 0 0 4.2-.3A16.6 16.6 0 0 0 53 58q3.1-1.2 5.3-3.4a14.8 14.8 0 0 0 3.3-5 17 17 0 0 0 0-.2A17.3 17.3 0 0 0 63 45a21.6 21.6 0 0 0 0-2.4Zm138.3 10.5V36a8.4 8.4 0 0 0-.1-1.5l-.5-1.4a3.7 3.7 0 0 0-.7-1 4.2 4.2 0 0 0-1.8-1l-1.4-.3a8.9 8.9 0 0 0-.7 0h-22.8q-1.7 0-3 .6a4 4 0 0 0-.8.7q-1.2 1.1-1.3 3.2a8.7 8.7 0 0 0 0 .6v17.2q0 1.8.7 3a4 4 0 0 0 .6.8 4.2 4.2 0 0 0 1.7 1l1.5.3a8.9 8.9 0 0 0 .6 0H196a8 8 0 0 0 1.5-.1l1.4-.5a3.7 3.7 0 0 0 1-.7 4.2 4.2 0 0 0 1-1.7l.3-1.5a8.9 8.9 0 0 0 0-.6Z" />
<svg viewBox="0 0 299 82" className={className}>
<path d="M202.1 36v35h-12.6V36a7.5 7.5 0 0 0-.2-1.5q-.1-.8-.5-1.4a3.9 3.9 0 0 0-.7-.9q-1-1-3-1.3a9.2 9.2 0 0 0-.9 0h-16.5V71H155V24.5a6.3 6.3 0 0 1 .4-2.2 6 6 0 0 1 .1-.3q.5-1.1 1.4-2 .9-.8 2-1.3a6.4 6.4 0 0 1 2.5-.5h23a17.2 17.2 0 0 1 3 .3 22.8 22.8 0 0 1 2.6.6q3 1 5.8 3v-3.9h17.1a17.7 17.7 0 0 1 2.6.2 21.3 21.3 0 0 1 1.2.2 19.5 19.5 0 0 1 3.9 1.3 21.5 21.5 0 0 1 .1 0q2 .9 3.8 2.3a15 15 0 0 1 3.2 3.3 16.3 16.3 0 0 1 0 0 16.3 16.3 0 0 1 1.6 3 19.7 19.7 0 0 1 .6 1.6q.8 2.6.8 5.9v35H218V36a8 8 0 0 0-.1-1.5q-.3-1.4-1.1-2.3-1.3-1.3-3.9-1.3h-11.4q.6 2.4.6 5Zm94.8-.3v17.8a17.3 17.3 0 0 1-.3 3 23.1 23.1 0 0 1-.7 2.7 17 17 0 0 1-3 5.7 15.9 15.9 0 0 1-3.6 3.3 19.6 19.6 0 0 1-1.8 1Q284.4 71 280 71a25.4 25.4 0 0 1-.6 0h-22.9a17.3 17.3 0 0 1-3-.3 23.1 23.1 0 0 1-2.7-.6 17 17 0 0 1-5.7-3 15.9 15.9 0 0 1-3.3-3.7 19.6 19.6 0 0 1-1-1.8q-1.7-3.1-1.8-7.5a25.4 25.4 0 0 1 0-.6 17.3 17.3 0 0 1 .3-3 23.4 23.4 0 0 1 .6-2.7q1-3 3-5.7a15.9 15.9 0 0 1 3.7-3.3 19.6 19.6 0 0 1 1.8-1q3.1-1.7 7.5-1.8a25.4 25.4 0 0 1 .6 0h22.9V48h-22.9a6.8 6.8 0 0 0-1.6.2 4.6 4.6 0 0 0-2.4 1.4A5.5 5.5 0 0 0 251 53a7.3 7.3 0 0 0 0 .6 6 6 0 0 0 .2 1.7 4.4 4.4 0 0 0 1.4 2.2 5.8 5.8 0 0 0 3.9 1.4h22.8a6.9 6.9 0 0 0 1.6-.2 4.6 4.6 0 0 0 2.4-1.4 5.4 5.4 0 0 0 1.4-3.2 7.2 7.2 0 0 0 0-.7V35.7a6.5 6.5 0 0 0-.2-1.7 4.8 4.8 0 0 0-1.3-2.3q-1.6-1.4-4-1.4h-27.8v-12h27.9a17.3 17.3 0 0 1 3 .2 23.1 23.1 0 0 1 2.7.6 17 17 0 0 1 5.6 3 15.9 15.9 0 0 1 3.4 3.7 19.6 19.6 0 0 1 1 1.8q1.7 3.1 1.8 7.5a25.4 25.4 0 0 1 0 .6ZM75.7 29.3v13.4a32.8 32.8 0 0 1-.8 7.1 29.5 29.5 0 0 1-.5 2 29 29 0 0 1-3.1 7 26.9 26.9 0 0 1-.6 1 27 27 0 0 1-5.7 6 27 27 0 0 1-7.4 4.2l14.8 11.8H54L41.8 72H29.3a32.1 32.1 0 0 1-8.2-1 28.7 28.7 0 0 1-3.5-1.2q-5.3-2.2-9.3-6a28.2 28.2 0 0 1-6-9.4A29.6 29.6 0 0 1 0 45.2a35.1 35.1 0 0 1-.1-2.5V29.3A31.8 31.8 0 0 1 1 21a28.5 28.5 0 0 1 1.2-3.4 28.1 28.1 0 0 1 5.2-8.3 26.7 26.7 0 0 1 1-1 28 28 0 0 1 9.1-6 31.8 31.8 0 0 1 .1-.1A29.9 29.9 0 0 1 27.4.1a35 35 0 0 1 1.9-.1h17.2a31.6 31.6 0 0 1 8.2 1 28.2 28.2 0 0 1 3.4 1.2 28.1 28.1 0 0 1 9.3 6 27.5 27.5 0 0 1 6 9 31.3 31.3 0 0 1 0 .4 30.1 30.1 0 0 1 2.2 9.6 35.4 35.4 0 0 1 0 2.1Zm68.5 6.7v17.2a22.2 22.2 0 0 1-.2 3 17 17 0 0 1-.6 2.9 18.6 18.6 0 0 1-1.2 2.8 15.3 15.3 0 0 1-1 1.7 15 15 0 0 1-3.1 3.4 14.2 14.2 0 0 1 0 0 18.5 18.5 0 0 1-3.8 2.3 19.5 19.5 0 0 1-4 1.3 20.8 20.8 0 0 1-2.4.3 17 17 0 0 1-1.5.1h-22.9q-2.6 0-5.7-1-3.2-.9-5.8-3a16.3 16.3 0 0 1-3.4-3.7 20 20 0 0 1-1-1.8 14.7 14.7 0 0 1-1.4-3.8q-.4-1.7-.4-3.6a26.1 26.1 0 0 1 0-1V36q0-4.4 1.4-7.6a13.2 13.2 0 0 1 .3-.7 18.6 18.6 0 0 1 2.4-3.5 15.6 15.6 0 0 1 2-2q2.7-2.1 5.9-3a24.2 24.2 0 0 1 2.8-.7q1.5-.3 3-.3h22.8a22.7 22.7 0 0 1 3.7.3q2.2.4 4 1.2a13.5 13.5 0 0 1 .6.3 18 18 0 0 1 3.4 2.2 15 15 0 0 1 2.1 2.2q2.1 2.7 3 5.8a23.3 23.3 0 0 1 .8 3 17.3 17.3 0 0 1 .2 2.8ZM63 42.7V29.3a20.4 20.4 0 0 0-.4-4 16.6 16.6 0 0 0-.8-2.8 15.4 15.4 0 0 0-2.5-4.2 14.3 14.3 0 0 0-.9-1 15 15 0 0 0-4.8-3.2 17.2 17.2 0 0 0-.4-.2 17.5 17.5 0 0 0-4.9-1.1 21 21 0 0 0-1.8-.1H29.3a20 20 0 0 0-4 .4 16.6 16.6 0 0 0-2.8.8q-3 1.2-5.2 3.4a14.8 14.8 0 0 0-3.3 5 17 17 0 0 0-.1.2 17.3 17.3 0 0 0-1 4.4 21.6 21.6 0 0 0-.2 2.4v13.4a20.4 20.4 0 0 0 .4 4 16.6 16.6 0 0 0 .8 2.8 15 15 0 0 0 2.7 4.5 14.3 14.3 0 0 0 .7.7 15.2 15.2 0 0 0 5 3.3 17.5 17.5 0 0 0 .2 0 17.4 17.4 0 0 0 4.7 1.2 21.3 21.3 0 0 0 2.1 0h17a20 20 0 0 0 4.2-.3A16.6 16.6 0 0 0 53 58q3.1-1.2 5.3-3.4a14.8 14.8 0 0 0 3.3-5 17 17 0 0 0 0-.2A17.3 17.3 0 0 0 63 45a21.6 21.6 0 0 0 0-2.4Zm68.5 10.5V36a8.4 8.4 0 0 0 0-1.5l-.5-1.4a3.7 3.7 0 0 0-.8-1 4.2 4.2 0 0 0-1.7-1l-1.4-.3a8.9 8.9 0 0 0-.7 0h-22.8q-1.8 0-3 .6a4 4 0 0 0-.8.7q-1.2 1.1-1.3 3.2a8.7 8.7 0 0 0 0 .6v17.2q0 1.8.7 3a4 4 0 0 0 .6.8 4.2 4.2 0 0 0 1.7 1l1.5.3a8.9 8.9 0 0 0 .6 0h22.8a8 8 0 0 0 1.5-.1l1.4-.5a3.7 3.7 0 0 0 1-.7 4.2 4.2 0 0 0 1-1.7q.2-.7.2-1.5a8.9 8.9 0 0 0 0-.6Z" />
</svg>
)
}

View File

@@ -9,7 +9,7 @@ const DataTable = lazy(() => import('../server-table/data-table'))
export default function () {
useEffect(() => {
document.title = 'Home'
document.title = 'Qoma Dashboard'
}, [])
useEffect(updateServerList, [])
@@ -49,7 +49,7 @@ export default function () {
<>
<Card>
<CardHeader>
<CardTitle className={'mb-1.5'}>All Servers</CardTitle>
<CardTitle className={'mb-1.5'}>All Systems</CardTitle>
<CardDescription>
Updated in real time. Press{' '}
<kbd className="pointer-events-none inline-flex h-5 select-none items-center gap-0.5 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium text-muted-foreground opacity-100">

View File

@@ -33,7 +33,7 @@ export default function ServerDetail({ name }: { name: string }) {
const [serverStats, setServerStats] = useState([] as SystemStatsRecord[])
const [cpuChartData, setCpuChartData] = useState([] as { time: string; cpu: number }[])
const [memChartData, setMemChartData] = useState(
[] as { time: string; mem: number; memUsed: number }[]
[] as { time: string; mem: number; memUsed: number; memCache: number }[]
)
const [diskChartData, setDiskChartData] = useState(
[] as { time: string; disk: number; diskUsed: number }[]
@@ -46,7 +46,7 @@ export default function ServerDetail({ name }: { name: string }) {
)
useEffect(() => {
document.title = name
document.title = `${name} / Qoma`
return () => {
setContainerCpuChartData([])
setCpuChartData([])
@@ -80,12 +80,12 @@ export default function ServerDetail({ name }: { name: string }) {
}
// let maxCpu = 0
const cpuData = [] as { time: string; cpu: number }[]
const memData = [] as { time: string; mem: number; memUsed: number }[]
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 })
// maxCpu = Math.max(maxCpu, stats.c)
memData.push({ time: created, mem: stats.m, memUsed: stats.mu })
memData.push({ time: created, mem: stats.m, memUsed: stats.mu, memCache: stats.mb })
diskData.push({ time: created, disk: stats.d, diskUsed: stats.du })
}
setCpuChartData(cpuData.reverse())

View File

@@ -62,6 +62,10 @@
z-index: 1;
}
.recharts-yAxis {
font-variant-numeric: tabular-nums;
}
/* charts */
@layer base {
:root {

View File

@@ -51,3 +51,6 @@ const shortDateFormatter = new Intl.DateTimeFormat(undefined, {
minute: 'numeric',
})
export const formatShortDate = (timestamp: string) => shortDateFormatter.format(new Date(timestamp))
export const updateFavicon = (newIconUrl: string) =>
((document.querySelector("link[rel='icon']") as HTMLLinkElement).href = newIconUrl)

View File

@@ -3,9 +3,9 @@ import React, { 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'
import { $authenticated, $router, navigate } from './lib/stores.ts'
import { $authenticated, $router, $servers, navigate } from './lib/stores.ts'
import { ModeToggle } from './components/mode-toggle.tsx'
import { cn, updateServerList } from './lib/utils.ts'
import { cn, updateFavicon, updateServerList } from './lib/utils.ts'
import { buttonVariants } from './components/ui/button.tsx'
import { Github } from 'lucide-react'
import { useStore } from '@nanostores/react'
@@ -24,10 +24,24 @@ const LoginPage = lazy(() => import('./components/login.tsx'))
const App = () => {
const page = useStore($router)
const authenticated = useStore($authenticated)
const servers = useStore($servers)
// get servers
useEffect(updateServerList, [])
// update favicon
useEffect(() => {
if (!authenticated || !servers.length) {
updateFavicon('/favicon.svg')
} else if (servers.find((server) => !server.active)) {
updateFavicon('/favicon-red.svg')
} else {
// all servers good
updateFavicon('/favicon-green.svg')
}
}, [authenticated, servers])
if (!page) {
return <h1>404</h1>
} else if (page.path === '/') {
@@ -61,7 +75,7 @@ const Layout = () => {
navigate('/')
}}
>
<Logo className="h-[1.1em] fill-foreground" />
<Logo className="h-[1.2em] fill-foreground" />
</a>
<div className={'flex gap-1 ml-auto'}>

2
site/src/types.d.ts vendored
View File

@@ -21,6 +21,8 @@ export interface SystemStats {
m: number
/** memory percent */
mp: number
/** memory buffer + cache (gb) */
mb: number
/** memory used (gb) */
mu: number
}