mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
fix[ux]: referenced block renaming (#132)
* fix[ui]: referenced block renaming #120 * improvement[block-renaming]: added support for condition/function blocks --------- Co-authored-by: Braulio Fernandes <brauliopf+github@gmail.com>
This commit is contained in:
co-authored by
Braulio Fernandes
parent
73f224de33
commit
f5063af161
@@ -402,11 +402,15 @@ export const useWorkflowStore = create<WorkflowStoreWithHistory>()(
|
||||
},
|
||||
|
||||
updateBlockName: (id: string, name: string) => {
|
||||
const oldBlock = get().blocks[id]
|
||||
if (!oldBlock) return
|
||||
|
||||
// Create a new state with the updated block name
|
||||
const newState = {
|
||||
blocks: {
|
||||
...get().blocks,
|
||||
[id]: {
|
||||
...get().blocks[id],
|
||||
...oldBlock,
|
||||
name,
|
||||
},
|
||||
},
|
||||
@@ -414,6 +418,64 @@ export const useWorkflowStore = create<WorkflowStoreWithHistory>()(
|
||||
loops: { ...get().loops },
|
||||
}
|
||||
|
||||
// Update references in subblock store
|
||||
const subBlockStore = useSubBlockStore.getState()
|
||||
const activeWorkflowId = useWorkflowRegistry.getState().activeWorkflowId
|
||||
if (activeWorkflowId) {
|
||||
// Get the workflow values for the active workflow
|
||||
// workflowValues: {[block_id]:{[subblock_id]:[subblock_value]}}
|
||||
const workflowValues = subBlockStore.workflowValues[activeWorkflowId] || {}
|
||||
const updatedWorkflowValues = { ...workflowValues }
|
||||
|
||||
// Loop through blocks
|
||||
Object.entries(workflowValues).forEach(([blockId, blockValues]) => {
|
||||
if (blockId === id) return // Skip the block being renamed
|
||||
|
||||
// Loop through subblocks and update references
|
||||
Object.entries(blockValues).forEach(([subBlockId, value]) => {
|
||||
const oldBlockName = oldBlock.name.replace(/\s+/g, '').toLowerCase()
|
||||
const newBlockName = name.replace(/\s+/g, '').toLowerCase()
|
||||
const regex = new RegExp(`<${oldBlockName}\\.`, 'g')
|
||||
|
||||
// Use a recursive function to handle all object types
|
||||
updatedWorkflowValues[blockId][subBlockId] = updateReferences(value, regex, `<${newBlockName}.`)
|
||||
|
||||
// Helper function to recursively update references in any data structure
|
||||
function updateReferences(value: any, regex: RegExp, replacement: string): any {
|
||||
// Handle string values
|
||||
if (typeof value === 'string') {
|
||||
return regex.test(value) ? value.replace(regex, replacement) : value
|
||||
}
|
||||
|
||||
// Handle arrays
|
||||
if (Array.isArray(value)) {
|
||||
return value.map(item => updateReferences(item, regex, replacement))
|
||||
}
|
||||
|
||||
// Handle objects
|
||||
if (value !== null && typeof value === 'object') {
|
||||
const result = { ...value }
|
||||
for (const key in result) {
|
||||
result[key] = updateReferences(result[key], regex, replacement)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// Return unchanged for other types
|
||||
return value
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// Update the subblock store with the new values
|
||||
useSubBlockStore.setState({
|
||||
workflowValues: {
|
||||
...subBlockStore.workflowValues,
|
||||
[activeWorkflowId]: updatedWorkflowValues,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
set(newState)
|
||||
pushHistory(set, get, newState, `${name} block name updated`)
|
||||
get().updateLastSaved()
|
||||
|
||||
+64
-40
@@ -36,12 +36,6 @@ interface ConditionInputProps {
|
||||
|
||||
export function ConditionInput({ blockId, subBlockId, isConnecting }: ConditionInputProps) {
|
||||
const [storeValue, setStoreValue] = useSubBlockValue(blockId, subBlockId)
|
||||
const [lineCount, setLineCount] = useState(1)
|
||||
const [showTags, setShowTags] = useState(false)
|
||||
const [showEnvVars, setShowEnvVars] = useState(false)
|
||||
const [searchTerm, setSearchTerm] = useState('')
|
||||
const [cursorPosition, setCursorPosition] = useState(0)
|
||||
const [activeSourceBlockId, setActiveSourceBlockId] = useState<string | null>(null)
|
||||
const editorRef = useRef<HTMLDivElement>(null)
|
||||
const [visualLineHeights, setVisualLineHeights] = useState<{
|
||||
[key: string]: number[]
|
||||
@@ -50,6 +44,11 @@ export function ConditionInput({ blockId, subBlockId, isConnecting }: ConditionI
|
||||
const removeEdge = useWorkflowStore((state) => state.removeEdge)
|
||||
const edges = useWorkflowStore((state) => state.edges)
|
||||
|
||||
// Use a ref to track the previous store value for comparison
|
||||
const prevStoreValueRef = useRef<string | null>(null)
|
||||
// Use a ref to track if we're currently syncing from store to prevent loops
|
||||
const isSyncingFromStoreRef = useRef(false)
|
||||
|
||||
// Initialize conditional blocks with if and else blocks
|
||||
const [conditionalBlocks, setConditionalBlocks] = useState<ConditionalBlock[]>([
|
||||
{
|
||||
@@ -74,46 +73,71 @@ export function ConditionInput({ blockId, subBlockId, isConnecting }: ConditionI
|
||||
},
|
||||
])
|
||||
|
||||
// Sync store value with conditional blocks on initial load
|
||||
// Sync store value with conditional blocks when storeValue changes
|
||||
useEffect(() => {
|
||||
if (storeValue !== null) {
|
||||
try {
|
||||
const parsedValue = JSON.parse(storeValue.toString())
|
||||
if (Array.isArray(parsedValue)) {
|
||||
setConditionalBlocks(parsedValue)
|
||||
}
|
||||
} catch {
|
||||
// If the store value isn't valid JSON, initialize with default blocks
|
||||
setConditionalBlocks([
|
||||
{
|
||||
id: crypto.randomUUID(),
|
||||
title: 'if',
|
||||
value: '',
|
||||
showTags: false,
|
||||
showEnvVars: false,
|
||||
searchTerm: '',
|
||||
cursorPosition: 0,
|
||||
activeSourceBlockId: null,
|
||||
},
|
||||
{
|
||||
id: crypto.randomUUID(),
|
||||
title: 'else',
|
||||
value: '',
|
||||
showTags: false,
|
||||
showEnvVars: false,
|
||||
searchTerm: '',
|
||||
cursorPosition: 0,
|
||||
activeSourceBlockId: null,
|
||||
},
|
||||
])
|
||||
// Skip if we don't have a store value
|
||||
if (storeValue === null) return
|
||||
|
||||
// Skip if the store value hasn't changed
|
||||
const storeValueStr = storeValue.toString()
|
||||
if (storeValueStr === prevStoreValueRef.current) return
|
||||
|
||||
// Update the previous store value ref
|
||||
prevStoreValueRef.current = storeValueStr
|
||||
|
||||
// Set that we're syncing from store to prevent loops
|
||||
isSyncingFromStoreRef.current = true
|
||||
|
||||
try {
|
||||
const parsedValue = JSON.parse(storeValueStr)
|
||||
if (Array.isArray(parsedValue)) {
|
||||
setConditionalBlocks(parsedValue)
|
||||
}
|
||||
} catch (error) {
|
||||
// If parsing fails, set default blocks
|
||||
setConditionalBlocks([
|
||||
{
|
||||
id: crypto.randomUUID(),
|
||||
title: 'if',
|
||||
value: '',
|
||||
showTags: false,
|
||||
showEnvVars: false,
|
||||
searchTerm: '',
|
||||
cursorPosition: 0,
|
||||
activeSourceBlockId: null,
|
||||
},
|
||||
{
|
||||
id: crypto.randomUUID(),
|
||||
title: 'else',
|
||||
value: '',
|
||||
showTags: false,
|
||||
showEnvVars: false,
|
||||
searchTerm: '',
|
||||
cursorPosition: 0,
|
||||
activeSourceBlockId: null,
|
||||
},
|
||||
])
|
||||
} finally {
|
||||
// Reset the syncing flag
|
||||
setTimeout(() => {
|
||||
isSyncingFromStoreRef.current = false
|
||||
}, 0)
|
||||
}
|
||||
}, [])
|
||||
}, [storeValue])
|
||||
|
||||
// Update store whenever conditional blocks change
|
||||
useEffect(() => {
|
||||
setStoreValue(JSON.stringify(conditionalBlocks))
|
||||
updateNodeInternals(`${blockId}-${subBlockId}`)
|
||||
// Skip if we're currently syncing from store to prevent loops
|
||||
if (isSyncingFromStoreRef.current) return
|
||||
|
||||
const newValue = JSON.stringify(conditionalBlocks)
|
||||
|
||||
// Only update if the value has actually changed
|
||||
if (newValue !== prevStoreValueRef.current) {
|
||||
prevStoreValueRef.current = newValue
|
||||
setStoreValue(newValue)
|
||||
updateNodeInternals(`${blockId}-${subBlockId}`)
|
||||
}
|
||||
}, [conditionalBlocks, blockId, subBlockId])
|
||||
|
||||
// Update block value with trigger checks - handle both tag and env var triggers consistently
|
||||
|
||||
Reference in New Issue
Block a user