diff --git a/src/components/CustomNode/ObjectNode.tsx b/src/components/CustomNode/ObjectNode.tsx index 2ae9971..ba6840b 100644 --- a/src/components/CustomNode/ObjectNode.tsx +++ b/src/components/CustomNode/ObjectNode.tsx @@ -20,15 +20,15 @@ const ObjectNode: React.FC> = ({ (val, idx) => val[1] && ( - {val[0]}: - {val[1]} + {JSON.stringify(val[0]).replaceAll('"', "")}: + {JSON.stringify(val[1])} ) )} diff --git a/src/components/CustomNode/TextNode.tsx b/src/components/CustomNode/TextNode.tsx index 8bf0397..328fa4d 100644 --- a/src/components/CustomNode/TextNode.tsx +++ b/src/components/CustomNode/TextNode.tsx @@ -20,10 +20,10 @@ const TextNode: React.FC> = ({ - {value} + {JSON.stringify(value).replaceAll('"', "")} diff --git a/src/components/Graph/index.tsx b/src/components/Graph/index.tsx index 860b736..bc51c1d 100644 --- a/src/components/Graph/index.tsx +++ b/src/components/Graph/index.tsx @@ -13,11 +13,11 @@ import { NodeProps, } from "reaflow"; import { CustomNode } from "src/components/CustomNode"; +import { NodeModal } from "src/containers/Modals/NodeModal"; import { getEdgeNodes } from "src/containers/Editor/LiveEditor/helpers"; import useConfig from "src/hooks/store/useConfig"; import styled from "styled-components"; import shallow from "zustand/shallow"; -import toast from "react-hot-toast"; interface GraphProps { json: string; @@ -48,6 +48,7 @@ export const Graph: React.FC = ({ isWidget = false, ...props }) => { + const [isModalVisible, setModalVisible] = React.useState(false); const updateSetting = useConfig((state) => state.updateSetting); const [expand, layout] = useConfig( (state) => [state.settings.expand, state.settings.layout], @@ -58,6 +59,7 @@ export const Graph: React.FC = ({ updateSetting("zoomPanPinch", ref); }; + const [selectedNode, setSelectedNode] = React.useState(null); const [nodes, setNodes] = React.useState([]); const [edges, setEdges] = React.useState([]); const [size, setSize] = React.useState({ @@ -86,49 +88,56 @@ export const Graph: React.FC = ({ e: React.MouseEvent, props: NodeProps ) => { - if (e.detail === 2) { - toast("Object copied to clipboard!"); - navigator.clipboard.writeText(JSON.stringify(props.properties.text)); - } + setSelectedNode(props.properties); + setModalVisible(true); }; return ( - - - + + - ( - handleNodeClick(e, props)} - {...props} - /> - )} - zoomable={false} - readonly - {...props} - /> - - - + + ( + handleNodeClick(e, props)} + {...props} + /> + )} + zoomable={false} + readonly + {...props} + /> + + + + {!isWidget && selectedNode && ( + + )} + ); }; diff --git a/src/containers/Editor/LiveEditor/helpers.ts b/src/containers/Editor/LiveEditor/helpers.ts index a37a258..ee93b59 100644 --- a/src/containers/Editor/LiveEditor/helpers.ts +++ b/src/containers/Editor/LiveEditor/helpers.ts @@ -1,22 +1,6 @@ import { CanvasDirection, NodeData, EdgeData } from "reaflow"; import { parser } from "src/utils/json-editor-parser"; -const toString = (value: string | object) => { - const isObject = value instanceof Object; - - if (isObject) { - const entries = Object.entries(value); - const stringObj = entries.map((val) => [ - JSON.stringify(val[0]).replaceAll('"', ""), - JSON.stringify(val[1]), - ]); - - return Object.fromEntries(stringObj); - } - - return String(value); -}; - export function getEdgeNodes( graph: string, isExpanded: boolean = true @@ -44,7 +28,7 @@ export function getEdgeNodes( nodes.push({ id: el.id, - text: toString(el.text), + text: el.text, data: { isParent: el.parent, }, diff --git a/src/containers/Modals/NodeModal/index.tsx b/src/containers/Modals/NodeModal/index.tsx new file mode 100644 index 0000000..2250fe2 --- /dev/null +++ b/src/containers/Modals/NodeModal/index.tsx @@ -0,0 +1,52 @@ +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"; + +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 NodeModal = ({ selectedNode, visible = true, setVisible }) => { + const handleClipboard = () => { + toast("Content copied to clipboard!"); + navigator.clipboard.writeText(JSON.stringify(selectedNode)); + setVisible(false); + }; + + + return ( + + Node Content + + { + if (typeof v === "string") return v.replaceAll('"', ""); + return v; + }, + 2 + )} + /> + + + + + + ); +};