forked from github-starred/komodo
load all deployments in one
This commit is contained in:
@@ -13,35 +13,73 @@ import {
|
||||
getPeripheryContainers,
|
||||
} from "../util/periphery/container";
|
||||
|
||||
async function getDeployments(app: FastifyInstance, serverID: string) {
|
||||
const server = await app.servers.findById(serverID);
|
||||
if (!server) return {};
|
||||
const deployments = await app.deployments.find(
|
||||
{ serverID: server._id },
|
||||
"name containerName serverID owners repo"
|
||||
);
|
||||
const status = server.isCore
|
||||
? await deploymentStatusLocal(app)
|
||||
: await getPeripheryContainers(server);
|
||||
return intoCollection(
|
||||
deployments.map((deployment) => ({
|
||||
...deployment,
|
||||
status: status[deployment.containerName!] || "not deployed",
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
const deployments = fp((app: FastifyInstance, _: {}, done: () => void) => {
|
||||
// app.get(
|
||||
// "/api/deployments",
|
||||
// { onRequest: [app.auth, app.userEnabled] },
|
||||
// async (req, res) => {
|
||||
// // returns the periphery deployments on the given serverID
|
||||
// // returns the core deployments if no serverID is specified
|
||||
// const { serverID } = req.query as { serverID?: string };
|
||||
// const server = serverID ? await app.servers.findById(serverID) : app.core;
|
||||
// if (!server) {
|
||||
// res.status(400);
|
||||
// res.send();
|
||||
// return;
|
||||
// }
|
||||
// const deployments = await app.deployments.find(
|
||||
// { serverID: server._id },
|
||||
// "name containerName serverID owners repo"
|
||||
// );
|
||||
// const status = server.isCore
|
||||
// ? await deploymentStatusLocal(app)
|
||||
// : await getPeripheryContainers(server);
|
||||
// res.send(
|
||||
// intoCollection(
|
||||
// deployments.map((deployment) => ({
|
||||
// ...deployment,
|
||||
// status: status[deployment.containerName!] || "not deployed",
|
||||
// }))
|
||||
// )
|
||||
// );
|
||||
// }
|
||||
// );
|
||||
|
||||
app.get(
|
||||
"/api/deployments",
|
||||
{ onRequest: [app.auth, app.userEnabled] },
|
||||
async (req, res) => {
|
||||
// returns the periphery deployments on the given serverID
|
||||
// returns the core deployments if no serverID is specified
|
||||
const { serverID } = req.query as { serverID?: string };
|
||||
const server = serverID ? await app.servers.findById(serverID) : app.core;
|
||||
if (!server) {
|
||||
res.status(400);
|
||||
res.send();
|
||||
return;
|
||||
}
|
||||
const deployments = await app.deployments.find(
|
||||
{ serverID: server._id },
|
||||
"name containerName serverID owners repo"
|
||||
);
|
||||
const status = server.isCore
|
||||
? await deploymentStatusLocal(app)
|
||||
: await getPeripheryContainers(server);
|
||||
res.send(
|
||||
intoCollection(
|
||||
deployments.map((deployment) => ({
|
||||
...deployment,
|
||||
status: status[deployment.containerName!] || "not deployed",
|
||||
}))
|
||||
async (_, res) => {
|
||||
// returns all the deployments
|
||||
const servers = await app.servers.find({});
|
||||
const deployments = (
|
||||
await Promise.all(
|
||||
servers.map((server) => getDeployments(app, server._id!))
|
||||
)
|
||||
);
|
||||
).reduce((acc, curr) => {
|
||||
Object.keys(curr).forEach((id) => {
|
||||
acc[id] = curr[id];
|
||||
});
|
||||
return acc;
|
||||
}, {});
|
||||
res.send(deployments);
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -11,4 +11,4 @@ export function sendAlert(
|
||||
message: string
|
||||
) {
|
||||
client.send(JSON.stringify({ type: ALERT, status, message }))
|
||||
}
|
||||
}
|
||||
@@ -14,11 +14,68 @@ const Header: Component<{}> = (p) => {
|
||||
const { servers, deployments, ws, selected } = useAppState();
|
||||
const deployment = () => deployments.get(selected.id());
|
||||
const server = () => deployment() && servers.get(deployment()?.serverID!);
|
||||
const status = () =>
|
||||
const state = () =>
|
||||
deployment()!.status === "not deployed"
|
||||
? "not deployed"
|
||||
: (deployment()!.status as ContainerStatus).State;
|
||||
const status = () =>
|
||||
deployment()!.status === "not deployed"
|
||||
? undefined
|
||||
: (deployment()!.status as ContainerStatus).Status.toLowerCase();
|
||||
const actions = useActionStates();
|
||||
return (
|
||||
<Grid gap="0.5rem" class="card shadow">
|
||||
<Flex alignItems="center" justifyContent="space-between">
|
||||
<h1>{deployment()!.name}</h1>
|
||||
<Show
|
||||
when={!actions.fullDeleting}
|
||||
fallback={
|
||||
<button class="red">
|
||||
<Icon type="trash" />
|
||||
</button>
|
||||
}
|
||||
>
|
||||
<HoverMenu
|
||||
target={
|
||||
<ConfirmButton
|
||||
onConfirm={() => {
|
||||
ws.send(DELETE_DEPLOYMENT, { deploymentID: selected.id() });
|
||||
}}
|
||||
color="red"
|
||||
>
|
||||
<Icon type="trash" />
|
||||
</ConfirmButton>
|
||||
}
|
||||
content="delete deployment"
|
||||
position="bottom center"
|
||||
padding="0.5rem"
|
||||
/>
|
||||
</Show>
|
||||
</Flex>
|
||||
<Flex alignItems="center" justifyContent="space-between">
|
||||
<HoverMenu
|
||||
target={
|
||||
<button
|
||||
class="grey"
|
||||
style={{ opacity: 0.8 }}
|
||||
onClick={() => selected.set(deployment()?.serverID!, "server")}
|
||||
>
|
||||
{server()!.name}
|
||||
</button>
|
||||
}
|
||||
content="show server"
|
||||
position="bottom center"
|
||||
padding="0.5rem"
|
||||
/>
|
||||
<Flex alignItems="center">
|
||||
<div class={deploymentStatusClass(state())}>{state()}</div>
|
||||
<Show when={status()}>
|
||||
<div style={{ opacity: 0.7 }}>{status()}</div>
|
||||
</Show>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Grid>
|
||||
);
|
||||
return (
|
||||
<Flex
|
||||
class="card shadow"
|
||||
@@ -36,7 +93,12 @@ const Header: Component<{}> = (p) => {
|
||||
</button>
|
||||
</Grid>
|
||||
<Flex alignItems="center">
|
||||
<div class={deploymentStatusClass(status())}>{status()}</div>
|
||||
<Grid gap="0.3rem" placeItems="center start">
|
||||
<div class={deploymentStatusClass(state())}>{state()}</div>
|
||||
<Show when={status()}>
|
||||
<div style={{ opacity: 0.7 }}>{status()}</div>
|
||||
</Show>
|
||||
</Grid>
|
||||
<Show
|
||||
when={!actions.fullDeleting}
|
||||
fallback={
|
||||
|
||||
@@ -33,6 +33,14 @@ const Home: Component<{}> = (p) => {
|
||||
(id) =>
|
||||
permissions() > 1 || servers.get(id)!.owners.includes(username()!)
|
||||
);
|
||||
const deploymentState = (id: string) =>
|
||||
deployments.get(id)!.status === "not deployed"
|
||||
? "not deployed"
|
||||
: (deployments.get(id)!.status as ContainerStatus).State;
|
||||
const deploymentStatus = (id: string) =>
|
||||
deployments.get(id)!.status === "not deployed"
|
||||
? undefined
|
||||
: (deployments.get(id)!.status as ContainerStatus).Status.toLowerCase();
|
||||
return (
|
||||
<Grid class={s.Home}>
|
||||
<Grid style={{ height: "fit-content" }}>
|
||||
@@ -46,19 +54,15 @@ const Home: Component<{}> = (p) => {
|
||||
<button
|
||||
class="grey"
|
||||
onClick={() => selected.set(id, "deployment")}
|
||||
style={{ "justify-content": "space-between", width: "22rem" }}
|
||||
>
|
||||
<h2>{deployments.get(id)!.name}</h2>
|
||||
<div
|
||||
class={deploymentStatusClass(
|
||||
deployments.get(id)!.status === "not deployed"
|
||||
? "not deployed"
|
||||
: (deployments.get(id)!.status as ContainerStatus).State
|
||||
)}
|
||||
>
|
||||
{deployments.get(id)!.status === "not deployed"
|
||||
? "not deployed"
|
||||
: (deployments.get(id)!.status as ContainerStatus).State}
|
||||
</div>
|
||||
<Flex>
|
||||
<div class={deploymentStatusClass(deploymentState(id))}>
|
||||
{deploymentState(id)}
|
||||
</div>
|
||||
<div style={{ opacity: 0.7 }}>{deploymentStatus(id)}</div>
|
||||
</Flex>
|
||||
</button>
|
||||
)}
|
||||
</For>
|
||||
@@ -70,7 +74,11 @@ const Home: Component<{}> = (p) => {
|
||||
<h1>my servers</h1>
|
||||
<For each={filteredServerIds()}>
|
||||
{(id) => (
|
||||
<button class="grey" onClick={() => selected.set(id, "server")}>
|
||||
<button
|
||||
class="grey"
|
||||
onClick={() => selected.set(id, "server")}
|
||||
style={{ "justify-content": "space-between", width: "22rem" }}
|
||||
>
|
||||
<h2>{servers.get(id)!.name}</h2>
|
||||
<div
|
||||
class={serverStatusClass(
|
||||
@@ -98,7 +106,11 @@ const Home: Component<{}> = (p) => {
|
||||
<h1>my builds</h1>
|
||||
<For each={filteredBuildIds()}>
|
||||
{(id) => (
|
||||
<button class="grey" onClick={() => selected.set(id, "build")}>
|
||||
<button
|
||||
class="grey"
|
||||
onClick={() => selected.set(id, "build")}
|
||||
style={{ "justify-content": "space-between", width: "22rem" }}
|
||||
>
|
||||
<h2>{builds.get(id)!.name}</h2>
|
||||
</button>
|
||||
)}
|
||||
|
||||
@@ -22,13 +22,13 @@ const Server: Component<{ id: string }> = (p) => {
|
||||
);
|
||||
});
|
||||
const [open, toggleOpen] = useLocalStorageToggle(p.id);
|
||||
createEffect(() => {
|
||||
if (server() && !server()!.isCore) {
|
||||
getDeployments({ serverID: p.id }).then((more) =>
|
||||
deployments.addMany(more)
|
||||
);
|
||||
}
|
||||
});
|
||||
// createEffect(() => {
|
||||
// if (server() && !server()!.isCore) {
|
||||
// getDeployments({ serverID: p.id }).then((more) =>
|
||||
// deployments.addMany(more)
|
||||
// );
|
||||
// }
|
||||
// });
|
||||
return (
|
||||
<Show when={server()}>
|
||||
<div class={combineClasses(s.Server, "shadow")}>
|
||||
@@ -42,7 +42,7 @@ const Server: Component<{ id: string }> = (p) => {
|
||||
>
|
||||
<Flex>
|
||||
<Icon type="chevron-down" width="1rem" />
|
||||
<div>{server()?.name}</div>
|
||||
<h2>{server()?.name}</h2>
|
||||
</Flex>
|
||||
<div
|
||||
class={server()?.status === "OK" ? "green" : "red"}
|
||||
|
||||
+15
-11
@@ -43,14 +43,19 @@ export function useSelected({ servers, builds, deployments }: State) {
|
||||
history.replaceState({ id: "", type: "home" }, "", "/");
|
||||
setFirstLoad(false);
|
||||
} else if (selected().type === "deployment" && deployments.loaded()) {
|
||||
const [type, id] = location.pathname.split("/").filter((val) => val);
|
||||
if (type !== selected().type || id !== selected().id) {
|
||||
history.replaceState(
|
||||
{ id, type },
|
||||
"",
|
||||
`${selected().type}/${selected().id}`
|
||||
);
|
||||
setFirstLoad(false);
|
||||
if (!deployments.get(selected().id)) {
|
||||
const id = deployments.ids()![0];
|
||||
set(id, "deployment");
|
||||
} else {
|
||||
const [type, id] = location.pathname.split("/").filter((val) => val);
|
||||
if (type !== selected().type || id !== selected().id) {
|
||||
history.replaceState(
|
||||
{ type, id },
|
||||
"",
|
||||
`${selected().type}/${selected().id}`
|
||||
);
|
||||
setFirstLoad(false);
|
||||
}
|
||||
}
|
||||
setFirstLoad(false);
|
||||
} else if (
|
||||
@@ -69,7 +74,6 @@ export function useSelected({ servers, builds, deployments }: State) {
|
||||
"",
|
||||
`${selected().type}/${selected().id}`
|
||||
);
|
||||
setFirstLoad(false);
|
||||
}
|
||||
}
|
||||
setFirstLoad(false);
|
||||
@@ -123,8 +127,8 @@ export function useBuilds() {
|
||||
return useCollection(getBuilds);
|
||||
}
|
||||
|
||||
export function useDeployments(query?: Parameters<typeof getDeployments>[0]) {
|
||||
return useCollection(() => getDeployments(query));
|
||||
export function useDeployments() {
|
||||
return useCollection(getDeployments);
|
||||
}
|
||||
|
||||
export function useUpdates(query?: Parameters<typeof getUpdates>[0]) {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
$app-color: #fceade;
|
||||
|
||||
$lightgrey: #414852;
|
||||
$grey: #2c3137;
|
||||
$darkgrey: #1c1f23;
|
||||
$lightgrey: #3f454d;
|
||||
$grey: #25292e;
|
||||
$darkgrey: #16181b;
|
||||
|
||||
$lightblue: #1c63cd;
|
||||
$blue: #184e9f;
|
||||
|
||||
@@ -1,9 +1,18 @@
|
||||
@use "colors" as c;
|
||||
@import url("https://fonts.googleapis.com/css2?family=Chakra+Petch:wght@300;400;500&display=swap");
|
||||
@import url("https://fonts.googleapis.com/css2?family=Work+Sans&display=swap");
|
||||
@import url("https://fonts.googleapis.com/css2?family=Ubuntu+Mono&display=swap");
|
||||
@import url("https://fonts.googleapis.com/css2?family=Tajawal&display=swap");
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: "Chakra Petch", sans-serif;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||
sans-serif;
|
||||
// font-family: "Chakra Petch", sans-serif;
|
||||
// font-family: "Work Sans", sans-serif;
|
||||
// font-family: 'Ubuntu Mono', monospace;
|
||||
// font-family: "Tajawal", sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
|
||||
@@ -82,7 +91,6 @@ input::placeholder {
|
||||
background-color: rgba(c.$grey, 0.8);
|
||||
}
|
||||
|
||||
|
||||
.grey {
|
||||
background-color: rgba(c.$grey, 0.8);
|
||||
}
|
||||
|
||||
@@ -39,24 +39,16 @@ export async function getBuildActionState(buildID: string) {
|
||||
);
|
||||
}
|
||||
|
||||
export async function addOwnerToBuild(
|
||||
buildID: string,
|
||||
username: string
|
||||
) {
|
||||
export async function addOwnerToBuild(buildID: string, username: string) {
|
||||
return await client.post(`/api/build/${buildID}/${username}`);
|
||||
}
|
||||
|
||||
export async function removeOwnerFromBuild(
|
||||
buildID: string,
|
||||
username: string
|
||||
) {
|
||||
export async function removeOwnerFromBuild(buildID: string, username: string) {
|
||||
return await client.delete(`/api/build/${buildID}/${username}`);
|
||||
}
|
||||
|
||||
export async function getDeployments(query?: { serverID?: string }) {
|
||||
return await client.get<Deployments>(
|
||||
"/api/deployments" + generateQuery(query)
|
||||
);
|
||||
export async function getDeployments() {
|
||||
return await client.get<Deployments>("/api/deployments");
|
||||
}
|
||||
|
||||
export async function getDeployment(deploymentID: string) {
|
||||
@@ -107,7 +99,10 @@ export async function addOwnerToServer(serverID: string, username: string) {
|
||||
return await client.post(`/api/server/${serverID}/${username}`);
|
||||
}
|
||||
|
||||
export async function removeOwnerFromServer(serverID: string, username: string) {
|
||||
export async function removeOwnerFromServer(
|
||||
serverID: string,
|
||||
username: string
|
||||
) {
|
||||
return await client.delete(`/api/server/${serverID}/${username}`);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user