add dropdown link

This commit is contained in:
Lorenzo Migliorero
2024-10-03 15:27:48 +02:00
parent 9b255964fe
commit 21ee22d4f5
2 changed files with 93 additions and 9 deletions

View File

@@ -15,14 +15,18 @@ import { Card, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
import { import {
DropdownMenu, DropdownMenu,
DropdownMenuContent, DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem, DropdownMenuItem,
DropdownMenuLabel, DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger, DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"; } from "@/components/ui/dropdown-menu";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { import {
AlertTriangle, AlertTriangle,
BookIcon, BookIcon,
CircuitBoard,
ExternalLink,
ExternalLinkIcon, ExternalLinkIcon,
FolderInput, FolderInput,
MoreHorizontalIcon, MoreHorizontalIcon,
@@ -31,6 +35,7 @@ import {
import Link from "next/link"; import Link from "next/link";
import { toast } from "sonner"; import { toast } from "sonner";
import { UpdateProject } from "./update"; import { UpdateProject } from "./update";
import { Fragment } from "react";
export const ShowProjects = () => { export const ShowProjects = () => {
const utils = api.useUtils(); const utils = api.useUtils();
@@ -45,6 +50,7 @@ export const ShowProjects = () => {
}, },
); );
const { mutateAsync } = api.project.remove.useMutation(); const { mutateAsync } = api.project.remove.useMutation();
return ( return (
<> <>
{data?.length === 0 && ( {data?.length === 0 && (
@@ -74,17 +80,85 @@ export const ShowProjects = () => {
project?.redis.length + project?.redis.length +
project?.applications.length + project?.applications.length +
project?.compose.length; project?.compose.length;
const flattedDomains = [
...project.applications.flatMap((a) => a.domains),
...project.compose.flatMap((a) => a.domains),
];
const renderDomainsDropdown = (
item: typeof project.compose | typeof project.applications,
) =>
item[0] ? (
<DropdownMenuGroup>
<DropdownMenuLabel>
{"applicationId" in item[0] ? "Applications" : "Compose"}
</DropdownMenuLabel>
{item.map((a) => (
<Fragment
key={"applicationId" in a ? a.applicationId : a.composeId}
>
<DropdownMenuSeparator />
<DropdownMenuGroup>
<DropdownMenuLabel className="font-normal capitalize text-xs ">
{a.name}
</DropdownMenuLabel>
<DropdownMenuSeparator />
{a.domains.map((domain) => (
<DropdownMenuItem key={domain.domainId} asChild>
<Link
className="space-x-4 text-xs cursor-pointer justify-between"
target="_blank"
href={`${domain.https ? "https" : "http"}://${domain.host}${domain.path}`}
onClick={(e) => e.stopPropagation()}
>
<span>{domain.host}</span>
<ExternalLink className="size-4 shrink-0" />
</Link>
</DropdownMenuItem>
))}
</DropdownMenuGroup>
</Fragment>
))}
</DropdownMenuGroup>
) : null;
return ( return (
<div key={project.projectId} className="w-full lg:max-w-md"> <div key={project.projectId} className="w-full lg:max-w-md">
<Link href={`/dashboard/project/${project.projectId}`}> <Link href={`/dashboard/project/${project.projectId}`}>
<Card className="group relative w-full bg-transparent transition-colors hover:bg-card"> <Card className="group relative w-full bg-transparent transition-colors hover:bg-card">
<Button {flattedDomains.length > 1 ? (
className="absolute -right-3 -top-3 size-9 translate-y-1 rounded-full p-0 opacity-0 transition-all duration-200 group-hover:translate-y-0 group-hover:opacity-100" <DropdownMenu>
size="sm" <DropdownMenuTrigger asChild>
variant="default" <Button
> className="absolute -right-3 -top-3 size-9 translate-y-1 rounded-full p-0 opacity-0 transition-all duration-200 group-hover:translate-y-0 group-hover:opacity-100"
<ExternalLinkIcon className="size-3.5" /> size="sm"
</Button> variant="default"
>
<ExternalLinkIcon className="size-3.5" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-[200px] space-y-2">
{renderDomainsDropdown(project.applications)}
{renderDomainsDropdown(project.compose)}
</DropdownMenuContent>
</DropdownMenu>
) : flattedDomains[0] ? (
<Button
className="absolute -right-3 -top-3 size-9 translate-y-1 rounded-full p-0 opacity-0 transition-all duration-200 group-hover:translate-y-0 group-hover:opacity-100"
size="sm"
variant="default"
onClick={(e) => e.stopPropagation()}
>
<Link
href={`${flattedDomains[0].https ? "https" : "http"}://${flattedDomains[0].host}${flattedDomains[0].path}`}
target="_blank"
>
<ExternalLinkIcon className="size-3.5" />
</Link>
</Button>
) : null}
<CardHeader> <CardHeader>
<CardTitle className="flex items-center justify-between gap-2"> <CardTitle className="flex items-center justify-between gap-2">
<span className="flex flex-col gap-1.5"> <span className="flex flex-col gap-1.5">

View File

@@ -125,6 +125,7 @@ export const projectRouter = createTRPCRouter({
applications.applicationId, applications.applicationId,
accesedServices, accesedServices,
), ),
with: { domains: true },
}, },
mariadb: { mariadb: {
where: buildServiceFilter(mariadb.mariadbId, accesedServices), where: buildServiceFilter(mariadb.mariadbId, accesedServices),
@@ -143,6 +144,7 @@ export const projectRouter = createTRPCRouter({
}, },
compose: { compose: {
where: buildServiceFilter(compose.composeId, accesedServices), where: buildServiceFilter(compose.composeId, accesedServices),
with: { domains: true },
}, },
}, },
orderBy: desc(projects.createdAt), orderBy: desc(projects.createdAt),
@@ -153,13 +155,21 @@ export const projectRouter = createTRPCRouter({
return await db.query.projects.findMany({ return await db.query.projects.findMany({
with: { with: {
applications: true, applications: {
with: {
domains: true,
},
},
mariadb: true, mariadb: true,
mongo: true, mongo: true,
mysql: true, mysql: true,
postgres: true, postgres: true,
redis: true, redis: true,
compose: true, compose: {
with: {
domains: true,
},
},
}, },
where: eq(projects.adminId, ctx.user.adminId), where: eq(projects.adminId, ctx.user.adminId),
orderBy: desc(projects.createdAt), orderBy: desc(projects.createdAt),