瀏覽代碼

Implement EdgeModal

hanbin9775 2 年之前
父節點
當前提交
fce4b0abb3

+ 24 - 5
src/components/Graph/index.tsx

@@ -11,8 +11,10 @@ import { PremiumView } from "./PremiumView";
 
 interface GraphProps {
   isWidget?: boolean;
-  openModal: () => void;
+  openNodeModal: () => void;
   setSelectedNode: (node: [string, string][]) => void;
+  openEdgeModal: () => void;
+  setSelectedEdge: (edgeInfo: string) => void;
 }
 
 const StyledEditorWrapper = styled.div<{ widget: boolean }>`
@@ -42,7 +44,13 @@ const StyledEditorWrapper = styled.div<{ widget: boolean }>`
   }
 `;
 
-const GraphComponent = ({ isWidget = false, openModal, setSelectedNode }: GraphProps) => {
+const GraphComponent = ({
+  isWidget = false,
+  openNodeModal,
+  setSelectedNode,
+  openEdgeModal,
+  setSelectedEdge,
+}: GraphProps) => {
   const isPremium = useUser(state => state.isPremium);
   const setLoading = useGraph(state => state.setLoading);
   const setZoomPanPinch = useGraph(state => state.setZoomPanPinch);
@@ -60,12 +68,21 @@ const GraphComponent = ({ isWidget = false, openModal, setSelectedNode }: GraphP
 
   const handleNodeClick = React.useCallback(
     (e: React.MouseEvent<SVGElement>, data: NodeData) => {
+      console.log(data);
       if (setSelectedNode) setSelectedNode(data.text);
-      if (openModal) openModal();
+      if (openNodeModal) openNodeModal();
     },
-    [openModal, setSelectedNode]
+    [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 onInit = React.useCallback(
     (ref: ReactZoomPanPinchRef) => {
       setZoomPanPinch(ref);
@@ -147,7 +164,9 @@ const GraphComponent = ({ isWidget = false, openModal, setSelectedNode }: GraphP
             fit={true}
             key={direction}
             node={props => <CustomNode {...props} onClick={handleNodeClick} />}
-            edge={props => <Edge {...props} containerClassName={`edge-${props.id}`} />}
+            edge={props => (
+              <Edge {...props} onClick={handleEdgeClick} containerClassName={`edge-${props.id}`} />
+            )}
           />
         </TransformComponent>
       </TransformWrapper>

+ 20 - 5
src/containers/Editor/LiveEditor/GraphCanvas.tsx

@@ -1,16 +1,20 @@
 import React from "react";
 import { Graph } from "src/components/Graph";
+import { EdgeModal } from "src/containers/Modals/EdgeModal";
 import { NodeModal } from "src/containers/Modals/NodeModal";
 import useGraph from "src/store/useGraph";
 
 export const GraphCanvas = ({ isWidget = false }: { isWidget?: boolean }) => {
-  const [isModalVisible, setModalVisible] = React.useState(false);
+  const [isNodeModalVisible, setNodeModalVisible] = React.useState(false);
   const [selectedNode, setSelectedNode] = React.useState<[string, string][]>([]);
+  const [isEdgeModalVisible, setEdgeModalVisible] = React.useState(false);
+  const [selectedEdge, setSelectedEdge] = React.useState("");
 
   const collapsedNodes = useGraph(state => state.collapsedNodes);
   const collapsedEdges = useGraph(state => state.collapsedEdges);
 
-  const openModal = React.useCallback(() => setModalVisible(true), []);
+  const openNodeModal = React.useCallback(() => setNodeModalVisible(true), []);
+  const openEdgeModal = React.useCallback(() => setEdgeModalVisible(true), []);
 
   React.useEffect(() => {
     const nodeList = collapsedNodes.map(id => `[id$="node-${id}"]`);
@@ -32,11 +36,22 @@ export const GraphCanvas = ({ isWidget = false }: { isWidget?: boolean }) => {
 
   return (
     <>
-      <Graph openModal={openModal} setSelectedNode={setSelectedNode} isWidget={isWidget} />
+      <Graph
+        openNodeModal={openNodeModal}
+        setSelectedNode={setSelectedNode}
+        openEdgeModal={openEdgeModal}
+        setSelectedEdge={setSelectedEdge}
+        isWidget={isWidget}
+      />
       <NodeModal
         selectedNode={selectedNode}
-        visible={isModalVisible}
-        closeModal={() => setModalVisible(false)}
+        visible={isNodeModalVisible}
+        closeModal={() => setNodeModalVisible(false)}
+      />
+      <EdgeModal
+        selectedEdge={selectedEdge}
+        visible={isEdgeModalVisible}
+        closeModal={() => setEdgeModalVisible(false)}
       />
     </>
   );

+ 48 - 0
src/containers/Modals/EdgeModal/index.tsx

@@ -0,0 +1,48 @@
+import React from "react";
+import toast from "react-hot-toast";
+import { FiCopy } from "react-icons/fi";
+import { Button } from "src/components/Button";
+import { Modal } from "src/components/Modal";
+import styled from "styled-components";
+
+interface EdgeModalProps {
+  selectedEdge: string;
+  visible: boolean;
+  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 handleClipboard = () => {
+    toast.success("Content copied to clipboard!");
+    navigator.clipboard.writeText(selectedEdge);
+    closeModal();
+  };
+
+  return (
+    <Modal visible={visible} setVisible={closeModal}>
+      <Modal.Header>Edge Content</Modal.Header>
+      <Modal.Content>
+        <StyledTextarea defaultValue={selectedEdge} readOnly />
+      </Modal.Content>
+      <Modal.Controls setVisible={closeModal}>
+        <Button status="SECONDARY" onClick={handleClipboard}>
+          <FiCopy size={18} /> Clipboard
+        </Button>
+      </Modal.Controls>
+    </Modal>
+  );
+};