forked from github-starred/komodo
add actions, refactor deployments
This commit is contained in:
@@ -119,7 +119,7 @@ export const DeploymentCard = ({ id }: { id: string }) => {
|
||||
if (!deployment) return null;
|
||||
return (
|
||||
<Link to={`/deployments/${deployment.id}`}>
|
||||
<Card className="hover:bg-accent">
|
||||
<Card hoverable>
|
||||
<CardHeader>
|
||||
<CardTitle>{deployment.name}</CardTitle>
|
||||
<CardDescription>
|
||||
@@ -138,7 +138,7 @@ export const ServerCard = ({ id }: { id: string }) => {
|
||||
|
||||
return (
|
||||
<Link to={`/servers/${server.id}`} key={server.id}>
|
||||
<Card className="hover:bg-accent">
|
||||
<Card hoverable>
|
||||
<CardHeader className="flex flex-row justify-between">
|
||||
<div>
|
||||
<CardTitle>{server.name}</CardTitle>
|
||||
@@ -161,7 +161,7 @@ export const BuildCard = ({ id }: { id: string }) => {
|
||||
|
||||
return (
|
||||
<Link to={`/builds/${build.id}`} key={build.id}>
|
||||
<Card className="hover:bg-accent">
|
||||
<Card hoverable>
|
||||
<CardHeader className="flex flex-row justify-between">
|
||||
<div>
|
||||
<CardTitle>{build.name}</CardTitle>
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
// import { DeploymentLogs } from "@pages/resource/deployment/components/logs";
|
||||
import { Resource } from "@layouts/resource";
|
||||
// import { Updates } from "@components/updates";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { CardDescription } from "@ui/card";
|
||||
// import { DeploymentConfig } from "@pages/resource/deployment/components/config";
|
||||
// import {
|
||||
// RedeployContainer,
|
||||
// StartOrStopContainer,
|
||||
// RemoveContainer,
|
||||
// } from "@pages/resource/deployment/components/actions";
|
||||
// import { DeleteDeployment } from "@pages/resource/deployment/components/delete";
|
||||
import { useRead, useSetRecentlyViewed } from "@hooks";
|
||||
import { Circle } from "lucide-react";
|
||||
import { cn } from "@util/helpers";
|
||||
import { DeploymentLogs } from "./components/deployment-logs";
|
||||
import { Updates } from "@components/updates/updates";
|
||||
|
||||
export const DeploymentName = ({
|
||||
deploymentId,
|
||||
}: {
|
||||
deploymentId: string | undefined;
|
||||
}) => {
|
||||
const deployments = useRead({ type: "ListDeployments", params: {} }).data;
|
||||
const deployment = deployments?.find((d) => d.id === deploymentId);
|
||||
return <>{deployment?.name ?? "..."}</>;
|
||||
};
|
||||
|
||||
export const DeploymentStatus = ({
|
||||
deploymentId,
|
||||
}: {
|
||||
deploymentId: string | undefined;
|
||||
}) => {
|
||||
const deployments = useRead({ type: "ListDeployments", params: {} }).data;
|
||||
const deployment = deployments?.find((d) => d.id === deploymentId);
|
||||
return <>{deployments ? deployment?.status ?? "not deployed" : "..."}</>;
|
||||
};
|
||||
|
||||
export const DeploymentStatusIcon = ({
|
||||
deploymentId,
|
||||
}: {
|
||||
deploymentId: string | undefined;
|
||||
}) => {
|
||||
const deployments = useRead({ type: "ListDeployments", params: {} }).data;
|
||||
const deployment = deployments?.find((d) => d.id === deploymentId);
|
||||
return (
|
||||
<Circle
|
||||
className={cn(
|
||||
"w-4 h-4 stroke-none",
|
||||
deployment?.status === "running" && "fill-green-500",
|
||||
deployment?.status === "exited" && "fill-red-500",
|
||||
deployment?.status === "not_deployed" && "fill-blue-500"
|
||||
)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
// export const DeploymentInfo = ({ deploymentId }: { deploymentId: string }) => {
|
||||
// const deployments = useRead({ type: "ListDeployments", params: {} }).data;
|
||||
// const deployment = deployments?.find((d) => d.id === deploymentId);
|
||||
|
||||
// return (
|
||||
// <div className="flex flex-col gap-2 md:flex-row md:gap-4">
|
||||
// <Link to={`/builds/${deployment?.deployment.build_id}`}>
|
||||
// <CardDescription className="flex items-center">
|
||||
// <HardDrive className="w-4 h-4 mr-2" />
|
||||
// {data ? deployment?.container?.image ?? "no image" : "..."}
|
||||
// </CardDescription>
|
||||
// </Link>
|
||||
// <Link to={`/servers/${deployment?.deployment.server_id}`}>
|
||||
// <CardDescription className="flex items-center gap-2">
|
||||
// <Server className="w-4 h-4" />
|
||||
// <ServerName serverId={deployment?.deployment.server_id} />
|
||||
// </CardDescription>
|
||||
// </Link>
|
||||
// </div>
|
||||
// );
|
||||
// };
|
||||
|
||||
export const Deployment = () => {
|
||||
const { deploymentId } = useParams();
|
||||
const push = useSetRecentlyViewed();
|
||||
|
||||
if (!deploymentId) return null;
|
||||
push("Deployment", deploymentId);
|
||||
|
||||
return (
|
||||
<Resource
|
||||
title={<DeploymentName deploymentId={deploymentId} />}
|
||||
info={
|
||||
<div className="flex flex-col gap-2 md:flex-row md:items-center md:gap-4">
|
||||
<div>deployment info</div>
|
||||
{/* <DeploymentInfo deploymentId={deploymentId} /> */}
|
||||
<CardDescription className="hidden md:block">|</CardDescription>
|
||||
<CardDescription className="flex items-center gap-2">
|
||||
<DeploymentStatusIcon deploymentId={deploymentId} />
|
||||
<DeploymentStatus deploymentId={deploymentId} />
|
||||
</CardDescription>
|
||||
<CardDescription className="hidden md:block">|</CardDescription>
|
||||
{/* <DeleteDeployment deploymentId={deploymentId} /> */}
|
||||
</div>
|
||||
}
|
||||
actions={
|
||||
<>
|
||||
{/* <RedeployContainer deploymentId={deploymentId} />
|
||||
<StartOrStopContainer deploymentId={deploymentId} />
|
||||
<RemoveContainer deploymentId={deploymentId} /> */}
|
||||
</>
|
||||
}
|
||||
tabs={[
|
||||
{
|
||||
title: "Logs",
|
||||
component: <DeploymentLogs deploymentId={deploymentId} />,
|
||||
},
|
||||
{
|
||||
title: "Config",
|
||||
component: <>Config</>,
|
||||
},
|
||||
{
|
||||
title: "Updates",
|
||||
component: <>Updates</>,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,92 @@
|
||||
import { ActionButton } from "@components/util";
|
||||
import { RefreshCw, Play, Trash, Pause } from "lucide-react";
|
||||
import { useExecute, useRead } from "@hooks";
|
||||
import { DockerContainerState } from "@monitor/client/dist/types";
|
||||
|
||||
export const RedeployContainer = ({
|
||||
deploymentId,
|
||||
}: {
|
||||
deploymentId: string;
|
||||
}) => {
|
||||
const { mutate, isLoading } = useExecute();
|
||||
return (
|
||||
<ActionButton
|
||||
title="Redeploy"
|
||||
intent="success"
|
||||
icon={<RefreshCw className="h-4 w-4" />}
|
||||
onClick={() =>
|
||||
mutate({ type: "Deploy", params: { deployment_id: deploymentId } })
|
||||
}
|
||||
disabled={isLoading}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const StartContainer = ({ deploymentId }: { deploymentId: string }) => {
|
||||
const { mutate, isLoading } = useExecute();
|
||||
|
||||
return (
|
||||
<ActionButton
|
||||
title="Start"
|
||||
intent="success"
|
||||
icon={<Play className="h-4 w-4" />}
|
||||
onClick={() =>
|
||||
mutate({
|
||||
type: "StartContainer",
|
||||
params: { deployment_id: deploymentId },
|
||||
})
|
||||
}
|
||||
disabled={isLoading}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const StopContainer = ({ deploymentId }: { deploymentId: string }) => {
|
||||
const { mutate, isLoading } = useExecute();
|
||||
|
||||
return (
|
||||
<ActionButton
|
||||
title="Stop"
|
||||
intent="warning"
|
||||
icon={<Pause className="h-4 w-4" />}
|
||||
onClick={() =>
|
||||
mutate({
|
||||
type: "StopContainer",
|
||||
params: { deployment_id: deploymentId },
|
||||
})
|
||||
}
|
||||
disabled={isLoading}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export const StartOrStopContainer = ({
|
||||
deploymentId,
|
||||
}: {
|
||||
deploymentId: string;
|
||||
}) => {
|
||||
const { data } = useRead({ type: "ListDeployments", params: {} });
|
||||
const deployment = data?.find((d) => d.id == deploymentId);
|
||||
if (deployment?.state === DockerContainerState.Running)
|
||||
return <StopContainer deploymentId={deploymentId} />;
|
||||
return <StartContainer deploymentId={deploymentId} />;
|
||||
};
|
||||
|
||||
export const RemoveContainer = ({ deploymentId }: { deploymentId: string }) => {
|
||||
const { mutate, isLoading } = useExecute();
|
||||
|
||||
return (
|
||||
<ActionButton
|
||||
title="Remove"
|
||||
intent="warning"
|
||||
icon={<Trash className="h-4 w-4" />}
|
||||
onClick={() =>
|
||||
mutate({
|
||||
type: "RemoveContainer",
|
||||
params: { deployment_id: deploymentId },
|
||||
})
|
||||
}
|
||||
disabled={isLoading}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,42 @@
|
||||
import { useRead } from "@hooks";
|
||||
import { cn } from "@util/helpers";
|
||||
import { Circle } from "lucide-react";
|
||||
|
||||
export const DeploymentName = ({
|
||||
deploymentId,
|
||||
}: {
|
||||
deploymentId: string | undefined;
|
||||
}) => {
|
||||
const deployments = useRead({ type: "ListDeployments", params: {} }).data;
|
||||
const deployment = deployments?.find((d) => d.id === deploymentId);
|
||||
return <>{deployment?.name ?? "..."}</>;
|
||||
};
|
||||
|
||||
export const DeploymentStatus = ({
|
||||
deploymentId,
|
||||
}: {
|
||||
deploymentId: string | undefined;
|
||||
}) => {
|
||||
const deployments = useRead({ type: "ListDeployments", params: {} }).data;
|
||||
const deployment = deployments?.find((d) => d.id === deploymentId);
|
||||
return <>{deployments ? deployment?.status ?? "not deployed" : "..."}</>;
|
||||
};
|
||||
|
||||
export const DeploymentStatusIcon = ({
|
||||
deploymentId,
|
||||
}: {
|
||||
deploymentId: string | undefined;
|
||||
}) => {
|
||||
const deployments = useRead({ type: "ListDeployments", params: {} }).data;
|
||||
const deployment = deployments?.find((d) => d.id === deploymentId);
|
||||
return (
|
||||
<Circle
|
||||
className={cn(
|
||||
"w-4 h-4 stroke-none",
|
||||
deployment?.status === "running" && "fill-green-500",
|
||||
deployment?.status === "exited" && "fill-red-500",
|
||||
deployment?.status === undefined && "fill-blue-500"
|
||||
)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,63 @@
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useSetRecentlyViewed } from "@hooks";
|
||||
import { Resource } from "@layouts/resource";
|
||||
import { CardDescription } from "@ui/card";
|
||||
import {
|
||||
DeploymentName,
|
||||
DeploymentStatus,
|
||||
DeploymentStatusIcon,
|
||||
} from "./components/util";
|
||||
import {
|
||||
RedeployContainer,
|
||||
RemoveContainer,
|
||||
StartOrStopContainer,
|
||||
} from "./components/actions";
|
||||
import { DeploymentLogs } from "./components/deployment-logs";
|
||||
|
||||
export const Deployment = () => {
|
||||
const { deploymentId } = useParams();
|
||||
const push = useSetRecentlyViewed();
|
||||
|
||||
if (!deploymentId) return null;
|
||||
push("Deployment", deploymentId);
|
||||
|
||||
return (
|
||||
<Resource
|
||||
title={<DeploymentName deploymentId={deploymentId} />}
|
||||
info={
|
||||
<div className="flex flex-col gap-2 md:flex-row md:items-center md:gap-4">
|
||||
<div>deployment info</div>
|
||||
{/* <DeploymentInfo deploymentId={deploymentId} /> */}
|
||||
<CardDescription className="hidden md:block">|</CardDescription>
|
||||
<CardDescription className="flex items-center gap-2">
|
||||
<DeploymentStatusIcon deploymentId={deploymentId} />
|
||||
<DeploymentStatus deploymentId={deploymentId} />
|
||||
</CardDescription>
|
||||
<CardDescription className="hidden md:block">|</CardDescription>
|
||||
{/* <DeleteDeployment deploymentId={deploymentId} /> */}
|
||||
</div>
|
||||
}
|
||||
actions={
|
||||
<>
|
||||
<RedeployContainer deploymentId={deploymentId} />
|
||||
<StartOrStopContainer deploymentId={deploymentId} />
|
||||
<RemoveContainer deploymentId={deploymentId} />
|
||||
</>
|
||||
}
|
||||
tabs={[
|
||||
{
|
||||
title: "Logs",
|
||||
component: <DeploymentLogs deploymentId={deploymentId} />,
|
||||
},
|
||||
{
|
||||
title: "Config",
|
||||
component: <>Config</>,
|
||||
},
|
||||
{
|
||||
title: "Updates",
|
||||
component: <>Updates</>,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -4,11 +4,11 @@ import { Login } from "@pages/auth/login";
|
||||
import { Signup } from "@pages/auth/signup";
|
||||
import { Dashboard } from "@pages/dashboard";
|
||||
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";
|
||||
import { Deployment } from "@resources/deployment/page";
|
||||
|
||||
const router = createBrowserRouter([
|
||||
{
|
||||
|
||||
@@ -3,12 +3,13 @@ import * as React from "react";
|
||||
|
||||
const Card = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
React.HTMLAttributes<HTMLDivElement> & { hoverable?: boolean }
|
||||
>(({ className, hoverable, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"rounded-lg border bg-card text-card-foreground shadow-sm",
|
||||
hoverable && "hover:shadow-md transition-shadow",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
Reference in New Issue
Block a user