diff --git a/app/w/[id]/workflow.tsx b/app/w/[id]/workflow.tsx index d81ec6bd4f..449c7492e8 100644 --- a/app/w/[id]/workflow.tsx +++ b/app/w/[id]/workflow.tsx @@ -1,8 +1,16 @@ 'use client' import { useState, useCallback, useEffect } from 'react' -import { BlockConfig, BLOCKS } from '../components/block/blocks' -import { WorkflowBlock } from '../components/block/workflow-block' +import { BlockConfig } from '../components/blocks/types/block' +import { WorkflowBlock } from '../components/blocks/components/workflow-block/workflow-block' +import { getBlock } from '../components/blocks/configs' + +interface WorkflowBlock { + id: string + type: string + position: { x: number; y: number } + config: BlockConfig +} const ZOOM_SPEED = 0.005 const MIN_ZOOM = 0.5 @@ -10,14 +18,7 @@ const MAX_ZOOM = 2 const CANVAS_SIZE = 5000 // 5000px x 5000px virtual canvas export default function Workflow() { - const [blocks, setBlocks] = useState< - { - id: string - position: { x: number; y: number } - type: string - config: BlockConfig - }[] - >([]) + const [blocks, setBlocks] = useState([]) const [zoom, setZoom] = useState(1) const [pan, setPan] = useState({ x: 0, y: 0 }) const [isPanning, setIsPanning] = useState(false) @@ -66,29 +67,28 @@ export default function Workflow() { e.preventDefault() try { - const blockData = JSON.parse( - e.dataTransfer.getData('application/json') - ) as BlockConfig + const { type } = JSON.parse(e.dataTransfer.getData('application/json')) + const blockConfig = getBlock(type) + + if (!blockConfig) { + console.error('Invalid block type:', type) + return + } - // Get the canvas element's bounding rectangle const rect = e.currentTarget.getBoundingClientRect() - - // Calculate the drop position in canvas coordinates - // 1. Get the mouse position relative to the canvas element - // 2. Remove the pan offset (scaled by zoom) - // 3. Scale by zoom to get true canvas coordinates const mouseX = e.clientX - rect.left const mouseY = e.clientY - rect.top const x = mouseX / zoom const y = mouseY / zoom - setBlocks((prev: any) => [ + setBlocks((prev) => [ ...prev, { - ...blockData, id: crypto.randomUUID(), + type, position: { x, y }, + config: blockConfig, }, ]) } catch (err) { @@ -200,20 +200,16 @@ export default function Workflow() { onDragOver={handleDragOver} onDrop={handleDrop} > - {blocks.map((block, index) => { - const blockConfig = - BLOCKS.find((b) => b.type === block.type) || block.config - return ( - - ) - })} + {blocks.map((block, index) => ( + + ))} ) diff --git a/app/w/components/block/blocks.ts b/app/w/components/block/blocks.ts deleted file mode 100644 index 1c1f633883..0000000000 --- a/app/w/components/block/blocks.ts +++ /dev/null @@ -1,128 +0,0 @@ -import { AgentIcon, ApiIcon, ConditionalIcon } from '@/components/icons' - -export interface SubBlockConfig { - title: string - type: 'short-text' | 'long-text' | 'dropdown' | 'slider' | 'group' - options?: string[] // For dropdown - min?: number // For slider - max?: number // For slider - layout?: 'full' | 'half' // Controls if the block takes full width or shares space -} - -export interface BlockConfig { - type: string - toolbar: { - title: string - description: string - bgColor: string - icon: any - category: 'basic' | 'advanced' - } - workflow: { - inputs: { [key: string]: string } - outputs: { [key: string]: string } - subBlocks: SubBlockConfig[] - } -} - -export const BLOCKS: BlockConfig[] = [ - { - type: 'agent', - toolbar: { - title: 'Agent', - description: 'Use any LLM', - bgColor: '#7F2FFF', - icon: AgentIcon, - category: 'basic', - }, - workflow: { - inputs: { - prompt: 'string', - }, - outputs: { - response: 'string', - }, - subBlocks: [ - { - title: 'System Prompt', - type: 'long-text', - layout: 'full', - }, - { - title: 'Model', - type: 'dropdown', - layout: 'half', - options: ['GPT-4', 'GPT-3.5', 'Claude'], - }, - { - title: 'Temperature', - type: 'slider', - layout: 'half', - min: 0, - max: 2, - }, - - ], - }, - }, - { - type: 'api', - toolbar: { - title: 'API', - description: 'Connect to any API', - bgColor: '#2F55FF', - icon: ApiIcon, - category: 'basic', - }, - workflow: { - inputs: { - url: 'string', - method: 'string', - }, - outputs: { - response: 'string', - }, - subBlocks: [ - { - title: 'URL', - type: 'long-text', - }, - { - title: 'Method', - type: 'dropdown', - options: ['GET', 'POST', 'PUT', 'DELETE'], - }, - ], - }, - }, - { - type: 'conditional', - toolbar: { - title: 'Conditional', - description: 'Create branching logic', - bgColor: '#FF972F', - icon: ConditionalIcon, - category: 'basic', - }, - workflow: { - inputs: { - // Add conditional-specific inputs - }, - outputs: { - // Add conditional-specific outputs - }, - subBlocks: [ - { - title: 'Condition', - type: 'dropdown', - options: ['True', 'False'], - }, - { - title: 'Action', - type: 'dropdown', - options: ['Do Something', 'Do Nothing'], - }, - ], - }, - }, -] \ No newline at end of file diff --git a/app/w/components/block/sub-block.tsx b/app/w/components/block/sub-block.tsx deleted file mode 100644 index 9490667680..0000000000 --- a/app/w/components/block/sub-block.tsx +++ /dev/null @@ -1,108 +0,0 @@ -import { Input } from '@/components/ui/input' -import { SubBlockConfig } from './blocks' -import { Textarea } from '@/components/ui/textarea' -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from '@/components/ui/select' -import { Slider } from '@/components/ui/slider' -import { Label } from '@/components/ui/label' -import { useState } from 'react' - -interface SubBlockProps { - config: SubBlockConfig -} - -export function SubBlock({ config }: SubBlockProps) { - const [sliderValue, setSliderValue] = useState( - config.type === 'slider' - ? (config.min || 0) + ((config.max || 100) - (config.min || 0)) / 2 - : 0 - ) - - const handleMouseDown = (e: React.MouseEvent) => { - e.stopPropagation() - } - - const renderInput = () => { - switch (config.type) { - case 'short-text': - return - case 'long-text': - return