0

I am new to Reactflow and trying to make this basic drag-drop workflow builder to work but I m not able to drag-drop my nodes from left to right panel. page renders ok. I am able to drag the nodes but not drop

I do not get any error when I run this just that I am unable to drop the nodes

screenshot

Here is my code

// Frontend: React (ReactFlow-based Flow Builder)
import React, { useState, useCallback } from 'react';
import ReactFlow, { addEdge, Background, Controls, MiniMap, Handle } from 'react-flow-renderer';
import axios from 'axios';

const initialElements = [
  { id: '1', type: 'input', data: { label: 'Start' }, position: { x: 250, y: 5 } },
];

const nodeTypes = {
  textNode: ({ data }) => (
    <div style={{ padding: 10, border: '1px solid #777', borderRadius: 5 }}>
      <Handle type="target" position="top" />
      <div>{data.label}</div>
      <Handle type="source" position="bottom" />
    </div>
  ),
  conditionNode: ({ data }) => (
    <div style={{ padding: 10, border: '1px solid #f39c12', borderRadius: 5, backgroundColor: '#fdf3e7' }}>
      <Handle type="target" position="top" />
      <div>If: {data.ifCondition}</div>
      <div>Then: {data.thenAction}</div>
      <div>Else: {data.elseAction}</div>
      <Handle type="source" position="bottom" />
    </div>
  ),
  switchNode: ({ data }) => (
    <div style={{ padding: 10, border: '1px solid #3498db', borderRadius: 5, backgroundColor: '#eaf4fd' }}>
      <Handle type="target" position="top" />
      <div>Switch: {data.label}</div>
      <div>Cases:</div>
      {data.cases.map((caseItem, index) => (
        <div key={index}>{`Case ${index + 1}: ${caseItem}`}</div>
      ))}
      <Handle type="source" position="bottom" />
    </div>
  ),
  apiCallNode: ({ data }) => (
    <div style={{ padding: 10, border: '1px solid #27ae60', borderRadius: 5, backgroundColor: '#eafaf1' }}>
      <Handle type="target" position="top" />
      <div>API Call: {data.url}</div>
      <Handle type="source" position="bottom" />
    </div>
  ),
  setVariableNode: ({ data }) => (
    <div style={{ padding: 10, border: '1px solid #e74c3c', borderRadius: 5, backgroundColor: '#fdecea' }}>
      <Handle type="target" position="top" />
      <div>Set Variable: {data.variableName} = {data.value}</div>
      <Handle type="source" position="bottom" />
    </div>
  ),
};

const DraggableNode = ({ type, label }) => {
  const onDragStart = (event) => {
    event.dataTransfer.setData('application/reactflow', type);
    event.dataTransfer.effectAllowed = 'move';
  };

  return (
    <div
      draggable
      onDragStart={onDragStart}
      style={{ padding: '8px', marginBottom: '8px', backgroundColor: '#eee', cursor: 'grab' }}
    >
      {label}
    </div>
  );
};

const ChatBuilder = () => {
  const [elements, setElements] = useState(initialElements);
  const [reactFlowInstance, setReactFlowInstance] = useState(null);

  const onConnect = (params) => setElements((els) => addEdge(params, els));

  const onDrop = useCallback(
    (event) => {
      event.preventDefault();
      if (!reactFlowInstance) {
        console.error('React Flow instance is not ready');
        return;
      }

      const type = event.dataTransfer.getData('application/reactflow');
      if (!type) {
        console.error('No node type found in drag data');
        return;
      }

      const reactFlowBounds = document.querySelector('.reactflow-wrapper').getBoundingClientRect();
      const position = reactFlowInstance.project({
        x: event.clientX - reactFlowBounds.left,
        y: event.clientY - reactFlowBounds.top,
      });

      console.log('Adding node at position:', position); // Debugging log

      const id = `node_${+new Date()}`;
      const newNode = {
        id,
        type,
        position,
        data: { label: `${type} Node` },
      };

      setElements((es) => es.concat(newNode));
    },
    [reactFlowInstance]
  );

  const onDragOver = useCallback((event) => {
    event.preventDefault();
    event.dataTransfer.dropEffect = 'move';
  }, []);

  const onLoad = useCallback((rfi) => {
    setReactFlowInstance(rfi);
    rfi.fitView();
  }, []);


  const saveFlow = async () => {
    try {
      const response = await axios.post('http://localhost:5000/api/saveFlow', {
        name: 'My First Flow',
        flowJson: elements,
      });
      alert(`Flow saved with ID: ${response.data.id}`);
    } catch (error) {
      console.error('Error saving flow', error);
      alert('Failed to save flow');
    }
  };  

  return (
    <div style={{ display: 'flex', height: '90vh' }}>
      <div style={{ width: '20%', padding: '10px', borderRight: '1px solid #ccc' }}>
        <h3>Node Types</h3>
        <DraggableNode type="textNode" label="Text Node" />
        <DraggableNode type="conditionNode" label="Condition Node" />
        <DraggableNode type="switchNode" label="Switch Node" />
        <DraggableNode type="apiCallNode" label="API Call Node" />
        <DraggableNode type="setVariableNode" label="Set Variable Node" />
        <button onClick={saveFlow}>Save Flow</button>
      </div>
      <div className="reactflow-wrapper" style={{ width: '80%', height: '100%' }}>
        <ReactFlow
          elements={elements}
          onConnect={onConnect}
          onElementsRemove={(elementsToRemove) =>
            setElements((els) => els.filter((e) => !elementsToRemove.includes(e)))
          }
          onLoad={onLoad}
          onNodeDragStop={(event, node) =>
            setElements((els) =>
              els.map((el) => (el.id === node.id ? { ...el, position: node.position } : el))
            )
          }
          onDrop={onDrop}
          onDragOver={onDragOver}
          nodeTypes={nodeTypes}
          snapToGrid={true}
        >
          <Background color="#aaa" gap={16} />
          <Controls />
          <MiniMap />
        </ReactFlow>
      </div>
    </div>
  );
};

export default ChatBuilder;

I should be able to drag and drop the nodes and build my workflow

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.