From 8531e1b58d33a449c638e3d0a3e55ec3706dc046 Mon Sep 17 00:00:00 2001 From: Cristhian Zanforlin Lousa Date: Wed, 5 Feb 2025 11:02:57 -0300 Subject: [PATCH] feat: Update node name and description UX editing (#5920) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ✨ (NodeName/index.tsx): add cursor-grab class to improve user experience when dragging the node ✨ (NodeName/index.tsx): add nodrag class to prevent text selection when dragging the node ✨ (NodeStatus/index.tsx): add nodrag class to prevent text selection when dragging the node ✨ (GenericNode/index.tsx): add nopan, nodelete, nodrag, noflow classes to improve node dragging behavior * 📝 (NodeDescription/index.tsx): Update cursor style to 'auto' for better user experience 📝 (NodeName/index.tsx): Update cursor style to 'auto' for better user experience 📝 (NodeOutputfield/index.tsx): Add cursor style 'pointer' to improve interactivity * ✨ (NodeDescription/index.tsx): Add support for editing node description when selected and editNameDescription is true ✨ (NodeName/index.tsx): Add support for editing node name when selected and editNameDescription is true 🔧 (GenericNode/index.tsx): Introduce useAlternate hook to handle toggling editNameDescription state 📝 (use-alternate.tsx): Add custom hook useAlternate to handle toggling boolean state 🔧 (style/index.css): Add new CSS variable --zinc-foreground for styling purposes 🔧 (tailwind.config.mjs): Add new tailwind color variable "zinc-foreground" for styling purposes * 📝 (NodeDescription/index.tsx): Remove unnecessary setInputDescription call and update useEffect dependencies for better performance 📝 (NodeDescription/index.tsx): Update className for Textarea component to improve styling and readability 📝 (NodeDescription/index.tsx): Update className for generic-node-desc-text to improve styling and cursor behavior 📝 (NodeName/index.tsx): Remove unnecessary setInputName call and update useEffect dependencies for better performance 📝 (NodeName/index.tsx): Update className for span element to improve cursor behavior and styling 📝 (GenericNode/index.tsx): Add useRef for node element and implement useChangeOnUnfocus hook for better handling of focus events 📝 (GenericNode/index.tsx): Update className for pencil icon based on editNameDescription state for better visual feedback 📝 (GenericNode/index.tsx): Add editNameDescription to dependencies of useCallback to prevent unnecessary re-renders 📝 (GenericNode/index.tsx): Add editNameDescription to dependencies of useEffect to handle changes in editNameDescription state 📝 (use-change-on-unfocus.tsx): Implement custom hook useChangeOnUnfocus for handling focus events and state changes * Refactor NodeDescription to remove old logic and variables * Refactor NodeName component to remove unnecessary logic and variables * [autofix.ci] apply automated fixes * ✨ (NodeDescription/index.tsx): Add functionality to edit node description and handle events like blur, key down, and double click for sticky notes 📝 (NoteNode/index.tsx): Introduce useAlternate hook to toggle edit mode for node description in NoteNode component * ♻️ (NoteNode/index.tsx): refactor useAlternate hook usage to simplify code and improve readability * 🔧 (GenericNode/index.tsx): refactor className to conditionally apply translate-x styles based on showNode state for improved UI responsiveness * 📝 (NodeDescription/index.tsx): Refactor handleBlurFn and handleKeyDownFn to improve code readability and maintainability 📝 (NodeName/index.tsx): Refactor handleBlur and handleKeyDown functions for better code organization and readability 📝 (GenericNode/index.tsx): Update toggleEditNameDescription prop to setEditNameDescription for consistency and clarity 📝 (use-change-on-unfocus.tsx): Remove unnecessary handleEscape function and handleBlur event listener for better code simplicity and performance * 📝 (NodeDescription/index.tsx): Update CSS class name to use 'focus-border-primary' instead of 'focus-border-black' for consistency and clarity 📝 (GenericNode/index.tsx): Add data-testid attribute to save and edit name description buttons for testing purposes 📝 (edit-name-description-node.spec.ts): Add test to verify user can edit name and description of a node in the UI * ✨ (GenericNode/index.tsx): Add functionality to show and hide toolbar with animation based on node selection status 📝 (get-class-toolbar-transform.ts): Create helper function to determine transform classes for toolbar animation based on showToolbar and showNode status * ✨ (NodeDescription/index.tsx): add setHasChangedNodeDescription prop to update parent component when node description changes ✨ (NodeName/index.tsx): add setHasChangedNodeDescription prop to update parent component when node name changes ✨ (GenericNode/index.tsx): add hasChangedNodeDescription state and setHasChangedNodeDescription function to track changes in node description and update parent component 📝 (edit-name-description-node.spec.ts): add wait for sidebar custom component button and timeout to improve test reliability * ✨ (group.spec.ts): Update click event on "title-Group" element to improve user interaction 🐛 (group.spec.ts): Fix click event on "save-name-description-button" element to properly save changes 🐛 (general-bugs-save-changes-on-node.spec.ts): Increase timeout for selectors to prevent test failures due to slow loading 🐛 (general-bugs-save-changes-on-node.spec.ts): Fix random value generation to ensure consistent length 🐛 (general-bugs-save-changes-on-node.spec.ts): Fix click event on "add-component-button-text-output" element to add component correctly 🐛 (general-bugs-save-changes-on-node.spec.ts): Fix timeout for selector to prevent test failures due to slow loading 🐛 (general-bugs-save-changes-on-node.spec.ts): Fix verifyTextareaValue function to properly verify textarea values --------- Co-authored-by: anovazzi1 Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --- .../components/NodeDescription/index.tsx | 126 ++++++++++------ .../GenericNode/components/NodeName/index.tsx | 86 ++++++----- .../components/NodeOutputfield/index.tsx | 1 + .../components/NodeStatus/index.tsx | 2 +- .../src/CustomNodes/GenericNode/index.tsx | 142 ++++++++++++++---- .../src/CustomNodes/NoteNode/index.tsx | 6 + .../helpers/get-class-toolbar-transform.ts | 6 + .../src/shared/hooks/use-alternate.tsx | 14 ++ .../shared/hooks/use-change-on-unfocus.tsx | 49 ++++++ src/frontend/src/style/index.css | 4 + src/frontend/tailwind.config.mjs | 1 + .../tests/core/features/group.spec.ts | 5 +- .../edit-name-description-node.spec.ts | 113 ++++++++++++++ .../general-bugs-save-changes-on-node.spec.ts | 37 +++-- 14 files changed, 465 insertions(+), 127 deletions(-) create mode 100644 src/frontend/src/CustomNodes/helpers/get-class-toolbar-transform.ts create mode 100644 src/frontend/src/shared/hooks/use-alternate.tsx create mode 100644 src/frontend/src/shared/hooks/use-change-on-unfocus.tsx create mode 100644 src/frontend/tests/extended/features/edit-name-description-node.spec.ts diff --git a/src/frontend/src/CustomNodes/GenericNode/components/NodeDescription/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/NodeDescription/index.tsx index 271bfac55..f43d4b9bc 100644 --- a/src/frontend/src/CustomNodes/GenericNode/components/NodeDescription/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/components/NodeDescription/index.tsx @@ -16,6 +16,10 @@ export default function NodeDescription({ inputClassName, mdClassName, style, + editNameDescription, + setEditNameDescription, + stickyNote, + setHasChangedNodeDescription, }: { description?: string; selected?: boolean; @@ -26,8 +30,11 @@ export default function NodeDescription({ inputClassName?: string; mdClassName?: string; style?: React.CSSProperties; + editNameDescription: boolean; + setEditNameDescription?: (value: boolean) => void; + stickyNote?: boolean; + setHasChangedNodeDescription?: (value: boolean) => void; }) { - const [inputDescription, setInputDescription] = useState(false); const [nodeDescription, setNodeDescription] = useState( description ?? "", ); @@ -36,6 +43,12 @@ export default function NodeDescription({ const overflowRef = useRef(null); const [hasScroll, sethasScroll] = useState(false); + useEffect(() => { + if (selected && editNameDescription) { + takeSnapshot(); + } + }, [editNameDescription]); + useEffect(() => { //timeout to wait for the dom to update setTimeout(() => { @@ -49,13 +62,7 @@ export default function NodeDescription({ } } }, 200); - }, [inputDescription]); - - useEffect(() => { - if (!selected) { - setInputDescription(false); - } - }, [selected]); + }, [editNameDescription]); useEffect(() => { setNodeDescription(description ?? ""); @@ -80,55 +87,81 @@ export default function NodeDescription({ [description, emptyPlaceholder, mdClassName], ); + const handleBlurFn = () => { + setNodeDescription(nodeDescription); + setNode(nodeId, (old) => ({ + ...old, + data: { + ...old.data, + node: { + ...old.data.node, + description: nodeDescription, + }, + }, + })); + if (stickyNote) { + setEditNameDescription?.(false); + } + }; + + const handleKeyDownFn = (e: React.KeyboardEvent) => { + handleKeyDown(e, nodeDescription, ""); + + if (e.key === "Escape") { + setEditNameDescription?.(false); + setNodeDescription(description ?? ""); + + if (stickyNote) { + setNodeDescription(nodeDescription); + setNode(nodeId, (old) => ({ + ...old, + data: { + ...old.data, + node: { + ...old.data.node, + description: nodeDescription, + }, + }, + })); + } + } + }; + + const handleDoubleClickFn = () => { + if (stickyNote) { + setEditNameDescription?.(true); + takeSnapshot(); + } + }; + + const onChange = (e: React.ChangeEvent) => { + setHasChangedNodeDescription?.(true); + setNodeDescription(e.target.value); + }; + return (
- {inputDescription ? ( + {editNameDescription ? ( <>