blob: 626c4339a86ee2fd0600399062ae68819acfbf0a [file] [log] [blame]
giob77cb932025-05-19 09:37:14 +00001import { z } from "zod";
2import { accessSchema, useEnv } from "./lib/state";
gio48679462025-05-21 04:27:27 +00003import { Copy, Check } from "lucide-react";
giob77cb932025-05-19 09:37:14 +00004import { Button } from "./components/ui/button";
5import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "./components/ui/tooltip";
6import { useCallback, useState } from "react";
gio48679462025-05-21 04:27:27 +00007import { AccessType } from "./components/icon";
giob77cb932025-05-19 09:37:14 +00008
9export function Gateways() {
10 const env = useEnv();
11 const groupedAccess = env.access.reduce((acc, curr) => {
12 if (!acc.has(curr.name)) {
13 acc.set(curr.name, []);
14 }
15 acc.get(curr.name)!.push(curr);
16 return acc;
17 }, new Map<string, typeof env.access>());
18 return (
19 <ul>
20 {Array.from(groupedAccess.entries()).map(([name, access]) => (
gio40370782025-05-19 11:04:52 +000021 <>
giob77cb932025-05-19 09:37:14 +000022 {access.map((a) => (
gio40370782025-05-19 11:04:52 +000023 <li key={name}>
24 <Gateway g={a} />
25 </li>
giob77cb932025-05-19 09:37:14 +000026 ))}
gio40370782025-05-19 11:04:52 +000027 </>
giob77cb932025-05-19 09:37:14 +000028 ))}
29 </ul>
30 );
31}
32
33function Gateway({ g }: { g: z.infer<typeof accessSchema> }) {
34 const [hidden, content] = (() => {
35 switch (g.type) {
36 case "https":
37 return [g.address, g.address];
38 case "ssh":
39 case "tcp":
40 case "udp":
41 return [`${g.host}:${g.port}`, `${g.host}:${g.port}`];
42 case "postgresql":
43 return [
44 `postgresql://${g.username}:*****@${g.host}:${g.port}/${g.database}`,
45 `postgresql://${g.username}:${g.password}@${g.host}:${g.port}/${g.database}`,
46 ];
47 case "mongodb":
48 return [
49 `mongodb://${g.username}:*****@${g.host}:${g.port}/${g.database}`,
50 `mongodb://${g.username}:${g.password}@${g.host}:${g.port}/${g.database}`,
51 ];
52 }
53 })();
54 const [clicked, setClicked] = useState(false);
55 const [open, setOpen] = useState(false);
56 const copy = useCallback(() => {
57 navigator.clipboard.writeText(content);
58 setClicked(true);
59 setOpen(true);
60 setTimeout(() => {
61 setClicked(false);
62 setOpen(false);
63 }, 1000);
64 }, [content, setClicked, setOpen]);
65 return (
66 <TooltipProvider>
67 <Tooltip delayDuration={100} open={open} onOpenChange={setOpen}>
68 <TooltipTrigger asChild>
gio6d8b71c2025-05-19 12:57:35 +000069 <Button
70 variant="ghost"
71 onClick={g.type === "https" ? () => window.open(content, "_blank") : copy}
72 className="!gap-1 !p-0 !h-fit"
73 >
giob77cb932025-05-19 09:37:14 +000074 <AccessType type={g.type} className="w-4 h-4" />
75 <div className="hover:bg-gray-200 p-x-1">{hidden}</div>
76 </Button>
77 </TooltipTrigger>
gio05a993c2025-05-19 11:51:33 +000078 <TooltipContent side="right" className="!bg-transparent cursor-pointer !p-0" sideOffset={10}>
giob77cb932025-05-19 09:37:14 +000079 {!clicked && <Copy className="w-4 h-4 !bg-transparent" color="black" />}
80 {clicked && <Check className="w-4 h-4 !bg-transparent" color="black" />}
81 </TooltipContent>
82 </Tooltip>
83 </TooltipProvider>
84 );
85}