blob: 9b6cb20cd1203ef252ca790c8154c14fa8059d74 [file] [log] [blame]
gio5f2f1002025-03-20 18:38:48 +04001import { useNodes } from "@xyflow/react";
gio3ec94242025-05-16 12:46:57 +00002import { AppNode, nodeLabel, NodeType, useMode } from "@/lib/state";
gio5f2f1002025-03-20 18:38:48 +04003import { NodeDetails } from "@/components/node-details";
4import { Accordion, AccordionContent, AccordionTrigger } from "./ui/accordion";
5import { AccordionItem } from "@radix-ui/react-accordion";
gio6cf8c272025-05-08 09:01:38 +00006import { useMemo, useState } from "react";
gio5f2f1002025-03-20 18:38:48 +04007import { Icon } from "./icon";
gio880de162025-05-11 07:26:00 +00008import { Separator } from "./ui/separator";
gio5f2f1002025-03-20 18:38:48 +04009
10function unique<T>(v: T, i: number, a: T[]) {
giod0026612025-05-08 13:00:36 +000011 return a.indexOf(v) === i;
gio5f2f1002025-03-20 18:38:48 +040012}
13
giofe746dd2025-05-07 09:57:40 +000014const nodeTypeIndex = new Map<NodeType, number>([
giod0026612025-05-08 13:00:36 +000015 ["github", 1],
16 // ["gitlab", 2],
17 ["volume", 3],
18 ["postgresql", 4],
19 ["mongodb", 5],
20 ["app", 6],
21 ["gateway-tcp", 7],
22 ["gateway-https", 8],
giofe746dd2025-05-07 09:57:40 +000023]);
24
gio6cf8c272025-05-08 09:01:38 +000025function cmpNodes(x: AppNode, y: AppNode): number {
giod0026612025-05-08 13:00:36 +000026 if (x.type === y.type) {
27 if (nodeLabel(x) < nodeLabel(y)) {
28 return -1;
29 } else if (nodeLabel(x) > nodeLabel(y)) {
30 return 1;
31 }
32 return 0;
33 }
34 // TODO(gio): why !
35 return (nodeTypeIndex.get(x.type!) || 0) - (nodeTypeIndex.get(y.type!) || 0);
gio6cf8c272025-05-08 09:01:38 +000036}
37
gio5f2f1002025-03-20 18:38:48 +040038export function Details() {
giod0026612025-05-08 13:00:36 +000039 const nodes = useNodes<AppNode>();
40 const sorted = useMemo(() => nodes.filter((n) => n.type !== "network").sort(cmpNodes), [nodes]);
41 const [open, setOpen] = useState<string[]>([]);
42 const selected = useMemo(() => nodes.filter((n) => n.selected).map((n) => n.id), [nodes]);
43 const all = useMemo(() => open.concat(selected).filter(unique), [open, selected]);
gio3ec94242025-05-16 12:46:57 +000044 const mode = useMode();
45 const isDeployMode = mode === "deploy";
46
giod0026612025-05-08 13:00:36 +000047 return (
gio8cadbc72025-05-16 07:51:02 +000048 <Accordion
49 type="multiple"
50 value={all}
51 onValueChange={(v) => setOpen(v)}
52 className="flex flex-col overflow-y-auto"
53 >
gio880de162025-05-11 07:26:00 +000054 {sorted.map((n, index) => (
55 <>
giof8fa0f82025-05-16 12:34:26 +000056 {index > 0 && <Separator />}
57 <AccordionItem key={n.id} value={n.id} className="px-1">
58 <AccordionTrigger className="!h-fit">
gio0b4002c2025-05-11 15:48:51 +000059 <div className="flex flex-row space-x-2 items-center">
60 <Icon type={n.type} />
gio880de162025-05-11 07:26:00 +000061 <span>{nodeLabel(n)}</span>
62 </div>
63 </AccordionTrigger>
giof8fa0f82025-05-16 12:34:26 +000064 <AccordionContent className="pt-1">
gio08acd3a2025-06-12 12:15:30 +000065 <NodeDetails node={n} disabled={isDeployMode} />
gio880de162025-05-11 07:26:00 +000066 </AccordionContent>
67 </AccordionItem>
68 </>
giod0026612025-05-08 13:00:36 +000069 ))}
70 </Accordion>
71 );
gio5f2f1002025-03-20 18:38:48 +040072}