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 { useState, useRef, useEffect, useContext } from "react";
import { ReactFlowProvider } from "reactflow";
import "./CustomNodes/inputTextFolder/inputText.css";
import "./App.css";
import { useLocation } from "react-router-dom";
import ErrorAlert from "./alerts/error";

View file

@ -1,17 +1,30 @@
import { Transition } from "@headlessui/react";
import { Handle, Position } from "reactflow";
export default function AgentNode({ data }) {
console.log(data)
console.log(data);
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">
<Handle type="source" position={Position.Left}></Handle>
<label className="absolute cursor-grab text-sm -top-3 left-1 bg-white w-14 text-center">
Agent
</label>
<div className="w-full h-min text-xs text-center">
Agent data
<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>
<label className="absolute cursor-grab text-sm -top-3 left-1 bg-white w-14 text-center">
Agent
</label>
<div className="w-full h-min text-xs text-center">Agent data</div>
<Handle type="target" position={Position.Right}></Handle>
</div>
<Handle type="target" position={Position.Right}></Handle>
</div>
</Transition>
);
}

View file

@ -1,8 +1,19 @@
import { Transition } from "@headlessui/react";
import { Handle, Position } from "reactflow";
export default function ChainNode({ data }) {
console.log(data)
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">
<Handle type="source" position={Position.Left}></Handle>
<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>
<Handle type="target" position={Position.Right}></Handle>
</div>
</Transition>
);
}

View file

@ -1,17 +1,32 @@
import { Transition } from "@headlessui/react";
import { Handle, Position } from "reactflow";
export default function ModelNode({ data }) {
console.log(data)
console.log(data);
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">
<Handle type="source" position={Position.Left}></Handle>
<label className="absolute cursor-grab text-sm -top-3 left-1 bg-white w-14 text-center">
Model
</label>
<div className="w-full h-min text-xs text-center">
{data.llm.model_name}
<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>
<label className="absolute cursor-grab text-sm -top-3 left-1 bg-white w-14 text-center">
Model
</label>
<div className="w-full h-min text-xs text-center">
{data.llm.model_name}
</div>
<Handle type="target" position={Position.Right}></Handle>
</div>
<Handle type="target" position={Position.Right}></Handle>
</div>
</Transition>
);
}

View file

@ -1,23 +1,36 @@
import { Handle, Position } from "reactflow";
import { useContext } from "react";
import { PopUpContext } from "../../contexts/popUpContext";
import { Transition } from "@headlessui/react";
export default function PromptNode({ data }) {
const {openPopUp} = useContext(PopUpContext)
const { openPopUp } = useContext(PopUpContext);
return (
<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"
<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"
>
<Handle type="source" position={Position.Left}></Handle>
<label className="absolute cursor-grab text-sm -top-3 left-1 bg-white w-14 text-center">
Prompt
</label>
<div className="w-full h-10 truncate bg-slate-50 text-xs">
{data.template}
<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"
>
<Handle type="source" position={Position.Left}></Handle>
<label className="absolute cursor-grab text-sm -top-3 left-1 bg-white w-14 text-center">
Prompt
</label>
<div className="w-full h-10 truncate bg-slate-50 text-xs">
{data.template}
</div>
<Handle type="target" position={Position.Right}></Handle>
</div>
<Handle type="target" position={Position.Right}></Handle>
</div>
</Transition>
);
}

View file

@ -1,17 +1,30 @@
import { Transition } from "@headlessui/react";
import { Handle, Position } from "reactflow";
export default function ValidatorNode({ data }) {
console.log(data)
console.log(data);
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">
<Handle type="source" position={Position.Left}></Handle>
<label className="absolute cursor-grab text-sm -top-3 left-1 bg-white w-14 text-center">
Validator
</label>
<div className="w-full h-min text-xs text-center">
validator data
<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>
<label className="absolute cursor-grab text-sm -top-3 left-1 bg-white w-14 text-center">
Validator
</label>
<div className="w-full h-min text-xs text-center">validator data</div>
<Handle type="target" position={Position.Right}></Handle>
</div>
<Handle type="target" position={Position.Right}></Handle>
</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 { prompt } from "../../../../data_assets/prompt";
import DisclosureComponent from "../DisclosureComponent";
export function ExtraSidebar(){
function onDragStart(event:React.DragEvent<any>,nodeType){
let json;
event.dataTransfer.setData('application/reactflow',nodeType)
event.dataTransfer.effectAllowed = 'move'
if(nodeType==="promptNode"){
json = JSON.stringify(prompt)
}
if(nodeType==="modelNode"){
json = JSON.stringify(llm_chain)
}
if(nodeType==="chainNode"){
json = JSON.stringify({content:""})
}
if(nodeType==="agentNode"){
json = JSON.stringify({content:""})
}
if(nodeType==="validatorNode"){
json = JSON.stringify({content:""})
}
event.dataTransfer.setData('json',json);
export function ExtraSidebar() {
function onDragStart(event: React.DragEvent<any>, nodeType) {
let json;
event.dataTransfer.setData("application/reactflow", nodeType);
event.dataTransfer.effectAllowed = "move";
if (nodeType === "promptNode") {
json = JSON.stringify(prompt);
}
if (nodeType === "modelNode") {
json = JSON.stringify(llm_chain);
}
if (nodeType === "chainNode") {
json = JSON.stringify({ content: "" });
}
if (nodeType === "agentNode") {
json = JSON.stringify({ content: "" });
}
if (nodeType === "validatorNode") {
json = JSON.stringify({ content: "" });
}
event.dataTransfer.setData("json", json);
}
return(
<div className="h-full w-48 bg-slate-200 flex flex-col">
<div draggable className="w-full text-center border border-black cursor-grab" onDragStart={(event)=>onDragStart(event,'promptNode')}> Prompt Node</div>
<div draggable className="w-full text-center border border-black cursor-grab" onDragStart={(event)=>onDragStart(event,'modelNode')}> Model Node</div>
<div draggable className="w-full text-center border border-black cursor-grab" onDragStart={(event)=>onDragStart(event,'chainNode')}> Chain Node</div>
<div draggable className="w-full text-center border border-black cursor-grab" onDragStart={(event)=>onDragStart(event,'agentNode')}> Agent Node</div>
<div draggable className="w-full text-center border border-black cursor-grab" onDragStart={(event)=>onDragStart(event,'validatorNode')}> Validator Node</div>
return (
<div className="mt-4">
<DisclosureComponent button={{ title: "Prompts", Icon: CommandLineIcon }}>
<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, "promptNode")}
>
<span className="text-black">Prompt</span>
<Bars2Icon className="w-6 text-gray-400" />
</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,
useNodesState,
} from "reactflow";
import TextUpdaterNode from "../../CustomNodes/inputTextFolder";
import PromptNode from "../../CustomNodes/PromptNode";
import ModelNode from "../../CustomNodes/ModelNode";
import { locationContext } from "../../contexts/locationContext";
@ -16,7 +15,6 @@ import ChainNode from "../../CustomNodes/ChainNode";
import ValidatorNode from "../../CustomNodes/ValidatorNode";
const nodeTypes = {
textUpdater: TextUpdaterNode,
promptNode: PromptNode,
modelNode: ModelNode,
chainNode: ChainNode,
@ -37,10 +35,11 @@ export default function FlowPage() {
const getId = () => `dndnode_${id++}`;
const { setExtraComponent } = useContext(locationContext);
const { setExtraComponent, setExtraNavigation } = useContext(locationContext);
useEffect(() => {
setExtraComponent(ExtraSidebar);
setExtraNavigation({title: "Nodes"})
}, []);
const [nodes, setNodes, onNodesChange] = useNodesState([]);