consolidate page layouts, cleanup

This commit is contained in:
karamvir
2023-07-25 11:56:57 -07:00
parent 6f5a7b97b5
commit 59a06c84a1
11 changed files with 161 additions and 78 deletions

View File

@@ -2,6 +2,7 @@ import { useRead } from "@hooks";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@ui/dropdown";
@@ -21,9 +22,11 @@ export const DesktopUpdates = () => {
</DropdownMenuTrigger>
<DropdownMenuContent>
{updates?.map((update) => (
<DropdownMenuItem key={update._id?.$oid}>
<SingleUpdate update={update} />
</DropdownMenuItem>
<DropdownMenuGroup>
<div className="p-2 hover:bg-muted transition-colors">
<SingleUpdate update={update} />
</div>
</DropdownMenuGroup>
))}
</DropdownMenuContent>
</DropdownMenu>

View File

@@ -13,7 +13,16 @@ import {
readableVersion,
version_to_string,
} from "@util/helpers";
import { Calendar, Clock, Milestone, Search, User } from "lucide-react";
import {
Calendar,
Clock,
Hammer,
Milestone,
Rocket,
Search,
Server,
User,
} from "lucide-react";
// import { UpdateUser } from ".";
import {
Card,
@@ -22,6 +31,11 @@ import {
CardHeader,
CardTitle,
} from "@ui/card";
import { ReactNode } from "react";
import { useNavigate } from "react-router-dom";
import { ServerName } from "@resources/server/util";
import { DeploymentName } from "@resources/deployment/util";
import { BuildName } from "@resources/build/util";
// import { useRead } from "@hooks";
export const UpdateUser = ({ userId }: { userId: string }) => {
@@ -31,18 +45,17 @@ export const UpdateUser = ({ userId }: { userId: string }) => {
return <>{userId.slice(0, 5)}...</>;
};
export const UpdateDetails = ({ update }: { update: Update }) => {
export const UpdateDetails = ({
update,
children,
}: {
update: Update;
children: ReactNode;
}) => {
const nav = useNavigate();
return (
<Sheet>
<SheetTrigger asChild>
<Button
variant="outline"
size="sm"
className="flex items-center gap-2 w-full max-w-fit"
>
<Search className="w-4 h-4" />
</Button>
</SheetTrigger>
<SheetTrigger>{children}</SheetTrigger>
<SheetContent position="right" size="lg">
<SheetHeader className="mb-4">
<SheetTitle>
@@ -53,6 +66,37 @@ export const UpdateDetails = ({ update }: { update: Update }) => {
{version_to_string(update.version)}
</SheetTitle>
<SheetDescription className="flex flex-col gap-2">
<div
className="flex items-center gap-2 cursor-pointer"
onClick={() => {
update.target.id
? nav(
`/${update.target.type.toLowerCase()}s/${
update.target.id
}`
)
: null;
}}
>
{update.target.type === "Server" && (
<>
<Server className="w-4 h-4" />
<ServerName serverId={update.target.id} />
</>
)}
{update.target.type === "Deployment" && (
<>
<Rocket className="w-4 h-4" />
<DeploymentName deploymentId={update.target.id} />
</>
)}
{update.target.type === "Build" && (
<>
<Hammer className="w-4 h-4" />
<BuildName id={update.target.id} />
</>
)}
</div>
<div className="flex items-center gap-2">
<Calendar className="w-4 h-4" />
{new Date(update.start_ts).toLocaleString()}

View File

@@ -4,28 +4,28 @@ import { UpdateDetails, UpdateUser } from "./update";
import { Update } from "@monitor/client/dist/types";
export const SingleUpdate = ({ update }: { update: Update }) => (
<div className="flex items-center justify-between">
<div>
{update.operation
.split("_")
.map((s) => s[0].toUpperCase() + s.slice(1))
.join(" ")}{" "}
{version_to_string(update.version)}
</div>
<div>
<div className="flex gap-2 items-center md:w-[200px]">
<Calendar className="w-4 h-4" />
<div className="text-xs md:text-sm">
<UpdateDetails update={update}>
<div className="flex items-center justify-between">
<div className="flex gap-2 items-center">
<div className="text-xs">
{update.end_ts ? new Date(update.end_ts).toLocaleString() : "ongoing"}
</div>
</div>
</div>
<div className="flex gap-2 items-center">
<User className="w-4 h-4" />
<div>
<UpdateUser userId={update.operator} />
{update.operation
.split("_")
.map((s) => s[0].toUpperCase() + s.slice(1))
.join(" ")}{" "}
{version_to_string(update.version)}
</div>
<div className="flex gap-2 items-center">
<User className="w-4 h-4" />
<div>
<UpdateUser userId={update.operator} />
</div>
</div>
</div>
<UpdateDetails update={update} />
</div>
</UpdateDetails>
);

View File

@@ -0,0 +1,21 @@
import { ReactNode } from "react";
interface PageProps {
title: ReactNode;
subtitle: ReactNode;
actions: ReactNode;
content: ReactNode;
}
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">
{title}
{subtitle}
</div>
{actions}
</div>
{content}
</div>
);

View File

@@ -1,5 +1,6 @@
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@ui/tabs";
import { ReactNode } from "react";
import { Page } from "./page";
interface ResourceProps {
title: ReactNode;
@@ -10,28 +11,26 @@ interface ResourceProps {
export const Resource = ({ title, info, actions, tabs }: ResourceProps) => (
<Tabs defaultValue={tabs[0].title}>
<div className="flex flex-col w-full gap-12">
<div className="flex flex-col lg:flex-row gap-2 justify-between">
<div>
<div className="text-4xl">{title}</div>
<h2 className="text-xl">{info}</h2>
</div>
<div className="flex gap-4">{actions}</div>
</div>
<div className="flex flex-col gap-2">
<TabsList className=" w-fit">
{tabs.map(({ title }) => (
<TabsTrigger key={title} value={title}>
{title}
</TabsTrigger>
<Page
title={<h1 className="text-4xl">{title}</h1>}
subtitle={<h2 className="text-lg">{info}</h2>}
actions={actions}
content={
<div className="flex flex-col gap-2">
<TabsList className=" w-fit">
{tabs.map(({ title }) => (
<TabsTrigger key={title} value={title}>
{title}
</TabsTrigger>
))}
</TabsList>
{tabs.map((t, i) => (
<TabsContent key={i} value={t.title}>
{t.component}
</TabsContent>
))}
</TabsList>
{tabs.map((t, i) => (
<TabsContent key={i} value={t.title}>
{t.component}
</TabsContent>
))}
</div>
</div>
</div>
}
/>
</Tabs>
);

View File

@@ -1,8 +1,10 @@
import { NewDeployment } from "@resources/deployment/new";
import { Button } from "@ui/button";
import { Input } from "@ui/input";
import { History } from "lucide-react";
import { PlusCircle } from "lucide-react";
import { ReactNode, useState } from "react";
import { Page } from "./page";
export const Resources = ({
type,
@@ -18,15 +20,15 @@ export const Resources = ({
const [search, setSearch] = useState("");
const [open, setOpen] = useState(false);
return (
<div className="flex flex-col gap-12">
<div className="flex justify-between">
<div>
<h1 className="text-4xl">{type}s</h1>
<div className="flex items-center gap-2 text-muted-foreground">
{icon}
<h2 className="text-xl">{info}</h2>
</div>
</div>
<Page
title={<h1 className="text-4xl">{type}s</h1>}
subtitle={
<h2 className="text-lg text-muted-foreground flex items-center gap-2">
{icon}
{info}
</h2>
}
actions={
<div className="flex gap-4">
<Input
className="w-[300px]"
@@ -45,8 +47,10 @@ export const Resources = ({
</Button>
<NewDeployment open={open} set={setOpen} />
</div>
</div>
<div className="grid grid-cols-3 gap-8">{components(search)}</div>
</div>
}
content={
<div className="grid grid-cols-3 gap-8">{components(search)}</div>
}
/>
);
};

View File

@@ -78,7 +78,7 @@ export const RecentlyViewed = () => {
{!!recents.length && (
<div className="flex items-center gap-2 text-muted-foreground">
<History className="w-4 h-4" />
<h2 className="text-xl ">Recently Viewed</h2>
<h2 className="text-xl">Recently Viewed</h2>
</div>
)}
</div>

View File

@@ -14,6 +14,7 @@ import {
StartOrStopContainer,
} from "./components/actions";
import { DeploymentLogs } from "./components/deployment-logs";
import { Rocket } from "lucide-react";
export const Deployment = () => {
const { deploymentId } = useParams();
@@ -26,7 +27,9 @@ export const Deployment = () => {
<Resource
title={<DeploymentName deploymentId={deploymentId} />}
info={
<div className="flex flex-col gap-2 md:flex-row md:items-center md:gap-4">
<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">
<DeploymentStatusIcon deploymentId={deploymentId} />
<DeploymentStatus deploymentId={deploymentId} />
@@ -36,11 +39,11 @@ export const Deployment = () => {
</div>
}
actions={
<>
<div className="flex gap-4">
<RedeployContainer deployment_id={deploymentId} />
<StartOrStopContainer deployment_id={deploymentId} />
<RemoveContainer deployment_id={deploymentId} />
</>
</div>
}
tabs={[
{

View File

@@ -35,7 +35,7 @@ export const Servers = () => {
<Resources
type="Server"
info={`${summary?.total} Total, ${summary?.healthy} Healthy, ${summary?.unhealthy} Unhealthy`}
icon={<Server className="w-6 h-6" />}
icon={<Server className="w-4 h-4" />}
components={(search) => (
<>
{servers
@@ -57,7 +57,7 @@ export const Builds = () => {
<Resources
type="Build"
info={`${summary?.total} Total`}
icon={<Hammer className="w-6 h-6" />}
icon={<Hammer className="w-4 h-4" />}
components={(search) => (
<>
{builds
@@ -79,7 +79,7 @@ export const Builders = () => {
<Resources
type="Builder"
info={`${summary?.total} Total`}
icon={<Factory className="w-6 h-6" />}
icon={<Factory className="w-4 h-4" />}
components={(search) => (
<>
{builders

View File

@@ -2,6 +2,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 { CardDescription } from "@ui/card";
export const Server = () => {
const { serverId } = useParams();
@@ -15,7 +17,13 @@ export const Server = () => {
return (
<Resource
title={<ServerName serverId={serverId} />}
info={<ServerInfo serverId={serverId} />}
info={
<div className="flex items-center gap-4">
<ServerIcon className="w-4 h-4" />
<CardDescription className="hidden md:block">|</CardDescription>
<ServerInfo serverId={serverId} />
</div>
}
actions=""
tabs={[
{

View File

@@ -1,5 +1,6 @@
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, MemoryStick } from "lucide-react";
import { useEffect } from "react";
@@ -15,12 +16,12 @@ export const ServerInfo = ({ serverId }: { serverId: string | undefined }) => {
const server = servers?.find((s) => s.id === serverId);
return (
<div className="flex items-center gap-4 text-muted-foreground">
{serverId && <ServerStats server_id={serverId} />}
<div>|</div>
<div className="flex items-center gap-4">
<div> Status: {server?.status}</div>
<div className="flex items-center gap-2">
<ServerStatusIcon serverId={serverId} />
<div> {server?.status}</div>
</div>
<CardDescription className="hidden md:block">|</CardDescription>
{serverId && <ServerStats server_id={serverId} />}
</div>
);
};