improve cards, add tags and accordion

This commit is contained in:
karamvir
2023-07-25 14:27:48 -07:00
parent c8b312bcb1
commit 9a3b160e62
10 changed files with 188 additions and 27 deletions

View File

@@ -11,6 +11,7 @@
},
"dependencies": {
"@monitor/client": "link:../client/ts",
"@radix-ui/react-accordion": "^1.1.2",
"@radix-ui/react-dialog": "^1.0.4",
"@radix-ui/react-dropdown-menu": "^2.0.5",
"@radix-ui/react-label": "^2.0.2",

View File

@@ -1,3 +1,10 @@
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@ui/accordion";
import { Badge } from "@ui/badge";
import {
Card,
CardHeader,
@@ -28,12 +35,39 @@ export const ResourceCard = ({
<CardTitle>{title}</CardTitle>
<CardDescription>{description}</CardDescription>
</div>
{statusIcon}
<div className="flex items-center gap-2">
{statusIcon && (
<>
{statusIcon}
<div className="border h-6 w-0" />
</>
)}
{icon}
</div>
</CardHeader>
<CardContent className="flex items-center gap-4">
{icon}
<div className="border h-6" />
<CardContent className="flex flex-col gap-6">
{/* {icon}
<div className="border h-6" /> */}
{children}
<Accordion
type="single"
collapsible
onClick={(e) => {
e.stopPropagation();
e.preventDefault();
}}
>
<AccordionItem value="tags">
<AccordionTrigger>Show Tags</AccordionTrigger>
<AccordionContent>
<div className="flex gap-2 flex-wrap">
<Badge>crawler</Badge>
<Badge>prod</Badge>
<Badge>cex</Badge>
</div>
</AccordionContent>
</AccordionItem>
</Accordion>
</CardContent>
</Card>
);

View File

@@ -1,12 +1,4 @@
import { useRead } from "@hooks";
import { ServerStatusIcon } from "@resources/server/util";
import {
Card,
CardHeader,
CardTitle,
CardDescription,
CardContent,
} from "@ui/card";
import { version_to_string } from "@util/helpers";
import { Link } from "react-router-dom";
import { BuildInfo } from "./util";

View File

@@ -1,5 +1,4 @@
import { useRead } from "@hooks";
import { CardDescription } from "@ui/card";
import { version_to_string } from "@util/helpers";
import { Factory, History } from "lucide-react";
@@ -18,7 +17,7 @@ export const BuildVersion = ({ id }: { id: string }) => {
export const BuildBuilder = ({ id }: { id: string }) => {
const builds = useRead("ListBuilds", {}).data;
const build = builds?.find((b) => b.id === id);
return <>{build?.id.slice(0, 10) + "..." ?? "..."}</>;
return <>{build?.id ?? "..."}</>;
};
export const BuildLastBuilt = ({ id }: { id: string }) => {
@@ -30,7 +29,7 @@ export const BuildLastBuilt = ({ id }: { id: string }) => {
export const BuildInfo = ({ id }: { id: string }) => {
return (
<div className="flex items-center gap-4 text-sm text-muted-foreground">
<div className="flex flex-col text-muted-foreground text-sm">
<div className="flex items-center gap-2">
<Factory className="w-4 h-4" />
<BuildBuilder id={id} />

View File

@@ -19,5 +19,13 @@ export const DeploymentCard = ({ id }: { id: string }) => {
<DeploymentInfo deploymentId={id} />
</ResourceCard>
</Link>
// <ResourceCard
// title={deployment.name}
// description={deployment.status ?? "not deployed"}
// statusIcon={<DeploymentStatusIcon deploymentId={id} />}
// icon={<Rocket className="w-4 h-4" />}
// >
// <DeploymentInfo deploymentId={id} />
// </ResourceCard>
);
};

View File

@@ -46,7 +46,7 @@ export const DeploymentInfo = ({ deploymentId }: { deploymentId: string }) => {
const deployment = deployments?.find((d) => d.id === deploymentId);
return (
<div className="flex items-center gap-4 text-sm text-muted-foreground">
<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

View File

@@ -2,7 +2,7 @@ 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 { Circle, Cpu, Database, MapPin, MemoryStick } from "lucide-react";
import { useEffect } from "react";
export const ServerName = ({ serverId }: { serverId: string | undefined }) => {
@@ -37,18 +37,24 @@ export const ServerStats = ({ server_id }: { server_id: string }) => {
}, [refetch]);
return (
<div className="flex gap-4 text-sm text-muted-foreground">
<div className="flex gap-2 items-center ">
<Cpu className="w-4 h-4" />
{data?.cpu_perc.toFixed(2)}%
<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>
<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
<MapPin className="w-4 h-4" />
server.region
</div>
</div>
);

View File

@@ -0,0 +1,55 @@
"use client";
import * as React from "react";
import * as AccordionPrimitive from "@radix-ui/react-accordion";
// import { ChevronDownIcon } from "@radix-ui/react-icons";
import { cn } from "@util/helpers";
import { ChevronDown } from "lucide-react";
const Accordion = AccordionPrimitive.Root;
const AccordionItem = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
>(({ ...props }, ref) => <AccordionPrimitive.Item ref={ref} {...props} />);
AccordionItem.displayName = "AccordionItem";
const AccordionTrigger = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
>(({ className, children, ...props }, ref) => (
<AccordionPrimitive.Header className="flex">
<AccordionPrimitive.Trigger
ref={ref}
className={cn(
"flex flex-1 items-center justify-between py-2 text-sm font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180",
className
)}
{...props}
>
{children}
<ChevronDown className="h-4 w-4 shrink-0 text-muted-foreground transition-transform duration-200" />
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
));
AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;
const AccordionContent = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
>(({ className, children, ...props }, ref) => (
<AccordionPrimitive.Content
ref={ref}
className={cn(
"overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down",
className
)}
{...props}
>
{children}
</AccordionPrimitive.Content>
));
AccordionContent.displayName = AccordionPrimitive.Content.displayName;
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent };

35
frontend/src/ui/badge.tsx Normal file
View File

@@ -0,0 +1,35 @@
import * as React from "react";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@util/helpers";
const badgeVariants = cva(
"inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
{
variants: {
variant: {
default:
"border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80",
secondary:
"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
destructive:
"border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80",
outline: "text-foreground",
},
},
defaultVariants: {
variant: "default",
},
}
);
export interface BadgeProps
extends React.HTMLAttributes<HTMLDivElement>,
VariantProps<typeof badgeVariants> {}
function Badge({ className, variant, ...props }: BadgeProps) {
return (
<div className={cn(badgeVariants({ variant }), className)} {...props} />
);
}
export { Badge, badgeVariants };

View File

@@ -485,6 +485,22 @@
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-accordion@^1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@radix-ui/react-accordion/-/react-accordion-1.1.2.tgz#738441f7343e5142273cdef94d12054c3287966f"
integrity sha512-fDG7jcoNKVjSK6yfmuAs0EnPDro0WMXIhMtXdTBWqEioVW206ku+4Lw07e+13lUkFkpoEQ2PdeMIAGpdqEAmDg==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/primitive" "1.0.1"
"@radix-ui/react-collapsible" "1.0.3"
"@radix-ui/react-collection" "1.0.3"
"@radix-ui/react-compose-refs" "1.0.1"
"@radix-ui/react-context" "1.0.1"
"@radix-ui/react-direction" "1.0.1"
"@radix-ui/react-id" "1.0.1"
"@radix-ui/react-primitive" "1.0.3"
"@radix-ui/react-use-controllable-state" "1.0.1"
"@radix-ui/react-arrow@1.0.3":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.0.3.tgz#c24f7968996ed934d57fe6cde5d6ec7266e1d25d"
@@ -493,6 +509,21 @@
"@babel/runtime" "^7.13.10"
"@radix-ui/react-primitive" "1.0.3"
"@radix-ui/react-collapsible@1.0.3":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@radix-ui/react-collapsible/-/react-collapsible-1.0.3.tgz#df0e22e7a025439f13f62d4e4a9e92c4a0df5b81"
integrity sha512-UBmVDkmR6IvDsloHVN+3rtx4Mi5TFvylYXpluuv0f37dtaz3H99bp8No0LGXRigVpl3UAT4l9j6bIchh42S/Gg==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/primitive" "1.0.1"
"@radix-ui/react-compose-refs" "1.0.1"
"@radix-ui/react-context" "1.0.1"
"@radix-ui/react-id" "1.0.1"
"@radix-ui/react-presence" "1.0.1"
"@radix-ui/react-primitive" "1.0.3"
"@radix-ui/react-use-controllable-state" "1.0.1"
"@radix-ui/react-use-layout-effect" "1.0.1"
"@radix-ui/react-collection@1.0.2":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-1.0.2.tgz#d50da00bfa2ac14585319efdbbb081d4c5a29a97"