From 1b922beee346adc312288ae5b34e36bf456f06ae Mon Sep 17 00:00:00 2001 From: tessjaworski Date: Thu, 13 Nov 2025 21:04:46 -0500 Subject: [PATCH] added edit feature --- .../editor/views/GraphView/stores/useGraph.ts | 40 +++++++++ src/features/modals/NodeModal/index.tsx | 86 +++++++++++++++---- 2 files changed, 107 insertions(+), 19 deletions(-) diff --git a/src/features/editor/views/GraphView/stores/useGraph.ts b/src/features/editor/views/GraphView/stores/useGraph.ts index 6e067c3c2a7..267325bc10f 100644 --- a/src/features/editor/views/GraphView/stores/useGraph.ts +++ b/src/features/editor/views/GraphView/stores/useGraph.ts @@ -101,6 +101,46 @@ const useGraph = create((set, get) => ({ }, toggleFullscreen: fullscreen => set({ fullscreen }), setViewPort: viewPort => set({ viewPort }), + + updateNodeValue: (id, newValue) => + set(state => { + const updatedNodes = state.nodes.map(node => { + if (node.id !== id) return node; + + // Update only the text value + const newText = [...node.text]; + if (newText[0]) newText[0].value = newValue; + + return { ...node, text: newText }; + }); + + return { + ...state, + nodes: updatedNodes, + selectedNode: updatedNodes.find(n => n.id === state.selectedNode?.id), + }; + }), + updateNodeFields: (id, newFields) => + set(state => { + const updatedNodes = state.nodes.map(node => { + if (node.id !== id) return node; + + const newText = node.text.map(row => { + if (row.key && newFields[row.key] !== undefined) { + return { ...row, value: newFields[row.key] }; + } + return row; + }); + + return { ...node, text: newText }; + }); + + return { + ...state, + nodes: updatedNodes, + selectedNode: updatedNodes.find(n => n.id === state.selectedNode?.id), + }; + }), })); export default useGraph; diff --git a/src/features/modals/NodeModal/index.tsx b/src/features/modals/NodeModal/index.tsx index caba85febac..5bb02c9f223 100644 --- a/src/features/modals/NodeModal/index.tsx +++ b/src/features/modals/NodeModal/index.tsx @@ -1,6 +1,6 @@ -import React from "react"; +import React, { useState } 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, Textarea } from "@mantine/core"; import { CodeHighlight } from "@mantine/code-highlight"; import type { NodeData } from "../../../types/graph"; import useGraph from "../../editor/views/GraphView/stores/useGraph"; @@ -28,38 +28,86 @@ const jsonPathToString = (path?: NodeData["path"]) => { export const NodeModal = ({ opened, onClose }: ModalProps) => { const nodeData = useGraph(state => state.selectedNode); + const updateNodeFields = useGraph(state => state.updateNodeFields); + + const [isEditing, setIsEditing] = useState(false); + const [draft, setDraft] = useState(""); + + // load initial content when entering edit mode + const startEdit = () => { + setDraft(normalizeNodeData(nodeData?.text ?? [])); + setIsEditing(true); + }; + + const handleSave = () => { + try { + const parsed = JSON.parse(draft); + updateNodeFields(nodeData!.id, parsed); + setIsEditing(false); + } catch (err) { + alert("Invalid JSON"); + } + }; + + const handleCancel = () => { + setIsEditing(false); + }; return ( - - Content - + Content - - - + + {!isEditing && ( + <> + + + + + + )} + + {isEditing && ( + <> +