server info tab

This commit is contained in:
beckerinj
2023-01-19 23:36:38 -05:00
parent 37046ddbd8
commit a6a58a25be
9 changed files with 151 additions and 17 deletions

View File

@@ -5,6 +5,7 @@
"scripts": {
"start": "vite",
"dev": "vite",
"check": "tsc",
"build": "vite build && node post-build.mjs",
"serve": "vite preview"
},

View File

@@ -100,7 +100,7 @@ export const ConfigProvider: ParentComponent<{}> = (p) => {
onCleanup(() => modify_unsub());
const userCanUpdate = () => user().admin || build.permissions[getId(user())] === PermissionLevel.Update;
const userCanUpdate = () => user().admin || build.permissions![getId(user())] === PermissionLevel.Update;
const state = {
build,

View File

@@ -7,10 +7,13 @@ import { combineClasses } from "../../util/helpers";
import { Operation } from "../../types";
import Flex from "../shared/layout/Flex";
import Loading from "../shared/loading/Loading";
import { useParams } from "@solidjs/router";
const Updates: Component<{}> = (p) => {
const { ws, params, deployment } = useAppState();
const updates = useUpdates({ type: "Deployment", id: params.id! }, true);
const { ws, deployments } = useAppState();
const params = useParams();
const deployment = () => deployments.get(params.id)!
const updates = useUpdates({ type: "Deployment", id: params.id }, true);
const buildID = () => deployment()?.deployment.build_id;
let unsub = () => {};
createEffect(() => {

View File

@@ -4,6 +4,7 @@ import { Operation, Update as UpdateType, UpdateStatus } from "../../../types";
import {
combineClasses,
readableMonitorTimestamp,
readableVersion,
} from "../../../util/helpers";
import Icon from "../../shared/Icon";
import Flex from "../../shared/layout/Flex";
@@ -26,9 +27,9 @@ const Update: Component<{ update: UpdateType }> = (p) => {
};
const operation = () => {
if (p.update.operation === Operation.BuildBuild) {
return "build";
return `build ${readableVersion(p.update.version!)}`;
}
return p.update.operation.replaceAll("_", " ");
return `${p.update.operation.replaceAll("_", " ")}${p.update.version ? " " + readableVersion(p.update.version) : ""}`;
};
return (
<Flex

View File

@@ -0,0 +1,98 @@
import { useParams } from "@solidjs/router";
import { Component, createResource, For, Show } from "solid-js";
import { client } from "../../..";
import { useAppState } from "../../../state/StateProvider";
import { readableStorageAmount } from "../../../util/helpers";
import Flex from "../../shared/layout/Flex";
import Grid from "../../shared/layout/Grid";
import Loading from "../../shared/loading/Loading";
const Info: Component<{}> = (p) => {
const { serverInfo } = useAppState();
const params = useParams();
const [stats] = createResource(() => client.get_server_stats(params.id, { disks: true }));
const info = () => serverInfo.get(params.id)!;
return (
<Grid class="config">
<Grid class="config-items">
<Show when={info()} fallback={<Loading type="three-dot" />}>
<Show when={info().host_name}>
<Flex
class="config-item shadow"
alignItems="center"
justifyContent="space-between"
>
<h1>hostname</h1> <h2>{info().host_name}</h2>
</Flex>
</Show>
<Show when={info().os}>
<Flex
class="config-item shadow"
alignItems="center"
justifyContent="space-between"
>
<h1>os</h1> <h2>{info().os}</h2>
</Flex>
</Show>
<Show when={info().kernel}>
<Flex
class="config-item shadow"
alignItems="center"
justifyContent="space-between"
>
<h1>kernel</h1> <h2>{info().kernel}</h2>
</Flex>
</Show>
<Flex
class="config-item shadow"
alignItems="center"
justifyContent="space-between"
>
<h1>cpu</h1>{" "}
<h2>
{info().cpu_brand}
{info().core_count
? `, ${info().core_count} core${
info().core_count! > 1 ? "s" : ""
}`
: ""}
</h2>
</Flex>
</Show>
<Show when={stats()} fallback={<Loading type="three-dot" />}>
<Show when={stats()!.disk.disks}>
<Grid class="config-item shadow" gap="0.5rem">
<h1>disks</h1>
<For each={stats()!.disk.disks}>
{(disk) => (
<Flex
class="grey-no-hover"
style={{
padding: "0.5rem",
}}
alignItems="center"
justifyContent="space-between"
>
<Flex alignItems="center">
<div>mount point:</div>
<h2>{disk.mount}</h2>
</Flex>
<Flex alignItems="center">
<div>{readableStorageAmount(disk.used_gb)} used</div>
<div>{readableStorageAmount(disk.total_gb)} total</div>
<div>
{((100 * disk.used_gb) / disk.total_gb).toFixed()}% full
</div>
</Flex>
</Flex>
)}
</For>
</Grid>
</Show>
</Show>
</Grid>
</Grid>
);
};
export default Info;

View File

@@ -6,6 +6,7 @@ import SimpleTabs from "../../shared/tabs/SimpleTabs";
import { Tab } from "../../shared/tabs/Tabs";
import Config from "./config/Config";
import { ConfigProvider } from "./config/Provider";
import Info from "./Info";
import Permissions from "./Permissions";
const ServerTabs: Component<{}> = (p) => {
@@ -25,6 +26,10 @@ const ServerTabs: Component<{}> = (p) => {
title: "config",
element: () => <Config />,
},
{
title: "info",
element: () => <Info />
},
user().admin && {
title: "permissions",
element: () => <Permissions />,

View File

@@ -1,4 +1,4 @@
import { Params, useNavigate, useParams } from "@solidjs/router";
import { useNavigate } from "@solidjs/router";
import { createContext, ParentComponent, useContext } from "solid-js";
import { useWindowKeyDown } from "../util/hooks";
import {
@@ -6,6 +6,7 @@ import {
useDeployments,
useGroups,
useProcedures,
useServerInfo,
useServers,
useServerStats,
useUpdates,
@@ -13,19 +14,17 @@ import {
} from "./hooks";
import connectToWs from "./ws";
import { useUser } from "./UserProvider";
import { Build, DeploymentWithContainerState, PermissionLevel, ServerWithStatus } from "../types";
import { PermissionLevel } from "../types";
export type State = {
usernames: ReturnType<typeof useUsernames>;
servers: ReturnType<typeof useServers>;
server: () => ServerWithStatus | undefined;
getPermissionOnServer: (id: string) => PermissionLevel;
serverStats: ReturnType<typeof useServerStats>;
serverInfo: ReturnType<typeof useServerInfo>;
ungroupedServerIds: () => string[] | undefined;
build: () => Build | undefined;
builds: ReturnType<typeof useBuilds>;
getPermissionOnBuild: (id: string) => PermissionLevel;
deployment: () => DeploymentWithContainerState | undefined;
deployments: ReturnType<typeof useDeployments>;
getPermissionOnDeployment: (id: string) => PermissionLevel;
groups: ReturnType<typeof useGroups>;
@@ -33,7 +32,6 @@ export type State = {
procedures: ReturnType<typeof useProcedures>;
getPermissionOnProcedure: (id: string) => PermissionLevel;
updates: ReturnType<typeof useUpdates>;
params: { id?: string };
};
const context = createContext<
@@ -45,7 +43,6 @@ const context = createContext<
export const AppStateProvider: ParentComponent = (p) => {
const { user, logout } = useUser();
const params = useParams<{ id?: string }>();
const navigate = useNavigate();
const userId = (user()._id as any).$oid as string;
const servers = useServers();
@@ -57,7 +54,6 @@ export const AppStateProvider: ParentComponent = (p) => {
const state: State = {
usernames,
servers,
server: () => servers.get(params.id!),
getPermissionOnServer: (id: string) => {
const server = servers.get(id)!;
const permissions = server.server.permissions![userId] as
@@ -83,7 +79,6 @@ export const AppStateProvider: ParentComponent = (p) => {
});
},
builds,
build: () => builds.get(params.id!),
getPermissionOnBuild: (id: string) => {
const build = builds.get(id)!;
const permissions = build.permissions![userId] as
@@ -95,7 +90,6 @@ export const AppStateProvider: ParentComponent = (p) => {
return PermissionLevel.None;
}
},
deployment: () => deployments.get(params.id!),
deployments,
getPermissionOnDeployment: (id: string) => {
const deployment = deployments.get(id)!;
@@ -109,6 +103,7 @@ export const AppStateProvider: ParentComponent = (p) => {
}
},
serverStats: useServerStats(),
serverInfo: useServerInfo(),
groups,
getPermissionOnGroup: (id: string) => {
const group = groups.get(id)!;
@@ -134,7 +129,6 @@ export const AppStateProvider: ParentComponent = (p) => {
}
},
updates: useUpdates(),
params,
};
// createEffect(() => {

View File

@@ -1,6 +1,6 @@
import { createEffect, createResource, createSignal } from "solid-js";
import { client } from "..";
import { ServerStatus, SystemStats, UpdateTarget } from "../types";
import { ServerStatus, SystemInformation, SystemStats, UpdateTarget } from "../types";
import {
filterOutFromObj,
getNestedEntry,
@@ -65,6 +65,32 @@ export function useServerStats() {
};
}
export function useServerInfo() {
const [info, set] = createSignal<Record<string, SystemInformation | undefined>>(
{}
);
const load = async (serverID: string) => {
const info = await client.get_server_system_info(serverID);
set((s) => ({ ...s, [serverID]: info }));
};
const loading: Record<string, boolean> = {};
return {
get: (serverID: string, serverStatus?: ServerStatus) => {
const information = info()[serverID];
if (
information === undefined &&
!loading[serverID] &&
(serverStatus ? serverStatus === ServerStatus.Ok : true)
) {
loading[serverID] = true;
load(serverID);
}
return information;
},
load,
};
}
export function useUsernames() {
const [usernames, set] = createSignal<Record<string, string | undefined>>({});
const load = async (userID: string) => {

View File

@@ -216,7 +216,13 @@ export function convert_timelength_to_ms(timelength: Timelength) {
export function readableStorageAmount(gb: number) {
if (gb > 512) {
return `${(gb / 1024).toFixed(1)} TB`
} else if (gb < 1) {
return `${(gb * 1024).toFixed()} MiB`
} else {
return `${gb.toFixed()} GiB`
}
}
export function readableVersion(version: Version) {
return `v${version.major}.${version.minor}.${version.patch}`;
}