implement description

This commit is contained in:
mbecker20
2023-03-01 09:46:50 +00:00
parent 5a2a1a3d98
commit 1b39aaaa38
9 changed files with 207 additions and 32 deletions

View File

@@ -170,7 +170,7 @@ impl State {
self.get_deployment_check_permissions(id, user, PermissionLevel::Update)
.await?;
self.db
.builds
.deployments
.update_one::<()>(id, mungos::Update::Set(doc! { "description": description }))
.await?;
}
@@ -178,7 +178,7 @@ impl State {
self.get_server_check_permissions(id, user, PermissionLevel::Update)
.await?;
self.db
.builds
.servers
.update_one::<()>(id, mungos::Update::Set(doc! { "description": description }))
.await?;
}
@@ -186,7 +186,7 @@ impl State {
self.get_group_check_permissions(id, user, PermissionLevel::Update)
.await?;
self.db
.builds
.groups
.update_one::<()>(id, mungos::Update::Set(doc! { "description": description }))
.await?;
}
@@ -194,7 +194,7 @@ impl State {
self.get_procedure_check_permissions(id, user, PermissionLevel::Update)
.await?;
self.db
.builds
.procedures
.update_one::<()>(id, mungos::Update::Set(doc! { "description": description }))
.await?;
}

View File

@@ -0,0 +1,125 @@
import { Component, createSignal, onMount, Show } from "solid-js";
import { client, pushNotification } from "..";
import { useAppState } from "../state/StateProvider";
import { UpdateTarget } from "../types";
import { useToggle } from "../util/hooks";
import ConfirmButton from "./shared/ConfirmButton";
import Flex from "./shared/layout/Flex";
import Grid from "./shared/layout/Grid";
import Loading from "./shared/loading/Loading";
import CenterMenu from "./shared/menu/CenterMenu";
import TextArea from "./shared/TextArea";
const Description: Component<{
name: string;
target: UpdateTarget;
description?: string;
userCanUpdate: boolean;
}> = (p) => {
const [show, toggleShow] = useToggle();
const description = () => {
if (p.description) {
return p.description;
} else {
return "add a description";
}
};
const [width, setWidth] = createSignal<number>();
onMount(() => {
setWidth(ref!?.clientWidth);
});
let ref: HTMLDivElement;
return (
<CenterMenu
show={show}
toggleShow={toggleShow}
title={`description | ${p.name}`}
targetClass="card grey"
targetStyle={{ width: "100%", "justify-content": "flex-start" }}
target={
<div
ref={ref! as any}
class="ellipsis"
style={{
opacity: 0.7,
width: width() ? `${width()}px` : "100%",
"box-sizing": "border-box",
"text-align": "left"
}}
>
{width() ? description() : ""}
</div>
}
content={() => (
<DescriptionMenu
target={p.target}
description={p.description}
userCanUpdate={p.userCanUpdate}
toggleShow={toggleShow}
/>
)}
/>
);
};
const DescriptionMenu: Component<{
target: UpdateTarget;
description?: string;
userCanUpdate: boolean;
toggleShow: () => void;
}> = (p) => {
const { builds, servers, deployments } = useAppState();
let ref: HTMLTextAreaElement;
onMount(() => {
ref?.focus();
});
const [desc, setDesc] = createSignal(p.description);
const [loading, setLoading] = createSignal(false);
const update_description = () => {
setLoading(true);
client
.update_description({ target: p.target, description: desc() || "" })
.then(() => {
if (p.target.type === "Build") {
builds.update({ ...builds.get(p.target.id)!, description: desc() });
} else if (p.target.type === "Deployment") {
const deployment = deployments.get(p.target.id)!;
deployments.update({
...deployment,
deployment: { ...deployment.deployment, description: desc() },
});
} else if (p.target.type === "Server") {
const server = servers.get(p.target.id)!;
servers.update({
...server,
server: { ...server.server, description: desc() },
});
}
p.toggleShow();
})
.catch(() => {
pushNotification("bad", "failed to update description");
p.toggleShow();
});
};
return (
<Grid placeItems="center">
<TextArea
ref={ref! as any}
placeholder="add a description"
value={desc()}
onEdit={setDesc}
onEnter={update_description}
style={{ width: "700px", "max-width": "90vw", padding: "1rem" }}
disabled={!p.userCanUpdate}
/>
<Show when={!loading()} fallback={<Loading />}>
<button class="green" onClick={update_description}>
update
</button>
</Show>
</Grid>
);
};
export default Description;

View File

@@ -1,19 +1,24 @@
import { Component } from "solid-js";
import { Component, Show } from "solid-js";
import Grid from "./shared/layout/Grid";
import Loading from "./shared/loading/Loading";
const NotFound: Component<{ type: "deployment" | "server" | "build" }> = (p) => {
return (
<Grid
placeItems="center"
style={{ height: "100%", width: "100%" }}
>
<Grid placeItems="center" style={{ width: "fit-content", height: "fit-content" }}>
<h2>{p.type} at id not found</h2>
const NotFound: Component<{
type: "deployment" | "server" | "build";
loaded: boolean;
}> = (p) => {
return (
<Grid placeItems="center" style={{ height: "100%", width: "100%" }}>
<Grid
placeItems="center"
style={{ width: "fit-content", height: "fit-content" }}
>
<Show when={p.loaded} fallback={<h2>loading {p.type}...</h2>}>
<h2>{p.type} at id not found</h2>
</Show>
<Loading type="sonar" />
</Grid>
</Grid>
);
}
};
export default NotFound;
export default NotFound;

View File

@@ -2,7 +2,9 @@ import { useNavigate, useParams } from "@solidjs/router";
import { Component, createEffect, onCleanup, Show } from "solid-js";
import { useAppDimensions } from "../../state/DimensionProvider";
import { useAppState } from "../../state/StateProvider";
import { Operation } from "../../types";
import { useUser } from "../../state/UserProvider";
import { Operation, PermissionLevel } from "../../types";
import Description from "../Description";
import NotFound from "../NotFound";
import Grid from "../shared/layout/Grid";
import Actions from "./Actions";
@@ -12,6 +14,7 @@ import BuildTabs from "./tabs/Tabs";
import Updates from "./Updates";
const Build: Component<{}> = (p) => {
const { user, user_id } = useUser();
const { builds, ws } = useAppState();
const navigate = useNavigate();
const params = useParams();
@@ -31,8 +34,11 @@ const Build: Component<{}> = (p) => {
});
});
onCleanup(() => unsub);
const userCanUpdate = () =>
user().admin ||
build()?.permissions![user_id()] === PermissionLevel.Update;
return (
<Show when={build()} fallback={<NotFound type="build" />}>
<Show when={build()} fallback={<NotFound type="build" loaded={builds.loaded()} />}>
<ActionStateProvider build_id={params.id}>
<Grid
style={{
@@ -44,8 +50,14 @@ const Build: Component<{}> = (p) => {
style={{ width: "100%" }}
gridTemplateColumns={isSemiMobile() ? "1fr" : "1fr 1fr"}
>
<Grid style={{ "flex-grow": 1, "grid-auto-rows": "auto 1fr" }}>
<Grid style={{ "flex-grow": 1, "grid-auto-rows": "auto auto 1fr" }}>
<Header />
<Description
target={{ type: "Build", id: params.id }}
name={build()?.name!}
description={build()?.description}
userCanUpdate={userCanUpdate()}
/>
<Actions />
</Grid>
<Show when={!isSemiMobile()}>

View File

@@ -1,9 +1,10 @@
import { useParams } from "@solidjs/router";
import { Component, onCleanup, Show } from "solid-js";
import { client } from "../..";
import { Component, Show } from "solid-js";
import { useAppDimensions } from "../../state/DimensionProvider";
import { useAppState } from "../../state/StateProvider";
import { ServerStatus } from "../../types";
import { useUser } from "../../state/UserProvider";
import { PermissionLevel } from "../../types";
import Description from "../Description";
import NotFound from "../NotFound";
import Grid from "../shared/layout/Grid";
import Actions from "./Actions";
@@ -16,12 +17,16 @@ const POLLING_RATE = 10000;
// let interval = -1;
const Deployment: Component<{}> = (p) => {
const { user, user_id } = useUser();
const { servers, deployments } = useAppState();
const { isSemiMobile } = useAppDimensions();
const params = useParams();
const deployment = () => deployments.get(params.id);
const server = () =>
deployment() && servers.get(deployment()!.deployment.server_id);
const userCanUpdate = () =>
user().admin ||
deployment()?.deployment.permissions![user_id()] === PermissionLevel.Update;
// clearInterval(interval);
// interval = setInterval(async () => {
// if (server()?.status === ServerStatus.Ok) {
@@ -33,7 +38,7 @@ const Deployment: Component<{}> = (p) => {
return (
<Show
when={deployment() && server()}
fallback={<NotFound type="deployment" />}
fallback={<NotFound type="deployment" loaded={deployments.loaded()} />}
>
<ActionStateProvider>
<Grid
@@ -46,8 +51,14 @@ const Deployment: Component<{}> = (p) => {
style={{ width: "100%" }}
gridTemplateColumns={isSemiMobile() ? "1fr" : "1fr 1fr"}
>
<Grid style={{ "flex-grow": 1, "grid-auto-rows": "auto 1fr" }}>
<Grid style={{ "flex-grow": 1, "grid-auto-rows": "auto auto 1fr" }}>
<Header />
<Description
target={{ type: "Deployment", id: params.id }}
name={deployment()?.deployment.name!}
description={deployment()?.deployment.description}
userCanUpdate={userCanUpdate()}
/>
<Actions />
</Grid>
<Show when={!isSemiMobile()}>

View File

@@ -2,6 +2,9 @@ import { useParams } from "@solidjs/router";
import { Component, Show } from "solid-js";
import { useAppDimensions } from "../../state/DimensionProvider";
import { useAppState } from "../../state/StateProvider";
import { useUser } from "../../state/UserProvider";
import { PermissionLevel } from "../../types";
import Description from "../Description";
import NotFound from "../NotFound";
import ServerChildren from "../server_children/ServerChildren";
import Grid from "../shared/layout/Grid";
@@ -12,15 +15,16 @@ import ServerTabs from "./tabs/Tabs";
import Updates from "./Updates";
const Server: Component<{}> = (p) => {
const { user, user_id } = useUser();
const { servers } = useAppState();
const params = useParams();
const server = () => servers.get(params.id)!;
const { isSemiMobile } = useAppDimensions();
// const userCanUpdate = () =>
// user().admin ||
// server()!.server.permissions![getId(user())] === PermissionLevel.Update;
const userCanUpdate = () =>
user().admin ||
server()?.server.permissions![user_id()] === PermissionLevel.Update;
return (
<Show when={server()} fallback={<NotFound type="server" />}>
<Show when={server()} fallback={<NotFound type="server" loaded={servers.loaded()} />}>
<ActionStateProvider>
<Grid
style={{
@@ -32,8 +36,14 @@ const Server: Component<{}> = (p) => {
style={{ width: "100%" }}
gridTemplateColumns={isSemiMobile() ? "1fr" : "1fr 1fr"}
>
<Grid style={{ "flex-grow": 1, "grid-auto-rows": "auto 1fr" }}>
<Grid style={{ "flex-grow": 1, "grid-auto-rows": "auto auto 1fr" }}>
<Header />
<Description
target={{ type: "Server", id: params.id }}
name={server().server.name}
description={server().server.description}
userCanUpdate={userCanUpdate()}
/>
<Actions />
</Grid>
<Show when={!isSemiMobile()}>

View File

@@ -1,13 +1,16 @@
import { useParams } from "@solidjs/router";
import { Component, createResource, For, Show } from "solid-js";
import { client } from "../../..";
import { useAppDimensions } from "../../../state/DimensionProvider";
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";
import HoverMenu from "../../shared/menu/HoverMenu";
const Info: Component<{}> = (p) => {
const { isMobile } = useAppDimensions();
const { serverInfo } = useAppState();
const params = useParams();
const [stats] = createResource(() => client.get_server_stats(params.id, { disks: true }));
@@ -74,8 +77,17 @@ const Info: Component<{}> = (p) => {
justifyContent="space-between"
>
<Flex alignItems="center">
<div>mount point:</div>
<h2>{disk.mount}</h2>
<div style={{ "white-space": "nowrap" }}>
mount point:
</div>
<h2
class="ellipsis"
style={{
"max-width": isMobile() ? "50px" : "200px",
}}
>
{disk.mount}
</h2>
</Flex>
<Flex alignItems="center">
<div>{readableStorageAmount(disk.used_gb)} used</div>

View File

@@ -17,6 +17,7 @@ const TextArea: Component<
onBlur={(e) => p.onConfirm && p.onConfirm(e.currentTarget.value)}
onKeyDown={(e) => {
if (e.key === "Enter" && p.onEnter) {
e.preventDefault();
p.onEnter(e.currentTarget.value);
}
}}

View File

@@ -38,7 +38,7 @@ h1 {
h2 {
font-size: 1.1rem;
font-weight: 450;
user-select: none;
// user-select: none;
margin: 0;
}
@@ -294,7 +294,6 @@ svg {
}
.ellipsis {
width: 100%;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;