mirror of
https://github.com/moghtech/komodo.git
synced 2026-04-28 19:59:46 -05:00
add builds page, build page, etc
This commit is contained in:
63
frontend/src/pages/build/index.tsx
Normal file
63
frontend/src/pages/build/index.tsx
Normal file
@@ -0,0 +1,63 @@
|
||||
import { Resource } from "@layouts/resource";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useExecute, useRead, useSetRecentlyViewed } from "@hooks";
|
||||
import { ActionButton } from "@components/util";
|
||||
import { Hammer } from "lucide-react";
|
||||
import { version_to_string } from "@util/helpers";
|
||||
|
||||
export const BuildName = ({ id }: { id: string }) => {
|
||||
const builds = useRead({ type: "ListBuilds", params: {} }).data;
|
||||
const build = builds?.find((b) => b.id === id);
|
||||
return <>{build?.name ?? "..."}</>;
|
||||
};
|
||||
|
||||
export const BuildVersion = ({ id }: { id: string }) => {
|
||||
const builds = useRead({ type: "ListBuilds", params: {} }).data;
|
||||
const build = builds?.find((b) => b.id === id);
|
||||
return <>{version_to_string(build?.version) ?? "..."}</>;
|
||||
};
|
||||
|
||||
export const RebuildBuild = ({ buildId }: { buildId: string }) => {
|
||||
const { mutate, isLoading } = useExecute();
|
||||
return (
|
||||
<ActionButton
|
||||
title="Build"
|
||||
intent="success"
|
||||
icon={<Hammer className="h-4 w-4" />}
|
||||
onClick={() =>
|
||||
mutate({ type: "RunBuild", params: { build_id: buildId } })
|
||||
}
|
||||
disabled={isLoading}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export const Build = () => {
|
||||
const { buildId } = useParams();
|
||||
const push = useSetRecentlyViewed();
|
||||
|
||||
if (!buildId) return null;
|
||||
push("Build", buildId);
|
||||
|
||||
return (
|
||||
<Resource
|
||||
title={<BuildName id={buildId} />}
|
||||
info={<BuildVersion id={buildId} />}
|
||||
actions={<RebuildBuild buildId={buildId} />}
|
||||
tabs={[
|
||||
{
|
||||
title: "Config",
|
||||
component: "config",
|
||||
},
|
||||
{
|
||||
title: "Builder",
|
||||
component: "builder",
|
||||
},
|
||||
{
|
||||
title: "Updates",
|
||||
component: "updates",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
};
|
||||
17
frontend/src/pages/builds/index.tsx
Normal file
17
frontend/src/pages/builds/index.tsx
Normal file
@@ -0,0 +1,17 @@
|
||||
import { useRead } from "@hooks";
|
||||
import { BuildCard } from "@pages/dashboard";
|
||||
|
||||
export const Builds = () => {
|
||||
const builds = useRead({ type: "ListBuilds", params: {} }).data;
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-12">
|
||||
<h1 className="text-3xl">Builds</h1>
|
||||
<div className="grid grid-cols-4 gap-8">
|
||||
{builds?.map(({ id }) => (
|
||||
<BuildCard key={id} id={id} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1,21 +1,19 @@
|
||||
import { useGetRecentlyViewed } from "@hooks";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@ui/card";
|
||||
import { DeploymentCard, ServerCard } from "..";
|
||||
import { BuildCard, DeploymentCard, ServerCard } from "..";
|
||||
|
||||
export const RecentlyViewed = () => {
|
||||
const recents = useGetRecentlyViewed();
|
||||
return (
|
||||
<Card className="w-full">
|
||||
<CardHeader>
|
||||
<CardTitle>Recently Viewed</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="flex flex-col gap-4">
|
||||
<div className="w-full flex flex-col gap-6">
|
||||
<h2 className="text-xl">Recently Viewed</h2>
|
||||
<div className="flex flex-col gap-4">
|
||||
{recents.map(({ type, id }) => {
|
||||
if (type === "Deployment") return <DeploymentCard key={id} id={id} />;
|
||||
if (type === "Build") return <div></div>;
|
||||
if (type === "Build") return <BuildCard key={id} id={id} />;
|
||||
if (type === "Server") return <ServerCard key={id} id={id} />;
|
||||
})}
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@ui/card";
|
||||
import { version_to_string } from "@util/helpers";
|
||||
import { readableVersion, version_to_string } from "@util/helpers";
|
||||
import { ServersChart } from "./components/servers-chart";
|
||||
import { DeploymentsChart } from "./components/deployments-chart";
|
||||
import { Input } from "@ui/input";
|
||||
@@ -30,7 +30,7 @@ import {
|
||||
DialogTitle,
|
||||
} from "@ui/dialog";
|
||||
import { useState } from "react";
|
||||
import { RecentlyViewed } from "./components/recents";
|
||||
import { RecentlyViewed } from "./components/recently-viewed";
|
||||
import { ServerStats, ServerStatusIcon } from "@pages/server";
|
||||
|
||||
const NewDeployment = ({
|
||||
@@ -78,8 +78,55 @@ const NewDeployment = ({
|
||||
);
|
||||
};
|
||||
|
||||
const NewBuild = ({
|
||||
open,
|
||||
set,
|
||||
}: {
|
||||
open: boolean;
|
||||
set: (b: boolean) => void;
|
||||
}) => {
|
||||
const { mutate } = useWrite();
|
||||
const [name, setName] = useState("");
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={set}>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>New Build</DialogTitle>
|
||||
</DialogHeader>
|
||||
<div className="flex items-center justify-between">
|
||||
<div>Build Name</div>
|
||||
<Input
|
||||
className="max-w-[50%]"
|
||||
placeholder="Build Name"
|
||||
name={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<Button
|
||||
variant="outline"
|
||||
intent="success"
|
||||
onClick={() => {
|
||||
mutate({
|
||||
type: "CreateBuild",
|
||||
params: { name, config: {} },
|
||||
});
|
||||
set(false);
|
||||
}}
|
||||
>
|
||||
Create
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
const NewButton = () => {
|
||||
const [open, set] = useState<"deployment" | "server" | boolean>(false);
|
||||
const [open, set] = useState<"deployment" | "build" | "server" | boolean>(
|
||||
false
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<DropdownMenu>
|
||||
@@ -104,12 +151,15 @@ const NewButton = () => {
|
||||
<DropdownMenuItem onClick={() => set("deployment")}>
|
||||
Deployment
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem> Build </DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => set("build")}>
|
||||
Build
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem> Server </DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
<NewDeployment open={open === "deployment"} set={set} />
|
||||
<NewBuild open={open === "build"} set={set} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -181,6 +231,28 @@ const ServersList = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export const BuildCard = ({ id }: { id: string }) => {
|
||||
const builds = useRead({ type: "ListBuilds", params: {} }).data;
|
||||
const build = builds?.find((server) => server.id === id);
|
||||
if (!build) return null;
|
||||
|
||||
return (
|
||||
<Link to={`/builds/${build.id}`} key={build.id}>
|
||||
<Card className="hover:bg-accent">
|
||||
<CardHeader className="flex flex-row justify-between">
|
||||
<div>
|
||||
<CardTitle>{build.name}</CardTitle>
|
||||
<CardDescription>
|
||||
{version_to_string(build.version)}
|
||||
</CardDescription>
|
||||
</div>
|
||||
<ServerStatusIcon serverId={build.id} />
|
||||
</CardHeader>
|
||||
</Card>
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
const BuildsList = () => {
|
||||
const builds = useRead({ type: "ListBuilds", params: {} }).data;
|
||||
|
||||
@@ -188,14 +260,7 @@ const BuildsList = () => {
|
||||
<div className="flex flex-col gap-2 w-full">
|
||||
<h2 className="text-lg">Builds</h2>
|
||||
{builds?.map((build) => (
|
||||
<Card>
|
||||
<CardHeader key={build.id}>
|
||||
<CardTitle>{build.name}</CardTitle>
|
||||
<CardDescription>
|
||||
{version_to_string(build.version)}
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
</Card>
|
||||
<BuildCard id={build.id} key={build.id} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,16 +1,42 @@
|
||||
import { useRead } from "@hooks";
|
||||
import { DeploymentCard } from "@pages/dashboard";
|
||||
import { Button } from "@ui/button";
|
||||
import { Input } from "@ui/input";
|
||||
import { PlusCircle } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
|
||||
export const Deployments = () => {
|
||||
const deployments = useRead({ type: "ListDeployments", params: {} }).data;
|
||||
const [search, set] = useState("");
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-12">
|
||||
<h1 className="text-3xl">Deployments</h1>
|
||||
<div className="flex justify-between">
|
||||
<h1 className="text-3xl">Deployments</h1>
|
||||
<div className="flex gap-4">
|
||||
<Input
|
||||
className="w-[300px]"
|
||||
placeholder="Search"
|
||||
value={search}
|
||||
onChange={(e) => set(e.target.value)}
|
||||
/>
|
||||
<Button
|
||||
className="w-[200px] flex items-center gap-2"
|
||||
variant="outline"
|
||||
intent="success"
|
||||
>
|
||||
<PlusCircle className="w-4 h-4 text-green-500" />
|
||||
New Deployment
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid grid-cols-4 gap-8">
|
||||
{deployments?.map(({ id }) => (
|
||||
<DeploymentCard key={id} id={id} />
|
||||
))}
|
||||
{deployments?.map(
|
||||
({ id, name }) =>
|
||||
(search.includes(name) || name.includes(search)) && (
|
||||
<DeploymentCard key={id} id={id} />
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
// import { Build } from "@pages/resource/build";
|
||||
// import { Server } from "@pages/resource/server";
|
||||
import { RouterProvider, createBrowserRouter } from "react-router-dom";
|
||||
// import { Deployment } from "@pages/resource/deployment";
|
||||
// import { Builds, Dashboard, Deployments, Servers } from "@pages/resources";
|
||||
import { Layout } from "@layouts/layout";
|
||||
import { Login } from "@pages/auth/login";
|
||||
import { Signup } from "@pages/auth/signup";
|
||||
@@ -11,6 +7,8 @@ import { Server } from "@pages/server";
|
||||
import { Deployment } from "@pages/deployment";
|
||||
import { Servers } from "@pages/servers";
|
||||
import { Deployments } from "@pages/deployments";
|
||||
import { Builds } from "@pages/builds";
|
||||
import { Build } from "@pages/build";
|
||||
|
||||
const router = createBrowserRouter([
|
||||
{
|
||||
@@ -28,13 +26,13 @@ const router = createBrowserRouter([
|
||||
{ path: ":deploymentId", element: <Deployment /> },
|
||||
],
|
||||
},
|
||||
// {
|
||||
// path: "builds",
|
||||
// children: [
|
||||
// { path: "", element: <Builds /> },
|
||||
// { path: ":buildId", element: <Build /> },
|
||||
// ],
|
||||
// },
|
||||
{
|
||||
path: "builds",
|
||||
children: [
|
||||
{ path: "", element: <Builds /> },
|
||||
{ path: ":buildId", element: <Build /> },
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "servers",
|
||||
children: [
|
||||
|
||||
Reference in New Issue
Block a user