mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-04-08 03:00:28 -04:00
Feat(Builder): Make the copy block button work (#7920)
* Feat(Builder): Make the copy block button work * prettier * Fixes * fix block id * prettier * fix type
This commit is contained in:
@@ -50,6 +50,7 @@
|
||||
"react-shepherd": "^6.1.1",
|
||||
"tailwind-merge": "^2.3.0",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"uuid": "^10.0.0",
|
||||
"zod": "^3.23.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -56,7 +56,7 @@ export type CustomNodeData = {
|
||||
|
||||
export type CustomNode = Node<CustomNodeData, "custom">;
|
||||
|
||||
export function CustomNode({ data, id }: NodeProps<CustomNode>) {
|
||||
export function CustomNode({ data, id, width, height }: NodeProps<CustomNode>) {
|
||||
const [isOutputOpen, setIsOutputOpen] = useState(data.isOutputOpen || false);
|
||||
const [isAdvancedOpen, setIsAdvancedOpen] = useState(false);
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
@@ -64,7 +64,10 @@ export function CustomNode({ data, id }: NodeProps<CustomNode>) {
|
||||
const [modalValue, setModalValue] = useState<string>("");
|
||||
const [isOutputModalOpen, setIsOutputModalOpen] = useState(false);
|
||||
const [isHovered, setIsHovered] = useState(false);
|
||||
const { updateNodeData, deleteElements } = useReactFlow<CustomNode, Edge>();
|
||||
const { updateNodeData, deleteElements, addNodes, getNode } = useReactFlow<
|
||||
CustomNode,
|
||||
Edge
|
||||
>();
|
||||
const isInitialSetup = useRef(true);
|
||||
const flowContext = useContext(FlowContext);
|
||||
|
||||
@@ -72,7 +75,7 @@ export function CustomNode({ data, id }: NodeProps<CustomNode>) {
|
||||
throw new Error("FlowContext consumer must be inside FlowEditor component");
|
||||
}
|
||||
|
||||
const { setIsAnyModalOpen } = flowContext;
|
||||
const { setIsAnyModalOpen, getNextNodeId } = flowContext;
|
||||
|
||||
useEffect(() => {
|
||||
if (data.output_data || data.status) {
|
||||
@@ -281,10 +284,41 @@ export function CustomNode({ data, id }: NodeProps<CustomNode>) {
|
||||
}, [id, deleteElements]);
|
||||
|
||||
const copyNode = useCallback(() => {
|
||||
// This is a placeholder function. The actual copy functionality
|
||||
// will be implemented by another team member.
|
||||
console.log("Copy node:", id);
|
||||
}, [id]);
|
||||
const newId = getNextNodeId();
|
||||
const currentNode = getNode(id);
|
||||
|
||||
if (!currentNode) {
|
||||
console.error("Cannot copy node: current node not found");
|
||||
return;
|
||||
}
|
||||
|
||||
const verticalOffset = height ?? 100;
|
||||
|
||||
const newNode: CustomNode = {
|
||||
id: newId,
|
||||
type: currentNode.type,
|
||||
position: {
|
||||
x: currentNode.position.x,
|
||||
y: currentNode.position.y - verticalOffset - 20,
|
||||
},
|
||||
data: {
|
||||
...data,
|
||||
title: `${data.title} (Copy)`,
|
||||
block_id: data.block_id,
|
||||
connections: [],
|
||||
isOutputOpen: false,
|
||||
},
|
||||
};
|
||||
|
||||
addNodes(newNode);
|
||||
|
||||
history.push({
|
||||
type: "ADD_NODE",
|
||||
payload: { node: newNode },
|
||||
undo: () => deleteElements({ nodes: [{ id: newId }] }),
|
||||
redo: () => addNodes(newNode),
|
||||
});
|
||||
}, [id, data, height, addNodes, deleteElements, getNode, getNextNodeId]);
|
||||
|
||||
return (
|
||||
<div
|
||||
|
||||
@@ -37,6 +37,7 @@ import { BlocksControl } from "@/components/edit/control/BlocksControl";
|
||||
import { IconPlay, IconRedo2, IconUndo2 } from "@/components/ui/icons";
|
||||
import { startTutorial } from "./tutorial";
|
||||
import useAgentGraph from "@/hooks/useAgentGraph";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
|
||||
// This is for the history, this is the minimum distance a block must move before it is logged
|
||||
// It helps to prevent spamming the history with small movements especially when pressing on a input in a block
|
||||
@@ -45,6 +46,7 @@ const MINIMUM_MOVE_BEFORE_LOG = 50;
|
||||
type FlowContextType = {
|
||||
visualizeBeads: "no" | "static" | "animate";
|
||||
setIsAnyModalOpen: (isOpen: boolean) => void;
|
||||
getNextNodeId: () => string;
|
||||
};
|
||||
|
||||
export const FlowContext = createContext<FlowContextType | null>(null);
|
||||
@@ -347,6 +349,10 @@ const FlowEditor: React.FC<{
|
||||
[setNodes, clearNodesStatusAndOutput],
|
||||
);
|
||||
|
||||
const getNextNodeId = useCallback(() => {
|
||||
return uuidv4();
|
||||
}, []);
|
||||
|
||||
const { x, y, zoom } = useViewport();
|
||||
|
||||
const addNode = useCallback(
|
||||
@@ -519,7 +525,9 @@ const FlowEditor: React.FC<{
|
||||
];
|
||||
|
||||
return (
|
||||
<FlowContext.Provider value={{ visualizeBeads, setIsAnyModalOpen }}>
|
||||
<FlowContext.Provider
|
||||
value={{ visualizeBeads, setIsAnyModalOpen, getNextNodeId }}
|
||||
>
|
||||
<div className={className}>
|
||||
<ReactFlow
|
||||
nodes={nodes}
|
||||
|
||||
@@ -4442,6 +4442,11 @@ util-deprecate@^1.0.2:
|
||||
resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz"
|
||||
integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
|
||||
|
||||
uuid@^10.0.0:
|
||||
version "10.0.0"
|
||||
resolved "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz"
|
||||
integrity sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==
|
||||
|
||||
vfile-message@^4.0.0:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz"
|
||||
|
||||
Reference in New Issue
Block a user