mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
Feature: max iterations can be updated from UI
This commit is contained in:
@@ -1,21 +1,88 @@
|
||||
import { useState } from 'react'
|
||||
import { ChevronDown } from 'lucide-react'
|
||||
import { NodeProps } from 'reactflow'
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { useWorkflowStore } from '@/stores/workflow/store'
|
||||
|
||||
export function LoopInput({ id }: NodeProps) {
|
||||
// Extract the loop ID from the node ID (removes 'loop-input-' prefix)
|
||||
// Extract the loop ID from the node ID
|
||||
const loopId = id.replace('loop-input-', '')
|
||||
|
||||
// Get the max iterations from the store for this loop
|
||||
const maxIterations = useWorkflowStore((state) => state.loops[loopId]?.maxIterations ?? 5)
|
||||
const updateLoopMaxIterations = useWorkflowStore((state) => state.updateLoopMaxIterations)
|
||||
|
||||
// Local state for input value
|
||||
const [inputValue, setInputValue] = useState(maxIterations.toString())
|
||||
const [open, setOpen] = useState(false)
|
||||
|
||||
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const sanitizedValue = e.target.value.replace(/[^0-9]/g, '')
|
||||
const numValue = parseInt(sanitizedValue)
|
||||
|
||||
// Only update if it's a valid number and <= 50
|
||||
if (!isNaN(numValue)) {
|
||||
setInputValue(Math.min(50, numValue).toString())
|
||||
} else {
|
||||
setInputValue(sanitizedValue)
|
||||
}
|
||||
}
|
||||
|
||||
const handleSave = () => {
|
||||
const value = parseInt(inputValue)
|
||||
if (!isNaN(value)) {
|
||||
const newValue = Math.min(50, value)
|
||||
updateLoopMaxIterations(loopId, newValue)
|
||||
// Sync input with store value
|
||||
setInputValue(newValue.toString())
|
||||
} else {
|
||||
// Reset to current store value if invalid
|
||||
setInputValue(maxIterations.toString())
|
||||
}
|
||||
}
|
||||
|
||||
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault()
|
||||
handleSave()
|
||||
setOpen(false)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Badge
|
||||
variant="outline"
|
||||
className="bg-white border-[rgb(203,213,225)] text-gray-700 font-medium px-2 py-0.5 text-sm
|
||||
hover:bg-gray-50 transition-colors duration-150"
|
||||
>
|
||||
Max Iterations: {maxIterations}
|
||||
</Badge>
|
||||
<Popover open={open} onOpenChange={setOpen}>
|
||||
<PopoverTrigger asChild onClick={(e) => e.stopPropagation()}>
|
||||
<Badge
|
||||
variant="outline"
|
||||
className={cn(
|
||||
'bg-white border-[rgb(203,213,225)] text-gray-700 font-medium px-2 py-0.5 text-sm',
|
||||
'hover:bg-gray-50 transition-colors duration-150 cursor-pointer',
|
||||
'flex items-center gap-1'
|
||||
)}
|
||||
>
|
||||
Max Iterations: {maxIterations}
|
||||
<ChevronDown className="h-3 w-3 text-muted-foreground" />
|
||||
</Badge>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-48 p-3" align="start" onClick={(e) => e.stopPropagation()}>
|
||||
<div className="space-y-2">
|
||||
<div className="text-xs font-medium text-muted-foreground">Max Iterations</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Input
|
||||
type="text"
|
||||
value={inputValue}
|
||||
onChange={handleChange}
|
||||
onBlur={handleSave}
|
||||
onKeyDown={handleKeyDown}
|
||||
className="h-8 text-sm"
|
||||
/>
|
||||
</div>
|
||||
<div className="text-[10px] text-muted-foreground">Enter a number between 1 and 50</div>
|
||||
</div>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { useWorkflowStore } from '@/stores/workflow/store'
|
||||
import { Loop } from '@/stores/workflow/types'
|
||||
|
||||
interface WorkflowLoopProps {
|
||||
@@ -22,7 +23,8 @@ function createLoopLabelNode(loopId: string, bounds: { x: number; y: number }) {
|
||||
|
||||
// Helper function to create loop input node
|
||||
function createLoopInputNode(loopId: string, bounds: { x: number; width: number }) {
|
||||
const BADGE_WIDTH = 128
|
||||
const loop = useWorkflowStore.getState().loops[loopId]
|
||||
const BADGE_WIDTH = loop?.maxIterations > 9 ? 153 : 144
|
||||
|
||||
return {
|
||||
id: `loop-input-${loopId}`,
|
||||
|
||||
Reference in New Issue
Block a user