Jelajahi Sumber

feat: function that returns information of edge

hanbin9775 2 tahun lalu
induk
melakukan
de667d05fc
2 mengubah file dengan 81 tambahan dan 24 penghapusan
  1. 58 8
      src/components/Graph/index.tsx
  2. 23 16
      src/containers/Modals/EdgeModal/index.tsx

+ 58 - 8
src/components/Graph/index.tsx

@@ -68,20 +68,70 @@ const GraphComponent = ({
 
   const handleNodeClick = React.useCallback(
     (e: React.MouseEvent<SVGElement>, data: NodeData) => {
-      console.log(data);
       if (setSelectedNode) setSelectedNode(data.text);
       if (openNodeModal) openNodeModal();
     },
     [openNodeModal, setSelectedNode]
   );
 
-  const handleEdgeClick = React.useCallback((e: React.MouseEvent<SVGElement>, data: EdgeData) => {
-    const fromIndex = Number(data.from) - 1;
-    const toIndex = Number(data.to) - 1;
-    console.log(`${fromIndex}-${toIndex}`);
-    if (setSelectedEdge) setSelectedEdge(`${fromIndex}-${toIndex}`);
-    if (openEdgeModal) openEdgeModal();
-  }, []);
+  const handleEdgeClick = React.useCallback(
+    (e: React.MouseEvent<SVGElement>, data: EdgeData) => {
+      let curFromId = data.from;
+      let curToId = data.to;
+      const path = [curFromId, curToId];
+      while (curFromId !== "1") {
+        curToId = curFromId;
+        curFromId = edges.find(({ to }) => to === curFromId)?.from;
+        if (curFromId === undefined) {
+          break;
+        }
+        path.unshift(curFromId);
+      }
+      const rootArrayElementIds = ["1"];
+      const edgeLength = edges.length;
+      for (let i = 1; i < edgeLength; i++) {
+        const curNodeId = edges[i].from!;
+        if (rootArrayElementIds.find(id => id === curNodeId)) continue;
+        let isRootArrayElement = true;
+        for (let j = i - 1; j >= 0; j--) {
+          if (curNodeId === edges[j]?.to) {
+            isRootArrayElement = false;
+          }
+        }
+        if (isRootArrayElement) {
+          rootArrayElementIds.push(curNodeId);
+        }
+      }
+      const pathLength = path.length;
+      let resolvedPath = "";
+      if (rootArrayElementIds.length > 1) {
+        resolvedPath += `Root[${rootArrayElementIds.findIndex(id => id === path[0])}]`;
+      } else {
+        resolvedPath += "{Root}";
+      }
+      for (let i = 1; i < pathLength; i++) {
+        const curId = path[i];
+        if (curId === undefined) break;
+        const curNode = nodes[+curId - 1];
+        if (curNode?.data.parent === "array") {
+          resolvedPath += `.${curNode.text}`;
+          if (i !== pathLength - 1) {
+            const idx = edges
+              .filter(({ from }) => from === curId)
+              .findIndex(({ to }) => to === path[i + 1]);
+            resolvedPath += `[${idx}]`;
+          }
+        }
+        if (curNode?.data.parent === "object") {
+          resolvedPath += `.${curNode.text}`;
+        }
+      }
+
+      if (setSelectedEdge) setSelectedEdge(resolvedPath);
+      if (openEdgeModal) openEdgeModal();
+    },
+    [nodes, edges]
+  );
 
   const onInit = React.useCallback(
     (ref: ReactZoomPanPinchRef) => {

+ 23 - 16
src/containers/Modals/EdgeModal/index.tsx

@@ -1,9 +1,19 @@
 import React from "react";
+import dynamic from "next/dynamic";
 import toast from "react-hot-toast";
 import { FiCopy } from "react-icons/fi";
+import { vscDarkPlus } from "react-syntax-highlighter/dist/cjs/styles/prism";
+import { vs } from "react-syntax-highlighter/dist/cjs/styles/prism";
 import { Button } from "src/components/Button";
 import { Modal } from "src/components/Modal";
-import styled from "styled-components";
+import useStored from "src/store/useStored";
+
+const SyntaxHighlighter = dynamic(
+  () => import("react-syntax-highlighter/dist/esm/prism-async").then(c => c),
+  {
+    ssr: false,
+  }
+);
 
 interface EdgeModalProps {
   selectedEdge: string;
@@ -11,21 +21,8 @@ interface EdgeModalProps {
   closeModal: () => void;
 }
 
-const StyledTextarea = styled.textarea`
-  resize: none;
-  width: 100%;
-  min-height: 200px;
-
-  padding: 10px;
-  background: ${({ theme }) => theme.BACKGROUND_TERTIARY};
-  color: ${({ theme }) => theme.INTERACTIVE_NORMAL};
-  outline: none;
-  border-radius: 4px;
-  line-height: 20px;
-  border: none;
-`;
-
 export const EdgeModal = ({ selectedEdge, visible, closeModal }: EdgeModalProps) => {
+  const lightmode = useStored(state => state.lightmode);
   const handleClipboard = () => {
     toast.success("Content copied to clipboard!");
     navigator.clipboard.writeText(selectedEdge);
@@ -36,7 +33,17 @@ export const EdgeModal = ({ selectedEdge, visible, closeModal }: EdgeModalProps)
     <Modal visible={visible} setVisible={closeModal}>
       <Modal.Header>Edge Content</Modal.Header>
       <Modal.Content>
-        <StyledTextarea defaultValue={selectedEdge} readOnly />
+        <SyntaxHighlighter
+          style={lightmode ? vs : vscDarkPlus}
+          customStyle={{
+            borderRadius: "4px",
+            fontSize: "14px",
+            margin: "0",
+          }}
+          language="javascript"
+        >
+          {selectedEdge}
+        </SyntaxHighlighter>
       </Modal.Content>
       <Modal.Controls setVisible={closeModal}>
         <Button status="SECONDARY" onClick={handleClipboard}>