Bugfix/Update array item config correctly (#4510)

update array item config correctly
This commit is contained in:
Henry Heng
2025-05-27 14:29:58 +01:00
committed by GitHub
parent 66bf0749af
commit 0dd6c5b2b9
2 changed files with 99 additions and 3 deletions
@@ -54,7 +54,7 @@ export const ArrayRenderer = ({ inputParam, data, disabled }) => {
// Initialize array items and parameters when component mounts or data changes // Initialize array items and parameters when component mounts or data changes
useEffect(() => { useEffect(() => {
const initialArrayItems = data.inputs[inputParam.name] || [] const initialArrayItems = cloneDeep(data.inputs[inputParam.name]) || []
setArrayItems(initialArrayItems) setArrayItems(initialArrayItems)
// Calculate initial display parameters for each array item // Calculate initial display parameters for each array item
@@ -1,4 +1,4 @@
import { useContext, useState, useEffect } from 'react' import { useContext, useState, useEffect, useRef } from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { cloneDeep } from 'lodash' import { cloneDeep } from 'lodash'
@@ -26,6 +26,9 @@ export const ConfigInput = ({ data, inputParam, disabled = false, arrayIndex = n
const [expanded, setExpanded] = useState(false) const [expanded, setExpanded] = useState(false)
const [selectedComponentNodeData, setSelectedComponentNodeData] = useState({}) const [selectedComponentNodeData, setSelectedComponentNodeData] = useState({})
// Track the last processed input values to prevent infinite loops
const lastProcessedInputsRef = useRef({})
const handleAccordionChange = (event, isExpanded) => { const handleAccordionChange = (event, isExpanded) => {
setExpanded(isExpanded) setExpanded(isExpanded)
} }
@@ -133,6 +136,13 @@ export const ConfigInput = ({ data, inputParam, disabled = false, arrayIndex = n
componentNodeData.credential = credential ? credential : undefined componentNodeData.credential = credential ? credential : undefined
setSelectedComponentNodeData(componentNodeData) setSelectedComponentNodeData(componentNodeData)
// Store the processed inputs to track changes
lastProcessedInputsRef.current = {
mainValue: data.inputs[inputParam.name],
configValue: data.inputs[`${inputParam.name}Config`],
arrayValue: parentParamForArray ? data.inputs[parentParamForArray.name] : null
}
} }
loadComponentData() loadComponentData()
@@ -140,6 +150,92 @@ export const ConfigInput = ({ data, inputParam, disabled = false, arrayIndex = n
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, []) }, [])
// Handle external changes to data.inputs
useEffect(() => {
if (!selectedComponentNodeData.inputParams) return
// Get current input values
const currentMainValue = data.inputs[inputParam.name]
const currentConfigValue = data.inputs[`${inputParam.name}Config`]
const currentArrayValue = parentParamForArray ? data.inputs[parentParamForArray.name] : null
// Check if relevant inputs have changed
const hasMainValueChanged = lastProcessedInputsRef.current.mainValue !== currentMainValue
const hasConfigValueChanged = lastProcessedInputsRef.current.configValue !== currentConfigValue
const hasArrayValueChanged = lastProcessedInputsRef.current.arrayValue !== currentArrayValue
if (!hasMainValueChanged && !hasConfigValueChanged && !hasArrayValueChanged) {
return // No relevant changes
}
// Update selectedComponentNodeData with new input values
const updateComponentData = () => {
const updatedComponentData = cloneDeep(selectedComponentNodeData)
// Helper functions (same as in initial load)
const hasArrayConfig = () => {
return (
parentParamForArray &&
data.inputs[parentParamForArray.name] &&
Array.isArray(data.inputs[parentParamForArray.name]) &&
data.inputs[parentParamForArray.name][arrayIndex] &&
data.inputs[parentParamForArray.name][arrayIndex][`${inputParam.name}Config`]
)
}
const getCurrentInputValue = () => {
return hasArrayConfig() ? data.inputs[parentParamForArray.name][arrayIndex][inputParam.name] : data.inputs[inputParam.name]
}
const getConfigData = () => {
return hasArrayConfig()
? data.inputs[parentParamForArray.name][arrayIndex][`${inputParam.name}Config`]
: data.inputs[`${inputParam.name}Config`]
}
// Update the main input value in component data
const currentValue = getCurrentInputValue()
if (currentValue !== undefined) {
updatedComponentData.inputs[inputParam.name] = currentValue
}
// If there's config data and it matches the current value, use it
if (hasArrayConfig() || data.inputs[`${inputParam.name}Config`]) {
const configData = getConfigData()
if (configData && configData[inputParam.name] === currentValue) {
// Config is still valid, merge it with current value
updatedComponentData.inputs = { ...configData, [inputParam.name]: currentValue }
} else if (hasMainValueChanged) {
// Main value changed but config doesn't match, reset to defaults with new value
const defaultInput = initializeDefaultNodeData(updatedComponentData.inputParams)
updatedComponentData.inputs = { ...defaultInput, [inputParam.name]: currentValue }
}
}
// Update input parameters visibility
updatedComponentData.inputParams = showHideInputParams({
...updatedComponentData,
inputs: updatedComponentData.inputs
})
const credential = updatedComponentData.inputs.credential || updatedComponentData.inputs[FLOWISE_CREDENTIAL_ID]
updatedComponentData.credential = credential ? credential : undefined
setSelectedComponentNodeData(updatedComponentData)
// Update the tracked values
lastProcessedInputsRef.current = {
mainValue: currentMainValue,
configValue: currentConfigValue,
arrayValue: currentArrayValue
}
}
updateComponentData()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [data.inputs, inputParam.name, parentParamForArray?.name, arrayIndex])
// Update node configuration when selected component data changes // Update node configuration when selected component data changes
useEffect(() => { useEffect(() => {
if (!selectedComponentNodeData.inputs) return if (!selectedComponentNodeData.inputs) return
@@ -169,7 +265,7 @@ export const ConfigInput = ({ data, inputParam, disabled = false, arrayIndex = n
) )
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [data.inputs, arrayIndex, parentParamForArray, selectedComponentNodeData]) }, [selectedComponentNodeData])
return ( return (
<> <>