forked from github-starred/komodo
Merge branch 'responsive'
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
import { useNavigate, useParams } from "@solidjs/router";
|
||||
import { Component, createEffect, onCleanup, Show } from "solid-js";
|
||||
import { MAX_PAGE_WIDTH } from "../..";
|
||||
import { useAppDimensions } from "../../state/DimensionProvider";
|
||||
import { useAppState } from "../../state/StateProvider";
|
||||
import { useUser } from "../../state/UserProvider";
|
||||
@@ -14,16 +13,16 @@ import Header from "./Header";
|
||||
import BuildTabs from "./tabs/Tabs";
|
||||
import Updates from "./Updates";
|
||||
|
||||
const Build2: Component<{}> = (p) => {
|
||||
const Build: Component<{}> = (p) => {
|
||||
const { builds, ws } = useAppState();
|
||||
const navigate = useNavigate();
|
||||
const params = useParams();
|
||||
const build = () => builds.get(params.id)!;
|
||||
const { isSemiMobile } = useAppDimensions();
|
||||
const { user } = useUser();
|
||||
const userCanUpdate = () =>
|
||||
user().admin ||
|
||||
build().permissions![getId(user())] === PermissionLevel.Update;
|
||||
// const { user } = useUser();
|
||||
// const userCanUpdate = () =>
|
||||
// user().admin ||
|
||||
// build().permissions![getId(user())] === PermissionLevel.Update;
|
||||
let unsub = () => {};
|
||||
createEffect(() => {
|
||||
unsub();
|
||||
@@ -39,58 +38,22 @@ const Build2: Component<{}> = (p) => {
|
||||
<ActionStateProvider>
|
||||
<Grid
|
||||
style={{
|
||||
width: "100vw",
|
||||
"max-width": `${MAX_PAGE_WIDTH}px`,
|
||||
width: "100%",
|
||||
"box-sizing": "border-box",
|
||||
}}
|
||||
>
|
||||
<Grid style={{ width: "100%" }} gridTemplateColumns="1fr 1fr">
|
||||
<Grid
|
||||
style={{ width: "100%" }}
|
||||
gridTemplateColumns={isSemiMobile() ? "1fr" : "1fr 1fr"}
|
||||
>
|
||||
<Grid style={{ "flex-grow": 1, "grid-auto-rows": "auto 1fr" }}>
|
||||
<Header />
|
||||
<Actions />
|
||||
</Grid>
|
||||
<Updates />
|
||||
</Grid>
|
||||
<BuildTabs />
|
||||
</Grid>
|
||||
</ActionStateProvider>
|
||||
</Show>
|
||||
);
|
||||
};
|
||||
|
||||
const Build: Component<{}> = (p) => {
|
||||
const { builds, ws } = useAppState();
|
||||
const navigate = useNavigate();
|
||||
const params = useParams();
|
||||
const build = () => builds.get(params.id)!;
|
||||
const { isSemiMobile } = useAppDimensions();
|
||||
const { user } = useUser();
|
||||
const userCanUpdate = () =>
|
||||
user().admin ||
|
||||
build().permissions![getId(user())] === PermissionLevel.Update;
|
||||
let unsub = () => {};
|
||||
createEffect(() => {
|
||||
unsub();
|
||||
unsub = ws.subscribe([Operation.DeleteBuild], (update) => {
|
||||
if (update.target.id === params.id) {
|
||||
navigate("/");
|
||||
}
|
||||
});
|
||||
});
|
||||
onCleanup(() => unsub);
|
||||
return (
|
||||
<Show when={build()} fallback={<NotFound type="build" />}>
|
||||
<ActionStateProvider>
|
||||
<Grid class={combineClasses("content")}>
|
||||
{/* left / actions */}
|
||||
<Grid class="left-content">
|
||||
<Header />
|
||||
<Actions />
|
||||
<Show when={!isSemiMobile() && userCanUpdate()}>
|
||||
<Show when={!isSemiMobile()}>
|
||||
<Updates />
|
||||
</Show>
|
||||
</Grid>
|
||||
{/* right / tabs */}
|
||||
<BuildTabs />
|
||||
</Grid>
|
||||
</ActionStateProvider>
|
||||
@@ -98,4 +61,4 @@ const Build: Component<{}> = (p) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default Build2;
|
||||
export default Build;
|
||||
|
||||
@@ -18,7 +18,7 @@ const Header: Component<{}> = (p) => {
|
||||
const params = useParams();
|
||||
const build = () => builds.get(params.id)!;
|
||||
const { user } = useUser();
|
||||
const { isMobile } = useAppDimensions();
|
||||
const { isSemiMobile } = useAppDimensions();
|
||||
const [showUpdates, toggleShowUpdates] =
|
||||
useLocalStorageToggle("show-updates");
|
||||
const userCanUpdate = () =>
|
||||
@@ -32,10 +32,10 @@ const Header: Component<{}> = (p) => {
|
||||
alignItems="center"
|
||||
style={{
|
||||
position: "relative",
|
||||
cursor: isMobile() && userCanUpdate() ? "pointer" : undefined,
|
||||
cursor: isSemiMobile() ? "pointer" : undefined,
|
||||
}}
|
||||
onClick={() => {
|
||||
if (isMobile() && userCanUpdate()) toggleShowUpdates();
|
||||
if (isSemiMobile()) toggleShowUpdates();
|
||||
}}
|
||||
>
|
||||
<Grid gap="0.1rem">
|
||||
@@ -54,7 +54,7 @@ const Header: Component<{}> = (p) => {
|
||||
<Icon type="trash" />
|
||||
</ConfirmButton>
|
||||
</Show>
|
||||
<Show when={isMobile() && userCanUpdate()}>
|
||||
<Show when={isSemiMobile()}>
|
||||
<Flex gap="0.5rem" alignItems="center" class="show-updates-indicator">
|
||||
updates{" "}
|
||||
<Icon
|
||||
@@ -64,7 +64,7 @@ const Header: Component<{}> = (p) => {
|
||||
</Flex>
|
||||
</Show>
|
||||
</Flex>
|
||||
<Show when={isMobile() && userCanUpdate() && showUpdates()}>
|
||||
<Show when={isSemiMobile() && showUpdates()}>
|
||||
<Updates />
|
||||
</Show>
|
||||
</>
|
||||
|
||||
@@ -17,6 +17,7 @@ import Updates from "./Updates";
|
||||
|
||||
const Deployment2: Component<{}> = (p) => {
|
||||
const { servers, deployments } = useAppState();
|
||||
const { isSemiMobile, isMobile } = useAppDimensions();
|
||||
const params = useParams();
|
||||
const deployment = () => deployments.get(params.id);
|
||||
const server = () =>
|
||||
@@ -29,17 +30,21 @@ const Deployment2: Component<{}> = (p) => {
|
||||
<ActionStateProvider>
|
||||
<Grid
|
||||
style={{
|
||||
width: "100vw",
|
||||
"max-width": `${MAX_PAGE_WIDTH}px`,
|
||||
width: "100%",
|
||||
"box-sizing": "border-box",
|
||||
}}
|
||||
>
|
||||
<Grid style={{ width: "100%" }} gridTemplateColumns="1fr 1fr">
|
||||
<Grid
|
||||
style={{ width: "100%" }}
|
||||
gridTemplateColumns={isSemiMobile() ? "1fr" : "1fr 1fr"}
|
||||
>
|
||||
<Grid style={{ "flex-grow": 1, "grid-auto-rows": "auto 1fr" }}>
|
||||
<Header />
|
||||
<Actions />
|
||||
</Grid>
|
||||
<Updates />
|
||||
<Show when={!isMobile()}>
|
||||
<Updates />
|
||||
</Show>
|
||||
</Grid>
|
||||
<DeploymentTabs />
|
||||
</Grid>
|
||||
|
||||
@@ -24,7 +24,7 @@ const Header: Component<{}> = (p) => {
|
||||
deployment()!.state === DockerContainerState.NotDeployed
|
||||
? undefined
|
||||
: deployment().container?.status?.toLowerCase();
|
||||
const { isMobile } = useAppDimensions();
|
||||
const { isSemiMobile } = useAppDimensions();
|
||||
const [showUpdates, toggleShowUpdates] =
|
||||
useLocalStorageToggle("show-updates");
|
||||
const userCanUpdate = () =>
|
||||
@@ -38,11 +38,11 @@ const Header: Component<{}> = (p) => {
|
||||
class={combineClasses("card shadow")}
|
||||
style={{
|
||||
position: "relative",
|
||||
cursor: isMobile() && userCanUpdate() ? "pointer" : undefined,
|
||||
height: "fit-content"
|
||||
cursor: isSemiMobile() && userCanUpdate() ? "pointer" : undefined,
|
||||
height: "fit-content",
|
||||
}}
|
||||
onClick={() => {
|
||||
if (isMobile() && userCanUpdate()) toggleShowUpdates();
|
||||
if (isSemiMobile() && userCanUpdate()) toggleShowUpdates();
|
||||
}}
|
||||
>
|
||||
<Flex alignItems="center" justifyContent="space-between">
|
||||
@@ -52,7 +52,7 @@ const Header: Component<{}> = (p) => {
|
||||
target={
|
||||
<ConfirmButton
|
||||
onConfirm={() => {
|
||||
client.delete_deployment(params.id)
|
||||
client.delete_deployment(params.id);
|
||||
}}
|
||||
class="red"
|
||||
>
|
||||
@@ -73,7 +73,7 @@ const Header: Component<{}> = (p) => {
|
||||
<div style={{ opacity: 0.7 }}>{status()}</div>
|
||||
</Show>
|
||||
</Flex>
|
||||
<Show when={isMobile() && userCanUpdate()}>
|
||||
<Show when={isSemiMobile()}>
|
||||
<Flex gap="0.5rem" alignItems="center" class="show-updates-indicator">
|
||||
updates{" "}
|
||||
<Icon
|
||||
@@ -83,7 +83,7 @@ const Header: Component<{}> = (p) => {
|
||||
</Flex>
|
||||
</Show>
|
||||
</Grid>
|
||||
<Show when={isMobile() && userCanUpdate() && showUpdates()}>
|
||||
<Show when={isSemiMobile() && showUpdates()}>
|
||||
<Updates />
|
||||
</Show>
|
||||
</>
|
||||
|
||||
@@ -19,24 +19,20 @@ const Home2: Component<{}> = (p) => {
|
||||
// const { width } = useAppDimensions();
|
||||
const { servers } = useAppState();
|
||||
return (
|
||||
<Grid placeItems="center start" style={{ "width": "100vw", "max-width": `${MAX_PAGE_WIDTH}px`, "box-sizing": "border-box" }}>
|
||||
{/* <Summary /> */}
|
||||
<SimpleTabs
|
||||
containerStyle={{ width: "100%" }}
|
||||
localStorageKey="home-groups-servers-tab-v1"
|
||||
tabs={[
|
||||
{
|
||||
title: "groups",
|
||||
element: () => <Groups />,
|
||||
},
|
||||
{
|
||||
title: "servers",
|
||||
element: () => <Servers serverIDs={servers.ids()!} showAdd />,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
{/* <Updates /> */}
|
||||
</Grid>
|
||||
<SimpleTabs
|
||||
containerStyle={{ width: "100%" }}
|
||||
localStorageKey="home-groups-servers-tab-v1"
|
||||
tabs={[
|
||||
{
|
||||
title: "groups",
|
||||
element: () => <Groups />,
|
||||
},
|
||||
{
|
||||
title: "servers",
|
||||
element: () => <Servers serverIDs={servers.ids()!} showAdd />,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -69,6 +69,7 @@ const Group: Component<{ id: string }> = (p) => {
|
||||
<h1 style={{ "font-size": "1.25rem" }}>{group()?.name}</h1>
|
||||
</Flex>
|
||||
<Flex alignItems="center">
|
||||
<h2>{serverIDs()!.length} server{serverIDs()!.length > 1 ? "s" : ""}</h2>
|
||||
<Show when={open()}>
|
||||
<button
|
||||
class="blue"
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
} from "solid-js";
|
||||
import { useAppState } from "../../../state/StateProvider";
|
||||
import { useUser } from "../../../state/UserProvider";
|
||||
import { combineClasses, getId } from "../../../util/helpers";
|
||||
import { combineClasses, getId, readableStorageAmount } from "../../../util/helpers";
|
||||
import { useLocalStorageToggle } from "../../../util/hooks";
|
||||
import Icon from "../../shared/Icon";
|
||||
import Flex from "../../shared/layout/Flex";
|
||||
@@ -25,7 +25,7 @@ import SimpleTabs from "../../shared/tabs/SimpleTabs";
|
||||
|
||||
const Server: Component<{ id: string }> = (p) => {
|
||||
const { servers, serverStats, deployments, builds } = useAppState();
|
||||
const { width } = useAppDimensions();
|
||||
const { isSemiMobile } = useAppDimensions();
|
||||
const { user } = useUser();
|
||||
const [open, toggleOpen] = useLocalStorageToggle(p.id + "-homeopen");
|
||||
const server = () => servers.get(p.id);
|
||||
@@ -43,13 +43,6 @@ const Server: Component<{ id: string }> = (p) => {
|
||||
.ids()!
|
||||
.filter((id) => builds.get(id)?.server_id === p.id)) as string[];
|
||||
});
|
||||
const [reloading, setReloading] = createSignal(false);
|
||||
const stats = () => serverStats.get(p.id);
|
||||
const reloadStats = async () => {
|
||||
setReloading(true);
|
||||
await serverStats.load(p.id);
|
||||
setReloading(false);
|
||||
};
|
||||
return (
|
||||
<Show when={server()}>
|
||||
<div class={combineClasses(s.Server, "shadow")}>
|
||||
@@ -62,54 +55,7 @@ const Server: Component<{ id: string }> = (p) => {
|
||||
<h1 style={{ "font-size": "1.25rem" }}>{server()?.server.name}</h1>
|
||||
</Flex>
|
||||
<Flex alignItems="center">
|
||||
<Show when={width() > 500 && server()?.status === ServerStatus.Ok}>
|
||||
<Show when={stats()} fallback={<Loading type="three-dot" />}>
|
||||
<div>
|
||||
<div style={{ opacity: 0.7 }}>cpu:</div>{" "}
|
||||
{stats()!.cpu_perc.toFixed(1)}%
|
||||
</div>
|
||||
<div>
|
||||
<div style={{ opacity: 0.7 }}>mem:</div>{" "}
|
||||
{(
|
||||
(100 * stats()!.mem_used_gb) /
|
||||
stats()!.mem_total_gb
|
||||
).toFixed(1)}
|
||||
%
|
||||
</div>
|
||||
<div>
|
||||
<div style={{ opacity: 0.7 }}>disk:</div>{" "}
|
||||
{(
|
||||
(100 * stats()!.disk.used_gb) /
|
||||
stats()!.disk.total_gb
|
||||
).toFixed(1)}
|
||||
%
|
||||
</div>
|
||||
<Flex gap=".5rem" alignItems="center">
|
||||
<Show
|
||||
when={!reloading()}
|
||||
fallback={
|
||||
<button class="blue" style={{ height: "fit-content" }}>
|
||||
<Loading type="spinner" scale={0.2} />
|
||||
</button>
|
||||
}
|
||||
>
|
||||
<button
|
||||
class="blue"
|
||||
style={{ height: "fit-content" }}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
reloadStats();
|
||||
}}
|
||||
>
|
||||
<Icon type="refresh" width="0.85rem" />
|
||||
</button>
|
||||
</Show>
|
||||
<A href={`/server/${p.id}/stats`} class="blue" onClick={e => e.stopPropagation()}>
|
||||
<Icon type="timeline-line-chart" />
|
||||
</A>
|
||||
</Flex>
|
||||
</Show>
|
||||
</Show>
|
||||
<ServerStats id={p.id} />
|
||||
<A
|
||||
href={`/server/${p.id}`}
|
||||
class={
|
||||
@@ -146,6 +92,7 @@ const Server: Component<{ id: string }> = (p) => {
|
||||
s.Deployments,
|
||||
open() ? s.Enter : s.Exit
|
||||
)}
|
||||
gridTemplateColumns={isSemiMobile() ? "1fr" : "1fr 1fr"}
|
||||
>
|
||||
<For each={deploymentIDs()}>
|
||||
{(id) => <Deployment id={id} />}
|
||||
@@ -171,6 +118,7 @@ const Server: Component<{ id: string }> = (p) => {
|
||||
s.Deployments,
|
||||
open() ? s.Enter : s.Exit
|
||||
)}
|
||||
gridTemplateColumns={isSemiMobile() ? "1fr" : "1fr 1fr"}
|
||||
>
|
||||
<For each={buildIDs()}>{(id) => <Build id={id} />}</For>
|
||||
<Show
|
||||
@@ -194,3 +142,110 @@ const Server: Component<{ id: string }> = (p) => {
|
||||
};
|
||||
|
||||
export default Server;
|
||||
|
||||
const ServerStats: Component<{ id: string }> = (p) => {
|
||||
const { servers, serverStats } = useAppState();
|
||||
const { isMobile, isSemiMobile } = useAppDimensions();
|
||||
const server = () => servers.get(p.id);
|
||||
const [reloading, setReloading] = createSignal(false);
|
||||
const stats = () => serverStats.get(p.id);
|
||||
const reloadStats = async () => {
|
||||
setReloading(true);
|
||||
await serverStats.load(p.id);
|
||||
setReloading(false);
|
||||
};
|
||||
return (
|
||||
<Show when={!isMobile() && server()?.status === ServerStatus.Ok}>
|
||||
<Show when={stats()} fallback={<Loading type="three-dot" />}>
|
||||
<Grid
|
||||
// gap="0.25rem"
|
||||
placeItems="center"
|
||||
gridTemplateColumns={
|
||||
isSemiMobile() ? "100px 100px 100px" : "90px 160px 160px"
|
||||
}
|
||||
>
|
||||
<Flex
|
||||
style={{
|
||||
width: "100%",
|
||||
"box-sizing": "border-box",
|
||||
}}
|
||||
gap="0.5rem"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
>
|
||||
<div style={{ opacity: 0.7 }}>cpu:</div>
|
||||
<h2>{stats()!.cpu_perc.toFixed(1)}%</h2>
|
||||
</Flex>
|
||||
<Flex
|
||||
style={{
|
||||
width: "100%",
|
||||
"box-sizing": "border-box",
|
||||
}}
|
||||
gap="0.5rem"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
>
|
||||
<div style={{ opacity: 0.7 }}>mem:</div>
|
||||
<h2>
|
||||
{((100 * stats()!.mem_used_gb) / stats()!.mem_total_gb).toFixed(
|
||||
1
|
||||
)}
|
||||
%
|
||||
</h2>
|
||||
<Show when={!isSemiMobile()}>
|
||||
<div>{stats()!.mem_total_gb.toFixed()} GiB</div>
|
||||
</Show>
|
||||
</Flex>
|
||||
<Flex
|
||||
style={{
|
||||
width: "100%",
|
||||
"box-sizing": "border-box",
|
||||
}}
|
||||
gap="0.5rem"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
>
|
||||
<div style={{ opacity: 0.7 }}>disk:</div>
|
||||
<h2>
|
||||
{((100 * stats()!.disk.used_gb) / stats()!.disk.total_gb).toFixed(
|
||||
1
|
||||
)}
|
||||
%
|
||||
</h2>
|
||||
<Show when={!isSemiMobile()}>
|
||||
<div>{readableStorageAmount(stats()!.disk.total_gb)}</div>
|
||||
</Show>
|
||||
</Flex>
|
||||
</Grid>
|
||||
<Flex gap=".5rem" alignItems="center">
|
||||
<Show
|
||||
when={!reloading()}
|
||||
fallback={
|
||||
<button class="blue" style={{ height: "fit-content" }}>
|
||||
<Loading type="spinner" scale={0.2} />
|
||||
</button>
|
||||
}
|
||||
>
|
||||
<button
|
||||
class="blue"
|
||||
style={{ height: "fit-content" }}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
reloadStats();
|
||||
}}
|
||||
>
|
||||
<Icon type="refresh" width="0.85rem" />
|
||||
</button>
|
||||
</Show>
|
||||
<A
|
||||
href={`/server/${p.id}/stats`}
|
||||
class="blue"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<Icon type="timeline-line-chart" />
|
||||
</A>
|
||||
</Flex>
|
||||
</Show>
|
||||
</Show>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
@use "../../style/colors.scss" as c;
|
||||
|
||||
.Home {
|
||||
width: 100%;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1200px) {
|
||||
.Home {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.SummaryItem {
|
||||
background-color: c.$lightgrey;
|
||||
padding: 1rem;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Component, Show } from "solid-js";
|
||||
import { Component, createResource, Show } from "solid-js";
|
||||
import { useAppState } from "../../state/StateProvider";
|
||||
import { useUser } from "../../state/UserProvider";
|
||||
import { combineClasses, getId, serverStatusClass } from "../../util/helpers";
|
||||
@@ -12,6 +12,7 @@ import Updates from "./Updates";
|
||||
import { PermissionLevel, Server } from "../../types";
|
||||
import { A, useParams } from "@solidjs/router";
|
||||
import { client } from "../..";
|
||||
import Loading from "../shared/loading/Loading";
|
||||
|
||||
const Header: Component<{}> = (p) => {
|
||||
const { servers } = useAppState();
|
||||
@@ -19,12 +20,15 @@ const Header: Component<{}> = (p) => {
|
||||
const server = () => servers.get(params.id)!;
|
||||
const status = () => server().status.replaceAll("_", " ").toUpperCase();
|
||||
const { user } = useUser();
|
||||
const { isMobile } = useAppDimensions();
|
||||
const { isMobile, isSemiMobile } = useAppDimensions();
|
||||
const [showUpdates, toggleShowUpdates] =
|
||||
useLocalStorageToggle("show-updates");
|
||||
const userCanUpdate = () =>
|
||||
user().admin ||
|
||||
server().server.permissions![getId(user())] === PermissionLevel.Update;
|
||||
const [version] = createResource(async () => {
|
||||
return await client.get_server_version(params.id).catch();
|
||||
});
|
||||
return (
|
||||
<>
|
||||
<Flex
|
||||
@@ -33,10 +37,10 @@ const Header: Component<{}> = (p) => {
|
||||
alignItems="center"
|
||||
style={{
|
||||
position: "relative",
|
||||
cursor: isMobile() && userCanUpdate() ? "pointer" : undefined,
|
||||
cursor: isSemiMobile() ? "pointer" : undefined,
|
||||
}}
|
||||
onClick={() => {
|
||||
if (isMobile() && userCanUpdate()) toggleShowUpdates();
|
||||
if (isSemiMobile()) toggleShowUpdates();
|
||||
}}
|
||||
>
|
||||
<Grid gap="0.1rem">
|
||||
@@ -50,6 +54,11 @@ const Header: Component<{}> = (p) => {
|
||||
</Flex>
|
||||
</Grid>
|
||||
<Flex alignItems="center">
|
||||
<Show when={!isMobile()}>
|
||||
<Show when={version()} fallback={<Loading type="three-dot" />}>
|
||||
<div style={{ opacity: 0.7 }}>periphery v{version()}</div>
|
||||
</Show>
|
||||
</Show>
|
||||
<div class={serverStatusClass(server().status)}>{status()}</div>
|
||||
<A
|
||||
href={`/server/${params.id}/stats`}
|
||||
@@ -69,7 +78,7 @@ const Header: Component<{}> = (p) => {
|
||||
</ConfirmButton>
|
||||
</Show>
|
||||
</Flex>
|
||||
<Show when={isMobile() && userCanUpdate()}>
|
||||
<Show when={isSemiMobile()}>
|
||||
<Flex gap="0.5rem" alignItems="center" class="show-updates-indicator">
|
||||
updates{" "}
|
||||
<Icon
|
||||
@@ -79,7 +88,7 @@ const Header: Component<{}> = (p) => {
|
||||
</Flex>
|
||||
</Show>
|
||||
</Flex>
|
||||
<Show when={isMobile() && userCanUpdate() && showUpdates()}>
|
||||
<Show when={isSemiMobile() && showUpdates()}>
|
||||
<Updates />
|
||||
</Show>
|
||||
</>
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
import { useParams } from "@solidjs/router";
|
||||
import { Component, Show } from "solid-js";
|
||||
import { MAX_PAGE_WIDTH } from "../..";
|
||||
import { useAppDimensions } from "../../state/DimensionProvider";
|
||||
import { useAppState } from "../../state/StateProvider";
|
||||
import { useUser } from "../../state/UserProvider";
|
||||
import { PermissionLevel } from "../../types";
|
||||
import { combineClasses, getId } from "../../util/helpers";
|
||||
import NotFound from "../NotFound";
|
||||
import Flex from "../shared/layout/Flex";
|
||||
import Grid from "../shared/layout/Grid";
|
||||
import Actions from "./Actions";
|
||||
import { ActionStateProvider } from "./ActionStateProvider";
|
||||
@@ -15,11 +10,11 @@ import Header from "./Header";
|
||||
import ServerTabs from "./tabs/Tabs";
|
||||
import Updates from "./Updates";
|
||||
|
||||
const Server2: Component<{}> = (p) => {
|
||||
const Server: Component<{}> = (p) => {
|
||||
const { servers } = useAppState();
|
||||
const params = useParams();
|
||||
const server = () => servers.get(params.id)!;
|
||||
const { user } = useUser();
|
||||
const { isSemiMobile } = useAppDimensions();
|
||||
// const userCanUpdate = () =>
|
||||
// user().admin ||
|
||||
// server()!.server.permissions![getId(user())] === PermissionLevel.Update;
|
||||
@@ -28,47 +23,22 @@ const Server2: Component<{}> = (p) => {
|
||||
<ActionStateProvider>
|
||||
<Grid
|
||||
style={{
|
||||
width: "100vw",
|
||||
"max-width": `${MAX_PAGE_WIDTH}px`,
|
||||
width: "100%",
|
||||
"box-sizing": "border-box",
|
||||
}}
|
||||
>
|
||||
<Grid style={{ width: "100%" }} gridTemplateColumns="1fr 1fr">
|
||||
<Grid
|
||||
style={{ width: "100%" }}
|
||||
gridTemplateColumns={isSemiMobile() ? "1fr" : "1fr 1fr"}
|
||||
>
|
||||
<Grid>
|
||||
<Header />
|
||||
<Actions />
|
||||
</Grid>
|
||||
<Updates />
|
||||
</Grid>
|
||||
<ServerTabs />
|
||||
</Grid>
|
||||
</ActionStateProvider>
|
||||
</Show>
|
||||
);
|
||||
};
|
||||
|
||||
const Server: Component<{}> = (p) => {
|
||||
const { servers } = useAppState();
|
||||
const params = useParams();
|
||||
const server = () => servers.get(params.id)!;
|
||||
const { isSemiMobile } = useAppDimensions();
|
||||
const { user } = useUser();
|
||||
const userCanUpdate = () =>
|
||||
user().admin ||
|
||||
server()!.server.permissions![getId(user())] === PermissionLevel.Update;
|
||||
return (
|
||||
<Show when={server()} fallback={<NotFound type="server" />}>
|
||||
<ActionStateProvider>
|
||||
<Grid class={combineClasses("content")}>
|
||||
{/* left / actions */}
|
||||
<Grid class="left-content">
|
||||
<Header />
|
||||
<Actions />
|
||||
<Show when={!isSemiMobile() && userCanUpdate()}>
|
||||
<Show when={!isSemiMobile()}>
|
||||
<Updates />
|
||||
</Show>
|
||||
</Grid>
|
||||
{/* right / tabs */}
|
||||
<ServerTabs />
|
||||
</Grid>
|
||||
</ActionStateProvider>
|
||||
@@ -76,4 +46,4 @@ const Server: Component<{}> = (p) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default Server2;
|
||||
export default Server;
|
||||
|
||||
@@ -78,7 +78,6 @@ const CurrentStats2: Component<{}> = (p) => {
|
||||
style={{
|
||||
width: "100%",
|
||||
"box-sizing": "border-box",
|
||||
"max-width": `${MAX_PAGE_WIDTH}px`,
|
||||
}}
|
||||
gridTemplateColumns="auto 1fr auto"
|
||||
>
|
||||
|
||||
@@ -39,8 +39,7 @@ const StatsComp: Component<{}> = () => {
|
||||
return (
|
||||
<Grid
|
||||
style={{
|
||||
width: "100vw",
|
||||
"max-width": `${MAX_PAGE_WIDTH}px`,
|
||||
width: "100%",
|
||||
"box-sizing": "border-box",
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -27,7 +27,7 @@ const mobileStyle: JSX.CSSProperties = {
|
||||
};
|
||||
|
||||
export const Search: Component<{}> = (p) => {
|
||||
const { isMobile } = useAppDimensions();
|
||||
const { isSemiMobile } = useAppDimensions();
|
||||
const { search, open, input } = useSearchState();
|
||||
let inputRef: HTMLInputElement | undefined;
|
||||
useWindowKeyDown((e) => {
|
||||
@@ -44,12 +44,12 @@ export const Search: Component<{}> = (p) => {
|
||||
menuClass={s.SearchMenu}
|
||||
menuStyle={{
|
||||
gap: "0.5rem",
|
||||
...(isMobile() ? mobileStyle : {}),
|
||||
...(isSemiMobile() ? mobileStyle : {}),
|
||||
}}
|
||||
backgroundColor={isMobile() ? "rgba(0,0,0,0.6)" : "rgba(0,0,0,0.4)"}
|
||||
backgroundColor={isSemiMobile() ? "rgba(0,0,0,0.6)" : "rgba(0,0,0,0.4)"}
|
||||
target={
|
||||
<Show
|
||||
when={!isMobile()}
|
||||
when={!isSemiMobile()}
|
||||
fallback={
|
||||
<button class="grey" onClick={() => open.set(true)}>
|
||||
<Icon type="search" width="1.15rem" />
|
||||
|
||||
@@ -29,7 +29,7 @@ const Topbar: Component = () => {
|
||||
<Grid
|
||||
class={combineClasses(s.Topbar, "shadow")}
|
||||
placeItems="center"
|
||||
style={{ height: inPx(TOPBAR_HEIGHT) }}
|
||||
style={{ height: inPx(TOPBAR_HEIGHT), width: "100%" }}
|
||||
>
|
||||
<LeftSide />
|
||||
<SearchProvider>
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
@use "../../style/colors.scss" as c;
|
||||
|
||||
.Topbar {
|
||||
grid-area: topbar;
|
||||
width: 100vw;
|
||||
max-width: 1200px;
|
||||
box-sizing: border-box;
|
||||
background-color: c.$grey;
|
||||
z-index: 90;
|
||||
|
||||
@@ -3,14 +3,12 @@
|
||||
.app {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: auto auto;
|
||||
gap: 1rem;
|
||||
padding: 1rem;
|
||||
width: 100vw;
|
||||
max-width: calc(1200px + 2rem);
|
||||
box-sizing: border-box;
|
||||
grid-template-areas:
|
||||
"topbar"
|
||||
"content";
|
||||
place-items: start center;
|
||||
place-items: center;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1200px) {
|
||||
|
||||
@@ -10,6 +10,10 @@ body {
|
||||
|
||||
background-color: c.$darkgrey;
|
||||
color: c.$app-color;
|
||||
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
place-items: center;
|
||||
}
|
||||
|
||||
code {
|
||||
@@ -96,6 +100,12 @@ input {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 700px) {
|
||||
input {
|
||||
width: 200px;
|
||||
}
|
||||
}
|
||||
|
||||
input:focus {
|
||||
outline: solid 1px rgba(c.$lightgrey, 0.7);
|
||||
}
|
||||
|
||||
@@ -211,4 +211,12 @@ export function convert_timelength_to_ms(timelength: Timelength) {
|
||||
} else if (timelength === Timelength.OneMinute) {
|
||||
return 60000;
|
||||
}
|
||||
}
|
||||
|
||||
export function readableStorageAmount(gb: number) {
|
||||
if (gb > 512) {
|
||||
return `${(gb / 1024).toFixed(1)} TB`
|
||||
} else {
|
||||
return `${gb.toFixed()} GiB`
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user