From 06a887852983d4cc02a9ac34493604aa30e86c8b Mon Sep 17 00:00:00 2001 From: Matt Forrest Date: Wed, 10 Aug 2022 15:10:41 -0500 Subject: [PATCH] Cleaning up code prior to adding floating edges --- src/App.tsx | 349 ++++++++++++++++++++++++++++++------ src/Edge.js | 104 +++++++++++ src/{Nodes.js => Nodes.tsx} | 27 ++- src/SocketClient.tsx | 303 ------------------------------- src/edgeStyles.css | 2 +- src/index.tsx | 4 +- 6 files changed, 412 insertions(+), 377 deletions(-) create mode 100644 src/Edge.js rename src/{Nodes.js => Nodes.tsx} (89%) delete mode 100644 src/SocketClient.tsx diff --git a/src/App.tsx b/src/App.tsx index e113d8a..b8b168e 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,62 +1,297 @@ -import { useState, useCallback } from 'react'; +import React, {useState, useEffect, useCallback, CSSProperties} from 'react'; +import io from 'socket.io-client'; +import Table from "@mui/material/Table"; +import TableHead from "@mui/material/TableHead"; +import TableRow from "@mui/material/TableRow"; +import TableCell from "@mui/material/TableCell"; +import TableBody from "@mui/material/TableBody"; +import TableContainer from "@mui/material/TableContainer"; +import {TableFooter} from "@mui/material"; import ReactFlow, { - Controls, - addEdge, - FitViewOptions, - applyNodeChanges, - applyEdgeChanges, - Node, - Edge, - NodeChange, - EdgeChange, - Connection -} from 'react-flow-renderer'; - -const initialNodes: Node[] = [ - { id: '1', data: { label: 'Node 1' }, position: { x: 5, y: 5 } }, - { id: '2', data: { label: 'Node 2' }, position: { x: 5, y: 100 } }, -]; - -const initialEdges: Edge[] = [ - { id: 'e1-2', source: '1', target: '2'}, -]; - -const fitViewOptions: FitViewOptions = { - padding: 0.2 + addEdge, + applyEdgeChanges, + applyNodeChanges, Connection, + Controls, + Edge, + EdgeChange, + FitViewOptions, + Node, + NodeChange, ReactFlowInstance, ReactFlowProvider, useReactFlow +} from "react-flow-renderer"; +import { getLayoutedElements } from "./Layout"; +import { nodeTypes } from "./Nodes"; +import "./nodeStyles.css" +import "./edgeStyles.css" +import CustomEdge from './Edge'; + +const socket = io("http://localhost:4000"); + +export const App = ()=> { + const [isConnected, setIsConnected] = useState(socket.connected); + const [consoleLines, setConsoleLines] = useState([""]); + const [inputtedMessage, setInputtedMessage] = useState(''); + const [sendReadyState, setSendReadyState] = useState(false) + enum LastCommand { + NO_CMD = "no_cmd", + GET_ATOMS = "get_atoms", + PUT_ATOM = "put_atom", + ERROR = "error", + GET_NODES = "get_nodes", + GET_LINKS = "get_links" + } + const [curCmdState, setCurCmdState] = useState(LastCommand.NO_CMD) + let curCmd = LastCommand.NO_CMD + let nodeCount = 3; + const bottomRef = React.useRef(null); + + const initialNodes: Node[] = [ + ]; + + const initialEdges: Edge[] = [ + ]; + + const fitViewOptions: FitViewOptions = { + padding: 0.2 + } + + + const [nodes, setNodesState] = useState(initialNodes); + const [edges, setEdgesState] = useState(initialEdges); + + const setNodes = (nodes: Node[]) => { + const layoutedElements = getLayoutedElements(nodes, edges); + setNodesState(layoutedElements.nodes); + } + + const setEdges = (edges: Edge[]) => { + const layoutedElements = getLayoutedElements(nodes, edges); + setEdgesState(layoutedElements.edges); + } + const onNodesChange = useCallback( + (changes: NodeChange[]) => setNodes(applyNodeChanges(changes, nodes)), + [setNodes] + ); + const onEdgesChange = useCallback( + (changes: EdgeChange[]) => setEdges(applyEdgeChanges(changes, edges)), + [setEdges] + ); + const onConnect = useCallback( + (connection: Connection) => setEdges(addEdge(connection, edges)), + [setEdges] + ); + + const reactFlowInstance = useReactFlow(); + const makeNodes = useCallback(() => { + let newNode = { id: `${nodeCount}`, data: { label: `Node ${nodeCount}` }, position: { x: 100, y: 100 } }; + nodeCount++; + reactFlowInstance.addNodes(newNode) + }, []); + + const setAtoms = useCallback((atoms: AtomBase[]) => { + let linkAtoms = atoms.filter(atom => atom.type.includes("Link")) + let nodeAtoms = atoms.filter(atom => atom.type.includes("Node")) + let newNodes: Node[] = []; + let newEdges: Edge[] = []; + nodeAtoms.forEach((atom:AtomBase, index:number, array:AtomBase[])=>{ + let newNode = { id: `${atom.name}`, type: "rectangle", data: { label: `Name: ${atom.name}`, info: `Type: ${atom.type}`, atomType: atom.type }, position: { x: 100, y: 100 }}; + newNodes.push(newNode); + }); + (linkAtoms as AtomLink[]).forEach((link:AtomLink, index:number, array:AtomBase[])=>{ + let linkId = `${link.type}:${link.outgoing[0].name},${link.outgoing[1].name}` + let newNode = { id: linkId, type: "circle" ,data: { label: `${link.type}, Links: ${link.outgoing.length}`, atomType: link.type }, position: { x: 100, y: 100 }}; + link.outgoing.forEach((linkNode, index:number )=> { + let newEdge = { id: `${index}${linkId}`, type: "colored", source: linkId, target: `${linkNode.name}`, atomType: link.type }; + newEdges.push(newEdge); + }) + newNodes.push(newNode); + }); + reactFlowInstance.setNodes(newNodes); + reactFlowInstance.setEdges(newEdges); + }, []); + + const sendMessage = (sendMessage: string) => { + var data = {msg: sendMessage} + setConsoleLines(state => [ ...state,"Sent: " + data.msg]) + console.log("Sent: " + data.msg) + setSendReadyState(false) + socket.emit('SendEvent',data); + } + + const getAtoms = ()=>{ + setCurCmdState(LastCommand.GET_ATOMS); + sendMessage('AtomSpace.getAtoms("Atom")'); + } + + const getLinks = ()=>{ + setCurCmdState(LastCommand.GET_LINKS); + sendMessage('AtomSpace.getAtoms("Link")'); + } + + const trimTrailJson = (res: string) => { + console.log(`trim "${res.substring(res.length-6)}"?`) + if(res.substring(res.length-6).includes("json")) { + return res.substring(0, res.length - 6) + } + else { + return res + } + } + + interface AtomBase { + type: string; + name?: string; + outgoing?: AtomBase[]; + } + interface AtomLink extends AtomBase{ + type: string; + outgoing: AtomBase[]; + } + + + useEffect(()=>{ + socket.on('connect', () => { + console.log("Connected") + setIsConnected(true); + setSendReadyState(true); + }); + + socket.on('disconnect', () => { + setIsConnected(false); + }); + // Move this outsite of useEffect + },[]); + + const edgeTypes = { + colored: CustomEdge, + }; + + useEffect(() => { + socket.removeListener('RecEvent'); + socket.on('RecEvent', function (ReceiveEvent) { + //console.log("Received: " + ReceiveEvent.msg) + setConsoleLines(state => [ ...state, "Rec: " + ReceiveEvent.msg]) + bottomRef.current?.scrollIntoView(); + setSendReadyState(true); + console.log(`Current Command: ${curCmdState}`); + switch(curCmdState){ + case LastCommand.GET_ATOMS: { + let trimmed = trimTrailJson(ReceiveEvent.msg) + console.log(trimmed); + let newAtoms: AtomBase[] = JSON.parse(trimmed) + setAtoms(newAtoms); + + // makeAtom(newAtom[0]); + setCurCmdState(LastCommand.NO_CMD); + break + } + case LastCommand.GET_LINKS: { + let trimmed = trimTrailJson(ReceiveEvent.msg) + console.log(trimmed); + + + // makeAtom(newAtom[0]); + setCurCmdState(LastCommand.NO_CMD); + break + } + } + }); + + }, [curCmdState]); + + return ( +
+
+ + + + + telnet output - Connected: {String(isConnected)} + + + + {consoleLines.map((row, index) => ( + + + {row} + + + ))} + + +
+ {'_'} + +
+ +
+
+ setInputtedMessage(e.target.value)} + style={{ width:"900px" }} + /> + +
+ + + +
+
+ + + +
+
+ ); } -function Flow() { - const [nodes, setNodes] = useState(initialNodes); - const [edges, setEdges] = useState(initialEdges); - - const onNodesChange = useCallback( - (changes: NodeChange[]) => setNodes((nds) => applyNodeChanges(changes, nds)), - [setNodes] - ); - const onEdgesChange = useCallback( - (changes: EdgeChange[]) => setEdges((eds) => applyEdgeChanges(changes, eds)), - [setEdges] - ); - const onConnect = useCallback( - (connection: Connection) => setEdges((eds) => addEdge(connection, eds)), - [setEdges] - ); - - return ( -
- - - -
- ) +function FlowWithProvider() { + return ( + + + + ); } -export default Flow +export default FlowWithProvider; \ No newline at end of file diff --git a/src/Edge.js b/src/Edge.js new file mode 100644 index 0000000..d92498d --- /dev/null +++ b/src/Edge.js @@ -0,0 +1,104 @@ +import React from 'react'; +import { getBezierPath, getMarkerEnd } from 'react-flow-renderer'; +import {TextNode} from "./Nodes"; + + +export default function CustomEdge ({ + id, + source, + target, + sourcePosition, + targetPosition, + style = {}, + data, + markerEnd, + }) { + const edgePath = getBezierPath({ + source, + sourcePosition, + target, + targetPosition, + }); + + return ( + <> + + + ); +} + +const getLinkSuperType = (typeName) => { + let superTypeName; + + switch(typeName) { + case "OrderedLink": + case "ListLink": + case "SetDifferenceLink": + case "MemberLink": + case "SubsetLink": + case "ContextLink": + case "TrueLink": + case "FalseLink": + case "SequentialAndLink": + case "SequentialOrLink": + case "ChoiceLink": + case "Section": + case "TagLink": + case "QuoteLink": + case "UnquoteLink": + case "LocalQuoteLink": + case "DontExecLink": + case "ReplacementLink": + case "FreeLink": + case "IntervalLink": + case "ImplicationLink": + case "InheritanceLink": + case "AssociativeLink": + case "ExecutionLink": + superTypeName = "OrderedLink"; + break; + case "UnorderedLink": + superTypeName = "UnorderedLink"; + break; + case "EvaluatableLink": + superTypeName = "EvaluatableLink"; + break; + case "NumericOutputLink": + superTypeName = "NumericOutputLink"; + break; + case "BooleanLink": + superTypeName = "BooleanLink"; + break; + case "NumericInputLink": + superTypeName = "NumericInputLink"; + break; + case "TypeInputLink": + superTypeName = "TypeInputLink"; + break; + case "TypeOutputLink": + superTypeName = "TypeOutputLink"; + break; + case "AlphaConvertibleLink": + superTypeName = "AlphaConvertibleLink"; + break; + case "CollectionLink": + superTypeName = "CollectionLink"; + break; + case "ForeignAst": + superTypeName = "ForeignAst"; + break; + case "DirectlyEvaluatableLink": + superTypeName = "DirectlyEvaluatableLink"; + break; + default: + superTypeName = "Unknown" + } + console.log(superTypeName + "Edge") + return superTypeName+"Edge"; +} \ No newline at end of file diff --git a/src/Nodes.js b/src/Nodes.tsx similarity index 89% rename from src/Nodes.js rename to src/Nodes.tsx index cdc8320..9eb8ca0 100644 --- a/src/Nodes.js +++ b/src/Nodes.tsx @@ -1,14 +1,14 @@ import React from "react"; -import { Handle } from "react-flow-renderer"; +import {Handle, Position} from "react-flow-renderer"; -const RectangleNode = ({ data }) => { +const RectangleNode = ({ data }: any) => { return ( -
+
@@ -16,13 +16,13 @@ const RectangleNode = ({ data }) => {
{data.info}
@@ -30,13 +30,12 @@ const RectangleNode = ({ data }) => { ); }; -const CircleNode = ({ data }) => { +const CircleNode = ({ data }: any) => { return ( -
@@ -44,7 +43,7 @@ const CircleNode = ({ data }) => {
@@ -52,7 +51,8 @@ const CircleNode = ({ data }) => { }; -export const TextNode = ({ data }) => { + +export const TextNode = ({ data }: any) => { return (
{data.label}
@@ -66,7 +66,7 @@ export const nodeTypes = { text: TextNode }; -const getNodeSuperType = (typeName) => { +const getNodeSuperType = (typeName: string) => { let superTypeName = "Node" switch(typeName) { @@ -124,7 +124,7 @@ const getNodeSuperType = (typeName) => { return superTypeName } -const getLinkSuperType = (typeName) => { +const getLinkSuperType = (typeName:string) => { let superTypeName = "Link"; switch(typeName) { @@ -190,6 +190,5 @@ const getLinkSuperType = (typeName) => { default: superTypeName = "Unknown" } - console.log("circle-node " + superTypeName) return "circle-node " + superTypeName; } diff --git a/src/SocketClient.tsx b/src/SocketClient.tsx deleted file mode 100644 index 59d36ce..0000000 --- a/src/SocketClient.tsx +++ /dev/null @@ -1,303 +0,0 @@ -import React, {useState, useEffect, useCallback, CSSProperties} from 'react'; -import io from 'socket.io-client'; -import Table from "@mui/material/Table"; -import TableHead from "@mui/material/TableHead"; -import TableRow from "@mui/material/TableRow"; -import TableCell from "@mui/material/TableCell"; -import TableBody from "@mui/material/TableBody"; -import TableContainer from "@mui/material/TableContainer"; -import {TableFooter} from "@mui/material"; -import ReactFlow, { - addEdge, - applyEdgeChanges, - applyNodeChanges, Connection, - Controls, - Edge, - EdgeChange, - FitViewOptions, - Node, - NodeChange, ReactFlowInstance, ReactFlowProvider, useReactFlow -} from "react-flow-renderer"; -import { getLayoutedElements } from "./Layout"; -import { nodeTypes } from "./Nodes"; -import "./nodeStyles.css" -import "./edgeStyles.css" - -const socket = io("http://localhost:4000"); - -export const SocketClient = ()=> { - const [isConnected, setIsConnected] = useState(socket.connected); - const [lastPong, setLastPong] = useState(null); - const [consoleLines, setConsoleLines] = useState([""]); - const [inputtedMessage, setInputtedMessage] = useState(''); - const [sendReadyState, setSendReadyState] = useState(false) - enum LastCommand { - NO_CMD = "no_cmd", - GET_ATOMS = "get_atoms", - PUT_ATOM = "put_atom", - ERROR = "error", - GET_NODES = "get_nodes", - GET_LINKS = "get_links" - } - const [curCmdState, setCurCmdState] = useState(LastCommand.NO_CMD) - let curCmd = LastCommand.NO_CMD - let nodeCount = 3; - const bottomRef = React.useRef(null); - - const initialNodes: Node[] = [ - ]; - - const initialEdges: Edge[] = [ - ]; - - const fitViewOptions: FitViewOptions = { - padding: 0.2 - } - - - const [nodes, setNodesState] = useState(initialNodes); - const [edges, setEdgesState] = useState(initialEdges); - - const setNodes = (nodes: Node[]) => { - const layoutedElements = getLayoutedElements(nodes, edges); - setNodesState(layoutedElements.nodes); - } - - const setEdges = (edges: Edge[]) => { - const layoutedElements = getLayoutedElements(nodes, edges); - setEdgesState(layoutedElements.edges); - } - const onNodesChange = useCallback( - (changes: NodeChange[]) => setNodes(applyNodeChanges(changes, nodes)), - [setNodes] - ); - const onEdgesChange = useCallback( - (changes: EdgeChange[]) => setEdges(applyEdgeChanges(changes, edges)), - [setEdges] - ); - const onConnect = useCallback( - (connection: Connection) => setEdges(addEdge(connection, edges)), - [setEdges] - ); - - const reactFlowInstance = useReactFlow(); - const makeNodes = useCallback(() => { - let newNode = { id: `${nodeCount}`, data: { label: `Node ${nodeCount}` }, position: { x: 100, y: 100 } }; - nodeCount++; - reactFlowInstance.addNodes(newNode) - }, []); - - const setAtoms = useCallback((atoms: AtomBase[]) => { - let linkAtoms = atoms.filter(atom => atom.type.includes("Link")) - let nodeAtoms = atoms.filter(atom => atom.type.includes("Node")) - let newNodes: Node[] = []; - let newEdges: Edge[] = []; - nodeAtoms.forEach((atom:AtomBase, index:number, array:AtomBase[])=>{ - let newNode = { id: `${atom.name}`, type: "rectangle", data: { label: `Name: ${atom.name}`, info: `Type: ${atom.type}`, atomType: atom.type }, position: { x: 100, y: 100 }}; - newNodes.push(newNode); - }); - (linkAtoms as AtomLink[]).forEach((link:AtomLink, index:number, array:AtomBase[])=>{ - let linkId = `${link.type}:${link.outgoing[0].name},${link.outgoing[1].name}` - let newNode = { id: linkId, type: "circle" ,data: { label: `${link.type}, Links: ${link.outgoing.length}`, atomType: link.type }, position: { x: 100, y: 100 }}; - link.outgoing.forEach((linkNode, index:number )=> { - let newEdge = { id: `${index}${linkId}`, source: linkId, target: `${linkNode.name}`, className: `${link.type}Edge` }; - newEdges.push(newEdge); - }) - newNodes.push(newNode); - }); - reactFlowInstance.setNodes(newNodes); - reactFlowInstance.setEdges(newEdges); - }, []); - - const setLinks = useCallback((atoms: AtomBase[]) => { - let newNodes: Node[] = []; - atoms.forEach((atom:AtomBase, index:number, array:AtomBase[])=>{ - let newNode = { id: `${index}`, type: "circle" ,data: { label: `Name: ${atom.name}, type: ${atom.type}` }, position: { x: 100, y: 100 }}; - newNodes.push(newNode); - }); - nodeCount++; - reactFlowInstance.setNodes(newNodes); - }, []); - - - const sendMessage = (sendMessage: string) => { - var data = {msg: sendMessage} - setConsoleLines(state => [ ...state,"Sent: " + data.msg]) - console.log("Sent: " + data.msg) - setSendReadyState(false) - socket.emit('SendEvent',data); - } - - const getAtoms = ()=>{ - setCurCmdState(LastCommand.GET_ATOMS); - sendMessage('AtomSpace.getAtoms("Atom")'); - } - - const getLinks = ()=>{ - setCurCmdState(LastCommand.GET_LINKS); - sendMessage('AtomSpace.getAtoms("Link")'); - } - - const trimTrailJson = (res: string) => { - console.log(`trim "${res.substring(res.length-6)}"?`) - if(res.substring(res.length-6).includes("json")) { - return res.substring(0, res.length - 6) - } - else { - return res - } - } - - interface AtomBase { - type: string; - name?: string; - outgoing?: AtomBase[]; - } - interface AtomLink extends AtomBase{ - type: string; - outgoing: AtomBase[]; - } - - - useEffect(()=>{ - socket.on('connect', () => { - console.log("Connected") - setIsConnected(true); - setSendReadyState(true); - }); - - socket.on('disconnect', () => { - setIsConnected(false); - }); - // Move this outsite of useEffect - },[]); - - useEffect(() => { - socket.removeListener('RecEvent'); - socket.on('RecEvent', function (ReceiveEvent) { - //console.log("Received: " + ReceiveEvent.msg) - setConsoleLines(state => [ ...state, "Rec: " + ReceiveEvent.msg]) - bottomRef.current?.scrollIntoView(); - setSendReadyState(true); - console.log(`Current Command: ${curCmdState}`); - switch(curCmdState){ - case LastCommand.GET_ATOMS: { - let trimmed = trimTrailJson(ReceiveEvent.msg) - console.log(trimmed); - let newAtoms: AtomBase[] = JSON.parse(trimmed) - setAtoms(newAtoms); - - // makeAtom(newAtom[0]); - setCurCmdState(LastCommand.NO_CMD); - break - } - case LastCommand.GET_LINKS: { - let trimmed = trimTrailJson(ReceiveEvent.msg) - console.log(trimmed); - - - // makeAtom(newAtom[0]); - setCurCmdState(LastCommand.NO_CMD); - break - } - } - }); - - }, [curCmdState]); - - return ( -
-
- - - - - telnet output - Connected: {String(isConnected)} - - - - {consoleLines.map((row, index) => ( - - - {row} - - - ))} - - -
- {'_'} - -
- -
-
- setInputtedMessage(e.target.value)} - style={{ width:"900px" }} - /> - -
- - - -
-
- - - -
-
- ); -} - -function FlowWithProvider() { - return ( - - - - ); -} - -export default FlowWithProvider; \ No newline at end of file diff --git a/src/edgeStyles.css b/src/edgeStyles.css index 361ce53..08c8f48 100644 --- a/src/edgeStyles.css +++ b/src/edgeStyles.css @@ -20,6 +20,6 @@ stroke: orange; } -.ListLink { +.ListLinkEdge { stroke: cyan; } diff --git a/src/index.tsx b/src/index.tsx index bbd6aa2..81a5a68 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -3,14 +3,14 @@ import ReactDOM from 'react-dom/client'; import './index.css'; import Flow from './App'; import reportWebVitals from './reportWebVitals'; -import SocketClient from "./SocketClient"; +import App from "./App"; const root = ReactDOM.createRoot( document.getElementById('root') as HTMLElement ); root.render( - + );