Fixed sidebar and added transitions on the nodes

This commit is contained in:
Lucas Oliveira 2023-02-10 17:49:47 -03:00
commit 868356c11e
11 changed files with 239 additions and 122 deletions

View file

@ -1,7 +1,6 @@
import "reactflow/dist/style.css"; import "reactflow/dist/style.css";
import { useState, useRef, useEffect, useContext } from "react"; import { useState, useRef, useEffect, useContext } from "react";
import { ReactFlowProvider } from "reactflow"; import { ReactFlowProvider } from "reactflow";
import "./CustomNodes/inputTextFolder/inputText.css";
import "./App.css"; import "./App.css";
import { useLocation } from "react-router-dom"; import { useLocation } from "react-router-dom";
import ErrorAlert from "./alerts/error"; import ErrorAlert from "./alerts/error";

View file

@ -1,17 +1,30 @@
import { Transition } from "@headlessui/react";
import { Handle, Position } from "reactflow"; import { Handle, Position } from "reactflow";
export default function AgentNode({ data }) { export default function AgentNode({ data }) {
console.log(data) console.log(data);
return ( return (
<div onClick={data.delete} className="agent-node relative bg-white h-16 w-40 border rounded-sm solid border-black flex flex-col justify-center"> <Transition
appear={true}
show={true}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<div
onClick={data.delete}
className="agent-node relative bg-white h-16 w-40 border rounded-sm solid border-black flex flex-col justify-center"
>
<Handle type="source" position={Position.Left}></Handle> <Handle type="source" position={Position.Left}></Handle>
<label className="absolute cursor-grab text-sm -top-3 left-1 bg-white w-14 text-center"> <label className="absolute cursor-grab text-sm -top-3 left-1 bg-white w-14 text-center">
Agent Agent
</label> </label>
<div className="w-full h-min text-xs text-center"> <div className="w-full h-min text-xs text-center">Agent data</div>
Agent data
</div>
<Handle type="target" position={Position.Right}></Handle> <Handle type="target" position={Position.Right}></Handle>
</div> </div>
</Transition>
); );
} }

View file

@ -1,8 +1,19 @@
import { Transition } from "@headlessui/react";
import { Handle, Position } from "reactflow"; import { Handle, Position } from "reactflow";
export default function ChainNode({ data }) { export default function ChainNode({ data }) {
console.log(data) console.log(data)
return ( return (
<Transition
appear={true}
show={true}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<div onClick={data.delete} className="chain-node relative bg-white h-16 w-40 border rounded-sm solid border-black flex flex-col justify-center"> <div onClick={data.delete} className="chain-node relative bg-white h-16 w-40 border rounded-sm solid border-black flex flex-col justify-center">
<Handle type="source" position={Position.Left}></Handle> <Handle type="source" position={Position.Left}></Handle>
<label className="absolute cursor-grab text-sm -top-3 left-1 bg-white w-14 text-center"> <label className="absolute cursor-grab text-sm -top-3 left-1 bg-white w-14 text-center">
@ -13,5 +24,6 @@ export default function ChainNode({ data }) {
</div> </div>
<Handle type="target" position={Position.Right}></Handle> <Handle type="target" position={Position.Right}></Handle>
</div> </div>
</Transition>
); );
} }

View file

@ -1,9 +1,23 @@
import { Transition } from "@headlessui/react";
import { Handle, Position } from "reactflow"; import { Handle, Position } from "reactflow";
export default function ModelNode({ data }) { export default function ModelNode({ data }) {
console.log(data) console.log(data);
return ( return (
<div onClick={data.delete} className="model-node relative bg-white h-16 w-40 border rounded-sm solid border-black flex flex-col justify-center"> <Transition
appear={true}
show={true}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<div
onClick={data.delete}
className="model-node relative bg-white h-16 w-40 border rounded-sm solid border-black flex flex-col justify-center"
>
<Handle type="source" position={Position.Left}></Handle> <Handle type="source" position={Position.Left}></Handle>
<label className="absolute cursor-grab text-sm -top-3 left-1 bg-white w-14 text-center"> <label className="absolute cursor-grab text-sm -top-3 left-1 bg-white w-14 text-center">
Model Model
@ -13,5 +27,6 @@ export default function ModelNode({ data }) {
</div> </div>
<Handle type="target" position={Position.Right}></Handle> <Handle type="target" position={Position.Right}></Handle>
</div> </div>
</Transition>
); );
} }

View file

@ -1,13 +1,25 @@
import { Handle, Position } from "reactflow"; import { Handle, Position } from "reactflow";
import { useContext } from "react"; import { useContext } from "react";
import { PopUpContext } from "../../contexts/popUpContext"; import { PopUpContext } from "../../contexts/popUpContext";
import { Transition } from "@headlessui/react";
export default function PromptNode({ data }) { export default function PromptNode({ data }) {
const {openPopUp} = useContext(PopUpContext) const { openPopUp } = useContext(PopUpContext);
return ( return (
<Transition
appear={true}
show={true}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<div <div
onClick={()=>openPopUp(<div className="absolute top-1/2 left-1/2">teste</div>)} onClick={() =>
openPopUp(<div className="absolute top-1/2 left-1/2">teste</div>)
}
className="prompt-node relative bg-white h-16 w-40 border rounded-sm solid border-black flex flex-col justify-center" className="prompt-node relative bg-white h-16 w-40 border rounded-sm solid border-black flex flex-col justify-center"
> >
<Handle type="source" position={Position.Left}></Handle> <Handle type="source" position={Position.Left}></Handle>
@ -19,5 +31,6 @@ export default function PromptNode({ data }) {
</div> </div>
<Handle type="target" position={Position.Right}></Handle> <Handle type="target" position={Position.Right}></Handle>
</div> </div>
</Transition>
); );
} }

View file

@ -1,17 +1,30 @@
import { Transition } from "@headlessui/react";
import { Handle, Position } from "reactflow"; import { Handle, Position } from "reactflow";
export default function ValidatorNode({ data }) { export default function ValidatorNode({ data }) {
console.log(data) console.log(data);
return ( return (
<div onClick={data.delete} className="validator-node relative bg-white h-16 w-40 border rounded-sm solid border-black flex flex-col justify-center"> <Transition
appear={true}
show={true}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<div
onClick={data.delete}
className="validator-node relative bg-white h-16 w-40 border rounded-sm solid border-black flex flex-col justify-center"
>
<Handle type="source" position={Position.Left}></Handle> <Handle type="source" position={Position.Left}></Handle>
<label className="absolute cursor-grab text-sm -top-3 left-1 bg-white w-14 text-center"> <label className="absolute cursor-grab text-sm -top-3 left-1 bg-white w-14 text-center">
Validator Validator
</label> </label>
<div className="w-full h-min text-xs text-center"> <div className="w-full h-min text-xs text-center">validator data</div>
validator data
</div>
<Handle type="target" position={Position.Right}></Handle> <Handle type="target" position={Position.Right}></Handle>
</div> </div>
</Transition>
); );
} }

View file

@ -1,28 +0,0 @@
import { useCallback } from 'react';
import { Handle, Position } from 'reactflow';
const handleStyle = {left:10};
export default function TextUpdaterNode({data})
{
const onChange = useCallback((evt)=>{
console.log(evt.target.value)
},[])
return (
<div className="text-updater-node">
<Handle type='target' position={Position.Top}/>
<div>
<label htmlFor='text'>Text:</label>
<input id="text" name="text" onChange={onChange}></input>
</div>
<Handle type='source' id='a' position={Position.Bottom} style={handleStyle}/>
<Handle type='source' id='b' position={Position.Bottom}/>
</div>
)
}

View file

@ -1,14 +0,0 @@
.text-updater-node {
height: 50px;
border: 1px solid black;
padding: 5px;
border-radius: 5px;
background: white;
}
.text-updater-node label {
display: block;
color: #777;
font-size: 12px;
}

View file

@ -0,0 +1,49 @@
import {
CpuChipIcon,
PlusIcon,
ChevronRightIcon,
ArrowPathIcon,
BoltIcon,
ChevronDoubleRightIcon,
} from "@heroicons/react/24/outline";
import { Disclosure } from "@headlessui/react";
import { useState } from "react";
export default function DisclosureComponent({
button: { title, Icon, Modal = null, buttons = [] },
children,
}) {
return (
<Disclosure as="div" key={title}>
{({ open }) => (
<>
<div className="select-none bg-gray-50 w-full flex justify-between items-center -mt-px px-3 py-2 border border-gray-200">
<div className="flex gap-4">
<Icon className="w-6 text-gray-800" />
<span className="flex items-center text-sm text-gray-800 font-medium">
{title}
</span>
</div>
<div className="flex gap-2">
{buttons.map((x, index)=>(
<button key={index} onClick={x.onClick}>
{x.Icon}
</button>
))}
<Disclosure.Button as="button">
<ChevronRightIcon
className={`${
open ? "rotate-90 transform" : ""
} h-5 w-5 text-gray-800`}
/>
</Disclosure.Button>
</div>
</div>
<Disclosure.Panel as="div" className="-mt-px">
{children}
</Disclosure.Panel>
</>
)}
</Disclosure>
);
}

View file

@ -1,39 +1,85 @@
import { Bars2Icon, CommandLineIcon, LightBulbIcon, LinkIcon, RocketLaunchIcon, ShieldCheckIcon, ViewColumnsIcon } from "@heroicons/react/24/outline";
import { llm_chain } from "../../../../data_assets/llm_chain"; import { llm_chain } from "../../../../data_assets/llm_chain";
import { prompt } from "../../../../data_assets/prompt"; import { prompt } from "../../../../data_assets/prompt";
import DisclosureComponent from "../DisclosureComponent";
export function ExtraSidebar() {
export function ExtraSidebar(){ function onDragStart(event: React.DragEvent<any>, nodeType) {
function onDragStart(event:React.DragEvent<any>,nodeType){
let json; let json;
event.dataTransfer.setData('application/reactflow',nodeType) event.dataTransfer.setData("application/reactflow", nodeType);
event.dataTransfer.effectAllowed = 'move' event.dataTransfer.effectAllowed = "move";
if(nodeType==="promptNode"){ if (nodeType === "promptNode") {
json = JSON.stringify(prompt) json = JSON.stringify(prompt);
} }
if(nodeType==="modelNode"){ if (nodeType === "modelNode") {
json = JSON.stringify(llm_chain) json = JSON.stringify(llm_chain);
} }
if(nodeType==="chainNode"){ if (nodeType === "chainNode") {
json = JSON.stringify({content:""}) json = JSON.stringify({ content: "" });
} }
if(nodeType==="agentNode"){ if (nodeType === "agentNode") {
json = JSON.stringify({content:""}) json = JSON.stringify({ content: "" });
} }
if(nodeType==="validatorNode"){ if (nodeType === "validatorNode") {
json = JSON.stringify({content:""}) json = JSON.stringify({ content: "" });
} }
event.dataTransfer.setData('json',json); event.dataTransfer.setData("json", json);
} }
return( return (
<div className="h-full w-48 bg-slate-200 flex flex-col"> <div className="mt-4">
<div draggable className="w-full text-center border border-black cursor-grab" onDragStart={(event)=>onDragStart(event,'promptNode')}> Prompt Node</div> <DisclosureComponent button={{ title: "Prompts", Icon: CommandLineIcon }}>
<div draggable className="w-full text-center border border-black cursor-grab" onDragStart={(event)=>onDragStart(event,'modelNode')}> Model Node</div> <div
<div draggable className="w-full text-center border border-black cursor-grab" onDragStart={(event)=>onDragStart(event,'chainNode')}> Chain Node</div> draggable
<div draggable className="w-full text-center border border-black cursor-grab" onDragStart={(event)=>onDragStart(event,'agentNode')}> Agent Node</div> className="flex justify-between text-sm p-4 items-center h-12 m-2 border-dashed border-gray-400 rounded-md border-2 cursor-grab"
<div draggable className="w-full text-center border border-black cursor-grab" onDragStart={(event)=>onDragStart(event,'validatorNode')}> Validator Node</div> onDragStart={(event) => onDragStart(event, "promptNode")}
>
<span className="text-black">Prompt</span>
<Bars2Icon className="w-6 text-gray-400" />
</div> </div>
) </DisclosureComponent>
<DisclosureComponent button={{ title: "Models", Icon: LightBulbIcon }}>
<div
draggable
className="flex justify-between text-sm p-4 items-center h-12 m-2 border-dashed border-gray-400 rounded-md border-2 cursor-grab"
onDragStart={(event) => onDragStart(event, "modelNode")}
>
<span className="text-black">Model</span>
<Bars2Icon className="w-6 text-gray-400" />
</div>
</DisclosureComponent>
<DisclosureComponent button={{ title: "Chains", Icon: LinkIcon }}>
<div
draggable
className="flex justify-between text-sm p-4 items-center h-12 m-2 border-dashed border-gray-400 rounded-md border-2 cursor-grab"
onDragStart={(event) => onDragStart(event, "chainNode")}
>
<span className="text-black">Chain</span>
<Bars2Icon className="w-6 text-gray-400" />
</div>
</DisclosureComponent>
<DisclosureComponent button={{ title: "Agents", Icon: RocketLaunchIcon }}>
<div
draggable
className="flex justify-between text-sm p-4 items-center h-12 m-2 border-dashed border-gray-400 rounded-md border-2 cursor-grab"
onDragStart={(event) => onDragStart(event, "agentNode")}
>
<span className="text-black">Agent</span>
<Bars2Icon className="w-6 text-gray-400" />
</div>
</DisclosureComponent>
<DisclosureComponent
button={{ title: "Validators", Icon: ShieldCheckIcon }}
>
<div
draggable
className="flex justify-between text-sm p-4 items-center h-12 m-2 border-dashed border-gray-400 rounded-md border-2 cursor-grab"
onDragStart={(event) => onDragStart(event, "validatorNode")}
>
<span className="text-black">Validator</span>
<Bars2Icon className="w-6 text-gray-400" />
</div>
</DisclosureComponent>
</div>
);
} }

View file

@ -6,7 +6,6 @@ import ReactFlow, {
useEdgesState, useEdgesState,
useNodesState, useNodesState,
} from "reactflow"; } from "reactflow";
import TextUpdaterNode from "../../CustomNodes/inputTextFolder";
import PromptNode from "../../CustomNodes/PromptNode"; import PromptNode from "../../CustomNodes/PromptNode";
import ModelNode from "../../CustomNodes/ModelNode"; import ModelNode from "../../CustomNodes/ModelNode";
import { locationContext } from "../../contexts/locationContext"; import { locationContext } from "../../contexts/locationContext";
@ -16,7 +15,6 @@ import ChainNode from "../../CustomNodes/ChainNode";
import ValidatorNode from "../../CustomNodes/ValidatorNode"; import ValidatorNode from "../../CustomNodes/ValidatorNode";
const nodeTypes = { const nodeTypes = {
textUpdater: TextUpdaterNode,
promptNode: PromptNode, promptNode: PromptNode,
modelNode: ModelNode, modelNode: ModelNode,
chainNode: ChainNode, chainNode: ChainNode,
@ -37,10 +35,11 @@ export default function FlowPage() {
const getId = () => `dndnode_${id++}`; const getId = () => `dndnode_${id++}`;
const { setExtraComponent } = useContext(locationContext); const { setExtraComponent, setExtraNavigation } = useContext(locationContext);
useEffect(() => { useEffect(() => {
setExtraComponent(ExtraSidebar); setExtraComponent(ExtraSidebar);
setExtraNavigation({title: "Nodes"})
}, []); }, []);
const [nodes, setNodes, onNodesChange] = useNodesState([]); const [nodes, setNodes, onNodesChange] = useNodesState([]);