diff --git a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx index dbd091e63..33073b628 100644 --- a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx @@ -25,7 +25,7 @@ import { TabsContext } from "../../../../contexts/tabsContext"; import { typesContext } from "../../../../contexts/typesContext"; import { ParameterComponentType } from "../../../../types/components"; import { TabsState } from "../../../../types/tabs"; -import { isValidConnection } from "../../../../utils/reactflowUtils"; +import { convertArrayToObj, convertObjToArray, hasDuplicateKeys, isValidConnection } from "../../../../utils/reactflowUtils"; import { nodeColors, nodeIconsLucide, @@ -53,6 +53,7 @@ export default function ParameterComponent({ const updateNodeInternals = useUpdateNodeInternals(); const [position, setPosition] = useState(0); const { setTabsState, tabId, save, flows } = useContext(TabsContext); + const [errorDuplicateKey, setErrorDuplicateKey] = useState(false); const flow = flows.find((flow) => flow.id === tabId)?.data?.nodes ?? null; @@ -105,34 +106,9 @@ export default function ParameterComponent({ const [dictArr, setDictArr] = useState([]); useEffect(() => { - convertToArray(dict); + setDictArr(convertObjToArray(dict)); }, [dict]); - const convertToArray = (singleObject) => { - let arrConverted: any = []; - for (const key in singleObject) { - if (singleObject.hasOwnProperty(key)) { - const newObj = {}; - newObj[key] = singleObject[key]; - arrConverted.push(newObj); - } - } - setDictArr(arrConverted); - }; - - const convertToDict = (newValue): void => { - const flattenedObject = {}; - for (const obj of newValue) { - for (const key in obj) { - if (obj.hasOwnProperty(key)) { - flattenedObject[key] = obj[key]; - } - } - } - let newData = cloneDeep(flattenedObject); - setDict(newData); - }; - useEffect(() => { if (name === "openai_api_base") console.log(info); // @ts-ignore @@ -254,7 +230,12 @@ export default function ParameterComponent({ disabled={disabled} editNode={false} value={dictArr} - onChange={convertToDict} + duplicateKey={errorDuplicateKey} + onChange={(newValue) => { + setErrorDuplicateKey(hasDuplicateKeys(newValue)); + if(hasDuplicateKeys(newValue)) return; + setDict(convertArrayToObj(newValue)); + }} /> ) : ( diff --git a/src/frontend/src/components/keypairListComponent/index.tsx b/src/frontend/src/components/keypairListComponent/index.tsx index ef30ac331..1e9f73ccf 100644 --- a/src/frontend/src/components/keypairListComponent/index.tsx +++ b/src/frontend/src/components/keypairListComponent/index.tsx @@ -13,6 +13,7 @@ export default function KeypairListComponent({ onChange, disabled, editNode = false, + duplicateKey }: KeyPairListComponent): JSX.Element { useEffect(() => { if (disabled) { @@ -20,19 +21,17 @@ export default function KeypairListComponent({ } }, [disabled]); - const handleChangeKey = (event, idx) => { + console.log(duplicateKey); + + + const handleChangeKey = (event, idx) => { const newInputList = _.cloneDeep(value); const oldKey = Object.keys(newInputList[idx])[0]; - let counter = 1; - let newKey = event.target.value; - while (newInputList.some(obj => Object.keys(obj)[0] === newKey)) { - newKey = `${event.target.value}_${counter}`; - counter++; - } - newInputList[idx] = { [newKey]: newInputList[idx][oldKey] }; + const updatedObj = { [event.target.value]: newInputList[idx][oldKey] }; + newInputList[idx] = updatedObj; onChange(newInputList); }; - + const handleChangeValue = (newValue, idx) => { const newInputList = _.cloneDeep(value); const key = Object.keys(newInputList[idx])[0]; diff --git a/src/frontend/src/types/components/index.ts b/src/frontend/src/types/components/index.ts index 7f826cdf5..64b8ae774 100644 --- a/src/frontend/src/types/components/index.ts +++ b/src/frontend/src/types/components/index.ts @@ -59,6 +59,7 @@ export type KeyPairListComponent = { onChange: (value: string[]) => void; disabled: boolean; editNode?: boolean; + duplicateKey?: boolean; }; export type TextAreaComponentType = { diff --git a/src/frontend/src/utils/reactflowUtils.ts b/src/frontend/src/utils/reactflowUtils.ts index 87971ef9b..1394203f1 100644 --- a/src/frontend/src/utils/reactflowUtils.ts +++ b/src/frontend/src/utils/reactflowUtils.ts @@ -289,3 +289,42 @@ export function getConnectedNodes( const targetId = edge.target; return nodes.filter((node) => node.id === targetId || node.id === sourceId); } + +export function convertObjToArray(singleObject){ + let arrConverted: any = []; + for (const key in singleObject) { + if (singleObject.hasOwnProperty(key)) { + const newObj = {}; + newObj[key] = singleObject[key]; + arrConverted.push(newObj); + } + } + + return arrConverted; +} + +export function convertArrayToObj(newValue){ + const flattenedObject = {}; + for (const obj of newValue) { + for (const key in obj) { + if (obj.hasOwnProperty(key)) { + flattenedObject[key] = obj[key]; + } + } + } + let newData = _.cloneDeep(flattenedObject); + return newData; +} + +export function hasDuplicateKeys(array) { + const keys = {}; + for (const obj of array) { + for (const key in obj) { + if (keys[key]) { + return true; // Duplicate key found + } + keys[key] = true; + } + } + return false; // No duplicate keys found +} \ No newline at end of file