Canvas: Render network nodes

Change-Id: I63938da205af9377a1e210c0e972591142211a68
diff --git a/apps/canvas/front/src/components/node-gateway-tcp.tsx b/apps/canvas/front/src/components/node-gateway-tcp.tsx
index aeca41e..3588502 100644
--- a/apps/canvas/front/src/components/node-gateway-tcp.tsx
+++ b/apps/canvas/front/src/components/node-gateway-tcp.tsx
@@ -23,17 +23,26 @@
 
 export function NodeGatewayTCP(node: GatewayTCPNode) {
   const { id, selected } = node;
+  const isConnectableNetwork = useMemo(() => nodeIsConnectable(node, "subdomain"), [node]);
   const isConnectable = useMemo(() => nodeIsConnectable(node, "tcp"), [node]);
   return (
     <NodeRect id={id} selected={selected} type={node.type} state={node.data.state}>
       {nodeLabel(node)}
       <Handle
+        type={"source"}
+        id="subdomain"
+        position={Position.Top}
+        isConnectable={isConnectableNetwork}
+        isConnectableStart={isConnectableNetwork}
+        isConnectableEnd={isConnectableNetwork}
+      />
+      <Handle
         type={"target"}
-        id="tcp" 
+        id="tcp"
         position={Position.Bottom}
         isConnectable={isConnectable}
-        isConnectableStart={isConnectable} 
-        isConnectableEnd={isConnectable} 
+        isConnectableStart={isConnectable}
+        isConnectableEnd={isConnectable}
       />
     </NodeRect>
   );
@@ -46,24 +55,41 @@
     resolver: zodResolver(schema),
     mode: "onChange",
     defaultValues: {
-      network: "",
-      subdomain: "",
+      network: data.network,
+      subdomain: data.subdomain,
     },
   });
   useEffect(() => {
     const sub = form.watch((value: DeepPartial<z.infer<typeof schema>>, { name }: { name?: keyof z.infer<typeof schema> | undefined, type?: EventType | undefined }) => {
       if (name === "network") {
-        if (value.network !== undefined) {
-          store.updateNodeData<"gateway-tcp">(id, { network: value.network });
-        } else {
-          
+        let edges = store.edges;
+        if (data.network !== undefined) {
+          edges = edges.filter((e) => {
+            console.log(e);
+            if (e.source === id && e.sourceHandle === "subdomain" && e.target === data.network && e.targetHandle === "subdomain") {
+              return false;
+            } else {
+              return true;
+            }
+          });
         }
+        if (value.network !== undefined) {
+          edges = edges.concat({
+            id: uuidv4(),
+            source: id,
+            sourceHandle: "subdomain",
+            target: value.network,
+            targetHandle: "subdomain",
+          });
+        }
+        store.setEdges(edges);
+        store.updateNodeData<"gateway-tcp">(id, { network: value.network });
       } else if (name === "subdomain") {
         store.updateNodeData<"gateway-tcp">(id, { subdomain: value.subdomain });
       }
     });
     return () => sub.unsubscribe();
-  }, [form, store]);
+  }, [id, data, form, store]);
   const connectedToForm = useForm<z.infer<typeof connectedToSchema>>({
     resolver: zodResolver(connectedToSchema),
     mode: "onSubmit",
@@ -142,7 +168,7 @@
     setPortLabels(new Map((data.exposed || []).map((e) => [`${e.serviceId} - ${e.portId}`, (nodes.find((n) => n.id === e.serviceId)!.data.ports || []).find((p) => p.id === e.portId)!.name])));
   }, [nodes, data, setNodeLabels, setPortLabels]);
   const onSubmit = useCallback((values: z.infer<typeof connectedToSchema>) => {
-    store.setEdges(store.edges.filter((e) => e.target !== id));
+    const edges = store.edges.filter((e) => e.target !== id);
     const exp = (data.exposed || []).concat({
       serviceId: values.serviceId,
       portId: values.portId,
@@ -151,7 +177,7 @@
       exposed: exp,
       selected: undefined,
     });
-    store.setEdges(store.edges.concat(exp.map((e): Edge => ({
+    store.setEdges(edges.concat(exp.map((e): Edge => ({
       id: uuidv4(),
       source: e.serviceId,
       sourceHandle: "ports",
@@ -163,7 +189,7 @@
     <>
       <Form {...form}>
         <form className="space-y-2">
-          <FormField 
+          <FormField
             control={form.control}
             name="network"
             render={({ field }) => (
@@ -184,7 +210,7 @@
               </FormItem>
             )}
           />
-          <FormField 
+          <FormField
             control={form.control}
             name="subdomain"
             render={({ field }) => (
@@ -208,7 +234,7 @@
       </ul>
       <Form {...connectedToForm}>
         <form className="space-y-2" onSubmit={connectedToForm.handleSubmit(onSubmit)}>
-        <FormField
+          <FormField
             control={connectedToForm.control}
             name="serviceId"
             render={({ field }) => (
@@ -229,7 +255,7 @@
               </FormItem>
             )}
           />
-          <FormField 
+          <FormField
             control={connectedToForm.control}
             name="portId"
             render={({ field }) => (
@@ -247,7 +273,7 @@
                   </SelectContent>
                 </Select>
                 <FormMessage />
-              </FormItem>           
+              </FormItem>
             )}
           />
           <Button type="submit">Expose</Button>