forked from github-starred/komodo
server info tab
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
"scripts": {
|
||||
"start": "vite",
|
||||
"dev": "vite",
|
||||
"check": "tsc",
|
||||
"build": "vite build && node post-build.mjs",
|
||||
"serve": "vite preview"
|
||||
},
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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(() => {
|
||||
|
||||
@@ -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
|
||||
|
||||
98
frontend/src/components/server/tabs/Info.tsx
Normal file
98
frontend/src/components/server/tabs/Info.tsx
Normal 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;
|
||||
@@ -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 />,
|
||||
|
||||
@@ -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(() => {
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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}`;
|
||||
}
|
||||
Reference in New Issue
Block a user