forked from github-starred/komodo
update cards, fix responsive layouts
This commit is contained in:
@@ -53,16 +53,14 @@ export const Header = () => {
|
||||
|
||||
return (
|
||||
<header className="sticky top-0 z-40 w-full border-b bg-background">
|
||||
<div className="container flex h-16 items-center space-x-4 justify-between sm:space-x-0">
|
||||
<div className="container flex h-16 items-center justify-between">
|
||||
<div className="flex gap-4">
|
||||
<Link to="/">
|
||||
<div className="flex gap-8 font-bold text-xl cursor-pointer">
|
||||
Monitor
|
||||
</div>
|
||||
<Link to="/" className="font-bold text-xl cursor-pointer">
|
||||
Monitor
|
||||
</Link>
|
||||
<Paths />
|
||||
</div>
|
||||
<div className="flex ">
|
||||
<div className="flex">
|
||||
{user && (
|
||||
<Button disabled variant="ghost">
|
||||
<Circle className="w-4 h-4 fill-green-500 stroke-none" />
|
||||
|
||||
@@ -17,7 +17,7 @@ import { ReactNode } from "react";
|
||||
interface CardProps {
|
||||
title: string;
|
||||
description: string;
|
||||
icon: ReactNode;
|
||||
// icon: ReactNode;
|
||||
children: ReactNode;
|
||||
statusIcon?: ReactNode;
|
||||
}
|
||||
@@ -25,7 +25,7 @@ interface CardProps {
|
||||
export const ResourceCard = ({
|
||||
title,
|
||||
description,
|
||||
icon,
|
||||
// icon,
|
||||
children,
|
||||
statusIcon,
|
||||
}: CardProps) => (
|
||||
@@ -35,14 +35,9 @@ export const ResourceCard = ({
|
||||
<CardTitle>{title}</CardTitle>
|
||||
<CardDescription>{description}</CardDescription>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
{statusIcon && (
|
||||
<>
|
||||
{statusIcon}
|
||||
<div className="border h-6 w-0" />
|
||||
</>
|
||||
)}
|
||||
{icon}
|
||||
<div className="flex gap-2">
|
||||
{statusIcon}
|
||||
{/* {icon} */}
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="flex flex-col gap-6">
|
||||
|
||||
@@ -13,7 +13,7 @@ export const Layout = () => {
|
||||
<>
|
||||
<div className="relative flex min-h-screen flex-col">
|
||||
<Header />
|
||||
<div className="container px-2 md:px-8 grid gap-6 pb-8 pt-6 md:py-10">
|
||||
<div className="container pt-8">
|
||||
<Outlet />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -9,7 +9,7 @@ interface PageProps {
|
||||
|
||||
export const Page = ({ title, subtitle, actions, content }: PageProps) => (
|
||||
<div className="flex flex-col gap-12">
|
||||
<div className="flex justify-between">
|
||||
<div className="flex flex-col gap-6 lg:flex-row lg:gap-0 justify-between">
|
||||
<div className="flex flex-col">
|
||||
{title}
|
||||
{subtitle}
|
||||
|
||||
@@ -28,9 +28,9 @@ export const Resources = ({
|
||||
</h2>
|
||||
}
|
||||
actions={
|
||||
<div className="flex gap-4">
|
||||
<div className="flex flex-col-reverse md:flex-row gap-4">
|
||||
<Input
|
||||
className="w-[300px]"
|
||||
className="w-full md:w-[300px]"
|
||||
placeholder={`Search ${type}s`}
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
@@ -48,7 +48,9 @@ export const Resources = ({
|
||||
</div>
|
||||
}
|
||||
content={
|
||||
<div className="grid grid-cols-3 gap-8">{components(search)}</div>
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
{components(search)}
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -10,13 +10,11 @@ export const Dashboard = () => {
|
||||
<div className="flex flex-col gap-24">
|
||||
<RecentlyViewed />
|
||||
<div className="flex flex-col gap-6 w-full">
|
||||
<div>
|
||||
<div className="flex items-center gap-2 text-muted-foreground">
|
||||
<Box className="w-4 h-4" />
|
||||
<h2 className="text-xl">My Resources</h2>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 text-muted-foreground">
|
||||
<Box className="w-4 h-4" />
|
||||
<h2 className="text-xl">My Resources</h2>
|
||||
</div>
|
||||
<div className="flex gap-4">
|
||||
<div className="flex flex-col md:flex-row gap-4">
|
||||
<div className="flex gap-4 w-full h-fit">
|
||||
<DeploymentsChart />
|
||||
<ServersChart />
|
||||
|
||||
@@ -15,7 +15,7 @@ export const BuildCard = ({ id }: { id: string }) => {
|
||||
<ResourceCard
|
||||
title={build.name}
|
||||
description={version_to_string(build.version) ?? "not built"}
|
||||
icon={<Hammer className="w-4 h-4" />}
|
||||
statusIcon={<Hammer className="w-6 h-6 stroke-primary stroke-2" />}
|
||||
>
|
||||
<BuildInfo id={id} />
|
||||
</ResourceCard>
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { useRead } from "@hooks";
|
||||
import { Link } from "react-router-dom";
|
||||
import { DeploymentInfo, DeploymentStatusIcon } from "./util";
|
||||
import { Rocket } from "lucide-react";
|
||||
import {
|
||||
DeploymentBuild,
|
||||
DeploymentServer,
|
||||
DeploymentStatusIcon,
|
||||
} from "./util";
|
||||
import { ResourceCard } from "@layouts/card";
|
||||
|
||||
export const DeploymentCard = ({ id }: { id: string }) => {
|
||||
@@ -14,9 +17,12 @@ export const DeploymentCard = ({ id }: { id: string }) => {
|
||||
title={deployment.name}
|
||||
description={deployment.status ?? "not deployed"}
|
||||
statusIcon={<DeploymentStatusIcon deploymentId={id} />}
|
||||
icon={<Rocket className="w-4 h-4" />}
|
||||
// icon={<Rocket className="w-4 h-4" />}
|
||||
>
|
||||
<DeploymentInfo deploymentId={id} />
|
||||
<div className="flex flex-col text-muted-foreground">
|
||||
<DeploymentServer deploymentId={id} />
|
||||
<DeploymentBuild deploymentId={id} />
|
||||
</div>
|
||||
</ResourceCard>
|
||||
</Link>
|
||||
// <ResourceCard
|
||||
|
||||
@@ -3,8 +3,9 @@ import { useSetRecentlyViewed } from "@hooks";
|
||||
import { Resource } from "@layouts/resource";
|
||||
import { CardDescription } from "@ui/card";
|
||||
import {
|
||||
DeploymentInfo,
|
||||
DeploymentBuild,
|
||||
DeploymentName,
|
||||
DeploymentServer,
|
||||
DeploymentStatus,
|
||||
DeploymentStatusIcon,
|
||||
} from "./util";
|
||||
@@ -14,7 +15,6 @@ import {
|
||||
StartOrStopContainer,
|
||||
} from "./components/actions";
|
||||
import { DeploymentLogs } from "./components/deployment-logs";
|
||||
import { Rocket } from "lucide-react";
|
||||
|
||||
export const Deployment = () => {
|
||||
const { deploymentId } = useParams();
|
||||
@@ -27,15 +27,15 @@ export const Deployment = () => {
|
||||
<Resource
|
||||
title={<DeploymentName deploymentId={deploymentId} />}
|
||||
info={
|
||||
<div className="flex items-center gap-4">
|
||||
<Rocket className="w-4 h-4" />
|
||||
<CardDescription className="hidden md:block">|</CardDescription>
|
||||
<div className="flex items-center gap-2 text-muted-foreground">
|
||||
<div className="flex flex-col lg:flex-row lg:items-center lg:gap-4 text-muted-foreground">
|
||||
<div className="flex items-center gap-2 ">
|
||||
<DeploymentStatusIcon deploymentId={deploymentId} />
|
||||
<DeploymentStatus deploymentId={deploymentId} />
|
||||
</div>
|
||||
<CardDescription className="hidden md:block">|</CardDescription>
|
||||
<DeploymentInfo deploymentId={deploymentId} />
|
||||
<CardDescription className="hidden lg:block">|</CardDescription>
|
||||
<DeploymentServer deploymentId={deploymentId} />
|
||||
<CardDescription className="hidden lg:block">|</CardDescription>
|
||||
<DeploymentBuild deploymentId={deploymentId} />
|
||||
</div>
|
||||
}
|
||||
actions={
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useRead } from "@hooks";
|
||||
import { cn } from "@util/helpers";
|
||||
import { Circle, HardDrive, Server } from "lucide-react";
|
||||
import { Circle, HardDrive, Rocket, Server } from "lucide-react";
|
||||
|
||||
export const DeploymentName = ({
|
||||
deploymentId,
|
||||
@@ -30,9 +30,9 @@ export const DeploymentStatusIcon = ({
|
||||
const deployments = useRead("ListDeployments", {}).data;
|
||||
const deployment = deployments?.find((d) => d.id === deploymentId);
|
||||
return (
|
||||
<Circle
|
||||
<Rocket
|
||||
className={cn(
|
||||
"w-4 h-4 stroke-none",
|
||||
"w-4 h-4 stroke-primary",
|
||||
deployment?.status === "running" && "fill-green-500",
|
||||
deployment?.status === "exited" && "fill-red-500",
|
||||
deployment?.status === null && "fill-blue-500"
|
||||
@@ -41,22 +41,30 @@ export const DeploymentStatusIcon = ({
|
||||
);
|
||||
};
|
||||
|
||||
export const DeploymentInfo = ({ deploymentId }: { deploymentId: string }) => {
|
||||
export const DeploymentServer = ({
|
||||
deploymentId,
|
||||
}: {
|
||||
deploymentId: string;
|
||||
}) => {
|
||||
const deployments = useRead("ListDeployments", {}).data;
|
||||
const deployment = deployments?.find((d) => d.id === deploymentId);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col text-muted-foreground text-sm">
|
||||
<div className="flex items-center gap-2">
|
||||
<Server className="w-4 h-4" />
|
||||
server name
|
||||
{/* <ServerName serverId={deployment?.deployment.server_id} /> */}
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
<HardDrive className="w-4 h-4 mr-2" />
|
||||
{/* {data ? deployment?.container?.image ?? "no image" : "..."} */}
|
||||
build.name @ build.version {deployment?.status}
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Server className="w-4 h-4" />
|
||||
server name {deployment?.state}
|
||||
{/* <ServerName serverId={deployment?.deployment.server_id} /> */}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const DeploymentBuild = ({ deploymentId }: { deploymentId: string }) => {
|
||||
const deployments = useRead("ListDeployments", {}).data;
|
||||
const deployment = deployments?.find((d) => d.id === deploymentId);
|
||||
return (
|
||||
<div className="flex items-center">
|
||||
<HardDrive className="w-4 h-4 mr-2" />
|
||||
{/* {data ? deployment?.container?.image ?? "no image" : "..."} */}
|
||||
build.name @ build.version {deployment?.status}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { useRead } from "@hooks";
|
||||
import { Link } from "react-router-dom";
|
||||
import { ServerStatusIcon, ServerStats } from "./util";
|
||||
import { Server } from "lucide-react";
|
||||
import { ServerStatusIcon, ServerStats, ServerRegion } from "./util";
|
||||
import { ResourceCard } from "@layouts/card";
|
||||
|
||||
export const ServerCard = ({ id }: { id: string }) => {
|
||||
@@ -15,9 +14,12 @@ export const ServerCard = ({ id }: { id: string }) => {
|
||||
title={server.name}
|
||||
description={server.status}
|
||||
statusIcon={<ServerStatusIcon serverId={server.id} />}
|
||||
icon={<Server className="w-4 h-4" />}
|
||||
// icon={<Server className="w-4 h-4" />}
|
||||
>
|
||||
<ServerStats server_id={server.id} />
|
||||
<div className="flex flex-col">
|
||||
<ServerStats server_id={server.id} />
|
||||
<ServerRegion />
|
||||
</div>
|
||||
</ResourceCard>
|
||||
</Link>
|
||||
);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { useSetRecentlyViewed } from "@hooks";
|
||||
import { Resource } from "@layouts/resource";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { ServerInfo, ServerName } from "./util";
|
||||
import { Server as ServerIcon } from "lucide-react";
|
||||
import { ServerName, ServerStats } from "./util";
|
||||
import { ServerStatusIcon } from "./util";
|
||||
import { CardDescription } from "@ui/card";
|
||||
|
||||
export const Server = () => {
|
||||
@@ -19,9 +19,9 @@ export const Server = () => {
|
||||
title={<ServerName serverId={serverId} />}
|
||||
info={
|
||||
<div className="flex items-center gap-4">
|
||||
<ServerIcon className="w-4 h-4" />
|
||||
<ServerStatusIcon serverId={serverId} />
|
||||
<CardDescription className="hidden md:block">|</CardDescription>
|
||||
<ServerInfo serverId={serverId} />
|
||||
<ServerStats server_id={serverId} />
|
||||
</div>
|
||||
}
|
||||
actions=""
|
||||
|
||||
@@ -2,7 +2,14 @@ import { useRead } from "@hooks";
|
||||
import { ServerStatus } from "@monitor/client/dist/types";
|
||||
import { CardDescription } from "@ui/card";
|
||||
import { cn } from "@util/helpers";
|
||||
import { Circle, Cpu, Database, MapPin, MemoryStick } from "lucide-react";
|
||||
import {
|
||||
Circle,
|
||||
Cpu,
|
||||
Database,
|
||||
MapPin,
|
||||
MemoryStick,
|
||||
Server,
|
||||
} from "lucide-react";
|
||||
import { useEffect } from "react";
|
||||
|
||||
export const ServerName = ({ serverId }: { serverId: string | undefined }) => {
|
||||
@@ -37,25 +44,28 @@ export const ServerStats = ({ server_id }: { server_id: string }) => {
|
||||
}, [refetch]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col text-sm text-muted-foreground">
|
||||
<div className="flex gap-4">
|
||||
<div className="flex gap-2 items-center">
|
||||
<Cpu className="w-4 h-4" />
|
||||
{data?.cpu_perc.toFixed(2)}%
|
||||
</div>
|
||||
<div className="flex gap-2 items-center">
|
||||
<MemoryStick className="w-4 h-4" />
|
||||
{data?.mem_total_gb.toFixed(2)} GB
|
||||
</div>
|
||||
<div className="flex gap-2 items-center">
|
||||
<Database className="w-4 h-4" />
|
||||
{data?.disk_total_gb.toFixed(2)} GB
|
||||
</div>
|
||||
<div className="flex gap-4 text-muted-foreground">
|
||||
<div className="flex gap-2 items-center">
|
||||
<Cpu className="w-4 h-4" />
|
||||
{data?.cpu_perc.toFixed(2)}%
|
||||
</div>
|
||||
<div className="flex gap-2 items-center">
|
||||
<MapPin className="w-4 h-4" />
|
||||
server.region
|
||||
<MemoryStick className="w-4 h-4" />
|
||||
{data?.mem_total_gb.toFixed(2)} GB
|
||||
</div>
|
||||
<div className="flex gap-2 items-center">
|
||||
<Database className="w-4 h-4" />
|
||||
{data?.disk_total_gb.toFixed(2)} GB
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const ServerRegion = () => {
|
||||
return (
|
||||
<div className="flex gap-2 items-center text-muted-foreground">
|
||||
<MapPin className="w-4 h-4" />
|
||||
server.region
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -70,9 +80,9 @@ export const ServerStatusIcon = ({
|
||||
const servers = useRead("ListServers", {}).data;
|
||||
const server = servers?.find((s) => s.id === serverId);
|
||||
return (
|
||||
<Circle
|
||||
<Server
|
||||
className={cn(
|
||||
"w-4 h-4 stroke-none",
|
||||
"w-4 h-4 stroke-primary",
|
||||
server?.status === ServerStatus.Ok && "fill-green-500",
|
||||
server?.status === ServerStatus.NotOk && "fill-red-500",
|
||||
server?.status === ServerStatus.Disabled && "fill-blue-500",
|
||||
|
||||
Reference in New Issue
Block a user