add some stuff

This commit is contained in:
Hamcha 2024-04-14 17:22:16 +02:00
parent c23af50f0f
commit 2d9e0ef66e
Signed by: hamcha
GPG Key ID: 1669C533B8CF6D89
12 changed files with 227 additions and 27 deletions

View File

@ -27,11 +27,12 @@
"svelte-check": "^3.6.9",
"tslib": "^2.6.2",
"typescript": "^5.4.5",
"vite": "^5.2.8"
"vite": "^5.2.8",
"@fontsource-variable/inter": "^5.0.17",
"@fontsource/iosevka": "^5.0.7",
"unplugin-icons": "^0.18.5",
"@iconify-json/ri": "^1.1.20"
},
"type": "module",
"dependencies": {
"@fontsource-variable/inter": "^5.0.17",
"@fontsource/iosevka": "^5.0.7"
}
"dependencies": {}
}

View File

@ -0,0 +1,38 @@
import { fetchAPI } from './api';
enum MountPointTypeEnum {
EMPTY = '',
BIND = 'bind',
VOLUME = 'volume',
TMPFS = 'tmpfs',
NPIPE = 'npipe',
CLUSTER = 'cluster'
}
interface MountPoint {
Type?: MountPointTypeEnum;
Name?: string;
Source?: string;
Destination?: string;
Driver?: string;
Mode?: string;
RW?: boolean;
Propagation?: string;
}
export interface ContainerInfo {
id: string;
name: string;
state: string;
image: string;
image_id: string;
created_at: string;
volumes?: MountPoint[];
env?: string[];
labels?: Record<string, string>;
}
export async function getContainerList(): Promise<ContainerInfo[]> {
const res = await fetchAPI('/containers');
return res.json();
}

View File

@ -31,6 +31,7 @@ export interface SystemInfo {
disks: DiskInfo[];
// CPU
cpu_count: number;
load_average: [number, number, number];
}

View File

@ -19,6 +19,7 @@
& header {
margin-bottom: var(--padding-normal);
font-weight: bold;
}
}
</style>

View File

@ -57,4 +57,9 @@
font-family: var(--font-sans);
scrollbar-width: thin;
}
:global(p) {
margin: 0;
padding: 0;
}
</style>

View File

@ -1,8 +1,10 @@
import { getContainerList } from '$lib/server/containers';
import { getSystemInfo } from '$lib/server/system';
import type { PageServerLoad } from './$types';
export const load: PageServerLoad = async ({ params }) => {
export const load: PageServerLoad = async ({}) => {
return {
systemInfo: await getSystemInfo()
systemInfo: await getSystemInfo(),
containers: await getContainerList()
};
};

View File

@ -1,8 +1,10 @@
<script lang="ts">
import type { PageData } from './$types';
import HardwareInfo from './HardwareInfo.svelte';
import ContainerList from './ContainerList.svelte';
import SystemInfo from './SystemInfo.svelte';
export let data: PageData;
</script>
<HardwareInfo data={data.systemInfo} />
<SystemInfo data={data.systemInfo} />
<ContainerList data={data.containers} />

View File

@ -0,0 +1,11 @@
<script lang="ts">
import type { ContainerInfo } from '$lib/server/containers';
export let data: ContainerInfo[];
</script>
<ul>
{#each data as container}
<li>{container.name}</li>
{/each}
</ul>

View File

@ -1,15 +0,0 @@
<script lang="ts">
import type { SystemInfo } from '$lib/server/system';
import Panel from '$lib/ui/Panel.svelte';
export let data: SystemInfo;
</script>
<Panel title="Hardware Info">
{data.host_name}
</Panel>
<style>
.hardware-info {
}
</style>

View File

@ -0,0 +1,145 @@
<script lang="ts">
import type { SystemInfo } from '$lib/server/system';
import Panel from '$lib/ui/Panel.svelte';
import IconCPU from '~icons/ri/cpu-fill';
import IconRAM from '~icons/ri/ram-fill';
import IconDrive from '~icons/ri/hard-drive-2-fill';
export let data: SystemInfo;
function formatBytes(bytes: number): string {
const sizes = ['B', 'KiB', 'MiB', 'GiB', 'TiB'];
if (bytes === 0) {
return 'n/a';
}
const i = Math.floor(Math.log(bytes) / Math.log(1024));
return `${(bytes / 1024 ** i).toFixed(1)} ${sizes[i]}`;
}
</script>
<Panel title="System info">
<div class="sections">
<section class="info">
<dl>
<dt>Hostname</dt>
<dd>{data.host_name}</dd>
<dt>Hardware</dt>
<dd>
<IconCPU />
{data.cpu_count}
<IconRAM />
{formatBytes(data.total_memory)}
<IconDrive />
{formatBytes(data.disks[0].total_space)}
</dd>
<dt>OS</dt>
<dd>
{data.name}
{data.os_version} (kernel {data.kernel_version})
</dd>
</dl>
</section>
<section class="stats">
<header>Load Avg</header>
<article>{data.load_average[0]} - {data.load_average[1]} - {data.load_average[2]}</article>
</section>
<section class="stats">
<header>RAM usage</header>
<article>
<p>{formatBytes(data.used_memory)} / {formatBytes(data.total_memory)}</p>
<progress value={data.used_memory} max={data.total_memory} />
</article>
</section>
<section class="stats">
<header>Disk usage</header>
<article>
<p>
{formatBytes(data.disks[0].total_space - data.disks[0].available_space)}
/
{formatBytes(data.disks[0].total_space)}
</p>
<progress
value={data.disks[0].total_space - data.disks[0].available_space}
max={data.disks[0].total_space}
/>
</article>
</section>
</div>
</Panel>
<style scoped>
.sections {
display: flex;
gap: 1rem;
flex-wrap: wrap;
& > * {
background-color: var(--table-bg);
padding: var(--padding-normal);
border: 1px solid var(--table-border-color);
border-radius: 3px;
}
}
.stats {
display: flex;
flex-direction: column;
align-items: stretch;
padding: 0;
min-width: 100px;
flex: 1;
text-align: center;
& > header {
width: 100%;
display: flex;
justify-content: center;
background-color: var(--table-bg);
border-bottom: 1px solid var(--table-border-color);
padding: var(--padding-narrow) 0;
margin-bottom: var(--padding-narrow);
}
& > article {
flex: 1;
justify-content: center;
display: flex;
flex-direction: column;
align-items: stretch;
gap: var(--padding-narrow);
padding: var(--padding-narrow) var(--padding-wide);
& progress {
width: 100%;
}
}
}
.info {
& dl {
margin: 0;
padding: 0;
display: grid;
grid-template-columns: 4fr 10fr;
& dt {
color: var(--header-color);
font-weight: bold;
}
& dd {
display: flex;
gap: 0.5rem;
align-items: center;
& > * {
flex: 1;
}
& .right-align {
text-align: right;
}
}
}
}
</style>

View File

@ -9,11 +9,14 @@
"skipLibCheck": true,
"sourceMap": true,
"strict": true,
"moduleResolution": "bundler"
"moduleResolution": "bundler",
"types": [
"unplugin-icons/types/svelte"
]
}
// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
// except $lib which is handled by https://kit.svelte.dev/docs/configuration#files
//
// If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
// from the referenced tsconfig.json - TypeScript does not merge them in
}
}

View File

@ -1,6 +1,12 @@
import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite';
import Icons from 'unplugin-icons/vite';
export default defineConfig({
plugins: [sveltekit()]
plugins: [
sveltekit(),
Icons({
compiler: 'svelte'
})
]
});