diff --git a/src/features/modals/EditNodeModal/index.tsx b/src/features/modals/EditNodeModal/index.tsx new file mode 100644 index 00000000000..c27a6264175 --- /dev/null +++ b/src/features/modals/EditNodeModal/index.tsx @@ -0,0 +1,122 @@ +import React from "react"; +import type { ModalProps } from "@mantine/core"; +import { Modal, Stack, Text, TextInput, Group, Button, CloseButton, Flex, ScrollArea } from "@mantine/core"; +import { useModal } from "../../../store/useModal"; +import { CodeHighlight } from "@mantine/code-highlight"; +import type { NodeData } from "../../../types/graph"; +import useGraph from "../../editor/views/GraphView/stores/useGraph"; +import useJson from "../../../store/useJson"; + +export const EditNodeModal = ({ opened, onClose }: ModalProps) => { + const nodeData = useGraph(state => state.selectedNode); + const setVisible = useModal(state => state.setVisible); + const [editedValues, setEditedValues] = React.useState>({}); + const json = useJson(state => state.getJson()); + const setJson = useJson(state => state.setJson); + + React.useEffect(() => { + if (nodeData?.text) { + const values: Record = {}; + nodeData.text.forEach(row => { + if (row.key && row.type !== "object" && row.type !== "array") { + values[row.key] = row.value ?? ""; + } + }); + setEditedValues(values); + } else { + setEditedValues({}); + } + }, [nodeData]); + + const handleSave = React.useCallback(() => { + if (!nodeData?.path) return; + + try { + const data = JSON.parse(json); + let current: any = data; + + // Navigate to the target object using the path + for (let i = 0; i < nodeData.path!.length; i++) { + current = current[nodeData.path![i]]; + } + + // Update the values + Object.entries(editedValues).forEach(([key, value]) => { + current[key] = value; + }); + + const updatedJson = JSON.stringify(data, null, 2); + setJson(updatedJson); + onClose(); + } catch (error) { + console.error("Error updating node:", error); + } + }, [nodeData, editedValues, json, setJson, onClose]); + + const jsonPathToString = (path?: NodeData["path"]) => { + if (!path || path.length === 0) return "$"; + const segments = path.map(seg => (typeof seg === "number" ? seg : `"${seg}"`)); + return `$[${segments.join("][")}]`; + }; + + return ( + + + + + Content + + + + + + + + + + + {nodeData?.text + .filter(row => row.key && row.type !== "object" && row.type !== "array") + .map((row, index) => ( +
+ + {row.key} + + + setEditedValues(prev => ({ + ...prev, + [row.key!]: e.currentTarget.value, + })) + } + size="sm" + /> +
+ ))} +
+ + + JSON Path + + + + + +
+
+ ); +}; diff --git a/src/features/modals/NodeModal/index.tsx b/src/features/modals/NodeModal/index.tsx index caba85febac..254e5e19077 100644 --- a/src/features/modals/NodeModal/index.tsx +++ b/src/features/modals/NodeModal/index.tsx @@ -1,9 +1,10 @@ import React from "react"; import type { ModalProps } from "@mantine/core"; -import { Modal, Stack, Text, ScrollArea, Flex, CloseButton } from "@mantine/core"; +import { Modal, Stack, Text, ScrollArea, Flex, CloseButton, Button, Group } from "@mantine/core"; import { CodeHighlight } from "@mantine/code-highlight"; import type { NodeData } from "../../../types/graph"; import useGraph from "../../editor/views/GraphView/stores/useGraph"; +import { useModal } from "../../../store/useModal"; // return object from json removing array and object fields const normalizeNodeData = (nodeRows: NodeData["text"]) => { @@ -28,6 +29,7 @@ const jsonPathToString = (path?: NodeData["path"]) => { export const NodeModal = ({ opened, onClose }: ModalProps) => { const nodeData = useGraph(state => state.selectedNode); + const setVisible = useModal(state => state.setVisible); return ( @@ -37,7 +39,12 @@ export const NodeModal = ({ opened, onClose }: ModalProps) => { Content - + + + +