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